15e9cd1aeSAssar Westerlund /* 2c19800e8SDoug Rabson * Copyright (c) 1999-2001, 2003, PADL Software Pty Ltd. 3c19800e8SDoug Rabson * Copyright (c) 2004, Andrew Bartlett. 4ae771770SStanislav Sedov * Copyright (c) 2003 - 2008, Kungliga Tekniska Högskolan. 55e9cd1aeSAssar Westerlund * All rights reserved. 65e9cd1aeSAssar Westerlund * 75e9cd1aeSAssar Westerlund * Redistribution and use in source and binary forms, with or without 85e9cd1aeSAssar Westerlund * modification, are permitted provided that the following conditions 95e9cd1aeSAssar Westerlund * are met: 105e9cd1aeSAssar Westerlund * 115e9cd1aeSAssar Westerlund * 1. Redistributions of source code must retain the above copyright 125e9cd1aeSAssar Westerlund * notice, this list of conditions and the following disclaimer. 135e9cd1aeSAssar Westerlund * 145e9cd1aeSAssar Westerlund * 2. Redistributions in binary form must reproduce the above copyright 155e9cd1aeSAssar Westerlund * notice, this list of conditions and the following disclaimer in the 165e9cd1aeSAssar Westerlund * documentation and/or other materials provided with the distribution. 175e9cd1aeSAssar Westerlund * 185e9cd1aeSAssar Westerlund * 3. Neither the name of PADL Software nor the names of its contributors 195e9cd1aeSAssar Westerlund * may be used to endorse or promote products derived from this software 205e9cd1aeSAssar Westerlund * without specific prior written permission. 215e9cd1aeSAssar Westerlund * 225e9cd1aeSAssar Westerlund * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND 235e9cd1aeSAssar Westerlund * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 245e9cd1aeSAssar Westerlund * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 255e9cd1aeSAssar Westerlund * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE 265e9cd1aeSAssar Westerlund * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 275e9cd1aeSAssar Westerlund * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 285e9cd1aeSAssar Westerlund * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 295e9cd1aeSAssar Westerlund * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 305e9cd1aeSAssar Westerlund * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 315e9cd1aeSAssar Westerlund * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 325e9cd1aeSAssar Westerlund * SUCH DAMAGE. 335e9cd1aeSAssar Westerlund */ 345e9cd1aeSAssar Westerlund 355e9cd1aeSAssar Westerlund #include "hdb_locl.h" 365e9cd1aeSAssar Westerlund 375e9cd1aeSAssar Westerlund #ifdef OPENLDAP 385e9cd1aeSAssar Westerlund 395e9cd1aeSAssar Westerlund #include <lber.h> 40adb0ddaeSAssar Westerlund #include <ldap.h> 415e9cd1aeSAssar Westerlund #include <sys/un.h> 42c19800e8SDoug Rabson #include <hex.h> 435e9cd1aeSAssar Westerlund 44c19800e8SDoug Rabson static krb5_error_code LDAP__connect(krb5_context context, HDB *); 45c19800e8SDoug Rabson static krb5_error_code LDAP_close(krb5_context context, HDB *); 465e9cd1aeSAssar Westerlund 47*a0d7d68aSCy Schubert static krb5_error_code hdb_ldap_create(krb5_context context, HDB **, const char *); 48*a0d7d68aSCy Schubert static krb5_error_code hdb_ldapi_create(krb5_context context, HDB **, const char *); 49*a0d7d68aSCy Schubert 505e9cd1aeSAssar Westerlund static krb5_error_code 515e9cd1aeSAssar Westerlund LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg, 52ae771770SStanislav Sedov int flags, hdb_entry_ex * ent); 535e9cd1aeSAssar Westerlund 54c19800e8SDoug Rabson static const char *default_structural_object = "account"; 55c19800e8SDoug Rabson static char *structural_object; 56c19800e8SDoug Rabson static krb5_boolean samba_forwardable; 57c19800e8SDoug Rabson 58c19800e8SDoug Rabson struct hdbldapdb { 59c19800e8SDoug Rabson LDAP *h_lp; 60c19800e8SDoug Rabson int h_msgid; 61c19800e8SDoug Rabson char *h_base; 62c19800e8SDoug Rabson char *h_url; 63c19800e8SDoug Rabson char *h_createbase; 64c19800e8SDoug Rabson }; 65c19800e8SDoug Rabson 66c19800e8SDoug Rabson #define HDB2LDAP(db) (((struct hdbldapdb *)(db)->hdb_db)->h_lp) 67c19800e8SDoug Rabson #define HDB2MSGID(db) (((struct hdbldapdb *)(db)->hdb_db)->h_msgid) 68c19800e8SDoug Rabson #define HDBSETMSGID(db,msgid) \ 69c19800e8SDoug Rabson do { ((struct hdbldapdb *)(db)->hdb_db)->h_msgid = msgid; } while(0) 70c19800e8SDoug Rabson #define HDB2BASE(dn) (((struct hdbldapdb *)(db)->hdb_db)->h_base) 71c19800e8SDoug Rabson #define HDB2URL(dn) (((struct hdbldapdb *)(db)->hdb_db)->h_url) 72c19800e8SDoug Rabson #define HDB2CREATE(db) (((struct hdbldapdb *)(db)->hdb_db)->h_createbase) 73c19800e8SDoug Rabson 74c19800e8SDoug Rabson /* 75c19800e8SDoug Rabson * 76c19800e8SDoug Rabson */ 77c19800e8SDoug Rabson 78c19800e8SDoug Rabson static char * krb5kdcentry_attrs[] = { 79c19800e8SDoug Rabson "cn", 80c19800e8SDoug Rabson "createTimestamp", 81c19800e8SDoug Rabson "creatorsName", 82c19800e8SDoug Rabson "krb5EncryptionType", 83c19800e8SDoug Rabson "krb5KDCFlags", 84c19800e8SDoug Rabson "krb5Key", 85c19800e8SDoug Rabson "krb5KeyVersionNumber", 86c19800e8SDoug Rabson "krb5MaxLife", 87c19800e8SDoug Rabson "krb5MaxRenew", 88c19800e8SDoug Rabson "krb5PasswordEnd", 89c19800e8SDoug Rabson "krb5PrincipalName", 90c19800e8SDoug Rabson "krb5PrincipalRealm", 91c19800e8SDoug Rabson "krb5ValidEnd", 92c19800e8SDoug Rabson "krb5ValidStart", 93c19800e8SDoug Rabson "modifiersName", 94c19800e8SDoug Rabson "modifyTimestamp", 95c19800e8SDoug Rabson "objectClass", 96c19800e8SDoug Rabson "sambaAcctFlags", 97c19800e8SDoug Rabson "sambaKickoffTime", 98c19800e8SDoug Rabson "sambaNTPassword", 99c19800e8SDoug Rabson "sambaPwdLastSet", 100c19800e8SDoug Rabson "sambaPwdMustChange", 101c19800e8SDoug Rabson "uid", 1025e9cd1aeSAssar Westerlund NULL 1035e9cd1aeSAssar Westerlund }; 1045e9cd1aeSAssar Westerlund 105c19800e8SDoug Rabson static char *krb5principal_attrs[] = { 106c19800e8SDoug Rabson "cn", 107c19800e8SDoug Rabson "createTimestamp", 108c19800e8SDoug Rabson "creatorsName", 109c19800e8SDoug Rabson "krb5PrincipalName", 110c19800e8SDoug Rabson "krb5PrincipalRealm", 111c19800e8SDoug Rabson "modifiersName", 112c19800e8SDoug Rabson "modifyTimestamp", 113c19800e8SDoug Rabson "objectClass", 114c19800e8SDoug Rabson "uid", 1155e9cd1aeSAssar Westerlund NULL 1165e9cd1aeSAssar Westerlund }; 1175e9cd1aeSAssar Westerlund 118c19800e8SDoug Rabson static int 119c19800e8SDoug Rabson LDAP_no_size_limit(krb5_context context, LDAP *lp) 120c19800e8SDoug Rabson { 121c19800e8SDoug Rabson int ret, limit = LDAP_NO_LIMIT; 122c19800e8SDoug Rabson 123c19800e8SDoug Rabson ret = ldap_set_option(lp, LDAP_OPT_SIZELIMIT, (const void *)&limit); 124c19800e8SDoug Rabson if (ret != LDAP_SUCCESS) { 125ae771770SStanislav Sedov krb5_set_error_message(context, HDB_ERR_BADVERSION, 126ae771770SStanislav Sedov "ldap_set_option: %s", 127c19800e8SDoug Rabson ldap_err2string(ret)); 128c19800e8SDoug Rabson return HDB_ERR_BADVERSION; 129c19800e8SDoug Rabson } 130c19800e8SDoug Rabson return 0; 131c19800e8SDoug Rabson } 132c19800e8SDoug Rabson 133c19800e8SDoug Rabson static int 134c19800e8SDoug Rabson check_ldap(krb5_context context, HDB *db, int ret) 135c19800e8SDoug Rabson { 136c19800e8SDoug Rabson switch (ret) { 137c19800e8SDoug Rabson case LDAP_SUCCESS: 138c19800e8SDoug Rabson return 0; 139c19800e8SDoug Rabson case LDAP_SERVER_DOWN: 140c19800e8SDoug Rabson LDAP_close(context, db); 141c19800e8SDoug Rabson return 1; 142c19800e8SDoug Rabson default: 143c19800e8SDoug Rabson return 1; 144c19800e8SDoug Rabson } 145c19800e8SDoug Rabson } 146c19800e8SDoug Rabson 1475e9cd1aeSAssar Westerlund static krb5_error_code 1481c43270aSJacques Vidrine LDAP__setmod(LDAPMod *** modlist, int modop, const char *attribute, 1491c43270aSJacques Vidrine int *pIndex) 1505e9cd1aeSAssar Westerlund { 1511c43270aSJacques Vidrine int cMods; 1525e9cd1aeSAssar Westerlund 1531c43270aSJacques Vidrine if (*modlist == NULL) { 1541c43270aSJacques Vidrine *modlist = (LDAPMod **)ber_memcalloc(1, sizeof(LDAPMod *)); 155c19800e8SDoug Rabson if (*modlist == NULL) 1565e9cd1aeSAssar Westerlund return ENOMEM; 1575e9cd1aeSAssar Westerlund } 1585e9cd1aeSAssar Westerlund 1591c43270aSJacques Vidrine for (cMods = 0; (*modlist)[cMods] != NULL; cMods++) { 1601c43270aSJacques Vidrine if ((*modlist)[cMods]->mod_op == modop && 1611c43270aSJacques Vidrine strcasecmp((*modlist)[cMods]->mod_type, attribute) == 0) { 1625e9cd1aeSAssar Westerlund break; 1635e9cd1aeSAssar Westerlund } 1645e9cd1aeSAssar Westerlund } 1655e9cd1aeSAssar Westerlund 1661c43270aSJacques Vidrine *pIndex = cMods; 1671c43270aSJacques Vidrine 1681c43270aSJacques Vidrine if ((*modlist)[cMods] == NULL) { 1691c43270aSJacques Vidrine LDAPMod *mod; 1701c43270aSJacques Vidrine 1711c43270aSJacques Vidrine *modlist = (LDAPMod **)ber_memrealloc(*modlist, 1721c43270aSJacques Vidrine (cMods + 2) * sizeof(LDAPMod *)); 173c19800e8SDoug Rabson if (*modlist == NULL) 1745e9cd1aeSAssar Westerlund return ENOMEM; 175c19800e8SDoug Rabson 1761c43270aSJacques Vidrine (*modlist)[cMods] = (LDAPMod *)ber_memalloc(sizeof(LDAPMod)); 177c19800e8SDoug Rabson if ((*modlist)[cMods] == NULL) 1785e9cd1aeSAssar Westerlund return ENOMEM; 1791c43270aSJacques Vidrine 1801c43270aSJacques Vidrine mod = (*modlist)[cMods]; 1811c43270aSJacques Vidrine mod->mod_op = modop; 1821c43270aSJacques Vidrine mod->mod_type = ber_strdup(attribute); 1831c43270aSJacques Vidrine if (mod->mod_type == NULL) { 1841c43270aSJacques Vidrine ber_memfree(mod); 1851c43270aSJacques Vidrine (*modlist)[cMods] = NULL; 1865e9cd1aeSAssar Westerlund return ENOMEM; 1875e9cd1aeSAssar Westerlund } 1881c43270aSJacques Vidrine 1891c43270aSJacques Vidrine if (modop & LDAP_MOD_BVALUES) { 1901c43270aSJacques Vidrine mod->mod_bvalues = NULL; 1911c43270aSJacques Vidrine } else { 1921c43270aSJacques Vidrine mod->mod_values = NULL; 1931c43270aSJacques Vidrine } 1941c43270aSJacques Vidrine 1951c43270aSJacques Vidrine (*modlist)[cMods + 1] = NULL; 1961c43270aSJacques Vidrine } 1971c43270aSJacques Vidrine 1981c43270aSJacques Vidrine return 0; 1991c43270aSJacques Vidrine } 2001c43270aSJacques Vidrine 2011c43270aSJacques Vidrine static krb5_error_code 2021c43270aSJacques Vidrine LDAP_addmod_len(LDAPMod *** modlist, int modop, const char *attribute, 2031c43270aSJacques Vidrine unsigned char *value, size_t len) 2041c43270aSJacques Vidrine { 2051c43270aSJacques Vidrine krb5_error_code ret; 206c19800e8SDoug Rabson int cMods, i = 0; 2071c43270aSJacques Vidrine 2081c43270aSJacques Vidrine ret = LDAP__setmod(modlist, modop | LDAP_MOD_BVALUES, attribute, &cMods); 209c19800e8SDoug Rabson if (ret) 2101c43270aSJacques Vidrine return ret; 2115e9cd1aeSAssar Westerlund 2125e9cd1aeSAssar Westerlund if (value != NULL) { 213c19800e8SDoug Rabson struct berval **bv; 2141c43270aSJacques Vidrine 215c19800e8SDoug Rabson bv = (*modlist)[cMods]->mod_bvalues; 216c19800e8SDoug Rabson if (bv != NULL) { 217c19800e8SDoug Rabson for (i = 0; bv[i] != NULL; i++) 2181c43270aSJacques Vidrine ; 219c19800e8SDoug Rabson bv = ber_memrealloc(bv, (i + 2) * sizeof(*bv)); 220c19800e8SDoug Rabson } else 221c19800e8SDoug Rabson bv = ber_memalloc(2 * sizeof(*bv)); 222c19800e8SDoug Rabson if (bv == NULL) 2235e9cd1aeSAssar Westerlund return ENOMEM; 224c19800e8SDoug Rabson 225c19800e8SDoug Rabson (*modlist)[cMods]->mod_bvalues = bv; 226c19800e8SDoug Rabson 227ae771770SStanislav Sedov bv[i] = ber_memalloc(sizeof(**bv));; 228c19800e8SDoug Rabson if (bv[i] == NULL) 2295e9cd1aeSAssar Westerlund return ENOMEM; 2301c43270aSJacques Vidrine 231c19800e8SDoug Rabson bv[i]->bv_val = (void *)value; 232c19800e8SDoug Rabson bv[i]->bv_len = len; 2331c43270aSJacques Vidrine 234c19800e8SDoug Rabson bv[i + 1] = NULL; 2355e9cd1aeSAssar Westerlund } 2361c43270aSJacques Vidrine 2375e9cd1aeSAssar Westerlund return 0; 2385e9cd1aeSAssar Westerlund } 2395e9cd1aeSAssar Westerlund 2405e9cd1aeSAssar Westerlund static krb5_error_code 2415e9cd1aeSAssar Westerlund LDAP_addmod(LDAPMod *** modlist, int modop, const char *attribute, 2425e9cd1aeSAssar Westerlund const char *value) 2435e9cd1aeSAssar Westerlund { 244c19800e8SDoug Rabson int cMods, i = 0; 2451c43270aSJacques Vidrine krb5_error_code ret; 2465e9cd1aeSAssar Westerlund 2471c43270aSJacques Vidrine ret = LDAP__setmod(modlist, modop, attribute, &cMods); 248c19800e8SDoug Rabson if (ret) 2491c43270aSJacques Vidrine return ret; 2505e9cd1aeSAssar Westerlund 2515e9cd1aeSAssar Westerlund if (value != NULL) { 252c19800e8SDoug Rabson char **bv; 2531c43270aSJacques Vidrine 254c19800e8SDoug Rabson bv = (*modlist)[cMods]->mod_values; 255c19800e8SDoug Rabson if (bv != NULL) { 256c19800e8SDoug Rabson for (i = 0; bv[i] != NULL; i++) 2571c43270aSJacques Vidrine ; 258c19800e8SDoug Rabson bv = ber_memrealloc(bv, (i + 2) * sizeof(*bv)); 259c19800e8SDoug Rabson } else 260c19800e8SDoug Rabson bv = ber_memalloc(2 * sizeof(*bv)); 261c19800e8SDoug Rabson if (bv == NULL) 2625e9cd1aeSAssar Westerlund return ENOMEM; 263c19800e8SDoug Rabson 264c19800e8SDoug Rabson (*modlist)[cMods]->mod_values = bv; 265c19800e8SDoug Rabson 266c19800e8SDoug Rabson bv[i] = ber_strdup(value); 267c19800e8SDoug Rabson if (bv[i] == NULL) 2685e9cd1aeSAssar Westerlund return ENOMEM; 269c19800e8SDoug Rabson 270c19800e8SDoug Rabson bv[i + 1] = NULL; 2715e9cd1aeSAssar Westerlund } 2721c43270aSJacques Vidrine 2735e9cd1aeSAssar Westerlund return 0; 2745e9cd1aeSAssar Westerlund } 2755e9cd1aeSAssar Westerlund 2765e9cd1aeSAssar Westerlund static krb5_error_code 2775e9cd1aeSAssar Westerlund LDAP_addmod_generalized_time(LDAPMod *** mods, int modop, 2785e9cd1aeSAssar Westerlund const char *attribute, KerberosTime * time) 2795e9cd1aeSAssar Westerlund { 2805e9cd1aeSAssar Westerlund char buf[22]; 2815e9cd1aeSAssar Westerlund struct tm *tm; 2825e9cd1aeSAssar Westerlund 2835e9cd1aeSAssar Westerlund /* XXX not threadsafe */ 2845e9cd1aeSAssar Westerlund tm = gmtime(time); 2855e9cd1aeSAssar Westerlund strftime(buf, sizeof(buf), "%Y%m%d%H%M%SZ", tm); 2865e9cd1aeSAssar Westerlund 2875e9cd1aeSAssar Westerlund return LDAP_addmod(mods, modop, attribute, buf); 2885e9cd1aeSAssar Westerlund } 2895e9cd1aeSAssar Westerlund 2905e9cd1aeSAssar Westerlund static krb5_error_code 291c19800e8SDoug Rabson LDAP_addmod_integer(krb5_context context, 292c19800e8SDoug Rabson LDAPMod *** mods, int modop, 293c19800e8SDoug Rabson const char *attribute, unsigned long l) 294c19800e8SDoug Rabson { 295c19800e8SDoug Rabson krb5_error_code ret; 296c19800e8SDoug Rabson char *buf; 297c19800e8SDoug Rabson 298c19800e8SDoug Rabson ret = asprintf(&buf, "%ld", l); 299c19800e8SDoug Rabson if (ret < 0) { 300ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, 301ae771770SStanislav Sedov "asprintf: out of memory:"); 302ae771770SStanislav Sedov return ENOMEM; 303c19800e8SDoug Rabson } 304c19800e8SDoug Rabson ret = LDAP_addmod(mods, modop, attribute, buf); 305c19800e8SDoug Rabson free (buf); 306c19800e8SDoug Rabson return ret; 307c19800e8SDoug Rabson } 308c19800e8SDoug Rabson 309c19800e8SDoug Rabson static krb5_error_code 3105e9cd1aeSAssar Westerlund LDAP_get_string_value(HDB * db, LDAPMessage * entry, 3115e9cd1aeSAssar Westerlund const char *attribute, char **ptr) 3125e9cd1aeSAssar Westerlund { 313ae771770SStanislav Sedov struct berval **vals; 3145e9cd1aeSAssar Westerlund 315ae771770SStanislav Sedov vals = ldap_get_values_len(HDB2LDAP(db), entry, attribute); 316ae771770SStanislav Sedov if (vals == NULL || vals[0] == NULL) { 317c19800e8SDoug Rabson *ptr = NULL; 3185e9cd1aeSAssar Westerlund return HDB_ERR_NOENTRY; 3195e9cd1aeSAssar Westerlund } 320c19800e8SDoug Rabson 321ae771770SStanislav Sedov *ptr = malloc(vals[0]->bv_len + 1); 322ae771770SStanislav Sedov if (*ptr == NULL) { 323ae771770SStanislav Sedov ldap_value_free_len(vals); 324ae771770SStanislav Sedov return ENOMEM; 325ae771770SStanislav Sedov } 3265e9cd1aeSAssar Westerlund 327ae771770SStanislav Sedov memcpy(*ptr, vals[0]->bv_val, vals[0]->bv_len); 328ae771770SStanislav Sedov (*ptr)[vals[0]->bv_len] = 0; 3295e9cd1aeSAssar Westerlund 330ae771770SStanislav Sedov ldap_value_free_len(vals); 331ae771770SStanislav Sedov 332ae771770SStanislav Sedov return 0; 3335e9cd1aeSAssar Westerlund } 3345e9cd1aeSAssar Westerlund 3355e9cd1aeSAssar Westerlund static krb5_error_code 3365e9cd1aeSAssar Westerlund LDAP_get_integer_value(HDB * db, LDAPMessage * entry, 3375e9cd1aeSAssar Westerlund const char *attribute, int *ptr) 3385e9cd1aeSAssar Westerlund { 339ae771770SStanislav Sedov krb5_error_code ret; 340ae771770SStanislav Sedov char *val; 3415e9cd1aeSAssar Westerlund 342ae771770SStanislav Sedov ret = LDAP_get_string_value(db, entry, attribute, &val); 343ae771770SStanislav Sedov if (ret) 344ae771770SStanislav Sedov return ret; 345ae771770SStanislav Sedov *ptr = atoi(val); 346ae771770SStanislav Sedov free(val); 3475e9cd1aeSAssar Westerlund return 0; 3485e9cd1aeSAssar Westerlund } 3495e9cd1aeSAssar Westerlund 3505e9cd1aeSAssar Westerlund static krb5_error_code 3515e9cd1aeSAssar Westerlund LDAP_get_generalized_time_value(HDB * db, LDAPMessage * entry, 3525e9cd1aeSAssar Westerlund const char *attribute, KerberosTime * kt) 3535e9cd1aeSAssar Westerlund { 3545e9cd1aeSAssar Westerlund char *tmp, *gentime; 3555e9cd1aeSAssar Westerlund struct tm tm; 3565e9cd1aeSAssar Westerlund int ret; 3575e9cd1aeSAssar Westerlund 3585e9cd1aeSAssar Westerlund *kt = 0; 3595e9cd1aeSAssar Westerlund 3605e9cd1aeSAssar Westerlund ret = LDAP_get_string_value(db, entry, attribute, &gentime); 361c19800e8SDoug Rabson if (ret) 3625e9cd1aeSAssar Westerlund return ret; 3635e9cd1aeSAssar Westerlund 3645e9cd1aeSAssar Westerlund tmp = strptime(gentime, "%Y%m%d%H%M%SZ", &tm); 3655e9cd1aeSAssar Westerlund if (tmp == NULL) { 3665e9cd1aeSAssar Westerlund free(gentime); 3675e9cd1aeSAssar Westerlund return HDB_ERR_NOENTRY; 3685e9cd1aeSAssar Westerlund } 3695e9cd1aeSAssar Westerlund 3705e9cd1aeSAssar Westerlund free(gentime); 3715e9cd1aeSAssar Westerlund 3725e9cd1aeSAssar Westerlund *kt = timegm(&tm); 3735e9cd1aeSAssar Westerlund 3745e9cd1aeSAssar Westerlund return 0; 3755e9cd1aeSAssar Westerlund } 3765e9cd1aeSAssar Westerlund 377ae771770SStanislav Sedov static int 378ae771770SStanislav Sedov bervalstrcmp(struct berval *v, const char *str) 379ae771770SStanislav Sedov { 380ae771770SStanislav Sedov size_t len = strlen(str); 381ae771770SStanislav Sedov return (v->bv_len == len) && strncasecmp(str, (char *)v->bv_val, len) == 0; 382ae771770SStanislav Sedov } 383ae771770SStanislav Sedov 384ae771770SStanislav Sedov 3855e9cd1aeSAssar Westerlund static krb5_error_code 386c19800e8SDoug Rabson LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent, 3875e9cd1aeSAssar Westerlund LDAPMessage * msg, LDAPMod *** pmods) 3885e9cd1aeSAssar Westerlund { 3895e9cd1aeSAssar Westerlund krb5_error_code ret; 3905e9cd1aeSAssar Westerlund krb5_boolean is_new_entry; 3915e9cd1aeSAssar Westerlund char *tmp = NULL; 3925e9cd1aeSAssar Westerlund LDAPMod **mods = NULL; 393c19800e8SDoug Rabson hdb_entry_ex orig; 3945e9cd1aeSAssar Westerlund unsigned long oflags, nflags; 395c19800e8SDoug Rabson int i; 396c19800e8SDoug Rabson 397c19800e8SDoug Rabson krb5_boolean is_samba_account = FALSE; 398c19800e8SDoug Rabson krb5_boolean is_account = FALSE; 399c19800e8SDoug Rabson krb5_boolean is_heimdal_entry = FALSE; 400c19800e8SDoug Rabson krb5_boolean is_heimdal_principal = FALSE; 401c19800e8SDoug Rabson 402ae771770SStanislav Sedov struct berval **vals; 403c19800e8SDoug Rabson 404c19800e8SDoug Rabson *pmods = NULL; 4055e9cd1aeSAssar Westerlund 4065e9cd1aeSAssar Westerlund if (msg != NULL) { 407c19800e8SDoug Rabson 408ae771770SStanislav Sedov ret = LDAP_message2entry(context, db, msg, 0, &orig); 409c19800e8SDoug Rabson if (ret) 410c19800e8SDoug Rabson goto out; 411c19800e8SDoug Rabson 412c19800e8SDoug Rabson is_new_entry = FALSE; 413c19800e8SDoug Rabson 414ae771770SStanislav Sedov vals = ldap_get_values_len(HDB2LDAP(db), msg, "objectClass"); 415ae771770SStanislav Sedov if (vals) { 416ae771770SStanislav Sedov int num_objectclasses = ldap_count_values_len(vals); 417c19800e8SDoug Rabson for (i=0; i < num_objectclasses; i++) { 418ae771770SStanislav Sedov if (bervalstrcmp(vals[i], "sambaSamAccount")) 419c19800e8SDoug Rabson is_samba_account = TRUE; 420ae771770SStanislav Sedov else if (bervalstrcmp(vals[i], structural_object)) 421c19800e8SDoug Rabson is_account = TRUE; 422ae771770SStanislav Sedov else if (bervalstrcmp(vals[i], "krb5Principal")) 423c19800e8SDoug Rabson is_heimdal_principal = TRUE; 424ae771770SStanislav Sedov else if (bervalstrcmp(vals[i], "krb5KDCEntry")) 425c19800e8SDoug Rabson is_heimdal_entry = TRUE; 426c19800e8SDoug Rabson } 427ae771770SStanislav Sedov ldap_value_free_len(vals); 428c19800e8SDoug Rabson } 429c19800e8SDoug Rabson 430c19800e8SDoug Rabson /* 431c19800e8SDoug Rabson * If this is just a "account" entry and no other objectclass 432c19800e8SDoug Rabson * is hanging on this entry, it's really a new entry. 433c19800e8SDoug Rabson */ 434c19800e8SDoug Rabson if (is_samba_account == FALSE && is_heimdal_principal == FALSE && 435c19800e8SDoug Rabson is_heimdal_entry == FALSE) { 436c19800e8SDoug Rabson if (is_account == TRUE) { 437c19800e8SDoug Rabson is_new_entry = TRUE; 438c19800e8SDoug Rabson } else { 439c19800e8SDoug Rabson ret = HDB_ERR_NOENTRY; 4405e9cd1aeSAssar Westerlund goto out; 4415e9cd1aeSAssar Westerlund } 442c19800e8SDoug Rabson } 443c19800e8SDoug Rabson } else 444c19800e8SDoug Rabson is_new_entry = TRUE; 445c19800e8SDoug Rabson 446c19800e8SDoug Rabson if (is_new_entry) { 447c19800e8SDoug Rabson 4485e9cd1aeSAssar Westerlund /* to make it perfectly obvious we're depending on 4495e9cd1aeSAssar Westerlund * orig being intiialized to zero */ 4505e9cd1aeSAssar Westerlund memset(&orig, 0, sizeof(orig)); 451c19800e8SDoug Rabson 452c19800e8SDoug Rabson ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", "top"); 453c19800e8SDoug Rabson if (ret) 454c19800e8SDoug Rabson goto out; 455c19800e8SDoug Rabson 456c19800e8SDoug Rabson /* account is the structural object class */ 457c19800e8SDoug Rabson if (is_account == FALSE) { 458c19800e8SDoug Rabson ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", 459c19800e8SDoug Rabson structural_object); 460c19800e8SDoug Rabson is_account = TRUE; 461c19800e8SDoug Rabson if (ret) 462c19800e8SDoug Rabson goto out; 4635e9cd1aeSAssar Westerlund } 4645e9cd1aeSAssar Westerlund 465c19800e8SDoug Rabson ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", "krb5Principal"); 466c19800e8SDoug Rabson is_heimdal_principal = TRUE; 467c19800e8SDoug Rabson if (ret) 4685e9cd1aeSAssar Westerlund goto out; 469c19800e8SDoug Rabson 470c19800e8SDoug Rabson ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", "krb5KDCEntry"); 471c19800e8SDoug Rabson is_heimdal_entry = TRUE; 472c19800e8SDoug Rabson if (ret) 4735e9cd1aeSAssar Westerlund goto out; 4745e9cd1aeSAssar Westerlund } 4755e9cd1aeSAssar Westerlund 4765e9cd1aeSAssar Westerlund if (is_new_entry || 477c19800e8SDoug Rabson krb5_principal_compare(context, ent->entry.principal, orig.entry.principal) 478c19800e8SDoug Rabson == FALSE) 479c19800e8SDoug Rabson { 480c19800e8SDoug Rabson if (is_heimdal_principal || is_heimdal_entry) { 481c19800e8SDoug Rabson 482c19800e8SDoug Rabson ret = krb5_unparse_name(context, ent->entry.principal, &tmp); 483c19800e8SDoug Rabson if (ret) 4845e9cd1aeSAssar Westerlund goto out; 485c19800e8SDoug Rabson 486c19800e8SDoug Rabson ret = LDAP_addmod(&mods, LDAP_MOD_REPLACE, 487c19800e8SDoug Rabson "krb5PrincipalName", tmp); 488c19800e8SDoug Rabson if (ret) { 4895e9cd1aeSAssar Westerlund free(tmp); 4905e9cd1aeSAssar Westerlund goto out; 4915e9cd1aeSAssar Westerlund } 4925e9cd1aeSAssar Westerlund free(tmp); 4935e9cd1aeSAssar Westerlund } 4945e9cd1aeSAssar Westerlund 495c19800e8SDoug Rabson if (is_account || is_samba_account) { 496c19800e8SDoug Rabson ret = krb5_unparse_name_short(context, ent->entry.principal, &tmp); 497c19800e8SDoug Rabson if (ret) 498c19800e8SDoug Rabson goto out; 499c19800e8SDoug Rabson ret = LDAP_addmod(&mods, LDAP_MOD_REPLACE, "uid", tmp); 500c19800e8SDoug Rabson if (ret) { 501c19800e8SDoug Rabson free(tmp); 5025e9cd1aeSAssar Westerlund goto out; 5035e9cd1aeSAssar Westerlund } 5045e9cd1aeSAssar Westerlund free(tmp); 5055e9cd1aeSAssar Westerlund } 5065e9cd1aeSAssar Westerlund } 5075e9cd1aeSAssar Westerlund 508c19800e8SDoug Rabson if (is_heimdal_entry && (ent->entry.kvno != orig.entry.kvno || is_new_entry)) { 509c19800e8SDoug Rabson ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, 510c19800e8SDoug Rabson "krb5KeyVersionNumber", 511c19800e8SDoug Rabson ent->entry.kvno); 512c19800e8SDoug Rabson if (ret) 513c19800e8SDoug Rabson goto out; 514c19800e8SDoug Rabson } 515c19800e8SDoug Rabson 516c19800e8SDoug Rabson if (is_heimdal_entry && ent->entry.valid_start) { 517c19800e8SDoug Rabson if (orig.entry.valid_end == NULL 518c19800e8SDoug Rabson || (*(ent->entry.valid_start) != *(orig.entry.valid_start))) { 519c19800e8SDoug Rabson ret = LDAP_addmod_generalized_time(&mods, LDAP_MOD_REPLACE, 5205e9cd1aeSAssar Westerlund "krb5ValidStart", 521c19800e8SDoug Rabson ent->entry.valid_start); 522c19800e8SDoug Rabson if (ret) 5235e9cd1aeSAssar Westerlund goto out; 5245e9cd1aeSAssar Westerlund } 5255e9cd1aeSAssar Westerlund } 5265e9cd1aeSAssar Westerlund 527c19800e8SDoug Rabson if (ent->entry.valid_end) { 528c19800e8SDoug Rabson if (orig.entry.valid_end == NULL || (*(ent->entry.valid_end) != *(orig.entry.valid_end))) { 529c19800e8SDoug Rabson if (is_heimdal_entry) { 530c19800e8SDoug Rabson ret = LDAP_addmod_generalized_time(&mods, LDAP_MOD_REPLACE, 5315e9cd1aeSAssar Westerlund "krb5ValidEnd", 532c19800e8SDoug Rabson ent->entry.valid_end); 533c19800e8SDoug Rabson if (ret) 534c19800e8SDoug Rabson goto out; 535c19800e8SDoug Rabson } 536c19800e8SDoug Rabson if (is_samba_account) { 537c19800e8SDoug Rabson ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, 538c19800e8SDoug Rabson "sambaKickoffTime", 539c19800e8SDoug Rabson *(ent->entry.valid_end)); 540c19800e8SDoug Rabson if (ret) 5415e9cd1aeSAssar Westerlund goto out; 5425e9cd1aeSAssar Westerlund } 5435e9cd1aeSAssar Westerlund } 5445e9cd1aeSAssar Westerlund } 5455e9cd1aeSAssar Westerlund 546c19800e8SDoug Rabson if (ent->entry.pw_end) { 547c19800e8SDoug Rabson if (orig.entry.pw_end == NULL || (*(ent->entry.pw_end) != *(orig.entry.pw_end))) { 548c19800e8SDoug Rabson if (is_heimdal_entry) { 549c19800e8SDoug Rabson ret = LDAP_addmod_generalized_time(&mods, LDAP_MOD_REPLACE, 5505e9cd1aeSAssar Westerlund "krb5PasswordEnd", 551c19800e8SDoug Rabson ent->entry.pw_end); 552c19800e8SDoug Rabson if (ret) 553c19800e8SDoug Rabson goto out; 554c19800e8SDoug Rabson } 555c19800e8SDoug Rabson 556c19800e8SDoug Rabson if (is_samba_account) { 557c19800e8SDoug Rabson ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, 558c19800e8SDoug Rabson "sambaPwdMustChange", 559c19800e8SDoug Rabson *(ent->entry.pw_end)); 560c19800e8SDoug Rabson if (ret) 5615e9cd1aeSAssar Westerlund goto out; 5625e9cd1aeSAssar Westerlund } 5635e9cd1aeSAssar Westerlund } 5645e9cd1aeSAssar Westerlund } 5655e9cd1aeSAssar Westerlund 5665e9cd1aeSAssar Westerlund 567c19800e8SDoug Rabson #if 0 /* we we have last_pw_change */ 568c19800e8SDoug Rabson if (is_samba_account && ent->entry.last_pw_change) { 569c19800e8SDoug Rabson if (orig.entry.last_pw_change == NULL || (*(ent->entry.last_pw_change) != *(orig.entry.last_pw_change))) { 570c19800e8SDoug Rabson ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, 571c19800e8SDoug Rabson "sambaPwdLastSet", 572c19800e8SDoug Rabson *(ent->entry.last_pw_change)); 573c19800e8SDoug Rabson if (ret) 5745e9cd1aeSAssar Westerlund goto out; 5755e9cd1aeSAssar Westerlund } 5765e9cd1aeSAssar Westerlund } 577c19800e8SDoug Rabson #endif 5785e9cd1aeSAssar Westerlund 579c19800e8SDoug Rabson if (is_heimdal_entry && ent->entry.max_life) { 580c19800e8SDoug Rabson if (orig.entry.max_life == NULL 581c19800e8SDoug Rabson || (*(ent->entry.max_life) != *(orig.entry.max_life))) { 5825e9cd1aeSAssar Westerlund 583c19800e8SDoug Rabson ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, 584c19800e8SDoug Rabson "krb5MaxLife", 585c19800e8SDoug Rabson *(ent->entry.max_life)); 586c19800e8SDoug Rabson if (ret) 5875e9cd1aeSAssar Westerlund goto out; 5885e9cd1aeSAssar Westerlund } 5895e9cd1aeSAssar Westerlund } 5905e9cd1aeSAssar Westerlund 591c19800e8SDoug Rabson if (is_heimdal_entry && ent->entry.max_renew) { 592c19800e8SDoug Rabson if (orig.entry.max_renew == NULL 593c19800e8SDoug Rabson || (*(ent->entry.max_renew) != *(orig.entry.max_renew))) { 594c19800e8SDoug Rabson 595c19800e8SDoug Rabson ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, 596c19800e8SDoug Rabson "krb5MaxRenew", 597c19800e8SDoug Rabson *(ent->entry.max_renew)); 598c19800e8SDoug Rabson if (ret) 599c19800e8SDoug Rabson goto out; 600c19800e8SDoug Rabson } 601c19800e8SDoug Rabson } 602c19800e8SDoug Rabson 603c19800e8SDoug Rabson oflags = HDBFlags2int(orig.entry.flags); 604c19800e8SDoug Rabson nflags = HDBFlags2int(ent->entry.flags); 605c19800e8SDoug Rabson 606c19800e8SDoug Rabson if (is_heimdal_entry && oflags != nflags) { 607c19800e8SDoug Rabson 608c19800e8SDoug Rabson ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, 609c19800e8SDoug Rabson "krb5KDCFlags", 610c19800e8SDoug Rabson nflags); 611c19800e8SDoug Rabson if (ret) 612c19800e8SDoug Rabson goto out; 613c19800e8SDoug Rabson } 614c19800e8SDoug Rabson 615c19800e8SDoug Rabson /* Remove keys if they exists, and then replace keys. */ 616c19800e8SDoug Rabson if (!is_new_entry && orig.entry.keys.len > 0) { 617ae771770SStanislav Sedov vals = ldap_get_values_len(HDB2LDAP(db), msg, "krb5Key"); 618ae771770SStanislav Sedov if (vals) { 619ae771770SStanislav Sedov ldap_value_free_len(vals); 620c19800e8SDoug Rabson 6215e9cd1aeSAssar Westerlund ret = LDAP_addmod(&mods, LDAP_MOD_DELETE, "krb5Key", NULL); 622c19800e8SDoug Rabson if (ret) 6235e9cd1aeSAssar Westerlund goto out; 6245e9cd1aeSAssar Westerlund } 6255e9cd1aeSAssar Westerlund } 6265e9cd1aeSAssar Westerlund 627c19800e8SDoug Rabson for (i = 0; i < ent->entry.keys.len; i++) { 628c19800e8SDoug Rabson 629c19800e8SDoug Rabson if (is_samba_account 630c19800e8SDoug Rabson && ent->entry.keys.val[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5) { 631c19800e8SDoug Rabson char *ntHexPassword; 632c19800e8SDoug Rabson char *nt; 633ae771770SStanislav Sedov time_t now = time(NULL); 634c19800e8SDoug Rabson 635c19800e8SDoug Rabson /* the key might have been 'sealed', but samba passwords 636c19800e8SDoug Rabson are clear in the directory */ 637c19800e8SDoug Rabson ret = hdb_unseal_key(context, db, &ent->entry.keys.val[i]); 638c19800e8SDoug Rabson if (ret) 639c19800e8SDoug Rabson goto out; 640c19800e8SDoug Rabson 641c19800e8SDoug Rabson nt = ent->entry.keys.val[i].key.keyvalue.data; 642c19800e8SDoug Rabson /* store in ntPassword, not krb5key */ 643c19800e8SDoug Rabson ret = hex_encode(nt, 16, &ntHexPassword); 644c19800e8SDoug Rabson if (ret < 0) { 645c19800e8SDoug Rabson ret = ENOMEM; 646ae771770SStanislav Sedov krb5_set_error_message(context, ret, "hdb-ldap: failed to " 647ae771770SStanislav Sedov "hex encode key"); 648c19800e8SDoug Rabson goto out; 649c19800e8SDoug Rabson } 650c19800e8SDoug Rabson ret = LDAP_addmod(&mods, LDAP_MOD_REPLACE, "sambaNTPassword", 651c19800e8SDoug Rabson ntHexPassword); 652c19800e8SDoug Rabson free(ntHexPassword); 653c19800e8SDoug Rabson if (ret) 654c19800e8SDoug Rabson goto out; 655ae771770SStanislav Sedov ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, 656ae771770SStanislav Sedov "sambaPwdLastSet", now); 657ae771770SStanislav Sedov if (ret) 658ae771770SStanislav Sedov goto out; 659c19800e8SDoug Rabson 660c19800e8SDoug Rabson /* have to kill the LM passwod if it exists */ 661ae771770SStanislav Sedov vals = ldap_get_values_len(HDB2LDAP(db), msg, "sambaLMPassword"); 662ae771770SStanislav Sedov if (vals) { 663ae771770SStanislav Sedov ldap_value_free_len(vals); 664c19800e8SDoug Rabson ret = LDAP_addmod(&mods, LDAP_MOD_DELETE, 665c19800e8SDoug Rabson "sambaLMPassword", NULL); 666c19800e8SDoug Rabson if (ret) 667c19800e8SDoug Rabson goto out; 668c19800e8SDoug Rabson } 669c19800e8SDoug Rabson 670c19800e8SDoug Rabson } else if (is_heimdal_entry) { 6715e9cd1aeSAssar Westerlund unsigned char *buf; 672c19800e8SDoug Rabson size_t len, buf_size; 6735e9cd1aeSAssar Westerlund 674c19800e8SDoug Rabson ASN1_MALLOC_ENCODE(Key, buf, buf_size, &ent->entry.keys.val[i], &len, ret); 675c19800e8SDoug Rabson if (ret) 6765e9cd1aeSAssar Westerlund goto out; 677c19800e8SDoug Rabson if(buf_size != len) 678c19800e8SDoug Rabson krb5_abortx(context, "internal error in ASN.1 encoder"); 6795e9cd1aeSAssar Westerlund 6805e9cd1aeSAssar Westerlund /* addmod_len _owns_ the key, doesn't need to copy it */ 6815e9cd1aeSAssar Westerlund ret = LDAP_addmod_len(&mods, LDAP_MOD_ADD, "krb5Key", buf, len); 682c19800e8SDoug Rabson if (ret) 6835e9cd1aeSAssar Westerlund goto out; 6845e9cd1aeSAssar Westerlund } 6855e9cd1aeSAssar Westerlund } 6865e9cd1aeSAssar Westerlund 687c19800e8SDoug Rabson if (ent->entry.etypes) { 688c19800e8SDoug Rabson int add_krb5EncryptionType = 0; 689c19800e8SDoug Rabson 690c19800e8SDoug Rabson /* 691c19800e8SDoug Rabson * Only add/modify krb5EncryptionType if it's a new heimdal 692c19800e8SDoug Rabson * entry or krb5EncryptionType already exists on the entry. 693c19800e8SDoug Rabson */ 694c19800e8SDoug Rabson 695c19800e8SDoug Rabson if (!is_new_entry) { 696ae771770SStanislav Sedov vals = ldap_get_values_len(HDB2LDAP(db), msg, "krb5EncryptionType"); 697ae771770SStanislav Sedov if (vals) { 698ae771770SStanislav Sedov ldap_value_free_len(vals); 699c19800e8SDoug Rabson ret = LDAP_addmod(&mods, LDAP_MOD_DELETE, "krb5EncryptionType", 7005e9cd1aeSAssar Westerlund NULL); 701c19800e8SDoug Rabson if (ret) 702c19800e8SDoug Rabson goto out; 703c19800e8SDoug Rabson add_krb5EncryptionType = 1; 7045e9cd1aeSAssar Westerlund } 705c19800e8SDoug Rabson } else if (is_heimdal_entry) 706c19800e8SDoug Rabson add_krb5EncryptionType = 1; 707c19800e8SDoug Rabson 708c19800e8SDoug Rabson if (add_krb5EncryptionType) { 709c19800e8SDoug Rabson for (i = 0; i < ent->entry.etypes->len; i++) { 710c19800e8SDoug Rabson if (is_samba_account && 711c19800e8SDoug Rabson ent->entry.keys.val[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5) 712c19800e8SDoug Rabson { 713c19800e8SDoug Rabson ; 714c19800e8SDoug Rabson } else if (is_heimdal_entry) { 715c19800e8SDoug Rabson ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_ADD, 716c19800e8SDoug Rabson "krb5EncryptionType", 717c19800e8SDoug Rabson ent->entry.etypes->val[i]); 718c19800e8SDoug Rabson if (ret) 7195e9cd1aeSAssar Westerlund goto out; 7205e9cd1aeSAssar Westerlund } 7215e9cd1aeSAssar Westerlund } 7225e9cd1aeSAssar Westerlund } 7235e9cd1aeSAssar Westerlund } 7245e9cd1aeSAssar Westerlund 7255e9cd1aeSAssar Westerlund /* for clarity */ 7265e9cd1aeSAssar Westerlund ret = 0; 7275e9cd1aeSAssar Westerlund 7285e9cd1aeSAssar Westerlund out: 7295e9cd1aeSAssar Westerlund 730c19800e8SDoug Rabson if (ret == 0) 7315e9cd1aeSAssar Westerlund *pmods = mods; 732c19800e8SDoug Rabson else if (mods != NULL) { 7335e9cd1aeSAssar Westerlund ldap_mods_free(mods, 1); 7345e9cd1aeSAssar Westerlund *pmods = NULL; 7355e9cd1aeSAssar Westerlund } 7365e9cd1aeSAssar Westerlund 737c19800e8SDoug Rabson if (msg) 7385e9cd1aeSAssar Westerlund hdb_free_entry(context, &orig); 7395e9cd1aeSAssar Westerlund 7405e9cd1aeSAssar Westerlund return ret; 7415e9cd1aeSAssar Westerlund } 7425e9cd1aeSAssar Westerlund 7435e9cd1aeSAssar Westerlund static krb5_error_code 7445e9cd1aeSAssar Westerlund LDAP_dn2principal(krb5_context context, HDB * db, const char *dn, 7455e9cd1aeSAssar Westerlund krb5_principal * principal) 7465e9cd1aeSAssar Westerlund { 7475e9cd1aeSAssar Westerlund krb5_error_code ret; 748c19800e8SDoug Rabson int rc; 749c19800e8SDoug Rabson const char *filter = "(objectClass=krb5Principal)"; 7505e9cd1aeSAssar Westerlund LDAPMessage *res = NULL, *e; 751ae771770SStanislav Sedov char *p; 7525e9cd1aeSAssar Westerlund 753c19800e8SDoug Rabson ret = LDAP_no_size_limit(context, HDB2LDAP(db)); 754c19800e8SDoug Rabson if (ret) 7554137ff4cSJacques Vidrine goto out; 7564137ff4cSJacques Vidrine 757ae771770SStanislav Sedov rc = ldap_search_ext_s(HDB2LDAP(db), dn, LDAP_SCOPE_SUBTREE, 758ae771770SStanislav Sedov filter, krb5principal_attrs, 0, 759ae771770SStanislav Sedov NULL, NULL, NULL, 7605e9cd1aeSAssar Westerlund 0, &res); 761c19800e8SDoug Rabson if (check_ldap(context, db, rc)) { 7625e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 763ae771770SStanislav Sedov krb5_set_error_message(context, ret, "ldap_search_ext_s: " 764ae771770SStanislav Sedov "filter: %s error: %s", 765ae771770SStanislav Sedov filter, ldap_err2string(rc)); 7665e9cd1aeSAssar Westerlund goto out; 7675e9cd1aeSAssar Westerlund } 7685e9cd1aeSAssar Westerlund 769c19800e8SDoug Rabson e = ldap_first_entry(HDB2LDAP(db), res); 7705e9cd1aeSAssar Westerlund if (e == NULL) { 7715e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 7725e9cd1aeSAssar Westerlund goto out; 7735e9cd1aeSAssar Westerlund } 7745e9cd1aeSAssar Westerlund 775ae771770SStanislav Sedov ret = LDAP_get_string_value(db, e, "krb5PrincipalName", &p); 776ae771770SStanislav Sedov if (ret) { 7775e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 7785e9cd1aeSAssar Westerlund goto out; 7795e9cd1aeSAssar Westerlund } 7805e9cd1aeSAssar Westerlund 781ae771770SStanislav Sedov ret = krb5_parse_name(context, p, principal); 782ae771770SStanislav Sedov free(p); 7835e9cd1aeSAssar Westerlund 7845e9cd1aeSAssar Westerlund out: 785c19800e8SDoug Rabson if (res) 7865e9cd1aeSAssar Westerlund ldap_msgfree(res); 787c19800e8SDoug Rabson 7885e9cd1aeSAssar Westerlund return ret; 7895e9cd1aeSAssar Westerlund } 7905e9cd1aeSAssar Westerlund 791ae771770SStanislav Sedov static int 792ae771770SStanislav Sedov need_quote(unsigned char c) 793ae771770SStanislav Sedov { 794ae771770SStanislav Sedov return (c & 0x80) || 795ae771770SStanislav Sedov (c < 32) || 796ae771770SStanislav Sedov (c == '(') || 797ae771770SStanislav Sedov (c == ')') || 798ae771770SStanislav Sedov (c == '*') || 799ae771770SStanislav Sedov (c == '\\') || 800ae771770SStanislav Sedov (c == 0x7f); 801ae771770SStanislav Sedov } 802ae771770SStanislav Sedov 803*a0d7d68aSCy Schubert static const char hexchar[] = "0123456789ABCDEF"; 804ae771770SStanislav Sedov 805ae771770SStanislav Sedov static krb5_error_code 806*a0d7d68aSCy Schubert escape_value(krb5_context context, const char *unquoted, char **quoted) 807ae771770SStanislav Sedov { 808ae771770SStanislav Sedov size_t i, len; 809ae771770SStanislav Sedov 810ae771770SStanislav Sedov for (i = 0, len = 0; unquoted[i] != '\0'; i++, len++) { 811ae771770SStanislav Sedov if (need_quote((unsigned char)unquoted[i])) 812ae771770SStanislav Sedov len += 2; 813ae771770SStanislav Sedov } 814ae771770SStanislav Sedov 815ae771770SStanislav Sedov *quoted = malloc(len + 1); 816ae771770SStanislav Sedov if (*quoted == NULL) { 817ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 818ae771770SStanislav Sedov return ENOMEM; 819ae771770SStanislav Sedov } 820ae771770SStanislav Sedov 821ae771770SStanislav Sedov for (i = 0; unquoted[0] ; unquoted++) { 822*a0d7d68aSCy Schubert if (need_quote((unsigned char)unquoted[0])) { 823ae771770SStanislav Sedov (*quoted)[i++] = '\\'; 824ae771770SStanislav Sedov (*quoted)[i++] = hexchar[(unquoted[0] >> 4) & 0xf]; 825ae771770SStanislav Sedov (*quoted)[i++] = hexchar[(unquoted[0] ) & 0xf]; 826ae771770SStanislav Sedov } else 827ae771770SStanislav Sedov (*quoted)[i++] = (char)unquoted[0]; 828ae771770SStanislav Sedov } 829ae771770SStanislav Sedov (*quoted)[i] = '\0'; 830ae771770SStanislav Sedov return 0; 831ae771770SStanislav Sedov } 832ae771770SStanislav Sedov 833ae771770SStanislav Sedov 8345e9cd1aeSAssar Westerlund static krb5_error_code 835c19800e8SDoug Rabson LDAP__lookup_princ(krb5_context context, 836c19800e8SDoug Rabson HDB *db, 837c19800e8SDoug Rabson const char *princname, 838c19800e8SDoug Rabson const char *userid, 8395e9cd1aeSAssar Westerlund LDAPMessage **msg) 8405e9cd1aeSAssar Westerlund { 8415e9cd1aeSAssar Westerlund krb5_error_code ret; 842c19800e8SDoug Rabson int rc; 843ae771770SStanislav Sedov char *quote, *filter = NULL; 8445e9cd1aeSAssar Westerlund 845c19800e8SDoug Rabson ret = LDAP__connect(context, db); 846c19800e8SDoug Rabson if (ret) 847c19800e8SDoug Rabson return ret; 8485e9cd1aeSAssar Westerlund 849ae771770SStanislav Sedov /* 850ae771770SStanislav Sedov * Quote searches that contain filter language, this quote 851ae771770SStanislav Sedov * searches for *@REALM, which takes very long time. 852ae771770SStanislav Sedov */ 853ae771770SStanislav Sedov 854ae771770SStanislav Sedov ret = escape_value(context, princname, "e); 855ae771770SStanislav Sedov if (ret) 856ae771770SStanislav Sedov goto out; 857ae771770SStanislav Sedov 858c19800e8SDoug Rabson rc = asprintf(&filter, 859c19800e8SDoug Rabson "(&(objectClass=krb5Principal)(krb5PrincipalName=%s))", 860ae771770SStanislav Sedov quote); 861ae771770SStanislav Sedov free(quote); 862ae771770SStanislav Sedov 8635e9cd1aeSAssar Westerlund if (rc < 0) { 8645e9cd1aeSAssar Westerlund ret = ENOMEM; 865ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 8665e9cd1aeSAssar Westerlund goto out; 8675e9cd1aeSAssar Westerlund } 8685e9cd1aeSAssar Westerlund 869c19800e8SDoug Rabson ret = LDAP_no_size_limit(context, HDB2LDAP(db)); 870c19800e8SDoug Rabson if (ret) 871c19800e8SDoug Rabson goto out; 872c19800e8SDoug Rabson 873ae771770SStanislav Sedov rc = ldap_search_ext_s(HDB2LDAP(db), HDB2BASE(db), 874ae771770SStanislav Sedov LDAP_SCOPE_SUBTREE, filter, 875ae771770SStanislav Sedov krb5kdcentry_attrs, 0, 876ae771770SStanislav Sedov NULL, NULL, NULL, 877ae771770SStanislav Sedov 0, msg); 878c19800e8SDoug Rabson if (check_ldap(context, db, rc)) { 879c19800e8SDoug Rabson ret = HDB_ERR_NOENTRY; 880ae771770SStanislav Sedov krb5_set_error_message(context, ret, "ldap_search_ext_s: " 881ae771770SStanislav Sedov "filter: %s - error: %s", 882ae771770SStanislav Sedov filter, ldap_err2string(rc)); 8834137ff4cSJacques Vidrine goto out; 8844137ff4cSJacques Vidrine } 8855e9cd1aeSAssar Westerlund 886c19800e8SDoug Rabson if (userid && ldap_count_entries(HDB2LDAP(db), *msg) == 0) { 887c19800e8SDoug Rabson free(filter); 888c19800e8SDoug Rabson filter = NULL; 889c19800e8SDoug Rabson ldap_msgfree(*msg); 890c19800e8SDoug Rabson *msg = NULL; 891c19800e8SDoug Rabson 892ae771770SStanislav Sedov ret = escape_value(context, userid, "e); 893ae771770SStanislav Sedov if (ret) 894ae771770SStanislav Sedov goto out; 895ae771770SStanislav Sedov 896c19800e8SDoug Rabson rc = asprintf(&filter, 897c19800e8SDoug Rabson "(&(|(objectClass=sambaSamAccount)(objectClass=%s))(uid=%s))", 898ae771770SStanislav Sedov structural_object, quote); 899ae771770SStanislav Sedov free(quote); 900c19800e8SDoug Rabson if (rc < 0) { 901c19800e8SDoug Rabson ret = ENOMEM; 902ae771770SStanislav Sedov krb5_set_error_message(context, ret, "asprintf: out of memory"); 903c19800e8SDoug Rabson goto out; 904c19800e8SDoug Rabson } 905c19800e8SDoug Rabson 906c19800e8SDoug Rabson ret = LDAP_no_size_limit(context, HDB2LDAP(db)); 907c19800e8SDoug Rabson if (ret) 908c19800e8SDoug Rabson goto out; 909c19800e8SDoug Rabson 910ae771770SStanislav Sedov rc = ldap_search_ext_s(HDB2LDAP(db), HDB2BASE(db), LDAP_SCOPE_SUBTREE, 911ae771770SStanislav Sedov filter, krb5kdcentry_attrs, 0, 912ae771770SStanislav Sedov NULL, NULL, NULL, 913ae771770SStanislav Sedov 0, msg); 914c19800e8SDoug Rabson if (check_ldap(context, db, rc)) { 9155e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 916ae771770SStanislav Sedov krb5_set_error_message(context, ret, 917ae771770SStanislav Sedov "ldap_search_ext_s: filter: %s error: %s", 918ae771770SStanislav Sedov filter, ldap_err2string(rc)); 9195e9cd1aeSAssar Westerlund goto out; 9205e9cd1aeSAssar Westerlund } 921c19800e8SDoug Rabson } 9225e9cd1aeSAssar Westerlund 9235e9cd1aeSAssar Westerlund ret = 0; 9245e9cd1aeSAssar Westerlund 9255e9cd1aeSAssar Westerlund out: 926c19800e8SDoug Rabson if (filter) 9275e9cd1aeSAssar Westerlund free(filter); 928c19800e8SDoug Rabson 9295e9cd1aeSAssar Westerlund return ret; 9305e9cd1aeSAssar Westerlund } 9315e9cd1aeSAssar Westerlund 9325e9cd1aeSAssar Westerlund static krb5_error_code 9335e9cd1aeSAssar Westerlund LDAP_principal2message(krb5_context context, HDB * db, 934c19800e8SDoug Rabson krb5_const_principal princ, LDAPMessage ** msg) 9355e9cd1aeSAssar Westerlund { 936c19800e8SDoug Rabson char *name, *name_short = NULL; 9375e9cd1aeSAssar Westerlund krb5_error_code ret; 938c19800e8SDoug Rabson krb5_realm *r, *r0; 9395e9cd1aeSAssar Westerlund 940c19800e8SDoug Rabson *msg = NULL; 941c19800e8SDoug Rabson 942c19800e8SDoug Rabson ret = krb5_unparse_name(context, princ, &name); 943c19800e8SDoug Rabson if (ret) 944c19800e8SDoug Rabson return ret; 945c19800e8SDoug Rabson 946c19800e8SDoug Rabson ret = krb5_get_default_realms(context, &r0); 947c19800e8SDoug Rabson if(ret) { 948c19800e8SDoug Rabson free(name); 9495e9cd1aeSAssar Westerlund return ret; 9505e9cd1aeSAssar Westerlund } 951c19800e8SDoug Rabson for (r = r0; *r != NULL; r++) { 952c19800e8SDoug Rabson if(strcmp(krb5_principal_get_realm(context, princ), *r) == 0) { 953c19800e8SDoug Rabson ret = krb5_unparse_name_short(context, princ, &name_short); 954c19800e8SDoug Rabson if (ret) { 955c19800e8SDoug Rabson krb5_free_host_realm(context, r0); 956c19800e8SDoug Rabson free(name); 957c19800e8SDoug Rabson return ret; 958c19800e8SDoug Rabson } 959c19800e8SDoug Rabson break; 960c19800e8SDoug Rabson } 961c19800e8SDoug Rabson } 962c19800e8SDoug Rabson krb5_free_host_realm(context, r0); 9635e9cd1aeSAssar Westerlund 964c19800e8SDoug Rabson ret = LDAP__lookup_princ(context, db, name, name_short, msg); 965c19800e8SDoug Rabson free(name); 966c19800e8SDoug Rabson free(name_short); 9675e9cd1aeSAssar Westerlund 9685e9cd1aeSAssar Westerlund return ret; 9695e9cd1aeSAssar Westerlund } 9705e9cd1aeSAssar Westerlund 9715e9cd1aeSAssar Westerlund /* 9725e9cd1aeSAssar Westerlund * Construct an hdb_entry from a directory entry. 9735e9cd1aeSAssar Westerlund */ 9745e9cd1aeSAssar Westerlund static krb5_error_code 9755e9cd1aeSAssar Westerlund LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg, 976ae771770SStanislav Sedov int flags, hdb_entry_ex * ent) 9775e9cd1aeSAssar Westerlund { 978c19800e8SDoug Rabson char *unparsed_name = NULL, *dn = NULL, *ntPasswordIN = NULL; 979c19800e8SDoug Rabson char *samba_acct_flags = NULL; 9805e9cd1aeSAssar Westerlund struct berval **keys; 981ae771770SStanislav Sedov struct berval **vals; 982ae771770SStanislav Sedov int tmp, tmp_time, i, ret, have_arcfour = 0; 9835e9cd1aeSAssar Westerlund 9845e9cd1aeSAssar Westerlund memset(ent, 0, sizeof(*ent)); 985c19800e8SDoug Rabson ent->entry.flags = int2HDBFlags(0); 9865e9cd1aeSAssar Westerlund 987c19800e8SDoug Rabson ret = LDAP_get_string_value(db, msg, "krb5PrincipalName", &unparsed_name); 988c19800e8SDoug Rabson if (ret == 0) { 989c19800e8SDoug Rabson ret = krb5_parse_name(context, unparsed_name, &ent->entry.principal); 990c19800e8SDoug Rabson if (ret) 9915e9cd1aeSAssar Westerlund goto out; 992c19800e8SDoug Rabson } else { 993c19800e8SDoug Rabson ret = LDAP_get_string_value(db, msg, "uid", 994c19800e8SDoug Rabson &unparsed_name); 995c19800e8SDoug Rabson if (ret == 0) { 996c19800e8SDoug Rabson ret = krb5_parse_name(context, unparsed_name, &ent->entry.principal); 997c19800e8SDoug Rabson if (ret) 998c19800e8SDoug Rabson goto out; 999c19800e8SDoug Rabson } else { 1000ae771770SStanislav Sedov krb5_set_error_message(context, HDB_ERR_NOENTRY, 1001ae771770SStanislav Sedov "hdb-ldap: ldap entry missing" 1002c19800e8SDoug Rabson "principal name"); 1003c19800e8SDoug Rabson return HDB_ERR_NOENTRY; 1004c19800e8SDoug Rabson } 10055e9cd1aeSAssar Westerlund } 10065e9cd1aeSAssar Westerlund 1007c19800e8SDoug Rabson { 1008c19800e8SDoug Rabson int integer; 1009c19800e8SDoug Rabson ret = LDAP_get_integer_value(db, msg, "krb5KeyVersionNumber", 1010c19800e8SDoug Rabson &integer); 1011c19800e8SDoug Rabson if (ret) 1012c19800e8SDoug Rabson ent->entry.kvno = 0; 1013c19800e8SDoug Rabson else 1014c19800e8SDoug Rabson ent->entry.kvno = integer; 10155e9cd1aeSAssar Westerlund } 10165e9cd1aeSAssar Westerlund 1017c19800e8SDoug Rabson keys = ldap_get_values_len(HDB2LDAP(db), msg, "krb5Key"); 10185e9cd1aeSAssar Westerlund if (keys != NULL) { 10195e9cd1aeSAssar Westerlund int i; 10205e9cd1aeSAssar Westerlund size_t l; 10215e9cd1aeSAssar Westerlund 1022c19800e8SDoug Rabson ent->entry.keys.len = ldap_count_values_len(keys); 1023c19800e8SDoug Rabson ent->entry.keys.val = (Key *) calloc(ent->entry.keys.len, sizeof(Key)); 1024c19800e8SDoug Rabson if (ent->entry.keys.val == NULL) { 10254137ff4cSJacques Vidrine ret = ENOMEM; 1026ae771770SStanislav Sedov krb5_set_error_message(context, ret, "calloc: out of memory"); 10274137ff4cSJacques Vidrine goto out; 10284137ff4cSJacques Vidrine } 1029c19800e8SDoug Rabson for (i = 0; i < ent->entry.keys.len; i++) { 10305e9cd1aeSAssar Westerlund decode_Key((unsigned char *) keys[i]->bv_val, 1031c19800e8SDoug Rabson (size_t) keys[i]->bv_len, &ent->entry.keys.val[i], &l); 10325e9cd1aeSAssar Westerlund } 10335e9cd1aeSAssar Westerlund ber_bvecfree(keys); 10345e9cd1aeSAssar Westerlund } else { 10355e9cd1aeSAssar Westerlund #if 1 10365e9cd1aeSAssar Westerlund /* 10375e9cd1aeSAssar Westerlund * This violates the ASN1 but it allows a principal to 10385e9cd1aeSAssar Westerlund * be related to a general directory entry without creating 10395e9cd1aeSAssar Westerlund * the keys. Hopefully it's OK. 10405e9cd1aeSAssar Westerlund */ 1041c19800e8SDoug Rabson ent->entry.keys.len = 0; 1042c19800e8SDoug Rabson ent->entry.keys.val = NULL; 10435e9cd1aeSAssar Westerlund #else 10445e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 10455e9cd1aeSAssar Westerlund goto out; 10465e9cd1aeSAssar Westerlund #endif 10475e9cd1aeSAssar Westerlund } 10485e9cd1aeSAssar Westerlund 1049ae771770SStanislav Sedov vals = ldap_get_values_len(HDB2LDAP(db), msg, "krb5EncryptionType"); 1050ae771770SStanislav Sedov if (vals != NULL) { 1051c19800e8SDoug Rabson int i; 1052c19800e8SDoug Rabson 1053c19800e8SDoug Rabson ent->entry.etypes = malloc(sizeof(*(ent->entry.etypes))); 1054c19800e8SDoug Rabson if (ent->entry.etypes == NULL) { 1055c19800e8SDoug Rabson ret = ENOMEM; 1056ae771770SStanislav Sedov krb5_set_error_message(context, ret,"malloc: out of memory"); 1057c19800e8SDoug Rabson goto out; 1058c19800e8SDoug Rabson } 1059ae771770SStanislav Sedov ent->entry.etypes->len = ldap_count_values_len(vals); 1060c19800e8SDoug Rabson ent->entry.etypes->val = calloc(ent->entry.etypes->len, sizeof(int)); 1061c19800e8SDoug Rabson if (ent->entry.etypes->val == NULL) { 1062c19800e8SDoug Rabson ret = ENOMEM; 1063ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 1064ae771770SStanislav Sedov ent->entry.etypes->len = 0; 1065c19800e8SDoug Rabson goto out; 1066c19800e8SDoug Rabson } 1067c19800e8SDoug Rabson for (i = 0; i < ent->entry.etypes->len; i++) { 1068ae771770SStanislav Sedov char *buf; 1069ae771770SStanislav Sedov 1070ae771770SStanislav Sedov buf = malloc(vals[i]->bv_len + 1); 1071ae771770SStanislav Sedov if (buf == NULL) { 1072ae771770SStanislav Sedov ret = ENOMEM; 1073ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 1074ae771770SStanislav Sedov goto out; 1075c19800e8SDoug Rabson } 1076ae771770SStanislav Sedov memcpy(buf, vals[i]->bv_val, vals[i]->bv_len); 1077ae771770SStanislav Sedov buf[vals[i]->bv_len] = '\0'; 1078ae771770SStanislav Sedov ent->entry.etypes->val[i] = atoi(buf); 1079ae771770SStanislav Sedov free(buf); 1080ae771770SStanislav Sedov } 1081ae771770SStanislav Sedov ldap_value_free_len(vals); 10825e9cd1aeSAssar Westerlund } 10835e9cd1aeSAssar Westerlund 1084c19800e8SDoug Rabson for (i = 0; i < ent->entry.keys.len; i++) { 1085c19800e8SDoug Rabson if (ent->entry.keys.val[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5) { 1086c19800e8SDoug Rabson have_arcfour = 1; 1087c19800e8SDoug Rabson break; 1088c19800e8SDoug Rabson } 1089c19800e8SDoug Rabson } 1090c19800e8SDoug Rabson 1091c19800e8SDoug Rabson /* manually construct the NT (type 23) key */ 1092c19800e8SDoug Rabson ret = LDAP_get_string_value(db, msg, "sambaNTPassword", &ntPasswordIN); 1093c19800e8SDoug Rabson if (ret == 0 && have_arcfour == 0) { 1094c19800e8SDoug Rabson unsigned *etypes; 1095c19800e8SDoug Rabson Key *keys; 1096c19800e8SDoug Rabson int i; 1097c19800e8SDoug Rabson 1098c19800e8SDoug Rabson keys = realloc(ent->entry.keys.val, 1099c19800e8SDoug Rabson (ent->entry.keys.len + 1) * sizeof(ent->entry.keys.val[0])); 1100c19800e8SDoug Rabson if (keys == NULL) { 1101c19800e8SDoug Rabson free(ntPasswordIN); 1102c19800e8SDoug Rabson ret = ENOMEM; 1103ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 1104c19800e8SDoug Rabson goto out; 1105c19800e8SDoug Rabson } 1106c19800e8SDoug Rabson ent->entry.keys.val = keys; 1107c19800e8SDoug Rabson memset(&ent->entry.keys.val[ent->entry.keys.len], 0, sizeof(Key)); 1108c19800e8SDoug Rabson ent->entry.keys.val[ent->entry.keys.len].key.keytype = ETYPE_ARCFOUR_HMAC_MD5; 1109c19800e8SDoug Rabson ret = krb5_data_alloc (&ent->entry.keys.val[ent->entry.keys.len].key.keyvalue, 16); 1110c19800e8SDoug Rabson if (ret) { 1111ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 1112c19800e8SDoug Rabson free(ntPasswordIN); 1113c19800e8SDoug Rabson ret = ENOMEM; 1114c19800e8SDoug Rabson goto out; 1115c19800e8SDoug Rabson } 1116c19800e8SDoug Rabson ret = hex_decode(ntPasswordIN, 1117c19800e8SDoug Rabson ent->entry.keys.val[ent->entry.keys.len].key.keyvalue.data, 16); 1118c19800e8SDoug Rabson ent->entry.keys.len++; 1119c19800e8SDoug Rabson 1120c19800e8SDoug Rabson if (ent->entry.etypes == NULL) { 1121c19800e8SDoug Rabson ent->entry.etypes = malloc(sizeof(*(ent->entry.etypes))); 1122c19800e8SDoug Rabson if (ent->entry.etypes == NULL) { 1123c19800e8SDoug Rabson ret = ENOMEM; 1124ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 1125c19800e8SDoug Rabson goto out; 1126c19800e8SDoug Rabson } 1127c19800e8SDoug Rabson ent->entry.etypes->val = NULL; 1128c19800e8SDoug Rabson ent->entry.etypes->len = 0; 1129c19800e8SDoug Rabson } 1130c19800e8SDoug Rabson 1131c19800e8SDoug Rabson for (i = 0; i < ent->entry.etypes->len; i++) 1132c19800e8SDoug Rabson if (ent->entry.etypes->val[i] == ETYPE_ARCFOUR_HMAC_MD5) 1133c19800e8SDoug Rabson break; 1134c19800e8SDoug Rabson /* If there is no ARCFOUR enctype, add one */ 1135c19800e8SDoug Rabson if (i == ent->entry.etypes->len) { 1136c19800e8SDoug Rabson etypes = realloc(ent->entry.etypes->val, 1137c19800e8SDoug Rabson (ent->entry.etypes->len + 1) * 1138c19800e8SDoug Rabson sizeof(ent->entry.etypes->val[0])); 1139c19800e8SDoug Rabson if (etypes == NULL) { 1140c19800e8SDoug Rabson ret = ENOMEM; 1141ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 1142c19800e8SDoug Rabson goto out; 1143c19800e8SDoug Rabson } 1144c19800e8SDoug Rabson ent->entry.etypes->val = etypes; 1145c19800e8SDoug Rabson ent->entry.etypes->val[ent->entry.etypes->len] = 1146c19800e8SDoug Rabson ETYPE_ARCFOUR_HMAC_MD5; 1147c19800e8SDoug Rabson ent->entry.etypes->len++; 1148c19800e8SDoug Rabson } 1149c19800e8SDoug Rabson } 1150c19800e8SDoug Rabson 1151c19800e8SDoug Rabson ret = LDAP_get_generalized_time_value(db, msg, "createTimestamp", 1152c19800e8SDoug Rabson &ent->entry.created_by.time); 1153c19800e8SDoug Rabson if (ret) 1154c19800e8SDoug Rabson ent->entry.created_by.time = time(NULL); 1155c19800e8SDoug Rabson 1156c19800e8SDoug Rabson ent->entry.created_by.principal = NULL; 11575e9cd1aeSAssar Westerlund 1158ae771770SStanislav Sedov if (flags & HDB_F_ADMIN_DATA) { 11595e9cd1aeSAssar Westerlund ret = LDAP_get_string_value(db, msg, "creatorsName", &dn); 11605e9cd1aeSAssar Westerlund if (ret == 0) { 1161ae771770SStanislav Sedov LDAP_dn2principal(context, db, dn, &ent->entry.created_by.principal); 11625e9cd1aeSAssar Westerlund free(dn); 11635e9cd1aeSAssar Westerlund } 11645e9cd1aeSAssar Westerlund 1165ae771770SStanislav Sedov ent->entry.modified_by = calloc(1, sizeof(*ent->entry.modified_by)); 1166c19800e8SDoug Rabson if (ent->entry.modified_by == NULL) { 11675e9cd1aeSAssar Westerlund ret = ENOMEM; 1168ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 11695e9cd1aeSAssar Westerlund goto out; 11705e9cd1aeSAssar Westerlund } 1171ae771770SStanislav Sedov 1172c19800e8SDoug Rabson ret = LDAP_get_generalized_time_value(db, msg, "modifyTimestamp", 1173c19800e8SDoug Rabson &ent->entry.modified_by->time); 11745e9cd1aeSAssar Westerlund if (ret == 0) { 11755e9cd1aeSAssar Westerlund ret = LDAP_get_string_value(db, msg, "modifiersName", &dn); 1176ae771770SStanislav Sedov if (ret == 0) { 1177ae771770SStanislav Sedov LDAP_dn2principal(context, db, dn, &ent->entry.modified_by->principal); 11785e9cd1aeSAssar Westerlund free(dn); 11795e9cd1aeSAssar Westerlund } else { 1180c19800e8SDoug Rabson free(ent->entry.modified_by); 1181c19800e8SDoug Rabson ent->entry.modified_by = NULL; 11825e9cd1aeSAssar Westerlund } 1183ae771770SStanislav Sedov } 1184ae771770SStanislav Sedov } 11855e9cd1aeSAssar Westerlund 1186c19800e8SDoug Rabson ent->entry.valid_start = malloc(sizeof(*ent->entry.valid_start)); 1187c19800e8SDoug Rabson if (ent->entry.valid_start == NULL) { 11885e9cd1aeSAssar Westerlund ret = ENOMEM; 1189ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 11905e9cd1aeSAssar Westerlund goto out; 11915e9cd1aeSAssar Westerlund } 1192c19800e8SDoug Rabson ret = LDAP_get_generalized_time_value(db, msg, "krb5ValidStart", 1193c19800e8SDoug Rabson ent->entry.valid_start); 1194c19800e8SDoug Rabson if (ret) { 11955e9cd1aeSAssar Westerlund /* OPTIONAL */ 1196c19800e8SDoug Rabson free(ent->entry.valid_start); 1197c19800e8SDoug Rabson ent->entry.valid_start = NULL; 11985e9cd1aeSAssar Westerlund } 11995e9cd1aeSAssar Westerlund 1200c19800e8SDoug Rabson ent->entry.valid_end = malloc(sizeof(*ent->entry.valid_end)); 1201c19800e8SDoug Rabson if (ent->entry.valid_end == NULL) { 12024137ff4cSJacques Vidrine ret = ENOMEM; 1203ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 12045e9cd1aeSAssar Westerlund goto out; 12055e9cd1aeSAssar Westerlund } 1206c19800e8SDoug Rabson ret = LDAP_get_generalized_time_value(db, msg, "krb5ValidEnd", 1207c19800e8SDoug Rabson ent->entry.valid_end); 1208c19800e8SDoug Rabson if (ret) { 12095e9cd1aeSAssar Westerlund /* OPTIONAL */ 1210c19800e8SDoug Rabson free(ent->entry.valid_end); 1211c19800e8SDoug Rabson ent->entry.valid_end = NULL; 12125e9cd1aeSAssar Westerlund } 12135e9cd1aeSAssar Westerlund 1214c19800e8SDoug Rabson ret = LDAP_get_integer_value(db, msg, "sambaKickoffTime", &tmp_time); 1215c19800e8SDoug Rabson if (ret == 0) { 1216c19800e8SDoug Rabson if (ent->entry.valid_end == NULL) { 1217c19800e8SDoug Rabson ent->entry.valid_end = malloc(sizeof(*ent->entry.valid_end)); 1218c19800e8SDoug Rabson if (ent->entry.valid_end == NULL) { 12194137ff4cSJacques Vidrine ret = ENOMEM; 1220ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 12215e9cd1aeSAssar Westerlund goto out; 12225e9cd1aeSAssar Westerlund } 1223c19800e8SDoug Rabson } 1224c19800e8SDoug Rabson *ent->entry.valid_end = tmp_time; 1225c19800e8SDoug Rabson } 1226c19800e8SDoug Rabson 1227c19800e8SDoug Rabson ent->entry.pw_end = malloc(sizeof(*ent->entry.pw_end)); 1228c19800e8SDoug Rabson if (ent->entry.pw_end == NULL) { 1229c19800e8SDoug Rabson ret = ENOMEM; 1230ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 1231c19800e8SDoug Rabson goto out; 1232c19800e8SDoug Rabson } 1233c19800e8SDoug Rabson ret = LDAP_get_generalized_time_value(db, msg, "krb5PasswordEnd", 1234c19800e8SDoug Rabson ent->entry.pw_end); 1235c19800e8SDoug Rabson if (ret) { 12365e9cd1aeSAssar Westerlund /* OPTIONAL */ 1237c19800e8SDoug Rabson free(ent->entry.pw_end); 1238c19800e8SDoug Rabson ent->entry.pw_end = NULL; 12395e9cd1aeSAssar Westerlund } 12405e9cd1aeSAssar Westerlund 1241ae771770SStanislav Sedov ret = LDAP_get_integer_value(db, msg, "sambaPwdLastSet", &tmp_time); 1242ae771770SStanislav Sedov if (ret == 0) { 1243ae771770SStanislav Sedov time_t delta; 1244ae771770SStanislav Sedov 1245ae771770SStanislav Sedov if (ent->entry.pw_end == NULL) { 1246ae771770SStanislav Sedov ent->entry.pw_end = malloc(sizeof(*ent->entry.pw_end)); 1247ae771770SStanislav Sedov if (ent->entry.pw_end == NULL) { 1248ae771770SStanislav Sedov ret = ENOMEM; 1249ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 1250ae771770SStanislav Sedov goto out; 1251ae771770SStanislav Sedov } 1252ae771770SStanislav Sedov } 1253ae771770SStanislav Sedov 1254ae771770SStanislav Sedov delta = krb5_config_get_time_default(context, NULL, 1255ae771770SStanislav Sedov 365 * 24 * 60 * 60, 1256ae771770SStanislav Sedov "kadmin", 1257ae771770SStanislav Sedov "password_lifetime", 1258ae771770SStanislav Sedov NULL); 1259ae771770SStanislav Sedov *ent->entry.pw_end = tmp_time + delta; 1260ae771770SStanislav Sedov } 1261ae771770SStanislav Sedov 1262c19800e8SDoug Rabson ret = LDAP_get_integer_value(db, msg, "sambaPwdMustChange", &tmp_time); 1263c19800e8SDoug Rabson if (ret == 0) { 1264c19800e8SDoug Rabson if (ent->entry.pw_end == NULL) { 1265c19800e8SDoug Rabson ent->entry.pw_end = malloc(sizeof(*ent->entry.pw_end)); 1266c19800e8SDoug Rabson if (ent->entry.pw_end == NULL) { 12675e9cd1aeSAssar Westerlund ret = ENOMEM; 1268ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 12695e9cd1aeSAssar Westerlund goto out; 12705e9cd1aeSAssar Westerlund } 1271c19800e8SDoug Rabson } 1272c19800e8SDoug Rabson *ent->entry.pw_end = tmp_time; 12735e9cd1aeSAssar Westerlund } 12745e9cd1aeSAssar Westerlund 1275c19800e8SDoug Rabson /* OPTIONAL */ 1276c19800e8SDoug Rabson ret = LDAP_get_integer_value(db, msg, "sambaPwdLastSet", &tmp_time); 1277c19800e8SDoug Rabson if (ret == 0) 1278c19800e8SDoug Rabson hdb_entry_set_pw_change_time(context, &ent->entry, tmp_time); 1279c19800e8SDoug Rabson 1280c19800e8SDoug Rabson { 1281c19800e8SDoug Rabson int max_life; 1282c19800e8SDoug Rabson 1283c19800e8SDoug Rabson ent->entry.max_life = malloc(sizeof(*ent->entry.max_life)); 1284c19800e8SDoug Rabson if (ent->entry.max_life == NULL) { 12855e9cd1aeSAssar Westerlund ret = ENOMEM; 1286ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 12875e9cd1aeSAssar Westerlund goto out; 12885e9cd1aeSAssar Westerlund } 1289c19800e8SDoug Rabson ret = LDAP_get_integer_value(db, msg, "krb5MaxLife", &max_life); 1290c19800e8SDoug Rabson if (ret) { 1291c19800e8SDoug Rabson free(ent->entry.max_life); 1292c19800e8SDoug Rabson ent->entry.max_life = NULL; 1293c19800e8SDoug Rabson } else 1294c19800e8SDoug Rabson *ent->entry.max_life = max_life; 12955e9cd1aeSAssar Westerlund } 12965e9cd1aeSAssar Westerlund 1297c19800e8SDoug Rabson { 1298c19800e8SDoug Rabson int max_renew; 1299c19800e8SDoug Rabson 1300c19800e8SDoug Rabson ent->entry.max_renew = malloc(sizeof(*ent->entry.max_renew)); 1301c19800e8SDoug Rabson if (ent->entry.max_renew == NULL) { 1302c19800e8SDoug Rabson ret = ENOMEM; 1303ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 1304c19800e8SDoug Rabson goto out; 1305c19800e8SDoug Rabson } 1306c19800e8SDoug Rabson ret = LDAP_get_integer_value(db, msg, "krb5MaxRenew", &max_renew); 1307c19800e8SDoug Rabson if (ret) { 1308c19800e8SDoug Rabson free(ent->entry.max_renew); 1309c19800e8SDoug Rabson ent->entry.max_renew = NULL; 1310c19800e8SDoug Rabson } else 1311c19800e8SDoug Rabson *ent->entry.max_renew = max_renew; 1312c19800e8SDoug Rabson } 1313c19800e8SDoug Rabson 1314ae771770SStanislav Sedov ret = LDAP_get_integer_value(db, msg, "krb5KDCFlags", &tmp); 1315ae771770SStanislav Sedov if (ret) 13165e9cd1aeSAssar Westerlund tmp = 0; 13175e9cd1aeSAssar Westerlund 1318c19800e8SDoug Rabson ent->entry.flags = int2HDBFlags(tmp); 1319c19800e8SDoug Rabson 1320c19800e8SDoug Rabson /* Try and find Samba flags to put into the mix */ 1321c19800e8SDoug Rabson ret = LDAP_get_string_value(db, msg, "sambaAcctFlags", &samba_acct_flags); 1322c19800e8SDoug Rabson if (ret == 0) { 1323c19800e8SDoug Rabson /* parse the [UXW...] string: 1324c19800e8SDoug Rabson 1325c19800e8SDoug Rabson 'N' No password 1326c19800e8SDoug Rabson 'D' Disabled 1327c19800e8SDoug Rabson 'H' Homedir required 1328c19800e8SDoug Rabson 'T' Temp account. 1329c19800e8SDoug Rabson 'U' User account (normal) 1330c19800e8SDoug Rabson 'M' MNS logon user account - what is this ? 1331c19800e8SDoug Rabson 'W' Workstation account 1332c19800e8SDoug Rabson 'S' Server account 1333c19800e8SDoug Rabson 'L' Locked account 1334c19800e8SDoug Rabson 'X' No Xpiry on password 1335c19800e8SDoug Rabson 'I' Interdomain trust account 1336c19800e8SDoug Rabson 1337c19800e8SDoug Rabson */ 1338c19800e8SDoug Rabson 13395e9cd1aeSAssar Westerlund int i; 1340c19800e8SDoug Rabson int flags_len = strlen(samba_acct_flags); 13415e9cd1aeSAssar Westerlund 1342c19800e8SDoug Rabson if (flags_len < 2) 1343c19800e8SDoug Rabson goto out2; 1344c19800e8SDoug Rabson 1345c19800e8SDoug Rabson if (samba_acct_flags[0] != '[' 1346c19800e8SDoug Rabson || samba_acct_flags[flags_len - 1] != ']') 1347c19800e8SDoug Rabson goto out2; 1348c19800e8SDoug Rabson 1349c19800e8SDoug Rabson /* Allow forwarding */ 1350c19800e8SDoug Rabson if (samba_forwardable) 1351c19800e8SDoug Rabson ent->entry.flags.forwardable = TRUE; 1352c19800e8SDoug Rabson 1353c19800e8SDoug Rabson for (i=0; i < flags_len; i++) { 1354c19800e8SDoug Rabson switch (samba_acct_flags[i]) { 1355c19800e8SDoug Rabson case ' ': 1356c19800e8SDoug Rabson case '[': 1357c19800e8SDoug Rabson case ']': 1358c19800e8SDoug Rabson break; 1359c19800e8SDoug Rabson case 'N': 1360c19800e8SDoug Rabson /* how to handle no password in kerberos? */ 1361c19800e8SDoug Rabson break; 1362c19800e8SDoug Rabson case 'D': 1363c19800e8SDoug Rabson ent->entry.flags.invalid = TRUE; 1364c19800e8SDoug Rabson break; 1365c19800e8SDoug Rabson case 'H': 1366c19800e8SDoug Rabson break; 1367c19800e8SDoug Rabson case 'T': 1368c19800e8SDoug Rabson /* temp duplicate */ 1369c19800e8SDoug Rabson ent->entry.flags.invalid = TRUE; 1370c19800e8SDoug Rabson break; 1371c19800e8SDoug Rabson case 'U': 1372c19800e8SDoug Rabson ent->entry.flags.client = TRUE; 1373c19800e8SDoug Rabson break; 1374c19800e8SDoug Rabson case 'M': 1375c19800e8SDoug Rabson break; 1376c19800e8SDoug Rabson case 'W': 1377c19800e8SDoug Rabson case 'S': 1378c19800e8SDoug Rabson ent->entry.flags.server = TRUE; 1379c19800e8SDoug Rabson ent->entry.flags.client = TRUE; 1380c19800e8SDoug Rabson break; 1381c19800e8SDoug Rabson case 'L': 1382c19800e8SDoug Rabson ent->entry.flags.invalid = TRUE; 1383c19800e8SDoug Rabson break; 1384c19800e8SDoug Rabson case 'X': 1385c19800e8SDoug Rabson if (ent->entry.pw_end) { 1386c19800e8SDoug Rabson free(ent->entry.pw_end); 1387c19800e8SDoug Rabson ent->entry.pw_end = NULL; 13885e9cd1aeSAssar Westerlund } 1389c19800e8SDoug Rabson break; 1390c19800e8SDoug Rabson case 'I': 1391c19800e8SDoug Rabson ent->entry.flags.server = TRUE; 1392c19800e8SDoug Rabson ent->entry.flags.client = TRUE; 1393c19800e8SDoug Rabson break; 13945e9cd1aeSAssar Westerlund } 1395c19800e8SDoug Rabson } 1396c19800e8SDoug Rabson out2: 1397c19800e8SDoug Rabson free(samba_acct_flags); 13985e9cd1aeSAssar Westerlund } 13995e9cd1aeSAssar Westerlund 14005e9cd1aeSAssar Westerlund ret = 0; 14015e9cd1aeSAssar Westerlund 14025e9cd1aeSAssar Westerlund out: 1403c19800e8SDoug Rabson if (unparsed_name) 14045e9cd1aeSAssar Westerlund free(unparsed_name); 14055e9cd1aeSAssar Westerlund 1406c19800e8SDoug Rabson if (ret) 14075e9cd1aeSAssar Westerlund hdb_free_entry(context, ent); 14085e9cd1aeSAssar Westerlund 14095e9cd1aeSAssar Westerlund return ret; 14105e9cd1aeSAssar Westerlund } 14115e9cd1aeSAssar Westerlund 1412c19800e8SDoug Rabson static krb5_error_code 1413c19800e8SDoug Rabson LDAP_close(krb5_context context, HDB * db) 14145e9cd1aeSAssar Westerlund { 1415c19800e8SDoug Rabson if (HDB2LDAP(db)) { 1416c19800e8SDoug Rabson ldap_unbind_ext(HDB2LDAP(db), NULL, NULL); 1417c19800e8SDoug Rabson ((struct hdbldapdb *)db->hdb_db)->h_lp = NULL; 1418c19800e8SDoug Rabson } 14194137ff4cSJacques Vidrine 14205e9cd1aeSAssar Westerlund return 0; 14215e9cd1aeSAssar Westerlund } 14225e9cd1aeSAssar Westerlund 14235e9cd1aeSAssar Westerlund static krb5_error_code 14245e9cd1aeSAssar Westerlund LDAP_lock(krb5_context context, HDB * db, int operation) 14255e9cd1aeSAssar Westerlund { 14265e9cd1aeSAssar Westerlund return 0; 14275e9cd1aeSAssar Westerlund } 14285e9cd1aeSAssar Westerlund 1429c19800e8SDoug Rabson static krb5_error_code 1430c19800e8SDoug Rabson LDAP_unlock(krb5_context context, HDB * db) 14315e9cd1aeSAssar Westerlund { 14325e9cd1aeSAssar Westerlund return 0; 14335e9cd1aeSAssar Westerlund } 14345e9cd1aeSAssar Westerlund 14355e9cd1aeSAssar Westerlund static krb5_error_code 1436c19800e8SDoug Rabson LDAP_seq(krb5_context context, HDB * db, unsigned flags, hdb_entry_ex * entry) 14375e9cd1aeSAssar Westerlund { 14385e9cd1aeSAssar Westerlund int msgid, rc, parserc; 14395e9cd1aeSAssar Westerlund krb5_error_code ret; 14405e9cd1aeSAssar Westerlund LDAPMessage *e; 14415e9cd1aeSAssar Westerlund 1442c19800e8SDoug Rabson msgid = HDB2MSGID(db); 1443c19800e8SDoug Rabson if (msgid < 0) 14445e9cd1aeSAssar Westerlund return HDB_ERR_NOENTRY; 14455e9cd1aeSAssar Westerlund 14465e9cd1aeSAssar Westerlund do { 1447c19800e8SDoug Rabson rc = ldap_result(HDB2LDAP(db), msgid, LDAP_MSG_ONE, NULL, &e); 14485e9cd1aeSAssar Westerlund switch (rc) { 1449c19800e8SDoug Rabson case LDAP_RES_SEARCH_REFERENCE: 1450c19800e8SDoug Rabson ldap_msgfree(e); 1451c19800e8SDoug Rabson ret = 0; 1452c19800e8SDoug Rabson break; 14535e9cd1aeSAssar Westerlund case LDAP_RES_SEARCH_ENTRY: 14545e9cd1aeSAssar Westerlund /* We have an entry. Parse it. */ 1455ae771770SStanislav Sedov ret = LDAP_message2entry(context, db, e, flags, entry); 14565e9cd1aeSAssar Westerlund ldap_msgfree(e); 14575e9cd1aeSAssar Westerlund break; 14585e9cd1aeSAssar Westerlund case LDAP_RES_SEARCH_RESULT: 14595e9cd1aeSAssar Westerlund /* We're probably at the end of the results. If not, abandon. */ 14605e9cd1aeSAssar Westerlund parserc = 1461c19800e8SDoug Rabson ldap_parse_result(HDB2LDAP(db), e, NULL, NULL, NULL, 14625e9cd1aeSAssar Westerlund NULL, NULL, 1); 1463ae771770SStanislav Sedov ret = HDB_ERR_NOENTRY; 14645e9cd1aeSAssar Westerlund if (parserc != LDAP_SUCCESS 14655e9cd1aeSAssar Westerlund && parserc != LDAP_MORE_RESULTS_TO_RETURN) { 1466ae771770SStanislav Sedov krb5_set_error_message(context, ret, "ldap_parse_result: %s", 1467c19800e8SDoug Rabson ldap_err2string(parserc)); 1468ae771770SStanislav Sedov ldap_abandon_ext(HDB2LDAP(db), msgid, NULL, NULL); 14695e9cd1aeSAssar Westerlund } 1470c19800e8SDoug Rabson HDBSETMSGID(db, -1); 14715e9cd1aeSAssar Westerlund break; 1472c19800e8SDoug Rabson case LDAP_SERVER_DOWN: 1473c19800e8SDoug Rabson ldap_msgfree(e); 1474c19800e8SDoug Rabson LDAP_close(context, db); 1475c19800e8SDoug Rabson HDBSETMSGID(db, -1); 1476c19800e8SDoug Rabson ret = ENETDOWN; 1477c19800e8SDoug Rabson break; 14785e9cd1aeSAssar Westerlund default: 14795e9cd1aeSAssar Westerlund /* Some unspecified error (timeout?). Abandon. */ 14805e9cd1aeSAssar Westerlund ldap_msgfree(e); 1481ae771770SStanislav Sedov ldap_abandon_ext(HDB2LDAP(db), msgid, NULL, NULL); 14825e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 1483c19800e8SDoug Rabson HDBSETMSGID(db, -1); 14845e9cd1aeSAssar Westerlund break; 14855e9cd1aeSAssar Westerlund } 14865e9cd1aeSAssar Westerlund } while (rc == LDAP_RES_SEARCH_REFERENCE); 14875e9cd1aeSAssar Westerlund 14885e9cd1aeSAssar Westerlund if (ret == 0) { 1489c19800e8SDoug Rabson if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) { 1490c19800e8SDoug Rabson ret = hdb_unseal_keys(context, db, &entry->entry); 14915e9cd1aeSAssar Westerlund if (ret) 14925e9cd1aeSAssar Westerlund hdb_free_entry(context, entry); 14935e9cd1aeSAssar Westerlund } 14945e9cd1aeSAssar Westerlund } 14955e9cd1aeSAssar Westerlund 14965e9cd1aeSAssar Westerlund return ret; 14975e9cd1aeSAssar Westerlund } 14985e9cd1aeSAssar Westerlund 14995e9cd1aeSAssar Westerlund static krb5_error_code 15005e9cd1aeSAssar Westerlund LDAP_firstkey(krb5_context context, HDB *db, unsigned flags, 1501c19800e8SDoug Rabson hdb_entry_ex *entry) 15025e9cd1aeSAssar Westerlund { 1503c19800e8SDoug Rabson krb5_error_code ret; 1504c19800e8SDoug Rabson int msgid; 15055e9cd1aeSAssar Westerlund 1506c19800e8SDoug Rabson ret = LDAP__connect(context, db); 1507c19800e8SDoug Rabson if (ret) 1508c19800e8SDoug Rabson return ret; 15095e9cd1aeSAssar Westerlund 1510c19800e8SDoug Rabson ret = LDAP_no_size_limit(context, HDB2LDAP(db)); 1511c19800e8SDoug Rabson if (ret) 1512c19800e8SDoug Rabson return ret; 15135e9cd1aeSAssar Westerlund 1514ae771770SStanislav Sedov ret = ldap_search_ext(HDB2LDAP(db), HDB2BASE(db), 1515c19800e8SDoug Rabson LDAP_SCOPE_SUBTREE, 1516c19800e8SDoug Rabson "(|(objectClass=krb5Principal)(objectClass=sambaSamAccount))", 1517ae771770SStanislav Sedov krb5kdcentry_attrs, 0, 1518ae771770SStanislav Sedov NULL, NULL, NULL, 0, &msgid); 1519c19800e8SDoug Rabson if (msgid < 0) 15205e9cd1aeSAssar Westerlund return HDB_ERR_NOENTRY; 15215e9cd1aeSAssar Westerlund 1522c19800e8SDoug Rabson HDBSETMSGID(db, msgid); 15235e9cd1aeSAssar Westerlund 15245e9cd1aeSAssar Westerlund return LDAP_seq(context, db, flags, entry); 15255e9cd1aeSAssar Westerlund } 15265e9cd1aeSAssar Westerlund 15275e9cd1aeSAssar Westerlund static krb5_error_code 15285e9cd1aeSAssar Westerlund LDAP_nextkey(krb5_context context, HDB * db, unsigned flags, 1529c19800e8SDoug Rabson hdb_entry_ex * entry) 15305e9cd1aeSAssar Westerlund { 15315e9cd1aeSAssar Westerlund return LDAP_seq(context, db, flags, entry); 15325e9cd1aeSAssar Westerlund } 15335e9cd1aeSAssar Westerlund 15345e9cd1aeSAssar Westerlund static krb5_error_code 1535c19800e8SDoug Rabson LDAP__connect(krb5_context context, HDB * db) 15365e9cd1aeSAssar Westerlund { 15374137ff4cSJacques Vidrine int rc, version = LDAP_VERSION3; 15381c43270aSJacques Vidrine /* 15391c43270aSJacques Vidrine * Empty credentials to do a SASL bind with LDAP. Note that empty 15401c43270aSJacques Vidrine * different from NULL credentials. If you provide NULL 15411c43270aSJacques Vidrine * credentials instead of empty credentials you will get a SASL 15421c43270aSJacques Vidrine * bind in progress message. 15431c43270aSJacques Vidrine */ 15441c43270aSJacques Vidrine struct berval bv = { 0, "" }; 15455e9cd1aeSAssar Westerlund 1546c19800e8SDoug Rabson if (HDB2LDAP(db)) { 15475e9cd1aeSAssar Westerlund /* connection has been opened. ping server. */ 15485e9cd1aeSAssar Westerlund struct sockaddr_un addr; 1549c19800e8SDoug Rabson socklen_t len = sizeof(addr); 15505e9cd1aeSAssar Westerlund int sd; 15515e9cd1aeSAssar Westerlund 1552c19800e8SDoug Rabson if (ldap_get_option(HDB2LDAP(db), LDAP_OPT_DESC, &sd) == 0 && 15535e9cd1aeSAssar Westerlund getpeername(sd, (struct sockaddr *) &addr, &len) < 0) { 15545e9cd1aeSAssar Westerlund /* the other end has died. reopen. */ 15555e9cd1aeSAssar Westerlund LDAP_close(context, db); 15565e9cd1aeSAssar Westerlund } 15575e9cd1aeSAssar Westerlund } 15585e9cd1aeSAssar Westerlund 1559c19800e8SDoug Rabson if (HDB2LDAP(db) != NULL) /* server is UP */ 15605e9cd1aeSAssar Westerlund return 0; 15615e9cd1aeSAssar Westerlund 1562c19800e8SDoug Rabson rc = ldap_initialize(&((struct hdbldapdb *)db->hdb_db)->h_lp, HDB2URL(db)); 15635e9cd1aeSAssar Westerlund if (rc != LDAP_SUCCESS) { 1564ae771770SStanislav Sedov krb5_set_error_message(context, HDB_ERR_NOENTRY, "ldap_initialize: %s", 1565c19800e8SDoug Rabson ldap_err2string(rc)); 15665e9cd1aeSAssar Westerlund return HDB_ERR_NOENTRY; 15675e9cd1aeSAssar Westerlund } 15685e9cd1aeSAssar Westerlund 1569c19800e8SDoug Rabson rc = ldap_set_option(HDB2LDAP(db), LDAP_OPT_PROTOCOL_VERSION, 1570c19800e8SDoug Rabson (const void *)&version); 15715e9cd1aeSAssar Westerlund if (rc != LDAP_SUCCESS) { 1572ae771770SStanislav Sedov krb5_set_error_message(context, HDB_ERR_BADVERSION, 1573ae771770SStanislav Sedov "ldap_set_option: %s", ldap_err2string(rc)); 1574c19800e8SDoug Rabson LDAP_close(context, db); 15754137ff4cSJacques Vidrine return HDB_ERR_BADVERSION; 15765e9cd1aeSAssar Westerlund } 15775e9cd1aeSAssar Westerlund 1578c19800e8SDoug Rabson rc = ldap_sasl_bind_s(HDB2LDAP(db), NULL, "EXTERNAL", &bv, 1579c19800e8SDoug Rabson NULL, NULL, NULL); 15801c43270aSJacques Vidrine if (rc != LDAP_SUCCESS) { 1581ae771770SStanislav Sedov krb5_set_error_message(context, HDB_ERR_BADVERSION, 1582ae771770SStanislav Sedov "ldap_sasl_bind_s: %s", ldap_err2string(rc)); 1583c19800e8SDoug Rabson LDAP_close(context, db); 15841c43270aSJacques Vidrine return HDB_ERR_BADVERSION; 15851c43270aSJacques Vidrine } 15861c43270aSJacques Vidrine 15874137ff4cSJacques Vidrine return 0; 15885e9cd1aeSAssar Westerlund } 15895e9cd1aeSAssar Westerlund 15905e9cd1aeSAssar Westerlund static krb5_error_code 15915e9cd1aeSAssar Westerlund LDAP_open(krb5_context context, HDB * db, int flags, mode_t mode) 15925e9cd1aeSAssar Westerlund { 15935e9cd1aeSAssar Westerlund /* Not the right place for this. */ 15945e9cd1aeSAssar Westerlund #ifdef HAVE_SIGACTION 15955e9cd1aeSAssar Westerlund struct sigaction sa; 15965e9cd1aeSAssar Westerlund 15975e9cd1aeSAssar Westerlund sa.sa_flags = 0; 15985e9cd1aeSAssar Westerlund sa.sa_handler = SIG_IGN; 15995e9cd1aeSAssar Westerlund sigemptyset(&sa.sa_mask); 16005e9cd1aeSAssar Westerlund 16015e9cd1aeSAssar Westerlund sigaction(SIGPIPE, &sa, NULL); 16025e9cd1aeSAssar Westerlund #else 16035e9cd1aeSAssar Westerlund signal(SIGPIPE, SIG_IGN); 16044137ff4cSJacques Vidrine #endif /* HAVE_SIGACTION */ 16055e9cd1aeSAssar Westerlund 16064137ff4cSJacques Vidrine return LDAP__connect(context, db); 16075e9cd1aeSAssar Westerlund } 16085e9cd1aeSAssar Westerlund 16095e9cd1aeSAssar Westerlund static krb5_error_code 1610ae771770SStanislav Sedov LDAP_fetch_kvno(krb5_context context, HDB * db, krb5_const_principal principal, 1611ae771770SStanislav Sedov unsigned flags, krb5_kvno kvno, hdb_entry_ex * entry) 16125e9cd1aeSAssar Westerlund { 16135e9cd1aeSAssar Westerlund LDAPMessage *msg, *e; 16145e9cd1aeSAssar Westerlund krb5_error_code ret; 16155e9cd1aeSAssar Westerlund 1616c19800e8SDoug Rabson ret = LDAP_principal2message(context, db, principal, &msg); 1617c19800e8SDoug Rabson if (ret) 16185e9cd1aeSAssar Westerlund return ret; 16195e9cd1aeSAssar Westerlund 1620c19800e8SDoug Rabson e = ldap_first_entry(HDB2LDAP(db), msg); 16215e9cd1aeSAssar Westerlund if (e == NULL) { 16225e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 16235e9cd1aeSAssar Westerlund goto out; 16245e9cd1aeSAssar Westerlund } 16255e9cd1aeSAssar Westerlund 1626ae771770SStanislav Sedov ret = LDAP_message2entry(context, db, e, flags, entry); 16275e9cd1aeSAssar Westerlund if (ret == 0) { 1628c19800e8SDoug Rabson if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) { 1629c19800e8SDoug Rabson ret = hdb_unseal_keys(context, db, &entry->entry); 16305e9cd1aeSAssar Westerlund if (ret) 16315e9cd1aeSAssar Westerlund hdb_free_entry(context, entry); 16325e9cd1aeSAssar Westerlund } 16335e9cd1aeSAssar Westerlund } 16345e9cd1aeSAssar Westerlund 16355e9cd1aeSAssar Westerlund out: 16365e9cd1aeSAssar Westerlund ldap_msgfree(msg); 16375e9cd1aeSAssar Westerlund 16385e9cd1aeSAssar Westerlund return ret; 16395e9cd1aeSAssar Westerlund } 16405e9cd1aeSAssar Westerlund 16415e9cd1aeSAssar Westerlund static krb5_error_code 1642ae771770SStanislav Sedov LDAP_fetch(krb5_context context, HDB * db, krb5_const_principal principal, 1643ae771770SStanislav Sedov unsigned flags, hdb_entry_ex * entry) 1644ae771770SStanislav Sedov { 1645ae771770SStanislav Sedov return LDAP_fetch_kvno(context, db, principal, 1646ae771770SStanislav Sedov flags & (~HDB_F_KVNO_SPECIFIED), 0, entry); 1647ae771770SStanislav Sedov } 1648ae771770SStanislav Sedov 1649ae771770SStanislav Sedov static krb5_error_code 16505e9cd1aeSAssar Westerlund LDAP_store(krb5_context context, HDB * db, unsigned flags, 1651c19800e8SDoug Rabson hdb_entry_ex * entry) 16525e9cd1aeSAssar Westerlund { 16535e9cd1aeSAssar Westerlund LDAPMod **mods = NULL; 16545e9cd1aeSAssar Westerlund krb5_error_code ret; 16554137ff4cSJacques Vidrine const char *errfn; 16564137ff4cSJacques Vidrine int rc; 16575e9cd1aeSAssar Westerlund LDAPMessage *msg = NULL, *e = NULL; 16585e9cd1aeSAssar Westerlund char *dn = NULL, *name = NULL; 16595e9cd1aeSAssar Westerlund 1660c19800e8SDoug Rabson ret = LDAP_principal2message(context, db, entry->entry.principal, &msg); 1661c19800e8SDoug Rabson if (ret == 0) 1662c19800e8SDoug Rabson e = ldap_first_entry(HDB2LDAP(db), msg); 1663c19800e8SDoug Rabson 1664c19800e8SDoug Rabson ret = krb5_unparse_name(context, entry->entry.principal, &name); 1665c19800e8SDoug Rabson if (ret) { 1666c19800e8SDoug Rabson free(name); 1667c19800e8SDoug Rabson return ret; 16685e9cd1aeSAssar Westerlund } 16695e9cd1aeSAssar Westerlund 1670c19800e8SDoug Rabson ret = hdb_seal_keys(context, db, &entry->entry); 1671c19800e8SDoug Rabson if (ret) 16725e9cd1aeSAssar Westerlund goto out; 16735e9cd1aeSAssar Westerlund 16745e9cd1aeSAssar Westerlund /* turn new entry into LDAPMod array */ 16755e9cd1aeSAssar Westerlund ret = LDAP_entry2mods(context, db, entry, e, &mods); 1676c19800e8SDoug Rabson if (ret) 16775e9cd1aeSAssar Westerlund goto out; 16785e9cd1aeSAssar Westerlund 16795e9cd1aeSAssar Westerlund if (e == NULL) { 1680c19800e8SDoug Rabson ret = asprintf(&dn, "krb5PrincipalName=%s,%s", name, HDB2CREATE(db)); 16815e9cd1aeSAssar Westerlund if (ret < 0) { 16825e9cd1aeSAssar Westerlund ret = ENOMEM; 1683ae771770SStanislav Sedov krb5_set_error_message(context, ret, "asprintf: out of memory"); 16845e9cd1aeSAssar Westerlund goto out; 16855e9cd1aeSAssar Westerlund } 16865e9cd1aeSAssar Westerlund } else if (flags & HDB_F_REPLACE) { 16875e9cd1aeSAssar Westerlund /* Entry exists, and we're allowed to replace it. */ 1688c19800e8SDoug Rabson dn = ldap_get_dn(HDB2LDAP(db), e); 16895e9cd1aeSAssar Westerlund } else { 16905e9cd1aeSAssar Westerlund /* Entry exists, but we're not allowed to replace it. Bail. */ 16915e9cd1aeSAssar Westerlund ret = HDB_ERR_EXISTS; 16925e9cd1aeSAssar Westerlund goto out; 16935e9cd1aeSAssar Westerlund } 16945e9cd1aeSAssar Westerlund 16955e9cd1aeSAssar Westerlund /* write entry into directory */ 16965e9cd1aeSAssar Westerlund if (e == NULL) { 16975e9cd1aeSAssar Westerlund /* didn't exist before */ 1698ae771770SStanislav Sedov rc = ldap_add_ext_s(HDB2LDAP(db), dn, mods, NULL, NULL ); 1699ae771770SStanislav Sedov errfn = "ldap_add_ext_s"; 17005e9cd1aeSAssar Westerlund } else { 17015e9cd1aeSAssar Westerlund /* already existed, send deltas only */ 1702ae771770SStanislav Sedov rc = ldap_modify_ext_s(HDB2LDAP(db), dn, mods, NULL, NULL ); 1703ae771770SStanislav Sedov errfn = "ldap_modify_ext_s"; 17045e9cd1aeSAssar Westerlund } 17055e9cd1aeSAssar Westerlund 1706c19800e8SDoug Rabson if (check_ldap(context, db, rc)) { 1707c19800e8SDoug Rabson char *ld_error = NULL; 1708c19800e8SDoug Rabson ldap_get_option(HDB2LDAP(db), LDAP_OPT_ERROR_STRING, 1709c19800e8SDoug Rabson &ld_error); 17105e9cd1aeSAssar Westerlund ret = HDB_ERR_CANT_LOCK_DB; 1711ae771770SStanislav Sedov krb5_set_error_message(context, ret, "%s: %s (DN=%s) %s: %s", 1712ae771770SStanislav Sedov errfn, name, dn, ldap_err2string(rc), ld_error); 1713c19800e8SDoug Rabson } else 1714c19800e8SDoug Rabson ret = 0; 17155e9cd1aeSAssar Westerlund 17165e9cd1aeSAssar Westerlund out: 17175e9cd1aeSAssar Westerlund /* free stuff */ 1718c19800e8SDoug Rabson if (dn) 17195e9cd1aeSAssar Westerlund free(dn); 1720c19800e8SDoug Rabson if (msg) 17215e9cd1aeSAssar Westerlund ldap_msgfree(msg); 1722c19800e8SDoug Rabson if (mods) 17235e9cd1aeSAssar Westerlund ldap_mods_free(mods, 1); 1724c19800e8SDoug Rabson if (name) 17255e9cd1aeSAssar Westerlund free(name); 17265e9cd1aeSAssar Westerlund 17275e9cd1aeSAssar Westerlund return ret; 17285e9cd1aeSAssar Westerlund } 17295e9cd1aeSAssar Westerlund 17305e9cd1aeSAssar Westerlund static krb5_error_code 1731c19800e8SDoug Rabson LDAP_remove(krb5_context context, HDB *db, krb5_const_principal principal) 17325e9cd1aeSAssar Westerlund { 17335e9cd1aeSAssar Westerlund krb5_error_code ret; 17345e9cd1aeSAssar Westerlund LDAPMessage *msg, *e; 17355e9cd1aeSAssar Westerlund char *dn = NULL; 17364137ff4cSJacques Vidrine int rc, limit = LDAP_NO_LIMIT; 17375e9cd1aeSAssar Westerlund 1738c19800e8SDoug Rabson ret = LDAP_principal2message(context, db, principal, &msg); 1739c19800e8SDoug Rabson if (ret) 17405e9cd1aeSAssar Westerlund goto out; 17415e9cd1aeSAssar Westerlund 1742c19800e8SDoug Rabson e = ldap_first_entry(HDB2LDAP(db), msg); 17435e9cd1aeSAssar Westerlund if (e == NULL) { 17445e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 17455e9cd1aeSAssar Westerlund goto out; 17465e9cd1aeSAssar Westerlund } 17475e9cd1aeSAssar Westerlund 1748c19800e8SDoug Rabson dn = ldap_get_dn(HDB2LDAP(db), e); 17495e9cd1aeSAssar Westerlund if (dn == NULL) { 17505e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 17515e9cd1aeSAssar Westerlund goto out; 17525e9cd1aeSAssar Westerlund } 17535e9cd1aeSAssar Westerlund 1754c19800e8SDoug Rabson rc = ldap_set_option(HDB2LDAP(db), LDAP_OPT_SIZELIMIT, (const void *)&limit); 17554137ff4cSJacques Vidrine if (rc != LDAP_SUCCESS) { 17564137ff4cSJacques Vidrine ret = HDB_ERR_BADVERSION; 1757ae771770SStanislav Sedov krb5_set_error_message(context, ret, "ldap_set_option: %s", 1758ae771770SStanislav Sedov ldap_err2string(rc)); 17594137ff4cSJacques Vidrine goto out; 17604137ff4cSJacques Vidrine } 17615e9cd1aeSAssar Westerlund 1762ae771770SStanislav Sedov rc = ldap_delete_ext_s(HDB2LDAP(db), dn, NULL, NULL ); 1763c19800e8SDoug Rabson if (check_ldap(context, db, rc)) { 17645e9cd1aeSAssar Westerlund ret = HDB_ERR_CANT_LOCK_DB; 1765ae771770SStanislav Sedov krb5_set_error_message(context, ret, "ldap_delete_ext_s: %s", 1766ae771770SStanislav Sedov ldap_err2string(rc)); 1767c19800e8SDoug Rabson } else 1768c19800e8SDoug Rabson ret = 0; 17695e9cd1aeSAssar Westerlund 17705e9cd1aeSAssar Westerlund out: 1771c19800e8SDoug Rabson if (dn != NULL) 17725e9cd1aeSAssar Westerlund free(dn); 1773c19800e8SDoug Rabson if (msg != NULL) 17745e9cd1aeSAssar Westerlund ldap_msgfree(msg); 17755e9cd1aeSAssar Westerlund 17765e9cd1aeSAssar Westerlund return ret; 17775e9cd1aeSAssar Westerlund } 17785e9cd1aeSAssar Westerlund 17795e9cd1aeSAssar Westerlund static krb5_error_code 1780c19800e8SDoug Rabson LDAP_destroy(krb5_context context, HDB * db) 17815e9cd1aeSAssar Westerlund { 17825e9cd1aeSAssar Westerlund krb5_error_code ret; 17835e9cd1aeSAssar Westerlund 1784c19800e8SDoug Rabson LDAP_close(context, db); 1785c19800e8SDoug Rabson 17865e9cd1aeSAssar Westerlund ret = hdb_clear_master_key(context, db); 1787c19800e8SDoug Rabson if (HDB2BASE(db)) 1788c19800e8SDoug Rabson free(HDB2BASE(db)); 1789c19800e8SDoug Rabson if (HDB2CREATE(db)) 1790c19800e8SDoug Rabson free(HDB2CREATE(db)); 1791c19800e8SDoug Rabson if (HDB2URL(db)) 1792c19800e8SDoug Rabson free(HDB2URL(db)); 1793c19800e8SDoug Rabson if (db->hdb_name) 1794c19800e8SDoug Rabson free(db->hdb_name); 1795c19800e8SDoug Rabson free(db->hdb_db); 17965e9cd1aeSAssar Westerlund free(db); 17975e9cd1aeSAssar Westerlund 17985e9cd1aeSAssar Westerlund return ret; 17995e9cd1aeSAssar Westerlund } 18005e9cd1aeSAssar Westerlund 1801ae771770SStanislav Sedov static krb5_error_code 1802c19800e8SDoug Rabson hdb_ldap_common(krb5_context context, 1803c19800e8SDoug Rabson HDB ** db, 1804c19800e8SDoug Rabson const char *search_base, 1805c19800e8SDoug Rabson const char *url) 18065e9cd1aeSAssar Westerlund { 1807c19800e8SDoug Rabson struct hdbldapdb *h; 1808c19800e8SDoug Rabson const char *create_base = NULL; 1809c19800e8SDoug Rabson 1810c19800e8SDoug Rabson if (search_base == NULL && search_base[0] == '\0') { 1811ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, "ldap search base not configured"); 1812c19800e8SDoug Rabson return ENOMEM; /* XXX */ 1813c19800e8SDoug Rabson } 1814c19800e8SDoug Rabson 1815c19800e8SDoug Rabson if (structural_object == NULL) { 1816c19800e8SDoug Rabson const char *p; 1817c19800e8SDoug Rabson 1818c19800e8SDoug Rabson p = krb5_config_get_string(context, NULL, "kdc", 1819c19800e8SDoug Rabson "hdb-ldap-structural-object", NULL); 1820c19800e8SDoug Rabson if (p == NULL) 1821c19800e8SDoug Rabson p = default_structural_object; 1822c19800e8SDoug Rabson structural_object = strdup(p); 1823c19800e8SDoug Rabson if (structural_object == NULL) { 1824ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 1825c19800e8SDoug Rabson return ENOMEM; 1826c19800e8SDoug Rabson } 1827c19800e8SDoug Rabson } 1828c19800e8SDoug Rabson 1829c19800e8SDoug Rabson samba_forwardable = 1830c19800e8SDoug Rabson krb5_config_get_bool_default(context, NULL, TRUE, 1831c19800e8SDoug Rabson "kdc", "hdb-samba-forwardable", NULL); 1832c19800e8SDoug Rabson 1833c19800e8SDoug Rabson *db = calloc(1, sizeof(**db)); 18344137ff4cSJacques Vidrine if (*db == NULL) { 1835ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 18365e9cd1aeSAssar Westerlund return ENOMEM; 18374137ff4cSJacques Vidrine } 1838c19800e8SDoug Rabson memset(*db, 0, sizeof(**db)); 18395e9cd1aeSAssar Westerlund 1840c19800e8SDoug Rabson h = calloc(1, sizeof(*h)); 1841c19800e8SDoug Rabson if (h == NULL) { 18424137ff4cSJacques Vidrine free(*db); 18434137ff4cSJacques Vidrine *db = NULL; 1844ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 18454137ff4cSJacques Vidrine return ENOMEM; 18464137ff4cSJacques Vidrine } 1847c19800e8SDoug Rabson (*db)->hdb_db = h; 1848c19800e8SDoug Rabson 1849c19800e8SDoug Rabson /* XXX */ 1850c19800e8SDoug Rabson if (asprintf(&(*db)->hdb_name, "ldap:%s", search_base) == -1) { 1851c19800e8SDoug Rabson LDAP_destroy(context, *db); 1852c19800e8SDoug Rabson *db = NULL; 1853ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, "strdup: out of memory"); 1854c19800e8SDoug Rabson return ENOMEM; 18554137ff4cSJacques Vidrine } 18564137ff4cSJacques Vidrine 1857c19800e8SDoug Rabson h->h_url = strdup(url); 1858c19800e8SDoug Rabson h->h_base = strdup(search_base); 1859c19800e8SDoug Rabson if (h->h_url == NULL || h->h_base == NULL) { 1860c19800e8SDoug Rabson LDAP_destroy(context, *db); 1861c19800e8SDoug Rabson *db = NULL; 1862ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, "strdup: out of memory"); 1863c19800e8SDoug Rabson return ENOMEM; 1864c19800e8SDoug Rabson } 1865c19800e8SDoug Rabson 1866c19800e8SDoug Rabson create_base = krb5_config_get_string(context, NULL, "kdc", 1867c19800e8SDoug Rabson "hdb-ldap-create-base", NULL); 1868c19800e8SDoug Rabson if (create_base == NULL) 1869c19800e8SDoug Rabson create_base = h->h_base; 1870c19800e8SDoug Rabson 1871c19800e8SDoug Rabson h->h_createbase = strdup(create_base); 1872c19800e8SDoug Rabson if (h->h_createbase == NULL) { 1873c19800e8SDoug Rabson LDAP_destroy(context, *db); 1874c19800e8SDoug Rabson *db = NULL; 1875ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, "strdup: out of memory"); 1876c19800e8SDoug Rabson return ENOMEM; 1877c19800e8SDoug Rabson } 1878c19800e8SDoug Rabson 1879c19800e8SDoug Rabson (*db)->hdb_master_key_set = 0; 1880c19800e8SDoug Rabson (*db)->hdb_openp = 0; 1881ae771770SStanislav Sedov (*db)->hdb_capability_flags = 0; 1882c19800e8SDoug Rabson (*db)->hdb_open = LDAP_open; 1883c19800e8SDoug Rabson (*db)->hdb_close = LDAP_close; 1884ae771770SStanislav Sedov (*db)->hdb_fetch_kvno = LDAP_fetch_kvno; 1885c19800e8SDoug Rabson (*db)->hdb_store = LDAP_store; 1886c19800e8SDoug Rabson (*db)->hdb_remove = LDAP_remove; 1887c19800e8SDoug Rabson (*db)->hdb_firstkey = LDAP_firstkey; 1888c19800e8SDoug Rabson (*db)->hdb_nextkey = LDAP_nextkey; 1889c19800e8SDoug Rabson (*db)->hdb_lock = LDAP_lock; 1890c19800e8SDoug Rabson (*db)->hdb_unlock = LDAP_unlock; 1891c19800e8SDoug Rabson (*db)->hdb_rename = NULL; 1892c19800e8SDoug Rabson (*db)->hdb__get = NULL; 1893c19800e8SDoug Rabson (*db)->hdb__put = NULL; 1894c19800e8SDoug Rabson (*db)->hdb__del = NULL; 1895c19800e8SDoug Rabson (*db)->hdb_destroy = LDAP_destroy; 18965e9cd1aeSAssar Westerlund 18975e9cd1aeSAssar Westerlund return 0; 18985e9cd1aeSAssar Westerlund } 18995e9cd1aeSAssar Westerlund 1900c19800e8SDoug Rabson krb5_error_code 1901c19800e8SDoug Rabson hdb_ldap_create(krb5_context context, HDB ** db, const char *arg) 1902c19800e8SDoug Rabson { 1903c19800e8SDoug Rabson return hdb_ldap_common(context, db, arg, "ldapi:///"); 1904c19800e8SDoug Rabson } 1905c19800e8SDoug Rabson 1906c19800e8SDoug Rabson krb5_error_code 1907c19800e8SDoug Rabson hdb_ldapi_create(krb5_context context, HDB ** db, const char *arg) 1908c19800e8SDoug Rabson { 1909c19800e8SDoug Rabson krb5_error_code ret; 1910c19800e8SDoug Rabson char *search_base, *p; 1911c19800e8SDoug Rabson 1912c19800e8SDoug Rabson asprintf(&p, "ldapi:%s", arg); 1913c19800e8SDoug Rabson if (p == NULL) { 1914c19800e8SDoug Rabson *db = NULL; 1915ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, "out of memory"); 1916c19800e8SDoug Rabson return ENOMEM; 1917c19800e8SDoug Rabson } 1918c19800e8SDoug Rabson search_base = strchr(p + strlen("ldapi://"), ':'); 1919c19800e8SDoug Rabson if (search_base == NULL) { 1920c19800e8SDoug Rabson *db = NULL; 1921ae771770SStanislav Sedov krb5_set_error_message(context, HDB_ERR_BADVERSION, 1922ae771770SStanislav Sedov "search base missing"); 1923c19800e8SDoug Rabson return HDB_ERR_BADVERSION; 1924c19800e8SDoug Rabson } 1925c19800e8SDoug Rabson *search_base = '\0'; 1926c19800e8SDoug Rabson search_base++; 1927c19800e8SDoug Rabson 1928c19800e8SDoug Rabson ret = hdb_ldap_common(context, db, search_base, p); 1929c19800e8SDoug Rabson free(p); 1930c19800e8SDoug Rabson return ret; 1931c19800e8SDoug Rabson } 1932c19800e8SDoug Rabson 1933c19800e8SDoug Rabson #ifdef OPENLDAP_MODULE 1934c19800e8SDoug Rabson 1935c19800e8SDoug Rabson struct hdb_so_method hdb_ldap_interface = { 1936c19800e8SDoug Rabson HDB_INTERFACE_VERSION, 1937c19800e8SDoug Rabson "ldap", 1938c19800e8SDoug Rabson hdb_ldap_create 1939c19800e8SDoug Rabson }; 1940c19800e8SDoug Rabson 1941c19800e8SDoug Rabson struct hdb_so_method hdb_ldapi_interface = { 1942c19800e8SDoug Rabson HDB_INTERFACE_VERSION, 1943c19800e8SDoug Rabson "ldapi", 1944c19800e8SDoug Rabson hdb_ldapi_create 1945c19800e8SDoug Rabson }; 1946c19800e8SDoug Rabson 1947c19800e8SDoug Rabson #endif 1948c19800e8SDoug Rabson 19495e9cd1aeSAssar Westerlund #endif /* OPENLDAP */ 1950