diff options
author | Sumit Bose <sbose@redhat.com> | 2017-02-14 22:47:08 +0100 |
---|---|---|
committer | Sumit Bose <sbose@redhat.com> | 2017-02-14 22:47:08 +0100 |
commit | 75d194e95637ee53be298a39aeb2fb79379e2367 (patch) | |
tree | 01608a3e1aeed30067f52b3efeb2e0548f7e6195 | |
parent | 20b1e6eba52caaea74eef0131ecf628f0760ae3d (diff) | |
download | sssd-75d194e95637ee53be298a39aeb2fb79379e2367.tar.gz sssd-75d194e95637ee53be298a39aeb2fb79379e2367.tar.xz sssd-75d194e95637ee53be298a39aeb2fb79379e2367.zip |
certmap openssl
-rw-r--r-- | Makefile.am | 44 | ||||
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | contrib/sssd.spec.in | 2 | ||||
-rw-r--r-- | src/lib/certmap/sss_cert_content_openssl.c | 278 | ||||
-rw-r--r-- | src/tests/dlopen-tests.c | 1 |
5 files changed, 326 insertions, 3 deletions
diff --git a/Makefile.am b/Makefile.am index 37aaf80af..39d5b2b70 100644 --- a/Makefile.am +++ b/Makefile.am @@ -276,6 +276,7 @@ if HAVE_CMOCKA simple-access-tests \ krb5_common_test \ sss_certmap_test \ + sss_certmap_openssl_test \ $(NULL) if HAVE_LIBRESOLV @@ -1050,6 +1051,7 @@ lib_LTLIBRARIES = libipa_hbac.la \ libsss_idmap.la \ libsss_nss_idmap.la \ libsss_certmap.la \ + libsss_certmap_openssl.la \ $(NULL) pkgconfig_DATA += src/lib/ipa_hbac/ipa_hbac.pc @@ -1697,6 +1699,28 @@ libsss_certmap_la_LDFLAGS = \ dist_noinst_DATA += src/lib/certmap/sss_certmap.exports dist_noinst_HEADERS += src/lib/certmap/sss_certmap_int.h endif +libsss_certmap_openssl_la_DEPENDENCIES = src/lib/certmap/sss_certmap.exports +libsss_certmap_openssl_la_SOURCES = \ + src/lib/certmap/sss_certmap.c \ + src/lib/certmap/sss_cert_content_openssl.c \ + src/util/util_ext.c \ + src/util/cert/cert_common.c \ + src/util/crypto/libcrypto/crypto_base64.c \ + src/util/cert/libcrypto/cert.c \ + $(NULL) +libsss_certmap_openssl_la_CFLAGS = \ + $(AM_CFLAGS) \ + $(TALLOC_CFLAGS) \ + $(CRYPTO_CFLAGS) \ + $(NULL) +libsss_certmap_openssl_la_LIBADD = \ + $(TALLOC_LIBS) \ + $(CRYPTO_LIBS) \ + $(NULL) +libsss_certmap_openssl_la_LDFLAGS = \ + -Wl,--version-script,$(srcdir)/src/lib/certmap/sss_certmap.exports \ + -version-info 0:0:0 + ################# # Feature Tests # @@ -3226,6 +3250,26 @@ sss_certmap_test_LDADD = \ libsss_certmap.la \ $(NULL) endif + +sss_certmap_openssl_test_SOURCES = \ + src/tests/cmocka/test_certmap.c \ + src/util/util.c \ + src/util/debug.c \ + src/util/sss_log.c \ + src/util/util_ext.c \ + $(NULL) +sss_certmap_openssl_test_CFLAGS = \ + $(AM_CFLAGS) \ + $(NULL) +sss_certmap_openssl_test_LDADD = \ + $(CMOCKA_LIBS) \ + $(POPT_LIBS) \ + $(TALLOC_LIBS) \ + $(DHASH_LIBS) \ + $(SYSTEMD_DAEMON_LIBS) \ + libsss_test_common.la \ + libsss_certmap_openssl.la \ + $(NULL) endif # HAVE_CMOCKA noinst_PROGRAMS = pam_test_client diff --git a/configure.ac b/configure.ac index e82c010b2..f40890f1f 100644 --- a/configure.ac +++ b/configure.ac @@ -365,9 +365,7 @@ if test x$cryptolib = xnss; then AM_CHECK_NSS fi -if test x$cryptolib = xlibcrypto; then - AM_CHECK_LIBCRYPTO -fi +AM_CHECK_LIBCRYPTO AM_CHECK_INOTIFY diff --git a/contrib/sssd.spec.in b/contrib/sssd.spec.in index bbb5eb5d6..920d09e76 100644 --- a/contrib/sssd.spec.in +++ b/contrib/sssd.spec.in @@ -1162,12 +1162,14 @@ done %defattr(-,root,root,-) %doc src/sss_client/COPYING src/sss_client/COPYING.LESSER %{_libdir}/libsss_certmap.so.* +%{_libdir}/libsss_certmap_openssl.so.* %files -n libsss_certmap-devel %defattr(-,root,root,-) %doc certmap_doc/html %{_includedir}/sss_certmap.h %{_libdir}/libsss_certmap.so +%{_libdir}/libsss_certmap_openssl.so %{_libdir}/pkgconfig/sss_certmap.pc %pre common diff --git a/src/lib/certmap/sss_cert_content_openssl.c b/src/lib/certmap/sss_cert_content_openssl.c new file mode 100644 index 000000000..590d79167 --- /dev/null +++ b/src/lib/certmap/sss_cert_content_openssl.c @@ -0,0 +1,278 @@ +/* + SSSD - certificate handling utils - OpenSSL version + The calls defined here should be useable outside of SSSD as well, e.g. in + libsss_certmap. + + Copyright (C) Sumit Bose <sbose@redhat.com> 2017 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "config.h" + +#include <talloc.h> +#include <openssl/x509v3.h> + +#include "util/crypto/sss_crypto.h" +#include "util/cert.h" +#include "lib/certmap/sss_certmap.h" +#include "lib/certmap/sss_certmap_int.h" + +static int get_extended_key_usage_oids(TALLOC_CTX *mem_ctx, + X509 *cert, + const char ***_oids) +{ + const char **oids_list = NULL; + size_t c; + int ret; + char oid_buf[128]; /* FIXME: any other size ?? */ + int len; + EXTENDED_KEY_USAGE *extusage = NULL; + + + extusage = X509_get_ext_d2i(cert, NID_ext_key_usage, NULL, NULL); + if (extusage == NULL) { + return EIO; + } + + oids_list = talloc_zero_array(mem_ctx, const char *, + sk_ASN1_OBJECT_num(extusage) + 1); + if (oids_list == NULL) { + return ENOMEM; + } + + for (c = 0; c < sk_ASN1_OBJECT_num(extusage); c++) { + len = OBJ_obj2txt(oid_buf, sizeof(oid_buf), + sk_ASN1_OBJECT_value(extusage, c) , 1); + if (len < 0) { + return EIO; + } + + oids_list[c] = talloc_strndup(oids_list, oid_buf, len); + if(oids_list[c] == NULL) { + ret = ENOMEM; + goto done; + } + } + + ret = 0; + +done: + sk_ASN1_OBJECT_pop_free(extusage, ASN1_OBJECT_free); + if (ret == 0) { + *_oids = oids_list; + } else { + talloc_free(oids_list); + } + + return ret; + +} + +static int get_rdn_list(TALLOC_CTX *mem_ctx, X509_NAME *name, + const char ***rdn_list) +{ + int ret; + size_t c; + const char **list = NULL; + X509_NAME_ENTRY *e; + ASN1_STRING *rdn_str; + ASN1_OBJECT *rdn_name; + BIO *bio_mem = NULL; + char *tmp_str; + long tmp_str_size; + + int nid; + const char *sn; + + bio_mem = BIO_new(BIO_s_mem()); + if (bio_mem == NULL) { + ret = ENOMEM; + goto done; + } + + list = talloc_zero_array(mem_ctx, const char *, + X509_NAME_entry_count(name) + 1); + if (list == NULL) { + ret = ENOMEM; + goto done; + } + + for (c = 0; c < X509_NAME_entry_count(name); c++) { + e = X509_NAME_get_entry(name, c); + rdn_str = X509_NAME_ENTRY_get_data(e); + + ret = ASN1_STRING_print_ex(bio_mem, rdn_str,ASN1_STRFLGS_RFC2253); + if (ret < 0) { + ret = EIO; + goto done; + } + + tmp_str_size = BIO_get_mem_data(bio_mem, &tmp_str); + if (tmp_str_size == 0) { + ret = EINVAL; + goto done; + } + + rdn_name = X509_NAME_ENTRY_get_object(e); + nid = OBJ_obj2nid(rdn_name); + sn = OBJ_nid2sn(nid); + + list[c] = talloc_asprintf(list, "%s=%.*s", sn, (int) tmp_str_size, + tmp_str); + BIO_reset(bio_mem); + if (list[c] == NULL) { + ret = ENOMEM; + goto done; + } + } + + ret = 0; + +done: + BIO_free_all(bio_mem); + if (ret == 0) { + *rdn_list = list; + } else { + talloc_free(list); + } + + return ret; +} + +int sss_cert_get_content(TALLOC_CTX *mem_ctx, + const uint8_t *der_blob, size_t der_size, + struct sss_cert_content **content) +{ + int ret; + struct sss_cert_content *cont = NULL; + X509 *cert = NULL; + const unsigned char *der; + BIO *bio_mem = NULL; + char *tmp_str; + long tmp_str_size; + X509_NAME *tmp_name; + + if (der_blob == NULL || der_size == 0) { + return EINVAL; + } + + cont = talloc_zero(mem_ctx, struct sss_cert_content); + if (cont == NULL) { + return ENOMEM; + } + + bio_mem = BIO_new(BIO_s_mem()); + if (bio_mem == NULL) { + ret = ENOMEM; + goto done; + } + + der = (const unsigned char *) der_blob; + cert = d2i_X509(NULL, &der, (int) der_size); + if (cert == NULL) { + ret = EINVAL; + goto done; + } + + tmp_name = X509_get_issuer_name(cert); + ret = X509_NAME_print_ex(bio_mem, tmp_name, 0, XN_FLAG_RFC2253); + if (ret < 0) { + ret = EIO; + goto done; + } + + tmp_str_size = BIO_get_mem_data(bio_mem, &tmp_str); + if (tmp_str_size == 0) { + ret = EINVAL; + goto done; + } + + cont->issuer_str = talloc_strndup(cont, tmp_str, tmp_str_size); + BIO_reset(bio_mem); + if (cont->issuer_str == NULL) { + ret = ENOMEM; + goto done; + } + + ret = get_rdn_list(cont, tmp_name, &cont->issuer_rdn_list); + if (ret != 0) { + goto done; + } + + tmp_name = X509_get_subject_name(cert); + ret = X509_NAME_print_ex(bio_mem, tmp_name, 0, XN_FLAG_RFC2253); + if (ret < 0) { + ret = EIO; + goto done; + } + + tmp_str_size = BIO_get_mem_data(bio_mem, &tmp_str); + if (tmp_str_size == 0) { + ret = EINVAL; + goto done; + } + + cont->subject_str = talloc_strndup(cont, tmp_str, tmp_str_size); + BIO_reset(bio_mem); + if (cont->subject_str == NULL) { + ret = ENOMEM; + goto done; + } + + ret = get_rdn_list(cont, tmp_name, &cont->subject_rdn_list); + if (ret != 0) { + goto done; + } + + ret = X509_check_purpose(cert, -1, -1); + if (ret < 0) { + ret = EIO; + goto done; + } + if (!(cert->ex_flags & EXFLAG_KUSAGE)) { + ret = EINVAL; + goto done; + } + cont->key_usage = cert->ex_kusage; + + ret = get_extended_key_usage_oids(cont, cert, + &(cont->extended_key_usage_oids)); + if (ret != 0) { + goto done; + } + + cont->cert_der = talloc_memdup(cont, der_blob, der_size); + if (cont->cert_der == NULL) { + ret = ENOMEM; + goto done; + } + + cont->cert_der_size = der_size; + + ret = EOK; + +done: + + X509_free(cert); + BIO_free_all(bio_mem); + + if (ret == EOK) { + *content = cont; + } else { + talloc_free(cont); + } + + return ret; +} diff --git a/src/tests/dlopen-tests.c b/src/tests/dlopen-tests.c index 89b4dae22..7efc2c084 100644 --- a/src/tests/dlopen-tests.c +++ b/src/tests/dlopen-tests.c @@ -46,6 +46,7 @@ struct so { { "libsss_nss_idmap.so", { LIBPFX"libsss_nss_idmap.so", NULL } }, { "libnss_sss.so", { LIBPFX"libnss_sss.so", NULL } }, { "libsss_certmap.so", { LIBPFX"libsss_certmap.so", NULL } }, + { "libsss_certmap_openssl.so", { LIBPFX"libsss_certmap_openssl.so", NULL } }, { "pam_sss.so", { LIBPFX"pam_sss.so", NULL } }, #ifdef BUILD_LIBWBCLIENT { "libwbclient.so", { LIBPFX"libwbclient.so", NULL } }, |