1 /*
2 
3 kHTTPd -- the next generation
4 
5 Sysctl interface
6 
7 */
8 /****************************************************************
9  *	This program is free software; you can redistribute it and/or modify
10  *	it under the terms of the GNU General Public License as published by
11  *	the Free Software Foundation; either version 2, or (at your option)
12  *	any later version.
13  *
14  *	This program is distributed in the hope that it will be useful,
15  *	but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *	GNU General Public License for more details.
18  *
19  *	You should have received a copy of the GNU General Public License
20  *	along with this program; if not, write to the Free Software
21  *	Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22  *
23  ****************************************************************/
24 
25 
26 #include <linux/kernel.h>
27 #include <linux/errno.h>
28 #include <linux/slab.h>
29 #include <linux/net.h>
30 #include <linux/sched.h>
31 #include <linux/skbuff.h>
32 #include <linux/smp_lock.h>
33 #include <linux/sysctl.h>
34 #include <linux/un.h>
35 #include <linux/unistd.h>
36 
37 #include <net/ip.h>
38 #include <net/sock.h>
39 #include <net/tcp.h>
40 
41 #include <asm/atomic.h>
42 #include <asm/semaphore.h>
43 #include <asm/processor.h>
44 #include <asm/uaccess.h>
45 
46 #include <linux/file.h>
47 #include "prototypes.h"
48 
49 
50 
51 char 	sysctl_khttpd_docroot[200] = "/var/www";
52 int 	sysctl_khttpd_stop 	= 0;
53 int 	sysctl_khttpd_start 	= 0;
54 int 	sysctl_khttpd_unload 	= 0;
55 int 	sysctl_khttpd_clientport = 80;
56 int 	sysctl_khttpd_permreq    = S_IROTH; /* "other" read-access is required by default*/
57 int 	sysctl_khttpd_permforbid = S_IFDIR | S_ISVTX | S_IXOTH | S_IXGRP | S_IXUSR;
58  				/* forbidden is execute, directory and sticky*/
59 int 	sysctl_khttpd_logging 	= 0;
60 int 	sysctl_khttpd_serverport= 8080;
61 
62 char	sysctl_khttpd_dynamicstring[200];
63 int 	sysctl_khttpd_sloppymime= 0;
64 int	sysctl_khttpd_threads	= 2;
65 int	sysctl_khttpd_maxconnect = 1000;
66 
67 atomic_t        khttpd_stopCount;
68 
69 static struct ctl_table_header *khttpd_table_header;
70 
71 static int sysctl_SecureString(ctl_table *table, int *name, int nlen,
72 		  void *oldval, size_t *oldlenp,
73 		  void *newval, size_t newlen, void **context);
74 static int proc_dosecurestring(ctl_table *table, int write, struct file *filp,
75 		  void *buffer, size_t *lenp);
76 static int khttpd_stop_wrap_proc_dointvec(ctl_table *table, int write, struct file *filp,
77 		  void *buffer, size_t *lenp);
78 
79 
80 static ctl_table khttpd_table[] = {
81 	{	NET_KHTTPD_DOCROOT,
82 		"documentroot",
83 		&sysctl_khttpd_docroot,
84 		sizeof(sysctl_khttpd_docroot),
85 		0644,
86 		NULL,
87 		proc_dostring,
88 		&sysctl_string,
89 		NULL,
90 		NULL,
91 		NULL
92 	},
93 	{	NET_KHTTPD_STOP,
94 		"stop",
95 		&sysctl_khttpd_stop,
96 		sizeof(int),
97 		0644,
98 		NULL,
99 		khttpd_stop_wrap_proc_dointvec,
100 		&sysctl_intvec,
101 		NULL,
102 		NULL,
103 		NULL
104 	},
105 	{	NET_KHTTPD_START,
106 		"start",
107 		&sysctl_khttpd_start,
108 		sizeof(int),
109 		0644,
110 		NULL,
111 		proc_dointvec,
112 		&sysctl_intvec,
113 		NULL,
114 		NULL,
115 		NULL
116 	},
117 	{	NET_KHTTPD_UNLOAD,
118 		"unload",
119 		&sysctl_khttpd_unload,
120 		sizeof(int),
121 		0644,
122 		NULL,
123 		proc_dointvec,
124 		&sysctl_intvec,
125 		NULL,
126 		NULL,
127 		NULL
128 	},
129 	{	NET_KHTTPD_THREADS,
130 		"threads",
131 		&sysctl_khttpd_threads,
132 		sizeof(int),
133 		0644,
134 		NULL,
135 		proc_dointvec,
136 		&sysctl_intvec,
137 		NULL,
138 		NULL,
139 		NULL
140 	},
141 	{	NET_KHTTPD_MAXCONNECT,
142 		"maxconnect",
143 		&sysctl_khttpd_maxconnect,
144 		sizeof(int),
145 		0644,
146 		NULL,
147 		proc_dointvec,
148 		&sysctl_intvec,
149 		NULL,
150 		NULL,
151 		NULL
152 	},
153 	{	NET_KHTTPD_SLOPPYMIME,
154 		"sloppymime",
155 		&sysctl_khttpd_sloppymime,
156 		sizeof(int),
157 		0644,
158 		NULL,
159 		proc_dointvec,
160 		&sysctl_intvec,
161 		NULL,
162 		NULL,
163 		NULL
164 	},
165 	{	NET_KHTTPD_CLIENTPORT,
166 		"clientport",
167 		&sysctl_khttpd_clientport,
168 		sizeof(int),
169 		0644,
170 		NULL,
171 		proc_dointvec,
172 		&sysctl_intvec,
173 		NULL,
174 		NULL,
175 		NULL
176 	},
177 	{	NET_KHTTPD_PERMREQ,
178 		"perm_required",
179 		&sysctl_khttpd_permreq,
180 		sizeof(int),
181 		0644,
182 		NULL,
183 		proc_dointvec,
184 		&sysctl_intvec,
185 		NULL,
186 		NULL,
187 		NULL
188 	},
189 	{	NET_KHTTPD_PERMFORBID,
190 		"perm_forbid",
191 		&sysctl_khttpd_permforbid,
192 		sizeof(int),
193 		0644,
194 		NULL,
195 		proc_dointvec,
196 		&sysctl_intvec,
197 		NULL,
198 		NULL,
199 		NULL
200 	},
201 	{	NET_KHTTPD_LOGGING,
202 		"logging",
203 		&sysctl_khttpd_logging,
204 		sizeof(int),
205 		0644,
206 		NULL,
207 		proc_dointvec,
208 		&sysctl_intvec,
209 		NULL,
210 		NULL,
211 		NULL
212 	},
213 	{	NET_KHTTPD_SERVERPORT,
214 		"serverport",
215 		&sysctl_khttpd_serverport,
216 		sizeof(int),
217 		0644,
218 		NULL,
219 		proc_dointvec,
220 		&sysctl_intvec,
221 		NULL,
222 		NULL,
223 		NULL
224 	},
225 	{	NET_KHTTPD_DYNAMICSTRING,
226 		"dynamic",
227 		&sysctl_khttpd_dynamicstring,
228 		sizeof(sysctl_khttpd_dynamicstring),
229 		0644,
230 		NULL,
231 		proc_dosecurestring,
232 		&sysctl_SecureString,
233 		NULL,
234 		NULL,
235 		NULL
236 	},
237 	{0,0,0,0,0,0,0,0,0,0,0}	};
238 
239 
240 static ctl_table khttpd_dir_table[] = {
241 	{NET_KHTTPD, "khttpd", NULL, 0, 0555, khttpd_table,0,0,0,0,0},
242 	{0,0,0,0,0,0,0,0,0,0,0}
243 };
244 
245 static ctl_table khttpd_root_table[] = {
246 	{CTL_NET, "net", NULL, 0, 0555, khttpd_dir_table,0,0,0,0,0},
247 	{0,0,0,0,0,0,0,0,0,0,0}
248 };
249 
250 
StartSysctl(void)251 void StartSysctl(void)
252 {
253 	khttpd_table_header = register_sysctl_table(khttpd_root_table,1);
254 }
255 
256 
EndSysctl(void)257 void EndSysctl(void)
258 {
259 	unregister_sysctl_table(khttpd_table_header);
260 }
261 
proc_dosecurestring(ctl_table * table,int write,struct file * filp,void * buffer,size_t * lenp)262 static int proc_dosecurestring(ctl_table *table, int write, struct file *filp,
263 		  void *buffer, size_t *lenp)
264 {
265 	size_t len;
266 	char *p, c=0;
267 	char String[256];
268 
269 	if ((table->data==0) || (table->maxlen==0) || (*lenp==0) ||
270 	    ((filp->f_pos!=0) && (write==0))) {
271 		*lenp = 0;
272 		return 0;
273 	}
274 
275 	if (write!=0) {
276 		len = 0;
277 		p = buffer;
278 		while (len < *lenp) {
279 			if(get_user(c, p++))
280 				return -EFAULT;
281 			if (c == 0 || c == '\n')
282 				break;
283 			len++;
284 		}
285 		if (len >= table->maxlen)
286 			len = table->maxlen-1;
287 		if(copy_from_user(String, buffer,(unsigned long)len))
288 			return -EFAULT;
289 		((char *) String)[len] = 0;
290 		filp->f_pos += *lenp;
291 		AddDynamicString(String);
292 	} else {
293 		GetSecureString(String);
294 		len = strlen(String);
295 		if (len > table->maxlen)
296 			len = table->maxlen;
297 		if (len > *lenp)
298 			len = *lenp;
299 		if (len!=0)
300 			if(copy_to_user(buffer, String,(unsigned long)len))
301 				return -EFAULT;
302 		if (len < *lenp) {
303 			if(put_user('\n', ((char *) buffer) + len))
304 				return -EFAULT;
305 			len++;
306 		}
307 		*lenp = len;
308 		filp->f_pos += len;
309 	}
310 	return 0;
311 }
312 
313 /* A wrapper around proc_dointvec that computes
314  * khttpd_stopCount = # of times sysctl_khttpd_stop has gone true
315  * Sensing sysctl_khttpd_stop in other threads is racy;
316  * sensing khttpd_stopCount in other threads is not.
317  */
khttpd_stop_wrap_proc_dointvec(ctl_table * table,int write,struct file * filp,void * buffer,size_t * lenp)318 static int khttpd_stop_wrap_proc_dointvec(ctl_table *table, int write, struct file *filp,
319 		  void *buffer, size_t *lenp)
320 {
321 	int rv;
322 	int oldstop = sysctl_khttpd_stop;
323 	rv = proc_dointvec(table, write, filp, buffer, lenp);
324 	if (sysctl_khttpd_stop && !oldstop)
325 		atomic_inc(&khttpd_stopCount);
326 
327 	return rv;
328 }
329 
330 
sysctl_SecureString(ctl_table * table,int * name,int nlen,void * oldval,size_t * oldlenp,void * newval,size_t newlen,void ** context)331 static int sysctl_SecureString (/*@unused@*/ctl_table *table,
332 				/*@unused@*/int *name,
333 				/*@unused@*/int nlen,
334 		  		/*@unused@*/void *oldval,
335 		  		/*@unused@*/size_t *oldlenp,
336 		  		/*@unused@*/void *newval,
337 		  		/*@unused@*/size_t newlen,
338 		  		/*@unused@*/void **context)
339 {
340 	return -ENOSYS;
341 }
342