const UI_METHOD *UI_get_default_method(void) { if (default_UI_meth == NULL) { default_UI_meth = UI_OpenSSL(); } return default_UI_meth; }
NOEXPORT int load_key_engine(SERVICE_OPTIONS *section) { int i, reason; UI_DATA ui_data; EVP_PKEY *pkey; UI_METHOD *ui_method; s_log(LOG_INFO, "Loading key from engine: %s", section->key); ui_data.section=section; /* setup current section for callbacks */ #if defined(USE_WIN32) || OPENSSL_VERSION_NUMBER>=0x0090700fL SSL_CTX_set_default_passwd_cb(section->ctx, password_cb); #endif #ifdef USE_WIN32 ui_method=UI_create_method("stunnel WIN32 UI"); UI_method_set_reader(ui_method, pin_cb); #else /* USE_WIN32 */ ui_method=UI_OpenSSL(); /* workaround for broken engines */ /* ui_data.section=NULL; */ #endif /* USE_WIN32 */ for(i=1; i<=3; i++) { pkey=ENGINE_load_private_key(section->engine, section->key, ui_method, &ui_data); if(!pkey) { reason=ERR_GET_REASON(ERR_peek_error()); if(i<=2 && (reason==7 || reason==160)) { /* wrong PIN */ sslerror_queue(); /* dump the error queue */ s_log(LOG_ERR, "Wrong PIN: retrying"); continue; } sslerror("ENGINE_load_private_key"); return 1; /* FAILED */ } if(SSL_CTX_use_PrivateKey(section->ctx, pkey)) break; /* success */ sslerror("SSL_CTX_use_PrivateKey"); return 1; /* FAILED */ } return 0; /* OK */ }
static int ui_write(UI *ui, UI_STRING *uis) { if (UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD && UI_get0_user_data(ui)) { switch(UI_get_string_type(uis)) { case UIT_PROMPT: case UIT_VERIFY: { const char *password = (const char*) ((PW_CB_DATA *)UI_get0_user_data(ui))->password; if (password && password[0] != '\0') return 1; } default: break; } } return UI_method_get_writer(UI_OpenSSL())(ui, uis); }
static int ui_open(UI *ui) { return UI_method_get_opener(UI_OpenSSL())(ui); }
static int ui_close(UI *ui) { return UI_method_get_closer(UI_OpenSSL())(ui); }
static int cert_stuff(struct connectdata *conn, SSL_CTX* ctx, char *cert_file, const char *cert_type, char *key_file, const char *key_type) { struct SessionHandle *data = conn->data; int file_type; if(cert_file != NULL) { SSL *ssl; X509 *x509; if(data->set.key_passwd) { #ifndef HAVE_USERDATA_IN_PWD_CALLBACK /* * If password has been given, we store that in the global * area (*shudder*) for a while: */ size_t len = strlen(data->set.key_passwd); if(len < sizeof(global_passwd)) memcpy(global_passwd, data->set.key_passwd, len+1); #else /* * We set the password in the callback userdata */ SSL_CTX_set_default_passwd_cb_userdata(ctx, data->set.key_passwd); #endif /* Set passwd callback: */ SSL_CTX_set_default_passwd_cb(ctx, passwd_callback); } file_type = do_file_type(cert_type); switch(file_type) { case SSL_FILETYPE_PEM: /* SSL_CTX_use_certificate_chain_file() only works on PEM files */ if(SSL_CTX_use_certificate_chain_file(ctx, cert_file) != 1) { failf(data, "unable to set certificate file (wrong password?)"); return 0; } break; case SSL_FILETYPE_ASN1: /* SSL_CTX_use_certificate_file() works with either PEM or ASN1, but we use the case above for PEM so this can only be performed with ASN1 files. */ if(SSL_CTX_use_certificate_file(ctx, cert_file, file_type) != 1) { failf(data, "unable to set certificate file (wrong password?)"); return 0; } break; case SSL_FILETYPE_ENGINE: failf(data, "file type ENG for certificate not implemented"); return 0; default: failf(data, "not supported file type '%s' for certificate", cert_type); return 0; } file_type = do_file_type(key_type); switch(file_type) { case SSL_FILETYPE_PEM: if(key_file == NULL) /* cert & key can only be in PEM case in the same file */ key_file=cert_file; case SSL_FILETYPE_ASN1: if(SSL_CTX_use_PrivateKey_file(ctx, key_file, file_type) != 1) { failf(data, "unable to set private key file: '%s' type %s\n", key_file, key_type?key_type:"PEM"); return 0; } break; case SSL_FILETYPE_ENGINE: #ifdef HAVE_OPENSSL_ENGINE_H { /* XXXX still needs some work */ EVP_PKEY *priv_key = NULL; if(conn && conn->data && conn->data->engine) { #ifdef HAVE_ENGINE_LOAD_FOUR_ARGS UI_METHOD *ui_method = UI_OpenSSL(); #endif if(!key_file || !key_file[0]) { failf(data, "no key set to load from crypto engine\n"); return 0; } /* the typecast below was added to please mingw32 */ priv_key = (EVP_PKEY *) ENGINE_load_private_key(conn->data->engine,key_file, #ifdef HAVE_ENGINE_LOAD_FOUR_ARGS ui_method, #endif data->set.key_passwd); if(!priv_key) { failf(data, "failed to load private key from crypto engine\n"); return 0; } if(SSL_CTX_use_PrivateKey(ctx, priv_key) != 1) { failf(data, "unable to set private key\n"); EVP_PKEY_free(priv_key); return 0; } EVP_PKEY_free(priv_key); /* we don't need the handle any more... */ } else { failf(data, "crypto engine not set, can't load private key\n"); return 0; } } break; #else failf(data, "file type ENG for private key not supported\n"); return 0; #endif default: failf(data, "not supported file type for private key\n"); return 0; } ssl=SSL_new(ctx); x509=SSL_get_certificate(ssl); /* This version was provided by Evan Jordan and is supposed to not leak memory as the previous version: */ if(x509 != NULL) { EVP_PKEY *pktmp = X509_get_pubkey(x509); EVP_PKEY_copy_parameters(pktmp,SSL_get_privatekey(ssl)); EVP_PKEY_free(pktmp); } SSL_free(ssl); /* If we are using DSA, we can copy the parameters from * the private key */ /* Now we know that a key and cert have been set against * the SSL context */ if(!SSL_CTX_check_private_key(ctx)) { failf(data, "Private key does not match the certificate public key"); return(0); } #ifndef HAVE_USERDATA_IN_PWD_CALLBACK /* erase it now */ memset(global_passwd, 0, sizeof(global_passwd)); #endif } return(1); }
static int SAVEDS ui_open(UI *ui) { int (*func)(UI *) = UI_method_get_opener(UI_OpenSSL()); return(func ? func(ui) : 1); }
static int SAVEDS ui_write(UI *ui, UI_STRING *uis) { int (*func)(UI *, UI_STRING *) = UI_method_get_writer(UI_OpenSSL()); return(func ? func(ui, uis) : 1); }
int tls_ctx_load_priv_file (struct tls_root_ctx *ctx, const char *priv_key_engine, const char *priv_key_file #if ENABLE_INLINE_FILES , const char *priv_key_file_inline #endif ) { int status; SSL_CTX *ssl_ctx = NULL; BIO *in = NULL; EVP_PKEY *pkey = NULL; int ret = 1; ASSERT(NULL != ctx); ssl_ctx = ctx->ctx; #if ENABLE_INLINE_FILES if (!strcmp (priv_key_file, INLINE_FILE_TAG) && priv_key_file_inline) in = BIO_new_mem_buf ((char *)priv_key_file_inline, -1); else #endif /* ENABLE_INLINE_FILES */ in = BIO_new_file (priv_key_file, "r"); if (!in) goto end; if (priv_key_engine) { ENGINE *engine; ENGINE_load_builtin_engines(); engine = ENGINE_by_id(priv_key_engine); if (!ENGINE_init(engine)) { msg (M_WARN|M_SSL, "Cannot init engine %s", priv_key_engine); goto end; } pkey = ENGINE_load_private_key(engine, priv_key_file, UI_OpenSSL(), NULL); } else { pkey = PEM_read_bio_PrivateKey (in, NULL, ssl_ctx->default_passwd_callback, ssl_ctx->default_passwd_callback_userdata); } if (!pkey) goto end; if (!SSL_CTX_use_PrivateKey (ssl_ctx, pkey)) { #ifdef ENABLE_MANAGEMENT if (management && (ERR_GET_REASON (ERR_peek_error()) == EVP_R_BAD_DECRYPT)) management_auth_failure (management, UP_TYPE_PRIVATE_KEY, NULL); #endif msg (M_WARN|M_SSL, "Cannot load private key file %s", priv_key_file); goto end; } warn_if_group_others_accessible (priv_key_file); /* Check Private Key */ if (!SSL_CTX_check_private_key (ssl_ctx)) msg (M_SSLERR, "Private key does not match the certificate"); ret = 0; end: if (pkey) EVP_PKEY_free (pkey); if (in) BIO_free (in); return ret; }