1 /* ******** netUstad: Network Ustadi (Network Master) *********/
2 /* This software is Copyright (C) 2004 by Ozkan KIRIK.        */
3 /* Permission is granted to redistribute and modify this      */
4 /* software under the terms of the GNU General Public License */
5 /* available at http://www.gnu.org/                           */
6 /**************************************************************/
7 
8 #include "common.h"
9 
10 /******************/
11 /* Manage Request */
12 /******************/
13 void
accept_request(nunetwork_socket client,struct nunetwork_headerstruct * headerbuf)14 accept_request(nunetwork_socket client, struct nunetwork_headerstruct *headerbuf)
15 {
16 	int auth_form = 0;
17 	int p = 0,i,t;
18 	char path[512], parameters[512];
19 	char env_str[512];
20 	struct stat st;
21 	int cgi = 0;		/* becomes true if server decides this is a CGI program */
22 	char *query_string = NULL;
23 	char *tmp_str = NULL;
24 	char *tmp_url = NULL;
25 	char *client_sid = " ";
26 	char method[5];
27 	char url[256];
28 	char header[256];
29 	char value[256];
30 	/* Vars for processing HTTP 304*/
31 	/*enum en_day { Sun = 0, Mon, Tue, Wed, Thu, Fri, Sat} days;
32 	enum en_month { Jan = 0, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec } months;*/
33 	/*char *withoutsession[] = {
34 			"/netustad.css",
35 			"/authform",
36 			"/images/bg.png",
37 			"/images/buton_0.png",
38 			"/images/buton_1.png",
39 			"/images/buton_2.png",
40 			"/images/buton_3.png",
41 			"/images/buton_4.png",
42 			"/images/buton_5.png",
43 			"/images/buton_6.png",
44 			"/images/buton_7.png",
45 			"/images/banner.png",
46 			"/images/banner-alt.png",
47 			"/images/menu_login.png",
48 			"/images/menu_rulelist.png",
49 			"/images/menu_addrule.png",
50 			"/images/menu_logout.png",
51 			NULL
52 			};
53 	int ifwithoutsession=0;*/
54 	/*struct tm zamanstr;
55 	time_t zaman_t;
56 	char str4[5]="123";*/
57 	char *start;
58 	/*****************************************/
59 
60 	/* Processing the header buffer */
61 	/* GET request is saved to be processed at the end*/
62 	for (t=0; t< headerbuf->number_of_headers; t++)  {
63 
64 		if (!strcasecmp(headerbuf->headers[t].header_id, "POST") ) {
65 			/* sorry maybe next time */
66 			unimplemented(client);
67 			return;
68 		} else if (!strcasecmp(headerbuf->headers[t].header_id, "HEAD")) {
69 			tmp_url = strdup(headerbuf->headers[t].header_value);
70 
71 			/*Getting the requested url */
72 			start = headerbuf->headers[t].header_value;
73 			while (*start!=' ' || *start!='\t') start++;
74 			tmp_url = strstr(start, "HTTP/") - 1;
75 			while ( *tmp_url!= ' ' || *tmp_url != '\t' ) tmp_url--;
76 			snprintf(url, tmp_url - start + 1, "script%s", start );
77 			headers(client, url);
78 			return;
79 		} else if (!strcasecmp(headerbuf->headers[t].header_id, "GET")) {
80 			/* this is it ... getting the method and the url without HTTP id */
81 			strncpy(method, headerbuf->headers[t].header_id, sizeof(method));
82 			strncpy(url, headerbuf->headers[t].header_value, sizeof(url));
83 			i=0; while(url[i++]!=' ');
84 			url[i-1]='\0';
85 		/*} else if (!strcasecmp(headerbuf->headers[t].header_id, "If-Modified-Since")) {*/
86 
87 			/* Processing If-Modified-Since header value if its not related with cgis */
88 			/*if ( (strstr(url, ".png")!=NULL && strstr(url, "images")!=NULL) ||
89 				strstr(url, "netustad.css") ) {*/
90 
91 				/* Getting Day */
92 				/*	HTTP/1.1 304 Not Modified
93 					Date: Fri, 31 Dec 1999 23:59:59 GMT	*/
94 
95 				/*start = headerbuf->headers[t].header_value;
96 				if (strlen(start)>10) {
97 					while (*start==' ') start++;
98 					start+=5;
99 					snprintf(str4, 2, start, "%s");
100 					zamanstr.tm_mday=atoi(start);
101 
102 					start+=2;
103 					snprintf(str4, 3, start, "%s");
104 					zamanstr.tm_mon=months[str4];
105 
106 					start+=4;
107 					snprintf(str4, 4, start, "%s");
108 					zamanstr.tm_year= atoi(str4)-1900;
109 
110 					start+=5;
111 					snprintf(str4, 2, start, "%s");
112 					zamanstr.tm_hour=atoi(str4);
113 
114 					start+=3;
115 					snprintf(str4, 2, start, "%s");
116 					zamanstr.tm_min=atoi(str4);
117 
118 					start+=3;
119 					snprintf(str4, 2, start, "%s");
120 					zamanstr.tm_sec=atoi(str4);
121 					zamanstr.tm_isdst=-1;
122 
123 					zaman_t = mktime(&zamanstr);
124 
125 				}
126 
127 
128 			}*/
129 
130 		}
131 	}
132 
133 	query_string = url;
134 	while ((*query_string != '?') && (*query_string != '\0'))
135 		query_string++;
136 
137 	if (*query_string == '?') {
138 		cgi = 1;
139 		*query_string = '\0';
140 		query_string++;
141 	}
142 
143 	  /*******************/
144 	 /* Parse SessionID */
145 	/*******************/
146 	if (query_string[0] == 0) {
147 		tmp_str = url;
148 		tmp_url = strtok(tmp_str, "$\n");
149 		while (tmp_url != NULL && (int) p <= (int) strlen(value))
150 			value[p++] = *tmp_url++;
151 	} else {
152 		tmp_str = strdup(query_string);
153 		query_string = strtok(tmp_str, "$\n");
154 	}
155 	client_sid = strtok(NULL, "$\n");
156 	if (client_sid == 0)
157 		client_sid = "$";
158 
159 	  /****************************/
160 	 /* add script folder to url */
161 	/****************************/
162 	snprintf(path, sizeof (path)-1, "script%s", url);
163 
164    	  /*****************************/
165 	 /* Check Unwanted Characters */
166  	/*****************************/
167 	if (strstr(path, "..") != NULL) {
168 		server_sid[0] = '$';
169 		server_sid[1] = '\0';
170 		snprintf(parameters, sizeof (parameters)-1,
171 			 " -- %s: %s. %s: %s\n",
172 			 (char *) gettext("Bad Request From"),
173 			 (char *) inet_ntoa(client_name.sin_addr),
174 			 (char *) gettext("The Request is"),
175 			 (char *) path);
176 		log_msg(mainlogfile, parameters, 1);
177 		log_msg(mainlogfile, gettext("Session Killed Because of Bad Request\n"), 1);
178 		snprintf(auth_msg, sizeof (auth_msg)-1, " ");
179 		auth_form = 1;
180 	}
181 
182   	  /************************/
183 	 /* Check Session Expire */
184 	/************************/
185 	time(&currentsec);
186 	if ((long) currentsec - (long) lastactionsec <= sesexpiretime) {	/* Session Not Expired */
187 		time(&lastactionsec);
188 	} else {		/* Session Expired, close session */
189 		server_sid[0] = '$';
190 		server_sid[1] = '\0';
191 		if (!(rightcmp(path, "/netustad.css") ||\
192 		rightcmp(path, "/authform") ||\
193 		rightcmp(path, "/images/bg.png") ||\
194 		rightcmp(path, "/images/buton_0.png") ||\
195 		rightcmp(path, "/images/buton_1.png") ||\
196         	rightcmp(path, "/images/buton_2.png") ||\
197         	rightcmp(path, "/images/buton_3.png") ||\
198         	rightcmp(path, "/images/buton_4.png") ||\
199         	rightcmp(path, "/images/buton_5.png") ||\
200         	rightcmp(path, "/images/buton_6.png") ||\
201         	rightcmp(path, "/images/buton_7.png") ||\
202         	rightcmp(path, "/images/banner.png") ||\
203         	rightcmp(path, "/images/banner-alt.png") ||\
204         	rightcmp(path, "/images/editor.png") ||\
205         	rightcmp(path, "/images/eraser.png") ||\
206 		rightcmp(path, "/images/menu_rulelist.png") ||\
207 		rightcmp(path, "/images/menu_addrule.png") ||\
208 		rightcmp(path, "/images/menu_logout.png") ||\
209         	rightcmp(path, "/images/menu_login.png"))) {
210 			log_msg(mainlogfile, gettext("Administrator's Session Expired!\n"), 1);
211 		}
212 		/*t=0;
213 		while (withoutsession[t]!=NULL && !rightcmp(path, withoutsession[t])) {
214 			t++;
215 		}
216 		if (withoutsession[t]!=NULL && !rightcmp(path, withoutsession[t])) {
217 			log_msg(mainlogfile, gettext("Administrator's Session Expired!\n"), 1);
218 		} else {
219 			ifwithoutsession=1;
220 		}*/
221 		snprintf(auth_msg, sizeof (auth_msg)-1, gettext("Session Expired!"));
222 		auth_form = 1;
223 	}
224 
225 	  /********************/
226 	 /* Check Session ID */
227 	/********************/
228 	if (strcmp(server_sid, "$") != 0 && *client_sid != '$')
229 		if (strcmp(client_sid, server_sid) != 0 ||
230 		    strcmp(client_ip,
231 			   (char *) inet_ntoa(client_name.sin_addr)) != 0) {
232 			snprintf(auth_msg, sizeof (auth_msg)-1, gettext("You are not logged in!"));
233 			auth_form = 1;
234 		} else
235 			auth_form = 0;
236 	else {
237 		if ((long) lastactionsec == 0)
238 			snprintf(auth_msg, sizeof (auth_msg)-1, " ");
239 		auth_form = 1;
240 	}
241 
242  	  /********************************/
243 	 /* Define Environment Variables */
244  	/********************************/
245 	snprintf(env_str, sizeof (env_str)-1, "netustadversion=%s", NUVERSION);
246 	env_p[0] = strdup(env_str);	/* netustad version */
247 
248 	snprintf(env_str, sizeof (env_str)-1, "work_path=%s/script", workdir);
249 	env_p[1] = strdup(env_str);	/* work_path */
250 
251 	env_p[2] = "auth_msg=";		/* authform message */
252 
253 	snprintf(env_str, sizeof (env_str)-1, "server_sid=%s", server_sid);
254 	env_p[3] = strdup(env_str);	/* server session id */
255 
256 	snprintf(env_str, sizeof (env_str)-1, "fw_cmd=%s", fw_cmd);
257 	env_p[4] = strdup(env_str);	/* iptables command */
258 
259 	snprintf(env_str, sizeof (env_str)-1, "TEXTDOMAIN=%s", PACKAGE);
260 	env_p[5] = strdup(env_str);	/* TEXTDOMAIN (for gettext) */
261 
262 	snprintf(env_str, sizeof (env_str)-1, "TEXTDOMAINDIR=%s", PACKAGE_LOCALE_DIR);
263 	env_p[6] = strdup(env_str);	/* TEXTDOMAINDIR (for gettext) */
264 
265 	snprintf(env_str, sizeof (env_str)-1, "LC_ALL=%s", lc_all );
266 	env_p[7] = strdup(env_str);	/* Choose locale */
267 
268 	snprintf(env_str, sizeof (env_str)-1, "gettext_cmd=%s", gettext_cmd);
269 	env_p[8] = strdup(env_str);	/* gettext command */
270 
271 	snprintf(env_str, sizeof (env_str)-1, "cat_cmd=%s", cat_cmd);
272 	env_p[9] = strdup(env_str);	/* full path of cat command */
273 
274 	snprintf(env_str, sizeof (env_str)-1, "awk_cmd=%s", awk_cmd);
275 	env_p[10] = strdup(env_str);	/* full path of awk command */
276 
277 	snprintf(env_str, sizeof (env_str)-1, "MM_CHARSET=%s", gettext("charset"));
278 	env_p[11] = strdup(env_str);	/* charset environ */
279 
280 	snprintf(env_str, sizeof (env_str)-1, "LANG=%s", lc_all );
281 	env_p[12] = strdup(env_str);	/* LANG environ */
282 
283 	snprintf(env_str, sizeof (env_str)-1, "netstat_cmd=%s", netstat_cmd );
284 	env_p[13] = strdup(env_str);	/* netstat_cmd environ */
285 
286 	snprintf(env_str, sizeof (env_str)-1, "grep_cmd=%s", grep_cmd );
287 	env_p[14] = strdup(env_str);	/* grep_cmd environ */
288 
289 	snprintf(env_str, sizeof (env_str)-1, "tr_cmd=%s", tr_cmd );
290 	env_p[15] = strdup(env_str);	/* tr_cmd environ */
291 
292 	snprintf(env_str, sizeof (env_str)-1, "sed_cmd=%s", sed_cmd );
293 	env_p[16] = strdup(env_str);	/* sed_cmd environ */
294 
295 	snprintf(env_str, sizeof (env_str)-1, "tail_cmd=%s", tail_cmd );
296 	env_p[17] = strdup(env_str);	/* tail_cmd environ */
297 
298 	snprintf(env_str, sizeof (env_str)-1, "route_cmd=%s", route_cmd );
299 	env_p[18] = strdup(env_str);	/* route_cmd environ */
300 
301 	snprintf(env_str, sizeof (env_str)-1, "QUERY_STRING=a");
302 	env_p[19] = strdup(env_str);	/* QUERY_STRING environ */
303 
304 	snprintf(env_str, sizeof (env_str)-1, "ifconfig_cmd=%s", ifconfig_cmd );
305 	env_p[20] = strdup(env_str);	/* ifconfig_cmd environ */
306 
307 	env_p[21] = NULL;	/*temporary variable */
308 	env_p[22] = NULL;	/*temporary variable */
309 	env_p[23] = NULL;	/*parameter terminate */
310 
311  	  /***************************/
312 	 /* Parse Requested Address */
313 	/***************************/
314 
315 	/* If Logout Requested Close Session and Goto Auth */
316 	if (rightcmp(path, "/logout")) {
317 		server_sid[0] = '$';
318 		server_sid[1] = '\0';
319 		snprintf(auth_msg, sizeof (auth_msg)-1, gettext("You are logged out"));
320 		log_msg(mainlogfile, gettext("Administrator logged out\n"), 1);
321 		auth_form = 1;
322 	/*} else if (ifwithoutsession && strcmp(withoutsession[t], "/authform")!=0) {
323 		snprintf(path, sizeof(path)-1, "script%s", withoutsession[t]);
324 	}*/
325 	} else if (rightcmp(path, "/images/bg.png")) {
326 		snprintf(path, sizeof (path)-1, "script/images/bg.png");
327         } else if (rightcmp(path, "/images/buton_0.png")) {
328                 snprintf(path, sizeof(path)-1, "script/images/buton_0.png");
329         } else if (rightcmp(path, "/images/buton_1.png")) {
330                 snprintf(path, sizeof(path)-1, "script/images/buton_1.png");
331         } else if (rightcmp(path, "/images/buton_2.png")) {
332                 snprintf(path, sizeof(path)-1, "script/images/buton_2.png");
333         } else if (rightcmp(path, "/images/buton_3.png")) {
334                 snprintf(path, sizeof(path)-1, "script/images/buton_3.png");
335         } else if (rightcmp(path, "/images/menu_login.png")) {
336                 snprintf(path, sizeof(path)-1, "script/images/menu_login.png");
337         } else if (rightcmp(path, "/images/menu_logout.png")) {
338                 snprintf(path, sizeof(path)-1, "script/images/menu_logout.png");
339         } else if (rightcmp(path, "/images/menu_addrule.png")) {
340                 snprintf(path, sizeof(path)-1, "script/images/menu_addrule.png");
341         } else if (rightcmp(path, "/images/menu_rulelist.png")) {
342                 snprintf(path, sizeof(path)-1, "script/images/menu_rulelist.png");
343         } else if (rightcmp(path, "/images/buton_4.png")) {
344                 snprintf(path, sizeof(path)-1, "script/images/buton_4.png");
345         } else if (rightcmp(path, "/images/buton_5.png")) {
346                 snprintf(path, sizeof(path)-1, "script/images/buton_5.png");
347         } else if (rightcmp(path, "/images/buton_7.png")) {
348                 snprintf(path, sizeof(path)-1, "script/images/buton_7.png");
349         } else if (rightcmp(path, "/images/banner.png")) {
350                 snprintf(path, sizeof(path)-1, "script/images/banner.png");
351         } else if (rightcmp(path, "/images/banner-alt.png")) {
352                 snprintf(path, sizeof(path)-1, "script/images/banner-alt.png");
353         } else if (rightcmp(path, "/images/editor.png")) {
354                 snprintf(path, sizeof(path)-1, "script/images/editor.png");
355         } else if (rightcmp(path, "/images/eraser.png")) {
356                 snprintf(path, sizeof(path)-1, "script/images/eraser.png");
357         } else if (rightcmp(path, "/netustad.css")) {
358                 snprintf(path, sizeof(path)-1, "script/netustad.css");
359 	}
360 
361 	/* Other Requests */
362 	if (auth_form == 1 && \
363 	    !(rightcmp(path, "/auth")) && \
364             !(rightcmp(path, "/netustad.css")) && \
365             !(rightcmp(path, "/images/bg.png")) && \
366             !(rightcmp(path, "/images/buton_0.png")) && \
367             !(rightcmp(path, "/images/buton_1.png")) && \
368             !(rightcmp(path, "/images/buton_2.png")) && \
369             !(rightcmp(path, "/images/buton_3.png")) && \
370             !(rightcmp(path, "/images/buton_4.png")) && \
371             !(rightcmp(path, "/images/buton_5.png")) && \
372             !(rightcmp(path, "/images/buton_6.png")) && \
373             !(rightcmp(path, "/images/buton_7.png")) && \
374             !(rightcmp(path, "/images/banner.png")) && \
375             !(rightcmp(path, "/images/banner-alt.png")) && \
376             !(rightcmp(path, "/images/editor.png")) && \
377             !(rightcmp(path, "/images/eraser.png")) && \
378 	    !(rightcmp(path, "/images/menu_logout.png")) && \
379 	    !(rightcmp(path, "/images/menu_addrule.png")) && \
380 	    !(rightcmp(path, "/images/menu_rulelist.png")) && \
381             !(rightcmp(path, "/images/menu_login.png"))) {
382 		snprintf(env_str, sizeof (env_str)-1, "auth_msg=%s", auth_msg);
383 		env_p[2] = strdup(env_str);
384 		snprintf(path, sizeof (path)-1, "script/authform");
385 	} else if (path[strlen(path) - 1] == '/') {
386 		strncat(path, "showrule", (size_t) (sizeof (path) - 1 - strlen(path)));
387 	} else if (rightcmp(path, "/edit")) {
388 		snprintf(env_str, sizeof (env_str)-1, "ruleno=%s", strtok(query_string,"@\n"));
389 		env_p[21] = strdup(env_str);
390 	#ifdef LINUX
391 		snprintf(env_str, sizeof (env_str)-1, "chain=%s", strtok(NULL,"@\n"));
392 		env_p[22] = strdup(env_str);
393 	#endif
394 		strncat(path, "form", (size_t) (sizeof (path) - 1 - strlen(path)));
395 
396 	} else if (rightcmp(path, "/if_edit")) {
397 		snprintf(env_str, sizeof (env_str)-1, "if_name=%s", strtok(query_string,"@\n"));
398 		env_p[21] = strdup(env_str);
399 		snprintf(path, sizeof(path)-1, "script/if_edit");
400 
401 	} else if (rightcmp(path, "/nat_del")) {
402 		snprintf(env_str, sizeof (env_str)-1, "nat_name=%s", strtok(query_string,"@\n"));
403 		env_p[21] = strdup(env_str);
404 		snprintf(path, sizeof(path)-1, "script/nat_del");
405 
406 	} else if (rightcmp(path, "/rt_del")) {
407 		snprintf(env_str, sizeof (env_str)-1, "route=%s", strtok(query_string,"@\n"));
408 		env_p[21] = strdup(env_str);
409 		snprintf(path, sizeof(path)-1, "script/rt_del");
410 
411 	} else if (rightcmp(path, "/auth") && auth_form == 1) {
412 		snprintf(path, sizeof (path)-1, "%s", auth(query_string));
413 		snprintf(env_str, sizeof (env_str)-1, "auth_msg=%s", auth_msg);
414 		env_p[2] = strdup(env_str);
415 		snprintf(env_str, sizeof (env_str)-1, "server_sid=%s", server_sid);
416 		env_p[3] = strdup(env_str);
417 	#ifdef FREEBSD
418 	} else if (rightcmp(path, "/write")) {
419 		snprintf(path, sizeof(path)-1, "script/writeconfig");
420 	#endif
421 	}
422 
423 	/* If Rule Deleting Requested ("del" word) */
424 	if (rightcmp(path, "/del")) {
425 		strncpy(path, fw_cmd, sizeof (path)-1);
426 		deleterule(client, path, header, query_string);
427 	} else if (rightcmp(path, "/addnew")) {
428 		strncpy(path, fw_cmd, sizeof (path)-1);
429 		addnewrule(client, path, header, query_string);
430 	} else if (rightcmp(path, "/applyedit")) {
431 		strncpy(path, fw_cmd, sizeof (path)-1);
432 		editrule(client, path, header, query_string);
433 	} else if (stat(path, &st) == -1) {
434 		snprintf(log_msg_text, sizeof(log_msg_text)-1, gettext("File not found: %s"), path);
435 		log_msg(logfile, log_msg_text, 1);
436 		not_found(client);
437 	} else {
438 		if ((st.st_mode & S_IFMT) == S_IFDIR)
439 			strncat(path, "/showrule",
440 				(size_t) (sizeof (path) - 1 - strlen(path)));
441 		if ((st.st_mode & S_IXUSR) || (st.st_mode & S_IXGRP)
442 		    || (st.st_mode & S_IXOTH))
443 			cgi = 1;
444 		if (!cgi)
445 			serve_file(client, path);
446 		else
447 			snprintf(env_str, sizeof (env_str)-1, "QUERY_STRING=%s", query_string);
448 			env_p[19] = strdup(env_str);	/* QUERY_STRING environ */
449 			execute_cgi(client, path, header, query_string, env_p, 1);
450 	}
451 	return;
452 }
453 
454 /******************************/
455 /* Send client a regular file */
456 /******************************/
457 void
serve_file(nunetwork_socket client,char * filename)458 serve_file(nunetwork_socket client, char *filename)
459 {
460 	FILE *resource = NULL;
461 	char buf[1024];
462 
463 	buf[0] = 'A';
464 	buf[1] = '\0';
465 	resource = fopen(filename, "r");
466 	if (resource == NULL)
467 		not_found(client);
468 	else {
469 		headers(client, filename);
470 		binarycat(client, resource);
471 	}
472 	fclose(resource);
473 }
474 
475 /*********************************/
476 /* Compare two string from right */
477 /*********************************/
478 /* For example:                  */
479 /*      str="abcd"; look4str="cd"*/
480 /* rightcmp(str,look4str) = 1    */
481 /*      str="abcd"; look4str="ab"*/
482 /* rightcmp(str,look4str) = 0    */
483 /*********************************/
484 int
rightcmp(char * str,char * look4str)485 rightcmp(char *str, char *look4str)
486 {
487 	int i = 0;
488 	if (look4str == NULL || str == NULL) {
489 		return 0;
490 	}			/* Oopps, invalid number of args */
491 	if (strlen(look4str) > strlen(str)) {	/* If look4str is longer then str, compare cannot be done */
492 		return 0;
493 	}
494 	for (i = strlen(look4str); i >= 1; i--) {
495 		if ((char) str[strlen(str) - i] !=
496 		    (char) look4str[strlen(look4str) - i]) {
497 			return 0;
498 		}
499 	}
500 	return 1;
501 }
502