]> git.sur5r.net Git - freertos/blob - FreeRTOS-Plus/CyaSSL/examples/client/client.c
Prepare for V7.2.0 release.
[freertos] / FreeRTOS-Plus / CyaSSL / examples / client / client.c
1 /* client.c
2  *
3  * Copyright (C) 2006-2012 Sawtooth Consulting Ltd.
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
20  */
21
22 #ifdef HAVE_CONFIG_H
23     #include <config.h>
24 #endif
25
26 #include <cyassl/ssl.h>
27 #include <cyassl/test.h>
28
29 /*
30 #define TEST_RESUME 
31 */
32
33
34 #ifdef CYASSL_CALLBACKS
35     int handShakeCB(HandShakeInfo*);
36     int timeoutCB(TimeoutInfo*);
37     Timeval timeout;
38 #endif
39
40 #if defined(NON_BLOCKING) || defined(CYASSL_CALLBACKS)
41     void NonBlockingSSL_Connect(CYASSL* ssl)
42     {
43 #ifndef CYASSL_CALLBACKS
44         int ret = CyaSSL_connect(ssl);
45 #else
46         int ret = CyaSSL_connect_ex(ssl, handShakeCB, timeoutCB, timeout);
47 #endif
48         int error = CyaSSL_get_error(ssl, 0);
49         while (ret != SSL_SUCCESS && (error == SSL_ERROR_WANT_READ ||
50                                       error == SSL_ERROR_WANT_WRITE)) {
51             if (error == SSL_ERROR_WANT_READ)
52                 printf("... client would read block\n");
53             else
54                 printf("... client would write block\n");
55             #ifdef USE_WINDOWS_API 
56                 Sleep(100);
57             #else
58                 sleep(1);
59             #endif
60             #ifndef CYASSL_CALLBACKS
61                 ret = CyaSSL_connect(ssl);
62             #else
63                 ret = CyaSSL_connect_ex(ssl, handShakeCB, timeoutCB, timeout);
64             #endif
65             error = CyaSSL_get_error(ssl, 0);
66         }
67         if (ret != SSL_SUCCESS)
68             err_sys("SSL_connect failed");
69     }
70 #endif
71
72
73 static void Usage(void)
74 {
75     printf("client "    LIBCYASSL_VERSION_STRING
76            " NOTE: All files relative to CyaSSL home dir\n");
77     printf("-?          Help, print this usage\n");
78     printf("-h <host>   Host to connect to, default %s\n", yasslIP);
79     printf("-p <num>    Port to connect on, default %d\n", yasslPort);
80     printf("-v <num>    SSL version [0-3], SSLv3(0) - TLS1.2(3)), default %d\n",
81                                  CLIENT_DEFAULT_VERSION);
82     printf("-l <str>    Cipher list\n");
83     printf("-c <file>   Certificate file,           default %s\n", cliCert);
84     printf("-k <file>   Key file,                   default %s\n", cliKey);
85     printf("-A <file>   Certificate Authority file, default %s\n", caCert);
86     printf("-b <num>    Benchmark <num> connections and print stats\n");
87     printf("-s          Use pre Shared keys\n");
88     printf("-d          Disable peer checks\n");
89     printf("-g          Send server HTTP GET\n");
90     printf("-u          Use UDP DTLS\n");
91     printf("-m          Match domain name in cert\n");
92 }
93
94
95 void client_test(void* args)
96 {
97     SOCKET_T sockfd = 0;
98
99     CYASSL_METHOD*  method  = 0;
100     CYASSL_CTX*     ctx     = 0;
101     CYASSL*         ssl     = 0;
102     
103 #ifdef TEST_RESUME
104     CYASSL*         sslResume = 0;
105     CYASSL_SESSION* session = 0;
106     char         resumeMsg[] = "resuming cyassl!";
107     int          resumeSz    = sizeof(resumeMsg);
108 #endif
109
110     char msg[64] = "hello cyassl!";
111     char reply[1024];
112     int  input;
113     int  msgSz = strlen(msg);
114
115     int   port   = yasslPort;
116     char* host   = (char*)yasslIP;
117     char* domain = "www.yassl.com";
118
119     int    ch;
120     int    version = CLIENT_DEFAULT_VERSION;
121     int    usePsk   = 0;
122     int    sendGET  = 0;
123     int    benchmark = 0;
124     int    doDTLS    = 0;
125     int    matchName = 0;
126     int    doPeerCheck = 1;
127     char*  cipherList = NULL;
128     char*  verifyCert = (char*)caCert;
129     char*  ourCert    = (char*)cliCert;
130     char*  ourKey     = (char*)cliKey;
131
132     int     argc = ((func_args*)args)->argc;
133     char**  argv = ((func_args*)args)->argv;
134
135     ((func_args*)args)->return_code = -1; /* error state */
136
137     while ((ch = mygetopt(argc, argv, "?gdusmh:p:v:l:A:c:k:b:")) != -1) {
138         switch (ch) {
139             case '?' :
140                 Usage();
141                 exit(EXIT_SUCCESS);
142
143             case 'g' :
144                 sendGET = 1;
145                 break;
146
147             case 'd' :
148                 doPeerCheck = 0;
149                 break;
150
151             case 'u' :
152                 doDTLS  = 1;
153                 version = -1;  /* DTLS flag */
154                 break;
155
156             case 's' :
157                 usePsk = 1;
158                 break;
159
160             case 'm' :
161                 matchName = 1;
162                 break;
163
164             case 'h' :
165                 host   = myoptarg;
166                 domain = myoptarg;
167                 break;
168
169             case 'p' :
170                 port = atoi(myoptarg);
171                 break;
172
173             case 'v' :
174                 version = atoi(myoptarg);
175                 if (version < 0 || version > 3) {
176                     Usage();
177                     exit(MY_EX_USAGE);
178                 }
179                 if (doDTLS)
180                     version = -1;   /* DTLS flag */
181                 break;
182
183             case 'l' :
184                 cipherList = myoptarg;
185                 break;
186
187             case 'A' :
188                 verifyCert = myoptarg;
189                 break;
190
191             case 'c' :
192                 ourCert = myoptarg;
193                 break;
194
195             case 'k' :
196                 ourKey = myoptarg;
197                 break;
198
199             case 'b' :
200                 benchmark = atoi(myoptarg);
201                 if (benchmark < 0 || benchmark > 1000000) {
202                     Usage();
203                     exit(MY_EX_USAGE);
204                 }
205                 break;
206
207             default:
208                 Usage();
209                 exit(MY_EX_USAGE);
210         }
211     }
212
213     argc -= myoptind;
214     argv += myoptind;
215     myoptind = 0;      /* reset for test cases */
216
217     switch (version) {
218         case 0:
219             method = CyaSSLv3_client_method();
220             break;
221
222         case 1:
223             method = CyaTLSv1_client_method();
224             break;
225
226         case 2:
227             method = CyaTLSv1_1_client_method();
228             break;
229
230         case 3:
231             method = CyaTLSv1_2_client_method();
232             break;
233
234 #ifdef CYASSL_DTLS
235         case -1:
236             method = CyaDTLSv1_client_method();
237             break;
238 #endif
239
240         default:
241             err_sys("Bad SSL version");
242     }
243
244     if (method == NULL)
245         err_sys("unable to get method");
246
247     ctx = CyaSSL_CTX_new(method);
248     if (ctx == NULL)
249         err_sys("unable to get ctx");
250
251     if (cipherList)
252         if (CyaSSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS)
253             err_sys("can't set cipher list");
254
255 #ifndef NO_PSK
256     if (usePsk)
257         CyaSSL_CTX_set_psk_client_callback(ctx, my_psk_client_cb);
258 #endif
259
260 #ifdef OPENSSL_EXTRA
261     CyaSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
262 #endif
263
264 #if defined(CYASSL_SNIFFER) && !defined(HAVE_NTRU) && !defined(HAVE_ECC)
265     /* don't use EDH, can't sniff tmp keys */
266     if (cipherList == NULL)
267         if (CyaSSL_CTX_set_cipher_list(ctx, "AES256-SHA") != SSL_SUCCESS)
268             err_sys("can't set cipher list");
269 #endif
270
271 #ifdef USER_CA_CB
272     CyaSSL_CTX_SetCACb(ctx, CaCb);
273 #endif
274
275 #ifdef VERIFY_CALLBACK
276     CyaSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, myVerify);
277 #endif
278
279     if (CyaSSL_CTX_use_certificate_file(ctx, ourCert, SSL_FILETYPE_PEM)
280                                      != SSL_SUCCESS)
281         err_sys("can't load client cert file, check file and run from"
282                 " CyaSSL home dir");
283
284     if (CyaSSL_CTX_use_PrivateKey_file(ctx, ourKey, SSL_FILETYPE_PEM)
285                                      != SSL_SUCCESS)
286         err_sys("can't load client cert file, check file and run from"
287                 " CyaSSL home dir");    
288
289     if (CyaSSL_CTX_load_verify_locations(ctx, verifyCert, 0) != SSL_SUCCESS)
290             err_sys("can't load ca file, Please run from CyaSSL home dir");
291
292     if (doPeerCheck == 0)
293         CyaSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
294
295     if (benchmark) {
296         /* time passed in number of connects give average */
297         int times = benchmark;
298         int i = 0;
299
300         double start = current_time(), avg;
301
302         for (i = 0; i < times; i++) {
303             tcp_connect(&sockfd, host, port, doDTLS);
304             ssl = CyaSSL_new(ctx);
305             CyaSSL_set_fd(ssl, sockfd);
306             if (CyaSSL_connect(ssl) != SSL_SUCCESS)
307                 err_sys("SSL_connect failed");
308
309             CyaSSL_shutdown(ssl);
310             CyaSSL_free(ssl);
311             CloseSocket(sockfd);
312         }
313         avg = current_time() - start;
314         avg /= times;
315         avg *= 1000;   /* milliseconds */
316         printf("CyaSSL_connect avg took: %8.3f milliseconds\n", avg);
317
318         CyaSSL_CTX_free(ctx);
319         ((func_args*)args)->return_code = 0;
320
321         exit(EXIT_SUCCESS);
322     }
323
324     tcp_connect(&sockfd, host, port, doDTLS);
325     ssl = CyaSSL_new(ctx);
326     if (ssl == NULL)
327         err_sys("unable to get SSL object");
328     CyaSSL_set_fd(ssl, sockfd);
329 #ifdef HAVE_CRL
330     if (CyaSSL_EnableCRL(ssl, CYASSL_CRL_CHECKALL) != SSL_SUCCESS)
331         err_sys("can't enable crl check");
332     if (CyaSSL_LoadCRL(ssl, crlPemDir, SSL_FILETYPE_PEM, 0) != SSL_SUCCESS)
333         err_sys("can't load crl, check crlfile and date validity");
334     if (CyaSSL_SetCRL_Cb(ssl, CRL_CallBack) != SSL_SUCCESS)
335         err_sys("can't set crl callback");
336 #endif
337     if (matchName && doPeerCheck)
338         CyaSSL_check_domain_name(ssl, domain);
339 #ifdef NON_BLOCKING
340     tcp_set_nonblocking(&sockfd);
341     NonBlockingSSL_Connect(ssl);
342 #else
343     #ifndef CYASSL_CALLBACKS
344         if (CyaSSL_connect(ssl) != SSL_SUCCESS) {/* see note at top of README */
345             int  err = CyaSSL_get_error(ssl, 0);
346             char buffer[80];
347             printf("err = %d, %s\n", err, CyaSSL_ERR_error_string(err, buffer));
348             err_sys("SSL_connect failed");/* if you're getting an error here  */
349         }
350     #else
351         timeout.tv_sec  = 2;
352         timeout.tv_usec = 0;
353         NonBlockingSSL_Connect(ssl);  /* will keep retrying on timeout */
354     #endif
355 #endif
356     showPeer(ssl);
357     
358     if (sendGET) {
359         printf("SSL connect ok, sending GET...\n");
360         msgSz = 28;
361         strncpy(msg, "GET /index.html HTTP/1.0\r\n\r\n", msgSz);
362     }
363     if (CyaSSL_write(ssl, msg, msgSz) != msgSz)
364         err_sys("SSL_write failed");
365
366     input = CyaSSL_read(ssl, reply, sizeof(reply));
367     if (input > 0) {
368         reply[input] = 0;
369         printf("Server response: %s\n", reply);
370
371         if (sendGET) {  /* get html */
372             while (1) {
373                 input = CyaSSL_read(ssl, reply, sizeof(reply));
374                 if (input > 0) {
375                     reply[input] = 0;
376                     printf("%s\n", reply);
377                 }
378                 else
379                     break;
380             }
381         }
382     }
383   
384 #ifdef TEST_RESUME
385     if (doDTLS) {
386         strncpy(msg, "break", 6);
387         msgSz = (int)strlen(msg);
388         /* try to send session close */
389         CyaSSL_write(ssl, msg, msgSz);
390     }
391     session   = CyaSSL_get_session(ssl);
392     sslResume = CyaSSL_new(ctx);
393 #endif
394
395     CyaSSL_shutdown(ssl);
396     CyaSSL_free(ssl);
397     CloseSocket(sockfd);
398
399 #ifdef TEST_RESUME
400     if (doDTLS) {
401         #ifdef USE_WINDOWS_API 
402             Sleep(500);
403         #else
404             sleep(1);
405         #endif
406     }
407     tcp_connect(&sockfd, host, port);
408     CyaSSL_set_fd(sslResume, sockfd);
409     CyaSSL_set_session(sslResume, session);
410    
411     showPeer(sslResume); 
412     if (CyaSSL_connect(sslResume) != SSL_SUCCESS) err_sys("SSL resume failed");
413
414 #ifdef OPENSSL_EXTRA
415     if (CyaSSL_session_reused(sslResume))
416         printf("reused session id\n");
417     else
418         printf("didn't reuse session id!!!\n");
419 #endif
420   
421     if (CyaSSL_write(sslResume, resumeMsg, resumeSz) != resumeSz)
422         err_sys("SSL_write failed");
423
424     input = CyaSSL_read(sslResume, reply, sizeof(reply));
425     if (input > 0) {
426         reply[input] = 0;
427         printf("Server resume response: %s\n", reply);
428     }
429
430     /* try to send session break */
431     CyaSSL_write(sslResume, msg, msgSz); 
432
433     CyaSSL_shutdown(sslResume);
434     CyaSSL_free(sslResume);
435 #endif /* TEST_RESUME */
436
437     CyaSSL_CTX_free(ctx);
438     CloseSocket(sockfd);
439
440     ((func_args*)args)->return_code = 0;
441 }
442
443
444 /* so overall tests can pull in test function */
445 #ifndef NO_MAIN_DRIVER
446
447     int main(int argc, char** argv)
448     {
449         func_args args;
450
451         StartTCP();
452
453         args.argc = argc;
454         args.argv = argv;
455
456         CyaSSL_Init();
457 #ifdef DEBUG_CYASSL
458         CyaSSL_Debugging_ON();
459 #endif
460         if (CurrentDir("client") || CurrentDir("build"))
461             ChangeDirBack(2);
462    
463         client_test(&args);
464         CyaSSL_Cleanup();
465
466         return args.return_code;
467     }
468
469     int myoptind = 0;
470     char* myoptarg = NULL;
471
472 #endif /* NO_MAIN_DRIVER */
473
474
475
476 #ifdef CYASSL_CALLBACKS
477
478     int handShakeCB(HandShakeInfo* info)
479     {
480
481         return 0;
482     }
483
484
485     int timeoutCB(TimeoutInfo* info)
486     {
487
488         return 0;
489     }
490
491 #endif
492
493