diff options
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); +} | 
