/* * Copyright (C) 2010-2012 Free Software Foundation, Inc. * Author: Ludovic Courtès * * 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 General Public License * along with GNUTLS; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include "utils.h" #include #include #include #include #include #if !defined(_WIN32) #include #endif #include #include #include #if !defined(_WIN32) static const char message[] = "Hello, brave GNU world!"; /* The OpenPGP key pair for use and the key ID in those keys. */ static const char pub_key_file[] = "../guile/tests/openpgp-pub.asc"; static const char priv_key_file[] = "../guile/tests/openpgp-sec.asc"; static const char *key_id = NULL; static gnutls_datum_t stored_cli_cert = {NULL, 0}; static void log_message (int level, const char *message) { fprintf (stderr, "[%5d|%2d] %s", getpid (), level, message); } static int key_recv_func(gnutls_session_t session, const unsigned char *keyfpr, unsigned int keyfpr_length, gnutls_datum_t * key) { key->data = gnutls_malloc(stored_cli_cert.size); memcpy(key->data, stored_cli_cert.data, stored_cli_cert.size); key->size = stored_cli_cert.size; return 0; } void doit () { int err, i; int sockets[2]; const char *srcdir; pid_t child; char pub_key_path[512], priv_key_path[512]; global_init (); srcdir = getenv ("srcdir") ? getenv ("srcdir") : "."; for (i = 0; i < 5; i++) { if (i <= 1) key_id = NULL; /* try using the master key */ else if (i == 2) key_id = "auto"; /* test auto */ else if (i >= 3) key_id = "f30fd423c143e7ba"; if (debug) { gnutls_global_set_log_level (5); gnutls_global_set_log_function (log_message); } err = socketpair (AF_UNIX, SOCK_STREAM, 0, sockets); if (err != 0) fail ("socketpair %s\n", strerror (errno)); if (sizeof(pub_key_path) < strlen (srcdir) + strlen (pub_key_file) + 2) abort(); strcpy (pub_key_path, srcdir); strcat (pub_key_path, "/"); strcat (pub_key_path, pub_key_file); if (sizeof(priv_key_path) < strlen (srcdir) + strlen (priv_key_file) + 2) abort(); strcpy (priv_key_path, srcdir); strcat (priv_key_path, "/"); strcat (priv_key_path, priv_key_file); child = fork (); if (child == -1) fail ("fork %s\n", strerror (errno)); if (child == 0) { /* Child process (client). */ gnutls_session_t session; gnutls_certificate_credentials_t cred; ssize_t sent; if (debug) printf ("client process %i\n", getpid ()); err = gnutls_init (&session, GNUTLS_CLIENT); if (err != 0) fail ("client session %d\n", err); if (i==0) /* we use the primary key which is RSA. Test the RSA ciphersuite */ gnutls_priority_set_direct (session, "NONE:+VERS-TLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+RSA:+CTYPE-OPENPGP", NULL); else gnutls_priority_set_direct (session, "NONE:+VERS-TLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+DHE-DSS:+DHE-RSA:+CTYPE-OPENPGP", NULL); gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) (intptr_t) sockets[0]); err = gnutls_certificate_allocate_credentials (&cred); if (err != 0) fail ("client credentials %d\n", err); err = gnutls_certificate_set_openpgp_key_file2 (cred, pub_key_path, priv_key_path, key_id, GNUTLS_OPENPGP_FMT_BASE64); if (err != 0) fail ("client openpgp keys %s\n", gnutls_strerror (err)); err = gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, cred); if (err != 0) fail ("client credential_set %d\n", err); gnutls_dh_set_prime_bits (session, 1024); if (i==4) gnutls_openpgp_send_cert(session, GNUTLS_OPENPGP_CERT_FINGERPRINT); err = gnutls_handshake (session); if (err != 0) fail ("client handshake %s (%d) \n", gnutls_strerror (err), err); else if (debug) printf ("client handshake successful\n"); sent = gnutls_record_send (session, message, sizeof (message)); if (sent != sizeof (message)) fail ("client sent %li vs. %li\n", (long) sent, (long) sizeof (message)); err = gnutls_bye (session, GNUTLS_SHUT_RDWR); if (err != 0) fail ("client bye %d\n", err); if (debug) printf ("client done\n"); gnutls_deinit(session); gnutls_certificate_free_credentials (cred); gnutls_free(stored_cli_cert.data); gnutls_global_deinit (); return; } else { /* Parent process (server). */ gnutls_session_t session; gnutls_dh_params_t dh_params; gnutls_certificate_credentials_t cred; char greetings[sizeof (message) * 2]; ssize_t received; pid_t done; int status; const gnutls_datum_t p3 = { (void *) pkcs3, strlen (pkcs3) }; if (debug) printf ("server process %i (child %i)\n", getpid (), child); err = gnutls_init (&session, GNUTLS_SERVER); if (err != 0) fail ("server session %d\n", err); gnutls_priority_set_direct (session, "NONE:+VERS-TLS1.0:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+DHE-DSS:+DHE-RSA:+RSA:+CTYPE-OPENPGP", NULL); gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) (intptr_t) sockets[1]); err = gnutls_certificate_allocate_credentials (&cred); if (err != 0) fail ("server credentials %d\n", err); err = gnutls_certificate_set_openpgp_key_file2 (cred, pub_key_path, priv_key_path, key_id, GNUTLS_OPENPGP_FMT_BASE64); if (err != 0) fail ("server openpgp keys %s\n", gnutls_strerror (err)); err = gnutls_dh_params_init (&dh_params); if (err) fail ("server DH params init %d\n", err); err = gnutls_dh_params_import_pkcs3 (dh_params, &p3, GNUTLS_X509_FMT_PEM); if (err) fail ("server DH params generate %d\n", err); gnutls_certificate_set_dh_params (cred, dh_params); err = gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, cred); if (err != 0) fail ("server credential_set %d\n", err); gnutls_certificate_server_set_request (session, GNUTLS_CERT_REQUIRE); if (i==4) gnutls_openpgp_set_recv_key_function(session, key_recv_func); err = gnutls_handshake (session); if (err != 0) fail ("server handshake %s (%d) \n", gnutls_strerror (err), err); if (stored_cli_cert.data == NULL) { const gnutls_datum_t* d; unsigned int d_size; d = gnutls_certificate_get_peers(session, &d_size); if (d != NULL) { stored_cli_cert.data = gnutls_malloc(d[0].size); memcpy(stored_cli_cert.data, d[0].data, d[0].size); stored_cli_cert.size = d[0].size; } } received = gnutls_record_recv (session, greetings, sizeof (greetings)); if (received != sizeof (message) || memcmp (greetings, message, sizeof (message))) fail ("server received %li vs. %li\n", (long) received, (long) sizeof (message)); err = gnutls_bye (session, GNUTLS_SHUT_RDWR); if (err != 0) fail ("server bye %s (%d) \n", gnutls_strerror (err), err); if (debug) printf ("server done\n"); gnutls_deinit(session); gnutls_certificate_free_credentials (cred); gnutls_dh_params_deinit (dh_params); done = wait (&status); if (done < 0) fail ("wait %s\n", strerror (errno)); if (done != child) fail ("who's that?! %d\n", done); if (WIFEXITED (status)) { if (WEXITSTATUS (status) != 0) fail ("child exited with status %d\n", WEXITSTATUS (status)); } else if (WIFSIGNALED (status)) fail ("child stopped by signal %d\n", WTERMSIG (status)); else fail ("child failed: %d\n", status); } } gnutls_free(stored_cli_cert.data); gnutls_global_deinit (); } #else void doit () { exit (77); } #endif