2 * Copyright (c) 1998-2004 Sendmail, Inc. and its suppliers.
4 * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
5 * Copyright (c) 1988, 1993
6 * The Regents of the University of California. All rights reserved.
8 * By using this file, you agree to the terms and conditions set
9 * forth in the LICENSE file which can be found at the top level of
10 * the sendmail distribution.
16 #include <sm/errstring.h>
18 SM_RCSID("@(#)$Id: safefile.c,v 8.128 2004/09/30 18:15:49 ca Exp $")
22 ** SAFEFILE -- return 0 if a file exists and is safe for a user.
25 ** fn -- filename to check.
26 ** uid -- user id to compare against.
27 ** gid -- group id to compare against.
28 ** user -- user name to compare against (used for group
30 ** flags -- modifiers:
31 ** SFF_MUSTOWN -- "uid" must own this file.
32 ** SFF_NOSLINK -- file cannot be a symbolic link.
33 ** mode -- mode bits that must match.
34 ** st -- if set, points to a stat structure that will
35 ** get the stat info for the file.
38 ** 0 if fn exists, is owned by uid, and matches mode.
39 ** An errno otherwise. The actual errno is cleared.
46 safefile(fn, uid, gid, user, flags, mode, st)
56 register struct group *gr = NULL;
61 char fbuf[MAXPATHLEN];
64 sm_dprintf("safefile(%s, uid=%d, gid=%d, flags=%lx, mode=%o):\n",
65 fn, (int) uid, (int) gid, flags, mode);
67 if (sm_strlcpy(fbuf, fn, sizeof fbuf) >= sizeof fbuf)
70 sm_dprintf("\tpathname too long\n");
77 /* ignore SFF_SAFEDIRPATH if we are debugging */
78 if (RealUid != 0 && RunAsUid == RealUid)
79 flags &= ~SFF_SAFEDIRPATH;
81 /* first check to see if the file exists at all */
83 if ((bitset(SFF_NOSLINK, flags) ? lstat(fn, st)
87 # endif /* HASLSTAT */
91 else if (bitset(SFF_SETUIDOK, flags) &&
92 !bitset(S_IXUSR|S_IXGRP|S_IXOTH, st->st_mode) &&
96 ** If final file is set-user-ID, run as the owner of that
97 ** file. Gotta be careful not to reveal anything too
101 # ifdef SUID_ROOT_FILES_OK
102 if (bitset(S_ISUID, st->st_mode))
103 # else /* SUID_ROOT_FILES_OK */
104 if (bitset(S_ISUID, st->st_mode) && st->st_uid != 0 &&
105 st->st_uid != TrustedUid)
106 # endif /* SUID_ROOT_FILES_OK */
111 # ifdef SUID_ROOT_FILES_OK
112 if (bitset(S_ISGID, st->st_mode))
113 # else /* SUID_ROOT_FILES_OK */
114 if (bitset(S_ISGID, st->st_mode) && st->st_gid != 0)
115 # endif /* SUID_ROOT_FILES_OK */
119 checkpath = !bitset(SFF_NOPATHCHECK, flags) ||
120 (uid == 0 && !bitset(SFF_ROOTOK|SFF_OPENASROOT, flags));
121 if (bitset(SFF_NOWLINK, flags) && !bitset(SFF_SAFEDIRPATH, flags))
125 /* check the directory */
126 p = strrchr(fn, '/');
129 ret = safedirpath(".", uid, gid, user,
130 flags|SFF_SAFEDIRPATH, 0, 0);
135 ret = safedirpath(fn, uid, gid, user,
136 flags|SFF_SAFEDIRPATH, 0, 0);
141 /* directory is safe */
147 /* Need lstat() information if called stat() before */
148 if (!bitset(SFF_NOSLINK, flags) && lstat(fn, st) < 0)
152 sm_dprintf("\t%s\n", sm_errstring(ret));
155 # endif /* HASLSTAT */
156 /* directory is writable: disallow links */
165 p = strrchr(fn, '/');
168 ret = safedirpath(".", uid, gid, user, flags, 0, 0);
173 ret = safedirpath(fn, uid, gid, user, flags, 0, 0);
181 ** If the target file doesn't exist, check the directory to
182 ** ensure that it is writable by this user.
187 int ret = file_errno;
191 sm_dprintf("\t%s\n", sm_errstring(ret));
194 if (!bitset(SFF_CREAT, flags) || file_errno != ENOENT)
197 /* check to see if legal to create the file */
198 p = strrchr(dir, '/');
205 if (stat(dir, &stbuf) >= 0)
207 int md = S_IWRITE|S_IEXEC;
210 if (stbuf.st_uid == uid)
213 else if (uid == 0 && stbuf.st_uid == TrustedUid)
219 if (stbuf.st_gid == gid)
222 # ifndef NO_GROUP_SET
223 else if (user != NULL && !DontInitGroups &&
225 gr->gr_gid == stbuf.st_gid) ||
226 (gr = getgrgid(stbuf.st_gid)) != NULL))
230 for (gp = gr->gr_mem; *gp != NULL; gp++)
231 if (strcmp(*gp, user) == 0)
236 # endif /* ! NO_GROUP_SET */
240 if ((stbuf.st_mode & md) != md)
241 ret = errno = EACCES;
246 sm_dprintf("\t[final dir %s uid %d mode %lo] %s\n",
247 dir, (int) stbuf.st_uid,
248 (unsigned long) stbuf.st_mode,
252 st->st_mode = ST_MODE_NOFILE;
257 if (bitset(SFF_NOSLINK, flags) && S_ISLNK(st->st_mode))
260 sm_dprintf("\t[slink mode %lo]\tE_SM_NOSLINK\n",
261 (unsigned long) st->st_mode);
264 # endif /* S_ISLNK */
265 if (bitset(SFF_REGONLY, flags) && !S_ISREG(st->st_mode))
268 sm_dprintf("\t[non-reg mode %lo]\tE_SM_REGONLY\n",
269 (unsigned long) st->st_mode);
272 if (bitset(SFF_NOGWFILES, flags) &&
273 bitset(S_IWGRP, st->st_mode))
276 sm_dprintf("\t[write bits %lo]\tE_SM_GWFILE\n",
277 (unsigned long) st->st_mode);
280 if (bitset(SFF_NOWWFILES, flags) &&
281 bitset(S_IWOTH, st->st_mode))
284 sm_dprintf("\t[write bits %lo]\tE_SM_WWFILE\n",
285 (unsigned long) st->st_mode);
288 if (bitset(SFF_NOGRFILES, flags) && bitset(S_IRGRP, st->st_mode))
291 sm_dprintf("\t[read bits %lo]\tE_SM_GRFILE\n",
292 (unsigned long) st->st_mode);
295 if (bitset(SFF_NOWRFILES, flags) && bitset(S_IROTH, st->st_mode))
298 sm_dprintf("\t[read bits %lo]\tE_SM_WRFILE\n",
299 (unsigned long) st->st_mode);
302 if (!bitset(SFF_EXECOK, flags) &&
303 bitset(S_IWUSR|S_IWGRP|S_IWOTH, mode) &&
304 bitset(S_IXUSR|S_IXGRP|S_IXOTH, st->st_mode))
307 sm_dprintf("\t[exec bits %lo]\tE_SM_ISEXEC\n",
308 (unsigned long) st->st_mode);
311 if (bitset(SFF_NOHLINK, flags) && st->st_nlink != 1)
314 sm_dprintf("\t[link count %d]\tE_SM_NOHLINK\n",
319 if (uid == 0 && bitset(SFF_OPENASROOT, flags))
322 else if (uid == 0 && !bitset(SFF_ROOTOK, flags))
324 else if (st->st_uid == uid)
327 else if (uid == 0 && st->st_uid == TrustedUid)
333 if (st->st_gid == gid)
336 # ifndef NO_GROUP_SET
337 else if (user != NULL && !DontInitGroups &&
338 ((gr != NULL && gr->gr_gid == st->st_gid) ||
339 (gr = getgrgid(st->st_gid)) != NULL))
343 for (gp = gr->gr_mem; *gp != NULL; gp++)
344 if (strcmp(*gp, user) == 0)
349 # endif /* ! NO_GROUP_SET */
354 sm_dprintf("\t[uid %d, nlink %d, stat %lo, mode %lo] ",
355 (int) st->st_uid, (int) st->st_nlink,
356 (unsigned long) st->st_mode, (unsigned long) mode);
357 if ((st->st_uid == uid || st->st_uid == 0 ||
358 st->st_uid == TrustedUid ||
359 !bitset(SFF_MUSTOWN, flags)) &&
360 (st->st_mode & mode) == mode)
363 sm_dprintf("\tOK\n");
367 sm_dprintf("\tEACCES\n");
371 ** SAFEDIRPATH -- check to make sure a path to a directory is safe
373 ** Safe means not writable and owned by the right folks.
376 ** fn -- filename to check.
377 ** uid -- user id to compare against.
378 ** gid -- group id to compare against.
379 ** user -- user name to compare against (used for group
381 ** flags -- modifiers:
382 ** SFF_ROOTOK -- ok to use root permissions to open.
383 ** SFF_SAFEDIRPATH -- writable directories are considered
384 ** to be fatal errors.
385 ** level -- symlink recursive level.
386 ** offset -- offset into fn to start checking from.
389 ** 0 -- if the directory path is "safe".
390 ** else -- an error number associated with the path.
394 safedirpath(fn, uid, gid, user, flags, level, offset)
406 char *saveptr = NULL;
408 register struct group *gr = NULL;
409 char s[MAXLINKPATHLEN];
412 /* make sure we aren't in a symlink loop */
413 if (level > MAXSYMLINKS)
416 if (level < 0 || offset < 0 || offset > strlen(fn))
419 /* special case root directory */
424 sm_dprintf("safedirpath(%s, uid=%ld, gid=%ld, flags=%lx, level=%d, offset=%d):\n",
425 fn, (long) uid, (long) gid, flags, level, offset);
427 if (!bitnset(DBS_GROUPWRITABLEDIRPATHSAFE, DontBlameSendmail))
430 /* Make a modifiable copy of the filename */
431 if (sm_strlcpy(s, fn, sizeof s) >= sizeof s)
437 /* put back character */
450 /* Special case for root directory */
464 /* Heuristic: . and .. have already been checked */
465 enddir = strrchr(s, '/');
466 if (enddir != NULL &&
467 (strcmp(enddir, "/..") == 0 ||
468 strcmp(enddir, "/.") == 0))
472 sm_dprintf("\t[dir %s]\n", s);
475 ret = lstat(s, &stbuf);
476 # else /* HASLSTAT */
477 ret = stat(s, &stbuf);
478 # endif /* HASLSTAT */
486 /* Follow symlinks */
487 if (S_ISLNK(stbuf.st_mode))
491 char buf[MAXPATHLEN];
492 char fullbuf[MAXLINKPATHLEN];
494 memset(buf, '\0', sizeof buf);
495 linklen = readlink(s, buf, sizeof buf);
501 if (linklen >= sizeof buf)
503 /* file name too long for buffer */
504 ret = errno = EINVAL;
513 /* If path is the same, avoid rechecks */
514 while (s[offset] == buf[offset] &&
518 if (s[offset] == '\0' && buf[offset] == '\0')
520 /* strings match, symlink loop */
524 /* back off from the mismatch */
528 /* Make sure we are at a directory break */
533 while (buf[offset] != '/' &&
541 /* Include the trailing slash */
549 sptr = strrchr(s, '/');
553 offset = sptr + 1 - s;
554 if (sm_strlcpyn(fullbuf,
558 sm_strlcat(fullbuf, buf,
569 if (sm_strlcpy(fullbuf, buf,
579 ret = safedirpath(target, uid, gid, user, flags,
584 /* Don't check permissions on the link file itself */
589 if ((uid == 0 || bitset(SFF_SAFEDIRPATH, flags)) &&
591 !(bitnset(DBS_TRUSTSTICKYBIT, DontBlameSendmail) &&
592 bitset(S_ISVTX, stbuf.st_mode)) &&
594 bitset(mode, stbuf.st_mode))
597 sm_dprintf("\t[dir %s] mode %lo ",
598 s, (unsigned long) stbuf.st_mode);
599 if (bitset(SFF_SAFEDIRPATH, flags))
601 if (bitset(S_IWOTH, stbuf.st_mode))
606 sm_dprintf("FATAL\n");
610 sm_dprintf("WARNING\n");
612 message("051 WARNING: %s writable directory %s",
613 bitset(S_IWOTH, stbuf.st_mode)
618 if (uid == 0 && !bitset(SFF_ROOTOK|SFF_OPENASROOT, flags))
620 if (bitset(S_IXOTH, stbuf.st_mode))
627 ** Let OS determine access to file if we are not
628 ** running as a privileged user. This allows ACLs
629 ** to work. Also, if opening as root, assume we can
630 ** scan the directory.
632 if (geteuid() != 0 || bitset(SFF_OPENASROOT, flags))
635 if (stbuf.st_uid == uid &&
636 bitset(S_IXUSR, stbuf.st_mode))
638 if (stbuf.st_gid == gid &&
639 bitset(S_IXGRP, stbuf.st_mode))
641 # ifndef NO_GROUP_SET
642 if (user != NULL && !DontInitGroups &&
643 ((gr != NULL && gr->gr_gid == stbuf.st_gid) ||
644 (gr = getgrgid(stbuf.st_gid)) != NULL))
648 for (gp = gr->gr_mem; gp != NULL && *gp != NULL; gp++)
649 if (strcmp(*gp, user) == 0)
651 if (gp != NULL && *gp != NULL &&
652 bitset(S_IXGRP, stbuf.st_mode))
655 # endif /* ! NO_GROUP_SET */
656 if (!bitset(S_IXOTH, stbuf.st_mode))
663 sm_dprintf("\t[dir %s] %s\n", fn,
664 ret == 0 ? "OK" : sm_errstring(ret));
668 ** SAFEOPEN -- do a file open with extra checking
671 ** fn -- the file name to open.
672 ** omode -- the open-style mode flags.
673 ** cmode -- the create-style mode flags.
674 ** sff -- safefile flags.
681 safeopen(fn, omode, cmode, sff)
689 #endif /* !NOFTRUNCATE */
696 sm_dprintf("safeopen: fn=%s, omode=%x, cmode=%x, sff=%lx\n",
697 fn, omode, cmode, sff);
699 if (bitset(O_CREAT, omode))
703 switch (omode & O_ACCMODE)
714 smode = S_IREAD|S_IWRITE;
721 if (bitset(SFF_OPENASROOT, sff))
722 rval = safefile(fn, RunAsUid, RunAsGid, RunAsUserName,
725 rval = safefile(fn, RealUid, RealGid, RealUserName,
732 if (stb.st_mode == ST_MODE_NOFILE && bitset(SFF_CREAT, sff))
733 omode |= O_CREAT | (bitset(SFF_NOTEXCL, sff) ? 0 : O_EXCL);
734 else if (bitset(SFF_CREAT, sff) && bitset(O_EXCL, omode))
736 /* The file exists so an exclusive create would fail */
742 truncate = bitset(O_TRUNC, omode);
745 #endif /* !NOFTRUNCATE */
747 fd = dfopen(fn, omode, cmode, sff);
750 if (filechanged(fn, fd, &stb))
752 syserr("554 5.3.0 cannot open: file %s changed after open", fn);
754 errno = E_SM_FILECHANGE;
760 ftruncate(fd, (off_t) 0) < 0)
765 syserr("554 5.3.0 cannot open: file %s could not be truncated",
771 #endif /* !NOFTRUNCATE */
776 ** SAFEFOPEN -- do a file open with extra checking
779 ** fn -- the file name to open.
780 ** omode -- the open-style mode flags.
781 ** cmode -- the create-style mode flags.
782 ** sff -- safefile flags.
789 safefopen(fn, omode, cmode, sff)
800 switch (omode & O_ACCMODE)
803 fmode = SM_IO_RDONLY;
807 if (bitset(O_APPEND, omode))
808 fmode = SM_IO_APPEND;
810 fmode = SM_IO_WRONLY;
814 if (bitset(O_TRUNC, omode))
815 fmode = SM_IO_RDWRTR;
816 else if (bitset(O_APPEND, omode))
817 fmode = SM_IO_APPENDRW;
823 syserr("554 5.3.5 safefopen: unknown omode %o", omode);
826 fd = safeopen(fn, omode, cmode, sff);
831 sm_dprintf("safefopen: safeopen failed: %s\n",
832 sm_errstring(errno));
836 fp = sm_io_open(SmFtStdiofd, SM_TIME_DEFAULT,
837 (void *) &fd, fmode, NULL);
844 sm_dprintf("safefopen: fdopen(%s, %d) failed: omode=%x, sff=%lx, err=%s\n",
845 fn, fmode, omode, sff, sm_errstring(errno));
852 ** FILECHANGED -- check to see if file changed after being opened
855 ** fn -- pathname of file to check.
856 ** fd -- file descriptor to check.
857 ** stb -- stat structure from before open.
860 ** true -- if a problem was detected.
861 ** false -- if this file is still the same.
865 filechanged(fn, fd, stb)
872 if (stb->st_mode == ST_MODE_NOFILE)
874 # if HASLSTAT && BOGUS_O_EXCL
875 /* only necessary if exclusive open follows symbolic links */
876 if (lstat(fn, stb) < 0 || stb->st_nlink != 1)
878 # else /* HASLSTAT && BOGUS_O_EXCL */
880 # endif /* HASLSTAT && BOGUS_O_EXCL */
882 if (fstat(fd, &sta) < 0)
885 if (sta.st_nlink != stb->st_nlink ||
886 sta.st_dev != stb->st_dev ||
887 sta.st_ino != stb->st_ino ||
888 # if HAS_ST_GEN && 0 /* AFS returns garbage in st_gen */
889 sta.st_gen != stb->st_gen ||
890 # endif /* HAS_ST_GEN && 0 */
891 sta.st_uid != stb->st_uid ||
892 sta.st_gid != stb->st_gid)
896 sm_dprintf("File changed after opening:\n");
897 sm_dprintf(" nlink = %ld/%ld\n",
898 (long) stb->st_nlink, (long) sta.st_nlink);
899 sm_dprintf(" dev = %ld/%ld\n",
900 (long) stb->st_dev, (long) sta.st_dev);
901 sm_dprintf(" ino = %llu/%llu\n",
902 (ULONGLONG_T) stb->st_ino,
903 (ULONGLONG_T) sta.st_ino);
905 sm_dprintf(" gen = %ld/%ld\n",
906 (long) stb->st_gen, (long) sta.st_gen);
907 # endif /* HAS_ST_GEN */
908 sm_dprintf(" uid = %ld/%ld\n",
909 (long) stb->st_uid, (long) sta.st_uid);
910 sm_dprintf(" gid = %ld/%ld\n",
911 (long) stb->st_gid, (long) sta.st_gid);
919 ** DFOPEN -- determined file open
921 ** This routine has the semantics of open, except that it will
922 ** keep trying a few times to make this happen. The idea is that
923 ** on very loaded systems, we may run out of resources (inodes,
924 ** whatever), so this tries to get around it.
928 dfopen(filename, omode, cmode, sff)
938 for (tries = 0; tries < 10; tries++)
940 (void) sleep((unsigned) (10 * tries));
942 fd = open(filename, omode, cmode);
947 case ENFILE: /* system file table full */
948 case EINTR: /* interrupted syscall */
950 case ETXTBSY: /* Apollo: net file locked */
956 if (!bitset(SFF_NOLOCK, sff) &&
958 fstat(fd, &st) >= 0 &&
963 /* lock the file to avoid accidental conflicts */
964 if ((omode & O_ACCMODE) != O_RDONLY)
968 if (bitset(SFF_NBLOCK, sff))
971 if (!lockfile(fd, filename, NULL, locktype))
973 int save_errno = errno;