+
+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;
+ }
+
+/* Verbose print out of security callback */
+
+typedef struct
+ {
+ BIO *out;
+ int verbose;
+ int (*old_cb)(SSL *s, SSL_CTX *ctx, int op, int bits, int nid,
+ void *other, void *ex);
+ } security_debug_ex;
+
+static int security_callback_debug(SSL *s, SSL_CTX *ctx,
+ int op, int bits, int nid,
+ void *other, void *ex)
+ {
+ security_debug_ex *sdb = ex;
+ int rv, show_bits = 1, cert_md = 0;
+ const char *nm;
+ rv = sdb->old_cb(s, ctx, op, bits, nid, other, ex);
+ if (rv == 1 && sdb->verbose < 2)
+ return 1;
+ BIO_puts(sdb->out, "Security callback: ");
+
+ switch (op)
+ {
+ case SSL_SECOP_CIPHER_SUPPORTED:
+ nm = "Supported Ciphersuite";
+ break;
+ case SSL_SECOP_CIPHER_SHARED:
+ nm = "Shared Ciphersuite";
+ break;
+ case SSL_SECOP_CIPHER_CHECK:
+ nm = "Check Ciphersuite";
+ break;
+ case SSL_SECOP_TICKET:
+ BIO_puts(sdb->out, "Session ticket");
+ show_bits = 0;
+ nm = NULL;
+ break;
+ case SSL_SECOP_COMPRESSION:
+ BIO_puts(sdb->out, "SSL compression");
+ show_bits = 0;
+ nm = NULL;
+ break;
+#ifndef OPENSSL_NO_DH
+ case SSL_SECOP_TMP_DH:
+ nm = "Temp DH key bits";
+ break;
+#endif
+ case SSL_SECOP_CURVE_SUPPORTED:
+ nm = "Supported Curve";
+ break;
+ case SSL_SECOP_CURVE_SHARED:
+ nm = "Shared Curve";
+ break;
+ case SSL_SECOP_CURVE_CHECK:
+ nm = "Check Curve";
+ break;
+ case SSL_SECOP_SSL2_COMPAT:
+ BIO_puts(sdb->out, "SSLv2 compatible");
+ show_bits = 0;
+ nm = NULL;
+ break;
+ case SSL_SECOP_VERSION:
+ BIO_printf(sdb->out, "Version=%s", ssl_version_str(nid));
+ show_bits = 0;
+ nm = NULL;
+ break;
+ case SSL_SECOP_SIGALG_SUPPORTED:
+ nm = "Supported Signature Algorithm digest";
+ break;
+ case SSL_SECOP_SIGALG_SHARED:
+ nm = "Shared Signature Algorithm digest";
+ break;
+ case SSL_SECOP_SIGALG_CHECK:
+ nm = "Check Signature Algorithm digest";
+ break;
+ case SSL_SECOP_SIGALG_MASK:
+ nm = "Signature Algorithm mask";
+ break;
+ case SSL_SECOP_EE_KEY:
+ nm = "Certificate chain EE key";
+ break;
+ case SSL_SECOP_CA_KEY:
+ nm = "Certificate chain CA key";
+ break;
+ case SSL_SECOP_CA_MD:
+ cert_md = 1;
+ nm = "Certificate chain CA digest";
+ break;
+ case SSL_SECOP_PEER_EE_KEY:
+ nm = "Peer Chain EE key";
+ break;
+ case SSL_SECOP_PEER_CA_KEY:
+ nm = "Peer Chain CA key";
+ break;
+ case SSL_SECOP_PEER_CA_MD:
+ cert_md = 1;
+ nm = "Peer chain CA digest";
+ break;
+ default:
+ nm = NULL;
+ }
+ if (nm)
+ BIO_printf(sdb->out, "%s=", nm);
+
+ switch (op & SSL_SECOP_OTHER_TYPE)
+ {
+
+ case SSL_SECOP_OTHER_CIPHER:
+ BIO_puts(sdb->out, SSL_CIPHER_get_name(other));
+ break;
+
+ case SSL_SECOP_OTHER_CURVE:
+ {
+ const char *cname;
+ cname = EC_curve_nid2nist(nid);
+ if (cname == NULL)
+ cname = OBJ_nid2sn(nid);
+ BIO_puts(sdb->out, cname);
+ }
+ break;
+
+ case SSL_SECOP_OTHER_DH:
+ {
+ DH *dh = other;
+ BIO_printf(sdb->out, "%d", BN_num_bits(dh->p));
+ break;
+ }
+ case SSL_SECOP_OTHER_CERT:
+ {
+ if (cert_md)
+ {
+ int sig_nid = X509_get_signature_nid(other);
+ BIO_puts(sdb->out, OBJ_nid2sn(sig_nid));
+ }
+ else
+ {
+ EVP_PKEY *pkey = X509_get_pubkey(other);
+ const char *algname = "";
+ EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL,
+ &algname,
+ EVP_PKEY_get0_asn1(pkey));
+ BIO_printf(sdb->out, "%s, bits=%d",
+ algname, EVP_PKEY_bits(pkey));
+ EVP_PKEY_free(pkey);
+ }
+ break;
+ }
+ case SSL_SECOP_OTHER_SIGALG:
+ {
+ const unsigned char *salg = other;
+ const char *sname = NULL;
+ switch (salg[1])
+ {
+ case TLSEXT_signature_anonymous:
+ sname = "anonymous";
+ break;
+ case TLSEXT_signature_rsa:
+ sname = "RSA";
+ break;
+ case TLSEXT_signature_dsa:
+ sname = "DSA";
+ break;
+ case TLSEXT_signature_ecdsa:
+ sname = "ECDSA";
+ break;
+ }
+
+ BIO_puts(sdb->out, OBJ_nid2sn(nid));
+ if (sname)
+ BIO_printf(sdb->out, ", algorithm=%s", sname);
+ else
+ BIO_printf(sdb->out, ", algid=%d", salg[1]);
+ break;
+ }
+
+ }
+
+ if (show_bits)
+ BIO_printf(sdb->out, ", security bits=%d", bits);
+ BIO_printf(sdb->out, ": %s\n", rv ? "yes" : "no");
+ return rv;
+ }
+
+void ssl_ctx_security_debug(SSL_CTX *ctx, BIO *out, int verbose)
+ {
+ static security_debug_ex sdb;
+ sdb.out = out;
+ sdb.verbose = verbose;
+ sdb.old_cb = SSL_CTX_get_security_callback(ctx);
+ SSL_CTX_set_security_callback(ctx, security_callback_debug);
+ SSL_CTX_set0_security_ex_data(ctx, &sdb);
+ }
+
+
+