1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
|
From 276cf337346e0ea111883a05bc00f764d201d6ab Mon Sep 17 00:00:00 2001
From: Alejandro Soto <alejandro@34project.org>
Date: Sun, 29 Jun 2025 11:35:57 -0600
Subject: [PATCH 2/2] gnutls: implement token insertion and PKCS#11 PIN prompts
---
conn/gnutls.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 71 insertions(+), 1 deletion(-)
diff --git a/conn/gnutls.c b/conn/gnutls.c
index 379580871..32ad1ae85 100644
--- a/conn/gnutls.c
+++ b/conn/gnutls.c
@@ -29,6 +29,7 @@
#include "config.h"
#include <gnutls/gnutls.h>
+#include <gnutls/pkcs11.h>
#include <gnutls/x509.h>
#include <stdbool.h>
#include <stdio.h>
@@ -39,10 +40,14 @@
#include "mutt/lib.h"
#include "config/lib.h"
#include "core/lib.h"
-#include "lib.h"
#include "connaccount.h"
#include "connection.h"
+#include "editor/lib.h"
#include "globals.h"
+#include "gui/lib.h"
+#include "history/lib.h"
+#include "lib.h"
+#include "mutt.h"
#include "muttlib.h"
#include "ssl.h"
@@ -84,6 +89,64 @@ struct TlsSockData
gnutls_certificate_credentials_t xcred;
};
+int tls_pkcs11_token_callback(void *userdata, const char *label, unsigned retry)
+{
+ (void) userdata;
+
+ if (OptNoCurses) {
+ mutt_error(_("Unable to prompt for PKCS#11 token insertion in batch mode"));
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ char msg[256] = { 0 };
+
+ size_t len = 0;
+ if (retry > 0)
+ len += snprintf(msg, sizeof msg, _("[Not found - attempt %u] "), retry + 1);
+
+ snprintf(msg + len, sizeof msg - len, _("Insert PKCS#11 token '%s' and press any key..."), label);
+
+ mutt_any_key_to_continue(msg);
+ return 0;
+}
+
+int tls_pin_callback(void *userdata, int attempt, const char *url, const char *label,
+ unsigned int flags, char *pin, size_t pin_max)
+{
+ (void) url;
+ const intptr_t is_token = (intptr_t) userdata;
+
+ if (OptNoCurses) {
+ mutt_error(_("Unable to prompt for pin in batch mode"));
+ return GNUTLS_E_INVALID_REQUEST;
+ }
+
+ char prompt[256] = { 0 };
+
+ size_t len = 0;
+ if (attempt > 0)
+ len += snprintf(prompt, sizeof prompt, _("[Attempt %d] "), attempt + 1);
+
+ if (flags & GNUTLS_PIN_FINAL_TRY)
+ len += mutt_str_copy(prompt + len, _("FINAL TRY - "), sizeof prompt - len);
+
+ if (is_token)
+ snprintf(prompt + len, sizeof prompt - len, _("Pin for PKCS#11 token '%s': "), label);
+ else
+ snprintf(prompt + len, sizeof prompt - len, _("Password for certificate '%s': "), label);
+
+ struct Buffer *buf = buf_pool_get();
+ const int rc = mw_get_field(prompt, buf, MUTT_COMP_PASS | MUTT_COMP_UNBUFFERED,
+ HC_OTHER, NULL, NULL);
+ mutt_str_copy(pin, buf_string(buf), pin_max);
+ buf_pool_release(&buf);
+
+ if (rc != 0)
+ return GNUTLS_E_APPLICATION_ERROR_MIN;
+
+ return 0;
+}
+
/**
* tls_init - Set up Gnu TLS
* @retval 0 Success
@@ -104,6 +167,10 @@ static int tls_init(void)
return -1;
}
+ const intptr_t is_token = 1;
+ gnutls_pkcs11_set_pin_function(tls_pin_callback, (void *)is_token);
+ gnutls_pkcs11_set_token_function(tls_pkcs11_token_callback, NULL);
+
init_complete = true;
return 0;
}
@@ -904,6 +971,9 @@ static int tls_negotiate(struct Connection *conn)
mutt_debug(LL_DEBUG2, "Using client certificate %s, key %s\n", c_ssl_client_cert, c_ssl_client_key);
gnutls_certificate_set_x509_key_file(data->xcred, c_ssl_client_cert,
c_ssl_client_key, GNUTLS_X509_FMT_PEM);
+
+ const intptr_t is_token = 0;
+ gnutls_certificate_set_pin_function(data->xcred, tls_pin_callback, (void *)is_token);
}
#ifdef HAVE_DECL_GNUTLS_VERIFY_DISABLE_TIME_CHECKS
--
2.49.0
|