wolf SSL / wolfSSL-TLS13-Beta

Fork of wolfSSL by wolf 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-2016 wolfSSL Inc.
00004  *
00005  * This file is part of wolfSSL.
00006  *
00007  * wolfSSL 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  * wolfSSL 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-1335, USA
00020  */
00021 
00022 
00023 #ifdef HAVE_CONFIG_H
00024     #include <config.h>
00025 #endif
00026 
00027 #include <wolfssl/wolfcrypt/settings.h>
00028 
00029 #ifndef WOLFCRYPT_ONLY
00030 #ifdef WOLFSSL_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 <wolfssl/openssl/ssl.h>
00046 #include <wolfssl/internal.h>
00047 #include <wolfssl/error-ssl.h>
00048 #include <wolfssl/sniffer.h>
00049 #include <wolfssl/sniffer_error.h>
00050 #ifdef NO_INLINE
00051     #include <wolfssl/wolfcrypt/misc.h>
00052 #else
00053     #define WOLFSSL_MISC_INCLUDED
00054     #include <wolfcrypt/src/misc.c>
00055 #endif
00056 
00057 
00058 #ifndef WOLFSSL_SNIFFER_TIMEOUT
00059     #define WOLFSSL_SNIFFER_TIMEOUT 900
00060     /* Cache unclosed Sessions for 15 minutes since last used */
00061 #endif
00062 
00063 /* Misc constants */
00064 enum {
00065     MAX_SERVER_ADDRESS = 128, /* maximum server address length */
00066     MAX_SERVER_NAME    = 128, /* maximum server name length */
00067     MAX_ERROR_LEN      = 80,  /* maximum error length */
00068     ETHER_IF_ADDR_LEN  = 6,   /* ethernet interface address length */
00069     LOCAL_IF_ADDR_LEN  = 4,   /* localhost interface address length, !windows */
00070     TCP_PROTO          = 6,   /* TCP_PROTOCOL */
00071     IP_HDR_SZ          = 20,  /* IP header length, min */
00072     TCP_HDR_SZ         = 20,  /* TCP header length, min */
00073     IPV4               = 4,   /* IP version 4 */
00074     TCP_PROTOCOL       = 6,   /* TCP Protocol id */
00075     TRACE_MSG_SZ       = 80,  /* Trace Message buffer size */
00076     HASH_SIZE          = 499, /* Session Hash Table Rows */
00077     PSEUDO_HDR_SZ      = 12,  /* TCP Pseudo Header size in bytes */
00078     FATAL_ERROR_STATE  =  1,  /* SnifferSession fatal error state */
00079     TICKET_HINT_LEN    = 4,   /* Session Ticket Hint length */
00080     EXT_TYPE_SZ        = 2,   /* Extension length */
00081     MAX_INPUT_SZ       = MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA +
00082                          MTU_EXTRA,  /* Max input sz of reassembly */
00083     EXT_MASTER_SECRET  = 0x17, /* Extended Master Secret Extension ID */
00084     TICKET_EXT_ID      = 0x23 /* Session Ticket Extension ID */
00085 };
00086 
00087 
00088 #ifdef _WIN32
00089 
00090 static HMODULE dllModule;  /* for error string resources */
00091 
00092 BOOL APIENTRY DllMain( HMODULE hModule,
00093                        DWORD  ul_reason_for_call,
00094                        LPVOID lpReserved
00095                      )
00096 {
00097     static int didInit = 0;
00098 
00099     switch (ul_reason_for_call)
00100     {
00101     case DLL_PROCESS_ATTACH:
00102         if (didInit == 0) {
00103             dllModule = hModule;
00104             ssl_InitSniffer();
00105             didInit = 1;
00106         }
00107         break;
00108     case DLL_THREAD_ATTACH:
00109         break;
00110     case DLL_THREAD_DETACH:
00111         break;
00112     case DLL_PROCESS_DETACH:
00113         if (didInit) {
00114             ssl_FreeSniffer();
00115             didInit = 0;
00116         }
00117         break;
00118     }
00119     return TRUE;
00120 }
00121 
00122 #endif /* _WIN32 */
00123 
00124 
00125 static int TraceOn = 0;         /* Trace is off by default */
00126 static FILE* TraceFile = 0;
00127 
00128 
00129 /* windows uses .rc table for this */
00130 #ifndef _WIN32
00131 
00132 static const char* const msgTable[] =
00133 {
00134     /* 1 */
00135     "Out of Memory",
00136     "New SSL Sniffer Server Registered",
00137     "Checking IP Header",
00138     "SSL Sniffer Server Not Registered",
00139     "Checking TCP Header",
00140 
00141     /* 6 */
00142     "SSL Sniffer Server Port Not Registered",
00143     "RSA Private Decrypt Error",
00144     "RSA Private Decode Error",
00145     "Set Cipher Spec Error",
00146     "Server Hello Input Malformed",
00147 
00148     /* 11 */
00149     "Couldn't Resume Session Error",
00150     "Server Did Resumption",
00151     "Client Hello Input Malformed",
00152     "Client Trying to Resume",
00153     "Handshake Input Malformed",
00154 
00155     /* 16 */
00156     "Got Hello Verify msg",
00157     "Got Server Hello msg",
00158     "Got Cert Request msg",
00159     "Got Server Key Exchange msg",
00160     "Got Cert msg",
00161 
00162     /* 21 */
00163     "Got Server Hello Done msg",
00164     "Got Finished msg",
00165     "Got Client Hello msg",
00166     "Got Client Key Exchange msg",
00167     "Got Cert Verify msg",
00168 
00169     /* 26 */
00170     "Got Unknown Handshake msg",
00171     "New SSL Sniffer Session created",
00172     "Couldn't create new SSL",
00173     "Got a Packet to decode",
00174     "No data present",
00175 
00176     /* 31 */
00177     "Session Not Found",
00178     "Got an Old Client Hello msg",
00179     "Old Client Hello Input Malformed",
00180     "Old Client Hello OK",
00181     "Bad Old Client Hello",
00182 
00183     /* 36 */
00184     "Bad Record Header",
00185     "Record Header Input Malformed",
00186     "Got a HandShake msg",
00187     "Bad HandShake msg",
00188     "Got a Change Cipher Spec msg",
00189 
00190     /* 41 */
00191     "Got Application Data msg",
00192     "Bad Application Data",
00193     "Got an Alert msg",
00194     "Another msg to Process",
00195     "Removing Session From Table",
00196     
00197     /* 46 */
00198     "Bad Key File",
00199     "Wrong IP Version",
00200     "Wrong Protocol type",
00201     "Packet Short for header processing",
00202     "Got Unknown Record Type",
00203     
00204     /* 51 */
00205     "Can't Open Trace File",
00206     "Session in Fatal Error State",
00207     "Partial SSL record received",
00208     "Buffer Error, malformed input",
00209     "Added to Partial Input",
00210     
00211     /* 56 */
00212     "Received a Duplicate Packet",
00213     "Received an Out of Order Packet",
00214     "Received an Overlap Duplicate Packet",
00215     "Received an Overlap Reassembly Begin Duplicate Packet",
00216     "Received an Overlap Reassembly End Duplicate Packet",
00217 
00218     /* 61 */
00219     "Missed the Client Hello Entirely",
00220     "Got Hello Request msg",
00221     "Got Session Ticket msg",
00222     "Bad Input",
00223     "Bad Decrypt Type",
00224 
00225     /* 66 */
00226     "Bad Finished Message Processing",
00227     "Bad Compression Type",
00228     "Bad DeriveKeys Error",
00229     "Saw ACK for Missing Packet Error",
00230     "Bad Decrypt Operation",
00231 
00232     /* 71 */
00233     "Decrypt Keys Not Set Up",
00234     "Late Key Load Error",
00235     "Got Certificate Status msg",
00236     "RSA Key Missing Error",
00237     "Secure Renegotiation Not Supported",
00238 
00239     /* 76 */
00240     "Get Session Stats Failure",
00241     "Reassembly Buffer Size Exceeded",
00242     "Dropping Lost Fragment",
00243     "Dropping Partial Record",
00244     "Clear ACK Fault",
00245 
00246     /* 81 */
00247     "Bad Decrypt Size",
00248     "Extended Master Secret Hash Error"
00249 };
00250 
00251 
00252 /* *nix version uses table above */
00253 static void GetError(int idx, char* str)
00254 {
00255     XSTRNCPY(str, msgTable[idx - 1], MAX_ERROR_LEN);
00256 }
00257 
00258 
00259 #else /* _WIN32 */
00260 
00261 
00262 /* Windows version uses .rc table */
00263 static void GetError(int idx, char* buffer)
00264 {
00265     if (!LoadStringA(dllModule, idx, buffer, MAX_ERROR_LEN))
00266         buffer[0] = 0;
00267 }
00268 
00269 
00270 #endif /* _WIN32 */
00271 
00272 
00273 /* Packet Buffer for reassembly list and ready list */
00274 typedef struct PacketBuffer {
00275     word32  begin;      /* relative sequence begin */
00276     word32  end;        /* relative sequence end   */
00277     byte*   data;       /* actual data             */
00278     struct PacketBuffer* next; /* next on reassembly list or ready list */
00279 } PacketBuffer;
00280 
00281 
00282 #ifdef HAVE_SNI
00283 
00284 /* NamedKey maps a SNI name to a specific private key */
00285 typedef struct NamedKey {
00286     char             name[MAX_SERVER_NAME];      /* server DNS name */
00287     word32           nameSz;                     /* size of server DNS name */
00288     byte*            key;                        /* DER private key */
00289     word32           keySz;                      /* size of DER private key */
00290     struct NamedKey* next;                       /* for list */
00291 } NamedKey;
00292 
00293 #endif
00294 
00295 
00296 /* Sniffer Server holds info for each server/port monitored */
00297 typedef struct SnifferServer {
00298     SSL_CTX*       ctx;                          /* SSL context */
00299     char           address[MAX_SERVER_ADDRESS];  /* passed in server address */
00300     word32         server;                       /* netowrk order address */
00301     int            port;                         /* server port */
00302 #ifdef HAVE_SNI
00303     NamedKey*      namedKeys;                    /* mapping of names and keys */
00304     wolfSSL_Mutex   namedKeysMutex;               /* mutex for namedKey list */
00305 #endif
00306     struct SnifferServer* next;                  /* for list */
00307 } SnifferServer;
00308 
00309 
00310 /* Session Flags */
00311 typedef struct Flags {
00312     byte           side;            /* which end is current packet headed */
00313     byte           serverCipherOn;  /* indicates whether cipher is active */
00314     byte           clientCipherOn;  /* indicates whether cipher is active */
00315     byte           resuming;        /* did this session come from resumption */
00316     byte           cached;          /* have we cached this session yet */
00317     byte           clientHello;     /* processed client hello yet, for SSLv2 */
00318     byte           finCount;        /* get both FINs before removing */
00319     byte           fatalError;      /* fatal error state */
00320     byte           cliAckFault;     /* client acked unseen data from server */
00321     byte           srvAckFault;     /* server acked unseen data from client */
00322     byte           cliSkipPartial;  /* client skips partial data to catch up */
00323     byte           srvSkipPartial;  /* server skips partial data to catch up */
00324 #ifdef HAVE_EXTENDED_MASTER
00325     byte           expectEms;       /* expect extended master secret */
00326 #endif
00327 } Flags;
00328 
00329 
00330 /* Out of Order FIN caputre */
00331 typedef struct FinCaputre {
00332     word32 cliFinSeq;               /* client relative sequence FIN  0 is no */
00333     word32 srvFinSeq;               /* server relative sequence FIN, 0 is no */
00334     byte   cliCounted;              /* did we count yet, detects duplicates */
00335     byte   srvCounted;              /* did we count yet, detects duplicates */
00336 } FinCaputre;
00337 
00338 
00339 typedef struct HsHashes {
00340 #ifndef NO_OLD_TLS
00341 #ifndef NO_SHA
00342     Sha hashSha;
00343 #endif
00344 #ifndef NO_MD5
00345     Md5 hashMd5;
00346 #endif
00347 #endif
00348 #ifndef NO_SHA256
00349     Sha256 hashSha256;
00350 #endif
00351 #ifdef WOLFSSL_SHA384
00352     Sha384 hashSha384;
00353 #endif
00354 } HsHashes;
00355 
00356 
00357 /* Sniffer Session holds info for each client/server SSL/TLS session */
00358 typedef struct SnifferSession {
00359     SnifferServer* context;         /* server context */
00360     SSL*           sslServer;       /* SSL server side decode */
00361     SSL*           sslClient;       /* SSL client side decode */
00362     word32         server;          /* server address in network byte order */
00363     word32         client;          /* client address in network byte order */
00364     word16         srvPort;         /* server port */
00365     word16         cliPort;         /* client port */
00366     word32         cliSeqStart;     /* client start sequence */
00367     word32         srvSeqStart;     /* server start sequence */
00368     word32         cliExpected;     /* client expected sequence (relative) */
00369     word32         srvExpected;     /* server expected sequence (relative) */
00370     FinCaputre     finCaputre;      /* retain out of order FIN s */
00371     Flags          flags;           /* session flags */
00372     time_t         lastUsed;          /* last used ticks */
00373     PacketBuffer*  cliReassemblyList; /* client out of order packets */
00374     PacketBuffer*  srvReassemblyList; /* server out of order packets */
00375     word32         cliReassemblyMemory; /* client packet memory used */
00376     word32         srvReassemblyMemory; /* server packet memory used */
00377     struct SnifferSession* next;      /* for hash table list */
00378     byte*          ticketID;          /* mac ID of session ticket */
00379 #ifdef HAVE_EXTENDED_MASTER
00380     HsHashes*       hash;
00381 #endif
00382 } SnifferSession;
00383 
00384 
00385 /* Sniffer Server List and mutex */
00386 static SnifferServer* ServerList = 0;
00387 static wolfSSL_Mutex ServerListMutex;
00388 
00389 
00390 /* Session Hash Table, mutex, and count */
00391 static SnifferSession* SessionTable[HASH_SIZE];
00392 static wolfSSL_Mutex SessionMutex;
00393 static int SessionCount = 0;
00394 
00395 /* Recovery of missed data switches and stats */
00396 static wolfSSL_Mutex RecoveryMutex;      /* for stats */
00397 static int RecoveryEnabled    = 0;       /* global switch */
00398 static int MaxRecoveryMemory  = -1;      /* per session max recovery memory */
00399 static word32 MissedDataSessions = 0;    /* # of sessions with missed data */
00400 
00401 
00402 static void UpdateMissedDataSessions(void)
00403 {
00404     wc_LockMutex(&RecoveryMutex);
00405     MissedDataSessions += 1;
00406     wc_UnLockMutex(&RecoveryMutex);
00407 }
00408 
00409 
00410 /* Initialize overall Sniffer */
00411 void ssl_InitSniffer(void)
00412 {
00413     wolfSSL_Init();
00414     wc_InitMutex(&ServerListMutex);
00415     wc_InitMutex(&SessionMutex);
00416     wc_InitMutex(&RecoveryMutex);
00417 }
00418 
00419 
00420 #ifdef HAVE_SNI
00421 
00422 /* Free Named Key and the zero out the private key it holds */
00423 static void FreeNamedKey(NamedKey* in)
00424 {
00425     if (in) {
00426         if (in->key) {
00427             ForceZero(in->key, in->keySz);
00428             free(in->key);
00429         }
00430         free(in);
00431     }
00432 }
00433 
00434 
00435 static void FreeNamedKeyList(NamedKey* in)
00436 {
00437     NamedKey* next;
00438 
00439     while (in) {
00440         next = in->next;
00441         FreeNamedKey(in);
00442         in = next;
00443     }
00444 }
00445 
00446 #endif
00447 
00448 
00449 /* Free Sniffer Server's resources/self */
00450 static void FreeSnifferServer(SnifferServer* srv)
00451 {
00452     if (srv) {
00453 #ifdef HAVE_SNI
00454         wc_LockMutex(&srv->namedKeysMutex);
00455         FreeNamedKeyList(srv->namedKeys);
00456         wc_UnLockMutex(&srv->namedKeysMutex);
00457         wc_FreeMutex(&srv->namedKeysMutex);
00458 #endif
00459         SSL_CTX_free(srv->ctx);
00460     }
00461     free(srv);
00462 }
00463 
00464 
00465 /* free PacketBuffer's resources/self */
00466 static void FreePacketBuffer(PacketBuffer* del)
00467 {
00468     if (del) {
00469         free(del->data);
00470         free(del);
00471     }
00472 }
00473 
00474 
00475 /* remove PacketBuffer List */
00476 static void FreePacketList(PacketBuffer* in)
00477 {
00478     if (in) {
00479         PacketBuffer* del;
00480         PacketBuffer* packet = in;
00481         
00482         while (packet) {
00483             del = packet;
00484             packet = packet->next;
00485             FreePacketBuffer(del);
00486         }
00487     }
00488 }
00489 
00490 
00491 /* Free Sniffer Session's resources/self */
00492 static void FreeSnifferSession(SnifferSession* session)
00493 {
00494     if (session) {
00495         SSL_free(session->sslClient);
00496         SSL_free(session->sslServer);
00497         
00498         FreePacketList(session->cliReassemblyList);
00499         FreePacketList(session->srvReassemblyList);
00500 
00501         free(session->ticketID);
00502 #ifdef HAVE_EXTENDED_MASTER
00503         free(session->hash);
00504 #endif
00505     }
00506     free(session);
00507 }
00508 
00509 
00510 /* Free overall Sniffer */
00511 void ssl_FreeSniffer(void)
00512 {
00513     SnifferServer*  srv;
00514     SnifferServer*  removeServer;
00515     SnifferSession* session;
00516     SnifferSession* removeSession;
00517     int i;
00518 
00519     wc_LockMutex(&ServerListMutex);
00520     wc_LockMutex(&SessionMutex);
00521     
00522     srv = ServerList;
00523     while (srv) {
00524         removeServer = srv;
00525         srv = srv->next;
00526         FreeSnifferServer(removeServer);
00527     }
00528 
00529     for (i = 0; i < HASH_SIZE; i++) {
00530         session = SessionTable[i];
00531         while (session) {
00532             removeSession = session;
00533             session = session->next;
00534             FreeSnifferSession(removeSession);
00535         }
00536     }
00537 
00538     wc_UnLockMutex(&SessionMutex);
00539     wc_UnLockMutex(&ServerListMutex);
00540 
00541     wc_FreeMutex(&RecoveryMutex);
00542     wc_FreeMutex(&SessionMutex);
00543     wc_FreeMutex(&ServerListMutex);
00544 
00545     if (TraceFile) {
00546         TraceOn = 0;
00547         fclose(TraceFile);
00548         TraceFile = NULL;
00549     }
00550 
00551     wolfSSL_Cleanup();
00552 }
00553 
00554 
00555 #ifdef HAVE_EXTENDED_MASTER
00556 
00557 static int HashInit(HsHashes* hash)
00558 {
00559     int ret = 0;
00560 
00561     XMEMSET(hash, 0, sizeof(HsHashes));
00562 
00563 #ifndef NO_OLD_TLS
00564 #ifndef NO_SHA
00565     if (ret == 0)
00566         ret = wc_InitSha(&hash->hashSha);
00567 #endif
00568 #ifndef NO_MD5
00569     if (ret == 0)
00570         wc_InitMd5(&hash->hashMd5);
00571 #endif
00572 #endif
00573 #ifndef NO_SHA256
00574     if (ret == 0)
00575         ret = wc_InitSha256(&hash->hashSha256);
00576 #endif
00577 #ifdef WOLFSSL_SHA384
00578     if (ret == 0)
00579         ret = wc_InitSha384(&hash->hashSha384);
00580 #endif
00581 
00582     return ret;
00583 }
00584 
00585 
00586 static int HashUpdate(HsHashes* hash, const byte* input, int sz)
00587 {
00588     int ret = 0;
00589 
00590     input -= HANDSHAKE_HEADER_SZ;
00591     sz += HANDSHAKE_HEADER_SZ;
00592 
00593 #ifndef NO_OLD_TLS
00594 #ifndef NO_SHA
00595     if (ret == 0)
00596         ret = wc_ShaUpdate(&hash->hashSha, input, sz);
00597 #endif
00598 #ifndef NO_MD5
00599     if (ret == 0)
00600         wc_Md5Update(&hash->hashMd5, input, sz);
00601 #endif
00602 #endif
00603 #ifndef NO_SHA256
00604     if (ret == 0)
00605         ret = wc_Sha256Update(&hash->hashSha256, input, sz);
00606 #endif
00607 #ifdef WOLFSSL_SHA384
00608     if (ret == 0)
00609         ret = wc_Sha384Update(&hash->hashSha384, input, sz);
00610 #endif
00611 
00612     return ret;
00613 }
00614 
00615 
00616 static int HashCopy(HS_Hashes* d, HsHashes* s)
00617 {
00618 #ifndef NO_OLD_TLS
00619 #ifndef NO_SHA
00620         XMEMCPY(&d->hashSha, &s->hashSha, sizeof(Sha));
00621 #endif
00622 #ifndef NO_MD5
00623         XMEMCPY(&d->hashMd5, &s->hashMd5, sizeof(Md5));
00624 #endif
00625 #endif
00626 
00627 #ifndef NO_SHA256
00628         XMEMCPY(&d->hashSha256, &s->hashSha256, sizeof(Sha256));
00629 #endif
00630 #ifdef WOLFSSL_SHA384
00631         XMEMCPY(&d->hashSha384, &s->hashSha384, sizeof(Sha384));
00632 #endif
00633 
00634     return 0;
00635 }
00636 
00637 #endif
00638 
00639 
00640 /* Initialize a SnifferServer */
00641 static void InitSnifferServer(SnifferServer* sniffer)
00642 {
00643     sniffer->ctx = 0;
00644     XMEMSET(sniffer->address, 0, MAX_SERVER_ADDRESS);
00645     sniffer->server   = 0;
00646     sniffer->port     = 0;
00647 #ifdef HAVE_SNI
00648     sniffer->namedKeys = 0;
00649     wc_InitMutex(&sniffer->namedKeysMutex);
00650 #endif
00651     sniffer->next     = 0;
00652 }
00653 
00654 
00655 /* Initialize session flags */
00656 static void InitFlags(Flags* flags)
00657 {
00658     flags->side           = 0;
00659     flags->serverCipherOn = 0;
00660     flags->clientCipherOn = 0;
00661     flags->resuming       = 0;
00662     flags->cached         = 0;
00663     flags->clientHello    = 0;
00664     flags->finCount       = 0;
00665     flags->fatalError     = 0;
00666     flags->cliAckFault    = 0;
00667     flags->srvAckFault    = 0;
00668     flags->cliSkipPartial = 0;
00669     flags->srvSkipPartial = 0;
00670 #ifdef HAVE_EXTENDED_MASTER
00671     flags->expectEms      = 0;
00672 #endif
00673 }
00674 
00675 
00676 /* Initialize FIN Capture */
00677 static void InitFinCapture(FinCaputre* cap)
00678 {
00679     cap->cliFinSeq  = 0;
00680     cap->srvFinSeq  = 0;
00681     cap->cliCounted = 0;
00682     cap->srvCounted = 0;
00683 }
00684 
00685 
00686 /* Initialize a Sniffer Session */
00687 static void InitSession(SnifferSession* session)
00688 {
00689     session->context        = 0;
00690     session->sslServer      = 0;
00691     session->sslClient      = 0;
00692     session->server         = 0;
00693     session->client         = 0;
00694     session->srvPort        = 0;
00695     session->cliPort        = 0;
00696     session->cliSeqStart    = 0;
00697     session->srvSeqStart    = 0;
00698     session->cliExpected    = 0;
00699     session->srvExpected    = 0;
00700     session->lastUsed       = 0;
00701     session->cliReassemblyList = 0;
00702     session->srvReassemblyList = 0;
00703     session->cliReassemblyMemory = 0;
00704     session->srvReassemblyMemory = 0;
00705     session->next           = 0;
00706     session->ticketID       = 0;
00707     
00708     InitFlags(&session->flags);
00709     InitFinCapture(&session->finCaputre);
00710 #ifdef HAVE_EXTENDED_MASTER
00711     session->hash = 0;
00712 #endif
00713 }
00714 
00715 
00716 /* IP Info from IP Header */
00717 typedef struct IpInfo {
00718     int    length;        /* length of this header */
00719     int    total;         /* total length of fragment */
00720     word32 src;           /* network order source address */
00721     word32 dst;           /* network order destination address */
00722 } IpInfo;
00723 
00724 
00725 /* TCP Info from TCP Header */
00726 typedef struct TcpInfo {
00727     int    srcPort;       /* source port */
00728     int    dstPort;       /* source port */
00729     int    length;        /* length of this header */
00730     word32 sequence;      /* sequence number */
00731     word32 ackNumber;     /* ack number */
00732     byte   fin;           /* FIN set */
00733     byte   rst;           /* RST set */
00734     byte   syn;           /* SYN set */
00735     byte   ack;           /* ACK set */
00736 } TcpInfo;
00737 
00738 
00739 /* Tcp Pseudo Header for Checksum calculation */
00740 typedef struct TcpPseudoHdr {
00741     word32  src;        /* source address */
00742     word32  dst;        /* destination address */
00743     byte    rsv;        /* reserved, always 0 */
00744     byte    protocol;   /* IP protocol */
00745     word16  length;     /* tcp header length + data length (doesn't include */
00746                         /* pseudo header length) network order */
00747 } TcpPseudoHdr;
00748 
00749 
00750 /* Password Setting Callback */
00751 static int SetPassword(char* passwd, int sz, int rw, void* userdata)
00752 {
00753     (void)rw;
00754     XSTRNCPY(passwd, (const char*)userdata, sz);
00755     return (int)XSTRLEN((const char*)userdata);
00756 }
00757 
00758 
00759 /* Ethernet Header */
00760 typedef struct EthernetHdr {
00761     byte   dst[ETHER_IF_ADDR_LEN];    /* destination host address */ 
00762     byte   src[ETHER_IF_ADDR_LEN];    /* source  host address */ 
00763     word16 type;                      /* IP, ARP, etc */ 
00764 } EthernetHdr;
00765 
00766 
00767 /* IP Header */
00768 typedef struct IpHdr {
00769     byte    ver_hl;              /* version/header length */
00770     byte    tos;                 /* type of service */
00771     word16  length;              /* total length */
00772     word16  id;                  /* identification */
00773     word16  offset;              /* fragment offset field */
00774     byte    ttl;                 /* time to live */
00775     byte    protocol;            /* protocol */
00776     word16  sum;                 /* checksum */
00777     word32  src;                 /* source address */
00778     word32  dst;                 /* destination address */
00779 } IpHdr;
00780 
00781 
00782 #define IP_HL(ip)      ( (((ip)->ver_hl) & 0x0f) * 4)
00783 #define IP_V(ip)       ( ((ip)->ver_hl) >> 4)
00784 
00785 /* TCP Header */
00786 typedef struct TcpHdr {
00787     word16  srcPort;            /* source port */
00788     word16  dstPort;            /* destination port */
00789     word32  sequence;           /* sequence number */ 
00790     word32  ack;                /* acknoledgment number */ 
00791     byte    offset;             /* data offset, reserved */
00792     byte    flags;              /* option flags */
00793     word16  window;             /* window */
00794     word16  sum;                /* checksum */
00795     word16  urgent;             /* urgent pointer */
00796 } TcpHdr;
00797 
00798 #define TCP_LEN(tcp)  ( (((tcp)->offset & 0xf0) >> 4) * 4)
00799 #define TCP_FIN 0x01
00800 #define TCP_SYN 0x02
00801 #define TCP_RST 0x04
00802 #define TCP_ACK 0x10
00803 
00804 
00805 
00806 
00807 
00808 /* Use platform specific GetError to write to tracfile if tracing */ 
00809 static void Trace(int idx) 
00810 {
00811     if (TraceOn) {
00812         char myBuffer[MAX_ERROR_LEN];
00813         GetError(idx, myBuffer);
00814         fprintf(TraceFile, "\t%s\n", myBuffer);
00815 #ifdef DEBUG_SNIFFER
00816         fprintf(stderr,    "\t%s\n", myBuffer);
00817 #endif
00818     }
00819 }
00820 
00821 
00822 /* Show TimeStamp for beginning of packet Trace */
00823 static void TraceHeader(void)
00824 {
00825     if (TraceOn) {
00826         time_t ticks = time(NULL);
00827         fprintf(TraceFile, "\n%s", ctime(&ticks));
00828     }
00829 }
00830 
00831 
00832 /* Show Set Server info for Trace */
00833 static void TraceSetServer(const char* srv, int port, const char* keyFile)
00834 {
00835     if (TraceOn) {
00836         fprintf(TraceFile, "\tTrying to install a new Sniffer Server with\n");
00837         fprintf(TraceFile, "\tserver: %s, port: %d, keyFile: %s\n", srv, port,
00838                                                                     keyFile);
00839     }
00840 }
00841 
00842 
00843 #ifdef HAVE_SNI
00844 
00845 /* Show Set Named Server info for Trace */
00846 static void TraceSetNamedServer(const char* name,
00847                                  const char* srv, int port, const char* keyFile)
00848 {
00849     if (TraceOn) {
00850         fprintf(TraceFile, "\tTrying to install a new Sniffer Server with\n");
00851         fprintf(TraceFile, "\tname: %s, server: %s, port: %d, keyFile: %s\n",
00852                                                       name, srv, port, keyFile);
00853     }
00854 }
00855 
00856 #endif
00857 
00858 
00859 /* Trace got packet number */
00860 static void TracePacket(void)
00861 {
00862     if (TraceOn) {
00863         static word32 packetNumber = 0;
00864         fprintf(TraceFile, "\tGot a Packet to decode, packet %u\n",
00865                 ++packetNumber);
00866     }
00867 }
00868 
00869 
00870 /* Convert network byte order address into human readable */
00871 static char* IpToS(word32 addr, char* str)
00872 {
00873     byte* p = (byte*)&addr;
00874     
00875     SNPRINTF(str, TRACE_MSG_SZ, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
00876     
00877     return str;
00878 }
00879 
00880 
00881 /* Show destination and source address from Ip Hdr for packet Trace */
00882 static void TraceIP(IpHdr* iphdr)
00883 {
00884     if (TraceOn) {
00885         char src[TRACE_MSG_SZ];
00886         char dst[TRACE_MSG_SZ];
00887         fprintf(TraceFile, "\tdst:%s src:%s\n", IpToS(iphdr->dst, dst),
00888                 IpToS(iphdr->src, src));
00889     }
00890 }
00891 
00892 
00893 /* Show destination and source port from Tcp Hdr for packet Trace */
00894 static void TraceTcp(TcpHdr* tcphdr)
00895 {
00896     if (TraceOn) {
00897         fprintf(TraceFile, "\tdstPort:%u srcPort:%u\n", ntohs(tcphdr->dstPort),
00898                 ntohs(tcphdr->srcPort));
00899     }
00900 }
00901 
00902 
00903 /* Show sequence and payload length for Trace */
00904 static void TraceSequence(word32 seq, int len)
00905 {
00906     if (TraceOn) {
00907         fprintf(TraceFile, "\tSequence:%u, payload length:%d\n", seq, len);
00908     }
00909 }
00910 
00911 
00912 /* Show sequence and payload length for Trace */
00913 static void TraceAck(word32 ack, word32 expected)
00914 {
00915     if (TraceOn) {
00916         fprintf(TraceFile, "\tAck:%u Expected:%u\n", ack, expected);
00917     }
00918 }
00919 
00920 
00921 /* Show relative expected and relative received sequences */
00922 static void TraceRelativeSequence(word32 expected, word32 got)
00923 {
00924     if (TraceOn) {
00925         fprintf(TraceFile, "\tExpected sequence:%u, received sequence:%u\n",
00926                 expected, got);
00927     }
00928 }
00929 
00930 
00931 /* Show server sequence startup from SYN */
00932 static void TraceServerSyn(word32 seq)
00933 {
00934     if (TraceOn) {
00935         fprintf(TraceFile, "\tServer SYN, Sequence Start:%u\n", seq);
00936     }
00937 }
00938 
00939 
00940 /* Show client sequence startup from SYN */
00941 static void TraceClientSyn(word32 seq)
00942 {
00943     if (TraceOn) {
00944         fprintf(TraceFile, "\tClient SYN, Sequence Start:%u\n", seq);
00945     }
00946 }
00947 
00948 
00949 /* Show client FIN capture */
00950 static void TraceClientFin(word32 finSeq, word32 relSeq)
00951 {
00952     if (TraceOn) {
00953         fprintf(TraceFile, "\tClient FIN capture:%u, current SEQ:%u\n",
00954                 finSeq, relSeq);
00955     }
00956 }
00957 
00958 
00959 /* Show server FIN capture */
00960 static void TraceServerFin(word32 finSeq, word32 relSeq)
00961 {
00962     if (TraceOn) {
00963         fprintf(TraceFile, "\tServer FIN capture:%u, current SEQ:%u\n",
00964                 finSeq, relSeq);
00965     }
00966 }
00967 
00968 
00969 /* Show number of SSL data bytes decoded, could be 0 (ok) */
00970 static void TraceGotData(int bytes)
00971 {
00972     if (TraceOn) {
00973         fprintf(TraceFile, "\t%d bytes of SSL App data processed\n", bytes);
00974     }
00975 }
00976 
00977 
00978 /* Show bytes added to old SSL App data */
00979 static void TraceAddedData(int newBytes, int existingBytes)
00980 {
00981     if (TraceOn) {
00982         fprintf(TraceFile,
00983                 "\t%d bytes added to %d existing bytes in User Buffer\n",
00984                 newBytes, existingBytes);
00985     }
00986 }
00987 
00988 
00989 /* Show Stale Session */
00990 static void TraceStaleSession(void)
00991 {
00992     if (TraceOn) {
00993         fprintf(TraceFile, "\tFound a stale session\n");
00994     }
00995 }
00996 
00997 
00998 /* Show Finding Stale Sessions */
00999 static void TraceFindingStale(void)
01000 {
01001     if (TraceOn) {
01002         fprintf(TraceFile, "\tTrying to find Stale Sessions\n");
01003     }
01004 }
01005 
01006 
01007 /* Show Removed Session */
01008 static void TraceRemovedSession(void)
01009 {
01010     if (TraceOn) {
01011         fprintf(TraceFile, "\tRemoved it\n");
01012     }
01013 }
01014 
01015 
01016 /* Set user error string */
01017 static void SetError(int idx, char* error, SnifferSession* session, int fatal)
01018 {
01019     GetError(idx, error);
01020     Trace(idx);
01021     if (session && fatal == FATAL_ERROR_STATE)
01022         session->flags.fatalError = 1;
01023 }
01024 
01025 
01026 /* See if this IPV4 network order address has been registered */
01027 /* return 1 is true, 0 is false */
01028 static int IsServerRegistered(word32 addr)
01029 {
01030     int ret = 0;     /* false */
01031     SnifferServer* sniffer;
01032 
01033     wc_LockMutex(&ServerListMutex);
01034     
01035     sniffer = ServerList;
01036     while (sniffer) {
01037         if (sniffer->server == addr) {
01038             ret = 1;
01039             break;
01040         }
01041         sniffer = sniffer->next;
01042     }
01043     
01044     wc_UnLockMutex(&ServerListMutex);
01045 
01046     return ret;
01047 }
01048 
01049 
01050 /* See if this port has been registered to watch */
01051 /* return 1 is true, 0 is false */
01052 static int IsPortRegistered(word32 port)
01053 {
01054     int ret = 0;    /* false */
01055     SnifferServer* sniffer;
01056     
01057     wc_LockMutex(&ServerListMutex);
01058     
01059     sniffer = ServerList;
01060     while (sniffer) {
01061         if (sniffer->port == (int)port) {
01062             ret = 1; 
01063             break;
01064         }
01065         sniffer = sniffer->next;
01066     }
01067     
01068     wc_UnLockMutex(&ServerListMutex);
01069 
01070     return ret;
01071 }
01072 
01073 
01074 /* Get SnifferServer from IP and Port */
01075 static SnifferServer* GetSnifferServer(IpInfo* ipInfo, TcpInfo* tcpInfo)
01076 {
01077     SnifferServer* sniffer;
01078     
01079     wc_LockMutex(&ServerListMutex);
01080     
01081     sniffer = ServerList;
01082     while (sniffer) {
01083         if (sniffer->port == tcpInfo->srcPort && sniffer->server == ipInfo->src)
01084             break;
01085         if (sniffer->port == tcpInfo->dstPort && sniffer->server == ipInfo->dst)
01086             break;
01087         sniffer = sniffer->next;
01088     }
01089     
01090     wc_UnLockMutex(&ServerListMutex);
01091     
01092     return sniffer;
01093 }
01094 
01095 
01096 /* Hash the Session Info, return hash row */
01097 static word32 SessionHash(IpInfo* ipInfo, TcpInfo* tcpInfo)
01098 {
01099     word32 hash = ipInfo->src * ipInfo->dst;
01100     hash *= tcpInfo->srcPort * tcpInfo->dstPort;
01101     
01102     return hash % HASH_SIZE;
01103 }
01104 
01105 
01106 /* Get Exisiting SnifferSession from IP and Port */
01107 static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo)
01108 {
01109     SnifferSession* session;
01110     time_t          currTime = time(NULL); 
01111     word32          row = SessionHash(ipInfo, tcpInfo);
01112 
01113     assert(row <= HASH_SIZE);
01114     
01115     wc_LockMutex(&SessionMutex);
01116     
01117     session = SessionTable[row];
01118     while (session) {
01119         if (session->server == ipInfo->src && session->client == ipInfo->dst &&
01120                     session->srvPort == tcpInfo->srcPort &&
01121                     session->cliPort == tcpInfo->dstPort)
01122             break;
01123         if (session->client == ipInfo->src && session->server == ipInfo->dst &&
01124                     session->cliPort == tcpInfo->srcPort &&
01125                     session->srvPort == tcpInfo->dstPort)
01126             break;
01127         
01128         session = session->next;
01129     }
01130 
01131     if (session)
01132         session->lastUsed= currTime; /* keep session alive, remove stale will */
01133                                      /* leave alone */   
01134     wc_UnLockMutex(&SessionMutex);
01135     
01136     /* determine side */
01137     if (session) {
01138         if (ipInfo->dst == session->context->server &&
01139             tcpInfo->dstPort == session->context->port)
01140             session->flags.side = WOLFSSL_SERVER_END;
01141         else
01142             session->flags.side = WOLFSSL_CLIENT_END;
01143     }    
01144     
01145     return session;
01146 }
01147 
01148 
01149 #ifdef HAVE_SNI
01150 
01151 static int LoadKeyFile(byte** keyBuf, word32* keyBufSz,
01152                 const char* keyFile, int typeKey,
01153                 const char* password)
01154 {
01155     byte* loadBuf;
01156     long fileSz = 0;
01157     XFILE file;
01158     int ret;
01159 
01160     if (keyBuf == NULL || keyBufSz == NULL || keyFile == NULL) {
01161         return -1;
01162     }
01163 
01164     file = XFOPEN(keyFile, "rb");
01165     if (file == XBADFILE) return -1;
01166     XFSEEK(file, 0, XSEEK_END);
01167     fileSz = XFTELL(file);
01168     XREWIND(file);
01169 
01170     loadBuf = (byte*)malloc(fileSz);
01171     if (loadBuf == NULL) {
01172         XFCLOSE(file);
01173         return -1;
01174     }
01175 
01176     ret = (int)XFREAD(loadBuf, 1, fileSz, file);
01177     XFCLOSE(file);
01178 
01179     if (ret != fileSz) {
01180         free(loadBuf);
01181         return -1;
01182     }
01183 
01184     if (typeKey == SSL_FILETYPE_PEM) {
01185         byte* saveBuf   = (byte*)malloc(fileSz);
01186         int   saveBufSz = 0;
01187 
01188         ret = -1;
01189         if (saveBuf != NULL) {
01190             saveBufSz = wolfSSL_KeyPemToDer(loadBuf, (int)fileSz,
01191                                                 saveBuf, (int)fileSz, password);
01192             if (saveBufSz < 0) {
01193                 saveBufSz = 0;
01194                 free(saveBuf);
01195                 saveBuf = NULL;
01196             }
01197             else
01198                 ret = 0;
01199         }
01200 
01201         ForceZero(loadBuf, (word32)fileSz);
01202         free(loadBuf);
01203 
01204         if (saveBuf) {
01205             *keyBuf = saveBuf;
01206             *keyBufSz = (word32)saveBufSz;
01207         }
01208     }
01209     else {
01210         *keyBuf = loadBuf;
01211         *keyBufSz = (word32)fileSz;
01212     }
01213 
01214     if (ret < 0) {
01215         return -1;
01216     }
01217 
01218     return ret;
01219 }
01220 
01221 #endif
01222 
01223 
01224 static int SetNamedPrivateKey(const char* name, const char* address, int port,
01225             const char* keyFile, int typeKey, const char* password, char* error)
01226 {
01227     SnifferServer* sniffer;
01228     int            ret;
01229     int            type = (typeKey == FILETYPE_PEM) ? SSL_FILETYPE_PEM :
01230                                                       SSL_FILETYPE_ASN1;
01231     int            isNew = 0;
01232     word32         serverIp;
01233 
01234 #ifdef HAVE_SNI
01235     NamedKey* namedKey = NULL;
01236 #endif
01237 
01238     (void)name;
01239 #ifdef HAVE_SNI
01240     if (name != NULL) {
01241         namedKey = (NamedKey*)malloc(sizeof(NamedKey));
01242         if (namedKey == NULL) {
01243             SetError(MEMORY_STR, error, NULL, 0);
01244             return -1;
01245         }
01246         XMEMSET(namedKey, 0, sizeof(NamedKey));
01247 
01248         namedKey->nameSz = (word32)XSTRLEN(name);
01249         XSTRNCPY(namedKey->name, name, sizeof(namedKey->name));
01250         if (namedKey->nameSz >= sizeof(namedKey->name)) {
01251             namedKey->nameSz = sizeof(namedKey->name) - 1;
01252             namedKey->name[namedKey->nameSz] = '\0';
01253         }
01254 
01255         ret = LoadKeyFile(&namedKey->key, &namedKey->keySz,
01256                           keyFile, type, password);
01257         if (ret < 0) {
01258             SetError(KEY_FILE_STR, error, NULL, 0);
01259             FreeNamedKey(namedKey);
01260             return -1;
01261         }
01262     }
01263 #endif
01264 
01265     serverIp = inet_addr(address);
01266     sniffer = ServerList;
01267     while (sniffer != NULL &&
01268            (sniffer->server != serverIp || sniffer->port != port)) {
01269         sniffer = sniffer->next;
01270     }
01271 
01272     if (sniffer == NULL) {
01273         isNew = 1;
01274         sniffer = (SnifferServer*)malloc(sizeof(SnifferServer));
01275         if (sniffer == NULL) {
01276             SetError(MEMORY_STR, error, NULL, 0);
01277 #ifdef HAVE_SNI
01278             FreeNamedKey(namedKey);
01279 #endif
01280             return -1;
01281         }
01282         InitSnifferServer(sniffer);
01283 
01284         XSTRNCPY(sniffer->address, address, MAX_SERVER_ADDRESS-1);
01285         sniffer->address[MAX_SERVER_ADDRESS-1] = '\0';
01286         sniffer->server = serverIp;
01287         sniffer->port = port;
01288 
01289         sniffer->ctx = SSL_CTX_new(TLSv1_client_method());
01290         if (!sniffer->ctx) {
01291             SetError(MEMORY_STR, error, NULL, 0);
01292 #ifdef HAVE_SNI
01293             FreeNamedKey(namedKey);
01294 #endif
01295             FreeSnifferServer(sniffer);
01296             return -1;
01297         }
01298     }
01299 
01300     if (name == NULL) {
01301         if (password) {
01302             SSL_CTX_set_default_passwd_cb(sniffer->ctx, SetPassword);
01303             SSL_CTX_set_default_passwd_cb_userdata(
01304                                                  sniffer->ctx, (void*)password);
01305         }
01306         ret = SSL_CTX_use_PrivateKey_file(sniffer->ctx, keyFile, type);
01307         if (ret != SSL_SUCCESS) {
01308             SetError(KEY_FILE_STR, error, NULL, 0);
01309             if (isNew)
01310                 FreeSnifferServer(sniffer);
01311             return -1;
01312         }
01313     }
01314 #ifdef HAVE_SNI
01315     else {
01316         wc_LockMutex(&sniffer->namedKeysMutex);
01317         namedKey->next = sniffer->namedKeys;
01318         sniffer->namedKeys = namedKey;
01319         wc_UnLockMutex(&sniffer->namedKeysMutex);
01320     }
01321 #endif
01322 
01323     if (isNew) {
01324         sniffer->next = ServerList;
01325         ServerList = sniffer;
01326     }
01327 
01328     return 0;
01329 }
01330 
01331 
01332 #ifdef HAVE_SNI
01333 
01334 /* Sets the private key for a specific name, server and port  */
01335 /* returns 0 on success, -1 on error */
01336 int ssl_SetNamedPrivateKey(const char* name,
01337                            const char* address, int port,
01338                            const char* keyFile, int typeKey,
01339                            const char* password, char* error)
01340 {
01341     int ret;
01342 
01343     TraceHeader();
01344     TraceSetNamedServer(name, address, port, keyFile);
01345 
01346     wc_LockMutex(&ServerListMutex);
01347     ret = SetNamedPrivateKey(name, address, port, keyFile,
01348                              typeKey, password, error);
01349     wc_UnLockMutex(&ServerListMutex);
01350 
01351     if (ret == 0)
01352         Trace(NEW_SERVER_STR);
01353 
01354     return ret;
01355 }
01356 
01357 #endif
01358 
01359 
01360 /* Sets the private key for a specific server and port  */
01361 /* returns 0 on success, -1 on error */
01362 int ssl_SetPrivateKey(const char* address, int port, const char* keyFile,
01363                       int typeKey, const char* password, char* error)
01364 {
01365     int ret;
01366 
01367     TraceHeader();
01368     TraceSetServer(address, port, keyFile);
01369 
01370     wc_LockMutex(&ServerListMutex);
01371     ret = SetNamedPrivateKey(NULL, address, port, keyFile,
01372                              typeKey, password, error);
01373     wc_UnLockMutex(&ServerListMutex);
01374 
01375     if (ret == 0)
01376         Trace(NEW_SERVER_STR);
01377 
01378     return ret;
01379 }
01380 
01381 
01382 /* Check IP Header for IPV4, TCP, and a registered server address */
01383 /* returns 0 on success, -1 on error */
01384 static int CheckIpHdr(IpHdr* iphdr, IpInfo* info, int length, char* error)
01385 {
01386     int    version = IP_V(iphdr);
01387 
01388     TraceIP(iphdr);
01389     Trace(IP_CHECK_STR);
01390 
01391     if (version != IPV4) {
01392         SetError(BAD_IPVER_STR, error, NULL, 0); 
01393         return -1;
01394     }
01395 
01396     if (iphdr->protocol != TCP_PROTOCOL) { 
01397         SetError(BAD_PROTO_STR, error, NULL, 0);
01398         return -1;
01399     }
01400 
01401     if (!IsServerRegistered(iphdr->src) && !IsServerRegistered(iphdr->dst)) {
01402         SetError(SERVER_NOT_REG_STR, error, NULL, 0);
01403         return -1;
01404     }
01405 
01406     info->length  = IP_HL(iphdr);
01407     info->total   = ntohs(iphdr->length);
01408     info->src     = iphdr->src;
01409     info->dst     = iphdr->dst;
01410 
01411     if (info->total == 0)
01412         info->total = length;  /* reassembled may be off */
01413 
01414     return 0;
01415 }
01416 
01417 
01418 /* Check TCP Header for a registered port */
01419 /* returns 0 on success, -1 on error */
01420 static int CheckTcpHdr(TcpHdr* tcphdr, TcpInfo* info, char* error)
01421 {
01422     TraceTcp(tcphdr);
01423     Trace(TCP_CHECK_STR);
01424     info->srcPort   = ntohs(tcphdr->srcPort);
01425     info->dstPort   = ntohs(tcphdr->dstPort);
01426     info->length    = TCP_LEN(tcphdr);
01427     info->sequence  = ntohl(tcphdr->sequence);
01428     info->fin       = tcphdr->flags & TCP_FIN;
01429     info->rst       = tcphdr->flags & TCP_RST;
01430     info->syn       = tcphdr->flags & TCP_SYN;
01431     info->ack       = tcphdr->flags & TCP_ACK;
01432     if (info->ack)
01433         info->ackNumber = ntohl(tcphdr->ack); 
01434 
01435     if (!IsPortRegistered(info->srcPort) && !IsPortRegistered(info->dstPort)) {
01436         SetError(SERVER_PORT_NOT_REG_STR, error, NULL, 0);
01437         return -1;
01438     }
01439 
01440     return 0;
01441 }
01442 
01443 
01444 /* Decode Record Layer Header */
01445 static int GetRecordHeader(const byte* input, RecordLayerHeader* rh, int* size)
01446 {
01447     XMEMCPY(rh, input, RECORD_HEADER_SZ);
01448     *size = (rh->length[0] << 8) | rh->length[1];
01449 
01450     if (*size > (MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA))
01451         return LENGTH_ERROR;
01452 
01453     return 0;
01454 }
01455 
01456 
01457 /* Process Client Key Exchange, RSA only */
01458 static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
01459                                     SnifferSession* session, char* error)
01460 {
01461     word32 idx = 0;
01462     RsaKey key;
01463     int    ret;
01464 
01465     if (session->sslServer->buffers.key == NULL ||
01466         session->sslServer->buffers.key->buffer == NULL ||
01467         session->sslServer->buffers.key->length == 0) {
01468 
01469         SetError(RSA_KEY_MISSING_STR, error, session, FATAL_ERROR_STATE);
01470         return -1;
01471     }
01472     ret = wc_InitRsaKey(&key, 0);
01473     if (ret == 0)
01474         ret = wc_RsaPrivateKeyDecode(session->sslServer->buffers.key->buffer,
01475                           &idx, &key, session->sslServer->buffers.key->length);
01476     if (ret == 0) {
01477         int length = wc_RsaEncryptSize(&key);
01478 
01479         if (IsTLS(session->sslServer))
01480             input += 2;     /* tls pre length */
01481 
01482         if (length > *sslBytes) {
01483             SetError(PARTIAL_INPUT_STR, error, session, FATAL_ERROR_STATE);
01484             wc_FreeRsaKey(&key);
01485             return -1;
01486         }
01487         #ifdef WC_RSA_BLINDING
01488             ret = wc_RsaSetRNG(&key, session->sslServer->rng);
01489             if (ret != 0) {
01490                 SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE);
01491                 return -1;
01492             }
01493         #endif
01494         ret = wc_RsaPrivateDecrypt(input, length,
01495                   session->sslServer->arrays->preMasterSecret,SECRET_LEN, &key);
01496 
01497         if (ret != SECRET_LEN) {
01498             SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE);
01499             wc_FreeRsaKey(&key);
01500             return -1;
01501         }
01502         session->sslServer->arrays->preMasterSz = SECRET_LEN;
01503 
01504         /* store for client side as well */
01505         XMEMCPY(session->sslClient->arrays->preMasterSecret,
01506                session->sslServer->arrays->preMasterSecret, SECRET_LEN);
01507         session->sslClient->arrays->preMasterSz = SECRET_LEN;
01508 
01509         #ifdef SHOW_SECRETS
01510         {
01511             int i;
01512             printf("pre master secret: ");
01513             for (i = 0; i < SECRET_LEN; i++)
01514                 printf("%02x", session->sslServer->arrays->preMasterSecret[i]);
01515             printf("\n");
01516         }
01517         #endif
01518     }
01519     else {
01520         SetError(RSA_DECODE_STR, error, session, FATAL_ERROR_STATE);
01521         wc_FreeRsaKey(&key);
01522         return -1;
01523     }
01524 
01525     if (SetCipherSpecs(session->sslServer) != 0) {
01526         SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
01527         wc_FreeRsaKey(&key);
01528         return -1;
01529     }
01530 
01531     if (SetCipherSpecs(session->sslClient) != 0) {
01532         SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
01533         wc_FreeRsaKey(&key);
01534         return -1;
01535     }
01536 
01537     ret  = MakeMasterSecret(session->sslServer);
01538     ret += MakeMasterSecret(session->sslClient);
01539     ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE);
01540     ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE);
01541 
01542     if (ret != 0) {
01543         SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE);
01544         return -1;
01545     }
01546 
01547 #ifdef SHOW_SECRETS
01548     {
01549         int i;
01550         printf("server master secret: ");
01551         for (i = 0; i < SECRET_LEN; i++)
01552             printf("%02x", session->sslServer->arrays->masterSecret[i]);
01553         printf("\n");
01554 
01555         printf("client master secret: ");
01556         for (i = 0; i < SECRET_LEN; i++)
01557             printf("%02x", session->sslClient->arrays->masterSecret[i]);
01558         printf("\n");
01559 
01560         printf("server suite = %d\n", session->sslServer->options.cipherSuite);
01561         printf("client suite = %d\n", session->sslClient->options.cipherSuite);
01562     }
01563 #endif
01564 
01565     wc_FreeRsaKey(&key);
01566     return ret;
01567 }
01568 
01569 
01570 /* Process Session Ticket */
01571 static int ProcessSessionTicket(const byte* input, int* sslBytes,
01572                                 SnifferSession* session, char* error)
01573 {
01574     word16 len;
01575 
01576     /* make sure can read through hint and len */
01577     if (TICKET_HINT_LEN + LENGTH_SZ > *sslBytes) {
01578         SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
01579         return -1;
01580     }
01581 
01582     input     += TICKET_HINT_LEN;  /* skip over hint */
01583     *sslBytes -= TICKET_HINT_LEN;
01584 
01585     len = (word16)((input[0] << 8) | input[1]);
01586     input     += LENGTH_SZ;
01587     *sslBytes -= LENGTH_SZ;
01588 
01589     /* make sure can read through ticket */
01590     if (len > *sslBytes || len < ID_LEN) {
01591         SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
01592         return -1;
01593     }
01594 
01595     /* store session with macID as sessionID */
01596     session->sslServer->options.haveSessionId = 1;
01597     XMEMCPY(session->sslServer->arrays->sessionID, input + len - ID_LEN,ID_LEN);
01598 
01599     return 0;
01600 }
01601 
01602 
01603 /* Process Server Hello */
01604 static int ProcessServerHello(int msgSz, const byte* input, int* sslBytes,
01605                               SnifferSession* session, char* error)
01606 {
01607     ProtocolVersion pv;
01608     byte            b;
01609     int             toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
01610     int             doResume     = 0;
01611     int             initialBytes = *sslBytes;
01612 
01613     (void)msgSz;
01614     (void)initialBytes;
01615 
01616     /* make sure we didn't miss ClientHello */
01617     if (session->flags.clientHello == 0) {
01618         SetError(MISSED_CLIENT_HELLO_STR, error, session, FATAL_ERROR_STATE);
01619         return -1;
01620     }
01621 
01622     /* make sure can read through session len */
01623     if (toRead > *sslBytes) {
01624         SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
01625         return -1;
01626     }
01627 
01628     XMEMCPY(&pv, input, VERSION_SZ);
01629     input     += VERSION_SZ;
01630     *sslBytes -= VERSION_SZ;
01631 
01632     session->sslServer->version = pv;
01633     session->sslClient->version = pv;
01634 
01635     XMEMCPY(session->sslServer->arrays->serverRandom, input, RAN_LEN);
01636     XMEMCPY(session->sslClient->arrays->serverRandom, input, RAN_LEN);
01637     input    += RAN_LEN;
01638     *sslBytes -= RAN_LEN;
01639 
01640     b = *input++;
01641     *sslBytes -= 1;
01642 
01643     /* make sure can read through compression */
01644     if ( (b + SUITE_LEN + ENUM_LEN) > *sslBytes) {
01645         SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
01646         return -1;
01647     }
01648     if (b) {
01649         XMEMCPY(session->sslServer->arrays->sessionID, input, ID_LEN);
01650         session->sslServer->options.haveSessionId = 1;
01651     }
01652     input     += b;
01653     *sslBytes -= b;
01654 
01655     /* cipher suite */
01656     b = *input++;  /* first byte, ECC or not */
01657     session->sslServer->options.cipherSuite0 = b;
01658     session->sslClient->options.cipherSuite0 = b;
01659     b = *input++;
01660     session->sslServer->options.cipherSuite = b;
01661     session->sslClient->options.cipherSuite = b;
01662     *sslBytes -= SUITE_LEN;
01663 
01664     /* compression */
01665     b = *input++;
01666     *sslBytes -= ENUM_LEN;
01667 
01668     if (b) {
01669         SetError(BAD_COMPRESSION_STR, error, session, FATAL_ERROR_STATE);
01670         return -1;
01671     }
01672 
01673 #ifdef HAVE_EXTENDED_MASTER
01674     /* extensions */
01675     if ((initialBytes - *sslBytes) < msgSz) {
01676         word16 len;
01677 
01678         /* skip extensions until extended master secret */
01679         /* make sure can read len */
01680         if (SUITE_LEN > *sslBytes) {
01681             SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
01682             return -1;
01683         }
01684         len = (word16)((input[0] << 8) | input[1]);
01685         input     += SUITE_LEN;
01686         *sslBytes -= SUITE_LEN;
01687         /* make sure can read through all extensions */
01688         if (len > *sslBytes) {
01689             SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
01690             return -1;
01691         }
01692 
01693         while (len >= EXT_TYPE_SZ + LENGTH_SZ) {
01694             byte   extType[EXT_TYPE_SZ];
01695             word16 extLen;
01696 
01697             extType[0] = input[0];
01698             extType[1] = input[1];
01699             input     += EXT_TYPE_SZ;
01700             *sslBytes -= EXT_TYPE_SZ;
01701 
01702             extLen = (word16)((input[0] << 8) | input[1]);
01703             input     += LENGTH_SZ;
01704             *sslBytes -= LENGTH_SZ;
01705 
01706             /* make sure can read through individual extension */
01707             if (extLen > *sslBytes) {
01708                 SetError(SERVER_HELLO_INPUT_STR, error, session,
01709                          FATAL_ERROR_STATE);
01710                 return -1;
01711             }
01712 
01713             if (extType[0] == 0x00 && extType[1] == EXT_MASTER_SECRET) {
01714                 session->flags.expectEms = 1;
01715             }
01716 
01717             input     += extLen;
01718             *sslBytes -= extLen;
01719             len       -= extLen + EXT_TYPE_SZ + LENGTH_SZ;
01720         }
01721     }
01722 
01723     if (!session->flags.expectEms) {
01724         free(session->hash);
01725         session->hash = NULL;
01726     }
01727 #endif
01728 
01729     if (session->sslServer->options.haveSessionId &&
01730             XMEMCMP(session->sslServer->arrays->sessionID,
01731                     session->sslClient->arrays->sessionID, ID_LEN) == 0)
01732         doResume = 1;
01733     else if (session->sslClient->options.haveSessionId == 0 &&
01734              session->sslServer->options.haveSessionId == 0 &&
01735              session->ticketID)
01736         doResume = 1;
01737 
01738     if (session->ticketID && doResume) {
01739         /* use ticketID to retrieve from session, prefer over sessionID */
01740         XMEMCPY(session->sslServer->arrays->sessionID,session->ticketID,ID_LEN);
01741         session->sslServer->options.haveSessionId = 1;  /* may not have
01742                                                            actual sessionID */
01743     }
01744 
01745     if (doResume ) {
01746         int ret = 0;
01747         SSL_SESSION* resume = GetSession(session->sslServer,
01748                                   session->sslServer->arrays->masterSecret, 0);
01749         if (resume == NULL) {
01750             SetError(BAD_SESSION_RESUME_STR, error, session, FATAL_ERROR_STATE);
01751             return -1;
01752         }
01753         /* make sure client has master secret too */
01754         XMEMCPY(session->sslClient->arrays->masterSecret,
01755                session->sslServer->arrays->masterSecret, SECRET_LEN);
01756         session->flags.resuming = 1;
01757 
01758         Trace(SERVER_DID_RESUMPTION_STR);
01759         if (SetCipherSpecs(session->sslServer) != 0) {
01760             SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
01761             return -1;
01762         }
01763 
01764         if (SetCipherSpecs(session->sslClient) != 0) {
01765             SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
01766             return -1;
01767         }
01768 
01769         if (session->sslServer->options.tls) {
01770             ret =  DeriveTlsKeys(session->sslServer);
01771             ret += DeriveTlsKeys(session->sslClient);
01772         }
01773         else {
01774             ret =  DeriveKeys(session->sslServer);
01775             ret += DeriveKeys(session->sslClient);
01776         }
01777         ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE);
01778         ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE);
01779 
01780         if (ret != 0) {
01781             SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE);
01782             return -1;
01783         }
01784     }
01785 #ifdef SHOW_SECRETS
01786     {
01787         int i;
01788         printf("cipher suite = 0x%02x\n",
01789                session->sslServer->options.cipherSuite);
01790         printf("server random: ");
01791         for (i = 0; i < RAN_LEN; i++)
01792             printf("%02x", session->sslServer->arrays->serverRandom[i]);
01793         printf("\n");
01794     }
01795 #endif
01796     return 0;
01797 }
01798 
01799 
01800 /* Process normal Client Hello */
01801 static int ProcessClientHello(const byte* input, int* sslBytes,
01802                               SnifferSession* session, char* error)
01803 {
01804     byte   bLen;
01805     word16 len;
01806     int    toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
01807 
01808 #ifdef HAVE_SNI
01809     {
01810         byte name[MAX_SERVER_NAME];
01811         word32 nameSz = sizeof(name);
01812         int ret;
01813 
01814         ret = wolfSSL_SNI_GetFromBuffer(
01815                              input - HANDSHAKE_HEADER_SZ - RECORD_HEADER_SZ,
01816                              *sslBytes + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ,
01817                              WOLFSSL_SNI_HOST_NAME, name, &nameSz);
01818 
01819         if (ret == SSL_SUCCESS) {
01820             NamedKey* namedKey;
01821 
01822             if (nameSz >= sizeof(name))
01823                 nameSz = sizeof(name) - 1;
01824             name[nameSz] = 0;
01825             wc_LockMutex(&session->context->namedKeysMutex);
01826             namedKey = session->context->namedKeys;
01827             while (namedKey != NULL) {
01828                 if (nameSz == namedKey->nameSz &&
01829                            XSTRNCMP((char*)name, namedKey->name, nameSz) == 0) {
01830                     if (wolfSSL_use_PrivateKey_buffer(session->sslServer,
01831                                             namedKey->key, namedKey->keySz,
01832                                             SSL_FILETYPE_ASN1) != SSL_SUCCESS) {
01833                         wc_UnLockMutex(&session->context->namedKeysMutex);
01834                         SetError(CLIENT_HELLO_LATE_KEY_STR, error, session,
01835                                                              FATAL_ERROR_STATE);
01836                         return -1;
01837                     }
01838                     break;
01839                 }
01840                 else
01841                     namedKey = namedKey->next;
01842             }
01843             wc_UnLockMutex(&session->context->namedKeysMutex);
01844         }
01845     }
01846 #endif
01847 
01848     session->flags.clientHello = 1;  /* don't process again */
01849 
01850     /* make sure can read up to session len */
01851     if (toRead > *sslBytes) {
01852         SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
01853         return -1;
01854     }
01855 
01856     /* skip, get negotiated one from server hello */
01857     input     += VERSION_SZ;
01858     *sslBytes -= VERSION_SZ;
01859 
01860     XMEMCPY(session->sslServer->arrays->clientRandom, input, RAN_LEN);
01861     XMEMCPY(session->sslClient->arrays->clientRandom, input, RAN_LEN);
01862 
01863     input     += RAN_LEN;
01864     *sslBytes -= RAN_LEN;
01865 
01866     /* store session in case trying to resume */
01867     bLen = *input++;
01868     *sslBytes -= ENUM_LEN;
01869     if (bLen) {
01870         if (ID_LEN > *sslBytes) {
01871             SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
01872             return -1;
01873         }
01874         Trace(CLIENT_RESUME_TRY_STR);
01875         XMEMCPY(session->sslClient->arrays->sessionID, input, ID_LEN);
01876         session->sslClient->options.haveSessionId = 1;
01877     }
01878 #ifdef SHOW_SECRETS
01879     {
01880         int i;
01881         printf("client random: ");
01882         for (i = 0; i < RAN_LEN; i++)
01883             printf("%02x", session->sslServer->arrays->clientRandom[i]);
01884         printf("\n");
01885     }
01886 #endif
01887 
01888     input     += bLen;
01889     *sslBytes -= bLen;
01890 
01891     /* skip cipher suites */
01892     /* make sure can read len */
01893     if (SUITE_LEN > *sslBytes) {
01894         SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
01895         return -1;
01896     }
01897     len = (word16)((input[0] << 8) | input[1]);
01898     input     += SUITE_LEN;
01899     *sslBytes -= SUITE_LEN;
01900     /* make sure can read suites + comp len */
01901     if (len + ENUM_LEN > *sslBytes) {
01902         SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
01903         return -1;
01904     }
01905     input     += len;
01906     *sslBytes -= len;
01907 
01908     /* skip compression */
01909     bLen       = *input++;
01910     *sslBytes -= ENUM_LEN;
01911     /* make sure can read len */
01912     if (bLen > *sslBytes) {
01913         SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
01914         return -1;
01915     }
01916     input     += bLen;
01917     *sslBytes -= bLen;
01918   
01919     if (*sslBytes == 0) {
01920         /* no extensions */
01921         return 0;
01922     }
01923     
01924     /* skip extensions until session ticket */
01925     /* make sure can read len */
01926     if (SUITE_LEN > *sslBytes) {
01927         SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
01928         return -1;
01929     }
01930     len = (word16)((input[0] << 8) | input[1]);
01931     input     += SUITE_LEN;
01932     *sslBytes -= SUITE_LEN;
01933     /* make sure can read through all extensions */
01934     if (len > *sslBytes) {
01935         SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
01936         return -1;
01937     }
01938 
01939     while (len >= EXT_TYPE_SZ + LENGTH_SZ) {
01940         byte   extType[EXT_TYPE_SZ];
01941         word16 extLen;
01942 
01943         extType[0] = input[0];
01944         extType[1] = input[1];
01945         input     += EXT_TYPE_SZ;
01946         *sslBytes -= EXT_TYPE_SZ;
01947 
01948         extLen = (word16)((input[0] << 8) | input[1]);
01949         input     += LENGTH_SZ;
01950         *sslBytes -= LENGTH_SZ;
01951 
01952         /* make sure can read through individual extension */
01953         if (extLen > *sslBytes) {
01954             SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
01955             return -1;
01956         }
01957 
01958         if (extType[0] == 0x00 && extType[1] == TICKET_EXT_ID) {
01959 
01960             /* make sure can read through ticket if there is a non blank one */
01961             if (extLen && extLen < ID_LEN) {
01962                 SetError(CLIENT_HELLO_INPUT_STR, error, session,
01963                          FATAL_ERROR_STATE);
01964                 return -1;
01965             }
01966 
01967             if (extLen) {
01968                 if (session->ticketID == 0) {
01969                     session->ticketID = (byte*)malloc(ID_LEN);
01970                     if (session->ticketID == 0) {
01971                         SetError(MEMORY_STR, error, session,
01972                                  FATAL_ERROR_STATE);
01973                         return -1;
01974                     }
01975                 }
01976                 XMEMCPY(session->ticketID, input + extLen - ID_LEN, ID_LEN);
01977             }
01978         }
01979 
01980         input     += extLen;
01981         *sslBytes -= extLen;
01982         len       -= extLen + EXT_TYPE_SZ + LENGTH_SZ;
01983     }
01984 
01985     return 0;
01986 }
01987 
01988 
01989 /* Process Finished */
01990 static int ProcessFinished(const byte* input, int size, int* sslBytes,
01991                            SnifferSession* session, char* error)
01992 {
01993     SSL*   ssl;
01994     word32 inOutIdx = 0;
01995     int    ret;
01996                 
01997     if (session->flags.side == WOLFSSL_SERVER_END)
01998         ssl = session->sslServer;
01999     else
02000         ssl = session->sslClient;
02001 
02002     ret = DoFinished(ssl, input, &inOutIdx, (word32) size, (word32) *sslBytes,
02003                                                                          SNIFF);
02004     *sslBytes -= (int)inOutIdx;
02005 
02006     if (ret < 0) {
02007         SetError(BAD_FINISHED_MSG, error, session, FATAL_ERROR_STATE);
02008         return ret;
02009     }
02010                 
02011     if (ret == 0 && session->flags.cached == 0) {
02012         if (session->sslServer->options.haveSessionId) {
02013             WOLFSSL_SESSION* sess = GetSession(session->sslServer, NULL, 0);
02014             if (sess == NULL)
02015                 AddSession(session->sslServer);  /* don't re add */
02016             session->flags.cached = 1;
02017          }
02018     }
02019 
02020     /* If receiving a finished message from one side, free the resources
02021      * from the other side's tracker. */
02022     if (session->flags.side == WOLFSSL_SERVER_END)
02023         FreeHandshakeResources(session->sslClient);
02024     else
02025         FreeHandshakeResources(session->sslServer);
02026 
02027     return ret;
02028 }
02029 
02030 
02031 /* Process HandShake input */
02032 static int DoHandShake(const byte* input, int* sslBytes,
02033                        SnifferSession* session, char* error)
02034 {
02035     byte type;
02036     int  size;
02037     int  ret = 0;
02038     int  startBytes;
02039 
02040     if (*sslBytes < HANDSHAKE_HEADER_SZ) {
02041         SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE);
02042         return -1;
02043     }
02044     type = input[0];
02045     size = (input[1] << 16) | (input[2] << 8) | input[3];
02046     
02047     input     += HANDSHAKE_HEADER_SZ;
02048     *sslBytes -= HANDSHAKE_HEADER_SZ;
02049     startBytes = *sslBytes;
02050 
02051     if (*sslBytes < size) {
02052         SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE);
02053         return -1;
02054     }
02055 
02056     /* A session's arrays are released when the handshake is completed. */
02057     if (session->sslServer->arrays == NULL &&
02058         session->sslClient->arrays == NULL) {
02059 
02060         SetError(NO_SECURE_RENEGOTIATION, error, session, FATAL_ERROR_STATE);
02061         return -1;
02062     }
02063     
02064 #ifdef HAVE_EXTENDED_MASTER
02065     if (session->hash) {
02066         if (HashUpdate(session->hash, input, size) != 0) {
02067             SetError(EXTENDED_MASTER_HASH_STR, error,
02068                      session, FATAL_ERROR_STATE);
02069             return -1;
02070         }
02071     }
02072 #endif
02073 
02074     switch (type) {
02075         case hello_verify_request:
02076             Trace(GOT_HELLO_VERIFY_STR);
02077             break;
02078         case hello_request:
02079             Trace(GOT_HELLO_REQUEST_STR);
02080             break;
02081         case session_ticket:
02082             Trace(GOT_SESSION_TICKET_STR);
02083             ret = ProcessSessionTicket(input, sslBytes, session, error);
02084             break;
02085         case server_hello:
02086             Trace(GOT_SERVER_HELLO_STR);
02087             ret = ProcessServerHello(size, input, sslBytes, session, error);
02088             break;
02089         case certificate_request:
02090             Trace(GOT_CERT_REQ_STR);
02091             break;
02092         case server_key_exchange:
02093             Trace(GOT_SERVER_KEY_EX_STR);
02094             /* can't know temp key passively */
02095             SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
02096             ret = -1;
02097             break;
02098         case certificate:
02099             Trace(GOT_CERT_STR);
02100             break;
02101         case server_hello_done:
02102             Trace(GOT_SERVER_HELLO_DONE_STR);
02103             break;
02104         case finished:
02105             Trace(GOT_FINISHED_STR);
02106             ret = ProcessFinished(input, size, sslBytes, session, error);
02107             break;
02108         case client_hello:
02109             Trace(GOT_CLIENT_HELLO_STR);
02110             ret = ProcessClientHello(input, sslBytes, session, error);
02111             break;
02112         case client_key_exchange:
02113             Trace(GOT_CLIENT_KEY_EX_STR);
02114 #ifdef HAVE_EXTENDED_MASTER
02115             if (session->flags.expectEms && session->hash != NULL) {
02116                 if (HashCopy(session->sslServer->hsHashes,
02117                              session->hash) == 0 &&
02118                     HashCopy(session->sslClient->hsHashes,
02119                              session->hash) == 0) {
02120 
02121                     session->sslServer->options.haveEMS = 1;
02122                     session->sslClient->options.haveEMS = 1;
02123                 }
02124                 else {
02125                     SetError(EXTENDED_MASTER_HASH_STR, error,
02126                              session, FATAL_ERROR_STATE);
02127                     ret = -1;
02128                 }
02129                 XMEMSET(session->hash, 0, sizeof(HsHashes));
02130                 free(session->hash);
02131                 session->hash = NULL;
02132             }
02133             else {
02134                 session->sslServer->options.haveEMS = 0;
02135                 session->sslClient->options.haveEMS = 0;
02136             }
02137 #endif
02138             if (ret == 0)
02139                 ret = ProcessClientKeyExchange(input, sslBytes, session, error);
02140             break;
02141         case certificate_verify:
02142             Trace(GOT_CERT_VER_STR);
02143             break;
02144         case certificate_status:
02145             Trace(GOT_CERT_STATUS_STR);
02146             break;
02147         default:
02148             SetError(GOT_UNKNOWN_HANDSHAKE_STR, error, session, 0);
02149             return -1;
02150     }
02151 
02152     *sslBytes = startBytes - size;  /* actual bytes of full process */
02153 
02154     return ret;
02155 }
02156 
02157 
02158 /* Decrypt input into plain output, 0 on success */
02159 static int Decrypt(SSL* ssl, byte* output, const byte* input, word32 sz)
02160 {
02161     int ret = 0;
02162 
02163     (void)output;
02164     (void)input;
02165     (void)sz;
02166 
02167     switch (ssl->specs.bulk_cipher_algorithm) {
02168         #ifdef BUILD_ARC4
02169         case wolfssl_rc4:
02170             wc_Arc4Process(ssl->decrypt.arc4, output, input, sz);
02171             break;
02172         #endif
02173             
02174         #ifdef BUILD_DES3
02175         case wolfssl_triple_des:
02176             ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, output, input, sz);
02177             break;
02178         #endif
02179             
02180         #ifdef BUILD_AES
02181         case wolfssl_aes:
02182             ret = wc_AesCbcDecrypt(ssl->decrypt.aes, output, input, sz);
02183             break;
02184         #endif
02185             
02186         #ifdef HAVE_HC128
02187         case wolfssl_hc128:
02188             wc_Hc128_Process(ssl->decrypt.hc128, output, input, sz);
02189             break;
02190         #endif
02191             
02192         #ifdef BUILD_RABBIT
02193         case wolfssl_rabbit:
02194             wc_RabbitProcess(ssl->decrypt.rabbit, output, input, sz);
02195             break;
02196         #endif
02197 
02198         #ifdef HAVE_CAMELLIA 
02199         case wolfssl_camellia:
02200             wc_CamelliaCbcDecrypt(ssl->decrypt.cam, output, input, sz);
02201             break;
02202         #endif
02203 
02204         #ifdef HAVE_IDEA
02205         case wolfssl_idea:
02206             wc_IdeaCbcDecrypt(ssl->decrypt.idea, output, input, sz);
02207             break;
02208         #endif
02209 
02210         #ifdef HAVE_AESGCM
02211         case wolfssl_aes_gcm:
02212             if (sz >= (word32)(AESGCM_EXP_IV_SZ + ssl->specs.aead_mac_size))
02213             {
02214                 /* scratch buffer, sniffer ignores auth tag*/
02215                 byte authTag[WOLFSSL_MIN_AUTH_TAG_SZ];
02216 
02217                 byte nonce[AESGCM_NONCE_SZ];
02218                 XMEMCPY(nonce, ssl->keys.aead_dec_imp_IV, AESGCM_IMP_IV_SZ);
02219                 XMEMCPY(nonce + AESGCM_IMP_IV_SZ, input, AESGCM_EXP_IV_SZ);
02220 
02221                 if (wc_AesGcmEncrypt(ssl->decrypt.aes,
02222                             output,
02223                             input + AESGCM_EXP_IV_SZ,
02224                             sz - AESGCM_EXP_IV_SZ - ssl->specs.aead_mac_size,
02225                             nonce, AESGCM_NONCE_SZ,
02226                             authTag, sizeof(authTag),
02227                             NULL, 0) < 0) {
02228                     Trace(BAD_DECRYPT);
02229                     ret = -1;
02230                 }
02231                 ForceZero(nonce, AESGCM_NONCE_SZ);
02232             }
02233             else {
02234                 Trace(BAD_DECRYPT_SIZE);
02235                 ret = -1;
02236             }
02237             break;
02238          #endif
02239 
02240         default:
02241             Trace(BAD_DECRYPT_TYPE);
02242             ret = -1;
02243             break;
02244     }
02245 
02246     return ret;
02247 }
02248 
02249 
02250 /* Decrypt input message into output, adjust output steam if needed */
02251 static const byte* DecryptMessage(SSL* ssl, const byte* input, word32 sz,
02252                                   byte* output, int* error, int* advance)
02253 {
02254     int ivExtra = 0;
02255 
02256     int ret = Decrypt(ssl, output, input, sz);
02257     if (ret != 0) {
02258         *error = ret;
02259         return NULL;
02260     }
02261     ssl->keys.encryptSz = sz;
02262     if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) {
02263         output += ssl->specs.block_size;     /* go past TLSv1.1 IV */
02264         ivExtra = ssl->specs.block_size;
02265         *advance = ssl->specs.block_size;
02266     }
02267 
02268     if (ssl->specs.cipher_type == aead) {
02269         *advance = ssl->specs.aead_mac_size;
02270         ssl->keys.padSz = ssl->specs.aead_mac_size;
02271     }
02272     else
02273         ssl->keys.padSz = ssl->specs.hash_size;
02274 
02275     if (ssl->specs.cipher_type == block)
02276         ssl->keys.padSz += *(output + sz - ivExtra - 1) + 1;
02277     
02278     return output;
02279 }
02280 
02281 
02282 /* remove session from table, use rowHint if no info (means we have a lock) */
02283 static void RemoveSession(SnifferSession* session, IpInfo* ipInfo,
02284                         TcpInfo* tcpInfo, word32 rowHint)
02285 {
02286     SnifferSession* previous = 0;
02287     SnifferSession* current;
02288     word32          row = rowHint;
02289     int             haveLock = 0;
02290    
02291     if (ipInfo && tcpInfo)
02292         row = SessionHash(ipInfo, tcpInfo);
02293     else
02294         haveLock = 1;
02295     
02296     assert(row <= HASH_SIZE);
02297     Trace(REMOVE_SESSION_STR);
02298     
02299     if (!haveLock)
02300         wc_LockMutex(&SessionMutex);
02301     
02302     current = SessionTable[row];
02303     
02304     while (current) {
02305         if (current == session) {
02306             if (previous)
02307                 previous->next = current->next;
02308             else
02309                 SessionTable[row] = current->next;
02310             FreeSnifferSession(session);
02311             TraceRemovedSession();
02312             break;
02313         }
02314         previous = current;
02315         current  = current->next;
02316     }
02317     
02318     if (!haveLock)
02319         wc_UnLockMutex(&SessionMutex);
02320 }
02321 
02322 
02323 /* Remove stale sessions from the Session Table, have a lock */
02324 static void RemoveStaleSessions(void)
02325 {
02326     word32 i;
02327     SnifferSession* session;
02328     
02329     for (i = 0; i < HASH_SIZE; i++) {
02330         session = SessionTable[i];
02331         while (session) {
02332             SnifferSession* next = session->next; 
02333             if (time(NULL) >= session->lastUsed + WOLFSSL_SNIFFER_TIMEOUT) {
02334                 TraceStaleSession();
02335                 RemoveSession(session, NULL, NULL, i);
02336             }
02337             session = next;
02338         }
02339     }
02340 }
02341 
02342 
02343 /* Create a new Sniffer Session */
02344 static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
02345                                      char* error)
02346 {
02347     SnifferSession* session = 0;
02348     int row;
02349         
02350     Trace(NEW_SESSION_STR);
02351     /* create a new one */
02352     session = (SnifferSession*)malloc(sizeof(SnifferSession));
02353     if (session == NULL) {
02354         SetError(MEMORY_STR, error, NULL, 0);
02355         return 0;
02356     }
02357     InitSession(session);
02358 #ifdef HAVE_EXTENDED_MASTER
02359     {
02360         HsHashes* newHash = (HsHashes*)malloc(sizeof(HsHashes));
02361         if (newHash == NULL) {
02362             SetError(MEMORY_STR, error, NULL, 0);
02363             free(session);
02364             return 0;
02365         }
02366         if (HashInit(newHash) != 0) {
02367             SetError(EXTENDED_MASTER_HASH_STR, error, NULL, 0);
02368             free(session);
02369             return 0;
02370         }
02371         session->hash = newHash;
02372     }
02373 #endif
02374     session->server  = ipInfo->dst;
02375     session->client  = ipInfo->src;
02376     session->srvPort = (word16)tcpInfo->dstPort;
02377     session->cliPort = (word16)tcpInfo->srcPort;
02378     session->cliSeqStart = tcpInfo->sequence;
02379     session->cliExpected = 1;  /* relative */
02380     session->lastUsed= time(NULL);
02381                 
02382     session->context = GetSnifferServer(ipInfo, tcpInfo);
02383     if (session->context == NULL) {
02384         SetError(SERVER_NOT_REG_STR, error, NULL, 0);
02385         free(session);
02386         return 0;
02387     }
02388         
02389     session->sslServer = SSL_new(session->context->ctx);
02390     if (session->sslServer == NULL) {
02391         SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE);
02392         free(session);
02393         return 0;
02394     }
02395     session->sslClient = SSL_new(session->context->ctx);
02396     if (session->sslClient == NULL) {
02397         SSL_free(session->sslServer);
02398         session->sslServer = 0;
02399 
02400         SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE);
02401         free(session);
02402         return 0;
02403     }
02404     /* put server back into server mode */
02405     session->sslServer->options.side = WOLFSSL_SERVER_END;
02406         
02407     row = SessionHash(ipInfo, tcpInfo);
02408     
02409     /* add it to the session table */
02410     wc_LockMutex(&SessionMutex);
02411         
02412     session->next = SessionTable[row];
02413     SessionTable[row] = session;
02414     
02415     SessionCount++;
02416     
02417     if ( (SessionCount % HASH_SIZE) == 0) {
02418         TraceFindingStale();
02419         RemoveStaleSessions();
02420     }
02421         
02422     wc_UnLockMutex(&SessionMutex);
02423         
02424     /* determine headed side */
02425     if (ipInfo->dst == session->context->server &&
02426         tcpInfo->dstPort == session->context->port)
02427         session->flags.side = WOLFSSL_SERVER_END;
02428     else
02429         session->flags.side = WOLFSSL_CLIENT_END;        
02430     
02431     return session;
02432 }
02433 
02434 
02435 #ifdef OLD_HELLO_ALLOWED
02436 
02437 /* Process Old Client Hello Input */
02438 static int DoOldHello(SnifferSession* session, const byte* sslFrame,
02439                       int* rhSize, int* sslBytes, char* error)
02440 {
02441     const byte* input = sslFrame;
02442     byte        b0, b1;
02443     word32      idx = 0;
02444     int         ret;
02445 
02446     Trace(GOT_OLD_CLIENT_HELLO_STR);
02447     session->flags.clientHello = 1;    /* don't process again */
02448     b0 = *input++;
02449     b1 = *input++;
02450     *sslBytes -= 2;
02451     *rhSize = ((b0 & 0x7f) << 8) | b1;
02452 
02453     if (*rhSize > *sslBytes) {
02454         SetError(OLD_CLIENT_INPUT_STR, error, session, FATAL_ERROR_STATE);
02455         return -1;
02456     }
02457 
02458     ret = ProcessOldClientHello(session->sslServer, input, &idx, *sslBytes,
02459                                 (word16)*rhSize);    
02460     if (ret < 0 && ret != MATCH_SUITE_ERROR) {
02461         SetError(BAD_OLD_CLIENT_STR, error, session, FATAL_ERROR_STATE);
02462         return -1;
02463     }
02464     
02465     Trace(OLD_CLIENT_OK_STR);
02466     XMEMCPY(session->sslClient->arrays->clientRandom,
02467            session->sslServer->arrays->clientRandom, RAN_LEN);
02468     
02469     *sslBytes -= *rhSize;
02470     return 0;
02471 }
02472 
02473 #endif /* OLD_HELLO_ALLOWED */
02474 
02475 
02476 #if 0
02477 /* Calculate the TCP checksum, see RFC 1071 */
02478 /* return 0 for success, -1 on error */
02479 /* can be called from decode() with
02480    TcpChecksum(&ipInfo, &tcpInfo, sslBytes, packet + ipInfo.length);
02481    could also add a 64bit version if type available and using this
02482 */
02483 int TcpChecksum(IpInfo* ipInfo, TcpInfo* tcpInfo, int dataLen,
02484                 const byte* packet)
02485 {
02486     TcpPseudoHdr  pseudo;
02487     int           count = PSEUDO_HDR_SZ;
02488     const word16* data = (word16*)&pseudo;
02489     word32        sum = 0;
02490     word16        checksum;
02491     
02492     pseudo.src = ipInfo->src;
02493     pseudo.dst = ipInfo->dst;
02494     pseudo.rsv = 0;
02495     pseudo.protocol = TCP_PROTO;
02496     pseudo.length = htons(tcpInfo->length + dataLen);
02497     
02498     /* pseudo header sum */
02499     while (count >= 2) {
02500         sum   += *data++;
02501         count -= 2;
02502     }
02503     
02504     count = tcpInfo->length + dataLen;
02505     data = (word16*)packet;
02506     
02507     /* main sum */
02508     while (count > 1) {
02509         sum   += *data++;
02510         count -=2;
02511     }
02512     
02513     /* get left-over, if any */
02514     packet = (byte*)data;
02515     if (count > 0) {
02516         sum += *packet;
02517     }
02518     
02519     /* fold 32bit sum into 16 bits */
02520     while (sum >> 16)
02521         sum = (sum & 0xffff) + (sum >> 16);
02522     
02523     checksum = (word16)~sum;
02524     /* checksum should now equal 0, since included already calcd checksum */
02525     /* field, but tcp checksum offloading could negate calculation */
02526     if (checksum == 0)
02527         return 0;
02528     return -1;
02529 }
02530 #endif
02531 
02532 
02533 /* Check IP and TCP headers, set payload */
02534 /* returns 0 on success, -1 on error */
02535 static int CheckHeaders(IpInfo* ipInfo, TcpInfo* tcpInfo, const byte* packet,
02536                   int length, const byte** sslFrame, int* sslBytes, char* error)
02537 {
02538     TraceHeader();
02539     TracePacket();
02540 
02541     /* ip header */
02542     if (length < IP_HDR_SZ) {
02543         SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
02544         return -1;
02545     }
02546     if (CheckIpHdr((IpHdr*)packet, ipInfo, length, error) != 0)
02547         return -1;
02548    
02549     /* tcp header */ 
02550     if (length < (ipInfo->length + TCP_HDR_SZ)) {
02551         SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
02552         return -1;
02553     }
02554     if (CheckTcpHdr((TcpHdr*)(packet + ipInfo->length), tcpInfo, error) != 0)
02555         return -1;
02556    
02557     /* setup */ 
02558     *sslFrame = packet + ipInfo->length + tcpInfo->length;
02559     if (*sslFrame > packet + length) {
02560         SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
02561         return -1;
02562     }
02563     *sslBytes = (int)(packet + length - *sslFrame);
02564     
02565     return 0;
02566 }
02567 
02568 
02569 /* Create or Find existing session */
02570 /* returns 0 on success (continue), -1 on error, 1 on success (end) */
02571 static int CheckSession(IpInfo* ipInfo, TcpInfo* tcpInfo, int sslBytes,
02572                         SnifferSession** session, char* error)
02573 {
02574     /* create a new SnifferSession on client SYN */
02575     if (tcpInfo->syn && !tcpInfo->ack) {
02576         TraceClientSyn(tcpInfo->sequence);
02577         *session = CreateSession(ipInfo, tcpInfo, error);
02578         if (*session == NULL) {
02579             *session = GetSnifferSession(ipInfo, tcpInfo);
02580             /* already had existing, so OK */
02581             if (*session)
02582                 return 1;
02583             
02584             SetError(MEMORY_STR, error, NULL, 0);
02585             return -1;
02586         }
02587         return 1;
02588     }
02589     /* get existing sniffer session */
02590     else {
02591         *session = GetSnifferSession(ipInfo, tcpInfo);
02592         if (*session == NULL) {
02593             /* don't worry about extraneous RST or duplicate FINs */
02594             if (tcpInfo->fin || tcpInfo->rst)
02595                 return 1;
02596             /* don't worry about duplicate ACKs either */
02597             if (sslBytes == 0 && tcpInfo->ack)
02598                 return 1;
02599             
02600             SetError(BAD_SESSION_STR, error, NULL, 0);
02601             return -1;
02602         }        
02603     }
02604     return 0;
02605 }
02606 
02607 
02608 /* Create a Packet Buffer from *begin - end, adjust new *begin and bytesLeft */
02609 static PacketBuffer* CreateBuffer(word32* begin, word32 end, const byte* data,
02610                                   int* bytesLeft)
02611 {
02612     PacketBuffer* pb;
02613     
02614     int added = end - *begin + 1;
02615     assert(*begin <= end);
02616     
02617     pb = (PacketBuffer*)malloc(sizeof(PacketBuffer));
02618     if (pb == NULL) return NULL;
02619     
02620     pb->next  = 0;
02621     pb->begin = *begin;
02622     pb->end   = end;
02623     pb->data = (byte*)malloc(added);
02624     
02625     if (pb->data == NULL) {
02626         free(pb);
02627         return NULL;
02628     }
02629     XMEMCPY(pb->data, data, added);
02630     
02631     *bytesLeft -= added;
02632     *begin      = pb->end + 1;
02633     
02634     return pb;
02635 }
02636 
02637 
02638 /* Add sslFrame to Reassembly List */
02639 /* returns 1 (end) on success, -1, on error */
02640 static int AddToReassembly(byte from, word32 seq, const byte* sslFrame,
02641                            int sslBytes, SnifferSession* session, char* error)
02642 {
02643     PacketBuffer*  add;
02644     PacketBuffer** front = (from == WOLFSSL_SERVER_END) ?
02645                        &session->cliReassemblyList: &session->srvReassemblyList;
02646     PacketBuffer*  curr = *front;
02647     PacketBuffer*  prev = curr;
02648     
02649     word32* reassemblyMemory = (from == WOLFSSL_SERVER_END) ?
02650                   &session->cliReassemblyMemory : &session->srvReassemblyMemory;
02651     word32  startSeq = seq;
02652     word32  added;
02653     int     bytesLeft = sslBytes;  /* could be overlapping fragment */
02654 
02655     /* if list is empty add full frame to front */
02656     if (!curr) {
02657         if (MaxRecoveryMemory != -1 &&
02658                       (int)(*reassemblyMemory + sslBytes) > MaxRecoveryMemory) {
02659             SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE);
02660             return -1;
02661         }
02662         add = CreateBuffer(&seq, seq + sslBytes - 1, sslFrame, &bytesLeft);
02663         if (add == NULL) {
02664             SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
02665             return -1;
02666         }
02667         *front = add;
02668         *reassemblyMemory += sslBytes;
02669         return 1;
02670     }
02671     
02672     /* add to front if before current front, up to next->begin */
02673     if (seq < curr->begin) {
02674         word32 end = seq + sslBytes - 1;
02675         
02676         if (end >= curr->begin)
02677             end = curr->begin - 1;
02678         
02679         if (MaxRecoveryMemory -1 &&
02680                       (int)(*reassemblyMemory + sslBytes) > MaxRecoveryMemory) {
02681             SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE);
02682             return -1;
02683         }
02684         add = CreateBuffer(&seq, end, sslFrame, &bytesLeft);
02685         if (add == NULL) {
02686             SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
02687             return -1;
02688         }
02689         add->next = curr;
02690         *front = add;
02691         *reassemblyMemory += sslBytes;
02692     }
02693     
02694     /* while we have bytes left, try to find a gap to fill */
02695     while (bytesLeft > 0) {
02696         /* get previous packet in list */
02697         while (curr && (seq >= curr->begin)) {
02698             prev = curr;
02699             curr = curr->next;
02700         }
02701         
02702         /* don't add  duplicate data */
02703         if (prev->end >= seq) {
02704             if ( (seq + bytesLeft - 1) <= prev->end)
02705                 return 1;
02706             seq = prev->end + 1;
02707             bytesLeft = startSeq + sslBytes - seq;
02708         }
02709         
02710         if (!curr)
02711             /* we're at the end */
02712             added = bytesLeft;
02713         else 
02714             /* we're in between two frames */
02715             added = min((word32)bytesLeft, curr->begin - seq);
02716         
02717         /* data already there */
02718         if (added == 0)
02719             continue;
02720         
02721         if (MaxRecoveryMemory != -1 &&
02722                          (int)(*reassemblyMemory + added) > MaxRecoveryMemory) {
02723             SetError(REASSEMBLY_MAX_STR, error, session, FATAL_ERROR_STATE);
02724             return -1;
02725         }
02726         add = CreateBuffer(&seq, seq + added - 1, &sslFrame[seq - startSeq],
02727                            &bytesLeft);
02728         if (add == NULL) {
02729             SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
02730             return -1;
02731         }
02732         add->next  = prev->next;
02733         prev->next = add;
02734         *reassemblyMemory += added;
02735     }
02736     return 1;
02737 }
02738 
02739 
02740 /* Add out of order FIN capture */
02741 /* returns 1 for success (end) */
02742 static int AddFinCapture(SnifferSession* session, word32 sequence)
02743 {
02744     if (session->flags.side == WOLFSSL_SERVER_END) {
02745         if (session->finCaputre.cliCounted == 0)
02746             session->finCaputre.cliFinSeq = sequence;
02747     }
02748     else {
02749         if (session->finCaputre.srvCounted == 0)
02750             session->finCaputre.srvFinSeq = sequence;
02751     }
02752     return 1;
02753 }
02754 
02755 
02756 /* Adjust incoming sequence based on side */
02757 /* returns 0 on success (continue), -1 on error, 1 on success (end) */
02758 static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
02759                           int* sslBytes, const byte** sslFrame, char* error)
02760 {
02761     word32  seqStart = (session->flags.side == WOLFSSL_SERVER_END) ? 
02762                                      session->cliSeqStart :session->srvSeqStart;
02763     word32  real     = tcpInfo->sequence - seqStart;
02764     word32* expected = (session->flags.side == WOLFSSL_SERVER_END) ?
02765                                   &session->cliExpected : &session->srvExpected;
02766     PacketBuffer* reassemblyList = (session->flags.side == WOLFSSL_SERVER_END) ?
02767                         session->cliReassemblyList : session->srvReassemblyList;
02768     byte  skipPartial = (session->flags.side == WOLFSSL_SERVER_END) ?
02769                                 session->flags.srvSkipPartial :
02770                                 session->flags.cliSkipPartial;
02771     
02772     /* handle rollover of sequence */
02773     if (tcpInfo->sequence < seqStart)
02774         real = 0xffffffffU - seqStart + tcpInfo->sequence;
02775         
02776     TraceRelativeSequence(*expected, real);
02777     
02778     if (real < *expected) {
02779         Trace(DUPLICATE_STR);
02780         if (real + *sslBytes > *expected) {
02781             int overlap = *expected - real;
02782             Trace(OVERLAP_DUPLICATE_STR);
02783                 
02784             /* adjust to expected, remove duplicate */
02785             *sslFrame += overlap;
02786             *sslBytes -= overlap;
02787 
02788             /* The following conditional block is duplicated below. It is the
02789              * same action but for a different setup case. If changing this
02790              * block be sure to also update the block below. */
02791             if (reassemblyList) {
02792                 word32 newEnd = *expected + *sslBytes;
02793                     
02794                 if (newEnd > reassemblyList->begin) {
02795                     Trace(OVERLAP_REASSEMBLY_BEGIN_STR);
02796                     
02797                     /* remove bytes already on reassembly list */
02798                     *sslBytes -= newEnd - reassemblyList->begin;
02799                 }
02800                 if (newEnd > reassemblyList->end) {
02801                     Trace(OVERLAP_REASSEMBLY_END_STR);
02802                     
02803                     /* may be past reassembly list end (could have more on list)
02804                        so try to add what's past the front->end */
02805                     AddToReassembly(session->flags.side, reassemblyList->end +1,
02806                                 *sslFrame + reassemblyList->end - *expected + 1,
02807                                  newEnd - reassemblyList->end, session, error);
02808                 }
02809             }
02810         }
02811         else
02812             return 1;
02813     }
02814     else if (real > *expected) {
02815         Trace(OUT_OF_ORDER_STR);
02816         if (*sslBytes > 0) {
02817             int addResult = AddToReassembly(session->flags.side, real,
02818                                           *sslFrame, *sslBytes, session, error);
02819             if (skipPartial) {
02820                 *sslBytes = 0;
02821                 return 0;
02822             }
02823             else
02824                 return addResult;
02825         }
02826         else if (tcpInfo->fin)
02827             return AddFinCapture(session, real);
02828     }
02829     else if (*sslBytes > 0) {
02830         if (skipPartial) {
02831             AddToReassembly(session->flags.side, real,
02832                                           *sslFrame, *sslBytes, session, error);
02833             *expected += *sslBytes;
02834             *sslBytes = 0;
02835             if (tcpInfo->fin)
02836                 *expected += 1;
02837             return 0;
02838         }
02839         /* The following conditional block is duplicated above. It is the
02840          * same action but for a different setup case. If changing this
02841          * block be sure to also update the block above. */
02842         else if (reassemblyList) {
02843             word32 newEnd = *expected + *sslBytes;
02844 
02845             if (newEnd > reassemblyList->begin) {
02846                 Trace(OVERLAP_REASSEMBLY_BEGIN_STR);
02847 
02848                 /* remove bytes already on reassembly list */
02849                 *sslBytes -= newEnd - reassemblyList->begin;
02850             }
02851             if (newEnd > reassemblyList->end) {
02852                 Trace(OVERLAP_REASSEMBLY_END_STR);
02853 
02854                 /* may be past reassembly list end (could have more on list)
02855                    so try to add what's past the front->end */
02856                 AddToReassembly(session->flags.side, reassemblyList->end +1,
02857                             *sslFrame + reassemblyList->end - *expected + 1,
02858                              newEnd - reassemblyList->end, session, error);
02859             }
02860         }
02861     }
02862     /* got expected sequence */
02863     *expected += *sslBytes;
02864     if (tcpInfo->fin)
02865         *expected += 1;
02866     
02867     return 0;
02868 }
02869 
02870 
02871 static int FindNextRecordInAssembly(SnifferSession* session,
02872                                     const byte** sslFrame, int* sslBytes,
02873                                     const byte** end, char* error)
02874 {
02875     PacketBuffer**     front = (session->flags.side == WOLFSSL_SERVER_END) ?
02876                                     &session->cliReassemblyList :
02877                                     &session->srvReassemblyList;
02878     PacketBuffer*       curr = *front;
02879     PacketBuffer*       prev = NULL;
02880     byte*        skipPartial = (session->flags.side == WOLFSSL_SERVER_END) ?
02881                                     &session->flags.srvSkipPartial :
02882                                     &session->flags.cliSkipPartial;
02883     word32* reassemblyMemory = (session->flags.side == WOLFSSL_SERVER_END) ?
02884                                     &session->cliReassemblyMemory :
02885                                     &session->srvReassemblyMemory;
02886     SSL*                 ssl = (session->flags.side == WOLFSSL_SERVER_END) ?
02887                                     session->sslServer :
02888                                     session->sslClient;
02889     ProtocolVersion       pv = ssl->version;
02890     word32*         expected = (session->flags.side == WOLFSSL_SERVER_END) ?
02891                                     &session->cliExpected :
02892                                     &session->srvExpected;
02893 
02894     while (curr != NULL) {
02895         *expected = curr->end + 1;
02896 
02897         if (curr->data[0] == application_data &&
02898             curr->data[1] == pv.major &&
02899             curr->data[2] == pv.minor) {
02900 
02901             if (ssl->buffers.inputBuffer.length > 0)
02902                 Trace(DROPPING_PARTIAL_RECORD);
02903 
02904             *sslBytes = curr->end - curr->begin + 1;
02905             if ( (word32)*sslBytes > ssl->buffers.inputBuffer.bufferSize) {
02906                 if (GrowInputBuffer(ssl, *sslBytes, 0) < 0) {
02907                     SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
02908                     return -1;
02909                 }
02910             }
02911 
02912             XMEMCPY(ssl->buffers.inputBuffer.buffer, curr->data, *sslBytes);
02913 
02914             *front = curr->next;
02915             *reassemblyMemory -= *sslBytes;
02916             FreePacketBuffer(curr);
02917 
02918             ssl->buffers.inputBuffer.length = *sslBytes;
02919             *sslFrame = ssl->buffers.inputBuffer.buffer;
02920             *end = *sslFrame + *sslBytes;
02921             *skipPartial = 0;
02922 
02923             return 0;
02924         }
02925         else if (ssl->specs.cipher_type == block) {
02926             if (ssl->specs.bulk_cipher_algorithm == wolfssl_aes) {
02927 #ifdef BUILD_AES
02928                 wc_AesSetIV(ssl->decrypt.aes,
02929                             curr->data + curr->end - curr->begin
02930                                        - ssl->specs.block_size + 1);
02931 #endif
02932             }
02933             else if (ssl->specs.bulk_cipher_algorithm == wolfssl_triple_des) {
02934 #ifdef BUILD_DES3
02935                 wc_Des3_SetIV(ssl->decrypt.des3,
02936                               curr->data + curr->end - curr->begin
02937                                          - ssl->specs.block_size + 1);
02938 #endif
02939             }
02940         }
02941 
02942         Trace(DROPPING_LOST_FRAG_STR);
02943         prev = curr;
02944         curr = curr->next;
02945         *reassemblyMemory -= (prev->end - prev->begin + 1);
02946         FreePacketBuffer(prev);
02947     }
02948 
02949     *front = curr;
02950 
02951     return 0;
02952 }
02953 
02954 
02955 static int FixSequence(TcpInfo* tcpInfo, SnifferSession* session)
02956 {
02957     word32*   expected = (session->flags.side == WOLFSSL_SERVER_END) ?
02958                                 &session->srvExpected : &session->cliExpected;
02959     PacketBuffer* list = (session->flags.side == WOLFSSL_SERVER_END) ?
02960                                 session->srvReassemblyList :
02961                                 session->cliReassemblyList;
02962     byte*  skipPartial = (session->flags.side != WOLFSSL_SERVER_END) ?
02963                                 &session->flags.srvSkipPartial :
02964                                 &session->flags.cliSkipPartial;
02965 
02966     *skipPartial = 1;
02967     if (list != NULL)
02968         *expected = list->begin;
02969     else {
02970         word32 seqStart = (session->flags.side == WOLFSSL_SERVER_END) ?
02971                                 session->srvSeqStart : session->cliSeqStart;
02972         word32     real = tcpInfo->ackNumber - seqStart;
02973 
02974         *expected = real;
02975     }
02976 
02977     return 1;
02978 }
02979 
02980 
02981 /* Check latest ack number for missing packets
02982    return 0 ok, <0 on error */
02983 static int CheckAck(TcpInfo* tcpInfo, SnifferSession* session)
02984 {
02985     if (tcpInfo->ack) {
02986         word32  seqStart = (session->flags.side == WOLFSSL_SERVER_END) ? 
02987                                      session->srvSeqStart :session->cliSeqStart;
02988         word32  real     = tcpInfo->ackNumber - seqStart;
02989         word32  expected = (session->flags.side == WOLFSSL_SERVER_END) ?
02990                                   session->srvExpected : session->cliExpected;
02991     
02992         /* handle rollover of sequence */
02993         if (tcpInfo->ackNumber < seqStart)
02994             real = 0xffffffffU - seqStart + tcpInfo->ackNumber;
02995         
02996         TraceAck(real, expected);
02997 
02998         if (real > expected)
02999             return -1;  /* we missed a packet, ACKing data we never saw */
03000     }
03001     return 0;
03002 }
03003 
03004 
03005 /* Check TCP Sequence status */
03006 /* returns 0 on success (continue), -1 on error, 1 on success (end) */
03007 static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo,
03008                          SnifferSession* session, int* sslBytes,
03009                          const byte** sslFrame, char* error)
03010 {
03011     int actualLen;
03012     byte* ackFault = (session->flags.side == WOLFSSL_SERVER_END) ?
03013                         &session->flags.cliAckFault :
03014                         &session->flags.srvAckFault;
03015 
03016     /* init SEQ from server to client */
03017     if (tcpInfo->syn && tcpInfo->ack) {
03018         session->srvSeqStart = tcpInfo->sequence;
03019         session->srvExpected = 1;
03020         TraceServerSyn(tcpInfo->sequence);
03021         return 1;
03022     }
03023     
03024     /* adjust potential ethernet trailer */
03025     actualLen = ipInfo->total - ipInfo->length - tcpInfo->length;
03026     if (*sslBytes > actualLen) {
03027         *sslBytes = actualLen;
03028     }
03029     
03030     TraceSequence(tcpInfo->sequence, *sslBytes);
03031     if (CheckAck(tcpInfo, session) < 0) {
03032         if (!RecoveryEnabled) {
03033             UpdateMissedDataSessions();
03034             SetError(ACK_MISSED_STR, error, session, FATAL_ERROR_STATE);
03035             return -1;
03036         }
03037         else {
03038             SetError(ACK_MISSED_STR, error, session, 0);
03039             if (*ackFault == 0) {
03040                 *ackFault = 1;
03041                 UpdateMissedDataSessions();
03042             }
03043             return FixSequence(tcpInfo, session);
03044         }
03045     }
03046     
03047     if (*ackFault) {
03048         Trace(CLEAR_ACK_FAULT);
03049         *ackFault = 0;
03050     }
03051 
03052     return AdjustSequence(tcpInfo, session, sslBytes, sslFrame, error);    
03053 }
03054 
03055 
03056 /* Check Status before record processing */
03057 /* returns 0 on success (continue), -1 on error, 1 on success (end) */
03058 static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo,
03059                           const byte** sslFrame, SnifferSession** session,
03060                           int* sslBytes, const byte** end, char* error)
03061 {
03062     word32 length;
03063     SSL*  ssl = ((*session)->flags.side == WOLFSSL_SERVER_END) ?
03064                                   (*session)->sslServer : (*session)->sslClient;
03065     byte  skipPartial = ((*session)->flags.side == WOLFSSL_SERVER_END) ?
03066                         (*session)->flags.srvSkipPartial :
03067                         (*session)->flags.cliSkipPartial;
03068     /* remove SnifferSession on 2nd FIN or RST */
03069     if (tcpInfo->fin || tcpInfo->rst) {
03070         /* flag FIN and RST */
03071         if (tcpInfo->fin)
03072             (*session)->flags.finCount += 1;
03073         else if (tcpInfo->rst)
03074             (*session)->flags.finCount += 2;
03075         
03076         if ((*session)->flags.finCount >= 2) {
03077             RemoveSession(*session, ipInfo, tcpInfo, 0);
03078             *session = NULL;
03079             return 1;
03080         }
03081     }
03082     
03083     if ((*session)->flags.fatalError == FATAL_ERROR_STATE) {
03084         SetError(FATAL_ERROR_STR, error, NULL, 0);
03085         return -1;
03086     }
03087     
03088     if (skipPartial) {
03089         if (FindNextRecordInAssembly(*session,
03090                                      sslFrame, sslBytes, end, error) < 0) {
03091             return -1;
03092         }
03093     }
03094 
03095     if (*sslBytes == 0) {
03096         Trace(NO_DATA_STR);
03097         return 1;
03098     }
03099     
03100     /* if current partial data, add to end of partial */
03101     /* if skipping, the data is already at the end of partial */
03102     if ( !skipPartial &&
03103          (length = ssl->buffers.inputBuffer.length) ) {
03104         Trace(PARTIAL_ADD_STR);
03105         
03106         if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) {
03107             if (GrowInputBuffer(ssl, *sslBytes, length) < 0) {
03108                 SetError(MEMORY_STR, error, *session, FATAL_ERROR_STATE);
03109                 return -1;
03110             }
03111         }
03112         XMEMCPY(&ssl->buffers.inputBuffer.buffer[length], *sslFrame, *sslBytes);
03113         *sslBytes += length;
03114         ssl->buffers.inputBuffer.length = *sslBytes;
03115         *sslFrame = ssl->buffers.inputBuffer.buffer;
03116         *end = *sslFrame + *sslBytes;
03117     }
03118 
03119     if ((*session)->flags.clientHello == 0 && **sslFrame != handshake) {
03120         /* Sanity check the packet for an old style client hello. */
03121         int rhSize = (((*sslFrame)[0] & 0x7f) << 8) | ((*sslFrame)[1]);
03122 
03123         if ((rhSize <= (*sslBytes - 2)) &&
03124             (*sslFrame)[2] == OLD_HELLO_ID && (*sslFrame)[3] == SSLv3_MAJOR) {
03125 #ifdef OLD_HELLO_ALLOWED
03126         int ret = DoOldHello(*session, *sslFrame, &rhSize, sslBytes, error);
03127         if (ret < 0)
03128             return -1;  /* error already set */
03129         if (*sslBytes <= 0)
03130             return 1;
03131 #endif
03132         }
03133         else {
03134 #ifdef STARTTLS_ALLOWED
03135             return 1;
03136 #endif
03137         }
03138     }
03139 
03140     return 0;
03141 }
03142 
03143 
03144 /* See if input on the reassembly list is ready for consuming */
03145 /* returns 1 for TRUE, 0 for FALSE */
03146 static int HaveMoreInput(SnifferSession* session, const byte** sslFrame,
03147                          int* sslBytes, const byte** end, char* error)
03148 {
03149     /* sequence and reassembly based on from, not to */
03150     int            moreInput = 0;
03151     PacketBuffer** front = (session->flags.side == WOLFSSL_SERVER_END) ?
03152                       &session->cliReassemblyList : &session->srvReassemblyList;
03153     word32*        expected = (session->flags.side == WOLFSSL_SERVER_END) ?
03154                                   &session->cliExpected : &session->srvExpected;
03155     /* buffer is on receiving end */
03156     word32*        length = (session->flags.side == WOLFSSL_SERVER_END) ?
03157                                &session->sslServer->buffers.inputBuffer.length :
03158                                &session->sslClient->buffers.inputBuffer.length;
03159     byte**         myBuffer = (session->flags.side == WOLFSSL_SERVER_END) ?
03160                                &session->sslServer->buffers.inputBuffer.buffer :
03161                                &session->sslClient->buffers.inputBuffer.buffer;
03162     word32*       bufferSize = (session->flags.side == WOLFSSL_SERVER_END) ?
03163                            &session->sslServer->buffers.inputBuffer.bufferSize :
03164                            &session->sslClient->buffers.inputBuffer.bufferSize;
03165     SSL*               ssl  = (session->flags.side == WOLFSSL_SERVER_END) ?
03166                             session->sslServer : session->sslClient;
03167     word32*     reassemblyMemory = (session->flags.side == WOLFSSL_SERVER_END) ?
03168                   &session->cliReassemblyMemory : &session->srvReassemblyMemory;
03169     
03170     while (*front && ((*front)->begin == *expected) ) {
03171         word32 room = *bufferSize - *length;
03172         word32 packetLen = (*front)->end - (*front)->begin + 1;
03173 
03174         if (packetLen > room && *bufferSize < MAX_INPUT_SZ) {
03175             if (GrowInputBuffer(ssl, packetLen, *length) < 0) {
03176                 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
03177                 return 0;
03178             }
03179             room = *bufferSize - *length;   /* bufferSize is now bigger */
03180         }
03181         
03182         if (packetLen <= room) {
03183             PacketBuffer* del = *front;
03184             byte*         buf = *myBuffer;
03185             
03186             XMEMCPY(&buf[*length], (*front)->data, packetLen);
03187             *length   += packetLen;
03188             *expected += packetLen;
03189             
03190             /* remove used packet */
03191             *front = (*front)->next;
03192 
03193             *reassemblyMemory -= packetLen;
03194             FreePacketBuffer(del);
03195             
03196             moreInput = 1;
03197         }
03198         else
03199             break;
03200     }
03201     if (moreInput) {
03202         *sslFrame = *myBuffer;
03203         *sslBytes = *length;
03204         *end      = *myBuffer + *length;
03205     }
03206     return moreInput;
03207 }
03208                          
03209 
03210 
03211 /* Process Message(s) from sslFrame */
03212 /* return Number of bytes on success, 0 for no data yet, and -1 on error */
03213 static int ProcessMessage(const byte* sslFrame, SnifferSession* session,
03214                           int sslBytes, byte** data, const byte* end,
03215                           char* error)
03216 {
03217     const byte*       sslBegin = sslFrame;
03218     const byte*       recordEnd;   /* end of record indicator */
03219     const byte*       inRecordEnd; /* indicator from input stream not decrypt */
03220     RecordLayerHeader rh;
03221     int               rhSize = 0;
03222     int               ret;
03223     int               errCode = 0;
03224     int               decoded = 0;      /* bytes stored for user in data */
03225     int               notEnough;        /* notEnough bytes yet flag */
03226     int               decrypted = 0;    /* was current msg decrypted */
03227     SSL*              ssl = (session->flags.side == WOLFSSL_SERVER_END) ?
03228                                         session->sslServer : session->sslClient;
03229 doMessage:
03230     notEnough = 0;
03231     if (sslBytes < 0) {
03232         SetError(PACKET_HDR_SHORT_STR, error, session, FATAL_ERROR_STATE);
03233         return -1;
03234     }
03235     if (sslBytes >= RECORD_HEADER_SZ) {
03236         if (GetRecordHeader(sslFrame, &rh, &rhSize) != 0) {
03237             SetError(BAD_RECORD_HDR_STR, error, session, FATAL_ERROR_STATE);
03238             return -1;
03239         }
03240     }
03241     else
03242         notEnough = 1;
03243 
03244     if (notEnough || rhSize > (sslBytes - RECORD_HEADER_SZ)) {
03245         /* don't have enough input yet to process full SSL record */
03246         Trace(PARTIAL_INPUT_STR);
03247         
03248         /* store partial if not there already or we advanced */
03249         if (ssl->buffers.inputBuffer.length == 0 || sslBegin != sslFrame) {
03250             if (sslBytes > (int)ssl->buffers.inputBuffer.bufferSize) {
03251                 if (GrowInputBuffer(ssl, sslBytes, 0) < 0) { 
03252                     SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
03253                     return -1;
03254                 }
03255             }
03256             XMEMMOVE(ssl->buffers.inputBuffer.buffer, sslFrame, sslBytes);
03257             ssl->buffers.inputBuffer.length = sslBytes;
03258         }
03259         if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error))
03260             goto doMessage;
03261         return decoded;
03262     }
03263     sslFrame += RECORD_HEADER_SZ;
03264     sslBytes -= RECORD_HEADER_SZ;
03265     recordEnd = sslFrame + rhSize;   /* may have more than one record */
03266     inRecordEnd = recordEnd;
03267     
03268     /* decrypt if needed */
03269     if ((session->flags.side == WOLFSSL_SERVER_END &&
03270                                                session->flags.serverCipherOn)
03271      || (session->flags.side == WOLFSSL_CLIENT_END &&
03272                                                session->flags.clientCipherOn)) {
03273         int ivAdvance = 0;  /* TLSv1.1 advance amount */
03274         if (ssl->decrypt.setup != 1) {
03275             SetError(DECRYPT_KEYS_NOT_SETUP, error, session, FATAL_ERROR_STATE);
03276             return -1;
03277         }
03278         if (CheckAvailableSize(ssl, rhSize) < 0) {
03279             SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
03280             return -1;
03281         }
03282         sslFrame = DecryptMessage(ssl, sslFrame, rhSize,
03283                                   ssl->buffers.outputBuffer.buffer, &errCode,
03284                                   &ivAdvance);
03285         recordEnd = sslFrame - ivAdvance + rhSize;  /* sslFrame moved so
03286                                                        should recordEnd */
03287         decrypted = 1;
03288         if (errCode != 0) {
03289             SetError(BAD_DECRYPT, error, session, FATAL_ERROR_STATE);
03290             return -1;
03291         }
03292     }
03293 
03294 doPart:
03295             
03296     switch ((enum ContentType)rh.type) {
03297         case handshake:
03298             {
03299                 int startIdx = sslBytes;
03300                 int used;
03301 
03302                 Trace(GOT_HANDSHAKE_STR);
03303                 ret = DoHandShake(sslFrame, &sslBytes, session, error);
03304                 if (ret != 0) {
03305                     if (session->flags.fatalError == 0)
03306                         SetError(BAD_HANDSHAKE_STR, error, session,
03307                                  FATAL_ERROR_STATE);
03308                     return -1;
03309                 }
03310 
03311                 /* DoHandShake now fully decrements sslBytes to remaining */
03312                 used = startIdx - sslBytes;
03313                 sslFrame += used;
03314                 if (decrypted)
03315                     sslFrame += ssl->keys.padSz;
03316             }
03317             break;
03318         case change_cipher_spec:
03319             if (session->flags.side == WOLFSSL_SERVER_END)
03320                 session->flags.serverCipherOn = 1;
03321             else
03322                 session->flags.clientCipherOn = 1;
03323             Trace(GOT_CHANGE_CIPHER_STR);
03324             ssl->options.handShakeState = HANDSHAKE_DONE;
03325             ssl->options.handShakeDone  = 1;
03326 
03327             sslFrame += 1;
03328             sslBytes -= 1;
03329 
03330             break;
03331         case application_data:
03332             Trace(GOT_APP_DATA_STR);
03333             {
03334                 word32 inOutIdx = 0;
03335                     
03336                 ret = DoApplicationData(ssl, (byte*)sslFrame, &inOutIdx);
03337                 if (ret == 0) {
03338                     ret = ssl->buffers.clearOutputBuffer.length;
03339                     TraceGotData(ret);
03340                     if (ret) {  /* may be blank message */
03341                         byte* tmpData;  /* don't leak on realloc free */
03342                         /* add an extra byte at end of allocation in case user
03343                          * wants to null terminate plaintext */
03344                         tmpData = (byte*)realloc(*data, decoded + ret + 1);
03345                         if (tmpData == NULL) {
03346                             ForceZero(*data, decoded);
03347                             free(*data);
03348                             *data = NULL;
03349                             SetError(MEMORY_STR, error, session,
03350                                      FATAL_ERROR_STATE);
03351                             return -1;
03352                         }
03353                         *data = tmpData;
03354                         XMEMCPY(*data + decoded,
03355                                 ssl->buffers.clearOutputBuffer.buffer, ret);
03356                         TraceAddedData(ret, decoded);
03357                         decoded += ret;
03358                         ssl->buffers.clearOutputBuffer.length = 0;
03359                     }
03360                 }
03361                 else {
03362                     SetError(BAD_APP_DATA_STR, error,session,FATAL_ERROR_STATE);
03363                     return -1;
03364                 }
03365                 if (ssl->buffers.outputBuffer.dynamicFlag)
03366                     ShrinkOutputBuffer(ssl);
03367 
03368                 sslFrame += inOutIdx;
03369                 sslBytes -= inOutIdx;
03370             }
03371             break;
03372         case alert:
03373             Trace(GOT_ALERT_STR);
03374             sslFrame += rhSize;
03375             sslBytes -= rhSize;
03376             break;
03377         case no_type:
03378         default:
03379             SetError(GOT_UNKNOWN_RECORD_STR, error, session, FATAL_ERROR_STATE);
03380             return -1;
03381     }
03382 
03383     /* do we have another msg in record ? */
03384     if (sslFrame < recordEnd) {
03385         Trace(ANOTHER_MSG_STR);
03386         goto doPart;
03387     }
03388 
03389     /* back to input stream instead of potential decrypt buffer */
03390     recordEnd = inRecordEnd;
03391 
03392     /* do we have more records ? */
03393     if (recordEnd < end) {
03394         Trace(ANOTHER_MSG_STR);
03395         sslFrame = recordEnd;
03396         sslBytes = (int)(end - recordEnd);
03397         goto doMessage;
03398     }
03399     
03400     /* clear used input */
03401     ssl->buffers.inputBuffer.length = 0;
03402     
03403     /* could have more input ready now */
03404     if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error))
03405         goto doMessage;
03406 
03407     if (ssl->buffers.inputBuffer.dynamicFlag)
03408         ShrinkInputBuffer(ssl, NO_FORCED_FREE);
03409     
03410     return decoded;
03411 }
03412 
03413 
03414 /* See if we need to process any pending FIN captures */
03415 static void CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo, 
03416                             SnifferSession* session)
03417 {
03418     if (session->finCaputre.cliFinSeq && session->finCaputre.cliFinSeq <= 
03419                                          session->cliExpected) {
03420         if (session->finCaputre.cliCounted == 0) {
03421             session->flags.finCount += 1;
03422             session->finCaputre.cliCounted = 1;
03423             TraceClientFin(session->finCaputre.cliFinSeq, session->cliExpected);
03424         }
03425     }
03426         
03427     if (session->finCaputre.srvFinSeq && session->finCaputre.srvFinSeq <= 
03428                                          session->srvExpected) {
03429         if (session->finCaputre.srvCounted == 0) {
03430             session->flags.finCount += 1;
03431             session->finCaputre.srvCounted = 1;
03432             TraceServerFin(session->finCaputre.srvFinSeq, session->srvExpected);
03433         }
03434     }
03435                 
03436     if (session->flags.finCount >= 2) 
03437         RemoveSession(session, ipInfo, tcpInfo, 0);
03438 }
03439 
03440 
03441 /* If session is in fatal error state free resources now 
03442    return true if removed, 0 otherwise */
03443 static int RemoveFatalSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
03444                               SnifferSession* session, char* error)
03445 {
03446     if (session && session->flags.fatalError == FATAL_ERROR_STATE) {
03447         RemoveSession(session, ipInfo, tcpInfo, 0);
03448         SetError(FATAL_ERROR_STR, error, NULL, 0);
03449         return 1;
03450     }
03451     return 0;
03452 }
03453 
03454 
03455 /* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */
03456 /* returns Number of bytes on success, 0 for no data yet, and -1 on error */
03457 int ssl_DecodePacket(const byte* packet, int length, byte** data, char* error)
03458 {
03459     TcpInfo           tcpInfo;
03460     IpInfo            ipInfo;
03461     const byte*       sslFrame;
03462     const byte*       end = packet + length;
03463     int               sslBytes;                /* ssl bytes unconsumed */
03464     int               ret;
03465     SnifferSession*   session = 0;
03466 
03467     if (CheckHeaders(&ipInfo, &tcpInfo, packet, length, &sslFrame, &sslBytes,
03468                      error) != 0)
03469         return -1;
03470     
03471     ret = CheckSession(&ipInfo, &tcpInfo, sslBytes, &session, error);
03472     if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
03473     else if (ret == -1) return -1;
03474     else if (ret ==  1) return  0;   /* done for now */
03475     
03476     ret = CheckSequence(&ipInfo, &tcpInfo, session, &sslBytes, &sslFrame,error);
03477     if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
03478     else if (ret == -1) return -1;
03479     else if (ret ==  1) return  0;   /* done for now */
03480     
03481     ret = CheckPreRecord(&ipInfo, &tcpInfo, &sslFrame, &session, &sslBytes,
03482                          &end, error);
03483     if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
03484     else if (ret == -1) return -1;
03485     else if (ret ==  1) return  0;   /* done for now */
03486 
03487     ret = ProcessMessage(sslFrame, session, sslBytes, data, end, error);
03488     if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
03489     CheckFinCapture(&ipInfo, &tcpInfo, session);
03490     return ret;
03491 }
03492 
03493 
03494 /* Deallocator for the decoded data buffer. */
03495 /* returns 0 on success, -1 on error */
03496 int ssl_FreeDecodeBuffer(byte** data, char* error)
03497 {
03498     return ssl_FreeZeroDecodeBuffer(data, 0, error);
03499 }
03500 
03501 
03502 /* Deallocator for the decoded data buffer, zeros out buffer. */
03503 /* returns 0 on success, -1 on error */
03504 int ssl_FreeZeroDecodeBuffer(byte** data, int sz, char* error)
03505 {
03506     (void)error;
03507 
03508     if (sz < 0) {
03509         return -1;
03510     }
03511 
03512     if (data != NULL) {
03513         ForceZero(*data, (word32)sz);
03514         free(*data);
03515         *data = NULL;
03516     }
03517 
03518     return 0;
03519 }
03520 
03521 
03522 /* Enables (if traceFile)/ Disables debug tracing */
03523 /* returns 0 on success, -1 on error */
03524 int ssl_Trace(const char* traceFile, char* error)
03525 {
03526     if (traceFile) {
03527         TraceFile = fopen(traceFile, "a");
03528         if (!TraceFile) {
03529             SetError(BAD_TRACE_FILE_STR, error, NULL, 0);
03530             return -1;
03531         }
03532         TraceOn = 1;
03533     }
03534     else 
03535         TraceOn = 0;
03536 
03537     return 0;
03538 }
03539 
03540 
03541 /* Enables/Disables Recovery of missed data if later packets allow
03542  * maxMemory is number of bytes to use for reassembly buffering per session,
03543  * -1 means unlimited
03544  * returns 0 on success, -1 on error */
03545 int ssl_EnableRecovery(int onOff, int maxMemory, char* error)
03546 {
03547     (void)error;
03548 
03549     RecoveryEnabled = onOff;
03550     if (onOff)
03551         MaxRecoveryMemory = maxMemory;
03552 
03553     return 0;
03554 }
03555 
03556 
03557 
03558 int ssl_GetSessionStats(unsigned int* active,     unsigned int* total,
03559                         unsigned int* peak,       unsigned int* maxSessions,
03560                         unsigned int* missedData, unsigned int* reassemblyMem,
03561                         char* error)
03562 {
03563     int ret;
03564 
03565     if (missedData) {
03566         wc_LockMutex(&RecoveryMutex);
03567         *missedData = MissedDataSessions;
03568         wc_UnLockMutex(&RecoveryMutex);
03569     }
03570 
03571     if (reassemblyMem) {
03572         SnifferSession* session;
03573         int i;
03574 
03575         *reassemblyMem = 0;
03576         wc_LockMutex(&SessionMutex);
03577         for (i = 0; i < HASH_SIZE; i++) {
03578             session = SessionTable[i];
03579             while (session) {
03580                 *reassemblyMem += session->cliReassemblyMemory;
03581                 *reassemblyMem += session->srvReassemblyMemory;
03582                 session = session->next;
03583             }
03584         }
03585         wc_UnLockMutex(&SessionMutex);
03586     }
03587 
03588     ret = wolfSSL_get_session_stats(active, total, peak, maxSessions);
03589 
03590     if (ret == SSL_SUCCESS)
03591         return 0;
03592     else {
03593         SetError(BAD_SESSION_STATS, error, NULL, 0);
03594         return -1;
03595     }
03596 }
03597 
03598 
03599 
03600 #endif /* WOLFSSL_SNIFFER */
03601 #endif /* WOLFCRYPT_ONLY */
03602