sslcon.c (7089B)
1 /* 2 * Basic SSL handshake functions. 3 * 4 * This Source Code Form is subject to the terms of the Mozilla Public 5 * License, v. 2.0. If a copy of the MPL was not distributed with this 6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 7 8 #include "nssrenam.h" 9 #include "cert.h" 10 #include "secitem.h" 11 #include "sechash.h" 12 #include "cryptohi.h" /* for SGN_ funcs */ 13 #include "keyhi.h" /* for SECKEY_ high level functions. */ 14 #include "ssl.h" 15 #include "sslimpl.h" 16 #include "sslproto.h" 17 #include "ssl3prot.h" 18 #include "sslerr.h" 19 #include "pk11func.h" 20 #include "prinit.h" 21 22 /* 23 ** Put a string tag in the library so that we can examine an executable 24 ** and see what kind of security it supports. 25 */ 26 const char *ssl_version = "SECURITY_VERSION:" 27 " +us" 28 " +export" 29 #ifdef TRACE 30 " +trace" 31 #endif 32 #ifdef DEBUG 33 " +debug" 34 #endif 35 ; 36 37 /*********************************************************************** 38 * Gathers in and handles records/messages until either the handshake is 39 * complete or application data is available. 40 * 41 * Called from ssl_Do1stHandshake() via function pointer ss->handshake. 42 * Caller must hold handshake lock. 43 * This function acquires and releases the RecvBufLock. 44 * 45 * returns SECSuccess for success. 46 * returns SECFailure on error, setting PR_WOULD_BLOCK_ERROR if only blocked. 47 * 48 * The gather functions called by ssl_GatherRecord1stHandshake are expected 49 * to return values interpreted as follows: 50 * 1 : the function completed without error. 51 * 0 : the function read EOF. 52 * -1 : read error, or PR_WOULD_BLOCK_ERROR, or handleRecord error. 53 * 54 * This code is similar to, and easily confused with, DoRecv() in sslsecur.c 55 * 56 * This function is called from ssl_Do1stHandshake(). 57 * The following functions put ssl_GatherRecord1stHandshake into ss->handshake: 58 * ssl_BeginClientHandshake 59 * ssl3_RestartHandshakeAfterCertReq 60 * ssl3_RestartHandshakeAfterServerCert 61 * ssl_BeginServerHandshake 62 */ 63 SECStatus 64 ssl_GatherRecord1stHandshake(sslSocket *ss) 65 { 66 int rv; 67 68 PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss)); 69 70 ssl_GetRecvBufLock(ss); 71 72 /* Wait for handshake to complete, or application data to arrive. */ 73 rv = ssl3_GatherCompleteHandshake(ss, 0); 74 SSL_TRC(10, ("%d: SSL[%d]: handshake gathering, rv=%d", 75 SSL_GETPID(), ss->fd, rv)); 76 77 ssl_ReleaseRecvBufLock(ss); 78 79 if (rv <= 0) { 80 if (rv == 0) { 81 /* EOF. Loser */ 82 PORT_SetError(PR_END_OF_FILE_ERROR); 83 } 84 if (PORT_GetError() == PR_WOULD_BLOCK_ERROR) { 85 SSL_TRC(10, ("%d: SSL[%d]: handshake blocked (need %d)", 86 SSL_GETPID(), ss->fd, ss->gs.remainder)); 87 } 88 return SECFailure; /* rv is < 0 here. */ 89 } 90 91 ss->handshake = NULL; 92 return SECSuccess; 93 } 94 95 /* This function is called at the beginning of a handshake to ensure that at 96 * least one SSL/TLS version is enabled. */ 97 static SECStatus 98 ssl_CheckConfigSanity(sslSocket *ss) 99 { 100 if (SSL_ALL_VERSIONS_DISABLED(&ss->vrange)) { 101 SSL_DBG(("%d: SSL[%d]: Can't handshake! all versions disabled.", 102 SSL_GETPID(), ss->fd)); 103 PORT_SetError(SSL_ERROR_SSL_DISABLED); 104 return SECFailure; 105 } 106 return SECSuccess; 107 } 108 109 /* Sends out the initial client Hello message on the connection. 110 * Acquires and releases the socket's xmitBufLock. 111 */ 112 SECStatus 113 ssl_BeginClientHandshake(sslSocket *ss) 114 { 115 sslSessionID *sid = NULL; 116 SECStatus rv; 117 118 PORT_Assert(ss->opt.noLocks || ssl_Have1stHandshakeLock(ss)); 119 120 ss->sec.isServer = PR_FALSE; 121 122 rv = ssl_CheckConfigSanity(ss); 123 if (rv != SECSuccess) 124 goto loser; 125 126 /* Get peer name of server */ 127 rv = ssl_GetPeerInfo(ss); 128 if (rv < 0) { 129 #ifdef HPUX11 130 /* 131 * On some HP-UX B.11.00 systems, getpeername() occasionally 132 * fails with ENOTCONN after a successful completion of 133 * non-blocking connect. I found that if we do a write() 134 * and then retry getpeername(), it will work. 135 */ 136 if (PR_GetError() == PR_NOT_CONNECTED_ERROR) { 137 char dummy; 138 (void)PR_Write(ss->fd->lower, &dummy, 0); 139 rv = ssl_GetPeerInfo(ss); 140 if (rv < 0) { 141 goto loser; 142 } 143 } 144 #else 145 goto loser; 146 #endif 147 } 148 149 SSL_TRC(3, ("%d: SSL[%d]: sending client-hello", SSL_GETPID(), ss->fd)); 150 151 /* If there's an sid set from an external cache, use it. */ 152 if (ss->sec.ci.sid && ss->sec.ci.sid->cached == in_external_cache) { 153 sid = ss->sec.ci.sid; 154 SSL_TRC(3, ("%d: SSL[%d]: using external token", SSL_GETPID(), ss->fd)); 155 } else if (!ss->opt.noCache) { 156 /* Try to find server in our session-id cache */ 157 sid = ssl_LookupSID(ssl_Time(ss), &ss->sec.ci.peer, 158 ss->sec.ci.port, ss->peerID, ss->url); 159 } 160 161 if (sid) { 162 if (sid->version >= ss->vrange.min && sid->version <= ss->vrange.max) { 163 PORT_Assert(!ss->sec.localCert); 164 ss->sec.localCert = CERT_DupCertificate(sid->localCert); 165 } else { 166 ssl_UncacheSessionID(ss); 167 ssl_FreeSID(sid); 168 sid = NULL; 169 } 170 } 171 if (!sid) { 172 sid = ssl3_NewSessionID(ss, PR_FALSE); 173 if (!sid) { 174 goto loser; 175 } 176 /* This session is a dummy, which we don't want to resume. */ 177 sid->u.ssl3.keys.resumable = PR_FALSE; 178 } 179 ss->sec.ci.sid = sid; 180 181 ss->gs.state = GS_INIT; 182 ss->handshake = ssl_GatherRecord1stHandshake; 183 184 /* ssl3_SendClientHello will override this if it succeeds. */ 185 ss->version = SSL_LIBRARY_VERSION_3_0; 186 187 ssl_GetSSL3HandshakeLock(ss); 188 ssl_GetXmitBufLock(ss); 189 rv = ssl3_SendClientHello(ss, client_hello_initial); 190 ssl_ReleaseXmitBufLock(ss); 191 ssl_ReleaseSSL3HandshakeLock(ss); 192 193 return rv; 194 195 loser: 196 return SECFailure; 197 } 198 199 SECStatus 200 ssl_BeginServerHandshake(sslSocket *ss) 201 { 202 SECStatus rv; 203 204 ss->sec.isServer = PR_TRUE; 205 ss->ssl3.hs.ws = wait_client_hello; 206 207 rv = ssl_CheckConfigSanity(ss); 208 if (rv != SECSuccess) 209 goto loser; 210 211 ss->handshake = ssl_GatherRecord1stHandshake; 212 return SECSuccess; 213 214 loser: 215 return SECFailure; 216 } 217 218 /* This function doesn't really belong in this file. 219 ** It's here to keep AIX compilers from optimizing it away, 220 ** and not including it in the DSO. 221 */ 222 223 #include "nss.h" 224 extern const char __nss_ssl_version[]; 225 226 PRBool 227 NSSSSL_VersionCheck(const char *importedVersion) 228 { 229 #define NSS_VERSION_VARIABLE __nss_ssl_version 230 #include "verref.h" 231 232 /* 233 * This is the secret handshake algorithm. 234 * 235 * This release has a simple version compatibility 236 * check algorithm. This release is not backward 237 * compatible with previous major releases. It is 238 * not compatible with future major, minor, or 239 * patch releases. 240 */ 241 return NSS_VersionCheck(importedVersion); 242 } 243 244 const char * 245 NSSSSL_GetVersion(void) 246 { 247 return NSS_VERSION; 248 }