2 * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
6 #pragma ident "%Z%%M% %I% %E% SMI"
9 * usr/src/cmd/cmd-inet/usr.bin/telnet/auth.c
13 * Copyright (c) 1991, 1993
14 * The Regents of the University of California. All rights reserved.
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. All advertising materials mentioning features or use of this software
25 * must display the following acknowledgement:
26 * This product includes software developed by the University of
27 * California, Berkeley and its contributors.
28 * 4. Neither the name of the University nor the names of its contributors
29 * may be used to endorse or promote products derived from this software
30 * without specific prior written permission.
32 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
33 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
34 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
35 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
36 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
40 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
41 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
45 /* based on @(#)auth.c 8.1 (Berkeley) 6/4/93 */
48 * Copyright (C) 1990 by the Massachusetts Institute of Technology
50 * Export of this software from the United States of America may
51 * require a specific license from the United States Government.
52 * It is the responsibility of any person or organization contemplating
53 * export to obtain such a license before exporting.
55 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
56 * distribute this software and its documentation for any purpose and
57 * without fee is hereby granted, provided that the above copyright
58 * notice appear in all copies and that both that copyright notice and
59 * this permission notice appear in supporting documentation, and that
60 * the name of M.I.T. not be used in advertising or publicity pertaining
61 * to distribution of the software without specific, written prior
62 * permission. Furthermore if you modify this software you must label
63 * your software as modified software and not distribute it in such a
64 * fashion that it might be confused with the original M.I.T. software.
65 * M.I.T. makes no representations about the suitability of
66 * this software for any purpose. It is provided "as is" without express
67 * or implied warranty.
72 #include <sys/types.h>
75 #define AUTHTYPE_NAMES /* this is needed for arpa/telnet.h */
76 #include <arpa/telnet.h>
88 #define typemask(x) ((x) > 0 ? 1 << ((x)-1) : 0)
90 static int auth_onoff(const char *type
, boolean_t on
);
91 static void auth_gen_printsub(uchar_t
*, uint_t
, uchar_t
*, uint_t
);
93 boolean_t auth_debug_mode
= B_FALSE
;
94 boolean_t auth_has_failed
= B_FALSE
;
95 boolean_t auth_enable_encrypt
= B_FALSE
;
97 static char *Name
= "Noname";
98 static Authenticator
*authenticated
= NULL
;
99 static uchar_t _auth_send_data
[BUFSIZ
];
100 static uchar_t
*auth_send_data
;
101 static int auth_send_cnt
= 0;
104 * Authentication types supported. Note that these are stored
105 * in priority order, i.e. try the first one first.
107 static Authenticator authenticators
[] = {
108 { AUTHTYPE_KERBEROS_V5
,
109 AUTH_WHO_CLIENT
|AUTH_HOW_MUTUAL
|AUTH_ENCRYPT_ON
,
114 kerberos5_printsub
},
115 { AUTHTYPE_KERBEROS_V5
, AUTH_WHO_CLIENT
|AUTH_HOW_MUTUAL
,
120 kerberos5_printsub
},
121 { AUTHTYPE_KERBEROS_V5
, AUTH_WHO_CLIENT
|AUTH_HOW_ONE_WAY
,
126 kerberos5_printsub
},
130 static Authenticator NoAuth
= { 0 };
132 static uint_t i_support
= 0;
133 static uint_t i_wont_support
= 0;
136 * Traverse the Authenticator array until we find the authentication type
137 * and matching direction we are looking for. Return a pointer into the
138 * Authenticator type array.
140 * Returns: 0 - type not found (error)
141 * nonzero - pointer to authenticator
143 static Authenticator
*
144 findauthenticator(int type
, int way
)
146 Authenticator
*ap
= authenticators
;
148 while (ap
->type
&& (ap
->type
!= type
|| ap
->way
!= way
))
150 return (ap
->type
? ap
: NULL
);
154 * For each authentication type in the Authenticator array,
155 * call the associated init routine, and update the i_support bitfield.
158 auth_init(const char *name
)
160 Authenticator
*ap
= authenticators
;
162 Name
= name
? strdup(name
) : "Noname";
165 authenticated
= NULL
;
167 if (!ap
->init
|| (*ap
->init
)(ap
)) {
168 i_support
|= typemask(ap
->type
);
170 (void) printf(gettext
171 (">>>%s: I support auth type %d %d\r\n"),
172 Name
, ap
->type
, ap
->way
);
179 * Search the Authenticator array for the authentication type 'name',
180 * and disable this type by updating the i_wont_support bitfield.
183 auth_disable_name(const char *name
)
186 for (x
= 0; x
< AUTHTYPE_CNT
; ++x
) {
187 if (!strcasecmp(name
, AUTHTYPE_NAME(x
))) {
188 i_wont_support
|= typemask(x
);
195 gettext("%s : invalid authentication type\n"),
200 * Search the Authenticator array for the authentication type given
201 * by the character string 'type', and return its integer bitmask
204 * Returns: 1 - no error
205 * 0 - type not found (error)
208 getauthmask(const char *type
, uint_t
*maskp
)
212 if (!strcasecmp(type
, AUTHTYPE_NAME(0))) {
217 for (x
= 1; x
< AUTHTYPE_CNT
; ++x
) {
218 if (!strcasecmp(type
, AUTHTYPE_NAME(x
))) {
219 *maskp
= typemask(x
);
227 auth_enable(char *type
)
229 return (auth_onoff(type
, B_TRUE
));
233 auth_disable(char *type
)
235 return (auth_onoff(type
, B_FALSE
));
239 * Responds to the 'auth enable <option>' and 'auth disable <option>' commands.
242 * - a valid authentication type, turns support on / off
243 * - "?" or "help", print a usage message
244 * - not recognized, print an error message.
246 * Returns: 1 - no error, authentication is enabled or disabled
247 * 0 - error, or help requested
250 auth_onoff(const char *type
, boolean_t on
)
255 if (!strcasecmp(type
, "?") || !strcasecmp(type
, "help")) {
257 gettext("auth enable 'type'\n") :
258 gettext("auth disable 'type'\n"));
260 gettext("Where 'type' is one of:\n"));
261 (void) printf("\t%s\n", AUTHTYPE_NAME(0));
262 for (ap
= authenticators
; ap
->type
; ap
++) {
263 if ((mask
& (i
= typemask(ap
->type
))) != 0)
266 (void) printf("\t%s\n", AUTHTYPE_NAME(ap
->type
));
271 if (!getauthmask(type
, &mask
)) {
273 gettext("%s: invalid authentication type\n"), type
);
277 i_wont_support
&= ~mask
;
279 i_wont_support
|= mask
;
284 * Responds to the 'toggle authdebug' command.
286 * Returns: 1 - always
289 auth_togdebug(int on
)
292 auth_debug_mode
= !auth_debug_mode
;
294 auth_debug_mode
= on
> 0 ? B_TRUE
: B_FALSE
;
295 (void) printf(auth_debug_mode
?
296 gettext("auth debugging enabled\n") :
297 gettext("auth debugging disabled\n"));
302 * Responds to the 'auth status' command.
303 * Traverses the authenticator array and prints enabled or disabled for
304 * each authentication type, depencing on the i_wont_support bitfield.
306 * Returns: 1 - always
314 if (i_wont_support
== (uint_t
)-1)
315 (void) printf(gettext("Authentication disabled\n"));
317 (void) printf(gettext("Authentication enabled\n"));
320 for (ap
= authenticators
; ap
->type
; ap
++) {
321 if ((mask
& (i
= typemask(ap
->type
))) != 0)
324 (void) printf("%s: %s\n", AUTHTYPE_NAME(ap
->type
),
325 (i_wont_support
& typemask(ap
->type
)) ?
326 gettext("disabled") : gettext("enabled"));
332 * This is called when an AUTH SEND is received.
333 * data is a list of authentication mechanisms we support
336 auth_send(uchar_t
*data
, int cnt
)
339 if (auth_debug_mode
) {
340 (void) printf(gettext(">>>%s: auth_send got:"), Name
);
342 (void) printf("\r\n");
346 * Save the list of authentication mechanisms
349 if (auth_send_cnt
> sizeof (_auth_send_data
))
350 auth_send_cnt
= sizeof (_auth_send_data
);
351 (void) memcpy((void *)_auth_send_data
, (void *)data
, auth_send_cnt
);
352 auth_send_data
= _auth_send_data
;
358 * Try the next authentication mechanism on the list, and see if it
362 auth_send_retry(void)
365 static uchar_t str_none
[] = { IAC
, SB
, TELOPT_AUTHENTICATION
,
366 TELQUAL_IS
, AUTHTYPE_NULL
, 0, IAC
, SE
};
368 for (; (auth_send_cnt
-= 2) >= 0; auth_send_data
+= 2) {
371 gettext(">>>%s: Remote host supports %d\r\n"),
372 Name
, *auth_send_data
);
373 if (!(i_support
& typemask(*auth_send_data
)))
375 if (i_wont_support
& typemask(*auth_send_data
))
377 ap
= findauthenticator(auth_send_data
[0], auth_send_data
[1]);
378 if (!ap
|| !ap
->send
)
380 if ((ap
->way
& AUTH_ENCRYPT_MASK
) && !auth_enable_encrypt
)
385 gettext(">>>%s: Trying %d %d\r\n"), Name
,
386 auth_send_data
[0], auth_send_data
[1]);
387 if ((*ap
->send
)(ap
)) {
389 * Okay, we found one we like and did it. we can go
393 (void) printf(gettext(">>>%s: Using type %d\r\n"),
394 Name
, *auth_send_data
);
399 (void) net_write(str_none
, sizeof (str_none
));
400 printsub('>', &str_none
[2], sizeof (str_none
) - 2);
403 gettext(">>>%s: Sent failure message\r\n"), Name
);
404 auth_finished(0, AUTH_REJECT
);
405 auth_has_failed
= B_TRUE
;
409 auth_reply(uchar_t
*data
, int cnt
)
416 if (ap
= findauthenticator(data
[0], data
[1])) {
418 (*ap
->reply
)(ap
, data
+2, cnt
-2);
419 } else if (auth_debug_mode
)
420 (void) printf(gettext
421 (">>>%s: Invalid authentication in SEND: %d\r\n"),
426 auth_sendname(uchar_t
*cp
, int len
)
428 static uchar_t str_request
[AUTH_NAME_BUFSIZ
+ 6] = { IAC
, SB
,
429 TELOPT_AUTHENTICATION
, TELQUAL_NAME
, };
430 register uchar_t
*e
= str_request
+ 4;
431 register uchar_t
*ee
= &str_request
[sizeof (str_request
) - 2];
434 if ((*e
++ = *cp
++) == IAC
)
441 (void) net_write(str_request
, e
- str_request
);
442 printsub('>', &str_request
[2], e
- &str_request
[2]);
448 auth_finished(Authenticator
*ap
, int result
)
451 if (authenticated
== NULL
)
452 authenticated
= &NoAuth
;
456 auth_printsub(uchar_t
*data
, uint_t cnt
, uchar_t
*buf
, uint_t buflen
)
460 ap
= findauthenticator(data
[1], data
[2]);
461 if (ap
&& ap
->printsub
)
462 (*ap
->printsub
)(data
, cnt
, buf
, buflen
);
464 auth_gen_printsub(data
, cnt
, buf
, buflen
);
468 auth_gen_printsub(uchar_t
*data
, uint_t cnt
, uchar_t
*buf
, uint_t buflen
)
470 register uchar_t
*cp
;
471 uchar_t lbuf
[AUTH_LBUF_BUFSIZ
];
475 cnt
= (cnt
> 3) ? cnt
- 3 : 0;
477 buf
[buflen
- 1] = '\0';
478 buf
[buflen
- 2] = '*';
480 for (; cnt
> 0; cnt
--, data
++) {
481 (void) snprintf((char *)lbuf
, AUTH_LBUF_BUFSIZ
, " %d", *data
);
482 for (cp
= lbuf
; (*cp
!= '\0') && (buflen
> 0); --buflen
)