ssltap.c

来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 1,340 行 · 第 1/3 页

C
1,340
字号
/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ *  * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. *  * The Original Code is the Netscape security libraries. *  * The Initial Developer of the Original Code is Netscape * Communications Corporation.  Portions created by Netscape are  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All * Rights Reserved. *  * Contributor(s): *  * Alternatively, the contents of this file may be used under the * terms of the GNU General Public License Version 2 or later (the * "GPL"), in which case the provisions of the GPL are applicable  * instead of those above.  If you wish to allow use of your  * version of this file only under the terms of the GPL and not to * allow others to use your version of this file under the MPL, * indicate your decision by deleting the provisions above and * replace them with the notice and other provisions required by * the GPL.  If you do not delete the provisions above, a recipient * may use your version of this file under either the MPL or the * GPL. *//* * ssltap.c * * Version 1.0 : Frederick Roeber : 11 June 1997 * Version 2.0 : Steve Parkinson  : 13 November 1997 * Version 3.0 : Nelson Bolyard   : 22 July 1998 * Version 3.1 : Nelson Bolyard   : 24 May  1999 * * changes in version 2.0: *  Uses NSPR20 *  Shows structure of SSL negotiation, if enabled. * * This "proxies" a socket connection (like a socks tunnel), but displays the * data is it flies by. * * In the code, the 'client' socket is the one on the client side of the * proxy, and the server socket is on the server side. * */#include "nspr.h"#include "plstr.h"#include "secutil.h"#include <memory.h>	/* for memcpy, etc. */#include <string.h>#include <time.h>#include "plgetopt.h"#define VERSIONSTRING "$Revision: 1.1 $ ($Date: 2000/03/31 20:12:54 $) $Author: relyea%netscape.com $"struct _DataBufferList;struct _DataBuffer;typedef struct _DataBufferList {  struct _DataBuffer *first,*last;  int size;  int isEncrypted;} DataBufferList;typedef struct _DataBuffer {  unsigned char *buffer;  int length;  int offset;  /* offset of first good byte */  struct _DataBuffer *next;} DataBuffer;DataBufferList  clientstream = {NULL, NULL, 0, 0},  serverstream = {NULL, NULL, 0, 0};struct sslhandshake {  PRUint8 type;  PRUint32 length;};typedef struct _SSLRecord {  PRUint8 type;  PRUint8 ver_maj,ver_min;  PRUint8 length[2];} SSLRecord;typedef struct _ClientHelloV2 {  PRUint8 length[2];  PRUint8 type;  PRUint8 version[2];  PRUint8 cslength[2];  PRUint8 sidlength[2];  PRUint8 rndlength[2];  PRUint8 csuites[1];} ClientHelloV2;typedef struct _ServerHelloV2 {  PRUint8 length[2];  PRUint8 type;  PRUint8 sidhit;  PRUint8 certtype;  PRUint8 version[2];  PRUint8 certlength[2];  PRUint8 cslength[2];  PRUint8 cidlength[2];} ServerHelloV2;typedef struct _ClientMasterKeyV2 {  PRUint8 length[2];  PRUint8 type;  PRUint8 cipherkind[3];  PRUint8 clearkey[2];  PRUint8 secretkey[2];} ClientMasterKeyV2;#define TAPBUFSIZ 16384#define DEFPORT 1924#include <ctype.h>int hexparse=0;int sslparse=0;int sslhexparse=0;int looparound=0;int fancy=0;int isV2Session=0;#define GET_SHORT(x) ((PRUint16)(((PRUint16)((PRUint8*)x)[0]) << 8) + ((PRUint16)((PRUint8*)x)[1]))#define GET_24(x) ((PRUint32)   (  \				 (((PRUint32)((PRUint8*)x)[0]) << 16) \				 +                          \				 (((PRUint32)((PRUint8*)x)[1]) << 8)  \				 +                          \				 (((PRUint32)((PRUint8*)x)[2]) << 0)  \				 ) )void print_hex(int amt, unsigned char *buf);void read_stream_bytes(unsigned char *d, DataBufferList *db, int length);void myhalt(int dblsize,int collectedsize) {  while(1) ;}const char *get_error_text(int error) {  switch (error) {  case PR_IO_TIMEOUT_ERROR:    return "Timeout";    break;  case PR_CONNECT_REFUSED_ERROR:    return "Connection refused";    break;  case PR_NETWORK_UNREACHABLE_ERROR:    return "Network unreachable";    break;  case PR_BAD_ADDRESS_ERROR:    return "Bad address";    break;  case PR_CONNECT_RESET_ERROR:    return "Connection reset";    break;  case PR_PIPE_ERROR:    return "Pipe error";    break;  }  return "";}void check_integrity(DataBufferList *dbl) {  DataBuffer *db;  int i;  db = dbl->first;  i =0;  while (db) {    i+= db->length - db->offset;    db = db->next;  }  if (i != dbl->size) {    myhalt(dbl->size,i);  }}/* Free's the DataBuffer at the head of the list and returns the pointer * to the new head of the list. */DataBuffer * free_head(DataBufferList *dbl){  DataBuffer *db       = dbl->first;  PR_ASSERT(db->offset >= db->length);  if (db->offset >= db->length) {    dbl->first = db->next;    if (dbl->first == NULL) {      dbl->last = NULL;    }    PR_Free(db->buffer);    PR_Free(db);    db = dbl->first;  }  return db;}void read_stream_bytes(unsigned char *d, DataBufferList *dbl, int length) {  int         copied 	= 0;  DataBuffer *db	= dbl->first;  if (!db) {    PR_fprintf(PR_STDERR,"assert failed - dbl->first is null\n");    exit(8);  }  while (length) {    int         toCopy;    /* find the number of bytes to copy from the head buffer */    /* if there's too many in this buffer, then only copy 'length' */    toCopy = PR_MIN(db->length - db->offset, length);    memcpy(d + copied, db->buffer + db->offset, toCopy);    copied     += toCopy;    db->offset += toCopy;    length     -= toCopy;    dbl->size  -= toCopy;    /* if we emptied the head buffer */    if (db->offset >= db->length) {      db = free_head(dbl);    }  }  check_integrity(dbl);}voidflush_stream(DataBufferList *dbl){    DataBuffer *db = dbl->first;    check_integrity(dbl);    while (db) {	db->offset = db->length;    	db = free_head(dbl);    }    dbl->size = 0;    check_integrity(dbl);}const char * V2CipherString(int cs_int) {  char *cs_str;  cs_str = NULL;  switch (cs_int) {  case 0x010080:    cs_str = "SSL2/RSA/RC4-128/MD5";       break;  case 0x020080:    cs_str = "SSL2/RSA/RC4-40/MD5";    break;  case 0x030080:    cs_str = "SSL2/RSA/RC2CBC128/MD5";     break;  case 0x040080:    cs_str = "SSL2/RSA/RC2CBC40/MD5";  break;  case 0x050080:    cs_str = "SSL2/RSA/IDEA128CBC/MD5";    break;  case 0x060040:    cs_str = "SSL2/RSA/DES56-CBC/MD5";      break;  case 0x0700C0:    cs_str = "SSL2/RSA/3DES192EDE-CBC/MD5"; break;  case 0x000001:    cs_str = "SSL3/RSA/NULL/MD5";             break;  case 0x000002:    cs_str = "SSL3/RSA/NULL/SHA";             break;  case 0x000003:    cs_str = "SSL3/RSA/RC4-40/MD5";       break;  case 0x000004:    cs_str = "SSL3/RSA/RC4-128/MD5";          break;  case 0x000005:    cs_str = "SSL3/RSA/RC4-128/SHA";          break;  case 0x000006:    cs_str = "SSL3/RSA/RC2CBC40/MD5";     break;  case 0x000007:    cs_str = "SSL3/RSA/IDEA128CBC/SHA";       break;  case 0x000008:    cs_str = "SSL3/RSA/DES40-CBC/SHA";         break;  case 0x000009:    cs_str = "SSL3/RSA/DES56-CBC/SHA";         break;  case 0x00000A:    cs_str = "SSL3/RSA/3DES192EDE-CBC/SHA";    break;  case 0x00000B:    cs_str = "SSL3/DH-DSS/DES40-CBC/SHA";      break;  case 0x00000C:    cs_str = "SSL3/DH_DSS/DES56-CBC/SHA";      break;  case 0x00000D:    cs_str = "SSL3/DH-DSS/DES192EDE3CBC/SHA"; break;  case 0x00000E:    cs_str = "SSL3/DH-RSA/DES40-CBC/SHA";      break;  case 0x00000F:    cs_str = "SSL3/DH_RSA/DES56-CBC/SHA";      break;  case 0x000010:    cs_str = "SSL3/DH-RSA/3DES192EDE-CBC/SHA"; break;  case 0x000011:    cs_str = "SSL3/DHE-DSS/DES40-CBC/SHA";      break;  case 0x000012:    cs_str = "SSL3/DHE_DSS/DES56-CBC/SHA";      break;  case 0x000013:    cs_str = "SSL3/DHE-DSS/DES192EDE3CBC/SHA"; break;  case 0x000014:    cs_str = "SSL3/DHE-RSA/DES40-CBC/SHA";      break;  case 0x000015:    cs_str = "SSL3/DHE_RSA/DES56-CBC/SHA";      break;  case 0x000016:    cs_str = "SSL3/DHE-RSA/3DES192EDE-CBC/SHA"; break;  case 0x000017:    cs_str = "SSL3/DH-anon/RC4-40/MD5";     break;  case 0x000018:    cs_str = "SSL3/DH-anon/RC4-128/MD5";        break;  case 0x000019:    cs_str = "SSL3/DH-anon/DES40-CBC/SHA";       break;  case 0x00001A:    cs_str = "SSL3/DH-anon/DES56-CBC/SHA";       break;  case 0x00001B:    cs_str = "SSL3/DH-anon/3DES192EDE-CBC/SHA"; break;  case 0x00001C:    cs_str = "SSL3/FORTEZZA-DMS/NULL/SHA";      break;  case 0x00001D:    cs_str = "SSL3/FORTEZZA-DMS/FORTEZZA-CBC/SHA";  break;  case 0x00001E:    cs_str = "SSL3/FORTEZZA-DMS/RC4-128/SHA";  break;  case 0x000062:    cs_str = "TLS/RSA_EXPORT1024/DES56_CBC/SHA";   break;  case 0x000064:    cs_str = "TLS/RSA_EXPORT1024/RC4-56/SHA";	   break;  case 0x000063:    cs_str = "TLS/DHE-DSS_EXPORT1024/DES56-CBC/SHA"; break;  case 0x000065:    cs_str = "TLS/DHE-DSS_EXPORT1024/RC4-56/SHA";  break;  case 0x000066:    cs_str = "TLS/DHE-DSS/RC4-128/SHA";		   break;  case 0x00ffe1:    cs_str = "SSL3/RSA-FIPS/DES56-CBC/SHA";         break;  case 0x00ffe0:    cs_str = "SSL3/RSA-FIPS/3DES192EDE-CBC/SHA";    break;  default:          cs_str = "????/????????/?????????/???";     break;  }  return cs_str;}void partial_packet(int thispacket, int size, int needed){  PR_fprintf(PR_STDOUT,"(%u bytes", thispacket);  if (thispacket < needed) {    PR_fprintf(PR_STDOUT,", making %u", size);  }  PR_fprintf(PR_STDOUT," of %u", needed);  if (size > needed) {    PR_fprintf(PR_STDOUT,", with %u left over", size - needed);  }  PR_fprintf(PR_STDOUT,")\n");}char * get_time_string(void){  struct tm *tm;  char      *cp;  char      *eol;  time_t     tt;  time(&tt);#if 0  tm = localtime(&tt);  cp = asctime(tm);#else  cp = ctime(&tt);#endif  eol = strchr(cp, '\n');  if (eol)     *eol = 0;  return cp;}void print_sslv2(DataBufferList *s, unsigned char *tbuf, unsigned int alloclen){  ClientHelloV2 *chv2;  ServerHelloV2 *shv2;  unsigned char *pos;  unsigned int   p;  unsigned int   q;  PRUint32       len;  chv2 = (ClientHelloV2 *)tbuf;  shv2 = (ServerHelloV2 *)tbuf;  if (s->isEncrypted) {    PR_fprintf(PR_STDOUT," [ssl2]  Encrypted {...}\n");    return;  }  PR_fprintf(PR_STDOUT," [%s]", get_time_string() );  switch(chv2->type) {  case 1:    PR_fprintf(PR_STDOUT," [ssl2]  ClientHelloV2 {\n");    PR_fprintf(PR_STDOUT,"           version = {0x%02x, 0x%02x}\n",	       (PRUint32)chv2->version[0],(PRUint32)chv2->version[1]);    PR_fprintf(PR_STDOUT,"           cipher-specs-length = %d (0x%02x)\n",	       (PRUint32)(GET_SHORT((chv2->cslength))),	       (PRUint32)(GET_SHORT((chv2->cslength))));    PR_fprintf(PR_STDOUT,"           sid-length = %d (0x%02x)\n",	       (PRUint32)(GET_SHORT((chv2->sidlength))),	       (PRUint32)(GET_SHORT((chv2->sidlength))));    PR_fprintf(PR_STDOUT,"           challenge-length = %d (0x%02x)\n",	       (PRUint32)(GET_SHORT((chv2->rndlength))),	       (PRUint32)(GET_SHORT((chv2->rndlength))));    PR_fprintf(PR_STDOUT,"           cipher-suites = { \n");    for (p=0;p<GET_SHORT((chv2->cslength));p+=3) {      const char *cs_str=NULL;      PRUint32 cs_int=0;      cs_int = GET_24((&chv2->csuites[p]));      cs_str = V2CipherString(cs_int);      PR_fprintf(PR_STDOUT,"                (0x%06x) %s\n",		  cs_int, cs_str);    }    q = p;    PR_fprintf(PR_STDOUT,"                }\n");    if (chv2->sidlength) {      PR_fprintf(PR_STDOUT,"           session-id = { ");      for (p=0;p<GET_SHORT((chv2->sidlength));p+=2) {	PR_fprintf(PR_STDOUT,"0x%04x ",(PRUint32)(GET_SHORT((&chv2->csuites[p+q]))));      }    }    q += p;    PR_fprintf(PR_STDOUT,"}\n");    if (chv2->rndlength) {      PR_fprintf(PR_STDOUT,"           challenge = { ");      for (p=0;p<GET_SHORT((chv2->rndlength));p+=2) {	PR_fprintf(PR_STDOUT,"0x%04x ",(PRUint32)(GET_SHORT((&chv2->csuites[p+q]))));      }      PR_fprintf(PR_STDOUT,"}\n");    }    PR_fprintf(PR_STDOUT,"}\n");    break;    /* end of V2 CLientHello Parsing */  case 2:  /* Client Master Key  */    {    const char *cs_str=NULL;    PRUint32 cs_int=0;    ClientMasterKeyV2 *cmkv2;    cmkv2 = (ClientMasterKeyV2 *)chv2;    isV2Session = 1;    PR_fprintf(PR_STDOUT," [ssl2]  ClientMasterKeyV2 { \n");    cs_int = GET_24(&cmkv2->cipherkind[0]);    cs_str = V2CipherString(cs_int);    PR_fprintf(PR_STDOUT,"         cipher-spec-chosen = (0x%06x) %s\n",	       cs_int, cs_str);    PR_fprintf(PR_STDOUT,"         clear-portion = %d bits\n",	       8*(PRUint32)(GET_SHORT((cmkv2->clearkey))));    PR_fprintf(PR_STDOUT,"      }\n");    clientstream.isEncrypted = 1;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?