Update gnulib files.
[gnutls.git] / tests / tlsia.c
blobbce5f84d23ebbdaf95c0c14765b52abcc58fedf7
1 /*
2 * Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010 Free Software
3 * Foundation, Inc.
5 * Author: Simon Josefsson
7 * This file is part of GNUTLS.
9 * GNUTLS is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 3 of the License, or
12 * (at your option) any later version.
14 * GNUTLS is distributed in the hope that it will be useful, but
15 * WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with GNUTLS; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24 /* Parts copied from GnuTLS example programs. */
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <sys/wait.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
38 #include <unistd.h>
39 #include <gnutls/gnutls.h>
40 #include <gnutls/extra.h>
42 #include "utils.h"
44 #include "tcp.c"
46 #include <readline.h>
48 /* A very basic TLS client, with anonymous authentication.
51 #define MAX_BUF 1024
52 #define MSG "Hello TLS"
54 static int
55 client_avp (gnutls_session_t session, void *ptr,
56 const char *last, size_t lastlen, char **new, size_t * newlen)
58 static int iter = 0;
59 const char *p;
61 if (last)
62 printf ("client: received %d bytes AVP: `%.*s'\n",
63 (int)lastlen, (int) lastlen, last);
64 else
65 printf ("client: new application phase\n");
67 switch (iter)
69 case 0:
70 p = "client's first AVP, next will be empty";
71 break;
73 case 1:
74 p = "";
75 break;
77 case 2:
78 p = "client avp";
79 break;
81 default:
82 p = "final client AVP, we'll restart next";
83 iter = -1;
84 break;
87 iter++;
89 if (debug)
90 p = readline ("Client TLS/IA AVP: ");
92 *new = gnutls_strdup (p);
93 if (!*new)
94 return -1;
95 *newlen = strlen (*new);
97 printf ("client: sending %d bytes AVP: `%s'\n", (int)*newlen, *new);
99 gnutls_ia_permute_inner_secret (session, 3, "foo");
101 return 0;
104 static void
105 client (void)
107 int ret, sd, ii;
108 gnutls_session_t session;
109 char buffer[MAX_BUF + 1];
110 gnutls_anon_client_credentials_t anoncred;
111 gnutls_ia_client_credentials_t iacred;
112 /* Need to enable anonymous KX specifically. */
113 const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 };
115 ret = gnutls_global_init ();
116 if (ret)
117 fail ("global_init: %d\n", ret);
118 ret = gnutls_global_init_extra ();
119 if (ret)
120 fail ("global_init_extra: %d\n", ret);
122 gnutls_anon_allocate_client_credentials (&anoncred);
123 gnutls_ia_allocate_client_credentials (&iacred);
125 /* Initialize TLS session
127 gnutls_init (&session, GNUTLS_CLIENT);
129 /* Use default priorities */
130 gnutls_set_default_priority (session);
131 gnutls_kx_set_priority (session, kx_prio);
133 /* put the anonymous credentials to the current session
135 gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred);
136 gnutls_credentials_set (session, GNUTLS_CRD_IA, iacred);
138 /* connect to the peer
140 sd = tcp_connect ();
142 gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd);
144 /* Enable TLS/IA. */
145 gnutls_ia_set_client_avp_function (iacred, client_avp);
147 /* Perform the TLS handshake
149 ret = gnutls_handshake (session);
151 if (ret < 0)
153 fail ("client: Handshake failed\n");
154 gnutls_perror (ret);
155 goto end;
157 else
159 success ("client: Handshake was completed\n");
163 To test TLS/IA alert's (the server will print that a fatal alert
164 was received):
165 gnutls_alert_send(session, GNUTLS_AL_FATAL,
166 GNUTLS_A_INNER_APPLICATION_FAILURE);
169 if (!gnutls_ia_handshake_p (session))
170 fail ("client: No TLS/IA negotiation\n");
171 else
173 success ("client: TLS/IA handshake\n");
175 ret = gnutls_ia_handshake (session);
177 if (ret < 0)
179 fail ("client: TLS/IA handshake failed\n");
180 gnutls_perror (ret);
181 goto end;
183 else
185 success ("client: TLS/IA Handshake was completed\n");
189 gnutls_record_send (session, MSG, strlen (MSG));
191 ret = gnutls_record_recv (session, buffer, MAX_BUF);
192 if (ret == 0)
194 success ("client: Peer has closed the TLS connection\n");
195 goto end;
197 else if (ret < 0)
199 fail ("client: Error: %s\n", gnutls_strerror (ret));
200 goto end;
203 if (debug)
205 printf ("- Received %d bytes: ", ret);
206 for (ii = 0; ii < ret; ii++)
208 fputc (buffer[ii], stdout);
210 fputs ("\n", stdout);
213 gnutls_bye (session, GNUTLS_SHUT_RDWR);
215 end:
217 tcp_close (sd);
219 gnutls_deinit (session);
221 gnutls_ia_free_client_credentials (iacred);
223 gnutls_anon_free_client_credentials (anoncred);
225 gnutls_global_deinit ();
228 /* This is a sample TLS 1.0 echo server, for anonymous authentication only.
231 #define SA struct sockaddr
232 #define MAX_BUF 1024
233 #define PORT 5556 /* listen to 5556 port */
234 #define DH_BITS 1024
236 /* These are global */
237 gnutls_anon_server_credentials_t anoncred;
238 gnutls_ia_server_credentials_t iacred;
240 static gnutls_session_t
241 initialize_tls_session (void)
243 gnutls_session_t session;
244 const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 };
246 gnutls_init (&session, GNUTLS_SERVER);
248 /* avoid calling all the priority functions, since the defaults
249 * are adequate.
251 gnutls_set_default_priority (session);
252 gnutls_kx_set_priority (session, kx_prio);
254 gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred);
256 gnutls_dh_set_prime_bits (session, DH_BITS);
258 return session;
261 static gnutls_dh_params_t dh_params;
263 static int
264 generate_dh_params (void)
266 const gnutls_datum_t p3 = { (char *) pkcs3, strlen (pkcs3) };
267 /* Generate Diffie-Hellman parameters - for use with DHE
268 * kx algorithms. These should be discarded and regenerated
269 * once a day, once a week or once a month. Depending on the
270 * security requirements.
272 gnutls_dh_params_init (&dh_params);
273 return gnutls_dh_params_import_pkcs3 (dh_params, &p3, GNUTLS_X509_FMT_PEM);
276 int err, listen_sd, i;
277 int sd, ret;
278 struct sockaddr_in sa_serv;
279 struct sockaddr_in sa_cli;
280 socklen_t client_len;
281 char topbuf[512];
282 gnutls_session_t session;
283 char buffer[MAX_BUF + 1];
284 int optval = 1;
286 static int
287 server_avp (gnutls_session_t session, void *ptr,
288 const char *last, size_t lastlen, char **new, size_t * newlen)
290 static int iter = 0;
291 const char *p;
293 if (last)
294 printf ("server: received %d bytes AVP: `%.*s'\n",
295 (int)lastlen, (int) lastlen, last);
297 gnutls_ia_permute_inner_secret (session, 3, "foo");
299 switch (iter)
301 case 0:
302 p = "first server AVP";
303 break;
305 case 1:
306 p = "second server AVP, next will be empty, then a intermediate finish";
307 break;
309 case 2:
310 p = "";
311 break;
313 case 3:
314 p = "1";
315 break;
317 case 4:
318 p = "server avp, after intermediate finish, next another intermediate";
319 break;
321 case 5:
322 p = "1";
323 break;
325 case 6:
326 p = "server avp, next will be the finish phase";
327 break;
329 default:
330 p = "2";
331 break;
334 iter++;
336 if (debug)
337 p = readline ("Server TLS/IA AVP (type '1' to sync, '2' to finish): ");
339 if (!p)
340 return -1;
342 if (strcmp (p, "1") == 0)
344 success ("server: Sending IntermediatePhaseFinished...\n");
345 return 1;
348 if (strcmp (p, "2") == 0)
350 success ("server: Sending FinalPhaseFinished...\n");
351 return 2;
354 *new = gnutls_strdup (p);
355 if (!*new)
356 return -1;
357 *newlen = strlen (*new);
359 printf ("server: sending %d bytes AVP: `%s'\n", (int)*newlen, *new);
361 return 0;
364 static void
365 server_start (void)
367 /* Socket operations
369 listen_sd = socket (AF_INET, SOCK_STREAM, 0);
370 if (err == -1)
372 perror ("socket");
373 fail ("server: socket failed\n");
374 return;
377 memset (&sa_serv, '\0', sizeof (sa_serv));
378 sa_serv.sin_family = AF_INET;
379 sa_serv.sin_addr.s_addr = INADDR_ANY;
380 sa_serv.sin_port = htons (PORT); /* Server Port number */
382 setsockopt (listen_sd, SOL_SOCKET, SO_REUSEADDR, (void *) &optval,
383 sizeof (int));
385 err = bind (listen_sd, (SA *) & sa_serv, sizeof (sa_serv));
386 if (err == -1)
388 perror ("bind");
389 fail ("server: bind failed\n");
390 return;
393 err = listen (listen_sd, 1024);
394 if (err == -1)
396 perror ("listen");
397 fail ("server: listen failed\n");
398 return;
401 success ("server: ready. Listening to port '%d'\n", PORT);
404 static void
405 server (void)
407 /* this must be called once in the program
409 ret = gnutls_global_init ();
410 if (ret)
411 fail ("global_init: %d\n", ret);
412 ret = gnutls_global_init_extra ();
413 if (ret)
414 fail ("global_init_extra: %d\n", ret);
416 gnutls_anon_allocate_server_credentials (&anoncred);
417 gnutls_ia_allocate_server_credentials (&iacred);
419 success ("Launched, generating DH parameters...\n");
421 generate_dh_params ();
423 gnutls_anon_set_server_dh_params (anoncred, dh_params);
425 client_len = sizeof (sa_cli);
427 session = initialize_tls_session ();
429 sd = accept (listen_sd, (SA *) & sa_cli, &client_len);
431 success ("server: connection from %s, port %d\n",
432 inet_ntop (AF_INET, &sa_cli.sin_addr, topbuf,
433 sizeof (topbuf)), ntohs (sa_cli.sin_port));
435 gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd);
437 /* Enable TLS/IA. */
438 gnutls_credentials_set (session, GNUTLS_CRD_IA, iacred);
439 gnutls_ia_set_server_avp_function (iacred, server_avp);
441 ret = gnutls_handshake (session);
442 if (ret < 0)
444 close (sd);
445 gnutls_deinit (session);
446 fail ("server: Handshake has failed (%s)\n\n", gnutls_strerror (ret));
447 return;
449 success ("server: Handshake was completed\n");
451 if (!gnutls_ia_handshake_p (session))
452 fail ("server: No TLS/IA negotiation\n");
453 else
455 success ("server: TLS/IA handshake\n");
457 ret = gnutls_ia_handshake (session);
459 if (ret < 0)
461 fail ("server: TLS/IA handshake failed\n");
462 gnutls_perror (ret);
463 return;
465 else
467 success ("server: TLS/IA Handshake was completed\n");
471 /* see the Getting peer's information example */
472 /* print_info(session); */
474 i = 0;
475 for (;;)
477 memset (buffer, 0, MAX_BUF + 1);
478 ret = gnutls_record_recv (session, buffer, MAX_BUF);
480 if (ret == 0)
482 success ("server: Peer has closed the GNUTLS connection\n");
483 break;
485 else if (ret < 0)
487 if (ret == GNUTLS_E_FATAL_ALERT_RECEIVED)
489 gnutls_alert_description_t alert;
490 const char *err;
491 alert = gnutls_alert_get (session);
492 err = gnutls_alert_get_name (alert);
493 if (err)
494 printf ("Fatal alert: %s\n", err);
497 fail ("server: Received corrupted data(%d). Closing...\n", ret);
498 break;
500 else if (ret > 0)
502 /* echo data back to the client
504 gnutls_record_send (session, buffer, strlen (buffer));
507 /* do not wait for the peer to close the connection.
509 gnutls_bye (session, GNUTLS_SHUT_WR);
511 close (sd);
512 gnutls_deinit (session);
514 close (listen_sd);
516 gnutls_ia_free_server_credentials (iacred);
518 gnutls_anon_free_server_credentials (anoncred);
520 gnutls_dh_params_deinit (dh_params);
522 gnutls_global_deinit ();
524 success ("server: finished\n");
527 void
528 doit (void)
530 pid_t child;
532 server_start ();
533 if (error_count)
534 return;
536 child = fork ();
537 if (child < 0)
539 perror ("fork");
540 fail ("fork");
541 return;
544 if (child)
546 int status;
547 /* parent */
548 server ();
549 wait (&status);
551 else
552 client ();