#include #include #include #include #include #include #include #include #include static void debug_log (int level, const char *str) { fputs (str, stderr); } int main (int argc, char **argv) { int opt, debug = 0, listener, sin_len, i; const char *ssl_cert_file = "./test-cert.pem"; const char *ssl_key_file = "./test-key.pem"; int port = 9999; struct sockaddr_in sin; int client; static gnutls_dh_params_t dh_params; gnutls_certificate_credentials creds; gnutls_session_t session; int len; int status; while ((opt = getopt (argc, argv, "c:d:k:p:")) != -1) { switch (opt) { case 'c': ssl_cert_file = optarg; break; case 'd': debug = atoi (optarg); break; case 'k': ssl_key_file = optarg; break; case 'p': port = atoi (optarg); break; case '?': fprintf (stderr, "Usage: %s [-d debuglevel] [-c ssl-cert-file] [-k ssl-key-file]\n", argv[0]); break; } } if (debug) { gnutls_global_set_log_function (debug_log); gnutls_global_set_log_level (debug); } /* Create server socket */ listener = socket (AF_INET, SOCK_STREAM, 0); if (listener == -1) { perror ("creating listening socket"); exit (1); } memset (&sin, 0, sizeof (sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = INADDR_ANY; sin.sin_port = htons (port); if (bind (listener, (struct sockaddr *) &sin, sizeof (sin)) == -1) { perror ("binding listening socket"); exit (1); } if (listen (listener, 1) == -1) { perror ("listening on socket"); exit (1); } sin_len = sizeof (sin); getsockname (listener, (struct sockaddr *)&sin, (void *)&sin_len); port = ntohs (sin.sin_port); printf ("listening on port %d\n", port); #if defined(GCRY_THREAD_OPTION_PTHREAD_IMPL) && !defined(G_OS_WIN32) gcry_control (GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); #endif gnutls_global_init (); gnutls_certificate_allocate_credentials (&creds); if (gnutls_certificate_set_x509_key_file (creds, ssl_cert_file, ssl_key_file, GNUTLS_X509_FMT_PEM) != 0) { fprintf (stderr, "Failed to set SSL certificate and key files " "(%s, %s).\n", ssl_cert_file, ssl_key_file); exit (1); } gnutls_certificate_set_dh_params (creds, dh_params); while (1) { len = sizeof (sin); client = accept (listener, (struct sockaddr *) &sin, (void *)&len); gnutls_init (&session, GNUTLS_SERVER); gnutls_set_default_priority (session); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, creds); gnutls_dh_set_prime_bits (session, 1024); gnutls_transport_set_ptr (session, (void *)client); /* Initial handshake */ status = gnutls_handshake (session); if (status < 0) gnutls_perror (status); /* Rehandshake */ status = gnutls_rehandshake (session); if (status < 0) gnutls_perror (status); status = gnutls_handshake (session); if (status < 0) gnutls_perror (status); /* Close */ gnutls_bye (session, GNUTLS_SHUT_WR); gnutls_deinit (session); close (client); } return 0; }