Print this page
    
_XOPEN_SOURCE not needed for usleep() in Solarish systems.
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/tls/s2n_recv.c
          +++ new/tls/s2n_recv.c
   1    1  /*
   2    2   * Copyright 2014 Amazon.com, Inc. or its affiliates. All Rights Reserved.
   3    3   *
   4    4   * Licensed under the Apache License, Version 2.0 (the "License").
   5    5   * You may not use this file except in compliance with the License.
   6    6   * A copy of the License is located at
  
    | 
      ↓ open down ↓ | 
    6 lines elided | 
    
      ↑ open up ↑ | 
  
   7    7   *
   8    8   *  http://aws.amazon.com/apache2.0
   9    9   *
  10   10   * or in the "license" file accompanying this file. This file is distributed
  11   11   * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  12   12   * express or implied. See the License for the specific language governing
  13   13   * permissions and limitations under the License.
  14   14   */
  15   15  
  16   16  /* Use usleep */
       17 +#ifndef __sun
  17   18  #define _XOPEN_SOURCE 500
       19 +#endif /* __sun doesn't need XOPEN_SOURCE defined for usleep() in unistd.h. */
  18   20  #include <unistd.h>
  19   21  
  20   22  #include <errno.h>
  21   23  #include <s2n.h>
  22   24  
  23   25  #include "error/s2n_errno.h"
  24   26  
  25   27  #include "tls/s2n_connection.h"
  26   28  #include "tls/s2n_handshake.h"
  27   29  #include "tls/s2n_record.h"
  28   30  #include "tls/s2n_alerts.h"
  29   31  #include "tls/s2n_tls.h"
  30   32  
  31   33  #include "stuffer/s2n_stuffer.h"
  32   34  
  33   35  #include "utils/s2n_safety.h"
  34   36  #include "utils/s2n_blob.h"
  35   37  
  36   38  int s2n_read_full_record(struct s2n_connection *conn, uint8_t *record_type, int *isSSLv2)
  37   39  {
  38   40      int r;
  39   41  
  40   42      *isSSLv2 = 0;
  41   43  
  42   44      /* If the record has already been decrypted, then leave it alone */
  43   45      if (conn->in_status == PLAINTEXT) {
  44   46          /* Only application data packets count as plaintext */
  45   47          *record_type = TLS_APPLICATION_DATA;
  46   48          return 0;
  47   49      }
  48   50  
  49   51      /* Read the record until we at least have a header */
  50   52      while (s2n_stuffer_data_available(&conn->header_in) < S2N_TLS_RECORD_HEADER_LENGTH) {
  51   53          r = s2n_stuffer_recv_from_fd(&conn->header_in, conn->readfd, S2N_TLS_RECORD_HEADER_LENGTH - s2n_stuffer_data_available(&conn->header_in));
  52   54          if (r == 0) {
  53   55              return -2;
  54   56          }
  55   57          if (r < 0) {
  56   58              return -1;
  57   59          }
  58   60          conn->wire_bytes_in += r;
  59   61      }
  60   62  
  61   63      uint16_t fragment_length;
  62   64  
  63   65      /* If the first bit is set then this is an SSLv2 record */
  64   66      if (conn->header_in.blob.data[0] & 0x80) {
  65   67          conn->header_in.blob.data[0] &= 0x7f;
  66   68          *isSSLv2 = 1;
  67   69  
  68   70          if (s2n_sslv2_record_header_parse(conn, record_type, &conn->client_protocol_version, &fragment_length) < 0) {
  69   71              conn->closed = 1;
  70   72              GUARD(s2n_connection_wipe(conn));
  71   73              return -1;
  72   74          }
  73   75      } else {
  74   76          if (s2n_record_header_parse(conn, record_type, &fragment_length) < 0) {
  75   77              conn->closed = 1;
  76   78              GUARD(s2n_connection_wipe(conn));
  77   79              return -1;
  78   80          }
  79   81      }
  80   82  
  81   83      /* Read enough to have the whole record */
  82   84      while (s2n_stuffer_data_available(&conn->in) < fragment_length) {
  83   85          r = s2n_stuffer_recv_from_fd(&conn->in, conn->readfd, fragment_length - s2n_stuffer_data_available(&conn->in));
  84   86          if (r == 0) {
  85   87              return -2;
  86   88          }
  87   89          if (r < 0) {
  88   90              return -1;
  89   91          }
  90   92          conn->wire_bytes_in += r;
  91   93      }
  92   94  
  93   95      if (*isSSLv2) {
  94   96          return 0;
  95   97      }
  96   98  
  97   99      /* Decrypt and parse the record */
  98  100      if (s2n_record_parse(conn) < 0) {
  99  101          conn->closed = 1;
 100  102          GUARD(s2n_connection_wipe(conn));
 101  103  
 102  104          if (conn->blinding == S2N_BUILT_IN_BLINDING) {
 103  105              int delay;
 104  106              GUARD(delay = s2n_connection_get_delay(conn)); 
 105  107              GUARD(sleep(delay / 1000000));
 106  108              GUARD(usleep(delay % 1000000));
 107  109          }
 108  110  
 109  111          return -1;
 110  112      }
 111  113  
 112  114      return 0;
 113  115  }
 114  116  
 115  117  ssize_t s2n_recv(struct s2n_connection *conn, void *buf, ssize_t size, int *more)
 116  118  {
 117  119      ssize_t bytes_read = 0;
 118  120      struct s2n_blob out = {.data = (uint8_t *) buf };
 119  121  
 120  122      if (conn->closed) {
 121  123          return 0;
 122  124      }
 123  125  
 124  126      *more = 1;
 125  127  
 126  128      while (size && !conn->closed) {
 127  129          int isSSLv2 = 0;
 128  130          uint8_t record_type;
 129  131          errno = 0;
 130  132          int r = s2n_read_full_record(conn, &record_type, &isSSLv2);
 131  133          if (r < 0) {
 132  134              if (errno == EWOULDBLOCK) {
 133  135                  if (bytes_read) {
 134  136                      return bytes_read;
 135  137                  }
 136  138                  return -1;
 137  139              }
 138  140              if (r == -2) {
 139  141                  conn->closed = 1;
 140  142                  GUARD(s2n_connection_wipe(conn));
 141  143                  return bytes_read;
 142  144              }
 143  145              return -1;
 144  146          }
 145  147      
 146  148          if (isSSLv2) {
 147  149              S2N_ERROR(S2N_ERR_BAD_MESSAGE);
 148  150          }
 149  151          
 150  152          if (record_type != TLS_APPLICATION_DATA) {
 151  153              if (record_type == TLS_ALERT) {
 152  154                  GUARD(s2n_process_alert_fragment(conn));
 153  155                  GUARD(s2n_flush(conn, more));
 154  156              }
 155  157  
 156  158              GUARD(s2n_stuffer_wipe(&conn->header_in));
 157  159              GUARD(s2n_stuffer_wipe(&conn->in));
 158  160              conn->in_status = ENCRYPTED;
 159  161              continue;
 160  162          }
 161  163  
 162  164          out.size = size;
 163  165          if (out.size > s2n_stuffer_data_available(&conn->in)) {
 164  166              out.size = s2n_stuffer_data_available(&conn->in);
 165  167          }
 166  168  
 167  169          GUARD(s2n_stuffer_erase_and_read(&conn->in, &out));
 168  170          bytes_read += out.size;
 169  171  
 170  172          out.data += out.size;
 171  173          size -= out.size;
 172  174  
 173  175          /* Are we ready for more encrypted data? */
 174  176          if (s2n_stuffer_data_available(&conn->in) == 0) {
 175  177              GUARD(s2n_stuffer_wipe(&conn->header_in));
 176  178              GUARD(s2n_stuffer_wipe(&conn->in));
 177  179              conn->in_status = ENCRYPTED;
 178  180          }
 179  181  
 180  182          /* If we've read some data, return it */
 181  183          if (bytes_read) {
 182  184              break;
 183  185          }
 184  186      }
 185  187  
 186  188      if (s2n_stuffer_data_available(&conn->in) == 0) {
 187  189          *more = 0;
 188  190      }
 189  191  
 190  192      return bytes_read;
 191  193  }
  
    | 
      ↓ open down ↓ | 
    164 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX