This is a port of cyaSSL 2.7.0.

Dependents:   CyaSSL_DTLS_Cellular CyaSSL_DTLS_Ethernet

Committer:
ashleymills
Date:
Thu Sep 05 15:55:50 2013 +0000
Revision:
1:c0ce1562443a
Parent:
0:714293de3836
Nothing;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ashleymills 0:714293de3836 1 /* sniffer.c
ashleymills 0:714293de3836 2 *
ashleymills 0:714293de3836 3 * Copyright (C) 2006-2013 wolfSSL Inc.
ashleymills 0:714293de3836 4 *
ashleymills 0:714293de3836 5 * This file is part of CyaSSL.
ashleymills 0:714293de3836 6 *
ashleymills 0:714293de3836 7 * CyaSSL is free software; you can redistribute it and/or modify
ashleymills 0:714293de3836 8 * it under the terms of the GNU General Public License as published by
ashleymills 0:714293de3836 9 * the Free Software Foundation; either version 2 of the License, or
ashleymills 0:714293de3836 10 * (at your option) any later version.
ashleymills 0:714293de3836 11 *
ashleymills 0:714293de3836 12 * CyaSSL is distributed in the hope that it will be useful,
ashleymills 0:714293de3836 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
ashleymills 0:714293de3836 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
ashleymills 0:714293de3836 15 * GNU General Public License for more details.
ashleymills 0:714293de3836 16 *
ashleymills 0:714293de3836 17 * You should have received a copy of the GNU General Public License
ashleymills 0:714293de3836 18 * along with this program; if not, write to the Free Software
ashleymills 0:714293de3836 19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
ashleymills 0:714293de3836 20 */
ashleymills 0:714293de3836 21
ashleymills 0:714293de3836 22
ashleymills 0:714293de3836 23
ashleymills 0:714293de3836 24 #ifdef HAVE_CONFIG_H
ashleymills 0:714293de3836 25 #include <config.h>
ashleymills 0:714293de3836 26 #endif
ashleymills 0:714293de3836 27
ashleymills 0:714293de3836 28 #include <cyassl/ctaocrypt/settings.h>
ashleymills 0:714293de3836 29
ashleymills 0:714293de3836 30 #ifdef CYASSL_SNIFFER
ashleymills 0:714293de3836 31
ashleymills 0:714293de3836 32 #include <assert.h>
ashleymills 0:714293de3836 33 #include <time.h>
ashleymills 0:714293de3836 34
ashleymills 0:714293de3836 35 #ifndef _WIN32
ashleymills 0:714293de3836 36 #include <arpa/inet.h>
ashleymills 0:714293de3836 37 #endif
ashleymills 0:714293de3836 38
ashleymills 0:714293de3836 39 #ifdef _WIN32
ashleymills 0:714293de3836 40 #define SNPRINTF _snprintf
ashleymills 0:714293de3836 41 #else
ashleymills 0:714293de3836 42 #define SNPRINTF snprintf
ashleymills 0:714293de3836 43 #endif
ashleymills 0:714293de3836 44
ashleymills 0:714293de3836 45 #include <cyassl/openssl/ssl.h>
ashleymills 0:714293de3836 46 #include <cyassl/internal.h>
ashleymills 0:714293de3836 47 #include <cyassl/ctaoerror.h>
ashleymills 0:714293de3836 48 #include <cyassl/sniffer.h>
ashleymills 0:714293de3836 49 #include <cyassl/sniffer_error.h>
ashleymills 0:714293de3836 50
ashleymills 0:714293de3836 51
ashleymills 0:714293de3836 52 #ifndef min
ashleymills 0:714293de3836 53
ashleymills 0:714293de3836 54 static INLINE word32 min(word32 a, word32 b)
ashleymills 0:714293de3836 55 {
ashleymills 0:714293de3836 56 return a > b ? b : a;
ashleymills 0:714293de3836 57 }
ashleymills 0:714293de3836 58
ashleymills 0:714293de3836 59 #endif
ashleymills 0:714293de3836 60
ashleymills 0:714293de3836 61
ashleymills 0:714293de3836 62 /* Misc constants */
ashleymills 0:714293de3836 63 enum {
ashleymills 0:714293de3836 64 MAX_SERVER_ADDRESS = 128, /* maximum server address length */
ashleymills 0:714293de3836 65 MAX_ERROR_LEN = 80, /* maximum error length */
ashleymills 0:714293de3836 66 ETHER_IF_ADDR_LEN = 6, /* ethernet interface address length */
ashleymills 0:714293de3836 67 LOCAL_IF_ADDR_LEN = 4, /* localhost interface address length, !windows */
ashleymills 0:714293de3836 68 TCP_PROTO = 6, /* TCP_PROTOCOL */
ashleymills 0:714293de3836 69 IP_HDR_SZ = 20, /* IP header legnth, min */
ashleymills 0:714293de3836 70 TCP_HDR_SZ = 20, /* TCP header legnth, min */
ashleymills 0:714293de3836 71 IPV4 = 4, /* IP version 4 */
ashleymills 0:714293de3836 72 TCP_PROTOCOL = 6, /* TCP Protocol id */
ashleymills 0:714293de3836 73 TRACE_MSG_SZ = 80, /* Trace Message buffer size */
ashleymills 0:714293de3836 74 HASH_SIZE = 499, /* Session Hash Table Rows */
ashleymills 0:714293de3836 75 PSEUDO_HDR_SZ = 12, /* TCP Pseudo Header size in bytes */
ashleymills 0:714293de3836 76 FATAL_ERROR_STATE = 1, /* SnifferSession fatal error state */
ashleymills 0:714293de3836 77 SNIFFER_TIMEOUT = 900, /* Cache unclosed Sessions for 15 minutes */
ashleymills 0:714293de3836 78 TICKET_HINT_LEN = 4, /* Session Ticket Hint length */
ashleymills 0:714293de3836 79 EXT_TYPE_SZ = 2, /* Extension length */
ashleymills 0:714293de3836 80 MAX_INPUT_SZ = MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA +
ashleymills 0:714293de3836 81 MTU_EXTRA, /* Max input sz of reassembly */
ashleymills 0:714293de3836 82 TICKET_EXT_ID = 0x23 /* Session Ticket Extension ID */
ashleymills 0:714293de3836 83 };
ashleymills 0:714293de3836 84
ashleymills 0:714293de3836 85
ashleymills 0:714293de3836 86 #ifdef _WIN32
ashleymills 0:714293de3836 87
ashleymills 0:714293de3836 88 static HMODULE dllModule; /* for error string resources */
ashleymills 0:714293de3836 89
ashleymills 0:714293de3836 90 BOOL APIENTRY DllMain( HMODULE hModule,
ashleymills 0:714293de3836 91 DWORD ul_reason_for_call,
ashleymills 0:714293de3836 92 LPVOID lpReserved
ashleymills 0:714293de3836 93 )
ashleymills 0:714293de3836 94 {
ashleymills 0:714293de3836 95 static int didInit = 0;
ashleymills 0:714293de3836 96
ashleymills 0:714293de3836 97 switch (ul_reason_for_call)
ashleymills 0:714293de3836 98 {
ashleymills 0:714293de3836 99 case DLL_PROCESS_ATTACH:
ashleymills 0:714293de3836 100 if (didInit == 0) {
ashleymills 0:714293de3836 101 dllModule = hModule;
ashleymills 0:714293de3836 102 ssl_InitSniffer();
ashleymills 0:714293de3836 103 didInit = 1;
ashleymills 0:714293de3836 104 }
ashleymills 0:714293de3836 105 break;
ashleymills 0:714293de3836 106 case DLL_THREAD_ATTACH:
ashleymills 0:714293de3836 107 break;
ashleymills 0:714293de3836 108 case DLL_THREAD_DETACH:
ashleymills 0:714293de3836 109 break;
ashleymills 0:714293de3836 110 case DLL_PROCESS_DETACH:
ashleymills 0:714293de3836 111 if (didInit) {
ashleymills 0:714293de3836 112 ssl_FreeSniffer();
ashleymills 0:714293de3836 113 didInit = 0;
ashleymills 0:714293de3836 114 }
ashleymills 0:714293de3836 115 break;
ashleymills 0:714293de3836 116 }
ashleymills 0:714293de3836 117 return TRUE;
ashleymills 0:714293de3836 118 }
ashleymills 0:714293de3836 119
ashleymills 0:714293de3836 120 #endif /* _WIN32 */
ashleymills 0:714293de3836 121
ashleymills 0:714293de3836 122
ashleymills 0:714293de3836 123 static int TraceOn = 0; /* Trace is off by default */
ashleymills 0:714293de3836 124 static FILE* TraceFile = 0;
ashleymills 0:714293de3836 125
ashleymills 0:714293de3836 126
ashleymills 0:714293de3836 127 /* windows uses .rc table for this */
ashleymills 0:714293de3836 128 #ifndef _WIN32
ashleymills 0:714293de3836 129
ashleymills 0:714293de3836 130 static const char* const msgTable[] =
ashleymills 0:714293de3836 131 {
ashleymills 0:714293de3836 132 /* 1 */
ashleymills 0:714293de3836 133 "Out of Memory",
ashleymills 0:714293de3836 134 "New SSL Sniffer Server Registered",
ashleymills 0:714293de3836 135 "Checking IP Header",
ashleymills 0:714293de3836 136 "SSL Sniffer Server Not Registered",
ashleymills 0:714293de3836 137 "Checking TCP Header",
ashleymills 0:714293de3836 138
ashleymills 0:714293de3836 139 /* 6 */
ashleymills 0:714293de3836 140 "SSL Sniffer Server Port Not Registered",
ashleymills 0:714293de3836 141 "RSA Private Decrypt Error",
ashleymills 0:714293de3836 142 "RSA Private Decode Error",
ashleymills 0:714293de3836 143 "Set Cipher Spec Error",
ashleymills 0:714293de3836 144 "Server Hello Input Malformed",
ashleymills 0:714293de3836 145
ashleymills 0:714293de3836 146 /* 11 */
ashleymills 0:714293de3836 147 "Couldn't Resume Session Error",
ashleymills 0:714293de3836 148 "Server Did Resumption",
ashleymills 0:714293de3836 149 "Client Hello Input Malformed",
ashleymills 0:714293de3836 150 "Client Trying to Resume",
ashleymills 0:714293de3836 151 "Handshake Input Malformed",
ashleymills 0:714293de3836 152
ashleymills 0:714293de3836 153 /* 16 */
ashleymills 0:714293de3836 154 "Got Hello Verify msg",
ashleymills 0:714293de3836 155 "Got Server Hello msg",
ashleymills 0:714293de3836 156 "Got Cert Request msg",
ashleymills 0:714293de3836 157 "Got Server Key Exchange msg",
ashleymills 0:714293de3836 158 "Got Cert msg",
ashleymills 0:714293de3836 159
ashleymills 0:714293de3836 160 /* 21 */
ashleymills 0:714293de3836 161 "Got Server Hello Done msg",
ashleymills 0:714293de3836 162 "Got Finished msg",
ashleymills 0:714293de3836 163 "Got Client Hello msg",
ashleymills 0:714293de3836 164 "Got Client Key Exchange msg",
ashleymills 0:714293de3836 165 "Got Cert Verify msg",
ashleymills 0:714293de3836 166
ashleymills 0:714293de3836 167 /* 26 */
ashleymills 0:714293de3836 168 "Got Unknown Handshake msg",
ashleymills 0:714293de3836 169 "New SSL Sniffer Session created",
ashleymills 0:714293de3836 170 "Couldn't create new SSL",
ashleymills 0:714293de3836 171 "Got a Packet to decode",
ashleymills 0:714293de3836 172 "No data present",
ashleymills 0:714293de3836 173
ashleymills 0:714293de3836 174 /* 31 */
ashleymills 0:714293de3836 175 "Session Not Found",
ashleymills 0:714293de3836 176 "Got an Old Client Hello msg",
ashleymills 0:714293de3836 177 "Old Client Hello Input Malformed",
ashleymills 0:714293de3836 178 "Old Client Hello OK",
ashleymills 0:714293de3836 179 "Bad Old Client Hello",
ashleymills 0:714293de3836 180
ashleymills 0:714293de3836 181 /* 36 */
ashleymills 0:714293de3836 182 "Bad Record Header",
ashleymills 0:714293de3836 183 "Record Header Input Malformed",
ashleymills 0:714293de3836 184 "Got a HandShake msg",
ashleymills 0:714293de3836 185 "Bad HandShake msg",
ashleymills 0:714293de3836 186 "Got a Change Cipher Spec msg",
ashleymills 0:714293de3836 187
ashleymills 0:714293de3836 188 /* 41 */
ashleymills 0:714293de3836 189 "Got Application Data msg",
ashleymills 0:714293de3836 190 "Bad Application Data",
ashleymills 0:714293de3836 191 "Got an Alert msg",
ashleymills 0:714293de3836 192 "Another msg to Process",
ashleymills 0:714293de3836 193 "Removing Session From Table",
ashleymills 0:714293de3836 194
ashleymills 0:714293de3836 195 /* 46 */
ashleymills 0:714293de3836 196 "Bad Key File",
ashleymills 0:714293de3836 197 "Wrong IP Version",
ashleymills 0:714293de3836 198 "Wrong Protocol type",
ashleymills 0:714293de3836 199 "Packet Short for header processing",
ashleymills 0:714293de3836 200 "Got Unknown Record Type",
ashleymills 0:714293de3836 201
ashleymills 0:714293de3836 202 /* 51 */
ashleymills 0:714293de3836 203 "Can't Open Trace File",
ashleymills 0:714293de3836 204 "Session in Fatal Error State",
ashleymills 0:714293de3836 205 "Partial SSL record received",
ashleymills 0:714293de3836 206 "Buffer Error, malformed input",
ashleymills 0:714293de3836 207 "Added to Partial Input",
ashleymills 0:714293de3836 208
ashleymills 0:714293de3836 209 /* 56 */
ashleymills 0:714293de3836 210 "Received a Duplicate Packet",
ashleymills 0:714293de3836 211 "Received an Out of Order Packet",
ashleymills 0:714293de3836 212 "Received an Overlap Duplicate Packet",
ashleymills 0:714293de3836 213 "Received an Overlap Reassembly Begin Duplicate Packet",
ashleymills 0:714293de3836 214 "Received an Overlap Reassembly End Duplicate Packet",
ashleymills 0:714293de3836 215
ashleymills 0:714293de3836 216 /* 61 */
ashleymills 0:714293de3836 217 "Missed the Client Hello Entirely",
ashleymills 0:714293de3836 218 "Got Hello Request msg",
ashleymills 0:714293de3836 219 "Got Session Ticket msg",
ashleymills 0:714293de3836 220 "Bad Input",
ashleymills 0:714293de3836 221 "Bad Decrypt Type",
ashleymills 0:714293de3836 222
ashleymills 0:714293de3836 223 /* 66 */
ashleymills 0:714293de3836 224 "Bad Finished Message Processing",
ashleymills 0:714293de3836 225 "Bad Compression Type",
ashleymills 0:714293de3836 226 "Bad DeriveKeys Error",
ashleymills 0:714293de3836 227 "Saw ACK for Missing Packet Error"
ashleymills 0:714293de3836 228 };
ashleymills 0:714293de3836 229
ashleymills 0:714293de3836 230
ashleymills 0:714293de3836 231 /* *nix version uses table above */
ashleymills 0:714293de3836 232 static void GetError(int idx, char* str)
ashleymills 0:714293de3836 233 {
ashleymills 0:714293de3836 234 XSTRNCPY(str, msgTable[idx - 1], MAX_ERROR_LEN);
ashleymills 0:714293de3836 235 }
ashleymills 0:714293de3836 236
ashleymills 0:714293de3836 237
ashleymills 0:714293de3836 238 #else /* _WIN32 */
ashleymills 0:714293de3836 239
ashleymills 0:714293de3836 240
ashleymills 0:714293de3836 241 /* Windows version uses .rc table */
ashleymills 0:714293de3836 242 static void GetError(int idx, char* buffer)
ashleymills 0:714293de3836 243 {
ashleymills 0:714293de3836 244 if (!LoadStringA(dllModule, idx, buffer, MAX_ERROR_LEN))
ashleymills 0:714293de3836 245 buffer[0] = 0;
ashleymills 0:714293de3836 246 }
ashleymills 0:714293de3836 247
ashleymills 0:714293de3836 248
ashleymills 0:714293de3836 249 #endif /* _WIN32 */
ashleymills 0:714293de3836 250
ashleymills 0:714293de3836 251
ashleymills 0:714293de3836 252 /* Packet Buffer for reassembly list and ready list */
ashleymills 0:714293de3836 253 typedef struct PacketBuffer {
ashleymills 0:714293de3836 254 word32 begin; /* relative sequence begin */
ashleymills 0:714293de3836 255 word32 end; /* relative sequence end */
ashleymills 0:714293de3836 256 byte* data; /* actual data */
ashleymills 0:714293de3836 257 struct PacketBuffer* next; /* next on reassembly list or ready list */
ashleymills 0:714293de3836 258 } PacketBuffer;
ashleymills 0:714293de3836 259
ashleymills 0:714293de3836 260
ashleymills 0:714293de3836 261 /* Sniffer Server holds info for each server/port monitored */
ashleymills 0:714293de3836 262 typedef struct SnifferServer {
ashleymills 0:714293de3836 263 SSL_CTX* ctx; /* SSL context */
ashleymills 0:714293de3836 264 char address[MAX_SERVER_ADDRESS]; /* passed in server address */
ashleymills 0:714293de3836 265 word32 server; /* netowrk order address */
ashleymills 0:714293de3836 266 int port; /* server port */
ashleymills 0:714293de3836 267 struct SnifferServer* next; /* for list */
ashleymills 0:714293de3836 268 } SnifferServer;
ashleymills 0:714293de3836 269
ashleymills 0:714293de3836 270
ashleymills 0:714293de3836 271 /* Session Flags */
ashleymills 0:714293de3836 272 typedef struct Flags {
ashleymills 0:714293de3836 273 byte side; /* which end is current packet headed */
ashleymills 0:714293de3836 274 byte serverCipherOn; /* indicates whether cipher is active */
ashleymills 0:714293de3836 275 byte clientCipherOn; /* indicates whether cipher is active */
ashleymills 0:714293de3836 276 byte resuming; /* did this session come from resumption */
ashleymills 0:714293de3836 277 byte cached; /* have we cached this session yet */
ashleymills 0:714293de3836 278 byte clientHello; /* processed client hello yet, for SSLv2 */
ashleymills 0:714293de3836 279 byte finCount; /* get both FINs before removing */
ashleymills 0:714293de3836 280 byte fatalError; /* fatal error state */
ashleymills 0:714293de3836 281 } Flags;
ashleymills 0:714293de3836 282
ashleymills 0:714293de3836 283
ashleymills 0:714293de3836 284 /* Out of Order FIN caputre */
ashleymills 0:714293de3836 285 typedef struct FinCaputre {
ashleymills 0:714293de3836 286 word32 cliFinSeq; /* client relative sequence FIN 0 is no */
ashleymills 0:714293de3836 287 word32 srvFinSeq; /* server relative sequence FIN, 0 is no */
ashleymills 0:714293de3836 288 byte cliCounted; /* did we count yet, detects duplicates */
ashleymills 0:714293de3836 289 byte srvCounted; /* did we count yet, detects duplicates */
ashleymills 0:714293de3836 290 } FinCaputre;
ashleymills 0:714293de3836 291
ashleymills 0:714293de3836 292
ashleymills 0:714293de3836 293 /* Sniffer Session holds info for each client/server SSL/TLS session */
ashleymills 0:714293de3836 294 typedef struct SnifferSession {
ashleymills 0:714293de3836 295 SnifferServer* context; /* server context */
ashleymills 0:714293de3836 296 SSL* sslServer; /* SSL server side decode */
ashleymills 0:714293de3836 297 SSL* sslClient; /* SSL client side decode */
ashleymills 0:714293de3836 298 word32 server; /* server address in network byte order */
ashleymills 0:714293de3836 299 word32 client; /* client address in network byte order */
ashleymills 0:714293de3836 300 word16 srvPort; /* server port */
ashleymills 0:714293de3836 301 word16 cliPort; /* client port */
ashleymills 0:714293de3836 302 word32 cliSeqStart; /* client start sequence */
ashleymills 0:714293de3836 303 word32 srvSeqStart; /* server start sequence */
ashleymills 0:714293de3836 304 word32 cliExpected; /* client expected sequence (relative) */
ashleymills 0:714293de3836 305 word32 srvExpected; /* server expected sequence (relative) */
ashleymills 0:714293de3836 306 FinCaputre finCaputre; /* retain out of order FIN s */
ashleymills 0:714293de3836 307 Flags flags; /* session flags */
ashleymills 0:714293de3836 308 time_t lastUsed; /* last used ticks */
ashleymills 0:714293de3836 309 PacketBuffer* cliReassemblyList; /* client out of order packets */
ashleymills 0:714293de3836 310 PacketBuffer* srvReassemblyList; /* server out of order packets */
ashleymills 0:714293de3836 311 struct SnifferSession* next; /* for hash table list */
ashleymills 0:714293de3836 312 byte* ticketID; /* mac ID of session ticket */
ashleymills 0:714293de3836 313 } SnifferSession;
ashleymills 0:714293de3836 314
ashleymills 0:714293de3836 315
ashleymills 0:714293de3836 316 /* Sniffer Server List and mutex */
ashleymills 0:714293de3836 317 static SnifferServer* ServerList = 0;
ashleymills 0:714293de3836 318 static CyaSSL_Mutex ServerListMutex;
ashleymills 0:714293de3836 319
ashleymills 0:714293de3836 320
ashleymills 0:714293de3836 321 /* Session Hash Table, mutex, and count */
ashleymills 0:714293de3836 322 static SnifferSession* SessionTable[HASH_SIZE];
ashleymills 0:714293de3836 323 static CyaSSL_Mutex SessionMutex;
ashleymills 0:714293de3836 324 static int SessionCount = 0;
ashleymills 0:714293de3836 325
ashleymills 0:714293de3836 326
ashleymills 0:714293de3836 327 /* Initialize overall Sniffer */
ashleymills 0:714293de3836 328 void ssl_InitSniffer(void)
ashleymills 0:714293de3836 329 {
ashleymills 0:714293de3836 330 CyaSSL_Init();
ashleymills 0:714293de3836 331 InitMutex(&ServerListMutex);
ashleymills 0:714293de3836 332 InitMutex(&SessionMutex);
ashleymills 0:714293de3836 333 }
ashleymills 0:714293de3836 334
ashleymills 0:714293de3836 335
ashleymills 0:714293de3836 336 /* Free Sniffer Server's resources/self */
ashleymills 0:714293de3836 337 static void FreeSnifferServer(SnifferServer* srv)
ashleymills 0:714293de3836 338 {
ashleymills 0:714293de3836 339 if (srv)
ashleymills 0:714293de3836 340 SSL_CTX_free(srv->ctx);
ashleymills 0:714293de3836 341 free(srv);
ashleymills 0:714293de3836 342 }
ashleymills 0:714293de3836 343
ashleymills 0:714293de3836 344
ashleymills 0:714293de3836 345 /* free PacketBuffer's resources/self */
ashleymills 0:714293de3836 346 static void FreePacketBuffer(PacketBuffer* del)
ashleymills 0:714293de3836 347 {
ashleymills 0:714293de3836 348 if (del) {
ashleymills 0:714293de3836 349 free(del->data);
ashleymills 0:714293de3836 350 free(del);
ashleymills 0:714293de3836 351 }
ashleymills 0:714293de3836 352 }
ashleymills 0:714293de3836 353
ashleymills 0:714293de3836 354
ashleymills 0:714293de3836 355 /* remove PacketBuffer List */
ashleymills 0:714293de3836 356 static void FreePacketList(PacketBuffer* in)
ashleymills 0:714293de3836 357 {
ashleymills 0:714293de3836 358 if (in) {
ashleymills 0:714293de3836 359 PacketBuffer* del;
ashleymills 0:714293de3836 360 PacketBuffer* packet = in;
ashleymills 0:714293de3836 361
ashleymills 0:714293de3836 362 while (packet) {
ashleymills 0:714293de3836 363 del = packet;
ashleymills 0:714293de3836 364 packet = packet->next;
ashleymills 0:714293de3836 365 FreePacketBuffer(del);
ashleymills 0:714293de3836 366 }
ashleymills 0:714293de3836 367 }
ashleymills 0:714293de3836 368 }
ashleymills 0:714293de3836 369
ashleymills 0:714293de3836 370
ashleymills 0:714293de3836 371 /* Free Sniffer Session's resources/self */
ashleymills 0:714293de3836 372 static void FreeSnifferSession(SnifferSession* session)
ashleymills 0:714293de3836 373 {
ashleymills 0:714293de3836 374 if (session) {
ashleymills 0:714293de3836 375 SSL_free(session->sslClient);
ashleymills 0:714293de3836 376 SSL_free(session->sslServer);
ashleymills 0:714293de3836 377
ashleymills 0:714293de3836 378 FreePacketList(session->cliReassemblyList);
ashleymills 0:714293de3836 379 FreePacketList(session->srvReassemblyList);
ashleymills 0:714293de3836 380
ashleymills 0:714293de3836 381 free(session->ticketID);
ashleymills 0:714293de3836 382 }
ashleymills 0:714293de3836 383 free(session);
ashleymills 0:714293de3836 384 }
ashleymills 0:714293de3836 385
ashleymills 0:714293de3836 386
ashleymills 0:714293de3836 387 /* Free overall Sniffer */
ashleymills 0:714293de3836 388 void ssl_FreeSniffer(void)
ashleymills 0:714293de3836 389 {
ashleymills 0:714293de3836 390 SnifferServer* srv;
ashleymills 0:714293de3836 391 SnifferServer* removeServer;
ashleymills 0:714293de3836 392 SnifferSession* session;
ashleymills 0:714293de3836 393 SnifferSession* removeSession;
ashleymills 0:714293de3836 394 int i;
ashleymills 0:714293de3836 395
ashleymills 0:714293de3836 396 LockMutex(&ServerListMutex);
ashleymills 0:714293de3836 397 LockMutex(&SessionMutex);
ashleymills 0:714293de3836 398
ashleymills 0:714293de3836 399 srv = ServerList;
ashleymills 0:714293de3836 400 while (srv) {
ashleymills 0:714293de3836 401 removeServer = srv;
ashleymills 0:714293de3836 402 srv = srv->next;
ashleymills 0:714293de3836 403 FreeSnifferServer(removeServer);
ashleymills 0:714293de3836 404 }
ashleymills 0:714293de3836 405
ashleymills 0:714293de3836 406 for (i = 0; i < HASH_SIZE; i++) {
ashleymills 0:714293de3836 407 session = SessionTable[i];
ashleymills 0:714293de3836 408 while (session) {
ashleymills 0:714293de3836 409 removeSession = session;
ashleymills 0:714293de3836 410 session = session->next;
ashleymills 0:714293de3836 411 FreeSnifferSession(removeSession);
ashleymills 0:714293de3836 412 }
ashleymills 0:714293de3836 413 }
ashleymills 0:714293de3836 414
ashleymills 0:714293de3836 415 UnLockMutex(&SessionMutex);
ashleymills 0:714293de3836 416 UnLockMutex(&ServerListMutex);
ashleymills 0:714293de3836 417
ashleymills 0:714293de3836 418 FreeMutex(&SessionMutex);
ashleymills 0:714293de3836 419 FreeMutex(&ServerListMutex);
ashleymills 0:714293de3836 420 CyaSSL_Cleanup();
ashleymills 0:714293de3836 421 }
ashleymills 0:714293de3836 422
ashleymills 0:714293de3836 423
ashleymills 0:714293de3836 424 /* Initialize a SnifferServer */
ashleymills 0:714293de3836 425 static void InitSnifferServer(SnifferServer* sniffer)
ashleymills 0:714293de3836 426 {
ashleymills 0:714293de3836 427 sniffer->ctx = 0;
ashleymills 0:714293de3836 428 XMEMSET(sniffer->address, 0, MAX_SERVER_ADDRESS);
ashleymills 0:714293de3836 429 sniffer->server = 0;
ashleymills 0:714293de3836 430 sniffer->port = 0;
ashleymills 0:714293de3836 431 sniffer->next = 0;
ashleymills 0:714293de3836 432 }
ashleymills 0:714293de3836 433
ashleymills 0:714293de3836 434
ashleymills 0:714293de3836 435 /* Initialize session flags */
ashleymills 0:714293de3836 436 static void InitFlags(Flags* flags)
ashleymills 0:714293de3836 437 {
ashleymills 0:714293de3836 438 flags->side = 0;
ashleymills 0:714293de3836 439 flags->serverCipherOn = 0;
ashleymills 0:714293de3836 440 flags->clientCipherOn = 0;
ashleymills 0:714293de3836 441 flags->resuming = 0;
ashleymills 0:714293de3836 442 flags->cached = 0;
ashleymills 0:714293de3836 443 flags->clientHello = 0;
ashleymills 0:714293de3836 444 flags->finCount = 0;
ashleymills 0:714293de3836 445 flags->fatalError = 0;
ashleymills 0:714293de3836 446 }
ashleymills 0:714293de3836 447
ashleymills 0:714293de3836 448
ashleymills 0:714293de3836 449 /* Initialize FIN Capture */
ashleymills 0:714293de3836 450 static void InitFinCapture(FinCaputre* cap)
ashleymills 0:714293de3836 451 {
ashleymills 0:714293de3836 452 cap->cliFinSeq = 0;
ashleymills 0:714293de3836 453 cap->srvFinSeq = 0;
ashleymills 0:714293de3836 454 cap->cliCounted = 0;
ashleymills 0:714293de3836 455 cap->srvCounted = 0;
ashleymills 0:714293de3836 456 }
ashleymills 0:714293de3836 457
ashleymills 0:714293de3836 458
ashleymills 0:714293de3836 459 /* Initialize a Sniffer Session */
ashleymills 0:714293de3836 460 static void InitSession(SnifferSession* session)
ashleymills 0:714293de3836 461 {
ashleymills 0:714293de3836 462 session->context = 0;
ashleymills 0:714293de3836 463 session->sslServer = 0;
ashleymills 0:714293de3836 464 session->sslClient = 0;
ashleymills 0:714293de3836 465 session->server = 0;
ashleymills 0:714293de3836 466 session->client = 0;
ashleymills 0:714293de3836 467 session->srvPort = 0;
ashleymills 0:714293de3836 468 session->cliPort = 0;
ashleymills 0:714293de3836 469 session->cliSeqStart = 0;
ashleymills 0:714293de3836 470 session->srvSeqStart = 0;
ashleymills 0:714293de3836 471 session->cliExpected = 0;
ashleymills 0:714293de3836 472 session->srvExpected = 0;
ashleymills 0:714293de3836 473 session->lastUsed = 0;
ashleymills 0:714293de3836 474 session->cliReassemblyList = 0;
ashleymills 0:714293de3836 475 session->srvReassemblyList = 0;
ashleymills 0:714293de3836 476 session->next = 0;
ashleymills 0:714293de3836 477 session->ticketID = 0;
ashleymills 0:714293de3836 478
ashleymills 0:714293de3836 479 InitFlags(&session->flags);
ashleymills 0:714293de3836 480 InitFinCapture(&session->finCaputre);
ashleymills 0:714293de3836 481 }
ashleymills 0:714293de3836 482
ashleymills 0:714293de3836 483
ashleymills 0:714293de3836 484 /* IP Info from IP Header */
ashleymills 0:714293de3836 485 typedef struct IpInfo {
ashleymills 0:714293de3836 486 int length; /* length of this header */
ashleymills 0:714293de3836 487 int total; /* total length of fragment */
ashleymills 0:714293de3836 488 word32 src; /* network order source address */
ashleymills 0:714293de3836 489 word32 dst; /* network order destination address */
ashleymills 0:714293de3836 490 } IpInfo;
ashleymills 0:714293de3836 491
ashleymills 0:714293de3836 492
ashleymills 0:714293de3836 493 /* TCP Info from TCP Header */
ashleymills 0:714293de3836 494 typedef struct TcpInfo {
ashleymills 0:714293de3836 495 int srcPort; /* source port */
ashleymills 0:714293de3836 496 int dstPort; /* source port */
ashleymills 0:714293de3836 497 int length; /* length of this header */
ashleymills 0:714293de3836 498 word32 sequence; /* sequence number */
ashleymills 0:714293de3836 499 word32 ackNumber; /* ack number */
ashleymills 0:714293de3836 500 byte fin; /* FIN set */
ashleymills 0:714293de3836 501 byte rst; /* RST set */
ashleymills 0:714293de3836 502 byte syn; /* SYN set */
ashleymills 0:714293de3836 503 byte ack; /* ACK set */
ashleymills 0:714293de3836 504 } TcpInfo;
ashleymills 0:714293de3836 505
ashleymills 0:714293de3836 506
ashleymills 0:714293de3836 507 /* Tcp Pseudo Header for Checksum calculation */
ashleymills 0:714293de3836 508 typedef struct TcpPseudoHdr {
ashleymills 0:714293de3836 509 word32 src; /* source address */
ashleymills 0:714293de3836 510 word32 dst; /* destination address */
ashleymills 0:714293de3836 511 byte rsv; /* reserved, always 0 */
ashleymills 0:714293de3836 512 byte protocol; /* IP protocol */
ashleymills 0:714293de3836 513 word16 legnth; /* tcp header length + data length (doesn't include */
ashleymills 0:714293de3836 514 /* pseudo header length) network order */
ashleymills 0:714293de3836 515 } TcpPseudoHdr;
ashleymills 0:714293de3836 516
ashleymills 0:714293de3836 517
ashleymills 0:714293de3836 518 /* Password Setting Callback */
ashleymills 0:714293de3836 519 static int SetPassword(char* passwd, int sz, int rw, void* userdata)
ashleymills 0:714293de3836 520 {
ashleymills 0:714293de3836 521 (void)rw;
ashleymills 0:714293de3836 522 XSTRNCPY(passwd, userdata, sz);
ashleymills 0:714293de3836 523 return (int)XSTRLEN(userdata);
ashleymills 0:714293de3836 524 }
ashleymills 0:714293de3836 525
ashleymills 0:714293de3836 526
ashleymills 0:714293de3836 527 /* Ethernet Header */
ashleymills 0:714293de3836 528 typedef struct EthernetHdr {
ashleymills 0:714293de3836 529 byte dst[ETHER_IF_ADDR_LEN]; /* destination host address */
ashleymills 0:714293de3836 530 byte src[ETHER_IF_ADDR_LEN]; /* source host address */
ashleymills 0:714293de3836 531 word16 type; /* IP, ARP, etc */
ashleymills 0:714293de3836 532 } EthernetHdr;
ashleymills 0:714293de3836 533
ashleymills 0:714293de3836 534
ashleymills 0:714293de3836 535 /* IP Header */
ashleymills 0:714293de3836 536 typedef struct IpHdr {
ashleymills 0:714293de3836 537 byte ver_hl; /* version/header length */
ashleymills 0:714293de3836 538 byte tos; /* type of service */
ashleymills 0:714293de3836 539 word16 length; /* total length */
ashleymills 0:714293de3836 540 word16 id; /* identification */
ashleymills 0:714293de3836 541 word16 offset; /* fragment offset field */
ashleymills 0:714293de3836 542 byte ttl; /* time to live */
ashleymills 0:714293de3836 543 byte protocol; /* protocol */
ashleymills 0:714293de3836 544 word16 sum; /* checksum */
ashleymills 0:714293de3836 545 word32 src; /* source address */
ashleymills 0:714293de3836 546 word32 dst; /* destination address */
ashleymills 0:714293de3836 547 } IpHdr;
ashleymills 0:714293de3836 548
ashleymills 0:714293de3836 549
ashleymills 0:714293de3836 550 #define IP_HL(ip) ( (((ip)->ver_hl) & 0x0f) * 4)
ashleymills 0:714293de3836 551 #define IP_V(ip) ( ((ip)->ver_hl) >> 4)
ashleymills 0:714293de3836 552
ashleymills 0:714293de3836 553 /* TCP Header */
ashleymills 0:714293de3836 554 typedef struct TcpHdr {
ashleymills 0:714293de3836 555 word16 srcPort; /* source port */
ashleymills 0:714293de3836 556 word16 dstPort; /* destination port */
ashleymills 0:714293de3836 557 word32 sequence; /* sequence number */
ashleymills 0:714293de3836 558 word32 ack; /* acknoledgment number */
ashleymills 0:714293de3836 559 byte offset; /* data offset, reserved */
ashleymills 0:714293de3836 560 byte flags; /* option flags */
ashleymills 0:714293de3836 561 word16 window; /* window */
ashleymills 0:714293de3836 562 word16 sum; /* checksum */
ashleymills 0:714293de3836 563 word16 urgent; /* urgent pointer */
ashleymills 0:714293de3836 564 } TcpHdr;
ashleymills 0:714293de3836 565
ashleymills 0:714293de3836 566 #define TCP_LEN(tcp) ( (((tcp)->offset & 0xf0) >> 4) * 4)
ashleymills 0:714293de3836 567 #define TCP_FIN 0x01
ashleymills 0:714293de3836 568 #define TCP_SYN 0x02
ashleymills 0:714293de3836 569 #define TCP_RST 0x04
ashleymills 0:714293de3836 570 #define TCP_ACK 0x10
ashleymills 0:714293de3836 571
ashleymills 0:714293de3836 572
ashleymills 0:714293de3836 573
ashleymills 0:714293de3836 574
ashleymills 0:714293de3836 575
ashleymills 0:714293de3836 576 /* Use platform specific GetError to write to tracfile if tracing */
ashleymills 0:714293de3836 577 static void Trace(int idx)
ashleymills 0:714293de3836 578 {
ashleymills 0:714293de3836 579 if (TraceOn) {
ashleymills 0:714293de3836 580 char myBuffer[MAX_ERROR_LEN];
ashleymills 0:714293de3836 581 GetError(idx, myBuffer);
ashleymills 0:714293de3836 582 fprintf(TraceFile, "\t%s\n", myBuffer);
ashleymills 0:714293de3836 583 #ifdef DEBUG_SNIFFER
ashleymills 0:714293de3836 584 fprintf(stderr, "\t%s\n", myBuffer);
ashleymills 0:714293de3836 585 #endif
ashleymills 0:714293de3836 586 }
ashleymills 0:714293de3836 587 }
ashleymills 0:714293de3836 588
ashleymills 0:714293de3836 589
ashleymills 0:714293de3836 590 /* Show TimeStamp for beginning of packet Trace */
ashleymills 0:714293de3836 591 static void TraceHeader(void)
ashleymills 0:714293de3836 592 {
ashleymills 0:714293de3836 593 if (TraceOn) {
ashleymills 0:714293de3836 594 time_t ticks = time(NULL);
ashleymills 0:714293de3836 595 fprintf(TraceFile, "\n%s", ctime(&ticks));
ashleymills 0:714293de3836 596 }
ashleymills 0:714293de3836 597 }
ashleymills 0:714293de3836 598
ashleymills 0:714293de3836 599
ashleymills 0:714293de3836 600 /* Show Set Server info for Trace */
ashleymills 0:714293de3836 601 static void TraceSetServer(const char* srv, int port, const char* keyFile)
ashleymills 0:714293de3836 602 {
ashleymills 0:714293de3836 603 if (TraceOn) {
ashleymills 0:714293de3836 604 fprintf(TraceFile, "\tTrying to install a new Sniffer Server with\n");
ashleymills 0:714293de3836 605 fprintf(TraceFile, "\tserver: %s, port: %d, keyFile: %s\n", srv, port,
ashleymills 0:714293de3836 606 keyFile);
ashleymills 0:714293de3836 607 }
ashleymills 0:714293de3836 608 }
ashleymills 0:714293de3836 609
ashleymills 0:714293de3836 610
ashleymills 0:714293de3836 611 /* Trace got packet number */
ashleymills 0:714293de3836 612 static void TracePacket(void)
ashleymills 0:714293de3836 613 {
ashleymills 0:714293de3836 614 if (TraceOn) {
ashleymills 0:714293de3836 615 static word32 packetNumber = 0;
ashleymills 0:714293de3836 616 fprintf(TraceFile, "\tGot a Packet to decode, packet %u\n",
ashleymills 0:714293de3836 617 ++packetNumber);
ashleymills 0:714293de3836 618 }
ashleymills 0:714293de3836 619 }
ashleymills 0:714293de3836 620
ashleymills 0:714293de3836 621
ashleymills 0:714293de3836 622 /* Convert network byte order address into human readable */
ashleymills 0:714293de3836 623 static char* IpToS(word32 addr, char* str)
ashleymills 0:714293de3836 624 {
ashleymills 0:714293de3836 625 byte* p = (byte*)&addr;
ashleymills 0:714293de3836 626
ashleymills 0:714293de3836 627 SNPRINTF(str, TRACE_MSG_SZ, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
ashleymills 0:714293de3836 628
ashleymills 0:714293de3836 629 return str;
ashleymills 0:714293de3836 630 }
ashleymills 0:714293de3836 631
ashleymills 0:714293de3836 632
ashleymills 0:714293de3836 633 /* Show destination and source address from Ip Hdr for packet Trace */
ashleymills 0:714293de3836 634 static void TraceIP(IpHdr* iphdr)
ashleymills 0:714293de3836 635 {
ashleymills 0:714293de3836 636 if (TraceOn) {
ashleymills 0:714293de3836 637 char src[TRACE_MSG_SZ];
ashleymills 0:714293de3836 638 char dst[TRACE_MSG_SZ];
ashleymills 0:714293de3836 639 fprintf(TraceFile, "\tdst:%s src:%s\n", IpToS(iphdr->dst, dst),
ashleymills 0:714293de3836 640 IpToS(iphdr->src, src));
ashleymills 0:714293de3836 641 }
ashleymills 0:714293de3836 642 }
ashleymills 0:714293de3836 643
ashleymills 0:714293de3836 644
ashleymills 0:714293de3836 645 /* Show destination and source port from Tcp Hdr for packet Trace */
ashleymills 0:714293de3836 646 static void TraceTcp(TcpHdr* tcphdr)
ashleymills 0:714293de3836 647 {
ashleymills 0:714293de3836 648 if (TraceOn) {
ashleymills 0:714293de3836 649 fprintf(TraceFile, "\tdstPort:%u srcPort:%u\n", ntohs(tcphdr->dstPort),
ashleymills 0:714293de3836 650 ntohs(tcphdr->srcPort));
ashleymills 0:714293de3836 651 }
ashleymills 0:714293de3836 652 }
ashleymills 0:714293de3836 653
ashleymills 0:714293de3836 654
ashleymills 0:714293de3836 655 /* Show sequence and payload length for Trace */
ashleymills 0:714293de3836 656 static void TraceSequence(word32 seq, int len)
ashleymills 0:714293de3836 657 {
ashleymills 0:714293de3836 658 if (TraceOn) {
ashleymills 0:714293de3836 659 fprintf(TraceFile, "\tSequence:%u, payload length:%d\n", seq, len);
ashleymills 0:714293de3836 660 }
ashleymills 0:714293de3836 661 }
ashleymills 0:714293de3836 662
ashleymills 0:714293de3836 663
ashleymills 0:714293de3836 664 /* Show sequence and payload length for Trace */
ashleymills 0:714293de3836 665 static void TraceAck(word32 ack, word32 expected)
ashleymills 0:714293de3836 666 {
ashleymills 0:714293de3836 667 if (TraceOn) {
ashleymills 0:714293de3836 668 fprintf(TraceFile, "\tAck:%u Expected:%u\n", ack, expected);
ashleymills 0:714293de3836 669 }
ashleymills 0:714293de3836 670 }
ashleymills 0:714293de3836 671
ashleymills 0:714293de3836 672
ashleymills 0:714293de3836 673 /* Show relative expected and relative received sequences */
ashleymills 0:714293de3836 674 static void TraceRelativeSequence(word32 expected, word32 got)
ashleymills 0:714293de3836 675 {
ashleymills 0:714293de3836 676 if (TraceOn) {
ashleymills 0:714293de3836 677 fprintf(TraceFile, "\tExpected sequence:%u, received sequence:%u\n",
ashleymills 0:714293de3836 678 expected, got);
ashleymills 0:714293de3836 679 }
ashleymills 0:714293de3836 680 }
ashleymills 0:714293de3836 681
ashleymills 0:714293de3836 682
ashleymills 0:714293de3836 683 /* Show server sequence startup from SYN */
ashleymills 0:714293de3836 684 static void TraceServerSyn(word32 seq)
ashleymills 0:714293de3836 685 {
ashleymills 0:714293de3836 686 if (TraceOn) {
ashleymills 0:714293de3836 687 fprintf(TraceFile, "\tServer SYN, Sequence Start:%u\n", seq);
ashleymills 0:714293de3836 688 }
ashleymills 0:714293de3836 689 }
ashleymills 0:714293de3836 690
ashleymills 0:714293de3836 691
ashleymills 0:714293de3836 692 /* Show client sequence startup from SYN */
ashleymills 0:714293de3836 693 static void TraceClientSyn(word32 seq)
ashleymills 0:714293de3836 694 {
ashleymills 0:714293de3836 695 if (TraceOn) {
ashleymills 0:714293de3836 696 fprintf(TraceFile, "\tClient SYN, Sequence Start:%u\n", seq);
ashleymills 0:714293de3836 697 }
ashleymills 0:714293de3836 698 }
ashleymills 0:714293de3836 699
ashleymills 0:714293de3836 700
ashleymills 0:714293de3836 701 /* Show client FIN capture */
ashleymills 0:714293de3836 702 static void TraceClientFin(word32 finSeq, word32 relSeq)
ashleymills 0:714293de3836 703 {
ashleymills 0:714293de3836 704 if (TraceOn) {
ashleymills 0:714293de3836 705 fprintf(TraceFile, "\tClient FIN capture:%u, current SEQ:%u\n",
ashleymills 0:714293de3836 706 finSeq, relSeq);
ashleymills 0:714293de3836 707 }
ashleymills 0:714293de3836 708 }
ashleymills 0:714293de3836 709
ashleymills 0:714293de3836 710
ashleymills 0:714293de3836 711 /* Show server FIN capture */
ashleymills 0:714293de3836 712 static void TraceServerFin(word32 finSeq, word32 relSeq)
ashleymills 0:714293de3836 713 {
ashleymills 0:714293de3836 714 if (TraceOn) {
ashleymills 0:714293de3836 715 fprintf(TraceFile, "\tServer FIN capture:%u, current SEQ:%u\n",
ashleymills 0:714293de3836 716 finSeq, relSeq);
ashleymills 0:714293de3836 717 }
ashleymills 0:714293de3836 718 }
ashleymills 0:714293de3836 719
ashleymills 0:714293de3836 720
ashleymills 0:714293de3836 721 /* Show number of SSL data bytes decoded, could be 0 (ok) */
ashleymills 0:714293de3836 722 static void TraceGotData(int bytes)
ashleymills 0:714293de3836 723 {
ashleymills 0:714293de3836 724 if (TraceOn) {
ashleymills 0:714293de3836 725 fprintf(TraceFile, "\t%d bytes of SSL App data processed\n", bytes);
ashleymills 0:714293de3836 726 }
ashleymills 0:714293de3836 727 }
ashleymills 0:714293de3836 728
ashleymills 0:714293de3836 729
ashleymills 0:714293de3836 730 /* Show bytes added to old SSL App data */
ashleymills 0:714293de3836 731 static void TraceAddedData(int newBytes, int existingBytes)
ashleymills 0:714293de3836 732 {
ashleymills 0:714293de3836 733 if (TraceOn) {
ashleymills 0:714293de3836 734 fprintf(TraceFile,
ashleymills 0:714293de3836 735 "\t%d bytes added to %d exisiting bytes in User Buffer\n",
ashleymills 0:714293de3836 736 newBytes, existingBytes);
ashleymills 0:714293de3836 737 }
ashleymills 0:714293de3836 738 }
ashleymills 0:714293de3836 739
ashleymills 0:714293de3836 740
ashleymills 0:714293de3836 741 /* Show Stale Session */
ashleymills 0:714293de3836 742 static void TraceStaleSession(void)
ashleymills 0:714293de3836 743 {
ashleymills 0:714293de3836 744 if (TraceOn) {
ashleymills 0:714293de3836 745 fprintf(TraceFile, "\tFound a stale session\n");
ashleymills 0:714293de3836 746 }
ashleymills 0:714293de3836 747 }
ashleymills 0:714293de3836 748
ashleymills 0:714293de3836 749
ashleymills 0:714293de3836 750 /* Show Finding Stale Sessions */
ashleymills 0:714293de3836 751 static void TraceFindingStale(void)
ashleymills 0:714293de3836 752 {
ashleymills 0:714293de3836 753 if (TraceOn) {
ashleymills 0:714293de3836 754 fprintf(TraceFile, "\tTrying to find Stale Sessions\n");
ashleymills 0:714293de3836 755 }
ashleymills 0:714293de3836 756 }
ashleymills 0:714293de3836 757
ashleymills 0:714293de3836 758
ashleymills 0:714293de3836 759 /* Show Removed Session */
ashleymills 0:714293de3836 760 static void TraceRemovedSession(void)
ashleymills 0:714293de3836 761 {
ashleymills 0:714293de3836 762 if (TraceOn) {
ashleymills 0:714293de3836 763 fprintf(TraceFile, "\tRemoved it\n");
ashleymills 0:714293de3836 764 }
ashleymills 0:714293de3836 765 }
ashleymills 0:714293de3836 766
ashleymills 0:714293de3836 767
ashleymills 0:714293de3836 768 /* Set user error string */
ashleymills 0:714293de3836 769 static void SetError(int idx, char* error, SnifferSession* session, int fatal)
ashleymills 0:714293de3836 770 {
ashleymills 0:714293de3836 771 GetError(idx, error);
ashleymills 0:714293de3836 772 Trace(idx);
ashleymills 0:714293de3836 773 if (session && fatal == FATAL_ERROR_STATE)
ashleymills 0:714293de3836 774 session->flags.fatalError = 1;
ashleymills 0:714293de3836 775 }
ashleymills 0:714293de3836 776
ashleymills 0:714293de3836 777
ashleymills 0:714293de3836 778 /* See if this IPV4 network order address has been registered */
ashleymills 0:714293de3836 779 /* return 1 is true, 0 is false */
ashleymills 0:714293de3836 780 static int IsServerRegistered(word32 addr)
ashleymills 0:714293de3836 781 {
ashleymills 0:714293de3836 782 int ret = 0; /* false */
ashleymills 0:714293de3836 783 SnifferServer* sniffer;
ashleymills 0:714293de3836 784
ashleymills 0:714293de3836 785 LockMutex(&ServerListMutex);
ashleymills 0:714293de3836 786
ashleymills 0:714293de3836 787 sniffer = ServerList;
ashleymills 0:714293de3836 788 while (sniffer) {
ashleymills 0:714293de3836 789 if (sniffer->server == addr) {
ashleymills 0:714293de3836 790 ret = 1;
ashleymills 0:714293de3836 791 break;
ashleymills 0:714293de3836 792 }
ashleymills 0:714293de3836 793 sniffer = sniffer->next;
ashleymills 0:714293de3836 794 }
ashleymills 0:714293de3836 795
ashleymills 0:714293de3836 796 UnLockMutex(&ServerListMutex);
ashleymills 0:714293de3836 797
ashleymills 0:714293de3836 798 return ret;
ashleymills 0:714293de3836 799 }
ashleymills 0:714293de3836 800
ashleymills 0:714293de3836 801
ashleymills 0:714293de3836 802 /* See if this port has been registered to watch */
ashleymills 0:714293de3836 803 /* return 1 is true, 0 is false */
ashleymills 0:714293de3836 804 static int IsPortRegistered(word32 port)
ashleymills 0:714293de3836 805 {
ashleymills 0:714293de3836 806 int ret = 0; /* false */
ashleymills 0:714293de3836 807 SnifferServer* sniffer;
ashleymills 0:714293de3836 808
ashleymills 0:714293de3836 809 LockMutex(&ServerListMutex);
ashleymills 0:714293de3836 810
ashleymills 0:714293de3836 811 sniffer = ServerList;
ashleymills 0:714293de3836 812 while (sniffer) {
ashleymills 0:714293de3836 813 if (sniffer->port == (int)port) {
ashleymills 0:714293de3836 814 ret = 1;
ashleymills 0:714293de3836 815 break;
ashleymills 0:714293de3836 816 }
ashleymills 0:714293de3836 817 sniffer = sniffer->next;
ashleymills 0:714293de3836 818 }
ashleymills 0:714293de3836 819
ashleymills 0:714293de3836 820 UnLockMutex(&ServerListMutex);
ashleymills 0:714293de3836 821
ashleymills 0:714293de3836 822 return ret;
ashleymills 0:714293de3836 823 }
ashleymills 0:714293de3836 824
ashleymills 0:714293de3836 825
ashleymills 0:714293de3836 826 /* Get SnifferServer from IP and Port */
ashleymills 0:714293de3836 827 static SnifferServer* GetSnifferServer(IpInfo* ipInfo, TcpInfo* tcpInfo)
ashleymills 0:714293de3836 828 {
ashleymills 0:714293de3836 829 SnifferServer* sniffer;
ashleymills 0:714293de3836 830
ashleymills 0:714293de3836 831 LockMutex(&ServerListMutex);
ashleymills 0:714293de3836 832
ashleymills 0:714293de3836 833 sniffer = ServerList;
ashleymills 0:714293de3836 834 while (sniffer) {
ashleymills 0:714293de3836 835 if (sniffer->port == tcpInfo->srcPort && sniffer->server == ipInfo->src)
ashleymills 0:714293de3836 836 break;
ashleymills 0:714293de3836 837 if (sniffer->port == tcpInfo->dstPort && sniffer->server == ipInfo->dst)
ashleymills 0:714293de3836 838 break;
ashleymills 0:714293de3836 839 sniffer = sniffer->next;
ashleymills 0:714293de3836 840 }
ashleymills 0:714293de3836 841
ashleymills 0:714293de3836 842 UnLockMutex(&ServerListMutex);
ashleymills 0:714293de3836 843
ashleymills 0:714293de3836 844 return sniffer;
ashleymills 0:714293de3836 845 }
ashleymills 0:714293de3836 846
ashleymills 0:714293de3836 847
ashleymills 0:714293de3836 848 /* Hash the Session Info, return hash row */
ashleymills 0:714293de3836 849 static word32 SessionHash(IpInfo* ipInfo, TcpInfo* tcpInfo)
ashleymills 0:714293de3836 850 {
ashleymills 0:714293de3836 851 word32 hash = ipInfo->src * ipInfo->dst;
ashleymills 0:714293de3836 852 hash *= tcpInfo->srcPort * tcpInfo->dstPort;
ashleymills 0:714293de3836 853
ashleymills 0:714293de3836 854 return hash % HASH_SIZE;
ashleymills 0:714293de3836 855 }
ashleymills 0:714293de3836 856
ashleymills 0:714293de3836 857
ashleymills 0:714293de3836 858 /* Get Exisiting SnifferSession from IP and Port */
ashleymills 0:714293de3836 859 static SnifferSession* GetSnifferSession(IpInfo* ipInfo, TcpInfo* tcpInfo)
ashleymills 0:714293de3836 860 {
ashleymills 0:714293de3836 861 SnifferSession* session;
ashleymills 0:714293de3836 862 time_t currTime = time(NULL);
ashleymills 0:714293de3836 863 word32 row = SessionHash(ipInfo, tcpInfo);
ashleymills 0:714293de3836 864
ashleymills 0:714293de3836 865 assert(row <= HASH_SIZE);
ashleymills 0:714293de3836 866
ashleymills 0:714293de3836 867 LockMutex(&SessionMutex);
ashleymills 0:714293de3836 868
ashleymills 0:714293de3836 869 session = SessionTable[row];
ashleymills 0:714293de3836 870 while (session) {
ashleymills 0:714293de3836 871 if (session->server == ipInfo->src && session->client == ipInfo->dst &&
ashleymills 0:714293de3836 872 session->srvPort == tcpInfo->srcPort &&
ashleymills 0:714293de3836 873 session->cliPort == tcpInfo->dstPort)
ashleymills 0:714293de3836 874 break;
ashleymills 0:714293de3836 875 if (session->client == ipInfo->src && session->server == ipInfo->dst &&
ashleymills 0:714293de3836 876 session->cliPort == tcpInfo->srcPort &&
ashleymills 0:714293de3836 877 session->srvPort == tcpInfo->dstPort)
ashleymills 0:714293de3836 878 break;
ashleymills 0:714293de3836 879
ashleymills 0:714293de3836 880 session = session->next;
ashleymills 0:714293de3836 881 }
ashleymills 0:714293de3836 882
ashleymills 0:714293de3836 883 if (session)
ashleymills 0:714293de3836 884 session->lastUsed= currTime; /* keep session alive, remove stale will */
ashleymills 0:714293de3836 885 /* leave alone */
ashleymills 0:714293de3836 886 UnLockMutex(&SessionMutex);
ashleymills 0:714293de3836 887
ashleymills 0:714293de3836 888 /* determine side */
ashleymills 0:714293de3836 889 if (session) {
ashleymills 0:714293de3836 890 if (ipInfo->dst == session->context->server &&
ashleymills 0:714293de3836 891 tcpInfo->dstPort == session->context->port)
ashleymills 0:714293de3836 892 session->flags.side = SERVER_END;
ashleymills 0:714293de3836 893 else
ashleymills 0:714293de3836 894 session->flags.side = CLIENT_END;
ashleymills 0:714293de3836 895 }
ashleymills 0:714293de3836 896
ashleymills 0:714293de3836 897 return session;
ashleymills 0:714293de3836 898 }
ashleymills 0:714293de3836 899
ashleymills 0:714293de3836 900
ashleymills 0:714293de3836 901 /* Sets the private key for a specific server and port */
ashleymills 0:714293de3836 902 /* returns 0 on success, -1 on error */
ashleymills 0:714293de3836 903 int ssl_SetPrivateKey(const char* serverAddress, int port, const char* keyFile,
ashleymills 0:714293de3836 904 int typeKey, const char* password, char* error)
ashleymills 0:714293de3836 905 {
ashleymills 0:714293de3836 906 int ret;
ashleymills 0:714293de3836 907 int type = (typeKey == FILETYPE_PEM) ? SSL_FILETYPE_PEM :
ashleymills 0:714293de3836 908 SSL_FILETYPE_ASN1;
ashleymills 0:714293de3836 909 SnifferServer* sniffer;
ashleymills 0:714293de3836 910
ashleymills 0:714293de3836 911 TraceHeader();
ashleymills 0:714293de3836 912 TraceSetServer(serverAddress, port, keyFile);
ashleymills 0:714293de3836 913
ashleymills 0:714293de3836 914 sniffer = (SnifferServer*)malloc(sizeof(SnifferServer));
ashleymills 0:714293de3836 915 if (sniffer == NULL) {
ashleymills 0:714293de3836 916 SetError(MEMORY_STR, error, NULL, 0);
ashleymills 0:714293de3836 917 return -1;
ashleymills 0:714293de3836 918 }
ashleymills 0:714293de3836 919 InitSnifferServer(sniffer);
ashleymills 0:714293de3836 920
ashleymills 0:714293de3836 921 XSTRNCPY(sniffer->address, serverAddress, MAX_SERVER_ADDRESS);
ashleymills 0:714293de3836 922 sniffer->server = inet_addr(sniffer->address);
ashleymills 0:714293de3836 923 sniffer->port = port;
ashleymills 0:714293de3836 924
ashleymills 0:714293de3836 925 /* start in client mode since SSL_new needs a cert for server */
ashleymills 0:714293de3836 926 sniffer->ctx = SSL_CTX_new(SSLv3_client_method());
ashleymills 0:714293de3836 927 if (!sniffer->ctx) {
ashleymills 0:714293de3836 928 SetError(MEMORY_STR, error, NULL, 0);
ashleymills 0:714293de3836 929 FreeSnifferServer(sniffer);
ashleymills 0:714293de3836 930 return -1;
ashleymills 0:714293de3836 931 }
ashleymills 0:714293de3836 932
ashleymills 0:714293de3836 933 if (password){
ashleymills 0:714293de3836 934 SSL_CTX_set_default_passwd_cb(sniffer->ctx, SetPassword);
ashleymills 0:714293de3836 935 SSL_CTX_set_default_passwd_cb_userdata(sniffer->ctx, (void*)password);
ashleymills 0:714293de3836 936 }
ashleymills 0:714293de3836 937 ret = SSL_CTX_use_PrivateKey_file(sniffer->ctx, keyFile, type);
ashleymills 0:714293de3836 938 if (ret != SSL_SUCCESS) {
ashleymills 0:714293de3836 939 SetError(KEY_FILE_STR, error, NULL, 0);
ashleymills 0:714293de3836 940 FreeSnifferServer(sniffer);
ashleymills 0:714293de3836 941 return -1;
ashleymills 0:714293de3836 942 }
ashleymills 0:714293de3836 943 Trace(NEW_SERVER_STR);
ashleymills 0:714293de3836 944
ashleymills 0:714293de3836 945 LockMutex(&ServerListMutex);
ashleymills 0:714293de3836 946
ashleymills 0:714293de3836 947 sniffer->next = ServerList;
ashleymills 0:714293de3836 948 ServerList = sniffer;
ashleymills 0:714293de3836 949
ashleymills 0:714293de3836 950 UnLockMutex(&ServerListMutex);
ashleymills 0:714293de3836 951
ashleymills 0:714293de3836 952 return 0;
ashleymills 0:714293de3836 953 }
ashleymills 0:714293de3836 954
ashleymills 0:714293de3836 955
ashleymills 0:714293de3836 956 /* Check IP Header for IPV4, TCP, and a registered server address */
ashleymills 0:714293de3836 957 /* returns 0 on success, -1 on error */
ashleymills 0:714293de3836 958 static int CheckIpHdr(IpHdr* iphdr, IpInfo* info, char* error)
ashleymills 0:714293de3836 959 {
ashleymills 0:714293de3836 960 int version = IP_V(iphdr);
ashleymills 0:714293de3836 961
ashleymills 0:714293de3836 962 TraceIP(iphdr);
ashleymills 0:714293de3836 963 Trace(IP_CHECK_STR);
ashleymills 0:714293de3836 964 if (version != IPV4) {
ashleymills 0:714293de3836 965 SetError(BAD_IPVER_STR, error, NULL, 0);
ashleymills 0:714293de3836 966 return -1;
ashleymills 0:714293de3836 967 }
ashleymills 0:714293de3836 968
ashleymills 0:714293de3836 969 if (iphdr->protocol != TCP_PROTOCOL) {
ashleymills 0:714293de3836 970 SetError(BAD_PROTO_STR, error, NULL, 0);
ashleymills 0:714293de3836 971 return -1;
ashleymills 0:714293de3836 972 }
ashleymills 0:714293de3836 973
ashleymills 0:714293de3836 974 if (!IsServerRegistered(iphdr->src) && !IsServerRegistered(iphdr->dst)) {
ashleymills 0:714293de3836 975 SetError(SERVER_NOT_REG_STR, error, NULL, 0);
ashleymills 0:714293de3836 976 return -1;
ashleymills 0:714293de3836 977 }
ashleymills 0:714293de3836 978
ashleymills 0:714293de3836 979 info->length = IP_HL(iphdr);
ashleymills 0:714293de3836 980 info->total = ntohs(iphdr->length);
ashleymills 0:714293de3836 981 info->src = iphdr->src;
ashleymills 0:714293de3836 982 info->dst = iphdr->dst;
ashleymills 0:714293de3836 983
ashleymills 0:714293de3836 984 return 0;
ashleymills 0:714293de3836 985 }
ashleymills 0:714293de3836 986
ashleymills 0:714293de3836 987
ashleymills 0:714293de3836 988 /* Check TCP Header for a registered port */
ashleymills 0:714293de3836 989 /* returns 0 on success, -1 on error */
ashleymills 0:714293de3836 990 static int CheckTcpHdr(TcpHdr* tcphdr, TcpInfo* info, char* error)
ashleymills 0:714293de3836 991 {
ashleymills 0:714293de3836 992 TraceTcp(tcphdr);
ashleymills 0:714293de3836 993 Trace(TCP_CHECK_STR);
ashleymills 0:714293de3836 994 info->srcPort = ntohs(tcphdr->srcPort);
ashleymills 0:714293de3836 995 info->dstPort = ntohs(tcphdr->dstPort);
ashleymills 0:714293de3836 996 info->length = TCP_LEN(tcphdr);
ashleymills 0:714293de3836 997 info->sequence = ntohl(tcphdr->sequence);
ashleymills 0:714293de3836 998 info->fin = tcphdr->flags & TCP_FIN;
ashleymills 0:714293de3836 999 info->rst = tcphdr->flags & TCP_RST;
ashleymills 0:714293de3836 1000 info->syn = tcphdr->flags & TCP_SYN;
ashleymills 0:714293de3836 1001 info->ack = tcphdr->flags & TCP_ACK;
ashleymills 0:714293de3836 1002 if (info->ack)
ashleymills 0:714293de3836 1003 info->ackNumber = ntohl(tcphdr->ack);
ashleymills 0:714293de3836 1004
ashleymills 0:714293de3836 1005 if (!IsPortRegistered(info->srcPort) && !IsPortRegistered(info->dstPort)) {
ashleymills 0:714293de3836 1006 SetError(SERVER_PORT_NOT_REG_STR, error, NULL, 0);
ashleymills 0:714293de3836 1007 return -1;
ashleymills 0:714293de3836 1008 }
ashleymills 0:714293de3836 1009
ashleymills 0:714293de3836 1010 return 0;
ashleymills 0:714293de3836 1011 }
ashleymills 0:714293de3836 1012
ashleymills 0:714293de3836 1013
ashleymills 0:714293de3836 1014 /* Decode Record Layer Header */
ashleymills 0:714293de3836 1015 static int GetRecordHeader(const byte* input, RecordLayerHeader* rh, int* size)
ashleymills 0:714293de3836 1016 {
ashleymills 0:714293de3836 1017 XMEMCPY(rh, input, RECORD_HEADER_SZ);
ashleymills 0:714293de3836 1018 *size = (rh->length[0] << 8) | rh->length[1];
ashleymills 0:714293de3836 1019
ashleymills 0:714293de3836 1020 if (*size > (MAX_RECORD_SIZE + COMP_EXTRA + MAX_MSG_EXTRA))
ashleymills 0:714293de3836 1021 return LENGTH_ERROR;
ashleymills 0:714293de3836 1022
ashleymills 0:714293de3836 1023 return 0;
ashleymills 0:714293de3836 1024 }
ashleymills 0:714293de3836 1025
ashleymills 0:714293de3836 1026
ashleymills 0:714293de3836 1027 /* Process Client Key Exchange, RSA only */
ashleymills 0:714293de3836 1028 static int ProcessClientKeyExchange(const byte* input, int* sslBytes,
ashleymills 0:714293de3836 1029 SnifferSession* session, char* error)
ashleymills 0:714293de3836 1030 {
ashleymills 0:714293de3836 1031 word32 idx = 0;
ashleymills 0:714293de3836 1032 RsaKey key;
ashleymills 0:714293de3836 1033 int ret;
ashleymills 0:714293de3836 1034
ashleymills 0:714293de3836 1035 InitRsaKey(&key, 0);
ashleymills 0:714293de3836 1036
ashleymills 0:714293de3836 1037 ret = RsaPrivateKeyDecode(session->context->ctx->privateKey.buffer,
ashleymills 0:714293de3836 1038 &idx, &key, session->context->ctx->privateKey.length);
ashleymills 0:714293de3836 1039 if (ret == 0) {
ashleymills 0:714293de3836 1040 int length = RsaEncryptSize(&key);
ashleymills 0:714293de3836 1041
ashleymills 0:714293de3836 1042 if (IsTLS(session->sslServer))
ashleymills 0:714293de3836 1043 input += 2; /* tls pre length */
ashleymills 0:714293de3836 1044
ashleymills 0:714293de3836 1045 if (length > *sslBytes) {
ashleymills 0:714293de3836 1046 SetError(PARTIAL_INPUT_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1047 FreeRsaKey(&key);
ashleymills 0:714293de3836 1048 return -1;
ashleymills 0:714293de3836 1049 }
ashleymills 0:714293de3836 1050 ret = RsaPrivateDecrypt(input, length,
ashleymills 0:714293de3836 1051 session->sslServer->arrays->preMasterSecret,SECRET_LEN, &key);
ashleymills 0:714293de3836 1052
ashleymills 0:714293de3836 1053 if (ret != SECRET_LEN) {
ashleymills 0:714293de3836 1054 SetError(RSA_DECRYPT_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1055 FreeRsaKey(&key);
ashleymills 0:714293de3836 1056 return -1;
ashleymills 0:714293de3836 1057 }
ashleymills 0:714293de3836 1058 ret = 0; /* not in error state */
ashleymills 0:714293de3836 1059 session->sslServer->arrays->preMasterSz = SECRET_LEN;
ashleymills 0:714293de3836 1060
ashleymills 0:714293de3836 1061 /* store for client side as well */
ashleymills 0:714293de3836 1062 XMEMCPY(session->sslClient->arrays->preMasterSecret,
ashleymills 0:714293de3836 1063 session->sslServer->arrays->preMasterSecret, SECRET_LEN);
ashleymills 0:714293de3836 1064 session->sslClient->arrays->preMasterSz = SECRET_LEN;
ashleymills 0:714293de3836 1065
ashleymills 0:714293de3836 1066 #ifdef SHOW_SECRETS
ashleymills 0:714293de3836 1067 {
ashleymills 0:714293de3836 1068 int i;
ashleymills 0:714293de3836 1069 printf("pre master secret: ");
ashleymills 0:714293de3836 1070 for (i = 0; i < SECRET_LEN; i++)
ashleymills 0:714293de3836 1071 printf("%02x", session->sslServer->arrays->preMasterSecret[i]);
ashleymills 0:714293de3836 1072 printf("\n");
ashleymills 0:714293de3836 1073 }
ashleymills 0:714293de3836 1074 #endif
ashleymills 0:714293de3836 1075 }
ashleymills 0:714293de3836 1076 else {
ashleymills 0:714293de3836 1077 SetError(RSA_DECODE_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1078 FreeRsaKey(&key);
ashleymills 0:714293de3836 1079 return -1;
ashleymills 0:714293de3836 1080 }
ashleymills 0:714293de3836 1081
ashleymills 0:714293de3836 1082 if (SetCipherSpecs(session->sslServer) != 0) {
ashleymills 0:714293de3836 1083 SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1084 FreeRsaKey(&key);
ashleymills 0:714293de3836 1085 return -1;
ashleymills 0:714293de3836 1086 }
ashleymills 0:714293de3836 1087
ashleymills 0:714293de3836 1088 if (SetCipherSpecs(session->sslClient) != 0) {
ashleymills 0:714293de3836 1089 SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1090 FreeRsaKey(&key);
ashleymills 0:714293de3836 1091 return -1;
ashleymills 0:714293de3836 1092 }
ashleymills 0:714293de3836 1093
ashleymills 0:714293de3836 1094 MakeMasterSecret(session->sslServer);
ashleymills 0:714293de3836 1095 MakeMasterSecret(session->sslClient);
ashleymills 0:714293de3836 1096 #ifdef SHOW_SECRETS
ashleymills 0:714293de3836 1097 {
ashleymills 0:714293de3836 1098 int i;
ashleymills 0:714293de3836 1099 printf("server master secret: ");
ashleymills 0:714293de3836 1100 for (i = 0; i < SECRET_LEN; i++)
ashleymills 0:714293de3836 1101 printf("%02x", session->sslServer->arrays->masterSecret[i]);
ashleymills 0:714293de3836 1102 printf("\n");
ashleymills 0:714293de3836 1103
ashleymills 0:714293de3836 1104 printf("client master secret: ");
ashleymills 0:714293de3836 1105 for (i = 0; i < SECRET_LEN; i++)
ashleymills 0:714293de3836 1106 printf("%02x", session->sslClient->arrays->masterSecret[i]);
ashleymills 0:714293de3836 1107 printf("\n");
ashleymills 0:714293de3836 1108
ashleymills 0:714293de3836 1109 printf("server suite = %d\n", session->sslServer->options.cipherSuite);
ashleymills 0:714293de3836 1110 printf("client suite = %d\n", session->sslClient->options.cipherSuite);
ashleymills 0:714293de3836 1111 }
ashleymills 0:714293de3836 1112 #endif
ashleymills 0:714293de3836 1113
ashleymills 0:714293de3836 1114 FreeRsaKey(&key);
ashleymills 0:714293de3836 1115 return ret;
ashleymills 0:714293de3836 1116 }
ashleymills 0:714293de3836 1117
ashleymills 0:714293de3836 1118
ashleymills 0:714293de3836 1119 /* Process Session Ticket */
ashleymills 0:714293de3836 1120 static int ProcessSessionTicket(const byte* input, int* sslBytes,
ashleymills 0:714293de3836 1121 SnifferSession* session, char* error)
ashleymills 0:714293de3836 1122 {
ashleymills 0:714293de3836 1123 word16 len;
ashleymills 0:714293de3836 1124
ashleymills 0:714293de3836 1125 /* make sure can read through hint and len */
ashleymills 0:714293de3836 1126 if (TICKET_HINT_LEN + LENGTH_SZ > *sslBytes) {
ashleymills 0:714293de3836 1127 SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1128 return -1;
ashleymills 0:714293de3836 1129 }
ashleymills 0:714293de3836 1130
ashleymills 0:714293de3836 1131 input += TICKET_HINT_LEN; /* skip over hint */
ashleymills 0:714293de3836 1132 *sslBytes -= TICKET_HINT_LEN;
ashleymills 0:714293de3836 1133
ashleymills 0:714293de3836 1134 len = (input[0] << 8) | input[1];
ashleymills 0:714293de3836 1135 input += LENGTH_SZ;
ashleymills 0:714293de3836 1136 *sslBytes -= LENGTH_SZ;
ashleymills 0:714293de3836 1137
ashleymills 0:714293de3836 1138 /* make sure can read through ticket */
ashleymills 0:714293de3836 1139 if (len > *sslBytes || len < ID_LEN) {
ashleymills 0:714293de3836 1140 SetError(BAD_INPUT_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1141 return -1;
ashleymills 0:714293de3836 1142 }
ashleymills 0:714293de3836 1143
ashleymills 0:714293de3836 1144 /* store session with macID as sessionID */
ashleymills 0:714293de3836 1145 session->sslServer->options.haveSessionId = 1;
ashleymills 0:714293de3836 1146 XMEMCPY(session->sslServer->arrays->sessionID, input + len - ID_LEN,ID_LEN);
ashleymills 0:714293de3836 1147
ashleymills 0:714293de3836 1148 return 0;
ashleymills 0:714293de3836 1149 }
ashleymills 0:714293de3836 1150
ashleymills 0:714293de3836 1151
ashleymills 0:714293de3836 1152 /* Process Server Hello */
ashleymills 0:714293de3836 1153 static int ProcessServerHello(const byte* input, int* sslBytes,
ashleymills 0:714293de3836 1154 SnifferSession* session, char* error)
ashleymills 0:714293de3836 1155 {
ashleymills 0:714293de3836 1156 ProtocolVersion pv;
ashleymills 0:714293de3836 1157 byte b;
ashleymills 0:714293de3836 1158 int toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
ashleymills 0:714293de3836 1159 int doResume = 0;
ashleymills 0:714293de3836 1160
ashleymills 0:714293de3836 1161 /* make sure we didn't miss ClientHello */
ashleymills 0:714293de3836 1162 if (session->flags.clientHello == 0) {
ashleymills 0:714293de3836 1163 SetError(MISSED_CLIENT_HELLO_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1164 return -1;
ashleymills 0:714293de3836 1165 }
ashleymills 0:714293de3836 1166
ashleymills 0:714293de3836 1167 /* make sure can read through session len */
ashleymills 0:714293de3836 1168 if (toRead > *sslBytes) {
ashleymills 0:714293de3836 1169 SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1170 return -1;
ashleymills 0:714293de3836 1171 }
ashleymills 0:714293de3836 1172
ashleymills 0:714293de3836 1173 XMEMCPY(&pv, input, VERSION_SZ);
ashleymills 0:714293de3836 1174 input += VERSION_SZ;
ashleymills 0:714293de3836 1175 *sslBytes -= VERSION_SZ;
ashleymills 0:714293de3836 1176
ashleymills 0:714293de3836 1177 session->sslServer->version = pv;
ashleymills 0:714293de3836 1178 session->sslClient->version = pv;
ashleymills 0:714293de3836 1179
ashleymills 0:714293de3836 1180 XMEMCPY(session->sslServer->arrays->serverRandom, input, RAN_LEN);
ashleymills 0:714293de3836 1181 XMEMCPY(session->sslClient->arrays->serverRandom, input, RAN_LEN);
ashleymills 0:714293de3836 1182 input += RAN_LEN;
ashleymills 0:714293de3836 1183 *sslBytes -= RAN_LEN;
ashleymills 0:714293de3836 1184
ashleymills 0:714293de3836 1185 b = *input++;
ashleymills 0:714293de3836 1186 *sslBytes -= 1;
ashleymills 0:714293de3836 1187
ashleymills 0:714293de3836 1188 /* make sure can read through compression */
ashleymills 0:714293de3836 1189 if ( (b + SUITE_LEN + ENUM_LEN) > *sslBytes) {
ashleymills 0:714293de3836 1190 SetError(SERVER_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1191 return -1;
ashleymills 0:714293de3836 1192 }
ashleymills 0:714293de3836 1193 if (b) {
ashleymills 0:714293de3836 1194 XMEMCPY(session->sslServer->arrays->sessionID, input, ID_LEN);
ashleymills 0:714293de3836 1195 session->sslServer->options.haveSessionId = 1;
ashleymills 0:714293de3836 1196 }
ashleymills 0:714293de3836 1197 input += b;
ashleymills 0:714293de3836 1198 *sslBytes -= b;
ashleymills 0:714293de3836 1199
ashleymills 0:714293de3836 1200 /* cipher suite */
ashleymills 0:714293de3836 1201 b = *input++; /* first byte, ECC or not */
ashleymills 0:714293de3836 1202 session->sslServer->options.cipherSuite0 = b;
ashleymills 0:714293de3836 1203 session->sslClient->options.cipherSuite0 = b;
ashleymills 0:714293de3836 1204 b = *input++;
ashleymills 0:714293de3836 1205 session->sslServer->options.cipherSuite = b;
ashleymills 0:714293de3836 1206 session->sslClient->options.cipherSuite = b;
ashleymills 0:714293de3836 1207 *sslBytes -= SUITE_LEN;
ashleymills 0:714293de3836 1208
ashleymills 0:714293de3836 1209 /* compression */
ashleymills 0:714293de3836 1210 b = *input++;
ashleymills 0:714293de3836 1211 *sslBytes -= ENUM_LEN;
ashleymills 0:714293de3836 1212
ashleymills 0:714293de3836 1213 if (b) {
ashleymills 0:714293de3836 1214 SetError(BAD_COMPRESSION_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1215 return -1;
ashleymills 0:714293de3836 1216 }
ashleymills 0:714293de3836 1217
ashleymills 0:714293de3836 1218 if (session->sslServer->options.haveSessionId &&
ashleymills 0:714293de3836 1219 XMEMCMP(session->sslServer->arrays->sessionID,
ashleymills 0:714293de3836 1220 session->sslClient->arrays->sessionID, ID_LEN) == 0)
ashleymills 0:714293de3836 1221 doResume = 1;
ashleymills 0:714293de3836 1222 else if (session->sslClient->options.haveSessionId == 0 &&
ashleymills 0:714293de3836 1223 session->sslServer->options.haveSessionId == 0 &&
ashleymills 0:714293de3836 1224 session->ticketID)
ashleymills 0:714293de3836 1225 doResume = 1;
ashleymills 0:714293de3836 1226
ashleymills 0:714293de3836 1227 if (session->ticketID && doResume) {
ashleymills 0:714293de3836 1228 /* use ticketID to retrieve from session */
ashleymills 0:714293de3836 1229 XMEMCPY(session->sslServer->arrays->sessionID,session->ticketID,ID_LEN);
ashleymills 0:714293de3836 1230 }
ashleymills 0:714293de3836 1231
ashleymills 0:714293de3836 1232 if (doResume ) {
ashleymills 0:714293de3836 1233 int ret = 0;
ashleymills 0:714293de3836 1234 SSL_SESSION* resume = GetSession(session->sslServer,
ashleymills 0:714293de3836 1235 session->sslServer->arrays->masterSecret);
ashleymills 0:714293de3836 1236 if (resume == NULL) {
ashleymills 0:714293de3836 1237 SetError(BAD_SESSION_RESUME_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1238 return -1;
ashleymills 0:714293de3836 1239 }
ashleymills 0:714293de3836 1240 /* make sure client has master secret too */
ashleymills 0:714293de3836 1241 XMEMCPY(session->sslClient->arrays->masterSecret,
ashleymills 0:714293de3836 1242 session->sslServer->arrays->masterSecret, SECRET_LEN);
ashleymills 0:714293de3836 1243 session->flags.resuming = 1;
ashleymills 0:714293de3836 1244
ashleymills 0:714293de3836 1245 Trace(SERVER_DID_RESUMPTION_STR);
ashleymills 0:714293de3836 1246 if (SetCipherSpecs(session->sslServer) != 0) {
ashleymills 0:714293de3836 1247 SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1248 return -1;
ashleymills 0:714293de3836 1249 }
ashleymills 0:714293de3836 1250
ashleymills 0:714293de3836 1251 if (SetCipherSpecs(session->sslClient) != 0) {
ashleymills 0:714293de3836 1252 SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1253 return -1;
ashleymills 0:714293de3836 1254 }
ashleymills 0:714293de3836 1255
ashleymills 0:714293de3836 1256 if (session->sslServer->options.tls) {
ashleymills 0:714293de3836 1257 ret = DeriveTlsKeys(session->sslServer);
ashleymills 0:714293de3836 1258 ret += DeriveTlsKeys(session->sslClient);
ashleymills 0:714293de3836 1259 }
ashleymills 0:714293de3836 1260 else {
ashleymills 0:714293de3836 1261 ret = DeriveKeys(session->sslServer);
ashleymills 0:714293de3836 1262 ret += DeriveKeys(session->sslClient);
ashleymills 0:714293de3836 1263 }
ashleymills 0:714293de3836 1264 if (ret != 0) {
ashleymills 0:714293de3836 1265 SetError(BAD_DERIVE_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1266 return -1;
ashleymills 0:714293de3836 1267 }
ashleymills 0:714293de3836 1268 }
ashleymills 0:714293de3836 1269 #ifdef SHOW_SECRETS
ashleymills 0:714293de3836 1270 {
ashleymills 0:714293de3836 1271 int i;
ashleymills 0:714293de3836 1272 printf("cipher suite = 0x%02x\n",
ashleymills 0:714293de3836 1273 session->sslServer->options.cipherSuite);
ashleymills 0:714293de3836 1274 printf("server random: ");
ashleymills 0:714293de3836 1275 for (i = 0; i < RAN_LEN; i++)
ashleymills 0:714293de3836 1276 printf("%02x", session->sslServer->arrays->serverRandom[i]);
ashleymills 0:714293de3836 1277 printf("\n");
ashleymills 0:714293de3836 1278 }
ashleymills 0:714293de3836 1279 #endif
ashleymills 0:714293de3836 1280 return 0;
ashleymills 0:714293de3836 1281 }
ashleymills 0:714293de3836 1282
ashleymills 0:714293de3836 1283
ashleymills 0:714293de3836 1284 /* Process normal Client Hello */
ashleymills 0:714293de3836 1285 static int ProcessClientHello(const byte* input, int* sslBytes,
ashleymills 0:714293de3836 1286 SnifferSession* session, char* error)
ashleymills 0:714293de3836 1287 {
ashleymills 0:714293de3836 1288 byte bLen;
ashleymills 0:714293de3836 1289 word16 len;
ashleymills 0:714293de3836 1290 int toRead = VERSION_SZ + RAN_LEN + ENUM_LEN;
ashleymills 0:714293de3836 1291
ashleymills 0:714293de3836 1292 session->flags.clientHello = 1; /* don't process again */
ashleymills 0:714293de3836 1293
ashleymills 0:714293de3836 1294 /* make sure can read up to session len */
ashleymills 0:714293de3836 1295 if (toRead > *sslBytes) {
ashleymills 0:714293de3836 1296 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1297 return -1;
ashleymills 0:714293de3836 1298 }
ashleymills 0:714293de3836 1299
ashleymills 0:714293de3836 1300 /* skip, get negotiated one from server hello */
ashleymills 0:714293de3836 1301 input += VERSION_SZ;
ashleymills 0:714293de3836 1302 *sslBytes -= VERSION_SZ;
ashleymills 0:714293de3836 1303
ashleymills 0:714293de3836 1304 XMEMCPY(session->sslServer->arrays->clientRandom, input, RAN_LEN);
ashleymills 0:714293de3836 1305 XMEMCPY(session->sslClient->arrays->clientRandom, input, RAN_LEN);
ashleymills 0:714293de3836 1306
ashleymills 0:714293de3836 1307 input += RAN_LEN;
ashleymills 0:714293de3836 1308 *sslBytes -= RAN_LEN;
ashleymills 0:714293de3836 1309
ashleymills 0:714293de3836 1310 /* store session in case trying to resume */
ashleymills 0:714293de3836 1311 bLen = *input++;
ashleymills 0:714293de3836 1312 *sslBytes -= ENUM_LEN;
ashleymills 0:714293de3836 1313 if (bLen) {
ashleymills 0:714293de3836 1314 if (ID_LEN > *sslBytes) {
ashleymills 0:714293de3836 1315 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1316 return -1;
ashleymills 0:714293de3836 1317 }
ashleymills 0:714293de3836 1318 Trace(CLIENT_RESUME_TRY_STR);
ashleymills 0:714293de3836 1319 XMEMCPY(session->sslClient->arrays->sessionID, input, ID_LEN);
ashleymills 0:714293de3836 1320 session->sslClient->options.haveSessionId = 1;
ashleymills 0:714293de3836 1321 }
ashleymills 0:714293de3836 1322 #ifdef SHOW_SECRETS
ashleymills 0:714293de3836 1323 {
ashleymills 0:714293de3836 1324 int i;
ashleymills 0:714293de3836 1325 printf("client random: ");
ashleymills 0:714293de3836 1326 for (i = 0; i < RAN_LEN; i++)
ashleymills 0:714293de3836 1327 printf("%02x", session->sslServer->arrays->clientRandom[i]);
ashleymills 0:714293de3836 1328 printf("\n");
ashleymills 0:714293de3836 1329 }
ashleymills 0:714293de3836 1330 #endif
ashleymills 0:714293de3836 1331
ashleymills 0:714293de3836 1332 input += bLen;
ashleymills 0:714293de3836 1333 *sslBytes -= bLen;
ashleymills 0:714293de3836 1334
ashleymills 0:714293de3836 1335 /* skip cipher suites */
ashleymills 0:714293de3836 1336 /* make sure can read len */
ashleymills 0:714293de3836 1337 if (SUITE_LEN > *sslBytes) {
ashleymills 0:714293de3836 1338 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1339 return -1;
ashleymills 0:714293de3836 1340 }
ashleymills 0:714293de3836 1341 len = (input[0] << 8) | input[1];
ashleymills 0:714293de3836 1342 input += SUITE_LEN;
ashleymills 0:714293de3836 1343 *sslBytes -= SUITE_LEN;
ashleymills 0:714293de3836 1344 /* make sure can read suites + comp len */
ashleymills 0:714293de3836 1345 if (len + ENUM_LEN > *sslBytes) {
ashleymills 0:714293de3836 1346 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1347 return -1;
ashleymills 0:714293de3836 1348 }
ashleymills 0:714293de3836 1349 input += len;
ashleymills 0:714293de3836 1350 *sslBytes -= len;
ashleymills 0:714293de3836 1351
ashleymills 0:714293de3836 1352 /* skip compression */
ashleymills 0:714293de3836 1353 bLen = *input++;
ashleymills 0:714293de3836 1354 *sslBytes -= ENUM_LEN;
ashleymills 0:714293de3836 1355 /* make sure can read len */
ashleymills 0:714293de3836 1356 if (bLen > *sslBytes) {
ashleymills 0:714293de3836 1357 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1358 return -1;
ashleymills 0:714293de3836 1359 }
ashleymills 0:714293de3836 1360 input += bLen;
ashleymills 0:714293de3836 1361 *sslBytes -= bLen;
ashleymills 0:714293de3836 1362
ashleymills 0:714293de3836 1363 if (*sslBytes == 0) {
ashleymills 0:714293de3836 1364 /* no extensions */
ashleymills 0:714293de3836 1365 return 0;
ashleymills 0:714293de3836 1366 }
ashleymills 0:714293de3836 1367
ashleymills 0:714293de3836 1368 /* skip extensions until session ticket */
ashleymills 0:714293de3836 1369 /* make sure can read len */
ashleymills 0:714293de3836 1370 if (SUITE_LEN > *sslBytes) {
ashleymills 0:714293de3836 1371 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1372 return -1;
ashleymills 0:714293de3836 1373 }
ashleymills 0:714293de3836 1374 len = (input[0] << 8) | input[1];
ashleymills 0:714293de3836 1375 input += SUITE_LEN;
ashleymills 0:714293de3836 1376 *sslBytes -= SUITE_LEN;
ashleymills 0:714293de3836 1377 /* make sure can read through all extensions */
ashleymills 0:714293de3836 1378 if (len > *sslBytes) {
ashleymills 0:714293de3836 1379 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1380 return -1;
ashleymills 0:714293de3836 1381 }
ashleymills 0:714293de3836 1382
ashleymills 0:714293de3836 1383 while (len > EXT_TYPE_SZ + LENGTH_SZ) {
ashleymills 0:714293de3836 1384 byte extType[EXT_TYPE_SZ];
ashleymills 0:714293de3836 1385 word16 extLen;
ashleymills 0:714293de3836 1386
ashleymills 0:714293de3836 1387 extType[0] = input[0];
ashleymills 0:714293de3836 1388 extType[1] = input[1];
ashleymills 0:714293de3836 1389 input += EXT_TYPE_SZ;
ashleymills 0:714293de3836 1390 *sslBytes -= EXT_TYPE_SZ;
ashleymills 0:714293de3836 1391
ashleymills 0:714293de3836 1392 extLen = (input[0] << 8) | input[1];
ashleymills 0:714293de3836 1393 input += LENGTH_SZ;
ashleymills 0:714293de3836 1394 *sslBytes -= LENGTH_SZ;
ashleymills 0:714293de3836 1395
ashleymills 0:714293de3836 1396 /* make sure can read through individual extension */
ashleymills 0:714293de3836 1397 if (extLen > *sslBytes) {
ashleymills 0:714293de3836 1398 SetError(CLIENT_HELLO_INPUT_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1399 return -1;
ashleymills 0:714293de3836 1400 }
ashleymills 0:714293de3836 1401
ashleymills 0:714293de3836 1402 if (extType[0] == 0x00 && extType[1] == TICKET_EXT_ID) {
ashleymills 0:714293de3836 1403
ashleymills 0:714293de3836 1404 /* make sure can read through ticket if there is a non blank one */
ashleymills 0:714293de3836 1405 if (extLen && extLen < ID_LEN) {
ashleymills 0:714293de3836 1406 SetError(CLIENT_HELLO_INPUT_STR, error, session,
ashleymills 0:714293de3836 1407 FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1408 return -1;
ashleymills 0:714293de3836 1409 }
ashleymills 0:714293de3836 1410
ashleymills 0:714293de3836 1411 if (extLen) {
ashleymills 0:714293de3836 1412 if (session->ticketID == 0) {
ashleymills 0:714293de3836 1413 session->ticketID = (byte*)malloc(ID_LEN);
ashleymills 0:714293de3836 1414 if (session->ticketID == 0) {
ashleymills 0:714293de3836 1415 SetError(MEMORY_STR, error, session,
ashleymills 0:714293de3836 1416 FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1417 return -1;
ashleymills 0:714293de3836 1418 }
ashleymills 0:714293de3836 1419 }
ashleymills 0:714293de3836 1420 XMEMCPY(session->ticketID, input + extLen - ID_LEN, ID_LEN);
ashleymills 0:714293de3836 1421 }
ashleymills 0:714293de3836 1422 }
ashleymills 0:714293de3836 1423
ashleymills 0:714293de3836 1424 input += extLen;
ashleymills 0:714293de3836 1425 *sslBytes -= extLen;
ashleymills 0:714293de3836 1426 len -= extLen + EXT_TYPE_SZ + LENGTH_SZ;
ashleymills 0:714293de3836 1427 }
ashleymills 0:714293de3836 1428
ashleymills 0:714293de3836 1429 return 0;
ashleymills 0:714293de3836 1430 }
ashleymills 0:714293de3836 1431
ashleymills 0:714293de3836 1432
ashleymills 0:714293de3836 1433 /* Process Finished */
ashleymills 0:714293de3836 1434 static int ProcessFinished(const byte* input, int* sslBytes,
ashleymills 0:714293de3836 1435 SnifferSession* session, char* error)
ashleymills 0:714293de3836 1436 {
ashleymills 0:714293de3836 1437 SSL* ssl;
ashleymills 0:714293de3836 1438 word32 inOutIdx = 0;
ashleymills 0:714293de3836 1439 int ret;
ashleymills 0:714293de3836 1440
ashleymills 0:714293de3836 1441 if (session->flags.side == SERVER_END)
ashleymills 0:714293de3836 1442 ssl = session->sslServer;
ashleymills 0:714293de3836 1443 else
ashleymills 0:714293de3836 1444 ssl = session->sslClient;
ashleymills 0:714293de3836 1445 ret = DoFinished(ssl, input, &inOutIdx, SNIFF);
ashleymills 0:714293de3836 1446 *sslBytes -= (int)inOutIdx;
ashleymills 0:714293de3836 1447
ashleymills 0:714293de3836 1448 if (ret < 0) {
ashleymills 0:714293de3836 1449 SetError(BAD_FINISHED_MSG, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1450 return ret;
ashleymills 0:714293de3836 1451 }
ashleymills 0:714293de3836 1452
ashleymills 0:714293de3836 1453 if (ret == 0 && session->flags.cached == 0) {
ashleymills 0:714293de3836 1454 if (session->sslServer->options.haveSessionId) {
ashleymills 0:714293de3836 1455 CYASSL_SESSION* sess = GetSession(session->sslServer, NULL);
ashleymills 0:714293de3836 1456 if (sess == NULL)
ashleymills 0:714293de3836 1457 AddSession(session->sslServer); /* don't re add */
ashleymills 0:714293de3836 1458 session->flags.cached = 1;
ashleymills 0:714293de3836 1459 }
ashleymills 0:714293de3836 1460 }
ashleymills 0:714293de3836 1461
ashleymills 0:714293de3836 1462 FreeHandshakeResources(ssl);
ashleymills 0:714293de3836 1463
ashleymills 0:714293de3836 1464 return ret;
ashleymills 0:714293de3836 1465 }
ashleymills 0:714293de3836 1466
ashleymills 0:714293de3836 1467
ashleymills 0:714293de3836 1468 /* Process HandShake input */
ashleymills 0:714293de3836 1469 static int DoHandShake(const byte* input, int* sslBytes,
ashleymills 0:714293de3836 1470 SnifferSession* session, char* error)
ashleymills 0:714293de3836 1471 {
ashleymills 0:714293de3836 1472 byte type;
ashleymills 0:714293de3836 1473 int size;
ashleymills 0:714293de3836 1474 int ret = 0;
ashleymills 0:714293de3836 1475
ashleymills 0:714293de3836 1476 if (*sslBytes < HANDSHAKE_HEADER_SZ) {
ashleymills 0:714293de3836 1477 SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1478 return -1;
ashleymills 0:714293de3836 1479 }
ashleymills 0:714293de3836 1480 type = input[0];
ashleymills 0:714293de3836 1481 size = (input[1] << 16) | (input[2] << 8) | input[3];
ashleymills 0:714293de3836 1482
ashleymills 0:714293de3836 1483 input += HANDSHAKE_HEADER_SZ;
ashleymills 0:714293de3836 1484 *sslBytes -= HANDSHAKE_HEADER_SZ;
ashleymills 0:714293de3836 1485
ashleymills 0:714293de3836 1486 if (*sslBytes < size) {
ashleymills 0:714293de3836 1487 SetError(HANDSHAKE_INPUT_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1488 return -1;
ashleymills 0:714293de3836 1489 }
ashleymills 0:714293de3836 1490
ashleymills 0:714293de3836 1491 switch (type) {
ashleymills 0:714293de3836 1492 case hello_verify_request:
ashleymills 0:714293de3836 1493 Trace(GOT_HELLO_VERIFY_STR);
ashleymills 0:714293de3836 1494 break;
ashleymills 0:714293de3836 1495 case hello_request:
ashleymills 0:714293de3836 1496 Trace(GOT_HELLO_REQUEST_STR);
ashleymills 0:714293de3836 1497 break;
ashleymills 0:714293de3836 1498 case session_ticket:
ashleymills 0:714293de3836 1499 Trace(GOT_SESSION_TICKET_STR);
ashleymills 0:714293de3836 1500 ret = ProcessSessionTicket(input, sslBytes, session, error);
ashleymills 0:714293de3836 1501 break;
ashleymills 0:714293de3836 1502 case server_hello:
ashleymills 0:714293de3836 1503 Trace(GOT_SERVER_HELLO_STR);
ashleymills 0:714293de3836 1504 ret = ProcessServerHello(input, sslBytes, session, error);
ashleymills 0:714293de3836 1505 break;
ashleymills 0:714293de3836 1506 case certificate_request:
ashleymills 0:714293de3836 1507 Trace(GOT_CERT_REQ_STR);
ashleymills 0:714293de3836 1508 break;
ashleymills 0:714293de3836 1509 case server_key_exchange:
ashleymills 0:714293de3836 1510 Trace(GOT_SERVER_KEY_EX_STR);
ashleymills 0:714293de3836 1511 /* can't know temp key passively */
ashleymills 0:714293de3836 1512 SetError(BAD_CIPHER_SPEC_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1513 ret = -1;
ashleymills 0:714293de3836 1514 break;
ashleymills 0:714293de3836 1515 case certificate:
ashleymills 0:714293de3836 1516 Trace(GOT_CERT_STR);
ashleymills 0:714293de3836 1517 break;
ashleymills 0:714293de3836 1518 case server_hello_done:
ashleymills 0:714293de3836 1519 Trace(GOT_SERVER_HELLO_DONE_STR);
ashleymills 0:714293de3836 1520 break;
ashleymills 0:714293de3836 1521 case finished:
ashleymills 0:714293de3836 1522 Trace(GOT_FINISHED_STR);
ashleymills 0:714293de3836 1523 ret = ProcessFinished(input, sslBytes, session, error);
ashleymills 0:714293de3836 1524 break;
ashleymills 0:714293de3836 1525 case client_hello:
ashleymills 0:714293de3836 1526 Trace(GOT_CLIENT_HELLO_STR);
ashleymills 0:714293de3836 1527 ret = ProcessClientHello(input, sslBytes, session, error);
ashleymills 0:714293de3836 1528 break;
ashleymills 0:714293de3836 1529 case client_key_exchange:
ashleymills 0:714293de3836 1530 Trace(GOT_CLIENT_KEY_EX_STR);
ashleymills 0:714293de3836 1531 ret = ProcessClientKeyExchange(input, sslBytes, session, error);
ashleymills 0:714293de3836 1532 break;
ashleymills 0:714293de3836 1533 case certificate_verify:
ashleymills 0:714293de3836 1534 Trace(GOT_CERT_VER_STR);
ashleymills 0:714293de3836 1535 break;
ashleymills 0:714293de3836 1536 default:
ashleymills 0:714293de3836 1537 SetError(GOT_UNKNOWN_HANDSHAKE_STR, error, session, 0);
ashleymills 0:714293de3836 1538 return -1;
ashleymills 0:714293de3836 1539 }
ashleymills 0:714293de3836 1540
ashleymills 0:714293de3836 1541 return ret;
ashleymills 0:714293de3836 1542 }
ashleymills 0:714293de3836 1543
ashleymills 0:714293de3836 1544
ashleymills 0:714293de3836 1545 /* Decrypt input into plain output */
ashleymills 0:714293de3836 1546 static void Decrypt(SSL* ssl, byte* output, const byte* input, word32 sz)
ashleymills 0:714293de3836 1547 {
ashleymills 0:714293de3836 1548 switch (ssl->specs.bulk_cipher_algorithm) {
ashleymills 0:714293de3836 1549 #ifdef BUILD_ARC4
ashleymills 0:714293de3836 1550 case rc4:
ashleymills 0:714293de3836 1551 Arc4Process(ssl->decrypt.arc4, output, input, sz);
ashleymills 0:714293de3836 1552 break;
ashleymills 0:714293de3836 1553 #endif
ashleymills 0:714293de3836 1554
ashleymills 0:714293de3836 1555 #ifdef BUILD_DES3
ashleymills 0:714293de3836 1556 case triple_des:
ashleymills 0:714293de3836 1557 Des3_CbcDecrypt(ssl->decrypt.des3, output, input, sz);
ashleymills 0:714293de3836 1558 break;
ashleymills 0:714293de3836 1559 #endif
ashleymills 0:714293de3836 1560
ashleymills 0:714293de3836 1561 #ifdef BUILD_AES
ashleymills 0:714293de3836 1562 case aes:
ashleymills 0:714293de3836 1563 AesCbcDecrypt(ssl->decrypt.aes, output, input, sz);
ashleymills 0:714293de3836 1564 break;
ashleymills 0:714293de3836 1565 #endif
ashleymills 0:714293de3836 1566
ashleymills 0:714293de3836 1567 #ifdef HAVE_HC128
ashleymills 0:714293de3836 1568 case hc128:
ashleymills 0:714293de3836 1569 Hc128_Process(ssl->decrypt.hc128, output, input, sz);
ashleymills 0:714293de3836 1570 break;
ashleymills 0:714293de3836 1571 #endif
ashleymills 0:714293de3836 1572
ashleymills 0:714293de3836 1573 #ifdef BUILD_RABBIT
ashleymills 0:714293de3836 1574 case rabbit:
ashleymills 0:714293de3836 1575 RabbitProcess(ssl->decrypt.rabbit, output, input, sz);
ashleymills 0:714293de3836 1576 break;
ashleymills 0:714293de3836 1577 #endif
ashleymills 0:714293de3836 1578
ashleymills 0:714293de3836 1579 #ifdef HAVE_CAMELLIA
ashleymills 0:714293de3836 1580 case camellia:
ashleymills 0:714293de3836 1581 CamelliaCbcDecrypt(ssl->decrypt.cam, output, input, sz);
ashleymills 0:714293de3836 1582 break;
ashleymills 0:714293de3836 1583 #endif
ashleymills 0:714293de3836 1584
ashleymills 0:714293de3836 1585 default:
ashleymills 0:714293de3836 1586 Trace(BAD_DECRYPT_TYPE);
ashleymills 0:714293de3836 1587 break;
ashleymills 0:714293de3836 1588 }
ashleymills 0:714293de3836 1589 }
ashleymills 0:714293de3836 1590
ashleymills 0:714293de3836 1591
ashleymills 0:714293de3836 1592 /* Decrypt input message into output, adjust output steam if needed */
ashleymills 0:714293de3836 1593 static const byte* DecryptMessage(SSL* ssl, const byte* input, word32 sz,
ashleymills 0:714293de3836 1594 byte* output)
ashleymills 0:714293de3836 1595 {
ashleymills 0:714293de3836 1596 Decrypt(ssl, output, input, sz);
ashleymills 0:714293de3836 1597 ssl->keys.encryptSz = sz;
ashleymills 0:714293de3836 1598 if (ssl->options.tls1_1 && ssl->specs.cipher_type == block)
ashleymills 0:714293de3836 1599 return output + ssl->specs.block_size; /* go past TLSv1.1 IV */
ashleymills 0:714293de3836 1600
ashleymills 0:714293de3836 1601 return output;
ashleymills 0:714293de3836 1602 }
ashleymills 0:714293de3836 1603
ashleymills 0:714293de3836 1604
ashleymills 0:714293de3836 1605 /* remove session from table, use rowHint if no info (means we have a lock) */
ashleymills 0:714293de3836 1606 static void RemoveSession(SnifferSession* session, IpInfo* ipInfo,
ashleymills 0:714293de3836 1607 TcpInfo* tcpInfo, word32 rowHint)
ashleymills 0:714293de3836 1608 {
ashleymills 0:714293de3836 1609 SnifferSession* previous = 0;
ashleymills 0:714293de3836 1610 SnifferSession* current;
ashleymills 0:714293de3836 1611 word32 row = rowHint;
ashleymills 0:714293de3836 1612 int haveLock = 0;
ashleymills 0:714293de3836 1613
ashleymills 0:714293de3836 1614 if (ipInfo && tcpInfo)
ashleymills 0:714293de3836 1615 row = SessionHash(ipInfo, tcpInfo);
ashleymills 0:714293de3836 1616 else
ashleymills 0:714293de3836 1617 haveLock = 1;
ashleymills 0:714293de3836 1618
ashleymills 0:714293de3836 1619 assert(row <= HASH_SIZE);
ashleymills 0:714293de3836 1620 Trace(REMOVE_SESSION_STR);
ashleymills 0:714293de3836 1621
ashleymills 0:714293de3836 1622 if (!haveLock)
ashleymills 0:714293de3836 1623 LockMutex(&SessionMutex);
ashleymills 0:714293de3836 1624
ashleymills 0:714293de3836 1625 current = SessionTable[row];
ashleymills 0:714293de3836 1626
ashleymills 0:714293de3836 1627 while (current) {
ashleymills 0:714293de3836 1628 if (current == session) {
ashleymills 0:714293de3836 1629 if (previous)
ashleymills 0:714293de3836 1630 previous->next = current->next;
ashleymills 0:714293de3836 1631 else
ashleymills 0:714293de3836 1632 SessionTable[row] = current->next;
ashleymills 0:714293de3836 1633 FreeSnifferSession(session);
ashleymills 0:714293de3836 1634 TraceRemovedSession();
ashleymills 0:714293de3836 1635 break;
ashleymills 0:714293de3836 1636 }
ashleymills 0:714293de3836 1637 previous = current;
ashleymills 0:714293de3836 1638 current = current->next;
ashleymills 0:714293de3836 1639 }
ashleymills 0:714293de3836 1640
ashleymills 0:714293de3836 1641 if (!haveLock)
ashleymills 0:714293de3836 1642 UnLockMutex(&SessionMutex);
ashleymills 0:714293de3836 1643 }
ashleymills 0:714293de3836 1644
ashleymills 0:714293de3836 1645
ashleymills 0:714293de3836 1646 /* Remove stale sessions from the Session Table, have a lock */
ashleymills 0:714293de3836 1647 static void RemoveStaleSessions(void)
ashleymills 0:714293de3836 1648 {
ashleymills 0:714293de3836 1649 word32 i;
ashleymills 0:714293de3836 1650 SnifferSession* session;
ashleymills 0:714293de3836 1651
ashleymills 0:714293de3836 1652 for (i = 0; i < HASH_SIZE; i++) {
ashleymills 0:714293de3836 1653 session = SessionTable[i];
ashleymills 0:714293de3836 1654 while (session) {
ashleymills 0:714293de3836 1655 SnifferSession* next = session->next;
ashleymills 0:714293de3836 1656 if (time(NULL) >= session->lastUsed + SNIFFER_TIMEOUT) {
ashleymills 0:714293de3836 1657 TraceStaleSession();
ashleymills 0:714293de3836 1658 RemoveSession(session, NULL, NULL, i);
ashleymills 0:714293de3836 1659 }
ashleymills 0:714293de3836 1660 session = next;
ashleymills 0:714293de3836 1661 }
ashleymills 0:714293de3836 1662 }
ashleymills 0:714293de3836 1663 }
ashleymills 0:714293de3836 1664
ashleymills 0:714293de3836 1665
ashleymills 0:714293de3836 1666 /* Create a new Sniffer Session */
ashleymills 0:714293de3836 1667 static SnifferSession* CreateSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
ashleymills 0:714293de3836 1668 char* error)
ashleymills 0:714293de3836 1669 {
ashleymills 0:714293de3836 1670 SnifferSession* session = 0;
ashleymills 0:714293de3836 1671 int row;
ashleymills 0:714293de3836 1672
ashleymills 0:714293de3836 1673 Trace(NEW_SESSION_STR);
ashleymills 0:714293de3836 1674 /* create a new one */
ashleymills 0:714293de3836 1675 session = (SnifferSession*)malloc(sizeof(SnifferSession));
ashleymills 0:714293de3836 1676 if (session == NULL) {
ashleymills 0:714293de3836 1677 SetError(MEMORY_STR, error, NULL, 0);
ashleymills 0:714293de3836 1678 return 0;
ashleymills 0:714293de3836 1679 }
ashleymills 0:714293de3836 1680 InitSession(session);
ashleymills 0:714293de3836 1681 session->server = ipInfo->dst;
ashleymills 0:714293de3836 1682 session->client = ipInfo->src;
ashleymills 0:714293de3836 1683 session->srvPort = tcpInfo->dstPort;
ashleymills 0:714293de3836 1684 session->cliPort = tcpInfo->srcPort;
ashleymills 0:714293de3836 1685 session->cliSeqStart = tcpInfo->sequence;
ashleymills 0:714293de3836 1686 session->cliExpected = 1; /* relative */
ashleymills 0:714293de3836 1687 session->lastUsed= time(NULL);
ashleymills 0:714293de3836 1688
ashleymills 0:714293de3836 1689 session->context = GetSnifferServer(ipInfo, tcpInfo);
ashleymills 0:714293de3836 1690 if (session->context == NULL) {
ashleymills 0:714293de3836 1691 SetError(SERVER_NOT_REG_STR, error, NULL, 0);
ashleymills 0:714293de3836 1692 free(session);
ashleymills 0:714293de3836 1693 return 0;
ashleymills 0:714293de3836 1694 }
ashleymills 0:714293de3836 1695
ashleymills 0:714293de3836 1696 session->sslServer = SSL_new(session->context->ctx);
ashleymills 0:714293de3836 1697 if (session->sslServer == NULL) {
ashleymills 0:714293de3836 1698 SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1699 free(session);
ashleymills 0:714293de3836 1700 return 0;
ashleymills 0:714293de3836 1701 }
ashleymills 0:714293de3836 1702 session->sslClient = SSL_new(session->context->ctx);
ashleymills 0:714293de3836 1703 if (session->sslClient == NULL) {
ashleymills 0:714293de3836 1704 SSL_free(session->sslServer);
ashleymills 0:714293de3836 1705 session->sslServer = 0;
ashleymills 0:714293de3836 1706
ashleymills 0:714293de3836 1707 SetError(BAD_NEW_SSL_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1708 free(session);
ashleymills 0:714293de3836 1709 return 0;
ashleymills 0:714293de3836 1710 }
ashleymills 0:714293de3836 1711 /* put server back into server mode */
ashleymills 0:714293de3836 1712 session->sslServer->options.side = SERVER_END;
ashleymills 0:714293de3836 1713
ashleymills 0:714293de3836 1714 row = SessionHash(ipInfo, tcpInfo);
ashleymills 0:714293de3836 1715
ashleymills 0:714293de3836 1716 /* add it to the session table */
ashleymills 0:714293de3836 1717 LockMutex(&SessionMutex);
ashleymills 0:714293de3836 1718
ashleymills 0:714293de3836 1719 session->next = SessionTable[row];
ashleymills 0:714293de3836 1720 SessionTable[row] = session;
ashleymills 0:714293de3836 1721
ashleymills 0:714293de3836 1722 SessionCount++;
ashleymills 0:714293de3836 1723
ashleymills 0:714293de3836 1724 if ( (SessionCount % HASH_SIZE) == 0) {
ashleymills 0:714293de3836 1725 TraceFindingStale();
ashleymills 0:714293de3836 1726 RemoveStaleSessions();
ashleymills 0:714293de3836 1727 }
ashleymills 0:714293de3836 1728
ashleymills 0:714293de3836 1729 UnLockMutex(&SessionMutex);
ashleymills 0:714293de3836 1730
ashleymills 0:714293de3836 1731 /* determine headed side */
ashleymills 0:714293de3836 1732 if (ipInfo->dst == session->context->server &&
ashleymills 0:714293de3836 1733 tcpInfo->dstPort == session->context->port)
ashleymills 0:714293de3836 1734 session->flags.side = SERVER_END;
ashleymills 0:714293de3836 1735 else
ashleymills 0:714293de3836 1736 session->flags.side = CLIENT_END;
ashleymills 0:714293de3836 1737
ashleymills 0:714293de3836 1738 return session;
ashleymills 0:714293de3836 1739 }
ashleymills 0:714293de3836 1740
ashleymills 0:714293de3836 1741
ashleymills 0:714293de3836 1742 /* Process Old Client Hello Input */
ashleymills 0:714293de3836 1743 static int DoOldHello(SnifferSession* session, const byte* sslFrame,
ashleymills 0:714293de3836 1744 int* rhSize, int* sslBytes, char* error)
ashleymills 0:714293de3836 1745 {
ashleymills 0:714293de3836 1746 const byte* input = sslFrame;
ashleymills 0:714293de3836 1747 byte b0, b1;
ashleymills 0:714293de3836 1748 word32 idx = 0;
ashleymills 0:714293de3836 1749 int ret;
ashleymills 0:714293de3836 1750
ashleymills 0:714293de3836 1751 Trace(GOT_OLD_CLIENT_HELLO_STR);
ashleymills 0:714293de3836 1752 session->flags.clientHello = 1; /* don't process again */
ashleymills 0:714293de3836 1753 b0 = *input++;
ashleymills 0:714293de3836 1754 b1 = *input++;
ashleymills 0:714293de3836 1755 *sslBytes -= 2;
ashleymills 0:714293de3836 1756 *rhSize = ((b0 & 0x7f) << 8) | b1;
ashleymills 0:714293de3836 1757
ashleymills 0:714293de3836 1758 if (*rhSize > *sslBytes) {
ashleymills 0:714293de3836 1759 SetError(OLD_CLIENT_INPUT_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1760 return -1;
ashleymills 0:714293de3836 1761 }
ashleymills 0:714293de3836 1762
ashleymills 0:714293de3836 1763 ret = ProcessOldClientHello(session->sslServer, input, &idx, *sslBytes,
ashleymills 0:714293de3836 1764 *rhSize);
ashleymills 0:714293de3836 1765 if (ret < 0) {
ashleymills 0:714293de3836 1766 SetError(BAD_OLD_CLIENT_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1767 return -1;
ashleymills 0:714293de3836 1768 }
ashleymills 0:714293de3836 1769
ashleymills 0:714293de3836 1770 Trace(OLD_CLIENT_OK_STR);
ashleymills 0:714293de3836 1771 XMEMCPY(session->sslClient->arrays->clientRandom,
ashleymills 0:714293de3836 1772 session->sslServer->arrays->clientRandom, RAN_LEN);
ashleymills 0:714293de3836 1773
ashleymills 0:714293de3836 1774 *sslBytes -= *rhSize;
ashleymills 0:714293de3836 1775 return 0;
ashleymills 0:714293de3836 1776 }
ashleymills 0:714293de3836 1777
ashleymills 0:714293de3836 1778
ashleymills 0:714293de3836 1779 #if 0
ashleymills 0:714293de3836 1780 /* Calculate the TCP checksum, see RFC 1071 */
ashleymills 0:714293de3836 1781 /* return 0 for success, -1 on error */
ashleymills 0:714293de3836 1782 /* can be called from decode() with
ashleymills 0:714293de3836 1783 TcpChecksum(&ipInfo, &tcpInfo, sslBytes, packet + ipInfo.length);
ashleymills 0:714293de3836 1784 could also add a 64bit version if type available and using this
ashleymills 0:714293de3836 1785 */
ashleymills 0:714293de3836 1786 int TcpChecksum(IpInfo* ipInfo, TcpInfo* tcpInfo, int dataLen,
ashleymills 0:714293de3836 1787 const byte* packet)
ashleymills 0:714293de3836 1788 {
ashleymills 0:714293de3836 1789 TcpPseudoHdr pseudo;
ashleymills 0:714293de3836 1790 int count = PSEUDO_HDR_SZ;
ashleymills 0:714293de3836 1791 const word16* data = (word16*)&pseudo;
ashleymills 0:714293de3836 1792 word32 sum = 0;
ashleymills 0:714293de3836 1793 word16 checksum;
ashleymills 0:714293de3836 1794
ashleymills 0:714293de3836 1795 pseudo.src = ipInfo->src;
ashleymills 0:714293de3836 1796 pseudo.dst = ipInfo->dst;
ashleymills 0:714293de3836 1797 pseudo.rsv = 0;
ashleymills 0:714293de3836 1798 pseudo.protocol = TCP_PROTO;
ashleymills 0:714293de3836 1799 pseudo.legnth = htons(tcpInfo->length + dataLen);
ashleymills 0:714293de3836 1800
ashleymills 0:714293de3836 1801 /* pseudo header sum */
ashleymills 0:714293de3836 1802 while (count >= 2) {
ashleymills 0:714293de3836 1803 sum += *data++;
ashleymills 0:714293de3836 1804 count -= 2;
ashleymills 0:714293de3836 1805 }
ashleymills 0:714293de3836 1806
ashleymills 0:714293de3836 1807 count = tcpInfo->length + dataLen;
ashleymills 0:714293de3836 1808 data = (word16*)packet;
ashleymills 0:714293de3836 1809
ashleymills 0:714293de3836 1810 /* main sum */
ashleymills 0:714293de3836 1811 while (count > 1) {
ashleymills 0:714293de3836 1812 sum += *data++;
ashleymills 0:714293de3836 1813 count -=2;
ashleymills 0:714293de3836 1814 }
ashleymills 0:714293de3836 1815
ashleymills 0:714293de3836 1816 /* get left-over, if any */
ashleymills 0:714293de3836 1817 packet = (byte*)data;
ashleymills 0:714293de3836 1818 if (count > 0) {
ashleymills 0:714293de3836 1819 sum += *packet;
ashleymills 0:714293de3836 1820 }
ashleymills 0:714293de3836 1821
ashleymills 0:714293de3836 1822 /* fold 32bit sum into 16 bits */
ashleymills 0:714293de3836 1823 while (sum >> 16)
ashleymills 0:714293de3836 1824 sum = (sum & 0xffff) + (sum >> 16);
ashleymills 0:714293de3836 1825
ashleymills 0:714293de3836 1826 checksum = (word16)~sum;
ashleymills 0:714293de3836 1827 /* checksum should now equal 0, since included already calcd checksum */
ashleymills 0:714293de3836 1828 /* field, but tcp checksum offloading could negate calculation */
ashleymills 0:714293de3836 1829 if (checksum == 0)
ashleymills 0:714293de3836 1830 return 0;
ashleymills 0:714293de3836 1831 return -1;
ashleymills 0:714293de3836 1832 }
ashleymills 0:714293de3836 1833 #endif
ashleymills 0:714293de3836 1834
ashleymills 0:714293de3836 1835
ashleymills 0:714293de3836 1836 /* Check IP and TCP headers, set payload */
ashleymills 0:714293de3836 1837 /* returns 0 on success, -1 on error */
ashleymills 0:714293de3836 1838 static int CheckHeaders(IpInfo* ipInfo, TcpInfo* tcpInfo, const byte* packet,
ashleymills 0:714293de3836 1839 int length, const byte** sslFrame, int* sslBytes, char* error)
ashleymills 0:714293de3836 1840 {
ashleymills 0:714293de3836 1841 TraceHeader();
ashleymills 0:714293de3836 1842 TracePacket();
ashleymills 0:714293de3836 1843 if (length < IP_HDR_SZ) {
ashleymills 0:714293de3836 1844 SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
ashleymills 0:714293de3836 1845 return -1;
ashleymills 0:714293de3836 1846 }
ashleymills 0:714293de3836 1847 if (CheckIpHdr((IpHdr*)packet, ipInfo, error) != 0)
ashleymills 0:714293de3836 1848 return -1;
ashleymills 0:714293de3836 1849
ashleymills 0:714293de3836 1850 if (length < (ipInfo->length + TCP_HDR_SZ)) {
ashleymills 0:714293de3836 1851 SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
ashleymills 0:714293de3836 1852 return -1;
ashleymills 0:714293de3836 1853 }
ashleymills 0:714293de3836 1854 if (CheckTcpHdr((TcpHdr*)(packet + ipInfo->length), tcpInfo, error) != 0)
ashleymills 0:714293de3836 1855 return -1;
ashleymills 0:714293de3836 1856
ashleymills 0:714293de3836 1857 *sslFrame = packet + ipInfo->length + tcpInfo->length;
ashleymills 0:714293de3836 1858 if (*sslFrame > packet + length) {
ashleymills 0:714293de3836 1859 SetError(PACKET_HDR_SHORT_STR, error, NULL, 0);
ashleymills 0:714293de3836 1860 return -1;
ashleymills 0:714293de3836 1861 }
ashleymills 0:714293de3836 1862 *sslBytes = (int)(packet + length - *sslFrame);
ashleymills 0:714293de3836 1863
ashleymills 0:714293de3836 1864 return 0;
ashleymills 0:714293de3836 1865 }
ashleymills 0:714293de3836 1866
ashleymills 0:714293de3836 1867
ashleymills 0:714293de3836 1868 /* Create or Find existing session */
ashleymills 0:714293de3836 1869 /* returns 0 on success (continue), -1 on error, 1 on success (end) */
ashleymills 0:714293de3836 1870 static int CheckSession(IpInfo* ipInfo, TcpInfo* tcpInfo, int sslBytes,
ashleymills 0:714293de3836 1871 SnifferSession** session, char* error)
ashleymills 0:714293de3836 1872 {
ashleymills 0:714293de3836 1873 /* create a new SnifferSession on client SYN */
ashleymills 0:714293de3836 1874 if (tcpInfo->syn && !tcpInfo->ack) {
ashleymills 0:714293de3836 1875 TraceClientSyn(tcpInfo->sequence);
ashleymills 0:714293de3836 1876 *session = CreateSession(ipInfo, tcpInfo, error);
ashleymills 0:714293de3836 1877 if (*session == NULL) {
ashleymills 0:714293de3836 1878 *session = GetSnifferSession(ipInfo, tcpInfo);
ashleymills 0:714293de3836 1879 /* already had exisiting, so OK */
ashleymills 0:714293de3836 1880 if (*session)
ashleymills 0:714293de3836 1881 return 1;
ashleymills 0:714293de3836 1882
ashleymills 0:714293de3836 1883 SetError(MEMORY_STR, error, NULL, 0);
ashleymills 0:714293de3836 1884 return -1;
ashleymills 0:714293de3836 1885 }
ashleymills 0:714293de3836 1886 return 1;
ashleymills 0:714293de3836 1887 }
ashleymills 0:714293de3836 1888 /* get existing sniffer session */
ashleymills 0:714293de3836 1889 else {
ashleymills 0:714293de3836 1890 *session = GetSnifferSession(ipInfo, tcpInfo);
ashleymills 0:714293de3836 1891 if (*session == NULL) {
ashleymills 0:714293de3836 1892 /* don't worry about extraneous RST or duplicate FINs */
ashleymills 0:714293de3836 1893 if (tcpInfo->fin || tcpInfo->rst)
ashleymills 0:714293de3836 1894 return 1;
ashleymills 0:714293de3836 1895 /* don't worry about duplicate ACKs either */
ashleymills 0:714293de3836 1896 if (sslBytes == 0 && tcpInfo->ack)
ashleymills 0:714293de3836 1897 return 1;
ashleymills 0:714293de3836 1898
ashleymills 0:714293de3836 1899 SetError(BAD_SESSION_STR, error, NULL, 0);
ashleymills 0:714293de3836 1900 return -1;
ashleymills 0:714293de3836 1901 }
ashleymills 0:714293de3836 1902 }
ashleymills 0:714293de3836 1903 return 0;
ashleymills 0:714293de3836 1904 }
ashleymills 0:714293de3836 1905
ashleymills 0:714293de3836 1906
ashleymills 0:714293de3836 1907 /* Create a Packet Buffer from *begin - end, adjust new *begin and bytesLeft */
ashleymills 0:714293de3836 1908 static PacketBuffer* CreateBuffer(word32* begin, word32 end, const byte* data,
ashleymills 0:714293de3836 1909 int* bytesLeft)
ashleymills 0:714293de3836 1910 {
ashleymills 0:714293de3836 1911 PacketBuffer* pb;
ashleymills 0:714293de3836 1912
ashleymills 0:714293de3836 1913 int added = end - *begin + 1;
ashleymills 0:714293de3836 1914 assert(*begin <= end);
ashleymills 0:714293de3836 1915
ashleymills 0:714293de3836 1916 pb = (PacketBuffer*)malloc(sizeof(PacketBuffer));
ashleymills 0:714293de3836 1917 if (pb == NULL) return NULL;
ashleymills 0:714293de3836 1918
ashleymills 0:714293de3836 1919 pb->next = 0;
ashleymills 0:714293de3836 1920 pb->begin = *begin;
ashleymills 0:714293de3836 1921 pb->end = end;
ashleymills 0:714293de3836 1922 pb->data = (byte*)malloc(added);
ashleymills 0:714293de3836 1923
ashleymills 0:714293de3836 1924 if (pb->data == NULL) {
ashleymills 0:714293de3836 1925 free(pb);
ashleymills 0:714293de3836 1926 return NULL;
ashleymills 0:714293de3836 1927 }
ashleymills 0:714293de3836 1928 XMEMCPY(pb->data, data, added);
ashleymills 0:714293de3836 1929
ashleymills 0:714293de3836 1930 *bytesLeft -= added;
ashleymills 0:714293de3836 1931 *begin = pb->end + 1;
ashleymills 0:714293de3836 1932
ashleymills 0:714293de3836 1933 return pb;
ashleymills 0:714293de3836 1934 }
ashleymills 0:714293de3836 1935
ashleymills 0:714293de3836 1936
ashleymills 0:714293de3836 1937 /* Add sslFrame to Reassembly List */
ashleymills 0:714293de3836 1938 /* returns 1 (end) on success, -1, on error */
ashleymills 0:714293de3836 1939 static int AddToReassembly(byte from, word32 seq, const byte* sslFrame,
ashleymills 0:714293de3836 1940 int sslBytes, SnifferSession* session, char* error)
ashleymills 0:714293de3836 1941 {
ashleymills 0:714293de3836 1942 PacketBuffer* add;
ashleymills 0:714293de3836 1943 PacketBuffer** front = (from == SERVER_END) ? &session->cliReassemblyList:
ashleymills 0:714293de3836 1944 &session->srvReassemblyList;
ashleymills 0:714293de3836 1945 PacketBuffer* curr = *front;
ashleymills 0:714293de3836 1946 PacketBuffer* prev = curr;
ashleymills 0:714293de3836 1947
ashleymills 0:714293de3836 1948 word32 startSeq = seq;
ashleymills 0:714293de3836 1949 word32 added;
ashleymills 0:714293de3836 1950 int bytesLeft = sslBytes; /* could be overlapping fragment */
ashleymills 0:714293de3836 1951
ashleymills 0:714293de3836 1952 /* if list is empty add full frame to front */
ashleymills 0:714293de3836 1953 if (!curr) {
ashleymills 0:714293de3836 1954 add = CreateBuffer(&seq, seq + sslBytes - 1, sslFrame, &bytesLeft);
ashleymills 0:714293de3836 1955 if (add == NULL) {
ashleymills 0:714293de3836 1956 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1957 return -1;
ashleymills 0:714293de3836 1958 }
ashleymills 0:714293de3836 1959 *front = add;
ashleymills 0:714293de3836 1960 return 1;
ashleymills 0:714293de3836 1961 }
ashleymills 0:714293de3836 1962
ashleymills 0:714293de3836 1963 /* add to front if before current front, up to next->begin */
ashleymills 0:714293de3836 1964 if (seq < curr->begin) {
ashleymills 0:714293de3836 1965 word32 end = seq + sslBytes - 1;
ashleymills 0:714293de3836 1966
ashleymills 0:714293de3836 1967 if (end >= curr->begin)
ashleymills 0:714293de3836 1968 end = curr->begin - 1;
ashleymills 0:714293de3836 1969
ashleymills 0:714293de3836 1970 add = CreateBuffer(&seq, end, sslFrame, &bytesLeft);
ashleymills 0:714293de3836 1971 if (add == NULL) {
ashleymills 0:714293de3836 1972 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 1973 return -1;
ashleymills 0:714293de3836 1974 }
ashleymills 0:714293de3836 1975 add->next = curr;
ashleymills 0:714293de3836 1976 *front = add;
ashleymills 0:714293de3836 1977 }
ashleymills 0:714293de3836 1978
ashleymills 0:714293de3836 1979 /* while we have bytes left, try to find a gap to fill */
ashleymills 0:714293de3836 1980 while (bytesLeft > 0) {
ashleymills 0:714293de3836 1981 /* get previous packet in list */
ashleymills 0:714293de3836 1982 while (curr && (seq >= curr->begin)) {
ashleymills 0:714293de3836 1983 prev = curr;
ashleymills 0:714293de3836 1984 curr = curr->next;
ashleymills 0:714293de3836 1985 }
ashleymills 0:714293de3836 1986
ashleymills 0:714293de3836 1987 /* don't add duplicate data */
ashleymills 0:714293de3836 1988 if (prev->end >= seq) {
ashleymills 0:714293de3836 1989 if ( (seq + bytesLeft - 1) <= prev->end)
ashleymills 0:714293de3836 1990 return 1;
ashleymills 0:714293de3836 1991 seq = prev->end + 1;
ashleymills 0:714293de3836 1992 bytesLeft = startSeq + sslBytes - seq;
ashleymills 0:714293de3836 1993 }
ashleymills 0:714293de3836 1994
ashleymills 0:714293de3836 1995 if (!curr)
ashleymills 0:714293de3836 1996 /* we're at the end */
ashleymills 0:714293de3836 1997 added = bytesLeft;
ashleymills 0:714293de3836 1998 else
ashleymills 0:714293de3836 1999 /* we're in between two frames */
ashleymills 0:714293de3836 2000 added = min((word32)bytesLeft, curr->begin - seq);
ashleymills 0:714293de3836 2001
ashleymills 0:714293de3836 2002 /* data already there */
ashleymills 0:714293de3836 2003 if (added == 0)
ashleymills 0:714293de3836 2004 continue;
ashleymills 0:714293de3836 2005
ashleymills 0:714293de3836 2006 add = CreateBuffer(&seq, seq + added - 1, &sslFrame[seq - startSeq],
ashleymills 0:714293de3836 2007 &bytesLeft);
ashleymills 0:714293de3836 2008 if (add == NULL) {
ashleymills 0:714293de3836 2009 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 2010 return -1;
ashleymills 0:714293de3836 2011 }
ashleymills 0:714293de3836 2012 add->next = prev->next;
ashleymills 0:714293de3836 2013 prev->next = add;
ashleymills 0:714293de3836 2014 }
ashleymills 0:714293de3836 2015 return 1;
ashleymills 0:714293de3836 2016 }
ashleymills 0:714293de3836 2017
ashleymills 0:714293de3836 2018
ashleymills 0:714293de3836 2019 /* Add out of order FIN capture */
ashleymills 0:714293de3836 2020 /* returns 1 for success (end) */
ashleymills 0:714293de3836 2021 static int AddFinCapture(SnifferSession* session, word32 sequence)
ashleymills 0:714293de3836 2022 {
ashleymills 0:714293de3836 2023 if (session->flags.side == SERVER_END) {
ashleymills 0:714293de3836 2024 if (session->finCaputre.cliCounted == 0)
ashleymills 0:714293de3836 2025 session->finCaputre.cliFinSeq = sequence;
ashleymills 0:714293de3836 2026 }
ashleymills 0:714293de3836 2027 else {
ashleymills 0:714293de3836 2028 if (session->finCaputre.srvCounted == 0)
ashleymills 0:714293de3836 2029 session->finCaputre.srvFinSeq = sequence;
ashleymills 0:714293de3836 2030 }
ashleymills 0:714293de3836 2031 return 1;
ashleymills 0:714293de3836 2032 }
ashleymills 0:714293de3836 2033
ashleymills 0:714293de3836 2034
ashleymills 0:714293de3836 2035 /* Adjust incoming sequence based on side */
ashleymills 0:714293de3836 2036 /* returns 0 on success (continue), -1 on error, 1 on success (end) */
ashleymills 0:714293de3836 2037 static int AdjustSequence(TcpInfo* tcpInfo, SnifferSession* session,
ashleymills 0:714293de3836 2038 int* sslBytes, const byte** sslFrame, char* error)
ashleymills 0:714293de3836 2039 {
ashleymills 0:714293de3836 2040 word32 seqStart = (session->flags.side == SERVER_END) ?
ashleymills 0:714293de3836 2041 session->cliSeqStart :session->srvSeqStart;
ashleymills 0:714293de3836 2042 word32 real = tcpInfo->sequence - seqStart;
ashleymills 0:714293de3836 2043 word32* expected = (session->flags.side == SERVER_END) ?
ashleymills 0:714293de3836 2044 &session->cliExpected : &session->srvExpected;
ashleymills 0:714293de3836 2045 PacketBuffer* reassemblyList = (session->flags.side == SERVER_END) ?
ashleymills 0:714293de3836 2046 session->cliReassemblyList : session->srvReassemblyList;
ashleymills 0:714293de3836 2047
ashleymills 0:714293de3836 2048 /* handle rollover of sequence */
ashleymills 0:714293de3836 2049 if (tcpInfo->sequence < seqStart)
ashleymills 0:714293de3836 2050 real = 0xffffffffU - seqStart + tcpInfo->sequence;
ashleymills 0:714293de3836 2051
ashleymills 0:714293de3836 2052 TraceRelativeSequence(*expected, real);
ashleymills 0:714293de3836 2053
ashleymills 0:714293de3836 2054 if (real < *expected) {
ashleymills 0:714293de3836 2055 Trace(DUPLICATE_STR);
ashleymills 0:714293de3836 2056 if (real + *sslBytes > *expected) {
ashleymills 0:714293de3836 2057 int overlap = *expected - real;
ashleymills 0:714293de3836 2058 Trace(OVERLAP_DUPLICATE_STR);
ashleymills 0:714293de3836 2059
ashleymills 0:714293de3836 2060 /* adjust to expected, remove duplicate */
ashleymills 0:714293de3836 2061 *sslFrame += overlap;
ashleymills 0:714293de3836 2062 *sslBytes -= overlap;
ashleymills 0:714293de3836 2063
ashleymills 0:714293de3836 2064 if (reassemblyList) {
ashleymills 0:714293de3836 2065 word32 newEnd = *expected + *sslBytes;
ashleymills 0:714293de3836 2066
ashleymills 0:714293de3836 2067 if (newEnd > reassemblyList->begin) {
ashleymills 0:714293de3836 2068 Trace(OVERLAP_REASSEMBLY_BEGIN_STR);
ashleymills 0:714293de3836 2069
ashleymills 0:714293de3836 2070 /* remove bytes already on reassembly list */
ashleymills 0:714293de3836 2071 *sslBytes -= newEnd - reassemblyList->begin;
ashleymills 0:714293de3836 2072 }
ashleymills 0:714293de3836 2073 if (newEnd > reassemblyList->end) {
ashleymills 0:714293de3836 2074 Trace(OVERLAP_REASSEMBLY_END_STR);
ashleymills 0:714293de3836 2075
ashleymills 0:714293de3836 2076 /* may be past reassembly list end (could have more on list)
ashleymills 0:714293de3836 2077 so try to add what's past the front->end */
ashleymills 0:714293de3836 2078 AddToReassembly(session->flags.side, reassemblyList->end +1,
ashleymills 0:714293de3836 2079 *sslFrame + reassemblyList->end - *expected + 1,
ashleymills 0:714293de3836 2080 newEnd - reassemblyList->end, session, error);
ashleymills 0:714293de3836 2081 }
ashleymills 0:714293de3836 2082 }
ashleymills 0:714293de3836 2083 }
ashleymills 0:714293de3836 2084 else
ashleymills 0:714293de3836 2085 return 1;
ashleymills 0:714293de3836 2086 }
ashleymills 0:714293de3836 2087 else if (real > *expected) {
ashleymills 0:714293de3836 2088 Trace(OUT_OF_ORDER_STR);
ashleymills 0:714293de3836 2089 if (*sslBytes > 0)
ashleymills 0:714293de3836 2090 return AddToReassembly(session->flags.side, real, *sslFrame,
ashleymills 0:714293de3836 2091 *sslBytes, session, error);
ashleymills 0:714293de3836 2092 else if (tcpInfo->fin)
ashleymills 0:714293de3836 2093 return AddFinCapture(session, real);
ashleymills 0:714293de3836 2094 }
ashleymills 0:714293de3836 2095 /* got expected sequence */
ashleymills 0:714293de3836 2096 *expected += *sslBytes;
ashleymills 0:714293de3836 2097 if (tcpInfo->fin)
ashleymills 0:714293de3836 2098 *expected += 1;
ashleymills 0:714293de3836 2099
ashleymills 0:714293de3836 2100 return 0;
ashleymills 0:714293de3836 2101 }
ashleymills 0:714293de3836 2102
ashleymills 0:714293de3836 2103
ashleymills 0:714293de3836 2104 /* Check latest ack number for missing packets
ashleymills 0:714293de3836 2105 return 0 ok, <0 on error */
ashleymills 0:714293de3836 2106 static int CheckAck(TcpInfo* tcpInfo, SnifferSession* session)
ashleymills 0:714293de3836 2107 {
ashleymills 0:714293de3836 2108 if (tcpInfo->ack) {
ashleymills 0:714293de3836 2109 word32 seqStart = (session->flags.side == SERVER_END) ?
ashleymills 0:714293de3836 2110 session->srvSeqStart :session->cliSeqStart;
ashleymills 0:714293de3836 2111 word32 real = tcpInfo->ackNumber - seqStart;
ashleymills 0:714293de3836 2112 word32 expected = (session->flags.side == SERVER_END) ?
ashleymills 0:714293de3836 2113 session->srvExpected : session->cliExpected;
ashleymills 0:714293de3836 2114
ashleymills 0:714293de3836 2115 /* handle rollover of sequence */
ashleymills 0:714293de3836 2116 if (tcpInfo->ackNumber < seqStart)
ashleymills 0:714293de3836 2117 real = 0xffffffffU - seqStart + tcpInfo->ackNumber;
ashleymills 0:714293de3836 2118
ashleymills 0:714293de3836 2119 TraceAck(real, expected);
ashleymills 0:714293de3836 2120
ashleymills 0:714293de3836 2121 if (real > expected)
ashleymills 0:714293de3836 2122 return -1; /* we missed a packet, ACKing data we never saw */
ashleymills 0:714293de3836 2123 }
ashleymills 0:714293de3836 2124 return 0;
ashleymills 0:714293de3836 2125 }
ashleymills 0:714293de3836 2126
ashleymills 0:714293de3836 2127
ashleymills 0:714293de3836 2128 /* Check TCP Sequence status */
ashleymills 0:714293de3836 2129 /* returns 0 on success (continue), -1 on error, 1 on success (end) */
ashleymills 0:714293de3836 2130 static int CheckSequence(IpInfo* ipInfo, TcpInfo* tcpInfo,
ashleymills 0:714293de3836 2131 SnifferSession* session, int* sslBytes,
ashleymills 0:714293de3836 2132 const byte** sslFrame, char* error)
ashleymills 0:714293de3836 2133 {
ashleymills 0:714293de3836 2134 int actualLen;
ashleymills 0:714293de3836 2135
ashleymills 0:714293de3836 2136 /* init SEQ from server to client */
ashleymills 0:714293de3836 2137 if (tcpInfo->syn && tcpInfo->ack) {
ashleymills 0:714293de3836 2138 session->srvSeqStart = tcpInfo->sequence;
ashleymills 0:714293de3836 2139 session->srvExpected = 1;
ashleymills 0:714293de3836 2140 TraceServerSyn(tcpInfo->sequence);
ashleymills 0:714293de3836 2141 return 1;
ashleymills 0:714293de3836 2142 }
ashleymills 0:714293de3836 2143
ashleymills 0:714293de3836 2144 /* adjust potential ethernet trailer */
ashleymills 0:714293de3836 2145 actualLen = ipInfo->total - ipInfo->length - tcpInfo->length;
ashleymills 0:714293de3836 2146 if (*sslBytes > actualLen) {
ashleymills 0:714293de3836 2147 *sslBytes = actualLen;
ashleymills 0:714293de3836 2148 }
ashleymills 0:714293de3836 2149
ashleymills 0:714293de3836 2150 TraceSequence(tcpInfo->sequence, *sslBytes);
ashleymills 0:714293de3836 2151 if (CheckAck(tcpInfo, session) < 0) {
ashleymills 0:714293de3836 2152 SetError(ACK_MISSED_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 2153 return -1;
ashleymills 0:714293de3836 2154 }
ashleymills 0:714293de3836 2155
ashleymills 0:714293de3836 2156 return AdjustSequence(tcpInfo, session, sslBytes, sslFrame, error);
ashleymills 0:714293de3836 2157 }
ashleymills 0:714293de3836 2158
ashleymills 0:714293de3836 2159
ashleymills 0:714293de3836 2160 /* Check Status before record processing */
ashleymills 0:714293de3836 2161 /* returns 0 on success (continue), -1 on error, 1 on success (end) */
ashleymills 0:714293de3836 2162 static int CheckPreRecord(IpInfo* ipInfo, TcpInfo* tcpInfo,
ashleymills 0:714293de3836 2163 const byte** sslFrame, SnifferSession** session,
ashleymills 0:714293de3836 2164 int* sslBytes, const byte** end, char* error)
ashleymills 0:714293de3836 2165 {
ashleymills 0:714293de3836 2166 word32 length;
ashleymills 0:714293de3836 2167 SSL* ssl = ((*session)->flags.side == SERVER_END) ? (*session)->sslServer :
ashleymills 0:714293de3836 2168 (*session)->sslClient;
ashleymills 0:714293de3836 2169 /* remove SnifferSession on 2nd FIN or RST */
ashleymills 0:714293de3836 2170 if (tcpInfo->fin || tcpInfo->rst) {
ashleymills 0:714293de3836 2171 /* flag FIN and RST */
ashleymills 0:714293de3836 2172 if (tcpInfo->fin)
ashleymills 0:714293de3836 2173 (*session)->flags.finCount += 1;
ashleymills 0:714293de3836 2174 else if (tcpInfo->rst)
ashleymills 0:714293de3836 2175 (*session)->flags.finCount += 2;
ashleymills 0:714293de3836 2176
ashleymills 0:714293de3836 2177 if ((*session)->flags.finCount >= 2) {
ashleymills 0:714293de3836 2178 RemoveSession(*session, ipInfo, tcpInfo, 0);
ashleymills 0:714293de3836 2179 *session = NULL;
ashleymills 0:714293de3836 2180 return 1;
ashleymills 0:714293de3836 2181 }
ashleymills 0:714293de3836 2182 }
ashleymills 0:714293de3836 2183
ashleymills 0:714293de3836 2184 if ((*session)->flags.fatalError == FATAL_ERROR_STATE) {
ashleymills 0:714293de3836 2185 SetError(FATAL_ERROR_STR, error, NULL, 0);
ashleymills 0:714293de3836 2186 return -1;
ashleymills 0:714293de3836 2187 }
ashleymills 0:714293de3836 2188
ashleymills 0:714293de3836 2189 if (*sslBytes == 0) {
ashleymills 0:714293de3836 2190 Trace(NO_DATA_STR);
ashleymills 0:714293de3836 2191 return 1;
ashleymills 0:714293de3836 2192 }
ashleymills 0:714293de3836 2193
ashleymills 0:714293de3836 2194 /* if current partial data, add to end of partial */
ashleymills 0:714293de3836 2195 if ( (length = ssl->buffers.inputBuffer.length) ) {
ashleymills 0:714293de3836 2196 Trace(PARTIAL_ADD_STR);
ashleymills 0:714293de3836 2197
ashleymills 0:714293de3836 2198 if ( (*sslBytes + length) > ssl->buffers.inputBuffer.bufferSize) {
ashleymills 0:714293de3836 2199 if (GrowInputBuffer(ssl, *sslBytes, length) < 0) {
ashleymills 0:714293de3836 2200 SetError(MEMORY_STR, error, *session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 2201 return -1;
ashleymills 0:714293de3836 2202 }
ashleymills 0:714293de3836 2203 }
ashleymills 0:714293de3836 2204 XMEMCPY(&ssl->buffers.inputBuffer.buffer[length], *sslFrame, *sslBytes);
ashleymills 0:714293de3836 2205 *sslBytes += length;
ashleymills 0:714293de3836 2206 ssl->buffers.inputBuffer.length = *sslBytes;
ashleymills 0:714293de3836 2207 *sslFrame = ssl->buffers.inputBuffer.buffer;
ashleymills 0:714293de3836 2208 *end = *sslFrame + *sslBytes;
ashleymills 0:714293de3836 2209 }
ashleymills 0:714293de3836 2210
ashleymills 0:714293de3836 2211 if ((*session)->flags.clientHello == 0 && **sslFrame != handshake) {
ashleymills 0:714293de3836 2212 int rhSize;
ashleymills 0:714293de3836 2213 int ret = DoOldHello(*session, *sslFrame, &rhSize, sslBytes, error);
ashleymills 0:714293de3836 2214 if (ret < 0)
ashleymills 0:714293de3836 2215 return -1; /* error already set */
ashleymills 0:714293de3836 2216 if (*sslBytes <= 0)
ashleymills 0:714293de3836 2217 return 1;
ashleymills 0:714293de3836 2218 }
ashleymills 0:714293de3836 2219
ashleymills 0:714293de3836 2220 return 0;
ashleymills 0:714293de3836 2221 }
ashleymills 0:714293de3836 2222
ashleymills 0:714293de3836 2223
ashleymills 0:714293de3836 2224 /* See if input on the reassembly list is ready for consuming */
ashleymills 0:714293de3836 2225 /* returns 1 for TRUE, 0 for FALSE */
ashleymills 0:714293de3836 2226 static int HaveMoreInput(SnifferSession* session, const byte** sslFrame,
ashleymills 0:714293de3836 2227 int* sslBytes, const byte** end, char* error)
ashleymills 0:714293de3836 2228 {
ashleymills 0:714293de3836 2229 /* sequence and reassembly based on from, not to */
ashleymills 0:714293de3836 2230 int moreInput = 0;
ashleymills 0:714293de3836 2231 PacketBuffer** front = (session->flags.side == SERVER_END) ?
ashleymills 0:714293de3836 2232 &session->cliReassemblyList : &session->srvReassemblyList;
ashleymills 0:714293de3836 2233 word32* expected = (session->flags.side == SERVER_END) ?
ashleymills 0:714293de3836 2234 &session->cliExpected : &session->srvExpected;
ashleymills 0:714293de3836 2235 /* buffer is on receiving end */
ashleymills 0:714293de3836 2236 word32* length = (session->flags.side == SERVER_END) ?
ashleymills 0:714293de3836 2237 &session->sslServer->buffers.inputBuffer.length :
ashleymills 0:714293de3836 2238 &session->sslClient->buffers.inputBuffer.length;
ashleymills 0:714293de3836 2239 byte* myBuffer = (session->flags.side == SERVER_END) ?
ashleymills 0:714293de3836 2240 session->sslServer->buffers.inputBuffer.buffer :
ashleymills 0:714293de3836 2241 session->sslClient->buffers.inputBuffer.buffer;
ashleymills 0:714293de3836 2242 word32 bufferSize = (session->flags.side == SERVER_END) ?
ashleymills 0:714293de3836 2243 session->sslServer->buffers.inputBuffer.bufferSize :
ashleymills 0:714293de3836 2244 session->sslClient->buffers.inputBuffer.bufferSize;
ashleymills 0:714293de3836 2245 SSL* ssl = (session->flags.side == SERVER_END) ?
ashleymills 0:714293de3836 2246 session->sslServer : session->sslClient;
ashleymills 0:714293de3836 2247
ashleymills 0:714293de3836 2248 while (*front && ((*front)->begin == *expected) ) {
ashleymills 0:714293de3836 2249 word32 room = bufferSize - *length;
ashleymills 0:714293de3836 2250 word32 packetLen = (*front)->end - (*front)->begin + 1;
ashleymills 0:714293de3836 2251
ashleymills 0:714293de3836 2252 if (packetLen > room && bufferSize < MAX_INPUT_SZ) {
ashleymills 0:714293de3836 2253 if (GrowInputBuffer(ssl, packetLen, *length) < 0) {
ashleymills 0:714293de3836 2254 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 2255 return 0;
ashleymills 0:714293de3836 2256 }
ashleymills 0:714293de3836 2257 }
ashleymills 0:714293de3836 2258
ashleymills 0:714293de3836 2259 if (packetLen <= room) {
ashleymills 0:714293de3836 2260 PacketBuffer* del = *front;
ashleymills 0:714293de3836 2261
ashleymills 0:714293de3836 2262 XMEMCPY(&myBuffer[*length], (*front)->data, packetLen);
ashleymills 0:714293de3836 2263 *length += packetLen;
ashleymills 0:714293de3836 2264 *expected += packetLen;
ashleymills 0:714293de3836 2265
ashleymills 0:714293de3836 2266 /* remove used packet */
ashleymills 0:714293de3836 2267 *front = (*front)->next;
ashleymills 0:714293de3836 2268 FreePacketBuffer(del);
ashleymills 0:714293de3836 2269
ashleymills 0:714293de3836 2270 moreInput = 1;
ashleymills 0:714293de3836 2271 }
ashleymills 0:714293de3836 2272 else
ashleymills 0:714293de3836 2273 break;
ashleymills 0:714293de3836 2274 }
ashleymills 0:714293de3836 2275 if (moreInput) {
ashleymills 0:714293de3836 2276 *sslFrame = myBuffer;
ashleymills 0:714293de3836 2277 *sslBytes = *length;
ashleymills 0:714293de3836 2278 *end = myBuffer + *length;
ashleymills 0:714293de3836 2279 }
ashleymills 0:714293de3836 2280 return moreInput;
ashleymills 0:714293de3836 2281 }
ashleymills 0:714293de3836 2282
ashleymills 0:714293de3836 2283
ashleymills 0:714293de3836 2284
ashleymills 0:714293de3836 2285 /* Process Message(s) from sslFrame */
ashleymills 0:714293de3836 2286 /* return Number of bytes on success, 0 for no data yet, and -1 on error */
ashleymills 0:714293de3836 2287 static int ProcessMessage(const byte* sslFrame, SnifferSession* session,
ashleymills 0:714293de3836 2288 int sslBytes, byte* data, const byte* end,char* error)
ashleymills 0:714293de3836 2289 {
ashleymills 0:714293de3836 2290 const byte* sslBegin = sslFrame;
ashleymills 0:714293de3836 2291 const byte* tmp;
ashleymills 0:714293de3836 2292 RecordLayerHeader rh;
ashleymills 0:714293de3836 2293 int rhSize = 0;
ashleymills 0:714293de3836 2294 int ret;
ashleymills 0:714293de3836 2295 int decoded = 0; /* bytes stored for user in data */
ashleymills 0:714293de3836 2296 int notEnough; /* notEnough bytes yet flag */
ashleymills 0:714293de3836 2297 SSL* ssl = (session->flags.side == SERVER_END) ?
ashleymills 0:714293de3836 2298 session->sslServer : session->sslClient;
ashleymills 0:714293de3836 2299 doMessage:
ashleymills 0:714293de3836 2300 notEnough = 0;
ashleymills 0:714293de3836 2301 if (sslBytes >= RECORD_HEADER_SZ) {
ashleymills 0:714293de3836 2302 if (GetRecordHeader(sslFrame, &rh, &rhSize) != 0) {
ashleymills 0:714293de3836 2303 SetError(BAD_RECORD_HDR_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 2304 return -1;
ashleymills 0:714293de3836 2305 }
ashleymills 0:714293de3836 2306 }
ashleymills 0:714293de3836 2307 else
ashleymills 0:714293de3836 2308 notEnough = 1;
ashleymills 0:714293de3836 2309
ashleymills 0:714293de3836 2310 if (notEnough || rhSize > (sslBytes - RECORD_HEADER_SZ)) {
ashleymills 0:714293de3836 2311 /* don't have enough input yet to process full SSL record */
ashleymills 0:714293de3836 2312 Trace(PARTIAL_INPUT_STR);
ashleymills 0:714293de3836 2313
ashleymills 0:714293de3836 2314 /* store partial if not there already or we advanced */
ashleymills 0:714293de3836 2315 if (ssl->buffers.inputBuffer.length == 0 || sslBegin != sslFrame) {
ashleymills 0:714293de3836 2316 if (sslBytes > (int)ssl->buffers.inputBuffer.bufferSize) {
ashleymills 0:714293de3836 2317 if (GrowInputBuffer(ssl, sslBytes, 0) < 0) {
ashleymills 0:714293de3836 2318 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 2319 return -1;
ashleymills 0:714293de3836 2320 }
ashleymills 0:714293de3836 2321 }
ashleymills 0:714293de3836 2322 XMEMCPY(ssl->buffers.inputBuffer.buffer, sslFrame, sslBytes);
ashleymills 0:714293de3836 2323 ssl->buffers.inputBuffer.length = sslBytes;
ashleymills 0:714293de3836 2324 }
ashleymills 0:714293de3836 2325 if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error))
ashleymills 0:714293de3836 2326 goto doMessage;
ashleymills 0:714293de3836 2327 return decoded;
ashleymills 0:714293de3836 2328 }
ashleymills 0:714293de3836 2329 sslFrame += RECORD_HEADER_SZ;
ashleymills 0:714293de3836 2330 sslBytes -= RECORD_HEADER_SZ;
ashleymills 0:714293de3836 2331 tmp = sslFrame + rhSize; /* may have more than one record to process */
ashleymills 0:714293de3836 2332
ashleymills 0:714293de3836 2333 /* decrypt if needed */
ashleymills 0:714293de3836 2334 if ((session->flags.side == SERVER_END && session->flags.serverCipherOn)
ashleymills 0:714293de3836 2335 || (session->flags.side == CLIENT_END && session->flags.clientCipherOn)) {
ashleymills 0:714293de3836 2336 if (CheckAvailableSize(ssl, rhSize) < 0) {
ashleymills 0:714293de3836 2337 SetError(MEMORY_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 2338 return -1;
ashleymills 0:714293de3836 2339 }
ashleymills 0:714293de3836 2340 sslFrame = DecryptMessage(ssl, sslFrame, rhSize,
ashleymills 0:714293de3836 2341 ssl->buffers.outputBuffer.buffer);
ashleymills 0:714293de3836 2342 }
ashleymills 0:714293de3836 2343
ashleymills 0:714293de3836 2344 switch ((enum ContentType)rh.type) {
ashleymills 0:714293de3836 2345 case handshake:
ashleymills 0:714293de3836 2346 Trace(GOT_HANDSHAKE_STR);
ashleymills 0:714293de3836 2347 ret = DoHandShake(sslFrame, &sslBytes, session, error);
ashleymills 0:714293de3836 2348 if (ret != 0) {
ashleymills 0:714293de3836 2349 if (session->flags.fatalError == 0)
ashleymills 0:714293de3836 2350 SetError(BAD_HANDSHAKE_STR,error,session,FATAL_ERROR_STATE);
ashleymills 0:714293de3836 2351 return -1;
ashleymills 0:714293de3836 2352 }
ashleymills 0:714293de3836 2353 break;
ashleymills 0:714293de3836 2354 case change_cipher_spec:
ashleymills 0:714293de3836 2355 if (session->flags.side == SERVER_END)
ashleymills 0:714293de3836 2356 session->flags.serverCipherOn = 1;
ashleymills 0:714293de3836 2357 else
ashleymills 0:714293de3836 2358 session->flags.clientCipherOn = 1;
ashleymills 0:714293de3836 2359 Trace(GOT_CHANGE_CIPHER_STR);
ashleymills 0:714293de3836 2360 ssl->options.handShakeState = HANDSHAKE_DONE;
ashleymills 0:714293de3836 2361 break;
ashleymills 0:714293de3836 2362 case application_data:
ashleymills 0:714293de3836 2363 Trace(GOT_APP_DATA_STR);
ashleymills 0:714293de3836 2364 {
ashleymills 0:714293de3836 2365 word32 inOutIdx = 0;
ashleymills 0:714293de3836 2366
ashleymills 0:714293de3836 2367 ret = DoApplicationData(ssl, (byte*)sslFrame, &inOutIdx);
ashleymills 0:714293de3836 2368 if (ret == 0) {
ashleymills 0:714293de3836 2369 ret = ssl->buffers.clearOutputBuffer.length;
ashleymills 0:714293de3836 2370 TraceGotData(ret);
ashleymills 0:714293de3836 2371 if (ret) { /* may be blank message */
ashleymills 0:714293de3836 2372 XMEMCPY(&data[decoded],
ashleymills 0:714293de3836 2373 ssl->buffers.clearOutputBuffer.buffer, ret);
ashleymills 0:714293de3836 2374 TraceAddedData(ret, decoded);
ashleymills 0:714293de3836 2375 decoded += ret;
ashleymills 0:714293de3836 2376 ssl->buffers.clearOutputBuffer.length = 0;
ashleymills 0:714293de3836 2377 }
ashleymills 0:714293de3836 2378 }
ashleymills 0:714293de3836 2379 else {
ashleymills 0:714293de3836 2380 SetError(BAD_APP_DATA_STR, error,session,FATAL_ERROR_STATE);
ashleymills 0:714293de3836 2381 return -1;
ashleymills 0:714293de3836 2382 }
ashleymills 0:714293de3836 2383 if (ssl->buffers.outputBuffer.dynamicFlag)
ashleymills 0:714293de3836 2384 ShrinkOutputBuffer(ssl);
ashleymills 0:714293de3836 2385 }
ashleymills 0:714293de3836 2386 break;
ashleymills 0:714293de3836 2387 case alert:
ashleymills 0:714293de3836 2388 Trace(GOT_ALERT_STR);
ashleymills 0:714293de3836 2389 break;
ashleymills 0:714293de3836 2390 case no_type:
ashleymills 0:714293de3836 2391 default:
ashleymills 0:714293de3836 2392 SetError(GOT_UNKNOWN_RECORD_STR, error, session, FATAL_ERROR_STATE);
ashleymills 0:714293de3836 2393 return -1;
ashleymills 0:714293de3836 2394 }
ashleymills 0:714293de3836 2395
ashleymills 0:714293de3836 2396 if (tmp < end) {
ashleymills 0:714293de3836 2397 Trace(ANOTHER_MSG_STR);
ashleymills 0:714293de3836 2398 sslFrame = tmp;
ashleymills 0:714293de3836 2399 sslBytes = (int)(end - tmp);
ashleymills 0:714293de3836 2400 goto doMessage;
ashleymills 0:714293de3836 2401 }
ashleymills 0:714293de3836 2402
ashleymills 0:714293de3836 2403 /* clear used input */
ashleymills 0:714293de3836 2404 ssl->buffers.inputBuffer.length = 0;
ashleymills 0:714293de3836 2405
ashleymills 0:714293de3836 2406 /* could have more input ready now */
ashleymills 0:714293de3836 2407 if (HaveMoreInput(session, &sslFrame, &sslBytes, &end, error))
ashleymills 0:714293de3836 2408 goto doMessage;
ashleymills 0:714293de3836 2409
ashleymills 0:714293de3836 2410 if (ssl->buffers.inputBuffer.dynamicFlag)
ashleymills 0:714293de3836 2411 ShrinkInputBuffer(ssl, NO_FORCED_FREE);
ashleymills 0:714293de3836 2412
ashleymills 0:714293de3836 2413 return decoded;
ashleymills 0:714293de3836 2414 }
ashleymills 0:714293de3836 2415
ashleymills 0:714293de3836 2416
ashleymills 0:714293de3836 2417 /* See if we need to process any pending FIN captures */
ashleymills 0:714293de3836 2418 static void CheckFinCapture(IpInfo* ipInfo, TcpInfo* tcpInfo,
ashleymills 0:714293de3836 2419 SnifferSession* session)
ashleymills 0:714293de3836 2420 {
ashleymills 0:714293de3836 2421 if (session->finCaputre.cliFinSeq && session->finCaputre.cliFinSeq <=
ashleymills 0:714293de3836 2422 session->cliExpected) {
ashleymills 0:714293de3836 2423 if (session->finCaputre.cliCounted == 0) {
ashleymills 0:714293de3836 2424 session->flags.finCount += 1;
ashleymills 0:714293de3836 2425 session->finCaputre.cliCounted = 1;
ashleymills 0:714293de3836 2426 TraceClientFin(session->finCaputre.cliFinSeq, session->cliExpected);
ashleymills 0:714293de3836 2427 }
ashleymills 0:714293de3836 2428 }
ashleymills 0:714293de3836 2429
ashleymills 0:714293de3836 2430 if (session->finCaputre.srvFinSeq && session->finCaputre.srvFinSeq <=
ashleymills 0:714293de3836 2431 session->srvExpected) {
ashleymills 0:714293de3836 2432 if (session->finCaputre.srvCounted == 0) {
ashleymills 0:714293de3836 2433 session->flags.finCount += 1;
ashleymills 0:714293de3836 2434 session->finCaputre.srvCounted = 1;
ashleymills 0:714293de3836 2435 TraceServerFin(session->finCaputre.srvFinSeq, session->srvExpected);
ashleymills 0:714293de3836 2436 }
ashleymills 0:714293de3836 2437 }
ashleymills 0:714293de3836 2438
ashleymills 0:714293de3836 2439 if (session->flags.finCount >= 2)
ashleymills 0:714293de3836 2440 RemoveSession(session, ipInfo, tcpInfo, 0);
ashleymills 0:714293de3836 2441 }
ashleymills 0:714293de3836 2442
ashleymills 0:714293de3836 2443
ashleymills 0:714293de3836 2444 /* If session is in fatal error state free resources now
ashleymills 0:714293de3836 2445 return true if removed, 0 otherwise */
ashleymills 0:714293de3836 2446 static int RemoveFatalSession(IpInfo* ipInfo, TcpInfo* tcpInfo,
ashleymills 0:714293de3836 2447 SnifferSession* session, char* error)
ashleymills 0:714293de3836 2448 {
ashleymills 0:714293de3836 2449 if (session && session->flags.fatalError == FATAL_ERROR_STATE) {
ashleymills 0:714293de3836 2450 RemoveSession(session, ipInfo, tcpInfo, 0);
ashleymills 0:714293de3836 2451 SetError(FATAL_ERROR_STR, error, NULL, 0);
ashleymills 0:714293de3836 2452 return 1;
ashleymills 0:714293de3836 2453 }
ashleymills 0:714293de3836 2454 return 0;
ashleymills 0:714293de3836 2455 }
ashleymills 0:714293de3836 2456
ashleymills 0:714293de3836 2457
ashleymills 0:714293de3836 2458 /* Passes in an IP/TCP packet for decoding (ethernet/localhost frame) removed */
ashleymills 0:714293de3836 2459 /* returns Number of bytes on success, 0 for no data yet, and -1 on error */
ashleymills 0:714293de3836 2460 int ssl_DecodePacket(const byte* packet, int length, byte* data, char* error)
ashleymills 0:714293de3836 2461 {
ashleymills 0:714293de3836 2462 TcpInfo tcpInfo;
ashleymills 0:714293de3836 2463 IpInfo ipInfo;
ashleymills 0:714293de3836 2464 const byte* sslFrame;
ashleymills 0:714293de3836 2465 const byte* end = packet + length;
ashleymills 0:714293de3836 2466 int sslBytes; /* ssl bytes unconsumed */
ashleymills 0:714293de3836 2467 int ret;
ashleymills 0:714293de3836 2468 SnifferSession* session = 0;
ashleymills 0:714293de3836 2469
ashleymills 0:714293de3836 2470 if (CheckHeaders(&ipInfo, &tcpInfo, packet, length, &sslFrame, &sslBytes,
ashleymills 0:714293de3836 2471 error) != 0)
ashleymills 0:714293de3836 2472 return -1;
ashleymills 0:714293de3836 2473
ashleymills 0:714293de3836 2474 ret = CheckSession(&ipInfo, &tcpInfo, sslBytes, &session, error);
ashleymills 0:714293de3836 2475 if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
ashleymills 0:714293de3836 2476 else if (ret == -1) return -1;
ashleymills 0:714293de3836 2477 else if (ret == 1) return 0; /* done for now */
ashleymills 0:714293de3836 2478
ashleymills 0:714293de3836 2479 ret = CheckSequence(&ipInfo, &tcpInfo, session, &sslBytes, &sslFrame,error);
ashleymills 0:714293de3836 2480 if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
ashleymills 0:714293de3836 2481 else if (ret == -1) return -1;
ashleymills 0:714293de3836 2482 else if (ret == 1) return 0; /* done for now */
ashleymills 0:714293de3836 2483
ashleymills 0:714293de3836 2484 ret = CheckPreRecord(&ipInfo, &tcpInfo, &sslFrame, &session, &sslBytes,
ashleymills 0:714293de3836 2485 &end, error);
ashleymills 0:714293de3836 2486 if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
ashleymills 0:714293de3836 2487 else if (ret == -1) return -1;
ashleymills 0:714293de3836 2488 else if (ret == 1) return 0; /* done for now */
ashleymills 0:714293de3836 2489
ashleymills 0:714293de3836 2490 ret = ProcessMessage(sslFrame, session, sslBytes, data, end, error);
ashleymills 0:714293de3836 2491 if (RemoveFatalSession(&ipInfo, &tcpInfo, session, error)) return -1;
ashleymills 0:714293de3836 2492 CheckFinCapture(&ipInfo, &tcpInfo, session);
ashleymills 0:714293de3836 2493 return ret;
ashleymills 0:714293de3836 2494 }
ashleymills 0:714293de3836 2495
ashleymills 0:714293de3836 2496
ashleymills 0:714293de3836 2497 /* Enables (if traceFile)/ Disables debug tracing */
ashleymills 0:714293de3836 2498 /* returns 0 on success, -1 on error */
ashleymills 0:714293de3836 2499 int ssl_Trace(const char* traceFile, char* error)
ashleymills 0:714293de3836 2500 {
ashleymills 0:714293de3836 2501 if (traceFile) {
ashleymills 0:714293de3836 2502 TraceFile = fopen(traceFile, "a");
ashleymills 0:714293de3836 2503 if (!TraceFile) {
ashleymills 0:714293de3836 2504 SetError(BAD_TRACE_FILE_STR, error, NULL, 0);
ashleymills 0:714293de3836 2505 return -1;
ashleymills 0:714293de3836 2506 }
ashleymills 0:714293de3836 2507 TraceOn = 1;
ashleymills 0:714293de3836 2508 }
ashleymills 0:714293de3836 2509 else
ashleymills 0:714293de3836 2510 TraceOn = 0;
ashleymills 0:714293de3836 2511
ashleymills 0:714293de3836 2512 return 0;
ashleymills 0:714293de3836 2513 }
ashleymills 0:714293de3836 2514
ashleymills 0:714293de3836 2515
ashleymills 0:714293de3836 2516
ashleymills 0:714293de3836 2517
ashleymills 0:714293de3836 2518 #endif /* CYASSL_SNIFFER */