busybox/networking/ssl_helper-wolfssl/ssl_helper.c
<<
>>
Prefs
   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}
 481