4.4BSD/usr/src/kerberosIV/kdb_edit/kdb_edit.c

Compare this file to the similar file:
Show the results in this format:

/*
 * $Source: /usr/src/kerberosIV/kdb_edit/RCS/kdb_edit.c,v $
 * $Author: torek $
 *
 * Copyright 1985, 1986, 1987, 1988 by the Massachusetts Institute
 * of Technology.
 *
 * For copying and distribution information, please see the file
 * <mit-copyright.h>.
 *
 * This routine changes the Kerberos encryption keys for principals,
 * i.e., users or services. 
 */

/*
 * exit returns 	 0 ==> success -1 ==> error 
 */

#ifndef	lint
static char rcsid_kdb_edit_c[] =
"$Id: kdb_edit.c,v 4.4 93/05/16 00:04:33 torek Exp $";
#endif	lint

#include <mit-copyright.h>

#include <stdio.h>
#include <signal.h>
#include <errno.h>
#include <strings.h>
#include <sys/ioctl.h>
#include <sys/file.h>
#include "time.h"
#include <des.h>
#include <krb.h>
#include <krb_db.h>
/* MKEYFILE is now defined in kdc.h */
#include <kdc.h>

extern char *errmsg();
extern int errno;
extern char *strcpy();

void    sig_exit();

#define zaptime(foo) bzero((char *)(foo), sizeof(*(foo)))

char    prog[32];
char   *progname = prog;
int     nflag = 0;
int     cflag;
int     lflag;
int     uflag;
int     debug;
extern  kerb_debug;

Key_schedule KS;
C_Block new_key;
unsigned char *input;

unsigned char *ivec;
int     i, j;
int     more;

char   *in_ptr;
char    input_name[ANAME_SZ];
char    input_instance[INST_SZ];
char    input_string[ANAME_SZ];

#define	MAX_PRINCIPAL	10
Principal principal_data[MAX_PRINCIPAL];

static Principal old_principal;
static Principal default_princ;

static C_Block master_key;
static C_Block session_key;
static Key_schedule master_key_schedule;
static char pw_str[255];
static long master_key_version;

#define	gets(buf) _gets(buf, sizeof(buf))	/* hack */

char *
_gets(p, n)
	char *p;
	int n;
{
	char *rv, *fgets();
	
	if ((rv = fgets(p, n, stdin)) == NULL)
		return (rv);
	if (p = index(p, '\n'))
		*p = '\0';
	return (rv);
}

main(argc, argv)
    int     argc;
    char   *argv[];

{
    /* Local Declarations */

    long    n;

    prog[sizeof prog - 1] = '\0';	/* make sure terminated */
    strncpy(prog, argv[0], sizeof prog - 1);	/* salt away invoking
						 * program */

    /* Assume a long is four bytes */
    if (sizeof(long) != 4) {
	fprintf(stdout, "%s: size of long is %d.\n", sizeof(long), prog);
	exit(-1);
    }
    /* Assume <=32 signals */
    if (NSIG > 32) {
	fprintf(stderr, "%s: more than 32 signals defined.\n", prog);
	exit(-1);
    }
    while (--argc > 0 && (*++argv)[0] == '-')
	for (i = 1; argv[0][i] != '\0'; i++) {
	    switch (argv[0][i]) {

		/* debug flag */
	    case 'd':
		debug = 1;
		continue;

		/* debug flag */
	    case 'l':
		kerb_debug |= 1;
		continue;

	    case 'n':		/* read MKEYFILE for master key */
		nflag = 1;
		continue;

	    default:
		fprintf(stderr, "%s: illegal flag \"%c\"\n",
			progname, argv[0][i]);
		Usage();	/* Give message and die */
	    }
	};

    fprintf(stdout, "Opening database...\n");
    fflush(stdout);
    kerb_init();
    if (argc > 0) {
	if (kerb_db_set_name(*argv) != 0) {
	    fprintf(stderr, "Could not open altername database name\n");
	    exit(1);
	}
    }

#ifdef	notdef
    no_core_dumps();		/* diddle signals to avoid core dumps! */

    /* ignore whatever is reasonable */
    signal(SIGHUP, SIG_IGN);
    signal(SIGINT, SIG_IGN);
    signal(SIGTSTP, SIG_IGN);

#endif

    if (kdb_get_master_key ((nflag == 0), 
			    master_key, master_key_schedule) != 0) {
      fprintf (stdout, "Couldn't read master key.\n");
      fflush (stdout);
      exit (-1);
    }

    if ((master_key_version = kdb_verify_master_key(master_key,
						    master_key_schedule,
						    stdout)) < 0)
      exit (-1);

    /* lookup the default values */
    n = kerb_get_principal(KERB_DEFAULT_NAME, KERB_DEFAULT_INST,
			   &default_princ, 1, &more);
    if (n != 1) {
	fprintf(stderr,
	     "%s: Kerberos error on default value lookup, %d found.\n",
		progname, n);
	exit(-1);
    }
    fprintf(stdout, "Previous or default values are in [brackets] ,\n");
    fprintf(stdout, "enter return to leave the same, or new value.\n");

    while (change_principal()) {
    }

    cleanup();
}

change_principal()
{
    static char temp[255];
    int     creating = 0;
    int     editpw = 0;
    int     changed = 0;
    long    temp_long;
    int     n;
    struct tm 	*tp, edate, *localtime();
    long 	maketime();

    fprintf(stdout, "\nPrincipal name: ");
    fflush(stdout);
    if (!gets(input_name) || *input_name == '\0')
	return 0;
    fprintf(stdout, "Instance: ");
    fflush(stdout);
    /* instance can be null */
    gets(input_instance);
    j = kerb_get_principal(input_name, input_instance, principal_data,
			   MAX_PRINCIPAL, &more);
    if (!j) {
	fprintf(stdout, "%s.%s not found, Create [y] ? ", input_name,
	    input_instance);
	gets(temp);		/* Default case should work, it didn't */
	if (temp[0] != 'y' && temp[0] != 'Y' && temp[0] != '\0')
	    return -1;
	/* make a new principal, fill in defaults */
	j = 1;
	creating = 1;
	strcpy(principal_data[0].name, input_name);
	strcpy(principal_data[0].instance, input_instance);
	principal_data[0].old = NULL;
	principal_data[0].exp_date = default_princ.exp_date;
	principal_data[0].max_life = default_princ.max_life;
	principal_data[0].attributes = default_princ.attributes;
	principal_data[0].kdc_key_ver = (unsigned char) master_key_version;
	principal_data[0].key_version = 0; /* bumped up later */
    }
    tp = localtime(&principal_data[0].exp_date);
    (void) sprintf(principal_data[0].exp_date_txt, "%4d-%02d-%02d",
		   tp->tm_year > 1900 ? tp->tm_year : tp->tm_year + 1900,
		   tp->tm_mon + 1, tp->tm_mday); /* January is 0, not 1 */
    for (i = 0; i < j; i++) {
	for (;;) {
	    fprintf(stdout,
		    "Principal: %s, Instance: %s, kdc_key_ver: %d\n",
		    principal_data[i].name, principal_data[i].instance,
		    principal_data[i].kdc_key_ver);
	    editpw = 1;
	    changed = 0;
	    if (!creating) {
		/*
		 * copy the existing data so we can use the old values
		 * for the qualifier clause of the replace 
		 */
		principal_data[i].old = (char *) &old_principal;
		bcopy(&principal_data[i], &old_principal,
		      sizeof(old_principal));
		printf("Change password [n] ? ");
		gets(temp);
		if (strcmp("y", temp) && strcmp("Y", temp))
		    editpw = 0;
	    }
	    /* password */
	    if (editpw) {
#ifdef NOENCRYPTION
		placebo_read_pw_string(pw_str, sizeof pw_str,
		    "New Password: ", TRUE);
#else
		des_read_pw_string(pw_str, sizeof pw_str,
		    "New Password: ", TRUE);
#endif
		if (pw_str[0] == '\0' || !strcmp(pw_str, "RANDOM")) {
		    printf("Random password [y] ? ");
		    gets(temp);
		    if (!strcmp("n", temp) || !strcmp("N", temp)) {
			/* no, use literal */
#ifdef NOENCRYPTION
			bzero(new_key, sizeof(C_Block));
			new_key[0] = 127;
#else
			string_to_key(pw_str, new_key);
#endif
			bzero(pw_str, sizeof pw_str);	/* "RANDOM" */
		    } else {
#ifdef NOENCRYPTION
			bzero(new_key, sizeof(C_Block));
			new_key[0] = 127;
#else
			random_key(new_key);	/* yes, random */
#endif
			bzero(pw_str, sizeof pw_str);
		    }
		} else if (!strcmp(pw_str, "NULL")) {
		    printf("\nNull Key [y] ? ");
		    gets(temp);
		    if (!strcmp("n", temp) || !strcmp("N", temp)) {
			/* no, use literal */
#ifdef NOENCRYPTION
			bzero(new_key, sizeof(C_Block));
			new_key[0] = 127;
#else
			string_to_key(pw_str, new_key);
#endif
			bzero(pw_str, sizeof pw_str);	/* "NULL" */
		    } else {

			principal_data[i].key_low = 0;
			principal_data[i].key_high = 0;
			goto null_key;
		    }
		} else {
#ifdef NOENCRYPTION
		    bzero(new_key, sizeof(C_Block));
		    new_key[0] = 127;
#else
		    string_to_key(pw_str, new_key);
#endif
		    bzero(pw_str, sizeof pw_str);
		}

		/* seal it under the kerberos master key */
		kdb_encrypt_key (new_key, new_key, 
				 master_key, master_key_schedule,
				 ENCRYPT);
		bcopy(new_key, &principal_data[i].key_low, 4);
		bcopy(((long *) new_key) + 1,
		    &principal_data[i].key_high, 4);
		bzero(new_key, sizeof(new_key));
	null_key:
		/* set master key version */
		principal_data[i].kdc_key_ver =
		    (unsigned char) master_key_version;
		/* bump key version # */
		principal_data[i].key_version++;
		fprintf(stdout,
			"\nPrincipal's new key version = %d\n",
			principal_data[i].key_version);
		fflush(stdout);
		changed = 1;
	    }
	    /* expiration date */
	    fprintf(stdout, "Expiration date (enter yyyy-mm-dd) [ %s ] ? ",
		    principal_data[i].exp_date_txt);
	    zaptime(&edate);
	    while (gets(temp) && ((n = strlen(temp)) >
				  sizeof(principal_data[0].exp_date_txt))) {
	    bad_date:
		fprintf(stdout, "\07\07Date Invalid\n");
		fprintf(stdout,
			"Expiration date (enter yyyy-mm-dd) [ %s ] ? ",
			principal_data[i].exp_date_txt);
		zaptime(&edate);
	    }

	    if (*temp) {
		if (sscanf(temp, "%d-%d-%d", &edate.tm_year,
			      &edate.tm_mon, &edate.tm_mday) != 3)
		    goto bad_date;
		(void) strcpy(principal_data[i].exp_date_txt, temp);
		edate.tm_mon--;		/* January is 0, not 1 */
		edate.tm_hour = 23;	/* nearly midnight at the end of the */
		edate.tm_min = 59;	/* specified day */
		if (!(principal_data[i].exp_date = maketime(&edate, 1)))
		    goto bad_date;
		changed = 1;
	    }

	    /* maximum lifetime */
	    fprintf(stdout, "Max ticket lifetime (*5 minutes) [ %d ] ? ",
		    principal_data[i].max_life);
	    while (gets(temp) && *temp) {
		if (sscanf(temp, "%d", &temp_long) != 1)
		    goto bad_life;
		if (temp_long > 255 || (temp_long < 0)) {
		bad_life:
		    fprintf(stdout, "\07\07Invalid, choose 0-255\n");
		    fprintf(stdout,
			    "Max ticket lifetime (*5 minutes) [ %d ] ? ",
			    principal_data[i].max_life);
		    continue;
		}
		changed = 1;
		/* dont clobber */
		principal_data[i].max_life = (unsigned short) temp_long;
		break;
	    }

	    /* attributes */
	    fprintf(stdout, "Attributes [ %d ] ? ",
		    principal_data[i].attributes);
	    while (gets(temp) && *temp) {
		if (sscanf(temp, "%d", &temp_long) != 1)
		    goto bad_att;
		if (temp_long > 65535 || (temp_long < 0)) {
		bad_att:
		    fprintf(stdout, "\07\07Invalid, choose 0-65535\n");
		    fprintf(stdout, "Attributes [ %d ] ? ",
			    principal_data[i].attributes);
		    continue;
		}
		changed = 1;
		/* dont clobber */
		principal_data[i].attributes =
		    (unsigned short) temp_long;
		break;
	    }

	    /*
	     * remaining fields -- key versions and mod info, should
	     * not be directly manipulated 
	     */
	    if (changed) {
		if (kerb_put_principal(&principal_data[i], 1)) {
		    fprintf(stdout,
			"\nError updating Kerberos database");
		} else {
		    fprintf(stdout, "Edit O.K.");
		}
	    } else {
		fprintf(stdout, "Unchanged");
	    }


	    bzero(&principal_data[i].key_low, 4);
	    bzero(&principal_data[i].key_high, 4);
	    fflush(stdout);
	    break;
	}
    }
    if (more) {
	fprintf(stdout, "\nThere were more tuples found ");
	fprintf(stdout, "than there were space for");
      }
    return 1;
}


no_core_dumps()
{

    signal(SIGQUIT, sig_exit);
    signal(SIGILL, sig_exit);
    signal(SIGTRAP, sig_exit);
    signal(SIGIOT, sig_exit);
    signal(SIGEMT, sig_exit);
    signal(SIGFPE, sig_exit);
    signal(SIGBUS, sig_exit);
    signal(SIGSEGV, sig_exit);
    signal(SIGSYS, sig_exit);
}

void
sig_exit(sig, code, scp)
    int     sig, code;
    struct sigcontext *scp;
{
    cleanup();
    fprintf(stderr,
	"\nSignal caught, sig = %d code = %d old pc = 0x%X \nexiting",
        sig, code, scp->sc_pc);
    exit(-1);
}


cleanup()
{

    bzero(master_key, sizeof(master_key));
    bzero(session_key, sizeof(session_key));
    bzero(master_key_schedule, sizeof(master_key_schedule));
    bzero(principal_data, sizeof(principal_data));
    bzero(new_key, sizeof(new_key));
    bzero(pw_str, sizeof(pw_str));
}
Usage()
{
    fprintf(stderr, "Usage: %s [-n]\n", progname);
    exit(1);
}