diff options
author | Russ Allbery <rra@stanford.edu> | 2010-07-28 22:05:05 -0700 |
---|---|---|
committer | Russ Allbery <rra@stanford.edu> | 2010-07-28 22:05:05 -0700 |
commit | 5a48a5d5f7f2af72cf84114453748fbd2a337537 (patch) | |
tree | 052cd5178f6026994b94a6ff93fdfad1b2c00aa2 /client/keytab.c | |
parent | a87062c0c60ba4daa3489966c85233c549a5c477 (diff) |
Break wallet-rekey out into a separate client program
Build a separate wallet-rekey client that rekeys every keytab given
on the command-line. Fix some coding style issues and add internal
prototypes. Build the shared source for both clients into an
uninstalled library to save compilation time.
Diffstat (limited to 'client/keytab.c')
-rw-r--r-- | client/keytab.c | 73 |
1 files changed, 37 insertions, 36 deletions
diff --git a/client/keytab.c b/client/keytab.c index 94a7858..41baa73 100644 --- a/client/keytab.c +++ b/client/keytab.c @@ -25,11 +25,12 @@ struct principal_name { struct principal_name* next; }; + /* * Given a context, a keytab file, and a realm, return a list of all * principals in that file. */ -struct principal_name * +static struct principal_name * keytab_principals(krb5_context ctx, const char *file, char *realm) { char *princname = NULL, *princrealm = NULL; @@ -69,31 +70,27 @@ keytab_principals(krb5_context ctx, const char *file, char *realm) break; } } - if (found == false) { current = xmalloc(sizeof(struct principal_name)); current->princ = xstrdup(princname); current->next = names; names = current; } - krb5_kt_free_entry(ctx, &entry); free(princname); } - if (status != KRB5_KT_END) die_krb5(ctx, status, "error reading keytab %s", file); krb5_kt_end_seq_get(ctx, keytab, &cursor); krb5_kt_close(ctx, keytab); - return names; } + /* - * Given keytab data as a pointer to memory and a length and the path of a - * second keytab, merge the keys in the memory keytab into the file keytab. - * Currently, this doesn't do any cleanup of old kvnos and doesn't handle - * duplicate kvnos correctly. Dies on any error. + * Given two files containing keytab data, second keytab, merge the keys into + * the new file. Currently, this doesn't do any cleanup of old kvnos and + * doesn't handle duplicate kvnos correctly. Dies on any error. */ static void merge_keytab(krb5_context ctx, const char *newfile, const char *file) @@ -131,13 +128,14 @@ merge_keytab(krb5_context ctx, const char *newfile, const char *file) krb5_kt_close(ctx, temp); } + /* * Given a remctl object, the type and name of a keytab object, and * references to keytab data and data length, call the correct wallet * commands to download a keytab and return the keytab data. Returns the * status of the remctl command. */ -int +static int download_keytab(struct remctl *r, const char *type, const char *name, char **data, size_t *length) { @@ -157,6 +155,7 @@ download_keytab(struct remctl *r, const char *type, const char *name, return status; } + /* * Given a remctl object, the Kerberos context, the name of a keytab object, * and a file name, call the correct wallet commands to download a keytab and @@ -201,13 +200,15 @@ get_keytab(struct remctl *r, krb5_context ctx, const char *type, return 0; } + /* - * Given a remctl object, the Kerberos context, the type and name of a keytab - * object, and a file name, iterate through every existing principal in the - * keytab, get fresh keys for those principals, and save the old and new - * keys to that file. Returns the status, or 255 on an internal error. + * Given a remctl object, the Kerberos context, the type for the wallet + * interface, and a file name of a keytab, iterate through every existing + * principal in the keytab in the local realm, get fresh keys for those + * principals, and save the old and new keys to that file. Returns true on + * success and false on partial failure to retrieve all the keys. */ -int +bool rekey_keytab(struct remctl *r, krb5_context ctx, const char *type, const char *file) { @@ -220,46 +221,46 @@ rekey_keytab(struct remctl *r, krb5_context ctx, const char *type, struct principal_name *names, *current; tempfile = concat(file, ".new", (char *) 0); - krb5_get_default_realm(ctx, &realm); names = keytab_principals(ctx, file, realm); - for (current = names; current != NULL; current = current->next) { status = download_keytab(r, type, current->princ, &data, &length); if (status != 0) { warn("error rekeying for principal %s", current->princ); error = true; - } else { - if (data != NULL) { - if (access(tempfile, F_OK) == 0) - append_file(tempfile, data, length); - else - write_file(tempfile, data, length); - rekeyed = true; - } + } else if (data != NULL) { + if (access(tempfile, F_OK) == 0) + append_file(tempfile, data, length); + else + write_file(tempfile, data, length); + rekeyed = true; } } /* If no new keytab data, then leave the keytab as-is. */ - if (rekeyed == false) - sysdie("no rekeyed principals found"); + if (!rekeyed) + sysdie("no rekeyable principals found"); - /* Now merge the original keytab file with the one containing the new. */ - if (access(file, F_OK) == 0) { - - /* If error, first copy the keytab file to filename.old */ - if (error == true) { + /* + * Now merge the original keytab file with the one containing the new + * keys. If there is an error, first make a backup of the current keytab + * file as keytab.old. + */ + if (access(file, F_OK) != 0) + link(tempfile, file); + else { + if (error) { data = read_file(file, &length); backupfile = concat(file, ".old", (char *) 0); overwrite_file(backupfile, data, length); + warn("partial failure to rekey keytab %s, old keyab left in %s", + file, backupfile); + free(backupfile); } merge_keytab(ctx, tempfile, file); - } else { - data = read_file(tempfile, &length); - write_file(file, data, length); } if (unlink(tempfile) < 0) sysdie("unlink of temporary keytab file %s failed", tempfile); free(tempfile); - return 0; + return !error; } |