cyassl re-port with cellular comms, PSK test

Dependencies:   VodafoneUSBModem_bleedingedge2 mbed-rtos mbed-src

Committer:
ashleymills
Date:
Fri Apr 26 16:59:36 2013 +0000
Revision:
1:b211d97b0068
Parent:
0:e979170e02e7
nothing

Who changed what in which revision?

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