148652Sbostic /*-
2*62386Sbostic * Copyright (c) 1985, 1993
3*62386Sbostic * The Regents of the University of California. All rights reserved.
448652Sbostic *
548652Sbostic * %sccs.include.proprietary.c%
648652Sbostic */
748652Sbostic
813638Ssam #ifndef lint
9*62386Sbostic static char sccsid[] = "@(#)chkpth.c 8.1 (Berkeley) 06/06/93";
1048652Sbostic #endif /* not lint */
1113638Ssam
1213638Ssam #include "uucp.h"
1313638Ssam #include <sys/stat.h>
1413638Ssam
1513638Ssam struct userpath {
1613638Ssam char *us_lname;
1713638Ssam char *us_mname;
1813638Ssam char us_callback;
1913638Ssam char **us_path;
2013638Ssam struct userpath *unext;
2113638Ssam };
2233944Srick
2313638Ssam struct userpath *Uhead = NULL;
2413638Ssam struct userpath *Mchdef = NULL, *Logdef = NULL;
2513638Ssam int Uptfirst = 1;
2613638Ssam
2723588Sbloom /*LINTLIBRARY*/
2823588Sbloom
2923588Sbloom /*
3023588Sbloom * this routine will check the path table for the
3113638Ssam * machine or log name (non-null parameter) to see if the
3223588Sbloom * input path (path) starts with an acceptable prefix.
3313638Ssam *
3413638Ssam * return codes: 0 | FAIL
3513638Ssam */
3613638Ssam
chkpth(logname,mchname,path)3713638Ssam chkpth(logname, mchname, path)
3813638Ssam char *path, *logname, *mchname;
3913638Ssam {
4013638Ssam register struct userpath *u;
4113638Ssam extern char *lastpart();
4213638Ssam register char **p, *s;
4313638Ssam
4413638Ssam /* Allow only rooted pathnames. Security wish. rti!trt */
4518616Sralph if (*path != '/') {
4618616Sralph DEBUG(4, "filename doesn't begin with /\n", CNULL);
4717767Sralph return FAIL;
4818616Sralph }
4913638Ssam
5013638Ssam if (Uptfirst) {
5113638Ssam rdpth();
5233944Srick if (Uhead == NULL) {
5333944Srick syslog(LOG_ERR, "USERFILE empty!");
5433944Srick cleanup(FAIL);
5533944Srick }
5613638Ssam Uptfirst = 0;
5713638Ssam }
5813638Ssam for (u = Uhead; u != NULL; ) {
5913638Ssam if (*logname != '\0' && strcmp(logname, u->us_lname) == SAME)
6013638Ssam break;
6123588Sbloom if (*mchname != '\0' && strncmp(mchname, u->us_mname, MAXBASENAME) == SAME)
6213638Ssam break;
6313638Ssam u = u->unext;
6413638Ssam }
6513638Ssam if (u == NULL) {
6613638Ssam if (*logname == '\0')
6713638Ssam u = Mchdef;
6813638Ssam else
6913638Ssam u = Logdef;
7013638Ssam if (u == NULL)
7117767Sralph return FAIL;
7213638Ssam }
7313638Ssam
7413638Ssam /* check for /../ in path name */
7513638Ssam for (s = path; *s != '\0'; s++) {
7618616Sralph if (prefix("/../",s)) {
7718616Sralph DEBUG(4, "filename has /../ in it\n", CNULL);
7817767Sralph return FAIL;
7918616Sralph }
8013638Ssam }
8113638Ssam
8213638Ssam /* Check for access permission */
8313638Ssam for (p = u->us_path; *p != NULL; p++)
8413638Ssam if (prefix(*p, path))
8517767Sralph return SUCCESS;
8618616Sralph DEBUG(4, "filename not in list\n", CNULL);
8713638Ssam
8813638Ssam /* path name not valid */
8917767Sralph return FAIL;
9013638Ssam }
9113638Ssam
9213638Ssam
9313638Ssam /***
9413638Ssam * rdpth()
9513638Ssam *
9613638Ssam * rdpth - this routine will read the USERFILE and
9713638Ssam * construct the userpath structure pointed to by (u);
9813638Ssam *
9913638Ssam */
10013638Ssam
rdpth()10113638Ssam rdpth()
10213638Ssam {
10313638Ssam char buf[100 + 1], *pbuf[50 + 1];
10413638Ssam register struct userpath *u;
10513638Ssam register char *pc, **cp;
10613638Ssam FILE *uf;
10713638Ssam
10813638Ssam if ((uf = fopen(USERFILE, "r")) == NULL) {
10913638Ssam /* can not open file */
11013638Ssam return;
11113638Ssam }
11213638Ssam
11313638Ssam while (cfgets(buf, sizeof(buf), uf) != NULL) {
11413638Ssam int nargs, i;
11513638Ssam
11617767Sralph u = (struct userpath *)malloc(sizeof (struct userpath));
11717767Sralph if (u == NULL) {
11813638Ssam DEBUG (1, "*** Userpath malloc failed\n", 0);
11913638Ssam fclose (uf);
12013638Ssam return;
12113638Ssam }
12213638Ssam if ((pc = calloc((unsigned)strlen(buf) + 1, sizeof (char)))
12313638Ssam == NULL) {
12413638Ssam /* can not allocate space */
12513638Ssam DEBUG (1, "Userpath calloc 1 failed\n", 0);
12613638Ssam fclose(uf);
12713638Ssam return;
12813638Ssam }
12913638Ssam
13013638Ssam strcpy(pc, buf);
13117767Sralph nargs = getargs(pc, pbuf, 50);
13213638Ssam u->us_lname = pbuf[0];
13313638Ssam pc = index(u->us_lname, ',');
13413638Ssam if (pc != NULL)
13513638Ssam *pc++ = '\0';
13613638Ssam else
13713638Ssam pc = u->us_lname + strlen(u->us_lname);
13813638Ssam u->us_mname = pc;
13923588Sbloom if (strlen(u->us_mname) > MAXBASENAME)
14023588Sbloom u->us_mname[MAXBASENAME] = '\0';
14113638Ssam if (*u->us_lname == '\0' && Logdef == NULL)
14213638Ssam Logdef = u;
14317767Sralph if (*u->us_mname == '\0' && Mchdef == NULL)
14413638Ssam Mchdef = u;
14513638Ssam i = 1;
14613638Ssam if (strcmp(pbuf[1], "c") == SAME) {
14713638Ssam u->us_callback = 1;
14813638Ssam i++;
14913638Ssam }
15013638Ssam else
15113638Ssam u->us_callback = 0;
15217767Sralph cp = (char **)calloc((unsigned)(nargs-i+1), sizeof(char *));
15317767Sralph if (cp == NULL) {
15413638Ssam /* can not allocate space */
15513638Ssam DEBUG (1, "Userpath calloc 2 failed!\n", 0);
15613638Ssam fclose(uf);
15713638Ssam return;
15813638Ssam }
15917767Sralph u->us_path = cp;
16013638Ssam
16113638Ssam while (i < nargs)
16213638Ssam *cp++ = pbuf[i++];
16313638Ssam *cp = NULL;
16413638Ssam u->unext = Uhead;
16513638Ssam Uhead = u;
16613638Ssam }
16713638Ssam
16813638Ssam fclose(uf);
16913638Ssam return;
17013638Ssam }
17113638Ssam
17213638Ssam /***
17313638Ssam * callback(name) check for callback
17413638Ssam * char *name;
17513638Ssam *
17613638Ssam * return codes:
17713638Ssam * 0 - no call back
17813638Ssam * 1 - call back
17913638Ssam */
18013638Ssam
callback(name)18113638Ssam callback(name)
18213638Ssam register char *name;
18313638Ssam {
18413638Ssam register struct userpath *u;
18513638Ssam
18613638Ssam if (Uptfirst) {
18713638Ssam rdpth();
18833944Srick if (Uhead == NULL) {
18933944Srick syslog(LOG_ERR, "USERFILE empty!");
19033944Srick cleanup(FAIL);
19133944Srick }
19213638Ssam Uptfirst = 0;
19313638Ssam }
19413638Ssam
19513638Ssam for (u = Uhead; u != NULL; ) {
19613638Ssam if (strcmp(u->us_lname, name) == SAME)
19713638Ssam /* found user name */
19817767Sralph return u->us_callback;
19913638Ssam u = u->unext;
20013638Ssam }
20113638Ssam
20213638Ssam /* userid not found */
20317767Sralph return 0;
20413638Ssam }
20513638Ssam
20613638Ssam
20713638Ssam /***
20813638Ssam * chkperm(file, mopt) check write permission of file
20913638Ssam * char *mopt; none NULL - create directories
21013638Ssam *
21113638Ssam * if mopt != NULL and permissions are ok,
21213638Ssam * a side effect of this routine is to make
21313638Ssam * directories up to the last part of the
21413638Ssam * filename (if they do not exist).
21513638Ssam *
21617767Sralph * return SUCCESS | FAIL
21713638Ssam */
21813638Ssam
chkperm(file,mopt)21913638Ssam chkperm(file, mopt)
22013638Ssam char *file, *mopt;
22113638Ssam {
22213638Ssam struct stat s;
22313638Ssam int ret;
22413638Ssam char dir[MAXFULLNAME];
22513638Ssam extern char *lastpart();
22613638Ssam
22713638Ssam if (stat(subfile(file), &s) == 0) {
22818616Sralph if ((s.st_mode & ANYWRITE) == 0) {
22918616Sralph DEBUG(4,"file is not writable: mode %o\n", s.st_mode);
23017767Sralph return FAIL;
23118616Sralph }
23217767Sralph return SUCCESS;
23313638Ssam }
23413638Ssam
23513638Ssam strcpy(dir, file);
23613638Ssam *lastpart(dir) = '\0';
23718616Sralph if ((ret = stat(subfile(dir), &s)) == -1 && mopt == NULL) {
23818616Sralph DEBUG(4, "can't stat directory %s\n", subfile(dir));
23917767Sralph return FAIL;
24018616Sralph }
24113638Ssam
24213638Ssam if (ret != -1) {
24313638Ssam if ((s.st_mode & ANYWRITE) == 0)
24417767Sralph return FAIL;
24513638Ssam else
24617767Sralph return SUCCESS;
24713638Ssam }
24813638Ssam
24913638Ssam /* make directories */
25017767Sralph return mkdirs(file);
25113638Ssam }
25213638Ssam
25313638Ssam /*
25413638Ssam * Check for sufficient privilege to request debugging.
25513638Ssam */
chkdebug()25617767Sralph chkdebug()
25713638Ssam {
25817767Sralph if (access(SYSFILE, 04) < 0) {
25917767Sralph fprintf(stderr, "Sorry, you must be able to read L.sys for debugging\n");
26013638Ssam cleanup(1);
26113638Ssam exit(1); /* Just in case */
26213638Ssam }
26313638Ssam }
264