summaryrefslogtreecommitdiffstats
path: root/recipes-security/sssd/files/CVE-2022-4254-2.patch
diff options
context:
space:
mode:
Diffstat (limited to 'recipes-security/sssd/files/CVE-2022-4254-2.patch')
-rw-r--r--recipes-security/sssd/files/CVE-2022-4254-2.patch655
1 files changed, 655 insertions, 0 deletions
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