bool SSLConnection::checkCertSigner() { X509_STORE_CTX xsc; X509_STORE *c; bool pass = false; if (!(c = X509_STORE_new())) return false; if (UseSysCerts) { if (!X509_STORE_set_default_paths (c)) { DEBUGPRINT(D_SOCKET,(("X509_STORE_set_default_paths failed"))); } else pass = true; } if (!X509_STORE_load_locations (c, SSLCertFile, NULL)) { DEBUGPRINT(D_SOCKET,("X509_STORE_load_locations_failed")); } else pass = true; if (!pass) { /* nothing to do */ X509_STORE_free (c); return false; } X509_STORE_CTX_init (&xsc, c, cert, NULL); pass = (X509_verify_cert (&xsc) > 0); X509_STORE_CTX_cleanup (&xsc); X509_STORE_free (c); return pass; }
static X509_STORE *create_store(nsp_state *N) { #define __FN__ __FILE__ ":create_store()" X509_STORE *store; X509_LOOKUP *lookup; if (!(store = X509_STORE_new())) { n_warn(N, __FN__, "Error creating X509_STORE_CTX object"); goto err; } X509_STORE_set_verify_cb_func(store, verify_callback); if (X509_STORE_load_locations(store, CA_FILE, CA_DIR) != 1) { n_warn(N, __FN__, "Error loading the CA file or directory"); goto err; } if (X509_STORE_set_default_paths(store) != 1) { n_warn(N, __FN__, "Error loading the system-wide CA certificates"); goto err; } if (!(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()))) { n_warn(N, __FN__, "Error creating X509_LOOKUP object"); goto err; } if (X509_load_crl_file(lookup, CRL_FILE, X509_FILETYPE_PEM) != 1) { n_warn(N, __FN__, "Error reading the CRL file"); goto err; } X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); return store; err: return NULL; #undef __FN__ }
int main(int argc, char *argv[]) { X509 *cert; X509_STORE *store; X509_LOOKUP *lookup; X509_STORE_CTX *verify_ctx; FILE *fp; OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); /* frist read the client certificate */ if (!(fp = fopen(CLIENT_CERT, "r"))) { int_error("Error reading client certificate file"); } if (!(cert = PEM_read_X509(fp, NULL, NULL, NULL))) { int_error("Error reading client certificate in file"); } fclose(fp); /* create the cert store and set the verify callback */ if (!(store = X509_STORE_new())) { int_error("Error creating X509_STORE_CTX object"); } X509_STORE_set_verify_cb_func(store, verify_callback); /* load the CA certificates and CRLs */ if (X509_STORE_load_locations(store, CA_FILE, CA_DIR) != 1) { int_error("Error loading the CA file or directory"); } if (X509_STORE_set_default_paths(store) != 1) { int_error("Error loading the system-wide CA certificates"); } if (!(lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file()))) { int_error("Error creating X509_LOOKUP object"); } if (X509_load_crl_file(lookup, CRL_FILE, X509_FILETYPE_PEM) != 1) { int_error("Error reading the CRL file"); } /* set the flags of the store so that the CRLs are consulted */ X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); /* create a verification context and initialize it */ if (!(verify_ctx = X509_STORE_CTX_new())) { int_error("Error creating X509_STORE_CTX object"); } if (X509_STORE_CTX_init(verify_ctx, store, cert, NULL) != 1) { int_error("Error initializing verification context"); } /* verify the certificate */ if (X509_verify_cert(verify_ctx) != 1) { int_error("Error verifying the certificate"); } else { printf("Certificate verified correctly!\n"); } return 0; }
/** * @brief HTTPS::HTTPS * @param inServer * @param inPath * @param args * @param max_redir */ HTTPS::HTTPS(std::string inServer, std::string inPath, Arguments *args, int max_redir) : HTTP(inServer, inPath, max_redir) { m_args = args; ctx = NULL; ssl = NULL; SSL_library_init(); OpenSSL_add_all_algorithms(); // requited initialization functions m_port = 443; // port for SSL ctx = SSL_CTX_new(SSLv23_client_method()); // for better compatibility if (args->getCertfileUsed()) // if we are using certfile { if (!SSL_CTX_load_verify_locations(ctx, args->sCertFileName().c_str(), NULL)) // test the file { throw ISAException("Error - Loading Certificate File"); } } else if (args->getCertfileFolderUsed()) // if we are using a folder { if (!SSL_CTX_load_verify_locations(ctx, NULL, args->sCertFilesFolder().c_str())) // test the folder { throw ISAException("Error - Loading Certificates from a folder"); } } else { if (!SSL_CTX_load_verify_locations(ctx, NULL, "/etc/ssl/certs/")) // default folder for certs { throw ISAException("Error - Loading cerificates from /etc/ssl/certs"); } } SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL); SSL_CTX_set_options(ctx, SSL_OP_SINGLE_DH_USE); SSL_CTX_get_cert_store(ctx); // set up a store certstore = X509_STORE_new(); // create a new one if (m_args->getCertfileUsed()) X509_STORE_load_locations(certstore, m_args->sCertFileName().c_str(), NULL); // if we use file, test again else if (m_args->getCertfileFolderUsed()) X509_STORE_load_locations(certstore, NULL, m_args->sCertFilesFolder().c_str()); // test folder else X509_STORE_load_locations(certstore, NULL, "/etc/ssl/certs/"); // else load default location if (certstore == NULL) throw ISAException("Error - Certificate could not be loaded."); // error, throw ISAException SSL_CTX_set_cert_store(ctx, certstore); // set up the store with ctx }
static int check_certificate_by_signer (X509 *peercert) { X509_STORE_CTX *xsc; X509_STORE *ctx; int pass = 0, i; ctx = X509_STORE_new (); if (ctx == NULL) return 0; if (option (OPTSSLSYSTEMCERTS)) { if (X509_STORE_set_default_paths (ctx)) pass++; else dprint (2, (debugfile, "X509_STORE_set_default_paths failed\n")); } if (X509_STORE_load_locations (ctx, SslCertFile, NULL)) pass++; else dprint (2, (debugfile, "X509_STORE_load_locations failed\n")); for (i = 0; i < sk_X509_num (SslSessionCerts); i++) pass += (X509_STORE_add_cert (ctx, sk_X509_value (SslSessionCerts, i)) != 0); if (pass == 0) { /* nothing to do */ X509_STORE_free (ctx); return 0; } xsc = X509_STORE_CTX_new(); if (xsc == NULL) return 0; X509_STORE_CTX_init (xsc, ctx, peercert, SslSessionCerts); pass = (X509_verify_cert (xsc) > 0); #ifdef DEBUG if (! pass) { char buf[SHORT_STRING]; int err; err = X509_STORE_CTX_get_error (xsc); snprintf (buf, sizeof (buf), "%s (%d)", X509_verify_cert_error_string(err), err); dprint (2, (debugfile, "X509_verify_cert: %s\n", buf)); dprint (2, (debugfile, " [%s]\n", peercert->name)); } #endif X509_STORE_CTX_free (xsc); X509_STORE_free (ctx); return pass; }
/// \brief Used by pkcs7_main() - not to be used directly. /// /// \param N/A /// \return N/A /// X509_STORE * create_store (void) { X509_STORE *store; X509_LOOKUP *lookup; /* create the cert store and set the verify callback */ if (!(store = X509_STORE_new ())) { fprintf (stderr, "Error creating X509_STORE_CTX object\n"); goto err; } X509_STORE_set_verify_cb_func (store, verify_callback); /* load the CA certificates and CRLs */ if (X509_STORE_load_locations (store, CA_FILE, CA_DIR) != 1) { fprintf (stderr, "Error loading the CA file or directory\n"); goto err; } if (X509_STORE_set_default_paths (store) != 1) { fprintf (stderr, "Error loading the system-wide CA certificates\n"); goto err; } if (!(lookup = X509_STORE_add_lookup (store, X509_LOOKUP_file ()))) { fprintf (stderr, "Error creating X509_LOOKUP object\n"); goto err; } /* if (X509_load_crl_file (lookup, CRL_FILE, X509_FILETYPE_PEM) != 1) { fprintf (stderr, "Error reading the CRL file\n"); goto err; } */ /* set the flags of the store so that CRLs are consulted */ X509_STORE_set_flags (store, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); return store; err: return NULL; }
static X509_STORE *X509_default_lookup(unsigned long issuer_name_hash) { static X509_STORE *store = NULL; if (!store) store = X509_STORE_new(); check(store, "Failed to create trust store"); if (!X509_STORE_load_locations(store, NULL, x509_default_dir)) { log_err("Failed to load trusted certificates"); X509_STORE_free(store); store = NULL; } err: return store; }
static int do_store(SSL_CONF_CTX *cctx, const char *CAfile, const char *CApath, int verify_store) { CERT *cert; X509_STORE **st; if (cctx->ctx) cert = cctx->ctx->cert; else if (cctx->ssl) cert = cctx->ssl->cert; else return 1; st = verify_store ? &cert->verify_store : &cert->chain_store; if (*st == NULL) { *st = X509_STORE_new(); if (*st == NULL) return 0; } return X509_STORE_load_locations(*st, CAfile, CApath) > 0; }
int ca_X509_verify(void *certificate, void *chain, const char *CAfile, const char *CRLfile, const char **errstr) { X509_STORE *store = NULL; X509_STORE_CTX *xsc = NULL; int ret = 0; if ((store = X509_STORE_new()) == NULL) goto end; if (!X509_STORE_load_locations(store, CAfile, NULL)) { log_warn("warn: unable to load CA file %s", CAfile); goto end; } X509_STORE_set_default_paths(store); if ((xsc = X509_STORE_CTX_new()) == NULL) goto end; if (X509_STORE_CTX_init(xsc, store, certificate, chain) != 1) goto end; X509_STORE_CTX_set_verify_cb(xsc, ca_verify_cb); ret = X509_verify_cert(xsc); end: *errstr = NULL; if (ret != 1) { if (xsc) *errstr = X509_verify_cert_error_string(xsc->error); else if (ERR_peek_last_error()) *errstr = ERR_error_string(ERR_peek_last_error(), NULL); } if (xsc) X509_STORE_CTX_free(xsc); if (store) X509_STORE_free(store); return ret > 0 ? 1 : 0; }
/* * Create Global X509 revocation store and use it to verify * OCSP responses * * - Load the trusted CAs * - Load the trusted issuer certificates */ static X509_STORE *init_revocation_store(EAP_TLS_CONF *conf) { X509_STORE *store = NULL; store = X509_STORE_new(); /* Load the CAs we trust */ if (conf->ca_file || conf->ca_path) if(!X509_STORE_load_locations(store, conf->ca_file, conf->ca_path)) { radlog(L_ERR, "rlm_eap: X509_STORE error %s", ERR_error_string(ERR_get_error(), NULL)); radlog(L_ERR, "rlm_eap_tls: Error reading Trusted root CA list %s",conf->ca_file ); return NULL; } #ifdef X509_V_FLAG_CRL_CHECK if (conf->check_crl) X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK); #endif return store; }
int s2n_x509_trust_store_from_ca_file(struct s2n_x509_trust_store *store, const char *ca_pem_filename, const char *ca_dir) { if (!store->trust_store) { store->trust_store = X509_STORE_new(); notnull_check(store->trust_store); } int err_code = X509_STORE_load_locations(store->trust_store, ca_pem_filename, ca_dir); if (!err_code) { s2n_x509_trust_store_wipe(store); return -1; } /* It's a likely scenario if this function is called, a self-signed certificate is used, and that is was generated * without a trust anchor. However if you call this function, the assumption is you trust ca_file or path and if a certificate * is encountered that's in that path, it should be trusted. The following flag tells libcrypto to not care that the cert * is missing a root anchor. */ unsigned long flags = X509_VP_FLAG_DEFAULT; flags |= X509_V_FLAG_PARTIAL_CHAIN; X509_STORE_set_flags(store->trust_store, flags); return 0; }
/* * Initialize global SSL context. */ void be_tls_init(void) { struct stat buf; STACK_OF(X509_NAME) *root_cert_list = NULL; if (!SSL_context) { #if SSLEAY_VERSION_NUMBER >= 0x0907000L OPENSSL_config(NULL); #endif SSL_library_init(); SSL_load_error_strings(); /* * We use SSLv23_method() because it can negotiate use of the highest * mutually supported protocol version, while alternatives like * TLSv1_2_method() permit only one specific version. Note that we * don't actually allow SSL v2 or v3, only TLS protocols (see below). */ SSL_context = SSL_CTX_new(SSLv23_method()); if (!SSL_context) ereport(FATAL, (errmsg("could not create SSL context: %s", SSLerrmessage()))); /* * Disable OpenSSL's moving-write-buffer sanity check, because it * causes unnecessary failures in nonblocking send cases. */ SSL_CTX_set_mode(SSL_context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); /* * Load and verify server's certificate and private key */ if (SSL_CTX_use_certificate_chain_file(SSL_context, ssl_cert_file) != 1) ereport(FATAL, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("could not load server certificate file \"%s\": %s", ssl_cert_file, SSLerrmessage()))); if (stat(ssl_key_file, &buf) != 0) ereport(FATAL, (errcode_for_file_access(), errmsg("could not access private key file \"%s\": %m", ssl_key_file))); /* * Require no public access to key file. * * XXX temporarily suppress check when on Windows, because there may * not be proper support for Unix-y file permissions. Need to think * of a reasonable check to apply on Windows. (See also the data * directory permission check in postmaster.c) */ #if !defined(WIN32) && !defined(__CYGWIN__) if (!S_ISREG(buf.st_mode) || buf.st_mode & (S_IRWXG | S_IRWXO)) ereport(FATAL, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("private key file \"%s\" has group or world access", ssl_key_file), errdetail("Permissions should be u=rw (0600) or less."))); #endif if (SSL_CTX_use_PrivateKey_file(SSL_context, ssl_key_file, SSL_FILETYPE_PEM) != 1) ereport(FATAL, (errmsg("could not load private key file \"%s\": %s", ssl_key_file, SSLerrmessage()))); if (SSL_CTX_check_private_key(SSL_context) != 1) ereport(FATAL, (errmsg("check of private key failed: %s", SSLerrmessage()))); } /* set up ephemeral DH keys, and disallow SSL v2/v3 while at it */ SSL_CTX_set_tmp_dh_callback(SSL_context, tmp_dh_cb); SSL_CTX_set_options(SSL_context, SSL_OP_SINGLE_DH_USE | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3); /* set up ephemeral ECDH keys */ initialize_ecdh(); /* set up the allowed cipher list */ if (SSL_CTX_set_cipher_list(SSL_context, SSLCipherSuites) != 1) elog(FATAL, "could not set the cipher list (no valid ciphers available)"); /* Let server choose order */ if (SSLPreferServerCiphers) SSL_CTX_set_options(SSL_context, SSL_OP_CIPHER_SERVER_PREFERENCE); /* * Load CA store, so we can verify client certificates if needed. */ if (ssl_ca_file[0]) { if (SSL_CTX_load_verify_locations(SSL_context, ssl_ca_file, NULL) != 1 || (root_cert_list = SSL_load_client_CA_file(ssl_ca_file)) == NULL) ereport(FATAL, (errmsg("could not load root certificate file \"%s\": %s", ssl_ca_file, SSLerrmessage()))); } /*---------- * Load the Certificate Revocation List (CRL). * http://searchsecurity.techtarget.com/sDefinition/0,,sid14_gci803160,00.html *---------- */ if (ssl_crl_file[0]) { X509_STORE *cvstore = SSL_CTX_get_cert_store(SSL_context); if (cvstore) { /* Set the flags to check against the complete CRL chain */ if (X509_STORE_load_locations(cvstore, ssl_crl_file, NULL) == 1) { /* OpenSSL 0.96 does not support X509_V_FLAG_CRL_CHECK */ #ifdef X509_V_FLAG_CRL_CHECK X509_STORE_set_flags(cvstore, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); #else ereport(LOG, (errmsg("SSL certificate revocation list file \"%s\" ignored", ssl_crl_file), errdetail("SSL library does not support certificate revocation lists."))); #endif } else ereport(FATAL, (errmsg("could not load SSL certificate revocation list file \"%s\": %s", ssl_crl_file, SSLerrmessage()))); } } if (ssl_ca_file[0]) { /* * Always ask for SSL client cert, but don't fail if it's not * presented. We might fail such connections later, depending on what * we find in pg_hba.conf. */ SSL_CTX_set_verify(SSL_context, (SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE), verify_cb); /* Set flag to remember CA store is successfully loaded */ ssl_loaded_verify_locations = true; /* * Tell OpenSSL to send the list of root certs we trust to clients in * CertificateRequests. This lets a client with a keystore select the * appropriate client certificate to send to us. */ SSL_CTX_set_client_CA_list(SSL_context, root_cert_list); } }
/* * Initialize global SSL context. */ static void initialize_SSL(void) { struct stat buf; STACK_OF(X509_NAME) *root_cert_list = NULL; if (!SSL_context) { #if SSLEAY_VERSION_NUMBER >= 0x0907000L OPENSSL_config(NULL); #endif SSL_library_init(); SSL_load_error_strings(); SSL_context = SSL_CTX_new(SSLv23_method()); if (!SSL_context) ereport(FATAL, (errmsg("could not create SSL context: %s", SSLerrmessage()))); /* * Disable OpenSSL's moving-write-buffer sanity check, because it * causes unnecessary failures in nonblocking send cases. */ SSL_CTX_set_mode(SSL_context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); /* * Load and verify server's certificate and private key */ if (SSL_CTX_use_certificate_chain_file(SSL_context, SERVER_CERT_FILE) != 1) ereport(FATAL, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("could not load server certificate file \"%s\": %s", SERVER_CERT_FILE, SSLerrmessage()))); if (stat(SERVER_PRIVATE_KEY_FILE, &buf) != 0) ereport(FATAL, (errcode_for_file_access(), errmsg("could not access private key file \"%s\": %m", SERVER_PRIVATE_KEY_FILE))); /* * Require no public access to key file. * * XXX temporarily suppress check when on Windows, because there may * not be proper support for Unix-y file permissions. Need to think * of a reasonable check to apply on Windows. (See also the data * directory permission check in postmaster.c) */ #if !defined(WIN32) && !defined(__CYGWIN__) if (!S_ISREG(buf.st_mode) || buf.st_mode & (S_IRWXG | S_IRWXO)) ereport(FATAL, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("private key file \"%s\" has group or world access", SERVER_PRIVATE_KEY_FILE), errdetail("Permissions should be u=rw (0600) or less."))); #endif if (SSL_CTX_use_PrivateKey_file(SSL_context, SERVER_PRIVATE_KEY_FILE, SSL_FILETYPE_PEM) != 1) ereport(FATAL, (errmsg("could not load private key file \"%s\": %s", SERVER_PRIVATE_KEY_FILE, SSLerrmessage()))); if (SSL_CTX_check_private_key(SSL_context) != 1) ereport(FATAL, (errmsg("check of private key failed: %s", SSLerrmessage()))); } /* set up ephemeral DH keys, and disallow SSL v2 while at it */ SSL_CTX_set_tmp_dh_callback(SSL_context, tmp_dh_cb); SSL_CTX_set_options(SSL_context, SSL_OP_SINGLE_DH_USE | SSL_OP_NO_SSLv2); /* set up the allowed cipher list */ if (SSL_CTX_set_cipher_list(SSL_context, SSLCipherSuites) != 1) elog(FATAL, "could not set the cipher list (no valid ciphers available)"); /* * Attempt to load CA store, so we can verify client certificates if * needed. */ ssl_loaded_verify_locations = false; if (access(ROOT_CERT_FILE, R_OK) != 0) { /* * If root certificate file simply not found, don't log an error here, * because it's quite likely the user isn't planning on using client * certificates. If we can't access it for other reasons, it is an * error. */ if (errno != ENOENT) ereport(FATAL, (errmsg("could not access root certificate file \"%s\": %m", ROOT_CERT_FILE))); } else if (SSL_CTX_load_verify_locations(SSL_context, ROOT_CERT_FILE, NULL) != 1 || (root_cert_list = SSL_load_client_CA_file(ROOT_CERT_FILE)) == NULL) { /* * File was there, but we could not load it. This means the file is * somehow broken, and we cannot do verification at all - so fail. */ ereport(FATAL, (errmsg("could not load root certificate file \"%s\": %s", ROOT_CERT_FILE, SSLerrmessage()))); } else { /*---------- * Load the Certificate Revocation List (CRL) if file exists. * http://searchsecurity.techtarget.com/sDefinition/0,,sid14_gci803160,00.html *---------- */ X509_STORE *cvstore = SSL_CTX_get_cert_store(SSL_context); if (cvstore) { /* Set the flags to check against the complete CRL chain */ if (X509_STORE_load_locations(cvstore, ROOT_CRL_FILE, NULL) == 1) { /* OpenSSL 0.96 does not support X509_V_FLAG_CRL_CHECK */ #ifdef X509_V_FLAG_CRL_CHECK X509_STORE_set_flags(cvstore, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); #else ereport(LOG, (errmsg("SSL certificate revocation list file \"%s\" ignored", ROOT_CRL_FILE), errdetail("SSL library does not support certificate revocation lists."))); #endif } else { /* Not fatal - we do not require CRL */ ereport(LOG, (errmsg("SSL certificate revocation list file \"%s\" not found, skipping: %s", ROOT_CRL_FILE, SSLerrmessage()), errdetail("Certificates will not be checked against revocation list."))); } /* * Always ask for SSL client cert, but don't fail if it's not * presented. We might fail such connections later, depending on * what we find in pg_hba.conf. */ SSL_CTX_set_verify(SSL_context, (SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE), verify_cb); /* Set flag to remember CA store is successfully loaded */ ssl_loaded_verify_locations = true; } /* * Tell OpenSSL to send the list of root certs we trust to clients in * CertificateRequests. This lets a client with a keystore select the * appropriate client certificate to send to us. */ SSL_CTX_set_client_CA_list(SSL_context, root_cert_list); } }
int easy_pkcs7_verify(const char *content, size_t len, const char *signature, size_t signature_len, const char *anchor, int is_pkg) { STACK_OF(X509) *cert_chain, *signers; X509_STORE *store; BIO *sig, *in; PKCS7 *p7; int i, status; X509_NAME *name; char *subject; OpenSSL_add_all_algorithms(); ERR_load_crypto_strings(); status = -1; if (cert_chain_file) cert_chain = file_to_certs(cert_chain_file); else cert_chain = NULL; store = X509_STORE_new(); if (store == NULL) { sk_X509_free(cert_chain); warnx("Failed to create certificate store"); return -1; } X509_STORE_load_locations(store, anchor, NULL); in = BIO_new_mem_buf(__UNCONST(content), len); sig = BIO_new_mem_buf(__UNCONST(signature), signature_len); signers = NULL; p7 = PEM_read_bio_PKCS7(sig, NULL, NULL, NULL); if (p7 == NULL) { warnx("Failed to parse the signature"); goto cleanup; } if (PKCS7_verify(p7, cert_chain, store, in, NULL, 0) != 1) { warnx("Failed to verify signature"); goto cleanup; } signers = PKCS7_get0_signers(p7, NULL, 0); if (signers == NULL) { warnx("Failed to get signers"); goto cleanup; } if (sk_X509_num(signers) == 0) { warnx("No signers found"); goto cleanup; } for (i = 0; i < sk_X509_num(signers); i++) { /* Compute ex_xkusage */ X509_check_purpose(sk_X509_value(signers, i), -1, -1); if (check_ca(sk_X509_value(signers, i))) { warnx("CA keys are not valid for signatures"); goto cleanup; } if (is_pkg) { if (sk_X509_value(signers, i)->ex_xkusage != pkg_key_usage) { warnx("Certificate must have CODE SIGNING " "and EMAIL PROTECTION property"); goto cleanup; } } else { if (sk_X509_value(signers, i)->ex_xkusage != 0) { warnx("Certificate must not have any property"); goto cleanup; } } } printf("Sigature ok, signed by:\n"); for (i = 0; i < sk_X509_num(signers); i++) { name = X509_get_subject_name(sk_X509_value(signers, i)); subject = X509_NAME_oneline(name, NULL, 0); printf("\t%s\n", subject); OPENSSL_free(subject); } status = 0; cleanup: sk_X509_free(cert_chain); sk_X509_free(signers); X509_STORE_free(store); PKCS7_free(p7); BIO_free(in); BIO_free(sig); return status; }
int pkcs12_main(int argc, char **argv) { ENGINE *e = NULL; char *infile = NULL, *outfile = NULL, *keyname = NULL; char *certfile = NULL; BIO *in = NULL, *out = NULL; char **args; char *name = NULL; char *csp_name = NULL; int add_lmk = 0; PKCS12 *p12 = NULL; char pass[50], macpass[50]; int export_cert = 0; int options = 0; int chain = 0; int badarg = 0; int iter = PKCS12_DEFAULT_ITER; int maciter = PKCS12_DEFAULT_ITER; int twopass = 0; int keytype = 0; int cert_pbe; int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; int ret = 1; int macver = 1; int noprompt = 0; STACK_OF(OPENSSL_STRING) * canames = NULL; char *cpass = NULL, *mpass = NULL; char *passargin = NULL, *passargout = NULL, *passarg = NULL; char *passin = NULL, *passout = NULL; char *inrand = NULL; char *macalg = NULL; char *CApath = NULL, *CAfile = NULL; #ifndef OPENSSL_NO_ENGINE char *engine = NULL; #endif signal(SIGPIPE, SIG_IGN); cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC; enc = EVP_des_ede3_cbc(); if (bio_err == NULL) bio_err = BIO_new_fp(stderr, BIO_NOCLOSE); if (!load_config(bio_err, NULL)) goto end; args = argv + 1; while (*args) { if (*args[0] == '-') { if (!strcmp(*args, "-nokeys")) options |= NOKEYS; else if (!strcmp(*args, "-keyex")) keytype = KEY_EX; else if (!strcmp(*args, "-keysig")) keytype = KEY_SIG; else if (!strcmp(*args, "-nocerts")) options |= NOCERTS; else if (!strcmp(*args, "-clcerts")) options |= CLCERTS; else if (!strcmp(*args, "-cacerts")) options |= CACERTS; else if (!strcmp(*args, "-noout")) options |= (NOKEYS | NOCERTS); else if (!strcmp(*args, "-info")) options |= INFO; else if (!strcmp(*args, "-chain")) chain = 1; else if (!strcmp(*args, "-twopass")) twopass = 1; else if (!strcmp(*args, "-nomacver")) macver = 0; else if (!strcmp(*args, "-descert")) cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; else if (!strcmp(*args, "-export")) export_cert = 1; else if (!strcmp(*args, "-des")) enc = EVP_des_cbc(); else if (!strcmp(*args, "-des3")) enc = EVP_des_ede3_cbc(); #ifndef OPENSSL_NO_IDEA else if (!strcmp(*args, "-idea")) enc = EVP_idea_cbc(); #endif #ifndef OPENSSL_NO_SEED else if (!strcmp(*args, "-seed")) enc = EVP_seed_cbc(); #endif #ifndef OPENSSL_NO_AES else if (!strcmp(*args, "-aes128")) enc = EVP_aes_128_cbc(); else if (!strcmp(*args, "-aes192")) enc = EVP_aes_192_cbc(); else if (!strcmp(*args, "-aes256")) enc = EVP_aes_256_cbc(); #endif #ifndef OPENSSL_NO_CAMELLIA else if (!strcmp(*args, "-camellia128")) enc = EVP_camellia_128_cbc(); else if (!strcmp(*args, "-camellia192")) enc = EVP_camellia_192_cbc(); else if (!strcmp(*args, "-camellia256")) enc = EVP_camellia_256_cbc(); #endif else if (!strcmp(*args, "-noiter")) iter = 1; else if (!strcmp(*args, "-maciter")) maciter = PKCS12_DEFAULT_ITER; else if (!strcmp(*args, "-nomaciter")) maciter = 1; else if (!strcmp(*args, "-nomac")) maciter = -1; else if (!strcmp(*args, "-macalg")) if (args[1]) { args++; macalg = *args; } else badarg = 1; else if (!strcmp(*args, "-nodes")) enc = NULL; else if (!strcmp(*args, "-certpbe")) { if (!set_pbe(bio_err, &cert_pbe, *++args)) badarg = 1; } else if (!strcmp(*args, "-keypbe")) { if (!set_pbe(bio_err, &key_pbe, *++args)) badarg = 1; } else if (!strcmp(*args, "-rand")) { if (args[1]) { args++; inrand = *args; } else badarg = 1; } else if (!strcmp(*args, "-inkey")) { if (args[1]) { args++; keyname = *args; } else badarg = 1; } else if (!strcmp(*args, "-certfile")) { if (args[1]) { args++; certfile = *args; } else badarg = 1; } else if (!strcmp(*args, "-name")) { if (args[1]) { args++; name = *args; } else badarg = 1; } else if (!strcmp(*args, "-LMK")) add_lmk = 1; else if (!strcmp(*args, "-CSP")) { if (args[1]) { args++; csp_name = *args; } else badarg = 1; } else if (!strcmp(*args, "-caname")) { if (args[1]) { args++; if (!canames) canames = sk_OPENSSL_STRING_new_null(); sk_OPENSSL_STRING_push(canames, *args); } else badarg = 1; } else if (!strcmp(*args, "-in")) { if (args[1]) { args++; infile = *args; } else badarg = 1; } else if (!strcmp(*args, "-out")) { if (args[1]) { args++; outfile = *args; } else badarg = 1; } else if (!strcmp(*args, "-passin")) { if (args[1]) { args++; passargin = *args; } else badarg = 1; } else if (!strcmp(*args, "-passout")) { if (args[1]) { args++; passargout = *args; } else badarg = 1; } else if (!strcmp(*args, "-password")) { if (args[1]) { args++; passarg = *args; noprompt = 1; } else badarg = 1; } else if (!strcmp(*args, "-CApath")) { if (args[1]) { args++; CApath = *args; } else badarg = 1; } else if (!strcmp(*args, "-CAfile")) { if (args[1]) { args++; CAfile = *args; } else badarg = 1; #ifndef OPENSSL_NO_ENGINE } else if (!strcmp(*args, "-engine")) { if (args[1]) { args++; engine = *args; } else badarg = 1; #endif } else badarg = 1; } else badarg = 1; args++; } if (badarg) { BIO_printf(bio_err, "Usage: pkcs12 [options]\n"); BIO_printf(bio_err, "where options are\n"); BIO_printf(bio_err, "-export output PKCS12 file\n"); BIO_printf(bio_err, "-chain add certificate chain\n"); BIO_printf(bio_err, "-inkey file private key if not infile\n"); BIO_printf(bio_err, "-certfile f add all certs in f\n"); BIO_printf(bio_err, "-CApath arg - PEM format directory of CA's\n"); BIO_printf(bio_err, "-CAfile arg - PEM format file of CA's\n"); BIO_printf(bio_err, "-name \"name\" use name as friendly name\n"); BIO_printf(bio_err, "-caname \"nm\" use nm as CA friendly name (can be used more than once).\n"); BIO_printf(bio_err, "-in infile input filename\n"); BIO_printf(bio_err, "-out outfile output filename\n"); BIO_printf(bio_err, "-noout don't output anything, just verify.\n"); BIO_printf(bio_err, "-nomacver don't verify MAC.\n"); BIO_printf(bio_err, "-nocerts don't output certificates.\n"); BIO_printf(bio_err, "-clcerts only output client certificates.\n"); BIO_printf(bio_err, "-cacerts only output CA certificates.\n"); BIO_printf(bio_err, "-nokeys don't output private keys.\n"); BIO_printf(bio_err, "-info give info about PKCS#12 structure.\n"); BIO_printf(bio_err, "-des encrypt private keys with DES\n"); BIO_printf(bio_err, "-des3 encrypt private keys with triple DES (default)\n"); #ifndef OPENSSL_NO_IDEA BIO_printf(bio_err, "-idea encrypt private keys with idea\n"); #endif #ifndef OPENSSL_NO_SEED BIO_printf(bio_err, "-seed encrypt private keys with seed\n"); #endif #ifndef OPENSSL_NO_AES BIO_printf(bio_err, "-aes128, -aes192, -aes256\n"); BIO_printf(bio_err, " encrypt PEM output with cbc aes\n"); #endif #ifndef OPENSSL_NO_CAMELLIA BIO_printf(bio_err, "-camellia128, -camellia192, -camellia256\n"); BIO_printf(bio_err, " encrypt PEM output with cbc camellia\n"); #endif BIO_printf(bio_err, "-nodes don't encrypt private keys\n"); BIO_printf(bio_err, "-noiter don't use encryption iteration\n"); BIO_printf(bio_err, "-nomaciter don't use MAC iteration\n"); BIO_printf(bio_err, "-maciter use MAC iteration\n"); BIO_printf(bio_err, "-nomac don't generate MAC\n"); BIO_printf(bio_err, "-twopass separate MAC, encryption passwords\n"); BIO_printf(bio_err, "-descert encrypt PKCS#12 certificates with triple DES (default RC2-40)\n"); BIO_printf(bio_err, "-certpbe alg specify certificate PBE algorithm (default RC2-40)\n"); BIO_printf(bio_err, "-keypbe alg specify private key PBE algorithm (default 3DES)\n"); BIO_printf(bio_err, "-macalg alg digest algorithm used in MAC (default SHA1)\n"); BIO_printf(bio_err, "-keyex set MS key exchange type\n"); BIO_printf(bio_err, "-keysig set MS key signature type\n"); BIO_printf(bio_err, "-password p set import/export password source\n"); BIO_printf(bio_err, "-passin p input file pass phrase source\n"); BIO_printf(bio_err, "-passout p output file pass phrase source\n"); #ifndef OPENSSL_NO_ENGINE BIO_printf(bio_err, "-engine e use engine e, possibly a hardware device.\n"); #endif BIO_printf(bio_err, "-rand file:file:...\n"); BIO_printf(bio_err, " load the file (or the files in the directory) into\n"); BIO_printf(bio_err, " the random number generator\n"); BIO_printf(bio_err, "-CSP name Microsoft CSP name\n"); BIO_printf(bio_err, "-LMK Add local machine keyset attribute to private key\n"); goto end; } #ifndef OPENSSL_NO_ENGINE e = setup_engine(bio_err, engine, 0); #endif if (passarg) { if (export_cert) passargout = passarg; else passargin = passarg; } if (!app_passwd(bio_err, passargin, passargout, &passin, &passout)) { BIO_printf(bio_err, "Error getting passwords\n"); goto end; } if (!cpass) { if (export_cert) cpass = passout; else cpass = passin; } if (cpass) { mpass = cpass; noprompt = 1; } else { cpass = pass; mpass = macpass; } ERR_load_crypto_strings(); #ifdef CRYPTO_MDEBUG CRYPTO_push_info("read files"); #endif if (!infile) in = BIO_new_fp(stdin, BIO_NOCLOSE); else in = BIO_new_file(infile, "rb"); if (!in) { BIO_printf(bio_err, "Error opening input file %s\n", infile ? infile : "<stdin>"); perror(infile); goto end; } #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("write files"); #endif if (!outfile) { out = BIO_new_fp(stdout, BIO_NOCLOSE); } else out = BIO_new_file(outfile, "wb"); if (!out) { BIO_printf(bio_err, "Error opening output file %s\n", outfile ? outfile : "<stdout>"); perror(outfile); goto end; } if (twopass) { #ifdef CRYPTO_MDEBUG CRYPTO_push_info("read MAC password"); #endif if (EVP_read_pw_string(macpass, sizeof macpass, "Enter MAC Password:"******"Can't read Password\n"); goto end; } #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); #endif } if (export_cert) { EVP_PKEY *key = NULL; X509 *ucert = NULL, *x = NULL; STACK_OF(X509) * certs = NULL; const EVP_MD *macmd = NULL; unsigned char *catmp = NULL; int i; if ((options & (NOCERTS | NOKEYS)) == (NOCERTS | NOKEYS)) { BIO_printf(bio_err, "Nothing to do!\n"); goto export_end; } if (options & NOCERTS) chain = 0; #ifdef CRYPTO_MDEBUG CRYPTO_push_info("process -export_cert"); CRYPTO_push_info("reading private key"); #endif if (!(options & NOKEYS)) { key = load_key(bio_err, keyname ? keyname : infile, FORMAT_PEM, 1, passin, e, "private key"); if (!key) goto export_end; } #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("reading certs from input"); #endif /* Load in all certs in input file */ if (!(options & NOCERTS)) { certs = load_certs(bio_err, infile, FORMAT_PEM, NULL, e, "certificates"); if (!certs) goto export_end; if (key) { /* Look for matching private key */ for (i = 0; i < sk_X509_num(certs); i++) { x = sk_X509_value(certs, i); if (X509_check_private_key(x, key)) { ucert = x; /* Zero keyid and alias */ X509_keyid_set1(ucert, NULL, 0); X509_alias_set1(ucert, NULL, 0); /* Remove from list */ (void) sk_X509_delete(certs, i); break; } } if (!ucert) { BIO_printf(bio_err, "No certificate matches private key\n"); goto export_end; } } } #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("reading certs from input 2"); #endif /* Add any more certificates asked for */ if (certfile) { STACK_OF(X509) * morecerts = NULL; if (!(morecerts = load_certs(bio_err, certfile, FORMAT_PEM, NULL, e, "certificates from certfile"))) goto export_end; while (sk_X509_num(morecerts) > 0) sk_X509_push(certs, sk_X509_shift(morecerts)); sk_X509_free(morecerts); } #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("reading certs from certfile"); #endif #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("building chain"); #endif /* If chaining get chain from user cert */ if (chain) { int vret; STACK_OF(X509) * chain2; X509_STORE *store = X509_STORE_new(); if (!store) { BIO_printf(bio_err, "Memory allocation error\n"); goto export_end; } if (!X509_STORE_load_locations(store, CAfile, CApath)) X509_STORE_set_default_paths(store); vret = get_cert_chain(ucert, store, &chain2); X509_STORE_free(store); if (!vret) { /* Exclude verified certificate */ for (i = 1; i < sk_X509_num(chain2); i++) sk_X509_push(certs, sk_X509_value(chain2, i)); /* Free first certificate */ X509_free(sk_X509_value(chain2, 0)); sk_X509_free(chain2); } else { if (vret >= 0) BIO_printf(bio_err, "Error %s getting chain.\n", X509_verify_cert_error_string(vret)); else ERR_print_errors(bio_err); goto export_end; } } /* Add any CA names */ for (i = 0; i < sk_OPENSSL_STRING_num(canames); i++) { catmp = (unsigned char *) sk_OPENSSL_STRING_value(canames, i); X509_alias_set1(sk_X509_value(certs, i), catmp, -1); } if (csp_name && key) EVP_PKEY_add1_attr_by_NID(key, NID_ms_csp_name, MBSTRING_ASC, (unsigned char *) csp_name, -1); if (add_lmk && key) EVP_PKEY_add1_attr_by_NID(key, NID_LocalKeySet, 0, NULL, -1); #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("reading password"); #endif if (!noprompt && EVP_read_pw_string(pass, sizeof pass, "Enter Export Password:"******"Can't read Password\n"); goto export_end; } if (!twopass) strlcpy(macpass, pass, sizeof macpass); #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("creating PKCS#12 structure"); #endif p12 = PKCS12_create(cpass, name, key, ucert, certs, key_pbe, cert_pbe, iter, -1, keytype); if (!p12) { ERR_print_errors(bio_err); goto export_end; } if (macalg) { macmd = EVP_get_digestbyname(macalg); if (!macmd) { BIO_printf(bio_err, "Unknown digest algorithm %s\n", macalg); } } if (maciter != -1) PKCS12_set_mac(p12, mpass, -1, NULL, 0, maciter, macmd); #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("writing pkcs12"); #endif i2d_PKCS12_bio(out, p12); ret = 0; export_end: #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_pop_info(); CRYPTO_push_info("process -export_cert: freeing"); #endif if (key) EVP_PKEY_free(key); if (certs) sk_X509_pop_free(certs, X509_free); if (ucert) X509_free(ucert); #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); #endif goto end; } if (!(p12 = d2i_PKCS12_bio(in, NULL))) { ERR_print_errors(bio_err); goto end; } #ifdef CRYPTO_MDEBUG CRYPTO_push_info("read import password"); #endif if (!noprompt && EVP_read_pw_string(pass, sizeof pass, "Enter Import Password:"******"Can't read Password\n"); goto end; } #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); #endif if (!twopass) strlcpy(macpass, pass, sizeof macpass); if ((options & INFO) && p12->mac) BIO_printf(bio_err, "MAC Iteration %ld\n", p12->mac->iter ? ASN1_INTEGER_get(p12->mac->iter) : 1); if (macver) { #ifdef CRYPTO_MDEBUG CRYPTO_push_info("verify MAC"); #endif /* If we enter empty password try no password first */ if (!mpass[0] && PKCS12_verify_mac(p12, NULL, 0)) { /* If mac and crypto pass the same set it to NULL too */ if (!twopass) cpass = NULL; } else if (!PKCS12_verify_mac(p12, mpass, -1)) { BIO_printf(bio_err, "Mac verify error: invalid password?\n"); ERR_print_errors(bio_err); goto end; } BIO_printf(bio_err, "MAC verified OK\n"); #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); #endif } #ifdef CRYPTO_MDEBUG CRYPTO_push_info("output keys and certificates"); #endif if (!dump_certs_keys_p12(out, p12, cpass, -1, options, passout)) { BIO_printf(bio_err, "Error outputting keys and certificates\n"); ERR_print_errors(bio_err); goto end; } #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); #endif ret = 0; end: if (p12) PKCS12_free(p12); #ifdef CRYPTO_MDEBUG CRYPTO_remove_all_info(); #endif BIO_free(in); BIO_free_all(out); if (canames) sk_OPENSSL_STRING_free(canames); if (passin) free(passin); if (passout) free(passout); return (ret); }
/* Set certification stuff. */ static int my_ssl_set_certs(SSL *ssl) { int have_cert= 0; MYSQL *mysql; DBUG_ENTER("my_ssl_set_certs"); /* Make sure that ssl was allocated and ssl_system was initialized */ DBUG_ASSERT(ssl != NULL); DBUG_ASSERT(my_ssl_initialized == TRUE); /* get connection for current ssl */ mysql= (MYSQL *)SSL_get_app_data(ssl); /* add cipher */ if ((mysql->options.ssl_cipher && mysql->options.ssl_cipher[0] != 0) && SSL_set_cipher_list(ssl, mysql->options.ssl_cipher) == 0) goto error; /* set cert */ if (mysql->options.ssl_cert && mysql->options.ssl_cert[0] != 0) { if (SSL_CTX_use_certificate_chain_file(SSL_context, mysql->options.ssl_cert) <= 0) goto error; have_cert= 1; } /* set key */ if (mysql->options.ssl_key && mysql->options.ssl_key[0]) { if (SSL_CTX_use_PrivateKey_file(SSL_context, mysql->options.ssl_key, SSL_FILETYPE_PEM) <= 0) goto error; /* verify key */ if (have_cert && SSL_CTX_check_private_key(SSL_context) != 1) goto error; } /* ca_file and ca_path */ if (SSL_CTX_load_verify_locations(SSL_context, mysql->options.ssl_ca, mysql->options.ssl_capath) == 0) { if (mysql->options.ssl_ca || mysql->options.ssl_capath) goto error; if (SSL_CTX_set_default_verify_paths(SSL_context) == 0) goto error; } if (mysql->options.extension && (mysql->options.extension->ssl_crl || mysql->options.extension->ssl_crlpath)) { X509_STORE *certstore; if ((certstore= SSL_CTX_get_cert_store(SSL_context))) { if (X509_STORE_load_locations(certstore, mysql->options.ssl_ca, mysql->options.ssl_capath) == 0 || X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL) == 0) goto error; } } DBUG_RETURN(0); error: my_SSL_error(mysql); DBUG_RETURN(1); }
inline void store::load_locations(const char* file, const char* dir) { throw_error_if_not(X509_STORE_load_locations(raw(), const_cast<char*>(file), const_cast<char*>(dir)) != 0); }
int be_tls_init(bool isServerStart) { STACK_OF(X509_NAME) *root_cert_list = NULL; SSL_CTX *context; /* This stuff need be done only once. */ if (!SSL_initialized) { #ifdef HAVE_OPENSSL_INIT_SSL OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, NULL); #else OPENSSL_config(NULL); SSL_library_init(); SSL_load_error_strings(); #endif SSL_initialized = true; } /* * We use SSLv23_method() because it can negotiate use of the highest * mutually supported protocol version, while alternatives like * TLSv1_2_method() permit only one specific version. Note that we don't * actually allow SSL v2 or v3, only TLS protocols (see below). */ context = SSL_CTX_new(SSLv23_method()); if (!context) { ereport(isServerStart ? FATAL : LOG, (errmsg("could not create SSL context: %s", SSLerrmessage(ERR_get_error())))); goto error; } /* * Disable OpenSSL's moving-write-buffer sanity check, because it causes * unnecessary failures in nonblocking send cases. */ SSL_CTX_set_mode(context, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); /* * Set password callback */ if (isServerStart) { if (ssl_passphrase_command[0]) SSL_CTX_set_default_passwd_cb(context, ssl_external_passwd_cb); } else { if (ssl_passphrase_command[0] && ssl_passphrase_command_supports_reload) SSL_CTX_set_default_passwd_cb(context, ssl_external_passwd_cb); else /* * If reloading and no external command is configured, override * OpenSSL's default handling of passphrase-protected files, * because we don't want to prompt for a passphrase in an * already-running server. */ SSL_CTX_set_default_passwd_cb(context, dummy_ssl_passwd_cb); } /* used by the callback */ ssl_is_server_start = isServerStart; /* * Load and verify server's certificate and private key */ if (SSL_CTX_use_certificate_chain_file(context, ssl_cert_file) != 1) { ereport(isServerStart ? FATAL : LOG, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("could not load server certificate file \"%s\": %s", ssl_cert_file, SSLerrmessage(ERR_get_error())))); goto error; } if (!check_ssl_key_file_permissions(ssl_key_file, isServerStart)) goto error; /* * OK, try to load the private key file. */ dummy_ssl_passwd_cb_called = false; if (SSL_CTX_use_PrivateKey_file(context, ssl_key_file, SSL_FILETYPE_PEM) != 1) { if (dummy_ssl_passwd_cb_called) ereport(isServerStart ? FATAL : LOG, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("private key file \"%s\" cannot be reloaded because it requires a passphrase", ssl_key_file))); else ereport(isServerStart ? FATAL : LOG, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("could not load private key file \"%s\": %s", ssl_key_file, SSLerrmessage(ERR_get_error())))); goto error; } if (SSL_CTX_check_private_key(context) != 1) { ereport(isServerStart ? FATAL : LOG, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("check of private key failed: %s", SSLerrmessage(ERR_get_error())))); goto error; } if (ssl_min_protocol_version) SSL_CTX_set_min_proto_version(context, ssl_protocol_version_to_openssl(ssl_min_protocol_version, "ssl_min_protocol_version")); if (ssl_max_protocol_version) SSL_CTX_set_max_proto_version(context, ssl_protocol_version_to_openssl(ssl_max_protocol_version, "ssl_max_protocol_version")); /* disallow SSL session tickets */ #ifdef SSL_OP_NO_TICKET /* added in OpenSSL 0.9.8f */ SSL_CTX_set_options(context, SSL_OP_NO_TICKET); #endif /* disallow SSL session caching, too */ SSL_CTX_set_session_cache_mode(context, SSL_SESS_CACHE_OFF); /* set up ephemeral DH and ECDH keys */ if (!initialize_dh(context, isServerStart)) goto error; if (!initialize_ecdh(context, isServerStart)) goto error; /* set up the allowed cipher list */ if (SSL_CTX_set_cipher_list(context, SSLCipherSuites) != 1) { ereport(isServerStart ? FATAL : LOG, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("could not set the cipher list (no valid ciphers available)"))); goto error; } /* Let server choose order */ if (SSLPreferServerCiphers) SSL_CTX_set_options(context, SSL_OP_CIPHER_SERVER_PREFERENCE); /* * Load CA store, so we can verify client certificates if needed. */ if (ssl_ca_file[0]) { if (SSL_CTX_load_verify_locations(context, ssl_ca_file, NULL) != 1 || (root_cert_list = SSL_load_client_CA_file(ssl_ca_file)) == NULL) { ereport(isServerStart ? FATAL : LOG, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("could not load root certificate file \"%s\": %s", ssl_ca_file, SSLerrmessage(ERR_get_error())))); goto error; } } /*---------- * Load the Certificate Revocation List (CRL). * http://searchsecurity.techtarget.com/sDefinition/0,,sid14_gci803160,00.html *---------- */ if (ssl_crl_file[0]) { X509_STORE *cvstore = SSL_CTX_get_cert_store(context); if (cvstore) { /* Set the flags to check against the complete CRL chain */ if (X509_STORE_load_locations(cvstore, ssl_crl_file, NULL) == 1) { /* OpenSSL 0.96 does not support X509_V_FLAG_CRL_CHECK */ #ifdef X509_V_FLAG_CRL_CHECK X509_STORE_set_flags(cvstore, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); #else ereport(LOG, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("SSL certificate revocation list file \"%s\" ignored", ssl_crl_file), errdetail("SSL library does not support certificate revocation lists."))); #endif } else { ereport(isServerStart ? FATAL : LOG, (errcode(ERRCODE_CONFIG_FILE_ERROR), errmsg("could not load SSL certificate revocation list file \"%s\": %s", ssl_crl_file, SSLerrmessage(ERR_get_error())))); goto error; } } } if (ssl_ca_file[0]) { /* * Always ask for SSL client cert, but don't fail if it's not * presented. We might fail such connections later, depending on what * we find in pg_hba.conf. */ SSL_CTX_set_verify(context, (SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE), verify_cb); /* * Tell OpenSSL to send the list of root certs we trust to clients in * CertificateRequests. This lets a client with a keystore select the * appropriate client certificate to send to us. */ SSL_CTX_set_client_CA_list(context, root_cert_list); } /* * Success! Replace any existing SSL_context. */ if (SSL_context) SSL_CTX_free(SSL_context); SSL_context = context; /* * Set flag to remember whether CA store has been loaded into SSL_context. */ if (ssl_ca_file[0]) ssl_loaded_verify_locations = true; else ssl_loaded_verify_locations = false; return 0; error: if (context) SSL_CTX_free(context); return -1; }
/* Open the SSL module */ PUBLIC int sslOpen() { RandBuf randBuf; X509_STORE *store; uchar resume[16]; char *ciphers; trace(7, "Initializing SSL"); randBuf.now = time(0); randBuf.pid = getpid(); RAND_seed((void*) &randBuf, sizeof(randBuf)); #if ME_UNIX_LIKE trace(6, "OpenSsl: Before calling RAND_load_file"); RAND_load_file("/dev/urandom", 256); trace(6, "OpenSsl: After calling RAND_load_file"); #endif CRYPTO_malloc_init(); #if !ME_WIN_LIKE OpenSSL_add_all_algorithms(); #endif SSL_library_init(); SSL_load_error_strings(); SSLeay_add_ssl_algorithms(); if ((sslctx = SSL_CTX_new(SSLv23_server_method())) == 0) { error("Unable to create SSL context"); return -1; } /* Set the server certificate and key files */ if (*ME_GOAHEAD_SSL_KEY && sslSetKeyFile(ME_GOAHEAD_SSL_KEY) < 0) { sslClose(); return -1; } if (*ME_GOAHEAD_SSL_CERTIFICATE && sslSetCertFile(ME_GOAHEAD_SSL_CERTIFICATE) < 0) { sslClose(); return -1; } if (ME_GOAHEAD_SSL_VERIFY_PEER) { SSL_CTX_set_verify(sslctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, verifyClientCertificate); SSL_CTX_set_verify_depth(sslctx, VERIFY_DEPTH); } else { SSL_CTX_set_verify(sslctx, SSL_VERIFY_NONE, verifyClientCertificate); } /* Set the client certificate verification locations */ if (ME_GOAHEAD_SSL_AUTHORITY && *ME_GOAHEAD_SSL_AUTHORITY) { if ((!SSL_CTX_load_verify_locations(sslctx, ME_GOAHEAD_SSL_AUTHORITY, NULL)) || (!SSL_CTX_set_default_verify_paths(sslctx))) { error("Unable to read cert verification locations"); sslClose(); return -1; } /* Define the list of CA certificates to send to the client before they send their client certificate for validation */ SSL_CTX_set_client_CA_list(sslctx, SSL_load_client_CA_file(ME_GOAHEAD_SSL_AUTHORITY)); } if (ME_GOAHEAD_SSL_REVOKE && *ME_GOAHEAD_SSL_REVOKE) { store = SSL_CTX_get_cert_store(sslctx); if (!X509_STORE_load_locations(store, ME_GOAHEAD_SSL_REVOKE, 0)) { error("Cannot load certificate revoke list: %s", ME_GOAHEAD_SSL_REVOKE); sslClose(); return -1; } } /* Configure DH parameters */ dhKey = getDhKey(); SSL_CTX_set_tmp_dh_callback(sslctx, dhcallback); /* Configure cipher suite */ if (ME_GOAHEAD_SSL_CIPHERS && *ME_GOAHEAD_SSL_CIPHERS) { ciphers = ME_GOAHEAD_SSL_CIPHERS; } else { ciphers = OPENSSL_DEFAULT_CIPHERS; } ciphers = mapCipherNames(ciphers); trace(5, "Using OpenSSL ciphers: %s", ciphers); if (SSL_CTX_set_cipher_list(sslctx, ciphers) != 1) { error("Unable to set cipher list \"%s\"", ciphers); sslClose(); wfree(ciphers); return -1; } wfree(ciphers); /* Define default OpenSSL options */ SSL_CTX_set_options(sslctx, SSL_OP_ALL); /* Ensure we generate a new private key for each connection */ SSL_CTX_set_options(sslctx, SSL_OP_SINGLE_DH_USE); /* Define a session reuse context */ RAND_bytes(resume, sizeof(resume)); SSL_CTX_set_session_id_context(sslctx, resume, sizeof(resume)); /* Elliptic Curve initialization */ #if SSL_OP_SINGLE_ECDH_USE #ifdef SSL_CTX_set_ecdh_auto SSL_CTX_set_ecdh_auto(sslctx, 1); #else { EC_KEY *ecdh; cchar *name; int nid; name = ME_GOAHEAD_SSL_CURVE; if ((nid = OBJ_sn2nid(name)) == 0) { error("Unknown curve name \"%s\"", name); sslClose(); return -1; } if ((ecdh = EC_KEY_new_by_curve_name(nid)) == 0) { error("Unable to create curve \"%s\"", name); sslClose(); return -1; } SSL_CTX_set_options(sslctx, SSL_OP_SINGLE_ECDH_USE); SSL_CTX_set_tmp_ecdh(sslctx, ecdh); EC_KEY_free(ecdh); } #endif #endif SSL_CTX_set_mode(sslctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); #ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING SSL_CTX_set_options(sslctx, SSL_OP_MSIE_SSLV2_RSA_PADDING); #endif #ifdef SSL_MODE_RELEASE_BUFFERS SSL_CTX_set_mode(sslctx, SSL_MODE_RELEASE_BUFFERS); #endif #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE SSL_CTX_set_mode(sslctx, SSL_OP_CIPHER_SERVER_PREFERENCE); #endif /* Select the required protocols Disable both SSLv2 and SSLv3 by default - they are insecure */ SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv2); SSL_CTX_set_options(sslctx, SSL_OP_NO_SSLv3); #if defined(SSL_OP_NO_TLSv1) && ME_GOAHEAD_SSL_NO_V1 SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1); #endif #if defined(SSL_OP_NO_TLSv1_1) && ME_GOAHEAD_SSL_NO_V1_1 SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1_1); #endif #if defined(SSL_OP_NO_TLSv1_2) && ME_GOAHEAD_SSL_NO_V1_2 SSL_CTX_set_options(sslctx, SSL_OP_NO_TLSv1_2); #endif #if defined(SSL_OP_NO_TICKET) /* Ticket based session reuse is enabled by default */ #if defined(ME_GOAHEAD_SSL_TICKET) if (ME_GOAHEAD_SSL_TICKET) { SSL_CTX_clear_options(sslctx, SSL_OP_NO_TICKET); } else { SSL_CTX_set_options(sslctx, SSL_OP_NO_TICKET); } #else SSL_CTX_clear_options(sslctx, SSL_OP_NO_TICKET); #endif #endif #if defined(SSL_OP_NO_COMPRESSION) /* CRIME attack targets compression */ SSL_CTX_clear_options(sslctx, SSL_OP_NO_COMPRESSION); #endif #if defined(SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) /* Disables a countermeasure against a SSL 3.0/TLS 1.0 protocol vulnerability affecting CBC ciphers. Defaults to true. */ #if defined(ME_GOAHEAD_SSL_EMPTY_FRAGMENTS) if (ME_GOAHEAD_SSL_EMPTY_FRAGMENTS) { /* SSL_OP_ALL disables empty fragments. Only needed for ancient browsers like IE-6 on SSL-3.0/TLS-1.0 */ SSL_CTX_clear_options(sslctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); } else { SSL_CTX_set_options(sslctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); } #else SSL_CTX_set_options(sslctx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); #endif #endif #if defined(ME_GOAHEAD_SSL_CACHE) /* Set the number of sessions supported. Default in OpenSSL is 20K. */ SSL_CTX_sess_set_cache_size(sslctx, ME_GOAHEAD_SSL_CACHE); #else SSL_CTX_sess_set_cache_size(sslctx, 256); #endif return 0; }
int SSL_CTX_load_verify_locations(SSL_CTX *ctx, const char *ca_file, const char *ca_dir) { check_ssl_ctx_x509_method(ctx); return X509_STORE_load_locations(ctx->cert_store, ca_file, ca_dir); }
static int mod_init(void) { CURLcode iRet; str sstr; FILE *hpemfile; char serr[160]; X509 *pmycert=NULL; /* certificate of the authentication service */ time_t tnow, ttmp; /* * * Parameter check * */ if (glb_sprivkeypath[0]==0) { LOG(L_WARN, "AUTH_IDENTITY:mod_init: Private key path is missing! Authorization service is disabled\n"); glb_authservice_disabled=1; } if (!glb_authservice_disabled && glb_sservercerturl[0]==0) { LOG(L_WARN, "AUTH_IDENTITY:mod_init: URL of certificate of the server is missing! Authorization service is disabled\n"); glb_authservice_disabled=1; } if (!glb_authservice_disabled && glb_sservercertpath[0]==0) { LOG(L_WARN, "AUTH_IDENTITY:mod_init: Path of certificate of the server is missing! Authorization service is disabled\n"); glb_authservice_disabled=1; } /* * * Init the curl session and download buffer * */ curl_global_init(CURL_GLOBAL_ALL); if ((glb_hcurl=curl_easy_init())==NULL) { LOG(L_ERR, "AUTH_IDENTITY:mod_init: Unable to init cURL library!\n"); return -1; } /* send all data to this function */ if ((iRet=curl_easy_setopt(glb_hcurl, CURLOPT_WRITEFUNCTION, curlmem_cb))!=0) { LOG(L_ERR, "AUTH_IDENTITY:mod_init: Unable to set cURL write function option: %s\n", curl_easy_strerror(iRet)); return -2; } /* we pass our 'glb_tcert' struct to the callback function */ if ((iRet=curl_easy_setopt(glb_hcurl, CURLOPT_WRITEDATA, (void *)&glb_tcert.scertpem))!=0) { LOG(L_ERR, "AUTH_IDENTITY:mod_init: Unable to set cURL writedata option: %s\n", curl_easy_strerror(iRet)); return -4; } if (!(glb_tcert.scertpem.s=pkg_malloc(CERTIFICATE_LENGTH))) { LOG(L_ERR, "AUTH_IDENTITY:mod_init: Not enough memory error\n"); return -3; } /* some servers don't like requests that are made without a user-agent field, so we provide one */ if ((iRet=curl_easy_setopt(glb_hcurl, CURLOPT_USERAGENT, "ser-agent/1.0"))!=0) { LOG(L_WARN, "AUTH_IDENTITY:mod_init: Unable to set cURL useragent option: %s\n", curl_easy_strerror(iRet)); } if ((iRet=curl_easy_setopt(glb_hcurl, CURLOPT_SSL_VERIFYPEER, 1))!=0) { LOG(L_WARN, "AUTH_IDENTITY:mod_init: Unable to set cURL verifypeer option: %s\n", curl_easy_strerror(iRet)); } if ((iRet=curl_easy_setopt(glb_hcurl, CURLOPT_SSL_VERIFYHOST, 2))!=0) { LOG(L_WARN, "AUTH_IDENTITY:mod_init: Unable to set cURL verifyhost option: %s\n", curl_easy_strerror(iRet)); } /* cainfo_path module parameter's been set */ if (glb_scainfo[0]) { if ((iRet=curl_easy_setopt(glb_hcurl, CURLOPT_CAINFO, glb_scainfo))!=0) { LOG(L_WARN, "AUTH_IDENTITY:mod_init: Unable to set cURL cainfo option: %s\n", curl_easy_strerror(iRet)); } } /* * * OpenSSL certificate verification initialization * */ OpenSSL_add_all_algorithms(); if (!(glb_cacerts=X509_STORE_new())) { LOG(L_ERR, "AUTH_IDENTITY:mod_init: unable to initialize X509 store\n"); return -16; } if (X509_STORE_set_default_paths(glb_cacerts)!=1) { LOG(L_ERR, "AUTH_IDENTITY:mod_init: unable to set X509 store default path\n"); return -17; } if (glb_scainfo[0] && X509_STORE_load_locations(glb_cacerts, glb_scainfo, NULL) != 1) LOG(L_WARN, "AUTH_IDENTITY:mod_init: unable to load X509 store location\n"); /* * * Init the Date, Digest-String, Identity and Identity-Info * */ if (initdynstr(&glb_sdgst, DGST_STR_INIT_SIZE)) return -5; /* * Init certificate table */ if (init_table(&glb_tcert_table, CERTIFICATE_TABLE_ENTRIES, glb_icertlimit, cert_item_cmp, cert_item_init, cert_item_least, cert_item_free, NULL)) return -5; /* * Init call-id table */ if (init_table(&glb_tcallid_table, CALLID_TABLE_ITEM_LIMIT, glb_icallidlimit, cid_item_cmp, cid_item_init, cid_item_least, cid_item_free, cid_item_gc)) return -5; glb_ttimeparams.ibnow=0; /* we've to check the whole table in glb_imsgtime, so the number of buckets we've to check in every timer call is CALLID_TABLE_ENTRIES/glb_imsgtime/CALLID_GARBAGE_COLLECTOR_INTERVAL */ glb_ttimeparams.ibcir=glb_iauthval/CALLID_GARBAGE_COLLECTOR_INTERVAL; if (!glb_ttimeparams.ibcir) glb_ttimeparams.ibcir=1; glb_ttimeparams.ibnum=CALLID_TABLE_ENTRIES/glb_ttimeparams.ibcir; if (register_timer(callid_gc, (void*)&glb_ttimeparams /* param*/, CALLID_GARBAGE_COLLECTOR_INTERVAL /* period */) < 0 ) { LOG(L_ERR, "AUTH_IDENTITY:mod_init: Can not register timer\n"); return -5; } /* * If there were not enough parameter set then we could not initialize * the authorizer part */ if (glb_authservice_disabled) return 0; if (initdynstr(&glb_sidentity, DGST_STR_INIT_SIZE)) return -6; if (initdynstr(&glb_sdate, AUTH_TIME_LENGTH)) return -7; if (initdynstr(&glb_sidentityinfo, AUTH_URL_LENGTH)) return -8; /* we initialize indentity info header */ sstr.s=IDENTITY_INFO_FIRST_PART; sstr.len=strlen(IDENTITY_INFO_FIRST_PART); if (cpy2dynstr(&glb_sidentityinfo, &sstr)) return -9; sstr.s=glb_sservercerturl; sstr.len=strlen(glb_sservercerturl); if (app2dynstr(&glb_sidentityinfo, &sstr)) return -10; sstr.s=IDENTITY_INFO_LAST_PART; /* we copy the trailing \0 because append_hf expects strings */ sstr.len=strlen(IDENTITY_INFO_LAST_PART) + 1; if (app2dynstr(&glb_sidentityinfo, &sstr)) return -11; /* * Get my certificate */ if (!(hpemfile=fopen(glb_sservercertpath, "r"))) { LOG(L_ERR, "AUTH_IDENTITY:mod_init: unable to open certificate '%s'\n", strerror(errno)); return -12; } if (!(pmycert=PEM_read_X509(hpemfile, NULL, NULL, NULL))) { ERR_error_string_n(ERR_get_error(), serr, sizeof serr); LOG(L_ERR, "AUTH_IDENTITY:mod_init: '%s'\n", serr); fclose(hpemfile); return -13; } if (x509_get_notafter(&glb_imycertnotafter, pmycert)) { LOG(L_ERR, "AUTH_IDENTITY:mod_init: Error getting certificate expiration date\n"); return -13; } if (x509_get_notbefore(&ttmp, pmycert)) { LOG(L_ERR, "AUTH_IDENTITY:mod_init: Error getting certificate validity date\n"); return -13; } if ((tnow=time(0)) < 0) { LOG(L_ERR, "AUTH_IDENTITY:mod_init: time error %s\n", strerror(errno)); return -13; } if (tnow < ttmp || tnow > glb_imycertnotafter) { LOG(L_ERR, "AUTH_IDENTITY:mod_init: Date of certificate is invalid (%s)\n", glb_sservercertpath); return -14; } if (fclose(hpemfile)) LOG(L_ERR, "AUTH_IDENTITY:mod_init: unable to close file\n"); X509_free(pmycert); /* * * Init RSA-SHA1 encoder * */ hpemfile=fopen(glb_sprivkeypath, "r"); if (!hpemfile) { LOG(L_ERR, "AUTH_IDENTITY:mod_init: unable to open private key '%s'\n", strerror(errno)); return -12; } glb_hmyprivkey=PEM_read_RSAPrivateKey(hpemfile, NULL, NULL, NULL); if (!glb_hmyprivkey) { ERR_error_string_n(ERR_get_error(), serr, sizeof serr); LOG(L_ERR, "AUTH_IDENTITY:mod_init: '%s'\n", serr); fclose(hpemfile); return -13; } if (fclose(hpemfile)) LOG(L_ERR, "AUTH_IDENTITY:mod_init: unable to close file\n"); /* we encrypt the digest string hash to this buffer */ if (initdynstr(&glb_encedmsg, RSA_size(glb_hmyprivkey))) return -14; /* we base64 encode the encrypted digest string hash to this buffer */ if (initdynstr(&glb_b64encedmsg, (RSA_size(glb_hmyprivkey)/3+1)*4)) return -15; return 0; }
int MAIN(int argc, char **argv) { ENGINE *e = NULL; char *infile=NULL, *outfile=NULL, *keyname = NULL; char *certfile=NULL; BIO *in=NULL, *out = NULL; char **args; char *name = NULL; char *csp_name = NULL; PKCS12 *p12 = NULL; char pass[50], macpass[50]; int export_cert = 0; int options = 0; int chain = 0; int badarg = 0; int iter = PKCS12_DEFAULT_ITER; int maciter = PKCS12_DEFAULT_ITER; int twopass = 0; int keytype = 0; int cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC; int key_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; int ret = 1; int macver = 1; int noprompt = 0; STACK *canames = NULL; char *cpass = NULL, *mpass = NULL; char *passargin = NULL, *passargout = NULL, *passarg = NULL; char *passin = NULL, *passout = NULL; char *inrand = NULL; char *CApath = NULL, *CAfile = NULL; char *engine=NULL; apps_startup(); enc = EVP_des_ede3_cbc(); if (bio_err == NULL ) bio_err = BIO_new_fp (stderr, BIO_NOCLOSE); if (!load_config(bio_err, NULL)) goto end; args = argv + 1; while (*args) { if (*args[0] == '-') { if (!strcmp (*args, "-nokeys")) options |= NOKEYS; else if (!strcmp (*args, "-keyex")) keytype = KEY_EX; else if (!strcmp (*args, "-keysig")) keytype = KEY_SIG; else if (!strcmp (*args, "-nocerts")) options |= NOCERTS; else if (!strcmp (*args, "-clcerts")) options |= CLCERTS; else if (!strcmp (*args, "-cacerts")) options |= CACERTS; else if (!strcmp (*args, "-noout")) options |= (NOKEYS|NOCERTS); else if (!strcmp (*args, "-info")) options |= INFO; else if (!strcmp (*args, "-chain")) chain = 1; else if (!strcmp (*args, "-twopass")) twopass = 1; else if (!strcmp (*args, "-nomacver")) macver = 0; else if (!strcmp (*args, "-descert")) cert_pbe = NID_pbe_WithSHA1And3_Key_TripleDES_CBC; else if (!strcmp (*args, "-export")) export_cert = 1; else if (!strcmp (*args, "-des")) enc=EVP_des_cbc(); #ifndef OPENSSL_NO_IDEA else if (!strcmp (*args, "-idea")) enc=EVP_idea_cbc(); #endif else if (!strcmp (*args, "-des3")) enc = EVP_des_ede3_cbc(); #ifndef OPENSSL_NO_AES else if (!strcmp(*args,"-aes128")) enc=EVP_aes_128_cbc(); else if (!strcmp(*args,"-aes192")) enc=EVP_aes_192_cbc(); else if (!strcmp(*args,"-aes256")) enc=EVP_aes_256_cbc(); #endif else if (!strcmp (*args, "-noiter")) iter = 1; else if (!strcmp (*args, "-maciter")) maciter = PKCS12_DEFAULT_ITER; else if (!strcmp (*args, "-nomaciter")) maciter = 1; else if (!strcmp (*args, "-nodes")) enc=NULL; else if (!strcmp (*args, "-certpbe")) { if (args[1]) { args++; cert_pbe=OBJ_txt2nid(*args); if(cert_pbe == NID_undef) { BIO_printf(bio_err, "Unknown PBE algorithm %s\n", *args); badarg = 1; } } else badarg = 1; } else if (!strcmp (*args, "-keypbe")) { if (args[1]) { args++; key_pbe=OBJ_txt2nid(*args); if(key_pbe == NID_undef) { BIO_printf(bio_err, "Unknown PBE algorithm %s\n", *args); badarg = 1; } } else badarg = 1; } else if (!strcmp (*args, "-rand")) { if (args[1]) { args++; inrand = *args; } else badarg = 1; } else if (!strcmp (*args, "-inkey")) { if (args[1]) { args++; keyname = *args; } else badarg = 1; } else if (!strcmp (*args, "-certfile")) { if (args[1]) { args++; certfile = *args; } else badarg = 1; } else if (!strcmp (*args, "-name")) { if (args[1]) { args++; name = *args; } else badarg = 1; } else if (!strcmp (*args, "-CSP")) { if (args[1]) { args++; csp_name = *args; } else badarg = 1; } else if (!strcmp (*args, "-caname")) { if (args[1]) { args++; if (!canames) canames = sk_new_null(); sk_push(canames, *args); } else badarg = 1; } else if (!strcmp (*args, "-in")) { if (args[1]) { args++; infile = *args; } else badarg = 1; } else if (!strcmp (*args, "-out")) { if (args[1]) { args++; outfile = *args; } else badarg = 1; } else if (!strcmp(*args,"-passin")) { if (args[1]) { args++; passargin = *args; } else badarg = 1; } else if (!strcmp(*args,"-passout")) { if (args[1]) { args++; passargout = *args; } else badarg = 1; } else if (!strcmp (*args, "-password")) { if (args[1]) { args++; passarg = *args; noprompt = 1; } else badarg = 1; } else if (!strcmp(*args,"-CApath")) { if (args[1]) { args++; CApath = *args; } else badarg = 1; } else if (!strcmp(*args,"-CAfile")) { if (args[1]) { args++; CAfile = *args; } else badarg = 1; } else if (!strcmp(*args,"-engine")) { if (args[1]) { args++; engine = *args; } else badarg = 1; } else badarg = 1; } else badarg = 1; args++; } if (badarg) { BIO_printf (bio_err, "Usage: pkcs12 [options]\n"); BIO_printf (bio_err, "where options are\n"); BIO_printf (bio_err, "-export output PKCS12 file\n"); BIO_printf (bio_err, "-chain add certificate chain\n"); BIO_printf (bio_err, "-inkey file private key if not infile\n"); BIO_printf (bio_err, "-certfile f add all certs in f\n"); BIO_printf (bio_err, "-CApath arg - PEM format directory of CA's\n"); BIO_printf (bio_err, "-CAfile arg - PEM format file of CA's\n"); BIO_printf (bio_err, "-name \"name\" use name as friendly name\n"); BIO_printf (bio_err, "-caname \"nm\" use nm as CA friendly name (can be used more than once).\n"); BIO_printf (bio_err, "-in infile input filename\n"); BIO_printf (bio_err, "-out outfile output filename\n"); BIO_printf (bio_err, "-noout don't output anything, just verify.\n"); BIO_printf (bio_err, "-nomacver don't verify MAC.\n"); BIO_printf (bio_err, "-nocerts don't output certificates.\n"); BIO_printf (bio_err, "-clcerts only output client certificates.\n"); BIO_printf (bio_err, "-cacerts only output CA certificates.\n"); BIO_printf (bio_err, "-nokeys don't output private keys.\n"); BIO_printf (bio_err, "-info give info about PKCS#12 structure.\n"); BIO_printf (bio_err, "-des encrypt private keys with DES\n"); BIO_printf (bio_err, "-des3 encrypt private keys with triple DES (default)\n"); #ifndef OPENSSL_NO_IDEA BIO_printf (bio_err, "-idea encrypt private keys with idea\n"); #endif #ifndef OPENSSL_NO_AES BIO_printf (bio_err, "-aes128, -aes192, -aes256\n"); BIO_printf (bio_err, " encrypt PEM output with cbc aes\n"); #endif BIO_printf (bio_err, "-nodes don't encrypt private keys\n"); BIO_printf (bio_err, "-noiter don't use encryption iteration\n"); BIO_printf (bio_err, "-maciter use MAC iteration\n"); BIO_printf (bio_err, "-twopass separate MAC, encryption passwords\n"); BIO_printf (bio_err, "-descert encrypt PKCS#12 certificates with triple DES (default RC2-40)\n"); BIO_printf (bio_err, "-certpbe alg specify certificate PBE algorithm (default RC2-40)\n"); BIO_printf (bio_err, "-keypbe alg specify private key PBE algorithm (default 3DES)\n"); BIO_printf (bio_err, "-keyex set MS key exchange type\n"); BIO_printf (bio_err, "-keysig set MS key signature type\n"); BIO_printf (bio_err, "-password p set import/export password source\n"); BIO_printf (bio_err, "-passin p input file pass phrase source\n"); BIO_printf (bio_err, "-passout p output file pass phrase source\n"); BIO_printf (bio_err, "-engine e use engine e, possibly a hardware device.\n"); BIO_printf(bio_err, "-rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR); BIO_printf(bio_err, " load the file (or the files in the directory) into\n"); BIO_printf(bio_err, " the random number generator\n"); goto end; } e = setup_engine(bio_err, engine, 0); if(passarg) { if(export_cert) passargout = passarg; else passargin = passarg; } if(!app_passwd(bio_err, passargin, passargout, &passin, &passout)) { BIO_printf(bio_err, "Error getting passwords\n"); goto end; } if(!cpass) { if(export_cert) cpass = passout; else cpass = passin; } if(cpass) { mpass = cpass; noprompt = 1; } else { cpass = pass; mpass = macpass; } if(export_cert || inrand) { app_RAND_load_file(NULL, bio_err, (inrand != NULL)); if (inrand != NULL) BIO_printf(bio_err,"%ld semi-random bytes loaded\n", app_RAND_load_files(inrand)); } ERR_load_crypto_strings(); #ifdef CRYPTO_MDEBUG CRYPTO_push_info("read files"); #endif if (!infile) in = BIO_new_fp(stdin, BIO_NOCLOSE); else in = BIO_new_file(infile, "rb"); if (!in) { BIO_printf(bio_err, "Error opening input file %s\n", infile ? infile : "<stdin>"); perror (infile); goto end; } #if 0 if (certfile) { if(!(certsin = BIO_new_file(certfile, "r"))) { BIO_printf(bio_err, "Can't open certificate file %s\n", certfile); perror (certfile); goto end; } } if (keyname) { if(!(inkey = BIO_new_file(keyname, "r"))) { BIO_printf(bio_err, "Can't key certificate file %s\n", keyname); perror (keyname); goto end; } } #endif #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("write files"); #endif if (!outfile) { out = BIO_new_fp(stdout, BIO_NOCLOSE); #ifdef OPENSSL_SYS_VMS { BIO *tmpbio = BIO_new(BIO_f_linebuffer()); out = BIO_push(tmpbio, out); } #endif } else out = BIO_new_file(outfile, "wb"); if (!out) { BIO_printf(bio_err, "Error opening output file %s\n", outfile ? outfile : "<stdout>"); perror (outfile); goto end; } if (twopass) { #ifdef CRYPTO_MDEBUG CRYPTO_push_info("read MAC password"); #endif if(EVP_read_pw_string (macpass, sizeof macpass, "Enter MAC Password:"******"Can't read Password\n"); goto end; } #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); #endif } if (export_cert) { EVP_PKEY *key = NULL; STACK_OF(PKCS12_SAFEBAG) *bags = NULL; STACK_OF(PKCS7) *safes = NULL; PKCS12_SAFEBAG *bag = NULL; PKCS8_PRIV_KEY_INFO *p8 = NULL; PKCS7 *authsafe = NULL; X509 *ucert = NULL; STACK_OF(X509) *certs=NULL; char *catmp = NULL; int i; unsigned char keyid[EVP_MAX_MD_SIZE]; unsigned int keyidlen = 0; #ifdef CRYPTO_MDEBUG CRYPTO_push_info("process -export_cert"); CRYPTO_push_info("reading private key"); #endif key = load_key(bio_err, keyname ? keyname : infile, FORMAT_PEM, 1, passin, e, "private key"); if (!key) { goto export_end; } #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("reading certs from input"); #endif /* Load in all certs in input file */ if(!(certs = load_certs(bio_err, infile, FORMAT_PEM, NULL, e, "certificates"))) { goto export_end; } #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("reading certs from input 2"); #endif for(i = 0; i < sk_X509_num(certs); i++) { ucert = sk_X509_value(certs, i); if(X509_check_private_key(ucert, key)) { X509_digest(ucert, EVP_sha1(), keyid, &keyidlen); break; } } if(!keyidlen) { ucert = NULL; BIO_printf(bio_err, "No certificate matches private key\n"); goto export_end; } #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("reading certs from certfile"); #endif bags = sk_PKCS12_SAFEBAG_new_null (); /* Add any more certificates asked for */ if (certfile) { STACK_OF(X509) *morecerts=NULL; if(!(morecerts = load_certs(bio_err, certfile, FORMAT_PEM, NULL, e, "certificates from certfile"))) { goto export_end; } while(sk_X509_num(morecerts) > 0) { sk_X509_push(certs, sk_X509_shift(morecerts)); } sk_X509_free(morecerts); } #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("building chain"); #endif /* If chaining get chain from user cert */ if (chain) { int vret; STACK_OF(X509) *chain2; X509_STORE *store = X509_STORE_new(); if (!store) { BIO_printf (bio_err, "Memory allocation error\n"); goto export_end; } if (!X509_STORE_load_locations(store, CAfile, CApath)) X509_STORE_set_default_paths (store); vret = get_cert_chain (ucert, store, &chain2); X509_STORE_free(store); if (!vret) { /* Exclude verified certificate */ for (i = 1; i < sk_X509_num (chain2) ; i++) sk_X509_push(certs, sk_X509_value (chain2, i)); /* Free first certificate */ X509_free(sk_X509_value(chain2, 0)); sk_X509_free(chain2); } else { BIO_printf (bio_err, "Error %s getting chain.\n", X509_verify_cert_error_string(vret)); goto export_end; } } #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("building bags"); #endif /* We now have loads of certificates: include them all */ for(i = 0; i < sk_X509_num(certs); i++) { X509 *cert = NULL; cert = sk_X509_value(certs, i); bag = PKCS12_x5092certbag(cert); /* If it matches private key set id */ if(cert == ucert) { if(name) PKCS12_add_friendlyname(bag, name, -1); PKCS12_add_localkeyid(bag, keyid, keyidlen); } else if((catmp = sk_shift(canames))) PKCS12_add_friendlyname(bag, catmp, -1); sk_PKCS12_SAFEBAG_push(bags, bag); } sk_X509_pop_free(certs, X509_free); certs = NULL; #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("encrypting bags"); #endif if(!noprompt && EVP_read_pw_string(pass, sizeof pass, "Enter Export Password:"******"Can't read Password\n"); goto export_end; } if (!twopass) strcpy(macpass, pass); /* Turn certbags into encrypted authsafe */ authsafe = PKCS12_pack_p7encdata(cert_pbe, cpass, -1, NULL, 0, iter, bags); sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); bags = NULL; if (!authsafe) { ERR_print_errors (bio_err); goto export_end; } safes = sk_PKCS7_new_null (); sk_PKCS7_push (safes, authsafe); #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("building shrouded key bag"); #endif /* Make a shrouded key bag */ p8 = EVP_PKEY2PKCS8 (key); if(keytype) PKCS8_add_keyusage(p8, keytype); bag = PKCS12_MAKE_SHKEYBAG(key_pbe, cpass, -1, NULL, 0, iter, p8); PKCS8_PRIV_KEY_INFO_free(p8); p8 = NULL; if (name) PKCS12_add_friendlyname (bag, name, -1); if(csp_name) PKCS12_add_CSPName_asc(bag, csp_name, -1); PKCS12_add_localkeyid (bag, keyid, keyidlen); bags = sk_PKCS12_SAFEBAG_new_null(); sk_PKCS12_SAFEBAG_push (bags, bag); #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("encrypting shrouded key bag"); #endif /* Turn it into unencrypted safe bag */ authsafe = PKCS12_pack_p7data (bags); sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); bags = NULL; sk_PKCS7_push (safes, authsafe); #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("building pkcs12"); #endif p12 = PKCS12_init(NID_pkcs7_data); PKCS12_pack_authsafes(p12, safes); sk_PKCS7_pop_free(safes, PKCS7_free); safes = NULL; PKCS12_set_mac (p12, mpass, -1, NULL, 0, maciter, NULL); #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_push_info("writing pkcs12"); #endif i2d_PKCS12_bio (out, p12); ret = 0; export_end: #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); CRYPTO_pop_info(); CRYPTO_push_info("process -export_cert: freeing"); #endif if (key) EVP_PKEY_free(key); if (certs) sk_X509_pop_free(certs, X509_free); if (safes) sk_PKCS7_pop_free(safes, PKCS7_free); if (bags) sk_PKCS12_SAFEBAG_pop_free(bags, PKCS12_SAFEBAG_free); #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); #endif goto end; } if (!(p12 = d2i_PKCS12_bio (in, NULL))) { ERR_print_errors(bio_err); goto end; } #ifdef CRYPTO_MDEBUG CRYPTO_push_info("read import password"); #endif if(!noprompt && EVP_read_pw_string(pass, sizeof pass, "Enter Import Password:"******"Can't read Password\n"); goto end; } #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); #endif if (!twopass) strcpy(macpass, pass); if (options & INFO) BIO_printf (bio_err, "MAC Iteration %ld\n", p12->mac->iter ? ASN1_INTEGER_get (p12->mac->iter) : 1); if(macver) { #ifdef CRYPTO_MDEBUG CRYPTO_push_info("verify MAC"); #endif /* If we enter empty password try no password first */ if(!macpass[0] && PKCS12_verify_mac(p12, NULL, 0)) { /* If mac and crypto pass the same set it to NULL too */ if(!twopass) cpass = NULL; } else if (!PKCS12_verify_mac(p12, mpass, -1)) { BIO_printf (bio_err, "Mac verify error: invalid password?\n"); ERR_print_errors (bio_err); goto end; } BIO_printf (bio_err, "MAC verified OK\n"); #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); #endif } #ifdef CRYPTO_MDEBUG CRYPTO_push_info("output keys and certificates"); #endif if (!dump_certs_keys_p12 (out, p12, cpass, -1, options, passout)) { BIO_printf(bio_err, "Error outputting keys and certificates\n"); ERR_print_errors (bio_err); goto end; } #ifdef CRYPTO_MDEBUG CRYPTO_pop_info(); #endif ret = 0; end: if (p12) PKCS12_free(p12); if(export_cert || inrand) app_RAND_write_file(NULL, bio_err); #ifdef CRYPTO_MDEBUG CRYPTO_remove_all_info(); #endif BIO_free(in); BIO_free_all(out); if (canames) sk_free(canames); if(passin) OPENSSL_free(passin); if(passout) OPENSSL_free(passout); apps_shutdown(); OPENSSL_EXIT(ret); }
static SSL_CTX *initialise_ssl_ctx(int server_mode, const char *engine_id, const char *CAfile, const char *cert, const char *key, const char *dcert, const char *dkey, const char *cipher_list, const char *dh_file, const char *dh_special, int tmp_rsa, int ctx_options, int out_state, int out_verify, int verify_mode, unsigned int verify_depth) { SSL_CTX *ctx = NULL, *ret = NULL; const SSL_METHOD *meth; ENGINE *e = NULL; OpenSSL_add_ssl_algorithms(); SSL_load_error_strings(); meth = (server_mode ? SSLv23_server_method() : SSLv23_client_method()); if (meth == NULL) goto err; if (engine_id) { ENGINE_load_builtin_engines(); if ((e = ENGINE_by_id(engine_id)) == NULL) { fprintf(stderr, "Error obtaining '%s' engine, openssl " "errors follow\n", engine_id); goto err; } if (!ENGINE_set_default(e, ENGINE_METHOD_ALL)) { fprintf(stderr, "Error assigning '%s' engine, openssl " "errors follow\n", engine_id); goto err; } ENGINE_free(e); } if ((ctx = SSL_CTX_new(meth)) == NULL) goto err; /* cacert */ if (CAfile) { if (!X509_STORE_load_locations(SSL_CTX_get_cert_store(ctx), CAfile, NULL)) { fprintf(stderr, "Error loading CA cert(s) in '%s'\n", CAfile); goto err; } fprintf(stderr, "Info, operating with CA cert(s) in '%s'\n", CAfile); } else fprintf(stderr, "Info, operating without a CA cert(-list)\n"); if (!SSL_CTX_set_default_verify_paths(ctx)) { fprintf(stderr, "Error setting default verify paths\n"); goto err; } /* cert and key */ if ((cert || key) && !ctx_set_cert(ctx, cert, key)) goto err; /* dcert and dkey */ if ((dcert || dkey) && !ctx_set_cert(ctx, dcert, dkey)) goto err; /* temporary RSA key generation */ if (tmp_rsa) SSL_CTX_set_tmp_rsa_callback(ctx, cb_generate_tmp_rsa); /* cipher_list */ if (cipher_list) { if (!SSL_CTX_set_cipher_list(ctx, cipher_list)) { fprintf(stderr, "Error setting cipher list '%s'\n", cipher_list); goto err; } fprintf(stderr, "Info, set cipher list '%s'\n", cipher_list); } else fprintf(stderr, "Info, operating with default cipher list\n"); /* dh_file & dh_special */ if ((dh_file || dh_special) && !ctx_set_dh(ctx, dh_file, dh_special)) goto err; /* ctx_options */ SSL_CTX_set_options(ctx, ctx_options); /* out_state (output of SSL handshake states to screen). */ if (out_state) cb_ssl_info_set_output(stderr); /* 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); /* Success! (includes setting verify_mode) */ SSL_CTX_set_info_callback(ctx, cb_ssl_info); SSL_CTX_set_verify(ctx, verify_mode, cb_ssl_verify); ret = ctx; err: if (!ret) { ERR_print_errors_fp(stderr); if (ctx) SSL_CTX_free(ctx); } return ret; }
/* Create and initialize an SSL configuration for a route. This configuration is used by all requests for a given route. An application can have different SSL configurations for different routes. There is also a default SSL configuration that is used when a route does not define a configuration and one for clients. */ static int configOss(MprSsl *ssl, int flags, char **errorMsg) { OpenConfig *cfg; X509_STORE *store; SSL_CTX *ctx; cchar *key; uchar resume[16]; int verifyMode; assert(ssl); if (ssl->config && !ssl->changed) { return 0; } if ((ssl->config = mprAllocObj(OpenConfig, manageOpenConfig)) == 0) { return MPR_ERR_MEMORY; } cfg = ssl->config; if ((ctx = SSL_CTX_new(SSLv23_method())) == 0) { mprLog("error openssl", 0, "Unable to create SSL context"); return MPR_ERR_CANT_INITIALIZE; } SSL_CTX_set_app_data(ctx, (void*) ssl); if (ssl->verifyPeer && !(ssl->caFile || ssl->caPath)) { *errorMsg = sfmt("Cannot verify peer due to undefined CA certificates"); SSL_CTX_free(ctx); return MPR_ERR_CANT_INITIALIZE; } /* Configure the certificates */ if (ssl->certFile) { if (setCertFile(ctx, ssl->certFile) < 0) { SSL_CTX_free(ctx); return MPR_ERR_CANT_INITIALIZE; } key = (ssl->keyFile == 0) ? ssl->certFile : ssl->keyFile; if (key) { if (setKeyFile(ctx, key) < 0) { SSL_CTX_free(ctx); return MPR_ERR_CANT_INITIALIZE; } if (!SSL_CTX_check_private_key(ctx)) { mprLog("error openssl", 0, "Check of private key file failed: %s", key); SSL_CTX_free(ctx); return MPR_ERR_CANT_INITIALIZE; } } } if (ssl->ciphers) { ssl->ciphers = mapCipherNames(ssl->ciphers); } if (!ssl->ciphers && (flags & MPR_SOCKET_SERVER)) { ssl->ciphers = sclone(OPENSSL_DEFAULT_CIPHERS); } if (ssl->ciphers) { mprLog("info openssl", 5, "Using SSL ciphers: %s", ssl->ciphers); if (SSL_CTX_set_cipher_list(ctx, ssl->ciphers) != 1) { *errorMsg = sfmt("Unable to set cipher list \"%s\"", ssl->ciphers); SSL_CTX_free(ctx); return MPR_ERR_CANT_INITIALIZE; } } verifyMode = ssl->verifyPeer ? SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT : SSL_VERIFY_NONE; if (verifyMode != SSL_VERIFY_NONE) { if (!(ssl->caFile || ssl->caPath)) { *errorMsg = sclone("No defined certificate authority file"); SSL_CTX_free(ctx); return MPR_ERR_CANT_INITIALIZE; } if ((!SSL_CTX_load_verify_locations(ctx, (char*) ssl->caFile, (char*) ssl->caPath)) || (!SSL_CTX_set_default_verify_paths(ctx))) { *errorMsg = sfmt("Unable to set certificate locations: %s: %s", ssl->caFile, ssl->caPath); SSL_CTX_free(ctx); return MPR_ERR_CANT_INITIALIZE; } if (ssl->caFile) { STACK_OF(X509_NAME) *certNames; certNames = SSL_load_client_CA_file(ssl->caFile); if (certNames) { /* Define the list of CA certificates to send to the client before they send their client certificate for validation */ SSL_CTX_set_client_CA_list(ctx, certNames); } } store = SSL_CTX_get_cert_store(ctx); if (ssl->revoke && !X509_STORE_load_locations(store, ssl->revoke, 0)) { mprLog("error openssl", 0, "Cannot load certificate revoke list: %s", ssl->revoke); SSL_CTX_free(ctx); return MPR_ERR_CANT_INITIALIZE; } if (flags & MPR_SOCKET_SERVER) { SSL_CTX_set_verify_depth(ctx, ssl->verifyDepth); } } /* Define callbacks */ SSL_CTX_set_verify(ctx, verifyMode, verifyPeerCertificate); if (flags & MPR_SOCKET_SERVER) { SSL_CTX_set_tlsext_servername_callback(ctx, sniHostname); } /* Configure DH parameters */ SSL_CTX_set_tmp_dh_callback(ctx, dhcallback); cfg->dhKey = getDhKey(); /* Define default OpenSSL options Ensure we generate a new private key for each connection Disable SSLv2 and SSLv3 by default -- they are insecure. */ cfg->setFlags = SSL_OP_ALL | SSL_OP_SINGLE_DH_USE | SSL_OP_SINGLE_ECDH_USE | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3; #ifdef SSL_OP_NO_TLSv1 if (!(ssl->protocols & MPR_PROTO_TLSV1)) { cfg->setFlags |= SSL_OP_NO_TLSv1; } #endif #ifdef SSL_OP_NO_TLSv1_1 if (!(ssl->protocols & MPR_PROTO_TLSV1_1)) { cfg->setFlags |= SSL_OP_NO_TLSv1_1; } #endif #ifdef SSL_OP_NO_TLSv1_2 if (!(ssl->protocols & MPR_PROTO_TLSV1_2)) { cfg->setFlags |= SSL_OP_NO_TLSv1_2; } #endif #ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING cfg->setFlags |= SSL_OP_MSIE_SSLV2_RSA_PADDING; #endif #if defined(SSL_OP_NO_TICKET) /* Ticket based session reuse is enabled by default */ #if defined(ME_MPR_SSL_TICKET) if (ME_MPR_SSL_TICKET) { cfg->clearFlags |= SSL_OP_NO_TICKET; } else { cfg->setFlags |= SSL_OP_NO_TICKET; } #else cfg->clearFlags |= SSL_OP_NO_TICKET; #endif #endif #if defined(SSL_OP_NO_COMPRESSION) /* CRIME attack targets compression */ cfg->clearFlags |= SSL_OP_NO_COMPRESSION; #endif #if defined(SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION) /* Force a new session on renegotiation. Default to true. This is required when using SNI and changing context during the SSL hello */ #if defined(ME_MPR_SSL_RENEGOTIATE) if (ME_MPR_SSL_RENEGOTIATE) { cfg->clearFlags |= SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION; } else { cfg->setFlags |= SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION; } #else cfg->setFlags |= SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION; #endif #endif #if defined(SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) /* Disables a countermeasure against a SSL 3.0/TLS 1.0 protocol vulnerability affecting CBC ciphers. Defaults to true. */ #if defined(ME_MPR_SSL_EMPTY_FRAGMENTS) if (ME_MPR_SSL_EMPTY_FRAGMENTS) { /* SSL_OP_ALL disables empty fragments. Only needed for ancient browsers like IE-6 on SSL-3.0/TLS-1.0 */ cfg->clearFlags |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; } else { cfg->setFlags |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; } #else cfg->setFlags |= SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; #endif #endif /* Define a session reuse context */ RAND_bytes(resume, sizeof(resume)); SSL_CTX_set_session_id_context(ctx, resume, sizeof(resume)); /* Elliptic Curve initialization */ #if SSL_OP_SINGLE_ECDH_USE #ifdef SSL_CTX_set_ecdh_auto /* This is supported in OpenSSL 1.0.2 */ SSL_CTX_set_ecdh_auto(ctx, 1); #else { EC_KEY *ecdh; cchar *name; int nid; name = ME_MPR_SSL_CURVE; if ((nid = OBJ_sn2nid(name)) == 0) { *errorMsg = sfmt("Unknown curve name \"%s\"", name); SSL_CTX_free(ctx); return MPR_ERR_CANT_INITIALIZE; } if ((ecdh = EC_KEY_new_by_curve_name(nid)) == 0) { *errorMsg = sfmt("Unable to create curve \"%s\"", name); SSL_CTX_free(ctx); return MPR_ERR_CANT_INITIALIZE; } SSL_CTX_set_tmp_ecdh(ctx, ecdh); EC_KEY_free(ecdh); } #endif #endif SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); #ifdef SSL_MODE_RELEASE_BUFFERS SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS); #endif #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE SSL_CTX_set_mode(ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); #endif #if defined(ME_MPR_SSL_CACHE) /* Set the number of sessions supported. Default in OpenSSL is 20K. */ SSL_CTX_sess_set_cache_size(ctx, ME_MPR_SSL_CACHE); #else SSL_CTX_sess_set_cache_size(ctx, 1024); #endif SSL_CTX_set_options(ctx, cfg->setFlags); SSL_CTX_clear_options(ctx, cfg->clearFlags); cfg->ctx = ctx; ssl->changed = 0; ssl->config = cfg; return 0; }
/* Set certification stuff. */ static int my_ssl_set_certs(MYSQL *mysql) { char *certfile= mysql->options.ssl_cert, *keyfile= mysql->options.ssl_key; DBUG_ENTER("my_ssl_set_certs"); /* Make sure that ssl was allocated and ssl_system was initialized */ DBUG_ASSERT(my_ssl_initialized == TRUE); /* add cipher */ if ((mysql->options.ssl_cipher && mysql->options.ssl_cipher[0] != 0) && SSL_CTX_set_cipher_list(SSL_context, mysql->options.ssl_cipher) == 0) goto error; /* ca_file and ca_path */ if (SSL_CTX_load_verify_locations(SSL_context, mysql->options.ssl_ca, mysql->options.ssl_capath) == 0) { if (mysql->options.ssl_ca || mysql->options.ssl_capath) goto error; if (SSL_CTX_set_default_verify_paths(SSL_context) == 0) goto error; } if (keyfile && !certfile) certfile= keyfile; if (certfile && !keyfile) keyfile= certfile; /* set cert */ if (certfile && certfile[0] != 0) if (SSL_CTX_use_certificate_file(SSL_context, certfile, SSL_FILETYPE_PEM) != 1) goto error; /* set key */ if (keyfile && keyfile[0]) { if (SSL_CTX_use_PrivateKey_file(SSL_context, keyfile, SSL_FILETYPE_PEM) != 1) goto error; } /* verify key */ if (certfile && !SSL_CTX_check_private_key(SSL_context)) goto error; if (mysql->options.extension && (mysql->options.extension->ssl_crl || mysql->options.extension->ssl_crlpath)) { X509_STORE *certstore; if ((certstore= SSL_CTX_get_cert_store(SSL_context))) { if (X509_STORE_load_locations(certstore, mysql->options.extension->ssl_crl, mysql->options.extension->ssl_crlpath) == 0 || X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL) == 0) goto error; } } DBUG_RETURN(0); error: my_SSL_error(mysql); DBUG_RETURN(1); }
int32_t mz_crypt_sign_verify(uint8_t *message, int32_t message_size, uint8_t *signature, int32_t signature_size) { CMS_ContentInfo *cms = NULL; STACK_OF(X509) *signers = NULL; STACK_OF(X509) *intercerts = NULL; X509_STORE *cert_store = NULL; X509_LOOKUP *lookup = NULL; X509_STORE_CTX *store_ctx = NULL; BIO *message_bio = NULL; BIO *signature_bio = NULL; BUF_MEM *buf_mem = NULL; int32_t signer_count = 0; int32_t result = 0; int32_t i = 0; int32_t err = MZ_SIGN_ERROR; if (message == NULL || message_size == 0 || signature == NULL || signature_size == 0) return MZ_PARAM_ERROR; mz_crypt_init(); cert_store = X509_STORE_new(); X509_STORE_load_locations(cert_store, "cacert.pem", NULL); X509_STORE_set_default_paths(cert_store); #if 0 BIO *yy = BIO_new_file("xyz", "wb"); BIO_write(yy, signature, signature_size); BIO_flush(yy); BIO_free(yy); #endif lookup = X509_STORE_add_lookup(cert_store, X509_LOOKUP_file()); if (lookup != NULL) X509_LOOKUP_load_file(lookup, "cacert.pem", X509_FILETYPE_PEM); lookup = X509_STORE_add_lookup(cert_store, X509_LOOKUP_hash_dir()); if (lookup != NULL) X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT); signature_bio = BIO_new_mem_buf(signature, signature_size); message_bio = BIO_new(BIO_s_mem()); cms = d2i_CMS_bio(signature_bio, NULL); if (cms) { result = CMS_verify(cms, NULL, cert_store, NULL, message_bio, CMS_NO_SIGNER_CERT_VERIFY | CMS_BINARY); if (result) signers = CMS_get0_signers(cms); if (signers) intercerts = CMS_get1_certs(cms); if (intercerts) { /* Verify signer certificates */ signer_count = sk_X509_num(signers); if (signer_count > 0) err = MZ_OK; for (i = 0; i < signer_count; i++) { store_ctx = X509_STORE_CTX_new(); X509_STORE_CTX_init(store_ctx, cert_store, sk_X509_value(signers, i), intercerts); result = X509_verify_cert(store_ctx); if (store_ctx) X509_STORE_CTX_free(store_ctx); if (!result) { err = MZ_SIGN_ERROR; break; } } } BIO_get_mem_ptr(message_bio, &buf_mem); if (err == MZ_OK) { /* Verify the message */ if (((int32_t)buf_mem->length != message_size) || (memcmp(buf_mem->data, message, message_size) != 0)) err = MZ_SIGN_ERROR; } } #if 0 if (!result) printf(ERR_error_string(ERR_get_error(), NULL)); #endif if (cms) CMS_ContentInfo_free(cms); if (message_bio) BIO_free(message_bio); if (signature_bio) BIO_free(signature_bio); if (cert_store) X509_STORE_free(cert_store); return err; }
static int ma_tls_set_certs(MYSQL *mysql) { char *certfile= mysql->options.ssl_cert, *keyfile= mysql->options.ssl_key; /* add cipher */ if ((mysql->options.ssl_cipher && mysql->options.ssl_cipher[0] != 0) && SSL_CTX_set_cipher_list(SSL_context, mysql->options.ssl_cipher) == 0) goto error; /* ca_file and ca_path */ if (SSL_CTX_load_verify_locations(SSL_context, mysql->options.ssl_ca, mysql->options.ssl_capath) == 0) { if (mysql->options.ssl_ca || mysql->options.ssl_capath) goto error; if (SSL_CTX_set_default_verify_paths(SSL_context) == 0) goto error; } if (keyfile && !certfile) certfile= keyfile; if (certfile && !keyfile) keyfile= certfile; /* set cert */ if (certfile && certfile[0] != 0) if (SSL_CTX_use_certificate_file(SSL_context, certfile, SSL_FILETYPE_PEM) != 1) goto error; /* If the private key file is encrypted, we need to register a callback function * for providing password. */ if (OPT_HAS_EXT_VAL(mysql, tls_pw)) { SSL_CTX_set_default_passwd_cb_userdata(SSL_context, (void *)mysql->options.extension->tls_pw); SSL_CTX_set_default_passwd_cb(SSL_context, ma_tls_get_password); } if (keyfile && keyfile[0]) { if (SSL_CTX_use_PrivateKey_file(SSL_context, keyfile, SSL_FILETYPE_PEM) != 1) { unsigned long err= ERR_peek_error(); if (!(ERR_GET_LIB(err) == ERR_LIB_X509 && ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE)) goto error; } } if (OPT_HAS_EXT_VAL(mysql, tls_pw)) { SSL_CTX_set_default_passwd_cb_userdata(SSL_context, NULL); SSL_CTX_set_default_passwd_cb(SSL_context, NULL); } /* verify key */ if (certfile && !SSL_CTX_check_private_key(SSL_context)) goto error; if (mysql->options.extension && (mysql->options.extension->ssl_crl || mysql->options.extension->ssl_crlpath)) { X509_STORE *certstore; if ((certstore= SSL_CTX_get_cert_store(SSL_context))) { if (X509_STORE_load_locations(certstore, mysql->options.extension->ssl_crl, mysql->options.extension->ssl_crlpath) == 0) goto error; X509_STORE_set_flags(certstore, X509_V_FLAG_CRL_CHECK | X509_V_FLAG_CRL_CHECK_ALL); } } return 0; error: ma_tls_set_error(mysql); return 1; }
/* Create and initialize an SSL configuration for a route. This configuration is used by all requests for a given route. An application can have different SSL configurations for different routes. There is also a default SSL configuration that is used when a route does not define a configuration and one for clients. */ static OpenConfig *createOpenSslConfig(MprSocket *sp) { MprSsl *ssl; OpenConfig *cfg; X509_STORE *store; SSL_CTX *context; cchar *key; uchar resume[16]; int verifyMode; ssl = sp->ssl; assert(ssl); if ((ssl->config = mprAllocObj(OpenConfig, manageOpenConfig)) == 0) { return 0; } cfg = ssl->config; if ((context = SSL_CTX_new(SSLv23_method())) == 0) { mprLog("error openssl", 0, "Unable to create SSL context"); return 0; } SSL_CTX_set_app_data(context, (void*) ssl); if (ssl->verifyPeer && !(ssl->caFile || ssl->caPath)) { sp->errorMsg = sfmt("Cannot verify peer due to undefined CA certificates"); SSL_CTX_free(context); return 0; } /* Configure the certificates */ if (ssl->certFile) { if (SSL_CTX_use_certificate_chain_file(context, ssl->certFile) <= 0) { if (SSL_CTX_use_certificate_file(context, ssl->certFile, SSL_FILETYPE_ASN1) <= 0) { mprLog("error openssl", 0, "Cannot open certificate file: %s", ssl->certFile); SSL_CTX_free(context); return 0; } } key = (ssl->keyFile == 0) ? ssl->certFile : ssl->keyFile; if (key) { if (SSL_CTX_use_PrivateKey_file(context, key, SSL_FILETYPE_PEM) <= 0) { /* attempt ASN1 for self-signed format */ if (SSL_CTX_use_PrivateKey_file(context, key, SSL_FILETYPE_ASN1) <= 0) { mprLog("error openssl", 0, "Cannot open private key file: %s", key); SSL_CTX_free(context); return 0; } } if (!SSL_CTX_check_private_key(context)) { mprLog("error openssl", 0, "Check of private key file failed: %s", key); SSL_CTX_free(context); return 0; } } } if (ssl->ciphers) { ssl->ciphers = mapCipherNames(ssl->ciphers); } if (!ssl->ciphers && (sp->flags & MPR_SOCKET_SERVER)) { ssl->ciphers = sclone(OPENSSL_DEFAULT_CIPHERS); } if (ssl->ciphers) { mprLog("info openssl", 5, "Using SSL ciphers: %s", ssl->ciphers); if (SSL_CTX_set_cipher_list(context, ssl->ciphers) != 1) { sp->errorMsg = sfmt("Unable to set cipher list \"%s\". %s", ssl->ciphers, getOssError(sp)); SSL_CTX_free(context); return 0; } } verifyMode = ssl->verifyPeer ? SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT : SSL_VERIFY_NONE; if (verifyMode != SSL_VERIFY_NONE) { if (!(ssl->caFile || ssl->caPath)) { sp->errorMsg = sclone("No defined certificate authority file"); SSL_CTX_free(context); return 0; } if ((!SSL_CTX_load_verify_locations(context, (char*) ssl->caFile, (char*) ssl->caPath)) || (!SSL_CTX_set_default_verify_paths(context))) { sp->errorMsg = sfmt("Unable to set certificate locations: %s: %s", ssl->caFile, ssl->caPath); SSL_CTX_free(context); return 0; } if (ssl->caFile) { STACK_OF(X509_NAME) *certNames; certNames = SSL_load_client_CA_file(ssl->caFile); if (certNames) { /* Define the list of CA certificates to send to the client before they send their client certificate for validation */ SSL_CTX_set_client_CA_list(context, certNames); } } store = SSL_CTX_get_cert_store(context); if (ssl->revokeList && !X509_STORE_load_locations(store, ssl->revokeList, 0)) { mprLog("error openssl", 0, "Cannot load certificate revoke list: %s", ssl->revokeList); SSL_CTX_free(context); return 0; } if (sp->flags & MPR_SOCKET_SERVER) { SSL_CTX_set_verify_depth(context, ssl->verifyDepth); } } /* Define callbacks */ SSL_CTX_set_verify(context, verifyMode, verifyPeerCertificate); /* Configure DH parameters */ SSL_CTX_set_tmp_dh_callback(context, dhcallback); cfg->dhKey = getDhKey(); /* Define default OpenSSL options */ SSL_CTX_set_options(context, SSL_OP_ALL); /* Ensure we generate a new private key for each connection */ SSL_CTX_set_options(context, SSL_OP_SINGLE_DH_USE); /* Define a session reuse context */ RAND_bytes(resume, sizeof(resume)); SSL_CTX_set_session_id_context(context, resume, sizeof(resume)); /* Elliptic Curve initialization */ #if SSL_OP_SINGLE_ECDH_USE #ifdef SSL_CTX_set_ecdh_auto SSL_CTX_set_ecdh_auto(context, 1); #else { EC_KEY *ecdh; cchar *name; int nid; name = ME_MPR_SSL_CURVE; if ((nid = OBJ_sn2nid(name)) == 0) { sp->errorMsg = sfmt("Unknown curve name \"%s\"", name); SSL_CTX_free(context); return 0; } if ((ecdh = EC_KEY_new_by_curve_name(nid)) == 0) { sp->errorMsg = sfmt("Unable to create curve \"%s\"", name); SSL_CTX_free(context); return 0; } SSL_CTX_set_options(context, SSL_OP_SINGLE_ECDH_USE); SSL_CTX_set_tmp_ecdh(context, ecdh); EC_KEY_free(ecdh); } #endif #endif SSL_CTX_set_mode(context, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY | SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER); #ifdef SSL_OP_MSIE_SSLV2_RSA_PADDING SSL_CTX_set_options(context, SSL_OP_MSIE_SSLV2_RSA_PADDING); #endif #ifdef SSL_MODE_RELEASE_BUFFERS SSL_CTX_set_mode(context, SSL_MODE_RELEASE_BUFFERS); #endif #ifdef SSL_OP_CIPHER_SERVER_PREFERENCE SSL_CTX_set_mode(context, SSL_OP_CIPHER_SERVER_PREFERENCE); #endif /* Select the required protocols Disable SSLv2 and SSLv3 by default -- they are insecure. */ SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); SSL_CTX_set_options(context, SSL_OP_NO_SSLv3); #ifdef SSL_OP_NO_TLSv1 if (!(ssl->protocols & MPR_PROTO_TLSV1)) { SSL_CTX_set_options(context, SSL_OP_NO_TLSv1); } #endif #ifdef SSL_OP_NO_TLSv1_1 if (!(ssl->protocols & MPR_PROTO_TLSV1_1)) { SSL_CTX_set_options(context, SSL_OP_NO_TLSv1_1); } #endif #ifdef SSL_OP_NO_TLSv1_2 if (!(ssl->protocols & MPR_PROTO_TLSV1_2)) { SSL_CTX_set_options(context, SSL_OP_NO_TLSv1_2); } #endif /* Options set via main.me mpr.ssl.* */ #if defined(SSL_OP_NO_TICKET) /* Ticket based session reuse is enabled by default */ #if defined(ME_MPR_SSL_TICKET) if (ME_MPR_SSL_TICKET) { SSL_CTX_clear_options(context, SSL_OP_NO_TICKET); } else { SSL_CTX_set_options(context, SSL_OP_NO_TICKET); } #else SSL_CTX_clear_options(context, SSL_OP_NO_TICKET); #endif #endif #if defined(SSL_OP_NO_COMPRESSION) /* Use of compression is not secure. Disabled by default. */ #if defined(ME_MPR_SSL_COMPRESSION) if (ME_MPR_SSL_COMPRESSION) { SSL_CTX_clear_options(context, SSL_OP_NO_COMPRESSION); } else { SSL_CTX_set_options(context, SSL_OP_NO_COMPRESSION); } #else /* CRIME attack targets compression */ SSL_CTX_clear_options(context, SSL_OP_NO_COMPRESSION); #endif #endif #if defined(SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION) /* Force a new session on renegotiation. Default to true. */ #if defined(ME_MPR_SSL_RENEGOTIATE) if (ME_MPR_SSL_RENEGOTIATE) { SSL_CTX_clear_options(context, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); } else { SSL_CTX_set_options(context, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); } #else SSL_CTX_set_options(context, SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION); #endif #endif #if defined(SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS) /* Disables a countermeasure against a SSL 3.0/TLS 1.0 protocol vulnerability affecting CBC ciphers. Defaults to true. */ #if defined(ME_MPR_SSL_EMPTY_FRAGMENTS) if (ME_MPR_SSL_EMPTY_FRAGMENTS) { /* SSL_OP_ALL disables empty fragments. Only needed for ancient browsers like IE-6 on SSL-3.0/TLS-1.0 */ SSL_CTX_clear_options(context, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); } else { SSL_CTX_set_options(context, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); } #else SSL_CTX_set_options(context, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS); #endif #endif #if defined(ME_MPR_SSL_CACHE) /* Set the number of sessions supported. Default in OpenSSL is 20K. */ SSL_CTX_sess_set_cache_size(context, ME_MPR_SSL_CACHE); #else SSL_CTX_sess_set_cache_size(context, 1024); #endif cfg->context = context; return cfg; }