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
56RCSID("$Id: auth.c 10809 2002-01-18 12:58:49Z joda $");
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	KRB4_ENCPWD
85extern krb4encpwd_init();
86extern krb4encpwd_send();
87extern krb4encpwd_is();
88extern krb4encpwd_reply();
89extern krb4encpwd_status();
90extern krb4encpwd_printsub();
91#endif
92
93#ifdef	RSA_ENCPWD
94extern rsaencpwd_init();
95extern rsaencpwd_send();
96extern rsaencpwd_is();
97extern rsaencpwd_reply();
98extern rsaencpwd_status();
99extern rsaencpwd_printsub();
100#endif
101
102int auth_debug_mode = 0;
103int auth_has_failed  = 0;
104int auth_enable_encrypt = 0;
105static 	const	char	*Name = "Noname";
106static	int	Server = 0;
107static	Authenticator	*authenticated = 0;
108static	int	authenticating = 0;
109static	int	validuser = 0;
110static	unsigned char	_auth_send_data[256];
111static	unsigned char	*auth_send_data;
112static	int	auth_send_cnt = 0;
113
114/*
115 * Authentication types supported.  Plese note that these are stored
116 * in priority order, i.e. try the first one first.
117 */
118Authenticator authenticators[] = {
119#ifdef UNSAFE
120    { AUTHTYPE_UNSAFE, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
121      unsafe_init,
122      unsafe_send,
123      unsafe_is,
124      unsafe_reply,
125      unsafe_status,
126      unsafe_printsub },
127#endif
128#ifdef SRA
129    { AUTHTYPE_SRA, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
130      sra_init,
131      sra_send,
132      sra_is,
133      sra_reply,
134      sra_status,
135      sra_printsub },
136#endif
137#ifdef	SPX
138    { AUTHTYPE_SPX, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
139      spx_init,
140      spx_send,
141      spx_is,
142      spx_reply,
143      spx_status,
144      spx_printsub },
145    { AUTHTYPE_SPX, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
146      spx_init,
147      spx_send,
148      spx_is,
149      spx_reply,
150      spx_status,
151      spx_printsub },
152#endif
153#ifdef	KRB5
154    { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
155      kerberos5_init,
156      kerberos5_send_mutual,
157      kerberos5_is,
158      kerberos5_reply,
159      kerberos5_status,
160      kerberos5_printsub },
161    { AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
162      kerberos5_init,
163      kerberos5_send_oneway,
164      kerberos5_is,
165      kerberos5_reply,
166      kerberos5_status,
167      kerberos5_printsub },
168#endif
169#ifdef	KRB4
170    { AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
171      kerberos4_init,
172      kerberos4_send_mutual,
173      kerberos4_is,
174      kerberos4_reply,
175      kerberos4_status,
176      kerberos4_printsub },
177    { AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
178      kerberos4_init,
179      kerberos4_send_oneway,
180      kerberos4_is,
181      kerberos4_reply,
182      kerberos4_status,
183      kerberos4_printsub },
184#endif
185#ifdef	KRB4_ENCPWD
186    { AUTHTYPE_KRB4_ENCPWD, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
187      krb4encpwd_init,
188      krb4encpwd_send,
189      krb4encpwd_is,
190      krb4encpwd_reply,
191      krb4encpwd_status,
192      krb4encpwd_printsub },
193#endif
194#ifdef	RSA_ENCPWD
195    { AUTHTYPE_RSA_ENCPWD, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
196      rsaencpwd_init,
197      rsaencpwd_send,
198      rsaencpwd_is,
199      rsaencpwd_reply,
200      rsaencpwd_status,
201      rsaencpwd_printsub },
202#endif
203    { 0, },
204};
205
206static Authenticator NoAuth = { 0 };
207
208static int	i_support = 0;
209static int	i_wont_support = 0;
210
211Authenticator *
212findauthenticator(int type, int way)
213{
214    Authenticator *ap = authenticators;
215
216    while (ap->type && (ap->type != type || ap->way != way))
217	++ap;
218    return(ap->type ? ap : 0);
219}
220
221void
222auth_init(const char *name, int server)
223{
224    Authenticator *ap = authenticators;
225
226    Server = server;
227    Name = name;
228
229    i_support = 0;
230    authenticated = 0;
231    authenticating = 0;
232    while (ap->type) {
233	if (!ap->init || (*ap->init)(ap, server)) {
234	    i_support |= typemask(ap->type);
235	    if (auth_debug_mode)
236		printf(">>>%s: I support auth type %d %d\r\n",
237		       Name,
238		       ap->type, ap->way);
239	}
240	else if (auth_debug_mode)
241	    printf(">>>%s: Init failed: auth type %d %d\r\n",
242		   Name, ap->type, ap->way);
243	++ap;
244    }
245}
246
247void
248auth_disable_name(char *name)
249{
250    int x;
251    for (x = 0; x < AUTHTYPE_CNT; ++x) {
252	if (!strcasecmp(name, AUTHTYPE_NAME(x))) {
253	    i_wont_support |= typemask(x);
254	    break;
255	}
256    }
257}
258
259int
260getauthmask(char *type, int *maskp)
261{
262    int x;
263
264    if (!strcasecmp(type, AUTHTYPE_NAME(0))) {
265	*maskp = -1;
266	return(1);
267    }
268
269    for (x = 1; x < AUTHTYPE_CNT; ++x) {
270	if (!strcasecmp(type, AUTHTYPE_NAME(x))) {
271	    *maskp = typemask(x);
272	    return(1);
273	}
274    }
275    return(0);
276}
277
278int
279auth_enable(char *type)
280{
281    return(auth_onoff(type, 1));
282}
283
284int
285auth_disable(char *type)
286{
287    return(auth_onoff(type, 0));
288}
289
290int
291auth_onoff(char *type, int on)
292{
293    int i, mask = -1;
294    Authenticator *ap;
295
296    if (!strcasecmp(type, "?") || !strcasecmp(type, "help")) {
297	printf("auth %s 'type'\n", on ? "enable" : "disable");
298	printf("Where 'type' is one of:\n");
299	printf("\t%s\n", AUTHTYPE_NAME(0));
300	mask = 0;
301	for (ap = authenticators; ap->type; ap++) {
302	    if ((mask & (i = typemask(ap->type))) != 0)
303		continue;
304	    mask |= i;
305	    printf("\t%s\n", AUTHTYPE_NAME(ap->type));
306	}
307	return(0);
308    }
309
310    if (!getauthmask(type, &mask)) {
311	printf("%s: invalid authentication type\n", type);
312	return(0);
313    }
314    if (on)
315	i_wont_support &= ~mask;
316    else
317	i_wont_support |= mask;
318    return(1);
319}
320
321int
322auth_togdebug(int on)
323{
324    if (on < 0)
325	auth_debug_mode ^= 1;
326    else
327	auth_debug_mode = on;
328    printf("auth debugging %s\n", auth_debug_mode ? "enabled" : "disabled");
329    return(1);
330}
331
332int
333auth_status(void)
334{
335    Authenticator *ap;
336    int i, mask;
337
338    if (i_wont_support == -1)
339	printf("Authentication disabled\n");
340    else
341	printf("Authentication enabled\n");
342
343    mask = 0;
344    for (ap = authenticators; ap->type; ap++) {
345	if ((mask & (i = typemask(ap->type))) != 0)
346	    continue;
347	mask |= i;
348	printf("%s: %s\n", AUTHTYPE_NAME(ap->type),
349	       (i_wont_support & typemask(ap->type)) ?
350	       "disabled" : "enabled");
351    }
352    return(1);
353}
354
355/*
356 * This routine is called by the server to start authentication
357 * negotiation.
358 */
359void
360auth_request(void)
361{
362    static unsigned char str_request[64] = { IAC, SB,
363					     TELOPT_AUTHENTICATION,
364					     TELQUAL_SEND, };
365    Authenticator *ap = authenticators;
366    unsigned char *e = str_request + 4;
367
368    if (!authenticating) {
369	authenticating = 1;
370	while (ap->type) {
371	    if (i_support & ~i_wont_support & typemask(ap->type)) {
372		if (auth_debug_mode) {
373		    printf(">>>%s: Sending type %d %d\r\n",
374			   Name, ap->type, ap->way);
375		}
376		*e++ = ap->type;
377		*e++ = ap->way;
378	    }
379	    ++ap;
380	}
381	*e++ = IAC;
382	*e++ = SE;
383	telnet_net_write(str_request, e - str_request);
384	printsub('>', &str_request[2], e - str_request - 2);
385    }
386}
387
388/*
389 * This is called when an AUTH SEND is received.
390 * It should never arrive on the server side (as only the server can
391 * send an AUTH SEND).
392 * You should probably respond to it if you can...
393 *
394 * If you want to respond to the types out of order (i.e. even
395 * if he sends  LOGIN KERBEROS and you support both, you respond
396 * with KERBEROS instead of LOGIN (which is against what the
397 * protocol says)) you will have to hack this code...
398 */
399void
400auth_send(unsigned char *data, int cnt)
401{
402    Authenticator *ap;
403    static unsigned char str_none[] = { IAC, SB, TELOPT_AUTHENTICATION,
404					TELQUAL_IS, AUTHTYPE_NULL, 0,
405					IAC, SE };
406    if (Server) {
407	if (auth_debug_mode) {
408	    printf(">>>%s: auth_send called!\r\n", Name);
409	}
410	return;
411    }
412
413    if (auth_debug_mode) {
414	printf(">>>%s: auth_send got:", Name);
415	printd(data, cnt); printf("\r\n");
416    }
417
418    /*
419     * Save the data, if it is new, so that we can continue looking
420     * at it if the authorization we try doesn't work
421     */
422    if (data < _auth_send_data ||
423	data > _auth_send_data + sizeof(_auth_send_data)) {
424	auth_send_cnt = cnt > sizeof(_auth_send_data)
425	    ? sizeof(_auth_send_data)
426	    : cnt;
427	memmove(_auth_send_data, data, auth_send_cnt);
428	auth_send_data = _auth_send_data;
429    } else {
430	/*
431	 * This is probably a no-op, but we just make sure
432	 */
433	auth_send_data = data;
434	auth_send_cnt = cnt;
435    }
436    while ((auth_send_cnt -= 2) >= 0) {
437	if (auth_debug_mode)
438	    printf(">>>%s: He supports %d\r\n",
439		   Name, *auth_send_data);
440	if ((i_support & ~i_wont_support) & typemask(*auth_send_data)) {
441	    ap = findauthenticator(auth_send_data[0],
442				   auth_send_data[1]);
443	    if (ap && ap->send) {
444		if (auth_debug_mode)
445		    printf(">>>%s: Trying %d %d\r\n",
446			   Name, auth_send_data[0],
447			   auth_send_data[1]);
448		if ((*ap->send)(ap)) {
449		    /*
450		     * Okay, we found one we like
451		     * and did it.
452		     * we can go home now.
453		     */
454		    if (auth_debug_mode)
455			printf(">>>%s: Using type %d\r\n",
456			       Name, *auth_send_data);
457		    auth_send_data += 2;
458		    return;
459		}
460	    }
461	    /* else
462	     *	just continue on and look for the
463	     *	next one if we didn't do anything.
464	     */
465	}
466	auth_send_data += 2;
467    }
468    telnet_net_write(str_none, sizeof(str_none));
469    printsub('>', &str_none[2], sizeof(str_none) - 2);
470    if (auth_debug_mode)
471	printf(">>>%s: Sent failure message\r\n", Name);
472    auth_finished(0, AUTH_REJECT);
473    auth_has_failed = 1;
474#ifdef KANNAN
475    /*
476     *  We requested strong authentication, however no mechanisms worked.
477     *  Therefore, exit on client end.
478     */
479    printf("Unable to securely authenticate user ... exit\n");
480    exit(0);
481#endif /* KANNAN */
482}
483
484void
485auth_send_retry(void)
486{
487    /*
488     * if auth_send_cnt <= 0 then auth_send will end up rejecting
489     * the authentication and informing the other side of this.
490	 */
491    auth_send(auth_send_data, auth_send_cnt);
492}
493
494void
495auth_is(unsigned char *data, int cnt)
496{
497    Authenticator *ap;
498
499    if (cnt < 2)
500	return;
501
502    if (data[0] == AUTHTYPE_NULL) {
503	auth_finished(0, AUTH_REJECT);
504	return;
505    }
506
507    if ((ap = findauthenticator(data[0], data[1]))) {
508	if (ap->is)
509	    (*ap->is)(ap, data+2, cnt-2);
510    } else if (auth_debug_mode)
511	printf(">>>%s: Invalid authentication in IS: %d\r\n",
512	       Name, *data);
513}
514
515void
516auth_reply(unsigned char *data, int cnt)
517{
518    Authenticator *ap;
519
520    if (cnt < 2)
521	return;
522
523    if ((ap = findauthenticator(data[0], data[1]))) {
524	if (ap->reply)
525	    (*ap->reply)(ap, data+2, cnt-2);
526    } else if (auth_debug_mode)
527	printf(">>>%s: Invalid authentication in SEND: %d\r\n",
528	       Name, *data);
529}
530
531void
532auth_name(unsigned char *data, int cnt)
533{
534    char savename[256];
535
536    if (cnt < 1) {
537	if (auth_debug_mode)
538	    printf(">>>%s: Empty name in NAME\r\n", Name);
539	return;
540    }
541    if (cnt > sizeof(savename) - 1) {
542	if (auth_debug_mode)
543	    printf(">>>%s: Name in NAME (%d) exceeds %lu length\r\n",
544		   Name, cnt, (unsigned long)(sizeof(savename)-1));
545	return;
546    }
547    memmove(savename, data, cnt);
548    savename[cnt] = '\0';	/* Null terminate */
549    if (auth_debug_mode)
550	printf(">>>%s: Got NAME [%s]\r\n", Name, savename);
551    auth_encrypt_user(savename);
552}
553
554int
555auth_sendname(unsigned char *cp, int len)
556{
557    static unsigned char str_request[256+6]
558	= { IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_NAME, };
559    unsigned char *e = str_request + 4;
560    unsigned char *ee = &str_request[sizeof(str_request)-2];
561
562    while (--len >= 0) {
563	if ((*e++ = *cp++) == IAC)
564	    *e++ = IAC;
565	if (e >= ee)
566	    return(0);
567    }
568    *e++ = IAC;
569    *e++ = SE;
570    telnet_net_write(str_request, e - str_request);
571    printsub('>', &str_request[2], e - &str_request[2]);
572    return(1);
573}
574
575void
576auth_finished(Authenticator *ap, int result)
577{
578    if (!(authenticated = ap))
579	authenticated = &NoAuth;
580    validuser = result;
581}
582
583/* ARGSUSED */
584static void
585auth_intr(int sig)
586{
587    auth_finished(0, AUTH_REJECT);
588}
589
590int
591auth_wait(char *name, size_t name_sz)
592{
593    if (auth_debug_mode)
594	printf(">>>%s: in auth_wait.\r\n", Name);
595
596    if (Server && !authenticating)
597	return(0);
598
599    signal(SIGALRM, auth_intr);
600    alarm(30);
601    while (!authenticated)
602	if (telnet_spin())
603	    break;
604    alarm(0);
605    signal(SIGALRM, SIG_DFL);
606
607    /*
608     * Now check to see if the user is valid or not
609     */
610    if (!authenticated || authenticated == &NoAuth)
611	return(AUTH_REJECT);
612
613    if (validuser == AUTH_VALID)
614	validuser = AUTH_USER;
615
616    if (authenticated->status)
617	validuser = (*authenticated->status)(authenticated,
618					     name, name_sz,
619					     validuser);
620    return(validuser);
621}
622
623void
624auth_debug(int mode)
625{
626    auth_debug_mode = mode;
627}
628
629void
630auth_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
631{
632    Authenticator *ap;
633
634    if ((ap = findauthenticator(data[1], data[2])) && ap->printsub)
635	(*ap->printsub)(data, cnt, buf, buflen);
636    else
637	auth_gen_printsub(data, cnt, buf, buflen);
638}
639
640void
641auth_gen_printsub(unsigned char *data, int cnt, unsigned char *buf, int buflen)
642{
643    unsigned char *cp;
644    unsigned char tbuf[16];
645
646    cnt -= 3;
647    data += 3;
648    buf[buflen-1] = '\0';
649    buf[buflen-2] = '*';
650    buflen -= 2;
651    for (; cnt > 0; cnt--, data++) {
652	snprintf((char*)tbuf, sizeof(tbuf), " %d", *data);
653	for (cp = tbuf; *cp && buflen > 0; --buflen)
654	    *buf++ = *cp++;
655	if (buflen <= 0)
656	    return;
657    }
658    *buf = '\0';
659}
660#endif
661