Bug 294537: ssltap should display ASCII CA names from cert request message
authornelson%bolyard.com
Tue, 25 Apr 2006 04:58:45 +0000
changeset 6941 fa63be68ccf88bd779589e83952c565ff3f57322
parent 6940 8605ce12bc7bcf66df455bc6ecf508ed1b321055
child 6942 9f54cf30768966ad00845080067f9c721b67d26c
push idunknown
push userunknown
push dateunknown
bugs294537
Bug 294537: ssltap should display ASCII CA names from cert request message r=alexei.volkov
security/nss/cmd/ssltap/ssltap.c
--- a/security/nss/cmd/ssltap/ssltap.c
+++ b/security/nss/cmd/ssltap/ssltap.c
@@ -57,16 +57,18 @@
 #include "nspr.h"
 #include "plstr.h"
 #include "secutil.h"
 #include <memory.h>	/* for memcpy, etc. */
 #include <string.h>
 #include <time.h>
 
 #include "plgetopt.h"
+#include "nss.h"
+#include "cert.h"
 
 #define VERSIONSTRING "$Revision$ ($Date$) $Author$"
 
 
 struct _DataBufferList;
 struct _DataBuffer;
 
 typedef struct _DataBufferList {
@@ -659,17 +661,47 @@ eosh:
     PR_fprintf(PR_STDOUT," [ssl2]  UnknownType 0x%02x {...}\n",
 	  (PRUint32)chv2->type);
     break;
   }
 }
 
 
 
-
+unsigned int print_hello_extension(unsigned char *  hsdata,
+				   unsigned int     length,
+				   unsigned int     pos)
+{
+  /* pretty print extensions, if any */
+  if (pos < length) {
+    int exListLen = GET_SHORT((hsdata+pos)); pos += 2;
+    PR_fprintf(PR_STDOUT,
+	       "            extensions[%d] = {\n", exListLen);
+    while (exListLen > 0 && pos < length) {
+      int exLen;
+      int exType = GET_SHORT((hsdata+pos)); pos += 2;
+      exLen = GET_SHORT((hsdata+pos)); pos += 2;
+      /* dump the extension */
+      PR_fprintf(PR_STDOUT,
+		 "              extension type %s, length [%d]",
+		 helloExtensionNameString(exType), exLen);
+      if (exLen > 0) {
+	  PR_fprintf(PR_STDOUT, " = {\n");
+	  print_hex(exLen, hsdata + pos);
+	  PR_fprintf(PR_STDOUT, "              }\n");
+      } else {
+	  PR_fprintf(PR_STDOUT, "\n");
+      }
+      pos += exLen;
+      exListLen -= 2 + exLen;
+    }
+    PR_fprintf(PR_STDOUT,"            }\n");
+  }
+  return pos;
+}
 
 
 void print_ssl3_handshake(unsigned char *tbuf, 
                           unsigned int   alloclen,
                           SSLRecord *    sr)
 {
   struct sslhandshake sslh; 
   unsigned char *     hsdata;  
@@ -697,16 +729,18 @@ void print_ssl3_handshake(unsigned char 
     case 16: PR_FPUTS("client_key_exchange)\n"         ); break;
     case 20: PR_FPUTS("finished)\n"                    ); break;
     default: PR_FPUTS("unknown)\n"                     ); break;
     }
 
     PR_fprintf(PR_STDOUT,"      length = %d (0x%06x)\n",sslh.length,sslh.length);
     switch (sslh.type) {
 
+    case 0: /* hello_request */ /* not much to show here. */ break;
+
     case 1: /* client hello */
       switch (sr->ver_maj)  {
       case 3:  /* ssl version 3 */
 	{
 	  unsigned int pos;
 	  int w;
 
 	  PR_fprintf(PR_STDOUT,"         ClientHelloV3 {\n");
@@ -755,36 +789,17 @@ void print_ssl3_handshake(unsigned char 
 	    for (w=0; w < complength; w++) {
 	      PR_fprintf(PR_STDOUT, " %02x", hsdata[pos+1+w]);
 	    }
 	    pos += 1 + complength;
 	    PR_fprintf(PR_STDOUT," }\n");
 	  }
 
 	  /* pretty print extensions, if any */
-	  if (pos < sslh.length) {
-	    int exListLen = GET_SHORT((hsdata+pos)); pos += 2;
-	    PR_fprintf(PR_STDOUT,
-	               "            extensions[%d] = {\n", exListLen);
-	    while (exListLen > 0 && pos < sslh.length) {
-	      int exLen;
-	      int exType = GET_SHORT((hsdata+pos)); pos += 2;
-	      exLen = GET_SHORT((hsdata+pos)); pos += 2;
-	      /* dump the extension */
-	      PR_fprintf(PR_STDOUT,
-	                 "              extension type %s, length [%d] = {\n",
-			 helloExtensionNameString(exType), exLen);
-	      print_hex(exLen, hsdata + pos);
-	      PR_fprintf(PR_STDOUT,
-	                 "              }\n");
-              pos += exLen;
-	      exListLen -= 2 + exLen;
-	    }
-	    PR_fprintf(PR_STDOUT,"                 }\n");
-	  }
+	  pos = print_hello_extension(hsdata, sslh.length, pos);
 
 	  PR_fprintf(PR_STDOUT,"         }\n");
 	} /* end of ssl version 3 */
 	break;
       default:
 	PR_fprintf(PR_STDOUT,"         UNDEFINED VERSION %d.%d {...}\n",
 	                     sr->ver_maj, sr->ver_min );
 	if (sslhexparse) print_hex(sslh.length, hsdata);
@@ -817,43 +832,22 @@ void print_ssl3_handshake(unsigned char 
 	  PR_fprintf(PR_STDOUT,"            cipher_suite = (0x%04x) %s\n",
 		     cs_int, cs_str);
 	  pos += 2;
 	}
 	PR_fprintf(PR_STDOUT,  "            compression method = %02x\n", 
 		   hsdata[pos++]);
 
 	/* pretty print extensions, if any */
-	if (pos < sslh.length) {
-	  int exListLen = GET_SHORT((hsdata+pos)); pos += 2;
-	  PR_fprintf(PR_STDOUT,
-		     "            extensions[%d] = {\n", exListLen);
-	  while (exListLen > 0 && pos < sslh.length) {
-	    int exLen;
-	    int exType = GET_SHORT((hsdata+pos)); pos += 2;
-	    exLen = GET_SHORT((hsdata+pos)); pos += 2;
-	    /* dump the extension */
-	    PR_fprintf(PR_STDOUT,
-		       "              extension type %s, length [%d] = {\n",
-		       helloExtensionNameString(exType), exLen);
-	    print_hex(exLen, hsdata + pos);
-	    PR_fprintf(PR_STDOUT,
-		       "              }\n");
-	    pos += exLen;
-	    exListLen -= 2 + exLen;
-	  }
-	  PR_fprintf(PR_STDOUT,"                 }\n");
-	}
+	pos = print_hello_extension(hsdata, sslh.length, pos);
 
 	PR_fprintf(PR_STDOUT,"         }\n");
       }
       break;
 
-
-
     case 11: /* certificate */
       {
 	PRFileDesc *cfd;
 	int         pos;
 	int         certslength;
 	int         certlength;
 	int         certbytesread	= 0;
 	static int  certFileNumber;
@@ -890,32 +884,103 @@ void print_ssl3_handshake(unsigned char 
 	  PR_fprintf(PR_STDOUT,"            }\n");
 	  pos           += certlength;
 	  certbytesread += certlength+3;
 	}
 	PR_fprintf(PR_STDOUT,"         }\n");
       }
       break;
 
+    case 12: /* server_key_exchange */                    
+      if (sslhexparse) print_hex(sslh.length, hsdata);
+      break;
+
     case 13: /* certificate request */
-      if (sslhexparse) { 
+      { 
+	unsigned int pos = 0;
+	int w, reqLength;
+
 	PR_fprintf(PR_STDOUT,"         CertificateRequest {\n");
-        print_hex(sslh.length, hsdata);
+
+	/* pretty print requested certificate types */
+	reqLength = hsdata[pos];
+	PR_fprintf(PR_STDOUT,"            certificate types[%d] = {",
+		   reqLength);
+	for (w=0; w < reqLength; w++) {
+	  PR_fprintf(PR_STDOUT, " %02x", hsdata[pos+1+w]);
+	}
+	pos += 1 + reqLength;
+	PR_fprintf(PR_STDOUT," }\n");
+
+	/* pretty print CA names, if any */
+	if (pos < sslh.length) {
+	  int exListLen = GET_SHORT((hsdata+pos)); pos += 2;
+	  PR_fprintf(PR_STDOUT,
+		     "            certificate_authorities[%d] = {\n", 
+		     exListLen);
+	  while (exListLen > 0 && pos < sslh.length) {
+	    char *  ca_name;
+	    SECItem it;
+	    int     dnLen = GET_SHORT((hsdata+pos)); pos += 2;
+
+	    /* dump the CA name */
+	    it.type = siBuffer;
+	    it.data = hsdata + pos;
+	    it.len  = dnLen;
+	    ca_name = CERT_DerNameToAscii(&it);
+	    if (ca_name) {
+	      PR_fprintf(PR_STDOUT,"   %s\n", ca_name);
+	      PORT_Free(ca_name);
+	    } else {
+	      PR_fprintf(PR_STDOUT,
+			 "              distinguished name [%d]", dnLen);
+	      if (dnLen > 0 && sslhexparse) {
+		  PR_fprintf(PR_STDOUT, " = {\n");
+		  print_hex(dnLen, hsdata + pos);
+		  PR_fprintf(PR_STDOUT, "              }\n");
+	      } else {
+		  PR_fprintf(PR_STDOUT, "\n");
+	      }
+            }
+	    pos += dnLen;
+	    exListLen -= 2 + dnLen;
+	  }
+	  PR_fprintf(PR_STDOUT,"            }\n");
+	}
+
 	PR_fprintf(PR_STDOUT,"         }\n");
       }
       break;
 
+    case 14: /* server_hello_done */ /* not much to show here. */ break;
+
+    case 15: /* certificate_verify */	           
+      if (sslhexparse) print_hex(sslh.length, hsdata);
+      break;
+
     case 16: /* client key exchange */
       {
 	PR_fprintf(PR_STDOUT,"         ClientKeyExchange {\n");
 	PR_fprintf(PR_STDOUT,"            message = {...}\n");
 	PR_fprintf(PR_STDOUT,"         }\n");
       }
       break;
 
+    case 20: /* finished */			 
+      if (sslhexparse) print_hex(sslh.length, hsdata);
+      break;
+
+    default:
+      {
+	PR_fprintf(PR_STDOUT,"         UNKNOWN MESSAGE TYPE %d [%d] {\n",
+	                     sslh.type, sslh.length);
+	if (sslhexparse) print_hex(sslh.length, hsdata);
+	PR_fprintf(PR_STDOUT,"         }\n");
+
+      }
     }  /* end of switch sslh.type */
     offset += sslh.length + 4; /* +4 because of length (3 bytes) and type (1 byte) */
   } /* while */
   PR_fprintf(PR_STDOUT,"   }\n");
 }
 
 
 void print_ssl(DataBufferList *s, int length, unsigned char *buffer)
@@ -1262,16 +1327,17 @@ int main(int argc,  char *argv[])
   PRHostEnt hp;
   PRStatus r;
   PRNetAddr na_client,na_server,na_rend;
   PRFileDesc *s_server,*s_client,*s_rend; /*rendezvous */
   char netdbbuf[PR_NETDB_BUF_SIZE];
   int c_count=0;
   PLOptState *optstate;
   PLOptStatus status;
+  SECStatus   rv;
 
   optstate = PL_CreateOptState(argc,argv,"fvxhslp:");
     while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
     switch (optstate->option) {
     case 'f':
       fancy++;
       break;
     case 'h':
@@ -1344,16 +1410,22 @@ int main(int argc,  char *argv[])
 
   r = PR_InitializeNetAddr(PR_IpAddrAny,rendport,&na_rend);
   if (r == PR_FAILURE) {
     PR_fprintf(PR_STDERR,
     "PR_InitializeNetAddr(,%d,) failed with error %d\n",PR_GetError());
     exit(0);
   }
 
+  rv = NSS_NoDB_Init("");
+  if (rv != SECSuccess) {
+    PR_fprintf(PR_STDERR,
+    "NSS_NoDB_Init() failed with error %d\n",PR_GetError());
+    exit(5);
+  }
 
   s_rend = PR_NewTCPSocket();
   if (!s_rend) {
     showErr("Couldn't create socket\n");
     exit(6);
   }
 
   if (PR_Bind(s_rend, &na_rend )) {
@@ -1528,10 +1600,11 @@ int main(int argc,  char *argv[])
       flush_stream(&clientstream);
       flush_stream(&serverstream);
 
       c_count++;
       PR_fprintf(PR_STDERR,"Connection %d Complete [%s]\n", c_count,
                             get_time_string() );
     }  while (looparound); /* accept connection and process it. */
     PR_Close(s_rend);
+    NSS_Shutdown();
     return 0;
 }