Beispiel #1
0
static afs_int32
check_auth(struct packet *pkt, char *auth, int authLen,
	   struct ktc_encryptionKey *key, char *name, char *inst,
	   char *cell)
{
    char *packet;
    DES_key_schedule schedule;
    afs_int32 cksum;
    afs_int32 time_sec;
    int byteOrder = pkt->byteOrder;

    DES_key_sched(ktc_to_cblock(key), &schedule);
    DES_pcbc_encrypt(auth, auth, authLen, &schedule, ktc_to_cblockptr(key), DECRYPT);
    packet = auth;
    if (strcmp(packet, name) != 0)
	return KABADTICKET;
    packet += strlen(packet) + 1;
    if (strcmp(packet, inst) != 0)
	return KABADTICKET;
    packet += strlen(packet) + 1;
    if (strcmp(packet, cell) != 0)
	return KABADTICKET;
    packet += strlen(packet) + 1;
    getint(cksum);
    /* Comments in the original IBM source suggest this byte was/is "time_msec" */
    packet++;
    getint(time_sec);
    if ((packet - auth) > authLen)
	return KABADTICKET;
    return 0;
}
Beispiel #2
0
int
tkt_MakeTicket(char *ticket, int *ticketLen, struct ktc_encryptionKey *key,
	       char *name, char *inst, char *cell, afs_uint32 start,
	       afs_uint32 end, struct ktc_encryptionKey *sessionKey,
	       afs_uint32 host, char *sname, char *sinst)
{
    int code;
    union Key_schedule_safe schedule;

    *ticketLen = 0;		/* in case we return early */
    code =
	assemble_athena_ticket(ticket, ticketLen, name, inst, cell, host,
			       sessionKey, start, end, sname, sinst);
    *ticketLen = round_up_to_ebs(*ticketLen);	/* round up */
    if (code)
	return -1;

    /* encrypt ticket */
    if ((code = key_sched(ktc_to_cblock(key), schedule.schedule))) {
	printf("In tkt_MakeTicket: key_sched returned %d\n", code);
	return RXKADBADKEY;
    }
    pcbc_encrypt(ticket, ticket, *ticketLen, schedule.schedule, ktc_to_cblockptr(key), ENCRYPT);
    return 0;
}
Beispiel #3
0
static afs_int32
create_cipher(char *cipher, int *cipherLen,
	      struct ktc_encryptionKey *sessionKey, char *sname,
	      char *sinst, Date start, Date end, afs_int32 kvno,
	      char *ticket, int ticketLen, struct ktc_encryptionKey *key)
{
    char *answer;
    int slen;
    unsigned char life = time_to_life(start, end);
    int len;
    DES_key_schedule schedule;
    afs_int32 code;

    answer = cipher;
    len =
	sizeof(*sessionKey) + strlen(sname) + strlen(sinst) + strlen(lrealm) +
	3 /*nulls */  + 3 + ticketLen + sizeof(Date);
    if (len > *cipherLen)
	return KAANSWERTOOLONG;
    if (ticketLen > 255)
	return KAANSWERTOOLONG;
    if (kvno > 255)
	return KAANSWERTOOLONG;

    memcpy(answer, sessionKey, sizeof(*sessionKey));
    answer += sizeof(*sessionKey);
    putstr(sname);
    putstr(sinst);
    putstr(lrealm);
    *answer++ = life;
    *answer++ = (unsigned char)kvno;
    *answer++ = (unsigned char)ticketLen;
    memcpy(answer, ticket, ticketLen);
    answer += ticketLen;
    putint(start);

    if (krb_udp_debug) {
	printf("Printing ticket (%d) and date: ", ticketLen);
	ka_PrintBytes(ticket, ticketLen);
	ka_PrintBytes(answer - 4, 4);
	printf("\n");
    }

    if ((code = DES_key_sched(ktc_to_cblock(key), &schedule)))
	printf("In KAAuthenticate: key_sched returned %d\n", code);
    DES_pcbc_encrypt(cipher, cipher, len, &schedule, ktc_to_cblockptr(key), ENCRYPT);
    *cipherLen = round_up_to_ebs(len);

    if (krb_udp_debug) {
	printf("Printing cipher (%d): ", *cipherLen);
	ka_PrintBytes(cipher, *cipherLen);
	printf("\n");
    }
    return 0;
}
Beispiel #4
0
int
tkt_DecodeTicket(char *asecret, afs_int32 ticketLen,
		 struct ktc_encryptionKey *key, char *name, char *inst,
		 char *cell, struct ktc_encryptionKey *sessionKey, afs_int32 * host,
		 afs_uint32 * start, afs_uint32 * end)
{
    char clear_ticket[MAXKTCTICKETLEN];
    char *ticket;
    union Key_schedule_safe schedule;
    int code;

    if (ticketLen == 0)
	return RXKADBADTICKET;	/* no ticket */
    if ((ticketLen < MINKTCTICKETLEN) ||	/* minimum legal ticket size */
	(ticketLen > MAXKTCTICKETLEN) ||	/* maximum legal ticket size */
	((ticketLen) % 8 != 0))	/* enc. part must be (0 mod 8) bytes */
	return RXKADBADTICKET;

    if (key_sched(ktc_to_cblock(key), schedule.schedule))
	return RXKADBADKEY;

    ticket = clear_ticket;
    pcbc_encrypt(asecret, ticket, ticketLen, schedule.schedule, ktc_to_cblockptr(key), DECRYPT);

    code =
	decode_athena_ticket(ticket, ticketLen, name, inst, cell, host,
			     (struct ktc_encryptionKey *)sessionKey, start, end);

    if (code)
	return RXKADBADTICKET;

    code = tkt_CheckTimes(*start, *end, time(0));
    if (code == 0)
	return RXKADNOAUTH;
    else if (code == -1)
	return RXKADEXPIRED;
    else if (code < -1)
	return RXKADBADTICKET;

    return 0;
}
Beispiel #5
0
int
main(int argc, char **argv)
{
    struct afsconf_dir *tdir;
    afs_int32 code;

    if (argc == 1) {
	printf("bos_util: usage is 'bos_util <opcode> options, e.g.\n");
	printf("    bos_util add <kvno>\n");
	printf("    bos_util adddes <kvno>\n");
#ifdef KERBEROS
	printf("    bos_util srvtab2keyfile <kvno> <keyfile> <princ>\n");
#endif
	printf("    bos_util delete <kvno>\n");
	printf("    bos_util list\n");
	exit(1);
    }

    tdir = afsconf_Open(AFSDIR_SERVER_ETC_DIR);
    if (!tdir) {
	printf("bos_util: can't initialize conf dir '%s'\n",
	       AFSDIR_SERVER_ETC_DIR);
	exit(1);
    }
    if (strcmp(argv[1], "add") == 0) {
	struct ktc_encryptionKey tkey;
	int kvno;
	char buf[BUFSIZ], ver[BUFSIZ];
	char *tcell = NULL;

	if (argc != 3) {
	    printf("bos_util add: usage is 'bos_util add <kvno>\n");
	    exit(1);
	}
	kvno = atoi(argv[2]);
	memset(&tkey, 0, sizeof(struct ktc_encryptionKey));

	/* prompt for key */
	code = des_read_pw_string(buf, sizeof(buf), "input key: ", 0);
	if (code || strlen(buf) == 0) {
	    printf("Bad key: \n");
	    exit(1);
	}
	code = des_read_pw_string(ver, sizeof(ver), "Retype input key: ", 0);
	if (code || strlen(ver) == 0) {
	    printf("Bad key: \n");
	    exit(1);
	}
	if (strcmp(ver, buf) != 0) {
	    printf("\nInput key mismatch\n");
	    exit(1);
	}
	ka_StringToKey(buf, tcell, &tkey);
	code = afsconf_AddKey(tdir, kvno, ktc_to_charptr(&tkey), 0);
	if (code) {
	    printf("bos_util: failed to set key, code %d.\n", code);
	    exit(1);
	}
    } else if (strcmp(argv[1], "adddes") == 0) {
	struct ktc_encryptionKey tkey;
	int kvno;
	afs_int32 code;
	char buf[BUFSIZ], ver[BUFSIZ];

	if (argc != 3) {
	    printf("bos_util adddes: usage is 'bos_util adddes <kvno>\n");
	    exit(1);
	}
	kvno = atoi(argv[2]);
	memset(&tkey, 0, sizeof(struct ktc_encryptionKey));

	/* prompt for key */
	code = des_read_pw_string(buf, sizeof(buf), "input key: ", 0);
	if (code || strlen(buf) == 0) {
	    printf("Bad key: \n");
	    exit(1);
	}
	code = des_read_pw_string(ver, sizeof(ver), "Retype input key: ", 0);
	if (code || strlen(ver) == 0) {
	    printf("Bad key: \n");
	    exit(1);
	}
	if (strcmp(ver, buf) != 0) {
	    printf("\nInput key mismatch\n");
	    exit(1);
	}
	des_string_to_key(buf, ktc_to_cblockptr(&tkey));
	code = afsconf_AddKey(tdir, kvno, ktc_to_charptr(&tkey), 0);
	if (code) {
	    printf("bos_util: failed to set key, code %d.\n", code);
	    exit(1);
	}
    }
#ifdef KERBEROS
    else if (strcmp(argv[1], "srvtab2keyfile") == 0) {
	char tkey[8], name[255], inst[255], realm[255];
	int kvno;
	if (argc != 5) {
	    printf
		("bos_util add: usage is 'bos_util srvtab2keyfile <kvno> <keyfile> <princ>\n");
	    exit(1);
	}
	kvno = atoi(argv[2]);
	bzero(tkey, sizeof(tkey));
	code = kname_parse(name, inst, realm, argv[4]);
	if (code != 0) {
	    printf("Invalid kerberos name\n");
	    exit(1);
	}
	code = read_service_key(name, inst, realm, kvno, argv[3], tkey);
	if (code != 0) {
	    printf("Can't find key in %s\n", argv[3]);
	    exit(1);
	}
	code = afsconf_AddKey(tdir, kvno, tkey, 0);
	if (code) {
	    printf("bos_util: failed to set key, code %d.\n", code);
	    exit(1);
	}
    }
#endif
    else if (strcmp(argv[1], "delete") == 0) {
	long kvno;
	if (argc != 3) {
	    printf("bos_util delete: usage is 'bos_util delete <kvno>\n");
	    exit(1);
	}
	kvno = atoi(argv[2]);
	code = afsconf_DeleteKey(tdir, kvno);
	if (code) {
	    printf("bos_util: failed to delete key %ld, (code %d)\n", kvno,
		   code);
	    exit(1);
	}
    } else if (strcmp(argv[1], "list") == 0) {
	struct afsconf_keys tkeys;
	int i;
	unsigned char tbuffer[9];

	code = afsconf_GetKeys(tdir, &tkeys);
	if (code) {
	    printf("bos_util: failed to get keys, code %d\n", code);
	    exit(1);
	}
	for (i = 0; i < tkeys.nkeys; i++) {
	    if (tkeys.key[i].kvno != -1) {
		int count;
		unsigned char x[8];
		memcpy(tbuffer, tkeys.key[i].key, 8);
		tbuffer[8] = 0;
		printf("kvno %4d: key is '%s' '", tkeys.key[i].kvno, tbuffer);
		strcpy((char *)x, (char *)tbuffer);
		for (count = 0; count < 8; count++)
		    printf("\\%03o", x[count]);
		printf("'\n");
	    }
	}
	printf("All done.\n");
    } else {
	printf
	    ("bos_util: unknown operation '%s', type 'bos_util' for assistance\n",
	     argv[1]);
	exit(1);
    }
    exit(0);
}
Beispiel #6
0
afs_int32
ka_UserAuthenticateGeneral(afs_int32 flags, char *name, char *instance,
			   char *realm, char *password, Date lifetime,
			   afs_int32 * password_expires,	/* days 'til, or don't change if not set */
			   afs_int32 spare2, char **reasonP)
{
    int remainingTime = 0;
    struct ktc_encryptionKey key;
    afs_int32 code, dosetpag = 0;

    if (reasonP)
	*reasonP = "";
    if ((flags & KA_USERAUTH_VERSION_MASK) != KA_USERAUTH_VERSION)
	return KAOLDINTERFACE;
    if ((strcmp(name, "root") == 0) && (instance == 0)) {
	if (reasonP)
	    *reasonP = "root is only authenticated locally";
	return KANOENT;
    }
    code = ka_Init(0);
    if (code)
	return code;

    ka_StringToKey(password, realm, &key);

/*
 * alarm is set by kpasswd only so ignore for
 * NT
 */

#ifndef AFS_NT40_ENV
    {				/* Rx uses timers, save to be safe */
	if (rx_socket) {
	    /* don't reset alarms, rx already running */
	    remainingTime = 0;
	} else
	    remainingTime = alarm(0);
    }
#endif

#if !defined(AFS_NT40_ENV) && !defined(AFS_LINUX20_ENV) && !defined(AFS_USR_LINUX20_ENV) && (!defined(AFS_XBSD_ENV) || defined(AFS_FBSD_ENV))
    /* handle smoothly the case where no AFS system calls exists (yet) */
    (void)signal(SIGSYS, SIG_IGN);
#endif
#ifdef	AFS_DECOSF_ENV
    (void)signal(SIGTRAP, SIG_IGN);
#endif /* AFS_DECOSF_ENV */
    if (instance == 0)
	instance = "";
    if (flags & KA_USERAUTH_ONLY_VERIFY) {
	code = ka_VerifyUserToken(name, instance, realm, &key);
	if (code == KABADREQUEST) {
	    DES_string_to_key(password, ktc_to_cblockptr(&key));
	    code = ka_VerifyUserToken(name, instance, realm, &key);
	}
    } else {
#ifdef AFS_DUX40_ENV
	if (flags & KA_USERAUTH_DOSETPAG)
	    afs_setpag();
#else
#if !defined(UKERNEL) && !defined(AFS_NT40_ENV)
	if (flags & KA_USERAUTH_DOSETPAG)
	    setpag();
#endif
#endif
	if (flags & KA_USERAUTH_DOSETPAG2)
	    dosetpag = 1;
#ifdef AFS_KERBEROS_ENV
	if ((flags & KA_USERAUTH_DOSETPAG) || dosetpag)
	    ktc_newpag();
#endif
	if (lifetime == 0)
	    lifetime = MAXKTCTICKETLIFETIME;
	code =
	    GetTickets(name, instance, realm, &key, lifetime,
		       password_expires, dosetpag);
	if (code == KABADREQUEST) {
	    DES_string_to_key(password, ktc_to_cblockptr(&key));
	    code =
		GetTickets(name, instance, realm, &key, lifetime,
			   password_expires, dosetpag);
	}
    }

#ifndef AFS_NT40_ENV
    if (remainingTime) {
	pr_End();
	rx_Finalize();
	alarm(remainingTime);	/* restore timer, if any */
    }
#endif

    if (code && reasonP)
	switch (code) {
	case KABADREQUEST:
	    *reasonP = "password was incorrect";
	    break;
	case KAUBIKCALL:
	    *reasonP = "Authentication Server was unavailable";
	    break;
	default:
	    *reasonP = (char *)afs_error_message(code);
	}
    return code;
}
Beispiel #7
0
int
CommandProc(struct cmd_syndesc *as, void *arock)
{
    char name[MAXKTCNAMELEN] = "";
    char instance[MAXKTCNAMELEN] = "";
    char cell[MAXKTCREALMLEN] = "";
    char realm[MAXKTCREALMLEN] = "";
    afs_int32 serverList[MAXSERVERS];
    char *lcell;		/* local cellname */
    int code;
    int i;

    struct ubik_client *conn = 0;
    struct ktc_encryptionKey key;
    struct ktc_encryptionKey mitkey;
    struct ktc_encryptionKey newkey;
    struct ktc_encryptionKey newmitkey;

    struct ktc_token token;

    struct passwd pwent;
    struct passwd *pw = &pwent;

    int insist;			/* insist on good password quality */
    int lexplicit = 0;		/* servers specified explicitly */
    int local;			/* explicit cell is same a local cell */
    int foundPassword = 0;	/*Not yet, anyway */
    int foundNewPassword = 0;	/*Not yet, anyway */
    int foundExplicitCell = 0;	/*Not yet, anyway */
#ifdef DEFAULT_MITV4_STRINGTOKEY
    int dess2k = 1;
#elif DEFAULT_AFS_STRINGTOKEY
    int dess2k = 0;
#else
    int dess2k = -1;
#endif

    /* blow away command line arguments */
    for (i = 1; i < zero_argc; i++)
	memset(zero_argv[i], 0, strlen(zero_argv[i]));
    zero_argc = 0;

    /* first determine quiet flag based on -pipe switch */
    Pipe = (as->parms[aPIPE].items ? 1 : 0);

#if TIMEOUT
    signal(SIGALRM, timedout);
    alarm(30);
#endif

    code = ka_Init(0);
    if (code || !(lcell = ka_LocalCell())) {
#ifndef AFS_FREELANCE_CLIENT
	if (!Pipe)
	    afs_com_err(rn, code, "Can't get local cell name!");
	exit(1);
#endif
    }

    code = rx_Init(0);
    if (code) {
	if (!Pipe)
	    afs_com_err(rn, code, "Failed to initialize Rx");
	exit(1);
    }

    strcpy(instance, "");

    /* Parse our arguments. */

    if (as->parms[aCELL].items) {
	/*
	 * cell name explicitly mentioned; take it in if no other cell name
	 * has already been specified and if the name actually appears.  If
	 * the given cell name differs from our own, we don't do a lookup.
	 */
	foundExplicitCell = 1;
	strncpy(realm, as->parms[aCELL].items->data, sizeof(realm));
    }

    if (as->parms[aSERVERS].items) {
	/* explicit server list */
	int i;
	struct cmd_item *ip;
	char *ap[MAXSERVERS + 2];

	for (ip = as->parms[aSERVERS].items, i = 2; ip; ip = ip->next, i++)
	    ap[i] = ip->data;
	ap[0] = "";
	ap[1] = "-servers";
	code = ubik_ParseClientList(i, ap, serverList);
	if (code) {
	    if (!Pipe)
		afs_com_err(rn, code, "could not parse server list");
	    return code;
	}
	lexplicit = 1;
    }

    if (as->parms[aPRINCIPAL].items) {
	ka_ParseLoginName(as->parms[aPRINCIPAL].items->data, name, instance,
			  cell);
	if (strlen(instance) > 0)
	    if (!Pipe)
		fprintf(stderr,
			"Non-null instance (%s) may cause strange behavior.\n",
			instance);
	if (strlen(cell) > 0) {
	    if (foundExplicitCell) {
		if (!Pipe)
		    fprintf(stderr,
			    "%s: May not specify an explicit cell twice.\n",
			    rn);
		return -1;
	    }
	    foundExplicitCell = 1;
	    strncpy(realm, cell, sizeof(realm));
	}
	pw->pw_name = name;
    } else {
	/* No explicit name provided: use Unix uid. */
#ifdef AFS_NT40_ENV
	userNameLen = 128;
	if (GetUserName(userName, &userNameLen) == 0) {
	    if (!Pipe) {
		fprintf(stderr,
			"Can't figure out your name in local cell %s from your user id.\n",
			lcell);
		fprintf(stderr, "Try providing the user name.\n");
	    }
	    exit(1);
	}
	pw->pw_name = userName;
#else
	pw = getpwuid(getuid());
	if (pw == 0) {
	    if (!Pipe) {
		fprintf(stderr,
			"Can't figure out your name in local cell %s from your user id.\n",
			lcell);
		fprintf(stderr, "Try providing the user name.\n");
	    }
	    exit(1);
	}
#endif
    }

    if (as->parms[aPASSWORD].items) {
	/*
	 * Current argument is the desired password string.  Remember it in
	 * our local buffer, and zero out the argument string - anyone can
	 * see it there with ps!
	 */
	foundPassword = 1;
	strncpy(passwd, as->parms[aPASSWORD].items->data, sizeof(passwd));
	memset(as->parms[aPASSWORD].items->data, 0,
	       strlen(as->parms[aPASSWORD].items->data));
    }

    if (as->parms[aNEWPASSWORD].items) {
	/*
	 * Current argument is the new password string.  Remember it in
	 * our local buffer, and zero out the argument string - anyone can
	 * see it there with ps!
	 */
	foundNewPassword = 1;
	strncpy(npasswd, as->parms[aNEWPASSWORD].items->data,
		sizeof(npasswd));
	memset(as->parms[aNEWPASSWORD].items->data, 0,
	       strlen(as->parms[aNEWPASSWORD].items->data));
    }
#ifdef AFS_FREELANCE_CLIENT
    if (!foundExplicitCell && !lcell) {
	if (!Pipe)
	    afs_com_err(rn, code, "no cell name provided");
	exit(1);
    }
#else
    if (!foundExplicitCell)
	strcpy(realm, lcell);
#endif /* freelance */

    if ((code = ka_CellToRealm(realm, realm, &local))) {
	if (!Pipe)
	    afs_com_err(rn, code, "Can't convert cell to realm");
	exit(1);
    }
    lcstring(cell, realm, sizeof(cell));

    ka_PrintUserID("Changing password for '", pw->pw_name, instance, "'");
    printf(" in cell '%s'.\n", cell);

    /* Get the password if it wasn't provided. */
    if (!foundPassword) {
	if (Pipe)
	    getpipepass(passwd, sizeof(passwd));
	else {
	    code = read_pass(passwd, sizeof(passwd), "Old password: "******"reading password");
		exit(1);
	    }
	}
    }
    ka_StringToKey(passwd, realm, &key);
    des_string_to_key(passwd, ktc_to_cblockptr(&mitkey));
    give_to_child(passwd);

    /* Get new password if it wasn't provided. */
    insist = 0;
    if (!foundNewPassword) {
	if (Pipe)
	    getpipepass(npasswd, sizeof(npasswd));
	else {
	    do {
		code =
		    read_pass(npasswd, sizeof(npasswd),
			      "New password (RETURN to abort): ", 0);
		if (code || (strlen(npasswd) == 0)) {
		    if (code)
			code = KAREADPW;
		    goto no_change;

		}
	    } while (password_bad(npasswd));

	    code =
		read_pass(verify, sizeof(verify), "Retype new password: "******"Mismatch - ");
		goto no_change;
	    }
	    memset(verify, 0, sizeof(verify));
	}
    }
    if ((code = password_bad(npasswd))) {	/* assmt here! */
	goto no_change_no_msg;
    }
#if TRUNCATEPASSWORD
    if (strlen(npasswd) > 8) {
	npasswd[8] = 0;
	fprintf(stderr,
		"%s: password too long, only the first 8 chars will be used.\n",
		rn);
    } else
	npasswd[8] = 0;		/* in case the password was exactly 8 chars long */
#endif
    ka_StringToKey(npasswd, realm, &newkey);
    des_string_to_key(npasswd, ktc_to_cblockptr(&newmitkey));
    memset(npasswd, 0, sizeof(npasswd));

    if (lexplicit)
	ka_ExplicitCell(realm, serverList);

    /* Get an connection to kaserver's admin service in desired cell.  Set the
     * lifetime above the time uncertainty so that badly skewed clocks are
     * reported when the ticket is decrypted.  Then give us 10 seconds to
     * actually get our work done if the clocks are skewed by only 14:59.
     * NOTE: Kerberos lifetime encoding will round this up to next 5 minute
     * interval, namely 20 minutes. */

#define ADMIN_LIFETIME (KTC_TIME_UNCERTAINTY+1)

    code =
	ka_GetAdminToken(pw->pw_name, instance, realm, &key, ADMIN_LIFETIME,
			 &token, /*!new */ 0);
    if (code == KABADREQUEST) {
	code =
	    ka_GetAdminToken(pw->pw_name, instance, realm, &mitkey,
			     ADMIN_LIFETIME, &token, /*!new */ 0);
	if ((code == KABADREQUEST) && (strlen(passwd) > 8)) {
	    /* try with only the first 8 characters incase they set their password
	     * with an old style passwd program. */
	    char pass8[9];
	    strncpy(pass8, passwd, 8);
	    pass8[8] = 0;
	    ka_StringToKey(pass8, realm, &key);
	    memset(pass8, 0, sizeof(pass8));
	    memset(passwd, 0, sizeof(passwd));
	    code = ka_GetAdminToken(pw->pw_name, instance, realm, &key, ADMIN_LIFETIME, &token,	/*!new */
				    0);
#ifdef notdef
	    /* the folks in testing really *hate* this message */
	    if (code == 0) {
		fprintf(stderr,
			"Warning: only the first 8 characters of your old password were significant.\n");
	    }
#endif
	    if (code == 0) {
		if (dess2k == -1)
		    dess2k = 0;
	    }
	} else {
	    if (dess2k == -1)
		dess2k = 1;
	}
    } else {
	if (dess2k == -1)
	    dess2k = 0;
    }

    memset(&mitkey, 0, sizeof(mitkey));
    memset(&key, 0, sizeof(key));
    if (code == KAUBIKCALL)
	afs_com_err(rn, code, "(Authentication Server unavailable, try later)");
    else if (code) {
	if (code == KABADREQUEST)
	    fprintf(stderr, "%s: Incorrect old password.\n", rn);
	else
	    afs_com_err(rn, code, "so couldn't change password");
    } else {
	code =
	    ka_AuthServerConn(realm, KA_MAINTENANCE_SERVICE, &token, &conn);
	if (code)
	    afs_com_err(rn, code, "contacting Admin Server");
	else {
	    if (dess2k == 1)
		code =
		    ka_ChangePassword(pw->pw_name, instance, conn, 0,
				      &newmitkey);
	    else
		code =
		    ka_ChangePassword(pw->pw_name, instance, conn, 0,
				      &newkey);
	    memset(&newkey, 0, sizeof(newkey));
	    memset(&newmitkey, 0, sizeof(newmitkey));
	    if (code) {
		char *reason;
		reason = (char *)afs_error_message(code);
		fprintf(stderr, "%s: Password was not changed because %s\n",
			rn, reason);
	    } else
		printf("Password changed.\n\n");
	}
    }
    memset(&newkey, 0, sizeof(newkey));
    memset(&newmitkey, 0, sizeof(newmitkey));

    /* Might need to close down the ubik_Client connection */
    if (conn) {
	ubik_ClientDestroy(conn);
	conn = 0;
    }
    rx_Finalize();
    terminate_child();
    exit(code);

  no_change:			/* yuck, yuck, yuck */
    if (code)
	afs_com_err(rn, code, "getting new password");
  no_change_no_msg:
    memset(&key, 0, sizeof(key));
    memset(npasswd, 0, sizeof(npasswd));
    printf("Password for '%s' in cell '%s' unchanged.\n\n", pw->pw_name,
	   cell);
    terminate_child();
    exit(code ? code : 1);
}