Back to index

lightning-sunbird  0.9+nobinonly
sslgathr.c
Go to the documentation of this file.
00001 /*
00002  * Gather (Read) entire SSL2 records from socket into buffer.  
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  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either the GNU General Public License Version 2 or later (the "GPL"), or
00028  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 /* $Id: sslgathr.c,v 1.8 2005/09/09 03:02:16 nelsonb%netscape.com Exp $ */
00040 #include "cert.h"
00041 #include "ssl.h"
00042 #include "sslimpl.h"
00043 #include "sslproto.h"
00044 
00045 /* Forward static declarations */
00046 static SECStatus ssl2_HandleV3HandshakeRecord(sslSocket *ss);
00047 
00048 /*
00049 ** Gather a single record of data from the receiving stream. This code
00050 ** first gathers the header (2 or 3 bytes long depending on the value of
00051 ** the most significant bit in the first byte) then gathers up the data
00052 ** for the record into gs->buf. This code handles non-blocking I/O
00053 ** and is to be called multiple times until ss->sec.recordLen != 0.
00054 ** This function decrypts the gathered record in place, in gs_buf.
00055  *
00056  * Caller must hold RecvBufLock. 
00057  *
00058  * Returns +1 when it has gathered a complete SSLV2 record.
00059  * Returns  0 if it hits EOF.
00060  * Returns -1 (SECFailure)    on any error
00061  * Returns -2 (SECWouldBlock) when it gathers an SSL v3 client hello header.
00062 **
00063 ** The SSL2 Gather State machine has 4 states:
00064 ** GS_INIT   - Done reading in previous record.  Haven't begun to read in
00065 **             next record.  When ssl2_GatherData is called with the machine
00066 **             in this state, the machine will attempt to read the first 3
00067 **             bytes of the SSL2 record header, and will advance the state
00068 **             to GS_HEADER.
00069 **
00070 ** GS_HEADER - The machine is in this state while waiting for the completion
00071 **             of the first 3 bytes of the SSL2 record.  When complete, the
00072 **             machine will compute the remaining unread length of this record
00073 **             and will initiate a read of that many bytes.  The machine will
00074 **             advance to one of two states, depending on whether the record
00075 **             is encrypted (GS_MAC), or unencrypted (GS_DATA).
00076 **
00077 ** GS_MAC    - The machine is in this state while waiting for the remainder 
00078 **             of the SSL2 record to be read in.  When the read is completed,
00079 **             the machine checks the record for valid length, decrypts it,
00080 **             and checks and discards the MAC, then advances to GS_INIT.
00081 **
00082 ** GS_DATA   - The machine is in this state while waiting for the remainder
00083 **             of the unencrypted SSL2 record to be read in.  Upon completion,
00084 **             the machine advances to the GS_INIT state and returns the data.
00085 */
00086 int 
00087 ssl2_GatherData(sslSocket *ss, sslGather *gs, int flags)
00088 {
00089     unsigned char *  bp;
00090     unsigned char *  pBuf;
00091     int              nb, err, rv;
00092 
00093     PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
00094 
00095     if (gs->state == GS_INIT) {
00096        /* Initialize gathering engine */
00097        gs->state         = GS_HEADER;
00098        gs->remainder     = 3;
00099        gs->count         = 3;
00100        gs->offset        = 0;
00101        gs->recordLen     = 0;
00102        gs->recordPadding = 0;
00103        gs->hdr[2]        = 0;
00104 
00105        gs->writeOffset   = 0;
00106        gs->readOffset    = 0;
00107     }
00108     if (gs->encrypted) {
00109        PORT_Assert(ss->sec.hash != 0);
00110     }
00111 
00112     pBuf = gs->buf.buf;
00113     for (;;) {
00114        SSL_TRC(30, ("%d: SSL[%d]: gather state %d (need %d more)",
00115                    SSL_GETPID(), ss->fd, gs->state, gs->remainder));
00116        bp = ((gs->state != GS_HEADER) ? pBuf : gs->hdr) + gs->offset;
00117        nb = ssl_DefRecv(ss, bp, gs->remainder, flags);
00118        if (nb > 0) {
00119            PRINT_BUF(60, (ss, "raw gather data:", bp, nb));
00120        }
00121        if (nb == 0) {
00122            /* EOF */
00123            SSL_TRC(30, ("%d: SSL[%d]: EOF", SSL_GETPID(), ss->fd));
00124            rv = 0;
00125            break;
00126        }
00127        if (nb < 0) {
00128            SSL_DBG(("%d: SSL[%d]: recv error %d", SSL_GETPID(), ss->fd,
00129                    PR_GetError()));
00130            rv = SECFailure;
00131            break;
00132        }
00133 
00134        gs->offset    += nb;
00135        gs->remainder -= nb;
00136 
00137        if (gs->remainder > 0) {
00138            continue;
00139        }
00140 
00141        /* Probably finished this piece */
00142        switch (gs->state) {
00143        case GS_HEADER: 
00144            if ((ss->opt.enableSSL3 || ss->opt.enableTLS) && !ss->firstHsDone) {
00145 
00146               PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
00147 
00148               /* If this looks like an SSL3 handshake record, 
00149               ** and we're expecting an SSL2 Hello message from our peer, 
00150               ** handle it here.
00151               */
00152               if (gs->hdr[0] == content_handshake) {
00153                   if ((ss->nextHandshake == ssl2_HandleClientHelloMessage) ||
00154                      (ss->nextHandshake == ssl2_HandleServerHelloMessage)) {
00155                      rv = ssl2_HandleV3HandshakeRecord(ss);
00156                      if (rv == SECFailure) {
00157                          return SECFailure;
00158                      }
00159                   }
00160                   /* XXX_1  The call stack to here is:
00161                    * ssl_Do1stHandshake -> ssl_GatherRecord1stHandshake -> 
00162                    *               ssl2_GatherRecord -> here.
00163                    * We want to return all the way out to ssl_Do1stHandshake,
00164                    * and have it call ssl_GatherRecord1stHandshake again. 
00165                    * ssl_GatherRecord1stHandshake will call 
00166                    * ssl3_GatherCompleteHandshake when it is called again.
00167                    *
00168                    * Returning SECWouldBlock here causes 
00169                    * ssl_GatherRecord1stHandshake to return without clearing 
00170                    * ss->handshake, ensuring that ssl_Do1stHandshake will 
00171                    * call it again immediately.
00172                    * 
00173                    * If we return 1 here, ssl_GatherRecord1stHandshake will 
00174                    * clear ss->handshake before returning, and thus will not 
00175                    * be called again by ssl_Do1stHandshake.  
00176                    */
00177                   return SECWouldBlock;
00178               } else if (gs->hdr[0] == content_alert) {
00179                   if (ss->nextHandshake == ssl2_HandleServerHelloMessage) {
00180                      /* XXX This is a hack.  We're assuming that any failure
00181                       * XXX on the client hello is a failure to match
00182                       * XXX ciphers.
00183                       */
00184                      PORT_SetError(SSL_ERROR_NO_CYPHER_OVERLAP);
00185                      return SECFailure;
00186                   }
00187               }
00188            }  /* ((ss->opt.enableSSL3 || ss->opt.enableTLS) && !ss->firstHsDone) */
00189 
00190            /* we've got the first 3 bytes.  The header may be two or three. */
00191            if (gs->hdr[0] & 0x80) {
00192               /* This record has a 2-byte header, and no padding */
00193               gs->count = ((gs->hdr[0] & 0x7f) << 8) | gs->hdr[1];
00194               gs->recordPadding = 0;
00195            } else {
00196               /* This record has a 3-byte header that is all read in now. */
00197               gs->count = ((gs->hdr[0] & 0x3f) << 8) | gs->hdr[1];
00198            /*  is_escape =  (gs->hdr[0] & 0x40) != 0; */
00199               gs->recordPadding = gs->hdr[2];
00200            }
00201            if (!gs->count) {
00202               PORT_SetError(SSL_ERROR_RX_RECORD_TOO_LONG);
00203               goto cleanup;
00204            }
00205 
00206            if (gs->count > gs->buf.space) {
00207               err = sslBuffer_Grow(&gs->buf, gs->count);
00208               if (err) {
00209                   return err;
00210               }
00211               pBuf = gs->buf.buf;
00212            }
00213 
00214 
00215            if (gs->hdr[0] & 0x80) {
00216               /* we've already read in the first byte of the body.
00217               ** Put it into the buffer.
00218               */
00219               pBuf[0]        = gs->hdr[2];
00220               gs->offset    = 1;
00221               gs->remainder = gs->count - 1;
00222            } else {
00223               gs->offset    = 0;
00224               gs->remainder = gs->count;
00225            }
00226 
00227            if (gs->encrypted) {
00228               gs->state     = GS_MAC;
00229               gs->recordLen = gs->count - gs->recordPadding
00230                                         - ss->sec.hash->length;
00231            } else {
00232               gs->state     = GS_DATA;
00233               gs->recordLen = gs->count;
00234            }
00235 
00236            break;
00237 
00238 
00239        case GS_MAC:
00240            /* Have read in entire rest of the ciphertext.  
00241            ** Check for valid length.
00242            ** Decrypt it.
00243            ** Check the MAC.
00244            */
00245            PORT_Assert(gs->encrypted);
00246 
00247          {
00248            unsigned int     macLen;
00249            int              nout;
00250            unsigned char    mac[SSL_MAX_MAC_BYTES];
00251 
00252            ssl_GetSpecReadLock(ss); /**********************************/
00253 
00254            /* If this is a stream cipher, blockSize will be 1,
00255             * and this test will always be false.
00256             * If this is a block cipher, this will detect records
00257             * that are not a multiple of the blocksize in length.
00258             */
00259            if (gs->count & (ss->sec.blockSize - 1)) {
00260               /* This is an error. Sender is misbehaving */
00261               SSL_DBG(("%d: SSL[%d]: sender, count=%d blockSize=%d",
00262                       SSL_GETPID(), ss->fd, gs->count,
00263                       ss->sec.blockSize));
00264               PORT_SetError(SSL_ERROR_BAD_BLOCK_PADDING);
00265               rv = SECFailure;
00266               goto spec_locked_done;
00267            }
00268            PORT_Assert(gs->count == gs->offset);
00269 
00270            if (gs->offset == 0) {
00271               rv = 0;                     /* means EOF. */
00272               goto spec_locked_done;
00273            }
00274 
00275            /* Decrypt the portion of data that we just recieved.
00276            ** Decrypt it in place.
00277            */
00278            rv = (*ss->sec.dec)(ss->sec.readcx, pBuf, &nout, gs->offset,
00279                           pBuf, gs->offset);
00280            if (rv != SECSuccess) {
00281               goto spec_locked_done;
00282            }
00283 
00284 
00285            /* Have read in all the MAC portion of record 
00286            **
00287            ** Prepare MAC by resetting it and feeding it the shared secret
00288            */
00289            macLen = ss->sec.hash->length;
00290            if (gs->offset >= macLen) {
00291               uint32           sequenceNumber = ss->sec.rcvSequence++;
00292               unsigned char    seq[4];
00293 
00294               seq[0] = (unsigned char) (sequenceNumber >> 24);
00295               seq[1] = (unsigned char) (sequenceNumber >> 16);
00296               seq[2] = (unsigned char) (sequenceNumber >> 8);
00297               seq[3] = (unsigned char) (sequenceNumber);
00298 
00299               (*ss->sec.hash->begin)(ss->sec.hashcx);
00300               (*ss->sec.hash->update)(ss->sec.hashcx, ss->sec.rcvSecret.data,
00301                                     ss->sec.rcvSecret.len);
00302               (*ss->sec.hash->update)(ss->sec.hashcx, pBuf + macLen, 
00303                                     gs->offset - macLen);
00304               (*ss->sec.hash->update)(ss->sec.hashcx, seq, 4);
00305               (*ss->sec.hash->end)(ss->sec.hashcx, mac, &macLen, macLen);
00306            }
00307 
00308            PORT_Assert(macLen == ss->sec.hash->length);
00309 
00310            ssl_ReleaseSpecReadLock(ss);  /******************************/
00311 
00312            if (PORT_Memcmp(mac, pBuf, macLen) != 0) {
00313               /* MAC's didn't match... */
00314               SSL_DBG(("%d: SSL[%d]: mac check failed, seq=%d",
00315                       SSL_GETPID(), ss->fd, ss->sec.rcvSequence));
00316               PRINT_BUF(1, (ss, "computed mac:", mac, macLen));
00317               PRINT_BUF(1, (ss, "received mac:", pBuf, macLen));
00318               PORT_SetError(SSL_ERROR_BAD_MAC_READ);
00319               rv = SECFailure;
00320               goto cleanup;
00321            }
00322 
00323 
00324            PORT_Assert(gs->recordPadding + macLen <= gs->offset);
00325            if (gs->recordPadding + macLen <= gs->offset) {
00326               gs->recordOffset  = macLen;
00327               gs->readOffset    = macLen;
00328               gs->writeOffset   = gs->offset - gs->recordPadding;
00329               rv = 1;
00330            } else {
00331               PORT_SetError(SSL_ERROR_BAD_BLOCK_PADDING);
00332 cleanup:
00333               /* nothing in the buffer any more. */
00334               gs->recordOffset  = 0;
00335               gs->readOffset    = 0;
00336               gs->writeOffset   = 0;
00337               rv = SECFailure;
00338            }
00339 
00340            gs->recordLen     = gs->writeOffset - gs->readOffset;
00341            gs->recordPadding = 0;  /* forget we did any padding. */
00342            gs->state = GS_INIT;
00343 
00344 
00345            if (rv > 0) {
00346               PRINT_BUF(50, (ss, "recv clear record:", 
00347                              pBuf + gs->recordOffset, gs->recordLen));
00348            }
00349            return rv;
00350 
00351 spec_locked_done:
00352            ssl_ReleaseSpecReadLock(ss);
00353            return rv;
00354          }
00355 
00356        case GS_DATA:
00357            /* Have read in all the DATA portion of record */
00358 
00359            gs->recordOffset  = 0;
00360            gs->readOffset    = 0;
00361            gs->writeOffset   = gs->offset;
00362            PORT_Assert(gs->recordLen == gs->writeOffset - gs->readOffset);
00363            gs->recordLen     = gs->offset;
00364            gs->recordPadding = 0;
00365            gs->state         = GS_INIT;
00366 
00367            ++ss->sec.rcvSequence;
00368 
00369            PRINT_BUF(50, (ss, "recv clear record:", 
00370                           pBuf + gs->recordOffset, gs->recordLen));
00371            return 1;
00372 
00373        }      /* end switch gs->state */
00374     }         /* end gather loop. */
00375     return rv;
00376 }
00377 
00378 /*
00379 ** Gather a single record of data from the receiving stream. This code
00380 ** first gathers the header (2 or 3 bytes long depending on the value of
00381 ** the most significant bit in the first byte) then gathers up the data
00382 ** for the record into the readBuf. This code handles non-blocking I/O
00383 ** and is to be called multiple times until ss->sec.recordLen != 0.
00384  *
00385  * Returns +1 when it has gathered a complete SSLV2 record.
00386  * Returns  0 if it hits EOF.
00387  * Returns -1 (SECFailure)    on any error
00388  * Returns -2 (SECWouldBlock) 
00389  *
00390  * Called by ssl_GatherRecord1stHandshake in sslcon.c, 
00391  * and by DoRecv in sslsecur.c
00392  * Caller must hold RecvBufLock.
00393  */
00394 int 
00395 ssl2_GatherRecord(sslSocket *ss, int flags)
00396 {
00397     return ssl2_GatherData(ss, &ss->gs, flags);
00398 }
00399 
00400 /*
00401  * Returns +1 when it has gathered a complete SSLV2 record.
00402  * Returns  0 if it hits EOF.
00403  * Returns -1 (SECFailure)    on any error
00404  * Returns -2 (SECWouldBlock) 
00405  *
00406  * Called from SocksStartGather in sslsocks.c
00407  * Caller must hold RecvBufLock. 
00408  */
00409 int 
00410 ssl2_StartGatherBytes(sslSocket *ss, sslGather *gs, unsigned int count)
00411 {
00412     int rv;
00413 
00414     PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
00415     gs->state     = GS_DATA;
00416     gs->remainder = count;
00417     gs->count     = count;
00418     gs->offset    = 0;
00419     if (count > gs->buf.space) {
00420        rv = sslBuffer_Grow(&gs->buf, count);
00421        if (rv) {
00422            return rv;
00423        }
00424     }
00425     return ssl2_GatherData(ss, gs, 0);
00426 }
00427 
00428 /* Caller should hold RecvBufLock. */
00429 SECStatus
00430 ssl_InitGather(sslGather *gs)
00431 {
00432     SECStatus status;
00433 
00434     gs->state = GS_INIT;
00435     gs->writeOffset = 0;
00436     gs->readOffset  = 0;
00437     status = sslBuffer_Grow(&gs->buf, 4096);
00438     return status;
00439 }
00440 
00441 /* Caller must hold RecvBufLock. */
00442 void 
00443 ssl_DestroyGather(sslGather *gs)
00444 {
00445     if (gs) { /* the PORT_*Free functions check for NULL pointers. */
00446        PORT_ZFree(gs->buf.buf, gs->buf.space);
00447        PORT_Free(gs->inbuf.buf);
00448     }
00449 }
00450 
00451 /* Caller must hold RecvBufLock. */
00452 static SECStatus
00453 ssl2_HandleV3HandshakeRecord(sslSocket *ss)
00454 {
00455     SECStatus           rv;
00456     SSL3ProtocolVersion version = (ss->gs.hdr[1] << 8) | ss->gs.hdr[2];
00457 
00458     PORT_Assert( ss->opt.noLocks || ssl_HaveRecvBufLock(ss) );
00459     PORT_Assert( ss->opt.noLocks || ssl_Have1stHandshakeLock(ss) );
00460 
00461     /* We've read in 3 bytes, there are 2 more to go in an ssl3 header. */
00462     ss->gs.remainder         = 2;
00463     ss->gs.count             = 0;
00464 
00465     /* Clearing these handshake pointers ensures that 
00466      * ssl_Do1stHandshake won't call ssl2_HandleMessage when we return.
00467      */
00468     ss->nextHandshake     = 0;
00469     ss->securityHandshake = 0;
00470 
00471     /* Setting ss->version to an SSL 3.x value will cause 
00472     ** ssl_GatherRecord1stHandshake to invoke ssl3_GatherCompleteHandshake() 
00473     ** the next time it is called.
00474     **/
00475     rv = ssl3_NegotiateVersion(ss, version);
00476     if (rv != SECSuccess) {
00477        return rv;
00478     }
00479 
00480     ss->sec.send         = ssl3_SendApplicationData;
00481 
00482     return SECSuccess;
00483 }