diff --git a/src/conn.c b/src/conn.c index 645884c..95b7eb9 100644 --- a/src/conn.c +++ b/src/conn.c @@ -573,11 +573,12 @@ const char *xmpp_conn_get_keyfile(const xmpp_conn_t *conn) * \ref xmpp_conn_set_password_callback so the TLS stack can retrieve the * password. * - * In case one wants to use a PKCS#12 encoded file, it must be passed via - * the `key` parameter and `cert` must be NULL. + * In case one wants to use a PKCS#12 encoded file, it should be passed via + * the `cert` parameter and `key` should be NULL. Passing a PKCS#12 file in + * `key` is deprecated. * * @param conn a Strophe connection object - * @param cert path to a certificate file + * @param cert path to a certificate file or a P12 file * @param key path to a private key file or a P12 file * * @ingroup TLS @@ -589,13 +590,21 @@ void xmpp_conn_set_client_cert(xmpp_conn_t *const conn, strophe_debug(conn->ctx, "conn", "set client cert %s %s", cert, key); if (conn->tls_client_cert) strophe_free(conn->ctx, conn->tls_client_cert); - if (cert) - conn->tls_client_cert = strophe_strdup(conn->ctx, cert); - else - conn->tls_client_cert = NULL; + conn->tls_client_cert = NULL; if (conn->tls_client_key) strophe_free(conn->ctx, conn->tls_client_key); - conn->tls_client_key = strophe_strdup(conn->ctx, key); + conn->tls_client_key = NULL; + if (cert && key) { + conn->tls_client_cert = strophe_strdup(conn->ctx, cert); + conn->tls_client_key = strophe_strdup(conn->ctx, key); + } else if (cert && !key) { + conn->tls_client_cert = strophe_strdup(conn->ctx, cert); + } else if (!cert && key) { + strophe_warn(conn->ctx, "xmpp", + "xmpp_conn_set_client_cert: Passing PKCS#12 in 'key' " + "parameter is deprecated. Use 'cert' instead"); + conn->tls_client_cert = strophe_strdup(conn->ctx, key); + } } /** Get the number of xmppAddr entries in the client certificate. diff --git a/src/tls.c b/src/tls.c index a6e75a5..afb6a52 100644 --- a/src/tls.c +++ b/src/tls.c @@ -221,7 +221,7 @@ int tls_caching_password_callback(char *pw, size_t pw_max, xmpp_conn_t *conn) int ret; unsigned char hash[XMPP_SHA1_DIGEST_SIZE]; - const char *fname = conn->tls_client_key; + const char *fname = conn->tls_client_cert; size_t fname_len = strlen(fname); xmpp_sha1_digest((void *)fname, fname_len, hash); if (fname_len && fname_len == conn->password_cache.fnamelen && diff --git a/src/tls_gnutls.c b/src/tls_gnutls.c index 5b14ca6..bc6a08a 100644 --- a/src/tls_gnutls.c +++ b/src/tls_gnutls.c @@ -95,7 +95,7 @@ static gnutls_x509_crt_t _tls_load_cert_p12(xmpp_conn_t *conn) int err = -1; if (gnutls_pkcs12_init(&p12) < 0) return NULL; - if (gnutls_load_file(conn->tls_client_key, &data) < 0) + if (gnutls_load_file(conn->tls_client_cert, &data) < 0) goto error_out; if (gnutls_pkcs12_import(p12, &data, GNUTLS_X509_FMT_DER, 0) < 0) goto error_out2; @@ -168,7 +168,7 @@ static gnutls_x509_crt_t _tls_load_cert(xmpp_conn_t *conn) { if (conn->tls && conn->tls->client_cert) return conn->tls->client_cert; - if (!conn->tls_client_cert && conn->tls_client_key) { + if (conn->tls_client_cert && !conn->tls_client_key) { return _tls_load_cert_p12(conn); } return _tls_load_cert_x509(conn); @@ -459,7 +459,7 @@ tls_t *tls_new(xmpp_conn_t *conn) } strophe_debug(tls->ctx, "tls", "wrong password?"); } - } else if (conn->tls_client_key) { + } else if (conn->tls_client_cert) { unsigned int retries = 0; while (retries++ < conn->password_retries) { @@ -470,7 +470,8 @@ tls_t *tls_new(xmpp_conn_t *conn) if (passlen < 0) continue; int err = gnutls_certificate_set_x509_simple_pkcs12_file( - tls->cred, conn->tls_client_key, GNUTLS_X509_FMT_DER, pass); + tls->cred, conn->tls_client_cert, GNUTLS_X509_FMT_DER, + pass); memset(pass, 0, sizeof(pass)); if (err == 0) break; diff --git a/src/tls_openssl.c b/src/tls_openssl.c index 19deae9..28e36be 100644 --- a/src/tls_openssl.c +++ b/src/tls_openssl.c @@ -616,7 +616,7 @@ tls_t *tls_new(xmpp_conn_t *conn) ERR_GET_LIB(err), ERR_GET_REASON(err)); goto err_free_ctx; } - } else if (conn->tls_client_key) { + } else if (conn->tls_client_cert) { EVP_PKEY *pkey = NULL; STACK_OF(X509) *ca = NULL; X509 *cert = _tls_cert_read_p12(conn, &pkey, &ca); @@ -974,7 +974,7 @@ _tls_cert_read_p12(xmpp_conn_t *conn, EVP_PKEY **pkey, STACK_OF(X509) * *ca) return conn->tls->client_cert; X509 *cert = NULL; PKCS12 *p12 = NULL; - BIO *f = BIO_new_file(conn->tls_client_key, "rb"); + BIO *f = BIO_new_file(conn->tls_client_cert, "rb"); if (!f) { strophe_debug(conn->ctx, "tls", "f == NULL"); goto error_out; @@ -1034,7 +1034,7 @@ static X509 *_tls_cert_read(xmpp_conn_t *conn) { if (conn->tls && conn->tls->client_cert) return conn->tls->client_cert; - if (!conn->tls_client_cert && conn->tls_client_key) { + if (conn->tls_client_cert && !conn->tls_client_key) { return _tls_cert_read_p12(conn, NULL, NULL); } return _tls_cert_read_x509(conn); diff --git a/tests/test_xmppaddr.c b/tests/test_xmppaddr.c index e04e5d6..9f3ff3d 100644 --- a/tests/test_xmppaddr.c +++ b/tests/test_xmppaddr.c @@ -43,6 +43,9 @@ int main() {0, NULL, "tests/cert.emptypass.pfx"}, {0, NULL, "tests/cert.nopass.pfx"}, {1, NULL, "tests/cert.pfx"}, + {0, "tests/cert.emptypass.pfx", NULL}, + {0, "tests/cert.nopass.pfx", NULL}, + {1, "tests/cert.pfx", NULL}, }; const char *srcdir; @@ -68,7 +71,10 @@ int main() else certfile = NULL; - snprintf(keyfile, MAXPATHLEN, "%s/%s", srcdir, client_cert[m].key); + if (client_cert[m].key) + snprintf(keyfile, MAXPATHLEN, "%s/%s", srcdir, client_cert[m].key); + else + keyfile = NULL; if (client_cert[m].needs_callback) xmpp_conn_set_password_callback(conn, password_callback, NULL);