/src/nss/lib/ssl/ssldef.c
Line | Count | Source (jump to first uncovered line) |
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 | 0 | { |
26 | 0 | PRFileDesc *lower = ss->fd->lower; |
27 | 0 | int rv; |
28 | |
|
29 | 0 | rv = lower->methods->connect(lower, sa, ss->cTimeout); |
30 | 0 | return rv; |
31 | 0 | } |
32 | | |
33 | | int |
34 | | ssl_DefBind(sslSocket *ss, const PRNetAddr *addr) |
35 | 0 | { |
36 | 0 | PRFileDesc *lower = ss->fd->lower; |
37 | 0 | int rv; |
38 | |
|
39 | 0 | rv = lower->methods->bind(lower, addr); |
40 | 0 | return rv; |
41 | 0 | } |
42 | | |
43 | | int |
44 | | ssl_DefListen(sslSocket *ss, int backlog) |
45 | 0 | { |
46 | 0 | PRFileDesc *lower = ss->fd->lower; |
47 | 0 | int rv; |
48 | |
|
49 | 0 | rv = lower->methods->listen(lower, backlog); |
50 | 0 | return rv; |
51 | 0 | } |
52 | | |
53 | | int |
54 | | ssl_DefShutdown(sslSocket *ss, int how) |
55 | 0 | { |
56 | 0 | PRFileDesc *lower = ss->fd->lower; |
57 | 0 | int rv; |
58 | |
|
59 | 0 | rv = lower->methods->shutdown(lower, how); |
60 | 0 | return rv; |
61 | 0 | } |
62 | | |
63 | | int |
64 | | ssl_DefRecv(sslSocket *ss, unsigned char *buf, int len, int flags) |
65 | 2.65M | { |
66 | 2.65M | PRFileDesc *lower = ss->fd->lower; |
67 | 2.65M | int rv; |
68 | | |
69 | 2.65M | PORT_Assert(buf && len > 0); |
70 | | |
71 | 2.65M | rv = lower->methods->recv(lower, (void *)buf, len, flags, ss->rTimeout); |
72 | 2.65M | if (rv < 0) { |
73 | 0 | DEFINE_ERROR |
74 | 0 | MAP_ERROR(PR_SOCKET_SHUTDOWN_ERROR, PR_CONNECT_RESET_ERROR) |
75 | 2.65M | } else if (rv > len) { |
76 | 0 | PORT_Assert(rv <= len); |
77 | 0 | PORT_SetError(PR_BUFFER_OVERFLOW_ERROR); |
78 | 0 | rv = SECFailure; |
79 | 0 | } |
80 | 2.65M | return rv; |
81 | 2.65M | } |
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 | 318k | { |
92 | 318k | PRFileDesc *lower = ss->fd->lower; |
93 | 318k | 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 | 318k | do { |
105 | 318k | int rv = lower->methods->send(lower, (const void *)(buf + sent), |
106 | 318k | len - sent, flags, ss->wTimeout); |
107 | 318k | if (rv < 0) { |
108 | 0 | PRErrorCode err = PR_GetError(); |
109 | 0 | if (err == PR_WOULD_BLOCK_ERROR) { |
110 | 0 | ss->lastWriteBlocked = 1; |
111 | 0 | return sent ? sent : SECFailure; |
112 | 0 | } |
113 | 0 | ss->lastWriteBlocked = 0; |
114 | 0 | MAP_ERROR(PR_CONNECT_ABORTED_ERROR, PR_CONNECT_RESET_ERROR) |
115 | | /* Loser */ |
116 | 0 | return rv; |
117 | 0 | } |
118 | 318k | sent += rv; |
119 | | |
120 | 318k | if (IS_DTLS(ss) && (len > sent)) { |
121 | | /* We got a partial write so just return it */ |
122 | 0 | return sent; |
123 | 0 | } |
124 | 318k | } while (len > sent); |
125 | 318k | ss->lastWriteBlocked = 0; |
126 | 318k | return sent; |
127 | 318k | } |
128 | | |
129 | | int |
130 | | ssl_DefRead(sslSocket *ss, unsigned char *buf, int len) |
131 | 0 | { |
132 | 0 | PRFileDesc *lower = ss->fd->lower; |
133 | 0 | int rv; |
134 | |
|
135 | 0 | rv = lower->methods->read(lower, (void *)buf, len); |
136 | 0 | if (rv < 0) { |
137 | 0 | DEFINE_ERROR |
138 | 0 | MAP_ERROR(PR_SOCKET_SHUTDOWN_ERROR, PR_CONNECT_RESET_ERROR) |
139 | 0 | } |
140 | 0 | return rv; |
141 | 0 | } |
142 | | |
143 | | int |
144 | | ssl_DefWrite(sslSocket *ss, const unsigned char *buf, int len) |
145 | 0 | { |
146 | 0 | PRFileDesc *lower = ss->fd->lower; |
147 | 0 | int sent = 0; |
148 | |
|
149 | 0 | do { |
150 | 0 | int rv = lower->methods->write(lower, (const void *)(buf + sent), |
151 | 0 | len - sent); |
152 | 0 | if (rv < 0) { |
153 | 0 | PRErrorCode err = PR_GetError(); |
154 | 0 | if (err == PR_WOULD_BLOCK_ERROR) { |
155 | 0 | ss->lastWriteBlocked = 1; |
156 | 0 | return sent ? sent : SECFailure; |
157 | 0 | } |
158 | 0 | ss->lastWriteBlocked = 0; |
159 | 0 | MAP_ERROR(PR_CONNECT_ABORTED_ERROR, PR_CONNECT_RESET_ERROR) |
160 | | /* Loser */ |
161 | 0 | return rv; |
162 | 0 | } |
163 | 0 | sent += rv; |
164 | 0 | } while (len > sent); |
165 | 0 | ss->lastWriteBlocked = 0; |
166 | 0 | return sent; |
167 | 0 | } |
168 | | |
169 | | int |
170 | | ssl_DefGetpeername(sslSocket *ss, PRNetAddr *name) |
171 | 68.7k | { |
172 | 68.7k | PRFileDesc *lower = ss->fd->lower; |
173 | 68.7k | int rv; |
174 | | |
175 | 68.7k | rv = lower->methods->getpeername(lower, name); |
176 | 68.7k | return rv; |
177 | 68.7k | } |
178 | | |
179 | | int |
180 | | ssl_DefGetsockname(sslSocket *ss, PRNetAddr *name) |
181 | 0 | { |
182 | 0 | PRFileDesc *lower = ss->fd->lower; |
183 | 0 | int rv; |
184 | |
|
185 | 0 | rv = lower->methods->getsockname(lower, name); |
186 | 0 | return rv; |
187 | 0 | } |
188 | | |
189 | | int |
190 | | ssl_DefClose(sslSocket *ss) |
191 | 68.7k | { |
192 | 68.7k | PRFileDesc *fd; |
193 | 68.7k | PRFileDesc *popped; |
194 | 68.7k | int rv; |
195 | | |
196 | 68.7k | 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 | 68.7k | PORT_Assert(fd->higher == NULL); |
203 | 68.7k | if (fd->higher) { |
204 | 0 | PORT_SetError(PR_BAD_DESCRIPTOR_ERROR); |
205 | 0 | return SECFailure; |
206 | 0 | } |
207 | 68.7k | 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 | 68.7k | popped = PR_PopIOLayer(fd, PR_TOP_IO_LAYER); |
214 | 68.7k | popped->dtor(popped); |
215 | | |
216 | | /* fd is now the PRFileDesc for the next layer down. |
217 | | ** Now close the underlying socket. |
218 | | */ |
219 | 68.7k | rv = fd->methods->close(fd); |
220 | | |
221 | 68.7k | ssl_FreeSocket(ss); |
222 | | |
223 | 68.7k | SSL_TRC(5, ("%d: SSL[%d]: closing, rv=%d errno=%d", |
224 | 68.7k | SSL_GETPID(), fd, rv, PORT_GetError())); |
225 | 68.7k | return rv; |
226 | 68.7k | } |