提交 30dd9163 编写于 作者: M Mark Lodato 提交者: Junio C Hamano

http.c: prompt for SSL client certificate password

If an SSL client certificate is enabled (via http.sslcert or
GIT_SSL_CERT), prompt for the certificate password rather than
defaulting to OpenSSL's password prompt.  This causes the prompt to only
appear once each run.  Previously, OpenSSL prompted the user *many*
times, causing git to be unusable over HTTPS with client-side
certificates.

Note that the password is stored in memory in the clear while the
program is running.  This may be a security problem if git crashes and
core dumps.

The user is always prompted, even if the certificate is not encrypted.
This should be fine; unencrypted certificates are rare and a security
risk anyway.
Signed-off-by: NMark Lodato <lodatom@gmail.com>
Signed-off-by: NJunio C Hamano <gitster@pobox.com>
上级 cb9d398c
...@@ -27,6 +27,17 @@ static int curl_ftp_no_epsv; ...@@ -27,6 +27,17 @@ static int curl_ftp_no_epsv;
static const char *curl_http_proxy; static const char *curl_http_proxy;
static char *user_name, *user_pass; static char *user_name, *user_pass;
#if LIBCURL_VERSION_NUM >= 0x071700
/* Use CURLOPT_KEYPASSWD as is */
#elif LIBCURL_VERSION_NUM >= 0x070903
#define CURLOPT_KEYPASSWD CURLOPT_SSLKEYPASSWD
#else
#define CURLOPT_KEYPASSWD CURLOPT_SSLCERTPASSWD
#endif
static char *ssl_cert_password;
static int ssl_cert_password_required;
static struct curl_slist *pragma_header; static struct curl_slist *pragma_header;
static struct active_request_slot *active_queue_head; static struct active_request_slot *active_queue_head;
...@@ -167,6 +178,22 @@ static void init_curl_http_auth(CURL *result) ...@@ -167,6 +178,22 @@ static void init_curl_http_auth(CURL *result)
} }
} }
static int has_cert_password(void)
{
if (ssl_cert_password != NULL)
return 1;
if (ssl_cert == NULL || ssl_cert_password_required != 1)
return 0;
/* Only prompt the user once. */
ssl_cert_password_required = -1;
ssl_cert_password = getpass("Certificate Password: ");
if (ssl_cert_password != NULL) {
ssl_cert_password = xstrdup(ssl_cert_password);
return 1;
} else
return 0;
}
static CURL *get_curl_handle(void) static CURL *get_curl_handle(void)
{ {
CURL *result = curl_easy_init(); CURL *result = curl_easy_init();
...@@ -189,6 +216,8 @@ static CURL *get_curl_handle(void) ...@@ -189,6 +216,8 @@ static CURL *get_curl_handle(void)
if (ssl_cert != NULL) if (ssl_cert != NULL)
curl_easy_setopt(result, CURLOPT_SSLCERT, ssl_cert); curl_easy_setopt(result, CURLOPT_SSLCERT, ssl_cert);
if (has_cert_password())
curl_easy_setopt(result, CURLOPT_KEYPASSWD, ssl_cert_password);
#if LIBCURL_VERSION_NUM >= 0x070902 #if LIBCURL_VERSION_NUM >= 0x070902
if (ssl_key != NULL) if (ssl_key != NULL)
curl_easy_setopt(result, CURLOPT_SSLKEY, ssl_key); curl_easy_setopt(result, CURLOPT_SSLKEY, ssl_key);
...@@ -329,8 +358,11 @@ void http_init(struct remote *remote) ...@@ -329,8 +358,11 @@ void http_init(struct remote *remote)
if (getenv("GIT_CURL_FTP_NO_EPSV")) if (getenv("GIT_CURL_FTP_NO_EPSV"))
curl_ftp_no_epsv = 1; curl_ftp_no_epsv = 1;
if (remote && remote->url && remote->url[0]) if (remote && remote->url && remote->url[0]) {
http_auth_init(remote->url[0]); http_auth_init(remote->url[0]);
if (!prefixcmp(remote->url[0], "https://"))
ssl_cert_password_required = 1;
}
#ifndef NO_CURL_EASY_DUPHANDLE #ifndef NO_CURL_EASY_DUPHANDLE
curl_default = get_curl_handle(); curl_default = get_curl_handle();
...@@ -370,6 +402,13 @@ void http_cleanup(void) ...@@ -370,6 +402,13 @@ void http_cleanup(void)
free((void *)curl_http_proxy); free((void *)curl_http_proxy);
curl_http_proxy = NULL; curl_http_proxy = NULL;
} }
if (ssl_cert_password != NULL) {
memset(ssl_cert_password, 0, strlen(ssl_cert_password));
free(ssl_cert_password);
ssl_cert_password = NULL;
}
ssl_cert_password_required = 0;
} }
struct active_request_slot *get_active_slot(void) struct active_request_slot *get_active_slot(void)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册