|
|
6cf099 |
From cbbdb6250744154bf9b5d0718ec68f2b63dfaff0 Mon Sep 17 00:00:00 2001
|
|
|
6cf099 |
From: Sumit Bose <sbose@redhat.com>
|
|
|
6cf099 |
Date: Mon, 22 Jun 2015 16:36:36 +0200
|
|
|
6cf099 |
Subject: [PATCH 30/37] utils: add NSS version of cert utils
|
|
|
6cf099 |
|
|
|
6cf099 |
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
|
|
|
6cf099 |
---
|
|
|
6cf099 |
Makefile.am | 29 ++++-
|
|
|
6cf099 |
configure.ac | 4 +-
|
|
|
6cf099 |
contrib/sssd.spec.in | 1 -
|
|
|
6cf099 |
src/tests/cmocka/test_cert_utils.c | 4 +
|
|
|
6cf099 |
src/util/cert/nss/cert.c | 212 +++++++++++++++++++++++++++++++++++++
|
|
|
6cf099 |
5 files changed, 244 insertions(+), 6 deletions(-)
|
|
|
6cf099 |
create mode 100644 src/util/cert/nss/cert.c
|
|
|
6cf099 |
|
|
|
6cf099 |
diff --git a/Makefile.am b/Makefile.am
|
|
|
6cf099 |
index 912bfc6641465ef5cd2ff2cce9975b4027c3218d..277166ec66b3d67101e628990e68704c886b0c59 100644
|
|
|
6cf099 |
--- a/Makefile.am
|
|
|
6cf099 |
+++ b/Makefile.am
|
|
|
6cf099 |
@@ -709,6 +709,17 @@ if HAVE_NSS
|
|
|
6cf099 |
src/util/crypto/nss/nss_util.c
|
|
|
6cf099 |
SSS_CRYPT_CFLAGS = $(NSS_CFLAGS)
|
|
|
6cf099 |
SSS_CRYPT_LIBS = $(NSS_LIBS)
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ SSS_CERT_SOURCES = \
|
|
|
6cf099 |
+ src/util/cert/cert_common.c \
|
|
|
6cf099 |
+ src/util/cert/nss/cert.c \
|
|
|
6cf099 |
+ $(NULL)
|
|
|
6cf099 |
+ SSS_CERT_CFLAGS = \
|
|
|
6cf099 |
+ $(NSS_CFLAGS) \
|
|
|
6cf099 |
+ $(NULL)
|
|
|
6cf099 |
+ SSS_CERT_LIBS = \
|
|
|
6cf099 |
+ $(NSS_LIBS) \
|
|
|
6cf099 |
+ $(NULL)
|
|
|
6cf099 |
else
|
|
|
6cf099 |
SSS_CRYPT_SOURCES = src/util/crypto/libcrypto/crypto_base64.c \
|
|
|
6cf099 |
src/util/crypto/libcrypto/crypto_hmac_sha1.c \
|
|
|
6cf099 |
@@ -716,6 +727,17 @@ else
|
|
|
6cf099 |
src/util/crypto/libcrypto/crypto_obfuscate.c
|
|
|
6cf099 |
SSS_CRYPT_CFLAGS = $(CRYPTO_CFLAGS)
|
|
|
6cf099 |
SSS_CRYPT_LIBS = $(CRYPTO_LIBS)
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ SSS_CERT_SOURCES = \
|
|
|
6cf099 |
+ src/util/cert/cert_common.c \
|
|
|
6cf099 |
+ src/util/cert/libcrypto/cert.c \
|
|
|
6cf099 |
+ $(NULL)
|
|
|
6cf099 |
+ SSS_CERT_CFLAGS = \
|
|
|
6cf099 |
+ $(CRYPTO_CFLAGS) \
|
|
|
6cf099 |
+ $(NULL)
|
|
|
6cf099 |
+ SSS_CERT_LIBS = \
|
|
|
6cf099 |
+ $(CRYPTO_LIBS) \
|
|
|
6cf099 |
+ $(NULL)
|
|
|
6cf099 |
endif
|
|
|
6cf099 |
|
|
|
6cf099 |
libsss_crypt_la_SOURCES = \
|
|
|
6cf099 |
@@ -735,14 +757,13 @@ libsss_crypt_la_LDFLAGS = \
|
|
|
6cf099 |
pkglib_LTLIBRARIES += libsss_cert.la
|
|
|
6cf099 |
|
|
|
6cf099 |
libsss_cert_la_SOURCES = \
|
|
|
6cf099 |
- src/util/cert/cert_common.c \
|
|
|
6cf099 |
- src/util/cert/libcrypto/cert.c \
|
|
|
6cf099 |
+ $(SSS_CERT_SOURCES) \
|
|
|
6cf099 |
$(NULL)
|
|
|
6cf099 |
libsss_cert_la_CFLAGS = \
|
|
|
6cf099 |
- $(CRYPTO_CFLAGS) \
|
|
|
6cf099 |
+ $(SSS_CERT_CFLAGS) \
|
|
|
6cf099 |
$(NULL)
|
|
|
6cf099 |
libsss_cert_la_LIBADD = \
|
|
|
6cf099 |
- $(CRYPTO_LIBS) \
|
|
|
6cf099 |
+ $(SSS_CERT_LIBS) \
|
|
|
6cf099 |
$(TALLOC_LIBS) \
|
|
|
6cf099 |
libsss_crypt.la \
|
|
|
6cf099 |
libsss_debug.la \
|
|
|
6cf099 |
diff --git a/configure.ac b/configure.ac
|
|
|
6cf099 |
index 29bedf74db6594b5788d51570514a07e082d5e42..4b4f8f3228bf13c594c86e1e39474a1d02ffd984 100644
|
|
|
6cf099 |
--- a/configure.ac
|
|
|
6cf099 |
+++ b/configure.ac
|
|
|
6cf099 |
@@ -341,7 +341,9 @@ if test x$cryptolib = xnss; then
|
|
|
6cf099 |
AM_CHECK_NSS
|
|
|
6cf099 |
fi
|
|
|
6cf099 |
|
|
|
6cf099 |
-AM_CHECK_LIBCRYPTO
|
|
|
6cf099 |
+if test x$cryptolib = xlibcrypto; then
|
|
|
6cf099 |
+ AM_CHECK_LIBCRYPTO
|
|
|
6cf099 |
+fi
|
|
|
6cf099 |
|
|
|
6cf099 |
AM_CHECK_INOTIFY
|
|
|
6cf099 |
|
|
|
6cf099 |
diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in
|
|
|
6cf099 |
index f050501ff9d0711a0da7f094ee968cae87a3f49b..54260e32e24ece372ed7130ab29d766bb1923f77 100644
|
|
|
6cf099 |
--- a/contrib/sssd.spec.in
|
|
|
6cf099 |
+++ b/contrib/sssd.spec.in
|
|
|
6cf099 |
@@ -106,7 +106,6 @@ BuildRequires: dbus-libs
|
|
|
6cf099 |
BuildRequires: openldap-devel
|
|
|
6cf099 |
BuildRequires: pam-devel
|
|
|
6cf099 |
BuildRequires: nss-devel
|
|
|
6cf099 |
-BuildRequires: openssl-devel
|
|
|
6cf099 |
BuildRequires: nspr-devel
|
|
|
6cf099 |
BuildRequires: pcre-devel
|
|
|
6cf099 |
BuildRequires: libxslt
|
|
|
6cf099 |
diff --git a/src/tests/cmocka/test_cert_utils.c b/src/tests/cmocka/test_cert_utils.c
|
|
|
6cf099 |
index 5bcbafb27dbdff596c07b8aad10ca15a35ff4ef5..8063b1a65e8692142cbb3cf82fe41afa6567bc91 100644
|
|
|
6cf099 |
--- a/src/tests/cmocka/test_cert_utils.c
|
|
|
6cf099 |
+++ b/src/tests/cmocka/test_cert_utils.c
|
|
|
6cf099 |
@@ -23,7 +23,9 @@
|
|
|
6cf099 |
*/
|
|
|
6cf099 |
|
|
|
6cf099 |
#include <popt.h>
|
|
|
6cf099 |
+#ifdef HAVE_LIBCRYPTO
|
|
|
6cf099 |
#include <openssl/objects.h>
|
|
|
6cf099 |
+#endif
|
|
|
6cf099 |
|
|
|
6cf099 |
#include "util/cert.h"
|
|
|
6cf099 |
#include "tests/cmocka/common_mock.h"
|
|
|
6cf099 |
@@ -349,7 +351,9 @@ int main(int argc, const char *argv[])
|
|
|
6cf099 |
|
|
|
6cf099 |
ret = cmocka_run_group_tests(tests, NULL, NULL);
|
|
|
6cf099 |
|
|
|
6cf099 |
+#ifdef HAVE_LIBCRYPTO
|
|
|
6cf099 |
CRYPTO_cleanup_all_ex_data(); /* to make valgrind happy */
|
|
|
6cf099 |
+#endif
|
|
|
6cf099 |
|
|
|
6cf099 |
#ifdef HAVE_NSS
|
|
|
6cf099 |
/* Cleanup NSS and NSPR to make valgrind happy. */
|
|
|
6cf099 |
diff --git a/src/util/cert/nss/cert.c b/src/util/cert/nss/cert.c
|
|
|
6cf099 |
new file mode 100644
|
|
|
6cf099 |
index 0000000000000000000000000000000000000000..a20abf63a10de9a5e9810f1c7d56686d063d60c7
|
|
|
6cf099 |
--- /dev/null
|
|
|
6cf099 |
+++ b/src/util/cert/nss/cert.c
|
|
|
6cf099 |
@@ -0,0 +1,212 @@
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+/*
|
|
|
6cf099 |
+ SSSD - certificate handling utils - NSS version
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ Copyright (C) Sumit Bose <sbose@redhat.com> 2015
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ This program is free software; you can redistribute it and/or modify
|
|
|
6cf099 |
+ it under the terms of the GNU General Public License as published by
|
|
|
6cf099 |
+ the Free Software Foundation; either version 3 of the License, or
|
|
|
6cf099 |
+ (at your option) any later version.
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ This program is distributed in the hope that it will be useful,
|
|
|
6cf099 |
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
6cf099 |
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
6cf099 |
+ GNU General Public License for more details.
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ You should have received a copy of the GNU General Public License
|
|
|
6cf099 |
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
6cf099 |
+*/
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+#include "util/util.h"
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+#include <cert.h>
|
|
|
6cf099 |
+#include <base64.h>
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+#include "util/crypto/nss/nss_util.h"
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+#define NS_CERT_HEADER "-----BEGIN CERTIFICATE-----"
|
|
|
6cf099 |
+#define NS_CERT_TRAILER "-----END CERTIFICATE-----"
|
|
|
6cf099 |
+#define NS_CERT_HEADER_LEN ((sizeof NS_CERT_HEADER) - 1)
|
|
|
6cf099 |
+#define NS_CERT_TRAILER_LEN ((sizeof NS_CERT_TRAILER) - 1)
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+errno_t sss_cert_der_to_pem(TALLOC_CTX *mem_ctx, const uint8_t *der_blob,
|
|
|
6cf099 |
+ size_t der_size, char **pem, size_t *pem_size)
|
|
|
6cf099 |
+{
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ CERTCertDBHandle *handle;
|
|
|
6cf099 |
+ CERTCertificate *cert = NULL;
|
|
|
6cf099 |
+ SECItem der_item;
|
|
|
6cf099 |
+ char *ascii_crlf = NULL;
|
|
|
6cf099 |
+ size_t ascii_crlf_len;
|
|
|
6cf099 |
+ char *ascii_lf = NULL;
|
|
|
6cf099 |
+ char *pem_cert_str = NULL;
|
|
|
6cf099 |
+ int ret;
|
|
|
6cf099 |
+ size_t c;
|
|
|
6cf099 |
+ size_t d;
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ /* initialize NSS if needed */
|
|
|
6cf099 |
+ ret = nspr_nss_init();
|
|
|
6cf099 |
+ if (ret != EOK) {
|
|
|
6cf099 |
+ DEBUG(SSSDBG_OP_FAILURE, "nspr_nss_init failed.\n");
|
|
|
6cf099 |
+ return ret;
|
|
|
6cf099 |
+ }
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ handle = CERT_GetDefaultCertDB();
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ der_item.len = der_size;
|
|
|
6cf099 |
+ der_item.data = discard_const(der_blob);
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ cert = CERT_NewTempCertificate(handle, &der_item, NULL, PR_FALSE, PR_TRUE);
|
|
|
6cf099 |
+ if (cert == NULL) {
|
|
|
6cf099 |
+ DEBUG(SSSDBG_OP_FAILURE, "CERT_NewTempCertificate failed.\n");
|
|
|
6cf099 |
+ return EINVAL;
|
|
|
6cf099 |
+ }
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ ascii_crlf = BTOA_DataToAscii(cert->derCert.data, cert->derCert.len);
|
|
|
6cf099 |
+ if (ascii_crlf == NULL) {
|
|
|
6cf099 |
+ DEBUG(SSSDBG_OP_FAILURE, "BTOA_DataToAscii failed.\n");
|
|
|
6cf099 |
+ ret = EIO;
|
|
|
6cf099 |
+ goto done;
|
|
|
6cf099 |
+ }
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ ascii_crlf_len = strlen(ascii_crlf) + 1;
|
|
|
6cf099 |
+ ascii_lf = talloc_size(mem_ctx, ascii_crlf_len * sizeof(char));
|
|
|
6cf099 |
+ if (ascii_lf == NULL) {
|
|
|
6cf099 |
+ DEBUG(SSSDBG_OP_FAILURE, "malloc failed.\n");
|
|
|
6cf099 |
+ ret = ENOMEM;
|
|
|
6cf099 |
+ goto done;
|
|
|
6cf099 |
+ }
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ d = 0;
|
|
|
6cf099 |
+ for (c = 0; c < ascii_crlf_len; c++) {
|
|
|
6cf099 |
+ if (ascii_crlf[c] != '\r') {
|
|
|
6cf099 |
+ ascii_lf[d++] = ascii_crlf[c];
|
|
|
6cf099 |
+ }
|
|
|
6cf099 |
+ }
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ pem_cert_str = talloc_asprintf(mem_ctx, "%s\n%s\n%s\n", NS_CERT_HEADER,
|
|
|
6cf099 |
+ ascii_lf,
|
|
|
6cf099 |
+ NS_CERT_TRAILER);
|
|
|
6cf099 |
+ if (pem_cert_str == NULL) {
|
|
|
6cf099 |
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_asprintf failed.\n");
|
|
|
6cf099 |
+ ret = ENOMEM;
|
|
|
6cf099 |
+ goto done;
|
|
|
6cf099 |
+ }
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ if (pem_size != NULL) {
|
|
|
6cf099 |
+ *pem_size = strlen(pem_cert_str);
|
|
|
6cf099 |
+ }
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ if (pem != NULL) {
|
|
|
6cf099 |
+ *pem = pem_cert_str;
|
|
|
6cf099 |
+ pem_cert_str = NULL;
|
|
|
6cf099 |
+ }
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ ret = EOK;
|
|
|
6cf099 |
+done:
|
|
|
6cf099 |
+ talloc_free(pem_cert_str);
|
|
|
6cf099 |
+ talloc_free(ascii_lf);
|
|
|
6cf099 |
+ PORT_Free(ascii_crlf);
|
|
|
6cf099 |
+ CERT_DestroyCertificate(cert);
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ return ret;
|
|
|
6cf099 |
+}
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+errno_t sss_cert_pem_to_der(TALLOC_CTX *mem_ctx, const char *pem,
|
|
|
6cf099 |
+ uint8_t **_der_blob, size_t *_der_size)
|
|
|
6cf099 |
+{
|
|
|
6cf099 |
+ const char *ps;
|
|
|
6cf099 |
+ const char *pe;
|
|
|
6cf099 |
+ size_t pem_len;
|
|
|
6cf099 |
+ uint8_t *der_blob = NULL;
|
|
|
6cf099 |
+ unsigned int der_size; /* unsigned int to match 2nd parameter of
|
|
|
6cf099 |
+ ATOB_AsciiToData */
|
|
|
6cf099 |
+ CERTCertDBHandle *handle;
|
|
|
6cf099 |
+ CERTCertificate *cert = NULL;
|
|
|
6cf099 |
+ SECItem der_item;
|
|
|
6cf099 |
+ int ret;
|
|
|
6cf099 |
+ char *b64 = NULL;
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ /* initialize NSS if needed */
|
|
|
6cf099 |
+ ret = nspr_nss_init();
|
|
|
6cf099 |
+ if (ret != EOK) {
|
|
|
6cf099 |
+ DEBUG(SSSDBG_OP_FAILURE, "nspr_nss_init failed.\n");
|
|
|
6cf099 |
+ return ret;
|
|
|
6cf099 |
+ }
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ if (pem == NULL || *pem == '\0') {
|
|
|
6cf099 |
+ return EINVAL;
|
|
|
6cf099 |
+ }
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ pem_len = strlen(pem);
|
|
|
6cf099 |
+ if (pem_len <= NS_CERT_HEADER_LEN + NS_CERT_TRAILER_LEN) {
|
|
|
6cf099 |
+ DEBUG(SSSDBG_CRIT_FAILURE, "PEM data too short.\n");
|
|
|
6cf099 |
+ return EINVAL;
|
|
|
6cf099 |
+ }
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ if (strncmp(pem, NS_CERT_HEADER, NS_CERT_HEADER_LEN) != 0) {
|
|
|
6cf099 |
+ DEBUG(SSSDBG_CRIT_FAILURE, "Wrong PEM header.\n");
|
|
|
6cf099 |
+ return EINVAL;
|
|
|
6cf099 |
+ }
|
|
|
6cf099 |
+ if (pem[NS_CERT_HEADER_LEN] != '\n') {
|
|
|
6cf099 |
+ DEBUG(SSSDBG_CRIT_FAILURE, "Missing newline in PEM data.\n");
|
|
|
6cf099 |
+ return EINVAL;
|
|
|
6cf099 |
+ }
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ pe = pem + pem_len - NS_CERT_TRAILER_LEN;
|
|
|
6cf099 |
+ if (pem[pem_len - 1] == '\n') {
|
|
|
6cf099 |
+ pe--;
|
|
|
6cf099 |
+ }
|
|
|
6cf099 |
+ if (strncmp(pe, NS_CERT_TRAILER, NS_CERT_TRAILER_LEN) != 0) {
|
|
|
6cf099 |
+ DEBUG(SSSDBG_CRIT_FAILURE, "Wrong PEM trailer.\n");
|
|
|
6cf099 |
+ return EINVAL;
|
|
|
6cf099 |
+ }
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ ps = pem + NS_CERT_HEADER_LEN + 1;
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ b64 = talloc_strndup(mem_ctx, ps, pe - ps);
|
|
|
6cf099 |
+ if(b64 == NULL) {
|
|
|
6cf099 |
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_strndup failed.\n");
|
|
|
6cf099 |
+ ret = ENOMEM;
|
|
|
6cf099 |
+ goto done;
|
|
|
6cf099 |
+ }
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ der_blob = ATOB_AsciiToData(b64, &der_size);
|
|
|
6cf099 |
+ if (der_blob == NULL) {
|
|
|
6cf099 |
+ DEBUG(SSSDBG_OP_FAILURE, "ATOB_AsciiToData failed.\n");
|
|
|
6cf099 |
+ return EIO;
|
|
|
6cf099 |
+ }
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ handle = CERT_GetDefaultCertDB();
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ der_item.len = der_size;
|
|
|
6cf099 |
+ der_item.data = der_blob;
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ cert = CERT_NewTempCertificate(handle, &der_item, NULL, PR_FALSE, PR_TRUE);
|
|
|
6cf099 |
+ if (cert == NULL) {
|
|
|
6cf099 |
+ DEBUG(SSSDBG_OP_FAILURE, "CERT_NewTempCertificate failed.\n");
|
|
|
6cf099 |
+ ret = EINVAL;
|
|
|
6cf099 |
+ goto done;
|
|
|
6cf099 |
+ }
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ if (_der_blob != NULL) {
|
|
|
6cf099 |
+ *_der_blob = talloc_memdup(mem_ctx, cert->derCert.data,
|
|
|
6cf099 |
+ cert->derCert.len);
|
|
|
6cf099 |
+ if (*_der_blob == NULL) {
|
|
|
6cf099 |
+ DEBUG(SSSDBG_OP_FAILURE, "talloc_memdup failed.\n");
|
|
|
6cf099 |
+ ret = ENOMEM;
|
|
|
6cf099 |
+ goto done;
|
|
|
6cf099 |
+ }
|
|
|
6cf099 |
+ }
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ if (_der_size != NULL) {
|
|
|
6cf099 |
+ *_der_size = cert->derCert.len;
|
|
|
6cf099 |
+ }
|
|
|
6cf099 |
+done:
|
|
|
6cf099 |
+ PORT_Free(der_blob);
|
|
|
6cf099 |
+ talloc_free(b64);
|
|
|
6cf099 |
+ CERT_DestroyCertificate(cert);
|
|
|
6cf099 |
+
|
|
|
6cf099 |
+ return ret;
|
|
|
6cf099 |
+}
|
|
|
6cf099 |
--
|
|
|
6cf099 |
2.4.3
|
|
|
6cf099 |
|