summaryrefslogtreecommitdiffstats
path: root/src/kadmin/cli/kadmin.c
diff options
context:
space:
mode:
authorMarc Horowitz <marc@mit.edu>1996-07-22 20:49:46 +0000
committerMarc Horowitz <marc@mit.edu>1996-07-22 20:49:46 +0000
commitedf8b4d8a6a665c2aa150993cd813ea6c5cf12e1 (patch)
tree6c2974a97b448c040fa4a31708ec5e02f187526c /src/kadmin/cli/kadmin.c
parent013bb1391582ed9e653ae706e398ddb8d08cfcc9 (diff)
downloadkrb5-edf8b4d8a6a665c2aa150993cd813ea6c5cf12e1.tar.gz
krb5-edf8b4d8a6a665c2aa150993cd813ea6c5cf12e1.tar.xz
krb5-edf8b4d8a6a665c2aa150993cd813ea6c5cf12e1.zip
this commit includes all the changes on the OV_9510_INTEGRATION and
OV_MERGE branches. This includes, but is not limited to, the new openvision admin system, and major changes to gssapi to add functionality, and bring the implementation in line with rfc1964. before committing, the code was built and tested for netbsd and solaris. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@8774 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/kadmin/cli/kadmin.c')
-rw-r--r--src/kadmin/cli/kadmin.c1322
1 files changed, 1322 insertions, 0 deletions
diff --git a/src/kadmin/cli/kadmin.c b/src/kadmin/cli/kadmin.c
new file mode 100644
index 0000000000..e19383dd99
--- /dev/null
+++ b/src/kadmin/cli/kadmin.c
@@ -0,0 +1,1322 @@
+/*
+ * Copyright 1994 by the Massachusetts Institute of Technology.
+ * All Rights Reserved.
+ *
+ * Export of this software from the United States of America may
+ * require a specific license from the United States Government.
+ * It is the responsibility of any person or organization contemplating
+ * export to obtain such a license before exporting.
+ *
+ * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
+ * distribute this software and its documentation for any purpose and
+ * without fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright notice and
+ * this permission notice appear in supporting documentation, and that
+ * the name of M.I.T. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * kadmin.c: base functions for a kadmin command line interface using
+ * the OVSecure library
+ */
+
+#include <krb5.h>
+#include <k5-int.h>
+#include <kadm5/admin.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <math.h>
+#include <unistd.h>
+#include <pwd.h>
+/* #include <sys/timeb.h> */
+#include <time.h>
+
+/* special struct to convert flag names for principals
+ to actual krb5_flags for a principal */
+struct pflag {
+ char *flagname; /* name of flag as typed to CLI */
+ int flaglen; /* length of string (not counting -,+) */
+ krb5_flags theflag; /* actual principal flag to set/clear */
+ int set; /* 0 means clear, 1 means set (on '-') */
+};
+
+static struct pflag flags[] = {
+{"allow_postdated", 15, KRB5_KDB_DISALLOW_POSTDATED, 1},
+{"allow_forwardable", 17, KRB5_KDB_DISALLOW_FORWARDABLE, 1},
+{"allow_tgs_req", 13, KRB5_KDB_DISALLOW_TGT_BASED, 1},
+{"allow_renewable", 15, KRB5_KDB_DISALLOW_RENEWABLE, 1},
+{"allow_proxiable", 15, KRB5_KDB_DISALLOW_PROXIABLE, 1},
+{"allow_dup_skey", 14, KRB5_KDB_DISALLOW_DUP_SKEY, 1},
+{"allow_tix", 9, KRB5_KDB_DISALLOW_ALL_TIX, 1},
+{"requires_preauth", 16, KRB5_KDB_REQUIRES_PRE_AUTH, 0},
+{"requires_hwauth", 15, KRB5_KDB_REQUIRES_HW_AUTH, 0},
+{"needchange", 10, KRB5_KDB_REQUIRES_PWCHANGE, 0},
+{"allow_svr", 9, KRB5_KDB_DISALLOW_SVR, 1},
+{"password_changing_service", 25, KRB5_KDB_PWCHANGE_SERVICE, 0 }
+};
+
+static char *prflags[] = {
+ "DISALLOW_POSTDATED", /* 0x00000001 */
+ "DISALLOW_FORWARDABLE", /* 0x00000002 */
+ "DISALLOW_TGT_BASED", /* 0x00000004 */
+ "DISALLOW_RENEWABLE", /* 0x00000008 */
+ "DISALLOW_PROXIABLE", /* 0x00000010 */
+ "DISALLOW_DUP_SKEY", /* 0x00000020 */
+ "DISALLOW_ALL_TIX", /* 0x00000040 */
+ "REQUIRES_PRE_AUTH", /* 0x00000080 */
+ "REQUIRES_HW_AUTH", /* 0x00000100 */
+ "REQUIRES_PWCHANGE", /* 0x00000200 */
+ "UNKNOWN_0x00000400", /* 0x00000400 */
+ "UNKNOWN_0x00000800", /* 0x00000800 */
+ "DISALLOW_SVR", /* 0x00001000 */
+ "PWCHANGE_SERVICE" /* 0x00002000 */
+};
+
+char *getenv();
+struct passwd *getpwuid();
+int exit_status = 0;
+char *def_realm = NULL;
+char *whoami = NULL;
+time_t get_date();
+
+void *handle = NULL;
+krb5_context context;
+char *ccache_name = NULL;
+
+void usage()
+{
+ fprintf(stderr,
+ "Usage: %s [-r realm] [-p principal] [-q query] [clnt|local args]\n"
+ "\tclnt args: [-s admin_server[:port]] [[-c ccache]|[-k [-t keytab]]]\n"
+ "\tlocal args: [-d dbname] [-e \"enc:salt ...\"] [-m]\n", whoami);
+ exit(1);
+}
+
+char *strdur(duration)
+ time_t duration;
+{
+ static char out[50];
+ int days, hours, minutes, seconds;
+
+ days = duration / (24 * 3600);
+ duration %= 24 * 3600;
+ hours = duration / 3600;
+ duration %= 3600;
+ minutes = duration / 60;
+ duration %= 60;
+ seconds = duration;
+ sprintf(out, "%d %s %02d:%02d:%02d", days, days == 1 ? "day" : "days",
+ hours, minutes, seconds);
+ return out;
+}
+
+char *strdate(when)
+ krb5_timestamp when;
+{
+ struct tm *tm;
+ static char out[30];
+
+ time_t lcltim = when;
+ tm = localtime(&lcltim);
+ strftime(out, 30, "%a %b %d %H:%M:%S %Z %Y", tm);
+ return out;
+}
+
+/* this is a wrapper to go around krb5_parse_principal so we can set
+ the default realm up properly */
+krb5_error_code kadmin_parse_name(name, principal)
+ char *name;
+ krb5_principal *principal;
+{
+ char *cp, *fullname;
+ krb5_error_code retval;
+
+ /* assumes def_realm is initialized! */
+ fullname = (char *)malloc(strlen(name) + 1 + strlen(def_realm) + 1);
+ if (fullname == NULL)
+ return ENOMEM;
+ strcpy(fullname, name);
+ cp = strchr(fullname, '@');
+ while (cp) {
+ if (cp - fullname && *(cp - 1) != '\\')
+ break;
+ else
+ cp = strchr(cp, '@');
+ }
+ if (cp == NULL) {
+ strcat(fullname, "@");
+ strcat(fullname, def_realm);
+ }
+ retval = krb5_parse_name(context, fullname, principal);
+ free(fullname);
+ return retval;
+}
+
+char *kadmin_startup(argc, argv)
+ int argc;
+ char *argv[];
+{
+ extern krb5_kt_ops krb5_ktf_writable_ops;
+ extern char *optarg;
+ char *princstr = NULL, *keytab_name = NULL, *query = NULL;
+ char *password = NULL;
+ char *luser, *canon, *cp;
+ int optchar, freeprinc = 0, use_keytab = 0;
+ struct passwd *pw;
+ kadm5_ret_t retval;
+ krb5_ccache cc;
+ krb5_principal princ;
+ kadm5_config_params params;
+
+ memset((char *) &params, 0, sizeof(params));
+
+ if (retval = krb5_init_context(&context)) {
+ com_err(whoami, retval, "while initializing krb5 library");
+ exit(1);
+ }
+ krb5_init_ets(context);
+
+ while ((optchar = getopt(argc, argv, "r:p:kq:w:d:s:m:c:t:e:")) != EOF) {
+ switch (optchar) {
+ case 'r':
+ def_realm = optarg;
+ break;
+ case 'p':
+ princstr = optarg;
+ break;
+ case 'c':
+ ccache_name = optarg;
+ break;
+ case 'k':
+ use_keytab++;
+ break;
+ case 't':
+ keytab_name = optarg;
+ break;
+ case 'w':
+ password = optarg;
+ break;
+ case 'q':
+ query = optarg;
+ break;
+ case 'd':
+ params.dbname = optarg;
+ params.mask |= KADM5_CONFIG_DBNAME;
+ break;
+ case 's':
+ params.admin_server = optarg;
+ params.mask |= KADM5_CONFIG_ADMIN_SERVER;
+ break;
+ case 'm':
+ params.mkey_from_kbd = 1;
+ params.mask |= KADM5_CONFIG_MKEY_FROM_KBD;
+ break;
+ case 'e':
+ retval = krb5_string_to_keysalts(optarg,
+ ", \t",
+ ":.-",
+ 0,
+ &params.keysalts,
+ &params.num_keysalts);
+ if (retval) {
+ com_err(whoami, retval, "while parsing keysalts %s", optarg);
+ exit(1);
+ }
+ params.mask |= KADM5_CONFIG_ENCTYPES;
+ break;
+ default:
+ usage();
+ }
+ }
+ if ((ccache_name && use_keytab) ||
+ (keytab_name && !use_keytab))
+ usage();
+
+ if (def_realm == NULL && krb5_get_default_realm(context, &def_realm)) {
+ if (freeprinc)
+ free(princstr);
+ fprintf(stderr, "%s: unable to get default realm\n", whoami);
+ exit(1);
+ }
+
+ params.mask |= KADM5_CONFIG_REALM;
+ params.realm = def_realm;
+
+ /*
+ * Set cc to an open credentials cache, either specified by the -c
+ * argument or the default.
+ */
+ if (ccache_name == NULL) {
+ if (retval = krb5_cc_default(context, &cc)) {
+ com_err(whoami, retval,
+ "while opening default credentials cache");
+ exit(1);
+ }
+ } else {
+ if (retval = krb5_cc_resolve(context, ccache_name, &cc)) {
+ com_err(whoami, retval,
+ "while opening credentials cache %s", ccache_name);
+ exit(1);
+ }
+ }
+
+ /*
+ * If no principal name is specified: If a ccache was specified
+ * and its primary principal name can be read, it is used, else if
+ * a keytab was specified, the principal name is host/hostname,
+ * otherwise append "/admin" to the primary name of the default
+ * ccache, $USER, or pw_name.
+ *
+ * Gee, 100+ lines to figure out the client principal name. This
+ * should be compressed...
+ */
+
+ if (princstr == NULL) {
+ if (ccache_name != NULL &&
+ !krb5_cc_get_principal(context, cc, &princ)) {
+ if (retval = krb5_unparse_name(context, princ, &princstr)) {
+ com_err(whoami, retval,
+ "while canonicalizing principal name");
+ krb5_free_principal(context, princ);
+ exit(1);
+ }
+ krb5_free_principal(context, princ);
+ freeprinc++;
+ } else if (use_keytab != NULL) {
+ if (retval = krb5_sname_to_principal(context, NULL,
+ "host",
+ KRB5_NT_SRV_HST,
+ &princ)) {
+ com_err(whoami, retval,
+ "creating host service principal");
+ exit(1);
+ }
+ if (retval = krb5_unparse_name(context, princ, &princstr)) {
+ com_err(whoami, retval,
+ "while canonicalizing principal name");
+ krb5_free_principal(context, princ);
+ exit(1);
+ }
+ krb5_free_principal(context, princ);
+ freeprinc++;
+ } else if (!krb5_cc_get_principal(context, cc, &princ)) {
+ char *realm = NULL;
+ if (krb5_unparse_name(context, princ, &canon)) {
+ fprintf(stderr,
+ "%s: unable to canonicalize principal\n", whoami);
+ krb5_free_principal(context, princ);
+ exit(1);
+ }
+ /* strip out realm of principal if it's there */
+ realm = strchr(canon, '@');
+ while (realm) {
+ if (realm - canon && *(realm - 1) != '\\')
+ break;
+ else
+ realm = strchr(realm, '@');
+ }
+ if (realm)
+ *realm++ = '\0';
+ cp = strchr(canon, '/');
+ while (cp) {
+ if (cp - canon && *(cp - 1) != '\\')
+ break;
+ else
+ cp = strchr(cp, '/');
+ }
+ if (cp != NULL)
+ *cp = '\0';
+ princstr = (char*)malloc(strlen(canon) + 6 /* "/admin" */ +
+ (realm ? 1 + strlen(realm) : 0) + 1);
+ if (princstr == NULL) {
+ fprintf(stderr, "%s: out of memory\n", whoami);
+ exit(1);
+ }
+ strcpy(princstr, canon);
+ strcat(princstr, "/admin");
+ if (realm) {
+ strcat(princstr, "@");
+ strcat(princstr, realm);
+ }
+ free(canon);
+ krb5_free_principal(context, princ);
+ freeprinc++;
+ } else if (luser = getenv("USER")) {
+ princstr = (char *) malloc(strlen(luser) + 7 /* "/admin@" */
+ + strlen(def_realm) + 1);
+ if (princstr == NULL) {
+ fprintf(stderr, "%s: out of memory\n", whoami);
+ exit(1);
+ }
+ strcpy(princstr, luser);
+ strcat(princstr, "/admin");
+ strcat(princstr, "@");
+ strcat(princstr, def_realm);
+ freeprinc++;
+ } else if (pw = getpwuid(getuid())) {
+ princstr = (char *) malloc(strlen(pw->pw_name) + 7 /* "/admin@" */
+ + strlen(def_realm) + 1);
+ if (princstr == NULL) {
+ fprintf(stderr, "%s: out of memory\n", whoami);
+ exit(1);
+ }
+ strcpy(princstr, pw->pw_name);
+ strcat(princstr, "/admin@");
+ strcat(princstr, def_realm);
+ freeprinc++;
+ } else {
+ fprintf(stderr, "%s: unable to figure out a principal name\n",
+ whoami);
+ exit(1);
+ }
+ }
+
+ /*
+ * Initialize the kadm5 connection. If we were given a ccache,
+ * use it. Otherwise, use/prompt for the password.
+ */
+ if (ccache_name)
+ retval = kadm5_init_with_creds(princstr, cc,
+ KADM5_ADMIN_SERVICE,
+ &params,
+ KADM5_STRUCT_VERSION,
+ KADM5_API_VERSION_2,
+ &handle);
+ else if (use_keytab)
+ retval = kadm5_init_with_skey(princstr, keytab_name,
+ KADM5_ADMIN_SERVICE,
+ &params,
+ KADM5_STRUCT_VERSION,
+ KADM5_API_VERSION_2,
+ &handle);
+ else
+ retval = kadm5_init_with_password(princstr, password,
+ KADM5_ADMIN_SERVICE,
+ &params,
+ KADM5_STRUCT_VERSION,
+ KADM5_API_VERSION_2,
+ &handle);
+ if (retval) {
+ com_err(whoami, retval, "while initializing %s interface", whoami);
+ if (retval == KADM5_BAD_CLIENT_PARAMS ||
+ retval == KADM5_BAD_SERVER_PARAMS)
+ usage();
+ exit(1);
+ }
+ if (freeprinc)
+ free(princstr);
+
+ if (retval = krb5_cc_close(context, cc)) {
+ com_err(whoami, retval, "while closing ccache %s",
+ ccache_name);
+ exit(1);
+ }
+
+ /* register the WRFILE keytab type and set it as the default */
+ if (retval = krb5_kt_register(context, &krb5_ktf_writable_ops)) {
+ com_err(whoami, retval,
+ "while registering writable key table functions");
+ exit(1);
+ }
+ {
+#define DEFAULT_KEYTAB "WRFILE:/etc/v5srvtab"
+ extern char *krb5_defkeyname;
+ krb5_defkeyname = DEFAULT_KEYTAB;
+ }
+
+ return query;
+}
+
+int quit()
+{
+ krb5_ccache cc;
+ int retval;
+
+ kadm5_destroy(handle);
+ if (ccache_name != NULL) {
+ fprintf(stderr,
+ "\n\a\a\aAdministration credentials NOT DESTROYED.\n");
+ }
+
+ /* insert more random cleanup here */
+}
+
+void kadmin_delprinc(argc, argv)
+ int argc;
+ char *argv[];
+{
+ kadm5_ret_t retval;
+ krb5_principal princ;
+ char *canon;
+ char reply[5];
+
+ if (! (argc == 2 ||
+ (argc == 3 && !strcmp("-force", argv[1])))) {
+ fprintf(stderr, "usage: delete_principal [-force] principal\n");
+ return;
+ }
+ retval = kadmin_parse_name(argv[argc - 1], &princ);
+ if (retval) {
+ com_err("delete_principal", retval, "while parsing principal name");
+ return;
+ }
+ retval = krb5_unparse_name(context, princ, &canon);
+ if (retval) {
+ com_err("delete_principal", retval,
+ "while canonicalizing principal");
+ krb5_free_principal(context, princ);
+ return;
+ }
+ if (argc == 2) {
+ printf("Are you sure you want to delete the principal \"%s\"? (yes/no): ", canon);
+ fgets(reply, sizeof (reply), stdin);
+ if (strcmp("yes\n", reply)) {
+ fprintf(stderr, "Principal \"%s\" not deleted\n", canon);
+ free(canon);
+ krb5_free_principal(context, princ);
+ return;
+ }
+ }
+ retval = kadm5_delete_principal(handle, princ);
+ krb5_free_principal(context, princ);
+ if (retval) {
+ com_err("delete_principal", retval,
+ "while deleteing principal \"%s\"", canon);
+ free(canon);
+ return;
+ }
+ printf("Principal \"%s\" deleted.\nMake sure that you have removed this principal from all ACLs before reusing.\n", canon);
+ free(canon);
+ return;
+}
+
+void kadmin_renprinc(argc, argv)
+ int argc;
+ char *argv[];
+{
+ krb5_principal oldprinc, newprinc;
+ char *oldcanon, *newcanon;
+ char reply[5];
+ kadm5_ret_t retval;
+
+ if (! (argc == 3 ||
+ (argc == 4 && !strcmp("-force", argv[1])))) {
+ fprintf(stderr, "usage: rename_principal [-force] old new\n");
+ return;
+ }
+ retval = kadmin_parse_name(argv[argc - 2], &oldprinc);
+ if (retval) {
+ com_err("rename_principal", retval, "while parsing old principal");
+ return;
+ }
+ retval = kadmin_parse_name(argv[argc - 1], &newprinc);
+ if (retval) {
+ krb5_free_principal(context, oldprinc);
+ com_err("rename_principal", retval, "while parsing new principal");
+ return;
+ }
+ retval = krb5_unparse_name(context, oldprinc, &oldcanon);
+ if (retval) {
+ com_err("rename_principal", retval,
+ "while canonicalizing old principal");
+ krb5_free_principal(context, newprinc);
+ krb5_free_principal(context, oldprinc);
+ return;
+ }
+ retval = krb5_unparse_name(context, newprinc, &newcanon);
+ if (retval) {
+ com_err("rename_principal", retval,
+ "while canonicalizing new principal");
+ free(oldcanon);
+ krb5_free_principal(context, newprinc);
+ krb5_free_principal(context, oldprinc);
+ return;
+ }
+ if (argc == 3) {
+ printf("Are you sure you want to rename the principal \"%s\" to \"%s\"? (yes/no): ",
+ oldcanon, newcanon);
+ fgets(reply, sizeof (reply), stdin);
+ if (strcmp("yes\n", reply)) {
+ fprintf(stderr,
+ "rename_principal: \"%s\" NOT renamed to \"%s\".\n",
+ oldcanon, newcanon);
+ free(newcanon);
+ free(oldcanon);
+ krb5_free_principal(context, newprinc);
+ krb5_free_principal(context, oldprinc);
+ return;
+ }
+ }
+ retval = kadm5_rename_principal(handle, oldprinc, newprinc);
+ krb5_free_principal(context, oldprinc);
+ krb5_free_principal(context, newprinc);
+ if (retval) {
+ com_err("rename_principal", retval,
+ "while renaming \"%s\" to \"%s\".", oldcanon,
+ newcanon);
+ free(newcanon);
+ free(oldcanon);
+ return;
+ }
+ printf("Principal \"%s\" renamed to \"%s\".\nMake sure that you have removed \"%s\" from all ACLs before reusing.\n",
+ oldcanon, newcanon, newcanon);
+ return;
+}
+
+void kadmin_cpw(argc, argv)
+ int argc;
+ char *argv[];
+{
+ kadm5_ret_t retval;
+ static char newpw[1024];
+ static char prompt1[1024], prompt2[1024];
+ char *canon;
+ krb5_principal princ;
+
+ if (argc < 2) {
+ goto usage;
+ }
+
+ retval = kadmin_parse_name(argv[argc - 1], &princ);
+ if (retval) {
+ com_err("change_password", retval, "while parsing principal name");
+ return;
+ }
+ retval = krb5_unparse_name(context, princ, &canon);
+ if (retval) {
+ com_err("change_password", retval, "while canonicalizing principal");
+ krb5_free_principal(context, princ);
+ return;
+ }
+ if ((argc == 4) && (strlen(argv[1]) == 3) && !strcmp("-pw", argv[1])) {
+ retval = kadm5_chpass_principal(handle, princ, argv[2]);
+ krb5_free_principal(context, princ);
+ if (retval) {
+ com_err("change_password", retval,
+ "while changing password for \"%s\".", canon);
+ free(canon);
+ return;
+ }
+ printf("Password for \"%s\" changed.\n", canon);
+ free(canon);
+ return;
+ } else if ((argc == 3) && (strlen(argv[1]) == 8) &&
+ !strcmp("-randkey", argv[1])) {
+ retval = kadm5_randkey_principal(handle, princ, NULL, NULL);
+ krb5_free_principal(context, princ);
+ if (retval) {
+ com_err("change_password", retval,
+ "while randomizing key for \"%s\".", canon);
+ free(canon);
+ return;
+ }
+ printf("Key for \"%s\" randomized.\n", canon);
+ free(canon);
+ return;
+ } else if (argc == 2) {
+ int i = sizeof (newpw) - 1;
+
+ sprintf(prompt1, "Enter password for principal \"%.900s\": ",
+ argv[1]);
+ sprintf(prompt2,
+ "Re-enter password for principal \"%.900s\": ",
+ argv[1]);
+ retval = krb5_read_password(context, prompt1, prompt2,
+ newpw, &i);
+ if (retval) {
+ com_err("change_password", retval,
+ "while reading password for \"%s\".", canon);
+ free(canon);
+ krb5_free_principal(context, princ);
+ return;
+ }
+ retval = kadm5_chpass_principal(handle, princ, newpw);
+ krb5_free_principal(context, princ);
+ memset(newpw, 0, sizeof (newpw));
+ if (retval) {
+ com_err("change_password", retval,
+ "while changing password for \"%s\".", canon);
+ free(canon);
+ return;
+ }
+ printf("Password for \"%s\" changed.\n", canon);
+ free(canon);
+ return;
+ } else {
+ free(canon);
+ krb5_free_principal(context, princ);
+ usage:
+ fprintf(stderr,
+ "usage: change_password [-randpass] [-pw passowrd] "
+ "principal\n");
+ return;
+ }
+}
+
+int kadmin_parse_princ_args(argc, argv, oprinc, mask, pass, randkey, caller)
+ int argc;
+ char *argv[];
+ kadm5_principal_ent_t oprinc;
+ long *mask;
+ char **pass;
+ int *randkey;
+ char *caller;
+{
+ int i, j, attrib_set;
+ time_t date;
+ time_t now;
+ krb5_error_code retval;
+
+ *mask = 0;
+ *pass = NULL;
+ time(&now);
+ *randkey = 0;
+ for (i = 1; i < argc - 1; i++) {
+ attrib_set = 0;
+ if (strlen(argv[i]) == 7 &&
+ !strcmp("-expire", argv[i])) {
+ if (++i > argc - 2)
+ return -1;
+ else {
+ date = get_date(argv[i], NULL);
+ oprinc->princ_expire_time = date == (time_t)-1 ? 0 : date;
+ *mask |= KADM5_PRINC_EXPIRE_TIME;
+ continue;
+ }
+ }
+ if (strlen(argv[i]) == 9 &&
+ !strcmp("-pwexpire", argv[i])) {
+ if (++i > argc - 2)
+ return -1;
+ else {
+ date = get_date(argv[i], NULL);
+ oprinc->pw_expiration = date == (time_t)-1 ? 0 : date;
+ *mask |= KADM5_PW_EXPIRATION;
+ continue;
+ }
+ }
+ if (strlen(argv[i]) == 8 &&
+ !strcmp("-maxlife", argv[i])) {
+ if (++i > argc - 2)
+ return -1;
+ else {
+ oprinc->max_life = get_date(argv[i], NULL) - now;
+ *mask |= KADM5_MAX_LIFE;
+ continue;
+ }
+ }
+ if (strlen(argv[i]) == 5 &&
+ !strcmp("-kvno", argv[i])) {
+ if (++i > argc - 2)
+ return -1;
+ else {
+ oprinc->kvno = atoi(argv[i]);
+ *mask |= KADM5_KVNO;
+ continue;
+ }
+ }
+ if (strlen(argv[i]) == 7 &&
+ !strcmp("-policy", argv[i])) {
+ if (++i > argc - 2)
+ return -1;
+ else {
+ oprinc->policy = argv[i];
+ *mask |= KADM5_POLICY;
+ continue;
+ }
+ }
+ if (strlen(argv[i]) == 12 &&
+ !strcmp("-clearpolicy", argv[i])) {
+ oprinc->policy = NULL;
+ *mask |= KADM5_POLICY_CLR;
+ continue;
+ }
+ if (strlen(argv[i]) == 3 &&
+ !strcmp("-pw", argv[i])) {
+ if (++i > argc - 2)
+ return -1;
+ else {
+ *pass = argv[i];
+ continue;
+ }
+ }
+ if (strlen(argv[i]) == 8 &&
+ !strcmp("-randkey", argv[i])) {
+ ++*randkey;
+ continue;
+ }
+ for (j = 0; j < sizeof (flags) / sizeof (struct pflag); j++) {
+ if (strlen(argv[i]) == flags[j].flaglen + 1 &&
+ !strcmp(flags[j].flagname,
+ &argv[i][1] /* strip off leading + or - */)) {
+ if (flags[j].set && argv[i][0] == '-' ||
+ !flags[j].set && argv[i][0] == '+') {
+ oprinc->attributes |= flags[j].theflag;
+ *mask |= KADM5_ATTRIBUTES;
+ attrib_set++;
+ break;
+ } else if (flags[j].set && argv[i][0] == '+' ||
+ !flags[j].set && argv[i][0] == '-') {
+ oprinc->attributes &= ~flags[j].theflag;
+ *mask |= KADM5_ATTRIBUTES;
+ attrib_set++;
+ break;
+ } else {
+ return -1;
+ }
+ }
+ }
+ if (!attrib_set)
+ return -1; /* nothing was parsed */
+ }
+ if (i != argc - 1) {
+ fprintf(stderr, "%s: parser lost count!\n", caller);
+ return -1;
+ }
+ retval = kadmin_parse_name(argv[i], &oprinc->principal);
+ if (retval) {
+ com_err(caller, retval, "while parsing principal");
+ return -1;
+ }
+ return 0;
+}
+
+void kadmin_addmodprinc_usage(func)
+ char *func;
+{
+ fprintf(stderr, "usage: %s [options] principal\n", func);
+ fprintf(stderr, "\toptions are:\n");
+ fprintf(stderr, "\t\t[-salt salttype] [-expire expdate] [-pwexpire pwexpdate]\n\t\t[-maxlife maxtixlife] [-kvno kvno] [-policy policy]\n\t\t[-randkey] [-pw password] [{+|-}attribute]\n");
+ fprintf(stderr, "\tattributes are:\n");
+ fprintf(stderr, "\t\tallow_tgs_req, allow_tix, needchange, password_changing_service\n");
+}
+
+void kadmin_addprinc(argc, argv)
+ int argc;
+ char *argv[];
+{
+ kadm5_principal_ent_rec princ;
+ long mask;
+ int randkey = 0;
+ char *pass, *canon;
+ krb5_error_code retval;
+ static char newpw[1024];
+ static char prompt1[1024], prompt2[1024];
+
+ princ.attributes = 0;
+ if (kadmin_parse_princ_args(argc, argv,
+ &princ, &mask, &pass, &randkey,
+ "add_principal")) {
+ kadmin_addmodprinc_usage("add_principal");
+ return;
+ }
+ retval = krb5_unparse_name(context, princ.principal, &canon);
+ if (retval) {
+ com_err("add_principal",
+ retval, "while canonicalizing principal");
+ krb5_free_principal(context, princ.principal);
+ return;
+ }
+ if (randkey) { /* do special stuff if -randkey specified */
+ princ.attributes |= KRB5_KDB_DISALLOW_ALL_TIX; /* set notix */
+ mask |= KADM5_ATTRIBUTES;
+ pass = "dummy";
+ } else if (pass == NULL) {
+ int i = sizeof (newpw) - 1;
+
+ sprintf(prompt1, "Enter password for principal \"%.900s\": ",
+ canon);
+ sprintf(prompt2,
+ "Re-enter password for principal \"%.900s\": ",
+ canon);
+ retval = krb5_read_password(context, prompt1, prompt2,
+ newpw, &i);
+ if (retval) {
+ com_err("add_principal", retval,
+ "while reading password for \"%s\".", canon);
+ free(canon);
+ krb5_free_principal(context, princ.principal);
+ return;
+ }
+ pass = newpw;
+ }
+ mask |= KADM5_PRINCIPAL;
+ retval = kadm5_create_principal(handle, &princ, mask, pass);
+ if (retval) {
+ com_err("add_principal", retval, "while creating \"%s\".",
+ canon);
+ krb5_free_principal(context, princ.principal);
+ free(canon);
+ return;
+ }
+ if (randkey) { /* more special stuff for -randkey */
+ retval = kadm5_randkey_principal(handle, princ.principal,
+ NULL, NULL);
+ if (retval) {
+ com_err("add_principal", retval,
+ "while randomizing key for \"%s\".", canon);
+ krb5_free_principal(context, princ.principal);
+ free(canon);
+ return;
+ }
+ princ.attributes &= ~KRB5_KDB_DISALLOW_ALL_TIX; /* clear notix */
+ mask = KADM5_ATTRIBUTES;
+ retval = kadm5_modify_principal(handle, &princ, mask);
+ if (retval) {
+ com_err("add_principal", retval,
+ "while clearing DISALLOW_ALL_TIX for \"%s\".", canon);
+ krb5_free_principal(context, princ.principal);
+ free(canon);
+ return;
+ }
+ }
+ krb5_free_principal(context, princ.principal);
+ printf("Principal \"%s\" created.\n", canon);
+ free(canon);
+}
+
+void kadmin_modprinc(argc, argv)
+ int argc;
+ char *argv[];
+{
+ kadm5_principal_ent_rec princ, oldprinc;
+ krb5_principal kprinc;
+ long mask;
+ krb5_error_code retval;
+ char *pass, *canon;
+ int randkey = 0;
+
+ if (argc < 2) {
+ kadmin_addmodprinc_usage("modify_principal");
+ return;
+ }
+
+ retval = kadmin_parse_name(argv[argc - 1], &kprinc);
+ if (retval) {
+ com_err("modify_principal", retval, "while parsing principal");
+ return;
+ }
+ retval = krb5_unparse_name(context, kprinc, &canon);
+ if (retval) {
+ com_err("modify_principal", retval,
+ "while canonicalizing principal");
+ krb5_free_principal(context, kprinc);
+ return;
+ }
+ retval = kadm5_get_principal(handle, kprinc, &oldprinc,
+ KADM5_PRINCIPAL_NORMAL_MASK);
+ krb5_free_principal(context, kprinc);
+ if (retval) {
+ com_err("modify_principal", retval, "while getting \"%s\".",
+ canon);
+ free(canon);
+ return;
+ }
+ princ.attributes = oldprinc.attributes;
+ kadm5_free_principal_ent(handle, &oldprinc);
+ retval = kadmin_parse_princ_args(argc, argv,
+ &princ, &mask,
+ &pass, &randkey,
+ "modify_principal");
+ if (retval) {
+ kadmin_addmodprinc_usage("modify_principal");
+ free(canon);
+ return;
+ }
+ if (randkey) {
+ fprintf(stderr, "modify_principal: -randkey not allowed\n");
+ krb5_free_principal(context, princ.principal);
+ free(canon);
+ return;
+ }
+ retval = kadm5_modify_principal(handle, &princ, mask);
+ krb5_free_principal(context, princ.principal);
+ if (retval) {
+ com_err("modify_principal", retval,
+ "while modifying \"%s\".", canon);
+ free(canon);
+ return;
+ }
+ printf("Principal \"%s\" modified.\n", canon);
+ free(canon);
+}
+
+void kadmin_getprinc(argc, argv)
+ int argc;
+ char *argv[];
+{
+ kadm5_principal_ent_rec dprinc;
+ krb5_principal princ;
+ krb5_error_code retval;
+ char *canon, *modcanon;
+ int i;
+
+ if (! (argc == 2 ||
+ (argc == 3 && !strcmp("-terse", argv[1])))) {
+ fprintf(stderr, "usage: get_principal [-terse] principal\n");
+ return;
+ }
+ retval = kadmin_parse_name(argv[argc - 1], &princ);
+ if (retval) {
+ com_err("get_principal", retval, "while parsing principal");
+ return;
+ }
+ retval = krb5_unparse_name(context, princ, &canon);
+ if (retval) {
+ com_err("get_principal", retval, "while canonicalizing principal");
+ krb5_free_principal(context, princ);
+ return;
+ }
+ retval = kadm5_get_principal(handle, princ, &dprinc,
+ KADM5_PRINCIPAL_NORMAL_MASK | KADM5_KEY_DATA);
+ krb5_free_principal(context, princ);
+ if (retval) {
+ com_err("get_principal", retval, "while retrieving \"%s\".", canon);
+ free(canon);
+ return;
+ }
+ retval = krb5_unparse_name(context, dprinc.mod_name, &modcanon);
+ if (retval) {
+ com_err("get_principal", retval, "while unparsing modname");
+ kadm5_free_principal_ent(handle, &dprinc);
+ free(canon);
+ return;
+ }
+ if (argc == 2) {
+ printf("Principal: %s\n", canon);
+ printf("Expiration date: %s\n", strdate(dprinc.princ_expire_time));
+ printf("Last password change: %s\n",
+ strdate(dprinc.last_pwd_change));
+ printf("Password expiration date: %s\n",
+ dprinc.pw_expiration ?
+ strdate(dprinc.pw_expiration) : "[none]");
+ printf("Maximum ticket life: %s\n", strdur(dprinc.max_life));
+ printf("Last modified: by %s\n\ton %s\n",
+ modcanon, strdate(dprinc.mod_date));
+ printf("Last successful authentication: %s\n",
+ strdate(dprinc.last_success));
+ printf("Last failed authentication: %s\n",
+ strdate(dprinc.last_failed));
+ printf("Failed password attempts: %d\n",
+ dprinc.fail_auth_count);
+ printf("Number of keys: %d\n", dprinc.n_key_data);
+ for (i = 0; i < dprinc.n_key_data; i++) {
+ krb5_key_data *key_data = &dprinc.key_data[i];
+ char enctype[BUFSIZ], salttype[BUFSIZ];
+
+ if (krb5_enctype_to_string(key_data->key_data_type[0],
+ enctype, sizeof(enctype)))
+ sprintf(enctype, "<Encryption type 0x%x>",
+ key_data->key_data_type[0]);
+ printf("Key: vno %d, %s, ", key_data->key_data_kvno, enctype);
+ if (key_data->key_data_ver > 1) {
+ if (krb5_salttype_to_string(key_data->key_data_type[1],
+ salttype, sizeof(salttype)))
+ sprintf(salttype, "<Salt type 0x%x>",
+ key_data->key_data_type[1]);
+ printf("%s\n", salttype);
+ } else
+ printf("no salt\n");
+ }
+
+ printf("Attributes:");
+ for (i = 0; i < sizeof (prflags) / sizeof (char *); i++) {
+ if (dprinc.attributes & (krb5_flags) 1 << i)
+ printf(" %s", prflags[i]);
+ }
+ printf("\n");
+ printf("Policy: %s\n", dprinc.policy ? dprinc.policy : "[none]");
+ } else {
+ printf("\"%s\"\t%d\t%d\t%d\t%d\t\"%s\"\t%d\t%d\t%d\t%d\t\"%s\""
+ "\t%d\t%d\t%d\t%d\t%d",
+ canon, dprinc.princ_expire_time, dprinc.last_pwd_change,
+ dprinc.pw_expiration, dprinc.max_life, modcanon,
+ dprinc.mod_date, dprinc.attributes, dprinc.kvno,
+ dprinc.mkvno, dprinc.policy,
+ dprinc.max_renewable_life, dprinc.last_success,
+ dprinc.last_failed, dprinc.fail_auth_count,
+ dprinc.n_key_data);
+ for (i = 0; i < dprinc.n_key_data; i++)
+ printf("\t%d\t%d\t%d\t%d",
+ dprinc.key_data[i].key_data_ver,
+ dprinc.key_data[i].key_data_kvno,
+ dprinc.key_data[i].key_data_type[0],
+ dprinc.key_data[i].key_data_type[1]);
+ printf("\n");
+ }
+ free(modcanon);
+ kadm5_free_principal_ent(handle, &dprinc);
+ free(canon);
+}
+
+void kadmin_getprincs(argc, argv)
+ int argc;
+ char *argv[];
+{
+ krb5_error_code retval;
+ char *exp, **names;
+ int i, count;
+
+ exp = NULL;
+ if (! (argc == 1 || (argc == 2 && (exp = argv[1])))) {
+ fprintf(stderr, "usage: get_principals [expression]\n");
+ return;
+ }
+ retval = kadm5_get_principals(handle, exp, &names, &count);
+ if (retval) {
+ com_err("get_principals", retval, "while retrieving list.");
+ return;
+ }
+ for (i = 0; i < count; i++)
+ printf("%s\n", names[i]);
+ kadm5_free_name_list(handle, names, count);
+}
+
+int kadmin_parse_policy_args(argc, argv, policy, mask, caller)
+ int argc;
+ char *argv[];
+ kadm5_policy_ent_t policy;
+ long *mask;
+ char *caller;
+{
+ int i;
+ time_t now;
+ time_t date;
+ krb5_error_code retval;
+
+ time(&now);
+ *mask = 0;
+ for (i = 1; i < argc - 1; i++) {
+ if (strlen(argv[i]) == 8 &&
+ !strcmp(argv[i], "-maxlife")) {
+ if (++i > argc -2)
+ return -1;
+ else {
+ date = get_date(argv[i], NULL);
+ policy->pw_max_life =
+ (date == (time_t)-1 ? 0 : date) - now;
+ *mask |= KADM5_PW_MAX_LIFE;
+ continue;
+ }
+ } else if (strlen(argv[i]) == 8 &&
+ !strcmp(argv[i], "-minlife")) {
+ if (++i > argc - 2)
+ return -1;
+ else {
+ date = get_date(argv[i], NULL);
+ policy->pw_min_life =
+ (date == (time_t)-1 ? 0 : date) - now;
+ *mask |= KADM5_PW_MIN_LIFE;
+ continue;
+ }
+ } else if (strlen(argv[i]) == 10 &&
+ !strcmp(argv[i], "-minlength")) {
+ if (++i > argc - 2)
+ return -1;
+ else {
+ policy->pw_min_length = atoi(argv[i]);
+ *mask |= KADM5_PW_MIN_LENGTH;
+ continue;
+ }
+ } else if (strlen(argv[i]) == 11 &&
+ !strcmp(argv[i], "-minclasses")) {
+ if (++i > argc - 2)
+ return -1;
+ else {
+ policy->pw_min_classes = atoi(argv[i]);
+ *mask |= KADM5_PW_MIN_CLASSES;
+ continue;
+ }
+ } else if (strlen(argv[i]) == 8 &&
+ !strcmp(argv[i], "-history")) {
+ if (++i > argc - 2)
+ return -1;
+ else {
+ policy->pw_history_num = atoi(argv[i]);
+ *mask |= KADM5_PW_HISTORY_NUM;
+ continue;
+ }
+ } else
+ return -1;
+ }
+ if (i != argc -1) {
+ fprintf(stderr, "%s: parser lost count!\n", caller);
+ return -1;
+ } else
+ return 0;
+}
+
+void kadmin_addmodpol_usage(func)
+ char *func;
+{
+ fprintf(stderr, "usage; %s [options] policy\n", func);
+ fprintf(stderr, "\toptions are:\n");
+ fprintf(stderr, "\t\t[-maxlife time] [-minlife time] [-minlength length]\n\t\t[-minclasses number] [-history number]\n");
+}
+
+void kadmin_addpol(argc, argv)
+ int argc;
+ char *argv[];
+{
+ krb5_error_code retval;
+ long mask;
+ kadm5_policy_ent_rec policy;
+
+ if (kadmin_parse_policy_args(argc, argv, &policy, &mask, "add_policy")) {
+ kadmin_addmodpol_usage("add_policy");
+ return;
+ } else {
+ policy.policy = argv[argc - 1];
+ mask |= KADM5_POLICY;
+ retval = kadm5_create_policy(handle, &policy, mask);
+ if (retval) {
+ com_err("add_policy", retval, "while creating policy \"%s\".",
+ policy.policy);
+ return;
+ }
+ }
+ return;
+}
+
+void kadmin_modpol(argc, argv)
+ int argc;
+ char *argv[];
+{
+ krb5_error_code retval;
+ long mask;
+ kadm5_policy_ent_rec policy;
+
+ if (kadmin_parse_policy_args(argc, argv, &policy, &mask,
+ "modify_policy")) {
+ kadmin_addmodpol_usage("modify_policy");
+ return;
+ } else {
+ policy.policy = argv[argc - 1];
+ retval = kadm5_modify_policy(handle, &policy, mask);
+ if (retval) {
+ com_err("modify_policy", retval, "while modifying policy \"%s\".",
+ policy.policy);
+ return;
+ }
+ }
+ return;
+}
+
+void kadmin_delpol(argc, argv)
+ int argc;
+ char *argv[];
+{
+ krb5_error_code retval;
+ char reply[5];
+
+ if (! (argc == 2 ||
+ (argc == 3 && !strcmp("-force", argv[1])))) {
+ fprintf(stderr, "usage: delete_policy [-force] policy\n");
+ return;
+ }
+ if (argc == 2) {
+ printf("Are you sure you want to delete the policy \"%s\"? (yes/no): ", argv[1]);
+ fgets(reply, sizeof (reply), stdin);
+ if (strcmp("yes\n", reply)) {
+ fprintf(stderr, "Policy \"%s\" not deleted.\n", argv[1]);
+ return;
+ }
+ }
+ retval = kadm5_delete_policy(handle, argv[argc - 1]);
+ if (retval) {
+ com_err("delete_policy:", retval, "while deleting policy \"%s\"",
+ argv[argc - 1]);
+ return;
+ }
+ return;
+}
+
+void kadmin_getpol(argc, argv)
+ int argc;
+ char *argv[];
+{
+ krb5_error_code retval;
+ kadm5_policy_ent_rec policy;
+
+ if (! (argc == 2 ||
+ (argc == 3 && !strcmp("-terse", argv[1])))) {
+ fprintf(stderr, "usage: get_policy [-terse] policy\n");
+ return;
+ }
+ retval = kadm5_get_policy(handle, argv[argc - 1], &policy);
+ if (retval) {
+ com_err("get_policy", retval, "while retrieving policy \"%s\".",
+ argv[argc - 1]);
+ return;
+ }
+ if (argc == 2) {
+ printf("Policy: %s\n", policy.policy);
+ printf("Maximum password life: %d\n", policy.pw_max_life);
+ printf("Minimum password life: %d\n", policy.pw_min_life);
+ printf("Minimum password length: %d\n", policy.pw_min_length);
+ printf("Minimum number of password character classes: %d\n",
+ policy.pw_min_classes);
+ printf("Number of old keys kept: %d\n", policy.pw_history_num);
+ printf("Reference count: %d\n", policy.policy_refcnt);
+ } else {
+ printf("\"%s\"\t%d\t%d\t%d\t%d\t%d\t%d\n",
+ policy.policy, policy.pw_max_life, policy.pw_min_life,
+ policy.pw_min_length, policy.pw_min_classes,
+ policy.pw_history_num, policy.policy_refcnt);
+ }
+ kadm5_free_policy_ent(handle, &policy);
+ return;
+}
+
+void kadmin_getpols(argc, argv)
+ int argc;
+ char *argv[];
+{
+ krb5_error_code retval;
+ char *exp, **names;
+ int i, count;
+
+ exp = NULL;
+ if (! (argc == 1 || (argc == 2 && (exp = argv[1])))) {
+ fprintf(stderr, "usage: get_policies [expression]\n");
+ return;
+ }
+ retval = kadm5_get_policies(handle, exp, &names, &count);
+ if (retval) {
+ com_err("get_policies", retval, "while retrieving list.");
+ return;
+ }
+ for (i = 0; i < count; i++)
+ printf("%s\n", names[i]);
+ kadm5_free_name_list(handle, names, count);
+}
+
+kadmin_getprivs(argc, argv)
+ int argc;
+ char *argv[];
+{
+ static char *privs[] = {"GET", "ADD", "MODIFY", "DELETE"};
+ krb5_error_code retval;
+ int i;
+ long plist;
+
+ if (argc != 1) {
+ fprintf(stderr, "usage: get_privs\n");
+ return;
+ }
+ retval = kadm5_get_privs(handle, &plist);
+ if (retval) {
+ com_err("get_privs", retval, "while retrieving privileges");
+ return;
+ }
+ printf("current privileges:");
+ for (i = 0; i < sizeof (privs) / sizeof (char *); i++) {
+ if (plist & 1 << i)
+ printf(" %s", privs[i]);
+ }
+ printf("\n");
+ return;
+}