X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=apps%2Fs_cb.c;h=e339a6ce5d5ea26c7c17049d2f2acba17bc116e0;hp=34c018555965524c5b422c694f5f66679b450d16;hb=2a7cbe77b3abb244c2211d22d7aa3416b97c9342;hpb=18d7158809c9722f4c6d2a8af7513577274f9b56 diff --git a/apps/s_cb.c b/apps/s_cb.c index 34c0185559..e339a6ce5d 100644 --- a/apps/s_cb.c +++ b/apps/s_cb.c @@ -125,6 +125,7 @@ #define COOKIE_SECRET_LENGTH 16 int verify_depth=0; +int verify_quiet=0; int verify_error=X509_V_OK; int verify_return_error=0; unsigned char cookie_secret[COOKIE_SECRET_LENGTH]; @@ -139,15 +140,19 @@ int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx) err= X509_STORE_CTX_get_error(ctx); depth= X509_STORE_CTX_get_error_depth(ctx); - BIO_printf(bio_err,"depth=%d ",depth); - if (err_cert) + if (!verify_quiet || !ok) { - X509_NAME_print_ex(bio_err, X509_get_subject_name(err_cert), + BIO_printf(bio_err,"depth=%d ",depth); + if (err_cert) + { + X509_NAME_print_ex(bio_err, + X509_get_subject_name(err_cert), 0, XN_FLAG_ONELINE); - BIO_puts(bio_err, "\n"); + BIO_puts(bio_err, "\n"); + } + else + BIO_puts(bio_err, "\n"); } - else - BIO_puts(bio_err, "\n"); if (!ok) { BIO_printf(bio_err,"verify error:num=%d:%s\n",err, @@ -188,10 +193,10 @@ int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx) policies_print(bio_err, ctx); break; } - if (err == X509_V_OK && ok == 2) + if (err == X509_V_OK && ok == 2 && !verify_quiet) policies_print(bio_err, ctx); - - BIO_printf(bio_err,"verify return:%d\n",ok); + if (ok && !verify_quiet) + BIO_printf(bio_err,"verify return:%d\n",ok); return(ok); } @@ -251,7 +256,7 @@ int set_cert_stuff(SSL_CTX *ctx, char *cert_file, char *key_file) } int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key, - STACK_OF(X509) *chain) + STACK_OF(X509) *chain, int build_chain) { if (cert == NULL) return 1; @@ -282,12 +287,85 @@ int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key, ERR_print_errors(bio_err); return 0; } + if (!chain && build_chain && !SSL_CTX_build_cert_chain(ctx, 0)) + { + BIO_printf(bio_err,"error building certificate chain\n"); + ERR_print_errors(bio_err); + return 0; + } + return 1; } -static int do_print_sigalgs(BIO *out, SSL *s, int client, int shared) +static void ssl_print_client_cert_types(BIO *bio, SSL *s) + { + const unsigned char *p; + int i; + int cert_type_num = SSL_get0_certificate_types(s, &p); + if (!cert_type_num) + return; + BIO_puts(bio, "Client Certificate Types: "); + for (i = 0; i < cert_type_num; i++) + { + unsigned char cert_type = p[i]; + char *cname; + switch(cert_type) + { + case TLS_CT_RSA_SIGN: + cname = "RSA sign"; + break; + + case TLS_CT_DSS_SIGN: + cname = "DSA sign"; + break; + + case TLS_CT_RSA_FIXED_DH: + cname = "RSA fixed DH"; + break; + + case TLS_CT_DSS_FIXED_DH: + cname = "DSS fixed DH"; + break; + + case TLS_CT_ECDSA_SIGN: + cname = "ECDSA sign"; + break; + + case TLS_CT_RSA_FIXED_ECDH: + cname = "RSA fixed ECDH"; + break; + + case TLS_CT_ECDSA_FIXED_ECDH: + cname = "ECDSA fixed ECDH"; + break; + + case TLS_CT_GOST94_SIGN: + cname = "GOST94 Sign"; + break; + + case TLS_CT_GOST01_SIGN: + cname = "GOST01 Sign"; + break; + + default: + cname = NULL; + } + + if (i) + BIO_puts(bio, ", "); + + if (cname) + BIO_puts(bio, cname); + else + BIO_printf(bio, "UNKNOWN (%d),", cert_type); + } + BIO_puts(bio, "\n"); + } + +static int do_print_sigalgs(BIO *out, SSL *s, int shared) { - int i, nsig; + int i, nsig, client; + client = SSL_is_server(s) ? 0 : 1; if (shared) nsig = SSL_get_shared_sigalgs(s, -1, NULL, NULL, NULL, NULL, NULL); @@ -334,14 +412,19 @@ static int do_print_sigalgs(BIO *out, SSL *s, int client, int shared) return 1; } -int ssl_print_sigalgs(BIO *out, SSL *s, int client) +int ssl_print_sigalgs(BIO *out, SSL *s) { - do_print_sigalgs(out, s, client, 0); - do_print_sigalgs(out, s, client, 1); + int mdnid; + if (!SSL_is_server(s)) + ssl_print_client_cert_types(out, s); + do_print_sigalgs(out, s, 0); + do_print_sigalgs(out, s, 1); + if (SSL_get_peer_signature_nid(s, &mdnid)) + BIO_printf(out, "Peer signing digest: %s\n", OBJ_nid2sn(mdnid)); return 1; } -int ssl_print_curves(BIO *out, SSL *s) +int ssl_print_curves(BIO *out, SSL *s, int noshared) { int i, ncurves, *curves, nid; const char *cname; @@ -369,6 +452,13 @@ int ssl_print_curves(BIO *out, SSL *s) BIO_printf(out, "%s", cname); } } + if (ncurves == 0) + BIO_puts(out, "NONE"); + if (noshared) + { + BIO_puts(out, "\n"); + return 1; + } BIO_puts(out, "\nShared Elliptic curves: "); OPENSSL_free(curves); ncurves = SSL_get_shared_curve(s, -1); @@ -388,6 +478,40 @@ int ssl_print_curves(BIO *out, SSL *s) return 1; } +int ssl_print_tmp_key(BIO *out, SSL *s) + { + EVP_PKEY *key; + if (!SSL_get_server_tmp_key(s, &key)) + return 1; + BIO_puts(out, "Server Temp Key: "); + switch (EVP_PKEY_id(key)) + { + case EVP_PKEY_RSA: + BIO_printf(out, "RSA, %d bits\n", EVP_PKEY_bits(key)); + break; + + case EVP_PKEY_DH: + BIO_printf(out, "DH, %d bits\n", EVP_PKEY_bits(key)); + break; + + case EVP_PKEY_EC: + { + EC_KEY *ec = EVP_PKEY_get1_EC_KEY(key); + int nid; + const char *cname; + nid = EC_GROUP_get_curve_name(EC_KEY_get0_group(ec)); + EC_KEY_free(ec); + cname = EC_curve_nid2nist(nid); + if (!cname) + cname = OBJ_nid2sn(nid); + BIO_printf(out, "ECDH, %s, %d bits\n", + cname, EVP_PKEY_bits(key)); + } + } + EVP_PKEY_free(key); + return 1; + } + long MS_CALLBACK bio_dump_callback(BIO *bio, int cmd, const char *argp, int argi, long argl, long ret) @@ -547,6 +671,8 @@ void MS_CALLBACK msg_cb(int write_p, int version, int content_type, const void * if (version == SSL3_VERSION || version == TLS1_VERSION || + version == TLS1_1_VERSION || + version == TLS1_2_VERSION || version == DTLS1_VERSION || version == DTLS1_BAD_VER) { @@ -1055,15 +1181,49 @@ struct ssl_excert_st X509 *cert; EVP_PKEY *key; STACK_OF(X509) *chain; + int build_chain; struct ssl_excert_st *next, *prev; }; +struct chain_flags + { + int flag; + const char *name; + }; + +struct chain_flags chain_flags_list[] = + { + {CERT_PKEY_VALID, "Overall Validity"}, + {CERT_PKEY_SIGN, "Sign with EE key"}, + {CERT_PKEY_EE_SIGNATURE, "EE signature"}, + {CERT_PKEY_CA_SIGNATURE, "CA signature"}, + {CERT_PKEY_EE_PARAM, "EE key parameters"}, + {CERT_PKEY_CA_PARAM, "CA key parameters"}, + {CERT_PKEY_EXPLICIT_SIGN, "Explicity sign with EE key"}, + {CERT_PKEY_ISSUER_NAME, "Issuer Name"}, + {CERT_PKEY_CERT_TYPE, "Certificate Type"}, + {0, NULL} + }; + + +static void print_chain_flags(BIO *out, int flags) + { + struct chain_flags *ctmp = chain_flags_list; + while(ctmp->name) + { + BIO_printf(out, "\t%s: %s\n", ctmp->name, + flags & ctmp->flag ? "OK" : "NOT OK"); + ctmp++; + } + } + /* Very basic selection callback: just use any certificate chain * reported as valid. More sophisticated could prioritise according * to local policy. */ static int set_cert_cb(SSL *ssl, void *arg) { + int i, rv; SSL_EXCERT *exc = arg; SSL_certs_clear(ssl); @@ -1075,14 +1235,33 @@ static int set_cert_cb(SSL *ssl, void *arg) */ while (exc->next) exc = exc->next; - + + i = 0; + while(exc) { - if (SSL_check_chain(ssl, exc->cert, exc->key, exc->chain)) + i++; + rv = SSL_check_chain(ssl, exc->cert, exc->key, exc->chain); + BIO_printf(bio_err, "Checking cert chain %d:\nSubject: ", i); + X509_NAME_print_ex(bio_err, X509_get_subject_name(exc->cert), 0, + XN_FLAG_ONELINE); + BIO_puts(bio_err, "\n"); + + print_chain_flags(bio_err, rv); + if (rv & CERT_PKEY_VALID) { SSL_use_certificate(ssl, exc->cert); SSL_use_PrivateKey(ssl, exc->key); - if (exc->chain) + /* NB: we wouldn't normally do this as it is + * not efficient building chains on each connection + * better to cache the chain in advance. + */ + if (exc->build_chain) + { + if (!SSL_build_cert_chain(ssl, 0)) + return 0; + } + else if (exc->chain) SSL_set1_chain(ssl, exc->chain); } exc = exc->prev; @@ -1108,6 +1287,7 @@ static int ssl_excert_prepend(SSL_EXCERT **pexc) exc->key = NULL; exc->chain = NULL; exc->prev = NULL; + exc->build_chain = 0; exc->next = *pexc; *pexc = exc; @@ -1192,11 +1372,17 @@ int args_excert(char ***pargs, int *pargc, { char *arg = **pargs, *argn = (*pargs)[1]; SSL_EXCERT *exc = *pexc; - if (!exc && !ssl_excert_prepend(&exc)) + int narg = 2; + if (!exc) { - BIO_printf(err, "Error initialising xcert\n"); - *badarg = 1; - goto err; + if (ssl_excert_prepend(&exc)) + *pexc = exc; + else + { + BIO_printf(err, "Error initialising xcert\n"); + *badarg = 1; + goto err; + } } if (strcmp(arg, "-xcert") == 0) { @@ -1243,6 +1429,11 @@ int args_excert(char ***pargs, int *pargc, } exc->chainfile = argn; } + else if (strcmp(arg,"-xchain_build") == 0) + { + narg = 1; + exc->build_chain = 1; + } else if (strcmp(arg,"-xcertform") == 0) { if (!argn) @@ -1264,10 +1455,10 @@ int args_excert(char ***pargs, int *pargc, else return 0; - (*pargs) += 2; + (*pargs) += narg; if (pargc) - *pargc -= 2; + *pargc -= narg; *pexc = exc; @@ -1280,3 +1471,65 @@ int args_excert(char ***pargs, int *pargc, return 1; } +static void print_raw_cipherlist(BIO *bio, SSL *s) + { + const unsigned char *rlist; + static const unsigned char scsv_id[] = {0, 0, 0xFF}; + size_t i, rlistlen, num; + if (!SSL_is_server(s)) + return; + num = SSL_get0_raw_cipherlist(s, NULL); + rlistlen = SSL_get0_raw_cipherlist(s, &rlist); + BIO_puts(bio, "Client cipher list: "); + for (i = 0; i < rlistlen; i += num, rlist += num) + { + const SSL_CIPHER *c = SSL_CIPHER_find(s, rlist); + if (i) + BIO_puts(bio, ":"); + if (c) + BIO_puts(bio, SSL_CIPHER_get_name(c)); + else if (!memcmp(rlist, scsv_id - num + 3, num)) + BIO_puts(bio, "SCSV"); + else + { + size_t j; + BIO_puts(bio, "0x"); + for (j = 0; j < num; j++) + BIO_printf(bio, "%02X", rlist[j]); + } + } + BIO_puts(bio, "\n"); + } + + +void print_ssl_summary(BIO *bio, SSL *s) + { + const SSL_CIPHER *c; + X509 *peer; + /*const char *pnam = SSL_is_server(s) ? "client" : "server";*/ + BIO_printf(bio, "Protocol version: %s\n", SSL_get_version(s)); + print_raw_cipherlist(bio, s); + c = SSL_get_current_cipher(s); + BIO_printf(bio,"Ciphersuite: %s\n", SSL_CIPHER_get_name(c)); + do_print_sigalgs(bio, s, 0); + peer = SSL_get_peer_certificate(s); + if (peer) + { + int nid; + BIO_puts(bio, "Peer certificate: "); + X509_NAME_print_ex(bio, X509_get_subject_name(peer), + 0, XN_FLAG_ONELINE); + BIO_puts(bio, "\n"); + if (SSL_get_peer_signature_nid(s, &nid)) + BIO_printf(bio, "Hash used: %s\n", OBJ_nid2sn(nid)); + } + else + BIO_puts(bio, "No peer certificate\n"); + if (peer) + X509_free(peer); + if (SSL_is_server(s)) + ssl_print_curves(bio, s, 1); + else + ssl_print_tmp_key(bio, s); + } +