remove krb4
git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@24520 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
		@@ -1,724 +0,0 @@
 | 
			
		||||
/*-
 | 
			
		||||
 * Copyright (c) 1991, 1993
 | 
			
		||||
 *	The Regents of the University of California.  All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 * 1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 * 2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *    documentation and/or other materials provided with the distribution.
 | 
			
		||||
 * 3. All advertising materials mentioning features or use of this software
 | 
			
		||||
 *    must display the following acknowledgement:
 | 
			
		||||
 *	This product includes software developed by the University of
 | 
			
		||||
 *	California, Berkeley and its contributors.
 | 
			
		||||
 * 4. Neither the name of the University nor the names of its contributors
 | 
			
		||||
 *    may be used to endorse or promote products derived from this software
 | 
			
		||||
 *    without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 | 
			
		||||
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 | 
			
		||||
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | 
			
		||||
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 | 
			
		||||
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | 
			
		||||
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | 
			
		||||
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 | 
			
		||||
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Copyright (C) 1990 by the Massachusetts Institute of Technology
 | 
			
		||||
 *
 | 
			
		||||
 * Export of this software from the United States of America is assumed
 | 
			
		||||
 * to 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.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#ifdef HAVE_CONFIG_H
 | 
			
		||||
#include <config.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
RCSID("$Id$");
 | 
			
		||||
 | 
			
		||||
#ifdef	KRB4
 | 
			
		||||
#ifdef HAVE_SYS_TYPES_H
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef HAVE_ARPA_TELNET_H
 | 
			
		||||
#include <arpa/telnet.h>
 | 
			
		||||
#endif
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include <krb.h>
 | 
			
		||||
#include <pwd.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#include <roken.h>
 | 
			
		||||
#ifdef SOCKS
 | 
			
		||||
#include <socks.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#include "encrypt.h"
 | 
			
		||||
#include "auth.h"
 | 
			
		||||
#include "misc.h"
 | 
			
		||||
 | 
			
		||||
int kerberos4_cksum (unsigned char *, int);
 | 
			
		||||
extern int auth_debug_mode;
 | 
			
		||||
 | 
			
		||||
static unsigned char str_data[2048] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
 | 
			
		||||
			  		AUTHTYPE_KERBEROS_V4, };
 | 
			
		||||
 | 
			
		||||
#define	KRB_AUTH	0		/* Authentication data follows */
 | 
			
		||||
#define	KRB_REJECT	1		/* Rejected (reason might follow) */
 | 
			
		||||
#define	KRB_ACCEPT	2		/* Accepted */
 | 
			
		||||
#define	KRB_CHALLENGE	3		/* Challenge for mutual auth. */
 | 
			
		||||
#define	KRB_RESPONSE	4		/* Response for mutual auth. */
 | 
			
		||||
 | 
			
		||||
#define KRB_FORWARD		5	/* */
 | 
			
		||||
#define KRB_FORWARD_ACCEPT	6	/* */
 | 
			
		||||
#define KRB_FORWARD_REJECT	7	/* */
 | 
			
		||||
 | 
			
		||||
#define KRB_SERVICE_NAME   "rcmd"
 | 
			
		||||
 | 
			
		||||
static	KTEXT_ST auth;
 | 
			
		||||
static	char name[ANAME_SZ];
 | 
			
		||||
static	AUTH_DAT adat;
 | 
			
		||||
static des_cblock session_key;
 | 
			
		||||
static des_cblock cred_session;
 | 
			
		||||
static des_key_schedule sched;
 | 
			
		||||
static des_cblock challenge;
 | 
			
		||||
static int auth_done; /* XXX */
 | 
			
		||||
 | 
			
		||||
static int pack_cred(CREDENTIALS *cred, unsigned char *buf);
 | 
			
		||||
static int unpack_cred(unsigned char *buf, int len, CREDENTIALS *cred);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
Data(Authenticator *ap, int type, const void *d, int c)
 | 
			
		||||
{
 | 
			
		||||
    unsigned char *p = str_data + 4;
 | 
			
		||||
    const unsigned char *cd = (const unsigned char *)d;
 | 
			
		||||
 | 
			
		||||
    if (c == -1)
 | 
			
		||||
	c = strlen((const char *)cd);
 | 
			
		||||
 | 
			
		||||
    if (auth_debug_mode) {
 | 
			
		||||
	printf("%s:%d: [%d] (%d)",
 | 
			
		||||
	       str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
 | 
			
		||||
	       str_data[3],
 | 
			
		||||
	       type, c);
 | 
			
		||||
	printd(d, c);
 | 
			
		||||
	printf("\r\n");
 | 
			
		||||
    }
 | 
			
		||||
    *p++ = ap->type;
 | 
			
		||||
    *p++ = ap->way;
 | 
			
		||||
    *p++ = type;
 | 
			
		||||
    while (c-- > 0) {
 | 
			
		||||
	if ((*p++ = *cd++) == IAC)
 | 
			
		||||
	    *p++ = IAC;
 | 
			
		||||
    }
 | 
			
		||||
    *p++ = IAC;
 | 
			
		||||
    *p++ = SE;
 | 
			
		||||
    if (str_data[3] == TELQUAL_IS)
 | 
			
		||||
	printsub('>', &str_data[2], p - (&str_data[2]));
 | 
			
		||||
    return(telnet_net_write(str_data, p - str_data));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
kerberos4_init(Authenticator *ap, int server)
 | 
			
		||||
{
 | 
			
		||||
    FILE *fp;
 | 
			
		||||
 | 
			
		||||
    if (server) {
 | 
			
		||||
	str_data[3] = TELQUAL_REPLY;
 | 
			
		||||
	if ((fp = fopen(KEYFILE, "r")) == NULL)
 | 
			
		||||
	    return(0);
 | 
			
		||||
	fclose(fp);
 | 
			
		||||
    } else {
 | 
			
		||||
	str_data[3] = TELQUAL_IS;
 | 
			
		||||
    }
 | 
			
		||||
    return(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
char dst_realm_buf[REALM_SZ], *dest_realm = NULL;
 | 
			
		||||
int dst_realm_sz = REALM_SZ;
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
kerberos4_send(char *name, Authenticator *ap)
 | 
			
		||||
{
 | 
			
		||||
    KTEXT_ST auth;
 | 
			
		||||
    char instance[INST_SZ];
 | 
			
		||||
    char *realm;
 | 
			
		||||
    CREDENTIALS cred;
 | 
			
		||||
    int r;
 | 
			
		||||
 | 
			
		||||
    if (!UserNameRequested) {
 | 
			
		||||
	if (auth_debug_mode) {
 | 
			
		||||
	    printf("Kerberos V4: no user name supplied\r\n");
 | 
			
		||||
	}
 | 
			
		||||
	return(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    memset(instance, 0, sizeof(instance));
 | 
			
		||||
 | 
			
		||||
    strlcpy (instance,
 | 
			
		||||
		     krb_get_phost(RemoteHostName),
 | 
			
		||||
		     INST_SZ);
 | 
			
		||||
 | 
			
		||||
    realm = dest_realm ? dest_realm : krb_realmofhost(RemoteHostName);
 | 
			
		||||
 | 
			
		||||
    if (!realm) {
 | 
			
		||||
	printf("Kerberos V4: no realm for %s\r\n", RemoteHostName);
 | 
			
		||||
	return(0);
 | 
			
		||||
    }
 | 
			
		||||
    printf("[ Trying %s (%s.%s@%s) ... ]\r\n", name,
 | 
			
		||||
	   KRB_SERVICE_NAME, instance, realm);
 | 
			
		||||
    r = krb_mk_req(&auth, KRB_SERVICE_NAME, instance, realm, 0L);
 | 
			
		||||
    if (r) {
 | 
			
		||||
	printf("mk_req failed: %s\r\n", krb_get_err_text(r));
 | 
			
		||||
	return(0);
 | 
			
		||||
    }
 | 
			
		||||
    r = krb_get_cred(KRB_SERVICE_NAME, instance, realm, &cred);
 | 
			
		||||
    if (r) {
 | 
			
		||||
	printf("get_cred failed: %s\r\n", krb_get_err_text(r));
 | 
			
		||||
	return(0);
 | 
			
		||||
    }
 | 
			
		||||
    if (!auth_sendname((unsigned char*)UserNameRequested,
 | 
			
		||||
		       strlen(UserNameRequested))) {
 | 
			
		||||
	if (auth_debug_mode)
 | 
			
		||||
	    printf("Not enough room for user name\r\n");
 | 
			
		||||
	return(0);
 | 
			
		||||
    }
 | 
			
		||||
    if (auth_debug_mode)
 | 
			
		||||
	printf("Sent %d bytes of authentication data\r\n", auth.length);
 | 
			
		||||
    if (!Data(ap, KRB_AUTH, (void *)auth.dat, auth.length)) {
 | 
			
		||||
	if (auth_debug_mode)
 | 
			
		||||
	    printf("Not enough room for authentication data\r\n");
 | 
			
		||||
	return(0);
 | 
			
		||||
    }
 | 
			
		||||
#ifdef ENCRYPTION
 | 
			
		||||
    /* create challenge */
 | 
			
		||||
    if ((ap->way & AUTH_HOW_MASK)==AUTH_HOW_MUTUAL) {
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	des_key_sched(&cred.session, sched);
 | 
			
		||||
	memcpy (&cred_session, &cred.session, sizeof(cred_session));
 | 
			
		||||
#ifndef HAVE_OPENSSL
 | 
			
		||||
	des_init_random_number_generator(&cred.session);
 | 
			
		||||
#endif
 | 
			
		||||
	des_new_random_key(&session_key);
 | 
			
		||||
	des_ecb_encrypt(&session_key, &session_key, sched, 0);
 | 
			
		||||
	des_ecb_encrypt(&session_key, &challenge, sched, 0);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	  old code
 | 
			
		||||
	  Some CERT Advisory thinks this is a bad thing...
 | 
			
		||||
	
 | 
			
		||||
	  des_init_random_number_generator(&cred.session);
 | 
			
		||||
	  des_new_random_key(&challenge);
 | 
			
		||||
	  des_ecb_encrypt(&challenge, &session_key, sched, 1);
 | 
			
		||||
	  */
 | 
			
		||||
	
 | 
			
		||||
	/*
 | 
			
		||||
	 * Increment the challenge by 1, and encrypt it for
 | 
			
		||||
	 * later comparison.
 | 
			
		||||
	 */
 | 
			
		||||
	for (i = 7; i >= 0; --i)
 | 
			
		||||
	    if(++challenge[i] != 0) /* No carry! */
 | 
			
		||||
		break;
 | 
			
		||||
	des_ecb_encrypt(&challenge, &challenge, sched, 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
    if (auth_debug_mode) {
 | 
			
		||||
	printf("CK: %d:", kerberos4_cksum(auth.dat, auth.length));
 | 
			
		||||
	printd(auth.dat, auth.length);
 | 
			
		||||
	printf("\r\n");
 | 
			
		||||
	printf("Sent Kerberos V4 credentials to server\r\n");
 | 
			
		||||
    }
 | 
			
		||||
    return(1);
 | 
			
		||||
}
 | 
			
		||||
int
 | 
			
		||||
kerberos4_send_mutual(Authenticator *ap)
 | 
			
		||||
{
 | 
			
		||||
    return kerberos4_send("mutual KERBEROS4", ap);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
kerberos4_send_oneway(Authenticator *ap)
 | 
			
		||||
{
 | 
			
		||||
    return kerberos4_send("KERBEROS4", ap);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
kerberos4_is(Authenticator *ap, unsigned char *data, int cnt)
 | 
			
		||||
{
 | 
			
		||||
    struct sockaddr_in addr;
 | 
			
		||||
    char realm[REALM_SZ];
 | 
			
		||||
    char instance[INST_SZ];
 | 
			
		||||
    int r;
 | 
			
		||||
    socklen_t addr_len;
 | 
			
		||||
 | 
			
		||||
    if (cnt-- < 1)
 | 
			
		||||
	return;
 | 
			
		||||
    switch (*data++) {
 | 
			
		||||
    case KRB_AUTH:
 | 
			
		||||
	if (krb_get_lrealm(realm, 1) != KSUCCESS) {
 | 
			
		||||
	    Data(ap, KRB_REJECT, (void *)"No local V4 Realm.", -1);
 | 
			
		||||
	    auth_finished(ap, AUTH_REJECT);
 | 
			
		||||
	    if (auth_debug_mode)
 | 
			
		||||
		printf("No local realm\r\n");
 | 
			
		||||
	    return;
 | 
			
		||||
	}
 | 
			
		||||
	memmove(auth.dat, data, auth.length = cnt);
 | 
			
		||||
	if (auth_debug_mode) {
 | 
			
		||||
	    printf("Got %d bytes of authentication data\r\n", cnt);
 | 
			
		||||
	    printf("CK: %d:", kerberos4_cksum(auth.dat, auth.length));
 | 
			
		||||
	    printd(auth.dat, auth.length);
 | 
			
		||||
	    printf("\r\n");
 | 
			
		||||
	}
 | 
			
		||||
	k_getsockinst(0, instance, sizeof(instance));
 | 
			
		||||
	addr_len = sizeof(addr);
 | 
			
		||||
	if(getpeername(0, (struct sockaddr *)&addr, &addr_len) < 0) {
 | 
			
		||||
	    if(auth_debug_mode)
 | 
			
		||||
		printf("getpeername failed\r\n");
 | 
			
		||||
	    Data(ap, KRB_REJECT, "getpeername failed", -1);
 | 
			
		||||
	    auth_finished(ap, AUTH_REJECT);
 | 
			
		||||
	    return;
 | 
			
		||||
	}
 | 
			
		||||
	if (addr.sin_family != AF_INET) {
 | 
			
		||||
	    if (auth_debug_mode)
 | 
			
		||||
		printf("unknown address family: %d\r\n", addr.sin_family);
 | 
			
		||||
	    Data(ap, KRB_REJECT, "bad address family", -1);
 | 
			
		||||
	    auth_finished(ap, AUTH_REJECT);
 | 
			
		||||
	    return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	r = krb_rd_req(&auth, KRB_SERVICE_NAME,
 | 
			
		||||
		       instance, addr.sin_addr.s_addr, &adat, "");
 | 
			
		||||
	if (r) {
 | 
			
		||||
	    if (auth_debug_mode)
 | 
			
		||||
		printf("Kerberos failed him as %s\r\n", name);
 | 
			
		||||
	    Data(ap, KRB_REJECT, (void *)krb_get_err_text(r), -1);
 | 
			
		||||
	    auth_finished(ap, AUTH_REJECT);
 | 
			
		||||
	    return;
 | 
			
		||||
	}
 | 
			
		||||
	/* save the session key */
 | 
			
		||||
	memmove(session_key, adat.session, sizeof(adat.session));
 | 
			
		||||
	krb_kntoln(&adat, name);
 | 
			
		||||
 | 
			
		||||
	if (UserNameRequested && !kuserok(&adat, UserNameRequested)){
 | 
			
		||||
	    char ts[MaxPathLen];
 | 
			
		||||
	    struct passwd *pw = getpwnam(UserNameRequested);
 | 
			
		||||
 | 
			
		||||
	    if(pw){
 | 
			
		||||
		snprintf(ts, sizeof(ts),
 | 
			
		||||
			 "%s%u",
 | 
			
		||||
			 TKT_ROOT,
 | 
			
		||||
			 (unsigned)pw->pw_uid);
 | 
			
		||||
		esetenv("KRBTKFILE", ts, 1);
 | 
			
		||||
 | 
			
		||||
		if (pw->pw_uid == 0)
 | 
			
		||||
		    syslog(LOG_INFO|LOG_AUTH,
 | 
			
		||||
			   "ROOT Kerberos login from %s on %s\n",
 | 
			
		||||
			   krb_unparse_name_long(adat.pname,
 | 
			
		||||
						 adat.pinst,
 | 
			
		||||
						 adat.prealm),
 | 
			
		||||
			   RemoteHostName);
 | 
			
		||||
	    }
 | 
			
		||||
	    Data(ap, KRB_ACCEPT, NULL, 0);
 | 
			
		||||
	} else {
 | 
			
		||||
	    char *msg;
 | 
			
		||||
	    int ret;
 | 
			
		||||
 | 
			
		||||
	    ret = asprintf (&msg, "user `%s' is not authorized to "
 | 
			
		||||
			    "login as `%s'",
 | 
			
		||||
			    krb_unparse_name_long(adat.pname,
 | 
			
		||||
						  adat.pinst,
 | 
			
		||||
						  adat.prealm),
 | 
			
		||||
			    UserNameRequested ? UserNameRequested : "<nobody>");
 | 
			
		||||
	    if (ret == -1)
 | 
			
		||||
		Data(ap, KRB_REJECT, NULL, 0);
 | 
			
		||||
	    else {
 | 
			
		||||
		Data(ap, KRB_REJECT, (void *)msg, -1);
 | 
			
		||||
		free(msg);
 | 
			
		||||
	    }
 | 
			
		||||
	    auth_finished(ap, AUTH_REJECT);
 | 
			
		||||
	    break;
 | 
			
		||||
	}
 | 
			
		||||
	auth_finished(ap, AUTH_USER);
 | 
			
		||||
	break;
 | 
			
		||||
	
 | 
			
		||||
    case KRB_CHALLENGE:
 | 
			
		||||
#ifndef ENCRYPTION
 | 
			
		||||
	Data(ap, KRB_RESPONSE, NULL, 0);
 | 
			
		||||
#else
 | 
			
		||||
	if(!VALIDKEY(session_key)){
 | 
			
		||||
	    Data(ap, KRB_RESPONSE, NULL, 0);
 | 
			
		||||
	    break;
 | 
			
		||||
	}
 | 
			
		||||
	des_key_sched(&session_key, sched);
 | 
			
		||||
	{
 | 
			
		||||
	    des_cblock d_block;
 | 
			
		||||
	    int i;
 | 
			
		||||
	    Session_Key skey;
 | 
			
		||||
 | 
			
		||||
	    memmove(d_block, data, sizeof(d_block));
 | 
			
		||||
 | 
			
		||||
	    /* make a session key for encryption */
 | 
			
		||||
	    des_ecb_encrypt(&d_block, &session_key, sched, 1);
 | 
			
		||||
	    skey.type=SK_DES;
 | 
			
		||||
	    skey.length=8;
 | 
			
		||||
	    skey.data=session_key;
 | 
			
		||||
	    encrypt_session_key(&skey, 1);
 | 
			
		||||
 | 
			
		||||
	    /* decrypt challenge, add one and encrypt it */
 | 
			
		||||
	    des_ecb_encrypt(&d_block, &challenge, sched, 0);
 | 
			
		||||
	    for (i = 7; i >= 0; i--)
 | 
			
		||||
		if(++challenge[i] != 0)
 | 
			
		||||
		    break;
 | 
			
		||||
	    des_ecb_encrypt(&challenge, &challenge, sched, 1);
 | 
			
		||||
	    Data(ap, KRB_RESPONSE, (void *)challenge, sizeof(challenge));
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
	break;
 | 
			
		||||
 | 
			
		||||
    case KRB_FORWARD:
 | 
			
		||||
	{
 | 
			
		||||
	    des_key_schedule ks;
 | 
			
		||||
	    unsigned char netcred[sizeof(CREDENTIALS)];
 | 
			
		||||
	    CREDENTIALS cred;
 | 
			
		||||
	    int ret;
 | 
			
		||||
	    if(cnt > sizeof(cred))
 | 
			
		||||
		abort();
 | 
			
		||||
 | 
			
		||||
	    memcpy (session_key, adat.session, sizeof(session_key));
 | 
			
		||||
	    des_set_key(&session_key, ks);
 | 
			
		||||
	    des_pcbc_encrypt((void*)data, (void*)netcred, cnt,
 | 
			
		||||
			     ks, &session_key, DES_DECRYPT);
 | 
			
		||||
	    unpack_cred(netcred, cnt, &cred);
 | 
			
		||||
	    {
 | 
			
		||||
		if(strcmp(cred.service, KRB_TICKET_GRANTING_TICKET) ||
 | 
			
		||||
		   strncmp(cred.instance, cred.realm, sizeof(cred.instance)) ||
 | 
			
		||||
		   cred.lifetime < 0 || cred.lifetime > 255 ||
 | 
			
		||||
		   cred.kvno < 0 || cred.kvno > 255 ||
 | 
			
		||||
		   cred.issue_date < 0 ||
 | 
			
		||||
		   cred.issue_date > time(0) + CLOCK_SKEW ||
 | 
			
		||||
		   strncmp(cred.pname, adat.pname, sizeof(cred.pname)) ||
 | 
			
		||||
		   strncmp(cred.pinst, adat.pinst, sizeof(cred.pinst))){
 | 
			
		||||
		    Data(ap, KRB_FORWARD_REJECT, "Bad credentials", -1);
 | 
			
		||||
		}else{
 | 
			
		||||
		    if((ret = tf_setup(&cred,
 | 
			
		||||
				       cred.pname,
 | 
			
		||||
				       cred.pinst)) == KSUCCESS){
 | 
			
		||||
		        struct passwd *pw = getpwnam(UserNameRequested);
 | 
			
		||||
 | 
			
		||||
			if (pw)
 | 
			
		||||
			  chown(tkt_string(), pw->pw_uid, pw->pw_gid);
 | 
			
		||||
			Data(ap, KRB_FORWARD_ACCEPT, 0, 0);
 | 
			
		||||
		    } else{
 | 
			
		||||
			Data(ap, KRB_FORWARD_REJECT,
 | 
			
		||||
			     krb_get_err_text(ret), -1);
 | 
			
		||||
		    }
 | 
			
		||||
		}
 | 
			
		||||
	    }
 | 
			
		||||
	    memset(data, 0, cnt);
 | 
			
		||||
	    memset(&ks, 0, sizeof(ks));
 | 
			
		||||
	    memset(&cred, 0, sizeof(cred));
 | 
			
		||||
	}
 | 
			
		||||
	
 | 
			
		||||
	break;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
	if (auth_debug_mode)
 | 
			
		||||
	    printf("Unknown Kerberos option %d\r\n", data[-1]);
 | 
			
		||||
	Data(ap, KRB_REJECT, 0, 0);
 | 
			
		||||
	break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
kerberos4_reply(Authenticator *ap, unsigned char *data, int cnt)
 | 
			
		||||
{
 | 
			
		||||
    Session_Key skey;
 | 
			
		||||
 | 
			
		||||
    if (cnt-- < 1)
 | 
			
		||||
	return;
 | 
			
		||||
    switch (*data++) {
 | 
			
		||||
    case KRB_REJECT:
 | 
			
		||||
	if(auth_done){ /* XXX Ick! */
 | 
			
		||||
	    printf("[ Kerberos V4 received unknown opcode ]\r\n");
 | 
			
		||||
	}else{
 | 
			
		||||
	    printf("[ Kerberos V4 refuses authentication ");
 | 
			
		||||
	    if (cnt > 0)
 | 
			
		||||
		printf("because %.*s ", cnt, data);
 | 
			
		||||
	    printf("]\r\n");
 | 
			
		||||
	    auth_send_retry();
 | 
			
		||||
	}
 | 
			
		||||
	return;
 | 
			
		||||
    case KRB_ACCEPT:
 | 
			
		||||
	printf("[ Kerberos V4 accepts you ]\r\n");
 | 
			
		||||
	auth_done = 1;
 | 
			
		||||
	if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
 | 
			
		||||
	    /*
 | 
			
		||||
	     * Send over the encrypted challenge.
 | 
			
		||||
	     */
 | 
			
		||||
	    Data(ap, KRB_CHALLENGE, session_key,
 | 
			
		||||
		 sizeof(session_key));
 | 
			
		||||
	    des_ecb_encrypt(&session_key, &session_key, sched, 1);
 | 
			
		||||
	    skey.type = SK_DES;
 | 
			
		||||
	    skey.length = 8;
 | 
			
		||||
	    skey.data = session_key;
 | 
			
		||||
	    encrypt_session_key(&skey, 0);
 | 
			
		||||
#if 0
 | 
			
		||||
	    kerberos4_forward(ap, &cred_session);
 | 
			
		||||
#endif
 | 
			
		||||
	    return;
 | 
			
		||||
	}
 | 
			
		||||
	auth_finished(ap, AUTH_USER);
 | 
			
		||||
	return;
 | 
			
		||||
    case KRB_RESPONSE:
 | 
			
		||||
	/* make sure the response is correct */
 | 
			
		||||
	if ((cnt != sizeof(des_cblock)) ||
 | 
			
		||||
	    (memcmp(data, challenge, sizeof(challenge)))){
 | 
			
		||||
	    printf("[ Kerberos V4 challenge failed!!! ]\r\n");
 | 
			
		||||
	    auth_send_retry();
 | 
			
		||||
	    return;
 | 
			
		||||
	}
 | 
			
		||||
	printf("[ Kerberos V4 challenge successful ]\r\n");
 | 
			
		||||
	auth_finished(ap, AUTH_USER);
 | 
			
		||||
	break;
 | 
			
		||||
    case KRB_FORWARD_ACCEPT:
 | 
			
		||||
	printf("[ Kerberos V4 accepted forwarded credentials ]\r\n");
 | 
			
		||||
	break;
 | 
			
		||||
    case KRB_FORWARD_REJECT:
 | 
			
		||||
	printf("[ Kerberos V4 rejected forwarded credentials: `%.*s']\r\n",
 | 
			
		||||
	       cnt, data);
 | 
			
		||||
	break;
 | 
			
		||||
    default:
 | 
			
		||||
	if (auth_debug_mode)
 | 
			
		||||
	    printf("Unknown Kerberos option %d\r\n", data[-1]);
 | 
			
		||||
	return;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
kerberos4_status(Authenticator *ap, char *name, size_t name_sz, int level)
 | 
			
		||||
{
 | 
			
		||||
    if (level < AUTH_USER)
 | 
			
		||||
	return(level);
 | 
			
		||||
 | 
			
		||||
    if (UserNameRequested && !kuserok(&adat, UserNameRequested)) {
 | 
			
		||||
	strlcpy(name, UserNameRequested, name_sz);
 | 
			
		||||
	return(AUTH_VALID);
 | 
			
		||||
    } else
 | 
			
		||||
	return(AUTH_USER);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define	BUMP(buf, len)		while (*(buf)) {++(buf), --(len);}
 | 
			
		||||
#define	ADDC(buf, len, c)	if ((len) > 0) {*(buf)++ = (c); --(len);}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
kerberos4_printsub(unsigned char *data, size_t cnt,
 | 
			
		||||
		   unsigned char *buf, size_t buflen)
 | 
			
		||||
{
 | 
			
		||||
    int i;
 | 
			
		||||
 | 
			
		||||
    buf[buflen-1] = '\0';		/* make sure it's NULL terminated */
 | 
			
		||||
    buflen -= 1;
 | 
			
		||||
 | 
			
		||||
    switch(data[3]) {
 | 
			
		||||
    case KRB_REJECT:		/* Rejected (reason might follow) */
 | 
			
		||||
	strlcpy((char *)buf, " REJECT ", buflen);
 | 
			
		||||
	goto common;
 | 
			
		||||
 | 
			
		||||
    case KRB_ACCEPT:		/* Accepted (name might follow) */
 | 
			
		||||
	strlcpy((char *)buf, " ACCEPT ", buflen);
 | 
			
		||||
    common:
 | 
			
		||||
	BUMP(buf, buflen);
 | 
			
		||||
	if (cnt <= 4)
 | 
			
		||||
	    break;
 | 
			
		||||
	ADDC(buf, buflen, '"');
 | 
			
		||||
	for (i = 4; i < cnt; i++)
 | 
			
		||||
	    ADDC(buf, buflen, data[i]);
 | 
			
		||||
	ADDC(buf, buflen, '"');
 | 
			
		||||
	ADDC(buf, buflen, '\0');
 | 
			
		||||
	break;
 | 
			
		||||
 | 
			
		||||
    case KRB_AUTH:			/* Authentication data follows */
 | 
			
		||||
	strlcpy((char *)buf, " AUTH", buflen);
 | 
			
		||||
	goto common2;
 | 
			
		||||
 | 
			
		||||
    case KRB_CHALLENGE:
 | 
			
		||||
	strlcpy((char *)buf, " CHALLENGE", buflen);
 | 
			
		||||
	goto common2;
 | 
			
		||||
 | 
			
		||||
    case KRB_RESPONSE:
 | 
			
		||||
	strlcpy((char *)buf, " RESPONSE", buflen);
 | 
			
		||||
	goto common2;
 | 
			
		||||
 | 
			
		||||
    default:
 | 
			
		||||
	snprintf((char*)buf, buflen, " %d (unknown)", data[3]);
 | 
			
		||||
    common2:
 | 
			
		||||
	BUMP(buf, buflen);
 | 
			
		||||
	for (i = 4; i < cnt; i++) {
 | 
			
		||||
	    snprintf((char*)buf, buflen, " %d", data[i]);
 | 
			
		||||
	    BUMP(buf, buflen);
 | 
			
		||||
	}
 | 
			
		||||
	break;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
kerberos4_cksum(unsigned char *d, int n)
 | 
			
		||||
{
 | 
			
		||||
    int ck = 0;
 | 
			
		||||
 | 
			
		||||
    /*
 | 
			
		||||
     * A comment is probably needed here for those not
 | 
			
		||||
     * well versed in the "C" language.  Yes, this is
 | 
			
		||||
     * supposed to be a "switch" with the body of the
 | 
			
		||||
     * "switch" being a "while" statement.  The whole
 | 
			
		||||
     * purpose of the switch is to allow us to jump into
 | 
			
		||||
     * the middle of the while() loop, and then not have
 | 
			
		||||
     * to do any more switch()s.
 | 
			
		||||
     *
 | 
			
		||||
     * Some compilers will spit out a warning message
 | 
			
		||||
     * about the loop not being entered at the top.
 | 
			
		||||
     */
 | 
			
		||||
    switch (n&03)
 | 
			
		||||
	while (n > 0) {
 | 
			
		||||
	case 0:
 | 
			
		||||
	    ck ^= (int)*d++ << 24;
 | 
			
		||||
	    --n;
 | 
			
		||||
	case 3:
 | 
			
		||||
	    ck ^= (int)*d++ << 16;
 | 
			
		||||
	    --n;
 | 
			
		||||
	case 2:
 | 
			
		||||
	    ck ^= (int)*d++ << 8;
 | 
			
		||||
	    --n;
 | 
			
		||||
	case 1:
 | 
			
		||||
	    ck ^= (int)*d++;
 | 
			
		||||
	    --n;
 | 
			
		||||
	}
 | 
			
		||||
    return(ck);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
pack_cred(CREDENTIALS *cred, unsigned char *buf)
 | 
			
		||||
{
 | 
			
		||||
    unsigned char *p = buf;
 | 
			
		||||
 | 
			
		||||
    memcpy (p, cred->service, ANAME_SZ);
 | 
			
		||||
    p += ANAME_SZ;
 | 
			
		||||
    memcpy (p, cred->instance, INST_SZ);
 | 
			
		||||
    p += INST_SZ;
 | 
			
		||||
    memcpy (p, cred->realm, REALM_SZ);
 | 
			
		||||
    p += REALM_SZ;
 | 
			
		||||
    memcpy(p, cred->session, 8);
 | 
			
		||||
    p += 8;
 | 
			
		||||
    p += KRB_PUT_INT(cred->lifetime, p, 4, 4);
 | 
			
		||||
    p += KRB_PUT_INT(cred->kvno, p, 4, 4);
 | 
			
		||||
    p += KRB_PUT_INT(cred->ticket_st.length, p, 4, 4);
 | 
			
		||||
    memcpy(p, cred->ticket_st.dat, cred->ticket_st.length);
 | 
			
		||||
    p += cred->ticket_st.length;
 | 
			
		||||
    p += KRB_PUT_INT(0, p, 4, 4);
 | 
			
		||||
    p += KRB_PUT_INT(cred->issue_date, p, 4, 4);
 | 
			
		||||
    memcpy (p, cred->pname, ANAME_SZ);
 | 
			
		||||
    p += ANAME_SZ;
 | 
			
		||||
    memcpy (p, cred->pinst, INST_SZ);
 | 
			
		||||
    p += INST_SZ;
 | 
			
		||||
    return p - buf;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static int
 | 
			
		||||
unpack_cred(unsigned char *buf, int len, CREDENTIALS *cred)
 | 
			
		||||
{
 | 
			
		||||
    char *p = (char*)buf;
 | 
			
		||||
    uint32_t tmp;
 | 
			
		||||
 | 
			
		||||
    strncpy (cred->service, p, ANAME_SZ);
 | 
			
		||||
    cred->service[ANAME_SZ - 1] = '\0';
 | 
			
		||||
    p += ANAME_SZ;
 | 
			
		||||
    strncpy (cred->instance, p, INST_SZ);
 | 
			
		||||
    cred->instance[INST_SZ - 1] = '\0';
 | 
			
		||||
    p += INST_SZ;
 | 
			
		||||
    strncpy (cred->realm, p, REALM_SZ);
 | 
			
		||||
    cred->realm[REALM_SZ - 1] = '\0';
 | 
			
		||||
    p += REALM_SZ;
 | 
			
		||||
 | 
			
		||||
    memcpy(cred->session, p, 8);
 | 
			
		||||
    p += 8;
 | 
			
		||||
    p += krb_get_int(p, &tmp, 4, 0);
 | 
			
		||||
    cred->lifetime = tmp;
 | 
			
		||||
    p += krb_get_int(p, &tmp, 4, 0);
 | 
			
		||||
    cred->kvno = tmp;
 | 
			
		||||
 | 
			
		||||
    p += krb_get_int(p, &cred->ticket_st.length, 4, 0);
 | 
			
		||||
    memcpy(cred->ticket_st.dat, p, cred->ticket_st.length);
 | 
			
		||||
    p += cred->ticket_st.length;
 | 
			
		||||
    p += krb_get_int(p, &tmp, 4, 0);
 | 
			
		||||
    cred->ticket_st.mbz = 0;
 | 
			
		||||
    p += krb_get_int(p, (uint32_t *)&cred->issue_date, 4, 0);
 | 
			
		||||
 | 
			
		||||
    strncpy (cred->pname, p, ANAME_SZ);
 | 
			
		||||
    cred->pname[ANAME_SZ - 1] = '\0';
 | 
			
		||||
    p += ANAME_SZ;
 | 
			
		||||
    strncpy (cred->pinst, p, INST_SZ);
 | 
			
		||||
    cred->pinst[INST_SZ - 1] = '\0';
 | 
			
		||||
    p += INST_SZ;
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
int
 | 
			
		||||
kerberos4_forward(Authenticator *ap, void *v)
 | 
			
		||||
{
 | 
			
		||||
    des_cblock *key = (des_cblock *)v;
 | 
			
		||||
    CREDENTIALS cred;
 | 
			
		||||
    char *realm;
 | 
			
		||||
    des_key_schedule ks;
 | 
			
		||||
    int len;
 | 
			
		||||
    unsigned char netcred[sizeof(CREDENTIALS)];
 | 
			
		||||
    int ret;
 | 
			
		||||
 | 
			
		||||
    realm = krb_realmofhost(RemoteHostName);
 | 
			
		||||
    if(realm == NULL)
 | 
			
		||||
	return -1;
 | 
			
		||||
    memset(&cred, 0, sizeof(cred));
 | 
			
		||||
    ret = krb_get_cred(KRB_TICKET_GRANTING_TICKET,
 | 
			
		||||
		       realm,
 | 
			
		||||
		       realm,
 | 
			
		||||
		       &cred);
 | 
			
		||||
    if(ret)
 | 
			
		||||
	return ret;
 | 
			
		||||
    des_set_key(key, ks);
 | 
			
		||||
    len = pack_cred(&cred, netcred);
 | 
			
		||||
    des_pcbc_encrypt((void*)netcred, (void*)netcred, len,
 | 
			
		||||
		     ks, key, DES_ENCRYPT);
 | 
			
		||||
    memset(&ks, 0, sizeof(ks));
 | 
			
		||||
    Data(ap, KRB_FORWARD, netcred, len);
 | 
			
		||||
    memset(netcred, 0, sizeof(netcred));
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif /* KRB4 */
 | 
			
		||||
 | 
			
		||||
@@ -1,435 +0,0 @@
 | 
			
		||||
/*-
 | 
			
		||||
 * Copyright (c) 1992, 1993
 | 
			
		||||
 *	The Regents of the University of California.  All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Redistribution and use in source and binary forms, with or without
 | 
			
		||||
 * modification, are permitted provided that the following conditions
 | 
			
		||||
 * are met:
 | 
			
		||||
 * 1. Redistributions of source code must retain the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer.
 | 
			
		||||
 * 2. Redistributions in binary form must reproduce the above copyright
 | 
			
		||||
 *    notice, this list of conditions and the following disclaimer in the
 | 
			
		||||
 *    documentation and/or other materials provided with the distribution.
 | 
			
		||||
 * 3. All advertising materials mentioning features or use of this software
 | 
			
		||||
 *    must display the following acknowledgement:
 | 
			
		||||
 *	This product includes software developed by the University of
 | 
			
		||||
 *	California, Berkeley and its contributors.
 | 
			
		||||
 * 4. Neither the name of the University nor the names of its contributors
 | 
			
		||||
 *    may be used to endorse or promote products derived from this software
 | 
			
		||||
 *    without specific prior written permission.
 | 
			
		||||
 *
 | 
			
		||||
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 | 
			
		||||
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | 
			
		||||
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | 
			
		||||
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 | 
			
		||||
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | 
			
		||||
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 | 
			
		||||
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | 
			
		||||
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | 
			
		||||
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 | 
			
		||||
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | 
			
		||||
 * SUCH DAMAGE.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <config.h>
 | 
			
		||||
 | 
			
		||||
RCSID("$Id$");
 | 
			
		||||
 | 
			
		||||
#ifdef	KRB4_ENCPWD
 | 
			
		||||
/*
 | 
			
		||||
 * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
 | 
			
		||||
 * ALL RIGHTS RESERVED
 | 
			
		||||
 *
 | 
			
		||||
 * "Digital Equipment Corporation authorizes the reproduction,
 | 
			
		||||
 * distribution and modification of this software subject to the following
 | 
			
		||||
 * restrictions:
 | 
			
		||||
 *
 | 
			
		||||
 * 1.  Any partial or whole copy of this software, or any modification
 | 
			
		||||
 * thereof, must include this copyright notice in its entirety.
 | 
			
		||||
 *
 | 
			
		||||
 * 2.  This software is supplied "as is" with no warranty of any kind,
 | 
			
		||||
 * expressed or implied, for any purpose, including any warranty of fitness
 | 
			
		||||
 * or merchantibility.  DIGITAL assumes no responsibility for the use or
 | 
			
		||||
 * reliability of this software, nor promises to provide any form of
 | 
			
		||||
 * support for it on any basis.
 | 
			
		||||
 *
 | 
			
		||||
 * 3.  Distribution of this software is authorized only if no profit or
 | 
			
		||||
 * remuneration of any kind is received in exchange for such distribution.
 | 
			
		||||
 *
 | 
			
		||||
 * 4.  This software produces public key authentication certificates
 | 
			
		||||
 * bearing an expiration date established by DIGITAL and RSA Data
 | 
			
		||||
 * Security, Inc.  It may cease to generate certificates after the expiration
 | 
			
		||||
 * date.  Any modification of this software that changes or defeats
 | 
			
		||||
 * the expiration date or its effect is unauthorized.
 | 
			
		||||
 *
 | 
			
		||||
 * 5.  Software that will renew or extend the expiration date of
 | 
			
		||||
 * authentication certificates produced by this software may be obtained
 | 
			
		||||
 * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
 | 
			
		||||
 * 94065, (415)595-8782, or from DIGITAL"
 | 
			
		||||
 *
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
#include <sys/types.h>
 | 
			
		||||
#include <arpa/telnet.h>
 | 
			
		||||
#include <pwd.h>
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
 | 
			
		||||
#include <krb.h>
 | 
			
		||||
#include <stdlib.h>
 | 
			
		||||
#include <string.h>
 | 
			
		||||
#ifdef SOCKS
 | 
			
		||||
#include <socks.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "encrypt.h"
 | 
			
		||||
#include "auth.h"
 | 
			
		||||
#include "misc.h"
 | 
			
		||||
 | 
			
		||||
int krb_mk_encpwd_req (KTEXT, char *, char *, char *, char *, char *, char *);
 | 
			
		||||
int krb_rd_encpwd_req (KTEXT, char *, char *, u_long, AUTH_DAT *, char *, char *, char *, char *);
 | 
			
		||||
 | 
			
		||||
extern auth_debug_mode;
 | 
			
		||||
 | 
			
		||||
static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
 | 
			
		||||
			  		AUTHTYPE_KRB4_ENCPWD, };
 | 
			
		||||
static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION,
 | 
			
		||||
					TELQUAL_NAME, };
 | 
			
		||||
 | 
			
		||||
#define	KRB4_ENCPWD_AUTH	0	/* Authentication data follows */
 | 
			
		||||
#define	KRB4_ENCPWD_REJECT	1	/* Rejected (reason might follow) */
 | 
			
		||||
#define KRB4_ENCPWD_ACCEPT	2	/* Accepted */
 | 
			
		||||
#define	KRB4_ENCPWD_CHALLENGE	3	/* Challenge for mutual auth. */
 | 
			
		||||
#define	KRB4_ENCPWD_ACK		4	/* Acknowledge */
 | 
			
		||||
 | 
			
		||||
#define KRB_SERVICE_NAME    "rcmd"
 | 
			
		||||
 | 
			
		||||
static	KTEXT_ST auth;
 | 
			
		||||
static	char name[ANAME_SZ];
 | 
			
		||||
static	char user_passwd[ANAME_SZ];
 | 
			
		||||
static	AUTH_DAT adat = { 0 };
 | 
			
		||||
static des_key_schedule sched;
 | 
			
		||||
static char  challenge[REALM_SZ];
 | 
			
		||||
 | 
			
		||||
	static int
 | 
			
		||||
Data(ap, type, d, c)
 | 
			
		||||
	Authenticator *ap;
 | 
			
		||||
	int type;
 | 
			
		||||
	void *d;
 | 
			
		||||
	int c;
 | 
			
		||||
{
 | 
			
		||||
	unsigned char *p = str_data + 4;
 | 
			
		||||
	unsigned char *cd = (unsigned char *)d;
 | 
			
		||||
 | 
			
		||||
	if (c == -1)
 | 
			
		||||
		c = strlen(cd);
 | 
			
		||||
 | 
			
		||||
	if (0) {
 | 
			
		||||
		printf("%s:%d: [%d] (%d)",
 | 
			
		||||
			str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
 | 
			
		||||
			str_data[3],
 | 
			
		||||
			type, c);
 | 
			
		||||
		printd(d, c);
 | 
			
		||||
		printf("\r\n");
 | 
			
		||||
	}
 | 
			
		||||
	*p++ = ap->type;
 | 
			
		||||
	*p++ = ap->way;
 | 
			
		||||
	*p++ = type;
 | 
			
		||||
	while (c-- > 0) {
 | 
			
		||||
		if ((*p++ = *cd++) == IAC)
 | 
			
		||||
			*p++ = IAC;
 | 
			
		||||
	}
 | 
			
		||||
	*p++ = IAC;
 | 
			
		||||
	*p++ = SE;
 | 
			
		||||
	if (str_data[3] == TELQUAL_IS)
 | 
			
		||||
		printsub('>', &str_data[2], p - (&str_data[2]));
 | 
			
		||||
	return(telnet_net_write(str_data, p - str_data));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	int
 | 
			
		||||
krb4encpwd_init(ap, server)
 | 
			
		||||
	Authenticator *ap;
 | 
			
		||||
	int server;
 | 
			
		||||
{
 | 
			
		||||
	char hostname[80], *cp, *realm;
 | 
			
		||||
	des_clock skey;
 | 
			
		||||
 | 
			
		||||
	if (server) {
 | 
			
		||||
		str_data[3] = TELQUAL_REPLY;
 | 
			
		||||
	} else {
 | 
			
		||||
		str_data[3] = TELQUAL_IS;
 | 
			
		||||
		gethostname(hostname, sizeof(hostname));
 | 
			
		||||
		realm = krb_realmofhost(hostname);
 | 
			
		||||
		cp = strchr(hostname, '.');
 | 
			
		||||
		if (*cp != NULL) *cp = NULL;
 | 
			
		||||
		if (read_service_key(KRB_SERVICE_NAME, hostname, realm, 0,
 | 
			
		||||
					KEYFILE, (char *)skey)) {
 | 
			
		||||
		  return(0);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	return(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	int
 | 
			
		||||
krb4encpwd_send(ap)
 | 
			
		||||
	Authenticator *ap;
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	printf("[ Trying KRB4ENCPWD ... ]\r\n");
 | 
			
		||||
	if (!UserNameRequested) {
 | 
			
		||||
		return(0);
 | 
			
		||||
	}
 | 
			
		||||
	if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
 | 
			
		||||
		return(0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!Data(ap, KRB4_ENCPWD_ACK, NULL, 0)) {
 | 
			
		||||
		return(0);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	void
 | 
			
		||||
krb4encpwd_is(ap, data, cnt)
 | 
			
		||||
	Authenticator *ap;
 | 
			
		||||
	unsigned char *data;
 | 
			
		||||
	int cnt;
 | 
			
		||||
{
 | 
			
		||||
	Session_Key skey;
 | 
			
		||||
	des_cblock datablock;
 | 
			
		||||
	char  r_passwd[ANAME_SZ], r_user[ANAME_SZ];
 | 
			
		||||
	char  lhostname[ANAME_SZ], *cp;
 | 
			
		||||
	int r;
 | 
			
		||||
	time_t now;
 | 
			
		||||
 | 
			
		||||
	if (cnt-- < 1)
 | 
			
		||||
		return;
 | 
			
		||||
	switch (*data++) {
 | 
			
		||||
	case KRB4_ENCPWD_AUTH:
 | 
			
		||||
		memmove(auth.dat, data, auth.length = cnt);
 | 
			
		||||
 | 
			
		||||
		gethostname(lhostname, sizeof(lhostname));
 | 
			
		||||
		if ((cp = strchr(lhostname, '.')) != 0)  *cp = '\0';
 | 
			
		||||
 | 
			
		||||
		if (r = krb_rd_encpwd_req(&auth, KRB_SERVICE_NAME, lhostname, 0, &adat, NULL, challenge, r_user, r_passwd)) {
 | 
			
		||||
			Data(ap, KRB4_ENCPWD_REJECT, "Auth failed", -1);
 | 
			
		||||
			auth_finished(ap, AUTH_REJECT);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
		auth_encrypt_userpwd(r_passwd);
 | 
			
		||||
		if (passwdok(UserNameRequested, UserPassword) == 0) {
 | 
			
		||||
		  /*
 | 
			
		||||
		   *  illegal username and password
 | 
			
		||||
		   */
 | 
			
		||||
		  Data(ap, KRB4_ENCPWD_REJECT, "Illegal password", -1);
 | 
			
		||||
		  auth_finished(ap, AUTH_REJECT);
 | 
			
		||||
		  return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		memmove(session_key, adat.session, sizeof(des_cblock));
 | 
			
		||||
		Data(ap, KRB4_ENCPWD_ACCEPT, 0, 0);
 | 
			
		||||
		auth_finished(ap, AUTH_USER);
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case KRB4_ENCPWD_CHALLENGE:
 | 
			
		||||
		/*
 | 
			
		||||
		 *  Take the received random challenge text and save
 | 
			
		||||
		 *  for future authentication.
 | 
			
		||||
		 */
 | 
			
		||||
		memmove(challenge, data, sizeof(des_cblock));
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	case KRB4_ENCPWD_ACK:
 | 
			
		||||
		/*
 | 
			
		||||
		 *  Receive ack, if mutual then send random challenge
 | 
			
		||||
		 */
 | 
			
		||||
 | 
			
		||||
		/*
 | 
			
		||||
		 * If we are doing mutual authentication, get set up to send
 | 
			
		||||
		 * the challenge, and verify it when the response comes back.
 | 
			
		||||
		 */
 | 
			
		||||
 | 
			
		||||
		if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
 | 
			
		||||
		  int i;
 | 
			
		||||
 | 
			
		||||
		  time(&now);
 | 
			
		||||
		  snprintf(challenge, sizeof(challenge), "%x", now);
 | 
			
		||||
		  Data(ap, KRB4_ENCPWD_CHALLENGE, challenge, strlen(challenge));
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		Data(ap, KRB4_ENCPWD_REJECT, 0, 0);
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	void
 | 
			
		||||
krb4encpwd_reply(ap, data, cnt)
 | 
			
		||||
	Authenticator *ap;
 | 
			
		||||
	unsigned char *data;
 | 
			
		||||
	int cnt;
 | 
			
		||||
{
 | 
			
		||||
	Session_Key skey;
 | 
			
		||||
	KTEXT_ST krb_token;
 | 
			
		||||
	des_cblock enckey;
 | 
			
		||||
	CREDENTIALS cred;
 | 
			
		||||
	int r;
 | 
			
		||||
	char	randchal[REALM_SZ], instance[ANAME_SZ], *cp;
 | 
			
		||||
	char	hostname[80], *realm;
 | 
			
		||||
 | 
			
		||||
	if (cnt-- < 1)
 | 
			
		||||
		return;
 | 
			
		||||
	switch (*data++) {
 | 
			
		||||
	case KRB4_ENCPWD_REJECT:
 | 
			
		||||
		if (cnt > 0) {
 | 
			
		||||
			printf("[ KRB4_ENCPWD refuses authentication because %.*s ]\r\n",
 | 
			
		||||
				cnt, data);
 | 
			
		||||
		} else
 | 
			
		||||
			printf("[ KRB4_ENCPWD refuses authentication ]\r\n");
 | 
			
		||||
		auth_send_retry();
 | 
			
		||||
		return;
 | 
			
		||||
	case KRB4_ENCPWD_ACCEPT:
 | 
			
		||||
		printf("[ KRB4_ENCPWD accepts you ]\r\n");
 | 
			
		||||
		auth_finished(ap, AUTH_USER);
 | 
			
		||||
		return;
 | 
			
		||||
	case KRB4_ENCPWD_CHALLENGE:
 | 
			
		||||
		/*
 | 
			
		||||
		 * Verify that the response to the challenge is correct.
 | 
			
		||||
		 */
 | 
			
		||||
 | 
			
		||||
		gethostname(hostname, sizeof(hostname));
 | 
			
		||||
		realm = krb_realmofhost(hostname);
 | 
			
		||||
		memmove(challenge, data, cnt);
 | 
			
		||||
		memset(user_passwd, 0, sizeof(user_passwd));
 | 
			
		||||
		des_read_pw_string(user_passwd, sizeof(user_passwd)-1, "Password: ", 0);
 | 
			
		||||
		UserPassword = user_passwd;
 | 
			
		||||
		Challenge = challenge;
 | 
			
		||||
		strlcpy(instance, RemoteHostName, sizeof(instance));
 | 
			
		||||
		if ((cp = strchr(instance, '.')) != 0)  *cp = '\0';
 | 
			
		||||
 | 
			
		||||
		if (r = krb_mk_encpwd_req(&krb_token, KRB_SERVICE_NAME, instance, realm, Challenge, UserNameRequested, user_passwd)) {
 | 
			
		||||
		  krb_token.length = 0;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (!Data(ap, KRB4_ENCPWD_AUTH, krb_token.dat, krb_token.length)) {
 | 
			
		||||
		  return;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
	int
 | 
			
		||||
krb4encpwd_status(ap, name, name_sz, level)
 | 
			
		||||
	Authenticator *ap;
 | 
			
		||||
	char *name;
 | 
			
		||||
	size_t name_sz;
 | 
			
		||||
	int level;
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
	if (level < AUTH_USER)
 | 
			
		||||
		return(level);
 | 
			
		||||
 | 
			
		||||
	if (UserNameRequested && passwdok(UserNameRequested, UserPassword)) {
 | 
			
		||||
		strlcpy(name, UserNameRequested, name_sz);
 | 
			
		||||
		return(AUTH_VALID);
 | 
			
		||||
	} else {
 | 
			
		||||
		return(AUTH_USER);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#define	BUMP(buf, len)		while (*(buf)) {++(buf), --(len);}
 | 
			
		||||
#define	ADDC(buf, len, c)	if ((len) > 0) {*(buf)++ = (c); --(len);}
 | 
			
		||||
 | 
			
		||||
	void
 | 
			
		||||
krb4encpwd_printsub(unsigned char *data, size_t cnt,
 | 
			
		||||
		    unsigned char *buf, size_t buflen)
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
 | 
			
		||||
	buf[buflen-1] = '\0';		/* make sure it's NULL terminated */
 | 
			
		||||
	buflen -= 1;
 | 
			
		||||
 | 
			
		||||
	switch(data[3]) {
 | 
			
		||||
	case KRB4_ENCPWD_REJECT:	/* Rejected (reason might follow) */
 | 
			
		||||
		strlcpy((char *)buf, " REJECT ", buflen);
 | 
			
		||||
		goto common;
 | 
			
		||||
 | 
			
		||||
	case KRB4_ENCPWD_ACCEPT:	/* Accepted (name might follow) */
 | 
			
		||||
		strlcpy((char *)buf, " ACCEPT ", buflen);
 | 
			
		||||
	common:
 | 
			
		||||
		BUMP(buf, buflen);
 | 
			
		||||
		if (cnt <= 4)
 | 
			
		||||
			break;
 | 
			
		||||
		ADDC(buf, buflen, '"');
 | 
			
		||||
		for (i = 4; i < cnt; i++)
 | 
			
		||||
			ADDC(buf, buflen, data[i]);
 | 
			
		||||
		ADDC(buf, buflen, '"');
 | 
			
		||||
		ADDC(buf, buflen, '\0');
 | 
			
		||||
		break;
 | 
			
		||||
 | 
			
		||||
	case KRB4_ENCPWD_AUTH:		/* Authentication data follows */
 | 
			
		||||
		strlcpy((char *)buf, " AUTH", buflen);
 | 
			
		||||
		goto common2;
 | 
			
		||||
 | 
			
		||||
	case KRB4_ENCPWD_CHALLENGE:
 | 
			
		||||
		strlcpy((char *)buf, " CHALLENGE", buflen);
 | 
			
		||||
		goto common2;
 | 
			
		||||
 | 
			
		||||
	case KRB4_ENCPWD_ACK:
 | 
			
		||||
		strlcpy((char *)buf, " ACK", buflen);
 | 
			
		||||
		goto common2;
 | 
			
		||||
 | 
			
		||||
	default:
 | 
			
		||||
		snprintf(buf, buflen, " %d (unknown)", data[3]);
 | 
			
		||||
	common2:
 | 
			
		||||
		BUMP(buf, buflen);
 | 
			
		||||
		for (i = 4; i < cnt; i++) {
 | 
			
		||||
			snprintf(buf, buflen, " %d", data[i]);
 | 
			
		||||
			BUMP(buf, buflen);
 | 
			
		||||
		}
 | 
			
		||||
		break;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int passwdok(name, passwd)
 | 
			
		||||
char *name, *passwd;
 | 
			
		||||
{
 | 
			
		||||
  char *crypt();
 | 
			
		||||
  char *salt, *p;
 | 
			
		||||
  struct passwd *pwd;
 | 
			
		||||
  int   passwdok_status = 0;
 | 
			
		||||
 | 
			
		||||
  if (pwd = k_getpwnam(name))
 | 
			
		||||
    salt = pwd->pw_passwd;
 | 
			
		||||
  else salt = "xx";
 | 
			
		||||
 | 
			
		||||
  p = crypt(passwd, salt);
 | 
			
		||||
 | 
			
		||||
  if (pwd && !strcmp(p, pwd->pw_passwd)) {
 | 
			
		||||
    passwdok_status = 1;
 | 
			
		||||
  } else passwdok_status = 0;
 | 
			
		||||
  return(passwdok_status);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifdef notdef
 | 
			
		||||
 | 
			
		||||
prkey(msg, key)
 | 
			
		||||
	char *msg;
 | 
			
		||||
	unsigned char *key;
 | 
			
		||||
{
 | 
			
		||||
	int i;
 | 
			
		||||
	printf("%s:", msg);
 | 
			
		||||
	for (i = 0; i < 8; i++)
 | 
			
		||||
		printf(" %3d", key[i]);
 | 
			
		||||
	printf("\r\n");
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
		Reference in New Issue
	
	Block a user