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