diff options
author | Russ Allbery <rra@stanford.edu> | 2007-10-05 00:16:26 +0000 |
---|---|---|
committer | Russ Allbery <rra@stanford.edu> | 2007-10-05 00:16:26 +0000 |
commit | dbe948ca3ebdad97f4f2096f6074623fc2a8e3c8 (patch) | |
tree | ab0cd9bd84b5402df10da91deefc5354a1b3a73c | |
parent | a78a2615ae535839700b48d200a097c1c62021be (diff) |
Pull the file writing code for the wallet client into a separate file
so that the srvtab and keytab management can share it. Write atomically
to a new file and then link and rename to do an atomic update. Leave a
backup copy of any file that's replaced.
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | TODO | 13 | ||||
-rw-r--r-- | client/file.c | 50 | ||||
-rw-r--r-- | client/internal.h | 30 | ||||
-rw-r--r-- | client/srvtab.c | 11 | ||||
-rw-r--r-- | client/wallet.c | 11 | ||||
-rw-r--r-- | tests/client/basic-t.in | 16 |
7 files changed, 80 insertions, 55 deletions
diff --git a/Makefile.am b/Makefile.am index b433f6d..e49ba62 100644 --- a/Makefile.am +++ b/Makefile.am @@ -27,8 +27,8 @@ util_libutil_a_SOURCES = util/concat.c util/messages.c util/util.h \ bin_PROGRAMS = client/wallet sbin_PROGRAMS = kasetkey/kasetkey sbin_SCRIPTS = server/keytab-backend server/wallet-backend -client_wallet_SOURCES = client/internal.h client/srvtab.c client/wallet.c \ - system.h +client_wallet_SOURCES = client/file.c client/internal.h client/srvtab.c \ + client/wallet.c system.h client_wallet_CPPFLAGS = @REMCTL_CPPFLAGS@ client_wallet_LDFLAGS = @REMCTL_LDFLAGS@ client_wallet_LDADD = util/libutil.a portable/libportable.a -lremctl -lkrb5 @@ -9,10 +9,6 @@ Required to replace leland_srvtab: enctype attribute on the object and include the enctypes in the object show display. -* Write new files atomically in the wallet client and save backups unless - told not to (write to file.new, link the old file to file.old, and do - an atomic rename). - * Add support to the test suite for specifying a different database than SQLite for testing. For MySQL and other database types that we can't just delete, also requires adding a method to Wallet::Schema to drop all @@ -50,6 +46,9 @@ Future work: * Add a help function to wallet-backend listing the commands. +* The client may not compile against Heimdal due to changes in how the + krb5_keyblock structure is laid out. Check and fix. + * Rewrite the client test suite to use Perl and to make better use of shared code so that it can be broken into function components. @@ -152,12 +151,12 @@ Future work: * Add support for enforcing a naming policy through another policy function. -* Add readline support to the wallet client to make it easier to issue - multiple commands. - * The keytab backend currently only supports MIT Kerberos. Add support for Heimdal. +* Add readline support to the wallet client to make it easier to issue + multiple commands. + * The wallet-backend and wallet documentation share the COMMANDS section. Work out some means to assemble the documentation without duplicating content. diff --git a/client/file.c b/client/file.c new file mode 100644 index 0000000..621b49d --- /dev/null +++ b/client/file.c @@ -0,0 +1,50 @@ +/* $Id$ +** +** File 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 <fcntl.h> + +#include <client/internal.h> +#include <util/util.h> + +/* +** 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. +*/ +void +write_file(const char *name, const void *data, size_t length) +{ + int fd; + ssize_t status; + char *temp, *backup; + + temp = concat(name, ".new", (char *) 0); + backup = concat(name, ".bak", (char *) 0); + fd = open(temp, O_WRONLY | O_CREAT | O_TRUNC, 0600); + if (fd < 0) + sysdie("open of %s failed", temp); + status = write(fd, data, length); + if (status < 0) + sysdie("write to %s failed", temp); + else if (status != (ssize_t) length) + die("write to %s truncated", temp); + if (close(fd) < 0) + sysdie("close of %s failed (file probably truncated)", temp); + if (access(name, F_OK) == 0) + if (link(name, backup) < 0) + sysdie("link of %s to %s failed", name, backup); + if (rename(temp, name) < 0) + sysdie("rename of %s to %s failed", temp, name); + free(temp); + free(backup); +} diff --git a/client/internal.h b/client/internal.h index 834ec57..186d83f 100644 --- a/client/internal.h +++ b/client/internal.h @@ -11,29 +11,8 @@ #ifndef CLIENT_INTERNAL_H #define CLIENT_INTERNAL_H 1 -/* __attribute__ is available in gcc 2.5 and later, but only with gcc 2.7 - could you use the __format__ form of the attributes, which is what we use - (to avoid confusion with other macros). */ -#ifndef __attribute__ -# if __GNUC__ < 2 || (__GNUC__ == 2 && __GNUC_MINOR__ < 7) -# define __attribute__(spec) /* empty */ -# endif -#endif - -/* Used for unused parameters to silence gcc warnings. */ -#define UNUSED __attribute__((__unused__)) - -/* BEGIN_DECLS is used at the beginning of declarations so that C++ - compilers don't mangle their names. END_DECLS is used at the end. */ -#undef BEGIN_DECLS -#undef END_DECLS -#ifdef __cplusplus -# define BEGIN_DECLS extern "C" { -# define END_DECLS } -#else -# define BEGIN_DECLS /* empty */ -# define END_DECLS /* empty */ -#endif +#include <sys/types.h> +#include <util/util.h> /* Temporary until we have some real configuration. */ #ifndef SERVER @@ -45,6 +24,11 @@ BEGIN_DECLS +/* 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. */ +void write_file(const char *name, const void *data, size_t length); + /* Given a srvtab file, the Kerberos v5 principal, and the keytab file, write a srvtab file for the corresponding Kerberos v4 principal. */ void write_srvtab(const char *srvtab, const char *principal, diff --git a/client/srvtab.c b/client/srvtab.c index b50193e..68a2618 100644 --- a/client/srvtab.c +++ b/client/srvtab.c @@ -148,14 +148,5 @@ write_srvtab(const char *srvtab, const char *principal, const char *keytab) krb5_free_keytab_entry_contents(ctx, &entry); /* Write out the srvtab file. */ - fd = open(srvtab, O_WRONLY | O_CREAT | O_TRUNC, 0600); - if (fd < 0) - sysdie("open of %s failed", srvtab); - status = write(fd, data, length); - if (status < 0) - sysdie("write to %s failed", srvtab); - else if (status != (ssize_t) length) - die("write to %s truncated", srvtab); - if (close(fd) < 0) - sysdie("close of %s failed (file probably truncated)", srvtab); + write_file(srvtab, data, length); } diff --git a/client/wallet.c b/client/wallet.c index e3ca4dd..998ec30 100644 --- a/client/wallet.c +++ b/client/wallet.c @@ -140,16 +140,7 @@ main(int argc, char *argv[]) fprintf(stderr, "wallet: "); fwrite(result->stderr_buf, 1, result->stderr_len, stderr); } else if (file != NULL && strcmp(command[1], "get") == 0) { - fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, 0600); - if (fd < 0) - sysdie("open of %s failed", file); - status = write(fd, result->stdout_buf, result->stdout_len); - if (status < 0) - sysdie("write to %s failed", file); - else if (status != (ssize_t) result->stdout_len) - die("write to %s truncated", file); - if (close(fd) < 0) - sysdie("close of %s failed (file probably truncated)", file); + write_file(file, result->stdout_buf, result->stdout_len); if (srvtab != NULL) write_srvtab(srvtab, command[3], file); } else { diff --git a/tests/client/basic-t.in b/tests/client/basic-t.in index 50a4ab5..6b05a3a 100644 --- a/tests/client/basic-t.in +++ b/tests/client/basic-t.in @@ -54,7 +54,7 @@ runfailure () { } # Print the number of tests. -echo 10 +echo 12 # Find the client program. if [ -f ../data/test.keytab ] ; then @@ -65,7 +65,7 @@ else fi fi if [ ! -f data/test.keytab ] || [ -z "@REMCTLD@" ] ; then - for n in 1 2 3 4 5 6 7 8 9 10 ; do + for n in 1 2 3 4 5 6 7 8 9 10 11 12 ; do echo ok $n \# skip -- no Kerberos configuration done exit 0 @@ -125,10 +125,14 @@ done runsuccess "" -c fake-wallet get keytab -f keytab service/fake-test if cmp keytab data/fake-data >/dev/null 2>&1 ; then printcount "ok" - rm keytab else printcount "not ok" fi +if [ -f keytab.bak ] || [ -f keytab.new ] ; then + printcount "not ok" +else + printcount "ok" +fi runsuccess "" -c fake-wallet get keytab -f keytab -S srvtab service/fake-srvtab if cmp keytab data/fake-keytab >/dev/null 2>&1 ; then printcount "ok" @@ -136,6 +140,12 @@ if cmp keytab data/fake-keytab >/dev/null 2>&1 ; then else printcount "not ok" fi +if cmp keytab.bak data/fake-data >/dev/null 2>&1 ; then + printcount "ok" + rm keytab.bak +else + printcount "not ok" +fi if [ -n "$krb5conf" ] ; then if cmp srvtab data/fake-srvtab >/dev/null 2>&1 ; then printcount "ok" |