cyassl re-port with cellular comms, PSK test
Dependencies: VodafoneUSBModem_bleedingedge2 mbed-rtos mbed-src
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 */
Generated on Thu Jul 14 2022 00:25:23 by 1.7.2