diff options
author | Russ Allbery <rra@stanford.edu> | 2007-10-05 01:24:06 +0000 |
---|---|---|
committer | Russ Allbery <rra@stanford.edu> | 2007-10-05 01:24:06 +0000 |
commit | fe56c09a7feeb2d1c9cd699fda07e145c4c354a2 (patch) | |
tree | e0e1f0570ef13d801b5a5bcb5920bb2e12180635 /client | |
parent | dbe948ca3ebdad97f4f2096f6074623fc2a8e3c8 (diff) |
Pull keytab handling in the client into a separate file for later
expansion. Use the fine-grained remctl API instead of the simple one
since in some cases we'll be running multiple commands.
Diffstat (limited to 'client')
-rw-r--r-- | client/internal.h | 9 | ||||
-rw-r--r-- | client/keytab.c | 74 | ||||
-rw-r--r-- | client/srvtab.c | 4 | ||||
-rw-r--r-- | client/wallet.c | 75 |
4 files changed, 131 insertions, 31 deletions
diff --git a/client/internal.h b/client/internal.h index 186d83f..092240e 100644 --- a/client/internal.h +++ b/client/internal.h @@ -14,6 +14,9 @@ #include <sys/types.h> #include <util/util.h> +/* Forward declarations to avoid unnecessary includes. */ +struct remctl; + /* Temporary until we have some real configuration. */ #ifndef SERVER # define SERVER "wallet.stanford.edu" @@ -24,6 +27,12 @@ BEGIN_DECLS +/* Given a remctl object, the type for the wallet interface, the name of a + keytab object, and a file name, call the correct wallet commands to + download a keytab and write it to that file. */ +void get_keytab(struct remctl *, const char *type, const char *name, + const char *file); + /* Given a filename, some data, and a length, write that data to the given file safely and atomically by creating file.new, writing the data, linking file to file.bak, and then renaming file.new to file. */ diff --git a/client/keytab.c b/client/keytab.c new file mode 100644 index 0000000..3450766 --- /dev/null +++ b/client/keytab.c @@ -0,0 +1,74 @@ +/* $Id$ +** +** Implementation of keytab handling for the wallet client. +** +** Written by Russ Allbery <rra@stanford.edu> +** Copyright 2007 Board of Trustees, Leland Stanford Jr. University +** +** See README for licensing terms. +*/ + +#include <config.h> +#include <system.h> + +#include <remctl.h> + +#include <client/internal.h> +#include <util/util.h> + +/* +** Given a remctl object, the name of a keytab object, and a file name, call +** the correct wallet commands to download a keytab and write it to that +** file. +*/ +void +get_keytab(struct remctl *r, const char *type, const char *name, + const char *file) +{ + const char *command[5]; + struct remctl_output *output; + char *data = NULL; + size_t length = 0; + int status = 255; + + /* Run the command on the wallet server */ + command[0] = type; + command[1] = "get"; + command[2] = "keytab"; + command[3] = name; + command[4] = NULL; + if (!remctl_command(r, command)) + die("%s", remctl_error(r)); + + /* Retrieve the results. */ + do { + output = remctl_output(r); + switch (output->type) { + case REMCTL_OUT_OUTPUT: + if (output->stream == 1) { + data = xrealloc(data, length + output->length); + memcpy(data + length, output->data, output->length); + length += output->length; + } else { + fprintf(stderr, "wallet: "); + fwrite(output->data, 1, output->length, stderr); + } + break; + case REMCTL_OUT_STATUS: + status = output->status; + break; + case REMCTL_OUT_ERROR: + fprintf(stderr, "wallet: "); + fwrite(output->data, 1, output->length, stderr); + fputc('\n', stderr); + exit(255); + case REMCTL_OUT_DONE: + break; + } + } while (output->type != REMCTL_OUT_DONE); + if (status != 0) + exit(status); + + /* Okay, we now have the valid keytab data in data. Write it out. */ + write_file(file, data, length); +} diff --git a/client/srvtab.c b/client/srvtab.c index 68a2618..e6b9e0d 100644 --- a/client/srvtab.c +++ b/client/srvtab.c @@ -11,8 +11,6 @@ #include <config.h> #include <system.h> -#include <errno.h> -#include <fcntl.h> #include <krb5.h> #include <client/internal.h> @@ -100,8 +98,6 @@ write_srvtab(const char *srvtab, const char *principal, const char *keytab) krb5_keytab_entry entry; krb5_error_code ret; size_t length; - int fd; - ssize_t status; char aname[ANAME_SZ + 1] = ""; char inst[INST_SZ + 1] = ""; char realm[REALM_SZ + 1] = ""; diff --git a/client/wallet.c b/client/wallet.c index 998ec30..f0a0e4f 100644 --- a/client/wallet.c +++ b/client/wallet.c @@ -12,7 +12,6 @@ #include <system.h> #include <errno.h> -#include <fcntl.h> #include <remctl.h> #include <client/internal.h> @@ -52,17 +51,16 @@ usage(int status) int main(int argc, char *argv[]) { - int option, fd; - ssize_t status; + int option, i; const char **command; - struct remctl_result *result; const char *type = "wallet"; const char *server = SERVER; const char *principal = NULL; unsigned short port = PORT; const char *file = NULL; const char *srvtab = NULL; - int i; + struct remctl *r; + struct remctl_output *output; long tmp; char *end; @@ -120,31 +118,54 @@ main(int argc, char *argv[]) die("-S option requires -f also be used"); } - /* Allocate space for the command to send to the server. */ - command = xmalloc(sizeof(char *) * (argc + 2)); - command[0] = type; - for (i = 0; i < argc; i++) - command[i + 1] = argv[i]; - command[argc + 1] = NULL; - - /* Run the command. */ - result = remctl(server, port, principal, command); - if (result == NULL) + /* Open a remctl connection. */ + r = remctl_new(); + if (r == NULL) sysdie("cannot allocate memory"); - free(command); + if (!remctl_open(r, server, port, principal)) + die("%s", remctl_error(r)); - /* Display the results. */ - if (result->error != NULL) { - fprintf(stderr, "wallet: %s\n", result->error); - } else if (result->stderr_len > 0) { - fprintf(stderr, "wallet: "); - fwrite(result->stderr_buf, 1, result->stderr_len, stderr); - } else if (file != NULL && strcmp(command[1], "get") == 0) { - write_file(file, result->stdout_buf, result->stdout_len); + /* Most commands, we handle ourselves, but keytab get commands with -f are + special. */ + if (strcmp(argv[0], "get") == 0 && strcmp(argv[1], "keytab") == 0) { + if (argc > 3) + die("too many arguments"); + get_keytab(r, type, argv[2], file); if (srvtab != NULL) - write_srvtab(srvtab, command[3], file); + write_srvtab(srvtab, argv[2], file); + exit(0); } else { - fwrite(result->stdout_buf, 1, result->stdout_len, stdout); + command = xmalloc(sizeof(char *) * (argc + 2)); + command[0] = type; + for (i = 0; i < argc; i++) + command[i + 1] = argv[i]; + command[argc + 1] = NULL; + if (!remctl_command(r, command)) + die("%s", remctl_error(r)); + do { + output = remctl_output(r); + switch (output->type) { + case REMCTL_OUT_OUTPUT: + if (output->stream == 1) + fwrite(output->data, 1, output->length, stdout); + else { + fprintf(stderr, "wallet: "); + fwrite(output->data, 1, output->length, stderr); + } + break; + case REMCTL_OUT_STATUS: + exit(output->status); + case REMCTL_OUT_ERROR: + fprintf(stderr, "wallet: "); + fwrite(output->data, 1, output->length, stderr); + fputc('\n', stderr); + exit(255); + case REMCTL_OUT_DONE: + break; + } + } while (output->type != REMCTL_OUT_DONE); } - exit(result->status); + + /* This should never be reached. */ + die("invalid return from wallet server"); } |