kadmin.c revision 1fceb383a3f0b59711832b9dc4e8329d7f216604
/*
* Copyright 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* 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. Furthermore if you modify this software you must label
* your software as modified software and not distribute it in such a
* fashion that it might be confused with the original M.I.T. software.
* 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 <krb5/adm_proto.h>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <unistd.h>
#include <pwd.h>
#include <time.h>
#include "kadmin.h"
#include <libintl.h>
/*
* Solaris: the following are needed for paging
*/
#include <signal.h>
/* command name when called "locally" (i.e. non-networked client ) */
#define KADMIN_LOCAL_NAME "kadmin.local"
extern void usage(const char *);
/* 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 -,+) */
int set; /* 0 means clear, 1 means set (on '-') */
};
};
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 */
"SUPPORT_DESMD5", /* 0x00004000 */
"NEW_PRINC", /* 0x00008000 */
};
char *getenv();
int exit_status = 0;
char *ccache_name = NULL;
int locked = 0;
{
static char out[50];
if (duration < 0) {
duration *= -1;
neg = 1;
} else
neg = 0;
duration %= 3600;
duration %= 60;
return out;
}
{
static char out[40];
return out;
}
/* this is a wrapper to go around krb5_parse_principal so we can set
the default realm up properly */
static krb5_error_code
char *name;
{
return (EINVAL);
/* assumes def_realm is initialized! */
return ENOMEM;
while (cp) {
break;
else
}
}
return retval;
}
{
if (code) {
const char *emsg;
} else {
}
}
int argc;
char *argv[];
{
extern char *optarg;
int db_args_size = 0;
if (retval) {
exit(1);
}
switch (optchar) {
case 'x':
db_args_size++;
{
argv[0]);
exit(1);
}
}
break;
case 'r':
break;
case 'p':
break;
case 'c':
break;
case 'k':
use_keytab++;
break;
case 't':
break;
case 'w':
break;
case 'q':
break;
case 'd':
/* now db_name is not a seperate argument. It has to be passed as part of the db_args */
if (!db_name) {
} else {
}
db_args_size++;
{
gettext("%s: Cannot initialize. Not enough memory\n"),
argv[0]);
exit(1);
}
}
break;
case 's':
break;
case 'm':
break;
case 'e':
", \t",
":.-",
0,
if (retval) {
exit(1);
}
break;
case 'O': /* Undocumented option for testing only */
break;
default:
}
}
if ((ccache_name && use_keytab) ||
(keytab_name && !use_keytab))
if (freeprinc)
exit(1);
}
gettext("%s: unable to get host based "
"service name for realm %s\n"),
if (freeprinc)
exit(1);
}
}
/*
* Set cc to an open credentials cache, either specified by the -c
* argument or the default.
*/
if (ccache_name == NULL) {
gettext("while opening default "
"credentials cache"));
exit(1);
}
} else {
gettext("while opening credentials cache %s"),
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
* 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 (ccache_name != NULL &&
gettext("while canonicalizing principal name"));
exit(1);
}
freeprinc++;
} else if (use_keytab != 0) {
"host",
&princ))) {
gettext("creating host service principal"));
exit(1);
}
gettext("while canonicalizing principal name"));
exit(1);
}
freeprinc++;
gettext("%s: unable to canonicalize "
"principal\n"), whoami);
exit(1);
}
/* strip out realm of principal if it's there */
while (realm) {
break;
else
}
if (realm)
*realm++ = '\0';
while (cp) {
break;
else
}
*cp = '\0';
gettext("%s: out of memory\n"),
whoami);
exit(1);
}
if (realm) {
}
freeprinc++;
gettext("%s: out of memory\n"),
whoami);
exit(1);
}
freeprinc++;
gettext("%s: out of memory\n"),
whoami);
exit(1);
}
freeprinc++;
} else {
gettext("%s: unable to figure out "
"a principal name\n"),
whoami);
exit(1);
}
}
if (retval) {
exit(1);
}
/*
* Initialize the kadm5 connection. If we were given a ccache,
*/
/* Solaris Kerberos:
* Send warnings to stderr
*/
if (ccache_name) {
princstr);
¶ms,
&handle);
} else if (use_keytab) {
if (keytab_name)
else
princstr);
¶ms,
&handle);
} else {
princstr);
¶ms,
&handle);
}
if (retval) {
if (retval == KADM5_RPC_ERROR_CANTENCODEARGS ||
} else {
if (retval == KADM5_BAD_CLIENT_PARAMS ||
}
exit(1);
}
if (freeprinc)
if (db_name)
if (db_args)
exit(1);
}
/* register the WRFILE keytab type and set it as the default */
{
/* XXX krb5_defkeyname is an internal library global and
should go away */
extern char *krb5_defkeyname;
}
exit(1);
}
/* Solaris kerberos: fix memory leak */
if (svcname)
return query;
}
int quit()
{
if (locked) {
if (retval) {
return 1;
}
locked = 0;
}
if (ccache_name != NULL) {
gettext("\n\a\a\aAdministration credentials "
"NOT DESTROYED.\n"));
}
/* insert more random cleanup here */
return 0;
}
int argc;
char *argv[];
{
if (locked)
return;
if (retval) {
return;
}
locked = 1;
}
int argc;
char *argv[];
{
if (!locked)
return;
if (retval) {
return;
}
locked = 0;
}
int argc;
char *argv[];
{
char *canon;
char reply[32];
if (! (argc == 2 ||
return;
}
if (retval) {
gettext("while parsing principal name"));
return;
}
if (retval) {
gettext("while canonicalizing principal"));
return;
}
if (argc == 2) {
gettext("Principal \"%s\" not deleted\n"),
canon);
return;
}
}
if (retval) {
return;
}
"from all ACLs before reusing.\n"));
return;
}
int argc;
char *argv[];
{
static char newpw[1024];
char *canon;
int n_ks_tuple = 0, randkey = 0;
int db_args_size = 0;
int local_kadmin = 0;
if (argc < 2) {
goto usage;
}
argc--;
if (argc < 1) {
goto usage;
}
db_args_size++;
{
exit(1);
}
}
continue;
}
argc--;
if (argc < 1) {
gettext("missing password arg\n"));
goto usage;
}
continue;
}
randkey++;
continue;
}
continue;
}
argc--;
if (argc < 1) {
gettext("missing keysaltlist arg\n"));
goto usage;
}
&ks_tuple, &n_ks_tuple);
if (retval) {
return;
}
continue;
}
goto usage;
}
goto usage;
}
if (retval) {
gettext("while parsing principal name"));
goto usage;
}
if (retval) {
gettext("while canonicalizing principal"));
return;
}
} else {
}
if (retval) {
gettext("while changing password for \"%s\"."),
canon);
return;
}
return;
} else if (randkey) {
} else {
}
if (retval) {
gettext("while randomizing key for \"%s\"."),
canon);
return;
}
return;
} else if (argc == 1) {
unsigned int i = sizeof (newpw) - 1;
gettext("Enter password for principal \"%.900s\""),
*argv);
gettext("Re-enter password for principal \"%.900s\""),
*argv);
newpw, &i);
if (retval) {
gettext("while reading password for \"%s\"."),
canon);
return;
}
newpw);
} else {
}
if (retval) {
gettext("while changing password for \"%s\"."),
canon);
return;
}
return;
} else {
"[-e keysaltlist] [-pw password] %s\n",
return;
}
}
static void
{
int i;
if (tl_data->tl_data_contents)
}
}
#define KRB5_TL_DB_ARGS 0x7fff
static int
int argc;
char *argv[];
long *mask;
char **pass;
int *randkey;
int *n_ks_tuple;
char *caller;
{
int i, j, attrib_set;
*mask = 0;
*n_ks_tuple = 0;
*randkey = 0;
attrib_set = 0;
if (++i > argc - 2)
return -1;
return ENOMEM;
}
if (tail) {
} else {
}
return ENOMEM;
}
*mask |= KADM5_TL_DATA;
continue;
}
if (++i > argc - 2)
return -1;
else {
gettext("Invalid date "
"specification "
"\"%s\".\n"),
argv[i]);
return -1;
}
continue;
}
}
if (++i > argc - 2)
return -1;
else {
gettext("Invalid date "
"specification "
"\"%s\".\n"),
argv[i]);
return -1;
}
*mask |= KADM5_PW_EXPIRATION;
continue;
}
}
if (++i > argc - 2)
return -1;
else {
gettext("Invalid date "
"specification "
"\"%s\".\n"),
argv[i]);
return -1;
}
gettext("Date specified is "
"in the past "
"\"%s\".\n"),
argv[i]);
return (-1);
}
*mask |= KADM5_MAX_LIFE;
continue;
}
}
if (++i > argc - 2)
return -1;
else {
gettext("Invalid date "
"specification "
"\"%s\".\n"),
argv[i]);
return -1;
}
gettext("Date specified is "
"in the past "
"\"%s\".\n"),
argv[i]);
return (-1);
}
*mask |= KADM5_MAX_RLIFE;
continue;
}
}
if (++i > argc - 2)
return -1;
else {
*mask |= KADM5_KVNO;
continue;
}
}
if (++i > argc - 2)
return -1;
else {
*mask |= KADM5_POLICY;
continue;
}
}
*mask |= KADM5_POLICY_CLR;
continue;
}
if (++i > argc - 2)
return -1;
else {
continue;
}
}
++*randkey;
continue;
}
if (++i > argc - 2)
return -1;
else {
if (retval) {
return -1;
}
}
continue;
}
*mask |= KADM5_ATTRIBUTES;
attrib_set++;
break;
*mask |= KADM5_ATTRIBUTES;
attrib_set++;
break;
} else {
return -1;
}
}
}
if (!attrib_set)
return -1; /* nothing was parsed */
}
if (i != argc - 1) {
return -1;
}
if (retval) {
return -1;
}
return 0;
}
static void
char *func;
{
gettext("[options] principal"));
"[-maxlife maxtixlife]\n\t\t[-kvno kvno] [-policy policy] "
"[-randkey] [-pw password]\n\t\t[-maxrenewlife maxrenewlife] "
"[-e keysaltlist] [{+|-}attribute]\n");
"\t\tallow_postdated allow_forwardable allow_tgs_req "
"allow_renewable\n",
"\t\tallow_proxiable allow_dup_skey allow_tix "
"requires_preauth\n",
"\t\trequires_hwauth needchange allow_svr "
"password_changing_service\n");
}
static void
char *func;
{
gettext("[options] principal"));
"[-maxlife maxtixlife]\n\t\t[-kvno kvno] [-policy policy] "
"[-clearpolicy]\n\t\t[-maxrenewlife maxrenewlife] "
"[{+|-}attribute]\n");
"\t\tallow_postdated allow_forwardable allow_tgs_req "
"allow_renewable\n",
"\t\tallow_proxiable allow_dup_skey allow_tix "
"requires_preauth\n",
"\t\trequires_hwauth needchange allow_svr "
"password_changing_service\n");
}
int argc;
char *argv[];
{
long mask;
int randkey = 0, i;
int n_ks_tuple;
int local_kadmin = 0;
if (dummybuf[0] == 0) {
for (i = 0; i < 256; i++)
}
/* Zero all fields in request structure */
&ks_tuple, &n_ks_tuple,
"add_principal")) {
kadmin_addprinc_usage("add_principal");
return;
}
if (retval) {
com_err("add_principal",
return;
}
/*
* If -policy was not specified, and -clearpolicy was not
* specified, and the policy "default" exists, assign it. If
* -clearpolicy was specified, then KADM5_POLICY_CLR should be
* unset, since it is never valid for kadm5_create_principal.
*/
if ((! (mask & KADM5_POLICY)) &&
(! (mask & KADM5_POLICY_CLR))) {
gettext("NOTICE: no policy specified for %s; assigning \"default\"\n"),
canon);
mask |= KADM5_POLICY;
} else
gettext("WARNING: no policy specified for %s; defaulting to no policy\n"),
canon);
}
mask &= ~KADM5_POLICY_CLR;
/*
* Set 'notix' for randkey principals and also for principals which have
* specified flag options on the cmdline. This is because we want to apply
* generic flag settings from 'default_principal_flags' first (during
* principal creation), followed by a kadm5_modify_principal() which
* correctly applies the cli flag options. So, we do *not* want any tix
* issued in the interim.
*/
if (randkey) {
mask |= KADM5_ATTRIBUTES;
gettext("Enter password for principal \"%.900s\""),
canon);
gettext("Re-enter password for principal \"%.900s\""),
canon);
if (retval) {
return;
}
}
mask |= KADM5_PRINCIPAL;
/*
* If the client being used is local, always use the new
* API so we get the full set of enctype support.
*/
} else {
}
if (retval) {
return;
}
if (randkey) { /* more special stuff for -randkey */
} else {
}
if (retval) {
return;
}
}
/*
* We now retrieve the intersection set of the generic flag settings and
* the ones specified on the cli & re-parse the princ args, just to make
* sure we account for conflicts between 'default_principal_flags' and
* the cmdline flag args. While we are here, also clear 'notix'.
*/
if (retval == 0) {
if (dprinc.attributes != 0)
} else {
"flag settings, as a result of a failed get_principal.\n"
"Check the 'default_principal_flags' setting in kdc.conf(4).\n"
"If there is a mismatch, use modprinc in kadmin(1M) to rectify "
"the same.\n\n"), canon);
}
/*
* Solaris Kerberos: We unset KRB5_KDB_DISALLOW_ALL_TIX before
* kadmin_parse_princ_args is called, because -allow_tix may
* have been an argument. We still have to unset here because
* kadmin_parse_princ_args will not reset the attribute unless
* it is was explicity defined.
*/
if (retval) {
gettext("while doing a modify_principal to restore flag "
"settings for \"%s\"."), canon);
return;
}
}
}
int argc;
char *argv[];
{
long mask;
int randkey = 0;
int n_ks_tuple = 0;
if (argc < 2) {
kadmin_modprinc_usage("modify_principal");
return;
}
if (retval) {
gettext("while parsing principal"));
return;
}
if (retval) {
gettext("while canonicalizing principal"));
return;
}
if (retval) {
return;
}
&ks_tuple, &n_ks_tuple,
"modify_principal");
kadmin_modprinc_usage("modify_principal");
return;
}
if (retval) {
kadmin_modprinc_usage("modify_principal");
return;
}
if (randkey) {
gettext("not allowed\n"));
return;
}
if (pass) {
"modify_principal: -pw %s change_password\n",
gettext("not allowed; use"));
return;
}
if (retval) {
return;
}
}
int argc;
char *argv[];
{
int i;
if (! (argc == 2 ||
return;
}
if (retval) {
gettext("while parsing principal"));
return;
}
if (retval) {
gettext("while canonicalizing principal"));
return;
}
if (retval) {
return;
}
if (retval) {
gettext("while unparsing modname"));
return;
}
if (argc == 2) {
gettext("[never]"));
gettext("[never]"));
gettext("[never]"));
gettext("[never]"));
for (i = 0; i < dprinc.n_key_data; i++) {
key_data->key_data_type[0]);
} else
}
for (i = 0; i < sizeof (prflags) / sizeof (char *); i++) {
}
printf("\n");
} 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",
for (i = 0; i < dprinc.n_key_data; i++)
printf("\t%d\t%d\t%d\t%d",
printf("\n");
}
}
int argc;
char *argv[];
{
int i, count;
int fd;
int waitb;
return;
}
if (retval) {
gettext("while retrieving list."));
return;
}
/*
* Solaris: the following code is used for paging
*/
sigemptyset(&nmask);
fd = ss_pager_create();
for (i = 0; i < count; i++)
/* Solaris Kerberos:
* Restore the original handler for SIGINT
*/
perror("sigaction");
}
}
static int
int argc;
char *argv[];
long *mask;
char *caller;
{
int i;
*mask = 0;
if (++i > argc -2)
return -1;
else {
argv[i]);
return -1;
}
gettext("Date specified is "
"in the past "
"\"%s\".\n"),
argv[i]);
return (-1);
}
*mask |= KADM5_PW_MAX_LIFE;
continue;
}
if (++i > argc - 2)
return -1;
else {
argv[i]);
return -1;
}
gettext("Date specified is "
"in the past "
"\"%s\".\n"),
argv[i]);
return (-1);
}
*mask |= KADM5_PW_MIN_LIFE;
continue;
}
if (++i > argc - 2)
return -1;
else {
*mask |= KADM5_PW_MIN_LENGTH;
continue;
}
if (++i > argc - 2)
return -1;
else {
*mask |= KADM5_PW_MIN_CLASSES;
continue;
}
if (++i > argc - 2)
return -1;
else {
*mask |= KADM5_PW_HISTORY_NUM;
continue;
}
} else
return -1;
}
if (i != argc -1) {
return -1;
} else
return 0;
}
static void
char *func;
{
gettext("[options] policy"));
"[-minlength length]\n\t\t[-minclasses number] "
"[-history number]\n");
}
int argc;
char *argv[];
{
long mask;
kadmin_addmodpol_usage("add_policy");
return;
} else {
mask |= KADM5_POLICY;
if (retval) {
gettext("while creating policy \"%s\"."),
return;
}
}
return;
}
int argc;
char *argv[];
{
long mask;
"modify_policy")) {
kadmin_addmodpol_usage("modify_policy");
return;
} else {
if (retval) {
return;
}
}
return;
}
int argc;
char *argv[];
{
char reply[32];
if (! (argc == 2 ||
return;
}
if (argc == 2) {
) {
gettext("Policy \"%s\" not deleted.\n"),
argv[1]);
return;
}
}
if (retval) {
gettext("while deleting policy \"%s\""),
return;
}
return;
}
int argc;
char *argv[];
{
if (! (argc == 2 ||
return;
}
if (retval) {
gettext("while retrieving policy \"%s\"."),
return;
}
if (argc == 2) {
"character classes: %ld\n"),
} else {
printf("\"%s\"\t%ld\t%ld\t%ld\t%ld\t%ld\t%ld\n",
}
return;
}
int argc;
char *argv[];
{
int i, count;
/* Solaris Kerberos:
* Use a pager for listing policies (similar to listing princs)
*/
int fd;
int waitb;
return;
}
if (retval) {
gettext("while retrieving list."));
return;
}
perror("sigemptyset");
return;
}
perror("sigaddset");
return;
}
perror("sigemptyset");
return;
}
perror("sigprocmask");
return;
}
perror("sigaction");
perror("sigprocmask");
}
return;
}
fd = ss_pager_create();
if (fd == -1) {
perror("sigprocmask");
}
perror("sigaction");
}
return;
}
perror("fdopen");
}
perror("sigprocmask");
}
for (i = 0; i < count; i++)
}
perror("fclose");
}
perror("wait");
}
perror("sigaction");
}
}