summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHitendra Prajapati <hprajapati@mvista.com>2023-02-24 10:11:06 +0530
committerArmin Kuster <akuster808@gmail.com>2023-03-23 06:28:09 -0400
commiteb631c12be585d18beddbb41f6035772b2cb17d5 (patch)
tree16a9f27a58d4bfb526793fa2be3680319f5ba058
parentc62970fda82acf75035243766ecd195243e0f82a (diff)
downloadmeta-security-dunfell.tar.gz
sssd: CVE-2022-4254 libsss_certmap fails to sanitise certificate data used in LDAP filtersdunfell
Upstream-Status: Backport from https://github.com/SSSD/sssd/commit/1c40208aa1e0f9a17cc4f336c99bcaa6977592d3 & https://github.com/SSSD/sssd/commit/a2b9a84460429181f2a4fa7e2bb5ab49fd561274 Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com> Signed-off-by: Armin Kuster <akuster808@gmail.com>
-rw-r--r--recipes-security/sssd/files/CVE-2022-4254-1.patch515
-rw-r--r--recipes-security/sssd/files/CVE-2022-4254-2.patch655
-rw-r--r--recipes-security/sssd/sssd_1.16.4.bb2
3 files changed, 1172 insertions, 0 deletions
diff --git a/recipes-security/sssd/files/CVE-2022-4254-1.patch b/recipes-security/sssd/files/CVE-2022-4254-1.patch
new file mode 100644
index 0000000..a52ce1a
--- /dev/null
+++ b/recipes-security/sssd/files/CVE-2022-4254-1.patch
@@ -0,0 +1,515 @@
1From 1c40208aa1e0f9a17cc4f336c99bcaa6977592d3 Mon Sep 17 00:00:00 2001
2From: Sumit Bose <sbose@redhat.com>
3Date: Tue, 27 Nov 2018 16:40:01 +0100
4Subject: [PATCH] certmap: add sss_certmap_display_cert_content()
5
6To make debugging and writing certificate mapping and matching rules
7more easy a new function is added to libsss_certmap to display the
8certificate content as seen by libsss_certmap. Please note that the
9actual output might change in future.
10
11Reviewed-by: Jakub Hrozek <jhrozek@redhat.com>
12
13CVE: CVE-2022-4254
14Upstream-Status: Backport [https://github.com/SSSD/sssd/commit/1c40208aa1e0f9a17cc4f336c99bcaa6977592d3]
15Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
16---
17 Makefile.am | 2 +-
18 src/lib/certmap/sss_certmap.c | 142 ++++++++++++++++++++++
19 src/lib/certmap/sss_certmap.exports | 5 +
20 src/lib/certmap/sss_certmap.h | 18 +++
21 src/lib/certmap/sss_certmap_int.h | 31 ++++-
22 src/lib/certmap/sss_certmap_krb5_match.c | 145 +++++++++++------------
23 6 files changed, 261 insertions(+), 82 deletions(-)
24
25diff --git a/Makefile.am b/Makefile.am
26index 4475b3d..29cd93c 100644
27--- a/Makefile.am
28+++ b/Makefile.am
29@@ -1835,7 +1835,7 @@ libsss_certmap_la_LIBADD = \
30 $(NULL)
31 libsss_certmap_la_LDFLAGS = \
32 -Wl,--version-script,$(srcdir)/src/lib/certmap/sss_certmap.exports \
33- -version-info 0:0:0
34+ -version-info 1:0:1
35
36 if HAVE_NSS
37 libsss_certmap_la_SOURCES += \
38diff --git a/src/lib/certmap/sss_certmap.c b/src/lib/certmap/sss_certmap.c
39index f6f6f98..c60ac24 100644
40--- a/src/lib/certmap/sss_certmap.c
41+++ b/src/lib/certmap/sss_certmap.c
42@@ -914,3 +914,145 @@ void sss_certmap_free_filter_and_domains(char *filter, char **domains)
43 talloc_free(filter);
44 talloc_free(domains);
45 }
46+
47+static const char *sss_eku_oid2name(const char *oid)
48+{
49+ size_t c;
50+
51+ for (c = 0; sss_ext_key_usage[c].name != NULL; c++) {
52+ if (strcmp(sss_ext_key_usage[c].oid, oid) == 0) {
53+ return sss_ext_key_usage[c].name;
54+ }
55+ }
56+
57+ return NULL;
58+}
59+
60+struct parsed_template san_parsed_template[] = {
61+ { NULL, NULL, NULL }, /* SAN_OTHER_NAME handled separately */
62+ { "subject_rfc822_name", NULL, NULL},
63+ { "subject_dns_name", NULL, NULL},
64+ { "subject_x400_address", NULL, NULL},
65+ { "subject_directory_name", NULL, NULL},
66+ { "subject_ediparty_name", NULL, NULL},
67+ { "subject_uri", NULL, NULL},
68+ { "subject_ip_address", NULL, NULL},
69+ { "subject_registered_id", NULL, NULL},
70+ { "subject_pkinit_principal", NULL, NULL},
71+ { "subject_nt_principal", NULL, NULL},
72+ { "subject_principal", NULL, NULL},
73+ { NULL, NULL, NULL }, /* SAN_STRING_OTHER_NAME handled separately */
74+ { NULL, NULL, NULL } /* SAN_END */
75+};
76+
77+int sss_cert_dump_content(TALLOC_CTX *mem_ctx, struct sss_cert_content *c,
78+ char **content_str)
79+{
80+ char *out = NULL;
81+ size_t o;
82+ struct san_list *s;
83+ struct sss_certmap_ctx *ctx = NULL;
84+ char *expanded = NULL;
85+ int ret;
86+ char *b64 = NULL;
87+ const char *eku_str = NULL;
88+
89+ ret = sss_certmap_init(mem_ctx, NULL, NULL, &ctx);
90+ if (ret != EOK) {
91+ return ret;
92+ }
93+
94+ out = talloc_strdup(mem_ctx, "sss cert content (format might change):\n");
95+ if (out == NULL) return ENOMEM;
96+
97+ out = talloc_asprintf_append(out, "Issuer: %s\n", c->issuer_str != NULL
98+ ? c->issuer_str
99+ : "- not available -");
100+ if (out == NULL) return ENOMEM;
101+ out = talloc_asprintf_append(out, "Subject: %s\n", c->subject_str != NULL
102+ ? c->subject_str
103+ : "- not available -");
104+ if (out == NULL) return ENOMEM;
105+
106+ out = talloc_asprintf_append(out, "Key Usage: %u(0x%04x)", c->key_usage,
107+ c->key_usage);
108+ if (out == NULL) return ENOMEM;
109+
110+ if (c->key_usage != 0) {
111+ out = talloc_asprintf_append(out, " (");
112+ if (out == NULL) return ENOMEM;
113+ for (o = 0; sss_key_usage[o].name != NULL; o++) {
114+ if ((c->key_usage & sss_key_usage[o].flag) != 0) {
115+ out = talloc_asprintf_append(out, "%s%s",
116+ o == 0 ? "" : ",",
117+ sss_key_usage[o].name);
118+ if (out == NULL) return ENOMEM;
119+ }
120+ }
121+ out = talloc_asprintf_append(out, ")");
122+ if (out == NULL) return ENOMEM;
123+ }
124+ out = talloc_asprintf_append(out, "\n");
125+ if (out == NULL) return ENOMEM;
126+
127+ for (o = 0; c->extended_key_usage_oids[o] != NULL; o++) {
128+ eku_str = sss_eku_oid2name(c->extended_key_usage_oids[o]);
129+ out = talloc_asprintf_append(out, "Extended Key Usage #%zu: %s%s%s%s\n",
130+ o, c->extended_key_usage_oids[o],
131+ eku_str == NULL ? "" : " (",
132+ eku_str == NULL ? "" : eku_str,
133+ eku_str == NULL ? "" : ")");
134+ if (out == NULL) return ENOMEM;
135+ }
136+
137+ DLIST_FOR_EACH(s, c->san_list) {
138+ out = talloc_asprintf_append(out, "SAN type: %s\n",
139+ s->san_opt < SAN_END
140+ ? sss_san_names[s->san_opt].name
141+ : "- unsupported -");
142+ if (out == NULL) return ENOMEM;
143+
144+ if (san_parsed_template[s->san_opt].name != NULL) {
145+ ret = expand_san(ctx, &san_parsed_template[s->san_opt], c->san_list,
146+ &expanded);
147+ if (ret != EOK) {
148+ return ret;
149+ }
150+ out = talloc_asprintf_append(out, " %s=%s\n\n",
151+ san_parsed_template[s->san_opt].name,
152+ expanded);
153+ talloc_free(expanded);
154+ if (out == NULL) return ENOMEM;
155+ } else if (s->san_opt == SAN_STRING_OTHER_NAME) {
156+ b64 = sss_base64_encode(mem_ctx, s->bin_val, s->bin_val_len);
157+ out = talloc_asprintf_append(out, " %s=%s\n\n", s->other_name_oid,
158+ b64 != NULL ? b64
159+ : "- cannot encode -");
160+ talloc_free(b64);
161+ }
162+ }
163+
164+ *content_str = out;
165+
166+ return EOK;
167+}
168+
169+int sss_certmap_display_cert_content(TALLOC_CTX *mem_cxt,
170+ const uint8_t *der_cert, size_t der_size,
171+ char **desc)
172+{
173+ int ret;
174+ struct sss_cert_content *content;
175+
176+ ret = sss_cert_get_content(mem_cxt, der_cert, der_size, &content);
177+ if (ret != EOK) {
178+ return ret;
179+ }
180+
181+ ret = sss_cert_dump_content(mem_cxt, content, desc);
182+ if (ret != EOK) {
183+ return ret;
184+ }
185+
186+ return 0;
187+}
188diff --git a/src/lib/certmap/sss_certmap.exports b/src/lib/certmap/sss_certmap.exports
189index 8b5d536..a9e48d6 100644
190--- a/src/lib/certmap/sss_certmap.exports
191+++ b/src/lib/certmap/sss_certmap.exports
192@@ -11,3 +11,8 @@ SSS_CERTMAP_0.0 {
193 local:
194 *;
195 };
196+
197+SSS_CERTMAP_0.1 {
198+ global:
199+ sss_certmap_display_cert_content;
200+} SSS_CERTMAP_0.0;
201diff --git a/src/lib/certmap/sss_certmap.h b/src/lib/certmap/sss_certmap.h
202index 646e0f3..7da2d1c 100644
203--- a/src/lib/certmap/sss_certmap.h
204+++ b/src/lib/certmap/sss_certmap.h
205@@ -146,6 +146,24 @@ int sss_certmap_get_search_filter(struct sss_certmap_ctx *ctx,
206 */
207 void sss_certmap_free_filter_and_domains(char *filter, char **domains);
208
209+/**
210+ * @brief Get a string with the content of the certificate used by the library
211+ *
212+ * @param[in] mem_ctx Talloc memory context, may be NULL
213+ * @param[in] der_cert binary blog with the DER encoded certificate
214+ * @param[in] der_size size of the certificate blob
215+ * @param[out] desc Multiline string showing the certificate content
216+ * which is used by libsss_certmap
217+ *
218+ * @return
219+ * - 0: success
220+ * - EINVAL: certificate cannot be parsed
221+ * - ENOMEM: memory allocation failure
222+ */
223+int sss_certmap_display_cert_content(TALLOC_CTX *mem_cxt,
224+ const uint8_t *der_cert, size_t der_size,
225+ char **desc);
226+
227 /**
228 * @}
229 */
230diff --git a/src/lib/certmap/sss_certmap_int.h b/src/lib/certmap/sss_certmap_int.h
231index 479cc16..b1155e2 100644
232--- a/src/lib/certmap/sss_certmap_int.h
233+++ b/src/lib/certmap/sss_certmap_int.h
234@@ -101,9 +101,9 @@ enum comp_type {
235 };
236
237 struct parsed_template {
238- char *name;
239- char *attr_name;
240- char *conversion;
241+ const char *name;
242+ const char *attr_name;
243+ const char *conversion;
244 };
245
246 struct ldap_mapping_rule_comp {
247@@ -166,6 +166,28 @@ struct san_list {
248 #define SSS_KU_ENCIPHER_ONLY 0x0001
249 #define SSS_KU_DECIPHER_ONLY 0x8000
250
251+struct sss_key_usage {
252+ const char *name;
253+ uint32_t flag;
254+};
255+
256+extern const struct sss_key_usage sss_key_usage[];
257+
258+struct sss_ext_key_usage {
259+ const char *name;
260+ const char *oid;
261+};
262+
263+extern const struct sss_ext_key_usage sss_ext_key_usage[];
264+
265+struct sss_san_name {
266+ const char *name;
267+ enum san_opt san_opt;
268+ bool is_string;
269+};
270+
271+extern const struct sss_san_name sss_san_names[];
272+
273 struct sss_cert_content {
274 char *issuer_str;
275 const char **issuer_rdn_list;
276@@ -183,6 +205,9 @@ int sss_cert_get_content(TALLOC_CTX *mem_ctx,
277 const uint8_t *der_blob, size_t der_size,
278 struct sss_cert_content **content);
279
280+int sss_cert_dump_content(TALLOC_CTX *mem_ctx, struct sss_cert_content *c,
281+ char **content_str);
282+
283 char *check_ad_attr_name(TALLOC_CTX *mem_ctx, const char *rdn);
284
285 char *openssl_2_nss_attr_name(const char *attr);
286diff --git a/src/lib/certmap/sss_certmap_krb5_match.c b/src/lib/certmap/sss_certmap_krb5_match.c
287index 125e925..398d3d2 100644
288--- a/src/lib/certmap/sss_certmap_krb5_match.c
289+++ b/src/lib/certmap/sss_certmap_krb5_match.c
290@@ -29,6 +29,59 @@
291 #include "lib/certmap/sss_certmap.h"
292 #include "lib/certmap/sss_certmap_int.h"
293
294+const struct sss_key_usage sss_key_usage[] = {
295+ {"digitalSignature" , SSS_KU_DIGITAL_SIGNATURE},
296+ {"nonRepudiation" , SSS_KU_NON_REPUDIATION},
297+ {"keyEncipherment" , SSS_KU_KEY_ENCIPHERMENT},
298+ {"dataEncipherment" , SSS_KU_DATA_ENCIPHERMENT},
299+ {"keyAgreement" , SSS_KU_KEY_AGREEMENT},
300+ {"keyCertSign" , SSS_KU_KEY_CERT_SIGN},
301+ {"cRLSign" , SSS_KU_CRL_SIGN},
302+ {"encipherOnly" , SSS_KU_ENCIPHER_ONLY},
303+ {"decipherOnly" , SSS_KU_DECIPHER_ONLY},
304+ {NULL ,0}
305+};
306+
307+const struct sss_ext_key_usage sss_ext_key_usage[] = {
308+ /* RFC 3280 section 4.2.1.13 */
309+ {"serverAuth", "1.3.6.1.5.5.7.3.1"},
310+ {"clientAuth", "1.3.6.1.5.5.7.3.2"},
311+ {"codeSigning", "1.3.6.1.5.5.7.3.3"},
312+ {"emailProtection", "1.3.6.1.5.5.7.3.4"},
313+ {"timeStamping", "1.3.6.1.5.5.7.3.8"},
314+ {"OCSPSigning", "1.3.6.1.5.5.7.3.9"},
315+
316+ /* RFC 4556 section 3.2.2 */
317+ {"KPClientAuth", "1.3.6.1.5.2.3.4"},
318+ {"pkinit", "1.3.6.1.5.2.3.4"},
319+
320+ /* https://support.microsoft.com/en-us/help/287547/object-ids-associated-with-microsoft-cryptography*/
321+ {"msScLogin", "1.3.6.1.4.1.311.20.2.2"},
322+
323+ {NULL ,0}
324+};
325+
326+const struct sss_san_name sss_san_names[] = {
327+ /* https://www.ietf.org/rfc/rfc3280.txt section 4.2.1.7 */
328+ {"otherName", SAN_OTHER_NAME, false},
329+ {"rfc822Name", SAN_RFC822_NAME, true},
330+ {"dNSName", SAN_DNS_NAME, true},
331+ {"x400Address", SAN_X400_ADDRESS, false},
332+ {"directoryName", SAN_DIRECTORY_NAME, true},
333+ {"ediPartyName", SAN_EDIPART_NAME, false},
334+ {"uniformResourceIdentifier", SAN_URI, true},
335+ {"iPAddress", SAN_IP_ADDRESS, true},
336+ {"registeredID", SAN_REGISTERED_ID, true},
337+ /* https://www.ietf.org/rfc/rfc4556.txt section 3.2.2 */
338+ {"pkinitSAN", SAN_PKINIT, true},
339+ /* https://support.microsoft.com/en-us/help/287547/object-ids-associated-with-microsoft-cryptography */
340+ {"ntPrincipalName", SAN_NT, true},
341+ /* both previous principal types */
342+ {"Principal", SAN_PRINCIPAL, true},
343+ {"stringOtherName", SAN_STRING_OTHER_NAME, true},
344+ {NULL, SAN_END, false}
345+};
346+
347 static bool is_dotted_decimal(const char *s, size_t len)
348 {
349 size_t c = 0;
350@@ -145,28 +198,6 @@ static int parse_krb5_get_eku_value(TALLOC_CTX *mem_ctx,
351 size_t e = 0;
352 int eku_list_size;
353
354- struct ext_key_usage {
355- const char *name;
356- const char *oid;
357- } ext_key_usage[] = {
358- /* RFC 3280 section 4.2.1.13 */
359- {"serverAuth", "1.3.6.1.5.5.7.3.1"},
360- {"clientAuth", "1.3.6.1.5.5.7.3.2"},
361- {"codeSigning", "1.3.6.1.5.5.7.3.3"},
362- {"emailProtection", "1.3.6.1.5.5.7.3.4"},
363- {"timeStamping", "1.3.6.1.5.5.7.3.8"},
364- {"OCSPSigning", "1.3.6.1.5.5.7.3.9"},
365-
366- /* RFC 4556 section 3.2.2 */
367- {"KPClientAuth", "1.3.6.1.5.2.3.4"},
368- {"pkinit", "1.3.6.1.5.2.3.4"},
369-
370- /* https://support.microsoft.com/en-us/help/287547/object-ids-associated-with-microsoft-cryptography*/
371- {"msScLogin", "1.3.6.1.4.1.311.20.2.2"},
372-
373- {NULL ,0}
374- };
375-
376 ret = get_comp_value(mem_ctx, ctx, cur, &comp);
377 if (ret != 0) {
378 CM_DEBUG(ctx, "Failed to parse regexp.");
379@@ -188,11 +219,11 @@ static int parse_krb5_get_eku_value(TALLOC_CTX *mem_ctx,
380 }
381
382 for (c = 0; eku_list[c] != NULL; c++) {
383- for (k = 0; ext_key_usage[k].name != NULL; k++) {
384-CM_DEBUG(ctx, "[%s][%s].", eku_list[c], ext_key_usage[k].name);
385- if (strcasecmp(eku_list[c], ext_key_usage[k].name) == 0) {
386+ for (k = 0; sss_ext_key_usage[k].name != NULL; k++) {
387+CM_DEBUG(ctx, "[%s][%s].", eku_list[c], sss_ext_key_usage[k].name);
388+ if (strcasecmp(eku_list[c], sss_ext_key_usage[k].name) == 0) {
389 comp->eku_oid_list[e] = talloc_strdup(comp->eku_oid_list,
390- ext_key_usage[k].oid);
391+ sss_ext_key_usage[k].oid);
392 if (comp->eku_oid_list[e] == NULL) {
393 ret = ENOMEM;
394 goto done;
395@@ -202,7 +233,7 @@ CM_DEBUG(ctx, "[%s][%s].", eku_list[c], ext_key_usage[k].name);
396 }
397 }
398
399- if (ext_key_usage[k].name == NULL) {
400+ if (sss_ext_key_usage[k].name == NULL) {
401 /* check for an dotted-decimal OID */
402 if (*(eku_list[c]) != '.') {
403 o = eku_list[c];
404@@ -252,23 +283,6 @@ static int parse_krb5_get_ku_value(TALLOC_CTX *mem_ctx,
405 size_t c;
406 size_t k;
407
408- struct key_usage {
409- const char *name;
410- uint32_t flag;
411- } key_usage[] = {
412- {"digitalSignature" , SSS_KU_DIGITAL_SIGNATURE},
413- {"nonRepudiation" , SSS_KU_NON_REPUDIATION},
414- {"keyEncipherment" , SSS_KU_KEY_ENCIPHERMENT},
415- {"dataEncipherment" , SSS_KU_DATA_ENCIPHERMENT},
416- {"keyAgreement" , SSS_KU_KEY_AGREEMENT},
417- {"keyCertSign" , SSS_KU_KEY_CERT_SIGN},
418- {"cRLSign" , SSS_KU_CRL_SIGN},
419- {"encipherOnly" , SSS_KU_ENCIPHER_ONLY},
420- {"decipherOnly" , SSS_KU_DECIPHER_ONLY},
421- {NULL ,0}
422- };
423-
424-
425 ret = get_comp_value(mem_ctx, ctx, cur, &comp);
426 if (ret != 0) {
427 CM_DEBUG(ctx, "Failed to get value.");
428@@ -283,14 +297,14 @@ static int parse_krb5_get_ku_value(TALLOC_CTX *mem_ctx,
429 }
430
431 for (c = 0; ku_list[c] != NULL; c++) {
432- for (k = 0; key_usage[k].name != NULL; k++) {
433- if (strcasecmp(ku_list[c], key_usage[k].name) == 0) {
434- comp->ku |= key_usage[k].flag;
435+ for (k = 0; sss_key_usage[k].name != NULL; k++) {
436+ if (strcasecmp(ku_list[c], sss_key_usage[k].name) == 0) {
437+ comp->ku |= sss_key_usage[k].flag;
438 break;
439 }
440 }
441
442- if (key_usage[k].name == NULL) {
443+ if (sss_key_usage[k].name == NULL) {
444 /* FIXME: add check for numerical ku */
445 CM_DEBUG(ctx, "No matching key usage found.");
446 ret = EINVAL;
447@@ -342,31 +356,6 @@ done:
448 return ret;
449 }
450
451-struct san_name {
452- const char *name;
453- enum san_opt san_opt;
454- bool is_string;
455-} san_names[] = {
456- /* https://www.ietf.org/rfc/rfc3280.txt section 4.2.1.7 */
457- {"otherName", SAN_OTHER_NAME, false},
458- {"rfc822Name", SAN_RFC822_NAME,true},
459- {"dNSName", SAN_DNS_NAME, true},
460- {"x400Address", SAN_X400_ADDRESS, false},
461- {"directoryName", SAN_DIRECTORY_NAME, true},
462- {"ediPartyName", SAN_EDIPART_NAME, false},
463- {"uniformResourceIdentifier", SAN_URI, true},
464- {"iPAddress", SAN_IP_ADDRESS, true},
465- {"registeredID", SAN_REGISTERED_ID, true},
466- /* https://www.ietf.org/rfc/rfc4556.txt section 3.2.2 */
467- {"pkinitSAN", SAN_PKINIT, true},
468- /* https://support.microsoft.com/en-us/help/287547/object-ids-associated-with-microsoft-cryptography */
469- {"ntPrincipalName", SAN_NT, true},
470- /* both previous principal types */
471- {"Principal", SAN_PRINCIPAL, true},
472- {"stringOtherName", SAN_STRING_OTHER_NAME, true},
473- {NULL, SAN_END, false}
474-};
475-
476 static int parse_krb5_get_san_option(TALLOC_CTX *mem_ctx,
477 struct sss_certmap_ctx *ctx,
478 const char **cur,
479@@ -388,12 +377,12 @@ static int parse_krb5_get_san_option(TALLOC_CTX *mem_ctx,
480 if (len == 0) {
481 c= SAN_PRINCIPAL;
482 } else {
483- for (c = 0; san_names[c].name != NULL; c++) {
484- if (strncasecmp(*cur, san_names[c].name, len) == 0) {
485+ for (c = 0; sss_san_names[c].name != NULL; c++) {
486+ if (strncasecmp(*cur, sss_san_names[c].name, len) == 0) {
487 break;
488 }
489 }
490- if (san_names[c].name == NULL) {
491+ if (sss_san_names[c].name == NULL) {
492 if (is_dotted_decimal(*cur, len)) {
493 c = SAN_STRING_OTHER_NAME;
494 *str_other_name_oid = talloc_strndup(mem_ctx, *cur, len);
495@@ -408,7 +397,7 @@ static int parse_krb5_get_san_option(TALLOC_CTX *mem_ctx,
496 }
497 }
498
499- *option = san_names[c].san_opt;
500+ *option = sss_san_names[c].san_opt;
501 *cur = end + 1;
502
503 return 0;
504@@ -432,7 +421,7 @@ static int parse_krb5_get_san_value(TALLOC_CTX *mem_ctx,
505 }
506 }
507
508- if (san_names[san_opt].is_string) {
509+ if (sss_san_names[san_opt].is_string) {
510 ret = parse_krb5_get_component_value(mem_ctx, ctx, cur, &comp);
511 if (ret != 0) {
512 goto done;
513--
5142.25.1
515
diff --git a/recipes-security/sssd/files/CVE-2022-4254-2.patch b/recipes-security/sssd/files/CVE-2022-4254-2.patch
new file mode 100644
index 0000000..018b95c
--- /dev/null
+++ b/recipes-security/sssd/files/CVE-2022-4254-2.patch
@@ -0,0 +1,655 @@
1From a2b9a84460429181f2a4fa7e2bb5ab49fd561274 Mon Sep 17 00:00:00 2001
2From: Sumit Bose <sbose@redhat.com>
3Date: Mon, 9 Dec 2019 11:31:14 +0100
4Subject: [PATCH] certmap: sanitize LDAP search filter
5
6The sss_certmap_get_search_filter() will now sanitize the values read
7from the certificates before adding them to a search filter. To be able
8to get the plain values as well sss_certmap_expand_mapping_rule() is
9added.
10
11Resolves:
12https://github.com/SSSD/sssd/issues/5135
13
14Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
15
16CVE: CVE-2022-4254
17Upstream-Status: Backport [https://github.com/SSSD/sssd/commit/a2b9a84460429181f2a4fa7e2bb5ab49fd561274]
18Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
19---
20 Makefile.am | 2 +-
21 src/lib/certmap/sss_certmap.c | 42 ++++++++++--
22 src/lib/certmap/sss_certmap.exports | 5 ++
23 src/lib/certmap/sss_certmap.h | 35 ++++++++--
24 src/responder/pam/pamsrv_p11.c | 5 +-
25 src/tests/cmocka/test_certmap.c | 98 +++++++++++++++++++++++++++-
26 src/util/util.c | 94 ---------------------------
27 src/util/util_ext.c | 99 +++++++++++++++++++++++++++++
28 8 files changed, 272 insertions(+), 108 deletions(-)
29
30diff --git a/Makefile.am b/Makefile.am
31index 29cd93c..dd6add2 100644
32--- a/Makefile.am
33+++ b/Makefile.am
34@@ -1835,7 +1835,7 @@ libsss_certmap_la_LIBADD = \
35 $(NULL)
36 libsss_certmap_la_LDFLAGS = \
37 -Wl,--version-script,$(srcdir)/src/lib/certmap/sss_certmap.exports \
38- -version-info 1:0:1
39+ -version-info 2:0:2
40
41 if HAVE_NSS
42 libsss_certmap_la_SOURCES += \
43diff --git a/src/lib/certmap/sss_certmap.c b/src/lib/certmap/sss_certmap.c
44index c60ac24..d7bc992 100644
45--- a/src/lib/certmap/sss_certmap.c
46+++ b/src/lib/certmap/sss_certmap.c
47@@ -441,10 +441,12 @@ static int expand_san(struct sss_certmap_ctx *ctx,
48 static int expand_template(struct sss_certmap_ctx *ctx,
49 struct parsed_template *parsed_template,
50 struct sss_cert_content *cert_content,
51+ bool sanitize,
52 char **expanded)
53 {
54 int ret;
55 char *exp = NULL;
56+ char *exp_sanitized = NULL;
57
58 if (strcmp("issuer_dn", parsed_template->name) == 0) {
59 ret = rdn_list_2_dn_str(ctx, parsed_template->conversion,
60@@ -455,6 +457,8 @@ static int expand_template(struct sss_certmap_ctx *ctx,
61 } else if (strncmp("subject_", parsed_template->name, 8) == 0) {
62 ret = expand_san(ctx, parsed_template, cert_content->san_list, &exp);
63 } else if (strcmp("cert", parsed_template->name) == 0) {
64+ /* cert blob is already sanitized */
65+ sanitize = false;
66 ret = expand_cert(ctx, parsed_template, cert_content, &exp);
67 } else {
68 CM_DEBUG(ctx, "Unsupported template name.");
69@@ -471,6 +475,16 @@ static int expand_template(struct sss_certmap_ctx *ctx,
70 goto done;
71 }
72
73+ if (sanitize) {
74+ ret = sss_filter_sanitize(ctx, exp, &exp_sanitized);
75+ if (ret != EOK) {
76+ CM_DEBUG(ctx, "Failed to sanitize expanded template.");
77+ goto done;
78+ }
79+ talloc_free(exp);
80+ exp = exp_sanitized;
81+ }
82+
83 ret = 0;
84
85 done:
86@@ -485,7 +499,7 @@ done:
87
88 static int get_filter(struct sss_certmap_ctx *ctx,
89 struct ldap_mapping_rule *parsed_mapping_rule,
90- struct sss_cert_content *cert_content,
91+ struct sss_cert_content *cert_content, bool sanitize,
92 char **filter)
93 {
94 struct ldap_mapping_rule_comp *comp;
95@@ -503,7 +517,7 @@ static int get_filter(struct sss_certmap_ctx *ctx,
96 result = talloc_strdup_append(result, comp->val);
97 } else if (comp->type == comp_template) {
98 ret = expand_template(ctx, comp->parsed_template, cert_content,
99- &expanded);
100+ sanitize, &expanded);
101 if (ret != 0) {
102 CM_DEBUG(ctx, "Failed to expanded template.");
103 goto done;
104@@ -791,8 +805,9 @@ done:
105 return ret;
106 }
107
108-int sss_certmap_get_search_filter(struct sss_certmap_ctx *ctx,
109+static int expand_mapping_rule_ex(struct sss_certmap_ctx *ctx,
110 const uint8_t *der_cert, size_t der_size,
111+ bool sanitize,
112 char **_filter, char ***_domains)
113 {
114 int ret;
115@@ -819,7 +834,8 @@ int sss_certmap_get_search_filter(struct sss_certmap_ctx *ctx,
116 return EINVAL;
117 }
118
119- ret = get_filter(ctx, ctx->default_mapping_rule, cert_content, &filter);
120+ ret = get_filter(ctx, ctx->default_mapping_rule, cert_content, sanitize,
121+ &filter);
122 goto done;
123 }
124
125@@ -829,7 +845,7 @@ int sss_certmap_get_search_filter(struct sss_certmap_ctx *ctx,
126 if (ret == 0) {
127 /* match */
128 ret = get_filter(ctx, r->parsed_mapping_rule, cert_content,
129- &filter);
130+ sanitize, &filter);
131 if (ret != 0) {
132 CM_DEBUG(ctx, "Failed to get filter");
133 goto done;
134@@ -873,6 +889,22 @@ done:
135 return ret;
136 }
137
138+int sss_certmap_get_search_filter(struct sss_certmap_ctx *ctx,
139+ const uint8_t *der_cert, size_t der_size,
140+ char **_filter, char ***_domains)
141+{
142+ return expand_mapping_rule_ex(ctx, der_cert, der_size, true,
143+ _filter, _domains);
144+}
145+
146+int sss_certmap_expand_mapping_rule(struct sss_certmap_ctx *ctx,
147+ const uint8_t *der_cert, size_t der_size,
148+ char **_expanded, char ***_domains)
149+{
150+ return expand_mapping_rule_ex(ctx, der_cert, der_size, false,
151+ _expanded, _domains);
152+}
153+
154 int sss_certmap_init(TALLOC_CTX *mem_ctx,
155 sss_certmap_ext_debug *debug, void *debug_priv,
156 struct sss_certmap_ctx **ctx)
157diff --git a/src/lib/certmap/sss_certmap.exports b/src/lib/certmap/sss_certmap.exports
158index a9e48d6..7d76677 100644
159--- a/src/lib/certmap/sss_certmap.exports
160+++ b/src/lib/certmap/sss_certmap.exports
161@@ -16,3 +16,8 @@ SSS_CERTMAP_0.1 {
162 global:
163 sss_certmap_display_cert_content;
164 } SSS_CERTMAP_0.0;
165+
166+SSS_CERTMAP_0.2 {
167+ global:
168+ sss_certmap_expand_mapping_rule;
169+} SSS_CERTMAP_0.1;
170diff --git a/src/lib/certmap/sss_certmap.h b/src/lib/certmap/sss_certmap.h
171index 7da2d1c..058d4f9 100644
172--- a/src/lib/certmap/sss_certmap.h
173+++ b/src/lib/certmap/sss_certmap.h
174@@ -103,7 +103,7 @@ int sss_certmap_add_rule(struct sss_certmap_ctx *ctx,
175 *
176 * @param[in] ctx certmap context previously initialized with
177 * @ref sss_certmap_init
178- * @param[in] der_cert binary blog with the DER encoded certificate
179+ * @param[in] der_cert binary blob with the DER encoded certificate
180 * @param[in] der_size size of the certificate blob
181 *
182 * @return
183@@ -119,10 +119,11 @@ int sss_certmap_match_cert(struct sss_certmap_ctx *ctx,
184 *
185 * @param[in] ctx certmap context previously initialized with
186 * @ref sss_certmap_init
187- * @param[in] der_cert binary blog with the DER encoded certificate
188+ * @param[in] der_cert binary blob with the DER encoded certificate
189 * @param[in] der_size size of the certificate blob
190- * @param[out] filter LDAP filter string, caller should free the data by
191- * calling sss_certmap_free_filter_and_domains
192+ * @param[out] filter LDAP filter string, expanded templates are sanitized,
193+ * caller should free the data by calling
194+ * sss_certmap_free_filter_and_domains
195 * @param[out] domains NULL-terminated array of strings with the domains the
196 * rule applies, caller should free the data by calling
197 * sss_certmap_free_filter_and_domains
198@@ -136,8 +137,32 @@ int sss_certmap_get_search_filter(struct sss_certmap_ctx *ctx,
199 const uint8_t *der_cert, size_t der_size,
200 char **filter, char ***domains);
201
202+/**
203+ * @brief Expand the mapping rule by replacing the templates
204+ *
205+ * @param[in] ctx certmap context previously initialized with
206+ * @ref sss_certmap_init
207+ * @param[in] der_cert binary blob with the DER encoded certificate
208+ * @param[in] der_size size of the certificate blob
209+ * @param[out] expanded expanded mapping rule, templates are filled in
210+ * verbatim in contrast to sss_certmap_get_search_filter,
211+ * caller should free the data by
212+ * calling sss_certmap_free_filter_and_domains
213+ * @param[out] domains NULL-terminated array of strings with the domains the
214+ * rule applies, caller should free the data by calling
215+ * sss_certmap_free_filter_and_domains
216+ *
217+ * @return
218+ * - 0: certificate matches a rule
219+ * - ENOENT: certificate does not match
220+ * - EINVAL: internal error
221+ */
222+int sss_certmap_expand_mapping_rule(struct sss_certmap_ctx *ctx,
223+ const uint8_t *der_cert, size_t der_size,
224+ char **_expanded, char ***_domains);
225 /**
226 * @brief Free data returned by @ref sss_certmap_get_search_filter
227+ * and @ref sss_certmap_expand_mapping_rule
228 *
229 * @param[in] filter LDAP filter strings returned by
230 * sss_certmap_get_search_filter
231@@ -150,7 +175,7 @@ void sss_certmap_free_filter_and_domains(char *filter, char **domains);
232 * @brief Get a string with the content of the certificate used by the library
233 *
234 * @param[in] mem_ctx Talloc memory context, may be NULL
235- * @param[in] der_cert binary blog with the DER encoded certificate
236+ * @param[in] der_cert binary blob with the DER encoded certificate
237 * @param[in] der_size size of the certificate blob
238 * @param[out] desc Multiline string showing the certificate content
239 * which is used by libsss_certmap
240diff --git a/src/responder/pam/pamsrv_p11.c b/src/responder/pam/pamsrv_p11.c
241index c7e57be..b9f6787 100644
242--- a/src/responder/pam/pamsrv_p11.c
243+++ b/src/responder/pam/pamsrv_p11.c
244@@ -1023,9 +1023,10 @@ static char *get_cert_prompt(TALLOC_CTX *mem_ctx,
245 goto done;
246 }
247
248- ret = sss_certmap_get_search_filter(ctx, der, der_size, &filter, &domains);
249+ ret = sss_certmap_expand_mapping_rule(ctx, der, der_size,
250+ &filter, &domains);
251 if (ret != 0) {
252- DEBUG(SSSDBG_OP_FAILURE, "sss_certmap_get_search_filter failed.\n");
253+ DEBUG(SSSDBG_OP_FAILURE, "sss_certmap_expand_mapping_rule failed.\n");
254 goto done;
255 }
256
257diff --git a/src/tests/cmocka/test_certmap.c b/src/tests/cmocka/test_certmap.c
258index 3091e1a..abf1dba 100644
259--- a/src/tests/cmocka/test_certmap.c
260+++ b/src/tests/cmocka/test_certmap.c
261@@ -1387,6 +1387,15 @@ static void test_sss_certmap_get_search_filter(void **state)
262 &filter, &domains);
263 assert_int_equal(ret, 0);
264 assert_non_null(filter);
265+ assert_string_equal(filter, "rule100=<I>CN=Certificate\\20Authority,O=IPA.DEVEL"
266+ "<S>CN=ipa-devel.ipa.devel,O=IPA.DEVEL");
267+ assert_null(domains);
268+
269+ ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert_der),
270+ sizeof(test_cert_der),
271+ &filter, &domains);
272+ assert_int_equal(ret, 0);
273+ assert_non_null(filter);
274 assert_string_equal(filter, "rule100=<I>CN=Certificate Authority,O=IPA.DEVEL"
275 "<S>CN=ipa-devel.ipa.devel,O=IPA.DEVEL");
276 assert_null(domains);
277@@ -1401,6 +1410,17 @@ static void test_sss_certmap_get_search_filter(void **state)
278 &filter, &domains);
279 assert_int_equal(ret, 0);
280 assert_non_null(filter);
281+ assert_string_equal(filter, "rule99=<I>CN=Certificate\\20Authority,O=IPA.DEVEL"
282+ "<S>CN=ipa-devel.ipa.devel,O=IPA.DEVEL");
283+ assert_non_null(domains);
284+ assert_string_equal(domains[0], "test.dom");
285+ assert_null(domains[1]);
286+
287+ ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert_der),
288+ sizeof(test_cert_der),
289+ &filter, &domains);
290+ assert_int_equal(ret, 0);
291+ assert_non_null(filter);
292 assert_string_equal(filter, "rule99=<I>CN=Certificate Authority,O=IPA.DEVEL"
293 "<S>CN=ipa-devel.ipa.devel,O=IPA.DEVEL");
294 assert_non_null(domains);
295@@ -1422,6 +1442,16 @@ static void test_sss_certmap_get_search_filter(void **state)
296 assert_string_equal(domains[0], "test.dom");
297 assert_null(domains[1]);
298
299+ ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert_der),
300+ sizeof(test_cert_der),
301+ &filter, &domains);
302+ assert_int_equal(ret, 0);
303+ assert_non_null(filter);
304+ assert_string_equal(filter, "rule98=userCertificate;binary=" TEST_CERT_BIN);
305+ assert_non_null(domains);
306+ assert_string_equal(domains[0], "test.dom");
307+ assert_null(domains[1]);
308+
309 ret = sss_certmap_add_rule(ctx, 97,
310 "KRB5:<ISSUER>CN=Certificate Authority,O=IPA.DEVEL",
311 "LDAP:rule97=<I>{issuer_dn!nss_x500}<S>{subject_dn}",
312@@ -1432,6 +1462,17 @@ static void test_sss_certmap_get_search_filter(void **state)
313 &filter, &domains);
314 assert_int_equal(ret, 0);
315 assert_non_null(filter);
316+ assert_string_equal(filter, "rule97=<I>O=IPA.DEVEL,CN=Certificate\\20Authority"
317+ "<S>CN=ipa-devel.ipa.devel,O=IPA.DEVEL");
318+ assert_non_null(domains);
319+ assert_string_equal(domains[0], "test.dom");
320+ assert_null(domains[1]);
321+
322+ ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert_der),
323+ sizeof(test_cert_der),
324+ &filter, &domains);
325+ assert_int_equal(ret, 0);
326+ assert_non_null(filter);
327 assert_string_equal(filter, "rule97=<I>O=IPA.DEVEL,CN=Certificate Authority"
328 "<S>CN=ipa-devel.ipa.devel,O=IPA.DEVEL");
329 assert_non_null(domains);
330@@ -1448,6 +1489,17 @@ static void test_sss_certmap_get_search_filter(void **state)
331 &filter, &domains);
332 assert_int_equal(ret, 0);
333 assert_non_null(filter);
334+ assert_string_equal(filter, "rule96=<I>O=IPA.DEVEL,CN=Certificate\\20Authority"
335+ "<S>O=IPA.DEVEL,CN=ipa-devel.ipa.devel");
336+ assert_non_null(domains);
337+ assert_string_equal(domains[0], "test.dom");
338+ assert_null(domains[1]);
339+
340+ ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert_der),
341+ sizeof(test_cert_der),
342+ &filter, &domains);
343+ assert_int_equal(ret, 0);
344+ assert_non_null(filter);
345 assert_string_equal(filter, "rule96=<I>O=IPA.DEVEL,CN=Certificate Authority"
346 "<S>O=IPA.DEVEL,CN=ipa-devel.ipa.devel");
347 assert_non_null(domains);
348@@ -1466,6 +1518,14 @@ static void test_sss_certmap_get_search_filter(void **state)
349 assert_string_equal(filter, "(userCertificate;binary=" TEST_CERT_BIN ")");
350 assert_null(domains);
351
352+ ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert_der),
353+ sizeof(test_cert_der),
354+ &filter, &domains);
355+ assert_int_equal(ret, 0);
356+ assert_non_null(filter);
357+ assert_string_equal(filter, "(userCertificate;binary=" TEST_CERT_BIN ")");
358+ assert_null(domains);
359+
360 ret = sss_certmap_add_rule(ctx, 94,
361 "KRB5:<ISSUER>CN=Certificate Authority,O=IPA.DEVEL",
362 "LDAP:rule94=<I>{issuer_dn!ad_x500}<S>{subject_dn!ad_x500}",
363@@ -1476,12 +1536,22 @@ static void test_sss_certmap_get_search_filter(void **state)
364 &filter, &domains);
365 assert_int_equal(ret, 0);
366 assert_non_null(filter);
367- assert_string_equal(filter, "rule94=<I>O=IPA.DEVEL,CN=Certificate Authority"
368+ assert_string_equal(filter, "rule94=<I>O=IPA.DEVEL,CN=Certificate\\20Authority"
369 "<S>O=IPA.DEVEL,CN=ipa-devel.ipa.devel");
370 assert_non_null(domains);
371 assert_string_equal(domains[0], "test.dom");
372 assert_null(domains[1]);
373
374+ ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert_der),
375+ sizeof(test_cert_der),
376+ &filter, &domains);
377+ assert_int_equal(ret, 0);
378+ assert_non_null(filter);
379+ assert_string_equal(filter, "rule94=<I>O=IPA.DEVEL,CN=Certificate Authority"
380+ "<S>O=IPA.DEVEL,CN=ipa-devel.ipa.devel");
381+ assert_non_null(domains);
382+ assert_string_equal(domains[0], "test.dom");
383+ assert_null(domains[1]);
384
385 ret = sss_certmap_add_rule(ctx, 89, NULL,
386 "(rule89={subject_nt_principal})",
387@@ -1495,6 +1565,14 @@ static void test_sss_certmap_get_search_filter(void **state)
388 assert_string_equal(filter, "(rule89=tu1@ad.devel)");
389 assert_null(domains);
390
391+ ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert2_der),
392+ sizeof(test_cert2_der),
393+ &filter, &domains);
394+ assert_int_equal(ret, 0);
395+ assert_non_null(filter);
396+ assert_string_equal(filter, "(rule89=tu1@ad.devel)");
397+ assert_null(domains);
398+
399 ret = sss_certmap_add_rule(ctx, 88, NULL,
400 "(rule88={subject_nt_principal.short_name})",
401 NULL);
402@@ -1516,6 +1594,15 @@ static void test_sss_certmap_get_search_filter(void **state)
403 &filter, &domains);
404 assert_int_equal(ret, 0);
405 assert_non_null(filter);
406+ assert_string_equal(filter, "rule87=<I>DC=devel,DC=ad,CN=ad-AD-SERVER-CA"
407+ "<S>DC=devel,DC=ad,CN=Users,CN=t\\20u,E=test.user@email.domain");
408+ assert_null(domains);
409+
410+ ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert2_der),
411+ sizeof(test_cert2_der),
412+ &filter, &domains);
413+ assert_int_equal(ret, 0);
414+ assert_non_null(filter);
415 assert_string_equal(filter, "rule87=<I>DC=devel,DC=ad,CN=ad-AD-SERVER-CA"
416 "<S>DC=devel,DC=ad,CN=Users,CN=t u,E=test.user@email.domain");
417 assert_null(domains);
418@@ -1529,6 +1616,15 @@ static void test_sss_certmap_get_search_filter(void **state)
419 &filter, &domains);
420 assert_int_equal(ret, 0);
421 assert_non_null(filter);
422+ assert_string_equal(filter, "rule86=<I>DC=devel,DC=ad,CN=ad-AD-SERVER-CA"
423+ "<S>DC=devel,DC=ad,CN=Users,CN=t\\20u,E=test.user@email.domain");
424+ assert_null(domains);
425+
426+ ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert2_der),
427+ sizeof(test_cert2_der),
428+ &filter, &domains);
429+ assert_int_equal(ret, 0);
430+ assert_non_null(filter);
431 assert_string_equal(filter, "rule86=<I>DC=devel,DC=ad,CN=ad-AD-SERVER-CA"
432 "<S>DC=devel,DC=ad,CN=Users,CN=t u,E=test.user@email.domain");
433 assert_null(domains);
434diff --git a/src/util/util.c b/src/util/util.c
435index e3efa7f..0653638 100644
436--- a/src/util/util.c
437+++ b/src/util/util.c
438@@ -436,100 +436,6 @@ errno_t sss_hash_create(TALLOC_CTX *mem_ctx, unsigned long count,
439 return sss_hash_create_ex(mem_ctx, count, tbl, 0, 0, 0, 0, NULL, NULL);
440 }
441
442-errno_t sss_filter_sanitize_ex(TALLOC_CTX *mem_ctx,
443- const char *input,
444- char **sanitized,
445- const char *ignore)
446-{
447- char *output;
448- size_t i = 0;
449- size_t j = 0;
450- char *allowed;
451-
452- /* Assume the worst-case. We'll resize it later, once */
453- output = talloc_array(mem_ctx, char, strlen(input) * 3 + 1);
454- if (!output) {
455- return ENOMEM;
456- }
457-
458- while (input[i]) {
459- /* Even though this character might have a special meaning, if it's
460- * expliticly allowed, just copy it and move on
461- */
462- if (ignore == NULL) {
463- allowed = NULL;
464- } else {
465- allowed = strchr(ignore, input[i]);
466- }
467- if (allowed) {
468- output[j++] = input[i++];
469- continue;
470- }
471-
472- switch(input[i]) {
473- case '\t':
474- output[j++] = '\\';
475- output[j++] = '0';
476- output[j++] = '9';
477- break;
478- case ' ':
479- output[j++] = '\\';
480- output[j++] = '2';
481- output[j++] = '0';
482- break;
483- case '*':
484- output[j++] = '\\';
485- output[j++] = '2';
486- output[j++] = 'a';
487- break;
488- case '(':
489- output[j++] = '\\';
490- output[j++] = '2';
491- output[j++] = '8';
492- break;
493- case ')':
494- output[j++] = '\\';
495- output[j++] = '2';
496- output[j++] = '9';
497- break;
498- case '\\':
499- output[j++] = '\\';
500- output[j++] = '5';
501- output[j++] = 'c';
502- break;
503- case '\r':
504- output[j++] = '\\';
505- output[j++] = '0';
506- output[j++] = 'd';
507- break;
508- case '\n':
509- output[j++] = '\\';
510- output[j++] = '0';
511- output[j++] = 'a';
512- break;
513- default:
514- output[j++] = input[i];
515- }
516-
517- i++;
518- }
519- output[j] = '\0';
520- *sanitized = talloc_realloc(mem_ctx, output, char, j+1);
521- if (!*sanitized) {
522- talloc_free(output);
523- return ENOMEM;
524- }
525-
526- return EOK;
527-}
528-
529-errno_t sss_filter_sanitize(TALLOC_CTX *mem_ctx,
530- const char *input,
531- char **sanitized)
532-{
533- return sss_filter_sanitize_ex(mem_ctx, input, sanitized, NULL);
534-}
535-
536 char *
537 sss_escape_ip_address(TALLOC_CTX *mem_ctx, int family, const char *addr)
538 {
539diff --git a/src/util/util_ext.c b/src/util/util_ext.c
540index 04dc02a..a89b60f 100644
541--- a/src/util/util_ext.c
542+++ b/src/util/util_ext.c
543@@ -29,6 +29,11 @@
544
545 #define EOK 0
546
547+#ifndef HAVE_ERRNO_T
548+#define HAVE_ERRNO_T
549+typedef int errno_t;
550+#endif
551+
552 int split_on_separator(TALLOC_CTX *mem_ctx, const char *str,
553 const char sep, bool trim, bool skip_empty,
554 char ***_list, int *size)
555@@ -141,3 +146,97 @@ bool string_in_list(const char *string, char **list, bool case_sensitive)
556
557 return false;
558 }
559+
560+errno_t sss_filter_sanitize_ex(TALLOC_CTX *mem_ctx,
561+ const char *input,
562+ char **sanitized,
563+ const char *ignore)
564+{
565+ char *output;
566+ size_t i = 0;
567+ size_t j = 0;
568+ char *allowed;
569+
570+ /* Assume the worst-case. We'll resize it later, once */
571+ output = talloc_array(mem_ctx, char, strlen(input) * 3 + 1);
572+ if (!output) {
573+ return ENOMEM;
574+ }
575+
576+ while (input[i]) {
577+ /* Even though this character might have a special meaning, if it's
578+ * explicitly allowed, just copy it and move on
579+ */
580+ if (ignore == NULL) {
581+ allowed = NULL;
582+ } else {
583+ allowed = strchr(ignore, input[i]);
584+ }
585+ if (allowed) {
586+ output[j++] = input[i++];
587+ continue;
588+ }
589+
590+ switch(input[i]) {
591+ case '\t':
592+ output[j++] = '\\';
593+ output[j++] = '0';
594+ output[j++] = '9';
595+ break;
596+ case ' ':
597+ output[j++] = '\\';
598+ output[j++] = '2';
599+ output[j++] = '0';
600+ break;
601+ case '*':
602+ output[j++] = '\\';
603+ output[j++] = '2';
604+ output[j++] = 'a';
605+ break;
606+ case '(':
607+ output[j++] = '\\';
608+ output[j++] = '2';
609+ output[j++] = '8';
610+ break;
611+ case ')':
612+ output[j++] = '\\';
613+ output[j++] = '2';
614+ output[j++] = '9';
615+ break;
616+ case '\\':
617+ output[j++] = '\\';
618+ output[j++] = '5';
619+ output[j++] = 'c';
620+ break;
621+ case '\r':
622+ output[j++] = '\\';
623+ output[j++] = '0';
624+ output[j++] = 'd';
625+ break;
626+ case '\n':
627+ output[j++] = '\\';
628+ output[j++] = '0';
629+ output[j++] = 'a';
630+ break;
631+ default:
632+ output[j++] = input[i];
633+ }
634+
635+ i++;
636+ }
637+ output[j] = '\0';
638+ *sanitized = talloc_realloc(mem_ctx, output, char, j+1);
639+ if (!*sanitized) {
640+ talloc_free(output);
641+ return ENOMEM;
642+ }
643+
644+ return EOK;
645+}
646+
647+errno_t sss_filter_sanitize(TALLOC_CTX *mem_ctx,
648+ const char *input,
649+ char **sanitized)
650+{
651+ return sss_filter_sanitize_ex(mem_ctx, input, sanitized, NULL);
652+}
653--
6542.25.1
655
diff --git a/recipes-security/sssd/sssd_1.16.4.bb b/recipes-security/sssd/sssd_1.16.4.bb
index 186c9e0..e512dbf 100644
--- a/recipes-security/sssd/sssd_1.16.4.bb
+++ b/recipes-security/sssd/sssd_1.16.4.bb
@@ -18,6 +18,8 @@ SRC_URI = "https://releases.pagure.org/SSSD/${BPN}/${BP}.tar.gz \
18 file://volatiles.99_sssd \ 18 file://volatiles.99_sssd \
19 file://fix-ldblibdir.patch \ 19 file://fix-ldblibdir.patch \
20 file://0001-build-Don-t-use-AC_CHECK_FILE-when-building-manpages.patch \ 20 file://0001-build-Don-t-use-AC_CHECK_FILE-when-building-manpages.patch \
21 file://CVE-2022-4254-1.patch \
22 file://CVE-2022-4254-2.patch \
21 " 23 "
22 24
23SRC_URI[md5sum] = "757bbb6f15409d8d075f4f06cb678d50" 25SRC_URI[md5sum] = "757bbb6f15409d8d075f4f06cb678d50"