Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 /*
6 * ssltap.c
7 *
8 * Version 1.0 : Frederick Roeber : 11 June 1997
9 * Version 2.0 : Steve Parkinson : 13 November 1997
10 * Version 3.0 : Nelson Bolyard : 22 July 1998
11 * Version 3.1 : Nelson Bolyard : 24 May 1999
12 *
13 * changes in version 2.0:
14 * Uses NSPR20
15 * Shows structure of SSL negotiation, if enabled.
16 *
17 * This "proxies" a socket connection (like a socks tunnel), but displays the
18 * data is it flies by.
19 *
20 * In the code, the 'client' socket is the one on the client side of the
21 * proxy, and the server socket is on the server side.
22 *
23 */
25 #include "nspr.h"
26 #include "plstr.h"
27 #include "secutil.h"
28 #include <memory.h> /* for memcpy, etc. */
29 #include <string.h>
30 #include <time.h>
32 #include "plgetopt.h"
33 #include "nss.h"
34 #include "cert.h"
35 #include "sslproto.h"
36 #include "ocsp.h"
37 #include "ocspti.h" /* internals for pretty-printing routines *only* */
39 struct _DataBufferList;
40 struct _DataBuffer;
42 typedef struct _DataBufferList {
43 struct _DataBuffer *first,*last;
44 int size;
45 int isEncrypted;
46 unsigned char * msgBuf;
47 int msgBufOffset;
48 int msgBufSize;
49 int hMACsize;
50 } DataBufferList;
52 typedef struct _DataBuffer {
53 unsigned char *buffer;
54 int length;
55 int offset; /* offset of first good byte */
56 struct _DataBuffer *next;
57 } DataBuffer;
61 struct sslhandshake {
62 PRUint8 type;
63 PRUint32 length;
64 };
66 typedef struct _SSLRecord {
67 PRUint8 type;
68 PRUint8 ver_maj,ver_min;
70 PRUint8 length[2];
71 } SSLRecord;
73 typedef struct _ClientHelloV2 {
74 PRUint8 length[2];
75 PRUint8 type;
76 PRUint8 version[2];
77 PRUint8 cslength[2];
78 PRUint8 sidlength[2];
79 PRUint8 rndlength[2];
80 PRUint8 csuites[1];
81 } ClientHelloV2;
83 typedef struct _ServerHelloV2 {
84 PRUint8 length[2];
85 PRUint8 type;
86 PRUint8 sidhit;
87 PRUint8 certtype;
88 PRUint8 version[2];
89 PRUint8 certlength[2];
90 PRUint8 cslength[2];
91 PRUint8 cidlength[2];
92 } ServerHelloV2;
94 typedef struct _ClientMasterKeyV2 {
95 PRUint8 length[2];
96 PRUint8 type;
98 PRUint8 cipherkind[3];
99 PRUint8 clearkey[2];
100 PRUint8 secretkey[2];
102 } ClientMasterKeyV2;
104 /* forward declaration */
105 void showErr(const char * msg);
107 #define TAPBUFSIZ 16384
109 #define DEFPORT 1924
110 #include <ctype.h>
112 const char * progName;
113 int hexparse=0;
114 int sslparse=0;
115 int sslhexparse=0;
116 int looparound=0;
117 int fancy=0;
118 int isV2Session=0;
119 int currentcipher=0;
120 DataBufferList clientstream, serverstream;
122 #define PR_FPUTS(x) PR_fprintf(PR_STDOUT, x )
124 #define GET_SHORT(x) ((PRUint16)(((PRUint16)((PRUint8*)x)[0]) << 8) + ((PRUint16)((PRUint8*)x)[1]))
125 #define GET_24(x) ((PRUint32) ( \
126 (((PRUint32)((PRUint8*)x)[0]) << 16) \
127 + \
128 (((PRUint32)((PRUint8*)x)[1]) << 8) \
129 + \
130 (((PRUint32)((PRUint8*)x)[2]) << 0) \
131 ) )
132 #define GET_32(x) ((PRUint32) ( \
133 (((PRUint32)((PRUint8*)x)[0]) << 24) \
134 + \
135 (((PRUint32)((PRUint8*)x)[1]) << 16) \
136 + \
137 (((PRUint32)((PRUint8*)x)[2]) << 8) \
138 + \
139 (((PRUint32)((PRUint8*)x)[3]) << 0) \
140 ) )
142 void print_hex(int amt, unsigned char *buf);
143 void read_stream_bytes(unsigned char *d, DataBufferList *db, int length);
145 void myhalt(int dblsize,int collectedsize)
146 {
148 PR_fprintf(PR_STDERR,"HALTED\n");
149 PR_ASSERT(dblsize == collectedsize);
150 exit(13);
151 }
153 const char *get_error_text(int error)
154 {
155 switch (error) {
156 case PR_IO_TIMEOUT_ERROR:
157 return "Timeout";
158 break;
159 case PR_CONNECT_REFUSED_ERROR:
160 return "Connection refused";
161 break;
162 case PR_NETWORK_UNREACHABLE_ERROR:
163 return "Network unreachable";
164 break;
165 case PR_BAD_ADDRESS_ERROR:
166 return "Bad address";
167 break;
168 case PR_CONNECT_RESET_ERROR:
169 return "Connection reset";
170 break;
171 case PR_PIPE_ERROR:
172 return "Pipe error";
173 break;
174 }
176 return "";
177 }
183 void check_integrity(DataBufferList *dbl)
184 {
185 DataBuffer *db;
186 int i;
188 db = dbl->first;
189 i =0;
190 while (db) {
191 i+= db->length - db->offset;
192 db = db->next;
193 }
194 if (i != dbl->size) {
195 myhalt(dbl->size,i);
196 }
197 }
199 /* Free's the DataBuffer at the head of the list and returns the pointer
200 * to the new head of the list.
201 */
202 DataBuffer *
203 free_head(DataBufferList *dbl)
204 {
205 DataBuffer *db = dbl->first;
206 PR_ASSERT(db->offset >= db->length);
207 if (db->offset >= db->length) {
208 dbl->first = db->next;
209 if (dbl->first == NULL) {
210 dbl->last = NULL;
211 }
212 PORT_Free(db->buffer);
213 PORT_Free(db);
214 db = dbl->first;
215 }
216 return db;
217 }
219 void
220 read_stream_bytes(unsigned char *d, DataBufferList *dbl, int length)
221 {
222 int copied = 0;
223 DataBuffer *db = dbl->first;
225 if (!db) {
226 PR_fprintf(PR_STDERR,"assert failed - dbl->first is null\n");
227 exit(8);
228 }
229 while (length) {
230 int toCopy;
231 /* find the number of bytes to copy from the head buffer */
232 /* if there's too many in this buffer, then only copy 'length' */
233 toCopy = PR_MIN(db->length - db->offset, length);
235 memcpy(d + copied, db->buffer + db->offset, toCopy);
236 copied += toCopy;
237 db->offset += toCopy;
238 length -= toCopy;
239 dbl->size -= toCopy;
241 /* if we emptied the head buffer */
242 if (db->offset >= db->length) {
243 db = free_head(dbl);
244 }
245 }
247 check_integrity(dbl);
249 }
251 void
252 flush_stream(DataBufferList *dbl)
253 {
254 DataBuffer *db = dbl->first;
255 check_integrity(dbl);
256 while (db) {
257 db->offset = db->length;
258 db = free_head(dbl);
259 }
260 dbl->size = 0;
261 check_integrity(dbl);
262 if (dbl->msgBuf) {
263 PORT_Free(dbl->msgBuf);
264 dbl->msgBuf = NULL;
265 }
266 dbl->msgBufOffset = 0;
267 dbl->msgBufSize = 0;
268 dbl->hMACsize = 0;
269 }
272 const char * V2CipherString(int cs_int)
273 {
274 char *cs_str;
275 cs_str = NULL;
276 switch (cs_int) {
278 case 0x010080: cs_str = "SSL2/RSA/RC4-128/MD5"; break;
279 case 0x020080: cs_str = "SSL2/RSA/RC4-40/MD5"; break;
280 case 0x030080: cs_str = "SSL2/RSA/RC2CBC128/MD5"; break;
281 case 0x040080: cs_str = "SSL2/RSA/RC2CBC40/MD5"; break;
282 case 0x050080: cs_str = "SSL2/RSA/IDEA128CBC/MD5"; break;
283 case 0x060040: cs_str = "SSL2/RSA/DES56-CBC/MD5"; break;
284 case 0x0700C0: cs_str = "SSL2/RSA/3DES192EDE-CBC/MD5"; break;
286 case 0x000001: cs_str = "SSL3/RSA/NULL/MD5"; break;
287 case 0x000002: cs_str = "SSL3/RSA/NULL/SHA"; break;
288 case 0x000003: cs_str = "SSL3/RSA/RC4-40/MD5"; break;
289 case 0x000004: cs_str = "SSL3/RSA/RC4-128/MD5"; break;
290 case 0x000005: cs_str = "SSL3/RSA/RC4-128/SHA"; break;
291 case 0x000006: cs_str = "SSL3/RSA/RC2CBC40/MD5"; break;
292 case 0x000007: cs_str = "SSL3/RSA/IDEA128CBC/SHA"; break;
293 case 0x000008: cs_str = "SSL3/RSA/DES40-CBC/SHA"; break;
294 case 0x000009: cs_str = "SSL3/RSA/DES56-CBC/SHA"; break;
295 case 0x00000A: cs_str = "SSL3/RSA/3DES192EDE-CBC/SHA"; break;
297 case 0x00000B: cs_str = "SSL3/DH-DSS/DES40-CBC/SHA"; break;
298 case 0x00000C: cs_str = "SSL3/DH-DSS/DES56-CBC/SHA"; break;
299 case 0x00000D: cs_str = "SSL3/DH-DSS/DES192EDE3CBC/SHA"; break;
300 case 0x00000E: cs_str = "SSL3/DH-RSA/DES40-CBC/SHA"; break;
301 case 0x00000F: cs_str = "SSL3/DH-RSA/DES56-CBC/SHA"; break;
302 case 0x000010: cs_str = "SSL3/DH-RSA/3DES192EDE-CBC/SHA"; break;
304 case 0x000011: cs_str = "SSL3/DHE-DSS/DES40-CBC/SHA"; break;
305 case 0x000012: cs_str = "SSL3/DHE-DSS/DES56-CBC/SHA"; break;
306 case 0x000013: cs_str = "SSL3/DHE-DSS/DES192EDE3CBC/SHA"; break;
307 case 0x000014: cs_str = "SSL3/DHE-RSA/DES40-CBC/SHA"; break;
308 case 0x000015: cs_str = "SSL3/DHE-RSA/DES56-CBC/SHA"; break;
309 case 0x000016: cs_str = "SSL3/DHE-RSA/3DES192EDE-CBC/SHA"; break;
311 case 0x000017: cs_str = "SSL3/DH-anon/RC4-40/MD5"; break;
312 case 0x000018: cs_str = "SSL3/DH-anon/RC4-128/MD5"; break;
313 case 0x000019: cs_str = "SSL3/DH-anon/DES40-CBC/SHA"; break;
314 case 0x00001A: cs_str = "SSL3/DH-anon/DES56-CBC/SHA"; break;
315 case 0x00001B: cs_str = "SSL3/DH-anon/3DES192EDE-CBC/SHA"; break;
317 case 0x00001C: cs_str = "SSL3/FORTEZZA-DMS/NULL/SHA"; break;
318 case 0x00001D: cs_str = "SSL3/FORTEZZA-DMS/FORTEZZA-CBC/SHA"; break;
319 case 0x00001E: cs_str = "SSL3/FORTEZZA-DMS/RC4-128/SHA"; break;
321 case 0x00002F: cs_str = "TLS/RSA/AES128-CBC/SHA"; break;
322 case 0x000030: cs_str = "TLS/DH-DSS/AES128-CBC/SHA"; break;
323 case 0x000031: cs_str = "TLS/DH-RSA/AES128-CBC/SHA"; break;
324 case 0x000032: cs_str = "TLS/DHE-DSS/AES128-CBC/SHA"; break;
325 case 0x000033: cs_str = "TLS/DHE-RSA/AES128-CBC/SHA"; break;
326 case 0x000034: cs_str = "TLS/DH-ANON/AES128-CBC/SHA"; break;
328 case 0x000035: cs_str = "TLS/RSA/AES256-CBC/SHA"; break;
329 case 0x000036: cs_str = "TLS/DH-DSS/AES256-CBC/SHA"; break;
330 case 0x000037: cs_str = "TLS/DH-RSA/AES256-CBC/SHA"; break;
331 case 0x000038: cs_str = "TLS/DHE-DSS/AES256-CBC/SHA"; break;
332 case 0x000039: cs_str = "TLS/DHE-RSA/AES256-CBC/SHA"; break;
333 case 0x00003A: cs_str = "TLS/DH-ANON/AES256-CBC/SHA"; break;
335 case 0x00003B: cs_str = "TLS/RSA/NULL/SHA256"; break;
336 case 0x00003C: cs_str = "TLS/RSA/AES128-CBC/SHA256"; break;
337 case 0x00003D: cs_str = "TLS/RSA/AES256-CBC/SHA256"; break;
338 case 0x00003E: cs_str = "TLS/DH-DSS/AES128-CBC/SHA256"; break;
339 case 0x00003F: cs_str = "TLS/DH-RSA/AES128-CBC/SHA256"; break;
340 case 0x000040: cs_str = "TLS/DHE-DSS/AES128-CBC/SHA256"; break;
342 case 0x000041: cs_str = "TLS/RSA/CAMELLIA128-CBC/SHA"; break;
343 case 0x000042: cs_str = "TLS/DH-DSS/CAMELLIA128-CBC/SHA"; break;
344 case 0x000043: cs_str = "TLS/DH-RSA/CAMELLIA128-CBC/SHA"; break;
345 case 0x000044: cs_str = "TLS/DHE-DSS/CAMELLIA128-CBC/SHA"; break;
346 case 0x000045: cs_str = "TLS/DHE-RSA/CAMELLIA128-CBC/SHA"; break;
347 case 0x000046: cs_str = "TLS/DH-ANON/CAMELLIA128-CBC/SHA"; break;
349 case 0x000060: cs_str = "TLS/RSA-EXPORT1024/RC4-56/MD5"; break;
350 case 0x000061: cs_str = "TLS/RSA-EXPORT1024/RC2CBC56/MD5"; break;
351 case 0x000062: cs_str = "TLS/RSA-EXPORT1024/DES56-CBC/SHA"; break;
352 case 0x000064: cs_str = "TLS/RSA-EXPORT1024/RC4-56/SHA"; break;
353 case 0x000063: cs_str = "TLS/DHE-DSS_EXPORT1024/DES56-CBC/SHA"; break;
354 case 0x000065: cs_str = "TLS/DHE-DSS_EXPORT1024/RC4-56/SHA"; break;
355 case 0x000066: cs_str = "TLS/DHE-DSS/RC4-128/SHA"; break;
357 case 0x000067: cs_str = "TLS/DHE-RSA/AES128-CBC/SHA256"; break;
358 case 0x000068: cs_str = "TLS/DH-DSS/AES256-CBC/SHA256"; break;
359 case 0x000069: cs_str = "TLS/DH-RSA/AES256-CBC/SHA256"; break;
360 case 0x00006A: cs_str = "TLS/DHE-DSS/AES256-CBC/SHA256"; break;
361 case 0x00006B: cs_str = "TLS/DHE-RSA/AES256-CBC/SHA256"; break;
363 case 0x000072: cs_str = "TLS/DHE-DSS/3DESEDE-CBC/RMD160"; break;
364 case 0x000073: cs_str = "TLS/DHE-DSS/AES128-CBC/RMD160"; break;
365 case 0x000074: cs_str = "TLS/DHE-DSS/AES256-CBC/RMD160"; break;
367 case 0x000079: cs_str = "TLS/DHE-RSA/AES256-CBC/RMD160"; break;
369 case 0x00007C: cs_str = "TLS/RSA/3DESEDE-CBC/RMD160"; break;
370 case 0x00007D: cs_str = "TLS/RSA/AES128-CBC/RMD160"; break;
371 case 0x00007E: cs_str = "TLS/RSA/AES256-CBC/RMD160"; break;
373 case 0x000080: cs_str = "TLS/GOST341094/GOST28147-OFB/GOST28147"; break;
374 case 0x000081: cs_str = "TLS/GOST34102001/GOST28147-OFB/GOST28147"; break;
375 case 0x000082: cs_str = "TLS/GOST341094/NULL/GOSTR3411"; break;
376 case 0x000083: cs_str = "TLS/GOST34102001/NULL/GOSTR3411"; break;
378 case 0x000084: cs_str = "TLS/RSA/CAMELLIA256-CBC/SHA"; break;
379 case 0x000085: cs_str = "TLS/DH-DSS/CAMELLIA256-CBC/SHA"; break;
380 case 0x000086: cs_str = "TLS/DH-RSA/CAMELLIA256-CBC/SHA"; break;
381 case 0x000087: cs_str = "TLS/DHE-DSS/CAMELLIA256-CBC/SHA"; break;
382 case 0x000088: cs_str = "TLS/DHE-RSA/CAMELLIA256-CBC/SHA"; break;
383 case 0x000089: cs_str = "TLS/DH-ANON/CAMELLIA256-CBC/SHA"; break;
384 case 0x00008A: cs_str = "TLS/PSK/RC4-128/SHA"; break;
385 case 0x00008B: cs_str = "TLS/PSK/3DES-EDE-CBC/SHA"; break;
386 case 0x00008C: cs_str = "TLS/PSK/AES128-CBC/SHA"; break;
387 case 0x00008D: cs_str = "TLS/PSK/AES256-CBC/SHA"; break;
388 case 0x00008E: cs_str = "TLS/DHE-PSK/RC4-128/SHA"; break;
389 case 0x00008F: cs_str = "TLS/DHE-PSK/3DES-EDE-CBC/SHA"; break;
390 case 0x000090: cs_str = "TLS/DHE-PSK/AES128-CBC/SHA"; break;
391 case 0x000091: cs_str = "TLS/DHE-PSK/AES256-CBC/SHA"; break;
392 case 0x000092: cs_str = "TLS/RSA-PSK/RC4-128/SHA"; break;
393 case 0x000093: cs_str = "TLS/RSA-PSK/3DES-EDE-CBC/SHA"; break;
394 case 0x000094: cs_str = "TLS/RSA-PSK/AES128-CBC/SHA"; break;
395 case 0x000095: cs_str = "TLS/RSA-PSK/AES256-CBC/SHA"; break;
396 case 0x000096: cs_str = "TLS/RSA/SEED-CBC/SHA"; break;
397 case 0x000097: cs_str = "TLS/DH-DSS/SEED-CBC/SHA"; break;
398 case 0x000098: cs_str = "TLS/DH-RSA/SEED-CBC/SHA"; break;
399 case 0x000099: cs_str = "TLS/DHE-DSS/SEED-CBC/SHA"; break;
400 case 0x00009A: cs_str = "TLS/DHE-RSA/SEED-CBC/SHA"; break;
401 case 0x00009B: cs_str = "TLS/DH-ANON/SEED-CBC/SHA"; break;
402 case 0x00009C: cs_str = "TLS/RSA/AES128-GCM/SHA256"; break;
403 case 0x00009E: cs_str = "TLS/DHE-RSA/AES128-GCM/SHA256"; break;
405 case 0x0000FF: cs_str = "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"; break;
407 case 0x00C001: cs_str = "TLS/ECDH-ECDSA/NULL/SHA"; break;
408 case 0x00C002: cs_str = "TLS/ECDH-ECDSA/RC4-128/SHA"; break;
409 case 0x00C003: cs_str = "TLS/ECDH-ECDSA/3DES-EDE-CBC/SHA"; break;
410 case 0x00C004: cs_str = "TLS/ECDH-ECDSA/AES128-CBC/SHA"; break;
411 case 0x00C005: cs_str = "TLS/ECDH-ECDSA/AES256-CBC/SHA"; break;
412 case 0x00C006: cs_str = "TLS/ECDHE-ECDSA/NULL/SHA"; break;
413 case 0x00C007: cs_str = "TLS/ECDHE-ECDSA/RC4-128/SHA"; break;
414 case 0x00C008: cs_str = "TLS/ECDHE-ECDSA/3DES-EDE-CBC/SHA";break;
415 case 0x00C009: cs_str = "TLS/ECDHE-ECDSA/AES128-CBC/SHA"; break;
416 case 0x00C00A: cs_str = "TLS/ECDHE-ECDSA/AES256-CBC/SHA"; break;
417 case 0x00C00B: cs_str = "TLS/ECDH-RSA/NULL/SHA"; break;
418 case 0x00C00C: cs_str = "TLS/ECDH-RSA/RC4-128/SHA"; break;
419 case 0x00C00D: cs_str = "TLS/ECDH-RSA/3DES-EDE-CBC/SHA"; break;
420 case 0x00C00E: cs_str = "TLS/ECDH-RSA/AES128-CBC/SHA"; break;
421 case 0x00C00F: cs_str = "TLS/ECDH-RSA/AES256-CBC/SHA"; break;
422 case 0x00C010: cs_str = "TLS/ECDHE-RSA/NULL/SHA"; break;
423 case 0x00C011: cs_str = "TLS/ECDHE-RSA/RC4-128/SHA"; break;
424 case 0x00C012: cs_str = "TLS/ECDHE-RSA/3DES-EDE-CBC/SHA"; break;
425 case 0x00C013: cs_str = "TLS/ECDHE-RSA/AES128-CBC/SHA"; break;
426 case 0x00C014: cs_str = "TLS/ECDHE-RSA/AES256-CBC/SHA"; break;
427 case 0x00C015: cs_str = "TLS/ECDH-anon/NULL/SHA"; break;
428 case 0x00C016: cs_str = "TLS/ECDH-anon/RC4-128/SHA"; break;
429 case 0x00C017: cs_str = "TLS/ECDH-anon/3DES-EDE-CBC/SHA"; break;
430 case 0x00C018: cs_str = "TLS/ECDH-anon/AES128-CBC/SHA"; break;
431 case 0x00C019: cs_str = "TLS/ECDH-anon/AES256-CBC/SHA"; break;
433 case 0x00C023: cs_str = "TLS/ECDHE-ECDSA/AES128-CBC/SHA256"; break;
434 case 0x00C024: cs_str = "TLS/ECDHE-ECDSA/AES256-CBC/SHA384"; break;
435 case 0x00C025: cs_str = "TLS/ECDH-ECDSA/AES128-CBC/SHA256"; break;
436 case 0x00C026: cs_str = "TLS/ECDH-ECDSA/AES256-CBC/SHA384"; break;
437 case 0x00C027: cs_str = "TLS/ECDHE-RSA/AES128-CBC/SHA256"; break;
438 case 0x00C028: cs_str = "TLS/ECDHE-RSA/AES256-CBC/SHA384"; break;
439 case 0x00C029: cs_str = "TLS/ECDH-RSA/AES128-CBC/SHA256"; break;
440 case 0x00C02A: cs_str = "TLS/ECDH-RSA/AES256-CBC/SHA384"; break;
441 case 0x00C02B: cs_str = "TLS/ECDHE-ECDSA/AES128-GCM/SHA256"; break;
442 case 0x00C02C: cs_str = "TLS/ECDHE-ECDSA/AES256-GCM/SHA384"; break;
443 case 0x00C02F: cs_str = "TLS/ECDHE-RSA/AES128-GCM/SHA256"; break;
445 case 0x00FEFF: cs_str = "SSL3/RSA-FIPS/3DESEDE-CBC/SHA"; break;
446 case 0x00FEFE: cs_str = "SSL3/RSA-FIPS/DES-CBC/SHA"; break;
447 case 0x00FFE1: cs_str = "SSL3/RSA-FIPS/DES56-CBC/SHA"; break;
448 case 0x00FFE0: cs_str = "SSL3/RSA-FIPS/3DES192EDE-CBC/SHA";break;
450 /* the string literal is broken up to avoid trigraphs */
451 default: cs_str = "????" "/????????" "/?????????" "/???"; break;
452 }
454 return cs_str;
455 }
457 const char * CompressionMethodString(int cm_int)
458 {
459 char *cm_str;
460 cm_str = NULL;
461 switch (cm_int) {
462 case 0: cm_str = "NULL"; break;
463 case 1: cm_str = "DEFLATE"; break; /* RFC 3749 */
464 case 64: cm_str = "LZS"; break; /* RFC 3943 */
465 default: cm_str = "???"; break;
466 }
468 return cm_str;
469 }
471 const char * helloExtensionNameString(int ex_num)
472 {
473 const char *ex_name = NULL;
474 static char buf[10];
476 switch (ex_num) {
477 case 0: ex_name = "server_name"; break;
478 case 1: ex_name = "max_fragment_length"; break;
479 case 2: ex_name = "client_certificate_url"; break;
480 case 3: ex_name = "trusted_ca_keys"; break;
481 case 4: ex_name = "truncated_hmac"; break;
482 case 5: ex_name = "status_request"; break;
483 case 10: ex_name = "elliptic_curves"; break;
484 case 11: ex_name = "ec_point_formats"; break;
485 case 13: ex_name = "signature_algorithms"; break;
486 case 35: ex_name = "session_ticket"; break;
487 case 0xff01: ex_name = "renegotiation_info"; break;
488 default: sprintf(buf, "%d", ex_num); ex_name = (const char *)buf; break;
489 }
491 return ex_name;
492 }
494 static int isNULLmac(int cs_int)
495 {
496 return (cs_int == TLS_NULL_WITH_NULL_NULL);
497 }
499 static int isNULLcipher(int cs_int)
500 {
501 return ((cs_int == TLS_RSA_WITH_NULL_MD5) ||
502 (cs_int == TLS_RSA_WITH_NULL_SHA) ||
503 (cs_int == SSL_FORTEZZA_DMS_WITH_NULL_SHA) ||
504 (cs_int == TLS_ECDH_ECDSA_WITH_NULL_SHA) ||
505 (cs_int == TLS_ECDHE_ECDSA_WITH_NULL_SHA) ||
506 (cs_int == TLS_ECDH_RSA_WITH_NULL_SHA) ||
507 (cs_int == TLS_ECDHE_RSA_WITH_NULL_SHA));
508 }
510 void partial_packet(int thispacket, int size, int needed)
511 {
512 PR_fprintf(PR_STDOUT,"(%u bytes", thispacket);
513 if (thispacket < needed) {
514 PR_fprintf(PR_STDOUT,", making %u", size);
515 }
516 PR_fprintf(PR_STDOUT," of %u", needed);
517 if (size > needed) {
518 PR_fprintf(PR_STDOUT,", with %u left over", size - needed);
519 }
520 PR_fprintf(PR_STDOUT,")\n");
521 }
523 char * get_time_string(void)
524 {
525 char *cp;
526 char *eol;
527 time_t tt;
529 time(&tt);
530 cp = ctime(&tt);
531 eol = strchr(cp, '\n');
532 if (eol)
533 *eol = 0;
534 return cp;
535 }
537 void print_sslv2(DataBufferList *s, unsigned char *recordBuf, unsigned int recordLen)
538 {
539 ClientHelloV2 *chv2;
540 ServerHelloV2 *shv2;
541 unsigned char *pos;
542 unsigned int p;
543 unsigned int q;
544 PRUint32 len;
546 chv2 = (ClientHelloV2 *)recordBuf;
547 shv2 = (ServerHelloV2 *)recordBuf;
548 if (s->isEncrypted) {
549 PR_fprintf(PR_STDOUT," [ssl2] Encrypted {...}\n");
550 return;
551 }
552 PR_fprintf(PR_STDOUT," [%s]", get_time_string() );
553 switch(chv2->type) {
554 case 1:
555 PR_fprintf(PR_STDOUT," [ssl2] ClientHelloV2 {\n");
556 PR_fprintf(PR_STDOUT," version = {0x%02x, 0x%02x}\n",
557 (PRUint32)chv2->version[0],(PRUint32)chv2->version[1]);
558 PR_fprintf(PR_STDOUT," cipher-specs-length = %d (0x%02x)\n",
559 (PRUint32)(GET_SHORT((chv2->cslength))),
560 (PRUint32)(GET_SHORT((chv2->cslength))));
561 PR_fprintf(PR_STDOUT," sid-length = %d (0x%02x)\n",
562 (PRUint32)(GET_SHORT((chv2->sidlength))),
563 (PRUint32)(GET_SHORT((chv2->sidlength))));
564 PR_fprintf(PR_STDOUT," challenge-length = %d (0x%02x)\n",
565 (PRUint32)(GET_SHORT((chv2->rndlength))),
566 (PRUint32)(GET_SHORT((chv2->rndlength))));
567 PR_fprintf(PR_STDOUT," cipher-suites = { \n");
568 for (p=0;p<GET_SHORT((chv2->cslength));p+=3) {
569 PRUint32 cs_int = GET_24((&chv2->csuites[p]));
570 const char *cs_str = V2CipherString(cs_int);
572 PR_fprintf(PR_STDOUT," (0x%06x) %s\n",
573 cs_int, cs_str);
574 }
575 q = p;
576 PR_fprintf(PR_STDOUT," }\n");
577 if (chv2->sidlength) {
578 PR_fprintf(PR_STDOUT," session-id = { ");
579 for (p=0;p<GET_SHORT((chv2->sidlength));p+=2) {
580 PR_fprintf(PR_STDOUT,"0x%04x ",(PRUint32)(GET_SHORT((&chv2->csuites[p+q]))));
581 }
582 }
583 q += p;
584 PR_fprintf(PR_STDOUT,"}\n");
585 if (chv2->rndlength) {
586 PR_fprintf(PR_STDOUT," challenge = { ");
587 for (p=0;p<GET_SHORT((chv2->rndlength));p+=2) {
588 PR_fprintf(PR_STDOUT,"0x%04x ",(PRUint32)(GET_SHORT((&chv2->csuites[p+q]))));
589 }
590 PR_fprintf(PR_STDOUT,"}\n");
591 }
592 PR_fprintf(PR_STDOUT,"}\n");
593 break;
594 /* end of V2 CLientHello Parsing */
596 case 2: /* Client Master Key */
597 {
598 const char *cs_str=NULL;
599 PRUint32 cs_int=0;
600 ClientMasterKeyV2 *cmkv2;
601 cmkv2 = (ClientMasterKeyV2 *)chv2;
602 isV2Session = 1;
604 PR_fprintf(PR_STDOUT," [ssl2] ClientMasterKeyV2 { \n");
606 cs_int = GET_24(&cmkv2->cipherkind[0]);
607 cs_str = V2CipherString(cs_int);
608 PR_fprintf(PR_STDOUT," cipher-spec-chosen = (0x%06x) %s\n",
609 cs_int, cs_str);
611 PR_fprintf(PR_STDOUT," clear-portion = %d bits\n",
612 8*(PRUint32)(GET_SHORT((cmkv2->clearkey))));
614 PR_fprintf(PR_STDOUT," }\n");
615 clientstream.isEncrypted = 1;
616 serverstream.isEncrypted = 1;
617 }
618 break;
621 case 3:
622 PR_fprintf(PR_STDOUT," [ssl2] Client Finished V2 {...}\n");
623 isV2Session = 1;
624 break;
627 case 4: /* V2 Server Hello */
628 isV2Session = 1;
630 PR_fprintf(PR_STDOUT," [ssl2] ServerHelloV2 {\n");
631 PR_fprintf(PR_STDOUT," sid hit = {0x%02x}\n",
632 (PRUintn)shv2->sidhit);
633 PR_fprintf(PR_STDOUT," version = {0x%02x, 0x%02x}\n",
634 (PRUint32)shv2->version[0],(PRUint32)shv2->version[1]);
635 PR_fprintf(PR_STDOUT," cipher-specs-length = %d (0x%02x)\n",
636 (PRUint32)(GET_SHORT((shv2->cslength))),
637 (PRUint32)(GET_SHORT((shv2->cslength))));
638 PR_fprintf(PR_STDOUT," sid-length = %d (0x%02x)\n",
639 (PRUint32)(GET_SHORT((shv2->cidlength))),
640 (PRUint32)(GET_SHORT((shv2->cidlength))));
642 pos = (unsigned char *)shv2;
643 pos += 2; /* skip length header */
644 pos += 11; /* position pointer to Certificate data area */
645 q = GET_SHORT(&shv2->certlength);
646 if (q >recordLen) {
647 goto eosh;
648 }
649 pos += q; /* skip certificate */
651 PR_fprintf(PR_STDOUT," cipher-suites = { ");
652 len = GET_SHORT((shv2->cslength));
653 for (p = 0; p < len; p += 3) {
654 PRUint32 cs_int = GET_24((pos+p));
655 const char *cs_str = V2CipherString(cs_int);
656 PR_fprintf(PR_STDOUT,"\n ");
657 PR_fprintf(PR_STDOUT,"(0x%06x) %s", cs_int, cs_str);
658 }
659 pos += len;
660 PR_fprintf(PR_STDOUT," }\n"); /* End of cipher suites */
661 len = (PRUint32)GET_SHORT((shv2->cidlength));
662 if (len) {
663 PR_fprintf(PR_STDOUT," connection-id = { ");
664 for (p = 0; p < len; p += 2) {
665 PR_fprintf(PR_STDOUT,"0x%04x ", (PRUint32)(GET_SHORT((pos + p))));
666 }
667 PR_fprintf(PR_STDOUT," }\n"); /* End of connection id */
668 }
669 eosh:
670 PR_fprintf(PR_STDOUT,"\n }\n"); /* end of ServerHelloV2 */
671 if (shv2->sidhit) {
672 clientstream.isEncrypted = 1;
673 serverstream.isEncrypted = 1;
674 }
675 break;
677 case 5:
678 PR_fprintf(PR_STDOUT," [ssl2] Server Verify V2 {...}\n");
679 isV2Session = 1;
680 break;
682 case 6:
683 PR_fprintf(PR_STDOUT," [ssl2] Server Finished V2 {...}\n");
684 isV2Session = 1;
685 break;
687 case 7:
688 PR_fprintf(PR_STDOUT," [ssl2] Request Certificate V2 {...}\n");
689 isV2Session = 1;
690 break;
692 case 8:
693 PR_fprintf(PR_STDOUT," [ssl2] Client Certificate V2 {...}\n");
694 isV2Session = 1;
695 break;
697 default:
698 PR_fprintf(PR_STDOUT," [ssl2] UnknownType 0x%02x {...}\n",
699 (PRUint32)chv2->type);
700 break;
701 }
702 }
706 unsigned int print_hello_extension(unsigned char * hsdata,
707 unsigned int length,
708 unsigned int pos)
709 {
710 /* pretty print extensions, if any */
711 if (pos < length) {
712 int exListLen = GET_SHORT((hsdata+pos)); pos += 2;
713 PR_fprintf(PR_STDOUT,
714 " extensions[%d] = {\n", exListLen);
715 while (exListLen > 0 && pos < length) {
716 int exLen;
717 int exType = GET_SHORT((hsdata+pos)); pos += 2;
718 exLen = GET_SHORT((hsdata+pos)); pos += 2;
719 /* dump the extension */
720 PR_fprintf(PR_STDOUT,
721 " extension type %s, length [%d]",
722 helloExtensionNameString(exType), exLen);
723 if (exLen > 0) {
724 PR_fprintf(PR_STDOUT, " = {\n");
725 print_hex(exLen, hsdata + pos);
726 PR_fprintf(PR_STDOUT, " }\n");
727 } else {
728 PR_fprintf(PR_STDOUT, "\n");
729 }
730 pos += exLen;
731 exListLen -= 2 + exLen;
732 }
733 PR_fprintf(PR_STDOUT," }\n");
734 }
735 return pos;
736 }
738 /*
739 * Note this must match (exactly) the enumeration ocspResponseStatus.
740 */
741 static char *responseStatusNames[] = {
742 "successful (Response has valid confirmations)",
743 "malformedRequest (Illegal confirmation request)",
744 "internalError (Internal error in issuer)",
745 "tryLater (Try again later)",
746 "unused ((4) is not used)",
747 "sigRequired (Must sign the request)",
748 "unauthorized (Request unauthorized)",
749 };
751 static void
752 print_ocsp_cert_id (FILE *out_file, CERTOCSPCertID *cert_id, int level)
753 {
754 SECU_Indent (out_file, level);
755 fprintf (out_file, "Cert ID:\n");
756 level++;
757 /*
758 SECU_PrintAlgorithmID (out_file, &(cert_id->hashAlgorithm),
759 "Hash Algorithm", level);
760 SECU_PrintAsHex (out_file, &(cert_id->issuerNameHash),
761 "Issuer Name Hash", level);
762 SECU_PrintAsHex (out_file, &(cert_id->issuerKeyHash),
763 "Issuer Key Hash", level);
764 */
765 SECU_PrintInteger (out_file, &(cert_id->serialNumber),
766 "Serial Number", level);
767 /* XXX lookup the cert; if found, print something nice (nickname?) */
768 }
770 static void
771 print_ocsp_version (FILE *out_file, SECItem *version, int level)
772 {
773 if (version->len > 0) {
774 SECU_PrintInteger (out_file, version, "Version", level);
775 } else {
776 SECU_Indent (out_file, level);
777 fprintf (out_file, "Version: DEFAULT\n");
778 }
779 }
781 static void
782 print_responder_id (FILE *out_file, ocspResponderID *responderID, int level)
783 {
784 SECU_Indent (out_file, level);
785 fprintf (out_file, "Responder ID ");
787 switch (responderID->responderIDType) {
788 case ocspResponderID_byName:
789 fprintf (out_file, "(byName):\n");
790 SECU_PrintName (out_file, &(responderID->responderIDValue.name),
791 "Name", level + 1);
792 break;
793 case ocspResponderID_byKey:
794 fprintf (out_file, "(byKey):\n");
795 SECU_PrintAsHex (out_file, &(responderID->responderIDValue.keyHash),
796 "Key Hash", level + 1);
797 break;
798 default:
799 fprintf (out_file, "Unrecognized Responder ID Type\n");
800 break;
801 }
802 }
804 static void
805 print_ocsp_extensions (FILE *out_file, CERTCertExtension **extensions,
806 char *msg, int level)
807 {
808 if (extensions) {
809 SECU_PrintExtensions (out_file, extensions, msg, level);
810 } else {
811 SECU_Indent (out_file, level);
812 fprintf (out_file, "No %s\n", msg);
813 }
814 }
816 static void
817 print_revoked_info (FILE *out_file, ocspRevokedInfo *revoked_info, int level)
818 {
819 SECU_PrintGeneralizedTime (out_file, &(revoked_info->revocationTime),
820 "Revocation Time", level);
822 if (revoked_info->revocationReason != NULL) {
823 SECU_PrintAsHex (out_file, revoked_info->revocationReason,
824 "Revocation Reason", level);
825 } else {
826 SECU_Indent (out_file, level);
827 fprintf (out_file, "No Revocation Reason.\n");
828 }
829 }
831 static void
832 print_cert_status (FILE *out_file, ocspCertStatus *status, int level)
833 {
834 SECU_Indent (out_file, level);
835 fprintf (out_file, "Status: ");
837 switch (status->certStatusType) {
838 case ocspCertStatus_good:
839 fprintf (out_file, "Cert is good.\n");
840 break;
841 case ocspCertStatus_revoked:
842 fprintf (out_file, "Cert has been revoked.\n");
843 print_revoked_info (out_file, status->certStatusInfo.revokedInfo,
844 level + 1);
845 break;
846 case ocspCertStatus_unknown:
847 fprintf (out_file, "Cert is unknown to responder.\n");
848 break;
849 default:
850 fprintf (out_file, "Unrecognized status.\n");
851 break;
852 }
853 }
855 static void
856 print_single_response (FILE *out_file, CERTOCSPSingleResponse *single,
857 int level)
858 {
859 print_ocsp_cert_id (out_file, single->certID, level);
861 print_cert_status (out_file, single->certStatus, level);
863 SECU_PrintGeneralizedTime (out_file, &(single->thisUpdate),
864 "This Update", level);
866 if (single->nextUpdate != NULL) {
867 SECU_PrintGeneralizedTime (out_file, single->nextUpdate,
868 "Next Update", level);
869 } else {
870 SECU_Indent (out_file, level);
871 fprintf (out_file, "No Next Update\n");
872 }
874 print_ocsp_extensions (out_file, single->singleExtensions,
875 "Single Response Extensions", level);
876 }
878 static void
879 print_response_data (FILE *out_file, ocspResponseData *responseData, int level)
880 {
881 SECU_Indent (out_file, level);
882 fprintf (out_file, "Response Data:\n");
883 level++;
885 print_ocsp_version (out_file, &(responseData->version), level);
887 print_responder_id (out_file, responseData->responderID, level);
889 SECU_PrintGeneralizedTime (out_file, &(responseData->producedAt),
890 "Produced At", level);
892 if (responseData->responses != NULL) {
893 int i;
895 for (i = 0; responseData->responses[i] != NULL; i++) {
896 SECU_Indent (out_file, level);
897 fprintf (out_file, "Response %d:\n", i);
898 print_single_response (out_file, responseData->responses[i],
899 level + 1);
900 }
901 } else {
902 fprintf (out_file, "Response list is empty.\n");
903 }
905 print_ocsp_extensions (out_file, responseData->responseExtensions,
906 "Response Extensions", level);
907 }
909 static void
910 print_basic_response (FILE *out_file, ocspBasicOCSPResponse *basic, int level)
911 {
912 SECU_Indent (out_file, level);
913 fprintf (out_file, "Basic OCSP Response:\n");
914 level++;
916 print_response_data (out_file, basic->tbsResponseData, level);
917 }
919 static void
920 print_status_response(SECItem *data)
921 {
922 int level = 2;
923 CERTOCSPResponse *response;
924 response = CERT_DecodeOCSPResponse (data);
925 if (!response) {
926 SECU_Indent (stdout, level);
927 fprintf(stdout,"unable to decode certificate_status\n");
928 return;
929 }
931 SECU_Indent (stdout, level);
932 if (response->statusValue >= ocspResponse_min &&
933 response->statusValue <= ocspResponse_max) {
934 fprintf (stdout, "Response Status: %s\n",
935 responseStatusNames[response->statusValue]);
936 } else {
937 fprintf (stdout,
938 "Response Status: other (Status value %d out of defined range)\n",
939 (int)response->statusValue);
940 }
942 if (response->statusValue == ocspResponse_successful) {
943 ocspResponseBytes *responseBytes = response->responseBytes;
944 PORT_Assert (responseBytes != NULL);
946 level++;
947 SECU_PrintObjectID (stdout, &(responseBytes->responseType),
948 "Response Type", level);
949 switch (response->responseBytes->responseTypeTag) {
950 case SEC_OID_PKIX_OCSP_BASIC_RESPONSE:
951 print_basic_response (stdout,
952 responseBytes->decodedResponse.basic,
953 level);
954 break;
955 default:
956 SECU_Indent (stdout, level);
957 fprintf (stdout, "Unknown response syntax\n");
958 break;
959 }
960 } else {
961 SECU_Indent (stdout, level);
962 fprintf (stdout, "Unsuccessful response, no more information.\n");
963 }
965 CERT_DestroyOCSPResponse (response);
966 }
968 /* In the case of renegotiation, handshakes that occur in an already MAC'ed
969 * channel, by the time of this call, the caller has already removed the MAC
970 * from input recordLen. The only MAC'ed record that will get here with its
971 * MAC intact (not removed) is the first Finished message on the connection.
972 */
973 void print_ssl3_handshake(unsigned char *recordBuf,
974 unsigned int recordLen,
975 SSLRecord * sr,
976 DataBufferList *s)
977 {
978 struct sslhandshake sslh;
979 unsigned char * hsdata;
980 int offset=0;
982 PR_fprintf(PR_STDOUT," handshake {\n");
984 if (s->msgBufOffset && s->msgBuf) {
985 /* append recordBuf to msgBuf, then use msgBuf */
986 if (s->msgBufOffset + recordLen > s->msgBufSize) {
987 int newSize = s->msgBufOffset + recordLen;
988 unsigned char * newBuf = PORT_Realloc(s->msgBuf, newSize);
989 if (!newBuf) {
990 PR_ASSERT(newBuf);
991 showErr( "Realloc failed");
992 exit(10);
993 }
994 s->msgBuf = newBuf;
995 s->msgBufSize = newSize;
996 }
997 memcpy(s->msgBuf + s->msgBufOffset, recordBuf, recordLen);
998 s->msgBufOffset += recordLen;
999 recordLen = s->msgBufOffset;
1000 recordBuf = s->msgBuf;
1001 }
1002 while (offset + 4 <= recordLen) {
1003 sslh.type = recordBuf[offset];
1004 sslh.length = GET_24(recordBuf+offset+1);
1005 if (offset + 4 + sslh.length > recordLen)
1006 break;
1007 /* finally have a complete message */
1008 if (sslhexparse)
1009 print_hex(4,recordBuf+offset);
1011 hsdata = &recordBuf[offset+4];
1013 PR_fprintf(PR_STDOUT," type = %d (",sslh.type);
1014 switch(sslh.type) {
1015 case 0: PR_FPUTS("hello_request)\n" ); break;
1016 case 1: PR_FPUTS("client_hello)\n" ); break;
1017 case 2: PR_FPUTS("server_hello)\n" ); break;
1018 case 4: PR_FPUTS("new_session_ticket)\n" ); break;
1019 case 11: PR_FPUTS("certificate)\n" ); break;
1020 case 12: PR_FPUTS("server_key_exchange)\n" ); break;
1021 case 13: PR_FPUTS("certificate_request)\n" ); break;
1022 case 14: PR_FPUTS("server_hello_done)\n" ); break;
1023 case 15: PR_FPUTS("certificate_verify)\n" ); break;
1024 case 16: PR_FPUTS("client_key_exchange)\n" ); break;
1025 case 20: PR_FPUTS("finished)\n" ); break;
1026 case 22: PR_FPUTS("certificate_status)\n" ); break;
1027 default: PR_FPUTS("unknown)\n" ); break;
1028 }
1030 PR_fprintf(PR_STDOUT," length = %d (0x%06x)\n",sslh.length,sslh.length);
1031 switch (sslh.type) {
1033 case 0: /* hello_request */ /* not much to show here. */ break;
1035 case 1: /* client hello */
1036 switch (sr->ver_maj) {
1037 case 3: /* ssl version 3 */
1038 {
1039 unsigned int pos;
1040 int w;
1042 PR_fprintf(PR_STDOUT," ClientHelloV3 {\n");
1043 PR_fprintf(PR_STDOUT," client_version = {%d, %d}\n",
1044 (PRUint8)hsdata[0],(PRUint8)hsdata[1]);
1045 PR_fprintf(PR_STDOUT," random = {...}\n");
1046 if (sslhexparse) print_hex(32,&hsdata[2]);
1048 /* pretty print Session ID */
1049 {
1050 int sidlength = (int)hsdata[2+32];
1051 PR_fprintf(PR_STDOUT," session ID = {\n");
1052 PR_fprintf(PR_STDOUT," length = %d\n",sidlength);
1053 PR_fprintf(PR_STDOUT," contents = {...}\n");
1054 if (sslhexparse) print_hex(sidlength,&hsdata[2+32+1]);
1055 PR_fprintf(PR_STDOUT," }\n");
1056 pos = 2+32+1+sidlength;
1057 }
1059 /* pretty print cipher suites */
1060 {
1061 int csuitelength = GET_SHORT((hsdata+pos));
1062 PR_fprintf(PR_STDOUT," cipher_suites[%d] = {\n",
1063 csuitelength/2);
1064 if (csuitelength % 2) {
1065 PR_fprintf(PR_STDOUT,
1066 "*error in protocol - csuitelength shouldn't be odd*\n");
1067 }
1068 for (w=0; w<csuitelength; w+=2) {
1069 PRUint32 cs_int = GET_SHORT((hsdata+pos+2+w));
1070 const char *cs_str = V2CipherString(cs_int);
1071 PR_fprintf(PR_STDOUT,
1072 " (0x%04x) %s\n", cs_int, cs_str);
1073 }
1074 pos += 2 + csuitelength;
1075 PR_fprintf(PR_STDOUT," }\n");
1076 }
1078 /* pretty print compression methods */
1079 {
1080 int complength = hsdata[pos];
1081 PR_fprintf(PR_STDOUT," compression[%d] = {\n",
1082 complength);
1083 for (w=0; w < complength; w++) {
1084 PRUint32 cm_int = hsdata[pos+1+w];
1085 const char *cm_str = CompressionMethodString(cm_int);
1086 PR_fprintf(PR_STDOUT,
1087 " (%02x) %s\n", cm_int, cm_str);
1088 }
1089 pos += 1 + complength;
1090 PR_fprintf(PR_STDOUT," }\n");
1091 }
1093 /* pretty print extensions, if any */
1094 pos = print_hello_extension(hsdata, sslh.length, pos);
1096 PR_fprintf(PR_STDOUT," }\n");
1097 } /* end of ssl version 3 */
1098 break;
1099 default:
1100 PR_fprintf(PR_STDOUT," UNDEFINED VERSION %d.%d {...}\n",
1101 sr->ver_maj, sr->ver_min );
1102 if (sslhexparse) print_hex(sslh.length, hsdata);
1103 break;
1104 } /* end of switch sr->ver_maj */
1105 break;
1107 case 2: /* server hello */
1108 {
1109 unsigned int sidlength, pos;
1111 PR_fprintf(PR_STDOUT," ServerHello {\n");
1113 PR_fprintf(PR_STDOUT," server_version = {%d, %d}\n",
1114 (PRUint8)hsdata[0],(PRUint8)hsdata[1]);
1115 PR_fprintf(PR_STDOUT," random = {...}\n");
1116 if (sslhexparse) print_hex(32,&hsdata[2]);
1117 PR_fprintf(PR_STDOUT," session ID = {\n");
1118 sidlength = (int)hsdata[2+32];
1119 PR_fprintf(PR_STDOUT," length = %d\n",sidlength);
1120 PR_fprintf(PR_STDOUT," contents = {...}\n");
1121 if (sslhexparse) print_hex(sidlength,&hsdata[2+32+1]);
1122 PR_fprintf(PR_STDOUT," }\n");
1123 pos = 2+32+1+sidlength;
1125 /* pretty print chosen cipher suite */
1126 {
1127 PRUint32 cs_int = GET_SHORT((hsdata+pos));
1128 const char *cs_str = V2CipherString(cs_int);
1129 PR_fprintf(PR_STDOUT," cipher_suite = (0x%04x) %s\n",
1130 cs_int, cs_str);
1131 currentcipher = cs_int;
1132 pos += 2;
1133 }
1134 /* pretty print chosen compression method */
1135 {
1136 PRUint32 cm_int = hsdata[pos++];
1137 const char *cm_str = CompressionMethodString(cm_int);
1138 PR_fprintf(PR_STDOUT," compression method = (%02x) %s\n",
1139 cm_int, cm_str);
1140 }
1142 /* pretty print extensions, if any */
1143 pos = print_hello_extension(hsdata, sslh.length, pos);
1145 PR_fprintf(PR_STDOUT," }\n");
1146 }
1147 break;
1149 case 4: /* new session ticket */
1150 {
1151 PRUint32 lifetimehint;
1152 PRUint16 ticketlength;
1153 char lifetime[32];
1154 lifetimehint = GET_32(hsdata);
1155 if (lifetimehint) {
1156 PRExplodedTime et;
1157 PRTime t = lifetimehint;
1158 t *= PR_USEC_PER_SEC;
1159 PR_ExplodeTime(t, PR_GMTParameters, &et);
1160 /* use HTTP Cookie header's date format */
1161 PR_FormatTimeUSEnglish(lifetime, sizeof lifetime,
1162 "%a, %d-%b-%Y %H:%M:%S GMT", &et);
1163 } else {
1164 /* 0 means the lifetime of the ticket is unspecified */
1165 strcpy(lifetime, "unspecified");
1166 }
1167 ticketlength = GET_SHORT((hsdata+4));
1168 PR_fprintf(PR_STDOUT," NewSessionTicket {\n");
1169 PR_fprintf(PR_STDOUT," ticket_lifetime_hint = %s\n",
1170 lifetime);
1171 PR_fprintf(PR_STDOUT," ticket = {\n");
1172 PR_fprintf(PR_STDOUT," length = %d\n",ticketlength);
1173 PR_fprintf(PR_STDOUT," contents = {...}\n");
1174 if (sslhexparse) print_hex(ticketlength,&hsdata[4+2]);
1175 PR_fprintf(PR_STDOUT," }\n");
1176 PR_fprintf(PR_STDOUT," }\n");
1177 }
1178 break;
1180 case 11: /* certificate */
1181 {
1182 PRFileDesc *cfd;
1183 int pos;
1184 int certslength;
1185 int certlength;
1186 int certbytesread = 0;
1187 static int certFileNumber;
1188 char certFileName[20];
1190 PR_fprintf(PR_STDOUT," CertificateChain {\n");
1191 certslength = GET_24(hsdata);
1192 PR_fprintf(PR_STDOUT," chainlength = %d (0x%04x)\n",
1193 certslength,certslength);
1194 pos = 3;
1195 while (certbytesread < certslength) {
1196 certlength = GET_24((hsdata+pos));
1197 pos += 3;
1198 PR_fprintf(PR_STDOUT," Certificate {\n");
1199 PR_fprintf(PR_STDOUT," size = %d (0x%04x)\n",
1200 certlength,certlength);
1201 certbytesread += certlength+3;
1202 if (certbytesread <= certslength) {
1203 PR_snprintf(certFileName, sizeof certFileName, "cert.%03d",
1204 ++certFileNumber);
1205 cfd = PR_Open(certFileName, PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE,
1206 0664);
1207 if (!cfd) {
1208 PR_fprintf(PR_STDOUT,
1209 " data = { couldn't save file '%s' }\n",
1210 certFileName);
1211 } else {
1212 PR_Write(cfd, (hsdata+pos), certlength);
1213 PR_fprintf(PR_STDOUT,
1214 " data = { saved in file '%s' }\n",
1215 certFileName);
1216 PR_Close(cfd);
1217 }
1218 }
1220 PR_fprintf(PR_STDOUT," }\n");
1221 pos += certlength;
1222 }
1223 PR_fprintf(PR_STDOUT," }\n");
1224 }
1225 break;
1227 case 12: /* server_key_exchange */
1228 if (sslhexparse) print_hex(sslh.length, hsdata);
1229 break;
1231 case 13: /* certificate request */
1232 {
1233 unsigned int pos = 0;
1234 int w, reqLength;
1236 PR_fprintf(PR_STDOUT," CertificateRequest {\n");
1238 /* pretty print requested certificate types */
1239 reqLength = hsdata[pos];
1240 PR_fprintf(PR_STDOUT," certificate types[%d] = {",
1241 reqLength);
1242 for (w=0; w < reqLength; w++) {
1243 PR_fprintf(PR_STDOUT, " %02x", hsdata[pos+1+w]);
1244 }
1245 pos += 1 + reqLength;
1246 PR_fprintf(PR_STDOUT," }\n");
1248 /* pretty print CA names, if any */
1249 if (pos < sslh.length) {
1250 int exListLen = GET_SHORT((hsdata+pos)); pos += 2;
1251 PR_fprintf(PR_STDOUT,
1252 " certificate_authorities[%d] = {\n",
1253 exListLen);
1254 while (exListLen > 0 && pos < sslh.length) {
1255 char * ca_name;
1256 SECItem it;
1257 int dnLen = GET_SHORT((hsdata+pos)); pos += 2;
1259 /* dump the CA name */
1260 it.type = siBuffer;
1261 it.data = hsdata + pos;
1262 it.len = dnLen;
1263 ca_name = CERT_DerNameToAscii(&it);
1264 if (ca_name) {
1265 PR_fprintf(PR_STDOUT," %s\n", ca_name);
1266 PORT_Free(ca_name);
1267 } else {
1268 PR_fprintf(PR_STDOUT,
1269 " distinguished name [%d]", dnLen);
1270 if (dnLen > 0 && sslhexparse) {
1271 PR_fprintf(PR_STDOUT, " = {\n");
1272 print_hex(dnLen, hsdata + pos);
1273 PR_fprintf(PR_STDOUT, " }\n");
1274 } else {
1275 PR_fprintf(PR_STDOUT, "\n");
1276 }
1277 }
1278 pos += dnLen;
1279 exListLen -= 2 + dnLen;
1280 }
1281 PR_fprintf(PR_STDOUT," }\n");
1282 }
1284 PR_fprintf(PR_STDOUT," }\n");
1285 }
1286 break;
1288 case 14: /* server_hello_done */ /* not much to show here. */ break;
1290 case 15: /* certificate_verify */
1291 if (sslhexparse) print_hex(sslh.length, hsdata);
1292 break;
1294 case 16: /* client key exchange */
1295 {
1296 PR_fprintf(PR_STDOUT," ClientKeyExchange {\n");
1297 PR_fprintf(PR_STDOUT," message = {...}\n");
1298 PR_fprintf(PR_STDOUT," }\n");
1299 }
1300 break;
1302 case 20: /* finished */
1303 PR_fprintf(PR_STDOUT," Finished {\n");
1304 PR_fprintf(PR_STDOUT," verify_data = {...}\n");
1305 if (sslhexparse) print_hex(sslh.length, hsdata);
1306 PR_fprintf(PR_STDOUT," }\n");
1308 if (!isNULLmac(currentcipher) && !s->hMACsize) {
1309 /* To calculate the size of MAC, we subtract the number of known
1310 * bytes of message from the number of remaining bytes in the
1311 * record. This assumes that this is the first record on the
1312 * connection to have a MAC, and that the sender has not put another
1313 * message after the finished message in the handshake record.
1314 * This is only correct for the first transition from unMACed to
1315 * MACed. If the connection switches from one cipher suite to
1316 * another one with a different MAC, this logic will not track that
1317 * change correctly.
1318 */
1319 s->hMACsize = recordLen - (sslh.length + 4);
1320 sslh.length += s->hMACsize; /* skip over the MAC data */
1321 }
1322 break;
1324 case 22: /* certificate_status */
1325 {
1326 SECItem data;
1327 PRFileDesc *ofd;
1328 static int ocspFileNumber;
1329 char ocspFileName[20];
1331 /* skip 4 bytes with handshake numbers, as in ssl3_HandleCertificateStatus */
1332 data.type = siBuffer;
1333 data.data = hsdata + 4;
1334 data.len = sslh.length - 4;
1335 print_status_response(&data);
1337 PR_snprintf(ocspFileName, sizeof ocspFileName, "ocsp.%03d",
1338 ++ocspFileNumber);
1339 ofd = PR_Open(ocspFileName, PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE,
1340 0664);
1341 if (!ofd) {
1342 PR_fprintf(PR_STDOUT,
1343 " data = { couldn't save file '%s' }\n",
1344 ocspFileName);
1345 } else {
1346 PR_Write(ofd, data.data, data.len);
1347 PR_fprintf(PR_STDOUT,
1348 " data = { saved in file '%s' }\n",
1349 ocspFileName);
1350 PR_Close(ofd);
1351 }
1352 }
1353 break;
1355 default:
1356 {
1357 PR_fprintf(PR_STDOUT," UNKNOWN MESSAGE TYPE %d [%d] {\n",
1358 sslh.type, sslh.length);
1359 if (sslhexparse) print_hex(sslh.length, hsdata);
1360 PR_fprintf(PR_STDOUT," }\n");
1362 }
1363 } /* end of switch sslh.type */
1364 offset += sslh.length + 4;
1365 } /* while */
1366 if (offset < recordLen) { /* stuff left over */
1367 int newMsgLen = recordLen - offset;
1368 if (!s->msgBuf) {
1369 s->msgBuf = PORT_Alloc(newMsgLen);
1370 if (!s->msgBuf) {
1371 PR_ASSERT(s->msgBuf);
1372 showErr( "Malloc failed");
1373 exit(11);
1374 }
1375 s->msgBufSize = newMsgLen;
1376 memcpy(s->msgBuf, recordBuf + offset, newMsgLen);
1377 } else if (newMsgLen > s->msgBufSize) {
1378 unsigned char * newBuf = PORT_Realloc(s->msgBuf, newMsgLen);
1379 if (!newBuf) {
1380 PR_ASSERT(newBuf);
1381 showErr( "Realloc failed");
1382 exit(12);
1383 }
1384 s->msgBuf = newBuf;
1385 s->msgBufSize = newMsgLen;
1386 } else if (offset || s->msgBuf != recordBuf) {
1387 memmove(s->msgBuf, recordBuf + offset, newMsgLen);
1388 }
1389 s->msgBufOffset = newMsgLen;
1390 PR_fprintf(PR_STDOUT," [incomplete handshake message]\n");
1391 } else {
1392 s->msgBufOffset = 0;
1393 }
1394 PR_fprintf(PR_STDOUT," }\n");
1395 }
1398 void print_ssl(DataBufferList *s, int length, unsigned char *buffer)
1399 {
1400 /* -------------------------------------------------------- */
1401 /* first, create a new buffer object for this piece of data. */
1403 DataBuffer *db;
1405 if (s->size == 0 && length > 0 && buffer[0] >= 32 && buffer[0] < 128) {
1406 /* Not an SSL record, treat entire buffer as plaintext */
1407 PR_Write(PR_STDOUT,buffer,length);
1408 return;
1409 }
1411 check_integrity(s);
1413 db = PR_NEW(struct _DataBuffer);
1415 db->buffer = (unsigned char*)PORT_Alloc(length);
1416 db->length = length;
1417 db->offset = 0;
1418 memcpy(db->buffer, buffer, length);
1419 db->next = NULL;
1421 /* now, add it to the stream */
1423 if (s->last != NULL) s->last->next = db;
1424 s->last = db;
1425 s->size += length;
1426 if (s->first == NULL) s->first = db;
1428 check_integrity(s);
1430 /*------------------------------------------------------- */
1431 /* now we look at the stream to see if we have enough data to
1432 decode */
1434 while (s->size > 0 ) {
1435 unsigned char *recordBuf = NULL;
1437 SSLRecord sr;
1438 unsigned recordLen;
1439 unsigned recordsize;
1441 check_integrity(s);
1443 if ( s->first == NULL) {
1444 PR_fprintf(PR_STDOUT,"ERROR: s->first is null\n");
1445 exit(9);
1446 }
1448 /* in the case of an SSL 2 client-hello */
1449 /* will have the high-bit set, whereas an SSL 3 client-hello will not */
1450 /* SSL2 can also send records that begin with the high bit clear.
1451 * This code will incorrectly handle them. XXX
1452 */
1453 if (isV2Session || s->first->buffer[s->first->offset] & 0x80) {
1454 /* it's an SSL 2 packet */
1455 unsigned char lenbuf[3];
1457 /* first, we check if there's enough data for it to be an SSL2-type
1458 * record. What a pain.*/
1459 if (s->size < sizeof lenbuf) {
1460 partial_packet(length, s->size, sizeof lenbuf);
1461 return;
1462 }
1464 /* read the first two bytes off the stream. */
1465 read_stream_bytes(lenbuf, s, sizeof(lenbuf));
1466 recordLen = ((unsigned int)(lenbuf[0] & 0x7f) << 8) + lenbuf[1] +
1467 ((lenbuf[0] & 0x80) ? 2 : 3);
1468 PR_fprintf(PR_STDOUT, "recordLen = %u bytes\n", recordLen);
1470 /* put 'em back on the head of the stream. */
1471 db = PR_NEW(struct _DataBuffer);
1473 db->length = sizeof lenbuf;
1474 db->buffer = (unsigned char*) PORT_Alloc(db->length);
1475 db->offset = 0;
1476 memcpy(db->buffer, lenbuf, sizeof lenbuf);
1478 db->next = s->first;
1479 s->first = db;
1480 if (s->last == NULL)
1481 s->last = db;
1482 s->size += db->length;
1484 /* if there wasn't enough, go back for more. */
1485 if (s->size < recordLen) {
1486 check_integrity(s);
1487 partial_packet(length, s->size, recordLen);
1488 return;
1489 }
1490 partial_packet(length, s->size, recordLen);
1492 /* read in the whole record. */
1493 recordBuf = PORT_Alloc(recordLen);
1494 read_stream_bytes(recordBuf, s, recordLen);
1496 print_sslv2(s, recordBuf, recordLen);
1497 PR_FREEIF(recordBuf);
1498 check_integrity(s);
1500 continue;
1501 }
1503 /***********************************************************/
1504 /* It's SSL v3 */
1505 /***********************************************************/
1506 check_integrity(s);
1508 if (s->size < sizeof sr) {
1509 partial_packet(length, s->size, sizeof(SSLRecord));
1510 return;
1511 }
1513 read_stream_bytes((unsigned char *)&sr, s, sizeof sr);
1515 /* we have read the stream bytes. Look at the length of
1516 the ssl record. If we don't have enough data to satisfy this
1517 request, then put the bytes we just took back at the head
1518 of the queue */
1519 recordsize = GET_SHORT(sr.length);
1521 if (recordsize > s->size) {
1522 db = PR_NEW(struct _DataBuffer);
1524 db->length = sizeof sr;
1525 db->buffer = (unsigned char*) PORT_Alloc(db->length);
1526 db->offset = 0;
1527 memcpy(db->buffer, &sr, sizeof sr);
1528 db->next = s->first;
1530 /* now, add it back on to the head of the stream */
1532 s->first = db;
1533 if (s->last == NULL)
1534 s->last = db;
1535 s->size += db->length;
1537 check_integrity(s);
1538 partial_packet(length, s->size, recordsize);
1539 return;
1540 }
1541 partial_packet(length, s->size, recordsize);
1544 PR_fprintf(PR_STDOUT,"SSLRecord { [%s]\n", get_time_string() );
1545 if (sslhexparse) {
1546 print_hex(5,(unsigned char*)&sr);
1547 }
1549 check_integrity(s);
1551 PR_fprintf(PR_STDOUT," type = %d (",sr.type);
1552 switch(sr.type) {
1553 case 20 :
1554 PR_fprintf(PR_STDOUT,"change_cipher_spec)\n");
1555 break;
1556 case 21 :
1557 PR_fprintf(PR_STDOUT,"alert)\n");
1558 break;
1559 case 22 :
1560 PR_fprintf(PR_STDOUT,"handshake)\n");
1561 break;
1562 case 23 :
1563 PR_fprintf(PR_STDOUT,"application_data)\n");
1564 break;
1565 default:
1566 PR_fprintf(PR_STDOUT,"unknown)\n");
1567 break;
1568 }
1569 PR_fprintf(PR_STDOUT," version = { %d,%d }\n",
1570 (PRUint32)sr.ver_maj,(PRUint32)sr.ver_min);
1571 PR_fprintf(PR_STDOUT," length = %d (0x%x)\n",
1572 (PRUint32)GET_SHORT(sr.length), (PRUint32)GET_SHORT(sr.length));
1575 recordLen = recordsize;
1576 PR_ASSERT(s->size >= recordLen);
1577 if (s->size >= recordLen) {
1578 recordBuf = (unsigned char*) PORT_Alloc(recordLen);
1579 read_stream_bytes(recordBuf, s, recordLen);
1581 if (s->isEncrypted) {
1582 PR_fprintf(PR_STDOUT," < encrypted >\n");
1583 } else { /* not encrypted */
1585 switch(sr.type) {
1586 case 20 : /* change_cipher_spec */
1587 if (sslhexparse) print_hex(recordLen - s->hMACsize,recordBuf);
1588 /* mark to say we can only dump hex form now on
1589 * if it is not one on a null cipher */
1590 s->isEncrypted = isNULLcipher(currentcipher) ? 0 : 1;
1591 break;
1593 case 21 : /* alert */
1594 switch(recordBuf[0]) {
1595 case 1: PR_fprintf(PR_STDOUT, " warning: "); break;
1596 case 2: PR_fprintf(PR_STDOUT, " fatal: "); break;
1597 default: PR_fprintf(PR_STDOUT, " unknown level %d: ", recordBuf[0]); break;
1598 }
1600 switch(recordBuf[1]) {
1601 case 0: PR_FPUTS("close_notify\n" ); break;
1602 case 10: PR_FPUTS("unexpected_message\n" ); break;
1603 case 20: PR_FPUTS("bad_record_mac\n" ); break;
1604 case 21: PR_FPUTS("decryption_failed\n" ); break;
1605 case 22: PR_FPUTS("record_overflow\n" ); break;
1606 case 30: PR_FPUTS("decompression_failure\n" ); break;
1607 case 40: PR_FPUTS("handshake_failure\n" ); break;
1608 case 41: PR_FPUTS("no_certificate\n" ); break;
1609 case 42: PR_FPUTS("bad_certificate\n" ); break;
1610 case 43: PR_FPUTS("unsupported_certificate\n" ); break;
1611 case 44: PR_FPUTS("certificate_revoked\n" ); break;
1612 case 45: PR_FPUTS("certificate_expired\n" ); break;
1613 case 46: PR_FPUTS("certificate_unknown\n" ); break;
1614 case 47: PR_FPUTS("illegal_parameter\n" ); break;
1615 case 48: PR_FPUTS("unknown_ca\n" ); break;
1616 case 49: PR_FPUTS("access_denied\n" ); break;
1617 case 50: PR_FPUTS("decode_error\n" ); break;
1618 case 51: PR_FPUTS("decrypt_error\n" ); break;
1619 case 60: PR_FPUTS("export_restriction\n" ); break;
1620 case 70: PR_FPUTS("protocol_version\n" ); break;
1621 case 71: PR_FPUTS("insufficient_security\n" ); break;
1622 case 80: PR_FPUTS("internal_error\n" ); break;
1623 case 90: PR_FPUTS("user_canceled\n" ); break;
1624 case 100: PR_FPUTS("no_renegotiation\n" ); break;
1625 case 110: PR_FPUTS("unsupported_extension\n" ); break;
1626 case 111: PR_FPUTS("certificate_unobtainable\n" ); break;
1627 case 112: PR_FPUTS("unrecognized_name\n" ); break;
1628 case 113: PR_FPUTS("bad_certificate_status_response\n" ); break;
1629 case 114: PR_FPUTS("bad_certificate_hash_value\n" ); break;
1631 default: PR_fprintf(PR_STDOUT, "unknown alert %d\n", recordBuf[1]);
1632 break;
1633 }
1635 if (sslhexparse) print_hex(recordLen - s->hMACsize,recordBuf);
1636 break;
1638 case 22 : /* handshake */
1639 print_ssl3_handshake( recordBuf, recordLen - s->hMACsize, &sr, s );
1640 break;
1642 case 23 : /* application data */
1643 print_hex(recordLen - s->hMACsize,recordBuf);
1644 break;
1646 default:
1647 print_hex(recordLen - s->hMACsize,recordBuf);
1648 break;
1649 }
1650 if (s->hMACsize) {
1651 PR_fprintf(PR_STDOUT," MAC = {...}\n");
1652 if (sslhexparse) {
1653 unsigned char *offset = recordBuf + (recordLen - s->hMACsize);
1654 print_hex(s->hMACsize, offset);
1655 }
1656 }
1657 } /* not encrypted */
1658 }
1659 PR_fprintf(PR_STDOUT,"}\n");
1660 PR_FREEIF(recordBuf);
1661 check_integrity(s);
1662 }
1663 }
1665 void print_hex(int amt, unsigned char *buf)
1666 {
1667 int i,j,k;
1668 char t[20];
1669 static char string[5000];
1672 for(i=0;i<amt;i++) {
1673 t[1] =0;
1675 if (i%16 ==0) { /* if we are at the beginning of a line */
1676 PR_fprintf(PR_STDOUT,"%4x:",i); /* print the line number */
1677 strcpy(string,"");
1678 }
1680 if (i%4 == 0) {
1681 PR_fprintf(PR_STDOUT," ");
1682 }
1684 j = buf[i];
1686 t[0] = (j >= 0x20 && j < 0x80) ? j : '.';
1688 if (fancy) {
1689 switch (t[0]) {
1690 case '<':
1691 strcpy(t,"<");
1692 break;
1693 case '>':
1694 strcpy(t,">");
1695 break;
1696 case '&':
1697 strcpy(t,"&");
1698 break;
1699 }
1700 }
1701 strcat(string,t);
1703 PR_fprintf(PR_STDOUT,"%02x ",(PRUint8) buf[i]);
1705 /* if we've reached the end of the line - add the string */
1706 if (i%16 == 15) PR_fprintf(PR_STDOUT," | %s\n",string);
1707 }
1708 /* we reached the end of the buffer,*/
1709 /* do we have buffer left over? */
1710 j = i%16;
1711 if (j > 0) {
1712 for (k=0;k<(16-j);k++) {
1713 /* print additional space after every four bytes */
1714 if ((k + j)%4 == 0) {
1715 PR_fprintf(PR_STDOUT," ");
1716 }
1717 PR_fprintf(PR_STDOUT," ");
1718 }
1719 PR_fprintf(PR_STDOUT," | %s\n",string);
1720 }
1721 }
1723 void Usage(void)
1724 {
1725 PR_fprintf(PR_STDERR, "SSLTAP (C) 1997, 1998 Netscape Communications Corporation.\n");
1726 PR_fprintf(PR_STDERR, "Usage: ssltap [-vhfsxl] [-p port] hostname:port\n");
1727 PR_fprintf(PR_STDERR, " -v [prints version string]\n");
1728 PR_fprintf(PR_STDERR, " -h [outputs hex instead of ASCII]\n");
1729 PR_fprintf(PR_STDERR, " -f [turn on Fancy HTML coloring]\n");
1730 PR_fprintf(PR_STDERR, " -s [turn on SSL decoding]\n");
1731 PR_fprintf(PR_STDERR, " -x [turn on extra SSL hex dumps]\n");
1732 PR_fprintf(PR_STDERR, " -p port [specify rendezvous port (default 1924)]\n");
1733 PR_fprintf(PR_STDERR, " -l [loop - continue to wait for more connections]\n");
1736 }
1738 void
1739 showErr(const char * msg)
1740 {
1741 PRErrorCode err = PR_GetError();
1742 const char * errString;
1744 if (err == PR_UNKNOWN_ERROR)
1745 err = PR_CONNECT_RESET_ERROR; /* bug in NSPR. */
1746 errString = SECU_Strerror(err);
1748 if (!errString)
1749 errString = "(no text available)";
1750 PR_fprintf(PR_STDERR, "%s: Error %d: %s: %s", progName, err, errString, msg);
1751 }
1753 int main(int argc, char *argv[])
1754 {
1755 char *hostname=NULL;
1756 PRUint16 rendport=DEFPORT,port;
1757 PRAddrInfo *ai;
1758 void *iter;
1759 PRStatus r;
1760 PRNetAddr na_client,na_server,na_rend;
1761 PRFileDesc *s_server,*s_client,*s_rend; /*rendezvous */
1762 int c_count=0;
1763 PLOptState *optstate;
1764 PLOptStatus status;
1765 SECStatus rv;
1767 progName = argv[0];
1768 optstate = PL_CreateOptState(argc,argv,"fxhslp:");
1769 while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
1770 switch (optstate->option) {
1771 case 'f':
1772 fancy++;
1773 break;
1774 case 'h':
1775 hexparse++;
1776 break;
1777 case 's':
1778 sslparse++;
1779 break;
1780 case 'x':
1781 sslhexparse++;
1782 break;
1783 case 'l':
1784 looparound++;
1785 break;
1786 case 'p':
1787 rendport = atoi(optstate->value);
1788 break;
1789 case '\0':
1790 hostname = PL_strdup(optstate->value);
1791 }
1792 }
1793 if (status == PL_OPT_BAD)
1794 Usage();
1796 if (fancy) {
1797 if (!hexparse && !sslparse) {
1798 PR_fprintf(PR_STDERR,
1799 "Note: use of -f without -s or -h not recommended, \n"
1800 "as the output looks a little strange. It may be useful, however\n");
1801 }
1802 }
1804 if(! hostname ) Usage(), exit(2);
1806 {
1807 char *colon = (char *)strchr(hostname, ':');
1808 if (!colon) {
1809 PR_fprintf(PR_STDERR,
1810 "You must specify the host AND port you wish to connect to\n");
1811 Usage(), exit(3);
1812 }
1813 port = atoi(&colon[1]);
1814 *colon = '\0';
1816 if (port == 0) {
1817 PR_fprintf(PR_STDERR, "Port must be a nonzero number.\n");
1818 exit(4);
1819 }
1820 }
1822 /* find the 'server' IP address so we don't have to look it up later */
1824 if (fancy) {
1825 PR_fprintf(PR_STDOUT,"<HTML><HEAD><TITLE>SSLTAP output</TITLE></HEAD>\n");
1826 PR_fprintf(PR_STDOUT,"<BODY><PRE>\n");
1827 }
1828 PR_fprintf(PR_STDERR,"Looking up \"%s\"...\n", hostname);
1829 ai = PR_GetAddrInfoByName(hostname, PR_AF_UNSPEC, PR_AI_ADDRCONFIG);
1830 if (!ai) {
1831 showErr("Host Name lookup failed\n");
1832 exit(5);
1833 }
1835 iter = NULL;
1836 iter = PR_EnumerateAddrInfo(iter, ai, port, &na_server);
1837 /* set up the port which the client will connect to */
1839 r = PR_InitializeNetAddr(PR_IpAddrAny,rendport,&na_rend);
1840 if (r == PR_FAILURE) {
1841 PR_fprintf(PR_STDERR,
1842 "PR_InitializeNetAddr(,%d,) failed with error %d\n",PR_GetError());
1843 exit(0);
1844 }
1846 rv = NSS_NoDB_Init("");
1847 if (rv != SECSuccess) {
1848 PR_fprintf(PR_STDERR,
1849 "NSS_NoDB_Init() failed with error %d\n",PR_GetError());
1850 exit(5);
1851 }
1853 s_rend = PR_NewTCPSocket();
1854 if (!s_rend) {
1855 showErr("Couldn't create socket\n");
1856 exit(6);
1857 }
1859 if (PR_Bind(s_rend, &na_rend )) {
1860 PR_fprintf(PR_STDERR,"Couldn't bind to port %d (error %d)\n",rendport, PR_GetError());
1861 exit(-1);
1862 }
1864 if ( PR_Listen(s_rend, 5)) {
1865 showErr("Couldn't listen\n");
1866 exit(-1);
1867 }
1869 PR_fprintf(PR_STDERR,"Proxy socket ready and listening\n");
1870 do { /* accept one connection and process it. */
1871 PRPollDesc pds[2];
1873 s_client = PR_Accept(s_rend,&na_client,PR_SecondsToInterval(3600));
1874 if (s_client == NULL) {
1875 showErr("accept timed out\n");
1876 exit(7);
1877 }
1879 s_server = PR_OpenTCPSocket(na_server.raw.family);
1880 if (s_server == NULL) {
1881 showErr("couldn't open new socket to connect to server \n");
1882 exit(8);
1883 }
1885 r = PR_Connect(s_server,&na_server,PR_SecondsToInterval(5));
1887 if ( r == PR_FAILURE )
1888 {
1889 showErr("Couldn't connect\n");
1890 return -1;
1891 }
1893 if (looparound) {
1894 if (fancy) PR_fprintf(PR_STDOUT,"<p><HR><H2>");
1895 PR_fprintf(PR_STDOUT,"Connection #%d [%s]\n", c_count+1,
1896 get_time_string());
1897 if (fancy) PR_fprintf(PR_STDOUT,"</H2>");
1898 }
1901 PR_fprintf(PR_STDOUT,"Connected to %s:%d\n", hostname, port);
1903 #define PD_C 0
1904 #define PD_S 1
1906 pds[PD_C].fd = s_client;
1907 pds[PD_S].fd = s_server;
1908 pds[PD_C].in_flags = PR_POLL_READ;
1909 pds[PD_S].in_flags = PR_POLL_READ;
1911 /* make sure the new connections don't start out encrypted. */
1912 clientstream.isEncrypted = 0;
1913 serverstream.isEncrypted = 0;
1914 isV2Session = 0;
1916 while( (pds[PD_C].in_flags & PR_POLL_READ) != 0 ||
1917 (pds[PD_S].in_flags & PR_POLL_READ) != 0 )
1918 { /* Handle all messages on the connection */
1919 PRInt32 amt;
1920 PRInt32 wrote;
1921 unsigned char buffer[ TAPBUFSIZ ];
1923 amt = PR_Poll(pds,2,PR_INTERVAL_NO_TIMEOUT);
1924 if (amt <= 0) {
1925 if (amt)
1926 showErr( "PR_Poll failed.\n");
1927 else
1928 showErr( "PR_Poll timed out.\n");
1929 break;
1930 }
1932 if (pds[PD_C].out_flags & PR_POLL_EXCEPT) {
1933 showErr( "Exception on client-side socket.\n");
1934 break;
1935 }
1937 if (pds[PD_S].out_flags & PR_POLL_EXCEPT) {
1938 showErr( "Exception on server-side socket.\n");
1939 break;
1940 }
1943 /* read data, copy it to stdout, and write to other socket */
1945 if ((pds[PD_C].in_flags & PR_POLL_READ) != 0 &&
1946 (pds[PD_C].out_flags & PR_POLL_READ) != 0 ) {
1948 amt = PR_Read(s_client, buffer, sizeof(buffer));
1950 if ( amt < 0) {
1951 showErr( "Client socket read failed.\n");
1952 break;
1953 }
1955 if( amt == 0 ) {
1956 PR_fprintf(PR_STDOUT, "Read EOF on Client socket. [%s]\n",
1957 get_time_string() );
1958 pds[PD_C].in_flags &= ~PR_POLL_READ;
1959 PR_Shutdown(s_server, PR_SHUTDOWN_SEND);
1960 continue;
1961 }
1963 PR_fprintf(PR_STDOUT,"--> [\n");
1964 if (fancy) PR_fprintf(PR_STDOUT,"<font color=blue>");
1966 if (hexparse) print_hex(amt, buffer);
1967 if (sslparse) print_ssl(&clientstream,amt,buffer);
1968 if (!hexparse && !sslparse) PR_Write(PR_STDOUT,buffer,amt);
1969 if (fancy) PR_fprintf(PR_STDOUT,"</font>");
1970 PR_fprintf(PR_STDOUT,"]\n");
1972 wrote = PR_Write(s_server, buffer, amt);
1973 if (wrote != amt ) {
1974 if (wrote < 0) {
1975 showErr("Write to server socket failed.\n");
1976 break;
1977 } else {
1978 PR_fprintf(PR_STDERR, "Short write to server socket!\n");
1979 }
1980 }
1981 } /* end of read from client socket. */
1983 /* read data, copy it to stdout, and write to other socket */
1984 if ((pds[PD_S].in_flags & PR_POLL_READ) != 0 &&
1985 (pds[PD_S].out_flags & PR_POLL_READ) != 0 ) {
1987 amt = PR_Read(s_server, buffer, sizeof(buffer));
1989 if ( amt < 0) {
1990 showErr( "error on server-side socket.\n");
1991 break;
1992 }
1994 if( amt == 0 ) {
1995 PR_fprintf(PR_STDOUT, "Read EOF on Server socket. [%s]\n",
1996 get_time_string() );
1997 pds[PD_S].in_flags &= ~PR_POLL_READ;
1998 PR_Shutdown(s_client, PR_SHUTDOWN_SEND);
1999 continue;
2000 }
2002 PR_fprintf(PR_STDOUT,"<-- [\n");
2003 if (fancy) PR_fprintf(PR_STDOUT,"<font color=red>");
2004 if (hexparse) print_hex(amt, (unsigned char *)buffer);
2005 if (sslparse) print_ssl(&serverstream,amt,(unsigned char *)buffer);
2006 if (!hexparse && !sslparse) PR_Write(PR_STDOUT,buffer,amt);
2007 if (fancy) PR_fprintf(PR_STDOUT,"</font>");
2008 PR_fprintf(PR_STDOUT,"]\n");
2011 wrote = PR_Write(s_client, buffer, amt);
2012 if (wrote != amt ) {
2013 if (wrote < 0) {
2014 showErr("Write to client socket failed.\n");
2015 break;
2016 } else {
2017 PR_fprintf(PR_STDERR, "Short write to client socket!\n");
2018 }
2019 }
2021 } /* end of read from server socket. */
2023 /* Loop, handle next message. */
2025 } /* handle messages during a connection loop */
2026 PR_Close(s_client);
2027 PR_Close(s_server);
2028 flush_stream(&clientstream);
2029 flush_stream(&serverstream);
2030 /* Connection is closed, so reset the current cipher */
2031 currentcipher = 0;
2032 c_count++;
2033 PR_fprintf(PR_STDERR,"Connection %d Complete [%s]\n", c_count,
2034 get_time_string() );
2035 } while (looparound); /* accept connection and process it. */
2036 PR_Close(s_rend);
2037 NSS_Shutdown();
2038 return 0;
2039 }