security/nss/cmd/ssltap/ssltap.c

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/security/nss/cmd/ssltap/ssltap.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,2039 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +/*
     1.9 + * ssltap.c
    1.10 + *
    1.11 + * Version 1.0 : Frederick Roeber : 11 June 1997
    1.12 + * Version 2.0 : Steve Parkinson  : 13 November 1997
    1.13 + * Version 3.0 : Nelson Bolyard   : 22 July 1998
    1.14 + * Version 3.1 : Nelson Bolyard   : 24 May  1999
    1.15 + *
    1.16 + * changes in version 2.0:
    1.17 + *  Uses NSPR20
    1.18 + *  Shows structure of SSL negotiation, if enabled.
    1.19 + *
    1.20 + * This "proxies" a socket connection (like a socks tunnel), but displays the
    1.21 + * data is it flies by.
    1.22 + *
    1.23 + * In the code, the 'client' socket is the one on the client side of the
    1.24 + * proxy, and the server socket is on the server side.
    1.25 + *
    1.26 + */
    1.27 +
    1.28 +#include "nspr.h"
    1.29 +#include "plstr.h"
    1.30 +#include "secutil.h"
    1.31 +#include <memory.h>	/* for memcpy, etc. */
    1.32 +#include <string.h>
    1.33 +#include <time.h>
    1.34 +
    1.35 +#include "plgetopt.h"
    1.36 +#include "nss.h"
    1.37 +#include "cert.h"
    1.38 +#include "sslproto.h"
    1.39 +#include "ocsp.h"
    1.40 +#include "ocspti.h"     /* internals for pretty-printing routines *only* */
    1.41 +
    1.42 +struct _DataBufferList;
    1.43 +struct _DataBuffer;
    1.44 +
    1.45 +typedef struct _DataBufferList {
    1.46 +  struct _DataBuffer *first,*last;
    1.47 +  int size;
    1.48 +  int isEncrypted;
    1.49 +  unsigned char * msgBuf;
    1.50 +  int             msgBufOffset;
    1.51 +  int             msgBufSize;
    1.52 +  int             hMACsize;
    1.53 +} DataBufferList;
    1.54 +
    1.55 +typedef struct _DataBuffer {
    1.56 +  unsigned char *buffer;
    1.57 +  int length;
    1.58 +  int offset;  /* offset of first good byte */
    1.59 +  struct _DataBuffer *next;
    1.60 +} DataBuffer;
    1.61 +
    1.62 +
    1.63 +
    1.64 +struct sslhandshake {
    1.65 +  PRUint8 type;
    1.66 +  PRUint32 length;
    1.67 +};
    1.68 +
    1.69 +typedef struct _SSLRecord {
    1.70 +  PRUint8 type;
    1.71 +  PRUint8 ver_maj,ver_min;
    1.72 +
    1.73 +  PRUint8 length[2];
    1.74 +} SSLRecord;
    1.75 +
    1.76 +typedef struct _ClientHelloV2 {
    1.77 +  PRUint8 length[2];
    1.78 +  PRUint8 type;
    1.79 +  PRUint8 version[2];
    1.80 +  PRUint8 cslength[2];
    1.81 +  PRUint8 sidlength[2];
    1.82 +  PRUint8 rndlength[2];
    1.83 +  PRUint8 csuites[1];
    1.84 +} ClientHelloV2;
    1.85 +
    1.86 +typedef struct _ServerHelloV2 {
    1.87 +  PRUint8 length[2];
    1.88 +  PRUint8 type;
    1.89 +  PRUint8 sidhit;
    1.90 +  PRUint8 certtype;
    1.91 +  PRUint8 version[2];
    1.92 +  PRUint8 certlength[2];
    1.93 +  PRUint8 cslength[2];
    1.94 +  PRUint8 cidlength[2];
    1.95 +} ServerHelloV2;
    1.96 +
    1.97 +typedef struct _ClientMasterKeyV2 {
    1.98 +  PRUint8 length[2];
    1.99 +  PRUint8 type;
   1.100 +
   1.101 +  PRUint8 cipherkind[3];
   1.102 +  PRUint8 clearkey[2];
   1.103 +  PRUint8 secretkey[2];
   1.104 +
   1.105 +} ClientMasterKeyV2;
   1.106 +
   1.107 +/* forward declaration */
   1.108 +void showErr(const char * msg);
   1.109 +
   1.110 +#define TAPBUFSIZ 16384
   1.111 +
   1.112 +#define DEFPORT 1924
   1.113 +#include <ctype.h>
   1.114 +
   1.115 +const char * progName;
   1.116 +int hexparse=0;
   1.117 +int sslparse=0;
   1.118 +int sslhexparse=0;
   1.119 +int looparound=0;
   1.120 +int fancy=0;
   1.121 +int isV2Session=0;
   1.122 +int currentcipher=0;
   1.123 +DataBufferList clientstream, serverstream;
   1.124 +
   1.125 +#define PR_FPUTS(x) PR_fprintf(PR_STDOUT, x )
   1.126 +
   1.127 +#define GET_SHORT(x) ((PRUint16)(((PRUint16)((PRUint8*)x)[0]) << 8) + ((PRUint16)((PRUint8*)x)[1]))
   1.128 +#define GET_24(x) ((PRUint32)   (  \
   1.129 +				 (((PRUint32)((PRUint8*)x)[0]) << 16) \
   1.130 +				 +                          \
   1.131 +				 (((PRUint32)((PRUint8*)x)[1]) << 8)  \
   1.132 +				 +                          \
   1.133 +				 (((PRUint32)((PRUint8*)x)[2]) << 0)  \
   1.134 +				 ) )
   1.135 +#define GET_32(x) ((PRUint32)   (  \
   1.136 +				 (((PRUint32)((PRUint8*)x)[0]) << 24) \
   1.137 +				 +                          \
   1.138 +				 (((PRUint32)((PRUint8*)x)[1]) << 16) \
   1.139 +				 +                          \
   1.140 +				 (((PRUint32)((PRUint8*)x)[2]) << 8)  \
   1.141 +				 +                          \
   1.142 +				 (((PRUint32)((PRUint8*)x)[3]) << 0)  \
   1.143 +				 ) )
   1.144 +
   1.145 +void print_hex(int amt, unsigned char *buf);
   1.146 +void read_stream_bytes(unsigned char *d, DataBufferList *db, int length);
   1.147 +
   1.148 +void myhalt(int dblsize,int collectedsize) 
   1.149 +{
   1.150 +
   1.151 +  PR_fprintf(PR_STDERR,"HALTED\n");
   1.152 +  PR_ASSERT(dblsize == collectedsize);
   1.153 +  exit(13);
   1.154 +}
   1.155 +
   1.156 +const char *get_error_text(int error) 
   1.157 +{
   1.158 +  switch (error) {
   1.159 +  case PR_IO_TIMEOUT_ERROR:
   1.160 +    return "Timeout";
   1.161 +    break;
   1.162 +  case PR_CONNECT_REFUSED_ERROR:
   1.163 +    return "Connection refused";
   1.164 +    break;
   1.165 +  case PR_NETWORK_UNREACHABLE_ERROR:
   1.166 +    return "Network unreachable";
   1.167 +    break;
   1.168 +  case PR_BAD_ADDRESS_ERROR:
   1.169 +    return "Bad address";
   1.170 +    break;
   1.171 +  case PR_CONNECT_RESET_ERROR:
   1.172 +    return "Connection reset";
   1.173 +    break;
   1.174 +  case PR_PIPE_ERROR:
   1.175 +    return "Pipe error";
   1.176 +    break;
   1.177 +  }
   1.178 +
   1.179 +  return "";
   1.180 +}
   1.181 +
   1.182 +
   1.183 +
   1.184 +
   1.185 +
   1.186 +void check_integrity(DataBufferList *dbl) 
   1.187 +{
   1.188 +  DataBuffer *db;
   1.189 +  int i;
   1.190 +
   1.191 +  db = dbl->first;
   1.192 +  i =0;
   1.193 +  while (db) {
   1.194 +    i+= db->length - db->offset;
   1.195 +    db = db->next;
   1.196 +  }
   1.197 +  if (i != dbl->size) {
   1.198 +    myhalt(dbl->size,i);
   1.199 +  }
   1.200 +}
   1.201 +
   1.202 +/* Free's the DataBuffer at the head of the list and returns the pointer
   1.203 + * to the new head of the list.
   1.204 + */
   1.205 +DataBuffer * 
   1.206 +free_head(DataBufferList *dbl)
   1.207 +{
   1.208 +  DataBuffer *db       = dbl->first;
   1.209 +  PR_ASSERT(db->offset >= db->length);
   1.210 +  if (db->offset >= db->length) {
   1.211 +    dbl->first = db->next;
   1.212 +    if (dbl->first == NULL) {
   1.213 +      dbl->last = NULL;
   1.214 +    }
   1.215 +    PORT_Free(db->buffer);
   1.216 +    PORT_Free(db);
   1.217 +    db = dbl->first;
   1.218 +  }
   1.219 +  return db;
   1.220 +}
   1.221 +
   1.222 +void 
   1.223 +read_stream_bytes(unsigned char *d, DataBufferList *dbl, int length) 
   1.224 +{
   1.225 +  int         copied 	= 0;
   1.226 +  DataBuffer *db	= dbl->first;
   1.227 +
   1.228 +  if (!db) {
   1.229 +    PR_fprintf(PR_STDERR,"assert failed - dbl->first is null\n");
   1.230 +    exit(8);
   1.231 +  }
   1.232 +  while (length) {
   1.233 +    int         toCopy;
   1.234 +    /* find the number of bytes to copy from the head buffer */
   1.235 +    /* if there's too many in this buffer, then only copy 'length' */
   1.236 +    toCopy = PR_MIN(db->length - db->offset, length);
   1.237 +
   1.238 +    memcpy(d + copied, db->buffer + db->offset, toCopy);
   1.239 +    copied     += toCopy;
   1.240 +    db->offset += toCopy;
   1.241 +    length     -= toCopy;
   1.242 +    dbl->size  -= toCopy;
   1.243 +
   1.244 +    /* if we emptied the head buffer */
   1.245 +    if (db->offset >= db->length) {
   1.246 +      db = free_head(dbl);
   1.247 +    }
   1.248 +  }
   1.249 +
   1.250 +  check_integrity(dbl);
   1.251 +
   1.252 +}
   1.253 +
   1.254 +void
   1.255 +flush_stream(DataBufferList *dbl)
   1.256 +{
   1.257 +    DataBuffer *db = dbl->first;
   1.258 +    check_integrity(dbl);
   1.259 +    while (db) {
   1.260 +	db->offset = db->length;
   1.261 +    	db = free_head(dbl);
   1.262 +    }
   1.263 +    dbl->size = 0;
   1.264 +    check_integrity(dbl);
   1.265 +    if (dbl->msgBuf) {
   1.266 +        PORT_Free(dbl->msgBuf);
   1.267 +	dbl->msgBuf = NULL;
   1.268 +    }
   1.269 +    dbl->msgBufOffset = 0;
   1.270 +    dbl->msgBufSize = 0;
   1.271 +    dbl->hMACsize = 0;
   1.272 +}
   1.273 +
   1.274 +
   1.275 +const char * V2CipherString(int cs_int) 
   1.276 +{
   1.277 +  char *cs_str;
   1.278 +  cs_str = NULL;
   1.279 +  switch (cs_int) {
   1.280 +
   1.281 +  case 0x010080:    cs_str = "SSL2/RSA/RC4-128/MD5";       break;
   1.282 +  case 0x020080:    cs_str = "SSL2/RSA/RC4-40/MD5";    break;
   1.283 +  case 0x030080:    cs_str = "SSL2/RSA/RC2CBC128/MD5";     break;
   1.284 +  case 0x040080:    cs_str = "SSL2/RSA/RC2CBC40/MD5";  break;
   1.285 +  case 0x050080:    cs_str = "SSL2/RSA/IDEA128CBC/MD5";    break;
   1.286 +  case 0x060040:    cs_str = "SSL2/RSA/DES56-CBC/MD5";      break;
   1.287 +  case 0x0700C0:    cs_str = "SSL2/RSA/3DES192EDE-CBC/MD5"; break;
   1.288 +
   1.289 +  case 0x000001:    cs_str = "SSL3/RSA/NULL/MD5";             break;
   1.290 +  case 0x000002:    cs_str = "SSL3/RSA/NULL/SHA";             break;
   1.291 +  case 0x000003:    cs_str = "SSL3/RSA/RC4-40/MD5";       break;
   1.292 +  case 0x000004:    cs_str = "SSL3/RSA/RC4-128/MD5";          break;
   1.293 +  case 0x000005:    cs_str = "SSL3/RSA/RC4-128/SHA";          break;
   1.294 +  case 0x000006:    cs_str = "SSL3/RSA/RC2CBC40/MD5";     break;
   1.295 +  case 0x000007:    cs_str = "SSL3/RSA/IDEA128CBC/SHA";       break;
   1.296 +  case 0x000008:    cs_str = "SSL3/RSA/DES40-CBC/SHA";         break;
   1.297 +  case 0x000009:    cs_str = "SSL3/RSA/DES56-CBC/SHA";         break;
   1.298 +  case 0x00000A:    cs_str = "SSL3/RSA/3DES192EDE-CBC/SHA";    break;
   1.299 +
   1.300 +  case 0x00000B:    cs_str = "SSL3/DH-DSS/DES40-CBC/SHA";      break;
   1.301 +  case 0x00000C:    cs_str = "SSL3/DH-DSS/DES56-CBC/SHA";      break;
   1.302 +  case 0x00000D:    cs_str = "SSL3/DH-DSS/DES192EDE3CBC/SHA"; break;
   1.303 +  case 0x00000E:    cs_str = "SSL3/DH-RSA/DES40-CBC/SHA";      break;
   1.304 +  case 0x00000F:    cs_str = "SSL3/DH-RSA/DES56-CBC/SHA";      break;
   1.305 +  case 0x000010:    cs_str = "SSL3/DH-RSA/3DES192EDE-CBC/SHA"; break;
   1.306 +
   1.307 +  case 0x000011:    cs_str = "SSL3/DHE-DSS/DES40-CBC/SHA";      break;
   1.308 +  case 0x000012:    cs_str = "SSL3/DHE-DSS/DES56-CBC/SHA";      break;
   1.309 +  case 0x000013:    cs_str = "SSL3/DHE-DSS/DES192EDE3CBC/SHA"; break;
   1.310 +  case 0x000014:    cs_str = "SSL3/DHE-RSA/DES40-CBC/SHA";      break;
   1.311 +  case 0x000015:    cs_str = "SSL3/DHE-RSA/DES56-CBC/SHA";      break;
   1.312 +  case 0x000016:    cs_str = "SSL3/DHE-RSA/3DES192EDE-CBC/SHA"; break;
   1.313 +
   1.314 +  case 0x000017:    cs_str = "SSL3/DH-anon/RC4-40/MD5";     break;
   1.315 +  case 0x000018:    cs_str = "SSL3/DH-anon/RC4-128/MD5";        break;
   1.316 +  case 0x000019:    cs_str = "SSL3/DH-anon/DES40-CBC/SHA";       break;
   1.317 +  case 0x00001A:    cs_str = "SSL3/DH-anon/DES56-CBC/SHA";       break;
   1.318 +  case 0x00001B:    cs_str = "SSL3/DH-anon/3DES192EDE-CBC/SHA"; break;
   1.319 +
   1.320 +  case 0x00001C:    cs_str = "SSL3/FORTEZZA-DMS/NULL/SHA";      break;
   1.321 +  case 0x00001D:    cs_str = "SSL3/FORTEZZA-DMS/FORTEZZA-CBC/SHA";  break;
   1.322 +  case 0x00001E:    cs_str = "SSL3/FORTEZZA-DMS/RC4-128/SHA";  break;
   1.323 +
   1.324 +  case 0x00002F:    cs_str = "TLS/RSA/AES128-CBC/SHA";  	break;
   1.325 +  case 0x000030:    cs_str = "TLS/DH-DSS/AES128-CBC/SHA";	break;
   1.326 +  case 0x000031:    cs_str = "TLS/DH-RSA/AES128-CBC/SHA";	break;
   1.327 +  case 0x000032:    cs_str = "TLS/DHE-DSS/AES128-CBC/SHA";	break;
   1.328 +  case 0x000033:    cs_str = "TLS/DHE-RSA/AES128-CBC/SHA";	break;
   1.329 +  case 0x000034:    cs_str = "TLS/DH-ANON/AES128-CBC/SHA";	break;
   1.330 +
   1.331 +  case 0x000035:    cs_str = "TLS/RSA/AES256-CBC/SHA";  	break;
   1.332 +  case 0x000036:    cs_str = "TLS/DH-DSS/AES256-CBC/SHA";	break;
   1.333 +  case 0x000037:    cs_str = "TLS/DH-RSA/AES256-CBC/SHA";	break;
   1.334 +  case 0x000038:    cs_str = "TLS/DHE-DSS/AES256-CBC/SHA";	break;
   1.335 +  case 0x000039:    cs_str = "TLS/DHE-RSA/AES256-CBC/SHA";	break;
   1.336 +  case 0x00003A:    cs_str = "TLS/DH-ANON/AES256-CBC/SHA";	break;
   1.337 +
   1.338 +  case 0x00003B:    cs_str = "TLS/RSA/NULL/SHA256";		break;
   1.339 +  case 0x00003C:    cs_str = "TLS/RSA/AES128-CBC/SHA256";  	break;
   1.340 +  case 0x00003D:    cs_str = "TLS/RSA/AES256-CBC/SHA256";  	break;
   1.341 +  case 0x00003E:    cs_str = "TLS/DH-DSS/AES128-CBC/SHA256";  	break;
   1.342 +  case 0x00003F:    cs_str = "TLS/DH-RSA/AES128-CBC/SHA256";  	break;
   1.343 +  case 0x000040:    cs_str = "TLS/DHE-DSS/AES128-CBC/SHA256";	break;
   1.344 +
   1.345 +  case 0x000041:    cs_str = "TLS/RSA/CAMELLIA128-CBC/SHA";	break;
   1.346 +  case 0x000042:    cs_str = "TLS/DH-DSS/CAMELLIA128-CBC/SHA";	break;
   1.347 +  case 0x000043:    cs_str = "TLS/DH-RSA/CAMELLIA128-CBC/SHA";	break;
   1.348 +  case 0x000044:    cs_str = "TLS/DHE-DSS/CAMELLIA128-CBC/SHA";	break;
   1.349 +  case 0x000045:    cs_str = "TLS/DHE-RSA/CAMELLIA128-CBC/SHA";	break;
   1.350 +  case 0x000046:    cs_str = "TLS/DH-ANON/CAMELLIA128-CBC/SHA";	break;
   1.351 +
   1.352 +  case 0x000060:    cs_str = "TLS/RSA-EXPORT1024/RC4-56/MD5";	break;
   1.353 +  case 0x000061:    cs_str = "TLS/RSA-EXPORT1024/RC2CBC56/MD5";	break;
   1.354 +  case 0x000062:    cs_str = "TLS/RSA-EXPORT1024/DES56-CBC/SHA";   break;
   1.355 +  case 0x000064:    cs_str = "TLS/RSA-EXPORT1024/RC4-56/SHA";	   break;
   1.356 +  case 0x000063:    cs_str = "TLS/DHE-DSS_EXPORT1024/DES56-CBC/SHA"; break;
   1.357 +  case 0x000065:    cs_str = "TLS/DHE-DSS_EXPORT1024/RC4-56/SHA";  break;
   1.358 +  case 0x000066:    cs_str = "TLS/DHE-DSS/RC4-128/SHA";		   break;
   1.359 +
   1.360 +  case 0x000067:    cs_str = "TLS/DHE-RSA/AES128-CBC/SHA256";   break;
   1.361 +  case 0x000068:    cs_str = "TLS/DH-DSS/AES256-CBC/SHA256";    break;
   1.362 +  case 0x000069:    cs_str = "TLS/DH-RSA/AES256-CBC/SHA256";    break;
   1.363 +  case 0x00006A:    cs_str = "TLS/DHE-DSS/AES256-CBC/SHA256";	break;
   1.364 +  case 0x00006B:    cs_str = "TLS/DHE-RSA/AES256-CBC/SHA256";	break;
   1.365 +
   1.366 +  case 0x000072:    cs_str = "TLS/DHE-DSS/3DESEDE-CBC/RMD160"; break;
   1.367 +  case 0x000073:    cs_str = "TLS/DHE-DSS/AES128-CBC/RMD160";  break;
   1.368 +  case 0x000074:    cs_str = "TLS/DHE-DSS/AES256-CBC/RMD160";  break;
   1.369 +
   1.370 +  case 0x000079:    cs_str = "TLS/DHE-RSA/AES256-CBC/RMD160";  break;
   1.371 +
   1.372 +  case 0x00007C:    cs_str = "TLS/RSA/3DESEDE-CBC/RMD160"; break;
   1.373 +  case 0x00007D:    cs_str = "TLS/RSA/AES128-CBC/RMD160"; break;
   1.374 +  case 0x00007E:    cs_str = "TLS/RSA/AES256-CBC/RMD160"; break;
   1.375 +
   1.376 +  case 0x000080:    cs_str = "TLS/GOST341094/GOST28147-OFB/GOST28147"; break;
   1.377 +  case 0x000081:    cs_str = "TLS/GOST34102001/GOST28147-OFB/GOST28147"; break;
   1.378 +  case 0x000082:    cs_str = "TLS/GOST341094/NULL/GOSTR3411"; break;
   1.379 +  case 0x000083:    cs_str = "TLS/GOST34102001/NULL/GOSTR3411"; break;
   1.380 +
   1.381 +  case 0x000084:    cs_str = "TLS/RSA/CAMELLIA256-CBC/SHA";	break;
   1.382 +  case 0x000085:    cs_str = "TLS/DH-DSS/CAMELLIA256-CBC/SHA";	break;
   1.383 +  case 0x000086:    cs_str = "TLS/DH-RSA/CAMELLIA256-CBC/SHA";	break;
   1.384 +  case 0x000087:    cs_str = "TLS/DHE-DSS/CAMELLIA256-CBC/SHA";	break;
   1.385 +  case 0x000088:    cs_str = "TLS/DHE-RSA/CAMELLIA256-CBC/SHA";	break;
   1.386 +  case 0x000089:    cs_str = "TLS/DH-ANON/CAMELLIA256-CBC/SHA";	break;
   1.387 +  case 0x00008A:    cs_str = "TLS/PSK/RC4-128/SHA";		break;
   1.388 +  case 0x00008B:    cs_str = "TLS/PSK/3DES-EDE-CBC/SHA";	break;
   1.389 +  case 0x00008C:    cs_str = "TLS/PSK/AES128-CBC/SHA";		break;      
   1.390 +  case 0x00008D:    cs_str = "TLS/PSK/AES256-CBC/SHA";		break;      
   1.391 +  case 0x00008E:    cs_str = "TLS/DHE-PSK/RC4-128/SHA";		break;      
   1.392 +  case 0x00008F:    cs_str = "TLS/DHE-PSK/3DES-EDE-CBC/SHA";	break; 
   1.393 +  case 0x000090:    cs_str = "TLS/DHE-PSK/AES128-CBC/SHA";	break;  
   1.394 +  case 0x000091:    cs_str = "TLS/DHE-PSK/AES256-CBC/SHA";	break;  
   1.395 +  case 0x000092:    cs_str = "TLS/RSA-PSK/RC4-128/SHA";		break;      
   1.396 +  case 0x000093:    cs_str = "TLS/RSA-PSK/3DES-EDE-CBC/SHA";	break; 
   1.397 +  case 0x000094:    cs_str = "TLS/RSA-PSK/AES128-CBC/SHA";	break;  
   1.398 +  case 0x000095:    cs_str = "TLS/RSA-PSK/AES256-CBC/SHA";	break;  
   1.399 +  case 0x000096:    cs_str = "TLS/RSA/SEED-CBC/SHA";		break;         
   1.400 +  case 0x000097:    cs_str = "TLS/DH-DSS/SEED-CBC/SHA";		break;      
   1.401 +  case 0x000098:    cs_str = "TLS/DH-RSA/SEED-CBC/SHA";		break;      
   1.402 +  case 0x000099:    cs_str = "TLS/DHE-DSS/SEED-CBC/SHA";	break;     
   1.403 +  case 0x00009A:    cs_str = "TLS/DHE-RSA/SEED-CBC/SHA";	break;     
   1.404 +  case 0x00009B:    cs_str = "TLS/DH-ANON/SEED-CBC/SHA";	break;     
   1.405 +  case 0x00009C:    cs_str = "TLS/RSA/AES128-GCM/SHA256";	break;     
   1.406 +  case 0x00009E:    cs_str = "TLS/DHE-RSA/AES128-GCM/SHA256";	break;     
   1.407 +
   1.408 +  case 0x0000FF:    cs_str = "TLS_EMPTY_RENEGOTIATION_INFO_SCSV"; break;
   1.409 +
   1.410 +  case 0x00C001:    cs_str = "TLS/ECDH-ECDSA/NULL/SHA";         break;
   1.411 +  case 0x00C002:    cs_str = "TLS/ECDH-ECDSA/RC4-128/SHA";      break;
   1.412 +  case 0x00C003:    cs_str = "TLS/ECDH-ECDSA/3DES-EDE-CBC/SHA"; break;
   1.413 +  case 0x00C004:    cs_str = "TLS/ECDH-ECDSA/AES128-CBC/SHA";   break;
   1.414 +  case 0x00C005:    cs_str = "TLS/ECDH-ECDSA/AES256-CBC/SHA";   break;
   1.415 +  case 0x00C006:    cs_str = "TLS/ECDHE-ECDSA/NULL/SHA";        break;
   1.416 +  case 0x00C007:    cs_str = "TLS/ECDHE-ECDSA/RC4-128/SHA";     break;
   1.417 +  case 0x00C008:    cs_str = "TLS/ECDHE-ECDSA/3DES-EDE-CBC/SHA";break;
   1.418 +  case 0x00C009:    cs_str = "TLS/ECDHE-ECDSA/AES128-CBC/SHA";  break;
   1.419 +  case 0x00C00A:    cs_str = "TLS/ECDHE-ECDSA/AES256-CBC/SHA";  break;
   1.420 +  case 0x00C00B:    cs_str = "TLS/ECDH-RSA/NULL/SHA";           break;
   1.421 +  case 0x00C00C:    cs_str = "TLS/ECDH-RSA/RC4-128/SHA";        break;
   1.422 +  case 0x00C00D:    cs_str = "TLS/ECDH-RSA/3DES-EDE-CBC/SHA";   break;
   1.423 +  case 0x00C00E:    cs_str = "TLS/ECDH-RSA/AES128-CBC/SHA";     break;
   1.424 +  case 0x00C00F:    cs_str = "TLS/ECDH-RSA/AES256-CBC/SHA";     break;
   1.425 +  case 0x00C010:    cs_str = "TLS/ECDHE-RSA/NULL/SHA";          break;
   1.426 +  case 0x00C011:    cs_str = "TLS/ECDHE-RSA/RC4-128/SHA";       break;
   1.427 +  case 0x00C012:    cs_str = "TLS/ECDHE-RSA/3DES-EDE-CBC/SHA";  break;
   1.428 +  case 0x00C013:    cs_str = "TLS/ECDHE-RSA/AES128-CBC/SHA";    break;
   1.429 +  case 0x00C014:    cs_str = "TLS/ECDHE-RSA/AES256-CBC/SHA";    break;
   1.430 +  case 0x00C015:    cs_str = "TLS/ECDH-anon/NULL/SHA";          break;
   1.431 +  case 0x00C016:    cs_str = "TLS/ECDH-anon/RC4-128/SHA";       break;
   1.432 +  case 0x00C017:    cs_str = "TLS/ECDH-anon/3DES-EDE-CBC/SHA";  break;
   1.433 +  case 0x00C018:    cs_str = "TLS/ECDH-anon/AES128-CBC/SHA";    break;
   1.434 +  case 0x00C019:    cs_str = "TLS/ECDH-anon/AES256-CBC/SHA";    break;
   1.435 +
   1.436 +  case 0x00C023:    cs_str = "TLS/ECDHE-ECDSA/AES128-CBC/SHA256"; break;
   1.437 +  case 0x00C024:    cs_str = "TLS/ECDHE-ECDSA/AES256-CBC/SHA384"; break;
   1.438 +  case 0x00C025:    cs_str = "TLS/ECDH-ECDSA/AES128-CBC/SHA256"; break;
   1.439 +  case 0x00C026:    cs_str = "TLS/ECDH-ECDSA/AES256-CBC/SHA384"; break;
   1.440 +  case 0x00C027:    cs_str = "TLS/ECDHE-RSA/AES128-CBC/SHA256"; break;
   1.441 +  case 0x00C028:    cs_str = "TLS/ECDHE-RSA/AES256-CBC/SHA384"; break;
   1.442 +  case 0x00C029:    cs_str = "TLS/ECDH-RSA/AES128-CBC/SHA256"; break;
   1.443 +  case 0x00C02A:    cs_str = "TLS/ECDH-RSA/AES256-CBC/SHA384"; break;
   1.444 +  case 0x00C02B:    cs_str = "TLS/ECDHE-ECDSA/AES128-GCM/SHA256"; break;
   1.445 +  case 0x00C02C:    cs_str = "TLS/ECDHE-ECDSA/AES256-GCM/SHA384"; break;
   1.446 +  case 0x00C02F:    cs_str = "TLS/ECDHE-RSA/AES128-GCM/SHA256"; break;
   1.447 +
   1.448 +  case 0x00FEFF:    cs_str = "SSL3/RSA-FIPS/3DESEDE-CBC/SHA";	break;
   1.449 +  case 0x00FEFE:    cs_str = "SSL3/RSA-FIPS/DES-CBC/SHA";	break;
   1.450 +  case 0x00FFE1:    cs_str = "SSL3/RSA-FIPS/DES56-CBC/SHA";     break;
   1.451 +  case 0x00FFE0:    cs_str = "SSL3/RSA-FIPS/3DES192EDE-CBC/SHA";break;
   1.452 +
   1.453 +  /* the string literal is broken up to avoid trigraphs */
   1.454 +  default:          cs_str = "????" "/????????" "/?????????" "/???"; break;
   1.455 +  }
   1.456 +
   1.457 +  return cs_str;
   1.458 +}
   1.459 +
   1.460 +const char * CompressionMethodString(int cm_int) 
   1.461 +{
   1.462 +  char *cm_str;
   1.463 +  cm_str = NULL;
   1.464 +  switch (cm_int) {
   1.465 +  case  0: cm_str = "NULL";     break;
   1.466 +  case  1: cm_str = "DEFLATE";  break;  /* RFC 3749 */
   1.467 +  case 64: cm_str = "LZS";      break;  /* RFC 3943 */
   1.468 +  default: cm_str = "???";      break;
   1.469 +  }
   1.470 +
   1.471 +  return cm_str;
   1.472 +}
   1.473 +
   1.474 +const char * helloExtensionNameString(int ex_num) 
   1.475 +{
   1.476 +  const char *ex_name = NULL;
   1.477 +  static char buf[10];
   1.478 +
   1.479 +  switch (ex_num) {
   1.480 +  case  0: ex_name = "server_name";                    break;
   1.481 +  case  1: ex_name = "max_fragment_length";            break;
   1.482 +  case  2: ex_name = "client_certificate_url";         break;
   1.483 +  case  3: ex_name = "trusted_ca_keys";                break;
   1.484 +  case  4: ex_name = "truncated_hmac";                 break;
   1.485 +  case  5: ex_name = "status_request";                 break;
   1.486 +  case 10: ex_name = "elliptic_curves";                break;
   1.487 +  case 11: ex_name = "ec_point_formats";               break;
   1.488 +  case 13: ex_name = "signature_algorithms";           break;
   1.489 +  case 35: ex_name = "session_ticket";                 break;
   1.490 +  case 0xff01: ex_name = "renegotiation_info";         break;
   1.491 +  default: sprintf(buf, "%d", ex_num);  ex_name = (const char *)buf; break;
   1.492 +  }
   1.493 +
   1.494 +  return ex_name;
   1.495 +}
   1.496 +
   1.497 +static int isNULLmac(int cs_int)
   1.498 +{
   1.499 +    return (cs_int == TLS_NULL_WITH_NULL_NULL);
   1.500 +}
   1.501 +
   1.502 +static int isNULLcipher(int cs_int)
   1.503 +{
   1.504 + return ((cs_int == TLS_RSA_WITH_NULL_MD5) ||
   1.505 +         (cs_int == TLS_RSA_WITH_NULL_SHA) ||
   1.506 +         (cs_int == SSL_FORTEZZA_DMS_WITH_NULL_SHA) ||
   1.507 +         (cs_int == TLS_ECDH_ECDSA_WITH_NULL_SHA) ||
   1.508 +         (cs_int == TLS_ECDHE_ECDSA_WITH_NULL_SHA) ||
   1.509 +         (cs_int == TLS_ECDH_RSA_WITH_NULL_SHA) ||
   1.510 +         (cs_int == TLS_ECDHE_RSA_WITH_NULL_SHA));
   1.511 +} 
   1.512 +
   1.513 +void partial_packet(int thispacket, int size, int needed)
   1.514 +{
   1.515 +  PR_fprintf(PR_STDOUT,"(%u bytes", thispacket);
   1.516 +  if (thispacket < needed) {
   1.517 +    PR_fprintf(PR_STDOUT,", making %u", size);
   1.518 +  }
   1.519 +  PR_fprintf(PR_STDOUT," of %u", needed);
   1.520 +  if (size > needed) {
   1.521 +    PR_fprintf(PR_STDOUT,", with %u left over", size - needed);
   1.522 +  }
   1.523 +  PR_fprintf(PR_STDOUT,")\n");
   1.524 +}
   1.525 +
   1.526 +char * get_time_string(void)
   1.527 +{
   1.528 +  char      *cp;
   1.529 +  char      *eol;
   1.530 +  time_t     tt;
   1.531 +
   1.532 +  time(&tt);
   1.533 +  cp = ctime(&tt);
   1.534 +  eol = strchr(cp, '\n');
   1.535 +  if (eol) 
   1.536 +    *eol = 0;
   1.537 +  return cp;
   1.538 +}
   1.539 +
   1.540 +void print_sslv2(DataBufferList *s, unsigned char *recordBuf, unsigned int recordLen)
   1.541 +{
   1.542 +  ClientHelloV2 *chv2;
   1.543 +  ServerHelloV2 *shv2;
   1.544 +  unsigned char *pos;
   1.545 +  unsigned int   p;
   1.546 +  unsigned int   q;
   1.547 +  PRUint32       len;
   1.548 +
   1.549 +  chv2 = (ClientHelloV2 *)recordBuf;
   1.550 +  shv2 = (ServerHelloV2 *)recordBuf;
   1.551 +  if (s->isEncrypted) {
   1.552 +    PR_fprintf(PR_STDOUT," [ssl2]  Encrypted {...}\n");
   1.553 +    return;
   1.554 +  }
   1.555 +  PR_fprintf(PR_STDOUT," [%s]", get_time_string() );
   1.556 +  switch(chv2->type) {
   1.557 +  case 1:
   1.558 +    PR_fprintf(PR_STDOUT," [ssl2]  ClientHelloV2 {\n");
   1.559 +    PR_fprintf(PR_STDOUT,"           version = {0x%02x, 0x%02x}\n",
   1.560 +	       (PRUint32)chv2->version[0],(PRUint32)chv2->version[1]);
   1.561 +    PR_fprintf(PR_STDOUT,"           cipher-specs-length = %d (0x%02x)\n",
   1.562 +	       (PRUint32)(GET_SHORT((chv2->cslength))),
   1.563 +	       (PRUint32)(GET_SHORT((chv2->cslength))));
   1.564 +    PR_fprintf(PR_STDOUT,"           sid-length = %d (0x%02x)\n",
   1.565 +	       (PRUint32)(GET_SHORT((chv2->sidlength))),
   1.566 +	       (PRUint32)(GET_SHORT((chv2->sidlength))));
   1.567 +    PR_fprintf(PR_STDOUT,"           challenge-length = %d (0x%02x)\n",
   1.568 +	       (PRUint32)(GET_SHORT((chv2->rndlength))),
   1.569 +	       (PRUint32)(GET_SHORT((chv2->rndlength))));
   1.570 +    PR_fprintf(PR_STDOUT,"           cipher-suites = { \n");
   1.571 +    for (p=0;p<GET_SHORT((chv2->cslength));p+=3) {
   1.572 +      PRUint32 cs_int    = GET_24((&chv2->csuites[p]));
   1.573 +      const char *cs_str = V2CipherString(cs_int);
   1.574 +
   1.575 +      PR_fprintf(PR_STDOUT,"                (0x%06x) %s\n",
   1.576 +		  cs_int, cs_str);
   1.577 +    }
   1.578 +    q = p;
   1.579 +    PR_fprintf(PR_STDOUT,"                }\n");
   1.580 +    if (chv2->sidlength) {
   1.581 +      PR_fprintf(PR_STDOUT,"           session-id = { ");
   1.582 +      for (p=0;p<GET_SHORT((chv2->sidlength));p+=2) {
   1.583 +	PR_fprintf(PR_STDOUT,"0x%04x ",(PRUint32)(GET_SHORT((&chv2->csuites[p+q]))));
   1.584 +      }
   1.585 +    }
   1.586 +    q += p;
   1.587 +    PR_fprintf(PR_STDOUT,"}\n");
   1.588 +    if (chv2->rndlength) {
   1.589 +      PR_fprintf(PR_STDOUT,"           challenge = { ");
   1.590 +      for (p=0;p<GET_SHORT((chv2->rndlength));p+=2) {
   1.591 +	PR_fprintf(PR_STDOUT,"0x%04x ",(PRUint32)(GET_SHORT((&chv2->csuites[p+q]))));
   1.592 +      }
   1.593 +      PR_fprintf(PR_STDOUT,"}\n");
   1.594 +    }
   1.595 +    PR_fprintf(PR_STDOUT,"}\n");
   1.596 +    break;
   1.597 +    /* end of V2 CLientHello Parsing */
   1.598 +
   1.599 +  case 2:  /* Client Master Key  */
   1.600 +    {
   1.601 +    const char *cs_str=NULL;
   1.602 +    PRUint32 cs_int=0;
   1.603 +    ClientMasterKeyV2 *cmkv2;
   1.604 +    cmkv2 = (ClientMasterKeyV2 *)chv2;
   1.605 +    isV2Session = 1;
   1.606 +
   1.607 +    PR_fprintf(PR_STDOUT," [ssl2]  ClientMasterKeyV2 { \n");
   1.608 +
   1.609 +    cs_int = GET_24(&cmkv2->cipherkind[0]);
   1.610 +    cs_str = V2CipherString(cs_int);
   1.611 +    PR_fprintf(PR_STDOUT,"         cipher-spec-chosen = (0x%06x) %s\n",
   1.612 +	       cs_int, cs_str);
   1.613 +
   1.614 +    PR_fprintf(PR_STDOUT,"         clear-portion = %d bits\n",
   1.615 +	       8*(PRUint32)(GET_SHORT((cmkv2->clearkey))));
   1.616 +
   1.617 +    PR_fprintf(PR_STDOUT,"      }\n");
   1.618 +    clientstream.isEncrypted = 1;
   1.619 +    serverstream.isEncrypted = 1;
   1.620 +    }
   1.621 +    break;
   1.622 +
   1.623 +
   1.624 +  case 3:
   1.625 +    PR_fprintf(PR_STDOUT," [ssl2]  Client Finished V2 {...}\n");
   1.626 +    isV2Session = 1;
   1.627 +    break;
   1.628 +
   1.629 +
   1.630 +  case 4:  /* V2 Server Hello */
   1.631 +    isV2Session = 1;
   1.632 +
   1.633 +    PR_fprintf(PR_STDOUT," [ssl2]  ServerHelloV2 {\n");
   1.634 +    PR_fprintf(PR_STDOUT,"           sid hit = {0x%02x}\n",
   1.635 +	       (PRUintn)shv2->sidhit);
   1.636 +    PR_fprintf(PR_STDOUT,"           version = {0x%02x, 0x%02x}\n",
   1.637 +	       (PRUint32)shv2->version[0],(PRUint32)shv2->version[1]);
   1.638 +    PR_fprintf(PR_STDOUT,"           cipher-specs-length = %d (0x%02x)\n",
   1.639 +	       (PRUint32)(GET_SHORT((shv2->cslength))),
   1.640 +	       (PRUint32)(GET_SHORT((shv2->cslength))));
   1.641 +    PR_fprintf(PR_STDOUT,"           sid-length = %d (0x%02x)\n",
   1.642 +	       (PRUint32)(GET_SHORT((shv2->cidlength))),
   1.643 +	       (PRUint32)(GET_SHORT((shv2->cidlength))));
   1.644 +
   1.645 +    pos = (unsigned char *)shv2;
   1.646 +    pos += 2;   /* skip length header */
   1.647 +    pos += 11;  /* position pointer to Certificate data area */
   1.648 +    q = GET_SHORT(&shv2->certlength);
   1.649 +    if (q >recordLen) {
   1.650 +      goto eosh;
   1.651 +    }
   1.652 +    pos += q; 			/* skip certificate */
   1.653 +
   1.654 +    PR_fprintf(PR_STDOUT,"           cipher-suites = { ");
   1.655 +    len = GET_SHORT((shv2->cslength));
   1.656 +    for (p = 0; p < len; p += 3) {
   1.657 +      PRUint32 cs_int    = GET_24((pos+p));
   1.658 +      const char *cs_str = V2CipherString(cs_int);
   1.659 +      PR_fprintf(PR_STDOUT,"\n              ");
   1.660 +      PR_fprintf(PR_STDOUT,"(0x%06x) %s", cs_int, cs_str);
   1.661 +    }
   1.662 +    pos += len;
   1.663 +    PR_fprintf(PR_STDOUT,"   }\n");	/* End of cipher suites */
   1.664 +    len = (PRUint32)GET_SHORT((shv2->cidlength));
   1.665 +    if (len) {
   1.666 +      PR_fprintf(PR_STDOUT,"           connection-id = { ");
   1.667 +      for (p = 0; p < len; p += 2) {
   1.668 +	PR_fprintf(PR_STDOUT,"0x%04x ", (PRUint32)(GET_SHORT((pos + p))));
   1.669 +      }
   1.670 +      PR_fprintf(PR_STDOUT,"   }\n");	/* End of connection id */
   1.671 +    }
   1.672 +eosh:
   1.673 +    PR_fprintf(PR_STDOUT,"\n              }\n"); /* end of ServerHelloV2 */
   1.674 +    if (shv2->sidhit) {
   1.675 +      clientstream.isEncrypted = 1;
   1.676 +      serverstream.isEncrypted = 1;
   1.677 +    }
   1.678 +    break;
   1.679 +
   1.680 +  case 5:
   1.681 +    PR_fprintf(PR_STDOUT," [ssl2]  Server Verify V2 {...}\n");
   1.682 +    isV2Session = 1;
   1.683 +    break;
   1.684 +
   1.685 +  case 6:
   1.686 +    PR_fprintf(PR_STDOUT," [ssl2]  Server Finished V2 {...}\n");
   1.687 +    isV2Session = 1;
   1.688 +    break;
   1.689 +
   1.690 +  case 7:
   1.691 +    PR_fprintf(PR_STDOUT," [ssl2]  Request Certificate V2 {...}\n");
   1.692 +    isV2Session = 1;
   1.693 +    break;
   1.694 +
   1.695 +  case 8:
   1.696 +    PR_fprintf(PR_STDOUT," [ssl2]  Client Certificate V2 {...}\n");
   1.697 +    isV2Session = 1;
   1.698 +    break;
   1.699 +
   1.700 +  default:
   1.701 +    PR_fprintf(PR_STDOUT," [ssl2]  UnknownType 0x%02x {...}\n",
   1.702 +	  (PRUint32)chv2->type);
   1.703 +    break;
   1.704 +  }
   1.705 +}
   1.706 +
   1.707 +
   1.708 +
   1.709 +unsigned int print_hello_extension(unsigned char *  hsdata,
   1.710 +				   unsigned int     length,
   1.711 +				   unsigned int     pos)
   1.712 +{
   1.713 +  /* pretty print extensions, if any */
   1.714 +  if (pos < length) {
   1.715 +    int exListLen = GET_SHORT((hsdata+pos)); pos += 2;
   1.716 +    PR_fprintf(PR_STDOUT,
   1.717 +	       "            extensions[%d] = {\n", exListLen);
   1.718 +    while (exListLen > 0 && pos < length) {
   1.719 +      int exLen;
   1.720 +      int exType = GET_SHORT((hsdata+pos)); pos += 2;
   1.721 +      exLen = GET_SHORT((hsdata+pos)); pos += 2;
   1.722 +      /* dump the extension */
   1.723 +      PR_fprintf(PR_STDOUT,
   1.724 +		 "              extension type %s, length [%d]",
   1.725 +		 helloExtensionNameString(exType), exLen);
   1.726 +      if (exLen > 0) {
   1.727 +	  PR_fprintf(PR_STDOUT, " = {\n");
   1.728 +	  print_hex(exLen, hsdata + pos);
   1.729 +	  PR_fprintf(PR_STDOUT, "              }\n");
   1.730 +      } else {
   1.731 +	  PR_fprintf(PR_STDOUT, "\n");
   1.732 +      }
   1.733 +      pos += exLen;
   1.734 +      exListLen -= 2 + exLen;
   1.735 +    }
   1.736 +    PR_fprintf(PR_STDOUT,"            }\n");
   1.737 +  }
   1.738 +  return pos;
   1.739 +}
   1.740 +
   1.741 +/*
   1.742 + * Note this must match (exactly) the enumeration ocspResponseStatus.
   1.743 + */
   1.744 +static char *responseStatusNames[] = {
   1.745 +    "successful (Response has valid confirmations)",
   1.746 +    "malformedRequest (Illegal confirmation request)",
   1.747 +    "internalError (Internal error in issuer)",
   1.748 +    "tryLater (Try again later)",
   1.749 +    "unused ((4) is not used)",
   1.750 +    "sigRequired (Must sign the request)",
   1.751 +    "unauthorized (Request unauthorized)",
   1.752 +};
   1.753 +
   1.754 +static void
   1.755 +print_ocsp_cert_id (FILE *out_file, CERTOCSPCertID *cert_id, int level)
   1.756 +{
   1.757 +    SECU_Indent (out_file, level);
   1.758 +    fprintf (out_file, "Cert ID:\n");
   1.759 +    level++;
   1.760 +/*
   1.761 +    SECU_PrintAlgorithmID (out_file, &(cert_id->hashAlgorithm),
   1.762 +                           "Hash Algorithm", level);
   1.763 +    SECU_PrintAsHex (out_file, &(cert_id->issuerNameHash),
   1.764 +                     "Issuer Name Hash", level);
   1.765 +    SECU_PrintAsHex (out_file, &(cert_id->issuerKeyHash),
   1.766 +                     "Issuer Key Hash", level);
   1.767 +*/
   1.768 +    SECU_PrintInteger (out_file, &(cert_id->serialNumber),
   1.769 +                       "Serial Number", level);
   1.770 +    /* XXX lookup the cert; if found, print something nice (nickname?) */
   1.771 +}
   1.772 +
   1.773 +static void
   1.774 +print_ocsp_version (FILE *out_file, SECItem *version, int level)
   1.775 +{
   1.776 +    if (version->len > 0) {
   1.777 +        SECU_PrintInteger (out_file, version, "Version", level);
   1.778 +    } else {
   1.779 +        SECU_Indent (out_file, level);
   1.780 +        fprintf (out_file, "Version: DEFAULT\n");
   1.781 +    }
   1.782 +}
   1.783 +
   1.784 +static void
   1.785 +print_responder_id (FILE *out_file, ocspResponderID *responderID, int level)
   1.786 +{
   1.787 +    SECU_Indent (out_file, level);
   1.788 +    fprintf (out_file, "Responder ID ");
   1.789 +
   1.790 +    switch (responderID->responderIDType) {
   1.791 +      case ocspResponderID_byName:
   1.792 +        fprintf (out_file, "(byName):\n");
   1.793 +        SECU_PrintName (out_file, &(responderID->responderIDValue.name),
   1.794 +                        "Name", level + 1);
   1.795 +        break;
   1.796 +      case ocspResponderID_byKey:
   1.797 +        fprintf (out_file, "(byKey):\n");
   1.798 +        SECU_PrintAsHex (out_file, &(responderID->responderIDValue.keyHash),
   1.799 +                         "Key Hash", level + 1);
   1.800 +        break;
   1.801 +      default:
   1.802 +        fprintf (out_file, "Unrecognized Responder ID Type\n");
   1.803 +        break;
   1.804 +    }
   1.805 +}
   1.806 +
   1.807 +static void
   1.808 +print_ocsp_extensions (FILE *out_file, CERTCertExtension **extensions,
   1.809 +                       char *msg, int level)
   1.810 +{
   1.811 +    if (extensions) {
   1.812 +        SECU_PrintExtensions (out_file, extensions, msg, level);
   1.813 +    } else {
   1.814 +        SECU_Indent (out_file, level);
   1.815 +        fprintf (out_file, "No %s\n", msg);
   1.816 +    }
   1.817 +}
   1.818 +
   1.819 +static void
   1.820 +print_revoked_info (FILE *out_file, ocspRevokedInfo *revoked_info, int level)
   1.821 +{
   1.822 +    SECU_PrintGeneralizedTime (out_file, &(revoked_info->revocationTime),
   1.823 +                               "Revocation Time", level);
   1.824 +
   1.825 +    if (revoked_info->revocationReason != NULL) {
   1.826 +        SECU_PrintAsHex (out_file, revoked_info->revocationReason,
   1.827 +                         "Revocation Reason", level);
   1.828 +    } else {
   1.829 +        SECU_Indent (out_file, level);
   1.830 +        fprintf (out_file, "No Revocation Reason.\n");
   1.831 +    }
   1.832 +}
   1.833 +
   1.834 +static void
   1.835 +print_cert_status (FILE *out_file, ocspCertStatus *status, int level)
   1.836 +{
   1.837 +    SECU_Indent (out_file, level);
   1.838 +    fprintf (out_file, "Status: ");
   1.839 +
   1.840 +    switch (status->certStatusType) {
   1.841 +      case ocspCertStatus_good:
   1.842 +        fprintf (out_file, "Cert is good.\n");
   1.843 +        break;
   1.844 +      case ocspCertStatus_revoked:
   1.845 +        fprintf (out_file, "Cert has been revoked.\n");
   1.846 +        print_revoked_info (out_file, status->certStatusInfo.revokedInfo,
   1.847 +                            level + 1);
   1.848 +        break;
   1.849 +      case ocspCertStatus_unknown:
   1.850 +        fprintf (out_file, "Cert is unknown to responder.\n");
   1.851 +        break;
   1.852 +      default:
   1.853 +        fprintf (out_file, "Unrecognized status.\n");
   1.854 +        break;
   1.855 +    }
   1.856 +}
   1.857 +
   1.858 +static void
   1.859 +print_single_response (FILE *out_file, CERTOCSPSingleResponse *single,
   1.860 +                       int level)
   1.861 +{
   1.862 +    print_ocsp_cert_id (out_file, single->certID, level);
   1.863 +
   1.864 +    print_cert_status (out_file, single->certStatus, level);
   1.865 +
   1.866 +    SECU_PrintGeneralizedTime (out_file, &(single->thisUpdate),
   1.867 +                               "This Update", level);
   1.868 +
   1.869 +    if (single->nextUpdate != NULL) {
   1.870 +        SECU_PrintGeneralizedTime (out_file, single->nextUpdate,
   1.871 +                                   "Next Update", level);
   1.872 +    } else {
   1.873 +        SECU_Indent (out_file, level);
   1.874 +        fprintf (out_file, "No Next Update\n");
   1.875 +    }
   1.876 +
   1.877 +    print_ocsp_extensions (out_file, single->singleExtensions,
   1.878 +                           "Single Response Extensions", level);
   1.879 +}
   1.880 +
   1.881 +static void
   1.882 +print_response_data (FILE *out_file, ocspResponseData *responseData, int level)
   1.883 +{
   1.884 +    SECU_Indent (out_file, level);
   1.885 +    fprintf (out_file, "Response Data:\n");
   1.886 +    level++;
   1.887 +
   1.888 +    print_ocsp_version (out_file, &(responseData->version), level);
   1.889 +
   1.890 +    print_responder_id (out_file, responseData->responderID, level);
   1.891 +
   1.892 +    SECU_PrintGeneralizedTime (out_file, &(responseData->producedAt),
   1.893 +                               "Produced At", level);
   1.894 +
   1.895 +    if (responseData->responses != NULL) {
   1.896 +        int i;
   1.897 +
   1.898 +        for (i = 0; responseData->responses[i] != NULL; i++) {
   1.899 +            SECU_Indent (out_file, level);
   1.900 +            fprintf (out_file, "Response %d:\n", i);
   1.901 +            print_single_response (out_file, responseData->responses[i],
   1.902 +                                   level + 1);
   1.903 +        }
   1.904 +    } else {
   1.905 +        fprintf (out_file, "Response list is empty.\n");
   1.906 +    }
   1.907 +
   1.908 +    print_ocsp_extensions (out_file, responseData->responseExtensions,
   1.909 +                           "Response Extensions", level);
   1.910 +}
   1.911 +
   1.912 +static void
   1.913 +print_basic_response (FILE *out_file, ocspBasicOCSPResponse *basic, int level)
   1.914 +{
   1.915 +    SECU_Indent (out_file, level);
   1.916 +    fprintf (out_file, "Basic OCSP Response:\n");
   1.917 +    level++;
   1.918 +
   1.919 +    print_response_data (out_file, basic->tbsResponseData, level);
   1.920 +}
   1.921 +
   1.922 +static void
   1.923 +print_status_response(SECItem *data)
   1.924 +{
   1.925 +    int level = 2;
   1.926 +    CERTOCSPResponse *response;
   1.927 +    response = CERT_DecodeOCSPResponse (data);
   1.928 +    if (!response) {
   1.929 +        SECU_Indent (stdout, level);
   1.930 +        fprintf(stdout,"unable to decode certificate_status\n");
   1.931 +        return;
   1.932 +    }
   1.933 +    
   1.934 +    SECU_Indent (stdout, level);
   1.935 +    if (response->statusValue >= ocspResponse_min &&
   1.936 +	response->statusValue <= ocspResponse_max) {
   1.937 +	fprintf (stdout, "Response Status: %s\n",
   1.938 +		 responseStatusNames[response->statusValue]);
   1.939 +    } else {
   1.940 +	fprintf (stdout,
   1.941 +		 "Response Status: other (Status value %d out of defined range)\n",
   1.942 +		 (int)response->statusValue);
   1.943 +    }
   1.944 +
   1.945 +    if (response->statusValue == ocspResponse_successful) {
   1.946 +        ocspResponseBytes *responseBytes = response->responseBytes;
   1.947 +        PORT_Assert (responseBytes != NULL);
   1.948 +
   1.949 +        level++;
   1.950 +        SECU_PrintObjectID (stdout, &(responseBytes->responseType),
   1.951 +                            "Response Type", level);
   1.952 +        switch (response->responseBytes->responseTypeTag) {
   1.953 +          case SEC_OID_PKIX_OCSP_BASIC_RESPONSE:
   1.954 +            print_basic_response (stdout,
   1.955 +                                  responseBytes->decodedResponse.basic,
   1.956 +                                  level);
   1.957 +            break;
   1.958 +          default:
   1.959 +            SECU_Indent (stdout, level);
   1.960 +            fprintf (stdout, "Unknown response syntax\n");
   1.961 +            break;
   1.962 +        }
   1.963 +    } else {
   1.964 +        SECU_Indent (stdout, level);
   1.965 +        fprintf (stdout, "Unsuccessful response, no more information.\n");
   1.966 +    }
   1.967 +
   1.968 +    CERT_DestroyOCSPResponse (response);
   1.969 +}
   1.970 +
   1.971 +/* In the case of renegotiation, handshakes that occur in an already MAC'ed 
   1.972 + * channel, by the time of this call, the caller has already removed the MAC 
   1.973 + * from input recordLen. The only MAC'ed record that will get here with its 
   1.974 + * MAC intact (not removed) is the first Finished message on the connection.
   1.975 + */
   1.976 +void print_ssl3_handshake(unsigned char *recordBuf, 
   1.977 +                          unsigned int   recordLen,
   1.978 +                          SSLRecord *    sr,
   1.979 +			  DataBufferList *s)
   1.980 +{
   1.981 +  struct sslhandshake sslh; 
   1.982 +  unsigned char *     hsdata;  
   1.983 +  int                 offset=0;
   1.984 +
   1.985 +  PR_fprintf(PR_STDOUT,"   handshake {\n");
   1.986 +
   1.987 +  if (s->msgBufOffset && s->msgBuf) {
   1.988 +    /* append recordBuf to msgBuf, then use msgBuf */
   1.989 +    if (s->msgBufOffset + recordLen > s->msgBufSize) {
   1.990 +      int             newSize = s->msgBufOffset + recordLen;
   1.991 +      unsigned char * newBuf = PORT_Realloc(s->msgBuf, newSize);
   1.992 +      if (!newBuf) {
   1.993 +	PR_ASSERT(newBuf);
   1.994 +	showErr( "Realloc failed");
   1.995 +        exit(10);
   1.996 +      }
   1.997 +      s->msgBuf = newBuf;
   1.998 +      s->msgBufSize = newSize;
   1.999 +    }
  1.1000 +    memcpy(s->msgBuf + s->msgBufOffset, recordBuf, recordLen);
  1.1001 +    s->msgBufOffset += recordLen;
  1.1002 +    recordLen = s->msgBufOffset;
  1.1003 +    recordBuf = s->msgBuf;
  1.1004 +  }
  1.1005 +  while (offset + 4 <= recordLen) {
  1.1006 +    sslh.type = recordBuf[offset]; 
  1.1007 +    sslh.length = GET_24(recordBuf+offset+1);
  1.1008 +    if (offset + 4 + sslh.length > recordLen)
  1.1009 +      break;
  1.1010 +    /* finally have a complete message */
  1.1011 +    if (sslhexparse) 
  1.1012 +      print_hex(4,recordBuf+offset);
  1.1013 +
  1.1014 +    hsdata = &recordBuf[offset+4];
  1.1015 +
  1.1016 +    PR_fprintf(PR_STDOUT,"      type = %d (",sslh.type);
  1.1017 +    switch(sslh.type) {
  1.1018 +    case 0:  PR_FPUTS("hello_request)\n"               ); break;
  1.1019 +    case 1:  PR_FPUTS("client_hello)\n"                ); break;
  1.1020 +    case 2:  PR_FPUTS("server_hello)\n"                ); break;
  1.1021 +    case 4:  PR_FPUTS("new_session_ticket)\n"          ); break;
  1.1022 +    case 11: PR_FPUTS("certificate)\n"                 ); break;
  1.1023 +    case 12: PR_FPUTS("server_key_exchange)\n"         ); break;
  1.1024 +    case 13: PR_FPUTS("certificate_request)\n"         ); break;
  1.1025 +    case 14: PR_FPUTS("server_hello_done)\n"           ); break;
  1.1026 +    case 15: PR_FPUTS("certificate_verify)\n"          ); break;
  1.1027 +    case 16: PR_FPUTS("client_key_exchange)\n"         ); break;
  1.1028 +    case 20: PR_FPUTS("finished)\n"                    ); break;
  1.1029 +    case 22: PR_FPUTS("certificate_status)\n"          ); break;
  1.1030 +    default: PR_FPUTS("unknown)\n"                     ); break;
  1.1031 +    }
  1.1032 +
  1.1033 +    PR_fprintf(PR_STDOUT,"      length = %d (0x%06x)\n",sslh.length,sslh.length);
  1.1034 +    switch (sslh.type) {
  1.1035 +
  1.1036 +    case 0: /* hello_request */ /* not much to show here. */ break;
  1.1037 +
  1.1038 +    case 1: /* client hello */
  1.1039 +      switch (sr->ver_maj)  {
  1.1040 +      case 3:  /* ssl version 3 */
  1.1041 +	{
  1.1042 +	  unsigned int pos;
  1.1043 +	  int w;
  1.1044 +
  1.1045 +	  PR_fprintf(PR_STDOUT,"         ClientHelloV3 {\n");
  1.1046 +	  PR_fprintf(PR_STDOUT,"            client_version = {%d, %d}\n",
  1.1047 +		     (PRUint8)hsdata[0],(PRUint8)hsdata[1]);
  1.1048 +	  PR_fprintf(PR_STDOUT,"            random = {...}\n");
  1.1049 +	  if (sslhexparse) print_hex(32,&hsdata[2]);
  1.1050 +
  1.1051 +	  /* pretty print Session ID */
  1.1052 +	  {
  1.1053 +	    int sidlength = (int)hsdata[2+32];
  1.1054 +	    PR_fprintf(PR_STDOUT,"            session ID = {\n");
  1.1055 +	    PR_fprintf(PR_STDOUT,"                length = %d\n",sidlength);
  1.1056 +	    PR_fprintf(PR_STDOUT,"                contents = {...}\n");
  1.1057 +	    if (sslhexparse) print_hex(sidlength,&hsdata[2+32+1]);
  1.1058 +	    PR_fprintf(PR_STDOUT,"            }\n");
  1.1059 +	    pos = 2+32+1+sidlength;
  1.1060 +	  }
  1.1061 +
  1.1062 +	  /* pretty print cipher suites */
  1.1063 +	  {
  1.1064 +	    int csuitelength = GET_SHORT((hsdata+pos));
  1.1065 +	    PR_fprintf(PR_STDOUT,"            cipher_suites[%d] = {\n",
  1.1066 +		       csuitelength/2);
  1.1067 +	    if (csuitelength % 2) {
  1.1068 +	      PR_fprintf(PR_STDOUT,
  1.1069 +		 "*error in protocol - csuitelength shouldn't be odd*\n");
  1.1070 +	    }
  1.1071 +	    for (w=0; w<csuitelength; w+=2) {
  1.1072 +	      PRUint32 cs_int    = GET_SHORT((hsdata+pos+2+w));
  1.1073 +	      const char *cs_str = V2CipherString(cs_int);
  1.1074 +	      PR_fprintf(PR_STDOUT,
  1.1075 +		"                (0x%04x) %s\n", cs_int, cs_str);
  1.1076 +	    }
  1.1077 +	    pos += 2 + csuitelength;
  1.1078 +	    PR_fprintf(PR_STDOUT,"            }\n");
  1.1079 +	  }
  1.1080 +
  1.1081 +	  /* pretty print compression methods */
  1.1082 +	  {
  1.1083 +	    int complength = hsdata[pos];
  1.1084 +	    PR_fprintf(PR_STDOUT,"            compression[%d] = {\n",
  1.1085 +	               complength);
  1.1086 +	    for (w=0; w < complength; w++) {
  1.1087 +	      PRUint32 cm_int    = hsdata[pos+1+w];
  1.1088 +	      const char *cm_str = CompressionMethodString(cm_int);
  1.1089 +	      PR_fprintf(PR_STDOUT,
  1.1090 +		"                (%02x) %s\n", cm_int, cm_str);
  1.1091 +	    }
  1.1092 +	    pos += 1 + complength;
  1.1093 +	    PR_fprintf(PR_STDOUT,"            }\n");
  1.1094 +	  }
  1.1095 +
  1.1096 +	  /* pretty print extensions, if any */
  1.1097 +	  pos = print_hello_extension(hsdata, sslh.length, pos);
  1.1098 +
  1.1099 +	  PR_fprintf(PR_STDOUT,"         }\n");
  1.1100 +	} /* end of ssl version 3 */
  1.1101 +	break;
  1.1102 +      default:
  1.1103 +	PR_fprintf(PR_STDOUT,"         UNDEFINED VERSION %d.%d {...}\n",
  1.1104 +	                     sr->ver_maj, sr->ver_min );
  1.1105 +	if (sslhexparse) print_hex(sslh.length, hsdata);
  1.1106 +	break;
  1.1107 +      } /* end of switch sr->ver_maj */
  1.1108 +      break;
  1.1109 +
  1.1110 +    case 2: /* server hello */
  1.1111 +      {
  1.1112 +	unsigned int sidlength, pos;
  1.1113 +
  1.1114 +	PR_fprintf(PR_STDOUT,"         ServerHello {\n");
  1.1115 +
  1.1116 +	PR_fprintf(PR_STDOUT,"            server_version = {%d, %d}\n",
  1.1117 +		   (PRUint8)hsdata[0],(PRUint8)hsdata[1]);
  1.1118 +	PR_fprintf(PR_STDOUT,"            random = {...}\n");
  1.1119 +	if (sslhexparse) print_hex(32,&hsdata[2]);
  1.1120 +	PR_fprintf(PR_STDOUT,"            session ID = {\n");
  1.1121 +	sidlength = (int)hsdata[2+32];
  1.1122 +	PR_fprintf(PR_STDOUT,"                length = %d\n",sidlength);
  1.1123 +	PR_fprintf(PR_STDOUT,"                contents = {...}\n");
  1.1124 +	if (sslhexparse) print_hex(sidlength,&hsdata[2+32+1]);
  1.1125 +	PR_fprintf(PR_STDOUT,"            }\n");
  1.1126 +	pos = 2+32+1+sidlength;
  1.1127 +
  1.1128 +	/* pretty print chosen cipher suite */
  1.1129 +	{
  1.1130 +	  PRUint32 cs_int    = GET_SHORT((hsdata+pos));
  1.1131 +	  const char *cs_str = V2CipherString(cs_int);
  1.1132 +	  PR_fprintf(PR_STDOUT,"            cipher_suite = (0x%04x) %s\n",
  1.1133 +		     cs_int, cs_str);
  1.1134 +	  currentcipher = cs_int;
  1.1135 +	  pos += 2;
  1.1136 +	}
  1.1137 +	/* pretty print chosen compression method */
  1.1138 +	{
  1.1139 +	  PRUint32 cm_int    = hsdata[pos++];
  1.1140 +	  const char *cm_str = CompressionMethodString(cm_int);
  1.1141 +	  PR_fprintf(PR_STDOUT,"            compression method = (%02x) %s\n",
  1.1142 +		     cm_int, cm_str);
  1.1143 +	}
  1.1144 +
  1.1145 +	/* pretty print extensions, if any */
  1.1146 +	pos = print_hello_extension(hsdata, sslh.length, pos);
  1.1147 +
  1.1148 +	PR_fprintf(PR_STDOUT,"         }\n");
  1.1149 +      }
  1.1150 +      break;
  1.1151 +
  1.1152 +    case 4: /* new session ticket */
  1.1153 +      {
  1.1154 +	PRUint32 lifetimehint;
  1.1155 +	PRUint16 ticketlength;
  1.1156 +	char lifetime[32];
  1.1157 +	lifetimehint = GET_32(hsdata);
  1.1158 +	if (lifetimehint) {
  1.1159 +	  PRExplodedTime et;
  1.1160 +	  PRTime t = lifetimehint;
  1.1161 +	  t *= PR_USEC_PER_SEC;
  1.1162 +	  PR_ExplodeTime(t, PR_GMTParameters, &et);
  1.1163 +	  /* use HTTP Cookie header's date format */
  1.1164 +	  PR_FormatTimeUSEnglish(lifetime, sizeof lifetime,
  1.1165 +				 "%a, %d-%b-%Y %H:%M:%S GMT", &et);
  1.1166 +	} else {
  1.1167 +	  /* 0 means the lifetime of the ticket is unspecified */
  1.1168 +	  strcpy(lifetime, "unspecified");
  1.1169 +	}
  1.1170 +	ticketlength = GET_SHORT((hsdata+4));
  1.1171 +	PR_fprintf(PR_STDOUT,"         NewSessionTicket {\n");
  1.1172 +	PR_fprintf(PR_STDOUT,"            ticket_lifetime_hint = %s\n",
  1.1173 +		   lifetime);
  1.1174 +	PR_fprintf(PR_STDOUT,"            ticket = {\n");
  1.1175 +	PR_fprintf(PR_STDOUT,"                length = %d\n",ticketlength);
  1.1176 +	PR_fprintf(PR_STDOUT,"                contents = {...}\n");
  1.1177 +	if (sslhexparse) print_hex(ticketlength,&hsdata[4+2]);
  1.1178 +	PR_fprintf(PR_STDOUT,"            }\n");
  1.1179 +	PR_fprintf(PR_STDOUT,"         }\n");
  1.1180 +      }
  1.1181 +      break;
  1.1182 +
  1.1183 +    case 11: /* certificate */
  1.1184 +      {
  1.1185 +	PRFileDesc *cfd;
  1.1186 +	int         pos;
  1.1187 +	int         certslength;
  1.1188 +	int         certlength;
  1.1189 +	int         certbytesread	= 0;
  1.1190 +	static int  certFileNumber;
  1.1191 +	char        certFileName[20];
  1.1192 +
  1.1193 +	PR_fprintf(PR_STDOUT,"         CertificateChain {\n");
  1.1194 +	certslength = GET_24(hsdata);
  1.1195 +	PR_fprintf(PR_STDOUT,"            chainlength = %d (0x%04x)\n",
  1.1196 +		certslength,certslength);
  1.1197 +	pos = 3;
  1.1198 +	while (certbytesread < certslength) {
  1.1199 +	  certlength = GET_24((hsdata+pos));
  1.1200 +	  pos += 3;
  1.1201 +	  PR_fprintf(PR_STDOUT,"            Certificate {\n");
  1.1202 +	  PR_fprintf(PR_STDOUT,"               size = %d (0x%04x)\n",
  1.1203 +		certlength,certlength);
  1.1204 +	  certbytesread += certlength+3;
  1.1205 +	  if (certbytesread <= certslength) {
  1.1206 +	    PR_snprintf(certFileName, sizeof certFileName, "cert.%03d",
  1.1207 +			++certFileNumber);
  1.1208 +	    cfd = PR_Open(certFileName, PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE, 
  1.1209 +			  0664);
  1.1210 +	    if (!cfd) {
  1.1211 +	      PR_fprintf(PR_STDOUT,
  1.1212 +			 "               data = { couldn't save file '%s' }\n",
  1.1213 +			 certFileName);
  1.1214 +	    } else {
  1.1215 +	      PR_Write(cfd, (hsdata+pos), certlength);
  1.1216 +	      PR_fprintf(PR_STDOUT,
  1.1217 +			 "               data = { saved in file '%s' }\n",
  1.1218 +			 certFileName);
  1.1219 +	      PR_Close(cfd);
  1.1220 +	    }
  1.1221 +	  }
  1.1222 +
  1.1223 +	  PR_fprintf(PR_STDOUT,"            }\n");
  1.1224 +	  pos           += certlength;
  1.1225 +	}
  1.1226 +	PR_fprintf(PR_STDOUT,"         }\n");
  1.1227 +      }
  1.1228 +      break;
  1.1229 +
  1.1230 +    case 12: /* server_key_exchange */                    
  1.1231 +      if (sslhexparse) print_hex(sslh.length, hsdata);
  1.1232 +      break;
  1.1233 +
  1.1234 +    case 13: /* certificate request */
  1.1235 +      { 
  1.1236 +	unsigned int pos = 0;
  1.1237 +	int w, reqLength;
  1.1238 +
  1.1239 +	PR_fprintf(PR_STDOUT,"         CertificateRequest {\n");
  1.1240 +
  1.1241 +	/* pretty print requested certificate types */
  1.1242 +	reqLength = hsdata[pos];
  1.1243 +	PR_fprintf(PR_STDOUT,"            certificate types[%d] = {",
  1.1244 +		   reqLength);
  1.1245 +	for (w=0; w < reqLength; w++) {
  1.1246 +	  PR_fprintf(PR_STDOUT, " %02x", hsdata[pos+1+w]);
  1.1247 +	}
  1.1248 +	pos += 1 + reqLength;
  1.1249 +	PR_fprintf(PR_STDOUT," }\n");
  1.1250 +
  1.1251 +	/* pretty print CA names, if any */
  1.1252 +	if (pos < sslh.length) {
  1.1253 +	  int exListLen = GET_SHORT((hsdata+pos)); pos += 2;
  1.1254 +	  PR_fprintf(PR_STDOUT,
  1.1255 +		     "            certificate_authorities[%d] = {\n", 
  1.1256 +		     exListLen);
  1.1257 +	  while (exListLen > 0 && pos < sslh.length) {
  1.1258 +	    char *  ca_name;
  1.1259 +	    SECItem it;
  1.1260 +	    int     dnLen = GET_SHORT((hsdata+pos)); pos += 2;
  1.1261 +
  1.1262 +	    /* dump the CA name */
  1.1263 +	    it.type = siBuffer;
  1.1264 +	    it.data = hsdata + pos;
  1.1265 +	    it.len  = dnLen;
  1.1266 +	    ca_name = CERT_DerNameToAscii(&it);
  1.1267 +	    if (ca_name) {
  1.1268 +	      PR_fprintf(PR_STDOUT,"   %s\n", ca_name);
  1.1269 +	      PORT_Free(ca_name);
  1.1270 +	    } else {
  1.1271 +	      PR_fprintf(PR_STDOUT,
  1.1272 +			 "              distinguished name [%d]", dnLen);
  1.1273 +	      if (dnLen > 0 && sslhexparse) {
  1.1274 +		  PR_fprintf(PR_STDOUT, " = {\n");
  1.1275 +		  print_hex(dnLen, hsdata + pos);
  1.1276 +		  PR_fprintf(PR_STDOUT, "              }\n");
  1.1277 +	      } else {
  1.1278 +		  PR_fprintf(PR_STDOUT, "\n");
  1.1279 +	      }
  1.1280 +            }
  1.1281 +	    pos += dnLen;
  1.1282 +	    exListLen -= 2 + dnLen;
  1.1283 +	  }
  1.1284 +	  PR_fprintf(PR_STDOUT,"            }\n");
  1.1285 +	}
  1.1286 +
  1.1287 +	PR_fprintf(PR_STDOUT,"         }\n");
  1.1288 +      }
  1.1289 +      break;
  1.1290 +
  1.1291 +    case 14: /* server_hello_done */ /* not much to show here. */ break;
  1.1292 +
  1.1293 +    case 15: /* certificate_verify */	           
  1.1294 +      if (sslhexparse) print_hex(sslh.length, hsdata);
  1.1295 +      break;
  1.1296 +
  1.1297 +    case 16: /* client key exchange */
  1.1298 +      {
  1.1299 +	PR_fprintf(PR_STDOUT,"         ClientKeyExchange {\n");
  1.1300 +	PR_fprintf(PR_STDOUT,"            message = {...}\n");
  1.1301 +	PR_fprintf(PR_STDOUT,"         }\n");
  1.1302 +      }
  1.1303 +      break;
  1.1304 +
  1.1305 +    case 20: /* finished */			 
  1.1306 +      PR_fprintf(PR_STDOUT,"         Finished {\n");
  1.1307 +      PR_fprintf(PR_STDOUT,"            verify_data = {...}\n");
  1.1308 +      if (sslhexparse) print_hex(sslh.length, hsdata);
  1.1309 +      PR_fprintf(PR_STDOUT,"         }\n");
  1.1310 +
  1.1311 +      if (!isNULLmac(currentcipher) && !s->hMACsize) {
  1.1312 +          /* To calculate the size of MAC, we subtract the number of known 
  1.1313 +	   * bytes of message from the number of remaining bytes in the 
  1.1314 +	   * record. This assumes that this is the first record on the 
  1.1315 +	   * connection to have a MAC, and that the sender has not put another 
  1.1316 +	   * message after the finished message in the handshake record. 
  1.1317 +	   * This is only correct for the first transition from unMACed to 
  1.1318 +	   * MACed. If the connection switches from one cipher suite to 
  1.1319 +	   * another one with a different MAC, this logic will not track that 
  1.1320 +	   * change correctly.
  1.1321 +	   */
  1.1322 +          s->hMACsize = recordLen - (sslh.length + 4);
  1.1323 +	  sslh.length += s->hMACsize;  /* skip over the MAC data */
  1.1324 +      }
  1.1325 +      break;
  1.1326 +
  1.1327 +    case 22: /* certificate_status */
  1.1328 +      {
  1.1329 +        SECItem data;
  1.1330 +        PRFileDesc *ofd;
  1.1331 +        static int  ocspFileNumber;
  1.1332 +        char        ocspFileName[20];
  1.1333 +
  1.1334 +        /* skip 4 bytes with handshake numbers, as in ssl3_HandleCertificateStatus */
  1.1335 +        data.type = siBuffer;
  1.1336 +        data.data = hsdata + 4;
  1.1337 +        data.len = sslh.length - 4;
  1.1338 +        print_status_response(&data);
  1.1339 +
  1.1340 +        PR_snprintf(ocspFileName, sizeof ocspFileName, "ocsp.%03d",
  1.1341 +                    ++ocspFileNumber);
  1.1342 +        ofd = PR_Open(ocspFileName, PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE, 
  1.1343 +                      0664);
  1.1344 +        if (!ofd) {
  1.1345 +          PR_fprintf(PR_STDOUT,
  1.1346 +                      "               data = { couldn't save file '%s' }\n",
  1.1347 +                      ocspFileName);
  1.1348 +        } else {
  1.1349 +          PR_Write(ofd, data.data, data.len);
  1.1350 +          PR_fprintf(PR_STDOUT,
  1.1351 +                      "               data = { saved in file '%s' }\n",
  1.1352 +                      ocspFileName);
  1.1353 +          PR_Close(ofd);
  1.1354 +        }
  1.1355 +      }
  1.1356 +      break;
  1.1357 +
  1.1358 +    default:
  1.1359 +      {
  1.1360 +	PR_fprintf(PR_STDOUT,"         UNKNOWN MESSAGE TYPE %d [%d] {\n",
  1.1361 +	                     sslh.type, sslh.length);
  1.1362 +	if (sslhexparse) print_hex(sslh.length, hsdata);
  1.1363 +	PR_fprintf(PR_STDOUT,"         }\n");
  1.1364 +
  1.1365 +      }
  1.1366 +    }  /* end of switch sslh.type */
  1.1367 +    offset += sslh.length + 4; 
  1.1368 +  } /* while */
  1.1369 +  if (offset < recordLen) { /* stuff left over */
  1.1370 +    int newMsgLen = recordLen - offset;
  1.1371 +    if (!s->msgBuf) {
  1.1372 +      s->msgBuf = PORT_Alloc(newMsgLen);
  1.1373 +      if (!s->msgBuf) {
  1.1374 +	PR_ASSERT(s->msgBuf);
  1.1375 +	showErr( "Malloc failed");
  1.1376 +        exit(11);
  1.1377 +      }
  1.1378 +      s->msgBufSize = newMsgLen;
  1.1379 +      memcpy(s->msgBuf, recordBuf + offset, newMsgLen);
  1.1380 +    } else if (newMsgLen > s->msgBufSize) {
  1.1381 +      unsigned char * newBuf = PORT_Realloc(s->msgBuf, newMsgLen);
  1.1382 +      if (!newBuf) {
  1.1383 +	PR_ASSERT(newBuf);
  1.1384 +	showErr( "Realloc failed");
  1.1385 +        exit(12);
  1.1386 +      }
  1.1387 +      s->msgBuf = newBuf;
  1.1388 +      s->msgBufSize = newMsgLen;
  1.1389 +    } else if (offset || s->msgBuf != recordBuf) {
  1.1390 +      memmove(s->msgBuf, recordBuf + offset, newMsgLen);
  1.1391 +    }
  1.1392 +    s->msgBufOffset = newMsgLen;
  1.1393 +    PR_fprintf(PR_STDOUT,"     [incomplete handshake message]\n");
  1.1394 +  } else {
  1.1395 +    s->msgBufOffset = 0;
  1.1396 +  }
  1.1397 +  PR_fprintf(PR_STDOUT,"   }\n");
  1.1398 +}
  1.1399 +
  1.1400 +
  1.1401 +void print_ssl(DataBufferList *s, int length, unsigned char *buffer)
  1.1402 +{
  1.1403 +  /* --------------------------------------------------------  */
  1.1404 +  /* first, create a new buffer object for this piece of data. */
  1.1405 +
  1.1406 +  DataBuffer *db;
  1.1407 +
  1.1408 +  if (s->size == 0 && length > 0 && buffer[0] >= 32 && buffer[0] < 128) {
  1.1409 +    /* Not an SSL record, treat entire buffer as plaintext */
  1.1410 +    PR_Write(PR_STDOUT,buffer,length);
  1.1411 +    return;
  1.1412 +  }
  1.1413 +
  1.1414 +  check_integrity(s);
  1.1415 +
  1.1416 +  db = PR_NEW(struct _DataBuffer);
  1.1417 +
  1.1418 +  db->buffer = (unsigned char*)PORT_Alloc(length);
  1.1419 +  db->length = length;
  1.1420 +  db->offset = 0;
  1.1421 +  memcpy(db->buffer, buffer, length);
  1.1422 +  db->next = NULL;
  1.1423 +
  1.1424 +  /* now, add it to the stream */
  1.1425 +
  1.1426 +  if (s->last != NULL) s->last->next = db;
  1.1427 +  s->last = db;
  1.1428 +  s->size += length;
  1.1429 +  if (s->first == NULL) s->first = db;
  1.1430 +
  1.1431 +  check_integrity(s);
  1.1432 +
  1.1433 +  /*------------------------------------------------------- */
  1.1434 +  /* now we look at the stream to see if we have enough data to
  1.1435 +     decode  */
  1.1436 +
  1.1437 +  while (s->size > 0 ) {
  1.1438 +    unsigned char *recordBuf = NULL;
  1.1439 +
  1.1440 +    SSLRecord sr;
  1.1441 +    unsigned recordLen;
  1.1442 +    unsigned recordsize;
  1.1443 +
  1.1444 +    check_integrity(s);
  1.1445 +
  1.1446 +    if ( s->first == NULL) {
  1.1447 +      PR_fprintf(PR_STDOUT,"ERROR: s->first is null\n");
  1.1448 +      exit(9);
  1.1449 +    }
  1.1450 +
  1.1451 +    /* in the case of an SSL 2 client-hello  */
  1.1452 +    /* will have the high-bit set, whereas an SSL 3 client-hello will not  */
  1.1453 +    /* SSL2 can also send records that begin with the high bit clear.
  1.1454 +     * This code will incorrectly handle them. XXX
  1.1455 +     */
  1.1456 +    if (isV2Session || s->first->buffer[s->first->offset] & 0x80) {
  1.1457 +      /* it's an SSL 2 packet */
  1.1458 +      unsigned char lenbuf[3];
  1.1459 +
  1.1460 +      /* first, we check if there's enough data for it to be an SSL2-type
  1.1461 +       * record.  What a pain.*/
  1.1462 +      if (s->size < sizeof lenbuf) {
  1.1463 +	partial_packet(length, s->size, sizeof lenbuf);
  1.1464 +	return;
  1.1465 +      }
  1.1466 +
  1.1467 +      /* read the first two bytes off the stream. */
  1.1468 +      read_stream_bytes(lenbuf, s, sizeof(lenbuf));
  1.1469 +      recordLen = ((unsigned int)(lenbuf[0] & 0x7f) << 8) + lenbuf[1] + 
  1.1470 +                 ((lenbuf[0] & 0x80) ? 2 : 3);
  1.1471 +      PR_fprintf(PR_STDOUT, "recordLen = %u bytes\n", recordLen);
  1.1472 +
  1.1473 +      /* put 'em back on the head of the stream. */
  1.1474 +      db = PR_NEW(struct _DataBuffer);
  1.1475 +
  1.1476 +      db->length = sizeof lenbuf;
  1.1477 +      db->buffer = (unsigned char*) PORT_Alloc(db->length);
  1.1478 +      db->offset = 0;
  1.1479 +      memcpy(db->buffer, lenbuf, sizeof lenbuf);
  1.1480 +
  1.1481 +      db->next = s->first;
  1.1482 +      s->first = db;
  1.1483 +      if (s->last == NULL) 
  1.1484 +	s->last = db;
  1.1485 +      s->size += db->length;
  1.1486 +
  1.1487 +      /* if there wasn't enough, go back for more. */
  1.1488 +      if (s->size < recordLen) {
  1.1489 +	check_integrity(s);
  1.1490 +	partial_packet(length, s->size, recordLen);
  1.1491 +	return;
  1.1492 +      }
  1.1493 +      partial_packet(length, s->size, recordLen);
  1.1494 +
  1.1495 +      /* read in the whole record. */
  1.1496 +      recordBuf = PORT_Alloc(recordLen);
  1.1497 +      read_stream_bytes(recordBuf, s, recordLen);
  1.1498 +
  1.1499 +      print_sslv2(s, recordBuf, recordLen);
  1.1500 +      PR_FREEIF(recordBuf);
  1.1501 +      check_integrity(s);
  1.1502 +
  1.1503 +      continue;
  1.1504 +    }
  1.1505 +
  1.1506 +    /***********************************************************/
  1.1507 +    /* It's SSL v3 */
  1.1508 +    /***********************************************************/
  1.1509 +    check_integrity(s);
  1.1510 +
  1.1511 +    if (s->size < sizeof sr) {
  1.1512 +      partial_packet(length, s->size, sizeof(SSLRecord));
  1.1513 +      return;
  1.1514 +    }
  1.1515 +
  1.1516 +    read_stream_bytes((unsigned char *)&sr, s, sizeof sr);
  1.1517 +
  1.1518 +    /* we have read the stream bytes. Look at the length of
  1.1519 +       the ssl record. If we don't have enough data to satisfy this
  1.1520 +       request, then put the bytes we just took back at the head
  1.1521 +       of the queue */
  1.1522 +    recordsize = GET_SHORT(sr.length);
  1.1523 +
  1.1524 +    if (recordsize > s->size) {
  1.1525 +      db = PR_NEW(struct _DataBuffer);
  1.1526 +
  1.1527 +      db->length = sizeof sr;
  1.1528 +      db->buffer = (unsigned char*) PORT_Alloc(db->length);
  1.1529 +      db->offset = 0;
  1.1530 +      memcpy(db->buffer, &sr, sizeof sr);
  1.1531 +      db->next = s->first;
  1.1532 +
  1.1533 +      /* now, add it back on to the head of the stream */
  1.1534 +
  1.1535 +      s->first = db;
  1.1536 +      if (s->last == NULL) 
  1.1537 +        s->last = db;
  1.1538 +      s->size += db->length;
  1.1539 +
  1.1540 +      check_integrity(s);
  1.1541 +      partial_packet(length, s->size, recordsize);
  1.1542 +      return;
  1.1543 +    }
  1.1544 +    partial_packet(length, s->size, recordsize);
  1.1545 +
  1.1546 +
  1.1547 +    PR_fprintf(PR_STDOUT,"SSLRecord { [%s]\n", get_time_string() );
  1.1548 +    if (sslhexparse) {
  1.1549 +      print_hex(5,(unsigned char*)&sr);
  1.1550 +    }
  1.1551 +
  1.1552 +    check_integrity(s);
  1.1553 +
  1.1554 +    PR_fprintf(PR_STDOUT,"   type    = %d (",sr.type);
  1.1555 +    switch(sr.type) {
  1.1556 +    case 20 :
  1.1557 +      PR_fprintf(PR_STDOUT,"change_cipher_spec)\n");
  1.1558 +      break;
  1.1559 +    case 21 :
  1.1560 +      PR_fprintf(PR_STDOUT,"alert)\n");
  1.1561 +      break;
  1.1562 +    case 22 :
  1.1563 +      PR_fprintf(PR_STDOUT,"handshake)\n");
  1.1564 +      break;
  1.1565 +    case 23 :
  1.1566 +      PR_fprintf(PR_STDOUT,"application_data)\n");
  1.1567 +      break;
  1.1568 +    default:
  1.1569 +      PR_fprintf(PR_STDOUT,"unknown)\n");
  1.1570 +      break;
  1.1571 +    }
  1.1572 +    PR_fprintf(PR_STDOUT,"   version = { %d,%d }\n",
  1.1573 +	       (PRUint32)sr.ver_maj,(PRUint32)sr.ver_min);
  1.1574 +    PR_fprintf(PR_STDOUT,"   length  = %d (0x%x)\n",
  1.1575 +    	(PRUint32)GET_SHORT(sr.length), (PRUint32)GET_SHORT(sr.length));
  1.1576 +
  1.1577 +
  1.1578 +    recordLen = recordsize;
  1.1579 +    PR_ASSERT(s->size >= recordLen);
  1.1580 +    if (s->size >= recordLen) {
  1.1581 +      recordBuf = (unsigned char*) PORT_Alloc(recordLen);
  1.1582 +      read_stream_bytes(recordBuf, s, recordLen);
  1.1583 +
  1.1584 +      if (s->isEncrypted) {
  1.1585 +	PR_fprintf(PR_STDOUT,"            < encrypted >\n");
  1.1586 +      } else { /* not encrypted */
  1.1587 +
  1.1588 +      switch(sr.type) {
  1.1589 +      case 20 : /* change_cipher_spec */
  1.1590 +	if (sslhexparse) print_hex(recordLen - s->hMACsize,recordBuf);
  1.1591 +         /* mark to say we can only dump hex form now on
  1.1592 +          * if it is not one on a null cipher */
  1.1593 +	s->isEncrypted = isNULLcipher(currentcipher) ? 0 : 1; 
  1.1594 +	break;
  1.1595 +
  1.1596 +      case 21 : /* alert */
  1.1597 +	switch(recordBuf[0]) {
  1.1598 +	case 1: PR_fprintf(PR_STDOUT, "   warning: "); break;
  1.1599 +	case 2: PR_fprintf(PR_STDOUT, "   fatal: "); break;
  1.1600 +	default: PR_fprintf(PR_STDOUT, "   unknown level %d: ", recordBuf[0]); break;
  1.1601 +	}
  1.1602 +
  1.1603 +	switch(recordBuf[1]) {
  1.1604 +	case 0:   PR_FPUTS("close_notify\n"                    ); break;
  1.1605 +	case 10:  PR_FPUTS("unexpected_message\n"              ); break;
  1.1606 +	case 20:  PR_FPUTS("bad_record_mac\n"                  ); break;
  1.1607 +	case 21:  PR_FPUTS("decryption_failed\n"               ); break;
  1.1608 +	case 22:  PR_FPUTS("record_overflow\n"                 ); break;
  1.1609 +	case 30:  PR_FPUTS("decompression_failure\n"           ); break;
  1.1610 +	case 40:  PR_FPUTS("handshake_failure\n"               ); break;
  1.1611 +	case 41:  PR_FPUTS("no_certificate\n"                  ); break;
  1.1612 +	case 42:  PR_FPUTS("bad_certificate\n"                 ); break;
  1.1613 +	case 43:  PR_FPUTS("unsupported_certificate\n"         ); break;
  1.1614 +	case 44:  PR_FPUTS("certificate_revoked\n"             ); break;
  1.1615 +	case 45:  PR_FPUTS("certificate_expired\n"             ); break;
  1.1616 +	case 46:  PR_FPUTS("certificate_unknown\n"             ); break;
  1.1617 +	case 47:  PR_FPUTS("illegal_parameter\n"               ); break;
  1.1618 +	case 48:  PR_FPUTS("unknown_ca\n"                      ); break;
  1.1619 +	case 49:  PR_FPUTS("access_denied\n"                   ); break;
  1.1620 +	case 50:  PR_FPUTS("decode_error\n"                    ); break;
  1.1621 +	case 51:  PR_FPUTS("decrypt_error\n"                   ); break;
  1.1622 +	case 60:  PR_FPUTS("export_restriction\n"              ); break;
  1.1623 +	case 70:  PR_FPUTS("protocol_version\n"                ); break;
  1.1624 +	case 71:  PR_FPUTS("insufficient_security\n"           ); break;
  1.1625 +	case 80:  PR_FPUTS("internal_error\n"                  ); break;
  1.1626 +	case 90:  PR_FPUTS("user_canceled\n"                   ); break;
  1.1627 +	case 100: PR_FPUTS("no_renegotiation\n"                ); break;
  1.1628 +	case 110: PR_FPUTS("unsupported_extension\n"           ); break;
  1.1629 +	case 111: PR_FPUTS("certificate_unobtainable\n"        ); break;
  1.1630 +	case 112: PR_FPUTS("unrecognized_name\n"               ); break;
  1.1631 +	case 113: PR_FPUTS("bad_certificate_status_response\n" ); break;
  1.1632 +	case 114: PR_FPUTS("bad_certificate_hash_value\n"      ); break;
  1.1633 +
  1.1634 +	default: PR_fprintf(PR_STDOUT, "unknown alert %d\n", recordBuf[1]); 
  1.1635 +	         break;
  1.1636 +	}
  1.1637 +
  1.1638 +	if (sslhexparse) print_hex(recordLen - s->hMACsize,recordBuf);
  1.1639 +	break;
  1.1640 +
  1.1641 +      case 22 : /* handshake */ 	
  1.1642 +        print_ssl3_handshake( recordBuf, recordLen - s->hMACsize, &sr, s );
  1.1643 +	break;
  1.1644 +
  1.1645 +      case 23 : /* application data */
  1.1646 +	 print_hex(recordLen - s->hMACsize,recordBuf);
  1.1647 +         break;
  1.1648 +
  1.1649 +      default:
  1.1650 +	print_hex(recordLen - s->hMACsize,recordBuf);
  1.1651 +	break;
  1.1652 +      }
  1.1653 +      if (s->hMACsize) {
  1.1654 +	  PR_fprintf(PR_STDOUT,"      MAC = {...}\n");
  1.1655 +	  if (sslhexparse) {
  1.1656 +	      unsigned char *offset = recordBuf + (recordLen - s->hMACsize);
  1.1657 +	      print_hex(s->hMACsize, offset);
  1.1658 +	  }
  1.1659 +      }
  1.1660 +     } /* not encrypted */
  1.1661 +    }
  1.1662 +    PR_fprintf(PR_STDOUT,"}\n");
  1.1663 +    PR_FREEIF(recordBuf);
  1.1664 +    check_integrity(s);
  1.1665 +  }
  1.1666 +}
  1.1667 +
  1.1668 +void print_hex(int amt, unsigned char *buf) 
  1.1669 +{
  1.1670 +  int i,j,k;
  1.1671 +  char t[20];
  1.1672 +  static char string[5000];
  1.1673 +
  1.1674 +
  1.1675 +  for(i=0;i<amt;i++) {
  1.1676 +    t[1] =0;
  1.1677 +
  1.1678 +    if (i%16 ==0) {  /* if we are at the beginning of a line */
  1.1679 +      PR_fprintf(PR_STDOUT,"%4x:",i); /* print the line number  */
  1.1680 +      strcpy(string,"");
  1.1681 +    }
  1.1682 +
  1.1683 +    if (i%4 == 0) {
  1.1684 +      PR_fprintf(PR_STDOUT," ");
  1.1685 +    }
  1.1686 +
  1.1687 +    j = buf[i];
  1.1688 +
  1.1689 +    t[0] = (j >= 0x20 && j < 0x80) ? j : '.';
  1.1690 +
  1.1691 +    if (fancy)  {
  1.1692 +      switch (t[0]) {
  1.1693 +      case '<':
  1.1694 +        strcpy(t,"&lt;");
  1.1695 +        break;
  1.1696 +      case '>':
  1.1697 +        strcpy(t,"&gt;");
  1.1698 +        break;
  1.1699 +      case '&':
  1.1700 +        strcpy(t,"&amp;");
  1.1701 +        break;
  1.1702 +      }
  1.1703 +    }
  1.1704 +    strcat(string,t);
  1.1705 +
  1.1706 +    PR_fprintf(PR_STDOUT,"%02x ",(PRUint8) buf[i]);
  1.1707 +
  1.1708 +    /* if we've reached the end of the line - add the string */
  1.1709 +    if (i%16 == 15) PR_fprintf(PR_STDOUT," | %s\n",string);
  1.1710 +  }
  1.1711 +  /* we reached the end of the buffer,*/
  1.1712 +  /* do we have buffer left over? */
  1.1713 +  j = i%16;
  1.1714 +  if (j > 0) {
  1.1715 +    for (k=0;k<(16-j);k++) {
  1.1716 +        /* print additional space after every four bytes */
  1.1717 +        if ((k + j)%4 == 0) {
  1.1718 +            PR_fprintf(PR_STDOUT," ");
  1.1719 +        }
  1.1720 +        PR_fprintf(PR_STDOUT,"   ");
  1.1721 +    }
  1.1722 +    PR_fprintf(PR_STDOUT," | %s\n",string);
  1.1723 +  }
  1.1724 +}
  1.1725 +
  1.1726 +void Usage(void) 
  1.1727 +{
  1.1728 +  PR_fprintf(PR_STDERR, "SSLTAP (C) 1997, 1998 Netscape Communications Corporation.\n");
  1.1729 +  PR_fprintf(PR_STDERR, "Usage: ssltap [-vhfsxl] [-p port] hostname:port\n");
  1.1730 +  PR_fprintf(PR_STDERR, "   -v      [prints version string]\n");
  1.1731 +  PR_fprintf(PR_STDERR, "   -h      [outputs hex instead of ASCII]\n");
  1.1732 +  PR_fprintf(PR_STDERR, "   -f      [turn on Fancy HTML coloring]\n");
  1.1733 +  PR_fprintf(PR_STDERR, "   -s      [turn on SSL decoding]\n");
  1.1734 +  PR_fprintf(PR_STDERR, "   -x      [turn on extra SSL hex dumps]\n");
  1.1735 +  PR_fprintf(PR_STDERR, "   -p port [specify rendezvous port (default 1924)]\n");
  1.1736 +  PR_fprintf(PR_STDERR, "   -l      [loop - continue to wait for more connections]\n");
  1.1737 +
  1.1738 +
  1.1739 +}
  1.1740 +
  1.1741 +void
  1.1742 +showErr(const char * msg) 
  1.1743 +{
  1.1744 +  PRErrorCode  err       = PR_GetError();
  1.1745 +  const char * errString;
  1.1746 +
  1.1747 +  if (err == PR_UNKNOWN_ERROR)
  1.1748 +    err = PR_CONNECT_RESET_ERROR;	/* bug in NSPR. */
  1.1749 +  errString = SECU_Strerror(err);
  1.1750 +
  1.1751 +  if (!errString)
  1.1752 +    errString = "(no text available)";
  1.1753 +  PR_fprintf(PR_STDERR, "%s: Error %d: %s: %s", progName, err, errString, msg);
  1.1754 +}
  1.1755 +
  1.1756 +int main(int argc,  char *argv[])
  1.1757 +{
  1.1758 +  char *hostname=NULL;
  1.1759 +  PRUint16 rendport=DEFPORT,port;
  1.1760 +  PRAddrInfo *ai;
  1.1761 +  void *iter;
  1.1762 +  PRStatus r;
  1.1763 +  PRNetAddr na_client,na_server,na_rend;
  1.1764 +  PRFileDesc *s_server,*s_client,*s_rend; /*rendezvous */
  1.1765 +  int c_count=0;
  1.1766 +  PLOptState *optstate;
  1.1767 +  PLOptStatus status;
  1.1768 +  SECStatus   rv;
  1.1769 +
  1.1770 +  progName = argv[0];
  1.1771 +  optstate = PL_CreateOptState(argc,argv,"fxhslp:");
  1.1772 +    while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
  1.1773 +    switch (optstate->option) {
  1.1774 +    case 'f':
  1.1775 +      fancy++;
  1.1776 +      break;
  1.1777 +    case 'h':
  1.1778 +      hexparse++;
  1.1779 +      break;
  1.1780 +    case 's':
  1.1781 +      sslparse++;
  1.1782 +      break;
  1.1783 +    case 'x':
  1.1784 +      sslhexparse++;
  1.1785 +      break;
  1.1786 +    case 'l':
  1.1787 +      looparound++;
  1.1788 +      break;
  1.1789 +    case 'p':
  1.1790 +      rendport = atoi(optstate->value);
  1.1791 +      break;
  1.1792 +    case '\0':
  1.1793 +      hostname = PL_strdup(optstate->value);
  1.1794 +    }
  1.1795 +  }
  1.1796 +  if (status == PL_OPT_BAD)
  1.1797 +    Usage();
  1.1798 +
  1.1799 +  if (fancy) {
  1.1800 +    if (!hexparse && !sslparse) {
  1.1801 +      PR_fprintf(PR_STDERR,
  1.1802 +"Note: use of -f without -s or -h not recommended, \n"
  1.1803 +"as the output looks a little strange. It may be useful, however\n");
  1.1804 +    }
  1.1805 +  }
  1.1806 +
  1.1807 +  if(! hostname ) Usage(), exit(2);
  1.1808 +
  1.1809 +  {
  1.1810 +    char *colon = (char *)strchr(hostname, ':');
  1.1811 +    if (!colon) {
  1.1812 +      PR_fprintf(PR_STDERR,
  1.1813 +      "You must specify the host AND port you wish to connect to\n");
  1.1814 +      Usage(), exit(3);
  1.1815 +    }
  1.1816 +    port = atoi(&colon[1]);
  1.1817 +    *colon = '\0';
  1.1818 +
  1.1819 +    if (port == 0) {
  1.1820 +	PR_fprintf(PR_STDERR, "Port must be a nonzero number.\n");
  1.1821 +	exit(4);
  1.1822 +      }
  1.1823 +  }
  1.1824 +
  1.1825 +  /* find the 'server' IP address so we don't have to look it up later */
  1.1826 +
  1.1827 +  if (fancy) {
  1.1828 +      PR_fprintf(PR_STDOUT,"<HTML><HEAD><TITLE>SSLTAP output</TITLE></HEAD>\n");
  1.1829 +      PR_fprintf(PR_STDOUT,"<BODY><PRE>\n");
  1.1830 +    }
  1.1831 +  PR_fprintf(PR_STDERR,"Looking up \"%s\"...\n", hostname);
  1.1832 +  ai = PR_GetAddrInfoByName(hostname, PR_AF_UNSPEC, PR_AI_ADDRCONFIG);
  1.1833 +  if (!ai) {
  1.1834 +    showErr("Host Name lookup failed\n");
  1.1835 +    exit(5);
  1.1836 +  }
  1.1837 +
  1.1838 +  iter = NULL;
  1.1839 +  iter = PR_EnumerateAddrInfo(iter, ai, port, &na_server);
  1.1840 +  /* set up the port which the client will connect to */
  1.1841 +
  1.1842 +  r = PR_InitializeNetAddr(PR_IpAddrAny,rendport,&na_rend);
  1.1843 +  if (r == PR_FAILURE) {
  1.1844 +    PR_fprintf(PR_STDERR,
  1.1845 +    "PR_InitializeNetAddr(,%d,) failed with error %d\n",PR_GetError());
  1.1846 +    exit(0);
  1.1847 +  }
  1.1848 +
  1.1849 +  rv = NSS_NoDB_Init("");
  1.1850 +  if (rv != SECSuccess) {
  1.1851 +    PR_fprintf(PR_STDERR,
  1.1852 +    "NSS_NoDB_Init() failed with error %d\n",PR_GetError());
  1.1853 +    exit(5);
  1.1854 +  }
  1.1855 +
  1.1856 +  s_rend = PR_NewTCPSocket();
  1.1857 +  if (!s_rend) {
  1.1858 +    showErr("Couldn't create socket\n");
  1.1859 +    exit(6);
  1.1860 +  }
  1.1861 +
  1.1862 +  if (PR_Bind(s_rend, &na_rend )) {
  1.1863 +    PR_fprintf(PR_STDERR,"Couldn't bind to port %d (error %d)\n",rendport, PR_GetError());
  1.1864 +    exit(-1);
  1.1865 +  }
  1.1866 +
  1.1867 +  if ( PR_Listen(s_rend, 5)) {
  1.1868 +    showErr("Couldn't listen\n");
  1.1869 +    exit(-1);
  1.1870 +  }
  1.1871 +
  1.1872 +  PR_fprintf(PR_STDERR,"Proxy socket ready and listening\n");
  1.1873 +  do {	/* accept one connection and process it. */
  1.1874 +      PRPollDesc pds[2];
  1.1875 +
  1.1876 +      s_client = PR_Accept(s_rend,&na_client,PR_SecondsToInterval(3600));
  1.1877 +      if (s_client == NULL) {
  1.1878 +	showErr("accept timed out\n");
  1.1879 +	exit(7);
  1.1880 +      }
  1.1881 +
  1.1882 +      s_server = PR_OpenTCPSocket(na_server.raw.family);
  1.1883 +      if (s_server == NULL) {
  1.1884 +	showErr("couldn't open new socket to connect to server \n");
  1.1885 +	exit(8);
  1.1886 +      }
  1.1887 +
  1.1888 +      r = PR_Connect(s_server,&na_server,PR_SecondsToInterval(5));
  1.1889 +
  1.1890 +      if ( r == PR_FAILURE )
  1.1891 +        {
  1.1892 +	  showErr("Couldn't connect\n");
  1.1893 +	  return -1;
  1.1894 +        }
  1.1895 +
  1.1896 +      if (looparound) {
  1.1897 +	if (fancy)  PR_fprintf(PR_STDOUT,"<p><HR><H2>");
  1.1898 +	PR_fprintf(PR_STDOUT,"Connection #%d [%s]\n", c_count+1,
  1.1899 +	                     get_time_string());
  1.1900 +	if (fancy)  PR_fprintf(PR_STDOUT,"</H2>");
  1.1901 +	}
  1.1902 +
  1.1903 +
  1.1904 +      PR_fprintf(PR_STDOUT,"Connected to %s:%d\n", hostname, port);
  1.1905 +
  1.1906 +#define PD_C 0
  1.1907 +#define PD_S 1
  1.1908 +
  1.1909 +      pds[PD_C].fd = s_client;
  1.1910 +      pds[PD_S].fd = s_server;
  1.1911 +      pds[PD_C].in_flags = PR_POLL_READ;
  1.1912 +      pds[PD_S].in_flags = PR_POLL_READ;
  1.1913 +
  1.1914 +      /* make sure the new connections don't start out encrypted. */
  1.1915 +      clientstream.isEncrypted = 0;
  1.1916 +      serverstream.isEncrypted = 0;
  1.1917 +      isV2Session = 0;
  1.1918 +
  1.1919 +      while( (pds[PD_C].in_flags & PR_POLL_READ) != 0 ||
  1.1920 +             (pds[PD_S].in_flags & PR_POLL_READ) != 0 )
  1.1921 +        {  /* Handle all messages on the connection */
  1.1922 +	  PRInt32 amt;
  1.1923 +	  PRInt32 wrote;
  1.1924 +	  unsigned char buffer[ TAPBUFSIZ ];
  1.1925 +
  1.1926 +	  amt = PR_Poll(pds,2,PR_INTERVAL_NO_TIMEOUT);
  1.1927 +	  if (amt <= 0) {
  1.1928 +	    if (amt)
  1.1929 +		showErr( "PR_Poll failed.\n");
  1.1930 +	    else
  1.1931 +		showErr( "PR_Poll timed out.\n");
  1.1932 +	    break;
  1.1933 +	  }
  1.1934 +
  1.1935 +	  if (pds[PD_C].out_flags & PR_POLL_EXCEPT) {
  1.1936 +	    showErr( "Exception on client-side socket.\n");
  1.1937 +	    break;
  1.1938 +	  }
  1.1939 +
  1.1940 +	  if (pds[PD_S].out_flags & PR_POLL_EXCEPT) {
  1.1941 +	    showErr( "Exception on server-side socket.\n");
  1.1942 +	    break;
  1.1943 +	  }
  1.1944 +
  1.1945 +
  1.1946 +/* read data, copy it to stdout, and write to other socket */
  1.1947 +
  1.1948 +	  if ((pds[PD_C].in_flags  & PR_POLL_READ) != 0 &&
  1.1949 +	      (pds[PD_C].out_flags & PR_POLL_READ) != 0 ) {
  1.1950 +
  1.1951 +	    amt = PR_Read(s_client, buffer, sizeof(buffer));
  1.1952 +
  1.1953 +	    if ( amt < 0)  {
  1.1954 +	      showErr( "Client socket read failed.\n");
  1.1955 +	      break;
  1.1956 +	    }
  1.1957 +
  1.1958 +	    if( amt == 0 ) {
  1.1959 +	      PR_fprintf(PR_STDOUT, "Read EOF on Client socket. [%s]\n",
  1.1960 +	                            get_time_string() );
  1.1961 +	      pds[PD_C].in_flags &= ~PR_POLL_READ;
  1.1962 +	      PR_Shutdown(s_server, PR_SHUTDOWN_SEND);
  1.1963 +	      continue;
  1.1964 +	    }
  1.1965 +
  1.1966 +	    PR_fprintf(PR_STDOUT,"--> [\n");
  1.1967 +	    if (fancy) PR_fprintf(PR_STDOUT,"<font color=blue>");
  1.1968 +
  1.1969 +	    if (hexparse)  print_hex(amt, buffer);
  1.1970 +	    if (sslparse)  print_ssl(&clientstream,amt,buffer);
  1.1971 +	    if (!hexparse && !sslparse)  PR_Write(PR_STDOUT,buffer,amt);
  1.1972 +	    if (fancy) PR_fprintf(PR_STDOUT,"</font>");
  1.1973 +	    PR_fprintf(PR_STDOUT,"]\n");
  1.1974 +
  1.1975 +	    wrote = PR_Write(s_server, buffer, amt);
  1.1976 +	    if (wrote != amt )  {
  1.1977 +	      if (wrote < 0) {
  1.1978 +	        showErr("Write to server socket failed.\n");
  1.1979 +		break;
  1.1980 +	      } else {
  1.1981 +		PR_fprintf(PR_STDERR, "Short write to server socket!\n");
  1.1982 +	      }
  1.1983 +	    }
  1.1984 +	  }  /* end of read from client socket. */
  1.1985 +
  1.1986 +/* read data, copy it to stdout, and write to other socket */
  1.1987 +	  if ((pds[PD_S].in_flags  & PR_POLL_READ) != 0 &&
  1.1988 +	      (pds[PD_S].out_flags & PR_POLL_READ) != 0 ) {
  1.1989 +
  1.1990 +	    amt = PR_Read(s_server, buffer, sizeof(buffer));
  1.1991 +
  1.1992 +	    if ( amt < 0)  {
  1.1993 +	      showErr( "error on server-side socket.\n");
  1.1994 +	      break;
  1.1995 +	    }
  1.1996 +
  1.1997 +	    if( amt == 0 ) {
  1.1998 +	      PR_fprintf(PR_STDOUT, "Read EOF on Server socket. [%s]\n",
  1.1999 +	                            get_time_string() );
  1.2000 +	      pds[PD_S].in_flags &= ~PR_POLL_READ;
  1.2001 +	      PR_Shutdown(s_client, PR_SHUTDOWN_SEND);
  1.2002 +	      continue;
  1.2003 +	    } 
  1.2004 +
  1.2005 +	    PR_fprintf(PR_STDOUT,"<-- [\n");
  1.2006 +	    if (fancy) PR_fprintf(PR_STDOUT,"<font color=red>");
  1.2007 +	    if (hexparse)  print_hex(amt, (unsigned char *)buffer);
  1.2008 +	    if (sslparse)  print_ssl(&serverstream,amt,(unsigned char *)buffer);
  1.2009 +	    if (!hexparse && !sslparse)  PR_Write(PR_STDOUT,buffer,amt);
  1.2010 +	    if (fancy) PR_fprintf(PR_STDOUT,"</font>");
  1.2011 +	    PR_fprintf(PR_STDOUT,"]\n");
  1.2012 +
  1.2013 +
  1.2014 +	    wrote = PR_Write(s_client, buffer, amt);
  1.2015 +	    if (wrote != amt )  {
  1.2016 +	      if (wrote < 0) {
  1.2017 +	        showErr("Write to client socket failed.\n");
  1.2018 +		break;
  1.2019 +	      } else {
  1.2020 +		PR_fprintf(PR_STDERR, "Short write to client socket!\n");
  1.2021 +	      }
  1.2022 +	    }
  1.2023 +
  1.2024 +	  } /* end of read from server socket. */
  1.2025 +
  1.2026 +/* Loop, handle next message. */
  1.2027 +
  1.2028 +        }	/* handle messages during a connection loop */
  1.2029 +      PR_Close(s_client);
  1.2030 +      PR_Close(s_server);
  1.2031 +      flush_stream(&clientstream);
  1.2032 +      flush_stream(&serverstream);
  1.2033 +      /* Connection is closed, so reset the current cipher */
  1.2034 +      currentcipher = 0;
  1.2035 +      c_count++;
  1.2036 +      PR_fprintf(PR_STDERR,"Connection %d Complete [%s]\n", c_count,
  1.2037 +                            get_time_string() );
  1.2038 +    }  while (looparound); /* accept connection and process it. */
  1.2039 +    PR_Close(s_rend);
  1.2040 +    NSS_Shutdown();
  1.2041 +    return 0;
  1.2042 +}

mercurial