summaryrefslogtreecommitdiff
path: root/usr.sbin/sendmail/src/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/sendmail/src/util.c')
-rw-r--r--usr.sbin/sendmail/src/util.c142
1 files changed, 121 insertions, 21 deletions
diff --git a/usr.sbin/sendmail/src/util.c b/usr.sbin/sendmail/src/util.c
index f296513df3b..85e0f04dd34 100644
--- a/usr.sbin/sendmail/src/util.c
+++ b/usr.sbin/sendmail/src/util.c
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)util.c 8.15 (Berkeley) 10/31/93";
+static char sccsid[] = "@(#)util.c 8.28 (Berkeley) 1/4/94";
#endif /* not lint */
# include "sendmail.h"
@@ -407,7 +407,9 @@ buildfname(gecos, login, buf)
** gid -- group id to compare against.
** uname -- user name to compare against (used for group
** sets).
-** mustown -- to be safe, this uid must own the file.
+** flags -- modifiers:
+** SFF_MUSTOWN -- "uid" must own this file.
+** SFF_NOSLINK -- file cannot be a symbolic link.
** mode -- mode bits that must match.
**
** Returns:
@@ -433,12 +435,12 @@ buildfname(gecos, login, buf)
#endif
int
-safefile(fn, uid, gid, uname, mustown, mode)
+safefile(fn, uid, gid, uname, flags, mode)
char *fn;
uid_t uid;
gid_t gid;
char *uname;
- bool mustown;
+ int flags;
int mode;
{
register char *p;
@@ -446,8 +448,8 @@ safefile(fn, uid, gid, uname, mustown, mode)
struct stat stbuf;
if (tTd(54, 4))
- printf("safefile(%s, uid=%d, gid=%d, mustown=%d, mode=%o):\n",
- fn, uid, gid, mustown, mode);
+ printf("safefile(%s, uid=%d, gid=%d, flags=%x, mode=%o):\n",
+ fn, uid, gid, flags, mode);
errno = 0;
for (p = fn; (p = strchr(++p, '/')) != NULL; *p = '/')
@@ -455,6 +457,12 @@ safefile(fn, uid, gid, uname, mustown, mode)
*p = '\0';
if (stat(fn, &stbuf) < 0)
break;
+ if (uid == 0 && !bitset(SFF_ROOTOK, flags))
+ {
+ if (bitset(S_IXOTH, stbuf.st_mode))
+ continue;
+ break;
+ }
if (stbuf.st_uid == uid && bitset(S_IXUSR, stbuf.st_mode))
continue;
if (stbuf.st_gid == gid && bitset(S_IXGRP, stbuf.st_mode))
@@ -488,7 +496,12 @@ safefile(fn, uid, gid, uname, mustown, mode)
return ret;
}
+#ifdef HASLSTAT
+ if ((bitset(SFF_NOSLINK, flags) ? lstat(fn, &stbuf)
+ : stat(fn, &stbuf)) < 0)
+#else
if (stat(fn, &stbuf) < 0)
+#endif
{
int ret = errno;
@@ -498,7 +511,17 @@ safefile(fn, uid, gid, uname, mustown, mode)
errno = 0;
return ret;
}
- if (uid == 0)
+
+#ifdef S_ISLNK
+ if (bitset(SFF_NOSLINK, flags) && S_ISLNK(stbuf.st_mode))
+ {
+ if (tTd(54, 4))
+ printf("\t[slink mode %o]\tEPERM\n", stbuf.st_mode);
+ return EPERM;
+ }
+#endif
+
+ if (uid == 0 && !bitset(SFF_ROOTOK, flags))
mode >>= 6;
else if (stbuf.st_uid != uid)
{
@@ -525,7 +548,8 @@ safefile(fn, uid, gid, uname, mustown, mode)
if (tTd(54, 4))
printf("\t[uid %d, stat %o, mode %o] ",
stbuf.st_uid, stbuf.st_mode, mode);
- if ((stbuf.st_uid == uid || uid == 0 || !mustown) &&
+ if ((stbuf.st_uid == uid || stbuf.st_uid == 0 ||
+ !bitset(SFF_MUSTOWN, flags)) &&
(stbuf.st_mode & mode) == mode)
{
if (tTd(54, 4))
@@ -836,12 +860,13 @@ sfgets(buf, siz, fp, timeout, during)
/* try to read */
p = NULL;
- while (p == NULL && !feof(fp) && !ferror(fp))
+ while (!feof(fp) && !ferror(fp))
{
errno = 0;
p = fgets(buf, siz, fp);
- if (errno == EINTR)
- clearerr(fp);
+ if (p != NULL || errno != EINTR)
+ break;
+ clearerr(fp);
}
/* clear the event if it has not sprung */
@@ -1120,18 +1145,23 @@ strcontainedin(a, b)
register char *a;
register char *b;
{
- int l;
-
- l = strlen(a);
- for (;;)
+ int la;
+ int lb;
+ int c;
+
+ la = strlen(a);
+ lb = strlen(b);
+ c = *a;
+ if (isascii(c) && isupper(c))
+ c = tolower(c);
+ for (; lb-- >= la; b++)
{
- b = strchr(b, a[0]);
- if (b == NULL)
- return FALSE;
- if (strncmp(a, b, l) == 0)
+ if (*b != c && isascii(*b) && isupper(*b) && tolower(*b) != c)
+ continue;
+ if (strncasecmp(a, b, la) == 0)
return TRUE;
- b++;
}
+ return FALSE;
}
/*
** CHECKFD012 -- check low numbered file descriptors
@@ -1279,6 +1309,27 @@ dumpfd(fd, printclosed, logit)
p += strlen(p);
goto defprint;
+#ifdef S_IFIFO
+ case S_IFIFO:
+ sprintf(p, "FIFO: ");
+ p += strlen(p);
+ goto defprint;
+#endif
+
+#ifdef S_IFDIR
+ case S_IFDIR:
+ sprintf(p, "DIR: ");
+ p += strlen(p);
+ goto defprint;
+#endif
+
+#ifdef S_IFLNK
+ case S_IFLNK:
+ sprintf(p, "LNK: ");
+ p += strlen(p);
+ goto defprint;
+#endif
+
default:
defprint:
sprintf(p, "dev=%d/%d, ino=%d, nlink=%d, u/gid=%d/%d, size=%ld",
@@ -1289,7 +1340,56 @@ defprint:
printit:
if (logit)
- syslog(LOG_INFO, "%s", buf);
+ syslog(LOG_DEBUG, "%s", buf);
else
printf("%s\n", buf);
}
+ /*
+** SHORTENSTRING -- return short version of a string
+**
+** If the string is already short, just return it. If it is too
+** long, return the head and tail of the string.
+**
+** Parameters:
+** s -- the string to shorten.
+** m -- the max length of the string.
+**
+** Returns:
+** Either s or a short version of s.
+*/
+
+#ifndef MAXSHORTSTR
+# define MAXSHORTSTR 203
+#endif
+
+char *
+shortenstring(s, m)
+ register char *s;
+ int m;
+{
+ int l;
+ static char buf[MAXSHORTSTR + 1];
+
+ l = strlen(s);
+ if (l < m)
+ return s;
+ if (m > MAXSHORTSTR)
+ m = MAXSHORTSTR;
+ else if (m < 10)
+ {
+ if (m < 5)
+ {
+ strncpy(buf, s, m);
+ buf[m] = '\0';
+ return buf;
+ }
+ strncpy(buf, s, m - 3);
+ strcpy(buf + m - 3, "...");
+ return buf;
+ }
+ m = (m - 3) / 2;
+ strncpy(buf, s, m);
+ strcpy(buf + m, "...");
+ strcpy(buf + m + 3, s + l - m);
+ return buf;
+}