aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/config.txt6
-rw-r--r--http.c48
2 files changed, 53 insertions, 1 deletions
diff --git a/Documentation/config.txt b/Documentation/config.txt
index bf97e1dee..cb6832b4e 100644
--- a/Documentation/config.txt
+++ b/Documentation/config.txt
@@ -1045,6 +1045,12 @@ http.sslKey::
over HTTPS. Can be overridden by the 'GIT_SSL_KEY' environment
variable.
+http.sslCertPasswordProtected::
+ Enable git's password prompt for the SSL certificate. Otherwise
+ OpenSSL will prompt the user, possibly many times, if the
+ certificate or private key is encrypted. Can be overridden by the
+ 'GIT_SSL_CERT_PASSWORD_PROTECTED' environment variable.
+
http.sslCAInfo::
File containing the certificates to verify the peer with when
fetching or pushing over HTTPS. Can be overridden by the
diff --git a/http.c b/http.c
index b04994824..a2720d576 100644
--- a/http.c
+++ b/http.c
@@ -33,6 +33,17 @@ static int curl_ftp_no_epsv;
static const char *curl_http_proxy;
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 *no_pragma_header;
@@ -136,6 +147,11 @@ static int http_options(const char *var, const char *value, void *cb)
#endif
if (!strcmp("http.sslcainfo", var))
return git_config_string(&ssl_cainfo, var, value);
+ if (!strcmp("http.sslcertpasswordprotected", var)) {
+ if (git_config_bool(var, value))
+ ssl_cert_password_required = 1;
+ return 0;
+ }
#ifdef USE_CURL_MULTI
if (!strcmp("http.maxrequests", var)) {
max_requests = git_config_int(var, value);
@@ -174,6 +190,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)
{
CURL *result = curl_easy_init();
@@ -196,6 +228,8 @@ static CURL *get_curl_handle(void)
if (ssl_cert != NULL)
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 >= 0x070903
if (ssl_key != NULL)
curl_easy_setopt(result, CURLOPT_SSLKEY, ssl_key);
@@ -339,8 +373,13 @@ void http_init(struct remote *remote)
if (getenv("GIT_CURL_FTP_NO_EPSV"))
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]);
+ if (!ssl_cert_password_required &&
+ getenv("GIT_SSL_CERT_PASSWORD_PROTECTED") &&
+ !prefixcmp(remote->url[0], "https://"))
+ ssl_cert_password_required = 1;
+ }
#ifndef NO_CURL_EASY_DUPHANDLE
curl_default = get_curl_handle();
@@ -383,6 +422,13 @@ void http_cleanup(void)
free((void *)curl_http_proxy);
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)