security/nss/lib/ssl/ssldef.c

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial