185690Snsayer/*-
285690Snsayer * Copyright (c) 1991, 1993
385690Snsayer *      Dave Safford.  All rights reserved.
485690Snsayer *
585690Snsayer * Redistribution and use in source and binary forms, with or without
685690Snsayer * modification, are permitted provided that the following conditions
785690Snsayer * are met:
885690Snsayer * 1. Redistributions of source code must retain the above copyright
985690Snsayer *    notice, this list of conditions and the following disclaimer.
1085690Snsayer * 2. Redistributions in binary form must reproduce the above copyright
1185690Snsayer *    notice, this list of conditions and the following disclaimer in the
1285690Snsayer *    documentation and/or other materials provided with the distribution.
1385690Snsayer * 3. Neither the name of the University nor the names of its contributors
1485690Snsayer *    may be used to endorse or promote products derived from this software
1585690Snsayer *    without specific prior written permission.
1685690Snsayer *
1785690Snsayer * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1885690Snsayer * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1985690Snsayer * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2085690Snsayer * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2185690Snsayer * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2285690Snsayer * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2385690Snsayer * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2485690Snsayer * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2585690Snsayer * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2685690Snsayer * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2785690Snsayer * SUCH DAMAGE.
2885690Snsayer *
2985690Snsayer */
3085690Snsayer
3184305Smarkm#include <sys/cdefs.h>
3287139Smarkm
3384305Smarkm__FBSDID("$FreeBSD$");
3463248Speter
3549887Snsayer#ifdef	SRA
3687139Smarkm#ifdef	ENCRYPTION
3749887Snsayer#include <sys/types.h>
3849887Snsayer#include <arpa/telnet.h>
3987139Smarkm#include <pwd.h>
4049887Snsayer#include <stdio.h>
4149887Snsayer#include <stdlib.h>
4249887Snsayer#include <string.h>
4387139Smarkm#include <syslog.h>
4487139Smarkm#include <ttyent.h>
4549887Snsayer
4687139Smarkm#ifndef NOPAM
4776339Snsayer#include <security/pam_appl.h>
4881965Smarkm#else
4981965Smarkm#include <unistd.h>
5076339Snsayer#endif
5176339Snsayer
5249887Snsayer#include "auth.h"
5349887Snsayer#include "misc.h"
5449887Snsayer#include "encrypt.h"
5549887Snsayer#include "pk.h"
5649887Snsayer
5749887Snsayerchar pka[HEXKEYBYTES+1], ska[HEXKEYBYTES+1], pkb[HEXKEYBYTES+1];
5887139Smarkmchar *user, *pass, *xuser, *xpass;
5949887SnsayerDesData ck;
6049887SnsayerIdeaData ik;
6149887Snsayer
6249887Snsayerextern int auth_debug_mode;
6396108Smarkmextern char line[];
6476610Snsayer
6581965Smarkmstatic int sra_valid = 0;
6681965Smarkmstatic int passwd_sent = 0;
6749887Snsayer
6849887Snsayerstatic unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
6949887Snsayer			  		AUTHTYPE_SRA, };
7049887Snsayer
7149887Snsayer#define SRA_KEY	0
7249887Snsayer#define SRA_USER 1
7349887Snsayer#define SRA_CONTINUE 2
7449887Snsayer#define SRA_PASS 3
7549887Snsayer#define SRA_ACCEPT 4
7649887Snsayer#define SRA_REJECT 5
7749887Snsayer
7887139Smarkmstatic int check_user(char *, char *);
7981965Smarkm
8049887Snsayer/* support routine to send out authentication message */
8181965Smarkmstatic int
8281965SmarkmData(Authenticator *ap, int type, void *d, int c)
8349887Snsayer{
8449887Snsayer        unsigned char *p = str_data + 4;
8549887Snsayer	unsigned char *cd = (unsigned char *)d;
8649887Snsayer
8749887Snsayer	if (c == -1)
8849887Snsayer		c = strlen((char *)cd);
8949887Snsayer
9049887Snsayer        if (auth_debug_mode) {
9149887Snsayer                printf("%s:%d: [%d] (%d)",
9249887Snsayer                        str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
9349887Snsayer                        str_data[3],
9449887Snsayer                        type, c);
9549887Snsayer                printd(d, c);
9649887Snsayer                printf("\r\n");
9749887Snsayer        }
9849887Snsayer	*p++ = ap->type;
9949887Snsayer	*p++ = ap->way;
10049887Snsayer	*p++ = type;
10149887Snsayer        while (c-- > 0) {
10249887Snsayer                if ((*p++ = *cd++) == IAC)
10349887Snsayer                        *p++ = IAC;
10449887Snsayer        }
10549887Snsayer        *p++ = IAC;
10649887Snsayer        *p++ = SE;
10749887Snsayer	if (str_data[3] == TELQUAL_IS)
10849887Snsayer		printsub('>', &str_data[2], p - (&str_data[2]));
10949887Snsayer        return(net_write(str_data, p - str_data));
11049887Snsayer}
11149887Snsayer
11281965Smarkmint
11387139Smarkmsra_init(Authenticator *ap __unused, int server)
11449887Snsayer{
11549887Snsayer	if (server)
11649887Snsayer		str_data[3] = TELQUAL_REPLY;
11749887Snsayer	else
11849887Snsayer		str_data[3] = TELQUAL_IS;
11949887Snsayer
12049887Snsayer	user = (char *)malloc(256);
12176690Snsayer	xuser = (char *)malloc(513);
12249887Snsayer	pass = (char *)malloc(256);
12376690Snsayer	xpass = (char *)malloc(513);
12476689Snsayer
12576689Snsayer	if (user == NULL || xuser == NULL || pass == NULL || xpass ==
12676689Snsayer	NULL)
12776689Snsayer		return 0; /* malloc failed */
12876689Snsayer
12949887Snsayer	passwd_sent = 0;
13049887Snsayer
13149887Snsayer	genkeys(pka,ska);
13249887Snsayer	return(1);
13349887Snsayer}
13449887Snsayer
13549887Snsayer/* client received a go-ahead for sra */
13681965Smarkmint
13781965Smarkmsra_send(Authenticator *ap)
13849887Snsayer{
13949887Snsayer	/* send PKA */
14049887Snsayer
14149887Snsayer	if (auth_debug_mode)
14249887Snsayer		printf("Sent PKA to server.\r\n" );
14349887Snsayer	printf("Trying SRA secure login:\r\n");
14449887Snsayer	if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) {
14549887Snsayer		if (auth_debug_mode)
14649887Snsayer			printf("Not enough room for authentication data\r\n");
14749887Snsayer		return(0);
14849887Snsayer	}
14949887Snsayer
15049887Snsayer	return(1);
15149887Snsayer}
15249887Snsayer
15349887Snsayer/* server received an IS -- could be SRA KEY, USER, or PASS */
15481965Smarkmvoid
15581965Smarkmsra_is(Authenticator *ap, unsigned char *data, int cnt)
15649887Snsayer{
15749887Snsayer	int valid;
15849887Snsayer	Session_Key skey;
15949887Snsayer
16049887Snsayer	if (cnt-- < 1)
16176696Snsayer		goto bad;
16249887Snsayer	switch (*data++) {
16349887Snsayer
16449887Snsayer	case SRA_KEY:
16549887Snsayer		if (cnt < HEXKEYBYTES) {
16649887Snsayer			Data(ap, SRA_REJECT, (void *)0, 0);
16749887Snsayer			auth_finished(ap, AUTH_USER);
16849887Snsayer			if (auth_debug_mode) {
16949887Snsayer				printf("SRA user rejected for bad PKB\r\n");
17049887Snsayer			}
17149887Snsayer			return;
17249887Snsayer		}
17349887Snsayer		if (auth_debug_mode)
17449887Snsayer			printf("Sent pka\r\n");
17549887Snsayer		if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) {
17649887Snsayer			if (auth_debug_mode)
17749887Snsayer				printf("Not enough room\r\n");
17849887Snsayer			return;
17949887Snsayer		}
18049887Snsayer		memcpy(pkb,data,HEXKEYBYTES);
18149887Snsayer		pkb[HEXKEYBYTES] = '\0';
18249887Snsayer		common_key(ska,pkb,&ik,&ck);
18376696Snsayer		return;
18449887Snsayer
18549887Snsayer	case SRA_USER:
18649887Snsayer		/* decode KAB(u) */
18776690Snsayer		if (cnt > 512) /* Attempted buffer overflow */
18876690Snsayer			break;
18949887Snsayer		memcpy(xuser,data,cnt);
19049887Snsayer		xuser[cnt] = '\0';
19149887Snsayer		pk_decode(xuser,user,&ck);
19249887Snsayer		auth_encrypt_user(user);
19349887Snsayer		Data(ap, SRA_CONTINUE, (void *)0, 0);
19449887Snsayer
19576696Snsayer		return;
19649887Snsayer
19749887Snsayer	case SRA_PASS:
19876690Snsayer		if (cnt > 512) /* Attempted buffer overflow */
19976690Snsayer			break;
20049887Snsayer		/* decode KAB(P) */
20149887Snsayer		memcpy(xpass,data,cnt);
20249887Snsayer		xpass[cnt] = '\0';
20349887Snsayer		pk_decode(xpass,pass,&ck);
20449887Snsayer
20549887Snsayer		/* check user's password */
20649887Snsayer		valid = check_user(user,pass);
20749887Snsayer
20849887Snsayer		if(valid) {
20949887Snsayer			Data(ap, SRA_ACCEPT, (void *)0, 0);
21049887Snsayer			skey.data = ck;
21149887Snsayer			skey.type = SK_DES;
21249887Snsayer			skey.length = 8;
21349887Snsayer			encrypt_session_key(&skey, 1);
21449887Snsayer
21549887Snsayer			sra_valid = 1;
21649887Snsayer			auth_finished(ap, AUTH_VALID);
21749887Snsayer			if (auth_debug_mode) {
21849887Snsayer				printf("SRA user accepted\r\n");
21949887Snsayer			}
22049887Snsayer		}
22149887Snsayer		else {
22249887Snsayer			Data(ap, SRA_CONTINUE, (void *)0, 0);
22349887Snsayer/*
22449887Snsayer			Data(ap, SRA_REJECT, (void *)0, 0);
22549887Snsayer			sra_valid = 0;
22649887Snsayer			auth_finished(ap, AUTH_REJECT);
22749887Snsayer*/
22849887Snsayer			if (auth_debug_mode) {
22949887Snsayer				printf("SRA user failed\r\n");
23049887Snsayer			}
23149887Snsayer		}
23276696Snsayer		return;
23349887Snsayer
23449887Snsayer	default:
23549887Snsayer		if (auth_debug_mode)
23649887Snsayer			printf("Unknown SRA option %d\r\n", data[-1]);
23749887Snsayer	}
23876696Snsayerbad:
23976696Snsayer	Data(ap, SRA_REJECT, 0, 0);
24076696Snsayer	sra_valid = 0;
24176696Snsayer	auth_finished(ap, AUTH_REJECT);
24249887Snsayer}
24349887Snsayer
24449887Snsayer/* client received REPLY -- could be SRA KEY, CONTINUE, ACCEPT, or REJECT */
24581965Smarkmvoid
24681965Smarkmsra_reply(Authenticator *ap, unsigned char *data, int cnt)
24749887Snsayer{
24849887Snsayer	char uprompt[256],tuser[256];
24949887Snsayer	Session_Key skey;
25087139Smarkm	size_t i;
25149887Snsayer
25249887Snsayer	if (cnt-- < 1)
25349887Snsayer		return;
25449887Snsayer	switch (*data++) {
25549887Snsayer
25649887Snsayer	case SRA_KEY:
25749887Snsayer		/* calculate common key */
25849887Snsayer		if (cnt < HEXKEYBYTES) {
25949887Snsayer			if (auth_debug_mode) {
26049887Snsayer				printf("SRA user rejected for bad PKB\r\n");
26149887Snsayer			}
26249887Snsayer			return;
26349887Snsayer		}
26449887Snsayer		memcpy(pkb,data,HEXKEYBYTES);
26549887Snsayer		pkb[HEXKEYBYTES] = '\0';
26649887Snsayer
26749887Snsayer		common_key(ska,pkb,&ik,&ck);
26849887Snsayer
26949887Snsayer	enc_user:
27049887Snsayer
27149887Snsayer		/* encode user */
27249887Snsayer		memset(tuser,0,sizeof(tuser));
27349887Snsayer		sprintf(uprompt,"User (%s): ",UserNameRequested);
27449887Snsayer		telnet_gets(uprompt,tuser,255,1);
27549887Snsayer		if (tuser[0] == '\n' || tuser[0] == '\r' )
27649887Snsayer			strcpy(user,UserNameRequested);
27749887Snsayer		else {
27849887Snsayer			/* telnet_gets leaves the newline on */
27949887Snsayer			for(i=0;i<sizeof(tuser);i++) {
28049887Snsayer				if (tuser[i] == '\n') {
28149887Snsayer					tuser[i] = '\0';
28249887Snsayer					break;
28349887Snsayer				}
28449887Snsayer			}
28549887Snsayer			strcpy(user,tuser);
28649887Snsayer		}
28749887Snsayer		pk_encode(user,xuser,&ck);
28849887Snsayer
28949887Snsayer		/* send it off */
29049887Snsayer		if (auth_debug_mode)
29149887Snsayer			printf("Sent KAB(U)\r\n");
29249887Snsayer		if (!Data(ap, SRA_USER, (void *)xuser, strlen(xuser))) {
29349887Snsayer			if (auth_debug_mode)
29449887Snsayer				printf("Not enough room\r\n");
29549887Snsayer			return;
29649887Snsayer		}
29749887Snsayer		break;
29849887Snsayer
29949887Snsayer	case SRA_CONTINUE:
30049887Snsayer		if (passwd_sent) {
30149887Snsayer			passwd_sent = 0;
30249887Snsayer			printf("[ SRA login failed ]\r\n");
30349887Snsayer			goto enc_user;
30449887Snsayer		}
30549887Snsayer		/* encode password */
306228559Sdim		memset(pass,0,256);
30749887Snsayer		telnet_gets("Password: ",pass,255,0);
30849887Snsayer		pk_encode(pass,xpass,&ck);
30949887Snsayer		/* send it off */
31049887Snsayer		if (auth_debug_mode)
31149887Snsayer			printf("Sent KAB(P)\r\n");
31249887Snsayer		if (!Data(ap, SRA_PASS, (void *)xpass, strlen(xpass))) {
31349887Snsayer			if (auth_debug_mode)
31449887Snsayer				printf("Not enough room\r\n");
31549887Snsayer			return;
31649887Snsayer		}
31749887Snsayer		passwd_sent = 1;
31849887Snsayer		break;
31949887Snsayer
32049887Snsayer	case SRA_REJECT:
32149887Snsayer		printf("[ SRA refuses authentication ]\r\n");
32249887Snsayer		printf("Trying plaintext login:\r\n");
32349887Snsayer		auth_finished(0,AUTH_REJECT);
32449887Snsayer		return;
32549887Snsayer
32649887Snsayer	case SRA_ACCEPT:
32749887Snsayer		printf("[ SRA accepts you ]\r\n");
32849887Snsayer		skey.data = ck;
32949887Snsayer		skey.type = SK_DES;
33049887Snsayer		skey.length = 8;
33149887Snsayer		encrypt_session_key(&skey, 0);
33249887Snsayer
33349887Snsayer		auth_finished(ap, AUTH_VALID);
33449887Snsayer		return;
33549887Snsayer	default:
33649887Snsayer		if (auth_debug_mode)
33749887Snsayer			printf("Unknown SRA option %d\r\n", data[-1]);
33849887Snsayer		return;
33949887Snsayer	}
34049887Snsayer}
34149887Snsayer
34281965Smarkmint
34387139Smarkmsra_status(Authenticator *ap __unused, char *name, int level)
34449887Snsayer{
34549887Snsayer	if (level < AUTH_USER)
34649887Snsayer		return(level);
34749887Snsayer	if (UserNameRequested && sra_valid) {
34849887Snsayer		strcpy(name, UserNameRequested);
34949887Snsayer		return(AUTH_VALID);
35049887Snsayer	} else
35149887Snsayer		return(AUTH_USER);
35249887Snsayer}
35349887Snsayer
35449887Snsayer#define	BUMP(buf, len)		while (*(buf)) {++(buf), --(len);}
35549887Snsayer#define	ADDC(buf, len, c)	if ((len) > 0) {*(buf)++ = (c); --(len);}
35649887Snsayer
35781965Smarkmvoid
35881965Smarkmsra_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
35949887Snsayer{
36049887Snsayer	char lbuf[32];
36187139Smarkm	int i;
36249887Snsayer
36349887Snsayer	buf[buflen-1] = '\0';		/* make sure its NULL terminated */
36449887Snsayer	buflen -= 1;
36549887Snsayer
36649887Snsayer	switch(data[3]) {
36749887Snsayer
36849887Snsayer	case SRA_CONTINUE:
36949887Snsayer		strncpy((char *)buf, " CONTINUE ", buflen);
37049887Snsayer		goto common;
37149887Snsayer
37249887Snsayer	case SRA_REJECT:		/* Rejected (reason might follow) */
37349887Snsayer		strncpy((char *)buf, " REJECT ", buflen);
37449887Snsayer		goto common;
37549887Snsayer
37649887Snsayer	case SRA_ACCEPT:		/* Accepted (name might follow) */
37749887Snsayer		strncpy((char *)buf, " ACCEPT ", buflen);
37849887Snsayer
37949887Snsayer	common:
38049887Snsayer		BUMP(buf, buflen);
38149887Snsayer		if (cnt <= 4)
38249887Snsayer			break;
38349887Snsayer		ADDC(buf, buflen, '"');
38449887Snsayer		for (i = 4; i < cnt; i++)
38549887Snsayer			ADDC(buf, buflen, data[i]);
38649887Snsayer		ADDC(buf, buflen, '"');
38749887Snsayer		ADDC(buf, buflen, '\0');
38849887Snsayer		break;
38949887Snsayer
39049887Snsayer	case SRA_KEY:			/* Authentication data follows */
39149887Snsayer		strncpy((char *)buf, " KEY ", buflen);
39249887Snsayer		goto common2;
39349887Snsayer
39449887Snsayer	case SRA_USER:
39549887Snsayer		strncpy((char *)buf, " USER ", buflen);
39649887Snsayer		goto common2;
39749887Snsayer
39849887Snsayer	case SRA_PASS:
39949887Snsayer		strncpy((char *)buf, " PASS ", buflen);
40049887Snsayer		goto common2;
40149887Snsayer
40249887Snsayer	default:
40349887Snsayer		sprintf(lbuf, " %d (unknown)", data[3]);
40449887Snsayer		strncpy((char *)buf, lbuf, buflen);
40549887Snsayer	common2:
40649887Snsayer		BUMP(buf, buflen);
40749887Snsayer		for (i = 4; i < cnt; i++) {
40849887Snsayer			sprintf(lbuf, " %d", data[i]);
40949887Snsayer			strncpy((char *)buf, lbuf, buflen);
41049887Snsayer			BUMP(buf, buflen);
41149887Snsayer		}
41249887Snsayer		break;
41349887Snsayer	}
41449887Snsayer}
41549887Snsayer
41676610Snsayerstatic int
41787139Smarkmisroot(const char *usr)
41876610Snsayer{
41987139Smarkm	struct passwd *pwd;
42076610Snsayer
42187139Smarkm	if ((pwd=getpwnam(usr))==NULL)
42276610Snsayer		return 0;
42387139Smarkm	return (!pwd->pw_uid);
42476610Snsayer}
42576610Snsayer
42676610Snsayerstatic int
42781965Smarkmrootterm(char *ttyn)
42876610Snsayer{
42976610Snsayer	struct ttyent *t;
43076610Snsayer
43176610Snsayer	return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE);
43276610Snsayer}
43376610Snsayer
43476339Snsayer#ifdef NOPAM
43581965Smarkmstatic int
43687139Smarkmcheck_user(char *name, char *cred)
43749887Snsayer{
43887139Smarkm	char *cp;
43949887Snsayer	char *xpasswd, *salt;
44049887Snsayer
44176610Snsayer	if (isroot(name) && !rootterm(line))
44276610Snsayer	{
44376610Snsayer		crypt("AA","*"); /* Waste some time to simulate success */
44476610Snsayer		return(0);
44576610Snsayer	}
44676610Snsayer
44749887Snsayer	if (pw = sgetpwnam(name)) {
44849887Snsayer		if (pw->pw_shell == NULL) {
44949887Snsayer			pw = (struct passwd *) NULL;
45049887Snsayer			return(0);
45149887Snsayer		}
45249887Snsayer
45349887Snsayer		salt = pw->pw_passwd;
45487139Smarkm		xpasswd = crypt(cred, salt);
45549887Snsayer		/* The strcmp does not catch null passwords! */
45649887Snsayer		if (pw == NULL || *pw->pw_passwd == '\0' ||
45749887Snsayer			strcmp(xpasswd, pw->pw_passwd)) {
45849887Snsayer			pw = (struct passwd *) NULL;
45949887Snsayer			return(0);
46049887Snsayer		}
46149887Snsayer		return(1);
46249887Snsayer	}
46349887Snsayer	return(0);
46449887Snsayer}
46576339Snsayer#else
46649887Snsayer
46776339Snsayer/*
46876339Snsayer * The following is stolen from ftpd, which stole it from the imap-uw
46976339Snsayer * PAM module and login.c. It is needed because we can't really
47076339Snsayer * "converse" with the user, having already gone to the trouble of
47176339Snsayer * getting their username and password through an encrypted channel.
47276339Snsayer */
47349887Snsayer
47476339Snsayer#define COPY_STRING(s) (s ? strdup(s):NULL)
47576339Snsayer
47676339Snsayerstruct cred_t {
47776339Snsayer	const char *uname;
47876339Snsayer	const char *pass;
47976339Snsayer};
48076339Snsayertypedef struct cred_t cred_t;
48176339Snsayer
48287139Smarkmstatic int
48387139Smarkmauth_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata)
48476339Snsayer{
48576339Snsayer	int i;
48676339Snsayer	cred_t *cred = (cred_t *) appdata;
48776339Snsayer	struct pam_response *reply =
48876339Snsayer		malloc(sizeof(struct pam_response) * num_msg);
48976339Snsayer
49076689Snsayer	if (reply == NULL)
49176689Snsayer		return PAM_BUF_ERR;
49276689Snsayer
49376339Snsayer	for (i = 0; i < num_msg; i++) {
49476339Snsayer		switch (msg[i]->msg_style) {
49576339Snsayer		case PAM_PROMPT_ECHO_ON:        /* assume want user name */
49676339Snsayer			reply[i].resp_retcode = PAM_SUCCESS;
49776339Snsayer			reply[i].resp = COPY_STRING(cred->uname);
49876339Snsayer			/* PAM frees resp. */
49976339Snsayer			break;
50076339Snsayer		case PAM_PROMPT_ECHO_OFF:       /* assume want password */
50176339Snsayer			reply[i].resp_retcode = PAM_SUCCESS;
50276339Snsayer			reply[i].resp = COPY_STRING(cred->pass);
50376339Snsayer			/* PAM frees resp. */
50476339Snsayer			break;
50576339Snsayer		case PAM_TEXT_INFO:
50676339Snsayer		case PAM_ERROR_MSG:
50776339Snsayer			reply[i].resp_retcode = PAM_SUCCESS;
50876339Snsayer			reply[i].resp = NULL;
50976339Snsayer			break;
51076339Snsayer		default:                        /* unknown message style */
51176339Snsayer			free(reply);
51276339Snsayer			return PAM_CONV_ERR;
51376339Snsayer		}
51476339Snsayer	}
51576339Snsayer
51676339Snsayer	*resp = reply;
51776339Snsayer	return PAM_SUCCESS;
51876339Snsayer}
51976339Snsayer
52076339Snsayer/*
52176751Snsayer * The PAM version as a side effect may put a new username in *name.
52276339Snsayer */
52381965Smarkmstatic int
52487139Smarkmcheck_user(char *name, char *cred)
52576339Snsayer{
52676339Snsayer	pam_handle_t *pamh = NULL;
52776339Snsayer	const void *item;
52876339Snsayer	int rval;
52976339Snsayer	int e;
53087139Smarkm	cred_t auth_cred = { name, cred };
53176339Snsayer	struct pam_conv conv = { &auth_conv, &auth_cred };
53276339Snsayer
53376339Snsayer	e = pam_start("telnetd", name, &conv, &pamh);
53476339Snsayer	if (e != PAM_SUCCESS) {
53576339Snsayer		syslog(LOG_ERR, "pam_start: %s", pam_strerror(pamh, e));
53676339Snsayer		return 0;
53776339Snsayer	}
53876339Snsayer
53976339Snsayer#if 0 /* Where can we find this value? */
54076339Snsayer	e = pam_set_item(pamh, PAM_RHOST, remotehost);
54176339Snsayer	if (e != PAM_SUCCESS) {
54276339Snsayer		syslog(LOG_ERR, "pam_set_item(PAM_RHOST): %s",
54376339Snsayer			pam_strerror(pamh, e));
54476339Snsayer		return 0;
54576339Snsayer	}
54649887Snsayer#endif
54749887Snsayer
54876339Snsayer	e = pam_authenticate(pamh, 0);
54976339Snsayer	switch (e) {
55076339Snsayer	case PAM_SUCCESS:
55176339Snsayer		/*
55276339Snsayer		 * With PAM we support the concept of a "template"
55376339Snsayer		 * user.  The user enters a login name which is
55476339Snsayer		 * authenticated by PAM, usually via a remote service
55576339Snsayer		 * such as RADIUS or TACACS+.  If authentication
55676339Snsayer		 * succeeds, a different but related "template" name
55776339Snsayer		 * is used for setting the credentials, shell, and
55876339Snsayer		 * home directory.  The name the user enters need only
55976339Snsayer		 * exist on the remote authentication server, but the
56076339Snsayer		 * template name must be present in the local password
56176339Snsayer		 * database.
56276339Snsayer		 *
56376339Snsayer		 * This is supported by two various mechanisms in the
56476339Snsayer		 * individual modules.  However, from the application's
56576339Snsayer		 * point of view, the template user is always passed
56676339Snsayer		 * back as a changed value of the PAM_USER item.
56776339Snsayer		 */
56876339Snsayer		if ((e = pam_get_item(pamh, PAM_USER, &item)) ==
56976339Snsayer		    PAM_SUCCESS) {
57087139Smarkm			strcpy(name, item);
57176339Snsayer		} else
57276339Snsayer			syslog(LOG_ERR, "Couldn't get PAM_USER: %s",
57376339Snsayer			pam_strerror(pamh, e));
57476751Snsayer		if (isroot(name) && !rootterm(line))
57576610Snsayer			rval = 0;
57676610Snsayer		else
57776610Snsayer			rval = 1;
57876339Snsayer		break;
57976339Snsayer
58076339Snsayer	case PAM_AUTH_ERR:
58176339Snsayer	case PAM_USER_UNKNOWN:
58276339Snsayer	case PAM_MAXTRIES:
58376339Snsayer		rval = 0;
58476339Snsayer	break;
58576339Snsayer
58676339Snsayer	default:
58776339Snsayer		syslog(LOG_ERR, "auth_pam: %s", pam_strerror(pamh, e));
58876339Snsayer		rval = 0;
58976339Snsayer		break;
59076339Snsayer	}
59176339Snsayer
59276339Snsayer	if ((e = pam_end(pamh, e)) != PAM_SUCCESS) {
59376339Snsayer		syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e));
59476339Snsayer		rval = 0;
59576339Snsayer	}
59676339Snsayer	return rval;
59776339Snsayer}
59876339Snsayer
59976339Snsayer#endif
60076339Snsayer
60187139Smarkm#endif /* ENCRYPTION */
60287139Smarkm#endif /* SRA */
603