tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ssltap.c (86186B)


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