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