summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS5
-rw-r--r--TODO7
-rw-r--r--client/file.c52
-rw-r--r--client/internal.h8
-rw-r--r--client/wallet.c23
-rw-r--r--client/wallet.pod44
-rw-r--r--tests/client/basic-t.in30
-rwxr-xr-xtests/data/cmd-fake7
8 files changed, 148 insertions, 28 deletions
diff --git a/NEWS b/NEWS
index cf1d838..4bf3537 100644
--- a/NEWS
+++ b/NEWS
@@ -2,6 +2,11 @@
wallet 0.9 (unreleased)
+ 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.
+
Add support for enabling and disabling principals (clearing or setting
the NOTGS flag) and examining principals to kasetkey. This
functionality isn't used by wallet (and probably won't be) but is
diff --git a/TODO b/TODO
index 9bdd9ba..6414332 100644
--- a/TODO
+++ b/TODO
@@ -41,10 +41,6 @@ Release 1.0:
* On upgrades, support adding new object types and ACL verifiers to the
class tables.
-* Add an option to the wallet client to read the data from a file for
- object store. The initial implementation, depending on the underlying
- remctl support, may have to ban nul characters in the uploaded data.
-
* Write the LDAP entitlement ACL verifier.
* Write the PTS ACL verifier.
@@ -194,6 +190,9 @@ Future work:
* Support authenticating with a keytab.
+* Allow store data to contain nuls. Requires rewriting the command
+ processing for store to use iovecs.
+
May or may not be good ideas:
* Consider using Class::Accessor to get rid of the scaffolding code to
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 <config.h>
#include <portable/system.h>
+#include <errno.h>
#include <fcntl.h>
+#include <sys/stat.h>
#include <client/internal.h>
#include <util/util.h>
@@ -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<wallet> [B<-hv>] [B<-c> I<command>] [B<-f> I<output>]
-[B<-k> I<principal>] [B<-p> I<port>] [S<B<-s> I<server>>] [B<-S> I<srvtab>]
-[B<-u> I<principal>] I<command> [I<arg> ...]
+B<wallet> [B<-hv>] [B<-c> I<command>] [B<-f> I<file>]
+ [B<-k> I<principal>] [B<-p> I<port>] [S<B<-s> I<server>>]
+ [B<-S> I<srvtab>] [B<-u> I<principal>] I<command> [I<arg> ...]
=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<krb5.conf>; see L<CONFIGURATION> below.
-=item B<-f> I<output>
+=item B<-f> I<file>
-This flag is only used in combination with the C<get> command. Rather
-than sending the secure data to standard output (the default), store the
-secure data in the file I<output>.
+This flag is only used in combination with the C<get> and C<store>
+commands. For C<get>, rather than sending the secure data to standard
+output (the default), the secure data will be stored in I<file>. For
+C<store>, the data to be stored will be read from I<file>.
-If the object being retrieved is not a keytab object, any current file
-named I<output> is renamed to F<I<outout>.bak> before the new file is
-created. F<I<outout>.new> is used as a temporary file and any existing
-file with that name will be deleted.
+With C<get>, if the object being retrieved is not a keytab object, any
+current file named I<output> is renamed to F<I<outout>.bak> before the new
+file is created. F<I<outout>.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<output>
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<I<output>.new>
is still used as a temporary file and any existing file with that name
will be deleted.
+C<store> does not yet support nul bytes in I<file> (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<principal>
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 <type> <name> <data>
+=item store <type> <name> [<data>]
Stores <data> for the object identified by <type> and <name> for later
-retrieval with C<get>. Not all object types support this.
-
-Currently, <data> 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<get>. Not all object types support this. If <data> 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 <type> and name <name> does not already exist when
this command is issued (as checked with the check interface), B<wallet>
diff --git a/tests/client/basic-t.in b/tests/client/basic-t.in
index 3a9b2c3..f18c28e 100644
--- a/tests/client/basic-t.in
+++ b/tests/client/basic-t.in
@@ -12,7 +12,7 @@
. "@abs_top_srcdir@/tests/libtest.sh"
# Print the number of tests.
-total=31
+total=35
count=1
echo "$total"
@@ -210,6 +210,34 @@ else
fi
rm -f keytab srvtab
+# Test store from standard input.
+echo "This is a test of store" | runsuccess "" "$wallet" store file fake-test
+count=`expr $count + 1`
+echo "file fake-test" > store-correct
+echo "This is a test of store" >> store-correct
+if cmp store-output store-correct >/dev/null 2>&1 ; then
+ printcount "ok"
+else
+ printcount "not ok"
+ echo == store-output ==
+ cat store-output
+ echo == store-correct ==
+ cat store-correct
+fi
+rm -f store-output store-correct
+
+# Test store with -f.
+echo "This is more store input" > store-input
+echo "file fake-test" > store-correct
+cat store-input >> store-correct
+runsuccess "" "$wallet" -f store-input store file fake-test
+if cmp store-output store-correct >/dev/null 2>&1 ; then
+ printcount "ok"
+else
+ printcount "not ok"
+fi
+rm -f store-input store-output store-correct
+
# Test various other client functions and errors.
runsuccess "This is a fake keytab." "$wallet" get keytab service/fake-output
runsuccess "Some stuff about file fake-test" \
diff --git a/tests/data/cmd-fake b/tests/data/cmd-fake
index d12f839..3ffd9cc 100755
--- a/tests/data/cmd-fake
+++ b/tests/data/cmd-fake
@@ -130,6 +130,13 @@ get)
;;
esac
;;
+store)
+ if [ -n "$3" ] ; then
+ echo "Too many arguments" >&2
+ exit 1
+ fi
+ printf "$type $1\n$2" > store-output
+ ;;
show)
if [ -n "$2" ] ; then
echo "Too many arguments" >&2