/* * Copyright (C) 2004 Red Hat Inc. * * This program 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 2, or (at your option) any * later version. * * This program 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 this program; if not, write to the Free Software Foundation, * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Authors: * Mark McLoughlin */ #include #include #include #include #include #include #include #include #include #include #undef DEBUG #ifdef DEBUG static void debug_log (int level, const char *str) { fputs (str, stderr); } #endif static int do_server (int fd) { #define MESSAGE "hello there\n" #define DH_BITS 1024 static const int kx_priority[] = { GNUTLS_KX_ANON_DH, 0 }; gnutls_anon_server_credentials anon_cred; gnutls_dh_params dh_params; gnutls_session session; int err; int retval = 1; gnutls_anon_allocate_server_credentials (&anon_cred); gnutls_dh_params_init (&dh_params); gnutls_dh_params_generate2 (dh_params, DH_BITS); gnutls_anon_set_server_dh_params (anon_cred, dh_params); gnutls_init (&session, GNUTLS_SERVER); gnutls_set_default_priority (session); gnutls_kx_set_priority (session, kx_priority); gnutls_credentials_set (session, GNUTLS_CRD_ANON, anon_cred); gnutls_transport_set_ptr (session, (gnutls_transport_ptr) fd); do { fprintf (stderr, "Trying to complete handshake\n"); err = gnutls_handshake (session); } while (err != GNUTLS_E_SUCCESS && !gnutls_error_is_fatal (err)); if (err != GNUTLS_E_SUCCESS) { fprintf (stderr, "TLS Handshake failed: %s\n", gnutls_strerror (err)); retval = 0; goto handshake_failed; } gnutls_record_send (session, MESSAGE, sizeof (MESSAGE)); do { fprintf (stderr, "Trying to complete shutdown\n"); err = gnutls_bye (session, GNUTLS_SHUT_RDWR); } while (err != GNUTLS_E_SUCCESS && !gnutls_error_is_fatal (err)); if (err != GNUTLS_E_SUCCESS) { fprintf (stderr, "TLS shutdown failed: %s\n", gnutls_strerror (err)); retval = 0; } handshake_failed: gnutls_deinit (session); gnutls_dh_params_deinit (dh_params); gnutls_anon_free_server_credentials (anon_cred); return retval; #undef MESSAGE #undef DH_BITS } int main (int argc, char *argv[]) { struct sockaddr_in saddr; int sock; int opt = 1; int retval = 0; gnutls_global_init (); #ifdef DEBUG gnutls_global_set_log_level (10); gnutls_global_set_log_function (debug_log); #endif if ((sock = socket (AF_INET, SOCK_STREAM, 0)) == -1) { fprintf (stderr, "Error creating socket: %s\n", strerror (errno)); retval = 1; goto deinit_and_return; } if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (int)) == -1) { fprintf (stderr, "Error setting SO_REUSEADDR socket option: %s\n", strerror (errno)); retval = 1; goto deinit_and_return; } memset (&saddr, 0, sizeof (struct sockaddr_in)); saddr.sin_family = AF_INET; saddr.sin_port = htons (5899); saddr.sin_addr.s_addr = htonl (INADDR_ANY); if (bind (sock, (struct sockaddr *) &saddr, sizeof (struct sockaddr_in)) == -1) { fprintf (stderr, "Error binding socket: %s\n", strerror (errno)); retval = 1; goto deinit_and_return; } if (listen (sock, 1024) == -1) { fprintf (stderr, "Error listening on socket: %s\n", strerror (errno)); retval = 1; goto deinit_and_return; } while (1) { int fd; fprintf (stderr, "Ready and waiting\n"); fd = accept (sock, NULL, NULL); if (fd == -1) { fprintf (stderr, "Error accepting on socket: %s\n", strerror (errno)); continue; } fprintf (stderr, "Accepted connection on %d\n", fd); if (do_server (fd)) do_server (fd); close (fd); } close (sock); deinit_and_return: gnutls_global_deinit (); return retval; }