1
/* ***** BEGIN LICENSE BLOCK *****
2
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
4
* The contents of this file are subject to the Mozilla Public License Version
5
* 1.1 (the "License"); you may not use this file except in compliance with
6
* the License. You may obtain a copy of the License at
7
* http://www.mozilla.org/MPL/
9
* Software distributed under the License is distributed on an "AS IS" basis,
10
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
11
* for the specific language governing rights and limitations under the
14
* The Original Code is the Netscape security libraries.
16
* The Initial Developer of the Original Code is
17
* Netscape Communications Corporation.
18
* Portions created by the Initial Developer are Copyright (C) 1994-2000
19
* the Initial Developer. All Rights Reserved.
23
* Alternatively, the contents of this file may be used under the terms of
24
* either the GNU General Public License Version 2 or later (the "GPL"), or
25
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
26
* in which case the provisions of the GPL or the LGPL are applicable instead
27
* of those above. If you wish to allow use of your version of this file only
28
* under the terms of either the GPL or the LGPL, and not to allow others to
29
* use your version of this file under the terms of the MPL, indicate your
30
* decision by deleting the provisions above and replace them with the notice
31
* and other provisions required by the GPL or the LGPL. If you do not delete
32
* the provisions above, a recipient may use your version of this file under
33
* the terms of any one of the MPL, the GPL or the LGPL.
35
* ***** END LICENSE BLOCK ***** */
40
* Version 1.0 : Frederick Roeber : 11 June 1997
41
* Version 2.0 : Steve Parkinson : 13 November 1997
42
* Version 3.0 : Nelson Bolyard : 22 July 1998
43
* Version 3.1 : Nelson Bolyard : 24 May 1999
45
* changes in version 2.0:
47
* Shows structure of SSL negotiation, if enabled.
49
* This "proxies" a socket connection (like a socks tunnel), but displays the
50
* data is it flies by.
52
* In the code, the 'client' socket is the one on the client side of the
53
* proxy, and the server socket is on the server side.
60
#include <memory.h> /* for memcpy, etc. */
68
#define VERSIONSTRING "$Revision: 1.7.2.2 $ ($Date: 2006/07/19 01:18:33 $) $Author: nelson%bolyard.com $"
71
struct _DataBufferList;
74
typedef struct _DataBufferList {
75
struct _DataBuffer *first,*last;
80
typedef struct _DataBuffer {
81
unsigned char *buffer;
83
int offset; /* offset of first good byte */
84
struct _DataBuffer *next;
89
clientstream = {NULL, NULL, 0, 0},
90
serverstream = {NULL, NULL, 0, 0};
97
typedef struct _SSLRecord {
99
PRUint8 ver_maj,ver_min;
104
typedef struct _ClientHelloV2 {
109
PRUint8 sidlength[2];
110
PRUint8 rndlength[2];
114
typedef struct _ServerHelloV2 {
120
PRUint8 certlength[2];
122
PRUint8 cidlength[2];
125
typedef struct _ClientMasterKeyV2 {
129
PRUint8 cipherkind[3];
131
PRUint8 secretkey[2];
137
#define TAPBUFSIZ 16384
149
#define PR_FPUTS(x) PR_fprintf(PR_STDOUT, x )
151
#define GET_SHORT(x) ((PRUint16)(((PRUint16)((PRUint8*)x)[0]) << 8) + ((PRUint16)((PRUint8*)x)[1]))
152
#define GET_24(x) ((PRUint32) ( \
153
(((PRUint32)((PRUint8*)x)[0]) << 16) \
155
(((PRUint32)((PRUint8*)x)[1]) << 8) \
157
(((PRUint32)((PRUint8*)x)[2]) << 0) \
160
void print_hex(int amt, unsigned char *buf);
161
void read_stream_bytes(unsigned char *d, DataBufferList *db, int length);
163
void myhalt(int dblsize,int collectedsize) {
169
const char *get_error_text(int error) {
171
case PR_IO_TIMEOUT_ERROR:
174
case PR_CONNECT_REFUSED_ERROR:
175
return "Connection refused";
177
case PR_NETWORK_UNREACHABLE_ERROR:
178
return "Network unreachable";
180
case PR_BAD_ADDRESS_ERROR:
181
return "Bad address";
183
case PR_CONNECT_RESET_ERROR:
184
return "Connection reset";
198
void check_integrity(DataBufferList *dbl) {
205
i+= db->length - db->offset;
208
if (i != dbl->size) {
213
/* Free's the DataBuffer at the head of the list and returns the pointer
214
* to the new head of the list.
217
free_head(DataBufferList *dbl)
219
DataBuffer *db = dbl->first;
220
PR_ASSERT(db->offset >= db->length);
221
if (db->offset >= db->length) {
222
dbl->first = db->next;
223
if (dbl->first == NULL) {
234
read_stream_bytes(unsigned char *d, DataBufferList *dbl, int length) {
236
DataBuffer *db = dbl->first;
239
PR_fprintf(PR_STDERR,"assert failed - dbl->first is null\n");
244
/* find the number of bytes to copy from the head buffer */
245
/* if there's too many in this buffer, then only copy 'length' */
246
toCopy = PR_MIN(db->length - db->offset, length);
248
memcpy(d + copied, db->buffer + db->offset, toCopy);
250
db->offset += toCopy;
254
/* if we emptied the head buffer */
255
if (db->offset >= db->length) {
260
check_integrity(dbl);
265
flush_stream(DataBufferList *dbl)
267
DataBuffer *db = dbl->first;
268
check_integrity(dbl);
270
db->offset = db->length;
274
check_integrity(dbl);
278
const char * V2CipherString(int cs_int) {
283
case 0x010080: cs_str = "SSL2/RSA/RC4-128/MD5"; break;
284
case 0x020080: cs_str = "SSL2/RSA/RC4-40/MD5"; break;
285
case 0x030080: cs_str = "SSL2/RSA/RC2CBC128/MD5"; break;
286
case 0x040080: cs_str = "SSL2/RSA/RC2CBC40/MD5"; break;
287
case 0x050080: cs_str = "SSL2/RSA/IDEA128CBC/MD5"; break;
288
case 0x060040: cs_str = "SSL2/RSA/DES56-CBC/MD5"; break;
289
case 0x0700C0: cs_str = "SSL2/RSA/3DES192EDE-CBC/MD5"; break;
291
case 0x000001: cs_str = "SSL3/RSA/NULL/MD5"; break;
292
case 0x000002: cs_str = "SSL3/RSA/NULL/SHA"; break;
293
case 0x000003: cs_str = "SSL3/RSA/RC4-40/MD5"; break;
294
case 0x000004: cs_str = "SSL3/RSA/RC4-128/MD5"; break;
295
case 0x000005: cs_str = "SSL3/RSA/RC4-128/SHA"; break;
296
case 0x000006: cs_str = "SSL3/RSA/RC2CBC40/MD5"; break;
297
case 0x000007: cs_str = "SSL3/RSA/IDEA128CBC/SHA"; break;
298
case 0x000008: cs_str = "SSL3/RSA/DES40-CBC/SHA"; break;
299
case 0x000009: cs_str = "SSL3/RSA/DES56-CBC/SHA"; break;
300
case 0x00000A: cs_str = "SSL3/RSA/3DES192EDE-CBC/SHA"; break;
302
case 0x00000B: cs_str = "SSL3/DH-DSS/DES40-CBC/SHA"; break;
303
case 0x00000C: cs_str = "SSL3/DH-DSS/DES56-CBC/SHA"; break;
304
case 0x00000D: cs_str = "SSL3/DH-DSS/DES192EDE3CBC/SHA"; break;
305
case 0x00000E: cs_str = "SSL3/DH-RSA/DES40-CBC/SHA"; break;
306
case 0x00000F: cs_str = "SSL3/DH-RSA/DES56-CBC/SHA"; break;
307
case 0x000010: cs_str = "SSL3/DH-RSA/3DES192EDE-CBC/SHA"; break;
309
case 0x000011: cs_str = "SSL3/DHE-DSS/DES40-CBC/SHA"; break;
310
case 0x000012: cs_str = "SSL3/DHE-DSS/DES56-CBC/SHA"; break;
311
case 0x000013: cs_str = "SSL3/DHE-DSS/DES192EDE3CBC/SHA"; break;
312
case 0x000014: cs_str = "SSL3/DHE-RSA/DES40-CBC/SHA"; break;
313
case 0x000015: cs_str = "SSL3/DHE-RSA/DES56-CBC/SHA"; break;
314
case 0x000016: cs_str = "SSL3/DHE-RSA/3DES192EDE-CBC/SHA"; break;
316
case 0x000017: cs_str = "SSL3/DH-anon/RC4-40/MD5"; break;
317
case 0x000018: cs_str = "SSL3/DH-anon/RC4-128/MD5"; break;
318
case 0x000019: cs_str = "SSL3/DH-anon/DES40-CBC/SHA"; break;
319
case 0x00001A: cs_str = "SSL3/DH-anon/DES56-CBC/SHA"; break;
320
case 0x00001B: cs_str = "SSL3/DH-anon/3DES192EDE-CBC/SHA"; break;
322
case 0x00001C: cs_str = "SSL3/FORTEZZA-DMS/NULL/SHA"; break;
323
case 0x00001D: cs_str = "SSL3/FORTEZZA-DMS/FORTEZZA-CBC/SHA"; break;
324
case 0x00001E: cs_str = "SSL3/FORTEZZA-DMS/RC4-128/SHA"; break;
326
case 0x00002F: cs_str = "TLS/RSA/AES128-CBC/SHA"; break;
327
case 0x000030: cs_str = "TLS/DH-DSS/AES128-CBC/SHA"; break;
328
case 0x000031: cs_str = "TLS/DH-RSA/AES128-CBC/SHA"; break;
329
case 0x000032: cs_str = "TLS/DHE-DSS/AES128-CBC/SHA"; break;
330
case 0x000033: cs_str = "TLS/DHE-RSA/AES128-CBC/SHA"; break;
331
case 0x000034: cs_str = "TLS/DH-ANON/AES128-CBC/SHA"; break;
333
case 0x000035: cs_str = "TLS/RSA/AES256-CBC/SHA"; break;
334
case 0x000036: cs_str = "TLS/DH-DSS/AES256-CBC/SHA"; break;
335
case 0x000037: cs_str = "TLS/DH-RSA/AES256-CBC/SHA"; break;
336
case 0x000038: cs_str = "TLS/DHE-DSS/AES256-CBC/SHA"; break;
337
case 0x000039: cs_str = "TLS/DHE-RSA/AES256-CBC/SHA"; break;
338
case 0x00003A: cs_str = "TLS/DH-ANON/AES256-CBC/SHA"; break;
340
case 0x000041: cs_str = "TLS/RSA/CAMELLIA128-CBC/SHA"; break;
341
case 0x000042: cs_str = "TLS/DH-DSS/CAMELLIA128-CBC/SHA"; break;
342
case 0x000043: cs_str = "TLS/DH-RSA/CAMELLIA128-CBC/SHA"; break;
343
case 0x000044: cs_str = "TLS/DHE-DSS/CAMELLIA128-CBC/SHA"; break;
344
case 0x000045: cs_str = "TLS/DHE-RSA/CAMELLIA128-CBC/SHA"; break;
345
case 0x000046: cs_str = "TLS/DH-ANON/CAMELLIA128-CBC/SHA"; break;
347
case 0x000047: cs_str = "TLS/ECDH-ECDSA/NULL/SHA"; break;
348
case 0x000048: cs_str = "TLS/ECDH-ECDSA/RC4-128/SHA"; break;
349
case 0x000049: cs_str = "TLS/ECDH-ECDSA/DES-CBC/SHA"; break;
350
case 0x00004A: cs_str = "TLS/ECDH-ECDSA/3DESEDE-CBC/SHA"; break;
351
case 0x00004B: cs_str = "TLS/ECDH-ECDSA/AES128-CBC/SHA"; break;
352
case 0x00004C: cs_str = "TLS/ECDH-ECDSA/AES256-CBC/SHA"; break;
354
case 0x00004D: cs_str = "TLS/ECDH-RSA/NULL/SHA"; break;
355
case 0x00004E: cs_str = "TLS/ECDH-RSA/RC4-128/SHA"; break;
356
case 0x00004F: cs_str = "TLS/ECDH-RSA/DES-CBC/SHA"; break;
357
case 0x000050: cs_str = "TLS/ECDH-RSA/3DESEDE-CBC/SHA"; break;
358
case 0x000051: cs_str = "TLS/ECDH-RSA/AES128-CBC/SHA"; break;
359
case 0x000052: cs_str = "TLS/ECDH-RSA/AES256-CBC/SHA"; break;
361
case 0x000060: cs_str = "TLS/RSA-EXPORT1024/RC4-56/MD5"; break;
362
case 0x000061: cs_str = "TLS/RSA-EXPORT1024/RC2CBC56/MD5"; break;
363
case 0x000062: cs_str = "TLS/RSA-EXPORT1024/DES56-CBC/SHA"; break;
364
case 0x000064: cs_str = "TLS/RSA-EXPORT1024/RC4-56/SHA"; break;
365
case 0x000063: cs_str = "TLS/DHE-DSS_EXPORT1024/DES56-CBC/SHA"; break;
366
case 0x000065: cs_str = "TLS/DHE-DSS_EXPORT1024/RC4-56/SHA"; break;
367
case 0x000066: cs_str = "TLS/DHE-DSS/RC4-128/SHA"; break;
369
case 0x000072: cs_str = "TLS/DHE-DSS/3DESEDE-CBC/RMD160"; break;
370
case 0x000073: cs_str = "TLS/DHE-DSS/AES128-CBC/RMD160"; break;
371
case 0x000074: cs_str = "TLS/DHE-DSS/AES256-CBC/RMD160"; break;
373
case 0x000077: cs_str = "TLS/ECDHE-ECDSA/AES128-CBC/SHA"; break;
374
case 0x000078: cs_str = "TLS/ECDHE-RSA/AES128-CBC/SHA"; break;
376
case 0x000079: cs_str = "TLS/DHE-RSA/AES256-CBC/RMD160"; break;
378
case 0x00007C: cs_str = "TLS/RSA/3DESEDE-CBC/RMD160"; break;
379
case 0x00007D: cs_str = "TLS/RSA/AES128-CBC/RMD160"; break;
380
case 0x00007E: cs_str = "TLS/RSA/AES256-CBC/RMD160"; break;
382
case 0x000080: cs_str = "TLS/GOST341094/GOST28147-OFB/GOST28147"; break;
383
case 0x000081: cs_str = "TLS/GOST34102001/GOST28147-OFB/GOST28147"; break;
384
case 0x000082: cs_str = "TLS/GOST341094/NULL/GOSTR3411"; break;
385
case 0x000083: cs_str = "TLS/GOST34102001/NULL/GOSTR3411"; break;
387
case 0x000084: cs_str = "TLS/RSA/CAMELLIA256-CBC/SHA"; break;
388
case 0x000085: cs_str = "TLS/DH-DSS/CAMELLIA256-CBC/SHA"; break;
389
case 0x000086: cs_str = "TLS/DH-RSA/CAMELLIA256-CBC/SHA"; break;
390
case 0x000087: cs_str = "TLS/DHE-DSS/CAMELLIA256-CBC/SHA"; break;
391
case 0x000088: cs_str = "TLS/DHE-RSA/CAMELLIA256-CBC/SHA"; break;
392
case 0x000089: cs_str = "TLS/DH-ANON/CAMELLIA256-CBC/SHA"; break;
393
case 0x00008A: cs_str = "TLS/PSK/RC4-128/SHA"; break;
394
case 0x00008B: cs_str = "TLS/PSK/3DES-EDE-CBC/SHA"; break;
395
case 0x00008C: cs_str = "TLS/PSK/AES128-CBC/SHA"; break;
396
case 0x00008D: cs_str = "TLS/PSK/AES256-CBC/SHA"; break;
397
case 0x00008E: cs_str = "TLS/DHE-PSK/RC4-128/SHA"; break;
398
case 0x00008F: cs_str = "TLS/DHE-PSK/3DES-EDE-CBC/SHA"; break;
399
case 0x000090: cs_str = "TLS/DHE-PSK/AES128-CBC/SHA"; break;
400
case 0x000091: cs_str = "TLS/DHE-PSK/AES256-CBC/SHA"; break;
401
case 0x000092: cs_str = "TLS/RSA-PSK/RC4-128/SHA"; break;
402
case 0x000093: cs_str = "TLS/RSA-PSK/3DES-EDE-CBC/SHA"; break;
403
case 0x000094: cs_str = "TLS/RSA-PSK/AES128-CBC/SHA"; break;
404
case 0x000095: cs_str = "TLS/RSA-PSK/AES256-CBC/SHA"; break;
405
case 0x000096: cs_str = "TLS/RSA/SEED-CBC/SHA"; break;
406
case 0x000097: cs_str = "TLS/DH-DSS/SEED-CBC/SHA"; break;
407
case 0x000098: cs_str = "TLS/DH-RSA/SEED-CBC/SHA"; break;
408
case 0x000099: cs_str = "TLS/DHE-DSS/SEED-CBC/SHA"; break;
409
case 0x00009A: cs_str = "TLS/DHE-RSA/SEED-CBC/SHA"; break;
410
case 0x00009B: cs_str = "TLS/DH-ANON/SEED-CBC/SHA"; break;
412
case 0x00C001: cs_str = "TLS/ECDH-ECDSA/NULL/SHA"; break;
413
case 0x00C002: cs_str = "TLS/ECDH-ECDSA/RC4-128/SHA"; break;
414
case 0x00C003: cs_str = "TLS/ECDH-ECDSA/3DES-EDE-CBC/SHA"; break;
415
case 0x00C004: cs_str = "TLS/ECDH-ECDSA/AES128-CBC/SHA"; break;
416
case 0x00C005: cs_str = "TLS/ECDH-ECDSA/AES256-CBC/SHA"; break;
417
case 0x00C006: cs_str = "TLS/ECDHE-ECDSA/NULL/SHA"; break;
418
case 0x00C007: cs_str = "TLS/ECDHE-ECDSA/RC4-128/SHA"; break;
419
case 0x00C008: cs_str = "TLS/ECDHE-ECDSA/3DES-EDE-CBC/SHA";break;
420
case 0x00C009: cs_str = "TLS/ECDHE-ECDSA/AES128-CBC/SHA"; break;
421
case 0x00C00A: cs_str = "TLS/ECDHE-ECDSA/AES256-CBC/SHA"; break;
422
case 0x00C00B: cs_str = "TLS/ECDH-RSA/NULL/SHA"; break;
423
case 0x00C00C: cs_str = "TLS/ECDH-RSA/RC4-128/SHA"; break;
424
case 0x00C00D: cs_str = "TLS/ECDH-RSA/3DES-EDE-CBC/SHA"; break;
425
case 0x00C00E: cs_str = "TLS/ECDH-RSA/AES128-CBC/SHA"; break;
426
case 0x00C00F: cs_str = "TLS/ECDH-RSA/AES256-CBC/SHA"; break;
427
case 0x00C010: cs_str = "TLS/ECDHE-RSA/NULL/SHA"; break;
428
case 0x00C011: cs_str = "TLS/ECDHE-RSA/RC4-128/SHA"; break;
429
case 0x00C012: cs_str = "TLS/ECDHE-RSA/3DES-EDE-CBC/SHA"; break;
430
case 0x00C013: cs_str = "TLS/ECDHE-RSA/AES128-CBC/SHA"; break;
431
case 0x00C014: cs_str = "TLS/ECDHE-RSA/AES256-CBC/SHA"; break;
432
case 0x00C015: cs_str = "TLS/ECDH-anon/NULL/SHA"; break;
433
case 0x00C016: cs_str = "TLS/ECDH-anon/RC4-128/SHA"; break;
434
case 0x00C017: cs_str = "TLS/ECDH-anon/3DES-EDE-CBC/SHA"; break;
435
case 0x00C018: cs_str = "TLS/ECDH-anon/AES128-CBC/SHA"; break;
436
case 0x00C019: cs_str = "TLS/ECDH-anon/AES256-CBC/SHA"; break;
438
case 0x00feff: cs_str = "SSL3/RSA-FIPS/3DESEDE-CBC/SHA"; break;
439
case 0x00fefe: cs_str = "SSL3/RSA-FIPS/DES-CBC/SHA"; break;
440
case 0x00ffe1: cs_str = "SSL3/RSA-FIPS/DES56-CBC/SHA"; break;
441
case 0x00ffe0: cs_str = "SSL3/RSA-FIPS/3DES192EDE-CBC/SHA";break;
443
/* the string literal is broken up to avoid trigraphs */
444
default: cs_str = "????" "/????????" "/?????????" "/???"; break;
450
const char * helloExtensionNameString(int ex_num) {
451
const char *ex_name = NULL;
455
case 0: ex_name = "server_name"; break;
456
case 1: ex_name = "max_fragment_length"; break;
457
case 2: ex_name = "client_certificate_url"; break;
458
case 3: ex_name = "trusted_ca_keys"; break;
459
case 4: ex_name = "truncated_hmac"; break;
460
case 5: ex_name = "status_request"; break;
461
case 10: ex_name = "elliptic_curves"; break;
462
case 11: ex_name = "ec_point_formats"; break;
463
default: sprintf(buf, "%d", ex_num); ex_name = (const char *)buf; break;
469
void partial_packet(int thispacket, int size, int needed)
471
PR_fprintf(PR_STDOUT,"(%u bytes", thispacket);
472
if (thispacket < needed) {
473
PR_fprintf(PR_STDOUT,", making %u", size);
475
PR_fprintf(PR_STDOUT," of %u", needed);
477
PR_fprintf(PR_STDOUT,", with %u left over", size - needed);
479
PR_fprintf(PR_STDOUT,")\n");
482
char * get_time_string(void)
490
eol = strchr(cp, '\n');
496
void print_sslv2(DataBufferList *s, unsigned char *tbuf, unsigned int alloclen)
505
chv2 = (ClientHelloV2 *)tbuf;
506
shv2 = (ServerHelloV2 *)tbuf;
507
if (s->isEncrypted) {
508
PR_fprintf(PR_STDOUT," [ssl2] Encrypted {...}\n");
511
PR_fprintf(PR_STDOUT," [%s]", get_time_string() );
514
PR_fprintf(PR_STDOUT," [ssl2] ClientHelloV2 {\n");
515
PR_fprintf(PR_STDOUT," version = {0x%02x, 0x%02x}\n",
516
(PRUint32)chv2->version[0],(PRUint32)chv2->version[1]);
517
PR_fprintf(PR_STDOUT," cipher-specs-length = %d (0x%02x)\n",
518
(PRUint32)(GET_SHORT((chv2->cslength))),
519
(PRUint32)(GET_SHORT((chv2->cslength))));
520
PR_fprintf(PR_STDOUT," sid-length = %d (0x%02x)\n",
521
(PRUint32)(GET_SHORT((chv2->sidlength))),
522
(PRUint32)(GET_SHORT((chv2->sidlength))));
523
PR_fprintf(PR_STDOUT," challenge-length = %d (0x%02x)\n",
524
(PRUint32)(GET_SHORT((chv2->rndlength))),
525
(PRUint32)(GET_SHORT((chv2->rndlength))));
526
PR_fprintf(PR_STDOUT," cipher-suites = { \n");
527
for (p=0;p<GET_SHORT((chv2->cslength));p+=3) {
528
const char *cs_str=NULL;
530
cs_int = GET_24((&chv2->csuites[p]));
531
cs_str = V2CipherString(cs_int);
533
PR_fprintf(PR_STDOUT," (0x%06x) %s\n",
537
PR_fprintf(PR_STDOUT," }\n");
538
if (chv2->sidlength) {
539
PR_fprintf(PR_STDOUT," session-id = { ");
540
for (p=0;p<GET_SHORT((chv2->sidlength));p+=2) {
541
PR_fprintf(PR_STDOUT,"0x%04x ",(PRUint32)(GET_SHORT((&chv2->csuites[p+q]))));
545
PR_fprintf(PR_STDOUT,"}\n");
546
if (chv2->rndlength) {
547
PR_fprintf(PR_STDOUT," challenge = { ");
548
for (p=0;p<GET_SHORT((chv2->rndlength));p+=2) {
549
PR_fprintf(PR_STDOUT,"0x%04x ",(PRUint32)(GET_SHORT((&chv2->csuites[p+q]))));
551
PR_fprintf(PR_STDOUT,"}\n");
553
PR_fprintf(PR_STDOUT,"}\n");
555
/* end of V2 CLientHello Parsing */
557
case 2: /* Client Master Key */
559
const char *cs_str=NULL;
561
ClientMasterKeyV2 *cmkv2;
562
cmkv2 = (ClientMasterKeyV2 *)chv2;
565
PR_fprintf(PR_STDOUT," [ssl2] ClientMasterKeyV2 { \n");
567
cs_int = GET_24(&cmkv2->cipherkind[0]);
568
cs_str = V2CipherString(cs_int);
569
PR_fprintf(PR_STDOUT," cipher-spec-chosen = (0x%06x) %s\n",
572
PR_fprintf(PR_STDOUT," clear-portion = %d bits\n",
573
8*(PRUint32)(GET_SHORT((cmkv2->clearkey))));
575
PR_fprintf(PR_STDOUT," }\n");
576
clientstream.isEncrypted = 1;
577
serverstream.isEncrypted = 1;
583
PR_fprintf(PR_STDOUT," [ssl2] Client Finished V2 {...}\n");
588
case 4: /* V2 Server Hello */
591
PR_fprintf(PR_STDOUT," [ssl2] ServerHelloV2 {\n");
592
PR_fprintf(PR_STDOUT," sid hit = {0x%02x}\n",
593
(PRUintn)shv2->sidhit);
594
PR_fprintf(PR_STDOUT," version = {0x%02x, 0x%02x}\n",
595
(PRUint32)shv2->version[0],(PRUint32)shv2->version[1]);
596
PR_fprintf(PR_STDOUT," cipher-specs-length = %d (0x%02x)\n",
597
(PRUint32)(GET_SHORT((shv2->cslength))),
598
(PRUint32)(GET_SHORT((shv2->cslength))));
599
PR_fprintf(PR_STDOUT," sid-length = %d (0x%02x)\n",
600
(PRUint32)(GET_SHORT((shv2->cidlength))),
601
(PRUint32)(GET_SHORT((shv2->cidlength))));
603
pos = (unsigned char *)shv2;
604
pos += 2; /* skip length header */
605
pos += 11; /* position pointer to Certificate data area */
606
q = GET_SHORT(&shv2->certlength);
610
pos += q; /* skip certificate */
612
PR_fprintf(PR_STDOUT," cipher-suites = { ");
613
len = GET_SHORT((shv2->cslength));
614
for (p = 0; p < len; p += 3) {
615
const char *cs_str=NULL;
617
cs_int = GET_24((pos+p));
618
cs_str = V2CipherString(cs_int);
619
PR_fprintf(PR_STDOUT,"\n ");
620
PR_fprintf(PR_STDOUT,"(0x%06x) %s", cs_int, cs_str);
623
PR_fprintf(PR_STDOUT," }\n"); /* End of cipher suites */
624
len = (PRUint32)GET_SHORT((shv2->cidlength));
626
PR_fprintf(PR_STDOUT," connection-id = { ");
627
for (p = 0; p < len; p += 2) {
628
PR_fprintf(PR_STDOUT,"0x%04x ", (PRUint32)(GET_SHORT((pos + p))));
630
PR_fprintf(PR_STDOUT," }\n"); /* End of connection id */
633
PR_fprintf(PR_STDOUT,"\n }\n"); /* end of ServerHelloV2 */
635
clientstream.isEncrypted = 1;
636
serverstream.isEncrypted = 1;
641
PR_fprintf(PR_STDOUT," [ssl2] Server Verify V2 {...}\n");
646
PR_fprintf(PR_STDOUT," [ssl2] Server Finished V2 {...}\n");
651
PR_fprintf(PR_STDOUT," [ssl2] Request Certificate V2 {...}\n");
656
PR_fprintf(PR_STDOUT," [ssl2] Client Certificate V2 {...}\n");
661
PR_fprintf(PR_STDOUT," [ssl2] UnknownType 0x%02x {...}\n",
662
(PRUint32)chv2->type);
669
unsigned int print_hello_extension(unsigned char * hsdata,
673
/* pretty print extensions, if any */
675
int exListLen = GET_SHORT((hsdata+pos)); pos += 2;
676
PR_fprintf(PR_STDOUT,
677
" extensions[%d] = {\n", exListLen);
678
while (exListLen > 0 && pos < length) {
680
int exType = GET_SHORT((hsdata+pos)); pos += 2;
681
exLen = GET_SHORT((hsdata+pos)); pos += 2;
682
/* dump the extension */
683
PR_fprintf(PR_STDOUT,
684
" extension type %s, length [%d]",
685
helloExtensionNameString(exType), exLen);
687
PR_fprintf(PR_STDOUT, " = {\n");
688
print_hex(exLen, hsdata + pos);
689
PR_fprintf(PR_STDOUT, " }\n");
691
PR_fprintf(PR_STDOUT, "\n");
694
exListLen -= 2 + exLen;
696
PR_fprintf(PR_STDOUT," }\n");
702
void print_ssl3_handshake(unsigned char *tbuf,
703
unsigned int alloclen,
706
struct sslhandshake sslh;
707
unsigned char * hsdata;
710
PR_fprintf(PR_STDOUT," handshake {\n");
712
while (offset < alloclen) {
713
sslh.type = tbuf[offset];
714
sslh.length = GET_24(tbuf+offset+1);
715
hsdata= &tbuf[offset+4];
717
if (sslhexparse) print_hex(4,tbuf+offset);
719
PR_fprintf(PR_STDOUT," type = %d (",sslh.type);
721
case 0: PR_FPUTS("hello_request)\n" ); break;
722
case 1: PR_FPUTS("client_hello)\n" ); break;
723
case 2: PR_FPUTS("server_hello)\n" ); break;
724
case 11: PR_FPUTS("certificate)\n" ); break;
725
case 12: PR_FPUTS("server_key_exchange)\n" ); break;
726
case 13: PR_FPUTS("certificate_request)\n" ); break;
727
case 14: PR_FPUTS("server_hello_done)\n" ); break;
728
case 15: PR_FPUTS("certificate_verify)\n" ); break;
729
case 16: PR_FPUTS("client_key_exchange)\n" ); break;
730
case 20: PR_FPUTS("finished)\n" ); break;
731
default: PR_FPUTS("unknown)\n" ); break;
734
PR_fprintf(PR_STDOUT," length = %d (0x%06x)\n",sslh.length,sslh.length);
737
case 0: /* hello_request */ /* not much to show here. */ break;
739
case 1: /* client hello */
740
switch (sr->ver_maj) {
741
case 3: /* ssl version 3 */
746
PR_fprintf(PR_STDOUT," ClientHelloV3 {\n");
747
PR_fprintf(PR_STDOUT," client_version = {%d, %d}\n",
748
(PRUint8)hsdata[0],(PRUint8)hsdata[1]);
749
PR_fprintf(PR_STDOUT," random = {...}\n");
750
if (sslhexparse) print_hex(32,&hsdata[2]);
752
/* pretty print Session ID */
754
int sidlength = (int)hsdata[2+32];
755
PR_fprintf(PR_STDOUT," session ID = {\n");
756
PR_fprintf(PR_STDOUT," length = %d\n",sidlength);
757
PR_fprintf(PR_STDOUT," contents = {..}\n");
758
if (sslhexparse) print_hex(sidlength,&hsdata[2+32+1]);
759
PR_fprintf(PR_STDOUT," }\n");
760
pos = 2+32+1+sidlength;
763
/* pretty print cipher suites */
765
int csuitelength = GET_SHORT((hsdata+pos));
766
PR_fprintf(PR_STDOUT," cipher_suites[%d] = { \n",
768
if (csuitelength % 2) {
769
PR_fprintf(PR_STDOUT,
770
"*error in protocol - csuitelength shouldn't be odd*\n");
772
for (w=0; w<csuitelength; w+=2) {
773
const char *cs_str=NULL;
775
cs_int = GET_SHORT((hsdata+pos+2+w));
776
cs_str = V2CipherString(cs_int);
777
PR_fprintf(PR_STDOUT,
778
" (0x%04x) %s\n", cs_int, cs_str);
780
pos += 2 + csuitelength;
781
PR_fprintf(PR_STDOUT," }\n");
784
/* pretty print compression methods */
786
int complength = hsdata[pos];
787
PR_fprintf(PR_STDOUT," compression[%d] = {",
789
for (w=0; w < complength; w++) {
790
PR_fprintf(PR_STDOUT, " %02x", hsdata[pos+1+w]);
792
pos += 1 + complength;
793
PR_fprintf(PR_STDOUT," }\n");
796
/* pretty print extensions, if any */
797
pos = print_hello_extension(hsdata, sslh.length, pos);
799
PR_fprintf(PR_STDOUT," }\n");
800
} /* end of ssl version 3 */
803
PR_fprintf(PR_STDOUT," UNDEFINED VERSION %d.%d {...}\n",
804
sr->ver_maj, sr->ver_min );
805
if (sslhexparse) print_hex(sslh.length, hsdata);
807
} /* end of switch sr->ver_maj */
810
case 2: /* server hello */
812
unsigned int sidlength, pos;
814
PR_fprintf(PR_STDOUT," ServerHello {\n");
816
PR_fprintf(PR_STDOUT," server_version = {%d, %d}\n",
817
(PRUint8)hsdata[0],(PRUint8)hsdata[1]);
818
PR_fprintf(PR_STDOUT," random = {...}\n");
819
if (sslhexparse) print_hex(32,&hsdata[2]);
820
PR_fprintf(PR_STDOUT," session ID = {\n");
821
sidlength = (int)hsdata[2+32];
822
PR_fprintf(PR_STDOUT," length = %d\n",sidlength);
823
PR_fprintf(PR_STDOUT," contents = {..}\n");
824
if (sslhexparse) print_hex(sidlength,&hsdata[2+32+1]);
825
PR_fprintf(PR_STDOUT," }\n");
826
pos = 2+32+1+sidlength;
828
/* pretty print chosen cipher suite */
830
PRUint32 cs_int = GET_SHORT((hsdata+pos));
831
const char *cs_str = V2CipherString(cs_int);
832
PR_fprintf(PR_STDOUT," cipher_suite = (0x%04x) %s\n",
836
PR_fprintf(PR_STDOUT, " compression method = %02x\n",
839
/* pretty print extensions, if any */
840
pos = print_hello_extension(hsdata, sslh.length, pos);
842
PR_fprintf(PR_STDOUT," }\n");
846
case 11: /* certificate */
852
int certbytesread = 0;
853
static int certFileNumber;
854
char certFileName[20];
856
PR_fprintf(PR_STDOUT," CertificateChain {\n");
857
certslength = GET_24(hsdata);
858
PR_fprintf(PR_STDOUT," chainlength = %d (0x%04x)\n",
859
certslength,certslength);
861
while (certbytesread < certslength) {
862
certlength = GET_24((hsdata+pos));
864
PR_fprintf(PR_STDOUT," Certificate {\n");
865
PR_fprintf(PR_STDOUT," size = %d (0x%04x)\n",
866
certlength,certlength);
868
PR_snprintf(certFileName, sizeof certFileName, "cert.%03d",
870
cfd = PR_Open(certFileName, PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE,
873
PR_fprintf(PR_STDOUT,
874
" data = { couldn't save file '%s' }\n",
877
PR_Write(cfd, (hsdata+pos), certlength);
878
PR_fprintf(PR_STDOUT,
879
" data = { saved in file '%s' }\n",
884
PR_fprintf(PR_STDOUT," }\n");
886
certbytesread += certlength+3;
888
PR_fprintf(PR_STDOUT," }\n");
892
case 12: /* server_key_exchange */
893
if (sslhexparse) print_hex(sslh.length, hsdata);
896
case 13: /* certificate request */
898
unsigned int pos = 0;
901
PR_fprintf(PR_STDOUT," CertificateRequest {\n");
903
/* pretty print requested certificate types */
904
reqLength = hsdata[pos];
905
PR_fprintf(PR_STDOUT," certificate types[%d] = {",
907
for (w=0; w < reqLength; w++) {
908
PR_fprintf(PR_STDOUT, " %02x", hsdata[pos+1+w]);
910
pos += 1 + reqLength;
911
PR_fprintf(PR_STDOUT," }\n");
913
/* pretty print CA names, if any */
914
if (pos < sslh.length) {
915
int exListLen = GET_SHORT((hsdata+pos)); pos += 2;
916
PR_fprintf(PR_STDOUT,
917
" certificate_authorities[%d] = {\n",
919
while (exListLen > 0 && pos < sslh.length) {
922
int dnLen = GET_SHORT((hsdata+pos)); pos += 2;
924
/* dump the CA name */
926
it.data = hsdata + pos;
928
ca_name = CERT_DerNameToAscii(&it);
930
PR_fprintf(PR_STDOUT," %s\n", ca_name);
933
PR_fprintf(PR_STDOUT,
934
" distinguished name [%d]", dnLen);
935
if (dnLen > 0 && sslhexparse) {
936
PR_fprintf(PR_STDOUT, " = {\n");
937
print_hex(dnLen, hsdata + pos);
938
PR_fprintf(PR_STDOUT, " }\n");
940
PR_fprintf(PR_STDOUT, "\n");
944
exListLen -= 2 + dnLen;
946
PR_fprintf(PR_STDOUT," }\n");
949
PR_fprintf(PR_STDOUT," }\n");
953
case 14: /* server_hello_done */ /* not much to show here. */ break;
955
case 15: /* certificate_verify */
956
if (sslhexparse) print_hex(sslh.length, hsdata);
959
case 16: /* client key exchange */
961
PR_fprintf(PR_STDOUT," ClientKeyExchange {\n");
962
PR_fprintf(PR_STDOUT," message = {...}\n");
963
PR_fprintf(PR_STDOUT," }\n");
967
case 20: /* finished */
968
if (sslhexparse) print_hex(sslh.length, hsdata);
973
PR_fprintf(PR_STDOUT," UNKNOWN MESSAGE TYPE %d [%d] {\n",
974
sslh.type, sslh.length);
975
if (sslhexparse) print_hex(sslh.length, hsdata);
976
PR_fprintf(PR_STDOUT," }\n");
979
} /* end of switch sslh.type */
980
offset += sslh.length + 4; /* +4 because of length (3 bytes) and type (1 byte) */
982
PR_fprintf(PR_STDOUT," }\n");
986
void print_ssl(DataBufferList *s, int length, unsigned char *buffer)
988
/* -------------------------------------------------------- */
989
/* first, create a new buffer object for this piece of data. */
994
if (s->size == 0 && length > 0 && buffer[0] >= 32 && buffer[0] < 128) {
995
/* Not an SSL record, treat entire buffer as plaintext */
996
PR_Write(PR_STDOUT,buffer,length);
1006
db = PR_NEW(struct _DataBuffer);
1008
db->buffer = (unsigned char*)PR_Malloc(length);
1009
db->length = length;
1011
memcpy(db->buffer, buffer, length);
1014
/* now, add it to the stream */
1016
if (s->last != NULL) s->last->next = db;
1019
if (s->first == NULL) s->first = db;
1023
/*------------------------------------------------------- */
1024
/* now we look at the stream to see if we have enough data to
1027
while (s->size > 0 ) {
1028
unsigned char *tbuf = NULL;
1032
unsigned recordsize;
1036
if ( s->first == NULL) {
1037
PR_fprintf(PR_STDOUT,"ERROR: s->first is null\n");
1041
/* in the case of an SSL 2 client-hello (which is all ssltap supports) */
1042
/* will have the high-bit set, whereas an SSL 3 client-hello will not */
1043
/* SSL2 can also send records that begin with the high bit clear.
1044
* This code will incorrectly handle them. XXX
1046
if (isV2Session || s->first->buffer[s->first->offset] & 0x80) {
1047
/* it's an SSL 2 packet */
1048
unsigned char lenbuf[3];
1050
/* first, we check if there's enough data for it to be an SSL2-type
1051
* record. What a pain.*/
1052
if (s->size < sizeof lenbuf) {
1053
partial_packet(length, s->size, sizeof lenbuf);
1057
/* read the first two bytes off the stream. */
1058
read_stream_bytes(lenbuf, s, sizeof(lenbuf));
1059
alloclen = ((unsigned int)(lenbuf[0] & 0x7f) << 8) + lenbuf[1] +
1060
((lenbuf[0] & 0x80) ? 2 : 3);
1061
PR_fprintf(PR_STDOUT, "alloclen = %u bytes\n", alloclen);
1063
/* put 'em back on the head of the stream. */
1064
db = PR_NEW(struct _DataBuffer);
1066
db->length = sizeof lenbuf;
1067
db->buffer = (unsigned char*) PR_Malloc(db->length);
1069
memcpy(db->buffer, lenbuf, sizeof lenbuf);
1071
db->next = s->first;
1073
if (s->last == NULL)
1075
s->size += db->length;
1077
/* if there wasn't enough, go back for more. */
1078
if (s->size < alloclen) {
1080
partial_packet(length, s->size, alloclen);
1083
partial_packet(length, s->size, alloclen);
1085
/* read in the whole record. */
1086
tbuf = PR_Malloc(alloclen);
1087
read_stream_bytes(tbuf, s, alloclen);
1089
print_sslv2(s, tbuf, alloclen);
1096
/***********************************************************/
1098
/***********************************************************/
1101
if (s->size < sizeof(SSLRecord)) {
1102
partial_packet(length, s->size, sizeof(SSLRecord));
1106
read_stream_bytes((unsigned char *)&sr, s, sizeof sr);
1108
/* we have read the stream bytes. Look at the length of
1109
the ssl record. If we don't have enough data to satisfy this
1110
request, then put the bytes we just took back at the head
1112
recordsize = GET_SHORT(sr.length);
1114
if (recordsize > s->size) {
1115
db = PR_NEW(struct _DataBuffer);
1117
db->length = sizeof sr;
1118
db->buffer = (unsigned char*) PR_Malloc(db->length);
1120
memcpy(db->buffer, &sr, sizeof sr);
1121
db->next = s->first;
1123
/* now, add it back on to the head of the stream */
1126
if (s->last == NULL)
1128
s->size += db->length;
1131
partial_packet(length, s->size, recordsize);
1134
partial_packet(length, s->size, recordsize);
1137
PR_fprintf(PR_STDOUT,"SSLRecord { [%s]\n", get_time_string() );
1139
print_hex(5,(unsigned char*)&sr);
1144
PR_fprintf(PR_STDOUT," type = %d (",sr.type);
1147
PR_fprintf(PR_STDOUT,"change_cipher_spec)\n");
1150
PR_fprintf(PR_STDOUT,"alert)\n");
1153
PR_fprintf(PR_STDOUT,"handshake)\n");
1156
PR_fprintf(PR_STDOUT,"application_data)\n");
1159
PR_fprintf(PR_STDOUT,"unknown)\n");
1162
PR_fprintf(PR_STDOUT," version = { %d,%d }\n",
1163
(PRUint32)sr.ver_maj,(PRUint32)sr.ver_min);
1164
PR_fprintf(PR_STDOUT," length = %d (0x%x)\n",
1165
(PRUint32)GET_SHORT(sr.length), (PRUint32)GET_SHORT(sr.length));
1168
alloclen = recordsize;
1169
PR_ASSERT(s->size >= alloclen);
1170
if (s->size >= alloclen) {
1171
tbuf = (unsigned char*) PR_Malloc(alloclen);
1172
read_stream_bytes(tbuf, s, alloclen);
1174
if (s->isEncrypted) {
1175
PR_fprintf(PR_STDOUT," < encrypted >\n");
1179
case 20 : /* change_cipher_spec */
1180
if (sslhexparse) print_hex(alloclen,tbuf);
1181
s->isEncrypted = 1; /* mark to say we can only dump hex form now on */
1184
case 21 : /* alert */
1186
case 1: PR_fprintf(PR_STDOUT, " warning: "); break;
1187
case 2: PR_fprintf(PR_STDOUT, " fatal: "); break;
1188
default: PR_fprintf(PR_STDOUT, " unknown level %d: ", tbuf[0]); break;
1192
case 0: PR_FPUTS("close_notify\n" ); break;
1193
case 10: PR_FPUTS("unexpected_message\n" ); break;
1194
case 20: PR_FPUTS("bad_record_mac\n" ); break;
1195
case 21: PR_FPUTS("decryption_failed\n" ); break;
1196
case 22: PR_FPUTS("record_overflow\n" ); break;
1197
case 30: PR_FPUTS("decompression_failure\n" ); break;
1198
case 40: PR_FPUTS("handshake_failure\n" ); break;
1199
case 41: PR_FPUTS("no_certificate\n" ); break;
1200
case 42: PR_FPUTS("bad_certificate\n" ); break;
1201
case 43: PR_FPUTS("unsupported_certificate\n" ); break;
1202
case 44: PR_FPUTS("certificate_revoked\n" ); break;
1203
case 45: PR_FPUTS("certificate_expired\n" ); break;
1204
case 46: PR_FPUTS("certificate_unknown\n" ); break;
1205
case 47: PR_FPUTS("illegal_parameter\n" ); break;
1206
case 48: PR_FPUTS("unknown_ca\n" ); break;
1207
case 49: PR_FPUTS("access_denied\n" ); break;
1208
case 50: PR_FPUTS("decode_error\n" ); break;
1209
case 51: PR_FPUTS("decrypt_error\n" ); break;
1210
case 60: PR_FPUTS("export_restriction\n" ); break;
1211
case 70: PR_FPUTS("protocol_version\n" ); break;
1212
case 71: PR_FPUTS("insufficient_security\n" ); break;
1213
case 80: PR_FPUTS("internal_error\n" ); break;
1214
case 90: PR_FPUTS("user_canceled\n" ); break;
1215
case 100: PR_FPUTS("no_renegotiation\n" ); break;
1216
case 110: PR_FPUTS("unsupported_extension\n" ); break;
1217
case 111: PR_FPUTS("certificate_unobtainable\n" ); break;
1218
case 112: PR_FPUTS("unrecognized_name\n" ); break;
1219
case 113: PR_FPUTS("bad_certificate_status_response\n" ); break;
1220
case 114: PR_FPUTS("bad_certificate_hash_value\n" ); break;
1222
default: PR_fprintf(PR_STDOUT, "unknown alert %d\n", tbuf[1]); break;
1225
if (sslhexparse) print_hex(alloclen,tbuf);
1228
case 22 : /* handshake */
1229
print_ssl3_handshake( tbuf, alloclen, &sr );
1232
case 23 : /* application data */
1234
print_hex(alloclen,tbuf);
1238
PR_fprintf(PR_STDOUT,"}\n");
1244
void print_hex(int amt, unsigned char *buf) {
1247
static char string[5000];
1250
for(i=0;i<amt;i++) {
1253
if (i%16 ==0) { /* if we are at the beginning of a line */
1254
PR_fprintf(PR_STDOUT,"%4x:",i); /* print the line number */
1259
PR_fprintf(PR_STDOUT," ");
1264
t[0] = (j >= 0x20 && j < 0x80) ? j : '.';
1281
PR_fprintf(PR_STDOUT,"%02x ",(PRUint8) buf[i]);
1283
/* if we've reached the end of the line - add the string */
1284
if (i%16 == 15) PR_fprintf(PR_STDOUT," | %s\n",string);
1286
/* we reached the end of the buffer,*/
1287
/* do we have buffer left over? */
1290
for (k=0;k<(16-j);k++) PR_fprintf(PR_STDOUT," ");
1291
PR_fprintf(PR_STDOUT," |%s\n",string);
1296
PR_fprintf(PR_STDERR, "SSLTAP (C) 1997, 1998 Netscape Communications Corporation.\n");
1297
PR_fprintf(PR_STDERR, "Usage: ssltap [-vhfsxl] [-p port] hostname:port\n");
1298
PR_fprintf(PR_STDERR, " -v [prints version string]\n");
1299
PR_fprintf(PR_STDERR, " -h [outputs hex instead of ASCII]\n");
1300
PR_fprintf(PR_STDERR, " -f [turn on Fancy HTML coloring]\n");
1301
PR_fprintf(PR_STDERR, " -s [turn on SSL decoding]\n");
1302
PR_fprintf(PR_STDERR, " -x [turn on extra SSL hex dumps]\n");
1303
PR_fprintf(PR_STDERR, " -p port [specify rendezvous port (default 1924)]\n");
1304
PR_fprintf(PR_STDERR, " -l [loop - continue to wait for more connections]\n");
1310
showErr(const char * msg) {
1311
PRErrorCode err = PR_GetError();
1312
const char * errString;
1314
if (err == PR_UNKNOWN_ERROR)
1315
err = PR_CONNECT_RESET_ERROR; /* bug in NSPR. */
1316
errString = SECU_Strerror(err);
1319
errString = "(no text available)";
1320
PR_fprintf(PR_STDERR, "Error %d: %s: %s", err, errString, msg);
1323
int main(int argc, char *argv[])
1325
char *hostname=NULL;
1326
PRUint16 rendport=DEFPORT,port;
1329
PRNetAddr na_client,na_server,na_rend;
1330
PRFileDesc *s_server,*s_client,*s_rend; /*rendezvous */
1331
char netdbbuf[PR_NETDB_BUF_SIZE];
1333
PLOptState *optstate;
1337
optstate = PL_CreateOptState(argc,argv,"fvxhslp:");
1338
while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
1339
switch (optstate->option) {
1347
PR_fprintf(PR_STDOUT,"Version: %s\n",VERSIONSTRING);
1359
rendport = atoi(optstate->value);
1362
hostname = PL_strdup(optstate->value);
1365
if (status == PL_OPT_BAD)
1369
if (!hexparse && !sslparse) {
1370
PR_fprintf(PR_STDERR,
1371
"Note: use of -f without -s or -h not recommended, \n"
1372
"as the output looks a little strange. It may be useful, however\n");
1376
if(! hostname ) Usage(), exit(2);
1379
char *colon = (char *)strchr(hostname, ':');
1381
PR_fprintf(PR_STDERR,
1382
"You must specify the host AND port you wish to connect to\n");
1385
port = atoi(&colon[1]);
1389
PR_fprintf(PR_STDERR, "Port must be a nonzero number.\n");
1394
/* find the 'server' IP address so we don't have to look it up later */
1397
PR_fprintf(PR_STDOUT,"<HTML><HEAD><TITLE>SSLTAP output</TITLE></HEAD>\n");
1398
PR_fprintf(PR_STDOUT,"<BODY><PRE>\n");
1400
PR_fprintf(PR_STDERR,"Looking up \"%s\"...\n", hostname);
1401
r = PR_GetHostByName(hostname,netdbbuf,PR_NETDB_BUF_SIZE,&hp);
1403
showErr("Host Name lookup failed\n");
1407
PR_EnumerateHostEnt(0,&hp,0,&na_server);
1408
PR_InitializeNetAddr(PR_IpAddrNull,port,&na_server);
1409
/* set up the port which the client will connect to */
1411
r = PR_InitializeNetAddr(PR_IpAddrAny,rendport,&na_rend);
1412
if (r == PR_FAILURE) {
1413
PR_fprintf(PR_STDERR,
1414
"PR_InitializeNetAddr(,%d,) failed with error %d\n",PR_GetError());
1418
rv = NSS_NoDB_Init("");
1419
if (rv != SECSuccess) {
1420
PR_fprintf(PR_STDERR,
1421
"NSS_NoDB_Init() failed with error %d\n",PR_GetError());
1425
s_rend = PR_NewTCPSocket();
1427
showErr("Couldn't create socket\n");
1431
if (PR_Bind(s_rend, &na_rend )) {
1432
PR_fprintf(PR_STDERR,"Couldn't bind to port %d (error %d)\n",rendport, PR_GetError());
1436
if ( PR_Listen(s_rend, 5)) {
1437
showErr("Couldn't listen\n");
1441
PR_fprintf(PR_STDERR,"Proxy socket ready and listening\n");
1442
do { /* accept one connection and process it. */
1445
s_client = PR_Accept(s_rend,&na_client,PR_SecondsToInterval(3600));
1446
if (s_client == NULL) {
1447
showErr("accept timed out\n");
1451
s_server = PR_NewTCPSocket();
1452
if (s_server == NULL) {
1453
showErr("couldn't open new socket to connect to server \n");
1457
r = PR_Connect(s_server,&na_server,PR_SecondsToInterval(5));
1459
if ( r == PR_FAILURE )
1461
showErr("Couldn't connect\n");
1466
if (fancy) PR_fprintf(PR_STDOUT,"<p><HR><H2>");
1467
PR_fprintf(PR_STDOUT,"Connection #%d [%s]\n", c_count+1,
1469
if (fancy) PR_fprintf(PR_STDOUT,"</H2>");
1473
PR_fprintf(PR_STDOUT,"Connected to %s:%d\n", hostname, port);
1478
pds[PD_C].fd = s_client;
1479
pds[PD_S].fd = s_server;
1480
pds[PD_C].in_flags = PR_POLL_READ;
1481
pds[PD_S].in_flags = PR_POLL_READ;
1483
/* make sure the new connections don't start out encrypted. */
1484
clientstream.isEncrypted = 0;
1485
serverstream.isEncrypted = 0;
1488
while( (pds[PD_C].in_flags & PR_POLL_READ) != 0 ||
1489
(pds[PD_S].in_flags & PR_POLL_READ) != 0 )
1490
{ /* Handle all messages on the connection */
1493
unsigned char buffer[ TAPBUFSIZ ];
1495
amt = PR_Poll(pds,2,PR_INTERVAL_NO_TIMEOUT);
1498
showErr( "PR_Poll failed.\n");
1500
showErr( "PR_Poll timed out.\n");
1504
if (pds[PD_C].out_flags & PR_POLL_EXCEPT) {
1505
showErr( "Exception on client-side socket.\n");
1509
if (pds[PD_S].out_flags & PR_POLL_EXCEPT) {
1510
showErr( "Exception on server-side socket.\n");
1515
/* read data, copy it to stdout, and write to other socket */
1517
if ((pds[PD_C].in_flags & PR_POLL_READ) != 0 &&
1518
(pds[PD_C].out_flags & PR_POLL_READ) != 0 ) {
1520
amt = PR_Read(s_client, buffer, sizeof(buffer));
1523
showErr( "Client socket read failed.\n");
1528
PR_fprintf(PR_STDOUT, "Read EOF on Client socket. [%s]\n",
1529
get_time_string() );
1530
pds[PD_C].in_flags &= ~PR_POLL_READ;
1531
PR_Shutdown(s_server, PR_SHUTDOWN_SEND);
1535
PR_fprintf(PR_STDOUT,"--> [\n");
1536
if (fancy) PR_fprintf(PR_STDOUT,"<font color=blue>");
1538
if (hexparse) print_hex(amt, buffer);
1539
if (sslparse) print_ssl(&clientstream,amt,buffer);
1540
if (!hexparse && !sslparse) PR_Write(PR_STDOUT,buffer,amt);
1541
if (fancy) PR_fprintf(PR_STDOUT,"</font>");
1542
PR_fprintf(PR_STDOUT,"]\n");
1544
wrote = PR_Write(s_server, buffer, amt);
1545
if (wrote != amt ) {
1547
showErr("Write to server socket failed.\n");
1550
PR_fprintf(PR_STDERR, "Short write to server socket!\n");
1553
} /* end of read from client socket. */
1555
/* read data, copy it to stdout, and write to other socket */
1556
if ((pds[PD_S].in_flags & PR_POLL_READ) != 0 &&
1557
(pds[PD_S].out_flags & PR_POLL_READ) != 0 ) {
1559
amt = PR_Read(s_server, buffer, sizeof(buffer));
1562
showErr( "error on server-side socket.\n");
1567
PR_fprintf(PR_STDOUT, "Read EOF on Server socket. [%s]\n",
1568
get_time_string() );
1569
pds[PD_S].in_flags &= ~PR_POLL_READ;
1570
PR_Shutdown(s_client, PR_SHUTDOWN_SEND);
1574
PR_fprintf(PR_STDOUT,"<-- [\n");
1575
if (fancy) PR_fprintf(PR_STDOUT,"<font color=red>");
1576
if (hexparse) print_hex(amt, (unsigned char *)buffer);
1577
if (sslparse) print_ssl(&serverstream,amt,(unsigned char *)buffer);
1578
if (!hexparse && !sslparse) PR_Write(PR_STDOUT,buffer,amt);
1579
if (fancy) PR_fprintf(PR_STDOUT,"</font>");
1580
PR_fprintf(PR_STDOUT,"]\n");
1583
wrote = PR_Write(s_client, buffer, amt);
1584
if (wrote != amt ) {
1586
showErr("Write to client socket failed.\n");
1589
PR_fprintf(PR_STDERR, "Short write to client socket!\n");
1593
} /* end of read from server socket. */
1595
/* Loop, handle next message. */
1597
} /* handle messages during a connection loop */
1600
flush_stream(&clientstream);
1601
flush_stream(&serverstream);
1604
PR_fprintf(PR_STDERR,"Connection %d Complete [%s]\n", c_count,
1605
get_time_string() );
1606
} while (looparound); /* accept connection and process it. */