diff options
author | Russ Allbery <rra@stanford.edu> | 2007-03-07 08:49:14 +0000 |
---|---|---|
committer | Russ Allbery <rra@stanford.edu> | 2007-03-07 08:49:14 +0000 |
commit | b0e732ad807d10c84ba81ca5afcefc2c0f184f9c (patch) | |
tree | 15b763e53fce73701e21ac69f0bb853aaadbc833 /kasetkey | |
parent | 2ea4c462ab9c90be240f7c5e28c2f8c0f4d3a17c (diff) |
Redo the coding style of kasetkey and factor out common code.
Authenticate via a srvtab instead of a DES key to make management of
the key used by kasetkey easier.
Diffstat (limited to 'kasetkey')
-rw-r--r-- | kasetkey/kasetkey.c | 744 |
1 files changed, 410 insertions, 334 deletions
diff --git a/kasetkey/kasetkey.c b/kasetkey/kasetkey.c index 0e5878f..1d927e9 100644 --- a/kasetkey/kasetkey.c +++ b/kasetkey/kasetkey.c @@ -5,7 +5,7 @@ ** Written by Roland Schemers <schemers@stanford.edu> ** Updated by Russ Allbery <rra@stanford.edu> ** Updated again by AAU, Anton Ushakov <antonu@stanford.edu> -** Copyright 1994, 1998-2000, 2006 +** Copyright 1994, 1998, 1999, 2000, 2006, 2007 ** Board of Trustees, Leland Stanford Jr. University ** ** Sets the key of a principal in the AFS kaserver given a srvtab. This @@ -22,373 +22,449 @@ #include <unistd.h> #include <afs/stds.h> +#include <afs/kauth.h> #include <afs/kautils.h> #include <afs/cellconfig.h> -void crash_and_burn(char *message); -void errno_crash_and_burn(char *message); -void usage(void); -void do_init_key_file(void); -void do_service(void); - +/* Normally set by the AFS libraries. */ #ifndef SNAME_SZ # define SNAME_SZ 40 # define INST_SZ 40 # define REALM_SZ 40 #endif -#define VERSION "2.0" - -char *prog; /* duh */ -char *local_cell; /* duh^2 */ -int o_debug=0; /* turn on debugging */ -int o_init=0; /* intialize keyfile */ -int o_random=0; /* use random DES key */ +#define VERSION "3.0" + +/* The name of the program, for error reporting. */ +static const char *program = NULL; + +/* Some global state information. */ +struct config { + char *local_cell; + int debug; /* Whether to enable debugging. */ + int init; /* Keyfile initialization. */ + int random; /* Randomize the key. */ + char *keyfile; /* Name of srvtab to use. */ + char *admin; /* Name of ADMIN user to use. */ + char *password; /* Password to use. */ + char *srvtab; /* srvtab file to generate. */ + char *service; /* Service principal to create. */ + char *delete; /* Service principal to delete. */ + char *k5srvtab; /* K5 converted srvtab to read for key. */ +}; + +/* Usage message. Pass in the program name four times. */ +static const char usage_message[] = "\ +Usage: %s [options]\n\ + -a adminuser Admin user\n\ + -c k5srvtab Use the key from the given srvtab (for sync w/ K5)\n\ + -d turn on debugging\n\ + -f srvtab Name of srvtab file to create\n\ + -h This help\n\ + -i Initialize DES key file\n\ + -k keyfile File containing srvtab for admin user\n\ + -p password Use given password to create key\n\ + -r Use random key\n\ + -s service Name of service to create\n\ + -v Print version\n\ +\n\ +To create a srvtab for rcmd.slapshot and be prompted for the admin\n\ +passowrd:\n\ +\n\ + %s -f srvtab.rcmd.slapshot -s rcmd.slapshot -r\n\ +\n\ +To create a srvtab from within a script you must stash the DES key\n\ +in a srvtab with:\n\ + %s -a admin -i -k /.adminkey\n\ +\n\ +and then create a srvtab for rcmd.slapshot with:\n\ +\n\ + %s -k /.adminkey -a admin -r -f srvtab -s rcmd.slapshot\n\ +\n"; + + +/* Report a fatal error. */ +static void +die(const char *format, ...) +{ + va_list args; + + if (program != NULL) + fprintf(stderr, "%s: ", program); + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, "\n"); + exit(1); +} -char *o_keyfile = NULL; /* name of DES key file to use */ -char *o_admin = NULL; /* name of ADMIN user to use */ -char *o_pass = NULL; /* password to use (else random or prompted) */ -char *o_srvtab = NULL; /* srvtab file to generate */ -char *o_service = NULL; /* service to create */ -char *o_delete = NULL; /* service to delete */ -char *o_k5srvtab = NULL; /* converted keytab from K5 */ -int -main(int argc, char *argv[]) +/* Report a fatal error, including strerror information. */ +static void +sysdie(const char *format, ...) { - long code; - int c; - - /* initialize, get our local cell, etc */ - prog = argv[0]; - code = ka_Init(0); - local_cell = ka_LocalCell(); - if (o_debug) fprintf(stdout,"cell: %s\n", local_cell); - - if (!local_cell || code) crash_and_burn("can't initialize"); - - /* for production, remove the -d debugging option*/ - while ((c = getopt(argc, argv, "a:hk:is:p:f:rdD:vc:")) != EOF) { - switch(c) { - case 'k': o_keyfile = optarg; break; - case 'i': o_init = 1; break; - case 'a': o_admin = optarg; break; - case 'r': o_random = 1; break; - case 'p': o_pass = optarg; break; - case 'f': o_srvtab = optarg; break; - case 's': o_service = optarg; break; - case 'd': o_debug = 1; break; - case 'c': o_k5srvtab = optarg; break; - case 'D': o_delete = optarg; break; - case 'v': fprintf(stderr,"%s: version %s\n",prog,VERSION); exit(0); - case 'h': - default: usage(); /* usage doesn't return */ - } - } - - if (o_random && o_k5srvtab) - usage(); - - if (o_init) do_init_key_file(); - else if (o_service) do_service(); - else if (o_delete) do_delete(); - else usage(); - - return 0; + int oerrno; + va_list args; + + oerrno = errno; + if (program != NULL) + fprintf(stderr, "%s: ", program); + va_start(args, format); + vfprintf(stderr, format, args); + va_end(args); + fprintf(stderr, ": %s\n", strerror(oerrno)); + exit(1); } -void -do_init_key_file(void) + +/* + * Print out the usage message and then exit with the status given as the only + * argument. If status is zero, the message is printed to standard output; + * otherwise, it is sent to standard error. + */ +static void +usage(int status) { - struct ktc_encryptionKey key; - char name[MAXKTCNAMELEN]; - char inst[MAXKTCNAMELEN]; - char cell[MAXKTCNAMELEN]; - long code; - int kfd; + if (program == NULL) + program = ""; + fprintf((status == 0) ? stdout : stderr, usage_message, + program, program, program, program); + exit(status); +} - if (!o_keyfile) usage(); - if (!o_admin) o_admin = (char*)getlogin(); +/* + * Parse a principal name into name, inst, and cell, filling in the cell from + * local_cell if none was given. + */ +static void +parse_principal(struct config *config, const char *principal, char *name, + char *inst, char *cell) +{ + long code; + + code = ka_ParseLoginName(config->admin, name, inst, cell); + if (config->debug) + printf("ka_ParseLoginName %ld\n", code); + if (code != 0) + die("can't parse admin name"); + if (cell[0] == '\0') { + strncpy(cell, config->local_cell, MAXKTCREALMLEN - 1); + cell[MAXKTCREALMLEN - 1] = '\0'; + } +} - code = ka_ParseLoginName(o_admin, name, inst, cell); - if (o_debug) printf("ka_ParseLoginName %ld\n",code); - if (code) crash_and_burn("can't parse admin name"); - if (cell[0]=='\0') strcpy(cell, local_cell); - - if (o_pass) { - ka_StringToKey(o_pass, cell, &key); - memset(o_pass, 0, strlen(o_pass)); - } else { - char buffer[MAXKTCNAMELEN*3+40]; - sprintf(buffer,"password for %s: ",o_admin); - code = ka_ReadPassword(buffer, 1, cell, &key); - if (code) crash_and_burn("can't read password"); - } - - unlink(o_keyfile); /* remove it if it exists */ - kfd = open(o_keyfile, O_WRONLY | O_CREAT, 0600); - if (kfd == -1) errno_crash_and_burn("can't open keyfile"); - - if (write(kfd, &key, sizeof(key)) != sizeof(key)) { - errno_crash_and_burn("write keyfile"); - } - if (close(kfd)!=0) errno_crash_and_burn("close keyfile"); - - exit(0); + +/* + * Given a srvtab file name, the principal, the kvno, and the key, write out a + * new srvtab file. Dies on any error. + */ +static void +write_srvtab(const char *filename, const char *name, const char *inst, + char *cell, unsigned char kvno, struct ktc_encryptionKey *key) +{ + char realm[MAXKTCREALMLEN]; + int fd, local; + + if (ka_CellToRealm(cell, realm, &local) == KANOCELL) + die("unable to determine realm"); + fd = open(filename, O_WRONLY | O_CREAT, 0600); + if (fd == -1) + sysdie("can't create srvtab %s", filename); + if (write(fd, name, strlen(name) + 1) != strlen(name) + 1) + sysdie("can't write to srvtab %s", filename); + if (write(fd, inst, strlen(inst) + 1) != strlen(inst) + 1) + sysdie("can't write to srvtab %s", filename); + if (write(fd, realm, strlen(realm) + 1) != strlen(realm) + 1) + sysdie("can't write to srvtab %s", filename); + if (write(fd, &kvno, 1) != 1) + sysdie("can't write to srvtab %s", filename); + if (write(fd, key, sizeof(*key)) != sizeof(*key)) + sysdie("can't write to srvtab %s", filename); + if (close(fd) != 0) + sysdie("can't close srvtab %s", filename); } -void -do_delete(void) + +/* + * Initialize a DES keyfile from a password. If the password wasn't given via + * a command-line option, prompt for it. + */ +static void +initialize_admin_srvtab(struct config *config) { - struct ktc_encryptionKey key; - struct ktc_token token; - struct ubik_client *conn; - long code; - char name[MAXKTCNAMELEN]; - char inst[MAXKTCNAMELEN]; - char cell[MAXKTCNAMELEN]; - - if (!o_admin) o_admin = (char*)getlogin(); - - code = ka_ParseLoginName(o_admin, name, inst, cell); - if (o_debug) printf("ka_ParseLoginName %ld\n",code); - if (code) crash_and_burn("can't parse admin name"); - if (cell[0]=='\0') strcpy(cell, local_cell); - - if (o_keyfile) { - int kfd; - kfd = open(o_keyfile, O_RDONLY, 0); - if (kfd == -1) errno_crash_and_burn("can't open keyfile"); - if (read(kfd, &key, sizeof(key)) != sizeof(key)) { - errno_crash_and_burn("can't read keyfile"); + struct ktc_encryptionKey key; + char name[MAXKTCNAMELEN]; + char inst[MAXKTCNAMELEN]; + char cell[MAXKTCNAMELEN]; + long code; + + if (config->keyfile == NULL || config->admin == NULL) + usage(1); + + /* Get the password, one way or another. */ + parse_principal(config, config->admin, name, inst, cell); + if (config->password != NULL) { + ka_StringToKey(config->password, cell, &key); + memset(config->password, 0, strlen(config->password)); + } else { + char buffer[MAXKTCNAMELEN * 3 + 40]; + + sprintf(buffer,"password for %s: ", config->admin); + code = ka_ReadPassword(buffer, 1, cell, &key); + if (code != 0) + die("can't read password"); } - close(kfd); - } else { - char buffer[MAXKTCNAMELEN*3+40]; - sprintf(buffer,"password for %s: ",o_admin); - code = ka_ReadPassword(buffer, 0, cell, &key); - if (code) crash_and_burn("can't read password"); - } - - code = ka_GetAdminToken(name, inst, cell, &key, 300, &token, 1); - memset((char*)&key, 0, sizeof(key)); - if (o_debug) printf("ka_GetAdminToken %ld\n",code); - if (code) crash_and_burn("can't get admin token"); - - /* make connection to AuthServer */ - code = ka_AuthServerConn(cell, KA_MAINTENANCE_SERVICE, &token, &conn); - if (o_debug) printf("ka_AuthServerConn %ld\n",code); - if (code) crash_and_burn("can't make connection to auth server"); - - /* do a similar dance on the service principal and key */ - code = ka_ParseLoginName(o_service, name, inst, cell); - if (o_debug) printf("ka_ParseLoginName %ld\n",code); - if (code) crash_and_burn("can't parse service name"); - if (cell[0]=='\0') strcpy(cell, local_cell); - - /* delete the user */ - code = ubik_Call (KAM_DeleteUser, conn, 0, name, inst); - if (o_debug) printf("ubik_Call KAM_DeleteUser %ld\n",code); - if (code && code != KANOENT) - crash_and_burn("can't delete existing instance"); - - code = ubik_ClientDestroy (conn); - exit(0); + + /* Create the admin srvtab, removing any old one if one exists. */ + unlink(config->keyfile); + write_srvtab(config->keyfile, name, inst, cell, 0, &key); + exit(0); } -void -do_service(void) + +/* + * Takes the configuration struct and obtains an admin token, which it stores + * in the second parameter. Dies on any failure. + */ +static void +authenticate(struct config *config, struct ktc_token *token) { - struct ktc_encryptionKey key; - struct ktc_token token; - struct ubik_client *conn; - long code; - char name[MAXKTCNAMELEN]; - char inst[MAXKTCNAMELEN]; - char cell[MAXKTCNAMELEN]; - - /*AAU:*/ - char sbuf[SNAME_SZ * 4]; /* to read in the whole converted srvtab */ - char* sbuf_ptr = sbuf; /* "reading" pointer for parsing the srvtab*/ - char sname[SNAME_SZ]; /* name of service from converted srvtab*/ - char sinst[INST_SZ]; /* instance of service from converted srvtab*/ - char srealm[REALM_SZ]; /* realm of service from converted srvtab*/ - unsigned char kvno; /* key version number from converted srvtab*/ - - if (!o_admin) o_admin = (char*)getlogin(); - - code = ka_ParseLoginName(o_admin, name, inst, cell); - if (o_debug) printf("ka_ParseLoginName %ld\n",code); - if (code) crash_and_burn("can't parse admin name"); - if (cell[0]=='\0') strcpy(cell, local_cell); - - if (o_keyfile) { - int kfd; - kfd = open(o_keyfile, O_RDONLY, 0); - if (kfd == -1) errno_crash_and_burn("can't open keyfile"); - if (read(kfd, &key, sizeof(key)) != sizeof(key)) { - errno_crash_and_burn("can't read keyfile"); + char name[MAXKTCNAMELEN]; + char inst[MAXKTCNAMELEN]; + char cell[MAXKTCNAMELEN]; + long code; + struct ktc_encryptionKey key; + + /* Get the admin password one way or the other. */ + parse_principal(config, config->admin, name, inst, cell); + if (config->keyfile) { + code = read_service_key(name, inst, cell, 0, config->keyfile, + (char *) &key); + if (config->debug) + printf("read_service_key %ld", code); + if (code != 0) + die("can't get key for %s from srvtab %s", config->admin, + config->keyfile); + } else { + char buffer[MAXKTCNAMELEN * 3 + 40]; + + sprintf(buffer, "password for %s: ", config->admin); + code = ka_ReadPassword(buffer, 0, cell, &key); + if (code) + die("can't read password"); } - close(kfd); - } else { - char buffer[MAXKTCNAMELEN*3+40]; - sprintf(buffer,"password for %s: ",o_admin); - code = ka_ReadPassword(buffer, 0, cell, &key); - if (code) crash_and_burn("can't read password"); - } - - code = ka_GetAdminToken(name, inst, cell, &key, 300, &token, 1); - memset((char*)&key, 0, sizeof(key)); - if (o_debug) printf("ka_GetAdminToken %ld\n",code); - if (code) crash_and_burn("can't get admin token"); - - /* make connection to AuthServer */ - code = ka_AuthServerConn(cell, KA_MAINTENANCE_SERVICE, &token, &conn); - if (o_debug) printf("ka_AuthServerConn %ld\n",code); - if (code) crash_and_burn("can't make connection to auth server"); - - /* do a similar dance on the service principal and key */ - - code = ka_ParseLoginName(o_service, name, inst, cell); - if (o_debug) printf("ka_ParseLoginName %ld\n",code); - if (code) crash_and_burn("can't parse service name"); - if (cell[0]=='\0') strcpy(cell, local_cell); - - /*read service principal key from a srvtab, converted from a K5 keytab. AAU*/ - if (o_k5srvtab) { - FILE* ksfd; - ksfd = fopen(o_k5srvtab, "r"); - if (!ksfd) errno_crash_and_burn("can't open converted srvtab"); - - /*must read whole string first: srvtab fields are separated by NULLs, all in one line*/ - if (!(fgets(sbuf, sizeof(sbuf), ksfd))) - errno_crash_and_burn("can't read converted srvtab"); - strncpy(sname, sbuf_ptr, SNAME_SZ -1); - sbuf_ptr = &sbuf_ptr[strlen(sbuf_ptr)+1]; - strncpy(sinst, sbuf_ptr, INST_SZ -1); - sbuf_ptr = &sbuf_ptr[strlen(sbuf_ptr)+1]; - strncpy(srealm, sbuf_ptr, REALM_SZ -1); - sbuf_ptr = &sbuf_ptr[strlen(sbuf_ptr)+1]; - strncpy(&kvno, sbuf_ptr, sizeof(unsigned char)); - strncpy(key.data, sbuf_ptr+sizeof(unsigned char), sizeof(key)); - - fclose(ksfd); - } else if (o_random) { /* get random key */ - code = ubik_Call (KAM_GetRandomKey, conn, 0, &key); - if (o_debug) printf("ka_AuthServerConn %ld\n",code); - if (code) crash_and_burn("can't get random key"); - } else { - code = ka_ReadPassword("service password: ", 1, cell, &key); - if (code) crash_and_burn("can't read password"); - } - - /* try to create principal */ - code = ubik_Call (KAM_CreateUser, conn, 0, name, inst, key); - if (o_debug) printf("ubik_Call KAM_CreateUser %ld\n",code); - - if (code == KAEXIST) { /* need to delete first */ - code = ubik_Call (KAM_DeleteUser, conn, 0, name, inst); - if (o_debug) printf("ubik_Call KAM_DeleteUser %ld\n",code); - if (code) crash_and_burn("can't delete existing instance"); - code = ubik_Call (KAM_CreateUser, conn, 0, name, inst, key); - if (o_debug) printf("ubik_Call KAM_CreateUser %ld\n",code); - if (code) crash_and_burn("can't create user"); - } else if (code) { - crash_and_burn("can't create user"); - } - - code = ubik_ClientDestroy (conn); - - /* create srvtab file */ - if (o_srvtab && !o_k5srvtab) { - char realm[MAXKTCREALMLEN]; - int local; - unsigned char kvno=0; - int sfd; - int nlen, ilen, rlen; - - if (ka_CellToRealm(cell, realm, &local) == KANOCELL) { - crash_and_burn("unable to determine realm"); - } - if (access(o_srvtab,F_OK)==0) { - char backup[MAXPATHLEN]; - sprintf(backup,"%s.bak", o_srvtab); - if (rename(o_srvtab, backup)!=0) { - errno_crash_and_burn("can't create backup srvtab"); - } - } - - sfd = open(o_srvtab, O_WRONLY | O_CREAT, 0600); - if (sfd == -1) errno_crash_and_burn("can't open srvtab"); - - nlen = strlen(name)+1; - ilen = strlen(inst)+1; - rlen = strlen(realm)+1; - - if (write(sfd, name, nlen) != nlen) { - errno_crash_and_burn("write srvtab name"); - } - if (write(sfd, inst, ilen) != ilen) { - errno_crash_and_burn("write srvtab instance"); - } - if (write(sfd, realm, rlen) != rlen) { - errno_crash_and_burn("write srvtab realm"); - } - if (write(sfd, &kvno, sizeof(kvno)) != sizeof(kvno)) { - errno_crash_and_burn("write srvtab kvno"); - } - if (write(sfd, &key, sizeof(key)) != sizeof(key)) { - errno_crash_and_burn("write srvtab key"); - } - if (close(sfd)!=0) errno_crash_and_burn("close srvtab"); - } - memset((char*)&key, 0, sizeof(key)); - memset((char*)&sbuf, 0, sizeof(sbuf)); - exit(0); + + /* Now, get the admin token. */ + code = ka_GetAdminToken(name, inst, cell, &key, 300, token, 1); + memset(&key, 0, sizeof(key)); + if (config->debug) + printf("ka_GetAdminToken %ld\n", code); + if (code != 0) + die("can't get admin token"); } -void -crash_and_burn(char *message) + +/* Delete a principal out of the AFS kaserver. */ +void +delete_principal(struct config *config) { - fprintf(stderr,"%s: %s\n", prog, message); - exit(1); + struct ktc_token token; + struct ubik_client *conn; + char name[MAXKTCNAMELEN]; + char inst[MAXKTCNAMELEN]; + char cell[MAXKTCNAMELEN]; + long code; + + /* Make connection to AuthServer. */ + authenticate(config, &token); + code = ka_AuthServerConn(cell, KA_MAINTENANCE_SERVICE, &token, &conn); + if (config->debug) + printf("ka_AuthServerConn %ld\n", code); + if (code != 0) + die("can't make connection to auth server"); + + /* Delete the user. */ + parse_principal(config, config->service, name, inst, cell); + code = ubik_Call(KAM_DeleteUser, conn, 0, name, inst); + if (config->debug) + printf("ubik_Call KAM_DeleteUser %ld\n", code); + if (code != 0 && code != KANOENT) + die("can't delete existing instance"); + code = ubik_ClientDestroy(conn); + exit(0); } -void -errno_crash_and_burn(char *message) +/* + * Create a new principal in the AFS kaserver (deleting it and recreating it + * if it already exists) with either the indicated key or with a random key, + * and then write out a srvtab for that principal. Also supported is reading + * the key from an existing srvtab (likely created via Kerberos v5 kadmin from + * a keytab). + */ +void +generate_srvtab(struct config *config) { - fprintf(stderr,"%s: %s: %s\n", prog, message, strerror(errno)); - exit(1); + struct ktc_token token; + struct ubik_client *conn; + char name[MAXKTCNAMELEN]; + char inst[MAXKTCNAMELEN]; + char cell[MAXKTCNAMELEN]; + long code; + struct ktc_encryptionKey key; + + /* Make connection to AuthServer. */ + authenticate(config, &token); + code = ka_AuthServerConn(cell, KA_MAINTENANCE_SERVICE, &token, &conn); + if (config->debug) + printf("ka_AuthServerConn %ld\n", code); + if (code != 0) + die("can't make connection to auth server"); + + /* Get the key for the principal we're creating. */ + parse_principal(config, config->service, name, inst, cell); + if (config->k5srvtab != NULL) { + char buffer[SNAME_SZ * 4]; + char *p; + char sname[SNAME_SZ]; + char sinst[INST_SZ]; + char srealm[REALM_SZ]; + unsigned char kvno; + FILE *srvtab; + + /* Read the whole converted srvtab into memory. */ + srvtab = fopen(config->k5srvtab, "r"); + if (srvtab == NULL) + sysdie("can't open converted srvtab %s", config->k5srvtab); + if (fgets(buffer, sizeof(buffer), srvtab) == NULL) + sysdie("can't read converted srvtab %s", config->k5srvtab); + fclose(srvtab); + + /* Now parse it. Fields are delimited by NUL. */ + strncpy(sname, p, SNAME_SZ - 1); + sname[sizeof(sname) - 1] = '\0'; + p += strlen(sname) + 1; + strncpy(sinst, p, INST_SZ - 1); + sinst[sizeof(sinst) - 1] = '\0'; + p += strlen(sinst) + 1; + strncpy(srealm, p, REALM_SZ - 1); + srealm[sizeof(srealm) - 1] = '\0'; + p += strlen(srealm) + 1; + memcpy(&kvno, p, sizeof(unsigned char)); + p += sizeof(unsigned char); + memcpy(key.data, p, sizeof(key)); + memset(buffer, 0, sizeof(buffer)); + } else if (config->random) { + code = ubik_Call(KAM_GetRandomKey, conn, 0, &key); + if (config->debug) + printf("ka_AuthServerConn %ld\n", code); + if (code != 0) + die("can't get random key"); + } else { + code = ka_ReadPassword("service password: ", 1, cell, &key); + if (code != 0) + die("can't read password"); + } + + /* + * Now, we have the key. Try to create the principal. If it already + * exists, try deleting it first and then creating it again. + */ + code = ubik_Call(KAM_CreateUser, conn, 0, name, inst, key); + if (config->debug) + printf("ubik_Call KAM_CreateUser %ld\n", code); + if (code == KAEXIST) { + code = ubik_Call(KAM_DeleteUser, conn, 0, name, inst); + if (config->debug) + printf("ubik_Call KAM_DeleteUser %ld\n", code); + if (code != 0) + die("can't delete existing instance"); + code = ubik_Call(KAM_CreateUser, conn, 0, name, inst, key); + if (config->debug) + printf("ubik_Call KAM_CreateUser %ld\n", code); + } + if (code != 0) + die("can't create user"); + code = ubik_ClientDestroy (conn); + + /* Create the srvtab file. Don't bother if we have a converted one. */ + if (config->srvtab && !config->k5srvtab) { + char realm[MAXKTCREALMLEN]; + int local; + unsigned char kvno = 0; + int sfd; + + if (ka_CellToRealm(cell, realm, &local) == KANOCELL) + die("unable to determine realm"); + + /* Make a backup copy of any existing one, just in case. */ + if (access(config->srvtab, F_OK) == 0) { + char backup[MAXPATHLEN]; + + snprintf(backup, sizeof(backup), "%s.bak", config->srvtab); + if (rename(config->srvtab, backup) != 0) + sysdie("can't create backup srvtab %s", backup); + } + write_srvtab(config->srvtab, name, inst, cell, kvno, &key); + } + memset(&key, 0, sizeof(key)); + exit(0); } -void -usage() + +int +main(int argc, char *argv[]) { - fprintf(stderr,"usage: %s [options]\n",prog); - fprintf(stderr," -k keyfile file containing admin's DES key\n"); - fprintf(stderr," -i initialize DES key file\n"); - fprintf(stderr," -a adminuser admin user\n"); - fprintf(stderr," -r use random key\n"); - fprintf(stderr," -p password use given password to create key\n"); - fprintf(stderr," -c input_srvtab use the key from the given srvtab (for sync w/ K5)\n"); - fprintf(stderr," -f srvtabfile name of srvtab file to create\n"); - fprintf(stderr," -s service name of service to create\n"); - fprintf(stderr," -h this help\n"); - fprintf(stderr," -d turn on debugging\n"); - fprintf(stderr," -v version\n"); - fprintf(stderr,"\n"); - fprintf(stderr," To create a srvtab for rcmd.slapshot and be prompted \n"); - fprintf(stderr," for the admin (i.e, your) password:\n"); - fprintf(stderr,"\n"); - fprintf(stderr," %s -f srvtab.rcmd.slapshot -s rcmd.slapshot -r\n",prog); - fprintf(stderr,"\n"); - fprintf(stderr," To create a srvtab from within a script you must stash the DES key\n"); - fprintf(stderr," someplace then do something like:\n"); - fprintf(stderr,"\n"); - fprintf(stderr," %s -k /.adminkey -a admin -r -f srvtab -s rcmd.slapshot\n",prog); - fprintf(stderr,"\n"); - exit(1); -} + long code; + int opt; + struct config config; + + /* Initialize, get our local cell, etc. */ + memset(&config, 0, sizeof(config)); + program = argv[0]; + code = ka_Init(0); + config.local_cell = ka_LocalCell(); + if (config.local_cell == NULL || code != 0) + die("can't initialize"); + + /* Parse options. */ + while ((opt = getopt(argc, argv, "a:c:D:df:hik:p:rs:v")) != EOF) { + switch (opt) { + case 'a': config.admin = optarg; break; + case 'c': config.k5srvtab = optarg; break; + case 'D': config.delete = optarg; break; + case 'd': config.debug = 1; break; + case 'f': config.srvtab = optarg; break; + case 'i': config.init = 1; break; + case 'k': config.keyfile = optarg; break; + case 'p': config.password = optarg; break; + case 'r': config.random = 1; break; + case 's': config.service = optarg; break; + + /* Usage doesn't return. */ + case 'h': + usage(0); + case 'v': + printf("%s: version %s\n", program, VERSION); + exit(0); + default: + usage(1); + } + } + /* Take the right action. */ + if (config.random && config.k5srvtab) + usage(1); + if (config.debug) + fprintf(stdout,"cell: %s\n", config.local_cell); + if (config.init) + initialize_admin_srvtab(&config); + else if (config.service != NULL) + generate_srvtab(&config); + else if (config.delete != NULL) + delete_principal(&config); + else + usage(1); + exit(0); +} |