(kt_change): collect all principals we are going to change, and pick

the highest kvno and use that to guess what kvno the resulting kvno is
going to be. Now two ktutil change in a row works. XXX fix the
protocol to pass the kvno back.


git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@11949 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
Love Hörnquist Åstrand
2003-04-01 15:04:49 +00:00
parent 272d7d3e0b
commit 52bf663c4d

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1997 - 2001 Kungliga Tekniska H<>gskolan * Copyright (c) 1997 - 2001, 2003 Kungliga Tekniska H<>gskolan
* (Royal Institute of Technology, Stockholm, Sweden). * (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved. * All rights reserved.
* *
@@ -37,7 +37,7 @@ RCSID("$Id$");
static void static void
change_entry (krb5_context context, krb5_keytab keytab, change_entry (krb5_context context, krb5_keytab keytab,
krb5_keytab_entry *entry, krb5_principal principal, krb5_kvno kvno,
const char *realm, const char *admin_server, int server_port) const char *realm, const char *admin_server, int server_port)
{ {
krb5_error_code ret; krb5_error_code ret;
@@ -48,7 +48,7 @@ change_entry (krb5_context context, krb5_keytab keytab,
int num_keys; int num_keys;
int i; int i;
ret = krb5_unparse_name (context, entry->principal, &client_name); ret = krb5_unparse_name (context, principal, &client_name);
if (ret) { if (ret) {
krb5_warn (context, ret, "krb5_unparse_name"); krb5_warn (context, ret, "krb5_unparse_name");
return; return;
@@ -59,7 +59,7 @@ change_entry (krb5_context context, krb5_keytab keytab,
if(realm) if(realm)
conf.realm = (char *)realm; conf.realm = (char *)realm;
else else
conf.realm = *krb5_princ_realm (context, entry->principal); conf.realm = *krb5_princ_realm (context, principal);
conf.mask |= KADM5_CONFIG_REALM; conf.mask |= KADM5_CONFIG_REALM;
if (admin_server) { if (admin_server) {
@@ -83,8 +83,7 @@ change_entry (krb5_context context, krb5_keytab keytab,
krb5_warn (context, ret, "kadm5_c_init_with_skey_ctx"); krb5_warn (context, ret, "kadm5_c_init_with_skey_ctx");
return; return;
} }
ret = kadm5_randkey_principal (kadm_handle, entry->principal, ret = kadm5_randkey_principal (kadm_handle, principal, &keys, &num_keys);
&keys, &num_keys);
kadm5_destroy (kadm_handle); kadm5_destroy (kadm_handle);
if (ret) { if (ret) {
krb5_warn(context, ret, "kadm5_randkey_principal"); krb5_warn(context, ret, "kadm5_randkey_principal");
@@ -93,9 +92,9 @@ change_entry (krb5_context context, krb5_keytab keytab,
for (i = 0; i < num_keys; ++i) { for (i = 0; i < num_keys; ++i) {
krb5_keytab_entry new_entry; krb5_keytab_entry new_entry;
new_entry = *entry; new_entry.principal = principal;
new_entry.timestamp = time (NULL); new_entry.timestamp = time (NULL);
++new_entry.vno; new_entry.vno = kvno + 1;
new_entry.keyblock = keys[i]; new_entry.keyblock = keys[i];
ret = krb5_kt_add_entry (context, keytab, &new_entry); ret = krb5_kt_add_entry (context, keytab, &new_entry);
@@ -110,6 +109,11 @@ change_entry (krb5_context context, krb5_keytab keytab,
* their keys, writing the new keys * their keys, writing the new keys
*/ */
struct change_set {
krb5_principal principal;
krb5_kvno kvno;
};
int int
kt_change (int argc, char **argv) kt_change (int argc, char **argv)
{ {
@@ -122,8 +126,8 @@ kt_change (int argc, char **argv)
int server_port = 0; int server_port = 0;
int help_flag = 0; int help_flag = 0;
int optind = 0; int optind = 0;
int j, max; int i, j, max;
krb5_principal *princs; struct change_set *changeset;
struct getargs args[] = { struct getargs args[] = {
{ "realm", 'r', arg_string, NULL, { "realm", 'r', arg_string, NULL,
@@ -154,12 +158,8 @@ kt_change (int argc, char **argv)
return 1; return 1;
j = 0; j = 0;
max = 10; max = 0;
princs = malloc (max * sizeof(*princs)); changeset = NULL;
if (princs == NULL) {
krb5_warnx (context, "malloc: out of memory");
goto out;
}
ret = krb5_kt_start_seq_get(context, keytab, &cursor); ret = krb5_kt_start_seq_get(context, keytab, &cursor);
if(ret){ if(ret){
@@ -168,20 +168,21 @@ kt_change (int argc, char **argv)
} }
while((ret = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0) { while((ret = krb5_kt_next_entry(context, keytab, &entry, &cursor)) == 0) {
int i; int add = 0;
int done = 0;
for (i = 0; i < j; ++i) for (i = 0; i < j; ++i) {
if (krb5_principal_compare (context, princs[i], if (krb5_principal_compare (context, changeset[i].principal,
entry.principal)) entry.principal)) {
if (changeset[i].kvno < entry.vno)
changeset[i].kvno = entry.vno;
break; break;
}
}
if (i < j) if (i < j)
continue; continue;
if (optind == argc) { if (optind == argc) {
change_entry (context, keytab, &entry, realm, admin_server, add = 1;
server_port);
done = 1;
} else { } else {
for (i = optind; i < argc; ++i) { for (i = optind; i < argc; ++i) {
krb5_principal princ; krb5_principal princ;
@@ -191,40 +192,64 @@ kt_change (int argc, char **argv)
krb5_warn (context, ret, "krb5_parse_name %s", argv[i]); krb5_warn (context, ret, "krb5_parse_name %s", argv[i]);
continue; continue;
} }
if (krb5_principal_compare (context, princ, entry.principal)) { if (krb5_principal_compare (context, princ, entry.principal))
change_entry (context, keytab, &entry, add = 1;
realm, admin_server, server_port);
done = 1;
}
krb5_free_principal (context, princ); krb5_free_principal (context, princ);
} }
} }
if (done) {
if (add) {
if (j >= max) { if (j >= max) {
void *tmp; void *tmp;
max *= 2; max = max(max * 2, 1);
tmp = realloc (princs, max * sizeof(*princs)); tmp = realloc (changeset, max * sizeof(*changeset));
if (tmp == NULL) { if (tmp == NULL) {
krb5_kt_free_entry (context, &entry); krb5_kt_free_entry (context, &entry);
krb5_warnx (context, "realloc: out of memory"); krb5_warnx (context, "realloc: out of memory");
ret = ENOMEM;
break; break;
} }
princs = tmp; changeset = tmp;
} }
ret = krb5_copy_principal (context, entry.principal, &princs[j]); ret = krb5_copy_principal (context, entry.principal,
&changeset[j].principal);
if (ret) { if (ret) {
krb5_warn (context, ret, "krb5_copy_principal"); krb5_warn (context, ret, "krb5_copy_principal");
krb5_kt_free_entry (context, &entry); krb5_kt_free_entry (context, &entry);
break; break;
} }
changeset[j].kvno = entry.vno;
++j; ++j;
} }
krb5_kt_free_entry (context, &entry); krb5_kt_free_entry (context, &entry);
} }
while (j-- > 0)
krb5_free_principal (context, princs[j]); if (ret == KRB5_KT_END) {
free (princs); for (i = 0; i < j; i++) {
if (verbose_flag) {
char *client_name;
ret = krb5_unparse_name (context, changeset[i].principal,
&client_name);
if (ret) {
krb5_warn (context, ret, "krb5_unparse_name");
} else {
printf("Changing %s kvno %d\n",
client_name, changeset[i].kvno);
free(client_name);
}
}
change_entry (context, keytab,
changeset[i].principal, changeset[i].kvno,
realm, admin_server, server_port);
}
}
for (i = 0; i < j; i++)
krb5_free_principal (context, changeset[i].principal);
free (changeset);
ret = krb5_kt_end_seq_get(context, keytab, &cursor); ret = krb5_kt_end_seq_get(context, keytab, &cursor);
out: out:
krb5_kt_close(context, keytab); krb5_kt_close(context, keytab);