|
|
1.1 ! root 1: /* ufopen.c ! 2: Open a file with the permissions of the invoking user. ! 3: ! 4: Copyright (C) 1992 Ian Lance Taylor ! 5: ! 6: This file is part of the Taylor UUCP package. ! 7: ! 8: This program is free software; you can redistribute it and/or ! 9: modify it under the terms of the GNU General Public License as ! 10: published by the Free Software Foundation; either version 2 of the ! 11: License, or (at your option) any later version. ! 12: ! 13: This program is distributed in the hope that it will be useful, but ! 14: WITHOUT ANY WARRANTY; without even the implied warranty of ! 15: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ! 16: General Public License for more details. ! 17: ! 18: You should have received a copy of the GNU General Public License ! 19: along with this program; if not, write to the Free Software ! 20: Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ! 21: ! 22: The author of the program may be contacted at [email protected] or ! 23: c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254. ! 24: */ ! 25: ! 26: #include "uucp.h" ! 27: ! 28: #include "uudefs.h" ! 29: #include "sysdep.h" ! 30: #include "system.h" ! 31: ! 32: #include <errno.h> ! 33: ! 34: #if HAVE_FCNTL_H ! 35: #include <fcntl.h> ! 36: #else ! 37: #if HAVE_SYS_FILE_H ! 38: #include <sys/file.h> ! 39: #endif ! 40: #endif ! 41: ! 42: #ifndef O_RDONLY ! 43: #define O_RDONLY 0 ! 44: #define O_WRONLY 1 ! 45: #define O_RDWR 2 ! 46: #endif ! 47: ! 48: #ifndef O_NOCTTY ! 49: #define O_NOCTTY 0 ! 50: #endif ! 51: ! 52: #ifndef FD_CLOEXEC ! 53: #define FD_CLOEXEC 1 ! 54: #endif ! 55: ! 56: /* Local functions. */ ! 57: ! 58: static boolean fsuser_perms P((uid_t *pieuid)); ! 59: static boolean fsuucp_perms P((long ieuid)); ! 60: ! 61: /* Switch to permissions of the invoking user. */ ! 62: ! 63: static boolean ! 64: fsuser_perms (pieuid) ! 65: uid_t *pieuid; ! 66: { ! 67: uid_t ieuid, iuid; ! 68: ! 69: ieuid = geteuid (); ! 70: iuid = getuid (); ! 71: if (pieuid != NULL) ! 72: *pieuid = ieuid; ! 73: ! 74: #if HAVE_SETREUID ! 75: /* Swap the effective user id and the real user id. We can then ! 76: swap them back again when we want to return to the uucp user's ! 77: permissions. */ ! 78: if (setreuid (ieuid, iuid) < 0) ! 79: { ! 80: ulog (LOG_ERROR, "setreuid (%ld, %ld): %s", ! 81: (long) ieuid, (long) iuid, strerror (errno)); ! 82: return FALSE; ! 83: } ! 84: #else /* ! HAVE_SETREUID */ ! 85: #if HAVE_SAVED_SETUID ! 86: /* Set the effective user id to the real user id. Since the ! 87: effective user id is saved (it's the saved setuid) we will able ! 88: to set back to it later. If the real user id is root we will not ! 89: be able to switch back and forth, so don't even try. */ ! 90: if (iuid != 0) ! 91: { ! 92: if (setuid (iuid) < 0) ! 93: { ! 94: ulog (LOG_ERROR, "setuid (%ld): %s", (long) iuid, strerror (errno)); ! 95: return FALSE; ! 96: } ! 97: } ! 98: #else /* ! HAVE_SAVED_SETUID */ ! 99: /* There's no way to switch between real permissions and effective ! 100: permissions. Just try to open the file with the uucp ! 101: permissions. */ ! 102: #endif /* ! HAVE_SAVED_SETUID */ ! 103: #endif /* ! HAVE_SETREUID */ ! 104: ! 105: return TRUE; ! 106: } ! 107: ! 108: /* Restore the uucp permissions. */ ! 109: ! 110: /*ARGSUSED*/ ! 111: static boolean ! 112: fsuucp_perms (ieuid) ! 113: long ieuid; ! 114: { ! 115: #if HAVE_SETREUID ! 116: /* Swap effective and real user id's back to what they were. */ ! 117: if (! fsuser_perms ((uid_t *) NULL)) ! 118: return FALSE; ! 119: #else /* ! HAVE_SETREUID */ ! 120: #if HAVE_SAVED_SETUID ! 121: /* Set ourselves back to our original effective user id. */ ! 122: if (setuid ((uid_t) ieuid) < 0) ! 123: { ! 124: ulog (LOG_ERROR, "setuid (%ld): %s", (long) ieuid, strerror (errno)); ! 125: /* Is this error message helpful or confusing? */ ! 126: if (errno == EPERM) ! 127: ulog (LOG_ERROR, ! 128: "Probably HAVE_SAVED_SETUID in policy.h should be set to 0"); ! 129: return FALSE; ! 130: } ! 131: #else /* ! HAVE_SAVED_SETUID */ ! 132: /* We didn't switch, no need to switch back. */ ! 133: #endif /* ! HAVE_SAVED_SETUID */ ! 134: #endif /* ! HAVE_SETREUID */ ! 135: ! 136: return TRUE; ! 137: } ! 138: ! 139: /* Open a file with the permissions of the invoking user. Ignore the ! 140: fbinary argument since Unix has no distinction between text and ! 141: binary files. */ ! 142: ! 143: /*ARGSUSED*/ ! 144: openfile_t ! 145: esysdep_user_fopen (zfile, frd, fbinary) ! 146: const char *zfile; ! 147: boolean frd; ! 148: boolean fbinary; ! 149: { ! 150: uid_t ieuid; ! 151: openfile_t e; ! 152: const char *zerr; ! 153: int o = 0; ! 154: ! 155: if (! fsuser_perms (&ieuid)) ! 156: return EFILECLOSED; ! 157: ! 158: zerr = NULL; ! 159: ! 160: #if USE_STDIO ! 161: e = fopen (zfile, frd ? "r" : "w"); ! 162: if (e == NULL) ! 163: zerr = "fopen"; ! 164: else ! 165: o = fileno (e); ! 166: #else ! 167: if (frd) ! 168: { ! 169: e = open ((char *) zfile, O_RDONLY | O_NOCTTY, 0); ! 170: zerr = "open"; ! 171: } ! 172: else ! 173: { ! 174: e = creat ((char *) zfile, IPUBLIC_FILE_MODE); ! 175: zerr = "creat"; ! 176: } ! 177: if (e >= 0) ! 178: { ! 179: o = e; ! 180: zerr = NULL; ! 181: } ! 182: #endif ! 183: ! 184: if (! fsuucp_perms ((long) ieuid)) ! 185: { ! 186: if (ffileisopen (e)) ! 187: (void) ffileclose (e); ! 188: return EFILECLOSED; ! 189: } ! 190: ! 191: if (zerr != NULL) ! 192: { ! 193: ulog (LOG_ERROR, "%s (%s): %s", zerr, zfile, strerror (errno)); ! 194: #if ! HAVE_SETREUID ! 195: /* Are these error messages helpful or confusing? */ ! 196: #if HAVE_SAVED_SETUID ! 197: if (errno == EACCES && getuid () == 0) ! 198: ulog (LOG_ERROR, ! 199: "The superuser may only transfer files that are readable by %s", ! 200: OWNER); ! 201: #else ! 202: if (errno == EACCES) ! 203: ulog (LOG_ERROR, ! 204: "You may only transfer files that are readable by %s", OWNER); ! 205: #endif ! 206: #endif /* ! HAVE_SETREUID */ ! 207: return EFILECLOSED; ! 208: } ! 209: ! 210: if (fcntl (o, F_SETFD, fcntl (o, F_GETFD, 0) | FD_CLOEXEC) < 0) ! 211: { ! 212: ulog (LOG_ERROR, "fcntl (FD_CLOEXEC): %s", strerror (errno)); ! 213: (void) ffileclose (e); ! 214: return EFILECLOSED; ! 215: } ! 216: ! 217: return e; ! 218: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.