Make s_client/s_server-style cert verification output configurable by
[openssl.git] / demos / tunala / cb.c
1 #include "tunala.h"
2
3 #ifndef NO_OPENSSL
4
5 /* For callbacks generating output, here are their file-descriptors. */
6 static FILE *fp_cb_ssl_info = NULL;
7 static FILE *fp_cb_ssl_verify = NULL;
8
9 /* Other static rubbish (to mirror s_cb.c where required) */
10 static int verify_depth = 10;
11 static int verify_error = X509_V_OK;
12
13 /* This function is largely borrowed from the one used in OpenSSL's "s_client"
14  * and "s_server" utilities. */
15 void cb_ssl_info(SSL *s, int where, int ret)
16 {
17         char *str1, *str2;
18         int w;
19
20         if(!fp_cb_ssl_info)
21                 return;
22
23         w = where & ~SSL_ST_MASK;
24         str1 = (w & SSL_ST_CONNECT ? "SSL_connect" : (w & SSL_ST_ACCEPT ?
25                                 "SSL_accept" : "undefined")),
26         str2 = SSL_state_string_long(s);
27
28         if (where & SSL_CB_LOOP)
29                 fprintf(fp_cb_ssl_info, "%s:%s\n", str1, str2);
30         else if (where & SSL_CB_EXIT) {
31                 if (ret == 0)
32                         fprintf(fp_cb_ssl_info, "%s:failed in %s\n", str1, str2);
33                 else if (ret < 0)
34                         fprintf(fp_cb_ssl_info, "%s:error in %s\n", str1, str2);
35         }
36 }
37
38 void cb_ssl_info_set_output(FILE *fp)
39 {
40         fp_cb_ssl_info = fp;
41 }
42
43 /* Stolen wholesale from apps/s_cb.c :-) */
44 int cb_ssl_verify(int ok, X509_STORE_CTX *ctx)
45 {
46         char buf[256];
47         X509 *err_cert;
48         int err, depth;
49         BIO *bio;
50
51         if(!fp_cb_ssl_verify)
52                 return ok;
53         /* There's no <damned>FILE*</damned> version of ASN1_TIME_print */
54         bio = BIO_new_fp(fp_cb_ssl_verify, BIO_NOCLOSE);
55         err_cert = X509_STORE_CTX_get_current_cert(ctx);
56         err = X509_STORE_CTX_get_error(ctx);
57         depth = X509_STORE_CTX_get_error_depth(ctx);
58
59         X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
60         fprintf(fp_cb_ssl_verify, "depth=%d %s\n", depth, buf);
61         if(!ok) {
62                 fprintf(fp_cb_ssl_verify,"verify error:num=%d:%s\n",err,
63                         X509_verify_cert_error_string(err));
64                 if(verify_depth >= depth) {
65                         ok = 1;
66                         verify_error = X509_V_OK;
67                 } else {
68                         ok=0;
69                         verify_error = X509_V_ERR_CERT_CHAIN_TOO_LONG;
70                 }
71         }
72         switch (ctx->error) {
73         case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
74                 X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert),
75                                 buf, 256);
76                 fprintf(fp_cb_ssl_verify, "issuer= %s\n", buf);
77                 break;
78         case X509_V_ERR_CERT_NOT_YET_VALID:
79         case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
80                 fprintf(fp_cb_ssl_verify, "notBefore=");
81                 ASN1_TIME_print(bio, X509_get_notBefore(ctx->current_cert));
82                 fprintf(fp_cb_ssl_verify, "\n");
83                 break;
84         case X509_V_ERR_CERT_HAS_EXPIRED:
85         case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
86                 fprintf(fp_cb_ssl_verify, "notAfter=");
87                 ASN1_TIME_print(bio, X509_get_notAfter(ctx->current_cert));
88                 fprintf(fp_cb_ssl_verify, "\n");
89                 break;
90         }
91         fprintf(fp_cb_ssl_verify, "verify return:%d\n",ok);
92         return ok;
93 }
94
95 void cb_ssl_verify_set_output(FILE *fp)
96 {
97         fp_cb_ssl_verify = fp;
98 }
99
100 #endif /* !defined(NO_OPENSSL) */
101