1 /* $NetBSD: auth.c,v 1.18 2005/02/19 21:55:52 christos 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.18 2005/02/19 21:55:52 christos 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
= { 0 };
167 static int i_support
= 0;
168 static int i_wont_support
= 0;
171 findauthenticator(type
, way
)
175 Authenticator
*ap
= authenticators
;
177 while (ap
->type
&& (ap
->type
!= type
|| ap
->way
!= way
))
179 return(ap
->type
? ap
: 0);
183 auth_init(name
, server
)
187 Authenticator
*ap
= authenticators
;
196 if (!ap
->init
|| (*ap
->init
)(ap
, server
)) {
197 i_support
|= typemask(ap
->type
);
199 printf(">>>%s: I support auth type %d %d\r\n",
203 else if (auth_debug_mode
)
204 printf(">>>%s: Init failed: auth type %d %d\r\n",
205 Name
, ap
->type
, ap
->way
);
211 auth_disable_name(name
)
215 for (x
= 0; x
< AUTHTYPE_CNT
; ++x
) {
216 if (AUTHTYPE_NAME(x
) && !strcasecmp(name
, AUTHTYPE_NAME(x
))) {
217 i_wont_support
|= typemask(x
);
224 getauthmask(type
, maskp
)
230 if (AUTHTYPE_NAME(0) && !strcasecmp(type
, AUTHTYPE_NAME(0))) {
235 for (x
= 1; x
< AUTHTYPE_CNT
; ++x
) {
236 if (AUTHTYPE_NAME(x
) && !strcasecmp(type
, AUTHTYPE_NAME(x
))) {
237 *maskp
= typemask(x
);
248 return(auth_onoff(type
, 1));
255 return(auth_onoff(type
, 0));
266 if (!strcasecmp(type
, "?") || !strcasecmp(type
, "help")) {
267 printf("auth %s 'type'\n", on
? "enable" : "disable");
268 printf("Where 'type' is one of:\n");
269 printf("\t%s\n", AUTHTYPE_NAME(0));
271 for (ap
= authenticators
; ap
->type
; ap
++) {
272 if ((mask
& (i
= typemask(ap
->type
))) != 0)
275 printf("\t%s\n", AUTHTYPE_NAME(ap
->type
));
280 if (!getauthmask(type
, &mask
)) {
281 printf("%s: invalid authentication type\n", type
);
285 i_wont_support
&= ~mask
;
287 i_wont_support
|= mask
;
296 auth_debug_mode
^= 1;
298 auth_debug_mode
= on
;
299 printf("auth debugging %s\n", auth_debug_mode
? "enabled" : "disabled");
310 if (i_wont_support
== -1)
311 printf("Authentication disabled\n");
313 printf("Authentication enabled\n");
316 for (ap
= authenticators
; ap
->type
; ap
++) {
317 if ((mask
& (i
= typemask(ap
->type
))) != 0)
320 printf("%s: %s\n", AUTHTYPE_NAME(ap
->type
),
321 (i_wont_support
& typemask(ap
->type
)) ?
322 "disabled" : "enabled");
328 * This routine is called by the server to start authentication
334 static unsigned char str_request
[64] = { IAC
, SB
,
335 TELOPT_AUTHENTICATION
,
337 Authenticator
*ap
= authenticators
;
338 unsigned char *e
= str_request
+ 4;
340 if (!authenticating
) {
343 if (i_support
& ~i_wont_support
& typemask(ap
->type
)) {
344 if (auth_debug_mode
) {
345 printf(">>>%s: Sending type %d %d\r\n",
346 Name
, ap
->type
, ap
->way
);
355 telnet_net_write(str_request
, e
- str_request
);
356 printsub('>', &str_request
[2], e
- str_request
- 2);
361 * This is called when an AUTH SEND is received.
362 * It should never arrive on the server side (as only the server can
363 * send an AUTH SEND).
364 * You should probably respond to it if you can...
366 * If you want to respond to the types out of order (i.e. even
367 * if he sends LOGIN KERBEROS and you support both, you respond
368 * with KERBEROS instead of LOGIN (which is against what the
369 * protocol says)) you will have to hack this code...
377 static unsigned char str_none
[] = { IAC
, SB
, TELOPT_AUTHENTICATION
,
378 TELQUAL_IS
, AUTHTYPE_NULL
, 0,
381 if (auth_debug_mode
) {
382 printf(">>>%s: auth_send called!\r\n", Name
);
387 if (auth_debug_mode
) {
388 printf(">>>%s: auth_send got:", Name
);
389 printd(data
, cnt
); printf("\r\n");
393 * Save the data, if it is new, so that we can continue looking
394 * at it if the authorization we try doesn't work
396 if (data
< _auth_send_data
||
397 data
> _auth_send_data
+ sizeof(_auth_send_data
)) {
398 auth_send_cnt
= cnt
> sizeof(_auth_send_data
)
399 ? sizeof(_auth_send_data
)
401 memmove((void *)_auth_send_data
, (void *)data
, auth_send_cnt
);
402 auth_send_data
= _auth_send_data
;
405 * This is probably a no-op, but we just make sure
407 auth_send_data
= data
;
410 while ((auth_send_cnt
-= 2) >= 0) {
412 printf(">>>%s: He supports %d\r\n",
413 Name
, *auth_send_data
);
414 if ((i_support
& ~i_wont_support
) & typemask(*auth_send_data
)) {
415 ap
= findauthenticator(auth_send_data
[0],
417 if (ap
&& ap
->send
) {
419 printf(">>>%s: Trying %d %d\r\n",
420 Name
, auth_send_data
[0],
422 if ((*ap
->send
)(ap
)) {
424 * Okay, we found one we like
426 * we can go home now.
429 printf(">>>%s: Using type %d\r\n",
430 Name
, *auth_send_data
);
436 * just continue on and look for the
437 * next one if we didn't do anything.
442 telnet_net_write(str_none
, sizeof(str_none
));
443 printsub('>', &str_none
[2], sizeof(str_none
) - 2);
445 printf(">>>%s: Sent failure message\r\n", Name
);
446 auth_finished(0, AUTH_REJECT
);
449 * We requested strong authentication, however no mechanisms worked.
450 * Therefore, exit on client end.
452 printf("Unable to securely authenticate user ... exit\n");
461 * if auth_send_cnt <= 0 then auth_send will end up rejecting
462 * the authentication and informing the other side of this.
464 auth_send(auth_send_data
, auth_send_cnt
);
477 if (data
[0] == AUTHTYPE_NULL
) {
478 auth_finished(0, AUTH_REJECT
);
482 if ((ap
= findauthenticator(data
[0], data
[1])) != NULL
) {
484 (*ap
->is
)(ap
, data
+2, cnt
-2);
485 } else if (auth_debug_mode
)
486 printf(">>>%s: Invalid authentication in IS: %d\r\n",
491 auth_reply(data
, cnt
)
500 if ((ap
= findauthenticator(data
[0], data
[1])) != NULL
) {
502 (*ap
->reply
)(ap
, data
+2, cnt
-2);
503 } else if (auth_debug_mode
)
504 printf(">>>%s: Invalid authentication in SEND: %d\r\n",
513 unsigned char savename
[256];
517 printf(">>>%s: Empty name in NAME\r\n", Name
);
520 if (cnt
> sizeof(savename
) - 1) {
522 printf(">>>%s: Name in NAME (%d) exceeds %ld length\r\n",
523 Name
, cnt
, (long)sizeof(savename
)-1);
526 memmove((void *)savename
, (void *)data
, cnt
);
527 savename
[cnt
] = '\0'; /* Null terminate */
529 printf(">>>%s: Got NAME [%s]\r\n", Name
, savename
);
530 auth_encrypt_user(savename
);
534 auth_sendname(cp
, len
)
538 static unsigned char str_request
[256+6]
539 = { IAC
, SB
, TELOPT_AUTHENTICATION
, TELQUAL_NAME
, };
540 register unsigned char *e
= str_request
+ 4;
541 register unsigned char *ee
= &str_request
[sizeof(str_request
)-2];
544 if ((*e
++ = *cp
++) == IAC
)
551 telnet_net_write(str_request
, e
- str_request
);
552 printsub('>', &str_request
[2], e
- &str_request
[2]);
557 auth_finished(ap
, result
)
561 if (!(authenticated
= ap
))
562 authenticated
= &NoAuth
;
571 auth_finished(0, AUTH_REJECT
);
580 printf(">>>%s: in auth_wait.\r\n", Name
);
582 if (Server
&& !authenticating
)
585 (void) signal(SIGALRM
, auth_intr
);
587 while (!authenticated
)
591 (void) signal(SIGALRM
, SIG_DFL
);
594 * Now check to see if the user is valid or not
596 if (!authenticated
|| authenticated
== &NoAuth
)
599 if (validuser
== AUTH_VALID
)
600 validuser
= AUTH_USER
;
602 if (authenticated
->status
)
603 validuser
= (*authenticated
->status
)(authenticated
,
612 auth_debug_mode
= mode
;
616 auth_printsub(data
, cnt
, buf
, buflen
)
617 unsigned char *data
, *buf
;
622 if ((ap
= findauthenticator(data
[1], data
[2])) && ap
->printsub
)
623 (*ap
->printsub
)(data
, cnt
, buf
, buflen
);
625 auth_gen_printsub(data
, cnt
, buf
, buflen
);
629 auth_gen_printsub(data
, cnt
, buf
, buflen
)
630 unsigned char *data
, *buf
;
633 register unsigned char *cp
;
634 unsigned char tbuf
[16];
638 buf
[buflen
-1] = '\0';
641 for (; cnt
> 0; cnt
--, data
++) {
642 snprintf((char *)tbuf
, sizeof(tbuf
), " %d", *data
);
643 for (cp
= tbuf
; *cp
&& buflen
> 0; --buflen
)