security/nss/cmd/ssltap/ssltap.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial