sra.c revision 76610
163248Speter/* $FreeBSD: head/contrib/telnet/libtelnet/sra.c 76610 2001-05-15 04:47:14Z nsayer $ */
263248Speter
349887Snsayer#ifdef	SRA
449887Snsayer#include <sys/types.h>
549887Snsayer#include <arpa/telnet.h>
649887Snsayer#include <stdio.h>
749887Snsayer#ifdef	__STDC__
849887Snsayer#include <stdlib.h>
949887Snsayer#endif
1049887Snsayer#ifdef	NO_STRING_H
1149887Snsayer#include <strings.h>
1249887Snsayer#else
1349887Snsayer#include <string.h>
1449887Snsayer#endif
1549887Snsayer
1676339Snsayer#if !defined(NOPAM)
1776339Snsayer#include <security/pam_appl.h>
1876339Snsayer#endif
1976339Snsayer
2076610Snsayer#include <ttyent.h>
2176610Snsayer
2249887Snsayer#include "auth.h"
2349887Snsayer#include "misc.h"
2449887Snsayer#include "encrypt.h"
2549887Snsayer#include "pk.h"
2649887Snsayer
2749887Snsayerchar pka[HEXKEYBYTES+1], ska[HEXKEYBYTES+1], pkb[HEXKEYBYTES+1];
2849887Snsayerchar *user,*pass,*xuser,*xpass;
2949887SnsayerDesData ck;
3049887SnsayerIdeaData ik;
3149887Snsayer
3249887Snsayerextern int auth_debug_mode;
3376610Snsayerextern char *line;
3476610Snsayer
3549887Snsayerstatic sra_valid = 0;
3649887Snsayerstatic passwd_sent = 0;
3749887Snsayer
3849887Snsayerstatic unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
3949887Snsayer			  		AUTHTYPE_SRA, };
4049887Snsayer
4149887Snsayer#define SRA_KEY	0
4249887Snsayer#define SRA_USER 1
4349887Snsayer#define SRA_CONTINUE 2
4449887Snsayer#define SRA_PASS 3
4549887Snsayer#define SRA_ACCEPT 4
4649887Snsayer#define SRA_REJECT 5
4749887Snsayer
4849887Snsayer/* support routine to send out authentication message */
4949887Snsayerstatic int Data(ap, type, d, c)
5049887SnsayerAuthenticator *ap;
5149887Snsayerint type;
5249887Snsayervoid *d;
5349887Snsayerint c;
5449887Snsayer{
5549887Snsayer        unsigned char *p = str_data + 4;
5649887Snsayer	unsigned char *cd = (unsigned char *)d;
5749887Snsayer
5849887Snsayer	if (c == -1)
5949887Snsayer		c = strlen((char *)cd);
6049887Snsayer
6149887Snsayer        if (auth_debug_mode) {
6249887Snsayer                printf("%s:%d: [%d] (%d)",
6349887Snsayer                        str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
6449887Snsayer                        str_data[3],
6549887Snsayer                        type, c);
6649887Snsayer                printd(d, c);
6749887Snsayer                printf("\r\n");
6849887Snsayer        }
6949887Snsayer	*p++ = ap->type;
7049887Snsayer	*p++ = ap->way;
7149887Snsayer	*p++ = type;
7249887Snsayer        while (c-- > 0) {
7349887Snsayer                if ((*p++ = *cd++) == IAC)
7449887Snsayer                        *p++ = IAC;
7549887Snsayer        }
7649887Snsayer        *p++ = IAC;
7749887Snsayer        *p++ = SE;
7849887Snsayer	if (str_data[3] == TELQUAL_IS)
7949887Snsayer		printsub('>', &str_data[2], p - (&str_data[2]));
8049887Snsayer        return(net_write(str_data, p - str_data));
8149887Snsayer}
8249887Snsayer
8349887Snsayerint sra_init(ap, server)
8449887SnsayerAuthenticator *ap;
8549887Snsayerint server;
8649887Snsayer{
8749887Snsayer	if (server)
8849887Snsayer		str_data[3] = TELQUAL_REPLY;
8949887Snsayer	else
9049887Snsayer		str_data[3] = TELQUAL_IS;
9149887Snsayer
9249887Snsayer	user = (char *)malloc(256);
9349887Snsayer	xuser = (char *)malloc(512);
9449887Snsayer	pass = (char *)malloc(256);
9549887Snsayer	xpass = (char *)malloc(512);
9649887Snsayer	passwd_sent = 0;
9749887Snsayer
9849887Snsayer	genkeys(pka,ska);
9949887Snsayer	return(1);
10049887Snsayer}
10149887Snsayer
10249887Snsayer/* client received a go-ahead for sra */
10349887Snsayerint sra_send(ap)
10449887SnsayerAuthenticator *ap;
10549887Snsayer{
10649887Snsayer	/* send PKA */
10749887Snsayer
10849887Snsayer	if (auth_debug_mode)
10949887Snsayer		printf("Sent PKA to server.\r\n" );
11049887Snsayer	printf("Trying SRA secure login:\r\n");
11149887Snsayer	if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) {
11249887Snsayer		if (auth_debug_mode)
11349887Snsayer			printf("Not enough room for authentication data\r\n");
11449887Snsayer		return(0);
11549887Snsayer	}
11649887Snsayer
11749887Snsayer	return(1);
11849887Snsayer}
11949887Snsayer
12049887Snsayer/* server received an IS -- could be SRA KEY, USER, or PASS */
12149887Snsayervoid sra_is(ap, data, cnt)
12249887SnsayerAuthenticator *ap;
12349887Snsayerunsigned char *data;
12449887Snsayerint cnt;
12549887Snsayer{
12649887Snsayer	int valid;
12749887Snsayer	Session_Key skey;
12849887Snsayer
12949887Snsayer	if (cnt-- < 1)
13049887Snsayer		return;
13149887Snsayer	switch (*data++) {
13249887Snsayer
13349887Snsayer	case SRA_KEY:
13449887Snsayer		if (cnt < HEXKEYBYTES) {
13549887Snsayer			Data(ap, SRA_REJECT, (void *)0, 0);
13649887Snsayer			auth_finished(ap, AUTH_USER);
13749887Snsayer			if (auth_debug_mode) {
13849887Snsayer				printf("SRA user rejected for bad PKB\r\n");
13949887Snsayer			}
14049887Snsayer			return;
14149887Snsayer		}
14249887Snsayer		if (auth_debug_mode)
14349887Snsayer			printf("Sent pka\r\n");
14449887Snsayer		if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) {
14549887Snsayer			if (auth_debug_mode)
14649887Snsayer				printf("Not enough room\r\n");
14749887Snsayer			return;
14849887Snsayer		}
14949887Snsayer		memcpy(pkb,data,HEXKEYBYTES);
15049887Snsayer		pkb[HEXKEYBYTES] = '\0';
15149887Snsayer		common_key(ska,pkb,&ik,&ck);
15249887Snsayer		break;
15349887Snsayer
15449887Snsayer	case SRA_USER:
15549887Snsayer		/* decode KAB(u) */
15649887Snsayer		memcpy(xuser,data,cnt);
15749887Snsayer		xuser[cnt] = '\0';
15849887Snsayer		pk_decode(xuser,user,&ck);
15949887Snsayer		auth_encrypt_user(user);
16049887Snsayer		Data(ap, SRA_CONTINUE, (void *)0, 0);
16149887Snsayer
16249887Snsayer		break;
16349887Snsayer
16449887Snsayer	case SRA_PASS:
16549887Snsayer		/* decode KAB(P) */
16649887Snsayer		memcpy(xpass,data,cnt);
16749887Snsayer		xpass[cnt] = '\0';
16849887Snsayer		pk_decode(xpass,pass,&ck);
16949887Snsayer
17049887Snsayer		/* check user's password */
17149887Snsayer		valid = check_user(user,pass);
17249887Snsayer
17349887Snsayer		if(valid) {
17449887Snsayer			Data(ap, SRA_ACCEPT, (void *)0, 0);
17549887Snsayer#ifdef DES_ENCRYPTION
17649887Snsayer			skey.data = ck;
17749887Snsayer			skey.type = SK_DES;
17849887Snsayer			skey.length = 8;
17949887Snsayer			encrypt_session_key(&skey, 1);
18049887Snsayer#endif
18149887Snsayer
18249887Snsayer			sra_valid = 1;
18349887Snsayer			auth_finished(ap, AUTH_VALID);
18449887Snsayer			if (auth_debug_mode) {
18549887Snsayer				printf("SRA user accepted\r\n");
18649887Snsayer			}
18749887Snsayer		}
18849887Snsayer		else {
18949887Snsayer			Data(ap, SRA_CONTINUE, (void *)0, 0);
19049887Snsayer/*
19149887Snsayer			Data(ap, SRA_REJECT, (void *)0, 0);
19249887Snsayer			sra_valid = 0;
19349887Snsayer			auth_finished(ap, AUTH_REJECT);
19449887Snsayer*/
19549887Snsayer			if (auth_debug_mode) {
19649887Snsayer				printf("SRA user failed\r\n");
19749887Snsayer			}
19849887Snsayer		}
19949887Snsayer		break;
20049887Snsayer
20149887Snsayer	default:
20249887Snsayer		if (auth_debug_mode)
20349887Snsayer			printf("Unknown SRA option %d\r\n", data[-1]);
20449887Snsayer		Data(ap, SRA_REJECT, 0, 0);
20549887Snsayer		sra_valid = 0;
20649887Snsayer		auth_finished(ap, AUTH_REJECT);
20749887Snsayer		break;
20849887Snsayer	}
20949887Snsayer}
21049887Snsayer
21149887Snsayerextern char *getpass();
21249887Snsayer
21349887Snsayer/* client received REPLY -- could be SRA KEY, CONTINUE, ACCEPT, or REJECT */
21449887Snsayervoid sra_reply(ap, data, cnt)
21549887SnsayerAuthenticator *ap;
21649887Snsayerunsigned char *data;
21749887Snsayerint cnt;
21849887Snsayer{
21949887Snsayer	extern char *telnet_gets();
22049887Snsayer	char uprompt[256],tuser[256];
22149887Snsayer	Session_Key skey;
22249887Snsayer	int i;
22349887Snsayer
22449887Snsayer	if (cnt-- < 1)
22549887Snsayer		return;
22649887Snsayer	switch (*data++) {
22749887Snsayer
22849887Snsayer	case SRA_KEY:
22949887Snsayer		/* calculate common key */
23049887Snsayer		if (cnt < HEXKEYBYTES) {
23149887Snsayer			if (auth_debug_mode) {
23249887Snsayer				printf("SRA user rejected for bad PKB\r\n");
23349887Snsayer			}
23449887Snsayer			return;
23549887Snsayer		}
23649887Snsayer		memcpy(pkb,data,HEXKEYBYTES);
23749887Snsayer		pkb[HEXKEYBYTES] = '\0';
23849887Snsayer
23949887Snsayer		common_key(ska,pkb,&ik,&ck);
24049887Snsayer
24149887Snsayer	enc_user:
24249887Snsayer
24349887Snsayer		/* encode user */
24449887Snsayer		memset(tuser,0,sizeof(tuser));
24549887Snsayer		sprintf(uprompt,"User (%s): ",UserNameRequested);
24649887Snsayer		telnet_gets(uprompt,tuser,255,1);
24749887Snsayer		if (tuser[0] == '\n' || tuser[0] == '\r' )
24849887Snsayer			strcpy(user,UserNameRequested);
24949887Snsayer		else {
25049887Snsayer			/* telnet_gets leaves the newline on */
25149887Snsayer			for(i=0;i<sizeof(tuser);i++) {
25249887Snsayer				if (tuser[i] == '\n') {
25349887Snsayer					tuser[i] = '\0';
25449887Snsayer					break;
25549887Snsayer				}
25649887Snsayer			}
25749887Snsayer			strcpy(user,tuser);
25849887Snsayer		}
25949887Snsayer		pk_encode(user,xuser,&ck);
26049887Snsayer
26149887Snsayer		/* send it off */
26249887Snsayer		if (auth_debug_mode)
26349887Snsayer			printf("Sent KAB(U)\r\n");
26449887Snsayer		if (!Data(ap, SRA_USER, (void *)xuser, strlen(xuser))) {
26549887Snsayer			if (auth_debug_mode)
26649887Snsayer				printf("Not enough room\r\n");
26749887Snsayer			return;
26849887Snsayer		}
26949887Snsayer		break;
27049887Snsayer
27149887Snsayer	case SRA_CONTINUE:
27249887Snsayer		if (passwd_sent) {
27349887Snsayer			passwd_sent = 0;
27449887Snsayer			printf("[ SRA login failed ]\r\n");
27549887Snsayer			goto enc_user;
27649887Snsayer		}
27749887Snsayer		/* encode password */
27849887Snsayer		memset(pass,0,sizeof(pass));
27949887Snsayer		telnet_gets("Password: ",pass,255,0);
28049887Snsayer		pk_encode(pass,xpass,&ck);
28149887Snsayer		/* send it off */
28249887Snsayer		if (auth_debug_mode)
28349887Snsayer			printf("Sent KAB(P)\r\n");
28449887Snsayer		if (!Data(ap, SRA_PASS, (void *)xpass, strlen(xpass))) {
28549887Snsayer			if (auth_debug_mode)
28649887Snsayer				printf("Not enough room\r\n");
28749887Snsayer			return;
28849887Snsayer		}
28949887Snsayer		passwd_sent = 1;
29049887Snsayer		break;
29149887Snsayer
29249887Snsayer	case SRA_REJECT:
29349887Snsayer		printf("[ SRA refuses authentication ]\r\n");
29449887Snsayer		printf("Trying plaintext login:\r\n");
29549887Snsayer		auth_finished(0,AUTH_REJECT);
29649887Snsayer		return;
29749887Snsayer
29849887Snsayer	case SRA_ACCEPT:
29949887Snsayer		printf("[ SRA accepts you ]\r\n");
30049887Snsayer#ifdef DES_ENCRYPTION
30149887Snsayer		skey.data = ck;
30249887Snsayer		skey.type = SK_DES;
30349887Snsayer		skey.length = 8;
30449887Snsayer		encrypt_session_key(&skey, 0);
30549887Snsayer#endif
30649887Snsayer
30749887Snsayer		auth_finished(ap, AUTH_VALID);
30849887Snsayer		return;
30949887Snsayer	default:
31049887Snsayer		if (auth_debug_mode)
31149887Snsayer			printf("Unknown SRA option %d\r\n", data[-1]);
31249887Snsayer		return;
31349887Snsayer	}
31449887Snsayer}
31549887Snsayer
31649887Snsayerint sra_status(ap, name, level)
31749887SnsayerAuthenticator *ap;
31849887Snsayerchar *name;
31949887Snsayerint level;
32049887Snsayer{
32149887Snsayer	if (level < AUTH_USER)
32249887Snsayer		return(level);
32349887Snsayer	if (UserNameRequested && sra_valid) {
32449887Snsayer		strcpy(name, UserNameRequested);
32549887Snsayer		return(AUTH_VALID);
32649887Snsayer	} else
32749887Snsayer		return(AUTH_USER);
32849887Snsayer}
32949887Snsayer
33049887Snsayer#define	BUMP(buf, len)		while (*(buf)) {++(buf), --(len);}
33149887Snsayer#define	ADDC(buf, len, c)	if ((len) > 0) {*(buf)++ = (c); --(len);}
33249887Snsayer
33349887Snsayervoid sra_printsub(data, cnt, buf, buflen)
33449887Snsayerunsigned char *data, *buf;
33549887Snsayerint cnt, buflen;
33649887Snsayer{
33749887Snsayer	char lbuf[32];
33849887Snsayer	register int i;
33949887Snsayer
34049887Snsayer	buf[buflen-1] = '\0';		/* make sure its NULL terminated */
34149887Snsayer	buflen -= 1;
34249887Snsayer
34349887Snsayer	switch(data[3]) {
34449887Snsayer
34549887Snsayer	case SRA_CONTINUE:
34649887Snsayer		strncpy((char *)buf, " CONTINUE ", buflen);
34749887Snsayer		goto common;
34849887Snsayer
34949887Snsayer	case SRA_REJECT:		/* Rejected (reason might follow) */
35049887Snsayer		strncpy((char *)buf, " REJECT ", buflen);
35149887Snsayer		goto common;
35249887Snsayer
35349887Snsayer	case SRA_ACCEPT:		/* Accepted (name might follow) */
35449887Snsayer		strncpy((char *)buf, " ACCEPT ", buflen);
35549887Snsayer
35649887Snsayer	common:
35749887Snsayer		BUMP(buf, buflen);
35849887Snsayer		if (cnt <= 4)
35949887Snsayer			break;
36049887Snsayer		ADDC(buf, buflen, '"');
36149887Snsayer		for (i = 4; i < cnt; i++)
36249887Snsayer			ADDC(buf, buflen, data[i]);
36349887Snsayer		ADDC(buf, buflen, '"');
36449887Snsayer		ADDC(buf, buflen, '\0');
36549887Snsayer		break;
36649887Snsayer
36749887Snsayer	case SRA_KEY:			/* Authentication data follows */
36849887Snsayer		strncpy((char *)buf, " KEY ", buflen);
36949887Snsayer		goto common2;
37049887Snsayer
37149887Snsayer	case SRA_USER:
37249887Snsayer		strncpy((char *)buf, " USER ", buflen);
37349887Snsayer		goto common2;
37449887Snsayer
37549887Snsayer	case SRA_PASS:
37649887Snsayer		strncpy((char *)buf, " PASS ", buflen);
37749887Snsayer		goto common2;
37849887Snsayer
37949887Snsayer	default:
38049887Snsayer		sprintf(lbuf, " %d (unknown)", data[3]);
38149887Snsayer		strncpy((char *)buf, lbuf, buflen);
38249887Snsayer	common2:
38349887Snsayer		BUMP(buf, buflen);
38449887Snsayer		for (i = 4; i < cnt; i++) {
38549887Snsayer			sprintf(lbuf, " %d", data[i]);
38649887Snsayer			strncpy((char *)buf, lbuf, buflen);
38749887Snsayer			BUMP(buf, buflen);
38849887Snsayer		}
38949887Snsayer		break;
39049887Snsayer	}
39149887Snsayer}
39249887Snsayer
39349887Snsayerstruct	passwd *pw;
39449887Snsayer
39549887Snsayer/*
39649887Snsayer * Helper function for sgetpwnam().
39749887Snsayer */
39849887Snsayerchar *
39949887Snsayersgetsave(s)
40049887Snsayer	char *s;
40149887Snsayer{
40249887Snsayer	char *new = malloc((unsigned) strlen(s) + 1);
40349887Snsayer
40449887Snsayer	if (new == NULL) {
40549887Snsayer		return(NULL);
40649887Snsayer	}
40749887Snsayer	(void) strcpy(new, s);
40849887Snsayer	return (new);
40949887Snsayer}
41049887Snsayer
41149887Snsayer#include <pwd.h>
41249887Snsayer#include <syslog.h>
41349887Snsayer#ifdef USE_SHADOW
41449887Snsayer#include <shadow.h>
41549887Snsayer#endif
41649887Snsayer
41749887Snsayer
41849887Snsayerstruct passwd *
41949887Snsayersgetpwnam(name)
42049887Snsayer	char *name;
42149887Snsayer{
42249887Snsayer	static struct passwd save;
42349887Snsayer	register struct passwd *p;
42449887Snsayer	char *sgetsave();
42549887Snsayer
42649887Snsayer	if ((p = getpwnam(name)) == NULL)
42749887Snsayer		return (p);
42849887Snsayer	if (save.pw_name) {
42949887Snsayer		free(save.pw_name);
43049887Snsayer		free(save.pw_passwd);
43149887Snsayer		free(save.pw_gecos);
43249887Snsayer		free(save.pw_dir);
43349887Snsayer		free(save.pw_shell);
43449887Snsayer	}
43549887Snsayer	save = *p;
43649887Snsayer	save.pw_name = sgetsave(p->pw_name);
43749887Snsayer	save.pw_passwd = sgetsave(p->pw_passwd);
43849887Snsayer	save.pw_gecos = sgetsave(p->pw_gecos);
43949887Snsayer	save.pw_dir = sgetsave(p->pw_dir);
44049887Snsayer	save.pw_shell = sgetsave(p->pw_shell);
44149887Snsayer#if 0
44249887Snsayersyslog(LOG_WARNING,"%s\n",save.pw_name);
44349887Snsayersyslog(LOG_WARNING,"%s\n",save.pw_passwd);
44449887Snsayersyslog(LOG_WARNING,"%s\n",save.pw_gecos);
44549887Snsayersyslog(LOG_WARNING,"%s\n",save.pw_dir);
44649887Snsayer#endif
44749887Snsayer#ifdef USE_SHADOW
44849887Snsayer        {
44949887Snsayer                struct spwd *sp;
45049887Snsayer                sp = getspnam(name);
45149887Snsayer                free(save.pw_passwd);
45249887Snsayer                save.pw_passwd  = sgetsave(sp->sp_pwdp);
45349887Snsayer        }
45449887Snsayer#endif
45549887Snsayer	return (&save);
45649887Snsayer}
45749887Snsayer
45876610Snsayerstatic int
45976610Snsayerisroot(user)
46076610Snsayerchar *user;
46176610Snsayer{
46276610Snsayer	struct passwd *pw;
46376610Snsayer
46476610Snsayer	if ((pw=getpwnam(user))==NULL)
46576610Snsayer		return 0;
46676610Snsayer	return (!pw->pw_uid);
46776610Snsayer}
46876610Snsayer
46976610Snsayerstatic int
47076610Snsayerrootterm(ttyn)
47176610Snsayerchar *ttyn;
47276610Snsayer{
47376610Snsayer	struct ttyent *t;
47476610Snsayer
47576610Snsayer	return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE);
47676610Snsayer}
47776610Snsayer
47876339Snsayer#ifdef NOPAM
47949887Snsayerchar *crypt();
48049887Snsayer
48149887Snsayerint check_user(name, pass)
48249887Snsayerchar *name;
48349887Snsayerchar *pass;
48449887Snsayer{
48549887Snsayer	register char *cp;
48649887Snsayer	char *xpasswd, *salt;
48749887Snsayer
48876610Snsayer	if (isroot(name) && !rootterm(line))
48976610Snsayer	{
49076610Snsayer		crypt("AA","*"); /* Waste some time to simulate success */
49176610Snsayer		return(0);
49276610Snsayer	}
49376610Snsayer
49449887Snsayer	if (pw = sgetpwnam(name)) {
49549887Snsayer		if (pw->pw_shell == NULL) {
49649887Snsayer			pw = (struct passwd *) NULL;
49749887Snsayer			return(0);
49849887Snsayer		}
49949887Snsayer
50049887Snsayer		salt = pw->pw_passwd;
50149887Snsayer		xpasswd = crypt(pass, salt);
50249887Snsayer		/* The strcmp does not catch null passwords! */
50349887Snsayer		if (pw == NULL || *pw->pw_passwd == '\0' ||
50449887Snsayer			strcmp(xpasswd, pw->pw_passwd)) {
50549887Snsayer			pw = (struct passwd *) NULL;
50649887Snsayer			return(0);
50749887Snsayer		}
50849887Snsayer		return(1);
50949887Snsayer	}
51049887Snsayer	return(0);
51149887Snsayer}
51276339Snsayer#else
51349887Snsayer
51476339Snsayer/*
51576339Snsayer * The following is stolen from ftpd, which stole it from the imap-uw
51676339Snsayer * PAM module and login.c. It is needed because we can't really
51776339Snsayer * "converse" with the user, having already gone to the trouble of
51876339Snsayer * getting their username and password through an encrypted channel.
51976339Snsayer */
52049887Snsayer
52176339Snsayer#define COPY_STRING(s) (s ? strdup(s):NULL)
52276339Snsayer
52376339Snsayerstruct cred_t {
52476339Snsayer	const char *uname;
52576339Snsayer	const char *pass;
52676339Snsayer};
52776339Snsayertypedef struct cred_t cred_t;
52876339Snsayer
52976339Snsayerauth_conv(int num_msg, const struct pam_message **msg,
53076339Snsayer	struct pam_response **resp, void *appdata)
53176339Snsayer{
53276339Snsayer	int i;
53376339Snsayer	cred_t *cred = (cred_t *) appdata;
53476339Snsayer	struct pam_response *reply =
53576339Snsayer		malloc(sizeof(struct pam_response) * num_msg);
53676339Snsayer
53776339Snsayer	for (i = 0; i < num_msg; i++) {
53876339Snsayer		switch (msg[i]->msg_style) {
53976339Snsayer		case PAM_PROMPT_ECHO_ON:        /* assume want user name */
54076339Snsayer			reply[i].resp_retcode = PAM_SUCCESS;
54176339Snsayer			reply[i].resp = COPY_STRING(cred->uname);
54276339Snsayer			/* PAM frees resp. */
54376339Snsayer			break;
54476339Snsayer		case PAM_PROMPT_ECHO_OFF:       /* assume want password */
54576339Snsayer			reply[i].resp_retcode = PAM_SUCCESS;
54676339Snsayer			reply[i].resp = COPY_STRING(cred->pass);
54776339Snsayer			/* PAM frees resp. */
54876339Snsayer			break;
54976339Snsayer		case PAM_TEXT_INFO:
55076339Snsayer		case PAM_ERROR_MSG:
55176339Snsayer			reply[i].resp_retcode = PAM_SUCCESS;
55276339Snsayer			reply[i].resp = NULL;
55376339Snsayer			break;
55476339Snsayer		default:                        /* unknown message style */
55576339Snsayer			free(reply);
55676339Snsayer			return PAM_CONV_ERR;
55776339Snsayer		}
55876339Snsayer	}
55976339Snsayer
56076339Snsayer	*resp = reply;
56176339Snsayer	return PAM_SUCCESS;
56276339Snsayer}
56376339Snsayer
56476339Snsayer/*
56576339Snsayer * The PAM version as a side effect may put a new username in *user.
56676339Snsayer */
56776339Snsayerint check_user(const char *name, const char *pass)
56876339Snsayer{
56976339Snsayer	pam_handle_t *pamh = NULL;
57076339Snsayer	const char *tmpl_user;
57176339Snsayer	const void *item;
57276339Snsayer	int rval;
57376339Snsayer	int e;
57476339Snsayer	cred_t auth_cred = { name, pass };
57576339Snsayer	struct pam_conv conv = { &auth_conv, &auth_cred };
57676339Snsayer
57776339Snsayer	e = pam_start("telnetd", name, &conv, &pamh);
57876339Snsayer	if (e != PAM_SUCCESS) {
57976339Snsayer		syslog(LOG_ERR, "pam_start: %s", pam_strerror(pamh, e));
58076339Snsayer		return 0;
58176339Snsayer	}
58276339Snsayer
58376339Snsayer#if 0 /* Where can we find this value? */
58476339Snsayer	e = pam_set_item(pamh, PAM_RHOST, remotehost);
58576339Snsayer	if (e != PAM_SUCCESS) {
58676339Snsayer		syslog(LOG_ERR, "pam_set_item(PAM_RHOST): %s",
58776339Snsayer			pam_strerror(pamh, e));
58876339Snsayer		return 0;
58976339Snsayer	}
59049887Snsayer#endif
59149887Snsayer
59276339Snsayer	e = pam_authenticate(pamh, 0);
59376339Snsayer	switch (e) {
59476339Snsayer	case PAM_SUCCESS:
59576339Snsayer		/*
59676339Snsayer		 * With PAM we support the concept of a "template"
59776339Snsayer		 * user.  The user enters a login name which is
59876339Snsayer		 * authenticated by PAM, usually via a remote service
59976339Snsayer		 * such as RADIUS or TACACS+.  If authentication
60076339Snsayer		 * succeeds, a different but related "template" name
60176339Snsayer		 * is used for setting the credentials, shell, and
60276339Snsayer		 * home directory.  The name the user enters need only
60376339Snsayer		 * exist on the remote authentication server, but the
60476339Snsayer		 * template name must be present in the local password
60576339Snsayer		 * database.
60676339Snsayer		 *
60776339Snsayer		 * This is supported by two various mechanisms in the
60876339Snsayer		 * individual modules.  However, from the application's
60976339Snsayer		 * point of view, the template user is always passed
61076339Snsayer		 * back as a changed value of the PAM_USER item.
61176339Snsayer		 */
61276339Snsayer		if ((e = pam_get_item(pamh, PAM_USER, &item)) ==
61376339Snsayer		    PAM_SUCCESS) {
61476339Snsayer			strcpy(user, (const char *) item);
61576339Snsayer		} else
61676339Snsayer			syslog(LOG_ERR, "Couldn't get PAM_USER: %s",
61776339Snsayer			pam_strerror(pamh, e));
61876610Snsayer		if (isroot(user) && !rootterm(line))
61976610Snsayer			rval = 0;
62076610Snsayer		else
62176610Snsayer			rval = 1;
62276339Snsayer		break;
62376339Snsayer
62476339Snsayer	case PAM_AUTH_ERR:
62576339Snsayer	case PAM_USER_UNKNOWN:
62676339Snsayer	case PAM_MAXTRIES:
62776339Snsayer		rval = 0;
62876339Snsayer	break;
62976339Snsayer
63076339Snsayer	default:
63176339Snsayer		syslog(LOG_ERR, "auth_pam: %s", pam_strerror(pamh, e));
63276339Snsayer		rval = 0;
63376339Snsayer		break;
63476339Snsayer	}
63576339Snsayer
63676339Snsayer	if ((e = pam_end(pamh, e)) != PAM_SUCCESS) {
63776339Snsayer		syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e));
63876339Snsayer		rval = 0;
63976339Snsayer	}
64076339Snsayer	return rval;
64176339Snsayer}
64276339Snsayer
64376339Snsayer#endif
64476339Snsayer
64576339Snsayer#endif
64676339Snsayer
647