6
#include <sys/socket.h>
7
#include <netinet/in.h>
11
#include <gnutls/gnutls.h>
13
#define KEYFILE "key.pem"
14
#define CERTFILE "cert.pem"
15
#define CAFILE "ca.pem"
16
#define CRLFILE "crl.pem"
18
/* This is a sample TLS 1.0 echo server.
19
* Export-grade ciphersuites and session resuming are supported.
22
#define SA struct sockaddr
23
#define SOCKET_ERR(err,s) if(err==-1) {perror(s);return(1);}
25
#define PORT 5556 /* listen to 5556 port */
28
/* These are global */
29
gnutls_certificate_credentials_t cert_cred;
31
static void wrap_db_init (void);
32
static void wrap_db_deinit (void);
33
static int wrap_db_store (void *dbf, gnutls_datum_t key, gnutls_datum_t data);
34
static gnutls_datum_t wrap_db_fetch (void *dbf, gnutls_datum_t key);
35
static int wrap_db_delete (void *dbf, gnutls_datum_t key);
37
#define TLS_SESSION_CACHE 50
40
initialize_tls_session (void)
42
gnutls_session_t session;
44
gnutls_init (&session, GNUTLS_SERVER);
46
/* Use the default priorities, plus, export cipher suites.
48
gnutls_set_default_export_priority (session);
50
gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, cert_cred);
52
/* request client certificate if any.
54
gnutls_certificate_server_set_request (session, GNUTLS_CERT_REQUEST);
56
gnutls_dh_set_prime_bits (session, DH_BITS);
58
if (TLS_SESSION_CACHE != 0)
60
gnutls_db_set_retrieve_function (session, wrap_db_fetch);
61
gnutls_db_set_remove_function (session, wrap_db_delete);
62
gnutls_db_set_store_function (session, wrap_db_store);
63
gnutls_db_set_ptr (session, NULL);
69
gnutls_dh_params_t dh_params;
70
/* Export-grade cipher suites require temporary RSA
73
gnutls_rsa_params_t rsa_params;
76
generate_dh_params (void)
78
/* Generate Diffie Hellman parameters - for use with DHE
79
* kx algorithms. These should be discarded and regenerated
80
* once a day, once a week or once a month. Depends on the
81
* security requirements.
83
gnutls_dh_params_init (&dh_params);
84
gnutls_dh_params_generate2 (dh_params, DH_BITS);
90
generate_rsa_params (void)
92
gnutls_rsa_params_init (&rsa_params);
94
/* Generate RSA parameters - for use with RSA-export
95
* cipher suites. These should be discarded and regenerated
96
* once a day, once every 500 transactions etc. Depends on the
97
* security requirements.
100
gnutls_rsa_params_generate2 (rsa_params, 512);
108
int err, listen_sd, i;
110
struct sockaddr_in sa_serv;
111
struct sockaddr_in sa_cli;
114
gnutls_session_t session;
115
char buffer[MAX_BUF + 1];
119
strcpy (name, "Echo Server");
121
/* this must be called once in the program
123
gnutls_global_init ();
125
gnutls_certificate_allocate_credentials (&cert_cred);
127
gnutls_certificate_set_x509_trust_file (cert_cred, CAFILE,
128
GNUTLS_X509_FMT_PEM);
130
gnutls_certificate_set_x509_crl_file (cert_cred, CRLFILE,
131
GNUTLS_X509_FMT_PEM);
133
gnutls_certificate_set_x509_key_file (cert_cred, CERTFILE, KEYFILE,
134
GNUTLS_X509_FMT_PEM);
136
generate_dh_params ();
137
generate_rsa_params ();
139
if (TLS_SESSION_CACHE != 0)
144
gnutls_certificate_set_dh_params (cert_cred, dh_params);
145
gnutls_certificate_set_rsa_export_params (cert_cred, rsa_params);
149
listen_sd = socket (AF_INET, SOCK_STREAM, 0);
150
SOCKET_ERR (listen_sd, "socket");
152
memset (&sa_serv, '\0', sizeof (sa_serv));
153
sa_serv.sin_family = AF_INET;
154
sa_serv.sin_addr.s_addr = INADDR_ANY;
155
sa_serv.sin_port = htons (PORT); /* Server Port number */
157
setsockopt (listen_sd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof (int));
159
err = bind (listen_sd, (SA *) & sa_serv, sizeof (sa_serv));
160
SOCKET_ERR (err, "bind");
161
err = listen (listen_sd, 1024);
162
SOCKET_ERR (err, "listen");
164
printf ("%s ready. Listening to port '%d'.\n\n", name, PORT);
166
client_len = sizeof (sa_cli);
169
session = initialize_tls_session ();
171
sd = accept (listen_sd, (SA *) & sa_cli, &client_len);
173
printf ("- connection from %s, port %d\n",
174
inet_ntop (AF_INET, &sa_cli.sin_addr, topbuf,
175
sizeof (topbuf)), ntohs (sa_cli.sin_port));
177
gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd);
178
ret = gnutls_handshake (session);
182
gnutls_deinit (session);
183
fprintf (stderr, "*** Handshake has failed (%s)\n\n",
184
gnutls_strerror (ret));
187
printf ("- Handshake was completed\n");
189
/* print_info(session); */
194
memset (buffer, 0, MAX_BUF + 1);
195
ret = gnutls_record_recv (session, buffer, MAX_BUF);
199
printf ("\n- Peer has closed the TLS connection\n");
204
fprintf (stderr, "\n*** Received corrupted "
205
"data(%d). Closing the connection.\n\n", ret);
210
/* echo data back to the client
212
gnutls_record_send (session, buffer, strlen (buffer));
216
/* do not wait for the peer to close the connection.
218
gnutls_bye (session, GNUTLS_SHUT_WR);
221
gnutls_deinit (session);
226
gnutls_certificate_free_credentials (cert_cred);
228
gnutls_global_deinit ();
235
/* Functions and other stuff needed for session resuming.
236
* This is done using a very simple list which holds session ids
240
#define MAX_SESSION_ID_SIZE 32
241
#define MAX_SESSION_DATA_SIZE 512
245
char session_id[MAX_SESSION_ID_SIZE];
248
char session_data[MAX_SESSION_DATA_SIZE];
249
int session_data_size;
252
static CACHE *cache_db;
253
static int cache_db_ptr = 0;
259
/* allocate cache_db */
260
cache_db = calloc (1, TLS_SESSION_CACHE * sizeof (CACHE));
264
wrap_db_deinit (void)
270
wrap_db_store (void *dbf, gnutls_datum_t key, gnutls_datum_t data)
273
if (cache_db == NULL)
276
if (key.size > MAX_SESSION_ID_SIZE)
278
if (data.size > MAX_SESSION_DATA_SIZE)
281
memcpy (cache_db[cache_db_ptr].session_id, key.data, key.size);
282
cache_db[cache_db_ptr].session_id_size = key.size;
284
memcpy (cache_db[cache_db_ptr].session_data, data.data, data.size);
285
cache_db[cache_db_ptr].session_data_size = data.size;
288
cache_db_ptr %= TLS_SESSION_CACHE;
293
static gnutls_datum_t
294
wrap_db_fetch (void *dbf, gnutls_datum_t key)
296
gnutls_datum_t res = { NULL, 0 };
299
if (cache_db == NULL)
302
for (i = 0; i < TLS_SESSION_CACHE; i++)
304
if (key.size == cache_db[i].session_id_size &&
305
memcmp (key.data, cache_db[i].session_id, key.size) == 0)
309
res.size = cache_db[i].session_data_size;
311
res.data = gnutls_malloc (res.size);
312
if (res.data == NULL)
315
memcpy (res.data, cache_db[i].session_data, res.size);
324
wrap_db_delete (void *dbf, gnutls_datum_t key)
328
if (cache_db == NULL)
331
for (i = 0; i < TLS_SESSION_CACHE; i++)
333
if (key.size == cache_db[i].session_id_size &&
334
memcmp (key.data, cache_db[i].session_id, key.size) == 0)
337
cache_db[i].session_id_size = 0;
338
cache_db[i].session_data_size = 0;