This already worked when compiled against openssl, but not with gnutls.

Signed-off-by: Craig Gallek <cgal...@gmail.com>
---

NOTE: this depends on a yet-to-be-merged change to gnutls:
https://gitlab.com/gnutls/gnutls/-/merge_requests/1459

I figured it would be good to get some early feedback on this, though.
In particular, do you care that this duplicates a translation string?
It could certainly be put in a common place, but I wasn't sure where.

This change is safe with or without the gnutls change.  It simply won't
call the prompt callback with older versions of gnutls (though, it's proabably
best to wait for that change anyway to ensure that this callback mechanism
will be the one actually used).

 mutt_ssl_gnutls.c | 35 +++++++++++++++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/mutt_ssl_gnutls.c b/mutt_ssl_gnutls.c
index a576ab1537cb..b4540ad09ced 100644
--- a/mutt_ssl_gnutls.c
+++ b/mutt_ssl_gnutls.c
@@ -93,6 +93,10 @@ static int tls_starttls_close (CONNECTION* conn);
 static int tls_init (void);
 static int tls_negotiate (CONNECTION* conn);
 static int tls_check_certificate (CONNECTION* conn);
+static int tls_passwd_cb (void* userdata, int attempt, const char* token_url,
+                          const char* token_label,
+                          unsigned int flags,
+                          char* pin, size_t pin_max);
 
 
 static int tls_init (void)
@@ -426,6 +430,8 @@ static int tls_negotiate (CONNECTION * conn)
     mutt_sleep (2);
     return -1;
   }
+  gnutls_certificate_set_pin_function (data->xcred, tls_passwd_cb,
+                                       &conn->account);
 
   gnutls_certificate_set_x509_trust_file (data->xcred, SslCertFile,
                                          GNUTLS_X509_FMT_PEM);
@@ -1262,3 +1268,32 @@ static int tls_check_certificate (CONNECTION* conn)
 
   return rc;
 }
+
+static void client_cert_prompt (char *prompt, size_t prompt_size, ACCOUNT 
*account)
+{
+  /* L10N:
+     When using a $ssl_client_cert, GNUTLS may prompt for the password
+     to decrypt the cert.  %s is the hostname.
+  */
+  snprintf (prompt, prompt_size, _("Password for %s client cert: "),
+            account->host);
+}
+
+static int tls_passwd_cb (void* userdata, int attempt, const char* token_url,
+                          const char* token_label,
+                          unsigned int flags,
+                          char* buf, size_t size)
+{
+  ACCOUNT *account;
+
+  if (!buf || size <= 0 || !userdata)
+    return GNUTLS_E_INVALID_PASSWORD;
+
+  account = (ACCOUNT *) userdata;
+
+  if (_mutt_account_getpass (account, client_cert_prompt))
+    return GNUTLS_E_INVALID_PASSWORD;
+
+  snprintf(buf, size, "%s", account->pass);
+  return GNUTLS_E_SUCCESS;
+}
-- 
2.30.2

Reply via email to