* Copyright (c) 1991 The Regents of the University of California.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
static char sccsid
[] = "@(#)auth.c 5.2 (Berkeley) 3/22/91";
* Copyright (C) 1990 by the Massachusetts Institute of Technology
* Export of this software from the United States of America is assumed
* to require a specific license from the United States Government.
* It is the responsibility of any person or organization contemplating
* export to obtain such a license before exporting.
* WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
* distribute this software and its documentation for any purpose and
* without fee is hereby granted, provided that the above copyright
* notice appear in all copies and that both that copyright notice and
* this permission notice appear in supporting documentation, and that
* the name of M.I.T. not be used in advertising or publicity pertaining
* to distribution of the software without specific, written prior
* permission. M.I.T. makes no representations about the suitability of
* this software for any purpose. It is provided "as is" without express
#if defined(AUTHENTICATE)
#define typemask(x) (1<<((x)-1))
static char *Name
= "Noname";
static Authenticator
*authenticated
= 0;
static int authenticating
= 0;
static int validuser
= 0;
static unsigned char _auth_send_data
[256];
static unsigned char *auth_send_data
;
static int auth_send_cnt
= 0;
* Authentication types supported. Plese note that these are stored
* in priority order, i.e. try the first one first.
Authenticator authenticators
[] = {
{ AUTHTYPE_KERBEROS_V5
, AUTH_WHO_CLIENT
|AUTH_HOW_MUTUAL
,
{ AUTHTYPE_KERBEROS_V5
, AUTH_WHO_CLIENT
|AUTH_HOW_ONE_WAY
,
{ AUTHTYPE_KERBEROS_V4
, AUTH_WHO_CLIENT
|AUTH_HOW_MUTUAL
,
{ AUTHTYPE_KERBEROS_V4
, AUTH_WHO_CLIENT
|AUTH_HOW_ONE_WAY
,
static Authenticator NoAuth
= { 0 };
static int i_support
= 0;
static int i_wont_support
= 0;
findauthenticator(type
, way
)
Authenticator
*ap
= authenticators
;
while (ap
->type
&& (ap
->type
!= type
|| ap
->way
!= way
))
return(ap
->type
? ap
: 0);
Authenticator
*ap
= authenticators
;
if (!ap
->init
|| (*ap
->init
)(ap
, server
)) {
i_support
|= typemask(ap
->type
);
printf(">>>%s: I support auth type %d %d\r\n",
for (x
= 0; x
< AUTHTYPE_CNT
; ++x
) {
if (!strcasecmp(name
, AUTHTYPE_NAME(x
))) {
i_wont_support
|= typemask(x
);
if (strcasecmp(type
, AUTHTYPE_NAME(0))) {
for (x
= 1; x
< AUTHTYPE_CNT
; ++x
) {
if (!strcasecmp(type
, AUTHTYPE_NAME(x
))) {
return(auth_onoff(type
, 1));
return(auth_onoff(type
, 0));
if (!strcasecmp(type
, "?") || !strcasecmp(type
, "help")) {
printf("auth %s 'type'\n", on
? "enable" : "disable");
printf("Where 'type' is one of:\n");
printf("\t%s\n", AUTHTYPE_NAME(0));
for (ap
= authenticators
; ap
->type
; ap
++)
printf("\t%s\n", AUTHTYPE_NAME(ap
->type
));
if (!getauthmask(type
, &mask
)) {
printf("%s: invalid authentication type\n", type
);
mask
= getauthmask(type
, &mask
);
printf("auth debugging %s\n", auth_debug_mode
? "enabled" : "disabled");
if (i_wont_support
== -1)
printf("Authentication disabled\n");
printf("Authentication enabled\n");
for (ap
= authenticators
; ap
->type
; ap
++)
printf("%s: %s\n", AUTHTYPE_NAME(ap
->type
),
(i_wont_support
& typemask(ap
->type
)) ?
* This routine is called by the server to start authentication
static unsigned char str_request
[64] = { IAC
, SB
,
Authenticator
*ap
= authenticators
;
unsigned char *e
= str_request
+ 4;
if (i_support
& ~i_wont_support
& typemask(ap
->type
)) {
printf(">>>%s: Sending type %d %d\r\n",
Name
, ap
->type
, ap
->way
);
net_write(str_request
, e
- str_request
);
printsub('>', &str_request
[2], e
- str_request
- 2);
* This is called when an AUTH SEND is received.
* It should never arrive on the server side (as only the server can
* You should probably respond to it if you can...
* If you want to respond to the types out of order (i.e. even
* if he sends LOGIN KERBEROS and you support both, you respond
* with KERBEROS instead of LOGIN (which is against what the
* protocol says)) you will have to hack this code...
static unsigned char str_none
[] = { IAC
, SB
, TELOPT_AUTHENTICATION
,
TELQUAL_IS
, AUTHTYPE_NULL
, 0,
printf(">>>%s: auth_send called!\r\n", Name
);
printf(">>>%s: auth_send got:", Name
);
printd(data
, cnt
); printf("\r\n");
* Save the data, if it is new, so that we can continue looking
* at it if the authorization we try doesn't work
if (data
< _auth_send_data
||
data
> _auth_send_data
+ sizeof(_auth_send_data
)) {
auth_send_cnt
= cnt
> sizeof(_auth_send_data
)
? sizeof(_auth_send_data
)
bcopy((void *)data
, (void *)_auth_send_data
, auth_send_cnt
);
auth_send_data
= _auth_send_data
;
* This is probably a no-op, but we just make sure
while ((auth_send_cnt
-= 2) >= 0) {
printf(">>>%s: He supports %d\r\n",
if ((i_support
& ~i_wont_support
) & typemask(*auth_send_data
)) {
ap
= findauthenticator(auth_send_data
[0],
printf("Internal state error: cannot find authentication type %d a second time\r\n", *auth_send_data
);
printf(">>>%s: Trying %d %d\r\n",
* Okay, we found one we like
printf(">>>%s: Using type %d\r\n",
* just continue on and look for the
* next one if we didn't do anything.
net_write(str_none
, sizeof(str_none
));
printsub('>', &str_none
[2], sizeof(str_none
) - 2);
printf(">>>%s: Sent failure message\r\n", Name
);
auth_finished(0, AUTH_REJECT
);
* if auth_send_cnt <= 0 then auth_send will end up rejecting
* the authentication and informing the other side of this.
auth_send(auth_send_data
, auth_send_cnt
);
if (data
[0] == AUTHTYPE_NULL
) {
auth_finished(0, AUTH_REJECT
);
if (ap
= findauthenticator(data
[0], data
[1])) {
(*ap
->is
)(ap
, data
+2, cnt
-2);
} else if (auth_debug_mode
)
printf(">>>%s: Invalid authentication in IS: %d\r\n",
if (ap
= findauthenticator(data
[0], data
[1])) {
(*ap
->reply
)(ap
, data
+2, cnt
-2);
} else if (auth_debug_mode
)
printf(">>>%s: Invalid authentication in SEND: %d\r\n",
unsigned char savename
[256];
printf(">>>%s: Empty name in NAME\r\n", Name
);
if (cnt
> sizeof(savename
) - 1) {
printf(">>>%s: Name in NAME (%d) exceeds %d length\r\n",
Name
, cnt
, sizeof(savename
)-1);
bcopy((void *)data
, (void *)savename
, cnt
);
savename
[cnt
] = '\0'; /* Null terminate */
printf(">>>%s: Got NAME [%s]\r\n", Name
, savename
);
auth_encrypt_user(savename
);
static unsigned char str_request
[256+6]
= { IAC
, SB
, TELOPT_AUTHENTICATION
, TELQUAL_NAME
, };
register unsigned char *e
= str_request
+ 4;
register unsigned char *ee
= &str_request
[sizeof(str_request
)-2];
if ((*e
++ = *cp
++) == IAC
)
net_write(str_request
, e
- str_request
);
printsub('>', &str_request
[2], e
- &str_request
[2]);
auth_finished(ap
, result
)
if (!(authenticated
= ap
))
auth_finished(0, AUTH_REJECT
);
printf(">>>%s: in auth_wait.\r\n", Name
);
if (Server
&& !authenticating
)
(void) signal(SIGALRM
, auth_intr
);
(void) signal(SIGALRM
, SIG_DFL
);
* Now check to see if the user is valid or not
if (!authenticated
|| authenticated
== &NoAuth
)
if (validuser
== AUTH_VALID
)
if (authenticated
->status
)
validuser
= (*authenticated
->status
)(authenticated
,
auth_printsub(data
, cnt
, buf
, buflen
)
unsigned char *data
, *buf
;
if ((ap
= findauthenticator(data
[1], data
[2])) && ap
->printsub
)
(*ap
->printsub
)(data
, cnt
, buf
, buflen
);
auth_gen_printsub(data
, cnt
, buf
, buflen
);
auth_gen_printsub(data
, cnt
, buf
, buflen
)
unsigned char *data
, *buf
;
register unsigned char *cp
;
for (; cnt
> 0; cnt
--, data
++) {
sprintf((char *)tbuf
, " %d", *data
);
for (cp
= tbuf
; *cp
&& buflen
> 0; --buflen
)