From 86bce23e53e6cc89ed5104b21a5fe33fab5a7a9f Mon Sep 17 00:00:00 2001 From: Russ Allbery Date: Thu, 24 Apr 2008 23:05:14 +0000 Subject: The wallet command-line client now reads the data for store from a file (using -f) or from standard input (if -f wasn't given) when the data isn't specified on the command line. The data still must not contain nul characters. --- client/file.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ client/internal.h | 8 ++++++++ client/wallet.c | 23 ++++++++++++++++++----- client/wallet.pod | 44 ++++++++++++++++++++++++++------------------ 4 files changed, 104 insertions(+), 23 deletions(-) (limited to 'client') diff --git a/client/file.c b/client/file.c index 7e0563e..c109bd5 100644 --- a/client/file.c +++ b/client/file.c @@ -11,7 +11,9 @@ #include #include +#include #include +#include #include #include @@ -109,3 +111,53 @@ get_file(struct remctl *r, const char *prefix, const char *type, free(data); return 0; } + + +/* + * Read all of a file into memory and return the contents as a newly allocated + * string. Handles a file name of "-" to mean standard input. Dies on any + * failure. + * + * This will need modification later when we want to handle nul characters. + */ +char * +read_file(const char *name) +{ + char *contents; + size_t size, offset; + int fd; + struct stat st; + ssize_t status; + + if (strcmp(name, "-") == 0) { + fd = fileno(stdin); + size = BUFSIZ; + contents = xmalloc(size); + } else { + fd = open(name, O_RDONLY); + if (fd < 0) + sysdie("cannot open file %s", name); + if (fstat(fd, &st) < 0) + sysdie("cannot stat file %s", name); + size = st.st_size + 1; + contents = xmalloc(size); + } + offset = 0; + do { + if (offset >= size - 1) { + size += BUFSIZ; + contents = xrealloc(contents, size); + } + do { + status = read(fd, contents + offset, size - offset - 1); + } while (status == -1 && errno == EINTR); + if (status < 0) + sysdie("cannot read from file"); + offset += status; + } while (status > 0); + close(fd); + contents[offset] = '\0'; + if (memchr(contents, '\0', offset) != NULL) + die("cannot yet handle file data containing nul characters"); + return contents; +} diff --git a/client/internal.h b/client/internal.h index 64fad04..e55f2b8 100644 --- a/client/internal.h +++ b/client/internal.h @@ -90,6 +90,14 @@ void write_file(const char *name, const void *data, size_t length); void write_srvtab(krb5_context, const char *srvtab, const char *principal, const char *keytab); +/* + * Read all of a file into memory and return the contents as a newly allocated + * string. Handles a file name of "-" to mean standard input. Dies on any + * failure. This will need modification later when we want to handle nul + * characters. + */ +char *read_file(const char *); + END_DECLS #endif /* !CLIENT_INTERNAL_H */ diff --git a/client/wallet.c b/client/wallet.c index 2995cf6..5ee24f5 100644 --- a/client/wallet.c +++ b/client/wallet.c @@ -194,9 +194,10 @@ main(int argc, char *argv[]) if (argc < 3) usage(1); - /* -f is only supported for get and -S with get keytab. */ - if (file != NULL && strcmp(argv[0], "get") != 0) - die("-f only supported for get"); + /* -f is only supported for get and store and -S with get keytab. */ + if (file != NULL) + if (strcmp(argv[0], "get") != 0 && strcmp(argv[0], "store") != 0) + die("-f only supported for get and store"); if (srvtab != NULL) { if (strcmp(argv[0], "get") != 0 || strcmp(argv[1], "keytab") != 0) die("-S only supported for get keytab"); @@ -239,11 +240,23 @@ main(int argc, char *argv[]) status = get_file(r, options.type, argv[1], argv[2], file); } } else { - command = xmalloc(sizeof(char *) * (argc + 2)); + if (strcmp(argv[0], "store") == 0) { + if (argc > 4) + die("too many arguments"); + else if (argc == 4) + command = xmalloc(sizeof(char *) * (argc + 2)); + else + command = xmalloc(sizeof(char *) * (argc + 3)); + } else + command = xmalloc(sizeof(char *) * (argc + 2)); command[0] = options.type; for (i = 0; i < argc; i++) command[i + 1] = argv[i]; - command[argc + 1] = NULL; + if (strcmp(argv[0], "store") == 0 && argc < 4) { + command[argc + 1] = read_file(file == NULL ? "-" : file); + command[argc + 2] = NULL; + } else + command[argc + 1] = NULL; status = run_command(r, command, NULL, NULL); } remctl_close(r); diff --git a/client/wallet.pod b/client/wallet.pod index b6e8ff4..657929b 100644 --- a/client/wallet.pod +++ b/client/wallet.pod @@ -4,9 +4,9 @@ wallet - Client for retrieving secure data from a central server =head1 SYNOPSIS -B [B<-hv>] [B<-c> I] [B<-f> I] -[B<-k> I] [B<-p> I] [S I>] [B<-S> I] -[B<-u> I] I [I ...] +B [B<-hv>] [B<-c> I] [B<-f> I] + [B<-k> I] [B<-p> I] [S I>] + [B<-S> I] [B<-u> I] I [I ...] =head1 DESCRIPTION @@ -65,16 +65,17 @@ sometimes be useful to use a different prefix for testing a different version of the wallet code on the server. This option can also be set in F; see L below. -=item B<-f> I +=item B<-f> I -This flag is only used in combination with the C command. Rather -than sending the secure data to standard output (the default), store the -secure data in the file I. +This flag is only used in combination with the C and C +commands. For C, rather than sending the secure data to standard +output (the default), the secure data will be stored in I. For +C, the data to be stored will be read from I. -If the object being retrieved is not a keytab object, any current file -named I is renamed to F.bak> before the new file is -created. F.new> is used as a temporary file and any existing -file with that name will be deleted. +With C, if the object being retrieved is not a keytab object, any +current file named I is renamed to F.bak> before the new +file is created. F.new> is used as a temporary file and any +existing file with that name will be deleted. If the object being retrieved is a keytab object and the file I already exists, the downloaded keys will be added to the existing keytab @@ -83,6 +84,11 @@ ktremove> or an equivalent later to clean up old keys. F.new> is still used as a temporary file and any existing file with that name will be deleted. +C does not yet support nul bytes in I (or in any other way of +specifying the data to be stored). To store binary files in the wallet, +you will need to encode them with uuencode, base64, or some similar scheme +and then decode them after retrieval. + =item B<-k> I The service principal of the wallet server. The default is to use the @@ -323,15 +329,17 @@ name, the owner, any specific ACLs set on the object, the expiration if any, and the user, remote host, and time when the object was created, last stored, and last downloaded. -=item store +=item store [] Stores for the object identified by and for later -retrieval with C. Not all object types support this. - -Currently, is limited to not containing nul characters and may -therefore not be binary data, and is limited by the maximum command line -length of the operating system of the wallet server. These restrictions -will be lifted in the future. +retrieval with C. Not all object types support this. If is +not specified on the command line, it will be read from the file specified +with B<-f> (if given) or from standard input. + +Currently, the stored data must not contain nul characters and may +therefore not be binary data. Its length is also limited by the maximum +command line length of the operating system of the wallet server. These +restrictions will be lifted in the future. If an object with type and name does not already exist when this command is issued (as checked with the check interface), B -- cgit v1.2.3