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