1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112: #include <stdio.h>
113: #include <stdlib.h>
114: #define USE_SOCKETS
115: #define NON_MAIN
116: #include "apps.h"
117: #undef NON_MAIN
118: #undef USE_SOCKETS
119: #include <openssl/err.h>
120: #include <openssl/x509.h>
121: #include <openssl/ssl.h>
122: #include "s_apps.h"
123:
124: int verify_depth=0;
125: int verify_error=X509_V_OK;
126:
127: int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx)
128: {
129: char buf[256];
130: X509 *err_cert;
131: int err,depth;
132:
133: err_cert=X509_STORE_CTX_get_current_cert(ctx);
134: err= X509_STORE_CTX_get_error(ctx);
135: depth= X509_STORE_CTX_get_error_depth(ctx);
136:
137: X509_NAME_oneline(X509_get_subject_name(err_cert),buf,sizeof buf);
138: BIO_printf(bio_err,"depth=%d %s\n",depth,buf);
139: if (!ok)
140: {
141: BIO_printf(bio_err,"verify error:num=%d:%s\n",err,
142: X509_verify_cert_error_string(err));
143: if (verify_depth >= depth)
144: {
145: ok=1;
146: verify_error=X509_V_OK;
147: }
148: else
149: {
150: ok=0;
151: verify_error=X509_V_ERR_CERT_CHAIN_TOO_LONG;
152: }
153: }
154: switch (ctx->error)
155: {
156: case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
157: X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert),buf,sizeof buf);
158: BIO_printf(bio_err,"issuer= %s\n",buf);
159: break;
160: case X509_V_ERR_CERT_NOT_YET_VALID:
161: case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
162: BIO_printf(bio_err,"notBefore=");
163: ASN1_TIME_print(bio_err,X509_get_notBefore(ctx->current_cert));
164: BIO_printf(bio_err,"\n");
165: break;
166: case X509_V_ERR_CERT_HAS_EXPIRED:
167: case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
168: BIO_printf(bio_err,"notAfter=");
169: ASN1_TIME_print(bio_err,X509_get_notAfter(ctx->current_cert));
170: BIO_printf(bio_err,"\n");
171: break;
172: }
173: BIO_printf(bio_err,"verify return:%d\n",ok);
174: return(ok);
175: }
176:
177: int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file)
178: {
179: if (cert_file != NULL)
180: {
181:
182:
183:
184:
185:
186: if (SSL_CTX_use_certificate_file(ctx,cert_file,
187: SSL_FILETYPE_PEM) <= 0)
188: {
189: BIO_printf(bio_err,"unable to get certificate from '%s'\n",cert_file);
190: ERR_print_errors(bio_err);
191: return(0);
192: }
193: if (key_file == NULL) key_file=cert_file;
194: if (SSL_CTX_use_PrivateKey_file(ctx,key_file,
195: SSL_FILETYPE_PEM) <= 0)
196: {
197: BIO_printf(bio_err,"unable to get private key from '%s'\n",key_file);
198: ERR_print_errors(bio_err);
199: return(0);
200: }
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223: if (!SSL_CTX_check_private_key(ctx))
224: {
225: BIO_printf(bio_err,"Private key does not match the certificate public key\n");
226: return(0);
227: }
228: }
229: return(1);
230: }
231:
232: int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key)
233: {
234: if (cert == NULL)
235: return 1;
236: if (SSL_CTX_use_certificate(ctx,cert) <= 0)
237: {
238: BIO_printf(bio_err,"error setting certificate\n");
239: ERR_print_errors(bio_err);
240: return 0;
241: }
242: if (SSL_CTX_use_PrivateKey(ctx,key) <= 0)
243: {
244: BIO_printf(bio_err,"error setting private key\n");
245: ERR_print_errors(bio_err);
246: return 0;
247: }
248:
249:
250:
251:
252: if (!SSL_CTX_check_private_key(ctx))
253: {
254: BIO_printf(bio_err,"Private key does not match the certificate public key\n");
255: return 0;
256: }
257: return 1;
258: }
259:
260: long MS_CALLBACK bio_dump_callback(BIO *bio, int cmd, const char *argp,
261: int argi, long argl, long ret)
262: {
263: BIO *out;
264:
265: out=(BIO *)BIO_get_callback_arg(bio);
266: if (out == NULL) return(ret);
267:
268: if (cmd == (BIO_CB_READ|BIO_CB_RETURN))
269: {
270: BIO_printf(out,"read from %p [%p] (%d bytes => %ld (0x%lX))\n",
271: (void *)bio,argp,argi,ret,ret);
272: BIO_dump(out,argp,(int)ret);
273: return(ret);
274: }
275: else if (cmd == (BIO_CB_WRITE|BIO_CB_RETURN))
276: {
277: BIO_printf(out,"write to %p [%p] (%d bytes => %ld (0x%lX))\n",
278: (void *)bio,argp,argi,ret,ret);
279: BIO_dump(out,argp,(int)ret);
280: }
281: return(ret);
282: }
283:
284: void MS_CALLBACK apps_ssl_info_callback(const SSL *s, int where, int ret)
285: {
286: const char *str;
287: int w;
288:
289: w=where& ~SSL_ST_MASK;
290:
291: if (w & SSL_ST_CONNECT) str="SSL_connect";
292: else if (w & SSL_ST_ACCEPT) str="SSL_accept";
293: else str="undefined";
294:
295: if (where & SSL_CB_LOOP)
296: {
297: BIO_printf(bio_err,"%s:%s\n",str,SSL_state_string_long(s));
298: }
299: else if (where & SSL_CB_ALERT)
300: {
301: str=(where & SSL_CB_READ)?"read":"write";
302: BIO_printf(bio_err,"SSL3 alert %s:%s:%s\n",
303: str,
304: SSL_alert_type_string_long(ret),
305: SSL_alert_desc_string_long(ret));
306: }
307: else if (where & SSL_CB_EXIT)
308: {
309: if (ret == 0)
310: BIO_printf(bio_err,"%s:failed in %s\n",
311: str,SSL_state_string_long(s));
312: else if (ret < 0)
313: {
314: BIO_printf(bio_err,"%s:error in %s\n",
315: str,SSL_state_string_long(s));
316: }
317: }
318: }
319:
320:
321: void MS_CALLBACK msg_cb(int write_p, int version, int content_type, const void *buf, size_t len, SSL *ssl, void *arg)
322: {
323: BIO *bio = arg;
324: const char *str_write_p, *str_version, *str_content_type = "", *str_details1 = "", *str_details2= "";
325:
326: str_write_p = write_p ? ">>>" : "<<<";
327:
328: switch (version)
329: {
330: case SSL2_VERSION:
331: str_version = "SSL 2.0";
332: break;
333: case SSL3_VERSION:
334: str_version = "SSL 3.0 ";
335: break;
336: case TLS1_VERSION:
337: str_version = "TLS 1.0 ";
338: break;
339: default:
340: str_version = "???";
341: }
342:
343: if (version == SSL2_VERSION)
344: {
345: str_details1 = "???";
346:
347: if (len > 0)
348: {
349: switch (((const unsigned char*)buf)[0])
350: {
351: case 0:
352: str_details1 = ", ERROR:";
353: str_details2 = " ???";
354: if (len >= 3)
355: {
356: unsigned err = (((const unsigned char*)buf)[1]<<8) + ((const unsigned char*)buf)[2];
357:
358: switch (err)
359: {
360: case 0x0001:
361: str_details2 = " NO-CIPHER-ERROR";
362: break;
363: case 0x0002:
364: str_details2 = " NO-CERTIFICATE-ERROR";
365: break;
366: case 0x0004:
367: str_details2 = " BAD-CERTIFICATE-ERROR";
368: break;
369: case 0x0006:
370: str_details2 = " UNSUPPORTED-CERTIFICATE-TYPE-ERROR";
371: break;
372: }
373: }
374:
375: break;
376: case 1:
377: str_details1 = ", CLIENT-HELLO";
378: break;
379: case 2:
380: str_details1 = ", CLIENT-MASTER-KEY";
381: break;
382: case 3:
383: str_details1 = ", CLIENT-FINISHED";
384: break;
385: case 4:
386: str_details1 = ", SERVER-HELLO";
387: break;
388: case 5:
389: str_details1 = ", SERVER-VERIFY";
390: break;
391: case 6:
392: str_details1 = ", SERVER-FINISHED";
393: break;
394: case 7:
395: str_details1 = ", REQUEST-CERTIFICATE";
396: break;
397: case 8:
398: str_details1 = ", CLIENT-CERTIFICATE";
399: break;
400: }
401: }
402: }
403:
404: if (version == SSL3_VERSION || version == TLS1_VERSION)
405: {
406: switch (content_type)
407: {
408: case 20:
409: str_content_type = "ChangeCipherSpec";
410: break;
411: case 21:
412: str_content_type = "Alert";
413: break;
414: case 22:
415: str_content_type = "Handshake";
416: break;
417: }
418:
419: if (content_type == 21)
420: {
421: str_details1 = ", ???";
422:
423: if (len == 2)
424: {
425: switch (((const unsigned char*)buf)[0])
426: {
427: case 1:
428: str_details1 = ", warning";
429: break;
430: case 2:
431: str_details1 = ", fatal";
432: break;
433: }
434:
435: str_details2 = " ???";
436: switch (((const unsigned char*)buf)[1])
437: {
438: case 0:
439: str_details2 = " close_notify";
440: break;
441: case 10:
442: str_details2 = " unexpected_message";
443: break;
444: case 20:
445: str_details2 = " bad_record_mac";
446: break;
447: case 21:
448: str_details2 = " decryption_failed";
449: break;
450: case 22:
451: str_details2 = " record_overflow";
452: break;
453: case 30:
454: str_details2 = " decompression_failure";
455: break;
456: case 40:
457: str_details2 = " handshake_failure";
458: break;
459: case 42:
460: str_details2 = " bad_certificate";
461: break;
462: case 43:
463: str_details2 = " unsupported_certificate";
464: break;
465: case 44:
466: str_details2 = " certificate_revoked";
467: break;
468: case 45:
469: str_details2 = " certificate_expired";
470: break;
471: case 46:
472: str_details2 = " certificate_unknown";
473: break;
474: case 47:
475: str_details2 = " illegal_parameter";
476: break;
477: case 48:
478: str_details2 = " unknown_ca";
479: break;
480: case 49:
481: str_details2 = " access_denied";
482: break;
483: case 50:
484: str_details2 = " decode_error";
485: break;
486: case 51:
487: str_details2 = " decrypt_error";
488: break;
489: case 60:
490: str_details2 = " export_restriction";
491: break;
492: case 70:
493: str_details2 = " protocol_version";
494: break;
495: case 71:
496: str_details2 = " insufficient_security";
497: break;
498: case 80:
499: str_details2 = " internal_error";
500: break;
501: case 90:
502: str_details2 = " user_canceled";
503: break;
504: case 100:
505: str_details2 = " no_renegotiation";
506: break;
507: }
508: }
509: }
510:
511: if (content_type == 22)
512: {
513: str_details1 = "???";
514:
515: if (len > 0)
516: {
517: switch (((const unsigned char*)buf)[0])
518: {
519: case 0:
520: str_details1 = ", HelloRequest";
521: break;
522: case 1:
523: str_details1 = ", ClientHello";
524: break;
525: case 2:
526: str_details1 = ", ServerHello";
527: break;
528: case 11:
529: str_details1 = ", Certificate";
530: break;
531: case 12:
532: str_details1 = ", ServerKeyExchange";
533: break;
534: case 13:
535: str_details1 = ", CertificateRequest";
536: break;
537: case 14:
538: str_details1 = ", ServerHelloDone";
539: break;
540: case 15:
541: str_details1 = ", CertificateVerify";
542: break;
543: case 16:
544: str_details1 = ", ClientKeyExchange";
545: break;
546: case 20:
547: str_details1 = ", Finished";
548: break;
549: }
550: }
551: }
552: }
553:
554: BIO_printf(bio, "%s %s%s [length %04lx]%s%s\n", str_write_p, str_version, str_content_type, (unsigned long)len, str_details1, str_details2);
555:
556: if (len > 0)
557: {
558: size_t num, i;
559:
560: BIO_printf(bio, " ");
561: num = len;
562: #if 0
563: if (num > 16)
564: num = 16;
565: #endif
566: for (i = 0; i < num; i++)
567: {
568: if (i % 16 == 0 && i > 0)
569: BIO_printf(bio, "\n ");
570: BIO_printf(bio, " %02x", ((const unsigned char*)buf)[i]);
571: }
572: if (i < len)
573: BIO_printf(bio, " ...");
574: BIO_printf(bio, "\n");
575: }
576: (void)BIO_flush(bio);