15e9cd1aeSAssar Westerlund /* 25e9cd1aeSAssar Westerlund * Copyright (c) 1999 - 2001, PADL Software Pty Ltd. 35e9cd1aeSAssar Westerlund * All rights reserved. 45e9cd1aeSAssar Westerlund * 55e9cd1aeSAssar Westerlund * Redistribution and use in source and binary forms, with or without 65e9cd1aeSAssar Westerlund * modification, are permitted provided that the following conditions 75e9cd1aeSAssar Westerlund * are met: 85e9cd1aeSAssar Westerlund * 95e9cd1aeSAssar Westerlund * 1. Redistributions of source code must retain the above copyright 105e9cd1aeSAssar Westerlund * notice, this list of conditions and the following disclaimer. 115e9cd1aeSAssar Westerlund * 125e9cd1aeSAssar Westerlund * 2. Redistributions in binary form must reproduce the above copyright 135e9cd1aeSAssar Westerlund * notice, this list of conditions and the following disclaimer in the 145e9cd1aeSAssar Westerlund * documentation and/or other materials provided with the distribution. 155e9cd1aeSAssar Westerlund * 165e9cd1aeSAssar Westerlund * 3. Neither the name of PADL Software nor the names of its contributors 175e9cd1aeSAssar Westerlund * may be used to endorse or promote products derived from this software 185e9cd1aeSAssar Westerlund * without specific prior written permission. 195e9cd1aeSAssar Westerlund * 205e9cd1aeSAssar Westerlund * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND 215e9cd1aeSAssar Westerlund * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 225e9cd1aeSAssar Westerlund * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 235e9cd1aeSAssar Westerlund * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE 245e9cd1aeSAssar Westerlund * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 255e9cd1aeSAssar Westerlund * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 265e9cd1aeSAssar Westerlund * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 275e9cd1aeSAssar Westerlund * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 285e9cd1aeSAssar Westerlund * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 295e9cd1aeSAssar Westerlund * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 305e9cd1aeSAssar Westerlund * SUCH DAMAGE. 315e9cd1aeSAssar Westerlund */ 325e9cd1aeSAssar Westerlund 335e9cd1aeSAssar Westerlund #include "hdb_locl.h" 345e9cd1aeSAssar Westerlund 355e9cd1aeSAssar Westerlund RCSID("$Id: hdb-ldap.c,v 1.7 2001/01/30 16:59:08 assar Exp $"); 365e9cd1aeSAssar Westerlund 375e9cd1aeSAssar Westerlund #ifdef OPENLDAP 385e9cd1aeSAssar Westerlund 395e9cd1aeSAssar Westerlund #include <ldap.h> 405e9cd1aeSAssar Westerlund #include <lber.h> 415e9cd1aeSAssar Westerlund #include <ctype.h> 425e9cd1aeSAssar Westerlund #include <sys/un.h> 435e9cd1aeSAssar Westerlund 445e9cd1aeSAssar Westerlund static krb5_error_code LDAP__connect(krb5_context context, HDB * db); 455e9cd1aeSAssar Westerlund 465e9cd1aeSAssar Westerlund static krb5_error_code 475e9cd1aeSAssar Westerlund LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg, 485e9cd1aeSAssar Westerlund hdb_entry * ent); 495e9cd1aeSAssar Westerlund 505e9cd1aeSAssar Westerlund static char *krb5kdcentry_attrs[] = 515e9cd1aeSAssar Westerlund { "krb5PrincipalName", "cn", "krb5PrincipalRealm", 525e9cd1aeSAssar Westerlund "krb5KeyVersionNumber", "krb5Key", 535e9cd1aeSAssar Westerlund "krb5ValidStart", "krb5ValidEnd", "krb5PasswordEnd", 545e9cd1aeSAssar Westerlund "krb5MaxLife", "krb5MaxRenew", "krb5KDCFlags", "krb5EncryptionType", 555e9cd1aeSAssar Westerlund "modifiersName", "modifyTimestamp", "creatorsName", "createTimestamp", 565e9cd1aeSAssar Westerlund NULL 575e9cd1aeSAssar Westerlund }; 585e9cd1aeSAssar Westerlund 595e9cd1aeSAssar Westerlund static char *krb5principal_attrs[] = 605e9cd1aeSAssar Westerlund { "krb5PrincipalName", "cn", "krb5PrincipalRealm", 615e9cd1aeSAssar Westerlund "modifiersName", "modifyTimestamp", "creatorsName", "createTimestamp", 625e9cd1aeSAssar Westerlund NULL 635e9cd1aeSAssar Westerlund }; 645e9cd1aeSAssar Westerlund 655e9cd1aeSAssar Westerlund /* based on samba: source/passdb/ldap.c */ 665e9cd1aeSAssar Westerlund static krb5_error_code 675e9cd1aeSAssar Westerlund LDAP_addmod_len(LDAPMod *** modlist, int modop, const char *attribute, 685e9cd1aeSAssar Westerlund unsigned char *value, size_t len) 695e9cd1aeSAssar Westerlund { 705e9cd1aeSAssar Westerlund LDAPMod **mods = *modlist; 715e9cd1aeSAssar Westerlund int i, j; 725e9cd1aeSAssar Westerlund 735e9cd1aeSAssar Westerlund if (mods == NULL) { 745e9cd1aeSAssar Westerlund mods = (LDAPMod **) calloc(1, sizeof(LDAPMod *)); 755e9cd1aeSAssar Westerlund if (mods == NULL) { 765e9cd1aeSAssar Westerlund return ENOMEM; 775e9cd1aeSAssar Westerlund } 785e9cd1aeSAssar Westerlund mods[0] = NULL; 795e9cd1aeSAssar Westerlund } 805e9cd1aeSAssar Westerlund 815e9cd1aeSAssar Westerlund for (i = 0; mods[i] != NULL; ++i) { 825e9cd1aeSAssar Westerlund if ((mods[i]->mod_op & (~LDAP_MOD_BVALUES)) == modop 835e9cd1aeSAssar Westerlund && (!strcasecmp(mods[i]->mod_type, attribute))) { 845e9cd1aeSAssar Westerlund break; 855e9cd1aeSAssar Westerlund } 865e9cd1aeSAssar Westerlund } 875e9cd1aeSAssar Westerlund 885e9cd1aeSAssar Westerlund if (mods[i] == NULL) { 895e9cd1aeSAssar Westerlund mods = (LDAPMod **) realloc(mods, (i + 2) * sizeof(LDAPMod *)); 905e9cd1aeSAssar Westerlund if (mods == NULL) { 915e9cd1aeSAssar Westerlund return ENOMEM; 925e9cd1aeSAssar Westerlund } 935e9cd1aeSAssar Westerlund mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod)); 945e9cd1aeSAssar Westerlund if (mods[i] == NULL) { 955e9cd1aeSAssar Westerlund return ENOMEM; 965e9cd1aeSAssar Westerlund } 975e9cd1aeSAssar Westerlund mods[i]->mod_op = modop | LDAP_MOD_BVALUES; 985e9cd1aeSAssar Westerlund mods[i]->mod_bvalues = NULL; 995e9cd1aeSAssar Westerlund mods[i]->mod_type = strdup(attribute); 1005e9cd1aeSAssar Westerlund if (mods[i]->mod_type == NULL) { 1015e9cd1aeSAssar Westerlund return ENOMEM; 1025e9cd1aeSAssar Westerlund } 1035e9cd1aeSAssar Westerlund mods[i + 1] = NULL; 1045e9cd1aeSAssar Westerlund } 1055e9cd1aeSAssar Westerlund 1065e9cd1aeSAssar Westerlund if (value != NULL) { 1075e9cd1aeSAssar Westerlund j = 0; 1085e9cd1aeSAssar Westerlund if (mods[i]->mod_bvalues != NULL) { 1095e9cd1aeSAssar Westerlund for (; mods[i]->mod_bvalues[j] != NULL; j++); 1105e9cd1aeSAssar Westerlund } 1115e9cd1aeSAssar Westerlund mods[i]->mod_bvalues = 1125e9cd1aeSAssar Westerlund (struct berval **) realloc(mods[i]->mod_bvalues, 1135e9cd1aeSAssar Westerlund (j + 2) * sizeof(struct berval *)); 1145e9cd1aeSAssar Westerlund if (mods[i]->mod_bvalues == NULL) { 1155e9cd1aeSAssar Westerlund return ENOMEM; 1165e9cd1aeSAssar Westerlund } 1175e9cd1aeSAssar Westerlund /* Caller allocates memory on our behalf, unlike LDAP_addmod. */ 1185e9cd1aeSAssar Westerlund mods[i]->mod_bvalues[j] = 1195e9cd1aeSAssar Westerlund (struct berval *) malloc(sizeof(struct berval)); 1205e9cd1aeSAssar Westerlund if (mods[i]->mod_bvalues[j] == NULL) { 1215e9cd1aeSAssar Westerlund return ENOMEM; 1225e9cd1aeSAssar Westerlund } 1235e9cd1aeSAssar Westerlund mods[i]->mod_bvalues[j]->bv_val = value; 1245e9cd1aeSAssar Westerlund mods[i]->mod_bvalues[j]->bv_len = len; 1255e9cd1aeSAssar Westerlund mods[i]->mod_bvalues[j + 1] = NULL; 1265e9cd1aeSAssar Westerlund } 1275e9cd1aeSAssar Westerlund *modlist = mods; 1285e9cd1aeSAssar Westerlund return 0; 1295e9cd1aeSAssar Westerlund } 1305e9cd1aeSAssar Westerlund 1315e9cd1aeSAssar Westerlund static krb5_error_code 1325e9cd1aeSAssar Westerlund LDAP_addmod(LDAPMod *** modlist, int modop, const char *attribute, 1335e9cd1aeSAssar Westerlund const char *value) 1345e9cd1aeSAssar Westerlund { 1355e9cd1aeSAssar Westerlund LDAPMod **mods = *modlist; 1365e9cd1aeSAssar Westerlund int i, j; 1375e9cd1aeSAssar Westerlund 1385e9cd1aeSAssar Westerlund if (mods == NULL) { 1395e9cd1aeSAssar Westerlund mods = (LDAPMod **) calloc(1, sizeof(LDAPMod *)); 1405e9cd1aeSAssar Westerlund if (mods == NULL) { 1415e9cd1aeSAssar Westerlund return ENOMEM; 1425e9cd1aeSAssar Westerlund } 1435e9cd1aeSAssar Westerlund mods[0] = NULL; 1445e9cd1aeSAssar Westerlund } 1455e9cd1aeSAssar Westerlund 1465e9cd1aeSAssar Westerlund for (i = 0; mods[i] != NULL; ++i) { 1475e9cd1aeSAssar Westerlund if (mods[i]->mod_op == modop 1485e9cd1aeSAssar Westerlund && (!strcasecmp(mods[i]->mod_type, attribute))) { 1495e9cd1aeSAssar Westerlund break; 1505e9cd1aeSAssar Westerlund } 1515e9cd1aeSAssar Westerlund } 1525e9cd1aeSAssar Westerlund 1535e9cd1aeSAssar Westerlund if (mods[i] == NULL) { 1545e9cd1aeSAssar Westerlund mods = (LDAPMod **) realloc(mods, (i + 2) * sizeof(LDAPMod *)); 1555e9cd1aeSAssar Westerlund if (mods == NULL) { 1565e9cd1aeSAssar Westerlund return ENOMEM; 1575e9cd1aeSAssar Westerlund } 1585e9cd1aeSAssar Westerlund mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod)); 1595e9cd1aeSAssar Westerlund if (mods[i] == NULL) { 1605e9cd1aeSAssar Westerlund return ENOMEM; 1615e9cd1aeSAssar Westerlund } 1625e9cd1aeSAssar Westerlund mods[i]->mod_op = modop; 1635e9cd1aeSAssar Westerlund mods[i]->mod_values = NULL; 1645e9cd1aeSAssar Westerlund mods[i]->mod_type = strdup(attribute); 1655e9cd1aeSAssar Westerlund if (mods[i]->mod_type == NULL) { 1665e9cd1aeSAssar Westerlund return ENOMEM; 1675e9cd1aeSAssar Westerlund } 1685e9cd1aeSAssar Westerlund mods[i + 1] = NULL; 1695e9cd1aeSAssar Westerlund } 1705e9cd1aeSAssar Westerlund 1715e9cd1aeSAssar Westerlund if (value != NULL) { 1725e9cd1aeSAssar Westerlund j = 0; 1735e9cd1aeSAssar Westerlund if (mods[i]->mod_values != NULL) { 1745e9cd1aeSAssar Westerlund for (; mods[i]->mod_values[j] != NULL; j++); 1755e9cd1aeSAssar Westerlund } 1765e9cd1aeSAssar Westerlund mods[i]->mod_values = (char **) realloc(mods[i]->mod_values, 1775e9cd1aeSAssar Westerlund (j + 2) * sizeof(char *)); 1785e9cd1aeSAssar Westerlund if (mods[i]->mod_values == NULL) { 1795e9cd1aeSAssar Westerlund return ENOMEM; 1805e9cd1aeSAssar Westerlund } 1815e9cd1aeSAssar Westerlund mods[i]->mod_values[j] = strdup(value); 1825e9cd1aeSAssar Westerlund if (mods[i]->mod_values[j] == NULL) { 1835e9cd1aeSAssar Westerlund return ENOMEM; 1845e9cd1aeSAssar Westerlund } 1855e9cd1aeSAssar Westerlund mods[i]->mod_values[j + 1] = NULL; 1865e9cd1aeSAssar Westerlund } 1875e9cd1aeSAssar Westerlund *modlist = mods; 1885e9cd1aeSAssar Westerlund return 0; 1895e9cd1aeSAssar Westerlund } 1905e9cd1aeSAssar Westerlund 1915e9cd1aeSAssar Westerlund static krb5_error_code 1925e9cd1aeSAssar Westerlund LDAP_addmod_generalized_time(LDAPMod *** mods, int modop, 1935e9cd1aeSAssar Westerlund const char *attribute, KerberosTime * time) 1945e9cd1aeSAssar Westerlund { 1955e9cd1aeSAssar Westerlund char buf[22]; 1965e9cd1aeSAssar Westerlund struct tm *tm; 1975e9cd1aeSAssar Westerlund 1985e9cd1aeSAssar Westerlund /* XXX not threadsafe */ 1995e9cd1aeSAssar Westerlund tm = gmtime(time); 2005e9cd1aeSAssar Westerlund strftime(buf, sizeof(buf), "%Y%m%d%H%M%SZ", tm); 2015e9cd1aeSAssar Westerlund 2025e9cd1aeSAssar Westerlund return LDAP_addmod(mods, modop, attribute, buf); 2035e9cd1aeSAssar Westerlund } 2045e9cd1aeSAssar Westerlund 2055e9cd1aeSAssar Westerlund static krb5_error_code 2065e9cd1aeSAssar Westerlund LDAP_get_string_value(HDB * db, LDAPMessage * entry, 2075e9cd1aeSAssar Westerlund const char *attribute, char **ptr) 2085e9cd1aeSAssar Westerlund { 2095e9cd1aeSAssar Westerlund char **vals; 2105e9cd1aeSAssar Westerlund int ret; 2115e9cd1aeSAssar Westerlund 2125e9cd1aeSAssar Westerlund vals = ldap_get_values((LDAP *) db->db, entry, (char *) attribute); 2135e9cd1aeSAssar Westerlund if (vals == NULL) { 2145e9cd1aeSAssar Westerlund return HDB_ERR_NOENTRY; 2155e9cd1aeSAssar Westerlund } 2165e9cd1aeSAssar Westerlund *ptr = strdup(vals[0]); 2175e9cd1aeSAssar Westerlund if (*ptr == NULL) { 2185e9cd1aeSAssar Westerlund ret = ENOMEM; 2195e9cd1aeSAssar Westerlund } else { 2205e9cd1aeSAssar Westerlund ret = 0; 2215e9cd1aeSAssar Westerlund } 2225e9cd1aeSAssar Westerlund 2235e9cd1aeSAssar Westerlund ldap_value_free(vals); 2245e9cd1aeSAssar Westerlund 2255e9cd1aeSAssar Westerlund return ret; 2265e9cd1aeSAssar Westerlund } 2275e9cd1aeSAssar Westerlund 2285e9cd1aeSAssar Westerlund static krb5_error_code 2295e9cd1aeSAssar Westerlund LDAP_get_integer_value(HDB * db, LDAPMessage * entry, 2305e9cd1aeSAssar Westerlund const char *attribute, int *ptr) 2315e9cd1aeSAssar Westerlund { 2325e9cd1aeSAssar Westerlund char **vals; 2335e9cd1aeSAssar Westerlund 2345e9cd1aeSAssar Westerlund vals = ldap_get_values((LDAP *) db->db, entry, (char *) attribute); 2355e9cd1aeSAssar Westerlund if (vals == NULL) { 2365e9cd1aeSAssar Westerlund return HDB_ERR_NOENTRY; 2375e9cd1aeSAssar Westerlund } 2385e9cd1aeSAssar Westerlund *ptr = atoi(vals[0]); 2395e9cd1aeSAssar Westerlund ldap_value_free(vals); 2405e9cd1aeSAssar Westerlund return 0; 2415e9cd1aeSAssar Westerlund } 2425e9cd1aeSAssar Westerlund 2435e9cd1aeSAssar Westerlund static krb5_error_code 2445e9cd1aeSAssar Westerlund LDAP_get_generalized_time_value(HDB * db, LDAPMessage * entry, 2455e9cd1aeSAssar Westerlund const char *attribute, KerberosTime * kt) 2465e9cd1aeSAssar Westerlund { 2475e9cd1aeSAssar Westerlund char *tmp, *gentime; 2485e9cd1aeSAssar Westerlund struct tm tm; 2495e9cd1aeSAssar Westerlund int ret; 2505e9cd1aeSAssar Westerlund 2515e9cd1aeSAssar Westerlund *kt = 0; 2525e9cd1aeSAssar Westerlund 2535e9cd1aeSAssar Westerlund ret = LDAP_get_string_value(db, entry, attribute, &gentime); 2545e9cd1aeSAssar Westerlund if (ret != 0) { 2555e9cd1aeSAssar Westerlund return ret; 2565e9cd1aeSAssar Westerlund } 2575e9cd1aeSAssar Westerlund 2585e9cd1aeSAssar Westerlund tmp = strptime(gentime, "%Y%m%d%H%M%SZ", &tm); 2595e9cd1aeSAssar Westerlund if (tmp == NULL) { 2605e9cd1aeSAssar Westerlund free(gentime); 2615e9cd1aeSAssar Westerlund return HDB_ERR_NOENTRY; 2625e9cd1aeSAssar Westerlund } 2635e9cd1aeSAssar Westerlund 2645e9cd1aeSAssar Westerlund free(gentime); 2655e9cd1aeSAssar Westerlund 2665e9cd1aeSAssar Westerlund *kt = timegm(&tm); 2675e9cd1aeSAssar Westerlund 2685e9cd1aeSAssar Westerlund return 0; 2695e9cd1aeSAssar Westerlund } 2705e9cd1aeSAssar Westerlund 2715e9cd1aeSAssar Westerlund static krb5_error_code 2725e9cd1aeSAssar Westerlund LDAP_entry2mods(krb5_context context, HDB * db, hdb_entry * ent, 2735e9cd1aeSAssar Westerlund LDAPMessage * msg, LDAPMod *** pmods) 2745e9cd1aeSAssar Westerlund { 2755e9cd1aeSAssar Westerlund krb5_error_code ret; 2765e9cd1aeSAssar Westerlund krb5_boolean is_new_entry; 2775e9cd1aeSAssar Westerlund int rc, i; 2785e9cd1aeSAssar Westerlund char *tmp = NULL; 2795e9cd1aeSAssar Westerlund LDAPMod **mods = NULL; 2805e9cd1aeSAssar Westerlund hdb_entry orig; 2815e9cd1aeSAssar Westerlund unsigned long oflags, nflags; 2825e9cd1aeSAssar Westerlund 2835e9cd1aeSAssar Westerlund if (msg != NULL) { 2845e9cd1aeSAssar Westerlund ret = LDAP_message2entry(context, db, msg, &orig); 2855e9cd1aeSAssar Westerlund if (ret != 0) { 2865e9cd1aeSAssar Westerlund goto out; 2875e9cd1aeSAssar Westerlund } 2885e9cd1aeSAssar Westerlund is_new_entry = FALSE; 2895e9cd1aeSAssar Westerlund } else { 2905e9cd1aeSAssar Westerlund /* to make it perfectly obvious we're depending on 2915e9cd1aeSAssar Westerlund * orig being intiialized to zero */ 2925e9cd1aeSAssar Westerlund memset(&orig, 0, sizeof(orig)); 2935e9cd1aeSAssar Westerlund is_new_entry = TRUE; 2945e9cd1aeSAssar Westerlund } 2955e9cd1aeSAssar Westerlund 2965e9cd1aeSAssar Westerlund if (is_new_entry) { 2975e9cd1aeSAssar Westerlund ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", "top"); 2985e9cd1aeSAssar Westerlund if (ret != 0) { 2995e9cd1aeSAssar Westerlund goto out; 3005e9cd1aeSAssar Westerlund } 3015e9cd1aeSAssar Westerlund /* person is the structural object class */ 3025e9cd1aeSAssar Westerlund ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", "person"); 3035e9cd1aeSAssar Westerlund if (ret != 0) { 3045e9cd1aeSAssar Westerlund goto out; 3055e9cd1aeSAssar Westerlund } 3065e9cd1aeSAssar Westerlund ret = 3075e9cd1aeSAssar Westerlund LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", 3085e9cd1aeSAssar Westerlund "krb5Principal"); 3095e9cd1aeSAssar Westerlund if (ret != 0) { 3105e9cd1aeSAssar Westerlund goto out; 3115e9cd1aeSAssar Westerlund } 3125e9cd1aeSAssar Westerlund ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "objectClass", 3135e9cd1aeSAssar Westerlund "krb5KDCEntry"); 3145e9cd1aeSAssar Westerlund if (ret != 0) { 3155e9cd1aeSAssar Westerlund goto out; 3165e9cd1aeSAssar Westerlund } 3175e9cd1aeSAssar Westerlund } 3185e9cd1aeSAssar Westerlund 3195e9cd1aeSAssar Westerlund if (is_new_entry || 3205e9cd1aeSAssar Westerlund krb5_principal_compare(context, ent->principal, orig.principal) == 3215e9cd1aeSAssar Westerlund FALSE) { 3225e9cd1aeSAssar Westerlund ret = krb5_unparse_name(context, ent->principal, &tmp); 3235e9cd1aeSAssar Westerlund if (ret != 0) { 3245e9cd1aeSAssar Westerlund goto out; 3255e9cd1aeSAssar Westerlund } 3265e9cd1aeSAssar Westerlund ret = 3275e9cd1aeSAssar Westerlund LDAP_addmod(&mods, LDAP_MOD_REPLACE, "krb5PrincipalName", tmp); 3285e9cd1aeSAssar Westerlund if (ret != 0) { 3295e9cd1aeSAssar Westerlund free(tmp); 3305e9cd1aeSAssar Westerlund goto out; 3315e9cd1aeSAssar Westerlund } 3325e9cd1aeSAssar Westerlund free(tmp); 3335e9cd1aeSAssar Westerlund } 3345e9cd1aeSAssar Westerlund 3355e9cd1aeSAssar Westerlund if (ent->kvno != orig.kvno) { 3365e9cd1aeSAssar Westerlund rc = asprintf(&tmp, "%d", ent->kvno); 3375e9cd1aeSAssar Westerlund if (rc < 0) { 3385e9cd1aeSAssar Westerlund ret = ENOMEM; 3395e9cd1aeSAssar Westerlund goto out; 3405e9cd1aeSAssar Westerlund } 3415e9cd1aeSAssar Westerlund ret = 3425e9cd1aeSAssar Westerlund LDAP_addmod(&mods, LDAP_MOD_REPLACE, "krb5KeyVersionNumber", 3435e9cd1aeSAssar Westerlund tmp); 3445e9cd1aeSAssar Westerlund free(tmp); 3455e9cd1aeSAssar Westerlund if (ret != 0) { 3465e9cd1aeSAssar Westerlund goto out; 3475e9cd1aeSAssar Westerlund } 3485e9cd1aeSAssar Westerlund } 3495e9cd1aeSAssar Westerlund 3505e9cd1aeSAssar Westerlund if (ent->valid_start) { 3515e9cd1aeSAssar Westerlund if (orig.valid_end == NULL 3525e9cd1aeSAssar Westerlund || (*(ent->valid_start) != *(orig.valid_start))) { 3535e9cd1aeSAssar Westerlund ret = 3545e9cd1aeSAssar Westerlund LDAP_addmod_generalized_time(&mods, LDAP_MOD_REPLACE, 3555e9cd1aeSAssar Westerlund "krb5ValidStart", 3565e9cd1aeSAssar Westerlund ent->valid_start); 3575e9cd1aeSAssar Westerlund if (ret != 0) { 3585e9cd1aeSAssar Westerlund goto out; 3595e9cd1aeSAssar Westerlund } 3605e9cd1aeSAssar Westerlund } 3615e9cd1aeSAssar Westerlund } 3625e9cd1aeSAssar Westerlund 3635e9cd1aeSAssar Westerlund if (ent->valid_end) { 3645e9cd1aeSAssar Westerlund if (orig.valid_end == NULL 3655e9cd1aeSAssar Westerlund || (*(ent->valid_end) != *(orig.valid_end))) { 3665e9cd1aeSAssar Westerlund ret = 3675e9cd1aeSAssar Westerlund LDAP_addmod_generalized_time(&mods, LDAP_MOD_REPLACE, 3685e9cd1aeSAssar Westerlund "krb5ValidEnd", 3695e9cd1aeSAssar Westerlund ent->valid_end); 3705e9cd1aeSAssar Westerlund if (ret != 0) { 3715e9cd1aeSAssar Westerlund goto out; 3725e9cd1aeSAssar Westerlund } 3735e9cd1aeSAssar Westerlund } 3745e9cd1aeSAssar Westerlund } 3755e9cd1aeSAssar Westerlund 3765e9cd1aeSAssar Westerlund if (ent->pw_end) { 3775e9cd1aeSAssar Westerlund if (orig.pw_end == NULL || (*(ent->pw_end) != *(orig.pw_end))) { 3785e9cd1aeSAssar Westerlund ret = 3795e9cd1aeSAssar Westerlund LDAP_addmod_generalized_time(&mods, LDAP_MOD_REPLACE, 3805e9cd1aeSAssar Westerlund "krb5PasswordEnd", 3815e9cd1aeSAssar Westerlund ent->pw_end); 3825e9cd1aeSAssar Westerlund if (ret != 0) { 3835e9cd1aeSAssar Westerlund goto out; 3845e9cd1aeSAssar Westerlund } 3855e9cd1aeSAssar Westerlund } 3865e9cd1aeSAssar Westerlund } 3875e9cd1aeSAssar Westerlund 3885e9cd1aeSAssar Westerlund if (ent->max_life) { 3895e9cd1aeSAssar Westerlund if (orig.max_life == NULL 3905e9cd1aeSAssar Westerlund || (*(ent->max_life) != *(orig.max_life))) { 3915e9cd1aeSAssar Westerlund rc = asprintf(&tmp, "%d", *(ent->max_life)); 3925e9cd1aeSAssar Westerlund if (rc < 0) { 3935e9cd1aeSAssar Westerlund ret = ENOMEM; 3945e9cd1aeSAssar Westerlund goto out; 3955e9cd1aeSAssar Westerlund } 3965e9cd1aeSAssar Westerlund ret = LDAP_addmod(&mods, LDAP_MOD_REPLACE, "krb5MaxLife", tmp); 3975e9cd1aeSAssar Westerlund free(tmp); 3985e9cd1aeSAssar Westerlund if (ret != 0) { 3995e9cd1aeSAssar Westerlund goto out; 4005e9cd1aeSAssar Westerlund } 4015e9cd1aeSAssar Westerlund } 4025e9cd1aeSAssar Westerlund } 4035e9cd1aeSAssar Westerlund 4045e9cd1aeSAssar Westerlund if (ent->max_renew) { 4055e9cd1aeSAssar Westerlund if (orig.max_renew == NULL 4065e9cd1aeSAssar Westerlund || (*(ent->max_renew) != *(orig.max_renew))) { 4075e9cd1aeSAssar Westerlund rc = asprintf(&tmp, "%d", *(ent->max_renew)); 4085e9cd1aeSAssar Westerlund if (rc < 0) { 4095e9cd1aeSAssar Westerlund ret = ENOMEM; 4105e9cd1aeSAssar Westerlund goto out; 4115e9cd1aeSAssar Westerlund } 4125e9cd1aeSAssar Westerlund ret = 4135e9cd1aeSAssar Westerlund LDAP_addmod(&mods, LDAP_MOD_REPLACE, "krb5MaxRenew", tmp); 4145e9cd1aeSAssar Westerlund free(tmp); 4155e9cd1aeSAssar Westerlund if (ret != 0) { 4165e9cd1aeSAssar Westerlund goto out; 4175e9cd1aeSAssar Westerlund } 4185e9cd1aeSAssar Westerlund } 4195e9cd1aeSAssar Westerlund } 4205e9cd1aeSAssar Westerlund 4215e9cd1aeSAssar Westerlund memset(&oflags, 0, sizeof(oflags)); 4225e9cd1aeSAssar Westerlund memcpy(&oflags, &orig.flags, sizeof(HDBFlags)); 4235e9cd1aeSAssar Westerlund memset(&nflags, 0, sizeof(nflags)); 4245e9cd1aeSAssar Westerlund memcpy(&nflags, &ent->flags, sizeof(HDBFlags)); 4255e9cd1aeSAssar Westerlund 4265e9cd1aeSAssar Westerlund if (memcmp(&oflags, &nflags, sizeof(HDBFlags))) { 4275e9cd1aeSAssar Westerlund rc = asprintf(&tmp, "%lu", nflags); 4285e9cd1aeSAssar Westerlund if (rc < 0) { 4295e9cd1aeSAssar Westerlund ret = ENOMEM; 4305e9cd1aeSAssar Westerlund goto out; 4315e9cd1aeSAssar Westerlund } 4325e9cd1aeSAssar Westerlund ret = LDAP_addmod(&mods, LDAP_MOD_REPLACE, "krb5KDCFlags", tmp); 4335e9cd1aeSAssar Westerlund free(tmp); 4345e9cd1aeSAssar Westerlund if (ret != 0) { 4355e9cd1aeSAssar Westerlund goto out; 4365e9cd1aeSAssar Westerlund } 4375e9cd1aeSAssar Westerlund } 4385e9cd1aeSAssar Westerlund 4395e9cd1aeSAssar Westerlund if (is_new_entry == FALSE && orig.keys.len > 0) { 4405e9cd1aeSAssar Westerlund /* for the moment, clobber and replace keys. */ 4415e9cd1aeSAssar Westerlund ret = LDAP_addmod(&mods, LDAP_MOD_DELETE, "krb5Key", NULL); 4425e9cd1aeSAssar Westerlund if (ret != 0) { 4435e9cd1aeSAssar Westerlund goto out; 4445e9cd1aeSAssar Westerlund } 4455e9cd1aeSAssar Westerlund } 4465e9cd1aeSAssar Westerlund 4475e9cd1aeSAssar Westerlund for (i = 0; i < ent->keys.len; i++) { 4485e9cd1aeSAssar Westerlund unsigned char *buf; 4495e9cd1aeSAssar Westerlund size_t len; 4505e9cd1aeSAssar Westerlund Key new; 4515e9cd1aeSAssar Westerlund 4525e9cd1aeSAssar Westerlund ret = copy_Key(&ent->keys.val[i], &new); 4535e9cd1aeSAssar Westerlund if (ret != 0) { 4545e9cd1aeSAssar Westerlund goto out; 4555e9cd1aeSAssar Westerlund } 4565e9cd1aeSAssar Westerlund 4575e9cd1aeSAssar Westerlund len = length_Key(&new); 4585e9cd1aeSAssar Westerlund buf = malloc(len); 4595e9cd1aeSAssar Westerlund if (buf == NULL) { 4605e9cd1aeSAssar Westerlund ret = ENOMEM; 4615e9cd1aeSAssar Westerlund free_Key(&new); 4625e9cd1aeSAssar Westerlund goto out; 4635e9cd1aeSAssar Westerlund } 4645e9cd1aeSAssar Westerlund 4655e9cd1aeSAssar Westerlund ret = encode_Key(buf + len - 1, len, &new, &len); 4665e9cd1aeSAssar Westerlund if (ret != 0) { 4675e9cd1aeSAssar Westerlund free(buf); 4685e9cd1aeSAssar Westerlund free_Key(&new); 4695e9cd1aeSAssar Westerlund goto out; 4705e9cd1aeSAssar Westerlund } 4715e9cd1aeSAssar Westerlund free_Key(&new); 4725e9cd1aeSAssar Westerlund 4735e9cd1aeSAssar Westerlund /* addmod_len _owns_ the key, doesn't need to copy it */ 4745e9cd1aeSAssar Westerlund ret = LDAP_addmod_len(&mods, LDAP_MOD_ADD, "krb5Key", buf, len); 4755e9cd1aeSAssar Westerlund if (ret != 0) { 4765e9cd1aeSAssar Westerlund goto out; 4775e9cd1aeSAssar Westerlund } 4785e9cd1aeSAssar Westerlund } 4795e9cd1aeSAssar Westerlund 4805e9cd1aeSAssar Westerlund if (ent->etypes) { 4815e9cd1aeSAssar Westerlund /* clobber and replace encryption types. */ 4825e9cd1aeSAssar Westerlund if (is_new_entry == FALSE) { 4835e9cd1aeSAssar Westerlund ret = 4845e9cd1aeSAssar Westerlund LDAP_addmod(&mods, LDAP_MOD_DELETE, "krb5EncryptionType", 4855e9cd1aeSAssar Westerlund NULL); 4865e9cd1aeSAssar Westerlund } 4875e9cd1aeSAssar Westerlund for (i = 0; i < ent->etypes->len; i++) { 4885e9cd1aeSAssar Westerlund rc = asprintf(&tmp, "%d", ent->etypes->val[i]); 4895e9cd1aeSAssar Westerlund if (rc < 0) { 4905e9cd1aeSAssar Westerlund ret = ENOMEM; 4915e9cd1aeSAssar Westerlund goto out; 4925e9cd1aeSAssar Westerlund } 4935e9cd1aeSAssar Westerlund free(tmp); 4945e9cd1aeSAssar Westerlund ret = 4955e9cd1aeSAssar Westerlund LDAP_addmod(&mods, LDAP_MOD_ADD, "krb5EncryptionType", 4965e9cd1aeSAssar Westerlund tmp); 4975e9cd1aeSAssar Westerlund if (ret != 0) { 4985e9cd1aeSAssar Westerlund goto out; 4995e9cd1aeSAssar Westerlund } 5005e9cd1aeSAssar Westerlund } 5015e9cd1aeSAssar Westerlund } 5025e9cd1aeSAssar Westerlund 5035e9cd1aeSAssar Westerlund /* for clarity */ 5045e9cd1aeSAssar Westerlund ret = 0; 5055e9cd1aeSAssar Westerlund 5065e9cd1aeSAssar Westerlund out: 5075e9cd1aeSAssar Westerlund 5085e9cd1aeSAssar Westerlund if (ret == 0) { 5095e9cd1aeSAssar Westerlund *pmods = mods; 5105e9cd1aeSAssar Westerlund } else if (mods != NULL) { 5115e9cd1aeSAssar Westerlund ldap_mods_free(mods, 1); 5125e9cd1aeSAssar Westerlund *pmods = NULL; 5135e9cd1aeSAssar Westerlund } 5145e9cd1aeSAssar Westerlund 5155e9cd1aeSAssar Westerlund if (msg != NULL) { 5165e9cd1aeSAssar Westerlund hdb_free_entry(context, &orig); 5175e9cd1aeSAssar Westerlund } 5185e9cd1aeSAssar Westerlund 5195e9cd1aeSAssar Westerlund return ret; 5205e9cd1aeSAssar Westerlund } 5215e9cd1aeSAssar Westerlund 5225e9cd1aeSAssar Westerlund static krb5_error_code 5235e9cd1aeSAssar Westerlund LDAP_dn2principal(krb5_context context, HDB * db, const char *dn, 5245e9cd1aeSAssar Westerlund krb5_principal * principal) 5255e9cd1aeSAssar Westerlund { 5265e9cd1aeSAssar Westerlund krb5_error_code ret; 5275e9cd1aeSAssar Westerlund int rc; 5285e9cd1aeSAssar Westerlund char **values; 5295e9cd1aeSAssar Westerlund LDAPMessage *res = NULL, *e; 5305e9cd1aeSAssar Westerlund 5315e9cd1aeSAssar Westerlund rc = 1; 5325e9cd1aeSAssar Westerlund (void) ldap_set_option((LDAP *) db->db, LDAP_OPT_SIZELIMIT, &rc); 5335e9cd1aeSAssar Westerlund rc = ldap_search_s((LDAP *) db->db, db->name, LDAP_SCOPE_BASE, 5345e9cd1aeSAssar Westerlund "(objectclass=krb5Principal)", krb5principal_attrs, 5355e9cd1aeSAssar Westerlund 0, &res); 5365e9cd1aeSAssar Westerlund 5375e9cd1aeSAssar Westerlund if (rc != LDAP_SUCCESS) { 5385e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 5395e9cd1aeSAssar Westerlund goto out; 5405e9cd1aeSAssar Westerlund } 5415e9cd1aeSAssar Westerlund 5425e9cd1aeSAssar Westerlund e = ldap_first_entry((LDAP *) db->db, res); 5435e9cd1aeSAssar Westerlund if (e == NULL) { 5445e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 5455e9cd1aeSAssar Westerlund goto out; 5465e9cd1aeSAssar Westerlund } 5475e9cd1aeSAssar Westerlund 5485e9cd1aeSAssar Westerlund values = ldap_get_values((LDAP *) db->db, e, "krb5PrincipalName"); 5495e9cd1aeSAssar Westerlund if (values == NULL) { 5505e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 5515e9cd1aeSAssar Westerlund goto out; 5525e9cd1aeSAssar Westerlund } 5535e9cd1aeSAssar Westerlund 5545e9cd1aeSAssar Westerlund ret = krb5_parse_name(context, values[0], principal); 5555e9cd1aeSAssar Westerlund ldap_value_free(values); 5565e9cd1aeSAssar Westerlund 5575e9cd1aeSAssar Westerlund out: 5585e9cd1aeSAssar Westerlund if (res != NULL) { 5595e9cd1aeSAssar Westerlund ldap_msgfree(res); 5605e9cd1aeSAssar Westerlund } 5615e9cd1aeSAssar Westerlund return ret; 5625e9cd1aeSAssar Westerlund } 5635e9cd1aeSAssar Westerlund 5645e9cd1aeSAssar Westerlund static krb5_error_code 5655e9cd1aeSAssar Westerlund LDAP__lookup_princ(krb5_context context, HDB * db, const char *princname, 5665e9cd1aeSAssar Westerlund LDAPMessage ** msg) 5675e9cd1aeSAssar Westerlund { 5685e9cd1aeSAssar Westerlund krb5_error_code ret; 5695e9cd1aeSAssar Westerlund int rc; 5705e9cd1aeSAssar Westerlund char *filter = NULL; 5715e9cd1aeSAssar Westerlund 5725e9cd1aeSAssar Westerlund (void) LDAP__connect(context, db); 5735e9cd1aeSAssar Westerlund 5745e9cd1aeSAssar Westerlund rc = 5755e9cd1aeSAssar Westerlund asprintf(&filter, 5765e9cd1aeSAssar Westerlund "(&(objectclass=krb5KDCEntry)(krb5PrincipalName=%s))", 5775e9cd1aeSAssar Westerlund princname); 5785e9cd1aeSAssar Westerlund if (rc < 0) { 5795e9cd1aeSAssar Westerlund ret = ENOMEM; 5805e9cd1aeSAssar Westerlund goto out; 5815e9cd1aeSAssar Westerlund } 5825e9cd1aeSAssar Westerlund 5835e9cd1aeSAssar Westerlund rc = 1; 5845e9cd1aeSAssar Westerlund (void) ldap_set_option((LDAP *) db->db, LDAP_OPT_SIZELIMIT, (void *) &rc); 5855e9cd1aeSAssar Westerlund 5865e9cd1aeSAssar Westerlund rc = ldap_search_s((LDAP *) db->db, db->name, LDAP_SCOPE_ONELEVEL, filter, 5875e9cd1aeSAssar Westerlund krb5kdcentry_attrs, 0, msg); 5885e9cd1aeSAssar Westerlund if (rc != LDAP_SUCCESS) { 5895e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 5905e9cd1aeSAssar Westerlund goto out; 5915e9cd1aeSAssar Westerlund } 5925e9cd1aeSAssar Westerlund 5935e9cd1aeSAssar Westerlund ret = 0; 5945e9cd1aeSAssar Westerlund 5955e9cd1aeSAssar Westerlund out: 5965e9cd1aeSAssar Westerlund if (filter != NULL) { 5975e9cd1aeSAssar Westerlund free(filter); 5985e9cd1aeSAssar Westerlund } 5995e9cd1aeSAssar Westerlund return ret; 6005e9cd1aeSAssar Westerlund } 6015e9cd1aeSAssar Westerlund 6025e9cd1aeSAssar Westerlund static krb5_error_code 6035e9cd1aeSAssar Westerlund LDAP_principal2message(krb5_context context, HDB * db, 6045e9cd1aeSAssar Westerlund krb5_principal princ, LDAPMessage ** msg) 6055e9cd1aeSAssar Westerlund { 6065e9cd1aeSAssar Westerlund char *princname = NULL; 6075e9cd1aeSAssar Westerlund krb5_error_code ret; 6085e9cd1aeSAssar Westerlund 6095e9cd1aeSAssar Westerlund ret = krb5_unparse_name(context, princ, &princname); 6105e9cd1aeSAssar Westerlund if (ret != 0) { 6115e9cd1aeSAssar Westerlund return ret; 6125e9cd1aeSAssar Westerlund } 6135e9cd1aeSAssar Westerlund 6145e9cd1aeSAssar Westerlund ret = LDAP__lookup_princ(context, db, princname, msg); 6155e9cd1aeSAssar Westerlund free(princname); 6165e9cd1aeSAssar Westerlund 6175e9cd1aeSAssar Westerlund return ret; 6185e9cd1aeSAssar Westerlund } 6195e9cd1aeSAssar Westerlund 6205e9cd1aeSAssar Westerlund /* 6215e9cd1aeSAssar Westerlund * Construct an hdb_entry from a directory entry. 6225e9cd1aeSAssar Westerlund */ 6235e9cd1aeSAssar Westerlund static krb5_error_code 6245e9cd1aeSAssar Westerlund LDAP_message2entry(krb5_context context, HDB * db, LDAPMessage * msg, 6255e9cd1aeSAssar Westerlund hdb_entry * ent) 6265e9cd1aeSAssar Westerlund { 6275e9cd1aeSAssar Westerlund char *unparsed_name = NULL, *dn = NULL; 6285e9cd1aeSAssar Westerlund int ret; 6295e9cd1aeSAssar Westerlund unsigned long tmp; 6305e9cd1aeSAssar Westerlund struct berval **keys; 6315e9cd1aeSAssar Westerlund char **values; 6325e9cd1aeSAssar Westerlund 6335e9cd1aeSAssar Westerlund memset(ent, 0, sizeof(*ent)); 6345e9cd1aeSAssar Westerlund memset(&ent->flags, 0, sizeof(HDBFlags)); 6355e9cd1aeSAssar Westerlund 6365e9cd1aeSAssar Westerlund ret = 6375e9cd1aeSAssar Westerlund LDAP_get_string_value(db, msg, "krb5PrincipalName", 6385e9cd1aeSAssar Westerlund &unparsed_name); 6395e9cd1aeSAssar Westerlund if (ret != 0) { 6405e9cd1aeSAssar Westerlund return ret; 6415e9cd1aeSAssar Westerlund } 6425e9cd1aeSAssar Westerlund 6435e9cd1aeSAssar Westerlund ret = krb5_parse_name(context, unparsed_name, &ent->principal); 6445e9cd1aeSAssar Westerlund if (ret != 0) { 6455e9cd1aeSAssar Westerlund goto out; 6465e9cd1aeSAssar Westerlund } 6475e9cd1aeSAssar Westerlund 6485e9cd1aeSAssar Westerlund ret = 6495e9cd1aeSAssar Westerlund LDAP_get_integer_value(db, msg, "krb5KeyVersionNumber", 6505e9cd1aeSAssar Westerlund &ent->kvno); 6515e9cd1aeSAssar Westerlund if (ret != 0) { 6525e9cd1aeSAssar Westerlund ent->kvno = 0; 6535e9cd1aeSAssar Westerlund } 6545e9cd1aeSAssar Westerlund 6555e9cd1aeSAssar Westerlund keys = ldap_get_values_len((LDAP *) db->db, msg, "krb5Key"); 6565e9cd1aeSAssar Westerlund if (keys != NULL) { 6575e9cd1aeSAssar Westerlund int i; 6585e9cd1aeSAssar Westerlund size_t l; 6595e9cd1aeSAssar Westerlund 6605e9cd1aeSAssar Westerlund ent->keys.len = ldap_count_values_len(keys); 6615e9cd1aeSAssar Westerlund ent->keys.val = (Key *) calloc(ent->keys.len, sizeof(Key)); 6625e9cd1aeSAssar Westerlund for (i = 0; i < ent->keys.len; i++) { 6635e9cd1aeSAssar Westerlund decode_Key((unsigned char *) keys[i]->bv_val, 6645e9cd1aeSAssar Westerlund (size_t) keys[i]->bv_len, &ent->keys.val[i], &l); 6655e9cd1aeSAssar Westerlund } 6665e9cd1aeSAssar Westerlund ber_bvecfree(keys); 6675e9cd1aeSAssar Westerlund } else { 6685e9cd1aeSAssar Westerlund #if 1 6695e9cd1aeSAssar Westerlund /* 6705e9cd1aeSAssar Westerlund * This violates the ASN1 but it allows a principal to 6715e9cd1aeSAssar Westerlund * be related to a general directory entry without creating 6725e9cd1aeSAssar Westerlund * the keys. Hopefully it's OK. 6735e9cd1aeSAssar Westerlund */ 6745e9cd1aeSAssar Westerlund ent->keys.len = 0; 6755e9cd1aeSAssar Westerlund ent->keys.val = NULL; 6765e9cd1aeSAssar Westerlund #else 6775e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 6785e9cd1aeSAssar Westerlund goto out; 6795e9cd1aeSAssar Westerlund #endif 6805e9cd1aeSAssar Westerlund } 6815e9cd1aeSAssar Westerlund 6825e9cd1aeSAssar Westerlund ret = 6835e9cd1aeSAssar Westerlund LDAP_get_generalized_time_value(db, msg, "createTimestamp", 6845e9cd1aeSAssar Westerlund &ent->created_by.time); 6855e9cd1aeSAssar Westerlund if (ret != 0) { 6865e9cd1aeSAssar Westerlund ent->created_by.time = time(NULL); 6875e9cd1aeSAssar Westerlund } 6885e9cd1aeSAssar Westerlund 6895e9cd1aeSAssar Westerlund ent->created_by.principal = NULL; 6905e9cd1aeSAssar Westerlund 6915e9cd1aeSAssar Westerlund ret = LDAP_get_string_value(db, msg, "creatorsName", &dn); 6925e9cd1aeSAssar Westerlund if (ret == 0) { 6935e9cd1aeSAssar Westerlund if (LDAP_dn2principal(context, db, dn, &ent->created_by.principal) 6945e9cd1aeSAssar Westerlund != 0) { 6955e9cd1aeSAssar Westerlund ent->created_by.principal = NULL; 6965e9cd1aeSAssar Westerlund } 6975e9cd1aeSAssar Westerlund free(dn); 6985e9cd1aeSAssar Westerlund } 6995e9cd1aeSAssar Westerlund 7005e9cd1aeSAssar Westerlund ent->modified_by = (Event *) malloc(sizeof(Event)); 7015e9cd1aeSAssar Westerlund if (ent->modified_by == NULL) { 7025e9cd1aeSAssar Westerlund ret = ENOMEM; 7035e9cd1aeSAssar Westerlund goto out; 7045e9cd1aeSAssar Westerlund } 7055e9cd1aeSAssar Westerlund ret = 7065e9cd1aeSAssar Westerlund LDAP_get_generalized_time_value(db, msg, "modifyTimestamp", 7075e9cd1aeSAssar Westerlund &ent->modified_by->time); 7085e9cd1aeSAssar Westerlund if (ret == 0) { 7095e9cd1aeSAssar Westerlund ret = LDAP_get_string_value(db, msg, "modifiersName", &dn); 7105e9cd1aeSAssar Westerlund if (LDAP_dn2principal 7115e9cd1aeSAssar Westerlund (context, db, dn, &ent->modified_by->principal) != 0) { 7125e9cd1aeSAssar Westerlund ent->modified_by->principal = NULL; 7135e9cd1aeSAssar Westerlund } 7145e9cd1aeSAssar Westerlund free(dn); 7155e9cd1aeSAssar Westerlund } else { 7165e9cd1aeSAssar Westerlund free(ent->modified_by); 7175e9cd1aeSAssar Westerlund ent->modified_by = NULL; 7185e9cd1aeSAssar Westerlund } 7195e9cd1aeSAssar Westerlund 7205e9cd1aeSAssar Westerlund if ((ent->valid_start = (KerberosTime *) malloc(sizeof(KerberosTime))) 7215e9cd1aeSAssar Westerlund == NULL) { 7225e9cd1aeSAssar Westerlund ret = ENOMEM; 7235e9cd1aeSAssar Westerlund goto out; 7245e9cd1aeSAssar Westerlund } 7255e9cd1aeSAssar Westerlund ret = 7265e9cd1aeSAssar Westerlund LDAP_get_generalized_time_value(db, msg, "krb5ValidStart", 7275e9cd1aeSAssar Westerlund ent->valid_start); 7285e9cd1aeSAssar Westerlund if (ret != 0) { 7295e9cd1aeSAssar Westerlund /* OPTIONAL */ 7305e9cd1aeSAssar Westerlund free(ent->valid_start); 7315e9cd1aeSAssar Westerlund ent->valid_start = NULL; 7325e9cd1aeSAssar Westerlund } 7335e9cd1aeSAssar Westerlund 7345e9cd1aeSAssar Westerlund if ((ent->valid_end = (KerberosTime *) malloc(sizeof(KerberosTime))) == 7355e9cd1aeSAssar Westerlund NULL) {ret = ENOMEM; 7365e9cd1aeSAssar Westerlund goto out; 7375e9cd1aeSAssar Westerlund } 7385e9cd1aeSAssar Westerlund ret = 7395e9cd1aeSAssar Westerlund LDAP_get_generalized_time_value(db, msg, "krb5ValidEnd", 7405e9cd1aeSAssar Westerlund ent->valid_end); 7415e9cd1aeSAssar Westerlund if (ret != 0) { 7425e9cd1aeSAssar Westerlund /* OPTIONAL */ 7435e9cd1aeSAssar Westerlund free(ent->valid_end); 7445e9cd1aeSAssar Westerlund ent->valid_end = NULL; 7455e9cd1aeSAssar Westerlund } 7465e9cd1aeSAssar Westerlund 7475e9cd1aeSAssar Westerlund if ((ent->pw_end = (KerberosTime *) malloc(sizeof(KerberosTime))) == 7485e9cd1aeSAssar Westerlund NULL) {ret = ENOMEM; 7495e9cd1aeSAssar Westerlund goto out; 7505e9cd1aeSAssar Westerlund } 7515e9cd1aeSAssar Westerlund ret = 7525e9cd1aeSAssar Westerlund LDAP_get_generalized_time_value(db, msg, "krb5PasswordEnd", 7535e9cd1aeSAssar Westerlund ent->pw_end); 7545e9cd1aeSAssar Westerlund if (ret != 0) { 7555e9cd1aeSAssar Westerlund /* OPTIONAL */ 7565e9cd1aeSAssar Westerlund free(ent->pw_end); 7575e9cd1aeSAssar Westerlund ent->pw_end = NULL; 7585e9cd1aeSAssar Westerlund } 7595e9cd1aeSAssar Westerlund 7605e9cd1aeSAssar Westerlund ent->max_life = (int *) malloc(sizeof(int)); 7615e9cd1aeSAssar Westerlund if (ent->max_life == NULL) { 7625e9cd1aeSAssar Westerlund ret = ENOMEM; 7635e9cd1aeSAssar Westerlund goto out; 7645e9cd1aeSAssar Westerlund } 7655e9cd1aeSAssar Westerlund ret = LDAP_get_integer_value(db, msg, "krb5MaxLife", ent->max_life); 7665e9cd1aeSAssar Westerlund if (ret != 0) { 7675e9cd1aeSAssar Westerlund free(ent->max_life); 7685e9cd1aeSAssar Westerlund ent->max_life = NULL; 7695e9cd1aeSAssar Westerlund } 7705e9cd1aeSAssar Westerlund 7715e9cd1aeSAssar Westerlund ent->max_renew = (int *) malloc(sizeof(int)); 7725e9cd1aeSAssar Westerlund if (ent->max_renew == NULL) { 7735e9cd1aeSAssar Westerlund ret = ENOMEM; 7745e9cd1aeSAssar Westerlund goto out; 7755e9cd1aeSAssar Westerlund } 7765e9cd1aeSAssar Westerlund ret = LDAP_get_integer_value(db, msg, "krb5MaxRenew", ent->max_renew); 7775e9cd1aeSAssar Westerlund if (ret != 0) { 7785e9cd1aeSAssar Westerlund free(ent->max_renew); 7795e9cd1aeSAssar Westerlund ent->max_renew = NULL; 7805e9cd1aeSAssar Westerlund } 7815e9cd1aeSAssar Westerlund 7825e9cd1aeSAssar Westerlund values = ldap_get_values((LDAP *) db->db, msg, "krb5KDCFlags"); 7835e9cd1aeSAssar Westerlund if (values != NULL) { 7845e9cd1aeSAssar Westerlund tmp = strtoul(values[0], (char **) NULL, 10); 7855e9cd1aeSAssar Westerlund if (tmp == ULONG_MAX && errno == ERANGE) { 7865e9cd1aeSAssar Westerlund ret = ERANGE; 7875e9cd1aeSAssar Westerlund goto out; 7885e9cd1aeSAssar Westerlund } 7895e9cd1aeSAssar Westerlund } else { 7905e9cd1aeSAssar Westerlund tmp = 0; 7915e9cd1aeSAssar Westerlund } 7925e9cd1aeSAssar Westerlund memcpy(&ent->flags, &tmp, sizeof(HDBFlags)); 7935e9cd1aeSAssar Westerlund 7945e9cd1aeSAssar Westerlund values = ldap_get_values((LDAP *) db->db, msg, "krb5EncryptionType"); 7955e9cd1aeSAssar Westerlund if (values != NULL) { 7965e9cd1aeSAssar Westerlund int i; 7975e9cd1aeSAssar Westerlund 7985e9cd1aeSAssar Westerlund ent->etypes = malloc(sizeof(*(ent->etypes))); 7995e9cd1aeSAssar Westerlund if (ent->etypes == NULL) { 8005e9cd1aeSAssar Westerlund ret = ENOMEM; 8015e9cd1aeSAssar Westerlund goto out; 8025e9cd1aeSAssar Westerlund } 8035e9cd1aeSAssar Westerlund ent->etypes->len = ldap_count_values(values); 8045e9cd1aeSAssar Westerlund ent->etypes->val = calloc(ent->etypes->len, sizeof(int)); 8055e9cd1aeSAssar Westerlund for (i = 0; i < ent->etypes->len; i++) { 8065e9cd1aeSAssar Westerlund ent->etypes->val[i] = atoi(values[i]); 8075e9cd1aeSAssar Westerlund } 8085e9cd1aeSAssar Westerlund ldap_value_free(values); 8095e9cd1aeSAssar Westerlund } 8105e9cd1aeSAssar Westerlund 8115e9cd1aeSAssar Westerlund ret = 0; 8125e9cd1aeSAssar Westerlund 8135e9cd1aeSAssar Westerlund out: 8145e9cd1aeSAssar Westerlund if (unparsed_name != NULL) { 8155e9cd1aeSAssar Westerlund free(unparsed_name); 8165e9cd1aeSAssar Westerlund } 8175e9cd1aeSAssar Westerlund 8185e9cd1aeSAssar Westerlund if (ret != 0) { 8195e9cd1aeSAssar Westerlund /* I don't think this frees ent itself. */ 8205e9cd1aeSAssar Westerlund hdb_free_entry(context, ent); 8215e9cd1aeSAssar Westerlund } 8225e9cd1aeSAssar Westerlund 8235e9cd1aeSAssar Westerlund return ret; 8245e9cd1aeSAssar Westerlund } 8255e9cd1aeSAssar Westerlund 8265e9cd1aeSAssar Westerlund static krb5_error_code LDAP_close(krb5_context context, HDB * db) 8275e9cd1aeSAssar Westerlund { 8285e9cd1aeSAssar Westerlund LDAP *ld = (LDAP *) db->db; 8295e9cd1aeSAssar Westerlund 8305e9cd1aeSAssar Westerlund ldap_unbind(ld); 8315e9cd1aeSAssar Westerlund db->db = NULL; 8325e9cd1aeSAssar Westerlund return 0; 8335e9cd1aeSAssar Westerlund } 8345e9cd1aeSAssar Westerlund 8355e9cd1aeSAssar Westerlund static krb5_error_code 8365e9cd1aeSAssar Westerlund LDAP_lock(krb5_context context, HDB * db, int operation) 8375e9cd1aeSAssar Westerlund { 8385e9cd1aeSAssar Westerlund return 0; 8395e9cd1aeSAssar Westerlund } 8405e9cd1aeSAssar Westerlund 8415e9cd1aeSAssar Westerlund static krb5_error_code LDAP_unlock(krb5_context context, HDB * db) 8425e9cd1aeSAssar Westerlund { 8435e9cd1aeSAssar Westerlund return 0; 8445e9cd1aeSAssar Westerlund } 8455e9cd1aeSAssar Westerlund 8465e9cd1aeSAssar Westerlund static krb5_error_code 8475e9cd1aeSAssar Westerlund LDAP_seq(krb5_context context, HDB * db, unsigned flags, hdb_entry * entry) 8485e9cd1aeSAssar Westerlund { 8495e9cd1aeSAssar Westerlund int msgid, rc, parserc; 8505e9cd1aeSAssar Westerlund krb5_error_code ret; 8515e9cd1aeSAssar Westerlund LDAPMessage *e; 8525e9cd1aeSAssar Westerlund 8535e9cd1aeSAssar Westerlund msgid = db->openp; /* BOGUS OVERLOADING */ 8545e9cd1aeSAssar Westerlund if (msgid < 0) { 8555e9cd1aeSAssar Westerlund return HDB_ERR_NOENTRY; 8565e9cd1aeSAssar Westerlund } 8575e9cd1aeSAssar Westerlund 8585e9cd1aeSAssar Westerlund do { 8595e9cd1aeSAssar Westerlund rc = ldap_result((LDAP *) db->db, msgid, LDAP_MSG_ONE, NULL, &e); 8605e9cd1aeSAssar Westerlund switch (rc) { 8615e9cd1aeSAssar Westerlund case LDAP_RES_SEARCH_ENTRY: 8625e9cd1aeSAssar Westerlund /* We have an entry. Parse it. */ 8635e9cd1aeSAssar Westerlund ret = LDAP_message2entry(context, db, e, entry); 8645e9cd1aeSAssar Westerlund ldap_msgfree(e); 8655e9cd1aeSAssar Westerlund break; 8665e9cd1aeSAssar Westerlund case LDAP_RES_SEARCH_RESULT: 8675e9cd1aeSAssar Westerlund /* We're probably at the end of the results. If not, abandon. */ 8685e9cd1aeSAssar Westerlund parserc = 8695e9cd1aeSAssar Westerlund ldap_parse_result((LDAP *) db->db, e, NULL, NULL, NULL, 8705e9cd1aeSAssar Westerlund NULL, NULL, 1); 8715e9cd1aeSAssar Westerlund if (parserc != LDAP_SUCCESS 8725e9cd1aeSAssar Westerlund && parserc != LDAP_MORE_RESULTS_TO_RETURN) { 8735e9cd1aeSAssar Westerlund ldap_abandon((LDAP *) db->db, msgid); 8745e9cd1aeSAssar Westerlund } 8755e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 8765e9cd1aeSAssar Westerlund db->openp = -1; 8775e9cd1aeSAssar Westerlund break; 8785e9cd1aeSAssar Westerlund case 0: 8795e9cd1aeSAssar Westerlund case -1: 8805e9cd1aeSAssar Westerlund default: 8815e9cd1aeSAssar Westerlund /* Some unspecified error (timeout?). Abandon. */ 8825e9cd1aeSAssar Westerlund ldap_msgfree(e); 8835e9cd1aeSAssar Westerlund ldap_abandon((LDAP *) db->db, msgid); 8845e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 8855e9cd1aeSAssar Westerlund db->openp = -1; 8865e9cd1aeSAssar Westerlund break; 8875e9cd1aeSAssar Westerlund } 8885e9cd1aeSAssar Westerlund } while (rc == LDAP_RES_SEARCH_REFERENCE); 8895e9cd1aeSAssar Westerlund 8905e9cd1aeSAssar Westerlund if (ret == 0) { 8915e9cd1aeSAssar Westerlund if (db->master_key_set && (flags & HDB_F_DECRYPT)) { 8925e9cd1aeSAssar Westerlund ret = hdb_unseal_keys(context, db, entry); 8935e9cd1aeSAssar Westerlund if (ret) 8945e9cd1aeSAssar Westerlund hdb_free_entry(context,entry); 8955e9cd1aeSAssar Westerlund } 8965e9cd1aeSAssar Westerlund } 8975e9cd1aeSAssar Westerlund 8985e9cd1aeSAssar Westerlund return ret; 8995e9cd1aeSAssar Westerlund } 9005e9cd1aeSAssar Westerlund 9015e9cd1aeSAssar Westerlund static krb5_error_code 9025e9cd1aeSAssar Westerlund LDAP_firstkey(krb5_context context, HDB * db, unsigned flags, 9035e9cd1aeSAssar Westerlund hdb_entry * entry) 9045e9cd1aeSAssar Westerlund { 9055e9cd1aeSAssar Westerlund int msgid; 9065e9cd1aeSAssar Westerlund 9075e9cd1aeSAssar Westerlund (void) LDAP__connect(context, db); 9085e9cd1aeSAssar Westerlund 9095e9cd1aeSAssar Westerlund msgid = LDAP_NO_LIMIT; 9105e9cd1aeSAssar Westerlund (void) ldap_set_option((LDAP *) db->db, LDAP_OPT_SIZELIMIT, &msgid); 9115e9cd1aeSAssar Westerlund 9125e9cd1aeSAssar Westerlund msgid = ldap_search((LDAP *) db->db, db->name, 9135e9cd1aeSAssar Westerlund LDAP_SCOPE_ONELEVEL, "(objectclass=krb5KDCEntry)", 9145e9cd1aeSAssar Westerlund krb5kdcentry_attrs, 0); 9155e9cd1aeSAssar Westerlund if (msgid < 0) { 9165e9cd1aeSAssar Westerlund return HDB_ERR_NOENTRY; 9175e9cd1aeSAssar Westerlund } 9185e9cd1aeSAssar Westerlund 9195e9cd1aeSAssar Westerlund db->openp = msgid; 9205e9cd1aeSAssar Westerlund 9215e9cd1aeSAssar Westerlund return LDAP_seq(context, db, flags, entry); 9225e9cd1aeSAssar Westerlund } 9235e9cd1aeSAssar Westerlund 9245e9cd1aeSAssar Westerlund static krb5_error_code 9255e9cd1aeSAssar Westerlund LDAP_nextkey(krb5_context context, HDB * db, unsigned flags, 9265e9cd1aeSAssar Westerlund hdb_entry * entry) 9275e9cd1aeSAssar Westerlund { 9285e9cd1aeSAssar Westerlund return LDAP_seq(context, db, flags, entry); 9295e9cd1aeSAssar Westerlund } 9305e9cd1aeSAssar Westerlund 9315e9cd1aeSAssar Westerlund static krb5_error_code 9325e9cd1aeSAssar Westerlund LDAP_rename(krb5_context context, HDB * db, const char *new_name) 9335e9cd1aeSAssar Westerlund { 9345e9cd1aeSAssar Westerlund return HDB_ERR_DB_INUSE; 9355e9cd1aeSAssar Westerlund } 9365e9cd1aeSAssar Westerlund 9375e9cd1aeSAssar Westerlund static krb5_boolean LDAP__is_user_namingcontext(const char *ctx, 9385e9cd1aeSAssar Westerlund char *const *subschema) 9395e9cd1aeSAssar Westerlund { 9405e9cd1aeSAssar Westerlund char *const *p; 9415e9cd1aeSAssar Westerlund 9425e9cd1aeSAssar Westerlund if (!strcasecmp(ctx, "CN=MONITOR") 9435e9cd1aeSAssar Westerlund || !strcasecmp(ctx, "CN=CONFIG")) { 9445e9cd1aeSAssar Westerlund return FALSE; 9455e9cd1aeSAssar Westerlund } 9465e9cd1aeSAssar Westerlund 9475e9cd1aeSAssar Westerlund if (subschema != NULL) { 9485e9cd1aeSAssar Westerlund for (p = subschema; *p != NULL; p++) { 9495e9cd1aeSAssar Westerlund if (!strcasecmp(ctx, *p)) { 9505e9cd1aeSAssar Westerlund return FALSE; 9515e9cd1aeSAssar Westerlund } 9525e9cd1aeSAssar Westerlund } 9535e9cd1aeSAssar Westerlund } 9545e9cd1aeSAssar Westerlund 9555e9cd1aeSAssar Westerlund return TRUE; 9565e9cd1aeSAssar Westerlund } 9575e9cd1aeSAssar Westerlund 9585e9cd1aeSAssar Westerlund static krb5_error_code LDAP__connect(krb5_context context, HDB * db) 9595e9cd1aeSAssar Westerlund { 9605e9cd1aeSAssar Westerlund int rc; 9615e9cd1aeSAssar Westerlund krb5_error_code ret; 9625e9cd1aeSAssar Westerlund char *attrs[] = { "namingContexts", "subschemaSubentry", NULL }; 9635e9cd1aeSAssar Westerlund LDAPMessage *res = NULL, *e; 9645e9cd1aeSAssar Westerlund 9655e9cd1aeSAssar Westerlund if (db->db != NULL) { 9665e9cd1aeSAssar Westerlund /* connection has been opened. ping server. */ 9675e9cd1aeSAssar Westerlund struct sockaddr_un addr; 9685e9cd1aeSAssar Westerlund socklen_t len; 9695e9cd1aeSAssar Westerlund int sd; 9705e9cd1aeSAssar Westerlund 9715e9cd1aeSAssar Westerlund if (ldap_get_option((LDAP *) db->db, LDAP_OPT_DESC, &sd) == 0 && 9725e9cd1aeSAssar Westerlund getpeername(sd, (struct sockaddr *) &addr, &len) < 0) { 9735e9cd1aeSAssar Westerlund /* the other end has died. reopen. */ 9745e9cd1aeSAssar Westerlund LDAP_close(context, db); 9755e9cd1aeSAssar Westerlund } 9765e9cd1aeSAssar Westerlund } 9775e9cd1aeSAssar Westerlund 9785e9cd1aeSAssar Westerlund if (db->db != NULL) { 9795e9cd1aeSAssar Westerlund /* server is UP */ 9805e9cd1aeSAssar Westerlund return 0; 9815e9cd1aeSAssar Westerlund } 9825e9cd1aeSAssar Westerlund 9835e9cd1aeSAssar Westerlund rc = ldap_initialize((LDAP **) & db->db, "ldapi:///"); 9845e9cd1aeSAssar Westerlund if (rc != LDAP_SUCCESS) { 9855e9cd1aeSAssar Westerlund return HDB_ERR_NOENTRY; 9865e9cd1aeSAssar Westerlund } 9875e9cd1aeSAssar Westerlund 9885e9cd1aeSAssar Westerlund rc = LDAP_VERSION3; 9895e9cd1aeSAssar Westerlund (void) ldap_set_option((LDAP *) db->db, LDAP_OPT_PROTOCOL_VERSION, &rc); 9905e9cd1aeSAssar Westerlund 9915e9cd1aeSAssar Westerlund /* XXX set db->name to the search base */ 9925e9cd1aeSAssar Westerlund rc = ldap_search_s((LDAP *) db->db, "", LDAP_SCOPE_BASE, 9935e9cd1aeSAssar Westerlund "(objectclass=*)", attrs, 0, &res); 9945e9cd1aeSAssar Westerlund if (rc != LDAP_SUCCESS) { 9955e9cd1aeSAssar Westerlund ret = HDB_ERR_BADVERSION; 9965e9cd1aeSAssar Westerlund goto out; 9975e9cd1aeSAssar Westerlund } 9985e9cd1aeSAssar Westerlund 9995e9cd1aeSAssar Westerlund e = ldap_first_entry((LDAP *) db->db, res); 10005e9cd1aeSAssar Westerlund if (e == NULL) { 10015e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 10025e9cd1aeSAssar Westerlund goto out; 10035e9cd1aeSAssar Westerlund } 10045e9cd1aeSAssar Westerlund 10055e9cd1aeSAssar Westerlund if (db->name == NULL) { 10065e9cd1aeSAssar Westerlund char **contexts = NULL, **schema_contexts, **p; 10075e9cd1aeSAssar Westerlund 10085e9cd1aeSAssar Westerlund contexts = ldap_get_values((LDAP *) db->db, e, "namingContexts"); 10095e9cd1aeSAssar Westerlund if (contexts == NULL) { 10105e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 10115e9cd1aeSAssar Westerlund goto out; 10125e9cd1aeSAssar Westerlund } 10135e9cd1aeSAssar Westerlund 10145e9cd1aeSAssar Westerlund schema_contexts = 10155e9cd1aeSAssar Westerlund ldap_get_values((LDAP *) db->db, e, "subschemaSubentry"); 10165e9cd1aeSAssar Westerlund 10175e9cd1aeSAssar Westerlund if (db->name != NULL) { 10185e9cd1aeSAssar Westerlund free(db->name); 10195e9cd1aeSAssar Westerlund db->name = NULL; 10205e9cd1aeSAssar Westerlund } 10215e9cd1aeSAssar Westerlund 10225e9cd1aeSAssar Westerlund for (p = contexts; *p != NULL; p++) { 10235e9cd1aeSAssar Westerlund if (LDAP__is_user_namingcontext(*p, schema_contexts)) { 10245e9cd1aeSAssar Westerlund break; 10255e9cd1aeSAssar Westerlund } 10265e9cd1aeSAssar Westerlund } 10275e9cd1aeSAssar Westerlund 10285e9cd1aeSAssar Westerlund db->name = strdup(*p); 10295e9cd1aeSAssar Westerlund if (db->name == NULL) { 10305e9cd1aeSAssar Westerlund ldap_value_free(contexts); 10315e9cd1aeSAssar Westerlund ret = ENOMEM; 10325e9cd1aeSAssar Westerlund goto out; 10335e9cd1aeSAssar Westerlund } 10345e9cd1aeSAssar Westerlund 10355e9cd1aeSAssar Westerlund ldap_value_free(contexts); 10365e9cd1aeSAssar Westerlund if (schema_contexts != NULL) { 10375e9cd1aeSAssar Westerlund ldap_value_free(schema_contexts); 10385e9cd1aeSAssar Westerlund } 10395e9cd1aeSAssar Westerlund } 10405e9cd1aeSAssar Westerlund 10415e9cd1aeSAssar Westerlund ret = 0; 10425e9cd1aeSAssar Westerlund 10435e9cd1aeSAssar Westerlund out: 10445e9cd1aeSAssar Westerlund 10455e9cd1aeSAssar Westerlund if (res != NULL) { 10465e9cd1aeSAssar Westerlund ldap_msgfree(res); 10475e9cd1aeSAssar Westerlund } 10485e9cd1aeSAssar Westerlund 10495e9cd1aeSAssar Westerlund if (ret != 0) { 10505e9cd1aeSAssar Westerlund if (db->db != NULL) { 10515e9cd1aeSAssar Westerlund ldap_unbind((LDAP *) db->db); 10525e9cd1aeSAssar Westerlund db->db = NULL; 10535e9cd1aeSAssar Westerlund } 10545e9cd1aeSAssar Westerlund } 10555e9cd1aeSAssar Westerlund 10565e9cd1aeSAssar Westerlund return ret; 10575e9cd1aeSAssar Westerlund } 10585e9cd1aeSAssar Westerlund 10595e9cd1aeSAssar Westerlund static krb5_error_code 10605e9cd1aeSAssar Westerlund LDAP_open(krb5_context context, HDB * db, int flags, mode_t mode) 10615e9cd1aeSAssar Westerlund { 10625e9cd1aeSAssar Westerlund krb5_error_code ret; 10635e9cd1aeSAssar Westerlund 10645e9cd1aeSAssar Westerlund /* Not the right place for this. */ 10655e9cd1aeSAssar Westerlund #ifdef HAVE_SIGACTION 10665e9cd1aeSAssar Westerlund { 10675e9cd1aeSAssar Westerlund struct sigaction sa; 10685e9cd1aeSAssar Westerlund 10695e9cd1aeSAssar Westerlund sa.sa_flags = 0; 10705e9cd1aeSAssar Westerlund sa.sa_handler = SIG_IGN; 10715e9cd1aeSAssar Westerlund sigemptyset(&sa.sa_mask); 10725e9cd1aeSAssar Westerlund 10735e9cd1aeSAssar Westerlund sigaction(SIGPIPE, &sa, NULL); 10745e9cd1aeSAssar Westerlund } 10755e9cd1aeSAssar Westerlund #else 10765e9cd1aeSAssar Westerlund signal(SIGPIPE, SIG_IGN); 10775e9cd1aeSAssar Westerlund #endif 10785e9cd1aeSAssar Westerlund 10795e9cd1aeSAssar Westerlund if (db->name != NULL) { 10805e9cd1aeSAssar Westerlund free(db->name); 10815e9cd1aeSAssar Westerlund db->name = NULL; 10825e9cd1aeSAssar Westerlund } 10835e9cd1aeSAssar Westerlund 10845e9cd1aeSAssar Westerlund ret = LDAP__connect(context, db); 10855e9cd1aeSAssar Westerlund if (ret != 0) { 10865e9cd1aeSAssar Westerlund return ret; 10875e9cd1aeSAssar Westerlund } 10885e9cd1aeSAssar Westerlund 10895e9cd1aeSAssar Westerlund return ret; 10905e9cd1aeSAssar Westerlund } 10915e9cd1aeSAssar Westerlund 10925e9cd1aeSAssar Westerlund static krb5_error_code 10935e9cd1aeSAssar Westerlund LDAP_fetch(krb5_context context, HDB * db, unsigned flags, 10945e9cd1aeSAssar Westerlund hdb_entry * entry) 10955e9cd1aeSAssar Westerlund { 10965e9cd1aeSAssar Westerlund LDAPMessage *msg, *e; 10975e9cd1aeSAssar Westerlund krb5_error_code ret; 10985e9cd1aeSAssar Westerlund 10995e9cd1aeSAssar Westerlund ret = LDAP_principal2message(context, db, entry->principal, &msg); 11005e9cd1aeSAssar Westerlund if (ret != 0) { 11015e9cd1aeSAssar Westerlund return ret; 11025e9cd1aeSAssar Westerlund } 11035e9cd1aeSAssar Westerlund 11045e9cd1aeSAssar Westerlund e = ldap_first_entry((LDAP *) db->db, msg); 11055e9cd1aeSAssar Westerlund if (e == NULL) { 11065e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 11075e9cd1aeSAssar Westerlund goto out; 11085e9cd1aeSAssar Westerlund } 11095e9cd1aeSAssar Westerlund 11105e9cd1aeSAssar Westerlund ret = LDAP_message2entry(context, db, e, entry); 11115e9cd1aeSAssar Westerlund if (ret == 0) { 11125e9cd1aeSAssar Westerlund if (db->master_key_set && (flags & HDB_F_DECRYPT)) { 11135e9cd1aeSAssar Westerlund ret = hdb_unseal_keys(context, db, entry); 11145e9cd1aeSAssar Westerlund if (ret) 11155e9cd1aeSAssar Westerlund hdb_free_entry(context,entry); 11165e9cd1aeSAssar Westerlund } 11175e9cd1aeSAssar Westerlund } 11185e9cd1aeSAssar Westerlund 11195e9cd1aeSAssar Westerlund out: 11205e9cd1aeSAssar Westerlund ldap_msgfree(msg); 11215e9cd1aeSAssar Westerlund 11225e9cd1aeSAssar Westerlund return ret; 11235e9cd1aeSAssar Westerlund } 11245e9cd1aeSAssar Westerlund 11255e9cd1aeSAssar Westerlund static krb5_error_code 11265e9cd1aeSAssar Westerlund LDAP_store(krb5_context context, HDB * db, unsigned flags, 11275e9cd1aeSAssar Westerlund hdb_entry * entry) 11285e9cd1aeSAssar Westerlund { 11295e9cd1aeSAssar Westerlund LDAPMod **mods = NULL; 11305e9cd1aeSAssar Westerlund krb5_error_code ret; 11315e9cd1aeSAssar Westerlund LDAPMessage *msg = NULL, *e = NULL; 11325e9cd1aeSAssar Westerlund char *dn = NULL, *name = NULL; 11335e9cd1aeSAssar Westerlund 11345e9cd1aeSAssar Westerlund ret = krb5_unparse_name(context, entry->principal, &name); 11355e9cd1aeSAssar Westerlund if (ret != 0) { 11365e9cd1aeSAssar Westerlund goto out; 11375e9cd1aeSAssar Westerlund } 11385e9cd1aeSAssar Westerlund 11395e9cd1aeSAssar Westerlund ret = LDAP__lookup_princ(context, db, name, &msg); 11405e9cd1aeSAssar Westerlund if (ret == 0) { 11415e9cd1aeSAssar Westerlund e = ldap_first_entry((LDAP *) db->db, msg); 11425e9cd1aeSAssar Westerlund } 11435e9cd1aeSAssar Westerlund 11445e9cd1aeSAssar Westerlund ret = hdb_seal_keys(context, db, entry); 11455e9cd1aeSAssar Westerlund if (ret) 11465e9cd1aeSAssar Westerlund goto out; 11475e9cd1aeSAssar Westerlund 11485e9cd1aeSAssar Westerlund /* turn new entry into LDAPMod array */ 11495e9cd1aeSAssar Westerlund ret = LDAP_entry2mods(context, db, entry, e, &mods); 11505e9cd1aeSAssar Westerlund if (ret != 0) { 11515e9cd1aeSAssar Westerlund goto out; 11525e9cd1aeSAssar Westerlund } 11535e9cd1aeSAssar Westerlund 11545e9cd1aeSAssar Westerlund if (e == NULL) { 11555e9cd1aeSAssar Westerlund /* Doesn't exist yet. */ 11565e9cd1aeSAssar Westerlund char *p; 11575e9cd1aeSAssar Westerlund 11585e9cd1aeSAssar Westerlund e = NULL; 11595e9cd1aeSAssar Westerlund 11605e9cd1aeSAssar Westerlund /* normalize the naming attribute */ 11615e9cd1aeSAssar Westerlund for (p = name; *p != '\0'; p++) { 11625e9cd1aeSAssar Westerlund *p = (char) tolower((int) *p); 11635e9cd1aeSAssar Westerlund } 11645e9cd1aeSAssar Westerlund 11655e9cd1aeSAssar Westerlund /* 11665e9cd1aeSAssar Westerlund * We could do getpwnam() on the local component of 11675e9cd1aeSAssar Westerlund * the principal to find cn/sn but that's probably 11685e9cd1aeSAssar Westerlund * bad thing to do from inside a KDC. Better leave 11695e9cd1aeSAssar Westerlund * it to management tools. 11705e9cd1aeSAssar Westerlund */ 11715e9cd1aeSAssar Westerlund ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "cn", name); 11725e9cd1aeSAssar Westerlund if (ret < 0) { 11735e9cd1aeSAssar Westerlund goto out; 11745e9cd1aeSAssar Westerlund } 11755e9cd1aeSAssar Westerlund 11765e9cd1aeSAssar Westerlund ret = LDAP_addmod(&mods, LDAP_MOD_ADD, "sn", name); 11775e9cd1aeSAssar Westerlund if (ret < 0) { 11785e9cd1aeSAssar Westerlund goto out; 11795e9cd1aeSAssar Westerlund } 11805e9cd1aeSAssar Westerlund 11815e9cd1aeSAssar Westerlund ret = asprintf(&dn, "cn=%s,%s", name, db->name); 11825e9cd1aeSAssar Westerlund if (ret < 0) { 11835e9cd1aeSAssar Westerlund ret = ENOMEM; 11845e9cd1aeSAssar Westerlund goto out; 11855e9cd1aeSAssar Westerlund } 11865e9cd1aeSAssar Westerlund } else if (flags & HDB_F_REPLACE) { 11875e9cd1aeSAssar Westerlund /* Entry exists, and we're allowed to replace it. */ 11885e9cd1aeSAssar Westerlund dn = ldap_get_dn((LDAP *) db->db, e); 11895e9cd1aeSAssar Westerlund } else { 11905e9cd1aeSAssar Westerlund /* Entry exists, but we're not allowed to replace it. Bail. */ 11915e9cd1aeSAssar Westerlund ret = HDB_ERR_EXISTS; 11925e9cd1aeSAssar Westerlund goto out; 11935e9cd1aeSAssar Westerlund } 11945e9cd1aeSAssar Westerlund 11955e9cd1aeSAssar Westerlund /* write entry into directory */ 11965e9cd1aeSAssar Westerlund if (e == NULL) { 11975e9cd1aeSAssar Westerlund /* didn't exist before */ 11985e9cd1aeSAssar Westerlund ret = ldap_add_s((LDAP *) db->db, dn, mods); 11995e9cd1aeSAssar Westerlund } else { 12005e9cd1aeSAssar Westerlund /* already existed, send deltas only */ 12015e9cd1aeSAssar Westerlund ret = ldap_modify_s((LDAP *) db->db, dn, mods); 12025e9cd1aeSAssar Westerlund } 12035e9cd1aeSAssar Westerlund 12045e9cd1aeSAssar Westerlund if (ret == LDAP_SUCCESS) { 12055e9cd1aeSAssar Westerlund ret = 0; 12065e9cd1aeSAssar Westerlund } else { 12075e9cd1aeSAssar Westerlund ret = HDB_ERR_CANT_LOCK_DB; 12085e9cd1aeSAssar Westerlund } 12095e9cd1aeSAssar Westerlund 12105e9cd1aeSAssar Westerlund out: 12115e9cd1aeSAssar Westerlund /* free stuff */ 12125e9cd1aeSAssar Westerlund if (dn != NULL) { 12135e9cd1aeSAssar Westerlund free(dn); 12145e9cd1aeSAssar Westerlund } 12155e9cd1aeSAssar Westerlund 12165e9cd1aeSAssar Westerlund if (msg != NULL) { 12175e9cd1aeSAssar Westerlund ldap_msgfree(msg); 12185e9cd1aeSAssar Westerlund } 12195e9cd1aeSAssar Westerlund 12205e9cd1aeSAssar Westerlund if (mods != NULL) { 12215e9cd1aeSAssar Westerlund ldap_mods_free(mods, 1); 12225e9cd1aeSAssar Westerlund } 12235e9cd1aeSAssar Westerlund 12245e9cd1aeSAssar Westerlund if (name != NULL) { 12255e9cd1aeSAssar Westerlund free(name); 12265e9cd1aeSAssar Westerlund } 12275e9cd1aeSAssar Westerlund 12285e9cd1aeSAssar Westerlund return ret; 12295e9cd1aeSAssar Westerlund } 12305e9cd1aeSAssar Westerlund 12315e9cd1aeSAssar Westerlund static krb5_error_code 12325e9cd1aeSAssar Westerlund LDAP_remove(krb5_context context, HDB * db, hdb_entry * entry) 12335e9cd1aeSAssar Westerlund { 12345e9cd1aeSAssar Westerlund krb5_error_code ret; 12355e9cd1aeSAssar Westerlund LDAPMessage *msg, *e; 12365e9cd1aeSAssar Westerlund char *dn = NULL; 12375e9cd1aeSAssar Westerlund 12385e9cd1aeSAssar Westerlund ret = LDAP_principal2message(context, db, entry->principal, &msg); 12395e9cd1aeSAssar Westerlund if (ret != 0) { 12405e9cd1aeSAssar Westerlund goto out; 12415e9cd1aeSAssar Westerlund } 12425e9cd1aeSAssar Westerlund 12435e9cd1aeSAssar Westerlund e = ldap_first_entry((LDAP *) db->db, msg); 12445e9cd1aeSAssar Westerlund if (e == NULL) { 12455e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 12465e9cd1aeSAssar Westerlund goto out; 12475e9cd1aeSAssar Westerlund } 12485e9cd1aeSAssar Westerlund 12495e9cd1aeSAssar Westerlund dn = ldap_get_dn((LDAP *) db->db, e); 12505e9cd1aeSAssar Westerlund if (dn == NULL) { 12515e9cd1aeSAssar Westerlund ret = HDB_ERR_NOENTRY; 12525e9cd1aeSAssar Westerlund goto out; 12535e9cd1aeSAssar Westerlund } 12545e9cd1aeSAssar Westerlund 12555e9cd1aeSAssar Westerlund ret = LDAP_NO_LIMIT; 12565e9cd1aeSAssar Westerlund (void) ldap_set_option((LDAP *) db->db, LDAP_OPT_SIZELIMIT, &ret); 12575e9cd1aeSAssar Westerlund 12585e9cd1aeSAssar Westerlund ret = ldap_delete_s((LDAP *) db->db, dn); 12595e9cd1aeSAssar Westerlund if (ret == LDAP_SUCCESS) { 12605e9cd1aeSAssar Westerlund ret = 0; 12615e9cd1aeSAssar Westerlund } else { 12625e9cd1aeSAssar Westerlund ret = HDB_ERR_CANT_LOCK_DB; 12635e9cd1aeSAssar Westerlund } 12645e9cd1aeSAssar Westerlund 12655e9cd1aeSAssar Westerlund out: 12665e9cd1aeSAssar Westerlund if (dn != NULL) { 12675e9cd1aeSAssar Westerlund free(dn); 12685e9cd1aeSAssar Westerlund } 12695e9cd1aeSAssar Westerlund 12705e9cd1aeSAssar Westerlund if (msg != NULL) { 12715e9cd1aeSAssar Westerlund ldap_msgfree(msg); 12725e9cd1aeSAssar Westerlund } 12735e9cd1aeSAssar Westerlund 12745e9cd1aeSAssar Westerlund return ret; 12755e9cd1aeSAssar Westerlund } 12765e9cd1aeSAssar Westerlund 12775e9cd1aeSAssar Westerlund static krb5_error_code 12785e9cd1aeSAssar Westerlund LDAP__get(krb5_context context, HDB * db, krb5_data key, krb5_data * reply) 12795e9cd1aeSAssar Westerlund { 12805e9cd1aeSAssar Westerlund fprintf(stderr, "LDAP__get not implemented\n"); 12815e9cd1aeSAssar Westerlund abort(); 12825e9cd1aeSAssar Westerlund return 0; 12835e9cd1aeSAssar Westerlund } 12845e9cd1aeSAssar Westerlund 12855e9cd1aeSAssar Westerlund static krb5_error_code 12865e9cd1aeSAssar Westerlund LDAP__put(krb5_context context, HDB * db, int replace, 12875e9cd1aeSAssar Westerlund krb5_data key, krb5_data value) 12885e9cd1aeSAssar Westerlund { 12895e9cd1aeSAssar Westerlund fprintf(stderr, "LDAP__put not implemented\n"); 12905e9cd1aeSAssar Westerlund abort(); 12915e9cd1aeSAssar Westerlund return 0; 12925e9cd1aeSAssar Westerlund } 12935e9cd1aeSAssar Westerlund 12945e9cd1aeSAssar Westerlund static krb5_error_code 12955e9cd1aeSAssar Westerlund LDAP__del(krb5_context context, HDB * db, krb5_data key) 12965e9cd1aeSAssar Westerlund { 12975e9cd1aeSAssar Westerlund fprintf(stderr, "LDAP__del not implemented\n"); 12985e9cd1aeSAssar Westerlund abort(); 12995e9cd1aeSAssar Westerlund return 0; 13005e9cd1aeSAssar Westerlund } 13015e9cd1aeSAssar Westerlund 13025e9cd1aeSAssar Westerlund static krb5_error_code LDAP_destroy(krb5_context context, HDB * db) 13035e9cd1aeSAssar Westerlund { 13045e9cd1aeSAssar Westerlund krb5_error_code ret; 13055e9cd1aeSAssar Westerlund 13065e9cd1aeSAssar Westerlund ret = hdb_clear_master_key(context, db); 13075e9cd1aeSAssar Westerlund free(db->name); 13085e9cd1aeSAssar Westerlund free(db); 13095e9cd1aeSAssar Westerlund 13105e9cd1aeSAssar Westerlund return ret; 13115e9cd1aeSAssar Westerlund } 13125e9cd1aeSAssar Westerlund 13135e9cd1aeSAssar Westerlund krb5_error_code 13145e9cd1aeSAssar Westerlund hdb_ldap_create(krb5_context context, HDB ** db, const char *filename) 13155e9cd1aeSAssar Westerlund { 13165e9cd1aeSAssar Westerlund *db = malloc(sizeof(**db)); 13175e9cd1aeSAssar Westerlund if (*db == NULL) 13185e9cd1aeSAssar Westerlund return ENOMEM; 13195e9cd1aeSAssar Westerlund 13205e9cd1aeSAssar Westerlund (*db)->db = NULL; 13215e9cd1aeSAssar Westerlund /* (*db)->name = strdup(filename); */ 13225e9cd1aeSAssar Westerlund (*db)->name = NULL; 13235e9cd1aeSAssar Westerlund (*db)->master_key_set = 0; 13245e9cd1aeSAssar Westerlund (*db)->openp = 0; 13255e9cd1aeSAssar Westerlund (*db)->open = LDAP_open; 13265e9cd1aeSAssar Westerlund (*db)->close = LDAP_close; 13275e9cd1aeSAssar Westerlund (*db)->fetch = LDAP_fetch; 13285e9cd1aeSAssar Westerlund (*db)->store = LDAP_store; 13295e9cd1aeSAssar Westerlund (*db)->remove = LDAP_remove; 13305e9cd1aeSAssar Westerlund (*db)->firstkey = LDAP_firstkey; 13315e9cd1aeSAssar Westerlund (*db)->nextkey = LDAP_nextkey; 13325e9cd1aeSAssar Westerlund (*db)->lock = LDAP_lock; 13335e9cd1aeSAssar Westerlund (*db)->unlock = LDAP_unlock; 13345e9cd1aeSAssar Westerlund (*db)->rename = LDAP_rename; 13355e9cd1aeSAssar Westerlund /* can we ditch these? */ 13365e9cd1aeSAssar Westerlund (*db)->_get = LDAP__get; 13375e9cd1aeSAssar Westerlund (*db)->_put = LDAP__put; 13385e9cd1aeSAssar Westerlund (*db)->_del = LDAP__del; 13395e9cd1aeSAssar Westerlund (*db)->destroy = LDAP_destroy; 13405e9cd1aeSAssar Westerlund 13415e9cd1aeSAssar Westerlund return 0; 13425e9cd1aeSAssar Westerlund } 13435e9cd1aeSAssar Westerlund 13445e9cd1aeSAssar Westerlund #endif /* OPENLDAP */ 1345