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, &gtret), return EINVAL ); 1193 CHECK_GNUTLS_DO( gnutls_certificate_verify_peers2 (session, &gtret), 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
"Welcome to our mercurial repository"