]> begriffs open source - freertos/blob - FreeRTOS-Plus/Source/WolfSSL/src/sniffer.c
Change name of the CEC and MEC directory to CORTEX_MPU_CEC_MEC_17xx_51xx_Keil_GCC...
[freertos] / FreeRTOS-Plus / Source / WolfSSL / src / sniffer.c
1 /* sniffer.c
2  *
3  * Copyright (C) 2006-2015 wolfSSL Inc.
4  *
5  * This file is part of wolfSSL. (formerly known as CyaSSL)
6  *
7  * wolfSSL is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * wolfSSL is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20  */
21
22 #ifdef HAVE_CONFIG_H
23     #include <config.h>
24 #endif
25
26 #include <wolfssl/wolfcrypt/settings.h>
27
28 #ifdef WOLFSSL_SNIFFER
29
30 #include <assert.h>
31 #include <time.h>
32
33 #ifndef _WIN32
34   #include <arpa/inet.h>
35 #endif
36
37 #ifdef _WIN32
38     #define SNPRINTF _snprintf
39 #else
40     #define SNPRINTF snprintf
41 #endif
42
43 #include <wolfssl/openssl/ssl.h>
44 #include <wolfssl/internal.h>
45 #include <wolfssl/error-ssl.h>
46 #include <wolfssl/sniffer.h>
47 #include <wolfssl/sniffer_error.h>
48 #ifdef NO_INLINE
49     #include <wolfssl/wolfcrypt/misc.h>
50 #else
51     #include <wolfcrypt/src/misc.c>
52 #endif
53
54
55 #ifndef WOLFSSL_HAVE_MIN
56 #define WOLFSSL_HAVE_MIN
57
58 static INLINE word32 min(word32 a, word32 b)
59 {
60     return a > b ? b : a;
61 }
62
63 #endif /* WOLFSSL_HAVE_MIN */
64
65 #ifndef WOLFSSL_SNIFFER_TIMEOUT
66     #define WOLFSSL_SNIFFER_TIMEOUT 900
67     /* Cache unclosed Sessions for 15 minutes since last used */
68 #endif
69
70 /* Misc constants */
71 enum {
72     MAX_SERVER_ADDRESS = 128, /* maximum server address length */
73     MAX_SERVER_NAME    = 128, /* maximum server name length */
74     MAX_ERROR_LEN      = 80,  /* maximum error length */
75     ETHER_IF_ADDR_LEN  = 6,   /* ethernet interface address length */
76     LOCAL_IF_ADDR_LEN  = 4,   /* localhost interface address length, !windows */
77     TCP_PROTO          = 6,   /* TCP_PROTOCOL */
78     IP_HDR_SZ          = 20,  /* IP header legnth, min */
79     TCP_HDR_SZ         = 20,  /* TCP header legnth, min */
80     IPV4               = 4,   /* IP version 4 */
81     TCP_PROTOCOL       = 6,   /* TCP Protocol id */
82     TRACE_MSG_SZ       = 80,  /* Trace Message buffer size */
83     HASH_SIZE          = 499, /* Session Hash Table Rows */
84     PSEUDO_HDR_SZ      = 12,  /* TCP Pseudo Header size in bytes */
85     FATAL_ERROR_STATE  =  1,  /* SnifferSession fatal error state */
86     TICKET_HINT_LEN    = 4,   /* Session Ticket Hint length */
87     EXT_TYPE_SZ        = 2,   /* Extension length */
88     MAX_INPUT_SZ       = MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA +
89                          MTU_EXTRA,  /* Max input sz of reassembly */
90     TICKET_EXT_ID      = 0x23 /* Session Ticket Extension ID */
91 };
92
93
94 #ifdef _WIN32
95
96 static HMODULE dllModule;  /* for error string resources */
97
98 BOOL APIENTRY DllMain( HMODULE hModule,
99                        DWORD  ul_reason_for_call,
100                        LPVOID lpReserved
101                      )
102 {
103         static int didInit = 0;
104
105     switch (ul_reason_for_call)
106     {
107     case DLL_PROCESS_ATTACH:
108                 if (didInit == 0) {
109             dllModule = hModule;
110                         ssl_InitSniffer();
111                         didInit = 1;
112                 }
113         break;
114     case DLL_THREAD_ATTACH:
115         break;
116     case DLL_THREAD_DETACH:
117         break;
118     case DLL_PROCESS_DETACH:
119                 if (didInit) {
120                         ssl_FreeSniffer();
121                         didInit = 0;
122                 }
123         break;
124     }
125     return TRUE;
126 }
127
128 #endif /* _WIN32 */
129
130
131 static int TraceOn = 0;         /* Trace is off by default */
132 static FILE* TraceFile = 0;
133
134
135 /* windows uses .rc table for this */
136 #ifndef _WIN32
137
138 static const char* const msgTable[] =
139 {
140     /* 1 */
141     "Out of Memory",
142     "New SSL Sniffer Server Registered",
143     "Checking IP Header",
144     "SSL Sniffer Server Not Registered",
145     "Checking TCP Header",
146
147     /* 6 */
148     "SSL Sniffer Server Port Not Registered",
149     "RSA Private Decrypt Error",
150     "RSA Private Decode Error",
151     "Set Cipher Spec Error",
152     "Server Hello Input Malformed",
153
154     /* 11 */
155     "Couldn't Resume Session Error",
156     "Server Did Resumption",
157     "Client Hello Input Malformed",
158     "Client Trying to Resume",
159     "Handshake Input Malformed",
160
161     /* 16 */
162     "Got Hello Verify msg",
163     "Got Server Hello msg",
164     "Got Cert Request msg",
165     "Got Server Key Exchange msg",
166     "Got Cert msg",
167
168     /* 21 */
169     "Got Server Hello Done msg",
170     "Got Finished msg",
171     "Got Client Hello msg",
172     "Got Client Key Exchange msg",
173     "Got Cert Verify msg",
174
175     /* 26 */
176     "Got Unknown Handshake msg",
177     "New SSL Sniffer Session created",
178     "Couldn't create new SSL",
179     "Got a Packet to decode",
180     "No data present",
181
182     /* 31 */
183     "Session Not Found",
184     "Got an Old Client Hello msg",
185     "Old Client Hello Input Malformed",
186     "Old Client Hello OK",
187     "Bad Old Client Hello",
188
189     /* 36 */
190     "Bad Record Header",
191     "Record Header Input Malformed",
192     "Got a HandShake msg",
193     "Bad HandShake msg",
194     "Got a Change Cipher Spec msg",
195
196     /* 41 */
197     "Got Application Data msg",
198     "Bad Application Data",
199     "Got an Alert msg",
200     "Another msg to Process",
201     "Removing Session From Table",
202     
203     /* 46 */
204     "Bad Key File",
205     "Wrong IP Version",
206     "Wrong Protocol type",
207     "Packet Short for header processing",
208     "Got Unknown Record Type",
209     
210     /* 51 */
211     "Can't Open Trace File",
212     "Session in Fatal Error State",
213     "Partial SSL record received",
214     "Buffer Error, malformed input",
215     "Added to Partial Input",
216     
217     /* 56 */
218     "Received a Duplicate Packet",
219     "Received an Out of Order Packet",
220     "Received an Overlap Duplicate Packet",
221     "Received an Overlap Reassembly Begin Duplicate Packet",
222     "Received an Overlap Reassembly End Duplicate Packet",
223
224     /* 61 */
225     "Missed the Client Hello Entirely",
226     "Got Hello Request msg",
227     "Got Session Ticket msg",
228     "Bad Input",
229     "Bad Decrypt Type",
230
231     /* 66 */
232     "Bad Finished Message Processing",
233     "Bad Compression Type",
234     "Bad DeriveKeys Error",
235     "Saw ACK for Missing Packet Error",
236     "Bad Decrypt Operation",
237
238     /* 71 */
239     "Decrypt Keys Not Set Up",
240     "Late Key Load Error",
241     "Got Certificate Status msg",
242     "RSA Key Missing Error"
243 };
244
245
246 /* *nix version uses table above */
247 static void GetError(int idx, char* str)
248 {
249     XSTRNCPY(str, msgTable[idx - 1], MAX_ERROR_LEN);
250 }
251
252
253 #else /* _WIN32 */
254
255
256 /* Windows version uses .rc table */
257 static void GetError(int idx, char* buffer)
258 {
259     if (!LoadStringA(dllModule, idx, buffer, MAX_ERROR_LEN))
260         buffer[0] = 0;
261 }
262
263
264 #endif /* _WIN32 */
265
266
267 /* Packet Buffer for reassembly list and ready list */
268 typedef struct PacketBuffer {
269     word32  begin;      /* relative sequence begin */
270     word32  end;        /* relative sequence end   */
271     byte*   data;       /* actual data             */
272     struct PacketBuffer* next; /* next on reassembly list or ready list */
273 } PacketBuffer;
274
275
276 #ifdef HAVE_SNI
277
278 /* NamedKey maps a SNI name to a specific private key */
279 typedef struct NamedKey {
280     char             name[MAX_SERVER_NAME];      /* server DNS name */
281     word32           nameSz;                     /* size of server DNS name */
282     byte*            key;                        /* DER private key */
283     word32           keySz;                      /* size of DER private key */
284     struct NamedKey* next;                       /* for list */
285 } NamedKey;
286
287 #endif
288
289
290 /* Sniffer Server holds info for each server/port monitored */
291 typedef struct SnifferServer {
292     SSL_CTX*       ctx;                          /* SSL context */
293     char           address[MAX_SERVER_ADDRESS];  /* passed in server address */
294     word32         server;                       /* netowrk order address */
295     int            port;                         /* server port */
296 #ifdef HAVE_SNI
297     NamedKey*      namedKeys;                    /* mapping of names and keys */
298     wolfSSL_Mutex   namedKeysMutex;               /* mutex for namedKey list */
299 #endif
300     struct SnifferServer* next;                  /* for list */
301 } SnifferServer;
302
303
304 /* Session Flags */
305 typedef struct Flags {
306     byte           side;            /* which end is current packet headed */
307     byte           serverCipherOn;  /* indicates whether cipher is active */
308     byte           clientCipherOn;  /* indicates whether cipher is active */
309     byte           resuming;        /* did this session come from resumption */
310     byte           cached;          /* have we cached this session yet */
311     byte           clientHello;     /* processed client hello yet, for SSLv2 */
312     byte           finCount;        /* get both FINs before removing */
313     byte           fatalError;      /* fatal error state */
314 } Flags;
315
316
317 /* Out of Order FIN caputre */
318 typedef struct FinCaputre {
319     word32 cliFinSeq;               /* client relative sequence FIN  0 is no */
320     word32 srvFinSeq;               /* server relative sequence FIN, 0 is no */
321     byte   cliCounted;              /* did we count yet, detects duplicates */
322     byte   srvCounted;              /* did we count yet, detects duplicates */
323 } FinCaputre;
324
325
326 /* Sniffer Session holds info for each client/server SSL/TLS session */
327 typedef struct SnifferSession {
328     SnifferServer* context;         /* server context */
329     SSL*           sslServer;       /* SSL server side decode */
330     SSL*           sslClient;       /* SSL client side decode */
331     word32         server;          /* server address in network byte order */
332     word32         client;          /* client address in network byte order */
333     word16         srvPort;         /* server port */
334     word16         cliPort;         /* client port */
335     word32         cliSeqStart;     /* client start sequence */
336     word32         srvSeqStart;     /* server start sequence */
337     word32         cliExpected;     /* client expected sequence (relative) */
338     word32         srvExpected;     /* server expected sequence (relative) */
339     FinCaputre     finCaputre;      /* retain out of order FIN s */
340     Flags          flags;           /* session flags */
341     time_t         lastUsed;          /* last used ticks */
342     PacketBuffer*  cliReassemblyList; /* client out of order packets */
343     PacketBuffer*  srvReassemblyList; /* server out of order packets */
344     struct SnifferSession* next;      /* for hash table list */
345     byte*          ticketID;          /* mac ID of session ticket */
346 } SnifferSession;
347
348
349 /* Sniffer Server List and mutex */
350 static SnifferServer* ServerList = 0;
351 static wolfSSL_Mutex ServerListMutex;
352
353
354 /* Session Hash Table, mutex, and count */
355 static SnifferSession* SessionTable[HASH_SIZE];
356 static wolfSSL_Mutex SessionMutex;
357 static int SessionCount = 0;
358
359
360 /* Initialize overall Sniffer */
361 void ssl_InitSniffer(void)
362 {
363     wolfSSL_Init();
364     InitMutex(&ServerListMutex);
365     InitMutex(&SessionMutex);
366 }
367
368
369 #ifdef HAVE_SNI
370
371 /* Free Named Key and the zero out the private key it holds */
372 static void FreeNamedKey(NamedKey* in)
373 {
374     if (in) {
375         if (in->key) {
376             ForceZero(in->key, in->keySz);
377             free(in->key);
378         }
379         free(in);
380     }
381 }
382
383
384 static void FreeNamedKeyList(NamedKey* in)
385 {
386     NamedKey* next;
387
388     while (in) {
389         next = in->next;
390         FreeNamedKey(in);
391         in = next;
392     }
393 }
394
395 #endif
396
397
398 /* Free Sniffer Server's resources/self */
399 static void FreeSnifferServer(SnifferServer* srv)
400 {
401     if (srv) {
402 #ifdef HAVE_SNI
403         LockMutex(&srv->namedKeysMutex);
404         FreeNamedKeyList(srv->namedKeys);
405         UnLockMutex(&srv->namedKeysMutex);
406         FreeMutex(&srv->namedKeysMutex);
407 #endif
408         SSL_CTX_free(srv->ctx);
409     }
410     free(srv);
411 }
412
413
414 /* free PacketBuffer's resources/self */
415 static void FreePacketBuffer(PacketBuffer* del)
416 {
417     if (del) {
418         free(del->data);
419         free(del);
420     }
421 }
422
423
424 /* remove PacketBuffer List */
425 static void FreePacketList(PacketBuffer* in)
426 {
427     if (in) {
428         PacketBuffer* del;
429         PacketBuffer* packet = in;
430         
431         while (packet) {
432             del = packet;
433             packet = packet->next;
434             FreePacketBuffer(del);
435         }
436     }
437 }
438
439
440 /* Free Sniffer Session's resources/self */
441 static void FreeSnifferSession(SnifferSession* session)
442 {
443     if (session) {
444         SSL_free(session->sslClient);
445         SSL_free(session->sslServer);
446         
447         FreePacketList(session->cliReassemblyList);
448         FreePacketList(session->srvReassemblyList);
449
450         free(session->ticketID);
451     }
452     free(session);
453 }
454
455
456 /* Free overall Sniffer */
457 void ssl_FreeSniffer(void)
458 {
459     SnifferServer*  srv;
460     SnifferServer*  removeServer;
461     SnifferSession* session;
462     SnifferSession* removeSession;
463     int i;
464
465     LockMutex(&ServerListMutex);
466     LockMutex(&SessionMutex);
467     
468     srv = ServerList;
469     while (srv) {
470         removeServer = srv;
471         srv = srv->next;
472         FreeSnifferServer(removeServer);
473     }
474
475     for (i = 0; i < HASH_SIZE; i++) {
476         session = SessionTable[i];
477         while (session) {
478             removeSession = session;
479             session = session->next;
480             FreeSnifferSession(removeSession);
481         }
482     }
483
484     UnLockMutex(&SessionMutex);
485     UnLockMutex(&ServerListMutex);
486
487     FreeMutex(&SessionMutex);
488     FreeMutex(&ServerListMutex);
489
490     if (TraceFile) {
491         TraceOn = 0;
492         fclose(TraceFile);
493         TraceFile = NULL;
494     }
495
496     wolfSSL_Cleanup();
497 }
498
499
500 /* Initialize a SnifferServer */
501 static void InitSnifferServer(SnifferServer* sniffer)
502 {
503     sniffer->ctx = 0;
504     XMEMSET(sniffer->address, 0, MAX_SERVER_ADDRESS);
505     sniffer->server   = 0;
506     sniffer->port     = 0;
507 #ifdef HAVE_SNI
508     sniffer->namedKeys = 0;
509     InitMutex(&sniffer->namedKeysMutex);
510 #endif
511     sniffer->next     = 0;
512 }
513
514
515 /* Initialize session flags */
516 static void InitFlags(Flags* flags)
517 {
518     flags->side           = 0;
519     flags->serverCipherOn = 0;
520     flags->clientCipherOn = 0;
521     flags->resuming       = 0;
522     flags->cached         = 0;
523     flags->clientHello    = 0;
524     flags->finCount       = 0;
525     flags->fatalError     = 0;
526 }
527
528
529 /* Initialize FIN Capture */
530 static void InitFinCapture(FinCaputre* cap)
531 {
532     cap->cliFinSeq  = 0;
533     cap->srvFinSeq  = 0;
534     cap->cliCounted = 0;
535     cap->srvCounted = 0;
536 }
537
538
539 /* Initialize a Sniffer Session */
540 static void InitSession(SnifferSession* session)
541 {
542     session->context        = 0;
543     session->sslServer      = 0;
544     session->sslClient      = 0;
545     session->server         = 0;
546     session->client         = 0;
547     session->srvPort        = 0;
548     session->cliPort        = 0;
549     session->cliSeqStart    = 0;
550     session->srvSeqStart    = 0;
551     session->cliExpected    = 0;
552     session->srvExpected    = 0;
553     session->lastUsed       = 0;
554     session->cliReassemblyList = 0;
555     session->srvReassemblyList = 0;
556     session->next           = 0;
557     session->ticketID       = 0;
558     
559     InitFlags(&session->flags);
560     InitFinCapture(&session->finCaputre);
561 }
562
563
564 /* IP Info from IP Header */
565 typedef struct IpInfo {
566     int    length;        /* length of this header */
567     int    total;         /* total length of fragment */
568     word32 src;           /* network order source address */
569     word32 dst;           /* network order destination address */
570 } IpInfo;
571
572
573 /* TCP Info from TCP Header */
574 typedef struct TcpInfo {
575     int    srcPort;       /* source port */
576     int    dstPort;       /* source port */
577     int    length;        /* length of this header */
578     word32 sequence;      /* sequence number */
579     word32 ackNumber;     /* ack number */
580     byte   fin;           /* FIN set */
581     byte   rst;           /* RST set */
582     byte   syn;           /* SYN set */
583     byte   ack;           /* ACK set */
584 } TcpInfo;
585
586
587 /* Tcp Pseudo Header for Checksum calculation */
588 typedef struct TcpPseudoHdr {
589     word32  src;        /* source address */
590     word32  dst;        /* destination address */
591     byte    rsv;        /* reserved, always 0 */
592     byte    protocol;   /* IP protocol */
593     word16  legnth;     /* tcp header length + data length (doesn't include */
594                         /* pseudo header length) network order */
595 } TcpPseudoHdr;
596
597
598 /* Password Setting Callback */
599 static int SetPassword(char* passwd, int sz, int rw, void* userdata)
600 {
601     (void)rw;
602     XSTRNCPY(passwd, (const char*)userdata, sz);
603     return (int)XSTRLEN((const char*)userdata);
604 }
605
606
607 /* Ethernet Header */
608 typedef struct EthernetHdr {
609     byte   dst[ETHER_IF_ADDR_LEN];    /* destination host address */ 
610     byte   src[ETHER_IF_ADDR_LEN];    /* source  host address */ 
611     word16 type;                      /* IP, ARP, etc */ 
612 } EthernetHdr;
613
614
615 /* IP Header */
616 typedef struct IpHdr {
617     byte    ver_hl;              /* version/header length */
618     byte    tos;                 /* type of service */
619     word16  length;              /* total length */
620     word16  id;                  /* identification */
621     word16  offset;              /* fragment offset field */
622     byte    ttl;                 /* time to live */
623     byte    protocol;            /* protocol */
624     word16  sum;                 /* checksum */
625     word32  src;                 /* source address */
626     word32  dst;                 /* destination address */
627 } IpHdr;
628
629
630 #define IP_HL(ip)      ( (((ip)->ver_hl) & 0x0f) * 4)
631 #define IP_V(ip)       ( ((ip)->ver_hl) >> 4)
632
633 /* TCP Header */
634 typedef struct TcpHdr {
635     word16  srcPort;            /* source port */
636     word16  dstPort;            /* destination port */
637     word32  sequence;           /* sequence number */ 
638     word32  ack;                /* acknoledgment number */ 
639     byte    offset;             /* data offset, reserved */
640     byte    flags;              /* option flags */
641     word16  window;             /* window */
642     word16  sum;                /* checksum */
643     word16  urgent;             /* urgent pointer */
644 } TcpHdr;
645
646 #define TCP_LEN(tcp)  ( (((tcp)->offset & 0xf0) >> 4) * 4)
647 #define TCP_FIN 0x01
648 #define TCP_SYN 0x02
649 #define TCP_RST 0x04
650 #define TCP_ACK 0x10
651
652
653
654
655
656 /* Use platform specific GetError to write to tracfile if tracing */ 
657 static void Trace(int idx) 
658 {
659     if (TraceOn) {
660         char myBuffer[MAX_ERROR_LEN];
661         GetError(idx, myBuffer);
662         fprintf(TraceFile, "\t%s\n", myBuffer);
663 #ifdef DEBUG_SNIFFER
664         fprintf(stderr,    "\t%s\n", myBuffer);
665 #endif
666     }
667 }
668
669
670 /* Show TimeStamp for beginning of packet Trace */
671 static void TraceHeader(void)
672 {
673     if (TraceOn) {
674         time_t ticks = time(NULL);
675         fprintf(TraceFile, "\n%s", ctime(&ticks));
676     }
677 }
678
679
680 /* Show Set Server info for Trace */
681 static void TraceSetServer(const char* srv, int port, const char* keyFile)
682 {
683     if (TraceOn) {
684         fprintf(TraceFile, "\tTrying to install a new Sniffer Server with\n");
685         fprintf(TraceFile, "\tserver: %s, port: %d, keyFile: %s\n", srv, port,
686                                                                     keyFile);
687     }
688 }
689
690
691 #ifdef HAVE_SNI
692
693 /* Show Set Named Server info for Trace */
694 static void TraceSetNamedServer(const char* name,
695                                  const char* srv, int port, const char* keyFile)
696 {
697     if (TraceOn) {
698         fprintf(TraceFile, "\tTrying to install a new Sniffer Server with\n");
699         fprintf(TraceFile, "\tname: %s, server: %s, port: %d, keyFile: %s\n",
700                                                       name, srv, port, keyFile);
701     }
702 }
703
704 #endif
705
706
707 /* Trace got packet number */
708 static void TracePacket(void)
709 {
710     if (TraceOn) {
711         static word32 packetNumber = 0;
712         fprintf(TraceFile, "\tGot a Packet to decode, packet %u\n",
713                 ++packetNumber);
714     }
715 }
716
717
718 /* Convert network byte order address into human readable */
719 static char* IpToS(word32 addr, char* str)
720 {
721     byte* p = (byte*)&addr;
722     
723     SNPRINTF(str, TRACE_MSG_SZ, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
724     
725     return str;
726 }
727
728
729 /* Show destination and source address from Ip Hdr for packet Trace */
730 static void TraceIP(IpHdr* iphdr)
731 {
732     if (TraceOn) {
733         char src[TRACE_MSG_SZ];
734         char dst[TRACE_MSG_SZ];
735         fprintf(TraceFile, "\tdst:%s src:%s\n", IpToS(iphdr->dst, dst),
736                 IpToS(iphdr->src, src));
737     }
738 }
739
740
741 /* Show destination and source port from Tcp Hdr for packet Trace */
742 static void TraceTcp(TcpHdr* tcphdr)
743 {
744     if (TraceOn) {
745         fprintf(TraceFile, "\tdstPort:%u srcPort:%u\n", ntohs(tcphdr->dstPort),
746                 ntohs(tcphdr->srcPort));
747     }
748 }
749
750
751 /* Show sequence and payload length for Trace */
752 static void TraceSequence(word32 seq, int len)
753 {
754     if (TraceOn) {
755         fprintf(TraceFile, "\tSequence:%u, payload length:%d\n", seq, len);
756     }
757 }
758
759
760 /* Show sequence and payload length for Trace */
761 static void TraceAck(word32 ack, word32 expected)
762 {
763     if (TraceOn) {
764         fprintf(TraceFile, "\tAck:%u Expected:%u\n", ack, expected);
765     }
766 }
767
768
769 /* Show relative expected and relative received sequences */
770 static void TraceRelativeSequence(word32 expected, word32 got)
771 {
772     if (TraceOn) {
773         fprintf(TraceFile, "\tExpected sequence:%u, received sequence:%u\n",
774                 expected, got);
775     }
776 }
777
778
779 /* Show server sequence startup from SYN */
780 static void TraceServerSyn(word32 seq)
781 {
782     if (TraceOn) {
783         fprintf(TraceFile, "\tServer SYN, Sequence Start:%u\n", seq);
784     }
785 }
786
787
788 /* Show client sequence startup from SYN */
789 static void TraceClientSyn(word32 seq)
790 {
791     if (TraceOn) {
792         fprintf(TraceFile, "\tClient SYN, Sequence Start:%u\n", seq);
793     }
794 }
795
796
797 /* Show client FIN capture */
798 static void TraceClientFin(word32 finSeq, word32 relSeq)
799 {
800     if (TraceOn) {
801         fprintf(TraceFile, "\tClient FIN capture:%u, current SEQ:%u\n",
802                 finSeq, relSeq);
803     }
804 }
805
806
807 /* Show server FIN capture */
808 static void TraceServerFin(word32 finSeq, word32 relSeq)
809 {
810     if (TraceOn) {
811         fprintf(TraceFile, "\tServer FIN capture:%u, current SEQ:%u\n",
812                 finSeq, relSeq);
813     }
814 }
815
816
817 /* Show number of SSL data bytes decoded, could be 0 (ok) */
818 static void TraceGotData(int bytes)
819 {
820     if (TraceOn) {
821         fprintf(TraceFile, "\t%d bytes of SSL App data processed\n", bytes);
822     }
823 }
824
825
826 /* Show bytes added to old SSL App data */
827 static void TraceAddedData(int newBytes, int existingBytes)
828 {
829     if (TraceOn) {
830         fprintf(TraceFile,
831                 "\t%d bytes added to %d exisiting bytes in User Buffer\n",
832                 newBytes, existingBytes);
833     }
834 }
835
836
837 /* Show Stale Session */
838 static void TraceStaleSession(void)
839 {
840     if (TraceOn) {
841         fprintf(TraceFile, "\tFound a stale session\n");
842     }
843 }
844
845
846 /* Show Finding Stale Sessions */
847 static void TraceFindingStale(void)
848 {
849     if (TraceOn) {
850         fprintf(TraceFile, "\tTrying to find Stale Sessions\n");
851     }
852 }
853
854
855 /* Show Removed Session */
856 static void TraceRemovedSession(void)
857 {
858     if (TraceOn) {
859         fprintf(TraceFile, "\tRemoved it\n");
860     }
861 }
862
863
864 /* Set user error string */
865 static void SetError(int idx, char* error, SnifferSession* session, int fatal)
866 {
867     GetError(idx, error);
868     Trace(idx);
869     if (session && fatal == FATAL_ERROR_STATE)
870         session->flags.fatalError = 1;
871 }
872
873
874 /* See if this IPV4 network order address has been registered */
875 /* return 1 is true, 0 is false */
876 static int IsServerRegistered(word32 addr)
877 {
878     int ret = 0;     /* false */
879     SnifferServer* sniffer;
880
881     LockMutex(&ServerListMutex);
882     
883     sniffer = ServerList;
884     while (sniffer) {
885         if (sniffer->server == addr) {
886             ret = 1;
887             break;
888         }
889         sniffer = sniffer->next;
890     }
891     
892     UnLockMutex(&ServerListMutex);
893
894     return ret;
895 }
896
897
898 /* See if this port has been registered to watch */
899 /* return 1 is true, 0 is false */
900 static int IsPortRegistered(word32 port)
901 {
902     int ret = 0;    /* false */
903     SnifferServer* sniffer;
904     
905     LockMutex(&ServerListMutex);
906     
907     sniffer = ServerList;
908     while (sniffer) {
909         if (sniffer->port == (int)port) {
910             ret = 1; 
911             break;
912         }
913         sniffer = sniffer->next;
914     }
915     
916     UnLockMutex(&ServerListMutex);
917
918     return ret;
919 }
920
921
922 /* Get SnifferServer from IP and Port */
923 static SnifferServer* GetSnifferServer(IpInfo* ipInfo, TcpInfo* tcpInfo)
924 {
925     SnifferServer* sniffer;
926     
927     LockMutex(&ServerListMutex);
928     
929     sniffer = ServerList;
930     while (sniffer) {
931         if (sniffer->port == tcpInfo->srcPort && sniffer->server == ipInfo->src)
932             break;
933         if (sniffer->port == tcpInfo->dstPort && sniffer->server == ipInfo->dst)
934             break;
935         sniffer = sniffer->next;
936     }
937     
938     UnLockMutex(&ServerListMutex);
939     
940     return sniffer;
941 }
942
943
944 /* Hash the Session Info, return hash row */
945 static word32 SessionHash(IpInfo* ipInfo, TcpInfo* tcpInfo)
946 {
947     word32 hash = ipInfo->src * ipInfo->dst;
948     hash *= tcpInfo->srcPort * tcpInfo->dstPort;
949     
950     return hash % HASH_SIZE;
951 }
952
953
954 /* Get Exisiting SnifferSession from IP and Port */
955 static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo)
956 {
957     SnifferSession* session;
958     time_t          currTime = time(NULL); 
959     word32          row = SessionHash(ipInfo, tcpInfo);
960
961     assert(row <= HASH_SIZE);
962     
963     LockMutex(&SessionMutex);
964     
965     session = SessionTable[row];
966     while (session) {
967         if (session->server == ipInfo->src && session->client == ipInfo->dst &&
968                     session->srvPort == tcpInfo->srcPort &&
969                     session->cliPort == tcpInfo->dstPort)
970             break;
971         if (session->client == ipInfo->src && session->server == ipInfo->dst &&
972                     session->cliPort == tcpInfo->srcPort &&
973                     session->srvPort == tcpInfo->dstPort)
974             break;
975         
976         session = session->next;
977     }
978
979     if (session)
980         session->lastUsed= currTime; /* keep session alive, remove stale will */
981                                      /* leave alone */   
982     UnLockMutex(&SessionMutex);
983     
984     /* determine side */
985     if (session) {
986         if (ipInfo->dst == session->context->server &&
987             tcpInfo->dstPort == session->context->port)
988             session->flags.side = WOLFSSL_SERVER_END;
989         else
990             session->flags.side = WOLFSSL_CLIENT_END;
991     }    
992     
993     return session;
994 }
995
996
997 #ifdef HAVE_SNI
998
999 static int LoadKeyFile(byte** keyBuf, word32* keyBufSz,
1000                 const char* keyFile, int typeKey,
1001                 const char* password)
1002 {
1003     byte* loadBuf;
1004     byte* saveBuf;
1005     long fileSz = 0;
1006     int saveBufSz;
1007     XFILE file;
1008     int ret;
1009
1010     if (keyBuf == NULL || keyBufSz == NULL || keyFile == NULL) {
1011         return -1;
1012     }
1013
1014     file = XFOPEN(keyFile, "rb");
1015     if (file == XBADFILE) return -1;
1016     XFSEEK(file, 0, XSEEK_END);
1017     fileSz = XFTELL(file);
1018     XREWIND(file);
1019
1020     loadBuf = (byte*)malloc(fileSz);
1021     if (loadBuf == NULL) {
1022         XFCLOSE(file);
1023         return -1;
1024     }
1025
1026     ret = (int)XFREAD(loadBuf, fileSz, 1, file);
1027     XFCLOSE(file);
1028
1029     if (typeKey == SSL_FILETYPE_PEM) {
1030         saveBuf = (byte*)malloc(fileSz);
1031
1032         saveBufSz = wolfSSL_KeyPemToDer(loadBuf, (int)fileSz,
1033                                                 saveBuf, (int)fileSz, password);
1034         free(loadBuf);
1035
1036         *keyBuf = saveBuf;
1037         *keyBufSz = (word32)saveBufSz;
1038     }
1039     else {
1040         *keyBuf = loadBuf;
1041         *keyBufSz = (word32)fileSz;
1042     }
1043
1044
1045     if (ret < 0) {
1046         return -1;
1047     }
1048
1049     return ret;
1050 }
1051
1052 #endif
1053
1054
1055 static int SetNamedPrivateKey(const char* name, const char* address, int port,
1056             const char* keyFile, int typeKey, const char* password, char* error)
1057 {
1058     SnifferServer* sniffer;
1059     int            ret;
1060     int            type = (typeKey == FILETYPE_PEM) ? SSL_FILETYPE_PEM :
1061                                                       SSL_FILETYPE_ASN1;
1062     int            isNew = 0;
1063     word32         serverIp;
1064
1065 #ifdef HAVE_SNI
1066     NamedKey* namedKey = NULL;
1067 #endif
1068
1069     (void)name;
1070 #ifdef HAVE_SNI
1071     if (name != NULL) {
1072         namedKey = (NamedKey*)malloc(sizeof(NamedKey));
1073         if (namedKey == NULL) {
1074             SetError(MEMORY_STR, error, NULL, 0);
1075             return -1;
1076         }
1077         XMEMSET(namedKey, 0, sizeof(NamedKey));
1078
1079         namedKey->nameSz = (word32)XSTRLEN(name);
1080         XSTRNCPY(namedKey->name, name, sizeof(namedKey->name));
1081         if (namedKey->nameSz >= sizeof(namedKey->name)) {
1082             namedKey->nameSz = sizeof(namedKey->name) - 1;
1083             namedKey->name[namedKey->nameSz] = '\0';
1084         }
1085
1086         ret = LoadKeyFile(&namedKey->key, &namedKey->keySz,
1087                           keyFile, type, password);
1088         if (ret < 0) {
1089             SetError(KEY_FILE_STR, error, NULL, 0);
1090             FreeNamedKey(namedKey);
1091             return -1;
1092         }
1093     }
1094 #endif
1095
1096     serverIp = inet_addr(address);
1097     sniffer = ServerList;
1098     while (sniffer != NULL &&
1099            (sniffer->server != serverIp || sniffer->port != port)) {
1100         sniffer = sniffer->next;
1101     }
1102
1103     if (sniffer == NULL) {
1104         isNew = 1;
1105         sniffer = (SnifferServer*)malloc(sizeof(SnifferServer));
1106         if (sniffer == NULL) {
1107             SetError(MEMORY_STR, error, NULL, 0);
1108 #ifdef HAVE_SNI
1109             FreeNamedKey(namedKey);
1110 #endif
1111             return -1;
1112         }
1113         InitSnifferServer(sniffer);
1114
1115         XSTRNCPY(sniffer->address, address, MAX_SERVER_ADDRESS-1);
1116         sniffer->address[MAX_SERVER_ADDRESS-1] = '\0';
1117         sniffer->server = serverIp;
1118         sniffer->port = port;
1119
1120         sniffer->ctx = SSL_CTX_new(SSLv3_client_method());
1121         if (!sniffer->ctx) {
1122             SetError(MEMORY_STR, error, NULL, 0);
1123 #ifdef HAVE_SNI
1124             FreeNamedKey(namedKey);
1125 #endif
1126             FreeSnifferServer(sniffer);
1127             return -1;
1128         }
1129     }
1130
1131     if (name == NULL) {
1132         if (password) {
1133             SSL_CTX_set_default_passwd_cb(sniffer->ctx, SetPassword);
1134             SSL_CTX_set_default_passwd_cb_userdata(
1135                                                  sniffer->ctx, (void*)password);
1136         }
1137         ret = SSL_CTX_use_PrivateKey_file(sniffer->ctx, keyFile, type);
1138         if (ret != SSL_SUCCESS) {
1139             SetError(KEY_FILE_STR, error, NULL, 0);
1140             if (isNew)
1141                 FreeSnifferServer(sniffer);
1142             return -1;
1143         }
1144     }
1145 #ifdef HAVE_SNI
1146     else {
1147         LockMutex(&sniffer->namedKeysMutex);
1148         namedKey->next = sniffer->namedKeys;
1149         sniffer->namedKeys = namedKey;
1150         UnLockMutex(&sniffer->namedKeysMutex);
1151     }
1152 #endif
1153
1154     if (isNew) {
1155         sniffer->next = ServerList;
1156         ServerList = sniffer;
1157     }
1158
1159     return 0;
1160 }
1161
1162
1163 #ifdef HAVE_SNI
1164
1165 /* Sets the private key for a specific name, server and port  */
1166 /* returns 0 on success, -1 on error */
1167 int ssl_SetNamedPrivateKey(const char* name,
1168                            const char* address, int port,
1169                            const char* keyFile, int typeKey,
1170                            const char* password, char* error)
1171 {
1172     int ret;
1173
1174     TraceHeader();
1175     TraceSetNamedServer(name, address, port, keyFile);
1176
1177     LockMutex(&ServerListMutex);
1178     ret = SetNamedPrivateKey(name, address, port, keyFile,
1179                              typeKey, password, error);
1180     UnLockMutex(&ServerListMutex);
1181
1182     if (ret == 0)
1183         Trace(NEW_SERVER_STR);
1184
1185     return ret;
1186 }
1187
1188 #endif
1189
1190
1191 /* Sets the private key for a specific server and port  */
1192 /* returns 0 on success, -1 on error */
1193 int ssl_SetPrivateKey(const char* address, int port, const char* keyFile,
1194                       int typeKey, const char* password, char* error)
1195 {
1196     int ret;
1197
1198     TraceHeader();
1199     TraceSetServer(address, port, keyFile);
1200
1201     LockMutex(&ServerListMutex);
1202     ret = SetNamedPrivateKey(NULL, address, port, keyFile,
1203                              typeKey, password, error);
1204     UnLockMutex(&ServerListMutex);
1205
1206     if (ret == 0)
1207         Trace(NEW_SERVER_STR);
1208
1209     return ret;
1210 }
1211
1212
1213 /* Check IP Header for IPV4, TCP, and a registered server address */
1214 /* returns 0 on success, -1 on error */
1215 static int CheckIpHdr(IpHdr* iphdr, IpInfo* info, int length, char* error)
1216 {
1217     int    version = IP_V(iphdr);
1218
1219     TraceIP(iphdr);
1220     Trace(IP_CHECK_STR);
1221
1222     if (version != IPV4) {
1223         SetError(BAD_IPVER_STR, error, NULL, 0); 
1224         return -1;
1225     }
1226
1227     if (iphdr->protocol != TCP_PROTOCOL) { 
1228         SetError(BAD_PROTO_STR, error, NULL, 0);
1229         return -1;
1230     }
1231
1232     if (!IsServerRegistered(iphdr->src) && !IsServerRegistered(iphdr->dst)) {
1233         SetError(SERVER_NOT_REG_STR, error, NULL, 0);
1234         return -1;
1235     }
1236
1237     info->length  = IP_HL(iphdr);
1238     info->total   = ntohs(iphdr->length);
1239     info->src     = iphdr->src;
1240     info->dst     = iphdr->dst;
1241
1242     if (info->total == 0)
1243         info->total = length;  /* reassembled may be off */
1244
1245     return 0;
1246 }
1247
1248
1249 /* Check TCP Header for a registered port */
1250 /* returns 0 on success, -1 on error */
1251 static int CheckTcpHdr(TcpHdr* tcphdr, TcpInfo* info, char* error)
1252 {
1253     TraceTcp(tcphdr);
1254     Trace(TCP_CHECK_STR);
1255     info->srcPort   = ntohs(tcphdr->srcPort);
1256     info->dstPort   = ntohs(tcphdr->dstPort);
1257     info->length    = TCP_LEN(tcphdr);
1258     info->sequence  = ntohl(tcphdr->sequence);
1259     info->fin       = tcphdr->flags & TCP_FIN;
1260     info->rst       = tcphdr->flags & TCP_RST;
1261     info->syn       = tcphdr->flags & TCP_SYN;
1262     info->ack       = tcphdr->flags & TCP_ACK;
1263     if (info->ack)
1264         info->ackNumber = ntohl(tcphdr->ack); 
1265
1266     if (!IsPortRegistered(info->srcPort) && !IsPortRegistered(info->dstPort)) {
1267         SetError(SERVER_PORT_NOT_REG_STR, error, NULL, 0);
1268         return -1;
1269     }
1270
1271     return 0;
1272 }
1273
1274
1275 /* Decode Record Layer Header */
1276 static int GetRecordHeader(const byte* input, RecordLayerHeader* rh, int* size)
1277 {
1278     XMEMCPY(rh, input, RECORD_HEADER_SZ);
1279     *size = (rh->length[0] << 8) | rh->length[1];
1280
1281     if (*size > (MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA))
1282         return LENGTH_ERROR;
1283
1284     return 0;
1285 }
1286
1287
1288 /* Process Client Key Exchange, RSA only */
1289 static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
1290                                     SnifferSession* session, char* error)
1291 {
1292     word32 idx = 0;
1293     RsaKey key;
1294     int    ret;
1295
1296     if (session->sslServer->buffers.key.buffer == NULL ||
1297         session->sslServer->buffers.key.length == 0) {
1298
1299         SetError(RSA_KEY_MISSING_STR, error, session, FATAL_ERROR_STATE);
1300         return -1;
1301     }
1302     ret = wc_InitRsaKey(&key, 0);
1303     if (ret == 0)
1304         ret = wc_RsaPrivateKeyDecode(session->sslServer->buffers.key.buffer,
1305                           &idx, &key, session->sslServer->buffers.key.length);
1306     if (ret == 0) {
1307         int length = wc_RsaEncryptSize(&key);
1308
1309         if (IsTLS(session->sslServer))
1310             input += 2;     /* tls pre length */
1311
1312         if (length > *sslBytes) {
1313             SetError(PARTIAL_INPUT_STR, error, session, FATAL_ERROR_STATE);
1314             wc_FreeRsaKey(&key);
1315             return -1;
1316         }
1317         ret = wc_RsaPrivateDecrypt(input, length,
1318                   session->sslServer->arrays->preMasterSecret,SECRET_LEN, &key);
1319
1320         if (ret != SECRET_LEN) {
1321             SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE);
1322             wc_FreeRsaKey(&key);
1323             return -1;
1324         }
1325         ret = 0;  /* not in error state */
1326         session->sslServer->arrays->preMasterSz = SECRET_LEN;
1327
1328         /* store for client side as well */
1329         XMEMCPY(session->sslClient->arrays->preMasterSecret,
1330                session->sslServer->arrays->preMasterSecret, SECRET_LEN);
1331         session->sslClient->arrays->preMasterSz = SECRET_LEN;
1332
1333         #ifdef SHOW_SECRETS
1334         {
1335             int i;
1336             printf("pre master secret: ");
1337             for (i = 0; i < SECRET_LEN; i++)
1338                 printf("%02x", session->sslServer->arrays->preMasterSecret[i]);
1339             printf("\n");
1340         }
1341         #endif
1342     }
1343     else {
1344         SetError(RSA_DECODE_STR, error, session, FATAL_ERROR_STATE);
1345         wc_FreeRsaKey(&key);
1346         return -1;
1347     }
1348
1349     if (SetCipherSpecs(session->sslServer) != 0) {
1350         SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
1351         wc_FreeRsaKey(&key);
1352         return -1;
1353     }
1354
1355     if (SetCipherSpecs(session->sslClient) != 0) {
1356         SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
1357         wc_FreeRsaKey(&key);
1358         return -1;
1359     }
1360
1361     ret  = MakeMasterSecret(session->sslServer);
1362     ret += MakeMasterSecret(session->sslClient);
1363     ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE);
1364     ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE);
1365
1366     if (ret != 0) {
1367         SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE);
1368         return -1;
1369     }
1370
1371 #ifdef SHOW_SECRETS
1372     {
1373         int i;
1374         printf("server master secret: ");
1375         for (i = 0; i < SECRET_LEN; i++)
1376             printf("%02x", session->sslServer->arrays->masterSecret[i]);
1377         printf("\n");
1378
1379         printf("client master secret: ");
1380         for (i = 0; i < SECRET_LEN; i++)
1381             printf("%02x", session->sslClient->arrays->masterSecret[i]);
1382         printf("\n");
1383
1384         printf("server suite = %d\n", session->sslServer->options.cipherSuite);
1385         printf("client suite = %d\n", session->sslClient->options.cipherSuite);
1386     }
1387 #endif
1388
1389     wc_FreeRsaKey(&key);
1390     return ret;
1391 }
1392
1393
1394 /* Process Session Ticket */
1395 static int ProcessSessionTicket(const byte* input, int* sslBytes,
1396                                 SnifferSession* session, char* error)
1397 {
1398     word16 len;
1399
1400     /* make sure can read through hint and len */
1401     if (TICKET_HINT_LEN + LENGTH_SZ > *sslBytes) {
1402         SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
1403         return -1;
1404     }
1405
1406     input     += TICKET_HINT_LEN;  /* skip over hint */
1407     *sslBytes -= TICKET_HINT_LEN;
1408
1409     len = (word16)((input[0] << 8) | input[1]);
1410     input     += LENGTH_SZ;
1411     *sslBytes -= LENGTH_SZ;
1412
1413     /* make sure can read through ticket */
1414     if (len > *sslBytes || len < ID_LEN) {
1415         SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
1416         return -1;
1417     }
1418
1419     /* store session with macID as sessionID */
1420     session->sslServer->options.haveSessionId = 1;
1421     XMEMCPY(session->sslServer->arrays->sessionID, input + len - ID_LEN,ID_LEN);
1422
1423     return 0;
1424 }
1425
1426
1427 /* Process Server Hello */
1428 static int ProcessServerHello(const byte* input, int* sslBytes,
1429                               SnifferSession* session, char* error)
1430 {
1431     ProtocolVersion pv;
1432     byte            b;
1433     int             toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
1434     int             doResume     = 0;
1435
1436     /* make sure we didn't miss ClientHello */
1437     if (session->flags.clientHello == 0) {
1438         SetError(MISSED_CLIENT_HELLO_STR, error, session, FATAL_ERROR_STATE);
1439         return -1;
1440     }
1441
1442     /* make sure can read through session len */
1443     if (toRead > *sslBytes) {
1444         SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1445         return -1;
1446     }
1447
1448     XMEMCPY(&pv, input, VERSION_SZ);
1449     input     += VERSION_SZ;
1450     *sslBytes -= VERSION_SZ;
1451
1452     session->sslServer->version = pv;
1453     session->sslClient->version = pv;
1454
1455     XMEMCPY(session->sslServer->arrays->serverRandom, input, RAN_LEN);
1456     XMEMCPY(session->sslClient->arrays->serverRandom, input, RAN_LEN);
1457     input    += RAN_LEN;
1458     *sslBytes -= RAN_LEN;
1459
1460     b = *input++;
1461     *sslBytes -= 1;
1462
1463     /* make sure can read through compression */
1464     if ( (b + SUITE_LEN + ENUM_LEN) > *sslBytes) {
1465         SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1466         return -1;
1467     }
1468     if (b) {
1469         XMEMCPY(session->sslServer->arrays->sessionID, input, ID_LEN);
1470         session->sslServer->options.haveSessionId = 1;
1471     }
1472     input     += b;
1473     *sslBytes -= b;
1474
1475     /* cipher suite */
1476     b = *input++;  /* first byte, ECC or not */
1477     session->sslServer->options.cipherSuite0 = b;
1478     session->sslClient->options.cipherSuite0 = b;
1479     b = *input++;
1480     session->sslServer->options.cipherSuite = b;
1481     session->sslClient->options.cipherSuite = b;
1482     *sslBytes -= SUITE_LEN;
1483
1484     /* compression */
1485     b = *input++;
1486     *sslBytes -= ENUM_LEN;
1487
1488     if (b) {
1489         SetError(BAD_COMPRESSION_STR, error, session, FATAL_ERROR_STATE);
1490         return -1;
1491     }
1492
1493     if (session->sslServer->options.haveSessionId &&
1494             XMEMCMP(session->sslServer->arrays->sessionID,
1495                     session->sslClient->arrays->sessionID, ID_LEN) == 0)
1496         doResume = 1;
1497     else if (session->sslClient->options.haveSessionId == 0 &&
1498              session->sslServer->options.haveSessionId == 0 &&
1499              session->ticketID)
1500         doResume = 1;
1501
1502     if (session->ticketID && doResume) {
1503         /* use ticketID to retrieve from session, prefer over sessionID */
1504         XMEMCPY(session->sslServer->arrays->sessionID,session->ticketID,ID_LEN);
1505         session->sslServer->options.haveSessionId = 1;  /* may not have
1506                                                            actual sessionID */
1507     }
1508
1509     if (doResume ) {
1510         int ret = 0;
1511         SSL_SESSION* resume = GetSession(session->sslServer,
1512                                       session->sslServer->arrays->masterSecret);
1513         if (resume == NULL) {
1514             SetError(BAD_SESSION_RESUME_STR, error, session, FATAL_ERROR_STATE);
1515             return -1;
1516         }
1517         /* make sure client has master secret too */
1518         XMEMCPY(session->sslClient->arrays->masterSecret,
1519                session->sslServer->arrays->masterSecret, SECRET_LEN);
1520         session->flags.resuming = 1;
1521
1522         Trace(SERVER_DID_RESUMPTION_STR);
1523         if (SetCipherSpecs(session->sslServer) != 0) {
1524             SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
1525             return -1;
1526         }
1527
1528         if (SetCipherSpecs(session->sslClient) != 0) {
1529             SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
1530             return -1;
1531         }
1532
1533         if (session->sslServer->options.tls) {
1534             ret =  DeriveTlsKeys(session->sslServer);
1535             ret += DeriveTlsKeys(session->sslClient);
1536         }
1537         else {
1538             ret =  DeriveKeys(session->sslServer);
1539             ret += DeriveKeys(session->sslClient);
1540         }
1541         ret += SetKeysSide(session->sslServer, ENCRYPT_AND_DECRYPT_SIDE);
1542         ret += SetKeysSide(session->sslClient, ENCRYPT_AND_DECRYPT_SIDE);
1543
1544         if (ret != 0) {
1545             SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE);
1546             return -1;
1547         }
1548     }
1549 #ifdef SHOW_SECRETS
1550     {
1551         int i;
1552         printf("cipher suite = 0x%02x\n",
1553                session->sslServer->options.cipherSuite);
1554         printf("server random: ");
1555         for (i = 0; i < RAN_LEN; i++)
1556             printf("%02x", session->sslServer->arrays->serverRandom[i]);
1557         printf("\n");
1558     }
1559 #endif
1560     return 0;
1561 }
1562
1563
1564 /* Process normal Client Hello */
1565 static int ProcessClientHello(const byte* input, int* sslBytes,
1566                               SnifferSession* session, char* error)
1567 {
1568     byte   bLen;
1569     word16 len;
1570     int    toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
1571
1572 #ifdef HAVE_SNI
1573     {
1574         byte name[MAX_SERVER_NAME];
1575         word32 nameSz = sizeof(name);
1576         int ret;
1577
1578         ret = wolfSSL_SNI_GetFromBuffer(
1579                              input - HANDSHAKE_HEADER_SZ - RECORD_HEADER_SZ,
1580                              *sslBytes + HANDSHAKE_HEADER_SZ + RECORD_HEADER_SZ,
1581                              WOLFSSL_SNI_HOST_NAME, name, &nameSz);
1582
1583         if (ret == SSL_SUCCESS) {
1584             NamedKey* namedKey;
1585
1586             if (nameSz >= sizeof(name))
1587                 nameSz = sizeof(name) - 1;
1588             name[nameSz] = 0;
1589             LockMutex(&session->context->namedKeysMutex);
1590             namedKey = session->context->namedKeys;
1591             while (namedKey != NULL) {
1592                 if (nameSz == namedKey->nameSz &&
1593                            XSTRNCMP((char*)name, namedKey->name, nameSz) == 0) {
1594                     if (wolfSSL_use_PrivateKey_buffer(session->sslServer,
1595                                             namedKey->key, namedKey->keySz,
1596                                             SSL_FILETYPE_ASN1) != SSL_SUCCESS) {
1597                         UnLockMutex(&session->context->namedKeysMutex);
1598                         SetError(CLIENT_HELLO_LATE_KEY_STR, error, session,
1599                                                              FATAL_ERROR_STATE);
1600                         return -1;
1601                     }
1602                     break;
1603                 }
1604                 else
1605                     namedKey = namedKey->next;
1606             }
1607             UnLockMutex(&session->context->namedKeysMutex);
1608         }
1609     }
1610 #endif
1611
1612     session->flags.clientHello = 1;  /* don't process again */
1613
1614     /* make sure can read up to session len */
1615     if (toRead > *sslBytes) {
1616         SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1617         return -1;
1618     }
1619
1620     /* skip, get negotiated one from server hello */
1621     input     += VERSION_SZ;
1622     *sslBytes -= VERSION_SZ;
1623
1624     XMEMCPY(session->sslServer->arrays->clientRandom, input, RAN_LEN);
1625     XMEMCPY(session->sslClient->arrays->clientRandom, input, RAN_LEN);
1626
1627     input     += RAN_LEN;
1628     *sslBytes -= RAN_LEN;
1629
1630     /* store session in case trying to resume */
1631     bLen = *input++;
1632     *sslBytes -= ENUM_LEN;
1633     if (bLen) {
1634         if (ID_LEN > *sslBytes) {
1635             SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1636             return -1;
1637         }
1638         Trace(CLIENT_RESUME_TRY_STR);
1639         XMEMCPY(session->sslClient->arrays->sessionID, input, ID_LEN);
1640         session->sslClient->options.haveSessionId = 1;
1641     }
1642 #ifdef SHOW_SECRETS
1643     {
1644         int i;
1645         printf("client random: ");
1646         for (i = 0; i < RAN_LEN; i++)
1647             printf("%02x", session->sslServer->arrays->clientRandom[i]);
1648         printf("\n");
1649     }
1650 #endif
1651
1652     input     += bLen;
1653     *sslBytes -= bLen;
1654
1655     /* skip cipher suites */
1656     /* make sure can read len */
1657     if (SUITE_LEN > *sslBytes) {
1658         SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1659         return -1;
1660     }
1661     len = (word16)((input[0] << 8) | input[1]);
1662     input     += SUITE_LEN;
1663     *sslBytes -= SUITE_LEN;
1664     /* make sure can read suites + comp len */
1665     if (len + ENUM_LEN > *sslBytes) {
1666         SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1667         return -1;
1668     }
1669     input     += len;
1670     *sslBytes -= len;
1671
1672     /* skip compression */
1673     bLen       = *input++;
1674     *sslBytes -= ENUM_LEN;
1675     /* make sure can read len */
1676     if (bLen > *sslBytes) {
1677         SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1678         return -1;
1679     }
1680     input     += bLen;
1681     *sslBytes -= bLen;
1682   
1683     if (*sslBytes == 0) {
1684         /* no extensions */
1685         return 0;
1686     }
1687     
1688     /* skip extensions until session ticket */
1689     /* make sure can read len */
1690     if (SUITE_LEN > *sslBytes) {
1691         SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1692         return -1;
1693     }
1694     len = (word16)((input[0] << 8) | input[1]);
1695     input     += SUITE_LEN;
1696     *sslBytes -= SUITE_LEN;
1697     /* make sure can read through all extensions */
1698     if (len > *sslBytes) {
1699         SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1700         return -1;
1701     }
1702
1703     while (len > EXT_TYPE_SZ + LENGTH_SZ) {
1704         byte   extType[EXT_TYPE_SZ];
1705         word16 extLen;
1706
1707         extType[0] = input[0];
1708         extType[1] = input[1];
1709         input     += EXT_TYPE_SZ;
1710         *sslBytes -= EXT_TYPE_SZ;
1711
1712         extLen = (word16)((input[0] << 8) | input[1]);
1713         input     += LENGTH_SZ;
1714         *sslBytes -= LENGTH_SZ;
1715
1716         /* make sure can read through individual extension */
1717         if (extLen > *sslBytes) {
1718             SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
1719             return -1;
1720         }
1721
1722         if (extType[0] == 0x00 && extType[1] == TICKET_EXT_ID) {
1723
1724             /* make sure can read through ticket if there is a non blank one */
1725             if (extLen && extLen < ID_LEN) {
1726                 SetError(CLIENT_HELLO_INPUT_STR, error, session,
1727                          FATAL_ERROR_STATE);
1728                 return -1;
1729             }
1730
1731             if (extLen) {
1732                 if (session->ticketID == 0) {
1733                     session->ticketID = (byte*)malloc(ID_LEN);
1734                     if (session->ticketID == 0) {
1735                         SetError(MEMORY_STR, error, session,
1736                                  FATAL_ERROR_STATE);
1737                         return -1;
1738                     }
1739                 }
1740                 XMEMCPY(session->ticketID, input + extLen - ID_LEN, ID_LEN);
1741             }
1742         }
1743
1744         input     += extLen;
1745         *sslBytes -= extLen;
1746         len       -= extLen + EXT_TYPE_SZ + LENGTH_SZ;
1747     }
1748
1749     return 0;
1750 }
1751
1752
1753 /* Process Finished */
1754 static int ProcessFinished(const byte* input, int size, int* sslBytes,
1755                            SnifferSession* session, char* error)
1756 {
1757     SSL*   ssl;
1758     word32 inOutIdx = 0;
1759     int    ret;
1760                 
1761     if (session->flags.side == WOLFSSL_SERVER_END)
1762         ssl = session->sslServer;
1763     else
1764         ssl = session->sslClient;
1765
1766     ret = DoFinished(ssl, input, &inOutIdx, (word32) size, (word32) *sslBytes,
1767                                                                          SNIFF);
1768     *sslBytes -= (int)inOutIdx;
1769
1770     if (ret < 0) {
1771         SetError(BAD_FINISHED_MSG, error, session, FATAL_ERROR_STATE);
1772         return ret;
1773     }
1774                 
1775     if (ret == 0 && session->flags.cached == 0) {
1776         if (session->sslServer->options.haveSessionId) {
1777             WOLFSSL_SESSION* sess = GetSession(session->sslServer, NULL);
1778             if (sess == NULL)
1779                 AddSession(session->sslServer);  /* don't re add */
1780             session->flags.cached = 1;
1781          }
1782     }
1783
1784     /* If receiving a finished message from one side, free the resources
1785      * from the other side's tracker. */
1786     if (session->flags.side == WOLFSSL_SERVER_END)
1787         FreeHandshakeResources(session->sslClient);
1788     else
1789         FreeHandshakeResources(session->sslServer);
1790
1791     return ret;
1792 }
1793
1794
1795 /* Process HandShake input */
1796 static int DoHandShake(const byte* input, int* sslBytes,
1797                        SnifferSession* session, char* error)
1798 {
1799     byte type;
1800     int  size;
1801     int  ret = 0;
1802     int  startBytes;
1803
1804     if (*sslBytes < HANDSHAKE_HEADER_SZ) {
1805         SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE);
1806         return -1;
1807     }
1808     type = input[0];
1809     size = (input[1] << 16) | (input[2] << 8) | input[3];
1810     
1811     input     += HANDSHAKE_HEADER_SZ;
1812     *sslBytes -= HANDSHAKE_HEADER_SZ;
1813     startBytes = *sslBytes;
1814
1815     if (*sslBytes < size) {
1816         SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE);
1817         return -1;
1818     }
1819     
1820     switch (type) {
1821         case hello_verify_request:
1822             Trace(GOT_HELLO_VERIFY_STR);
1823             break;
1824         case hello_request:
1825             Trace(GOT_HELLO_REQUEST_STR);
1826             break;
1827         case session_ticket:
1828             Trace(GOT_SESSION_TICKET_STR);
1829             ret = ProcessSessionTicket(input, sslBytes, session, error);
1830             break;
1831         case server_hello:
1832             Trace(GOT_SERVER_HELLO_STR);
1833             ret = ProcessServerHello(input, sslBytes, session, error);
1834             break;
1835         case certificate_request:
1836             Trace(GOT_CERT_REQ_STR);
1837             break;
1838         case server_key_exchange:
1839             Trace(GOT_SERVER_KEY_EX_STR);
1840             /* can't know temp key passively */
1841             SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
1842             ret = -1;
1843             break;
1844         case certificate:
1845             Trace(GOT_CERT_STR);
1846             break;
1847         case server_hello_done:
1848             Trace(GOT_SERVER_HELLO_DONE_STR);
1849             break;
1850         case finished:
1851             Trace(GOT_FINISHED_STR);
1852             ret = ProcessFinished(input, size, sslBytes, session, error);
1853             break;
1854         case client_hello:
1855             Trace(GOT_CLIENT_HELLO_STR);
1856             ret = ProcessClientHello(input, sslBytes, session, error);
1857             break;
1858         case client_key_exchange:
1859             Trace(GOT_CLIENT_KEY_EX_STR);
1860             ret = ProcessClientKeyExchange(input, sslBytes, session, error);
1861             break;
1862         case certificate_verify:
1863             Trace(GOT_CERT_VER_STR);
1864             break;
1865         case certificate_status:
1866             Trace(GOT_CERT_STATUS_STR);
1867             break;
1868         default:
1869             SetError(GOT_UNKNOWN_HANDSHAKE_STR, error, session, 0);
1870             return -1;
1871     }
1872
1873     *sslBytes = startBytes - size;  /* actual bytes of full process */
1874
1875     return ret;
1876 }
1877
1878
1879 /* Decrypt input into plain output, 0 on success */
1880 static int Decrypt(SSL* ssl, byte* output, const byte* input, word32 sz)
1881 {
1882     int ret = 0;
1883
1884     switch (ssl->specs.bulk_cipher_algorithm) {
1885         #ifdef BUILD_ARC4
1886         case wolfssl_rc4:
1887             wc_Arc4Process(ssl->decrypt.arc4, output, input, sz);
1888             break;
1889         #endif
1890             
1891         #ifdef BUILD_DES3
1892         case wolfssl_triple_des:
1893             ret = wc_Des3_CbcDecrypt(ssl->decrypt.des3, output, input, sz);
1894             break;
1895         #endif
1896             
1897         #ifdef BUILD_AES
1898         case wolfssl_aes:
1899             ret = wc_AesCbcDecrypt(ssl->decrypt.aes, output, input, sz);
1900             break;
1901         #endif
1902             
1903         #ifdef HAVE_HC128
1904         case wolfssl_hc128:
1905             wc_Hc128_Process(ssl->decrypt.hc128, output, input, sz);
1906             break;
1907         #endif
1908             
1909         #ifdef BUILD_RABBIT
1910         case wolfssl_rabbit:
1911             wc_RabbitProcess(ssl->decrypt.rabbit, output, input, sz);
1912             break;
1913         #endif
1914
1915         #ifdef HAVE_CAMELLIA 
1916         case wolfssl_camellia:
1917             wc_CamelliaCbcDecrypt(ssl->decrypt.cam, output, input, sz);
1918             break;
1919         #endif
1920
1921         default:
1922             Trace(BAD_DECRYPT_TYPE);
1923             ret = -1;
1924             break;
1925     }
1926
1927     return ret;
1928 }
1929
1930
1931 /* Decrypt input message into output, adjust output steam if needed */
1932 static const byte* DecryptMessage(SSL* ssl, const byte* input, word32 sz,
1933                                   byte* output, int* error, int* advance)
1934 {
1935     int ivExtra = 0;
1936
1937     int ret = Decrypt(ssl, output, input, sz);
1938     if (ret != 0) {
1939         *error = ret;
1940         return NULL;
1941     }
1942     ssl->keys.encryptSz = sz;
1943     if (ssl->options.tls1_1 && ssl->specs.cipher_type == block) {
1944         output += ssl->specs.block_size;     /* go past TLSv1.1 IV */
1945         ivExtra = ssl->specs.block_size;
1946         *advance = ssl->specs.block_size;
1947     }
1948
1949     ssl->keys.padSz = ssl->specs.hash_size;
1950
1951     if (ssl->specs.cipher_type == block)
1952         ssl->keys.padSz += *(output + sz - ivExtra - 1) + 1;
1953     
1954     return output;
1955 }
1956
1957
1958 /* remove session from table, use rowHint if no info (means we have a lock) */
1959 static void RemoveSession(SnifferSession* session, IpInfo* ipInfo,
1960                         TcpInfo* tcpInfo, word32 rowHint)
1961 {
1962     SnifferSession* previous = 0;
1963     SnifferSession* current;
1964     word32          row = rowHint;
1965     int             haveLock = 0;
1966    
1967     if (ipInfo && tcpInfo)
1968         row = SessionHash(ipInfo, tcpInfo);
1969     else
1970         haveLock = 1;
1971     
1972     assert(row <= HASH_SIZE);
1973     Trace(REMOVE_SESSION_STR);
1974     
1975     if (!haveLock)
1976         LockMutex(&SessionMutex);
1977     
1978     current = SessionTable[row];
1979     
1980     while (current) {
1981         if (current == session) {
1982             if (previous)
1983                 previous->next = current->next;
1984             else
1985                 SessionTable[row] = current->next;
1986             FreeSnifferSession(session);
1987             TraceRemovedSession();
1988             break;
1989         }
1990         previous = current;
1991         current  = current->next;
1992     }
1993     
1994     if (!haveLock)
1995         UnLockMutex(&SessionMutex);
1996 }
1997
1998
1999 /* Remove stale sessions from the Session Table, have a lock */
2000 static void RemoveStaleSessions(void)
2001 {
2002     word32 i;
2003     SnifferSession* session;
2004     
2005     for (i = 0; i < HASH_SIZE; i++) {
2006         session = SessionTable[i];
2007         while (session) {
2008             SnifferSession* next = session->next; 
2009             if (time(NULL) >= session->lastUsed + WOLFSSL_SNIFFER_TIMEOUT) {
2010                 TraceStaleSession();
2011                 RemoveSession(session, NULL, NULL, i);
2012             }
2013             session = next;
2014         }
2015     }
2016 }
2017
2018
2019 /* Create a new Sniffer Session */
2020 static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
2021                                      char* error)
2022 {
2023     SnifferSession* session = 0;
2024     int row;
2025         
2026     Trace(NEW_SESSION_STR);
2027     /* create a new one */
2028     session = (SnifferSession*)malloc(sizeof(SnifferSession));
2029     if (session == NULL) {
2030         SetError(MEMORY_STR, error, NULL, 0);
2031         return 0;
2032     }
2033     InitSession(session);
2034     session->server  = ipInfo->dst;
2035     session->client  = ipInfo->src;
2036     session->srvPort = (word16)tcpInfo->dstPort;
2037     session->cliPort = (word16)tcpInfo->srcPort;
2038     session->cliSeqStart = tcpInfo->sequence;
2039     session->cliExpected = 1;  /* relative */
2040     session->lastUsed= time(NULL);
2041                 
2042     session->context = GetSnifferServer(ipInfo, tcpInfo);
2043     if (session->context == NULL) {
2044         SetError(SERVER_NOT_REG_STR, error, NULL, 0);
2045         free(session);
2046         return 0;
2047     }
2048         
2049     session->sslServer = SSL_new(session->context->ctx);
2050     if (session->sslServer == NULL) {
2051         SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE);
2052         free(session);
2053         return 0;
2054     }
2055     session->sslClient = SSL_new(session->context->ctx);
2056     if (session->sslClient == NULL) {
2057         SSL_free(session->sslServer);
2058         session->sslServer = 0;
2059
2060         SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE);
2061         free(session);
2062         return 0;
2063     }
2064     /* put server back into server mode */
2065     session->sslServer->options.side = WOLFSSL_SERVER_END;
2066         
2067     row = SessionHash(ipInfo, tcpInfo);
2068     
2069     /* add it to the session table */
2070     LockMutex(&SessionMutex);
2071         
2072     session->next = SessionTable[row];
2073     SessionTable[row] = session;
2074     
2075     SessionCount++;
2076     
2077     if ( (SessionCount % HASH_SIZE) == 0) {
2078         TraceFindingStale();
2079         RemoveStaleSessions();
2080     }
2081         
2082     UnLockMutex(&SessionMutex);
2083         
2084     /* determine headed side */
2085     if (ipInfo->dst == session->context->server &&
2086         tcpInfo->dstPort == session->context->port)
2087         session->flags.side = WOLFSSL_SERVER_END;
2088     else
2089         session->flags.side = WOLFSSL_CLIENT_END;        
2090     
2091     return session;
2092 }
2093
2094
2095 #ifdef OLD_HELLO_ALLOWED
2096
2097 /* Process Old Client Hello Input */
2098 static int DoOldHello(SnifferSession* session, const byte* sslFrame,
2099                       int* rhSize, int* sslBytes, char* error)
2100 {
2101     const byte* input = sslFrame;
2102     byte        b0, b1;
2103     word32      idx = 0;
2104     int         ret;
2105
2106     Trace(GOT_OLD_CLIENT_HELLO_STR);
2107     session->flags.clientHello = 1;    /* don't process again */
2108     b0 = *input++;
2109     b1 = *input++;
2110     *sslBytes -= 2;
2111     *rhSize = ((b0 & 0x7f) << 8) | b1;
2112
2113     if (*rhSize > *sslBytes) {
2114         SetError(OLD_CLIENT_INPUT_STR, error, session, FATAL_ERROR_STATE);
2115         return -1;
2116     }
2117
2118     ret = ProcessOldClientHello(session->sslServer, input, &idx, *sslBytes,
2119                                 (word16)*rhSize);    
2120     if (ret < 0 && ret != MATCH_SUITE_ERROR) {
2121         SetError(BAD_OLD_CLIENT_STR, error, session, FATAL_ERROR_STATE);
2122         return -1;
2123     }
2124     
2125     Trace(OLD_CLIENT_OK_STR);
2126     XMEMCPY(session->sslClient->arrays->clientRandom,
2127            session->sslServer->arrays->clientRandom, RAN_LEN);
2128     
2129     *sslBytes -= *rhSize;
2130     return 0;
2131 }
2132
2133 #endif /* OLD_HELLO_ALLOWED */
2134
2135
2136 #if 0
2137 /* Calculate the TCP checksum, see RFC 1071 */
2138 /* return 0 for success, -1 on error */
2139 /* can be called from decode() with
2140    TcpChecksum(&ipInfo, &tcpInfo, sslBytes, packet + ipInfo.length);
2141    could also add a 64bit version if type available and using this
2142 */
2143 int TcpChecksum(IpInfo* ipInfo, TcpInfo* tcpInfo, int dataLen,
2144                 const byte* packet)
2145 {
2146     TcpPseudoHdr  pseudo;
2147     int           count = PSEUDO_HDR_SZ;
2148     const word16* data = (word16*)&pseudo;
2149     word32        sum = 0;
2150     word16        checksum;
2151     
2152     pseudo.src = ipInfo->src;
2153     pseudo.dst = ipInfo->dst;
2154     pseudo.rsv = 0;
2155     pseudo.protocol = TCP_PROTO;
2156     pseudo.legnth = htons(tcpInfo->length + dataLen);
2157     
2158     /* pseudo header sum */
2159     while (count >= 2) {
2160         sum   += *data++;
2161         count -= 2;
2162     }
2163     
2164     count = tcpInfo->length + dataLen;
2165     data = (word16*)packet;
2166     
2167     /* main sum */
2168     while (count > 1) {
2169         sum   += *data++;
2170         count -=2;
2171     }
2172     
2173     /* get left-over, if any */
2174     packet = (byte*)data;
2175     if (count > 0) {
2176         sum += *packet;
2177     }
2178     
2179     /* fold 32bit sum into 16 bits */
2180     while (sum >> 16)
2181         sum = (sum & 0xffff) + (sum >> 16);
2182     
2183     checksum = (word16)~sum;
2184     /* checksum should now equal 0, since included already calcd checksum */
2185     /* field, but tcp checksum offloading could negate calculation */
2186     if (checksum == 0)
2187         return 0;
2188     return -1;
2189 }
2190 #endif
2191
2192
2193 /* Check IP and TCP headers, set payload */
2194 /* returns 0 on success, -1 on error */
2195 static int CheckHeaders(IpInfo* ipInfo, TcpInfo* tcpInfo, const byte* packet,
2196                   int length, const byte** sslFrame, int* sslBytes, char* error)
2197 {
2198     TraceHeader();
2199     TracePacket();
2200
2201     /* ip header */
2202     if (length < IP_HDR_SZ) {
2203         SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
2204         return -1;
2205     }
2206     if (CheckIpHdr((IpHdr*)packet, ipInfo, length, error) != 0)
2207         return -1;
2208    
2209     /* tcp header */ 
2210     if (length < (ipInfo->length + TCP_HDR_SZ)) {
2211         SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
2212         return -1;
2213     }
2214     if (CheckTcpHdr((TcpHdr*)(packet + ipInfo->length), tcpInfo, error) != 0)
2215         return -1;
2216    
2217     /* setup */ 
2218     *sslFrame = packet + ipInfo->length + tcpInfo->length;
2219     if (*sslFrame > packet + length) {
2220         SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
2221         return -1;
2222     }
2223     *sslBytes = (int)(packet + length - *sslFrame);
2224     
2225     return 0;
2226 }
2227
2228
2229 /* Create or Find existing session */
2230 /* returns 0 on success (continue), -1 on error, 1 on success (end) */
2231 static int CheckSession(IpInfo* ipInfo, TcpInfo* tcpInfo, int sslBytes,
2232                         SnifferSession** session, char* error)
2233 {
2234     /* create a new SnifferSession on client SYN */
2235     if (tcpInfo->syn && !tcpInfo->ack) {
2236         TraceClientSyn(tcpInfo->sequence);
2237         *session = CreateSession(ipInfo, tcpInfo, error);
2238         if (*session == NULL) {
2239             *session = GetSnifferSession(ipInfo, tcpInfo);
2240             /* already had exisiting, so OK */
2241             if (*session)
2242                 return 1;
2243             
2244             SetError(MEMORY_STR, error, NULL, 0);
2245             return -1;
2246         }
2247         return 1;
2248     }
2249     /* get existing sniffer session */
2250     else {
2251         *session = GetSnifferSession(ipInfo, tcpInfo);
2252         if (*session == NULL) {
2253             /* don't worry about extraneous RST or duplicate FINs */
2254             if (tcpInfo->fin || tcpInfo->rst)
2255                 return 1;
2256             /* don't worry about duplicate ACKs either */
2257             if (sslBytes == 0 && tcpInfo->ack)
2258                 return 1;
2259             
2260             SetError(BAD_SESSION_STR, error, NULL, 0);
2261             return -1;
2262         }        
2263     }
2264     return 0;
2265 }
2266
2267
2268 /* Create a Packet Buffer from *begin - end, adjust new *begin and bytesLeft */
2269 static PacketBuffer* CreateBuffer(word32* begin, word32 end, const byte* data,
2270                                   int* bytesLeft)
2271 {
2272     PacketBuffer* pb;
2273     
2274     int added = end - *begin + 1;
2275     assert(*begin <= end);
2276     
2277     pb = (PacketBuffer*)malloc(sizeof(PacketBuffer));
2278     if (pb == NULL) return NULL;
2279     
2280     pb->next  = 0;
2281     pb->begin = *begin;
2282     pb->end   = end;
2283     pb->data = (byte*)malloc(added);
2284     
2285     if (pb->data == NULL) {
2286         free(pb);
2287         return NULL;
2288     }
2289     XMEMCPY(pb->data, data, added);
2290     
2291     *bytesLeft -= added;
2292     *begin      = pb->end + 1;
2293     
2294     return pb;
2295 }
2296
2297
2298 /* Add sslFrame to Reassembly List */
2299 /* returns 1 (end) on success, -1, on error */
2300 static int AddToReassembly(byte from, word32 seq, const byte* sslFrame,
2301                            int sslBytes, SnifferSession* session, char* error)
2302 {
2303     PacketBuffer*  add;
2304     PacketBuffer** front = (from == WOLFSSL_SERVER_END) ?
2305                        &session->cliReassemblyList: &session->srvReassemblyList;
2306     PacketBuffer*  curr = *front;
2307     PacketBuffer*  prev = curr;
2308     
2309     word32  startSeq = seq;
2310     word32  added;
2311     int     bytesLeft = sslBytes;  /* could be overlapping fragment */
2312
2313     /* if list is empty add full frame to front */
2314     if (!curr) {
2315         add = CreateBuffer(&seq, seq + sslBytes - 1, sslFrame, &bytesLeft);
2316         if (add == NULL) {
2317             SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
2318             return -1;
2319         }
2320         *front = add;
2321         return 1;
2322     }
2323     
2324     /* add to front if before current front, up to next->begin */
2325     if (seq < curr->begin) {
2326         word32 end = seq + sslBytes - 1;
2327         
2328         if (end >= curr->begin)
2329             end = curr->begin - 1;
2330         
2331         add = CreateBuffer(&seq, end, sslFrame, &bytesLeft);
2332         if (add == NULL) {
2333             SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
2334             return -1;
2335         }
2336         add->next = curr;
2337         *front = add;
2338     }
2339     
2340     /* while we have bytes left, try to find a gap to fill */
2341     while (bytesLeft > 0) {
2342         /* get previous packet in list */
2343         while (curr && (seq >= curr->begin)) {
2344             prev = curr;
2345             curr = curr->next;
2346         }
2347         
2348         /* don't add  duplicate data */
2349         if (prev->end >= seq) {
2350             if ( (seq + bytesLeft - 1) <= prev->end)
2351                 return 1;
2352             seq = prev->end + 1;
2353             bytesLeft = startSeq + sslBytes - seq;
2354         }
2355         
2356         if (!curr)
2357             /* we're at the end */
2358             added = bytesLeft;
2359         else 
2360             /* we're in between two frames */
2361             added = min((word32)bytesLeft, curr->begin - seq);
2362         
2363         /* data already there */
2364         if (added == 0)
2365             continue;
2366         
2367         add = CreateBuffer(&seq, seq + added - 1, &sslFrame[seq - startSeq],
2368                            &bytesLeft);
2369         if (add == NULL) {
2370             SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
2371             return -1;
2372         }
2373         add->next  = prev->next;
2374         prev->next = add;
2375     }
2376     return 1;
2377 }
2378
2379
2380 /* Add out of order FIN capture */
2381 /* returns 1 for success (end) */
2382 static int AddFinCapture(SnifferSession* session, word32 sequence)
2383 {
2384     if (session->flags.side == WOLFSSL_SERVER_END) {
2385         if (session->finCaputre.cliCounted == 0)
2386             session->finCaputre.cliFinSeq = sequence;
2387     }
2388     else {
2389         if (session->finCaputre.srvCounted == 0)
2390             session->finCaputre.srvFinSeq = sequence;
2391     }
2392     return 1;
2393 }
2394
2395
2396 /* Adjust incoming sequence based on side */
2397 /* returns 0 on success (continue), -1 on error, 1 on success (end) */
2398 static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
2399                           int* sslBytes, const byte** sslFrame, char* error)
2400 {
2401     word32  seqStart = (session->flags.side == WOLFSSL_SERVER_END) ? 
2402                                      session->cliSeqStart :session->srvSeqStart;
2403     word32  real     = tcpInfo->sequence - seqStart;
2404     word32* expected = (session->flags.side == WOLFSSL_SERVER_END) ?
2405                                   &session->cliExpected : &session->srvExpected;
2406     PacketBuffer* reassemblyList = (session->flags.side == WOLFSSL_SERVER_END) ?
2407                         session->cliReassemblyList : session->srvReassemblyList;
2408     
2409     /* handle rollover of sequence */
2410     if (tcpInfo->sequence < seqStart)
2411         real = 0xffffffffU - seqStart + tcpInfo->sequence;
2412         
2413     TraceRelativeSequence(*expected, real);
2414     
2415     if (real < *expected) {
2416         Trace(DUPLICATE_STR);
2417         if (real + *sslBytes > *expected) {
2418             int overlap = *expected - real;
2419             Trace(OVERLAP_DUPLICATE_STR);
2420                 
2421             /* adjust to expected, remove duplicate */
2422             *sslFrame += overlap;
2423             *sslBytes -= overlap;
2424                 
2425             if (reassemblyList) {
2426                 word32 newEnd = *expected + *sslBytes;
2427                     
2428                 if (newEnd > reassemblyList->begin) {
2429                     Trace(OVERLAP_REASSEMBLY_BEGIN_STR);
2430                     
2431                     /* remove bytes already on reassembly list */
2432                     *sslBytes -= newEnd - reassemblyList->begin;
2433                 }
2434                 if (newEnd > reassemblyList->end) {
2435                     Trace(OVERLAP_REASSEMBLY_END_STR);
2436                     
2437                     /* may be past reassembly list end (could have more on list)
2438                        so try to add what's past the front->end */
2439                     AddToReassembly(session->flags.side, reassemblyList->end +1,
2440                                 *sslFrame + reassemblyList->end - *expected + 1,
2441                                  newEnd - reassemblyList->end, session, error);
2442                 }
2443             }
2444         }
2445         else
2446             return 1;
2447     }
2448     else if (real > *expected) {
2449         Trace(OUT_OF_ORDER_STR);
2450         if (*sslBytes > 0)
2451             return AddToReassembly(session->flags.side, real, *sslFrame,
2452                                    *sslBytes, session, error);
2453         else if (tcpInfo->fin)
2454             return AddFinCapture(session, real);
2455     }
2456     /* got expected sequence */
2457     *expected += *sslBytes;
2458     if (tcpInfo->fin)
2459         *expected += 1;
2460     
2461     return 0;
2462 }
2463
2464
2465 /* Check latest ack number for missing packets
2466    return 0 ok, <0 on error */
2467 static int CheckAck(TcpInfo* tcpInfo, SnifferSession* session)
2468 {
2469     if (tcpInfo->ack) {
2470         word32  seqStart = (session->flags.side == WOLFSSL_SERVER_END) ? 
2471                                      session->srvSeqStart :session->cliSeqStart;
2472         word32  real     = tcpInfo->ackNumber - seqStart;
2473         word32  expected = (session->flags.side == WOLFSSL_SERVER_END) ?
2474                                   session->srvExpected : session->cliExpected;
2475     
2476         /* handle rollover of sequence */
2477         if (tcpInfo->ackNumber < seqStart)
2478             real = 0xffffffffU - seqStart + tcpInfo->ackNumber;
2479         
2480         TraceAck(real, expected);
2481
2482         if (real > expected)
2483             return -1;  /* we missed a packet, ACKing data we never saw */
2484     }
2485     return 0;
2486 }
2487
2488
2489 /* Check TCP Sequence status */
2490 /* returns 0 on success (continue), -1 on error, 1 on success (end) */
2491 static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo,
2492                          SnifferSession* session, int* sslBytes,
2493                          const byte** sslFrame, char* error)
2494 {
2495     int actualLen;
2496     
2497     /* init SEQ from server to client */
2498     if (tcpInfo->syn && tcpInfo->ack) {
2499         session->srvSeqStart = tcpInfo->sequence;
2500         session->srvExpected = 1;
2501         TraceServerSyn(tcpInfo->sequence);
2502         return 1;
2503     }
2504     
2505     /* adjust potential ethernet trailer */
2506     actualLen = ipInfo->total - ipInfo->length - tcpInfo->length;
2507     if (*sslBytes > actualLen) {
2508         *sslBytes = actualLen;
2509     }
2510     
2511     TraceSequence(tcpInfo->sequence, *sslBytes);
2512     if (CheckAck(tcpInfo, session) < 0) {
2513         SetError(ACK_MISSED_STR, error, session, FATAL_ERROR_STATE);
2514         return -1;
2515     }
2516     
2517     return AdjustSequence(tcpInfo, session, sslBytes, sslFrame, error);    
2518 }
2519
2520
2521 /* Check Status before record processing */
2522 /* returns 0 on success (continue), -1 on error, 1 on success (end) */
2523 static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo,
2524                           const byte** sslFrame, SnifferSession** session,
2525                           int* sslBytes, const byte** end, char* error)
2526 {
2527     word32 length;
2528     SSL*  ssl = ((*session)->flags.side == WOLFSSL_SERVER_END) ?
2529                                   (*session)->sslServer : (*session)->sslClient;
2530     /* remove SnifferSession on 2nd FIN or RST */
2531     if (tcpInfo->fin || tcpInfo->rst) {
2532         /* flag FIN and RST */
2533         if (tcpInfo->fin)
2534             (*session)->flags.finCount += 1;
2535         else if (tcpInfo->rst)
2536             (*session)->flags.finCount += 2;
2537         
2538         if ((*session)->flags.finCount >= 2) {
2539             RemoveSession(*session, ipInfo, tcpInfo, 0);
2540             *session = NULL;
2541             return 1;
2542         }
2543     }
2544     
2545     if ((*session)->flags.fatalError == FATAL_ERROR_STATE) {
2546         SetError(FATAL_ERROR_STR, error, NULL, 0);
2547         return -1;
2548     }
2549     
2550     if (*sslBytes == 0) {
2551         Trace(NO_DATA_STR);
2552         return 1;
2553     }
2554     
2555     /* if current partial data, add to end of partial */
2556     if ( (length = ssl->buffers.inputBuffer.length) ) {
2557         Trace(PARTIAL_ADD_STR);
2558         
2559         if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) {
2560             if (GrowInputBuffer(ssl, *sslBytes, length) < 0) {
2561                 SetError(MEMORY_STR, error, *session, FATAL_ERROR_STATE);
2562                 return -1;
2563             }
2564         }
2565         XMEMCPY(&ssl->buffers.inputBuffer.buffer[length], *sslFrame, *sslBytes);
2566         *sslBytes += length;
2567         ssl->buffers.inputBuffer.length = *sslBytes;
2568         *sslFrame = ssl->buffers.inputBuffer.buffer;
2569         *end = *sslFrame + *sslBytes;
2570     }
2571
2572     if ((*session)->flags.clientHello == 0 && **sslFrame != handshake) {
2573         /* Sanity check the packet for an old style client hello. */
2574         int rhSize = (((*sslFrame)[0] & 0x7f) << 8) | ((*sslFrame)[1]);
2575
2576         if ((rhSize <= (*sslBytes - 2)) &&
2577             (*sslFrame)[2] == OLD_HELLO_ID && (*sslFrame)[3] == SSLv3_MAJOR) {
2578 #ifdef OLD_HELLO_ALLOWED
2579         int ret = DoOldHello(*session, *sslFrame, &rhSize, sslBytes, error);
2580         if (ret < 0)
2581             return -1;  /* error already set */
2582         if (*sslBytes <= 0)
2583             return 1;
2584 #endif
2585         }
2586         else {
2587 #ifdef STARTTLS_ALLOWED
2588             return 1;
2589 #endif
2590         }
2591     }
2592
2593     return 0;
2594 }
2595
2596
2597 /* See if input on the reassembly list is ready for consuming */
2598 /* returns 1 for TRUE, 0 for FALSE */
2599 static int HaveMoreInput(SnifferSession* session, const byte** sslFrame,
2600                          int* sslBytes, const byte** end, char* error)
2601 {
2602     /* sequence and reassembly based on from, not to */
2603     int            moreInput = 0;
2604     PacketBuffer** front = (session->flags.side == WOLFSSL_SERVER_END) ?
2605                       &session->cliReassemblyList : &session->srvReassemblyList;
2606     word32*        expected = (session->flags.side == WOLFSSL_SERVER_END) ?
2607                                   &session->cliExpected : &session->srvExpected;
2608     /* buffer is on receiving end */
2609     word32*        length = (session->flags.side == WOLFSSL_SERVER_END) ?
2610                                &session->sslServer->buffers.inputBuffer.length :
2611                                &session->sslClient->buffers.inputBuffer.length;
2612     byte*          myBuffer = (session->flags.side == WOLFSSL_SERVER_END) ?
2613                                 session->sslServer->buffers.inputBuffer.buffer :
2614                                 session->sslClient->buffers.inputBuffer.buffer;
2615     word32       bufferSize = (session->flags.side == WOLFSSL_SERVER_END) ?
2616                             session->sslServer->buffers.inputBuffer.bufferSize :
2617                             session->sslClient->buffers.inputBuffer.bufferSize;
2618     SSL*               ssl  = (session->flags.side == WOLFSSL_SERVER_END) ?
2619                             session->sslServer : session->sslClient;
2620     
2621     while (*front && ((*front)->begin == *expected) ) {
2622         word32 room = bufferSize - *length;
2623         word32 packetLen = (*front)->end - (*front)->begin + 1;
2624
2625         if (packetLen > room && bufferSize < MAX_INPUT_SZ) {
2626             if (GrowInputBuffer(ssl, packetLen, *length) < 0) {
2627                 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
2628                 return 0;
2629             }
2630         }
2631         
2632         if (packetLen <= room) {
2633             PacketBuffer* del = *front;
2634             
2635             XMEMCPY(&myBuffer[*length], (*front)->data, packetLen);
2636             *length   += packetLen;
2637             *expected += packetLen;
2638             
2639             /* remove used packet */
2640             *front = (*front)->next;
2641             FreePacketBuffer(del);
2642             
2643             moreInput = 1;
2644         }
2645         else
2646             break;
2647     }
2648     if (moreInput) {
2649         *sslFrame = myBuffer;
2650         *sslBytes = *length;
2651         *end      = myBuffer + *length;
2652     }
2653     return moreInput;
2654 }
2655                          
2656
2657
2658 /* Process Message(s) from sslFrame */
2659 /* return Number of bytes on success, 0 for no data yet, and -1 on error */
2660 static int ProcessMessage(const byte* sslFrame, SnifferSession* session,
2661                           int sslBytes, byte* data, const byte* end,char* error)
2662 {
2663     const byte*       sslBegin = sslFrame;
2664     const byte*       recordEnd;   /* end of record indicator */
2665     const byte*       inRecordEnd; /* indictor from input stream not decrypt */
2666     RecordLayerHeader rh;
2667     int               rhSize = 0;
2668     int               ret;
2669     int               errCode = 0;
2670     int               decoded = 0;      /* bytes stored for user in data */
2671     int               notEnough;        /* notEnough bytes yet flag */
2672     int               decrypted = 0;    /* was current msg decrypted */
2673     SSL*              ssl = (session->flags.side == WOLFSSL_SERVER_END) ?
2674                                         session->sslServer : session->sslClient;
2675 doMessage:
2676     notEnough = 0;
2677     if (sslBytes < 0) {
2678         SetError(PACKET_HDR_SHORT_STR, error, session, FATAL_ERROR_STATE);
2679         return -1;
2680     }
2681     if (sslBytes >= RECORD_HEADER_SZ) {
2682         if (GetRecordHeader(sslFrame, &rh, &rhSize) != 0) {
2683             SetError(BAD_RECORD_HDR_STR, error, session, FATAL_ERROR_STATE);
2684             return -1;
2685         }
2686     }
2687     else
2688         notEnough = 1;
2689
2690     if (notEnough || rhSize > (sslBytes - RECORD_HEADER_SZ)) {
2691         /* don't have enough input yet to process full SSL record */
2692         Trace(PARTIAL_INPUT_STR);
2693         
2694         /* store partial if not there already or we advanced */
2695         if (ssl->buffers.inputBuffer.length == 0 || sslBegin != sslFrame) {
2696             if (sslBytes > (int)ssl->buffers.inputBuffer.bufferSize) {
2697                 if (GrowInputBuffer(ssl, sslBytes, 0) < 0) { 
2698                     SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
2699                     return -1;
2700                 }
2701             }
2702             XMEMMOVE(ssl->buffers.inputBuffer.buffer, sslFrame, sslBytes);
2703             ssl->buffers.inputBuffer.length = sslBytes;
2704         }
2705         if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error))
2706             goto doMessage;
2707         return decoded;
2708     }
2709     sslFrame += RECORD_HEADER_SZ;
2710     sslBytes -= RECORD_HEADER_SZ;
2711     recordEnd = sslFrame + rhSize;   /* may have more than one record */
2712     inRecordEnd = recordEnd;
2713     
2714     /* decrypt if needed */
2715     if ((session->flags.side == WOLFSSL_SERVER_END &&
2716                                                session->flags.serverCipherOn)
2717      || (session->flags.side == WOLFSSL_CLIENT_END &&
2718                                                session->flags.clientCipherOn)) {
2719         int ivAdvance = 0;  /* TLSv1.1 advance amount */
2720         if (ssl->decrypt.setup != 1) {
2721             SetError(DECRYPT_KEYS_NOT_SETUP, error, session, FATAL_ERROR_STATE);
2722             return -1;
2723         }
2724         if (CheckAvailableSize(ssl, rhSize) < 0) {
2725             SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
2726             return -1;
2727         }
2728         sslFrame = DecryptMessage(ssl, sslFrame, rhSize,
2729                                   ssl->buffers.outputBuffer.buffer, &errCode,
2730                                   &ivAdvance);
2731         recordEnd = sslFrame - ivAdvance + rhSize;  /* sslFrame moved so
2732                                                        should recordEnd */
2733         decrypted = 1;
2734         if (errCode != 0) {
2735             SetError(BAD_DECRYPT, error, session, FATAL_ERROR_STATE);
2736             return -1;
2737         }
2738     }
2739
2740 doPart:
2741             
2742     switch ((enum ContentType)rh.type) {
2743         case handshake:
2744             {
2745                 int startIdx = sslBytes;
2746                 int used;
2747
2748                 Trace(GOT_HANDSHAKE_STR);
2749                 ret = DoHandShake(sslFrame, &sslBytes, session, error);
2750                 if (ret != 0) {
2751                     if (session->flags.fatalError == 0)
2752                         SetError(BAD_HANDSHAKE_STR, error, session,
2753                                  FATAL_ERROR_STATE);
2754                     return -1;
2755                 }
2756
2757                 /* DoHandShake now fully decrements sslBytes to remaining */
2758                 used = startIdx - sslBytes;
2759                 sslFrame += used;
2760                 if (decrypted)
2761                     sslFrame += ssl->keys.padSz;
2762             }
2763             break;
2764         case change_cipher_spec:
2765             if (session->flags.side == WOLFSSL_SERVER_END)
2766                 session->flags.serverCipherOn = 1;
2767             else
2768                 session->flags.clientCipherOn = 1;
2769             Trace(GOT_CHANGE_CIPHER_STR);
2770             ssl->options.handShakeState = HANDSHAKE_DONE;
2771             ssl->options.handShakeDone  = 1;
2772
2773             sslFrame += 1;
2774             sslBytes -= 1;
2775
2776             break;
2777         case application_data:
2778             Trace(GOT_APP_DATA_STR);
2779             {
2780                 word32 inOutIdx = 0;
2781                     
2782                 ret = DoApplicationData(ssl, (byte*)sslFrame, &inOutIdx);
2783                 if (ret == 0) {
2784                     ret = ssl->buffers.clearOutputBuffer.length;
2785                     TraceGotData(ret);
2786                     if (ret) {  /* may be blank message */
2787                         XMEMCPY(&data[decoded],
2788                                ssl->buffers.clearOutputBuffer.buffer, ret);
2789                         TraceAddedData(ret, decoded);
2790                         decoded += ret;
2791                         ssl->buffers.clearOutputBuffer.length = 0;
2792                     }
2793                 }
2794                 else {
2795                     SetError(BAD_APP_DATA_STR, error,session,FATAL_ERROR_STATE);
2796                     return -1;
2797                 }
2798                 if (ssl->buffers.outputBuffer.dynamicFlag)
2799                     ShrinkOutputBuffer(ssl);
2800
2801                 sslFrame += inOutIdx;
2802                 sslBytes -= inOutIdx;
2803             }
2804             break;
2805         case alert:
2806             Trace(GOT_ALERT_STR);
2807             sslFrame += rhSize;
2808             sslBytes -= rhSize;
2809             break;
2810         case no_type:
2811         default:
2812             SetError(GOT_UNKNOWN_RECORD_STR, error, session, FATAL_ERROR_STATE);
2813             return -1;
2814     }
2815
2816     /* do we have another msg in record ? */
2817     if (sslFrame < recordEnd) {
2818         Trace(ANOTHER_MSG_STR);
2819         goto doPart;
2820     }
2821
2822     /* back to input stream instead of potential decrypt buffer */
2823     recordEnd = inRecordEnd;
2824
2825     /* do we have more records ? */
2826     if (recordEnd < end) {
2827         Trace(ANOTHER_MSG_STR);
2828         sslFrame = recordEnd;
2829         sslBytes = (int)(end - recordEnd);
2830         goto doMessage;
2831     }
2832     
2833     /* clear used input */
2834     ssl->buffers.inputBuffer.length = 0;
2835     
2836     /* could have more input ready now */
2837     if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error))
2838         goto doMessage;
2839
2840     if (ssl->buffers.inputBuffer.dynamicFlag)
2841         ShrinkInputBuffer(ssl, NO_FORCED_FREE);
2842     
2843     return decoded;
2844 }
2845
2846
2847 /* See if we need to process any pending FIN captures */
2848 static void CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo, 
2849                             SnifferSession* session)
2850 {
2851     if (session->finCaputre.cliFinSeq && session->finCaputre.cliFinSeq <= 
2852                                          session->cliExpected) {
2853         if (session->finCaputre.cliCounted == 0) {
2854             session->flags.finCount += 1;
2855             session->finCaputre.cliCounted = 1;
2856             TraceClientFin(session->finCaputre.cliFinSeq, session->cliExpected);
2857         }
2858     }
2859         
2860     if (session->finCaputre.srvFinSeq && session->finCaputre.srvFinSeq <= 
2861                                          session->srvExpected) {
2862         if (session->finCaputre.srvCounted == 0) {
2863             session->flags.finCount += 1;
2864             session->finCaputre.srvCounted = 1;
2865             TraceServerFin(session->finCaputre.srvFinSeq, session->srvExpected);
2866         }
2867     }
2868                 
2869     if (session->flags.finCount >= 2) 
2870         RemoveSession(session, ipInfo, tcpInfo, 0);
2871 }
2872
2873
2874 /* If session is in fatal error state free resources now 
2875    return true if removed, 0 otherwise */
2876 static int RemoveFatalSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
2877                               SnifferSession* session, char* error)
2878 {
2879     if (session && session->flags.fatalError == FATAL_ERROR_STATE) {
2880         RemoveSession(session, ipInfo, tcpInfo, 0);
2881         SetError(FATAL_ERROR_STR, error, NULL, 0);
2882         return 1;
2883     }
2884     return 0;
2885 }
2886
2887
2888 /* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */
2889 /* returns Number of bytes on success, 0 for no data yet, and -1 on error */
2890 int ssl_DecodePacket(const byte* packet, int length, byte* data, char* error)
2891 {
2892     TcpInfo           tcpInfo;
2893     IpInfo            ipInfo;
2894     const byte*       sslFrame;
2895     const byte*       end = packet + length;
2896     int               sslBytes;                /* ssl bytes unconsumed */
2897     int               ret;
2898     SnifferSession*   session = 0;
2899
2900     if (CheckHeaders(&ipInfo, &tcpInfo, packet, length, &sslFrame, &sslBytes,
2901                      error) != 0)
2902         return -1;
2903     
2904     ret = CheckSession(&ipInfo, &tcpInfo, sslBytes, &session, error);
2905     if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
2906     else if (ret == -1) return -1;
2907     else if (ret ==  1) return  0;   /* done for now */
2908     
2909     ret = CheckSequence(&ipInfo, &tcpInfo, session, &sslBytes, &sslFrame,error);
2910     if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
2911     else if (ret == -1) return -1;
2912     else if (ret ==  1) return  0;   /* done for now */
2913     
2914     ret = CheckPreRecord(&ipInfo, &tcpInfo, &sslFrame, &session, &sslBytes,
2915                          &end, error);
2916     if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
2917     else if (ret == -1) return -1;
2918     else if (ret ==  1) return  0;   /* done for now */
2919
2920     ret = ProcessMessage(sslFrame, session, sslBytes, data, end, error);
2921     if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
2922     CheckFinCapture(&ipInfo, &tcpInfo, session);
2923     return ret;
2924 }
2925
2926
2927 /* Enables (if traceFile)/ Disables debug tracing */
2928 /* returns 0 on success, -1 on error */
2929 int ssl_Trace(const char* traceFile, char* error)
2930 {
2931     if (traceFile) {
2932         TraceFile = fopen(traceFile, "a");
2933         if (!TraceFile) {
2934             SetError(BAD_TRACE_FILE_STR, error, NULL, 0);
2935             return -1;
2936         }
2937         TraceOn = 1;
2938     }
2939     else 
2940         TraceOn = 0;
2941
2942     return 0;
2943 }
2944
2945
2946
2947
2948 #endif /* WOLFSSL_SNIFFER */