source: MondoRescue/branches/3.3/mindi-busybox/networking/ssl_helper-wolfssl/ssl_helper.c@ 3723

Last change on this file since 3723 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

  • Property svn:eol-style set to native
File size: 12.1 KB
Line 
1/*
2 * Adapted from:
3 *
4 * client.c
5 *
6 * Copyright (C) 2006-2015 wolfSSL Inc.
7 *
8 * This file is part of wolfSSL. (formerly known as CyaSSL)
9 *
10 * wolfSSL is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * wolfSSL is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23 */
24#include <stdlib.h>
25#include <unistd.h>
26#include <stdarg.h>
27#include <string.h>
28#include <errno.h>
29#include <fcntl.h>
30#include <stdio.h>
31#include <time.h>
32#include <poll.h>
33#include <sys/socket.h>
34
35#include <wolfssl/wolfcrypt/types.h>
36#include <wolfssl/ssl.h>
37
38#if 0
39# define dbg(...) say(__VA_ARGS__)
40#else
41# define dbg(...) ((void)0)
42#endif
43
44static ssize_t safe_write(int fd, const void *buf, size_t count)
45{
46 ssize_t n;
47
48 do {
49 n = write(fd, buf, count);
50 } while (n < 0 && errno == EINTR);
51
52 return n;
53}
54
55static ssize_t full_write(int fd, const void *buf, size_t len)
56{
57 ssize_t cc;
58 ssize_t total;
59
60 total = 0;
61
62 while (len) {
63 cc = safe_write(fd, buf, len);
64
65 if (cc < 0) {
66 if (total) {
67 /* we already wrote some! */
68 /* user can do another write to know the error code */
69 return total;
70 }
71 return cc; /* write() returns -1 on failure. */
72 }
73
74 total += cc;
75 buf = ((const char *)buf) + cc;
76 len -= cc;
77 }
78
79 return total;
80}
81
82static void say(const char *s, ...)
83{
84 char buf[256];
85 va_list p;
86 int sz;
87
88 va_start(p, s);
89 sz = vsnprintf(buf, sizeof(buf), s, p);
90 full_write(STDERR_FILENO, buf, sz >= 0 && sz < sizeof(buf) ? sz : strlen(buf));
91 va_end(p);
92}
93
94static void die(const char *s, ...)
95{
96 char buf[256];
97 va_list p;
98 int sz;
99
100 va_start(p, s);
101 sz = vsnprintf(buf, sizeof(buf), s, p);
102 full_write(STDERR_FILENO, buf, sz >= 0 && sz < sizeof(buf) ? sz : strlen(buf));
103 exit(1);
104 va_end(p);
105}
106
107static void err_sys(const char *msg)
108{
109 die("%s\n", msg);
110}
111
112/* ==== */
113
114#if 0
115static void showPeer(WOLFSSL* ssl)
116{
117 WOLFSSL_CIPHER* cipher;
118 WOLFSSL_X509* peer = wolfSSL_get_peer_certificate(ssl);
119 if (peer)
120 ShowX509(peer, "peer's cert info:");
121 else
122 say("peer has no cert!\n");
123 say("SSL version is %s\n", wolfSSL_get_version(ssl));
124
125 cipher = wolfSSL_get_current_cipher(ssl);
126 say("SSL cipher suite is %s\n", wolfSSL_CIPHER_get_name(cipher));
127
128 {
129 WOLFSSL_X509_CHAIN* chain = wolfSSL_get_peer_chain(ssl);
130 int count = wolfSSL_get_chain_count(chain);
131 int i;
132
133 for (i = 0; i < count; i++) {
134 int length;
135 unsigned char buffer[3072];
136 WOLFSSL_X509* chainX509;
137
138 wolfSSL_get_chain_cert_pem(chain, i, buffer, sizeof(buffer), &length);
139 buffer[length] = 0;
140 say("cert %d has length %d data = \n%s\n", i, length, buffer);
141
142 chainX509 = wolfSSL_get_chain_X509(chain, i);
143 if (chainX509)
144 ShowX509(chainX509, "session cert info:");
145 else
146 say("get_chain_X509 failed\n");
147 wolfSSL_FreeX509(chainX509);
148 }
149 }
150}
151#endif
152
153WOLFSSL *prepare(int sockfd)
154{
155 WOLFSSL_METHOD* method;
156 WOLFSSL_CTX* ctx;
157 WOLFSSL* ssl;
158
159 wolfSSL_Init();
160
161 method = wolfTLSv1_1_client_method();
162 if (method == NULL)
163 err_sys("out of memory");
164 ctx = wolfSSL_CTX_new(method);
165 if (ctx == NULL)
166 err_sys("out of memory");
167// if (cipherList)
168// if (wolfSSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS)
169// err_sys("client can't set cipher list 1");
170
171// if (fewerPackets)
172// wolfSSL_CTX_set_group_messages(ctx);
173
174//#ifndef NO_DH
175// wolfSSL_CTX_SetMinDhKey_Sz(ctx, (word16)minDhKeyBits);
176//#endif
177
178// if (usePsk) {
179// wolfSSL_CTX_set_psk_client_callback(ctx, my_psk_client_cb);
180// if (cipherList == NULL) {
181// const char *defaultCipherList;
182//#if defined(HAVE_AESGCM) && !defined(NO_DH)
183// defaultCipherList = "DHE-PSK-AES128-GCM-SHA256";
184//#elif defined(HAVE_NULL_CIPHER)
185// defaultCipherList = "PSK-NULL-SHA256";
186//#else
187// defaultCipherList = "PSK-AES128-CBC-SHA256";
188//#endif
189// if (wolfSSL_CTX_set_cipher_list(ctx,defaultCipherList) != SSL_SUCCESS)
190// err_sys("client can't set cipher list 2");
191// }
192// useClientCert = 0;
193// }
194
195// if (useAnon) {
196// if (cipherList == NULL) {
197// wolfSSL_CTX_allow_anon_cipher(ctx);
198// if (wolfSSL_CTX_set_cipher_list(ctx,"ADH-AES128-SHA") != SSL_SUCCESS)
199// err_sys("client can't set cipher list 4");
200// }
201// useClientCert = 0;
202// }
203
204//#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER)
205// wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
206//#endif
207
208// if (useOcsp) {
209// if (ocspUrl != NULL) {
210// wolfSSL_CTX_SetOCSP_OverrideURL(ctx, ocspUrl);
211// wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_NO_NONCE
212// | WOLFSSL_OCSP_URL_OVERRIDE);
213// }
214// else
215// wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_NO_NONCE);
216// }
217//
218//#ifdef USER_CA_CB
219// wolfSSL_CTX_SetCACb(ctx, CaCb);
220//#endif
221//
222//#ifdef VERIFY_CALLBACK
223// wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, myVerify);
224//#endif
225//#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS)
226// if (useClientCert) {
227// if (wolfSSL_CTX_use_certificate_chain_file(ctx, ourCert) != SSL_SUCCESS)
228// err_sys("can't load client cert file, check file and run from"
229// " wolfSSL home dir");
230// if (wolfSSL_CTX_use_PrivateKey_file(ctx, ourKey, SSL_FILETYPE_PEM) != SSL_SUCCESS)
231// err_sys("can't load client private key file, check file and run "
232// "from wolfSSL home dir");
233// }
234//
235// if (!usePsk && !useAnon) {
236// if (wolfSSL_CTX_load_verify_locations(ctx, verifyCert,0) != SSL_SUCCESS)
237// err_sys("can't load ca file, Please run from wolfSSL home dir");
238//#ifdef HAVE_ECC
239// /* load ecc verify too, echoserver uses it by default w/ ecc */
240// if (wolfSSL_CTX_load_verify_locations(ctx, eccCert, 0) != SSL_SUCCESS)
241// err_sys("can't load ecc ca file, Please run from wolfSSL home dir");
242//#endif
243// }
244//#endif /* !NO_FILESYSTEM && !NO_CERTS */
245
246//#if !defined(NO_CERTS)
247// if (!usePsk && !useAnon && doPeerCheck == 0)
248// wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
249// if (!usePsk && !useAnon && overrideDateErrors == 1)
250// wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, myDateCb);
251//#endif
252
253 wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
254
255//#ifdef HAVE_SNI
256// if (sniHostName)
257// if (wolfSSL_CTX_UseSNI(ctx, 0, sniHostName, XSTRLEN(sniHostName)) != SSL_SUCCESS)
258// err_sys("UseSNI failed");
259//#endif
260
261//#ifdef HAVE_MAX_FRAGMENT
262// if (maxFragment)
263// if (wolfSSL_CTX_UseMaxFragment(ctx, maxFragment) != SSL_SUCCESS)
264// err_sys("UseMaxFragment failed");
265//#endif
266//#ifdef HAVE_TRUNCATED_HMAC
267// if (truncatedHMAC)
268// if (wolfSSL_CTX_UseTruncatedHMAC(ctx) != SSL_SUCCESS)
269// err_sys("UseTruncatedHMAC failed");
270//#endif
271//#ifdef HAVE_SESSION_TICKET
272// if (wolfSSL_CTX_UseSessionTicket(ctx) != SSL_SUCCESS)
273// err_sys("UseSessionTicket failed");
274//#endif
275
276//#if defined(WOLFSSL_MDK_ARM)
277// wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0);
278//#endif
279
280 ssl = wolfSSL_new(ctx);
281 if (ssl == NULL)
282 err_sys("out of memory");
283
284//#ifdef HAVE_SESSION_TICKET
285// wolfSSL_set_SessionTicket_cb(ssl, sessionTicketCB, (void*)"initial session");
286//#endif
287
288// if (doDTLS) {
289// SOCKADDR_IN_T addr;
290// build_addr(&addr, host, port, 1);
291// wolfSSL_dtls_set_peer(ssl, &addr, sizeof(addr));
292// tcp_socket(&sockfd, 1);
293// } wlse {
294// tcp_connect(&sockfd, host, port, 0);
295// }
296
297//#ifdef HAVE_POLY1305
298// /* use old poly to connect with google server */
299// if (!XSTRNCMP(domain, "www.google.com", 14)) {
300// if (wolfSSL_use_old_poly(ssl, 1) != 0)
301// err_sys("unable to set to old poly");
302// }
303//#endif
304
305 wolfSSL_set_fd(ssl, sockfd);
306
307//#ifdef HAVE_CRL
308// if (disableCRL == 0) {
309// if (wolfSSL_EnableCRL(ssl, WOLFSSL_CRL_CHECKALL) != SSL_SUCCESS)
310// err_sys("can't enable crl check");
311// if (wolfSSL_LoadCRL(ssl, crlPemDir, SSL_FILETYPE_PEM, 0) != SSL_SUCCESS)
312// err_sys("can't load crl, check crlfile and date validity");
313// if (wolfSSL_SetCRL_Cb(ssl, CRL_CallBack) != SSL_SUCCESS)
314// err_sys("can't set crl callback");
315// }
316//#endif
317//#ifdef HAVE_SECURE_RENEGOTIATION
318// if (scr) {
319// if (wolfSSL_UseSecureRenegotiation(ssl) != SSL_SUCCESS)
320// err_sys("can't enable secure renegotiation");
321// }
322//#endif
323//#ifdef ATOMIC_USER
324// if (atomicUser)
325// SetupAtomicUser(ctx, ssl);
326//#endif
327//#ifdef HAVE_PK_CALLBACKS
328// if (pkCallbacks)
329// SetupPkCallbacks(ctx, ssl);
330//#endif
331// if (matchName && doPeerCheck)
332// wolfSSL_check_domain_name(ssl, domain);
333
334 if (wolfSSL_connect(ssl) != SSL_SUCCESS) {
335// /* see note at top of README */
336// int err = wolfSSL_get_error(ssl, 0);
337// char buffer[WOLFSSL_MAX_ERROR_SZ];
338// say("err = %d, %s\n", err,
339// wolfSSL_ERR_error_string(err, buffer));
340 err_sys("SSL_connect failed");
341 }
342// showPeer(ssl);
343
344//#ifdef HAVE_SECURE_RENEGOTIATION
345// if (scr && forceScr) {
346// if (wolfSSL_Rehandshake(ssl) != SSL_SUCCESS) {
347// int err = wolfSSL_get_error(ssl, 0);
348// char buffer[WOLFSSL_MAX_ERROR_SZ];
349// say("err = %d, %s\n", err,
350// wolfSSL_ERR_error_string(err, buffer));
351// err_sys("wolfSSL_Rehandshake failed");
352// }
353// }
354//#endif
355
356 return ssl;
357}
358
359static struct pollfd pfd[2] = {
360 { -1, POLLIN|POLLERR|POLLHUP, 0 },
361 { -1, POLLIN|POLLERR|POLLHUP, 0 },
362};
363#define STDIN pfd[0]
364#define NETWORK pfd[1]
365#define STDIN_READY() (pfd[0].revents & (POLLIN|POLLERR|POLLHUP))
366#define NETWORK_READY() (pfd[1].revents & (POLLIN|POLLERR|POLLHUP))
367
368static void wait_for_input(void)
369{
370 if (STDIN.fd == NETWORK.fd) /* means both are -1 */
371 exit(0);
372 dbg("polling\n");
373 STDIN.revents = NETWORK.revents = 0;
374 while (poll(pfd, 2, -1) < 0 && errno == EINTR)
375 continue;
376}
377
378static void do_io_until_eof_and_exit(WOLFSSL *ssl, int fd)
379{
380 int len;
381 char ibuf[4 * 1024];
382
383 NETWORK.fd = fd;
384 STDIN.fd = 0;
385
386 len = 0; /* only to suppress compiler warning */
387 for (;;) {
388 wait_for_input();
389
390 if (STDIN_READY()) {
391 dbg("reading stdin\n");
392 len = read(STDIN_FILENO, ibuf, sizeof(ibuf));
393 if (len < 0)
394 die("read error on stdin\n");
395 if (len == 0) {
396 dbg("read len = 0, stdin not polled anymore\n");
397 STDIN.fd = -1;
398 } else {
399 int n = wolfSSL_write(ssl, ibuf, len);
400 if (n != len)
401 die("SSL_write(%d) failed (returned %d)\n", len, n);
402 }
403 }
404
405 if (NETWORK_READY()) {
406 dbg("%s%s%s\n",
407 (pfd[1].revents & POLLIN) ? "POLLIN" : "",
408 (pfd[1].revents & POLLERR) ? "|POLLERR" : "",
409 (pfd[1].revents & POLLHUP) ? "|POLLHUP" : ""
410 );
411/* We are using blocking socket here.
412 * (Nonblocking socket would complicate writing to it).
413 * Therefore, SSL_read _can block_ here.
414 * This is not what wget expects (it wants to see short reads).
415 * Therefore, we use smallish buffer here, to approximate that.
416 */
417 len = wolfSSL_read(ssl, ibuf,
418 sizeof(ibuf) < 1024 ? sizeof(ibuf) : 1024
419 );
420 if (len < 0)
421 die("SSL_read error on network (%d)\n", len);
422 if (len > 0) {
423 int n;
424 n = full_write(STDOUT_FILENO, ibuf, len);
425 if (n != len)
426 die("write(%d) to stdout returned %d\n", len, n);
427 continue;
428 }
429/* Blocking reads are easier wtr EOF detection (no EAGAIN error to check for) */
430 dbg("read len = 0, network not polled anymore\n");
431 NETWORK.fd = -1;
432 /* saw EOF on network, and we processed
433 * and wrote out all ssl data. Signal it:
434 */
435 close(STDOUT_FILENO);
436 }
437 }
438}
439
440int main(int argc, char **argv)
441{
442 WOLFSSL *ssl;
443 int fd;
444 char *fd_str;
445
446 if (!argv[1])
447 die("Syntax error\n");
448 if (argv[1][0] != '-')
449 die("Syntax error\n");
450 if (argv[1][1] != 'd')
451 die("Syntax error\n");
452 fd_str = argv[1] + 2;
453 if (!fd_str[0])
454 fd_str = argv[2];
455 if (!fd_str || fd_str[0] < '0' || fd_str[0] > '9')
456 die("Syntax error\n");
457
458 fd = atoi(fd_str);
459 if (fd < 3)
460 die("Syntax error\n");
461
462 ssl = prepare(fd);
463 do_io_until_eof_and_exit(ssl, fd);
464 /* does not return */
465
466// if (doDTLS == 0) { /* don't send alert after "break" command */
467// ret = wolfSSL_shutdown(ssl);
468// if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE)
469// wolfSSL_shutdown(ssl); /* bidirectional shutdown */
470// }
471//#ifdef ATOMIC_USER
472// if (atomicUser)
473// FreeAtomicUser(ssl);
474//#endif
475// wolfSSL_free(ssl);
476// CloseSocket(sockfd);
477// wolfSSL_CTX_free(ctx);
478
479 return 0;
480}
Note: See TracBrowser for help on using the repository browser.