15e9cd1aeSAssar Westerlund /* 2c19800e8SDoug Rabson * Copyright (c) 1999-2001, 2003, PADL Software Pty Ltd. 3c19800e8SDoug Rabson * Copyright (c) 2004, Andrew Bartlett. 4*ae771770SStanislav 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 475e9cd1aeSAssar Westerlund static krb5_error_code 485e9cd1aeSAssar Westerlund LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg, 49*ae771770SStanislav Sedov int flags, hdb_entry_ex * ent); 505e9cd1aeSAssar Westerlund 51c19800e8SDoug Rabson static const char *default_structural_object = "account"; 52c19800e8SDoug Rabson static char *structural_object; 53c19800e8SDoug Rabson static krb5_boolean samba_forwardable; 54c19800e8SDoug Rabson 55c19800e8SDoug Rabson struct hdbldapdb { 56c19800e8SDoug Rabson LDAP *h_lp; 57c19800e8SDoug Rabson int h_msgid; 58c19800e8SDoug Rabson char *h_base; 59c19800e8SDoug Rabson char *h_url; 60c19800e8SDoug Rabson char *h_createbase; 61c19800e8SDoug Rabson }; 62c19800e8SDoug Rabson 63c19800e8SDoug Rabson #define HDB2LDAP(db) (((struct hdbldapdb *)(db)->hdb_db)->h_lp) 64c19800e8SDoug Rabson #define HDB2MSGID(db) (((struct hdbldapdb *)(db)->hdb_db)->h_msgid) 65c19800e8SDoug Rabson #define HDBSETMSGID(db,msgid) \ 66c19800e8SDoug Rabson do { ((struct hdbldapdb *)(db)->hdb_db)->h_msgid = msgid; } while(0) 67c19800e8SDoug Rabson #define HDB2BASE(dn) (((struct hdbldapdb *)(db)->hdb_db)->h_base) 68c19800e8SDoug Rabson #define HDB2URL(dn) (((struct hdbldapdb *)(db)->hdb_db)->h_url) 69c19800e8SDoug Rabson #define HDB2CREATE(db) (((struct hdbldapdb *)(db)->hdb_db)->h_createbase) 70c19800e8SDoug Rabson 71c19800e8SDoug Rabson /* 72c19800e8SDoug Rabson * 73c19800e8SDoug Rabson */ 74c19800e8SDoug Rabson 75c19800e8SDoug Rabson static char * krb5kdcentry_attrs[] = { 76c19800e8SDoug Rabson "cn", 77c19800e8SDoug Rabson "createTimestamp", 78c19800e8SDoug Rabson "creatorsName", 79c19800e8SDoug Rabson "krb5EncryptionType", 80c19800e8SDoug Rabson "krb5KDCFlags", 81c19800e8SDoug Rabson "krb5Key", 82c19800e8SDoug Rabson "krb5KeyVersionNumber", 83c19800e8SDoug Rabson "krb5MaxLife", 84c19800e8SDoug Rabson "krb5MaxRenew", 85c19800e8SDoug Rabson "krb5PasswordEnd", 86c19800e8SDoug Rabson "krb5PrincipalName", 87c19800e8SDoug Rabson "krb5PrincipalRealm", 88c19800e8SDoug Rabson "krb5ValidEnd", 89c19800e8SDoug Rabson "krb5ValidStart", 90c19800e8SDoug Rabson "modifiersName", 91c19800e8SDoug Rabson "modifyTimestamp", 92c19800e8SDoug Rabson "objectClass", 93c19800e8SDoug Rabson "sambaAcctFlags", 94c19800e8SDoug Rabson "sambaKickoffTime", 95c19800e8SDoug Rabson "sambaNTPassword", 96c19800e8SDoug Rabson "sambaPwdLastSet", 97c19800e8SDoug Rabson "sambaPwdMustChange", 98c19800e8SDoug Rabson "uid", 995e9cd1aeSAssar Westerlund NULL 1005e9cd1aeSAssar Westerlund }; 1015e9cd1aeSAssar Westerlund 102c19800e8SDoug Rabson static char *krb5principal_attrs[] = { 103c19800e8SDoug Rabson "cn", 104c19800e8SDoug Rabson "createTimestamp", 105c19800e8SDoug Rabson "creatorsName", 106c19800e8SDoug Rabson "krb5PrincipalName", 107c19800e8SDoug Rabson "krb5PrincipalRealm", 108c19800e8SDoug Rabson "modifiersName", 109c19800e8SDoug Rabson "modifyTimestamp", 110c19800e8SDoug Rabson "objectClass", 111c19800e8SDoug Rabson "uid", 1125e9cd1aeSAssar Westerlund NULL 1135e9cd1aeSAssar Westerlund }; 1145e9cd1aeSAssar Westerlund 115c19800e8SDoug Rabson static int 116c19800e8SDoug Rabson LDAP_no_size_limit(krb5_context context, LDAP *lp) 117c19800e8SDoug Rabson { 118c19800e8SDoug Rabson int ret, limit = LDAP_NO_LIMIT; 119c19800e8SDoug Rabson 120c19800e8SDoug Rabson ret = ldap_set_option(lp, LDAP_OPT_SIZELIMIT, (const void *)&limit); 121c19800e8SDoug Rabson if (ret != LDAP_SUCCESS) { 122*ae771770SStanislav Sedov krb5_set_error_message(context, HDB_ERR_BADVERSION, 123*ae771770SStanislav Sedov "ldap_set_option: %s", 124c19800e8SDoug Rabson ldap_err2string(ret)); 125c19800e8SDoug Rabson return HDB_ERR_BADVERSION; 126c19800e8SDoug Rabson } 127c19800e8SDoug Rabson return 0; 128c19800e8SDoug Rabson } 129c19800e8SDoug Rabson 130c19800e8SDoug Rabson static int 131c19800e8SDoug Rabson check_ldap(krb5_context context, HDB *db, int ret) 132c19800e8SDoug Rabson { 133c19800e8SDoug Rabson switch (ret) { 134c19800e8SDoug Rabson case LDAP_SUCCESS: 135c19800e8SDoug Rabson return 0; 136c19800e8SDoug Rabson case LDAP_SERVER_DOWN: 137c19800e8SDoug Rabson LDAP_close(context, db); 138c19800e8SDoug Rabson return 1; 139c19800e8SDoug Rabson default: 140c19800e8SDoug Rabson return 1; 141c19800e8SDoug Rabson } 142c19800e8SDoug Rabson } 143c19800e8SDoug Rabson 1445e9cd1aeSAssar Westerlund static krb5_error_code 1451c43270aSJacques Vidrine LDAP__setmod(LDAPMod *** modlist, int modop, const char *attribute, 1461c43270aSJacques Vidrine int *pIndex) 1475e9cd1aeSAssar Westerlund { 1481c43270aSJacques Vidrine int cMods; 1495e9cd1aeSAssar Westerlund 1501c43270aSJacques Vidrine if (*modlist == NULL) { 1511c43270aSJacques Vidrine *modlist = (LDAPMod **)ber_memcalloc(1, sizeof(LDAPMod *)); 152c19800e8SDoug Rabson if (*modlist == NULL) 1535e9cd1aeSAssar Westerlund return ENOMEM; 1545e9cd1aeSAssar Westerlund } 1555e9cd1aeSAssar Westerlund 1561c43270aSJacques Vidrine for (cMods = 0; (*modlist)[cMods] != NULL; cMods++) { 1571c43270aSJacques Vidrine if ((*modlist)[cMods]->mod_op == modop && 1581c43270aSJacques Vidrine strcasecmp((*modlist)[cMods]->mod_type, attribute) == 0) { 1595e9cd1aeSAssar Westerlund break; 1605e9cd1aeSAssar Westerlund } 1615e9cd1aeSAssar Westerlund } 1625e9cd1aeSAssar Westerlund 1631c43270aSJacques Vidrine *pIndex = cMods; 1641c43270aSJacques Vidrine 1651c43270aSJacques Vidrine if ((*modlist)[cMods] == NULL) { 1661c43270aSJacques Vidrine LDAPMod *mod; 1671c43270aSJacques Vidrine 1681c43270aSJacques Vidrine *modlist = (LDAPMod **)ber_memrealloc(*modlist, 1691c43270aSJacques Vidrine (cMods + 2) * sizeof(LDAPMod *)); 170c19800e8SDoug Rabson if (*modlist == NULL) 1715e9cd1aeSAssar Westerlund return ENOMEM; 172c19800e8SDoug Rabson 1731c43270aSJacques Vidrine (*modlist)[cMods] = (LDAPMod *)ber_memalloc(sizeof(LDAPMod)); 174c19800e8SDoug Rabson if ((*modlist)[cMods] == NULL) 1755e9cd1aeSAssar Westerlund return ENOMEM; 1761c43270aSJacques Vidrine 1771c43270aSJacques Vidrine mod = (*modlist)[cMods]; 1781c43270aSJacques Vidrine mod->mod_op = modop; 1791c43270aSJacques Vidrine mod->mod_type = ber_strdup(attribute); 1801c43270aSJacques Vidrine if (mod->mod_type == NULL) { 1811c43270aSJacques Vidrine ber_memfree(mod); 1821c43270aSJacques Vidrine (*modlist)[cMods] = NULL; 1835e9cd1aeSAssar Westerlund return ENOMEM; 1845e9cd1aeSAssar Westerlund } 1851c43270aSJacques Vidrine 1861c43270aSJacques Vidrine if (modop & LDAP_MOD_BVALUES) { 1871c43270aSJacques Vidrine mod->mod_bvalues = NULL; 1881c43270aSJacques Vidrine } else { 1891c43270aSJacques Vidrine mod->mod_values = NULL; 1901c43270aSJacques Vidrine } 1911c43270aSJacques Vidrine 1921c43270aSJacques Vidrine (*modlist)[cMods + 1] = NULL; 1931c43270aSJacques Vidrine } 1941c43270aSJacques Vidrine 1951c43270aSJacques Vidrine return 0; 1961c43270aSJacques Vidrine } 1971c43270aSJacques Vidrine 1981c43270aSJacques Vidrine static krb5_error_code 1991c43270aSJacques Vidrine LDAP_addmod_len(LDAPMod *** modlist, int modop, const char *attribute, 2001c43270aSJacques Vidrine unsigned char *value, size_t len) 2011c43270aSJacques Vidrine { 2021c43270aSJacques Vidrine krb5_error_code ret; 203c19800e8SDoug Rabson int cMods, i = 0; 2041c43270aSJacques Vidrine 2051c43270aSJacques Vidrine ret = LDAP__setmod(modlist, modop | LDAP_MOD_BVALUES, attribute, &cMods); 206c19800e8SDoug Rabson if (ret) 2071c43270aSJacques Vidrine return ret; 2085e9cd1aeSAssar Westerlund 2095e9cd1aeSAssar Westerlund if (value != NULL) { 210c19800e8SDoug Rabson struct berval **bv; 2111c43270aSJacques Vidrine 212c19800e8SDoug Rabson bv = (*modlist)[cMods]->mod_bvalues; 213c19800e8SDoug Rabson if (bv != NULL) { 214c19800e8SDoug Rabson for (i = 0; bv[i] != NULL; i++) 2151c43270aSJacques Vidrine ; 216c19800e8SDoug Rabson bv = ber_memrealloc(bv, (i + 2) * sizeof(*bv)); 217c19800e8SDoug Rabson } else 218c19800e8SDoug Rabson bv = ber_memalloc(2 * sizeof(*bv)); 219c19800e8SDoug Rabson if (bv == NULL) 2205e9cd1aeSAssar Westerlund return ENOMEM; 221c19800e8SDoug Rabson 222c19800e8SDoug Rabson (*modlist)[cMods]->mod_bvalues = bv; 223c19800e8SDoug Rabson 224*ae771770SStanislav Sedov bv[i] = ber_memalloc(sizeof(**bv));; 225c19800e8SDoug Rabson if (bv[i] == NULL) 2265e9cd1aeSAssar Westerlund return ENOMEM; 2271c43270aSJacques Vidrine 228c19800e8SDoug Rabson bv[i]->bv_val = (void *)value; 229c19800e8SDoug Rabson bv[i]->bv_len = len; 2301c43270aSJacques Vidrine 231c19800e8SDoug Rabson bv[i + 1] = NULL; 2325e9cd1aeSAssar Westerlund } 2331c43270aSJacques Vidrine 2345e9cd1aeSAssar Westerlund return 0; 2355e9cd1aeSAssar Westerlund } 2365e9cd1aeSAssar Westerlund 2375e9cd1aeSAssar Westerlund static krb5_error_code 2385e9cd1aeSAssar Westerlund LDAP_addmod(LDAPMod *** modlist, int modop, const char *attribute, 2395e9cd1aeSAssar Westerlund const char *value) 2405e9cd1aeSAssar Westerlund { 241c19800e8SDoug Rabson int cMods, i = 0; 2421c43270aSJacques Vidrine krb5_error_code ret; 2435e9cd1aeSAssar Westerlund 2441c43270aSJacques Vidrine ret = LDAP__setmod(modlist, modop, attribute, &cMods); 245c19800e8SDoug Rabson if (ret) 2461c43270aSJacques Vidrine return ret; 2475e9cd1aeSAssar Westerlund 2485e9cd1aeSAssar Westerlund if (value != NULL) { 249c19800e8SDoug Rabson char **bv; 2501c43270aSJacques Vidrine 251c19800e8SDoug Rabson bv = (*modlist)[cMods]->mod_values; 252c19800e8SDoug Rabson if (bv != NULL) { 253c19800e8SDoug Rabson for (i = 0; bv[i] != NULL; i++) 2541c43270aSJacques Vidrine ; 255c19800e8SDoug Rabson bv = ber_memrealloc(bv, (i + 2) * sizeof(*bv)); 256c19800e8SDoug Rabson } else 257c19800e8SDoug Rabson bv = ber_memalloc(2 * sizeof(*bv)); 258c19800e8SDoug Rabson if (bv == NULL) 2595e9cd1aeSAssar Westerlund return ENOMEM; 260c19800e8SDoug Rabson 261c19800e8SDoug Rabson (*modlist)[cMods]->mod_values = bv; 262c19800e8SDoug Rabson 263c19800e8SDoug Rabson bv[i] = ber_strdup(value); 264c19800e8SDoug Rabson if (bv[i] == NULL) 2655e9cd1aeSAssar Westerlund return ENOMEM; 266c19800e8SDoug Rabson 267c19800e8SDoug Rabson bv[i + 1] = NULL; 2685e9cd1aeSAssar Westerlund } 2691c43270aSJacques Vidrine 2705e9cd1aeSAssar Westerlund return 0; 2715e9cd1aeSAssar Westerlund } 2725e9cd1aeSAssar Westerlund 2735e9cd1aeSAssar Westerlund static krb5_error_code 2745e9cd1aeSAssar Westerlund LDAP_addmod_generalized_time(LDAPMod *** mods, int modop, 2755e9cd1aeSAssar Westerlund const char *attribute, KerberosTime * time) 2765e9cd1aeSAssar Westerlund { 2775e9cd1aeSAssar Westerlund char buf[22]; 2785e9cd1aeSAssar Westerlund struct tm *tm; 2795e9cd1aeSAssar Westerlund 2805e9cd1aeSAssar Westerlund /* XXX not threadsafe */ 2815e9cd1aeSAssar Westerlund tm = gmtime(time); 2825e9cd1aeSAssar Westerlund strftime(buf, sizeof(buf), "%Y%m%d%H%M%SZ", tm); 2835e9cd1aeSAssar Westerlund 2845e9cd1aeSAssar Westerlund return LDAP_addmod(mods, modop, attribute, buf); 2855e9cd1aeSAssar Westerlund } 2865e9cd1aeSAssar Westerlund 2875e9cd1aeSAssar Westerlund static krb5_error_code 288c19800e8SDoug Rabson LDAP_addmod_integer(krb5_context context, 289c19800e8SDoug Rabson LDAPMod *** mods, int modop, 290c19800e8SDoug Rabson const char *attribute, unsigned long l) 291c19800e8SDoug Rabson { 292c19800e8SDoug Rabson krb5_error_code ret; 293c19800e8SDoug Rabson char *buf; 294c19800e8SDoug Rabson 295c19800e8SDoug Rabson ret = asprintf(&buf, "%ld", l); 296c19800e8SDoug Rabson if (ret < 0) { 297*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, 298*ae771770SStanislav Sedov "asprintf: out of memory:"); 299*ae771770SStanislav Sedov return ENOMEM; 300c19800e8SDoug Rabson } 301c19800e8SDoug Rabson ret = LDAP_addmod(mods, modop, attribute, buf); 302c19800e8SDoug Rabson free (buf); 303c19800e8SDoug Rabson return ret; 304c19800e8SDoug Rabson } 305c19800e8SDoug Rabson 306c19800e8SDoug Rabson static krb5_error_code 3075e9cd1aeSAssar Westerlund LDAP_get_string_value(HDB * db, LDAPMessage * entry, 3085e9cd1aeSAssar Westerlund const char *attribute, char **ptr) 3095e9cd1aeSAssar Westerlund { 310*ae771770SStanislav Sedov struct berval **vals; 3115e9cd1aeSAssar Westerlund 312*ae771770SStanislav Sedov vals = ldap_get_values_len(HDB2LDAP(db), entry, attribute); 313*ae771770SStanislav Sedov if (vals == NULL || vals[0] == NULL) { 314c19800e8SDoug Rabson *ptr = NULL; 3155e9cd1aeSAssar Westerlund return HDB_ERR_NOENTRY; 3165e9cd1aeSAssar Westerlund } 317c19800e8SDoug Rabson 318*ae771770SStanislav Sedov *ptr = malloc(vals[0]->bv_len + 1); 319*ae771770SStanislav Sedov if (*ptr == NULL) { 320*ae771770SStanislav Sedov ldap_value_free_len(vals); 321*ae771770SStanislav Sedov return ENOMEM; 322*ae771770SStanislav Sedov } 3235e9cd1aeSAssar Westerlund 324*ae771770SStanislav Sedov memcpy(*ptr, vals[0]->bv_val, vals[0]->bv_len); 325*ae771770SStanislav Sedov (*ptr)[vals[0]->bv_len] = 0; 3265e9cd1aeSAssar Westerlund 327*ae771770SStanislav Sedov ldap_value_free_len(vals); 328*ae771770SStanislav Sedov 329*ae771770SStanislav Sedov return 0; 3305e9cd1aeSAssar Westerlund } 3315e9cd1aeSAssar Westerlund 3325e9cd1aeSAssar Westerlund static krb5_error_code 3335e9cd1aeSAssar Westerlund LDAP_get_integer_value(HDB * db, LDAPMessage * entry, 3345e9cd1aeSAssar Westerlund const char *attribute, int *ptr) 3355e9cd1aeSAssar Westerlund { 336*ae771770SStanislav Sedov krb5_error_code ret; 337*ae771770SStanislav Sedov char *val; 3385e9cd1aeSAssar Westerlund 339*ae771770SStanislav Sedov ret = LDAP_get_string_value(db, entry, attribute, &val); 340*ae771770SStanislav Sedov if (ret) 341*ae771770SStanislav Sedov return ret; 342*ae771770SStanislav Sedov *ptr = atoi(val); 343*ae771770SStanislav Sedov free(val); 3445e9cd1aeSAssar Westerlund return 0; 3455e9cd1aeSAssar Westerlund } 3465e9cd1aeSAssar Westerlund 3475e9cd1aeSAssar Westerlund static krb5_error_code 3485e9cd1aeSAssar Westerlund LDAP_get_generalized_time_value(HDB * db, LDAPMessage * entry, 3495e9cd1aeSAssar Westerlund const char *attribute, KerberosTime * kt) 3505e9cd1aeSAssar Westerlund { 3515e9cd1aeSAssar Westerlund char *tmp, *gentime; 3525e9cd1aeSAssar Westerlund struct tm tm; 3535e9cd1aeSAssar Westerlund int ret; 3545e9cd1aeSAssar Westerlund 3555e9cd1aeSAssar Westerlund *kt = 0; 3565e9cd1aeSAssar Westerlund 3575e9cd1aeSAssar Westerlund ret = LDAP_get_string_value(db, entry, attribute, &gentime); 358c19800e8SDoug Rabson if (ret) 3595e9cd1aeSAssar Westerlund return ret; 3605e9cd1aeSAssar Westerlund 3615e9cd1aeSAssar Westerlund tmp = strptime(gentime, "%Y%m%d%H%M%SZ", &tm); 3625e9cd1aeSAssar Westerlund if (tmp == NULL) { 3635e9cd1aeSAssar Westerlund free(gentime); 3645e9cd1aeSAssar Westerlund return HDB_ERR_NOENTRY; 3655e9cd1aeSAssar Westerlund } 3665e9cd1aeSAssar Westerlund 3675e9cd1aeSAssar Westerlund free(gentime); 3685e9cd1aeSAssar Westerlund 3695e9cd1aeSAssar Westerlund *kt = timegm(&tm); 3705e9cd1aeSAssar Westerlund 3715e9cd1aeSAssar Westerlund return 0; 3725e9cd1aeSAssar Westerlund } 3735e9cd1aeSAssar Westerlund 374*ae771770SStanislav Sedov static int 375*ae771770SStanislav Sedov bervalstrcmp(struct berval *v, const char *str) 376*ae771770SStanislav Sedov { 377*ae771770SStanislav Sedov size_t len = strlen(str); 378*ae771770SStanislav Sedov return (v->bv_len == len) && strncasecmp(str, (char *)v->bv_val, len) == 0; 379*ae771770SStanislav Sedov } 380*ae771770SStanislav Sedov 381*ae771770SStanislav Sedov 3825e9cd1aeSAssar Westerlund static krb5_error_code 383c19800e8SDoug Rabson LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry_ex * ent, 3845e9cd1aeSAssar Westerlund LDAPMessage * msg, LDAPMod *** pmods) 3855e9cd1aeSAssar Westerlund { 3865e9cd1aeSAssar Westerlund krb5_error_code ret; 3875e9cd1aeSAssar Westerlund krb5_boolean is_new_entry; 3885e9cd1aeSAssar Westerlund char *tmp = NULL; 3895e9cd1aeSAssar Westerlund LDAPMod **mods = NULL; 390c19800e8SDoug Rabson hdb_entry_ex orig; 3915e9cd1aeSAssar Westerlund unsigned long oflags, nflags; 392c19800e8SDoug Rabson int i; 393c19800e8SDoug Rabson 394c19800e8SDoug Rabson krb5_boolean is_samba_account = FALSE; 395c19800e8SDoug Rabson krb5_boolean is_account = FALSE; 396c19800e8SDoug Rabson krb5_boolean is_heimdal_entry = FALSE; 397c19800e8SDoug Rabson krb5_boolean is_heimdal_principal = FALSE; 398c19800e8SDoug Rabson 399*ae771770SStanislav Sedov struct berval **vals; 400c19800e8SDoug Rabson 401c19800e8SDoug Rabson *pmods = NULL; 4025e9cd1aeSAssar Westerlund 4035e9cd1aeSAssar Westerlund if (msg != NULL) { 404c19800e8SDoug Rabson 405*ae771770SStanislav Sedov ret = LDAP_message2entry(context, db, msg, 0, &orig); 406c19800e8SDoug Rabson if (ret) 407c19800e8SDoug Rabson goto out; 408c19800e8SDoug Rabson 409c19800e8SDoug Rabson is_new_entry = FALSE; 410c19800e8SDoug Rabson 411*ae771770SStanislav Sedov vals = ldap_get_values_len(HDB2LDAP(db), msg, "objectClass"); 412*ae771770SStanislav Sedov if (vals) { 413*ae771770SStanislav Sedov int num_objectclasses = ldap_count_values_len(vals); 414c19800e8SDoug Rabson for (i=0; i < num_objectclasses; i++) { 415*ae771770SStanislav Sedov if (bervalstrcmp(vals[i], "sambaSamAccount")) 416c19800e8SDoug Rabson is_samba_account = TRUE; 417*ae771770SStanislav Sedov else if (bervalstrcmp(vals[i], structural_object)) 418c19800e8SDoug Rabson is_account = TRUE; 419*ae771770SStanislav Sedov else if (bervalstrcmp(vals[i], "krb5Principal")) 420c19800e8SDoug Rabson is_heimdal_principal = TRUE; 421*ae771770SStanislav Sedov else if (bervalstrcmp(vals[i], "krb5KDCEntry")) 422c19800e8SDoug Rabson is_heimdal_entry = TRUE; 423c19800e8SDoug Rabson } 424*ae771770SStanislav Sedov ldap_value_free_len(vals); 425c19800e8SDoug Rabson } 426c19800e8SDoug Rabson 427c19800e8SDoug Rabson /* 428c19800e8SDoug Rabson * If this is just a "account" entry and no other objectclass 429c19800e8SDoug Rabson * is hanging on this entry, it's really a new entry. 430c19800e8SDoug Rabson */ 431c19800e8SDoug Rabson if (is_samba_account == FALSE && is_heimdal_principal == FALSE && 432c19800e8SDoug Rabson is_heimdal_entry == FALSE) { 433c19800e8SDoug Rabson if (is_account == TRUE) { 434c19800e8SDoug Rabson is_new_entry = TRUE; 435c19800e8SDoug Rabson } else { 436c19800e8SDoug Rabson ret = HDB_ERR_NOENTRY; 4375e9cd1aeSAssar Westerlund goto out; 4385e9cd1aeSAssar Westerlund } 439c19800e8SDoug Rabson } 440c19800e8SDoug Rabson } else 441c19800e8SDoug Rabson is_new_entry = TRUE; 442c19800e8SDoug Rabson 443c19800e8SDoug Rabson if (is_new_entry) { 444c19800e8SDoug Rabson 4455e9cd1aeSAssar Westerlund /* to make it perfectly obvious we're depending on 4465e9cd1aeSAssar Westerlund * orig being intiialized to zero */ 4475e9cd1aeSAssar Westerlund memset(&orig, 0, sizeof(orig)); 448c19800e8SDoug Rabson 449c19800e8SDoug Rabson ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", "top"); 450c19800e8SDoug Rabson if (ret) 451c19800e8SDoug Rabson goto out; 452c19800e8SDoug Rabson 453c19800e8SDoug Rabson /* account is the structural object class */ 454c19800e8SDoug Rabson if (is_account == FALSE) { 455c19800e8SDoug Rabson ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", 456c19800e8SDoug Rabson structural_object); 457c19800e8SDoug Rabson is_account = TRUE; 458c19800e8SDoug Rabson if (ret) 459c19800e8SDoug Rabson goto out; 4605e9cd1aeSAssar Westerlund } 4615e9cd1aeSAssar Westerlund 462c19800e8SDoug Rabson ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", "krb5Principal"); 463c19800e8SDoug Rabson is_heimdal_principal = TRUE; 464c19800e8SDoug Rabson if (ret) 4655e9cd1aeSAssar Westerlund goto out; 466c19800e8SDoug Rabson 467c19800e8SDoug Rabson ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", "krb5KDCEntry"); 468c19800e8SDoug Rabson is_heimdal_entry = TRUE; 469c19800e8SDoug Rabson if (ret) 4705e9cd1aeSAssar Westerlund goto out; 4715e9cd1aeSAssar Westerlund } 4725e9cd1aeSAssar Westerlund 4735e9cd1aeSAssar Westerlund if (is_new_entry || 474c19800e8SDoug Rabson krb5_principal_compare(context, ent->entry.principal, orig.entry.principal) 475c19800e8SDoug Rabson == FALSE) 476c19800e8SDoug Rabson { 477c19800e8SDoug Rabson if (is_heimdal_principal || is_heimdal_entry) { 478c19800e8SDoug Rabson 479c19800e8SDoug Rabson ret = krb5_unparse_name(context, ent->entry.principal, &tmp); 480c19800e8SDoug Rabson if (ret) 4815e9cd1aeSAssar Westerlund goto out; 482c19800e8SDoug Rabson 483c19800e8SDoug Rabson ret = LDAP_addmod(&mods, LDAP_MOD_REPLACE, 484c19800e8SDoug Rabson "krb5PrincipalName", tmp); 485c19800e8SDoug Rabson if (ret) { 4865e9cd1aeSAssar Westerlund free(tmp); 4875e9cd1aeSAssar Westerlund goto out; 4885e9cd1aeSAssar Westerlund } 4895e9cd1aeSAssar Westerlund free(tmp); 4905e9cd1aeSAssar Westerlund } 4915e9cd1aeSAssar Westerlund 492c19800e8SDoug Rabson if (is_account || is_samba_account) { 493c19800e8SDoug Rabson ret = krb5_unparse_name_short(context, ent->entry.principal, &tmp); 494c19800e8SDoug Rabson if (ret) 495c19800e8SDoug Rabson goto out; 496c19800e8SDoug Rabson ret = LDAP_addmod(&mods, LDAP_MOD_REPLACE, "uid", tmp); 497c19800e8SDoug Rabson if (ret) { 498c19800e8SDoug Rabson free(tmp); 4995e9cd1aeSAssar Westerlund goto out; 5005e9cd1aeSAssar Westerlund } 5015e9cd1aeSAssar Westerlund free(tmp); 5025e9cd1aeSAssar Westerlund } 5035e9cd1aeSAssar Westerlund } 5045e9cd1aeSAssar Westerlund 505c19800e8SDoug Rabson if (is_heimdal_entry && (ent->entry.kvno != orig.entry.kvno || is_new_entry)) { 506c19800e8SDoug Rabson ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, 507c19800e8SDoug Rabson "krb5KeyVersionNumber", 508c19800e8SDoug Rabson ent->entry.kvno); 509c19800e8SDoug Rabson if (ret) 510c19800e8SDoug Rabson goto out; 511c19800e8SDoug Rabson } 512c19800e8SDoug Rabson 513c19800e8SDoug Rabson if (is_heimdal_entry && ent->entry.valid_start) { 514c19800e8SDoug Rabson if (orig.entry.valid_end == NULL 515c19800e8SDoug Rabson || (*(ent->entry.valid_start) != *(orig.entry.valid_start))) { 516c19800e8SDoug Rabson ret = LDAP_addmod_generalized_time(&mods, LDAP_MOD_REPLACE, 5175e9cd1aeSAssar Westerlund "krb5ValidStart", 518c19800e8SDoug Rabson ent->entry.valid_start); 519c19800e8SDoug Rabson if (ret) 5205e9cd1aeSAssar Westerlund goto out; 5215e9cd1aeSAssar Westerlund } 5225e9cd1aeSAssar Westerlund } 5235e9cd1aeSAssar Westerlund 524c19800e8SDoug Rabson if (ent->entry.valid_end) { 525c19800e8SDoug Rabson if (orig.entry.valid_end == NULL || (*(ent->entry.valid_end) != *(orig.entry.valid_end))) { 526c19800e8SDoug Rabson if (is_heimdal_entry) { 527c19800e8SDoug Rabson ret = LDAP_addmod_generalized_time(&mods, LDAP_MOD_REPLACE, 5285e9cd1aeSAssar Westerlund "krb5ValidEnd", 529c19800e8SDoug Rabson ent->entry.valid_end); 530c19800e8SDoug Rabson if (ret) 531c19800e8SDoug Rabson goto out; 532c19800e8SDoug Rabson } 533c19800e8SDoug Rabson if (is_samba_account) { 534c19800e8SDoug Rabson ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, 535c19800e8SDoug Rabson "sambaKickoffTime", 536c19800e8SDoug Rabson *(ent->entry.valid_end)); 537c19800e8SDoug Rabson if (ret) 5385e9cd1aeSAssar Westerlund goto out; 5395e9cd1aeSAssar Westerlund } 5405e9cd1aeSAssar Westerlund } 5415e9cd1aeSAssar Westerlund } 5425e9cd1aeSAssar Westerlund 543c19800e8SDoug Rabson if (ent->entry.pw_end) { 544c19800e8SDoug Rabson if (orig.entry.pw_end == NULL || (*(ent->entry.pw_end) != *(orig.entry.pw_end))) { 545c19800e8SDoug Rabson if (is_heimdal_entry) { 546c19800e8SDoug Rabson ret = LDAP_addmod_generalized_time(&mods, LDAP_MOD_REPLACE, 5475e9cd1aeSAssar Westerlund "krb5PasswordEnd", 548c19800e8SDoug Rabson ent->entry.pw_end); 549c19800e8SDoug Rabson if (ret) 550c19800e8SDoug Rabson goto out; 551c19800e8SDoug Rabson } 552c19800e8SDoug Rabson 553c19800e8SDoug Rabson if (is_samba_account) { 554c19800e8SDoug Rabson ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, 555c19800e8SDoug Rabson "sambaPwdMustChange", 556c19800e8SDoug Rabson *(ent->entry.pw_end)); 557c19800e8SDoug Rabson if (ret) 5585e9cd1aeSAssar Westerlund goto out; 5595e9cd1aeSAssar Westerlund } 5605e9cd1aeSAssar Westerlund } 5615e9cd1aeSAssar Westerlund } 5625e9cd1aeSAssar Westerlund 5635e9cd1aeSAssar Westerlund 564c19800e8SDoug Rabson #if 0 /* we we have last_pw_change */ 565c19800e8SDoug Rabson if (is_samba_account && ent->entry.last_pw_change) { 566c19800e8SDoug Rabson if (orig.entry.last_pw_change == NULL || (*(ent->entry.last_pw_change) != *(orig.entry.last_pw_change))) { 567c19800e8SDoug Rabson ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, 568c19800e8SDoug Rabson "sambaPwdLastSet", 569c19800e8SDoug Rabson *(ent->entry.last_pw_change)); 570c19800e8SDoug Rabson if (ret) 5715e9cd1aeSAssar Westerlund goto out; 5725e9cd1aeSAssar Westerlund } 5735e9cd1aeSAssar Westerlund } 574c19800e8SDoug Rabson #endif 5755e9cd1aeSAssar Westerlund 576c19800e8SDoug Rabson if (is_heimdal_entry && ent->entry.max_life) { 577c19800e8SDoug Rabson if (orig.entry.max_life == NULL 578c19800e8SDoug Rabson || (*(ent->entry.max_life) != *(orig.entry.max_life))) { 5795e9cd1aeSAssar Westerlund 580c19800e8SDoug Rabson ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, 581c19800e8SDoug Rabson "krb5MaxLife", 582c19800e8SDoug Rabson *(ent->entry.max_life)); 583c19800e8SDoug Rabson if (ret) 5845e9cd1aeSAssar Westerlund goto out; 5855e9cd1aeSAssar Westerlund } 5865e9cd1aeSAssar Westerlund } 5875e9cd1aeSAssar Westerlund 588c19800e8SDoug Rabson if (is_heimdal_entry && ent->entry.max_renew) { 589c19800e8SDoug Rabson if (orig.entry.max_renew == NULL 590c19800e8SDoug Rabson || (*(ent->entry.max_renew) != *(orig.entry.max_renew))) { 591c19800e8SDoug Rabson 592c19800e8SDoug Rabson ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, 593c19800e8SDoug Rabson "krb5MaxRenew", 594c19800e8SDoug Rabson *(ent->entry.max_renew)); 595c19800e8SDoug Rabson if (ret) 596c19800e8SDoug Rabson goto out; 597c19800e8SDoug Rabson } 598c19800e8SDoug Rabson } 599c19800e8SDoug Rabson 600c19800e8SDoug Rabson oflags = HDBFlags2int(orig.entry.flags); 601c19800e8SDoug Rabson nflags = HDBFlags2int(ent->entry.flags); 602c19800e8SDoug Rabson 603c19800e8SDoug Rabson if (is_heimdal_entry && oflags != nflags) { 604c19800e8SDoug Rabson 605c19800e8SDoug Rabson ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, 606c19800e8SDoug Rabson "krb5KDCFlags", 607c19800e8SDoug Rabson nflags); 608c19800e8SDoug Rabson if (ret) 609c19800e8SDoug Rabson goto out; 610c19800e8SDoug Rabson } 611c19800e8SDoug Rabson 612c19800e8SDoug Rabson /* Remove keys if they exists, and then replace keys. */ 613c19800e8SDoug Rabson if (!is_new_entry && orig.entry.keys.len > 0) { 614*ae771770SStanislav Sedov vals = ldap_get_values_len(HDB2LDAP(db), msg, "krb5Key"); 615*ae771770SStanislav Sedov if (vals) { 616*ae771770SStanislav Sedov ldap_value_free_len(vals); 617c19800e8SDoug Rabson 6185e9cd1aeSAssar Westerlund ret = LDAP_addmod(&mods, LDAP_MOD_DELETE, "krb5Key", NULL); 619c19800e8SDoug Rabson if (ret) 6205e9cd1aeSAssar Westerlund goto out; 6215e9cd1aeSAssar Westerlund } 6225e9cd1aeSAssar Westerlund } 6235e9cd1aeSAssar Westerlund 624c19800e8SDoug Rabson for (i = 0; i < ent->entry.keys.len; i++) { 625c19800e8SDoug Rabson 626c19800e8SDoug Rabson if (is_samba_account 627c19800e8SDoug Rabson && ent->entry.keys.val[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5) { 628c19800e8SDoug Rabson char *ntHexPassword; 629c19800e8SDoug Rabson char *nt; 630*ae771770SStanislav Sedov time_t now = time(NULL); 631c19800e8SDoug Rabson 632c19800e8SDoug Rabson /* the key might have been 'sealed', but samba passwords 633c19800e8SDoug Rabson are clear in the directory */ 634c19800e8SDoug Rabson ret = hdb_unseal_key(context, db, &ent->entry.keys.val[i]); 635c19800e8SDoug Rabson if (ret) 636c19800e8SDoug Rabson goto out; 637c19800e8SDoug Rabson 638c19800e8SDoug Rabson nt = ent->entry.keys.val[i].key.keyvalue.data; 639c19800e8SDoug Rabson /* store in ntPassword, not krb5key */ 640c19800e8SDoug Rabson ret = hex_encode(nt, 16, &ntHexPassword); 641c19800e8SDoug Rabson if (ret < 0) { 642c19800e8SDoug Rabson ret = ENOMEM; 643*ae771770SStanislav Sedov krb5_set_error_message(context, ret, "hdb-ldap: failed to " 644*ae771770SStanislav Sedov "hex encode key"); 645c19800e8SDoug Rabson goto out; 646c19800e8SDoug Rabson } 647c19800e8SDoug Rabson ret = LDAP_addmod(&mods, LDAP_MOD_REPLACE, "sambaNTPassword", 648c19800e8SDoug Rabson ntHexPassword); 649c19800e8SDoug Rabson free(ntHexPassword); 650c19800e8SDoug Rabson if (ret) 651c19800e8SDoug Rabson goto out; 652*ae771770SStanislav Sedov ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_REPLACE, 653*ae771770SStanislav Sedov "sambaPwdLastSet", now); 654*ae771770SStanislav Sedov if (ret) 655*ae771770SStanislav Sedov goto out; 656c19800e8SDoug Rabson 657c19800e8SDoug Rabson /* have to kill the LM passwod if it exists */ 658*ae771770SStanislav Sedov vals = ldap_get_values_len(HDB2LDAP(db), msg, "sambaLMPassword"); 659*ae771770SStanislav Sedov if (vals) { 660*ae771770SStanislav Sedov ldap_value_free_len(vals); 661c19800e8SDoug Rabson ret = LDAP_addmod(&mods, LDAP_MOD_DELETE, 662c19800e8SDoug Rabson "sambaLMPassword", NULL); 663c19800e8SDoug Rabson if (ret) 664c19800e8SDoug Rabson goto out; 665c19800e8SDoug Rabson } 666c19800e8SDoug Rabson 667c19800e8SDoug Rabson } else if (is_heimdal_entry) { 6685e9cd1aeSAssar Westerlund unsigned char *buf; 669c19800e8SDoug Rabson size_t len, buf_size; 6705e9cd1aeSAssar Westerlund 671c19800e8SDoug Rabson ASN1_MALLOC_ENCODE(Key, buf, buf_size, &ent->entry.keys.val[i], &len, ret); 672c19800e8SDoug Rabson if (ret) 6735e9cd1aeSAssar Westerlund goto out; 674c19800e8SDoug Rabson if(buf_size != len) 675c19800e8SDoug Rabson krb5_abortx(context, "internal error in ASN.1 encoder"); 6765e9cd1aeSAssar Westerlund 6775e9cd1aeSAssar Westerlund /* addmod_len _owns_ the key, doesn't need to copy it */ 6785e9cd1aeSAssar Westerlund ret = LDAP_addmod_len(&mods, LDAP_MOD_ADD, "krb5Key", buf, len); 679c19800e8SDoug Rabson if (ret) 6805e9cd1aeSAssar Westerlund goto out; 6815e9cd1aeSAssar Westerlund } 6825e9cd1aeSAssar Westerlund } 6835e9cd1aeSAssar Westerlund 684c19800e8SDoug Rabson if (ent->entry.etypes) { 685c19800e8SDoug Rabson int add_krb5EncryptionType = 0; 686c19800e8SDoug Rabson 687c19800e8SDoug Rabson /* 688c19800e8SDoug Rabson * Only add/modify krb5EncryptionType if it's a new heimdal 689c19800e8SDoug Rabson * entry or krb5EncryptionType already exists on the entry. 690c19800e8SDoug Rabson */ 691c19800e8SDoug Rabson 692c19800e8SDoug Rabson if (!is_new_entry) { 693*ae771770SStanislav Sedov vals = ldap_get_values_len(HDB2LDAP(db), msg, "krb5EncryptionType"); 694*ae771770SStanislav Sedov if (vals) { 695*ae771770SStanislav Sedov ldap_value_free_len(vals); 696c19800e8SDoug Rabson ret = LDAP_addmod(&mods, LDAP_MOD_DELETE, "krb5EncryptionType", 6975e9cd1aeSAssar Westerlund NULL); 698c19800e8SDoug Rabson if (ret) 699c19800e8SDoug Rabson goto out; 700c19800e8SDoug Rabson add_krb5EncryptionType = 1; 7015e9cd1aeSAssar Westerlund } 702c19800e8SDoug Rabson } else if (is_heimdal_entry) 703c19800e8SDoug Rabson add_krb5EncryptionType = 1; 704c19800e8SDoug Rabson 705c19800e8SDoug Rabson if (add_krb5EncryptionType) { 706c19800e8SDoug Rabson for (i = 0; i < ent->entry.etypes->len; i++) { 707c19800e8SDoug Rabson if (is_samba_account && 708c19800e8SDoug Rabson ent->entry.keys.val[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5) 709c19800e8SDoug Rabson { 710c19800e8SDoug Rabson ; 711c19800e8SDoug Rabson } else if (is_heimdal_entry) { 712c19800e8SDoug Rabson ret = LDAP_addmod_integer(context, &mods, LDAP_MOD_ADD, 713c19800e8SDoug Rabson "krb5EncryptionType", 714c19800e8SDoug Rabson ent->entry.etypes->val[i]); 715c19800e8SDoug Rabson if (ret) 7165e9cd1aeSAssar Westerlund goto out; 7175e9cd1aeSAssar Westerlund } 7185e9cd1aeSAssar Westerlund } 7195e9cd1aeSAssar Westerlund } 7205e9cd1aeSAssar Westerlund } 7215e9cd1aeSAssar Westerlund 7225e9cd1aeSAssar Westerlund /* for clarity */ 7235e9cd1aeSAssar Westerlund ret = 0; 7245e9cd1aeSAssar Westerlund 7255e9cd1aeSAssar Westerlund out: 7265e9cd1aeSAssar Westerlund 727c19800e8SDoug Rabson if (ret == 0) 7285e9cd1aeSAssar Westerlund *pmods = mods; 729c19800e8SDoug Rabson else if (mods != NULL) { 7305e9cd1aeSAssar Westerlund ldap_mods_free(mods, 1); 7315e9cd1aeSAssar Westerlund *pmods = NULL; 7325e9cd1aeSAssar Westerlund } 7335e9cd1aeSAssar Westerlund 734c19800e8SDoug Rabson if (msg) 7355e9cd1aeSAssar Westerlund hdb_free_entry(context, &orig); 7365e9cd1aeSAssar Westerlund 7375e9cd1aeSAssar Westerlund return ret; 7385e9cd1aeSAssar Westerlund } 7395e9cd1aeSAssar Westerlund 7405e9cd1aeSAssar Westerlund static krb5_error_code 7415e9cd1aeSAssar Westerlund LDAP_dn2principal(krb5_context context, HDB * db, const char *dn, 7425e9cd1aeSAssar Westerlund krb5_principal * principal) 7435e9cd1aeSAssar Westerlund { 7445e9cd1aeSAssar Westerlund krb5_error_code ret; 745c19800e8SDoug Rabson int rc; 746c19800e8SDoug Rabson const char *filter = "(objectClass=krb5Principal)"; 7475e9cd1aeSAssar Westerlund LDAPMessage *res = NULL, *e; 748*ae771770SStanislav Sedov char *p; 7495e9cd1aeSAssar Westerlund 750c19800e8SDoug Rabson ret = LDAP_no_size_limit(context, HDB2LDAP(db)); 751c19800e8SDoug Rabson if (ret) 7524137ff4cSJacques Vidrine goto out; 7534137ff4cSJacques Vidrine 754*ae771770SStanislav Sedov rc = ldap_search_ext_s(HDB2LDAP(db), dn, LDAP_SCOPE_SUBTREE, 755*ae771770SStanislav Sedov filter, krb5principal_attrs, 0, 756*ae771770SStanislav Sedov NULL, NULL, NULL, 7575e9cd1aeSAssar Westerlund 0, &res); 758c19800e8SDoug Rabson if (check_ldap(context, db, rc)) { 7595e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 760*ae771770SStanislav Sedov krb5_set_error_message(context, ret, "ldap_search_ext_s: " 761*ae771770SStanislav Sedov "filter: %s error: %s", 762*ae771770SStanislav Sedov filter, ldap_err2string(rc)); 7635e9cd1aeSAssar Westerlund goto out; 7645e9cd1aeSAssar Westerlund } 7655e9cd1aeSAssar Westerlund 766c19800e8SDoug Rabson e = ldap_first_entry(HDB2LDAP(db), res); 7675e9cd1aeSAssar Westerlund if (e == NULL) { 7685e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 7695e9cd1aeSAssar Westerlund goto out; 7705e9cd1aeSAssar Westerlund } 7715e9cd1aeSAssar Westerlund 772*ae771770SStanislav Sedov ret = LDAP_get_string_value(db, e, "krb5PrincipalName", &p); 773*ae771770SStanislav Sedov if (ret) { 7745e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 7755e9cd1aeSAssar Westerlund goto out; 7765e9cd1aeSAssar Westerlund } 7775e9cd1aeSAssar Westerlund 778*ae771770SStanislav Sedov ret = krb5_parse_name(context, p, principal); 779*ae771770SStanislav Sedov free(p); 7805e9cd1aeSAssar Westerlund 7815e9cd1aeSAssar Westerlund out: 782c19800e8SDoug Rabson if (res) 7835e9cd1aeSAssar Westerlund ldap_msgfree(res); 784c19800e8SDoug Rabson 7855e9cd1aeSAssar Westerlund return ret; 7865e9cd1aeSAssar Westerlund } 7875e9cd1aeSAssar Westerlund 788*ae771770SStanislav Sedov static int 789*ae771770SStanislav Sedov need_quote(unsigned char c) 790*ae771770SStanislav Sedov { 791*ae771770SStanislav Sedov return (c & 0x80) || 792*ae771770SStanislav Sedov (c < 32) || 793*ae771770SStanislav Sedov (c == '(') || 794*ae771770SStanislav Sedov (c == ')') || 795*ae771770SStanislav Sedov (c == '*') || 796*ae771770SStanislav Sedov (c == '\\') || 797*ae771770SStanislav Sedov (c == 0x7f); 798*ae771770SStanislav Sedov } 799*ae771770SStanislav Sedov 800*ae771770SStanislav Sedov const static char hexchar[] = "0123456789ABCDEF"; 801*ae771770SStanislav Sedov 802*ae771770SStanislav Sedov static krb5_error_code 803*ae771770SStanislav Sedov escape_value(krb5_context context, const unsigned char *unquoted, char **quoted) 804*ae771770SStanislav Sedov { 805*ae771770SStanislav Sedov size_t i, len; 806*ae771770SStanislav Sedov 807*ae771770SStanislav Sedov for (i = 0, len = 0; unquoted[i] != '\0'; i++, len++) { 808*ae771770SStanislav Sedov if (need_quote((unsigned char)unquoted[i])) 809*ae771770SStanislav Sedov len += 2; 810*ae771770SStanislav Sedov } 811*ae771770SStanislav Sedov 812*ae771770SStanislav Sedov *quoted = malloc(len + 1); 813*ae771770SStanislav Sedov if (*quoted == NULL) { 814*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 815*ae771770SStanislav Sedov return ENOMEM; 816*ae771770SStanislav Sedov } 817*ae771770SStanislav Sedov 818*ae771770SStanislav Sedov for (i = 0; unquoted[0] ; unquoted++) { 819*ae771770SStanislav Sedov if (need_quote((unsigned char *)unquoted[0])) { 820*ae771770SStanislav Sedov (*quoted)[i++] = '\\'; 821*ae771770SStanislav Sedov (*quoted)[i++] = hexchar[(unquoted[0] >> 4) & 0xf]; 822*ae771770SStanislav Sedov (*quoted)[i++] = hexchar[(unquoted[0] ) & 0xf]; 823*ae771770SStanislav Sedov } else 824*ae771770SStanislav Sedov (*quoted)[i++] = (char)unquoted[0]; 825*ae771770SStanislav Sedov } 826*ae771770SStanislav Sedov (*quoted)[i] = '\0'; 827*ae771770SStanislav Sedov return 0; 828*ae771770SStanislav Sedov } 829*ae771770SStanislav Sedov 830*ae771770SStanislav Sedov 8315e9cd1aeSAssar Westerlund static krb5_error_code 832c19800e8SDoug Rabson LDAP__lookup_princ(krb5_context context, 833c19800e8SDoug Rabson HDB *db, 834c19800e8SDoug Rabson const char *princname, 835c19800e8SDoug Rabson const char *userid, 8365e9cd1aeSAssar Westerlund LDAPMessage **msg) 8375e9cd1aeSAssar Westerlund { 8385e9cd1aeSAssar Westerlund krb5_error_code ret; 839c19800e8SDoug Rabson int rc; 840*ae771770SStanislav Sedov char *quote, *filter = NULL; 8415e9cd1aeSAssar Westerlund 842c19800e8SDoug Rabson ret = LDAP__connect(context, db); 843c19800e8SDoug Rabson if (ret) 844c19800e8SDoug Rabson return ret; 8455e9cd1aeSAssar Westerlund 846*ae771770SStanislav Sedov /* 847*ae771770SStanislav Sedov * Quote searches that contain filter language, this quote 848*ae771770SStanislav Sedov * searches for *@REALM, which takes very long time. 849*ae771770SStanislav Sedov */ 850*ae771770SStanislav Sedov 851*ae771770SStanislav Sedov ret = escape_value(context, princname, "e); 852*ae771770SStanislav Sedov if (ret) 853*ae771770SStanislav Sedov goto out; 854*ae771770SStanislav Sedov 855c19800e8SDoug Rabson rc = asprintf(&filter, 856c19800e8SDoug Rabson "(&(objectClass=krb5Principal)(krb5PrincipalName=%s))", 857*ae771770SStanislav Sedov quote); 858*ae771770SStanislav Sedov free(quote); 859*ae771770SStanislav Sedov 8605e9cd1aeSAssar Westerlund if (rc < 0) { 8615e9cd1aeSAssar Westerlund ret = ENOMEM; 862*ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 8635e9cd1aeSAssar Westerlund goto out; 8645e9cd1aeSAssar Westerlund } 8655e9cd1aeSAssar Westerlund 866c19800e8SDoug Rabson ret = LDAP_no_size_limit(context, HDB2LDAP(db)); 867c19800e8SDoug Rabson if (ret) 868c19800e8SDoug Rabson goto out; 869c19800e8SDoug Rabson 870*ae771770SStanislav Sedov rc = ldap_search_ext_s(HDB2LDAP(db), HDB2BASE(db), 871*ae771770SStanislav Sedov LDAP_SCOPE_SUBTREE, filter, 872*ae771770SStanislav Sedov krb5kdcentry_attrs, 0, 873*ae771770SStanislav Sedov NULL, NULL, NULL, 874*ae771770SStanislav Sedov 0, msg); 875c19800e8SDoug Rabson if (check_ldap(context, db, rc)) { 876c19800e8SDoug Rabson ret = HDB_ERR_NOENTRY; 877*ae771770SStanislav Sedov krb5_set_error_message(context, ret, "ldap_search_ext_s: " 878*ae771770SStanislav Sedov "filter: %s - error: %s", 879*ae771770SStanislav Sedov filter, ldap_err2string(rc)); 8804137ff4cSJacques Vidrine goto out; 8814137ff4cSJacques Vidrine } 8825e9cd1aeSAssar Westerlund 883c19800e8SDoug Rabson if (userid && ldap_count_entries(HDB2LDAP(db), *msg) == 0) { 884c19800e8SDoug Rabson free(filter); 885c19800e8SDoug Rabson filter = NULL; 886c19800e8SDoug Rabson ldap_msgfree(*msg); 887c19800e8SDoug Rabson *msg = NULL; 888c19800e8SDoug Rabson 889*ae771770SStanislav Sedov ret = escape_value(context, userid, "e); 890*ae771770SStanislav Sedov if (ret) 891*ae771770SStanislav Sedov goto out; 892*ae771770SStanislav Sedov 893c19800e8SDoug Rabson rc = asprintf(&filter, 894c19800e8SDoug Rabson "(&(|(objectClass=sambaSamAccount)(objectClass=%s))(uid=%s))", 895*ae771770SStanislav Sedov structural_object, quote); 896*ae771770SStanislav Sedov free(quote); 897c19800e8SDoug Rabson if (rc < 0) { 898c19800e8SDoug Rabson ret = ENOMEM; 899*ae771770SStanislav Sedov krb5_set_error_message(context, ret, "asprintf: out of memory"); 900c19800e8SDoug Rabson goto out; 901c19800e8SDoug Rabson } 902c19800e8SDoug Rabson 903c19800e8SDoug Rabson ret = LDAP_no_size_limit(context, HDB2LDAP(db)); 904c19800e8SDoug Rabson if (ret) 905c19800e8SDoug Rabson goto out; 906c19800e8SDoug Rabson 907*ae771770SStanislav Sedov rc = ldap_search_ext_s(HDB2LDAP(db), HDB2BASE(db), LDAP_SCOPE_SUBTREE, 908*ae771770SStanislav Sedov filter, krb5kdcentry_attrs, 0, 909*ae771770SStanislav Sedov NULL, NULL, NULL, 910*ae771770SStanislav Sedov 0, msg); 911c19800e8SDoug Rabson if (check_ldap(context, db, rc)) { 9125e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 913*ae771770SStanislav Sedov krb5_set_error_message(context, ret, 914*ae771770SStanislav Sedov "ldap_search_ext_s: filter: %s error: %s", 915*ae771770SStanislav Sedov filter, ldap_err2string(rc)); 9165e9cd1aeSAssar Westerlund goto out; 9175e9cd1aeSAssar Westerlund } 918c19800e8SDoug Rabson } 9195e9cd1aeSAssar Westerlund 9205e9cd1aeSAssar Westerlund ret = 0; 9215e9cd1aeSAssar Westerlund 9225e9cd1aeSAssar Westerlund out: 923c19800e8SDoug Rabson if (filter) 9245e9cd1aeSAssar Westerlund free(filter); 925c19800e8SDoug Rabson 9265e9cd1aeSAssar Westerlund return ret; 9275e9cd1aeSAssar Westerlund } 9285e9cd1aeSAssar Westerlund 9295e9cd1aeSAssar Westerlund static krb5_error_code 9305e9cd1aeSAssar Westerlund LDAP_principal2message(krb5_context context, HDB * db, 931c19800e8SDoug Rabson krb5_const_principal princ, LDAPMessage ** msg) 9325e9cd1aeSAssar Westerlund { 933c19800e8SDoug Rabson char *name, *name_short = NULL; 9345e9cd1aeSAssar Westerlund krb5_error_code ret; 935c19800e8SDoug Rabson krb5_realm *r, *r0; 9365e9cd1aeSAssar Westerlund 937c19800e8SDoug Rabson *msg = NULL; 938c19800e8SDoug Rabson 939c19800e8SDoug Rabson ret = krb5_unparse_name(context, princ, &name); 940c19800e8SDoug Rabson if (ret) 941c19800e8SDoug Rabson return ret; 942c19800e8SDoug Rabson 943c19800e8SDoug Rabson ret = krb5_get_default_realms(context, &r0); 944c19800e8SDoug Rabson if(ret) { 945c19800e8SDoug Rabson free(name); 9465e9cd1aeSAssar Westerlund return ret; 9475e9cd1aeSAssar Westerlund } 948c19800e8SDoug Rabson for (r = r0; *r != NULL; r++) { 949c19800e8SDoug Rabson if(strcmp(krb5_principal_get_realm(context, princ), *r) == 0) { 950c19800e8SDoug Rabson ret = krb5_unparse_name_short(context, princ, &name_short); 951c19800e8SDoug Rabson if (ret) { 952c19800e8SDoug Rabson krb5_free_host_realm(context, r0); 953c19800e8SDoug Rabson free(name); 954c19800e8SDoug Rabson return ret; 955c19800e8SDoug Rabson } 956c19800e8SDoug Rabson break; 957c19800e8SDoug Rabson } 958c19800e8SDoug Rabson } 959c19800e8SDoug Rabson krb5_free_host_realm(context, r0); 9605e9cd1aeSAssar Westerlund 961c19800e8SDoug Rabson ret = LDAP__lookup_princ(context, db, name, name_short, msg); 962c19800e8SDoug Rabson free(name); 963c19800e8SDoug Rabson free(name_short); 9645e9cd1aeSAssar Westerlund 9655e9cd1aeSAssar Westerlund return ret; 9665e9cd1aeSAssar Westerlund } 9675e9cd1aeSAssar Westerlund 9685e9cd1aeSAssar Westerlund /* 9695e9cd1aeSAssar Westerlund * Construct an hdb_entry from a directory entry. 9705e9cd1aeSAssar Westerlund */ 9715e9cd1aeSAssar Westerlund static krb5_error_code 9725e9cd1aeSAssar Westerlund LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg, 973*ae771770SStanislav Sedov int flags, hdb_entry_ex * ent) 9745e9cd1aeSAssar Westerlund { 975c19800e8SDoug Rabson char *unparsed_name = NULL, *dn = NULL, *ntPasswordIN = NULL; 976c19800e8SDoug Rabson char *samba_acct_flags = NULL; 9775e9cd1aeSAssar Westerlund struct berval **keys; 978*ae771770SStanislav Sedov struct berval **vals; 979*ae771770SStanislav Sedov int tmp, tmp_time, i, ret, have_arcfour = 0; 9805e9cd1aeSAssar Westerlund 9815e9cd1aeSAssar Westerlund memset(ent, 0, sizeof(*ent)); 982c19800e8SDoug Rabson ent->entry.flags = int2HDBFlags(0); 9835e9cd1aeSAssar Westerlund 984c19800e8SDoug Rabson ret = LDAP_get_string_value(db, msg, "krb5PrincipalName", &unparsed_name); 985c19800e8SDoug Rabson if (ret == 0) { 986c19800e8SDoug Rabson ret = krb5_parse_name(context, unparsed_name, &ent->entry.principal); 987c19800e8SDoug Rabson if (ret) 9885e9cd1aeSAssar Westerlund goto out; 989c19800e8SDoug Rabson } else { 990c19800e8SDoug Rabson ret = LDAP_get_string_value(db, msg, "uid", 991c19800e8SDoug Rabson &unparsed_name); 992c19800e8SDoug Rabson if (ret == 0) { 993c19800e8SDoug Rabson ret = krb5_parse_name(context, unparsed_name, &ent->entry.principal); 994c19800e8SDoug Rabson if (ret) 995c19800e8SDoug Rabson goto out; 996c19800e8SDoug Rabson } else { 997*ae771770SStanislav Sedov krb5_set_error_message(context, HDB_ERR_NOENTRY, 998*ae771770SStanislav Sedov "hdb-ldap: ldap entry missing" 999c19800e8SDoug Rabson "principal name"); 1000c19800e8SDoug Rabson return HDB_ERR_NOENTRY; 1001c19800e8SDoug Rabson } 10025e9cd1aeSAssar Westerlund } 10035e9cd1aeSAssar Westerlund 1004c19800e8SDoug Rabson { 1005c19800e8SDoug Rabson int integer; 1006c19800e8SDoug Rabson ret = LDAP_get_integer_value(db, msg, "krb5KeyVersionNumber", 1007c19800e8SDoug Rabson &integer); 1008c19800e8SDoug Rabson if (ret) 1009c19800e8SDoug Rabson ent->entry.kvno = 0; 1010c19800e8SDoug Rabson else 1011c19800e8SDoug Rabson ent->entry.kvno = integer; 10125e9cd1aeSAssar Westerlund } 10135e9cd1aeSAssar Westerlund 1014c19800e8SDoug Rabson keys = ldap_get_values_len(HDB2LDAP(db), msg, "krb5Key"); 10155e9cd1aeSAssar Westerlund if (keys != NULL) { 10165e9cd1aeSAssar Westerlund int i; 10175e9cd1aeSAssar Westerlund size_t l; 10185e9cd1aeSAssar Westerlund 1019c19800e8SDoug Rabson ent->entry.keys.len = ldap_count_values_len(keys); 1020c19800e8SDoug Rabson ent->entry.keys.val = (Key *) calloc(ent->entry.keys.len, sizeof(Key)); 1021c19800e8SDoug Rabson if (ent->entry.keys.val == NULL) { 10224137ff4cSJacques Vidrine ret = ENOMEM; 1023*ae771770SStanislav Sedov krb5_set_error_message(context, ret, "calloc: out of memory"); 10244137ff4cSJacques Vidrine goto out; 10254137ff4cSJacques Vidrine } 1026c19800e8SDoug Rabson for (i = 0; i < ent->entry.keys.len; i++) { 10275e9cd1aeSAssar Westerlund decode_Key((unsigned char *) keys[i]->bv_val, 1028c19800e8SDoug Rabson (size_t) keys[i]->bv_len, &ent->entry.keys.val[i], &l); 10295e9cd1aeSAssar Westerlund } 10305e9cd1aeSAssar Westerlund ber_bvecfree(keys); 10315e9cd1aeSAssar Westerlund } else { 10325e9cd1aeSAssar Westerlund #if 1 10335e9cd1aeSAssar Westerlund /* 10345e9cd1aeSAssar Westerlund * This violates the ASN1 but it allows a principal to 10355e9cd1aeSAssar Westerlund * be related to a general directory entry without creating 10365e9cd1aeSAssar Westerlund * the keys. Hopefully it's OK. 10375e9cd1aeSAssar Westerlund */ 1038c19800e8SDoug Rabson ent->entry.keys.len = 0; 1039c19800e8SDoug Rabson ent->entry.keys.val = NULL; 10405e9cd1aeSAssar Westerlund #else 10415e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 10425e9cd1aeSAssar Westerlund goto out; 10435e9cd1aeSAssar Westerlund #endif 10445e9cd1aeSAssar Westerlund } 10455e9cd1aeSAssar Westerlund 1046*ae771770SStanislav Sedov vals = ldap_get_values_len(HDB2LDAP(db), msg, "krb5EncryptionType"); 1047*ae771770SStanislav Sedov if (vals != NULL) { 1048c19800e8SDoug Rabson int i; 1049c19800e8SDoug Rabson 1050c19800e8SDoug Rabson ent->entry.etypes = malloc(sizeof(*(ent->entry.etypes))); 1051c19800e8SDoug Rabson if (ent->entry.etypes == NULL) { 1052c19800e8SDoug Rabson ret = ENOMEM; 1053*ae771770SStanislav Sedov krb5_set_error_message(context, ret,"malloc: out of memory"); 1054c19800e8SDoug Rabson goto out; 1055c19800e8SDoug Rabson } 1056*ae771770SStanislav Sedov ent->entry.etypes->len = ldap_count_values_len(vals); 1057c19800e8SDoug Rabson ent->entry.etypes->val = calloc(ent->entry.etypes->len, sizeof(int)); 1058c19800e8SDoug Rabson if (ent->entry.etypes->val == NULL) { 1059c19800e8SDoug Rabson ret = ENOMEM; 1060*ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 1061*ae771770SStanislav Sedov ent->entry.etypes->len = 0; 1062c19800e8SDoug Rabson goto out; 1063c19800e8SDoug Rabson } 1064c19800e8SDoug Rabson for (i = 0; i < ent->entry.etypes->len; i++) { 1065*ae771770SStanislav Sedov char *buf; 1066*ae771770SStanislav Sedov 1067*ae771770SStanislav Sedov buf = malloc(vals[i]->bv_len + 1); 1068*ae771770SStanislav Sedov if (buf == NULL) { 1069*ae771770SStanislav Sedov ret = ENOMEM; 1070*ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 1071*ae771770SStanislav Sedov goto out; 1072c19800e8SDoug Rabson } 1073*ae771770SStanislav Sedov memcpy(buf, vals[i]->bv_val, vals[i]->bv_len); 1074*ae771770SStanislav Sedov buf[vals[i]->bv_len] = '\0'; 1075*ae771770SStanislav Sedov ent->entry.etypes->val[i] = atoi(buf); 1076*ae771770SStanislav Sedov free(buf); 1077*ae771770SStanislav Sedov } 1078*ae771770SStanislav Sedov ldap_value_free_len(vals); 10795e9cd1aeSAssar Westerlund } 10805e9cd1aeSAssar Westerlund 1081c19800e8SDoug Rabson for (i = 0; i < ent->entry.keys.len; i++) { 1082c19800e8SDoug Rabson if (ent->entry.keys.val[i].key.keytype == ETYPE_ARCFOUR_HMAC_MD5) { 1083c19800e8SDoug Rabson have_arcfour = 1; 1084c19800e8SDoug Rabson break; 1085c19800e8SDoug Rabson } 1086c19800e8SDoug Rabson } 1087c19800e8SDoug Rabson 1088c19800e8SDoug Rabson /* manually construct the NT (type 23) key */ 1089c19800e8SDoug Rabson ret = LDAP_get_string_value(db, msg, "sambaNTPassword", &ntPasswordIN); 1090c19800e8SDoug Rabson if (ret == 0 && have_arcfour == 0) { 1091c19800e8SDoug Rabson unsigned *etypes; 1092c19800e8SDoug Rabson Key *keys; 1093c19800e8SDoug Rabson int i; 1094c19800e8SDoug Rabson 1095c19800e8SDoug Rabson keys = realloc(ent->entry.keys.val, 1096c19800e8SDoug Rabson (ent->entry.keys.len + 1) * sizeof(ent->entry.keys.val[0])); 1097c19800e8SDoug Rabson if (keys == NULL) { 1098c19800e8SDoug Rabson free(ntPasswordIN); 1099c19800e8SDoug Rabson ret = ENOMEM; 1100*ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 1101c19800e8SDoug Rabson goto out; 1102c19800e8SDoug Rabson } 1103c19800e8SDoug Rabson ent->entry.keys.val = keys; 1104c19800e8SDoug Rabson memset(&ent->entry.keys.val[ent->entry.keys.len], 0, sizeof(Key)); 1105c19800e8SDoug Rabson ent->entry.keys.val[ent->entry.keys.len].key.keytype = ETYPE_ARCFOUR_HMAC_MD5; 1106c19800e8SDoug Rabson ret = krb5_data_alloc (&ent->entry.keys.val[ent->entry.keys.len].key.keyvalue, 16); 1107c19800e8SDoug Rabson if (ret) { 1108*ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 1109c19800e8SDoug Rabson free(ntPasswordIN); 1110c19800e8SDoug Rabson ret = ENOMEM; 1111c19800e8SDoug Rabson goto out; 1112c19800e8SDoug Rabson } 1113c19800e8SDoug Rabson ret = hex_decode(ntPasswordIN, 1114c19800e8SDoug Rabson ent->entry.keys.val[ent->entry.keys.len].key.keyvalue.data, 16); 1115c19800e8SDoug Rabson ent->entry.keys.len++; 1116c19800e8SDoug Rabson 1117c19800e8SDoug Rabson if (ent->entry.etypes == NULL) { 1118c19800e8SDoug Rabson ent->entry.etypes = malloc(sizeof(*(ent->entry.etypes))); 1119c19800e8SDoug Rabson if (ent->entry.etypes == NULL) { 1120c19800e8SDoug Rabson ret = ENOMEM; 1121*ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 1122c19800e8SDoug Rabson goto out; 1123c19800e8SDoug Rabson } 1124c19800e8SDoug Rabson ent->entry.etypes->val = NULL; 1125c19800e8SDoug Rabson ent->entry.etypes->len = 0; 1126c19800e8SDoug Rabson } 1127c19800e8SDoug Rabson 1128c19800e8SDoug Rabson for (i = 0; i < ent->entry.etypes->len; i++) 1129c19800e8SDoug Rabson if (ent->entry.etypes->val[i] == ETYPE_ARCFOUR_HMAC_MD5) 1130c19800e8SDoug Rabson break; 1131c19800e8SDoug Rabson /* If there is no ARCFOUR enctype, add one */ 1132c19800e8SDoug Rabson if (i == ent->entry.etypes->len) { 1133c19800e8SDoug Rabson etypes = realloc(ent->entry.etypes->val, 1134c19800e8SDoug Rabson (ent->entry.etypes->len + 1) * 1135c19800e8SDoug Rabson sizeof(ent->entry.etypes->val[0])); 1136c19800e8SDoug Rabson if (etypes == NULL) { 1137c19800e8SDoug Rabson ret = ENOMEM; 1138*ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 1139c19800e8SDoug Rabson goto out; 1140c19800e8SDoug Rabson } 1141c19800e8SDoug Rabson ent->entry.etypes->val = etypes; 1142c19800e8SDoug Rabson ent->entry.etypes->val[ent->entry.etypes->len] = 1143c19800e8SDoug Rabson ETYPE_ARCFOUR_HMAC_MD5; 1144c19800e8SDoug Rabson ent->entry.etypes->len++; 1145c19800e8SDoug Rabson } 1146c19800e8SDoug Rabson } 1147c19800e8SDoug Rabson 1148c19800e8SDoug Rabson ret = LDAP_get_generalized_time_value(db, msg, "createTimestamp", 1149c19800e8SDoug Rabson &ent->entry.created_by.time); 1150c19800e8SDoug Rabson if (ret) 1151c19800e8SDoug Rabson ent->entry.created_by.time = time(NULL); 1152c19800e8SDoug Rabson 1153c19800e8SDoug Rabson ent->entry.created_by.principal = NULL; 11545e9cd1aeSAssar Westerlund 1155*ae771770SStanislav Sedov if (flags & HDB_F_ADMIN_DATA) { 11565e9cd1aeSAssar Westerlund ret = LDAP_get_string_value(db, msg, "creatorsName", &dn); 11575e9cd1aeSAssar Westerlund if (ret == 0) { 1158*ae771770SStanislav Sedov LDAP_dn2principal(context, db, dn, &ent->entry.created_by.principal); 11595e9cd1aeSAssar Westerlund free(dn); 11605e9cd1aeSAssar Westerlund } 11615e9cd1aeSAssar Westerlund 1162*ae771770SStanislav Sedov ent->entry.modified_by = calloc(1, sizeof(*ent->entry.modified_by)); 1163c19800e8SDoug Rabson if (ent->entry.modified_by == NULL) { 11645e9cd1aeSAssar Westerlund ret = ENOMEM; 1165*ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 11665e9cd1aeSAssar Westerlund goto out; 11675e9cd1aeSAssar Westerlund } 1168*ae771770SStanislav Sedov 1169c19800e8SDoug Rabson ret = LDAP_get_generalized_time_value(db, msg, "modifyTimestamp", 1170c19800e8SDoug Rabson &ent->entry.modified_by->time); 11715e9cd1aeSAssar Westerlund if (ret == 0) { 11725e9cd1aeSAssar Westerlund ret = LDAP_get_string_value(db, msg, "modifiersName", &dn); 1173*ae771770SStanislav Sedov if (ret == 0) { 1174*ae771770SStanislav Sedov LDAP_dn2principal(context, db, dn, &ent->entry.modified_by->principal); 11755e9cd1aeSAssar Westerlund free(dn); 11765e9cd1aeSAssar Westerlund } else { 1177c19800e8SDoug Rabson free(ent->entry.modified_by); 1178c19800e8SDoug Rabson ent->entry.modified_by = NULL; 11795e9cd1aeSAssar Westerlund } 1180*ae771770SStanislav Sedov } 1181*ae771770SStanislav Sedov } 11825e9cd1aeSAssar Westerlund 1183c19800e8SDoug Rabson ent->entry.valid_start = malloc(sizeof(*ent->entry.valid_start)); 1184c19800e8SDoug Rabson if (ent->entry.valid_start == NULL) { 11855e9cd1aeSAssar Westerlund ret = ENOMEM; 1186*ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 11875e9cd1aeSAssar Westerlund goto out; 11885e9cd1aeSAssar Westerlund } 1189c19800e8SDoug Rabson ret = LDAP_get_generalized_time_value(db, msg, "krb5ValidStart", 1190c19800e8SDoug Rabson ent->entry.valid_start); 1191c19800e8SDoug Rabson if (ret) { 11925e9cd1aeSAssar Westerlund /* OPTIONAL */ 1193c19800e8SDoug Rabson free(ent->entry.valid_start); 1194c19800e8SDoug Rabson ent->entry.valid_start = NULL; 11955e9cd1aeSAssar Westerlund } 11965e9cd1aeSAssar Westerlund 1197c19800e8SDoug Rabson ent->entry.valid_end = malloc(sizeof(*ent->entry.valid_end)); 1198c19800e8SDoug Rabson if (ent->entry.valid_end == NULL) { 11994137ff4cSJacques Vidrine ret = ENOMEM; 1200*ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 12015e9cd1aeSAssar Westerlund goto out; 12025e9cd1aeSAssar Westerlund } 1203c19800e8SDoug Rabson ret = LDAP_get_generalized_time_value(db, msg, "krb5ValidEnd", 1204c19800e8SDoug Rabson ent->entry.valid_end); 1205c19800e8SDoug Rabson if (ret) { 12065e9cd1aeSAssar Westerlund /* OPTIONAL */ 1207c19800e8SDoug Rabson free(ent->entry.valid_end); 1208c19800e8SDoug Rabson ent->entry.valid_end = NULL; 12095e9cd1aeSAssar Westerlund } 12105e9cd1aeSAssar Westerlund 1211c19800e8SDoug Rabson ret = LDAP_get_integer_value(db, msg, "sambaKickoffTime", &tmp_time); 1212c19800e8SDoug Rabson if (ret == 0) { 1213c19800e8SDoug Rabson if (ent->entry.valid_end == NULL) { 1214c19800e8SDoug Rabson ent->entry.valid_end = malloc(sizeof(*ent->entry.valid_end)); 1215c19800e8SDoug Rabson if (ent->entry.valid_end == NULL) { 12164137ff4cSJacques Vidrine ret = ENOMEM; 1217*ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 12185e9cd1aeSAssar Westerlund goto out; 12195e9cd1aeSAssar Westerlund } 1220c19800e8SDoug Rabson } 1221c19800e8SDoug Rabson *ent->entry.valid_end = tmp_time; 1222c19800e8SDoug Rabson } 1223c19800e8SDoug Rabson 1224c19800e8SDoug Rabson ent->entry.pw_end = malloc(sizeof(*ent->entry.pw_end)); 1225c19800e8SDoug Rabson if (ent->entry.pw_end == NULL) { 1226c19800e8SDoug Rabson ret = ENOMEM; 1227*ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 1228c19800e8SDoug Rabson goto out; 1229c19800e8SDoug Rabson } 1230c19800e8SDoug Rabson ret = LDAP_get_generalized_time_value(db, msg, "krb5PasswordEnd", 1231c19800e8SDoug Rabson ent->entry.pw_end); 1232c19800e8SDoug Rabson if (ret) { 12335e9cd1aeSAssar Westerlund /* OPTIONAL */ 1234c19800e8SDoug Rabson free(ent->entry.pw_end); 1235c19800e8SDoug Rabson ent->entry.pw_end = NULL; 12365e9cd1aeSAssar Westerlund } 12375e9cd1aeSAssar Westerlund 1238*ae771770SStanislav Sedov ret = LDAP_get_integer_value(db, msg, "sambaPwdLastSet", &tmp_time); 1239*ae771770SStanislav Sedov if (ret == 0) { 1240*ae771770SStanislav Sedov time_t delta; 1241*ae771770SStanislav Sedov 1242*ae771770SStanislav Sedov if (ent->entry.pw_end == NULL) { 1243*ae771770SStanislav Sedov ent->entry.pw_end = malloc(sizeof(*ent->entry.pw_end)); 1244*ae771770SStanislav Sedov if (ent->entry.pw_end == NULL) { 1245*ae771770SStanislav Sedov ret = ENOMEM; 1246*ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 1247*ae771770SStanislav Sedov goto out; 1248*ae771770SStanislav Sedov } 1249*ae771770SStanislav Sedov } 1250*ae771770SStanislav Sedov 1251*ae771770SStanislav Sedov delta = krb5_config_get_time_default(context, NULL, 1252*ae771770SStanislav Sedov 365 * 24 * 60 * 60, 1253*ae771770SStanislav Sedov "kadmin", 1254*ae771770SStanislav Sedov "password_lifetime", 1255*ae771770SStanislav Sedov NULL); 1256*ae771770SStanislav Sedov *ent->entry.pw_end = tmp_time + delta; 1257*ae771770SStanislav Sedov } 1258*ae771770SStanislav Sedov 1259c19800e8SDoug Rabson ret = LDAP_get_integer_value(db, msg, "sambaPwdMustChange", &tmp_time); 1260c19800e8SDoug Rabson if (ret == 0) { 1261c19800e8SDoug Rabson if (ent->entry.pw_end == NULL) { 1262c19800e8SDoug Rabson ent->entry.pw_end = malloc(sizeof(*ent->entry.pw_end)); 1263c19800e8SDoug Rabson if (ent->entry.pw_end == NULL) { 12645e9cd1aeSAssar Westerlund ret = ENOMEM; 1265*ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 12665e9cd1aeSAssar Westerlund goto out; 12675e9cd1aeSAssar Westerlund } 1268c19800e8SDoug Rabson } 1269c19800e8SDoug Rabson *ent->entry.pw_end = tmp_time; 12705e9cd1aeSAssar Westerlund } 12715e9cd1aeSAssar Westerlund 1272c19800e8SDoug Rabson /* OPTIONAL */ 1273c19800e8SDoug Rabson ret = LDAP_get_integer_value(db, msg, "sambaPwdLastSet", &tmp_time); 1274c19800e8SDoug Rabson if (ret == 0) 1275c19800e8SDoug Rabson hdb_entry_set_pw_change_time(context, &ent->entry, tmp_time); 1276c19800e8SDoug Rabson 1277c19800e8SDoug Rabson { 1278c19800e8SDoug Rabson int max_life; 1279c19800e8SDoug Rabson 1280c19800e8SDoug Rabson ent->entry.max_life = malloc(sizeof(*ent->entry.max_life)); 1281c19800e8SDoug Rabson if (ent->entry.max_life == NULL) { 12825e9cd1aeSAssar Westerlund ret = ENOMEM; 1283*ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 12845e9cd1aeSAssar Westerlund goto out; 12855e9cd1aeSAssar Westerlund } 1286c19800e8SDoug Rabson ret = LDAP_get_integer_value(db, msg, "krb5MaxLife", &max_life); 1287c19800e8SDoug Rabson if (ret) { 1288c19800e8SDoug Rabson free(ent->entry.max_life); 1289c19800e8SDoug Rabson ent->entry.max_life = NULL; 1290c19800e8SDoug Rabson } else 1291c19800e8SDoug Rabson *ent->entry.max_life = max_life; 12925e9cd1aeSAssar Westerlund } 12935e9cd1aeSAssar Westerlund 1294c19800e8SDoug Rabson { 1295c19800e8SDoug Rabson int max_renew; 1296c19800e8SDoug Rabson 1297c19800e8SDoug Rabson ent->entry.max_renew = malloc(sizeof(*ent->entry.max_renew)); 1298c19800e8SDoug Rabson if (ent->entry.max_renew == NULL) { 1299c19800e8SDoug Rabson ret = ENOMEM; 1300*ae771770SStanislav Sedov krb5_set_error_message(context, ret, "malloc: out of memory"); 1301c19800e8SDoug Rabson goto out; 1302c19800e8SDoug Rabson } 1303c19800e8SDoug Rabson ret = LDAP_get_integer_value(db, msg, "krb5MaxRenew", &max_renew); 1304c19800e8SDoug Rabson if (ret) { 1305c19800e8SDoug Rabson free(ent->entry.max_renew); 1306c19800e8SDoug Rabson ent->entry.max_renew = NULL; 1307c19800e8SDoug Rabson } else 1308c19800e8SDoug Rabson *ent->entry.max_renew = max_renew; 1309c19800e8SDoug Rabson } 1310c19800e8SDoug Rabson 1311*ae771770SStanislav Sedov ret = LDAP_get_integer_value(db, msg, "krb5KDCFlags", &tmp); 1312*ae771770SStanislav Sedov if (ret) 13135e9cd1aeSAssar Westerlund tmp = 0; 13145e9cd1aeSAssar Westerlund 1315c19800e8SDoug Rabson ent->entry.flags = int2HDBFlags(tmp); 1316c19800e8SDoug Rabson 1317c19800e8SDoug Rabson /* Try and find Samba flags to put into the mix */ 1318c19800e8SDoug Rabson ret = LDAP_get_string_value(db, msg, "sambaAcctFlags", &samba_acct_flags); 1319c19800e8SDoug Rabson if (ret == 0) { 1320c19800e8SDoug Rabson /* parse the [UXW...] string: 1321c19800e8SDoug Rabson 1322c19800e8SDoug Rabson 'N' No password 1323c19800e8SDoug Rabson 'D' Disabled 1324c19800e8SDoug Rabson 'H' Homedir required 1325c19800e8SDoug Rabson 'T' Temp account. 1326c19800e8SDoug Rabson 'U' User account (normal) 1327c19800e8SDoug Rabson 'M' MNS logon user account - what is this ? 1328c19800e8SDoug Rabson 'W' Workstation account 1329c19800e8SDoug Rabson 'S' Server account 1330c19800e8SDoug Rabson 'L' Locked account 1331c19800e8SDoug Rabson 'X' No Xpiry on password 1332c19800e8SDoug Rabson 'I' Interdomain trust account 1333c19800e8SDoug Rabson 1334c19800e8SDoug Rabson */ 1335c19800e8SDoug Rabson 13365e9cd1aeSAssar Westerlund int i; 1337c19800e8SDoug Rabson int flags_len = strlen(samba_acct_flags); 13385e9cd1aeSAssar Westerlund 1339c19800e8SDoug Rabson if (flags_len < 2) 1340c19800e8SDoug Rabson goto out2; 1341c19800e8SDoug Rabson 1342c19800e8SDoug Rabson if (samba_acct_flags[0] != '[' 1343c19800e8SDoug Rabson || samba_acct_flags[flags_len - 1] != ']') 1344c19800e8SDoug Rabson goto out2; 1345c19800e8SDoug Rabson 1346c19800e8SDoug Rabson /* Allow forwarding */ 1347c19800e8SDoug Rabson if (samba_forwardable) 1348c19800e8SDoug Rabson ent->entry.flags.forwardable = TRUE; 1349c19800e8SDoug Rabson 1350c19800e8SDoug Rabson for (i=0; i < flags_len; i++) { 1351c19800e8SDoug Rabson switch (samba_acct_flags[i]) { 1352c19800e8SDoug Rabson case ' ': 1353c19800e8SDoug Rabson case '[': 1354c19800e8SDoug Rabson case ']': 1355c19800e8SDoug Rabson break; 1356c19800e8SDoug Rabson case 'N': 1357c19800e8SDoug Rabson /* how to handle no password in kerberos? */ 1358c19800e8SDoug Rabson break; 1359c19800e8SDoug Rabson case 'D': 1360c19800e8SDoug Rabson ent->entry.flags.invalid = TRUE; 1361c19800e8SDoug Rabson break; 1362c19800e8SDoug Rabson case 'H': 1363c19800e8SDoug Rabson break; 1364c19800e8SDoug Rabson case 'T': 1365c19800e8SDoug Rabson /* temp duplicate */ 1366c19800e8SDoug Rabson ent->entry.flags.invalid = TRUE; 1367c19800e8SDoug Rabson break; 1368c19800e8SDoug Rabson case 'U': 1369c19800e8SDoug Rabson ent->entry.flags.client = TRUE; 1370c19800e8SDoug Rabson break; 1371c19800e8SDoug Rabson case 'M': 1372c19800e8SDoug Rabson break; 1373c19800e8SDoug Rabson case 'W': 1374c19800e8SDoug Rabson case 'S': 1375c19800e8SDoug Rabson ent->entry.flags.server = TRUE; 1376c19800e8SDoug Rabson ent->entry.flags.client = TRUE; 1377c19800e8SDoug Rabson break; 1378c19800e8SDoug Rabson case 'L': 1379c19800e8SDoug Rabson ent->entry.flags.invalid = TRUE; 1380c19800e8SDoug Rabson break; 1381c19800e8SDoug Rabson case 'X': 1382c19800e8SDoug Rabson if (ent->entry.pw_end) { 1383c19800e8SDoug Rabson free(ent->entry.pw_end); 1384c19800e8SDoug Rabson ent->entry.pw_end = NULL; 13855e9cd1aeSAssar Westerlund } 1386c19800e8SDoug Rabson break; 1387c19800e8SDoug Rabson case 'I': 1388c19800e8SDoug Rabson ent->entry.flags.server = TRUE; 1389c19800e8SDoug Rabson ent->entry.flags.client = TRUE; 1390c19800e8SDoug Rabson break; 13915e9cd1aeSAssar Westerlund } 1392c19800e8SDoug Rabson } 1393c19800e8SDoug Rabson out2: 1394c19800e8SDoug Rabson free(samba_acct_flags); 13955e9cd1aeSAssar Westerlund } 13965e9cd1aeSAssar Westerlund 13975e9cd1aeSAssar Westerlund ret = 0; 13985e9cd1aeSAssar Westerlund 13995e9cd1aeSAssar Westerlund out: 1400c19800e8SDoug Rabson if (unparsed_name) 14015e9cd1aeSAssar Westerlund free(unparsed_name); 14025e9cd1aeSAssar Westerlund 1403c19800e8SDoug Rabson if (ret) 14045e9cd1aeSAssar Westerlund hdb_free_entry(context, ent); 14055e9cd1aeSAssar Westerlund 14065e9cd1aeSAssar Westerlund return ret; 14075e9cd1aeSAssar Westerlund } 14085e9cd1aeSAssar Westerlund 1409c19800e8SDoug Rabson static krb5_error_code 1410c19800e8SDoug Rabson LDAP_close(krb5_context context, HDB * db) 14115e9cd1aeSAssar Westerlund { 1412c19800e8SDoug Rabson if (HDB2LDAP(db)) { 1413c19800e8SDoug Rabson ldap_unbind_ext(HDB2LDAP(db), NULL, NULL); 1414c19800e8SDoug Rabson ((struct hdbldapdb *)db->hdb_db)->h_lp = NULL; 1415c19800e8SDoug Rabson } 14164137ff4cSJacques Vidrine 14175e9cd1aeSAssar Westerlund return 0; 14185e9cd1aeSAssar Westerlund } 14195e9cd1aeSAssar Westerlund 14205e9cd1aeSAssar Westerlund static krb5_error_code 14215e9cd1aeSAssar Westerlund LDAP_lock(krb5_context context, HDB * db, int operation) 14225e9cd1aeSAssar Westerlund { 14235e9cd1aeSAssar Westerlund return 0; 14245e9cd1aeSAssar Westerlund } 14255e9cd1aeSAssar Westerlund 1426c19800e8SDoug Rabson static krb5_error_code 1427c19800e8SDoug Rabson LDAP_unlock(krb5_context context, HDB * db) 14285e9cd1aeSAssar Westerlund { 14295e9cd1aeSAssar Westerlund return 0; 14305e9cd1aeSAssar Westerlund } 14315e9cd1aeSAssar Westerlund 14325e9cd1aeSAssar Westerlund static krb5_error_code 1433c19800e8SDoug Rabson LDAP_seq(krb5_context context, HDB * db, unsigned flags, hdb_entry_ex * entry) 14345e9cd1aeSAssar Westerlund { 14355e9cd1aeSAssar Westerlund int msgid, rc, parserc; 14365e9cd1aeSAssar Westerlund krb5_error_code ret; 14375e9cd1aeSAssar Westerlund LDAPMessage *e; 14385e9cd1aeSAssar Westerlund 1439c19800e8SDoug Rabson msgid = HDB2MSGID(db); 1440c19800e8SDoug Rabson if (msgid < 0) 14415e9cd1aeSAssar Westerlund return HDB_ERR_NOENTRY; 14425e9cd1aeSAssar Westerlund 14435e9cd1aeSAssar Westerlund do { 1444c19800e8SDoug Rabson rc = ldap_result(HDB2LDAP(db), msgid, LDAP_MSG_ONE, NULL, &e); 14455e9cd1aeSAssar Westerlund switch (rc) { 1446c19800e8SDoug Rabson case LDAP_RES_SEARCH_REFERENCE: 1447c19800e8SDoug Rabson ldap_msgfree(e); 1448c19800e8SDoug Rabson ret = 0; 1449c19800e8SDoug Rabson break; 14505e9cd1aeSAssar Westerlund case LDAP_RES_SEARCH_ENTRY: 14515e9cd1aeSAssar Westerlund /* We have an entry. Parse it. */ 1452*ae771770SStanislav Sedov ret = LDAP_message2entry(context, db, e, flags, entry); 14535e9cd1aeSAssar Westerlund ldap_msgfree(e); 14545e9cd1aeSAssar Westerlund break; 14555e9cd1aeSAssar Westerlund case LDAP_RES_SEARCH_RESULT: 14565e9cd1aeSAssar Westerlund /* We're probably at the end of the results. If not, abandon. */ 14575e9cd1aeSAssar Westerlund parserc = 1458c19800e8SDoug Rabson ldap_parse_result(HDB2LDAP(db), e, NULL, NULL, NULL, 14595e9cd1aeSAssar Westerlund NULL, NULL, 1); 1460*ae771770SStanislav Sedov ret = HDB_ERR_NOENTRY; 14615e9cd1aeSAssar Westerlund if (parserc != LDAP_SUCCESS 14625e9cd1aeSAssar Westerlund && parserc != LDAP_MORE_RESULTS_TO_RETURN) { 1463*ae771770SStanislav Sedov krb5_set_error_message(context, ret, "ldap_parse_result: %s", 1464c19800e8SDoug Rabson ldap_err2string(parserc)); 1465*ae771770SStanislav Sedov ldap_abandon_ext(HDB2LDAP(db), msgid, NULL, NULL); 14665e9cd1aeSAssar Westerlund } 1467c19800e8SDoug Rabson HDBSETMSGID(db, -1); 14685e9cd1aeSAssar Westerlund break; 1469c19800e8SDoug Rabson case LDAP_SERVER_DOWN: 1470c19800e8SDoug Rabson ldap_msgfree(e); 1471c19800e8SDoug Rabson LDAP_close(context, db); 1472c19800e8SDoug Rabson HDBSETMSGID(db, -1); 1473c19800e8SDoug Rabson ret = ENETDOWN; 1474c19800e8SDoug Rabson break; 14755e9cd1aeSAssar Westerlund default: 14765e9cd1aeSAssar Westerlund /* Some unspecified error (timeout?). Abandon. */ 14775e9cd1aeSAssar Westerlund ldap_msgfree(e); 1478*ae771770SStanislav Sedov ldap_abandon_ext(HDB2LDAP(db), msgid, NULL, NULL); 14795e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 1480c19800e8SDoug Rabson HDBSETMSGID(db, -1); 14815e9cd1aeSAssar Westerlund break; 14825e9cd1aeSAssar Westerlund } 14835e9cd1aeSAssar Westerlund } while (rc == LDAP_RES_SEARCH_REFERENCE); 14845e9cd1aeSAssar Westerlund 14855e9cd1aeSAssar Westerlund if (ret == 0) { 1486c19800e8SDoug Rabson if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) { 1487c19800e8SDoug Rabson ret = hdb_unseal_keys(context, db, &entry->entry); 14885e9cd1aeSAssar Westerlund if (ret) 14895e9cd1aeSAssar Westerlund hdb_free_entry(context, entry); 14905e9cd1aeSAssar Westerlund } 14915e9cd1aeSAssar Westerlund } 14925e9cd1aeSAssar Westerlund 14935e9cd1aeSAssar Westerlund return ret; 14945e9cd1aeSAssar Westerlund } 14955e9cd1aeSAssar Westerlund 14965e9cd1aeSAssar Westerlund static krb5_error_code 14975e9cd1aeSAssar Westerlund LDAP_firstkey(krb5_context context, HDB *db, unsigned flags, 1498c19800e8SDoug Rabson hdb_entry_ex *entry) 14995e9cd1aeSAssar Westerlund { 1500c19800e8SDoug Rabson krb5_error_code ret; 1501c19800e8SDoug Rabson int msgid; 15025e9cd1aeSAssar Westerlund 1503c19800e8SDoug Rabson ret = LDAP__connect(context, db); 1504c19800e8SDoug Rabson if (ret) 1505c19800e8SDoug Rabson return ret; 15065e9cd1aeSAssar Westerlund 1507c19800e8SDoug Rabson ret = LDAP_no_size_limit(context, HDB2LDAP(db)); 1508c19800e8SDoug Rabson if (ret) 1509c19800e8SDoug Rabson return ret; 15105e9cd1aeSAssar Westerlund 1511*ae771770SStanislav Sedov ret = ldap_search_ext(HDB2LDAP(db), HDB2BASE(db), 1512c19800e8SDoug Rabson LDAP_SCOPE_SUBTREE, 1513c19800e8SDoug Rabson "(|(objectClass=krb5Principal)(objectClass=sambaSamAccount))", 1514*ae771770SStanislav Sedov krb5kdcentry_attrs, 0, 1515*ae771770SStanislav Sedov NULL, NULL, NULL, 0, &msgid); 1516c19800e8SDoug Rabson if (msgid < 0) 15175e9cd1aeSAssar Westerlund return HDB_ERR_NOENTRY; 15185e9cd1aeSAssar Westerlund 1519c19800e8SDoug Rabson HDBSETMSGID(db, msgid); 15205e9cd1aeSAssar Westerlund 15215e9cd1aeSAssar Westerlund return LDAP_seq(context, db, flags, entry); 15225e9cd1aeSAssar Westerlund } 15235e9cd1aeSAssar Westerlund 15245e9cd1aeSAssar Westerlund static krb5_error_code 15255e9cd1aeSAssar Westerlund LDAP_nextkey(krb5_context context, HDB * db, unsigned flags, 1526c19800e8SDoug Rabson hdb_entry_ex * entry) 15275e9cd1aeSAssar Westerlund { 15285e9cd1aeSAssar Westerlund return LDAP_seq(context, db, flags, entry); 15295e9cd1aeSAssar Westerlund } 15305e9cd1aeSAssar Westerlund 15315e9cd1aeSAssar Westerlund static krb5_error_code 1532c19800e8SDoug Rabson LDAP__connect(krb5_context context, HDB * db) 15335e9cd1aeSAssar Westerlund { 15344137ff4cSJacques Vidrine int rc, version = LDAP_VERSION3; 15351c43270aSJacques Vidrine /* 15361c43270aSJacques Vidrine * Empty credentials to do a SASL bind with LDAP. Note that empty 15371c43270aSJacques Vidrine * different from NULL credentials. If you provide NULL 15381c43270aSJacques Vidrine * credentials instead of empty credentials you will get a SASL 15391c43270aSJacques Vidrine * bind in progress message. 15401c43270aSJacques Vidrine */ 15411c43270aSJacques Vidrine struct berval bv = { 0, "" }; 15425e9cd1aeSAssar Westerlund 1543c19800e8SDoug Rabson if (HDB2LDAP(db)) { 15445e9cd1aeSAssar Westerlund /* connection has been opened. ping server. */ 15455e9cd1aeSAssar Westerlund struct sockaddr_un addr; 1546c19800e8SDoug Rabson socklen_t len = sizeof(addr); 15475e9cd1aeSAssar Westerlund int sd; 15485e9cd1aeSAssar Westerlund 1549c19800e8SDoug Rabson if (ldap_get_option(HDB2LDAP(db), LDAP_OPT_DESC, &sd) == 0 && 15505e9cd1aeSAssar Westerlund getpeername(sd, (struct sockaddr *) &addr, &len) < 0) { 15515e9cd1aeSAssar Westerlund /* the other end has died. reopen. */ 15525e9cd1aeSAssar Westerlund LDAP_close(context, db); 15535e9cd1aeSAssar Westerlund } 15545e9cd1aeSAssar Westerlund } 15555e9cd1aeSAssar Westerlund 1556c19800e8SDoug Rabson if (HDB2LDAP(db) != NULL) /* server is UP */ 15575e9cd1aeSAssar Westerlund return 0; 15585e9cd1aeSAssar Westerlund 1559c19800e8SDoug Rabson rc = ldap_initialize(&((struct hdbldapdb *)db->hdb_db)->h_lp, HDB2URL(db)); 15605e9cd1aeSAssar Westerlund if (rc != LDAP_SUCCESS) { 1561*ae771770SStanislav Sedov krb5_set_error_message(context, HDB_ERR_NOENTRY, "ldap_initialize: %s", 1562c19800e8SDoug Rabson ldap_err2string(rc)); 15635e9cd1aeSAssar Westerlund return HDB_ERR_NOENTRY; 15645e9cd1aeSAssar Westerlund } 15655e9cd1aeSAssar Westerlund 1566c19800e8SDoug Rabson rc = ldap_set_option(HDB2LDAP(db), LDAP_OPT_PROTOCOL_VERSION, 1567c19800e8SDoug Rabson (const void *)&version); 15685e9cd1aeSAssar Westerlund if (rc != LDAP_SUCCESS) { 1569*ae771770SStanislav Sedov krb5_set_error_message(context, HDB_ERR_BADVERSION, 1570*ae771770SStanislav Sedov "ldap_set_option: %s", ldap_err2string(rc)); 1571c19800e8SDoug Rabson LDAP_close(context, db); 15724137ff4cSJacques Vidrine return HDB_ERR_BADVERSION; 15735e9cd1aeSAssar Westerlund } 15745e9cd1aeSAssar Westerlund 1575c19800e8SDoug Rabson rc = ldap_sasl_bind_s(HDB2LDAP(db), NULL, "EXTERNAL", &bv, 1576c19800e8SDoug Rabson NULL, NULL, NULL); 15771c43270aSJacques Vidrine if (rc != LDAP_SUCCESS) { 1578*ae771770SStanislav Sedov krb5_set_error_message(context, HDB_ERR_BADVERSION, 1579*ae771770SStanislav Sedov "ldap_sasl_bind_s: %s", ldap_err2string(rc)); 1580c19800e8SDoug Rabson LDAP_close(context, db); 15811c43270aSJacques Vidrine return HDB_ERR_BADVERSION; 15821c43270aSJacques Vidrine } 15831c43270aSJacques Vidrine 15844137ff4cSJacques Vidrine return 0; 15855e9cd1aeSAssar Westerlund } 15865e9cd1aeSAssar Westerlund 15875e9cd1aeSAssar Westerlund static krb5_error_code 15885e9cd1aeSAssar Westerlund LDAP_open(krb5_context context, HDB * db, int flags, mode_t mode) 15895e9cd1aeSAssar Westerlund { 15905e9cd1aeSAssar Westerlund /* Not the right place for this. */ 15915e9cd1aeSAssar Westerlund #ifdef HAVE_SIGACTION 15925e9cd1aeSAssar Westerlund struct sigaction sa; 15935e9cd1aeSAssar Westerlund 15945e9cd1aeSAssar Westerlund sa.sa_flags = 0; 15955e9cd1aeSAssar Westerlund sa.sa_handler = SIG_IGN; 15965e9cd1aeSAssar Westerlund sigemptyset(&sa.sa_mask); 15975e9cd1aeSAssar Westerlund 15985e9cd1aeSAssar Westerlund sigaction(SIGPIPE, &sa, NULL); 15995e9cd1aeSAssar Westerlund #else 16005e9cd1aeSAssar Westerlund signal(SIGPIPE, SIG_IGN); 16014137ff4cSJacques Vidrine #endif /* HAVE_SIGACTION */ 16025e9cd1aeSAssar Westerlund 16034137ff4cSJacques Vidrine return LDAP__connect(context, db); 16045e9cd1aeSAssar Westerlund } 16055e9cd1aeSAssar Westerlund 16065e9cd1aeSAssar Westerlund static krb5_error_code 1607*ae771770SStanislav Sedov LDAP_fetch_kvno(krb5_context context, HDB * db, krb5_const_principal principal, 1608*ae771770SStanislav Sedov unsigned flags, krb5_kvno kvno, hdb_entry_ex * entry) 16095e9cd1aeSAssar Westerlund { 16105e9cd1aeSAssar Westerlund LDAPMessage *msg, *e; 16115e9cd1aeSAssar Westerlund krb5_error_code ret; 16125e9cd1aeSAssar Westerlund 1613c19800e8SDoug Rabson ret = LDAP_principal2message(context, db, principal, &msg); 1614c19800e8SDoug Rabson if (ret) 16155e9cd1aeSAssar Westerlund return ret; 16165e9cd1aeSAssar Westerlund 1617c19800e8SDoug Rabson e = ldap_first_entry(HDB2LDAP(db), msg); 16185e9cd1aeSAssar Westerlund if (e == NULL) { 16195e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 16205e9cd1aeSAssar Westerlund goto out; 16215e9cd1aeSAssar Westerlund } 16225e9cd1aeSAssar Westerlund 1623*ae771770SStanislav Sedov ret = LDAP_message2entry(context, db, e, flags, entry); 16245e9cd1aeSAssar Westerlund if (ret == 0) { 1625c19800e8SDoug Rabson if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) { 1626c19800e8SDoug Rabson ret = hdb_unseal_keys(context, db, &entry->entry); 16275e9cd1aeSAssar Westerlund if (ret) 16285e9cd1aeSAssar Westerlund hdb_free_entry(context, entry); 16295e9cd1aeSAssar Westerlund } 16305e9cd1aeSAssar Westerlund } 16315e9cd1aeSAssar Westerlund 16325e9cd1aeSAssar Westerlund out: 16335e9cd1aeSAssar Westerlund ldap_msgfree(msg); 16345e9cd1aeSAssar Westerlund 16355e9cd1aeSAssar Westerlund return ret; 16365e9cd1aeSAssar Westerlund } 16375e9cd1aeSAssar Westerlund 16385e9cd1aeSAssar Westerlund static krb5_error_code 1639*ae771770SStanislav Sedov LDAP_fetch(krb5_context context, HDB * db, krb5_const_principal principal, 1640*ae771770SStanislav Sedov unsigned flags, hdb_entry_ex * entry) 1641*ae771770SStanislav Sedov { 1642*ae771770SStanislav Sedov return LDAP_fetch_kvno(context, db, principal, 1643*ae771770SStanislav Sedov flags & (~HDB_F_KVNO_SPECIFIED), 0, entry); 1644*ae771770SStanislav Sedov } 1645*ae771770SStanislav Sedov 1646*ae771770SStanislav Sedov static krb5_error_code 16475e9cd1aeSAssar Westerlund LDAP_store(krb5_context context, HDB * db, unsigned flags, 1648c19800e8SDoug Rabson hdb_entry_ex * entry) 16495e9cd1aeSAssar Westerlund { 16505e9cd1aeSAssar Westerlund LDAPMod **mods = NULL; 16515e9cd1aeSAssar Westerlund krb5_error_code ret; 16524137ff4cSJacques Vidrine const char *errfn; 16534137ff4cSJacques Vidrine int rc; 16545e9cd1aeSAssar Westerlund LDAPMessage *msg = NULL, *e = NULL; 16555e9cd1aeSAssar Westerlund char *dn = NULL, *name = NULL; 16565e9cd1aeSAssar Westerlund 1657c19800e8SDoug Rabson ret = LDAP_principal2message(context, db, entry->entry.principal, &msg); 1658c19800e8SDoug Rabson if (ret == 0) 1659c19800e8SDoug Rabson e = ldap_first_entry(HDB2LDAP(db), msg); 1660c19800e8SDoug Rabson 1661c19800e8SDoug Rabson ret = krb5_unparse_name(context, entry->entry.principal, &name); 1662c19800e8SDoug Rabson if (ret) { 1663c19800e8SDoug Rabson free(name); 1664c19800e8SDoug Rabson return ret; 16655e9cd1aeSAssar Westerlund } 16665e9cd1aeSAssar Westerlund 1667c19800e8SDoug Rabson ret = hdb_seal_keys(context, db, &entry->entry); 1668c19800e8SDoug Rabson if (ret) 16695e9cd1aeSAssar Westerlund goto out; 16705e9cd1aeSAssar Westerlund 16715e9cd1aeSAssar Westerlund /* turn new entry into LDAPMod array */ 16725e9cd1aeSAssar Westerlund ret = LDAP_entry2mods(context, db, entry, e, &mods); 1673c19800e8SDoug Rabson if (ret) 16745e9cd1aeSAssar Westerlund goto out; 16755e9cd1aeSAssar Westerlund 16765e9cd1aeSAssar Westerlund if (e == NULL) { 1677c19800e8SDoug Rabson ret = asprintf(&dn, "krb5PrincipalName=%s,%s", name, HDB2CREATE(db)); 16785e9cd1aeSAssar Westerlund if (ret < 0) { 16795e9cd1aeSAssar Westerlund ret = ENOMEM; 1680*ae771770SStanislav Sedov krb5_set_error_message(context, ret, "asprintf: out of memory"); 16815e9cd1aeSAssar Westerlund goto out; 16825e9cd1aeSAssar Westerlund } 16835e9cd1aeSAssar Westerlund } else if (flags & HDB_F_REPLACE) { 16845e9cd1aeSAssar Westerlund /* Entry exists, and we're allowed to replace it. */ 1685c19800e8SDoug Rabson dn = ldap_get_dn(HDB2LDAP(db), e); 16865e9cd1aeSAssar Westerlund } else { 16875e9cd1aeSAssar Westerlund /* Entry exists, but we're not allowed to replace it. Bail. */ 16885e9cd1aeSAssar Westerlund ret = HDB_ERR_EXISTS; 16895e9cd1aeSAssar Westerlund goto out; 16905e9cd1aeSAssar Westerlund } 16915e9cd1aeSAssar Westerlund 16925e9cd1aeSAssar Westerlund /* write entry into directory */ 16935e9cd1aeSAssar Westerlund if (e == NULL) { 16945e9cd1aeSAssar Westerlund /* didn't exist before */ 1695*ae771770SStanislav Sedov rc = ldap_add_ext_s(HDB2LDAP(db), dn, mods, NULL, NULL ); 1696*ae771770SStanislav Sedov errfn = "ldap_add_ext_s"; 16975e9cd1aeSAssar Westerlund } else { 16985e9cd1aeSAssar Westerlund /* already existed, send deltas only */ 1699*ae771770SStanislav Sedov rc = ldap_modify_ext_s(HDB2LDAP(db), dn, mods, NULL, NULL ); 1700*ae771770SStanislav Sedov errfn = "ldap_modify_ext_s"; 17015e9cd1aeSAssar Westerlund } 17025e9cd1aeSAssar Westerlund 1703c19800e8SDoug Rabson if (check_ldap(context, db, rc)) { 1704c19800e8SDoug Rabson char *ld_error = NULL; 1705c19800e8SDoug Rabson ldap_get_option(HDB2LDAP(db), LDAP_OPT_ERROR_STRING, 1706c19800e8SDoug Rabson &ld_error); 17075e9cd1aeSAssar Westerlund ret = HDB_ERR_CANT_LOCK_DB; 1708*ae771770SStanislav Sedov krb5_set_error_message(context, ret, "%s: %s (DN=%s) %s: %s", 1709*ae771770SStanislav Sedov errfn, name, dn, ldap_err2string(rc), ld_error); 1710c19800e8SDoug Rabson } else 1711c19800e8SDoug Rabson ret = 0; 17125e9cd1aeSAssar Westerlund 17135e9cd1aeSAssar Westerlund out: 17145e9cd1aeSAssar Westerlund /* free stuff */ 1715c19800e8SDoug Rabson if (dn) 17165e9cd1aeSAssar Westerlund free(dn); 1717c19800e8SDoug Rabson if (msg) 17185e9cd1aeSAssar Westerlund ldap_msgfree(msg); 1719c19800e8SDoug Rabson if (mods) 17205e9cd1aeSAssar Westerlund ldap_mods_free(mods, 1); 1721c19800e8SDoug Rabson if (name) 17225e9cd1aeSAssar Westerlund free(name); 17235e9cd1aeSAssar Westerlund 17245e9cd1aeSAssar Westerlund return ret; 17255e9cd1aeSAssar Westerlund } 17265e9cd1aeSAssar Westerlund 17275e9cd1aeSAssar Westerlund static krb5_error_code 1728c19800e8SDoug Rabson LDAP_remove(krb5_context context, HDB *db, krb5_const_principal principal) 17295e9cd1aeSAssar Westerlund { 17305e9cd1aeSAssar Westerlund krb5_error_code ret; 17315e9cd1aeSAssar Westerlund LDAPMessage *msg, *e; 17325e9cd1aeSAssar Westerlund char *dn = NULL; 17334137ff4cSJacques Vidrine int rc, limit = LDAP_NO_LIMIT; 17345e9cd1aeSAssar Westerlund 1735c19800e8SDoug Rabson ret = LDAP_principal2message(context, db, principal, &msg); 1736c19800e8SDoug Rabson if (ret) 17375e9cd1aeSAssar Westerlund goto out; 17385e9cd1aeSAssar Westerlund 1739c19800e8SDoug Rabson e = ldap_first_entry(HDB2LDAP(db), msg); 17405e9cd1aeSAssar Westerlund if (e == NULL) { 17415e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 17425e9cd1aeSAssar Westerlund goto out; 17435e9cd1aeSAssar Westerlund } 17445e9cd1aeSAssar Westerlund 1745c19800e8SDoug Rabson dn = ldap_get_dn(HDB2LDAP(db), e); 17465e9cd1aeSAssar Westerlund if (dn == NULL) { 17475e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 17485e9cd1aeSAssar Westerlund goto out; 17495e9cd1aeSAssar Westerlund } 17505e9cd1aeSAssar Westerlund 1751c19800e8SDoug Rabson rc = ldap_set_option(HDB2LDAP(db), LDAP_OPT_SIZELIMIT, (const void *)&limit); 17524137ff4cSJacques Vidrine if (rc != LDAP_SUCCESS) { 17534137ff4cSJacques Vidrine ret = HDB_ERR_BADVERSION; 1754*ae771770SStanislav Sedov krb5_set_error_message(context, ret, "ldap_set_option: %s", 1755*ae771770SStanislav Sedov ldap_err2string(rc)); 17564137ff4cSJacques Vidrine goto out; 17574137ff4cSJacques Vidrine } 17585e9cd1aeSAssar Westerlund 1759*ae771770SStanislav Sedov rc = ldap_delete_ext_s(HDB2LDAP(db), dn, NULL, NULL ); 1760c19800e8SDoug Rabson if (check_ldap(context, db, rc)) { 17615e9cd1aeSAssar Westerlund ret = HDB_ERR_CANT_LOCK_DB; 1762*ae771770SStanislav Sedov krb5_set_error_message(context, ret, "ldap_delete_ext_s: %s", 1763*ae771770SStanislav Sedov ldap_err2string(rc)); 1764c19800e8SDoug Rabson } else 1765c19800e8SDoug Rabson ret = 0; 17665e9cd1aeSAssar Westerlund 17675e9cd1aeSAssar Westerlund out: 1768c19800e8SDoug Rabson if (dn != NULL) 17695e9cd1aeSAssar Westerlund free(dn); 1770c19800e8SDoug Rabson if (msg != NULL) 17715e9cd1aeSAssar Westerlund ldap_msgfree(msg); 17725e9cd1aeSAssar Westerlund 17735e9cd1aeSAssar Westerlund return ret; 17745e9cd1aeSAssar Westerlund } 17755e9cd1aeSAssar Westerlund 17765e9cd1aeSAssar Westerlund static krb5_error_code 1777c19800e8SDoug Rabson LDAP_destroy(krb5_context context, HDB * db) 17785e9cd1aeSAssar Westerlund { 17795e9cd1aeSAssar Westerlund krb5_error_code ret; 17805e9cd1aeSAssar Westerlund 1781c19800e8SDoug Rabson LDAP_close(context, db); 1782c19800e8SDoug Rabson 17835e9cd1aeSAssar Westerlund ret = hdb_clear_master_key(context, db); 1784c19800e8SDoug Rabson if (HDB2BASE(db)) 1785c19800e8SDoug Rabson free(HDB2BASE(db)); 1786c19800e8SDoug Rabson if (HDB2CREATE(db)) 1787c19800e8SDoug Rabson free(HDB2CREATE(db)); 1788c19800e8SDoug Rabson if (HDB2URL(db)) 1789c19800e8SDoug Rabson free(HDB2URL(db)); 1790c19800e8SDoug Rabson if (db->hdb_name) 1791c19800e8SDoug Rabson free(db->hdb_name); 1792c19800e8SDoug Rabson free(db->hdb_db); 17935e9cd1aeSAssar Westerlund free(db); 17945e9cd1aeSAssar Westerlund 17955e9cd1aeSAssar Westerlund return ret; 17965e9cd1aeSAssar Westerlund } 17975e9cd1aeSAssar Westerlund 1798*ae771770SStanislav Sedov static krb5_error_code 1799c19800e8SDoug Rabson hdb_ldap_common(krb5_context context, 1800c19800e8SDoug Rabson HDB ** db, 1801c19800e8SDoug Rabson const char *search_base, 1802c19800e8SDoug Rabson const char *url) 18035e9cd1aeSAssar Westerlund { 1804c19800e8SDoug Rabson struct hdbldapdb *h; 1805c19800e8SDoug Rabson const char *create_base = NULL; 1806c19800e8SDoug Rabson 1807c19800e8SDoug Rabson if (search_base == NULL && search_base[0] == '\0') { 1808*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, "ldap search base not configured"); 1809c19800e8SDoug Rabson return ENOMEM; /* XXX */ 1810c19800e8SDoug Rabson } 1811c19800e8SDoug Rabson 1812c19800e8SDoug Rabson if (structural_object == NULL) { 1813c19800e8SDoug Rabson const char *p; 1814c19800e8SDoug Rabson 1815c19800e8SDoug Rabson p = krb5_config_get_string(context, NULL, "kdc", 1816c19800e8SDoug Rabson "hdb-ldap-structural-object", NULL); 1817c19800e8SDoug Rabson if (p == NULL) 1818c19800e8SDoug Rabson p = default_structural_object; 1819c19800e8SDoug Rabson structural_object = strdup(p); 1820c19800e8SDoug Rabson if (structural_object == NULL) { 1821*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 1822c19800e8SDoug Rabson return ENOMEM; 1823c19800e8SDoug Rabson } 1824c19800e8SDoug Rabson } 1825c19800e8SDoug Rabson 1826c19800e8SDoug Rabson samba_forwardable = 1827c19800e8SDoug Rabson krb5_config_get_bool_default(context, NULL, TRUE, 1828c19800e8SDoug Rabson "kdc", "hdb-samba-forwardable", NULL); 1829c19800e8SDoug Rabson 1830c19800e8SDoug Rabson *db = calloc(1, sizeof(**db)); 18314137ff4cSJacques Vidrine if (*db == NULL) { 1832*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 18335e9cd1aeSAssar Westerlund return ENOMEM; 18344137ff4cSJacques Vidrine } 1835c19800e8SDoug Rabson memset(*db, 0, sizeof(**db)); 18365e9cd1aeSAssar Westerlund 1837c19800e8SDoug Rabson h = calloc(1, sizeof(*h)); 1838c19800e8SDoug Rabson if (h == NULL) { 18394137ff4cSJacques Vidrine free(*db); 18404137ff4cSJacques Vidrine *db = NULL; 1841*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); 18424137ff4cSJacques Vidrine return ENOMEM; 18434137ff4cSJacques Vidrine } 1844c19800e8SDoug Rabson (*db)->hdb_db = h; 1845c19800e8SDoug Rabson 1846c19800e8SDoug Rabson /* XXX */ 1847c19800e8SDoug Rabson if (asprintf(&(*db)->hdb_name, "ldap:%s", search_base) == -1) { 1848c19800e8SDoug Rabson LDAP_destroy(context, *db); 1849c19800e8SDoug Rabson *db = NULL; 1850*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, "strdup: out of memory"); 1851c19800e8SDoug Rabson return ENOMEM; 18524137ff4cSJacques Vidrine } 18534137ff4cSJacques Vidrine 1854c19800e8SDoug Rabson h->h_url = strdup(url); 1855c19800e8SDoug Rabson h->h_base = strdup(search_base); 1856c19800e8SDoug Rabson if (h->h_url == NULL || h->h_base == NULL) { 1857c19800e8SDoug Rabson LDAP_destroy(context, *db); 1858c19800e8SDoug Rabson *db = NULL; 1859*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, "strdup: out of memory"); 1860c19800e8SDoug Rabson return ENOMEM; 1861c19800e8SDoug Rabson } 1862c19800e8SDoug Rabson 1863c19800e8SDoug Rabson create_base = krb5_config_get_string(context, NULL, "kdc", 1864c19800e8SDoug Rabson "hdb-ldap-create-base", NULL); 1865c19800e8SDoug Rabson if (create_base == NULL) 1866c19800e8SDoug Rabson create_base = h->h_base; 1867c19800e8SDoug Rabson 1868c19800e8SDoug Rabson h->h_createbase = strdup(create_base); 1869c19800e8SDoug Rabson if (h->h_createbase == NULL) { 1870c19800e8SDoug Rabson LDAP_destroy(context, *db); 1871c19800e8SDoug Rabson *db = NULL; 1872*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, "strdup: out of memory"); 1873c19800e8SDoug Rabson return ENOMEM; 1874c19800e8SDoug Rabson } 1875c19800e8SDoug Rabson 1876c19800e8SDoug Rabson (*db)->hdb_master_key_set = 0; 1877c19800e8SDoug Rabson (*db)->hdb_openp = 0; 1878*ae771770SStanislav Sedov (*db)->hdb_capability_flags = 0; 1879c19800e8SDoug Rabson (*db)->hdb_open = LDAP_open; 1880c19800e8SDoug Rabson (*db)->hdb_close = LDAP_close; 1881*ae771770SStanislav Sedov (*db)->hdb_fetch_kvno = LDAP_fetch_kvno; 1882c19800e8SDoug Rabson (*db)->hdb_store = LDAP_store; 1883c19800e8SDoug Rabson (*db)->hdb_remove = LDAP_remove; 1884c19800e8SDoug Rabson (*db)->hdb_firstkey = LDAP_firstkey; 1885c19800e8SDoug Rabson (*db)->hdb_nextkey = LDAP_nextkey; 1886c19800e8SDoug Rabson (*db)->hdb_lock = LDAP_lock; 1887c19800e8SDoug Rabson (*db)->hdb_unlock = LDAP_unlock; 1888c19800e8SDoug Rabson (*db)->hdb_rename = NULL; 1889c19800e8SDoug Rabson (*db)->hdb__get = NULL; 1890c19800e8SDoug Rabson (*db)->hdb__put = NULL; 1891c19800e8SDoug Rabson (*db)->hdb__del = NULL; 1892c19800e8SDoug Rabson (*db)->hdb_destroy = LDAP_destroy; 18935e9cd1aeSAssar Westerlund 18945e9cd1aeSAssar Westerlund return 0; 18955e9cd1aeSAssar Westerlund } 18965e9cd1aeSAssar Westerlund 1897c19800e8SDoug Rabson krb5_error_code 1898c19800e8SDoug Rabson hdb_ldap_create(krb5_context context, HDB ** db, const char *arg) 1899c19800e8SDoug Rabson { 1900c19800e8SDoug Rabson return hdb_ldap_common(context, db, arg, "ldapi:///"); 1901c19800e8SDoug Rabson } 1902c19800e8SDoug Rabson 1903c19800e8SDoug Rabson krb5_error_code 1904c19800e8SDoug Rabson hdb_ldapi_create(krb5_context context, HDB ** db, const char *arg) 1905c19800e8SDoug Rabson { 1906c19800e8SDoug Rabson krb5_error_code ret; 1907c19800e8SDoug Rabson char *search_base, *p; 1908c19800e8SDoug Rabson 1909c19800e8SDoug Rabson asprintf(&p, "ldapi:%s", arg); 1910c19800e8SDoug Rabson if (p == NULL) { 1911c19800e8SDoug Rabson *db = NULL; 1912*ae771770SStanislav Sedov krb5_set_error_message(context, ENOMEM, "out of memory"); 1913c19800e8SDoug Rabson return ENOMEM; 1914c19800e8SDoug Rabson } 1915c19800e8SDoug Rabson search_base = strchr(p + strlen("ldapi://"), ':'); 1916c19800e8SDoug Rabson if (search_base == NULL) { 1917c19800e8SDoug Rabson *db = NULL; 1918*ae771770SStanislav Sedov krb5_set_error_message(context, HDB_ERR_BADVERSION, 1919*ae771770SStanislav Sedov "search base missing"); 1920c19800e8SDoug Rabson return HDB_ERR_BADVERSION; 1921c19800e8SDoug Rabson } 1922c19800e8SDoug Rabson *search_base = '\0'; 1923c19800e8SDoug Rabson search_base++; 1924c19800e8SDoug Rabson 1925c19800e8SDoug Rabson ret = hdb_ldap_common(context, db, search_base, p); 1926c19800e8SDoug Rabson free(p); 1927c19800e8SDoug Rabson return ret; 1928c19800e8SDoug Rabson } 1929c19800e8SDoug Rabson 1930c19800e8SDoug Rabson #ifdef OPENLDAP_MODULE 1931c19800e8SDoug Rabson 1932c19800e8SDoug Rabson struct hdb_so_method hdb_ldap_interface = { 1933c19800e8SDoug Rabson HDB_INTERFACE_VERSION, 1934c19800e8SDoug Rabson "ldap", 1935c19800e8SDoug Rabson hdb_ldap_create 1936c19800e8SDoug Rabson }; 1937c19800e8SDoug Rabson 1938c19800e8SDoug Rabson struct hdb_so_method hdb_ldapi_interface = { 1939c19800e8SDoug Rabson HDB_INTERFACE_VERSION, 1940c19800e8SDoug Rabson "ldapi", 1941c19800e8SDoug Rabson hdb_ldapi_create 1942c19800e8SDoug Rabson }; 1943c19800e8SDoug Rabson 1944c19800e8SDoug Rabson #endif 1945c19800e8SDoug Rabson 19465e9cd1aeSAssar Westerlund #endif /* OPENLDAP */ 1947