/* * Fill out a krb5_db_entry princ entry struct given a LDAP message containing * the results of a principal search of the directory. */ krb5_error_code populate_krb5_db_entry(krb5_context context, krb5_ldap_context *ldap_context, LDAP *ld, LDAPMessage *ent, krb5_const_principal princ, krb5_db_entry *entry) { krb5_error_code ret; unsigned int mask = 0; int val, i, pcount, objtype; krb5_boolean attr_present; krb5_kvno mkvno = 0; krb5_timestamp lastpwdchange, unlock_time; char *policydn = NULL, *pwdpolicydn = NULL, *polname = NULL, *user = NULL; char *tktpolname = NULL, *dn = NULL, **link_references = NULL; char **pnvalues = NULL, **ocvalues = NULL, **a2d2 = NULL; struct berval **ber_key_data = NULL, **ber_tl_data = NULL; krb5_tl_data userinfo_tl_data = { NULL }, **endp, *tl; osa_princ_ent_rec princ_ent; memset(&princ_ent, 0, sizeof(princ_ent)); ret = krb5_copy_principal(context, princ, &entry->princ); if (ret) goto cleanup; /* get the associated directory user information */ pnvalues = ldap_get_values(ld, ent, "krbprincipalname"); if (pnvalues != NULL) { ret = krb5_unparse_name(context, princ, &user); if (ret) goto cleanup; pcount = 0; for (i = 0; pnvalues[i] != NULL; i++) { if (strcasecmp(pnvalues[i], user) == 0) { pcount = ldap_count_values(pnvalues); break; } } dn = ldap_get_dn(ld, ent); if (dn == NULL) { ldap_get_option(ld, LDAP_OPT_RESULT_CODE, &ret); ret = set_ldap_error(context, ret, 0); goto cleanup; } ocvalues = ldap_get_values(ld, ent, "objectclass"); if (ocvalues != NULL) { for (i = 0; ocvalues[i] != NULL; i++) { if (strcasecmp(ocvalues[i], "krbprincipal") == 0) { objtype = KDB_STANDALONE_PRINCIPAL_OBJECT; ret = store_tl_data(&userinfo_tl_data, KDB_TL_PRINCTYPE, &objtype); if (ret) goto cleanup; break; } } } /* Add principalcount, DN and principaltype user information to * tl_data */ ret = store_tl_data(&userinfo_tl_data, KDB_TL_PRINCCOUNT, &pcount); if (ret) goto cleanup; ret = store_tl_data(&userinfo_tl_data, KDB_TL_USERDN, dn); if (ret) goto cleanup; } ret = get_time(ld, ent, "krbLastSuccessfulAuth", &entry->last_success, &attr_present); if (ret) goto cleanup; if (attr_present) mask |= KDB_LAST_SUCCESS_ATTR; ret = get_time(ld, ent, "krbLastFailedAuth", &entry->last_failed, &attr_present); if (ret) goto cleanup; if (attr_present) mask |= KDB_LAST_FAILED_ATTR; if (krb5_ldap_get_value(ld, ent, "krbLoginFailedCount", &val) == 0) { entry->fail_auth_count = val; mask |= KDB_FAIL_AUTH_COUNT_ATTR; } if (krb5_ldap_get_value(ld, ent, "krbmaxticketlife", &val) == 0) { entry->max_life = val; mask |= KDB_MAX_LIFE_ATTR; } if (krb5_ldap_get_value(ld, ent, "krbmaxrenewableage", &val) == 0) { entry->max_renewable_life = val; mask |= KDB_MAX_RLIFE_ATTR; } if (krb5_ldap_get_value(ld, ent, "krbticketflags", &val) == 0) { entry->attributes = val; mask |= KDB_TKT_FLAGS_ATTR; } ret = get_time(ld, ent, "krbprincipalexpiration", &entry->expiration, &attr_present); if (ret) goto cleanup; if (attr_present) mask |= KDB_PRINC_EXPIRE_TIME_ATTR; ret = get_time(ld, ent, "krbpasswordexpiration", &entry->pw_expiration, &attr_present); if (ret) goto cleanup; if (attr_present) mask |= KDB_PWD_EXPIRE_TIME_ATTR; ret = krb5_ldap_get_string(ld, ent, "krbticketpolicyreference", &policydn, &attr_present); if (ret) goto cleanup; if (attr_present) { mask |= KDB_POL_REF_ATTR; /* Ensure that the policy is inside the realm container. */ ret = krb5_ldap_policydn_to_name(context, policydn, &tktpolname); if (ret) goto cleanup; } ret = krb5_ldap_get_string(ld, ent, "krbpwdpolicyreference", &pwdpolicydn, &attr_present); if (ret) goto cleanup; if (attr_present) { mask |= KDB_PWD_POL_REF_ATTR; /* Ensure that the policy is inside the realm container. */ ret = krb5_ldap_policydn_to_name(context, pwdpolicydn, &polname); if (ret) goto cleanup; princ_ent.policy = polname; princ_ent.aux_attributes |= KADM5_POLICY; } ber_key_data = ldap_get_values_len(ld, ent, "krbpwdhistory"); if (ber_key_data != NULL) { mask |= KDB_PWD_HISTORY_ATTR; ret = krb5_decode_histkey(context, ber_key_data, &princ_ent); if (ret) goto cleanup; ldap_value_free_len(ber_key_data); } if (princ_ent.aux_attributes) { ret = krb5_update_tl_kadm_data(context, entry, &princ_ent); if (ret) goto cleanup; } ber_key_data = ldap_get_values_len(ld, ent, "krbprincipalkey"); if (ber_key_data != NULL) { mask |= KDB_SECRET_KEY_ATTR; ret = krb5_decode_krbsecretkey(context, entry, ber_key_data, &mkvno); if (ret) goto cleanup; if (mkvno != 0) { ret = krb5_dbe_update_mkvno(context, entry, mkvno); if (ret) goto cleanup; } } ret = get_time(ld, ent, "krbLastPwdChange", &lastpwdchange, &attr_present); if (ret) goto cleanup; if (attr_present) { ret = krb5_dbe_update_last_pwd_change(context, entry, lastpwdchange); if (ret) goto cleanup; mask |= KDB_LAST_PWD_CHANGE_ATTR; } ret = get_time(ld, ent, "krbLastAdminUnlock", &unlock_time, &attr_present); if (ret) goto cleanup; if (attr_present) { ret = krb5_dbe_update_last_admin_unlock(context, entry, unlock_time); if (ret) goto cleanup; mask |= KDB_LAST_ADMIN_UNLOCK_ATTR; } a2d2 = ldap_get_values(ld, ent, "krbAllowedToDelegateTo"); if (a2d2 != NULL) { for (endp = &entry->tl_data; *endp; endp = &(*endp)->tl_data_next); for (i = 0; a2d2[i] != NULL; i++) { tl = k5alloc(sizeof(*tl), &ret); if (tl == NULL) goto cleanup; tl->tl_data_type = KRB5_TL_CONSTRAINED_DELEGATION_ACL; tl->tl_data_length = strlen(a2d2[i]); tl->tl_data_contents = (unsigned char *)strdup(a2d2[i]); if (tl->tl_data_contents == NULL) { ret = ENOMEM; free(tl); goto cleanup; } tl->tl_data_next = NULL; *endp = tl; endp = &tl->tl_data_next; } } link_references = ldap_get_values(ld, ent, "krbobjectreferences"); if (link_references != NULL) { for (i = 0; link_references[i] != NULL; i++) { ret = store_tl_data(&userinfo_tl_data, KDB_TL_LINKDN, link_references[i]); if (ret) goto cleanup; } } ber_tl_data = ldap_get_values_len(ld, ent, "krbExtraData"); if (ber_tl_data != NULL) { for (i = 0; ber_tl_data[i] != NULL; i++) { ret = berval2tl_data(ber_tl_data[i], &tl); if (ret) goto cleanup; ret = krb5_dbe_update_tl_data(context, entry, tl); free(tl->tl_data_contents); free(tl); if (ret) goto cleanup; } mask |= KDB_EXTRA_DATA_ATTR; } /* Auth indicators from krbPrincipalAuthInd will replace those from * krbExtraData. */ ret = get_ldap_auth_ind(context, ld, ent, entry, &mask); if (ret) goto cleanup; /* Update the mask of attributes present on the directory object to the * tl_data. */ ret = store_tl_data(&userinfo_tl_data, KDB_TL_MASK, &mask); if (ret) goto cleanup; ret = krb5_dbe_update_tl_data(context, entry, &userinfo_tl_data); if (ret) goto cleanup; ret = krb5_read_tkt_policy(context, ldap_context, entry, tktpolname); if (ret) goto cleanup; /* For compatibility with DB2 principals. */ entry->len = KRB5_KDB_V1_BASE_LENGTH; cleanup: ldap_memfree(dn); ldap_value_free_len(ber_key_data); ldap_value_free_len(ber_tl_data); ldap_value_free(pnvalues); ldap_value_free(ocvalues); ldap_value_free(link_references); ldap_value_free(a2d2); free(userinfo_tl_data.tl_data_contents); free(pwdpolicydn); free(polname); free(tktpolname); free(policydn); krb5_free_unparsed_name(context, user); free_princ_ent_contents(&princ_ent); return ret; }
krb5_error_code krb5_ldap_read_krbcontainer_params(krb5_context context, krb5_ldap_krbcontainer_params **cparamp) { krb5_error_code st=0, tempst=0; LDAP *ld=NULL; LDAPMessage *result=NULL, *ent=NULL; krb5_ldap_krbcontainer_params *cparams=NULL; kdb5_dal_handle *dal_handle=NULL; krb5_ldap_context *ldap_context=NULL; krb5_ldap_server_handle *ldap_server_handle=NULL; SETUP_CONTEXT(); GET_HANDLE(); cparams =(krb5_ldap_krbcontainer_params *) malloc(sizeof(krb5_ldap_krbcontainer_params)); CHECK_NULL(cparams); memset(cparams, 0, sizeof(krb5_ldap_krbcontainer_params)); /* read kerberos containter location from [dbmodules] section of krb5.conf file */ if (ldap_context->conf_section) { if ((st=profile_get_string(context->profile, KDB_MODULE_SECTION, ldap_context->conf_section, KRB5_CONF_LDAP_KERBEROS_CONTAINER_DN, NULL, &cparams->DN)) != 0) { krb5_set_error_message(context, st, _("Error reading kerberos container " "location from krb5.conf")); goto cleanup; } } /* read kerberos containter location from [dbdefaults] section of krb5.conf file */ if (cparams->DN == NULL) { if ((st=profile_get_string(context->profile, KDB_MODULE_DEF_SECTION, KRB5_CONF_LDAP_KERBEROS_CONTAINER_DN, NULL, NULL, &cparams->DN)) != 0) { krb5_set_error_message(context, st, _("Error reading kerberos container " "location from krb5.conf")); goto cleanup; } } if (cparams->DN == NULL) { st = KRB5_KDB_SERVER_INTERNAL_ERR; krb5_set_error_message(context, st, _("Kerberos container location not specified")); goto cleanup; } /* NOTE: krbmaxtktlife, krbmaxrenewableage ... present on Kerberos Container is * not read */ LDAP_SEARCH_1(cparams->DN, LDAP_SCOPE_BASE, "(objectclass=krbContainer)", policyrefattribute, IGNORE_STATUS); if (st != LDAP_SUCCESS && st != LDAP_NO_SUCH_OBJECT) { st = set_ldap_error(context, st, OP_SEARCH); goto cleanup; } if (st == LDAP_NO_SUCH_OBJECT) { st = KRB5_KDB_NOENTRY; goto cleanup; } if ((ent = ldap_first_entry(ld, result))) { if ((st=krb5_ldap_get_string(ld, ent, "krbticketpolicyreference", &(cparams->policyreference), NULL)) != 0) goto cleanup; } ldap_msgfree(result); if (cparams->policyreference != NULL) { LDAP_SEARCH_1(cparams->policyreference, LDAP_SCOPE_BASE, NULL, policy_attributes, IGNORE_STATUS); if (st != LDAP_SUCCESS && st!= LDAP_NO_SUCH_OBJECT) { st = set_ldap_error(context, st, OP_SEARCH); goto cleanup; } st = LDAP_SUCCESS; /* reset the return status in case it is LDAP_NO_SUCH_OBJECT */ ent=ldap_first_entry(ld, result); if (ent != NULL) { krb5_ldap_get_value(ld, ent, "krbmaxtktlife", &(cparams->max_life)); krb5_ldap_get_value(ld, ent, "krbmaxrenewableage", &(cparams->max_renewable_life)); krb5_ldap_get_value(ld, ent, "krbticketflags", &(cparams->tktflags)); } ldap_msgfree(result); } *cparamp=cparams; cleanup: if (st != 0) { krb5_ldap_free_krbcontainer_params(cparams); *cparamp=NULL; } krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle); return st; }