Add ability to store extended principal attributes in LDAP

A careful code review was undertaken, and it was determined
that the best way to store the extended attributes was in a
native ASN1 encoded field.  LDAP does not understand the
SEQUENCE of SEQUENCE structures used extensively throughout
the extended attributes structure, and there was already a
precedent set for storing the krb5Key data in a native ASN1
encoded field.
This commit is contained in:
Timothy Pearson
2015-09-26 16:23:55 -05:00
parent bb14c02e12
commit f5f76ee72c
2 changed files with 63 additions and 1 deletions

@@ -2,6 +2,7 @@
* Copyright (c) 1999-2001, 2003, PADL Software Pty Ltd.
* Copyright (c) 2004, Andrew Bartlett.
* Copyright (c) 2003 - 2008, Kungliga Tekniska Högskolan.
* Copyright (c) 2015, Timothy Pearson.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -91,6 +92,7 @@ static char * krb5kdcentry_attrs[] = {
"krb5PasswordEnd",
"krb5PrincipalName",
"krb5PrincipalRealm",
"krb5ExtendedAttributes",
"krb5ValidEnd",
"krb5ValidStart",
"modifiersName",
@@ -516,6 +518,33 @@ LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent,
goto out;
}
if (is_heimdal_entry && ent->entry.extensions) {
if (!is_new_entry) {
vals = ldap_get_values_len(HDB2LDAP(db), msg, "krb5ExtendedAttributes");
if (vals) {
ldap_value_free_len(vals);
ret = LDAP_addmod(&mods, LDAP_MOD_DELETE, "krb5ExtendedAttributes", NULL);
if (ret)
goto out;
}
}
for (i = 0; i < ent->entry.extensions->len; i++) {
unsigned char *buf;
size_t size, sz = 0;
ASN1_MALLOC_ENCODE(HDB_extension, buf, size, &ent->entry.extensions->val[i], &sz, ret);
if (ret)
goto out;
if (size != sz)
krb5_abortx(context, "internal error in ASN.1 encoder");
ret = LDAP_addmod_len(&mods, LDAP_MOD_ADD, "krb5ExtendedAttributes", buf, sz);
if (ret)
goto out;
}
}
if (is_heimdal_entry && ent->entry.valid_start) {
if (orig.entry.valid_end == NULL
|| (*(ent->entry.valid_start) != *(orig.entry.valid_start))) {
@@ -981,6 +1010,7 @@ LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg,
char *unparsed_name = NULL, *dn = NULL, *ntPasswordIN = NULL;
char *samba_acct_flags = NULL;
struct berval **keys;
struct berval **extensions;
struct berval **vals;
int tmp, tmp_time, i, ret, have_arcfour = 0;
@@ -1048,6 +1078,33 @@ LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg,
#endif
}
extensions = ldap_get_values_len(HDB2LDAP(db), msg, "krb5ExtendedAttributes");
if (extensions != NULL) {
size_t l;
ent->entry.extensions = malloc(sizeof(*(ent->entry.extensions)));
if (ent->entry.etypes == NULL) {
ret = krb5_enomem(context);
goto out;
}
ent->entry.extensions->len = ldap_count_values_len(extensions);
ent->entry.extensions->val = (HDB_extension *) calloc(ent->entry.extensions->len, sizeof(HDB_extension));
if (ent->entry.extensions->val == NULL) {
ent->entry.extensions->len = 0;
ret = krb5_enomem(context);
goto out;
}
for (i = 0; i < ent->entry.extensions->len; i++) {
ret = decode_HDB_extension((unsigned char *) extensions[i]->bv_val,
(size_t) extensions[i]->bv_len, &ent->entry.extensions->val[i], &l);
if (ret)
krb5_set_error_message(context, ret, "decode_HDB_extension failed");
}
ber_bvecfree(extensions);
} else {
ent->entry.extensions = NULL;
}
vals = ldap_get_values_len(HDB2LDAP(db), msg, "krb5EncryptionType");
if (vals != NULL) {
ent->entry.etypes = malloc(sizeof(*(ent->entry.etypes)));

@@ -113,6 +113,11 @@ attributetype ( 1.3.6.1.4.1.5322.10.1.12
EQUALITY octetStringMatch
SYNTAX 1.3.6.1.4.1.1466.115.121.1.40{128} )
attributetype ( 1.3.6.1.4.1.5322.10.1.13
NAME 'krb5ExtendedAttributes'
DESC 'Encoded ASN1 HDB Extension Attributes as an octet string'
SYNTAX 1.3.6.1.4.1.1466.115.121.1.5 )
# Object class definitions
objectclass ( 1.3.6.1.4.1.5322.10.2.1
@@ -129,7 +134,7 @@ objectclass ( 1.3.6.1.4.1.5322.10.2.2
MUST ( krb5KeyVersionNumber )
MAY ( krb5ValidStart $ krb5ValidEnd $ krb5PasswordEnd $
krb5MaxLife $ krb5MaxRenew $ krb5KDCFlags $
krb5EncryptionType $ krb5Key ) )
krb5EncryptionType $ krb5Key $ krb5ExtendedAttributes ) )
objectclass ( 1.3.6.1.4.1.5322.10.2.3
NAME 'krb5Realm'