diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2011-12-28 10:49:56 +0200 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2011-12-28 16:08:55 +0200 |
commit | 87ed97f3046dcc7f80d4ae70b40045f3a82112ed (patch) | |
tree | e76c1b95c806f62894049937cc6bdf7aa1deafb2 /doc/examples/ex-serv-x509.c | |
parent | c279f32d5ffc41ab41a1441687dcb9daea5e6475 (diff) | |
download | gnutls-87ed97f3046dcc7f80d4ae70b40045f3a82112ed.tar.gz |
updated examples and added new "handling alerts" section.
Diffstat (limited to 'doc/examples/ex-serv-x509.c')
-rw-r--r-- | doc/examples/ex-serv-x509.c | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/doc/examples/ex-serv-x509.c b/doc/examples/ex-serv-x509.c new file mode 100644 index 0000000000..5383fb3425 --- /dev/null +++ b/doc/examples/ex-serv-x509.c @@ -0,0 +1,199 @@ +/* This example code is placed in the public domain. */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <arpa/inet.h> +#include <netinet/in.h> +#include <string.h> +#include <unistd.h> +#include <gnutls/gnutls.h> + +#define KEYFILE "key.pem" +#define CERTFILE "cert.pem" +#define CAFILE "ca.pem" +#define CRLFILE "crl.pem" + +/* This is a sample TLS 1.0 echo server, using X.509 authentication. + */ + +#define MAX_BUF 1024 +#define PORT 5556 /* listen to 5556 port */ + +/* These are global */ +gnutls_certificate_credentials_t x509_cred; +gnutls_priority_t priority_cache; + +static gnutls_session_t +initialize_tls_session (void) +{ + gnutls_session_t session; + + gnutls_init (&session, GNUTLS_SERVER); + + gnutls_priority_set (session, priority_cache); + + gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, x509_cred); + + /* We don't request any certificate from the client. + * If we did we would need to verify it. + */ + gnutls_certificate_server_set_request (session, GNUTLS_CERT_IGNORE); + + return session; +} + +static gnutls_dh_params_t dh_params; + +static int +generate_dh_params (void) +{ + int bits = gnutls_sec_param_to_pk_bits (GNUTLS_PK_DH, GNUTLS_SEC_PARAM_LOW); + + /* Generate Diffie-Hellman parameters - for use with DHE + * kx algorithms. When short bit length is used, it might + * be wise to regenerate parameters often. + */ + gnutls_dh_params_init (&dh_params); + gnutls_dh_params_generate2 (dh_params, bits); + + return 0; +} + +int +main (void) +{ + int listen_sd; + int sd, ret; + struct sockaddr_in sa_serv; + struct sockaddr_in sa_cli; + int client_len; + char topbuf[512]; + gnutls_session_t session; + char buffer[MAX_BUF + 1]; + int optval = 1; + + /* this must be called once in the program + */ + gnutls_global_init (); + + gnutls_certificate_allocate_credentials (&x509_cred); + gnutls_certificate_set_x509_trust_file (x509_cred, CAFILE, + GNUTLS_X509_FMT_PEM); + + gnutls_certificate_set_x509_crl_file (x509_cred, CRLFILE, + GNUTLS_X509_FMT_PEM); + + ret = gnutls_certificate_set_x509_key_file (x509_cred, CERTFILE, KEYFILE, + GNUTLS_X509_FMT_PEM); + if (ret < 0) + { + printf("No certificate or key were found\n"); + exit(1); + } + + generate_dh_params (); + + gnutls_priority_init (&priority_cache, "PERFORMANCE:%SERVER_PRECEDENCE", NULL); + + + gnutls_certificate_set_dh_params (x509_cred, dh_params); + + /* Socket operations + */ + listen_sd = socket (AF_INET, SOCK_STREAM, 0); + + memset (&sa_serv, '\0', sizeof (sa_serv)); + sa_serv.sin_family = AF_INET; + sa_serv.sin_addr.s_addr = INADDR_ANY; + sa_serv.sin_port = htons (PORT); /* Server Port number */ + + setsockopt (listen_sd, SOL_SOCKET, SO_REUSEADDR, (void *) &optval, + sizeof (int)); + + bind (listen_sd, (struct sockaddr *) & sa_serv, sizeof (sa_serv)); + + listen (listen_sd, 1024); + + printf ("Server ready. Listening to port '%d'.\n\n", PORT); + + client_len = sizeof (sa_cli); + for (;;) + { + session = initialize_tls_session (); + + sd = accept (listen_sd, (struct sockaddr *) & sa_cli, &client_len); + + printf ("- connection from %s, port %d\n", + inet_ntop (AF_INET, &sa_cli.sin_addr, topbuf, + sizeof (topbuf)), ntohs (sa_cli.sin_port)); + + gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd); + + do + { + ret = gnutls_handshake (session); + } + while (gnutls_error_is_fatal (ret) == 0); + + if (ret < 0) + { + close (sd); + gnutls_deinit (session); + fprintf (stderr, "*** Handshake has failed (%s)\n\n", + gnutls_strerror (ret)); + continue; + } + printf ("- Handshake was completed\n"); + + /* see the Getting peer's information example */ + /* print_info(session); */ + + for (;;) + { + memset (buffer, 0, MAX_BUF + 1); + ret = gnutls_record_recv (session, buffer, MAX_BUF); + + if (ret == 0) + { + printf ("\n- Peer has closed the GnuTLS connection\n"); + break; + } + else if (ret < 0) + { + fprintf (stderr, "\n*** Received corrupted " + "data(%d). Closing the connection.\n\n", ret); + break; + } + else if (ret > 0) + { + /* echo data back to the client + */ + gnutls_record_send (session, buffer, strlen (buffer)); + } + } + printf ("\n"); + /* do not wait for the peer to close the connection. + */ + gnutls_bye (session, GNUTLS_SHUT_WR); + + close (sd); + gnutls_deinit (session); + + } + close (listen_sd); + + gnutls_certificate_free_credentials (x509_cred); + gnutls_priority_deinit (priority_cache); + + gnutls_global_deinit (); + + return 0; + +} |