Mercurial > hg > freeDiameter
diff tests/testcnx.c @ 1181:22de21feec64
Preparing for DTLS support
author | Sebastien Decugis <sdecugis@freediameter.net> |
---|---|
date | Wed, 05 Jun 2013 19:22:26 +0800 |
parents | 1af09cc156d6 |
children | 56c36d1007b4 |
line wrap: on
line diff
--- a/tests/testcnx.c Wed Jun 05 15:02:29 2013 +0800 +++ b/tests/testcnx.c Wed Jun 05 19:22:26 2013 +0800 @@ -548,6 +548,7 @@ struct handshake_flags { struct cnxctx * cnx; gnutls_certificate_credentials_t creds; + int algo; int ret; }; @@ -556,7 +557,7 @@ { struct handshake_flags * hf = arg; fd_log_threadname ( "testcnx:handshake" ); - hf->ret = fd_cnx_handshake(hf->cnx, GNUTLS_CLIENT, NULL, hf->creds); + hf->ret = fd_cnx_handshake(hf->cnx, GNUTLS_CLIENT, hf->algo, NULL, hf->creds); return NULL; } @@ -863,7 +864,7 @@ /* At this point in legacy Diameter we start the handshake */ CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) ); - CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, NULL, NULL) ); + CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_DEFAULT /* No impact on TCP */, NULL, NULL) ); CHECK( 0, pthread_join(thr, NULL) ); CHECK( 0, hf.ret ); @@ -904,6 +905,7 @@ cf.proto = IPPROTO_SCTP; memset(&hf, 0, sizeof(hf)); + hf.algo = ALGO_HANDSHAKE_3436; /* this is mandatory for old TLS mechanism */ /* Initialize remote certificate */ CHECK_GNUTLS_DO( ret = gnutls_certificate_allocate_credentials (&hf.creds), ); @@ -948,7 +950,7 @@ /* At this point in legacy Diameter we start the handshake */ CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) ); - CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, NULL, NULL) ); + CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_3436, NULL, NULL) ); CHECK( 0, pthread_join(thr, NULL) ); CHECK( 0, hf.ret ); @@ -1014,7 +1016,7 @@ /* Start the handshake directly */ CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) ); - CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, NULL, NULL) ); + CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_DEFAULT, NULL, NULL) ); CHECK( 0, pthread_join(thr, NULL) ); CHECK( 0, hf.ret ); @@ -1045,7 +1047,11 @@ } #ifndef DISABLE_SCTP - /* SCTP Client / server emulating new Diameter behavior (handshake at connection directly) */ + + + /* SCTP Client / server emulating new Diameter behavior (DTLS handshake at connection directly) */ + TODO("Enabled after DTLS implementation"); + if (0) { struct connect_flags cf; struct handshake_flags hf; @@ -1079,7 +1085,73 @@ /* Start the handshake directly */ CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) ); - CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, NULL, NULL) ); + CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_DEFAULT, NULL, NULL) ); + CHECK( 0, pthread_join(thr, NULL) ); + CHECK( 0, hf.ret ); + + /* Send a few TLS protected messages, and replies */ + for (i = 0; i < 2 * NB_STREAMS; i++) { + CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz)); + CHECK( cer_sz, rcv_sz ); + CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); + free(rcv_buf); + + CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz)); + CHECK( cer_sz, rcv_sz ); + CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); + free(rcv_buf); + } + + + /* Now close the connection */ + CHECK( 0, pthread_create(&thr, NULL, destroy_thr, client_side) ); + fd_cnx_destroy(server_side); + CHECK( 0, pthread_join(thr, NULL) ); + + /* Free the credentials */ + gnutls_certificate_free_keys(hf.creds); + gnutls_certificate_free_cas(hf.creds); + gnutls_certificate_free_credentials(hf.creds); + } + + /* SCTP Client / server emulating old intermediary Diameter behavior (TLS handshake at connection directly) */ + { + struct connect_flags cf; + struct handshake_flags hf; + + memset(&cf, 0, sizeof(cf)); + cf.proto = IPPROTO_SCTP; + + memset(&hf, 0, sizeof(hf)); + hf.algo = ALGO_HANDSHAKE_3436; /* this is mandatory for old TLS mechanism */ + + /* Initialize remote certificate */ + CHECK_GNUTLS_DO( ret = gnutls_certificate_allocate_credentials (&hf.creds), ); + CHECK( GNUTLS_E_SUCCESS, ret ); + /* Set the CA */ + CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_trust_mem( hf.creds, &ca, GNUTLS_X509_FMT_PEM), ); + CHECK( 1, ret ); + /* Set the key */ + CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_key_mem( hf.creds, &client_cert, &client_priv, GNUTLS_X509_FMT_PEM), ); + CHECK( GNUTLS_E_SUCCESS, ret ); + + /* Start the client thread */ + CHECK( 0, pthread_create(&thr, NULL, connect_thr, &cf) ); + + /* Accept the connection of the client */ + server_side = fd_cnx_serv_accept(listener_sctp); + CHECK( 1, server_side ? 1 : 0 ); + + /* Retrieve the client connection object */ + CHECK( 0, pthread_join( thr, (void *)&client_side ) ); + CHECK( 1, client_side ? 1 : 0 ); + hf.cnx = client_side; + + /* Start the handshake directly */ + CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) ); + CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_3436, NULL, NULL) ); CHECK( 0, pthread_join(thr, NULL) ); CHECK( 0, hf.ret ); @@ -1113,6 +1185,9 @@ /* Test with different number of streams between server and client */ #ifndef DISABLE_SCTP + /* DTLS / SCTP style */ + TODO("Enabled after DTLS implementation"); + if (0) { struct connect_flags cf; struct handshake_flags hf; @@ -1147,7 +1222,7 @@ /* Start the handshake directly */ CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) ); - CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, NULL, NULL) ); + CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_DEFAULT, NULL, NULL) ); CHECK( 0, pthread_join(thr, NULL) ); CHECK( 0, hf.ret ); @@ -1186,7 +1261,7 @@ /* Start the handshake directly */ CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) ); - CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, NULL, NULL) ); + CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_DEFAULT, NULL, NULL) ); CHECK( 0, pthread_join(thr, NULL) ); CHECK( 0, hf.ret ); @@ -1216,6 +1291,113 @@ gnutls_certificate_free_cas(hf.creds); gnutls_certificate_free_credentials(hf.creds); } + + /* TLS / SCTP style */ + { + struct connect_flags cf; + struct handshake_flags hf; + + memset(&cf, 0, sizeof(cf)); + cf.proto = IPPROTO_SCTP; + + memset(&hf, 0, sizeof(hf)); + hf.algo = ALGO_HANDSHAKE_3436; + + /* Initialize remote certificate */ + CHECK_GNUTLS_DO( ret = gnutls_certificate_allocate_credentials (&hf.creds), ); + CHECK( GNUTLS_E_SUCCESS, ret ); + /* Set the CA */ + CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_trust_mem( hf.creds, &ca, GNUTLS_X509_FMT_PEM), ); + CHECK( 1, ret ); + /* Set the key */ + CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_key_mem( hf.creds, &client_cert, &client_priv, GNUTLS_X509_FMT_PEM), ); + CHECK( GNUTLS_E_SUCCESS, ret ); + + /* Start the client thread with more streams than the server */ + fd_g_config->cnf_sctp_str = 2 * NB_STREAMS; + CHECK( 0, pthread_create(&thr, NULL, connect_thr, &cf) ); + + /* Accept the connection of the client */ + server_side = fd_cnx_serv_accept(listener_sctp); + CHECK( 1, server_side ? 1 : 0 ); + + /* Retrieve the client connection object */ + CHECK( 0, pthread_join( thr, (void *)&client_side ) ); + CHECK( 1, client_side ? 1 : 0 ); + hf.cnx = client_side; + + /* Start the handshake directly */ + CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) ); + CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_3436, NULL, NULL) ); + CHECK( 0, pthread_join(thr, NULL) ); + CHECK( 0, hf.ret ); + + /* Send a few TLS protected message, and replies */ + for (i = 0; i < 4 * NB_STREAMS; i++) { + CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz)); + CHECK( cer_sz, rcv_sz ); + CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); + free(rcv_buf); + + CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz)); + CHECK( cer_sz, rcv_sz ); + CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); + free(rcv_buf); + } + + /* Now close the connection */ + CHECK( 0, pthread_create(&thr, NULL, destroy_thr, client_side) ); + fd_cnx_destroy(server_side); + CHECK( 0, pthread_join(thr, NULL) ); + + /* Do the same test but with more streams on the server this time */ + fd_g_config->cnf_sctp_str = NB_STREAMS / 2; + CHECK( 0, pthread_create(&thr, NULL, connect_thr, &cf) ); + + /* Accept the connection of the client */ + server_side = fd_cnx_serv_accept(listener_sctp); + CHECK( 1, server_side ? 1 : 0 ); + + /* Retrieve the client connection object */ + CHECK( 0, pthread_join( thr, (void *)&client_side ) ); + CHECK( 1, client_side ? 1 : 0 ); + hf.cnx = client_side; + + /* Start the handshake directly */ + CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) ); + CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_3436, NULL, NULL) ); + CHECK( 0, pthread_join(thr, NULL) ); + CHECK( 0, hf.ret ); + + /* Send a few TLS protected message, and replies */ + for (i = 0; i < 2 * NB_STREAMS; i++) { + CHECK( 0, fd_cnx_send(server_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_receive(client_side, NULL, &rcv_buf, &rcv_sz)); + CHECK( cer_sz, rcv_sz ); + CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); + free(rcv_buf); + + CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_cnx_receive(server_side, NULL, &rcv_buf, &rcv_sz)); + CHECK( cer_sz, rcv_sz ); + CHECK( 0, memcmp( rcv_buf, cer_buf, cer_sz ) ); + free(rcv_buf); + } + + /* Now close the connection */ + CHECK( 0, pthread_create(&thr, NULL, destroy_thr, client_side) ); + fd_cnx_destroy(server_side); + CHECK( 0, pthread_join(thr, NULL) ); + + + /* Free the credentials */ + gnutls_certificate_free_keys(hf.creds); + gnutls_certificate_free_cas(hf.creds); + gnutls_certificate_free_credentials(hf.creds); + } + #endif /* DISABLE_SCTP */ @@ -1256,7 +1438,7 @@ /* Start the handshake directly */ CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) ); - CHECK( EINVAL, fd_cnx_handshake(server_side, GNUTLS_SERVER, NULL, NULL) ); + CHECK( EINVAL, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_DEFAULT, NULL, NULL) ); fd_cnx_destroy(server_side); CHECK( 0, pthread_join(thr, NULL) ); @@ -1273,6 +1455,9 @@ /* Same in SCTP */ #ifndef DISABLE_SCTP + /* DTLS */ + TODO("Enabled after DTLS implementation"); + if (0) { struct connect_flags cf; struct handshake_flags hf; @@ -1307,7 +1492,57 @@ /* Start the handshake directly */ CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) ); - CHECK( EINVAL, fd_cnx_handshake(server_side, GNUTLS_SERVER, NULL, NULL) ); + CHECK( EINVAL, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_DEFAULT, NULL, NULL) ); + fd_cnx_destroy(server_side); + CHECK( 0, pthread_join(thr, NULL) ); + + /* Now close the connection */ + CHECK( 0, pthread_create(&thr, NULL, destroy_thr, client_side) ); + CHECK( 0, pthread_join(thr, NULL) ); + + /* Free the credentials */ + gnutls_certificate_free_keys(hf.creds); + gnutls_certificate_free_cas(hf.creds); + gnutls_certificate_free_credentials(hf.creds); + } + + /* TLS */ + { + struct connect_flags cf; + struct handshake_flags hf; + + memset(&cf, 0, sizeof(cf)); + cf.proto = IPPROTO_SCTP; + + memset(&hf, 0, sizeof(hf)); + hf.algo = ALGO_HANDSHAKE_3436; + + /* Initialize remote certificate */ + CHECK_GNUTLS_DO( ret = gnutls_certificate_allocate_credentials (&hf.creds), ); + CHECK( GNUTLS_E_SUCCESS, ret ); + /* Set the CA */ + CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_trust_mem( hf.creds, ¬rust_ca, GNUTLS_X509_FMT_PEM), ); + CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_trust_mem( hf.creds, &ca, GNUTLS_X509_FMT_PEM), ); + CHECK( 1, ret ); + /* Set the key */ + CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_key_mem( hf.creds, ¬rust_cert, ¬rust_priv, GNUTLS_X509_FMT_PEM), ); + CHECK( GNUTLS_E_SUCCESS, ret ); + + /* Start the client thread */ + CHECK( 0, pthread_create(&thr, NULL, connect_thr, &cf) ); + + /* Accept the connection of the client */ + server_side = fd_cnx_serv_accept(listener_sctp); + CHECK( 1, server_side ? 1 : 0 ); + + /* Retrieve the client connection object */ + CHECK( 0, pthread_join( thr, (void *)&client_side ) ); + CHECK( 1, client_side ? 1 : 0 ); + hf.cnx = client_side; + + /* Start the handshake directly */ + CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) ); + CHECK( EINVAL, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_3436, NULL, NULL) ); fd_cnx_destroy(server_side); CHECK( 0, pthread_join(thr, NULL) ); @@ -1356,7 +1591,7 @@ /* Start the handshake directly */ CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) ); - CHECK( EINVAL, fd_cnx_handshake(server_side, GNUTLS_SERVER, NULL, NULL) ); + CHECK( EINVAL, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_DEFAULT, NULL, NULL) ); fd_cnx_destroy(server_side); CHECK( 0, pthread_join(thr, NULL) ); @@ -1408,7 +1643,7 @@ /* Start the handshake, check it is successful */ CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) ); - CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, NULL, NULL) ); + CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_DEFAULT, NULL, NULL) ); CHECK( 0, pthread_join(thr, NULL) ); CHECK( 0, hf.ret ); @@ -1434,7 +1669,7 @@ /* Start the handshake, check it is successful */ CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) ); - CHECK( EINVAL, fd_cnx_handshake(server_side, GNUTLS_SERVER, NULL, NULL) ); + CHECK( EINVAL, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_DEFAULT, NULL, NULL) ); fd_cnx_destroy(server_side); CHECK( 0, pthread_join(thr, NULL) ); @@ -1488,7 +1723,7 @@ /* Start the handshake */ CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) ); - CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, NULL, NULL) ); + CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_DEFAULT, NULL, NULL) ); CHECK( 0, pthread_join(thr, NULL) ); CHECK( 0, hf.ret ); @@ -1542,6 +1777,8 @@ #ifndef DISABLE_SCTP /* And re-test with a SCTP connection */ + TODO("Enabled after DTLS implementation"); + if (0) { struct connect_flags cf; struct handshake_flags hf; @@ -1581,7 +1818,100 @@ /* Start the handshake */ CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) ); - CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, NULL, NULL) ); + CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_DEFAULT, NULL, NULL) ); + CHECK( 0, pthread_join(thr, NULL) ); + CHECK( 0, hf.ret ); + + /* Test some simple functions */ + + /* fd_cnx_getid */ + str = fd_cnx_getid(server_side); + CHECK( 1, str ? 1 : 0 ); + CHECK( 1, (str[0] != '\0') ? 1 : 0 ); + + /* fd_cnx_getproto */ + i = fd_cnx_getproto(server_side); + CHECK( IPPROTO_SCTP, i); + + /* fd_cnx_getTLS */ + i = fd_cnx_getTLS(server_side); + CHECK( 1, i ? 1 : 0 ); + + /* fd_cnx_getcred */ + CHECK( 0, fd_cnx_getcred(server_side, &cert_list, &cert_list_size) ); + CHECK( 1, (cert_list_size > 0) ? 1 : 0 ); + /* We could also verify that the cert_list really contains the client_cert and ca certificates */ + + /* fd_cnx_getremoteid */ + str = fd_cnx_getremoteid(server_side); + CHECK( 1, str ? 1 : 0 ); + CHECK( 1, (str[0] != '\0') ? 1 : 0 ); + + /* fd_cnx_recv_setaltfifo */ + CHECK( 0, fd_cnx_send(client_side, cer_buf, cer_sz, 0)); + CHECK( 0, fd_fifo_new(&myfifo, 0) ); + CHECK( 0, fd_cnx_recv_setaltfifo(server_side, myfifo) ); + CHECK( 0, clock_gettime(CLOCK_REALTIME, &now) ); + do { + CHECK( 0, fd_event_timedget(myfifo, &now, ETIMEDOUT, &ev_code, NULL, (void *)&rcv_buf) ); + free(rcv_buf); + } while (ev_code != FDEVP_CNX_MSG_RECV); + + /* Now close the connection */ + CHECK( 0, pthread_create(&thr, NULL, destroy_thr, client_side) ); + fd_cnx_destroy(server_side); + CHECK( 0, pthread_join(thr, NULL) ); + + fd_event_destroy(&myfifo, free); + + /* Free the credentials */ + gnutls_certificate_free_keys(hf.creds); + gnutls_certificate_free_cas(hf.creds); + gnutls_certificate_free_credentials(hf.creds); + } + + /* TLS */ + { + struct connect_flags cf; + struct handshake_flags hf; + char * str; + const gnutls_datum_t *cert_list; + unsigned int cert_list_size; + struct fifo * myfifo = NULL; + struct timespec now; + int ev_code; + + memset(&cf, 0, sizeof(cf)); + cf.proto = IPPROTO_SCTP; + + memset(&hf, 0, sizeof(hf)); + hf.algo = ALGO_HANDSHAKE_3436; + + /* Initialize remote certificate */ + CHECK_GNUTLS_DO( ret = gnutls_certificate_allocate_credentials (&hf.creds), ); + CHECK( GNUTLS_E_SUCCESS, ret ); + /* Set the CA */ + CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_trust_mem( hf.creds, &ca, GNUTLS_X509_FMT_PEM), ); + CHECK( 1, ret ); + /* Set the key */ + CHECK_GNUTLS_DO( ret = gnutls_certificate_set_x509_key_mem( hf.creds, &client_cert, &client_priv, GNUTLS_X509_FMT_PEM), ); + CHECK( GNUTLS_E_SUCCESS, ret ); + + /* Start the client thread */ + CHECK( 0, pthread_create(&thr, NULL, connect_thr, &cf) ); + + /* Accept the connection of the client */ + server_side = fd_cnx_serv_accept(listener_sctp); + CHECK( 1, server_side ? 1 : 0 ); + + /* Retrieve the client connection object */ + CHECK( 0, pthread_join( thr, (void *)&client_side ) ); + CHECK( 1, client_side ? 1 : 0 ); + hf.cnx = client_side; + + /* Start the handshake */ + CHECK( 0, pthread_create(&thr, NULL, handshake_thr, &hf) ); + CHECK( 0, fd_cnx_handshake(server_side, GNUTLS_SERVER, ALGO_HANDSHAKE_3436, NULL, NULL) ); CHECK( 0, pthread_join(thr, NULL) ); CHECK( 0, hf.ret );