Fork of CyaSSL for my specific settings

Dependents:   CyaSSL_Example

Fork of CyaSSL by wolf SSL

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers sniffer.c Source File

sniffer.c

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