wolfSSL SSL/TLS library, support up to TLS1.3

Dependents:   OS

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