Tizen 2.0 Release
[external/libgnutls26.git] / tests / pskself.c
1 /*
2  * Copyright (C) 2004, 2005, 2008, 2010 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 #if !defined(_WIN32)
34 #include <sys/socket.h>
35 #include <sys/wait.h>
36 #include <netinet/in.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 /* A very basic TLS client, with PSK authentication.
47  */
48
49 #define MAX_BUF 1024
50 #define MSG "Hello TLS"
51
52 static void
53 client (void)
54 {
55   int ret, sd, ii;
56   gnutls_session_t session;
57   char buffer[MAX_BUF + 1];
58   gnutls_psk_client_credentials_t pskcred;
59   /* Need to enable anonymous KX specifically. */
60   const gnutls_datum_t key = { (char *) "DEADBEEF", 8 };
61
62   gnutls_global_init ();
63
64   gnutls_psk_allocate_client_credentials (&pskcred);
65   gnutls_psk_set_client_credentials (pskcred, "test", &key,
66                                      GNUTLS_PSK_KEY_HEX);
67
68   /* Initialize TLS session
69    */
70   gnutls_init (&session, GNUTLS_CLIENT);
71
72   /* Use default priorities */
73   gnutls_priority_set_direct (session, "NORMAL:+PSK", NULL);
74
75   /* put the anonymous credentials to the current session
76    */
77   gnutls_credentials_set (session, GNUTLS_CRD_PSK, pskcred);
78
79   /* connect to the peer
80    */
81   sd = tcp_connect ();
82
83   gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd);
84
85   /* Perform the TLS handshake
86    */
87   ret = gnutls_handshake (session);
88
89   if (ret < 0)
90     {
91       fail ("client: Handshake failed\n");
92       gnutls_perror (ret);
93       goto end;
94     }
95   else
96     {
97       if (debug)
98         success ("client: Handshake was completed\n");
99     }
100
101   gnutls_record_send (session, MSG, strlen (MSG));
102
103   ret = gnutls_record_recv (session, buffer, MAX_BUF);
104   if (ret == 0)
105     {
106       if (debug)
107         success ("client: Peer has closed the TLS connection\n");
108       goto end;
109     }
110   else if (ret < 0)
111     {
112       fail ("client: Error: %s\n", gnutls_strerror (ret));
113       goto end;
114     }
115
116   if (debug)
117     {
118       printf ("- Received %d bytes: ", ret);
119       for (ii = 0; ii < ret; ii++)
120         {
121           fputc (buffer[ii], stdout);
122         }
123       fputs ("\n", stdout);
124     }
125
126   gnutls_bye (session, GNUTLS_SHUT_RDWR);
127
128 end:
129
130   tcp_close (sd);
131
132   gnutls_deinit (session);
133
134   gnutls_psk_free_client_credentials (pskcred);
135
136   gnutls_global_deinit ();
137 }
138
139 /* This is a sample TLS 1.0 echo server, for PSK authentication.
140  */
141
142 #define SA struct sockaddr
143 #define MAX_BUF 1024
144 #define PORT 5556               /* listen to 5556 port */
145
146 /* These are global */
147 gnutls_psk_server_credentials_t server_pskcred;
148
149 static gnutls_session_t
150 initialize_tls_session (void)
151 {
152   gnutls_session_t session;
153
154   gnutls_init (&session, GNUTLS_SERVER);
155
156   /* avoid calling all the priority functions, since the defaults
157    * are adequate.
158    */
159   gnutls_priority_set_direct (session, "NORMAL:+PSK", NULL);
160
161   gnutls_credentials_set (session, GNUTLS_CRD_PSK, server_pskcred);
162
163   return session;
164 }
165
166 static int
167 pskfunc (gnutls_session_t session, const char *username, gnutls_datum_t * key)
168 {
169   if (debug)
170     printf ("psk: username %s\n", username);
171   key->data = gnutls_malloc (4);
172   key->data[0] = 0xDE;
173   key->data[1] = 0xAD;
174   key->data[2] = 0xBE;
175   key->data[3] = 0xEF;
176   key->size = 4;
177   return 0;
178 }
179
180 int err, listen_sd, i;
181 int sd, ret;
182 struct sockaddr_in sa_serv;
183 struct sockaddr_in sa_cli;
184 int client_len;
185 char topbuf[512];
186 gnutls_session_t session;
187 char buffer[MAX_BUF + 1];
188 int optval = 1;
189
190 static void
191 server_start (void)
192 {
193   if (debug)
194     success ("Launched...\n");
195
196   /* Socket operations
197    */
198   listen_sd = socket (AF_INET, SOCK_STREAM, 0);
199   if (err == -1)
200     {
201       perror ("socket");
202       fail ("server: socket failed\n");
203       return;
204     }
205
206   memset (&sa_serv, '\0', sizeof (sa_serv));
207   sa_serv.sin_family = AF_INET;
208   sa_serv.sin_addr.s_addr = INADDR_ANY;
209   sa_serv.sin_port = htons (PORT);      /* Server Port number */
210
211   setsockopt (listen_sd, SOL_SOCKET, SO_REUSEADDR, (void *) &optval,
212               sizeof (int));
213
214   err = bind (listen_sd, (SA *) & sa_serv, sizeof (sa_serv));
215   if (err == -1)
216     {
217       perror ("bind");
218       fail ("server: bind failed\n");
219       return;
220     }
221
222   err = listen (listen_sd, 1024);
223   if (err == -1)
224     {
225       perror ("listen");
226       fail ("server: listen failed\n");
227       return;
228     }
229
230   if (debug)
231     success ("server: ready. Listening to port '%d'.\n", PORT);
232 }
233
234 static void
235 server (void)
236 {
237   /* this must be called once in the program
238    */
239   gnutls_global_init ();
240
241   gnutls_psk_allocate_server_credentials (&server_pskcred);
242   gnutls_psk_set_server_credentials_function (server_pskcred, pskfunc);
243
244   client_len = sizeof (sa_cli);
245
246   session = initialize_tls_session ();
247
248   sd = accept (listen_sd, (SA *) & sa_cli, &client_len);
249
250   if (debug)
251     success ("server: connection from %s, port %d\n",
252              inet_ntop (AF_INET, &sa_cli.sin_addr, topbuf,
253                         sizeof (topbuf)), ntohs (sa_cli.sin_port));
254
255   gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sd);
256   ret = gnutls_handshake (session);
257   if (ret < 0)
258     {
259       close (sd);
260       gnutls_deinit (session);
261       fail ("server: Handshake has failed (%s)\n\n", gnutls_strerror (ret));
262       return;
263     }
264   if (debug)
265     success ("server: Handshake was completed\n");
266
267   /* see the Getting peer's information example */
268   /* print_info(session); */
269
270   i = 0;
271   for (;;)
272     {
273       memset (buffer, 0, MAX_BUF + 1);
274       ret = gnutls_record_recv (session, buffer, MAX_BUF);
275
276       if (ret == 0)
277         {
278           if (debug)
279             success ("server: Peer has closed the GnuTLS connection\n");
280           break;
281         }
282       else if (ret < 0)
283         {
284           fail ("server: Received corrupted data(%d). Closing...\n", ret);
285           break;
286         }
287       else if (ret > 0)
288         {
289           /* echo data back to the client
290            */
291           gnutls_record_send (session, buffer, strlen (buffer));
292         }
293     }
294   /* do not wait for the peer to close the connection.
295    */
296   gnutls_bye (session, GNUTLS_SHUT_WR);
297
298   close (sd);
299   gnutls_deinit (session);
300
301   close (listen_sd);
302
303   gnutls_psk_free_server_credentials (server_pskcred);
304
305   gnutls_global_deinit ();
306
307   if (debug)
308     success ("server: finished\n");
309 }
310
311 void
312 doit (void)
313 {
314   pid_t child;
315
316   server_start ();
317   if (error_count)
318     return;
319
320   child = fork ();
321   if (child < 0)
322     {
323       perror ("fork");
324       fail ("fork");
325       return;
326     }
327
328   if (child)
329     {
330       int status;
331       /* parent */
332       server ();
333       wait (&status);
334     }
335   else
336     client ();
337 }