Changeset 807:09f8f0c4f4a4 in freeDiameter for libfdcore
- Timestamp:
- Aug 24, 2012, 7:15:48 AM (12 years ago)
- Branch:
- default
- Phase:
- public
- Location:
- libfdcore
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
libfdcore/cnxctx.c
r803 r807 587 587 588 588 TRACE_DEBUG(FULL, "Error flag set for socket %d (%s, %s)", conn->cc_socket, conn->cc_id, conn->cc_remid); 589 589 590 590 /* Mark the error */ 591 591 fd_cnx_addstate(conn, CC_STATUS_ERROR); … … 597 597 fd_cnx_addstate(conn, CC_STATUS_SIGNALED); 598 598 } 599 599 600 return; 600 601 fatal: … … 843 844 case GNUTLS_E_REHANDSHAKE: 844 845 if (!fd_cnx_teststate(conn, CC_STATUS_CLOSING)) { 845 #ifdef GNUTLS_VERSION_310846 GNUTLS_TRACE( gnutls_handshake_set_timeout( session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT));847 #endif /* GNUTLS_VERSION_310 */848 846 CHECK_GNUTLS_DO( ret = gnutls_handshake(session), 849 847 { … … 891 889 case GNUTLS_E_REHANDSHAKE: 892 890 if (!fd_cnx_teststate(conn, CC_STATUS_CLOSING)) { 893 #ifdef GNUTLS_VERSION_310894 GNUTLS_TRACE( gnutls_handshake_set_timeout( session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT));895 #endif /* GNUTLS_VERSION_310 */896 897 891 CHECK_GNUTLS_DO( ret = gnutls_handshake(session), 898 892 { … … 1031 1025 gnutls_certificate_server_set_request (*session, GNUTLS_CERT_REQUIRE); 1032 1026 } 1033 1027 1034 1028 return 0; 1035 1029 } 1030 1031 #ifndef GNUTLS_VERSION_300 1036 1032 1037 1033 /* Verify remote credentials after successful handshake (return 0 if OK, EINVAL otherwise) */ … … 1254 1250 } 1255 1251 1252 #else /* GNUTLS_VERSION_300 */ 1253 1254 /* Verify remote credentials DURING handshake (return gnutls status) */ 1255 int fd_tls_verify_credentials_2(gnutls_session_t session) 1256 { 1257 /* inspired from gnutls 3.x guidelines */ 1258 unsigned int status; 1259 const gnutls_datum_t *cert_list = NULL; 1260 unsigned int cert_list_size; 1261 gnutls_x509_crt_t cert; 1262 struct cnxctx * conn; 1263 int hostname_verified = 0; 1264 1265 TRACE_ENTRY("%p", session); 1266 1267 /* get the associated connection */ 1268 conn = gnutls_session_get_ptr (session); 1269 1270 /* Trace the session information -- http://www.gnu.org/software/gnutls/manual/gnutls.html#Obtaining-session-information */ 1271 if (TRACE_BOOL(FULL)) { 1272 const char *tmp; 1273 gnutls_credentials_type_t cred; 1274 gnutls_kx_algorithm_t kx; 1275 int dhe, ecdh; 1276 1277 dhe = ecdh = 0; 1278 1279 fd_log_debug("TLS Session information for connection '%s':\n", conn->cc_id); 1280 1281 /* print the key exchange's algorithm name 1282 */ 1283 GNUTLS_TRACE( kx = gnutls_kx_get (session) ); 1284 GNUTLS_TRACE( tmp = gnutls_kx_get_name (kx) ); 1285 fd_log_debug("\t- Key Exchange: %s\n", tmp); 1286 1287 /* Check the authentication type used and switch 1288 * to the appropriate. 1289 */ 1290 GNUTLS_TRACE( cred = gnutls_auth_get_type (session) ); 1291 switch (cred) 1292 { 1293 case GNUTLS_CRD_IA: 1294 fd_log_debug("\t - TLS/IA session\n"); 1295 break; 1296 1297 1298 #ifdef ENABLE_SRP 1299 case GNUTLS_CRD_SRP: 1300 fd_log_debug("\t - SRP session with username %s\n", 1301 gnutls_srp_server_get_username (session)); 1302 break; 1303 #endif 1304 1305 case GNUTLS_CRD_PSK: 1306 /* This returns NULL in server side. 1307 */ 1308 if (gnutls_psk_client_get_hint (session) != NULL) 1309 fd_log_debug("\t - PSK authentication. PSK hint '%s'\n", 1310 gnutls_psk_client_get_hint (session)); 1311 /* This returns NULL in client side. 1312 */ 1313 if (gnutls_psk_server_get_username (session) != NULL) 1314 fd_log_debug("\t - PSK authentication. Connected as '%s'\n", 1315 gnutls_psk_server_get_username (session)); 1316 1317 if (kx == GNUTLS_KX_ECDHE_PSK) 1318 ecdh = 1; 1319 else if (kx == GNUTLS_KX_DHE_PSK) 1320 dhe = 1; 1321 break; 1322 1323 case GNUTLS_CRD_ANON: /* anonymous authentication */ 1324 fd_log_debug("\t - Anonymous DH using prime of %d bits\n", 1325 gnutls_dh_get_prime_bits (session)); 1326 if (kx == GNUTLS_KX_ANON_ECDH) 1327 ecdh = 1; 1328 else if (kx == GNUTLS_KX_ANON_DH) 1329 dhe = 1; 1330 break; 1331 1332 case GNUTLS_CRD_CERTIFICATE: /* certificate authentication */ 1333 1334 /* Check if we have been using ephemeral Diffie-Hellman. 1335 */ 1336 if (kx == GNUTLS_KX_DHE_RSA || kx == GNUTLS_KX_DHE_DSS) 1337 dhe = 1; 1338 else if (kx == GNUTLS_KX_ECDHE_RSA || kx == GNUTLS_KX_ECDHE_ECDSA) 1339 ecdh = 1; 1340 1341 /* Now print some info on the remote certificate */ 1342 if (gnutls_certificate_type_get (session) == GNUTLS_CRT_X509) { 1343 gnutls_datum_t cinfo; 1344 1345 cert_list = gnutls_certificate_get_peers (session, &cert_list_size); 1346 1347 fd_log_debug("\t Peer provided %d certificates.\n", cert_list_size); 1348 1349 if (cert_list_size > 0) 1350 { 1351 int ret; 1352 1353 /* we only print information about the first certificate. 1354 */ 1355 gnutls_x509_crt_init (&cert); 1356 1357 gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER); 1358 1359 fd_log_debug("\t Certificate info:\n"); 1360 1361 /* This is the preferred way of printing short information about 1362 a certificate. */ 1363 1364 ret = gnutls_x509_crt_print (cert, GNUTLS_CRT_PRINT_ONELINE, &cinfo); 1365 if (ret == 0) 1366 { 1367 fd_log_debug("\t\t%s\n", cinfo.data); 1368 gnutls_free (cinfo.data); 1369 } 1370 1371 if (conn->cc_tls_para.cn) { 1372 if (!gnutls_x509_crt_check_hostname (cert, conn->cc_tls_para.cn)) { 1373 fd_log_debug("\tTLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :\n", conn->cc_socket, conn->cc_remid, conn->cc_id); 1374 fd_log_debug("\t - The certificate hostname does not match '%s'\n", conn->cc_tls_para.cn); 1375 gnutls_x509_crt_deinit (cert); 1376 return GNUTLS_E_CERTIFICATE_ERROR; 1377 } 1378 1379 } 1380 1381 hostname_verified = 1; 1382 1383 gnutls_x509_crt_deinit (cert); 1384 1385 } 1386 } 1387 break; 1388 1389 } /* switch */ 1390 1391 if (ecdh != 0) 1392 fd_log_debug("\t - Ephemeral ECDH using curve %s\n", 1393 gnutls_ecc_curve_get_name (gnutls_ecc_curve_get (session))); 1394 else if (dhe != 0) 1395 fd_log_debug("\t - Ephemeral DH using prime of %d bits\n", 1396 gnutls_dh_get_prime_bits (session)); 1397 1398 /* print the protocol's name (ie TLS 1.0) 1399 */ 1400 tmp = gnutls_protocol_get_name (gnutls_protocol_get_version (session)); 1401 fd_log_debug("\t - Protocol: %s\n", tmp); 1402 1403 /* print the certificate type of the peer. 1404 * ie X.509 1405 */ 1406 tmp = gnutls_certificate_type_get_name (gnutls_certificate_type_get (session)); 1407 fd_log_debug("\t - Certificate Type: %s\n", tmp); 1408 1409 /* print the compression algorithm (if any) 1410 */ 1411 tmp = gnutls_compression_get_name (gnutls_compression_get (session)); 1412 fd_log_debug("\t - Compression: %s\n", tmp); 1413 1414 /* print the name of the cipher used. 1415 * ie 3DES. 1416 */ 1417 tmp = gnutls_cipher_get_name (gnutls_cipher_get (session)); 1418 fd_log_debug("\t - Cipher: %s\n", tmp); 1419 1420 /* Print the MAC algorithms name. 1421 * ie SHA1 1422 */ 1423 tmp = gnutls_mac_get_name (gnutls_mac_get (session)); 1424 fd_log_debug("\t - MAC: %s\n", tmp); 1425 1426 } 1427 1428 /* This verification function uses the trusted CAs in the credentials 1429 * structure. So you must have installed one or more CA certificates. 1430 */ 1431 CHECK_GNUTLS_DO( gnutls_certificate_verify_peers2 (session, &status), return GNUTLS_E_CERTIFICATE_ERROR ); 1432 if (TRACE_BOOL(INFO) && (status & GNUTLS_CERT_INVALID)) { 1433 fd_log_debug("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :\n", conn->cc_socket, conn->cc_remid, conn->cc_id); 1434 if (status & GNUTLS_CERT_SIGNER_NOT_FOUND) 1435 fd_log_debug(" - The certificate hasn't got a known issuer.\n"); 1436 1437 if (status & GNUTLS_CERT_REVOKED) 1438 fd_log_debug(" - The certificate has been revoked.\n"); 1439 1440 if (status & GNUTLS_CERT_EXPIRED) 1441 fd_log_debug(" - The certificate has expired.\n"); 1442 1443 if (status & GNUTLS_CERT_NOT_ACTIVATED) 1444 fd_log_debug(" - The certificate is not yet activated.\n"); 1445 } 1446 if (status & GNUTLS_CERT_INVALID) 1447 { 1448 return GNUTLS_E_CERTIFICATE_ERROR; 1449 } 1450 1451 /* Up to here the process is the same for X.509 certificates and 1452 * OpenPGP keys. From now on X.509 certificates are assumed. This can 1453 * be easily extended to work with openpgp keys as well. 1454 */ 1455 if ((!hostname_verified) && (conn->cc_tls_para.cn)) { 1456 if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) { 1457 TRACE_DEBUG(INFO, "TLS: Remote credentials are not x509, rejected on socket %d (Remote: '%s')(Connection: '%s') :\n", conn->cc_socket, conn->cc_remid, conn->cc_id); 1458 return GNUTLS_E_CERTIFICATE_ERROR; 1459 } 1460 1461 CHECK_GNUTLS_DO( gnutls_x509_crt_init (&cert), return GNUTLS_E_CERTIFICATE_ERROR ); 1462 1463 cert_list = gnutls_certificate_get_peers (session, &cert_list_size); 1464 CHECK_PARAMS_DO( cert_list, return GNUTLS_E_CERTIFICATE_ERROR ); 1465 1466 CHECK_GNUTLS_DO( gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER), return GNUTLS_E_CERTIFICATE_ERROR ); 1467 1468 if (!gnutls_x509_crt_check_hostname (cert, conn->cc_tls_para.cn)) { 1469 if (TRACE_BOOL(INFO)) { 1470 fd_log_debug("TLS: Remote certificate invalid on socket %d (Remote: '%s')(Connection: '%s') :\n", conn->cc_socket, conn->cc_remid, conn->cc_id); 1471 fd_log_debug(" - The certificate hostname does not match '%s'\n", conn->cc_tls_para.cn); 1472 } 1473 gnutls_x509_crt_deinit (cert); 1474 return GNUTLS_E_CERTIFICATE_ERROR; 1475 } 1476 1477 gnutls_x509_crt_deinit (cert); 1478 } 1479 1480 /* notify gnutls to continue handshake normally */ 1481 return 0; 1482 } 1483 1484 #endif /* GNUTLS_VERSION_300 */ 1485 1256 1486 /* TLS handshake a connection; no need to have called start_clear before. Reception is active if handhsake is successful */ 1257 1487 int fd_cnx_handshake(struct cnxctx * conn, int mode, char * priority, void * alt_creds) … … 1289 1519 GNUTLS_TRACE( gnutls_transport_set_push_function(conn->cc_tls_para.session, (void *)fd_cnx_s_send) ); 1290 1520 } 1291 1521 1522 /* additional initialization for gnutls 3.x */ 1523 #ifdef GNUTLS_VERSION_300 1524 /* the verify function has already been set in the global initialization in config.c */ 1525 1526 /* fd_tls_verify_credentials_2 uses the connection */ 1527 gnutls_session_set_ptr (conn->cc_tls_para.session, (void *) conn); 1528 1529 if ((conn->cc_tls_para.cn != NULL) && (mode == GNUTLS_CLIENT)) { 1530 /* this might allow virtual hosting on the remote peer */ 1531 CHECK_GNUTLS_DO( gnutls_server_name_set (conn->cc_tls_para.session, GNUTLS_NAME_DNS, conn->cc_tls_para.cn, strlen(conn->cc_tls_para.cn)), /* ignore failure */); 1532 } 1533 1534 #endif /* GNUTLS_VERSION_300 */ 1535 1536 #ifdef GNUTLS_VERSION_310 1537 GNUTLS_TRACE( gnutls_handshake_set_timeout( conn->cc_tls_para.session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT)); 1538 #endif /* GNUTLS_VERSION_310 */ 1539 1292 1540 /* Mark the connection as protected from here, so that the gnutls credentials will be freed */ 1293 1541 fd_cnx_addstate(conn, CC_STATUS_TLS); … … 1296 1544 { 1297 1545 int ret; 1298 #ifdef GNUTLS_VERSION_310 1299 GNUTLS_TRACE( gnutls_handshake_set_timeout( conn->cc_tls_para.session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT)); 1300 #endif /* GNUTLS_VERSION_310 */ 1301 1302 /* 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. */ 1303 1546 1304 1547 CHECK_GNUTLS_DO( ret = gnutls_handshake(conn->cc_tls_para.session), 1305 1548 { … … 1311 1554 } ); 1312 1555 1556 #ifndef GNUTLS_VERSION_300 1313 1557 /* Now verify the remote credentials are valid -- only simple tests here */ 1314 1558 CHECK_FCT_DO( fd_tls_verify_credentials(conn->cc_tls_para.session, conn, 1), … … 1318 1562 return EINVAL; 1319 1563 }); 1564 #endif /* GNUTLS_VERSION_300 */ 1320 1565 } 1321 1566 … … 1325 1570 /* Start reading the messages from the master session. That way, if the remote peer closed, we are not stuck inside handshake */ 1326 1571 CHECK_FCT(fd_sctps_startthreads(conn, 0)); 1327 1572 1328 1573 /* Resume all additional sessions from the master one. */ 1329 1574 CHECK_FCT(fd_sctps_handshake_others(conn, priority, alt_creds)); -
libfdcore/cnxctx.h
r740 r807 98 98 int fd_tls_rcvthr_core(struct cnxctx * conn, gnutls_session_t session); 99 99 int fd_tls_prepare(gnutls_session_t * session, int mode, char * priority, void * alt_creds); 100 #ifndef GNUTLS_VERSION_300 100 101 int fd_tls_verify_credentials(gnutls_session_t session, struct cnxctx * conn, int verbose); 102 #endif /* GNUTLS_VERSION_300 */ 101 103 102 104 /* TCP */ … … 143 145 #endif /* DISABLE_SCTP */ 144 146 145 146 147 #endif /* _CNXCTX_H */ 147 148 -
libfdcore/config.c
r805 r807 538 538 /* gnutls_certificate_set_verify_limits -- so far the default values are fine... */ 539 539 540 #ifdef GNUTLS_VERSION_300 541 /* Use certificate verification during the handshake */ 542 gnutls_certificate_set_verify_function (fd_g_config->cnf_sec_data.credentials, fd_tls_verify_credentials_2); 543 #endif /* GNUTLS_VERSION_300 */ 544 540 545 /* DH */ 541 546 if (fd_g_config->cnf_sec_data.dh_file) { -
libfdcore/fdcore-internal.h
r805 r807 352 352 int fd_cnx_send(struct cnxctx * conn, unsigned char * buf, size_t len, uint32_t flags); 353 353 void fd_cnx_destroy(struct cnxctx * conn); 354 #ifdef GNUTLS_VERSION_300 355 int fd_tls_verify_credentials_2(gnutls_session_t session); 356 #endif /* GNUTLS_VERSION_300 */ 354 357 355 358 /* Flags for the fd_cnx_send function : */ -
libfdcore/sctps.c
r803 r807 105 105 106 106 case FDEVP_CNX_ERROR: 107 fd_cnx_markerror(conn);108 107 goto out; 109 108 … … 121 120 /* Signal termination of the connection to all decipher threads */ 122 121 for (strid = 0; strid < conn->cc_sctp_para.pairs; strid++) { 123 if (conn->cc_sctps_data.array[strid].raw_recv) 122 if (conn->cc_sctps_data.array[strid].raw_recv) { 124 123 CHECK_FCT_DO(fd_event_send(conn->cc_sctps_data.array[strid].raw_recv, FDEVP_CNX_ERROR, 0, NULL), goto fatal ); 125 } 124 } 125 } 126 fd_cnx_markerror(conn); 126 127 TRACE_DEBUG(FULL, "Thread terminated"); 127 128 return NULL; … … 171 172 CHECK_PARAMS_DO( tr && data, { errno = EINVAL; return -1; } ); 172 173 173 CHECK_FCT_DO( fd_sctp_sendstr(ctx->parent, ctx->strid, (uint8_t *)data, len), /* errno is already set */return -1 );174 CHECK_FCT_DO( fd_sctp_sendstr(ctx->parent, ctx->strid, (uint8_t *)data, len), return -1 ); 174 175 175 176 return len; … … 184 185 185 186 TRACE_ENTRY("%p %p %zd", tr, buf, len); 186 CHECK_PARAMS_DO( tr && buf, { errno = EINVAL; return -1; } );187 CHECK_PARAMS_DO( tr && buf, { errno = EINVAL; goto error; } ); 187 188 188 189 /* If we don't have data available now, pull new message from the fifo -- this is blocking (until the queue is destroyed) */ 189 190 if (!ctx->partial.buf) { 190 191 int ev; 191 CHECK_FCT_DO( errno = fd_event_get(ctx->raw_recv, &ev, &ctx->partial.bufsz, (void *)&ctx->partial.buf), return -1 ); 192 if (ev == FDEVP_CNX_ERROR) 193 return 0; /* connection closed */ 192 CHECK_FCT_DO( errno = fd_event_get(ctx->raw_recv, &ev, &ctx->partial.bufsz, (void *)&ctx->partial.buf), goto error ); 193 if (ev == FDEVP_CNX_ERROR) { 194 /* Documentations says to return 0 on connection closed, but it does hang within gnutls_handshake */ 195 return -1; 196 } 194 197 } 195 198 … … 216 219 /* We are done */ 217 220 return pulled; 221 222 error: 223 gnutls_transport_set_errno (ctx->session, errno); 224 return -1; 218 225 } 219 226 … … 463 470 464 471 TRACE_DEBUG(FULL, "Starting TLS resumed handshake on stream %hu", ctx->strid); 465 #ifdef GNUTLS_VERSION_310 466 GNUTLS_TRACE( gnutls_handshake_set_timeout( ctx->session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT)); 467 #endif /* GNUTLS_VERSION_310 */ 472 468 473 CHECK_GNUTLS_DO( gnutls_handshake( ctx->session ), return NULL); 469 474 470 475 GNUTLS_TRACE( resumed = gnutls_session_is_resumed(ctx->session) ); 476 #ifndef GNUTLS_VERSION_300 471 477 if (!resumed) { 472 478 /* Check the credentials here also */ 473 479 CHECK_FCT_DO( fd_tls_verify_credentials(ctx->session, ctx->parent, 0), return NULL ); 474 480 } 481 #endif /* GNUTLS_VERSION_300 */ 475 482 if (TRACE_BOOL(FULL)) { 476 483 if (resumed) { 477 484 fd_log_debug("Session was resumed successfully on stream %hu (conn: '%s')\n", ctx->strid, fd_cnx_getid(ctx->parent)); 478 485 } else { 479 fd_log_debug("Session was NOT resumed on stream %hu (full handshake + verif) (conn: '%s')\n", ctx->strid, fd_cnx_getid(ctx->parent));486 fd_log_debug("Session was NOT resumed on stream %hu (full handshake) (conn: '%s')\n", ctx->strid, fd_cnx_getid(ctx->parent)); 480 487 } 481 488 } … … 555 562 CHECK_FCT( fd_tls_prepare(&conn->cc_sctps_data.array[i].session, conn->cc_tls_para.mode, priority, alt_creds) ); 556 563 564 /* additional initialization for gnutls 3.x */ 565 #ifdef GNUTLS_VERSION_300 566 /* the verify function has already been set in the global initialization in config.c */ 567 568 /* fd_tls_verify_credentials_2 uses the connection */ 569 gnutls_session_set_ptr (conn->cc_sctps_data.array[i].session, (void *) conn); 570 571 if ((conn->cc_tls_para.cn != NULL) && (conn->cc_tls_para.mode == GNUTLS_CLIENT)) { 572 /* this might allow virtual hosting on the remote peer */ 573 CHECK_GNUTLS_DO( gnutls_server_name_set (conn->cc_sctps_data.array[i].session, GNUTLS_NAME_DNS, conn->cc_tls_para.cn, strlen(conn->cc_tls_para.cn)), /* ignore failure */); 574 } 575 576 #endif /* GNUTLS_VERSION_300 */ 577 578 #ifdef GNUTLS_VERSION_310 579 GNUTLS_TRACE( gnutls_handshake_set_timeout( conn->cc_sctps_data.array[i].session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT)); 580 #endif /* GNUTLS_VERSION_310 */ 581 557 582 /* For the client, copy data from master session; for the server, set session resuming pointers */ 558 583 if (conn->cc_tls_para.mode == GNUTLS_CLIENT) {
Note: See TracChangeset
for help on using the changeset viewer.