|
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 |