Skip to content

Commit

Permalink
certmap: add LDAPU1 mapping rules
Browse files Browse the repository at this point in the history
Add mapping rule templates for the new discovered attributes, templates
for certificate hashes and templates to select individual DN components.
To avoid issues with older versions of the library the new templates
must use the prefix LDAPU1.

:feature: New mapping template for serial number, subject key id, SID,
          certificate hashes and DN components are added to
          libsss_certmap.

Resolves: #6403

(cherry picked from commit 1303c62)

Reviewed-by: Alexey Tikhonov <atikhono@redhat.com>
Reviewed-by: Justin Stephenson <jstephen@redhat.com>
  • Loading branch information
sumit-bose authored and alexey-tikhonov committed Dec 2, 2022
1 parent 8a6a874 commit 698d568
Show file tree
Hide file tree
Showing 5 changed files with 519 additions and 8 deletions.
1 change: 1 addition & 0 deletions Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -1983,6 +1983,7 @@ libsss_certmap_la_SOURCES = \
src/lib/certmap/sss_certmap_ldap_mapping.c \
src/lib/certmap/sss_cert_content_common.c \
src/util/util_ext.c \
src/util/strtonum.c \
src/util/cert/cert_common.c \
$(NULL)
libsss_certmap_la_CFLAGS = \
Expand Down
82 changes: 82 additions & 0 deletions src/lib/certmap/sss_cert_content_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,3 +197,85 @@ int rdn_list_2_dn_str(TALLOC_CTX *mem_ctx, const char *conversion,

return ret;
}

int rdn_list_2_component(TALLOC_CTX *mem_ctx, const char *conversion,
const char **rdn_list, char **result)
{
int ret;
char *sep;
char *attr_name = NULL;
int32_t number = 0;
char *res = NULL;
size_t rdn_count;
size_t idx;
int i;

ret = check_attr_name_and_or_number(mem_ctx, conversion, &attr_name, &number);
if (ret != 0) {
return ret;
}

for (rdn_count = 0; rdn_list[rdn_count] != NULL; rdn_count++);

if (abs(number) > rdn_count || rdn_count == 0) {
ret = EINVAL;
goto done;
}

if (number == 0 && attr_name != NULL) {
for (i = rdn_count-1; i >= 0; i--) {
sep = strchr(rdn_list[i], '=');
if (sep == NULL) {
ret = EINVAL;
goto done;
}
if (strlen(attr_name) == (sep - rdn_list[i])
&& strncasecmp(attr_name, rdn_list[i],
(sep - rdn_list[i])) == 0) {
res = talloc_strdup(mem_ctx, sep + 1);
break;
}
}
} else {
if (number == 0) {
idx = rdn_count - 1;
} else {
if (number > 0) {
idx = rdn_count - number;
} else {
idx = number * (-1) - 1;
}
}

sep = strchr(rdn_list[idx], '=');
if (sep == NULL) {
ret = EINVAL;
goto done;
}
if (attr_name != NULL) {
if (strlen(attr_name) != (sep - rdn_list[idx])
|| strncasecmp(attr_name, rdn_list[idx],
(sep - rdn_list[idx])) != 0) {
ret = EINVAL;
goto done;
}
}
res = talloc_strdup(mem_ctx, sep + 1);
}

if (res == NULL) {
ret = EIO;
goto done;
}

ret = 0;

done:
talloc_free(attr_name);

if (ret == 0) {
*result = res;
}

return ret;
}
141 changes: 137 additions & 4 deletions src/lib/certmap/sss_certmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -180,11 +180,19 @@ static int parse_mapping_rule(struct sss_certmap_ctx *ctx,
}

if (type == NULL || strcmp(type, "LDAP") == 0) {
ctx->mapv = mapv_ldap;
ret = parse_ldap_mapping_rule(ctx, rule_start, parsed_mapping_rule);
if (ret != EOK) {
CM_DEBUG(ctx, "Failed to parse LDAP mapping rule.");
goto done;
}
} else if (strcmp(type, "LDAPU1") == 0) {
ctx->mapv = mapv_ldapu1;
ret = parse_ldap_mapping_rule(ctx, rule_start, parsed_mapping_rule);
if (ret != EOK) {
CM_DEBUG(ctx, "Failed to parse LDAPU1 mapping rule.");
goto done;
}
} else {
CM_DEBUG(ctx, "Unsupported mapping rule type.");
ret = ESRCH;
Expand Down Expand Up @@ -328,6 +336,10 @@ static int expand_cert(struct sss_certmap_ctx *ctx,
{
int ret;
char *tmp_str = NULL;
const char *dgst = NULL;
bool upper = false;
bool colon = false;
bool reverse = false;

if (parsed_template->conversion == NULL
|| strcmp(parsed_template->conversion, "bin") == 0) {
Expand All @@ -345,6 +357,15 @@ static int expand_cert(struct sss_certmap_ctx *ctx,
ret = ENOMEM;
goto done;
}
} else if (check_digest_conversion(parsed_template->conversion,
ctx->digest_list, &dgst,
&upper, &colon, &reverse) == 0) {
ret = get_hash(ctx, cert_content->cert_der, cert_content->cert_der_size,
dgst, upper, colon, reverse, &tmp_str);
if (ret != 0) {
CM_DEBUG(ctx, "Failed to generate digest of certificate.");
goto done;
}
} else {
CM_DEBUG(ctx, "Unsupported conversion.");
ret = EINVAL;
Expand All @@ -363,6 +384,69 @@ static int expand_cert(struct sss_certmap_ctx *ctx,
return ret;
}

static int expand_bin_number_array(struct sss_certmap_ctx *ctx,
struct parsed_template *parsed_template,
uint8_t *bin_number,
size_t bin_number_size,
const char *bin_number_dec_str,
char **expanded)
{
int ret;
char *tmp_str = NULL;
bool dec = false;
bool upper = false;
bool colon = false;
bool reverse = false;

if (bin_number == NULL || bin_number_size == 0) {
CM_DEBUG(ctx, "Missing data for conversion.");
ret = ENOENT;
goto done;
}

ret = check_hex_conversion(parsed_template->conversion, true,
&dec, &upper, &colon, &reverse);
if (ret != 0) {
CM_DEBUG(ctx, "Unsupported conversion.");
ret = EINVAL;
goto done;
}

if (dec) {
if (bin_number_dec_str != NULL) {
tmp_str = talloc_strdup(ctx, bin_number_dec_str);
if (tmp_str == NULL) {
CM_DEBUG(ctx, "Failed to copy binary number string.");
ret = ENOMEM;
goto done;
}
ret = 0;
} else {
CM_DEBUG(ctx, "Missing string for 'dec' conversion.");
ret = ENOENT;
goto done;
}
} else {
ret = bin_to_hex(ctx, upper, colon, reverse,
bin_number, bin_number_size, &tmp_str);
}
if (ret != 0) {
CM_DEBUG(ctx, "%s conversion failed.", parsed_template->conversion);
goto done;
}

ret = 0;

done:
if (ret == 0) {
*expanded = tmp_str;
} else {
talloc_free(tmp_str);
}

return ret;
}

static int expand_san_blob(struct sss_certmap_ctx *ctx, enum san_opt san_opt,
struct san_list *san_list, char **expanded)
{
Expand Down Expand Up @@ -490,6 +574,34 @@ static int expand_san(struct sss_certmap_ctx *ctx,
return ret;
}

static int expand_sid(struct sss_certmap_ctx *ctx, const char *attr_name,
const char *sid, char **expanded)
{
char *exp;
char *sep;

if (attr_name == NULL) {
exp = talloc_strdup(ctx, sid);
} else if (strcasecmp(attr_name, "rid") == 0) {
sep = strrchr(sid, '-');
if (sep == NULL || sep[1] == '\0') {
CM_DEBUG(ctx, "Unsupported SID string [%s].", sid);
return EINVAL;
}
exp = talloc_strdup(ctx, sep+1);
} else {
CM_DEBUG(ctx, "Unsupported attribute name [%s].", attr_name);
return EINVAL;
}

if (exp == NULL) {
return ENOMEM;
}

*expanded = exp;
return 0;
}

static int expand_template(struct sss_certmap_ctx *ctx,
struct parsed_template *parsed_template,
struct sss_cert_content *cert_content,
Expand All @@ -506,12 +618,32 @@ static int expand_template(struct sss_certmap_ctx *ctx,
} else if (strcmp("subject_dn", parsed_template->name) == 0) {
ret = rdn_list_2_dn_str(ctx, parsed_template->conversion,
cert_content->subject_rdn_list, &exp);
} else if (strcmp("subject_key_id", parsed_template->name) == 0) {
ret = expand_bin_number_array(ctx, parsed_template,
cert_content->subject_key_id,
cert_content->subject_key_id_size,
NULL, &exp);
} else if (strcmp("issuer_dn_component", parsed_template->name) == 0) {
ret = rdn_list_2_component(ctx, parsed_template->attr_name,
cert_content->issuer_rdn_list, &exp);
} else if (strcmp("subject_dn_component", parsed_template->name) == 0) {
ret = rdn_list_2_component(ctx, parsed_template->attr_name,
cert_content->subject_rdn_list, &exp);
} else if (strncmp("subject_", parsed_template->name, 8) == 0) {
ret = expand_san(ctx, parsed_template, cert_content->san_list, &exp);
} else if (strcmp("cert", parsed_template->name) == 0) {
/* cert blob is already sanitized */
sanitize = false;
ret = expand_cert(ctx, parsed_template, cert_content, &exp);
} else if (strcmp("serial_number", parsed_template->name) == 0) {
ret = expand_bin_number_array(ctx, parsed_template,
cert_content->serial_number,
cert_content->serial_number_size,
cert_content->serial_number_dec_str,
&exp);
} else if (strcmp("sid", parsed_template->name) == 0) {
ret = expand_sid(ctx, parsed_template->attr_name,
cert_content->sid_ext, &exp);
} else {
CM_DEBUG(ctx, "Unsupported template name.");
ret = EINVAL;
Expand Down Expand Up @@ -1046,6 +1178,7 @@ static int sss_cert_dump_content(TALLOC_CTX *mem_ctx,
struct sss_certmap_ctx *ctx = NULL;
char *expanded = NULL;
int ret;
int ret2;
char *b64 = NULL;
const char *eku_str = NULL;
TALLOC_CTX *tmp_ctx = NULL;
Expand Down Expand Up @@ -1106,9 +1239,9 @@ static int sss_cert_dump_content(TALLOC_CTX *mem_ctx,
}

if (c->serial_number_size != 0) {
ret = bin_to_hex(out, false, true, false, c->serial_number,
ret2 = bin_to_hex(out, false, true, false, c->serial_number,
c->serial_number_size, &hex);
if (ret == 0) {
if (ret2 == 0) {
out = talloc_asprintf_append(out, "Serial Number: %s (%s)\n", hex,
c->serial_number_dec_str);
talloc_free(hex);
Expand All @@ -1122,9 +1255,9 @@ static int sss_cert_dump_content(TALLOC_CTX *mem_ctx,
if (out == NULL) goto done;

if (c->subject_key_id_size != 0) {
ret = bin_to_hex(out, false, true, false, c->subject_key_id,
ret2 = bin_to_hex(out, false, true, false, c->subject_key_id,
c->subject_key_id_size, &hex);
if (ret == 0) {
if (ret2 == 0) {
out = talloc_asprintf_append(out, "Subject Key ID: %s\n", hex);
talloc_free(hex);
} else {
Expand Down
19 changes: 19 additions & 0 deletions src/lib/certmap/sss_certmap_int.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,11 +136,17 @@ struct priority_list {
struct priority_list *next;
};

enum mapping_rule_version {
mapv_ldap = 0,
mapv_ldapu1
};

struct sss_certmap_ctx {
struct priority_list *prio_list;
sss_certmap_ext_debug *debug;
void *debug_priv;
struct ldap_mapping_rule *default_mapping_rule;
enum mapping_rule_version mapv;
const char **digest_list;
};

Expand Down Expand Up @@ -223,10 +229,20 @@ int parse_krb5_match_rule(struct sss_certmap_ctx *ctx,
const char *rule_start,
struct krb5_match_rule **match_rule);

int check_hex_conversion(const char *inp, bool dec_allowed, bool *_dec,
bool *_upper, bool *_colon, bool *_reverse);

int check_digest_conversion(const char *inp, const char **digest_list,
const char **_dgst, bool *_upper, bool *_colon,
bool *_reverse);

int parse_ldap_mapping_rule(struct sss_certmap_ctx *ctx,
const char *rule_start,
struct ldap_mapping_rule **mapping_rule);

int check_attr_name_and_or_number(TALLOC_CTX *mem_ctx, const char *inp,
char **_attr_name, int32_t *_number);

int get_short_name(TALLOC_CTX *mem_ctx, const char *full_name,
char delim, char **short_name);

Expand All @@ -240,6 +256,9 @@ int add_principal_to_san_list(TALLOC_CTX *mem_ctx, enum san_opt san_opt,
int rdn_list_2_dn_str(TALLOC_CTX *mem_ctx, const char *conversion,
const char **rdn_list, char **result);

int rdn_list_2_component(TALLOC_CTX *mem_ctx, const char *conversion,
const char **rdn_list, char **result);

int get_digest_list(TALLOC_CTX *mem_ctx, const char ***digest_list);

int get_hash(TALLOC_CTX *mem_ctx, const uint8_t *blob, size_t blob_size,
Expand Down
Loading

0 comments on commit 698d568

Please sign in to comment.