summaryrefslogtreecommitdiff
path: root/usr.sbin/sendmail/src/conf.c
diff options
context:
space:
mode:
authorglass <glass@NetBSD.org>1994-03-16 02:11:31 +0000
committerglass <glass@NetBSD.org>1994-03-16 02:11:31 +0000
commit3fb497653d34cde8706b0e446e52182df5bc4ae7 (patch)
tree378207336652cf6132b6412b0e6c3f105621d985 /usr.sbin/sendmail/src/conf.c
parentc0ae496079e5f8f6af13afb704a68b285f4d14b4 (diff)
sendmail 8.6.7. fixes recently discovered security hole
Diffstat (limited to 'usr.sbin/sendmail/src/conf.c')
-rw-r--r--usr.sbin/sendmail/src/conf.c337
1 files changed, 283 insertions, 54 deletions
diff --git a/usr.sbin/sendmail/src/conf.c b/usr.sbin/sendmail/src/conf.c
index cc6605a66c1..1c859282e8f 100644
--- a/usr.sbin/sendmail/src/conf.c
+++ b/usr.sbin/sendmail/src/conf.c
@@ -33,7 +33,7 @@
*/
#ifndef lint
-static char sccsid[] = "@(#)conf.c 8.62 (Berkeley) 1/9/94";
+static char sccsid[] = "@(#)conf.c 8.82 (Berkeley) 3/6/94";
#endif /* not lint */
# include "sendmail.h"
@@ -628,6 +628,7 @@ init_md(argc, argv)
#define LA_SUBR 4 /* call getloadavg */
#define LA_MACH 5 /* MACH load averages (as on NeXT boxes) */
#define LA_SHORT 6 /* read kmem for avenrun; interpret as short */
+#define LA_PROCSTR 7 /* read string ("1.17") from /proc/loadavg */
/* do guesses based on general OS type */
#ifndef LA_TYPE
@@ -827,6 +828,52 @@ getla()
#else
+#if LA_TYPE == LA_PROCSTR
+
+/*
+** Read /proc/loadavg for the load average. This is assumed to be
+** in a format like "0.15 0.12 0.06".
+**
+** Initially intended for Linux. This has been in the kernel
+** since at least 0.99.15.
+*/
+
+# ifndef _PATH_LOADAVG
+# define _PATH_LOADAVG "/proc/loadavg"
+# endif
+
+int
+getla()
+{
+ double avenrun;
+ register int result;
+ FILE *fp;
+
+ fp = fopen(_PATH_LOADAVG, "r");
+ if (fp == NULL)
+ {
+ if (tTd(3, 1))
+ printf("getla: fopen(%s): %s\n",
+ _PATH_LOADAVG, errstring(errno));
+ return -1;
+ }
+ result = fscanf(fp, "%lf", &avenrun);
+ fclose(fp);
+ if (result != 1)
+ {
+ if (tTd(3, 1))
+ printf("getla: fscanf() = %d: %s\n",
+ result, errstring(errno));
+ return -1;
+ }
+
+ if (tTd(3, 1))
+ printf("getla(): %.2f\n", avenrun);
+
+ return ((int) (avenrun + 0.5));
+}
+
+#else
getla()
{
@@ -838,6 +885,54 @@ getla()
#endif
#endif
#endif
+#endif
+
+
+/*
+ * Copyright 1989 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, 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 or implied warranty.
+ *
+ * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Authors: Many and varied...
+ */
+
+/* Non Apollo stuff removed by Don Lewis 11/15/93 */
+#ifndef lint
+static char rcsid[] = "@(#)$Id: conf.c,v 1.7 1994/03/16 02:13:13 glass Exp $";
+#endif /* !lint */
+
+#ifdef apollo
+# undef volatile
+# include <apollo/base.h>
+
+/* ARGSUSED */
+int getloadavg( call_data )
+ caddr_t call_data; /* pointer to (double) return value */
+{
+ double *avenrun = (double *) call_data;
+ int i;
+ status_$t st;
+ long loadav[3];
+ proc1_$get_loadav(loadav, &st);
+ *avenrun = loadav[0] / (double) (1 << 16);
+ return(0);
+}
+# endif /* apollo */
/*
** SHOULDQUEUE -- should this message be queued or sent?
**
@@ -909,6 +1004,9 @@ refuseconnections()
*/
#ifdef SETPROCTITLE
+# ifdef HASSETPROCTITLE
+ *** ERROR *** Cannot have both SETPROCTITLE and HASSETPROCTITLE defined
+# endif
# ifdef __hpux
# include <sys/pstat.h>
# endif
@@ -932,6 +1030,8 @@ refuseconnections()
# define PROCTITLEPAD ' '
#endif
+#ifndef HASSETPROCTITLE
+
/*VARARGS1*/
#ifdef __STDC__
setproctitle(char *fmt, ...)
@@ -986,6 +1086,8 @@ setproctitle(fmt, va_alist)
# endif
# endif /* SETPROCTITLE */
}
+
+#endif
/*
** REAPCHILD -- pick up the body of my child, lest it become a zombie
**
@@ -1407,6 +1509,8 @@ char *DefaultUserShells[] =
#endif
+#define WILDCARD_SHELL "/SENDMAIL/ANY/SHELL/"
+
bool
usershellok(shell)
char *shell;
@@ -1417,7 +1521,7 @@ usershellok(shell)
setusershell();
while ((p = getusershell()) != NULL)
- if (strcmp(p, shell) == 0 || strcmp(p, "*") == 0)
+ if (strcmp(p, shell) == 0 || strcmp(p, WILDCARD_SHELL) == 0)
break;
endusershell();
return p != NULL;
@@ -1452,7 +1556,7 @@ usershellok(shell)
while (*p != '\0' && *p != '#' && !isspace(*p))
p++;
*p = '\0';
- if (strcmp(shell, q) == 0 || strcmp("*", q) == 0)
+ if (strcmp(shell, q) == 0 || strcmp(WILDCARD_SHELL, q) == 0)
{
fclose(shellf);
return TRUE;
@@ -1480,24 +1584,29 @@ usershellok(shell)
** Puts the filesystem block size into bsize.
*/
-#ifdef HASSTATFS
-# undef HASUSTAT
+/* statfs types */
+#define SFS_NONE 0 /* no statfs implementation */
+#define SFS_USTAT 1 /* use ustat */
+#define SFS_4ARGS 2 /* use four-argument statfs call */
+#define SFS_VFS 3 /* use <sys/vfs.h> implementation */
+#define SFS_MOUNT 4 /* use <sys/mount.h> implementation */
+#define SFS_STATFS 5 /* use <sys/statfs.h> implementation */
+
+#ifndef SFS_TYPE
+# define SFS_TYPE SFS_NONE
#endif
-#if defined(HASUSTAT)
+#if SFS_TYPE == SFS_USTAT
# include <ustat.h>
#endif
-
-#ifdef HASSTATFS
-# if defined(IRIX) || defined(apollo) || defined(_SCO_unix_) || defined(UMAXV) || defined(DGUX) || defined(_AIX3)
-# include <sys/statfs.h>
-# else
-# if (defined(sun) && !defined(BSD)) || defined(__hpux) || defined(_CONVEX_SOURCE) || defined(NeXT) || defined(_AUX_SOURCE) || defined(MACH386)
-# include <sys/vfs.h>
-# else
-# include <sys/mount.h>
-# endif
-# endif
+#if SFS_TYPE == SFS_4ARGS || SFS_TYPE == SFS_STATFS
+# include <sys/statfs.h>
+#endif
+#if SFS_TYPE == SFS_VFS
+# include <sys/vfs.h>
+#endif
+#if SFS_TYPE == SFS_MOUNT
+# include <sys/mount.h>
#endif
long
@@ -1505,8 +1614,8 @@ freespace(dir, bsize)
char *dir;
long *bsize;
{
-#if defined(HASSTATFS) || defined(HASUSTAT)
-# if defined(HASUSTAT)
+#if SFS_TYPE != SFS_NONE
+# if SFS_TYPE == SFS_USTAT
struct ustat fs;
struct stat statbuf;
# define FSBLOCKSIZE DEV_BSIZE
@@ -1519,17 +1628,17 @@ freespace(dir, bsize)
# else
struct statfs fs;
# define FSBLOCKSIZE fs.f_bsize
-# if defined(_SCO_unix_) || defined(IRIX)
+# if defined(_SCO_unix_) || defined(IRIX) || defined(apollo)
# define f_bavail f_bfree
# endif
# endif
# endif
extern int errno;
-# if defined(HASUSTAT)
+# if SFS_TYPE == SFS_USTAT
if (stat(dir, &statbuf) == 0 && ustat(statbuf.st_dev, &fs) == 0)
# else
-# if defined(IRIX) || defined(apollo) || defined(UMAXV) || defined(DGUX)
+# if SFS_TYPE == SFS_4ARGS
if (statfs(dir, &fs, sizeof fs, 0) == 0)
# else
# if defined(ultrix)
@@ -1694,6 +1803,9 @@ transienterror(err)
#ifdef EADDRNOTAVAIL
case EADDRNOTAVAIL: /* Can't assign requested address */
#endif
+#ifdef ETXTBSY
+ case ETXTBSY: /* (Apollo) file locked */
+#endif
#if defined(ENOSR) && (!defined(ENOBUFS) || (ENOBUFS != ENOSR))
case ENOSR: /* Out of streams resources */
#endif
@@ -1726,7 +1838,7 @@ lockfile(fd, filename, ext, type)
char *ext;
int type;
{
-# ifndef HASFLOCK
+# if !HASFLOCK
int action;
struct flock lfd;
@@ -1823,6 +1935,65 @@ lockfile(fd, filename, ext, type)
return FALSE;
}
/*
+** CHOWNSAFE -- tell if chown is "safe" (executable only by root)
+**
+** Parameters:
+** fd -- the file descriptor to check.
+**
+** Returns:
+** TRUE -- if only root can chown the file to an arbitrary
+** user.
+** FALSE -- if an arbitrary user can give away a file.
+*/
+
+bool
+chownsafe(fd)
+ int fd;
+{
+#ifdef __hpux
+ char *s;
+ int tfd;
+ uid_t o_uid, o_euid;
+ gid_t o_gid, o_egid;
+ bool rval;
+ struct stat stbuf;
+
+ o_uid = getuid();
+ o_euid = geteuid();
+ o_gid = getgid();
+ o_egid = getegid();
+ fstat(fd, &stbuf);
+ setresuid(stbuf.st_uid, stbuf.st_uid, -1);
+ setresgid(stbuf.st_gid, stbuf.st_gid, -1);
+ s = tmpnam(NULL);
+ tfd = open(s, O_RDONLY|O_CREAT, 0600);
+ rval = fchown(tfd, DefUid, DefGid) != 0;
+ close(tfd);
+ unlink(s);
+ setreuid(o_uid, o_euid);
+ setresgid(o_gid, o_egid, -1);
+ return rval;
+#else
+# ifdef _POSIX_CHOWN_RESTRICTED
+# if _POSIX_CHOWN_RESTRICTED == -1
+ return FALSE;
+# else
+ return TRUE;
+# endif
+# else
+# ifdef _PC_CHOWN_RESTRICTED
+ return fpathconf(fd, _PC_CHOWN_RESTRICTED) > 0;
+# else
+# ifdef BSD
+ return TRUE;
+# else
+ return FALSE;
+# endif
+# endif
+# endif
+#endif
+}
+ /*
** GETCFNAME -- return the name of the .cf file.
**
** Some systems (e.g., NeXT) determine this dynamically.
@@ -1877,46 +2048,104 @@ setvendor(vendor)
** STRTOL -- convert string to long integer
**
** For systems that don't have it in the C library.
+**
+** This is taken verbatim from the 4.4-Lite C library.
*/
#ifdef NEEDSTRTOL
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strtol.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+
+#include <limits.h>
+
+/*
+ * Convert a string to a long integer.
+ *
+ * Ignores `locale' stuff. Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+
long
-strtol(p, ep, b)
- char *p;
- char **ep;
- int b;
+strtol(nptr, endptr, base)
+ const char *nptr;
+ char **endptr;
+ register int base;
{
- long l = 0;
- char c;
- char maxd;
- int neg = 1;
-
- maxd = (b > 10) ? '9' : b + '0';
+ register const char *s = nptr;
+ register unsigned long acc;
+ register int c;
+ register unsigned long cutoff;
+ register int neg = 0, any, cutlim;
- if (p && *p == '-') {
- neg = -1;
- p++;
+ /*
+ * Skip white space and pick up leading +/- sign if any.
+ * If base is 0, allow 0x for hex and 0 for octal, else
+ * assume decimal; if base is already 16, allow 0x.
+ */
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else if (c == '+')
+ c = *s++;
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
}
- while (p && (c = *p)) {
- if (c >= '0' && c <= maxd) {
- l = l*b + *p++ - '0';
- continue;
- }
- if (c >= 'A' && c <= 'Z')
- c -= 'A' + 'a';
- c = c - 'a' + 10;
- if (b > c) {
- l = l*b + c;
- p++;
- continue;
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+
+ /*
+ * Compute the cutoff value between legal numbers and illegal
+ * numbers. That is the largest legal value, divided by the
+ * base. An input number that is greater than this value, if
+ * followed by a legal input character, is too big. One that
+ * is equal to this value may be valid or not; the limit
+ * between valid and invalid numbers is then based on the last
+ * digit. For instance, if the range for longs is
+ * [-2147483648..2147483647] and the input base is 10,
+ * cutoff will be set to 214748364 and cutlim to either
+ * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
+ * a value > 214748364, or equal but the next digit is > 7 (or 8),
+ * the number is too big, and we will return a range error.
+ *
+ * Set any if any `digits' consumed; make it negative to indicate
+ * overflow.
+ */
+ cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
+ cutlim = cutoff % (unsigned long)base;
+ cutoff /= (unsigned long)base;
+ for (acc = 0, any = 0;; c = *s++) {
+ if (isdigit(c))
+ c -= '0';
+ else if (isalpha(c))
+ c -= isupper(c) ? 'A' - 10 : 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
}
- break;
}
- l *= neg;
- if (ep)
- *ep = p;
- return l;
+ if (any < 0) {
+ acc = neg ? LONG_MIN : LONG_MAX;
+ errno = ERANGE;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != 0)
+ *endptr = (char *)(any ? s - 1 : nptr);
+ return (acc);
}
#endif
@@ -1998,7 +2227,7 @@ ni_propval(directory, propname)
char *directory;
char *propname;
{
- char *propval;
+ char *propval = NULL;
int i;
void *ni = NULL;
void *lastni = NULL;