* Copyright (c) 1991 The Regents of the University of California.
* %sccs.include.redist.c%
static char sccsid
[] = "@(#)auth.c 5.1 (Berkeley) %G%";
* 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 char valid_name
[256];
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_ONE_WAY
,
{ AUTHTYPE_KERBEROS_V4
, AUTH_WHO_CLIENT
|AUTH_HOW_ONE_WAY
,
{ AUTHTYPE_TEST
, 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\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\r\n",
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\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",
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
)