1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168
|
/*
* file.c contains file open/read/write routines to be used to open
* files with the access permissions of the real UID instead of the
* effective UID. This allows IRCII to be run setuid->root. If it
* has effective UID == root, it will then use privileged ports to
* connect to servers, allowing the servers, some day, to take
* advantage of this information to ensure that the user names are
* who they claim to be.
*
* It can also be run setuid->something else, with ircio being
* setuid->root and only runable by the given GID.
*
* Copyright (c) 1991 Troy Rollo
*
* See HELP IRCII COPYRIGHT for details.
*/
#ifndef lint
static char rcsid[] = "@(#)$Id: file.c,v 1.11 1996/06/19 07:18:42 mrg Exp $";
#endif /* lint */
#include "irc.h"
#include <sys/stat.h>
#ifdef PRIV_PORT
# undef PRIV_PORT
#endif /* PRIV_PORT */
int
directory_writeable(file)
char *file;
{
char dir[BIG_BUFFER_SIZE+1];
char *ptr;
strmcpy(dir, file, BIG_BUFFER_SIZE);
if (ptr = rindex(dir, '/'))
{
if (ptr == dir
#ifdef APOLLO
|| (ptr == dir+1 && *dir == '/')
#endif /* APOLLO */
)
ptr++;
*ptr = '\0';
}
else
strcpy(dir, ".");
return (!access(dir, W_OK|X_OK));
}
int
ruid_open(filename, flags, mode)
char *filename;
int flags;
int mode;
{
int access_flags;
int fd;
switch(flags&(O_RDONLY|O_WRONLY|O_RDWR))
{
case O_RDWR:
access_flags = R_OK|W_OK;
break;
case O_RDONLY:
access_flags = R_OK;
break;
case O_WRONLY:
access_flags = W_OK;
break;
}
if (!access(filename, access_flags))
return open(filename, flags, mode);
else if ((flags&O_CREAT) == O_CREAT && directory_writeable(filename))
{
fd = open(filename, flags, mode);
chown(filename, getuid(), getgid());
return fd;
}
else
return -1;
}
FILE *
ruid_fopen(filename, mode)
char *filename;
char *mode;
{
int access_flags;
FILE *fp;
char *tm;
access_flags = 0;
for (tm = mode; *tm != '\0'; tm++)
{
switch (*tm)
{
case '+':
access_flags |= W_OK|R_OK;
break;
case 'r':
access_flags |= R_OK;
break;
case 'w':
case 'a':
access_flags |= W_OK;
break;
case 't': /* Text and binary - harmless */
case 'b':
break;
default: /* Calls are guilty unless proven innocent */
return NULL; /* :P to all those who think otherwise! */
}
}
if (!access(filename, access_flags))
return fopen(filename, mode);
else if ((access_flags&W_OK) == W_OK && directory_writeable(filename))
{
fp = fopen(filename, mode);
chown(filename, getuid(), getgid());
return fp;
}
else
return NULL;
}
int
ruid_unlink(filename)
char *filename;
{
if (!access(filename, W_OK) && directory_writeable(filename))
unlink(filename);
}
int
ruid_system(command)
char *command;
{
int pid;
switch (pid = fork())
{
case 0:
setuid(getuid());
setgid(getgid());
system(command);
_exit(0);
break;
case -1:
return -1;
default:
while(wait(0) != pid);
return 0;
}
}
int
ruid_stat(path, buf)
char *path;
struct stat *buf;
{
if (!access(path, 0))
return -1;
else
return stat(path, buf);
}
|