Files
meta-security/recipes-security/sssd/files/CVE-2022-4254-1.patch
Hitendra Prajapati eb631c12be sssd: CVE-2022-4254 libsss_certmap fails to sanitise certificate data used in LDAP filters
Upstream-Status: Backport from 1c40208aa1 & a2b9a84460

Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
Signed-off-by: Armin Kuster <akuster808@gmail.com>
2023-03-23 06:28:09 -04:00

516 lines
19 KiB
Diff

From 1c40208aa1e0f9a17cc4f336c99bcaa6977592d3 Mon Sep 17 00:00:00 2001
From: Sumit Bose <sbose@redhat.com>
Date: Tue, 27 Nov 2018 16:40:01 +0100
Subject: [PATCH] certmap: add sss_certmap_display_cert_content()
To make debugging and writing certificate mapping and matching rules
more easy a new function is added to libsss_certmap to display the
certificate content as seen by libsss_certmap. Please note that the
actual output might change in future.
Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
CVE: CVE-2022-4254
Upstream-Status: Backport [https://github.com/SSSD/sssd/commit/1c40208aa1e0f9a17cc4f336c99bcaa6977592d3]
Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
---
Makefile.am | 2 +-
src/lib/certmap/sss_certmap.c | 142 ++++++++++++++++++++++
src/lib/certmap/sss_certmap.exports | 5 +
src/lib/certmap/sss_certmap.h | 18 +++
src/lib/certmap/sss_certmap_int.h | 31 ++++-
src/lib/certmap/sss_certmap_krb5_match.c | 145 +++++++++++------------
6 files changed, 261 insertions(+), 82 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 4475b3d..29cd93c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1835,7 +1835,7 @@ libsss_certmap_la_LIBADD = \
$(NULL)
libsss_certmap_la_LDFLAGS = \
-Wl,--version-script,$(srcdir)/src/lib/certmap/sss_certmap.exports \
- -version-info 0:0:0
+ -version-info 1:0:1
if HAVE_NSS
libsss_certmap_la_SOURCES += \
diff --git a/src/lib/certmap/sss_certmap.c b/src/lib/certmap/sss_certmap.c
index f6f6f98..c60ac24 100644
--- a/src/lib/certmap/sss_certmap.c
+++ b/src/lib/certmap/sss_certmap.c
@@ -914,3 +914,145 @@ void sss_certmap_free_filter_and_domains(char *filter, char **domains)
talloc_free(filter);
talloc_free(domains);
}
+
+static const char *sss_eku_oid2name(const char *oid)
+{
+ size_t c;
+
+ for (c = 0; sss_ext_key_usage[c].name != NULL; c++) {
+ if (strcmp(sss_ext_key_usage[c].oid, oid) == 0) {
+ return sss_ext_key_usage[c].name;
+ }
+ }
+
+ return NULL;
+}
+
+struct parsed_template san_parsed_template[] = {
+ { NULL, NULL, NULL }, /* SAN_OTHER_NAME handled separately */
+ { "subject_rfc822_name", NULL, NULL},
+ { "subject_dns_name", NULL, NULL},
+ { "subject_x400_address", NULL, NULL},
+ { "subject_directory_name", NULL, NULL},
+ { "subject_ediparty_name", NULL, NULL},
+ { "subject_uri", NULL, NULL},
+ { "subject_ip_address", NULL, NULL},
+ { "subject_registered_id", NULL, NULL},
+ { "subject_pkinit_principal", NULL, NULL},
+ { "subject_nt_principal", NULL, NULL},
+ { "subject_principal", NULL, NULL},
+ { NULL, NULL, NULL }, /* SAN_STRING_OTHER_NAME handled separately */
+ { NULL, NULL, NULL } /* SAN_END */
+};
+
+int sss_cert_dump_content(TALLOC_CTX *mem_ctx, struct sss_cert_content *c,
+ char **content_str)
+{
+ char *out = NULL;
+ size_t o;
+ struct san_list *s;
+ struct sss_certmap_ctx *ctx = NULL;
+ char *expanded = NULL;
+ int ret;
+ char *b64 = NULL;
+ const char *eku_str = NULL;
+
+ ret = sss_certmap_init(mem_ctx, NULL, NULL, &ctx);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ out = talloc_strdup(mem_ctx, "sss cert content (format might change):\n");
+ if (out == NULL) return ENOMEM;
+
+ out = talloc_asprintf_append(out, "Issuer: %s\n", c->issuer_str != NULL
+ ? c->issuer_str
+ : "- not available -");
+ if (out == NULL) return ENOMEM;
+ out = talloc_asprintf_append(out, "Subject: %s\n", c->subject_str != NULL
+ ? c->subject_str
+ : "- not available -");
+ if (out == NULL) return ENOMEM;
+
+ out = talloc_asprintf_append(out, "Key Usage: %u(0x%04x)", c->key_usage,
+ c->key_usage);
+ if (out == NULL) return ENOMEM;
+
+ if (c->key_usage != 0) {
+ out = talloc_asprintf_append(out, " (");
+ if (out == NULL) return ENOMEM;
+ for (o = 0; sss_key_usage[o].name != NULL; o++) {
+ if ((c->key_usage & sss_key_usage[o].flag) != 0) {
+ out = talloc_asprintf_append(out, "%s%s",
+ o == 0 ? "" : ",",
+ sss_key_usage[o].name);
+ if (out == NULL) return ENOMEM;
+ }
+ }
+ out = talloc_asprintf_append(out, ")");
+ if (out == NULL) return ENOMEM;
+ }
+ out = talloc_asprintf_append(out, "\n");
+ if (out == NULL) return ENOMEM;
+
+ for (o = 0; c->extended_key_usage_oids[o] != NULL; o++) {
+ eku_str = sss_eku_oid2name(c->extended_key_usage_oids[o]);
+ out = talloc_asprintf_append(out, "Extended Key Usage #%zu: %s%s%s%s\n",
+ o, c->extended_key_usage_oids[o],
+ eku_str == NULL ? "" : " (",
+ eku_str == NULL ? "" : eku_str,
+ eku_str == NULL ? "" : ")");
+ if (out == NULL) return ENOMEM;
+ }
+
+ DLIST_FOR_EACH(s, c->san_list) {
+ out = talloc_asprintf_append(out, "SAN type: %s\n",
+ s->san_opt < SAN_END
+ ? sss_san_names[s->san_opt].name
+ : "- unsupported -");
+ if (out == NULL) return ENOMEM;
+
+ if (san_parsed_template[s->san_opt].name != NULL) {
+ ret = expand_san(ctx, &san_parsed_template[s->san_opt], c->san_list,
+ &expanded);
+ if (ret != EOK) {
+ return ret;
+ }
+ out = talloc_asprintf_append(out, " %s=%s\n\n",
+ san_parsed_template[s->san_opt].name,
+ expanded);
+ talloc_free(expanded);
+ if (out == NULL) return ENOMEM;
+ } else if (s->san_opt == SAN_STRING_OTHER_NAME) {
+ b64 = sss_base64_encode(mem_ctx, s->bin_val, s->bin_val_len);
+ out = talloc_asprintf_append(out, " %s=%s\n\n", s->other_name_oid,
+ b64 != NULL ? b64
+ : "- cannot encode -");
+ talloc_free(b64);
+ }
+ }
+
+ *content_str = out;
+
+ return EOK;
+}
+
+int sss_certmap_display_cert_content(TALLOC_CTX *mem_cxt,
+ const uint8_t *der_cert, size_t der_size,
+ char **desc)
+{
+ int ret;
+ struct sss_cert_content *content;
+
+ ret = sss_cert_get_content(mem_cxt, der_cert, der_size, &content);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ ret = sss_cert_dump_content(mem_cxt, content, desc);
+ if (ret != EOK) {
+ return ret;
+ }
+
+ return 0;
+}
diff --git a/src/lib/certmap/sss_certmap.exports b/src/lib/certmap/sss_certmap.exports
index 8b5d536..a9e48d6 100644
--- a/src/lib/certmap/sss_certmap.exports
+++ b/src/lib/certmap/sss_certmap.exports
@@ -11,3 +11,8 @@ SSS_CERTMAP_0.0 {
local:
*;
};
+
+SSS_CERTMAP_0.1 {
+ global:
+ sss_certmap_display_cert_content;
+} SSS_CERTMAP_0.0;
diff --git a/src/lib/certmap/sss_certmap.h b/src/lib/certmap/sss_certmap.h
index 646e0f3..7da2d1c 100644
--- a/src/lib/certmap/sss_certmap.h
+++ b/src/lib/certmap/sss_certmap.h
@@ -146,6 +146,24 @@ int sss_certmap_get_search_filter(struct sss_certmap_ctx *ctx,
*/
void sss_certmap_free_filter_and_domains(char *filter, char **domains);
+/**
+ * @brief Get a string with the content of the certificate used by the library
+ *
+ * @param[in] mem_ctx Talloc memory context, may be NULL
+ * @param[in] der_cert binary blog with the DER encoded certificate
+ * @param[in] der_size size of the certificate blob
+ * @param[out] desc Multiline string showing the certificate content
+ * which is used by libsss_certmap
+ *
+ * @return
+ * - 0: success
+ * - EINVAL: certificate cannot be parsed
+ * - ENOMEM: memory allocation failure
+ */
+int sss_certmap_display_cert_content(TALLOC_CTX *mem_cxt,
+ const uint8_t *der_cert, size_t der_size,
+ char **desc);
+
/**
* @}
*/
diff --git a/src/lib/certmap/sss_certmap_int.h b/src/lib/certmap/sss_certmap_int.h
index 479cc16..b1155e2 100644
--- a/src/lib/certmap/sss_certmap_int.h
+++ b/src/lib/certmap/sss_certmap_int.h
@@ -101,9 +101,9 @@ enum comp_type {
};
struct parsed_template {
- char *name;
- char *attr_name;
- char *conversion;
+ const char *name;
+ const char *attr_name;
+ const char *conversion;
};
struct ldap_mapping_rule_comp {
@@ -166,6 +166,28 @@ struct san_list {
#define SSS_KU_ENCIPHER_ONLY 0x0001
#define SSS_KU_DECIPHER_ONLY 0x8000
+struct sss_key_usage {
+ const char *name;
+ uint32_t flag;
+};
+
+extern const struct sss_key_usage sss_key_usage[];
+
+struct sss_ext_key_usage {
+ const char *name;
+ const char *oid;
+};
+
+extern const struct sss_ext_key_usage sss_ext_key_usage[];
+
+struct sss_san_name {
+ const char *name;
+ enum san_opt san_opt;
+ bool is_string;
+};
+
+extern const struct sss_san_name sss_san_names[];
+
struct sss_cert_content {
char *issuer_str;
const char **issuer_rdn_list;
@@ -183,6 +205,9 @@ int sss_cert_get_content(TALLOC_CTX *mem_ctx,
const uint8_t *der_blob, size_t der_size,
struct sss_cert_content **content);
+int sss_cert_dump_content(TALLOC_CTX *mem_ctx, struct sss_cert_content *c,
+ char **content_str);
+
char *check_ad_attr_name(TALLOC_CTX *mem_ctx, const char *rdn);
char *openssl_2_nss_attr_name(const char *attr);
diff --git a/src/lib/certmap/sss_certmap_krb5_match.c b/src/lib/certmap/sss_certmap_krb5_match.c
index 125e925..398d3d2 100644
--- a/src/lib/certmap/sss_certmap_krb5_match.c
+++ b/src/lib/certmap/sss_certmap_krb5_match.c
@@ -29,6 +29,59 @@
#include "lib/certmap/sss_certmap.h"
#include "lib/certmap/sss_certmap_int.h"
+const struct sss_key_usage sss_key_usage[] = {
+ {"digitalSignature" , SSS_KU_DIGITAL_SIGNATURE},
+ {"nonRepudiation" , SSS_KU_NON_REPUDIATION},
+ {"keyEncipherment" , SSS_KU_KEY_ENCIPHERMENT},
+ {"dataEncipherment" , SSS_KU_DATA_ENCIPHERMENT},
+ {"keyAgreement" , SSS_KU_KEY_AGREEMENT},
+ {"keyCertSign" , SSS_KU_KEY_CERT_SIGN},
+ {"cRLSign" , SSS_KU_CRL_SIGN},
+ {"encipherOnly" , SSS_KU_ENCIPHER_ONLY},
+ {"decipherOnly" , SSS_KU_DECIPHER_ONLY},
+ {NULL ,0}
+};
+
+const struct sss_ext_key_usage sss_ext_key_usage[] = {
+ /* RFC 3280 section 4.2.1.13 */
+ {"serverAuth", "1.3.6.1.5.5.7.3.1"},
+ {"clientAuth", "1.3.6.1.5.5.7.3.2"},
+ {"codeSigning", "1.3.6.1.5.5.7.3.3"},
+ {"emailProtection", "1.3.6.1.5.5.7.3.4"},
+ {"timeStamping", "1.3.6.1.5.5.7.3.8"},
+ {"OCSPSigning", "1.3.6.1.5.5.7.3.9"},
+
+ /* RFC 4556 section 3.2.2 */
+ {"KPClientAuth", "1.3.6.1.5.2.3.4"},
+ {"pkinit", "1.3.6.1.5.2.3.4"},
+
+ /* https://support.microsoft.com/en-us/help/287547/object-ids-associated-with-microsoft-cryptography*/
+ {"msScLogin", "1.3.6.1.4.1.311.20.2.2"},
+
+ {NULL ,0}
+};
+
+const struct sss_san_name sss_san_names[] = {
+ /* https://www.ietf.org/rfc/rfc3280.txt section 4.2.1.7 */
+ {"otherName", SAN_OTHER_NAME, false},
+ {"rfc822Name", SAN_RFC822_NAME, true},
+ {"dNSName", SAN_DNS_NAME, true},
+ {"x400Address", SAN_X400_ADDRESS, false},
+ {"directoryName", SAN_DIRECTORY_NAME, true},
+ {"ediPartyName", SAN_EDIPART_NAME, false},
+ {"uniformResourceIdentifier", SAN_URI, true},
+ {"iPAddress", SAN_IP_ADDRESS, true},
+ {"registeredID", SAN_REGISTERED_ID, true},
+ /* https://www.ietf.org/rfc/rfc4556.txt section 3.2.2 */
+ {"pkinitSAN", SAN_PKINIT, true},
+ /* https://support.microsoft.com/en-us/help/287547/object-ids-associated-with-microsoft-cryptography */
+ {"ntPrincipalName", SAN_NT, true},
+ /* both previous principal types */
+ {"Principal", SAN_PRINCIPAL, true},
+ {"stringOtherName", SAN_STRING_OTHER_NAME, true},
+ {NULL, SAN_END, false}
+};
+
static bool is_dotted_decimal(const char *s, size_t len)
{
size_t c = 0;
@@ -145,28 +198,6 @@ static int parse_krb5_get_eku_value(TALLOC_CTX *mem_ctx,
size_t e = 0;
int eku_list_size;
- struct ext_key_usage {
- const char *name;
- const char *oid;
- } ext_key_usage[] = {
- /* RFC 3280 section 4.2.1.13 */
- {"serverAuth", "1.3.6.1.5.5.7.3.1"},
- {"clientAuth", "1.3.6.1.5.5.7.3.2"},
- {"codeSigning", "1.3.6.1.5.5.7.3.3"},
- {"emailProtection", "1.3.6.1.5.5.7.3.4"},
- {"timeStamping", "1.3.6.1.5.5.7.3.8"},
- {"OCSPSigning", "1.3.6.1.5.5.7.3.9"},
-
- /* RFC 4556 section 3.2.2 */
- {"KPClientAuth", "1.3.6.1.5.2.3.4"},
- {"pkinit", "1.3.6.1.5.2.3.4"},
-
- /* https://support.microsoft.com/en-us/help/287547/object-ids-associated-with-microsoft-cryptography*/
- {"msScLogin", "1.3.6.1.4.1.311.20.2.2"},
-
- {NULL ,0}
- };
-
ret = get_comp_value(mem_ctx, ctx, cur, &comp);
if (ret != 0) {
CM_DEBUG(ctx, "Failed to parse regexp.");
@@ -188,11 +219,11 @@ static int parse_krb5_get_eku_value(TALLOC_CTX *mem_ctx,
}
for (c = 0; eku_list[c] != NULL; c++) {
- for (k = 0; ext_key_usage[k].name != NULL; k++) {
-CM_DEBUG(ctx, "[%s][%s].", eku_list[c], ext_key_usage[k].name);
- if (strcasecmp(eku_list[c], ext_key_usage[k].name) == 0) {
+ for (k = 0; sss_ext_key_usage[k].name != NULL; k++) {
+CM_DEBUG(ctx, "[%s][%s].", eku_list[c], sss_ext_key_usage[k].name);
+ if (strcasecmp(eku_list[c], sss_ext_key_usage[k].name) == 0) {
comp->eku_oid_list[e] = talloc_strdup(comp->eku_oid_list,
- ext_key_usage[k].oid);
+ sss_ext_key_usage[k].oid);
if (comp->eku_oid_list[e] == NULL) {
ret = ENOMEM;
goto done;
@@ -202,7 +233,7 @@ CM_DEBUG(ctx, "[%s][%s].", eku_list[c], ext_key_usage[k].name);
}
}
- if (ext_key_usage[k].name == NULL) {
+ if (sss_ext_key_usage[k].name == NULL) {
/* check for an dotted-decimal OID */
if (*(eku_list[c]) != '.') {
o = eku_list[c];
@@ -252,23 +283,6 @@ static int parse_krb5_get_ku_value(TALLOC_CTX *mem_ctx,
size_t c;
size_t k;
- struct key_usage {
- const char *name;
- uint32_t flag;
- } key_usage[] = {
- {"digitalSignature" , SSS_KU_DIGITAL_SIGNATURE},
- {"nonRepudiation" , SSS_KU_NON_REPUDIATION},
- {"keyEncipherment" , SSS_KU_KEY_ENCIPHERMENT},
- {"dataEncipherment" , SSS_KU_DATA_ENCIPHERMENT},
- {"keyAgreement" , SSS_KU_KEY_AGREEMENT},
- {"keyCertSign" , SSS_KU_KEY_CERT_SIGN},
- {"cRLSign" , SSS_KU_CRL_SIGN},
- {"encipherOnly" , SSS_KU_ENCIPHER_ONLY},
- {"decipherOnly" , SSS_KU_DECIPHER_ONLY},
- {NULL ,0}
- };
-
-
ret = get_comp_value(mem_ctx, ctx, cur, &comp);
if (ret != 0) {
CM_DEBUG(ctx, "Failed to get value.");
@@ -283,14 +297,14 @@ static int parse_krb5_get_ku_value(TALLOC_CTX *mem_ctx,
}
for (c = 0; ku_list[c] != NULL; c++) {
- for (k = 0; key_usage[k].name != NULL; k++) {
- if (strcasecmp(ku_list[c], key_usage[k].name) == 0) {
- comp->ku |= key_usage[k].flag;
+ for (k = 0; sss_key_usage[k].name != NULL; k++) {
+ if (strcasecmp(ku_list[c], sss_key_usage[k].name) == 0) {
+ comp->ku |= sss_key_usage[k].flag;
break;
}
}
- if (key_usage[k].name == NULL) {
+ if (sss_key_usage[k].name == NULL) {
/* FIXME: add check for numerical ku */
CM_DEBUG(ctx, "No matching key usage found.");
ret = EINVAL;
@@ -342,31 +356,6 @@ done:
return ret;
}
-struct san_name {
- const char *name;
- enum san_opt san_opt;
- bool is_string;
-} san_names[] = {
- /* https://www.ietf.org/rfc/rfc3280.txt section 4.2.1.7 */
- {"otherName", SAN_OTHER_NAME, false},
- {"rfc822Name", SAN_RFC822_NAME,true},
- {"dNSName", SAN_DNS_NAME, true},
- {"x400Address", SAN_X400_ADDRESS, false},
- {"directoryName", SAN_DIRECTORY_NAME, true},
- {"ediPartyName", SAN_EDIPART_NAME, false},
- {"uniformResourceIdentifier", SAN_URI, true},
- {"iPAddress", SAN_IP_ADDRESS, true},
- {"registeredID", SAN_REGISTERED_ID, true},
- /* https://www.ietf.org/rfc/rfc4556.txt section 3.2.2 */
- {"pkinitSAN", SAN_PKINIT, true},
- /* https://support.microsoft.com/en-us/help/287547/object-ids-associated-with-microsoft-cryptography */
- {"ntPrincipalName", SAN_NT, true},
- /* both previous principal types */
- {"Principal", SAN_PRINCIPAL, true},
- {"stringOtherName", SAN_STRING_OTHER_NAME, true},
- {NULL, SAN_END, false}
-};
-
static int parse_krb5_get_san_option(TALLOC_CTX *mem_ctx,
struct sss_certmap_ctx *ctx,
const char **cur,
@@ -388,12 +377,12 @@ static int parse_krb5_get_san_option(TALLOC_CTX *mem_ctx,
if (len == 0) {
c= SAN_PRINCIPAL;
} else {
- for (c = 0; san_names[c].name != NULL; c++) {
- if (strncasecmp(*cur, san_names[c].name, len) == 0) {
+ for (c = 0; sss_san_names[c].name != NULL; c++) {
+ if (strncasecmp(*cur, sss_san_names[c].name, len) == 0) {
break;
}
}
- if (san_names[c].name == NULL) {
+ if (sss_san_names[c].name == NULL) {
if (is_dotted_decimal(*cur, len)) {
c = SAN_STRING_OTHER_NAME;
*str_other_name_oid = talloc_strndup(mem_ctx, *cur, len);
@@ -408,7 +397,7 @@ static int parse_krb5_get_san_option(TALLOC_CTX *mem_ctx,
}
}
- *option = san_names[c].san_opt;
+ *option = sss_san_names[c].san_opt;
*cur = end + 1;
return 0;
@@ -432,7 +421,7 @@ static int parse_krb5_get_san_value(TALLOC_CTX *mem_ctx,
}
}
- if (san_names[san_opt].is_string) {
+ if (sss_san_names[san_opt].is_string) {
ret = parse_krb5_get_component_value(mem_ctx, ctx, cur, &comp);
if (ret != 0) {
goto done;
--
2.25.1