178a89ac8Sdab /*-
2bd8e26d4Sbostic * Copyright (c) 1992, 1993
3bd8e26d4Sbostic * The Regents of the University of California. All rights reserved.
478a89ac8Sdab *
578a89ac8Sdab * %sccs.include.redist.c%
678a89ac8Sdab */
778a89ac8Sdab
878a89ac8Sdab #ifndef lint
9*c4f3b704Sdab static char sccsid[] = "@(#)krb4encpwd.c 8.3 (Berkeley) 05/30/95";
1078a89ac8Sdab #endif /* not lint */
1178a89ac8Sdab
1278a89ac8Sdab
1378a89ac8Sdab #ifdef KRB4_ENCPWD
1478a89ac8Sdab /*
1578a89ac8Sdab * COPYRIGHT (C) 1990 DIGITAL EQUIPMENT CORPORATION
1678a89ac8Sdab * ALL RIGHTS RESERVED
1778a89ac8Sdab *
1878a89ac8Sdab * "Digital Equipment Corporation authorizes the reproduction,
1978a89ac8Sdab * distribution and modification of this software subject to the following
2078a89ac8Sdab * restrictions:
2178a89ac8Sdab *
2278a89ac8Sdab * 1. Any partial or whole copy of this software, or any modification
2378a89ac8Sdab * thereof, must include this copyright notice in its entirety.
2478a89ac8Sdab *
2578a89ac8Sdab * 2. This software is supplied "as is" with no warranty of any kind,
2678a89ac8Sdab * expressed or implied, for any purpose, including any warranty of fitness
2778a89ac8Sdab * or merchantibility. DIGITAL assumes no responsibility for the use or
2878a89ac8Sdab * reliability of this software, nor promises to provide any form of
2978a89ac8Sdab * support for it on any basis.
3078a89ac8Sdab *
3178a89ac8Sdab * 3. Distribution of this software is authorized only if no profit or
3278a89ac8Sdab * remuneration of any kind is received in exchange for such distribution.
3378a89ac8Sdab *
3478a89ac8Sdab * 4. This software produces public key authentication certificates
3578a89ac8Sdab * bearing an expiration date established by DIGITAL and RSA Data
3678a89ac8Sdab * Security, Inc. It may cease to generate certificates after the expiration
3778a89ac8Sdab * date. Any modification of this software that changes or defeats
3878a89ac8Sdab * the expiration date or its effect is unauthorized.
3978a89ac8Sdab *
4078a89ac8Sdab * 5. Software that will renew or extend the expiration date of
4178a89ac8Sdab * authentication certificates produced by this software may be obtained
4278a89ac8Sdab * from RSA Data Security, Inc., 10 Twin Dolphin Drive, Redwood City, CA
4378a89ac8Sdab * 94065, (415)595-8782, or from DIGITAL"
4478a89ac8Sdab *
4578a89ac8Sdab */
4678a89ac8Sdab
4778a89ac8Sdab #include <sys/types.h>
4878a89ac8Sdab #include <arpa/telnet.h>
4978a89ac8Sdab #include <pwd.h>
5078a89ac8Sdab #include <stdio.h>
5178a89ac8Sdab
5278a89ac8Sdab #include <des.h>
5378a89ac8Sdab #include <krb.h>
5478a89ac8Sdab #ifdef __STDC__
5578a89ac8Sdab #include <stdlib.h>
5678a89ac8Sdab #endif
5778a89ac8Sdab #ifdef NO_STRING_H
5878a89ac8Sdab #include <strings.h>
5978a89ac8Sdab #else
6078a89ac8Sdab #include <string.h>
6178a89ac8Sdab #endif
6278a89ac8Sdab
6378a89ac8Sdab #include "encrypt.h"
6478a89ac8Sdab #include "auth.h"
6578a89ac8Sdab #include "misc.h"
6678a89ac8Sdab
6778a89ac8Sdab int krb_mk_encpwd_req P((KTEXT, char *, char *, char *, char *, char *, char *));
6878a89ac8Sdab int krb_rd_encpwd_req P((KTEXT, char *, char *, u_long, AUTH_DAT *, char *, char *, char *, char *));
6978a89ac8Sdab
7078a89ac8Sdab extern auth_debug_mode;
7178a89ac8Sdab
7278a89ac8Sdab static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
7378a89ac8Sdab AUTHTYPE_KRB4_ENCPWD, };
7478a89ac8Sdab static unsigned char str_name[1024] = { IAC, SB, TELOPT_AUTHENTICATION,
7578a89ac8Sdab TELQUAL_NAME, };
7678a89ac8Sdab
7778a89ac8Sdab #define KRB4_ENCPWD_AUTH 0 /* Authentication data follows */
7878a89ac8Sdab #define KRB4_ENCPWD_REJECT 1 /* Rejected (reason might follow) */
7978a89ac8Sdab #define KRB4_ENCPWD_ACCEPT 2 /* Accepted */
8078a89ac8Sdab #define KRB4_ENCPWD_CHALLENGE 3 /* Challenge for mutual auth. */
8178a89ac8Sdab #define KRB4_ENCPWD_ACK 4 /* Acknowledge */
8278a89ac8Sdab
8378a89ac8Sdab #define KRB_SERVICE_NAME "rcmd"
8478a89ac8Sdab
8578a89ac8Sdab static KTEXT_ST auth;
8678a89ac8Sdab static char name[ANAME_SZ];
8778a89ac8Sdab static char user_passwd[ANAME_SZ];
8878a89ac8Sdab static AUTH_DAT adat = { 0 };
89900e5c23Sdab #ifdef ENCRYPTION
9078a89ac8Sdab static Block session_key = { 0 };
91900e5c23Sdab #endif /* ENCRYPTION */
9278a89ac8Sdab static Schedule sched;
9378a89ac8Sdab static char challenge[REALM_SZ];
9478a89ac8Sdab
9578a89ac8Sdab static int
Data(ap,type,d,c)9678a89ac8Sdab Data(ap, type, d, c)
9778a89ac8Sdab Authenticator *ap;
9878a89ac8Sdab int type;
9978a89ac8Sdab void *d;
10078a89ac8Sdab int c;
10178a89ac8Sdab {
10278a89ac8Sdab unsigned char *p = str_data + 4;
10378a89ac8Sdab unsigned char *cd = (unsigned char *)d;
10478a89ac8Sdab
10578a89ac8Sdab if (c == -1)
10678a89ac8Sdab c = strlen((char *)cd);
10778a89ac8Sdab
10878a89ac8Sdab if (0) {
10978a89ac8Sdab printf("%s:%d: [%d] (%d)",
11078a89ac8Sdab str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
11178a89ac8Sdab str_data[3],
11278a89ac8Sdab type, c);
11378a89ac8Sdab printd(d, c);
11478a89ac8Sdab printf("\r\n");
11578a89ac8Sdab }
11678a89ac8Sdab *p++ = ap->type;
11778a89ac8Sdab *p++ = ap->way;
11878a89ac8Sdab *p++ = type;
11978a89ac8Sdab while (c-- > 0) {
12078a89ac8Sdab if ((*p++ = *cd++) == IAC)
12178a89ac8Sdab *p++ = IAC;
12278a89ac8Sdab }
12378a89ac8Sdab *p++ = IAC;
12478a89ac8Sdab *p++ = SE;
12578a89ac8Sdab if (str_data[3] == TELQUAL_IS)
12678a89ac8Sdab printsub('>', &str_data[2], p - (&str_data[2]));
12778a89ac8Sdab return(net_write(str_data, p - str_data));
12878a89ac8Sdab }
12978a89ac8Sdab
13078a89ac8Sdab int
krb4encpwd_init(ap,server)13178a89ac8Sdab krb4encpwd_init(ap, server)
13278a89ac8Sdab Authenticator *ap;
13378a89ac8Sdab int server;
13478a89ac8Sdab {
13578a89ac8Sdab char hostname[80], *cp, *realm;
13678a89ac8Sdab C_Block skey;
13778a89ac8Sdab
13878a89ac8Sdab if (server) {
13978a89ac8Sdab str_data[3] = TELQUAL_REPLY;
14078a89ac8Sdab } else {
14178a89ac8Sdab str_data[3] = TELQUAL_IS;
14278a89ac8Sdab gethostname(hostname, sizeof(hostname));
14378a89ac8Sdab realm = krb_realmofhost(hostname);
144*c4f3b704Sdab cp = strchr(hostname, '.');
14578a89ac8Sdab if (*cp != NULL) *cp = NULL;
14678a89ac8Sdab if (read_service_key(KRB_SERVICE_NAME, hostname, realm, 0,
14778a89ac8Sdab KEYFILE, (char *)skey)) {
14878a89ac8Sdab return(0);
14978a89ac8Sdab }
15078a89ac8Sdab }
15178a89ac8Sdab return(1);
15278a89ac8Sdab }
15378a89ac8Sdab
15478a89ac8Sdab int
krb4encpwd_send(ap)15578a89ac8Sdab krb4encpwd_send(ap)
15678a89ac8Sdab Authenticator *ap;
15778a89ac8Sdab {
15878a89ac8Sdab
15978a89ac8Sdab printf("[ Trying KRB4ENCPWD ... ]\n");
16078a89ac8Sdab if (!UserNameRequested) {
16178a89ac8Sdab return(0);
16278a89ac8Sdab }
16378a89ac8Sdab if (!auth_sendname(UserNameRequested, strlen(UserNameRequested))) {
16478a89ac8Sdab return(0);
16578a89ac8Sdab }
16678a89ac8Sdab
16778a89ac8Sdab if (!Data(ap, KRB4_ENCPWD_ACK, (void *)NULL, 0)) {
16878a89ac8Sdab return(0);
16978a89ac8Sdab }
17078a89ac8Sdab
17178a89ac8Sdab return(1);
17278a89ac8Sdab }
17378a89ac8Sdab
17478a89ac8Sdab void
krb4encpwd_is(ap,data,cnt)17578a89ac8Sdab krb4encpwd_is(ap, data, cnt)
17678a89ac8Sdab Authenticator *ap;
17778a89ac8Sdab unsigned char *data;
17878a89ac8Sdab int cnt;
17978a89ac8Sdab {
18078a89ac8Sdab Session_Key skey;
18178a89ac8Sdab Block datablock;
18278a89ac8Sdab char r_passwd[ANAME_SZ], r_user[ANAME_SZ];
18378a89ac8Sdab char lhostname[ANAME_SZ], *cp;
18478a89ac8Sdab int r;
18578a89ac8Sdab time_t now;
18678a89ac8Sdab
18778a89ac8Sdab if (cnt-- < 1)
18878a89ac8Sdab return;
18978a89ac8Sdab switch (*data++) {
19078a89ac8Sdab case KRB4_ENCPWD_AUTH:
191*c4f3b704Sdab memmove((void *)auth.dat, (void *)data, auth.length = cnt);
19278a89ac8Sdab
19378a89ac8Sdab gethostname(lhostname, sizeof(lhostname));
194*c4f3b704Sdab if ((cp = strchr(lhostname, '.')) != 0) *cp = '\0';
19578a89ac8Sdab
19678a89ac8Sdab if (r = krb_rd_encpwd_req(&auth, KRB_SERVICE_NAME, lhostname, 0, &adat, NULL, challenge, r_user, r_passwd)) {
19778a89ac8Sdab Data(ap, KRB4_ENCPWD_REJECT, (void *)"Auth failed", -1);
19878a89ac8Sdab auth_finished(ap, AUTH_REJECT);
19978a89ac8Sdab return;
20078a89ac8Sdab }
20178a89ac8Sdab auth_encrypt_userpwd(r_passwd);
20278a89ac8Sdab if (passwdok(UserNameRequested, UserPassword) == 0) {
20378a89ac8Sdab /*
20478a89ac8Sdab * illegal username and password
20578a89ac8Sdab */
20678a89ac8Sdab Data(ap, KRB4_ENCPWD_REJECT, (void *)"Illegal password", -1);
20778a89ac8Sdab auth_finished(ap, AUTH_REJECT);
20878a89ac8Sdab return;
20978a89ac8Sdab }
21078a89ac8Sdab
211*c4f3b704Sdab memmove((void *)session_key, (void *)adat.session, sizeof(Block));
21278a89ac8Sdab Data(ap, KRB4_ENCPWD_ACCEPT, (void *)0, 0);
21378a89ac8Sdab auth_finished(ap, AUTH_USER);
21478a89ac8Sdab break;
21578a89ac8Sdab
21678a89ac8Sdab case KRB4_ENCPWD_CHALLENGE:
21778a89ac8Sdab /*
21878a89ac8Sdab * Take the received random challenge text and save
21978a89ac8Sdab * for future authentication.
22078a89ac8Sdab */
221*c4f3b704Sdab memmove((void *)challenge, (void *)data, sizeof(Block));
22278a89ac8Sdab break;
22378a89ac8Sdab
22478a89ac8Sdab
22578a89ac8Sdab case KRB4_ENCPWD_ACK:
22678a89ac8Sdab /*
22778a89ac8Sdab * Receive ack, if mutual then send random challenge
22878a89ac8Sdab */
22978a89ac8Sdab
23078a89ac8Sdab /*
23178a89ac8Sdab * If we are doing mutual authentication, get set up to send
2328a34ee9eSdab * the challenge, and verify it when the response comes back.
23378a89ac8Sdab */
23478a89ac8Sdab
23578a89ac8Sdab if ((ap->way & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) {
23678a89ac8Sdab register int i;
23778a89ac8Sdab
23878a89ac8Sdab time(&now);
23978a89ac8Sdab sprintf(challenge, "%x", now);
24078a89ac8Sdab Data(ap, KRB4_ENCPWD_CHALLENGE, (void *)challenge, strlen(challenge));
24178a89ac8Sdab }
24278a89ac8Sdab break;
24378a89ac8Sdab
24478a89ac8Sdab default:
24578a89ac8Sdab Data(ap, KRB4_ENCPWD_REJECT, 0, 0);
24678a89ac8Sdab break;
24778a89ac8Sdab }
24878a89ac8Sdab }
24978a89ac8Sdab
25078a89ac8Sdab
25178a89ac8Sdab void
krb4encpwd_reply(ap,data,cnt)25278a89ac8Sdab krb4encpwd_reply(ap, data, cnt)
25378a89ac8Sdab Authenticator *ap;
25478a89ac8Sdab unsigned char *data;
25578a89ac8Sdab int cnt;
25678a89ac8Sdab {
25778a89ac8Sdab Session_Key skey;
25878a89ac8Sdab KTEXT_ST krb_token;
25978a89ac8Sdab Block enckey;
26078a89ac8Sdab CREDENTIALS cred;
26178a89ac8Sdab int r;
26278a89ac8Sdab char randchal[REALM_SZ], instance[ANAME_SZ], *cp;
26378a89ac8Sdab char hostname[80], *realm;
26478a89ac8Sdab
26578a89ac8Sdab if (cnt-- < 1)
26678a89ac8Sdab return;
26778a89ac8Sdab switch (*data++) {
26878a89ac8Sdab case KRB4_ENCPWD_REJECT:
26978a89ac8Sdab if (cnt > 0) {
27078a89ac8Sdab printf("[ KRB4_ENCPWD refuses authentication because %.*s ]\r\n",
27178a89ac8Sdab cnt, data);
27278a89ac8Sdab } else
27378a89ac8Sdab printf("[ KRB4_ENCPWD refuses authentication ]\r\n");
27478a89ac8Sdab auth_send_retry();
27578a89ac8Sdab return;
27678a89ac8Sdab case KRB4_ENCPWD_ACCEPT:
27778a89ac8Sdab printf("[ KRB4_ENCPWD accepts you ]\n");
27878a89ac8Sdab auth_finished(ap, AUTH_USER);
27978a89ac8Sdab return;
28078a89ac8Sdab case KRB4_ENCPWD_CHALLENGE:
28178a89ac8Sdab /*
28278a89ac8Sdab * Verify that the response to the challenge is correct.
28378a89ac8Sdab */
28478a89ac8Sdab
28578a89ac8Sdab gethostname(hostname, sizeof(hostname));
28678a89ac8Sdab realm = krb_realmofhost(hostname);
287*c4f3b704Sdab memmove((void *)challenge, (void *)data, cnt);
288*c4f3b704Sdab memset(user_passwd, 0, sizeof(user_passwd));
28978a89ac8Sdab local_des_read_pw_string(user_passwd, sizeof(user_passwd)-1, "Password: ", 0);
29078a89ac8Sdab UserPassword = user_passwd;
29178a89ac8Sdab Challenge = challenge;
29278a89ac8Sdab strcpy(instance, RemoteHostName);
293*c4f3b704Sdab if ((cp = strchr(instance, '.')) != 0) *cp = '\0';
29478a89ac8Sdab
29578a89ac8Sdab if (r = krb_mk_encpwd_req(&krb_token, KRB_SERVICE_NAME, instance, realm, Challenge, UserNameRequested, user_passwd)) {
29678a89ac8Sdab krb_token.length = 0;
29778a89ac8Sdab }
29878a89ac8Sdab
29978a89ac8Sdab if (!Data(ap, KRB4_ENCPWD_AUTH, (void *)krb_token.dat, krb_token.length)) {
30078a89ac8Sdab return;
30178a89ac8Sdab }
30278a89ac8Sdab
30378a89ac8Sdab break;
30478a89ac8Sdab
30578a89ac8Sdab default:
30678a89ac8Sdab return;
30778a89ac8Sdab }
30878a89ac8Sdab }
30978a89ac8Sdab
31078a89ac8Sdab int
krb4encpwd_status(ap,name,level)31178a89ac8Sdab krb4encpwd_status(ap, name, level)
31278a89ac8Sdab Authenticator *ap;
31378a89ac8Sdab char *name;
31478a89ac8Sdab int level;
31578a89ac8Sdab {
31678a89ac8Sdab
31778a89ac8Sdab if (level < AUTH_USER)
31878a89ac8Sdab return(level);
31978a89ac8Sdab
32078a89ac8Sdab if (UserNameRequested && passwdok(UserNameRequested, UserPassword)) {
32178a89ac8Sdab strcpy(name, UserNameRequested);
32278a89ac8Sdab return(AUTH_VALID);
32378a89ac8Sdab } else {
32478a89ac8Sdab return(AUTH_USER);
32578a89ac8Sdab }
32678a89ac8Sdab }
32778a89ac8Sdab
32878a89ac8Sdab #define BUMP(buf, len) while (*(buf)) {++(buf), --(len);}
32978a89ac8Sdab #define ADDC(buf, len, c) if ((len) > 0) {*(buf)++ = (c); --(len);}
33078a89ac8Sdab
33178a89ac8Sdab void
krb4encpwd_printsub(data,cnt,buf,buflen)33278a89ac8Sdab krb4encpwd_printsub(data, cnt, buf, buflen)
33378a89ac8Sdab unsigned char *data, *buf;
33478a89ac8Sdab int cnt, buflen;
33578a89ac8Sdab {
33678a89ac8Sdab char lbuf[32];
33778a89ac8Sdab register int i;
33878a89ac8Sdab
33978a89ac8Sdab buf[buflen-1] = '\0'; /* make sure its NULL terminated */
34078a89ac8Sdab buflen -= 1;
34178a89ac8Sdab
34278a89ac8Sdab switch(data[3]) {
34378a89ac8Sdab case KRB4_ENCPWD_REJECT: /* Rejected (reason might follow) */
34478a89ac8Sdab strncpy((char *)buf, " REJECT ", buflen);
34578a89ac8Sdab goto common;
34678a89ac8Sdab
34778a89ac8Sdab case KRB4_ENCPWD_ACCEPT: /* Accepted (name might follow) */
34878a89ac8Sdab strncpy((char *)buf, " ACCEPT ", buflen);
34978a89ac8Sdab common:
35078a89ac8Sdab BUMP(buf, buflen);
35178a89ac8Sdab if (cnt <= 4)
35278a89ac8Sdab break;
35378a89ac8Sdab ADDC(buf, buflen, '"');
35478a89ac8Sdab for (i = 4; i < cnt; i++)
35578a89ac8Sdab ADDC(buf, buflen, data[i]);
35678a89ac8Sdab ADDC(buf, buflen, '"');
35778a89ac8Sdab ADDC(buf, buflen, '\0');
35878a89ac8Sdab break;
35978a89ac8Sdab
36078a89ac8Sdab case KRB4_ENCPWD_AUTH: /* Authentication data follows */
36178a89ac8Sdab strncpy((char *)buf, " AUTH", buflen);
36278a89ac8Sdab goto common2;
36378a89ac8Sdab
36478a89ac8Sdab case KRB4_ENCPWD_CHALLENGE:
36578a89ac8Sdab strncpy((char *)buf, " CHALLENGE", buflen);
36678a89ac8Sdab goto common2;
36778a89ac8Sdab
36878a89ac8Sdab case KRB4_ENCPWD_ACK:
36978a89ac8Sdab strncpy((char *)buf, " ACK", buflen);
37078a89ac8Sdab goto common2;
37178a89ac8Sdab
37278a89ac8Sdab default:
37378a89ac8Sdab sprintf(lbuf, " %d (unknown)", data[3]);
37478a89ac8Sdab strncpy((char *)buf, lbuf, buflen);
37578a89ac8Sdab common2:
37678a89ac8Sdab BUMP(buf, buflen);
37778a89ac8Sdab for (i = 4; i < cnt; i++) {
37878a89ac8Sdab sprintf(lbuf, " %d", data[i]);
37978a89ac8Sdab strncpy((char *)buf, lbuf, buflen);
38078a89ac8Sdab BUMP(buf, buflen);
38178a89ac8Sdab }
38278a89ac8Sdab break;
38378a89ac8Sdab }
38478a89ac8Sdab }
38578a89ac8Sdab
passwdok(name,passwd)38678a89ac8Sdab int passwdok(name, passwd)
38778a89ac8Sdab char *name, *passwd;
38878a89ac8Sdab {
38978a89ac8Sdab char *crypt();
39078a89ac8Sdab char *salt, *p;
39178a89ac8Sdab struct passwd *pwd;
39278a89ac8Sdab int passwdok_status = 0;
39378a89ac8Sdab
39478a89ac8Sdab if (pwd = getpwnam(name))
39578a89ac8Sdab salt = pwd->pw_passwd;
39678a89ac8Sdab else salt = "xx";
39778a89ac8Sdab
39878a89ac8Sdab p = crypt(passwd, salt);
39978a89ac8Sdab
40078a89ac8Sdab if (pwd && !strcmp(p, pwd->pw_passwd)) {
40178a89ac8Sdab passwdok_status = 1;
40278a89ac8Sdab } else passwdok_status = 0;
40378a89ac8Sdab return(passwdok_status);
40478a89ac8Sdab }
40578a89ac8Sdab
40678a89ac8Sdab #endif
40778a89ac8Sdab
40878a89ac8Sdab #ifdef notdef
40978a89ac8Sdab
prkey(msg,key)41078a89ac8Sdab prkey(msg, key)
41178a89ac8Sdab char *msg;
41278a89ac8Sdab unsigned char *key;
41378a89ac8Sdab {
41478a89ac8Sdab register int i;
41578a89ac8Sdab printf("%s:", msg);
41678a89ac8Sdab for (i = 0; i < 8; i++)
41778a89ac8Sdab printf(" %3d", key[i]);
41878a89ac8Sdab printf("\r\n");
41978a89ac8Sdab }
42078a89ac8Sdab #endif
421