From f5f76ee72c5df3533218fb88c7c9172ba9ee64ba Mon Sep 17 00:00:00 2001 From: Timothy Pearson Date: Sat, 26 Sep 2015 16:23:55 -0500 Subject: [PATCH] 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. --- lib/hdb/hdb-ldap.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++ lib/hdb/hdb.schema | 7 +++++- 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/lib/hdb/hdb-ldap.c b/lib/hdb/hdb-ldap.c index caf892eeb..995131b5f 100644 --- a/lib/hdb/hdb-ldap.c +++ b/lib/hdb/hdb-ldap.c @@ -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))); diff --git a/lib/hdb/hdb.schema b/lib/hdb/hdb.schema index 57303900d..f9fb08098 100644 --- a/lib/hdb/hdb.schema +++ b/lib/hdb/hdb.schema @@ -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'