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