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