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