sssd/0104-certmap-add-OpenSSL-implementation.patch
Lukas Slebodnik 8eda442b2e Fix few bugs/regressions
Resolves: rhbz#1488327 - SELinux is preventing selinux_child from write access
                         on the sock_file system_bus_socket
Resolves: rhbz#1490402 - SSSD does not create /var/lib/sss/deskprofile and
                         fails to download desktop profile data
Resolves: upstream#3485 - getsidbyid does not work with 1.15.3
Resolves: upstream#3488 - SUDO doesn't work for IPA users on IPA clients after
                          applying ID Views for them in IPA server
Resolves: upstream#3501 - Accessing IdM kerberos ticket fails while id mapping
                          is applied
2017-09-12 09:22:07 +02:00

1683 lines
57 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From a20fb9cbd5f42a6ca895aea1b84347fdfea34b89 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Tue, 14 Feb 2017 22:47:08 +0100
Subject: [PATCH 104/115] certmap: add OpenSSL implementation
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
The OpenSSL 1.1 API is used but there is a short macro block which
should added the needed compatibility if and older OpenSSL version is
used.
Related to https://pagure.io/SSSD/sssd/issue/3050
Reviewed-by: Lukáš Slebodník <lslebodn@redhat.com>
---
Makefile.am | 7 +-
src/lib/certmap/sss_cert_content_common.c | 199 ++++++++
src/lib/certmap/sss_cert_content_crypto.c | 778 +++++++++++++++++++++++++++++-
src/lib/certmap/sss_cert_content_nss.c | 105 +---
src/lib/certmap/sss_certmap.c | 93 +---
src/lib/certmap/sss_certmap_attr_names.c | 81 ++--
src/lib/certmap/sss_certmap_int.h | 25 +-
src/tests/cmocka/test_certmap.c | 103 +++-
8 files changed, 1167 insertions(+), 224 deletions(-)
create mode 100644 src/lib/certmap/sss_cert_content_common.c
diff --git a/Makefile.am b/Makefile.am
index 273ecc72fba6793b4f46dbb11f6541e2e1bcc930..cb5c405a453cacbe5c2464ea09c0e6353253a789 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -288,11 +288,9 @@ if HAVE_CMOCKA
simple-access-tests \
krb5_common_test \
test_iobuf \
+ sss_certmap_test \
$(NULL)
-if HAVE_NSS
-non_interactive_cmocka_based_tests += sss_certmap_test
-endif #HAVE_NSS
if HAVE_LIBRESOLV
non_interactive_cmocka_based_tests += test_resolv_fake
@@ -1804,6 +1802,7 @@ libsss_certmap_la_SOURCES = \
src/lib/certmap/sss_certmap_attr_names.c \
src/lib/certmap/sss_certmap_krb5_match.c \
src/lib/certmap/sss_certmap_ldap_mapping.c \
+ src/lib/certmap/sss_cert_content_common.c \
src/util/util_ext.c \
src/util/cert/cert_common.c \
$(NULL)
@@ -3427,7 +3426,6 @@ test_inotify_LDADD = \
libsss_test_common.la \
$(NULL)
-if HAVE_NSS
sss_certmap_test_SOURCES = \
src/tests/cmocka/test_certmap.c \
src/lib/certmap/sss_certmap_attr_names.c \
@@ -3445,7 +3443,6 @@ sss_certmap_test_LDADD = \
libsss_test_common.la \
libsss_certmap.la \
$(NULL)
-endif
if BUILD_KCM
test_kcm_json_SOURCES = \
diff --git a/src/lib/certmap/sss_cert_content_common.c b/src/lib/certmap/sss_cert_content_common.c
new file mode 100644
index 0000000000000000000000000000000000000000..42919335221b6d1a188eebe24543668bb927f18a
--- /dev/null
+++ b/src/lib/certmap/sss_cert_content_common.c
@@ -0,0 +1,199 @@
+/*
+ SSSD - certificate handling utils
+ 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 <stdbool.h>
+#include <errno.h>
+#include <string.h>
+
+#include "lib/certmap/sss_certmap_int.h"
+
+int get_short_name(TALLOC_CTX *mem_ctx, const char *full_name,
+ char delim, char **short_name)
+{
+ char *at;
+ char *s;
+
+ if (full_name == NULL || delim == '\0' || short_name == NULL) {
+ return EINVAL;
+ }
+
+ at = strchr(full_name, delim);
+ if (at != NULL) {
+ s = talloc_strndup(mem_ctx, full_name, (at - full_name));
+ } else {
+ s = talloc_strdup(mem_ctx, full_name);
+ }
+ if (s == NULL) {
+ return ENOMEM;
+ }
+
+ *short_name = s;
+
+ return 0;
+}
+
+int add_to_san_list(TALLOC_CTX *mem_ctx, bool is_bin,
+ enum san_opt san_opt, const uint8_t *data, size_t len,
+ struct san_list **item)
+{
+ struct san_list *i;
+
+ if (data == NULL || len == 0 || san_opt == SAN_INVALID) {
+ return EINVAL;
+ }
+
+ i = talloc_zero(mem_ctx, struct san_list);
+ if (i == NULL) {
+ return ENOMEM;
+ }
+
+ i->san_opt = san_opt;
+ if (is_bin) {
+ i->bin_val = talloc_memdup(i, data, len);
+ i->bin_val_len = len;
+ } else {
+ i->val = talloc_strndup(i, (const char *) data, len);
+ }
+ if (i->val == NULL) {
+ talloc_free(i);
+ return ENOMEM;
+ }
+
+ *item = i;
+
+ return 0;
+}
+
+int add_principal_to_san_list(TALLOC_CTX *mem_ctx, enum san_opt san_opt,
+ const char *princ, struct san_list **item)
+{
+ struct san_list *i = NULL;
+ int ret;
+
+ i = talloc_zero(mem_ctx, struct san_list);
+ if (i == NULL) {
+ return ENOMEM;
+ }
+ i->san_opt = san_opt;
+
+ i->val = talloc_strdup(i, princ);
+ if (i->val == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = get_short_name(i, i->val, '@', &(i->short_name));
+ if (ret != 0) {
+ goto done;
+ }
+
+ ret = 0;
+
+done:
+ if (ret == 0) {
+ *item = i;
+ } else {
+ talloc_free(i);
+ }
+
+ return ret;
+}
+
+int rdn_list_2_dn_str(TALLOC_CTX *mem_ctx, const char *conversion,
+ const char **rdn_list, char **result)
+{
+ char *str = NULL;
+ size_t c;
+ int ret;
+ char *conv = NULL;
+
+ str = talloc_strdup(mem_ctx, "");
+ if (str == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ if (conversion == NULL || strcmp(conversion, "nss_ldap") == 0
+ || strcmp(conversion, "nss") == 0) {
+ for (c = 0; rdn_list[c] != NULL; c++);
+ while (c != 0) {
+ c--;
+ str = talloc_asprintf_append(str, "%s%s",
+ (rdn_list[c + 1] == NULL) ? "" : ",",
+ rdn_list[c]);
+ if (str == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ };
+ } else if (strcmp(conversion, "ad_ldap") == 0) {
+ for (c = 0; rdn_list[c] != NULL; c++);
+ while (c != 0) {
+ c--;
+ conv = check_ad_attr_name(str, rdn_list[c]);
+ str = talloc_asprintf_append(str, "%s%s",
+ (rdn_list[c + 1] == NULL) ? "" : ",",
+ conv == NULL ? rdn_list[c] : conv);
+ talloc_free(conv);
+ conv = NULL;
+ if (str == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ };
+ } else if (strcmp(conversion, "nss_x500") == 0) {
+ for (c = 0; rdn_list[c] != NULL; c++) {
+ str = talloc_asprintf_append(str, "%s%s", (c == 0) ? "" : ",",
+ rdn_list[c]);
+ if (str == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+ } else if (strcmp(conversion, "ad_x500") == 0
+ || strcmp(conversion, "ad") == 0) {
+ for (c = 0; rdn_list[c] != NULL; c++) {
+ conv = check_ad_attr_name(str, rdn_list[c]);
+ str = talloc_asprintf_append(str, "%s%s",
+ (c == 0) ? "" : ",",
+ conv == NULL ? rdn_list[c] : conv);
+ talloc_free(conv);
+ conv = NULL;
+ if (str == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+ } else {
+ ret = EINVAL;
+ goto done;
+ }
+
+ ret = 0;
+
+done:
+ if (ret == 0) {
+ *result = str;
+ } else {
+ talloc_free(str);
+ }
+
+ return ret;
+}
diff --git a/src/lib/certmap/sss_cert_content_crypto.c b/src/lib/certmap/sss_cert_content_crypto.c
index bddcf9bce986bd986aa0aa5f16a0744a97ab36d6..23e065a3cfedd103dabc0ba6379472da23d422b1 100644
--- a/src/lib/certmap/sss_cert_content_crypto.c
+++ b/src/lib/certmap/sss_cert_content_crypto.c
@@ -19,14 +19,788 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#include <errno.h>
+#include "config.h"
+#include <talloc.h>
+#include <openssl/x509v3.h>
+#include <openssl/asn1.h>
+#include <openssl/asn1t.h>
+#include <openssl/err.h>
+#include <openssl/stack.h>
+#include <openssl/safestack.h>
+
+#include "util/crypto/sss_crypto.h"
+#include "util/cert.h"
#include "lib/certmap/sss_certmap.h"
#include "lib/certmap/sss_certmap_int.h"
+/* backward compatible macros for OpenSSL < 1.1 */
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#define ASN1_STRING_get0_data(o) ASN1_STRING_data(o)
+#define X509_get_extension_flags(o) ((o)->ex_flags)
+#define X509_get_key_usage(o) ((o)->ex_kusage)
+#endif /* OPENSSL_VERSION_NUMBER < 0x10100000L */
+
+typedef struct PrincipalName_st {
+ ASN1_INTEGER *name_type;
+ STACK_OF(ASN1_GENERALSTRING) *name_string;
+} PrincipalName;
+
+ASN1_SEQUENCE(PrincipalName) = {
+ ASN1_EXP(PrincipalName, name_type, ASN1_INTEGER, 0),
+ ASN1_EXP_SEQUENCE_OF(PrincipalName, name_string, ASN1_GENERALSTRING, 1)
+} ASN1_SEQUENCE_END(PrincipalName)
+
+IMPLEMENT_ASN1_FUNCTIONS(PrincipalName)
+
+typedef struct KRB5PrincipalName_st {
+ ASN1_STRING *realm;
+ PrincipalName *principal_name;
+} KRB5PrincipalName;
+
+ASN1_SEQUENCE(KRB5PrincipalName) = {
+ ASN1_EXP(KRB5PrincipalName, realm, ASN1_GENERALSTRING, 0),
+ ASN1_EXP(KRB5PrincipalName, principal_name, PrincipalName, 1)
+} ASN1_SEQUENCE_END(KRB5PrincipalName)
+
+IMPLEMENT_ASN1_FUNCTIONS(KRB5PrincipalName)
+
+enum san_opt openssl_name_type_to_san_opt(int type)
+{
+ switch (type) {
+ case GEN_OTHERNAME:
+ return SAN_OTHER_NAME;
+ case GEN_EMAIL:
+ return SAN_RFC822_NAME;
+ case GEN_DNS:
+ return SAN_DNS_NAME;
+ case GEN_X400:
+ return SAN_X400_ADDRESS;
+ case GEN_DIRNAME:
+ return SAN_DIRECTORY_NAME;
+ case GEN_EDIPARTY:
+ return SAN_EDIPART_NAME;
+ case GEN_URI:
+ return SAN_URI;
+ case GEN_IPADD:
+ return SAN_IP_ADDRESS;
+ case GEN_RID:
+ return SAN_REGISTERED_ID;
+ default:
+ return SAN_INVALID;
+ }
+}
+
+static int add_string_other_name_to_san_list(TALLOC_CTX *mem_ctx,
+ enum san_opt san_opt,
+ OTHERNAME *other_name,
+ struct san_list **item)
+{
+ struct san_list *i = NULL;
+ int ret;
+ char oid_buf[128]; /* FIXME: any other size ?? */
+ int len;
+ unsigned char *p;
+
+ len = OBJ_obj2txt(oid_buf, sizeof(oid_buf), other_name->type_id, 1);
+ if (len <= 0) {
+ return EINVAL;
+ }
+
+ i = talloc_zero(mem_ctx, struct san_list);
+ if (i == NULL) {
+ return ENOMEM;
+ }
+ i->san_opt = san_opt;
+
+ i->other_name_oid = talloc_strndup(i, oid_buf, len);
+ if (i->other_name_oid == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ len = i2d_ASN1_TYPE(other_name->value, NULL);
+ if (len <= 0) {
+ ret = EINVAL;
+ goto done;
+ }
+
+ i->bin_val = talloc_size(mem_ctx, len);
+ if (i->bin_val == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ /* i2d_TYPE increment the second argument so that it points to the end of
+ * the written data hence we cannot use i->bin_val directly. */
+ p = i->bin_val;
+ i->bin_val_len = i2d_ASN1_TYPE(other_name->value, &p);
+
+ ret = 0;
+
+done:
+ if (ret == 0) {
+ *item = i;
+ } else {
+ talloc_free(i);
+ }
+
+ return ret;
+}
+
+static int add_nt_princ_to_san_list(TALLOC_CTX *mem_ctx,
+ enum san_opt san_opt,
+ GENERAL_NAME *current,
+ struct san_list **item)
+{
+ struct san_list *i = NULL;
+ int ret;
+ OTHERNAME *other_name = current->d.otherName;
+
+ if (ASN1_TYPE_get(other_name->value) != V_ASN1_UTF8STRING) {
+ return EINVAL;
+ }
+
+ i = talloc_zero(mem_ctx, struct san_list);
+ if (i == NULL) {
+ return ENOMEM;
+ }
+ i->san_opt = san_opt;
+
+ i->val = talloc_strndup(i,
+ (const char *) ASN1_STRING_get0_data(
+ other_name->value->value.utf8string),
+ ASN1_STRING_length(other_name->value->value.utf8string));
+ if (i->val == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = get_short_name(i, i->val, '@', &(i->short_name));
+ if (ret != 0) {
+ goto done;
+ }
+
+ ret = 0;
+
+done:
+ if (ret == 0) {
+ *item = i;
+ } else {
+ talloc_free(i);
+ }
+
+ return ret;
+}
+
+void *ASN1_TYPE_unpack_sequence(const ASN1_ITEM *it, const ASN1_TYPE *t)
+{
+ if (t == NULL || t->type != V_ASN1_SEQUENCE || t->value.sequence == NULL)
+ return NULL;
+ return ASN1_item_unpack(t->value.sequence, it);
+}
+
+static int add_pkinit_princ_to_san_list(TALLOC_CTX *mem_ctx,
+ enum san_opt san_opt,
+ GENERAL_NAME *current,
+ struct san_list **item)
+{
+ struct san_list *i = NULL;
+ int ret;
+ KRB5PrincipalName *princ = NULL;
+ size_t c;
+ const unsigned char *p;
+ const ASN1_STRING *oct;
+ ASN1_GENERALSTRING *name_comp;
+
+ oct = current->d.otherName->value->value.sequence;
+ p = oct->data;
+ princ = d2i_KRB5PrincipalName(NULL, &p, oct->length);
+ if (princ == NULL) {
+ return EINVAL;
+ }
+
+ if (princ->realm == NULL
+ || princ->principal_name == NULL
+ || princ->principal_name->name_string == NULL
+ || sk_ASN1_GENERALSTRING_num(princ->principal_name->name_string)
+ == 0) {
+ ret = EINVAL;
+ goto done;
+ }
+
+ i = talloc_zero(mem_ctx, struct san_list);
+ if (i == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ i->san_opt = san_opt;
+
+ i->val = talloc_strdup(i, "");
+ if (i->val == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ for (c = 0;
+ c < sk_ASN1_GENERALSTRING_num(princ->principal_name->name_string);
+ c++) {
+
+ if (c > 0) {
+ i->val = talloc_strdup_append(i->val, "/");
+ if (i->val == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+
+ name_comp = sk_ASN1_GENERALSTRING_value(
+ princ->principal_name->name_string, c);
+ i->val = talloc_strndup_append(i->val,
+ (const char *) ASN1_STRING_get0_data(name_comp),
+ ASN1_STRING_length(name_comp));
+ if (i->val == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+ }
+
+ i->val = talloc_asprintf_append(i->val, "@%.*s",
+ ASN1_STRING_length(princ->realm),
+ ASN1_STRING_get0_data(princ->realm));
+ if (i->val == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ ret = get_short_name(i, i->val, '@', &(i->short_name));
+ if (ret != 0) {
+ goto done;
+ }
+
+ ret = 0;
+
+done:
+ KRB5PrincipalName_free(princ);
+ if (ret == 0) {
+ *item = i;
+ } else {
+ talloc_free(i);
+ }
+
+ return ret;
+}
+
+static int add_ip_to_san_list(TALLOC_CTX *mem_ctx, enum san_opt san_opt,
+ const uint8_t *data, size_t len,
+ struct san_list **item)
+{
+ struct san_list *i = NULL;
+
+ i = talloc_zero(mem_ctx, struct san_list);
+ if (i == NULL) {
+ return ENOMEM;
+ }
+ i->san_opt = san_opt;
+
+ i->val = talloc_strndup(i, (const char *) data, len);
+ if (i->val == NULL) {
+ talloc_free(i);
+ return ENOMEM;
+ }
+
+ *item = i;
+ return 0;
+}
+
+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", openssl_2_nss_attr_name(sn),
+ (int) tmp_str_size, tmp_str);
+ ret = BIO_reset(bio_mem);
+ if (ret != 1) {
+ /* BIO_reset() for BIO_s_mem returns 1 for sucess */
+ ret = ENOMEM;
+ goto done;
+ }
+ 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;
+}
+
+static int add_rdn_list_to_san_list(TALLOC_CTX *mem_ctx,
+ enum san_opt san_opt,
+ X509_NAME *name,
+ struct san_list **item)
+{
+ struct san_list *i = NULL;
+ int ret;
+
+ i = talloc_zero(mem_ctx, struct san_list);
+ if (i == NULL) {
+ return ENOMEM;
+ }
+ i->san_opt = san_opt;
+
+ ret = get_rdn_list(i, name, &(i->rdn_list));
+ if (ret != 0) {
+ talloc_free(i);
+ return ret;
+ }
+
+ *item = i;
+ return 0;
+}
+
+static int add_oid_to_san_list(TALLOC_CTX *mem_ctx,
+ enum san_opt san_opt,
+ ASN1_OBJECT *oid,
+ struct san_list **item)
+{
+ struct san_list *i = NULL;
+ char oid_buf[128]; /* FIXME: any other size ?? */
+ int len;
+
+ len = OBJ_obj2txt(oid_buf, sizeof(oid_buf), oid, 1);
+ if (len <= 0) {
+ return EINVAL;
+ }
+
+ i = talloc_zero(mem_ctx, struct san_list);
+ if (i == NULL) {
+ return ENOMEM;
+ }
+ i->san_opt = san_opt;
+
+ i->val = talloc_strndup(i, oid_buf, len);
+ if (i->val == NULL) {
+ talloc_free(i);
+ return ENOMEM;
+ }
+
+ *item = i;
+ return 0;
+}
+
+static int get_san(TALLOC_CTX *mem_ctx, X509 *cert, struct san_list **san_list)
+{
+ STACK_OF(GENERAL_NAME) *extsan = NULL;
+ GENERAL_NAME *current;
+ size_t c;
+ int ret;
+ int crit;
+ struct san_list *list = NULL;
+ struct san_list *item = NULL;
+ struct san_list *item_s = NULL;
+ struct san_list *item_p = NULL;
+ struct san_list *item_pb = NULL;
+ int len;
+ unsigned char *data;
+ unsigned char *p;
+
+ extsan = X509_get_ext_d2i(cert, NID_subject_alt_name, &crit, NULL);
+ if (extsan == NULL) {
+ if (crit == -1) { /* extension could not be found */
+ return EOK;
+ } else {
+ return EINVAL;
+ }
+ }
+
+ for (c = 0; c < sk_GENERAL_NAME_num(extsan); c++) {
+ current = sk_GENERAL_NAME_value(extsan, c);
+ switch (current->type) {
+ case GEN_OTHERNAME:
+ ret = add_string_other_name_to_san_list(mem_ctx,
+ SAN_STRING_OTHER_NAME,
+ current->d.otherName,
+ &item_s);
+ if (ret != 0) {
+ goto done;
+ }
+ DLIST_ADD(list, item_s);
+
+ item_p = NULL;
+ if (strcmp(item_s->other_name_oid, NT_PRINCIPAL_OID) == 0) {
+ ret = add_nt_princ_to_san_list(mem_ctx, SAN_NT, current,
+ &item_p);
+ if (ret != 0) {
+ goto done;
+ }
+ DLIST_ADD(list, item_p);
+ } else if (strcmp(item_s->other_name_oid, PKINIT_OID) == 0) {
+ ret = add_pkinit_princ_to_san_list(mem_ctx, SAN_PKINIT,
+ current, &item_p);
+ if (ret != 0) {
+ goto done;
+ }
+ DLIST_ADD(list, item_p);
+ }
+
+ if (item_p != NULL) {
+ ret = add_principal_to_san_list(mem_ctx, SAN_PRINCIPAL,
+ item_p->val, &item_pb);
+ if (ret != 0) {
+ goto done;
+ }
+ DLIST_ADD(list, item_pb);
+ }
+
+ break;
+ break;
+ case GEN_EMAIL:
+ ret = add_to_san_list(mem_ctx, false,
+ openssl_name_type_to_san_opt(current->type),
+ ASN1_STRING_get0_data(current->d.rfc822Name),
+ ASN1_STRING_length(current->d.rfc822Name),
+ &item);
+ if (ret != 0) {
+ goto done;
+ }
+
+ ret = get_short_name(item, item->val, '@', &(item->short_name));
+ if (ret != 0) {
+ goto done;
+ }
+
+ DLIST_ADD(list, item);
+ break;
+ case GEN_DNS:
+ ret = add_to_san_list(mem_ctx, false,
+ openssl_name_type_to_san_opt(current->type),
+ ASN1_STRING_get0_data(current->d.dNSName),
+ ASN1_STRING_length(current->d.dNSName),
+ &item);
+ if (ret != 0) {
+ goto done;
+ }
+
+ ret = get_short_name(item, item->val, '.', &(item->short_name));
+ if (ret != 0) {
+ goto done;
+ }
+
+ DLIST_ADD(list, item);
+ break;
+ case GEN_URI:
+ ret = add_to_san_list(mem_ctx, false,
+ openssl_name_type_to_san_opt(current->type),
+ ASN1_STRING_get0_data(current->d.uniformResourceIdentifier),
+ ASN1_STRING_length(current->d.uniformResourceIdentifier),
+ &item);
+ if (ret != 0) {
+ goto done;
+ }
+ break;
+ case GEN_IPADD:
+ ret = add_ip_to_san_list(mem_ctx,
+ openssl_name_type_to_san_opt(current->type),
+ ASN1_STRING_get0_data(current->d.iPAddress),
+ ASN1_STRING_length(current->d.iPAddress),
+ &item);
+ if (ret != 0) {
+ goto done;
+ }
+ DLIST_ADD(list, item);
+ break;
+ case GEN_DIRNAME:
+ ret = add_rdn_list_to_san_list(mem_ctx,
+ openssl_name_type_to_san_opt(current->type),
+ current->d.directoryName, &item);
+ if (ret != 0) {
+ goto done;
+ }
+ DLIST_ADD(list, item);
+ break;
+ case GEN_RID:
+ ret = add_oid_to_san_list(mem_ctx,
+ openssl_name_type_to_san_opt(current->type),
+ current->d.registeredID, &item);
+ if (ret != 0) {
+ goto done;
+ }
+ DLIST_ADD(list, item);
+ break;
+ case GEN_X400:
+ len = i2d_ASN1_TYPE(current->d.x400Address, NULL);
+ if (len <= 0) {
+ ret = EINVAL;
+ goto done;
+ }
+
+ data = talloc_size(mem_ctx, len);
+ if (data == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ /* i2d_TYPE increment the second argument so that it points to the end of
+ * the written data hence we cannot use i->bin_val directly. */
+ p = data;
+ len = i2d_ASN1_TYPE(current->d.x400Address, &p);
+
+ ret = add_to_san_list(mem_ctx, true,
+ openssl_name_type_to_san_opt(current->type),
+ data, len, &item);
+ if (ret != 0) {
+ goto done;
+ }
+ DLIST_ADD(list, item);
+ break;
+ case GEN_EDIPARTY:
+ len = i2d_EDIPARTYNAME(current->d.ediPartyName, NULL);
+ if (len <= 0) {
+ ret = EINVAL;
+ goto done;
+ }
+
+ data = talloc_size(mem_ctx, len);
+ if (data == NULL) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ /* i2d_TYPE increment the second argument so that it points to the end of
+ * the written data hence we cannot use i->bin_val directly. */
+ p = data;
+ len = i2d_EDIPARTYNAME(current->d.ediPartyName, &data);
+
+ ret = add_to_san_list(mem_ctx, true,
+ openssl_name_type_to_san_opt(current->type),
+ data, len, &item);
+ if (ret != 0) {
+ goto done;
+ }
+ DLIST_ADD(list, item);
+ break;
+ default:
+ ret = EINVAL;
+ goto done;
+ }
+ }
+
+done:
+ GENERAL_NAMES_free(extsan);
+
+ if (ret == EOK) {
+ *san_list = list;
+ }
+
+ return ret;
+}
+
+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;
+}
+
int sss_cert_get_content(TALLOC_CTX *mem_ctx,
const uint8_t *der_blob, size_t der_size,
struct sss_cert_content **content)
{
- return EINVAL;
+ int ret;
+ struct sss_cert_content *cont = NULL;
+ X509 *cert = NULL;
+ const unsigned char *der;
+ BIO *bio_mem = NULL;
+ 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 = get_rdn_list(cont, tmp_name, &cont->issuer_rdn_list);
+ if (ret != 0) {
+ goto done;
+ }
+
+ ret = rdn_list_2_dn_str(cont, NULL, cont->issuer_rdn_list,
+ &cont->issuer_str);
+ if (ret != 0) {
+ goto done;
+ }
+
+ tmp_name = X509_get_subject_name(cert);
+
+ ret = get_rdn_list(cont, tmp_name, &cont->subject_rdn_list);
+ if (ret != 0) {
+ goto done;
+ }
+
+ ret = rdn_list_2_dn_str(cont, NULL, cont->subject_rdn_list,
+ &cont->subject_str);
+ if (ret != 0) {
+ goto done;
+ }
+
+ ret = X509_check_purpose(cert, -1, -1);
+ if (ret < 0) {
+ ret = EIO;
+ goto done;
+ }
+ if (!(X509_get_extension_flags(cert) & EXFLAG_KUSAGE)) {
+ ret = EINVAL;
+ goto done;
+ }
+ cont->key_usage = X509_get_key_usage(cert);
+
+ ret = get_extended_key_usage_oids(cont, cert,
+ &(cont->extended_key_usage_oids));
+ if (ret != 0) {
+ goto done;
+ }
+
+ ret = get_san(cont, cert, &(cont->san_list));
+ 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);
+ CRYPTO_cleanup_all_ex_data();
+
+ if (ret == EOK) {
+ *content = cont;
+ } else {
+ talloc_free(cont);
+ }
+
+ return ret;
}
diff --git a/src/lib/certmap/sss_cert_content_nss.c b/src/lib/certmap/sss_cert_content_nss.c
index d3182895465706c87503b8abb0cea49b7677625d..9b9409797228e906ce59de2472677cb292692610 100644
--- a/src/lib/certmap/sss_cert_content_nss.c
+++ b/src/lib/certmap/sss_cert_content_nss.c
@@ -278,38 +278,6 @@ enum san_opt nss_name_type_to_san_opt(CERTGeneralNameType type)
}
}
-static int add_to_san_list(TALLOC_CTX *mem_ctx, bool is_bin,
- enum san_opt san_opt, uint8_t *data, size_t len,
- struct san_list **item)
-{
- struct san_list *i;
-
- if (data == NULL || len == 0 || san_opt == SAN_INVALID) {
- return EINVAL;
- }
-
- i = talloc_zero(mem_ctx, struct san_list);
- if (i == NULL) {
- return ENOMEM;
- }
-
- i->san_opt = san_opt;
- if (is_bin) {
- i->bin_val = talloc_memdup(i, data, len);
- i->bin_val_len = len;
- } else {
- i->val = talloc_strndup(i, (char *) data, len);
- }
- if (i->val == NULL) {
- talloc_free(i);
- return ENOMEM;
- }
-
- *item = i;
-
- return 0;
-}
-
/* taken from pkinit_crypto_nss.c of MIT Kerberos */
/* KerberosString: RFC 4120, 5.2.1. */
static const SEC_ASN1Template kerberos_string_template[] = {
@@ -397,9 +365,6 @@ static const SEC_ASN1Template kerberos_principal_name_template[] = {
{0, 0, NULL, 0}
};
-#define PKINIT_OID "1.3.6.1.5.2.2"
-#define NT_PRINCIPAL_OID "1.3.6.1.4.1.311.20.2.3"
-
static int add_string_other_name_to_san_list(TALLOC_CTX *mem_ctx,
enum san_opt san_opt,
CERTGeneralName *current,
@@ -451,31 +416,6 @@ done:
return ret;
}
-static int get_short_name(TALLOC_CTX *mem_ctx, const char *full_name,
- char delim, char **short_name)
-{
- char *at;
- char *s;
-
- if (full_name == NULL || delim == '\0' || short_name == NULL) {
- return EINVAL;
- }
-
- at = strchr(full_name, delim);
- if (at != NULL) {
- s = talloc_strndup(mem_ctx, full_name, (at - full_name));
- } else {
- s = talloc_strdup(mem_ctx, full_name);
- }
- if (s == NULL) {
- return ENOMEM;
- }
-
- *short_name = s;
-
- return 0;
-}
-
static int add_nt_princ_to_san_list(TALLOC_CTX *mem_ctx,
PLArenaPool *pool,
enum san_opt san_opt,
@@ -532,7 +472,7 @@ static int add_pkinit_princ_to_san_list(TALLOC_CTX *mem_ctx,
{
struct san_list *i = NULL;
SECStatus rv;
- struct kerberos_principal_name kname;
+ struct kerberos_principal_name kname = { 0 };
int ret;
size_t c;
@@ -571,9 +511,9 @@ static int add_pkinit_princ_to_san_list(TALLOC_CTX *mem_ctx,
goto done;
}
}
- i->val = talloc_strndup_append(i->val,
- (char *) kname.realm.data,
- kname.realm.len);
+ i->val = talloc_asprintf_append(i->val, "@%.*s",
+ kname.realm.len,
+ (char *) kname.realm.data);
if (i->val == NULL) {
ret = ENOMEM;
goto done;
@@ -706,42 +646,6 @@ static int add_ip_to_san_list(TALLOC_CTX *mem_ctx, enum san_opt san_opt,
*item = i;
return 0;
}
-static int add_principal_to_san_list(TALLOC_CTX *mem_ctx,
- enum san_opt san_opt,
- const char *princ,
- struct san_list **item)
-{
- struct san_list *i = NULL;
- int ret;
-
- i = talloc_zero(mem_ctx, struct san_list);
- if (i == NULL) {
- return ENOMEM;
- }
- i->san_opt = san_opt;
-
- i->val = talloc_strdup(i, princ);
- if (i->val == NULL) {
- ret = ENOMEM;
- goto done;
- }
-
- ret = get_short_name(i, i->val, '@', &(i->short_name));
- if (ret != 0) {
- goto done;
- }
-
- ret = 0;
-
-done:
- if (ret == 0) {
- *item = i;
- } else {
- talloc_free(i);
- }
-
- return ret;
-}
static int get_san(TALLOC_CTX *mem_ctx, CERTCertificate *cert,
struct san_list **san_list)
@@ -887,6 +791,7 @@ static int get_san(TALLOC_CTX *mem_ctx, CERTCertificate *cert,
break;
default:
ret = EINVAL;
+ goto done;
}
current = CERT_GetNextGeneralName(current);
diff --git a/src/lib/certmap/sss_certmap.c b/src/lib/certmap/sss_certmap.c
index 37bbc5e7c556f637c7e09fce21950d320790ddd1..f6f6f98041bfd55a19ae919ebb62ec6f8a6e5f8f 100644
--- a/src/lib/certmap/sss_certmap.c
+++ b/src/lib/certmap/sss_certmap.c
@@ -311,87 +311,6 @@ done:
return ret;
}
-static int get_dn_str(struct sss_certmap_ctx *ctx, const char *conversion,
- const char **rdn_list, char **result)
-{
- char *str = NULL;
- size_t c;
- int ret;
- char *conv = NULL;
-
- str = talloc_strdup(ctx, "");
- if (str == NULL) {
- ret = ENOMEM;
- goto done;
- }
- if (conversion == NULL || strcmp(conversion, "nss_ldap") == 0
- || strcmp(conversion, "nss") == 0) {
- for (c = 0; rdn_list[c] != NULL; c++);
- while (c != 0) {
- c--;
- str = talloc_asprintf_append(str, "%s%s",
- (rdn_list[c + 1] == NULL) ? "" : ",",
- rdn_list[c]);
- if (str == NULL) {
- ret = ENOMEM;
- goto done;
- }
- };
- } else if (strcmp(conversion, "ad_ldap") == 0) {
- for (c = 0; rdn_list[c] != NULL; c++);
- while (c != 0) {
- c--;
- conv = check_ad_attr_name(str, rdn_list[c]);
- str = talloc_asprintf_append(str, "%s%s",
- (rdn_list[c + 1] == NULL) ? "" : ",",
- conv == NULL ? rdn_list[c] : conv);
- talloc_free(conv);
- conv = NULL;
- if (str == NULL) {
- ret = ENOMEM;
- goto done;
- }
- };
- } else if (strcmp(conversion, "nss_x500") == 0) {
- for (c = 0; rdn_list[c] != NULL; c++) {
- str = talloc_asprintf_append(str, "%s%s", (c == 0) ? "" : ",",
- rdn_list[c]);
- if (str == NULL) {
- ret = ENOMEM;
- goto done;
- }
- }
- } else if (strcmp(conversion, "ad_x500") == 0
- || strcmp(conversion, "ad") == 0) {
- for (c = 0; rdn_list[c] != NULL; c++) {
- conv = check_ad_attr_name(str, rdn_list[c]);
- str = talloc_asprintf_append(str, "%s%s",
- (c == 0) ? "" : ",",
- conv == NULL ? rdn_list[c] : conv);
- talloc_free(conv);
- conv = NULL;
- if (str == NULL) {
- ret = ENOMEM;
- goto done;
- }
- }
- } else {
- ret = EINVAL;
- goto done;
- }
-
- ret = 0;
-
-done:
- if (ret == 0) {
- *result = str;
- } else {
- talloc_free(str);
- }
-
- return ret;
-}
-
static int expand_san_blob(struct sss_certmap_ctx *ctx, enum san_opt san_opt,
struct san_list *san_list, char **expanded)
{
@@ -458,7 +377,7 @@ static int expand_san_rdn_list(struct sss_certmap_ctx *ctx,
DLIST_FOR_EACH(item, san_list) {
if (item->san_opt == san_opt) {
- ret = get_dn_str(ctx, conversion, item->rdn_list, &exp);
+ ret = rdn_list_2_dn_str(ctx, conversion, item->rdn_list, &exp);
if (ret != 0) {
return ret;
}
@@ -528,11 +447,11 @@ static int expand_template(struct sss_certmap_ctx *ctx,
char *exp = NULL;
if (strcmp("issuer_dn", parsed_template->name) == 0) {
- ret = get_dn_str(ctx, parsed_template->conversion,
- cert_content->issuer_rdn_list, &exp);
+ ret = rdn_list_2_dn_str(ctx, parsed_template->conversion,
+ cert_content->issuer_rdn_list, &exp);
} else if (strcmp("subject_dn", parsed_template->name) == 0) {
- ret = get_dn_str(ctx, parsed_template->conversion,
- cert_content->subject_rdn_list, &exp);
+ ret = rdn_list_2_dn_str(ctx, parsed_template->conversion,
+ cert_content->subject_rdn_list, &exp);
} else if (strncmp("subject_", parsed_template->name, 8) == 0) {
ret = expand_san(ctx, parsed_template, cert_content->san_list, &exp);
} else if (strcmp("cert", parsed_template->name) == 0) {
@@ -629,7 +548,7 @@ static bool check_san_regexp(struct sss_certmap_ctx *ctx,
if (item->san_opt == san_opt) {
if (item->san_opt == SAN_DIRECTORY_NAME) {
/* use LDAP order for matching */
- ret = get_dn_str(ctx, NULL, item->rdn_list, &tmp_str);
+ ret = rdn_list_2_dn_str(ctx, NULL, item->rdn_list, &tmp_str);
if (ret != 0 || tmp_str == NULL) {
return false;
}
diff --git a/src/lib/certmap/sss_certmap_attr_names.c b/src/lib/certmap/sss_certmap_attr_names.c
index a28a464910728cdd1f316b2b979da84f440685ea..65c0f9109f6d611e8054bd1ae681d5b8eee5c4f6 100644
--- a/src/lib/certmap/sss_certmap_attr_names.c
+++ b/src/lib/certmap/sss_certmap_attr_names.c
@@ -30,44 +30,48 @@
* https://msdn.microsoft.com/en-us/library/windows/desktop/aa376556%28v=vs.85%29.aspx
* and wine source code dlls/crypt32/oid.c  and include/wincrypt.h . */
+/* OpenSSL data taken from include/openssl/obj_mac.h */
+
#include <stdbool.h>
#include <string.h>
#include <talloc.h>
struct oid_attr_name_map {
bool nss_ad_differ;
+ bool nss_openssl_differ;
const char *oid;
const char *nss;
const char *ad;
+ const char *openssl;
} oid_attr_name_map[] = {
- { false, "2.5.4.3", "CN", "CN"},
- { true, "2.5.4.8", "ST", "S"},
- { false, "2.5.4.10", "O", "O"},
- { false, "2.5.4.11", "OU", "OU"},
- { false, "2.5.4.46", "dnQualifier", "dnQualifier"},
- { false, "2.5.4.6", "C", "C"},
- { true, "2.5.4.5", "serialNumber", "SERIALNUMBER"},
- { false, "2.5.4.7", "L", "L"},
- { true, "2.5.4.12", "title", "T"},
- { false, "2.5.4.4", "SN", "SN"},
- { true, "2.5.4.42", "givenName", "G"},
- { true, "2.5.4.43", "initials", "I"},
- { true, "2.5.4.44", "generationQualifier", "OID.2.5.4.44"},
- { false, "0.9.2342.19200300.100.1.25", "DC", "DC"},
- { true, "0.9.2342.19200300.100.1.3", "MAIL", "OID,0.9.2342.19200300.100.1.3"},
- { true, "0.9.2342.19200300.100.1.1", "UID", "OID.0.9.2342.19200300.100.1.1"},
- { true, "2.5.4.13", "OID.2.5.4.13", "Description"},
- { true, "2.5.4.16", "postalAddress", "OID.2.5.4.16"},
- { true, "2.5.4.17", "postalCode", "PostalCode"},
- { true, "2.5.4.18", "postOfficeBox", "POBox"},
- { true, "2.5.4.51", "houseIdentifier", "OID.2.5.4.51"},
- { false, "1.2.840.113549.1.9.1", "E", "E"},
- { false, "2.5.4.9", "STREET", "STREET"},
- { true, "2.5.4.65", "pseudonym", "OID.2.5.4.65"},
- { true, "2.5.4.15", "businessCategory", "OID.2.5.4.15"},
- { true, "2.5.4.41", "name", "OID.2.5.4.41"},
+ { false, false, "2.5.4.3", "CN", "CN", "CN"},
+ { true, false, "2.5.4.8", "ST", "S", "ST"},
+ { false, false, "2.5.4.10", "O", "O", "O"},
+ { false, false, "2.5.4.11", "OU", "OU", "OU"},
+ { false, false, "2.5.4.46", "dnQualifier", "dnQualifier", "dnQualifier"},
+ { false, false, "2.5.4.6", "C", "C", "C"},
+ { true, false, "2.5.4.5", "serialNumber", "SERIALNUMBER", "serialNumber"},
+ { false, false, "2.5.4.7", "L", "L", "L"},
+ { true, false, "2.5.4.12", "title", "T", "title"},
+ { false, false, "2.5.4.4", "SN", "SN", "SN"},
+ { true, true, "2.5.4.42", "givenName", "G", "GN"},
+ { true, false, "2.5.4.43", "initials", "I", "initials"},
+ { true, false, "2.5.4.44", "generationQualifier", "OID.2.5.4.44", "generationQualifier"},
+ { false, false, "0.9.2342.19200300.100.1.25", "DC", "DC", "DC"},
+ { true, true, "0.9.2342.19200300.100.1.3", "MAIL", "OID,0.9.2342.19200300.100.1.3", "mail"},
+ { true, false, "0.9.2342.19200300.100.1.1", "UID", "OID.0.9.2342.19200300.100.1.1", "UID"},
+ { true, true, "2.5.4.13", "OID.2.5.4.13", "Description", "description"},
+ { true, false, "2.5.4.16", "postalAddress", "OID.2.5.4.16", "postalAddress"},
+ { true, false, "2.5.4.17", "postalCode", "PostalCode", "postalCode"},
+ { true, false, "2.5.4.18", "postOfficeBox", "POBox", "postOfficeBox"},
+ { true, false, "2.5.4.51", "houseIdentifier", "OID.2.5.4.51", "houseIdentifier"},
+ { false, true, "1.2.840.113549.1.9.1", "E", "E", "emailAddress"},
+ { false, true, "2.5.4.9", "STREET", "STREET", "street"},
+ { true, false, "2.5.4.65", "pseudonym", "OID.2.5.4.65", "pseudonym"},
+ { true, false, "2.5.4.15", "businessCategory", "OID.2.5.4.15", "businessCategory"},
+ { true, false, "2.5.4.41", "name", "OID.2.5.4.41", "name"},
- { false, NULL, NULL, NULL}
+ { false, false, NULL, NULL, NULL, NULL}
};
char *check_ad_attr_name(TALLOC_CTX *mem_ctx, const char *rdn)
@@ -105,3 +109,26 @@ char *check_ad_attr_name(TALLOC_CTX *mem_ctx, const char *rdn)
return NULL;
}
+
+const char *openssl_2_nss_attr_name(const char *attr)
+{
+ size_t c;
+
+ if (attr == NULL) {
+ return NULL;
+ }
+
+ for (c = 0; oid_attr_name_map[c].oid != NULL; c++) {
+ if (!oid_attr_name_map[c].nss_openssl_differ) {
+ continue;
+ }
+
+ if (strcmp(attr, oid_attr_name_map[c].openssl) != 0) {
+ continue;
+ }
+
+ return oid_attr_name_map[c].nss;
+ }
+
+ return attr;
+}
diff --git a/src/lib/certmap/sss_certmap_int.h b/src/lib/certmap/sss_certmap_int.h
index 0b4cda73639be9b323ac3388f97be90bc1a771f2..479cc1606d2575b1b69007eb90eac0c9d5814582 100644
--- a/src/lib/certmap/sss_certmap_int.h
+++ b/src/lib/certmap/sss_certmap_int.h
@@ -28,8 +28,11 @@
#include <sys/types.h>
#include <regex.h>
#include <stdint.h>
+#include <stdbool.h>
#include <talloc.h>
+#include "lib/certmap/sss_certmap.h"
+
#define CM_DEBUG(cm_ctx, format, ...) do { \
if (cm_ctx != NULL && cm_ctx->debug != NULL) { \
cm_ctx->debug(cm_ctx->debug_priv, __FILE__, __LINE__, __FUNCTION__, \
@@ -40,6 +43,9 @@
#define DEFAULT_MATCH_RULE "<KU>digitalSignature<EKU>clientAuth"
#define DEFAULT_MAP_RULE "LDAP:(userCertificate;binary={cert!bin})"
+#define PKINIT_OID "1.3.6.1.5.2.2"
+#define NT_PRINCIPAL_OID "1.3.6.1.4.1.311.20.2.3"
+
enum san_opt {
SAN_OTHER_NAME = 0,
SAN_RFC822_NAME,
@@ -161,9 +167,9 @@ struct san_list {
#define SSS_KU_DECIPHER_ONLY 0x8000
struct sss_cert_content {
- const char *issuer_str;
+ char *issuer_str;
const char **issuer_rdn_list;
- const char *subject_str;
+ char *subject_str;
const char **subject_rdn_list;
uint32_t key_usage;
const char **extended_key_usage_oids;
@@ -179,6 +185,8 @@ int sss_cert_get_content(TALLOC_CTX *mem_ctx,
char *check_ad_attr_name(TALLOC_CTX *mem_ctx, const char *rdn);
+char *openssl_2_nss_attr_name(const char *attr);
+
int parse_krb5_match_rule(struct sss_certmap_ctx *ctx,
const char *rule_start,
struct krb5_match_rule **match_rule);
@@ -186,4 +194,17 @@ int parse_krb5_match_rule(struct sss_certmap_ctx *ctx,
int parse_ldap_mapping_rule(struct sss_certmap_ctx *ctx,
const char *rule_start,
struct ldap_mapping_rule **mapping_rule);
+
+int get_short_name(TALLOC_CTX *mem_ctx, const char *full_name,
+ char delim, char **short_name);
+
+int add_to_san_list(TALLOC_CTX *mem_ctx, bool is_bin,
+ enum san_opt san_opt, const uint8_t *data, size_t len,
+ struct san_list **item);
+
+int add_principal_to_san_list(TALLOC_CTX *mem_ctx, enum san_opt san_opt,
+ const char *princ, struct san_list **item);
+
+int rdn_list_2_dn_str(TALLOC_CTX *mem_ctx, const char *conversion,
+ const char **rdn_list, char **result);
#endif /* __SSS_CERTMAP_INT_H__ */
diff --git a/src/tests/cmocka/test_certmap.c b/src/tests/cmocka/test_certmap.c
index c998443d086eaa72cc2a05c38ddfc5ba590a1ce7..f1e73875bf7ae85fbf2be84d47d8d82f544ac8ba 100644
--- a/src/tests/cmocka/test_certmap.c
+++ b/src/tests/cmocka/test_certmap.c
@@ -40,6 +40,10 @@
#include "util/crypto/nss/nss_util.h"
#endif
+#ifdef HAVE_LIBCRYPTO
+#include <openssl/crypto.h>
+#endif
+
struct priv_sss_debug {
int level;
};
@@ -712,6 +716,65 @@ const uint8_t test_cert2_der[] = {
0xa2, 0xd3, 0x43, 0x21, 0x5b, 0xdc, 0xa2, 0x1d, 0x55, 0xa9, 0x48, 0xc5, 0xc4, 0xaa, 0xf3, 0x8b,
0xe6, 0x3e, 0x75, 0x96, 0xe4, 0x3e, 0x64, 0xaf, 0xe8, 0xa7, 0x6a, 0xb6};
+/* used to test SAN principal encoding according to RFC4556 */
+const uint8_t test_cert3_der[] = {
+0x30, 0x82, 0x03, 0x70, 0x30, 0x82, 0x02, 0x58, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x09, 0x00,
+0xe5, 0x8f, 0x16, 0xfe, 0x23, 0x4d, 0xc5, 0xd6, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
+0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x30, 0x1a, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55,
+0x04, 0x03, 0x0c, 0x0f, 0x6b, 0x72, 0x62, 0x35, 0x5f, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x5f, 0x74,
+0x65, 0x73, 0x74, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x37, 0x30, 0x37, 0x31, 0x32, 0x30, 0x39, 0x32,
+0x34, 0x31, 0x38, 0x5a, 0x17, 0x0d, 0x32, 0x30, 0x30, 0x34, 0x30, 0x37, 0x30, 0x39, 0x32, 0x34,
+0x31, 0x38, 0x5a, 0x30, 0x1a, 0x31, 0x18, 0x30, 0x16, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0f,
+0x6b, 0x72, 0x62, 0x35, 0x5f, 0x70, 0x72, 0x69, 0x6e, 0x63, 0x5f, 0x74, 0x65, 0x73, 0x74, 0x30,
+0x82, 0x01, 0x22, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01,
+0x05, 0x00, 0x03, 0x82, 0x01, 0x0f, 0x00, 0x30, 0x82, 0x01, 0x0a, 0x02, 0x82, 0x01, 0x01, 0x00,
+0xbf, 0x84, 0x34, 0x46, 0x37, 0x50, 0xb1, 0xca, 0x14, 0x4c, 0x6b, 0x0d, 0xe4, 0xab, 0xc1, 0xce,
+0xf4, 0xd1, 0xde, 0xca, 0xf5, 0x50, 0x46, 0x3c, 0x63, 0x0f, 0x8e, 0xb8, 0xe9, 0xf9, 0x3e, 0xc4,
+0xf3, 0x24, 0xc1, 0xe4, 0x78, 0xf6, 0xa4, 0x39, 0x6f, 0xc1, 0xd8, 0x9c, 0x1c, 0xa7, 0x47, 0xe4,
+0xc8, 0x71, 0x32, 0x9a, 0x1d, 0x1d, 0xfb, 0x30, 0x0f, 0xf9, 0x85, 0x48, 0xf8, 0x1f, 0xa7, 0xbd,
+0xda, 0x39, 0xd4, 0xc7, 0x27, 0x4f, 0xf5, 0x34, 0xee, 0x4a, 0x59, 0x0c, 0x7a, 0xec, 0x2b, 0xaf,
+0x81, 0x8e, 0x41, 0x54, 0x6f, 0xcc, 0x91, 0x61, 0x4c, 0x61, 0x80, 0xca, 0x37, 0xab, 0x2c, 0x63,
+0x8d, 0xce, 0x07, 0xcd, 0x61, 0x11, 0x10, 0xa0, 0xe4, 0x08, 0x7d, 0x1d, 0x10, 0x85, 0xb1, 0x64,
+0x33, 0x6b, 0x4d, 0x8d, 0xd2, 0x9d, 0xd7, 0x0b, 0x21, 0xbc, 0x15, 0xcd, 0xed, 0xaa, 0xc0, 0x01,
+0x67, 0xe1, 0x7c, 0xd4, 0xf7, 0xdd, 0xf8, 0x28, 0x92, 0xce, 0x8b, 0x7f, 0x08, 0x29, 0x76, 0x6e,
+0xa5, 0xe6, 0xcd, 0xeb, 0x9c, 0x13, 0x78, 0xa3, 0x08, 0xb5, 0xdc, 0x7f, 0xc2, 0x60, 0xc3, 0xac,
+0x68, 0x30, 0x37, 0xe1, 0x54, 0x6a, 0xa9, 0x34, 0x3e, 0x43, 0x8d, 0x6f, 0x9b, 0xe5, 0x8a, 0xf9,
+0xa4, 0x22, 0xab, 0x33, 0x01, 0x32, 0xaf, 0xc4, 0x9f, 0xb1, 0x27, 0xba, 0xae, 0x20, 0x60, 0xd7,
+0x16, 0x48, 0x66, 0x2b, 0x36, 0x9c, 0x54, 0xd0, 0x6e, 0x45, 0xd3, 0x23, 0x3f, 0x17, 0x2e, 0xee,
+0xd4, 0x55, 0xa7, 0x75, 0x2f, 0x28, 0xa9, 0x40, 0x3b, 0xbc, 0x79, 0x69, 0xea, 0x58, 0xc2, 0x3c,
+0x4c, 0x70, 0x4b, 0x93, 0xd8, 0xa4, 0xb6, 0x59, 0x24, 0x77, 0x10, 0xb3, 0xc7, 0x34, 0x99, 0x6b,
+0x28, 0xbd, 0x03, 0xdb, 0xda, 0xea, 0x23, 0x19, 0x10, 0x56, 0x7e, 0xa4, 0x28, 0x04, 0x5a, 0x53,
+0x02, 0x03, 0x01, 0x00, 0x01, 0xa3, 0x81, 0xb8, 0x30, 0x81, 0xb5, 0x30, 0x09, 0x06, 0x03, 0x55,
+0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06, 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03,
+0x02, 0x03, 0xa8, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x25, 0x04, 0x0b, 0x30, 0x09, 0x06, 0x07,
+0x2b, 0x06, 0x01, 0x05, 0x02, 0x03, 0x04, 0x30, 0x1d, 0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16,
+0x04, 0x14, 0xea, 0xd4, 0x30, 0xd7, 0x7d, 0x3b, 0xc7, 0xb4, 0x83, 0x53, 0x2c, 0xa5, 0xb9, 0xd8,
+0x1a, 0x47, 0x6b, 0xb5, 0xe5, 0x9d, 0x30, 0x1f, 0x06, 0x03, 0x55, 0x1d, 0x23, 0x04, 0x18, 0x30,
+0x16, 0x80, 0x14, 0xea, 0xd4, 0x30, 0xd7, 0x7d, 0x3b, 0xc7, 0xb4, 0x83, 0x53, 0x2c, 0xa5, 0xb9,
+0xd8, 0x1a, 0x47, 0x6b, 0xb5, 0xe5, 0x9d, 0x30, 0x47, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x04, 0x40,
+0x30, 0x3e, 0xa0, 0x3c, 0x06, 0x06, 0x2b, 0x06, 0x01, 0x05, 0x02, 0x02, 0xa0, 0x32, 0x30, 0x30,
+0xa0, 0x0b, 0x1b, 0x09, 0x53, 0x53, 0x53, 0x44, 0x2e, 0x54, 0x45, 0x53, 0x54, 0xa1, 0x21, 0x30,
+0x1f, 0xa0, 0x03, 0x02, 0x01, 0x01, 0xa1, 0x18, 0x30, 0x16, 0x1b, 0x04, 0x74, 0x65, 0x73, 0x74,
+0x1b, 0x05, 0x63, 0x6f, 0x6d, 0x70, 0x32, 0x1b, 0x07, 0x61, 0x6e, 0x6f, 0x74, 0x68, 0x65, 0x72,
+0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x0b, 0x05, 0x00, 0x03,
+0x82, 0x01, 0x01, 0x00, 0x08, 0x64, 0x63, 0x89, 0x6d, 0x3d, 0x66, 0x77, 0xe3, 0xb6, 0x40, 0x54,
+0xd7, 0xe2, 0xc5, 0x99, 0xac, 0x98, 0x6e, 0xf8, 0xcd, 0x62, 0xa4, 0xf8, 0xd9, 0xaf, 0xdb, 0xef,
+0xb7, 0x10, 0x8e, 0x45, 0x42, 0x53, 0x5c, 0x3f, 0x6a, 0x8d, 0xa8, 0x8a, 0x6d, 0x76, 0x51, 0x1a,
+0xf4, 0x71, 0x54, 0x27, 0x27, 0xe2, 0x45, 0xe8, 0xa8, 0xd2, 0xa9, 0xcd, 0x62, 0x0d, 0xfc, 0x0d,
+0x28, 0x46, 0x9e, 0x4e, 0x5a, 0x57, 0x72, 0xb4, 0xf2, 0x35, 0x91, 0x57, 0x11, 0xae, 0x2b, 0x9c,
+0x6a, 0x80, 0x21, 0x8e, 0x4c, 0x19, 0x4a, 0x2d, 0xe0, 0xd2, 0xdf, 0x83, 0x9d, 0x65, 0x49, 0xd1,
+0x34, 0x34, 0x14, 0xa0, 0xbb, 0x1c, 0xa8, 0x12, 0xb0, 0xe3, 0x5e, 0x82, 0x36, 0x41, 0x4c, 0x87,
+0xd1, 0x1e, 0x1a, 0xe9, 0xff, 0x55, 0xef, 0xb5, 0x2d, 0x20, 0xc5, 0xa7, 0xe5, 0x5a, 0xf2, 0xfc,
+0xf7, 0xd2, 0x21, 0xc5, 0x32, 0xb4, 0x07, 0x8f, 0xc4, 0x94, 0x56, 0xa6, 0x21, 0x6a, 0xb6, 0x26,
+0x05, 0x48, 0x90, 0xe0, 0x6b, 0x22, 0x35, 0x00, 0x51, 0x2e, 0xd7, 0xe8, 0x3a, 0x56, 0xa8, 0x70,
+0x7d, 0x0f, 0x9a, 0x97, 0x5a, 0xb8, 0x7f, 0x33, 0xc1, 0xe0, 0x92, 0x0f, 0xb3, 0xfe, 0x36, 0xe6,
+0x8b, 0x97, 0x58, 0x42, 0x49, 0xcb, 0x74, 0xde, 0x19, 0x59, 0x90, 0xb6, 0x36, 0x38, 0x07, 0x48,
+0x5d, 0x5b, 0xab, 0x08, 0xf0, 0x69, 0x22, 0x42, 0x08, 0x29, 0xfe, 0x43, 0xab, 0x83, 0x73, 0x74,
+0x5a, 0x3f, 0x3b, 0x5d, 0x8e, 0xca, 0x6f, 0x2d, 0xad, 0xa1, 0x6e, 0x80, 0x80, 0xd2, 0xc8, 0x16,
+0xb7, 0x67, 0x1a, 0x2d, 0x37, 0x8c, 0x20, 0x3b, 0x15, 0xef, 0xb2, 0x94, 0x86, 0x5c, 0xaf, 0xa2,
+0x61, 0x8b, 0xc7, 0xc1, 0xe4, 0xbe, 0x60, 0x5a, 0x86, 0x5c, 0x86, 0xba, 0x59, 0x97, 0x83, 0x1b,
+0x79, 0x1c, 0x7c, 0x26};
+
void test_sss_cert_get_content(void **state)
{
int ret;
@@ -802,7 +865,6 @@ FIXME:
assert_string_equal(content->subject_rdn_list[3], "CN=t u");
assert_string_equal(content->subject_rdn_list[4],
"E=test.user@email.domain");
- //"CN=t u/emailAddress=test.user@email.domain");
assert_null(content->subject_rdn_list[5]);
assert_non_null(content->san_list);
@@ -880,6 +942,21 @@ static void test_sss_certmap_match_cert(void **state)
{NULL, 0}
};
+ struct match_tests match_tests_3[] = {
+ {"KRB5:<KU>digitalSignature", 0},
+ {"KRB5:<KU>keyEncipherment", 0},
+ {"KRB5:<KU>keyAgreement", 0},
+ {"KRB5:<KU>digitalSignature,keyAgreement,keyEncipherment", 0},
+ {"KRB5:<SAN:Principal>test", 0},
+ {"KRB5:<SAN:ntPrincipal>test", ENOENT},
+ {"KRB5:<SAN:Principal>comp2", 0},
+ {"KRB5:<SAN:Principal>another", 0},
+ {"KRB5:<SAN:Principal>test/comp2/another@SSSD.TEST", 0},
+ {"KRB5:<SAN:Principal>^test/comp2/another@SSSD.TEST$", 0},
+ {"KRB5:<SAN:pkinitSAN>^test/comp2/another@SSSD.TEST$", 0},
+ {NULL, 0}
+ };
+
ret = sss_certmap_init(NULL, ext_debug, NULL, &ctx);
assert_int_equal(ret, EOK);
assert_non_null(ctx);
@@ -937,6 +1014,24 @@ static void test_sss_certmap_match_cert(void **state)
sss_certmap_free_ctx(ctx);
}
+
+ for (c = 0; match_tests_3[c].rule != NULL; c++) {
+ ret = sss_certmap_init(NULL, ext_debug, NULL, &ctx);
+ assert_int_equal(ret, EOK);
+ assert_non_null(ctx);
+ assert_null(ctx->prio_list);
+
+ print_error("Checking matching rule [%s]\n", match_tests_3[c].rule);
+
+ ret = sss_certmap_add_rule(ctx, 1, match_tests_3[c].rule, NULL, NULL);
+ assert_int_equal(ret, EOK);
+
+ ret = sss_certmap_match_cert(ctx, discard_const(test_cert3_der),
+ sizeof(test_cert3_der));
+ assert_int_equal(ret, match_tests_3[c].result);
+
+ sss_certmap_free_ctx(ctx);
+ }
}
static void test_sss_certmap_add_mapping_rule(void **state)
@@ -1385,6 +1480,8 @@ static void test_sss_certmap_get_search_filter(void **state)
assert_non_null(filter);
assert_string_equal(filter, "(userCertificate;binary=" TEST_CERT2_BIN")");
assert_null(domains);
+
+ sss_certmap_free_ctx(ctx);
}
int main(int argc, const char *argv[])
@@ -1439,5 +1536,9 @@ int main(int argc, const char *argv[])
nspr_nss_cleanup();
#endif
+#ifdef HAVE_LIBCRYPTO
+ CRYPTO_cleanup_all_ex_data(); /* to make valgrind happy */
+#endif
+
return rv;
}
--
2.14.1