Dependents:   HTTPClient-SSL HTTPClient-SSL HTTPClient-SSL HTTPClient-SSL

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sniffer.c Source File

sniffer.c

00001 /* sniffer.c
00002  *
00003  * Copyright (C) 2006-2014 wolfSSL Inc.
00004  *
00005  * This file is part of CyaSSL.
00006  *
00007  * CyaSSL is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * CyaSSL is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 
00023 
00024 #ifdef HAVE_CONFIG_H
00025     #include <config.h>
00026 #endif
00027 
00028 #include <cyassl/ctaocrypt/settings.h>
00029 
00030 #ifdef CYASSL_SNIFFER
00031 
00032 #include <assert.h>
00033 #include <time.h>
00034 
00035 #ifndef _WIN32
00036   #include <arpa/inet.h>
00037 #endif
00038 
00039 #ifdef _WIN32
00040     #define SNPRINTF _snprintf
00041 #else
00042     #define SNPRINTF snprintf
00043 #endif
00044 
00045 #include <cyassl/openssl/ssl.h>
00046 #include <cyassl/internal.h>
00047 #include <cyassl/error-ssl.h>
00048 #include <cyassl/sniffer.h>
00049 #include <cyassl/sniffer_error.h>
00050 
00051 
00052 #ifndef min
00053 
00054 static INLINE word32 min(word32 a, word32 b)
00055 {
00056     return a > b ? b : a;
00057 }
00058 
00059 #endif
00060 
00061 #ifndef CYASSL_SNIFFER_TIMEOUT
00062     #define CYASSL_SNIFFER_TIMEOUT 900
00063     /* Cache unclosed Sessions for 15 minutes since last used */
00064 #endif
00065 
00066 /* Misc constants */
00067 enum {
00068     MAX_SERVER_ADDRESS = 128, /* maximum server address length */
00069     MAX_SERVER_NAME    = 128, /* maximum server name length */
00070     MAX_ERROR_LEN      = 80,  /* maximum error length */
00071     ETHER_IF_ADDR_LEN  = 6,   /* ethernet interface address length */
00072     LOCAL_IF_ADDR_LEN  = 4,   /* localhost interface address length, !windows */
00073     TCP_PROTO          = 6,   /* TCP_PROTOCOL */
00074     IP_HDR_SZ          = 20,  /* IP header legnth, min */
00075     TCP_HDR_SZ         = 20,  /* TCP header legnth, min */
00076     IPV4               = 4,   /* IP version 4 */
00077     TCP_PROTOCOL       = 6,   /* TCP Protocol id */
00078     TRACE_MSG_SZ       = 80,  /* Trace Message buffer size */
00079     HASH_SIZE          = 499, /* Session Hash Table Rows */
00080     PSEUDO_HDR_SZ      = 12,  /* TCP Pseudo Header size in bytes */
00081     FATAL_ERROR_STATE  =  1,  /* SnifferSession fatal error state */
00082     TICKET_HINT_LEN    = 4,   /* Session Ticket Hint length */
00083     EXT_TYPE_SZ        = 2,   /* Extension length */
00084     MAX_INPUT_SZ       = MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA + 
00085                          MTU_EXTRA,  /* Max input sz of reassembly */
00086     TICKET_EXT_ID      = 0x23 /* Session Ticket Extension ID */
00087 };
00088 
00089 
00090 #ifdef _WIN32
00091 
00092 static HMODULE dllModule;  /* for error string resources */
00093 
00094 BOOL APIENTRY DllMain( HMODULE hModule,
00095                        DWORD  ul_reason_for_call,
00096                        LPVOID lpReserved
00097                      )
00098 {
00099     static int didInit = 0;
00100 
00101     switch (ul_reason_for_call)
00102     {
00103     case DLL_PROCESS_ATTACH:
00104         if (didInit == 0) {
00105             dllModule = hModule;
00106             ssl_InitSniffer();
00107             didInit = 1;
00108         }
00109         break;
00110     case DLL_THREAD_ATTACH:
00111         break;
00112     case DLL_THREAD_DETACH:
00113         break;
00114     case DLL_PROCESS_DETACH:
00115         if (didInit) {
00116             ssl_FreeSniffer();
00117             didInit = 0;
00118         }
00119         break;
00120     }
00121     return TRUE;
00122 }
00123 
00124 #endif /* _WIN32 */
00125 
00126 
00127 static int TraceOn = 0;         /* Trace is off by default */
00128 static FILE* TraceFile = 0;
00129 
00130 
00131 /* windows uses .rc table for this */
00132 #ifndef _WIN32
00133 
00134 static const char* const msgTable[] =
00135 {
00136     /* 1 */
00137     "Out of Memory",
00138     "New SSL Sniffer Server Registered",
00139     "Checking IP Header",
00140     "SSL Sniffer Server Not Registered",
00141     "Checking TCP Header",
00142 
00143     /* 6 */
00144     "SSL Sniffer Server Port Not Registered",
00145     "RSA Private Decrypt Error",
00146     "RSA Private Decode Error",
00147     "Set Cipher Spec Error",
00148     "Server Hello Input Malformed",
00149 
00150     /* 11 */
00151     "Couldn't Resume Session Error",
00152     "Server Did Resumption",
00153     "Client Hello Input Malformed",
00154     "Client Trying to Resume",
00155     "Handshake Input Malformed",
00156 
00157     /* 16 */
00158     "Got Hello Verify msg",
00159     "Got Server Hello msg",
00160     "Got Cert Request msg",
00161     "Got Server Key Exchange msg",
00162     "Got Cert msg",
00163 
00164     /* 21 */
00165     "Got Server Hello Done msg",
00166     "Got Finished msg",
00167     "Got Client Hello msg",
00168     "Got Client Key Exchange msg",
00169     "Got Cert Verify msg",
00170 
00171     /* 26 */
00172     "Got Unknown Handshake msg",
00173     "New SSL Sniffer Session created",
00174     "Couldn't create new SSL",
00175     "Got a Packet to decode",
00176     "No data present",
00177 
00178     /* 31 */
00179     "Session Not Found",
00180     "Got an Old Client Hello msg",
00181     "Old Client Hello Input Malformed",
00182     "Old Client Hello OK",
00183     "Bad Old Client Hello",
00184 
00185     /* 36 */
00186     "Bad Record Header",
00187     "Record Header Input Malformed",
00188     "Got a HandShake msg",
00189     "Bad HandShake msg",
00190     "Got a Change Cipher Spec msg",
00191 
00192     /* 41 */
00193     "Got Application Data msg",
00194     "Bad Application Data",
00195     "Got an Alert msg",
00196     "Another msg to Process",
00197     "Removing Session From Table",
00198     
00199     /* 46 */
00200     "Bad Key File",
00201     "Wrong IP Version",
00202     "Wrong Protocol type",
00203     "Packet Short for header processing",
00204     "Got Unknown Record Type",
00205     
00206     /* 51 */
00207     "Can't Open Trace File",
00208     "Session in Fatal Error State",
00209     "Partial SSL record received",
00210     "Buffer Error, malformed input",
00211     "Added to Partial Input",
00212     
00213     /* 56 */
00214     "Received a Duplicate Packet",
00215     "Received an Out of Order Packet",
00216     "Received an Overlap Duplicate Packet",
00217     "Received an Overlap Reassembly Begin Duplicate Packet",
00218     "Received an Overlap Reassembly End Duplicate Packet",
00219 
00220     /* 61 */
00221     "Missed the Client Hello Entirely",
00222     "Got Hello Request msg",
00223     "Got Session Ticket msg",
00224     "Bad Input",
00225     "Bad Decrypt Type",
00226 
00227     /* 66 */
00228     "Bad Finished Message Processing",
00229     "Bad Compression Type",
00230     "Bad DeriveKeys Error",
00231     "Saw ACK for Missing Packet Error",
00232     "Bad Decrypt Operation",
00233 
00234     /* 71 */
00235     "Decrypt Keys Not Set Up",
00236     "Late Key Load Error"
00237 };
00238 
00239 
00240 /* *nix version uses table above */
00241 static void GetError(int idx, char* str)
00242 {
00243     XSTRNCPY(str, msgTable[idx - 1], MAX_ERROR_LEN);
00244 }
00245 
00246 
00247 #else /* _WIN32 */
00248 
00249 
00250 /* Windows version uses .rc table */
00251 static void GetError(int idx, char* buffer)
00252 {
00253     if (!LoadStringA(dllModule, idx, buffer, MAX_ERROR_LEN))
00254         buffer[0] = 0;
00255 }
00256 
00257 
00258 #endif /* _WIN32 */
00259 
00260 
00261 /* Packet Buffer for reassembly list and ready list */
00262 typedef struct PacketBuffer {
00263     word32  begin;      /* relative sequence begin */
00264     word32  end;        /* relative sequence end   */
00265     byte*   data;       /* actual data             */
00266     struct PacketBuffer* next; /* next on reassembly list or ready list */
00267 } PacketBuffer;
00268 
00269 
00270 #ifdef HAVE_SNI
00271 
00272 /* NamedKey maps a SNI name to a specific private key */
00273 typedef struct NamedKey {
00274     char             name[MAX_SERVER_NAME];      /* server DNS name */
00275     word32           nameSz;                     /* size of server DNS name */
00276     byte*            key;                        /* DER private key */
00277     word32           keySz;                      /* size of DER private key */
00278     struct NamedKey* next;                       /* for list */
00279 } NamedKey;
00280 
00281 #endif
00282 
00283 
00284 /* Sniffer Server holds info for each server/port monitored */
00285 typedef struct SnifferServer {
00286     SSL_CTX*       ctx;                          /* SSL context */
00287     char           address[MAX_SERVER_ADDRESS];  /* passed in server address */
00288     word32         server;                       /* netowrk order address */
00289     int            port;                         /* server port */
00290 #ifdef HAVE_SNI
00291     NamedKey*      namedKeys;                    /* mapping of names and keys */
00292     CyaSSL_Mutex   namedKeysMutex;               /* mutex for namedKey list */
00293 #endif
00294     struct SnifferServer* next;                  /* for list */
00295 } SnifferServer;
00296 
00297 
00298 /* Session Flags */
00299 typedef struct Flags {
00300     byte           side;            /* which end is current packet headed */
00301     byte           serverCipherOn;  /* indicates whether cipher is active */
00302     byte           clientCipherOn;  /* indicates whether cipher is active */
00303     byte           resuming;        /* did this session come from resumption */
00304     byte           cached;          /* have we cached this session yet */
00305     byte           clientHello;     /* processed client hello yet, for SSLv2 */
00306     byte           finCount;        /* get both FINs before removing */
00307     byte           fatalError;      /* fatal error state */
00308 } Flags;
00309 
00310 
00311 /* Out of Order FIN caputre */
00312 typedef struct FinCaputre {
00313     word32 cliFinSeq;               /* client relative sequence FIN  0 is no */
00314     word32 srvFinSeq;               /* server relative sequence FIN, 0 is no */
00315     byte   cliCounted;              /* did we count yet, detects duplicates */
00316     byte   srvCounted;              /* did we count yet, detects duplicates */
00317 } FinCaputre;
00318 
00319 
00320 /* Sniffer Session holds info for each client/server SSL/TLS session */
00321 typedef struct SnifferSession {
00322     SnifferServer* context;         /* server context */
00323     SSL*           sslServer;       /* SSL server side decode */
00324     SSL*           sslClient;       /* SSL client side decode */
00325     word32         server;          /* server address in network byte order */
00326     word32         client;          /* client address in network byte order */
00327     word16         srvPort;         /* server port */
00328     word16         cliPort;         /* client port */
00329     word32         cliSeqStart;     /* client start sequence */
00330     word32         srvSeqStart;     /* server start sequence */
00331     word32         cliExpected;     /* client expected sequence (relative) */
00332     word32         srvExpected;     /* server expected sequence (relative) */
00333     FinCaputre     finCaputre;      /* retain out of order FIN s */
00334     Flags          flags;           /* session flags */
00335     time_t         lastUsed;          /* last used ticks */
00336     PacketBuffer*  cliReassemblyList; /* client out of order packets */
00337     PacketBuffer*  srvReassemblyList; /* server out of order packets */
00338     struct SnifferSession* next;      /* for hash table list */
00339     byte*          ticketID;          /* mac ID of session ticket */
00340 } SnifferSession;
00341 
00342 
00343 /* Sniffer Server List and mutex */
00344 static SnifferServer* ServerList = 0;
00345 static CyaSSL_Mutex ServerListMutex;
00346 
00347 
00348 /* Session Hash Table, mutex, and count */
00349 static SnifferSession* SessionTable[HASH_SIZE];
00350 static CyaSSL_Mutex SessionMutex;
00351 static int SessionCount = 0;
00352 
00353 
00354 /* Initialize overall Sniffer */
00355 void ssl_InitSniffer(void)
00356 {
00357     CyaSSL_Init();
00358     InitMutex(&ServerListMutex);
00359     InitMutex(&SessionMutex);
00360 }
00361 
00362 
00363 #ifdef HAVE_SNI
00364 
00365 /* Free Named Key and the zero out the private key it holds */
00366 static void FreeNamedKey(NamedKey* in)
00367 {
00368     if (in) {
00369         if (in->key) {
00370             XMEMSET(in->key, 0, in->keySz);
00371             free(in->key);
00372         }
00373         free(in);
00374     }
00375 }
00376 
00377 
00378 static void FreeNamedKeyList(NamedKey* in)
00379 {
00380     NamedKey* next;
00381 
00382     while (in) {
00383         next = in->next;
00384         FreeNamedKey(in);
00385         in = next;
00386     }
00387 }
00388 
00389 #endif
00390 
00391 
00392 /* Free Sniffer Server's resources/self */
00393 static void FreeSnifferServer(SnifferServer* srv)
00394 {
00395     if (srv) {
00396 #ifdef HAVE_SNI
00397         LockMutex(&srv->namedKeysMutex);
00398         FreeNamedKeyList(srv->namedKeys);
00399         UnLockMutex(&srv->namedKeysMutex);
00400         FreeMutex(&srv->namedKeysMutex);
00401 #endif
00402         SSL_CTX_free(srv->ctx);
00403     }
00404     free(srv);
00405 }
00406 
00407 
00408 /* free PacketBuffer's resources/self */
00409 static void FreePacketBuffer(PacketBuffer* del)
00410 {
00411     if (del) {
00412         free(del->data);
00413         free(del);
00414     }
00415 }
00416 
00417 
00418 /* remove PacketBuffer List */
00419 static void FreePacketList(PacketBuffer* in)
00420 {
00421     if (in) {
00422         PacketBuffer* del;
00423         PacketBuffer* packet = in;
00424         
00425         while (packet) {
00426             del = packet;
00427             packet = packet->next;
00428             FreePacketBuffer(del);
00429         }
00430     }
00431 }
00432 
00433 
00434 /* Free Sniffer Session's resources/self */
00435 static void FreeSnifferSession(SnifferSession* session)
00436 {
00437     if (session) {
00438         SSL_free(session->sslClient);
00439         SSL_free(session->sslServer);
00440         
00441         FreePacketList(session->cliReassemblyList);
00442         FreePacketList(session->srvReassemblyList);
00443 
00444         free(session->ticketID);
00445     }
00446     free(session);
00447 }
00448 
00449 
00450 /* Free overall Sniffer */
00451 void ssl_FreeSniffer(void)
00452 {
00453     SnifferServer*  srv;
00454     SnifferServer*  removeServer;
00455     SnifferSession* session;
00456     SnifferSession* removeSession;
00457     int i;
00458 
00459     LockMutex(&ServerListMutex);
00460     LockMutex(&SessionMutex);
00461     
00462     srv = ServerList;
00463     while (srv) {
00464         removeServer = srv;
00465         srv = srv->next;
00466         FreeSnifferServer(removeServer);
00467     }
00468 
00469     for (i = 0; i < HASH_SIZE; i++) {
00470         session = SessionTable[i];
00471         while (session) {
00472             removeSession = session;
00473             session = session->next;
00474             FreeSnifferSession(removeSession);
00475         }
00476     }
00477 
00478     UnLockMutex(&SessionMutex);
00479     UnLockMutex(&ServerListMutex);
00480 
00481     FreeMutex(&SessionMutex);
00482     FreeMutex(&ServerListMutex);
00483 
00484     if (TraceFile) {
00485         TraceOn = 0;
00486         fclose(TraceFile);
00487         TraceFile = NULL;
00488     }
00489 
00490     CyaSSL_Cleanup();
00491 }
00492 
00493 
00494 /* Initialize a SnifferServer */
00495 static void InitSnifferServer(SnifferServer* sniffer)
00496 {
00497     sniffer->ctx = 0;
00498     XMEMSET(sniffer->address, 0, MAX_SERVER_ADDRESS);
00499     sniffer->server   = 0;
00500     sniffer->port     = 0;
00501 #ifdef HAVE_SNI
00502     sniffer->namedKeys = 0;
00503     InitMutex(&sniffer->namedKeysMutex);
00504 #endif
00505     sniffer->next     = 0;
00506 }
00507 
00508 
00509 /* Initialize session flags */
00510 static void InitFlags(Flags* flags)
00511 {
00512     flags->side           = 0;
00513     flags->serverCipherOn = 0;
00514     flags->clientCipherOn = 0;
00515     flags->resuming       = 0;
00516     flags->cached         = 0;
00517     flags->clientHello    = 0;
00518     flags->finCount       = 0;
00519     flags->fatalError     = 0;
00520 }
00521 
00522 
00523 /* Initialize FIN Capture */
00524 static void InitFinCapture(FinCaputre* cap)
00525 {
00526     cap->cliFinSeq  = 0;
00527     cap->srvFinSeq  = 0;
00528     cap->cliCounted = 0;
00529     cap->srvCounted = 0;
00530 }
00531 
00532 
00533 /* Initialize a Sniffer Session */
00534 static void InitSession(SnifferSession* session)
00535 {
00536     session->context        = 0;
00537     session->sslServer      = 0;
00538     session->sslClient      = 0;
00539     session->server         = 0;
00540     session->client         = 0;
00541     session->srvPort        = 0;
00542     session->cliPort        = 0;
00543     session->cliSeqStart    = 0;
00544     session->srvSeqStart    = 0;
00545     session->cliExpected    = 0;
00546     session->srvExpected    = 0;
00547     session->lastUsed       = 0;
00548     session->cliReassemblyList = 0;
00549     session->srvReassemblyList = 0;
00550     session->next           = 0;
00551     session->ticketID       = 0;
00552     
00553     InitFlags(&session->flags);
00554     InitFinCapture(&session->finCaputre);
00555 }
00556 
00557 
00558 /* IP Info from IP Header */
00559 typedef struct IpInfo {
00560     int    length;        /* length of this header */
00561     int    total;         /* total length of fragment */
00562     word32 src;           /* network order source address */
00563     word32 dst;           /* network order destination address */
00564 } IpInfo;
00565 
00566 
00567 /* TCP Info from TCP Header */
00568 typedef struct TcpInfo {
00569     int    srcPort;       /* source port */
00570     int    dstPort;       /* source port */
00571     int    length;        /* length of this header */
00572     word32 sequence;      /* sequence number */
00573     word32 ackNumber;     /* ack number */
00574     byte   fin;           /* FIN set */
00575     byte   rst;           /* RST set */
00576     byte   syn;           /* SYN set */
00577     byte   ack;           /* ACK set */
00578 } TcpInfo;
00579 
00580 
00581 /* Tcp Pseudo Header for Checksum calculation */
00582 typedef struct TcpPseudoHdr {
00583     word32  src;        /* source address */
00584     word32  dst;        /* destination address */
00585     byte    rsv;        /* reserved, always 0 */
00586     byte    protocol;   /* IP protocol */
00587     word16  legnth;     /* tcp header length + data length (doesn't include */
00588                         /* pseudo header length) network order */
00589 } TcpPseudoHdr;
00590 
00591 
00592 /* Password Setting Callback */
00593 static int SetPassword(char* passwd, int sz, int rw, void* userdata)
00594 {
00595     (void)rw;
00596     XSTRNCPY(passwd, (const char*)userdata, sz);
00597     return (int)XSTRLEN((const char*)userdata);
00598 }
00599 
00600 
00601 /* Ethernet Header */
00602 typedef struct EthernetHdr {
00603     byte   dst[ETHER_IF_ADDR_LEN];    /* destination host address */ 
00604     byte   src[ETHER_IF_ADDR_LEN];    /* source  host address */ 
00605     word16 type;                      /* IP, ARP, etc */ 
00606 } EthernetHdr;
00607 
00608 
00609 /* IP Header */
00610 typedef struct IpHdr {
00611     byte    ver_hl;              /* version/header length */
00612     byte    tos;                 /* type of service */
00613     word16  length;              /* total length */
00614     word16  id;                  /* identification */
00615     word16  offset;              /* fragment offset field */
00616     byte    ttl;                 /* time to live */
00617     byte    protocol;            /* protocol */
00618     word16  sum;                 /* checksum */
00619     word32  src;                 /* source address */
00620     word32  dst;                 /* destination address */
00621 } IpHdr;
00622 
00623 
00624 #define IP_HL(ip)      ( (((ip)->ver_hl) & 0x0f) * 4)
00625 #define IP_V(ip)       ( ((ip)->ver_hl) >> 4)
00626 
00627 /* TCP Header */
00628 typedef struct TcpHdr {
00629     word16  srcPort;            /* source port */
00630     word16  dstPort;            /* destination port */
00631     word32  sequence;           /* sequence number */ 
00632     word32  ack;                /* acknoledgment number */ 
00633     byte    offset;             /* data offset, reserved */
00634     byte    flags;              /* option flags */
00635     word16  window;             /* window */
00636     word16  sum;                /* checksum */
00637     word16  urgent;             /* urgent pointer */
00638 } TcpHdr;
00639 
00640 #define TCP_LEN(tcp)  ( (((tcp)->offset & 0xf0) >> 4) * 4)
00641 #define TCP_FIN 0x01
00642 #define TCP_SYN 0x02
00643 #define TCP_RST 0x04
00644 #define TCP_ACK 0x10
00645 
00646 
00647 
00648 
00649 
00650 /* Use platform specific GetError to write to tracfile if tracing */ 
00651 static void Trace(int idx) 
00652 {
00653     if (TraceOn) {
00654         char myBuffer[MAX_ERROR_LEN];
00655         GetError(idx, myBuffer);
00656         fprintf(TraceFile, "\t%s\n", myBuffer);
00657 #ifdef DEBUG_SNIFFER
00658         fprintf(stderr,    "\t%s\n", myBuffer);
00659 #endif
00660     }
00661 }
00662 
00663 
00664 /* Show TimeStamp for beginning of packet Trace */
00665 static void TraceHeader(void)
00666 {
00667     if (TraceOn) {
00668         time_t ticks = time(NULL);
00669         fprintf(TraceFile, "\n%s", ctime(&ticks));
00670     }
00671 }
00672 
00673 
00674 /* Show Set Server info for Trace */
00675 static void TraceSetServer(const char* srv, int port, const char* keyFile)
00676 {
00677     if (TraceOn) {
00678         fprintf(TraceFile, "\tTrying to install a new Sniffer Server with\n");
00679         fprintf(TraceFile, "\tserver: %s, port: %d, keyFile: %s\n", srv, port,
00680                                                                     keyFile);
00681     }
00682 }
00683 
00684 
00685 #ifdef HAVE_SNI
00686 
00687 /* Show Set Named Server info for Trace */
00688 static void TraceSetNamedServer(const char* name,
00689                                  const char* srv, int port, const char* keyFile)
00690 {
00691     if (TraceOn) {
00692         fprintf(TraceFile, "\tTrying to install a new Sniffer Server with\n");
00693         fprintf(TraceFile, "\tname: %s, server: %s, port: %d, keyFile: %s\n",
00694                                                       name, srv, port, keyFile);
00695     }
00696 }
00697 
00698 #endif
00699 
00700 
00701 /* Trace got packet number */
00702 static void TracePacket(void)
00703 {
00704     if (TraceOn) {
00705         static word32 packetNumber = 0;
00706         fprintf(TraceFile, "\tGot a Packet to decode, packet %u\n",
00707                 ++packetNumber);
00708     }
00709 }
00710 
00711 
00712 /* Convert network byte order address into human readable */
00713 static char* IpToS(word32 addr, char* str)
00714 {
00715     byte* p = (byte*)&addr;
00716     
00717     SNPRINTF(str, TRACE_MSG_SZ, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
00718     
00719     return str;
00720 }
00721 
00722 
00723 /* Show destination and source address from Ip Hdr for packet Trace */
00724 static void TraceIP(IpHdr* iphdr)
00725 {
00726     if (TraceOn) {
00727         char src[TRACE_MSG_SZ];
00728         char dst[TRACE_MSG_SZ];
00729         fprintf(TraceFile, "\tdst:%s src:%s\n", IpToS(iphdr->dst, dst),
00730                 IpToS(iphdr->src, src));
00731     }
00732 }
00733 
00734 
00735 /* Show destination and source port from Tcp Hdr for packet Trace */
00736 static void TraceTcp(TcpHdr* tcphdr)
00737 {
00738     if (TraceOn) {
00739         fprintf(TraceFile, "\tdstPort:%u srcPort:%u\n", ntohs(tcphdr->dstPort),
00740                 ntohs(tcphdr->srcPort));
00741     }
00742 }
00743 
00744 
00745 /* Show sequence and payload length for Trace */
00746 static void TraceSequence(word32 seq, int len)
00747 {
00748     if (TraceOn) {
00749         fprintf(TraceFile, "\tSequence:%u, payload length:%d\n", seq, len);
00750     }
00751 }
00752 
00753 
00754 /* Show sequence and payload length for Trace */
00755 static void TraceAck(word32 ack, word32 expected)
00756 {
00757     if (TraceOn) {
00758         fprintf(TraceFile, "\tAck:%u Expected:%u\n", ack, expected);
00759     }
00760 }
00761 
00762 
00763 /* Show relative expected and relative received sequences */
00764 static void TraceRelativeSequence(word32 expected, word32 got)
00765 {
00766     if (TraceOn) {
00767         fprintf(TraceFile, "\tExpected sequence:%u, received sequence:%u\n",
00768                 expected, got);
00769     }
00770 }
00771 
00772 
00773 /* Show server sequence startup from SYN */
00774 static void TraceServerSyn(word32 seq)
00775 {
00776     if (TraceOn) {
00777         fprintf(TraceFile, "\tServer SYN, Sequence Start:%u\n", seq);
00778     }
00779 }
00780 
00781 
00782 /* Show client sequence startup from SYN */
00783 static void TraceClientSyn(word32 seq)
00784 {
00785     if (TraceOn) {
00786         fprintf(TraceFile, "\tClient SYN, Sequence Start:%u\n", seq);
00787     }
00788 }
00789 
00790 
00791 /* Show client FIN capture */
00792 static void TraceClientFin(word32 finSeq, word32 relSeq)
00793 {
00794     if (TraceOn) {
00795         fprintf(TraceFile, "\tClient FIN capture:%u, current SEQ:%u\n",
00796                 finSeq, relSeq);
00797     }
00798 }
00799 
00800 
00801 /* Show server FIN capture */
00802 static void TraceServerFin(word32 finSeq, word32 relSeq)
00803 {
00804     if (TraceOn) {
00805         fprintf(TraceFile, "\tServer FIN capture:%u, current SEQ:%u\n",
00806                 finSeq, relSeq);
00807     }
00808 }
00809 
00810 
00811 /* Show number of SSL data bytes decoded, could be 0 (ok) */
00812 static void TraceGotData(int bytes)
00813 {
00814     if (TraceOn) {
00815         fprintf(TraceFile, "\t%d bytes of SSL App data processed\n", bytes);
00816     }
00817 }
00818 
00819 
00820 /* Show bytes added to old SSL App data */
00821 static void TraceAddedData(int newBytes, int existingBytes)
00822 {
00823     if (TraceOn) {
00824         fprintf(TraceFile,
00825                 "\t%d bytes added to %d exisiting bytes in User Buffer\n",
00826                 newBytes, existingBytes);
00827     }
00828 }
00829 
00830 
00831 /* Show Stale Session */
00832 static void TraceStaleSession(void)
00833 {
00834     if (TraceOn) {
00835         fprintf(TraceFile, "\tFound a stale session\n");
00836     }
00837 }
00838 
00839 
00840 /* Show Finding Stale Sessions */
00841 static void TraceFindingStale(void)
00842 {
00843     if (TraceOn) {
00844         fprintf(TraceFile, "\tTrying to find Stale Sessions\n");
00845     }
00846 }
00847 
00848 
00849 /* Show Removed Session */
00850 static void TraceRemovedSession(void)
00851 {
00852     if (TraceOn) {
00853         fprintf(TraceFile, "\tRemoved it\n");
00854     }
00855 }
00856 
00857 
00858 /* Set user error string */
00859 static void SetError(int idx, char* error, SnifferSession* session, int fatal)
00860 {
00861     GetError(idx, error);
00862     Trace(idx);
00863     if (session && fatal == FATAL_ERROR_STATE)
00864         session->flags.fatalError = 1;
00865 }
00866 
00867 
00868 /* See if this IPV4 network order address has been registered */
00869 /* return 1 is true, 0 is false */
00870 static int IsServerRegistered(word32 addr)
00871 {
00872     int ret = 0;     /* false */
00873     SnifferServer* sniffer;
00874 
00875     LockMutex(&ServerListMutex);
00876     
00877     sniffer = ServerList;
00878     while (sniffer) {
00879         if (sniffer->server == addr) {
00880             ret = 1;
00881             break;
00882         }
00883         sniffer = sniffer->next;
00884     }
00885     
00886     UnLockMutex(&ServerListMutex);
00887 
00888     return ret;
00889 }
00890 
00891 
00892 /* See if this port has been registered to watch */
00893 /* return 1 is true, 0 is false */
00894 static int IsPortRegistered(word32 port)
00895 {
00896     int ret = 0;    /* false */
00897     SnifferServer* sniffer;
00898     
00899     LockMutex(&ServerListMutex);
00900     
00901     sniffer = ServerList;
00902     while (sniffer) {
00903         if (sniffer->port == (int)port) {
00904             ret = 1; 
00905             break;
00906         }
00907         sniffer = sniffer->next;
00908     }
00909     
00910     UnLockMutex(&ServerListMutex);
00911 
00912     return ret;
00913 }
00914 
00915 
00916 /* Get SnifferServer from IP and Port */
00917 static SnifferServer* GetSnifferServer(IpInfo* ipInfo, TcpInfo* tcpInfo)
00918 {
00919     SnifferServer* sniffer;
00920     
00921     LockMutex(&ServerListMutex);
00922     
00923     sniffer = ServerList;
00924     while (sniffer) {
00925         if (sniffer->port == tcpInfo->srcPort && sniffer->server == ipInfo->src)
00926             break;
00927         if (sniffer->port == tcpInfo->dstPort && sniffer->server == ipInfo->dst)
00928             break;
00929         sniffer = sniffer->next;
00930     }
00931     
00932     UnLockMutex(&ServerListMutex);
00933     
00934     return sniffer;
00935 }
00936 
00937 
00938 /* Hash the Session Info, return hash row */
00939 static word32 SessionHash(IpInfo* ipInfo, TcpInfo* tcpInfo)
00940 {
00941     word32 hash = ipInfo->src * ipInfo->dst;
00942     hash *= tcpInfo->srcPort * tcpInfo->dstPort;
00943     
00944     return hash % HASH_SIZE;
00945 }
00946 
00947 
00948 /* Get Exisiting SnifferSession from IP and Port */
00949 static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo)
00950 {
00951     SnifferSession* session;
00952     time_t          currTime = time(NULL); 
00953     word32          row = SessionHash(ipInfo, tcpInfo);
00954 
00955     assert(row <= HASH_SIZE);
00956     
00957     LockMutex(&SessionMutex);
00958     
00959     session = SessionTable[row];
00960     while (session) {
00961         if (session->server == ipInfo->src && session->client == ipInfo->dst &&
00962                     session->srvPort == tcpInfo->srcPort &&
00963                     session->cliPort == tcpInfo->dstPort)
00964             break;
00965         if (session->client == ipInfo->src && session->server == ipInfo->dst &&
00966                     session->cliPort == tcpInfo->srcPort &&
00967                     session->srvPort == tcpInfo->dstPort)
00968             break;
00969         
00970         session = session->next;
00971     }
00972 
00973     if (session)
00974         session->lastUsed= currTime; /* keep session alive, remove stale will */
00975                                      /* leave alone */   
00976     UnLockMutex(&SessionMutex);
00977     
00978     /* determine side */
00979     if (session) {
00980         if (ipInfo->dst == session->context->server &&
00981             tcpInfo->dstPort == session->context->port)
00982             session->flags.side = CYASSL_SERVER_END;
00983         else
00984             session->flags.side = CYASSL_CLIENT_END;
00985     }    
00986     
00987     return session;
00988 }
00989 
00990 
00991 #ifdef HAVE_SNI
00992 
00993 static int LoadKeyFile(byte** keyBuf, word32* keyBufSz,
00994                 const char* keyFile, int typeKey,
00995                 const char* password)
00996 {
00997     byte* loadBuf;
00998     byte* saveBuf;
00999     long fileSz = 0;
01000     int saveBufSz;
01001     XFILE file;
01002     int ret;
01003 
01004     if (keyBuf == NULL || keyBufSz == NULL || keyFile == NULL) {
01005         return -1;
01006     }
01007 
01008     file = XFOPEN(keyFile, "rb");
01009     if (file == XBADFILE) return -1;
01010     XFSEEK(file, 0, XSEEK_END);
01011     fileSz = XFTELL(file);
01012     XREWIND(file);
01013 
01014     loadBuf = (byte*)malloc(fileSz);
01015     if (loadBuf == NULL) {
01016         XFCLOSE(file);
01017         return -1;
01018     }
01019 
01020     ret = (int)XFREAD(loadBuf, fileSz, 1, file);
01021     XFCLOSE(file);
01022 
01023     if (typeKey == SSL_FILETYPE_PEM) {
01024         saveBuf = (byte*)malloc(fileSz);
01025 
01026         saveBufSz = CyaSSL_KeyPemToDer(loadBuf, (int)fileSz,
01027                                                 saveBuf, (int)fileSz, password);
01028         free(loadBuf);
01029 
01030         *keyBuf = saveBuf;
01031         *keyBufSz = (word32)saveBufSz;
01032     }
01033     else {
01034         *keyBuf = loadBuf;
01035         *keyBufSz = (word32)fileSz;
01036     }
01037 
01038 
01039     if (ret < 0) {
01040         return -1;
01041     }
01042 
01043     return ret;
01044 }
01045 
01046 #endif
01047 
01048 
01049 static int SetNamedPrivateKey(const char* name, const char* address, int port,
01050             const char* keyFile, int typeKey, const char* password, char* error)
01051 {
01052     SnifferServer* sniffer;
01053     int            ret;
01054     int            type = (typeKey == FILETYPE_PEM) ? SSL_FILETYPE_PEM :
01055                                                       SSL_FILETYPE_ASN1;
01056     int            isNew = 0;
01057     word32         serverIp;
01058 
01059 #ifdef HAVE_SNI
01060     NamedKey* namedKey = NULL;
01061 #endif
01062 
01063     (void)name;
01064 #ifdef HAVE_SNI
01065     if (name != NULL) {
01066         namedKey = (NamedKey*)malloc(sizeof(NamedKey));
01067         if (namedKey == NULL) {
01068             SetError(MEMORY_STR, error, NULL, 0);
01069             return -1;
01070         }
01071         XMEMSET(namedKey, 0, sizeof(NamedKey));
01072 
01073         namedKey->nameSz = (word32)strnlen(name, sizeof(namedKey->name));
01074         strncpy(namedKey->name, name, sizeof(namedKey->name));
01075 
01076         ret = LoadKeyFile(&namedKey->key, &namedKey->keySz,
01077                           keyFile, type, password);
01078         if (ret < 0) {
01079             SetError(KEY_FILE_STR, error, NULL, 0);
01080             FreeNamedKey(namedKey);
01081             return -1;
01082         }
01083     }
01084 #endif
01085 
01086     serverIp = inet_addr(address);
01087     sniffer = ServerList;
01088     while (sniffer != NULL &&
01089            (sniffer->server != serverIp || sniffer->port != port)) {
01090         sniffer = sniffer->next;
01091     }
01092 
01093     if (sniffer == NULL) {
01094         isNew = 1;
01095         sniffer = (SnifferServer*)malloc(sizeof(SnifferServer));
01096         if (sniffer == NULL) {
01097             SetError(MEMORY_STR, error, NULL, 0);
01098 #ifdef HAVE_SNI
01099             FreeNamedKey(namedKey);
01100 #endif
01101             return -1;
01102         }
01103         InitSnifferServer(sniffer);
01104 
01105         XSTRNCPY(sniffer->address, address, MAX_SERVER_ADDRESS-1);
01106         sniffer->address[MAX_SERVER_ADDRESS-1] = '\0';
01107         sniffer->server = serverIp;
01108         sniffer->port = port;
01109 
01110         sniffer->ctx = SSL_CTX_new(SSLv3_client_method());
01111         if (!sniffer->ctx) {
01112             SetError(MEMORY_STR, error, NULL, 0);
01113 #ifdef HAVE_SNI
01114             FreeNamedKey(namedKey);
01115 #endif
01116             FreeSnifferServer(sniffer);
01117             return -1;
01118         }
01119     }
01120 
01121     if (name == NULL) {
01122         if (password) {
01123             SSL_CTX_set_default_passwd_cb(sniffer->ctx, SetPassword);
01124             SSL_CTX_set_default_passwd_cb_userdata(
01125                                                  sniffer->ctx, (void*)password);
01126         }
01127         ret = SSL_CTX_use_PrivateKey_file(sniffer->ctx, keyFile, type);
01128         if (ret != SSL_SUCCESS) {
01129             SetError(KEY_FILE_STR, error, NULL, 0);
01130             if (isNew)
01131                 FreeSnifferServer(sniffer);
01132             return -1;
01133         }
01134     }
01135 #ifdef HAVE_SNI
01136     else {
01137         LockMutex(&sniffer->namedKeysMutex);
01138         namedKey->next = sniffer->namedKeys;
01139         sniffer->namedKeys = namedKey;
01140         UnLockMutex(&sniffer->namedKeysMutex);
01141     }
01142 #endif
01143 
01144     if (isNew) {
01145         sniffer->next = ServerList;
01146         ServerList = sniffer;
01147     }
01148 
01149     return 0;
01150 }
01151 
01152 
01153 #ifdef HAVE_SNI
01154 
01155 /* Sets the private key for a specific name, server and port  */
01156 /* returns 0 on success, -1 on error */
01157 int ssl_SetNamedPrivateKey(const char* name,
01158                            const char* address, int port,
01159                            const char* keyFile, int typeKey,
01160                            const char* password, char* error)
01161 {
01162     int ret;
01163 
01164     TraceHeader();
01165     TraceSetNamedServer(name, address, port, keyFile);
01166 
01167     LockMutex(&ServerListMutex);
01168     ret = SetNamedPrivateKey(name, address, port, keyFile,
01169                              typeKey, password, error);
01170     UnLockMutex(&ServerListMutex);
01171 
01172     if (ret == 0)
01173         Trace(NEW_SERVER_STR);
01174 
01175     return ret;
01176 }
01177 
01178 #endif
01179 
01180 
01181 /* Sets the private key for a specific server and port  */
01182 /* returns 0 on success, -1 on error */
01183 int ssl_SetPrivateKey(const char* address, int port, const char* keyFile,
01184                       int typeKey, const char* password, char* error)
01185 {
01186     int ret;
01187 
01188     TraceHeader();
01189     TraceSetServer(address, port, keyFile);
01190 
01191     LockMutex(&ServerListMutex);
01192     ret = SetNamedPrivateKey(NULL, address, port, keyFile,
01193                              typeKey, password, error);
01194     UnLockMutex(&ServerListMutex);
01195 
01196     if (ret == 0)
01197         Trace(NEW_SERVER_STR);
01198 
01199     return ret;
01200 }
01201 
01202 
01203 /* Check IP Header for IPV4, TCP, and a registered server address */
01204 /* returns 0 on success, -1 on error */
01205 static int CheckIpHdr(IpHdr* iphdr, IpInfo* info, int length, char* error)
01206 {
01207     int    version = IP_V(iphdr);
01208 
01209     TraceIP(iphdr);
01210     Trace(IP_CHECK_STR);
01211 
01212     if (version != IPV4) {
01213         SetError(BAD_IPVER_STR, error, NULL, 0); 
01214         return -1;
01215     }
01216 
01217     if (iphdr->protocol != TCP_PROTOCOL) { 
01218         SetError(BAD_PROTO_STR, error, NULL, 0);
01219         return -1;
01220     }
01221 
01222     if (!IsServerRegistered(iphdr->src) && !IsServerRegistered(iphdr->dst)) {
01223         SetError(SERVER_NOT_REG_STR, error, NULL, 0);
01224         return -1;
01225     }
01226 
01227     info->length  = IP_HL(iphdr);
01228     info->total   = ntohs(iphdr->length);
01229     info->src     = iphdr->src;
01230     info->dst     = iphdr->dst;
01231 
01232     if (info->total == 0)
01233         info->total = length;  /* reassembled may be off */
01234 
01235     return 0;
01236 }
01237 
01238 
01239 /* Check TCP Header for a registered port */
01240 /* returns 0 on success, -1 on error */
01241 static int CheckTcpHdr(TcpHdr* tcphdr, TcpInfo* info, char* error)
01242 {
01243     TraceTcp(tcphdr);
01244     Trace(TCP_CHECK_STR);
01245     info->srcPort   = ntohs(tcphdr->srcPort);
01246     info->dstPort   = ntohs(tcphdr->dstPort);
01247     info->length    = TCP_LEN(tcphdr);
01248     info->sequence  = ntohl(tcphdr->sequence);
01249     info->fin       = tcphdr->flags & TCP_FIN;
01250     info->rst       = tcphdr->flags & TCP_RST;
01251     info->syn       = tcphdr->flags & TCP_SYN;
01252     info->ack       = tcphdr->flags & TCP_ACK;
01253     if (info->ack)
01254         info->ackNumber = ntohl(tcphdr->ack); 
01255 
01256     if (!IsPortRegistered(info->srcPort) && !IsPortRegistered(info->dstPort)) {
01257         SetError(SERVER_PORT_NOT_REG_STR, error, NULL, 0);
01258         return -1;
01259     }
01260 
01261     return 0;
01262 }
01263 
01264 
01265 /* Decode Record Layer Header */
01266 static int GetRecordHeader(const byte* input, RecordLayerHeader* rh, int* size)
01267 {
01268     XMEMCPY(rh, input, RECORD_HEADER_SZ);
01269     *size = (rh->length[0] << 8) | rh->length[1];
01270 
01271     if (*size > (MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA))
01272         return LENGTH_ERROR;
01273 
01274     return 0;
01275 }
01276 
01277 
01278 /* Process Client Key Exchange, RSA only */
01279 static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
01280                                     SnifferSession* session, char* error)
01281 {
01282     word32 idx = 0;
01283     RsaKey key;
01284     int    ret;
01285 
01286     ret = InitRsaKey(&key, 0);
01287     if (ret == 0) 
01288         ret = RsaPrivateKeyDecode(session->sslServer->buffers.key.buffer,
01289                           &idx, &key, session->sslServer->buffers.key.length);
01290     if (ret == 0) {
01291         int length = RsaEncryptSize(&key);
01292         
01293         if (IsTLS(session->sslServer)) 
01294             input += 2;     /* tls pre length */
01295        
01296         if (length > *sslBytes) { 
01297             SetError(PARTIAL_INPUT_STR, error, session, FATAL_ERROR_STATE);
01298             FreeRsaKey(&key);
01299             return -1;
01300         }
01301         ret = RsaPrivateDecrypt(input, length, 
01302                   session->sslServer->arrays->preMasterSecret,SECRET_LEN, &key);
01303         
01304         if (ret != SECRET_LEN) {
01305             SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE);
01306             FreeRsaKey(&key);
01307             return -1;
01308         }
01309         ret = 0;  /* not in error state */
01310         session->sslServer->arrays->preMasterSz = SECRET_LEN;
01311         
01312         /* store for client side as well */
01313         XMEMCPY(session->sslClient->arrays->preMasterSecret,
01314                session->sslServer->arrays->preMasterSecret, SECRET_LEN);
01315         session->sslClient->arrays->preMasterSz = SECRET_LEN;
01316         
01317         #ifdef SHOW_SECRETS
01318         {
01319             int i;
01320             printf("pre master secret: ");
01321             for (i = 0; i < SECRET_LEN; i++)
01322                 printf("%02x", session->sslServer->arrays->preMasterSecret[i]);
01323             printf("\n");
01324         }
01325         #endif
01326     }
01327     else {
01328         SetError(RSA_DECODE_STR, error, session, FATAL_ERROR_STATE);
01329         FreeRsaKey(&key);
01330         return -1;
01331     }
01332     
01333     if (SetCipherSpecs(session->sslServer) != 0) {
01334         SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
01335         FreeRsaKey(&key);
01336         return -1;
01337     }
01338    
01339     if (SetCipherSpecs(session->sslClient) != 0) {
01340         SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
01341         FreeRsaKey(&key);
01342         return -1;
01343     }
01344 
01345     ret  = MakeMasterSecret(session->sslServer);
01346     ret += MakeMasterSecret(session->sslClient);
01347     ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE);
01348     ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE);
01349 
01350     if (ret != 0) {
01351         SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE);
01352         return -1;
01353     }
01354 
01355 #ifdef SHOW_SECRETS
01356     {
01357         int i;
01358         printf("server master secret: ");
01359         for (i = 0; i < SECRET_LEN; i++)
01360             printf("%02x", session->sslServer->arrays->masterSecret[i]);
01361         printf("\n");
01362         
01363         printf("client master secret: ");
01364         for (i = 0; i < SECRET_LEN; i++)
01365             printf("%02x", session->sslClient->arrays->masterSecret[i]);
01366         printf("\n");
01367 
01368         printf("server suite = %d\n", session->sslServer->options.cipherSuite);
01369         printf("client suite = %d\n", session->sslClient->options.cipherSuite);
01370     }
01371 #endif   
01372     
01373     FreeRsaKey(&key);
01374     return ret;
01375 }
01376 
01377 
01378 /* Process Session Ticket */
01379 static int ProcessSessionTicket(const byte* input, int* sslBytes,
01380                                 SnifferSession* session, char* error)
01381 {
01382     word16 len;
01383 
01384     /* make sure can read through hint and len */
01385     if (TICKET_HINT_LEN + LENGTH_SZ > *sslBytes) {
01386         SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
01387         return -1;
01388     }
01389     
01390     input     += TICKET_HINT_LEN;  /* skip over hint */
01391     *sslBytes -= TICKET_HINT_LEN;
01392 
01393     len = (word16)((input[0] << 8) | input[1]);
01394     input     += LENGTH_SZ;
01395     *sslBytes -= LENGTH_SZ;
01396 
01397     /* make sure can read through ticket */
01398     if (len > *sslBytes || len < ID_LEN) {
01399         SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
01400         return -1;
01401     }
01402 
01403     /* store session with macID as sessionID */
01404     session->sslServer->options.haveSessionId = 1;
01405     XMEMCPY(session->sslServer->arrays->sessionID, input + len - ID_LEN,ID_LEN);
01406     
01407     return 0;
01408 }
01409 
01410 
01411 /* Process Server Hello */
01412 static int ProcessServerHello(const byte* input, int* sslBytes,
01413                               SnifferSession* session, char* error)
01414 {
01415     ProtocolVersion pv;
01416     byte            b;
01417     int             toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
01418     int             doResume     = 0;
01419     
01420     /* make sure we didn't miss ClientHello */
01421     if (session->flags.clientHello == 0) {
01422         SetError(MISSED_CLIENT_HELLO_STR, error, session, FATAL_ERROR_STATE);
01423         return -1;
01424     }
01425 
01426     /* make sure can read through session len */
01427     if (toRead > *sslBytes) {
01428         SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
01429         return -1;
01430     }
01431     
01432     XMEMCPY(&pv, input, VERSION_SZ);
01433     input     += VERSION_SZ;
01434     *sslBytes -= VERSION_SZ;
01435            
01436     session->sslServer->version = pv;
01437     session->sslClient->version = pv;
01438            
01439     XMEMCPY(session->sslServer->arrays->serverRandom, input, RAN_LEN);
01440     XMEMCPY(session->sslClient->arrays->serverRandom, input, RAN_LEN);
01441     input    += RAN_LEN;
01442     *sslBytes -= RAN_LEN;
01443     
01444     b = *input++;
01445     *sslBytes -= 1;
01446     
01447     /* make sure can read through compression */
01448     if ( (b + SUITE_LEN + ENUM_LEN) > *sslBytes) {
01449         SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
01450         return -1;
01451     }
01452     if (b) {
01453         XMEMCPY(session->sslServer->arrays->sessionID, input, ID_LEN);
01454         session->sslServer->options.haveSessionId = 1;
01455     }
01456     input     += b;
01457     *sslBytes -= b;
01458    
01459     /* cipher suite */ 
01460     b = *input++;  /* first byte, ECC or not */
01461     session->sslServer->options.cipherSuite0 = b;
01462     session->sslClient->options.cipherSuite0 = b;
01463     b = *input++;
01464     session->sslServer->options.cipherSuite = b;
01465     session->sslClient->options.cipherSuite = b;
01466     *sslBytes -= SUITE_LEN;
01467 
01468     /* compression */
01469     b = *input++;
01470     *sslBytes -= ENUM_LEN;
01471 
01472     if (b) {
01473         SetError(BAD_COMPRESSION_STR, error, session, FATAL_ERROR_STATE);
01474         return -1;
01475     }
01476    
01477     if (session->sslServer->options.haveSessionId &&
01478             XMEMCMP(session->sslServer->arrays->sessionID,
01479                     session->sslClient->arrays->sessionID, ID_LEN) == 0)
01480         doResume = 1;
01481     else if (session->sslClient->options.haveSessionId == 0 &&
01482              session->sslServer->options.haveSessionId == 0 &&
01483              session->ticketID)
01484         doResume = 1;
01485 
01486     if (session->ticketID && doResume) {
01487         /* use ticketID to retrieve from session, prefer over sessionID */
01488         XMEMCPY(session->sslServer->arrays->sessionID,session->ticketID,ID_LEN);
01489         session->sslServer->options.haveSessionId = 1;  /* may not have
01490                                                            actual sessionID */
01491     }
01492 
01493     if (doResume ) {
01494         int ret = 0;
01495         SSL_SESSION* resume = GetSession(session->sslServer,
01496                                       session->sslServer->arrays->masterSecret);
01497         if (resume == NULL) {
01498             SetError(BAD_SESSION_RESUME_STR, error, session, FATAL_ERROR_STATE);
01499             return -1;
01500         }
01501         /* make sure client has master secret too */
01502         XMEMCPY(session->sslClient->arrays->masterSecret,
01503                session->sslServer->arrays->masterSecret, SECRET_LEN);
01504         session->flags.resuming = 1;
01505         
01506         Trace(SERVER_DID_RESUMPTION_STR);
01507         if (SetCipherSpecs(session->sslServer) != 0) {
01508             SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
01509             return -1;
01510         }
01511         
01512         if (SetCipherSpecs(session->sslClient) != 0) {
01513             SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
01514             return -1;
01515         }
01516         
01517         if (session->sslServer->options.tls) {
01518             ret =  DeriveTlsKeys(session->sslServer);
01519             ret += DeriveTlsKeys(session->sslClient);
01520         }
01521         else {
01522             ret =  DeriveKeys(session->sslServer);
01523             ret += DeriveKeys(session->sslClient);
01524         }
01525         ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE);
01526         ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE);
01527 
01528         if (ret != 0) {
01529             SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE);
01530             return -1;
01531         }
01532     }
01533 #ifdef SHOW_SECRETS
01534     {
01535         int i;
01536         printf("cipher suite = 0x%02x\n",
01537                session->sslServer->options.cipherSuite);
01538         printf("server random: ");
01539         for (i = 0; i < RAN_LEN; i++)
01540             printf("%02x", session->sslServer->arrays->serverRandom[i]);
01541         printf("\n");
01542     }
01543 #endif   
01544     return 0;
01545 }
01546 
01547 
01548 /* Process normal Client Hello */
01549 static int ProcessClientHello(const byte* input, int* sslBytes, 
01550                               SnifferSession* session, char* error)
01551 {
01552     byte   bLen;
01553     word16 len;
01554     int    toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
01555     
01556 #ifdef HAVE_SNI
01557     {
01558         byte name[MAX_SERVER_NAME];
01559         word32 nameSz = sizeof(name);
01560         int ret;
01561 
01562         ret = CyaSSL_SNI_GetFromBuffer(
01563                              input - HANDSHAKE_HEADER_SZ - RECORD_HEADER_SZ,
01564                              *sslBytes + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ,
01565                              CYASSL_SNI_HOST_NAME, name, &nameSz);
01566 
01567         if (ret == SSL_SUCCESS) {
01568             NamedKey* namedKey;
01569 
01570             name[nameSz] = 0;
01571             LockMutex(&session->context->namedKeysMutex);
01572             namedKey = session->context->namedKeys;
01573             while (namedKey != NULL) {
01574                 if (nameSz == namedKey->nameSz &&
01575                            XSTRNCMP((char*)name, namedKey->name, nameSz) == 0) {
01576                     if (CyaSSL_use_PrivateKey_buffer(session->sslServer,
01577                                             namedKey->key, namedKey->keySz,
01578                                             SSL_FILETYPE_ASN1) != SSL_SUCCESS) {
01579                         UnLockMutex(&session->context->namedKeysMutex);
01580                         SetError(CLIENT_HELLO_LATE_KEY_STR, error, session,
01581                                                              FATAL_ERROR_STATE);
01582                         return -1;
01583                     }
01584                     break;
01585                 }
01586                 else
01587                     namedKey = namedKey->next;
01588             }
01589             UnLockMutex(&session->context->namedKeysMutex);
01590         }
01591     }
01592 #endif
01593 
01594     session->flags.clientHello = 1;  /* don't process again */
01595     
01596     /* make sure can read up to session len */
01597     if (toRead > *sslBytes) {
01598         SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
01599         return -1;
01600     }
01601     
01602     /* skip, get negotiated one from server hello */
01603     input     += VERSION_SZ;
01604     *sslBytes -= VERSION_SZ;
01605     
01606     XMEMCPY(session->sslServer->arrays->clientRandom, input, RAN_LEN);
01607     XMEMCPY(session->sslClient->arrays->clientRandom, input, RAN_LEN);
01608     
01609     input     += RAN_LEN;
01610     *sslBytes -= RAN_LEN;
01611     
01612     /* store session in case trying to resume */
01613     bLen = *input++;
01614     *sslBytes -= ENUM_LEN;
01615     if (bLen) {
01616         if (ID_LEN > *sslBytes) {
01617             SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
01618             return -1;
01619         }
01620         Trace(CLIENT_RESUME_TRY_STR);
01621         XMEMCPY(session->sslClient->arrays->sessionID, input, ID_LEN);
01622         session->sslClient->options.haveSessionId = 1;
01623     }
01624 #ifdef SHOW_SECRETS
01625     {
01626         int i;
01627         printf("client random: ");
01628         for (i = 0; i < RAN_LEN; i++)
01629             printf("%02x", session->sslServer->arrays->clientRandom[i]);
01630         printf("\n");
01631     }
01632 #endif
01633 
01634     input     += bLen;
01635     *sslBytes -= bLen;
01636 
01637     /* skip cipher suites */
01638     /* make sure can read len */
01639     if (SUITE_LEN > *sslBytes) {
01640         SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
01641         return -1;
01642     }
01643     len = (word16)((input[0] << 8) | input[1]);
01644     input     += SUITE_LEN;
01645     *sslBytes -= SUITE_LEN;
01646     /* make sure can read suites + comp len */
01647     if (len + ENUM_LEN > *sslBytes) {
01648         SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
01649         return -1;
01650     }
01651     input     += len;
01652     *sslBytes -= len;
01653 
01654     /* skip compression */
01655     bLen       = *input++;
01656     *sslBytes -= ENUM_LEN;
01657     /* make sure can read len */
01658     if (bLen > *sslBytes) {
01659         SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
01660         return -1;
01661     }
01662     input     += bLen;
01663     *sslBytes -= bLen;
01664   
01665     if (*sslBytes == 0) {
01666         /* no extensions */
01667         return 0;
01668     }
01669     
01670     /* skip extensions until session ticket */
01671     /* make sure can read len */
01672     if (SUITE_LEN > *sslBytes) {
01673         SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
01674         return -1;
01675     }
01676     len = (word16)((input[0] << 8) | input[1]);
01677     input     += SUITE_LEN;
01678     *sslBytes -= SUITE_LEN;
01679     /* make sure can read through all extensions */
01680     if (len > *sslBytes) {
01681         SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
01682         return -1;
01683     }
01684 
01685     while (len > EXT_TYPE_SZ + LENGTH_SZ) {
01686         byte   extType[EXT_TYPE_SZ];
01687         word16 extLen;
01688 
01689         extType[0] = input[0];
01690         extType[1] = input[1];
01691         input     += EXT_TYPE_SZ;
01692         *sslBytes -= EXT_TYPE_SZ;
01693 
01694         extLen = (word16)((input[0] << 8) | input[1]);
01695         input     += LENGTH_SZ;
01696         *sslBytes -= LENGTH_SZ;
01697 
01698         /* make sure can read through individual extension */
01699         if (extLen > *sslBytes) {
01700             SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
01701             return -1;
01702         }
01703 
01704         if (extType[0] == 0x00 && extType[1] == TICKET_EXT_ID) {
01705 
01706             /* make sure can read through ticket if there is a non blank one */
01707             if (extLen && extLen < ID_LEN) {
01708                 SetError(CLIENT_HELLO_INPUT_STR, error, session,
01709                          FATAL_ERROR_STATE);
01710                 return -1;
01711             }
01712 
01713             if (extLen) {
01714                 if (session->ticketID == 0) {
01715                     session->ticketID = (byte*)malloc(ID_LEN);
01716                     if (session->ticketID == 0) {
01717                         SetError(MEMORY_STR, error, session,
01718                                  FATAL_ERROR_STATE);
01719                         return -1;
01720                     }
01721                 }
01722                 XMEMCPY(session->ticketID, input + extLen - ID_LEN, ID_LEN);
01723             }
01724         }
01725 
01726         input     += extLen;
01727         *sslBytes -= extLen;
01728         len       -= extLen + EXT_TYPE_SZ + LENGTH_SZ;
01729     }
01730 
01731     return 0;
01732 }
01733 
01734 
01735 /* Process Finished */
01736 static int ProcessFinished(const byte* input, int size, int* sslBytes,
01737                            SnifferSession* session, char* error)
01738 {
01739     SSL*   ssl;
01740     word32 inOutIdx = 0;
01741     int    ret;
01742                 
01743     if (session->flags.side == CYASSL_SERVER_END)
01744         ssl = session->sslServer;
01745     else
01746         ssl = session->sslClient;
01747 
01748     ret = DoFinished(ssl, input, &inOutIdx, (word32) size, (word32) *sslBytes,
01749                                                                          SNIFF);
01750     *sslBytes -= (int)inOutIdx;
01751 
01752     if (ret < 0) {
01753         SetError(BAD_FINISHED_MSG, error, session, FATAL_ERROR_STATE);
01754         return ret;
01755     }
01756                 
01757     if (ret == 0 && session->flags.cached == 0) {
01758         if (session->sslServer->options.haveSessionId) {
01759             CYASSL_SESSION* sess = GetSession(session->sslServer, NULL);
01760             if (sess == NULL)
01761                 AddSession(session->sslServer);  /* don't re add */
01762             session->flags.cached = 1;
01763          }
01764     }
01765 
01766     FreeHandshakeResources(ssl);
01767 
01768     return ret;
01769 }
01770 
01771 
01772 /* Process HandShake input */
01773 static int DoHandShake(const byte* input, int* sslBytes,
01774                        SnifferSession* session, char* error)
01775 {
01776     byte type;
01777     int  size;
01778     int  ret = 0;
01779     int  startBytes;
01780 
01781     if (*sslBytes < HANDSHAKE_HEADER_SZ) {
01782         SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE);
01783         return -1;
01784     }
01785     type = input[0];
01786     size = (input[1] << 16) | (input[2] << 8) | input[3];
01787     
01788     input     += HANDSHAKE_HEADER_SZ;
01789     *sslBytes -= HANDSHAKE_HEADER_SZ;
01790     startBytes = *sslBytes;
01791 
01792     if (*sslBytes < size) {
01793         SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE);
01794         return -1;
01795     }
01796     
01797     switch (type) {
01798         case hello_verify_request:
01799             Trace(GOT_HELLO_VERIFY_STR);
01800             break;
01801         case hello_request:
01802             Trace(GOT_HELLO_REQUEST_STR);
01803             break;
01804         case session_ticket:
01805             Trace(GOT_SESSION_TICKET_STR);
01806             ret = ProcessSessionTicket(input, sslBytes, session, error);
01807             break;
01808         case server_hello:
01809             Trace(GOT_SERVER_HELLO_STR);
01810             ret = ProcessServerHello(input, sslBytes, session, error);
01811             break;
01812         case certificate_request:
01813             Trace(GOT_CERT_REQ_STR);
01814             break;
01815         case server_key_exchange:
01816             Trace(GOT_SERVER_KEY_EX_STR);
01817             /* can't know temp key passively */
01818             SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
01819             ret = -1;
01820             break;
01821         case certificate:
01822             Trace(GOT_CERT_STR);
01823             break;
01824         case server_hello_done:
01825             Trace(GOT_SERVER_HELLO_DONE_STR);
01826             break;
01827         case finished:
01828             Trace(GOT_FINISHED_STR);
01829             ret = ProcessFinished(input, size, sslBytes, session, error);
01830             break;
01831         case client_hello:
01832             Trace(GOT_CLIENT_HELLO_STR);
01833             ret = ProcessClientHello(input, sslBytes, session, error);
01834             break;
01835         case client_key_exchange:
01836             Trace(GOT_CLIENT_KEY_EX_STR);
01837             ret = ProcessClientKeyExchange(input, sslBytes, session, error);
01838             break;
01839         case certificate_verify:
01840             Trace(GOT_CERT_VER_STR);
01841             break;
01842         default:
01843             SetError(GOT_UNKNOWN_HANDSHAKE_STR, error, session, 0);
01844             return -1;
01845     }
01846 
01847     *sslBytes = startBytes - size;  /* actual bytes of full process */
01848 
01849     return ret;
01850 }
01851 
01852 
01853 /* Decrypt input into plain output, 0 on success */
01854 static int Decrypt(SSL* ssl, byte* output, const byte* input, word32 sz)
01855 {
01856     int ret = 0;
01857 
01858     switch (ssl->specs.bulk_cipher_algorithm) {
01859         #ifdef BUILD_ARC4
01860         case cyassl_rc4:
01861             Arc4Process(ssl->decrypt.arc4, output, input, sz);
01862             break;
01863         #endif
01864             
01865         #ifdef BUILD_DES3
01866         case cyassl_triple_des:
01867             ret = Des3_CbcDecrypt(ssl->decrypt.des3, output, input, sz);
01868             break;
01869         #endif
01870             
01871         #ifdef BUILD_AES
01872         case cyassl_aes:
01873             ret = AesCbcDecrypt(ssl->decrypt.aes, output, input, sz);
01874             break;
01875         #endif
01876             
01877         #ifdef HAVE_HC128
01878         case cyassl_hc128:
01879             Hc128_Process(ssl->decrypt.hc128, output, input, sz);
01880             break;
01881         #endif
01882             
01883         #ifdef BUILD_RABBIT
01884         case cyassl_rabbit:
01885             RabbitProcess(ssl->decrypt.rabbit, output, input, sz);
01886             break;
01887         #endif
01888 
01889         #ifdef HAVE_CAMELLIA 
01890         case cyassl_camellia:
01891             CamelliaCbcDecrypt(ssl->decrypt.cam, output, input, sz);
01892             break;
01893         #endif
01894 
01895         default:
01896             Trace(BAD_DECRYPT_TYPE);
01897             ret = -1;
01898             break;
01899     }
01900 
01901     return ret;
01902 }
01903 
01904 
01905 /* Decrypt input message into output, adjust output steam if needed */
01906 static const byte* DecryptMessage(SSL* ssl, const byte* input, word32 sz,
01907                                   byte* output, int* error, int* advance)
01908 {
01909     int ivExtra = 0;
01910 
01911     int ret = Decrypt(ssl, output, input, sz);
01912     if (ret != 0) {
01913         *error = ret;
01914         return NULL;
01915     }
01916     ssl->keys.encryptSz = sz;
01917     if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) {
01918         output += ssl->specs.block_size;     /* go past TLSv1.1 IV */
01919         ivExtra = ssl->specs.block_size;
01920         *advance = ssl->specs.block_size;
01921     }
01922 
01923     ssl->keys.padSz = ssl->specs.hash_size;
01924 
01925     if (ssl->specs.cipher_type == block)
01926         ssl->keys.padSz += *(output + sz - ivExtra - 1) + 1;
01927     
01928     return output;
01929 }
01930 
01931 
01932 /* remove session from table, use rowHint if no info (means we have a lock) */
01933 static void RemoveSession(SnifferSession* session, IpInfo* ipInfo,
01934                         TcpInfo* tcpInfo, word32 rowHint)
01935 {
01936     SnifferSession* previous = 0;
01937     SnifferSession* current;
01938     word32          row = rowHint;
01939     int             haveLock = 0;
01940    
01941     if (ipInfo && tcpInfo)
01942         row = SessionHash(ipInfo, tcpInfo);
01943     else
01944         haveLock = 1;
01945     
01946     assert(row <= HASH_SIZE);
01947     Trace(REMOVE_SESSION_STR);
01948     
01949     if (!haveLock)
01950         LockMutex(&SessionMutex);
01951     
01952     current = SessionTable[row];
01953     
01954     while (current) {
01955         if (current == session) {
01956             if (previous)
01957                 previous->next = current->next;
01958             else
01959                 SessionTable[row] = current->next;
01960             FreeSnifferSession(session);
01961             TraceRemovedSession();
01962             break;
01963         }
01964         previous = current;
01965         current  = current->next;
01966     }
01967     
01968     if (!haveLock)
01969         UnLockMutex(&SessionMutex);
01970 }
01971 
01972 
01973 /* Remove stale sessions from the Session Table, have a lock */
01974 static void RemoveStaleSessions(void)
01975 {
01976     word32 i;
01977     SnifferSession* session;
01978     
01979     for (i = 0; i < HASH_SIZE; i++) {
01980         session = SessionTable[i];
01981         while (session) {
01982             SnifferSession* next = session->next; 
01983             if (time(NULL) >= session->lastUsed + CYASSL_SNIFFER_TIMEOUT) {
01984                 TraceStaleSession();
01985                 RemoveSession(session, NULL, NULL, i);
01986             }
01987             session = next;
01988         }
01989     }
01990 }
01991 
01992 
01993 /* Create a new Sniffer Session */
01994 static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
01995                                      char* error)
01996 {
01997     SnifferSession* session = 0;
01998     int row;
01999         
02000     Trace(NEW_SESSION_STR);
02001     /* create a new one */
02002     session = (SnifferSession*)malloc(sizeof(SnifferSession));
02003     if (session == NULL) {
02004         SetError(MEMORY_STR, error, NULL, 0);
02005         return 0;
02006     }
02007     InitSession(session);
02008     session->server  = ipInfo->dst;
02009     session->client  = ipInfo->src;
02010     session->srvPort = (word16)tcpInfo->dstPort;
02011     session->cliPort = (word16)tcpInfo->srcPort;
02012     session->cliSeqStart = tcpInfo->sequence;
02013     session->cliExpected = 1;  /* relative */
02014     session->lastUsed= time(NULL);
02015                 
02016     session->context = GetSnifferServer(ipInfo, tcpInfo);
02017     if (session->context == NULL) {
02018         SetError(SERVER_NOT_REG_STR, error, NULL, 0);
02019         free(session);
02020         return 0;
02021     }
02022         
02023     session->sslServer = SSL_new(session->context->ctx);
02024     if (session->sslServer == NULL) {
02025         SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE);
02026         free(session);
02027         return 0;
02028     }
02029     session->sslClient = SSL_new(session->context->ctx);
02030     if (session->sslClient == NULL) {
02031         SSL_free(session->sslServer);
02032         session->sslServer = 0;
02033 
02034         SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE);
02035         free(session);
02036         return 0;
02037     }
02038     /* put server back into server mode */
02039     session->sslServer->options.side = CYASSL_SERVER_END;
02040         
02041     row = SessionHash(ipInfo, tcpInfo);
02042     
02043     /* add it to the session table */
02044     LockMutex(&SessionMutex);
02045         
02046     session->next = SessionTable[row];
02047     SessionTable[row] = session;
02048     
02049     SessionCount++;
02050     
02051     if ( (SessionCount % HASH_SIZE) == 0) {
02052         TraceFindingStale();
02053         RemoveStaleSessions();
02054     }
02055         
02056     UnLockMutex(&SessionMutex);
02057         
02058     /* determine headed side */
02059     if (ipInfo->dst == session->context->server &&
02060         tcpInfo->dstPort == session->context->port)
02061         session->flags.side = CYASSL_SERVER_END;
02062     else
02063         session->flags.side = CYASSL_CLIENT_END;        
02064     
02065     return session;
02066 }
02067 
02068 
02069 #ifdef OLD_HELLO_ALLOWED
02070 
02071 /* Process Old Client Hello Input */
02072 static int DoOldHello(SnifferSession* session, const byte* sslFrame,
02073                       int* rhSize, int* sslBytes, char* error)
02074 {
02075     const byte* input = sslFrame;
02076     byte        b0, b1;
02077     word32      idx = 0;
02078     int         ret;
02079 
02080     Trace(GOT_OLD_CLIENT_HELLO_STR);
02081     session->flags.clientHello = 1;    /* don't process again */
02082     b0 = *input++;
02083     b1 = *input++;
02084     *sslBytes -= 2;
02085     *rhSize = ((b0 & 0x7f) << 8) | b1;
02086 
02087     if (*rhSize > *sslBytes) {
02088         SetError(OLD_CLIENT_INPUT_STR, error, session, FATAL_ERROR_STATE);
02089         return -1;
02090     }
02091 
02092     ret = ProcessOldClientHello(session->sslServer, input, &idx, *sslBytes,
02093                                 (word16)*rhSize);    
02094     if (ret < 0 && ret != MATCH_SUITE_ERROR) {
02095         SetError(BAD_OLD_CLIENT_STR, error, session, FATAL_ERROR_STATE);
02096         return -1;
02097     }
02098     
02099     Trace(OLD_CLIENT_OK_STR);
02100     XMEMCPY(session->sslClient->arrays->clientRandom,
02101            session->sslServer->arrays->clientRandom, RAN_LEN);
02102     
02103     *sslBytes -= *rhSize;
02104     return 0;
02105 }
02106 
02107 #endif /* OLD_HELLO_ALLOWED */
02108 
02109 
02110 #if 0
02111 /* Calculate the TCP checksum, see RFC 1071 */
02112 /* return 0 for success, -1 on error */
02113 /* can be called from decode() with
02114    TcpChecksum(&ipInfo, &tcpInfo, sslBytes, packet + ipInfo.length);
02115    could also add a 64bit version if type available and using this
02116 */
02117 int TcpChecksum(IpInfo* ipInfo, TcpInfo* tcpInfo, int dataLen,
02118                 const byte* packet)
02119 {
02120     TcpPseudoHdr  pseudo;
02121     int           count = PSEUDO_HDR_SZ;
02122     const word16* data = (word16*)&pseudo;
02123     word32        sum = 0;
02124     word16        checksum;
02125     
02126     pseudo.src = ipInfo->src;
02127     pseudo.dst = ipInfo->dst;
02128     pseudo.rsv = 0;
02129     pseudo.protocol = TCP_PROTO;
02130     pseudo.legnth = htons(tcpInfo->length + dataLen);
02131     
02132     /* pseudo header sum */
02133     while (count >= 2) {
02134         sum   += *data++;
02135         count -= 2;
02136     }
02137     
02138     count = tcpInfo->length + dataLen;
02139     data = (word16*)packet;
02140     
02141     /* main sum */
02142     while (count > 1) {
02143         sum   += *data++;
02144         count -=2;
02145     }
02146     
02147     /* get left-over, if any */
02148     packet = (byte*)data;
02149     if (count > 0) {
02150         sum += *packet;
02151     }
02152     
02153     /* fold 32bit sum into 16 bits */
02154     while (sum >> 16)
02155         sum = (sum & 0xffff) + (sum >> 16);
02156     
02157     checksum = (word16)~sum;
02158     /* checksum should now equal 0, since included already calcd checksum */
02159     /* field, but tcp checksum offloading could negate calculation */
02160     if (checksum == 0)
02161         return 0;
02162     return -1;
02163 }
02164 #endif
02165 
02166 
02167 /* Check IP and TCP headers, set payload */
02168 /* returns 0 on success, -1 on error */
02169 static int CheckHeaders(IpInfo* ipInfo, TcpInfo* tcpInfo, const byte* packet,
02170                   int length, const byte** sslFrame, int* sslBytes, char* error)
02171 {
02172     TraceHeader();
02173     TracePacket();
02174 
02175     /* ip header */
02176     if (length < IP_HDR_SZ) {
02177         SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
02178         return -1;
02179     }
02180     if (CheckIpHdr((IpHdr*)packet, ipInfo, length, error) != 0)
02181         return -1;
02182    
02183     /* tcp header */ 
02184     if (length < (ipInfo->length + TCP_HDR_SZ)) {
02185         SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
02186         return -1;
02187     }
02188     if (CheckTcpHdr((TcpHdr*)(packet + ipInfo->length), tcpInfo, error) != 0)
02189         return -1;
02190    
02191     /* setup */ 
02192     *sslFrame = packet + ipInfo->length + tcpInfo->length;
02193     if (*sslFrame > packet + length) {
02194         SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
02195         return -1;
02196     }
02197     *sslBytes = (int)(packet + length - *sslFrame);
02198     
02199     return 0;
02200 }
02201 
02202 
02203 /* Create or Find existing session */
02204 /* returns 0 on success (continue), -1 on error, 1 on success (end) */
02205 static int CheckSession(IpInfo* ipInfo, TcpInfo* tcpInfo, int sslBytes,
02206                         SnifferSession** session, char* error)
02207 {
02208     /* create a new SnifferSession on client SYN */
02209     if (tcpInfo->syn && !tcpInfo->ack) {
02210         TraceClientSyn(tcpInfo->sequence);
02211         *session = CreateSession(ipInfo, tcpInfo, error);
02212         if (*session == NULL) {
02213             *session = GetSnifferSession(ipInfo, tcpInfo);
02214             /* already had exisiting, so OK */
02215             if (*session)
02216                 return 1;
02217             
02218             SetError(MEMORY_STR, error, NULL, 0);
02219             return -1;
02220         }
02221         return 1;
02222     }
02223     /* get existing sniffer session */
02224     else {
02225         *session = GetSnifferSession(ipInfo, tcpInfo);
02226         if (*session == NULL) {
02227             /* don't worry about extraneous RST or duplicate FINs */
02228             if (tcpInfo->fin || tcpInfo->rst)
02229                 return 1;
02230             /* don't worry about duplicate ACKs either */
02231             if (sslBytes == 0 && tcpInfo->ack)
02232                 return 1;
02233             
02234             SetError(BAD_SESSION_STR, error, NULL, 0);
02235             return -1;
02236         }        
02237     }
02238     return 0;
02239 }
02240 
02241 
02242 /* Create a Packet Buffer from *begin - end, adjust new *begin and bytesLeft */
02243 static PacketBuffer* CreateBuffer(word32* begin, word32 end, const byte* data,
02244                                   int* bytesLeft)
02245 {
02246     PacketBuffer* pb;
02247     
02248     int added = end - *begin + 1;
02249     assert(*begin <= end);
02250     
02251     pb = (PacketBuffer*)malloc(sizeof(PacketBuffer));
02252     if (pb == NULL) return NULL;
02253     
02254     pb->next  = 0;
02255     pb->begin = *begin;
02256     pb->end   = end;
02257     pb->data = (byte*)malloc(added);
02258     
02259     if (pb->data == NULL) {
02260         free(pb);
02261         return NULL;
02262     }
02263     XMEMCPY(pb->data, data, added);
02264     
02265     *bytesLeft -= added;
02266     *begin      = pb->end + 1;
02267     
02268     return pb;
02269 }
02270 
02271 
02272 /* Add sslFrame to Reassembly List */
02273 /* returns 1 (end) on success, -1, on error */
02274 static int AddToReassembly(byte from, word32 seq, const byte* sslFrame,
02275                            int sslBytes, SnifferSession* session, char* error)
02276 {
02277     PacketBuffer*  add;
02278     PacketBuffer** front = (from == CYASSL_SERVER_END) ?
02279                        &session->cliReassemblyList: &session->srvReassemblyList;
02280     PacketBuffer*  curr = *front;
02281     PacketBuffer*  prev = curr;
02282     
02283     word32  startSeq = seq;
02284     word32  added;
02285     int     bytesLeft = sslBytes;  /* could be overlapping fragment */
02286 
02287     /* if list is empty add full frame to front */
02288     if (!curr) {
02289         add = CreateBuffer(&seq, seq + sslBytes - 1, sslFrame, &bytesLeft);
02290         if (add == NULL) {
02291             SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
02292             return -1;
02293         }
02294         *front = add;
02295         return 1;
02296     }
02297     
02298     /* add to front if before current front, up to next->begin */
02299     if (seq < curr->begin) {
02300         word32 end = seq + sslBytes - 1;
02301         
02302         if (end >= curr->begin)
02303             end = curr->begin - 1;
02304         
02305         add = CreateBuffer(&seq, end, sslFrame, &bytesLeft);
02306         if (add == NULL) {
02307             SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
02308             return -1;
02309         }
02310         add->next = curr;
02311         *front = add;
02312     }
02313     
02314     /* while we have bytes left, try to find a gap to fill */
02315     while (bytesLeft > 0) {
02316         /* get previous packet in list */
02317         while (curr && (seq >= curr->begin)) {
02318             prev = curr;
02319             curr = curr->next;
02320         }
02321         
02322         /* don't add  duplicate data */
02323         if (prev->end >= seq) {
02324             if ( (seq + bytesLeft - 1) <= prev->end)
02325                 return 1;
02326             seq = prev->end + 1;
02327             bytesLeft = startSeq + sslBytes - seq;
02328         }
02329         
02330         if (!curr)
02331             /* we're at the end */
02332             added = bytesLeft;
02333         else 
02334             /* we're in between two frames */
02335             added = min((word32)bytesLeft, curr->begin - seq);
02336         
02337         /* data already there */
02338         if (added == 0)
02339             continue;
02340         
02341         add = CreateBuffer(&seq, seq + added - 1, &sslFrame[seq - startSeq],
02342                            &bytesLeft);
02343         if (add == NULL) {
02344             SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
02345             return -1;
02346         }
02347         add->next  = prev->next;
02348         prev->next = add;
02349     }
02350     return 1;
02351 }
02352 
02353 
02354 /* Add out of order FIN capture */
02355 /* returns 1 for success (end) */
02356 static int AddFinCapture(SnifferSession* session, word32 sequence)
02357 {
02358     if (session->flags.side == CYASSL_SERVER_END) {
02359         if (session->finCaputre.cliCounted == 0)
02360             session->finCaputre.cliFinSeq = sequence;
02361     }
02362     else {
02363         if (session->finCaputre.srvCounted == 0)
02364             session->finCaputre.srvFinSeq = sequence;
02365     }
02366     return 1;
02367 }
02368 
02369 
02370 /* Adjust incoming sequence based on side */
02371 /* returns 0 on success (continue), -1 on error, 1 on success (end) */
02372 static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
02373                           int* sslBytes, const byte** sslFrame, char* error)
02374 {
02375     word32  seqStart = (session->flags.side == CYASSL_SERVER_END) ? 
02376                                      session->cliSeqStart :session->srvSeqStart;
02377     word32  real     = tcpInfo->sequence - seqStart;
02378     word32* expected = (session->flags.side == CYASSL_SERVER_END) ?
02379                                   &session->cliExpected : &session->srvExpected;
02380     PacketBuffer* reassemblyList = (session->flags.side == CYASSL_SERVER_END) ?
02381                         session->cliReassemblyList : session->srvReassemblyList;
02382     
02383     /* handle rollover of sequence */
02384     if (tcpInfo->sequence < seqStart)
02385         real = 0xffffffffU - seqStart + tcpInfo->sequence;
02386         
02387     TraceRelativeSequence(*expected, real);
02388     
02389     if (real < *expected) {
02390         Trace(DUPLICATE_STR);
02391         if (real + *sslBytes > *expected) {
02392             int overlap = *expected - real;
02393             Trace(OVERLAP_DUPLICATE_STR);
02394                 
02395             /* adjust to expected, remove duplicate */
02396             *sslFrame += overlap;
02397             *sslBytes -= overlap;
02398                 
02399             if (reassemblyList) {
02400                 word32 newEnd = *expected + *sslBytes;
02401                     
02402                 if (newEnd > reassemblyList->begin) {
02403                     Trace(OVERLAP_REASSEMBLY_BEGIN_STR);
02404                     
02405                     /* remove bytes already on reassembly list */
02406                     *sslBytes -= newEnd - reassemblyList->begin;
02407                 }
02408                 if (newEnd > reassemblyList->end) {
02409                     Trace(OVERLAP_REASSEMBLY_END_STR);
02410                     
02411                     /* may be past reassembly list end (could have more on list)
02412                        so try to add what's past the front->end */
02413                     AddToReassembly(session->flags.side, reassemblyList->end +1,
02414                                 *sslFrame + reassemblyList->end - *expected + 1,
02415                                  newEnd - reassemblyList->end, session, error);
02416                 }
02417             }
02418         }
02419         else
02420             return 1;
02421     }
02422     else if (real > *expected) {
02423         Trace(OUT_OF_ORDER_STR);
02424         if (*sslBytes > 0)
02425             return AddToReassembly(session->flags.side, real, *sslFrame,
02426                                    *sslBytes, session, error);
02427         else if (tcpInfo->fin)
02428             return AddFinCapture(session, real);
02429     }
02430     /* got expected sequence */
02431     *expected += *sslBytes;
02432     if (tcpInfo->fin)
02433         *expected += 1;
02434     
02435     return 0;
02436 }
02437 
02438 
02439 /* Check latest ack number for missing packets
02440    return 0 ok, <0 on error */
02441 static int CheckAck(TcpInfo* tcpInfo, SnifferSession* session)
02442 {
02443     if (tcpInfo->ack) {
02444         word32  seqStart = (session->flags.side == CYASSL_SERVER_END) ? 
02445                                      session->srvSeqStart :session->cliSeqStart;
02446         word32  real     = tcpInfo->ackNumber - seqStart;
02447         word32  expected = (session->flags.side == CYASSL_SERVER_END) ?
02448                                   session->srvExpected : session->cliExpected;
02449     
02450         /* handle rollover of sequence */
02451         if (tcpInfo->ackNumber < seqStart)
02452             real = 0xffffffffU - seqStart + tcpInfo->ackNumber;
02453         
02454         TraceAck(real, expected);
02455 
02456         if (real > expected)
02457             return -1;  /* we missed a packet, ACKing data we never saw */
02458     }
02459     return 0;
02460 }
02461 
02462 
02463 /* Check TCP Sequence status */
02464 /* returns 0 on success (continue), -1 on error, 1 on success (end) */
02465 static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo,
02466                          SnifferSession* session, int* sslBytes,
02467                          const byte** sslFrame, char* error)
02468 {
02469     int actualLen;
02470     
02471     /* init SEQ from server to client */
02472     if (tcpInfo->syn && tcpInfo->ack) {
02473         session->srvSeqStart = tcpInfo->sequence;
02474         session->srvExpected = 1;
02475         TraceServerSyn(tcpInfo->sequence);
02476         return 1;
02477     }
02478     
02479     /* adjust potential ethernet trailer */
02480     actualLen = ipInfo->total - ipInfo->length - tcpInfo->length;
02481     if (*sslBytes > actualLen) {
02482         *sslBytes = actualLen;
02483     }
02484     
02485     TraceSequence(tcpInfo->sequence, *sslBytes);
02486     if (CheckAck(tcpInfo, session) < 0) {
02487         SetError(ACK_MISSED_STR, error, session, FATAL_ERROR_STATE);
02488         return -1;
02489     }
02490     
02491     return AdjustSequence(tcpInfo, session, sslBytes, sslFrame, error);    
02492 }
02493 
02494 
02495 /* Check Status before record processing */
02496 /* returns 0 on success (continue), -1 on error, 1 on success (end) */
02497 static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo,
02498                           const byte** sslFrame, SnifferSession** session,
02499                           int* sslBytes, const byte** end, char* error)
02500 {
02501     word32 length;
02502     SSL*  ssl = ((*session)->flags.side == CYASSL_SERVER_END) ?
02503                                   (*session)->sslServer : (*session)->sslClient;
02504     /* remove SnifferSession on 2nd FIN or RST */
02505     if (tcpInfo->fin || tcpInfo->rst) {
02506         /* flag FIN and RST */
02507         if (tcpInfo->fin)
02508             (*session)->flags.finCount += 1;
02509         else if (tcpInfo->rst)
02510             (*session)->flags.finCount += 2;
02511         
02512         if ((*session)->flags.finCount >= 2) {
02513             RemoveSession(*session, ipInfo, tcpInfo, 0);
02514             *session = NULL;
02515             return 1;
02516         }
02517     }
02518     
02519     if ((*session)->flags.fatalError == FATAL_ERROR_STATE) {
02520         SetError(FATAL_ERROR_STR, error, NULL, 0);
02521         return -1;
02522     }
02523     
02524     if (*sslBytes == 0) {
02525         Trace(NO_DATA_STR);
02526         return 1;
02527     }
02528     
02529     /* if current partial data, add to end of partial */
02530     if ( (length = ssl->buffers.inputBuffer.length) ) {
02531         Trace(PARTIAL_ADD_STR);
02532         
02533         if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) {
02534             if (GrowInputBuffer(ssl, *sslBytes, length) < 0) {
02535                 SetError(MEMORY_STR, error, *session, FATAL_ERROR_STATE);
02536                 return -1;
02537             }
02538         }
02539         XMEMCPY(&ssl->buffers.inputBuffer.buffer[length], *sslFrame, *sslBytes);
02540         *sslBytes += length;
02541         ssl->buffers.inputBuffer.length = *sslBytes;
02542         *sslFrame = ssl->buffers.inputBuffer.buffer;
02543         *end = *sslFrame + *sslBytes;
02544     }
02545 
02546     if ((*session)->flags.clientHello == 0 && **sslFrame != handshake) {
02547         /* Sanity check the packet for an old style client hello. */
02548         int rhSize = (((*sslFrame)[0] & 0x7f) << 8) | ((*sslFrame)[1]);
02549 
02550         if ((rhSize <= (*sslBytes - 2)) &&
02551             (*sslFrame)[2] == OLD_HELLO_ID && (*sslFrame)[3] == SSLv3_MAJOR) {
02552 #ifdef OLD_HELLO_ALLOWED
02553         int ret = DoOldHello(*session, *sslFrame, &rhSize, sslBytes, error);
02554         if (ret < 0)
02555             return -1;  /* error already set */
02556         if (*sslBytes <= 0)
02557             return 1;
02558 #endif
02559         }
02560         else {
02561 #ifdef STARTTLS_ALLOWED
02562             return 1;
02563 #endif
02564         }
02565     }
02566 
02567     return 0;
02568 }
02569 
02570 
02571 /* See if input on the reassembly list is ready for consuming */
02572 /* returns 1 for TRUE, 0 for FALSE */
02573 static int HaveMoreInput(SnifferSession* session, const byte** sslFrame,
02574                          int* sslBytes, const byte** end, char* error)
02575 {
02576     /* sequence and reassembly based on from, not to */
02577     int            moreInput = 0;
02578     PacketBuffer** front = (session->flags.side == CYASSL_SERVER_END) ?
02579                       &session->cliReassemblyList : &session->srvReassemblyList;
02580     word32*        expected = (session->flags.side == CYASSL_SERVER_END) ?
02581                                   &session->cliExpected : &session->srvExpected;
02582     /* buffer is on receiving end */
02583     word32*        length = (session->flags.side == CYASSL_SERVER_END) ?
02584                                &session->sslServer->buffers.inputBuffer.length :
02585                                &session->sslClient->buffers.inputBuffer.length;
02586     byte*          myBuffer = (session->flags.side == CYASSL_SERVER_END) ?
02587                                 session->sslServer->buffers.inputBuffer.buffer :
02588                                 session->sslClient->buffers.inputBuffer.buffer;
02589     word32       bufferSize = (session->flags.side == CYASSL_SERVER_END) ?
02590                             session->sslServer->buffers.inputBuffer.bufferSize :
02591                             session->sslClient->buffers.inputBuffer.bufferSize;
02592     SSL*               ssl  = (session->flags.side == CYASSL_SERVER_END) ?
02593                             session->sslServer : session->sslClient;
02594     
02595     while (*front && ((*front)->begin == *expected) ) {
02596         word32 room = bufferSize - *length;
02597         word32 packetLen = (*front)->end - (*front)->begin + 1;
02598 
02599         if (packetLen > room && bufferSize < MAX_INPUT_SZ) {
02600             if (GrowInputBuffer(ssl, packetLen, *length) < 0) {
02601                 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
02602                 return 0;
02603             }
02604         }
02605         
02606         if (packetLen <= room) {
02607             PacketBuffer* del = *front;
02608             
02609             XMEMCPY(&myBuffer[*length], (*front)->data, packetLen);
02610             *length   += packetLen;
02611             *expected += packetLen;
02612             
02613             /* remove used packet */
02614             *front = (*front)->next;
02615             FreePacketBuffer(del);
02616             
02617             moreInput = 1;
02618         }
02619         else
02620             break;
02621     }
02622     if (moreInput) {
02623         *sslFrame = myBuffer;
02624         *sslBytes = *length;
02625         *end      = myBuffer + *length;
02626     }
02627     return moreInput;
02628 }
02629                          
02630 
02631 
02632 /* Process Message(s) from sslFrame */
02633 /* return Number of bytes on success, 0 for no data yet, and -1 on error */
02634 static int ProcessMessage(const byte* sslFrame, SnifferSession* session,
02635                           int sslBytes, byte* data, const byte* end,char* error)
02636 {
02637     const byte*       sslBegin = sslFrame;
02638     const byte*       recordEnd;   /* end of record indicator */
02639     const byte*       inRecordEnd; /* indictor from input stream not decrypt */
02640     RecordLayerHeader rh;
02641     int               rhSize = 0;
02642     int               ret;
02643     int               errCode = 0;
02644     int               decoded = 0;      /* bytes stored for user in data */
02645     int               notEnough;        /* notEnough bytes yet flag */
02646     int               decrypted = 0;    /* was current msg decrypted */
02647     SSL*              ssl = (session->flags.side == CYASSL_SERVER_END) ?
02648                                         session->sslServer : session->sslClient;
02649 doMessage:
02650     notEnough = 0;
02651     if (sslBytes < 0) {
02652         SetError(PACKET_HDR_SHORT_STR, error, session, FATAL_ERROR_STATE);
02653         return -1;
02654     }
02655     if (sslBytes >= RECORD_HEADER_SZ) {
02656         if (GetRecordHeader(sslFrame, &rh, &rhSize) != 0) {
02657             SetError(BAD_RECORD_HDR_STR, error, session, FATAL_ERROR_STATE);
02658             return -1;
02659         }
02660     }
02661     else
02662         notEnough = 1;
02663 
02664     if (notEnough || rhSize > (sslBytes - RECORD_HEADER_SZ)) {
02665         /* don't have enough input yet to process full SSL record */
02666         Trace(PARTIAL_INPUT_STR);
02667         
02668         /* store partial if not there already or we advanced */
02669         if (ssl->buffers.inputBuffer.length == 0 || sslBegin != sslFrame) {
02670             if (sslBytes > (int)ssl->buffers.inputBuffer.bufferSize) {
02671                 if (GrowInputBuffer(ssl, sslBytes, 0) < 0) { 
02672                     SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
02673                     return -1;
02674                 }
02675             }
02676             XMEMCPY(ssl->buffers.inputBuffer.buffer, sslFrame, sslBytes);
02677             ssl->buffers.inputBuffer.length = sslBytes;
02678         }
02679         if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error))
02680             goto doMessage;
02681         return decoded;
02682     }
02683     sslFrame += RECORD_HEADER_SZ;
02684     sslBytes -= RECORD_HEADER_SZ;
02685     recordEnd = sslFrame + rhSize;   /* may have more than one record */
02686     inRecordEnd = recordEnd;
02687     
02688     /* decrypt if needed */
02689     if ((session->flags.side == CYASSL_SERVER_END &&
02690                                                session->flags.serverCipherOn)
02691      || (session->flags.side == CYASSL_CLIENT_END &&
02692                                                session->flags.clientCipherOn)) {
02693         int ivAdvance = 0;  /* TLSv1.1 advance amount */
02694         if (ssl->decrypt.setup != 1) {
02695             SetError(DECRYPT_KEYS_NOT_SETUP, error, session, FATAL_ERROR_STATE);
02696             return -1;
02697         }
02698         if (CheckAvailableSize(ssl, rhSize) < 0) {
02699             SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
02700             return -1;
02701         }
02702         sslFrame = DecryptMessage(ssl, sslFrame, rhSize,
02703                                   ssl->buffers.outputBuffer.buffer, &errCode,
02704                                   &ivAdvance);
02705         recordEnd = sslFrame - ivAdvance + rhSize;  /* sslFrame moved so
02706                                                        should recordEnd */
02707         decrypted = 1;
02708         if (errCode != 0) {
02709             SetError(BAD_DECRYPT, error, session, FATAL_ERROR_STATE);
02710             return -1;
02711         }
02712     }
02713 
02714 doPart:
02715             
02716     switch ((enum ContentType)rh.type) {
02717         case handshake:
02718             {
02719                 int startIdx = sslBytes;
02720                 int used;
02721 
02722                 Trace(GOT_HANDSHAKE_STR);
02723                 ret = DoHandShake(sslFrame, &sslBytes, session, error);
02724                 if (ret != 0) {
02725                     if (session->flags.fatalError == 0)
02726                         SetError(BAD_HANDSHAKE_STR, error, session,
02727                                  FATAL_ERROR_STATE);
02728                     return -1;
02729                 }
02730 
02731                 /* DoHandShake now fully decrements sslBytes to remaining */
02732                 used = startIdx - sslBytes;
02733                 sslFrame += used;
02734                 if (decrypted)
02735                     sslFrame += ssl->keys.padSz;
02736             }
02737             break;
02738         case change_cipher_spec:
02739             if (session->flags.side == CYASSL_SERVER_END)
02740                 session->flags.serverCipherOn = 1;
02741             else
02742                 session->flags.clientCipherOn = 1;
02743             Trace(GOT_CHANGE_CIPHER_STR);
02744             ssl->options.handShakeState = HANDSHAKE_DONE;
02745             ssl->options.handShakeDone  = 1;
02746 
02747             sslFrame += 1;
02748             sslBytes -= 1;
02749 
02750             break;
02751         case application_data:
02752             Trace(GOT_APP_DATA_STR);
02753             {
02754                 word32 inOutIdx = 0;
02755                     
02756                 ret = DoApplicationData(ssl, (byte*)sslFrame, &inOutIdx);
02757                 if (ret == 0) {
02758                     ret = ssl->buffers.clearOutputBuffer.length;
02759                     TraceGotData(ret);
02760                     if (ret) {  /* may be blank message */
02761                         XMEMCPY(&data[decoded],
02762                                ssl->buffers.clearOutputBuffer.buffer, ret);
02763                         TraceAddedData(ret, decoded);
02764                         decoded += ret;
02765                         ssl->buffers.clearOutputBuffer.length = 0;
02766                     }
02767                 }
02768                 else {
02769                     SetError(BAD_APP_DATA_STR, error,session,FATAL_ERROR_STATE);
02770                     return -1;
02771                 }
02772                 if (ssl->buffers.outputBuffer.dynamicFlag)
02773                     ShrinkOutputBuffer(ssl);
02774 
02775                 sslFrame += inOutIdx;
02776                 sslBytes -= inOutIdx;
02777             }
02778             break;
02779         case alert:
02780             Trace(GOT_ALERT_STR);
02781             sslFrame += rhSize;
02782             sslBytes -= rhSize;
02783             break;
02784         case no_type:
02785         default:
02786             SetError(GOT_UNKNOWN_RECORD_STR, error, session, FATAL_ERROR_STATE);
02787             return -1;
02788     }
02789 
02790     /* do we have another msg in record ? */
02791     if (sslFrame < recordEnd) {
02792         Trace(ANOTHER_MSG_STR);
02793         goto doPart;
02794     }
02795 
02796     /* back to input stream instead of potential decrypt buffer */
02797     recordEnd = inRecordEnd;
02798 
02799     /* do we have more records ? */
02800     if (recordEnd < end) {
02801         Trace(ANOTHER_MSG_STR);
02802         sslFrame = recordEnd;
02803         sslBytes = (int)(end - recordEnd);
02804         goto doMessage;
02805     }
02806     
02807     /* clear used input */
02808     ssl->buffers.inputBuffer.length = 0;
02809     
02810     /* could have more input ready now */
02811     if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error))
02812         goto doMessage;
02813 
02814     if (ssl->buffers.inputBuffer.dynamicFlag)
02815         ShrinkInputBuffer(ssl, NO_FORCED_FREE);
02816     
02817     return decoded;
02818 }
02819 
02820 
02821 /* See if we need to process any pending FIN captures */
02822 static void CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo, 
02823                             SnifferSession* session)
02824 {
02825     if (session->finCaputre.cliFinSeq && session->finCaputre.cliFinSeq <= 
02826                                          session->cliExpected) {
02827         if (session->finCaputre.cliCounted == 0) {
02828             session->flags.finCount += 1;
02829             session->finCaputre.cliCounted = 1;
02830             TraceClientFin(session->finCaputre.cliFinSeq, session->cliExpected);
02831         }
02832     }
02833         
02834     if (session->finCaputre.srvFinSeq && session->finCaputre.srvFinSeq <= 
02835                                          session->srvExpected) {
02836         if (session->finCaputre.srvCounted == 0) {
02837             session->flags.finCount += 1;
02838             session->finCaputre.srvCounted = 1;
02839             TraceServerFin(session->finCaputre.srvFinSeq, session->srvExpected);
02840         }
02841     }
02842                 
02843     if (session->flags.finCount >= 2) 
02844         RemoveSession(session, ipInfo, tcpInfo, 0);
02845 }
02846 
02847 
02848 /* If session is in fatal error state free resources now 
02849    return true if removed, 0 otherwise */
02850 static int RemoveFatalSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
02851                               SnifferSession* session, char* error)
02852 {
02853     if (session && session->flags.fatalError == FATAL_ERROR_STATE) {
02854         RemoveSession(session, ipInfo, tcpInfo, 0);
02855         SetError(FATAL_ERROR_STR, error, NULL, 0);
02856         return 1;
02857     }
02858     return 0;
02859 }
02860 
02861 
02862 /* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */
02863 /* returns Number of bytes on success, 0 for no data yet, and -1 on error */
02864 int ssl_DecodePacket(const byte* packet, int length, byte* data, char* error)
02865 {
02866     TcpInfo           tcpInfo;
02867     IpInfo            ipInfo;
02868     const byte*       sslFrame;
02869     const byte*       end = packet + length;
02870     int               sslBytes;                /* ssl bytes unconsumed */
02871     int               ret;
02872     SnifferSession*   session = 0;
02873 
02874     if (CheckHeaders(&ipInfo, &tcpInfo, packet, length, &sslFrame, &sslBytes,
02875                      error) != 0)
02876         return -1;
02877     
02878     ret = CheckSession(&ipInfo, &tcpInfo, sslBytes, &session, error);
02879     if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
02880     else if (ret == -1) return -1;
02881     else if (ret ==  1) return  0;   /* done for now */
02882     
02883     ret = CheckSequence(&ipInfo, &tcpInfo, session, &sslBytes, &sslFrame,error);
02884     if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
02885     else if (ret == -1) return -1;
02886     else if (ret ==  1) return  0;   /* done for now */
02887     
02888     ret = CheckPreRecord(&ipInfo, &tcpInfo, &sslFrame, &session, &sslBytes,
02889                          &end, error);
02890     if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
02891     else if (ret == -1) return -1;
02892     else if (ret ==  1) return  0;   /* done for now */
02893 
02894     ret = ProcessMessage(sslFrame, session, sslBytes, data, end, error);
02895     if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
02896     CheckFinCapture(&ipInfo, &tcpInfo, session);
02897     return ret;
02898 }
02899 
02900 
02901 /* Enables (if traceFile)/ Disables debug tracing */
02902 /* returns 0 on success, -1 on error */
02903 int ssl_Trace(const char* traceFile, char* error)
02904 {
02905     if (traceFile) {
02906         TraceFile = fopen(traceFile, "a");
02907         if (!TraceFile) {
02908             SetError(BAD_TRACE_FILE_STR, error, NULL, 0);
02909             return -1;
02910         }
02911         TraceOn = 1;
02912     }
02913     else 
02914         TraceOn = 0;
02915 
02916     return 0;
02917 }
02918 
02919 
02920 
02921 
02922 #endif /* CYASSL_SNIFFER */