]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/WolfSSL/examples/server/server.c
43a5ad7fb8c4af25cdafa812d62c4fee7d4cb413
[freertos] / FreeRTOS-Plus / Source / WolfSSL / examples / server / server.c
1 /* server.c
2  *
3  * Copyright (C) 2006-2014 wolfSSL Inc.
4  *
5  * This file is part of CyaSSL.
6  *
7  * CyaSSL is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * CyaSSL is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #ifdef HAVE_CONFIG_H
23     #include <config.h>
24 #endif
25
26 #include <cyassl/ctaocrypt/settings.h>
27
28 #if !defined(CYASSL_TRACK_MEMORY) && !defined(NO_MAIN_DRIVER)
29     /* in case memory tracker wants stats */
30     #define CYASSL_TRACK_MEMORY
31 #endif
32
33 #if defined(CYASSL_MDK_ARM)
34         #include <stdio.h>
35         #include <string.h>
36
37         #if defined(CYASSL_MDK5)
38             #include "cmsis_os.h"
39             #include "rl_fs.h" 
40             #include "rl_net.h" 
41         #else
42             #include "rtl.h"
43         #endif
44
45         #include "cyassl_MDK_ARM.h"
46 #endif
47 #include <cyassl/openssl/ssl.h>
48 #include <cyassl/test.h>
49
50 #include "examples/server/server.h"
51
52
53 #ifdef CYASSL_CALLBACKS
54     int srvHandShakeCB(HandShakeInfo*);
55     int srvTimeoutCB(TimeoutInfo*);
56     Timeval srvTo;
57 #endif
58
59 static void NonBlockingSSL_Accept(SSL* ssl)
60 {
61 #ifndef CYASSL_CALLBACKS
62     int ret = SSL_accept(ssl);
63 #else
64     int ret = CyaSSL_accept_ex(ssl, srvHandShakeCB, srvTimeoutCB, srvTo);
65 #endif
66     int error = SSL_get_error(ssl, 0);
67     SOCKET_T sockfd = (SOCKET_T)CyaSSL_get_fd(ssl);
68     int select_ret;
69
70     while (ret != SSL_SUCCESS && (error == SSL_ERROR_WANT_READ ||
71                                   error == SSL_ERROR_WANT_WRITE)) {
72         int currTimeout = 1;
73
74         if (error == SSL_ERROR_WANT_READ)
75             printf("... server would read block\n");
76         else
77             printf("... server would write block\n");
78
79 #ifdef CYASSL_DTLS
80         currTimeout = CyaSSL_dtls_get_current_timeout(ssl);
81 #endif
82         select_ret = tcp_select(sockfd, currTimeout);
83
84         if ((select_ret == TEST_RECV_READY) ||
85                                         (select_ret == TEST_ERROR_READY)) {
86             #ifndef CYASSL_CALLBACKS
87                 ret = SSL_accept(ssl);
88             #else
89                 ret = CyaSSL_accept_ex(ssl,
90                                     srvHandShakeCB, srvTimeoutCB, srvTo);
91             #endif
92             error = SSL_get_error(ssl, 0);
93         }
94         else if (select_ret == TEST_TIMEOUT && !CyaSSL_dtls(ssl)) {
95             error = SSL_ERROR_WANT_READ;
96         }
97 #ifdef CYASSL_DTLS
98         else if (select_ret == TEST_TIMEOUT && CyaSSL_dtls(ssl) &&
99                                             CyaSSL_dtls_got_timeout(ssl) >= 0) {
100             error = SSL_ERROR_WANT_READ;
101         }
102 #endif
103         else {
104             error = SSL_FATAL_ERROR;
105         }
106     }
107     if (ret != SSL_SUCCESS)
108         err_sys("SSL_accept failed");
109 }
110
111
112 static void Usage(void)
113 {
114     printf("server "    LIBCYASSL_VERSION_STRING
115            " NOTE: All files relative to CyaSSL home dir\n");
116     printf("-?          Help, print this usage\n");
117     printf("-p <num>    Port to listen on, not 0, default %d\n", yasslPort);
118     printf("-v <num>    SSL version [0-3], SSLv3(0) - TLS1.2(3)), default %d\n",
119                                  SERVER_DEFAULT_VERSION);
120     printf("-l <str>    Cipher list\n");
121     printf("-c <file>   Certificate file,           default %s\n", svrCert);
122     printf("-k <file>   Key file,                   default %s\n", svrKey);
123     printf("-A <file>   Certificate Authority file, default %s\n", cliCert);
124     printf("-d          Disable client cert check\n");
125     printf("-b          Bind to any interface instead of localhost only\n");
126     printf("-s          Use pre Shared keys\n");
127     printf("-t          Track CyaSSL memory use\n");
128     printf("-u          Use UDP DTLS,"
129            " add -v 2 for DTLSv1 (default), -v 3 for DTLSv1.2\n");
130     printf("-f          Fewer packets/group messages\n");
131     printf("-N          Use Non-blocking sockets\n");
132     printf("-S <str>    Use Host Name Indication\n");
133 #ifdef HAVE_OCSP
134     printf("-o          Perform OCSP lookup on peer certificate\n");
135     printf("-O <url>    Perform OCSP lookup using <url> as responder\n");
136 #endif
137 #ifdef HAVE_PK_CALLBACKS 
138     printf("-P          Public Key Callbacks\n");
139 #endif
140 }
141
142 THREAD_RETURN CYASSL_THREAD server_test(void* args)
143 {
144     SOCKET_T sockfd   = 0;
145     SOCKET_T clientfd = 0;
146
147     SSL_METHOD* method = 0;
148     SSL_CTX*    ctx    = 0;
149     SSL*        ssl    = 0;
150
151     char   msg[] = "I hear you fa shizzle!";
152     char   input[80];
153     int    idx;
154     int    ch;
155     int    version = SERVER_DEFAULT_VERSION;
156     int    doCliCertCheck = 1;
157     int    useAnyAddr = 0;
158     word16 port = yasslPort;
159     int    usePsk = 0;
160     int    doDTLS = 0;
161     int    useNtruKey   = 0;
162     int    nonBlocking  = 0;
163     int    trackMemory  = 0;
164     int    fewerPackets = 0;
165     int    pkCallbacks  = 0;
166     char*  cipherList = NULL;
167     const char* verifyCert = cliCert;
168     const char* ourCert    = svrCert;
169     const char* ourKey     = svrKey;
170     int    argc = ((func_args*)args)->argc;
171     char** argv = ((func_args*)args)->argv;
172
173 #ifdef HAVE_SNI
174     char*  sniHostName = NULL;
175 #endif
176
177 #ifdef HAVE_OCSP
178     int    useOcsp  = 0;
179     char*  ocspUrl  = NULL;
180 #endif
181
182     ((func_args*)args)->return_code = -1; /* error state */
183
184 #ifdef NO_RSA
185     verifyCert = (char*)cliEccCert;
186     ourCert    = (char*)eccCert;
187     ourKey     = (char*)eccKey;
188 #endif
189     (void)trackMemory;
190     (void)pkCallbacks;
191
192     while ((ch = mygetopt(argc, argv, "?dbstnNufPp:v:l:A:c:k:S:oO:")) != -1) {
193         switch (ch) {
194             case '?' :
195                 Usage();
196                 exit(EXIT_SUCCESS);
197
198             case 'd' :
199                 doCliCertCheck = 0;
200                 break;
201
202             case 'b' :
203                 useAnyAddr = 1;
204                 break;
205
206             case 's' :
207                 usePsk = 1;
208                 break;
209
210             case 't' :
211             #ifdef USE_CYASSL_MEMORY
212                 trackMemory = 1;
213             #endif
214                 break;
215
216             case 'n' :
217                 useNtruKey = 1;
218                 break;
219
220             case 'u' :
221                 doDTLS  = 1;
222                 break;
223
224             case 'f' :
225                 fewerPackets = 1;
226                 break;
227
228             case 'P' :
229             #ifdef HAVE_PK_CALLBACKS 
230                 pkCallbacks = 1;
231             #endif
232                 break;
233
234             case 'p' :
235                 port = (word16)atoi(myoptarg);
236                 #if !defined(NO_MAIN_DRIVER) || defined(USE_WINDOWS_API)
237                     if (port == 0)
238                         err_sys("port number cannot be 0");
239                 #endif
240                 break;
241
242             case 'v' :
243                 version = atoi(myoptarg);
244                 if (version < 0 || version > 3) {
245                     Usage();
246                     exit(MY_EX_USAGE);
247                 }
248                 break;
249
250             case 'l' :
251                 cipherList = myoptarg;
252                 break;
253
254             case 'A' :
255                 verifyCert = myoptarg;
256                 break;
257
258             case 'c' :
259                 ourCert = myoptarg;
260                 break;
261
262             case 'k' :
263                 ourKey = myoptarg;
264                 break;
265
266             case 'N':
267                 nonBlocking = 1;
268                 break;
269
270             case 'S' :
271                 #ifdef HAVE_SNI
272                     sniHostName = myoptarg;
273                 #endif
274                 break;
275
276             case 'o' :
277                 #ifdef HAVE_OCSP
278                     useOcsp = 1;
279                 #endif
280                 break;
281
282             case 'O' :
283                 #ifdef HAVE_OCSP
284                     useOcsp = 1;
285                     ocspUrl = myoptarg;
286                 #endif
287                 break;
288
289             default:
290                 Usage();
291                 exit(MY_EX_USAGE);
292         }
293     }
294
295     myoptind = 0;      /* reset for test cases */
296
297     /* sort out DTLS versus TLS versions */
298     if (version == CLIENT_INVALID_VERSION) {
299         if (doDTLS)
300             version = CLIENT_DTLS_DEFAULT_VERSION;
301         else
302             version = CLIENT_DEFAULT_VERSION;
303     }
304     else {
305         if (doDTLS) {
306             if (version == 3)
307                 version = -2;
308             else
309                 version = -1;
310         }
311     }
312
313 #ifdef USE_CYASSL_MEMORY
314     if (trackMemory)
315         InitMemoryTracker(); 
316 #endif
317
318     switch (version) {
319 #ifndef NO_OLD_TLS
320         case 0:
321             method = SSLv3_server_method();
322             break;
323
324     #ifndef NO_TLS
325         case 1:
326             method = TLSv1_server_method();
327             break;
328
329
330         case 2:
331             method = TLSv1_1_server_method();
332             break;
333
334         #endif
335 #endif
336
337 #ifndef NO_TLS
338         case 3:
339             method = TLSv1_2_server_method();
340             break;
341 #endif
342                 
343 #ifdef CYASSL_DTLS
344         case -1:
345             method = DTLSv1_server_method();
346             break;
347
348         case -2:
349             method = DTLSv1_2_server_method();
350             break;
351 #endif
352
353         default:
354             err_sys("Bad SSL version");
355     }
356
357     if (method == NULL)
358         err_sys("unable to get method");
359
360     ctx = SSL_CTX_new(method);
361     if (ctx == NULL)
362         err_sys("unable to get ctx");
363
364     if (cipherList)
365         if (SSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS)
366             err_sys("server can't set cipher list 1");
367
368 #ifdef CYASSL_LEANPSK
369     usePsk = 1;
370 #endif
371
372 #if defined(NO_RSA) && !defined(HAVE_ECC)
373     usePsk = 1;
374 #endif
375
376     if (fewerPackets)
377         CyaSSL_CTX_set_group_messages(ctx);
378
379 #if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
380     SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
381 #endif
382
383 #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
384     if (!usePsk) {
385         if (SSL_CTX_use_certificate_file(ctx, ourCert, SSL_FILETYPE_PEM)
386                                          != SSL_SUCCESS)
387             err_sys("can't load server cert file, check file and run from"
388                     " CyaSSL home dir");
389     }
390 #endif
391
392 #ifdef HAVE_NTRU
393     if (useNtruKey) {
394         if (CyaSSL_CTX_use_NTRUPrivateKey_file(ctx, ourKey)
395                                                != SSL_SUCCESS)
396             err_sys("can't load ntru key file, "
397                     "Please run from CyaSSL home dir");
398     }
399 #endif
400
401 #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
402     if (!useNtruKey && !usePsk) {
403         if (SSL_CTX_use_PrivateKey_file(ctx, ourKey, SSL_FILETYPE_PEM)
404                                          != SSL_SUCCESS)
405             err_sys("can't load server private key file, check file and run "
406                 "from CyaSSL home dir");
407     }
408 #endif
409
410     if (usePsk) {
411 #ifndef NO_PSK
412         SSL_CTX_set_psk_server_callback(ctx, my_psk_server_cb);
413         SSL_CTX_use_psk_identity_hint(ctx, "cyassl server");
414         if (cipherList == NULL) {
415             const char *defaultCipherList;
416             #ifdef HAVE_NULL_CIPHER
417                 defaultCipherList = "PSK-NULL-SHA256";
418             #else
419                 defaultCipherList = "PSK-AES128-CBC-SHA256";
420             #endif
421             if (SSL_CTX_set_cipher_list(ctx, defaultCipherList) != SSL_SUCCESS)
422                 err_sys("server can't set cipher list 2");
423         }
424 #endif
425     }
426
427 #if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
428     /* if not using PSK, verify peer with certs */
429     if (doCliCertCheck && usePsk == 0) {
430         SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER |
431                                 SSL_VERIFY_FAIL_IF_NO_PEER_CERT,0);
432         if (SSL_CTX_load_verify_locations(ctx, verifyCert, 0) != SSL_SUCCESS)
433             err_sys("can't load ca file, Please run from CyaSSL home dir");
434     }
435 #endif
436
437 #if defined(CYASSL_SNIFFER) && !defined(HAVE_NTRU) && !defined(HAVE_ECC)
438     /* don't use EDH, can't sniff tmp keys */
439     if (cipherList == NULL) {
440         if (SSL_CTX_set_cipher_list(ctx, "AES256-SHA256") != SSL_SUCCESS)
441             err_sys("server can't set cipher list 3");
442     }
443 #endif
444
445 #ifdef HAVE_SNI
446     if (sniHostName)
447         if (CyaSSL_CTX_UseSNI(ctx, CYASSL_SNI_HOST_NAME, sniHostName,
448                                            XSTRLEN(sniHostName)) != SSL_SUCCESS)
449             err_sys("UseSNI failed");
450 #endif
451
452     ssl = SSL_new(ctx);
453     if (ssl == NULL)
454         err_sys("unable to get SSL");
455
456 #ifdef HAVE_CRL
457     CyaSSL_EnableCRL(ssl, 0);
458     CyaSSL_LoadCRL(ssl, crlPemDir, SSL_FILETYPE_PEM, CYASSL_CRL_MONITOR |
459                                                      CYASSL_CRL_START_MON);
460     CyaSSL_SetCRL_Cb(ssl, CRL_CallBack);
461 #endif
462 #ifdef HAVE_OCSP
463     if (useOcsp) {
464         if (ocspUrl != NULL) {
465             CyaSSL_CTX_SetOCSP_OverrideURL(ctx, ocspUrl);
466             CyaSSL_CTX_EnableOCSP(ctx, CYASSL_OCSP_NO_NONCE
467                                                     | CYASSL_OCSP_URL_OVERRIDE);
468         }
469         else
470             CyaSSL_CTX_EnableOCSP(ctx, CYASSL_OCSP_NO_NONCE);
471     }
472 #endif
473 #ifdef HAVE_PK_CALLBACKS
474     if (pkCallbacks)
475         SetupPkCallbacks(ctx, ssl);
476 #endif
477
478     tcp_accept(&sockfd, &clientfd, (func_args*)args, port, useAnyAddr, doDTLS);
479     if (!doDTLS) 
480         CloseSocket(sockfd);
481
482     SSL_set_fd(ssl, clientfd);
483     if (usePsk == 0 || cipherList != NULL) {
484         #if !defined(NO_FILESYSTEM) && !defined(NO_DH)
485             CyaSSL_SetTmpDH_file(ssl, dhParam, SSL_FILETYPE_PEM);
486         #elif !defined(NO_DH)
487             SetDH(ssl);  /* repick suites with DHE, higher priority than PSK */
488         #endif
489     }
490
491 #ifndef CYASSL_CALLBACKS
492     if (nonBlocking) {
493         CyaSSL_set_using_nonblock(ssl, 1);
494         tcp_set_nonblocking(&clientfd);
495         NonBlockingSSL_Accept(ssl);
496     } else if (SSL_accept(ssl) != SSL_SUCCESS) {
497         int err = SSL_get_error(ssl, 0);
498         char buffer[CYASSL_MAX_ERROR_SZ];
499         printf("error = %d, %s\n", err, ERR_error_string(err, buffer));
500         err_sys("SSL_accept failed");
501     }
502 #else
503     NonBlockingSSL_Accept(ssl);
504 #endif
505     showPeer(ssl);
506
507     idx = SSL_read(ssl, input, sizeof(input)-1);
508     if (idx > 0) {
509         input[idx] = 0;
510         printf("Client message: %s\n", input);
511
512     }
513     else if (idx < 0) {
514         int readErr = SSL_get_error(ssl, 0);
515         if (readErr != SSL_ERROR_WANT_READ)
516             err_sys("SSL_read failed");
517     }
518
519     if (SSL_write(ssl, msg, sizeof(msg)) != sizeof(msg))
520         err_sys("SSL_write failed");
521         
522     #if defined(CYASSL_MDK_SHELL) && defined(HAVE_MDK_RTX)
523         os_dly_wait(500) ;
524     #endif
525
526     SSL_shutdown(ssl);
527     SSL_free(ssl);
528     SSL_CTX_free(ctx);
529     
530     CloseSocket(clientfd);
531     ((func_args*)args)->return_code = 0;
532
533 #ifdef USE_CYASSL_MEMORY
534     if (trackMemory)
535         ShowMemoryTracker();
536 #endif /* USE_CYASSL_MEMORY */
537
538     return 0;
539 }
540
541
542 /* so overall tests can pull in test function */
543 #ifndef NO_MAIN_DRIVER
544
545     int main(int argc, char** argv)
546     {
547         func_args args;
548
549 #ifdef HAVE_CAVIUM
550         int ret = OpenNitroxDevice(CAVIUM_DIRECT, CAVIUM_DEV_ID);
551         if (ret != 0)
552             err_sys("Cavium OpenNitroxDevice failed");
553 #endif /* HAVE_CAVIUM */
554
555         StartTCP();
556
557         args.argc = argc;
558         args.argv = argv;
559
560         CyaSSL_Init();
561 #if defined(DEBUG_CYASSL) && !defined(CYASSL_MDK_SHELL)
562         CyaSSL_Debugging_ON();
563 #endif
564         if (CurrentDir("server"))
565             ChangeDirBack(2);
566         else if (CurrentDir("Debug") || CurrentDir("Release"))
567             ChangeDirBack(3);
568    
569 #ifdef HAVE_STACK_SIZE
570         StackSizeCheck(&args, server_test);
571 #else 
572         server_test(&args);
573 #endif
574         CyaSSL_Cleanup();
575
576 #ifdef HAVE_CAVIUM
577         CspShutdown(CAVIUM_DEV_ID);
578 #endif
579         return args.return_code;
580     }
581
582     int myoptind = 0;
583     char* myoptarg = NULL;
584
585 #endif /* NO_MAIN_DRIVER */
586
587
588 #ifdef CYASSL_CALLBACKS
589
590     int srvHandShakeCB(HandShakeInfo* info)
591     {
592         (void)info;
593         return 0;
594     }
595
596
597     int srvTimeoutCB(TimeoutInfo* info)
598     {
599         (void)info;
600         return 0;
601     }
602
603 #endif
604