xref: /freebsd/crypto/heimdal/appl/telnet/libtelnet/auth.c (revision b9f654b163bce26de79705e77b872427c9f2afa1)
1 /*-
2  * Copyright (c) 1991, 1993
3  *	The Regents of the University of California.  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. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *	This product includes software developed by the University of
16  *	California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33 
34 /*
35  * Copyright (C) 1990 by the Massachusetts Institute of Technology
36  *
37  * Export of this software from the United States of America is assumed
38  * to require a specific license from the United States Government.
39  * It is the responsibility of any person or organization contemplating
40  * export to obtain such a license before exporting.
41  *
42  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
43  * distribute this software and its documentation for any purpose and
44  * without fee is hereby granted, provided that the above copyright
45  * notice appear in all copies and that both that copyright notice and
46  * this permission notice appear in supporting documentation, and that
47  * the name of M.I.T. not be used in advertising or publicity pertaining
48  * to distribution of the software without specific, written prior
49  * permission.  M.I.T. makes no representations about the suitability of
50  * this software for any purpose.  It is provided "as is" without express
51  * or implied warranty.
52  */
53 
54 #include <config.h>
55 
56 RCSID("$Id$");
57 
58 #if	defined(AUTHENTICATION)
59 #include <stdio.h>
60 #ifdef HAVE_SYS_TYPES_H
61 #include <sys/types.h>
62 #endif
63 #include <signal.h>
64 #define	AUTH_NAMES
65 #ifdef HAVE_ARPA_TELNET_H
66 #include <arpa/telnet.h>
67 #endif
68 #include <stdlib.h>
69 #include <string.h>
70 
71 #include <roken.h>
72 
73 #ifdef SOCKS
74 #include <socks.h>
75 #endif
76 
77 #include "encrypt.h"
78 #include "auth.h"
79 #include "misc-proto.h"
80 #include "auth-proto.h"
81 
82 #define	typemask(x)		(1<<((x)-1))
83 
84 #ifdef	RSA_ENCPWD
85 extern rsaencpwd_init();
86 extern rsaencpwd_send();
87 extern rsaencpwd_is();
88 extern rsaencpwd_reply();
89 extern rsaencpwd_status();
90 extern rsaencpwd_printsub();
91 #endif
92 
93 int auth_debug_mode = 0;
94 int auth_has_failed  = 0;
95 int auth_enable_encrypt = 0;
96 static 	const	char	*Name = "Noname";
97 static	int	Server = 0;
98 static	Authenticator	*authenticated = 0;
99 static	int	authenticating = 0;
100 static	int	validuser = 0;
101 static	unsigned char	_auth_send_data[256];
102 static	unsigned char	*auth_send_data;
103 static	int	auth_send_cnt = 0;
104 
105 /*
106  * Authentication types supported.  Plese note that these are stored
107  * in priority order, i.e. try the first one first.
108  */
109 Authenticator authenticators[] = {
110 #ifdef UNSAFE
111     { AUTHTYPE_UNSAFE, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
112       unsafe_init,
113       unsafe_send,
114       unsafe_is,
115       unsafe_reply,
116       unsafe_status,
117       unsafe_printsub },
118 #endif
119 #ifdef SRA
120     { AUTHTYPE_SRA, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
121       sra_init,
122       sra_send,
123       sra_is,
124       sra_reply,
125       sra_status,
126       sra_printsub },
127 #endif
128 #ifdef	SPX
129     { AUTHTYPE_SPX, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
130       spx_init,
131       spx_send,
132       spx_is,
133       spx_reply,
134       spx_status,
135       spx_printsub },
136     { AUTHTYPE_SPX, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
137       spx_init,
138       spx_send,
139       spx_is,
140       spx_reply,
141       spx_status,
142       spx_printsub },
143 #endif
144 #ifdef	KRB5
145     { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
146       kerberos5_init,
147       kerberos5_send_mutual,
148       kerberos5_is,
149       kerberos5_reply,
150       kerberos5_status,
151       kerberos5_printsub },
152     { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
153       kerberos5_init,
154       kerberos5_send_oneway,
155       kerberos5_is,
156       kerberos5_reply,
157       kerberos5_status,
158       kerberos5_printsub },
159 #endif
160 #ifdef	RSA_ENCPWD
161     { AUTHTYPE_RSA_ENCPWD, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
162       rsaencpwd_init,
163       rsaencpwd_send,
164       rsaencpwd_is,
165       rsaencpwd_reply,
166       rsaencpwd_status,
167       rsaencpwd_printsub },
168 #endif
169     { 0, },
170 };
171 
172 static Authenticator NoAuth = { 0 };
173 
174 static int	i_support = 0;
175 static int	i_wont_support = 0;
176 
177 Authenticator *
178 findauthenticator(int type, int way)
179 {
180     Authenticator *ap = authenticators;
181 
182     while (ap->type && (ap->type != type || ap->way != way))
183 	++ap;
184     return(ap->type ? ap : 0);
185 }
186 
187 void
188 auth_init(const char *name, int server)
189 {
190     Authenticator *ap = authenticators;
191 
192     Server = server;
193     Name = name;
194 
195     i_support = 0;
196     authenticated = 0;
197     authenticating = 0;
198     while (ap->type) {
199 	if (!ap->init || (*ap->init)(ap, server)) {
200 	    i_support |= typemask(ap->type);
201 	    if (auth_debug_mode)
202 		printf(">>>%s: I support auth type %d %d\r\n",
203 		       Name,
204 		       ap->type, ap->way);
205 	}
206 	else if (auth_debug_mode)
207 	    printf(">>>%s: Init failed: auth type %d %d\r\n",
208 		   Name, ap->type, ap->way);
209 	++ap;
210     }
211 }
212 
213 void
214 auth_disable_name(char *name)
215 {
216     int x;
217     for (x = 0; x < AUTHTYPE_CNT; ++x) {
218 	if (!strcasecmp(name, AUTHTYPE_NAME(x))) {
219 	    i_wont_support |= typemask(x);
220 	    break;
221 	}
222     }
223 }
224 
225 int
226 getauthmask(char *type, int *maskp)
227 {
228     int x;
229 
230     if (!strcasecmp(type, AUTHTYPE_NAME(0))) {
231 	*maskp = -1;
232 	return(1);
233     }
234 
235     for (x = 1; x < AUTHTYPE_CNT; ++x) {
236 	if (!strcasecmp(type, AUTHTYPE_NAME(x))) {
237 	    *maskp = typemask(x);
238 	    return(1);
239 	}
240     }
241     return(0);
242 }
243 
244 int
245 auth_enable(char *type)
246 {
247     return(auth_onoff(type, 1));
248 }
249 
250 int
251 auth_disable(char *type)
252 {
253     return(auth_onoff(type, 0));
254 }
255 
256 int
257 auth_onoff(char *type, int on)
258 {
259     int i, mask = -1;
260     Authenticator *ap;
261 
262     if (!strcasecmp(type, "?") || !strcasecmp(type, "help")) {
263 	printf("auth %s 'type'\n", on ? "enable" : "disable");
264 	printf("Where 'type' is one of:\n");
265 	printf("\t%s\n", AUTHTYPE_NAME(0));
266 	mask = 0;
267 	for (ap = authenticators; ap->type; ap++) {
268 	    if ((mask & (i = typemask(ap->type))) != 0)
269 		continue;
270 	    mask |= i;
271 	    printf("\t%s\n", AUTHTYPE_NAME(ap->type));
272 	}
273 	return(0);
274     }
275 
276     if (!getauthmask(type, &mask)) {
277 	printf("%s: invalid authentication type\n", type);
278 	return(0);
279     }
280     if (on)
281 	i_wont_support &= ~mask;
282     else
283 	i_wont_support |= mask;
284     return(1);
285 }
286 
287 int
288 auth_togdebug(int on)
289 {
290     if (on < 0)
291 	auth_debug_mode ^= 1;
292     else
293 	auth_debug_mode = on;
294     printf("auth debugging %s\n", auth_debug_mode ? "enabled" : "disabled");
295     return(1);
296 }
297 
298 int
299 auth_status(void)
300 {
301     Authenticator *ap;
302     int i, mask;
303 
304     if (i_wont_support == -1)
305 	printf("Authentication disabled\n");
306     else
307 	printf("Authentication enabled\n");
308 
309     mask = 0;
310     for (ap = authenticators; ap->type; ap++) {
311 	if ((mask & (i = typemask(ap->type))) != 0)
312 	    continue;
313 	mask |= i;
314 	printf("%s: %s\n", AUTHTYPE_NAME(ap->type),
315 	       (i_wont_support & typemask(ap->type)) ?
316 	       "disabled" : "enabled");
317     }
318     return(1);
319 }
320 
321 /*
322  * This routine is called by the server to start authentication
323  * negotiation.
324  */
325 void
326 auth_request(void)
327 {
328     static unsigned char str_request[64] = { IAC, SB,
329 					     TELOPT_AUTHENTICATION,
330 					     TELQUAL_SEND, };
331     Authenticator *ap = authenticators;
332     unsigned char *e = str_request + 4;
333 
334     if (!authenticating) {
335 	authenticating = 1;
336 	while (ap->type) {
337 	    if (i_support & ~i_wont_support & typemask(ap->type)) {
338 		if (auth_debug_mode) {
339 		    printf(">>>%s: Sending type %d %d\r\n",
340 			   Name, ap->type, ap->way);
341 		}
342 		*e++ = ap->type;
343 		*e++ = ap->way;
344 	    }
345 	    ++ap;
346 	}
347 	*e++ = IAC;
348 	*e++ = SE;
349 	telnet_net_write(str_request, e - str_request);
350 	printsub('>', &str_request[2], e - str_request - 2);
351     }
352 }
353 
354 /*
355  * This is called when an AUTH SEND is received.
356  * It should never arrive on the server side (as only the server can
357  * send an AUTH SEND).
358  * You should probably respond to it if you can...
359  *
360  * If you want to respond to the types out of order (i.e. even
361  * if he sends  LOGIN KERBEROS and you support both, you respond
362  * with KERBEROS instead of LOGIN (which is against what the
363  * protocol says)) you will have to hack this code...
364  */
365 void
366 auth_send(unsigned char *data, int cnt)
367 {
368     Authenticator *ap;
369     static unsigned char str_none[] = { IAC, SB, TELOPT_AUTHENTICATION,
370 					TELQUAL_IS, AUTHTYPE_NULL, 0,
371 					IAC, SE };
372     if (Server) {
373 	if (auth_debug_mode) {
374 	    printf(">>>%s: auth_send called!\r\n", Name);
375 	}
376 	return;
377     }
378 
379     if (auth_debug_mode) {
380 	printf(">>>%s: auth_send got:", Name);
381 	printd(data, cnt); printf("\r\n");
382     }
383 
384     /*
385      * Save the data, if it is new, so that we can continue looking
386      * at it if the authorization we try doesn't work
387      */
388     if (data < _auth_send_data ||
389 	data > _auth_send_data + sizeof(_auth_send_data)) {
390 	auth_send_cnt = cnt > sizeof(_auth_send_data)
391 	    ? sizeof(_auth_send_data)
392 	    : cnt;
393 	memmove(_auth_send_data, data, auth_send_cnt);
394 	auth_send_data = _auth_send_data;
395     } else {
396 	/*
397 	 * This is probably a no-op, but we just make sure
398 	 */
399 	auth_send_data = data;
400 	auth_send_cnt = cnt;
401     }
402     while ((auth_send_cnt -= 2) >= 0) {
403 	if (auth_debug_mode)
404 	    printf(">>>%s: He supports %d\r\n",
405 		   Name, *auth_send_data);
406 	if ((i_support & ~i_wont_support) & typemask(*auth_send_data)) {
407 	    ap = findauthenticator(auth_send_data[0],
408 				   auth_send_data[1]);
409 	    if (ap && ap->send) {
410 		if (auth_debug_mode)
411 		    printf(">>>%s: Trying %d %d\r\n",
412 			   Name, auth_send_data[0],
413 			   auth_send_data[1]);
414 		if ((*ap->send)(ap)) {
415 		    /*
416 		     * Okay, we found one we like
417 		     * and did it.
418 		     * we can go home now.
419 		     */
420 		    if (auth_debug_mode)
421 			printf(">>>%s: Using type %d\r\n",
422 			       Name, *auth_send_data);
423 		    auth_send_data += 2;
424 		    return;
425 		}
426 	    }
427 	    /* else
428 	     *	just continue on and look for the
429 	     *	next one if we didn't do anything.
430 	     */
431 	}
432 	auth_send_data += 2;
433     }
434     telnet_net_write(str_none, sizeof(str_none));
435     printsub('>', &str_none[2], sizeof(str_none) - 2);
436     if (auth_debug_mode)
437 	printf(">>>%s: Sent failure message\r\n", Name);
438     auth_finished(0, AUTH_REJECT);
439     auth_has_failed = 1;
440 #ifdef KANNAN
441     /*
442      *  We requested strong authentication, however no mechanisms worked.
443      *  Therefore, exit on client end.
444      */
445     printf("Unable to securely authenticate user ... exit\n");
446     exit(0);
447 #endif /* KANNAN */
448 }
449 
450 void
451 auth_send_retry(void)
452 {
453     /*
454      * if auth_send_cnt <= 0 then auth_send will end up rejecting
455      * the authentication and informing the other side of this.
456 	 */
457     auth_send(auth_send_data, auth_send_cnt);
458 }
459 
460 void
461 auth_is(unsigned char *data, int cnt)
462 {
463     Authenticator *ap;
464 
465     if (cnt < 2)
466 	return;
467 
468     if (data[0] == AUTHTYPE_NULL) {
469 	auth_finished(0, AUTH_REJECT);
470 	return;
471     }
472 
473     if ((ap = findauthenticator(data[0], data[1]))) {
474 	if (ap->is)
475 	    (*ap->is)(ap, data+2, cnt-2);
476     } else if (auth_debug_mode)
477 	printf(">>>%s: Invalid authentication in IS: %d\r\n",
478 	       Name, *data);
479 }
480 
481 void
482 auth_reply(unsigned char *data, int cnt)
483 {
484     Authenticator *ap;
485 
486     if (cnt < 2)
487 	return;
488 
489     if ((ap = findauthenticator(data[0], data[1]))) {
490 	if (ap->reply)
491 	    (*ap->reply)(ap, data+2, cnt-2);
492     } else if (auth_debug_mode)
493 	printf(">>>%s: Invalid authentication in SEND: %d\r\n",
494 	       Name, *data);
495 }
496 
497 void
498 auth_name(unsigned char *data, int cnt)
499 {
500     char savename[256];
501 
502     if (cnt < 1) {
503 	if (auth_debug_mode)
504 	    printf(">>>%s: Empty name in NAME\r\n", Name);
505 	return;
506     }
507     if (cnt > sizeof(savename) - 1) {
508 	if (auth_debug_mode)
509 	    printf(">>>%s: Name in NAME (%d) exceeds %lu length\r\n",
510 		   Name, cnt, (unsigned long)(sizeof(savename)-1));
511 	return;
512     }
513     memmove(savename, data, cnt);
514     savename[cnt] = '\0';	/* Null terminate */
515     if (auth_debug_mode)
516 	printf(">>>%s: Got NAME [%s]\r\n", Name, savename);
517     auth_encrypt_user(savename);
518 }
519 
520 int
521 auth_sendname(unsigned char *cp, int len)
522 {
523     static unsigned char str_request[256+6]
524 	= { IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_NAME, };
525     unsigned char *e = str_request + 4;
526     unsigned char *ee = &str_request[sizeof(str_request)-2];
527 
528     while (--len >= 0) {
529 	if ((*e++ = *cp++) == IAC)
530 	    *e++ = IAC;
531 	if (e >= ee)
532 	    return(0);
533     }
534     *e++ = IAC;
535     *e++ = SE;
536     telnet_net_write(str_request, e - str_request);
537     printsub('>', &str_request[2], e - &str_request[2]);
538     return(1);
539 }
540 
541 void
542 auth_finished(Authenticator *ap, int result)
543 {
544     if (!(authenticated = ap))
545 	authenticated = &NoAuth;
546     validuser = result;
547 }
548 
549 /* ARGSUSED */
550 static void
551 auth_intr(int sig)
552 {
553     auth_finished(0, AUTH_REJECT);
554 }
555 
556 int
557 auth_wait(char *name, size_t name_sz)
558 {
559     if (auth_debug_mode)
560 	printf(">>>%s: in auth_wait.\r\n", Name);
561 
562     if (Server && !authenticating)
563 	return(0);
564 
565     signal(SIGALRM, auth_intr);
566     alarm(30);
567     while (!authenticated)
568 	if (telnet_spin())
569 	    break;
570     alarm(0);
571     signal(SIGALRM, SIG_DFL);
572 
573     /*
574      * Now check to see if the user is valid or not
575      */
576     if (!authenticated || authenticated == &NoAuth)
577 	return(AUTH_REJECT);
578 
579     if (validuser == AUTH_VALID)
580 	validuser = AUTH_USER;
581 
582     if (authenticated->status)
583 	validuser = (*authenticated->status)(authenticated,
584 					     name, name_sz,
585 					     validuser);
586     return(validuser);
587 }
588 
589 void
590 auth_debug(int mode)
591 {
592     auth_debug_mode = mode;
593 }
594 
595 void
596 auth_printsub(unsigned char *data, size_t cnt,
597 	      unsigned char *buf, size_t buflen)
598 {
599     Authenticator *ap;
600 
601     if ((ap = findauthenticator(data[1], data[2])) && ap->printsub)
602 	(*ap->printsub)(data, cnt, buf, buflen);
603     else
604 	auth_gen_printsub(data, cnt, buf, buflen);
605 }
606 
607 void
608 auth_gen_printsub(unsigned char *data, size_t cnt,
609 		  unsigned char *buf, size_t buflen)
610 {
611     unsigned char *cp;
612     unsigned char tbuf[16];
613 
614     cnt -= 3;
615     data += 3;
616     buf[buflen-1] = '\0';
617     buf[buflen-2] = '*';
618     buflen -= 2;
619     for (; cnt > 0; cnt--, data++) {
620 	snprintf((char*)tbuf, sizeof(tbuf), " %d", *data);
621 	for (cp = tbuf; *cp && buflen > 0; --buflen)
622 	    *buf++ = *cp++;
623 	if (buflen <= 0)
624 	    return;
625     }
626     *buf = '\0';
627 }
628 #endif
629