cyassl re-port with cellular comms, PSK test

Dependencies:   VodafoneUSBModem_bleedingedge2 mbed-rtos mbed-src

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