Imported Upstream version 3.0.30
[platform/upstream/gnutls.git] / tests / anonself.c
1 /*
2  * Copyright (C) 2004-2012 Free Software Foundation, Inc.
3  *
4  * Author: Simon Josefsson
5  *
6  * This file is part of GnuTLS.
7  *
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.
12  *
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.
17  *
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
21  */
22
23 /* Parts copied from GnuTLS example programs. */
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <sys/types.h>
33 #include <netinet/in.h>
34 #include <sys/socket.h>
35 #if !defined(_WIN32)
36 #include <sys/wait.h>
37 #include <arpa/inet.h>
38 #endif
39 #include <unistd.h>
40 #include <gnutls/gnutls.h>
41
42 #include "tcp.c"
43
44 #include "utils.h"
45
46 static void
47 tls_log_func (int level, const char *str)
48 {
49   fprintf (stderr, "|<%d>| %s", level, str);
50 }
51
52 /* A very basic TLS client, with anonymous authentication.
53  */
54
55 #define MAX_BUF 1024
56 #define MSG "Hello TLS"
57
58 static void
59 client (void)
60 {
61   int ret, sd, ii;
62   gnutls_session_t session;
63   char buffer[MAX_BUF + 1];
64   gnutls_anon_client_credentials_t anoncred;
65   /* Need to enable anonymous KX specifically. */
66
67   gnutls_global_init ();
68
69   gnutls_global_set_log_function (tls_log_func);
70   if (debug)
71     gnutls_global_set_log_level (4711);
72
73   gnutls_anon_allocate_client_credentials (&anoncred);
74
75   /* Initialize TLS session
76    */
77   gnutls_init (&session, GNUTLS_CLIENT);
78
79   /* Use default priorities */
80   gnutls_priority_set_direct (session, "NONE:+VERS-TLS-ALL:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-DH", NULL);
81
82   /* put the anonymous credentials to the current session
83    */
84   gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred);
85
86   /* connect to the peer
87    */
88   sd = tcp_connect ();
89
90   gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd);
91
92   /* Perform the TLS handshake
93    */
94   ret = gnutls_handshake (session);
95
96   if (ret < 0)
97     {
98       fail ("client: Handshake failed\n");
99       gnutls_perror (ret);
100       goto end;
101     }
102   else
103     {
104       if (debug)
105         success ("client: Handshake was completed\n");
106     }
107
108   if (debug)
109     success ("client: TLS version is: %s\n",
110              gnutls_protocol_get_name (gnutls_protocol_get_version
111                                        (session)));
112
113   gnutls_record_send (session, MSG, strlen (MSG));
114
115   ret = gnutls_record_recv (session, buffer, MAX_BUF);
116   if (ret == 0)
117     {
118       if (debug)
119         success ("client: Peer has closed the TLS connection\n");
120       goto end;
121     }
122   else if (ret < 0)
123     {
124       fail ("client: Error: %s\n", gnutls_strerror (ret));
125       goto end;
126     }
127
128   if (debug)
129     {
130       printf ("- Received %d bytes: ", ret);
131       for (ii = 0; ii < ret; ii++)
132         {
133           fputc (buffer[ii], stdout);
134         }
135       fputs ("\n", stdout);
136     }
137
138   gnutls_bye (session, GNUTLS_SHUT_RDWR);
139
140 end:
141
142   tcp_close (sd);
143
144   gnutls_deinit (session);
145
146   gnutls_anon_free_client_credentials (anoncred);
147
148   gnutls_global_deinit ();
149 }
150
151 /* This is a sample TLS 1.0 echo server, for anonymous authentication only.
152  */
153
154 #define SA struct sockaddr
155 #define MAX_BUF 1024
156 #define PORT 5556               /* listen to 5556 port */
157 #define DH_BITS 1024
158
159 /* These are global */
160 gnutls_anon_server_credentials_t anoncred;
161
162 static gnutls_session_t
163 initialize_tls_session (void)
164 {
165   gnutls_session_t session;
166
167   gnutls_init (&session, GNUTLS_SERVER);
168
169   /* avoid calling all the priority functions, since the defaults
170    * are adequate.
171    */
172   gnutls_priority_set_direct (session, "NONE:+VERS-TLS-ALL:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-DH", NULL);
173
174   gnutls_credentials_set (session, GNUTLS_CRD_ANON, anoncred);
175
176   gnutls_dh_set_prime_bits (session, DH_BITS);
177
178   return session;
179 }
180
181 static gnutls_dh_params_t dh_params;
182
183 static int
184 generate_dh_params (void)
185 {
186   const gnutls_datum_t p3 = { (void *) pkcs3, strlen (pkcs3) };
187   /* Generate Diffie-Hellman parameters - for use with DHE
188    * kx algorithms. These should be discarded and regenerated
189    * once a day, once a week or once a month. Depending on the
190    * security requirements.
191    */
192   gnutls_dh_params_init (&dh_params);
193   return gnutls_dh_params_import_pkcs3 (dh_params, &p3, GNUTLS_X509_FMT_PEM);
194 }
195
196 int err, listen_sd, i;
197 int sd, ret;
198 struct sockaddr_in sa_serv;
199 struct sockaddr_in sa_cli;
200 socklen_t client_len;
201 char topbuf[512];
202 gnutls_session_t session;
203 char buffer[MAX_BUF + 1];
204 int optval = 1;
205
206 static void
207 server_start (void)
208 {
209   /* Socket operations
210    */
211   listen_sd = socket (AF_INET, SOCK_STREAM, 0);
212   if (err == -1)
213     {
214       perror ("socket");
215       fail ("server: socket failed\n");
216       return;
217     }
218
219   memset (&sa_serv, '\0', sizeof (sa_serv));
220   sa_serv.sin_family = AF_INET;
221   sa_serv.sin_addr.s_addr = INADDR_ANY;
222   sa_serv.sin_port = htons (PORT);      /* Server Port number */
223
224   setsockopt (listen_sd, SOL_SOCKET, SO_REUSEADDR, (void *) &optval,
225               sizeof (int));
226
227   err = bind (listen_sd, (SA *) & sa_serv, sizeof (sa_serv));
228   if (err == -1)
229     {
230       perror ("bind");
231       fail ("server: bind failed\n");
232       return;
233     }
234
235   err = listen (listen_sd, 1024);
236   if (err == -1)
237     {
238       perror ("listen");
239       fail ("server: listen failed\n");
240       return;
241     }
242
243   if (debug)
244     success ("server: ready. Listening to port '%d'.\n", PORT);
245 }
246
247 static void
248 server (void)
249 {
250   /* this must be called once in the program
251    */
252   gnutls_global_init ();
253
254   gnutls_global_set_log_function (tls_log_func);
255   if (debug)
256     gnutls_global_set_log_level (4711);
257
258   gnutls_anon_allocate_server_credentials (&anoncred);
259
260   if (debug)
261     success ("Launched, generating DH parameters...\n");
262
263   generate_dh_params ();
264
265   gnutls_anon_set_server_dh_params (anoncred, dh_params);
266
267   client_len = sizeof (sa_cli);
268
269   session = initialize_tls_session ();
270
271   sd = accept (listen_sd, (SA *) & sa_cli, &client_len);
272
273   if (debug)
274     success ("server: connection from %s, port %d\n",
275              inet_ntop (AF_INET, &sa_cli.sin_addr, topbuf,
276                         sizeof (topbuf)), ntohs (sa_cli.sin_port));
277
278   gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd);
279   ret = gnutls_handshake (session);
280   if (ret < 0)
281     {
282       close (sd);
283       gnutls_deinit (session);
284       fail ("server: Handshake has failed (%s)\n\n", gnutls_strerror (ret));
285       return;
286     }
287   if (debug)
288     success ("server: Handshake was completed\n");
289
290   if (debug)
291     success ("server: TLS version is: %s\n",
292              gnutls_protocol_get_name (gnutls_protocol_get_version
293                                        (session)));
294
295   /* see the Getting peer's information example */
296   /* print_info(session); */
297
298   i = 0;
299   for (;;)
300     {
301       memset (buffer, 0, MAX_BUF + 1);
302       ret = gnutls_record_recv (session, buffer, MAX_BUF);
303
304       if (ret == 0)
305         {
306           if (debug)
307             success ("server: Peer has closed the GnuTLS connection\n");
308           break;
309         }
310       else if (ret < 0)
311         {
312           fail ("server: Received corrupted data(%d). Closing...\n", ret);
313           break;
314         }
315       else if (ret > 0)
316         {
317           /* echo data back to the client
318            */
319           gnutls_record_send (session, buffer, strlen (buffer));
320         }
321     }
322   /* do not wait for the peer to close the connection.
323    */
324   gnutls_bye (session, GNUTLS_SHUT_WR);
325
326   close (sd);
327   gnutls_deinit (session);
328
329   close (listen_sd);
330
331   gnutls_anon_free_server_credentials (anoncred);
332
333   gnutls_dh_params_deinit (dh_params);
334
335   gnutls_global_deinit ();
336
337   if (debug)
338     success ("server: finished\n");
339 }
340
341 void
342 doit (void)
343 {
344   pid_t child;
345
346   server_start ();
347   if (error_count)
348     return;
349
350   child = fork ();
351   if (child < 0)
352     {
353       perror ("fork");
354       fail ("fork");
355       return;
356     }
357
358   if (child)
359     {
360       int status;
361       /* parent */
362       server ();
363       wait (&status);
364     }
365   else
366     client ();
367 }