Skip to content

Commit a2b9a84

Browse files
sumit-bosepbrezina
authored andcommitted
certmap: sanitize LDAP search filter
The sss_certmap_get_search_filter() will now sanitize the values read from the certificates before adding them to a search filter. To be able to get the plain values as well sss_certmap_expand_mapping_rule() is added. Resolves: #5135 Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
1 parent 41a60c6 commit a2b9a84

8 files changed

Lines changed: 272 additions & 108 deletions

File tree

Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2163,7 +2163,7 @@ libsss_certmap_la_LIBADD = \
21632163
$(NULL)
21642164
libsss_certmap_la_LDFLAGS = \
21652165
-Wl,--version-script,$(srcdir)/src/lib/certmap/sss_certmap.exports \
2166-
-version-info 1:0:1
2166+
-version-info 2:0:2
21672167

21682168
if HAVE_NSS
21692169
libsss_certmap_la_SOURCES += \

src/lib/certmap/sss_certmap.c

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -441,10 +441,12 @@ static int expand_san(struct sss_certmap_ctx *ctx,
441441
static int expand_template(struct sss_certmap_ctx *ctx,
442442
struct parsed_template *parsed_template,
443443
struct sss_cert_content *cert_content,
444+
bool sanitize,
444445
char **expanded)
445446
{
446447
int ret;
447448
char *exp = NULL;
449+
char *exp_sanitized = NULL;
448450

449451
if (strcmp("issuer_dn", parsed_template->name) == 0) {
450452
ret = rdn_list_2_dn_str(ctx, parsed_template->conversion,
@@ -455,6 +457,8 @@ static int expand_template(struct sss_certmap_ctx *ctx,
455457
} else if (strncmp("subject_", parsed_template->name, 8) == 0) {
456458
ret = expand_san(ctx, parsed_template, cert_content->san_list, &exp);
457459
} else if (strcmp("cert", parsed_template->name) == 0) {
460+
/* cert blob is already sanitized */
461+
sanitize = false;
458462
ret = expand_cert(ctx, parsed_template, cert_content, &exp);
459463
} else {
460464
CM_DEBUG(ctx, "Unsupported template name.");
@@ -471,6 +475,16 @@ static int expand_template(struct sss_certmap_ctx *ctx,
471475
goto done;
472476
}
473477

478+
if (sanitize) {
479+
ret = sss_filter_sanitize(ctx, exp, &exp_sanitized);
480+
if (ret != EOK) {
481+
CM_DEBUG(ctx, "Failed to sanitize expanded template.");
482+
goto done;
483+
}
484+
talloc_free(exp);
485+
exp = exp_sanitized;
486+
}
487+
474488
ret = 0;
475489

476490
done:
@@ -485,7 +499,7 @@ static int expand_template(struct sss_certmap_ctx *ctx,
485499

486500
static int get_filter(struct sss_certmap_ctx *ctx,
487501
struct ldap_mapping_rule *parsed_mapping_rule,
488-
struct sss_cert_content *cert_content,
502+
struct sss_cert_content *cert_content, bool sanitize,
489503
char **filter)
490504
{
491505
struct ldap_mapping_rule_comp *comp;
@@ -503,7 +517,7 @@ static int get_filter(struct sss_certmap_ctx *ctx,
503517
result = talloc_strdup_append(result, comp->val);
504518
} else if (comp->type == comp_template) {
505519
ret = expand_template(ctx, comp->parsed_template, cert_content,
506-
&expanded);
520+
sanitize, &expanded);
507521
if (ret != 0) {
508522
CM_DEBUG(ctx, "Failed to expanded template.");
509523
goto done;
@@ -791,8 +805,9 @@ int sss_certmap_match_cert(struct sss_certmap_ctx *ctx,
791805
return ret;
792806
}
793807

794-
int sss_certmap_get_search_filter(struct sss_certmap_ctx *ctx,
808+
static int expand_mapping_rule_ex(struct sss_certmap_ctx *ctx,
795809
const uint8_t *der_cert, size_t der_size,
810+
bool sanitize,
796811
char **_filter, char ***_domains)
797812
{
798813
int ret;
@@ -819,7 +834,8 @@ int sss_certmap_get_search_filter(struct sss_certmap_ctx *ctx,
819834
return EINVAL;
820835
}
821836

822-
ret = get_filter(ctx, ctx->default_mapping_rule, cert_content, &filter);
837+
ret = get_filter(ctx, ctx->default_mapping_rule, cert_content, sanitize,
838+
&filter);
823839
goto done;
824840
}
825841

@@ -829,7 +845,7 @@ int sss_certmap_get_search_filter(struct sss_certmap_ctx *ctx,
829845
if (ret == 0) {
830846
/* match */
831847
ret = get_filter(ctx, r->parsed_mapping_rule, cert_content,
832-
&filter);
848+
sanitize, &filter);
833849
if (ret != 0) {
834850
CM_DEBUG(ctx, "Failed to get filter");
835851
goto done;
@@ -873,6 +889,22 @@ int sss_certmap_get_search_filter(struct sss_certmap_ctx *ctx,
873889
return ret;
874890
}
875891

892+
int sss_certmap_get_search_filter(struct sss_certmap_ctx *ctx,
893+
const uint8_t *der_cert, size_t der_size,
894+
char **_filter, char ***_domains)
895+
{
896+
return expand_mapping_rule_ex(ctx, der_cert, der_size, true,
897+
_filter, _domains);
898+
}
899+
900+
int sss_certmap_expand_mapping_rule(struct sss_certmap_ctx *ctx,
901+
const uint8_t *der_cert, size_t der_size,
902+
char **_expanded, char ***_domains)
903+
{
904+
return expand_mapping_rule_ex(ctx, der_cert, der_size, false,
905+
_expanded, _domains);
906+
}
907+
876908
int sss_certmap_init(TALLOC_CTX *mem_ctx,
877909
sss_certmap_ext_debug *debug, void *debug_priv,
878910
struct sss_certmap_ctx **ctx)

src/lib/certmap/sss_certmap.exports

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,8 @@ SSS_CERTMAP_0.1 {
1616
global:
1717
sss_certmap_display_cert_content;
1818
} SSS_CERTMAP_0.0;
19+
20+
SSS_CERTMAP_0.2 {
21+
global:
22+
sss_certmap_expand_mapping_rule;
23+
} SSS_CERTMAP_0.1;

src/lib/certmap/sss_certmap.h

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ int sss_certmap_add_rule(struct sss_certmap_ctx *ctx,
103103
*
104104
* @param[in] ctx certmap context previously initialized with
105105
* @ref sss_certmap_init
106-
* @param[in] der_cert binary blog with the DER encoded certificate
106+
* @param[in] der_cert binary blob with the DER encoded certificate
107107
* @param[in] der_size size of the certificate blob
108108
*
109109
* @return
@@ -119,10 +119,11 @@ int sss_certmap_match_cert(struct sss_certmap_ctx *ctx,
119119
*
120120
* @param[in] ctx certmap context previously initialized with
121121
* @ref sss_certmap_init
122-
* @param[in] der_cert binary blog with the DER encoded certificate
122+
* @param[in] der_cert binary blob with the DER encoded certificate
123123
* @param[in] der_size size of the certificate blob
124-
* @param[out] filter LDAP filter string, caller should free the data by
125-
* calling sss_certmap_free_filter_and_domains
124+
* @param[out] filter LDAP filter string, expanded templates are sanitized,
125+
* caller should free the data by calling
126+
* sss_certmap_free_filter_and_domains
126127
* @param[out] domains NULL-terminated array of strings with the domains the
127128
* rule applies, caller should free the data by calling
128129
* sss_certmap_free_filter_and_domains
@@ -136,8 +137,32 @@ int sss_certmap_get_search_filter(struct sss_certmap_ctx *ctx,
136137
const uint8_t *der_cert, size_t der_size,
137138
char **filter, char ***domains);
138139

140+
/**
141+
* @brief Expand the mapping rule by replacing the templates
142+
*
143+
* @param[in] ctx certmap context previously initialized with
144+
* @ref sss_certmap_init
145+
* @param[in] der_cert binary blob with the DER encoded certificate
146+
* @param[in] der_size size of the certificate blob
147+
* @param[out] expanded expanded mapping rule, templates are filled in
148+
* verbatim in contrast to sss_certmap_get_search_filter,
149+
* caller should free the data by
150+
* calling sss_certmap_free_filter_and_domains
151+
* @param[out] domains NULL-terminated array of strings with the domains the
152+
* rule applies, caller should free the data by calling
153+
* sss_certmap_free_filter_and_domains
154+
*
155+
* @return
156+
* - 0: certificate matches a rule
157+
* - ENOENT: certificate does not match
158+
* - EINVAL: internal error
159+
*/
160+
int sss_certmap_expand_mapping_rule(struct sss_certmap_ctx *ctx,
161+
const uint8_t *der_cert, size_t der_size,
162+
char **_expanded, char ***_domains);
139163
/**
140164
* @brief Free data returned by @ref sss_certmap_get_search_filter
165+
* and @ref sss_certmap_expand_mapping_rule
141166
*
142167
* @param[in] filter LDAP filter strings returned by
143168
* sss_certmap_get_search_filter
@@ -150,7 +175,7 @@ void sss_certmap_free_filter_and_domains(char *filter, char **domains);
150175
* @brief Get a string with the content of the certificate used by the library
151176
*
152177
* @param[in] mem_ctx Talloc memory context, may be NULL
153-
* @param[in] der_cert binary blog with the DER encoded certificate
178+
* @param[in] der_cert binary blob with the DER encoded certificate
154179
* @param[in] der_size size of the certificate blob
155180
* @param[out] desc Multiline string showing the certificate content
156181
* which is used by libsss_certmap

src/responder/pam/pamsrv_p11.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,9 +1049,10 @@ static char *get_cert_prompt(TALLOC_CTX *mem_ctx,
10491049
goto done;
10501050
}
10511051

1052-
ret = sss_certmap_get_search_filter(ctx, der, der_size, &filter, &domains);
1052+
ret = sss_certmap_expand_mapping_rule(ctx, der, der_size,
1053+
&filter, &domains);
10531054
if (ret != 0) {
1054-
DEBUG(SSSDBG_OP_FAILURE, "sss_certmap_get_search_filter failed.\n");
1055+
DEBUG(SSSDBG_OP_FAILURE, "sss_certmap_expand_mapping_rule failed.\n");
10551056
goto done;
10561057
}
10571058

src/tests/cmocka/test_certmap.c

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1431,6 +1431,15 @@ static void test_sss_certmap_get_search_filter(void **state)
14311431
&filter, &domains);
14321432
assert_int_equal(ret, 0);
14331433
assert_non_null(filter);
1434+
assert_string_equal(filter, "rule100=<I>CN=Certificate\\20Authority,O=IPA.DEVEL"
1435+
"<S>CN=ipa-devel.ipa.devel,O=IPA.DEVEL");
1436+
assert_null(domains);
1437+
1438+
ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert_der),
1439+
sizeof(test_cert_der),
1440+
&filter, &domains);
1441+
assert_int_equal(ret, 0);
1442+
assert_non_null(filter);
14341443
assert_string_equal(filter, "rule100=<I>CN=Certificate Authority,O=IPA.DEVEL"
14351444
"<S>CN=ipa-devel.ipa.devel,O=IPA.DEVEL");
14361445
assert_null(domains);
@@ -1445,6 +1454,17 @@ static void test_sss_certmap_get_search_filter(void **state)
14451454
&filter, &domains);
14461455
assert_int_equal(ret, 0);
14471456
assert_non_null(filter);
1457+
assert_string_equal(filter, "rule99=<I>CN=Certificate\\20Authority,O=IPA.DEVEL"
1458+
"<S>CN=ipa-devel.ipa.devel,O=IPA.DEVEL");
1459+
assert_non_null(domains);
1460+
assert_string_equal(domains[0], "test.dom");
1461+
assert_null(domains[1]);
1462+
1463+
ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert_der),
1464+
sizeof(test_cert_der),
1465+
&filter, &domains);
1466+
assert_int_equal(ret, 0);
1467+
assert_non_null(filter);
14481468
assert_string_equal(filter, "rule99=<I>CN=Certificate Authority,O=IPA.DEVEL"
14491469
"<S>CN=ipa-devel.ipa.devel,O=IPA.DEVEL");
14501470
assert_non_null(domains);
@@ -1466,6 +1486,16 @@ static void test_sss_certmap_get_search_filter(void **state)
14661486
assert_string_equal(domains[0], "test.dom");
14671487
assert_null(domains[1]);
14681488

1489+
ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert_der),
1490+
sizeof(test_cert_der),
1491+
&filter, &domains);
1492+
assert_int_equal(ret, 0);
1493+
assert_non_null(filter);
1494+
assert_string_equal(filter, "rule98=userCertificate;binary=" TEST_CERT_BIN);
1495+
assert_non_null(domains);
1496+
assert_string_equal(domains[0], "test.dom");
1497+
assert_null(domains[1]);
1498+
14691499
ret = sss_certmap_add_rule(ctx, 97,
14701500
"KRB5:<ISSUER>CN=Certificate Authority,O=IPA.DEVEL",
14711501
"LDAP:rule97=<I>{issuer_dn!nss_x500}<S>{subject_dn}",
@@ -1476,6 +1506,17 @@ static void test_sss_certmap_get_search_filter(void **state)
14761506
&filter, &domains);
14771507
assert_int_equal(ret, 0);
14781508
assert_non_null(filter);
1509+
assert_string_equal(filter, "rule97=<I>O=IPA.DEVEL,CN=Certificate\\20Authority"
1510+
"<S>CN=ipa-devel.ipa.devel,O=IPA.DEVEL");
1511+
assert_non_null(domains);
1512+
assert_string_equal(domains[0], "test.dom");
1513+
assert_null(domains[1]);
1514+
1515+
ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert_der),
1516+
sizeof(test_cert_der),
1517+
&filter, &domains);
1518+
assert_int_equal(ret, 0);
1519+
assert_non_null(filter);
14791520
assert_string_equal(filter, "rule97=<I>O=IPA.DEVEL,CN=Certificate Authority"
14801521
"<S>CN=ipa-devel.ipa.devel,O=IPA.DEVEL");
14811522
assert_non_null(domains);
@@ -1492,6 +1533,17 @@ static void test_sss_certmap_get_search_filter(void **state)
14921533
&filter, &domains);
14931534
assert_int_equal(ret, 0);
14941535
assert_non_null(filter);
1536+
assert_string_equal(filter, "rule96=<I>O=IPA.DEVEL,CN=Certificate\\20Authority"
1537+
"<S>O=IPA.DEVEL,CN=ipa-devel.ipa.devel");
1538+
assert_non_null(domains);
1539+
assert_string_equal(domains[0], "test.dom");
1540+
assert_null(domains[1]);
1541+
1542+
ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert_der),
1543+
sizeof(test_cert_der),
1544+
&filter, &domains);
1545+
assert_int_equal(ret, 0);
1546+
assert_non_null(filter);
14951547
assert_string_equal(filter, "rule96=<I>O=IPA.DEVEL,CN=Certificate Authority"
14961548
"<S>O=IPA.DEVEL,CN=ipa-devel.ipa.devel");
14971549
assert_non_null(domains);
@@ -1510,6 +1562,14 @@ static void test_sss_certmap_get_search_filter(void **state)
15101562
assert_string_equal(filter, "(userCertificate;binary=" TEST_CERT_BIN ")");
15111563
assert_null(domains);
15121564

1565+
ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert_der),
1566+
sizeof(test_cert_der),
1567+
&filter, &domains);
1568+
assert_int_equal(ret, 0);
1569+
assert_non_null(filter);
1570+
assert_string_equal(filter, "(userCertificate;binary=" TEST_CERT_BIN ")");
1571+
assert_null(domains);
1572+
15131573
ret = sss_certmap_add_rule(ctx, 94,
15141574
"KRB5:<ISSUER>CN=Certificate Authority,O=IPA.DEVEL",
15151575
"LDAP:rule94=<I>{issuer_dn!ad_x500}<S>{subject_dn!ad_x500}",
@@ -1520,12 +1580,22 @@ static void test_sss_certmap_get_search_filter(void **state)
15201580
&filter, &domains);
15211581
assert_int_equal(ret, 0);
15221582
assert_non_null(filter);
1523-
assert_string_equal(filter, "rule94=<I>O=IPA.DEVEL,CN=Certificate Authority"
1583+
assert_string_equal(filter, "rule94=<I>O=IPA.DEVEL,CN=Certificate\\20Authority"
15241584
"<S>O=IPA.DEVEL,CN=ipa-devel.ipa.devel");
15251585
assert_non_null(domains);
15261586
assert_string_equal(domains[0], "test.dom");
15271587
assert_null(domains[1]);
15281588

1589+
ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert_der),
1590+
sizeof(test_cert_der),
1591+
&filter, &domains);
1592+
assert_int_equal(ret, 0);
1593+
assert_non_null(filter);
1594+
assert_string_equal(filter, "rule94=<I>O=IPA.DEVEL,CN=Certificate Authority"
1595+
"<S>O=IPA.DEVEL,CN=ipa-devel.ipa.devel");
1596+
assert_non_null(domains);
1597+
assert_string_equal(domains[0], "test.dom");
1598+
assert_null(domains[1]);
15291599

15301600
ret = sss_certmap_add_rule(ctx, 89, NULL,
15311601
"(rule89={subject_nt_principal})",
@@ -1539,6 +1609,14 @@ static void test_sss_certmap_get_search_filter(void **state)
15391609
assert_string_equal(filter, "(rule89=tu1@ad.devel)");
15401610
assert_null(domains);
15411611

1612+
ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert2_der),
1613+
sizeof(test_cert2_der),
1614+
&filter, &domains);
1615+
assert_int_equal(ret, 0);
1616+
assert_non_null(filter);
1617+
assert_string_equal(filter, "(rule89=tu1@ad.devel)");
1618+
assert_null(domains);
1619+
15421620
ret = sss_certmap_add_rule(ctx, 88, NULL,
15431621
"(rule88={subject_nt_principal.short_name})",
15441622
NULL);
@@ -1560,6 +1638,15 @@ static void test_sss_certmap_get_search_filter(void **state)
15601638
&filter, &domains);
15611639
assert_int_equal(ret, 0);
15621640
assert_non_null(filter);
1641+
assert_string_equal(filter, "rule87=<I>DC=devel,DC=ad,CN=ad-AD-SERVER-CA"
1642+
"<S>DC=devel,DC=ad,CN=Users,CN=t\\20u,E=test.user@email.domain");
1643+
assert_null(domains);
1644+
1645+
ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert2_der),
1646+
sizeof(test_cert2_der),
1647+
&filter, &domains);
1648+
assert_int_equal(ret, 0);
1649+
assert_non_null(filter);
15631650
assert_string_equal(filter, "rule87=<I>DC=devel,DC=ad,CN=ad-AD-SERVER-CA"
15641651
"<S>DC=devel,DC=ad,CN=Users,CN=t u,E=test.user@email.domain");
15651652
assert_null(domains);
@@ -1573,6 +1660,15 @@ static void test_sss_certmap_get_search_filter(void **state)
15731660
&filter, &domains);
15741661
assert_int_equal(ret, 0);
15751662
assert_non_null(filter);
1663+
assert_string_equal(filter, "rule86=<I>DC=devel,DC=ad,CN=ad-AD-SERVER-CA"
1664+
"<S>DC=devel,DC=ad,CN=Users,CN=t\\20u,E=test.user@email.domain");
1665+
assert_null(domains);
1666+
1667+
ret = sss_certmap_expand_mapping_rule(ctx, discard_const(test_cert2_der),
1668+
sizeof(test_cert2_der),
1669+
&filter, &domains);
1670+
assert_int_equal(ret, 0);
1671+
assert_non_null(filter);
15761672
assert_string_equal(filter, "rule86=<I>DC=devel,DC=ad,CN=ad-AD-SERVER-CA"
15771673
"<S>DC=devel,DC=ad,CN=Users,CN=t u,E=test.user@email.domain");
15781674
assert_null(domains);

0 commit comments

Comments
 (0)