/* * Function: kdb_get_entry * * Purpose: Gets an entry from the kerberos database and breaks * it out into a krb5_db_entry and an osa_princ_ent_t. * * Arguments: * * handle (r) the server_handle * principal (r) the principal to get * kdb (w) krb5_db_entry to fill in * adb (w) osa_princ_ent_rec to fill in * * when the caller is done with kdb and adb, kdb_free_entry must be * called to release them. The adb record is filled in with the * contents of the KRB5_TL_KADM_DATA record; if that record doesn't * exist, an empty but valid adb record is returned. */ krb5_error_code kdb_get_entry(kadm5_server_handle_t handle, krb5_principal principal, krb5_db_entry *kdb, osa_princ_ent_rec *adb) { krb5_error_code ret; int nprincs; krb5_boolean more; krb5_tl_data tl_data; XDR xdrs; ret = krb5_db_get_principal(handle->context, principal, kdb, &nprincs, &more); if (ret) return(ret); if (more) { krb5_db_free_principal(handle->context, kdb, nprincs); return(KRB5KDC_ERR_PRINCIPAL_NOT_UNIQUE); } else if (nprincs != 1) { krb5_db_free_principal(handle->context, kdb, nprincs); return(KADM5_UNK_PRINC); } if (adb) { memset(adb, 0, sizeof(*adb)); tl_data.tl_data_type = KRB5_TL_KADM_DATA; /* * XXX Currently, lookup_tl_data always returns zero; it sets * tl_data->tl_data_length to zero if the type isn't found. * This should be fixed... */ if ((ret = krb5_dbe_lookup_tl_data(handle->context, kdb, &tl_data)) || (tl_data.tl_data_length == 0)) { /* there's no admin data. this can happen, if the admin server is put into production after some principals are created. In this case, return valid admin data (which is all zeros with the hist_kvno filled in), and when the entry is written, the admin data will get stored correctly. */ adb->admin_history_kvno = hist_kvno; return(ret); } /* Solaris Kerberos */ xdrmem_create(&xdrs, (caddr_t)tl_data.tl_data_contents, tl_data.tl_data_length, XDR_DECODE); if (! xdr_osa_princ_ent_rec(&xdrs, adb)) { xdr_destroy(&xdrs); krb5_db_free_principal(handle->context, kdb, 1); return(KADM5_XDR_FAILURE); } xdr_destroy(&xdrs); } return(0); }
krb5_error_code krb5_dbe_lookup_mod_princ_data(krb5_context context, krb5_db_entry *entry, krb5_timestamp *mod_time, krb5_principal *mod_princ) { krb5_tl_data tl_data; krb5_error_code code; tl_data.tl_data_type = KRB5_TL_MOD_PRINC; if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data))) return(code); if ((tl_data.tl_data_length < 5) || (tl_data.tl_data_contents[tl_data.tl_data_length-1] != '\0')) return(KRB5_KDB_TRUNCATED_RECORD); /* Mod Date */ krb5_kdb_decode_int32(tl_data.tl_data_contents, *mod_time); /* Mod Princ */ if ((code = krb5_parse_name(context, (const char *) (tl_data.tl_data_contents+4), mod_princ))) return(code); return(0); }
/* * Function: kdb_get_entry * * Purpose: Gets an entry from the kerberos database and breaks * it out into a krb5_db_entry and an osa_princ_ent_t. * * Arguments: * * handle (r) the server_handle * principal (r) the principal to get * kdb (w) krb5_db_entry to create * adb (w) osa_princ_ent_rec to fill in * * when the caller is done with kdb and adb, kdb_free_entry must be * called to release them. The adb record is filled in with the * contents of the KRB5_TL_KADM_DATA record; if that record doesn't * exist, an empty but valid adb record is returned. */ krb5_error_code kdb_get_entry(kadm5_server_handle_t handle, krb5_principal principal, krb5_db_entry **kdb_ptr, osa_princ_ent_rec *adb) { krb5_error_code ret; krb5_tl_data tl_data; XDR xdrs; krb5_db_entry *kdb; *kdb_ptr = NULL; ret = krb5_db_get_principal(handle->context, principal, KRB5_KDB_FLAG_ALIAS_OK, &kdb); if (ret == KRB5_KDB_NOENTRY) return(KADM5_UNK_PRINC); if (ret) return(ret); if (adb) { memset(adb, 0, sizeof(*adb)); tl_data.tl_data_type = KRB5_TL_KADM_DATA; /* * XXX Currently, lookup_tl_data always returns zero; it sets * tl_data->tl_data_length to zero if the type isn't found. * This should be fixed... */ if ((ret = krb5_dbe_lookup_tl_data(handle->context, kdb, &tl_data)) || (tl_data.tl_data_length == 0)) { /* there's no admin data. this can happen, if the admin server is put into production after some principals are created. In this case, return valid admin data (which is all zeros with the hist_kvno filled in), and when the entry is written, the admin data will get stored correctly. */ adb->admin_history_kvno = INITIAL_HIST_KVNO; *kdb_ptr = kdb; return(ret); } xdrmem_create(&xdrs, (caddr_t)tl_data.tl_data_contents, tl_data.tl_data_length, XDR_DECODE); if (! xdr_osa_princ_ent_rec(&xdrs, adb)) { xdr_destroy(&xdrs); krb5_db_free_principal(handle->context, kdb); return(KADM5_XDR_FAILURE); } xdr_destroy(&xdrs); } *kdb_ptr = kdb; return(0); }
static krb5_error_code lookup_lockout_policy(krb5_context context, krb5_db_entry *entry, krb5_kvno *pw_max_fail, krb5_deltat *pw_failcnt_interval, krb5_deltat *pw_lockout_duration) { krb5_tl_data tl_data; krb5_error_code code; osa_princ_ent_rec adb; XDR xdrs; *pw_max_fail = 0; *pw_failcnt_interval = 0; *pw_lockout_duration = 0; tl_data.tl_data_type = KRB5_TL_KADM_DATA; code = krb5_dbe_lookup_tl_data(context, entry, &tl_data); if (code != 0 || tl_data.tl_data_length == 0) return code; memset(&adb, 0, sizeof(adb)); xdrmem_create(&xdrs, (char *)tl_data.tl_data_contents, tl_data.tl_data_length, XDR_DECODE); if (!xdr_osa_princ_ent_rec(&xdrs, &adb)) { xdr_destroy(&xdrs); return KADM5_XDR_FAILURE; } if (adb.policy != NULL) { osa_policy_ent_t policy = NULL; code = krb5_db2_get_policy(context, adb.policy, &policy); if (code == 0) { *pw_max_fail = policy->pw_max_fail; *pw_failcnt_interval = policy->pw_failcnt_interval; *pw_lockout_duration = policy->pw_lockout_duration; krb5_db2_free_policy(context, policy); } } xdr_destroy(&xdrs); xdrmem_create(&xdrs, NULL, 0, XDR_FREE); xdr_osa_princ_ent_rec(&xdrs, &adb); xdr_destroy(&xdrs); return 0; }
krb5_error_code krb5_get_linkdn(krb5_context context, krb5_db_entry *entry, char ***link_dn) { krb5_error_code ret; krb5_tl_data tl_data; void *ptr; *link_dn = NULL; tl_data.tl_data_type = KDB_TL_USER_INFO; ret = krb5_dbe_lookup_tl_data(context, entry, &tl_data); if (ret || tl_data.tl_data_length == 0) return ret; if (decode_tl_data(&tl_data, KDB_TL_LINKDN, &ptr) == 0) *link_dn = ptr; return 0; }
/* Decode the KADM_DATA from a DB entry.*/ static int get_adb(krb5_db_entry *dbe, osa_princ_ent_rec *adb) { XDR xdrs; int success; krb5_tl_data tl_data; krb5_error_code ret; memset(adb, 0, sizeof(*adb)); tl_data.tl_data_type = KRB5_TL_KADM_DATA; ret = krb5_dbe_lookup_tl_data(util_context, dbe, &tl_data); if (ret != 0 || tl_data.tl_data_length == 0) return 0; xdrmem_create(&xdrs, (caddr_t)tl_data.tl_data_contents, tl_data.tl_data_length, XDR_DECODE); success = xdr_osa_princ_ent_rec(&xdrs, adb); xdr_destroy(&xdrs); return success; }
static krb5_error_code get_str_from_tl_data(krb5_context context, krb5_db_entry *entry, int type, char **strval) { krb5_error_code ret; krb5_tl_data tl_data; void *ptr; if (type != KDB_TL_USERDN) return EINVAL; tl_data.tl_data_type = KDB_TL_USER_INFO; ret = krb5_dbe_lookup_tl_data(context, entry, &tl_data); if (ret || tl_data.tl_data_length == 0) return ret; if (decode_tl_data(&tl_data, type, &ptr) == 0) *strval = ptr; return 0; }
/* * wrapper routines for decode_tl_data */ static krb5_error_code get_int_from_tl_data(krb5_context context, krb5_db_entry *entry, int type, int *intval) { krb5_error_code ret; krb5_tl_data tl_data; void *ptr; int *intptr; tl_data.tl_data_type = KDB_TL_USER_INFO; ret = krb5_dbe_lookup_tl_data(context, entry, &tl_data); if (ret || tl_data.tl_data_length == 0) return ret; if (decode_tl_data(&tl_data, type, &ptr) == 0) { intptr = ptr; *intval = *intptr; free(intptr); } return 0; }
/* Compare ent against sample_entry. */ static void check_entry(krb5_db_entry *ent) { krb5_int16 i, j; krb5_key_data *k1, *k2; krb5_tl_data *tl, etl; CHECK_COND(ent->attributes == sample_entry.attributes); CHECK_COND(ent->max_life == sample_entry.max_life); CHECK_COND(ent->max_renewable_life == sample_entry.max_renewable_life); CHECK_COND(ent->expiration == sample_entry.expiration); CHECK_COND(ent->pw_expiration == sample_entry.pw_expiration); CHECK_COND(ent->last_success == sample_entry.last_success); CHECK_COND(ent->last_failed == sample_entry.last_failed); CHECK_COND(ent->fail_auth_count == sample_entry.fail_auth_count); CHECK_COND(krb5_principal_compare(ctx, ent->princ, sample_entry.princ)); CHECK_COND(ent->n_key_data == sample_entry.n_key_data); for (i = 0; i < ent->n_key_data; i++) { k1 = &ent->key_data[i]; k2 = &sample_entry.key_data[i]; CHECK_COND(k1->key_data_ver == k2->key_data_ver); CHECK_COND(k1->key_data_kvno == k2->key_data_kvno); for (j = 0; j < k1->key_data_ver; j++) { CHECK_COND(k1->key_data_type[j] == k2->key_data_type[j]); CHECK_COND(k1->key_data_length[j] == k2->key_data_length[j]); CHECK_COND(memcmp(k1->key_data_contents[j], k2->key_data_contents[j], k1->key_data_length[j]) == 0); } } for (tl = sample_entry.tl_data; tl != NULL; tl = tl->tl_data_next) { etl.tl_data_type = tl->tl_data_type; CHECK(krb5_dbe_lookup_tl_data(ctx, ent, &etl)); CHECK_COND(tl->tl_data_length == etl.tl_data_length); CHECK_COND(memcmp(tl->tl_data_contents, etl.tl_data_contents, tl->tl_data_length) == 0); } }
krb5_error_code krb5_dbe_lookup_last_pwd_change(krb5_context context, krb5_db_entry *entry, krb5_timestamp *stamp) { krb5_tl_data tl_data; krb5_error_code code; krb5_int32 tmp; tl_data.tl_data_type = KRB5_TL_LAST_PWD_CHANGE; if ((code = krb5_dbe_lookup_tl_data(context, entry, &tl_data))) return(code); if (tl_data.tl_data_length != 4) { *stamp = 0; return(0); } krb5_kdb_decode_int32(tl_data.tl_data_contents, tmp); *stamp = (krb5_timestamp) tmp; return(0); }