diff options
-rw-r--r-- | tests/Makefile.am | 2 | ||||
-rwxr-xr-x | tests/fastopen.sh | 13 | ||||
-rw-r--r-- | tests/psk-file.c | 144 | ||||
-rw-r--r-- | tests/pskself.c | 36 | ||||
-rw-r--r-- | tests/tls13/no-psk-exts.c | 258 |
5 files changed, 411 insertions, 42 deletions
diff --git a/tests/Makefile.am b/tests/Makefile.am index 2f66ed5fc7..2536d3b8f1 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -122,6 +122,8 @@ ctests += tls13/change_cipher_spec ctests += tls13-cipher-neg +ctests += tls13/no-psk-exts + ctests += mini-record-2 simple gnutls_hmac_fast set_pkcs12_cred cert certuniqueid tls-neg-ext-key \ mpi certificate_set_x509_crl dn parse_ca x509-dn x509-dn-decode record-sizes \ hostname-check cve-2008-4989 pkcs12_s2k chainverify record-sizes-range \ diff --git a/tests/fastopen.sh b/tests/fastopen.sh index 5d58b35028..87f3b24bba 100755 --- a/tests/fastopen.sh +++ b/tests/fastopen.sh @@ -48,13 +48,20 @@ SERV="${SERV} -q" echo "Checking Fast open" +KEY1=${srcdir}/../doc/credentials/x509/key-rsa.pem +CERT1=${srcdir}/../doc/credentials/x509/cert-rsa.pem +CA1=${srcdir}/../doc/credentials/x509/ca.pem + eval "${GETPORT}" -launch_server $$ --echo --priority "NORMAL:+ANON-ECDH" +launch_server $$ --echo --x509keyfile ${KEY1} --x509certfile ${CERT1} PID=$! wait_server ${PID} -${VALGRIND} "${CLI}" -p "${PORT}" 127.0.0.1 --fastopen --rehandshake --priority "NORMAL:+ANON-ECDH:+ANON-DH" </dev/null >/dev/null || \ - fail ${PID} "1. rehandshake should have succeeded!" +${VALGRIND} "${CLI}" -p "${PORT}" localhost --fastopen --priority "NORMAL:-VERS-ALL:+VERS-TLS1.2" --x509cafile ${CA1} </dev/null || \ + fail ${PID} "1. TLS1.2 handshake should have succeeded!" + +${VALGRIND} "${CLI}" -p "${PORT}" localhost --fastopen --x509cafile ${CA1} </dev/null || \ + fail ${PID} "2. handshake should have succeeded!" kill ${PID} diff --git a/tests/psk-file.c b/tests/psk-file.c index ee6f8c533e..59f6f2d4a2 100644 --- a/tests/psk-file.c +++ b/tests/psk-file.c @@ -65,14 +65,13 @@ static void tls_log_func(int level, const char *str) #define MAX_BUF 1024 #define MSG "Hello TLS" -static void client(int sd, const char *prio, const char *user, unsigned expect_fail) +static void client(int sd, const char *prio, const char *user, const gnutls_datum_t *key, + unsigned expect_hint, int expect_fail, int exp_kx) { - int ret, ii; + int ret, ii, kx; gnutls_session_t session; char buffer[MAX_BUF + 1]; gnutls_psk_client_credentials_t pskcred; - /* Need to enable anonymous KX specifically. */ - const gnutls_datum_t key = { (void *) "9e32cf7786321a828ef7668f09fb35db", 32 }; const char *hint; global_init(); @@ -83,7 +82,7 @@ static void client(int sd, const char *prio, const char *user, unsigned expect_f side = "client"; gnutls_psk_allocate_client_credentials(&pskcred); - gnutls_psk_set_client_credentials(pskcred, user, &key, + gnutls_psk_set_client_credentials(pskcred, user, key, GNUTLS_PSK_KEY_HEX); /* Initialize TLS session @@ -106,7 +105,10 @@ static void client(int sd, const char *prio, const char *user, unsigned expect_f if (ret < 0) { if (!expect_fail) fail("client: Handshake failed\n"); - gnutls_perror(ret); + if (ret != expect_fail) { + fail("expected cli error %d (%s), got %d (%s)\n", expect_fail, gnutls_strerror(expect_fail), + ret, gnutls_strerror(ret)); + } goto end; } else { if (debug) @@ -114,10 +116,12 @@ static void client(int sd, const char *prio, const char *user, unsigned expect_f } /* check the hint */ - hint = gnutls_psk_client_get_hint(session); - if (hint == NULL || strcmp(hint, "hint") != 0) { - fail("client: hint is not the expected: %s\n", gnutls_psk_client_get_hint(session)); - goto end; + if (expect_hint) { + hint = gnutls_psk_client_get_hint(session); + if (hint == NULL || strcmp(hint, "hint") != 0) { + fail("client: hint is not the expected: %s\n", gnutls_psk_client_get_hint(session)); + goto end; + } } gnutls_record_send(session, MSG, strlen(MSG)); @@ -133,6 +137,8 @@ static void client(int sd, const char *prio, const char *user, unsigned expect_f goto end; } + kx = gnutls_kx_get(session); + if (debug) { printf("- Received %d bytes: ", ret); for (ii = 0; ii < ret; ii++) { @@ -143,6 +149,15 @@ static void client(int sd, const char *prio, const char *user, unsigned expect_f gnutls_bye(session, GNUTLS_SHUT_RDWR); + if (expect_fail) + fail("client: expected failure but connection succeeded!\n"); + + if (exp_kx && kx != exp_kx) { + fail("client: expected key exchange %s, but got %s\n", + gnutls_kx_get_name(exp_kx), + gnutls_kx_get_name(kx)); + } + end: close(sd); @@ -159,13 +174,14 @@ static void client(int sd, const char *prio, const char *user, unsigned expect_f #define MAX_BUF 1024 -static void server(int sd, const char *prio, const char *user, unsigned expect_fail) +static void server(int sd, const char *prio, const char *user, int expect_fail, int exp_kx) { gnutls_psk_server_credentials_t server_pskcred; - int ret; + int ret, kx; gnutls_session_t session; char buffer[MAX_BUF + 1]; char *psk_file = getenv("PSK_FILE"); + char *desc; /* this must be called once in the program */ @@ -197,17 +213,22 @@ static void server(int sd, const char *prio, const char *user, unsigned expect_f gnutls_transport_set_int(session, sd); ret = gnutls_handshake(session); if (ret < 0) { - close(sd); - gnutls_deinit(session); - gnutls_psk_free_server_credentials(server_pskcred); + gnutls_alert_send_appropriate(session, ret); if (expect_fail) { - success("server: Handshake has failed - expected (%s)\n\n", - gnutls_strerror(ret)); + if (ret != expect_fail) { + fail("expected error %d (%s), got %d (%s)\n", expect_fail, + gnutls_strerror(expect_fail), + ret, gnutls_strerror(ret)); + } + + if (debug) + success("server: Handshake has failed - expected (%s)\n\n", + gnutls_strerror(ret)); } else { fail("server: Handshake has failed (%s)\n\n", gnutls_strerror(ret)); } - return; + goto end; } if (debug) success("server: Handshake was completed\n"); @@ -235,10 +256,26 @@ static void server(int sd, const char *prio, const char *user, unsigned expect_f strlen(buffer)); } } + + kx = gnutls_kx_get(session); + + desc = gnutls_session_get_desc(session); + success(" - connected with: %s\n", desc); + gnutls_free(desc); /* do not wait for the peer to close the connection. */ gnutls_bye(session, GNUTLS_SHUT_WR); + if (expect_fail) + fail("server: expected failure but connection succeeded!\n"); + + if (exp_kx && kx != exp_kx) { + fail("server: expected key exchange %s, but got %s\n", + gnutls_kx_get_name(exp_kx), + gnutls_kx_get_name(kx)); + } + + end: close(sd); gnutls_deinit(session); @@ -251,13 +288,18 @@ static void server(int sd, const char *prio, const char *user, unsigned expect_f } static -void run_test(const char *prio, const char *user, unsigned expect_fail) +void run_test2(const char *prio, const char *sprio, const char *user, const gnutls_datum_t *key, + unsigned expect_hint, int exp_kx, int expect_fail_cli, int expect_fail_serv) { pid_t child; int err; int sockets[2]; - success("trying %s / user:%s\n", prio, user); + if (expect_fail_serv || expect_fail_cli) { + success("ntest %s (user:%s)\n", prio, user); + } else { + success("test %s (user:%s)\n", prio, user); + } err = socketpair(AF_UNIX, SOCK_STREAM, 0, sockets); if (err == -1) { @@ -277,22 +319,72 @@ void run_test(const char *prio, const char *user, unsigned expect_fail) close(sockets[1]); int status; /* parent */ - server(sockets[0], prio, user, expect_fail); + server(sockets[0], sprio?sprio:prio, user, expect_fail_serv, exp_kx); wait(&status); check_wait_status(status); } else { close(sockets[0]); - client(sockets[1], prio, user, expect_fail); + client(sockets[1], prio, user, key, expect_hint, expect_fail_cli, exp_kx); exit(0); } } +static +void run_test_ok(const char *prio, const char *user, const gnutls_datum_t *key, unsigned expect_hint, int expect_fail) +{ + return run_test2(prio, NULL, user, key, expect_hint, GNUTLS_KX_PSK, expect_fail, expect_fail); +} + +static +void run_ectest_ok(const char *prio, const char *user, const gnutls_datum_t *key, unsigned expect_hint, int expect_fail) +{ + return run_test2(prio, NULL, user, key, expect_hint, GNUTLS_KX_ECDHE_PSK, expect_fail, expect_fail); +} + +static +void run_dhtest_ok(const char *prio, const char *user, const gnutls_datum_t *key, unsigned expect_hint, int expect_fail) +{ + return run_test2(prio, NULL, user, key, expect_hint, GNUTLS_KX_DHE_PSK, expect_fail, expect_fail); +} + void doit(void) { - run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", "jas", 0); - run_test("NORMAL:-KX-ALL:+PSK", "jas", 0); - run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", "non-hex", 1); - run_test("NORMAL:-KX-ALL:+PSK", "non-hex", 1); + const gnutls_datum_t key = { (void *) "9e32cf7786321a828ef7668f09fb35db", 32 }; + const gnutls_datum_t wrong_key = { (void *) "9e31cf7786321a828ef7668f09fb35db", 32 }; + + run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", "jas", &key, 1, 0); + run_dhtest_ok("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+DHE-PSK", "jas", &key, 1, 0); + run_ectest_ok("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-PSK", "jas", &key, 1, 0); + run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", NULL, "unknown", &key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_DECRYPTION_FAILED); + run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", NULL, "jas", &wrong_key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_DECRYPTION_FAILED); + run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", NULL, "non-hex", &key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_KEYFILE_ERROR); + + run_test_ok("NORMAL:-KX-ALL:+PSK", "jas", &key, 1, 0); + run_test2("NORMAL:+PSK", NULL, "unknown", &key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_DECRYPTION_FAILED); + run_test2("NORMAL:+PSK", NULL, "jas", &wrong_key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_DECRYPTION_FAILED); + run_test2("NORMAL:-KX-ALL:+PSK", NULL, "non-hex", &key, 1, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_KEYFILE_ERROR); + + run_dhtest_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-EC-ALL", "jas", &key, 0, 0); + run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK", "jas", &key, 0, 0); + + /* test priorities of DHE-PSK and PSK */ + run_ectest_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+DHE-PSK:+PSK:-GROUP-DH-ALL", "jas", &key, 0, 0); + run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+PSK:+DHE-PSK:-GROUP-DH-ALL", "jas", &key, 0, 0); + run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+DHE-PSK:+PSK:-GROUP-DH-ALL", + "NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-128-GCM:+PSK:+DHE-PSK:%SERVER_PRECEDENCE:-GROUP-DH-ALL", + "jas", &key, 0, GNUTLS_KX_PSK, 0, 0); + /* try with PRF that doesn't match binder (SHA256) */ + run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:-CIPHER-ALL:+AES-256-GCM:+PSK:+DHE-PSK", NULL, "jas", &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_INSUFFICIENT_SECURITY); + /* try with no groups and PSK */ + run_test_ok("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK:-GROUP-ALL", "jas", &key, 0, 0); + /* try without any groups but DHE-PSK */ + run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-ALL", "NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:+PSK", "jas", &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_NO_COMMON_KEY_SHARE); + run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:-GROUP-ALL", "NORMAL:-VERS-ALL:+VERS-TLS1.3:+DHE-PSK:+PSK:-GROUP-ALL", "jas", &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_NO_COMMON_KEY_SHARE); + + /* if user invalid we continue without PSK */ + run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK:+DHE-PSK", NULL, "non-hex", &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_INSUFFICIENT_CREDENTIALS); + run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK:+DHE-PSK", NULL, "unknown", &key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); + run_test2("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK:+DHE-PSK", NULL, "jas", &wrong_key, 0, 0, GNUTLS_E_FATAL_ALERT_RECEIVED, GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER); } #endif /* _WIN32 */ diff --git a/tests/pskself.c b/tests/pskself.c index 293cb59561..9580abe86d 100644 --- a/tests/pskself.c +++ b/tests/pskself.c @@ -64,7 +64,7 @@ static void tls_log_func(int level, const char *str) #define MAX_BUF 1024 #define MSG "Hello TLS" -static void client(int sd, const char *prio) +static void client(int sd, const char *prio, unsigned exp_hint) { int ret, ii; gnutls_session_t session; @@ -112,10 +112,12 @@ static void client(int sd, const char *prio) } /* check the hint */ - hint = gnutls_psk_client_get_hint(session); - if (hint == NULL || strcmp(hint, "hint") != 0) { - fail("client: hint is not the expected: %s\n", gnutls_psk_client_get_hint(session)); - goto end; + if (exp_hint) { + hint = gnutls_psk_client_get_hint(session); + if (hint == NULL || strcmp(hint, "hint") != 0) { + fail("client: hint is not the expected: %s\n", gnutls_psk_client_get_hint(session)); + goto end; + } } gnutls_record_send(session, MSG, strlen(MSG)); @@ -274,12 +276,14 @@ char buffer[MAX_BUF + 1]; } static -void run_test(const char *prio) +void run_test(const char *prio, unsigned exp_hint) { pid_t child; int err; int sockets[2]; + success("trying with %s\n", prio); + err = socketpair(AF_UNIX, SOCK_STREAM, 0, sockets); if (err == -1) { perror("socketpair"); @@ -303,7 +307,7 @@ void run_test(const char *prio) check_wait_status(status); } else { close(sockets[0]); - client(sockets[1], prio); + client(sockets[1], prio, exp_hint); exit(0); } } @@ -312,13 +316,19 @@ void doit(void) { generate_dh_params(); - run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK"); - run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-PSK"); - run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+DHE-PSK"); + run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+PSK", 1); + run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+ECDHE-PSK", 1); + run_test("NORMAL:-VERS-ALL:+VERS-TLS1.2:-KX-ALL:+DHE-PSK", 1); + + run_test("NORMAL:-VERS-ALL:+VERS-TLS1.3:+PSK", 0); + run_test("NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-FFDHE2048:+DHE-PSK", 0); + run_test("NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+GROUP-SECP256R1:+ECDHE-PSK", 0); + /* the follow should work once we support PSK without DH */ + run_test("NORMAL:-VERS-ALL:+VERS-TLS1.3:-GROUP-ALL:+PSK", 0); - run_test("NORMAL:-KX-ALL:+PSK"); - run_test("NORMAL:-KX-ALL:+ECDHE-PSK"); - run_test("NORMAL:-KX-ALL:+DHE-PSK"); + run_test("NORMAL:-KX-ALL:+PSK", 1); + run_test("NORMAL:-KX-ALL:+ECDHE-PSK", 1); + run_test("NORMAL:-KX-ALL:+DHE-PSK", 1); gnutls_dh_params_deinit(dh_params); } diff --git a/tests/tls13/no-psk-exts.c b/tests/tls13/no-psk-exts.c new file mode 100644 index 0000000000..b70c667822 --- /dev/null +++ b/tests/tls13/no-psk-exts.c @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2017-2018 Red Hat, Inc. + * + * Author: Nikos Mavrogiannopoulos + * + * This file is part of GnuTLS. + * + * GnuTLS is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * GnuTLS is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/> + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> + +#if defined(_WIN32) + +int main() +{ + exit(77); +} + +#else + +#include <string.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <sys/socket.h> +#include <sys/wait.h> +#include <arpa/inet.h> +#include <unistd.h> +#include <gnutls/gnutls.h> +#include <gnutls/dtls.h> +#include <signal.h> + +#include "cert-common.h" +#include "tls13/ext-parse.h" +#include "utils.h" + +/* This program tests whether a connection without the PSK priority + * options, will contain PSK extensions */ + +static void server_log_func(int level, const char *str) +{ + fprintf(stderr, "server|<%d>| %s", level, str); +} + +static void client_log_func(int level, const char *str) +{ + fprintf(stderr, "client|<%d>| %s", level, str); +} + +#define MAX_BUF 1024 + +static void client(int fd) +{ + int ret; + gnutls_certificate_credentials_t x509_cred; + gnutls_psk_client_credentials_t psk_cred; + gnutls_session_t session; + + global_init(); + + if (debug) { + gnutls_global_set_log_function(client_log_func); + gnutls_global_set_log_level(7); + } + + gnutls_certificate_allocate_credentials(&x509_cred); + gnutls_psk_allocate_client_credentials(&psk_cred); + + /* Initialize TLS session + */ + gnutls_init(&session, GNUTLS_CLIENT); + + gnutls_handshake_set_timeout(session, 20 * 1000); + + ret = gnutls_priority_set_direct(session, "NORMAL:-VERS-ALL:+VERS-TLS1.3:+VERS-TLS1.2:+VERS-TLS1.0", NULL); + if (ret < 0) + fail("cannot set TLS 1.3 priorities\n"); + + /* put the anonymous credentials to the current session + */ + gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred); + gnutls_credentials_set(session, GNUTLS_CRD_PSK, psk_cred); + + gnutls_transport_set_int(session, fd); + + /* Perform the TLS handshake + */ + do { + ret = gnutls_handshake(session); + } + while (ret < 0 && gnutls_error_is_fatal(ret) == 0); + + /* try if gnutls_reauth() would fail as expected */ + ret = gnutls_reauth(session, 0); + if (ret != GNUTLS_E_INVALID_REQUEST) + fail("server: gnutls_reauth did not fail as expected: %s", gnutls_strerror(ret)); + + close(fd); + + gnutls_deinit(session); + + gnutls_certificate_free_credentials(x509_cred); + gnutls_psk_free_client_credentials(psk_cred); + + gnutls_global_deinit(); +} + +static unsigned server_hello_ok = 0; + +#define TLS_EXT_PSK 41 +#define TLS_EXT_PSK_KE 45 + +static int hellos_callback(gnutls_session_t session, unsigned int htype, + unsigned post, unsigned int incoming, const gnutls_datum_t *msg) +{ + if (htype == GNUTLS_HANDSHAKE_SERVER_HELLO && post == GNUTLS_HOOK_POST) { + if (find_server_extension(msg, TLS_EXT_PSK_KE, NULL, NULL)) { + fail("PSK KE extension seen on server (illegal)!\n"); + } + if (find_server_extension(msg, TLS_EXT_PSK, NULL, NULL)) { + fail("PSK extension seen on server (illegal)!\n"); + } + server_hello_ok = 1; + + return GNUTLS_E_INTERRUPTED; + } + + if (htype != GNUTLS_HANDSHAKE_CLIENT_HELLO || post != GNUTLS_HOOK_PRE) + return 0; + + if (find_client_extension(msg, TLS_EXT_PSK, NULL, NULL)) + fail("PSK extension seen in client hello with no PSK!\n"); + + if (find_client_extension(msg, TLS_EXT_PSK_KE, NULL, NULL)) + fail("PSK extension seen in client hello with no PSK!\n"); + + return 0; +} + +static void server(int fd) +{ + int ret; + char buffer[MAX_BUF + 1]; + gnutls_session_t session; + gnutls_certificate_credentials_t x509_cred; + + /* this must be called once in the program + */ + global_init(); + memset(buffer, 0, sizeof(buffer)); + + if (debug) { + gnutls_global_set_log_function(server_log_func); + gnutls_global_set_log_level(4711); + } + + gnutls_certificate_allocate_credentials(&x509_cred); + gnutls_certificate_set_x509_key_mem(x509_cred, &server_cert, + &server_key, + GNUTLS_X509_FMT_PEM); + + gnutls_init(&session, GNUTLS_SERVER); + + gnutls_handshake_set_timeout(session, 20 * 1000); + gnutls_handshake_set_hook_function(session, GNUTLS_HANDSHAKE_ANY, + GNUTLS_HOOK_BOTH, + hellos_callback); + + /* avoid calling all the priority functions, since the defaults + * are adequate. + */ + gnutls_priority_set_direct(session, "NORMAL:+VERS-TLS1.3", NULL); + + gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred); + + gnutls_transport_set_int(session, fd); + + do { + ret = gnutls_handshake(session); + if (ret == GNUTLS_E_INTERRUPTED) { /* expected */ + break; + } + } while (ret < 0 && gnutls_error_is_fatal(ret) == 0); + + + if (server_hello_ok == 0) { + fail("server: did not verify the server hello contents\n"); + } + + close(fd); + gnutls_deinit(session); + + gnutls_certificate_free_credentials(x509_cred); + + gnutls_global_deinit(); + + if (debug) + success("server: client/server hello were verified\n"); +} + +static void ch_handler(int sig) +{ + int status; + wait(&status); + check_wait_status(status); + return; +} + +void doit(void) +{ + int fd[2]; + int ret; + pid_t child; + + signal(SIGCHLD, ch_handler); + + ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd); + if (ret < 0) { + perror("socketpair"); + exit(1); + } + + child = fork(); + if (child < 0) { + perror("fork"); + fail("fork"); + exit(1); + } + + if (child) { + /* parent */ + close(fd[1]); + server(fd[0]); + kill(child, SIGTERM); + } else { + close(fd[0]); + client(fd[1]); + exit(0); + } +} + +#endif /* _WIN32 */ |