diff options
| -rw-r--r-- | client/file.c | 20 | ||||
| -rw-r--r-- | client/internal.h | 25 | ||||
| -rw-r--r-- | client/remctl.c | 53 | ||||
| -rw-r--r-- | client/wallet.c | 34 | ||||
| -rw-r--r-- | tests/client/basic-t.in | 9 | ||||
| -rw-r--r-- | tests/data/basic.conf | 1 | ||||
| -rwxr-xr-x | tests/data/cmd-fake | 9 | 
7 files changed, 100 insertions, 51 deletions
| diff --git a/client/file.c b/client/file.c index c9edf3a..66d5f63 100644 --- a/client/file.c +++ b/client/file.c @@ -115,14 +115,13 @@ get_file(struct remctl *r, const char *prefix, const char *type,  /* - * 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. + * Read all of a file into memory and return the contents in newly allocated + * memory.  Returns the size of the file contents in the second argument if + * it's not NULL.  Handles a file name of "-" to mean standard input.  Dies on + * any failure.   */ -char * -read_file(const char *name) +void * +read_file(const char *name, size_t *length)  {      char *contents;      size_t size, offset; @@ -140,7 +139,7 @@ read_file(const char *name)              sysdie("cannot open file %s", name);          if (fstat(fd, &st) < 0)              sysdie("cannot stat file %s", name); -        size = st.st_size + 1; +        size = st.st_size;          contents = xmalloc(size);      }      offset = 0; @@ -157,8 +156,7 @@ read_file(const char *name)          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"); +    if (length != NULL) +        *length = offset;      return contents;  } diff --git a/client/internal.h b/client/internal.h index 7fe962b..d82196c 100644 --- a/client/internal.h +++ b/client/internal.h @@ -17,6 +17,7 @@  /* Forward declarations to avoid unnecessary includes. */  struct remctl; +struct iovec;  BEGIN_DECLS @@ -29,14 +30,18 @@ void kinit(krb5_context, const char *principal);  void kdestroy(void);  /* - * Given a remctl object, run a remctl command.  If data is non-NULL, saves - * the standard output from the command into data with the length in length. - * Otherwise, prints it to standard output.  Either way, prints standard error - * output and errors to standard error and returns the exit status or 255 for - * a remctl internal error. + * Given a remctl object, either a NULL-terminated array of strings or an + * array of iovecs and the number of elements in the array, and optional data + * and size output variables, run a remctl command.  If data is non-NULL, + * saves the standard output from the command into data with the length in + * length.  Otherwise, prints it to standard output.  Either way, prints + * standard error output and errors to standard error and returns the exit + * status or 255 for a remctl internal error.   */  int run_command(struct remctl *, const char **command, char **data,                  size_t *length); +int run_commandv(struct remctl *, const struct iovec *command, size_t count, +                 char **data, size_t *length);  /*   * Check whether an object exists using the exists wallet interface.  Returns @@ -91,12 +96,12 @@ 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. + * Read all of a file into memory and return the contents in newly allocated + * memory.  Handles a file name of "-" to mean standard input.  Stores the + * length of the data in the second argument if it isn't NULL.  Dies on any + * failure.   */ -char *read_file(const char *); +void *read_file(const char *, size_t *);  END_DECLS diff --git a/client/remctl.c b/client/remctl.c index a4ff097..5a541d5 100644 --- a/client/remctl.c +++ b/client/remctl.c @@ -18,15 +18,14 @@  /* - * Given a remctl connection and a command, run the command. - * - * If data is non-NULL, save the output in it and return the length in length. - * Otherwise, send any output to stdout.  Either way, send error output to - * stderr, and return the exit status (or 255 if there is an error). + * Retrieve the results of a remctl command, which should be issued prior to + * calling this function.  If data is non-NULL, save the output in it and + * return the length in length.  Otherwise, send any output to stdout.  Either + * way, send error output to stderr, and return the exit status (or 255 if + * there is an error).   */ -int -run_command(struct remctl *r, const char **command, char **data, -            size_t *length) +static int +command_results(struct remctl *r, char **data, size_t *length)  {      struct remctl_output *output;      int status = 255; @@ -35,10 +34,6 @@ run_command(struct remctl *r, const char **command, char **data,          *data = NULL;      if (length != NULL)          *length = 0; -    if (!remctl_command(r, command)) { -        warn("%s", remctl_error(r)); -        return 255; -    }      do {          output = remctl_output(r);          switch (output->type) { @@ -74,6 +69,40 @@ run_command(struct remctl *r, const char **command, char **data,  /* + * Given a remctl connection and a NULL-terminated array of strings, run the + * command and return the results using command_results, optionally putting + * output into the data variable. + */ +int +run_command(struct remctl *r, const char **command, char **data, +            size_t *length) +{ +    if (!remctl_command(r, command)) { +        warn("%s", remctl_error(r)); +        return 255; +    } +    return command_results(r, data, length); +} + + +/* + * Given a remctl connection, an array of iovecs, and the length of the array, + * run the command and return the results using command_results, optionally + * putting output into the data variable. + */ +int +run_commandv(struct remctl *r, const struct iovec *command, size_t count, +             char **data, size_t *length) +{ +    if (!remctl_commandv(r, command, count)) { +        warn("%s", remctl_error(r)); +        return 255; +    } +    return command_results(r, data, 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.   */ diff --git a/client/wallet.c b/client/wallet.c index ce0f4e7..dc4fe18 100644 --- a/client/wallet.c +++ b/client/wallet.c @@ -135,7 +135,8 @@ main(int argc, char *argv[])      krb5_error_code retval;      struct options options;      int option, i, status; -    const char **command; +    struct iovec *command; +    size_t count, length;      const char *file = NULL;      const char *srvtab = NULL;      struct remctl *r; @@ -241,24 +242,27 @@ main(int argc, char *argv[])              status = get_file(r, options.type, argv[1], argv[2], file);          }      } else { +        count = argc + 1;          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]; +            else if (argc < 4) +                count++; +        } +        command = xmalloc(sizeof(struct iovec) * count); +        command[0].iov_base = (char *) options.type; +        command[0].iov_len = strlen(options.type); +        for (i = 0; i < argc; i++) { +            command[i + 1].iov_base = argv[i]; +            command[i + 1].iov_len = strlen(argv[i]); +        }          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); +            if (file == NULL) +                file = "-"; +            command[argc + 1].iov_base = read_file(file, &length); +            command[argc + 1].iov_len = length; +        } +        status = run_commandv(r, command, count, NULL, NULL);      }      remctl_close(r);      krb5_free_context(ctx); diff --git a/tests/client/basic-t.in b/tests/client/basic-t.in index 30bc004..1ae3a70 100644 --- a/tests/client/basic-t.in +++ b/tests/client/basic-t.in @@ -50,7 +50,7 @@ if [ $? != 0 ] ; then  elif [ -z '@REMCTLD@' ] ; then      skip_all 'No remctld found'  else -    plan 34 +    plan 36  fi  remctld_start '@REMCTLD@' "$SOURCE/data/basic.conf"  wallet="$BUILD/../client/wallet" @@ -141,6 +141,13 @@ ok_program 'store from a file' 0 '' \      "$wallet" -f store-input store file fake-test  ok '...and the correct data was stored' cmp store-output store-correct  rm -f store-input store-output store-correct +printf 'This is store input\000with a nul character' > store-input +echo 'file fake-nul' > store-correct +cat store-input >> store-correct +ok_program 'store from a file with a nul' 0 '' \ +    "$wallet" -f store-input store file fake-nul +ok '...and the correct data was stored' cmp store-output store-correct +rm -f store-input store-output store-correct  # Test various other client functions and errors.  ok_program 'get output to stdout' 0 'This is a fake keytab.' \ diff --git a/tests/data/basic.conf b/tests/data/basic.conf index 3280ce9..5f3c2a3 100644 --- a/tests/data/basic.conf +++ b/tests/data/basic.conf @@ -1,3 +1,4 @@  # remctl configuration for wallet client tests. +fake-wallet store data/cmd-fake stdin=last ANYUSER  fake-wallet ALL data/cmd-fake ANYUSER diff --git a/tests/data/cmd-fake b/tests/data/cmd-fake index 199bd57..add72fc 100755 --- a/tests/data/cmd-fake +++ b/tests/data/cmd-fake @@ -82,10 +82,15 @@ get)      ;;  store)      if [ -n "$3" ] ; then -        echo "Too many arguments" >&2 +        echo 'Too many arguments' >&2 +        exit 1 +    fi +    if [ -n "$2" ] ; then +        echo 'stdin remctld configuration not supported' >&2          exit 1      fi -    printf "$type $1\n$2" > store-output +    printf "$type $1\n" > store-output +    cat >> store-output      ;;  show)      if [ -n "$2" ] ; then | 
