From 3465dd3853f000e042dc3fd26f4ce03cd92374ad Mon Sep 17 00:00:00 2001 From: Geoff Thorpe Date: Thu, 30 Nov 2000 01:34:26 +0000 Subject: [PATCH] * Fix a slight bug in the state-machine. This caused the client end of a tunnel to not pro-actively close down when failing an SSL handshake. * Change the cert-chain callback - originally this was the same one used in s_client and s_server but the output's as ugly as sin, so I've prettied tunala's copy output up a bit (and made the output level configurable). * Remove the superfluous "errors" from the SSL state callback - these are just non-blocking side-effects. --- demos/tunala/cb.c | 88 +++++++++++++++++++++++++++++-------------- demos/tunala/tunala.c | 32 +++++++++++++--- demos/tunala/tunala.h | 1 + 3 files changed, 86 insertions(+), 35 deletions(-) diff --git a/demos/tunala/cb.c b/demos/tunala/cb.c index 4633c0993e..ac7122da4f 100644 --- a/demos/tunala/cb.c +++ b/demos/tunala/cb.c @@ -5,10 +5,15 @@ /* For callbacks generating output, here are their file-descriptors. */ static FILE *fp_cb_ssl_info = NULL; static FILE *fp_cb_ssl_verify = NULL; +/* Output level: + * 0 = nothing, + * 1 = minimal, just errors, + * 2 = minimal, all steps, + * 3 = detail, all steps */ +static unsigned int cb_ssl_verify_level = 1; /* Other static rubbish (to mirror s_cb.c where required) */ static int int_verify_depth = 10; -static int int_verify_error = X509_V_OK; /* This function is largely borrowed from the one used in OpenSSL's "s_client" * and "s_server" utilities. */ @@ -26,12 +31,18 @@ void cb_ssl_info(SSL *s, int where, int ret) str2 = SSL_state_string_long(s); if (where & SSL_CB_LOOP) - fprintf(fp_cb_ssl_info, "%s:%s\n", str1, str2); + fprintf(fp_cb_ssl_info, "(%s) %s\n", str1, str2); else if (where & SSL_CB_EXIT) { if (ret == 0) - fprintf(fp_cb_ssl_info, "%s:failed in %s\n", str1, str2); + fprintf(fp_cb_ssl_info, "(%s) failed in %s\n", str1, str2); +/* In a non-blocking model, we get a few of these "error"s simply because we're + * calling "reads" and "writes" on the state-machine that are virtual NOPs + * simply to avoid wasting the time seeing if we *should* call them. Removing + * this case makes the "-out_state" output a lot easier on the eye. */ +#if 0 else if (ret < 0) fprintf(fp_cb_ssl_info, "%s:error in %s\n", str1, str2); +#endif } } @@ -40,52 +51,65 @@ void cb_ssl_info_set_output(FILE *fp) fp_cb_ssl_info = fp; } -/* Stolen wholesale from apps/s_cb.c :-) */ +static const char *int_reason_no_issuer = "X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT"; +static const char *int_reason_not_yet = "X509_V_ERR_CERT_NOT_YET_VALID"; +static const char *int_reason_before = "X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD"; +static const char *int_reason_expired = "X509_V_ERR_CERT_HAS_EXPIRED"; +static const char *int_reason_after = "X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD"; + +/* Stolen wholesale from apps/s_cb.c :-) And since then, mutilated ... */ int cb_ssl_verify(int ok, X509_STORE_CTX *ctx) { - char buf[256]; + char buf1[256]; /* Used for the subject name */ + char buf2[256]; /* Used for the issuer name */ + const char *reason = NULL; /* Error reason (if any) */ X509 *err_cert; int err, depth; - BIO *bio; - if(!fp_cb_ssl_verify) + if(!fp_cb_ssl_verify || (cb_ssl_verify_level == 0)) return ok; - /* There's no FILE* version of ASN1_TIME_print */ - bio = BIO_new_fp(fp_cb_ssl_verify, BIO_NOCLOSE); err_cert = X509_STORE_CTX_get_current_cert(ctx); err = X509_STORE_CTX_get_error(ctx); depth = X509_STORE_CTX_get_error_depth(ctx); - X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256); - fprintf(fp_cb_ssl_verify, "depth=%d %s\n", depth, buf); - if(!ok) { - fprintf(fp_cb_ssl_verify,"verify error:num=%d:%s\n",err, - X509_verify_cert_error_string(err)); - if((int)int_verify_depth >= depth) - int_verify_error = err; - else - int_verify_error = X509_V_ERR_CERT_CHAIN_TOO_LONG; - } + buf1[0] = buf2[0] = '\0'; + /* Fill buf1 */ + X509_NAME_oneline(X509_get_subject_name(err_cert), buf1, 256); + /* Fill buf2 */ + X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf2, 256); switch (ctx->error) { case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: - X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), - buf, 256); - fprintf(fp_cb_ssl_verify, "issuer= %s\n", buf); + reason = int_reason_no_issuer; break; case X509_V_ERR_CERT_NOT_YET_VALID: + reason = int_reason_not_yet; + break; case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: - fprintf(fp_cb_ssl_verify, "notBefore="); - ASN1_TIME_print(bio, X509_get_notBefore(ctx->current_cert)); - fprintf(fp_cb_ssl_verify, "\n"); + reason = int_reason_before; break; case X509_V_ERR_CERT_HAS_EXPIRED: + reason = int_reason_expired; + break; case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: - fprintf(fp_cb_ssl_verify, "notAfter="); - ASN1_TIME_print(bio, X509_get_notAfter(ctx->current_cert)); - fprintf(fp_cb_ssl_verify, "\n"); + reason = int_reason_after; break; } - fprintf(fp_cb_ssl_verify, "verify return:%d\n",ok); + + if((cb_ssl_verify_level == 1) && ok) + return ok; + fprintf(fp_cb_ssl_verify, "chain-depth=%d, ", depth); + if(reason) + fprintf(fp_cb_ssl_verify, "error=%s\n", reason); + else + fprintf(fp_cb_ssl_verify, "error=%d\n", err); + if(cb_ssl_verify_level < 3) + return ok; + fprintf(fp_cb_ssl_verify, "--> subject = %s\n", buf1); + fprintf(fp_cb_ssl_verify, "--> issuer = %s\n", buf2); + if(!ok) + fprintf(fp_cb_ssl_verify,"--> verify error:num=%d:%s\n",err, + X509_verify_cert_error_string(err)); + fprintf(fp_cb_ssl_verify, "--> verify return:%d\n",ok); return ok; } @@ -99,5 +123,11 @@ void cb_ssl_verify_set_depth(unsigned int verify_depth) int_verify_depth = verify_depth; } +void cb_ssl_verify_set_level(unsigned int level) +{ + if(level < 4) + cb_ssl_verify_level = level; +} + #endif /* !defined(NO_OPENSSL) */ diff --git a/demos/tunala/tunala.c b/demos/tunala/tunala.c index 19d7d1150d..2b3d65d98c 100644 --- a/demos/tunala/tunala.c +++ b/demos/tunala/tunala.c @@ -99,7 +99,7 @@ static const char *def_engine_id = NULL; static int def_server_mode = 0; static const char *def_cipher_list = NULL; static int def_out_state = 0; -static int def_out_verify = 0; +static unsigned int def_out_verify = 0; static int def_verify_mode = 0; static unsigned int def_verify_depth = 10; @@ -118,7 +118,7 @@ static const char *helpstring = " -server <0|1> (default = 0, ie. an SSL client)\n" " -cipher (specifies cipher list to use)\n" " -out_state (prints SSL handshake states)\n" -" -out_verify (prints certificate verification states)\n" +" -out_verify <0|1|2|3> (prints certificate verification states: def=1)\n" " -v_peer (verify the peer certificate)\n" " -v_strict (do not continue if peer doesn't authenticate)\n" " -v_once (no verification in renegotiates)\n" @@ -180,6 +180,20 @@ static int parse_server_mode(const char *s, int *servermode) return 1; } +static int parse_verify_level(const char *s, unsigned int *verify_level) +{ + unsigned long l; + char *temp; + l = strtoul(s, &temp, 10); + if((temp == s) || (*temp != '\0') || (l > 3)) { + fprintf(stderr, "Error, '%s' is an invalid value for " + "out_verify\n", s); + return 0; + } + *verify_level = (unsigned int)l; + return 1; +} + static int parse_verify_depth(const char *s, unsigned int *verify_depth) { unsigned long l; @@ -215,7 +229,7 @@ int main(int argc, char *argv[]) int server_mode = def_server_mode; const char *cipher_list = def_cipher_list; int out_state = def_out_state; - int out_verify = def_out_verify; + unsigned int out_verify = def_out_verify; int verify_mode = def_verify_mode; unsigned int verify_depth = def_verify_depth; @@ -310,7 +324,11 @@ next_arg: out_state = 1; goto next_arg; } else if(strcmp(*argv, "-out_verify") == 0) { - out_verify = 1; + if(argc < 2) + return usage("-out_verify requires an argument", 0); + argc--; argv++; + if(!parse_verify_level(*argv, &out_verify)) + return 1; goto next_arg; } else if(strcmp(*argv, "-v_peer") == 0) { verify_mode |= SSL_VERIFY_PEER; @@ -570,8 +588,10 @@ static SSL_CTX *initialise_ssl_ctx(int server_mode, const char *engine_id, cb_ssl_info_set_output(stderr); /* out_verify */ - if(out_verify) + if(out_verify > 0) { cb_ssl_verify_set_output(stderr); + cb_ssl_verify_set_level(out_verify); + } /* verify_depth */ cb_ssl_verify_set_depth(verify_depth); @@ -857,7 +877,7 @@ static int tunala_item_io(tunala_selector_t *selector, tunala_item_t *item) return 0; } if((item->dirty_read == -1) || (item->dirty_send == -1)) { - if(state_machine_close_dirty(&item->sm)) + if(!state_machine_close_dirty(&item->sm)) return 0; } return 1; diff --git a/demos/tunala/tunala.h b/demos/tunala/tunala.h index 1aaa3e0ab7..7d4e35dc9c 100644 --- a/demos/tunala/tunala.h +++ b/demos/tunala/tunala.h @@ -96,6 +96,7 @@ void cb_ssl_info_set_output(FILE *fp); /* Called if output should be sent too */ int cb_ssl_verify(int ok, X509_STORE_CTX *ctx); void cb_ssl_verify_set_output(FILE *fp); void cb_ssl_verify_set_depth(unsigned int verify_depth); +void cb_ssl_verify_set_level(unsigned int level); #endif /* !defined(NO_OPENSSL) */ #endif /* !defined(NO_BUFFER) */ -- 2.25.1