aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/internal.h9
-rw-r--r--client/remctl.c45
-rw-r--r--client/wallet.c8
-rw-r--r--client/wallet.pod8
-rw-r--r--tests/client/basic-t.in12
-rwxr-xr-xtests/data/cmd-fake35
6 files changed, 112 insertions, 5 deletions
diff --git a/client/internal.h b/client/internal.h
index 88b0e24..795c58d 100644
--- a/client/internal.h
+++ b/client/internal.h
@@ -42,6 +42,15 @@ void kinit(krb5_context, const char *principal);
int run_command(struct remctl *, const char **command, char **data,
size_t *length);
+/* Check whether an object exists using the exists wallet interface. Returns
+ true if it does, false if it doesn't, and dies on remctl errors. */
+int object_exists(struct remctl *, const char *prefix, const char *type,
+ const char *name);
+
+/* Attempt autocreation of an object. Dies if autocreation fails. */
+void object_autocreate(struct remctl *, const char *prefix, const char *type,
+ const char *name);
+
/* Given a remctl object, the type for the wallet interface, object type,
object name, and a file (which may be NULL), send a wallet get command and
write the results to the provided file. If the file is NULL, write the
diff --git a/client/remctl.c b/client/remctl.c
index 6d80bf2..aa9a9f8 100644
--- a/client/remctl.c
+++ b/client/remctl.c
@@ -72,3 +72,48 @@ run_command(struct remctl *r, const char **command, char **data,
} while (output->type != REMCTL_OUT_DONE);
return status;
}
+
+
+/*
+** Check whether an object exists using the exists wallet interface. Returns
+** true if it does, false if it doesn't, and dies on remctl errors.
+*/
+int
+object_exists(struct remctl *r, const char *prefix, const char *type,
+ const char *name)
+{
+ const char *command[5];
+ char *data = NULL;
+ size_t length;
+
+ command[0] = prefix;
+ command[1] = "exists";
+ command[2] = type;
+ command[3] = name;
+ command[4] = NULL;
+ if (run_command(r, command, &data, &length) != 0)
+ exit(1);
+ if (length == 4 && strncmp(data, "yes\n", 4) == 0)
+ return 1;
+ else
+ return 0;
+}
+
+
+/*
+** Attempt autocreation of an object. Dies if autocreation fails.
+*/
+void
+object_autocreate(struct remctl *r, const char *prefix, const char *type,
+ const char *name)
+{
+ const char *command[5];
+
+ command[0] = prefix;
+ command[1] = "autocreate";
+ command[2] = type;
+ command[3] = name;
+ command[4] = NULL;
+ if (run_command(r, command, NULL, NULL) != 0)
+ exit(1);
+}
diff --git a/client/wallet.c b/client/wallet.c
index 8ce7ae0..2e4f755 100644
--- a/client/wallet.c
+++ b/client/wallet.c
@@ -216,8 +216,12 @@ main(int argc, char *argv[])
if (!remctl_open(r, options.server, options.port, options.principal))
die("%s", remctl_error(r));
- /* Most commands, we handle ourselves, but get commands are special and
- keytab get commands with -f are doubly special. */
+ /* Most commands, we handle ourselves, but get and store commands are
+ special and keytab get commands with -f are doubly special. */
+ if (strcmp(argv[0], "get") == 0 || strcmp(argv[0], "store") == 0) {
+ if (!object_exists(r, options.type, argv[1], argv[2]))
+ object_autocreate(r, options.type, argv[1], argv[2]);
+ }
if (strcmp(argv[0], "get") == 0) {
if (argc > 3)
die("too many arguments");
diff --git a/client/wallet.pod b/client/wallet.pod
index 10c44ba..3f2ca51 100644
--- a/client/wallet.pod
+++ b/client/wallet.pod
@@ -261,6 +261,10 @@ by <type> and <name>, or stores it in a file if the B<-f> option was
given. This may trigger generation of new data and invalidate old data
for that object depending on the object type.
+If an object with type <type> and name <name> does not already exist when
+this command is issued (as checked with the exists interface), B<wallet>
+will attempt to automatically create it (using autocreate).
+
=item getacl <type> <name> <acl>
Prints the ACL <acl>, which must be one of C<get>, C<store>, C<show>,
@@ -329,6 +333,10 @@ 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.
+If an object with type <type> and name <name> does not already exist when
+this command is issued (as checked with the exists interface), B<wallet>
+will attempt to automatically create it (using autocreate).
+
=back
=head1 ATTRIBUTES
diff --git a/tests/client/basic-t.in b/tests/client/basic-t.in
index 807d9e9..67d7a3a 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=30
+total=31
count=1
echo "$total"
@@ -78,7 +78,8 @@ if [ -z "$krb5conf" ] ; then
fi
# Make sure everything's clean.
-rm -f output output.bak keytab keytab.bak srvtab srvtab.bak sync-kaserver
+rm -f output output.bak keytab keytab.bak srvtab srvtab.bak sync-kaserver \
+ autocreated
# Now, we can finally run our tests. First, basic operations.
runsuccess "" "$wallet" -k "$principal" -p 14373 -s localhost -c fake-wallet \
@@ -93,6 +94,11 @@ if [ -f output.bak ] || [ -f output.new ] ; then
else
printcount "ok"
fi
+if [ -f autocreated ] ; then
+ printcount "ok"
+else
+ printcount "not ok"
+fi
runsuccess "" "$wallet" -k "$principal" -p 14373 -s localhost -c fake-wallet \
-f output get file fake-test
if cmp output data/fake-data >/dev/null 2>&1 ; then
@@ -220,7 +226,7 @@ runsuccess "Expiration date of keytab service/fake-test" \
# Clean up.
KRB5_CONFIG=
rm krb5.conf
-rm -f data/test.cache
+rm -f autocreated data/test.cache
if [ -f data/pid ] ; then
kill `cat data/pid`
rm -f data/pid
diff --git a/tests/data/cmd-fake b/tests/data/cmd-fake
index a8d979a..17bbb90 100755
--- a/tests/data/cmd-fake
+++ b/tests/data/cmd-fake
@@ -67,6 +67,41 @@ setattr)
;;
esac
;;
+exists)
+ if [ -n "$2" ] ; then
+ echo "Too many arguments" >&2
+ exit 1
+ fi
+ case "${type}:${1}" in
+ file:fake-test)
+ if [ -f autocreated ] ; then
+ echo 'yes'
+ else
+ echo 'no'
+ fi
+ ;;
+ *)
+ echo 'yes'
+ ;;
+ esac
+ exit 0
+ ;;
+autocreate)
+ if [ -n "$2" ] ; then
+ echo "Too many arguments" >&2
+ exit 1
+ fi
+ case "${type}:${1}" in
+ file:fake-test)
+ touch autocreated
+ exit 0
+ ;;
+ *)
+ echo "Autocreate called for existing object" >&2
+ exit 1
+ ;;
+ esac
+ ;;
get)
if [ -n "$2" ] ; then
echo "Too many arguments" >&2