tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ssldef.c (5669B)


      1 /*
      2 * "Default" SSLSocket methods, used by sockets that do neither SSL nor socks.
      3 *
      4 * This Source Code Form is subject to the terms of the Mozilla Public
      5 * License, v. 2.0. If a copy of the MPL was not distributed with this
      6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      7 
      8 #include "cert.h"
      9 #include "ssl.h"
     10 #include "sslimpl.h"
     11 
     12 #if defined(WIN32)
     13 #define MAP_ERROR(from, to) \
     14    if (err == from) {      \
     15        PORT_SetError(to);  \
     16    }
     17 #define DEFINE_ERROR PRErrorCode err = PR_GetError();
     18 #else
     19 #define MAP_ERROR(from, to)
     20 #define DEFINE_ERROR
     21 #endif
     22 
     23 int
     24 ssl_DefConnect(sslSocket *ss, const PRNetAddr *sa)
     25 {
     26    PRFileDesc *lower = ss->fd->lower;
     27    int rv;
     28 
     29    rv = lower->methods->connect(lower, sa, ss->cTimeout);
     30    return rv;
     31 }
     32 
     33 int
     34 ssl_DefBind(sslSocket *ss, const PRNetAddr *addr)
     35 {
     36    PRFileDesc *lower = ss->fd->lower;
     37    int rv;
     38 
     39    rv = lower->methods->bind(lower, addr);
     40    return rv;
     41 }
     42 
     43 int
     44 ssl_DefListen(sslSocket *ss, int backlog)
     45 {
     46    PRFileDesc *lower = ss->fd->lower;
     47    int rv;
     48 
     49    rv = lower->methods->listen(lower, backlog);
     50    return rv;
     51 }
     52 
     53 int
     54 ssl_DefShutdown(sslSocket *ss, int how)
     55 {
     56    PRFileDesc *lower = ss->fd->lower;
     57    int rv;
     58 
     59    rv = lower->methods->shutdown(lower, how);
     60    return rv;
     61 }
     62 
     63 int
     64 ssl_DefRecv(sslSocket *ss, unsigned char *buf, int len, int flags)
     65 {
     66    PRFileDesc *lower = ss->fd->lower;
     67    int rv;
     68 
     69    PORT_Assert(buf && len > 0);
     70 
     71    rv = lower->methods->recv(lower, (void *)buf, len, flags, ss->rTimeout);
     72    if (rv < 0) {
     73        DEFINE_ERROR
     74        MAP_ERROR(PR_SOCKET_SHUTDOWN_ERROR, PR_CONNECT_RESET_ERROR)
     75    } else if (rv > len) {
     76        PORT_Assert(rv <= len);
     77        PORT_SetError(PR_BUFFER_OVERFLOW_ERROR);
     78        rv = SECFailure;
     79    }
     80    return rv;
     81 }
     82 
     83 /* Default (unencrypted) send.
     84 * For blocking sockets, always returns len or SECFailure, no short writes.
     85 * For non-blocking sockets:
     86 *   Returns positive count if any data was written, else returns SECFailure.
     87 *   Short writes may occur.
     88 */
     89 int
     90 ssl_DefSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
     91 {
     92    PRFileDesc *lower = ss->fd->lower;
     93    int sent = 0;
     94 
     95 #if NSS_DISABLE_NAGLE_DELAYS
     96    /* Although this is overkill, we disable Nagle delays completely for
     97    ** SSL sockets.
     98    */
     99    if (ss->opt.useSecurity && !ss->delayDisabled) {
    100        ssl_EnableNagleDelay(ss, PR_FALSE); /* ignore error */
    101        ss->delayDisabled = 1;
    102    }
    103 #endif
    104    do {
    105        int rv = lower->methods->send(lower, (const void *)(buf + sent),
    106                                      len - sent, flags, ss->wTimeout);
    107        if (rv < 0) {
    108            PRErrorCode err = PR_GetError();
    109            if (err == PR_WOULD_BLOCK_ERROR) {
    110                ss->lastWriteBlocked = 1;
    111                return sent ? sent : SECFailure;
    112            }
    113            ss->lastWriteBlocked = 0;
    114            MAP_ERROR(PR_CONNECT_ABORTED_ERROR, PR_CONNECT_RESET_ERROR)
    115            /* Loser */
    116            return rv;
    117        }
    118        sent += rv;
    119 
    120        if (IS_DTLS(ss) && (len > sent)) {
    121            /* We got a partial write so just return it */
    122            return sent;
    123        }
    124    } while (len > sent);
    125    ss->lastWriteBlocked = 0;
    126    return sent;
    127 }
    128 
    129 int
    130 ssl_DefRead(sslSocket *ss, unsigned char *buf, int len)
    131 {
    132    PRFileDesc *lower = ss->fd->lower;
    133    int rv;
    134 
    135    rv = lower->methods->read(lower, (void *)buf, len);
    136    if (rv < 0) {
    137        DEFINE_ERROR
    138        MAP_ERROR(PR_SOCKET_SHUTDOWN_ERROR, PR_CONNECT_RESET_ERROR)
    139    }
    140    return rv;
    141 }
    142 
    143 int
    144 ssl_DefWrite(sslSocket *ss, const unsigned char *buf, int len)
    145 {
    146    PRFileDesc *lower = ss->fd->lower;
    147    int sent = 0;
    148 
    149    do {
    150        int rv = lower->methods->write(lower, (const void *)(buf + sent),
    151                                       len - sent);
    152        if (rv < 0) {
    153            PRErrorCode err = PR_GetError();
    154            if (err == PR_WOULD_BLOCK_ERROR) {
    155                ss->lastWriteBlocked = 1;
    156                return sent ? sent : SECFailure;
    157            }
    158            ss->lastWriteBlocked = 0;
    159            MAP_ERROR(PR_CONNECT_ABORTED_ERROR, PR_CONNECT_RESET_ERROR)
    160            /* Loser */
    161            return rv;
    162        }
    163        sent += rv;
    164    } while (len > sent);
    165    ss->lastWriteBlocked = 0;
    166    return sent;
    167 }
    168 
    169 int
    170 ssl_DefGetpeername(sslSocket *ss, PRNetAddr *name)
    171 {
    172    PRFileDesc *lower = ss->fd->lower;
    173    int rv;
    174 
    175    rv = lower->methods->getpeername(lower, name);
    176    return rv;
    177 }
    178 
    179 int
    180 ssl_DefGetsockname(sslSocket *ss, PRNetAddr *name)
    181 {
    182    PRFileDesc *lower = ss->fd->lower;
    183    int rv;
    184 
    185    rv = lower->methods->getsockname(lower, name);
    186    return rv;
    187 }
    188 
    189 int
    190 ssl_DefClose(sslSocket *ss)
    191 {
    192    PRFileDesc *fd;
    193    PRFileDesc *popped;
    194    int rv;
    195 
    196    fd = ss->fd;
    197 
    198    /* First, remove the SSL layer PRFileDesc from the socket's stack,
    199    ** then invoke the SSL layer's PRFileDesc destructor.
    200    ** This must happen before the next layer down is closed.
    201    */
    202    PORT_Assert(fd->higher == NULL);
    203    if (fd->higher) {
    204        PORT_SetError(PR_BAD_DESCRIPTOR_ERROR);
    205        return SECFailure;
    206    }
    207    ss->fd = NULL;
    208 
    209    /* PR_PopIOLayer will swap the contents of the top two PRFileDescs on
    210    ** the stack, and then remove the second one.  This way, the address
    211    ** of the PRFileDesc on the top of the stack doesn't change.
    212    */
    213    popped = PR_PopIOLayer(fd, PR_TOP_IO_LAYER);
    214    popped->dtor(popped);
    215 
    216    /* fd is now the PRFileDesc for the next layer down.
    217    ** Now close the underlying socket.
    218    */
    219    rv = fd->methods->close(fd);
    220 
    221    ssl_FreeSocket(ss);
    222 
    223    SSL_TRC(5, ("%d: SSL[%d]: closing, rv=%d errno=%d",
    224                SSL_GETPID(), fd, rv, PORT_GetError()));
    225    return rv;
    226 }