1 /* $NetBSD: auth.c,v 1.21 2012/03/21 05:33:27 matt Exp $ */
4 * Copyright (c) 1991, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
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.
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
32 #include <sys/cdefs.h>
35 static char sccsid
[] = "@(#)auth.c 8.3 (Berkeley) 5/30/95"
37 __RCSID("$NetBSD: auth.c,v 1.21 2012/03/21 05:33:27 matt Exp $");
42 * Copyright (C) 1990 by the Massachusetts Institute of Technology
44 * Export of this software from the United States of America is assumed
45 * to require a specific license from the United States Government.
46 * It is the responsibility of any person or organization contemplating
47 * export to obtain such a license before exporting.
49 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
50 * distribute this software and its documentation for any purpose and
51 * without fee is hereby granted, provided that the above copyright
52 * notice appear in all copies and that both that copyright notice and
53 * this permission notice appear in supporting documentation, and that
54 * the name of M.I.T. not be used in advertising or publicity pertaining
55 * to distribution of the software without specific, written prior
56 * permission. M.I.T. makes no representations about the suitability of
57 * this software for any purpose. It is provided "as is" without express
58 * or implied warranty.
64 #include <sys/types.h>
67 #include <arpa/telnet.h>
78 #include "misc-proto.h"
79 #include "auth-proto.h"
81 #define typemask(x) (1<<((x)-1))
84 extern rsaencpwd_init();
85 extern rsaencpwd_send();
86 extern rsaencpwd_is();
87 extern rsaencpwd_reply();
88 extern rsaencpwd_status();
89 extern rsaencpwd_printsub();
92 int auth_debug_mode
= 0;
93 static const char *Name
= "Noname";
94 static int Server
= 0;
95 static Authenticator
*authenticated
= 0;
96 static int authenticating
= 0;
97 static int validuser
= 0;
98 static unsigned char _auth_send_data
[256];
99 static unsigned char *auth_send_data
;
100 static int auth_send_cnt
= 0;
102 static void auth_intr(int);
105 * Authentication types supported. Plese note that these are stored
106 * in priority order, i.e. try the first one first.
108 Authenticator authenticators
[] = {
110 { AUTHTYPE_SPX
, AUTH_WHO_CLIENT
|AUTH_HOW_MUTUAL
,
117 { AUTHTYPE_SPX
, AUTH_WHO_CLIENT
|AUTH_HOW_ONE_WAY
,
127 { AUTHTYPE_KERBEROS_V5
, AUTH_WHO_CLIENT
|AUTH_HOW_MUTUAL
,
133 kerberos5_printsub
},
134 # endif /* ENCRYPTION */
135 { AUTHTYPE_KERBEROS_V5
, AUTH_WHO_CLIENT
|AUTH_HOW_ONE_WAY
,
141 kerberos5_printsub
},
144 { AUTHTYPE_RSA_ENCPWD
, AUTH_WHO_CLIENT
|AUTH_HOW_ONE_WAY
,
150 rsaencpwd_printsub
},
153 { AUTHTYPE_SRA
, AUTH_WHO_CLIENT
|AUTH_HOW_ONE_WAY
,
162 { 0, 0, 0, 0, 0, 0, 0, 0 },
165 static Authenticator NoAuth
= { .type
= 0 };
167 static int i_support
= 0;
168 static int i_wont_support
= 0;
171 findauthenticator(int type
, int way
)
173 Authenticator
*ap
= authenticators
;
175 while (ap
->type
&& (ap
->type
!= type
|| ap
->way
!= way
))
177 return(ap
->type
? ap
: 0);
181 auth_init(const char *name
, int server
)
183 Authenticator
*ap
= authenticators
;
192 if (!ap
->init
|| (*ap
->init
)(ap
, server
)) {
193 i_support
|= typemask(ap
->type
);
195 printf(">>>%s: I support auth type %d %d\r\n",
199 else if (auth_debug_mode
)
200 printf(">>>%s: Init failed: auth type %d %d\r\n",
201 Name
, ap
->type
, ap
->way
);
207 auth_disable_name(char *name
)
210 for (x
= 0; x
< AUTHTYPE_CNT
; ++x
) {
211 if (AUTHTYPE_NAME(x
) && !strcasecmp(name
, AUTHTYPE_NAME(x
))) {
212 i_wont_support
|= typemask(x
);
219 getauthmask(char *type
, int *maskp
)
223 if (AUTHTYPE_NAME(0) && !strcasecmp(type
, AUTHTYPE_NAME(0))) {
228 for (x
= 1; x
< AUTHTYPE_CNT
; ++x
) {
229 if (AUTHTYPE_NAME(x
) && !strcasecmp(type
, AUTHTYPE_NAME(x
))) {
230 *maskp
= typemask(x
);
238 auth_enable(char *type
)
240 return(auth_onoff(type
, 1));
244 auth_disable(char *type
)
246 return(auth_onoff(type
, 0));
250 auth_onoff(char *type
, int on
)
255 if (!strcasecmp(type
, "?") || !strcasecmp(type
, "help")) {
256 printf("auth %s 'type'\n", on
? "enable" : "disable");
257 printf("Where 'type' is one of:\n");
258 printf("\t%s\n", AUTHTYPE_NAME(0));
260 for (ap
= authenticators
; ap
->type
; ap
++) {
261 if ((mask
& (i
= typemask(ap
->type
))) != 0)
264 printf("\t%s\n", AUTHTYPE_NAME(ap
->type
));
269 if (!getauthmask(type
, &mask
)) {
270 printf("%s: invalid authentication type\n", type
);
274 i_wont_support
&= ~mask
;
276 i_wont_support
|= mask
;
281 auth_togdebug(int on
)
284 auth_debug_mode
^= 1;
286 auth_debug_mode
= on
;
287 printf("auth debugging %s\n", auth_debug_mode
? "enabled" : "disabled");
297 if (i_wont_support
== -1)
298 printf("Authentication disabled\n");
300 printf("Authentication enabled\n");
303 for (ap
= authenticators
; ap
->type
; ap
++) {
304 if ((mask
& (i
= typemask(ap
->type
))) != 0)
307 printf("%s: %s\n", AUTHTYPE_NAME(ap
->type
),
308 (i_wont_support
& typemask(ap
->type
)) ?
309 "disabled" : "enabled");
315 * This routine is called by the server to start authentication
321 static unsigned char str_request
[64] = { IAC
, SB
,
322 TELOPT_AUTHENTICATION
,
324 Authenticator
*ap
= authenticators
;
325 unsigned char *e
= str_request
+ 4;
327 if (!authenticating
) {
330 if (i_support
& ~i_wont_support
& typemask(ap
->type
)) {
331 if (auth_debug_mode
) {
332 printf(">>>%s: Sending type %d %d\r\n",
333 Name
, ap
->type
, ap
->way
);
342 telnet_net_write(str_request
, e
- str_request
);
343 printsub('>', &str_request
[2], e
- str_request
- 2);
348 * This is called when an AUTH SEND is received.
349 * It should never arrive on the server side (as only the server can
350 * send an AUTH SEND).
351 * You should probably respond to it if you can...
353 * If you want to respond to the types out of order (i.e. even
354 * if he sends LOGIN KERBEROS and you support both, you respond
355 * with KERBEROS instead of LOGIN (which is against what the
356 * protocol says)) you will have to hack this code...
359 auth_send(unsigned char *data
, int cnt
)
362 static unsigned char str_none
[] = { IAC
, SB
, TELOPT_AUTHENTICATION
,
363 TELQUAL_IS
, AUTHTYPE_NULL
, 0,
366 if (auth_debug_mode
) {
367 printf(">>>%s: auth_send called!\r\n", Name
);
372 if (auth_debug_mode
) {
373 printf(">>>%s: auth_send got:", Name
);
374 printd(data
, cnt
); printf("\r\n");
378 * Save the data, if it is new, so that we can continue looking
379 * at it if the authorization we try doesn't work
381 if (data
< _auth_send_data
||
382 data
> _auth_send_data
+ sizeof(_auth_send_data
)) {
383 auth_send_cnt
= (size_t)cnt
> sizeof(_auth_send_data
)
384 ? sizeof(_auth_send_data
)
386 memmove(_auth_send_data
, data
, auth_send_cnt
);
387 auth_send_data
= _auth_send_data
;
390 * This is probably a no-op, but we just make sure
392 auth_send_data
= data
;
395 while ((auth_send_cnt
-= 2) >= 0) {
397 printf(">>>%s: He supports %d\r\n",
398 Name
, *auth_send_data
);
399 if ((i_support
& ~i_wont_support
) & typemask(*auth_send_data
)) {
400 ap
= findauthenticator(auth_send_data
[0],
402 if (ap
&& ap
->send
) {
404 printf(">>>%s: Trying %d %d\r\n",
405 Name
, auth_send_data
[0],
407 if ((*ap
->send
)(ap
)) {
409 * Okay, we found one we like
411 * we can go home now.
414 printf(">>>%s: Using type %d\r\n",
415 Name
, *auth_send_data
);
421 * just continue on and look for the
422 * next one if we didn't do anything.
427 telnet_net_write(str_none
, sizeof(str_none
));
428 printsub('>', &str_none
[2], sizeof(str_none
) - 2);
430 printf(">>>%s: Sent failure message\r\n", Name
);
431 auth_finished(0, AUTH_REJECT
);
434 * We requested strong authentication, however no mechanisms worked.
435 * Therefore, exit on client end.
437 printf("Unable to securely authenticate user ... exit\n");
443 auth_send_retry(void)
446 * if auth_send_cnt <= 0 then auth_send will end up rejecting
447 * the authentication and informing the other side of this.
449 auth_send(auth_send_data
, auth_send_cnt
);
453 auth_is(unsigned char *data
, int cnt
)
460 if (data
[0] == AUTHTYPE_NULL
) {
461 auth_finished(0, AUTH_REJECT
);
465 if ((ap
= findauthenticator(data
[0], data
[1])) != NULL
) {
467 (*ap
->is
)(ap
, data
+2, cnt
-2);
468 } else if (auth_debug_mode
)
469 printf(">>>%s: Invalid authentication in IS: %d\r\n",
474 auth_reply(unsigned char *data
, int cnt
)
481 if ((ap
= findauthenticator(data
[0], data
[1])) != NULL
) {
483 (*ap
->reply
)(ap
, data
+2, cnt
-2);
484 } else if (auth_debug_mode
)
485 printf(">>>%s: Invalid authentication in SEND: %d\r\n",
490 auth_name(unsigned char *data
, int cnt
)
492 unsigned char savename
[256];
496 printf(">>>%s: Empty name in NAME\r\n", Name
);
499 if ((size_t)cnt
> sizeof(savename
) - 1) {
501 printf(">>>%s: Name in NAME (%d) exceeds %ld length\r\n",
502 Name
, cnt
, (long)sizeof(savename
)-1);
505 memmove((void *)savename
, (void *)data
, cnt
);
506 savename
[cnt
] = '\0'; /* Null terminate */
508 printf(">>>%s: Got NAME [%s]\r\n", Name
, savename
);
509 auth_encrypt_user(savename
);
513 auth_sendname(unsigned char *cp
, int len
)
515 static unsigned char str_request
[256+6]
516 = { IAC
, SB
, TELOPT_AUTHENTICATION
, TELQUAL_NAME
, };
517 register unsigned char *e
= str_request
+ 4;
518 register unsigned char *ee
= &str_request
[sizeof(str_request
)-2];
521 if ((*e
++ = *cp
++) == IAC
)
528 telnet_net_write(str_request
, e
- str_request
);
529 printsub('>', &str_request
[2], e
- &str_request
[2]);
534 auth_finished(Authenticator
*ap
, int result
)
536 if (!(authenticated
= ap
))
537 authenticated
= &NoAuth
;
545 auth_finished(0, AUTH_REJECT
);
549 auth_wait(char *name
, size_t l
)
552 printf(">>>%s: in auth_wait.\r\n", Name
);
554 if (Server
&& !authenticating
)
557 (void) signal(SIGALRM
, auth_intr
);
559 while (!authenticated
)
563 (void) signal(SIGALRM
, SIG_DFL
);
566 * Now check to see if the user is valid or not
568 if (!authenticated
|| authenticated
== &NoAuth
)
571 if (validuser
== AUTH_VALID
)
572 validuser
= AUTH_USER
;
574 if (authenticated
->status
)
575 validuser
= (*authenticated
->status
)(authenticated
,
583 auth_debug_mode
= mode
;
587 auth_printsub(unsigned char *data
, int cnt
, unsigned char *buf
, int buflen
)
591 if ((ap
= findauthenticator(data
[1], data
[2])) && ap
->printsub
)
592 (*ap
->printsub
)(data
, cnt
, buf
, buflen
);
594 auth_gen_printsub(data
, cnt
, buf
, buflen
);
598 auth_gen_printsub(unsigned char *data
, int cnt
, unsigned char *buf
, int buflen
)
600 register unsigned char *cp
;
601 unsigned char tbuf
[16];
605 buf
[buflen
-1] = '\0';
608 for (; cnt
> 0; cnt
--, data
++) {
609 snprintf((char *)tbuf
, sizeof(tbuf
), " %d", *data
);
610 for (cp
= tbuf
; *cp
&& buflen
> 0; --buflen
)