"SfR Fresh" - the SfR Freeware/Shareware Archive

Member "tn3270-5.2.0-glibc/tn3270/libtelnet/auth.c" of archive tn3270-5.2.0-glibc.tgz:


As a special service "SfR Fresh" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. That can be also achieved for any archive member file by clicking within an archive contents listing on the first character of the file(path) respectively on the according byte size field.
    1 /*-
    2  * Copyright (c) 1991 The Regents of the University of California.
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms are permitted provided
    6  * that: (1) source distributions retain this entire copyright notice and
    7  * comment, and (2) distributions including binaries display the following
    8  * acknowledgement:  ``This product includes software developed by the
    9  * University of California, Berkeley and its contributors'' in the
   10  * documentation or other materials provided with the distribution and in
   11  * all advertising materials mentioning features or use of this software.
   12  * Neither the name of the University nor the names of its contributors may
   13  * be used to endorse or promote products derived from this software without
   14  * specific prior written permission.
   15  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
   16  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
   17  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
   18  */
   19 
   20 #ifndef lint
   21 static char sccsid[] = "@(#)auth.c	5.1 (Berkeley) 2/28/91";
   22 #endif /* not lint */
   23 
   24 /*
   25  * Copyright (C) 1990 by the Massachusetts Institute of Technology
   26  *
   27  * Export of this software from the United States of America is assumed
   28  * to require a specific license from the United States Government.
   29  * It is the responsibility of any person or organization contemplating
   30  * export to obtain such a license before exporting.
   31  *
   32  * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
   33  * distribute this software and its documentation for any purpose and
   34  * without fee is hereby granted, provided that the above copyright
   35  * notice appear in all copies and that both that copyright notice and
   36  * this permission notice appear in supporting documentation, and that
   37  * the name of M.I.T. not be used in advertising or publicity pertaining
   38  * to distribution of the software without specific, written prior
   39  * permission.  M.I.T. makes no representations about the suitability of
   40  * this software for any purpose.  It is provided "as is" without express
   41  * or implied warranty.
   42  */
   43 
   44 
   45 #if	defined(AUTHENTICATE)
   46 #include <stdio.h>
   47 #include <sys/types.h>
   48 #include <signal.h>
   49 #define	AUTH_NAMES
   50 #include <arpa/telnet.h>
   51 #ifdef	__STDC__
   52 #include <stdlib.h>
   53 #endif
   54 #ifdef	NO_STRING_H
   55 #include <strings.h>
   56 #else
   57 #include <string.h>
   58 #endif
   59 
   60 #include "encrypt.h"
   61 #include "auth.h"
   62 #include "misc-proto.h"
   63 #include "auth-proto.h"
   64 
   65 #define	typemask(x)		(1<<((x)-1))
   66 
   67 int auth_debug_mode = 0;
   68 static 	char	*Name = "Noname";
   69 static	int	Server = 0;
   70 static	Authenticator	*authenticated = 0;
   71 static	int	authenticating = 0;
   72 static	int	validuser = 0;
   73 static	unsigned char	_auth_send_data[256];
   74 static	unsigned char	*auth_send_data;
   75 static	int	auth_send_cnt = 0;
   76 
   77 /*
   78  * Authentication types supported.  Plese note that these are stored
   79  * in priority order, i.e. try the first one first.
   80  */
   81 Authenticator authenticators[] = {
   82 #ifdef	KRB5
   83 	{ AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
   84 				kerberos5_init,
   85 				kerberos5_send,
   86 				kerberos5_is,
   87 				kerberos5_reply,
   88 				kerberos5_status,
   89 				kerberos5_printsub },
   90 	{ AUTHTYPE_KERBEROS_V5, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
   91 				kerberos5_init,
   92 				kerberos5_send,
   93 				kerberos5_is,
   94 				kerberos5_reply,
   95 				kerberos5_status,
   96 				kerberos5_printsub },
   97 #endif
   98 #ifdef	KRB4
   99 	{ AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_MUTUAL,
  100 				kerberos4_init,
  101 				kerberos4_send,
  102 				kerberos4_is,
  103 				kerberos4_reply,
  104 				kerberos4_status,
  105 				kerberos4_printsub },
  106 	{ AUTHTYPE_KERBEROS_V4, AUTH_WHO_CLIENT|AUTH_HOW_ONE_WAY,
  107 				kerberos4_init,
  108 				kerberos4_send,
  109 				kerberos4_is,
  110 				kerberos4_reply,
  111 				kerberos4_status,
  112 				kerberos4_printsub },
  113 #endif
  114 	{ 0, },
  115 };
  116 
  117 static Authenticator NoAuth = { 0 };
  118 
  119 static int	i_support = 0;
  120 static int	i_wont_support = 0;
  121 
  122 	Authenticator *
  123 findauthenticator(type, way)
  124 	int type;
  125 	int way;
  126 {
  127 	Authenticator *ap = authenticators;
  128 
  129 	while (ap->type && (ap->type != type || ap->way != way))
  130 		++ap;
  131 	return(ap->type ? ap : 0);
  132 }
  133 
  134 	void
  135 auth_init(name, server)
  136 	char *name;
  137 	int server;
  138 {
  139 	Authenticator *ap = authenticators;
  140 
  141 	Server = server;
  142 	Name = name;
  143 
  144 	i_support = 0;
  145 	authenticated = 0;
  146 	authenticating = 0;
  147 	while (ap->type) {
  148 		if (!ap->init || (*ap->init)(ap, server)) {
  149 			i_support |= typemask(ap->type);
  150 			if (auth_debug_mode)
  151 				printf(">>>%s: I support auth type %d %d\r\n",
  152 					Name,
  153 					ap->type, ap->way);
  154 		}
  155 		++ap;
  156 	}
  157 }
  158 
  159 	void
  160 auth_disable_name(name)
  161 	char *name;
  162 {
  163 	int x;
  164 	for (x = 0; x < AUTHTYPE_CNT; ++x) {
  165 		if (!strcasecmp(name, AUTHTYPE_NAME(x))) {
  166 			i_wont_support |= typemask(x);
  167 			break;
  168 		}
  169 	}
  170 }
  171 
  172 	int
  173 getauthmask(type, maskp)
  174 	char *type;
  175 	int *maskp;
  176 {
  177 	register int x;
  178 
  179 	if (strcasecmp(type, AUTHTYPE_NAME(0))) {
  180 		*maskp = -1;
  181 		return(1);
  182 	}
  183 
  184 	for (x = 1; x < AUTHTYPE_CNT; ++x) {
  185 		if (!strcasecmp(type, AUTHTYPE_NAME(x))) {
  186 			*maskp = typemask(x);
  187 			return(1);
  188 		}
  189 	}
  190 	return(0);
  191 }
  192 
  193 	int
  194 auth_enable(type)
  195 	int type;
  196 {
  197 	return(auth_onoff(type, 1));
  198 }
  199 
  200 	int
  201 auth_disable(type)
  202 	int type;
  203 {
  204 	return(auth_onoff(type, 0));
  205 }
  206 
  207 	int
  208 auth_onoff(type, on)
  209 	char *type;
  210 	int on;
  211 {
  212 	int mask = -1;
  213 	Authenticator *ap;
  214 
  215 	if (!strcasecmp(type, "?") || !strcasecmp(type, "help")) {
  216                 printf("auth %s 'type'\n", on ? "enable" : "disable");
  217 		printf("Where 'type' is one of:\n");
  218 		printf("\t%s\n", AUTHTYPE_NAME(0));
  219 		for (ap = authenticators; ap->type; ap++)
  220 			printf("\t%s\n", AUTHTYPE_NAME(ap->type));
  221 		return(0);
  222 	}
  223 
  224 	if (!getauthmask(type, &mask)) {
  225 		printf("%s: invalid authentication type\n", type);
  226 		return(0);
  227 	}
  228 	mask = getauthmask(type, &mask);
  229 	if (on)
  230 		i_wont_support &= ~mask;
  231 	else
  232 		i_wont_support |= mask;
  233 	return(1);
  234 }
  235 
  236 	int
  237 auth_togdebug(on)
  238 	int on;
  239 {
  240 	if (on < 0)
  241 		auth_debug_mode ^= 1;
  242 	else
  243 		auth_debug_mode = on;
  244 	printf("auth debugging %s\n", auth_debug_mode ? "enabled" : "disabled");
  245 	return(1);
  246 }
  247 
  248 	int
  249 auth_status()
  250 {
  251 	Authenticator *ap;
  252 
  253 	if (i_wont_support == -1)
  254 		printf("Authentication disabled\n");
  255 	else
  256 		printf("Authentication enabled\n");
  257 
  258 	for (ap = authenticators; ap->type; ap++)
  259 		printf("%s: %s\n", AUTHTYPE_NAME(ap->type),
  260 			(i_wont_support & typemask(ap->type)) ?
  261 					"disabled" : "enabled");
  262 	return(1);
  263 }
  264 
  265 /*
  266  * This routine is called by the server to start authentication
  267  * negotiation.
  268  */
  269 	void
  270 auth_request()
  271 {
  272 	static unsigned char str_request[64] = { IAC, SB,
  273 						 TELOPT_AUTHENTICATION,
  274 						 TELQUAL_SEND, };
  275 	Authenticator *ap = authenticators;
  276 	unsigned char *e = str_request + 4;
  277 
  278 	if (!authenticating) {
  279 		authenticating = 1;
  280 		while (ap->type) {
  281 			if (i_support & ~i_wont_support & typemask(ap->type)) {
  282 				if (auth_debug_mode) {
  283 					printf(">>>%s: Sending type %d %d\r\n",
  284 						Name, ap->type, ap->way);
  285 				}
  286 				*e++ = ap->type;
  287 				*e++ = ap->way;
  288 			}
  289 			++ap;
  290 		}
  291 		*e++ = IAC;
  292 		*e++ = SE;
  293 		net_write(str_request, e - str_request);
  294 		printsub('>', &str_request[2], e - str_request - 2);
  295 	}
  296 }
  297 
  298 /*
  299  * This is called when an AUTH SEND is received.
  300  * It should never arrive on the server side (as only the server can
  301  * send an AUTH SEND).
  302  * You should probably respond to it if you can...
  303  *
  304  * If you want to respond to the types out of order (i.e. even
  305  * if he sends  LOGIN KERBEROS and you support both, you respond
  306  * with KERBEROS instead of LOGIN (which is against what the
  307  * protocol says)) you will have to hack this code...
  308  */
  309 	void
  310 auth_send(data, cnt)
  311 	unsigned char *data;
  312 	int cnt;
  313 {
  314 	Authenticator *ap;
  315 	static unsigned char str_none[] = { IAC, SB, TELOPT_AUTHENTICATION,
  316 					    TELQUAL_IS, AUTHTYPE_NULL, 0,
  317 					    IAC, SE };
  318 	if (Server) {
  319 		if (auth_debug_mode) {
  320 			printf(">>>%s: auth_send called!\r\n", Name);
  321 		}
  322 		return;
  323 	}
  324 
  325 	if (auth_debug_mode) {
  326 		printf(">>>%s: auth_send got:", Name);
  327 		printd(data, cnt); printf("\r\n");
  328 	}
  329 
  330 	/*
  331 	 * Save the data, if it is new, so that we can continue looking
  332 	 * at it if the authorization we try doesn't work
  333 	 */
  334 	if (data < _auth_send_data ||
  335 	    data > _auth_send_data + sizeof(_auth_send_data)) {
  336 		auth_send_cnt = cnt > sizeof(_auth_send_data)
  337 					? sizeof(_auth_send_data)
  338 					: cnt;
  339 		bcopy((void *)data, (void *)_auth_send_data, auth_send_cnt);
  340 		auth_send_data = _auth_send_data;
  341 	} else {
  342 		/*
  343 		 * This is probably a no-op, but we just make sure
  344 		 */
  345 		auth_send_data = data;
  346 		auth_send_cnt = cnt;
  347 	}
  348 	while ((auth_send_cnt -= 2) >= 0) {
  349 		if (auth_debug_mode)
  350 			printf(">>>%s: He supports %d\r\n",
  351 				Name, *auth_send_data);
  352 		if ((i_support & ~i_wont_support) & typemask(*auth_send_data)) {
  353 			ap = findauthenticator(auth_send_data[0],
  354 					       auth_send_data[1]);
  355 			if (!ap) {
  356 				printf("Internal state error: cannot find authentication type %d a second time\r\n", *auth_send_data);
  357 			} else if (ap->send) {
  358 				if (auth_debug_mode)
  359 					printf(">>>%s: Trying %d %d\r\n",
  360 						Name, auth_send_data[0],
  361 							auth_send_data[1]);
  362 				if ((*ap->send)(ap)) {
  363 					/*
  364 					 * Okay, we found one we like
  365 					 * and did it.
  366 					 * we can go home now.
  367 					 */
  368 					if (auth_debug_mode)
  369 						printf(">>>%s: Using type %d\r\n",
  370 							Name, *auth_send_data);
  371 					auth_send_data += 2;
  372 					return;
  373 				}
  374 			}
  375 			/* else
  376 			 *	just continue on and look for the
  377 			 *	next one if we didn't do anything.
  378 			 */
  379 		}
  380 		auth_send_data += 2;
  381 	}
  382 	net_write(str_none, sizeof(str_none));
  383 	printsub('>', &str_none[2], sizeof(str_none) - 2);
  384 	if (auth_debug_mode)
  385 		printf(">>>%s: Sent failure message\r\n", Name);
  386 	auth_finished(0, AUTH_REJECT);
  387 }
  388 
  389 	void
  390 auth_send_retry()
  391 {
  392 	/*
  393 	 * if auth_send_cnt <= 0 then auth_send will end up rejecting
  394 	 * the authentication and informing the other side of this.
  395 	 */
  396 	auth_send(auth_send_data, auth_send_cnt);
  397 }
  398 
  399 	void
  400 auth_is(data, cnt)
  401 	unsigned char *data;
  402 	int cnt;
  403 {
  404 	Authenticator *ap;
  405 
  406 	if (cnt < 2)
  407 		return;
  408 
  409 	if (data[0] == AUTHTYPE_NULL) {
  410 		auth_finished(0, AUTH_REJECT);
  411 		return;
  412 	}
  413 
  414 	if (ap = findauthenticator(data[0], data[1])) {
  415 		if (ap->is)
  416 			(*ap->is)(ap, data+2, cnt-2);
  417 	} else if (auth_debug_mode)
  418 		printf(">>>%s: Invalid authentication in IS: %d\r\n",
  419 			Name, *data);
  420 }
  421 
  422 	void
  423 auth_reply(data, cnt)
  424 	unsigned char *data;
  425 	int cnt;
  426 {
  427 	Authenticator *ap;
  428 
  429 	if (cnt < 2)
  430 		return;
  431 
  432 	if (ap = findauthenticator(data[0], data[1])) {
  433 		if (ap->reply)
  434 			(*ap->reply)(ap, data+2, cnt-2);
  435 	} else if (auth_debug_mode)
  436 		printf(">>>%s: Invalid authentication in SEND: %d\r\n",
  437 			Name, *data);
  438 }
  439 
  440 	void
  441 auth_name(data, cnt)
  442 	unsigned char *data;
  443 	int cnt;
  444 {
  445 	Authenticator *ap;
  446 	unsigned char savename[256];
  447 
  448 	if (cnt < 1) {
  449 		if (auth_debug_mode)
  450 			printf(">>>%s: Empty name in NAME\r\n", Name);
  451 		return;
  452 	}
  453 	if (cnt > sizeof(savename) - 1) {
  454 		if (auth_debug_mode)
  455 			printf(">>>%s: Name in NAME (%d) exceeds %d length\r\n",
  456 					Name, cnt, sizeof(savename)-1);
  457 		return;
  458 	}
  459 	bcopy((void *)data, (void *)savename, cnt);
  460 	savename[cnt] = '\0';	/* Null terminate */
  461 	if (auth_debug_mode)
  462 		printf(">>>%s: Got NAME [%s]\r\n", Name, savename);
  463 	auth_encrypt_user(savename);
  464 }
  465 
  466 	int
  467 auth_sendname(cp, len)
  468 	unsigned char *cp;
  469 	int len;
  470 {
  471 	static unsigned char str_request[256+6]
  472 			= { IAC, SB, TELOPT_AUTHENTICATION, TELQUAL_NAME, };
  473 	register unsigned char *e = str_request + 4;
  474 	register unsigned char *ee = &str_request[sizeof(str_request)-2];
  475 
  476 	while (--len >= 0) {
  477 		if ((*e++ = *cp++) == IAC)
  478 			*e++ = IAC;
  479 		if (e >= ee)
  480 			return(0);
  481 	}
  482 	*e++ = IAC;
  483 	*e++ = SE;
  484 	net_write(str_request, e - str_request);
  485 	printsub('>', &str_request[2], e - &str_request[2]);
  486 	return(1);
  487 }
  488 
  489 	void
  490 auth_finished(ap, result)
  491 	Authenticator *ap;
  492 	int result;
  493 {
  494 	if (!(authenticated = ap))
  495 		authenticated = &NoAuth;
  496 	validuser = result;
  497 }
  498 
  499 	/* ARGSUSED */
  500 	static void
  501 auth_intr(sig)
  502 	int sig;
  503 {
  504 	auth_finished(0, AUTH_REJECT);
  505 }
  506 
  507 	int
  508 auth_wait(name)
  509 	char *name;
  510 {
  511 	if (auth_debug_mode)
  512 		printf(">>>%s: in auth_wait.\r\n", Name);
  513 
  514 	if (Server && !authenticating)
  515 		return(0);
  516 
  517 	(void) signal(SIGALRM, auth_intr);
  518 	alarm(30);
  519 	while (!authenticated)
  520 		if (telnet_spin())
  521 			break;
  522 	alarm(0);
  523 	(void) signal(SIGALRM, SIG_DFL);
  524 
  525 	/*
  526 	 * Now check to see if the user is valid or not
  527 	 */
  528 	if (!authenticated || authenticated == &NoAuth)
  529 		return(AUTH_REJECT);
  530 
  531 	if (validuser == AUTH_VALID)
  532 		validuser = AUTH_USER;
  533 
  534 	if (authenticated->status)
  535 		validuser = (*authenticated->status)(authenticated,
  536 						     name, validuser);
  537 	return(validuser);
  538 }
  539 
  540 	void
  541 auth_debug(mode)
  542 	int mode;
  543 {
  544 	auth_debug_mode = mode;
  545 }
  546 
  547 	void
  548 auth_printsub(data, cnt, buf, buflen)
  549 	unsigned char *data, *buf;
  550 	int cnt, buflen;
  551 {
  552 	Authenticator *ap;
  553 
  554 	if ((ap = findauthenticator(data[1], data[2])) && ap->printsub)
  555 		(*ap->printsub)(data, cnt, buf, buflen);
  556 	else
  557 		auth_gen_printsub(data, cnt, buf, buflen);
  558 }
  559 
  560 	void
  561 auth_gen_printsub(data, cnt, buf, buflen)
  562 	unsigned char *data, *buf;
  563 	int cnt, buflen;
  564 {
  565 	register unsigned char *cp;
  566 	unsigned char tbuf[16];
  567 
  568 	cnt -= 3;
  569 	data += 3;
  570 	buf[buflen-1] = '\0';
  571 	buf[buflen-2] = '*';
  572 	buflen -= 2;
  573 	for (; cnt > 0; cnt--, data++) {
  574 		sprintf((char *)tbuf, " %d", *data);
  575 		for (cp = tbuf; *cp && buflen > 0; --buflen)
  576 			*buf++ = *cp++;
  577 		if (buflen <= 0)
  578 			return;
  579 	}
  580 	*buf = '\0';
  581 }
  582 #endif