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 }
"Welcome to our mercurial repository"