]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/Source/WolfSSL/tests/suites.c
aeb4fd24d3ab3451a303849969b87b682999f109
[freertos] / FreeRTOS-Plus / Source / WolfSSL / tests / suites.c
1 /* suites.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 #include <stdlib.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <cyassl/ssl.h>
32 #include <tests/unit.h>
33
34
35 #define MAX_ARGS 40
36 #define MAX_COMMAND_SZ 240
37 #define MAX_SUITE_SZ 80 
38 #define NOT_BUILT_IN -123
39 #ifdef NO_OLD_TLS
40     #define VERSION_TOO_OLD -124
41 #endif
42
43 #include "examples/client/client.h"
44 #include "examples/server/server.h"
45
46
47 static CYASSL_CTX* cipherSuiteCtx = NULL;
48 static char nonblockFlag[] = "-N";
49 static char noVerifyFlag[] = "-d";
50 static char portFlag[] = "-p";
51 static char flagSep[] = " ";
52 static char svrPort[] = "0";
53
54
55 #ifdef NO_OLD_TLS
56 /* if the protocol version is less than tls 1.2 return 1, else 0 */
57 static int IsOldTlsVersion(const char* line)
58 {
59     const char* find = "-v ";
60     char* begin = strstr(line, find);
61
62     if (begin) {
63         int version = -1;
64
65         begin += 3;
66
67         version = atoi(begin);
68
69         if (version < 3)
70             return 1;
71     }
72
73     return 0;
74
75 #endif /* NO_OLD_TLS */
76
77
78 /* if the cipher suite on line is valid store in suite and return 1, else 0 */
79 static int IsValidCipherSuite(const char* line, char* suite)
80 {
81     int  found = 0;
82     int  valid = 0;
83
84     const char* find = "-l ";
85     const char* begin = strstr(line, find);
86     const char* end;
87
88     suite[0] = '\0';
89
90     if (begin) {
91         begin += 3;
92
93         end = strstr(begin, " ");
94
95         if (end) {
96             long len = end - begin;
97             if (len > MAX_SUITE_SZ) {
98                 printf("suite too long!\n");
99                 return 0;
100             }
101             memcpy(suite, begin, len);
102             suite[len] = '\0';
103         }
104         else
105             strncpy(suite, begin, MAX_SUITE_SZ);
106
107         suite[MAX_SUITE_SZ] = '\0';
108         found = 1;
109     }
110
111     if (found) {
112         if (CyaSSL_CTX_set_cipher_list(cipherSuiteCtx, suite) == SSL_SUCCESS)
113             valid = 1;
114     }
115
116     return valid;
117 }
118
119
120 static int execute_test_case(int svr_argc, char** svr_argv,
121                               int cli_argc, char** cli_argv,
122                               int addNoVerify, int addNonBlocking)
123 {
124     func_args cliArgs = {cli_argc, cli_argv, 0, NULL, NULL};
125     func_args svrArgs = {svr_argc, svr_argv, 0, NULL, NULL};
126
127     tcp_ready   ready;
128     THREAD_TYPE serverThread;
129     char        commandLine[MAX_COMMAND_SZ];
130     char        cipherSuite[MAX_SUITE_SZ+1];
131     int         i;
132     size_t      added = 0;
133     static      int tests = 1;
134
135     commandLine[0] = '\0';
136     for (i = 0; i < svr_argc; i++) {
137         added += strlen(svr_argv[i]) + 2;
138         if (added >= MAX_COMMAND_SZ) {
139             printf("server command line too long\n"); 
140             break;
141         }
142         strcat(commandLine, svr_argv[i]);
143         strcat(commandLine, flagSep);
144     }
145
146     if (IsValidCipherSuite(commandLine, cipherSuite) == 0) {
147         #ifdef DEBUG_SUITE_TESTS
148             printf("cipher suite %s not supported in build\n", cipherSuite);
149         #endif
150         return NOT_BUILT_IN;
151     }
152
153 #ifdef NO_OLD_TLS
154     if (IsOldTlsVersion(commandLine) == 1) {
155         #ifdef DEBUG_SUITE_TESTS
156             printf("protocol version on line %s is too old\n", commandLine);
157         #endif
158         return VERSION_TOO_OLD;
159     }
160 #endif
161
162     if (addNoVerify) {
163         printf("repeating test with client cert request off\n"); 
164         added += 4;   /* -d plus space plus terminator */
165         if (added >= MAX_COMMAND_SZ || svr_argc >= MAX_ARGS)
166             printf("server command line too long\n");
167         else {
168             svr_argv[svr_argc++] = noVerifyFlag;
169             svrArgs.argc = svr_argc;
170             strcat(commandLine, noVerifyFlag);
171             strcat(commandLine, flagSep);
172         }
173     }
174     if (addNonBlocking) {
175         printf("repeating test with non blocking on\n"); 
176         added += 4;   /* -N plus terminator */
177         if (added >= MAX_COMMAND_SZ || svr_argc >= MAX_ARGS)
178             printf("server command line too long\n");
179         else {
180             svr_argv[svr_argc++] = nonblockFlag;
181             svrArgs.argc = svr_argc;
182             strcat(commandLine, nonblockFlag);
183             strcat(commandLine, flagSep);
184         }
185     }
186     #ifndef USE_WINDOWS_API
187         /* add port 0 */
188         if (svr_argc + 2 > MAX_ARGS)
189             printf("cannot add the magic port number flag to server\n");
190         else
191         {
192             svr_argv[svr_argc++] = portFlag;
193             svr_argv[svr_argc++] = svrPort;
194             svrArgs.argc = svr_argc;
195         }
196     #endif
197     printf("trying server command line[%d]: %s\n", tests, commandLine);
198
199     commandLine[0] = '\0';
200     added = 0;
201     for (i = 0; i < cli_argc; i++) {
202         added += strlen(cli_argv[i]) + 2;
203         if (added >= MAX_COMMAND_SZ) {
204             printf("client command line too long\n"); 
205             break;
206         }
207         strcat(commandLine, cli_argv[i]);
208         strcat(commandLine, flagSep);
209     }
210     if (addNonBlocking) {
211         added += 4;   /* -N plus space plus terminator  */
212         if (added >= MAX_COMMAND_SZ)
213             printf("client command line too long\n");
214         else  {
215             cli_argv[cli_argc++] = nonblockFlag;
216             strcat(commandLine, nonblockFlag);
217             strcat(commandLine, flagSep);
218             cliArgs.argc = cli_argc;
219         }
220     }
221     printf("trying client command line[%d]: %s\n", tests++, commandLine);
222
223     InitTcpReady(&ready);
224
225     /* start server */
226     svrArgs.signal = &ready;
227     start_thread(server_test, &svrArgs, &serverThread);
228     wait_tcp_ready(&svrArgs);
229     #ifndef USE_WINDOWS_API
230         if (ready.port != 0)
231         {
232             if (cli_argc + 2 > MAX_ARGS)
233                 printf("cannot add the magic port number flag to client\n");
234             else {
235                 char portNumber[8];
236                 snprintf(portNumber, sizeof(portNumber), "%d", ready.port);
237                 cli_argv[cli_argc++] = portFlag;
238                 cli_argv[cli_argc++] = portNumber;
239                 cliArgs.argc = cli_argc;
240             }
241         }
242     #endif
243     /* start client */
244     client_test(&cliArgs);
245
246     /* verify results */ 
247     if (cliArgs.return_code != 0) {
248         printf("client_test failed\n");
249         exit(EXIT_FAILURE);
250     }
251
252     join_thread(serverThread);
253     if (svrArgs.return_code != 0) { 
254         printf("server_test failed\n");
255         exit(EXIT_FAILURE);
256     }
257
258     FreeTcpReady(&ready);
259     
260     return 0;
261 }
262
263 static void test_harness(void* vargs)
264 {
265     func_args* args = (func_args*)vargs;
266     char* script;
267     long  sz, len;
268     int   cliMode = 0;   /* server or client command flag, server first */
269     int   ret;
270     FILE* file;
271     char* svrArgs[MAX_ARGS];
272     int   svrArgsSz;
273     char* cliArgs[MAX_ARGS];
274     int   cliArgsSz;
275     char* cursor;
276     char* comment;
277     const char* fname = "tests/test.conf";
278
279     if (args->argc == 1) {
280         printf("notice: using default file %s\n", fname);
281     }
282     else if(args->argc != 2) {
283         printf("usage: harness [FILE]\n");
284         args->return_code = 1;
285         return;
286     }
287     else {
288         fname = args->argv[1];
289     }
290
291     file = fopen(fname, "r");
292     if (file == NULL) {
293         fprintf(stderr, "unable to open %s\n", fname);
294         args->return_code = 1;
295         return;
296     }
297     fseek(file, 0, SEEK_END);
298     sz = ftell(file);
299     rewind(file);
300     if (sz <= 0) {
301         fprintf(stderr, "%s is empty\n", fname);
302         fclose(file);
303         args->return_code = 1;
304         return;
305     }
306
307     script = (char*)malloc(sz+1);
308     if (script == 0) {
309         fprintf(stderr, "unable to allocte script buffer\n");
310         fclose(file);
311         args->return_code = 1;
312         return;
313     }
314
315     len = fread(script, 1, sz, file);
316     if (len != sz) {
317         fprintf(stderr, "read error\n");
318         fclose(file);
319         free(script);
320         args->return_code = 1;
321         return;
322     }
323     
324     fclose(file);
325     script[sz] = 0;
326
327     cursor = script;
328     svrArgsSz = 1;
329     svrArgs[0] = args->argv[0];
330     cliArgsSz = 1;
331     cliArgs[0] = args->argv[0];
332
333     while (*cursor != 0) {
334         int do_it = 0;
335
336         switch (*cursor) {
337             case '\n':
338                 /* A blank line triggers test case execution or switches
339                    to client mode if we don't have the client command yet */
340                 if (cliMode == 0)
341                     cliMode = 1;  /* switch to client mode processing */
342                 else
343                     do_it = 1;    /* Do It, we have server and client */
344                 cursor++;
345                 break;
346             case '#':
347                 /* Ignore lines that start with a #. */
348                 comment = strsep(&cursor, "\n");
349 #ifdef DEBUG_SUITE_TESTS
350                 printf("%s\n", comment);
351 #else
352                 (void)comment;
353 #endif
354                 break;
355             case '-':
356                 /* Parameters start with a -. They end in either a newline
357                  * or a space. Capture until either, save in Args list. */
358                 if (cliMode)
359                     cliArgs[cliArgsSz++] = strsep(&cursor, " \n");
360                 else
361                     svrArgs[svrArgsSz++] = strsep(&cursor, " \n");
362                 break;
363             default:
364                 /* Anything from cursor until end of line that isn't the above
365                  * is data for a paramter. Just up until the next newline in
366                  * the Args list. */
367                 if (cliMode)
368                     cliArgs[cliArgsSz++] = strsep(&cursor, "\n");
369                 else
370                     svrArgs[svrArgsSz++] = strsep(&cursor, "\n");
371                 if (*cursor == 0)  /* eof */
372                     do_it = 1; 
373         }
374
375         if (svrArgsSz == MAX_ARGS || cliArgsSz == MAX_ARGS) {
376             fprintf(stderr, "too many arguments, forcing test run\n");
377             do_it = 1;
378         }
379
380         if (do_it) {
381             ret = execute_test_case(svrArgsSz, svrArgs, cliArgsSz, cliArgs,0,0);
382             /* don't repeat if not supported in build */
383             if (ret == 0) {
384                 execute_test_case(svrArgsSz, svrArgs, cliArgsSz, cliArgs, 0, 1);
385                 execute_test_case(svrArgsSz, svrArgs, cliArgsSz, cliArgs, 1, 0);
386                 execute_test_case(svrArgsSz, svrArgs, cliArgsSz, cliArgs, 1, 1);
387             }
388             svrArgsSz = 1;
389             cliArgsSz = 1;
390             cliMode   = 0;
391         }
392     }
393
394     free(script);
395     args->return_code = 0;
396 }
397
398
399 int SuiteTest(void)
400 {
401     func_args args;
402     char argv0[2][80];
403     char* myArgv[2];
404
405     printf(" Begin Cipher Suite Tests\n");
406
407     /* setup */
408     myArgv[0] = argv0[0];
409     myArgv[1] = argv0[1];
410     args.argv = myArgv;
411     strcpy(argv0[0], "SuiteTest");
412
413     (void)test_harness;
414
415     cipherSuiteCtx = CyaSSL_CTX_new(CyaTLSv1_2_client_method());
416     if (cipherSuiteCtx == NULL) {
417         printf("can't get cipher suite ctx\n");
418         exit(EXIT_FAILURE);  
419     }
420
421     /* default case */
422     args.argc = 1;
423     printf("starting default cipher suite tests\n");
424     test_harness(&args);
425     if (args.return_code != 0) {
426         printf("error from script %d\n", args.return_code);
427         exit(EXIT_FAILURE);  
428     }
429
430     /* any extra cases will need another argument */
431     args.argc = 2;
432
433 #ifdef CYASSL_DTLS 
434     /* add dtls extra suites */
435     strcpy(argv0[1], "tests/test-dtls.conf");
436     printf("starting dtls extra cipher suite tests\n");
437     test_harness(&args);
438     if (args.return_code != 0) {
439         printf("error from script %d\n", args.return_code);
440         exit(EXIT_FAILURE);  
441     }
442 #endif
443
444     printf(" End Cipher Suite Tests\n");
445
446     CyaSSL_CTX_free(cipherSuiteCtx);
447
448     return args.return_code;
449 }
450
451