|
|
12bf12 |
--- neon-0.30.0/macros/neon.m4.pkcs11
|
|
|
12bf12 |
+++ neon-0.30.0/macros/neon.m4
|
|
|
12bf12 |
@@ -982,10 +982,11 @@
|
|
|
12bf12 |
|
|
|
12bf12 |
# Check for functions in later releases
|
|
|
12bf12 |
NE_CHECK_FUNCS([gnutls_session_get_data2 gnutls_x509_dn_get_rdn_ava \
|
|
|
12bf12 |
- gnutls_sign_callback_set \
|
|
|
12bf12 |
gnutls_certificate_get_issuer \
|
|
|
12bf12 |
gnutls_certificate_get_x509_cas \
|
|
|
12bf12 |
- gnutls_x509_crt_sign2])
|
|
|
12bf12 |
+ gnutls_x509_crt_sign2 \
|
|
|
12bf12 |
+ gnutls_certificate_set_retrieve_function2 \
|
|
|
12bf12 |
+ gnutls_privkey_import_ext])
|
|
|
12bf12 |
|
|
|
12bf12 |
# fail if gnutls_x509_crt_sign2 is not found (it was introduced in 1.2.0, which is required)
|
|
|
12bf12 |
if test x${ac_cv_func_gnutls_x509_crt_sign2} != xyes; then
|
|
|
12bf12 |
@@ -1039,7 +1040,7 @@
|
|
|
12bf12 |
;;
|
|
|
12bf12 |
esac
|
|
|
12bf12 |
|
|
|
12bf12 |
-case ${with_pakchois}X${ac_cv_func_gnutls_sign_callback_set}Y${ne_cv_lib_ssl097} in
|
|
|
12bf12 |
+case ${with_pakchois}X${ac_cv_func_gnutls_privkey_import_ext}Y${ne_cv_lib_ssl097} in
|
|
|
12bf12 |
noX*Y*) ;;
|
|
|
12bf12 |
*X*Yyes|*XyesY*)
|
|
|
12bf12 |
# PKCS#11... ho!
|
|
|
12bf12 |
--- neon-0.30.0/src/ne_gnutls.c.pkcs11
|
|
|
12bf12 |
+++ neon-0.30.0/src/ne_gnutls.c
|
|
|
12bf12 |
@@ -89,6 +89,13 @@
|
|
|
12bf12 |
ne_ssl_certificate cert;
|
|
|
12bf12 |
gnutls_x509_privkey_t pkey;
|
|
|
12bf12 |
char *friendly_name;
|
|
|
12bf12 |
+#ifdef HAVE_GNUTLS_PRIVKEY_IMPORT_EXT
|
|
|
12bf12 |
+ /* Signing callback & userdata provided by ne_pkcs11.c. It would
|
|
|
12bf12 |
+ * be better to rewrite the whole module to use gnutls_privkey_t
|
|
|
12bf12 |
+ * directly, but it seems impossible to dup such an object. */
|
|
|
12bf12 |
+ gnutls_privkey_sign_func sign_func;
|
|
|
12bf12 |
+ void *sign_ud;
|
|
|
12bf12 |
+#endif
|
|
|
12bf12 |
};
|
|
|
12bf12 |
|
|
|
12bf12 |
/* Returns the highest used index in subject (or issuer) DN of
|
|
|
12bf12 |
@@ -189,7 +196,7 @@
|
|
|
12bf12 |
char *ne_ssl_readable_dname(const ne_ssl_dname *name)
|
|
|
12bf12 |
{
|
|
|
12bf12 |
gnutls_x509_dn_t dn;
|
|
|
12bf12 |
- int ret, rdn = 0, flag = 0;
|
|
|
12bf12 |
+ int ret, rdn = 0;
|
|
|
12bf12 |
ne_buffer *buf;
|
|
|
12bf12 |
gnutls_x509_ava_st val;
|
|
|
12bf12 |
|
|
|
12bf12 |
@@ -227,7 +234,6 @@
|
|
|
12bf12 |
&& ((!CMPOID(&val, OID_emailAddress)
|
|
|
12bf12 |
&& !CMPOID(&val, OID_commonName))
|
|
|
12bf12 |
|| (buf->used == 1 && rdn == 0))) {
|
|
|
12bf12 |
- flag = 1;
|
|
|
12bf12 |
if (buf->used > 1) ne_buffer_append(buf, ", ", 2);
|
|
|
12bf12 |
|
|
|
12bf12 |
append_dirstring(buf, &val.value, val.value_tag);
|
|
|
12bf12 |
@@ -526,6 +532,10 @@
|
|
|
12bf12 |
|
|
|
12bf12 |
if (cc->keyless) {
|
|
|
12bf12 |
newcc->keyless = 1;
|
|
|
12bf12 |
+#ifdef HAVE_GNUTLS_PRIVKEY_IMPORT_EXT
|
|
|
12bf12 |
+ newcc->sign_func = cc->sign_func;
|
|
|
12bf12 |
+ newcc->sign_ud = cc->sign_ud;
|
|
|
12bf12 |
+#endif
|
|
|
12bf12 |
}
|
|
|
12bf12 |
else {
|
|
|
12bf12 |
ret = gnutls_x509_privkey_init(&newcc->pkey);
|
|
|
12bf12 |
@@ -554,7 +564,15 @@
|
|
|
12bf12 |
static int provide_client_cert(gnutls_session_t session,
|
|
|
12bf12 |
const gnutls_datum_t *req_ca_rdn, int nreqs,
|
|
|
12bf12 |
const gnutls_pk_algorithm_t *sign_algos,
|
|
|
12bf12 |
- int sign_algos_length, gnutls_retr_st *st)
|
|
|
12bf12 |
+ int sign_algos_length,
|
|
|
12bf12 |
+#ifdef HAVE_GNUTLS_CERTIFICATE_SET_RETRIEVE_FUNCTION2
|
|
|
12bf12 |
+ gnutls_pcert_st **pcert,
|
|
|
12bf12 |
+ unsigned int *pcert_length,
|
|
|
12bf12 |
+ gnutls_privkey_t *pkey
|
|
|
12bf12 |
+#else
|
|
|
12bf12 |
+ gnutls_retr2_st *st
|
|
|
12bf12 |
+#endif
|
|
|
12bf12 |
+ )
|
|
|
12bf12 |
{
|
|
|
12bf12 |
ne_session *sess = gnutls_session_get_ptr(session);
|
|
|
12bf12 |
|
|
|
12bf12 |
@@ -612,27 +630,58 @@
|
|
|
12bf12 |
if (sess->client_cert) {
|
|
|
12bf12 |
gnutls_certificate_type_t type = gnutls_certificate_type_get(session);
|
|
|
12bf12 |
if (type == GNUTLS_CRT_X509
|
|
|
12bf12 |
-#if LIBGNUTLS_VERSION_NUMBER > 0x030000
|
|
|
12bf12 |
- /* Ugly hack; prevent segfaults w/GnuTLS 3.0. */
|
|
|
12bf12 |
- && sess->client_cert->pkey != NULL
|
|
|
12bf12 |
+ && (sess->client_cert->pkey || sess->client_cert->keyless)) {
|
|
|
12bf12 |
+ int ret;
|
|
|
12bf12 |
+
|
|
|
12bf12 |
+#ifdef HAVE_GNUTLS_CERTIFICATE_SET_RETRIEVE_FUNCTION2
|
|
|
12bf12 |
+ gnutls_privkey_init(pkey);
|
|
|
12bf12 |
+
|
|
|
12bf12 |
+#ifdef HAVE_GNUTLS_PRIVKEY_IMPORT_EXT
|
|
|
12bf12 |
+ if (sess->client_cert->sign_func) {
|
|
|
12bf12 |
+ int algo = gnutls_x509_crt_get_pk_algorithm(sess->client_cert->cert.subject, NULL);
|
|
|
12bf12 |
+ NE_DEBUG(NE_DBG_SSL, "ssl: Signing for %s.\n", gnutls_pk_algorithm_get_name(algo));
|
|
|
12bf12 |
+
|
|
|
12bf12 |
+ ret = gnutls_privkey_import_ext(*pkey, algo, sess->client_cert->sign_ud,
|
|
|
12bf12 |
+ sess->client_cert->sign_func, NULL, 0);
|
|
|
12bf12 |
+ }
|
|
|
12bf12 |
+ else
|
|
|
12bf12 |
#endif
|
|
|
12bf12 |
- ) {
|
|
|
12bf12 |
- NE_DEBUG(NE_DBG_SSL, "Supplying client certificate.\n");
|
|
|
12bf12 |
+ if (sess->client_cert->keyless) {
|
|
|
12bf12 |
+ ret = GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
|
|
|
12bf12 |
+ }
|
|
|
12bf12 |
+ else {
|
|
|
12bf12 |
+ ret = gnutls_privkey_import_x509(*pkey, sess->client_cert->pkey, 0);
|
|
|
12bf12 |
+ }
|
|
|
12bf12 |
|
|
|
12bf12 |
- st->type = type;
|
|
|
12bf12 |
+ if (ret) {
|
|
|
12bf12 |
+ NE_DEBUG(NE_DBG_SSL, "ssl: Failed to import private key: %s.\n", gnutls_strerror(ret));
|
|
|
12bf12 |
+ ne_set_error(sess, _("Failed to import private key: %s"), gnutls_strerror(ret));
|
|
|
12bf12 |
+ return ret;
|
|
|
12bf12 |
+ }
|
|
|
12bf12 |
+
|
|
|
12bf12 |
+ *pcert = gnutls_calloc(1, sizeof **pcert);
|
|
|
12bf12 |
+ gnutls_pcert_import_x509(*pcert, sess->client_cert->cert.subject, 0);
|
|
|
12bf12 |
+ *pcert_length = 1;
|
|
|
12bf12 |
+#else /* !HAVE_GNUTLS_CERTIFICATE_SET_RETRIEVE_FUNCTION2 */
|
|
|
12bf12 |
+ st->cert_type = type;
|
|
|
12bf12 |
st->ncerts = 1;
|
|
|
12bf12 |
st->cert.x509 = &sess->client_cert->cert.subject;
|
|
|
12bf12 |
st->key.x509 = sess->client_cert->pkey;
|
|
|
12bf12 |
|
|
|
12bf12 |
/* tell GNU TLS not to deallocate the certs. */
|
|
|
12bf12 |
st->deinit_all = 0;
|
|
|
12bf12 |
+#endif
|
|
|
12bf12 |
} else {
|
|
|
12bf12 |
return GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE;
|
|
|
12bf12 |
}
|
|
|
12bf12 |
}
|
|
|
12bf12 |
else {
|
|
|
12bf12 |
- NE_DEBUG(NE_DBG_SSL, "No client certificate supplied.\n");
|
|
|
12bf12 |
+ NE_DEBUG(NE_DBG_SSL, "ssl: No client certificate supplied.\n");
|
|
|
12bf12 |
+#ifdef HAVE_GNUTLS_CERTIFICATE_SET_RETRIEVE_FUNCTION2
|
|
|
12bf12 |
+ *pcert_length = 0;
|
|
|
12bf12 |
+#else
|
|
|
12bf12 |
st->ncerts = 0;
|
|
|
12bf12 |
+#endif
|
|
|
12bf12 |
sess->ssl_cc_requested = 1;
|
|
|
12bf12 |
return 0;
|
|
|
12bf12 |
}
|
|
|
12bf12 |
@@ -650,8 +699,12 @@
|
|
|
12bf12 |
ne_ssl_context *ctx = ne_calloc(sizeof *ctx);
|
|
|
12bf12 |
gnutls_certificate_allocate_credentials(&ctx->cred);
|
|
|
12bf12 |
if (flags == NE_SSL_CTX_CLIENT) {
|
|
|
12bf12 |
+#ifdef HAVE_GNUTLS_CERTIFICATE_SET_RETRIEVE_FUNCTION2
|
|
|
12bf12 |
+ gnutls_certificate_set_retrieve_function2(ctx->cred, provide_client_cert);
|
|
|
12bf12 |
+#else
|
|
|
12bf12 |
gnutls_certificate_client_set_retrieve_function(ctx->cred,
|
|
|
12bf12 |
provide_client_cert);
|
|
|
12bf12 |
+#endif
|
|
|
12bf12 |
}
|
|
|
12bf12 |
gnutls_certificate_set_verify_flags(ctx->cred,
|
|
|
12bf12 |
GNUTLS_VERIFY_ALLOW_X509_V1_CA_CRT);
|
|
|
12bf12 |
@@ -694,7 +747,11 @@
|
|
|
12bf12 |
{
|
|
|
12bf12 |
gnutls_certificate_free_credentials(ctx->cred);
|
|
|
12bf12 |
if (ctx->cache.client.data) {
|
|
|
12bf12 |
+#if defined(HAVE_GNUTLS_SESSION_GET_DATA2)
|
|
|
12bf12 |
+ gnutls_free(ctx->cache.client.data);
|
|
|
12bf12 |
+#else
|
|
|
12bf12 |
ne_free(ctx->cache.client.data);
|
|
|
12bf12 |
+#endif
|
|
|
12bf12 |
} else if (ctx->cache.server.key.data) {
|
|
|
12bf12 |
gnutls_free(ctx->cache.server.key.data);
|
|
|
12bf12 |
gnutls_free(ctx->cache.server.data.data);
|
|
|
12bf12 |
@@ -1164,7 +1221,9 @@
|
|
|
12bf12 |
gnutls_x509_crt_t cert = NULL;
|
|
|
12bf12 |
gnutls_x509_privkey_t pkey = NULL;
|
|
|
12bf12 |
|
|
|
12bf12 |
- data.data = buffer;
|
|
|
12bf12 |
+ /* The datum structure is not modified by gnutls_pkcs12_import,
|
|
|
12bf12 |
+ * cast safely: */
|
|
|
12bf12 |
+ data.data = (unsigned char *)buffer;
|
|
|
12bf12 |
data.size = buflen;
|
|
|
12bf12 |
|
|
|
12bf12 |
if (gnutls_pkcs12_init(&p12) != 0) {
|
|
|
12bf12 |
@@ -1201,8 +1260,10 @@
|
|
|
12bf12 |
}
|
|
|
12bf12 |
}
|
|
|
12bf12 |
|
|
|
12bf12 |
-ne_ssl_client_cert *ne__ssl_clicert_exkey_import(const unsigned char *der,
|
|
|
12bf12 |
- size_t der_len)
|
|
|
12bf12 |
+#ifdef HAVE_GNUTLS_PRIVKEY_IMPORT_EXT
|
|
|
12bf12 |
+ne_ssl_client_cert *ne__ssl_clicert_exkey_import(const unsigned char *der, size_t der_len,
|
|
|
12bf12 |
+ gnutls_privkey_sign_func sign_func,
|
|
|
12bf12 |
+ void *userdata)
|
|
|
12bf12 |
{
|
|
|
12bf12 |
ne_ssl_client_cert *cc;
|
|
|
12bf12 |
gnutls_x509_crt_t x5;
|
|
|
12bf12 |
@@ -1221,9 +1282,12 @@
|
|
|
12bf12 |
cc->keyless = 1;
|
|
|
12bf12 |
cc->decrypted = 1;
|
|
|
12bf12 |
populate_cert(&cc->cert, x5);
|
|
|
12bf12 |
+ cc->sign_func = sign_func;
|
|
|
12bf12 |
+ cc->sign_ud = userdata;
|
|
|
12bf12 |
|
|
|
12bf12 |
- return cc;
|
|
|
12bf12 |
+ return cc;
|
|
|
12bf12 |
}
|
|
|
12bf12 |
+#endif
|
|
|
12bf12 |
|
|
|
12bf12 |
int ne_ssl_clicert_encrypted(const ne_ssl_client_cert *cc)
|
|
|
12bf12 |
{
|
|
|
12bf12 |
--- neon-0.30.0/src/ne_pkcs11.c.pkcs11
|
|
|
12bf12 |
+++ neon-0.30.0/src/ne_pkcs11.c
|
|
|
12bf12 |
@@ -160,6 +160,13 @@
|
|
|
12bf12 |
}
|
|
|
12bf12 |
#endif
|
|
|
12bf12 |
|
|
|
12bf12 |
+#ifdef HAVE_GNUTLS
|
|
|
12bf12 |
+static int pk11_sign_callback(gnutls_privkey_t pkey,
|
|
|
12bf12 |
+ void *userdata,
|
|
|
12bf12 |
+ const gnutls_datum_t *raw_data,
|
|
|
12bf12 |
+ gnutls_datum_t *signature);
|
|
|
12bf12 |
+#endif
|
|
|
12bf12 |
+
|
|
|
12bf12 |
static int pk11_find_x509(ne_ssl_pkcs11_provider *prov,
|
|
|
12bf12 |
pakchois_session_t *pks,
|
|
|
12bf12 |
unsigned char *certid, unsigned long *cid_len)
|
|
|
12bf12 |
@@ -207,9 +214,9 @@
|
|
|
12bf12 |
ne_ssl_client_cert *cc;
|
|
|
12bf12 |
|
|
|
12bf12 |
#ifdef HAVE_GNUTLS
|
|
|
12bf12 |
- cc = ne__ssl_clicert_exkey_import(value, a[0].value_len);
|
|
|
12bf12 |
+ cc = ne__ssl_clicert_exkey_import(value, a[0].value_len, pk11_sign_callback, prov);
|
|
|
12bf12 |
#else
|
|
|
12bf12 |
- cc = ne__ssl_clicert_exkey_import(value, a[0].value_len, pk11_rsa_method(prov));
|
|
|
12bf12 |
+ cc = ne__ssl_clicert_exkey_import(value, a[0].value_len, prov->method);
|
|
|
12bf12 |
#endif
|
|
|
12bf12 |
if (cc) {
|
|
|
12bf12 |
NE_DEBUG(NE_DBG_SSL, "pk11: Imported X.509 cert.\n");
|
|
|
12bf12 |
@@ -302,10 +309,8 @@
|
|
|
12bf12 |
#ifdef HAVE_GNUTLS
|
|
|
12bf12 |
/* Callback invoked by GnuTLS to provide the signature. The signature
|
|
|
12bf12 |
* operation is handled here by the PKCS#11 provider. */
|
|
|
12bf12 |
-static int pk11_sign_callback(gnutls_session_t session,
|
|
|
12bf12 |
+static int pk11_sign_callback(gnutls_privkey_t pkey,
|
|
|
12bf12 |
void *userdata,
|
|
|
12bf12 |
- gnutls_certificate_type_t cert_type,
|
|
|
12bf12 |
- const gnutls_datum_t *cert,
|
|
|
12bf12 |
const gnutls_datum_t *hash,
|
|
|
12bf12 |
gnutls_datum_t *signature)
|
|
|
12bf12 |
{
|
|
|
12bf12 |
@@ -575,11 +580,6 @@
|
|
|
12bf12 |
void ne_ssl_set_pkcs11_provider(ne_session *sess,
|
|
|
12bf12 |
ne_ssl_pkcs11_provider *provider)
|
|
|
12bf12 |
{
|
|
|
12bf12 |
-#ifdef HAVE_GNUTLS
|
|
|
12bf12 |
- sess->ssl_context->sign_func = pk11_sign_callback;
|
|
|
12bf12 |
- sess->ssl_context->sign_data = provider;
|
|
|
12bf12 |
-#endif
|
|
|
12bf12 |
-
|
|
|
12bf12 |
ne_ssl_provide_clicert(sess, pk11_provide, provider);
|
|
|
12bf12 |
}
|
|
|
12bf12 |
|
|
|
12bf12 |
--- neon-0.30.0/src/ne_privssl.h.pkcs11
|
|
|
12bf12 |
+++ neon-0.30.0/src/ne_privssl.h
|
|
|
12bf12 |
@@ -58,6 +58,10 @@
|
|
|
12bf12 |
|
|
|
12bf12 |
#include <gnutls/gnutls.h>
|
|
|
12bf12 |
|
|
|
12bf12 |
+#ifdef HAVE_GNUTLS_PRIVKEY_IMPORT_EXT
|
|
|
12bf12 |
+#include <gnutls/abstract.h>
|
|
|
12bf12 |
+#endif
|
|
|
12bf12 |
+
|
|
|
12bf12 |
struct ne_ssl_context_s {
|
|
|
12bf12 |
gnutls_certificate_credentials_t cred;
|
|
|
12bf12 |
int verify; /* non-zero if client cert verification required */
|
|
|
12bf12 |
@@ -78,17 +82,13 @@
|
|
|
12bf12 |
} client;
|
|
|
12bf12 |
#endif
|
|
|
12bf12 |
} cache;
|
|
|
12bf12 |
-
|
|
|
12bf12 |
-#ifdef HAVE_GNUTLS_SIGN_CALLBACK_SET
|
|
|
12bf12 |
- gnutls_sign_func sign_func;
|
|
|
12bf12 |
- void *sign_data;
|
|
|
12bf12 |
-#endif
|
|
|
12bf12 |
};
|
|
|
12bf12 |
|
|
|
12bf12 |
typedef gnutls_session_t ne_ssl_socket;
|
|
|
12bf12 |
|
|
|
12bf12 |
NE_PRIVATE ne_ssl_client_cert *
|
|
|
12bf12 |
-ne__ssl_clicert_exkey_import(const unsigned char *der, size_t der_len);
|
|
|
12bf12 |
+ne__ssl_clicert_exkey_import(const unsigned char *der, size_t der_len,
|
|
|
12bf12 |
+ gnutls_privkey_sign_func sign_func, void *userdata);
|
|
|
12bf12 |
|
|
|
12bf12 |
#endif /* HAVE_GNUTLS */
|
|
|
12bf12 |
|