~ubuntu-branches/ubuntu/trusty/xulrunner/trusty

« back to all changes in this revision

Viewing changes to security/nss-fips/cmd/ssltap/ssltap.c

  • Committer: Bazaar Package Importer
  • Author(s): Devid Antonio Filoni
  • Date: 2008-08-25 13:04:18 UTC
  • mfrom: (1.1.12 upstream)
  • Revision ID: james.westby@ubuntu.com-20080825130418-ck1i2ms384tzb9m0
Tags: 1.8.1.16+nobinonly-0ubuntu1
* New upstream release (taken from upstream CVS), LP: #254618.
* Fix MFSA 2008-35, MFSA 2008-34, MFSA 2008-33, MFSA 2008-32, MFSA 2008-31,
  MFSA 2008-30, MFSA 2008-29, MFSA 2008-28, MFSA 2008-27, MFSA 2008-25,
  MFSA 2008-24, MFSA 2008-23, MFSA 2008-22, MFSA 2008-21, MFSA 2008-26 also
  known as CVE-2008-2933, CVE-2008-2785, CVE-2008-2811, CVE-2008-2810,
  CVE-2008-2809, CVE-2008-2808, CVE-2008-2807, CVE-2008-2806, CVE-2008-2805,
  CVE-2008-2803, CVE-2008-2802, CVE-2008-2801, CVE-2008-2800, CVE-2008-2798.
* Drop 89_bz419350_attachment_306066 patch, merged upstream.
* Bump Standards-Version to 3.8.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ***** BEGIN LICENSE BLOCK *****
 
2
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 
3
 *
 
4
 * The contents of this file are subject to the Mozilla Public License Version
 
5
 * 1.1 (the "License"); you may not use this file except in compliance with
 
6
 * the License. You may obtain a copy of the License at
 
7
 * http://www.mozilla.org/MPL/
 
8
 *
 
9
 * Software distributed under the License is distributed on an "AS IS" basis,
 
10
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 
11
 * for the specific language governing rights and limitations under the
 
12
 * License.
 
13
 *
 
14
 * The Original Code is the Netscape security libraries.
 
15
 *
 
16
 * The Initial Developer of the Original Code is
 
17
 * Netscape Communications Corporation.
 
18
 * Portions created by the Initial Developer are Copyright (C) 1994-2000
 
19
 * the Initial Developer. All Rights Reserved.
 
20
 *
 
21
 * Contributor(s):
 
22
 *
 
23
 * Alternatively, the contents of this file may be used under the terms of
 
24
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 
25
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 
26
 * in which case the provisions of the GPL or the LGPL are applicable instead
 
27
 * of those above. If you wish to allow use of your version of this file only
 
28
 * under the terms of either the GPL or the LGPL, and not to allow others to
 
29
 * use your version of this file under the terms of the MPL, indicate your
 
30
 * decision by deleting the provisions above and replace them with the notice
 
31
 * and other provisions required by the GPL or the LGPL. If you do not delete
 
32
 * the provisions above, a recipient may use your version of this file under
 
33
 * the terms of any one of the MPL, the GPL or the LGPL.
 
34
 *
 
35
 * ***** END LICENSE BLOCK ***** */
 
36
 
 
37
/*
 
38
 * ssltap.c
 
39
 *
 
40
 * Version 1.0 : Frederick Roeber : 11 June 1997
 
41
 * Version 2.0 : Steve Parkinson  : 13 November 1997
 
42
 * Version 3.0 : Nelson Bolyard   : 22 July 1998
 
43
 * Version 3.1 : Nelson Bolyard   : 24 May  1999
 
44
 *
 
45
 * changes in version 2.0:
 
46
 *  Uses NSPR20
 
47
 *  Shows structure of SSL negotiation, if enabled.
 
48
 *
 
49
 * This "proxies" a socket connection (like a socks tunnel), but displays the
 
50
 * data is it flies by.
 
51
 *
 
52
 * In the code, the 'client' socket is the one on the client side of the
 
53
 * proxy, and the server socket is on the server side.
 
54
 *
 
55
 */
 
56
 
 
57
#include "nspr.h"
 
58
#include "plstr.h"
 
59
#include "secutil.h"
 
60
#include <memory.h>     /* for memcpy, etc. */
 
61
#include <string.h>
 
62
#include <time.h>
 
63
 
 
64
#include "plgetopt.h"
 
65
#include "nss.h"
 
66
#include "cert.h"
 
67
 
 
68
#define VERSIONSTRING "$Revision: 1.7.2.2 $ ($Date: 2006/07/19 01:18:33 $) $Author: nelson%bolyard.com $"
 
69
 
 
70
 
 
71
struct _DataBufferList;
 
72
struct _DataBuffer;
 
73
 
 
74
typedef struct _DataBufferList {
 
75
  struct _DataBuffer *first,*last;
 
76
  int size;
 
77
  int isEncrypted;
 
78
} DataBufferList;
 
79
 
 
80
typedef struct _DataBuffer {
 
81
  unsigned char *buffer;
 
82
  int length;
 
83
  int offset;  /* offset of first good byte */
 
84
  struct _DataBuffer *next;
 
85
} DataBuffer;
 
86
 
 
87
 
 
88
DataBufferList
 
89
  clientstream = {NULL, NULL, 0, 0},
 
90
  serverstream = {NULL, NULL, 0, 0};
 
91
 
 
92
struct sslhandshake {
 
93
  PRUint8 type;
 
94
  PRUint32 length;
 
95
};
 
96
 
 
97
typedef struct _SSLRecord {
 
98
  PRUint8 type;
 
99
  PRUint8 ver_maj,ver_min;
 
100
 
 
101
  PRUint8 length[2];
 
102
} SSLRecord;
 
103
 
 
104
typedef struct _ClientHelloV2 {
 
105
  PRUint8 length[2];
 
106
  PRUint8 type;
 
107
  PRUint8 version[2];
 
108
  PRUint8 cslength[2];
 
109
  PRUint8 sidlength[2];
 
110
  PRUint8 rndlength[2];
 
111
  PRUint8 csuites[1];
 
112
} ClientHelloV2;
 
113
 
 
114
typedef struct _ServerHelloV2 {
 
115
  PRUint8 length[2];
 
116
  PRUint8 type;
 
117
  PRUint8 sidhit;
 
118
  PRUint8 certtype;
 
119
  PRUint8 version[2];
 
120
  PRUint8 certlength[2];
 
121
  PRUint8 cslength[2];
 
122
  PRUint8 cidlength[2];
 
123
} ServerHelloV2;
 
124
 
 
125
typedef struct _ClientMasterKeyV2 {
 
126
  PRUint8 length[2];
 
127
  PRUint8 type;
 
128
 
 
129
  PRUint8 cipherkind[3];
 
130
  PRUint8 clearkey[2];
 
131
  PRUint8 secretkey[2];
 
132
 
 
133
} ClientMasterKeyV2;
 
134
 
 
135
 
 
136
 
 
137
#define TAPBUFSIZ 16384
 
138
 
 
139
#define DEFPORT 1924
 
140
#include <ctype.h>
 
141
 
 
142
int hexparse=0;
 
143
int sslparse=0;
 
144
int sslhexparse=0;
 
145
int looparound=0;
 
146
int fancy=0;
 
147
int isV2Session=0;
 
148
 
 
149
#define PR_FPUTS(x) PR_fprintf(PR_STDOUT, x )
 
150
 
 
151
#define GET_SHORT(x) ((PRUint16)(((PRUint16)((PRUint8*)x)[0]) << 8) + ((PRUint16)((PRUint8*)x)[1]))
 
152
#define GET_24(x) ((PRUint32)   (  \
 
153
                                 (((PRUint32)((PRUint8*)x)[0]) << 16) \
 
154
                                 +                          \
 
155
                                 (((PRUint32)((PRUint8*)x)[1]) << 8)  \
 
156
                                 +                          \
 
157
                                 (((PRUint32)((PRUint8*)x)[2]) << 0)  \
 
158
                                 ) )
 
159
 
 
160
void print_hex(int amt, unsigned char *buf);
 
161
void read_stream_bytes(unsigned char *d, DataBufferList *db, int length);
 
162
 
 
163
void myhalt(int dblsize,int collectedsize) {
 
164
 
 
165
  while(1) ;
 
166
 
 
167
}
 
168
 
 
169
const char *get_error_text(int error) {
 
170
  switch (error) {
 
171
  case PR_IO_TIMEOUT_ERROR:
 
172
    return "Timeout";
 
173
    break;
 
174
  case PR_CONNECT_REFUSED_ERROR:
 
175
    return "Connection refused";
 
176
    break;
 
177
  case PR_NETWORK_UNREACHABLE_ERROR:
 
178
    return "Network unreachable";
 
179
    break;
 
180
  case PR_BAD_ADDRESS_ERROR:
 
181
    return "Bad address";
 
182
    break;
 
183
  case PR_CONNECT_RESET_ERROR:
 
184
    return "Connection reset";
 
185
    break;
 
186
  case PR_PIPE_ERROR:
 
187
    return "Pipe error";
 
188
    break;
 
189
  }
 
190
 
 
191
  return "";
 
192
}
 
193
 
 
194
 
 
195
 
 
196
 
 
197
 
 
198
void check_integrity(DataBufferList *dbl) {
 
199
  DataBuffer *db;
 
200
  int i;
 
201
 
 
202
  db = dbl->first;
 
203
  i =0;
 
204
  while (db) {
 
205
    i+= db->length - db->offset;
 
206
    db = db->next;
 
207
  }
 
208
  if (i != dbl->size) {
 
209
    myhalt(dbl->size,i);
 
210
  }
 
211
}
 
212
 
 
213
/* Free's the DataBuffer at the head of the list and returns the pointer
 
214
 * to the new head of the list.
 
215
 */
 
216
DataBuffer * 
 
217
free_head(DataBufferList *dbl)
 
218
{
 
219
  DataBuffer *db       = dbl->first;
 
220
  PR_ASSERT(db->offset >= db->length);
 
221
  if (db->offset >= db->length) {
 
222
    dbl->first = db->next;
 
223
    if (dbl->first == NULL) {
 
224
      dbl->last = NULL;
 
225
    }
 
226
    PR_Free(db->buffer);
 
227
    PR_Free(db);
 
228
    db = dbl->first;
 
229
  }
 
230
  return db;
 
231
}
 
232
 
 
233
void 
 
234
read_stream_bytes(unsigned char *d, DataBufferList *dbl, int length) {
 
235
  int         copied    = 0;
 
236
  DataBuffer *db        = dbl->first;
 
237
 
 
238
  if (!db) {
 
239
    PR_fprintf(PR_STDERR,"assert failed - dbl->first is null\n");
 
240
    exit(8);
 
241
  }
 
242
  while (length) {
 
243
    int         toCopy;
 
244
    /* find the number of bytes to copy from the head buffer */
 
245
    /* if there's too many in this buffer, then only copy 'length' */
 
246
    toCopy = PR_MIN(db->length - db->offset, length);
 
247
 
 
248
    memcpy(d + copied, db->buffer + db->offset, toCopy);
 
249
    copied     += toCopy;
 
250
    db->offset += toCopy;
 
251
    length     -= toCopy;
 
252
    dbl->size  -= toCopy;
 
253
 
 
254
    /* if we emptied the head buffer */
 
255
    if (db->offset >= db->length) {
 
256
      db = free_head(dbl);
 
257
    }
 
258
  }
 
259
 
 
260
  check_integrity(dbl);
 
261
 
 
262
}
 
263
 
 
264
void
 
265
flush_stream(DataBufferList *dbl)
 
266
{
 
267
    DataBuffer *db = dbl->first;
 
268
    check_integrity(dbl);
 
269
    while (db) {
 
270
        db->offset = db->length;
 
271
        db = free_head(dbl);
 
272
    }
 
273
    dbl->size = 0;
 
274
    check_integrity(dbl);
 
275
}
 
276
 
 
277
 
 
278
const char * V2CipherString(int cs_int) {
 
279
  char *cs_str;
 
280
  cs_str = NULL;
 
281
  switch (cs_int) {
 
282
 
 
283
  case 0x010080:    cs_str = "SSL2/RSA/RC4-128/MD5";       break;
 
284
  case 0x020080:    cs_str = "SSL2/RSA/RC4-40/MD5";    break;
 
285
  case 0x030080:    cs_str = "SSL2/RSA/RC2CBC128/MD5";     break;
 
286
  case 0x040080:    cs_str = "SSL2/RSA/RC2CBC40/MD5";  break;
 
287
  case 0x050080:    cs_str = "SSL2/RSA/IDEA128CBC/MD5";    break;
 
288
  case 0x060040:    cs_str = "SSL2/RSA/DES56-CBC/MD5";      break;
 
289
  case 0x0700C0:    cs_str = "SSL2/RSA/3DES192EDE-CBC/MD5"; break;
 
290
 
 
291
  case 0x000001:    cs_str = "SSL3/RSA/NULL/MD5";             break;
 
292
  case 0x000002:    cs_str = "SSL3/RSA/NULL/SHA";             break;
 
293
  case 0x000003:    cs_str = "SSL3/RSA/RC4-40/MD5";       break;
 
294
  case 0x000004:    cs_str = "SSL3/RSA/RC4-128/MD5";          break;
 
295
  case 0x000005:    cs_str = "SSL3/RSA/RC4-128/SHA";          break;
 
296
  case 0x000006:    cs_str = "SSL3/RSA/RC2CBC40/MD5";     break;
 
297
  case 0x000007:    cs_str = "SSL3/RSA/IDEA128CBC/SHA";       break;
 
298
  case 0x000008:    cs_str = "SSL3/RSA/DES40-CBC/SHA";         break;
 
299
  case 0x000009:    cs_str = "SSL3/RSA/DES56-CBC/SHA";         break;
 
300
  case 0x00000A:    cs_str = "SSL3/RSA/3DES192EDE-CBC/SHA";    break;
 
301
 
 
302
  case 0x00000B:    cs_str = "SSL3/DH-DSS/DES40-CBC/SHA";      break;
 
303
  case 0x00000C:    cs_str = "SSL3/DH-DSS/DES56-CBC/SHA";      break;
 
304
  case 0x00000D:    cs_str = "SSL3/DH-DSS/DES192EDE3CBC/SHA"; break;
 
305
  case 0x00000E:    cs_str = "SSL3/DH-RSA/DES40-CBC/SHA";      break;
 
306
  case 0x00000F:    cs_str = "SSL3/DH-RSA/DES56-CBC/SHA";      break;
 
307
  case 0x000010:    cs_str = "SSL3/DH-RSA/3DES192EDE-CBC/SHA"; break;
 
308
 
 
309
  case 0x000011:    cs_str = "SSL3/DHE-DSS/DES40-CBC/SHA";      break;
 
310
  case 0x000012:    cs_str = "SSL3/DHE-DSS/DES56-CBC/SHA";      break;
 
311
  case 0x000013:    cs_str = "SSL3/DHE-DSS/DES192EDE3CBC/SHA"; break;
 
312
  case 0x000014:    cs_str = "SSL3/DHE-RSA/DES40-CBC/SHA";      break;
 
313
  case 0x000015:    cs_str = "SSL3/DHE-RSA/DES56-CBC/SHA";      break;
 
314
  case 0x000016:    cs_str = "SSL3/DHE-RSA/3DES192EDE-CBC/SHA"; break;
 
315
 
 
316
  case 0x000017:    cs_str = "SSL3/DH-anon/RC4-40/MD5";     break;
 
317
  case 0x000018:    cs_str = "SSL3/DH-anon/RC4-128/MD5";        break;
 
318
  case 0x000019:    cs_str = "SSL3/DH-anon/DES40-CBC/SHA";       break;
 
319
  case 0x00001A:    cs_str = "SSL3/DH-anon/DES56-CBC/SHA";       break;
 
320
  case 0x00001B:    cs_str = "SSL3/DH-anon/3DES192EDE-CBC/SHA"; break;
 
321
 
 
322
  case 0x00001C:    cs_str = "SSL3/FORTEZZA-DMS/NULL/SHA";      break;
 
323
  case 0x00001D:    cs_str = "SSL3/FORTEZZA-DMS/FORTEZZA-CBC/SHA";  break;
 
324
  case 0x00001E:    cs_str = "SSL3/FORTEZZA-DMS/RC4-128/SHA";  break;
 
325
 
 
326
  case 0x00002F:    cs_str = "TLS/RSA/AES128-CBC/SHA";          break;
 
327
  case 0x000030:    cs_str = "TLS/DH-DSS/AES128-CBC/SHA";       break;
 
328
  case 0x000031:    cs_str = "TLS/DH-RSA/AES128-CBC/SHA";       break;
 
329
  case 0x000032:    cs_str = "TLS/DHE-DSS/AES128-CBC/SHA";      break;
 
330
  case 0x000033:    cs_str = "TLS/DHE-RSA/AES128-CBC/SHA";      break;
 
331
  case 0x000034:    cs_str = "TLS/DH-ANON/AES128-CBC/SHA";      break;
 
332
 
 
333
  case 0x000035:    cs_str = "TLS/RSA/AES256-CBC/SHA";          break;
 
334
  case 0x000036:    cs_str = "TLS/DH-DSS/AES256-CBC/SHA";       break;
 
335
  case 0x000037:    cs_str = "TLS/DH-RSA/AES256-CBC/SHA";       break;
 
336
  case 0x000038:    cs_str = "TLS/DHE-DSS/AES256-CBC/SHA";      break;
 
337
  case 0x000039:    cs_str = "TLS/DHE-RSA/AES256-CBC/SHA";      break;
 
338
  case 0x00003A:    cs_str = "TLS/DH-ANON/AES256-CBC/SHA";      break;
 
339
 
 
340
  case 0x000041:    cs_str = "TLS/RSA/CAMELLIA128-CBC/SHA";     break;
 
341
  case 0x000042:    cs_str = "TLS/DH-DSS/CAMELLIA128-CBC/SHA";  break;
 
342
  case 0x000043:    cs_str = "TLS/DH-RSA/CAMELLIA128-CBC/SHA";  break;
 
343
  case 0x000044:    cs_str = "TLS/DHE-DSS/CAMELLIA128-CBC/SHA"; break;
 
344
  case 0x000045:    cs_str = "TLS/DHE-RSA/CAMELLIA128-CBC/SHA"; break;
 
345
  case 0x000046:    cs_str = "TLS/DH-ANON/CAMELLIA128-CBC/SHA"; break;
 
346
 
 
347
  case 0x000047:    cs_str = "TLS/ECDH-ECDSA/NULL/SHA";         break;
 
348
  case 0x000048:    cs_str = "TLS/ECDH-ECDSA/RC4-128/SHA";      break;
 
349
  case 0x000049:    cs_str = "TLS/ECDH-ECDSA/DES-CBC/SHA";      break;
 
350
  case 0x00004A:    cs_str = "TLS/ECDH-ECDSA/3DESEDE-CBC/SHA";  break;
 
351
  case 0x00004B:    cs_str = "TLS/ECDH-ECDSA/AES128-CBC/SHA";   break;
 
352
  case 0x00004C:    cs_str = "TLS/ECDH-ECDSA/AES256-CBC/SHA";   break;
 
353
 
 
354
  case 0x00004D:    cs_str = "TLS/ECDH-RSA/NULL/SHA";           break;
 
355
  case 0x00004E:    cs_str = "TLS/ECDH-RSA/RC4-128/SHA";        break;
 
356
  case 0x00004F:    cs_str = "TLS/ECDH-RSA/DES-CBC/SHA";        break;
 
357
  case 0x000050:    cs_str = "TLS/ECDH-RSA/3DESEDE-CBC/SHA";    break;
 
358
  case 0x000051:    cs_str = "TLS/ECDH-RSA/AES128-CBC/SHA";     break;
 
359
  case 0x000052:    cs_str = "TLS/ECDH-RSA/AES256-CBC/SHA";     break;
 
360
 
 
361
  case 0x000060:    cs_str = "TLS/RSA-EXPORT1024/RC4-56/MD5";   break;
 
362
  case 0x000061:    cs_str = "TLS/RSA-EXPORT1024/RC2CBC56/MD5"; break;
 
363
  case 0x000062:    cs_str = "TLS/RSA-EXPORT1024/DES56-CBC/SHA";   break;
 
364
  case 0x000064:    cs_str = "TLS/RSA-EXPORT1024/RC4-56/SHA";      break;
 
365
  case 0x000063:    cs_str = "TLS/DHE-DSS_EXPORT1024/DES56-CBC/SHA"; break;
 
366
  case 0x000065:    cs_str = "TLS/DHE-DSS_EXPORT1024/RC4-56/SHA";  break;
 
367
  case 0x000066:    cs_str = "TLS/DHE-DSS/RC4-128/SHA";            break;
 
368
 
 
369
  case 0x000072:    cs_str = "TLS/DHE-DSS/3DESEDE-CBC/RMD160"; break;
 
370
  case 0x000073:    cs_str = "TLS/DHE-DSS/AES128-CBC/RMD160";  break;
 
371
  case 0x000074:    cs_str = "TLS/DHE-DSS/AES256-CBC/RMD160";  break;
 
372
 
 
373
  case 0x000077:    cs_str = "TLS/ECDHE-ECDSA/AES128-CBC/SHA";  break;
 
374
  case 0x000078:    cs_str = "TLS/ECDHE-RSA/AES128-CBC/SHA";    break;
 
375
 
 
376
  case 0x000079:    cs_str = "TLS/DHE-RSA/AES256-CBC/RMD160";  break;
 
377
 
 
378
  case 0x00007C:    cs_str = "TLS/RSA/3DESEDE-CBC/RMD160"; break;
 
379
  case 0x00007D:    cs_str = "TLS/RSA/AES128-CBC/RMD160"; break;
 
380
  case 0x00007E:    cs_str = "TLS/RSA/AES256-CBC/RMD160"; break;
 
381
 
 
382
  case 0x000080:    cs_str = "TLS/GOST341094/GOST28147-OFB/GOST28147"; break;
 
383
  case 0x000081:    cs_str = "TLS/GOST34102001/GOST28147-OFB/GOST28147"; break;
 
384
  case 0x000082:    cs_str = "TLS/GOST341094/NULL/GOSTR3411"; break;
 
385
  case 0x000083:    cs_str = "TLS/GOST34102001/NULL/GOSTR3411"; break;
 
386
 
 
387
  case 0x000084:    cs_str = "TLS/RSA/CAMELLIA256-CBC/SHA";     break;
 
388
  case 0x000085:    cs_str = "TLS/DH-DSS/CAMELLIA256-CBC/SHA";  break;
 
389
  case 0x000086:    cs_str = "TLS/DH-RSA/CAMELLIA256-CBC/SHA";  break;
 
390
  case 0x000087:    cs_str = "TLS/DHE-DSS/CAMELLIA256-CBC/SHA"; break;
 
391
  case 0x000088:    cs_str = "TLS/DHE-RSA/CAMELLIA256-CBC/SHA"; break;
 
392
  case 0x000089:    cs_str = "TLS/DH-ANON/CAMELLIA256-CBC/SHA"; break;
 
393
  case 0x00008A:    cs_str = "TLS/PSK/RC4-128/SHA";             break;
 
394
  case 0x00008B:    cs_str = "TLS/PSK/3DES-EDE-CBC/SHA";        break;
 
395
  case 0x00008C:    cs_str = "TLS/PSK/AES128-CBC/SHA";          break;      
 
396
  case 0x00008D:    cs_str = "TLS/PSK/AES256-CBC/SHA";          break;      
 
397
  case 0x00008E:    cs_str = "TLS/DHE-PSK/RC4-128/SHA";         break;      
 
398
  case 0x00008F:    cs_str = "TLS/DHE-PSK/3DES-EDE-CBC/SHA";    break; 
 
399
  case 0x000090:    cs_str = "TLS/DHE-PSK/AES128-CBC/SHA";      break;  
 
400
  case 0x000091:    cs_str = "TLS/DHE-PSK/AES256-CBC/SHA";      break;  
 
401
  case 0x000092:    cs_str = "TLS/RSA-PSK/RC4-128/SHA";         break;      
 
402
  case 0x000093:    cs_str = "TLS/RSA-PSK/3DES-EDE-CBC/SHA";    break; 
 
403
  case 0x000094:    cs_str = "TLS/RSA-PSK/AES128-CBC/SHA";      break;  
 
404
  case 0x000095:    cs_str = "TLS/RSA-PSK/AES256-CBC/SHA";      break;  
 
405
  case 0x000096:    cs_str = "TLS/RSA/SEED-CBC/SHA";            break;         
 
406
  case 0x000097:    cs_str = "TLS/DH-DSS/SEED-CBC/SHA";         break;      
 
407
  case 0x000098:    cs_str = "TLS/DH-RSA/SEED-CBC/SHA";         break;      
 
408
  case 0x000099:    cs_str = "TLS/DHE-DSS/SEED-CBC/SHA";        break;     
 
409
  case 0x00009A:    cs_str = "TLS/DHE-RSA/SEED-CBC/SHA";        break;     
 
410
  case 0x00009B:    cs_str = "TLS/DH-ANON/SEED-CBC/SHA";        break;     
 
411
 
 
412
  case 0x00C001:    cs_str = "TLS/ECDH-ECDSA/NULL/SHA";         break;
 
413
  case 0x00C002:    cs_str = "TLS/ECDH-ECDSA/RC4-128/SHA";      break;
 
414
  case 0x00C003:    cs_str = "TLS/ECDH-ECDSA/3DES-EDE-CBC/SHA"; break;
 
415
  case 0x00C004:    cs_str = "TLS/ECDH-ECDSA/AES128-CBC/SHA";   break;
 
416
  case 0x00C005:    cs_str = "TLS/ECDH-ECDSA/AES256-CBC/SHA";   break;
 
417
  case 0x00C006:    cs_str = "TLS/ECDHE-ECDSA/NULL/SHA";        break;
 
418
  case 0x00C007:    cs_str = "TLS/ECDHE-ECDSA/RC4-128/SHA";     break;
 
419
  case 0x00C008:    cs_str = "TLS/ECDHE-ECDSA/3DES-EDE-CBC/SHA";break;
 
420
  case 0x00C009:    cs_str = "TLS/ECDHE-ECDSA/AES128-CBC/SHA";  break;
 
421
  case 0x00C00A:    cs_str = "TLS/ECDHE-ECDSA/AES256-CBC/SHA";  break;
 
422
  case 0x00C00B:    cs_str = "TLS/ECDH-RSA/NULL/SHA";           break;
 
423
  case 0x00C00C:    cs_str = "TLS/ECDH-RSA/RC4-128/SHA";        break;
 
424
  case 0x00C00D:    cs_str = "TLS/ECDH-RSA/3DES-EDE-CBC/SHA";   break;
 
425
  case 0x00C00E:    cs_str = "TLS/ECDH-RSA/AES128-CBC/SHA";     break;
 
426
  case 0x00C00F:    cs_str = "TLS/ECDH-RSA/AES256-CBC/SHA";     break;
 
427
  case 0x00C010:    cs_str = "TLS/ECDHE-RSA/NULL/SHA";          break;
 
428
  case 0x00C011:    cs_str = "TLS/ECDHE-RSA/RC4-128/SHA";       break;
 
429
  case 0x00C012:    cs_str = "TLS/ECDHE-RSA/3DES-EDE-CBC/SHA";  break;
 
430
  case 0x00C013:    cs_str = "TLS/ECDHE-RSA/AES128-CBC/SHA";    break;
 
431
  case 0x00C014:    cs_str = "TLS/ECDHE-RSA/AES256-CBC/SHA";    break;
 
432
  case 0x00C015:    cs_str = "TLS/ECDH-anon/NULL/SHA";          break;
 
433
  case 0x00C016:    cs_str = "TLS/ECDH-anon/RC4-128/SHA";       break;
 
434
  case 0x00C017:    cs_str = "TLS/ECDH-anon/3DES-EDE-CBC/SHA";  break;
 
435
  case 0x00C018:    cs_str = "TLS/ECDH-anon/AES128-CBC/SHA";    break;
 
436
  case 0x00C019:    cs_str = "TLS/ECDH-anon/AES256-CBC/SHA";    break;
 
437
 
 
438
  case 0x00feff:    cs_str = "SSL3/RSA-FIPS/3DESEDE-CBC/SHA";   break;
 
439
  case 0x00fefe:    cs_str = "SSL3/RSA-FIPS/DES-CBC/SHA";       break;
 
440
  case 0x00ffe1:    cs_str = "SSL3/RSA-FIPS/DES56-CBC/SHA";     break;
 
441
  case 0x00ffe0:    cs_str = "SSL3/RSA-FIPS/3DES192EDE-CBC/SHA";break;
 
442
 
 
443
  /* the string literal is broken up to avoid trigraphs */
 
444
  default:          cs_str = "????" "/????????" "/?????????" "/???"; break;
 
445
  }
 
446
 
 
447
  return cs_str;
 
448
}
 
449
 
 
450
const char * helloExtensionNameString(int ex_num) {
 
451
  const char *ex_name = NULL;
 
452
  static char buf[10];
 
453
 
 
454
  switch (ex_num) {
 
455
  case  0: ex_name = "server_name";                    break;
 
456
  case  1: ex_name = "max_fragment_length";            break;
 
457
  case  2: ex_name = "client_certificate_url";         break;
 
458
  case  3: ex_name = "trusted_ca_keys";                break;
 
459
  case  4: ex_name = "truncated_hmac";                 break;
 
460
  case  5: ex_name = "status_request";                 break;
 
461
  case 10: ex_name = "elliptic_curves";                break;
 
462
  case 11: ex_name = "ec_point_formats";               break;
 
463
  default: sprintf(buf, "%d", ex_num);  ex_name = (const char *)buf; break;
 
464
  }
 
465
 
 
466
  return ex_name;
 
467
}
 
468
 
 
469
void partial_packet(int thispacket, int size, int needed)
 
470
{
 
471
  PR_fprintf(PR_STDOUT,"(%u bytes", thispacket);
 
472
  if (thispacket < needed) {
 
473
    PR_fprintf(PR_STDOUT,", making %u", size);
 
474
  }
 
475
  PR_fprintf(PR_STDOUT," of %u", needed);
 
476
  if (size > needed) {
 
477
    PR_fprintf(PR_STDOUT,", with %u left over", size - needed);
 
478
  }
 
479
  PR_fprintf(PR_STDOUT,")\n");
 
480
}
 
481
 
 
482
char * get_time_string(void)
 
483
{
 
484
  char      *cp;
 
485
  char      *eol;
 
486
  time_t     tt;
 
487
 
 
488
  time(&tt);
 
489
  cp = ctime(&tt);
 
490
  eol = strchr(cp, '\n');
 
491
  if (eol) 
 
492
    *eol = 0;
 
493
  return cp;
 
494
}
 
495
 
 
496
void print_sslv2(DataBufferList *s, unsigned char *tbuf, unsigned int alloclen)
 
497
{
 
498
  ClientHelloV2 *chv2;
 
499
  ServerHelloV2 *shv2;
 
500
  unsigned char *pos;
 
501
  unsigned int   p;
 
502
  unsigned int   q;
 
503
  PRUint32       len;
 
504
 
 
505
  chv2 = (ClientHelloV2 *)tbuf;
 
506
  shv2 = (ServerHelloV2 *)tbuf;
 
507
  if (s->isEncrypted) {
 
508
    PR_fprintf(PR_STDOUT," [ssl2]  Encrypted {...}\n");
 
509
    return;
 
510
  }
 
511
  PR_fprintf(PR_STDOUT," [%s]", get_time_string() );
 
512
  switch(chv2->type) {
 
513
  case 1:
 
514
    PR_fprintf(PR_STDOUT," [ssl2]  ClientHelloV2 {\n");
 
515
    PR_fprintf(PR_STDOUT,"           version = {0x%02x, 0x%02x}\n",
 
516
               (PRUint32)chv2->version[0],(PRUint32)chv2->version[1]);
 
517
    PR_fprintf(PR_STDOUT,"           cipher-specs-length = %d (0x%02x)\n",
 
518
               (PRUint32)(GET_SHORT((chv2->cslength))),
 
519
               (PRUint32)(GET_SHORT((chv2->cslength))));
 
520
    PR_fprintf(PR_STDOUT,"           sid-length = %d (0x%02x)\n",
 
521
               (PRUint32)(GET_SHORT((chv2->sidlength))),
 
522
               (PRUint32)(GET_SHORT((chv2->sidlength))));
 
523
    PR_fprintf(PR_STDOUT,"           challenge-length = %d (0x%02x)\n",
 
524
               (PRUint32)(GET_SHORT((chv2->rndlength))),
 
525
               (PRUint32)(GET_SHORT((chv2->rndlength))));
 
526
    PR_fprintf(PR_STDOUT,"           cipher-suites = { \n");
 
527
    for (p=0;p<GET_SHORT((chv2->cslength));p+=3) {
 
528
      const char *cs_str=NULL;
 
529
      PRUint32 cs_int=0;
 
530
      cs_int = GET_24((&chv2->csuites[p]));
 
531
      cs_str = V2CipherString(cs_int);
 
532
 
 
533
      PR_fprintf(PR_STDOUT,"                (0x%06x) %s\n",
 
534
                  cs_int, cs_str);
 
535
    }
 
536
    q = p;
 
537
    PR_fprintf(PR_STDOUT,"                }\n");
 
538
    if (chv2->sidlength) {
 
539
      PR_fprintf(PR_STDOUT,"           session-id = { ");
 
540
      for (p=0;p<GET_SHORT((chv2->sidlength));p+=2) {
 
541
        PR_fprintf(PR_STDOUT,"0x%04x ",(PRUint32)(GET_SHORT((&chv2->csuites[p+q]))));
 
542
      }
 
543
    }
 
544
    q += p;
 
545
    PR_fprintf(PR_STDOUT,"}\n");
 
546
    if (chv2->rndlength) {
 
547
      PR_fprintf(PR_STDOUT,"           challenge = { ");
 
548
      for (p=0;p<GET_SHORT((chv2->rndlength));p+=2) {
 
549
        PR_fprintf(PR_STDOUT,"0x%04x ",(PRUint32)(GET_SHORT((&chv2->csuites[p+q]))));
 
550
      }
 
551
      PR_fprintf(PR_STDOUT,"}\n");
 
552
    }
 
553
    PR_fprintf(PR_STDOUT,"}\n");
 
554
    break;
 
555
    /* end of V2 CLientHello Parsing */
 
556
 
 
557
  case 2:  /* Client Master Key  */
 
558
    {
 
559
    const char *cs_str=NULL;
 
560
    PRUint32 cs_int=0;
 
561
    ClientMasterKeyV2 *cmkv2;
 
562
    cmkv2 = (ClientMasterKeyV2 *)chv2;
 
563
    isV2Session = 1;
 
564
 
 
565
    PR_fprintf(PR_STDOUT," [ssl2]  ClientMasterKeyV2 { \n");
 
566
 
 
567
    cs_int = GET_24(&cmkv2->cipherkind[0]);
 
568
    cs_str = V2CipherString(cs_int);
 
569
    PR_fprintf(PR_STDOUT,"         cipher-spec-chosen = (0x%06x) %s\n",
 
570
               cs_int, cs_str);
 
571
 
 
572
    PR_fprintf(PR_STDOUT,"         clear-portion = %d bits\n",
 
573
               8*(PRUint32)(GET_SHORT((cmkv2->clearkey))));
 
574
 
 
575
    PR_fprintf(PR_STDOUT,"      }\n");
 
576
    clientstream.isEncrypted = 1;
 
577
    serverstream.isEncrypted = 1;
 
578
    }
 
579
    break;
 
580
 
 
581
 
 
582
  case 3:
 
583
    PR_fprintf(PR_STDOUT," [ssl2]  Client Finished V2 {...}\n");
 
584
    isV2Session = 1;
 
585
    break;
 
586
 
 
587
 
 
588
  case 4:  /* V2 Server Hello */
 
589
    isV2Session = 1;
 
590
 
 
591
    PR_fprintf(PR_STDOUT," [ssl2]  ServerHelloV2 {\n");
 
592
    PR_fprintf(PR_STDOUT,"           sid hit = {0x%02x}\n",
 
593
               (PRUintn)shv2->sidhit);
 
594
    PR_fprintf(PR_STDOUT,"           version = {0x%02x, 0x%02x}\n",
 
595
               (PRUint32)shv2->version[0],(PRUint32)shv2->version[1]);
 
596
    PR_fprintf(PR_STDOUT,"           cipher-specs-length = %d (0x%02x)\n",
 
597
               (PRUint32)(GET_SHORT((shv2->cslength))),
 
598
               (PRUint32)(GET_SHORT((shv2->cslength))));
 
599
    PR_fprintf(PR_STDOUT,"           sid-length = %d (0x%02x)\n",
 
600
               (PRUint32)(GET_SHORT((shv2->cidlength))),
 
601
               (PRUint32)(GET_SHORT((shv2->cidlength))));
 
602
 
 
603
    pos = (unsigned char *)shv2;
 
604
    pos += 2;   /* skip length header */
 
605
    pos += 11;  /* position pointer to Certificate data area */
 
606
    q = GET_SHORT(&shv2->certlength);
 
607
    if (q >alloclen) {
 
608
      goto eosh;
 
609
    }
 
610
    pos += q;                   /* skip certificate */
 
611
 
 
612
    PR_fprintf(PR_STDOUT,"           cipher-suites = { ");
 
613
    len = GET_SHORT((shv2->cslength));
 
614
    for (p = 0; p < len; p += 3) {
 
615
      const char *cs_str=NULL;
 
616
      PRUint32 cs_int=0;
 
617
      cs_int = GET_24((pos+p));
 
618
      cs_str = V2CipherString(cs_int);
 
619
      PR_fprintf(PR_STDOUT,"\n              ");
 
620
      PR_fprintf(PR_STDOUT,"(0x%06x) %s", cs_int, cs_str);
 
621
    }
 
622
    pos += len;
 
623
    PR_fprintf(PR_STDOUT,"   }\n");     /* End of cipher suites */
 
624
    len = (PRUint32)GET_SHORT((shv2->cidlength));
 
625
    if (len) {
 
626
      PR_fprintf(PR_STDOUT,"           connection-id = { ");
 
627
      for (p = 0; p < len; p += 2) {
 
628
        PR_fprintf(PR_STDOUT,"0x%04x ", (PRUint32)(GET_SHORT((pos + p))));
 
629
      }
 
630
      PR_fprintf(PR_STDOUT,"   }\n");   /* End of connection id */
 
631
    }
 
632
eosh:
 
633
    PR_fprintf(PR_STDOUT,"\n              }\n"); /* end of ServerHelloV2 */
 
634
    if (shv2->sidhit) {
 
635
      clientstream.isEncrypted = 1;
 
636
      serverstream.isEncrypted = 1;
 
637
    }
 
638
    break;
 
639
 
 
640
  case 5:
 
641
    PR_fprintf(PR_STDOUT," [ssl2]  Server Verify V2 {...}\n");
 
642
    isV2Session = 1;
 
643
    break;
 
644
 
 
645
  case 6:
 
646
    PR_fprintf(PR_STDOUT," [ssl2]  Server Finished V2 {...}\n");
 
647
    isV2Session = 1;
 
648
    break;
 
649
 
 
650
  case 7:
 
651
    PR_fprintf(PR_STDOUT," [ssl2]  Request Certificate V2 {...}\n");
 
652
    isV2Session = 1;
 
653
    break;
 
654
 
 
655
  case 8:
 
656
    PR_fprintf(PR_STDOUT," [ssl2]  Client Certificate V2 {...}\n");
 
657
    isV2Session = 1;
 
658
    break;
 
659
 
 
660
  default:
 
661
    PR_fprintf(PR_STDOUT," [ssl2]  UnknownType 0x%02x {...}\n",
 
662
          (PRUint32)chv2->type);
 
663
    break;
 
664
  }
 
665
}
 
666
 
 
667
 
 
668
 
 
669
unsigned int print_hello_extension(unsigned char *  hsdata,
 
670
                                   unsigned int     length,
 
671
                                   unsigned int     pos)
 
672
{
 
673
  /* pretty print extensions, if any */
 
674
  if (pos < length) {
 
675
    int exListLen = GET_SHORT((hsdata+pos)); pos += 2;
 
676
    PR_fprintf(PR_STDOUT,
 
677
               "            extensions[%d] = {\n", exListLen);
 
678
    while (exListLen > 0 && pos < length) {
 
679
      int exLen;
 
680
      int exType = GET_SHORT((hsdata+pos)); pos += 2;
 
681
      exLen = GET_SHORT((hsdata+pos)); pos += 2;
 
682
      /* dump the extension */
 
683
      PR_fprintf(PR_STDOUT,
 
684
                 "              extension type %s, length [%d]",
 
685
                 helloExtensionNameString(exType), exLen);
 
686
      if (exLen > 0) {
 
687
          PR_fprintf(PR_STDOUT, " = {\n");
 
688
          print_hex(exLen, hsdata + pos);
 
689
          PR_fprintf(PR_STDOUT, "              }\n");
 
690
      } else {
 
691
          PR_fprintf(PR_STDOUT, "\n");
 
692
      }
 
693
      pos += exLen;
 
694
      exListLen -= 2 + exLen;
 
695
    }
 
696
    PR_fprintf(PR_STDOUT,"            }\n");
 
697
  }
 
698
  return pos;
 
699
}
 
700
 
 
701
 
 
702
void print_ssl3_handshake(unsigned char *tbuf, 
 
703
                          unsigned int   alloclen,
 
704
                          SSLRecord *    sr)
 
705
{
 
706
  struct sslhandshake sslh; 
 
707
  unsigned char *     hsdata;  
 
708
  int                 offset=0;
 
709
 
 
710
  PR_fprintf(PR_STDOUT,"   handshake {\n");
 
711
 
 
712
  while (offset < alloclen) {
 
713
    sslh.type = tbuf[offset]; 
 
714
    sslh.length = GET_24(tbuf+offset+1);
 
715
    hsdata= &tbuf[offset+4];
 
716
 
 
717
    if (sslhexparse) print_hex(4,tbuf+offset);
 
718
 
 
719
    PR_fprintf(PR_STDOUT,"      type = %d (",sslh.type);
 
720
    switch(sslh.type) {
 
721
    case 0:  PR_FPUTS("hello_request)\n"               ); break;
 
722
    case 1:  PR_FPUTS("client_hello)\n"                ); break;
 
723
    case 2:  PR_FPUTS("server_hello)\n"                ); break;
 
724
    case 11: PR_FPUTS("certificate)\n"                 ); break;
 
725
    case 12: PR_FPUTS("server_key_exchange)\n"         ); break;
 
726
    case 13: PR_FPUTS("certificate_request)\n"         ); break;
 
727
    case 14: PR_FPUTS("server_hello_done)\n"           ); break;
 
728
    case 15: PR_FPUTS("certificate_verify)\n"          ); break;
 
729
    case 16: PR_FPUTS("client_key_exchange)\n"         ); break;
 
730
    case 20: PR_FPUTS("finished)\n"                    ); break;
 
731
    default: PR_FPUTS("unknown)\n"                     ); break;
 
732
    }
 
733
 
 
734
    PR_fprintf(PR_STDOUT,"      length = %d (0x%06x)\n",sslh.length,sslh.length);
 
735
    switch (sslh.type) {
 
736
 
 
737
    case 0: /* hello_request */ /* not much to show here. */ break;
 
738
 
 
739
    case 1: /* client hello */
 
740
      switch (sr->ver_maj)  {
 
741
      case 3:  /* ssl version 3 */
 
742
        {
 
743
          unsigned int pos;
 
744
          int w;
 
745
 
 
746
          PR_fprintf(PR_STDOUT,"         ClientHelloV3 {\n");
 
747
          PR_fprintf(PR_STDOUT,"            client_version = {%d, %d}\n",
 
748
                     (PRUint8)hsdata[0],(PRUint8)hsdata[1]);
 
749
          PR_fprintf(PR_STDOUT,"            random = {...}\n");
 
750
          if (sslhexparse) print_hex(32,&hsdata[2]);
 
751
 
 
752
          /* pretty print Session ID */
 
753
          {
 
754
            int sidlength = (int)hsdata[2+32];
 
755
            PR_fprintf(PR_STDOUT,"            session ID = {\n");
 
756
            PR_fprintf(PR_STDOUT,"                length = %d\n",sidlength);
 
757
            PR_fprintf(PR_STDOUT,"                contents = {..}\n");
 
758
            if (sslhexparse) print_hex(sidlength,&hsdata[2+32+1]);
 
759
            PR_fprintf(PR_STDOUT,"            }\n");
 
760
            pos = 2+32+1+sidlength;
 
761
          }
 
762
 
 
763
          /* pretty print cipher suites */
 
764
          {
 
765
            int csuitelength = GET_SHORT((hsdata+pos));
 
766
            PR_fprintf(PR_STDOUT,"            cipher_suites[%d] = { \n",
 
767
                       csuitelength/2);
 
768
            if (csuitelength % 2) {
 
769
              PR_fprintf(PR_STDOUT,
 
770
                 "*error in protocol - csuitelength shouldn't be odd*\n");
 
771
            }
 
772
            for (w=0; w<csuitelength; w+=2) {
 
773
              const char *cs_str=NULL;
 
774
              PRUint32 cs_int=0;
 
775
              cs_int = GET_SHORT((hsdata+pos+2+w));
 
776
              cs_str = V2CipherString(cs_int);
 
777
              PR_fprintf(PR_STDOUT,
 
778
                "                (0x%04x) %s\n", cs_int, cs_str);
 
779
            }
 
780
            pos += 2 + csuitelength;
 
781
            PR_fprintf(PR_STDOUT,"            }\n");
 
782
          }
 
783
 
 
784
          /* pretty print compression methods */
 
785
          {
 
786
            int complength = hsdata[pos];
 
787
            PR_fprintf(PR_STDOUT,"            compression[%d] = {",
 
788
                       complength);
 
789
            for (w=0; w < complength; w++) {
 
790
              PR_fprintf(PR_STDOUT, " %02x", hsdata[pos+1+w]);
 
791
            }
 
792
            pos += 1 + complength;
 
793
            PR_fprintf(PR_STDOUT," }\n");
 
794
          }
 
795
 
 
796
          /* pretty print extensions, if any */
 
797
          pos = print_hello_extension(hsdata, sslh.length, pos);
 
798
 
 
799
          PR_fprintf(PR_STDOUT,"         }\n");
 
800
        } /* end of ssl version 3 */
 
801
        break;
 
802
      default:
 
803
        PR_fprintf(PR_STDOUT,"         UNDEFINED VERSION %d.%d {...}\n",
 
804
                             sr->ver_maj, sr->ver_min );
 
805
        if (sslhexparse) print_hex(sslh.length, hsdata);
 
806
        break;
 
807
      } /* end of switch sr->ver_maj */
 
808
      break;
 
809
 
 
810
    case 2: /* server hello */
 
811
      {
 
812
        unsigned int sidlength, pos;
 
813
 
 
814
        PR_fprintf(PR_STDOUT,"         ServerHello {\n");
 
815
 
 
816
        PR_fprintf(PR_STDOUT,"            server_version = {%d, %d}\n",
 
817
                   (PRUint8)hsdata[0],(PRUint8)hsdata[1]);
 
818
        PR_fprintf(PR_STDOUT,"            random = {...}\n");
 
819
        if (sslhexparse) print_hex(32,&hsdata[2]);
 
820
        PR_fprintf(PR_STDOUT,"            session ID = {\n");
 
821
        sidlength = (int)hsdata[2+32];
 
822
        PR_fprintf(PR_STDOUT,"                length = %d\n",sidlength);
 
823
        PR_fprintf(PR_STDOUT,"                contents = {..}\n");
 
824
        if (sslhexparse) print_hex(sidlength,&hsdata[2+32+1]);
 
825
        PR_fprintf(PR_STDOUT,"            }\n");
 
826
        pos = 2+32+1+sidlength;
 
827
 
 
828
        /* pretty print chosen cipher suite */
 
829
        {
 
830
          PRUint32 cs_int    = GET_SHORT((hsdata+pos));
 
831
          const char *cs_str = V2CipherString(cs_int);
 
832
          PR_fprintf(PR_STDOUT,"            cipher_suite = (0x%04x) %s\n",
 
833
                     cs_int, cs_str);
 
834
          pos += 2;
 
835
        }
 
836
        PR_fprintf(PR_STDOUT,  "            compression method = %02x\n", 
 
837
                   hsdata[pos++]);
 
838
 
 
839
        /* pretty print extensions, if any */
 
840
        pos = print_hello_extension(hsdata, sslh.length, pos);
 
841
 
 
842
        PR_fprintf(PR_STDOUT,"         }\n");
 
843
      }
 
844
      break;
 
845
 
 
846
    case 11: /* certificate */
 
847
      {
 
848
        PRFileDesc *cfd;
 
849
        int         pos;
 
850
        int         certslength;
 
851
        int         certlength;
 
852
        int         certbytesread       = 0;
 
853
        static int  certFileNumber;
 
854
        char        certFileName[20];
 
855
 
 
856
        PR_fprintf(PR_STDOUT,"         CertificateChain {\n");
 
857
        certslength = GET_24(hsdata);
 
858
        PR_fprintf(PR_STDOUT,"            chainlength = %d (0x%04x)\n",
 
859
                certslength,certslength);
 
860
        pos = 3;
 
861
        while (certbytesread < certslength) {
 
862
          certlength = GET_24((hsdata+pos));
 
863
          pos += 3;
 
864
          PR_fprintf(PR_STDOUT,"            Certificate {\n");
 
865
          PR_fprintf(PR_STDOUT,"               size = %d (0x%04x)\n",
 
866
                certlength,certlength);
 
867
 
 
868
          PR_snprintf(certFileName, sizeof certFileName, "cert.%03d",
 
869
                      ++certFileNumber);
 
870
          cfd = PR_Open(certFileName, PR_WRONLY|PR_CREATE_FILE|PR_TRUNCATE, 
 
871
                        0664);
 
872
          if (!cfd) {
 
873
            PR_fprintf(PR_STDOUT,
 
874
                       "               data = { couldn't save file '%s' }\n",
 
875
                       certFileName);
 
876
          } else {
 
877
            PR_Write(cfd, (hsdata+pos), certlength);
 
878
            PR_fprintf(PR_STDOUT,
 
879
                       "               data = { saved in file '%s' }\n",
 
880
                       certFileName);
 
881
            PR_Close(cfd);
 
882
          }
 
883
 
 
884
          PR_fprintf(PR_STDOUT,"            }\n");
 
885
          pos           += certlength;
 
886
          certbytesread += certlength+3;
 
887
        }
 
888
        PR_fprintf(PR_STDOUT,"         }\n");
 
889
      }
 
890
      break;
 
891
 
 
892
    case 12: /* server_key_exchange */                    
 
893
      if (sslhexparse) print_hex(sslh.length, hsdata);
 
894
      break;
 
895
 
 
896
    case 13: /* certificate request */
 
897
      { 
 
898
        unsigned int pos = 0;
 
899
        int w, reqLength;
 
900
 
 
901
        PR_fprintf(PR_STDOUT,"         CertificateRequest {\n");
 
902
 
 
903
        /* pretty print requested certificate types */
 
904
        reqLength = hsdata[pos];
 
905
        PR_fprintf(PR_STDOUT,"            certificate types[%d] = {",
 
906
                   reqLength);
 
907
        for (w=0; w < reqLength; w++) {
 
908
          PR_fprintf(PR_STDOUT, " %02x", hsdata[pos+1+w]);
 
909
        }
 
910
        pos += 1 + reqLength;
 
911
        PR_fprintf(PR_STDOUT," }\n");
 
912
 
 
913
        /* pretty print CA names, if any */
 
914
        if (pos < sslh.length) {
 
915
          int exListLen = GET_SHORT((hsdata+pos)); pos += 2;
 
916
          PR_fprintf(PR_STDOUT,
 
917
                     "            certificate_authorities[%d] = {\n", 
 
918
                     exListLen);
 
919
          while (exListLen > 0 && pos < sslh.length) {
 
920
            char *  ca_name;
 
921
            SECItem it;
 
922
            int     dnLen = GET_SHORT((hsdata+pos)); pos += 2;
 
923
 
 
924
            /* dump the CA name */
 
925
            it.type = siBuffer;
 
926
            it.data = hsdata + pos;
 
927
            it.len  = dnLen;
 
928
            ca_name = CERT_DerNameToAscii(&it);
 
929
            if (ca_name) {
 
930
              PR_fprintf(PR_STDOUT,"   %s\n", ca_name);
 
931
              PORT_Free(ca_name);
 
932
            } else {
 
933
              PR_fprintf(PR_STDOUT,
 
934
                         "              distinguished name [%d]", dnLen);
 
935
              if (dnLen > 0 && sslhexparse) {
 
936
                  PR_fprintf(PR_STDOUT, " = {\n");
 
937
                  print_hex(dnLen, hsdata + pos);
 
938
                  PR_fprintf(PR_STDOUT, "              }\n");
 
939
              } else {
 
940
                  PR_fprintf(PR_STDOUT, "\n");
 
941
              }
 
942
            }
 
943
            pos += dnLen;
 
944
            exListLen -= 2 + dnLen;
 
945
          }
 
946
          PR_fprintf(PR_STDOUT,"            }\n");
 
947
        }
 
948
 
 
949
        PR_fprintf(PR_STDOUT,"         }\n");
 
950
      }
 
951
      break;
 
952
 
 
953
    case 14: /* server_hello_done */ /* not much to show here. */ break;
 
954
 
 
955
    case 15: /* certificate_verify */              
 
956
      if (sslhexparse) print_hex(sslh.length, hsdata);
 
957
      break;
 
958
 
 
959
    case 16: /* client key exchange */
 
960
      {
 
961
        PR_fprintf(PR_STDOUT,"         ClientKeyExchange {\n");
 
962
        PR_fprintf(PR_STDOUT,"            message = {...}\n");
 
963
        PR_fprintf(PR_STDOUT,"         }\n");
 
964
      }
 
965
      break;
 
966
 
 
967
    case 20: /* finished */                      
 
968
      if (sslhexparse) print_hex(sslh.length, hsdata);
 
969
      break;
 
970
 
 
971
    default:
 
972
      {
 
973
        PR_fprintf(PR_STDOUT,"         UNKNOWN MESSAGE TYPE %d [%d] {\n",
 
974
                             sslh.type, sslh.length);
 
975
        if (sslhexparse) print_hex(sslh.length, hsdata);
 
976
        PR_fprintf(PR_STDOUT,"         }\n");
 
977
 
 
978
      }
 
979
    }  /* end of switch sslh.type */
 
980
    offset += sslh.length + 4; /* +4 because of length (3 bytes) and type (1 byte) */
 
981
  } /* while */
 
982
  PR_fprintf(PR_STDOUT,"   }\n");
 
983
}
 
984
 
 
985
 
 
986
void print_ssl(DataBufferList *s, int length, unsigned char *buffer)
 
987
{
 
988
  /* --------------------------------------------------------  */
 
989
  /* first, create a new buffer object for this piece of data. */
 
990
 
 
991
  DataBuffer *db;
 
992
  int i,l;
 
993
 
 
994
  if (s->size == 0 && length > 0 && buffer[0] >= 32 && buffer[0] < 128) {
 
995
    /* Not an SSL record, treat entire buffer as plaintext */
 
996
    PR_Write(PR_STDOUT,buffer,length);
 
997
    return;
 
998
  }
 
999
 
 
1000
 
 
1001
  check_integrity(s);
 
1002
 
 
1003
  i = 0;
 
1004
  l = length;
 
1005
 
 
1006
  db = PR_NEW(struct _DataBuffer);
 
1007
 
 
1008
  db->buffer = (unsigned char*)PR_Malloc(length);
 
1009
  db->length = length;
 
1010
  db->offset = 0;
 
1011
  memcpy(db->buffer, buffer, length);
 
1012
  db->next = NULL;
 
1013
 
 
1014
  /* now, add it to the stream */
 
1015
 
 
1016
  if (s->last != NULL) s->last->next = db;
 
1017
  s->last = db;
 
1018
  s->size += length;
 
1019
  if (s->first == NULL) s->first = db;
 
1020
 
 
1021
  check_integrity(s);
 
1022
 
 
1023
  /*------------------------------------------------------- */
 
1024
  /* now we look at the stream to see if we have enough data to
 
1025
     decode  */
 
1026
 
 
1027
  while (s->size > 0 ) {
 
1028
    unsigned char *tbuf = NULL;
 
1029
 
 
1030
    SSLRecord sr;
 
1031
    unsigned alloclen;
 
1032
    unsigned recordsize;
 
1033
 
 
1034
    check_integrity(s);
 
1035
 
 
1036
    if ( s->first == NULL) {
 
1037
      PR_fprintf(PR_STDOUT,"ERROR: s->first is null\n");
 
1038
      exit(9);
 
1039
    }
 
1040
 
 
1041
    /* in the case of an SSL 2 client-hello (which is all ssltap supports) */
 
1042
    /* will have the high-bit set, whereas an SSL 3 client-hello will not  */
 
1043
    /* SSL2 can also send records that begin with the high bit clear.
 
1044
     * This code will incorrectly handle them. XXX
 
1045
     */
 
1046
    if (isV2Session || s->first->buffer[s->first->offset] & 0x80) {
 
1047
      /* it's an SSL 2 packet */
 
1048
      unsigned char lenbuf[3];
 
1049
 
 
1050
      /* first, we check if there's enough data for it to be an SSL2-type
 
1051
       * record.  What a pain.*/
 
1052
      if (s->size < sizeof lenbuf) {
 
1053
        partial_packet(length, s->size, sizeof lenbuf);
 
1054
        return;
 
1055
      }
 
1056
 
 
1057
      /* read the first two bytes off the stream. */
 
1058
      read_stream_bytes(lenbuf, s, sizeof(lenbuf));
 
1059
      alloclen = ((unsigned int)(lenbuf[0] & 0x7f) << 8) + lenbuf[1] + 
 
1060
                 ((lenbuf[0] & 0x80) ? 2 : 3);
 
1061
      PR_fprintf(PR_STDOUT, "alloclen = %u bytes\n", alloclen);
 
1062
 
 
1063
      /* put 'em back on the head of the stream. */
 
1064
      db = PR_NEW(struct _DataBuffer);
 
1065
 
 
1066
      db->length = sizeof lenbuf;
 
1067
      db->buffer = (unsigned char*) PR_Malloc(db->length);
 
1068
      db->offset = 0;
 
1069
      memcpy(db->buffer, lenbuf, sizeof lenbuf);
 
1070
 
 
1071
      db->next = s->first;
 
1072
      s->first = db;
 
1073
      if (s->last == NULL) 
 
1074
        s->last = db;
 
1075
      s->size += db->length;
 
1076
 
 
1077
      /* if there wasn't enough, go back for more. */
 
1078
      if (s->size < alloclen) {
 
1079
        check_integrity(s);
 
1080
        partial_packet(length, s->size, alloclen);
 
1081
        return;
 
1082
      }
 
1083
      partial_packet(length, s->size, alloclen);
 
1084
 
 
1085
      /* read in the whole record. */
 
1086
      tbuf = PR_Malloc(alloclen);
 
1087
      read_stream_bytes(tbuf, s, alloclen);
 
1088
 
 
1089
      print_sslv2(s, tbuf, alloclen);
 
1090
      PR_FREEIF(tbuf);
 
1091
      check_integrity(s);
 
1092
 
 
1093
      continue;
 
1094
    }
 
1095
 
 
1096
    /***********************************************************/
 
1097
    /* It's SSL v3 */
 
1098
    /***********************************************************/
 
1099
    check_integrity(s);
 
1100
 
 
1101
    if (s->size < sizeof(SSLRecord)) {
 
1102
      partial_packet(length, s->size, sizeof(SSLRecord));
 
1103
      return;
 
1104
    }
 
1105
 
 
1106
    read_stream_bytes((unsigned char *)&sr, s, sizeof sr);
 
1107
 
 
1108
    /* we have read the stream bytes. Look at the length of
 
1109
       the ssl record. If we don't have enough data to satisfy this
 
1110
       request, then put the bytes we just took back at the head
 
1111
       of the queue */
 
1112
    recordsize = GET_SHORT(sr.length);
 
1113
 
 
1114
    if (recordsize > s->size) {
 
1115
      db = PR_NEW(struct _DataBuffer);
 
1116
 
 
1117
      db->length = sizeof sr;
 
1118
      db->buffer = (unsigned char*) PR_Malloc(db->length);
 
1119
      db->offset = 0;
 
1120
      memcpy(db->buffer, &sr, sizeof sr);
 
1121
      db->next = s->first;
 
1122
 
 
1123
      /* now, add it back on to the head of the stream */
 
1124
 
 
1125
      s->first = db;
 
1126
      if (s->last == NULL) 
 
1127
        s->last = db;
 
1128
      s->size += db->length;
 
1129
 
 
1130
      check_integrity(s);
 
1131
      partial_packet(length, s->size, recordsize);
 
1132
      return;
 
1133
    }
 
1134
    partial_packet(length, s->size, recordsize);
 
1135
 
 
1136
 
 
1137
    PR_fprintf(PR_STDOUT,"SSLRecord { [%s]\n", get_time_string() );
 
1138
    if (sslhexparse) {
 
1139
      print_hex(5,(unsigned char*)&sr);
 
1140
    }
 
1141
 
 
1142
    check_integrity(s);
 
1143
 
 
1144
    PR_fprintf(PR_STDOUT,"   type    = %d (",sr.type);
 
1145
    switch(sr.type) {
 
1146
    case 20 :
 
1147
      PR_fprintf(PR_STDOUT,"change_cipher_spec)\n");
 
1148
      break;
 
1149
    case 21 :
 
1150
      PR_fprintf(PR_STDOUT,"alert)\n");
 
1151
      break;
 
1152
    case 22 :
 
1153
      PR_fprintf(PR_STDOUT,"handshake)\n");
 
1154
      break;
 
1155
    case 23 :
 
1156
      PR_fprintf(PR_STDOUT,"application_data)\n");
 
1157
      break;
 
1158
    default:
 
1159
      PR_fprintf(PR_STDOUT,"unknown)\n");
 
1160
      break;
 
1161
    }
 
1162
    PR_fprintf(PR_STDOUT,"   version = { %d,%d }\n",
 
1163
               (PRUint32)sr.ver_maj,(PRUint32)sr.ver_min);
 
1164
    PR_fprintf(PR_STDOUT,"   length  = %d (0x%x)\n",
 
1165
        (PRUint32)GET_SHORT(sr.length), (PRUint32)GET_SHORT(sr.length));
 
1166
 
 
1167
 
 
1168
    alloclen = recordsize;
 
1169
    PR_ASSERT(s->size >= alloclen);
 
1170
    if (s->size >= alloclen) {
 
1171
      tbuf = (unsigned char*) PR_Malloc(alloclen);
 
1172
      read_stream_bytes(tbuf, s, alloclen);
 
1173
 
 
1174
      if (s->isEncrypted) {
 
1175
        PR_fprintf(PR_STDOUT,"            < encrypted >\n");
 
1176
      } else 
 
1177
 
 
1178
      switch(sr.type) {
 
1179
      case 20 : /* change_cipher_spec */
 
1180
        if (sslhexparse) print_hex(alloclen,tbuf);
 
1181
        s->isEncrypted = 1;  /* mark to say we can only dump hex form now on */
 
1182
        break;
 
1183
 
 
1184
      case 21 : /* alert */
 
1185
        switch(tbuf[0]) {
 
1186
        case 1: PR_fprintf(PR_STDOUT, "   warning: "); break;
 
1187
        case 2: PR_fprintf(PR_STDOUT, "   fatal: "); break;
 
1188
        default: PR_fprintf(PR_STDOUT, "   unknown level %d: ", tbuf[0]); break;
 
1189
        }
 
1190
 
 
1191
        switch(tbuf[1]) {
 
1192
        case 0:   PR_FPUTS("close_notify\n"                    ); break;
 
1193
        case 10:  PR_FPUTS("unexpected_message\n"              ); break;
 
1194
        case 20:  PR_FPUTS("bad_record_mac\n"                  ); break;
 
1195
        case 21:  PR_FPUTS("decryption_failed\n"               ); break;
 
1196
        case 22:  PR_FPUTS("record_overflow\n"                 ); break;
 
1197
        case 30:  PR_FPUTS("decompression_failure\n"           ); break;
 
1198
        case 40:  PR_FPUTS("handshake_failure\n"               ); break;
 
1199
        case 41:  PR_FPUTS("no_certificate\n"                  ); break;
 
1200
        case 42:  PR_FPUTS("bad_certificate\n"                 ); break;
 
1201
        case 43:  PR_FPUTS("unsupported_certificate\n"         ); break;
 
1202
        case 44:  PR_FPUTS("certificate_revoked\n"             ); break;
 
1203
        case 45:  PR_FPUTS("certificate_expired\n"             ); break;
 
1204
        case 46:  PR_FPUTS("certificate_unknown\n"             ); break;
 
1205
        case 47:  PR_FPUTS("illegal_parameter\n"               ); break;
 
1206
        case 48:  PR_FPUTS("unknown_ca\n"                      ); break;
 
1207
        case 49:  PR_FPUTS("access_denied\n"                   ); break;
 
1208
        case 50:  PR_FPUTS("decode_error\n"                    ); break;
 
1209
        case 51:  PR_FPUTS("decrypt_error\n"                   ); break;
 
1210
        case 60:  PR_FPUTS("export_restriction\n"              ); break;
 
1211
        case 70:  PR_FPUTS("protocol_version\n"                ); break;
 
1212
        case 71:  PR_FPUTS("insufficient_security\n"           ); break;
 
1213
        case 80:  PR_FPUTS("internal_error\n"                  ); break;
 
1214
        case 90:  PR_FPUTS("user_canceled\n"                   ); break;
 
1215
        case 100: PR_FPUTS("no_renegotiation\n"                ); break;
 
1216
        case 110: PR_FPUTS("unsupported_extension\n"           ); break;
 
1217
        case 111: PR_FPUTS("certificate_unobtainable\n"        ); break;
 
1218
        case 112: PR_FPUTS("unrecognized_name\n"               ); break;
 
1219
        case 113: PR_FPUTS("bad_certificate_status_response\n" ); break;
 
1220
        case 114: PR_FPUTS("bad_certificate_hash_value\n"      ); break;
 
1221
 
 
1222
        default:  PR_fprintf(PR_STDOUT, "unknown alert %d\n", tbuf[1]); break;
 
1223
        }
 
1224
 
 
1225
        if (sslhexparse) print_hex(alloclen,tbuf);
 
1226
        break;
 
1227
 
 
1228
      case 22 : /* handshake */         
 
1229
        print_ssl3_handshake( tbuf, alloclen, &sr );
 
1230
        break;
 
1231
 
 
1232
      case 23 : /* application data */
 
1233
      default:
 
1234
        print_hex(alloclen,tbuf);
 
1235
        break;
 
1236
      }
 
1237
    }
 
1238
    PR_fprintf(PR_STDOUT,"}\n");
 
1239
    PR_FREEIF(tbuf);
 
1240
    check_integrity(s);
 
1241
  }
 
1242
}
 
1243
 
 
1244
void print_hex(int amt, unsigned char *buf) {
 
1245
  int i,j,k;
 
1246
  char t[20];
 
1247
  static char string[5000];
 
1248
 
 
1249
 
 
1250
  for(i=0;i<amt;i++) {
 
1251
    t[1] =0;
 
1252
 
 
1253
    if (i%16 ==0) {  /* if we are at the beginning of a line */
 
1254
      PR_fprintf(PR_STDOUT,"%4x:",i); /* print the line number  */
 
1255
      strcpy(string,"");
 
1256
    }
 
1257
 
 
1258
    if (i%4 == 0) {
 
1259
      PR_fprintf(PR_STDOUT," ");
 
1260
    }
 
1261
 
 
1262
    j = buf[i];
 
1263
 
 
1264
    t[0] = (j >= 0x20 && j < 0x80) ? j : '.';
 
1265
 
 
1266
    if (fancy)  {
 
1267
      switch (t[0]) {
 
1268
      case '<':
 
1269
        strcpy(t,"&lt;");
 
1270
        break;
 
1271
      case '>':
 
1272
        strcpy(t,"&gt;");
 
1273
        break;
 
1274
      case '&':
 
1275
        strcpy(t,"&amp;");
 
1276
        break;
 
1277
      }
 
1278
    }
 
1279
    strcat(string,t);
 
1280
 
 
1281
    PR_fprintf(PR_STDOUT,"%02x ",(PRUint8) buf[i]);
 
1282
 
 
1283
    /* if we've reached the end of the line - add the string */
 
1284
    if (i%16 == 15) PR_fprintf(PR_STDOUT," | %s\n",string);
 
1285
  }
 
1286
  /* we reached the end of the buffer,*/
 
1287
  /* do we have buffer left over? */
 
1288
  j = i%16;
 
1289
  if (j > 0) {
 
1290
    for (k=0;k<(16-j);k++) PR_fprintf(PR_STDOUT,"   ");
 
1291
    PR_fprintf(PR_STDOUT," |%s\n",string);
 
1292
  }
 
1293
}
 
1294
 
 
1295
void Usage(void) {
 
1296
  PR_fprintf(PR_STDERR, "SSLTAP (C) 1997, 1998 Netscape Communications Corporation.\n");
 
1297
  PR_fprintf(PR_STDERR, "Usage: ssltap [-vhfsxl] [-p port] hostname:port\n");
 
1298
  PR_fprintf(PR_STDERR, "   -v      [prints version string]\n");
 
1299
  PR_fprintf(PR_STDERR, "   -h      [outputs hex instead of ASCII]\n");
 
1300
  PR_fprintf(PR_STDERR, "   -f      [turn on Fancy HTML coloring]\n");
 
1301
  PR_fprintf(PR_STDERR, "   -s      [turn on SSL decoding]\n");
 
1302
  PR_fprintf(PR_STDERR, "   -x      [turn on extra SSL hex dumps]\n");
 
1303
  PR_fprintf(PR_STDERR, "   -p port [specify rendezvous port (default 1924)]\n");
 
1304
  PR_fprintf(PR_STDERR, "   -l      [loop - continue to wait for more connections]\n");
 
1305
 
 
1306
 
 
1307
}
 
1308
 
 
1309
void
 
1310
showErr(const char * msg) {
 
1311
  PRErrorCode  err       = PR_GetError();
 
1312
  const char * errString;
 
1313
 
 
1314
  if (err == PR_UNKNOWN_ERROR)
 
1315
    err = PR_CONNECT_RESET_ERROR;       /* bug in NSPR. */
 
1316
  errString = SECU_Strerror(err);
 
1317
 
 
1318
  if (!errString)
 
1319
    errString = "(no text available)";
 
1320
  PR_fprintf(PR_STDERR, "Error %d: %s: %s", err, errString, msg);
 
1321
}
 
1322
 
 
1323
int main(int argc,  char *argv[])
 
1324
{
 
1325
  char *hostname=NULL;
 
1326
  PRUint16 rendport=DEFPORT,port;
 
1327
  PRHostEnt hp;
 
1328
  PRStatus r;
 
1329
  PRNetAddr na_client,na_server,na_rend;
 
1330
  PRFileDesc *s_server,*s_client,*s_rend; /*rendezvous */
 
1331
  char netdbbuf[PR_NETDB_BUF_SIZE];
 
1332
  int c_count=0;
 
1333
  PLOptState *optstate;
 
1334
  PLOptStatus status;
 
1335
  SECStatus   rv;
 
1336
 
 
1337
  optstate = PL_CreateOptState(argc,argv,"fvxhslp:");
 
1338
    while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
 
1339
    switch (optstate->option) {
 
1340
    case 'f':
 
1341
      fancy++;
 
1342
      break;
 
1343
    case 'h':
 
1344
      hexparse++;
 
1345
      break;
 
1346
    case 'v':
 
1347
      PR_fprintf(PR_STDOUT,"Version: %s\n",VERSIONSTRING);
 
1348
      break;
 
1349
    case 's':
 
1350
      sslparse++;
 
1351
      break;
 
1352
    case 'x':
 
1353
      sslhexparse++;
 
1354
      break;
 
1355
    case 'l':
 
1356
      looparound++;
 
1357
      break;
 
1358
    case 'p':
 
1359
      rendport = atoi(optstate->value);
 
1360
      break;
 
1361
    case '\0':
 
1362
      hostname = PL_strdup(optstate->value);
 
1363
    }
 
1364
  }
 
1365
  if (status == PL_OPT_BAD)
 
1366
    Usage();
 
1367
 
 
1368
  if (fancy) {
 
1369
    if (!hexparse && !sslparse) {
 
1370
      PR_fprintf(PR_STDERR,
 
1371
"Note: use of -f without -s or -h not recommended, \n"
 
1372
"as the output looks a little strange. It may be useful, however\n");
 
1373
    }
 
1374
  }
 
1375
 
 
1376
  if(! hostname ) Usage(), exit(2);
 
1377
 
 
1378
  {
 
1379
    char *colon = (char *)strchr(hostname, ':');
 
1380
    if (!colon) {
 
1381
      PR_fprintf(PR_STDERR,
 
1382
      "You must specify the host AND port you wish to connect to\n");
 
1383
      Usage(), exit(3);
 
1384
    }
 
1385
    port = atoi(&colon[1]);
 
1386
    *colon = '\0';
 
1387
 
 
1388
    if (port == 0) {
 
1389
        PR_fprintf(PR_STDERR, "Port must be a nonzero number.\n");
 
1390
        exit(4);
 
1391
      }
 
1392
  }
 
1393
 
 
1394
  /* find the 'server' IP address so we don't have to look it up later */
 
1395
 
 
1396
  if (fancy) {
 
1397
      PR_fprintf(PR_STDOUT,"<HTML><HEAD><TITLE>SSLTAP output</TITLE></HEAD>\n");
 
1398
      PR_fprintf(PR_STDOUT,"<BODY><PRE>\n");
 
1399
    }
 
1400
  PR_fprintf(PR_STDERR,"Looking up \"%s\"...\n", hostname);
 
1401
  r = PR_GetHostByName(hostname,netdbbuf,PR_NETDB_BUF_SIZE,&hp);
 
1402
  if (r) {
 
1403
    showErr("Host Name lookup failed\n");
 
1404
    exit(5);
 
1405
  }
 
1406
 
 
1407
  PR_EnumerateHostEnt(0,&hp,0,&na_server);
 
1408
  PR_InitializeNetAddr(PR_IpAddrNull,port,&na_server);
 
1409
  /* set up the port which the client will connect to */
 
1410
 
 
1411
  r = PR_InitializeNetAddr(PR_IpAddrAny,rendport,&na_rend);
 
1412
  if (r == PR_FAILURE) {
 
1413
    PR_fprintf(PR_STDERR,
 
1414
    "PR_InitializeNetAddr(,%d,) failed with error %d\n",PR_GetError());
 
1415
    exit(0);
 
1416
  }
 
1417
 
 
1418
  rv = NSS_NoDB_Init("");
 
1419
  if (rv != SECSuccess) {
 
1420
    PR_fprintf(PR_STDERR,
 
1421
    "NSS_NoDB_Init() failed with error %d\n",PR_GetError());
 
1422
    exit(5);
 
1423
  }
 
1424
 
 
1425
  s_rend = PR_NewTCPSocket();
 
1426
  if (!s_rend) {
 
1427
    showErr("Couldn't create socket\n");
 
1428
    exit(6);
 
1429
  }
 
1430
 
 
1431
  if (PR_Bind(s_rend, &na_rend )) {
 
1432
    PR_fprintf(PR_STDERR,"Couldn't bind to port %d (error %d)\n",rendport, PR_GetError());
 
1433
    exit(-1);
 
1434
  }
 
1435
 
 
1436
  if ( PR_Listen(s_rend, 5)) {
 
1437
    showErr("Couldn't listen\n");
 
1438
    exit(-1);
 
1439
  }
 
1440
 
 
1441
  PR_fprintf(PR_STDERR,"Proxy socket ready and listening\n");
 
1442
  do {  /* accept one connection and process it. */
 
1443
      PRPollDesc pds[2];
 
1444
 
 
1445
      s_client = PR_Accept(s_rend,&na_client,PR_SecondsToInterval(3600));
 
1446
      if (s_client == NULL) {
 
1447
        showErr("accept timed out\n");
 
1448
        exit(7);
 
1449
      }
 
1450
 
 
1451
      s_server = PR_NewTCPSocket();
 
1452
      if (s_server == NULL) {
 
1453
        showErr("couldn't open new socket to connect to server \n");
 
1454
        exit(8);
 
1455
      }
 
1456
 
 
1457
      r = PR_Connect(s_server,&na_server,PR_SecondsToInterval(5));
 
1458
 
 
1459
      if ( r == PR_FAILURE )
 
1460
        {
 
1461
          showErr("Couldn't connect\n");
 
1462
          return -1;
 
1463
        }
 
1464
 
 
1465
      if (looparound) {
 
1466
        if (fancy)  PR_fprintf(PR_STDOUT,"<p><HR><H2>");
 
1467
        PR_fprintf(PR_STDOUT,"Connection #%d [%s]\n", c_count+1,
 
1468
                             get_time_string());
 
1469
        if (fancy)  PR_fprintf(PR_STDOUT,"</H2>");
 
1470
        }
 
1471
 
 
1472
 
 
1473
      PR_fprintf(PR_STDOUT,"Connected to %s:%d\n", hostname, port);
 
1474
 
 
1475
#define PD_C 0
 
1476
#define PD_S 1
 
1477
 
 
1478
      pds[PD_C].fd = s_client;
 
1479
      pds[PD_S].fd = s_server;
 
1480
      pds[PD_C].in_flags = PR_POLL_READ;
 
1481
      pds[PD_S].in_flags = PR_POLL_READ;
 
1482
 
 
1483
      /* make sure the new connections don't start out encrypted. */
 
1484
      clientstream.isEncrypted = 0;
 
1485
      serverstream.isEncrypted = 0;
 
1486
      isV2Session = 0;
 
1487
 
 
1488
      while( (pds[PD_C].in_flags & PR_POLL_READ) != 0 ||
 
1489
             (pds[PD_S].in_flags & PR_POLL_READ) != 0 )
 
1490
        {  /* Handle all messages on the connection */
 
1491
          PRInt32 amt;
 
1492
          PRInt32 wrote;
 
1493
          unsigned char buffer[ TAPBUFSIZ ];
 
1494
 
 
1495
          amt = PR_Poll(pds,2,PR_INTERVAL_NO_TIMEOUT);
 
1496
          if (amt <= 0) {
 
1497
            if (amt)
 
1498
                showErr( "PR_Poll failed.\n");
 
1499
            else
 
1500
                showErr( "PR_Poll timed out.\n");
 
1501
            break;
 
1502
          }
 
1503
 
 
1504
          if (pds[PD_C].out_flags & PR_POLL_EXCEPT) {
 
1505
            showErr( "Exception on client-side socket.\n");
 
1506
            break;
 
1507
          }
 
1508
 
 
1509
          if (pds[PD_S].out_flags & PR_POLL_EXCEPT) {
 
1510
            showErr( "Exception on server-side socket.\n");
 
1511
            break;
 
1512
          }
 
1513
 
 
1514
 
 
1515
/* read data, copy it to stdout, and write to other socket */
 
1516
 
 
1517
          if ((pds[PD_C].in_flags  & PR_POLL_READ) != 0 &&
 
1518
              (pds[PD_C].out_flags & PR_POLL_READ) != 0 ) {
 
1519
 
 
1520
            amt = PR_Read(s_client, buffer, sizeof(buffer));
 
1521
 
 
1522
            if ( amt < 0)  {
 
1523
              showErr( "Client socket read failed.\n");
 
1524
              break;
 
1525
            }
 
1526
 
 
1527
            if( amt == 0 ) {
 
1528
              PR_fprintf(PR_STDOUT, "Read EOF on Client socket. [%s]\n",
 
1529
                                    get_time_string() );
 
1530
              pds[PD_C].in_flags &= ~PR_POLL_READ;
 
1531
              PR_Shutdown(s_server, PR_SHUTDOWN_SEND);
 
1532
              continue;
 
1533
            }
 
1534
 
 
1535
            PR_fprintf(PR_STDOUT,"--> [\n");
 
1536
            if (fancy) PR_fprintf(PR_STDOUT,"<font color=blue>");
 
1537
 
 
1538
            if (hexparse)  print_hex(amt, buffer);
 
1539
            if (sslparse)  print_ssl(&clientstream,amt,buffer);
 
1540
            if (!hexparse && !sslparse)  PR_Write(PR_STDOUT,buffer,amt);
 
1541
            if (fancy) PR_fprintf(PR_STDOUT,"</font>");
 
1542
            PR_fprintf(PR_STDOUT,"]\n");
 
1543
 
 
1544
            wrote = PR_Write(s_server, buffer, amt);
 
1545
            if (wrote != amt )  {
 
1546
              if (wrote < 0) {
 
1547
                showErr("Write to server socket failed.\n");
 
1548
                break;
 
1549
              } else {
 
1550
                PR_fprintf(PR_STDERR, "Short write to server socket!\n");
 
1551
              }
 
1552
            }
 
1553
          }  /* end of read from client socket. */
 
1554
 
 
1555
/* read data, copy it to stdout, and write to other socket */
 
1556
          if ((pds[PD_S].in_flags  & PR_POLL_READ) != 0 &&
 
1557
              (pds[PD_S].out_flags & PR_POLL_READ) != 0 ) {
 
1558
 
 
1559
            amt = PR_Read(s_server, buffer, sizeof(buffer));
 
1560
 
 
1561
            if ( amt < 0)  {
 
1562
              showErr( "error on server-side socket.\n");
 
1563
              break;
 
1564
            }
 
1565
 
 
1566
            if( amt == 0 ) {
 
1567
              PR_fprintf(PR_STDOUT, "Read EOF on Server socket. [%s]\n",
 
1568
                                    get_time_string() );
 
1569
              pds[PD_S].in_flags &= ~PR_POLL_READ;
 
1570
              PR_Shutdown(s_client, PR_SHUTDOWN_SEND);
 
1571
              continue;
 
1572
            } 
 
1573
 
 
1574
            PR_fprintf(PR_STDOUT,"<-- [\n");
 
1575
            if (fancy) PR_fprintf(PR_STDOUT,"<font color=red>");
 
1576
            if (hexparse)  print_hex(amt, (unsigned char *)buffer);
 
1577
            if (sslparse)  print_ssl(&serverstream,amt,(unsigned char *)buffer);
 
1578
            if (!hexparse && !sslparse)  PR_Write(PR_STDOUT,buffer,amt);
 
1579
            if (fancy) PR_fprintf(PR_STDOUT,"</font>");
 
1580
            PR_fprintf(PR_STDOUT,"]\n");
 
1581
 
 
1582
 
 
1583
            wrote = PR_Write(s_client, buffer, amt);
 
1584
            if (wrote != amt )  {
 
1585
              if (wrote < 0) {
 
1586
                showErr("Write to client socket failed.\n");
 
1587
                break;
 
1588
              } else {
 
1589
                PR_fprintf(PR_STDERR, "Short write to client socket!\n");
 
1590
              }
 
1591
            }
 
1592
 
 
1593
          } /* end of read from server socket. */
 
1594
 
 
1595
/* Loop, handle next message. */
 
1596
 
 
1597
        }       /* handle messages during a connection loop */
 
1598
      PR_Close(s_client);
 
1599
      PR_Close(s_server);
 
1600
      flush_stream(&clientstream);
 
1601
      flush_stream(&serverstream);
 
1602
 
 
1603
      c_count++;
 
1604
      PR_fprintf(PR_STDERR,"Connection %d Complete [%s]\n", c_count,
 
1605
                            get_time_string() );
 
1606
    }  while (looparound); /* accept connection and process it. */
 
1607
    PR_Close(s_rend);
 
1608
    NSS_Shutdown();
 
1609
    return 0;
 
1610
}