[net.bugs.uucp] Repaired UUCICO/chkpth.c

dpk (07/31/82)

#N:brl-bmd:1400003:000:4893
brl-bmd!dpk    Jul 31 14:12:00 1982

	This is the repaired verison of chkpth.c.  The only real
changes have to do with the userpath structure, which is now handled
as a dynamically allocated linked list.  I checked the vanilla V7
and 2.8BSD distributions, and they both have this bug.  It should
only be a problem on systems with USERFILE's of 16 or more entries.
Note that although defined, DFLTNAME is not used.  Anyone have
the code implement this?

	/*  chkpth  3.1  10/26/79  11:21:30  */
	/*  Modified Doug Kingston, 30 July 82 to fix handling of	*/
	/*	of the "userpath" structures.				*/
#include "uucp.h"
#include <sys/types.h>
#include <sys/stat.h>


#define DFLTNAME "default"	/* Not Implemented. ??? */

struct userpath {
	char *us_lname;
	char *us_mname;
	char us_callback;
	char **us_path;
	struct userpath *unext;
};
struct userpath *Uhead = NULL;
struct userpath *Mchdef = NULL, *Logdef = NULL;
int Uptfirst = 1;

/*******
 *	chkpth(logname, mchname, path)
 *	char *path, *logname, *mchname;
 *
 *	chkpth  -  this routine will check the path table for the
 *	machine or log name (non-null parameter) to see if the
 *	input path (path)
 *	starts with an acceptable prefix.
 *
 *	return codes:  0  |  FAIL
 */

chkpth(logname, mchname, path)
char *path, *logname, *mchname;
{
	struct userpath *u;
	extern char *lastpart();
	char **p, *s;
	char c;
	int ret, i;

	if (Uptfirst) {
		rdpth();
		ASSERT(Uhead != NULL, "INIT USERFILE, No entrys!", 0);
		Uptfirst = 0;
	}
	for (u = Uhead; u != NULL; ) {
		if (*logname != '\0' && strcmp(logname, u->us_lname) == SAME)
			break;
		if (*mchname != '\0' && strcmp(mchname, u->us_mname) == SAME)
			break;
		u = u->unext;
	}
	if (u == NULL) {
		if (*logname == '\0')
			u = Mchdef;
		else
			u = Logdef;
		if (u == NULL)
			return(FAIL);
	}
	/* found user name */
	p = u->us_path;
	/*  check for /../ in path name  */
	for (s = path; *s != '\0'; s++) {
		if(prefix("/../",s))
			return(FAIL);
	}

	for (p = u->us_path; *p != NULL; p++)
		if (prefix(*p, path))
			return(0);

	if (prefix(Spool, path)) {
		if ((c = *lastpart(path)) == DATAPRE
		  || c == XQTPRE)
			return(0);
	}
	/* path name not valid */
	return(FAIL);
}


/***
 *	rdpth()
 *
 *	rdpth  -  this routine will read the USERFILE and
 *	construct the userpath structure pointed to by (u);
 *
 *	return codes:  0  |  FAIL
 */

rdpth()
{
	char buf[BUFSIZ + 1], *pbuf[BUFSIZ + 1], *pc, **cp;
	char *calloc(), *index();
	FILE *uf;

	if ((uf = fopen(USERFILE, "r")) == NULL) {
		/* can not open file */
		return;
	}

	while (fgets(buf, BUFSIZ, uf) != NULL) {
		int nargs, i;
		struct userpath *u;

		if ((u = malloc (sizeof (struct userpath))) == NULL) {
			DEBUG (1, "*** Userpath malloc failed\n", 0);
			fclose (uf);
			return;
		}
		if ((pc = calloc(strlen(buf) + 1, sizeof (char)))
			== NULL) {
			/* can not allocate space */
			DEBUG (1, "Userpath calloc 1 failed\n", 0);
			fclose(uf);
			return;
		}

		strcpy(pc, buf);
		nargs = getargs(pc, pbuf);
		u->us_lname = pbuf[0];
		pc = index(u->us_lname, ',');
		if (pc != NULL)
			*pc++ = '\0';
		else
			pc = u->us_lname + strlen(u->us_lname);
		u->us_mname = pc;
		if (*u->us_lname == '\0' && Logdef == NULL)
			Logdef = u;
		else if (*u->us_mname == '\0' && Mchdef == NULL)
			Mchdef = u;
		i = 1;
		if (strcmp(pbuf[1], "c") == SAME) {
			u->us_callback = 1;
			i++;
		}
		else
			u->us_callback = 0;
		if ((cp = u->us_path =
		  (char **) calloc(nargs - i + 1, sizeof (char *))) == NULL) {
			/*  can not allocate space */
			DEBUG (1, "Userpath calloc 2 failed!\n", 0);
			fclose(uf);
			return;
		}

		while (i < nargs)
			*cp++ = pbuf[i++];
		*cp = NULL;
		u->unext = Uhead;
		Uhead = u;
	}

	fclose(uf);
	return;
}


/***
 *	callback(name)	check for callback
 *	char *name;
 *
 *	return codes:
 *		0  -  no call back
 *		1  -  call back
 */

callback(name)
char *name;
{
	struct userpath *u;
	int ret, i;

	if (Uptfirst) {
		rdpth();
		ASSERT(Uhead == NULL, "INIT USERFILE, No Users!", 0);
		Uptfirst = 0;
	}

	for (u = Uhead; u != NULL; ) {
		if (strcmp(u->us_lname, name) == SAME)
			/* found user name */
			return(u->us_callback);
		u = u->unext;
	}

	/* userid not found */
	return(0);
}


/***
 *	chkperm(file, mopt)	check write permission of file
 *	char *mopt;		none NULL - create directories
 *
 *	if mopt != NULL and permissions are ok,
 *	a side effect of this routine is to make
 *	directories up to the last part of the
 *	filename (if they do not exist).
 *
 *	return 0 | FAIL
 */

chkperm(file, mopt)
char *file, *mopt;
{
	struct stat s;
	int ret;
	char dir[MAXFULLNAME];
	extern char *lastpart();

	if (stat(file, &s) != -1)
		return(0);

	strcpy(dir, file);
	*lastpart(dir) = '\0';
	if ((ret = stat(dir, &s)) == -1
	  && mopt == NULL)
		return(FAIL);

	if (ret != -1) {
		if (prefix(SPOOL, dir))
			return(0);
		if ((s.st_mode & ANYWRITE) == 0)
			return(FAIL);
		else
			return(0);
	}

	/*  make directories  */
	return(mkdirs(file));
}

dpk (09/02/82)

#R:brl-bmd:1400003:brl-bmd:1400004:004:374
brl-bmd!dpk    Sep  1 19:22:00 1982

	There is a bug in my bug fix for chkpth.c.  In the function
callback(), the assertion should read "Uhead != NULL" instead of
"Uhead == NULL".  This will cause your UUCICO to refuse all incoming
calls with the AUDIT file showing something like:
	AERROR - (Uhead == NULL) INIT USERFILE, No Users!
Sorry for the inconvenience, we don't have people poll us much.

						-Doug-