OLD | NEW |
1 /* | 1 /* |
2 * Gather (Read) entire SSL3 records from socket into buffer. | 2 * Gather (Read) entire SSL3 records from socket into buffer. |
3 * | 3 * |
4 * This Source Code Form is subject to the terms of the Mozilla Public | 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 | 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/. */ | 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
7 | 7 |
8 #include "cert.h" | 8 #include "cert.h" |
9 #include "ssl.h" | 9 #include "ssl.h" |
10 #include "sslimpl.h" | 10 #include "sslimpl.h" |
11 #include "ssl3prot.h" | 11 #include "ssl3prot.h" |
12 | 12 |
13 /* | 13 /* |
14 * Attempt to read in an entire SSL3 record. | 14 * Attempt to read in an entire SSL3 record. |
15 * Blocks here for blocking sockets, otherwise returns -1 with | 15 * Blocks here for blocking sockets, otherwise returns -1 with |
16 * » PR_WOULD_BLOCK_ERROR when socket would block. | 16 * PR_WOULD_BLOCK_ERROR when socket would block. |
17 * | 17 * |
18 * returns 1 if received a complete SSL3 record. | 18 * returns 1 if received a complete SSL3 record. |
19 * returns 0 if recv returns EOF | 19 * returns 0 if recv returns EOF |
20 * returns -1 if recv returns < 0 | 20 * returns -1 if recv returns < 0 |
21 *» (The error value may have already been set to PR_WOULD_BLOCK_ERROR) | 21 * (The error value may have already been set to PR_WOULD_BLOCK_ERROR) |
22 * | 22 * |
23 * Caller must hold the recv buf lock. | 23 * Caller must hold the recv buf lock. |
24 * | 24 * |
25 * The Gather state machine has 3 states: GS_INIT, GS_HEADER, GS_DATA. | 25 * The Gather state machine has 3 states: GS_INIT, GS_HEADER, GS_DATA. |
26 * GS_HEADER: waiting for the 5-byte SSL3 record header to come in. | 26 * GS_HEADER: waiting for the 5-byte SSL3 record header to come in. |
27 * GS_DATA: waiting for the body of the SSL3 record to come in. | 27 * GS_DATA: waiting for the body of the SSL3 record to come in. |
28 * | 28 * |
29 * This loop returns when either | 29 * This loop returns when either |
30 * (a) an error or EOF occurs, | 30 * (a) an error or EOF occurs, |
31 *» (b) PR_WOULD_BLOCK_ERROR, | 31 * (b) PR_WOULD_BLOCK_ERROR, |
32 * » (c) data (entire SSL3 record) has been received. | 32 * (c) data (entire SSL3 record) has been received. |
33 */ | 33 */ |
34 static int | 34 static int |
35 ssl3_GatherData(sslSocket *ss, sslGather *gs, int flags) | 35 ssl3_GatherData(sslSocket *ss, sslGather *gs, int flags) |
36 { | 36 { |
37 unsigned char *bp; | 37 unsigned char *bp; |
38 unsigned char *lbp; | 38 unsigned char *lbp; |
39 int nb; | 39 int nb; |
40 int err; | 40 int err; |
41 int rv» » = 1; | 41 int rv = 1; |
42 | 42 |
43 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); | 43 PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); |
44 if (gs->state == GS_INIT) { | 44 if (gs->state == GS_INIT) { |
45 » gs->state = GS_HEADER; | 45 gs->state = GS_HEADER; |
46 » gs->remainder = 5; | 46 gs->remainder = 5; |
47 » gs->offset = 0; | 47 gs->offset = 0; |
48 » gs->writeOffset = 0; | 48 gs->writeOffset = 0; |
49 » gs->readOffset = 0; | 49 gs->readOffset = 0; |
50 » gs->inbuf.len = 0; | 50 gs->inbuf.len = 0; |
51 } | 51 } |
52 | 52 |
53 lbp = gs->inbuf.buf; | 53 lbp = gs->inbuf.buf; |
54 for(;;) { | 54 for (;;) { |
55 » SSL_TRC(30, ("%d: SSL3[%d]: gather state %d (need %d more)", | 55 SSL_TRC(30, ("%d: SSL3[%d]: gather state %d (need %d more)", |
56 » » SSL_GETPID(), ss->fd, gs->state, gs->remainder)); | 56 SSL_GETPID(), ss->fd, gs->state, gs->remainder)); |
57 » bp = ((gs->state != GS_HEADER) ? lbp : gs->hdr) + gs->offset; | 57 bp = ((gs->state != GS_HEADER) ? lbp : gs->hdr) + gs->offset; |
58 » nb = ssl_DefRecv(ss, bp, gs->remainder, flags); | 58 nb = ssl_DefRecv(ss, bp, gs->remainder, flags); |
59 | 59 |
60 » if (nb > 0) { | 60 if (nb > 0) { |
61 » PRINT_BUF(60, (ss, "raw gather data:", bp, nb)); | 61 PRINT_BUF(60, (ss, "raw gather data:", bp, nb)); |
62 » } else if (nb == 0) { | 62 } else if (nb == 0) { |
63 » /* EOF */ | 63 /* EOF */ |
64 » SSL_TRC(30, ("%d: SSL3[%d]: EOF", SSL_GETPID(), ss->fd)); | 64 SSL_TRC(30, ("%d: SSL3[%d]: EOF", SSL_GETPID(), ss->fd)); |
65 » rv = 0; | 65 rv = 0; |
66 » break; | 66 break; |
67 » } else /* if (nb < 0) */ { | 67 } else /* if (nb < 0) */ { |
68 » SSL_DBG(("%d: SSL3[%d]: recv error %d", SSL_GETPID(), ss->fd, | 68 SSL_DBG(("%d: SSL3[%d]: recv error %d", SSL_GETPID(), ss->fd, |
69 » » PR_GetError())); | 69 PR_GetError())); |
70 » rv = SECFailure; | 70 rv = SECFailure; |
71 » break; | 71 break; |
72 » } | 72 } |
73 | 73 |
74 » PORT_Assert( (unsigned int)nb <= gs->remainder ); | 74 PORT_Assert((unsigned int)nb <= gs->remainder); |
75 » if ((unsigned int)nb > gs->remainder) { | 75 if ((unsigned int)nb > gs->remainder) { |
76 » /* ssl_DefRecv is misbehaving! this error is fatal to SSL. */ | 76 /* ssl_DefRecv is misbehaving! this error is fatal to SSL. */ |
77 » gs->state = GS_INIT; /* so we don't crash next time */ | 77 gs->state = GS_INIT; /* so we don't crash next time */ |
78 » rv = SECFailure; | 78 rv = SECFailure; |
79 » break; | 79 break; |
80 » } | 80 } |
81 | 81 |
82 » gs->offset += nb; | 82 gs->offset += nb; |
83 » gs->remainder -= nb; | 83 gs->remainder -= nb; |
84 » if (gs->state == GS_DATA) | 84 if (gs->state == GS_DATA) |
85 » gs->inbuf.len += nb; | 85 gs->inbuf.len += nb; |
86 | 86 |
87 » /* if there's more to go, read some more. */ | 87 /* if there's more to go, read some more. */ |
88 » if (gs->remainder > 0) { | 88 if (gs->remainder > 0) { |
89 » continue; | 89 continue; |
90 » } | 90 } |
91 | 91 |
92 » /* have received entire record header, or entire record. */ | 92 /* have received entire record header, or entire record. */ |
93 » switch (gs->state) { | 93 switch (gs->state) { |
94 » case GS_HEADER: | 94 case GS_HEADER: |
95 » /* | 95 /* |
96 » ** Have received SSL3 record header in gs->hdr. | 96 ** Have received SSL3 record header in gs->hdr. |
97 » ** Now extract the length of the following encrypted data, | 97 ** Now extract the length of the following encrypted data, |
98 » ** and then read in the rest of the SSL3 record into gs->inbuf. | 98 ** and then read in the rest of the SSL3 record into gs->inbuf. |
99 » */ | 99 */ |
100 » gs->remainder = (gs->hdr[3] << 8) | gs->hdr[4]; | 100 gs->remainder = (gs->hdr[3] << 8) | gs->hdr[4]; |
101 | 101 |
102 » /* This is the max fragment length for an encrypted fragment | 102 /* This is the max fragment length for an encrypted fragment |
103 » ** plus the size of the record header. | 103 ** plus the size of the record header. |
104 » */ | 104 */ |
105 » if(gs->remainder > (MAX_FRAGMENT_LENGTH + 2048 + 5)) { | 105 if (gs->remainder > (MAX_FRAGMENT_LENGTH + 2048 + 5)) { |
106 » » SSL3_SendAlert(ss, alert_fatal, unexpected_message); | 106 SSL3_SendAlert(ss, alert_fatal, unexpected_message); |
107 » » gs->state = GS_INIT; | 107 gs->state = GS_INIT; |
108 » » PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG); | 108 PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG); |
109 » » return SECFailure; | 109 return SECFailure; |
110 » } | 110 } |
111 | 111 |
112 » gs->state = GS_DATA; | 112 gs->state = GS_DATA; |
113 » gs->offset = 0; | 113 gs->offset = 0; |
114 » gs->inbuf.len = 0; | 114 gs->inbuf.len = 0; |
115 | 115 |
116 » if (gs->remainder > gs->inbuf.space) { | 116 if (gs->remainder > gs->inbuf.space) { |
117 » » err = sslBuffer_Grow(&gs->inbuf, gs->remainder); | 117 err = sslBuffer_Grow(&gs->inbuf, gs->remainder); |
118 » » if (err) {» /* realloc has set error code to no mem. */ | 118 if (err) { /* realloc has set error code to no mem. */ |
119 » » return err; | 119 return err; |
120 » » } | 120 } |
121 » » lbp = gs->inbuf.buf; | 121 lbp = gs->inbuf.buf; |
122 » } | 122 } |
123 » break;» /* End this case. Continue around the loop. */ | 123 break; /* End this case. Continue around the loop. */ |
124 | 124 |
125 | 125 case GS_DATA: |
126 » case GS_DATA: | 126 /* |
127 » /* | 127 ** SSL3 record has been completely received. |
128 » ** SSL3 record has been completely received. | 128 */ |
129 » */ | 129 gs->state = GS_INIT; |
130 » gs->state = GS_INIT; | 130 return 1; |
131 » return 1; | 131 } |
132 » } | |
133 } | 132 } |
134 | 133 |
135 return rv; | 134 return rv; |
136 } | 135 } |
137 | 136 |
138 /* | 137 /* |
139 * Read in an entire DTLS record. | 138 * Read in an entire DTLS record. |
140 * | 139 * |
141 * Blocks here for blocking sockets, otherwise returns -1 with | 140 * Blocks here for blocking sockets, otherwise returns -1 with |
142 * » PR_WOULD_BLOCK_ERROR when socket would block. | 141 * PR_WOULD_BLOCK_ERROR when socket would block. |
143 * | 142 * |
144 * This is simpler than SSL because we are reading on a datagram socket | 143 * This is simpler than SSL because we are reading on a datagram socket |
145 * and datagrams must contain >=1 complete records. | 144 * and datagrams must contain >=1 complete records. |
146 * | 145 * |
147 * returns 1 if received a complete DTLS record. | 146 * returns 1 if received a complete DTLS record. |
148 * returns 0 if recv returns EOF | 147 * returns 0 if recv returns EOF |
149 * returns -1 if recv returns < 0 | 148 * returns -1 if recv returns < 0 |
150 *» (The error value may have already been set to PR_WOULD_BLOCK_ERROR) | 149 * (The error value may have already been set to PR_WOULD_BLOCK_ERROR) |
151 * | 150 * |
152 * Caller must hold the recv buf lock. | 151 * Caller must hold the recv buf lock. |
153 * | 152 * |
154 * This loop returns when either | 153 * This loop returns when either |
155 * (a) an error or EOF occurs, | 154 * (a) an error or EOF occurs, |
156 *» (b) PR_WOULD_BLOCK_ERROR, | 155 * (b) PR_WOULD_BLOCK_ERROR, |
157 * » (c) data (entire DTLS record) has been received. | 156 * (c) data (entire DTLS record) has been received. |
158 */ | 157 */ |
159 static int | 158 static int |
160 dtls_GatherData(sslSocket *ss, sslGather *gs, int flags) | 159 dtls_GatherData(sslSocket *ss, sslGather *gs, int flags) |
161 { | 160 { |
162 int nb; | 161 int nb; |
163 int err; | 162 int err; |
164 int rv» » = 1; | 163 int rv = 1; |
165 | 164 |
166 SSL_TRC(30, ("dtls_GatherData")); | 165 SSL_TRC(30, ("dtls_GatherData")); |
167 | 166 |
168 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); | 167 PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); |
169 | 168 |
170 gs->state = GS_HEADER; | 169 gs->state = GS_HEADER; |
171 gs->offset = 0; | 170 gs->offset = 0; |
172 | 171 |
173 if (gs->dtlsPacketOffset == gs->dtlsPacket.len) { /* No data left */ | 172 if (gs->dtlsPacketOffset == gs->dtlsPacket.len) { /* No data left */ |
174 gs->dtlsPacketOffset = 0; | 173 gs->dtlsPacketOffset = 0; |
175 gs->dtlsPacket.len = 0; | 174 gs->dtlsPacket.len = 0; |
176 | 175 |
177 /* Resize to the maximum possible size so we can fit a full datagram */ | 176 /* Resize to the maximum possible size so we can fit a full datagram */ |
178 » /* This is the max fragment length for an encrypted fragment | 177 /* This is the max fragment length for an encrypted fragment |
179 » ** plus the size of the record header. | 178 ** plus the size of the record header. |
180 » ** This magic constant is copied from ssl3_GatherData, with 5 changed | 179 ** This magic constant is copied from ssl3_GatherData, with 5 changed |
181 » ** to 13 (the size of the record header). | 180 ** to 13 (the size of the record header). |
182 » */ | 181 */ |
183 if (gs->dtlsPacket.space < MAX_FRAGMENT_LENGTH + 2048 + 13) { | 182 if (gs->dtlsPacket.space < MAX_FRAGMENT_LENGTH + 2048 + 13) { |
184 err = sslBuffer_Grow(&gs->dtlsPacket, | 183 err = sslBuffer_Grow(&gs->dtlsPacket, |
185 » » » » MAX_FRAGMENT_LENGTH + 2048 + 13); | 184 MAX_FRAGMENT_LENGTH + 2048 + 13); |
186 if (err) {» /* realloc has set error code to no mem. */ | 185 if (err) { /* realloc has set error code to no mem. */ |
187 return err; | 186 return err; |
188 } | 187 } |
189 } | 188 } |
190 | 189 |
191 /* recv() needs to read a full datagram at a time */ | 190 /* recv() needs to read a full datagram at a time */ |
192 nb = ssl_DefRecv(ss, gs->dtlsPacket.buf, gs->dtlsPacket.space, flags); | 191 nb = ssl_DefRecv(ss, gs->dtlsPacket.buf, gs->dtlsPacket.space, flags); |
193 | 192 |
194 if (nb > 0) { | 193 if (nb > 0) { |
195 PRINT_BUF(60, (ss, "raw gather data:", gs->dtlsPacket.buf, nb)); | 194 PRINT_BUF(60, (ss, "raw gather data:", gs->dtlsPacket.buf, nb)); |
196 } else if (nb == 0) { | 195 } else if (nb == 0) { |
197 /* EOF */ | 196 /* EOF */ |
198 SSL_TRC(30, ("%d: SSL3[%d]: EOF", SSL_GETPID(), ss->fd)); | 197 SSL_TRC(30, ("%d: SSL3[%d]: EOF", SSL_GETPID(), ss->fd)); |
199 rv = 0; | 198 rv = 0; |
200 return rv; | 199 return rv; |
201 } else /* if (nb < 0) */ { | 200 } else /* if (nb < 0) */ { |
202 SSL_DBG(("%d: SSL3[%d]: recv error %d", SSL_GETPID(), ss->fd, | 201 SSL_DBG(("%d: SSL3[%d]: recv error %d", SSL_GETPID(), ss->fd, |
203 PR_GetError())); | 202 PR_GetError())); |
204 rv = SECFailure; | 203 rv = SECFailure; |
205 return rv; | 204 return rv; |
206 } | 205 } |
207 | 206 |
208 gs->dtlsPacket.len = nb; | 207 gs->dtlsPacket.len = nb; |
209 } | 208 } |
210 | 209 |
211 /* At this point we should have >=1 complete records lined up in | 210 /* At this point we should have >=1 complete records lined up in |
212 * dtlsPacket. Read off the header. | 211 * dtlsPacket. Read off the header. |
213 */ | 212 */ |
214 if ((gs->dtlsPacket.len - gs->dtlsPacketOffset) < 13) { | 213 if ((gs->dtlsPacket.len - gs->dtlsPacketOffset) < 13) { |
215 SSL_DBG(("%d: SSL3[%d]: rest of DTLS packet " | 214 SSL_DBG(("%d: SSL3[%d]: rest of DTLS packet " |
216 » » "too short to contain header", SSL_GETPID(), ss->fd)); | 215 "too short to contain header", |
| 216 SSL_GETPID(), ss->fd)); |
217 PR_SetError(PR_WOULD_BLOCK_ERROR, 0); | 217 PR_SetError(PR_WOULD_BLOCK_ERROR, 0); |
218 gs->dtlsPacketOffset = 0; | 218 gs->dtlsPacketOffset = 0; |
219 gs->dtlsPacket.len = 0; | 219 gs->dtlsPacket.len = 0; |
220 rv = SECFailure; | 220 rv = SECFailure; |
221 return rv; | 221 return rv; |
222 } | 222 } |
223 memcpy(gs->hdr, gs->dtlsPacket.buf + gs->dtlsPacketOffset, 13); | 223 memcpy(gs->hdr, gs->dtlsPacket.buf + gs->dtlsPacketOffset, 13); |
224 gs->dtlsPacketOffset += 13; | 224 gs->dtlsPacketOffset += 13; |
225 | 225 |
226 /* Have received SSL3 record header in gs->hdr. */ | 226 /* Have received SSL3 record header in gs->hdr. */ |
227 gs->remainder = (gs->hdr[11] << 8) | gs->hdr[12]; | 227 gs->remainder = (gs->hdr[11] << 8) | gs->hdr[12]; |
228 | 228 |
229 if ((gs->dtlsPacket.len - gs->dtlsPacketOffset) < gs->remainder) { | 229 if ((gs->dtlsPacket.len - gs->dtlsPacketOffset) < gs->remainder) { |
230 SSL_DBG(("%d: SSL3[%d]: rest of DTLS packet too short " | 230 SSL_DBG(("%d: SSL3[%d]: rest of DTLS packet too short " |
231 » » "to contain rest of body", SSL_GETPID(), ss->fd)); | 231 "to contain rest of body", |
| 232 SSL_GETPID(), ss->fd)); |
232 PR_SetError(PR_WOULD_BLOCK_ERROR, 0); | 233 PR_SetError(PR_WOULD_BLOCK_ERROR, 0); |
233 gs->dtlsPacketOffset = 0; | 234 gs->dtlsPacketOffset = 0; |
234 gs->dtlsPacket.len = 0; | 235 gs->dtlsPacket.len = 0; |
235 rv = SECFailure; | 236 rv = SECFailure; |
236 return rv; | 237 return rv; |
237 } | 238 } |
238 | 239 |
239 /* OK, we have at least one complete packet, copy into inbuf */ | 240 /* OK, we have at least one complete packet, copy into inbuf */ |
240 if (gs->remainder > gs->inbuf.space) { | 241 if (gs->remainder > gs->inbuf.space) { |
241 » err = sslBuffer_Grow(&gs->inbuf, gs->remainder); | 242 err = sslBuffer_Grow(&gs->inbuf, gs->remainder); |
242 » if (err) {» /* realloc has set error code to no mem. */ | 243 if (err) { /* realloc has set error code to no mem. */ |
243 » return err; | 244 return err; |
244 » } | 245 } |
245 } | 246 } |
246 | 247 |
247 memcpy(gs->inbuf.buf, gs->dtlsPacket.buf + gs->dtlsPacketOffset, | 248 memcpy(gs->inbuf.buf, gs->dtlsPacket.buf + gs->dtlsPacketOffset, |
248 » gs->remainder); | 249 gs->remainder); |
249 gs->inbuf.len = gs->remainder; | 250 gs->inbuf.len = gs->remainder; |
250 gs->offset = gs->remainder; | 251 gs->offset = gs->remainder; |
251 gs->dtlsPacketOffset += gs->remainder; | 252 gs->dtlsPacketOffset += gs->remainder; |
252 gs->state = GS_INIT; | 253 gs->state = GS_INIT; |
253 | 254 |
254 return 1; | 255 return 1; |
255 } | 256 } |
256 | 257 |
257 /* Gather in a record and when complete, Handle that record. | 258 /* Gather in a record and when complete, Handle that record. |
258 * Repeat this until the handshake is complete, | 259 * Repeat this until the handshake is complete, |
259 * or until application data is available. | 260 * or until application data is available. |
260 * | 261 * |
261 * Returns 1 when the handshake is completed without error, or | 262 * Returns 1 when the handshake is completed without error, or |
262 * application data is available. | 263 * application data is available. |
263 * Returns 0 if ssl3_GatherData hits EOF. | 264 * Returns 0 if ssl3_GatherData hits EOF. |
264 * Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error. | 265 * Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error. |
265 * Returns -2 on SECWouldBlock return from ssl3_HandleRecord. | 266 * Returns -2 on SECWouldBlock return from ssl3_HandleRecord. |
266 * | 267 * |
267 * Called from ssl_GatherRecord1stHandshake in sslcon.c, | 268 * Called from ssl_GatherRecord1stHandshake in sslcon.c, |
268 * and from SSL_ForceHandshake in sslsecur.c | 269 * and from SSL_ForceHandshake in sslsecur.c |
269 * and from ssl3_GatherAppDataRecord below (<- DoRecv in sslsecur.c). | 270 * and from ssl3_GatherAppDataRecord below (<- DoRecv in sslsecur.c). |
270 * | 271 * |
271 * Caller must hold the recv buf lock. | 272 * Caller must hold the recv buf lock. |
272 */ | 273 */ |
273 int | 274 int |
274 ssl3_GatherCompleteHandshake(sslSocket *ss, int flags) | 275 ssl3_GatherCompleteHandshake(sslSocket *ss, int flags) |
275 { | 276 { |
276 SSL3Ciphertext cText; | 277 SSL3Ciphertext cText; |
277 int rv; | 278 int rv; |
278 PRBool keepGoing = PR_TRUE; | 279 PRBool keepGoing = PR_TRUE; |
279 | 280 |
280 SSL_TRC(30, ("ssl3_GatherCompleteHandshake")); | 281 SSL_TRC(30, ("ssl3_GatherCompleteHandshake")); |
281 | 282 |
282 /* ssl3_HandleRecord may end up eventually calling ssl_FinishHandshake, | 283 /* ssl3_HandleRecord may end up eventually calling ssl_FinishHandshake, |
283 * which requires the 1stHandshakeLock, which must be acquired before the | 284 * which requires the 1stHandshakeLock, which must be acquired before the |
284 * RecvBufLock. | 285 * RecvBufLock. |
285 */ | 286 */ |
286 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | 287 PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss)); |
287 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); | 288 PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); |
288 | 289 |
289 do { | 290 do { |
290 » PRBool handleRecordNow = PR_FALSE; | 291 PRBool handleRecordNow = PR_FALSE; |
291 | 292 |
292 » ssl_GetSSL3HandshakeLock(ss); | 293 ssl_GetSSL3HandshakeLock(ss); |
293 | 294 |
294 » /* Without this, we may end up wrongly reporting | 295 /* Without this, we may end up wrongly reporting |
295 » * SSL_ERROR_RX_UNEXPECTED_* errors if we receive any records from the | 296 * SSL_ERROR_RX_UNEXPECTED_* errors if we receive any records from the |
296 » * peer while we are waiting to be restarted. | 297 * peer while we are waiting to be restarted. |
297 » */ | 298 */ |
298 » if (ss->ssl3.hs.restartTarget) { | 299 if (ss->ssl3.hs.restartTarget) { |
299 » ssl_ReleaseSSL3HandshakeLock(ss); | 300 ssl_ReleaseSSL3HandshakeLock(ss); |
300 » PORT_SetError(PR_WOULD_BLOCK_ERROR); | 301 PORT_SetError(PR_WOULD_BLOCK_ERROR); |
301 » return (int) SECFailure; | 302 return (int)SECFailure; |
302 » } | 303 } |
303 | 304 |
304 » /* Treat an empty msgState like a NULL msgState. (Most of the time | 305 /* Treat an empty msgState like a NULL msgState. (Most of the time |
305 » * when ssl3_HandleHandshake returns SECWouldBlock, it leaves | 306 * when ssl3_HandleHandshake returns SECWouldBlock, it leaves |
306 » * behind a non-NULL but zero-length msgState). | 307 * behind a non-NULL but zero-length msgState). |
307 » * Test: async_cert_restart_server_sends_hello_request_first_in_separate
_record | 308 * Test: async_cert_restart_server_sends_hello_request_first_in_separate
_record |
308 » */ | 309 */ |
309 » if (ss->ssl3.hs.msgState.buf) { | 310 if (ss->ssl3.hs.msgState.buf) { |
310 » if (ss->ssl3.hs.msgState.len == 0) { | 311 if (ss->ssl3.hs.msgState.len == 0) { |
311 » » ss->ssl3.hs.msgState.buf = NULL; | 312 ss->ssl3.hs.msgState.buf = NULL; |
312 » } else { | 313 } else { |
313 » » handleRecordNow = PR_TRUE; | 314 handleRecordNow = PR_TRUE; |
314 » } | 315 } |
315 » } | 316 } |
316 | 317 |
317 » ssl_ReleaseSSL3HandshakeLock(ss); | 318 ssl_ReleaseSSL3HandshakeLock(ss); |
318 | 319 |
319 » if (handleRecordNow) { | 320 if (handleRecordNow) { |
320 » /* ssl3_HandleHandshake previously returned SECWouldBlock and the | 321 /* ssl3_HandleHandshake previously returned SECWouldBlock and the |
321 » * as-yet-unprocessed plaintext of that previous handshake record. | 322 * as-yet-unprocessed plaintext of that previous handshake record. |
322 » * We need to process it now before we overwrite it with the next | 323 * We need to process it now before we overwrite it with the next |
323 » * handshake record. | 324 * handshake record. |
324 » */ | 325 */ |
325 » rv = ssl3_HandleRecord(ss, NULL, &ss->gs.buf); | 326 rv = ssl3_HandleRecord(ss, NULL, &ss->gs.buf); |
326 » } else { | 327 } else { |
327 » /* bring in the next sslv3 record. */ | 328 /* bring in the next sslv3 record. */ |
328 » if (ss->recvdCloseNotify) { | 329 if (ss->recvdCloseNotify) { |
329 » » /* RFC 5246 Section 7.2.1: | 330 /* RFC 5246 Section 7.2.1: |
330 » » * Any data received after a closure alert is ignored. | 331 * Any data received after a closure alert is ignored. |
331 » » */ | 332 */ |
332 » » return 0; | 333 return 0; |
333 » } | 334 } |
334 » if (!IS_DTLS(ss)) { | 335 if (!IS_DTLS(ss)) { |
335 » » rv = ssl3_GatherData(ss, &ss->gs, flags); | 336 rv = ssl3_GatherData(ss, &ss->gs, flags); |
336 » } else { | 337 } else { |
337 » » rv = dtls_GatherData(ss, &ss->gs, flags); | 338 rv = dtls_GatherData(ss, &ss->gs, flags); |
338 » » | |
339 » » /* If we got a would block error, that means that no data was | |
340 » » * available, so we check the timer to see if it's time to | |
341 » » * retransmit */ | |
342 » » if (rv == SECFailure && | |
343 » » (PORT_GetError() == PR_WOULD_BLOCK_ERROR)) { | |
344 » » ssl_GetSSL3HandshakeLock(ss); | |
345 » » dtls_CheckTimer(ss); | |
346 » » ssl_ReleaseSSL3HandshakeLock(ss); | |
347 » » /* Restore the error in case something succeeded */ | |
348 » » PORT_SetError(PR_WOULD_BLOCK_ERROR); | |
349 » » } | |
350 » } | |
351 | 339 |
352 » if (rv <= 0) { | 340 /* If we got a would block error, that means that no data was |
353 » » return rv; | 341 * available, so we check the timer to see if it's time to |
354 » } | 342 * retransmit */ |
| 343 if (rv == SECFailure && |
| 344 (PORT_GetError() == PR_WOULD_BLOCK_ERROR)) { |
| 345 ssl_GetSSL3HandshakeLock(ss); |
| 346 dtls_CheckTimer(ss); |
| 347 ssl_ReleaseSSL3HandshakeLock(ss); |
| 348 /* Restore the error in case something succeeded */ |
| 349 PORT_SetError(PR_WOULD_BLOCK_ERROR); |
| 350 } |
| 351 } |
355 | 352 |
356 » /* decipher it, and handle it if it's a handshake. | 353 if (rv <= 0) { |
357 » * If it's application data, ss->gs.buf will not be empty upon retur
n. | 354 return rv; |
358 » * If it's a change cipher spec, alert, or handshake message, | 355 } |
359 » * ss->gs.buf.len will be 0 when ssl3_HandleRecord returns SECSucces
s. | |
360 » */ | |
361 » cText.type = (SSL3ContentType)ss->gs.hdr[0]; | |
362 » cText.version = (ss->gs.hdr[1] << 8) | ss->gs.hdr[2]; | |
363 | 356 |
364 » if (IS_DTLS(ss)) { | 357 /* decipher it, and handle it if it's a handshake. |
365 » » int i; | 358 * If it's application data, ss->gs.buf will not be empty upon retur
n. |
| 359 * If it's a change cipher spec, alert, or handshake message, |
| 360 * ss->gs.buf.len will be 0 when ssl3_HandleRecord returns SECSucces
s. |
| 361 */ |
| 362 cText.type = (SSL3ContentType)ss->gs.hdr[0]; |
| 363 cText.version = (ss->gs.hdr[1] << 8) | ss->gs.hdr[2]; |
366 | 364 |
367 » » cText.version = dtls_DTLSVersionToTLSVersion(cText.version); | 365 if (IS_DTLS(ss)) { |
368 » » /* DTLS sequence number */ | 366 int i; |
369 » » cText.seq_num.high = 0; cText.seq_num.low = 0; | |
370 » » for (i = 0; i < 4; i++) { | |
371 » » cText.seq_num.high <<= 8; cText.seq_num.low <<= 8; | |
372 » » cText.seq_num.high |= ss->gs.hdr[3 + i]; | |
373 » » cText.seq_num.low |= ss->gs.hdr[7 + i]; | |
374 » » } | |
375 » } | |
376 | 367 |
377 » cText.buf = &ss->gs.inbuf; | 368 cText.version = dtls_DTLSVersionToTLSVersion(cText.version); |
378 » rv = ssl3_HandleRecord(ss, &cText, &ss->gs.buf); | 369 /* DTLS sequence number */ |
379 » } | 370 cText.seq_num.high = 0; |
380 » if (rv < 0) { | 371 cText.seq_num.low = 0; |
381 » return ss->recvdCloseNotify ? 0 : rv; | 372 for (i = 0; i < 4; i++) { |
382 » } | 373 cText.seq_num.high <<= 8; |
383 » if (ss->gs.buf.len > 0) { | 374 cText.seq_num.low <<= 8; |
384 » /* We have application data to return to the application. This | 375 cText.seq_num.high |= ss->gs.hdr[3 + i]; |
385 » * prioritizes returning application data to the application over | 376 cText.seq_num.low |= ss->gs.hdr[7 + i]; |
386 » * completing any renegotiation handshake we may be doing. | 377 } |
387 » */ | 378 } |
388 » PORT_Assert(ss->firstHsDone); | |
389 » PORT_Assert(cText.type == content_application_data); | |
390 » break; | |
391 » } | |
392 | 379 |
393 » PORT_Assert(keepGoing); | 380 cText.buf = &ss->gs.inbuf; |
394 » ssl_GetSSL3HandshakeLock(ss); | 381 rv = ssl3_HandleRecord(ss, &cText, &ss->gs.buf); |
395 » if (ss->ssl3.hs.ws == idle_handshake) { | 382 } |
396 » /* We are done with the current handshake so stop trying to | 383 if (rv < 0) { |
397 » * handshake. Note that it would be safe to test ss->firstHsDone | 384 return ss->recvdCloseNotify ? 0 : rv; |
398 » * instead of ss->ssl3.hs.ws. By testing ss->ssl3.hs.ws instead, | 385 } |
399 » * we prioritize completing a renegotiation handshake over sending | 386 if (ss->gs.buf.len > 0) { |
400 » * application data. | 387 /* We have application data to return to the application. This |
401 » */ | 388 * prioritizes returning application data to the application over |
402 » PORT_Assert(ss->firstHsDone); | 389 * completing any renegotiation handshake we may be doing. |
403 » PORT_Assert(!ss->ssl3.hs.canFalseStart); | 390 */ |
404 » keepGoing = PR_FALSE; | 391 PORT_Assert(ss->firstHsDone); |
405 » } else if (ss->ssl3.hs.canFalseStart) { | 392 PORT_Assert(cText.type == content_application_data); |
406 » /* Prioritize sending application data over trying to complete | 393 break; |
407 » * the handshake if we're false starting. | 394 } |
408 » * | |
409 » * If we were to do this check at the beginning of the loop instead | |
410 » * of here, then this function would become be a no-op after | |
411 » * receiving the ServerHelloDone in the false start case, and we | |
412 » * would never complete the handshake. | |
413 » */ | |
414 » PORT_Assert(!ss->firstHsDone); | |
415 | 395 |
416 » if (ssl3_WaitingForStartOfServerSecondRound(ss)) { | 396 PORT_Assert(keepGoing); |
417 » » keepGoing = PR_FALSE; | 397 ssl_GetSSL3HandshakeLock(ss); |
418 » } else { | 398 if (ss->ssl3.hs.ws == idle_handshake) { |
419 » » ss->ssl3.hs.canFalseStart = PR_FALSE; | 399 /* We are done with the current handshake so stop trying to |
420 » } | 400 * handshake. Note that it would be safe to test ss->firstHsDone |
421 » } | 401 * instead of ss->ssl3.hs.ws. By testing ss->ssl3.hs.ws instead, |
422 » ssl_ReleaseSSL3HandshakeLock(ss); | 402 * we prioritize completing a renegotiation handshake over sending |
| 403 * application data. |
| 404 */ |
| 405 PORT_Assert(ss->firstHsDone); |
| 406 PORT_Assert(!ss->ssl3.hs.canFalseStart); |
| 407 keepGoing = PR_FALSE; |
| 408 } else if (ss->ssl3.hs.canFalseStart) { |
| 409 /* Prioritize sending application data over trying to complete |
| 410 * the handshake if we're false starting. |
| 411 * |
| 412 * If we were to do this check at the beginning of the loop instead |
| 413 * of here, then this function would become be a no-op after |
| 414 * receiving the ServerHelloDone in the false start case, and we |
| 415 * would never complete the handshake. |
| 416 */ |
| 417 PORT_Assert(!ss->firstHsDone); |
| 418 |
| 419 if (ssl3_WaitingForServerSecondRound(ss)) { |
| 420 keepGoing = PR_FALSE; |
| 421 } else { |
| 422 ss->ssl3.hs.canFalseStart = PR_FALSE; |
| 423 } |
| 424 } |
| 425 ssl_ReleaseSSL3HandshakeLock(ss); |
423 } while (keepGoing); | 426 } while (keepGoing); |
424 | 427 |
425 ss->gs.readOffset = 0; | 428 ss->gs.readOffset = 0; |
426 ss->gs.writeOffset = ss->gs.buf.len; | 429 ss->gs.writeOffset = ss->gs.buf.len; |
427 return 1; | 430 return 1; |
428 } | 431 } |
429 | 432 |
430 /* Repeatedly gather in a record and when complete, Handle that record. | 433 /* Repeatedly gather in a record and when complete, Handle that record. |
431 * Repeat this until some application data is received. | 434 * Repeat this until some application data is received. |
432 * | 435 * |
433 * Returns 1 when application data is available. | 436 * Returns 1 when application data is available. |
434 * Returns 0 if ssl3_GatherData hits EOF. | 437 * Returns 0 if ssl3_GatherData hits EOF. |
435 * Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error. | 438 * Returns -1 on read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error. |
436 * Returns -2 on SECWouldBlock return from ssl3_HandleRecord. | 439 * Returns -2 on SECWouldBlock return from ssl3_HandleRecord. |
437 * | 440 * |
438 * Called from DoRecv in sslsecur.c | 441 * Called from DoRecv in sslsecur.c |
439 * Caller must hold the recv buf lock. | 442 * Caller must hold the recv buf lock. |
440 */ | 443 */ |
441 int | 444 int |
442 ssl3_GatherAppDataRecord(sslSocket *ss, int flags) | 445 ssl3_GatherAppDataRecord(sslSocket *ss, int flags) |
443 { | 446 { |
444 int rv; | 447 int rv; |
445 | 448 |
446 /* ssl3_GatherCompleteHandshake requires both of these locks. */ | 449 /* ssl3_GatherCompleteHandshake requires both of these locks. */ |
447 PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) ); | 450 PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss)); |
448 PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) ); | 451 PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); |
449 | 452 |
450 do { | 453 do { |
451 » rv = ssl3_GatherCompleteHandshake(ss, flags); | 454 rv = ssl3_GatherCompleteHandshake(ss, flags); |
452 } while (rv > 0 && ss->gs.buf.len == 0); | 455 } while (rv > 0 && ss->gs.buf.len == 0); |
453 | 456 |
454 return rv; | 457 return rv; |
455 } | 458 } |
OLD | NEW |