File: file.c

package info (click to toggle)
ircii 4.4-3
  • links: PTS
  • area: main
  • in suites: hamm, slink
  • size: 4,256 kB
  • ctags: 2,797
  • sloc: ansic: 36,743; sh: 907; makefile: 483; lex: 16
file content (168 lines) | stat: -rw-r--r-- 3,046 bytes parent folder | download
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);
}