~ubuntu-branches/ubuntu/trusty/gnutls26/trusty-security

1 by Andreas Metzler
Import upstream version 2.2.3~rc
1
/*
1.4.3 by Andreas Metzler
Import upstream version 2.9.10
2
 * Copyright (C) 2004, 2005, 2007, 2008, 2009, 2010 Free Software
3
 * Foundation, Inc.
1 by Andreas Metzler
Import upstream version 2.2.3~rc
4
 *
5
 * Author: Simon Josefsson
6
 *
7
 * This file is part of GNUTLS.
8
 *
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.
13
 *
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.
18
 *
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
22
 */
23
24
/* Parts copied from GnuTLS example programs. */
25
1.2.1 by Andreas Metzler
Import upstream version 2.6.6
26
#ifdef HAVE_CONFIG_H
1 by Andreas Metzler
Import upstream version 2.2.3~rc
27
# include <config.h>
28
#endif
29
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>
41
42
#include "utils.h"
43
1.4.1 by Andreas Metzler
Import upstream version 2.8.1
44
#include "tcp.c"
45
1 by Andreas Metzler
Import upstream version 2.2.3~rc
46
#include <readline.h>
47
48
/* A very basic TLS client, with anonymous authentication.
49
 */
50
51
#define MAX_BUF 1024
52
#define MSG "Hello TLS"
53
1.4.1 by Andreas Metzler
Import upstream version 2.8.1
54
static int
1 by Andreas Metzler
Import upstream version 2.2.3~rc
55
client_avp (gnutls_session_t session, void *ptr,
56
	    const char *last, size_t lastlen, char **new, size_t * newlen)
57
{
58
  static int iter = 0;
1.4.1 by Andreas Metzler
Import upstream version 2.8.1
59
  const char *p;
1 by Andreas Metzler
Import upstream version 2.2.3~rc
60
1.4.3 by Andreas Metzler
Import upstream version 2.9.10
61
  if (debug)
62
    {
63
      if (last)
64
	printf ("client: received %d bytes AVP: `%.*s'\n",
65
		(int) lastlen, (int) lastlen, last);
66
      else
67
	printf ("client: new application phase\n");
68
    }
1 by Andreas Metzler
Import upstream version 2.2.3~rc
69
70
  switch (iter)
71
    {
72
    case 0:
73
      p = "client's first AVP, next will be empty";
74
      break;
75
76
    case 1:
77
      p = "";
78
      break;
79
80
    case 2:
81
      p = "client avp";
82
      break;
83
84
    default:
85
      p = "final client AVP, we'll restart next";
86
      iter = -1;
87
      break;
88
    }
89
90
  iter++;
91
92
  if (debug)
93
    p = readline ("Client TLS/IA AVP: ");
94
95
  *new = gnutls_strdup (p);
96
  if (!*new)
97
    return -1;
98
  *newlen = strlen (*new);
99
1.4.3 by Andreas Metzler
Import upstream version 2.9.10
100
  if (debug)
101
    printf ("client: sending %d bytes AVP: `%s'\n", (int) *newlen, *new);
1 by Andreas Metzler
Import upstream version 2.2.3~rc
102
103
  gnutls_ia_permute_inner_secret (session, 3, "foo");
104
105
  return 0;
106
}
107
1.4.1 by Andreas Metzler
Import upstream version 2.8.1
108
static void
1 by Andreas Metzler
Import upstream version 2.2.3~rc
109
client (void)
110
{
111
  int ret, sd, ii;
112
  gnutls_session_t session;
113
  char buffer[MAX_BUF + 1];
114
  gnutls_anon_client_credentials_t anoncred;
115
  gnutls_ia_client_credentials_t iacred;
116
  /* Need to enable anonymous KX specifically. */
117
  const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 };
118
119
  ret = gnutls_global_init ();
120
  if (ret)
121
    fail ("global_init: %d\n", ret);
122
  ret = gnutls_global_init_extra ();
123
  if (ret)
124
    fail ("global_init_extra: %d\n", ret);
125
126
  gnutls_anon_allocate_client_credentials (&anoncred);
127
  gnutls_ia_allocate_client_credentials (&iacred);
128
129
  /* Initialize TLS session
130
   */
131
  gnutls_init (&session, GNUTLS_CLIENT);
132
133
  /* Use default priorities */
134
  gnutls_set_default_priority (session);
135
  gnutls_kx_set_priority (session, kx_prio);
136
137
  /* put the anonymous credentials to the current session
138
   */
139
  gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred);
140
  gnutls_credentials_set (session, GNUTLS_CRD_IA, iacred);
141
142
  /* connect to the peer
143
   */
144
  sd = tcp_connect ();
145
146
  gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd);
147
148
  /* Enable TLS/IA. */
149
  gnutls_ia_set_client_avp_function (iacred, client_avp);
150
151
  /* Perform the TLS handshake
152
   */
153
  ret = gnutls_handshake (session);
154
155
  if (ret < 0)
156
    {
157
      fail ("client: Handshake failed\n");
158
      gnutls_perror (ret);
159
      goto end;
160
    }
161
  else
162
    {
1.4.3 by Andreas Metzler
Import upstream version 2.9.10
163
      if (debug)
164
	success ("client: Handshake was completed\n");
1 by Andreas Metzler
Import upstream version 2.2.3~rc
165
    }
166
167
  /*
168
     To test TLS/IA alert's (the server will print that a fatal alert
169
     was received):
170
     gnutls_alert_send(session, GNUTLS_AL_FATAL,
171
     GNUTLS_A_INNER_APPLICATION_FAILURE);
172
   */
173
174
  if (!gnutls_ia_handshake_p (session))
175
    fail ("client: No TLS/IA negotiation\n");
176
  else
177
    {
1.4.3 by Andreas Metzler
Import upstream version 2.9.10
178
      if (debug)
179
	success ("client: TLS/IA handshake\n");
1 by Andreas Metzler
Import upstream version 2.2.3~rc
180
181
      ret = gnutls_ia_handshake (session);
182
183
      if (ret < 0)
184
	{
185
	  fail ("client: TLS/IA handshake failed\n");
186
	  gnutls_perror (ret);
187
	  goto end;
188
	}
189
      else
190
	{
1.4.3 by Andreas Metzler
Import upstream version 2.9.10
191
	  if (debug)
192
	    success ("client: TLS/IA Handshake was completed\n");
1 by Andreas Metzler
Import upstream version 2.2.3~rc
193
	}
194
    }
195
196
  gnutls_record_send (session, MSG, strlen (MSG));
197
198
  ret = gnutls_record_recv (session, buffer, MAX_BUF);
199
  if (ret == 0)
200
    {
1.4.3 by Andreas Metzler
Import upstream version 2.9.10
201
      if (debug)
202
	success ("client: Peer has closed the TLS connection\n");
1 by Andreas Metzler
Import upstream version 2.2.3~rc
203
      goto end;
204
    }
205
  else if (ret < 0)
206
    {
207
      fail ("client: Error: %s\n", gnutls_strerror (ret));
208
      goto end;
209
    }
210
211
  if (debug)
212
    {
213
      printf ("- Received %d bytes: ", ret);
214
      for (ii = 0; ii < ret; ii++)
215
	{
216
	  fputc (buffer[ii], stdout);
217
	}
218
      fputs ("\n", stdout);
219
    }
220
221
  gnutls_bye (session, GNUTLS_SHUT_RDWR);
222
223
end:
224
225
  tcp_close (sd);
226
227
  gnutls_deinit (session);
228
229
  gnutls_ia_free_client_credentials (iacred);
230
231
  gnutls_anon_free_client_credentials (anoncred);
232
233
  gnutls_global_deinit ();
234
}
235
236
/* This is a sample TLS 1.0 echo server, for anonymous authentication only.
237
 */
238
239
#define SA struct sockaddr
240
#define MAX_BUF 1024
241
#define PORT 5556		/* listen to 5556 port */
242
#define DH_BITS 1024
243
244
/* These are global */
245
gnutls_anon_server_credentials_t anoncred;
246
gnutls_ia_server_credentials_t iacred;
247
1.4.1 by Andreas Metzler
Import upstream version 2.8.1
248
static gnutls_session_t
1 by Andreas Metzler
Import upstream version 2.2.3~rc
249
initialize_tls_session (void)
250
{
251
  gnutls_session_t session;
252
  const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 };
253
254
  gnutls_init (&session, GNUTLS_SERVER);
255
256
  /* avoid calling all the priority functions, since the defaults
257
   * are adequate.
258
   */
259
  gnutls_set_default_priority (session);
260
  gnutls_kx_set_priority (session, kx_prio);
261
262
  gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred);
263
264
  gnutls_dh_set_prime_bits (session, DH_BITS);
265
266
  return session;
267
}
268
269
static gnutls_dh_params_t dh_params;
270
271
static int
272
generate_dh_params (void)
273
{
1.4.2 by Andreas Metzler
Import upstream version 2.9.9
274
  const gnutls_datum_t p3 = { (char *) pkcs3, strlen (pkcs3) };
1.4.1 by Andreas Metzler
Import upstream version 2.8.1
275
  /* Generate Diffie-Hellman parameters - for use with DHE
1 by Andreas Metzler
Import upstream version 2.2.3~rc
276
   * kx algorithms. These should be discarded and regenerated
277
   * once a day, once a week or once a month. Depending on the
278
   * security requirements.
279
   */
280
  gnutls_dh_params_init (&dh_params);
281
  return gnutls_dh_params_import_pkcs3 (dh_params, &p3, GNUTLS_X509_FMT_PEM);
282
}
283
284
int err, listen_sd, i;
285
int sd, ret;
286
struct sockaddr_in sa_serv;
287
struct sockaddr_in sa_cli;
288
socklen_t client_len;
289
char topbuf[512];
290
gnutls_session_t session;
291
char buffer[MAX_BUF + 1];
292
int optval = 1;
293
1.4.1 by Andreas Metzler
Import upstream version 2.8.1
294
static int
1 by Andreas Metzler
Import upstream version 2.2.3~rc
295
server_avp (gnutls_session_t session, void *ptr,
296
	    const char *last, size_t lastlen, char **new, size_t * newlen)
297
{
298
  static int iter = 0;
1.4.1 by Andreas Metzler
Import upstream version 2.8.1
299
  const char *p;
1 by Andreas Metzler
Import upstream version 2.2.3~rc
300
1.4.3 by Andreas Metzler
Import upstream version 2.9.10
301
  if (last && debug)
1 by Andreas Metzler
Import upstream version 2.2.3~rc
302
    printf ("server: received %d bytes AVP: `%.*s'\n",
1.4.3 by Andreas Metzler
Import upstream version 2.9.10
303
	    (int) lastlen, (int) lastlen, last);
1 by Andreas Metzler
Import upstream version 2.2.3~rc
304
305
  gnutls_ia_permute_inner_secret (session, 3, "foo");
306
307
  switch (iter)
308
    {
309
    case 0:
310
      p = "first server AVP";
311
      break;
312
313
    case 1:
314
      p = "second server AVP, next will be empty, then a intermediate finish";
315
      break;
316
317
    case 2:
318
      p = "";
319
      break;
320
321
    case 3:
322
      p = "1";
323
      break;
324
325
    case 4:
326
      p = "server avp, after intermediate finish, next another intermediate";
327
      break;
328
329
    case 5:
330
      p = "1";
331
      break;
332
333
    case 6:
334
      p = "server avp, next will be the finish phase";
335
      break;
336
337
    default:
338
      p = "2";
339
      break;
340
    }
341
342
  iter++;
343
344
  if (debug)
345
    p = readline ("Server TLS/IA AVP (type '1' to sync, '2' to finish): ");
346
347
  if (!p)
348
    return -1;
349
350
  if (strcmp (p, "1") == 0)
351
    {
1.4.3 by Andreas Metzler
Import upstream version 2.9.10
352
      if (debug)
353
	success ("server: Sending IntermediatePhaseFinished...\n");
1 by Andreas Metzler
Import upstream version 2.2.3~rc
354
      return 1;
355
    }
356
357
  if (strcmp (p, "2") == 0)
358
    {
1.4.3 by Andreas Metzler
Import upstream version 2.9.10
359
      if (debug)
360
	success ("server: Sending FinalPhaseFinished...\n");
1 by Andreas Metzler
Import upstream version 2.2.3~rc
361
      return 2;
362
    }
363
364
  *new = gnutls_strdup (p);
365
  if (!*new)
366
    return -1;
367
  *newlen = strlen (*new);
368
1.4.3 by Andreas Metzler
Import upstream version 2.9.10
369
  if (debug)
370
    printf ("server: sending %d bytes AVP: `%s'\n", (int) *newlen, *new);
1 by Andreas Metzler
Import upstream version 2.2.3~rc
371
372
  return 0;
373
}
374
1.4.1 by Andreas Metzler
Import upstream version 2.8.1
375
static void
1 by Andreas Metzler
Import upstream version 2.2.3~rc
376
server_start (void)
377
{
378
  /* Socket operations
379
   */
380
  listen_sd = socket (AF_INET, SOCK_STREAM, 0);
381
  if (err == -1)
382
    {
383
      perror ("socket");
384
      fail ("server: socket failed\n");
385
      return;
386
    }
387
388
  memset (&sa_serv, '\0', sizeof (sa_serv));
389
  sa_serv.sin_family = AF_INET;
390
  sa_serv.sin_addr.s_addr = INADDR_ANY;
391
  sa_serv.sin_port = htons (PORT);	/* Server Port number */
392
1.4.2 by Andreas Metzler
Import upstream version 2.9.9
393
  setsockopt (listen_sd, SOL_SOCKET, SO_REUSEADDR, (void *) &optval,
394
	      sizeof (int));
1 by Andreas Metzler
Import upstream version 2.2.3~rc
395
396
  err = bind (listen_sd, (SA *) & sa_serv, sizeof (sa_serv));
397
  if (err == -1)
398
    {
399
      perror ("bind");
400
      fail ("server: bind failed\n");
401
      return;
402
    }
403
404
  err = listen (listen_sd, 1024);
405
  if (err == -1)
406
    {
407
      perror ("listen");
408
      fail ("server: listen failed\n");
409
      return;
410
    }
411
1.4.3 by Andreas Metzler
Import upstream version 2.9.10
412
  if (debug)
413
    success ("server: ready. Listening to port '%d'\n", PORT);
1 by Andreas Metzler
Import upstream version 2.2.3~rc
414
}
415
1.4.1 by Andreas Metzler
Import upstream version 2.8.1
416
static void
1 by Andreas Metzler
Import upstream version 2.2.3~rc
417
server (void)
418
{
1.1.2 by Andreas Metzler
Import upstream version 2.4.0
419
  /* this must be called once in the program
420
   */
1.2.1 by Andreas Metzler
Import upstream version 2.6.6
421
  ret = gnutls_global_init ();
422
  if (ret)
423
    fail ("global_init: %d\n", ret);
424
  ret = gnutls_global_init_extra ();
425
  if (ret)
426
    fail ("global_init_extra: %d\n", ret);
1.1.2 by Andreas Metzler
Import upstream version 2.4.0
427
428
  gnutls_anon_allocate_server_credentials (&anoncred);
429
  gnutls_ia_allocate_server_credentials (&iacred);
430
1.4.3 by Andreas Metzler
Import upstream version 2.9.10
431
  if (debug)
432
    success ("Launched, generating DH parameters...\n");
1.1.2 by Andreas Metzler
Import upstream version 2.4.0
433
434
  generate_dh_params ();
435
436
  gnutls_anon_set_server_dh_params (anoncred, dh_params);
437
1 by Andreas Metzler
Import upstream version 2.2.3~rc
438
  client_len = sizeof (sa_cli);
439
440
  session = initialize_tls_session ();
441
442
  sd = accept (listen_sd, (SA *) & sa_cli, &client_len);
443
1.4.3 by Andreas Metzler
Import upstream version 2.9.10
444
  if (debug)
445
    success ("server: connection from %s, port %d\n",
446
	     inet_ntop (AF_INET, &sa_cli.sin_addr, topbuf,
447
			sizeof (topbuf)), ntohs (sa_cli.sin_port));
1 by Andreas Metzler
Import upstream version 2.2.3~rc
448
449
  gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd);
450
451
  /* Enable TLS/IA. */
452
  gnutls_credentials_set (session, GNUTLS_CRD_IA, iacred);
453
  gnutls_ia_set_server_avp_function (iacred, server_avp);
454
455
  ret = gnutls_handshake (session);
456
  if (ret < 0)
457
    {
458
      close (sd);
459
      gnutls_deinit (session);
460
      fail ("server: Handshake has failed (%s)\n\n", gnutls_strerror (ret));
461
      return;
462
    }
1.4.3 by Andreas Metzler
Import upstream version 2.9.10
463
  if (debug)
464
    success ("server: Handshake was completed\n");
1 by Andreas Metzler
Import upstream version 2.2.3~rc
465
466
  if (!gnutls_ia_handshake_p (session))
467
    fail ("server: No TLS/IA negotiation\n");
468
  else
469
    {
1.4.3 by Andreas Metzler
Import upstream version 2.9.10
470
      if (debug)
471
	success ("server: TLS/IA handshake\n");
1 by Andreas Metzler
Import upstream version 2.2.3~rc
472
473
      ret = gnutls_ia_handshake (session);
474
475
      if (ret < 0)
476
	{
477
	  fail ("server: TLS/IA handshake failed\n");
478
	  gnutls_perror (ret);
479
	  return;
480
	}
481
      else
482
	{
1.4.3 by Andreas Metzler
Import upstream version 2.9.10
483
	  if (debug)
484
	    success ("server: TLS/IA Handshake was completed\n");
1 by Andreas Metzler
Import upstream version 2.2.3~rc
485
	}
486
    }
487
488
  /* see the Getting peer's information example */
489
  /* print_info(session); */
490
491
  i = 0;
492
  for (;;)
493
    {
1.4.1 by Andreas Metzler
Import upstream version 2.8.1
494
      memset (buffer, 0, MAX_BUF + 1);
1 by Andreas Metzler
Import upstream version 2.2.3~rc
495
      ret = gnutls_record_recv (session, buffer, MAX_BUF);
496
497
      if (ret == 0)
498
	{
1.4.3 by Andreas Metzler
Import upstream version 2.9.10
499
	  if (debug)
500
	    success ("server: Peer has closed the GNUTLS connection\n");
1 by Andreas Metzler
Import upstream version 2.2.3~rc
501
	  break;
502
	}
503
      else if (ret < 0)
504
	{
505
	  if (ret == GNUTLS_E_FATAL_ALERT_RECEIVED)
506
	    {
507
	      gnutls_alert_description_t alert;
508
	      const char *err;
509
	      alert = gnutls_alert_get (session);
510
	      err = gnutls_alert_get_name (alert);
511
	      if (err)
512
		printf ("Fatal alert: %s\n", err);
513
	    }
514
515
	  fail ("server: Received corrupted data(%d). Closing...\n", ret);
516
	  break;
517
	}
518
      else if (ret > 0)
519
	{
520
	  /* echo data back to the client
521
	   */
522
	  gnutls_record_send (session, buffer, strlen (buffer));
523
	}
524
    }
525
  /* do not wait for the peer to close the connection.
526
   */
527
  gnutls_bye (session, GNUTLS_SHUT_WR);
528
529
  close (sd);
530
  gnutls_deinit (session);
531
532
  close (listen_sd);
533
534
  gnutls_ia_free_server_credentials (iacred);
535
536
  gnutls_anon_free_server_credentials (anoncred);
537
1.1.2 by Andreas Metzler
Import upstream version 2.4.0
538
  gnutls_dh_params_deinit (dh_params);
539
1 by Andreas Metzler
Import upstream version 2.2.3~rc
540
  gnutls_global_deinit ();
541
1.4.3 by Andreas Metzler
Import upstream version 2.9.10
542
  if (debug)
543
    success ("server: finished\n");
1 by Andreas Metzler
Import upstream version 2.2.3~rc
544
}
545
546
void
547
doit (void)
548
{
549
  pid_t child;
550
551
  server_start ();
552
  if (error_count)
553
    return;
554
555
  child = fork ();
556
  if (child < 0)
557
    {
558
      perror ("fork");
559
      fail ("fork");
560
      return;
561
    }
562
563
  if (child)
564
    {
565
      int status;
566
      /* parent */
567
      server ();
568
      wait (&status);
569
    }
570
  else
571
    client ();
572
}