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/. */
4
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 */
24
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>
31
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* */
38
39 struct _DataBufferList;
40 struct _DataBuffer;
41
42 typedef struct _DataBufferList {
43 struct _DataBuffer *first, *last;
44 unsigned int size;
45 int isEncrypted;
46 unsigned char *msgBuf;
47 unsigned int msgBufOffset;
48 unsigned int msgBufSize;
49 unsigned int hMACsize;
50 } DataBufferList;
51
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;
58
59 struct sslhandshake {
60 PRUint8 type;
61 PRUint32 length;
62 };
63
64 typedef struct _SSLRecord {
65 PRUint8 type;
66 PRUint8 ver_maj, ver_min;
67
68 PRUint8 length[2];
69 } SSLRecord;
70
71 typedef struct _ClientHelloV2 {
72 PRUint8 length[2];
73 PRUint8 type;
74 PRUint8 version[2];
75 PRUint8 cslength[2];
76 PRUint8 sidlength[2];
77 PRUint8 rndlength[2];
78 PRUint8 csuites[1];
79 } ClientHelloV2;
80
81 typedef struct _ServerHelloV2 {
82 PRUint8 length[2];
83 PRUint8 type;
84 PRUint8 sidhit;
85 PRUint8 certtype;
86 PRUint8 version[2];
87 PRUint8 certlength[2];
88 PRUint8 cslength[2];
89 PRUint8 cidlength[2];
90 } ServerHelloV2;
91
92 typedef struct _ClientMasterKeyV2 {
93 PRUint8 length[2];
94 PRUint8 type;
95
96 PRUint8 cipherkind[3];
97 PRUint8 clearkey[2];
98 PRUint8 secretkey[2];
99
100 } ClientMasterKeyV2;
101
102 /* forward declaration */
103 void showErr(const char *msg);
104
105 #define TAPBUFSIZ 16384
106
107 #define DEFPORT 1924
108 #include <ctype.h>
109
110 const char *progName;
111 int hexparse = 0;
112 int sslparse = 0;
113 int sslhexparse = 0;
114 int looparound = 0;
115 int fancy = 0;
116 int isV2Session = 0;
117 int currentcipher = 0;
118 DataBufferList clientstream, serverstream;
119
120 #define PR_FPUTS(x) PR_fprintf(PR_STDOUT, x)
121
122 #define GET_SHORT(x) ((PRUint16)(((PRUint16)((PRUint8 *)x)[0]) << 8) + ((PRUint16)((PRUint8 *)x)[1]))
123 #define GET_24(x) ((PRUint32)( \
124 (((PRUint32)((PRUint8 *)x)[0]) << 16) + \
125 (((PRUint32)((PRUint8 *)x)[1]) << 8) + \
126 (((PRUint32)((PRUint8 *)x)[2]) << 0)))
127 #define GET_32(x) ((PRUint32)( \
128 (((PRUint32)((PRUint8 *)x)[0]) << 24) + \
129 (((PRUint32)((PRUint8 *)x)[1]) << 16) + \
130 (((PRUint32)((PRUint8 *)x)[2]) << 8) + \
131 (((PRUint32)((PRUint8 *)x)[3]) << 0)))
132
133 void print_hex(int amt, unsigned char *buf);
134 void read_stream_bytes(unsigned char *d, DataBufferList *db, int length);
135
136 void
myhalt(int dblsize,int collectedsize)137 myhalt(int dblsize, int collectedsize)
138 {
139
140 PR_fprintf(PR_STDERR, "HALTED\n");
141 PR_ASSERT(dblsize == collectedsize);
142 exit(13);
143 }
144
145 const char *
get_error_text(int error)146 get_error_text(int error)
147 {
148 switch (error) {
149 case PR_IO_TIMEOUT_ERROR:
150 return "Timeout";
151 break;
152 case PR_CONNECT_REFUSED_ERROR:
153 return "Connection refused";
154 break;
155 case PR_NETWORK_UNREACHABLE_ERROR:
156 return "Network unreachable";
157 break;
158 case PR_BAD_ADDRESS_ERROR:
159 return "Bad address";
160 break;
161 case PR_CONNECT_RESET_ERROR:
162 return "Connection reset";
163 break;
164 case PR_PIPE_ERROR:
165 return "Pipe error";
166 break;
167 }
168
169 return "";
170 }
171
172 void
check_integrity(DataBufferList * dbl)173 check_integrity(DataBufferList *dbl)
174 {
175 DataBuffer *db;
176 int i;
177
178 db = dbl->first;
179 i = 0;
180 while (db) {
181 i += db->length - db->offset;
182 db = db->next;
183 }
184 if (i != dbl->size) {
185 myhalt(dbl->size, i);
186 }
187 }
188
189 /* Free's the DataBuffer at the head of the list and returns the pointer
190 * to the new head of the list.
191 */
192 DataBuffer *
free_head(DataBufferList * dbl)193 free_head(DataBufferList *dbl)
194 {
195 DataBuffer *db = dbl->first;
196 PR_ASSERT(db->offset >= db->length);
197 if (db->offset >= db->length) {
198 dbl->first = db->next;
199 if (dbl->first == NULL) {
200 dbl->last = NULL;
201 }
202 PORT_Free(db->buffer);
203 PORT_Free(db);
204 db = dbl->first;
205 }
206 return db;
207 }
208
209 void
read_stream_bytes(unsigned char * d,DataBufferList * dbl,int length)210 read_stream_bytes(unsigned char *d, DataBufferList *dbl, int length)
211 {
212 int copied = 0;
213 DataBuffer *db = dbl->first;
214
215 if (!db) {
216 PR_fprintf(PR_STDERR, "assert failed - dbl->first is null\n");
217 exit(8);
218 }
219 while (length) {
220 int toCopy;
221 /* find the number of bytes to copy from the head buffer */
222 /* if there's too many in this buffer, then only copy 'length' */
223 toCopy = PR_MIN(db->length - db->offset, length);
224
225 memcpy(d + copied, db->buffer + db->offset, toCopy);
226 copied += toCopy;
227 db->offset += toCopy;
228 length -= toCopy;
229 dbl->size -= toCopy;
230
231 /* if we emptied the head buffer */
232 if (db->offset >= db->length) {
233 db = free_head(dbl);
234 }
235 }
236
237 check_integrity(dbl);
238 }
239
240 void
flush_stream(DataBufferList * dbl)241 flush_stream(DataBufferList *dbl)
242 {
243 DataBuffer *db = dbl->first;
244 check_integrity(dbl);
245 while (db) {
246 db->offset = db->length;
247 db = free_head(dbl);
248 }
249 dbl->size = 0;
250 check_integrity(dbl);
251 if (dbl->msgBuf) {
252 PORT_Free(dbl->msgBuf);
253 dbl->msgBuf = NULL;
254 }
255 dbl->msgBufOffset = 0;
256 dbl->msgBufSize = 0;
257 dbl->hMACsize = 0;
258 }
259
260 const char *
V2CipherString(int cs_int)261 V2CipherString(int cs_int)
262 {
263 char *cs_str;
264 cs_str = NULL;
265 switch (cs_int) {
266
267 case 0x010080:
268 cs_str = "SSL2/RSA/RC4-128/MD5";
269 break;
270 case 0x020080:
271 cs_str = "SSL2/RSA/RC4-40/MD5";
272 break;
273 case 0x030080:
274 cs_str = "SSL2/RSA/RC2CBC128/MD5";
275 break;
276 case 0x040080:
277 cs_str = "SSL2/RSA/RC2CBC40/MD5";
278 break;
279 case 0x050080:
280 cs_str = "SSL2/RSA/IDEA128CBC/MD5";
281 break;
282 case 0x060040:
283 cs_str = "SSL2/RSA/DES56-CBC/MD5";
284 break;
285 case 0x0700C0:
286 cs_str = "SSL2/RSA/3DES192EDE-CBC/MD5";
287 break;
288
289 case 0x000001:
290 cs_str = "SSL3/RSA/NULL/MD5";
291 break;
292 case 0x000002:
293 cs_str = "SSL3/RSA/NULL/SHA";
294 break;
295 case 0x000003:
296 cs_str = "SSL3/RSA/RC4-40/MD5";
297 break;
298 case 0x000004:
299 cs_str = "SSL3/RSA/RC4-128/MD5";
300 break;
301 case 0x000005:
302 cs_str = "SSL3/RSA/RC4-128/SHA";
303 break;
304 case 0x000006:
305 cs_str = "SSL3/RSA/RC2CBC40/MD5";
306 break;
307 case 0x000007:
308 cs_str = "SSL3/RSA/IDEA128CBC/SHA";
309 break;
310 case 0x000008:
311 cs_str = "SSL3/RSA/DES40-CBC/SHA";
312 break;
313 case 0x000009:
314 cs_str = "SSL3/RSA/DES56-CBC/SHA";
315 break;
316 case 0x00000A:
317 cs_str = "SSL3/RSA/3DES192EDE-CBC/SHA";
318 break;
319
320 case 0x00000B:
321 cs_str = "SSL3/DH-DSS/DES40-CBC/SHA";
322 break;
323 case 0x00000C:
324 cs_str = "SSL3/DH-DSS/DES56-CBC/SHA";
325 break;
326 case 0x00000D:
327 cs_str = "SSL3/DH-DSS/DES192EDE3CBC/SHA";
328 break;
329 case 0x00000E:
330 cs_str = "SSL3/DH-RSA/DES40-CBC/SHA";
331 break;
332 case 0x00000F:
333 cs_str = "SSL3/DH-RSA/DES56-CBC/SHA";
334 break;
335 case 0x000010:
336 cs_str = "SSL3/DH-RSA/3DES192EDE-CBC/SHA";
337 break;
338
339 case 0x000011:
340 cs_str = "SSL3/DHE-DSS/DES40-CBC/SHA";
341 break;
342 case 0x000012:
343 cs_str = "SSL3/DHE-DSS/DES56-CBC/SHA";
344 break;
345 case 0x000013:
346 cs_str = "SSL3/DHE-DSS/DES192EDE3CBC/SHA";
347 break;
348 case 0x000014:
349 cs_str = "SSL3/DHE-RSA/DES40-CBC/SHA";
350 break;
351 case 0x000015:
352 cs_str = "SSL3/DHE-RSA/DES56-CBC/SHA";
353 break;
354 case 0x000016:
355 cs_str = "SSL3/DHE-RSA/3DES192EDE-CBC/SHA";
356 break;
357
358 case 0x000017:
359 cs_str = "SSL3/DH-anon/RC4-40/MD5";
360 break;
361 case 0x000018:
362 cs_str = "SSL3/DH-anon/RC4-128/MD5";
363 break;
364 case 0x000019:
365 cs_str = "SSL3/DH-anon/DES40-CBC/SHA";
366 break;
367 case 0x00001A:
368 cs_str = "SSL3/DH-anon/DES56-CBC/SHA";
369 break;
370 case 0x00001B:
371 cs_str = "SSL3/DH-anon/3DES192EDE-CBC/SHA";
372 break;
373
374 case 0x00001C:
375 cs_str = "SSL3/FORTEZZA-DMS/NULL/SHA";
376 break;
377 case 0x00001D:
378 cs_str = "SSL3/FORTEZZA-DMS/FORTEZZA-CBC/SHA";
379 break;
380 case 0x00001E:
381 cs_str = "SSL3/FORTEZZA-DMS/RC4-128/SHA";
382 break;
383
384 case 0x00002F:
385 cs_str = "TLS/RSA/AES128-CBC/SHA";
386 break;
387 case 0x000030:
388 cs_str = "TLS/DH-DSS/AES128-CBC/SHA";
389 break;
390 case 0x000031:
391 cs_str = "TLS/DH-RSA/AES128-CBC/SHA";
392 break;
393 case 0x000032:
394 cs_str = "TLS/DHE-DSS/AES128-CBC/SHA";
395 break;
396 case 0x000033:
397 cs_str = "TLS/DHE-RSA/AES128-CBC/SHA";
398 break;
399 case 0x000034:
400 cs_str = "TLS/DH-ANON/AES128-CBC/SHA";
401 break;
402
403 case 0x000035:
404 cs_str = "TLS/RSA/AES256-CBC/SHA";
405 break;
406 case 0x000036:
407 cs_str = "TLS/DH-DSS/AES256-CBC/SHA";
408 break;
409 case 0x000037:
410 cs_str = "TLS/DH-RSA/AES256-CBC/SHA";
411 break;
412 case 0x000038:
413 cs_str = "TLS/DHE-DSS/AES256-CBC/SHA";
414 break;
415 case 0x000039:
416 cs_str = "TLS/DHE-RSA/AES256-CBC/SHA";
417 break;
418 case 0x00003A:
419 cs_str = "TLS/DH-ANON/AES256-CBC/SHA";
420 break;
421
422 case 0x00003B:
423 cs_str = "TLS/RSA/NULL/SHA256";
424 break;
425 case 0x00003C:
426 cs_str = "TLS/RSA/AES128-CBC/SHA256";
427 break;
428 case 0x00003D:
429 cs_str = "TLS/RSA/AES256-CBC/SHA256";
430 break;
431 case 0x00003E:
432 cs_str = "TLS/DH-DSS/AES128-CBC/SHA256";
433 break;
434 case 0x00003F:
435 cs_str = "TLS/DH-RSA/AES128-CBC/SHA256";
436 break;
437 case 0x000040:
438 cs_str = "TLS/DHE-DSS/AES128-CBC/SHA256";
439 break;
440
441 case 0x000041:
442 cs_str = "TLS/RSA/CAMELLIA128-CBC/SHA";
443 break;
444 case 0x000042:
445 cs_str = "TLS/DH-DSS/CAMELLIA128-CBC/SHA";
446 break;
447 case 0x000043:
448 cs_str = "TLS/DH-RSA/CAMELLIA128-CBC/SHA";
449 break;
450 case 0x000044:
451 cs_str = "TLS/DHE-DSS/CAMELLIA128-CBC/SHA";
452 break;
453 case 0x000045:
454 cs_str = "TLS/DHE-RSA/CAMELLIA128-CBC/SHA";
455 break;
456 case 0x000046:
457 cs_str = "TLS/DH-ANON/CAMELLIA128-CBC/SHA";
458 break;
459
460 case 0x000060:
461 cs_str = "TLS/RSA-EXPORT1024/RC4-56/MD5";
462 break;
463 case 0x000061:
464 cs_str = "TLS/RSA-EXPORT1024/RC2CBC56/MD5";
465 break;
466 case 0x000062:
467 cs_str = "TLS/RSA-EXPORT1024/DES56-CBC/SHA";
468 break;
469 case 0x000064:
470 cs_str = "TLS/RSA-EXPORT1024/RC4-56/SHA";
471 break;
472 case 0x000063:
473 cs_str = "TLS/DHE-DSS_EXPORT1024/DES56-CBC/SHA";
474 break;
475 case 0x000065:
476 cs_str = "TLS/DHE-DSS_EXPORT1024/RC4-56/SHA";
477 break;
478 case 0x000066:
479 cs_str = "TLS/DHE-DSS/RC4-128/SHA";
480 break;
481
482 case 0x000067:
483 cs_str = "TLS/DHE-RSA/AES128-CBC/SHA256";
484 break;
485 case 0x000068:
486 cs_str = "TLS/DH-DSS/AES256-CBC/SHA256";
487 break;
488 case 0x000069:
489 cs_str = "TLS/DH-RSA/AES256-CBC/SHA256";
490 break;
491 case 0x00006A:
492 cs_str = "TLS/DHE-DSS/AES256-CBC/SHA256";
493 break;
494 case 0x00006B:
495 cs_str = "TLS/DHE-RSA/AES256-CBC/SHA256";
496 break;
497
498 case 0x000072:
499 cs_str = "TLS/DHE-DSS/3DESEDE-CBC/RMD160";
500 break;
501 case 0x000073:
502 cs_str = "TLS/DHE-DSS/AES128-CBC/RMD160";
503 break;
504 case 0x000074:
505 cs_str = "TLS/DHE-DSS/AES256-CBC/RMD160";
506 break;
507
508 case 0x000079:
509 cs_str = "TLS/DHE-RSA/AES256-CBC/RMD160";
510 break;
511
512 case 0x00007C:
513 cs_str = "TLS/RSA/3DESEDE-CBC/RMD160";
514 break;
515 case 0x00007D:
516 cs_str = "TLS/RSA/AES128-CBC/RMD160";
517 break;
518 case 0x00007E:
519 cs_str = "TLS/RSA/AES256-CBC/RMD160";
520 break;
521
522 case 0x000080:
523 cs_str = "TLS/GOST341094/GOST28147-OFB/GOST28147";
524 break;
525 case 0x000081:
526 cs_str = "TLS/GOST34102001/GOST28147-OFB/GOST28147";
527 break;
528 case 0x000082:
529 cs_str = "TLS/GOST341094/NULL/GOSTR3411";
530 break;
531 case 0x000083:
532 cs_str = "TLS/GOST34102001/NULL/GOSTR3411";
533 break;
534
535 case 0x000084:
536 cs_str = "TLS/RSA/CAMELLIA256-CBC/SHA";
537 break;
538 case 0x000085:
539 cs_str = "TLS/DH-DSS/CAMELLIA256-CBC/SHA";
540 break;
541 case 0x000086:
542 cs_str = "TLS/DH-RSA/CAMELLIA256-CBC/SHA";
543 break;
544 case 0x000087:
545 cs_str = "TLS/DHE-DSS/CAMELLIA256-CBC/SHA";
546 break;
547 case 0x000088:
548 cs_str = "TLS/DHE-RSA/CAMELLIA256-CBC/SHA";
549 break;
550 case 0x000089:
551 cs_str = "TLS/DH-ANON/CAMELLIA256-CBC/SHA";
552 break;
553 case 0x00008A:
554 cs_str = "TLS/PSK/RC4-128/SHA";
555 break;
556 case 0x00008B:
557 cs_str = "TLS/PSK/3DES-EDE-CBC/SHA";
558 break;
559 case 0x00008C:
560 cs_str = "TLS/PSK/AES128-CBC/SHA";
561 break;
562 case 0x00008D:
563 cs_str = "TLS/PSK/AES256-CBC/SHA";
564 break;
565 case 0x00008E:
566 cs_str = "TLS/DHE-PSK/RC4-128/SHA";
567 break;
568 case 0x00008F:
569 cs_str = "TLS/DHE-PSK/3DES-EDE-CBC/SHA";
570 break;
571 case 0x000090:
572 cs_str = "TLS/DHE-PSK/AES128-CBC/SHA";
573 break;
574 case 0x000091:
575 cs_str = "TLS/DHE-PSK/AES256-CBC/SHA";
576 break;
577 case 0x000092:
578 cs_str = "TLS/RSA-PSK/RC4-128/SHA";
579 break;
580 case 0x000093:
581 cs_str = "TLS/RSA-PSK/3DES-EDE-CBC/SHA";
582 break;
583 case 0x000094:
584 cs_str = "TLS/RSA-PSK/AES128-CBC/SHA";
585 break;
586 case 0x000095:
587 cs_str = "TLS/RSA-PSK/AES256-CBC/SHA";
588 break;
589 case 0x000096:
590 cs_str = "TLS/RSA/SEED-CBC/SHA";
591 break;
592 case 0x000097:
593 cs_str = "TLS/DH-DSS/SEED-CBC/SHA";
594 break;
595 case 0x000098:
596 cs_str = "TLS/DH-RSA/SEED-CBC/SHA";
597 break;
598 case 0x000099:
599 cs_str = "TLS/DHE-DSS/SEED-CBC/SHA";
600 break;
601 case 0x00009A:
602 cs_str = "TLS/DHE-RSA/SEED-CBC/SHA";
603 break;
604 case 0x00009B:
605 cs_str = "TLS/DH-ANON/SEED-CBC/SHA";
606 break;
607 case 0x00009C:
608 cs_str = "TLS/RSA/AES128-GCM/SHA256";
609 break;
610 case 0x00009E:
611 cs_str = "TLS/DHE-RSA/AES128-GCM/SHA256";
612 break;
613
614 case 0x0000FF:
615 cs_str = "TLS_EMPTY_RENEGOTIATION_INFO_SCSV";
616 break;
617 case 0x005600:
618 cs_str = "TLS_FALLBACK_SCSV";
619 break;
620
621 case 0x00C001:
622 cs_str = "TLS/ECDH-ECDSA/NULL/SHA";
623 break;
624 case 0x00C002:
625 cs_str = "TLS/ECDH-ECDSA/RC4-128/SHA";
626 break;
627 case 0x00C003:
628 cs_str = "TLS/ECDH-ECDSA/3DES-EDE-CBC/SHA";
629 break;
630 case 0x00C004:
631 cs_str = "TLS/ECDH-ECDSA/AES128-CBC/SHA";
632 break;
633 case 0x00C005:
634 cs_str = "TLS/ECDH-ECDSA/AES256-CBC/SHA";
635 break;
636 case 0x00C006:
637 cs_str = "TLS/ECDHE-ECDSA/NULL/SHA";
638 break;
639 case 0x00C007:
640 cs_str = "TLS/ECDHE-ECDSA/RC4-128/SHA";
641 break;
642 case 0x00C008:
643 cs_str = "TLS/ECDHE-ECDSA/3DES-EDE-CBC/SHA";
644 break;
645 case 0x00C009:
646 cs_str = "TLS/ECDHE-ECDSA/AES128-CBC/SHA";
647 break;
648 case 0x00C00A:
649 cs_str = "TLS/ECDHE-ECDSA/AES256-CBC/SHA";
650 break;
651 case 0x00C00B:
652 cs_str = "TLS/ECDH-RSA/NULL/SHA";
653 break;
654 case 0x00C00C:
655 cs_str = "TLS/ECDH-RSA/RC4-128/SHA";
656 break;
657 case 0x00C00D:
658 cs_str = "TLS/ECDH-RSA/3DES-EDE-CBC/SHA";
659 break;
660 case 0x00C00E:
661 cs_str = "TLS/ECDH-RSA/AES128-CBC/SHA";
662 break;
663 case 0x00C00F:
664 cs_str = "TLS/ECDH-RSA/AES256-CBC/SHA";
665 break;
666 case 0x00C010:
667 cs_str = "TLS/ECDHE-RSA/NULL/SHA";
668 break;
669 case 0x00C011:
670 cs_str = "TLS/ECDHE-RSA/RC4-128/SHA";
671 break;
672 case 0x00C012:
673 cs_str = "TLS/ECDHE-RSA/3DES-EDE-CBC/SHA";
674 break;
675 case 0x00C013:
676 cs_str = "TLS/ECDHE-RSA/AES128-CBC/SHA";
677 break;
678 case 0x00C014:
679 cs_str = "TLS/ECDHE-RSA/AES256-CBC/SHA";
680 break;
681 case 0x00C015:
682 cs_str = "TLS/ECDH-anon/NULL/SHA";
683 break;
684 case 0x00C016:
685 cs_str = "TLS/ECDH-anon/RC4-128/SHA";
686 break;
687 case 0x00C017:
688 cs_str = "TLS/ECDH-anon/3DES-EDE-CBC/SHA";
689 break;
690 case 0x00C018:
691 cs_str = "TLS/ECDH-anon/AES128-CBC/SHA";
692 break;
693 case 0x00C019:
694 cs_str = "TLS/ECDH-anon/AES256-CBC/SHA";
695 break;
696
697 case 0x00C023:
698 cs_str = "TLS/ECDHE-ECDSA/AES128-CBC/SHA256";
699 break;
700 case 0x00C024:
701 cs_str = "TLS/ECDHE-ECDSA/AES256-CBC/SHA384";
702 break;
703 case 0x00C025:
704 cs_str = "TLS/ECDH-ECDSA/AES128-CBC/SHA256";
705 break;
706 case 0x00C026:
707 cs_str = "TLS/ECDH-ECDSA/AES256-CBC/SHA384";
708 break;
709 case 0x00C027:
710 cs_str = "TLS/ECDHE-RSA/AES128-CBC/SHA256";
711 break;
712 case 0x00C028:
713 cs_str = "TLS/ECDHE-RSA/AES256-CBC/SHA384";
714 break;
715 case 0x00C029:
716 cs_str = "TLS/ECDH-RSA/AES128-CBC/SHA256";
717 break;
718 case 0x00C02A:
719 cs_str = "TLS/ECDH-RSA/AES256-CBC/SHA384";
720 break;
721 case 0x00C02B:
722 cs_str = "TLS/ECDHE-ECDSA/AES128-GCM/SHA256";
723 break;
724 case 0x00C02C:
725 cs_str = "TLS/ECDHE-ECDSA/AES256-GCM/SHA384";
726 break;
727 case 0x00C02F:
728 cs_str = "TLS/ECDHE-RSA/AES128-GCM/SHA256";
729 break;
730
731 case 0x00CCA8:
732 cs_str = "TLS/ECDHE-RSA/CHACHA20-POLY1305/SHA256";
733 break;
734 case 0x00CCA9:
735 cs_str = "TLS/ECDHE-ECDSA/CHACHA20-POLY1305/SHA256";
736 break;
737 case 0x00CCAA:
738 cs_str = "TLS/DHE-RSA/CHACHA20-POLY1305/SHA256";
739 break;
740
741 case 0x00FEFF:
742 cs_str = "SSL3/RSA-FIPS/3DESEDE-CBC/SHA";
743 break;
744 case 0x00FEFE:
745 cs_str = "SSL3/RSA-FIPS/DES-CBC/SHA";
746 break;
747 case 0x00FFE1:
748 cs_str = "SSL3/RSA-FIPS/DES56-CBC/SHA";
749 break;
750 case 0x00FFE0:
751 cs_str = "SSL3/RSA-FIPS/3DES192EDE-CBC/SHA";
752 break;
753
754 /* the string literal is broken up to avoid trigraphs */
755 default:
756 cs_str = "????"
757 "/????????"
758 "/?????????"
759 "/???";
760 break;
761 }
762
763 return cs_str;
764 }
765
766 const char *
CompressionMethodString(int cm_int)767 CompressionMethodString(int cm_int)
768 {
769 char *cm_str;
770 cm_str = NULL;
771 switch (cm_int) {
772 case 0:
773 cm_str = "NULL";
774 break;
775 case 1:
776 cm_str = "DEFLATE";
777 break; /* RFC 3749 */
778 case 64:
779 cm_str = "LZS";
780 break; /* RFC 3943 */
781 default:
782 cm_str = "???";
783 break;
784 }
785
786 return cm_str;
787 }
788
789 const char *
helloExtensionNameString(int ex_num)790 helloExtensionNameString(int ex_num)
791 {
792 const char *ex_name = NULL;
793 static char buf[10];
794
795 switch (ex_num) {
796 case 0:
797 ex_name = "server_name";
798 break;
799 case 1:
800 ex_name = "max_fragment_length";
801 break;
802 case 2:
803 ex_name = "client_certificate_url";
804 break;
805 case 3:
806 ex_name = "trusted_ca_keys";
807 break;
808 case 4:
809 ex_name = "truncated_hmac";
810 break;
811 case 5:
812 ex_name = "status_request";
813 break;
814 case 10:
815 ex_name = "elliptic_curves";
816 break;
817 case 11:
818 ex_name = "ec_point_formats";
819 break;
820 case 13:
821 ex_name = "signature_algorithms";
822 break;
823 case 35:
824 ex_name = "session_ticket";
825 break;
826 case 0xff01:
827 ex_name = "renegotiation_info";
828 break;
829 default:
830 sprintf(buf, "%d", ex_num);
831 ex_name = (const char *)buf;
832 break;
833 }
834
835 return ex_name;
836 }
837
838 static int
isNULLmac(int cs_int)839 isNULLmac(int cs_int)
840 {
841 return (cs_int == TLS_NULL_WITH_NULL_NULL);
842 }
843
844 static int
isNULLcipher(int cs_int)845 isNULLcipher(int cs_int)
846 {
847 return ((cs_int == TLS_RSA_WITH_NULL_MD5) ||
848 (cs_int == TLS_RSA_WITH_NULL_SHA) ||
849 (cs_int == SSL_FORTEZZA_DMS_WITH_NULL_SHA) ||
850 (cs_int == TLS_ECDH_ECDSA_WITH_NULL_SHA) ||
851 (cs_int == TLS_ECDHE_ECDSA_WITH_NULL_SHA) ||
852 (cs_int == TLS_ECDH_RSA_WITH_NULL_SHA) ||
853 (cs_int == TLS_ECDHE_RSA_WITH_NULL_SHA));
854 }
855
856 void
partial_packet(int thispacket,int size,int needed)857 partial_packet(int thispacket, int size, int needed)
858 {
859 PR_fprintf(PR_STDOUT, "(%u bytes", thispacket);
860 if (thispacket < needed) {
861 PR_fprintf(PR_STDOUT, ", making %u", size);
862 }
863 PR_fprintf(PR_STDOUT, " of %u", needed);
864 if (size > needed) {
865 PR_fprintf(PR_STDOUT, ", with %u left over", size - needed);
866 }
867 PR_fprintf(PR_STDOUT, ")\n");
868 }
869
870 char *
get_time_string(void)871 get_time_string(void)
872 {
873 char *cp;
874 char *eol;
875 time_t tt;
876
877 time(&tt);
878 cp = ctime(&tt);
879 eol = strchr(cp, '\n');
880 if (eol)
881 *eol = 0;
882 return cp;
883 }
884
885 void
print_sslv2(DataBufferList * s,unsigned char * recordBuf,unsigned int recordLen)886 print_sslv2(DataBufferList *s, unsigned char *recordBuf, unsigned int recordLen)
887 {
888 ClientHelloV2 *chv2;
889 ServerHelloV2 *shv2;
890 unsigned char *pos;
891 unsigned int p;
892 unsigned int q;
893 PRUint32 len;
894
895 chv2 = (ClientHelloV2 *)recordBuf;
896 shv2 = (ServerHelloV2 *)recordBuf;
897 if (s->isEncrypted) {
898 PR_fprintf(PR_STDOUT, " [ssl2] Encrypted {...}\n");
899 return;
900 }
901 PR_fprintf(PR_STDOUT, " [%s]", get_time_string());
902 switch (chv2->type) {
903 case 1:
904 PR_fprintf(PR_STDOUT, " [ssl2] ClientHelloV2 {\n");
905 PR_fprintf(PR_STDOUT, " version = {0x%02x, 0x%02x}\n",
906 (PRUint32)chv2->version[0], (PRUint32)chv2->version[1]);
907 PR_fprintf(PR_STDOUT, " cipher-specs-length = %d (0x%02x)\n",
908 (PRUint32)(GET_SHORT((chv2->cslength))),
909 (PRUint32)(GET_SHORT((chv2->cslength))));
910 PR_fprintf(PR_STDOUT, " sid-length = %d (0x%02x)\n",
911 (PRUint32)(GET_SHORT((chv2->sidlength))),
912 (PRUint32)(GET_SHORT((chv2->sidlength))));
913 PR_fprintf(PR_STDOUT, " challenge-length = %d (0x%02x)\n",
914 (PRUint32)(GET_SHORT((chv2->rndlength))),
915 (PRUint32)(GET_SHORT((chv2->rndlength))));
916 PR_fprintf(PR_STDOUT, " cipher-suites = { \n");
917 for (p =
918 0;
919 p < (PRUint32)GET_SHORT((chv2->cslength)); p += 3) {
920 PRUint32 cs_int = GET_24((&chv2->csuites[p]));
921 const char *cs_str =
922 V2CipherString(cs_int);
923
924 PR_fprintf(PR_STDOUT, " (0x%06x) %s\n",
925 cs_int, cs_str);
926 }
927 q = p;
928 PR_fprintf(PR_STDOUT, " }\n");
929 if (GET_SHORT((chv2->sidlength))) {
930 PR_fprintf(PR_STDOUT, " session-id = { ");
931 for (p = 0;
932 p < (PRUint32)GET_SHORT((chv2->sidlength)); p += 2) {
933 PR_fprintf(PR_STDOUT, "0x%04x ", (PRUint32)(GET_SHORT((&chv2->csuites[p + q]))));
934 }
935 }
936 q += p;
937 PR_fprintf(PR_STDOUT, "}\n");
938 if (GET_SHORT((chv2->rndlength))) {
939 PR_fprintf(PR_STDOUT, " challenge = { ");
940 for (p = 0;
941 p < (PRUint32)GET_SHORT((chv2->rndlength)); p += 2) {
942 PR_fprintf(PR_STDOUT, "0x%04x ", (PRUint32)(GET_SHORT((&chv2->csuites[p + q]))));
943 }
944 PR_fprintf(PR_STDOUT, "}\n");
945 }
946 PR_fprintf(PR_STDOUT, "}\n");
947 break;
948 /* end of V2 CLientHello Parsing */
949
950 case 2: /* Client Master Key */
951 {
952 const char *cs_str =
953 NULL;
954 PRUint32 cs_int =
955 0;
956 ClientMasterKeyV2 *cmkv2;
957 cmkv2 = (ClientMasterKeyV2 *)chv2;
958 isV2Session = 1;
959
960 PR_fprintf(PR_STDOUT, " [ssl2] ClientMasterKeyV2 { \n");
961
962 cs_int = GET_24(&cmkv2->cipherkind[0]);
963 cs_str = V2CipherString(cs_int);
964 PR_fprintf(PR_STDOUT, " cipher-spec-chosen = (0x%06x) %s\n",
965 cs_int, cs_str);
966
967 PR_fprintf(PR_STDOUT, " clear-portion = %d bits\n",
968 8 *
969 (PRUint32)(GET_SHORT((cmkv2->clearkey))));
970
971 PR_fprintf(PR_STDOUT, " }\n");
972 clientstream.isEncrypted = 1;
973 serverstream.isEncrypted = 1;
974 } break;
975
976 case 3:
977 PR_fprintf(PR_STDOUT, " [ssl2] Client Finished V2 {...}\n");
978 isV2Session = 1;
979 break;
980
981 case 4: /* V2 Server Hello */
982 isV2Session = 1;
983
984 PR_fprintf(PR_STDOUT, " [ssl2] ServerHelloV2 {\n");
985 PR_fprintf(PR_STDOUT, " sid hit = {0x%02x}\n",
986 (PRUintn)shv2->sidhit);
987 PR_fprintf(PR_STDOUT, " version = {0x%02x, 0x%02x}\n",
988 (PRUint32)shv2->version[0], (PRUint32)shv2->version[1]);
989 PR_fprintf(PR_STDOUT, " cipher-specs-length = %d (0x%02x)\n",
990 (PRUint32)(GET_SHORT((shv2->cslength))),
991 (PRUint32)(GET_SHORT((shv2->cslength))));
992 PR_fprintf(PR_STDOUT, " sid-length = %d (0x%02x)\n",
993 (PRUint32)(GET_SHORT((shv2->cidlength))),
994 (PRUint32)(GET_SHORT((shv2->cidlength))));
995
996 pos = (unsigned char *)shv2;
997 pos += 2; /* skip length header */
998 pos += 11; /* position pointer to Certificate data area */
999 q = GET_SHORT(&shv2->certlength);
1000 if (q > recordLen) {
1001 goto eosh;
1002 }
1003 pos += q; /* skip certificate */
1004
1005 PR_fprintf(PR_STDOUT, " cipher-suites = { ");
1006 len = GET_SHORT((shv2->cslength));
1007 for (p = 0; p < len; p += 3) {
1008 PRUint32 cs_int = GET_24((pos + p));
1009 const char *cs_str =
1010 V2CipherString(cs_int);
1011 PR_fprintf(PR_STDOUT, "\n ");
1012 PR_fprintf(PR_STDOUT, "(0x%06x) %s", cs_int, cs_str);
1013 }
1014 pos += len;
1015 PR_fprintf(PR_STDOUT, " }\n"); /* End of cipher suites */
1016 len = (PRUint32)GET_SHORT((shv2->cidlength));
1017 if (len) {
1018 PR_fprintf(PR_STDOUT, " connection-id = { ");
1019 for (p =
1020 0;
1021 p < len; p += 2) {
1022 PR_fprintf(PR_STDOUT, "0x%04x ", (PRUint32)(GET_SHORT((pos +
1023 p))));
1024 }
1025 PR_fprintf(PR_STDOUT, " }\n"); /* End of connection id */
1026 }
1027 eosh:
1028 PR_fprintf(PR_STDOUT, "\n }\n"); /* end of ServerHelloV2 */
1029 if (shv2->sidhit) {
1030 clientstream.isEncrypted =
1031 1;
1032 serverstream.isEncrypted =
1033 1;
1034 }
1035 break;
1036
1037 case 5:
1038 PR_fprintf(PR_STDOUT, " [ssl2] Server Verify V2 {...}\n");
1039 isV2Session = 1;
1040 break;
1041
1042 case 6:
1043 PR_fprintf(PR_STDOUT, " [ssl2] Server Finished V2 {...}\n");
1044 isV2Session = 1;
1045 break;
1046
1047 case 7:
1048 PR_fprintf(PR_STDOUT, " [ssl2] Request Certificate V2 {...}\n");
1049 isV2Session = 1;
1050 break;
1051
1052 case 8:
1053 PR_fprintf(PR_STDOUT, " [ssl2] Client Certificate V2 {...}\n");
1054 isV2Session = 1;
1055 break;
1056
1057 default:
1058 PR_fprintf(PR_STDOUT, " [ssl2] UnknownType 0x%02x {...}\n",
1059 (PRUint32)chv2->type);
1060 break;
1061 }
1062 }
1063
1064 unsigned int
print_hello_extension(unsigned char * hsdata,unsigned int length,unsigned int pos)1065 print_hello_extension(unsigned char *hsdata,
1066 unsigned int length,
1067 unsigned int pos)
1068 {
1069 /* pretty print extensions, if any */
1070 if (pos < length) {
1071 int exListLen = GET_SHORT((hsdata + pos));
1072 pos += 2;
1073 PR_fprintf(PR_STDOUT,
1074 " extensions[%d] = {\n", exListLen);
1075 while (exListLen > 0 && pos < length) {
1076 int exLen;
1077 int exType = GET_SHORT((hsdata + pos));
1078 pos += 2;
1079 exLen = GET_SHORT((hsdata + pos));
1080 pos += 2;
1081 /* dump the extension */
1082 PR_fprintf(PR_STDOUT,
1083 " extension type %s, length [%d]",
1084 helloExtensionNameString(exType), exLen);
1085 if (exLen > 0) {
1086 PR_fprintf(PR_STDOUT, " = {\n");
1087 print_hex(exLen, hsdata + pos);
1088 PR_fprintf(PR_STDOUT, " }\n");
1089 } else {
1090 PR_fprintf(PR_STDOUT, "\n");
1091 }
1092 pos += exLen;
1093 exListLen -= 2 + exLen;
1094 }
1095 PR_fprintf(PR_STDOUT, " }\n");
1096 }
1097 return pos;
1098 }
1099
1100 /*
1101 * Note this must match (exactly) the enumeration ocspResponseStatus.
1102 */
1103 static char *responseStatusNames[] = {
1104 "successful (Response has valid confirmations)",
1105 "malformedRequest (Illegal confirmation request)",
1106 "internalError (Internal error in issuer)",
1107 "tryLater (Try again later)",
1108 "unused ((4) is not used)",
1109 "sigRequired (Must sign the request)",
1110 "unauthorized (Request unauthorized)",
1111 };
1112
1113 static void
print_ocsp_cert_id(FILE * out_file,CERTOCSPCertID * cert_id,int level)1114 print_ocsp_cert_id(FILE *out_file, CERTOCSPCertID *cert_id, int level)
1115 {
1116 SECU_Indent(out_file, level);
1117 fprintf(out_file, "Cert ID:\n");
1118 level++;
1119 /*
1120 SECU_PrintAlgorithmID (out_file, &(cert_id->hashAlgorithm),
1121 "Hash Algorithm", level);
1122 SECU_PrintAsHex (out_file, &(cert_id->issuerNameHash),
1123 "Issuer Name Hash", level);
1124 SECU_PrintAsHex (out_file, &(cert_id->issuerKeyHash),
1125 "Issuer Key Hash", level);
1126 */
1127 SECU_PrintInteger(out_file, &(cert_id->serialNumber),
1128 "Serial Number", level);
1129 /* XXX lookup the cert; if found, print something nice (nickname?) */
1130 }
1131
1132 static void
print_ocsp_version(FILE * out_file,SECItem * version,int level)1133 print_ocsp_version(FILE *out_file, SECItem *version, int level)
1134 {
1135 if (version->len > 0) {
1136 SECU_PrintInteger(out_file, version, "Version", level);
1137 } else {
1138 SECU_Indent(out_file, level);
1139 fprintf(out_file, "Version: DEFAULT\n");
1140 }
1141 }
1142
1143 static void
print_responder_id(FILE * out_file,ocspResponderID * responderID,int level)1144 print_responder_id(FILE *out_file, ocspResponderID *responderID, int level)
1145 {
1146 SECU_Indent(out_file, level);
1147 fprintf(out_file, "Responder ID ");
1148
1149 switch (responderID->responderIDType) {
1150 case ocspResponderID_byName:
1151 fprintf(out_file, "(byName):\n");
1152 SECU_PrintName(out_file, &(responderID->responderIDValue.name),
1153 "Name", level + 1);
1154 break;
1155 case ocspResponderID_byKey:
1156 fprintf(out_file, "(byKey):\n");
1157 SECU_PrintAsHex(out_file, &(responderID->responderIDValue.keyHash),
1158 "Key Hash", level + 1);
1159 break;
1160 default:
1161 fprintf(out_file, "Unrecognized Responder ID Type\n");
1162 break;
1163 }
1164 }
1165
1166 static void
print_ocsp_extensions(FILE * out_file,CERTCertExtension ** extensions,char * msg,int level)1167 print_ocsp_extensions(FILE *out_file, CERTCertExtension **extensions,
1168 char *msg, int level)
1169 {
1170 if (extensions) {
1171 SECU_PrintExtensions(out_file, extensions, msg, level);
1172 } else {
1173 SECU_Indent(out_file, level);
1174 fprintf(out_file, "No %s\n", msg);
1175 }
1176 }
1177
1178 static void
print_revoked_info(FILE * out_file,ocspRevokedInfo * revoked_info,int level)1179 print_revoked_info(FILE *out_file, ocspRevokedInfo *revoked_info, int level)
1180 {
1181 SECU_PrintGeneralizedTime(out_file, &(revoked_info->revocationTime),
1182 "Revocation Time", level);
1183
1184 if (revoked_info->revocationReason != NULL) {
1185 SECU_PrintAsHex(out_file, revoked_info->revocationReason,
1186 "Revocation Reason", level);
1187 } else {
1188 SECU_Indent(out_file, level);
1189 fprintf(out_file, "No Revocation Reason.\n");
1190 }
1191 }
1192
1193 static void
print_cert_status(FILE * out_file,ocspCertStatus * status,int level)1194 print_cert_status(FILE *out_file, ocspCertStatus *status, int level)
1195 {
1196 SECU_Indent(out_file, level);
1197 fprintf(out_file, "Status: ");
1198
1199 switch (status->certStatusType) {
1200 case ocspCertStatus_good:
1201 fprintf(out_file, "Cert is good.\n");
1202 break;
1203 case ocspCertStatus_revoked:
1204 fprintf(out_file, "Cert has been revoked.\n");
1205 print_revoked_info(out_file, status->certStatusInfo.revokedInfo,
1206 level + 1);
1207 break;
1208 case ocspCertStatus_unknown:
1209 fprintf(out_file, "Cert is unknown to responder.\n");
1210 break;
1211 default:
1212 fprintf(out_file, "Unrecognized status.\n");
1213 break;
1214 }
1215 }
1216
1217 static void
print_single_response(FILE * out_file,CERTOCSPSingleResponse * single,int level)1218 print_single_response(FILE *out_file, CERTOCSPSingleResponse *single,
1219 int level)
1220 {
1221 print_ocsp_cert_id(out_file, single->certID, level);
1222
1223 print_cert_status(out_file, single->certStatus, level);
1224
1225 SECU_PrintGeneralizedTime(out_file, &(single->thisUpdate),
1226 "This Update", level);
1227
1228 if (single->nextUpdate != NULL) {
1229 SECU_PrintGeneralizedTime(out_file, single->nextUpdate,
1230 "Next Update", level);
1231 } else {
1232 SECU_Indent(out_file, level);
1233 fprintf(out_file, "No Next Update\n");
1234 }
1235
1236 print_ocsp_extensions(out_file, single->singleExtensions,
1237 "Single Response Extensions", level);
1238 }
1239
1240 static void
print_response_data(FILE * out_file,ocspResponseData * responseData,int level)1241 print_response_data(FILE *out_file, ocspResponseData *responseData, int level)
1242 {
1243 SECU_Indent(out_file, level);
1244 fprintf(out_file, "Response Data:\n");
1245 level++;
1246
1247 print_ocsp_version(out_file, &(responseData->version), level);
1248
1249 print_responder_id(out_file, responseData->responderID, level);
1250
1251 SECU_PrintGeneralizedTime(out_file, &(responseData->producedAt),
1252 "Produced At", level);
1253
1254 if (responseData->responses != NULL) {
1255 int i;
1256
1257 for (i = 0; responseData->responses[i] != NULL; i++) {
1258 SECU_Indent(out_file, level);
1259 fprintf(out_file, "Response %d:\n", i);
1260 print_single_response(out_file, responseData->responses[i],
1261 level + 1);
1262 }
1263 } else {
1264 fprintf(out_file, "Response list is empty.\n");
1265 }
1266
1267 print_ocsp_extensions(out_file, responseData->responseExtensions,
1268 "Response Extensions", level);
1269 }
1270
1271 static void
print_basic_response(FILE * out_file,ocspBasicOCSPResponse * basic,int level)1272 print_basic_response(FILE *out_file, ocspBasicOCSPResponse *basic, int level)
1273 {
1274 SECU_Indent(out_file, level);
1275 fprintf(out_file, "Basic OCSP Response:\n");
1276 level++;
1277
1278 print_response_data(out_file, basic->tbsResponseData, level);
1279 }
1280
1281 static void
print_status_response(SECItem * data)1282 print_status_response(SECItem *data)
1283 {
1284 int level = 2;
1285 CERTOCSPResponse *response;
1286 response = CERT_DecodeOCSPResponse(data);
1287 if (!response) {
1288 SECU_Indent(stdout, level);
1289 fprintf(stdout, "unable to decode certificate_status\n");
1290 return;
1291 }
1292
1293 SECU_Indent(stdout, level);
1294 if (response->statusValue >= ocspResponse_min &&
1295 response->statusValue <= ocspResponse_max) {
1296 fprintf(stdout, "Response Status: %s\n",
1297 responseStatusNames[response->statusValue]);
1298 } else {
1299 fprintf(stdout,
1300 "Response Status: other (Status value %d out of defined range)\n",
1301 (int)response->statusValue);
1302 }
1303
1304 if (response->statusValue == ocspResponse_successful) {
1305 ocspResponseBytes *responseBytes = response->responseBytes;
1306 PORT_Assert(responseBytes != NULL);
1307
1308 level++;
1309 SECU_PrintObjectID(stdout, &(responseBytes->responseType),
1310 "Response Type", level);
1311 switch (response->responseBytes->responseTypeTag) {
1312 case SEC_OID_PKIX_OCSP_BASIC_RESPONSE:
1313 print_basic_response(stdout,
1314 responseBytes->decodedResponse.basic,
1315 level);
1316 break;
1317 default:
1318 SECU_Indent(stdout, level);
1319 fprintf(stdout, "Unknown response syntax\n");
1320 break;
1321 }
1322 } else {
1323 SECU_Indent(stdout, level);
1324 fprintf(stdout, "Unsuccessful response, no more information.\n");
1325 }
1326
1327 CERT_DestroyOCSPResponse(response);
1328 }
1329
1330 /* In the case of renegotiation, handshakes that occur in an already MAC'ed
1331 * channel, by the time of this call, the caller has already removed the MAC
1332 * from input recordLen. The only MAC'ed record that will get here with its
1333 * MAC intact (not removed) is the first Finished message on the connection.
1334 */
1335 void
print_ssl3_handshake(unsigned char * recordBuf,unsigned int recordLen,SSLRecord * sr,DataBufferList * s)1336 print_ssl3_handshake(unsigned char *recordBuf,
1337 unsigned int recordLen,
1338 SSLRecord *sr,
1339 DataBufferList *s)
1340 {
1341 struct sslhandshake sslh;
1342 unsigned char *hsdata;
1343 unsigned int offset = 0;
1344
1345 PR_fprintf(PR_STDOUT, " handshake {\n");
1346
1347 if (s->msgBufOffset && s->msgBuf) {
1348 /* append recordBuf to msgBuf, then use msgBuf */
1349 if (s->msgBufOffset + recordLen > s->msgBufSize) {
1350 int newSize = s->msgBufOffset + recordLen;
1351 unsigned char *newBuf = PORT_Realloc(s->msgBuf, newSize);
1352 if (!newBuf) {
1353 PR_ASSERT(newBuf);
1354 showErr("Realloc failed");
1355 exit(10);
1356 }
1357 s->msgBuf = newBuf;
1358 s->msgBufSize = newSize;
1359 }
1360 memcpy(s->msgBuf + s->msgBufOffset, recordBuf, recordLen);
1361 s->msgBufOffset += recordLen;
1362 recordLen = s->msgBufOffset;
1363 recordBuf = s->msgBuf;
1364 }
1365 while (offset + 4 <= recordLen) {
1366 sslh.type = recordBuf[offset];
1367 sslh.length = GET_24(recordBuf + offset + 1);
1368 if (offset + 4 + sslh.length > recordLen)
1369 break;
1370 /* finally have a complete message */
1371 if (sslhexparse)
1372 print_hex(4, recordBuf + offset);
1373
1374 hsdata = &recordBuf[offset + 4];
1375
1376 PR_fprintf(PR_STDOUT, " type = %d (", sslh.type);
1377 switch (sslh.type) {
1378 case 0:
1379 PR_FPUTS("hello_request)\n");
1380 break;
1381 case 1:
1382 PR_FPUTS("client_hello)\n");
1383 break;
1384 case 2:
1385 PR_FPUTS("server_hello)\n");
1386 break;
1387 case 4:
1388 PR_FPUTS("new_session_ticket)\n");
1389 break;
1390 case 11:
1391 PR_FPUTS("certificate)\n");
1392 break;
1393 case 12:
1394 PR_FPUTS("server_key_exchange)\n");
1395 break;
1396 case 13:
1397 PR_FPUTS("certificate_request)\n");
1398 break;
1399 case 14:
1400 PR_FPUTS("server_hello_done)\n");
1401 break;
1402 case 15:
1403 PR_FPUTS("certificate_verify)\n");
1404 break;
1405 case 16:
1406 PR_FPUTS("client_key_exchange)\n");
1407 break;
1408 case 20:
1409 PR_FPUTS("finished)\n");
1410 break;
1411 case 22:
1412 PR_FPUTS("certificate_status)\n");
1413 break;
1414 default:
1415 PR_FPUTS("unknown)\n");
1416 break;
1417 }
1418
1419 PR_fprintf(PR_STDOUT, " length = %d (0x%06x)\n", sslh.length, sslh.length);
1420 switch (sslh.type) {
1421
1422 case 0: /* hello_request */ /* not much to show here. */
1423 break;
1424
1425 case 1: /* client hello */
1426 switch (sr->ver_maj) {
1427 case 3: /* ssl version 3 */
1428 {
1429 unsigned int pos;
1430 int w;
1431
1432 PR_fprintf(PR_STDOUT, " ClientHelloV3 {\n");
1433 PR_fprintf(PR_STDOUT, " client_version = {%d, %d}\n",
1434 (PRUint8)hsdata[0], (PRUint8)hsdata[1]);
1435 PR_fprintf(PR_STDOUT, " random = {...}\n");
1436 if (sslhexparse)
1437 print_hex(32, &hsdata[2]);
1438
1439 /* pretty print Session ID */
1440 {
1441 int sidlength =
1442 (int)hsdata[2 + 32];
1443 PR_fprintf(PR_STDOUT, " session ID = {\n");
1444 PR_fprintf(PR_STDOUT, " length = %d\n", sidlength);
1445 PR_fprintf(PR_STDOUT, " contents = {...}\n");
1446 if (sslhexparse)
1447 print_hex(sidlength, &hsdata[2 + 32 + 1]);
1448 PR_fprintf(PR_STDOUT, " }\n");
1449 pos =
1450 2 +
1451 32 +
1452 1 +
1453 sidlength;
1454 }
1455
1456 /* pretty print cipher suites */
1457 {
1458 int csuitelength =
1459 GET_SHORT((hsdata + pos));
1460 PR_fprintf(PR_STDOUT, " cipher_suites[%d] = {\n",
1461 csuitelength /
1462 2);
1463 if (csuitelength %
1464 2) {
1465 PR_fprintf(PR_STDOUT,
1466 "*error in protocol - csuitelength shouldn't be odd*\n");
1467 }
1468 for (w =
1469 0;
1470 w <
1471 csuitelength;
1472 w += 2) {
1473 PRUint32 cs_int =
1474 GET_SHORT((hsdata + pos + 2 + w));
1475 const char *cs_str =
1476 V2CipherString(cs_int);
1477 PR_fprintf(PR_STDOUT,
1478 " (0x%04x) %s\n", cs_int, cs_str);
1479 }
1480 pos +=
1481 2 +
1482 csuitelength;
1483 PR_fprintf(PR_STDOUT, " }\n");
1484 }
1485
1486 /* pretty print compression methods */
1487 {
1488 int complength =
1489 hsdata[pos];
1490 PR_fprintf(PR_STDOUT, " compression[%d] = {\n",
1491 complength);
1492 for (w =
1493 0;
1494 w <
1495 complength;
1496 w++) {
1497 PRUint32 cm_int =
1498 hsdata[pos + 1 + w];
1499 const char *cm_str =
1500 CompressionMethodString(cm_int);
1501 PR_fprintf(PR_STDOUT,
1502 " (%02x) %s\n", cm_int, cm_str);
1503 }
1504 pos +=
1505 1 +
1506 complength;
1507 PR_fprintf(PR_STDOUT, " }\n");
1508 }
1509
1510 /* pretty print extensions, if any */
1511 pos =
1512 print_hello_extension(hsdata, sslh.length, pos);
1513
1514 PR_fprintf(PR_STDOUT, " }\n");
1515 } /* end of ssl version 3 */
1516 break;
1517 default:
1518 PR_fprintf(PR_STDOUT, " UNDEFINED VERSION %d.%d {...}\n",
1519 sr->ver_maj, sr->ver_min);
1520 if (sslhexparse)
1521 print_hex(sslh.length, hsdata);
1522 break;
1523 } /* end of switch sr->ver_maj */
1524 break;
1525
1526 case 2: /* server hello */
1527 {
1528 unsigned int sidlength, pos;
1529
1530 PR_fprintf(PR_STDOUT, " ServerHello {\n");
1531
1532 PR_fprintf(PR_STDOUT, " server_version = {%d, %d}\n",
1533 (PRUint8)hsdata[0], (PRUint8)hsdata[1]);
1534 PR_fprintf(PR_STDOUT, " random = {...}\n");
1535 if (sslhexparse)
1536 print_hex(32, &hsdata[2]);
1537 PR_fprintf(PR_STDOUT, " session ID = {\n");
1538 sidlength = (int)hsdata[2 +
1539 32];
1540 PR_fprintf(PR_STDOUT, " length = %d\n", sidlength);
1541 PR_fprintf(PR_STDOUT, " contents = {...}\n");
1542 if (sslhexparse)
1543 print_hex(sidlength, &hsdata[2 + 32 + 1]);
1544 PR_fprintf(PR_STDOUT, " }\n");
1545 pos = 2 +
1546 32 + 1 +
1547 sidlength;
1548
1549 /* pretty print chosen cipher suite */
1550 {
1551 PRUint32 cs_int = GET_SHORT((hsdata + pos));
1552 const char *cs_str =
1553 V2CipherString(cs_int);
1554 PR_fprintf(PR_STDOUT, " cipher_suite = (0x%04x) %s\n",
1555 cs_int, cs_str);
1556 currentcipher =
1557 cs_int;
1558 pos +=
1559 2;
1560 }
1561 /* pretty print chosen compression method */
1562 {
1563 PRUint32 cm_int = hsdata[pos++];
1564 const char *cm_str =
1565 CompressionMethodString(cm_int);
1566 PR_fprintf(PR_STDOUT, " compression method = (%02x) %s\n",
1567 cm_int, cm_str);
1568 }
1569
1570 /* pretty print extensions, if any */
1571 pos = print_hello_extension(hsdata, sslh.length, pos);
1572
1573 PR_fprintf(PR_STDOUT, " }\n");
1574 } break;
1575
1576 case 4: /* new session ticket */
1577 {
1578 PRUint32 lifetimehint;
1579 PRUint16 ticketlength;
1580 char lifetime[32];
1581 lifetimehint = GET_32(hsdata);
1582 if (lifetimehint) {
1583 PRExplodedTime et;
1584 PRTime t =
1585 lifetimehint;
1586 t *=
1587 PR_USEC_PER_SEC;
1588 PR_ExplodeTime(t, PR_GMTParameters, &et);
1589 /* use HTTP Cookie header's date format */
1590 PR_FormatTimeUSEnglish(lifetime, sizeof lifetime,
1591 "%a, %d-%b-%Y %H:%M:%S GMT", &et);
1592 } else {
1593 /* 0 means the lifetime of the ticket is unspecified */
1594 strcpy(lifetime, "unspecified");
1595 }
1596 ticketlength = GET_SHORT((hsdata +
1597 4));
1598 PR_fprintf(PR_STDOUT, " NewSessionTicket {\n");
1599 PR_fprintf(PR_STDOUT, " ticket_lifetime_hint = %s\n",
1600 lifetime);
1601 PR_fprintf(PR_STDOUT, " ticket = {\n");
1602 PR_fprintf(PR_STDOUT, " length = %d\n", ticketlength);
1603 PR_fprintf(PR_STDOUT, " contents = {...}\n");
1604 if (sslhexparse)
1605 print_hex(ticketlength, &hsdata[4 + 2]);
1606 PR_fprintf(PR_STDOUT, " }\n");
1607 PR_fprintf(PR_STDOUT, " }\n");
1608 } break;
1609
1610 case 11: /* certificate */
1611 {
1612 PRFileDesc *cfd;
1613 int pos;
1614 int certslength;
1615 int certlength;
1616 int certbytesread = 0;
1617 static int certFileNumber;
1618 char certFileName[20];
1619
1620 PR_fprintf(PR_STDOUT, " CertificateChain {\n");
1621 certslength = GET_24(hsdata);
1622 PR_fprintf(PR_STDOUT, " chainlength = %d (0x%04x)\n",
1623 certslength, certslength);
1624 pos = 3;
1625 while (certbytesread < certslength) {
1626 certlength =
1627 GET_24((hsdata + pos));
1628 pos +=
1629 3;
1630 PR_fprintf(PR_STDOUT, " Certificate {\n");
1631 PR_fprintf(PR_STDOUT, " size = %d (0x%04x)\n",
1632 certlength, certlength);
1633 certbytesread +=
1634 certlength + 3;
1635 if (certbytesread <=
1636 certslength) {
1637 PR_snprintf(certFileName, sizeof certFileName, "cert.%03d",
1638 ++certFileNumber);
1639 cfd =
1640 PR_Open(certFileName, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
1641 0664);
1642 if (!cfd) {
1643 PR_fprintf(PR_STDOUT,
1644 " data = { couldn't save file '%s' }\n",
1645 certFileName);
1646 } else {
1647 PR_Write(cfd, (hsdata +
1648 pos),
1649 certlength);
1650 PR_fprintf(PR_STDOUT,
1651 " data = { saved in file '%s' }\n",
1652 certFileName);
1653 PR_Close(cfd);
1654 }
1655 }
1656
1657 PR_fprintf(PR_STDOUT, " }\n");
1658 pos += certlength;
1659 }
1660 PR_fprintf(PR_STDOUT, " }\n");
1661 } break;
1662
1663 case 12: /* server_key_exchange */
1664 if (sslhexparse)
1665 print_hex(sslh.length, hsdata);
1666 break;
1667
1668 case 13: /* certificate request */
1669 {
1670 unsigned int pos = 0;
1671 int w, reqLength;
1672
1673 PR_fprintf(PR_STDOUT, " CertificateRequest {\n");
1674
1675 /* pretty print requested certificate types */
1676 reqLength = hsdata[pos];
1677 PR_fprintf(PR_STDOUT, " certificate types[%d] = {",
1678 reqLength);
1679 for (w =
1680 0;
1681 w < reqLength; w++) {
1682 PR_fprintf(PR_STDOUT, " %02x", hsdata[pos +
1683 1 + w]);
1684 }
1685 pos += 1 + reqLength;
1686 PR_fprintf(PR_STDOUT, " }\n");
1687
1688 /* pretty print CA names, if any */
1689 if (pos < sslh.length) {
1690 int exListLen =
1691 GET_SHORT((hsdata + pos));
1692 pos += 2;
1693 PR_fprintf(PR_STDOUT,
1694 " certificate_authorities[%d] = {\n",
1695 exListLen);
1696 while (exListLen >
1697 0 &&
1698 pos < sslh.length) {
1699 char *ca_name;
1700 SECItem it;
1701 int dnLen = GET_SHORT((hsdata +
1702 pos));
1703 pos += 2;
1704
1705 /* dump the CA name */
1706 it.type =
1707 siBuffer;
1708 it.data =
1709 hsdata + pos;
1710 it.len =
1711 dnLen;
1712 ca_name =
1713 CERT_DerNameToAscii(&it);
1714 if (ca_name) {
1715 PR_fprintf(PR_STDOUT, " %s\n", ca_name);
1716 PORT_Free(ca_name);
1717 } else {
1718 PR_fprintf(PR_STDOUT,
1719 " distinguished name [%d]", dnLen);
1720 if (dnLen >
1721 0 &&
1722 sslhexparse) {
1723 PR_fprintf(PR_STDOUT, " = {\n");
1724 print_hex(dnLen, hsdata + pos);
1725 PR_fprintf(PR_STDOUT, " }\n");
1726 } else {
1727 PR_fprintf(PR_STDOUT, "\n");
1728 }
1729 }
1730 pos +=
1731 dnLen;
1732 exListLen -=
1733 2 + dnLen;
1734 }
1735 PR_fprintf(PR_STDOUT, " }\n");
1736 }
1737
1738 PR_fprintf(PR_STDOUT, " }\n");
1739 } break;
1740
1741 case 14: /* server_hello_done */ /* not much to show here. */
1742 break;
1743
1744 case 15: /* certificate_verify */
1745 if (sslhexparse)
1746 print_hex(sslh.length, hsdata);
1747 break;
1748
1749 case 16: /* client key exchange */
1750 {
1751 PR_fprintf(PR_STDOUT, " ClientKeyExchange {\n");
1752 PR_fprintf(PR_STDOUT, " message = {...}\n");
1753 PR_fprintf(PR_STDOUT, " }\n");
1754 } break;
1755
1756 case 20: /* finished */
1757 PR_fprintf(PR_STDOUT, " Finished {\n");
1758 PR_fprintf(PR_STDOUT, " verify_data = {...}\n");
1759 if (sslhexparse)
1760 print_hex(sslh.length, hsdata);
1761 PR_fprintf(PR_STDOUT, " }\n");
1762
1763 if (!isNULLmac(currentcipher) &&
1764 !s->hMACsize) {
1765 /* To calculate the size of MAC, we subtract the number of known
1766 * bytes of message from the number of remaining bytes in the
1767 * record. This assumes that this is the first record on the
1768 * connection to have a MAC, and that the sender has not put another
1769 * message after the finished message in the handshake record.
1770 * This is only correct for the first transition from unMACed to
1771 * MACed. If the connection switches from one cipher suite to
1772 * another one with a different MAC, this logic will not track that
1773 * change correctly.
1774 */
1775 s->hMACsize =
1776 recordLen - (sslh.length + 4);
1777 sslh.length +=
1778 s->hMACsize; /* skip over the MAC data */
1779 }
1780 break;
1781
1782 case 22: /* certificate_status */
1783 {
1784 SECItem data;
1785 PRFileDesc *ofd;
1786 static int ocspFileNumber;
1787 char ocspFileName[20];
1788
1789 /* skip 4 bytes with handshake numbers, as in ssl3_HandleCertificateStatus */
1790 data.type = siBuffer;
1791 data.data = hsdata + 4;
1792 data.len = sslh.length - 4;
1793 print_status_response(&data);
1794
1795 PR_snprintf(ocspFileName, sizeof ocspFileName, "ocsp.%03d",
1796 ++ocspFileNumber);
1797 ofd = PR_Open(ocspFileName, PR_WRONLY | PR_CREATE_FILE | PR_TRUNCATE,
1798 0664);
1799 if (!ofd) {
1800 PR_fprintf(PR_STDOUT,
1801 " data = { couldn't save file '%s' }\n",
1802 ocspFileName);
1803 } else {
1804 PR_Write(ofd, data.data, data.len);
1805 PR_fprintf(PR_STDOUT,
1806 " data = { saved in file '%s' }\n",
1807 ocspFileName);
1808 PR_Close(ofd);
1809 }
1810 } break;
1811
1812 default: {
1813 PR_fprintf(PR_STDOUT, " UNKNOWN MESSAGE TYPE %d [%d] {\n",
1814 sslh.type, sslh.length);
1815 if (sslhexparse)
1816 print_hex(sslh.length, hsdata);
1817 PR_fprintf(PR_STDOUT, " }\n");
1818 }
1819 } /* end of switch sslh.type */
1820 offset += sslh.length + 4;
1821 } /* while */
1822 if (offset < recordLen) { /* stuff left over */
1823 unsigned int newMsgLen = recordLen - offset;
1824 if (!s->msgBuf) {
1825 s->msgBuf = PORT_Alloc(newMsgLen);
1826 if (!s->msgBuf) {
1827 PR_ASSERT(s->msgBuf);
1828 showErr("Malloc failed");
1829 exit(11);
1830 }
1831 s->msgBufSize = newMsgLen;
1832 memcpy(s->msgBuf, recordBuf + offset, newMsgLen);
1833 } else if (newMsgLen > s->msgBufSize) {
1834 unsigned char *newBuf = PORT_Realloc(s->msgBuf, newMsgLen);
1835 if (!newBuf) {
1836 PR_ASSERT(newBuf);
1837 showErr("Realloc failed");
1838 exit(12);
1839 }
1840 s->msgBuf = newBuf;
1841 s->msgBufSize = newMsgLen;
1842 } else if (offset || s->msgBuf != recordBuf) {
1843 memmove(s->msgBuf, recordBuf + offset, newMsgLen);
1844 }
1845 s->msgBufOffset = newMsgLen;
1846 PR_fprintf(PR_STDOUT, " [incomplete handshake message]\n");
1847 } else {
1848 s->msgBufOffset = 0;
1849 }
1850 PR_fprintf(PR_STDOUT, " }\n");
1851 }
1852
1853 void
print_ssl(DataBufferList * s,int length,unsigned char * buffer)1854 print_ssl(DataBufferList *s, int length, unsigned char *buffer)
1855 {
1856 /* -------------------------------------------------------- */
1857 /* first, create a new buffer object for this piece of data. */
1858
1859 DataBuffer *db;
1860
1861 if (s->size == 0 && length > 0 && buffer[0] >= 32 && buffer[0] < 128) {
1862 /* Not an SSL record, treat entire buffer as plaintext */
1863 PR_Write(PR_STDOUT, buffer, length);
1864 return;
1865 }
1866
1867 check_integrity(s);
1868
1869 db = PR_NEW(struct _DataBuffer);
1870
1871 if (!db) {
1872 return;
1873 }
1874
1875 db->buffer = (unsigned char *)PORT_Alloc(length);
1876 db->length = length;
1877 db->offset = 0;
1878 memcpy(db->buffer, buffer, length);
1879 db->next = NULL;
1880
1881 /* now, add it to the stream */
1882
1883 if (s->last != NULL)
1884 s->last->next = db;
1885 s->last = db;
1886 s->size += length;
1887 if (s->first == NULL)
1888 s->first = db;
1889
1890 check_integrity(s);
1891
1892 /*------------------------------------------------------- */
1893 /* now we look at the stream to see if we have enough data to
1894 decode */
1895
1896 while (s->size > 0) {
1897 unsigned char *recordBuf = NULL;
1898
1899 SSLRecord sr;
1900 unsigned recordLen;
1901 unsigned recordsize;
1902
1903 check_integrity(s);
1904
1905 if (s->first == NULL) {
1906 PR_fprintf(PR_STDOUT, "ERROR: s->first is null\n");
1907 exit(9);
1908 }
1909
1910 /* in the case of an SSL 2 client-hello */
1911 /* will have the high-bit set, whereas an SSL 3 client-hello will not */
1912 /* SSL2 can also send records that begin with the high bit clear.
1913 * This code will incorrectly handle them. XXX
1914 */
1915 if (isV2Session || s->first->buffer[s->first->offset] & 0x80) {
1916 /* it's an SSL 2 packet */
1917 unsigned char lenbuf[3];
1918
1919 /* first, we check if there's enough data for it to be an SSL2-type
1920 * record. What a pain.*/
1921 if (s->size < sizeof lenbuf) {
1922 partial_packet(length, s->size, sizeof lenbuf);
1923 return;
1924 }
1925
1926 /* read the first two bytes off the stream. */
1927 read_stream_bytes(lenbuf, s, sizeof(lenbuf));
1928 recordLen = ((unsigned int)(lenbuf[0] & 0x7f) << 8) + lenbuf[1] +
1929 ((lenbuf[0] & 0x80) ? 2 : 3);
1930 PR_fprintf(PR_STDOUT, "recordLen = %u bytes\n", recordLen);
1931
1932 /* put 'em back on the head of the stream. */
1933 db = PR_NEW(struct _DataBuffer);
1934
1935 db->length = sizeof lenbuf;
1936 db->buffer = (unsigned char *)PORT_Alloc(db->length);
1937 db->offset = 0;
1938 memcpy(db->buffer, lenbuf, sizeof lenbuf);
1939
1940 db->next = s->first;
1941 s->first = db;
1942 if (s->last == NULL)
1943 s->last = db;
1944 s->size += db->length;
1945
1946 /* if there wasn't enough, go back for more. */
1947 if (s->size < recordLen) {
1948 check_integrity(s);
1949 partial_packet(length, s->size, recordLen);
1950 return;
1951 }
1952 partial_packet(length, s->size, recordLen);
1953
1954 /* read in the whole record. */
1955 recordBuf = PORT_Alloc(recordLen);
1956 read_stream_bytes(recordBuf, s, recordLen);
1957
1958 print_sslv2(s, recordBuf, recordLen);
1959 PR_FREEIF(recordBuf);
1960 check_integrity(s);
1961
1962 continue;
1963 }
1964
1965 /***********************************************************/
1966 /* It's SSL v3 */
1967 /***********************************************************/
1968 check_integrity(s);
1969
1970 if (s->size < sizeof sr) {
1971 partial_packet(length, s->size, sizeof(SSLRecord));
1972 return;
1973 }
1974
1975 read_stream_bytes((unsigned char *)&sr, s, sizeof sr);
1976
1977 /* we have read the stream bytes. Look at the length of
1978 the ssl record. If we don't have enough data to satisfy this
1979 request, then put the bytes we just took back at the head
1980 of the queue */
1981 recordsize = GET_SHORT(sr.length);
1982
1983 if (recordsize > s->size) {
1984 db = PR_NEW(struct _DataBuffer);
1985
1986 db->length = sizeof sr;
1987 db->buffer = (unsigned char *)PORT_Alloc(db->length);
1988 db->offset = 0;
1989 memcpy(db->buffer, &sr, sizeof sr);
1990 db->next = s->first;
1991
1992 /* now, add it back on to the head of the stream */
1993
1994 s->first = db;
1995 if (s->last == NULL)
1996 s->last = db;
1997 s->size += db->length;
1998
1999 check_integrity(s);
2000 partial_packet(length, s->size, recordsize);
2001 return;
2002 }
2003 partial_packet(length, s->size, recordsize);
2004
2005 PR_fprintf(PR_STDOUT, "SSLRecord { [%s]\n", get_time_string());
2006 if (sslhexparse) {
2007 print_hex(5, (unsigned char *)&sr);
2008 }
2009
2010 check_integrity(s);
2011
2012 PR_fprintf(PR_STDOUT, " type = %d (", sr.type);
2013 switch (sr.type) {
2014 case 20:
2015 PR_fprintf(PR_STDOUT, "change_cipher_spec)\n");
2016 break;
2017 case 21:
2018 PR_fprintf(PR_STDOUT, "alert)\n");
2019 break;
2020 case 22:
2021 PR_fprintf(PR_STDOUT, "handshake)\n");
2022 break;
2023 case 23:
2024 PR_fprintf(PR_STDOUT, "application_data)\n");
2025 break;
2026 default:
2027 PR_fprintf(PR_STDOUT, "unknown)\n");
2028 break;
2029 }
2030 PR_fprintf(PR_STDOUT, " version = { %d,%d }\n",
2031 (PRUint32)sr.ver_maj, (PRUint32)sr.ver_min);
2032 PR_fprintf(PR_STDOUT, " length = %d (0x%x)\n",
2033 (PRUint32)GET_SHORT(sr.length), (PRUint32)GET_SHORT(sr.length));
2034
2035 recordLen = recordsize;
2036 PR_ASSERT(s->size >= recordLen);
2037 if (s->size >= recordLen) {
2038 recordBuf = (unsigned char *)PORT_Alloc(recordLen);
2039 read_stream_bytes(recordBuf, s, recordLen);
2040
2041 if (s->isEncrypted) {
2042 PR_fprintf(PR_STDOUT, " < encrypted >\n");
2043 } else { /* not encrypted */
2044
2045 switch (sr.type) {
2046 case 20: /* change_cipher_spec */
2047 if (sslhexparse)
2048 print_hex(recordLen - s->hMACsize, recordBuf);
2049 /* mark to say we can only dump hex form now on
2050 * if it is not one on a null cipher */
2051 s->isEncrypted =
2052 isNULLcipher(currentcipher) ? 0 : 1;
2053 break;
2054
2055 case 21: /* alert */
2056 switch (recordBuf[0]) {
2057 case 1:
2058 PR_fprintf(PR_STDOUT, " warning: ");
2059 break;
2060 case 2:
2061 PR_fprintf(PR_STDOUT, " fatal: ");
2062 break;
2063 default:
2064 PR_fprintf(PR_STDOUT, " unknown level %d: ", recordBuf[0]);
2065 break;
2066 }
2067
2068 switch (recordBuf[1]) {
2069 case 0:
2070 PR_FPUTS("close_notify\n");
2071 break;
2072 case 10:
2073 PR_FPUTS("unexpected_message\n");
2074 break;
2075 case 20:
2076 PR_FPUTS("bad_record_mac\n");
2077 break;
2078 case 21:
2079 PR_FPUTS("decryption_failed\n");
2080 break;
2081 case 22:
2082 PR_FPUTS("record_overflow\n");
2083 break;
2084 case 30:
2085 PR_FPUTS("decompression_failure\n");
2086 break;
2087 case 40:
2088 PR_FPUTS("handshake_failure\n");
2089 break;
2090 case 41:
2091 PR_FPUTS("no_certificate\n");
2092 break;
2093 case 42:
2094 PR_FPUTS("bad_certificate\n");
2095 break;
2096 case 43:
2097 PR_FPUTS("unsupported_certificate\n");
2098 break;
2099 case 44:
2100 PR_FPUTS("certificate_revoked\n");
2101 break;
2102 case 45:
2103 PR_FPUTS("certificate_expired\n");
2104 break;
2105 case 46:
2106 PR_FPUTS("certificate_unknown\n");
2107 break;
2108 case 47:
2109 PR_FPUTS("illegal_parameter\n");
2110 break;
2111 case 48:
2112 PR_FPUTS("unknown_ca\n");
2113 break;
2114 case 49:
2115 PR_FPUTS("access_denied\n");
2116 break;
2117 case 50:
2118 PR_FPUTS("decode_error\n");
2119 break;
2120 case 51:
2121 PR_FPUTS("decrypt_error\n");
2122 break;
2123 case 60:
2124 PR_FPUTS("export_restriction\n");
2125 break;
2126 case 70:
2127 PR_FPUTS("protocol_version\n");
2128 break;
2129 case 71:
2130 PR_FPUTS("insufficient_security\n");
2131 break;
2132 case 80:
2133 PR_FPUTS("internal_error\n");
2134 break;
2135 case 90:
2136 PR_FPUTS("user_canceled\n");
2137 break;
2138 case 100:
2139 PR_FPUTS("no_renegotiation\n");
2140 break;
2141 case 110:
2142 PR_FPUTS("unsupported_extension\n");
2143 break;
2144 case 111:
2145 PR_FPUTS("certificate_unobtainable\n");
2146 break;
2147 case 112:
2148 PR_FPUTS("unrecognized_name\n");
2149 break;
2150 case 113:
2151 PR_FPUTS("bad_certificate_status_response\n");
2152 break;
2153 case 114:
2154 PR_FPUTS("bad_certificate_hash_value\n");
2155 break;
2156
2157 default:
2158 PR_fprintf(PR_STDOUT, "unknown alert %d\n", recordBuf[1]);
2159 break;
2160 }
2161
2162 if (sslhexparse)
2163 print_hex(recordLen - s->hMACsize, recordBuf);
2164 break;
2165
2166 case 22: /* handshake */
2167 print_ssl3_handshake(recordBuf, recordLen - s->hMACsize,
2168 &sr, s);
2169 break;
2170
2171 case 23: /* application data */
2172 print_hex(recordLen -
2173 s->hMACsize,
2174 recordBuf);
2175 break;
2176
2177 default:
2178 print_hex(recordLen -
2179 s->hMACsize,
2180 recordBuf);
2181 break;
2182 }
2183 if (s->hMACsize) {
2184 PR_fprintf(PR_STDOUT, " MAC = {...}\n");
2185 if (sslhexparse) {
2186 unsigned char *offset =
2187 recordBuf + (recordLen - s->hMACsize);
2188 print_hex(s->hMACsize, offset);
2189 }
2190 }
2191 } /* not encrypted */
2192 }
2193 PR_fprintf(PR_STDOUT, "}\n");
2194 PR_FREEIF(recordBuf);
2195 check_integrity(s);
2196 }
2197 }
2198
2199 void
print_hex(int amt,unsigned char * buf)2200 print_hex(int amt, unsigned char *buf)
2201 {
2202 int i, j, k;
2203 char t[20];
2204 static char string[5000];
2205
2206 for (i = 0; i < amt; i++) {
2207 t[1] = 0;
2208
2209 if (i % 16 == 0) { /* if we are at the beginning of a line */
2210 PR_fprintf(PR_STDOUT, "%4x:", i); /* print the line number */
2211 strcpy(string, "");
2212 }
2213
2214 if (i % 4 == 0) {
2215 PR_fprintf(PR_STDOUT, " ");
2216 }
2217
2218 j = buf[i];
2219
2220 t[0] = (j >= 0x20 && j < 0x80) ? j : '.';
2221
2222 if (fancy) {
2223 switch (t[0]) {
2224 case '<':
2225 strcpy(t, "<");
2226 break;
2227 case '>':
2228 strcpy(t, ">");
2229 break;
2230 case '&':
2231 strcpy(t, "&");
2232 break;
2233 }
2234 }
2235 strcat(string, t);
2236
2237 PR_fprintf(PR_STDOUT, "%02x ", (PRUint8)buf[i]);
2238
2239 /* if we've reached the end of the line - add the string */
2240 if (i % 16 == 15)
2241 PR_fprintf(PR_STDOUT, " | %s\n", string);
2242 }
2243 /* we reached the end of the buffer,*/
2244 /* do we have buffer left over? */
2245 j = i % 16;
2246 if (j > 0) {
2247 for (k = 0; k < (16 -
2248 j);
2249 k++) {
2250 /* print additional space after every four bytes */
2251 if ((k + j) % 4 == 0) {
2252 PR_fprintf(PR_STDOUT, " ");
2253 }
2254 PR_fprintf(PR_STDOUT, " ");
2255 }
2256 PR_fprintf(PR_STDOUT, " | %s\n", string);
2257 }
2258 }
2259
2260 void
Usage(void)2261 Usage(void)
2262 {
2263 PR_fprintf(PR_STDERR, "Usage: ssltap [-vhfsxl] [-p port] hostname:port\n");
2264 PR_fprintf(PR_STDERR, " -v [prints version string]\n");
2265 PR_fprintf(PR_STDERR, " -h [outputs hex instead of ASCII]\n");
2266 PR_fprintf(PR_STDERR, " -f [turn on Fancy HTML coloring]\n");
2267 PR_fprintf(PR_STDERR, " -s [turn on SSL decoding]\n");
2268 PR_fprintf(PR_STDERR, " -x [turn on extra SSL hex dumps]\n");
2269 PR_fprintf(PR_STDERR, " -p port [specify rendezvous port (default 1924)]\n");
2270 PR_fprintf(PR_STDERR, " -l [loop - continue to wait for more connections]\n");
2271 }
2272
2273 void
showErr(const char * msg)2274 showErr(const char *msg)
2275 {
2276 PRErrorCode err = PR_GetError();
2277 const char *errString;
2278
2279 if (err == PR_UNKNOWN_ERROR)
2280 err = PR_CONNECT_RESET_ERROR; /* bug in NSPR. */
2281 errString = SECU_Strerror(err);
2282
2283 if (!errString)
2284 errString = "(no text available)";
2285 PR_fprintf(PR_STDERR, "%s: Error %d: %s: %s", progName, err, errString, msg);
2286 }
2287
2288 int
main(int argc,char * argv[])2289 main(int argc, char *argv[])
2290 {
2291 char *hostname = NULL;
2292 PRUint16 rendport = DEFPORT, port;
2293 PRAddrInfo *ai;
2294 void *iter;
2295 PRStatus r;
2296 PRNetAddr na_client, na_server, na_rend;
2297 PRFileDesc *s_server, *s_client, *s_rend; /*rendezvous */
2298 int c_count = 0;
2299 PLOptState *optstate;
2300 PLOptStatus status;
2301 SECStatus rv;
2302
2303 progName = argv[0];
2304 optstate = PL_CreateOptState(argc, argv, "fxhslp:");
2305 while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
2306 switch (optstate->option) {
2307 case 'f':
2308 fancy++;
2309 break;
2310 case 'h':
2311 hexparse++;
2312 break;
2313 case 's':
2314 sslparse++;
2315 break;
2316 case 'x':
2317 sslhexparse++;
2318 break;
2319 case 'l':
2320 looparound++;
2321 break;
2322 case 'p':
2323 rendport =
2324 atoi(optstate->value);
2325 break;
2326 case '\0':
2327 hostname =
2328 PL_strdup(optstate->value);
2329 }
2330 }
2331 if (status == PL_OPT_BAD)
2332 Usage();
2333
2334 if (fancy) {
2335 if (!hexparse && !sslparse) {
2336 PR_fprintf(PR_STDERR,
2337 "Note: use of -f without -s or -h not recommended, \n"
2338 "as the output looks a little strange. It may be useful, however\n");
2339 }
2340 }
2341
2342 if (!hostname)
2343 Usage(), exit(2);
2344
2345 {
2346 char *colon = (char *)strchr(hostname, ':');
2347 if (!colon) {
2348 PR_fprintf(PR_STDERR,
2349 "You must specify the host AND port you wish to connect to\n");
2350 Usage(), exit(3);
2351 }
2352 port = atoi(&colon[1]);
2353 *colon = '\0';
2354
2355 if (port == 0) {
2356 PR_fprintf(PR_STDERR, "Port must be a nonzero number.\n");
2357 exit(4);
2358 }
2359 }
2360
2361 /* find the 'server' IP address so we don't have to look it up later */
2362
2363 if (fancy) {
2364 PR_fprintf(PR_STDOUT, "<HTML><HEAD><TITLE>SSLTAP output</TITLE></HEAD>\n");
2365 PR_fprintf(PR_STDOUT, "<BODY><PRE>\n");
2366 }
2367 PR_fprintf(PR_STDERR, "Looking up \"%s\"...\n", hostname);
2368 ai = PR_GetAddrInfoByName(hostname, PR_AF_UNSPEC, PR_AI_ADDRCONFIG);
2369 if (!ai) {
2370 showErr("Host Name lookup failed\n");
2371 exit(5);
2372 }
2373
2374 iter = NULL;
2375 iter = PR_EnumerateAddrInfo(iter, ai, port, &na_server);
2376 /* set up the port which the client will connect to */
2377
2378 r = PR_InitializeNetAddr(PR_IpAddrAny, rendport, &na_rend);
2379 if (r == PR_FAILURE) {
2380 PR_fprintf(PR_STDERR,
2381 "PR_InitializeNetAddr(,%d,) failed with error %d\n", PR_GetError());
2382 exit(0);
2383 }
2384
2385 rv = NSS_NoDB_Init("");
2386 if (rv != SECSuccess) {
2387 PR_fprintf(PR_STDERR,
2388 "NSS_NoDB_Init() failed with error %d\n", PR_GetError());
2389 exit(5);
2390 }
2391
2392 s_rend = PR_NewTCPSocket();
2393 if (!s_rend) {
2394 showErr("Couldn't create socket\n");
2395 exit(6);
2396 }
2397
2398 if (PR_Bind(s_rend, &na_rend)) {
2399 PR_fprintf(PR_STDERR, "Couldn't bind to port %d (error %d)\n", rendport, PR_GetError());
2400 exit(-1);
2401 }
2402
2403 if (PR_Listen(s_rend, 5)) {
2404 showErr("Couldn't listen\n");
2405 exit(-1);
2406 }
2407
2408 PR_fprintf(PR_STDERR, "Proxy socket ready and listening\n");
2409 do { /* accept one connection and process it. */
2410 PRPollDesc pds[2];
2411
2412 s_client = PR_Accept(s_rend, &na_client, PR_SecondsToInterval(3600));
2413 if (s_client == NULL) {
2414 showErr("accept timed out\n");
2415 exit(7);
2416 }
2417
2418 s_server = PR_OpenTCPSocket(na_server.raw.family);
2419 if (s_server == NULL) {
2420 showErr("couldn't open new socket to connect to server \n");
2421 exit(8);
2422 }
2423
2424 r = PR_Connect(s_server, &na_server, PR_SecondsToInterval(5));
2425
2426 if (r == PR_FAILURE) {
2427 showErr("Couldn't connect\n");
2428 return -1;
2429 }
2430
2431 if (looparound) {
2432 if (fancy)
2433 PR_fprintf(PR_STDOUT, "<p><HR><H2>");
2434 PR_fprintf(PR_STDOUT, "Connection #%d [%s]\n", c_count + 1,
2435 get_time_string());
2436 if (fancy)
2437 PR_fprintf(PR_STDOUT, "</H2>");
2438 }
2439
2440 PR_fprintf(PR_STDOUT, "Connected to %s:%d\n", hostname, port);
2441
2442 #define PD_C 0
2443 #define PD_S 1
2444
2445 pds[PD_C].fd = s_client;
2446 pds[PD_S].fd = s_server;
2447 pds[PD_C].in_flags = PR_POLL_READ;
2448 pds[PD_S].in_flags = PR_POLL_READ;
2449
2450 /* make sure the new connections don't start out encrypted. */
2451 clientstream.isEncrypted = 0;
2452 serverstream.isEncrypted = 0;
2453 isV2Session = 0;
2454
2455 while ((pds[PD_C].in_flags & PR_POLL_READ) != 0 ||
2456 (pds[PD_S].in_flags & PR_POLL_READ) != 0) { /* Handle all messages on the connection */
2457 PRInt32 amt;
2458 PRInt32 wrote;
2459 unsigned char buffer[TAPBUFSIZ];
2460
2461 amt = PR_Poll(pds, 2, PR_INTERVAL_NO_TIMEOUT);
2462 if (amt <= 0) {
2463 if (amt)
2464 showErr("PR_Poll failed.\n");
2465 else
2466 showErr("PR_Poll timed out.\n");
2467 break;
2468 }
2469
2470 if (pds[PD_C].out_flags & PR_POLL_EXCEPT) {
2471 showErr("Exception on client-side socket.\n");
2472 break;
2473 }
2474
2475 if (pds[PD_S].out_flags & PR_POLL_EXCEPT) {
2476 showErr("Exception on server-side socket.\n");
2477 break;
2478 }
2479
2480 /* read data, copy it to stdout, and write to other socket */
2481
2482 if ((pds[PD_C].in_flags & PR_POLL_READ) != 0 &&
2483 (pds[PD_C].out_flags & PR_POLL_READ) != 0) {
2484
2485 amt = PR_Read(s_client, buffer, sizeof(buffer));
2486
2487 if (amt < 0) {
2488 showErr("Client socket read failed.\n");
2489 break;
2490 }
2491
2492 if (amt == 0) {
2493 PR_fprintf(PR_STDOUT, "Read EOF on Client socket. [%s]\n",
2494 get_time_string());
2495 pds[PD_C].in_flags &= ~PR_POLL_READ;
2496 PR_Shutdown(s_server, PR_SHUTDOWN_SEND);
2497 continue;
2498 }
2499
2500 PR_fprintf(PR_STDOUT, "--> [\n");
2501 if (fancy)
2502 PR_fprintf(PR_STDOUT, "<font color=blue>");
2503
2504 if (hexparse)
2505 print_hex(amt, buffer);
2506 if (sslparse)
2507 print_ssl(&clientstream, amt, buffer);
2508 if (!hexparse && !sslparse)
2509 PR_Write(PR_STDOUT, buffer, amt);
2510 if (fancy)
2511 PR_fprintf(PR_STDOUT, "</font>");
2512 PR_fprintf(PR_STDOUT, "]\n");
2513
2514 wrote = PR_Write(s_server, buffer, amt);
2515 if (wrote != amt) {
2516 if (wrote < 0) {
2517 showErr("Write to server socket failed.\n");
2518 break;
2519 } else {
2520 PR_fprintf(PR_STDERR, "Short write to server socket!\n");
2521 }
2522 }
2523 } /* end of read from client socket. */
2524
2525 /* read data, copy it to stdout, and write to other socket */
2526 if ((pds[PD_S].in_flags & PR_POLL_READ) != 0 &&
2527 (pds[PD_S].out_flags & PR_POLL_READ) != 0) {
2528
2529 amt = PR_Read(s_server, buffer, sizeof(buffer));
2530
2531 if (amt < 0) {
2532 showErr("error on server-side socket.\n");
2533 break;
2534 }
2535
2536 if (amt == 0) {
2537 PR_fprintf(PR_STDOUT, "Read EOF on Server socket. [%s]\n",
2538 get_time_string());
2539 pds[PD_S].in_flags &= ~PR_POLL_READ;
2540 PR_Shutdown(s_client, PR_SHUTDOWN_SEND);
2541 continue;
2542 }
2543
2544 PR_fprintf(PR_STDOUT, "<-- [\n");
2545 if (fancy)
2546 PR_fprintf(PR_STDOUT, "<font color=red>");
2547 if (hexparse)
2548 print_hex(amt, (unsigned char *)buffer);
2549 if (sslparse)
2550 print_ssl(&serverstream, amt, (unsigned char *)buffer);
2551 if (!hexparse && !sslparse)
2552 PR_Write(PR_STDOUT, buffer, amt);
2553 if (fancy)
2554 PR_fprintf(PR_STDOUT, "</font>");
2555 PR_fprintf(PR_STDOUT, "]\n");
2556
2557 wrote = PR_Write(s_client, buffer, amt);
2558 if (wrote != amt) {
2559 if (wrote < 0) {
2560 showErr("Write to client socket failed.\n");
2561 break;
2562 } else {
2563 PR_fprintf(PR_STDERR, "Short write to client socket!\n");
2564 }
2565 }
2566
2567 } /* end of read from server socket. */
2568
2569 /* Loop, handle next message. */
2570
2571 } /* handle messages during a connection loop */
2572 PR_Close(s_client);
2573 PR_Close(s_server);
2574 flush_stream(&clientstream);
2575 flush_stream(&serverstream);
2576 /* Connection is closed, so reset the current cipher */
2577 currentcipher = 0;
2578 c_count++;
2579 PR_fprintf(PR_STDERR, "Connection %d Complete [%s]\n", c_count,
2580 get_time_string());
2581 } while (looparound); /* accept connection and process it. */
2582 PR_Close(s_rend);
2583 if (NSS_Shutdown() != SECSuccess) {
2584 return 1;
2585 }
2586 return 0;
2587 }
2588