Changeset 807:09f8f0c4f4a4 in freeDiameter for libfdcore/cnxctx.c
- Timestamp:
- Aug 24, 2012, 7:15:48 AM (12 years ago)
- Branch:
- default
- Phase:
- public
- File:
-
- 1 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));
Note: See TracChangeset
for help on using the changeset viewer.