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