• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ssl_PrintBuf(sslSocket * ss,const char * msg,const void * vp,int len)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 
PrintType(sslSocket * ss,char * msg)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 
PrintInt(sslSocket * ss,char * msg,unsigned v)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  */
PrintBuf(sslSocket * ss,char * msg,unsigned char * cp,int len)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 
ssl_DumpMsg(sslSocket * ss,unsigned char * bp,unsigned len)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
ssl_Trace(const char * format,...)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