Add new kadmin/ktutil --keep* and --enctypes opts

- Add --keepold/keepallold/pruneall options to various kadmin/ktutil
   commands.  Default behavior to "prune old keys".

 - When setting keys for a service, we need to specify enctypes for it:

    - Always use kadm5_randkey_principal_3() instead of the older
      kadm5_randkey_principal().

    - Add krb5_string_to_keysalts2(), like MIT's krb5_string_to_keysalts(),
      but with a context, and simpler.

    - Add --enctypes options to various kadmin/ktutil commands.

    - Add [libdefaults] supported_enctypes param with enctype[:salttype]
      list.

    - Add [realms] realm supported_enctypes param with enctype[:salttype]
      list.

      Default to aes128-cts-hmac-sha1-96:normal.
This commit is contained in:
Nicolas Williams
2019-01-01 17:25:06 -06:00
committed by Nico Williams
parent 7b76d6719f
commit d8394c65b7
18 changed files with 574 additions and 142 deletions

View File

@@ -36,17 +36,23 @@
RCSID("$Id$");
static krb5_error_code
change_entry (krb5_keytab keytab,
krb5_principal principal, krb5_kvno kvno,
const char *realm, const char *admin_server, int server_port)
change_entry(krb5_keytab keytab,
krb5_principal principal,
krb5_kvno kvno,
int keep,
size_t nkstuple,
krb5_key_salt_tuple *kstuple,
const char *realm,
const char *admin_server,
int server_port)
{
krb5_error_code ret;
kadm5_config_params conf;
void *kadm_handle;
char *client_name;
krb5_keyblock *keys;
size_t i;
int num_keys;
int i;
ret = krb5_unparse_name (context, principal, &client_name);
if (ret) {
@@ -96,14 +102,15 @@ change_entry (krb5_keytab keytab,
free (client_name);
return ret;
}
ret = kadm5_randkey_principal (kadm_handle, principal, &keys, &num_keys);
kadm5_destroy (kadm_handle);
ret = kadm5_randkey_principal_3(kadm_handle, principal, keep, nkstuple,
kstuple, &keys, &num_keys);
kadm5_destroy(kadm_handle);
if (ret) {
krb5_warn(context, ret, "kadm5_randkey_principal: %s:", client_name);
krb5_warn(context, ret, "kadm5_randkey_principal_3: %s:", client_name);
free (client_name);
return ret;
}
free (client_name);
free(client_name);
for (i = 0; i < num_keys; ++i) {
krb5_keytab_entry new_entry;
@@ -131,16 +138,51 @@ struct change_set {
};
int
kt_change (struct change_options *opt, int argc, char **argv)
kt_change(struct change_options *opt, int argc, char **argv)
{
krb5_error_code ret;
krb5_keytab keytab;
krb5_kt_cursor cursor;
krb5_keytab_entry entry;
int i, j, max;
krb5_key_salt_tuple *kstuple = NULL;
const char *enctype;
size_t i, j, max, nkstuple;
int keep = 0;
struct change_set *changeset;
int errors = 0;
i = 0;
if (opt->keepold_flag) {
keep = 1;
i++;
}
if (opt->keepallold_flag) {
keep = 2;
i++;
}
if (opt->pruneall_flag) {
keep = 0;
i++;
}
if (i > 1) {
fprintf(stderr, "use only one of --keepold, --keepallold, or --pruneall\n");
return EINVAL;
}
enctype = opt->enctype_string;
if (enctype == NULL || enctype[0] == '\0')
enctype = krb5_config_get_string(context, NULL, "libdefaults",
"supported_enctypes", NULL);
if (enctype == NULL || enctype[0] == '\0')
enctype = "aes128-cts-hmac-sha1-96";
ret = krb5_string_to_keysalts2(context, enctype, &nkstuple, &kstuple);
if (ret) {
fprintf(stderr, "enctype(s) unknown\n");
return ret;
}
/* XXX Parameterize keytab name */
if((keytab = ktutil_open_keytab()) == NULL)
return 1;
@@ -232,11 +274,12 @@ kt_change (struct change_options *opt, int argc, char **argv)
free(client_name);
}
}
ret = change_entry (keytab,
changeset[i].principal, changeset[i].kvno,
opt->realm_string,
opt->admin_server_string,
opt->server_port_integer);
ret = change_entry(keytab,
changeset[i].principal, changeset[i].kvno,
keep, nkstuple, kstuple,
opt->realm_string,
opt->admin_server_string,
opt->server_port_integer);
if (ret != 0)
errors = 1;
}
@@ -247,6 +290,7 @@ kt_change (struct change_options *opt, int argc, char **argv)
free (changeset);
out:
free(kstuple);
krb5_kt_close(context, keytab);
return errors;
}

View File

@@ -82,45 +82,84 @@ open_kadmin_connection(char *principal,
return kadm_handle;
}
static int
parse_enctypes(struct get_options *opt,
size_t *nks,
krb5_key_salt_tuple **ks)
{
const char *str;
char *s = NULL;
char *tmp;
size_t i;
int ret;
*nks = 0;
*ks = NULL;
if (opt->enctypes_strings.num_strings == 0) {
str = krb5_config_get_string(context, NULL, "libdefaults",
"supported_enctypes", NULL);
if (str == NULL)
str = "aes128-cts-hmac-sha1-96";
return krb5_string_to_keysalts2(context, str, nks, ks);
}
for (i = 0; i < opt->enctypes_strings.num_strings; i++) {
if (asprintf(&tmp, "%s%s%s", i ? s : "", i ? "," : "",
opt->enctypes_strings.strings[i]) == -1) {
free(s);
return krb5_enomem(context);
}
s = tmp;
}
ret = krb5_string_to_keysalts2(context, s, nks, ks);
free(s);
return ret;
}
int
kt_get(struct get_options *opt, int argc, char **argv)
{
krb5_error_code ret = 0;
krb5_keytab keytab;
void *kadm_handle = NULL;
krb5_enctype *etypes = NULL;
size_t netypes = 0;
krb5_key_salt_tuple *ks = NULL;
size_t nks;
size_t i;
int a, j;
int a, j, keep;
unsigned int failed = 0;
if((keytab = ktutil_open_keytab()) == NULL)
i = 0;
keep = 0;
if (opt->keepallold_flag) {
keep = 2;
i++;
}
if (opt->keepold_flag) {
keep = 1;
i++;
}
if (opt->pruneall_flag) {
keep = 0;
i++;
}
if (i > 1) {
fprintf(stderr, "use only one of --keepold, --keepallold, or --pruneall\n");
return EINVAL;
}
if ((ret = parse_enctypes(opt, &nks, &ks))) {
fprintf(stderr, "invalid enctype(s)\n");
return ret;
}
if((keytab = ktutil_open_keytab()) == NULL) {
free(ks);
return 1;
}
if(opt->realm_string)
krb5_set_default_realm(context, opt->realm_string);
if (opt->enctypes_strings.num_strings != 0) {
etypes = malloc (opt->enctypes_strings.num_strings * sizeof(*etypes));
if (etypes == NULL) {
krb5_warnx(context, "malloc failed");
goto out;
}
netypes = opt->enctypes_strings.num_strings;
for(i = 0; i < netypes; i++) {
ret = krb5_string_to_enctype(context,
opt->enctypes_strings.strings[i],
&etypes[i]);
if(ret) {
krb5_warnx(context, "unrecognized enctype: %s",
opt->enctypes_strings.strings[i]);
goto out;
}
}
}
for(a = 0; a < argc; a++){
krb5_principal princ_ent;
kadm5_principal_ent_rec princ;
@@ -167,7 +206,8 @@ kt_get(struct get_options *opt, int argc, char **argv)
failed++;
continue;
}
ret = kadm5_randkey_principal(kadm_handle, princ_ent, &keys, &n_keys);
ret = kadm5_randkey_principal_3(kadm_handle, princ_ent, keep, nks, ks,
&keys, &n_keys);
if (ret) {
krb5_warn(context, ret, "kadm5_randkey_principal(%s)", argv[a]);
krb5_free_principal(context, princ_ent);
@@ -203,37 +243,22 @@ kt_get(struct get_options *opt, int argc, char **argv)
continue;
}
for(j = 0; j < n_keys; j++) {
int do_add = TRUE;
if (netypes) {
size_t k;
do_add = FALSE;
for (k = 0; k < netypes; ++k)
if (keys[j].keytype == etypes[k]) {
do_add = TRUE;
break;
}
}
if (do_add) {
entry.principal = princ_ent;
entry.vno = princ.kvno;
entry.keyblock = keys[j];
entry.timestamp = time (NULL);
ret = krb5_kt_add_entry(context, keytab, &entry);
if (ret)
krb5_warn(context, ret, "krb5_kt_add_entry");
}
entry.principal = princ_ent;
entry.vno = princ.kvno;
entry.keyblock = keys[j];
entry.timestamp = time (NULL);
ret = krb5_kt_add_entry(context, keytab, &entry);
if (ret)
krb5_warn(context, ret, "krb5_kt_add_entry");
krb5_free_keyblock_contents(context, &keys[j]);
}
kadm5_free_principal_ent(kadm_handle, &princ);
krb5_free_principal(context, princ_ent);
}
out:
free(etypes);
if (kadm_handle)
kadm5_destroy(kadm_handle);
krb5_kt_close(context, keytab);
free(ks);
return ret != 0 || failed > 0;
}

View File

@@ -54,7 +54,7 @@ command = {
short = "e"
type = "string"
argument = "enctype"
help = "encryption type"
help = "encryption type(s)"
}
option = {
long = "password"
@@ -75,6 +75,21 @@ command = {
type = "flag"
help = "generate random key"
}
option = {
long = "keepold"
type = "flag"
help = "keep old keys/password needed to decrypt extant tickets (default)"
}
option = {
long = "keepallold"
type = "flag"
help = "keep all old keys/password"
}
option = {
long = "pruneall"
type = "flag"
help = "delete all old keys"
}
option = {
long = "hex"
short = "H"
@@ -94,6 +109,28 @@ command = {
argument = "realm"
help = "realm to use"
}
option = {
long = "enctype"
short = "e"
type = "string"
argument = "enctype"
help = "encryption type(s)"
}
option = {
long = "keepold"
type = "flag"
help = "keep old keys/password needed to decrypt extant tickets (default)"
}
option = {
long = "keepallold"
type = "flag"
help = "keep all old keys/password"
}
option = {
long = "pruneall"
type = "flag"
help = "delete all old keys"
}
option = {
long = "admin-server"
short = "a"
@@ -136,6 +173,21 @@ command = {
help = "encryption types to use"
argument = "enctype"
}
option = {
long = "keepold"
type = "flag"
help = "keep old keys/password needed to decrypt extant tickets (default)"
}
option = {
long = "keepallold"
type = "flag"
help = "keep all old keys/password"
}
option = {
long = "pruneall"
type = "flag"
help = "delete all old keys"
}
option = {
long = "realm"
short = "r"

View File

@@ -62,6 +62,7 @@ can be one of the following:
.Bl -tag -width srvconvert
.It add Oo Fl p Ar principal Oc Oo Fl Fl principal= Ns Ar principal Oc \
Oo Fl V Ar kvno Oc Oo Fl Fl kvno= Ns Ar kvno Oc Oo Fl e Ar enctype Oc \
Oo Fl Fl keepold | Fl Fl keepallold | Fl Fl pruneall Oc \
Oo Fl Fl enctype= Ns Ar enctype Oc Oo Fl w Ar password Oc \
Oo Fl Fl password= Ns Ar password Oc Oo Fl r Oc Oo Fl Fl random Oc \
Oo Fl s Oc Oo Fl Fl no-salt Oc Oo Fl H Oc Op Fl Fl hex
@@ -72,6 +73,8 @@ the keytab, you should consider the
.Ar get
command, which talks to the kadmin server.
.It change Oo Fl r Ar realm Oc Oo Fl Fl realm= Ns Ar realm Oc \
Oo Fl Fl keepold | Fl Fl keepallold | Fl Fl pruneall Oc \
Oo Fl Fl enctype= Ns Ar enctype Oc \
Oo Fl Fl a Ar host Oc Oo Fl Fl admin-server= Ns Ar host Oc \
Oo Fl Fl s Ar port Oc Op Fl Fl server-port= Ns Ar port
Update one or several keys to new versions. By default, use the admin
@@ -86,6 +89,7 @@ to
.Ar keytab-dest .
.It get Oo Fl p Ar admin principal Oc \
Oo Fl Fl principal= Ns Ar admin principal Oc Oo Fl e Ar enctype Oc \
Oo Fl Fl keepold | Fl Fl keepallold | Fl Fl pruneall Oc \
Oo Fl Fl enctypes= Ns Ar enctype Oc Oo Fl r Ar realm Oc \
Oo Fl Fl realm= Ns Ar realm Oc Oo Fl a Ar admin server Oc \
Oo Fl Fl admin-server= Ns Ar admin server Oc Oo Fl s Ar server port Oc \

View File

@@ -63,18 +63,20 @@ get_default (kadm5_server_context *contextp,
*/
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)
add_one_principal(const char *name,
int rand_key,
int rand_password,
int use_defaults,
char *password,
char *policy,
size_t nkstuple,
krb5_key_salt_tuple *kstuple,
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;
@@ -157,11 +159,11 @@ add_one_principal (const char *name,
}
/* Save requested password expiry before it's clobbered */
pw_expire = princ.pw_expiration;
if(rand_key) {
if (rand_key) {
krb5_keyblock *new_keys;
int n_keys, i;
ret = kadm5_randkey_principal(kadm_handle, princ_ent,
&new_keys, &n_keys);
ret = kadm5_randkey_principal_3(kadm_handle, princ_ent, 0,
nkstuple, kstuple, &new_keys, &n_keys);
if(ret){
krb5_warn(context, ret, "kadm5_randkey_principal");
n_keys = 0;
@@ -231,10 +233,12 @@ int
add_new_key(struct add_options *opt, int argc, char **argv)
{
krb5_error_code ret = 0;
int i;
int num;
krb5_key_salt_tuple *kstuple = NULL;
krb5_key_data key_data[3];
krb5_key_data *kdp = NULL;
const char *enctypes;
size_t i, nkstuple;
int num;
num = 0;
if (opt->random_key_flag)
@@ -252,30 +256,46 @@ add_new_key(struct add_options *opt, int argc, char **argv)
return 1;
}
enctypes = opt->enctypes_string;
if (enctypes == NULL || enctypes[0] == '\0')
enctypes = krb5_config_get_string(context, NULL, "libdefaults",
"supported_enctypes", NULL);
if (enctypes == NULL || enctypes[0] == '\0')
enctypes = "aes128-cts-hmac-sha1-96";
ret = krb5_string_to_keysalts2(context, enctypes, &nkstuple, &kstuple);
if (ret) {
fprintf(stderr, "enctype(s) unknown\n");
return ret;
}
if (opt->key_string) {
const char *error;
if (parse_des_key (opt->key_string, key_data, &error)) {
fprintf (stderr, "failed parsing key \"%s\": %s\n",
opt->key_string, error);
fprintf(stderr, "failed parsing key \"%s\": %s\n",
opt->key_string, error);
free(kstuple);
return 1;
}
kdp = key_data;
}
for(i = 0; i < argc; i++) {
ret = add_one_principal (argv[i],
opt->random_key_flag,
opt->random_password_flag,
opt->use_defaults_flag,
opt->password_string,
opt->policy_string,
kdp,
opt->max_ticket_life_string,
opt->max_renewable_life_string,
opt->attributes_string,
opt->expiration_time_string,
opt->pw_expiration_time_string);
ret = add_one_principal(argv[i],
opt->random_key_flag,
opt->random_password_flag,
opt->use_defaults_flag,
opt->password_string,
opt->policy_string,
nkstuple,
kstuple,
kdp,
opt->max_ticket_life_string,
opt->max_renewable_life_string,
opt->attributes_string,
opt->expiration_time_string,
opt->pw_expiration_time_string);
if (ret) {
krb5_warn (context, ret, "adding %s", argv[i]);
break;

View File

@@ -148,12 +148,34 @@ cpw_entry(struct passwd_options *opt, int argc, char **argv)
int num;
krb5_key_data key_data[3];
data.keepold = opt->keepold_flag;
data.random_key = opt->random_key_flag;
data.random_password = opt->random_password_flag;
data.password = opt->password_string;
data.key_data = NULL;
/*
* --keepold is the the default, and it should mean "prune all old keys not
* needed to decrypt extant tickets".
*/
num = 0;
data.keepold = 0;
if (opt->keepold_flag) {
data.keepold = 1;
num++;
}
if (opt->keepallold_flag) {
data.keepold = 2;
num++;
}
if (opt->pruneall_flag) {
data.keepold = 0;
num++;
}
if (num > 1) {
fprintf(stderr, "use only one of --keepold, --keepallold, and --pruneall\n");
return 1;
}
num = 0;
if (data.random_key)
++num;

View File

@@ -36,7 +36,10 @@
struct ext_keytab_data {
krb5_keytab keytab;
int keep;
int random_key_flag;
size_t nkstuple;
krb5_key_salt_tuple *kstuple;
};
static int
@@ -109,7 +112,8 @@ do_ext_keytab(krb5_principal principal, void *data)
n_k++;
}
} else if (e->random_key_flag) {
ret = kadm5_randkey_principal(kadm_handle, principal, &k, &n_k);
ret = kadm5_randkey_principal_3(kadm_handle, principal, e->keep,
e->nkstuple, e->kstuple, &k, &n_k);
if (ret)
goto out;
@@ -151,8 +155,30 @@ int
ext_keytab(struct ext_keytab_options *opt, int argc, char **argv)
{
krb5_error_code ret;
int i;
struct ext_keytab_data data;
const char *enctypes;
size_t i;
data.random_key_flag = opt->random_key_flag;
data.keep = 0;
i = 0;
if (opt->keepallold_flag) {
data.keep = 2;
i++;
}
if (opt->keepold_flag) {
data.keep = 1;
i++;
}
if (opt->pruneall_flag) {
data.keep = 1;
i++;
}
if (i > 1) {
fprintf(stderr,
"use only one of --keepold, --keepallold, or --pruneall\n");
return EINVAL;
}
if (opt->keytab_string == NULL)
ret = krb5_kt_default(context, &data.keytab);
@@ -163,8 +189,19 @@ ext_keytab(struct ext_keytab_options *opt, int argc, char **argv)
krb5_warn(context, ret, "krb5_kt_resolve");
return 1;
}
data.random_key_flag = opt->random_key_flag;
enctypes = opt->enctypes_string;
if (enctypes == NULL || enctypes[0] == '\0')
enctypes = krb5_config_get_string(context, NULL, "libdefaults",
"supported_enctypes", NULL);
if (enctypes == NULL || enctypes[0] == '\0')
enctypes = "aes128-cts-hmac-sha1-96";
ret = krb5_string_to_keysalts2(context, enctypes, &data.nkstuple,
&data.kstuple);
if (ret) {
fprintf(stderr, "enctype(s) unknown\n");
krb5_kt_close(context, data.keytab);
return ret;
}
for(i = 0; i < argc; i++) {
ret = foreach_principal(argv[i], do_ext_keytab, "ext", &data);
@@ -173,6 +210,6 @@ ext_keytab(struct ext_keytab_options *opt, int argc, char **argv)
}
krb5_kt_close(context, data.keytab);
free(data.kstuple);
return ret != 0;
}

View File

@@ -534,9 +534,15 @@ get_entry(struct get_options *opt, int argc, char **argv)
int
list_princs(struct list_options *opt, int argc, char **argv)
{
struct get_options get_opt;
if(sizeof(struct get_options) != sizeof(struct list_options)) {
krb5_warnx(context, "programmer error: sizeof(struct get_options) != sizeof(struct list_options)");
return 0;
}
return getit((struct get_options*)opt, "list", argc, argv);
get_opt.long_flag = opt->long_flag;
get_opt.short_flag = opt->short_flag;
get_opt.terse_flag = opt->terse_flag;
get_opt.column_info_string = opt->column_info_string;
return getit(&get_opt, "list", argc, argv);
}

View File

@@ -139,6 +139,12 @@ command = {
type = "flag"
help = "set random password"
}
option = {
long = "enctypes"
short = "e"
type = "string"
help = "encryption type(s)"
}
option = {
long = "password"
short = "p"
@@ -225,6 +231,12 @@ command = {
type = "flag"
help = "set random password"
}
option = {
long = "enctypes"
short = "e"
type = "string"
help = "encryption type(s)"
}
option = {
long = "password"
short = "p"
@@ -239,7 +251,17 @@ command = {
option = {
long = "keepold"
type = "flag"
help = "keep old keys/password"
help = "keep old keys/password needed to decrypt extant tickets (default)"
}
option = {
long = "keepallold"
type = "flag"
help = "keep all old keys/password"
}
option = {
long = "pruneall"
type = "flag"
help = "delete all old keys"
}
argument = "principal..."
min_args = "1"
@@ -286,6 +308,27 @@ command = {
type = "flag"
help = "set random key"
}
option = {
long = "enctypes"
short = "e"
type = "string"
help = "encryption type(s)"
}
option = {
long = "keepold"
type = "flag"
help = "keep old keys/password needed to decrypt extant tickets (default)"
}
option = {
long = "keepallold"
type = "flag"
help = "keep all old keys/password"
}
option = {
long = "pruneall"
type = "flag"
help = "delete all old keys"
}
argument = "principal..."
min_args = "1"
help = "Extracts the keys of all principals matching the expressions, and stores them in a keytab."
@@ -294,7 +337,7 @@ command = {
name = "get"
name = "get_entry"
function = "get_entry"
/* XXX sync options with "list" */
/* Options added to list should be added here; not the reverse */
option = {
long = "long"
short = "l"

View File

@@ -102,6 +102,7 @@ Commands include:
.Pp
.Nm add
.Op Fl r | Fl Fl random-key
.Op Fl Fl enctypes= Ns Ar string
.Op Fl Fl random-password
.Op Fl p Ar string \*(Ba Fl Fl password= Ns Ar string
.Op Fl Fl key= Ns Ar string
@@ -115,6 +116,24 @@ Commands include:
.Bd -ragged -offset indent
Adds a new principal to the database. The options not passed on the
command line will be promped for.
If enctypes to use are not given, then the
.Ar [libdefaults] supported_enctypes
configuration parameter will be used on the client side to select
enctypes, defaulting to
.Ar aes128-cts-hmac-sha1-96.
For compatibility with MIT, the enctypes string is a space- or
comma-separated list of enctype:salttype.
If
.Fl Fl keepold
is given, then old keys needed to decrypt extant tickets are
kept, and all other old keys are deleted.
If
.Fl Fl keepallold
is given then all old keys are kept. If
.Fl Fl pruneall is given then all old keys are removed.
The
.Fl Fl keepold
behavior is the default if none of these are given.
The only policy supported by Heimdal servers is
.Ql default .
.Ed
@@ -157,6 +176,8 @@ principals, those are not consulted here.
.Pp
.Nm ext_keytab
.Oo Fl k Ar string \*(Ba Xo
.Op Fl Fl keepold | Fl Fl keepallold | Fl Fl pruneall
.Op Fl Fl enctypes= Ns Ar string
.Fl Fl keytab= Ns Ar string
.Xc
.Oc
@@ -165,6 +186,24 @@ principals, those are not consulted here.
Creates a keytab with the keys of the specified principals. Requires
get-keys rights, otherwise the principal's keys are changed and saved in
the keytab.
If enctypes to use are not given, then the
.Ar [libdefaults] supported_enctypes
configuration parameter will be used on the client side to select
enctypes, defaulting to
.Ar aes128-cts-hmac-sha1-96.
For compatibility with MIT, the enctypes string is a space- or
comma-separated list of enctype:salttype.
If
.Fl Fl keepold
is given, then old keys needed to decrypt extant tickets are
kept, and all other old keys are deleted.
If
.Fl Fl keepallold
is given then all old keys are kept. If
.Fl Fl pruneall is given then all old keys are removed.
The
.Fl Fl keepold
behavior is the default if none of these are given.
.Ed
.Pp
.Nm get
@@ -250,7 +289,8 @@ kadmin -l modify -a -disallow-proxiable user
.Ed
.Pp
.Nm passwd
.Op Fl Fl keepold
.Op Fl Fl keepold | Fl Fl keepallold | Fl Fl pruneall
.Op Fl Fl enctypes= Ns Ar string
.Op Fl r | Fl Fl random-key
.Op Fl Fl random-password
.Oo Fl p Ar string \*(Ba Xo
@@ -261,6 +301,24 @@ kadmin -l modify -a -disallow-proxiable user
.Ar principal...
.Bd -ragged -offset indent
Changes the password of an existing principal.
If enctypes to use are not given, then the
.Ar [libdefaults] supported_enctypes
configuration parameter will be used on the client side to select
enctypes, defaulting to
.Ar aes128-cts-hmac-sha1-96.
For compatibility with MIT, the enctypes string is a space- or
comma-separated list of enctype:salttype.
If
.Fl Fl keepold
is given, then old keys needed to decrypt extant tickets are
kept, and all other old keys are deleted.
If
.Fl Fl keepallold
is given then all old keys are kept. If
.Fl Fl pruneall is given then all old keys are removed.
The
.Fl Fl keepold
behavior is the default if none of these are given.
.Ed
.Pp
.Nm password-quality

View File

@@ -155,7 +155,23 @@ keytabs).
joe/admin@EXAMPLE.COM all
mallory/admin@EXAMPLE.COM add,get-keys host/*@EXAMPLE.COM
.Ed
.\".Sh DIAGNOSTICS
.Sh CONFIGURATION FILE
kadmind uses the following configuration parameters from the
.Ar [kadmin]
section of
.Ar krb5.conf:
.Bl -tag -width Ds -offset indent
.It password_lifetime
.El
.Pp
kadmind uses the following configuration parameters from the per-realm entries
in the
.Ar [realms]
section of
.Ar krb5.conf:
.Bl -tag -width Ds -offset indent
.It supported_enctypes
.El
.Sh SEE ALSO
.Xr kpasswd 1 ,
.Xr kadmin 1 ,

View File

@@ -448,9 +448,11 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
break;
}
case kadm_randkey:{
size_t i;
op = "RANDKEY";
ret = krb5_ret_principal(sp, &princ);
if(ret)
if (ret)
goto fail;
krb5_unparse_name_fixed(contextp->context, princ, name, sizeof(name));
krb5_warnx(contextp->context, "%s: %s %s", client, op, name);
@@ -483,39 +485,49 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
}
ret = krb5_ret_int32(sp, &n_ks_tuple);
if (ret != 0 && ret != HEIM_ERR_EOF) {
if (ret == HEIM_ERR_EOF) {
const char *enctypes;
enctypes = krb5_config_get_string(context, NULL, "realms",
krb5_principal_get_realm(context,
princ),
"supported_enctypes", NULL);
if (enctypes == NULL || enctypes[0] == '\0')
enctypes = "aes128-cts-hmac-sha1-96";
ret = krb5_string_to_keysalts2(context, enctypes, &n_ks_tuple,
&ks_tuple);
}
if (ret != 0) {
krb5_free_principal(contextp->context, princ);
goto fail;
} else if (ret == 0) {
size_t i;
if (n_ks_tuple < 0) {
ret = EOVERFLOW;
krb5_free_principal(contextp->context, princ);
goto fail;
}
if ((ks_tuple = calloc(n_ks_tuple, sizeof (*ks_tuple))) == NULL) {
ret = errno;
krb5_free_principal(contextp->context, princ);
goto fail;
}
for (i = 0; i < n_ks_tuple; i++) {
ret = krb5_ret_int32(sp, &ks_tuple[i].ks_enctype);
if (ret != 0) {
krb5_free_principal(contextp->context, princ);
free(ks_tuple);
goto fail;
}
ret = krb5_ret_int32(sp, &ks_tuple[i].ks_salttype);
if (ret != 0) {
krb5_free_principal(contextp->context, princ);
free(ks_tuple);
goto fail;
}
}
}
if (n_ks_tuple < 0) {
ret = EOVERFLOW;
krb5_free_principal(contextp->context, princ);
goto fail;
}
if ((ks_tuple = calloc(n_ks_tuple, sizeof (*ks_tuple))) == NULL) {
ret = errno;
krb5_free_principal(contextp->context, princ);
goto fail;
}
for (i = 0; i < n_ks_tuple; i++) {
ret = krb5_ret_int32(sp, &ks_tuple[i].ks_enctype);
if (ret != 0) {
krb5_free_principal(contextp->context, princ);
free(ks_tuple);
goto fail;
}
ret = krb5_ret_int32(sp, &ks_tuple[i].ks_salttype);
if (ret != 0) {
krb5_free_principal(contextp->context, princ);
free(ks_tuple);
goto fail;
}
}
ret = kadm5_randkey_principal_3(kadm_handlep, princ, keepold,
n_ks_tuple, ks_tuple, &new_keys,
&n_keys);
@@ -525,10 +537,9 @@ kadmind_dispatch(void *kadm_handlep, krb5_boolean initial,
krb5_storage_free(sp);
sp = krb5_storage_emem();
krb5_store_int32(sp, ret);
if(ret == 0){
int i;
if (ret == 0){
krb5_store_int32(sp, n_keys);
for(i = 0; i < n_keys; i++){
for (i = 0; i < n_keys; i++){
if (ret == 0)
ret = krb5_store_keyblock(sp, new_keys[i]);
krb5_free_keyblock_contents(contextp->context, &new_keys[i]);

View File

@@ -103,6 +103,14 @@ kadm5_s_randkey_principal(void *server_handle,
if (keepold) {
ret = hdb_add_current_keys_to_history(context->context, &ent.entry);
if (ret == 0 && keepold == 1)
ret = hdb_prune_keys_kvno(context, &ent.entry, 0);
if (ret)
goto out3;
} else {
/* Remove all key history */
ret = hdb_clear_extension(context, &ent.entry,
choice_HDB_extension_data_hist_keys);
if (ret)
goto out3;
}

View File

@@ -45,6 +45,7 @@ HEIMDAL_KADM5_CLIENT_1.0 {
kadm5_init_with_skey_ctx;
kadm5_modify_principal;
kadm5_randkey_principal;
kadm5_randkey_principal_3;
kadm5_rename_principal;
kadm5_ret_key_data;
kadm5_ret_principal_ent;

View File

@@ -653,6 +653,7 @@ EXPORTS
krb5_string_to_key_derived
krb5_string_to_key_salt
krb5_string_to_key_salt_opaque
krb5_string_to_keysalts2
krb5_string_to_keytype
krb5_string_to_salttype
krb5_ticket_get_authorization_data_type

View File

@@ -91,6 +91,69 @@ krb5_string_to_salttype (krb5_context context,
return HEIM_ERR_SALTTYPE_NOSUPP;
}
/*
* Like MIT's krb5_string_to_keysalts(), but simpler and with a context
* argument.
*/
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_string_to_keysalts2(krb5_context context, const char *string,
size_t *nksaltp, krb5_key_salt_tuple **ksaltp)
{
/* deleted: tupleseps, ksaltseps, dups */
krb5_key_salt_tuple *tmp = NULL;
krb5_error_code ret = 0;
char *copy, *token, *stype_str;
char *lasts = NULL;
krb5_enctype etype;
krb5_salttype stype;
size_t i;
*ksaltp = NULL;
*nksaltp = 0;
if ((copy = strdup(string)) == NULL)
return krb5_enomem(context);
for (token = strtok_r(copy, ", \t", &lasts), ret = 0;
token != NULL;
token = strtok_r(NULL, ", \t", &lasts)) {
if ((stype_str = strchr(token, ':')) != NULL)
*(stype_str++) = '\0';
if ((ret = krb5_string_to_enctype(context, token, &etype)))
continue;
if (stype_str == NULL)
stype = KRB5_PW_SALT;
else if ((ret = krb5_string_to_salttype(context, etype, stype_str, &stype)))
continue;
for (i = 0; i < *nksaltp; i++) {
if ((*ksaltp)[i].ks_enctype == etype &&
(*ksaltp)[i].ks_salttype == stype)
goto skip;
}
tmp = realloc(*ksaltp, ((*nksaltp) + 1) * sizeof(**ksaltp));
if (tmp == NULL) {
ret = krb5_enomem(context);
break;
}
*ksaltp = tmp;
(*ksaltp)[*nksaltp].ks_enctype = etype;
(*ksaltp)[*nksaltp].ks_salttype = stype;
(*nksaltp)++;
skip:
(void)1;
}
free(copy);
if (ret == ENOMEM) {
free(*ksaltp);
*nksaltp = 0;
*ksaltp = NULL;
} else if (*nksaltp) {
return 0;
} else if (ret == 0) {
return KRB5_PROG_ETYPE_NOSUPP;
}
return ret;
}
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_get_pw_salt(krb5_context context,
krb5_const_principal principal,

View File

@@ -646,6 +646,7 @@ HEIMDAL_KRB5_2.0 {
krb5_string_to_key_derived;
krb5_string_to_key_salt;
krb5_string_to_key_salt_opaque;
krb5_string_to_keysalts2;
krb5_string_to_keytype;
krb5_string_to_salttype;
krb5_ticket_get_authorization_data_type;

View File

@@ -87,9 +87,12 @@ ${kadmin} -l add -p "$foopassword" --use-defaults fez@${R} || exit 1
${kadmin} -l add -p "$foopassword" --use-defaults hasalias@${R} || exit 1
${kadmin} -l add -p "$foopassword" --use-defaults pkinit@${R} || exit 1
${kadmin} -l modify --pkinit-acl="CN=baz,DC=test,DC=h5l,DC=se" pkinit@${R} || exit 1
${kadmin} -l add -p foo --use-defaults prune@${R} || exit 1
${kadmin} -l add -p "$foopassword" --use-defaults prune@${R} || exit 1
${kadmin} -l cpw --keepold --random-key prune@${R} || exit 1
${kadmin} -l cpw --keepold --random-key prune@${R} || exit 1
${kadmin} -l add -p "$foopassword" --use-defaults pruneall@${R} || exit 1
${kadmin} -l cpw --pruneall --random-key pruneall@${R} || exit 1
${kadmin} -l cpw --pruneall --random-key pruneall@${R} || exit 1
echo "$foopassword" > ${objdir}/foopassword
@@ -382,6 +385,23 @@ cat kadmin.tmp | ${EGREP} Keytypes: | cut -d: -f2 | tr ' ' '
' | ${EGREP} '^13$' > /dev/null || \
{ echo "kadmin prune failed $?"; cat messages.log ; exit 1; }
#----------------------------------
${kadmind} -d &
kadmpid=$!
sleep 1
echo "kadmin pruneall"
env KRB5CCNAME=${cache} \
${kadmin} get pruneall@${R} \
> kadmin.tmp 2>&1 || \
{ echo "kadmin failed $?"; cat messages.log ; exit 1; }
wait $kadmpid || { echo "kadmind failed $?"; cat messages.log ; exit 1; }
cat kadmin.tmp | ${EGREP} Keytypes: | cut -d: -f2 | tr ' ' '
' | sed 's/^.*[[]\(.*\)[]].*$/\1/' | grep '[0-9]' | sort -nu | tr -d '
' | ${EGREP} '^3$' > /dev/null || \
{ echo "kadmin pruneall failed $?"; cat messages.log ; exit 1; }
#----------------------------------
echo "killing kdc (${kdcpid} ${kadmpid})"