sra.c revision 228559
1170613Sbms/*-
2189592Sbms * Copyright (c) 1991, 1993
3170613Sbms *      Dave Safford.  All rights reserved.
4170613Sbms *
5170613Sbms * Redistribution and use in source and binary forms, with or without
6170613Sbms * modification, are permitted provided that the following conditions
7170613Sbms * are met:
8170613Sbms * 1. Redistributions of source code must retain the above copyright
9170613Sbms *    notice, this list of conditions and the following disclaimer.
10170613Sbms * 2. Redistributions in binary form must reproduce the above copyright
11170613Sbms *    notice, this list of conditions and the following disclaimer in the
12170613Sbms *    documentation and/or other materials provided with the distribution.
13170613Sbms * 3. Neither the name of the University nor the names of its contributors
14170613Sbms *    may be used to endorse or promote products derived from this software
15170613Sbms *    without specific prior written permission.
16170613Sbms *
17170613Sbms * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18170613Sbms * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19170613Sbms * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20170613Sbms * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21170613Sbms * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22170613Sbms * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23170613Sbms * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24170613Sbms * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25170613Sbms * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26170613Sbms * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27170613Sbms * SUCH DAMAGE.
28170613Sbms *
29170613Sbms */
30170613Sbms
31170613Sbms#include <sys/cdefs.h>
32170613Sbms
33170613Sbms__FBSDID("$FreeBSD: head/contrib/telnet/libtelnet/sra.c 228559 2011-12-16 00:48:53Z dim $");
34170613Sbms
35170613Sbms#ifdef	SRA
36170613Sbms#ifdef	ENCRYPTION
37170613Sbms#include <sys/types.h>
38189106Sbz#include <arpa/telnet.h>
39189106Sbz#include <pwd.h>
40170613Sbms#include <stdio.h>
41170613Sbms#include <stdlib.h>
42170613Sbms#include <string.h>
43170613Sbms#include <syslog.h>
44170613Sbms#include <ttyent.h>
45171746Scsjp
46170613Sbms#ifndef NOPAM
47170613Sbms#include <security/pam_appl.h>
48189592Sbms#else
49170613Sbms#include <unistd.h>
50181803Sbz#endif
51189592Sbms
52189592Sbms#include "auth.h"
53170613Sbms#include "misc.h"
54170613Sbms#include "encrypt.h"
55170613Sbms#include "pk.h"
56170613Sbms
57185571Sbzchar pka[HEXKEYBYTES+1], ska[HEXKEYBYTES+1], pkb[HEXKEYBYTES+1];
58170613Sbmschar *user, *pass, *xuser, *xpass;
59170613SbmsDesData ck;
60170613SbmsIdeaData ik;
61170613Sbms
62170613Sbmsextern int auth_debug_mode;
63170613Sbmsextern char line[];
64170613Sbms
65185571Sbzstatic int sra_valid = 0;
66170613Sbmsstatic int passwd_sent = 0;
67189592Sbms
68191659Sbmsstatic unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
69189592Sbms			  		AUTHTYPE_SRA, };
70189592Sbms
71170613Sbms#define SRA_KEY	0
72170613Sbms#define SRA_USER 1
73170613Sbms#define SRA_CONTINUE 2
74170613Sbms#define SRA_PASS 3
75170613Sbms#define SRA_ACCEPT 4
76170613Sbms#define SRA_REJECT 5
77170613Sbms
78170613Sbmsstatic int check_user(char *, char *);
79170613Sbms
80170613Sbms/* support routine to send out authentication message */
81170613Sbmsstatic int
82189592SbmsData(Authenticator *ap, int type, void *d, int c)
83189592Sbms{
84170613Sbms        unsigned char *p = str_data + 4;
85170613Sbms	unsigned char *cd = (unsigned char *)d;
86189592Sbms
87189592Sbms	if (c == -1)
88170613Sbms		c = strlen((char *)cd);
89189592Sbms
90189592Sbms        if (auth_debug_mode) {
91189592Sbms                printf("%s:%d: [%d] (%d)",
92189592Sbms                        str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
93170613Sbms                        str_data[3],
94189592Sbms                        type, c);
95189592Sbms                printd(d, c);
96189592Sbms                printf("\r\n");
97189592Sbms        }
98189592Sbms	*p++ = ap->type;
99189592Sbms	*p++ = ap->way;
100189592Sbms	*p++ = type;
101189592Sbms        while (c-- > 0) {
102189592Sbms                if ((*p++ = *cd++) == IAC)
103170613Sbms                        *p++ = IAC;
104170613Sbms        }
105189592Sbms        *p++ = IAC;
106170613Sbms        *p++ = SE;
107170613Sbms	if (str_data[3] == TELQUAL_IS)
108170613Sbms		printsub('>', &str_data[2], p - (&str_data[2]));
109170613Sbms        return(net_write(str_data, p - str_data));
110189592Sbms}
111170613Sbms
112170613Sbmsint
113189592Sbmssra_init(Authenticator *ap __unused, int server)
114189592Sbms{
115189592Sbms	if (server)
116189592Sbms		str_data[3] = TELQUAL_REPLY;
117170613Sbms	else
118170613Sbms		str_data[3] = TELQUAL_IS;
119170613Sbms
120170613Sbms	user = (char *)malloc(256);
121189592Sbms	xuser = (char *)malloc(513);
122189592Sbms	pass = (char *)malloc(256);
123189592Sbms	xpass = (char *)malloc(513);
124170613Sbms
125189592Sbms	if (user == NULL || xuser == NULL || pass == NULL || xpass ==
126189592Sbms	NULL)
127189592Sbms		return 0; /* malloc failed */
128189592Sbms
129189592Sbms	passwd_sent = 0;
130189592Sbms
131189592Sbms	genkeys(pka,ska);
132189592Sbms	return(1);
133189592Sbms}
134189592Sbms
135189592Sbms/* client received a go-ahead for sra */
136189592Sbmsint
137170613Sbmssra_send(Authenticator *ap)
138189592Sbms{
139189592Sbms	/* send PKA */
140189592Sbms
141189592Sbms	if (auth_debug_mode)
142189592Sbms		printf("Sent PKA to server.\r\n" );
143189592Sbms	printf("Trying SRA secure login:\r\n");
144189592Sbms	if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) {
145189592Sbms		if (auth_debug_mode)
146189592Sbms			printf("Not enough room for authentication data\r\n");
147189592Sbms		return(0);
148189592Sbms	}
149189592Sbms
150189592Sbms	return(1);
151189592Sbms}
152189592Sbms
153170613Sbms/* server received an IS -- could be SRA KEY, USER, or PASS */
154170613Sbmsvoid
155170613Sbmssra_is(Authenticator *ap, unsigned char *data, int cnt)
156170613Sbms{
157170613Sbms	int valid;
158189592Sbms	Session_Key skey;
159189592Sbms
160189592Sbms	if (cnt-- < 1)
161189592Sbms		goto bad;
162170613Sbms	switch (*data++) {
163170613Sbms
164189592Sbms	case SRA_KEY:
165170613Sbms		if (cnt < HEXKEYBYTES) {
166189357Sbms			Data(ap, SRA_REJECT, (void *)0, 0);
167189357Sbms			auth_finished(ap, AUTH_USER);
168189592Sbms			if (auth_debug_mode) {
169189592Sbms				printf("SRA user rejected for bad PKB\r\n");
170189592Sbms			}
171189592Sbms			return;
172189592Sbms		}
173189592Sbms		if (auth_debug_mode)
174189592Sbms			printf("Sent pka\r\n");
175189592Sbms		if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) {
176189592Sbms			if (auth_debug_mode)
177189592Sbms				printf("Not enough room\r\n");
178189592Sbms			return;
179189592Sbms		}
180189357Sbms		memcpy(pkb,data,HEXKEYBYTES);
181189357Sbms		pkb[HEXKEYBYTES] = '\0';
182189357Sbms		common_key(ska,pkb,&ik,&ck);
183189357Sbms		return;
184189357Sbms
185189592Sbms	case SRA_USER:
186189592Sbms		/* decode KAB(u) */
187189592Sbms		if (cnt > 512) /* Attempted buffer overflow */
188189592Sbms			break;
189170613Sbms		memcpy(xuser,data,cnt);
190189592Sbms		xuser[cnt] = '\0';
191189592Sbms		pk_decode(xuser,user,&ck);
192189592Sbms		auth_encrypt_user(user);
193189592Sbms		Data(ap, SRA_CONTINUE, (void *)0, 0);
194189592Sbms
195189592Sbms		return;
196189592Sbms
197189592Sbms	case SRA_PASS:
198189592Sbms		if (cnt > 512) /* Attempted buffer overflow */
199189592Sbms			break;
200189592Sbms		/* decode KAB(P) */
201189592Sbms		memcpy(xpass,data,cnt);
202189592Sbms		xpass[cnt] = '\0';
203189592Sbms		pk_decode(xpass,pass,&ck);
204189592Sbms
205189592Sbms		/* check user's password */
206189592Sbms		valid = check_user(user,pass);
207189592Sbms
208189592Sbms		if(valid) {
209189592Sbms			Data(ap, SRA_ACCEPT, (void *)0, 0);
210189592Sbms			skey.data = ck;
211189592Sbms			skey.type = SK_DES;
212189592Sbms			skey.length = 8;
213189592Sbms			encrypt_session_key(&skey, 1);
214189592Sbms
215189592Sbms			sra_valid = 1;
216189592Sbms			auth_finished(ap, AUTH_VALID);
217189592Sbms			if (auth_debug_mode) {
218189592Sbms				printf("SRA user accepted\r\n");
219189592Sbms			}
220189592Sbms		}
221189592Sbms		else {
222189592Sbms			Data(ap, SRA_CONTINUE, (void *)0, 0);
223189592Sbms/*
224189592Sbms			Data(ap, SRA_REJECT, (void *)0, 0);
225189592Sbms			sra_valid = 0;
226170613Sbms			auth_finished(ap, AUTH_REJECT);
227170613Sbms*/
228170613Sbms			if (auth_debug_mode) {
229170613Sbms				printf("SRA user failed\r\n");
230170613Sbms			}
231170613Sbms		}
232170613Sbms		return;
233170613Sbms
234170613Sbms	default:
235170613Sbms		if (auth_debug_mode)
236170613Sbms			printf("Unknown SRA option %d\r\n", data[-1]);
237170613Sbms	}
238170613Sbmsbad:
239170613Sbms	Data(ap, SRA_REJECT, 0, 0);
240170613Sbms	sra_valid = 0;
241170613Sbms	auth_finished(ap, AUTH_REJECT);
242170613Sbms}
243170613Sbms
244170613Sbms/* client received REPLY -- could be SRA KEY, CONTINUE, ACCEPT, or REJECT */
245170613Sbmsvoid
246170613Sbmssra_reply(Authenticator *ap, unsigned char *data, int cnt)
247170613Sbms{
248170613Sbms	char uprompt[256],tuser[256];
249170613Sbms	Session_Key skey;
250170613Sbms	size_t i;
251189592Sbms
252170613Sbms	if (cnt-- < 1)
253170613Sbms		return;
254170613Sbms	switch (*data++) {
255189592Sbms
256189592Sbms	case SRA_KEY:
257170613Sbms		/* calculate common key */
258170613Sbms		if (cnt < HEXKEYBYTES) {
259170613Sbms			if (auth_debug_mode) {
260170613Sbms				printf("SRA user rejected for bad PKB\r\n");
261170613Sbms			}
262170613Sbms			return;
263170613Sbms		}
264170613Sbms		memcpy(pkb,data,HEXKEYBYTES);
265170613Sbms		pkb[HEXKEYBYTES] = '\0';
266170613Sbms
267170613Sbms		common_key(ska,pkb,&ik,&ck);
268189592Sbms
269170613Sbms	enc_user:
270170613Sbms
271170613Sbms		/* encode user */
272170613Sbms		memset(tuser,0,sizeof(tuser));
273170613Sbms		sprintf(uprompt,"User (%s): ",UserNameRequested);
274170613Sbms		telnet_gets(uprompt,tuser,255,1);
275170613Sbms		if (tuser[0] == '\n' || tuser[0] == '\r' )
276170613Sbms			strcpy(user,UserNameRequested);
277170613Sbms		else {
278170613Sbms			/* telnet_gets leaves the newline on */
279170613Sbms			for(i=0;i<sizeof(tuser);i++) {
280189592Sbms				if (tuser[i] == '\n') {
281189592Sbms					tuser[i] = '\0';
282189592Sbms					break;
283170613Sbms				}
284189592Sbms			}
285170613Sbms			strcpy(user,tuser);
286170613Sbms		}
287170613Sbms		pk_encode(user,xuser,&ck);
288170613Sbms
289189592Sbms		/* send it off */
290170613Sbms		if (auth_debug_mode)
291170613Sbms			printf("Sent KAB(U)\r\n");
292170613Sbms		if (!Data(ap, SRA_USER, (void *)xuser, strlen(xuser))) {
293170613Sbms			if (auth_debug_mode)
294170613Sbms				printf("Not enough room\r\n");
295170613Sbms			return;
296170613Sbms		}
297170613Sbms		break;
298170613Sbms
299170613Sbms	case SRA_CONTINUE:
300170613Sbms		if (passwd_sent) {
301189592Sbms			passwd_sent = 0;
302170613Sbms			printf("[ SRA login failed ]\r\n");
303170613Sbms			goto enc_user;
304170613Sbms		}
305170613Sbms		/* encode password */
306170613Sbms		memset(pass,0,256);
307170613Sbms		telnet_gets("Password: ",pass,255,0);
308170613Sbms		pk_encode(pass,xpass,&ck);
309170613Sbms		/* send it off */
310170613Sbms		if (auth_debug_mode)
311170613Sbms			printf("Sent KAB(P)\r\n");
312189592Sbms		if (!Data(ap, SRA_PASS, (void *)xpass, strlen(xpass))) {
313170613Sbms			if (auth_debug_mode)
314189592Sbms				printf("Not enough room\r\n");
315189592Sbms			return;
316189592Sbms		}
317170613Sbms		passwd_sent = 1;
318189592Sbms		break;
319189592Sbms
320189592Sbms	case SRA_REJECT:
321170613Sbms		printf("[ SRA refuses authentication ]\r\n");
322189592Sbms		printf("Trying plaintext login:\r\n");
323170613Sbms		auth_finished(0,AUTH_REJECT);
324189592Sbms		return;
325189592Sbms
326170613Sbms	case SRA_ACCEPT:
327170613Sbms		printf("[ SRA accepts you ]\r\n");
328170613Sbms		skey.data = ck;
329170613Sbms		skey.type = SK_DES;
330170613Sbms		skey.length = 8;
331170613Sbms		encrypt_session_key(&skey, 0);
332170613Sbms
333170613Sbms		auth_finished(ap, AUTH_VALID);
334170613Sbms		return;
335170613Sbms	default:
336189592Sbms		if (auth_debug_mode)
337189592Sbms			printf("Unknown SRA option %d\r\n", data[-1]);
338189592Sbms		return;
339189592Sbms	}
340189592Sbms}
341189592Sbms
342170613Sbmsint
343170613Sbmssra_status(Authenticator *ap __unused, char *name, int level)
344170613Sbms{
345189592Sbms	if (level < AUTH_USER)
346189592Sbms		return(level);
347189592Sbms	if (UserNameRequested && sra_valid) {
348189592Sbms		strcpy(name, UserNameRequested);
349170613Sbms		return(AUTH_VALID);
350189592Sbms	} else
351189592Sbms		return(AUTH_USER);
352189592Sbms}
353170613Sbms
354189592Sbms#define	BUMP(buf, len)		while (*(buf)) {++(buf), --(len);}
355189592Sbms#define	ADDC(buf, len, c)	if ((len) > 0) {*(buf)++ = (c); --(len);}
356189592Sbms
357189592Sbmsvoid
358189592Sbmssra_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
359189592Sbms{
360189592Sbms	char lbuf[32];
361189592Sbms	int i;
362189592Sbms
363189592Sbms	buf[buflen-1] = '\0';		/* make sure its NULL terminated */
364189592Sbms	buflen -= 1;
365189592Sbms
366189592Sbms	switch(data[3]) {
367189592Sbms
368189592Sbms	case SRA_CONTINUE:
369189592Sbms		strncpy((char *)buf, " CONTINUE ", buflen);
370189592Sbms		goto common;
371189592Sbms
372189592Sbms	case SRA_REJECT:		/* Rejected (reason might follow) */
373189592Sbms		strncpy((char *)buf, " REJECT ", buflen);
374189592Sbms		goto common;
375189592Sbms
376189592Sbms	case SRA_ACCEPT:		/* Accepted (name might follow) */
377189592Sbms		strncpy((char *)buf, " ACCEPT ", buflen);
378189592Sbms
379189592Sbms	common:
380189592Sbms		BUMP(buf, buflen);
381189592Sbms		if (cnt <= 4)
382189592Sbms			break;
383189592Sbms		ADDC(buf, buflen, '"');
384189592Sbms		for (i = 4; i < cnt; i++)
385189592Sbms			ADDC(buf, buflen, data[i]);
386189592Sbms		ADDC(buf, buflen, '"');
387189592Sbms		ADDC(buf, buflen, '\0');
388189592Sbms		break;
389189592Sbms
390189592Sbms	case SRA_KEY:			/* Authentication data follows */
391189592Sbms		strncpy((char *)buf, " KEY ", buflen);
392189592Sbms		goto common2;
393189592Sbms
394189592Sbms	case SRA_USER:
395189592Sbms		strncpy((char *)buf, " USER ", buflen);
396189592Sbms		goto common2;
397189592Sbms
398189592Sbms	case SRA_PASS:
399189592Sbms		strncpy((char *)buf, " PASS ", buflen);
400170613Sbms		goto common2;
401189592Sbms
402170613Sbms	default:
403189592Sbms		sprintf(lbuf, " %d (unknown)", data[3]);
404170613Sbms		strncpy((char *)buf, lbuf, buflen);
405189592Sbms	common2:
406170613Sbms		BUMP(buf, buflen);
407170613Sbms		for (i = 4; i < cnt; i++) {
408170613Sbms			sprintf(lbuf, " %d", data[i]);
409170613Sbms			strncpy((char *)buf, lbuf, buflen);
410170613Sbms			BUMP(buf, buflen);
411170613Sbms		}
412170613Sbms		break;
413170613Sbms	}
414189592Sbms}
415189592Sbms
416189592Sbmsstatic int
417170613Sbmsisroot(const char *usr)
418189592Sbms{
419189592Sbms	struct passwd *pwd;
420189592Sbms
421189592Sbms	if ((pwd=getpwnam(usr))==NULL)
422170613Sbms		return 0;
423189592Sbms	return (!pwd->pw_uid);
424189592Sbms}
425189592Sbms
426189592Sbmsstatic int
427189592Sbmsrootterm(char *ttyn)
428189592Sbms{
429189592Sbms	struct ttyent *t;
430189592Sbms
431189931Sbms	return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE);
432189931Sbms}
433189931Sbms
434189592Sbms#ifdef NOPAM
435189592Sbmsstatic int
436189592Sbmscheck_user(char *name, char *cred)
437189592Sbms{
438189592Sbms	char *cp;
439189592Sbms	char *xpasswd, *salt;
440189592Sbms
441189592Sbms	if (isroot(name) && !rootterm(line))
442189592Sbms	{
443170613Sbms		crypt("AA","*"); /* Waste some time to simulate success */
444189592Sbms		return(0);
445189592Sbms	}
446189592Sbms
447189592Sbms	if (pw = sgetpwnam(name)) {
448189592Sbms		if (pw->pw_shell == NULL) {
449189592Sbms			pw = (struct passwd *) NULL;
450189592Sbms			return(0);
451189592Sbms		}
452189592Sbms
453170613Sbms		salt = pw->pw_passwd;
454189592Sbms		xpasswd = crypt(cred, salt);
455189592Sbms		/* The strcmp does not catch null passwords! */
456189931Sbms		if (pw == NULL || *pw->pw_passwd == '\0' ||
457189592Sbms			strcmp(xpasswd, pw->pw_passwd)) {
458189592Sbms			pw = (struct passwd *) NULL;
459189592Sbms			return(0);
460189931Sbms		}
461189931Sbms		return(1);
462189592Sbms	}
463189592Sbms	return(0);
464189592Sbms}
465189592Sbms#else
466189592Sbms
467189592Sbms/*
468189592Sbms * The following is stolen from ftpd, which stole it from the imap-uw
469189592Sbms * PAM module and login.c. It is needed because we can't really
470189592Sbms * "converse" with the user, having already gone to the trouble of
471189592Sbms * getting their username and password through an encrypted channel.
472189931Sbms */
473189592Sbms
474189592Sbms#define COPY_STRING(s) (s ? strdup(s):NULL)
475189592Sbms
476189592Sbmsstruct cred_t {
477189592Sbms	const char *uname;
478189592Sbms	const char *pass;
479189592Sbms};
480189592Sbmstypedef struct cred_t cred_t;
481189592Sbms
482189592Sbmsstatic int
483189592Sbmsauth_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata)
484189592Sbms{
485189592Sbms	int i;
486189592Sbms	cred_t *cred = (cred_t *) appdata;
487189592Sbms	struct pam_response *reply =
488189592Sbms		malloc(sizeof(struct pam_response) * num_msg);
489189592Sbms
490189592Sbms	if (reply == NULL)
491189592Sbms		return PAM_BUF_ERR;
492189592Sbms
493189592Sbms	for (i = 0; i < num_msg; i++) {
494189592Sbms		switch (msg[i]->msg_style) {
495189931Sbms		case PAM_PROMPT_ECHO_ON:        /* assume want user name */
496189592Sbms			reply[i].resp_retcode = PAM_SUCCESS;
497189592Sbms			reply[i].resp = COPY_STRING(cred->uname);
498189592Sbms			/* PAM frees resp. */
499189592Sbms			break;
500189592Sbms		case PAM_PROMPT_ECHO_OFF:       /* assume want password */
501189592Sbms			reply[i].resp_retcode = PAM_SUCCESS;
502189592Sbms			reply[i].resp = COPY_STRING(cred->pass);
503189592Sbms			/* PAM frees resp. */
504189592Sbms			break;
505189592Sbms		case PAM_TEXT_INFO:
506189592Sbms		case PAM_ERROR_MSG:
507189592Sbms			reply[i].resp_retcode = PAM_SUCCESS;
508189592Sbms			reply[i].resp = NULL;
509189592Sbms			break;
510189592Sbms		default:                        /* unknown message style */
511189592Sbms			free(reply);
512189592Sbms			return PAM_CONV_ERR;
513189592Sbms		}
514189592Sbms	}
515189592Sbms
516189592Sbms	*resp = reply;
517189592Sbms	return PAM_SUCCESS;
518189592Sbms}
519189592Sbms
520189592Sbms/*
521189592Sbms * The PAM version as a side effect may put a new username in *name.
522189592Sbms */
523189592Sbmsstatic int
524189931Sbmscheck_user(char *name, char *cred)
525189592Sbms{
526189592Sbms	pam_handle_t *pamh = NULL;
527189592Sbms	const void *item;
528189592Sbms	int rval;
529189592Sbms	int e;
530189592Sbms	cred_t auth_cred = { name, cred };
531189592Sbms	struct pam_conv conv = { &auth_conv, &auth_cred };
532189592Sbms
533189592Sbms	e = pam_start("telnetd", name, &conv, &pamh);
534189592Sbms	if (e != PAM_SUCCESS) {
535189592Sbms		syslog(LOG_ERR, "pam_start: %s", pam_strerror(pamh, e));
536189592Sbms		return 0;
537189592Sbms	}
538189592Sbms
539189592Sbms#if 0 /* Where can we find this value? */
540189592Sbms	e = pam_set_item(pamh, PAM_RHOST, remotehost);
541189592Sbms	if (e != PAM_SUCCESS) {
542189592Sbms		syslog(LOG_ERR, "pam_set_item(PAM_RHOST): %s",
543189592Sbms			pam_strerror(pamh, e));
544189592Sbms		return 0;
545189592Sbms	}
546189592Sbms#endif
547189592Sbms
548189592Sbms	e = pam_authenticate(pamh, 0);
549189592Sbms	switch (e) {
550189592Sbms	case PAM_SUCCESS:
551189592Sbms		/*
552189592Sbms		 * With PAM we support the concept of a "template"
553170613Sbms		 * user.  The user enters a login name which is
554189592Sbms		 * authenticated by PAM, usually via a remote service
555189592Sbms		 * such as RADIUS or TACACS+.  If authentication
556189592Sbms		 * succeeds, a different but related "template" name
557189592Sbms		 * is used for setting the credentials, shell, and
558170613Sbms		 * home directory.  The name the user enters need only
559189592Sbms		 * exist on the remote authentication server, but the
560189592Sbms		 * template name must be present in the local password
561189592Sbms		 * database.
562189592Sbms		 *
563189592Sbms		 * This is supported by two various mechanisms in the
564189592Sbms		 * individual modules.  However, from the application's
565189592Sbms		 * point of view, the template user is always passed
566189592Sbms		 * back as a changed value of the PAM_USER item.
567189592Sbms		 */
568189592Sbms		if ((e = pam_get_item(pamh, PAM_USER, &item)) ==
569189592Sbms		    PAM_SUCCESS) {
570189592Sbms			strcpy(name, item);
571189592Sbms		} else
572189592Sbms			syslog(LOG_ERR, "Couldn't get PAM_USER: %s",
573189592Sbms			pam_strerror(pamh, e));
574189592Sbms		if (isroot(name) && !rootterm(line))
575189592Sbms			rval = 0;
576189592Sbms		else
577189592Sbms			rval = 1;
578189592Sbms		break;
579189592Sbms
580189592Sbms	case PAM_AUTH_ERR:
581189592Sbms	case PAM_USER_UNKNOWN:
582189592Sbms	case PAM_MAXTRIES:
583189592Sbms		rval = 0;
584189592Sbms	break;
585189592Sbms
586189592Sbms	default:
587189592Sbms		syslog(LOG_ERR, "auth_pam: %s", pam_strerror(pamh, e));
588189592Sbms		rval = 0;
589189592Sbms		break;
590189592Sbms	}
591189592Sbms
592189592Sbms	if ((e = pam_end(pamh, e)) != PAM_SUCCESS) {
593189592Sbms		syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e));
594189592Sbms		rval = 0;
595189592Sbms	}
596189592Sbms	return rval;
597189592Sbms}
598189592Sbms
599189592Sbms#endif
600189592Sbms
601189592Sbms#endif /* ENCRYPTION */
602189592Sbms#endif /* SRA */
603189592Sbms