Beispiel #1
0
/*
 * Fetch the current history key(s), creating the history principal if
 * necessary.  Database created since krb5 1.3 will have only one key, but
 * databases created before that may have multiple keys (of the same kvno)
 * and we need to try them all.  History keys will be returned in a list
 * terminated by an entry with enctype 0.
 */
krb5_error_code
kdb_get_hist_key(kadm5_server_handle_t handle, krb5_keyblock **keyblocks_out,
                 krb5_kvno *kvno_out)
{
    krb5_error_code ret;
    krb5_db_entry *kdb;
    krb5_keyblock *mkey, *kblist = NULL;
    krb5_int16 i;

    /* Fetch the history principal, creating it if necessary. */
    ret = kdb_get_entry(handle, hist_princ, &kdb, NULL);
    if (ret == KADM5_UNK_PRINC) {
        ret = create_hist(handle);
        if (ret)
            return ret;
        ret = kdb_get_entry(handle, hist_princ, &kdb, NULL);
    }
    if (ret)
        return ret;

    if (kdb->n_key_data <= 0) {
        ret = KRB5_KDB_NO_MATCHING_KEY;
        k5_setmsg(handle->context, ret,
                  _("History entry contains no key data"));
        goto done;
    }

    ret = krb5_dbe_find_mkey(handle->context, kdb, &mkey);
    if (ret)
        goto done;

    kblist = k5calloc(kdb->n_key_data + 1, sizeof(*kblist), &ret);
    if (kblist == NULL)
        goto done;
    for (i = 0; i < kdb->n_key_data; i++) {
        ret = krb5_dbe_decrypt_key_data(handle->context, mkey,
                                        &kdb->key_data[i], &kblist[i],
                                        NULL);
        if (ret)
            goto done;
    }

    *keyblocks_out = kblist;
    kblist = NULL;
    *kvno_out = kdb->key_data[0].key_data_kvno;

done:
    kdb_free_entry(handle, kdb, NULL);
    kdb_free_keyblocks(handle, kblist);
    return ret;
}
Beispiel #2
0
/*
 * Function: kdb_init_hist
 *
 * Purpose: Initializes the global history variables.
 *
 * Arguments:
 *
 *	handle		(r) kadm5 api server handle
 *	r		(r) realm of history principal to use, or NULL
 *
 * Effects: This function sets the value of the following global
 * variables:
 *
 *	hist_princ	krb5_principal holding the history principal
 *	hist_db		krb5_db_entry of the history principal
 *	hist_key	krb5_keyblock holding the history principal's key
 *	hist_encblock	krb5_encrypt_block holding the procssed hist_key
 *	hist_kvno	the version number of the history key
 *
 * If the history principal does not already exist, this function
 * attempts to create it with kadm5_create_principal.  WARNING!
 * If the history principal is deleted and this function is executed
 * (by kadmind, or kadmin.local, or anything else with permission),
 * the principal will be assigned a new random key and all existing
 * password history information will become useless.
 */
krb5_error_code kdb_init_hist(kadm5_server_handle_t handle, char *r)
{
    int	    ret = 0;
    char    *realm, *hist_name;
    krb5_key_data *key_data;
    krb5_key_salt_tuple ks[1];

    if (r == NULL)  {
	if ((ret = krb5_get_default_realm(handle->context, &realm)))
	    return ret;
    } else {
	realm = r;
    }

    if ((hist_name = (char *) malloc(strlen(KADM5_HIST_PRINCIPAL) +
				     strlen(realm) + 2)) == NULL)
	goto done;

    (void) sprintf(hist_name, "%s@%s", KADM5_HIST_PRINCIPAL, realm);

    if ((ret = krb5_parse_name(handle->context, hist_name, &hist_princ)))
	goto done;

    if ((ret = kdb_get_entry(handle, hist_princ, &hist_db, NULL))) {
	kadm5_principal_ent_rec ent;

	if (ret != KADM5_UNK_PRINC)
	    goto done;

	/* try to create the principal */

	memset(&ent, 0, sizeof(ent));

	ent.principal = hist_princ;
	ent.max_life = KRB5_KDB_DISALLOW_ALL_TIX;
	ent.attributes = 0;

	/* this uses hist_kvno.  So we set it to 2, which will be the
	   correct value once the principal is created and randomized.
	   Of course, it doesn't make sense to keep a history for the
	   history principal, anyway. */

	hist_kvno = 2;
	ks[0].ks_enctype = handle->params.enctype;
	ks[0].ks_salttype = KRB5_KDB_SALTTYPE_NORMAL;
	ret = kadm5_create_principal_3(handle, &ent,
				     (KADM5_PRINCIPAL |
				       KADM5_MAX_LIFE |
				       KADM5_ATTRIBUTES),
				       1, ks,
				      "to-be-random");
	if (ret)
	    goto done;

	/* this won't let us randomize the hist_princ.  So we cheat. */

	hist_princ = NULL;

	ret = kadm5_randkey_principal_3(handle, ent.principal, 0, 1, ks,
					NULL, NULL);

	hist_princ = ent.principal;

	if (ret)
	    goto done;

	/* now read the newly-created kdb record out of the
	   database. */

	if ((ret = kdb_get_entry(handle, hist_princ, &hist_db, NULL)))
	    goto done;

    }

    ret = krb5_dbe_find_enctype(handle->context, &hist_db,
			    handle->params.enctype, -1, -1, &key_data);
    if (ret)
	goto done;

    ret = krb5_dbekd_decrypt_key_data(handle->context,
		&handle->master_keyblock, key_data, &hist_key, NULL);
    if (ret)
	goto done;

    hist_kvno = key_data->key_data_kvno;

done:
    free(hist_name);
    if (r == NULL)
	free(realm);
    return ret;
}