Mercurial > hg > freeDiameter
comparison freeDiameter/cnxctx.c @ 543:40141acabee7
Fix behavior of TLS/SCTP when only one peer does not accept the remote certificate
author | Sebastien Decugis <sdecugis@nict.go.jp> |
---|---|
date | Tue, 14 Sep 2010 13:31:27 +0900 |
parents | 0b6cee362f5d |
children | 88a494357a9d |
comparison
equal
deleted
inserted
replaced
542:0b6cee362f5d | 543:40141acabee7 |
---|---|
992 } | 992 } |
993 | 993 |
994 /* Verify remote credentials after successful handshake (return 0 if OK, EINVAL otherwise) */ | 994 /* Verify remote credentials after successful handshake (return 0 if OK, EINVAL otherwise) */ |
995 int fd_tls_verify_credentials(gnutls_session_t session, struct cnxctx * conn, int verbose) | 995 int fd_tls_verify_credentials(gnutls_session_t session, struct cnxctx * conn, int verbose) |
996 { | 996 { |
997 int i; | 997 int i, ret = 0; |
998 unsigned int gtret; | 998 unsigned int gtret; |
999 const gnutls_datum_t *cert_list; | 999 const gnutls_datum_t *cert_list; |
1000 unsigned int cert_list_size; | 1000 unsigned int cert_list_size; |
1001 gnutls_x509_crt_t cert; | 1001 gnutls_x509_crt_t cert; |
1002 time_t now; | 1002 time_t now; |
1173 time_t deadline; | 1173 time_t deadline; |
1174 | 1174 |
1175 CHECK_GNUTLS_DO( gnutls_x509_crt_init (&cert), return EINVAL); | 1175 CHECK_GNUTLS_DO( gnutls_x509_crt_init (&cert), return EINVAL); |
1176 CHECK_GNUTLS_DO( gnutls_x509_crt_import (cert, &cert_list[i], GNUTLS_X509_FMT_DER), return EINVAL); | 1176 CHECK_GNUTLS_DO( gnutls_x509_crt_import (cert, &cert_list[i], GNUTLS_X509_FMT_DER), return EINVAL); |
1177 | 1177 |
1178 /* When gnutls 2.10.1 is around, we should use gnutls_certificate_set_verify_function */ | |
1179 | |
1180 GNUTLS_TRACE( deadline = gnutls_x509_crt_get_expiration_time(cert) ); | 1178 GNUTLS_TRACE( deadline = gnutls_x509_crt_get_expiration_time(cert) ); |
1181 if ((deadline != (time_t)-1) && (deadline < now)) { | 1179 if ((deadline != (time_t)-1) && (deadline < now)) { |
1182 if (TRACE_BOOL(INFO)) { | 1180 if (TRACE_BOOL(INFO)) { |
1183 fd_log_debug("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :\n", conn->cc_socket, conn->cc_remid, conn->cc_id); | 1181 fd_log_debug("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :\n", conn->cc_socket, conn->cc_remid, conn->cc_id); |
1184 fd_log_debug(" - The certificate %d in the chain is expired\n", i); | 1182 fd_log_debug(" - The certificate %d in the chain is expired\n", i); |
1185 } | 1183 } |
1186 return EINVAL; | 1184 ret = EINVAL; |
1187 } | 1185 } |
1188 | 1186 |
1189 GNUTLS_TRACE( deadline = gnutls_x509_crt_get_activation_time(cert) ); | 1187 GNUTLS_TRACE( deadline = gnutls_x509_crt_get_activation_time(cert) ); |
1190 if ((deadline != (time_t)-1) && (deadline > now)) { | 1188 if ((deadline != (time_t)-1) && (deadline > now)) { |
1191 if (TRACE_BOOL(INFO)) { | 1189 if (TRACE_BOOL(INFO)) { |
1192 fd_log_debug("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :\n", conn->cc_socket, conn->cc_remid, conn->cc_id); | 1190 fd_log_debug("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :\n", conn->cc_socket, conn->cc_remid, conn->cc_id); |
1193 fd_log_debug(" - The certificate %d in the chain is not yet activated\n", i); | 1191 fd_log_debug(" - The certificate %d in the chain is not yet activated\n", i); |
1194 } | 1192 } |
1195 return EINVAL; | 1193 ret = EINVAL; |
1196 } | 1194 } |
1197 | 1195 |
1198 if ((i == 0) && (conn->cc_tls_para.cn)) { | 1196 if ((i == 0) && (conn->cc_tls_para.cn)) { |
1199 if (!gnutls_x509_crt_check_hostname (cert, conn->cc_tls_para.cn)) { | 1197 if (!gnutls_x509_crt_check_hostname (cert, conn->cc_tls_para.cn)) { |
1200 if (TRACE_BOOL(INFO)) { | 1198 if (TRACE_BOOL(INFO)) { |
1201 fd_log_debug("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :\n", conn->cc_socket, conn->cc_remid, conn->cc_id); | 1199 fd_log_debug("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :\n", conn->cc_socket, conn->cc_remid, conn->cc_id); |
1202 fd_log_debug(" - The certificate hostname does not match '%s'\n", conn->cc_tls_para.cn); | 1200 fd_log_debug(" - The certificate hostname does not match '%s'\n", conn->cc_tls_para.cn); |
1203 } | 1201 } |
1204 return EINVAL; | 1202 ret = EINVAL; |
1205 } | 1203 } |
1206 } | 1204 } |
1207 | 1205 |
1208 GNUTLS_TRACE( gnutls_x509_crt_deinit (cert) ); | 1206 GNUTLS_TRACE( gnutls_x509_crt_deinit (cert) ); |
1209 } | 1207 } |
1210 | 1208 |
1211 return 0; | 1209 return ret; |
1212 } | 1210 } |
1213 | 1211 |
1214 /* TLS handshake a connection; no need to have called start_clear before. Reception is active if handhsake is successful */ | 1212 /* TLS handshake a connection; no need to have called start_clear before. Reception is active if handhsake is successful */ |
1215 int fd_cnx_handshake(struct cnxctx * conn, int mode, char * priority, void * alt_creds) | 1213 int fd_cnx_handshake(struct cnxctx * conn, int mode, char * priority, void * alt_creds) |
1216 { | 1214 { |
1253 | 1251 |
1254 /* Handshake master session */ | 1252 /* Handshake master session */ |
1255 { | 1253 { |
1256 int ret; | 1254 int ret; |
1257 | 1255 |
1258 /* When gnutls 2.10.1 is around, we should use gnutls_certificate_set_verify_function */ | 1256 /* When gnutls 2.10.1 is around, we should use gnutls_certificate_set_verify_function and fd_tls_verify_credentials, so that handshake fails directly. */ |
1259 | 1257 |
1260 CHECK_GNUTLS_DO( ret = gnutls_handshake(conn->cc_tls_para.session), | 1258 CHECK_GNUTLS_DO( ret = gnutls_handshake(conn->cc_tls_para.session), |
1261 { | 1259 { |
1262 if (TRACE_BOOL(INFO)) { | 1260 if (TRACE_BOOL(INFO)) { |
1263 fd_log_debug("TLS Handshake failed on socket %d (%s) : %s\n", conn->cc_socket, conn->cc_id, gnutls_strerror(ret)); | 1261 fd_log_debug("TLS Handshake failed on socket %d (%s) : %s\n", conn->cc_socket, conn->cc_id, gnutls_strerror(ret)); |
1276 } | 1274 } |
1277 | 1275 |
1278 /* Multi-stream TLS: handshake other streams as well */ | 1276 /* Multi-stream TLS: handshake other streams as well */ |
1279 if (conn->cc_sctp_para.pairs > 1) { | 1277 if (conn->cc_sctp_para.pairs > 1) { |
1280 #ifndef DISABLE_SCTP | 1278 #ifndef DISABLE_SCTP |
1279 /* Start reading the messages from the master session. That way, if the remote peer closed, we are not stuck inside handshake */ | |
1280 CHECK_FCT(fd_sctps_startthreads(conn, 0)); | |
1281 | |
1281 /* Resume all additional sessions from the master one. */ | 1282 /* Resume all additional sessions from the master one. */ |
1282 CHECK_FCT(fd_sctps_handshake_others(conn, priority, alt_creds)); | 1283 CHECK_FCT(fd_sctps_handshake_others(conn, priority, alt_creds)); |
1283 | 1284 |
1284 /* Start decrypting the messages from all threads and queuing them in target queue */ | 1285 /* Start decrypting the messages from all threads and queuing them in target queue */ |
1285 CHECK_FCT(fd_sctps_startthreads(conn)); | 1286 CHECK_FCT(fd_sctps_startthreads(conn, 1)); |
1286 #endif /* DISABLE_SCTP */ | 1287 #endif /* DISABLE_SCTP */ |
1287 } else { | 1288 } else { |
1288 /* Start decrypting the data */ | 1289 /* Start decrypting the data */ |
1289 CHECK_POSIX( pthread_create( &conn->cc_rcvthr, NULL, rcvthr_tls_single, conn ) ); | 1290 CHECK_POSIX( pthread_create( &conn->cc_rcvthr, NULL, rcvthr_tls_single, conn ) ); |
1290 } | 1291 } |