Changeset 1419:89cbb08d3189 in freeDiameter for libfdcore
- Timestamp:
- Feb 18, 2020, 7:38:37 PM (4 years ago)
- Branch:
- default
- Phase:
- public
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
libfdcore/cnxctx.c
r1356 r1419 177 177 cnx->cc_family = AF_INET6; /* can create socket for both IP and IPv6 */ 178 178 } 179 179 180 180 /* Create the socket */ 181 181 CHECK_FCT_DO( fd_sctp_create_bind_server( &cnx->cc_socket, cnx->cc_family, ep_list, port ), goto error ); … … 227 227 TRACE_ENTRY("%p", serv); 228 228 CHECK_PARAMS_DO(serv, return NULL); 229 229 230 230 /* Accept the new connection -- this is blocking until new client enters or until cancellation */ 231 231 CHECK_SYS_DO( cli_sock = accept(serv->cc_socket, (sSA *)&ss, &ss_len), return NULL ); 232 232 233 233 CHECK_MALLOC_DO( cli = fd_cnx_init(1), { shutdown(cli_sock, SHUT_RDWR); close(cli_sock); return NULL; } ); 234 234 cli->cc_socket = cli_sock; 235 235 cli->cc_family = serv->cc_family; 236 236 cli->cc_proto = serv->cc_proto; 237 237 238 238 /* Set the timeout */ 239 239 fd_cnx_s_setto(cli->cc_socket); 240 240 241 241 /* Generate the name for the connection object */ 242 242 { … … 244 244 char portbuf[10]; 245 245 int rc; 246 246 247 247 rc = getnameinfo((sSA *)&ss, ss_len, addrbuf, sizeof(addrbuf), portbuf, sizeof(portbuf), NI_NUMERICHOST | NI_NUMERICSERV); 248 248 if (rc) { … … 250 250 portbuf[0] = '\0'; 251 251 } 252 252 253 253 /* Numeric values for debug... */ 254 snprintf(cli->cc_id, sizeof(cli->cc_id), CC_ID_HDR "%s from [%s]:%s (%d<-%d)", 254 snprintf(cli->cc_id, sizeof(cli->cc_id), CC_ID_HDR "%s from [%s]:%s (%d<-%d)", 255 255 IPPROTO_NAME(cli->cc_proto), addrbuf, portbuf, serv->cc_socket, cli->cc_socket); 256 257 256 257 258 258 /* ...Name for log messages */ 259 259 rc = getnameinfo((sSA *)&ss, ss_len, cli->cc_remid, sizeof(cli->cc_remid), NULL, 0, 0); … … 261 261 snprintf(cli->cc_remid, sizeof(cli->cc_remid), "[err:%s]", gai_strerror(rc)); 262 262 } 263 263 264 264 LOG_D("Incoming connection: '%s' <- '%s' {%s}", fd_cnx_getid(serv), cli->cc_remid, cli->cc_id); 265 265 … … 273 273 else 274 274 cli->cc_sctp_para.pairs = cli->cc_sctp_para.str_in; 275 275 276 276 LOG_A( "%s : client '%s' (SCTP:%d, %d/%d streams)", fd_cnx_getid(serv), fd_cnx_getid(cli), cli->cc_socket, cli->cc_sctp_para.str_in, cli->cc_sctp_para.str_out); 277 277 } … … 287 287 struct cnxctx * cnx = NULL; 288 288 char sa_buf[sSA_DUMP_STRLEN]; 289 289 290 290 TRACE_ENTRY("%p %d", sa, addrlen); 291 291 CHECK_PARAMS_DO( sa && addrlen, return NULL ); 292 292 293 293 fd_sa_sdump_numeric(sa_buf, sa); 294 294 295 295 LOG_D("Connecting to TCP %s...", sa_buf); 296 296 297 297 /* Create the socket and connect, which can take some time and/or fail */ 298 298 { … … 303 303 } 304 304 } 305 305 306 306 /* Once the socket is created successfuly, prepare the remaining of the cnx */ 307 307 CHECK_MALLOC_DO( cnx = fd_cnx_init(1), { shutdown(sock, SHUT_RDWR); close(sock); return NULL; } ); 308 308 309 309 cnx->cc_socket = sock; 310 310 cnx->cc_family = sa->sa_family; 311 311 cnx->cc_proto = IPPROTO_TCP; 312 312 313 313 /* Set the timeout */ 314 314 fd_cnx_s_setto(cnx->cc_socket); 315 315 316 316 /* Generate the names for the object */ 317 317 { 318 318 int rc; 319 319 320 320 snprintf(cnx->cc_id, sizeof(cnx->cc_id), CC_ID_HDR "TCP,#%d->%s", cnx->cc_socket, sa_buf); 321 321 322 322 /* ...Name for log messages */ 323 323 rc = getnameinfo(sa, addrlen, cnx->cc_remid, sizeof(cnx->cc_remid), NULL, 0, 0); … … 325 325 snprintf(cnx->cc_remid, sizeof(cnx->cc_remid), "[err:%s]", gai_strerror(rc)); 326 326 } 327 327 328 328 LOG_A("TCP connection to %s succeed (socket:%d).", sa_buf, sock); 329 329 330 330 return cnx; 331 331 } … … 344 344 char sa_buf[sSA_DUMP_STRLEN]; 345 345 sSS primary; 346 346 347 347 TRACE_ENTRY("%p", list); 348 348 CHECK_PARAMS_DO( list && !FD_IS_LIST_EMPTY(list), return NULL ); 349 349 350 350 fd_sa_sdump_numeric(sa_buf, &((struct fd_endpoint *)(list->next))->sa); 351 351 352 352 LOG_D("Connecting to SCTP %s:%hu...", sa_buf, port); 353 353 354 354 { 355 355 int ret = fd_sctp_client( &sock, no_ip6, port, list ); … … 359 359 } 360 360 } 361 361 362 362 /* Once the socket is created successfuly, prepare the remaining of the cnx */ 363 363 CHECK_MALLOC_DO( cnx = fd_cnx_init(1), { shutdown(sock, SHUT_RDWR); close(sock); return NULL; } ); 364 364 365 365 cnx->cc_socket = sock; 366 366 cnx->cc_family = no_ip6 ? AF_INET : AF_INET6; 367 367 cnx->cc_proto = IPPROTO_SCTP; 368 368 369 369 /* Set the timeout */ 370 370 fd_cnx_s_setto(cnx->cc_socket); 371 371 372 372 /* Retrieve the number of streams and primary address */ 373 373 CHECK_FCT_DO( fd_sctp_get_str_info( sock, &cnx->cc_sctp_para.str_in, &cnx->cc_sctp_para.str_out, &primary ), goto error ); … … 376 376 else 377 377 cnx->cc_sctp_para.pairs = cnx->cc_sctp_para.str_in; 378 378 379 379 fd_sa_sdump_numeric(sa_buf, (sSA *)&primary); 380 380 381 381 /* Generate the names for the object */ 382 382 { 383 383 int rc; 384 384 385 385 snprintf(cnx->cc_id, sizeof(cnx->cc_id), CC_ID_HDR "SCTP,#%d->%s", cnx->cc_socket, sa_buf); 386 386 387 387 /* ...Name for log messages */ 388 388 rc = getnameinfo((sSA *)&primary, sSAlen(&primary), cnx->cc_remid, sizeof(cnx->cc_remid), NULL, 0, 0); … … 390 390 snprintf(cnx->cc_remid, sizeof(cnx->cc_remid), "[err:%s]", gai_strerror(rc)); 391 391 } 392 392 393 393 LOG_A("SCTP connection to %s succeed (socket:%d, %d/%d streams).", sa_buf, sock, cnx->cc_sctp_para.str_in, cnx->cc_sctp_para.str_out); 394 394 395 395 return cnx; 396 396 … … 445 445 else 446 446 conn->cc_id[1] = '-'; 447 447 448 448 if (conn->cc_state & CC_STATUS_ERROR) 449 449 conn->cc_id[2] = 'E'; 450 450 else 451 451 conn->cc_id[2] = '-'; 452 452 453 453 if (conn->cc_state & CC_STATUS_SIGNALED) 454 454 conn->cc_id[3] = 'S'; 455 455 else 456 456 conn->cc_id[3] = '-'; 457 457 458 458 if (conn->cc_state & CC_STATUS_TLS) 459 459 conn->cc_id[4] = 'T'; … … 509 509 TRACE_ENTRY("%p %p", conn, eps); 510 510 CHECK_PARAMS(conn && eps); 511 511 512 512 /* Check we have a full connection object, not a listening socket (with no remote) */ 513 513 CHECK_PARAMS( conn->cc_incoming ); … … 547 547 548 548 /* Get a short string representing the connection */ 549 int fd_cnx_proto_info(struct cnxctx * conn, char * buf, size_t len) 549 int fd_cnx_proto_info(struct cnxctx * conn, char * buf, size_t len) 550 550 { 551 551 CHECK_PARAMS( conn ); 552 552 553 553 if (fd_cnx_teststate(conn, CC_STATUS_TLS)) { 554 554 snprintf(buf, len, "%s,%s,soc#%d", IPPROTO_NAME(conn->cc_proto), fd_cnx_may_dtls(conn) ? "DTLS" : "TLS", conn->cc_socket); … … 556 556 snprintf(buf, len, "%s,soc#%d", IPPROTO_NAME(conn->cc_proto), conn->cc_socket); 557 557 } 558 558 559 559 return 0; 560 560 } … … 564 564 { 565 565 struct ifaddrs *iflist, *cur; 566 566 567 567 CHECK_SYS(getifaddrs(&iflist)); 568 568 569 569 for (cur = iflist; cur != NULL; cur = cur->ifa_next) { 570 570 if (cur->ifa_flags & IFF_LOOPBACK) 571 571 continue; 572 572 573 573 if (cur->ifa_addr == NULL) /* may happen with ppp interfaces */ 574 574 continue; 575 575 576 576 if (fd_g_config->cnf_flags.no_ip4 && (cur->ifa_addr->sa_family == AF_INET)) 577 577 continue; 578 578 579 579 if (fd_g_config->cnf_flags.no_ip6 && (cur->ifa_addr->sa_family == AF_INET6)) 580 580 continue; 581 581 582 582 CHECK_FCT(fd_ep_add_merge( list, cur->ifa_addr, sSAlen(cur->ifa_addr), EP_FL_LL )); 583 583 } 584 584 585 585 freeifaddrs(iflist); 586 586 587 587 return 0; 588 588 } … … 598 598 TRACE_ENTRY("%p", conn); 599 599 CHECK_PARAMS_DO( conn, goto fatal ); 600 600 601 601 TRACE_DEBUG(FULL, "Error flag set for socket %d (%s, %s)", conn->cc_socket, conn->cc_id, conn->cc_remid); 602 602 603 603 /* Mark the error */ 604 604 fd_cnx_addstate(conn, CC_STATUS_ERROR); 605 605 606 606 /* Report the error if not reported yet, and not closing */ 607 607 if (!fd_cnx_teststate(conn, CC_STATUS_CLOSING | CC_STATUS_SIGNALED )) { … … 610 610 fd_cnx_addstate(conn, CC_STATUS_SIGNALED); 611 611 } 612 612 613 613 return; 614 614 fatal: 615 615 /* An unrecoverable error occurred, stop the daemon */ 616 616 ASSERT(0); 617 CHECK_FCT_DO(fd_core_shutdown(), ); 617 CHECK_FCT_DO(fd_core_shutdown(), ); 618 618 } 619 619 620 620 /* Set the timeout option on the socket */ 621 void fd_cnx_s_setto(int sock) 621 void fd_cnx_s_setto(int sock) 622 622 { 623 623 struct timeval tv; 624 624 625 625 /* Set a timeout on the socket so that in any case we are not stuck waiting for something */ 626 626 memset(&tv, 0, sizeof(tv)); … … 637 637 fd_set rfds; 638 638 struct timeval tv; 639 639 640 640 FD_ZERO (&rfds); 641 641 FD_SET (conn->cc_socket, &rfds); 642 642 643 643 tv.tv_sec = ms / 1000; 644 644 tv.tv_usec = (ms * 1000) % 1000000; 645 645 646 646 return select (conn->cc_socket + 1, &rfds, NULL, NULL, &tv); 647 } 647 } 648 648 #endif /* GNUTLS_VERSION_300 */ 649 649 … … 665 665 } 666 666 } 667 667 668 668 /* Mark the error */ 669 669 if (ret <= 0) { … … 671 671 fd_cnx_markerror(conn); 672 672 } 673 673 674 674 return ret; 675 675 } … … 687 687 ret = -errno; 688 688 pthread_testcancel(); 689 689 690 690 /* Check how much time we were blocked for this sending. */ 691 691 CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &now), return -1 ); … … 695 695 goto again; /* don't care, just ignore */ 696 696 } 697 697 698 698 /* propagate the error */ 699 699 errno = -ret; … … 701 701 CHECK_SYS_DO(ret, /* continue */); 702 702 } 703 703 704 704 /* Mark the error */ 705 705 if (ret <= 0) 706 706 fd_cnx_markerror(conn); 707 707 708 708 return ret; 709 709 } … … 731 731 { 732 732 return (struct fd_msg_pmdl *)(buf + PMDL_PADDED(datalen)); 733 } 733 } 734 734 735 735 static int fd_cnx_init_msg_buffer(uint8_t * buffer, size_t expected_len, struct fd_msg_pmdl ** pmdl) … … 744 744 { 745 745 uint8_t * ret = NULL; 746 746 747 747 CHECK_MALLOC_DO( ret = malloc( fd_msg_pmdl_sizewithoverhead(expected_len) ), return NULL ); 748 748 CHECK_FCT_DO( fd_cnx_init_msg_buffer(ret, expected_len, pmdl), {free(ret); return NULL;} ); … … 754 754 { 755 755 uint8_t * ret = NULL; 756 756 757 757 CHECK_MALLOC_DO( ret = realloc( buffer, fd_msg_pmdl_sizewithoverhead(expected_len) ), return NULL ); 758 758 CHECK_FCT_DO( fd_cnx_init_msg_buffer(ret, expected_len, pmdl), {free(ret); return NULL;} ); … … 761 761 #endif /* DISABLE_SCTP */ 762 762 763 static void free_rcvdata(void * arg) 763 static void free_rcvdata(void * arg) 764 764 { 765 765 struct fd_cnx_rcvdata * data = arg; … … 773 773 { 774 774 struct cnxctx * conn = arg; 775 775 776 776 TRACE_ENTRY("%p", arg); 777 777 CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), goto out); 778 778 779 779 /* Set the thread name */ 780 780 { … … 783 783 fd_log_threadname ( buf ); 784 784 } 785 785 786 786 ASSERT( conn->cc_proto == IPPROTO_TCP ); 787 787 ASSERT( ! fd_cnx_teststate(conn, CC_STATUS_TLS ) ); 788 788 ASSERT( fd_cnx_target_queue(conn) ); 789 789 790 790 /* Receive from a TCP connection: we have to rebuild the message boundaries */ 791 791 do { … … 803 803 804 804 received += ret; 805 805 806 806 if (header[0] != DIAMETER_VERSION) 807 807 break; /* No need to wait for 4 bytes in this case */ … … 834 834 received += ret; 835 835 } 836 836 837 837 fd_hook_call(HOOK_DATA_RECEIVED, NULL, NULL, &rcv_data, pmdl); 838 838 839 839 /* We have received a complete message, pass it to the daemon */ 840 CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, rcv_data.length, rcv_data.buffer), 841 { 840 CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, rcv_data.length, rcv_data.buffer), 841 { 842 842 free_rcvdata(&rcv_data); 843 goto fatal; 843 goto fatal; 844 844 } ); 845 845 846 846 } while (conn->cc_loop); 847 847 848 848 out: 849 TRACE_DEBUG(FULL, "Thread terminated"); 849 TRACE_DEBUG(FULL, "Thread terminated"); 850 850 return NULL; 851 851 852 852 fatal: 853 853 /* An unrecoverable error occurred, stop the daemon */ … … 863 863 struct fd_cnx_rcvdata rcv_data; 864 864 int event; 865 865 866 866 TRACE_ENTRY("%p", arg); 867 867 CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), goto fatal); 868 868 869 869 /* Set the thread name */ 870 870 { … … 873 873 fd_log_threadname ( buf ); 874 874 } 875 875 876 876 ASSERT( conn->cc_proto == IPPROTO_SCTP ); 877 877 ASSERT( ! fd_cnx_teststate(conn, CC_STATUS_TLS ) ); 878 878 ASSERT( fd_cnx_target_queue(conn) ); 879 879 880 880 do { 881 881 struct fd_msg_pmdl *pmdl=NULL; … … 885 885 goto out; 886 886 } 887 887 888 888 if (event == FDEVP_CNX_SHUTDOWN) { 889 889 /* Just ignore the notification for now, we will get another error later anyway */ … … 896 896 } 897 897 CHECK_FCT_DO( fd_event_send( fd_cnx_target_queue(conn), event, rcv_data.length, rcv_data.buffer), goto fatal ); 898 898 899 899 } while (conn->cc_loop || (event != FDEVP_CNX_MSG_RECV)); 900 900 901 901 out: 902 TRACE_DEBUG(FULL, "Thread terminated"); 902 TRACE_DEBUG(FULL, "Thread terminated"); 903 903 return NULL; 904 904 … … 914 914 { 915 915 TRACE_ENTRY("%p %i", conn, loop); 916 916 917 917 CHECK_PARAMS( conn && fd_cnx_target_queue(conn) && (!fd_cnx_teststate(conn, CC_STATUS_TLS)) && (!conn->cc_loop)); 918 918 919 919 /* Release resources in case of a previous call was already made */ 920 920 CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */); 921 921 922 922 /* Save the loop request */ 923 923 conn->cc_loop = loop; 924 924 925 925 switch (conn->cc_proto) { 926 926 case IPPROTO_TCP: … … 939 939 return ENOTSUP; 940 940 } 941 941 942 942 return 0; 943 943 } … … 950 950 { 951 951 ssize_t ret; 952 again: 953 CHECK_GNUTLS_DO( ret = gnutls_record_recv(session, data, sz), 952 again: 953 CHECK_GNUTLS_DO( ret = gnutls_record_recv(session, data, sz), 954 954 { 955 955 switch (ret) { 956 case GNUTLS_E_REHANDSHAKE: 956 case GNUTLS_E_REHANDSHAKE: 957 957 if (!fd_cnx_teststate(conn, CC_STATUS_CLOSING)) { 958 958 CHECK_GNUTLS_DO( ret = gnutls_handshake(session), … … 976 976 TRACE_DEBUG(FULL, "Got 0 size while reading the socket, probably connection closed..."); 977 977 break; 978 978 979 979 default: 980 980 if (gnutls_error_is_fatal (ret) == 0) { … … 985 985 } 986 986 } ); 987 987 988 988 if (ret == 0) 989 989 CHECK_GNUTLS_DO( gnutls_bye(session, GNUTLS_SHUT_RDWR), ); 990 991 end: 990 991 end: 992 992 if (ret <= 0) 993 993 fd_cnx_markerror(conn); … … 1001 1001 struct timespec ts, now; 1002 1002 CHECK_SYS_DO( clock_gettime(CLOCK_REALTIME, &ts), return -1 ); 1003 again: 1003 again: 1004 1004 CHECK_GNUTLS_DO( ret = gnutls_record_send(session, data, sz), 1005 1005 { 1006 1006 pthread_testcancel(); 1007 1007 switch (ret) { 1008 case GNUTLS_E_REHANDSHAKE: 1008 case GNUTLS_E_REHANDSHAKE: 1009 1009 if (!fd_cnx_teststate(conn, CC_STATUS_CLOSING)) { 1010 1010 CHECK_GNUTLS_DO( ret = gnutls_handshake(session), … … 1035 1035 } 1036 1036 } ); 1037 end: 1037 end: 1038 1038 if (ret <= 0) 1039 1039 fd_cnx_markerror(conn); 1040 1040 1041 1041 return ret; 1042 1042 } … … 1046 1046 /* For the case of DTLS, since we are not using SCTP_UNORDERED, the messages over a single stream are ordered. 1047 1047 Furthermore, as long as messages are shorter than the MTU [2^14 = 16384 bytes], they are delivered in a single 1048 record, as far as I understand. 1049 For larger messages, however, it is possible that pieces of messages coming from different streams can get interleaved. 1048 record, as far as I understand. 1049 For larger messages, however, it is possible that pieces of messages coming from different streams can get interleaved. 1050 1050 As a result, we do not use the following function for DTLS reception, because we use the sequence number to rebuild the 1051 1051 messages. */ … … 1096 1096 received += ret; 1097 1097 } 1098 1098 1099 1099 fd_hook_call(HOOK_DATA_RECEIVED, NULL, NULL, &rcv_data, pmdl); 1100 1100 1101 1101 /* We have received a complete message, pass it to the daemon */ 1102 CHECK_FCT_DO( ret = fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, rcv_data.length, rcv_data.buffer), 1103 { 1102 CHECK_FCT_DO( ret = fd_event_send( fd_cnx_target_queue(conn), FDEVP_CNX_MSG_RECV, rcv_data.length, rcv_data.buffer), 1103 { 1104 1104 free_rcvdata(&rcv_data); 1105 1105 CHECK_FCT_DO(fd_core_shutdown(), ); 1106 return ret; 1106 return ret; 1107 1107 } ); 1108 1108 1109 1109 } while (1); 1110 1110 1111 1111 out: 1112 1112 return (ret == 0) ? 0 : ENOTCONN; … … 1117 1117 { 1118 1118 struct cnxctx * conn = arg; 1119 1119 1120 1120 TRACE_ENTRY("%p", arg); 1121 1121 CHECK_PARAMS_DO(conn && (conn->cc_socket > 0), return NULL ); 1122 1122 1123 1123 /* Set the thread name */ 1124 1124 { … … 1127 1127 fd_log_threadname ( buf ); 1128 1128 } 1129 1129 1130 1130 ASSERT( fd_cnx_teststate(conn, CC_STATUS_TLS) ); 1131 1131 ASSERT( fd_cnx_target_queue(conn) ); 1132 1132 1133 /* The next function only returns when there is an error on the socket */ 1133 /* The next function only returns when there is an error on the socket */ 1134 1134 CHECK_FCT_DO(fd_tls_rcvthr_core(conn, conn->cc_tls_para.session), /* continue */); 1135 1135 1136 TRACE_DEBUG(FULL, "Thread terminated"); 1136 TRACE_DEBUG(FULL, "Thread terminated"); 1137 1137 return NULL; 1138 1138 } … … 1152 1152 if (priority) { 1153 1153 const char * errorpos; 1154 CHECK_GNUTLS_DO( gnutls_priority_set_direct( *session, priority, &errorpos ), 1154 CHECK_GNUTLS_DO( gnutls_priority_set_direct( *session, priority, &errorpos ), 1155 1155 { TRACE_DEBUG(INFO, "Error in priority string '%s' at position: '%s'", priority, errorpos); return EINVAL; } ); 1156 1156 } else { … … 1165 1165 gnutls_certificate_server_set_request (*session, GNUTLS_CERT_REQUIRE); 1166 1166 } 1167 1167 1168 1168 return 0; 1169 1169 } … … 1180 1180 gnutls_x509_crt_t cert; 1181 1181 time_t now; 1182 1182 1183 1183 TRACE_ENTRY("%p %d", conn, verbose); 1184 1184 CHECK_PARAMS(conn); 1185 1185 1186 1186 /* Trace the session information -- http://www.gnu.org/software/gnutls/manual/gnutls.html#Obtaining-session-information */ 1187 1187 #ifdef DEBUG … … 1190 1190 gnutls_kx_algorithm_t kx; 1191 1191 gnutls_credentials_type_t cred; 1192 1192 1193 1193 LOG_D("TLS Session information for connection '%s':", conn->cc_id); 1194 1194 … … 1230 1230 } 1231 1231 break; 1232 #ifdef ENABLE_SRP 1232 #ifdef ENABLE_SRP 1233 1233 case GNUTLS_CRD_SRP: 1234 1234 LOG_D("\t - SRP session with username %s", … … 1264 1264 } 1265 1265 #endif /* DEBUG */ 1266 1266 1267 1267 /* First, use built-in verification */ 1268 1268 CHECK_GNUTLS_DO( gnutls_certificate_verify_peers2 (session, >ret), return EINVAL ); … … 1281 1281 return EINVAL; 1282 1282 } 1283 1283 1284 1284 /* Code from http://www.gnu.org/software/gnutls/manual/gnutls.html#Verifying-peer_0027s-certificate */ 1285 1285 if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509) { … … 1287 1287 return EINVAL; 1288 1288 } 1289 1289 1290 1290 GNUTLS_TRACE( cert_list = gnutls_certificate_get_peers (session, &cert_list_size) ); 1291 1291 if (cert_list == NULL) 1292 1292 return EINVAL; 1293 1293 1294 1294 now = time(NULL); 1295 1295 1296 1296 #ifdef DEBUG 1297 1297 char serial[40]; … … 1300 1300 unsigned int algo, bits; 1301 1301 time_t expiration_time, activation_time; 1302 1302 1303 1303 LOG_D("TLS Certificate information for connection '%s' (%d certs provided):", conn->cc_id, cert_list_size); 1304 1304 for (i = 0; i < cert_list_size; i++) … … 1307 1307 CHECK_GNUTLS_DO( gnutls_x509_crt_init (&cert), return EINVAL); 1308 1308 CHECK_GNUTLS_DO( gnutls_x509_crt_import (cert, &cert_list[i], GNUTLS_X509_FMT_DER), return EINVAL); 1309 1309 1310 1310 LOG_A(" Certificate %d info:", i); 1311 1311 … … 1319 1319 size = sizeof (serial); 1320 1320 gnutls_x509_crt_get_serial (cert, serial, &size); 1321 1321 1322 1322 { 1323 1323 int j; … … 1355 1355 { 1356 1356 time_t deadline; 1357 1357 1358 1358 CHECK_GNUTLS_DO( gnutls_x509_crt_init (&cert), return EINVAL); 1359 1359 CHECK_GNUTLS_DO( gnutls_x509_crt_import (cert, &cert_list[i], GNUTLS_X509_FMT_DER), return EINVAL); 1360 1360 1361 1361 GNUTLS_TRACE( deadline = gnutls_x509_crt_get_expiration_time(cert) ); 1362 1362 if ((deadline != (time_t)-1) && (deadline < now)) { … … 1365 1365 ret = EINVAL; 1366 1366 } 1367 1367 1368 1368 GNUTLS_TRACE( deadline = gnutls_x509_crt_get_activation_time(cert) ); 1369 1369 if ((deadline != (time_t)-1) && (deadline > now)) { … … 1372 1372 ret = EINVAL; 1373 1373 } 1374 1374 1375 1375 if ((i == 0) && (conn->cc_tls_para.cn)) { 1376 1376 if (!gnutls_x509_crt_check_hostname (cert, conn->cc_tls_para.cn)) { … … 1380 1380 } 1381 1381 } 1382 1382 1383 1383 GNUTLS_TRACE( gnutls_x509_crt_deinit (cert) ); 1384 1384 } … … 1401 1401 1402 1402 TRACE_ENTRY("%p", session); 1403 1403 1404 1404 /* get the associated connection */ 1405 1405 conn = gnutls_session_get_ptr (session); 1406 1406 1407 1407 /* Trace the session information -- http://www.gnu.org/software/gnutls/manual/gnutls.html#Obtaining-session-information */ 1408 1408 #ifdef DEBUG … … 1415 1415 1416 1416 LOG_A("TLS Session information for connection '%s':", conn->cc_id); 1417 1417 1418 1418 /* print the key exchange's algorithm name 1419 1419 */ … … 1475 1475 else if (kx == GNUTLS_KX_ECDHE_RSA || kx == GNUTLS_KX_ECDHE_ECDSA) 1476 1476 ecdh = 1; 1477 1477 1478 1478 /* Now print some info on the remote certificate */ 1479 1479 if (gnutls_certificate_type_get (session) == GNUTLS_CRT_X509) { … … 1505 1505 gnutls_free (cinfo.data); 1506 1506 } 1507 1507 1508 1508 if (conn->cc_tls_para.cn) { 1509 1509 if (!gnutls_x509_crt_check_hostname (cert, conn->cc_tls_para.cn)) { … … 1513 1513 return GNUTLS_E_CERTIFICATE_ERROR; 1514 1514 } 1515 1515 1516 1516 } 1517 1517 … … 1536 1536 gnutls_dh_get_prime_bits (session)); 1537 1537 1538 /* print the protocol's name (ie TLS 1.0) 1538 /* print the protocol's name (ie TLS 1.0) 1539 1539 */ 1540 1540 tmp = gnutls_protocol_get_name (gnutls_protocol_get_version (session)); … … 1558 1558 tmp = gnutls_mac_get_name (gnutls_mac_get (session)); 1559 1559 LOG_D("\t - MAC: %s", tmp); 1560 1561 #endif /* DEBUG */ 1560 1561 #endif /* DEBUG */ 1562 1562 1563 1563 /* This verification function uses the trusted CAs in the credentials … … 1578 1578 if (status & GNUTLS_CERT_NOT_ACTIVATED) 1579 1579 LOG_E(" - The certificate is not yet activated."); 1580 } 1580 } 1581 1581 if (status & GNUTLS_CERT_INVALID) 1582 1582 { 1583 1583 return GNUTLS_E_CERTIFICATE_ERROR; 1584 1584 } 1585 1585 1586 1586 /* Up to here the process is the same for X.509 certificates and 1587 1587 * OpenPGP keys. From now on X.509 certificates are assumed. This can … … 1635 1635 { 1636 1636 int dtls = 0; 1637 1637 1638 1638 TRACE_ENTRY( "%p %d %d %p %p", conn, mode, algo, priority, alt_creds); 1639 1639 CHECK_PARAMS( conn && (!fd_cnx_teststate(conn, CC_STATUS_TLS)) && ( (mode == GNUTLS_CLIENT) || (mode == GNUTLS_SERVER) ) && (!conn->cc_loop) ); … … 1642 1642 conn->cc_tls_para.mode = mode; 1643 1643 conn->cc_tls_para.algo = algo; 1644 1644 1645 1645 /* Cancel receiving thread if any -- it should already be terminated anyway, we just release the resources */ 1646 1646 CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */); 1647 1647 1648 1648 /* Once TLS handshake is done, we don't stop after the first message */ 1649 1649 conn->cc_loop = 1; 1650 1650 1651 1651 dtls = fd_cnx_may_dtls(conn); 1652 1652 1653 1653 /* Prepare the master session credentials and priority */ 1654 1654 CHECK_FCT( fd_tls_prepare(&conn->cc_tls_para.session, mode, dtls, priority, alt_creds) ); … … 1683 1683 } 1684 1684 } 1685 1685 1686 1686 /* additional initialization for gnutls 3.x */ 1687 1687 #ifdef GNUTLS_VERSION_300 1688 1688 /* the verify function has already been set in the global initialization in config.c */ 1689 1689 1690 1690 /* fd_tls_verify_credentials_2 uses the connection */ 1691 1691 gnutls_session_set_ptr (conn->cc_tls_para.session, (void *) conn); 1692 1692 1693 1693 if ((conn->cc_tls_para.cn != NULL) && (mode == GNUTLS_CLIENT)) { 1694 1694 /* this might allow virtual hosting on the remote peer */ 1695 1695 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 */); 1696 1696 } 1697 1697 1698 1698 #endif /* GNUTLS_VERSION_300 */ 1699 1699 … … 1701 1701 GNUTLS_TRACE( gnutls_handshake_set_timeout( conn->cc_tls_para.session, GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT)); 1702 1702 #endif /* GNUTLS_VERSION_310 */ 1703 1703 1704 1704 /* Mark the connection as protected from here, so that the gnutls credentials will be freed */ 1705 1705 fd_cnx_addstate(conn, CC_STATUS_TLS); 1706 1706 1707 1707 /* Handshake master session */ 1708 1708 { 1709 1709 int ret; 1710 1710 1711 1711 CHECK_GNUTLS_DO( ret = gnutls_handshake(conn->cc_tls_para.session), 1712 1712 { … … 1720 1720 #ifndef GNUTLS_VERSION_300 1721 1721 /* Now verify the remote credentials are valid -- only simple tests here */ 1722 CHECK_FCT_DO( fd_tls_verify_credentials(conn->cc_tls_para.session, conn, 1), 1723 { 1722 CHECK_FCT_DO( fd_tls_verify_credentials(conn->cc_tls_para.session, conn, 1), 1723 { 1724 1724 CHECK_GNUTLS_DO( gnutls_bye(conn->cc_tls_para.session, GNUTLS_SHUT_RDWR), ); 1725 1725 fd_cnx_markerror(conn); … … 1728 1728 #endif /* GNUTLS_VERSION_300 */ 1729 1729 } 1730 1730 1731 1731 /* Multi-stream TLS: handshake other streams as well */ 1732 1732 if ((!dtls) && (conn->cc_sctp_para.pairs > 1)) { … … 1751 1751 } 1752 1752 } 1753 1753 1754 1754 return 0; 1755 1755 } … … 1760 1760 TRACE_ENTRY("%p %p %p", conn, cert_list, cert_list_size); 1761 1761 CHECK_PARAMS( conn && fd_cnx_teststate(conn, CC_STATUS_TLS) && cert_list && cert_list_size ); 1762 1762 1763 1763 /* This function only works for X.509 certificates. */ 1764 1764 CHECK_PARAMS( gnutls_certificate_type_get (conn->cc_tls_para.session) == GNUTLS_CRT_X509 ); 1765 1765 1766 1766 GNUTLS_TRACE( *cert_list = gnutls_certificate_get_peers (conn->cc_tls_para.session, cert_list_size) ); 1767 1767 if (*cert_list == NULL) { … … 1771 1771 1772 1772 TRACE_DEBUG( FULL, "Saved certificate chain (%d certificates) in peer structure.", *cert_list_size); 1773 1773 1774 1774 return 0; 1775 1775 } … … 1782 1782 size_t ev_sz; 1783 1783 void * ev_data; 1784 1784 1785 1785 TRACE_ENTRY("%p %p %p %p", conn, timeout, buf, len); 1786 1786 CHECK_PARAMS(conn && (conn->cc_socket > 0) && buf && len); … … 1795 1795 CHECK_FCT( fd_event_get(conn->cc_incoming, &ev, &ev_sz, &ev_data) ); 1796 1796 } 1797 1797 1798 1798 switch (ev) { 1799 1799 case FDEVP_CNX_MSG_RECV: … … 1802 1802 *buf = ev_data; 1803 1803 return 0; 1804 1804 1805 1805 case FDEVP_PSM_TIMEOUT: 1806 1806 TRACE_DEBUG(FULL, "Timeout event received"); 1807 1807 return ETIMEDOUT; 1808 1808 1809 1809 case FDEVP_CNX_EP_CHANGE: 1810 1810 /* We ignore this event */ 1811 1811 goto get_next; 1812 1812 1813 1813 case FDEVP_CNX_ERROR: 1814 1814 TRACE_DEBUG(FULL, "Received ERROR event on the connection"); 1815 1815 return ENOTCONN; 1816 1816 } 1817 1817 1818 1818 TRACE_DEBUG(INFO, "Received unexpected event %d (%s)", ev, fd_pev_str(ev)); 1819 1819 return EINVAL; … … 1836 1836 TRACE_ENTRY( "%p %p", conn, alt_fifo ); 1837 1837 CHECK_PARAMS( conn && alt_fifo && conn->cc_incoming ); 1838 1838 1839 1839 /* The magic function does it all */ 1840 1840 CHECK_POSIX_DO( pthread_mutex_lock(&state_lock), { ASSERT(0); } ); 1841 1841 CHECK_FCT_DO( ret = fd_fifo_move( conn->cc_incoming, alt_fifo, &conn->cc_alt ), ); 1842 1842 CHECK_POSIX_DO( pthread_mutex_unlock(&state_lock), { ASSERT(0); } ); 1843 1843 1844 1844 return ret; 1845 1845 } … … 1862 1862 if (ret <= 0) 1863 1863 return ENOTCONN; 1864 1864 1865 1865 sent += ret; 1866 1866 } while ( sent < len ); … … 1872 1872 { 1873 1873 TRACE_ENTRY("%p %p %zd", conn, buf, len); 1874 1874 1875 1875 CHECK_PARAMS(conn && (conn->cc_socket > 0) && (! fd_cnx_teststate(conn, CC_STATUS_ERROR)) && buf && len); 1876 1876 1877 1877 TRACE_DEBUG(FULL, "Sending %zdb %sdata on connection %s", len, fd_cnx_teststate(conn, CC_STATUS_TLS) ? "TLS-protected ":"", conn->cc_id); 1878 1878 1879 1879 switch (conn->cc_proto) { 1880 1880 case IPPROTO_TCP: 1881 1881 CHECK_FCT( send_simple(conn, buf, len) ); 1882 1882 break; 1883 1883 1884 1884 #ifndef DISABLE_SCTP 1885 1885 case IPPROTO_SCTP: { … … 1893 1893 else 1894 1894 limit = conn->cc_sctp_para.str_out; 1895 1895 1896 1896 if (limit > 1) { 1897 1897 conn->cc_sctp_para.next += 1; … … 1900 1900 } 1901 1901 } 1902 1902 1903 1903 if (stream == 0) { 1904 1904 /* We can use default function, it sends over stream #0 */ … … 1909 1909 iov.iov_base = buf; 1910 1910 iov.iov_len = len; 1911 1911 1912 1912 CHECK_SYS_DO( fd_sctp_sendstrv(conn, stream, &iov, 1), { fd_cnx_markerror(conn); return ENOTCONN; } ); 1913 1913 } else { … … 1933 1933 break; 1934 1934 #endif /* DISABLE_SCTP */ 1935 1935 1936 1936 default: 1937 1937 TRACE_DEBUG(INFO, "Unknown protocol: %d", conn->cc_proto); … … 1939 1939 return ENOTSUP; /* or EINVAL... */ 1940 1940 } 1941 1941 1942 1942 return 0; 1943 1943 } … … 1952 1952 { 1953 1953 TRACE_ENTRY("%p", conn); 1954 1954 1955 1955 CHECK_PARAMS_DO(conn, return); 1956 1956 1957 1957 fd_cnx_addstate(conn, CC_STATUS_CLOSING); 1958 1958 1959 1959 /* Initiate shutdown of the TLS session(s): call gnutls_bye(WR), then read until error */ 1960 1960 if (fd_cnx_teststate(conn, CC_STATUS_TLS)) { … … 1986 1986 conn->cc_tls_para.session = NULL; 1987 1987 } 1988 1988 1989 1989 /* Destroy the wrapper (also stops the demux thread) */ 1990 1990 fd_sctp3436_destroy(conn); … … 2008 2008 CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */ ); 2009 2009 } 2010 2010 2011 2011 /* Free the resources of the TLS session */ 2012 2012 if (conn->cc_tls_para.session) { … … 2018 2018 #endif /* DISABLE_SCTP */ 2019 2019 } 2020 2020 2021 2021 /* Terminate the thread in case it is not done yet -- is there any such case left ?*/ 2022 2022 CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */ ); 2023 2023 2024 2024 /* Shut the connection down */ 2025 2025 if (conn->cc_socket > 0) { … … 2028 2028 conn->cc_socket = -1; 2029 2029 } 2030 2030 2031 2031 /* Empty and destroy FIFO list */ 2032 2032 if (conn->cc_incoming) { 2033 2033 fd_event_destroy( &conn->cc_incoming, free ); 2034 2034 } 2035 2035 2036 2036 /* Free the object */ 2037 2037 free(conn); 2038 2038 2039 2039 /* Done! */ 2040 2040 return;
Note: See TracChangeset
for help on using the changeset viewer.