aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPetr Písař <petr.pisar@atlas.cz>2013-08-20 17:02:53 +0200
committerDaniel Stenberg <daniel@haxx.se>2013-09-07 00:11:21 +0200
commit0119a93b335dfc7f58304a6c92f114c4f655b5a3 (patch)
treec29b389c558711cf059ee83eaf0ed0103a7a116e
parent9fa42beddc5e1f469ddf276a0715f2de82f51b6b (diff)
Pass password to OpenSSL engine by user interface
Recent OpenSSL uses user interface abstraction to negotiate access to private keys in the cryprographical engines. An OpenSSL application is expected to implement the user interface. Otherwise a default one provided by OpenSSL (interactive standard I/O) will be used and the aplication will have no way how to pass a password to the engine. Longer-desc: http://curl.haxx.se/mail/lib-2013-08/0265.html
-rw-r--r--lib/ssluse.c57
1 files changed, 56 insertions, 1 deletions
diff --git a/lib/ssluse.c b/lib/ssluse.c
index 69328f66a..57e8bea0b 100644
--- a/lib/ssluse.c
+++ b/lib/ssluse.c
@@ -294,6 +294,49 @@ static int do_file_type(const char *type)
return -1;
}
+#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
+/*
+ * Supply default password to the engine user interface conversation.
+ * The password is passed by OpenSSL engine from ENGINE_load_private_key()
+ * last argument to the ui and can be obtained by UI_get0_user_data(ui) here.
+ */
+static int ssl_ui_reader(UI *ui, UI_STRING *uis)
+{
+ const char *password;
+ switch(UI_get_string_type(uis)) {
+ case UIT_PROMPT:
+ case UIT_VERIFY:
+ password = (const char*)UI_get0_user_data(ui);
+ if(NULL != password &&
+ UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD) {
+ UI_set_result(ui, uis, password);
+ return 1;
+ }
+ default:
+ break;
+ }
+ return (UI_method_get_reader(UI_OpenSSL()))(ui, uis);
+}
+
+/*
+ * Suppress interactive request for a default password if available.
+ */
+static int ssl_ui_writer(UI *ui, UI_STRING *uis)
+{
+ switch(UI_get_string_type(uis)) {
+ case UIT_PROMPT:
+ case UIT_VERIFY:
+ if(NULL != UI_get0_user_data(ui) &&
+ UI_get_input_flags(uis) & UI_INPUT_FLAG_DEFAULT_PWD) {
+ return 1;
+ }
+ default:
+ break;
+ }
+ return (UI_method_get_writer(UI_OpenSSL()))(ui, uis);
+}
+#endif
+
static
int cert_stuff(struct connectdata *conn,
SSL_CTX* ctx,
@@ -527,7 +570,16 @@ int cert_stuff(struct connectdata *conn,
EVP_PKEY *priv_key = NULL;
if(data->state.engine) {
#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
- UI_METHOD *ui_method = UI_OpenSSL();
+ UI_METHOD *ui_method =
+ UI_create_method((char *)"cURL user interface");
+ if(NULL == ui_method) {
+ failf(data, "unable do create OpenSSL user-interface method");
+ return 0;
+ }
+ UI_method_set_opener(ui_method, UI_method_get_opener(UI_OpenSSL()));
+ UI_method_set_closer(ui_method, UI_method_get_closer(UI_OpenSSL()));
+ UI_method_set_reader(ui_method, ssl_ui_reader);
+ UI_method_set_writer(ui_method, ssl_ui_writer);
#endif
/* the typecast below was added to please mingw32 */
priv_key = (EVP_PKEY *)
@@ -536,6 +588,9 @@ int cert_stuff(struct connectdata *conn,
ui_method,
#endif
data->set.str[STRING_KEY_PASSWD]);
+#ifdef HAVE_ENGINE_LOAD_FOUR_ARGS
+ UI_destroy_method(ui_method);
+#endif
if(!priv_key) {
failf(data, "failed to load private key from crypto engine");
return 0;