Back to index

lightning-sunbird  0.9+nobinonly
sslsecur.c
Go to the documentation of this file.
00001 /*
00002  * Various SSL functions.
00003  *
00004  * ***** BEGIN LICENSE BLOCK *****
00005  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00006  *
00007  * The contents of this file are subject to the Mozilla Public License Version
00008  * 1.1 (the "License"); you may not use this file except in compliance with
00009  * the License. You may obtain a copy of the License at
00010  * http://www.mozilla.org/MPL/
00011  *
00012  * Software distributed under the License is distributed on an "AS IS" basis,
00013  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00014  * for the specific language governing rights and limitations under the
00015  * License.
00016  *
00017  * The Original Code is the Netscape security libraries.
00018  *
00019  * The Initial Developer of the Original Code is
00020  * Netscape Communications Corporation.
00021  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00022  * the Initial Developer. All Rights Reserved.
00023  *
00024  * Contributor(s):
00025  *   Dr Vipul Gupta <vipul.gupta@sun.com>, Sun Microsystems Laboratories
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either the GNU General Public License Version 2 or later (the "GPL"), or
00029  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 /* $Id: sslsecur.c,v 1.34.2.2 2006/04/23 03:05:42 nelson%bolyard.com Exp $ */
00041 #include "cert.h"
00042 #include "secitem.h"
00043 #include "keyhi.h"
00044 #include "ssl.h"
00045 #include "sslimpl.h"
00046 #include "sslproto.h"
00047 #include "secoid.h"  /* for SECOID_GetALgorithmTag */
00048 #include "pk11func.h"       /* for PK11_GenerateRandom */
00049 
00050 #define MAX_BLOCK_CYPHER_SIZE      32
00051 
00052 #define TEST_FOR_FAILURE    /* reminder */
00053 #define SET_ERROR_CODE             /* reminder */
00054 
00055 /* Returns a SECStatus: SECSuccess or SECFailure, NOT SECWouldBlock. 
00056  * 
00057  * Currently, the list of functions called through ss->handshake is:
00058  * 
00059  * In sslsocks.c:
00060  *  SocksGatherRecord
00061  *  SocksHandleReply 
00062  *  SocksStartGather
00063  *
00064  * In sslcon.c:
00065  *  ssl_GatherRecord1stHandshake
00066  *  ssl2_HandleClientSessionKeyMessage
00067  *  ssl2_HandleMessage
00068  *  ssl2_HandleVerifyMessage
00069  *  ssl2_BeginClientHandshake
00070  *  ssl2_BeginServerHandshake
00071  *  ssl2_HandleClientHelloMessage
00072  *  ssl2_HandleServerHelloMessage
00073  * 
00074  * The ss->handshake function returns SECWouldBlock under these conditions:
00075  * 1.  ssl_GatherRecord1stHandshake called ssl2_GatherData which read in 
00076  *     the beginning of an SSL v3 hello message and returned SECWouldBlock 
00077  *     to switch to SSL v3 handshake processing.
00078  *
00079  * 2.  ssl2_HandleClientHelloMessage discovered version 3.0 in the incoming
00080  *     v2 client hello msg, and called ssl3_HandleV2ClientHello which 
00081  *     returned SECWouldBlock.
00082  *
00083  * 3.   SECWouldBlock was returned by one of the callback functions, via
00084  *     one of these paths:
00085  * -   ssl2_HandleMessage() -> ssl2_HandleRequestCertificate() -> ss->getClientAuthData()
00086  *
00087  * -   ssl2_HandleServerHelloMessage() -> ss->handleBadCert()
00088  *
00089  * -   ssl_GatherRecord1stHandshake() -> ssl3_GatherCompleteHandshake() -> 
00090  *     ssl3_HandleRecord() -> ssl3_HandleHandshake() -> 
00091  *     ssl3_HandleHandshakeMessage() -> ssl3_HandleCertificate() -> 
00092  *     ss->handleBadCert()
00093  *
00094  * -   ssl_GatherRecord1stHandshake() -> ssl3_GatherCompleteHandshake() -> 
00095  *     ssl3_HandleRecord() -> ssl3_HandleHandshake() -> 
00096  *     ssl3_HandleHandshakeMessage() -> ssl3_HandleCertificateRequest() -> 
00097  *     ss->getClientAuthData()
00098  *
00099  * Called from: SSL_ForceHandshake (below), 
00100  *              ssl_SecureRecv            (below) and
00101  *              ssl_SecureSend            (below)
00102  *       from: WaitForResponse     in sslsocks.c
00103  *             ssl_SocksRecv       in sslsocks.c
00104  *              ssl_SocksSend      in sslsocks.c
00105  *
00106  * Caller must hold the (write) handshakeLock.
00107  */
00108 int 
00109 ssl_Do1stHandshake(sslSocket *ss)
00110 {
00111     int rv        = SECSuccess;
00112     int loopCount = 0;
00113 
00114     do {
00115        PORT_Assert(ss->opt.noLocks ||  ssl_Have1stHandshakeLock(ss) );
00116        PORT_Assert(ss->opt.noLocks || !ssl_HaveRecvBufLock(ss));
00117        PORT_Assert(ss->opt.noLocks || !ssl_HaveXmitBufLock(ss));
00118 
00119        if (ss->handshake == 0) {
00120            /* Previous handshake finished. Switch to next one */
00121            ss->handshake = ss->nextHandshake;
00122            ss->nextHandshake = 0;
00123        }
00124        if (ss->handshake == 0) {
00125            /* Previous handshake finished. Switch to security handshake */
00126            ss->handshake = ss->securityHandshake;
00127            ss->securityHandshake = 0;
00128        }
00129        if (ss->handshake == 0) {
00130            ssl_GetRecvBufLock(ss);
00131            ss->gs.recordLen = 0;
00132            ssl_ReleaseRecvBufLock(ss);
00133 
00134            SSL_TRC(3, ("%d: SSL[%d]: handshake is completed",
00135                      SSL_GETPID(), ss->fd));
00136             /* call handshake callback for ssl v2 */
00137            /* for v3 this is done in ssl3_HandleFinished() */
00138            if ((ss->handshakeCallback != NULL) && /* has callback */
00139               (!ss->firstHsDone) &&              /* only first time */
00140               (ss->version < SSL_LIBRARY_VERSION_3_0)) {  /* not ssl3 */
00141               ss->firstHsDone     = PR_TRUE;
00142               (ss->handshakeCallback)(ss->fd, ss->handshakeCallbackData);
00143            }
00144            ss->firstHsDone         = PR_TRUE;
00145            ss->gs.writeOffset = 0;
00146            ss->gs.readOffset  = 0;
00147            break;
00148        }
00149        rv = (*ss->handshake)(ss);
00150        ++loopCount;
00151     /* This code must continue to loop on SECWouldBlock, 
00152      * or any positive value.      See XXX_1 comments.
00153      */
00154     } while (rv != SECFailure);    /* was (rv >= 0); XXX_1 */
00155 
00156     PORT_Assert(ss->opt.noLocks || !ssl_HaveRecvBufLock(ss));
00157     PORT_Assert(ss->opt.noLocks || !ssl_HaveXmitBufLock(ss));
00158 
00159     if (rv == SECWouldBlock) {
00160        PORT_SetError(PR_WOULD_BLOCK_ERROR);
00161        rv = SECFailure;
00162     }
00163     return rv;
00164 }
00165 
00166 /*
00167  * Handshake function that blocks.  Used to force a
00168  * retry on a connection on the next read/write.
00169  */
00170 static SECStatus
00171 AlwaysBlock(sslSocket *ss)
00172 {
00173     PORT_SetError(PR_WOULD_BLOCK_ERROR);  /* perhaps redundant. */
00174     return SECWouldBlock;
00175 }
00176 
00177 /*
00178  * set the initial handshake state machine to block
00179  */
00180 void
00181 ssl_SetAlwaysBlock(sslSocket *ss)
00182 {
00183     if (!ss->firstHsDone) {
00184        ss->handshake = AlwaysBlock;
00185        ss->nextHandshake = 0;
00186     }
00187 }
00188 
00189 /* Acquires and releases HandshakeLock.
00190 */
00191 SECStatus
00192 SSL_ResetHandshake(PRFileDesc *s, PRBool asServer)
00193 {
00194     sslSocket *ss;
00195     SECStatus status;
00196     PRNetAddr addr;
00197 
00198     ss = ssl_FindSocket(s);
00199     if (!ss) {
00200        SSL_DBG(("%d: SSL[%d]: bad socket in ResetHandshake", SSL_GETPID(), s));
00201        return SECFailure;
00202     }
00203 
00204     /* Don't waste my time */
00205     if (!ss->opt.useSecurity)
00206        return SECSuccess;
00207 
00208     SSL_LOCK_READER(ss);
00209     SSL_LOCK_WRITER(ss);
00210 
00211     /* Reset handshake state */
00212     ssl_Get1stHandshakeLock(ss);
00213     ssl_GetSSL3HandshakeLock(ss);
00214 
00215     ss->firstHsDone = PR_FALSE;
00216     if ( asServer ) {
00217        ss->handshake = ssl2_BeginServerHandshake;
00218        ss->handshaking = sslHandshakingAsServer;
00219     } else {
00220        ss->handshake = ssl2_BeginClientHandshake;
00221        ss->handshaking = sslHandshakingAsClient;
00222     }
00223     ss->nextHandshake       = 0;
00224     ss->securityHandshake   = 0;
00225 
00226     ssl_GetRecvBufLock(ss);
00227     status = ssl_InitGather(&ss->gs);
00228     ssl_ReleaseRecvBufLock(ss);
00229 
00230     /*
00231     ** Blow away old security state and get a fresh setup.
00232     */
00233     ssl_GetXmitBufLock(ss); 
00234     ssl_ResetSecurityInfo(&ss->sec, PR_TRUE);
00235     status = ssl_CreateSecurityInfo(ss);
00236     ssl_ReleaseXmitBufLock(ss); 
00237 
00238     ssl_ReleaseSSL3HandshakeLock(ss);
00239     ssl_Release1stHandshakeLock(ss);
00240 
00241     if (!ss->TCPconnected)
00242        ss->TCPconnected = (PR_SUCCESS == ssl_DefGetpeername(ss, &addr));
00243 
00244     SSL_UNLOCK_WRITER(ss);
00245     SSL_UNLOCK_READER(ss);
00246 
00247     return status;
00248 }
00249 
00250 /* For SSLv2, does nothing but return an error.
00251 ** For SSLv3, flushes SID cache entry (if requested),
00252 ** and then starts new client hello or hello request.
00253 ** Acquires and releases HandshakeLock.
00254 */
00255 SECStatus
00256 SSL_ReHandshake(PRFileDesc *fd, PRBool flushCache)
00257 {
00258     sslSocket *ss;
00259     SECStatus  rv;
00260     
00261     ss = ssl_FindSocket(fd);
00262     if (!ss) {
00263        SSL_DBG(("%d: SSL[%d]: bad socket in RedoHandshake", SSL_GETPID(), fd));
00264        return SECFailure;
00265     }
00266 
00267     if (!ss->opt.useSecurity)
00268        return SECSuccess;
00269     
00270     ssl_Get1stHandshakeLock(ss);
00271 
00272     /* SSL v2 protocol does not support subsequent handshakes. */
00273     if (ss->version < SSL_LIBRARY_VERSION_3_0) {
00274        PORT_SetError(SEC_ERROR_INVALID_ARGS);
00275        rv = SECFailure;
00276     } else {
00277        ssl_GetSSL3HandshakeLock(ss);
00278        rv = ssl3_RedoHandshake(ss, flushCache); /* force full handshake. */
00279        ssl_ReleaseSSL3HandshakeLock(ss);
00280     }
00281 
00282     ssl_Release1stHandshakeLock(ss);
00283 
00284     return rv;
00285 }
00286 
00287 /*
00288 ** Same as above, but with an I/O timeout.
00289  */
00290 SSL_IMPORT SECStatus SSL_ReHandshakeWithTimeout(PRFileDesc *fd,
00291                                                 PRBool flushCache,
00292                                                 PRIntervalTime timeout)
00293 {
00294     if (SECSuccess != ssl_SetTimeout(fd, timeout)) {
00295         return SECFailure;
00296     }
00297     return SSL_ReHandshake(fd, flushCache);
00298 }
00299 
00300 SECStatus
00301 SSL_RedoHandshake(PRFileDesc *fd)
00302 {
00303     return SSL_ReHandshake(fd, PR_TRUE);
00304 }
00305 
00306 /* Register an application callback to be called when SSL handshake completes.
00307 ** Acquires and releases HandshakeLock.
00308 */
00309 SECStatus
00310 SSL_HandshakeCallback(PRFileDesc *fd, SSLHandshakeCallback cb,
00311                     void *client_data)
00312 {
00313     sslSocket *ss;
00314     
00315     ss = ssl_FindSocket(fd);
00316     if (!ss) {
00317        SSL_DBG(("%d: SSL[%d]: bad socket in HandshakeCallback",
00318                SSL_GETPID(), fd));
00319        return SECFailure;
00320     }
00321 
00322     if (!ss->opt.useSecurity) {
00323        PORT_SetError(SEC_ERROR_INVALID_ARGS);
00324        return SECFailure;
00325     }
00326 
00327     ssl_Get1stHandshakeLock(ss);
00328     ssl_GetSSL3HandshakeLock(ss);
00329 
00330     ss->handshakeCallback     = cb;
00331     ss->handshakeCallbackData = client_data;
00332 
00333     ssl_ReleaseSSL3HandshakeLock(ss);
00334     ssl_Release1stHandshakeLock(ss);
00335 
00336     return SECSuccess;
00337 }
00338 
00339 /* Try to make progress on an SSL handshake by attempting to read the 
00340 ** next handshake from the peer, and sending any responses.
00341 ** For non-blocking sockets, returns PR_ERROR_WOULD_BLOCK  if it cannot 
00342 ** read the next handshake from the underlying socket.
00343 ** For SSLv2, returns when handshake is complete or fatal error occurs.
00344 ** For SSLv3, returns when handshake is complete, or application data has
00345 ** arrived that must be taken by application before handshake can continue, 
00346 ** or a fatal error occurs.
00347 ** Application should use handshake completion callback to tell which. 
00348 */
00349 SECStatus
00350 SSL_ForceHandshake(PRFileDesc *fd)
00351 {
00352     sslSocket *ss;
00353     SECStatus  rv = SECFailure;
00354 
00355     ss = ssl_FindSocket(fd);
00356     if (!ss) {
00357        SSL_DBG(("%d: SSL[%d]: bad socket in ForceHandshake",
00358                SSL_GETPID(), fd));
00359        return rv;
00360     }
00361 
00362     /* Don't waste my time */
00363     if (!ss->opt.useSecurity) 
00364        return SECSuccess;
00365 
00366     ssl_Get1stHandshakeLock(ss);
00367 
00368     if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
00369        int gatherResult;
00370 
00371        ssl_GetRecvBufLock(ss);
00372        gatherResult = ssl3_GatherCompleteHandshake(ss, 0);
00373        ssl_ReleaseRecvBufLock(ss);
00374        if (gatherResult > 0) {
00375            rv = SECSuccess;
00376        } else if (gatherResult == 0) {
00377            PORT_SetError(PR_END_OF_FILE_ERROR);
00378        } else if (gatherResult == SECWouldBlock) {
00379            PORT_SetError(PR_WOULD_BLOCK_ERROR);
00380        }
00381     } else if (!ss->firstHsDone) {
00382        rv = ssl_Do1stHandshake(ss);
00383     } else {
00384        /* tried to force handshake on an SSL 2 socket that has 
00385        ** already completed the handshake. */
00386        rv = SECSuccess;     /* just pretend we did it. */
00387     }
00388 
00389     ssl_Release1stHandshakeLock(ss);
00390 
00391     return rv;
00392 }
00393 
00394 /*
00395  ** Same as above, but with an I/O timeout.
00396  */
00397 SSL_IMPORT SECStatus SSL_ForceHandshakeWithTimeout(PRFileDesc *fd,
00398                                                    PRIntervalTime timeout)
00399 {
00400     if (SECSuccess != ssl_SetTimeout(fd, timeout)) {
00401         return SECFailure;
00402     }
00403     return SSL_ForceHandshake(fd);
00404 }
00405 
00406 
00407 /************************************************************************/
00408 
00409 /*
00410 ** Grow a buffer to hold newLen bytes of data.
00411 ** Called for both recv buffers and xmit buffers.
00412 ** Caller must hold xmitBufLock or recvBufLock, as appropriate.
00413 */
00414 SECStatus
00415 sslBuffer_Grow(sslBuffer *b, unsigned int newLen)
00416 {
00417     newLen = PR_MAX(newLen, MAX_FRAGMENT_LENGTH + 2048);
00418     if (newLen > b->space) {
00419        unsigned char *newBuf;
00420        if (b->buf) {
00421            newBuf = (unsigned char *) PORT_Realloc(b->buf, newLen);
00422        } else {
00423            newBuf = (unsigned char *) PORT_Alloc(newLen);
00424        }
00425        if (!newBuf) {
00426            return SECFailure;
00427        }
00428        SSL_TRC(10, ("%d: SSL: grow buffer from %d to %d",
00429                    SSL_GETPID(), b->space, newLen));
00430        b->buf = newBuf;
00431        b->space = newLen;
00432     }
00433     return SECSuccess;
00434 }
00435 
00436 /*
00437 ** Save away write data that is trying to be written before the security
00438 ** handshake has been completed. When the handshake is completed, we will
00439 ** flush this data out.
00440 ** Caller must hold xmitBufLock
00441 */
00442 SECStatus 
00443 ssl_SaveWriteData(sslSocket *ss, const void *data, unsigned int len)
00444 {
00445     unsigned int newlen;
00446     SECStatus    rv;
00447 
00448     PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
00449     newlen = ss->pendingBuf.len + len;
00450     if (newlen > ss->pendingBuf.space) {
00451        rv = sslBuffer_Grow(&ss->pendingBuf, newlen);
00452        if (rv) {
00453            return rv;
00454        }
00455     }
00456     SSL_TRC(5, ("%d: SSL[%d]: saving %d bytes of data (%d total saved so far)",
00457                SSL_GETPID(), ss->fd, len, newlen));
00458     PORT_Memcpy(ss->pendingBuf.buf + ss->pendingBuf.len, data, len);
00459     ss->pendingBuf.len = newlen;
00460     return SECSuccess;
00461 }
00462 
00463 /*
00464 ** Send saved write data. This will flush out data sent prior to a
00465 ** complete security handshake. Hopefully there won't be too much of it.
00466 ** Returns count of the bytes sent, NOT a SECStatus.
00467 ** Caller must hold xmitBufLock
00468 */
00469 int 
00470 ssl_SendSavedWriteData(sslSocket *ss)
00471 {
00472     int rv    = 0;
00473 
00474     PORT_Assert( ss->opt.noLocks || ssl_HaveXmitBufLock(ss) );
00475     if (ss->pendingBuf.len != 0) {
00476        SSL_TRC(5, ("%d: SSL[%d]: sending %d bytes of saved data",
00477                    SSL_GETPID(), ss->fd, ss->pendingBuf.len));
00478        rv = ssl_DefSend(ss, ss->pendingBuf.buf, ss->pendingBuf.len, 0);
00479        if (rv < 0) {
00480            return rv;
00481        } 
00482        ss->pendingBuf.len -= rv;
00483        if (ss->pendingBuf.len > 0 && rv > 0) {
00484            /* UGH !! This shifts the whole buffer down by copying it */
00485            PORT_Memmove(ss->pendingBuf.buf, ss->pendingBuf.buf + rv, 
00486                         ss->pendingBuf.len);
00487        }
00488     }
00489     return rv;
00490 }
00491 
00492 /************************************************************************/
00493 
00494 /*
00495 ** Receive some application data on a socket.  Reads SSL records from the input
00496 ** stream, decrypts them and then copies them to the output buffer.
00497 ** Called from ssl_SecureRecv() below.
00498 **
00499 ** Caller does NOT hold 1stHandshakeLock because that handshake is over.
00500 ** Caller doesn't call this until initial handshake is complete.
00501 ** For SSLv2, there is no subsequent handshake.
00502 ** For SSLv3, the call to ssl3_GatherAppDataRecord may encounter handshake
00503 ** messages from a subsequent handshake.
00504 **
00505 ** This code is similar to, and easily confused with, 
00506 **   ssl_GatherRecord1stHandshake() in sslcon.c
00507 */
00508 static int 
00509 DoRecv(sslSocket *ss, unsigned char *out, int len, int flags)
00510 {
00511     int              rv;
00512     int              amount;
00513     int              available;
00514 
00515     ssl_GetRecvBufLock(ss);
00516 
00517     available = ss->gs.writeOffset - ss->gs.readOffset;
00518     if (available == 0) {
00519        /* Get some more data */
00520        if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
00521            /* Wait for application data to arrive.  */
00522            rv = ssl3_GatherAppDataRecord(ss, 0);
00523        } else {
00524            /* See if we have a complete record */
00525            rv = ssl2_GatherRecord(ss, 0);
00526        }
00527        if (rv <= 0) {
00528            if (rv == 0) {
00529               /* EOF */
00530               SSL_TRC(10, ("%d: SSL[%d]: ssl_recv EOF",
00531                           SSL_GETPID(), ss->fd));
00532               goto done;
00533            }
00534            if ((rv != SECWouldBlock) && 
00535                (PR_GetError() != PR_WOULD_BLOCK_ERROR)) {
00536               /* Some random error */
00537               goto done;
00538            }
00539 
00540            /*
00541            ** Gather record is blocked waiting for more record data to
00542            ** arrive. Try to process what we have already received
00543            */
00544        } else {
00545            /* Gather record has finished getting a complete record */
00546        }
00547 
00548        /* See if any clear data is now available */
00549        available = ss->gs.writeOffset - ss->gs.readOffset;
00550        if (available == 0) {
00551            /*
00552            ** No partial data is available. Force error code to
00553            ** EWOULDBLOCK so that caller will try again later. Note
00554            ** that the error code is probably EWOULDBLOCK already,
00555            ** but if it isn't (for example, if we received a zero
00556            ** length record) then this will force it to be correct.
00557            */
00558            PORT_SetError(PR_WOULD_BLOCK_ERROR);
00559            rv = SECFailure;
00560            goto done;
00561        }
00562        SSL_TRC(30, ("%d: SSL[%d]: partial data ready, available=%d",
00563                    SSL_GETPID(), ss->fd, available));
00564     }
00565 
00566     /* Dole out clear data to reader */
00567     amount = PR_MIN(len, available);
00568     PORT_Memcpy(out, ss->gs.buf.buf + ss->gs.readOffset, amount);
00569     if (!(flags & PR_MSG_PEEK)) {
00570        ss->gs.readOffset += amount;
00571     }
00572     rv = amount;
00573 
00574     SSL_TRC(30, ("%d: SSL[%d]: amount=%d available=%d",
00575                SSL_GETPID(), ss->fd, amount, available));
00576     PRINT_BUF(4, (ss, "DoRecv receiving plaintext:", out, amount));
00577 
00578 done:
00579     ssl_ReleaseRecvBufLock(ss);
00580     return rv;
00581 }
00582 
00583 /************************************************************************/
00584 
00585 SSLKEAType
00586 ssl_FindCertKEAType(CERTCertificate * cert)
00587 {
00588   SSLKEAType keaType = kt_null; 
00589   int tag;
00590   
00591   if (!cert) goto loser;
00592   
00593   tag = SECOID_GetAlgorithmTag(&(cert->subjectPublicKeyInfo.algorithm));
00594   
00595   switch (tag) {
00596   case SEC_OID_X500_RSA_ENCRYPTION:
00597   case SEC_OID_PKCS1_RSA_ENCRYPTION:
00598     keaType = kt_rsa;
00599     break;
00600 
00601   case SEC_OID_X942_DIFFIE_HELMAN_KEY:
00602     keaType = kt_dh;
00603     break;
00604 #ifdef NSS_ENABLE_ECC
00605   case SEC_OID_ANSIX962_EC_PUBLIC_KEY:
00606     keaType = kt_ecdh;
00607     break;
00608 #endif /* NSS_ENABLE_ECC */
00609   default:
00610     keaType = kt_null;
00611   }
00612   
00613  loser:
00614   
00615   return keaType;
00616 
00617 }
00618 
00619 
00620 /* XXX need to protect the data that gets changed here.!! */
00621 
00622 SECStatus
00623 SSL_ConfigSecureServer(PRFileDesc *fd, CERTCertificate *cert,
00624                      SECKEYPrivateKey *key, SSL3KEAType kea)
00625 {
00626     SECStatus rv;
00627     sslSocket *ss;
00628     sslServerCerts  *sc;
00629     SECKEYPublicKey * pubKey = NULL;
00630 
00631     ss = ssl_FindSocket(fd);
00632     if (!ss) {
00633        return SECFailure;
00634     }
00635 
00636     /* Both key and cert must have a value or be NULL */
00637     /* Passing a value of NULL will turn off key exchange algorithms that were
00638      * previously turned on */
00639     if (!cert != !key) {
00640        PORT_SetError(SEC_ERROR_INVALID_ARGS);
00641        return SECFailure;
00642     }
00643 
00644     /* make sure the key exchange is recognized */
00645     if ((kea >= kt_kea_size) || (kea < kt_null)) {
00646        PORT_SetError(SEC_ERROR_UNSUPPORTED_KEYALG);
00647        return SECFailure;
00648     }
00649 
00650     if (kea != ssl_FindCertKEAType(cert)) {
00651        PORT_SetError(SSL_ERROR_CERT_KEA_MISMATCH);
00652        return SECFailure;
00653     }
00654 
00655     sc = ss->serverCerts + kea;
00656     /* load the server certificate */
00657     if (sc->serverCert != NULL) {
00658        CERT_DestroyCertificate(sc->serverCert);
00659        sc->serverCert = NULL;
00660     }
00661     if (cert) {
00662        sc->serverCert = CERT_DupCertificate(cert);
00663        if (!sc->serverCert)
00664            goto loser;
00665        /* get the size of the cert's public key, and remember it */
00666        pubKey = CERT_ExtractPublicKey(cert);
00667        if (!pubKey) 
00668            goto loser;
00669        sc->serverKeyBits = SECKEY_PublicKeyStrengthInBits(pubKey);
00670     }
00671 
00672 
00673     /* load the server cert chain */
00674     if (sc->serverCertChain != NULL) {
00675        CERT_DestroyCertificateList(sc->serverCertChain);
00676        sc->serverCertChain = NULL;
00677     }
00678     if (cert) {
00679        sc->serverCertChain = CERT_CertChainFromCert(
00680                          sc->serverCert, certUsageSSLServer, PR_TRUE);
00681        if (sc->serverCertChain == NULL)
00682             goto loser;
00683     }
00684 
00685     /* load the private key */
00686     if (sc->serverKeyPair != NULL) {
00687         ssl3_FreeKeyPair(sc->serverKeyPair);
00688         sc->serverKeyPair = NULL;
00689     }
00690     if (key) {
00691        SECKEYPrivateKey * keyCopy  = NULL;
00692        CK_MECHANISM_TYPE  keyMech  = CKM_INVALID_MECHANISM;
00693 
00694        if (key->pkcs11Slot) {
00695            PK11SlotInfo * bestSlot;
00696            bestSlot = PK11_ReferenceSlot(key->pkcs11Slot);
00697            if (bestSlot) {
00698               keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key);
00699               PK11_FreeSlot(bestSlot);
00700            }
00701        }
00702        if (keyCopy == NULL)
00703            keyMech = PK11_MapSignKeyType(key->keyType);
00704        if (keyMech != CKM_INVALID_MECHANISM) {
00705            PK11SlotInfo * bestSlot;
00706            /* XXX Maybe should be bestSlotMultiple? */
00707            bestSlot = PK11_GetBestSlot(keyMech, NULL /* wincx */);
00708            if (bestSlot) {
00709               keyCopy = PK11_CopyTokenPrivKeyToSessionPrivKey(bestSlot, key);
00710               PK11_FreeSlot(bestSlot);
00711            }
00712        }
00713        if (keyCopy == NULL)
00714            keyCopy = SECKEY_CopyPrivateKey(key);
00715        if (keyCopy == NULL)
00716            goto loser;
00717        SECKEY_CacheStaticFlags(keyCopy);
00718         sc->serverKeyPair = ssl3_NewKeyPair(keyCopy, pubKey);
00719         if (sc->serverKeyPair == NULL) {
00720             SECKEY_DestroyPrivateKey(keyCopy);
00721             goto loser;
00722         }
00723        pubKey = NULL; /* adopted by serverKeyPair */
00724     }
00725 
00726     if (kea == kt_rsa && cert && sc->serverKeyBits > 512) {
00727        if (ss->opt.noStepDown) {
00728            /* disable all export ciphersuites */
00729        } else {
00730            rv = ssl3_CreateRSAStepDownKeys(ss);
00731            if (rv != SECSuccess) {
00732               return SECFailure; /* err set by ssl3_CreateRSAStepDownKeys */
00733            }
00734        }
00735     }
00736 
00737     /* Only do this once because it's global. */
00738     if (ssl3_server_ca_list == NULL)
00739        ssl3_server_ca_list = CERT_GetSSLCACerts(ss->dbHandle);
00740 
00741     return SECSuccess;
00742 
00743 loser:
00744     if (pubKey) {
00745        SECKEY_DestroyPublicKey(pubKey); 
00746        pubKey = NULL;
00747     }
00748     if (sc->serverCert != NULL) {
00749        CERT_DestroyCertificate(sc->serverCert);
00750        sc->serverCert = NULL;
00751     }
00752     if (sc->serverCertChain != NULL) {
00753        CERT_DestroyCertificateList(sc->serverCertChain);
00754        sc->serverCertChain = NULL;
00755     }
00756     if (sc->serverKeyPair != NULL) {
00757        ssl3_FreeKeyPair(sc->serverKeyPair);
00758        sc->serverKeyPair = NULL;
00759     }
00760     return SECFailure;
00761 }
00762 
00763 /************************************************************************/
00764 
00765 SECStatus
00766 ssl_CreateSecurityInfo(sslSocket *ss)
00767 {
00768     SECStatus status;
00769 
00770     /* initialize sslv2 socket to send data in the clear. */
00771     ssl2_UseClearSendFunc(ss);
00772 
00773     ss->sec.blockSize  = 1;
00774     ss->sec.blockShift = 0;
00775 
00776     ssl_GetXmitBufLock(ss); 
00777     status = sslBuffer_Grow(&ss->sec.writeBuf, 4096);
00778     ssl_ReleaseXmitBufLock(ss); 
00779 
00780     return status;
00781 }
00782 
00783 SECStatus
00784 ssl_CopySecurityInfo(sslSocket *ss, sslSocket *os)
00785 {
00786     ss->sec.send            = os->sec.send;
00787     ss->sec.isServer               = os->sec.isServer;
00788     ss->sec.keyBits                = os->sec.keyBits;
00789     ss->sec.secretKeyBits   = os->sec.secretKeyBits;
00790 
00791     ss->sec.peerCert               = CERT_DupCertificate(os->sec.peerCert);
00792     if (os->sec.peerCert && !ss->sec.peerCert)
00793        goto loser;
00794 
00795     ss->sec.cache                  = os->sec.cache;
00796     ss->sec.uncache                = os->sec.uncache;
00797 
00798     /* we don't dup the connection info. */
00799 
00800     ss->sec.sendSequence    = os->sec.sendSequence;
00801     ss->sec.rcvSequence     = os->sec.rcvSequence;
00802 
00803     if (os->sec.hash && os->sec.hashcx) {
00804        ss->sec.hash         = os->sec.hash;
00805        ss->sec.hashcx              = os->sec.hash->clone(os->sec.hashcx);
00806        if (os->sec.hashcx && !ss->sec.hashcx)
00807            goto loser;
00808     } else {
00809        ss->sec.hash         = NULL;
00810        ss->sec.hashcx              = NULL;
00811     }
00812 
00813     SECITEM_CopyItem(0, &ss->sec.sendSecret, &os->sec.sendSecret);
00814     if (os->sec.sendSecret.data && !ss->sec.sendSecret.data)
00815        goto loser;
00816     SECITEM_CopyItem(0, &ss->sec.rcvSecret,  &os->sec.rcvSecret);
00817     if (os->sec.rcvSecret.data && !ss->sec.rcvSecret.data)
00818        goto loser;
00819 
00820     /* XXX following code is wrong if either cx != 0 */
00821     PORT_Assert(os->sec.readcx  == 0);
00822     PORT_Assert(os->sec.writecx == 0);
00823     ss->sec.readcx                 = os->sec.readcx;
00824     ss->sec.writecx                = os->sec.writecx;
00825     ss->sec.destroy                = 0;   
00826 
00827     ss->sec.enc                    = os->sec.enc;
00828     ss->sec.dec                    = os->sec.dec;
00829 
00830     ss->sec.blockShift             = os->sec.blockShift;
00831     ss->sec.blockSize              = os->sec.blockSize;
00832 
00833     return SECSuccess;
00834 
00835 loser:
00836     return SECFailure;
00837 }
00838 
00839 /* Reset sec back to its initial state.
00840 ** Caller holds any relevant locks.
00841 */
00842 void 
00843 ssl_ResetSecurityInfo(sslSecurityInfo *sec, PRBool doMemset)
00844 {
00845     /* Destroy MAC */
00846     if (sec->hash && sec->hashcx) {
00847        (*sec->hash->destroy)(sec->hashcx, PR_TRUE);
00848        sec->hashcx = NULL;
00849        sec->hash = NULL;
00850     }
00851     SECITEM_ZfreeItem(&sec->sendSecret, PR_FALSE);
00852     SECITEM_ZfreeItem(&sec->rcvSecret, PR_FALSE);
00853 
00854     /* Destroy ciphers */
00855     if (sec->destroy) {
00856        (*sec->destroy)(sec->readcx, PR_TRUE);
00857        (*sec->destroy)(sec->writecx, PR_TRUE);
00858        sec->readcx = NULL;
00859        sec->writecx = NULL;
00860     } else {
00861        PORT_Assert(sec->readcx == 0);
00862        PORT_Assert(sec->writecx == 0);
00863     }
00864     sec->readcx = 0;
00865     sec->writecx = 0;
00866 
00867     if (sec->localCert) {
00868        CERT_DestroyCertificate(sec->localCert);
00869        sec->localCert = NULL;
00870     }
00871     if (sec->peerCert) {
00872        CERT_DestroyCertificate(sec->peerCert);
00873        sec->peerCert = NULL;
00874     }
00875     if (sec->peerKey) {
00876        SECKEY_DestroyPublicKey(sec->peerKey);
00877        sec->peerKey = NULL;
00878     }
00879 
00880     /* cleanup the ci */
00881     if (sec->ci.sid != NULL) {
00882        ssl_FreeSID(sec->ci.sid);
00883     }
00884     PORT_ZFree(sec->ci.sendBuf.buf, sec->ci.sendBuf.space);
00885     if (doMemset) {
00886         memset(&sec->ci, 0, sizeof sec->ci);
00887     }
00888     
00889 }
00890 
00891 /*
00892 ** Called from SSL_ResetHandshake (above), and 
00893 **        from ssl_FreeSocket     in sslsock.c
00894 ** Caller should hold relevant locks (e.g. XmitBufLock)
00895 */
00896 void 
00897 ssl_DestroySecurityInfo(sslSecurityInfo *sec)
00898 {
00899     ssl_ResetSecurityInfo(sec, PR_FALSE);
00900 
00901     PORT_ZFree(sec->writeBuf.buf, sec->writeBuf.space);
00902     sec->writeBuf.buf = 0;
00903 
00904     memset(sec, 0, sizeof *sec);
00905 }
00906 
00907 /************************************************************************/
00908 
00909 int 
00910 ssl_SecureConnect(sslSocket *ss, const PRNetAddr *sa)
00911 {
00912     PRFileDesc *osfd = ss->fd->lower;
00913     int rv;
00914 
00915     if ( ss->opt.handshakeAsServer ) {
00916        ss->securityHandshake = ssl2_BeginServerHandshake;
00917        ss->handshaking = sslHandshakingAsServer;
00918     } else {
00919        ss->securityHandshake = ssl2_BeginClientHandshake;
00920        ss->handshaking = sslHandshakingAsClient;
00921     }
00922 
00923     /* connect to server */
00924     rv = osfd->methods->connect(osfd, sa, ss->cTimeout);
00925     if (rv == PR_SUCCESS) {
00926        ss->TCPconnected = 1;
00927     } else {
00928        int err = PR_GetError();
00929        SSL_DBG(("%d: SSL[%d]: connect failed, errno=%d",
00930                SSL_GETPID(), ss->fd, err));
00931        if (err == PR_IS_CONNECTED_ERROR) {
00932            ss->TCPconnected = 1;
00933        } 
00934     }
00935 
00936     SSL_TRC(5, ("%d: SSL[%d]: secure connect completed, rv == %d",
00937               SSL_GETPID(), ss->fd, rv));
00938     return rv;
00939 }
00940 
00941 int
00942 ssl_SecureClose(sslSocket *ss)
00943 {
00944     int rv;
00945 
00946     if (ss->version >= SSL_LIBRARY_VERSION_3_0   &&
00947        ss->firstHsDone                    && 
00948        !(ss->shutdownHow & ssl_SHUTDOWN_SEND)    &&
00949        !ss->recvdCloseNotify                   &&
00950        ss->ssl3.initialized) {
00951 
00952        /* We don't want the final alert to be Nagle delayed. */
00953        if (!ss->delayDisabled) {
00954            ssl_EnableNagleDelay(ss, PR_FALSE);
00955            ss->delayDisabled = 1;
00956        }
00957 
00958        (void) SSL3_SendAlert(ss, alert_warning, close_notify);
00959     }
00960     rv = ssl_DefClose(ss);
00961     return rv;
00962 }
00963 
00964 /* Caller handles all locking */
00965 int
00966 ssl_SecureShutdown(sslSocket *ss, int nsprHow)
00967 {
00968     PRFileDesc *osfd = ss->fd->lower;
00969     int       rv;
00970     PRIntn    sslHow = nsprHow + 1;
00971 
00972     if ((unsigned)nsprHow > PR_SHUTDOWN_BOTH) {
00973        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
00974        return PR_FAILURE;
00975     }
00976 
00977     if ((sslHow & ssl_SHUTDOWN_SEND) != 0               &&
00978        !(ss->shutdownHow & ssl_SHUTDOWN_SEND)           &&
00979        (ss->version >= SSL_LIBRARY_VERSION_3_0)  &&
00980        ss->firstHsDone                           && 
00981        !ss->recvdCloseNotify                     &&
00982        ss->ssl3.initialized) {
00983 
00984        (void) SSL3_SendAlert(ss, alert_warning, close_notify);
00985     }
00986 
00987     rv = osfd->methods->shutdown(osfd, nsprHow);
00988 
00989     ss->shutdownHow |= sslHow;
00990 
00991     return rv;
00992 }
00993 
00994 /************************************************************************/
00995 
00996 
00997 int
00998 ssl_SecureRecv(sslSocket *ss, unsigned char *buf, int len, int flags)
00999 {
01000     sslSecurityInfo *sec;
01001     int              rv   = 0;
01002 
01003     sec = &ss->sec;
01004 
01005     if (ss->shutdownHow & ssl_SHUTDOWN_RCV) {
01006        PORT_SetError(PR_SOCKET_SHUTDOWN_ERROR);
01007        return PR_FAILURE;
01008     }
01009     if (flags & ~PR_MSG_PEEK) {
01010        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
01011        return PR_FAILURE;
01012     }
01013 
01014     if (!ssl_SocketIsBlocking(ss) && !ss->opt.fdx) {
01015        ssl_GetXmitBufLock(ss);
01016        if (ss->pendingBuf.len != 0) {
01017            rv = ssl_SendSavedWriteData(ss);
01018            if ((rv < 0) && (PORT_GetError() != PR_WOULD_BLOCK_ERROR)) {
01019               ssl_ReleaseXmitBufLock(ss);
01020               return SECFailure;
01021            }
01022            /* XXX short write? */
01023        }
01024        ssl_ReleaseXmitBufLock(ss);
01025     }
01026     
01027     rv = 0;
01028     /* If any of these is non-zero, the initial handshake is not done. */
01029     if (!ss->firstHsDone) {
01030        ssl_Get1stHandshakeLock(ss);
01031        if (ss->handshake || ss->nextHandshake || ss->securityHandshake) {
01032            rv = ssl_Do1stHandshake(ss);
01033        }
01034        ssl_Release1stHandshakeLock(ss);
01035     }
01036     if (rv < 0) {
01037        return rv;
01038     }
01039 
01040     if (len == 0) return 0;
01041 
01042     rv = DoRecv(ss, (unsigned char*) buf, len, flags);
01043     SSL_TRC(2, ("%d: SSL[%d]: recving %d bytes securely (errno=%d)",
01044               SSL_GETPID(), ss->fd, rv, PORT_GetError()));
01045     return rv;
01046 }
01047 
01048 int
01049 ssl_SecureRead(sslSocket *ss, unsigned char *buf, int len)
01050 {
01051     return ssl_SecureRecv(ss, buf, len, 0);
01052 }
01053 
01054 /* Caller holds the SSL Socket's write lock. SSL_LOCK_WRITER(ss) */
01055 int
01056 ssl_SecureSend(sslSocket *ss, const unsigned char *buf, int len, int flags)
01057 {
01058     int              rv            = 0;
01059 
01060     if (ss->shutdownHow & ssl_SHUTDOWN_SEND) {
01061        PORT_SetError(PR_SOCKET_SHUTDOWN_ERROR);
01062        return PR_FAILURE;
01063     }
01064     if (flags) {
01065        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
01066        return PR_FAILURE;
01067     }
01068 
01069     ssl_GetXmitBufLock(ss);
01070     if (ss->pendingBuf.len != 0) {
01071        PORT_Assert(ss->pendingBuf.len > 0);
01072        rv = ssl_SendSavedWriteData(ss);
01073        if (rv >= 0 && ss->pendingBuf.len != 0) {
01074            PORT_Assert(ss->pendingBuf.len > 0);
01075            PORT_SetError(PR_WOULD_BLOCK_ERROR);
01076            rv = SECFailure;
01077        }
01078     }
01079     ssl_ReleaseXmitBufLock(ss);
01080     if (rv < 0) {
01081        return rv;
01082     }
01083 
01084     if (len > 0) 
01085        ss->writerThread = PR_GetCurrentThread();
01086     /* If any of these is non-zero, the initial handshake is not done. */
01087     if (!ss->firstHsDone) {
01088        ssl_Get1stHandshakeLock(ss);
01089        if (ss->handshake || ss->nextHandshake || ss->securityHandshake) {
01090            rv = ssl_Do1stHandshake(ss);
01091        }
01092        ssl_Release1stHandshakeLock(ss);
01093     }
01094     if (rv < 0) {
01095        ss->writerThread = NULL;
01096        return rv;
01097     }
01098 
01099     /* Check for zero length writes after we do housekeeping so we make forward
01100      * progress.
01101      */
01102     if (len == 0) {
01103        return 0;
01104     }
01105     PORT_Assert(buf != NULL);
01106     if (!buf) {
01107        PORT_SetError(PR_INVALID_ARGUMENT_ERROR);
01108        return PR_FAILURE;
01109     }
01110     
01111     SSL_TRC(2, ("%d: SSL[%d]: SecureSend: sending %d bytes",
01112               SSL_GETPID(), ss->fd, len));
01113 
01114     /* Send out the data using one of these functions:
01115      * ssl2_SendClear, ssl2_SendStream, ssl2_SendBlock, 
01116      *  ssl3_SendApplicationData
01117      */
01118     ssl_GetXmitBufLock(ss);
01119     rv = (*ss->sec.send)(ss, buf, len, flags);
01120     ssl_ReleaseXmitBufLock(ss);
01121     ss->writerThread = NULL;
01122     return rv;
01123 }
01124 
01125 int
01126 ssl_SecureWrite(sslSocket *ss, const unsigned char *buf, int len)
01127 {
01128     return ssl_SecureSend(ss, buf, len, 0);
01129 }
01130 
01131 SECStatus
01132 SSL_BadCertHook(PRFileDesc *fd, SSLBadCertHandler f, void *arg)
01133 {
01134     sslSocket *ss;
01135     
01136     ss = ssl_FindSocket(fd);
01137     if (!ss) {
01138        SSL_DBG(("%d: SSL[%d]: bad socket in SSLBadCertHook",
01139                SSL_GETPID(), fd));
01140        return SECFailure;
01141     }
01142 
01143     ss->handleBadCert = f;
01144     ss->badCertArg = arg;
01145 
01146     return SECSuccess;
01147 }
01148 
01149 /*
01150  * Allow the application to pass the url or hostname into the SSL library
01151  * so that we can do some checking on it.
01152  */
01153 SECStatus
01154 SSL_SetURL(PRFileDesc *fd, const char *url)
01155 {
01156     sslSocket *   ss = ssl_FindSocket(fd);
01157     SECStatus     rv = SECSuccess;
01158 
01159     if (!ss) {
01160        SSL_DBG(("%d: SSL[%d]: bad socket in SSLSetURL",
01161                SSL_GETPID(), fd));
01162        return SECFailure;
01163     }
01164     ssl_Get1stHandshakeLock(ss);
01165     ssl_GetSSL3HandshakeLock(ss);
01166 
01167     if ( ss->url ) {
01168        PORT_Free((void *)ss->url); /* CONST */
01169     }
01170 
01171     ss->url = (const char *)PORT_Strdup(url);
01172     if ( ss->url == NULL ) {
01173        rv = SECFailure;
01174     }
01175 
01176     ssl_ReleaseSSL3HandshakeLock(ss);
01177     ssl_Release1stHandshakeLock(ss);
01178 
01179     return rv;
01180 }
01181 
01182 /*
01183 ** Returns Negative number on error, zero or greater on success.
01184 ** Returns the amount of data immediately available to be read.
01185 */
01186 int
01187 SSL_DataPending(PRFileDesc *fd)
01188 {
01189     sslSocket *ss;
01190     int        rv  = 0;
01191 
01192     ss = ssl_FindSocket(fd);
01193 
01194     if (ss && ss->opt.useSecurity) {
01195 
01196        ssl_Get1stHandshakeLock(ss);
01197        ssl_GetSSL3HandshakeLock(ss);
01198 
01199        ssl_GetRecvBufLock(ss);
01200        rv = ss->gs.writeOffset - ss->gs.readOffset;
01201        ssl_ReleaseRecvBufLock(ss);
01202 
01203        ssl_ReleaseSSL3HandshakeLock(ss);
01204        ssl_Release1stHandshakeLock(ss);
01205     }
01206 
01207     return rv;
01208 }
01209 
01210 SECStatus
01211 SSL_InvalidateSession(PRFileDesc *fd)
01212 {
01213     sslSocket *   ss = ssl_FindSocket(fd);
01214     SECStatus     rv = SECFailure;
01215 
01216     if (ss) {
01217        ssl_Get1stHandshakeLock(ss);
01218        ssl_GetSSL3HandshakeLock(ss);
01219 
01220        if (ss->sec.ci.sid) {
01221            ss->sec.uncache(ss->sec.ci.sid);
01222            rv = SECSuccess;
01223        }
01224 
01225        ssl_ReleaseSSL3HandshakeLock(ss);
01226        ssl_Release1stHandshakeLock(ss);
01227     }
01228     return rv;
01229 }
01230 
01231 SECItem *
01232 SSL_GetSessionID(PRFileDesc *fd)
01233 {
01234     sslSocket *    ss;
01235     SECItem *      item = NULL;
01236 
01237     ss = ssl_FindSocket(fd);
01238     if (ss) {
01239        ssl_Get1stHandshakeLock(ss);
01240        ssl_GetSSL3HandshakeLock(ss);
01241 
01242        if (ss->opt.useSecurity && ss->firstHsDone && ss->sec.ci.sid) {
01243            item = (SECItem *)PORT_Alloc(sizeof(SECItem));
01244            if (item) {
01245               sslSessionID * sid = ss->sec.ci.sid;
01246               if (sid->version < SSL_LIBRARY_VERSION_3_0) {
01247                   item->len = SSL2_SESSIONID_BYTES;
01248                   item->data = (unsigned char*)PORT_Alloc(item->len);
01249                   PORT_Memcpy(item->data, sid->u.ssl2.sessionID, item->len);
01250               } else {
01251                   item->len = sid->u.ssl3.sessionIDLength;
01252                   item->data = (unsigned char*)PORT_Alloc(item->len);
01253                   PORT_Memcpy(item->data, sid->u.ssl3.sessionID, item->len);
01254               }
01255            }
01256        }
01257 
01258        ssl_ReleaseSSL3HandshakeLock(ss);
01259        ssl_Release1stHandshakeLock(ss);
01260     }
01261     return item;
01262 }
01263 
01264 SECStatus
01265 SSL_CertDBHandleSet(PRFileDesc *fd, CERTCertDBHandle *dbHandle)
01266 {
01267     sslSocket *    ss;
01268 
01269     ss = ssl_FindSocket(fd);
01270     if (!ss)
01271        return SECFailure;
01272     if (!dbHandle) {
01273        PORT_SetError(SEC_ERROR_INVALID_ARGS);
01274        return SECFailure;
01275     }
01276     ss->dbHandle = dbHandle;
01277     return SECSuccess;
01278 }
01279 
01280 /*
01281  * attempt to restart the handshake after asynchronously handling
01282  * a request for the client's certificate.
01283  *
01284  * inputs:  
01285  *     cert   Client cert chosen by application.
01286  *            Note: ssl takes this reference, and does not bump the 
01287  *            reference count.  The caller should drop its reference
01288  *            without calling CERT_DestroyCert after calling this function.
01289  *
01290  *     key    Private key associated with cert.  This function makes a 
01291  *            copy of the private key, so the caller remains responsible 
01292  *            for destroying its copy after this function returns.
01293  *
01294  *     certChain  Chain of signers for cert.  
01295  *            Note: ssl takes this reference, and does not copy the chain.
01296  *            The caller should drop its reference without destroying the 
01297  *            chain.  SSL will free the chain when it is done with it.
01298  *
01299  * Return value: XXX
01300  *
01301  * XXX This code only works on the initial handshake on a connection, XXX
01302  *     It does not work on a subsequent handshake (redo).
01303  */
01304 int
01305 SSL_RestartHandshakeAfterCertReq(sslSocket *         ss,
01306                             CERTCertificate *    cert, 
01307                             SECKEYPrivateKey *   key,
01308                             CERTCertificateList *certChain)
01309 {
01310     int              ret;
01311 
01312     ssl_Get1stHandshakeLock(ss);   /************************************/
01313 
01314     if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
01315        ret = ssl3_RestartHandshakeAfterCertReq(ss, cert, key, certChain);
01316     } else {
01317        ret = ssl2_RestartHandshakeAfterCertReq(ss, cert, key);
01318     }
01319 
01320     ssl_Release1stHandshakeLock(ss);  /************************************/
01321     return ret;
01322 }
01323 
01324 
01325 /* restart an SSL connection that we stopped to run certificate dialogs 
01326 ** XXX Need to document here how an application marks a cert to show that
01327 **     the application has accepted it (overridden CERT_VerifyCert).
01328  *
01329  * XXX This code only works on the initial handshake on a connection, XXX
01330  *     It does not work on a subsequent handshake (redo).
01331  *
01332  * Return value: XXX
01333 */
01334 int
01335 SSL_RestartHandshakeAfterServerCert(sslSocket *ss)
01336 {
01337     int rv    = SECSuccess;
01338 
01339     ssl_Get1stHandshakeLock(ss); 
01340 
01341     if (ss->version >= SSL_LIBRARY_VERSION_3_0) {
01342        rv = ssl3_RestartHandshakeAfterServerCert(ss);
01343     } else {
01344        rv = ssl2_RestartHandshakeAfterServerCert(ss);
01345     }
01346 
01347     ssl_Release1stHandshakeLock(ss);
01348     return rv;
01349 }