Generated.
[gnutls.git] / tests / tlsia.c
blobb2f684154a7e5f26348d4f1adf7d086815dea006
1 /*
2 * Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation
4 * Author: Simon Josefsson
6 * This file is part of GNUTLS.
8 * GNUTLS is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 3 of the License, or
11 * (at your option) any later version.
13 * GNUTLS is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with GNUTLS; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 /* Parts copied from GnuTLS example programs. */
25 #ifdef HAVE_CONFIG_H
26 # include <config.h>
27 #endif
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <sys/wait.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
37 #include <unistd.h>
38 #include <gnutls/gnutls.h>
39 #include <gnutls/extra.h>
41 #include "utils.h"
43 #include "tcp.c"
45 #include <readline.h>
47 /* A very basic TLS client, with anonymous authentication.
50 #define MAX_BUF 1024
51 #define MSG "Hello TLS"
53 static int
54 client_avp (gnutls_session_t session, void *ptr,
55 const char *last, size_t lastlen, char **new, size_t * newlen)
57 static int iter = 0;
58 const char *p;
60 if (last)
61 printf ("client: received %d bytes AVP: `%.*s'\n",
62 (int)lastlen, (int) lastlen, last);
63 else
64 printf ("client: new application phase\n");
66 switch (iter)
68 case 0:
69 p = "client's first AVP, next will be empty";
70 break;
72 case 1:
73 p = "";
74 break;
76 case 2:
77 p = "client avp";
78 break;
80 default:
81 p = "final client AVP, we'll restart next";
82 iter = -1;
83 break;
86 iter++;
88 if (debug)
89 p = readline ("Client TLS/IA AVP: ");
91 *new = gnutls_strdup (p);
92 if (!*new)
93 return -1;
94 *newlen = strlen (*new);
96 printf ("client: sending %d bytes AVP: `%s'\n", (int)*newlen, *new);
98 gnutls_ia_permute_inner_secret (session, 3, "foo");
100 return 0;
103 static void
104 client (void)
106 int ret, sd, ii;
107 gnutls_session_t session;
108 char buffer[MAX_BUF + 1];
109 gnutls_anon_client_credentials_t anoncred;
110 gnutls_ia_client_credentials_t iacred;
111 /* Need to enable anonymous KX specifically. */
112 const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 };
114 ret = gnutls_global_init ();
115 if (ret)
116 fail ("global_init: %d\n", ret);
117 ret = gnutls_global_init_extra ();
118 if (ret)
119 fail ("global_init_extra: %d\n", ret);
121 gnutls_anon_allocate_client_credentials (&anoncred);
122 gnutls_ia_allocate_client_credentials (&iacred);
124 /* Initialize TLS session
126 gnutls_init (&session, GNUTLS_CLIENT);
128 /* Use default priorities */
129 gnutls_set_default_priority (session);
130 gnutls_kx_set_priority (session, kx_prio);
132 /* put the anonymous credentials to the current session
134 gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred);
135 gnutls_credentials_set (session, GNUTLS_CRD_IA, iacred);
137 /* connect to the peer
139 sd = tcp_connect ();
141 gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd);
143 /* Enable TLS/IA. */
144 gnutls_ia_set_client_avp_function (iacred, client_avp);
146 /* Perform the TLS handshake
148 ret = gnutls_handshake (session);
150 if (ret < 0)
152 fail ("client: Handshake failed\n");
153 gnutls_perror (ret);
154 goto end;
156 else
158 success ("client: Handshake was completed\n");
162 To test TLS/IA alert's (the server will print that a fatal alert
163 was received):
164 gnutls_alert_send(session, GNUTLS_AL_FATAL,
165 GNUTLS_A_INNER_APPLICATION_FAILURE);
168 if (!gnutls_ia_handshake_p (session))
169 fail ("client: No TLS/IA negotiation\n");
170 else
172 success ("client: TLS/IA handshake\n");
174 ret = gnutls_ia_handshake (session);
176 if (ret < 0)
178 fail ("client: TLS/IA handshake failed\n");
179 gnutls_perror (ret);
180 goto end;
182 else
184 success ("client: TLS/IA Handshake was completed\n");
188 gnutls_record_send (session, MSG, strlen (MSG));
190 ret = gnutls_record_recv (session, buffer, MAX_BUF);
191 if (ret == 0)
193 success ("client: Peer has closed the TLS connection\n");
194 goto end;
196 else if (ret < 0)
198 fail ("client: Error: %s\n", gnutls_strerror (ret));
199 goto end;
202 if (debug)
204 printf ("- Received %d bytes: ", ret);
205 for (ii = 0; ii < ret; ii++)
207 fputc (buffer[ii], stdout);
209 fputs ("\n", stdout);
212 gnutls_bye (session, GNUTLS_SHUT_RDWR);
214 end:
216 tcp_close (sd);
218 gnutls_deinit (session);
220 gnutls_ia_free_client_credentials (iacred);
222 gnutls_anon_free_client_credentials (anoncred);
224 gnutls_global_deinit ();
227 /* This is a sample TLS 1.0 echo server, for anonymous authentication only.
230 #define SA struct sockaddr
231 #define MAX_BUF 1024
232 #define PORT 5556 /* listen to 5556 port */
233 #define DH_BITS 1024
235 /* These are global */
236 gnutls_anon_server_credentials_t anoncred;
237 gnutls_ia_server_credentials_t iacred;
239 static gnutls_session_t
240 initialize_tls_session (void)
242 gnutls_session_t session;
243 const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 };
245 gnutls_init (&session, GNUTLS_SERVER);
247 /* avoid calling all the priority functions, since the defaults
248 * are adequate.
250 gnutls_set_default_priority (session);
251 gnutls_kx_set_priority (session, kx_prio);
253 gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred);
255 gnutls_dh_set_prime_bits (session, DH_BITS);
257 return session;
260 static gnutls_dh_params_t dh_params;
262 static int
263 generate_dh_params (void)
265 const gnutls_datum_t p3 = { (char *) pkcs3, strlen (pkcs3) };
266 /* Generate Diffie-Hellman parameters - for use with DHE
267 * kx algorithms. These should be discarded and regenerated
268 * once a day, once a week or once a month. Depending on the
269 * security requirements.
271 gnutls_dh_params_init (&dh_params);
272 return gnutls_dh_params_import_pkcs3 (dh_params, &p3, GNUTLS_X509_FMT_PEM);
275 int err, listen_sd, i;
276 int sd, ret;
277 struct sockaddr_in sa_serv;
278 struct sockaddr_in sa_cli;
279 socklen_t client_len;
280 char topbuf[512];
281 gnutls_session_t session;
282 char buffer[MAX_BUF + 1];
283 int optval = 1;
285 static int
286 server_avp (gnutls_session_t session, void *ptr,
287 const char *last, size_t lastlen, char **new, size_t * newlen)
289 static int iter = 0;
290 const char *p;
292 if (last)
293 printf ("server: received %d bytes AVP: `%.*s'\n",
294 (int)lastlen, (int) lastlen, last);
296 gnutls_ia_permute_inner_secret (session, 3, "foo");
298 switch (iter)
300 case 0:
301 p = "first server AVP";
302 break;
304 case 1:
305 p = "second server AVP, next will be empty, then a intermediate finish";
306 break;
308 case 2:
309 p = "";
310 break;
312 case 3:
313 p = "1";
314 break;
316 case 4:
317 p = "server avp, after intermediate finish, next another intermediate";
318 break;
320 case 5:
321 p = "1";
322 break;
324 case 6:
325 p = "server avp, next will be the finish phase";
326 break;
328 default:
329 p = "2";
330 break;
333 iter++;
335 if (debug)
336 p = readline ("Server TLS/IA AVP (type '1' to sync, '2' to finish): ");
338 if (!p)
339 return -1;
341 if (strcmp (p, "1") == 0)
343 success ("server: Sending IntermediatePhaseFinished...\n");
344 return 1;
347 if (strcmp (p, "2") == 0)
349 success ("server: Sending FinalPhaseFinished...\n");
350 return 2;
353 *new = gnutls_strdup (p);
354 if (!*new)
355 return -1;
356 *newlen = strlen (*new);
358 printf ("server: sending %d bytes AVP: `%s'\n", (int)*newlen, *new);
360 return 0;
363 static void
364 server_start (void)
366 /* Socket operations
368 listen_sd = socket (AF_INET, SOCK_STREAM, 0);
369 if (err == -1)
371 perror ("socket");
372 fail ("server: socket failed\n");
373 return;
376 memset (&sa_serv, '\0', sizeof (sa_serv));
377 sa_serv.sin_family = AF_INET;
378 sa_serv.sin_addr.s_addr = INADDR_ANY;
379 sa_serv.sin_port = htons (PORT); /* Server Port number */
381 setsockopt (listen_sd, SOL_SOCKET, SO_REUSEADDR, (void *) &optval,
382 sizeof (int));
384 err = bind (listen_sd, (SA *) & sa_serv, sizeof (sa_serv));
385 if (err == -1)
387 perror ("bind");
388 fail ("server: bind failed\n");
389 return;
392 err = listen (listen_sd, 1024);
393 if (err == -1)
395 perror ("listen");
396 fail ("server: listen failed\n");
397 return;
400 success ("server: ready. Listening to port '%d'\n", PORT);
403 static void
404 server (void)
406 /* this must be called once in the program
408 ret = gnutls_global_init ();
409 if (ret)
410 fail ("global_init: %d\n", ret);
411 ret = gnutls_global_init_extra ();
412 if (ret)
413 fail ("global_init_extra: %d\n", ret);
415 gnutls_anon_allocate_server_credentials (&anoncred);
416 gnutls_ia_allocate_server_credentials (&iacred);
418 success ("Launched, generating DH parameters...\n");
420 generate_dh_params ();
422 gnutls_anon_set_server_dh_params (anoncred, dh_params);
424 client_len = sizeof (sa_cli);
426 session = initialize_tls_session ();
428 sd = accept (listen_sd, (SA *) & sa_cli, &client_len);
430 success ("server: connection from %s, port %d\n",
431 inet_ntop (AF_INET, &sa_cli.sin_addr, topbuf,
432 sizeof (topbuf)), ntohs (sa_cli.sin_port));
434 gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd);
436 /* Enable TLS/IA. */
437 gnutls_credentials_set (session, GNUTLS_CRD_IA, iacred);
438 gnutls_ia_set_server_avp_function (iacred, server_avp);
440 ret = gnutls_handshake (session);
441 if (ret < 0)
443 close (sd);
444 gnutls_deinit (session);
445 fail ("server: Handshake has failed (%s)\n\n", gnutls_strerror (ret));
446 return;
448 success ("server: Handshake was completed\n");
450 if (!gnutls_ia_handshake_p (session))
451 fail ("server: No TLS/IA negotiation\n");
452 else
454 success ("server: TLS/IA handshake\n");
456 ret = gnutls_ia_handshake (session);
458 if (ret < 0)
460 fail ("server: TLS/IA handshake failed\n");
461 gnutls_perror (ret);
462 return;
464 else
466 success ("server: TLS/IA Handshake was completed\n");
470 /* see the Getting peer's information example */
471 /* print_info(session); */
473 i = 0;
474 for (;;)
476 memset (buffer, 0, MAX_BUF + 1);
477 ret = gnutls_record_recv (session, buffer, MAX_BUF);
479 if (ret == 0)
481 success ("server: Peer has closed the GNUTLS connection\n");
482 break;
484 else if (ret < 0)
486 if (ret == GNUTLS_E_FATAL_ALERT_RECEIVED)
488 gnutls_alert_description_t alert;
489 const char *err;
490 alert = gnutls_alert_get (session);
491 err = gnutls_alert_get_name (alert);
492 if (err)
493 printf ("Fatal alert: %s\n", err);
496 fail ("server: Received corrupted data(%d). Closing...\n", ret);
497 break;
499 else if (ret > 0)
501 /* echo data back to the client
503 gnutls_record_send (session, buffer, strlen (buffer));
506 /* do not wait for the peer to close the connection.
508 gnutls_bye (session, GNUTLS_SHUT_WR);
510 close (sd);
511 gnutls_deinit (session);
513 close (listen_sd);
515 gnutls_ia_free_server_credentials (iacred);
517 gnutls_anon_free_server_credentials (anoncred);
519 gnutls_dh_params_deinit (dh_params);
521 gnutls_global_deinit ();
523 success ("server: finished\n");
526 void
527 doit (void)
529 pid_t child;
531 server_start ();
532 if (error_count)
533 return;
535 child = fork ();
536 if (child < 0)
538 perror ("fork");
539 fail ("fork");
540 return;
543 if (child)
545 int status;
546 /* parent */
547 server ();
548 wait (&status);
550 else
551 client ();