Ejemplo n.º 1
0
/*
 * Function: kdb_put_entry
 *
 * Purpose: Stores the osa_princ_ent_t and krb5_db_entry into to
 * database.
 *
 * Arguments:
 *
 *              handle  (r) the server_handle
 *              kdb     (r/w) the krb5_db_entry to store
 *              adb     (r) the osa_princ_db_ent to store
 *
 * Effects:
 *
 * The last modifier field of the kdb is set to the caller at now.
 * adb is encoded with xdr_osa_princ_ent_ret and stored in kbd as
 * KRB5_TL_KADM_DATA.  kdb is then written to the database.
 */
krb5_error_code
kdb_put_entry(kadm5_server_handle_t handle,
              krb5_db_entry *kdb, osa_princ_ent_rec *adb)
{
    krb5_error_code ret;
    krb5_int32 now;
    XDR xdrs;
    krb5_tl_data tl_data;

    ret = krb5_timeofday(handle->context, &now);
    if (ret)
        return(ret);

    ret = krb5_dbe_update_mod_princ_data(handle->context, kdb, now,
                                         handle->current_caller);
    if (ret)
        return(ret);

    xdralloc_create(&xdrs, XDR_ENCODE);
    if(! xdr_osa_princ_ent_rec(&xdrs, adb)) {
        xdr_destroy(&xdrs);
        return(KADM5_XDR_FAILURE);
    }
    tl_data.tl_data_type = KRB5_TL_KADM_DATA;
    tl_data.tl_data_length = xdr_getpos(&xdrs);
    tl_data.tl_data_contents = (krb5_octet *)xdralloc_getdata(&xdrs);

    ret = krb5_dbe_update_tl_data(handle->context, kdb, &tl_data);

    xdr_destroy(&xdrs);

    if (ret)
        return(ret);

    /* we are always updating TL data */
    kdb->mask |= KADM5_TL_DATA;

    ret = krb5_db_put_principal(handle->context, kdb);
    if (ret)
        return(ret);

    return(0);
}
Ejemplo n.º 2
0
krb5_error_code
krb5_update_tl_kadm_data(krb5_context context, krb5_db_entry *entry,
			 osa_princ_ent_rec *princ_entry)
{
    XDR xdrs;
    krb5_tl_data tl_data;
    krb5_error_code retval;

    xdralloc_create(&xdrs, XDR_ENCODE);
    if (! ldap_xdr_osa_princ_ent_rec(&xdrs, princ_entry)) {
	xdr_destroy(&xdrs);
	return KADM5_XDR_FAILURE;
    }
    tl_data.tl_data_type = KRB5_TL_KADM_DATA;
    tl_data.tl_data_length = xdr_getpos(&xdrs);
    tl_data.tl_data_contents = (krb5_octet *)xdralloc_getdata(&xdrs);
    retval = krb5_dbe_update_tl_data(context, entry, &tl_data);
    xdr_destroy(&xdrs);
    return retval;
}
Ejemplo n.º 3
0
krb5_error_code
krb5_dbe_update_mod_princ_data(krb5_context context, krb5_db_entry *entry,
                               krb5_timestamp mod_date,
                               krb5_const_principal mod_princ)
{
    krb5_tl_data          tl_data;

    krb5_error_code       retval = 0;
    krb5_octet          * nextloc = 0;
    char                * unparse_mod_princ = 0;
    unsigned int        unparse_mod_princ_size;

    if ((retval = krb5_unparse_name(context, mod_princ,
                                    &unparse_mod_princ)))
        return(retval);

    unparse_mod_princ_size = strlen(unparse_mod_princ) + 1;

    if ((nextloc = (krb5_octet *) malloc(unparse_mod_princ_size + 4))
        == NULL) {
        free(unparse_mod_princ);
        return(ENOMEM);
    }

    tl_data.tl_data_type = KRB5_TL_MOD_PRINC;
    tl_data.tl_data_length = unparse_mod_princ_size + 4;
    tl_data.tl_data_contents = nextloc;

    /* Mod Date */
    krb5_kdb_encode_int32(mod_date, nextloc);

    /* Mod Princ */
    memcpy(nextloc+4, unparse_mod_princ, unparse_mod_princ_size);

    retval = krb5_dbe_update_tl_data(context, entry, &tl_data);

    free(unparse_mod_princ);
    free(nextloc);

    return(retval);
}
Ejemplo n.º 4
0
/*
 * Function: kdb_put_entry
 *
 * Purpose: Stores the osa_princ_ent_t and krb5_db_entry into to
 * database.
 *
 * Arguments:
 *
 *		handle	(r) the server_handle
 * 		kdb	(r/w) the krb5_db_entry to store
 * 		adb	(r) the osa_princ_db_ent to store
 *
 * Effects:
 *
 * The last modifier field of the kdb is set to the caller at now.
 * adb is encoded with xdr_osa_princ_ent_ret and stored in kbd as
 * KRB5_TL_KADM_DATA.  kdb is then written to the database.
 */
krb5_error_code
kdb_put_entry(kadm5_server_handle_t handle,
	      krb5_db_entry *kdb, osa_princ_ent_rec *adb)
{
    krb5_error_code ret;
    krb5_int32 now;
    XDR xdrs;
    krb5_tl_data tl_data;
    int one;

    if (ret = krb5_timeofday(handle->context, &now))
	return(ret);

    if (ret = krb5_dbe_update_mod_princ_data(handle->context, kdb, now,
					     handle->current_caller))
	return(ret);
    
    xdralloc_create(&xdrs, XDR_ENCODE); 
    if(! xdr_osa_princ_ent_rec(&xdrs, adb)) {
	xdr_destroy(&xdrs);
	return(OSA_ADB_XDR_FAILURE);
    }
    tl_data.tl_data_type = KRB5_TL_KADM_DATA;
    tl_data.tl_data_length = xdr_getpos(&xdrs);
    tl_data.tl_data_contents = (unsigned char *) xdralloc_getdata(&xdrs);

    ret = krb5_dbe_update_tl_data(handle->context, kdb, &tl_data);

    xdr_destroy(&xdrs);

    if (ret)
	return(ret);

    one = 1;

    if (ret = krb5_db_put_principal(handle->context, kdb, &one))
	return(ret);

    return(0);
}
Ejemplo n.º 5
0
/*
 * 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;
}
Ejemplo n.º 6
0
Archivo: kdbtest.c Proyecto: WeiY/krb5
int
main()
{
    krb5_db_entry *ent;
    osa_policy_ent_t pol;
    krb5_pa_data **e_data;
    const char *status;
    char *defrealm;
    int count;

    CHECK(krb5_init_context_profile(NULL, KRB5_INIT_CONTEXT_KDC, &ctx));

    /* Currently necessary for krb5_db_open to work. */
    CHECK(krb5_get_default_realm(ctx, &defrealm));

    /* If we can, revert to requiring all entries match sample_princ in
     * iter_princ_handler */
    CHECK_COND(krb5_db_inited(ctx) != 0);
    CHECK(krb5_db_create(ctx, NULL));
    CHECK(krb5_db_inited(ctx));
    CHECK(krb5_db_fini(ctx));
    CHECK_COND(krb5_db_inited(ctx) != 0);

    CHECK_COND(krb5_db_inited(ctx) != 0);
    CHECK(krb5_db_open(ctx, NULL, KRB5_KDB_OPEN_RW | KRB5_KDB_SRV_TYPE_ADMIN));
    CHECK(krb5_db_inited(ctx));

    /* Manipulate a policy, leaving it in place at the end. */
    CHECK_COND(krb5_db_put_policy(ctx, &sample_policy) != 0);
    CHECK_COND(krb5_db_delete_policy(ctx, polname) != 0);
    CHECK_COND(krb5_db_get_policy(ctx, polname, &pol) == KRB5_KDB_NOENTRY);
    CHECK(krb5_db_create_policy(ctx, &sample_policy));
    CHECK_COND(krb5_db_create_policy(ctx, &sample_policy) != 0);
    CHECK(krb5_db_get_policy(ctx, polname, &pol));
    check_policy(pol);
    pol->pw_min_length--;
    CHECK(krb5_db_put_policy(ctx, pol));
    krb5_db_free_policy(ctx, pol);
    CHECK(krb5_db_get_policy(ctx, polname, &pol));
    CHECK_COND(pol->pw_min_length == sample_policy.pw_min_length - 1);
    krb5_db_free_policy(ctx, pol);
    CHECK(krb5_db_delete_policy(ctx, polname));
    CHECK_COND(krb5_db_put_policy(ctx, &sample_policy) != 0);
    CHECK_COND(krb5_db_delete_policy(ctx, polname) != 0);
    CHECK_COND(krb5_db_get_policy(ctx, polname, &pol) == KRB5_KDB_NOENTRY);
    CHECK(krb5_db_create_policy(ctx, &sample_policy));
    count = 0;
    CHECK(krb5_db_iter_policy(ctx, NULL, iter_pol_handler, &count));
    CHECK_COND(count == 1);

    /* Create a principal. */
    CHECK_COND(krb5_db_delete_principal(ctx, &sample_princ) ==
               KRB5_KDB_NOENTRY);
    CHECK_COND(krb5_db_get_principal(ctx, &xrealm_princ, 0, &ent) ==
               KRB5_KDB_NOENTRY);
    CHECK(krb5_db_put_principal(ctx, &sample_entry));
    /* Putting again will fail with LDAP (due to KADM5_PRINCIPAL in mask)
     * but succeed with DB2, so don't check the result. */
    (void)krb5_db_put_principal(ctx, &sample_entry);
    /* But it should succeed in both back ends with KADM5_LOAD in mask. */
    sample_entry.mask |= KADM5_LOAD;
    CHECK(krb5_db_put_principal(ctx, &sample_entry));
    sample_entry.mask &= ~KADM5_LOAD;
    /* Fetch and compare the added principal. */
    CHECK(krb5_db_get_principal(ctx, &sample_princ, 0, &ent));
    check_entry(ent);

    /* We can't set up a successful allowed-to-delegate check through existing
     * APIs yet, but we can make a failed check. */
    CHECK_COND(krb5_db_check_allowed_to_delegate(ctx, &sample_princ, ent,
                                                 &sample_princ) != 0);

    /* Exercise lockout code. */
    /* Policy params: max_fail 2, failcnt_interval 60, lockout_duration 120 */
    /* Initial state: last_success 1, last_failed 5, fail_auth_count 2,
     * last admin unlock 6 */
    /* Check succeeds due to last admin unlock. */
    CHECK(krb5_db_check_policy_as(ctx, NULL, ent, ent, 7, &status, &e_data));
    /* Failure count resets to 1 due to last admin unlock. */
    sim_preauth(8, FALSE, &ent);
    CHECK_COND(ent->fail_auth_count == 1 && ent->last_failed == 8);
    /* Failure count resets to 1 due to failcnt_interval */
    sim_preauth(70, FALSE, &ent);
    CHECK_COND(ent->fail_auth_count == 1 && ent->last_failed == 70);
    /* Failure count resets to 0 due to successful preauth. */
    sim_preauth(75, TRUE, &ent);
    CHECK_COND(ent->fail_auth_count == 0 && ent->last_success == 75);
    /* Failure count increments to 2 and stops incrementing. */
    sim_preauth(80, FALSE, &ent);
    CHECK_COND(ent->fail_auth_count == 1 && ent->last_failed == 80);
    sim_preauth(100, FALSE, &ent);
    CHECK_COND(ent->fail_auth_count == 2 && ent->last_failed == 100);
    sim_preauth(110, FALSE, &ent);
    CHECK_COND(ent->fail_auth_count == 2 && ent->last_failed == 100);
    /* Check fails due to reaching maximum failure count. */
    CHECK_COND(krb5_db_check_policy_as(ctx, NULL, ent, ent, 170, &status,
                                       &e_data) == KRB5KDC_ERR_CLIENT_REVOKED);
    /* Check succeeds after lockout_duration has passed. */
    CHECK(krb5_db_check_policy_as(ctx, NULL, ent, ent, 230, &status, &e_data));
    /* Failure count resets to 1 on next failure. */
    sim_preauth(240, FALSE, &ent);
    CHECK_COND(ent->fail_auth_count == 1 && ent->last_failed == 240);

    /* Exercise LDAP code to clear a policy reference and to set the key
     * data on an existing principal. */
    CHECK(krb5_dbe_update_tl_data(ctx, ent, &tl_no_policy));
    ent->mask = KADM5_POLICY_CLR | KADM5_KEY_DATA;
    CHECK(krb5_db_put_principal(ctx, ent));
    CHECK(krb5_db_delete_policy(ctx, polname));

    /* Put the modified entry again (with KDB_TL_USER_INFO tl-data for LDAP) as
     * from a load operation. */
    ent->mask = (sample_entry.mask & ~KADM5_POLICY) | KADM5_LOAD;
    CHECK(krb5_db_put_principal(ctx, ent));

    /* Exercise LDAP code to create a new principal at a DN from
     * KDB_TL_USER_INFO tl-data. */
    CHECK(krb5_db_delete_principal(ctx, &sample_princ));
    CHECK(krb5_db_put_principal(ctx, ent));
    krb5_db_free_principal(ctx, ent);

    /* Exercise principal iteration code. */
    count = 0;
    CHECK(krb5_db_iterate(ctx, "xy*", iter_princ_handler, &count));
    CHECK_COND(count == 1);

    CHECK(krb5_db_fini(ctx));
    CHECK_COND(krb5_db_inited(ctx) != 0);

    /* It might be nice to exercise krb5_db_destroy here, but the LDAP module
     * doesn't support it. */

    krb5_free_default_realm(ctx, defrealm);
    krb5_free_context(ctx);
    return 0;
}