1/*-
2 * Copyright (c) 1991, 1993
3 *      Dave Safford.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 *    may be used to endorse or promote products derived from this software
15 *    without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 */
30
31#ifdef	SRA
32#ifdef	ENCRYPTION
33#include <sys/types.h>
34#include <arpa/telnet.h>
35#include <pwd.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <syslog.h>
40#include <ttyent.h>
41
42#ifndef NOPAM
43#include <security/pam_appl.h>
44#else
45#include <unistd.h>
46#endif
47
48#include "auth.h"
49#include "misc.h"
50#include "encrypt.h"
51#include "pk.h"
52
53char pka[HEXKEYBYTES+1], ska[HEXKEYBYTES+1], pkb[HEXKEYBYTES+1];
54char *user, *pass, *xuser, *xpass;
55DesData ck;
56IdeaData ik;
57
58extern int auth_debug_mode;
59extern char line[];
60
61static int sra_valid = 0;
62static int passwd_sent = 0;
63
64static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
65			  		AUTHTYPE_SRA, };
66
67#define SRA_KEY	0
68#define SRA_USER 1
69#define SRA_CONTINUE 2
70#define SRA_PASS 3
71#define SRA_ACCEPT 4
72#define SRA_REJECT 5
73
74static int check_user(char *, char *);
75
76/* support routine to send out authentication message */
77static int
78Data(Authenticator *ap, int type, void *d, int c)
79{
80        unsigned char *p = str_data + 4;
81	unsigned char *cd = (unsigned char *)d;
82
83	if (c == -1)
84		c = strlen((char *)cd);
85
86        if (auth_debug_mode) {
87                printf("%s:%d: [%d] (%d)",
88                        str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
89                        str_data[3],
90                        type, c);
91                printd(d, c);
92                printf("\r\n");
93        }
94	*p++ = ap->type;
95	*p++ = ap->way;
96	*p++ = type;
97        while (c-- > 0) {
98                if ((*p++ = *cd++) == IAC)
99                        *p++ = IAC;
100        }
101        *p++ = IAC;
102        *p++ = SE;
103	if (str_data[3] == TELQUAL_IS)
104		printsub('>', &str_data[2], p - (&str_data[2]));
105        return(net_write(str_data, p - str_data));
106}
107
108int
109sra_init(Authenticator *ap __unused, int server)
110{
111	if (server)
112		str_data[3] = TELQUAL_REPLY;
113	else
114		str_data[3] = TELQUAL_IS;
115
116	user = (char *)malloc(256);
117	xuser = (char *)malloc(513);
118	pass = (char *)malloc(256);
119	xpass = (char *)malloc(513);
120
121	if (user == NULL || xuser == NULL || pass == NULL || xpass ==
122	NULL)
123		return 0; /* malloc failed */
124
125	passwd_sent = 0;
126
127	genkeys(pka,ska);
128	return(1);
129}
130
131/* client received a go-ahead for sra */
132int
133sra_send(Authenticator *ap)
134{
135	/* send PKA */
136
137	if (auth_debug_mode)
138		printf("Sent PKA to server.\r\n" );
139	printf("Trying SRA secure login:\r\n");
140	if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) {
141		if (auth_debug_mode)
142			printf("Not enough room for authentication data\r\n");
143		return(0);
144	}
145
146	return(1);
147}
148
149/* server received an IS -- could be SRA KEY, USER, or PASS */
150void
151sra_is(Authenticator *ap, unsigned char *data, int cnt)
152{
153	int valid;
154	Session_Key skey;
155
156	if (cnt-- < 1)
157		goto bad;
158	switch (*data++) {
159
160	case SRA_KEY:
161		if (cnt < HEXKEYBYTES) {
162			Data(ap, SRA_REJECT, (void *)0, 0);
163			auth_finished(ap, AUTH_USER);
164			if (auth_debug_mode) {
165				printf("SRA user rejected for bad PKB\r\n");
166			}
167			return;
168		}
169		if (auth_debug_mode)
170			printf("Sent pka\r\n");
171		if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) {
172			if (auth_debug_mode)
173				printf("Not enough room\r\n");
174			return;
175		}
176		memcpy(pkb,data,HEXKEYBYTES);
177		pkb[HEXKEYBYTES] = '\0';
178		common_key(ska,pkb,&ik,&ck);
179		return;
180
181	case SRA_USER:
182		/* decode KAB(u) */
183		if (cnt > 512) /* Attempted buffer overflow */
184			break;
185		memcpy(xuser,data,cnt);
186		xuser[cnt] = '\0';
187		pk_decode(xuser,user,&ck);
188		auth_encrypt_user(user);
189		Data(ap, SRA_CONTINUE, (void *)0, 0);
190
191		return;
192
193	case SRA_PASS:
194		if (cnt > 512) /* Attempted buffer overflow */
195			break;
196		/* decode KAB(P) */
197		memcpy(xpass,data,cnt);
198		xpass[cnt] = '\0';
199		pk_decode(xpass,pass,&ck);
200
201		/* check user's password */
202		valid = check_user(user,pass);
203
204		if(valid) {
205			Data(ap, SRA_ACCEPT, (void *)0, 0);
206			skey.data = ck;
207			skey.type = SK_DES;
208			skey.length = 8;
209			encrypt_session_key(&skey, 1);
210
211			sra_valid = 1;
212			auth_finished(ap, AUTH_VALID);
213			if (auth_debug_mode) {
214				printf("SRA user accepted\r\n");
215			}
216		}
217		else {
218			Data(ap, SRA_CONTINUE, (void *)0, 0);
219/*
220			Data(ap, SRA_REJECT, (void *)0, 0);
221			sra_valid = 0;
222			auth_finished(ap, AUTH_REJECT);
223*/
224			if (auth_debug_mode) {
225				printf("SRA user failed\r\n");
226			}
227		}
228		return;
229
230	default:
231		if (auth_debug_mode)
232			printf("Unknown SRA option %d\r\n", data[-1]);
233	}
234bad:
235	Data(ap, SRA_REJECT, 0, 0);
236	sra_valid = 0;
237	auth_finished(ap, AUTH_REJECT);
238}
239
240/* client received REPLY -- could be SRA KEY, CONTINUE, ACCEPT, or REJECT */
241void
242sra_reply(Authenticator *ap, unsigned char *data, int cnt)
243{
244	char uprompt[256],tuser[256];
245	Session_Key skey;
246	size_t i;
247
248	if (cnt-- < 1)
249		return;
250	switch (*data++) {
251
252	case SRA_KEY:
253		/* calculate common key */
254		if (cnt < HEXKEYBYTES) {
255			if (auth_debug_mode) {
256				printf("SRA user rejected for bad PKB\r\n");
257			}
258			return;
259		}
260		memcpy(pkb,data,HEXKEYBYTES);
261		pkb[HEXKEYBYTES] = '\0';
262
263		common_key(ska,pkb,&ik,&ck);
264
265	enc_user:
266
267		/* encode user */
268		memset(tuser,0,sizeof(tuser));
269		sprintf(uprompt,"User (%s): ",UserNameRequested);
270		telnet_gets(uprompt,tuser,255,1);
271		if (tuser[0] == '\n' || tuser[0] == '\r' )
272			strcpy(user,UserNameRequested);
273		else {
274			/* telnet_gets leaves the newline on */
275			for(i=0;i<sizeof(tuser);i++) {
276				if (tuser[i] == '\n') {
277					tuser[i] = '\0';
278					break;
279				}
280			}
281			strcpy(user,tuser);
282		}
283		pk_encode(user,xuser,&ck);
284
285		/* send it off */
286		if (auth_debug_mode)
287			printf("Sent KAB(U)\r\n");
288		if (!Data(ap, SRA_USER, (void *)xuser, strlen(xuser))) {
289			if (auth_debug_mode)
290				printf("Not enough room\r\n");
291			return;
292		}
293		break;
294
295	case SRA_CONTINUE:
296		if (passwd_sent) {
297			passwd_sent = 0;
298			printf("[ SRA login failed ]\r\n");
299			goto enc_user;
300		}
301		/* encode password */
302		memset(pass,0,256);
303		telnet_gets("Password: ",pass,255,0);
304		pk_encode(pass,xpass,&ck);
305		/* send it off */
306		if (auth_debug_mode)
307			printf("Sent KAB(P)\r\n");
308		if (!Data(ap, SRA_PASS, (void *)xpass, strlen(xpass))) {
309			if (auth_debug_mode)
310				printf("Not enough room\r\n");
311			return;
312		}
313		passwd_sent = 1;
314		break;
315
316	case SRA_REJECT:
317		printf("[ SRA refuses authentication ]\r\n");
318		printf("Trying plaintext login:\r\n");
319		auth_finished(0,AUTH_REJECT);
320		return;
321
322	case SRA_ACCEPT:
323		printf("[ SRA accepts you ]\r\n");
324		skey.data = ck;
325		skey.type = SK_DES;
326		skey.length = 8;
327		encrypt_session_key(&skey, 0);
328
329		auth_finished(ap, AUTH_VALID);
330		return;
331	default:
332		if (auth_debug_mode)
333			printf("Unknown SRA option %d\r\n", data[-1]);
334		return;
335	}
336}
337
338int
339sra_status(Authenticator *ap __unused, char *name, int level)
340{
341	if (level < AUTH_USER)
342		return(level);
343	if (UserNameRequested && sra_valid) {
344		strcpy(name, UserNameRequested);
345		return(AUTH_VALID);
346	} else
347		return(AUTH_USER);
348}
349
350#define	BUMP(buf, len)		while (*(buf)) {++(buf), --(len);}
351#define	ADDC(buf, len, c)	if ((len) > 0) {*(buf)++ = (c); --(len);}
352
353void
354sra_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
355{
356	char lbuf[32];
357	int i;
358
359	buf[buflen-1] = '\0';		/* make sure its NULL terminated */
360	buflen -= 1;
361
362	switch(data[3]) {
363
364	case SRA_CONTINUE:
365		strncpy((char *)buf, " CONTINUE ", buflen);
366		goto common;
367
368	case SRA_REJECT:		/* Rejected (reason might follow) */
369		strncpy((char *)buf, " REJECT ", buflen);
370		goto common;
371
372	case SRA_ACCEPT:		/* Accepted (name might follow) */
373		strncpy((char *)buf, " ACCEPT ", buflen);
374
375	common:
376		BUMP(buf, buflen);
377		if (cnt <= 4)
378			break;
379		ADDC(buf, buflen, '"');
380		for (i = 4; i < cnt; i++)
381			ADDC(buf, buflen, data[i]);
382		ADDC(buf, buflen, '"');
383		ADDC(buf, buflen, '\0');
384		break;
385
386	case SRA_KEY:			/* Authentication data follows */
387		strncpy((char *)buf, " KEY ", buflen);
388		goto common2;
389
390	case SRA_USER:
391		strncpy((char *)buf, " USER ", buflen);
392		goto common2;
393
394	case SRA_PASS:
395		strncpy((char *)buf, " PASS ", buflen);
396		goto common2;
397
398	default:
399		sprintf(lbuf, " %d (unknown)", data[3]);
400		strncpy((char *)buf, lbuf, buflen);
401	common2:
402		BUMP(buf, buflen);
403		for (i = 4; i < cnt; i++) {
404			sprintf(lbuf, " %d", data[i]);
405			strncpy((char *)buf, lbuf, buflen);
406			BUMP(buf, buflen);
407		}
408		break;
409	}
410}
411
412static int
413isroot(const char *usr)
414{
415	struct passwd *pwd;
416
417	if ((pwd=getpwnam(usr))==NULL)
418		return 0;
419	return (!pwd->pw_uid);
420}
421
422static int
423rootterm(char *ttyn)
424{
425	struct ttyent *t;
426
427	return ((t = getttynam(ttyn)) && t->ty_status & TTY_SECURE);
428}
429
430#ifdef NOPAM
431static int
432check_user(char *name, char *cred)
433{
434	char *cp;
435	char *xpasswd, *salt;
436
437	if (isroot(name) && !rootterm(line))
438	{
439		crypt("AA","*"); /* Waste some time to simulate success */
440		return(0);
441	}
442
443	if (pw = sgetpwnam(name)) {
444		if (pw->pw_shell == NULL) {
445			pw = (struct passwd *) NULL;
446			return(0);
447		}
448
449		salt = pw->pw_passwd;
450		xpasswd = crypt(cred, salt);
451		/* The strcmp does not catch null passwords! */
452		if (pw == NULL || *pw->pw_passwd == '\0' ||
453			strcmp(xpasswd, pw->pw_passwd)) {
454			pw = (struct passwd *) NULL;
455			return(0);
456		}
457		return(1);
458	}
459	return(0);
460}
461#else
462
463/*
464 * The following is stolen from ftpd, which stole it from the imap-uw
465 * PAM module and login.c. It is needed because we can't really
466 * "converse" with the user, having already gone to the trouble of
467 * getting their username and password through an encrypted channel.
468 */
469
470#define COPY_STRING(s) (s ? strdup(s):NULL)
471
472struct cred_t {
473	const char *uname;
474	const char *pass;
475};
476typedef struct cred_t cred_t;
477
478static int
479auth_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata)
480{
481	int i;
482	cred_t *cred = (cred_t *) appdata;
483	struct pam_response *reply =
484		malloc(sizeof(struct pam_response) * num_msg);
485
486	if (reply == NULL)
487		return PAM_BUF_ERR;
488
489	for (i = 0; i < num_msg; i++) {
490		switch (msg[i]->msg_style) {
491		case PAM_PROMPT_ECHO_ON:        /* assume want user name */
492			reply[i].resp_retcode = PAM_SUCCESS;
493			reply[i].resp = COPY_STRING(cred->uname);
494			/* PAM frees resp. */
495			break;
496		case PAM_PROMPT_ECHO_OFF:       /* assume want password */
497			reply[i].resp_retcode = PAM_SUCCESS;
498			reply[i].resp = COPY_STRING(cred->pass);
499			/* PAM frees resp. */
500			break;
501		case PAM_TEXT_INFO:
502		case PAM_ERROR_MSG:
503			reply[i].resp_retcode = PAM_SUCCESS;
504			reply[i].resp = NULL;
505			break;
506		default:                        /* unknown message style */
507			free(reply);
508			return PAM_CONV_ERR;
509		}
510	}
511
512	*resp = reply;
513	return PAM_SUCCESS;
514}
515
516/*
517 * The PAM version as a side effect may put a new username in *name.
518 */
519static int
520check_user(char *name, char *cred)
521{
522	pam_handle_t *pamh = NULL;
523	const void *item;
524	int rval;
525	int e;
526	cred_t auth_cred = { name, cred };
527	struct pam_conv conv = { &auth_conv, &auth_cred };
528
529	e = pam_start("telnetd", name, &conv, &pamh);
530	if (e != PAM_SUCCESS) {
531		syslog(LOG_ERR, "pam_start: %s", pam_strerror(pamh, e));
532		return 0;
533	}
534
535#if 0 /* Where can we find this value? */
536	e = pam_set_item(pamh, PAM_RHOST, remotehost);
537	if (e != PAM_SUCCESS) {
538		syslog(LOG_ERR, "pam_set_item(PAM_RHOST): %s",
539			pam_strerror(pamh, e));
540		return 0;
541	}
542#endif
543
544	e = pam_authenticate(pamh, 0);
545	switch (e) {
546	case PAM_SUCCESS:
547		/*
548		 * With PAM we support the concept of a "template"
549		 * user.  The user enters a login name which is
550		 * authenticated by PAM, usually via a remote service
551		 * such as RADIUS or TACACS+.  If authentication
552		 * succeeds, a different but related "template" name
553		 * is used for setting the credentials, shell, and
554		 * home directory.  The name the user enters need only
555		 * exist on the remote authentication server, but the
556		 * template name must be present in the local password
557		 * database.
558		 *
559		 * This is supported by two various mechanisms in the
560		 * individual modules.  However, from the application's
561		 * point of view, the template user is always passed
562		 * back as a changed value of the PAM_USER item.
563		 */
564		if ((e = pam_get_item(pamh, PAM_USER, &item)) ==
565		    PAM_SUCCESS) {
566			strcpy(name, item);
567		} else
568			syslog(LOG_ERR, "Couldn't get PAM_USER: %s",
569			pam_strerror(pamh, e));
570		if (isroot(name) && !rootterm(line))
571			rval = 0;
572		else
573			rval = 1;
574		break;
575
576	case PAM_AUTH_ERR:
577	case PAM_USER_UNKNOWN:
578	case PAM_MAXTRIES:
579		rval = 0;
580	break;
581
582	default:
583		syslog(LOG_ERR, "auth_pam: %s", pam_strerror(pamh, e));
584		rval = 0;
585		break;
586	}
587
588	if ((e = pam_end(pamh, e)) != PAM_SUCCESS) {
589		syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e));
590		rval = 0;
591	}
592	return rval;
593}
594
595#endif
596
597#endif /* ENCRYPTION */
598#endif /* SRA */
599