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