diff options
author | Russ Allbery <rra@stanford.edu> | 2010-02-21 17:45:55 -0800 |
---|---|---|
committer | Russ Allbery <rra@stanford.edu> | 2010-02-21 17:45:55 -0800 |
commit | 60210334fa3dbd5dd168199063c6ee850d750d0c (patch) | |
tree | 31e832ba6788076075d38e20ffd27ebf09430407 /kasetkey/kasetkey.c | |
parent | e571a8eb96f42de5a114cf11ff1c3d63e5a8d301 (diff) |
Imported Upstream version 0.10
Diffstat (limited to 'kasetkey/kasetkey.c')
-rw-r--r-- | kasetkey/kasetkey.c | 583 |
1 files changed, 0 insertions, 583 deletions
diff --git a/kasetkey/kasetkey.c b/kasetkey/kasetkey.c deleted file mode 100644 index d40a9bb..0000000 --- a/kasetkey/kasetkey.c +++ /dev/null @@ -1,583 +0,0 @@ -/* $Id$ - * - * Create or change a principal and/or generate a srvtab. - * - * Sets the key of a principal in the AFS kaserver given a srvtab, enables or - * disables a principal, or displays information about a principal in an AFS - * kaserver. - * - * Written by Roland Schemers <schemers@stanford.edu> - * Updated by Russ Allbery <rra@stanford.edu> - * Updated again by Anton Ushakov <antonu@stanford.edu> - * Copyright 1994, 1998, 1999, 2000, 2006, 2007, 2008 - * Board of Trustees, Leland Stanford Jr. University - * - * See LICENSE for licensing terms. - */ - -#include <config.h> -#include <portable/system.h> - -#include <errno.h> -#include <fcntl.h> -#include <sys/stat.h> - -#ifdef HAVE_KERBEROSIV_KRB_H -# include <kerberosIV/krb.h> -#else -# include <krb.h> -#endif - -#include <afs/stds.h> -#include <afs/kauth.h> -#include <afs/kautils.h> -#include <afs/cellconfig.h> -#include <ubik.h> - -#include <util/util.h> - -/* Normally set by the AFS libraries. */ -#ifndef SNAME_SZ -# define SNAME_SZ 40 -# define INST_SZ 40 -# define REALM_SZ 40 -#endif - -/* - * AFS currently doesn't prototype this function. Cheat on the first argument - * since it actually takes a function with a completely variable argument - * list. - */ -#if !HAVE_DECL_UBIK_CALL -afs_int32 ubik_Call(void *, struct ubik_client *, afs_int32, ...); -#endif - -/* 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. */ - int tgs; /* Enable the principal. */ - int notgs; /* Disable the princial. */ - 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; /* Principal to create/enable. */ - char *delete; /* Principal to delete. */ - char *examine; /* Principal to examine. */ - 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 service Name of service to delete\n\ - -d Turn on debugging\n\ - -e principal Examine the given principal\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\ - -n Set the principal NOTGS\n\ - -p password Use given password to create key\n\ - -r Use random key\n\ - -s service Name of service to create\n\ - -t Set the principal TGS\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\ -\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"; - - -/* - * 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) -{ - if (program == NULL) - program = ""; - fprintf((status == 0) ? stdout : stderr, usage_message, - program, program, program, program); - exit(status); -} - - -/* - * Parse a principal name into name, inst, and cell, filling in the cell from - * local_cell if none was given. cell here is actually a realm and shouldn't - * need any further conversion. - */ -static void -parse_principal(struct config *config, char *principal, char *name, - char *inst, char *cell) -{ - long code; - int local; - - code = ka_ParseLoginName(principal, name, inst, cell); - if (config->debug) - printf("ka_ParseLoginName %ld\n", code); - if (code != 0) - die("can't parse principal %s", principal); - if (cell[0] == '\0') { - if (ka_CellToRealm(config->local_cell, cell, &local) == KANOCELL) - die("unable to determine realm from local cell"); - } -} - - -/* - * 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) -{ - int fd; - - 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) != (ssize_t) strlen(name) + 1) - sysdie("can't write to srvtab %s", filename); - if (write(fd, inst, strlen(inst) + 1) != (ssize_t) strlen(inst) + 1) - sysdie("can't write to srvtab %s", filename); - if (write(fd, cell, strlen(cell) + 1) != (ssize_t) strlen(cell) + 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); -} - - -/* - * 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; - 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"); - } - - /* 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); -} - - -/* - * 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) -{ - 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\n", code); - if (code != 0) - die("can't get key for %s.%s@%s from srvtab %s", name, inst, - cell, 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"); - } - - /* 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"); -} - - -/* - * Delete a principal out of the AFS kaserver. - */ -static void -delete_principal(struct config *config) -{ - 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); - parse_principal(config, config->delete, name, inst, cell); - code = ka_AuthServerConn(cell, KA_MAINTENANCE_SERVICE, &token, &conn); - if (config->debug) - printf("ka_AuthServerConn %s %ld\n", cell, code); - if (code != 0) - die("can't make connection to auth server"); - - /* Delete the user. */ - 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); -} - - -/* - * Format a date. The output format expects ctime-style date formatting, so - * we use that. Takes a buffer into which to put the date. There will be a - * trailing newline. - */ -static void -format_date(char *buffer, size_t size, time_t date) -{ - if (date == (time_t) NEVERDATE) - strlcpy(buffer, "never\n", size); - else - strlcpy(buffer, ctime(&date), size); -} - - -/* - * Enable or disable a principal in the AFS kaserver (by setting or clearing - * the NOTGS flag). The second argument says to enable if it's true, disable - * otherwise. - */ -static void -enable_principal(struct config *config, int enable) -{ - struct ktc_token token; - struct ubik_client *conn; - struct kaentryinfo entry; - char name[MAXKTCNAMELEN]; - char inst[MAXKTCNAMELEN]; - char cell[MAXKTCNAMELEN]; - long code; - - /* Make connection to AuthServer. */ - authenticate(config, &token); - parse_principal(config, config->service, name, inst, cell); - code = ka_AuthServerConn(cell, KA_MAINTENANCE_SERVICE, &token, &conn); - if (config->debug) - printf("ka_AuthServerConn %s %ld\n", cell, code); - if (code != 0) - die("can't make connection to auth server"); - - /* Retrieve the principal information. */ - code = ubik_Call(KAM_GetEntry, conn, 0, name, inst, KAMAJORVERSION, - &entry); - if (config->debug) - printf("ubik_Call KAM_GetEntry %ld\n", code); - if (code != 0) - die("can't retrieve current flags"); - - /* Set the flags. */ - if (enable) - entry.flags &= ~KAFNOTGS; - else - entry.flags |= KAFNOTGS; - code = ubik_Call(KAM_SetFields, conn, 0, name, inst, entry.flags, 0, 0, - -1, 0, 0); - if (config->debug) - printf("ubik_Call KAM_SetFields %ld\n", code); - if (code != 0) - die("can't %s principal", enable ? "enable" : "disable"); - code = ubik_ClientDestroy(conn); - exit(0); -} - - -/* - * Examine a principal. The output format is compatible with the old Stanford - * Kerberos v4 kadmin, which may be compatible with Kerberos v4 kadmin in - * general (I haven't checked). - */ -static void -examine_principal(struct config *config) -{ - struct ktc_token token; - struct ubik_client *conn; - struct kaentryinfo entry; - char name[MAXKTCNAMELEN]; - char inst[MAXKTCNAMELEN]; - char cell[MAXKTCNAMELEN]; - long code; - char edate[64], cdate[64], mdate[64]; - - /* Make connection to AuthServer. */ - authenticate(config, &token); - parse_principal(config, config->examine, name, inst, cell); - code = ka_AuthServerConn(cell, KA_MAINTENANCE_SERVICE, &token, &conn); - if (config->debug) - printf("ka_AuthServerConn %s %ld\n", cell, code); - if (code != 0) - die("can't make connection to auth server"); - - /* Retrieve and format the entry. */ - code = ubik_Call(KAM_GetEntry, conn, 0, name, inst, KAMAJORVERSION, - &entry); - if (config->debug) - printf("ubik_Call KAM_GetEntry %ld\n", code); - if (code != 0) { - if (code == KANOENT) - die("no such entry in the database"); - else - die("can't retrieve principal information"); - } - format_date(edate, sizeof(edate), entry.user_expiration); - format_date(mdate, sizeof(cdate), entry.modification_time); - format_date(cdate, sizeof(mdate), entry.change_password_time); - printf("status: %s\n", (entry.flags & KAFNOTGS) ? "disabled" : "enabled"); - printf("account expiration: %s", edate); - printf("password last changed: %s", cdate); - printf("modification time: %s", mdate); - printf("modified by: %s%s%s\n", entry.modification_user.name, - (entry.modification_user.instance[0] != '\0') ? "." : "", - entry.modification_user.instance); - code = ubik_ClientDestroy(conn); - exit(0); -} - - -/* - * 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). - */ -static void -generate_srvtab(struct config *config) -{ - 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); - parse_principal(config, config->service, name, inst, cell); - code = ka_AuthServerConn(cell, KA_MAINTENANCE_SERVICE, &token, &conn); - if (config->debug) - printf("ka_AuthServerConn %s %ld\n", cell, code); - if (code != 0) - die("can't make connection to auth server"); - - /* Get the key for the principal we're creating. */ - 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. */ - p = buffer; - 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("ubik_Call KAM_GetRandomKey %ld\n", code); - if (code != 0) - die("can't get random key"); - } else { - code = ka_ReadPassword((char *) "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) { - unsigned char kvno = 0; - - /* 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); -} - - -int -main(int argc, char *argv[]) -{ - long code; - int opt; - struct config config; - - /* Initialize, get our local cell, etc. */ - memset(&config, 0, sizeof(config)); - 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:de:f:hik:np:rs:tv")) != 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 'e': config.examine = optarg; break; - case 'f': config.srvtab = optarg; break; - case 'i': config.init = 1; break; - case 'k': config.keyfile = optarg; break; - case 'n': config.notgs = 1; break; - case 'p': config.password = optarg; break; - case 'r': config.random = 1; break; - case 's': config.service = optarg; break; - case 't': config.tgs = 1; break; - - /* Usage doesn't return. */ - case 'h': - usage(0); - case 'v': - printf("kasetkey %s\n", PACKAGE_VERSION); - exit(0); - default: - usage(1); - } - } - - /* Take the right action. */ - if (config.random && config.k5srvtab) - usage(1); - if (config.notgs && config.tgs) - die("cannot set principal both TGS and NOTGS at the same time"); - if ((config.notgs || config.tgs) && config.service == NULL) - die("must specify a principal with -s"); - if (config.debug) - fprintf(stdout, "cell: %s\n", config.local_cell); - if (config.init) - initialize_admin_srvtab(&config); - else if (config.tgs || config.notgs) - enable_principal(&config, config.tgs); - else if (config.examine != NULL) - examine_principal(&config); - else if (config.service != NULL) - generate_srvtab(&config); - else if (config.delete != NULL) - delete_principal(&config); - else - usage(1); - exit(0); -} |