X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=apps%2Fs_cb.c;h=083956916c790580b84b4d8106a2026902506900;hp=2ac3f969a8c3abc0dad1aad515967413cd8b37f5;hb=e02614417d41380c7ccc612375352aac2fab079c;hpb=74ecfab401fe65d23d9b297bf396efca3e419e47 diff --git a/apps/s_cb.c b/apps/s_cb.c index 2ac3f969a8..083956916c 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, @@ -185,13 +190,14 @@ int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx) BIO_printf(bio_err,"\n"); break; case X509_V_ERR_NO_EXPLICIT_POLICY: - policies_print(bio_err, ctx); + if (!verify_quiet) + 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); } @@ -288,7 +294,6 @@ int set_cert_key_stuff(SSL_CTX *ctx, X509 *cert, EVP_PKEY *key, ERR_print_errors(bio_err); return 0; } - return 1; } @@ -409,14 +414,55 @@ static int do_print_sigalgs(BIO *out, SSL *s, int shared) int ssl_print_sigalgs(BIO *out, SSL *s) { + 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; + } +#ifndef OPENSSL_NO_EC +int ssl_print_point_formats(BIO *out, SSL *s) + { + int i, nformats; + const char *pformats; + nformats = SSL_get0_ec_point_formats(s, &pformats); + if (nformats <= 0) + return 1; + BIO_puts(out, "Supported Elliptic Curve Point Formats: "); + for (i = 0; i < nformats; i++, pformats++) + { + if (i) + BIO_puts(out, ":"); + switch(*pformats) + { + case TLSEXT_ECPOINTFORMAT_uncompressed: + BIO_puts(out, "uncompressed"); + break; + + case TLSEXT_ECPOINTFORMAT_ansiX962_compressed_prime: + BIO_puts(out, "ansiX962_compressed_prime"); + break; + + case TLSEXT_ECPOINTFORMAT_ansiX962_compressed_char2: + BIO_puts(out, "ansiX962_compressed_char2"); + break; + + default: + BIO_printf(out, "unknown(%d)", (int)*pformats); + break; + + } + } + if (nformats <= 0) + BIO_puts(out, "NONE"); + BIO_puts(out, "\n"); 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; @@ -444,8 +490,15 @@ int ssl_print_curves(BIO *out, SSL *s) BIO_printf(out, "%s", cname); } } - BIO_puts(out, "\nShared Elliptic curves: "); + if (ncurves == 0) + BIO_puts(out, "NONE"); OPENSSL_free(curves); + if (noshared) + { + BIO_puts(out, "\n"); + return 1; + } + BIO_puts(out, "\nShared Elliptic curves: "); ncurves = SSL_get_shared_curve(s, -1); for (i = 0; i < ncurves; i++) { @@ -462,7 +515,42 @@ int ssl_print_curves(BIO *out, SSL *s) BIO_puts(out, "\n"); return 1; } +#endif +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; +#ifndef OPENSSL_NO_ECDH + 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)); + } +#endif + } + 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) @@ -622,6 +710,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) { @@ -789,6 +879,9 @@ void MS_CALLBACK msg_cb(int write_p, int version, int content_type, const void * case 20: str_details1 = ", Finished"; break; + case 23: + str_details1 = ", SupplementalData"; + break; } } } @@ -930,6 +1023,11 @@ void MS_CALLBACK tlsext_cb(SSL *s, int client_server, int type, extname = "next protocol"; break; #endif +#ifdef TLSEXT_TYPE_encrypt_then_mac + case TLSEXT_TYPE_encrypt_then_mac: + extname = "encrypt-then-mac"; + break; +#endif default: extname = "unknown"; @@ -1134,12 +1232,45 @@ struct ssl_excert_st 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); @@ -1151,10 +1282,20 @@ 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); @@ -1377,3 +1518,233 @@ 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); +#ifndef OPENSSL_NO_EC + ssl_print_point_formats(bio, s); + if (SSL_is_server(s)) + ssl_print_curves(bio, s, 1); + else + ssl_print_tmp_key(bio, s); +#else + if (!SSL_is_server(s)) + ssl_print_tmp_key(bio, s); +#endif + } + +int args_ssl(char ***pargs, int *pargc, SSL_CONF_CTX *cctx, + int *badarg, BIO *err, STACK_OF(OPENSSL_STRING) **pstr) + { + char *arg = **pargs, *argn = (*pargs)[1]; + int rv; + + /* Attempt to run SSL configuration command */ + rv = SSL_CONF_cmd_argv(cctx, pargc, pargs); + /* If parameter not recognised just return */ + if (rv == 0) + return 0; + /* see if missing argument error */ + if (rv == -3) + { + BIO_printf(err, "%s needs an argument\n", arg); + *badarg = 1; + goto end; + } + /* Check for some other error */ + if (rv < 0) + { + BIO_printf(err, "Error with command: \"%s %s\"\n", + arg, argn ? argn : ""); + *badarg = 1; + goto end; + } + /* Store command and argument */ + /* If only one argument processed store value as NULL */ + if (rv == 1) + argn = NULL; + if (!*pstr) + *pstr = sk_OPENSSL_STRING_new_null(); + if (!*pstr || !sk_OPENSSL_STRING_push(*pstr, arg) || + !sk_OPENSSL_STRING_push(*pstr, argn)) + { + BIO_puts(err, "Memory allocation failure\n"); + goto end; + } + + end: + if (*badarg) + ERR_print_errors(err); + + return 1; + } + +int args_ssl_call(SSL_CTX *ctx, BIO *err, SSL_CONF_CTX *cctx, + STACK_OF(OPENSSL_STRING) *str, int no_ecdhe, int no_jpake) + { + int i; + SSL_CONF_CTX_set_ssl_ctx(cctx, ctx); + for (i = 0; i < sk_OPENSSL_STRING_num(str); i+= 2) + { + const char *param = sk_OPENSSL_STRING_value(str, i); + const char *value = sk_OPENSSL_STRING_value(str, i + 1); + /* If no_ecdhe or named curve already specified don't need + * a default. + */ + if (!no_ecdhe && !strcmp(param, "-named_curve")) + no_ecdhe = 1; +#ifndef OPENSSL_NO_JPAKE + if (!no_jpake && !strcmp(param, "-cipher")) + { + BIO_puts(err, "JPAKE sets cipher to PSK\n"); + return 0; + } +#endif + if (SSL_CONF_cmd(cctx, param, value) <= 0) + { + BIO_printf(err, "Error with command: \"%s %s\"\n", + param, value ? value : ""); + ERR_print_errors(err); + return 0; + } + } + /* This is a special case to keep existing s_server functionality: + * if we don't have any curve specified *and* we haven't disabled + * ECDHE then use P-256. + */ + if (!no_ecdhe) + { + if (SSL_CONF_cmd(cctx, "-named_curve", "P-256") <= 0) + { + BIO_puts(err, "Error setting EC curve\n"); + ERR_print_errors(err); + return 0; + } + } +#ifndef OPENSSL_NO_JPAKE + if (!no_jpake) + { + if (SSL_CONF_cmd(cctx, "-cipher", "PSK") <= 0) + { + BIO_puts(err, "Error setting cipher to PSK\n"); + ERR_print_errors(err); + return 0; + } + } +#endif + if (!SSL_CONF_CTX_finish(cctx)) + { + BIO_puts(err, "Error finishing context\n"); + ERR_print_errors(err); + return 0; + } + return 1; + } + +static int add_crls_store(X509_STORE *st, STACK_OF(X509_CRL) *crls) + { + X509_CRL *crl; + int i; + for (i = 0; i < sk_X509_CRL_num(crls); i++) + { + crl = sk_X509_CRL_value(crls, i); + X509_STORE_add_crl(st, crl); + } + return 1; + } + +int ssl_ctx_add_crls(SSL_CTX *ctx, STACK_OF(X509_CRL) *crls, int crl_download) + { + X509_STORE *st; + st = SSL_CTX_get_cert_store(ctx); + add_crls_store(st, crls); + if (crl_download) + store_setup_crl_download(st); + return 1; + } + +int ssl_load_stores(SSL_CTX *ctx, + const char *vfyCApath, const char *vfyCAfile, + const char *chCApath, const char *chCAfile, + STACK_OF(X509_CRL) *crls, int crl_download) + { + X509_STORE *vfy = NULL, *ch = NULL; + int rv = 0; + if (vfyCApath || vfyCAfile) + { + vfy = X509_STORE_new(); + if (!X509_STORE_load_locations(vfy, vfyCAfile, vfyCApath)) + goto err; + add_crls_store(vfy, crls); + SSL_CTX_set1_verify_cert_store(ctx, vfy); + if (crl_download) + store_setup_crl_download(vfy); + } + if (chCApath || chCAfile) + { + ch = X509_STORE_new(); + if (!X509_STORE_load_locations(ch, chCAfile, chCApath)) + goto err; + SSL_CTX_set1_chain_cert_store(ctx, ch); + } + rv = 1; + err: + if (vfy) + X509_STORE_free(vfy); + if (ch) + X509_STORE_free(ch); + return rv; + }