blob: 2f1f2c45f39e680b7c5280a8177f70c765f59b6a [file] [log] [blame]
Manuel Pégourié-Gonnarde63582a2014-10-14 11:47:21 +02001/*
2 * Simple DTLS server demonstration program
3 *
4 * Copyright (C) 2014, Brainspark B.V.
5 *
6 * This file is part of PolarSSL (http://www.polarssl.org)
7 * Lead Maintainer: Paul Bakker <polarssl_maintainer at polarssl.org>
8 *
9 * All rights reserved.
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 */
25
26#if !defined(POLARSSL_CONFIG_FILE)
27#include "polarssl/config.h"
28#else
29#include POLARSSL_CONFIG_FILE
30#endif
31
32#if !defined(POLARSSL_SSL_SRV_C) || !defined(POLARSSL_SSL_PROTO_DTLS) || \
33 !defined(POLARSSL_SSL_COOKIE_C) || !defined(POLARSSL_NET_C) || \
34 !defined(POLARSSL_ENTROPY_C) || !defined(POLARSSL_CTR_DRBG_C) || \
35 !defined(POLARSSL_X509_CRT_PARSE_C) || !defined(POLARSSL_RSA_C) || \
36 !defined(POLARSSL_CERTS_C)
37
38#include <stdio.h>
39int main( void )
40{
41 printf( "POLARSSL_SSL_SRV_C and/or POLARSSL_SSL_PROTO_DTLS and/or "
42 "POLARSSL_SSL_COOKIE_C and/or POLARSSL_NET_C and/or "
43 "POLARSSL_ENTROPY_C and/or POLARSSL_CTR_DRBG_C and/or "
44 "POLARSSL_X509_CRT_PARSE_C and/or POLARSSL_RSA_C and/or "
45 "POLARSSL_CERTS_C not defined.\n" );
46 return( 0 );
47}
48#else
49
50#if defined(_WIN32)
51#include <windows.h>
52#endif
53
54#include <string.h>
55#include <stdlib.h>
56#include <stdio.h>
57
58#include "polarssl/entropy.h"
59#include "polarssl/ctr_drbg.h"
60#include "polarssl/certs.h"
61#include "polarssl/x509.h"
62#include "polarssl/ssl.h"
63#include "polarssl/ssl_cookie.h"
64#include "polarssl/net.h"
65#include "polarssl/error.h"
66#include "polarssl/debug.h"
67
68#if defined(POLARSSL_SSL_CACHE_C)
69#include "polarssl/ssl_cache.h"
70#endif
71
72#define READ_TIMEOUT_MS 10000 /* 5 seconds */
73#define DEBUG_LEVEL 0
74
75static void my_debug( void *ctx, int level, const char *str )
76{
77 ((void) level);
78
79 fprintf( (FILE *) ctx, "%s", str );
80 fflush( (FILE *) ctx );
81}
82
83int main( void )
84{
85 int ret, len;
86 int listen_fd;
87 int client_fd = -1;
88 unsigned char buf[1024];
89 const char *pers = "dtls_server";
90 unsigned char client_ip[16] = { 0 };
91 ssl_cookie_ctx cookie_ctx;
92
93 entropy_context entropy;
94 ctr_drbg_context ctr_drbg;
95 ssl_context ssl;
96 x509_crt srvcert;
97 pk_context pkey;
98#if defined(POLARSSL_SSL_CACHE_C)
99 ssl_cache_context cache;
100#endif
101
102 memset( &ssl, 0, sizeof(ssl_context) );
103 ssl_cookie_init( &cookie_ctx );
104#if defined(POLARSSL_SSL_CACHE_C)
105 ssl_cache_init( &cache );
106#endif
107 x509_crt_init( &srvcert );
108 pk_init( &pkey );
109 entropy_init( &entropy );
110
111#if defined(POLARSSL_DEBUG_C)
112 debug_set_threshold( DEBUG_LEVEL );
113#endif
114
115 /*
116 * 1. Load the certificates and private RSA key
117 */
118 printf( "\n . Loading the server cert. and key..." );
119 fflush( stdout );
120
121 /*
122 * This demonstration program uses embedded test certificates.
123 * Instead, you may want to use x509_crt_parse_file() to read the
124 * server and CA certificates, as well as pk_parse_keyfile().
125 */
126 ret = x509_crt_parse( &srvcert, (const unsigned char *) test_srv_crt,
127 strlen( test_srv_crt ) );
128 if( ret != 0 )
129 {
130 printf( " failed\n ! x509_crt_parse returned %d\n\n", ret );
131 goto exit;
132 }
133
134 ret = x509_crt_parse( &srvcert, (const unsigned char *) test_ca_list,
135 strlen( test_ca_list ) );
136 if( ret != 0 )
137 {
138 printf( " failed\n ! x509_crt_parse returned %d\n\n", ret );
139 goto exit;
140 }
141
142 ret = pk_parse_key( &pkey, (const unsigned char *) test_srv_key,
143 strlen( test_srv_key ), NULL, 0 );
144 if( ret != 0 )
145 {
146 printf( " failed\n ! pk_parse_key returned %d\n\n", ret );
147 goto exit;
148 }
149
150 printf( " ok\n" );
151
152 /*
153 * 2. Setup the "listening" UDP socket
154 */
155 printf( " . Bind on udp/*/4433 ..." );
156 fflush( stdout );
157
158 if( ( ret = net_bind( &listen_fd, NULL, 4433, NET_PROTO_UDP ) ) != 0 )
159 {
160 printf( " failed\n ! net_bind returned %d\n\n", ret );
161 goto exit;
162 }
163
164 printf( " ok\n" );
165
166 /*
167 * 3. Seed the RNG
168 */
169 printf( " . Seeding the random number generator..." );
170 fflush( stdout );
171
172 if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy,
173 (const unsigned char *) pers,
174 strlen( pers ) ) ) != 0 )
175 {
176 printf( " failed\n ! ctr_drbg_init returned %d\n", ret );
177 goto exit;
178 }
179
180 printf( " ok\n" );
181
182 /*
183 * 4. Setup stuff
184 */
185 printf( " . Setting up the DTLS data..." );
186 fflush( stdout );
187
188 if( ( ret = ssl_init( &ssl ) ) != 0 )
189 {
190 printf( " failed\n ! ssl_init returned %d\n\n", ret );
191 goto exit;
192 }
193
194 ssl_set_endpoint( &ssl, SSL_IS_SERVER );
195 ssl_set_transport( &ssl, SSL_TRANSPORT_DATAGRAM );
196 ssl_set_authmode( &ssl, SSL_VERIFY_NONE );
197
198 ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg );
199 ssl_set_dbg( &ssl, my_debug, stdout );
200
201#if defined(POLARSSL_SSL_CACHE_C)
202 ssl_set_session_cache( &ssl, ssl_cache_get, &cache,
203 ssl_cache_set, &cache );
204#endif
205
206 ssl_set_ca_chain( &ssl, srvcert.next, NULL, NULL );
207 if( ( ret = ssl_set_own_cert( &ssl, &srvcert, &pkey ) ) != 0 )
208 {
209 printf( " failed\n ! ssl_set_own_cert returned %d\n\n", ret );
210 goto exit;
211 }
212
213 if( ( ret = ssl_cookie_setup( &cookie_ctx,
214 ctr_drbg_random, &ctr_drbg ) ) != 0 )
215 {
216 printf( " failed\n ! ssl_cookie_setup returned %d\n\n", ret );
217 goto exit;
218 }
219
220 ssl_set_dtls_cookies( &ssl, ssl_cookie_write, ssl_cookie_check,
221 &cookie_ctx );
222
223 printf( " ok\n" );
224
225reset:
226#ifdef POLARSSL_ERROR_C
227 if( ret != 0 )
228 {
229 char error_buf[100];
230 polarssl_strerror( ret, error_buf, 100 );
231 printf("Last error was: %d - %s\n\n", ret, error_buf );
232 }
233#endif
234
235 if( client_fd != -1 )
236 net_close( client_fd );
237
238 ssl_session_reset( &ssl );
239
240 /*
241 * 3. Wait until a client connects
242 */
243 client_fd = -1;
244
245 printf( " . Waiting for a remote connection ..." );
246 fflush( stdout );
247
248 if( ( ret = net_accept( listen_fd, &client_fd, client_ip ) ) != 0 )
249 {
250 printf( " failed\n ! net_accept returned %d\n\n", ret );
251 goto exit;
252 }
253
254 /* With UDP, bind_fd is hijacked by client_fd, so bind a new one */
255 if( ( ret = net_bind( &listen_fd, NULL, 4433, NET_PROTO_UDP ) ) != 0 )
256 {
257 printf( " failed\n ! net_bind returned -0x%x\n\n", -ret );
258 goto exit;
259 }
260
261 /* For HelloVerifyRequest cookies */
262 if( ( ret = ssl_set_client_transport_id( &ssl, client_ip,
263 sizeof( client_ip ) ) ) != 0 )
264 {
265 printf( " failed\n ! "
266 "ssl_set_client_tranport_id() returned -0x%x\n\n", -ret );
267 goto exit;
268 }
269
270 ssl_set_bio_timeout( &ssl, &client_fd,
271 net_send, net_recv, net_recv_timeout,
272 READ_TIMEOUT_MS );
273
274 printf( " ok\n" );
275
276 /*
277 * 5. Handshake
278 */
279 printf( " . Performing the DTLS handshake..." );
280 fflush( stdout );
281
282 do ret = ssl_handshake( &ssl );
283 while( ret == POLARSSL_ERR_NET_WANT_READ ||
284 ret == POLARSSL_ERR_NET_WANT_WRITE );
285
286 if( ret == POLARSSL_ERR_SSL_HELLO_VERIFY_REQUIRED )
287 {
288 printf( " hello verification requested\n" );
289 ret = 0;
290 goto reset;
291 }
292 else if( ret != 0 )
293 {
294 printf( " failed\n ! ssl_handshake returned -0x%x\n\n", -ret );
295 goto reset;
296 }
297
298 printf( " ok\n" );
299
300 /*
301 * 6. Read the echo Request
302 */
303 printf( " < Read from client:" );
304 fflush( stdout );
305
306 len = sizeof( buf ) - 1;
307 memset( buf, 0, sizeof( buf ) );
308
309 do ret = ssl_read( &ssl, buf, len );
310 while( ret == POLARSSL_ERR_NET_WANT_READ ||
311 ret == POLARSSL_ERR_NET_WANT_WRITE );
312
313 if( ret <= 0 )
314 {
315 switch( ret )
316 {
317 case POLARSSL_ERR_NET_TIMEOUT:
318 printf( " timeout\n\n" );
319 goto reset;
320
321 case POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY:
322 printf( " connection was closed gracefully\n" );
323 ret = 0;
324 goto close_notify;
325
326 default:
327 printf( " ssl_read returned -0x%x\n\n", -ret );
328 goto reset;
329 }
330 }
331
332 len = ret;
333 printf( " %d bytes read\n\n%s\n\n", len, buf );
334
335 /*
336 * 7. Write the 200 Response
337 */
338 printf( " > Write to client:" );
339 fflush( stdout );
340
341 do ret = ssl_write( &ssl, buf, len );
342 while( ret == POLARSSL_ERR_NET_WANT_READ ||
343 ret == POLARSSL_ERR_NET_WANT_WRITE );
344
345 if( ret < 0 )
346 {
347 printf( " failed\n ! ssl_write returned %d\n\n", ret );
348 goto exit;
349 }
350
351 len = ret;
352 printf( " %d bytes written\n\n%s\n\n", len, buf );
353
354 /*
355 * 8. Done, cleanly close the connection
356 */
357close_notify:
358 printf( " . Closing the connection..." );
359
360 /* No error checking, the connection might be closed already */
361 do ret = ssl_close_notify( &ssl );
362 while( ret == POLARSSL_ERR_NET_WANT_WRITE );
363 ret = 0;
364
365 printf( " done\n" );
366
367 goto reset;
368
369 /*
370 * Final clean-ups and exit
371 */
372exit:
373
374#ifdef POLARSSL_ERROR_C
375 if( ret != 0 )
376 {
377 char error_buf[100];
378 polarssl_strerror( ret, error_buf, 100 );
379 printf( "Last error was: %d - %s\n\n", ret, error_buf );
380 }
381#endif
382
383 if( client_fd != -1 )
384 net_close( client_fd );
385
386 x509_crt_free( &srvcert );
387 pk_free( &pkey );
388 ssl_free( &ssl );
389 ssl_cookie_free( &cookie_ctx );
390#if defined(POLARSSL_SSL_CACHE_C)
391 ssl_cache_free( &cache );
392#endif
393 ctr_drbg_free( &ctr_drbg );
394 entropy_free( &entropy );
395
396#if defined(_WIN32)
397 printf( " Press Enter to exit this program.\n" );
398 fflush( stdout ); getchar();
399#endif
400
401 /* Shell can not handle large exit numbers -> 1 for errors */
402 if( ret < 0 )
403 ret = 1;
404
405 return( ret );
406}
407#endif /* POLARSSL_SSL_SRV_C && POLARSSL_SSL_PROTO_DTLS &&
408 POLARSSL_SSL_COOKIE_C && POLARSSL_NET_C && POLARSSL_ENTROPY_C &&
409 POLARSSL_CTR_DRBG_C && POLARSSL_X509_CRT_PARSE_C && POLARSSL_RSA_C
410 && POLARSSL_CERTS_C */