sra.c revision 63248
1/* $FreeBSD: head/contrib/telnet/libtelnet/sra.c 63248 2000-07-16 05:48:49Z peter $ */
2
3#ifdef	SRA
4#include <sys/types.h>
5#include <arpa/telnet.h>
6#include <stdio.h>
7#ifdef	__STDC__
8#include <stdlib.h>
9#endif
10#ifdef	NO_STRING_H
11#include <strings.h>
12#else
13#include <string.h>
14#endif
15
16#include "auth.h"
17#include "misc.h"
18#include "encrypt.h"
19#include "pk.h"
20
21char pka[HEXKEYBYTES+1], ska[HEXKEYBYTES+1], pkb[HEXKEYBYTES+1];
22char *user,*pass,*xuser,*xpass;
23DesData ck;
24IdeaData ik;
25
26extern int auth_debug_mode;
27static sra_valid = 0;
28static passwd_sent = 0;
29
30static unsigned char str_data[1024] = { IAC, SB, TELOPT_AUTHENTICATION, 0,
31			  		AUTHTYPE_SRA, };
32
33#define SRA_KEY	0
34#define SRA_USER 1
35#define SRA_CONTINUE 2
36#define SRA_PASS 3
37#define SRA_ACCEPT 4
38#define SRA_REJECT 5
39
40/* support routine to send out authentication message */
41static int Data(ap, type, d, c)
42Authenticator *ap;
43int type;
44void *d;
45int c;
46{
47        unsigned char *p = str_data + 4;
48	unsigned char *cd = (unsigned char *)d;
49
50	if (c == -1)
51		c = strlen((char *)cd);
52
53        if (auth_debug_mode) {
54                printf("%s:%d: [%d] (%d)",
55                        str_data[3] == TELQUAL_IS ? ">>>IS" : ">>>REPLY",
56                        str_data[3],
57                        type, c);
58                printd(d, c);
59                printf("\r\n");
60        }
61	*p++ = ap->type;
62	*p++ = ap->way;
63	*p++ = type;
64        while (c-- > 0) {
65                if ((*p++ = *cd++) == IAC)
66                        *p++ = IAC;
67        }
68        *p++ = IAC;
69        *p++ = SE;
70	if (str_data[3] == TELQUAL_IS)
71		printsub('>', &str_data[2], p - (&str_data[2]));
72        return(net_write(str_data, p - str_data));
73}
74
75int sra_init(ap, server)
76Authenticator *ap;
77int server;
78{
79	if (server)
80		str_data[3] = TELQUAL_REPLY;
81	else
82		str_data[3] = TELQUAL_IS;
83
84	user = (char *)malloc(256);
85	xuser = (char *)malloc(512);
86	pass = (char *)malloc(256);
87	xpass = (char *)malloc(512);
88	passwd_sent = 0;
89
90	genkeys(pka,ska);
91	return(1);
92}
93
94/* client received a go-ahead for sra */
95int sra_send(ap)
96Authenticator *ap;
97{
98	/* send PKA */
99
100	if (auth_debug_mode)
101		printf("Sent PKA to server.\r\n" );
102	printf("Trying SRA secure login:\r\n");
103	if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) {
104		if (auth_debug_mode)
105			printf("Not enough room for authentication data\r\n");
106		return(0);
107	}
108
109	return(1);
110}
111
112/* server received an IS -- could be SRA KEY, USER, or PASS */
113void sra_is(ap, data, cnt)
114Authenticator *ap;
115unsigned char *data;
116int cnt;
117{
118	int valid;
119	Session_Key skey;
120
121	if (cnt-- < 1)
122		return;
123	switch (*data++) {
124
125	case SRA_KEY:
126		if (cnt < HEXKEYBYTES) {
127			Data(ap, SRA_REJECT, (void *)0, 0);
128			auth_finished(ap, AUTH_USER);
129			if (auth_debug_mode) {
130				printf("SRA user rejected for bad PKB\r\n");
131			}
132			return;
133		}
134		if (auth_debug_mode)
135			printf("Sent pka\r\n");
136		if (!Data(ap, SRA_KEY, (void *)pka, HEXKEYBYTES)) {
137			if (auth_debug_mode)
138				printf("Not enough room\r\n");
139			return;
140		}
141		memcpy(pkb,data,HEXKEYBYTES);
142		pkb[HEXKEYBYTES] = '\0';
143		common_key(ska,pkb,&ik,&ck);
144		break;
145
146	case SRA_USER:
147		/* decode KAB(u) */
148		memcpy(xuser,data,cnt);
149		xuser[cnt] = '\0';
150		pk_decode(xuser,user,&ck);
151		auth_encrypt_user(user);
152		Data(ap, SRA_CONTINUE, (void *)0, 0);
153
154		break;
155
156	case SRA_PASS:
157		/* decode KAB(P) */
158		memcpy(xpass,data,cnt);
159		xpass[cnt] = '\0';
160		pk_decode(xpass,pass,&ck);
161
162		/* check user's password */
163		valid = check_user(user,pass);
164
165		if(valid) {
166			Data(ap, SRA_ACCEPT, (void *)0, 0);
167#ifdef DES_ENCRYPTION
168			skey.data = ck;
169			skey.type = SK_DES;
170			skey.length = 8;
171			encrypt_session_key(&skey, 1);
172#endif
173
174			sra_valid = 1;
175			auth_finished(ap, AUTH_VALID);
176			if (auth_debug_mode) {
177				printf("SRA user accepted\r\n");
178			}
179		}
180		else {
181			Data(ap, SRA_CONTINUE, (void *)0, 0);
182/*
183			Data(ap, SRA_REJECT, (void *)0, 0);
184			sra_valid = 0;
185			auth_finished(ap, AUTH_REJECT);
186*/
187			if (auth_debug_mode) {
188				printf("SRA user failed\r\n");
189			}
190		}
191		break;
192
193	default:
194		if (auth_debug_mode)
195			printf("Unknown SRA option %d\r\n", data[-1]);
196		Data(ap, SRA_REJECT, 0, 0);
197		sra_valid = 0;
198		auth_finished(ap, AUTH_REJECT);
199		break;
200	}
201}
202
203extern char *getpass();
204
205/* client received REPLY -- could be SRA KEY, CONTINUE, ACCEPT, or REJECT */
206void sra_reply(ap, data, cnt)
207Authenticator *ap;
208unsigned char *data;
209int cnt;
210{
211	extern char *telnet_gets();
212	char uprompt[256],tuser[256];
213	Session_Key skey;
214	int i;
215
216	if (cnt-- < 1)
217		return;
218	switch (*data++) {
219
220	case SRA_KEY:
221		/* calculate common key */
222		if (cnt < HEXKEYBYTES) {
223			if (auth_debug_mode) {
224				printf("SRA user rejected for bad PKB\r\n");
225			}
226			return;
227		}
228		memcpy(pkb,data,HEXKEYBYTES);
229		pkb[HEXKEYBYTES] = '\0';
230
231		common_key(ska,pkb,&ik,&ck);
232
233	enc_user:
234
235		/* encode user */
236		memset(tuser,0,sizeof(tuser));
237		sprintf(uprompt,"User (%s): ",UserNameRequested);
238		telnet_gets(uprompt,tuser,255,1);
239		if (tuser[0] == '\n' || tuser[0] == '\r' )
240			strcpy(user,UserNameRequested);
241		else {
242			/* telnet_gets leaves the newline on */
243			for(i=0;i<sizeof(tuser);i++) {
244				if (tuser[i] == '\n') {
245					tuser[i] = '\0';
246					break;
247				}
248			}
249			strcpy(user,tuser);
250		}
251		pk_encode(user,xuser,&ck);
252
253		/* send it off */
254		if (auth_debug_mode)
255			printf("Sent KAB(U)\r\n");
256		if (!Data(ap, SRA_USER, (void *)xuser, strlen(xuser))) {
257			if (auth_debug_mode)
258				printf("Not enough room\r\n");
259			return;
260		}
261		break;
262
263	case SRA_CONTINUE:
264		if (passwd_sent) {
265			passwd_sent = 0;
266			printf("[ SRA login failed ]\r\n");
267			goto enc_user;
268		}
269		/* encode password */
270		memset(pass,0,sizeof(pass));
271		telnet_gets("Password: ",pass,255,0);
272		pk_encode(pass,xpass,&ck);
273		/* send it off */
274		if (auth_debug_mode)
275			printf("Sent KAB(P)\r\n");
276		if (!Data(ap, SRA_PASS, (void *)xpass, strlen(xpass))) {
277			if (auth_debug_mode)
278				printf("Not enough room\r\n");
279			return;
280		}
281		passwd_sent = 1;
282		break;
283
284	case SRA_REJECT:
285		printf("[ SRA refuses authentication ]\r\n");
286		printf("Trying plaintext login:\r\n");
287		auth_finished(0,AUTH_REJECT);
288		return;
289
290	case SRA_ACCEPT:
291		printf("[ SRA accepts you ]\r\n");
292#ifdef DES_ENCRYPTION
293		skey.data = ck;
294		skey.type = SK_DES;
295		skey.length = 8;
296		encrypt_session_key(&skey, 0);
297#endif
298
299		auth_finished(ap, AUTH_VALID);
300		return;
301	default:
302		if (auth_debug_mode)
303			printf("Unknown SRA option %d\r\n", data[-1]);
304		return;
305	}
306}
307
308int sra_status(ap, name, level)
309Authenticator *ap;
310char *name;
311int level;
312{
313	if (level < AUTH_USER)
314		return(level);
315	if (UserNameRequested && sra_valid) {
316		strcpy(name, UserNameRequested);
317		return(AUTH_VALID);
318	} else
319		return(AUTH_USER);
320}
321
322#define	BUMP(buf, len)		while (*(buf)) {++(buf), --(len);}
323#define	ADDC(buf, len, c)	if ((len) > 0) {*(buf)++ = (c); --(len);}
324
325void sra_printsub(data, cnt, buf, buflen)
326unsigned char *data, *buf;
327int cnt, buflen;
328{
329	char lbuf[32];
330	register int i;
331
332	buf[buflen-1] = '\0';		/* make sure its NULL terminated */
333	buflen -= 1;
334
335	switch(data[3]) {
336
337	case SRA_CONTINUE:
338		strncpy((char *)buf, " CONTINUE ", buflen);
339		goto common;
340
341	case SRA_REJECT:		/* Rejected (reason might follow) */
342		strncpy((char *)buf, " REJECT ", buflen);
343		goto common;
344
345	case SRA_ACCEPT:		/* Accepted (name might follow) */
346		strncpy((char *)buf, " ACCEPT ", buflen);
347
348	common:
349		BUMP(buf, buflen);
350		if (cnt <= 4)
351			break;
352		ADDC(buf, buflen, '"');
353		for (i = 4; i < cnt; i++)
354			ADDC(buf, buflen, data[i]);
355		ADDC(buf, buflen, '"');
356		ADDC(buf, buflen, '\0');
357		break;
358
359	case SRA_KEY:			/* Authentication data follows */
360		strncpy((char *)buf, " KEY ", buflen);
361		goto common2;
362
363	case SRA_USER:
364		strncpy((char *)buf, " USER ", buflen);
365		goto common2;
366
367	case SRA_PASS:
368		strncpy((char *)buf, " PASS ", buflen);
369		goto common2;
370
371	default:
372		sprintf(lbuf, " %d (unknown)", data[3]);
373		strncpy((char *)buf, lbuf, buflen);
374	common2:
375		BUMP(buf, buflen);
376		for (i = 4; i < cnt; i++) {
377			sprintf(lbuf, " %d", data[i]);
378			strncpy((char *)buf, lbuf, buflen);
379			BUMP(buf, buflen);
380		}
381		break;
382	}
383}
384
385struct	passwd *pw;
386
387/*
388 * Helper function for sgetpwnam().
389 */
390char *
391sgetsave(s)
392	char *s;
393{
394	char *new = malloc((unsigned) strlen(s) + 1);
395
396	if (new == NULL) {
397		return(NULL);
398	}
399	(void) strcpy(new, s);
400	return (new);
401}
402
403#include <pwd.h>
404#include <syslog.h>
405#ifdef USE_SHADOW
406#include <shadow.h>
407#endif
408
409
410struct passwd *
411sgetpwnam(name)
412	char *name;
413{
414	static struct passwd save;
415	register struct passwd *p;
416	char *sgetsave();
417
418	if ((p = getpwnam(name)) == NULL)
419		return (p);
420	if (save.pw_name) {
421		free(save.pw_name);
422		free(save.pw_passwd);
423		free(save.pw_gecos);
424		free(save.pw_dir);
425		free(save.pw_shell);
426	}
427	save = *p;
428	save.pw_name = sgetsave(p->pw_name);
429	save.pw_passwd = sgetsave(p->pw_passwd);
430	save.pw_gecos = sgetsave(p->pw_gecos);
431	save.pw_dir = sgetsave(p->pw_dir);
432	save.pw_shell = sgetsave(p->pw_shell);
433#if 0
434syslog(LOG_WARNING,"%s\n",save.pw_name);
435syslog(LOG_WARNING,"%s\n",save.pw_passwd);
436syslog(LOG_WARNING,"%s\n",save.pw_gecos);
437syslog(LOG_WARNING,"%s\n",save.pw_dir);
438#endif
439#ifdef USE_SHADOW
440        {
441                struct spwd *sp;
442                sp = getspnam(name);
443                free(save.pw_passwd);
444                save.pw_passwd  = sgetsave(sp->sp_pwdp);
445        }
446#endif
447	return (&save);
448}
449
450char *crypt();
451
452int check_user(name, pass)
453char *name;
454char *pass;
455{
456	register char *cp;
457	char *xpasswd, *salt;
458
459	if (pw = sgetpwnam(name)) {
460		if (pw->pw_shell == NULL) {
461			pw = (struct passwd *) NULL;
462			return(0);
463		}
464
465		salt = pw->pw_passwd;
466		xpasswd = crypt(pass, salt);
467		/* The strcmp does not catch null passwords! */
468		if (pw == NULL || *pw->pw_passwd == '\0' ||
469			strcmp(xpasswd, pw->pw_passwd)) {
470			pw = (struct passwd *) NULL;
471			return(0);
472		}
473		return(1);
474	}
475	return(0);
476}
477
478
479#endif
480
481