xref: /freebsd/contrib/telnet/libtelnet/sra.c (revision 77a0943ded95b9e6438f7db70c4a28e4d93946d4)
1 /* $FreeBSD$ */
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 
21 char pka[HEXKEYBYTES+1], ska[HEXKEYBYTES+1], pkb[HEXKEYBYTES+1];
22 char *user,*pass,*xuser,*xpass;
23 DesData ck;
24 IdeaData ik;
25 
26 extern int auth_debug_mode;
27 static sra_valid = 0;
28 static passwd_sent = 0;
29 
30 static 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 */
41 static int Data(ap, type, d, c)
42 Authenticator *ap;
43 int type;
44 void *d;
45 int 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 
75 int sra_init(ap, server)
76 Authenticator *ap;
77 int 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 */
95 int sra_send(ap)
96 Authenticator *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 */
113 void sra_is(ap, data, cnt)
114 Authenticator *ap;
115 unsigned char *data;
116 int 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 
203 extern char *getpass();
204 
205 /* client received REPLY -- could be SRA KEY, CONTINUE, ACCEPT, or REJECT */
206 void sra_reply(ap, data, cnt)
207 Authenticator *ap;
208 unsigned char *data;
209 int 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 
308 int sra_status(ap, name, level)
309 Authenticator *ap;
310 char *name;
311 int 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 
325 void sra_printsub(data, cnt, buf, buflen)
326 unsigned char *data, *buf;
327 int 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 
385 struct	passwd *pw;
386 
387 /*
388  * Helper function for sgetpwnam().
389  */
390 char *
391 sgetsave(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 
410 struct passwd *
411 sgetpwnam(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
434 syslog(LOG_WARNING,"%s\n",save.pw_name);
435 syslog(LOG_WARNING,"%s\n",save.pw_passwd);
436 syslog(LOG_WARNING,"%s\n",save.pw_gecos);
437 syslog(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 
450 char *crypt();
451 
452 int check_user(name, pass)
453 char *name;
454 char *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