aboutsummaryrefslogtreecommitdiff
path: root/kasetkey
diff options
context:
space:
mode:
Diffstat (limited to 'kasetkey')
-rw-r--r--kasetkey/kasetkey.c744
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);
+}