示例#1
0
kadm5_ret_t
kadm5_s_get_principal(void *server_handle,
		      krb5_principal princ,
		      kadm5_principal_ent_t out,
		      uint32_t mask)
{
    kadm5_server_context *context = server_handle;
    kadm5_ret_t ret;
    hdb_entry_ex ent;

    memset(&ent, 0, sizeof(ent));
    ret = context->db->hdb_open(context->context, context->db, O_RDONLY, 0);
    if(ret)
	return ret;
    ret = context->db->hdb_fetch(context->context, context->db, princ,
				 HDB_F_DECRYPT|HDB_F_GET_ANY|HDB_F_ADMIN_DATA, &ent);
    context->db->hdb_close(context->context, context->db);
    if(ret)
	return _kadm5_error_code(ret);

    memset(out, 0, sizeof(*out));
    if(mask & KADM5_PRINCIPAL)
	ret  = krb5_copy_principal(context->context, ent.entry.principal,
				   &out->principal);
    if(ret)
	goto out;
    if(mask & KADM5_PRINC_EXPIRE_TIME && ent.entry.valid_end)
	out->princ_expire_time = *ent.entry.valid_end;
    if(mask & KADM5_PW_EXPIRATION && ent.entry.pw_end)
	out->pw_expiration = *ent.entry.pw_end;
    if(mask & KADM5_LAST_PWD_CHANGE)
	hdb_entry_get_pw_change_time(&ent.entry, &out->last_pwd_change);
    if(mask & KADM5_ATTRIBUTES){
	out->attributes |= ent.entry.flags.postdate ? 0 : KRB5_KDB_DISALLOW_POSTDATED;
	out->attributes |= ent.entry.flags.forwardable ? 0 : KRB5_KDB_DISALLOW_FORWARDABLE;
	out->attributes |= ent.entry.flags.initial ? KRB5_KDB_DISALLOW_TGT_BASED : 0;
	out->attributes |= ent.entry.flags.renewable ? 0 : KRB5_KDB_DISALLOW_RENEWABLE;
	out->attributes |= ent.entry.flags.proxiable ? 0 : KRB5_KDB_DISALLOW_PROXIABLE;
	out->attributes |= ent.entry.flags.invalid ? KRB5_KDB_DISALLOW_ALL_TIX : 0;
	out->attributes |= ent.entry.flags.require_preauth ? KRB5_KDB_REQUIRES_PRE_AUTH : 0;
	out->attributes |= ent.entry.flags.server ? 0 : KRB5_KDB_DISALLOW_SVR;
	out->attributes |= ent.entry.flags.change_pw ? KRB5_KDB_PWCHANGE_SERVICE : 0;
	out->attributes |= ent.entry.flags.ok_as_delegate ? KRB5_KDB_OK_AS_DELEGATE : 0;
	out->attributes |= ent.entry.flags.trusted_for_delegation ? KRB5_KDB_TRUSTED_FOR_DELEGATION : 0;
	out->attributes |= ent.entry.flags.allow_kerberos4 ? KRB5_KDB_ALLOW_KERBEROS4 : 0;
	out->attributes |= ent.entry.flags.allow_digest ? KRB5_KDB_ALLOW_DIGEST : 0;
    }
    if(mask & KADM5_MAX_LIFE) {
	if(ent.entry.max_life)
	    out->max_life = *ent.entry.max_life;
	else
	    out->max_life = INT_MAX;
    }
    if(mask & KADM5_MOD_TIME) {
	if(ent.entry.modified_by)
	    out->mod_date = ent.entry.modified_by->time;
	else
	    out->mod_date = ent.entry.created_by.time;
    }
    if(mask & KADM5_MOD_NAME) {
	if(ent.entry.modified_by) {
	    if (ent.entry.modified_by->principal != NULL)
		ret = krb5_copy_principal(context->context,
					  ent.entry.modified_by->principal,
					  &out->mod_name);
	} else if(ent.entry.created_by.principal != NULL)
	    ret = krb5_copy_principal(context->context,
				      ent.entry.created_by.principal,
				      &out->mod_name);
	else
	    out->mod_name = NULL;
    }
    if(ret)
	goto out;

    if(mask & KADM5_KVNO)
	out->kvno = ent.entry.kvno;
    if(mask & KADM5_MKVNO) {
	int n;
	out->mkvno = 0; /* XXX */
	for(n = 0; n < ent.entry.keys.len; n++)
	    if(ent.entry.keys.val[n].mkvno) {
		out->mkvno = *ent.entry.keys.val[n].mkvno; /* XXX this isn't right */
		break;
	    }
    }
#if 0 /* XXX implement */
    if(mask & KADM5_AUX_ATTRIBUTES)
	;	
    if(mask & KADM5_LAST_SUCCESS)
	;
    if(mask & KADM5_LAST_FAILED)
	;
    if(mask & KADM5_FAIL_AUTH_COUNT)
	;
#endif
    if(mask & KADM5_POLICY)
	out->policy = NULL;
    if(mask & KADM5_MAX_RLIFE) {
	if(ent.entry.max_renew)
	    out->max_renewable_life = *ent.entry.max_renew;
	else
	    out->max_renewable_life = INT_MAX;
    }
    if(mask & KADM5_KEY_DATA){
	int i;
	Key *key;
	krb5_key_data *kd;
	krb5_salt salt;
	krb5_data *sp;
	krb5_get_pw_salt(context->context, ent.entry.principal, &salt);
	out->key_data = malloc(ent.entry.keys.len * sizeof(*out->key_data));
	if (out->key_data == NULL && ent.entry.keys.len != 0) {
	    ret = ENOMEM;
	    goto out;
	}
	for(i = 0; i < ent.entry.keys.len; i++){
	    key = &ent.entry.keys.val[i];
	    kd = &out->key_data[i];
	    kd->key_data_ver = 2;
	    kd->key_data_kvno = ent.entry.kvno;
	    kd->key_data_type[0] = key->key.keytype;
	    if(key->salt)
		kd->key_data_type[1] = key->salt->type;
	    else
		kd->key_data_type[1] = KRB5_PADATA_PW_SALT;
	    /* setup key */
	    kd->key_data_length[0] = key->key.keyvalue.length;
	    kd->key_data_contents[0] = malloc(kd->key_data_length[0]);
	    if(kd->key_data_contents[0] == NULL && kd->key_data_length[0] != 0){
		ret = ENOMEM;
		break;
	    }
	    memcpy(kd->key_data_contents[0], key->key.keyvalue.data,
		   kd->key_data_length[0]);
	    /* setup salt */
	    if(key->salt)
		sp = &key->salt->salt;
	    else
		sp = &salt.saltvalue;
	    kd->key_data_length[1] = sp->length;
	    kd->key_data_contents[1] = malloc(kd->key_data_length[1]);
	    if(kd->key_data_length[1] != 0
	       && kd->key_data_contents[1] == NULL) {
		memset(kd->key_data_contents[0], 0, kd->key_data_length[0]);
		ret = ENOMEM;
		break;
	    }
	    memcpy(kd->key_data_contents[1], sp->data, kd->key_data_length[1]);
	    out->n_key_data = i + 1;
	}
	krb5_free_salt(context->context, salt);
    }
    if(ret){
	kadm5_free_principal_ent(context, out);
	goto out;
    }
    if(mask & KADM5_TL_DATA) {
	time_t last_pw_expire;
	const HDB_Ext_PKINIT_acl *acl;
	const HDB_Ext_Aliases *aliases;

	ret = hdb_entry_get_pw_change_time(&ent.entry, &last_pw_expire);
	if (ret == 0 && last_pw_expire) {
	    unsigned char buf[4];
	    _krb5_put_int(buf, last_pw_expire, sizeof(buf));
	    ret = add_tl_data(out, KRB5_TL_LAST_PWD_CHANGE, buf, sizeof(buf));
	}
	if(ret){
	    kadm5_free_principal_ent(context, out);
	    goto out;
	}
	/*
	 * If the client was allowed to get key data, let it have the
	 * password too.
	 */
	if(mask & KADM5_KEY_DATA) {
	    heim_utf8_string pw;

	    ret = hdb_entry_get_password(context->context,
					 context->db, &ent.entry, &pw);
	    if (ret == 0) {
		ret = add_tl_data(out, KRB5_TL_PASSWORD, pw, strlen(pw) + 1);
		free(pw);
	    }
	    krb5_clear_error_message(context->context);
	}

	ret = hdb_entry_get_pkinit_acl(&ent.entry, &acl);
	if (ret == 0 && acl) {
	    krb5_data buf;
	    size_t len;

	    ASN1_MALLOC_ENCODE(HDB_Ext_PKINIT_acl, buf.data, buf.length,
				acl, &len, ret);
	    if (ret) {
		kadm5_free_principal_ent(context, out);
		goto out;
	    }
	    if (len != buf.length)
		krb5_abortx(context->context,
			    "internal ASN.1 encoder error");
	    ret = add_tl_data(out, KRB5_TL_PKINIT_ACL, buf.data, buf.length);
	    free(buf.data);
	    if (ret) {
		kadm5_free_principal_ent(context, out);
		goto out;
	    }
	}
	if(ret){
	    kadm5_free_principal_ent(context, out);
	    goto out;
	}

	ret = hdb_entry_get_aliases(&ent.entry, &aliases);
	if (ret == 0 && aliases) {
	    krb5_data buf;
	    size_t len;

	    ASN1_MALLOC_ENCODE(HDB_Ext_Aliases, buf.data, buf.length,
			       aliases, &len, ret);
	    if (ret) {
		kadm5_free_principal_ent(context, out);
		goto out;
	    }
	    if (len != buf.length)
		krb5_abortx(context->context,
			    "internal ASN.1 encoder error");
	    ret = add_tl_data(out, KRB5_TL_ALIASES, buf.data, buf.length);
	    free(buf.data);
	    if (ret) {
		kadm5_free_principal_ent(context, out);
		goto out;
	    }
	}
	if(ret){
	    kadm5_free_principal_ent(context, out);
	    goto out;
	}

    }
out:
    hdb_free_entry(context->context, &ent);

    return _kadm5_error_code(ret);
}
示例#2
0
static int
do_mod_entry(krb5_principal principal, void *data)
{
    krb5_error_code ret;
    kadm5_principal_ent_rec princ;
    int mask = 0;
    struct modify_options *e = data;

    memset (&princ, 0, sizeof(princ));
    ret = kadm5_get_principal(kadm_handle, principal, &princ,
			      KADM5_PRINCIPAL | KADM5_ATTRIBUTES |
			      KADM5_MAX_LIFE | KADM5_MAX_RLIFE |
			      KADM5_PRINC_EXPIRE_TIME |
			      KADM5_PW_EXPIRATION);
    if(ret)
	return ret;

    if(e->max_ticket_life_string ||
       e->max_renewable_life_string ||
       e->expiration_time_string ||
       e->pw_expiration_time_string ||
       e->attributes_string ||
       e->kvno_integer != -1 ||
       e->constrained_delegation_strings.num_strings ||
       e->alias_strings.num_strings ||
       e->pkinit_acl_strings.num_strings) {
	ret = set_entry(context, &princ, &mask,
			e->max_ticket_life_string,
			e->max_renewable_life_string,
			e->expiration_time_string,
			e->pw_expiration_time_string,
			e->attributes_string);
	if(e->kvno_integer != -1) {
	    princ.kvno = e->kvno_integer;
	    mask |= KADM5_KVNO;
	}
	if (e->constrained_delegation_strings.num_strings) {
	    add_constrained_delegation(context, &princ,
				       &e->constrained_delegation_strings);
	    mask |= KADM5_TL_DATA;
	}
	if (e->alias_strings.num_strings) {
	    add_aliases(context, &princ, &e->alias_strings);
	    mask |= KADM5_TL_DATA;
	}
	if (e->pkinit_acl_strings.num_strings) {
	    add_pkinit_acl(context, &princ, &e->pkinit_acl_strings);
	    mask |= KADM5_TL_DATA;
	}

    } else
	ret = edit_entry(&princ, &mask, NULL, 0);
    if(ret == 0) {
	ret = kadm5_modify_principal(kadm_handle, &princ, mask);
	if(ret)
	    krb5_warn(context, ret, "kadm5_modify_principal");
    }

    kadm5_free_principal_ent(kadm_handle, &princ);
    return ret;
}
示例#3
0
int
del_enctype(void *opt, int argc, char **argv)
{
    kadm5_principal_ent_rec princ;
    krb5_principal princ_ent = NULL;
    krb5_error_code ret;
    const char *princ_name;
    int i, j, k;
    krb5_key_data *new_key_data;
    int n_etypes;
    krb5_enctype *etypes;

    memset (&princ, 0, sizeof(princ));
    princ_name = argv[0];
    n_etypes   = argc - 1;
    etypes     = malloc (n_etypes * sizeof(*etypes));
    if (etypes == NULL) {
	krb5_warnx (context, "out of memory");
	return 0;
    }
    argv++;
    for (i = 0; i < n_etypes; ++i) {
	ret = krb5_string_to_enctype (context, argv[i], &etypes[i]);
	if (ret) {
	    krb5_warnx (context, "bad enctype \"%s\"", argv[i]);
	    goto out2;
	}
    }

    ret = krb5_parse_name(context, princ_name, &princ_ent);
    if (ret) {
	krb5_warn (context, ret, "krb5_parse_name %s", princ_name);
	goto out2;
    }

    ret = kadm5_get_principal(kadm_handle, princ_ent, &princ,
			      KADM5_PRINCIPAL | KADM5_KEY_DATA);
    if (ret) {
	krb5_free_principal (context, princ_ent);
	krb5_warnx (context, "no such principal: %s", princ_name);
	goto out2;
    }

    new_key_data   = malloc(princ.n_key_data * sizeof(*new_key_data));
    if (new_key_data == NULL && princ.n_key_data != 0) {
	krb5_warnx (context, "out of memory");
	goto out;
    }

    for (i = 0, j = 0; i < princ.n_key_data; ++i) {
	krb5_key_data *key = &princ.key_data[i];
	int docopy = 1;

	for (k = 0; k < n_etypes; ++k)
	    if (etypes[k] == key->key_data_type[0]) {
		docopy = 0;
		break;
	    }
	if (docopy) {
	    new_key_data[j++] = *key;
	} else {
	    int16_t ignore = 1;

	    kadm5_free_key_data (kadm_handle, &ignore, key);
	}
    }

    free (princ.key_data);
    princ.n_key_data = j;
    princ.key_data   = new_key_data;

    ret = kadm5_modify_principal (kadm_handle, &princ, KADM5_KEY_DATA);
    if (ret)
	krb5_warn(context, ret, "kadm5_modify_principal");
out:
    krb5_free_principal (context, princ_ent);
    kadm5_free_principal_ent(kadm_handle, &princ);
out2:
    free (etypes);
    return ret != 0;
}
示例#4
0
int
check(void *opt, int argc, char **argv)
{
    kadm5_principal_ent_rec ent;
    krb5_error_code ret;
    char *realm = NULL, *p, *p2;
    int found;

    if (argc == 0) {
	ret = krb5_get_default_realm(context, &realm);
	if (ret) {
	    krb5_warn(context, ret, "krb5_get_default_realm");
	    goto fail;
	}
    } else {
	realm = strdup(argv[0]);
	if (realm == NULL) {
	    krb5_warnx(context, "malloc");
	    goto fail;
	}
    }

    /*
     * Check krbtgt/REALM@REALM
     *
     * For now, just check existance
     */

    if (asprintf(&p, "%s/%s@%s", KRB5_TGS_NAME, realm, realm) == -1) {
	krb5_warn(context, errno, "asprintf");
	goto fail;
    }

    ret = get_check_entry(p, &ent);
    if (ret) {
	printf("%s doesn't exist, are you sure %s is a realm in your database",
	       p, realm);
	free(p);
	goto fail;
    }
    free(p);

    kadm5_free_principal_ent(kadm_handle, &ent);

    /*
     * Check kadmin/admin@REALM
     */

    if (asprintf(&p, "kadmin/admin@%s", realm) == -1) {
	krb5_warn(context, errno, "asprintf");
	goto fail;
    }

    ret = get_check_entry(p, &ent);
    if (ret) {
	printf("%s doesn't exist, "
	       "there is no way to do remote administration", p);
	free(p);
	goto fail;
    }
    free(p);

    kadm5_free_principal_ent(kadm_handle, &ent);

    /*
     * Check kadmin/changepw@REALM
     */

    if (asprintf(&p, "kadmin/changepw@%s", realm) == -1) {
	krb5_warn(context, errno, "asprintf");
	goto fail;
    }

    ret = get_check_entry(p, &ent);
    if (ret) {
	printf("%s doesn't exist, "
	       "there is no way to do change password", p);
	free(p);
	goto fail;
    }
    free(p);

    kadm5_free_principal_ent(kadm_handle, &ent);

    /*
     * Check default@REALM
     *
     * Check that disallow-all-tix is set on the default principal
     * (or that the entry doesn't exists)
     */

    if (asprintf(&p, "default@%s", realm) == -1) {
	krb5_warn(context, errno, "asprintf");
	goto fail;
    }

    ret = get_check_entry(p, &ent);
    if (ret == 0) {
	if ((ent.attributes & KRB5_KDB_DISALLOW_ALL_TIX) == 0) {
	    printf("default template entry is not disabled\n");
	    ret = EINVAL;
	}
	kadm5_free_principal_ent(kadm_handle, &ent);

    } else {
	ret = 0;
    }

    free(p);

    if (ret)
	goto fail;

    /*
     * Check for duplicate afs keys
     */

    p2 = strdup(realm);
    if (p2 == NULL) {
	krb5_warn(context, errno, "malloc");
	goto fail;
    }
    strlwr(p2);

    if (asprintf(&p, "afs/%s@%s", p2, realm) == -1) {
	krb5_warn(context, errno, "asprintf");
	free(p2);
	goto fail;
    }
    free(p2);

    ret = get_check_entry(p, &ent);
    free(p);
    if (ret == 0) {
	kadm5_free_principal_ent(kadm_handle, &ent);
	found = 1;
    } else
	found = 0;

    if (asprintf(&p, "afs@%s", realm) == -1) {
	krb5_warn(context, errno, "asprintf");
	goto fail;
    }

    ret = get_check_entry(p, &ent);
    free(p);
    if (ret == 0) {
	kadm5_free_principal_ent(kadm_handle, &ent);
	if (found) {
	    krb5_warnx(context, "afs@REALM and afs/cellname@REALM both exists");
	    goto fail;
	}
    }

    foreach_principal("*", do_check_entry, "check", NULL);

    free(realm);
    return 0;
fail:
    free(realm);
    return 1;
}
示例#5
0
文件: ank.c 项目: DavidMulder/heimdal
static krb5_error_code
add_one_principal (const char *name,
		   int rand_key,
		   int rand_password,
		   int use_defaults,
		   char *password,
		   char *policy,
		   krb5_key_data *key_data,
		   const char *max_ticket_life,
		   const char *max_renewable_life,
		   const char *attributes,
		   const char *expiration,
		   const char *pw_expiration)
{
    krb5_error_code ret;
    kadm5_principal_ent_rec princ, defrec;
    kadm5_principal_ent_rec *default_ent = NULL;
    krb5_principal princ_ent = NULL;
    int mask = 0;
    int default_mask = 0;
    char pwbuf[1024];

    memset(&princ, 0, sizeof(princ));
    ret = krb5_parse_name(context, name, &princ_ent);
    if (ret) {
	krb5_warn(context, ret, "krb5_parse_name");
	return ret;
    }
    princ.principal = princ_ent;
    mask |= KADM5_PRINCIPAL;

    ret = set_entry(context, &princ, &mask,
		    max_ticket_life, max_renewable_life,
		    expiration, pw_expiration, attributes, policy);
    if (ret)
	goto out;

    default_ent = &defrec;
    ret = get_default (kadm_handle, princ_ent, default_ent);
    if (ret) {
	default_ent  = NULL;
	default_mask = 0;
    } else {
	default_mask = KADM5_ATTRIBUTES | KADM5_MAX_LIFE | KADM5_MAX_RLIFE |
	    KADM5_PRINC_EXPIRE_TIME | KADM5_PW_EXPIRATION;
    }

    if(use_defaults)
	set_defaults(&princ, &mask, default_ent, default_mask);
    else
	if(edit_entry(&princ, &mask, default_ent, default_mask))
	    goto out;
    if(rand_key || key_data) {
	princ.attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
	mask |= KADM5_ATTRIBUTES;
	random_password (pwbuf, sizeof(pwbuf));
	password = pwbuf;
    } else if (rand_password) {
	random_password (pwbuf, sizeof(pwbuf));
	password = pwbuf;
    } else if(password == NULL) {
	char *princ_name;
	char *prompt;
	int aret;

	ret = krb5_unparse_name(context, princ_ent, &princ_name);
	if (ret)
	    goto out;
	aret = asprintf (&prompt, "%s's Password: "******"out of memory");
	    goto out;
	}
	ret = UI_UTIL_read_pw_string (pwbuf, sizeof(pwbuf), prompt, 1);
	free (prompt);
	if (ret) {
	    ret = KRB5_LIBOS_BADPWDMATCH;
	    krb5_set_error_message(context, ret, "failed to verify password");
	    goto out;
	}
	password = pwbuf;
    }

    ret = kadm5_create_principal(kadm_handle, &princ, mask, password);
    if(ret) {
	krb5_warn(context, ret, "kadm5_create_principal");
	goto out;
    }
    if(rand_key) {
	krb5_keyblock *new_keys;
	int n_keys, i;
	ret = kadm5_randkey_principal(kadm_handle, princ_ent,
				      &new_keys, &n_keys);
	if(ret){
	    krb5_warn(context, ret, "kadm5_randkey_principal");
	    n_keys = 0;
	}
	for(i = 0; i < n_keys; i++)
	    krb5_free_keyblock_contents(context, &new_keys[i]);
	if (n_keys > 0)
	    free(new_keys);
	kadm5_get_principal(kadm_handle, princ_ent, &princ,
			    KADM5_PRINCIPAL | KADM5_KVNO | KADM5_ATTRIBUTES);
        krb5_free_principal(context, princ_ent);
        princ_ent = princ.principal;
	princ.attributes &= (~KRB5_KDB_DISALLOW_ALL_TIX);
	/*
	 * Updating kvno w/o key data and vice-versa gives _kadm5_setup_entry()
	 * and _kadm5_set_keys2() headaches.  But we used to, so we handle
	 * this in in those two functions.  Might as well leave this code as
	 * it was then.
	 */
	princ.kvno = 1;
	kadm5_modify_principal(kadm_handle, &princ,
			       KADM5_ATTRIBUTES | KADM5_KVNO);
    } else if (key_data) {
	ret = kadm5_chpass_principal_with_key (kadm_handle, princ_ent,
					       3, key_data);
	if (ret) {
	    krb5_warn(context, ret, "kadm5_chpass_principal_with_key");
	}
	kadm5_get_principal(kadm_handle, princ_ent, &princ,
			    KADM5_PRINCIPAL | KADM5_ATTRIBUTES);
        krb5_free_principal(context, princ_ent);
        princ_ent = princ.principal;
	princ.attributes &= (~KRB5_KDB_DISALLOW_ALL_TIX);
	kadm5_modify_principal(kadm_handle, &princ, KADM5_ATTRIBUTES);
    } else if (rand_password) {
	char *princ_name;

	krb5_unparse_name(context, princ_ent, &princ_name);
	printf ("added %s with password \"%s\"\n", princ_name, password);
	free (princ_name);
    }
out:
    kadm5_free_principal_ent(kadm_handle, &princ); /* frees princ_ent */
    if(default_ent)
	kadm5_free_principal_ent (kadm_handle, default_ent);
    if (password != NULL)
	memset (password, 0, strlen(password));
    return ret;
}
/**
 * This function is allows the caller to set new keys for a principal.
 * This is a simple wrapper around kadm5_get_principal() and
 * kadm5_modify_principal().
 */
kadm5_ret_t
kadm5_setkey_principal_3(void *server_handle,
                         krb5_principal princ,
                         krb5_boolean keepold,
                         int n_ks_tuple, krb5_key_salt_tuple *ks_tuple,
                         krb5_keyblock *keyblocks,
                         int n_keys)
{
    kadm5_principal_ent_rec princ_ent;
    kadm5_ret_t ret;
    krb5_key_data *new_key_data = NULL;
    size_t i;

    if (n_keys < 1)
	return EINVAL;
    if (n_ks_tuple > 0 && n_ks_tuple != n_keys)
	return KADM5_SETKEY3_ETYPE_MISMATCH;

    ret = kadm5_get_principal(server_handle, princ, &princ_ent,
                              KADM5_KVNO | KADM5_PRINCIPAL | KADM5_KEY_DATA);
    if (ret)
	return ret;

    if (keepold) {
	new_key_data = malloc((n_keys + princ_ent.n_key_data) * sizeof(*new_key_data));
	if (new_key_data == NULL) {
	    ret = ENOMEM;
	    goto out;
	}

	memcpy(&new_key_data[n_keys], &princ_ent.key_data[0],
		princ_ent.n_key_data * sizeof (princ_ent.key_data[0]));
    } else {
	new_key_data = malloc(n_keys * sizeof(*new_key_data));
	if (new_key_data == NULL) {
	    ret = ENOMEM;
	    goto out;
	}
    }

    princ_ent.kvno++;
    for (i = 0; i < n_keys; i++) {
	new_key_data[i].key_data_ver = 2;

	/* Key */
	new_key_data[i].key_data_kvno = princ_ent.kvno;
	new_key_data[i].key_data_type[0] = keyblocks[i].keytype;
	new_key_data[i].key_data_length[0] = keyblocks[i].keyvalue.length;
	new_key_data[i].key_data_contents[0] =
	    malloc(keyblocks[i].keyvalue.length);
	if (new_key_data[i].key_data_contents[0] == NULL) {
	    ret = ENOMEM;
	    goto out;
	}
	memcpy(new_key_data[i].key_data_contents[0],
	       keyblocks[i].keyvalue.data,
	       keyblocks[i].keyvalue.length);

	/*
	 * Salt (but there's no salt, just salttype, which is kinda
	 * silly -- what's the point of setkey_3() then, besides
	 * keepold?!)
	 */
	new_key_data[i].key_data_type[1] = 0;
	if (n_ks_tuple > 0) {
	    if (ks_tuple[i].ks_enctype != keyblocks[i].keytype)
		return KADM5_SETKEY3_ETYPE_MISMATCH;
	    new_key_data[i].key_data_type[1] = ks_tuple[i].ks_salttype;
	}
	new_key_data[i].key_data_length[1] = 0;
	new_key_data[i].key_data_contents[1] = NULL;
    }

    /* Free old keys */
    if (!keepold) {
	for (i = 0; i < princ_ent.n_key_data; i++) {
	    free(princ_ent.key_data[i].key_data_contents[0]);
	    free(princ_ent.key_data[i].key_data_contents[1]);
	}
    }
    free(princ_ent.key_data);
    princ_ent.key_data = new_key_data;
    princ_ent.n_key_data = n_keys + (keepold ? princ_ent.n_key_data : 0);
    new_key_data = NULL;

    /* Modify the principal */
    ret = kadm5_modify_principal(server_handle, &princ_ent, KADM5_KVNO | KADM5_KEY_DATA);

out:
    if (new_key_data != NULL) {
	for (i = 0; i < n_keys; i++) {
	    free(new_key_data[i].key_data_contents[0]);
	    free(new_key_data[i].key_data_contents[1]);
	}
	free(new_key_data);
    }
    kadm5_free_principal_ent(server_handle, &princ_ent);
    return ret;
}
示例#7
0
static int
do_ext_keytab(krb5_principal principal, void *data)
{
    krb5_error_code ret;
    kadm5_principal_ent_rec princ;
    struct ext_keytab_data *e = data;
    krb5_keytab_entry *keys = NULL;
    krb5_keyblock *k = NULL;
    int i, n_k;

    ret = kadm5_get_principal(kadm_handle, principal, &princ,
			      KADM5_PRINCIPAL|KADM5_KVNO|KADM5_KEY_DATA);
    if(ret)
	return ret;

    if (princ.n_key_data) {
	keys = malloc(sizeof(*keys) * princ.n_key_data);
	if (keys == NULL) {
	    kadm5_free_principal_ent(kadm_handle, &princ);
	    krb5_clear_error_message(context);
	    return ENOMEM;
	}
	for (i = 0; i < princ.n_key_data; i++) {
	    krb5_key_data *kd = &princ.key_data[i];

	    keys[i].principal = princ.principal;
	    keys[i].vno = kd->key_data_kvno;
	    keys[i].keyblock.keytype = kd->key_data_type[0];
	    keys[i].keyblock.keyvalue.length = kd->key_data_length[0];
	    keys[i].keyblock.keyvalue.data = kd->key_data_contents[0];
	    keys[i].timestamp = time(NULL);
	}

	n_k = princ.n_key_data;
    } else {
	ret = kadm5_randkey_principal(kadm_handle, principal, &k, &n_k);
	if (ret) {
	    kadm5_free_principal_ent(kadm_handle, &princ);
	    return ret;
	}
	keys = malloc(sizeof(*keys) * n_k);
	if (keys == NULL) {
	    kadm5_free_principal_ent(kadm_handle, &princ);
	    krb5_clear_error_message(context);
	    return ENOMEM;
	}
	for (i = 0; i < n_k; i++) {
	    keys[i].principal = principal;
	    keys[i].vno = princ.kvno + 1; /* XXX get entry again */
	    keys[i].keyblock = k[i];
	    keys[i].timestamp = time(NULL);
	}
    }

    for(i = 0; i < n_k; i++) {
	ret = krb5_kt_add_entry(context, e->keytab, &keys[i]);
	if(ret)
	    krb5_warn(context, ret, "krb5_kt_add_entry(%d)", i);
    }

    if (k) {
	memset(k, 0, n_k * sizeof(*k));
	free(k);
    }
    if (keys)
	free(keys);
    kadm5_free_principal_ent(kadm_handle, &princ);
    return 0;
}
示例#8
0
static int
do_ext_keytab(krb5_principal principal, void *data)
{
    krb5_error_code ret;
    kadm5_principal_ent_rec princ;
    struct ext_keytab_data *e = data;
    krb5_keytab_entry *keys = NULL;
    krb5_keyblock *k = NULL;
    size_t i;
    int n_k = 0;
    uint32_t mask;
    char *unparsed = NULL;

    mask = KADM5_PRINCIPAL;
    if (!e->random_key_flag)
        mask |= KADM5_KVNO | KADM5_KEY_DATA;

    ret = kadm5_get_principal(kadm_handle, principal, &princ, mask);
    if (ret)
	return ret;

    ret = krb5_unparse_name(context, principal, &unparsed);
    if (ret)
	goto out;

    if (!e->random_key_flag) {
        if (princ.n_key_data == 0) {
            krb5_warnx(context, "principal has no keys, or user lacks "
                       "get-keys privilege for %s", unparsed);
            goto out;
        }
        /*
         * kadmin clients and servers from master between 1.5 and 1.6
         * can have corrupted a principal's keys in the HDB.  If some
         * are bogus but not all are, then that must have happened.
         *
         * If all keys are bogus then the server may be a pre-1.6,
         * post-1.5 server and the client lacks get-keys privilege, or
         * the keys are corrupted.  We can't tell here.
         */
        if (kadm5_all_keys_are_bogus(princ.n_key_data, princ.key_data)) {
            krb5_warnx(context, "user lacks get-keys privilege for %s",
                       unparsed);
            goto out;
        }
        if (kadm5_some_keys_are_bogus(princ.n_key_data, princ.key_data)) {
            krb5_warnx(context, "some keys for %s are corrupted in the HDB",
                       unparsed);
        }
	keys = calloc(sizeof(*keys), princ.n_key_data);
	if (keys == NULL) {
	    ret = krb5_enomem(context);
	    goto out;
	}
	for (i = 0; i < princ.n_key_data; i++) {
	    krb5_key_data *kd = &princ.key_data[i];

            /* Don't extract bogus keys */
            if (kadm5_all_keys_are_bogus(1, kd))
                continue;

	    keys[i].principal = princ.principal;
	    keys[i].vno = kd->key_data_kvno;
	    keys[i].keyblock.keytype = kd->key_data_type[0];
	    keys[i].keyblock.keyvalue.length = kd->key_data_length[0];
	    keys[i].keyblock.keyvalue.data = kd->key_data_contents[0];
	    keys[i].timestamp = time(NULL);
            n_k++;
	}
    } else if (e->random_key_flag) {
	ret = kadm5_randkey_principal(kadm_handle, principal, &k, &n_k);
	if (ret)
	    goto out;

	keys = calloc(sizeof(*keys), n_k);
	if (keys == NULL) {
	    ret = krb5_enomem(context);
	    goto out;
	}
	for (i = 0; i < n_k; i++) {
	    keys[i].principal = principal;
	    keys[i].vno = princ.kvno + 1; /* XXX get entry again */
	    keys[i].keyblock = k[i];
	    keys[i].timestamp = time(NULL);
	}
    }

    if (n_k == 0)
        krb5_warn(context, ret, "no keys written to keytab for %s", unparsed);

    for (i = 0; i < n_k; i++) {
	ret = krb5_kt_add_entry(context, e->keytab, &keys[i]);
	if (ret)
	    krb5_warn(context, ret, "krb5_kt_add_entry(%lu)", (unsigned long)i);
    }

  out:
    kadm5_free_principal_ent(kadm_handle, &princ);
    if (k) {
        for (i = 0; i < n_k; i++)
            memset(k[i].keyvalue.data, 0, k[i].keyvalue.length);
	free(k);
    }
    free(unparsed);
    free(keys);
    return 0;
}