Home | History | Annotate | Download | only in ssl
      1 /*
      2  * Functions to trace SSL protocol behavior in DEBUG builds.
      3  *
      4  * This Source Code Form is subject to the terms of the Mozilla Public
      5  * License, v. 2.0. If a copy of the MPL was not distributed with this
      6  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      7 #include <stdarg.h>
      8 #include "cert.h"
      9 #include "ssl.h"
     10 #include "sslimpl.h"
     11 #include "sslproto.h"
     12 #include "prprf.h"
     13 
     14 #if defined(DEBUG) || defined(TRACE)
     15 static const char *hex = "0123456789abcdef";
     16 
     17 static const char printable[257] = {
     18 	"................"	/* 0x */
     19 	"................"	/* 1x */
     20 	" !\"#$%&'()*+,-./"	/* 2x */
     21 	"0123456789:;<=>?"	/* 3x */
     22 	"@ABCDEFGHIJKLMNO"	/* 4x */
     23 	"PQRSTUVWXYZ[\\]^_"	/* 5x */
     24 	"`abcdefghijklmno"	/* 6x */
     25 	"pqrstuvwxyz{|}~."	/* 7x */
     26 	"................"	/* 8x */
     27 	"................"	/* 9x */
     28 	"................"	/* ax */
     29 	"................"	/* bx */
     30 	"................"	/* cx */
     31 	"................"	/* dx */
     32 	"................"	/* ex */
     33 	"................"	/* fx */
     34 };
     35 
     36 void ssl_PrintBuf(sslSocket *ss, const char *msg, const void *vp, int len)
     37 {
     38     const unsigned char *cp = (const unsigned char *)vp;
     39     char buf[80];
     40     char *bp;
     41     char *ap;
     42 
     43     if (ss) {
     44 	SSL_TRACE(("%d: SSL[%d]: %s [Len: %d]", SSL_GETPID(), ss->fd,
     45 		   msg, len));
     46     } else {
     47 	SSL_TRACE(("%d: SSL: %s [Len: %d]", SSL_GETPID(), msg, len));
     48     }
     49     memset(buf, ' ', sizeof buf);
     50     bp = buf;
     51     ap = buf + 50;
     52     while (--len >= 0) {
     53 	unsigned char ch = *cp++;
     54 	*bp++ = hex[(ch >> 4) & 0xf];
     55 	*bp++ = hex[ch & 0xf];
     56 	*bp++ = ' ';
     57 	*ap++ = printable[ch];
     58 	if (ap - buf >= 66) {
     59 	    *ap = 0;
     60 	    SSL_TRACE(("   %s", buf));
     61 	    memset(buf, ' ', sizeof buf);
     62 	    bp = buf;
     63 	    ap = buf + 50;
     64 	}
     65     }
     66     if (bp > buf) {
     67 	*ap = 0;
     68 	SSL_TRACE(("   %s", buf));
     69     }
     70 }
     71 
     72 #define LEN(cp)		(((cp)[0] << 8) | ((cp)[1]))
     73 
     74 static void PrintType(sslSocket *ss, char *msg)
     75 {
     76     if (ss) {
     77 	SSL_TRACE(("%d: SSL[%d]: dump-msg: %s", SSL_GETPID(), ss->fd,
     78 		   msg));
     79     } else {
     80 	SSL_TRACE(("%d: SSL: dump-msg: %s", SSL_GETPID(), msg));
     81     }
     82 }
     83 
     84 static void PrintInt(sslSocket *ss, char *msg, unsigned v)
     85 {
     86     if (ss) {
     87 	SSL_TRACE(("%d: SSL[%d]:           %s=%u", SSL_GETPID(), ss->fd,
     88 		   msg, v));
     89     } else {
     90 	SSL_TRACE(("%d: SSL:           %s=%u", SSL_GETPID(), msg, v));
     91     }
     92 }
     93 
     94 /* PrintBuf is just like ssl_PrintBuf above, except that:
     95  * a) It prefixes each line of the buffer with "XX: SSL[xxx]           "
     96  * b) It dumps only hex, not ASCII.
     97  */
     98 static void PrintBuf(sslSocket *ss, char *msg, unsigned char *cp, int len)
     99 {
    100     char buf[80];
    101     char *bp;
    102 
    103     if (ss) {
    104 	SSL_TRACE(("%d: SSL[%d]:           %s [Len: %d]",
    105 		   SSL_GETPID(), ss->fd, msg, len));
    106     } else {
    107 	SSL_TRACE(("%d: SSL:           %s [Len: %d]",
    108 		   SSL_GETPID(), msg, len));
    109     }
    110     bp = buf;
    111     while (--len >= 0) {
    112 	unsigned char ch = *cp++;
    113 	*bp++ = hex[(ch >> 4) & 0xf];
    114 	*bp++ = hex[ch & 0xf];
    115 	*bp++ = ' ';
    116 	if (bp + 4 > buf + 50) {
    117 	    *bp = 0;
    118 	    if (ss) {
    119 		SSL_TRACE(("%d: SSL[%d]:             %s",
    120 			   SSL_GETPID(), ss->fd, buf));
    121 	    } else {
    122 		SSL_TRACE(("%d: SSL:             %s", SSL_GETPID(), buf));
    123 	    }
    124 	    bp = buf;
    125 	}
    126     }
    127     if (bp > buf) {
    128 	*bp = 0;
    129 	if (ss) {
    130 	    SSL_TRACE(("%d: SSL[%d]:             %s",
    131 		       SSL_GETPID(), ss->fd, buf));
    132 	} else {
    133 	    SSL_TRACE(("%d: SSL:             %s", SSL_GETPID(), buf));
    134 	}
    135     }
    136 }
    137 
    138 void ssl_DumpMsg(sslSocket *ss, unsigned char *bp, unsigned len)
    139 {
    140     switch (bp[0]) {
    141       case SSL_MT_ERROR:
    142 	PrintType(ss, "Error");
    143 	PrintInt(ss, "error", LEN(bp+1));
    144 	break;
    145 
    146       case SSL_MT_CLIENT_HELLO:
    147 	{
    148 	    unsigned lcs = LEN(bp+3);
    149 	    unsigned ls  = LEN(bp+5);
    150 	    unsigned lc  = LEN(bp+7);
    151 
    152 	    PrintType(ss, "Client-Hello");
    153 
    154 	    PrintInt(ss, "version (Major)",                   bp[1]);
    155 	    PrintInt(ss, "version (minor)",                   bp[2]);
    156 
    157 	    PrintBuf(ss, "cipher-specs",         bp+9,        lcs);
    158 	    PrintBuf(ss, "session-id",           bp+9+lcs,    ls);
    159 	    PrintBuf(ss, "challenge",            bp+9+lcs+ls, lc);
    160 	}
    161 	break;
    162       case SSL_MT_CLIENT_MASTER_KEY:
    163 	{
    164 	    unsigned lck = LEN(bp+4);
    165 	    unsigned lek = LEN(bp+6);
    166 	    unsigned lka = LEN(bp+8);
    167 
    168 	    PrintType(ss, "Client-Master-Key");
    169 
    170 	    PrintInt(ss, "cipher-choice",                       bp[1]);
    171 	    PrintInt(ss, "key-length",                          LEN(bp+2));
    172 
    173 	    PrintBuf(ss, "clear-key",            bp+10,         lck);
    174 	    PrintBuf(ss, "encrypted-key",        bp+10+lck,     lek);
    175 	    PrintBuf(ss, "key-arg",              bp+10+lck+lek, lka);
    176 	}
    177 	break;
    178       case SSL_MT_CLIENT_FINISHED:
    179 	PrintType(ss, "Client-Finished");
    180 	PrintBuf(ss, "connection-id",            bp+1,          len-1);
    181 	break;
    182       case SSL_MT_SERVER_HELLO:
    183 	{
    184 	    unsigned lc = LEN(bp+5);
    185 	    unsigned lcs = LEN(bp+7);
    186 	    unsigned lci = LEN(bp+9);
    187 
    188 	    PrintType(ss, "Server-Hello");
    189 
    190 	    PrintInt(ss, "session-id-hit",                     bp[1]);
    191 	    PrintInt(ss, "certificate-type",                   bp[2]);
    192 	    PrintInt(ss, "version (Major)",                    bp[3]);
    193 	    PrintInt(ss, "version (minor)",                    bp[3]);
    194 	    PrintBuf(ss, "certificate",          bp+11,        lc);
    195 	    PrintBuf(ss, "cipher-specs",         bp+11+lc,     lcs);
    196 	    PrintBuf(ss, "connection-id",        bp+11+lc+lcs, lci);
    197 	}
    198 	break;
    199       case SSL_MT_SERVER_VERIFY:
    200 	PrintType(ss, "Server-Verify");
    201 	PrintBuf(ss, "challenge",                bp+1,         len-1);
    202 	break;
    203       case SSL_MT_SERVER_FINISHED:
    204 	PrintType(ss, "Server-Finished");
    205 	PrintBuf(ss, "session-id",               bp+1,         len-1);
    206 	break;
    207       case SSL_MT_REQUEST_CERTIFICATE:
    208 	PrintType(ss, "Request-Certificate");
    209 	PrintInt(ss, "authentication-type",                    bp[1]);
    210 	PrintBuf(ss, "certificate-challenge",    bp+2,         len-2);
    211 	break;
    212       case SSL_MT_CLIENT_CERTIFICATE:
    213 	{
    214 	    unsigned lc = LEN(bp+2);
    215 	    unsigned lr = LEN(bp+4);
    216 	    PrintType(ss, "Client-Certificate");
    217 	    PrintInt(ss, "certificate-type",                   bp[1]);
    218 	    PrintBuf(ss, "certificate",          bp+6,         lc);
    219 	    PrintBuf(ss, "response",             bp+6+lc,      lr);
    220 	}
    221 	break;
    222       default:
    223 	ssl_PrintBuf(ss, "sending *unknown* message type", bp, len);
    224 	return;
    225     }
    226 }
    227 
    228 void
    229 ssl_Trace(const char *format, ... )
    230 {
    231     char buf[2000];
    232     va_list args;
    233 
    234     if (ssl_trace_iob) {
    235 	va_start(args, format);
    236 	PR_vsnprintf(buf, sizeof(buf), format, args);
    237 	va_end(args);
    238 
    239 	fputs(buf,  ssl_trace_iob);
    240 	fputs("\n", ssl_trace_iob);
    241     }
    242 }
    243 #endif
    244