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$");
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
85extern rsaencpwd_init();
86extern rsaencpwd_send();
87extern rsaencpwd_is();
88extern rsaencpwd_reply();
89extern rsaencpwd_status();
90extern rsaencpwd_printsub();
91#endif
92
93int auth_debug_mode = 0;
94int auth_has_failed  = 0;
95int auth_enable_encrypt = 0;
96static 	const	char	*Name = "Noname";
97static	int	Server = 0;
98static	Authenticator	*authenticated = 0;
99static	int	authenticating = 0;
100static	int	validuser = 0;
101static	unsigned char	_auth_send_data[256];
102static	unsigned char	*auth_send_data;
103static	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 */
109Authenticator 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
172static Authenticator NoAuth = { 0 };
173
174static int	i_support = 0;
175static int	i_wont_support = 0;
176
177Authenticator *
178findauthenticator(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
187void
188auth_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
213void
214auth_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
225int
226getauthmask(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
244int
245auth_enable(char *type)
246{
247    return(auth_onoff(type, 1));
248}
249
250int
251auth_disable(char *type)
252{
253    return(auth_onoff(type, 0));
254}
255
256int
257auth_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
287int
288auth_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
298int
299auth_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 */
325void
326auth_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 */
365void
366auth_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
450void
451auth_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
460void
461auth_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
481void
482auth_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
497void
498auth_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
520int
521auth_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
541void
542auth_finished(Authenticator *ap, int result)
543{
544    if (!(authenticated = ap))
545	authenticated = &NoAuth;
546    validuser = result;
547}
548
549/* ARGSUSED */
550static void
551auth_intr(int sig)
552{
553    auth_finished(0, AUTH_REJECT);
554}
555
556int
557auth_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
589void
590auth_debug(int mode)
591{
592    auth_debug_mode = mode;
593}
594
595void
596auth_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
607void
608auth_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