1#include "tunala.h" 2 3#ifndef NO_OPENSSL 4 5/* For callbacks generating output, here are their file-descriptors. */ 6static FILE *fp_cb_ssl_info = NULL; 7static FILE *fp_cb_ssl_verify = NULL; 8/* Output level: 9 * 0 = nothing, 10 * 1 = minimal, just errors, 11 * 2 = minimal, all steps, 12 * 3 = detail, all steps */ 13static unsigned int cb_ssl_verify_level = 1; 14 15/* Other static rubbish (to mirror s_cb.c where required) */ 16static int int_verify_depth = 10; 17 18/* This function is largely borrowed from the one used in OpenSSL's "s_client" 19 * and "s_server" utilities. */ 20void cb_ssl_info(const SSL *s, int where, int ret) 21{ 22 const char *str1, *str2; 23 int w; 24 25 if(!fp_cb_ssl_info) 26 return; 27 28 w = where & ~SSL_ST_MASK; 29 str1 = (w & SSL_ST_CONNECT ? "SSL_connect" : (w & SSL_ST_ACCEPT ? 30 "SSL_accept" : "undefined")), 31 str2 = SSL_state_string_long(s); 32 33 if (where & SSL_CB_LOOP) 34 fprintf(fp_cb_ssl_info, "(%s) %s\n", str1, str2); 35 else if (where & SSL_CB_EXIT) { 36 if (ret == 0) 37 fprintf(fp_cb_ssl_info, "(%s) failed in %s\n", str1, str2); 38/* In a non-blocking model, we get a few of these "error"s simply because we're 39 * calling "reads" and "writes" on the state-machine that are virtual NOPs 40 * simply to avoid wasting the time seeing if we *should* call them. Removing 41 * this case makes the "-out_state" output a lot easier on the eye. */ 42#if 0 43 else if (ret < 0) 44 fprintf(fp_cb_ssl_info, "%s:error in %s\n", str1, str2); 45#endif 46 } 47} 48 49void cb_ssl_info_set_output(FILE *fp) 50{ 51 fp_cb_ssl_info = fp; 52} 53 54static const char *int_reason_no_issuer = "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT"; 55static const char *int_reason_not_yet = "X509_V_ERR_CERT_NOT_YET_VALID"; 56static const char *int_reason_before = "X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD"; 57static const char *int_reason_expired = "X509_V_ERR_CERT_HAS_EXPIRED"; 58static const char *int_reason_after = "X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD"; 59 60/* Stolen wholesale from apps/s_cb.c :-) And since then, mutilated ... */ 61int cb_ssl_verify(int ok, X509_STORE_CTX *ctx) 62{ 63 char buf1[256]; /* Used for the subject name */ 64 char buf2[256]; /* Used for the issuer name */ 65 const char *reason = NULL; /* Error reason (if any) */ 66 X509 *err_cert; 67 int err, depth; 68 69 if(!fp_cb_ssl_verify || (cb_ssl_verify_level == 0)) 70 return ok; 71 err_cert = X509_STORE_CTX_get_current_cert(ctx); 72 err = X509_STORE_CTX_get_error(ctx); 73 depth = X509_STORE_CTX_get_error_depth(ctx); 74 75 buf1[0] = buf2[0] = '\0'; 76 /* Fill buf1 */ 77 X509_NAME_oneline(X509_get_subject_name(err_cert), buf1, 256); 78 /* Fill buf2 */ 79 X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf2, 256); 80 switch (ctx->error) { 81 case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: 82 reason = int_reason_no_issuer; 83 break; 84 case X509_V_ERR_CERT_NOT_YET_VALID: 85 reason = int_reason_not_yet; 86 break; 87 case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: 88 reason = int_reason_before; 89 break; 90 case X509_V_ERR_CERT_HAS_EXPIRED: 91 reason = int_reason_expired; 92 break; 93 case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: 94 reason = int_reason_after; 95 break; 96 } 97 98 if((cb_ssl_verify_level == 1) && ok) 99 return ok; 100 fprintf(fp_cb_ssl_verify, "chain-depth=%d, ", depth); 101 if(reason) 102 fprintf(fp_cb_ssl_verify, "error=%s\n", reason); 103 else 104 fprintf(fp_cb_ssl_verify, "error=%d\n", err); 105 if(cb_ssl_verify_level < 3) 106 return ok; 107 fprintf(fp_cb_ssl_verify, "--> subject = %s\n", buf1); 108 fprintf(fp_cb_ssl_verify, "--> issuer = %s\n", buf2); 109 if(!ok) 110 fprintf(fp_cb_ssl_verify,"--> verify error:num=%d:%s\n",err, 111 X509_verify_cert_error_string(err)); 112 fprintf(fp_cb_ssl_verify, "--> verify return:%d\n",ok); 113 return ok; 114} 115 116void cb_ssl_verify_set_output(FILE *fp) 117{ 118 fp_cb_ssl_verify = fp; 119} 120 121void cb_ssl_verify_set_depth(unsigned int verify_depth) 122{ 123 int_verify_depth = verify_depth; 124} 125 126void cb_ssl_verify_set_level(unsigned int level) 127{ 128 if(level < 4) 129 cb_ssl_verify_level = level; 130} 131 132RSA *cb_generate_tmp_rsa(SSL *s, int is_export, int keylength) 133{ 134 /* TODO: Perhaps make it so our global key can be generated on-the-fly 135 * after certain intervals? */ 136 static RSA *rsa_tmp = NULL; 137 if(!rsa_tmp) 138 rsa_tmp = RSA_generate_key(keylength, RSA_F4, NULL, NULL); 139 return rsa_tmp; 140} 141 142#endif /* !defined(NO_OPENSSL) */ 143 144