| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Various SSL functions. | |
| 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 #include "cert.h" | |
| 8 #include "secitem.h" | |
| 9 #include "keyhi.h" | |
| 10 #include "ssl.h" | |
| 11 #include "sslimpl.h" | |
| 12 #include "sslproto.h" | |
| 13 #include "secoid.h" /* for SECOID_GetALgorithmTag */ | |
| 14 #include "pk11func.h" /* for PK11_GenerateRandom */ | |
| 15 #include "nss.h" /* for NSS_RegisterShutdown */ | |
| 16 #include "prinit.h" /* for PR_CallOnceWithArg */ | |
| 17 | |
| 18 #define MAX_BLOCK_CYPHER_SIZE 32 | |
| 19 | |
| 20 #define TEST_FOR_FAILURE /* reminder */ | |
| 21 #define SET_ERROR_CODE /* reminder */ | |
| 22 | |
| 23 /* Returns a SECStatus: SECSuccess or SECFailure, NOT SECWouldBlock. | |
| 24 * | |
| 25 * Currently, the list of functions called through ss->handshake is: | |
| 26 * | |
| 27 * In sslsocks.c: | |
| 28 * SocksGatherRecord | |
| 29 * SocksHandleReply | |
| 30 * SocksStartGather | |
| 31 * | |
| 32 * In sslcon.c: | |
| 33 * ssl_GatherRecord1stHandshake | |
| 34 * ssl2_HandleClientSessionKeyMessage | |
| 35 * ssl2_HandleMessage | |
| 36 * ssl2_HandleVerifyMessage | |
| 37 * ssl2_BeginClientHandshake | |
| 38 * ssl2_BeginServerHandshake | |
| 39 * ssl2_HandleClientHelloMessage | |
| 40 * ssl2_HandleServerHelloMessage | |
| 41 * | |
| 42 * The ss->handshake function returns SECWouldBlock under these conditions: | |
| 43 * 1. ssl_GatherRecord1stHandshake called ssl2_GatherData which read in | |
| 44 * the beginning of an SSL v3 hello message and returned SECWouldBlock | |
| 45 * to switch to SSL v3 handshake processing. | |
| 46 * | |
| 47 * 2. ssl2_HandleClientHelloMessage discovered version 3.0 in the incoming | |
| 48 * v2 client hello msg, and called ssl3_HandleV2ClientHello which | |
| 49 * returned SECWouldBlock. | |
| 50 * | |
| 51 * 3. SECWouldBlock was returned by one of the callback functions, via | |
| 52 * one of these paths: | |
| 53 * - ssl2_HandleMessage() -> ssl2_HandleRequestCertificate() -> | |
| 54 * ss->getClientAuthData() | |
| 55 * | |
| 56 * - ssl2_HandleServerHelloMessage() -> ss->handleBadCert() | |
| 57 * | |
| 58 * - ssl_GatherRecord1stHandshake() -> ssl3_GatherCompleteHandshake() -> | |
| 59 * ssl3_HandleRecord() -> ssl3_HandleHandshake() -> | |
| 60 * ssl3_HandleHandshakeMessage() -> ssl3_HandleCertificate() -> | |
| 61 * ss->handleBadCert() | |
| 62 * | |
| 63 * - ssl_GatherRecord1stHandshake() -> ssl3_GatherCompleteHandshake() -> | |
| 64 * ssl3_HandleRecord() -> ssl3_HandleHandshake() -> | |
| 65 * ssl3_HandleHandshakeMessage() -> ssl3_HandleCertificateRequest() -> | |
| 66 * ss->getClientAuthData() | |
| 67 * | |
| 68 * Called from: SSL_ForceHandshake (below), | |
| 69 * ssl_SecureRecv (below) and | |
| 70 * ssl_SecureSend (below) | |
| 71 * from: WaitForResponse in sslsocks.c | |
| 72 * ssl_SocksRecv in sslsocks.c | |
| 73 * ssl_SocksSend in sslsocks.c | |
| 74 * | |
| 75 * Caller must hold the (write) handshakeLock. | |
| 76 */ | |
| 77 int | |
| 78 ssl_Do1stHandshake(sslSocket *ss) | |
| 79 { | |
| 80 int rv = SECSuccess; | |
| 81 int loopCount = 0; | |
| 82 | |
| 83 do { | |
| 84 PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss)); | |
| 85 PORT_Assert(ss->opt.noLocks || !ssl_HaveRecvBufLock(ss)); | |
| 86 PORT_Assert(ss->opt.noLocks || !ssl_HaveXmitBufLock(ss)); | |
| 87 PORT_Assert(ss->opt.noLocks || !ssl_HaveSSL3HandshakeLock(ss)); | |
| 88 | |
| 89 if (ss->handshake == 0) { | |
| 90 /* Previous handshake finished. Switch to next one */ | |
| 91 ss->handshake = ss->nextHandshake; | |
| 92 ss->nextHandshake = 0; | |
| 93 } | |
| 94 if (ss->handshake == 0) { | |
| 95 /* Previous handshake finished. Switch to security handshake */ | |
| 96 ss->handshake = ss->securityHandshake; | |
| 97 ss->securityHandshake = 0; | |
| 98 } | |
| 99 if (ss->handshake == 0) { | |
| 100 /* for v3 this is done in ssl3_FinishHandshake */ | |
| 101 if (!ss->firstHsDone && ss->version < SSL_LIBRARY_VERSION_3_0) { | |
| 102 ssl_GetRecvBufLock(ss); | |
| 103 ss->gs.recordLen = 0; | |
| 104 ssl_FinishHandshake(ss); | |
| 105 ssl_ReleaseRecvBufLock(ss); | |
| 106 } | |
| 107 break; | |
| 108 } | |
| 109 rv = (*ss->handshake)(ss); | |
| 110 ++loopCount; | |
| 111 /* This code must continue to loop on SECWouldBlock, | |
| 112 * or any positive value. See XXX_1 comments. | |
| 113 */ | |
| 114 } while (rv != SECFailure); /* was (rv >= 0); XXX_1 */ | |
| 115 | |
| 116 PORT_Assert(ss->opt.noLocks || !ssl_HaveRecvBufLock(ss)); | |
| 117 PORT_Assert(ss->opt.noLocks || !ssl_HaveXmitBufLock(ss)); | |
| 118 PORT_Assert(ss->opt.noLocks || !ssl_HaveSSL3HandshakeLock(ss)); | |
| 119 | |
| 120 if (rv == SECWouldBlock) { | |
| 121 PORT_SetError(PR_WOULD_BLOCK_ERROR); | |
| 122 rv = SECFailure; | |
| 123 } | |
| 124 return rv; | |
| 125 } | |
| 126 | |
| 127 void | |
| 128 ssl_FinishHandshake(sslSocket *ss) | |
| 129 { | |
| 130 PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss)); | |
| 131 PORT_Assert(ss->opt.noLocks || ssl_HaveRecvBufLock(ss)); | |
| 132 | |
| 133 SSL_TRC(3, ("%d: SSL[%d]: handshake is completed", SSL_GETPID(), ss->fd)); | |
| 134 | |
| 135 ss->firstHsDone = PR_TRUE; | |
| 136 ss->enoughFirstHsDone = PR_TRUE; | |
| 137 ss->gs.writeOffset = 0; | |
| 138 ss->gs.readOffset = 0; | |
| 139 | |
| 140 if (ss->handshakeCallback) { | |
| 141 PORT_Assert(ss->version < SSL_LIBRARY_VERSION_3_0 || | |
| 142 (ss->ssl3.hs.preliminaryInfo & ssl_preinfo_all) == | |
| 143 ssl_preinfo_all); | |
| 144 (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData); | |
| 145 } | |
| 146 } | |
| 147 | |
| 148 /* | |
| 149 * Handshake function that blocks. Used to force a | |
| 150 * retry on a connection on the next read/write. | |
| 151 */ | |
| 152 static SECStatus | |
| 153 ssl3_AlwaysBlock(sslSocket *ss) | |
| 154 { | |
| 155 PORT_SetError(PR_WOULD_BLOCK_ERROR); /* perhaps redundant. */ | |
| 156 return SECWouldBlock; | |
| 157 } | |
| 158 | |
| 159 /* | |
| 160 * set the initial handshake state machine to block | |
| 161 */ | |
| 162 void | |
| 163 ssl3_SetAlwaysBlock(sslSocket *ss) | |
| 164 { | |
| 165 if (!ss->firstHsDone) { | |
| 166 ss->handshake = ssl3_AlwaysBlock; | |
| 167 ss->nextHandshake = 0; | |
| 168 } | |
| 169 } | |
| 170 | |
| 171 static SECStatus | |
| 172 ssl_SetTimeout(PRFileDesc *fd, PRIntervalTime timeout) | |
| 173 { | |
| 174 sslSocket *ss; | |
| 175 | |
| 176 ss = ssl_FindSocket(fd); | |
| 177 if (!ss) { | |
| 178 SSL_DBG(("%d: SSL[%d]: bad socket in SetTimeout", SSL_GETPID(), fd)); | |
| 179 return SECFailure; | |
| 180 } | |
| 181 SSL_LOCK_READER(ss); | |
| 182 ss->rTimeout = timeout; | |
| 183 if (ss->opt.fdx) { | |
| 184 SSL_LOCK_WRITER(ss); | |
| 185 } | |
| 186 ss->wTimeout = timeout; | |
| 187 if (ss->opt.fdx) { | |
| 188 SSL_UNLOCK_WRITER(ss); | |
| 189 } | |
| 190 SSL_UNLOCK_READER(ss); | |
| 191 return SECSuccess; | |
| 192 } | |
| 193 | |
| 194 /* Acquires and releases HandshakeLock. | |
| 195 */ | |
| 196 SECStatus | |
| 197 SSL_ResetHandshake(PRFileDesc *s, PRBool asServer) | |
| 198 { | |
| 199 sslSocket *ss; | |
| 200 SECStatus status; | |
| 201 PRNetAddr addr; | |
| 202 | |
| 203 ss = ssl_FindSocket(s); | |
| 204 if (!ss) { | |
| 205 SSL_DBG(("%d: SSL[%d]: bad socket in ResetHandshake", SSL_GETPID(), s)); | |
| 206 return SECFailure; | |
| 207 } | |
| 208 | |
| 209 /* Don't waste my time */ | |
| 210 if (!ss->opt.useSecurity) | |
| 211 return SECSuccess; | |
| 212 | |
| 213 SSL_LOCK_READER(ss); | |
| 214 SSL_LOCK_WRITER(ss); | |
| 215 | |
| 216 /* Reset handshake state */ | |
| 217 ssl_Get1stHandshakeLock(ss); | |
| 218 | |
| 219 ss->firstHsDone = PR_FALSE; | |
| 220 ss->enoughFirstHsDone = PR_FALSE; | |
| 221 if (asServer) { | |
| 222 ss->handshake = ssl2_BeginServerHandshake; | |
| 223 ss->handshaking = sslHandshakingAsServer; | |
| 224 } else { | |
| 225 ss->handshake = ssl2_BeginClientHandshake; | |
| 226 ss->handshaking = sslHandshakingAsClient; | |
| 227 } | |
| 228 ss->nextHandshake = 0; | |
| 229 ss->securityHandshake = 0; | |
| 230 | |
| 231 ssl_GetRecvBufLock(ss); | |
| 232 status = ssl_InitGather(&ss->gs); | |
| 233 ssl_ReleaseRecvBufLock(ss); | |
| 234 | |
| 235 ssl_GetSSL3HandshakeLock(ss); | |
| 236 ss->ssl3.hs.canFalseStart = PR_FALSE; | |
| 237 ss->ssl3.hs.restartTarget = NULL; | |
| 238 | |
| 239 /* | |
| 240 ** Blow away old security state and get a fresh setup. | |
| 241 */ | |
| 242 ssl_GetXmitBufLock(ss); | |
| 243 ssl_ResetSecurityInfo(&ss->sec, PR_TRUE); | |
| 244 status = ssl_CreateSecurityInfo(ss); | |
| 245 ssl_ReleaseXmitBufLock(ss); | |
| 246 | |
| 247 ssl_ReleaseSSL3HandshakeLock(ss); | |
| 248 ssl_Release1stHandshakeLock(ss); | |
| 249 | |
| 250 if (!ss->TCPconnected) | |
| 251 ss->TCPconnected = (PR_SUCCESS == ssl_DefGetpeername(ss, &addr)); | |
| 252 | |
| 253 SSL_UNLOCK_WRITER(ss); | |
| 254 SSL_UNLOCK_READER(ss); | |
| 255 | |
| 256 return status; | |
| 257 } | |
| 258 | |
| 259 /* For SSLv2, does nothing but return an error. | |
| 260 ** For SSLv3, flushes SID cache entry (if requested), | |
| 261 ** and then starts new client hello or hello request. | |
| 262 ** Acquires and releases HandshakeLock. | |
| 263 */ | |
| 264 SECStatus | |
| 265 SSL_ReHandshake(PRFileDesc *fd, PRBool flushCache) | |
| 266 { | |
| 267 sslSocket *ss; | |
| 268 SECStatus rv; | |
| 269 | |
| 270 ss = ssl_FindSocket(fd); | |
| 271 if (!ss) { | |
| 272 SSL_DBG(("%d: SSL[%d]: bad socket in RedoHandshake", SSL_GETPID(), fd)); | |
| 273 return SECFailure; | |
| 274 } | |
| 275 | |
| 276 if (!ss->opt.useSecurity) | |
| 277 return SECSuccess; | |
| 278 | |
| 279 ssl_Get1stHandshakeLock(ss); | |
| 280 | |
| 281 /* SSL v2 protocol does not support subsequent handshakes. */ | |
| 282 if (ss->version < SSL_LIBRARY_VERSION_3_0) { | |
| 283 PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2); | |
| 284 rv = SECFailure; | |
| 285 } else { | |
| 286 ssl_GetSSL3HandshakeLock(ss); | |
| 287 rv = ssl3_RedoHandshake(ss, flushCache); /* force full handshake. */ | |
| 288 ssl_ReleaseSSL3HandshakeLock(ss); | |
| 289 } | |
| 290 | |
| 291 ssl_Release1stHandshakeLock(ss); | |
| 292 | |
| 293 return rv; | |
| 294 } | |
| 295 | |
| 296 /* | |
| 297 ** Same as above, but with an I/O timeout. | |
| 298 */ | |
| 299 SSL_IMPORT SECStatus | |
| 300 SSL_ReHandshakeWithTimeout(PRFileDesc *fd, | |
| 301 PRBool flushCache, | |
| 302 PRIntervalTime timeout) | |
| 303 { | |
| 304 if (SECSuccess != ssl_SetTimeout(fd, timeout)) { | |
| 305 return SECFailure; | |
| 306 } | |
| 307 return SSL_ReHandshake(fd, flushCache); | |
| 308 } | |
| 309 | |
| 310 SECStatus | |
| 311 SSL_RedoHandshake(PRFileDesc *fd) | |
| 312 { | |
| 313 return SSL_ReHandshake(fd, PR_TRUE); | |
| 314 } | |
| 315 | |
| 316 /* Register an application callback to be called when SSL handshake completes. | |
| 317 ** Acquires and releases HandshakeLock. | |
| 318 */ | |
| 319 SECStatus | |
| 320 SSL_HandshakeCallback(PRFileDesc *fd, SSLHandshakeCallback cb, | |
| 321 void *client_data) | |
| 322 { | |
| 323 sslSocket *ss; | |
| 324 | |
| 325 ss = ssl_FindSocket(fd); | |
| 326 if (!ss) { | |
| 327 SSL_DBG(("%d: SSL[%d]: bad socket in HandshakeCallback", | |
| 328 SSL_GETPID(), fd)); | |
| 329 return SECFailure; | |
| 330 } | |
| 331 | |
| 332 if (!ss->opt.useSecurity) { | |
| 333 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 334 return SECFailure; | |
| 335 } | |
| 336 | |
| 337 ssl_Get1stHandshakeLock(ss); | |
| 338 ssl_GetSSL3HandshakeLock(ss); | |
| 339 | |
| 340 ss->handshakeCallback = cb; | |
| 341 ss->handshakeCallbackData = client_data; | |
| 342 | |
| 343 ssl_ReleaseSSL3HandshakeLock(ss); | |
| 344 ssl_Release1stHandshakeLock(ss); | |
| 345 | |
| 346 return SECSuccess; | |
| 347 } | |
| 348 | |
| 349 /* Register an application callback to be called when false start may happen. | |
| 350 ** Acquires and releases HandshakeLock. | |
| 351 */ | |
| 352 SECStatus | |
| 353 SSL_SetCanFalseStartCallback(PRFileDesc *fd, SSLCanFalseStartCallback cb, | |
| 354 void *arg) | |
| 355 { | |
| 356 sslSocket *ss; | |
| 357 | |
| 358 ss = ssl_FindSocket(fd); | |
| 359 if (!ss) { | |
| 360 SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetCanFalseStartCallback", | |
| 361 SSL_GETPID(), fd)); | |
| 362 return SECFailure; | |
| 363 } | |
| 364 | |
| 365 if (!ss->opt.useSecurity) { | |
| 366 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 367 return SECFailure; | |
| 368 } | |
| 369 | |
| 370 ssl_Get1stHandshakeLock(ss); | |
| 371 ssl_GetSSL3HandshakeLock(ss); | |
| 372 | |
| 373 ss->canFalseStartCallback = cb; | |
| 374 ss->canFalseStartCallbackData = arg; | |
| 375 | |
| 376 ssl_ReleaseSSL3HandshakeLock(ss); | |
| 377 ssl_Release1stHandshakeLock(ss); | |
| 378 | |
| 379 return SECSuccess; | |
| 380 } | |
| 381 | |
| 382 SECStatus | |
| 383 SSL_RecommendedCanFalseStart(PRFileDesc *fd, PRBool *canFalseStart) | |
| 384 { | |
| 385 sslSocket *ss; | |
| 386 | |
| 387 *canFalseStart = PR_FALSE; | |
| 388 ss = ssl_FindSocket(fd); | |
| 389 if (!ss) { | |
| 390 SSL_DBG(("%d: SSL[%d]: bad socket in SSL_RecommendedCanFalseStart", | |
| 391 SSL_GETPID(), fd)); | |
| 392 return SECFailure; | |
| 393 } | |
| 394 | |
| 395 if (!ss->ssl3.initialized) { | |
| 396 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 397 return SECFailure; | |
| 398 } | |
| 399 | |
| 400 if (ss->version < SSL_LIBRARY_VERSION_3_0) { | |
| 401 PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2); | |
| 402 return SECFailure; | |
| 403 } | |
| 404 | |
| 405 /* Require a forward-secret key exchange. */ | |
| 406 *canFalseStart = ss->ssl3.hs.kea_def->kea == kea_dhe_dss || | |
| 407 ss->ssl3.hs.kea_def->kea == kea_dhe_rsa || | |
| 408 ss->ssl3.hs.kea_def->kea == kea_ecdhe_ecdsa || | |
| 409 ss->ssl3.hs.kea_def->kea == kea_ecdhe_rsa; | |
| 410 | |
| 411 return SECSuccess; | |
| 412 } | |
| 413 | |
| 414 /* Try to make progress on an SSL handshake by attempting to read the | |
| 415 ** next handshake from the peer, and sending any responses. | |
| 416 ** For non-blocking sockets, returns PR_ERROR_WOULD_BLOCK if it cannot | |
| 417 ** read the next handshake from the underlying socket. | |
| 418 ** For SSLv2, returns when handshake is complete or fatal error occurs. | |
| 419 ** For SSLv3, returns when handshake is complete, or application data has | |
| 420 ** arrived that must be taken by application before handshake can continue, | |
| 421 ** or a fatal error occurs. | |
| 422 ** Application should use handshake completion callback to tell which. | |
| 423 */ | |
| 424 SECStatus | |
| 425 SSL_ForceHandshake(PRFileDesc *fd) | |
| 426 { | |
| 427 sslSocket *ss; | |
| 428 SECStatus rv = SECFailure; | |
| 429 | |
| 430 ss = ssl_FindSocket(fd); | |
| 431 if (!ss) { | |
| 432 SSL_DBG(("%d: SSL[%d]: bad socket in ForceHandshake", | |
| 433 SSL_GETPID(), fd)); | |
| 434 return rv; | |
| 435 } | |
| 436 | |
| 437 /* Don't waste my time */ | |
| 438 if (!ss->opt.useSecurity) | |
| 439 return SECSuccess; | |
| 440 | |
| 441 if (!ssl_SocketIsBlocking(ss)) { | |
| 442 ssl_GetXmitBufLock(ss); | |
| 443 if (ss->pendingBuf.len != 0) { | |
| 444 int sent = ssl_SendSavedWriteData(ss); | |
| 445 if ((sent < 0) && (PORT_GetError() != PR_WOULD_BLOCK_ERROR)) { | |
| 446 ssl_ReleaseXmitBufLock(ss); | |
| 447 return SECFailure; | |
| 448 } | |
| 449 } | |
| 450 ssl_ReleaseXmitBufLock(ss); | |
| 451 } | |
| 452 | |
| 453 ssl_Get1stHandshakeLock(ss); | |
| 454 | |
| 455 if (ss->version >= SSL_LIBRARY_VERSION_3_0) { | |
| 456 int gatherResult; | |
| 457 | |
| 458 ssl_GetRecvBufLock(ss); | |
| 459 gatherResult = ssl3_GatherCompleteHandshake(ss, 0); | |
| 460 ssl_ReleaseRecvBufLock(ss); | |
| 461 if (gatherResult > 0) { | |
| 462 rv = SECSuccess; | |
| 463 } else if (gatherResult == 0) { | |
| 464 PORT_SetError(PR_END_OF_FILE_ERROR); | |
| 465 } else if (gatherResult == SECWouldBlock) { | |
| 466 PORT_SetError(PR_WOULD_BLOCK_ERROR); | |
| 467 } | |
| 468 } else if (!ss->firstHsDone) { | |
| 469 rv = ssl_Do1stHandshake(ss); | |
| 470 } else { | |
| 471 /* tried to force handshake on an SSL 2 socket that has | |
| 472 ** already completed the handshake. */ | |
| 473 rv = SECSuccess; /* just pretend we did it. */ | |
| 474 } | |
| 475 | |
| 476 ssl_Release1stHandshakeLock(ss); | |
| 477 | |
| 478 return rv; | |
| 479 } | |
| 480 | |
| 481 /* | |
| 482 ** Same as above, but with an I/O timeout. | |
| 483 */ | |
| 484 SSL_IMPORT SECStatus | |
| 485 SSL_ForceHandshakeWithTimeout(PRFileDesc *fd, | |
| 486 PRIntervalTime timeout) | |
| 487 { | |
| 488 if (SECSuccess != ssl_SetTimeout(fd, timeout)) { | |
| 489 return SECFailure; | |
| 490 } | |
| 491 return SSL_ForceHandshake(fd); | |
| 492 } | |
| 493 | |
| 494 /************************************************************************/ | |
| 495 | |
| 496 /* | |
| 497 ** Grow a buffer to hold newLen bytes of data. | |
| 498 ** Called for both recv buffers and xmit buffers. | |
| 499 ** Caller must hold xmitBufLock or recvBufLock, as appropriate. | |
| 500 */ | |
| 501 SECStatus | |
| 502 sslBuffer_Grow(sslBuffer *b, unsigned int newLen) | |
| 503 { | |
| 504 newLen = PR_MAX(newLen, MAX_FRAGMENT_LENGTH + 2048); | |
| 505 if (newLen > b->space) { | |
| 506 unsigned char *newBuf; | |
| 507 if (b->buf) { | |
| 508 newBuf = (unsigned char *)PORT_Realloc(b->buf, newLen); | |
| 509 } else { | |
| 510 newBuf = (unsigned char *)PORT_Alloc(newLen); | |
| 511 } | |
| 512 if (!newBuf) { | |
| 513 return SECFailure; | |
| 514 } | |
| 515 SSL_TRC(10, ("%d: SSL: grow buffer from %d to %d", | |
| 516 SSL_GETPID(), b->space, newLen)); | |
| 517 b->buf = newBuf; | |
| 518 b->space = newLen; | |
| 519 } | |
| 520 return SECSuccess; | |
| 521 } | |
| 522 | |
| 523 SECStatus | |
| 524 sslBuffer_Append(sslBuffer *b, const void *data, unsigned int len) | |
| 525 { | |
| 526 unsigned int newLen = b->len + len; | |
| 527 SECStatus rv; | |
| 528 | |
| 529 rv = sslBuffer_Grow(b, newLen); | |
| 530 if (rv != SECSuccess) | |
| 531 return rv; | |
| 532 PORT_Memcpy(b->buf + b->len, data, len); | |
| 533 b->len += len; | |
| 534 return SECSuccess; | |
| 535 } | |
| 536 | |
| 537 /* | |
| 538 ** Save away write data that is trying to be written before the security | |
| 539 ** handshake has been completed. When the handshake is completed, we will | |
| 540 ** flush this data out. | |
| 541 ** Caller must hold xmitBufLock | |
| 542 */ | |
| 543 SECStatus | |
| 544 ssl_SaveWriteData(sslSocket *ss, const void *data, unsigned int len) | |
| 545 { | |
| 546 SECStatus rv; | |
| 547 | |
| 548 PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); | |
| 549 rv = sslBuffer_Append(&ss->pendingBuf, data, len); | |
| 550 SSL_TRC(5, ("%d: SSL[%d]: saving %u bytes of data (%u total saved so far)", | |
| 551 SSL_GETPID(), ss->fd, len, ss->pendingBuf.len)); | |
| 552 return rv; | |
| 553 } | |
| 554 | |
| 555 /* | |
| 556 ** Send saved write data. This will flush out data sent prior to a | |
| 557 ** complete security handshake. Hopefully there won't be too much of it. | |
| 558 ** Returns count of the bytes sent, NOT a SECStatus. | |
| 559 ** Caller must hold xmitBufLock | |
| 560 */ | |
| 561 int | |
| 562 ssl_SendSavedWriteData(sslSocket *ss) | |
| 563 { | |
| 564 int rv = 0; | |
| 565 | |
| 566 PORT_Assert(ss->opt.noLocks || ssl_HaveXmitBufLock(ss)); | |
| 567 if (ss->pendingBuf.len != 0) { | |
| 568 SSL_TRC(5, ("%d: SSL[%d]: sending %d bytes of saved data", | |
| 569 SSL_GETPID(), ss->fd, ss->pendingBuf.len)); | |
| 570 rv = ssl_DefSend(ss, ss->pendingBuf.buf, ss->pendingBuf.len, 0); | |
| 571 if (rv < 0) { | |
| 572 return rv; | |
| 573 } | |
| 574 ss->pendingBuf.len -= rv; | |
| 575 if (ss->pendingBuf.len > 0 && rv > 0) { | |
| 576 /* UGH !! This shifts the whole buffer down by copying it */ | |
| 577 PORT_Memmove(ss->pendingBuf.buf, ss->pendingBuf.buf + rv, | |
| 578 ss->pendingBuf.len); | |
| 579 } | |
| 580 } | |
| 581 return rv; | |
| 582 } | |
| 583 | |
| 584 /************************************************************************/ | |
| 585 | |
| 586 /* | |
| 587 ** Receive some application data on a socket. Reads SSL records from the input | |
| 588 ** stream, decrypts them and then copies them to the output buffer. | |
| 589 ** Called from ssl_SecureRecv() below. | |
| 590 ** | |
| 591 ** Caller does NOT hold 1stHandshakeLock because that handshake is over. | |
| 592 ** Caller doesn't call this until initial handshake is complete. | |
| 593 ** For SSLv2, there is no subsequent handshake. | |
| 594 ** For SSLv3, the call to ssl3_GatherAppDataRecord may encounter handshake | |
| 595 ** messages from a subsequent handshake. | |
| 596 ** | |
| 597 ** This code is similar to, and easily confused with, | |
| 598 ** ssl_GatherRecord1stHandshake() in sslcon.c | |
| 599 */ | |
| 600 static int | |
| 601 DoRecv(sslSocket *ss, unsigned char *out, int len, int flags) | |
| 602 { | |
| 603 int rv; | |
| 604 int amount; | |
| 605 int available; | |
| 606 | |
| 607 /* ssl3_GatherAppDataRecord may call ssl_FinishHandshake, which needs the | |
| 608 * 1stHandshakeLock. */ | |
| 609 ssl_Get1stHandshakeLock(ss); | |
| 610 ssl_GetRecvBufLock(ss); | |
| 611 | |
| 612 available = ss->gs.writeOffset - ss->gs.readOffset; | |
| 613 if (available == 0) { | |
| 614 /* Get some more data */ | |
| 615 if (ss->version >= SSL_LIBRARY_VERSION_3_0) { | |
| 616 /* Wait for application data to arrive. */ | |
| 617 rv = ssl3_GatherAppDataRecord(ss, 0); | |
| 618 } else { | |
| 619 /* See if we have a complete record */ | |
| 620 rv = ssl2_GatherRecord(ss, 0); | |
| 621 } | |
| 622 if (rv <= 0) { | |
| 623 if (rv == 0) { | |
| 624 /* EOF */ | |
| 625 SSL_TRC(10, ("%d: SSL[%d]: ssl_recv EOF", | |
| 626 SSL_GETPID(), ss->fd)); | |
| 627 goto done; | |
| 628 } | |
| 629 if ((rv != SECWouldBlock) && | |
| 630 (PR_GetError() != PR_WOULD_BLOCK_ERROR)) { | |
| 631 /* Some random error */ | |
| 632 goto done; | |
| 633 } | |
| 634 | |
| 635 /* | |
| 636 ** Gather record is blocked waiting for more record data to | |
| 637 ** arrive. Try to process what we have already received | |
| 638 */ | |
| 639 } else { | |
| 640 /* Gather record has finished getting a complete record */ | |
| 641 } | |
| 642 | |
| 643 /* See if any clear data is now available */ | |
| 644 available = ss->gs.writeOffset - ss->gs.readOffset; | |
| 645 if (available == 0) { | |
| 646 /* | |
| 647 ** No partial data is available. Force error code to | |
| 648 ** EWOULDBLOCK so that caller will try again later. Note | |
| 649 ** that the error code is probably EWOULDBLOCK already, | |
| 650 ** but if it isn't (for example, if we received a zero | |
| 651 ** length record) then this will force it to be correct. | |
| 652 */ | |
| 653 PORT_SetError(PR_WOULD_BLOCK_ERROR); | |
| 654 rv = SECFailure; | |
| 655 goto done; | |
| 656 } | |
| 657 SSL_TRC(30, ("%d: SSL[%d]: partial data ready, available=%d", | |
| 658 SSL_GETPID(), ss->fd, available)); | |
| 659 } | |
| 660 | |
| 661 if (IS_DTLS(ss) && (len < available)) { | |
| 662 /* DTLS does not allow you to do partial reads */ | |
| 663 SSL_TRC(30, ("%d: SSL[%d]: DTLS short read. len=%d available=%d", | |
| 664 SSL_GETPID(), ss->fd, len, available)); | |
| 665 ss->gs.readOffset += available; | |
| 666 PORT_SetError(SSL_ERROR_RX_SHORT_DTLS_READ); | |
| 667 rv = SECFailure; | |
| 668 goto done; | |
| 669 } | |
| 670 | |
| 671 /* Dole out clear data to reader */ | |
| 672 amount = PR_MIN(len, available); | |
| 673 PORT_Memcpy(out, ss->gs.buf.buf + ss->gs.readOffset, amount); | |
| 674 if (!(flags & PR_MSG_PEEK)) { | |
| 675 ss->gs.readOffset += amount; | |
| 676 } | |
| 677 PORT_Assert(ss->gs.readOffset <= ss->gs.writeOffset); | |
| 678 rv = amount; | |
| 679 | |
| 680 SSL_TRC(30, ("%d: SSL[%d]: amount=%d available=%d", | |
| 681 SSL_GETPID(), ss->fd, amount, available)); | |
| 682 PRINT_BUF(4, (ss, "DoRecv receiving plaintext:", out, amount)); | |
| 683 | |
| 684 done: | |
| 685 ssl_ReleaseRecvBufLock(ss); | |
| 686 ssl_Release1stHandshakeLock(ss); | |
| 687 return rv; | |
| 688 } | |
| 689 | |
| 690 /************************************************************************/ | |
| 691 | |
| 692 /* | |
| 693 ** Return SSLKEAType derived from cert's Public Key algorithm info. | |
| 694 */ | |
| 695 SSLKEAType | |
| 696 NSS_FindCertKEAType(CERTCertificate *cert) | |
| 697 { | |
| 698 SSLKEAType keaType = kt_null; | |
| 699 int tag; | |
| 700 | |
| 701 if (!cert) | |
| 702 goto loser; | |
| 703 | |
| 704 tag = SECOID_GetAlgorithmTag(&(cert->subjectPublicKeyInfo.algorithm)); | |
| 705 | |
| 706 switch (tag) { | |
| 707 case SEC_OID_X500_RSA_ENCRYPTION: | |
| 708 case SEC_OID_PKCS1_RSA_ENCRYPTION: | |
| 709 keaType = kt_rsa; | |
| 710 break; | |
| 711 case SEC_OID_ANSIX9_DSA_SIGNATURE: /* hah, signature, not a key? */ | |
| 712 case SEC_OID_X942_DIFFIE_HELMAN_KEY: | |
| 713 keaType = kt_dh; | |
| 714 break; | |
| 715 #ifndef NSS_DISABLE_ECC | |
| 716 case SEC_OID_ANSIX962_EC_PUBLIC_KEY: | |
| 717 keaType = kt_ecdh; | |
| 718 break; | |
| 719 #endif /* NSS_DISABLE_ECC */ | |
| 720 default: | |
| 721 keaType = kt_null; | |
| 722 } | |
| 723 | |
| 724 loser: | |
| 725 | |
| 726 return keaType; | |
| 727 } | |
| 728 | |
| 729 static const PRCallOnceType pristineCallOnce; | |
| 730 static PRCallOnceType setupServerCAListOnce; | |
| 731 | |
| 732 static SECStatus | |
| 733 serverCAListShutdown(void *appData, void *nssData) | |
| 734 { | |
| 735 PORT_Assert(ssl3_server_ca_list); | |
| 736 if (ssl3_server_ca_list) { | |
| 737 CERT_FreeDistNames(ssl3_server_ca_list); | |
| 738 ssl3_server_ca_list = NULL; | |
| 739 } | |
| 740 setupServerCAListOnce = pristineCallOnce; | |
| 741 return SECSuccess; | |
| 742 } | |
| 743 | |
| 744 static PRStatus | |
| 745 serverCAListSetup(void *arg) | |
| 746 { | |
| 747 CERTCertDBHandle *dbHandle = (CERTCertDBHandle *)arg; | |
| 748 SECStatus rv = NSS_RegisterShutdown(serverCAListShutdown, NULL); | |
| 749 PORT_Assert(SECSuccess == rv); | |
| 750 if (SECSuccess == rv) { | |
| 751 ssl3_server_ca_list = CERT_GetSSLCACerts(dbHandle); | |
| 752 return PR_SUCCESS; | |
| 753 } | |
| 754 return PR_FAILURE; | |
| 755 } | |
| 756 | |
| 757 SECStatus | |
| 758 ssl_ConfigSecureServer(sslSocket *ss, CERTCertificate *cert, | |
| 759 const CERTCertificateList *certChain, | |
| 760 ssl3KeyPair *keyPair, SSLKEAType kea) | |
| 761 { | |
| 762 CERTCertificateList *localCertChain = NULL; | |
| 763 sslServerCerts *sc = ss->serverCerts + kea; | |
| 764 | |
| 765 /* load the server certificate */ | |
| 766 if (sc->serverCert != NULL) { | |
| 767 CERT_DestroyCertificate(sc->serverCert); | |
| 768 sc->serverCert = NULL; | |
| 769 sc->serverKeyBits = 0; | |
| 770 } | |
| 771 /* load the server cert chain */ | |
| 772 if (sc->serverCertChain != NULL) { | |
| 773 CERT_DestroyCertificateList(sc->serverCertChain); | |
| 774 sc->serverCertChain = NULL; | |
| 775 } | |
| 776 if (cert) { | |
| 777 sc->serverCert = CERT_DupCertificate(cert); | |
| 778 /* get the size of the cert's public key, and remember it */ | |
| 779 sc->serverKeyBits = SECKEY_PublicKeyStrengthInBits(keyPair->pubKey); | |
| 780 if (!certChain) { | |
| 781 localCertChain = | |
| 782 CERT_CertChainFromCert(sc->serverCert, certUsageSSLServer, | |
| 783 PR_TRUE); | |
| 784 if (!localCertChain) | |
| 785 goto loser; | |
| 786 } | |
| 787 sc->serverCertChain = (certChain) ? CERT_DupCertList(certChain) : | |
| 788 localCertChain; | |
| 789 if (!sc->serverCertChain) { | |
| 790 goto loser; | |
| 791 } | |
| 792 localCertChain = NULL; /* consumed */ | |
| 793 } | |
| 794 | |
| 795 /* get keyPair */ | |
| 796 if (sc->serverKeyPair != NULL) { | |
| 797 ssl3_FreeKeyPair(sc->serverKeyPair); | |
| 798 sc->serverKeyPair = NULL; | |
| 799 } | |
| 800 if (keyPair) { | |
| 801 SECKEY_CacheStaticFlags(keyPair->privKey); | |
| 802 sc->serverKeyPair = ssl3_GetKeyPairRef(keyPair); | |
| 803 } | |
| 804 if (kea == kt_rsa && cert && sc->serverKeyBits > 512 && | |
| 805 !ss->opt.noStepDown && !ss->stepDownKeyPair) { | |
| 806 if (ssl3_CreateRSAStepDownKeys(ss) != SECSuccess) { | |
| 807 goto loser; | |
| 808 } | |
| 809 } | |
| 810 if (kea == ssl_kea_dh || kea == ssl_kea_rsa) { | |
| 811 if (ssl3_SelectDHParams(ss) != SECSuccess) { | |
| 812 goto loser; | |
| 813 } | |
| 814 } | |
| 815 return SECSuccess; | |
| 816 | |
| 817 loser: | |
| 818 if (localCertChain) { | |
| 819 CERT_DestroyCertificateList(localCertChain); | |
| 820 } | |
| 821 if (sc->serverCert != NULL) { | |
| 822 CERT_DestroyCertificate(sc->serverCert); | |
| 823 sc->serverCert = NULL; | |
| 824 } | |
| 825 if (sc->serverCertChain != NULL) { | |
| 826 CERT_DestroyCertificateList(sc->serverCertChain); | |
| 827 sc->serverCertChain = NULL; | |
| 828 } | |
| 829 if (sc->serverKeyPair != NULL) { | |
| 830 ssl3_FreeKeyPair(sc->serverKeyPair); | |
| 831 sc->serverKeyPair = NULL; | |
| 832 } | |
| 833 return SECFailure; | |
| 834 } | |
| 835 | |
| 836 /* XXX need to protect the data that gets changed here.!! */ | |
| 837 | |
| 838 SECStatus | |
| 839 SSL_ConfigSecureServer(PRFileDesc *fd, CERTCertificate *cert, | |
| 840 SECKEYPrivateKey *key, SSL3KEAType kea) | |
| 841 { | |
| 842 | |
| 843 return SSL_ConfigSecureServerWithCertChain(fd, cert, NULL, key, kea); | |
| 844 } | |
| 845 | |
| 846 SECStatus | |
| 847 SSL_ConfigSecureServerWithCertChain(PRFileDesc *fd, CERTCertificate *cert, | |
| 848 const CERTCertificateList *certChainOpt, | |
| 849 SECKEYPrivateKey *key, SSL3KEAType kea) | |
| 850 { | |
| 851 sslSocket *ss; | |
| 852 SECKEYPublicKey *pubKey = NULL; | |
| 853 ssl3KeyPair *keyPair = NULL; | |
| 854 SECStatus rv = SECFailure; | |
| 855 | |
| 856 ss = ssl_FindSocket(fd); | |
| 857 if (!ss) { | |
| 858 return SECFailure; | |
| 859 } | |
| 860 | |
| 861 /* Both key and cert must have a value or be NULL */ | |
| 862 /* Passing a value of NULL will turn off key exchange algorithms that were | |
| 863 * previously turned on */ | |
| 864 if (!cert != !key) { | |
| 865 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 866 return SECFailure; | |
| 867 } | |
| 868 | |
| 869 /* make sure the key exchange is recognized */ | |
| 870 if ((kea >= kt_kea_size) || (kea < kt_null)) { | |
| 871 PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG); | |
| 872 return SECFailure; | |
| 873 } | |
| 874 | |
| 875 if (kea != NSS_FindCertKEAType(cert)) { | |
| 876 PORT_SetError(SSL_ERROR_CERT_KEA_MISMATCH); | |
| 877 return SECFailure; | |
| 878 } | |
| 879 | |
| 880 if (cert) { | |
| 881 /* get the size of the cert's public key, and remember it */ | |
| 882 pubKey = CERT_ExtractPublicKey(cert); | |
| 883 if (!pubKey) | |
| 884 return SECFailure; | |
| 885 } | |
| 886 | |
| 887 if (key) { | |
| 888 SECKEYPrivateKey *keyCopy = NULL; | |
| 889 CK_MECHANISM_TYPE keyMech = CKM_INVALID_MECHANISM; | |
| 890 | |
| 891 if (key->pkcs11Slot) { | |
| 892 PK11SlotInfo *bestSlot; | |
| 893 bestSlot = PK11_ReferenceSlot(key->pkcs11Slot); | |
| 894 if (bestSlot) { | |
| 895 keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key); | |
| 896 PK11_FreeSlot(bestSlot); | |
| 897 } | |
| 898 } | |
| 899 if (keyCopy == NULL) | |
| 900 keyMech = PK11_MapSignKeyType(key->keyType); | |
| 901 if (keyMech != CKM_INVALID_MECHANISM) { | |
| 902 PK11SlotInfo *bestSlot; | |
| 903 /* XXX Maybe should be bestSlotMultiple? */ | |
| 904 bestSlot = PK11_GetBestSlot(keyMech, NULL /* wincx */); | |
| 905 if (bestSlot) { | |
| 906 keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key); | |
| 907 PK11_FreeSlot(bestSlot); | |
| 908 } | |
| 909 } | |
| 910 if (keyCopy == NULL) | |
| 911 keyCopy = SECKEY_CopyPrivateKey(key); | |
| 912 if (keyCopy == NULL) | |
| 913 goto loser; | |
| 914 keyPair = ssl3_NewKeyPair(keyCopy, pubKey); | |
| 915 if (keyPair == NULL) { | |
| 916 SECKEY_DestroyPrivateKey(keyCopy); | |
| 917 goto loser; | |
| 918 } | |
| 919 pubKey = NULL; /* adopted by serverKeyPair */ | |
| 920 } | |
| 921 if (ssl_ConfigSecureServer(ss, cert, certChainOpt, | |
| 922 keyPair, kea) == SECFailure) { | |
| 923 goto loser; | |
| 924 } | |
| 925 | |
| 926 /* Only do this once because it's global. */ | |
| 927 if (PR_SUCCESS == PR_CallOnceWithArg(&setupServerCAListOnce, | |
| 928 &serverCAListSetup, | |
| 929 (void *)(ss->dbHandle))) { | |
| 930 rv = SECSuccess; | |
| 931 } | |
| 932 | |
| 933 loser: | |
| 934 if (keyPair) { | |
| 935 ssl3_FreeKeyPair(keyPair); | |
| 936 } | |
| 937 if (pubKey) { | |
| 938 SECKEY_DestroyPublicKey(pubKey); | |
| 939 pubKey = NULL; | |
| 940 } | |
| 941 return rv; | |
| 942 } | |
| 943 | |
| 944 /************************************************************************/ | |
| 945 | |
| 946 SECStatus | |
| 947 ssl_CreateSecurityInfo(sslSocket *ss) | |
| 948 { | |
| 949 SECStatus status; | |
| 950 | |
| 951 /* initialize sslv2 socket to send data in the clear. */ | |
| 952 ssl2_UseClearSendFunc(ss); | |
| 953 | |
| 954 ss->sec.blockSize = 1; | |
| 955 ss->sec.blockShift = 0; | |
| 956 | |
| 957 ssl_GetXmitBufLock(ss); | |
| 958 status = sslBuffer_Grow(&ss->sec.writeBuf, 4096); | |
| 959 ssl_ReleaseXmitBufLock(ss); | |
| 960 | |
| 961 return status; | |
| 962 } | |
| 963 | |
| 964 SECStatus | |
| 965 ssl_CopySecurityInfo(sslSocket *ss, sslSocket *os) | |
| 966 { | |
| 967 ss->sec.send = os->sec.send; | |
| 968 ss->sec.isServer = os->sec.isServer; | |
| 969 ss->sec.keyBits = os->sec.keyBits; | |
| 970 ss->sec.secretKeyBits = os->sec.secretKeyBits; | |
| 971 | |
| 972 ss->sec.peerCert = CERT_DupCertificate(os->sec.peerCert); | |
| 973 if (os->sec.peerCert && !ss->sec.peerCert) | |
| 974 goto loser; | |
| 975 | |
| 976 ss->sec.cache = os->sec.cache; | |
| 977 ss->sec.uncache = os->sec.uncache; | |
| 978 | |
| 979 /* we don't dup the connection info. */ | |
| 980 | |
| 981 ss->sec.sendSequence = os->sec.sendSequence; | |
| 982 ss->sec.rcvSequence = os->sec.rcvSequence; | |
| 983 | |
| 984 if (os->sec.hash && os->sec.hashcx) { | |
| 985 ss->sec.hash = os->sec.hash; | |
| 986 ss->sec.hashcx = os->sec.hash->clone(os->sec.hashcx); | |
| 987 if (os->sec.hashcx && !ss->sec.hashcx) | |
| 988 goto loser; | |
| 989 } else { | |
| 990 ss->sec.hash = NULL; | |
| 991 ss->sec.hashcx = NULL; | |
| 992 } | |
| 993 | |
| 994 if (SECITEM_CopyItem(0, &ss->sec.sendSecret, &os->sec.sendSecret)) | |
| 995 goto loser; | |
| 996 if (SECITEM_CopyItem(0, &ss->sec.rcvSecret, &os->sec.rcvSecret)) | |
| 997 goto loser; | |
| 998 | |
| 999 /* XXX following code is wrong if either cx != 0 */ | |
| 1000 PORT_Assert(os->sec.readcx == 0); | |
| 1001 PORT_Assert(os->sec.writecx == 0); | |
| 1002 ss->sec.readcx = os->sec.readcx; | |
| 1003 ss->sec.writecx = os->sec.writecx; | |
| 1004 ss->sec.destroy = 0; | |
| 1005 | |
| 1006 ss->sec.enc = os->sec.enc; | |
| 1007 ss->sec.dec = os->sec.dec; | |
| 1008 | |
| 1009 ss->sec.blockShift = os->sec.blockShift; | |
| 1010 ss->sec.blockSize = os->sec.blockSize; | |
| 1011 | |
| 1012 return SECSuccess; | |
| 1013 | |
| 1014 loser: | |
| 1015 return SECFailure; | |
| 1016 } | |
| 1017 | |
| 1018 /* Reset sec back to its initial state. | |
| 1019 ** Caller holds any relevant locks. | |
| 1020 */ | |
| 1021 void | |
| 1022 ssl_ResetSecurityInfo(sslSecurityInfo *sec, PRBool doMemset) | |
| 1023 { | |
| 1024 /* Destroy MAC */ | |
| 1025 if (sec->hash && sec->hashcx) { | |
| 1026 (*sec->hash->destroy)(sec->hashcx, PR_TRUE); | |
| 1027 sec->hashcx = NULL; | |
| 1028 sec->hash = NULL; | |
| 1029 } | |
| 1030 SECITEM_ZfreeItem(&sec->sendSecret, PR_FALSE); | |
| 1031 SECITEM_ZfreeItem(&sec->rcvSecret, PR_FALSE); | |
| 1032 | |
| 1033 /* Destroy ciphers */ | |
| 1034 if (sec->destroy) { | |
| 1035 (*sec->destroy)(sec->readcx, PR_TRUE); | |
| 1036 (*sec->destroy)(sec->writecx, PR_TRUE); | |
| 1037 sec->readcx = NULL; | |
| 1038 sec->writecx = NULL; | |
| 1039 } else { | |
| 1040 PORT_Assert(sec->readcx == 0); | |
| 1041 PORT_Assert(sec->writecx == 0); | |
| 1042 } | |
| 1043 sec->readcx = 0; | |
| 1044 sec->writecx = 0; | |
| 1045 | |
| 1046 if (sec->localCert) { | |
| 1047 CERT_DestroyCertificate(sec->localCert); | |
| 1048 sec->localCert = NULL; | |
| 1049 } | |
| 1050 if (sec->peerCert) { | |
| 1051 CERT_DestroyCertificate(sec->peerCert); | |
| 1052 sec->peerCert = NULL; | |
| 1053 } | |
| 1054 if (sec->peerKey) { | |
| 1055 SECKEY_DestroyPublicKey(sec->peerKey); | |
| 1056 sec->peerKey = NULL; | |
| 1057 } | |
| 1058 | |
| 1059 /* cleanup the ci */ | |
| 1060 if (sec->ci.sid != NULL) { | |
| 1061 ssl_FreeSID(sec->ci.sid); | |
| 1062 } | |
| 1063 PORT_ZFree(sec->ci.sendBuf.buf, sec->ci.sendBuf.space); | |
| 1064 if (doMemset) { | |
| 1065 memset(&sec->ci, 0, sizeof sec->ci); | |
| 1066 } | |
| 1067 } | |
| 1068 | |
| 1069 /* | |
| 1070 ** Called from SSL_ResetHandshake (above), and | |
| 1071 ** from ssl_FreeSocket in sslsock.c | |
| 1072 ** Caller should hold relevant locks (e.g. XmitBufLock) | |
| 1073 */ | |
| 1074 void | |
| 1075 ssl_DestroySecurityInfo(sslSecurityInfo *sec) | |
| 1076 { | |
| 1077 ssl_ResetSecurityInfo(sec, PR_FALSE); | |
| 1078 | |
| 1079 PORT_ZFree(sec->writeBuf.buf, sec->writeBuf.space); | |
| 1080 sec->writeBuf.buf = 0; | |
| 1081 | |
| 1082 memset(sec, 0, sizeof *sec); | |
| 1083 } | |
| 1084 | |
| 1085 /************************************************************************/ | |
| 1086 | |
| 1087 int | |
| 1088 ssl_SecureConnect(sslSocket *ss, const PRNetAddr *sa) | |
| 1089 { | |
| 1090 PRFileDesc *osfd = ss->fd->lower; | |
| 1091 int rv; | |
| 1092 | |
| 1093 if (ss->opt.handshakeAsServer) { | |
| 1094 ss->securityHandshake = ssl2_BeginServerHandshake; | |
| 1095 ss->handshaking = sslHandshakingAsServer; | |
| 1096 } else { | |
| 1097 ss->securityHandshake = ssl2_BeginClientHandshake; | |
| 1098 ss->handshaking = sslHandshakingAsClient; | |
| 1099 } | |
| 1100 | |
| 1101 /* connect to server */ | |
| 1102 rv = osfd->methods->connect(osfd, sa, ss->cTimeout); | |
| 1103 if (rv == PR_SUCCESS) { | |
| 1104 ss->TCPconnected = 1; | |
| 1105 } else { | |
| 1106 int err = PR_GetError(); | |
| 1107 SSL_DBG(("%d: SSL[%d]: connect failed, errno=%d", | |
| 1108 SSL_GETPID(), ss->fd, err)); | |
| 1109 if (err == PR_IS_CONNECTED_ERROR) { | |
| 1110 ss->TCPconnected = 1; | |
| 1111 } | |
| 1112 } | |
| 1113 | |
| 1114 SSL_TRC(5, ("%d: SSL[%d]: secure connect completed, rv == %d", | |
| 1115 SSL_GETPID(), ss->fd, rv)); | |
| 1116 return rv; | |
| 1117 } | |
| 1118 | |
| 1119 /* | |
| 1120 * The TLS 1.2 RFC 5246, Section 7.2.1 says: | |
| 1121 * | |
| 1122 * Unless some other fatal alert has been transmitted, each party is | |
| 1123 * required to send a close_notify alert before closing the write side | |
| 1124 * of the connection. The other party MUST respond with a close_notify | |
| 1125 * alert of its own and close down the connection immediately, | |
| 1126 * discarding any pending writes. It is not required for the initiator | |
| 1127 * of the close to wait for the responding close_notify alert before | |
| 1128 * closing the read side of the connection. | |
| 1129 * | |
| 1130 * The second sentence requires that we send a close_notify alert when we | |
| 1131 * have received a close_notify alert. In practice, all SSL implementations | |
| 1132 * close the socket immediately after sending a close_notify alert (which is | |
| 1133 * allowed by the third sentence), so responding with a close_notify alert | |
| 1134 * would result in a write failure with the ECONNRESET error. This is why | |
| 1135 * we don't respond with a close_notify alert. | |
| 1136 * | |
| 1137 * Also, in the unlikely event that the TCP pipe is full and the peer stops | |
| 1138 * reading, the SSL3_SendAlert call in ssl_SecureClose and ssl_SecureShutdown | |
| 1139 * may block indefinitely in blocking mode, and may fail (without retrying) | |
| 1140 * in non-blocking mode. | |
| 1141 */ | |
| 1142 | |
| 1143 int | |
| 1144 ssl_SecureClose(sslSocket *ss) | |
| 1145 { | |
| 1146 int rv; | |
| 1147 | |
| 1148 if (ss->version >= SSL_LIBRARY_VERSION_3_0 && | |
| 1149 !(ss->shutdownHow & ssl_SHUTDOWN_SEND) && | |
| 1150 ss->firstHsDone && | |
| 1151 !ss->recvdCloseNotify && | |
| 1152 ss->ssl3.initialized) { | |
| 1153 | |
| 1154 /* We don't want the final alert to be Nagle delayed. */ | |
| 1155 if (!ss->delayDisabled) { | |
| 1156 ssl_EnableNagleDelay(ss, PR_FALSE); | |
| 1157 ss->delayDisabled = 1; | |
| 1158 } | |
| 1159 | |
| 1160 (void)SSL3_SendAlert(ss, alert_warning, close_notify); | |
| 1161 } | |
| 1162 rv = ssl_DefClose(ss); | |
| 1163 return rv; | |
| 1164 } | |
| 1165 | |
| 1166 /* Caller handles all locking */ | |
| 1167 int | |
| 1168 ssl_SecureShutdown(sslSocket *ss, int nsprHow) | |
| 1169 { | |
| 1170 PRFileDesc *osfd = ss->fd->lower; | |
| 1171 int rv; | |
| 1172 PRIntn sslHow = nsprHow + 1; | |
| 1173 | |
| 1174 if ((unsigned)nsprHow > PR_SHUTDOWN_BOTH) { | |
| 1175 PORT_SetError(PR_INVALID_ARGUMENT_ERROR); | |
| 1176 return PR_FAILURE; | |
| 1177 } | |
| 1178 | |
| 1179 if ((sslHow & ssl_SHUTDOWN_SEND) != 0 && | |
| 1180 ss->version >= SSL_LIBRARY_VERSION_3_0 && | |
| 1181 !(ss->shutdownHow & ssl_SHUTDOWN_SEND) && | |
| 1182 ss->firstHsDone && | |
| 1183 !ss->recvdCloseNotify && | |
| 1184 ss->ssl3.initialized) { | |
| 1185 | |
| 1186 (void)SSL3_SendAlert(ss, alert_warning, close_notify); | |
| 1187 } | |
| 1188 | |
| 1189 rv = osfd->methods->shutdown(osfd, nsprHow); | |
| 1190 | |
| 1191 ss->shutdownHow |= sslHow; | |
| 1192 | |
| 1193 return rv; | |
| 1194 } | |
| 1195 | |
| 1196 /************************************************************************/ | |
| 1197 | |
| 1198 int | |
| 1199 ssl_SecureRecv(sslSocket *ss, unsigned char *buf, int len, int flags) | |
| 1200 { | |
| 1201 int rv = 0; | |
| 1202 | |
| 1203 if (ss->shutdownHow & ssl_SHUTDOWN_RCV) { | |
| 1204 PORT_SetError(PR_SOCKET_SHUTDOWN_ERROR); | |
| 1205 return PR_FAILURE; | |
| 1206 } | |
| 1207 if (flags & ~PR_MSG_PEEK) { | |
| 1208 PORT_SetError(PR_INVALID_ARGUMENT_ERROR); | |
| 1209 return PR_FAILURE; | |
| 1210 } | |
| 1211 | |
| 1212 if (!ssl_SocketIsBlocking(ss) && !ss->opt.fdx) { | |
| 1213 ssl_GetXmitBufLock(ss); | |
| 1214 if (ss->pendingBuf.len != 0) { | |
| 1215 rv = ssl_SendSavedWriteData(ss); | |
| 1216 if ((rv < 0) && (PORT_GetError() != PR_WOULD_BLOCK_ERROR)) { | |
| 1217 ssl_ReleaseXmitBufLock(ss); | |
| 1218 return SECFailure; | |
| 1219 } | |
| 1220 } | |
| 1221 ssl_ReleaseXmitBufLock(ss); | |
| 1222 } | |
| 1223 | |
| 1224 rv = 0; | |
| 1225 /* If any of these is non-zero, the initial handshake is not done. */ | |
| 1226 if (!ss->firstHsDone) { | |
| 1227 ssl_Get1stHandshakeLock(ss); | |
| 1228 if (ss->handshake || ss->nextHandshake || ss->securityHandshake) { | |
| 1229 rv = ssl_Do1stHandshake(ss); | |
| 1230 } | |
| 1231 ssl_Release1stHandshakeLock(ss); | |
| 1232 } | |
| 1233 if (rv < 0) { | |
| 1234 return rv; | |
| 1235 } | |
| 1236 | |
| 1237 if (len == 0) | |
| 1238 return 0; | |
| 1239 | |
| 1240 rv = DoRecv(ss, (unsigned char *)buf, len, flags); | |
| 1241 SSL_TRC(2, ("%d: SSL[%d]: recving %d bytes securely (errno=%d)", | |
| 1242 SSL_GETPID(), ss->fd, rv, PORT_GetError())); | |
| 1243 return rv; | |
| 1244 } | |
| 1245 | |
| 1246 int | |
| 1247 ssl_SecureRead(sslSocket *ss, unsigned char *buf, int len) | |
| 1248 { | |
| 1249 return ssl_SecureRecv(ss, buf, len, 0); | |
| 1250 } | |
| 1251 | |
| 1252 /* Caller holds the SSL Socket's write lock. SSL_LOCK_WRITER(ss) */ | |
| 1253 int | |
| 1254 ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags) | |
| 1255 { | |
| 1256 int rv = 0; | |
| 1257 | |
| 1258 SSL_TRC(2, ("%d: SSL[%d]: SecureSend: sending %d bytes", | |
| 1259 SSL_GETPID(), ss->fd, len)); | |
| 1260 | |
| 1261 if (ss->shutdownHow & ssl_SHUTDOWN_SEND) { | |
| 1262 PORT_SetError(PR_SOCKET_SHUTDOWN_ERROR); | |
| 1263 rv = PR_FAILURE; | |
| 1264 goto done; | |
| 1265 } | |
| 1266 if (flags) { | |
| 1267 PORT_SetError(PR_INVALID_ARGUMENT_ERROR); | |
| 1268 rv = PR_FAILURE; | |
| 1269 goto done; | |
| 1270 } | |
| 1271 | |
| 1272 ssl_GetXmitBufLock(ss); | |
| 1273 if (ss->pendingBuf.len != 0) { | |
| 1274 PORT_Assert(ss->pendingBuf.len > 0); | |
| 1275 rv = ssl_SendSavedWriteData(ss); | |
| 1276 if (rv >= 0 && ss->pendingBuf.len != 0) { | |
| 1277 PORT_Assert(ss->pendingBuf.len > 0); | |
| 1278 PORT_SetError(PR_WOULD_BLOCK_ERROR); | |
| 1279 rv = SECFailure; | |
| 1280 } | |
| 1281 } | |
| 1282 ssl_ReleaseXmitBufLock(ss); | |
| 1283 if (rv < 0) { | |
| 1284 goto done; | |
| 1285 } | |
| 1286 | |
| 1287 if (len > 0) | |
| 1288 ss->writerThread = PR_GetCurrentThread(); | |
| 1289 /* If any of these is non-zero, the initial handshake is not done. */ | |
| 1290 if (!ss->firstHsDone) { | |
| 1291 PRBool falseStart = PR_FALSE; | |
| 1292 ssl_Get1stHandshakeLock(ss); | |
| 1293 if (ss->opt.enableFalseStart && | |
| 1294 ss->version >= SSL_LIBRARY_VERSION_3_0) { | |
| 1295 ssl_GetSSL3HandshakeLock(ss); | |
| 1296 falseStart = ss->ssl3.hs.canFalseStart; | |
| 1297 ssl_ReleaseSSL3HandshakeLock(ss); | |
| 1298 } | |
| 1299 if (!falseStart && | |
| 1300 (ss->handshake || ss->nextHandshake || ss->securityHandshake)) { | |
| 1301 rv = ssl_Do1stHandshake(ss); | |
| 1302 } | |
| 1303 ssl_Release1stHandshakeLock(ss); | |
| 1304 } | |
| 1305 if (rv < 0) { | |
| 1306 ss->writerThread = NULL; | |
| 1307 goto done; | |
| 1308 } | |
| 1309 | |
| 1310 /* Check for zero length writes after we do housekeeping so we make forward | |
| 1311 * progress. | |
| 1312 */ | |
| 1313 if (len == 0) { | |
| 1314 rv = 0; | |
| 1315 goto done; | |
| 1316 } | |
| 1317 PORT_Assert(buf != NULL); | |
| 1318 if (!buf) { | |
| 1319 PORT_SetError(PR_INVALID_ARGUMENT_ERROR); | |
| 1320 rv = PR_FAILURE; | |
| 1321 goto done; | |
| 1322 } | |
| 1323 | |
| 1324 if (!ss->firstHsDone) { | |
| 1325 PORT_Assert(ss->version >= SSL_LIBRARY_VERSION_3_0); | |
| 1326 #ifdef DEBUG | |
| 1327 ssl_GetSSL3HandshakeLock(ss); | |
| 1328 PORT_Assert(ss->ssl3.hs.canFalseStart); | |
| 1329 ssl_ReleaseSSL3HandshakeLock(ss); | |
| 1330 #endif | |
| 1331 SSL_TRC(3, ("%d: SSL[%d]: SecureSend: sending data due to false start", | |
| 1332 SSL_GETPID(), ss->fd)); | |
| 1333 } | |
| 1334 | |
| 1335 /* Send out the data using one of these functions: | |
| 1336 * ssl2_SendClear, ssl2_SendStream, ssl2_SendBlock, | |
| 1337 * ssl3_SendApplicationData | |
| 1338 */ | |
| 1339 ssl_GetXmitBufLock(ss); | |
| 1340 rv = (*ss->sec.send)(ss, buf, len, flags); | |
| 1341 ssl_ReleaseXmitBufLock(ss); | |
| 1342 ss->writerThread = NULL; | |
| 1343 done: | |
| 1344 if (rv < 0) { | |
| 1345 SSL_TRC(2, ("%d: SSL[%d]: SecureSend: returning %d count, error %d", | |
| 1346 SSL_GETPID(), ss->fd, rv, PORT_GetError())); | |
| 1347 } else { | |
| 1348 SSL_TRC(2, ("%d: SSL[%d]: SecureSend: returning %d count", | |
| 1349 SSL_GETPID(), ss->fd, rv)); | |
| 1350 } | |
| 1351 return rv; | |
| 1352 } | |
| 1353 | |
| 1354 int | |
| 1355 ssl_SecureWrite(sslSocket *ss, const unsigned char *buf, int len) | |
| 1356 { | |
| 1357 return ssl_SecureSend(ss, buf, len, 0); | |
| 1358 } | |
| 1359 | |
| 1360 SECStatus | |
| 1361 SSL_BadCertHook(PRFileDesc *fd, SSLBadCertHandler f, void *arg) | |
| 1362 { | |
| 1363 sslSocket *ss; | |
| 1364 | |
| 1365 ss = ssl_FindSocket(fd); | |
| 1366 if (!ss) { | |
| 1367 SSL_DBG(("%d: SSL[%d]: bad socket in SSLBadCertHook", | |
| 1368 SSL_GETPID(), fd)); | |
| 1369 return SECFailure; | |
| 1370 } | |
| 1371 | |
| 1372 ss->handleBadCert = f; | |
| 1373 ss->badCertArg = arg; | |
| 1374 | |
| 1375 return SECSuccess; | |
| 1376 } | |
| 1377 | |
| 1378 /* | |
| 1379 * Allow the application to pass the url or hostname into the SSL library | |
| 1380 * so that we can do some checking on it. It will be used for the value in | |
| 1381 * SNI extension of client hello message. | |
| 1382 */ | |
| 1383 SECStatus | |
| 1384 SSL_SetURL(PRFileDesc *fd, const char *url) | |
| 1385 { | |
| 1386 sslSocket *ss = ssl_FindSocket(fd); | |
| 1387 SECStatus rv = SECSuccess; | |
| 1388 | |
| 1389 if (!ss) { | |
| 1390 SSL_DBG(("%d: SSL[%d]: bad socket in SSLSetURL", | |
| 1391 SSL_GETPID(), fd)); | |
| 1392 return SECFailure; | |
| 1393 } | |
| 1394 ssl_Get1stHandshakeLock(ss); | |
| 1395 ssl_GetSSL3HandshakeLock(ss); | |
| 1396 | |
| 1397 if (ss->url) { | |
| 1398 PORT_Free((void *)ss->url); /* CONST */ | |
| 1399 } | |
| 1400 | |
| 1401 ss->url = (const char *)PORT_Strdup(url); | |
| 1402 if (ss->url == NULL) { | |
| 1403 rv = SECFailure; | |
| 1404 } | |
| 1405 | |
| 1406 ssl_ReleaseSSL3HandshakeLock(ss); | |
| 1407 ssl_Release1stHandshakeLock(ss); | |
| 1408 | |
| 1409 return rv; | |
| 1410 } | |
| 1411 | |
| 1412 /* | |
| 1413 * Allow the application to pass the set of trust anchors | |
| 1414 */ | |
| 1415 SECStatus | |
| 1416 SSL_SetTrustAnchors(PRFileDesc *fd, CERTCertList *certList) | |
| 1417 { | |
| 1418 sslSocket *ss = ssl_FindSocket(fd); | |
| 1419 CERTDistNames *names = NULL; | |
| 1420 | |
| 1421 if (!certList) { | |
| 1422 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 1423 return SECFailure; | |
| 1424 } | |
| 1425 if (!ss) { | |
| 1426 SSL_DBG(("%d: SSL[%d]: bad socket in SSL_SetTrustAnchors", | |
| 1427 SSL_GETPID(), fd)); | |
| 1428 return SECFailure; | |
| 1429 } | |
| 1430 | |
| 1431 names = CERT_DistNamesFromCertList(certList); | |
| 1432 if (names == NULL) { | |
| 1433 return SECFailure; | |
| 1434 } | |
| 1435 ssl_Get1stHandshakeLock(ss); | |
| 1436 ssl_GetSSL3HandshakeLock(ss); | |
| 1437 if (ss->ssl3.ca_list) { | |
| 1438 CERT_FreeDistNames(ss->ssl3.ca_list); | |
| 1439 } | |
| 1440 ss->ssl3.ca_list = names; | |
| 1441 ssl_ReleaseSSL3HandshakeLock(ss); | |
| 1442 ssl_Release1stHandshakeLock(ss); | |
| 1443 | |
| 1444 return SECSuccess; | |
| 1445 } | |
| 1446 | |
| 1447 /* | |
| 1448 ** Returns Negative number on error, zero or greater on success. | |
| 1449 ** Returns the amount of data immediately available to be read. | |
| 1450 */ | |
| 1451 int | |
| 1452 SSL_DataPending(PRFileDesc *fd) | |
| 1453 { | |
| 1454 sslSocket *ss; | |
| 1455 int rv = 0; | |
| 1456 | |
| 1457 ss = ssl_FindSocket(fd); | |
| 1458 | |
| 1459 if (ss && ss->opt.useSecurity) { | |
| 1460 ssl_GetRecvBufLock(ss); | |
| 1461 rv = ss->gs.writeOffset - ss->gs.readOffset; | |
| 1462 ssl_ReleaseRecvBufLock(ss); | |
| 1463 } | |
| 1464 | |
| 1465 return rv; | |
| 1466 } | |
| 1467 | |
| 1468 SECStatus | |
| 1469 SSL_InvalidateSession(PRFileDesc *fd) | |
| 1470 { | |
| 1471 sslSocket *ss = ssl_FindSocket(fd); | |
| 1472 SECStatus rv = SECFailure; | |
| 1473 | |
| 1474 if (ss) { | |
| 1475 ssl_Get1stHandshakeLock(ss); | |
| 1476 ssl_GetSSL3HandshakeLock(ss); | |
| 1477 | |
| 1478 if (ss->sec.ci.sid && ss->sec.uncache) { | |
| 1479 ss->sec.uncache(ss->sec.ci.sid); | |
| 1480 rv = SECSuccess; | |
| 1481 } | |
| 1482 | |
| 1483 ssl_ReleaseSSL3HandshakeLock(ss); | |
| 1484 ssl_Release1stHandshakeLock(ss); | |
| 1485 } | |
| 1486 return rv; | |
| 1487 } | |
| 1488 | |
| 1489 static void | |
| 1490 ssl3_CacheSessionUnlocked(sslSocket *ss) | |
| 1491 { | |
| 1492 PORT_Assert(!ss->sec.isServer); | |
| 1493 | |
| 1494 if (ss->ssl3.hs.cacheSID) { | |
| 1495 ss->sec.cache(ss->sec.ci.sid); | |
| 1496 ss->ssl3.hs.cacheSID = PR_FALSE; | |
| 1497 } | |
| 1498 } | |
| 1499 | |
| 1500 SECStatus | |
| 1501 SSL_CacheSession(PRFileDesc *fd) | |
| 1502 { | |
| 1503 sslSocket *ss = ssl_FindSocket(fd); | |
| 1504 SECStatus rv = SECFailure; | |
| 1505 | |
| 1506 if (ss) { | |
| 1507 ssl_Get1stHandshakeLock(ss); | |
| 1508 ssl_GetSSL3HandshakeLock(ss); | |
| 1509 | |
| 1510 ssl3_CacheSessionUnlocked(ss); | |
| 1511 rv = SECSuccess; | |
| 1512 | |
| 1513 ssl_ReleaseSSL3HandshakeLock(ss); | |
| 1514 ssl_Release1stHandshakeLock(ss); | |
| 1515 } | |
| 1516 return rv; | |
| 1517 } | |
| 1518 | |
| 1519 SECStatus | |
| 1520 SSL_CacheSessionUnlocked(PRFileDesc *fd) | |
| 1521 { | |
| 1522 sslSocket *ss = ssl_FindSocket(fd); | |
| 1523 SECStatus rv = SECFailure; | |
| 1524 | |
| 1525 if (ss) { | |
| 1526 ssl3_CacheSessionUnlocked(ss); | |
| 1527 rv = SECSuccess; | |
| 1528 } | |
| 1529 return rv; | |
| 1530 } | |
| 1531 | |
| 1532 SECItem * | |
| 1533 SSL_GetSessionID(PRFileDesc *fd) | |
| 1534 { | |
| 1535 sslSocket *ss; | |
| 1536 SECItem *item = NULL; | |
| 1537 | |
| 1538 ss = ssl_FindSocket(fd); | |
| 1539 if (ss) { | |
| 1540 ssl_Get1stHandshakeLock(ss); | |
| 1541 ssl_GetSSL3HandshakeLock(ss); | |
| 1542 | |
| 1543 if (ss->opt.useSecurity && ss->firstHsDone && ss->sec.ci.sid) { | |
| 1544 item = (SECItem *)PORT_Alloc(sizeof(SECItem)); | |
| 1545 if (item) { | |
| 1546 sslSessionID *sid = ss->sec.ci.sid; | |
| 1547 if (sid->version < SSL_LIBRARY_VERSION_3_0) { | |
| 1548 item->len = SSL2_SESSIONID_BYTES; | |
| 1549 item->data = (unsigned char *)PORT_Alloc(item->len); | |
| 1550 PORT_Memcpy(item->data, sid->u.ssl2.sessionID, item->len); | |
| 1551 } else { | |
| 1552 item->len = sid->u.ssl3.sessionIDLength; | |
| 1553 item->data = (unsigned char *)PORT_Alloc(item->len); | |
| 1554 PORT_Memcpy(item->data, sid->u.ssl3.sessionID, item->len); | |
| 1555 } | |
| 1556 } | |
| 1557 } | |
| 1558 | |
| 1559 ssl_ReleaseSSL3HandshakeLock(ss); | |
| 1560 ssl_Release1stHandshakeLock(ss); | |
| 1561 } | |
| 1562 return item; | |
| 1563 } | |
| 1564 | |
| 1565 SECStatus | |
| 1566 SSL_CertDBHandleSet(PRFileDesc *fd, CERTCertDBHandle *dbHandle) | |
| 1567 { | |
| 1568 sslSocket *ss; | |
| 1569 | |
| 1570 ss = ssl_FindSocket(fd); | |
| 1571 if (!ss) | |
| 1572 return SECFailure; | |
| 1573 if (!dbHandle) { | |
| 1574 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 1575 return SECFailure; | |
| 1576 } | |
| 1577 ss->dbHandle = dbHandle; | |
| 1578 return SECSuccess; | |
| 1579 } | |
| 1580 | |
| 1581 /* | |
| 1582 * attempt to restart the handshake after asynchronously handling | |
| 1583 * a request for the client's certificate. | |
| 1584 * | |
| 1585 * inputs: | |
| 1586 * cert Client cert chosen by application. | |
| 1587 * Note: ssl takes this reference, and does not bump the | |
| 1588 * reference count. The caller should drop its reference | |
| 1589 * without calling CERT_DestroyCertificate after calling this | |
| 1590 * function. | |
| 1591 * | |
| 1592 * key Private key associated with cert. This function takes | |
| 1593 * ownership of the private key, so the caller should drop its | |
| 1594 * reference without destroying the private key after this | |
| 1595 * function returns. | |
| 1596 * | |
| 1597 * certChain Chain of signers for cert. | |
| 1598 * Note: ssl takes this reference, and does not copy the chain. | |
| 1599 * The caller should drop its reference without destroying the | |
| 1600 * chain. SSL will free the chain when it is done with it. | |
| 1601 * | |
| 1602 * Return value: XXX | |
| 1603 * | |
| 1604 * XXX This code only works on the initial handshake on a connection, XXX | |
| 1605 * It does not work on a subsequent handshake (redo). | |
| 1606 */ | |
| 1607 SECStatus | |
| 1608 SSL_RestartHandshakeAfterCertReq(PRFileDesc *fd, | |
| 1609 CERTCertificate *cert, | |
| 1610 SECKEYPrivateKey *key, | |
| 1611 CERTCertificateList *certChain) | |
| 1612 { | |
| 1613 sslSocket *ss = ssl_FindSocket(fd); | |
| 1614 SECStatus ret; | |
| 1615 | |
| 1616 if (!ss) { | |
| 1617 SSL_DBG(("%d: SSL[%d]: bad socket in SSL_RestartHandshakeAfterCertReq", | |
| 1618 SSL_GETPID(), fd)); | |
| 1619 if (cert) { | |
| 1620 CERT_DestroyCertificate(cert); | |
| 1621 } | |
| 1622 if (key) { | |
| 1623 SECKEY_DestroyPrivateKey(key); | |
| 1624 } | |
| 1625 if (certChain) { | |
| 1626 CERT_DestroyCertificateList(certChain); | |
| 1627 } | |
| 1628 return SECFailure; | |
| 1629 } | |
| 1630 | |
| 1631 ssl_Get1stHandshakeLock(ss); /************************************/ | |
| 1632 | |
| 1633 if (ss->version >= SSL_LIBRARY_VERSION_3_0) { | |
| 1634 ret = ssl3_RestartHandshakeAfterCertReq(ss, cert, key, certChain); | |
| 1635 } else { | |
| 1636 if (certChain != NULL) { | |
| 1637 CERT_DestroyCertificateList(certChain); | |
| 1638 } | |
| 1639 PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2); | |
| 1640 ret = SECFailure; | |
| 1641 } | |
| 1642 | |
| 1643 ssl_Release1stHandshakeLock(ss); /************************************/ | |
| 1644 return ret; | |
| 1645 } | |
| 1646 | |
| 1647 SECStatus | |
| 1648 SSL_RestartHandshakeAfterChannelIDReq(PRFileDesc *fd, | |
| 1649 SECKEYPublicKey *channelIDPub, | |
| 1650 SECKEYPrivateKey *channelID) | |
| 1651 { | |
| 1652 sslSocket *ss = ssl_FindSocket(fd); | |
| 1653 SECStatus ret; | |
| 1654 | |
| 1655 if (!ss) { | |
| 1656 SSL_DBG(("%d: SSL[%d]: bad socket in" | |
| 1657 " SSL_RestartHandshakeAfterChannelIDReq", | |
| 1658 SSL_GETPID(), fd)); | |
| 1659 goto loser; | |
| 1660 } | |
| 1661 | |
| 1662 ssl_Get1stHandshakeLock(ss); | |
| 1663 | |
| 1664 if (ss->version < SSL_LIBRARY_VERSION_3_0) { | |
| 1665 PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2); | |
| 1666 ssl_Release1stHandshakeLock(ss); | |
| 1667 goto loser; | |
| 1668 } | |
| 1669 | |
| 1670 ret = ssl3_RestartHandshakeAfterChannelIDReq(ss, channelIDPub, | |
| 1671 channelID); | |
| 1672 ssl_Release1stHandshakeLock(ss); | |
| 1673 | |
| 1674 return ret; | |
| 1675 | |
| 1676 loser: | |
| 1677 SECKEY_DestroyPublicKey(channelIDPub); | |
| 1678 SECKEY_DestroyPrivateKey(channelID); | |
| 1679 return SECFailure; | |
| 1680 } | |
| 1681 | |
| 1682 /* DO NOT USE. This function was exported in ssl.def with the wrong signature; | |
| 1683 * this implementation exists to maintain link-time compatibility. | |
| 1684 */ | |
| 1685 int | |
| 1686 SSL_RestartHandshakeAfterServerCert(sslSocket *ss) | |
| 1687 { | |
| 1688 PORT_SetError(PR_NOT_IMPLEMENTED_ERROR); | |
| 1689 return -1; | |
| 1690 } | |
| 1691 | |
| 1692 /* See documentation in ssl.h */ | |
| 1693 SECStatus | |
| 1694 SSL_AuthCertificateComplete(PRFileDesc *fd, PRErrorCode error) | |
| 1695 { | |
| 1696 SECStatus rv; | |
| 1697 sslSocket *ss = ssl_FindSocket(fd); | |
| 1698 | |
| 1699 if (!ss) { | |
| 1700 SSL_DBG(("%d: SSL[%d]: bad socket in SSL_AuthCertificateComplete", | |
| 1701 SSL_GETPID(), fd)); | |
| 1702 return SECFailure; | |
| 1703 } | |
| 1704 | |
| 1705 ssl_Get1stHandshakeLock(ss); | |
| 1706 | |
| 1707 if (!ss->ssl3.initialized) { | |
| 1708 PORT_SetError(SEC_ERROR_INVALID_ARGS); | |
| 1709 rv = SECFailure; | |
| 1710 } else if (ss->version < SSL_LIBRARY_VERSION_3_0) { | |
| 1711 PORT_SetError(SSL_ERROR_FEATURE_NOT_SUPPORTED_FOR_SSL2); | |
| 1712 rv = SECFailure; | |
| 1713 } else { | |
| 1714 rv = ssl3_AuthCertificateComplete(ss, error); | |
| 1715 } | |
| 1716 | |
| 1717 ssl_Release1stHandshakeLock(ss); | |
| 1718 | |
| 1719 return rv; | |
| 1720 } | |
| 1721 | |
| 1722 /* For more info see ssl.h */ | |
| 1723 SECStatus | |
| 1724 SSL_SNISocketConfigHook(PRFileDesc *fd, SSLSNISocketConfig func, | |
| 1725 void *arg) | |
| 1726 { | |
| 1727 sslSocket *ss; | |
| 1728 | |
| 1729 ss = ssl_FindSocket(fd); | |
| 1730 if (!ss) { | |
| 1731 SSL_DBG(("%d: SSL[%d]: bad socket in SNISocketConfigHook", | |
| 1732 SSL_GETPID(), fd)); | |
| 1733 return SECFailure; | |
| 1734 } | |
| 1735 | |
| 1736 ss->sniSocketConfig = func; | |
| 1737 ss->sniSocketConfigArg = arg; | |
| 1738 return SECSuccess; | |
| 1739 } | |
| OLD | NEW |