1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/cmd/ssltap/ssltap.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,2039 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +/* 1.9 + * ssltap.c 1.10 + * 1.11 + * Version 1.0 : Frederick Roeber : 11 June 1997 1.12 + * Version 2.0 : Steve Parkinson : 13 November 1997 1.13 + * Version 3.0 : Nelson Bolyard : 22 July 1998 1.14 + * Version 3.1 : Nelson Bolyard : 24 May 1999 1.15 + * 1.16 + * changes in version 2.0: 1.17 + * Uses NSPR20 1.18 + * Shows structure of SSL negotiation, if enabled. 1.19 + * 1.20 + * This "proxies" a socket connection (like a socks tunnel), but displays the 1.21 + * data is it flies by. 1.22 + * 1.23 + * In the code, the 'client' socket is the one on the client side of the 1.24 + * proxy, and the server socket is on the server side. 1.25 + * 1.26 + */ 1.27 + 1.28 +#include "nspr.h" 1.29 +#include "plstr.h" 1.30 +#include "secutil.h" 1.31 +#include <memory.h> /* for memcpy, etc. */ 1.32 +#include <string.h> 1.33 +#include <time.h> 1.34 + 1.35 +#include "plgetopt.h" 1.36 +#include "nss.h" 1.37 +#include "cert.h" 1.38 +#include "sslproto.h" 1.39 +#include "ocsp.h" 1.40 +#include "ocspti.h" /* internals for pretty-printing routines *only* */ 1.41 + 1.42 +struct _DataBufferList; 1.43 +struct _DataBuffer; 1.44 + 1.45 +typedef struct _DataBufferList { 1.46 + struct _DataBuffer *first,*last; 1.47 + int size; 1.48 + int isEncrypted; 1.49 + unsigned char * msgBuf; 1.50 + int msgBufOffset; 1.51 + int msgBufSize; 1.52 + int hMACsize; 1.53 +} DataBufferList; 1.54 + 1.55 +typedef struct _DataBuffer { 1.56 + unsigned char *buffer; 1.57 + int length; 1.58 + int offset; /* offset of first good byte */ 1.59 + struct _DataBuffer *next; 1.60 +} DataBuffer; 1.61 + 1.62 + 1.63 + 1.64 +struct sslhandshake { 1.65 + PRUint8 type; 1.66 + PRUint32 length; 1.67 +}; 1.68 + 1.69 +typedef struct _SSLRecord { 1.70 + PRUint8 type; 1.71 + PRUint8 ver_maj,ver_min; 1.72 + 1.73 + PRUint8 length[2]; 1.74 +} SSLRecord; 1.75 + 1.76 +typedef struct _ClientHelloV2 { 1.77 + PRUint8 length[2]; 1.78 + PRUint8 type; 1.79 + PRUint8 version[2]; 1.80 + PRUint8 cslength[2]; 1.81 + PRUint8 sidlength[2]; 1.82 + PRUint8 rndlength[2]; 1.83 + PRUint8 csuites[1]; 1.84 +} ClientHelloV2; 1.85 + 1.86 +typedef struct _ServerHelloV2 { 1.87 + PRUint8 length[2]; 1.88 + PRUint8 type; 1.89 + PRUint8 sidhit; 1.90 + PRUint8 certtype; 1.91 + PRUint8 version[2]; 1.92 + PRUint8 certlength[2]; 1.93 + PRUint8 cslength[2]; 1.94 + PRUint8 cidlength[2]; 1.95 +} ServerHelloV2; 1.96 + 1.97 +typedef struct _ClientMasterKeyV2 { 1.98 + PRUint8 length[2]; 1.99 + PRUint8 type; 1.100 + 1.101 + PRUint8 cipherkind[3]; 1.102 + PRUint8 clearkey[2]; 1.103 + PRUint8 secretkey[2]; 1.104 + 1.105 +} ClientMasterKeyV2; 1.106 + 1.107 +/* forward declaration */ 1.108 +void showErr(const char * msg); 1.109 + 1.110 +#define TAPBUFSIZ 16384 1.111 + 1.112 +#define DEFPORT 1924 1.113 +#include <ctype.h> 1.114 + 1.115 +const char * progName; 1.116 +int hexparse=0; 1.117 +int sslparse=0; 1.118 +int sslhexparse=0; 1.119 +int looparound=0; 1.120 +int fancy=0; 1.121 +int isV2Session=0; 1.122 +int currentcipher=0; 1.123 +DataBufferList clientstream, serverstream; 1.124 + 1.125 +#define PR_FPUTS(x) PR_fprintf(PR_STDOUT, x ) 1.126 + 1.127 +#define GET_SHORT(x) ((PRUint16)(((PRUint16)((PRUint8*)x)[0]) << 8) + ((PRUint16)((PRUint8*)x)[1])) 1.128 +#define GET_24(x) ((PRUint32) ( \ 1.129 + (((PRUint32)((PRUint8*)x)[0]) << 16) \ 1.130 + + \ 1.131 + (((PRUint32)((PRUint8*)x)[1]) << 8) \ 1.132 + + \ 1.133 + (((PRUint32)((PRUint8*)x)[2]) << 0) \ 1.134 + ) ) 1.135 +#define GET_32(x) ((PRUint32) ( \ 1.136 + (((PRUint32)((PRUint8*)x)[0]) << 24) \ 1.137 + + \ 1.138 + (((PRUint32)((PRUint8*)x)[1]) << 16) \ 1.139 + + \ 1.140 + (((PRUint32)((PRUint8*)x)[2]) << 8) \ 1.141 + + \ 1.142 + (((PRUint32)((PRUint8*)x)[3]) << 0) \ 1.143 + ) ) 1.144 + 1.145 +void print_hex(int amt, unsigned char *buf); 1.146 +void read_stream_bytes(unsigned char *d, DataBufferList *db, int length); 1.147 + 1.148 +void myhalt(int dblsize,int collectedsize) 1.149 +{ 1.150 + 1.151 + PR_fprintf(PR_STDERR,"HALTED\n"); 1.152 + PR_ASSERT(dblsize == collectedsize); 1.153 + exit(13); 1.154 +} 1.155 + 1.156 +const char *get_error_text(int error) 1.157 +{ 1.158 + switch (error) { 1.159 + case PR_IO_TIMEOUT_ERROR: 1.160 + return "Timeout"; 1.161 + break; 1.162 + case PR_CONNECT_REFUSED_ERROR: 1.163 + return "Connection refused"; 1.164 + break; 1.165 + case PR_NETWORK_UNREACHABLE_ERROR: 1.166 + return "Network unreachable"; 1.167 + break; 1.168 + case PR_BAD_ADDRESS_ERROR: 1.169 + return "Bad address"; 1.170 + break; 1.171 + case PR_CONNECT_RESET_ERROR: 1.172 + return "Connection reset"; 1.173 + break; 1.174 + case PR_PIPE_ERROR: 1.175 + return "Pipe error"; 1.176 + break; 1.177 + } 1.178 + 1.179 + return ""; 1.180 +} 1.181 + 1.182 + 1.183 + 1.184 + 1.185 + 1.186 +void check_integrity(DataBufferList *dbl) 1.187 +{ 1.188 + DataBuffer *db; 1.189 + int i; 1.190 + 1.191 + db = dbl->first; 1.192 + i =0; 1.193 + while (db) { 1.194 + i+= db->length - db->offset; 1.195 + db = db->next; 1.196 + } 1.197 + if (i != dbl->size) { 1.198 + myhalt(dbl->size,i); 1.199 + } 1.200 +} 1.201 + 1.202 +/* Free's the DataBuffer at the head of the list and returns the pointer 1.203 + * to the new head of the list. 1.204 + */ 1.205 +DataBuffer * 1.206 +free_head(DataBufferList *dbl) 1.207 +{ 1.208 + DataBuffer *db = dbl->first; 1.209 + PR_ASSERT(db->offset >= db->length); 1.210 + if (db->offset >= db->length) { 1.211 + dbl->first = db->next; 1.212 + if (dbl->first == NULL) { 1.213 + dbl->last = NULL; 1.214 + } 1.215 + PORT_Free(db->buffer); 1.216 + PORT_Free(db); 1.217 + db = dbl->first; 1.218 + } 1.219 + return db; 1.220 +} 1.221 + 1.222 +void 1.223 +read_stream_bytes(unsigned char *d, DataBufferList *dbl, int length) 1.224 +{ 1.225 + int copied = 0; 1.226 + DataBuffer *db = dbl->first; 1.227 + 1.228 + if (!db) { 1.229 + PR_fprintf(PR_STDERR,"assert failed - dbl->first is null\n"); 1.230 + exit(8); 1.231 + } 1.232 + while (length) { 1.233 + int toCopy; 1.234 + /* find the number of bytes to copy from the head buffer */ 1.235 + /* if there's too many in this buffer, then only copy 'length' */ 1.236 + toCopy = PR_MIN(db->length - db->offset, length); 1.237 + 1.238 + memcpy(d + copied, db->buffer + db->offset, toCopy); 1.239 + copied += toCopy; 1.240 + db->offset += toCopy; 1.241 + length -= toCopy; 1.242 + dbl->size -= toCopy; 1.243 + 1.244 + /* if we emptied the head buffer */ 1.245 + if (db->offset >= db->length) { 1.246 + db = free_head(dbl); 1.247 + } 1.248 + } 1.249 + 1.250 + check_integrity(dbl); 1.251 + 1.252 +} 1.253 + 1.254 +void 1.255 +flush_stream(DataBufferList *dbl) 1.256 +{ 1.257 + DataBuffer *db = dbl->first; 1.258 + check_integrity(dbl); 1.259 + while (db) { 1.260 + db->offset = db->length; 1.261 + db = free_head(dbl); 1.262 + } 1.263 + dbl->size = 0; 1.264 + check_integrity(dbl); 1.265 + if (dbl->msgBuf) { 1.266 + PORT_Free(dbl->msgBuf); 1.267 + dbl->msgBuf = NULL; 1.268 + } 1.269 + dbl->msgBufOffset = 0; 1.270 + dbl->msgBufSize = 0; 1.271 + dbl->hMACsize = 0; 1.272 +} 1.273 + 1.274 + 1.275 +const char * V2CipherString(int cs_int) 1.276 +{ 1.277 + char *cs_str; 1.278 + cs_str = NULL; 1.279 + switch (cs_int) { 1.280 + 1.281 + case 0x010080: cs_str = "SSL2/RSA/RC4-128/MD5"; break; 1.282 + case 0x020080: cs_str = "SSL2/RSA/RC4-40/MD5"; break; 1.283 + case 0x030080: cs_str = "SSL2/RSA/RC2CBC128/MD5"; break; 1.284 + case 0x040080: cs_str = "SSL2/RSA/RC2CBC40/MD5"; break; 1.285 + case 0x050080: cs_str = "SSL2/RSA/IDEA128CBC/MD5"; break; 1.286 + case 0x060040: cs_str = "SSL2/RSA/DES56-CBC/MD5"; break; 1.287 + case 0x0700C0: cs_str = "SSL2/RSA/3DES192EDE-CBC/MD5"; break; 1.288 + 1.289 + case 0x000001: cs_str = "SSL3/RSA/NULL/MD5"; break; 1.290 + case 0x000002: cs_str = "SSL3/RSA/NULL/SHA"; break; 1.291 + case 0x000003: cs_str = "SSL3/RSA/RC4-40/MD5"; break; 1.292 + case 0x000004: cs_str = "SSL3/RSA/RC4-128/MD5"; break; 1.293 + case 0x000005: cs_str = "SSL3/RSA/RC4-128/SHA"; break; 1.294 + case 0x000006: cs_str = "SSL3/RSA/RC2CBC40/MD5"; break; 1.295 + case 0x000007: cs_str = "SSL3/RSA/IDEA128CBC/SHA"; break; 1.296 + case 0x000008: cs_str = "SSL3/RSA/DES40-CBC/SHA"; break; 1.297 + case 0x000009: cs_str = "SSL3/RSA/DES56-CBC/SHA"; break; 1.298 + case 0x00000A: cs_str = "SSL3/RSA/3DES192EDE-CBC/SHA"; break; 1.299 + 1.300 + case 0x00000B: cs_str = "SSL3/DH-DSS/DES40-CBC/SHA"; break; 1.301 + case 0x00000C: cs_str = "SSL3/DH-DSS/DES56-CBC/SHA"; break; 1.302 + case 0x00000D: cs_str = "SSL3/DH-DSS/DES192EDE3CBC/SHA"; break; 1.303 + case 0x00000E: cs_str = "SSL3/DH-RSA/DES40-CBC/SHA"; break; 1.304 + case 0x00000F: cs_str = "SSL3/DH-RSA/DES56-CBC/SHA"; break; 1.305 + case 0x000010: cs_str = "SSL3/DH-RSA/3DES192EDE-CBC/SHA"; break; 1.306 + 1.307 + case 0x000011: cs_str = "SSL3/DHE-DSS/DES40-CBC/SHA"; break; 1.308 + case 0x000012: cs_str = "SSL3/DHE-DSS/DES56-CBC/SHA"; break; 1.309 + case 0x000013: cs_str = "SSL3/DHE-DSS/DES192EDE3CBC/SHA"; break; 1.310 + case 0x000014: cs_str = "SSL3/DHE-RSA/DES40-CBC/SHA"; break; 1.311 + case 0x000015: cs_str = "SSL3/DHE-RSA/DES56-CBC/SHA"; break; 1.312 + case 0x000016: cs_str = "SSL3/DHE-RSA/3DES192EDE-CBC/SHA"; break; 1.313 + 1.314 + case 0x000017: cs_str = "SSL3/DH-anon/RC4-40/MD5"; break; 1.315 + case 0x000018: cs_str = "SSL3/DH-anon/RC4-128/MD5"; break; 1.316 + case 0x000019: cs_str = "SSL3/DH-anon/DES40-CBC/SHA"; break; 1.317 + case 0x00001A: cs_str = "SSL3/DH-anon/DES56-CBC/SHA"; break; 1.318 + case 0x00001B: cs_str = "SSL3/DH-anon/3DES192EDE-CBC/SHA"; break; 1.319 + 1.320 + case 0x00001C: cs_str = "SSL3/FORTEZZA-DMS/NULL/SHA"; break; 1.321 + case 0x00001D: cs_str = "SSL3/FORTEZZA-DMS/FORTEZZA-CBC/SHA"; break; 1.322 + case 0x00001E: cs_str = "SSL3/FORTEZZA-DMS/RC4-128/SHA"; break; 1.323 + 1.324 + case 0x00002F: cs_str = "TLS/RSA/AES128-CBC/SHA"; break; 1.325 + case 0x000030: cs_str = "TLS/DH-DSS/AES128-CBC/SHA"; break; 1.326 + case 0x000031: cs_str = "TLS/DH-RSA/AES128-CBC/SHA"; break; 1.327 + case 0x000032: cs_str = "TLS/DHE-DSS/AES128-CBC/SHA"; break; 1.328 + case 0x000033: cs_str = "TLS/DHE-RSA/AES128-CBC/SHA"; break; 1.329 + case 0x000034: cs_str = "TLS/DH-ANON/AES128-CBC/SHA"; break; 1.330 + 1.331 + case 0x000035: cs_str = "TLS/RSA/AES256-CBC/SHA"; break; 1.332 + case 0x000036: cs_str = "TLS/DH-DSS/AES256-CBC/SHA"; break; 1.333 + case 0x000037: cs_str = "TLS/DH-RSA/AES256-CBC/SHA"; break; 1.334 + case 0x000038: cs_str = "TLS/DHE-DSS/AES256-CBC/SHA"; break; 1.335 + case 0x000039: cs_str = "TLS/DHE-RSA/AES256-CBC/SHA"; break; 1.336 + case 0x00003A: cs_str = "TLS/DH-ANON/AES256-CBC/SHA"; break; 1.337 + 1.338 + case 0x00003B: cs_str = "TLS/RSA/NULL/SHA256"; break; 1.339 + case 0x00003C: cs_str = "TLS/RSA/AES128-CBC/SHA256"; break; 1.340 + case 0x00003D: cs_str = "TLS/RSA/AES256-CBC/SHA256"; break; 1.341 + case 0x00003E: cs_str = "TLS/DH-DSS/AES128-CBC/SHA256"; break; 1.342 + case 0x00003F: cs_str = "TLS/DH-RSA/AES128-CBC/SHA256"; break; 1.343 + case 0x000040: cs_str = "TLS/DHE-DSS/AES128-CBC/SHA256"; break; 1.344 + 1.345 + case 0x000041: cs_str = "TLS/RSA/CAMELLIA128-CBC/SHA"; break; 1.346 + case 0x000042: cs_str = "TLS/DH-DSS/CAMELLIA128-CBC/SHA"; break; 1.347 + case 0x000043: cs_str = "TLS/DH-RSA/CAMELLIA128-CBC/SHA"; break; 1.348 + case 0x000044: cs_str = "TLS/DHE-DSS/CAMELLIA128-CBC/SHA"; break; 1.349 + case 0x000045: cs_str = "TLS/DHE-RSA/CAMELLIA128-CBC/SHA"; break; 1.350 + case 0x000046: cs_str = "TLS/DH-ANON/CAMELLIA128-CBC/SHA"; break; 1.351 + 1.352 + case 0x000060: cs_str = "TLS/RSA-EXPORT1024/RC4-56/MD5"; break; 1.353 + case 0x000061: cs_str = "TLS/RSA-EXPORT1024/RC2CBC56/MD5"; break; 1.354 + case 0x000062: cs_str = "TLS/RSA-EXPORT1024/DES56-CBC/SHA"; break; 1.355 + case 0x000064: cs_str = "TLS/RSA-EXPORT1024/RC4-56/SHA"; break; 1.356 + case 0x000063: cs_str = "TLS/DHE-DSS_EXPORT1024/DES56-CBC/SHA"; break; 1.357 + case 0x000065: cs_str = "TLS/DHE-DSS_EXPORT1024/RC4-56/SHA"; break; 1.358 + case 0x000066: cs_str = "TLS/DHE-DSS/RC4-128/SHA"; break; 1.359 + 1.360 + case 0x000067: cs_str = "TLS/DHE-RSA/AES128-CBC/SHA256"; break; 1.361 + case 0x000068: cs_str = "TLS/DH-DSS/AES256-CBC/SHA256"; break; 1.362 + case 0x000069: cs_str = "TLS/DH-RSA/AES256-CBC/SHA256"; break; 1.363 + case 0x00006A: cs_str = "TLS/DHE-DSS/AES256-CBC/SHA256"; break; 1.364 + case 0x00006B: cs_str = "TLS/DHE-RSA/AES256-CBC/SHA256"; break; 1.365 + 1.366 + case 0x000072: cs_str = "TLS/DHE-DSS/3DESEDE-CBC/RMD160"; break; 1.367 + case 0x000073: cs_str = "TLS/DHE-DSS/AES128-CBC/RMD160"; break; 1.368 + case 0x000074: cs_str = "TLS/DHE-DSS/AES256-CBC/RMD160"; break; 1.369 + 1.370 + case 0x000079: cs_str = "TLS/DHE-RSA/AES256-CBC/RMD160"; break; 1.371 + 1.372 + case 0x00007C: cs_str = "TLS/RSA/3DESEDE-CBC/RMD160"; break; 1.373 + case 0x00007D: cs_str = "TLS/RSA/AES128-CBC/RMD160"; break; 1.374 + case 0x00007E: cs_str = "TLS/RSA/AES256-CBC/RMD160"; break; 1.375 + 1.376 + case 0x000080: cs_str = "TLS/GOST341094/GOST28147-OFB/GOST28147"; break; 1.377 + case 0x000081: cs_str = "TLS/GOST34102001/GOST28147-OFB/GOST28147"; break; 1.378 + case 0x000082: cs_str = "TLS/GOST341094/NULL/GOSTR3411"; break; 1.379 + case 0x000083: cs_str = "TLS/GOST34102001/NULL/GOSTR3411"; break; 1.380 + 1.381 + case 0x000084: cs_str = "TLS/RSA/CAMELLIA256-CBC/SHA"; break; 1.382 + case 0x000085: cs_str = "TLS/DH-DSS/CAMELLIA256-CBC/SHA"; break; 1.383 + case 0x000086: cs_str = "TLS/DH-RSA/CAMELLIA256-CBC/SHA"; break; 1.384 + case 0x000087: cs_str = "TLS/DHE-DSS/CAMELLIA256-CBC/SHA"; break; 1.385 + case 0x000088: cs_str = "TLS/DHE-RSA/CAMELLIA256-CBC/SHA"; break; 1.386 + case 0x000089: cs_str = "TLS/DH-ANON/CAMELLIA256-CBC/SHA"; break; 1.387 + case 0x00008A: cs_str = "TLS/PSK/RC4-128/SHA"; break; 1.388 + case 0x00008B: cs_str = "TLS/PSK/3DES-EDE-CBC/SHA"; break; 1.389 + case 0x00008C: cs_str = "TLS/PSK/AES128-CBC/SHA"; break; 1.390 + case 0x00008D: cs_str = "TLS/PSK/AES256-CBC/SHA"; break; 1.391 + case 0x00008E: cs_str = "TLS/DHE-PSK/RC4-128/SHA"; break; 1.392 + case 0x00008F: cs_str = "TLS/DHE-PSK/3DES-EDE-CBC/SHA"; break; 1.393 + case 0x000090: cs_str = "TLS/DHE-PSK/AES128-CBC/SHA"; break; 1.394 + case 0x000091: cs_str = "TLS/DHE-PSK/AES256-CBC/SHA"; break; 1.395 + case 0x000092: cs_str = "TLS/RSA-PSK/RC4-128/SHA"; break; 1.396 + case 0x000093: cs_str = "TLS/RSA-PSK/3DES-EDE-CBC/SHA"; break; 1.397 + case 0x000094: cs_str = "TLS/RSA-PSK/AES128-CBC/SHA"; break; 1.398 + case 0x000095: cs_str = "TLS/RSA-PSK/AES256-CBC/SHA"; break; 1.399 + case 0x000096: cs_str = "TLS/RSA/SEED-CBC/SHA"; break; 1.400 + case 0x000097: cs_str = "TLS/DH-DSS/SEED-CBC/SHA"; break; 1.401 + case 0x000098: cs_str = "TLS/DH-RSA/SEED-CBC/SHA"; break; 1.402 + case 0x000099: cs_str = "TLS/DHE-DSS/SEED-CBC/SHA"; break; 1.403 + case 0x00009A: cs_str = "TLS/DHE-RSA/SEED-CBC/SHA"; break; 1.404 + case 0x00009B: cs_str = "TLS/DH-ANON/SEED-CBC/SHA"; break; 1.405 + case 0x00009C: cs_str = "TLS/RSA/AES128-GCM/SHA256"; break; 1.406 + case 0x00009E: cs_str = "TLS/DHE-RSA/AES128-GCM/SHA256"; break; 1.407 + 1.408 + case 0x0000FF: cs_str = "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"; break; 1.409 + 1.410 + case 0x00C001: cs_str = "TLS/ECDH-ECDSA/NULL/SHA"; break; 1.411 + case 0x00C002: cs_str = "TLS/ECDH-ECDSA/RC4-128/SHA"; break; 1.412 + case 0x00C003: cs_str = "TLS/ECDH-ECDSA/3DES-EDE-CBC/SHA"; break; 1.413 + case 0x00C004: cs_str = "TLS/ECDH-ECDSA/AES128-CBC/SHA"; break; 1.414 + case 0x00C005: cs_str = "TLS/ECDH-ECDSA/AES256-CBC/SHA"; break; 1.415 + case 0x00C006: cs_str = "TLS/ECDHE-ECDSA/NULL/SHA"; break; 1.416 + case 0x00C007: cs_str = "TLS/ECDHE-ECDSA/RC4-128/SHA"; break; 1.417 + case 0x00C008: cs_str = "TLS/ECDHE-ECDSA/3DES-EDE-CBC/SHA";break; 1.418 + case 0x00C009: cs_str = "TLS/ECDHE-ECDSA/AES128-CBC/SHA"; break; 1.419 + case 0x00C00A: cs_str = "TLS/ECDHE-ECDSA/AES256-CBC/SHA"; break; 1.420 + case 0x00C00B: cs_str = "TLS/ECDH-RSA/NULL/SHA"; break; 1.421 + case 0x00C00C: cs_str = "TLS/ECDH-RSA/RC4-128/SHA"; break; 1.422 + case 0x00C00D: cs_str = "TLS/ECDH-RSA/3DES-EDE-CBC/SHA"; break; 1.423 + case 0x00C00E: cs_str = "TLS/ECDH-RSA/AES128-CBC/SHA"; break; 1.424 + case 0x00C00F: cs_str = "TLS/ECDH-RSA/AES256-CBC/SHA"; break; 1.425 + case 0x00C010: cs_str = "TLS/ECDHE-RSA/NULL/SHA"; break; 1.426 + case 0x00C011: cs_str = "TLS/ECDHE-RSA/RC4-128/SHA"; break; 1.427 + case 0x00C012: cs_str = "TLS/ECDHE-RSA/3DES-EDE-CBC/SHA"; break; 1.428 + case 0x00C013: cs_str = "TLS/ECDHE-RSA/AES128-CBC/SHA"; break; 1.429 + case 0x00C014: cs_str = "TLS/ECDHE-RSA/AES256-CBC/SHA"; break; 1.430 + case 0x00C015: cs_str = "TLS/ECDH-anon/NULL/SHA"; break; 1.431 + case 0x00C016: cs_str = "TLS/ECDH-anon/RC4-128/SHA"; break; 1.432 + case 0x00C017: cs_str = "TLS/ECDH-anon/3DES-EDE-CBC/SHA"; break; 1.433 + case 0x00C018: cs_str = "TLS/ECDH-anon/AES128-CBC/SHA"; break; 1.434 + case 0x00C019: cs_str = "TLS/ECDH-anon/AES256-CBC/SHA"; break; 1.435 + 1.436 + case 0x00C023: cs_str = "TLS/ECDHE-ECDSA/AES128-CBC/SHA256"; break; 1.437 + case 0x00C024: cs_str = "TLS/ECDHE-ECDSA/AES256-CBC/SHA384"; break; 1.438 + case 0x00C025: cs_str = "TLS/ECDH-ECDSA/AES128-CBC/SHA256"; break; 1.439 + case 0x00C026: cs_str = "TLS/ECDH-ECDSA/AES256-CBC/SHA384"; break; 1.440 + case 0x00C027: cs_str = "TLS/ECDHE-RSA/AES128-CBC/SHA256"; break; 1.441 + case 0x00C028: cs_str = "TLS/ECDHE-RSA/AES256-CBC/SHA384"; break; 1.442 + case 0x00C029: cs_str = "TLS/ECDH-RSA/AES128-CBC/SHA256"; break; 1.443 + case 0x00C02A: cs_str = "TLS/ECDH-RSA/AES256-CBC/SHA384"; break; 1.444 + case 0x00C02B: cs_str = "TLS/ECDHE-ECDSA/AES128-GCM/SHA256"; break; 1.445 + case 0x00C02C: cs_str = "TLS/ECDHE-ECDSA/AES256-GCM/SHA384"; break; 1.446 + case 0x00C02F: cs_str = "TLS/ECDHE-RSA/AES128-GCM/SHA256"; break; 1.447 + 1.448 + case 0x00FEFF: cs_str = "SSL3/RSA-FIPS/3DESEDE-CBC/SHA"; break; 1.449 + case 0x00FEFE: cs_str = "SSL3/RSA-FIPS/DES-CBC/SHA"; break; 1.450 + case 0x00FFE1: cs_str = "SSL3/RSA-FIPS/DES56-CBC/SHA"; break; 1.451 + case 0x00FFE0: cs_str = "SSL3/RSA-FIPS/3DES192EDE-CBC/SHA";break; 1.452 + 1.453 + /* the string literal is broken up to avoid trigraphs */ 1.454 + default: cs_str = "????" "/????????" "/?????????" "/???"; break; 1.455 + } 1.456 + 1.457 + return cs_str; 1.458 +} 1.459 + 1.460 +const char * CompressionMethodString(int cm_int) 1.461 +{ 1.462 + char *cm_str; 1.463 + cm_str = NULL; 1.464 + switch (cm_int) { 1.465 + case 0: cm_str = "NULL"; break; 1.466 + case 1: cm_str = "DEFLATE"; break; /* RFC 3749 */ 1.467 + case 64: cm_str = "LZS"; break; /* RFC 3943 */ 1.468 + default: cm_str = "???"; break; 1.469 + } 1.470 + 1.471 + return cm_str; 1.472 +} 1.473 + 1.474 +const char * helloExtensionNameString(int ex_num) 1.475 +{ 1.476 + const char *ex_name = NULL; 1.477 + static char buf[10]; 1.478 + 1.479 + switch (ex_num) { 1.480 + case 0: ex_name = "server_name"; break; 1.481 + case 1: ex_name = "max_fragment_length"; break; 1.482 + case 2: ex_name = "client_certificate_url"; break; 1.483 + case 3: ex_name = "trusted_ca_keys"; break; 1.484 + case 4: ex_name = "truncated_hmac"; break; 1.485 + case 5: ex_name = "status_request"; break; 1.486 + case 10: ex_name = "elliptic_curves"; break; 1.487 + case 11: ex_name = "ec_point_formats"; break; 1.488 + case 13: ex_name = "signature_algorithms"; break; 1.489 + case 35: ex_name = "session_ticket"; break; 1.490 + case 0xff01: ex_name = "renegotiation_info"; break; 1.491 + default: sprintf(buf, "%d", ex_num); ex_name = (const char *)buf; break; 1.492 + } 1.493 + 1.494 + return ex_name; 1.495 +} 1.496 + 1.497 +static int isNULLmac(int cs_int) 1.498 +{ 1.499 + return (cs_int == TLS_NULL_WITH_NULL_NULL); 1.500 +} 1.501 + 1.502 +static int isNULLcipher(int cs_int) 1.503 +{ 1.504 + return ((cs_int == TLS_RSA_WITH_NULL_MD5) || 1.505 + (cs_int == TLS_RSA_WITH_NULL_SHA) || 1.506 + (cs_int == SSL_FORTEZZA_DMS_WITH_NULL_SHA) || 1.507 + (cs_int == TLS_ECDH_ECDSA_WITH_NULL_SHA) || 1.508 + (cs_int == TLS_ECDHE_ECDSA_WITH_NULL_SHA) || 1.509 + (cs_int == TLS_ECDH_RSA_WITH_NULL_SHA) || 1.510 + (cs_int == TLS_ECDHE_RSA_WITH_NULL_SHA)); 1.511 +} 1.512 + 1.513 +void partial_packet(int thispacket, int size, int needed) 1.514 +{ 1.515 + PR_fprintf(PR_STDOUT,"(%u bytes", thispacket); 1.516 + if (thispacket < needed) { 1.517 + PR_fprintf(PR_STDOUT,", making %u", size); 1.518 + } 1.519 + PR_fprintf(PR_STDOUT," of %u", needed); 1.520 + if (size > needed) { 1.521 + PR_fprintf(PR_STDOUT,", with %u left over", size - needed); 1.522 + } 1.523 + PR_fprintf(PR_STDOUT,")\n"); 1.524 +} 1.525 + 1.526 +char * get_time_string(void) 1.527 +{ 1.528 + char *cp; 1.529 + char *eol; 1.530 + time_t tt; 1.531 + 1.532 + time(&tt); 1.533 + cp = ctime(&tt); 1.534 + eol = strchr(cp, '\n'); 1.535 + if (eol) 1.536 + *eol = 0; 1.537 + return cp; 1.538 +} 1.539 + 1.540 +void print_sslv2(DataBufferList *s, unsigned char *recordBuf, unsigned int recordLen) 1.541 +{ 1.542 + ClientHelloV2 *chv2; 1.543 + ServerHelloV2 *shv2; 1.544 + unsigned char *pos; 1.545 + unsigned int p; 1.546 + unsigned int q; 1.547 + PRUint32 len; 1.548 + 1.549 + chv2 = (ClientHelloV2 *)recordBuf; 1.550 + shv2 = (ServerHelloV2 *)recordBuf; 1.551 + if (s->isEncrypted) { 1.552 + PR_fprintf(PR_STDOUT," [ssl2] Encrypted {...}\n"); 1.553 + return; 1.554 + } 1.555 + PR_fprintf(PR_STDOUT," [%s]", get_time_string() ); 1.556 + switch(chv2->type) { 1.557 + case 1: 1.558 + PR_fprintf(PR_STDOUT," [ssl2] ClientHelloV2 {\n"); 1.559 + PR_fprintf(PR_STDOUT," version = {0x%02x, 0x%02x}\n", 1.560 + (PRUint32)chv2->version[0],(PRUint32)chv2->version[1]); 1.561 + PR_fprintf(PR_STDOUT," cipher-specs-length = %d (0x%02x)\n", 1.562 + (PRUint32)(GET_SHORT((chv2->cslength))), 1.563 + (PRUint32)(GET_SHORT((chv2->cslength)))); 1.564 + PR_fprintf(PR_STDOUT," sid-length = %d (0x%02x)\n", 1.565 + (PRUint32)(GET_SHORT((chv2->sidlength))), 1.566 + (PRUint32)(GET_SHORT((chv2->sidlength)))); 1.567 + PR_fprintf(PR_STDOUT," challenge-length = %d (0x%02x)\n", 1.568 + (PRUint32)(GET_SHORT((chv2->rndlength))), 1.569 + (PRUint32)(GET_SHORT((chv2->rndlength)))); 1.570 + PR_fprintf(PR_STDOUT," cipher-suites = { \n"); 1.571 + for (p=0;p<GET_SHORT((chv2->cslength));p+=3) { 1.572 + PRUint32 cs_int = GET_24((&chv2->csuites[p])); 1.573 + const char *cs_str = V2CipherString(cs_int); 1.574 + 1.575 + PR_fprintf(PR_STDOUT," (0x%06x) %s\n", 1.576 + cs_int, cs_str); 1.577 + } 1.578 + q = p; 1.579 + PR_fprintf(PR_STDOUT," }\n"); 1.580 + if (chv2->sidlength) { 1.581 + PR_fprintf(PR_STDOUT," session-id = { "); 1.582 + for (p=0;p<GET_SHORT((chv2->sidlength));p+=2) { 1.583 + PR_fprintf(PR_STDOUT,"0x%04x ",(PRUint32)(GET_SHORT((&chv2->csuites[p+q])))); 1.584 + } 1.585 + } 1.586 + q += p; 1.587 + PR_fprintf(PR_STDOUT,"}\n"); 1.588 + if (chv2->rndlength) { 1.589 + PR_fprintf(PR_STDOUT," challenge = { "); 1.590 + for (p=0;p<GET_SHORT((chv2->rndlength));p+=2) { 1.591 + PR_fprintf(PR_STDOUT,"0x%04x ",(PRUint32)(GET_SHORT((&chv2->csuites[p+q])))); 1.592 + } 1.593 + PR_fprintf(PR_STDOUT,"}\n"); 1.594 + } 1.595 + PR_fprintf(PR_STDOUT,"}\n"); 1.596 + break; 1.597 + /* end of V2 CLientHello Parsing */ 1.598 + 1.599 + case 2: /* Client Master Key */ 1.600 + { 1.601 + const char *cs_str=NULL; 1.602 + PRUint32 cs_int=0; 1.603 + ClientMasterKeyV2 *cmkv2; 1.604 + cmkv2 = (ClientMasterKeyV2 *)chv2; 1.605 + isV2Session = 1; 1.606 + 1.607 + PR_fprintf(PR_STDOUT," [ssl2] ClientMasterKeyV2 { \n"); 1.608 + 1.609 + cs_int = GET_24(&cmkv2->cipherkind[0]); 1.610 + cs_str = V2CipherString(cs_int); 1.611 + PR_fprintf(PR_STDOUT," cipher-spec-chosen = (0x%06x) %s\n", 1.612 + cs_int, cs_str); 1.613 + 1.614 + PR_fprintf(PR_STDOUT," clear-portion = %d bits\n", 1.615 + 8*(PRUint32)(GET_SHORT((cmkv2->clearkey)))); 1.616 + 1.617 + PR_fprintf(PR_STDOUT," }\n"); 1.618 + clientstream.isEncrypted = 1; 1.619 + serverstream.isEncrypted = 1; 1.620 + } 1.621 + break; 1.622 + 1.623 + 1.624 + case 3: 1.625 + PR_fprintf(PR_STDOUT," [ssl2] Client Finished V2 {...}\n"); 1.626 + isV2Session = 1; 1.627 + break; 1.628 + 1.629 + 1.630 + case 4: /* V2 Server Hello */ 1.631 + isV2Session = 1; 1.632 + 1.633 + PR_fprintf(PR_STDOUT," [ssl2] ServerHelloV2 {\n"); 1.634 + PR_fprintf(PR_STDOUT," sid hit = {0x%02x}\n", 1.635 + (PRUintn)shv2->sidhit); 1.636 + PR_fprintf(PR_STDOUT," version = {0x%02x, 0x%02x}\n", 1.637 + (PRUint32)shv2->version[0],(PRUint32)shv2->version[1]); 1.638 + PR_fprintf(PR_STDOUT," cipher-specs-length = %d (0x%02x)\n", 1.639 + (PRUint32)(GET_SHORT((shv2->cslength))), 1.640 + (PRUint32)(GET_SHORT((shv2->cslength)))); 1.641 + PR_fprintf(PR_STDOUT," sid-length = %d (0x%02x)\n", 1.642 + (PRUint32)(GET_SHORT((shv2->cidlength))), 1.643 + (PRUint32)(GET_SHORT((shv2->cidlength)))); 1.644 + 1.645 + pos = (unsigned char *)shv2; 1.646 + pos += 2; /* skip length header */ 1.647 + pos += 11; /* position pointer to Certificate data area */ 1.648 + q = GET_SHORT(&shv2->certlength); 1.649 + if (q >recordLen) { 1.650 + goto eosh; 1.651 + } 1.652 + pos += q; /* skip certificate */ 1.653 + 1.654 + PR_fprintf(PR_STDOUT," cipher-suites = { "); 1.655 + len = GET_SHORT((shv2->cslength)); 1.656 + for (p = 0; p < len; p += 3) { 1.657 + PRUint32 cs_int = GET_24((pos+p)); 1.658 + const char *cs_str = V2CipherString(cs_int); 1.659 + PR_fprintf(PR_STDOUT,"\n "); 1.660 + PR_fprintf(PR_STDOUT,"(0x%06x) %s", cs_int, cs_str); 1.661 + } 1.662 + pos += len; 1.663 + PR_fprintf(PR_STDOUT," }\n"); /* End of cipher suites */ 1.664 + len = (PRUint32)GET_SHORT((shv2->cidlength)); 1.665 + if (len) { 1.666 + PR_fprintf(PR_STDOUT," connection-id = { "); 1.667 + for (p = 0; p < len; p += 2) { 1.668 + PR_fprintf(PR_STDOUT,"0x%04x ", (PRUint32)(GET_SHORT((pos + p)))); 1.669 + } 1.670 + PR_fprintf(PR_STDOUT," }\n"); /* End of connection id */ 1.671 + } 1.672 +eosh: 1.673 + PR_fprintf(PR_STDOUT,"\n }\n"); /* end of ServerHelloV2 */ 1.674 + if (shv2->sidhit) { 1.675 + clientstream.isEncrypted = 1; 1.676 + serverstream.isEncrypted = 1; 1.677 + } 1.678 + break; 1.679 + 1.680 + case 5: 1.681 + PR_fprintf(PR_STDOUT," [ssl2] Server Verify V2 {...}\n"); 1.682 + isV2Session = 1; 1.683 + break; 1.684 + 1.685 + case 6: 1.686 + PR_fprintf(PR_STDOUT," [ssl2] Server Finished V2 {...}\n"); 1.687 + isV2Session = 1; 1.688 + break; 1.689 + 1.690 + case 7: 1.691 + PR_fprintf(PR_STDOUT," [ssl2] Request Certificate V2 {...}\n"); 1.692 + isV2Session = 1; 1.693 + break; 1.694 + 1.695 + case 8: 1.696 + PR_fprintf(PR_STDOUT," [ssl2] Client Certificate V2 {...}\n"); 1.697 + isV2Session = 1; 1.698 + break; 1.699 + 1.700 + default: 1.701 + PR_fprintf(PR_STDOUT," [ssl2] UnknownType 0x%02x {...}\n", 1.702 + (PRUint32)chv2->type); 1.703 + break; 1.704 + } 1.705 +} 1.706 + 1.707 + 1.708 + 1.709 +unsigned int print_hello_extension(unsigned char * hsdata, 1.710 + unsigned int length, 1.711 + unsigned int pos) 1.712 +{ 1.713 + /* pretty print extensions, if any */ 1.714 + if (pos < length) { 1.715 + int exListLen = GET_SHORT((hsdata+pos)); pos += 2; 1.716 + PR_fprintf(PR_STDOUT, 1.717 + " extensions[%d] = {\n", exListLen); 1.718 + while (exListLen > 0 && pos < length) { 1.719 + int exLen; 1.720 + int exType = GET_SHORT((hsdata+pos)); pos += 2; 1.721 + exLen = GET_SHORT((hsdata+pos)); pos += 2; 1.722 + /* dump the extension */ 1.723 + PR_fprintf(PR_STDOUT, 1.724 + " extension type %s, length [%d]", 1.725 + helloExtensionNameString(exType), exLen); 1.726 + if (exLen > 0) { 1.727 + PR_fprintf(PR_STDOUT, " = {\n"); 1.728 + print_hex(exLen, hsdata + pos); 1.729 + PR_fprintf(PR_STDOUT, " }\n"); 1.730 + } else { 1.731 + PR_fprintf(PR_STDOUT, "\n"); 1.732 + } 1.733 + pos += exLen; 1.734 + exListLen -= 2 + exLen; 1.735 + } 1.736 + PR_fprintf(PR_STDOUT," }\n"); 1.737 + } 1.738 + return pos; 1.739 +} 1.740 + 1.741 +/* 1.742 + * Note this must match (exactly) the enumeration ocspResponseStatus. 1.743 + */ 1.744 +static char *responseStatusNames[] = { 1.745 + "successful (Response has valid confirmations)", 1.746 + "malformedRequest (Illegal confirmation request)", 1.747 + "internalError (Internal error in issuer)", 1.748 + "tryLater (Try again later)", 1.749 + "unused ((4) is not used)", 1.750 + "sigRequired (Must sign the request)", 1.751 + "unauthorized (Request unauthorized)", 1.752 +}; 1.753 + 1.754 +static void 1.755 +print_ocsp_cert_id (FILE *out_file, CERTOCSPCertID *cert_id, int level) 1.756 +{ 1.757 + SECU_Indent (out_file, level); 1.758 + fprintf (out_file, "Cert ID:\n"); 1.759 + level++; 1.760 +/* 1.761 + SECU_PrintAlgorithmID (out_file, &(cert_id->hashAlgorithm), 1.762 + "Hash Algorithm", level); 1.763 + SECU_PrintAsHex (out_file, &(cert_id->issuerNameHash), 1.764 + "Issuer Name Hash", level); 1.765 + SECU_PrintAsHex (out_file, &(cert_id->issuerKeyHash), 1.766 + "Issuer Key Hash", level); 1.767 +*/ 1.768 + SECU_PrintInteger (out_file, &(cert_id->serialNumber), 1.769 + "Serial Number", level); 1.770 + /* XXX lookup the cert; if found, print something nice (nickname?) */ 1.771 +} 1.772 + 1.773 +static void 1.774 +print_ocsp_version (FILE *out_file, SECItem *version, int level) 1.775 +{ 1.776 + if (version->len > 0) { 1.777 + SECU_PrintInteger (out_file, version, "Version", level); 1.778 + } else { 1.779 + SECU_Indent (out_file, level); 1.780 + fprintf (out_file, "Version: DEFAULT\n"); 1.781 + } 1.782 +} 1.783 + 1.784 +static void 1.785 +print_responder_id (FILE *out_file, ocspResponderID *responderID, int level) 1.786 +{ 1.787 + SECU_Indent (out_file, level); 1.788 + fprintf (out_file, "Responder ID "); 1.789 + 1.790 + switch (responderID->responderIDType) { 1.791 + case ocspResponderID_byName: 1.792 + fprintf (out_file, "(byName):\n"); 1.793 + SECU_PrintName (out_file, &(responderID->responderIDValue.name), 1.794 + "Name", level + 1); 1.795 + break; 1.796 + case ocspResponderID_byKey: 1.797 + fprintf (out_file, "(byKey):\n"); 1.798 + SECU_PrintAsHex (out_file, &(responderID->responderIDValue.keyHash), 1.799 + "Key Hash", level + 1); 1.800 + break; 1.801 + default: 1.802 + fprintf (out_file, "Unrecognized Responder ID Type\n"); 1.803 + break; 1.804 + } 1.805 +} 1.806 + 1.807 +static void 1.808 +print_ocsp_extensions (FILE *out_file, CERTCertExtension **extensions, 1.809 + char *msg, int level) 1.810 +{ 1.811 + if (extensions) { 1.812 + SECU_PrintExtensions (out_file, extensions, msg, level); 1.813 + } else { 1.814 + SECU_Indent (out_file, level); 1.815 + fprintf (out_file, "No %s\n", msg); 1.816 + } 1.817 +} 1.818 + 1.819 +static void 1.820 +print_revoked_info (FILE *out_file, ocspRevokedInfo *revoked_info, int level) 1.821 +{ 1.822 + SECU_PrintGeneralizedTime (out_file, &(revoked_info->revocationTime), 1.823 + "Revocation Time", level); 1.824 + 1.825 + if (revoked_info->revocationReason != NULL) { 1.826 + SECU_PrintAsHex (out_file, revoked_info->revocationReason, 1.827 + "Revocation Reason", level); 1.828 + } else { 1.829 + SECU_Indent (out_file, level); 1.830 + fprintf (out_file, "No Revocation Reason.\n"); 1.831 + } 1.832 +} 1.833 + 1.834 +static void 1.835 +print_cert_status (FILE *out_file, ocspCertStatus *status, int level) 1.836 +{ 1.837 + SECU_Indent (out_file, level); 1.838 + fprintf (out_file, "Status: "); 1.839 + 1.840 + switch (status->certStatusType) { 1.841 + case ocspCertStatus_good: 1.842 + fprintf (out_file, "Cert is good.\n"); 1.843 + break; 1.844 + case ocspCertStatus_revoked: 1.845 + fprintf (out_file, "Cert has been revoked.\n"); 1.846 + print_revoked_info (out_file, status->certStatusInfo.revokedInfo, 1.847 + level + 1); 1.848 + break; 1.849 + case ocspCertStatus_unknown: 1.850 + fprintf (out_file, "Cert is unknown to responder.\n"); 1.851 + break; 1.852 + default: 1.853 + fprintf (out_file, "Unrecognized status.\n"); 1.854 + break; 1.855 + } 1.856 +} 1.857 + 1.858 +static void 1.859 +print_single_response (FILE *out_file, CERTOCSPSingleResponse *single, 1.860 + int level) 1.861 +{ 1.862 + print_ocsp_cert_id (out_file, single->certID, level); 1.863 + 1.864 + print_cert_status (out_file, single->certStatus, level); 1.865 + 1.866 + SECU_PrintGeneralizedTime (out_file, &(single->thisUpdate), 1.867 + "This Update", level); 1.868 + 1.869 + if (single->nextUpdate != NULL) { 1.870 + SECU_PrintGeneralizedTime (out_file, single->nextUpdate, 1.871 + "Next Update", level); 1.872 + } else { 1.873 + SECU_Indent (out_file, level); 1.874 + fprintf (out_file, "No Next Update\n"); 1.875 + } 1.876 + 1.877 + print_ocsp_extensions (out_file, single->singleExtensions, 1.878 + "Single Response Extensions", level); 1.879 +} 1.880 + 1.881 +static void 1.882 +print_response_data (FILE *out_file, ocspResponseData *responseData, int level) 1.883 +{ 1.884 + SECU_Indent (out_file, level); 1.885 + fprintf (out_file, "Response Data:\n"); 1.886 + level++; 1.887 + 1.888 + print_ocsp_version (out_file, &(responseData->version), level); 1.889 + 1.890 + print_responder_id (out_file, responseData->responderID, level); 1.891 + 1.892 + SECU_PrintGeneralizedTime (out_file, &(responseData->producedAt), 1.893 + "Produced At", level); 1.894 + 1.895 + if (responseData->responses != NULL) { 1.896 + int i; 1.897 + 1.898 + for (i = 0; responseData->responses[i] != NULL; i++) { 1.899 + SECU_Indent (out_file, level); 1.900 + fprintf (out_file, "Response %d:\n", i); 1.901 + print_single_response (out_file, responseData->responses[i], 1.902 + level + 1); 1.903 + } 1.904 + } else { 1.905 + fprintf (out_file, "Response list is empty.\n"); 1.906 + } 1.907 + 1.908 + print_ocsp_extensions (out_file, responseData->responseExtensions, 1.909 + "Response Extensions", level); 1.910 +} 1.911 + 1.912 +static void 1.913 +print_basic_response (FILE *out_file, ocspBasicOCSPResponse *basic, int level) 1.914 +{ 1.915 + SECU_Indent (out_file, level); 1.916 + fprintf (out_file, "Basic OCSP Response:\n"); 1.917 + level++; 1.918 + 1.919 + print_response_data (out_file, basic->tbsResponseData, level); 1.920 +} 1.921 + 1.922 +static void 1.923 +print_status_response(SECItem *data) 1.924 +{ 1.925 + int level = 2; 1.926 + CERTOCSPResponse *response; 1.927 + response = CERT_DecodeOCSPResponse (data); 1.928 + if (!response) { 1.929 + SECU_Indent (stdout, level); 1.930 + fprintf(stdout,"unable to decode certificate_status\n"); 1.931 + return; 1.932 + } 1.933 + 1.934 + SECU_Indent (stdout, level); 1.935 + if (response->statusValue >= ocspResponse_min && 1.936 + response->statusValue <= ocspResponse_max) { 1.937 + fprintf (stdout, "Response Status: %s\n", 1.938 + responseStatusNames[response->statusValue]); 1.939 + } else { 1.940 + fprintf (stdout, 1.941 + "Response Status: other (Status value %d out of defined range)\n", 1.942 + (int)response->statusValue); 1.943 + } 1.944 + 1.945 + if (response->statusValue == ocspResponse_successful) { 1.946 + ocspResponseBytes *responseBytes = response->responseBytes; 1.947 + PORT_Assert (responseBytes != NULL); 1.948 + 1.949 + level++; 1.950 + SECU_PrintObjectID (stdout, &(responseBytes->responseType), 1.951 + "Response Type", level); 1.952 + switch (response->responseBytes->responseTypeTag) { 1.953 + case SEC_OID_PKIX_OCSP_BASIC_RESPONSE: 1.954 + print_basic_response (stdout, 1.955 + responseBytes->decodedResponse.basic, 1.956 + level); 1.957 + break; 1.958 + default: 1.959 + SECU_Indent (stdout, level); 1.960 + fprintf (stdout, "Unknown response syntax\n"); 1.961 + break; 1.962 + } 1.963 + } else { 1.964 + SECU_Indent (stdout, level); 1.965 + fprintf (stdout, "Unsuccessful response, no more information.\n"); 1.966 + } 1.967 + 1.968 + CERT_DestroyOCSPResponse (response); 1.969 +} 1.970 + 1.971 +/* In the case of renegotiation, handshakes that occur in an already MAC'ed 1.972 + * channel, by the time of this call, the caller has already removed the MAC 1.973 + * from input recordLen. The only MAC'ed record that will get here with its 1.974 + * MAC intact (not removed) is the first Finished message on the connection. 1.975 + */ 1.976 +void print_ssl3_handshake(unsigned char *recordBuf, 1.977 + unsigned int recordLen, 1.978 + SSLRecord * sr, 1.979 + DataBufferList *s) 1.980 +{ 1.981 + struct sslhandshake sslh; 1.982 + unsigned char * hsdata; 1.983 + int offset=0; 1.984 + 1.985 + PR_fprintf(PR_STDOUT," handshake {\n"); 1.986 + 1.987 + if (s->msgBufOffset && s->msgBuf) { 1.988 + /* append recordBuf to msgBuf, then use msgBuf */ 1.989 + if (s->msgBufOffset + recordLen > s->msgBufSize) { 1.990 + int newSize = s->msgBufOffset + recordLen; 1.991 + unsigned char * newBuf = PORT_Realloc(s->msgBuf, newSize); 1.992 + if (!newBuf) { 1.993 + PR_ASSERT(newBuf); 1.994 + showErr( "Realloc failed"); 1.995 + exit(10); 1.996 + } 1.997 + s->msgBuf = newBuf; 1.998 + s->msgBufSize = newSize; 1.999 + } 1.1000 + memcpy(s->msgBuf + s->msgBufOffset, recordBuf, recordLen); 1.1001 + s->msgBufOffset += recordLen; 1.1002 + recordLen = s->msgBufOffset; 1.1003 + recordBuf = s->msgBuf; 1.1004 + } 1.1005 + while (offset + 4 <= recordLen) { 1.1006 + sslh.type = recordBuf[offset]; 1.1007 + sslh.length = GET_24(recordBuf+offset+1); 1.1008 + if (offset + 4 + sslh.length > recordLen) 1.1009 + break; 1.1010 + /* finally have a complete message */ 1.1011 + if (sslhexparse) 1.1012 + print_hex(4,recordBuf+offset); 1.1013 + 1.1014 + hsdata = &recordBuf[offset+4]; 1.1015 + 1.1016 + PR_fprintf(PR_STDOUT," type = %d (",sslh.type); 1.1017 + switch(sslh.type) { 1.1018 + case 0: PR_FPUTS("hello_request)\n" ); break; 1.1019 + case 1: PR_FPUTS("client_hello)\n" ); break; 1.1020 + case 2: PR_FPUTS("server_hello)\n" ); break; 1.1021 + case 4: PR_FPUTS("new_session_ticket)\n" ); break; 1.1022 + case 11: PR_FPUTS("certificate)\n" ); break; 1.1023 + case 12: PR_FPUTS("server_key_exchange)\n" ); break; 1.1024 + case 13: PR_FPUTS("certificate_request)\n" ); break; 1.1025 + case 14: PR_FPUTS("server_hello_done)\n" ); break; 1.1026 + case 15: PR_FPUTS("certificate_verify)\n" ); break; 1.1027 + case 16: PR_FPUTS("client_key_exchange)\n" ); break; 1.1028 + case 20: PR_FPUTS("finished)\n" ); break; 1.1029 + case 22: PR_FPUTS("certificate_status)\n" ); break; 1.1030 + default: PR_FPUTS("unknown)\n" ); break; 1.1031 + } 1.1032 + 1.1033 + PR_fprintf(PR_STDOUT," length = %d (0x%06x)\n",sslh.length,sslh.length); 1.1034 + switch (sslh.type) { 1.1035 + 1.1036 + case 0: /* hello_request */ /* not much to show here. */ break; 1.1037 + 1.1038 + case 1: /* client hello */ 1.1039 + switch (sr->ver_maj) { 1.1040 + case 3: /* ssl version 3 */ 1.1041 + { 1.1042 + unsigned int pos; 1.1043 + int w; 1.1044 + 1.1045 + PR_fprintf(PR_STDOUT," ClientHelloV3 {\n"); 1.1046 + PR_fprintf(PR_STDOUT," client_version = {%d, %d}\n", 1.1047 + (PRUint8)hsdata[0],(PRUint8)hsdata[1]); 1.1048 + PR_fprintf(PR_STDOUT," random = {...}\n"); 1.1049 + if (sslhexparse) print_hex(32,&hsdata[2]); 1.1050 + 1.1051 + /* pretty print Session ID */ 1.1052 + { 1.1053 + int sidlength = (int)hsdata[2+32]; 1.1054 + PR_fprintf(PR_STDOUT," session ID = {\n"); 1.1055 + PR_fprintf(PR_STDOUT," length = %d\n",sidlength); 1.1056 + PR_fprintf(PR_STDOUT," contents = {...}\n"); 1.1057 + if (sslhexparse) print_hex(sidlength,&hsdata[2+32+1]); 1.1058 + PR_fprintf(PR_STDOUT," }\n"); 1.1059 + pos = 2+32+1+sidlength; 1.1060 + } 1.1061 + 1.1062 + /* pretty print cipher suites */ 1.1063 + { 1.1064 + int csuitelength = GET_SHORT((hsdata+pos)); 1.1065 + PR_fprintf(PR_STDOUT," cipher_suites[%d] = {\n", 1.1066 + csuitelength/2); 1.1067 + if (csuitelength % 2) { 1.1068 + PR_fprintf(PR_STDOUT, 1.1069 + "*error in protocol - csuitelength shouldn't be odd*\n"); 1.1070 + } 1.1071 + for (w=0; w<csuitelength; w+=2) { 1.1072 + PRUint32 cs_int = GET_SHORT((hsdata+pos+2+w)); 1.1073 + const char *cs_str = V2CipherString(cs_int); 1.1074 + PR_fprintf(PR_STDOUT, 1.1075 + " (0x%04x) %s\n", cs_int, cs_str); 1.1076 + } 1.1077 + pos += 2 + csuitelength; 1.1078 + PR_fprintf(PR_STDOUT," }\n"); 1.1079 + } 1.1080 + 1.1081 + /* pretty print compression methods */ 1.1082 + { 1.1083 + int complength = hsdata[pos]; 1.1084 + PR_fprintf(PR_STDOUT," compression[%d] = {\n", 1.1085 + complength); 1.1086 + for (w=0; w < complength; w++) { 1.1087 + PRUint32 cm_int = hsdata[pos+1+w]; 1.1088 + const char *cm_str = CompressionMethodString(cm_int); 1.1089 + PR_fprintf(PR_STDOUT, 1.1090 + " (%02x) %s\n", cm_int, cm_str); 1.1091 + } 1.1092 + pos += 1 + complength; 1.1093 + PR_fprintf(PR_STDOUT," }\n"); 1.1094 + } 1.1095 + 1.1096 + /* pretty print extensions, if any */ 1.1097 + pos = print_hello_extension(hsdata, sslh.length, pos); 1.1098 + 1.1099 + PR_fprintf(PR_STDOUT," }\n"); 1.1100 + } /* end of ssl version 3 */ 1.1101 + break; 1.1102 + default: 1.1103 + PR_fprintf(PR_STDOUT," UNDEFINED VERSION %d.%d {...}\n", 1.1104 + sr->ver_maj, sr->ver_min ); 1.1105 + if (sslhexparse) print_hex(sslh.length, hsdata); 1.1106 + break; 1.1107 + } /* end of switch sr->ver_maj */ 1.1108 + break; 1.1109 + 1.1110 + case 2: /* server hello */ 1.1111 + { 1.1112 + unsigned int sidlength, pos; 1.1113 + 1.1114 + PR_fprintf(PR_STDOUT," ServerHello {\n"); 1.1115 + 1.1116 + PR_fprintf(PR_STDOUT," server_version = {%d, %d}\n", 1.1117 + (PRUint8)hsdata[0],(PRUint8)hsdata[1]); 1.1118 + PR_fprintf(PR_STDOUT," random = {...}\n"); 1.1119 + if (sslhexparse) print_hex(32,&hsdata[2]); 1.1120 + PR_fprintf(PR_STDOUT," session ID = {\n"); 1.1121 + sidlength = (int)hsdata[2+32]; 1.1122 + PR_fprintf(PR_STDOUT," length = %d\n",sidlength); 1.1123 + PR_fprintf(PR_STDOUT," contents = {...}\n"); 1.1124 + if (sslhexparse) print_hex(sidlength,&hsdata[2+32+1]); 1.1125 + PR_fprintf(PR_STDOUT," }\n"); 1.1126 + pos = 2+32+1+sidlength; 1.1127 + 1.1128 + /* pretty print chosen cipher suite */ 1.1129 + { 1.1130 + PRUint32 cs_int = GET_SHORT((hsdata+pos)); 1.1131 + const char *cs_str = V2CipherString(cs_int); 1.1132 + PR_fprintf(PR_STDOUT," cipher_suite = (0x%04x) %s\n", 1.1133 + cs_int, cs_str); 1.1134 + currentcipher = cs_int; 1.1135 + pos += 2; 1.1136 + } 1.1137 + /* pretty print chosen compression method */ 1.1138 + { 1.1139 + PRUint32 cm_int = hsdata[pos++]; 1.1140 + const char *cm_str = CompressionMethodString(cm_int); 1.1141 + PR_fprintf(PR_STDOUT," compression method = (%02x) %s\n", 1.1142 + cm_int, cm_str); 1.1143 + } 1.1144 + 1.1145 + /* pretty print extensions, if any */ 1.1146 + pos = print_hello_extension(hsdata, sslh.length, pos); 1.1147 + 1.1148 + PR_fprintf(PR_STDOUT," }\n"); 1.1149 + } 1.1150 + break; 1.1151 + 1.1152 + case 4: /* new session ticket */ 1.1153 + { 1.1154 + PRUint32 lifetimehint; 1.1155 + PRUint16 ticketlength; 1.1156 + char lifetime[32]; 1.1157 + lifetimehint = GET_32(hsdata); 1.1158 + if (lifetimehint) { 1.1159 + PRExplodedTime et; 1.1160 + PRTime t = lifetimehint; 1.1161 + t *= PR_USEC_PER_SEC; 1.1162 + PR_ExplodeTime(t, PR_GMTParameters, &et); 1.1163 + /* use HTTP Cookie header's date format */ 1.1164 + PR_FormatTimeUSEnglish(lifetime, sizeof lifetime, 1.1165 + "%a, %d-%b-%Y %H:%M:%S GMT", &et); 1.1166 + } else { 1.1167 + /* 0 means the lifetime of the ticket is unspecified */ 1.1168 + strcpy(lifetime, "unspecified"); 1.1169 + } 1.1170 + ticketlength = GET_SHORT((hsdata+4)); 1.1171 + PR_fprintf(PR_STDOUT," NewSessionTicket {\n"); 1.1172 + PR_fprintf(PR_STDOUT," ticket_lifetime_hint = %s\n", 1.1173 + lifetime); 1.1174 + PR_fprintf(PR_STDOUT," ticket = {\n"); 1.1175 + PR_fprintf(PR_STDOUT," length = %d\n",ticketlength); 1.1176 + PR_fprintf(PR_STDOUT," contents = {...}\n"); 1.1177 + if (sslhexparse) print_hex(ticketlength,&hsdata[4+2]); 1.1178 + PR_fprintf(PR_STDOUT," }\n"); 1.1179 + PR_fprintf(PR_STDOUT," }\n"); 1.1180 + } 1.1181 + break; 1.1182 + 1.1183 + case 11: /* certificate */ 1.1184 + { 1.1185 + PRFileDesc *cfd; 1.1186 + int pos; 1.1187 + int certslength; 1.1188 + int certlength; 1.1189 + int certbytesread = 0; 1.1190 + static int certFileNumber; 1.1191 + char certFileName[20]; 1.1192 + 1.1193 + PR_fprintf(PR_STDOUT," CertificateChain {\n"); 1.1194 + certslength = GET_24(hsdata); 1.1195 + PR_fprintf(PR_STDOUT," chainlength = %d (0x%04x)\n", 1.1196 + certslength,certslength); 1.1197 + pos = 3; 1.1198 + while (certbytesread < certslength) { 1.1199 + certlength = GET_24((hsdata+pos)); 1.1200 + pos += 3; 1.1201 + PR_fprintf(PR_STDOUT," Certificate {\n"); 1.1202 + PR_fprintf(PR_STDOUT," size = %d (0x%04x)\n", 1.1203 + certlength,certlength); 1.1204 + certbytesread += certlength+3; 1.1205 + if (certbytesread <= certslength) { 1.1206 + PR_snprintf(certFileName, sizeof certFileName, "cert.%03d", 1.1207 + ++certFileNumber); 1.1208 + cfd = PR_Open(certFileName, PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE, 1.1209 + 0664); 1.1210 + if (!cfd) { 1.1211 + PR_fprintf(PR_STDOUT, 1.1212 + " data = { couldn't save file '%s' }\n", 1.1213 + certFileName); 1.1214 + } else { 1.1215 + PR_Write(cfd, (hsdata+pos), certlength); 1.1216 + PR_fprintf(PR_STDOUT, 1.1217 + " data = { saved in file '%s' }\n", 1.1218 + certFileName); 1.1219 + PR_Close(cfd); 1.1220 + } 1.1221 + } 1.1222 + 1.1223 + PR_fprintf(PR_STDOUT," }\n"); 1.1224 + pos += certlength; 1.1225 + } 1.1226 + PR_fprintf(PR_STDOUT," }\n"); 1.1227 + } 1.1228 + break; 1.1229 + 1.1230 + case 12: /* server_key_exchange */ 1.1231 + if (sslhexparse) print_hex(sslh.length, hsdata); 1.1232 + break; 1.1233 + 1.1234 + case 13: /* certificate request */ 1.1235 + { 1.1236 + unsigned int pos = 0; 1.1237 + int w, reqLength; 1.1238 + 1.1239 + PR_fprintf(PR_STDOUT," CertificateRequest {\n"); 1.1240 + 1.1241 + /* pretty print requested certificate types */ 1.1242 + reqLength = hsdata[pos]; 1.1243 + PR_fprintf(PR_STDOUT," certificate types[%d] = {", 1.1244 + reqLength); 1.1245 + for (w=0; w < reqLength; w++) { 1.1246 + PR_fprintf(PR_STDOUT, " %02x", hsdata[pos+1+w]); 1.1247 + } 1.1248 + pos += 1 + reqLength; 1.1249 + PR_fprintf(PR_STDOUT," }\n"); 1.1250 + 1.1251 + /* pretty print CA names, if any */ 1.1252 + if (pos < sslh.length) { 1.1253 + int exListLen = GET_SHORT((hsdata+pos)); pos += 2; 1.1254 + PR_fprintf(PR_STDOUT, 1.1255 + " certificate_authorities[%d] = {\n", 1.1256 + exListLen); 1.1257 + while (exListLen > 0 && pos < sslh.length) { 1.1258 + char * ca_name; 1.1259 + SECItem it; 1.1260 + int dnLen = GET_SHORT((hsdata+pos)); pos += 2; 1.1261 + 1.1262 + /* dump the CA name */ 1.1263 + it.type = siBuffer; 1.1264 + it.data = hsdata + pos; 1.1265 + it.len = dnLen; 1.1266 + ca_name = CERT_DerNameToAscii(&it); 1.1267 + if (ca_name) { 1.1268 + PR_fprintf(PR_STDOUT," %s\n", ca_name); 1.1269 + PORT_Free(ca_name); 1.1270 + } else { 1.1271 + PR_fprintf(PR_STDOUT, 1.1272 + " distinguished name [%d]", dnLen); 1.1273 + if (dnLen > 0 && sslhexparse) { 1.1274 + PR_fprintf(PR_STDOUT, " = {\n"); 1.1275 + print_hex(dnLen, hsdata + pos); 1.1276 + PR_fprintf(PR_STDOUT, " }\n"); 1.1277 + } else { 1.1278 + PR_fprintf(PR_STDOUT, "\n"); 1.1279 + } 1.1280 + } 1.1281 + pos += dnLen; 1.1282 + exListLen -= 2 + dnLen; 1.1283 + } 1.1284 + PR_fprintf(PR_STDOUT," }\n"); 1.1285 + } 1.1286 + 1.1287 + PR_fprintf(PR_STDOUT," }\n"); 1.1288 + } 1.1289 + break; 1.1290 + 1.1291 + case 14: /* server_hello_done */ /* not much to show here. */ break; 1.1292 + 1.1293 + case 15: /* certificate_verify */ 1.1294 + if (sslhexparse) print_hex(sslh.length, hsdata); 1.1295 + break; 1.1296 + 1.1297 + case 16: /* client key exchange */ 1.1298 + { 1.1299 + PR_fprintf(PR_STDOUT," ClientKeyExchange {\n"); 1.1300 + PR_fprintf(PR_STDOUT," message = {...}\n"); 1.1301 + PR_fprintf(PR_STDOUT," }\n"); 1.1302 + } 1.1303 + break; 1.1304 + 1.1305 + case 20: /* finished */ 1.1306 + PR_fprintf(PR_STDOUT," Finished {\n"); 1.1307 + PR_fprintf(PR_STDOUT," verify_data = {...}\n"); 1.1308 + if (sslhexparse) print_hex(sslh.length, hsdata); 1.1309 + PR_fprintf(PR_STDOUT," }\n"); 1.1310 + 1.1311 + if (!isNULLmac(currentcipher) && !s->hMACsize) { 1.1312 + /* To calculate the size of MAC, we subtract the number of known 1.1313 + * bytes of message from the number of remaining bytes in the 1.1314 + * record. This assumes that this is the first record on the 1.1315 + * connection to have a MAC, and that the sender has not put another 1.1316 + * message after the finished message in the handshake record. 1.1317 + * This is only correct for the first transition from unMACed to 1.1318 + * MACed. If the connection switches from one cipher suite to 1.1319 + * another one with a different MAC, this logic will not track that 1.1320 + * change correctly. 1.1321 + */ 1.1322 + s->hMACsize = recordLen - (sslh.length + 4); 1.1323 + sslh.length += s->hMACsize; /* skip over the MAC data */ 1.1324 + } 1.1325 + break; 1.1326 + 1.1327 + case 22: /* certificate_status */ 1.1328 + { 1.1329 + SECItem data; 1.1330 + PRFileDesc *ofd; 1.1331 + static int ocspFileNumber; 1.1332 + char ocspFileName[20]; 1.1333 + 1.1334 + /* skip 4 bytes with handshake numbers, as in ssl3_HandleCertificateStatus */ 1.1335 + data.type = siBuffer; 1.1336 + data.data = hsdata + 4; 1.1337 + data.len = sslh.length - 4; 1.1338 + print_status_response(&data); 1.1339 + 1.1340 + PR_snprintf(ocspFileName, sizeof ocspFileName, "ocsp.%03d", 1.1341 + ++ocspFileNumber); 1.1342 + ofd = PR_Open(ocspFileName, PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE, 1.1343 + 0664); 1.1344 + if (!ofd) { 1.1345 + PR_fprintf(PR_STDOUT, 1.1346 + " data = { couldn't save file '%s' }\n", 1.1347 + ocspFileName); 1.1348 + } else { 1.1349 + PR_Write(ofd, data.data, data.len); 1.1350 + PR_fprintf(PR_STDOUT, 1.1351 + " data = { saved in file '%s' }\n", 1.1352 + ocspFileName); 1.1353 + PR_Close(ofd); 1.1354 + } 1.1355 + } 1.1356 + break; 1.1357 + 1.1358 + default: 1.1359 + { 1.1360 + PR_fprintf(PR_STDOUT," UNKNOWN MESSAGE TYPE %d [%d] {\n", 1.1361 + sslh.type, sslh.length); 1.1362 + if (sslhexparse) print_hex(sslh.length, hsdata); 1.1363 + PR_fprintf(PR_STDOUT," }\n"); 1.1364 + 1.1365 + } 1.1366 + } /* end of switch sslh.type */ 1.1367 + offset += sslh.length + 4; 1.1368 + } /* while */ 1.1369 + if (offset < recordLen) { /* stuff left over */ 1.1370 + int newMsgLen = recordLen - offset; 1.1371 + if (!s->msgBuf) { 1.1372 + s->msgBuf = PORT_Alloc(newMsgLen); 1.1373 + if (!s->msgBuf) { 1.1374 + PR_ASSERT(s->msgBuf); 1.1375 + showErr( "Malloc failed"); 1.1376 + exit(11); 1.1377 + } 1.1378 + s->msgBufSize = newMsgLen; 1.1379 + memcpy(s->msgBuf, recordBuf + offset, newMsgLen); 1.1380 + } else if (newMsgLen > s->msgBufSize) { 1.1381 + unsigned char * newBuf = PORT_Realloc(s->msgBuf, newMsgLen); 1.1382 + if (!newBuf) { 1.1383 + PR_ASSERT(newBuf); 1.1384 + showErr( "Realloc failed"); 1.1385 + exit(12); 1.1386 + } 1.1387 + s->msgBuf = newBuf; 1.1388 + s->msgBufSize = newMsgLen; 1.1389 + } else if (offset || s->msgBuf != recordBuf) { 1.1390 + memmove(s->msgBuf, recordBuf + offset, newMsgLen); 1.1391 + } 1.1392 + s->msgBufOffset = newMsgLen; 1.1393 + PR_fprintf(PR_STDOUT," [incomplete handshake message]\n"); 1.1394 + } else { 1.1395 + s->msgBufOffset = 0; 1.1396 + } 1.1397 + PR_fprintf(PR_STDOUT," }\n"); 1.1398 +} 1.1399 + 1.1400 + 1.1401 +void print_ssl(DataBufferList *s, int length, unsigned char *buffer) 1.1402 +{ 1.1403 + /* -------------------------------------------------------- */ 1.1404 + /* first, create a new buffer object for this piece of data. */ 1.1405 + 1.1406 + DataBuffer *db; 1.1407 + 1.1408 + if (s->size == 0 && length > 0 && buffer[0] >= 32 && buffer[0] < 128) { 1.1409 + /* Not an SSL record, treat entire buffer as plaintext */ 1.1410 + PR_Write(PR_STDOUT,buffer,length); 1.1411 + return; 1.1412 + } 1.1413 + 1.1414 + check_integrity(s); 1.1415 + 1.1416 + db = PR_NEW(struct _DataBuffer); 1.1417 + 1.1418 + db->buffer = (unsigned char*)PORT_Alloc(length); 1.1419 + db->length = length; 1.1420 + db->offset = 0; 1.1421 + memcpy(db->buffer, buffer, length); 1.1422 + db->next = NULL; 1.1423 + 1.1424 + /* now, add it to the stream */ 1.1425 + 1.1426 + if (s->last != NULL) s->last->next = db; 1.1427 + s->last = db; 1.1428 + s->size += length; 1.1429 + if (s->first == NULL) s->first = db; 1.1430 + 1.1431 + check_integrity(s); 1.1432 + 1.1433 + /*------------------------------------------------------- */ 1.1434 + /* now we look at the stream to see if we have enough data to 1.1435 + decode */ 1.1436 + 1.1437 + while (s->size > 0 ) { 1.1438 + unsigned char *recordBuf = NULL; 1.1439 + 1.1440 + SSLRecord sr; 1.1441 + unsigned recordLen; 1.1442 + unsigned recordsize; 1.1443 + 1.1444 + check_integrity(s); 1.1445 + 1.1446 + if ( s->first == NULL) { 1.1447 + PR_fprintf(PR_STDOUT,"ERROR: s->first is null\n"); 1.1448 + exit(9); 1.1449 + } 1.1450 + 1.1451 + /* in the case of an SSL 2 client-hello */ 1.1452 + /* will have the high-bit set, whereas an SSL 3 client-hello will not */ 1.1453 + /* SSL2 can also send records that begin with the high bit clear. 1.1454 + * This code will incorrectly handle them. XXX 1.1455 + */ 1.1456 + if (isV2Session || s->first->buffer[s->first->offset] & 0x80) { 1.1457 + /* it's an SSL 2 packet */ 1.1458 + unsigned char lenbuf[3]; 1.1459 + 1.1460 + /* first, we check if there's enough data for it to be an SSL2-type 1.1461 + * record. What a pain.*/ 1.1462 + if (s->size < sizeof lenbuf) { 1.1463 + partial_packet(length, s->size, sizeof lenbuf); 1.1464 + return; 1.1465 + } 1.1466 + 1.1467 + /* read the first two bytes off the stream. */ 1.1468 + read_stream_bytes(lenbuf, s, sizeof(lenbuf)); 1.1469 + recordLen = ((unsigned int)(lenbuf[0] & 0x7f) << 8) + lenbuf[1] + 1.1470 + ((lenbuf[0] & 0x80) ? 2 : 3); 1.1471 + PR_fprintf(PR_STDOUT, "recordLen = %u bytes\n", recordLen); 1.1472 + 1.1473 + /* put 'em back on the head of the stream. */ 1.1474 + db = PR_NEW(struct _DataBuffer); 1.1475 + 1.1476 + db->length = sizeof lenbuf; 1.1477 + db->buffer = (unsigned char*) PORT_Alloc(db->length); 1.1478 + db->offset = 0; 1.1479 + memcpy(db->buffer, lenbuf, sizeof lenbuf); 1.1480 + 1.1481 + db->next = s->first; 1.1482 + s->first = db; 1.1483 + if (s->last == NULL) 1.1484 + s->last = db; 1.1485 + s->size += db->length; 1.1486 + 1.1487 + /* if there wasn't enough, go back for more. */ 1.1488 + if (s->size < recordLen) { 1.1489 + check_integrity(s); 1.1490 + partial_packet(length, s->size, recordLen); 1.1491 + return; 1.1492 + } 1.1493 + partial_packet(length, s->size, recordLen); 1.1494 + 1.1495 + /* read in the whole record. */ 1.1496 + recordBuf = PORT_Alloc(recordLen); 1.1497 + read_stream_bytes(recordBuf, s, recordLen); 1.1498 + 1.1499 + print_sslv2(s, recordBuf, recordLen); 1.1500 + PR_FREEIF(recordBuf); 1.1501 + check_integrity(s); 1.1502 + 1.1503 + continue; 1.1504 + } 1.1505 + 1.1506 + /***********************************************************/ 1.1507 + /* It's SSL v3 */ 1.1508 + /***********************************************************/ 1.1509 + check_integrity(s); 1.1510 + 1.1511 + if (s->size < sizeof sr) { 1.1512 + partial_packet(length, s->size, sizeof(SSLRecord)); 1.1513 + return; 1.1514 + } 1.1515 + 1.1516 + read_stream_bytes((unsigned char *)&sr, s, sizeof sr); 1.1517 + 1.1518 + /* we have read the stream bytes. Look at the length of 1.1519 + the ssl record. If we don't have enough data to satisfy this 1.1520 + request, then put the bytes we just took back at the head 1.1521 + of the queue */ 1.1522 + recordsize = GET_SHORT(sr.length); 1.1523 + 1.1524 + if (recordsize > s->size) { 1.1525 + db = PR_NEW(struct _DataBuffer); 1.1526 + 1.1527 + db->length = sizeof sr; 1.1528 + db->buffer = (unsigned char*) PORT_Alloc(db->length); 1.1529 + db->offset = 0; 1.1530 + memcpy(db->buffer, &sr, sizeof sr); 1.1531 + db->next = s->first; 1.1532 + 1.1533 + /* now, add it back on to the head of the stream */ 1.1534 + 1.1535 + s->first = db; 1.1536 + if (s->last == NULL) 1.1537 + s->last = db; 1.1538 + s->size += db->length; 1.1539 + 1.1540 + check_integrity(s); 1.1541 + partial_packet(length, s->size, recordsize); 1.1542 + return; 1.1543 + } 1.1544 + partial_packet(length, s->size, recordsize); 1.1545 + 1.1546 + 1.1547 + PR_fprintf(PR_STDOUT,"SSLRecord { [%s]\n", get_time_string() ); 1.1548 + if (sslhexparse) { 1.1549 + print_hex(5,(unsigned char*)&sr); 1.1550 + } 1.1551 + 1.1552 + check_integrity(s); 1.1553 + 1.1554 + PR_fprintf(PR_STDOUT," type = %d (",sr.type); 1.1555 + switch(sr.type) { 1.1556 + case 20 : 1.1557 + PR_fprintf(PR_STDOUT,"change_cipher_spec)\n"); 1.1558 + break; 1.1559 + case 21 : 1.1560 + PR_fprintf(PR_STDOUT,"alert)\n"); 1.1561 + break; 1.1562 + case 22 : 1.1563 + PR_fprintf(PR_STDOUT,"handshake)\n"); 1.1564 + break; 1.1565 + case 23 : 1.1566 + PR_fprintf(PR_STDOUT,"application_data)\n"); 1.1567 + break; 1.1568 + default: 1.1569 + PR_fprintf(PR_STDOUT,"unknown)\n"); 1.1570 + break; 1.1571 + } 1.1572 + PR_fprintf(PR_STDOUT," version = { %d,%d }\n", 1.1573 + (PRUint32)sr.ver_maj,(PRUint32)sr.ver_min); 1.1574 + PR_fprintf(PR_STDOUT," length = %d (0x%x)\n", 1.1575 + (PRUint32)GET_SHORT(sr.length), (PRUint32)GET_SHORT(sr.length)); 1.1576 + 1.1577 + 1.1578 + recordLen = recordsize; 1.1579 + PR_ASSERT(s->size >= recordLen); 1.1580 + if (s->size >= recordLen) { 1.1581 + recordBuf = (unsigned char*) PORT_Alloc(recordLen); 1.1582 + read_stream_bytes(recordBuf, s, recordLen); 1.1583 + 1.1584 + if (s->isEncrypted) { 1.1585 + PR_fprintf(PR_STDOUT," < encrypted >\n"); 1.1586 + } else { /* not encrypted */ 1.1587 + 1.1588 + switch(sr.type) { 1.1589 + case 20 : /* change_cipher_spec */ 1.1590 + if (sslhexparse) print_hex(recordLen - s->hMACsize,recordBuf); 1.1591 + /* mark to say we can only dump hex form now on 1.1592 + * if it is not one on a null cipher */ 1.1593 + s->isEncrypted = isNULLcipher(currentcipher) ? 0 : 1; 1.1594 + break; 1.1595 + 1.1596 + case 21 : /* alert */ 1.1597 + switch(recordBuf[0]) { 1.1598 + case 1: PR_fprintf(PR_STDOUT, " warning: "); break; 1.1599 + case 2: PR_fprintf(PR_STDOUT, " fatal: "); break; 1.1600 + default: PR_fprintf(PR_STDOUT, " unknown level %d: ", recordBuf[0]); break; 1.1601 + } 1.1602 + 1.1603 + switch(recordBuf[1]) { 1.1604 + case 0: PR_FPUTS("close_notify\n" ); break; 1.1605 + case 10: PR_FPUTS("unexpected_message\n" ); break; 1.1606 + case 20: PR_FPUTS("bad_record_mac\n" ); break; 1.1607 + case 21: PR_FPUTS("decryption_failed\n" ); break; 1.1608 + case 22: PR_FPUTS("record_overflow\n" ); break; 1.1609 + case 30: PR_FPUTS("decompression_failure\n" ); break; 1.1610 + case 40: PR_FPUTS("handshake_failure\n" ); break; 1.1611 + case 41: PR_FPUTS("no_certificate\n" ); break; 1.1612 + case 42: PR_FPUTS("bad_certificate\n" ); break; 1.1613 + case 43: PR_FPUTS("unsupported_certificate\n" ); break; 1.1614 + case 44: PR_FPUTS("certificate_revoked\n" ); break; 1.1615 + case 45: PR_FPUTS("certificate_expired\n" ); break; 1.1616 + case 46: PR_FPUTS("certificate_unknown\n" ); break; 1.1617 + case 47: PR_FPUTS("illegal_parameter\n" ); break; 1.1618 + case 48: PR_FPUTS("unknown_ca\n" ); break; 1.1619 + case 49: PR_FPUTS("access_denied\n" ); break; 1.1620 + case 50: PR_FPUTS("decode_error\n" ); break; 1.1621 + case 51: PR_FPUTS("decrypt_error\n" ); break; 1.1622 + case 60: PR_FPUTS("export_restriction\n" ); break; 1.1623 + case 70: PR_FPUTS("protocol_version\n" ); break; 1.1624 + case 71: PR_FPUTS("insufficient_security\n" ); break; 1.1625 + case 80: PR_FPUTS("internal_error\n" ); break; 1.1626 + case 90: PR_FPUTS("user_canceled\n" ); break; 1.1627 + case 100: PR_FPUTS("no_renegotiation\n" ); break; 1.1628 + case 110: PR_FPUTS("unsupported_extension\n" ); break; 1.1629 + case 111: PR_FPUTS("certificate_unobtainable\n" ); break; 1.1630 + case 112: PR_FPUTS("unrecognized_name\n" ); break; 1.1631 + case 113: PR_FPUTS("bad_certificate_status_response\n" ); break; 1.1632 + case 114: PR_FPUTS("bad_certificate_hash_value\n" ); break; 1.1633 + 1.1634 + default: PR_fprintf(PR_STDOUT, "unknown alert %d\n", recordBuf[1]); 1.1635 + break; 1.1636 + } 1.1637 + 1.1638 + if (sslhexparse) print_hex(recordLen - s->hMACsize,recordBuf); 1.1639 + break; 1.1640 + 1.1641 + case 22 : /* handshake */ 1.1642 + print_ssl3_handshake( recordBuf, recordLen - s->hMACsize, &sr, s ); 1.1643 + break; 1.1644 + 1.1645 + case 23 : /* application data */ 1.1646 + print_hex(recordLen - s->hMACsize,recordBuf); 1.1647 + break; 1.1648 + 1.1649 + default: 1.1650 + print_hex(recordLen - s->hMACsize,recordBuf); 1.1651 + break; 1.1652 + } 1.1653 + if (s->hMACsize) { 1.1654 + PR_fprintf(PR_STDOUT," MAC = {...}\n"); 1.1655 + if (sslhexparse) { 1.1656 + unsigned char *offset = recordBuf + (recordLen - s->hMACsize); 1.1657 + print_hex(s->hMACsize, offset); 1.1658 + } 1.1659 + } 1.1660 + } /* not encrypted */ 1.1661 + } 1.1662 + PR_fprintf(PR_STDOUT,"}\n"); 1.1663 + PR_FREEIF(recordBuf); 1.1664 + check_integrity(s); 1.1665 + } 1.1666 +} 1.1667 + 1.1668 +void print_hex(int amt, unsigned char *buf) 1.1669 +{ 1.1670 + int i,j,k; 1.1671 + char t[20]; 1.1672 + static char string[5000]; 1.1673 + 1.1674 + 1.1675 + for(i=0;i<amt;i++) { 1.1676 + t[1] =0; 1.1677 + 1.1678 + if (i%16 ==0) { /* if we are at the beginning of a line */ 1.1679 + PR_fprintf(PR_STDOUT,"%4x:",i); /* print the line number */ 1.1680 + strcpy(string,""); 1.1681 + } 1.1682 + 1.1683 + if (i%4 == 0) { 1.1684 + PR_fprintf(PR_STDOUT," "); 1.1685 + } 1.1686 + 1.1687 + j = buf[i]; 1.1688 + 1.1689 + t[0] = (j >= 0x20 && j < 0x80) ? j : '.'; 1.1690 + 1.1691 + if (fancy) { 1.1692 + switch (t[0]) { 1.1693 + case '<': 1.1694 + strcpy(t,"<"); 1.1695 + break; 1.1696 + case '>': 1.1697 + strcpy(t,">"); 1.1698 + break; 1.1699 + case '&': 1.1700 + strcpy(t,"&"); 1.1701 + break; 1.1702 + } 1.1703 + } 1.1704 + strcat(string,t); 1.1705 + 1.1706 + PR_fprintf(PR_STDOUT,"%02x ",(PRUint8) buf[i]); 1.1707 + 1.1708 + /* if we've reached the end of the line - add the string */ 1.1709 + if (i%16 == 15) PR_fprintf(PR_STDOUT," | %s\n",string); 1.1710 + } 1.1711 + /* we reached the end of the buffer,*/ 1.1712 + /* do we have buffer left over? */ 1.1713 + j = i%16; 1.1714 + if (j > 0) { 1.1715 + for (k=0;k<(16-j);k++) { 1.1716 + /* print additional space after every four bytes */ 1.1717 + if ((k + j)%4 == 0) { 1.1718 + PR_fprintf(PR_STDOUT," "); 1.1719 + } 1.1720 + PR_fprintf(PR_STDOUT," "); 1.1721 + } 1.1722 + PR_fprintf(PR_STDOUT," | %s\n",string); 1.1723 + } 1.1724 +} 1.1725 + 1.1726 +void Usage(void) 1.1727 +{ 1.1728 + PR_fprintf(PR_STDERR, "SSLTAP (C) 1997, 1998 Netscape Communications Corporation.\n"); 1.1729 + PR_fprintf(PR_STDERR, "Usage: ssltap [-vhfsxl] [-p port] hostname:port\n"); 1.1730 + PR_fprintf(PR_STDERR, " -v [prints version string]\n"); 1.1731 + PR_fprintf(PR_STDERR, " -h [outputs hex instead of ASCII]\n"); 1.1732 + PR_fprintf(PR_STDERR, " -f [turn on Fancy HTML coloring]\n"); 1.1733 + PR_fprintf(PR_STDERR, " -s [turn on SSL decoding]\n"); 1.1734 + PR_fprintf(PR_STDERR, " -x [turn on extra SSL hex dumps]\n"); 1.1735 + PR_fprintf(PR_STDERR, " -p port [specify rendezvous port (default 1924)]\n"); 1.1736 + PR_fprintf(PR_STDERR, " -l [loop - continue to wait for more connections]\n"); 1.1737 + 1.1738 + 1.1739 +} 1.1740 + 1.1741 +void 1.1742 +showErr(const char * msg) 1.1743 +{ 1.1744 + PRErrorCode err = PR_GetError(); 1.1745 + const char * errString; 1.1746 + 1.1747 + if (err == PR_UNKNOWN_ERROR) 1.1748 + err = PR_CONNECT_RESET_ERROR; /* bug in NSPR. */ 1.1749 + errString = SECU_Strerror(err); 1.1750 + 1.1751 + if (!errString) 1.1752 + errString = "(no text available)"; 1.1753 + PR_fprintf(PR_STDERR, "%s: Error %d: %s: %s", progName, err, errString, msg); 1.1754 +} 1.1755 + 1.1756 +int main(int argc, char *argv[]) 1.1757 +{ 1.1758 + char *hostname=NULL; 1.1759 + PRUint16 rendport=DEFPORT,port; 1.1760 + PRAddrInfo *ai; 1.1761 + void *iter; 1.1762 + PRStatus r; 1.1763 + PRNetAddr na_client,na_server,na_rend; 1.1764 + PRFileDesc *s_server,*s_client,*s_rend; /*rendezvous */ 1.1765 + int c_count=0; 1.1766 + PLOptState *optstate; 1.1767 + PLOptStatus status; 1.1768 + SECStatus rv; 1.1769 + 1.1770 + progName = argv[0]; 1.1771 + optstate = PL_CreateOptState(argc,argv,"fxhslp:"); 1.1772 + while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { 1.1773 + switch (optstate->option) { 1.1774 + case 'f': 1.1775 + fancy++; 1.1776 + break; 1.1777 + case 'h': 1.1778 + hexparse++; 1.1779 + break; 1.1780 + case 's': 1.1781 + sslparse++; 1.1782 + break; 1.1783 + case 'x': 1.1784 + sslhexparse++; 1.1785 + break; 1.1786 + case 'l': 1.1787 + looparound++; 1.1788 + break; 1.1789 + case 'p': 1.1790 + rendport = atoi(optstate->value); 1.1791 + break; 1.1792 + case '\0': 1.1793 + hostname = PL_strdup(optstate->value); 1.1794 + } 1.1795 + } 1.1796 + if (status == PL_OPT_BAD) 1.1797 + Usage(); 1.1798 + 1.1799 + if (fancy) { 1.1800 + if (!hexparse && !sslparse) { 1.1801 + PR_fprintf(PR_STDERR, 1.1802 +"Note: use of -f without -s or -h not recommended, \n" 1.1803 +"as the output looks a little strange. It may be useful, however\n"); 1.1804 + } 1.1805 + } 1.1806 + 1.1807 + if(! hostname ) Usage(), exit(2); 1.1808 + 1.1809 + { 1.1810 + char *colon = (char *)strchr(hostname, ':'); 1.1811 + if (!colon) { 1.1812 + PR_fprintf(PR_STDERR, 1.1813 + "You must specify the host AND port you wish to connect to\n"); 1.1814 + Usage(), exit(3); 1.1815 + } 1.1816 + port = atoi(&colon[1]); 1.1817 + *colon = '\0'; 1.1818 + 1.1819 + if (port == 0) { 1.1820 + PR_fprintf(PR_STDERR, "Port must be a nonzero number.\n"); 1.1821 + exit(4); 1.1822 + } 1.1823 + } 1.1824 + 1.1825 + /* find the 'server' IP address so we don't have to look it up later */ 1.1826 + 1.1827 + if (fancy) { 1.1828 + PR_fprintf(PR_STDOUT,"<HTML><HEAD><TITLE>SSLTAP output</TITLE></HEAD>\n"); 1.1829 + PR_fprintf(PR_STDOUT,"<BODY><PRE>\n"); 1.1830 + } 1.1831 + PR_fprintf(PR_STDERR,"Looking up \"%s\"...\n", hostname); 1.1832 + ai = PR_GetAddrInfoByName(hostname, PR_AF_UNSPEC, PR_AI_ADDRCONFIG); 1.1833 + if (!ai) { 1.1834 + showErr("Host Name lookup failed\n"); 1.1835 + exit(5); 1.1836 + } 1.1837 + 1.1838 + iter = NULL; 1.1839 + iter = PR_EnumerateAddrInfo(iter, ai, port, &na_server); 1.1840 + /* set up the port which the client will connect to */ 1.1841 + 1.1842 + r = PR_InitializeNetAddr(PR_IpAddrAny,rendport,&na_rend); 1.1843 + if (r == PR_FAILURE) { 1.1844 + PR_fprintf(PR_STDERR, 1.1845 + "PR_InitializeNetAddr(,%d,) failed with error %d\n",PR_GetError()); 1.1846 + exit(0); 1.1847 + } 1.1848 + 1.1849 + rv = NSS_NoDB_Init(""); 1.1850 + if (rv != SECSuccess) { 1.1851 + PR_fprintf(PR_STDERR, 1.1852 + "NSS_NoDB_Init() failed with error %d\n",PR_GetError()); 1.1853 + exit(5); 1.1854 + } 1.1855 + 1.1856 + s_rend = PR_NewTCPSocket(); 1.1857 + if (!s_rend) { 1.1858 + showErr("Couldn't create socket\n"); 1.1859 + exit(6); 1.1860 + } 1.1861 + 1.1862 + if (PR_Bind(s_rend, &na_rend )) { 1.1863 + PR_fprintf(PR_STDERR,"Couldn't bind to port %d (error %d)\n",rendport, PR_GetError()); 1.1864 + exit(-1); 1.1865 + } 1.1866 + 1.1867 + if ( PR_Listen(s_rend, 5)) { 1.1868 + showErr("Couldn't listen\n"); 1.1869 + exit(-1); 1.1870 + } 1.1871 + 1.1872 + PR_fprintf(PR_STDERR,"Proxy socket ready and listening\n"); 1.1873 + do { /* accept one connection and process it. */ 1.1874 + PRPollDesc pds[2]; 1.1875 + 1.1876 + s_client = PR_Accept(s_rend,&na_client,PR_SecondsToInterval(3600)); 1.1877 + if (s_client == NULL) { 1.1878 + showErr("accept timed out\n"); 1.1879 + exit(7); 1.1880 + } 1.1881 + 1.1882 + s_server = PR_OpenTCPSocket(na_server.raw.family); 1.1883 + if (s_server == NULL) { 1.1884 + showErr("couldn't open new socket to connect to server \n"); 1.1885 + exit(8); 1.1886 + } 1.1887 + 1.1888 + r = PR_Connect(s_server,&na_server,PR_SecondsToInterval(5)); 1.1889 + 1.1890 + if ( r == PR_FAILURE ) 1.1891 + { 1.1892 + showErr("Couldn't connect\n"); 1.1893 + return -1; 1.1894 + } 1.1895 + 1.1896 + if (looparound) { 1.1897 + if (fancy) PR_fprintf(PR_STDOUT,"<p><HR><H2>"); 1.1898 + PR_fprintf(PR_STDOUT,"Connection #%d [%s]\n", c_count+1, 1.1899 + get_time_string()); 1.1900 + if (fancy) PR_fprintf(PR_STDOUT,"</H2>"); 1.1901 + } 1.1902 + 1.1903 + 1.1904 + PR_fprintf(PR_STDOUT,"Connected to %s:%d\n", hostname, port); 1.1905 + 1.1906 +#define PD_C 0 1.1907 +#define PD_S 1 1.1908 + 1.1909 + pds[PD_C].fd = s_client; 1.1910 + pds[PD_S].fd = s_server; 1.1911 + pds[PD_C].in_flags = PR_POLL_READ; 1.1912 + pds[PD_S].in_flags = PR_POLL_READ; 1.1913 + 1.1914 + /* make sure the new connections don't start out encrypted. */ 1.1915 + clientstream.isEncrypted = 0; 1.1916 + serverstream.isEncrypted = 0; 1.1917 + isV2Session = 0; 1.1918 + 1.1919 + while( (pds[PD_C].in_flags & PR_POLL_READ) != 0 || 1.1920 + (pds[PD_S].in_flags & PR_POLL_READ) != 0 ) 1.1921 + { /* Handle all messages on the connection */ 1.1922 + PRInt32 amt; 1.1923 + PRInt32 wrote; 1.1924 + unsigned char buffer[ TAPBUFSIZ ]; 1.1925 + 1.1926 + amt = PR_Poll(pds,2,PR_INTERVAL_NO_TIMEOUT); 1.1927 + if (amt <= 0) { 1.1928 + if (amt) 1.1929 + showErr( "PR_Poll failed.\n"); 1.1930 + else 1.1931 + showErr( "PR_Poll timed out.\n"); 1.1932 + break; 1.1933 + } 1.1934 + 1.1935 + if (pds[PD_C].out_flags & PR_POLL_EXCEPT) { 1.1936 + showErr( "Exception on client-side socket.\n"); 1.1937 + break; 1.1938 + } 1.1939 + 1.1940 + if (pds[PD_S].out_flags & PR_POLL_EXCEPT) { 1.1941 + showErr( "Exception on server-side socket.\n"); 1.1942 + break; 1.1943 + } 1.1944 + 1.1945 + 1.1946 +/* read data, copy it to stdout, and write to other socket */ 1.1947 + 1.1948 + if ((pds[PD_C].in_flags & PR_POLL_READ) != 0 && 1.1949 + (pds[PD_C].out_flags & PR_POLL_READ) != 0 ) { 1.1950 + 1.1951 + amt = PR_Read(s_client, buffer, sizeof(buffer)); 1.1952 + 1.1953 + if ( amt < 0) { 1.1954 + showErr( "Client socket read failed.\n"); 1.1955 + break; 1.1956 + } 1.1957 + 1.1958 + if( amt == 0 ) { 1.1959 + PR_fprintf(PR_STDOUT, "Read EOF on Client socket. [%s]\n", 1.1960 + get_time_string() ); 1.1961 + pds[PD_C].in_flags &= ~PR_POLL_READ; 1.1962 + PR_Shutdown(s_server, PR_SHUTDOWN_SEND); 1.1963 + continue; 1.1964 + } 1.1965 + 1.1966 + PR_fprintf(PR_STDOUT,"--> [\n"); 1.1967 + if (fancy) PR_fprintf(PR_STDOUT,"<font color=blue>"); 1.1968 + 1.1969 + if (hexparse) print_hex(amt, buffer); 1.1970 + if (sslparse) print_ssl(&clientstream,amt,buffer); 1.1971 + if (!hexparse && !sslparse) PR_Write(PR_STDOUT,buffer,amt); 1.1972 + if (fancy) PR_fprintf(PR_STDOUT,"</font>"); 1.1973 + PR_fprintf(PR_STDOUT,"]\n"); 1.1974 + 1.1975 + wrote = PR_Write(s_server, buffer, amt); 1.1976 + if (wrote != amt ) { 1.1977 + if (wrote < 0) { 1.1978 + showErr("Write to server socket failed.\n"); 1.1979 + break; 1.1980 + } else { 1.1981 + PR_fprintf(PR_STDERR, "Short write to server socket!\n"); 1.1982 + } 1.1983 + } 1.1984 + } /* end of read from client socket. */ 1.1985 + 1.1986 +/* read data, copy it to stdout, and write to other socket */ 1.1987 + if ((pds[PD_S].in_flags & PR_POLL_READ) != 0 && 1.1988 + (pds[PD_S].out_flags & PR_POLL_READ) != 0 ) { 1.1989 + 1.1990 + amt = PR_Read(s_server, buffer, sizeof(buffer)); 1.1991 + 1.1992 + if ( amt < 0) { 1.1993 + showErr( "error on server-side socket.\n"); 1.1994 + break; 1.1995 + } 1.1996 + 1.1997 + if( amt == 0 ) { 1.1998 + PR_fprintf(PR_STDOUT, "Read EOF on Server socket. [%s]\n", 1.1999 + get_time_string() ); 1.2000 + pds[PD_S].in_flags &= ~PR_POLL_READ; 1.2001 + PR_Shutdown(s_client, PR_SHUTDOWN_SEND); 1.2002 + continue; 1.2003 + } 1.2004 + 1.2005 + PR_fprintf(PR_STDOUT,"<-- [\n"); 1.2006 + if (fancy) PR_fprintf(PR_STDOUT,"<font color=red>"); 1.2007 + if (hexparse) print_hex(amt, (unsigned char *)buffer); 1.2008 + if (sslparse) print_ssl(&serverstream,amt,(unsigned char *)buffer); 1.2009 + if (!hexparse && !sslparse) PR_Write(PR_STDOUT,buffer,amt); 1.2010 + if (fancy) PR_fprintf(PR_STDOUT,"</font>"); 1.2011 + PR_fprintf(PR_STDOUT,"]\n"); 1.2012 + 1.2013 + 1.2014 + wrote = PR_Write(s_client, buffer, amt); 1.2015 + if (wrote != amt ) { 1.2016 + if (wrote < 0) { 1.2017 + showErr("Write to client socket failed.\n"); 1.2018 + break; 1.2019 + } else { 1.2020 + PR_fprintf(PR_STDERR, "Short write to client socket!\n"); 1.2021 + } 1.2022 + } 1.2023 + 1.2024 + } /* end of read from server socket. */ 1.2025 + 1.2026 +/* Loop, handle next message. */ 1.2027 + 1.2028 + } /* handle messages during a connection loop */ 1.2029 + PR_Close(s_client); 1.2030 + PR_Close(s_server); 1.2031 + flush_stream(&clientstream); 1.2032 + flush_stream(&serverstream); 1.2033 + /* Connection is closed, so reset the current cipher */ 1.2034 + currentcipher = 0; 1.2035 + c_count++; 1.2036 + PR_fprintf(PR_STDERR,"Connection %d Complete [%s]\n", c_count, 1.2037 + get_time_string() ); 1.2038 + } while (looparound); /* accept connection and process it. */ 1.2039 + PR_Close(s_rend); 1.2040 + NSS_Shutdown(); 1.2041 + return 0; 1.2042 +}