Renesas / SecureDweet
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sniffer.c Source File

sniffer.c

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