Mercurial > hg > freeDiameter-dtls
comparison libfdcore/cnxctx.c @ 1181:22de21feec64
Preparing for DTLS support
author | Sebastien Decugis <sdecugis@freediameter.net> |
---|---|
date | Wed, 05 Jun 2013 19:22:26 +0800 |
parents | 773498f59520 |
children | 56c36d1007b4 |
comparison
equal
deleted
inserted
replaced
1180:773498f59520 | 1181:22de21feec64 |
---|---|
93 } | 93 } |
94 | 94 |
95 return conn; | 95 return conn; |
96 } | 96 } |
97 | 97 |
98 #define CC_ID_HDR "{----} " | |
99 | |
98 /* Create and bind a server socket to the given endpoint and port */ | 100 /* Create and bind a server socket to the given endpoint and port */ |
99 struct cnxctx * fd_cnx_serv_tcp(uint16_t port, int family, struct fd_endpoint * ep) | 101 struct cnxctx * fd_cnx_serv_tcp(uint16_t port, int family, struct fd_endpoint * ep) |
100 { | 102 { |
101 struct cnxctx * cnx = NULL; | 103 struct cnxctx * cnx = NULL; |
102 sSS dummy; | 104 sSS dummy; |
136 char addrbuf[INET6_ADDRSTRLEN]; | 138 char addrbuf[INET6_ADDRSTRLEN]; |
137 int rc; | 139 int rc; |
138 rc = getnameinfo(sa, sSAlen(sa), addrbuf, sizeof(addrbuf), NULL, 0, NI_NUMERICHOST); | 140 rc = getnameinfo(sa, sSAlen(sa), addrbuf, sizeof(addrbuf), NULL, 0, NI_NUMERICHOST); |
139 if (rc) | 141 if (rc) |
140 snprintf(addrbuf, sizeof(addrbuf), "[err:%s]", gai_strerror(rc)); | 142 snprintf(addrbuf, sizeof(addrbuf), "[err:%s]", gai_strerror(rc)); |
141 snprintf(cnx->cc_id, sizeof(cnx->cc_id), "TCP srv [%s]:%hu (%d)", addrbuf, port, cnx->cc_socket); | 143 snprintf(cnx->cc_id, sizeof(cnx->cc_id), CC_ID_HDR "TCP srv [%s]:%hu (%d)", addrbuf, port, cnx->cc_socket); |
142 } | 144 } |
143 | 145 |
144 cnx->cc_proto = IPPROTO_TCP; | 146 cnx->cc_proto = IPPROTO_TCP; |
145 | 147 |
146 return cnx; | 148 return cnx; |
176 | 178 |
177 /* Create the socket */ | 179 /* Create the socket */ |
178 CHECK_FCT_DO( fd_sctp_create_bind_server( &cnx->cc_socket, cnx->cc_family, ep_list, port ), goto error ); | 180 CHECK_FCT_DO( fd_sctp_create_bind_server( &cnx->cc_socket, cnx->cc_family, ep_list, port ), goto error ); |
179 | 181 |
180 /* Generate the name for the connection object */ | 182 /* Generate the name for the connection object */ |
181 snprintf(cnx->cc_id, sizeof(cnx->cc_id), "SCTP srv :%hu (%d)", port, cnx->cc_socket); | 183 snprintf(cnx->cc_id, sizeof(cnx->cc_id), CC_ID_HDR "SCTP srv :%hu (%d)", port, cnx->cc_socket); |
182 | 184 |
183 cnx->cc_proto = IPPROTO_SCTP; | 185 cnx->cc_proto = IPPROTO_SCTP; |
184 | 186 |
185 return cnx; | 187 return cnx; |
186 | 188 |
246 snprintf(addrbuf, sizeof(addrbuf), "[err:%s]", gai_strerror(rc)); | 248 snprintf(addrbuf, sizeof(addrbuf), "[err:%s]", gai_strerror(rc)); |
247 portbuf[0] = '\0'; | 249 portbuf[0] = '\0'; |
248 } | 250 } |
249 | 251 |
250 /* Numeric values for debug... */ | 252 /* Numeric values for debug... */ |
251 snprintf(cli->cc_id, sizeof(cli->cc_id), "%s from [%s]:%s (%d<-%d)", | 253 snprintf(cli->cc_id, sizeof(cli->cc_id), CC_ID_HDR "%s from [%s]:%s (%d<-%d)", |
252 IPPROTO_NAME(cli->cc_proto), addrbuf, portbuf, serv->cc_socket, cli->cc_socket); | 254 IPPROTO_NAME(cli->cc_proto), addrbuf, portbuf, serv->cc_socket, cli->cc_socket); |
253 | 255 |
254 | 256 |
255 /* ...Name for log messages */ | 257 /* ...Name for log messages */ |
256 rc = getnameinfo((sSA *)&ss, ss_len, cli->cc_remid, sizeof(cli->cc_remid), NULL, 0, 0); | 258 rc = getnameinfo((sSA *)&ss, ss_len, cli->cc_remid, sizeof(cli->cc_remid), NULL, 0, 0); |
310 | 312 |
311 /* Generate the names for the object */ | 313 /* Generate the names for the object */ |
312 { | 314 { |
313 int rc; | 315 int rc; |
314 | 316 |
315 snprintf(cnx->cc_id, sizeof(cnx->cc_id), "TCP,#%d->%s", cnx->cc_socket, sa_buf); | 317 snprintf(cnx->cc_id, sizeof(cnx->cc_id), CC_ID_HDR "TCP,#%d->%s", cnx->cc_socket, sa_buf); |
316 | 318 |
317 /* ...Name for log messages */ | 319 /* ...Name for log messages */ |
318 rc = getnameinfo(sa, addrlen, cnx->cc_remid, sizeof(cnx->cc_remid), NULL, 0, 0); | 320 rc = getnameinfo(sa, addrlen, cnx->cc_remid, sizeof(cnx->cc_remid), NULL, 0, 0); |
319 if (rc) | 321 if (rc) |
320 snprintf(cnx->cc_remid, sizeof(cnx->cc_remid), "[err:%s]", gai_strerror(rc)); | 322 snprintf(cnx->cc_remid, sizeof(cnx->cc_remid), "[err:%s]", gai_strerror(rc)); |
373 | 375 |
374 /* Generate the names for the object */ | 376 /* Generate the names for the object */ |
375 { | 377 { |
376 int rc; | 378 int rc; |
377 | 379 |
378 snprintf(cnx->cc_id, sizeof(cnx->cc_id), "SCTP,#%d->%s", cnx->cc_socket, sa_buf); | 380 snprintf(cnx->cc_id, sizeof(cnx->cc_id), CC_ID_HDR "SCTP,#%d->%s", cnx->cc_socket, sa_buf); |
379 | 381 |
380 /* ...Name for log messages */ | 382 /* ...Name for log messages */ |
381 rc = getnameinfo((sSA *)&primary, sSAlen(&primary), cnx->cc_remid, sizeof(cnx->cc_remid), NULL, 0, 0); | 383 rc = getnameinfo((sSA *)&primary, sSAlen(&primary), cnx->cc_remid, sizeof(cnx->cc_remid), NULL, 0, 0); |
382 if (rc) | 384 if (rc) |
383 snprintf(cnx->cc_remid, sizeof(cnx->cc_remid), "[err:%s]", gai_strerror(rc)); | 385 snprintf(cnx->cc_remid, sizeof(cnx->cc_remid), "[err:%s]", gai_strerror(rc)); |
430 CHECK_POSIX_DO( pthread_mutex_lock(&state_lock), { ASSERT(0); } ); | 432 CHECK_POSIX_DO( pthread_mutex_lock(&state_lock), { ASSERT(0); } ); |
431 st = conn->cc_state; | 433 st = conn->cc_state; |
432 CHECK_POSIX_DO( pthread_mutex_unlock(&state_lock), { ASSERT(0); } ); | 434 CHECK_POSIX_DO( pthread_mutex_unlock(&state_lock), { ASSERT(0); } ); |
433 return st & flag; | 435 return st & flag; |
434 } | 436 } |
437 void fd_cnx_update_id(struct cnxctx * conn) { | |
438 if (conn->cc_state & CC_STATUS_CLOSING) | |
439 conn->cc_id[1] = 'C'; | |
440 else | |
441 conn->cc_id[1] = '-'; | |
442 | |
443 if (conn->cc_state & CC_STATUS_ERROR) | |
444 conn->cc_id[2] = 'E'; | |
445 else | |
446 conn->cc_id[2] = '-'; | |
447 | |
448 if (conn->cc_state & CC_STATUS_SIGNALED) | |
449 conn->cc_id[3] = 'S'; | |
450 else | |
451 conn->cc_id[3] = '-'; | |
452 | |
453 if (conn->cc_state & CC_STATUS_TLS) | |
454 conn->cc_id[4] = 'T'; | |
455 else | |
456 conn->cc_id[4] = '-'; | |
457 } | |
435 void fd_cnx_addstate(struct cnxctx * conn, uint32_t orstate) | 458 void fd_cnx_addstate(struct cnxctx * conn, uint32_t orstate) |
436 { | 459 { |
437 CHECK_POSIX_DO( pthread_mutex_lock(&state_lock), { ASSERT(0); } ); | 460 CHECK_POSIX_DO( pthread_mutex_lock(&state_lock), { ASSERT(0); } ); |
438 conn->cc_state |= orstate; | 461 conn->cc_state |= orstate; |
462 fd_cnx_update_id(conn); | |
439 CHECK_POSIX_DO( pthread_mutex_unlock(&state_lock), { ASSERT(0); } ); | 463 CHECK_POSIX_DO( pthread_mutex_unlock(&state_lock), { ASSERT(0); } ); |
440 } | 464 } |
441 void fd_cnx_setstate(struct cnxctx * conn, uint32_t abstate) | 465 void fd_cnx_setstate(struct cnxctx * conn, uint32_t abstate) |
442 { | 466 { |
443 CHECK_POSIX_DO( pthread_mutex_lock(&state_lock), { ASSERT(0); } ); | 467 CHECK_POSIX_DO( pthread_mutex_lock(&state_lock), { ASSERT(0); } ); |
444 conn->cc_state = abstate; | 468 conn->cc_state = abstate; |
469 fd_cnx_update_id(conn); | |
445 CHECK_POSIX_DO( pthread_mutex_unlock(&state_lock), { ASSERT(0); } ); | 470 CHECK_POSIX_DO( pthread_mutex_unlock(&state_lock), { ASSERT(0); } ); |
446 } | 471 } |
447 | 472 |
448 | 473 |
449 /* Return the TLS state of a connection */ | 474 /* Return the TLS state of a connection */ |
656 CHECK_MALLOC_DO( ret = malloc( fd_msg_pmdl_sizewithoverhead(expected_len) ), return NULL ); | 681 CHECK_MALLOC_DO( ret = malloc( fd_msg_pmdl_sizewithoverhead(expected_len) ), return NULL ); |
657 CHECK_FCT_DO( fd_cnx_init_msg_buffer(ret, expected_len, pmdl), {free(ret); return NULL;} ); | 682 CHECK_FCT_DO( fd_cnx_init_msg_buffer(ret, expected_len, pmdl), {free(ret); return NULL;} ); |
658 return ret; | 683 return ret; |
659 } | 684 } |
660 | 685 |
661 #ifndef DISABLE_SCTP | 686 #ifndef DISABLE_SCTP /* WE use this function only in SCTP code */ |
662 static uint8_t * fd_cnx_realloc_msg_buffer(uint8_t * buffer, size_t expected_len, struct fd_msg_pmdl ** pmdl) | 687 static uint8_t * fd_cnx_realloc_msg_buffer(uint8_t * buffer, size_t expected_len, struct fd_msg_pmdl ** pmdl) |
663 { | 688 { |
664 uint8_t * ret = NULL; | 689 uint8_t * ret = NULL; |
665 | 690 |
666 CHECK_MALLOC_DO( ret = realloc( buffer, fd_msg_pmdl_sizewithoverhead(expected_len) ), return NULL ); | 691 CHECK_MALLOC_DO( ret = realloc( buffer, fd_msg_pmdl_sizewithoverhead(expected_len) ), return NULL ); |
850 } | 875 } |
851 | 876 |
852 | 877 |
853 | 878 |
854 | 879 |
855 /* Returns 0 on error, received data size otherwise (always >= 0) */ | 880 /* Returns 0 on error, received data size otherwise (always >= 0). This is not used for DTLS-protected associations. */ |
856 static ssize_t fd_tls_recv_handle_error(struct cnxctx * conn, gnutls_session_t session, void * data, size_t sz) | 881 static ssize_t fd_tls_recv_handle_error(struct cnxctx * conn, gnutls_session_t session, void * data, size_t sz) |
857 { | 882 { |
858 ssize_t ret; | 883 ssize_t ret; |
859 again: | 884 again: |
860 CHECK_GNUTLS_DO( ret = gnutls_record_recv(session, data, sz), | 885 CHECK_GNUTLS_DO( ret = gnutls_record_recv(session, data, sz), |
861 { | 886 { |
862 switch (ret) { | 887 switch (ret) { |
863 case GNUTLS_E_REHANDSHAKE: | 888 case GNUTLS_E_REHANDSHAKE: |
864 if (!fd_cnx_teststate(conn, CC_STATUS_CLOSING)) { | 889 if (!fd_cnx_teststate(conn, CC_STATUS_CLOSING)) { |
865 CHECK_GNUTLS_DO( ret = gnutls_handshake(session), | 890 CHECK_GNUTLS_DO( ret = gnutls_handshake(session), |
882 /* The connection is closed */ | 907 /* The connection is closed */ |
883 TRACE_DEBUG(FULL, "Got 0 size while reading the socket, probably connection closed..."); | 908 TRACE_DEBUG(FULL, "Got 0 size while reading the socket, probably connection closed..."); |
884 break; | 909 break; |
885 | 910 |
886 default: | 911 default: |
887 TRACE_DEBUG(INFO, "This GNU TLS error is not handled, assume unrecoverable error"); | 912 if (gnutls_error_is_fatal (ret) == 0) { |
913 LOG_N("Ignoring non-fatal GNU TLS error: %s", gnutls_strerror (ret)); | |
914 goto again; | |
915 } | |
916 LOG_E("Fatal GNUTLS error: %s", gnutls_strerror (ret)); | |
888 } | 917 } |
889 } ); | 918 } ); |
890 | 919 |
891 if (ret == 0) | 920 if (ret == 0) |
892 CHECK_GNUTLS_DO( gnutls_bye(session, GNUTLS_SHUT_RDWR), ); | 921 CHECK_GNUTLS_DO( gnutls_bye(session, GNUTLS_SHUT_RDWR), ); |
895 if (ret <= 0) | 924 if (ret <= 0) |
896 fd_cnx_markerror(conn); | 925 fd_cnx_markerror(conn); |
897 return ret; | 926 return ret; |
898 } | 927 } |
899 | 928 |
900 /* Wrapper around gnutls_record_send to handle some error codes */ | 929 /* Wrapper around gnutls_record_send to handle some error codes. This is also used for DTLS-protected associations */ |
901 static ssize_t fd_tls_send_handle_error(struct cnxctx * conn, gnutls_session_t session, void * data, size_t sz) | 930 static ssize_t fd_tls_send_handle_error(struct cnxctx * conn, gnutls_session_t session, void * data, size_t sz) |
902 { | 931 { |
903 ssize_t ret; | 932 ssize_t ret; |
904 again: | 933 again: |
905 CHECK_GNUTLS_DO( ret = gnutls_record_send(session, data, sz), | 934 CHECK_GNUTLS_DO( ret = gnutls_record_send(session, data, sz), |
922 goto again; | 951 goto again; |
923 TRACE_DEBUG(INFO, "Connection is closing, so abord gnutls_record_send now."); | 952 TRACE_DEBUG(INFO, "Connection is closing, so abord gnutls_record_send now."); |
924 break; | 953 break; |
925 | 954 |
926 default: | 955 default: |
927 TRACE_DEBUG(INFO, "This TLS error is not handled, assume unrecoverable error"); | 956 if (gnutls_error_is_fatal (ret) == 0) { |
957 LOG_N("Ignoring non-fatal GNU TLS error: %s", gnutls_strerror (ret)); | |
958 goto again; | |
959 } | |
960 LOG_E("Fatal GNUTLS error: %s", gnutls_strerror (ret)); | |
928 } | 961 } |
929 } ); | 962 } ); |
930 end: | 963 end: |
931 if (ret <= 0) | 964 if (ret <= 0) |
932 fd_cnx_markerror(conn); | 965 fd_cnx_markerror(conn); |
934 return ret; | 967 return ret; |
935 } | 968 } |
936 | 969 |
937 | 970 |
938 /* The function that receives TLS data and re-builds a Diameter message -- it exits only on error or cancelation */ | 971 /* The function that receives TLS data and re-builds a Diameter message -- it exits only on error or cancelation */ |
972 /* For the case of DTLS, since we are not using SCTP_UNORDERED, the messages over a single stream are ordered. | |
973 Furthermore, as long as messages are shorter than the MTU [2^14 = 16384 bytes], they are delivered in a single | |
974 record, as far as I understand. | |
975 For larger messages, however, it is possible that pieces of messages coming from different streams can get interleaved. | |
976 As a result, we do not use the following function for DTLS reception, because we use the sequence number to rebuild the | |
977 messages. */ | |
939 int fd_tls_rcvthr_core(struct cnxctx * conn, gnutls_session_t session) | 978 int fd_tls_rcvthr_core(struct cnxctx * conn, gnutls_session_t session) |
940 { | 979 { |
941 /* No guarantee that GnuTLS preserves the message boundaries, so we re-build it as in TCP */ | 980 /* No guarantee that GnuTLS preserves the message boundaries, so we re-build it as in TCP. */ |
942 do { | 981 do { |
943 uint8_t header[4]; | 982 uint8_t header[4]; |
944 struct fd_cnx_rcvdata rcv_data; | 983 struct fd_cnx_rcvdata rcv_data; |
945 struct fd_msg_pmdl *pmdl=NULL; | 984 struct fd_msg_pmdl *pmdl=NULL; |
946 ssize_t ret = 0; | 985 ssize_t ret = 0; |
1022 TRACE_DEBUG(FULL, "Thread terminated"); | 1061 TRACE_DEBUG(FULL, "Thread terminated"); |
1023 return NULL; | 1062 return NULL; |
1024 } | 1063 } |
1025 | 1064 |
1026 /* Prepare a gnutls session object for handshake */ | 1065 /* Prepare a gnutls session object for handshake */ |
1027 int fd_tls_prepare(gnutls_session_t * session, int mode, char * priority, void * alt_creds) | 1066 int fd_tls_prepare(gnutls_session_t * session, int mode, int dtls, char * priority, void * alt_creds) |
1028 { | 1067 { |
1068 if (dtls) { | |
1069 LOG_E("DTLS sessions not yet supported"); | |
1070 return ENOTSUP; | |
1071 } | |
1072 | |
1029 /* Create the session context */ | 1073 /* Create the session context */ |
1030 CHECK_GNUTLS_DO( gnutls_init (session, mode), return ENOMEM ); | 1074 CHECK_GNUTLS_DO( gnutls_init (session, mode), return ENOMEM ); |
1031 | 1075 |
1032 /* Set the algorithm suite */ | 1076 /* Set the algorithm suite */ |
1033 if (priority) { | 1077 if (priority) { |
1063 | 1107 |
1064 TRACE_ENTRY("%p %d", conn, verbose); | 1108 TRACE_ENTRY("%p %d", conn, verbose); |
1065 CHECK_PARAMS(conn); | 1109 CHECK_PARAMS(conn); |
1066 | 1110 |
1067 /* Trace the session information -- http://www.gnu.org/software/gnutls/manual/gnutls.html#Obtaining-session-information */ | 1111 /* Trace the session information -- http://www.gnu.org/software/gnutls/manual/gnutls.html#Obtaining-session-information */ |
1068 if (verbose && TRACE_BOOL(FULL)) { | 1112 #ifdef DEBUG |
1113 if (verbose) { | |
1069 const char *tmp; | 1114 const char *tmp; |
1070 gnutls_kx_algorithm_t kx; | 1115 gnutls_kx_algorithm_t kx; |
1071 gnutls_credentials_type_t cred; | 1116 gnutls_credentials_type_t cred; |
1072 | 1117 |
1073 fd_log_debug("TLS Session information for connection '%s':", conn->cc_id); | 1118 LOG_A("TLS Session information for connection '%s':", conn->cc_id); |
1074 | 1119 |
1075 /* print the key exchange's algorithm name */ | 1120 /* print the key exchange's algorithm name */ |
1076 GNUTLS_TRACE( kx = gnutls_kx_get (session) ); | 1121 GNUTLS_TRACE( kx = gnutls_kx_get (session) ); |
1077 GNUTLS_TRACE( tmp = gnutls_kx_get_name (kx) ); | 1122 GNUTLS_TRACE( tmp = gnutls_kx_get_name (kx) ); |
1078 fd_log_debug("\t - Key Exchange: %s", tmp); | 1123 LOG_A("\t - Key Exchange: %s", tmp); |
1079 | 1124 |
1080 /* Check the authentication type used and switch | 1125 /* Check the authentication type used and switch |
1081 * to the appropriate. */ | 1126 * to the appropriate. */ |
1082 GNUTLS_TRACE( cred = gnutls_auth_get_type (session) ); | 1127 GNUTLS_TRACE( cred = gnutls_auth_get_type (session) ); |
1083 switch (cred) | 1128 switch (cred) |
1084 { | 1129 { |
1085 case GNUTLS_CRD_IA: | 1130 case GNUTLS_CRD_IA: |
1086 fd_log_debug("\t - TLS/IA session"); | 1131 LOG_A("\t - TLS/IA session"); |
1087 break; | 1132 break; |
1088 | 1133 |
1089 case GNUTLS_CRD_PSK: | 1134 case GNUTLS_CRD_PSK: |
1090 /* This returns NULL in server side. */ | 1135 /* This returns NULL in server side. */ |
1091 if (gnutls_psk_client_get_hint (session) != NULL) | 1136 if (gnutls_psk_client_get_hint (session) != NULL) |
1092 fd_log_debug("\t - PSK authentication. PSK hint '%s'", | 1137 LOG_A("\t - PSK authentication. PSK hint '%s'", |
1093 gnutls_psk_client_get_hint (session)); | 1138 gnutls_psk_client_get_hint (session)); |
1094 /* This returns NULL in client side. */ | 1139 /* This returns NULL in client side. */ |
1095 if (gnutls_psk_server_get_username (session) != NULL) | 1140 if (gnutls_psk_server_get_username (session) != NULL) |
1096 fd_log_debug("\t - PSK authentication. Connected as '%s'", | 1141 LOG_A("\t - PSK authentication. Connected as '%s'", |
1097 gnutls_psk_server_get_username (session)); | 1142 gnutls_psk_server_get_username (session)); |
1098 break; | 1143 break; |
1099 | 1144 |
1100 case GNUTLS_CRD_ANON: /* anonymous authentication */ | 1145 case GNUTLS_CRD_ANON: /* anonymous authentication */ |
1101 fd_log_debug("\t - Anonymous DH using prime of %d bits", | 1146 LOG_A("\t - Anonymous DH using prime of %d bits", |
1102 gnutls_dh_get_prime_bits (session)); | 1147 gnutls_dh_get_prime_bits (session)); |
1103 break; | 1148 break; |
1104 | 1149 |
1105 case GNUTLS_CRD_CERTIFICATE: /* certificate authentication */ | 1150 case GNUTLS_CRD_CERTIFICATE: /* certificate authentication */ |
1106 /* Check if we have been using ephemeral Diffie-Hellman. */ | 1151 /* Check if we have been using ephemeral Diffie-Hellman. */ |
1107 if (kx == GNUTLS_KX_DHE_RSA || kx == GNUTLS_KX_DHE_DSS) { | 1152 if (kx == GNUTLS_KX_DHE_RSA || kx == GNUTLS_KX_DHE_DSS) { |
1108 fd_log_debug("\t - Ephemeral DH using prime of %d bits", | 1153 LOG_A("\t - Ephemeral DH using prime of %d bits", |
1109 gnutls_dh_get_prime_bits (session)); | 1154 gnutls_dh_get_prime_bits (session)); |
1110 } | 1155 } |
1111 break; | 1156 break; |
1112 #ifdef ENABLE_SRP | 1157 #ifdef ENABLE_SRP |
1113 case GNUTLS_CRD_SRP: | 1158 case GNUTLS_CRD_SRP: |
1114 fd_log_debug("\t - SRP session with username %s", | 1159 LOG_A("\t - SRP session with username %s", |
1115 gnutls_srp_server_get_username (session)); | 1160 gnutls_srp_server_get_username (session)); |
1116 break; | 1161 break; |
1117 #endif /* ENABLE_SRP */ | 1162 #endif /* ENABLE_SRP */ |
1118 | 1163 |
1119 default: | 1164 default: |
1122 | 1167 |
1123 } | 1168 } |
1124 | 1169 |
1125 /* print the protocol's name (ie TLS 1.0) */ | 1170 /* print the protocol's name (ie TLS 1.0) */ |
1126 tmp = gnutls_protocol_get_name (gnutls_protocol_get_version (session)); | 1171 tmp = gnutls_protocol_get_name (gnutls_protocol_get_version (session)); |
1127 fd_log_debug("\t - Protocol: %s", tmp); | 1172 LOG_A("\t - Protocol: %s", tmp); |
1128 | 1173 |
1129 /* print the certificate type of the peer. ie X.509 */ | 1174 /* print the certificate type of the peer. ie X.509 */ |
1130 tmp = gnutls_certificate_type_get_name (gnutls_certificate_type_get (session)); | 1175 tmp = gnutls_certificate_type_get_name (gnutls_certificate_type_get (session)); |
1131 fd_log_debug("\t - Certificate Type: %s", tmp); | 1176 LOG_A("\t - Certificate Type: %s", tmp); |
1132 | 1177 |
1133 /* print the compression algorithm (if any) */ | 1178 /* print the compression algorithm (if any) */ |
1134 tmp = gnutls_compression_get_name (gnutls_compression_get (session)); | 1179 tmp = gnutls_compression_get_name (gnutls_compression_get (session)); |
1135 fd_log_debug("\t - Compression: %s", tmp); | 1180 LOG_A("\t - Compression: %s", tmp); |
1136 | 1181 |
1137 /* print the name of the cipher used. ie 3DES. */ | 1182 /* print the name of the cipher used. ie 3DES. */ |
1138 tmp = gnutls_cipher_get_name (gnutls_cipher_get (session)); | 1183 tmp = gnutls_cipher_get_name (gnutls_cipher_get (session)); |
1139 fd_log_debug("\t - Cipher: %s", tmp); | 1184 LOG_A("\t - Cipher: %s", tmp); |
1140 | 1185 |
1141 /* Print the MAC algorithms name. ie SHA1 */ | 1186 /* Print the MAC algorithms name. ie SHA1 */ |
1142 tmp = gnutls_mac_get_name (gnutls_mac_get (session)); | 1187 tmp = gnutls_mac_get_name (gnutls_mac_get (session)); |
1143 fd_log_debug("\t - MAC: %s", tmp); | 1188 LOG_A("\t - MAC: %s", tmp); |
1144 } | 1189 } |
1190 #endif /* DEBUG */ | |
1145 | 1191 |
1146 /* First, use built-in verification */ | 1192 /* First, use built-in verification */ |
1147 CHECK_GNUTLS_DO( gnutls_certificate_verify_peers2 (session, >ret), return EINVAL ); | 1193 CHECK_GNUTLS_DO( gnutls_certificate_verify_peers2 (session, >ret), return EINVAL ); |
1148 if (gtret) { | 1194 if (gtret) { |
1149 if (TRACE_BOOL(INFO)) { | 1195 if (TRACE_BOOL(INFO)) { |
1170 if (cert_list == NULL) | 1216 if (cert_list == NULL) |
1171 return EINVAL; | 1217 return EINVAL; |
1172 | 1218 |
1173 now = time(NULL); | 1219 now = time(NULL); |
1174 | 1220 |
1175 if (verbose && TRACE_BOOL(FULL)) { | 1221 #ifdef DEBUG |
1176 char serial[40]; | 1222 char serial[40]; |
1177 char dn[128]; | 1223 char dn[128]; |
1178 size_t size; | 1224 size_t size; |
1179 unsigned int algo, bits; | 1225 unsigned int algo, bits; |
1180 time_t expiration_time, activation_time; | 1226 time_t expiration_time, activation_time; |
1181 | 1227 |
1182 fd_log_debug("TLS Certificate information for connection '%s' (%d certs provided):", conn->cc_id, cert_list_size); | 1228 LOG_D("TLS Certificate information for connection '%s' (%d certs provided):", conn->cc_id, cert_list_size); |
1183 for (i = 0; i < cert_list_size; i++) | 1229 for (i = 0; i < cert_list_size; i++) |
1184 { | 1230 { |
1185 | 1231 |
1186 CHECK_GNUTLS_DO( gnutls_x509_crt_init (&cert), return EINVAL); | 1232 CHECK_GNUTLS_DO( gnutls_x509_crt_init (&cert), return EINVAL); |
1187 CHECK_GNUTLS_DO( gnutls_x509_crt_import (cert, &cert_list[i], GNUTLS_X509_FMT_DER), return EINVAL); | 1233 CHECK_GNUTLS_DO( gnutls_x509_crt_import (cert, &cert_list[i], GNUTLS_X509_FMT_DER), return EINVAL); |
1188 | 1234 |
1189 fd_log_debug(" Certificate %d info:", i); | 1235 LOG_A(" Certificate %d info:", i); |
1190 | 1236 |
1191 GNUTLS_TRACE( expiration_time = gnutls_x509_crt_get_expiration_time (cert) ); | 1237 GNUTLS_TRACE( expiration_time = gnutls_x509_crt_get_expiration_time (cert) ); |
1192 GNUTLS_TRACE( activation_time = gnutls_x509_crt_get_activation_time (cert) ); | 1238 GNUTLS_TRACE( activation_time = gnutls_x509_crt_get_activation_time (cert) ); |
1193 | 1239 |
1194 fd_log_debug("\t - Certificate is valid since: %s", ctime (&activation_time)); | 1240 LOG( i ? FD_LOG_ANNOYING : FD_LOG_DEBUG, "\t - Certificate is valid since: %.24s", ctime (&activation_time)); |
1195 fd_log_debug("\t - Certificate expires: %s", ctime (&expiration_time)); | 1241 LOG( i ? FD_LOG_ANNOYING : FD_LOG_DEBUG, "\t - Certificate expires: %.24s", ctime (&expiration_time)); |
1196 | 1242 |
1197 /* Print the serial number of the certificate. */ | 1243 /* Print the serial number of the certificate. */ |
1198 size = sizeof (serial); | 1244 size = sizeof (serial); |
1199 gnutls_x509_crt_get_serial (cert, serial, &size); | 1245 gnutls_x509_crt_get_serial (cert, serial, &size); |
1200 | 1246 |
1203 char buf[1024]; | 1249 char buf[1024]; |
1204 snprintf(buf, sizeof(buf), "\t - Certificate serial number: "); | 1250 snprintf(buf, sizeof(buf), "\t - Certificate serial number: "); |
1205 for (j = 0; j < size; j++) { | 1251 for (j = 0; j < size; j++) { |
1206 snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%02hhx", serial[j]); | 1252 snprintf(buf+strlen(buf), sizeof(buf)-strlen(buf), "%02hhx", serial[j]); |
1207 } | 1253 } |
1208 fd_log_debug("%s", buf); | 1254 LOG( i ? FD_LOG_ANNOYING : FD_LOG_DEBUG, "%s", buf); |
1209 } | 1255 } |
1210 | 1256 |
1211 /* Extract some of the public key algorithm's parameters */ | 1257 /* Extract some of the public key algorithm's parameters */ |
1212 GNUTLS_TRACE( algo = gnutls_x509_crt_get_pk_algorithm (cert, &bits) ); | 1258 GNUTLS_TRACE( algo = gnutls_x509_crt_get_pk_algorithm (cert, &bits) ); |
1213 fd_log_debug("\t - Certificate public key: %s", | 1259 LOG( i ? FD_LOG_ANNOYING : FD_LOG_DEBUG, "\t - Certificate public key: %s", |
1214 gnutls_pk_algorithm_get_name (algo)); | 1260 gnutls_pk_algorithm_get_name (algo)); |
1215 | 1261 |
1216 /* Print the version of the X.509 certificate. */ | 1262 /* Print the version of the X.509 certificate. */ |
1217 fd_log_debug("\t - Certificate version: #%d", | 1263 LOG( i ? FD_LOG_ANNOYING : FD_LOG_DEBUG, "\t - Certificate version: #%d", |
1218 gnutls_x509_crt_get_version (cert)); | 1264 gnutls_x509_crt_get_version (cert)); |
1219 | 1265 |
1220 size = sizeof (dn); | 1266 size = sizeof (dn); |
1221 GNUTLS_TRACE( gnutls_x509_crt_get_dn (cert, dn, &size) ); | 1267 GNUTLS_TRACE( gnutls_x509_crt_get_dn (cert, dn, &size) ); |
1222 fd_log_debug("\t - DN: %s", dn); | 1268 LOG( i ? FD_LOG_ANNOYING : FD_LOG_DEBUG, "\t - DN: %s", dn); |
1223 | 1269 |
1224 size = sizeof (dn); | 1270 size = sizeof (dn); |
1225 GNUTLS_TRACE( gnutls_x509_crt_get_issuer_dn (cert, dn, &size) ); | 1271 GNUTLS_TRACE( gnutls_x509_crt_get_issuer_dn (cert, dn, &size) ); |
1226 fd_log_debug("\t - Issuer's DN: %s", dn); | 1272 LOG( i ? FD_LOG_ANNOYING : FD_LOG_DEBUG, "\t - Issuer's DN: %s", dn); |
1227 | 1273 |
1228 GNUTLS_TRACE( gnutls_x509_crt_deinit (cert) ); | 1274 GNUTLS_TRACE( gnutls_x509_crt_deinit (cert) ); |
1229 } | 1275 } |
1230 } | 1276 #endif /* DEBUG */ |
1231 | 1277 |
1232 /* Check validity of all the certificates */ | 1278 /* Check validity of all the certificates */ |
1233 for (i = 0; i < cert_list_size; i++) | 1279 for (i = 0; i < cert_list_size; i++) |
1234 { | 1280 { |
1235 time_t deadline; | 1281 time_t deadline; |
1288 | 1334 |
1289 /* get the associated connection */ | 1335 /* get the associated connection */ |
1290 conn = gnutls_session_get_ptr (session); | 1336 conn = gnutls_session_get_ptr (session); |
1291 | 1337 |
1292 /* Trace the session information -- http://www.gnu.org/software/gnutls/manual/gnutls.html#Obtaining-session-information */ | 1338 /* Trace the session information -- http://www.gnu.org/software/gnutls/manual/gnutls.html#Obtaining-session-information */ |
1293 if (TRACE_BOOL(FULL)) { | 1339 #ifdef DEBUG |
1294 const char *tmp; | 1340 const char *tmp; |
1295 gnutls_credentials_type_t cred; | 1341 gnutls_credentials_type_t cred; |
1296 gnutls_kx_algorithm_t kx; | 1342 gnutls_kx_algorithm_t kx; |
1297 int dhe, ecdh; | 1343 int dhe, ecdh; |
1298 | 1344 |
1299 dhe = ecdh = 0; | 1345 dhe = ecdh = 0; |
1300 | 1346 |
1301 fd_log_debug("TLS Session information for connection '%s':", conn->cc_id); | 1347 LOG_A("TLS Session information for connection '%s':", conn->cc_id); |
1302 | 1348 |
1303 /* print the key exchange's algorithm name | 1349 /* print the key exchange's algorithm name |
1304 */ | 1350 */ |
1305 GNUTLS_TRACE( kx = gnutls_kx_get (session) ); | 1351 GNUTLS_TRACE( kx = gnutls_kx_get (session) ); |
1306 GNUTLS_TRACE( tmp = gnutls_kx_get_name (kx) ); | 1352 GNUTLS_TRACE( tmp = gnutls_kx_get_name (kx) ); |
1307 fd_log_debug("\t- Key Exchange: %s", tmp); | 1353 LOG_A("\t- Key Exchange: %s", tmp); |
1308 | 1354 |
1309 /* Check the authentication type used and switch | 1355 /* Check the authentication type used and switch |
1310 * to the appropriate. | 1356 * to the appropriate. |
1311 */ | 1357 */ |
1312 GNUTLS_TRACE( cred = gnutls_auth_get_type (session) ); | 1358 GNUTLS_TRACE( cred = gnutls_auth_get_type (session) ); |
1313 switch (cred) | 1359 switch (cred) |
1314 { | 1360 { |
1315 case GNUTLS_CRD_IA: | 1361 case GNUTLS_CRD_IA: |
1316 fd_log_debug("\t - TLS/IA session"); | 1362 LOG_A("\t - TLS/IA session"); |
1317 break; | 1363 break; |
1318 | 1364 |
1319 | 1365 |
1320 #ifdef ENABLE_SRP | 1366 #ifdef ENABLE_SRP |
1321 case GNUTLS_CRD_SRP: | 1367 case GNUTLS_CRD_SRP: |
1322 fd_log_debug("\t - SRP session with username %s", | 1368 LOG_A("\t - SRP session with username %s", |
1323 gnutls_srp_server_get_username (session)); | 1369 gnutls_srp_server_get_username (session)); |
1324 break; | 1370 break; |
1325 #endif | 1371 #endif |
1326 | 1372 |
1327 case GNUTLS_CRD_PSK: | 1373 case GNUTLS_CRD_PSK: |
1328 /* This returns NULL in server side. | 1374 /* This returns NULL in server side. |
1329 */ | 1375 */ |
1330 if (gnutls_psk_client_get_hint (session) != NULL) | 1376 if (gnutls_psk_client_get_hint (session) != NULL) |
1331 fd_log_debug("\t - PSK authentication. PSK hint '%s'", | 1377 LOG_A("\t - PSK authentication. PSK hint '%s'", |
1332 gnutls_psk_client_get_hint (session)); | 1378 gnutls_psk_client_get_hint (session)); |
1333 /* This returns NULL in client side. | 1379 /* This returns NULL in client side. |
1334 */ | 1380 */ |
1335 if (gnutls_psk_server_get_username (session) != NULL) | 1381 if (gnutls_psk_server_get_username (session) != NULL) |
1336 fd_log_debug("\t - PSK authentication. Connected as '%s'", | 1382 LOG_A("\t - PSK authentication. Connected as '%s'", |
1337 gnutls_psk_server_get_username (session)); | 1383 gnutls_psk_server_get_username (session)); |
1338 | 1384 |
1339 if (kx == GNUTLS_KX_ECDHE_PSK) | 1385 if (kx == GNUTLS_KX_ECDHE_PSK) |
1340 ecdh = 1; | 1386 ecdh = 1; |
1341 else if (kx == GNUTLS_KX_DHE_PSK) | 1387 else if (kx == GNUTLS_KX_DHE_PSK) |
1342 dhe = 1; | 1388 dhe = 1; |
1343 break; | 1389 break; |
1344 | 1390 |
1345 case GNUTLS_CRD_ANON: /* anonymous authentication */ | 1391 case GNUTLS_CRD_ANON: /* anonymous authentication */ |
1346 fd_log_debug("\t - Anonymous DH using prime of %d bits", | 1392 LOG_A("\t - Anonymous DH using prime of %d bits", |
1347 gnutls_dh_get_prime_bits (session)); | 1393 gnutls_dh_get_prime_bits (session)); |
1348 if (kx == GNUTLS_KX_ANON_ECDH) | 1394 if (kx == GNUTLS_KX_ANON_ECDH) |
1349 ecdh = 1; | 1395 ecdh = 1; |
1350 else if (kx == GNUTLS_KX_ANON_DH) | 1396 else if (kx == GNUTLS_KX_ANON_DH) |
1351 dhe = 1; | 1397 dhe = 1; |
1364 if (gnutls_certificate_type_get (session) == GNUTLS_CRT_X509) { | 1410 if (gnutls_certificate_type_get (session) == GNUTLS_CRT_X509) { |
1365 gnutls_datum_t cinfo; | 1411 gnutls_datum_t cinfo; |
1366 | 1412 |
1367 cert_list = gnutls_certificate_get_peers (session, &cert_list_size); | 1413 cert_list = gnutls_certificate_get_peers (session, &cert_list_size); |
1368 | 1414 |
1369 fd_log_debug("\t Peer provided %d certificates.", cert_list_size); | 1415 LOG_A("\t Peer provided %d certificates.", cert_list_size); |
1370 | 1416 |
1371 if (cert_list_size > 0) | 1417 if (cert_list_size > 0) |
1372 { | 1418 { |
1373 int ret; | 1419 int ret; |
1374 | 1420 |
1376 */ | 1422 */ |
1377 gnutls_x509_crt_init (&cert); | 1423 gnutls_x509_crt_init (&cert); |
1378 | 1424 |
1379 gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER); | 1425 gnutls_x509_crt_import (cert, &cert_list[0], GNUTLS_X509_FMT_DER); |
1380 | 1426 |
1381 fd_log_debug("\t Certificate info:"); | 1427 LOG_A("\t Certificate info:"); |
1382 | 1428 |
1383 /* This is the preferred way of printing short information about | 1429 /* This is the preferred way of printing short information about |
1384 a certificate. */ | 1430 a certificate. */ |
1385 | 1431 |
1386 ret = gnutls_x509_crt_print (cert, GNUTLS_CRT_PRINT_ONELINE, &cinfo); | 1432 ret = gnutls_x509_crt_print (cert, GNUTLS_CRT_PRINT_ONELINE, &cinfo); |
1387 if (ret == 0) | 1433 if (ret == 0) |
1388 { | 1434 { |
1389 fd_log_debug("\t\t%s", cinfo.data); | 1435 LOG_A("\t\t%s", cinfo.data); |
1390 gnutls_free (cinfo.data); | 1436 gnutls_free (cinfo.data); |
1391 } | 1437 } |
1392 | 1438 |
1393 if (conn->cc_tls_para.cn) { | 1439 if (conn->cc_tls_para.cn) { |
1394 if (!gnutls_x509_crt_check_hostname (cert, conn->cc_tls_para.cn)) { | 1440 if (!gnutls_x509_crt_check_hostname (cert, conn->cc_tls_para.cn)) { |
1407 } | 1453 } |
1408 } | 1454 } |
1409 break; | 1455 break; |
1410 | 1456 |
1411 default: | 1457 default: |
1412 fd_log_debug("\t - unknown session type (%d)", cred); | 1458 LOG_A("\t - unknown session type (%d)", cred); |
1413 | 1459 |
1414 } /* switch */ | 1460 } /* switch */ |
1415 | 1461 |
1416 if (ecdh != 0) | 1462 if (ecdh != 0) |
1417 fd_log_debug("\t - Ephemeral ECDH using curve %s", | 1463 LOG_A("\t - Ephemeral ECDH using curve %s", |
1418 gnutls_ecc_curve_get_name (gnutls_ecc_curve_get (session))); | 1464 gnutls_ecc_curve_get_name (gnutls_ecc_curve_get (session))); |
1419 else if (dhe != 0) | 1465 else if (dhe != 0) |
1420 fd_log_debug("\t - Ephemeral DH using prime of %d bits", | 1466 LOG_A("\t - Ephemeral DH using prime of %d bits", |
1421 gnutls_dh_get_prime_bits (session)); | 1467 gnutls_dh_get_prime_bits (session)); |
1422 | 1468 |
1423 /* print the protocol's name (ie TLS 1.0) | 1469 /* print the protocol's name (ie TLS 1.0) |
1424 */ | 1470 */ |
1425 tmp = gnutls_protocol_get_name (gnutls_protocol_get_version (session)); | 1471 tmp = gnutls_protocol_get_name (gnutls_protocol_get_version (session)); |
1426 fd_log_debug("\t - Protocol: %s", tmp); | 1472 LOG_A("\t - Protocol: %s", tmp); |
1427 | 1473 |
1428 /* print the certificate type of the peer. | 1474 /* print the certificate type of the peer. |
1429 * ie X.509 | 1475 * ie X.509 |
1430 */ | 1476 */ |
1431 tmp = gnutls_certificate_type_get_name (gnutls_certificate_type_get (session)); | 1477 tmp = gnutls_certificate_type_get_name (gnutls_certificate_type_get (session)); |
1432 fd_log_debug("\t - Certificate Type: %s", tmp); | 1478 LOG_A("\t - Certificate Type: %s", tmp); |
1433 | 1479 |
1434 /* print the compression algorithm (if any) | 1480 /* print the compression algorithm (if any) |
1435 */ | 1481 */ |
1436 tmp = gnutls_compression_get_name (gnutls_compression_get (session)); | 1482 tmp = gnutls_compression_get_name (gnutls_compression_get (session)); |
1437 fd_log_debug("\t - Compression: %s", tmp); | 1483 LOG_A("\t - Compression: %s", tmp); |
1438 | 1484 |
1439 /* print the name of the cipher used. | 1485 /* print the name of the cipher used. |
1440 * ie 3DES. | 1486 * ie 3DES. |
1441 */ | 1487 */ |
1442 tmp = gnutls_cipher_get_name (gnutls_cipher_get (session)); | 1488 tmp = gnutls_cipher_get_name (gnutls_cipher_get (session)); |
1443 fd_log_debug("\t - Cipher: %s", tmp); | 1489 LOG_A("\t - Cipher: %s", tmp); |
1444 | 1490 |
1445 /* Print the MAC algorithms name. | 1491 /* Print the MAC algorithms name. |
1446 * ie SHA1 | 1492 * ie SHA1 |
1447 */ | 1493 */ |
1448 tmp = gnutls_mac_get_name (gnutls_mac_get (session)); | 1494 tmp = gnutls_mac_get_name (gnutls_mac_get (session)); |
1449 fd_log_debug("\t - MAC: %s", tmp); | 1495 LOG_A("\t - MAC: %s", tmp); |
1450 | 1496 |
1451 } | 1497 #endif /* DEBUG */ |
1452 | 1498 |
1453 /* This verification function uses the trusted CAs in the credentials | 1499 /* This verification function uses the trusted CAs in the credentials |
1454 * structure. So you must have installed one or more CA certificates. | 1500 * structure. So you must have installed one or more CA certificates. |
1455 */ | 1501 */ |
1456 CHECK_GNUTLS_DO( gnutls_certificate_verify_peers2 (session, &status), return GNUTLS_E_CERTIFICATE_ERROR ); | 1502 CHECK_GNUTLS_DO( gnutls_certificate_verify_peers2 (session, &status), return GNUTLS_E_CERTIFICATE_ERROR ); |
1506 return 0; | 1552 return 0; |
1507 } | 1553 } |
1508 | 1554 |
1509 #endif /* GNUTLS_VERSION_300 */ | 1555 #endif /* GNUTLS_VERSION_300 */ |
1510 | 1556 |
1557 static int fd_cnx_may_dtls(struct cnxctx * conn) { | |
1558 #ifndef DISABLE_SCTP | |
1559 if ((conn->cc_proto == IPPROTO_SCTP) && (conn->cc_tls_para.algo == ALGO_HANDSHAKE_DEFAULT)) | |
1560 return 1; | |
1561 #endif /* DISABLE_SCTP */ | |
1562 return 0; | |
1563 } | |
1564 | |
1565 static int fd_cnx_uses_dtls(struct cnxctx * conn) { | |
1566 return fd_cnx_may_dtls(conn) && (fd_cnx_teststate(conn, CC_STATUS_TLS)); | |
1567 } | |
1568 | |
1511 /* TLS handshake a connection; no need to have called start_clear before. Reception is active if handhsake is successful */ | 1569 /* TLS handshake a connection; no need to have called start_clear before. Reception is active if handhsake is successful */ |
1512 int fd_cnx_handshake(struct cnxctx * conn, int mode, char * priority, void * alt_creds) | 1570 int fd_cnx_handshake(struct cnxctx * conn, int mode, int algo, char * priority, void * alt_creds) |
1513 { | 1571 { |
1514 TRACE_ENTRY( "%p %d %p %p", conn, mode, priority, alt_creds); | 1572 int dtls = 0; |
1573 | |
1574 TRACE_ENTRY( "%p %d %d %p %p", conn, mode, algo, priority, alt_creds); | |
1515 CHECK_PARAMS( conn && (!fd_cnx_teststate(conn, CC_STATUS_TLS)) && ( (mode == GNUTLS_CLIENT) || (mode == GNUTLS_SERVER) ) && (!conn->cc_loop) ); | 1575 CHECK_PARAMS( conn && (!fd_cnx_teststate(conn, CC_STATUS_TLS)) && ( (mode == GNUTLS_CLIENT) || (mode == GNUTLS_SERVER) ) && (!conn->cc_loop) ); |
1516 | 1576 |
1517 /* Save the mode */ | 1577 /* Save the mode */ |
1518 conn->cc_tls_para.mode = mode; | 1578 conn->cc_tls_para.mode = mode; |
1579 conn->cc_tls_para.algo = algo; | |
1519 | 1580 |
1520 /* Cancel receiving thread if any -- it should already be terminated anyway, we just release the resources */ | 1581 /* Cancel receiving thread if any -- it should already be terminated anyway, we just release the resources */ |
1521 CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */); | 1582 CHECK_FCT_DO( fd_thr_term(&conn->cc_rcvthr), /* continue */); |
1522 | 1583 |
1523 /* Once TLS handshake is done, we don't stop after the first message */ | 1584 /* Once TLS handshake is done, we don't stop after the first message */ |
1524 conn->cc_loop = 1; | 1585 conn->cc_loop = 1; |
1525 | 1586 |
1587 dtls = fd_cnx_may_dtls(conn); | |
1588 | |
1526 /* Prepare the master session credentials and priority */ | 1589 /* Prepare the master session credentials and priority */ |
1527 CHECK_FCT( fd_tls_prepare(&conn->cc_tls_para.session, mode, priority, alt_creds) ); | 1590 CHECK_FCT( fd_tls_prepare(&conn->cc_tls_para.session, mode, dtls, priority, alt_creds) ); |
1528 | 1591 |
1529 /* Special case: multi-stream TLS is not natively managed in GNU TLS, we use a wrapper library */ | 1592 /* Special case: multi-stream TLS is not natively managed in GNU TLS, we use a wrapper library */ |
1530 if (conn->cc_sctp_para.pairs > 1) { | 1593 if ((!dtls) && (conn->cc_sctp_para.pairs > 1)) { |
1531 #ifdef DISABLE_SCTP | 1594 #ifdef DISABLE_SCTP |
1532 ASSERT(0); | 1595 ASSERT(0); |
1533 CHECK_FCT( ENOTSUP ); | 1596 CHECK_FCT( ENOTSUP ); |
1534 #else /* DISABLE_SCTP */ | 1597 #else /* DISABLE_SCTP */ |
1535 /* Initialize the wrapper, start the demux thread */ | 1598 /* Initialize the wrapper, start the demux thread */ |
1538 } else { | 1601 } else { |
1539 /* Set the transport pointer passed to push & pull callbacks */ | 1602 /* Set the transport pointer passed to push & pull callbacks */ |
1540 GNUTLS_TRACE( gnutls_transport_set_ptr( conn->cc_tls_para.session, (gnutls_transport_ptr_t) conn ) ); | 1603 GNUTLS_TRACE( gnutls_transport_set_ptr( conn->cc_tls_para.session, (gnutls_transport_ptr_t) conn ) ); |
1541 | 1604 |
1542 /* Set the push and pull callbacks */ | 1605 /* Set the push and pull callbacks */ |
1543 GNUTLS_TRACE( gnutls_transport_set_pull_function(conn->cc_tls_para.session, (void *)fd_cnx_s_recv) ); | 1606 if (!dtls) { |
1544 GNUTLS_TRACE( gnutls_transport_set_push_function(conn->cc_tls_para.session, (void *)fd_cnx_s_send) ); | 1607 GNUTLS_TRACE( gnutls_transport_set_pull_function(conn->cc_tls_para.session, (void *)fd_cnx_s_recv) ); |
1608 GNUTLS_TRACE( gnutls_transport_set_push_function(conn->cc_tls_para.session, (void *)fd_cnx_s_send) ); | |
1609 } else { | |
1610 TODO("DTLS push/pull functions"); | |
1611 return ENOTSUP; | |
1612 } | |
1545 } | 1613 } |
1546 | 1614 |
1547 /* additional initialization for gnutls 3.x */ | 1615 /* additional initialization for gnutls 3.x */ |
1548 #ifdef GNUTLS_VERSION_300 | 1616 #ifdef GNUTLS_VERSION_300 |
1549 /* the verify function has already been set in the global initialization in config.c */ | 1617 /* the verify function has already been set in the global initialization in config.c */ |
1586 fd_cnx_markerror(conn); | 1654 fd_cnx_markerror(conn); |
1587 return EINVAL; | 1655 return EINVAL; |
1588 }); | 1656 }); |
1589 #endif /* GNUTLS_VERSION_300 */ | 1657 #endif /* GNUTLS_VERSION_300 */ |
1590 } | 1658 } |
1591 | 1659 |
1592 /* Multi-stream TLS: handshake other streams as well */ | 1660 /* Multi-stream TLS: handshake other streams as well */ |
1593 if (conn->cc_sctp_para.pairs > 1) { | 1661 if ((!dtls) && (conn->cc_sctp_para.pairs > 1)) { |
1594 #ifndef DISABLE_SCTP | 1662 #ifndef DISABLE_SCTP |
1595 /* Start reading the messages from the master session. That way, if the remote peer closed, we are not stuck inside handshake */ | 1663 /* Start reading the messages from the master session. That way, if the remote peer closed, we are not stuck inside handshake */ |
1596 CHECK_FCT(fd_sctp3436_startthreads(conn, 0)); | 1664 CHECK_FCT(fd_sctp3436_startthreads(conn, 0)); |
1597 | 1665 |
1598 /* Resume all additional sessions from the master one. */ | 1666 /* Resume all additional sessions from the master one. */ |
1601 /* Start decrypting the messages from all threads and queuing them in target queue */ | 1669 /* Start decrypting the messages from all threads and queuing them in target queue */ |
1602 CHECK_FCT(fd_sctp3436_startthreads(conn, 1)); | 1670 CHECK_FCT(fd_sctp3436_startthreads(conn, 1)); |
1603 #endif /* DISABLE_SCTP */ | 1671 #endif /* DISABLE_SCTP */ |
1604 } else { | 1672 } else { |
1605 /* Start decrypting the data */ | 1673 /* Start decrypting the data */ |
1606 CHECK_POSIX( pthread_create( &conn->cc_rcvthr, NULL, rcvthr_tls_single, conn ) ); | 1674 if (!dtls) { |
1675 CHECK_POSIX( pthread_create( &conn->cc_rcvthr, NULL, rcvthr_tls_single, conn ) ); | |
1676 } else { | |
1677 TODO("Signal the dtls_push function that multiple streams can be used from this point."); | |
1678 TODO("Create DTLS rcvthr (must reassembly based on seq numbers & stream id ?)"); | |
1679 return ENOTSUP; | |
1680 } | |
1607 } | 1681 } |
1608 | 1682 |
1609 return 0; | 1683 return 0; |
1610 } | 1684 } |
1611 | 1685 |
1734 CHECK_FCT( send_simple(conn, buf, len) ); | 1808 CHECK_FCT( send_simple(conn, buf, len) ); |
1735 break; | 1809 break; |
1736 | 1810 |
1737 #ifndef DISABLE_SCTP | 1811 #ifndef DISABLE_SCTP |
1738 case IPPROTO_SCTP: { | 1812 case IPPROTO_SCTP: { |
1739 if (flags & FD_CNX_ORDERED) { | 1813 int dtls = fd_cnx_uses_dtls(conn); |
1740 /* We send over stream #0 */ | 1814 |
1741 CHECK_FCT( send_simple(conn, buf, len) ); | 1815 if (!dtls) { |
1742 } else { | 1816 if (flags & FD_CNX_ORDERED) { |
1743 /* Default case : no flag specified */ | 1817 /* We send over stream #0 */ |
1744 | |
1745 int another_str = 0; /* do we send over stream #0 ? */ | |
1746 | |
1747 if ((conn->cc_sctp_para.str_out > 1) && ((!fd_cnx_teststate(conn, CC_STATUS_TLS)) || (conn->cc_sctp_para.pairs > 1))) { | |
1748 /* Update the id of the stream we will send this message over */ | |
1749 conn->cc_sctp_para.next += 1; | |
1750 conn->cc_sctp_para.next %= (fd_cnx_teststate(conn, CC_STATUS_TLS) ? conn->cc_sctp_para.pairs : conn->cc_sctp_para.str_out); | |
1751 another_str = (conn->cc_sctp_para.next ? 1 : 0); | |
1752 } | |
1753 | |
1754 if ( ! another_str ) { | |
1755 CHECK_FCT( send_simple(conn, buf, len) ); | 1818 CHECK_FCT( send_simple(conn, buf, len) ); |
1756 } else { | 1819 } else { |
1757 if (!fd_cnx_teststate(conn, CC_STATUS_TLS)) { | 1820 /* Default case : no flag specified */ |
1758 CHECK_FCT_DO( fd_sctp_sendstr(conn, conn->cc_sctp_para.next, buf, len), { fd_cnx_markerror(conn); return ENOTCONN; } ); | 1821 |
1822 int another_str = 0; /* do we send over stream #0 ? */ | |
1823 | |
1824 if ((conn->cc_sctp_para.str_out > 1) && ((!fd_cnx_teststate(conn, CC_STATUS_TLS)) || (conn->cc_sctp_para.pairs > 1))) { | |
1825 /* Update the id of the stream we will send this message over */ | |
1826 conn->cc_sctp_para.next += 1; | |
1827 conn->cc_sctp_para.next %= (fd_cnx_teststate(conn, CC_STATUS_TLS) ? conn->cc_sctp_para.pairs : conn->cc_sctp_para.str_out); | |
1828 another_str = (conn->cc_sctp_para.next ? 1 : 0); | |
1829 } | |
1830 | |
1831 if ( ! another_str ) { | |
1832 CHECK_FCT( send_simple(conn, buf, len) ); | |
1759 } else { | 1833 } else { |
1760 /* push the record to the appropriate session */ | 1834 if (!fd_cnx_teststate(conn, CC_STATUS_TLS)) { |
1761 ssize_t ret; | 1835 CHECK_FCT_DO( fd_sctp_sendstr(conn, conn->cc_sctp_para.next, buf, len), { fd_cnx_markerror(conn); return ENOTCONN; } ); |
1762 size_t sent = 0; | 1836 } else { |
1763 ASSERT(conn->cc_sctp3436_data.array != NULL); | 1837 /* push the record to the appropriate session */ |
1764 do { | 1838 ssize_t ret; |
1765 CHECK_GNUTLS_DO( ret = fd_tls_send_handle_error(conn, conn->cc_sctp3436_data.array[conn->cc_sctp_para.next].session, buf + sent, len - sent), ); | 1839 size_t sent = 0; |
1766 if (ret <= 0) | 1840 ASSERT(conn->cc_sctp3436_data.array != NULL); |
1767 return ENOTCONN; | 1841 do { |
1768 | 1842 CHECK_GNUTLS_DO( ret = fd_tls_send_handle_error(conn, conn->cc_sctp3436_data.array[conn->cc_sctp_para.next].session, buf + sent, len - sent), ); |
1769 sent += ret; | 1843 if (ret <= 0) |
1770 } while ( sent < len ); | 1844 return ENOTCONN; |
1845 | |
1846 sent += ret; | |
1847 } while ( sent < len ); | |
1848 } | |
1771 } | 1849 } |
1772 } | 1850 } |
1851 } else { | |
1852 /* DTLS */ | |
1853 /* We signal the push function directly to tell if using stream 0 or round-robin */ | |
1854 TODO("DTLS send"); | |
1855 return ENOTSUP; | |
1773 } | 1856 } |
1774 } | 1857 } |
1775 break; | 1858 break; |
1776 #endif /* DISABLE_SCTP */ | 1859 #endif /* DISABLE_SCTP */ |
1777 | 1860 |
1799 fd_cnx_addstate(conn, CC_STATUS_CLOSING); | 1882 fd_cnx_addstate(conn, CC_STATUS_CLOSING); |
1800 | 1883 |
1801 /* Initiate shutdown of the TLS session(s): call gnutls_bye(WR), then read until error */ | 1884 /* Initiate shutdown of the TLS session(s): call gnutls_bye(WR), then read until error */ |
1802 if (fd_cnx_teststate(conn, CC_STATUS_TLS)) { | 1885 if (fd_cnx_teststate(conn, CC_STATUS_TLS)) { |
1803 #ifndef DISABLE_SCTP | 1886 #ifndef DISABLE_SCTP |
1804 if (conn->cc_sctp_para.pairs > 1) { | 1887 int dtls = fd_cnx_uses_dtls(conn); |
1888 if ((!dtls) && (conn->cc_sctp_para.pairs > 1)) { | |
1805 if (! fd_cnx_teststate(conn, CC_STATUS_ERROR )) { | 1889 if (! fd_cnx_teststate(conn, CC_STATUS_ERROR )) { |
1806 /* Bye on master session */ | 1890 /* Bye on master session */ |
1807 CHECK_GNUTLS_DO( gnutls_bye(conn->cc_tls_para.session, GNUTLS_SHUT_WR), fd_cnx_markerror(conn) ); | 1891 CHECK_GNUTLS_DO( gnutls_bye(conn->cc_tls_para.session, GNUTLS_SHUT_WR), fd_cnx_markerror(conn) ); |
1808 } | 1892 } |
1809 | 1893 |