This is a port of cyaSSL 2.7.0.

Dependents:   CyaSSL_DTLS_Cellular CyaSSL_DTLS_Ethernet

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