Home | History | Annotate | Download | only in ssl
      1 /*
      2  * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
      3  *
      4  * Licensed under the OpenSSL license (the "License").  You may not use
      5  * this file except in compliance with the License.  You can obtain a copy
      6  * in the file LICENSE in the source distribution or at
      7  * https://www.openssl.org/source/license.html
      8  */
      9 
     10 #include <openssl/ssl.h>
     11 
     12 #include <openssl/bio.h>
     13 
     14 
     15 static SSL *get_ssl(BIO *bio) {
     16   return reinterpret_cast<SSL *>(bio->ptr);
     17 }
     18 
     19 static int ssl_read(BIO *bio, char *out, int outl) {
     20   SSL *ssl = get_ssl(bio);
     21   if (ssl == NULL) {
     22     return 0;
     23   }
     24 
     25   BIO_clear_retry_flags(bio);
     26 
     27   const int ret = SSL_read(ssl, out, outl);
     28 
     29   switch (SSL_get_error(ssl, ret)) {
     30     case SSL_ERROR_WANT_READ:
     31       BIO_set_retry_read(bio);
     32       break;
     33 
     34     case SSL_ERROR_WANT_WRITE:
     35       BIO_set_retry_write(bio);
     36       break;
     37 
     38     case SSL_ERROR_WANT_ACCEPT:
     39       BIO_set_retry_special(bio);
     40       bio->retry_reason = BIO_RR_ACCEPT;
     41       break;
     42 
     43     case SSL_ERROR_WANT_CONNECT:
     44       BIO_set_retry_special(bio);
     45       bio->retry_reason = BIO_RR_CONNECT;
     46       break;
     47 
     48     case SSL_ERROR_NONE:
     49     case SSL_ERROR_SYSCALL:
     50     case SSL_ERROR_SSL:
     51     case SSL_ERROR_ZERO_RETURN:
     52     default:
     53       break;
     54   }
     55 
     56   return ret;
     57 }
     58 
     59 static int ssl_write(BIO *bio, const char *out, int outl) {
     60   SSL *ssl = get_ssl(bio);
     61   if (ssl == NULL) {
     62     return 0;
     63   }
     64 
     65   BIO_clear_retry_flags(bio);
     66 
     67   const int ret = SSL_write(ssl, out, outl);
     68 
     69   switch (SSL_get_error(ssl, ret)) {
     70     case SSL_ERROR_WANT_WRITE:
     71       BIO_set_retry_write(bio);
     72       break;
     73 
     74     case SSL_ERROR_WANT_READ:
     75       BIO_set_retry_read(bio);
     76       break;
     77 
     78     case SSL_ERROR_WANT_CONNECT:
     79       BIO_set_retry_special(bio);
     80       bio->retry_reason = BIO_RR_CONNECT;
     81       break;
     82 
     83     case SSL_ERROR_NONE:
     84     case SSL_ERROR_SYSCALL:
     85     case SSL_ERROR_SSL:
     86     default:
     87       break;
     88   }
     89 
     90   return ret;
     91 }
     92 
     93 static long ssl_ctrl(BIO *bio, int cmd, long num, void *ptr) {
     94   SSL *ssl = get_ssl(bio);
     95   if (ssl == NULL && cmd != BIO_C_SET_SSL) {
     96     return 0;
     97   }
     98 
     99   switch (cmd) {
    100     case BIO_C_SET_SSL:
    101       bio->shutdown = num;
    102       bio->ptr = ptr;
    103       bio->init = 1;
    104       return 1;
    105 
    106     case BIO_CTRL_GET_CLOSE:
    107       return bio->shutdown;
    108 
    109     case BIO_CTRL_SET_CLOSE:
    110       bio->shutdown = num;
    111       return 1;
    112 
    113     case BIO_CTRL_WPENDING:
    114       return BIO_ctrl(SSL_get_wbio(ssl), cmd, num, ptr);
    115 
    116     case BIO_CTRL_PENDING:
    117       return SSL_pending(ssl);
    118 
    119     case BIO_CTRL_FLUSH: {
    120       BIO_clear_retry_flags(bio);
    121       long ret = BIO_ctrl(SSL_get_wbio(ssl), cmd, num, ptr);
    122       BIO_copy_next_retry(bio);
    123       return ret;
    124     }
    125 
    126     case BIO_CTRL_PUSH:
    127     case BIO_CTRL_POP:
    128     case BIO_CTRL_DUP:
    129       return -1;
    130 
    131     default:
    132       return BIO_ctrl(SSL_get_rbio(ssl), cmd, num, ptr);
    133   }
    134 }
    135 
    136 static int ssl_new(BIO *bio) {
    137   return 1;
    138 }
    139 
    140 static int ssl_free(BIO *bio) {
    141   SSL *ssl = get_ssl(bio);
    142 
    143   if (ssl == NULL) {
    144     return 1;
    145   }
    146 
    147   SSL_shutdown(ssl);
    148   if (bio->shutdown) {
    149     SSL_free(ssl);
    150   }
    151 
    152   return 1;
    153 }
    154 
    155 static long ssl_callback_ctrl(BIO *bio, int cmd, bio_info_cb fp) {
    156   SSL *ssl = get_ssl(bio);
    157   if (ssl == NULL) {
    158     return 0;
    159   }
    160 
    161   switch (cmd) {
    162     case BIO_CTRL_SET_CALLBACK:
    163       return -1;
    164 
    165     default:
    166       return BIO_callback_ctrl(SSL_get_rbio(ssl), cmd, fp);
    167   }
    168 }
    169 
    170 static const BIO_METHOD ssl_method = {
    171     BIO_TYPE_SSL, "SSL",    ssl_write, ssl_read, NULL,
    172     NULL,         ssl_ctrl, ssl_new,   ssl_free, ssl_callback_ctrl,
    173 };
    174 
    175 const BIO_METHOD *BIO_f_ssl(void) { return &ssl_method; }
    176 
    177 long BIO_set_ssl(BIO *bio, SSL *ssl, int take_owership) {
    178   return BIO_ctrl(bio, BIO_C_SET_SSL, take_owership, ssl);
    179 }
    180