Esempio n. 1
0
static int processreq(int fd)
{
    lscgid_t cgi_req;
    int ret;

    ret = recv_req(fd, &cgi_req, 10);
    if (ret)
        cgiError(fd, ret);
    else
    {
        ret = execute_cgi(&cgi_req);
        if (ret)
            cgiError(fd, ret);
    }
    return ret;
}
Esempio n. 2
0
void accept_request(int client)
{
 char buf[1024];
 int numchars;
 char method[255];
 char url[255];
 char path[512];
 size_t i, j;
 struct stat st;
 int cgi = 0;      /* becomes true if server decides this is a CGI
                    * program */
 char *query_string = NULL;

 numchars = get_line(client, buf, sizeof(buf));
 i = 0; j = 0;
 while (!ISspace(buf[j]) && (i < sizeof(method) - 1))
 {
  method[i] = buf[j];
  i++; j++;
 }
 method[i] = '\0';

 if (strcasecmp(method, "GET") && strcasecmp(method, "POST"))
 {
  unimplemented(client);
  return;
 }

 if (strcasecmp(method, "POST") == 0)
  cgi = 1;

 i = 0;
 while (ISspace(buf[j]) && (j < sizeof(buf)))
  j++;
 while (!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < sizeof(buf)))
 {
  url[i] = buf[j];
  i++; j++;
 }
 url[i] = '\0';

 if (strcasecmp(method, "GET") == 0)
 {
  query_string = url;
  while ((*query_string != '?') && (*query_string != '\0'))
   query_string++;
  if (*query_string == '?')
  {
   cgi = 1;
   *query_string = '\0';
   query_string++;
  }
 }

 //sprintf(path, "htdocs%s", url);
 sprintf(path, ".%s", url);
 if (path[strlen(path) - 1] == '/')
  strcat(path, "index.html");
 if (stat(path, &st) == -1) {
  while ((numchars > 0) && strcmp("\n", buf))  /* read & discard headers */
   numchars = get_line(client, buf, sizeof(buf));
  not_found(client);
 }
 else
 {
  if ((st.st_mode & S_IFMT) == S_IFDIR)
   strcat(path, "/index.html");
  if ((st.st_mode & S_IXUSR) ||
      (st.st_mode & S_IXGRP) ||
      (st.st_mode & S_IXOTH)    )
   cgi = 1;
  cgi = 0;//must not cgi
  if (!cgi)
   serve_file(client, path);
  else
   execute_cgi(client, path, method, query_string);
 }

 close(client);
}
Esempio n. 3
0
/* Serve the client that connected to the webserver
 */
static int serve_client(t_session *session) {
	int result, length, auth_result;
	char *qmark, chr, *header;
	t_host *host_record;
	t_access access;
	t_deny_body *deny_body;
	t_req_method request_method;
	t_ip_addr ip_addr;
#ifdef ENABLE_XSLT
	char *xslt_file;
#endif
#ifdef ENABLE_TOOLKIT
	int i;
	t_toolkit_options toolkit_options;
#endif
#ifdef ENABLE_RPROXY
	t_rproxy *rproxy;
#endif

#ifdef ENABLE_DEBUG
	session->current_task = "fetch & parse request";
#endif

	if ((result = fetch_request(session)) != 200) {
		session->request_method = GET;
		return result;
	} else if ((result = parse_request(session, session->header_length + session->content_length)) != 200) {
		session->request_method = GET;
		return result;
	}

#ifdef ENABLE_DEBUG
	session->current_task = "serve client";
#endif

	session->time = time(NULL);

	/* Hide reverse proxies
	 */
	if (in_iplist(session->config->hide_proxy, &(session->ip_address))) {
		if (last_forwarded_ip(session->http_headers, &ip_addr) == 0) {
			if (reposition_client(session, &ip_addr) != -1) {
				copy_ip(&(session->ip_address), &ip_addr);
			}
		}
	}

	/* SSH tunneling
	 */
#ifdef ENABLE_RPROXY
	if (session->request_method == CONNECT) {
		if (in_iplist(session->config->tunnel_ssh, &(session->ip_address)) == false) {
			return 405;
		}

#ifdef ENABLE_SSL
		if (session->binding->use_ssl) {
			return 405;
		}
#endif

		if (strcmp(session->request_uri, "localhost:22") != 0) {
			if (strcmp(session->request_uri, "127.0.0.1:22") != 0) {
				if (strcmp(session->request_uri, "::1.22") != 0) {
					return 403;
				}
			}
		}

		log_system(session, "SSH tunnel requested");
		if (tunnel_ssh_connection(session->client_socket) != 0) {
			log_system(session, "SSH tunnel failed");
		} else {
			log_system(session, "SSH tunnel terminated");
		}

		session->keep_alive = false;

		return 200;
	}
#endif

	/* Find host record
	 */
	if (session->hostname != NULL) {
		if (remove_port_from_hostname(session) == -1) {
			log_error(session, "error removing port from hostname");
			return 500;
		}

		if ((host_record = get_hostrecord(session->config->first_host, session->hostname, session->binding)) != NULL) {
			session->host = host_record;
#ifdef ENABLE_TOMAHAWK
			session->last_host = host_record;
#endif
		}
	}
	session->host->access_time = session->time;

#ifdef ENABLE_SSL
	/* SSL client authentication
	 */
	if (session->binding->use_ssl) {
		if ((session->host->ca_certificate != NULL) && (ssl_has_peer_cert(&(session->ssl_context)) == false)) {
			log_error(session, "Missing client SSL certificate");
			return 440;
		}
	}
#endif

	/* Enforce usage of first hostname
	 */
	if (session->host->enforce_first_hostname && (session->hostname != NULL)) {
		if (**(session->host->hostname.item) != '*') {
			if (strcmp(session->hostname, *(session->host->hostname.item)) != 0) {
				session->cause_of_301 = enforce_first_hostname;
				return 301;
			}
		}
	}

	/* Enforce usage of SSL
	 */
#ifdef ENABLE_SSL
	if (session->host->require_ssl && (session->binding->use_ssl == false)) {
		if ((qmark = strchr(session->uri, '?')) != NULL) {
			*qmark = '\0';
			session->vars = qmark + 1;
			session->uri_len = strlen(session->uri);
		}
		session->cause_of_301 = require_ssl;
		return 301;
	}
#endif

	/* Deny matching bodies
	 */
	if (session->body != NULL) {
		chr = *(session->body + session->content_length);
		*(session->body + session->content_length) = '\0';

		deny_body = session->host->deny_body;
		while (deny_body != NULL) {
			if (strpcmp(session->body, &(deny_body->pattern)) == 0) {
				if ((session->config->ban_on_denied_body > 0) && (ip_allowed(&(session->ip_address), session->config->banlist_mask) != deny)) {
					ban_ip(&(session->ip_address), session->config->ban_on_denied_body, session->config->kick_on_ban);
					log_system(session, "Client banned because of denied body");
#ifdef ENABLE_MONITOR
					if (session->config->monitor_enabled) {
						monitor_count_ban(session);
					}
#endif
				}

				log_exploit_attempt(session, "denied body", session->body);
#ifdef ENABLE_TOMAHAWK
				increment_counter(COUNTER_EXPLOIT);
#endif
#ifdef ENABLE_MONITOR
				if (session->config->monitor_enabled) {
					monitor_count_exploit(session);
					monitor_event("Request body denied for %s", session->host->hostname.item[0]);
				}
#endif

				*(session->body + session->content_length) = chr;

				return 403;
			}
			deny_body = deny_body->next;
		}

		*(session->body + session->content_length) = chr;
	}

	/* Websocket
	 */
	if (session->request_method == GET) {
		if ((header = get_http_header("Connection:", session->http_headers)) != NULL) {
			if (strcasestr(header, "upgrade") != NULL) {
				if ((header = get_http_header("Upgrade:", session->http_headers)) != NULL) {
					if (strcasecmp(header, "websocket") == 0) {
						switch (access = allow_client(session)) {
							case deny:
								log_error(session, fb_accesslist);
								return 403;
							case allow:
								break;
							case pwd:
							case unspecified:
								if ((auth_result = http_authentication_result(session, access == unspecified)) != 200) {
									return auth_result;
								}
						}

						session->keep_alive = false;
						if (forward_to_websocket(session) == -1) {
							return 500;
						}

						return 200;
					}
				}
			}
		}
	}

#ifdef ENABLE_RPROXY
	/* Reverse proxy
	 */
	rproxy = session->host->rproxy;
	while (rproxy != NULL) {
		if (rproxy_match(rproxy, session->request_uri)) {
			if (rproxy_loop_detected(session->http_headers)) {
				return 508;
			}

			if ((qmark = strchr(session->uri, '?')) != NULL) {
				*qmark = '\0';
				session->vars = qmark + 1;
			}

			if (validate_url(session) == false) {
				return -1;
			}

			if ((session->vars != NULL) && (session->host->secure_url)) {
				if (forbidden_chars_present(session->vars)) {
					log_error(session, "URL contains forbidden characters");
					return 403;
				}
			}

			if (duplicate_host(session) == false) {
				log_error(session, "duplicate_host() error");
				return 500;
			}

			if ((result = uri_to_path(session)) != 200) {
				return result;
			}

			if (session->host->ignore_dot_hiawatha == false) {
				if (load_user_config(session) == -1) {
					return 500;
				}
			}

			if ((result = copy_directory_settings(session)) != 200) {
				return result;
			}

			switch (access = allow_client(session)) {
				case deny:
					log_error(session, fb_accesslist);
					return 403;
				case allow:
					break;
				case pwd:
				case unspecified:
					if ((auth_result = http_authentication_result(session, access == unspecified)) != 200) {
						return auth_result;
					}
			}

			/* Prevent SQL injection
			 */
			if (session->host->prevent_sqli) {
				result = prevent_sqli(session);
				if (result == 1) {
					session->error_cause = ec_SQL_INJECTION;
				}
				if (result != 0) {
					return -1;
				}
			}

			/* Prevent Cross-site Scripting
			 */
			if (session->host->prevent_xss != p_no) {
				if (prevent_xss(session) > 0) {
					if (session->host->prevent_xss == p_block) {
						session->error_cause = ec_XSS;
						return -1;
					}
				}
			}

			/* Prevent Cross-site Request Forgery
			 */
			if (session->host->prevent_csrf != p_no) {
				if (prevent_csrf(session) > 0) {
					if (session->host->prevent_csrf == p_block) {
						session->error_cause = ec_CSRF;
						return -1;
					}
				}
			}

			return proxy_request(session, rproxy);
		}

		rproxy = rproxy->next;
	}
#endif

	/* Actions based on request method
	 */
	switch (session->request_method) {
		case TRACE:
			if (session->binding->enable_trace == false) {
				return 501;
			}
			return handle_trace_request(session);
		case PUT:
		case DELETE:
			if ((session->binding->enable_alter == false) && (session->host->webdav_app == false)) {
				return 501;
			}
			break;
		case unknown:
			return 400;
		case unsupported:
			if (session->host->webdav_app == false) {
				return 501;
			}
			break;
		default:
			break;
	}

	if (duplicate_host(session) == false) {
		log_error(session, "duplicate_host() error");
		return 500;
	}

#ifdef ENABLE_TOOLKIT
	if (session->host->ignore_dot_hiawatha == false) {
		if (load_user_root_config(session) == -1) {
			return 500;
		}
	}

	/* URL toolkit
	 */
	init_toolkit_options(&toolkit_options);
	toolkit_options.method = session->method;
	toolkit_options.website_root = session->host->website_root;
	toolkit_options.url_toolkit = session->config->url_toolkit;
	toolkit_options.allow_dot_files = session->host->allow_dot_files;
	toolkit_options.http_headers = session->http_headers;
#ifdef ENABLE_SSL
	toolkit_options.use_ssl = session->binding->use_ssl;
#endif

	if (((session->request_method != PUT) && (session->request_method != DELETE)) || session->host->webdav_app) {
		for (i = 0; i < session->host->toolkit_rules.size; i++) {
			if ((result = use_toolkit(session->uri, session->host->toolkit_rules.item[i], &toolkit_options)) == UT_ERROR) {
				return 500;
			}

			if ((toolkit_options.ban > 0) && (ip_allowed(&(session->ip_address), session->config->banlist_mask) != deny)) {
				ban_ip(&(session->ip_address), toolkit_options.ban, session->config->kick_on_ban);
				log_system(session, "Client banned because of URL match in UrlToolkit rule");
#ifdef ENABLE_MONITOR
				if (session->config->monitor_enabled) {
					monitor_count_ban(session);
				}
#endif
				return 403;
			}

			session->toolkit_fastcgi = toolkit_options.fastcgi_server;
			if (toolkit_options.new_url != NULL) {
				if (register_tempdata(&(session->tempdata), toolkit_options.new_url, tc_data) == -1) {
					free(toolkit_options.new_url);
					log_error(session, "error registering temporary data");
					return 500;
				}
				session->uri = toolkit_options.new_url;
			}

			if (result == UT_REDIRECT) {
				if ((session->location = strdup(toolkit_options.new_url)) == NULL) {
					return -1;
				}
				session->cause_of_301 = location;
				return 301;
			}

			if (result == UT_DENY_ACCESS) {
				log_error(session, "access denied via URL toolkit rule");
				return 403;
			}

			if (toolkit_options.expire > -1) {
				session->expires = toolkit_options.expire;
				session->caco_private = toolkit_options.caco_private;
			}
		}
	}
#endif

	/* Find GET data
	 */
	if ((qmark = strchr(session->uri, '?')) != NULL) {
		*qmark = '\0';
		session->vars = qmark + 1;
	}

	url_decode(session->uri);
	session->uri_len = strlen(session->uri);

	if ((session->vars != NULL) && (session->host->secure_url)) {
		if (forbidden_chars_present(session->vars)) {
			log_error(session, "URL contains forbidden characters");
			return 403;
		}
	}

	if (validate_url(session) == false) {
		return -1;
	}

	if ((result = uri_to_path(session)) != 200) {
		return result;
	}

	/* Load configfile from directories
	 */
	if (session->host->ignore_dot_hiawatha == false) {
		if (load_user_config(session) == -1) {
			return 500;
		}
	}

	if ((result = copy_directory_settings(session)) != 200) {
		return result;
	}

	switch (access = allow_client(session)) {
		case deny:
			log_error(session, fb_accesslist);
			return 403;
		case allow:
			break;
		case pwd:
		case unspecified:
			if ((auth_result = http_authentication_result(session, access == unspecified)) != 200) {
				return auth_result;
			}
	}

	switch (is_directory(session->file_on_disk)) {
		case error:
			return 500;
		case yes:
			session->uri_is_dir = true;
			break;
		case no:
			if (((session->request_method != PUT) || session->host->webdav_app) && (session->host->enable_path_info)) {
				if ((result = get_path_info(session)) != 200) {
					return result;
				}
			}
			break;
		case no_access:
			log_error(session, fb_filesystem);
			return 403;
		case not_found:
			if (session->request_method == DELETE) {
				return 404;
			}
	}

#ifdef ENABLE_TOOLKIT
	if ((session->toolkit_fastcgi == NULL) && session->uri_is_dir) {
#else
	if (session->uri_is_dir) {
#endif
		length = strlen(session->file_on_disk);
		if (*(session->file_on_disk + length - 1) == '/') {
			strcpy(session->file_on_disk + length, session->host->start_file);
		} else {
			return 301;
		}
	}

	if (get_target_extension(session) == -1) {
		log_error(session, "error getting extension");
		return 500;
	}

	if (((session->request_method != PUT) && (session->request_method != DELETE)) || session->host->webdav_app) {
		check_target_is_cgi(session);
	}

	/* Handle request based on request method
	 */
	request_method = session->request_method;
	if (session->host->webdav_app) {
		if ((request_method == PUT) || (request_method == DELETE)) {
			request_method = POST;
		}
	}

	switch (request_method) {
		case GET:
		case HEAD:
			if (session->cgi_type != no_cgi) {
				session->body = NULL;
				result = execute_cgi(session);
#ifdef ENABLE_XSLT
			} else if ((xslt_file = find_xslt_file(session)) != NULL) {
				result = handle_xml_file(session, xslt_file);
				free(xslt_file);
#endif
			} else {
				result = send_file(session);
			}
			if (result == 404) {
#ifdef ENABLE_XSLT
				if ((session->host->show_index != NULL) && (session->uri[session->uri_len - 1] == '/')) {
					result = show_index(session);
				}
#endif
#ifdef ENABLE_MONITOR
			} else if (session->config->monitor_enabled) {
				if ((result == 200) && (session->host->monitor_host)) {
					unlink(session->file_on_disk);
				}
#endif
			}

			if ((session->request_method == GET) && (session->cgi_type == no_cgi) && (session->directory != NULL)) {
				if (session->directory->run_on_download != NULL) {
					run_program(session, session->directory->run_on_download, result);
				}
			}
			break;
		case POST:
		case unsupported:
			if (session->cgi_type != no_cgi) {
				result = execute_cgi(session);
#ifdef ENABLE_XSLT
			} else if ((xslt_file = find_xslt_file(session)) != NULL) {
				result = handle_xml_file(session, xslt_file);
				free(xslt_file);
#endif
			} else {
				result = 405;
			}
			break;
		case PUT:
			result = handle_put_request(session);
			if (((result == 201) || (result == 204)) && (session->host->run_on_alter != NULL)) {
				run_program(session, session->host->run_on_alter, result);
			}
			break;
		case DELETE:
			result = handle_delete_request(session);
			if ((result == 204) && (session->host->run_on_alter != NULL)) {
				run_program(session, session->host->run_on_alter, result);
			}
			break;
		case WHEN:
			send_code(session);
			break;
		default:
			result = 400;
	}

	return result;
}

/* Handle timeout upon sending request
 */
static void handle_timeout(t_session *session) {
	if ((session->config->ban_on_timeout > 0) && (ip_allowed(&(session->ip_address), session->config->banlist_mask) != deny)) {
		ban_ip(&(session->ip_address), session->config->ban_on_timeout, session->config->kick_on_ban);
		log_system(session, "Client banned because of connection timeout");
#ifdef ENABLE_MONITOR
		if (session->config->monitor_enabled) {
			monitor_count_ban(session);
		}
#endif
	} else {
		log_system(session, "Timeout while waiting for first request");
	}
}

/* Request has been handled, handle the return code.
 */
static void handle_request_result(t_session *session, int result) {
	char *hostname;

#ifdef ENABLE_DEBUG
	session->current_task = "handle request result";
#endif

	if (result == -1) switch (session->error_cause) {
		case ec_MAX_REQUESTSIZE:
			log_system(session, "Maximum request size reached");
			session->return_code = 413;
			send_code(session);
			if ((session->config->ban_on_max_request_size > 0) && (ip_allowed(&(session->ip_address), session->config->banlist_mask) != deny)) {
				ban_ip(&(session->ip_address), session->config->ban_on_max_request_size, session->config->kick_on_ban);
				log_system(session, "Client banned because of sending a too large request");
#ifdef ENABLE_MONITOR
				if (session->config->monitor_enabled) {
					monitor_count_ban(session);
				}
#endif
			}
			break;
		case ec_TIMEOUT:
			if (session->kept_alive == 0) {
				session->return_code = 408;
				send_code(session);
				handle_timeout(session);
			}
			break;
		case ec_CLIENT_DISCONNECTED:
			if (session->kept_alive == 0) {
				log_system(session, "Silent client disconnected");
			}
			break;
		case ec_SOCKET_READ_ERROR:
			if (errno != ECONNRESET) {
				log_system(session, "Error while reading request");
			}
			break;
		case ec_SOCKET_WRITE_ERROR:
			log_request(session);
			break;
		case ec_FORCE_QUIT:
			log_system(session, "Client kicked");
			break;
		case ec_SQL_INJECTION:
			if ((session->config->ban_on_sqli > 0) && (ip_allowed(&(session->ip_address), session->config->banlist_mask) != deny)) {
				ban_ip(&(session->ip_address), session->config->ban_on_sqli, session->config->kick_on_ban);
				hostname = (session->hostname != NULL) ? session->hostname : unknown_host;
				log_system(session, "Client banned because of SQL injection on %s", hostname);
#ifdef ENABLE_MONITOR
				if (session->config->monitor_enabled) {
					monitor_count_ban(session);
				}
#endif
			}
			session->return_code = 441;
			send_code(session);
			log_request(session);
			break;
		case ec_XSS:
			session->return_code = 442;
			send_code(session);
			log_request(session);
			break;
		case ec_CSRF:
			session->return_code = 443;
			send_code(session);
			log_request(session);
			break;
		case ec_INVALID_URL:
			if ((session->config->ban_on_invalid_url > 0) && (ip_allowed(&(session->ip_address), session->config->banlist_mask) != deny)) {
				ban_ip(&(session->ip_address), session->config->ban_on_invalid_url, session->config->kick_on_ban);
				hostname = (session->hostname != NULL) ? session->hostname : unknown_host;
				log_system(session, "Client banned because of invalid URL on %s", hostname);
#ifdef ENABLE_MONITOR
				if (session->config->monitor_enabled) {
					monitor_count_ban(session);
				}
#endif
			}
			send_code(session);
			break;
		default:
			if (session->data_sent == false) {
				session->return_code = 500;
				if (send_code(session) == -1) {
					session->keep_alive = false;
				}
			}
	} else switch (result) {
		case 200:
			break;
		case 201:
		case 204:
		case 304:
		case 412:
			if (session->data_sent == false) {
				session->return_code = result;
				if (send_header(session) == -1) {
					session->keep_alive = false;
				} else if (send_buffer(session, "Content-Length: 0\r\n\r\n", 21) == -1) {
					session->keep_alive = false;
				}
			}
			break;
		case 411:
		case 413:
			session->keep_alive = false;
			if (session->data_sent == false) {
				session->return_code = result;
				if (send_header(session) == -1) {
					session->keep_alive = false;
				} else if (send_buffer(session, "Content-Length: 0\r\n\r\n", 21) == -1) {
					session->keep_alive = false;
				}
			}
			break;
		case 400:
			log_garbage(session);
			if (session->data_sent == false) {
				session->return_code = 400;
				if (send_code(session) == -1) {
					session->keep_alive = false;
				}
			}
			if ((session->config->ban_on_garbage > 0) && (ip_allowed(&(session->ip_address), session->config->banlist_mask) != deny)) {
				ban_ip(&(session->ip_address), session->config->ban_on_garbage, session->config->kick_on_ban);
				log_system(session, "Client banned because of sending garbage");
#ifdef ENABLE_MONITOR
				if (session->config->monitor_enabled) {
					monitor_count_ban(session);
				}
#endif
			}
#ifdef ENABLE_MONITOR
			if (session->config->monitor_enabled) {
				monitor_count_bad_request(session);
			}
#endif
			break;
		case 401:
		case 403:
		case 404:
		case 501:
		case 503:
			if (session->data_sent == false) {
				switch (handle_error(session, result)) {
					case -1:
						session->keep_alive = false;
						break;
					case 200:
						break;
					default:
						if (session->data_sent == false) {
							session->return_code = result;
							if (send_code(session) == -1) {
								session->keep_alive = false;
							}
						}
				}
			}
			break;
		case 500:
			session->keep_alive = false;
		default:
			if (session->data_sent == false) {
				session->return_code = result;
				send_code(session);
			}
	}

	if ((result > 0) && (result != 400)) {
		log_request(session);
	} else {
		session->keep_alive = false;
	}
}
Esempio n. 4
0
/* Handle an HTTP error.
 */
static int handle_error(t_session *session, int error_code) {
	t_error_handler *error_handler;
	char *new_fod;
	int result = -1;
#ifdef ENABLE_XSLT
	char *xslt_file;
#endif

	error_handler = session->host->error_handlers;
	while (error_handler != NULL) {
		if (error_handler->code == error_code) {
			break;
		}
		error_handler = error_handler->next;
	}

	if (error_handler == NULL) {
		return 0;
	}

	session->return_code = error_code;
	session->error_code = error_code;
	session->handling_error = true;
	session->mimetype = NULL;
	session->vars = error_handler->parameters;

	if ((new_fod = (char*)malloc(session->host->website_root_len + strlen(error_handler->handler) + 4)) == NULL) { /* + 3 for .gz (gzip encoding) */
		log_error(session, "malloc() error while handling error");
		return 500;
	}

	if (session->file_on_disk != NULL) {
		free(session->file_on_disk);
	}
	session->file_on_disk = new_fod;

	memcpy(session->file_on_disk, session->host->website_root, session->host->website_root_len);
	strcpy(session->file_on_disk + session->host->website_root_len, error_handler->handler);

	if (get_target_extension(session) == -1) {
		log_error(session, "error getting extension while handing error");
		return 500;
	}
	check_target_is_cgi(session);

	if (session->cgi_type != no_cgi) {
		result = execute_cgi(session);
#ifdef ENABLE_XSLT
	} else if ((xslt_file = find_xslt_file(session)) != NULL) {
		result = handle_xml_file(session, xslt_file);
		free(xslt_file);
#endif
	} else switch (is_directory(session->file_on_disk)) {
		case error:
			result = 500;
			break;
		case yes:
			result = 301;
			break;
		case no:
			result = send_file(session);
			break;
		case no_access:
			result = 403;
			break;
		case not_found:
			result = 404;
			break;
	}

	switch (result) {
		case 301:
			log_error(session, "ErrorHandler is a directory");
			break;
		case 403:
			log_error(session, "no access to ErrorHandler");
			break;
		case 404:
			log_error(session, "ErrorHandler not found");
			break;
		case 500:
			log_file_error(session, error_handler->handler, "internal error for ErrorHandler");
			session->keep_alive = false;
			break;
		case 503:
			log_file_error(session, error_handler->handler, "FastCGI for ErrorHandler not available");
			break;
	}

	return result;
}
Esempio n. 5
0
void* accept_request(void* client1)  
//accept_request解析header里面的第一行获得request method(get/post)和请求路径,映射到htdoc文件夹下的路径,
//其中当对应的文件可执行的时候,就调用execute_cgi函数

{
 int client = (intptr_t)client1;
 char buf[1024];
 int numchars;
 char method[255];
 char url[255];
 char path[512];
 size_t i, j;
 struct stat st;
 int cgi = 0;      /* becomes true if server decides this is a CGI
                    * program */
 char *query_string = NULL;

 numchars = get_line(client, buf, sizeof(buf));
 i = 0; j = 0;
 while (!ISspace(buf[j]) && (i < sizeof(method) - 1))
 {
  method[i] = buf[j];
  i++; j++;
 }
 method[i] = '\0';

 if (strcasecmp(method, "GET") && strcasecmp(method, "POST")) 
 { 
  unimplemented(client); // 仅仅支持GET和POST方法,否则抛出未支持的方法
  return NULL;
 }

 if (strcasecmp(method, "POST") == 0)
  cgi = 1;

 i = 0;
 while (ISspace(buf[j]) && (j < sizeof(buf)))
  j++;
 while (!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < sizeof(buf)))
 {
  url[i] = buf[j];
  i++; j++;
 }
 url[i] = '\0';

 if (strcasecmp(method, "GET") == 0)
 {
  query_string = url;
  while ((*query_string != '?') && (*query_string != '\0'))
   query_string++;
  if (*query_string == '?')
  {
   cgi = 1;
   *query_string = '\0';
   query_string++;
  }
 }

 sprintf(path, "htdocs%s", url);
 if (path[strlen(path) - 1] == '/')
  strcat(path, "index.html");
 if (stat(path, &st) == -1) {
  while ((numchars > 0) && strcmp("\n", buf))  /* read & discard headers */
   numchars = get_line(client, buf, sizeof(buf));
  not_found(client);
 }
 else
 {
  if ((st.st_mode & S_IFMT) == S_IFDIR)
   strcat(path, "/index.html");
  if ((st.st_mode & S_IXUSR) ||
      (st.st_mode & S_IXGRP) ||
      (st.st_mode & S_IXOTH)    )
   cgi = 1;
  if (!cgi)
   serve_file(client, path);
  else
   execute_cgi(client, path, method, query_string);
 }

 close(client);
 return NULL;
}
Esempio n. 6
0
void accept_request(int client)
{
 char buf[1024];
 int numchars;
 char method[255];
 char url[255];
 char path[512];
 size_t i, j;
 struct stat st;
 int cgi = 0;      /* becomes true if server decides this is a CGI
                    * program */
 char *query_string = NULL;

 numchars = get_line(client, buf, sizeof(buf));//把client里的\r都换成\n
 i = 0; j = 0;
 //找出method是get还是post,只支持这两种方法
 while (!ISspace(buf[j]) && (i < sizeof(method) - 1))
 {
  method[i] = buf[j];
  i++; j++;
 }
 method[i] = '\0';

 //函数说明 strcasecmp()用来比较参数s1和s2字符串,比较时会自动忽略大小写的差异。
//返回值 若参数s1和s2字符串相等则返回0。s1大于s2则返回大于0 的值,s1 小于s2 则返回小于0的值。
 if (strcasecmp(method, "GET") && strcasecmp(method, "POST"))
 {
  unimplemented(client);//返回给浏览器表明收到的 HTTP 请求所用的 method 不被支持。
  return;
 }

 if (strcasecmp(method, "POST") == 0)
  cgi = 1;

 i = 0;
 while (ISspace(buf[j]) && (j < sizeof(buf)))
  j++;

//找出URL
 while (!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < sizeof(buf)))
 {
  url[i] = buf[j];
  i++; j++;
 }
 url[i] = '\0';


 if (strcasecmp(method, "GET") == 0)
 {
  query_string = url;
  while ((*query_string != '?') && (*query_string != '\0'))
   query_string++;
  if (*query_string == '?')
  {
   cgi = 1;
   *query_string = '\0';
   query_string++;
  }
 }

 sprintf(path, "htdocs%s", url);
 if (path[strlen(path) - 1] == '/')
  strcat(path, "index.html");
 if (stat(path, &st) == -1) {
  while ((numchars > 0) && strcmp("\n", buf))  /* read & discard headers */
   numchars = get_line(client, buf, sizeof(buf));
  not_found(client);
 }
 else
 {
  if ((st.st_mode & S_IFMT) == S_IFDIR)
   strcat(path, "/index.html");
  if ((st.st_mode & S_IXUSR) ||
      (st.st_mode & S_IXGRP) ||
      (st.st_mode & S_IXOTH)    )
   cgi = 1;
  if (!cgi)
   serve_file(client, path);
  else
   execute_cgi(client, path, method, query_string);
 }

 close(client);
}
Esempio n. 7
0
void
accept_request(nunetwork_socket client, struct nunetwork_headerstruct *headerbuf)
{
	int auth_form = 0;
	int p = 0,i,t;
	char path[512], parameters[512];
	char env_str[512];
	struct stat st;
	int cgi = 0;		/* becomes true if server decides this is a CGI program */
	char *query_string = NULL;
	char *tmp_str = NULL;
	char *tmp_url = NULL;
	char *client_sid = " ";
	char method[5];
	char url[256];
	char header[256];
	char value[256];
	/* Vars for processing HTTP 304*/
	/*enum en_day { Sun = 0, Mon, Tue, Wed, Thu, Fri, Sat} days;
	enum en_month { Jan = 0, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec } months;*/
	/*char *withoutsession[] = {
			"/netustad.css",
			"/authform",
			"/images/bg.png",
			"/images/buton_0.png",
			"/images/buton_1.png",
			"/images/buton_2.png",
			"/images/buton_3.png",
			"/images/buton_4.png",
			"/images/buton_5.png",
			"/images/buton_6.png",
			"/images/buton_7.png",
			"/images/banner.png",
			"/images/banner-alt.png",
			"/images/menu_login.png",
			"/images/menu_rulelist.png",
			"/images/menu_addrule.png",
			"/images/menu_logout.png",
			NULL
			};
	int ifwithoutsession=0;*/
	/*struct tm zamanstr;
	time_t zaman_t;
	char str4[5]="123";*/	
	char *start;
	/*****************************************/
	
	/* Processing the header buffer */
	/* GET request is saved to be processed at the end*/
	for (t=0; t< headerbuf->number_of_headers; t++)  {
		
		if (!strcasecmp(headerbuf->headers[t].header_id, "POST") ) {	
			/* sorry maybe next time */
			unimplemented(client);
			return;
		} else if (!strcasecmp(headerbuf->headers[t].header_id, "HEAD")) {
			tmp_url = strdup(headerbuf->headers[t].header_value);
			
			/*Getting the requested url */
			start = headerbuf->headers[t].header_value;
			while (*start!=' ' || *start!='\t') start++;
			tmp_url = strstr(start, "HTTP/") - 1;
			while ( *tmp_url!= ' ' || *tmp_url != '\t' ) tmp_url--;
			snprintf(url, tmp_url - start + 1, "script%s", start );
			headers(client, url);
			return;
		} else if (!strcasecmp(headerbuf->headers[t].header_id, "GET")) {
			/* this is it ... getting the method and the url without HTTP id */
			strncpy(method, headerbuf->headers[t].header_id, sizeof(method));
			strncpy(url, headerbuf->headers[t].header_value, sizeof(url)); 
			i=0; while(url[i++]!=' ');
			url[i-1]='\0';
		/*} else if (!strcasecmp(headerbuf->headers[t].header_id, "If-Modified-Since")) {*/

			/* Processing If-Modified-Since header value if its not related with cgis */
			/*if ( (strstr(url, ".png")!=NULL && strstr(url, "images")!=NULL) || 
				strstr(url, "netustad.css") ) {*/
			
				/* Getting Day */
				/*	HTTP/1.1 304 Not Modified
					Date: Fri, 31 Dec 1999 23:59:59 GMT	*/

				/*start = headerbuf->headers[t].header_value;
				if (strlen(start)>10) {
					while (*start==' ') start++;
					start+=5;
					snprintf(str4, 2, start, "%s");
					zamanstr.tm_mday=atoi(start);
					
					start+=2;
					snprintf(str4, 3, start, "%s");
					zamanstr.tm_mon=months[str4];
					
					start+=4;
					snprintf(str4, 4, start, "%s");
					zamanstr.tm_year= atoi(str4)-1900;
					
					start+=5;
					snprintf(str4, 2, start, "%s");
					zamanstr.tm_hour=atoi(str4);
					
					start+=3;
					snprintf(str4, 2, start, "%s");
					zamanstr.tm_min=atoi(str4);
					
					start+=3;
					snprintf(str4, 2, start, "%s");
					zamanstr.tm_sec=atoi(str4);
					zamanstr.tm_isdst=-1;
					
					zaman_t = mktime(&zamanstr);

				}
						
			
			}*/	

		}
	} 

	query_string = url;
	while ((*query_string != '?') && (*query_string != '\0'))
		query_string++;

	if (*query_string == '?') {
		cgi = 1;
		*query_string = '\0';
		query_string++;
	}

	  /*******************/
	 /* Parse SessionID */
	/*******************/
	if (query_string[0] == 0) {
		tmp_str = url;
		tmp_url = strtok(tmp_str, "$\n");
		while (tmp_url != NULL && (int) p <= (int) strlen(value))
			value[p++] = *tmp_url++;
	} else {
		tmp_str = strdup(query_string);
		query_string = strtok(tmp_str, "$\n");
	}
	client_sid = strtok(NULL, "$\n");
	if (client_sid == 0)
		client_sid = "$";

	  /****************************/
	 /* add script folder to url */
	/****************************/
	snprintf(path, sizeof (path)-1, "script%s", url);

   	  /*****************************/
	 /* Check Unwanted Characters */
 	/*****************************/
	if (strstr(path, "..") != NULL) {
		server_sid[0] = '$';
		server_sid[1] = '\0';
		snprintf(parameters, sizeof (parameters)-1,
			 " -- %s: %s. %s: %s\n",
			 (char *) gettext("Bad Request From"), 
			 (char *) inet_ntoa(client_name.sin_addr),
			 (char *) gettext("The Request is"),
			 (char *) path);
		log_msg(mainlogfile, parameters, 1);
		log_msg(mainlogfile, gettext("Session Killed Because of Bad Request\n"), 1);
		snprintf(auth_msg, sizeof (auth_msg)-1, " ");
		auth_form = 1;
	}

  	  /************************/
	 /* Check Session Expire */
	/************************/
	time(&currentsec);
	if ((long) currentsec - (long) lastactionsec <= sesexpiretime) {	/* Session Not Expired */
		time(&lastactionsec);
	} else {		/* Session Expired, close session */
		server_sid[0] = '$';
		server_sid[1] = '\0';
		if (!(rightcmp(path, "/netustad.css") ||\
		rightcmp(path, "/authform") ||\
		rightcmp(path, "/images/bg.png") ||\
		rightcmp(path, "/images/buton_0.png") ||\
		rightcmp(path, "/images/buton_1.png") ||\
        	rightcmp(path, "/images/buton_2.png") ||\
        	rightcmp(path, "/images/buton_3.png") ||\
        	rightcmp(path, "/images/buton_4.png") ||\
        	rightcmp(path, "/images/buton_5.png") ||\
        	rightcmp(path, "/images/buton_6.png") ||\
        	rightcmp(path, "/images/buton_7.png") ||\
        	rightcmp(path, "/images/banner.png") ||\
        	rightcmp(path, "/images/banner-alt.png") ||\
        	rightcmp(path, "/images/editor.png") ||\
        	rightcmp(path, "/images/eraser.png") ||\
		rightcmp(path, "/images/menu_rulelist.png") ||\
		rightcmp(path, "/images/menu_addrule.png") ||\
		rightcmp(path, "/images/menu_logout.png") ||\
        	rightcmp(path, "/images/menu_login.png"))) {
			log_msg(mainlogfile, gettext("Administrator's Session Expired!\n"), 1);
		}
		/*t=0;
		while (withoutsession[t]!=NULL && !rightcmp(path, withoutsession[t])) {
			t++;
		}
		if (withoutsession[t]!=NULL && !rightcmp(path, withoutsession[t])) {
			log_msg(mainlogfile, gettext("Administrator's Session Expired!\n"), 1);
		} else {
			ifwithoutsession=1;
		}*/
		snprintf(auth_msg, sizeof (auth_msg)-1, gettext("Session Expired!"));
		auth_form = 1;
	}

	  /********************/
	 /* Check Session ID */
	/********************/
	if (strcmp(server_sid, "$") != 0 && *client_sid != '$')
		if (strcmp(client_sid, server_sid) != 0 ||
		    strcmp(client_ip,
			   (char *) inet_ntoa(client_name.sin_addr)) != 0) {
			snprintf(auth_msg, sizeof (auth_msg)-1, gettext("You are not logged in!"));
			auth_form = 1;
		} else
			auth_form = 0;
	else {
		if ((long) lastactionsec == 0)
			snprintf(auth_msg, sizeof (auth_msg)-1, " ");
		auth_form = 1;
	}

 	  /********************************/
	 /* Define Environment Variables */
 	/********************************/
	snprintf(env_str, sizeof (env_str)-1, "netustadversion=%s", NUVERSION);
	env_p[0] = strdup(env_str);	/* netustad version */

	snprintf(env_str, sizeof (env_str)-1, "work_path=%s/script", workdir);
	env_p[1] = strdup(env_str);	/* work_path */

	env_p[2] = "auth_msg=";		/* authform message */

	snprintf(env_str, sizeof (env_str)-1, "server_sid=%s", server_sid);
	env_p[3] = strdup(env_str);	/* server session id */

	snprintf(env_str, sizeof (env_str)-1, "fw_cmd=%s", fw_cmd);
	env_p[4] = strdup(env_str);	/* iptables command */

	snprintf(env_str, sizeof (env_str)-1, "TEXTDOMAIN=%s", PACKAGE);
	env_p[5] = strdup(env_str);	/* TEXTDOMAIN (for gettext) */

	snprintf(env_str, sizeof (env_str)-1, "TEXTDOMAINDIR=%s", PACKAGE_LOCALE_DIR);
	env_p[6] = strdup(env_str);	/* TEXTDOMAINDIR (for gettext) */

	snprintf(env_str, sizeof (env_str)-1, "LC_ALL=%s", lc_all );
	env_p[7] = strdup(env_str);	/* Choose locale */

	snprintf(env_str, sizeof (env_str)-1, "gettext_cmd=%s", gettext_cmd);
	env_p[8] = strdup(env_str);	/* gettext command */

	snprintf(env_str, sizeof (env_str)-1, "cat_cmd=%s", cat_cmd);
	env_p[9] = strdup(env_str);	/* full path of cat command */

	snprintf(env_str, sizeof (env_str)-1, "awk_cmd=%s", awk_cmd);
	env_p[10] = strdup(env_str);	/* full path of awk command */

	snprintf(env_str, sizeof (env_str)-1, "MM_CHARSET=%s", gettext("charset"));
	env_p[11] = strdup(env_str);	/* charset environ */

	snprintf(env_str, sizeof (env_str)-1, "LANG=%s", lc_all );
	env_p[12] = strdup(env_str);	/* LANG environ */

	snprintf(env_str, sizeof (env_str)-1, "netstat_cmd=%s", netstat_cmd );
	env_p[13] = strdup(env_str);	/* netstat_cmd environ */

	snprintf(env_str, sizeof (env_str)-1, "grep_cmd=%s", grep_cmd );
	env_p[14] = strdup(env_str);	/* grep_cmd environ */

	snprintf(env_str, sizeof (env_str)-1, "tr_cmd=%s", tr_cmd );
	env_p[15] = strdup(env_str);	/* tr_cmd environ */

	snprintf(env_str, sizeof (env_str)-1, "sed_cmd=%s", sed_cmd );
	env_p[16] = strdup(env_str);	/* sed_cmd environ */

	snprintf(env_str, sizeof (env_str)-1, "tail_cmd=%s", tail_cmd );
	env_p[17] = strdup(env_str);	/* tail_cmd environ */

	snprintf(env_str, sizeof (env_str)-1, "route_cmd=%s", route_cmd );
	env_p[18] = strdup(env_str);	/* route_cmd environ */

	snprintf(env_str, sizeof (env_str)-1, "QUERY_STRING=a");
	env_p[19] = strdup(env_str);	/* QUERY_STRING environ */

	snprintf(env_str, sizeof (env_str)-1, "ifconfig_cmd=%s", ifconfig_cmd );
	env_p[20] = strdup(env_str);	/* ifconfig_cmd environ */

	env_p[21] = NULL;	/*temporary variable */
	env_p[22] = NULL;	/*temporary variable */
	env_p[23] = NULL;	/*parameter terminate */

 	  /***************************/
	 /* Parse Requested Address */
	/***************************/

	/* If Logout Requested Close Session and Goto Auth */
	if (rightcmp(path, "/logout")) {
		server_sid[0] = '$';
		server_sid[1] = '\0';
		snprintf(auth_msg, sizeof (auth_msg)-1, gettext("You are logged out"));
		log_msg(mainlogfile, gettext("Administrator logged out\n"), 1);
		auth_form = 1;
	/*} else if (ifwithoutsession && strcmp(withoutsession[t], "/authform")!=0) {
		snprintf(path, sizeof(path)-1, "script%s", withoutsession[t]);
	}*/
	} else if (rightcmp(path, "/images/bg.png")) {
		snprintf(path, sizeof (path)-1, "script/images/bg.png");
        } else if (rightcmp(path, "/images/buton_0.png")) {
                snprintf(path, sizeof(path)-1, "script/images/buton_0.png");
        } else if (rightcmp(path, "/images/buton_1.png")) {
                snprintf(path, sizeof(path)-1, "script/images/buton_1.png");
        } else if (rightcmp(path, "/images/buton_2.png")) {
                snprintf(path, sizeof(path)-1, "script/images/buton_2.png");
        } else if (rightcmp(path, "/images/buton_3.png")) {
                snprintf(path, sizeof(path)-1, "script/images/buton_3.png");
        } else if (rightcmp(path, "/images/menu_login.png")) {
                snprintf(path, sizeof(path)-1, "script/images/menu_login.png");
        } else if (rightcmp(path, "/images/menu_logout.png")) {
                snprintf(path, sizeof(path)-1, "script/images/menu_logout.png");
        } else if (rightcmp(path, "/images/menu_addrule.png")) {
                snprintf(path, sizeof(path)-1, "script/images/menu_addrule.png");
        } else if (rightcmp(path, "/images/menu_rulelist.png")) {
                snprintf(path, sizeof(path)-1, "script/images/menu_rulelist.png");
        } else if (rightcmp(path, "/images/buton_4.png")) {
                snprintf(path, sizeof(path)-1, "script/images/buton_4.png");
        } else if (rightcmp(path, "/images/buton_5.png")) {
                snprintf(path, sizeof(path)-1, "script/images/buton_5.png");
        } else if (rightcmp(path, "/images/buton_7.png")) {
                snprintf(path, sizeof(path)-1, "script/images/buton_7.png");
        } else if (rightcmp(path, "/images/banner.png")) {
                snprintf(path, sizeof(path)-1, "script/images/banner.png");
        } else if (rightcmp(path, "/images/banner-alt.png")) {
                snprintf(path, sizeof(path)-1, "script/images/banner-alt.png");
        } else if (rightcmp(path, "/images/editor.png")) {
                snprintf(path, sizeof(path)-1, "script/images/editor.png");
        } else if (rightcmp(path, "/images/eraser.png")) {
                snprintf(path, sizeof(path)-1, "script/images/eraser.png");
        } else if (rightcmp(path, "/netustad.css")) {
                snprintf(path, sizeof(path)-1, "script/netustad.css");
	}

	/* Other Requests */
	if (auth_form == 1 && \
	    !(rightcmp(path, "/auth")) && \
            !(rightcmp(path, "/netustad.css")) && \
            !(rightcmp(path, "/images/bg.png")) && \
            !(rightcmp(path, "/images/buton_0.png")) && \
            !(rightcmp(path, "/images/buton_1.png")) && \
            !(rightcmp(path, "/images/buton_2.png")) && \
            !(rightcmp(path, "/images/buton_3.png")) && \
            !(rightcmp(path, "/images/buton_4.png")) && \
            !(rightcmp(path, "/images/buton_5.png")) && \
            !(rightcmp(path, "/images/buton_6.png")) && \
            !(rightcmp(path, "/images/buton_7.png")) && \
            !(rightcmp(path, "/images/banner.png")) && \
            !(rightcmp(path, "/images/banner-alt.png")) && \
            !(rightcmp(path, "/images/editor.png")) && \
            !(rightcmp(path, "/images/eraser.png")) && \
	    !(rightcmp(path, "/images/menu_logout.png")) && \
	    !(rightcmp(path, "/images/menu_addrule.png")) && \
	    !(rightcmp(path, "/images/menu_rulelist.png")) && \
            !(rightcmp(path, "/images/menu_login.png"))) {
		snprintf(env_str, sizeof (env_str)-1, "auth_msg=%s", auth_msg);
		env_p[2] = strdup(env_str);
		snprintf(path, sizeof (path)-1, "script/authform");
	} else if (path[strlen(path) - 1] == '/') {
		strncat(path, "showrule", (size_t) (sizeof (path) - 1 - strlen(path)));
	} else if (rightcmp(path, "/edit")) {
		snprintf(env_str, sizeof (env_str)-1, "ruleno=%s", strtok(query_string,"@\n"));
		env_p[21] = strdup(env_str);
	#ifdef LINUX
		snprintf(env_str, sizeof (env_str)-1, "chain=%s", strtok(NULL,"@\n"));
		env_p[22] = strdup(env_str);
	#endif
		strncat(path, "form", (size_t) (sizeof (path) - 1 - strlen(path)));

	} else if (rightcmp(path, "/if_edit")) {
		snprintf(env_str, sizeof (env_str)-1, "if_name=%s", strtok(query_string,"@\n"));
		env_p[21] = strdup(env_str);
		snprintf(path, sizeof(path)-1, "script/if_edit");
	
	} else if (rightcmp(path, "/nat_del")) {
		snprintf(env_str, sizeof (env_str)-1, "nat_name=%s", strtok(query_string,"@\n"));
		env_p[21] = strdup(env_str);
		snprintf(path, sizeof(path)-1, "script/nat_del");
	
	} else if (rightcmp(path, "/rt_del")) {
		snprintf(env_str, sizeof (env_str)-1, "route=%s", strtok(query_string,"@\n"));
		env_p[21] = strdup(env_str);
		snprintf(path, sizeof(path)-1, "script/rt_del");
	
	} else if (rightcmp(path, "/auth") && auth_form == 1) {
		snprintf(path, sizeof (path)-1, "%s", auth(query_string));
		snprintf(env_str, sizeof (env_str)-1, "auth_msg=%s", auth_msg);
		env_p[2] = strdup(env_str);
		snprintf(env_str, sizeof (env_str)-1, "server_sid=%s", server_sid);
		env_p[3] = strdup(env_str);
	#ifdef FREEBSD
	} else if (rightcmp(path, "/write")) {
		snprintf(path, sizeof(path)-1, "script/writeconfig");
	#endif	
	}

	/* If Rule Deleting Requested ("del" word) */
	if (rightcmp(path, "/del")) {
		strncpy(path, fw_cmd, sizeof (path)-1);
		deleterule(client, path, header, query_string);
	} else if (rightcmp(path, "/addnew")) {
		strncpy(path, fw_cmd, sizeof (path)-1);
		addnewrule(client, path, header, query_string);
	} else if (rightcmp(path, "/applyedit")) {
		strncpy(path, fw_cmd, sizeof (path)-1);
		editrule(client, path, header, query_string);
	} else if (stat(path, &st) == -1) {
		snprintf(log_msg_text, sizeof(log_msg_text)-1, gettext("File not found: %s"), path);
		log_msg(logfile, log_msg_text, 1);
		not_found(client);
	} else {
		if ((st.st_mode & S_IFMT) == S_IFDIR)
			strncat(path, "/showrule",
				(size_t) (sizeof (path) - 1 - strlen(path)));
		if ((st.st_mode & S_IXUSR) || (st.st_mode & S_IXGRP)
		    || (st.st_mode & S_IXOTH))
			cgi = 1;
		if (!cgi)
			serve_file(client, path);
		else
			snprintf(env_str, sizeof (env_str)-1, "QUERY_STRING=%s", query_string);
			env_p[19] = strdup(env_str);	/* QUERY_STRING environ */
			execute_cgi(client, path, header, query_string, env_p, 1);
	}
	return;
}
Esempio n. 8
0
void accept_request(int client)  
{  
    char buf[1024];  
    int numchars;  
    char method[255];  
    char url[255];  
    char path[512];  
    size_t i, j;  
    struct stat st;  
    int cgi = 0;      /* becomes true if server decides this is a CGI program */  
    char *query_string = NULL;  
  
    /*得到请求的第一行*/  
    numchars = get_line(client, buf, sizeof(buf));  
    i = 0; j = 0;  
    /*把客户端的请求方法存到 method 数组*/  
    while (!ISspace(buf[j]) && (i < sizeof(method) - 1))  
    {  
        method[i] = buf[j];  
        i++; j++;  
    }  
    method[i] = '\0';  
  
    /*如果既不是 GET 又不是 POST 则无法处理 */  
    if (strcasecmp(method, "GET") && strcasecmp(method, "POST"))  
    {  
        unimplemented(client);  
        return;  
    }  
  
    /* POST 的时候开启 cgi */  
    if (strcasecmp(method, "POST") == 0)  
        cgi = 1;  
  
    /*读取 url 地址*/  
    i = 0;  
    while (ISspace(buf[j]) && (j < sizeof(buf)))  
        j++;  
    while (!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < sizeof(buf)))  
    {  
        /*存下 url */  
        url[i] = buf[j];  
        i++; j++;  
    }  
    url[i] = '\0';  
  
    /*处理 GET 方法*/  
    if (strcasecmp(method, "GET") == 0)  
    {  
        /* 待处理请求为 url */  
        query_string = url;  
        while ((*query_string != '?') && (*query_string != '\0'))  
            query_string++;  
        /* GET 方法特点,? 后面为参数*/  
        if (*query_string == '?')  
        {  
            /*开启 cgi */  
            cgi = 1;  
            *query_string = '\0';  
            query_string++;  
        }  
    }  
  
    /*格式化 url 到 path 数组,html 文件都在 htdocs 中*/  
    sprintf(path, "htdocs%s", url);  
    /*默认情况为 index.html */  
    if (path[strlen(path) - 1] == '/')  
        strcat(path, "index.html");  
    /*根据路径找到对应文件 */  
    if (stat(path, &st) == -1) {  
        /*把所有 headers 的信息都丢弃*/  
        while ((numchars > 0) && strcmp("\n", buf))  /* read & discard headers */  
            numchars = get_line(client, buf, sizeof(buf));  
        /*回应客户端找不到*/  
        not_found(client);  
    }  
    else  
    {  
        /*如果是个目录,则默认使用该目录下 index.html 文件*/  
        if ((st.st_mode & S_IFMT) == S_IFDIR)  
            strcat(path, "/index.html");  
      if ((st.st_mode & S_IXUSR) || (st.st_mode & S_IXGRP) || (st.st_mode & S_IXOTH)    )  
          cgi = 1;  
      /*不是 cgi,直接把服务器文件返回,否则执行 cgi */  
      if (!cgi)  
          serve_file(client, path);  
      else  
          execute_cgi(client, path, method, query_string);  
    }  
  
    /*断开与客户端的连接(HTTP 特点:无连接)*/  
    close(client);  
}  
Esempio n. 9
0
void accept_request(void *arg)
{
 int client = *((int*)arg);
 char buf[1024];
 int numchars;
 char method[255];
 char url[255];
 char path[512];
 size_t i, j;
 struct stat st;
 int cgi = 0;      /* becomes true if server decides this is a CGI
                    * program */
 char *query_string = NULL;

 //读http 请求的第一行数据(request line),把请求方法存进 method 中
 numchars = get_line(client, buf, sizeof(buf));
 i = 0; j = 0;
 while (!ISspace(buf[j]) && (i < sizeof(method) - 1))
 {
  method[i] = buf[j];
  i++; j++;
 }
 method[i] = '\0';

 //如果请求的方法不是 GET 或 POST 任意一个的话就直接发送 response 告诉客户端没实现该方法
 if (strcasecmp(method, "GET") && strcasecmp(method, "POST"))
 {
  unimplemented(client);
  return;
 }

 //如果是 POST 方法就将 cgi 标志变量置一(true)
 if (strcasecmp(method, "POST") == 0)
  cgi = 1;

 i = 0;
 //跳过所有的空白字符(空格)
 while (ISspace(buf[j]) && (j < sizeof(buf))) 
  j++;
 
 //然后把 URL 读出来放到 url 数组中
 while (!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < sizeof(buf)))
 {
  url[i] = buf[j];
  i++; j++;
 }
 url[i] = '\0';

 //如果这个请求是一个 GET 方法的话
 if (strcasecmp(method, "GET") == 0)
 {
  //用一个指针指向 url
  query_string = url;
  
  //去遍历这个 url,跳过字符 ?前面的所有字符,如果遍历完毕也没找到字符 ?则退出循环
  while ((*query_string != '?') && (*query_string != '\0'))
   query_string++;
  
  //退出循环后检查当前的字符是 ?还是字符串(url)的结尾
  if (*query_string == '?')
  {
   //如果是 ? 的话,证明这个请求需要调用 cgi,将 cgi 标志变量置一(true)
   cgi = 1;
   //从字符 ? 处把字符串 url 给分隔会两份
   *query_string = '\0';
   //使指针指向字符 ?后面的那个字符
   query_string++;
  }
 }

 //将前面分隔两份的前面那份字符串,拼接在字符串htdocs的后面之后就输出存储到数组 path 中。相当于现在 path 中存储着一个字符串
 sprintf(path, "htdocs%s", url);
 
 //如果 path 数组中的这个字符串的最后一个字符是以字符 / 结尾的话,就拼接上一个"index.html"的字符串。首页的意思
 if (path[strlen(path) - 1] == '/')
  strcat(path, "index.html");
 
 //在系统上去查询该文件是否存在
 if (stat(path, &st) == -1) {
  //如果不存在,那把这次 http 的请求后续的内容(head 和 body)全部读完并忽略
  while ((numchars > 0) && strcmp("\n", buf))  /* read & discard headers */
   numchars = get_line(client, buf, sizeof(buf));
  //然后返回一个找不到文件的 response 给客户端
  not_found(client);
 }
 else
 {
	 LOG_INFO("accept request  1");
  //文件存在,那去跟常量S_IFMT相与,相与之后的值可以用来判断该文件是什么类型的
  //S_IFMT参读《TLPI》P281,与下面的三个常量一样是包含在<sys/stat.h>
  if ((st.st_mode & S_IFMT) == S_IFDIR)  
   //如果这个文件是个目录,那就需要再在 path 后面拼接一个"/index.html"的字符串
   strcat(path, "/index.html");
   
   //S_IXUSR, S_IXGRP, S_IXOTH三者可以参读《TLPI》P295
  if ((st.st_mode & S_IXUSR) ||       
      (st.st_mode & S_IXGRP) ||
      (st.st_mode & S_IXOTH)    )
   //如果这个文件是一个可执行文件,不论是属于用户/组/其他这三者类型的,就将 cgi 标志变量置一
   cgi = 1;
   
  if (!cgi)
   //如果不需要 cgi 机制的话,
   serve_file(client, path);
  else
   //如果需要则调用
   execute_cgi(client, path, method, query_string);
 }

 LOG_INFO("accept request end");
 close(client);
}
Esempio n. 10
0
void* accept_request(void* arg)
{
	int client=(int)arg;
	char buf[1024];
	int numchars;
	char method[255];
	char url[255];
	char path[512];
	size_t i, j;
	struct stat st;
	int cgi = 0;/* becomes true if server decides this is a CGI
                    * program */
	char *query_string = NULL;

	numchars = get_line(client, buf, sizeof(buf));
	i = 0; j = 0;
	//解析method:GET OR POST?
	while (!ISspace(buf[j]) && (i < sizeof(method) - 1))
	{
		method[i] = buf[j];
		i++; j++;
	}
	method[i] = '\0';

	if (strcasecmp(method, "GET") && strcasecmp(method, "POST"))
	{
		unimplemented(client);
		return NULL;
	}
	//如果method为POST,则开启CGI;
	if (strcasecmp(method, "POST") == 0)
		cgi = 1;

	i = 0;
	while (ISspace(buf[j]) && (j < sizeof(buf)))
		j++;
	//获取method对应的url,例如:url=/color.cgi?color=red;
	while (!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < sizeof(buf)))
	{
		url[i] = buf[j];
		i++; j++;
	}
	url[i] = '\0';

	//如果method为GET,判断url中是否有CGI; 
	if (strcasecmp(method, "GET") == 0)
	{
		query_string = url;
		while ((*query_string != '?') && (*query_string != '\0'))
			query_string++;
		if (*query_string == '?')
		{
			cgi = 1;
			*query_string = '\0';
			query_string++;
		}
	}

	sprintf(path, "htdocs%s", url);
	if (path[strlen(path) - 1] == '/')
		strcat(path, "index.html");
	if (stat(path, &st) == -1) {
		while ((numchars > 0) && strcmp("\n", buf))  /* read & discard headers */
			numchars = get_line(client, buf, sizeof(buf));
		not_found(client);
	}
	else
	{
		if ((st.st_mode & S_IFMT) == S_IFDIR)
			strcat(path, "/index.html");
		//如果path指定的文件为可执行文件,则CGI置位;
		if ((st.st_mode & S_IXUSR) ||
			(st.st_mode & S_IXGRP) ||
				(st.st_mode & S_IXOTH)    )
			cgi = 1;
		if (!cgi)
			serve_file(client, path);
		else
			execute_cgi(client, path, method, query_string);
	}

	close(client);
	return NULL;
}
Esempio n. 11
0
/* ********************************
 * @描述:处理客户端HTTP请求
 * @输入:[in] client:	客户端地址
 * @输出: 无
 * ********************************/
void accept_request(int client)
{
	char buf[1024];
	int numchars;
	char method[255];
	char url[255];
	char path[512];
	size_t i, j;	// unsigned int
	struct stat st; // 保存文件信息
	int cgi = 0;	// 当服务端认为它是一个CGI时变成1
	char *query_string = NULL;

	/* 得到请求的第一行 */
	numchars = get_line(client, buf, sizeof(buf));
	i = 0;
	j = 0;
	
	/* 把客户端的请求方法存到method数组,遇到空格则停止 */
	while(!ISspace(buf[j]) && (i < sizeof(method) - 1))
	{
		method[i] = buf[j];
		i++; j++;
	}
	method[i] = '\0';
	
	/* 既不是GET也不是POST的情况,忽略大小写进行比较 */
	if(strcasecmp(method, "GET") && strcasecmp(method, "POST"))
	{
		unimplemented(client);
		return;
	}
	
	/* POST的情况,开启CGI */
	if(strcasecmp(method, "POST") == 0)
		cgi = 1;
	
	/* 读取URL地址 */
	i = 0;
	while(ISspace(buf[j]) && (j < sizeof(buf)))// 过滤掉空格
		j++;
	while(!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < sizeof(buf)))
	{
		url[i] = buf[j]; // 存下URL
		i++; j++;
	}
	url[i] = '\0';

	/* 处理GET方法 */
	if(strcasecmp(method, "GET") == 0)
	{
		query_string = url;
		/* 找到URL中的? */
		while((*query_string != '?') && (*query_string != '\0'))
			query_string++;
		/* GET方法特点,?后面为参数 */
		if(*query_string == '?')
		{
			cgi = 1;
			*query_string = '\0';
			query_string++;		//query_string指向'?'后面
		}
	}

	/* 格式化URL到path数组,html文件在htdocs目录中 */
	sprintf(path, "htdocs%s", url);
	/* 默认情况为index.html */
	if(path[strlen(path) - 1] == '/')// path中最后一个字符
		strcat(path, "index.html");

	/* 根据路径找到对应文件 */
	if(stat(path, &st) == -1) // 通过文件名path获取文件信息,并保存到st中,-1表示失败
	{
		/* 读取并丢弃header */
		while((numchars > 0) && strcmp("\n", buf))// strcmp 相等返回0
			numchars = get_line(client, buf, sizeof(buf));
		not_found(client);
	}
	else
	{
		/* 如果是目录,则默认使用该目录下的index.html 文件*/
		if((st.st_mode & S_IFMT) == S_IFDIR)
			strcat(path, "/index.html");
		if((st.st_mode & S_IXUSR) ||
		   (st.st_mode & S_IXGRP) ||
		   (st.st_mode & S_IXOTH)    )
			cgi = 1;

		if(!cgi) // cgi == 0
			serve_file(client, path);
		else	 // cgi == 1
			execute_cgi(client, path, method, query_string);
	}
	/* 断开与客户端的连接 */
	close(client);
}
Esempio n. 12
0
/* To reduce redundant error handling code [calls to abort_connection()]
 * most of the function is build around conditions that will assign the error
 * code to @state if anything goes wrong. The rest of the function will then just
 * do the necessary cleanups. If all works out we end up with @state being S_OK
 * resulting in a cache entry being created with the fragment data generated by
 * either reading the file content or listing a directory. */
void
file_protocol_handler(struct connection *connection)
{
	unsigned char *redirect_location = NULL;
	struct string page, name;
	struct connection_state state;
	int set_dir_content_type = 0;

	if (get_cmd_opt_bool((const unsigned char *)"anonymous")) {
		if (strcmp((const char *)connection->uri->string, "file:///dev/stdin")
		    || isatty(STDIN_FILENO)) {
			abort_connection(connection,
					 connection_state(S_FILE_ANONYMOUS));
			return;
		}
	}

#ifdef CONFIG_CGI
	if (!execute_cgi(connection)) return;
#endif /* CONFIG_CGI */

	/* Treat /dev/stdin in special way */
	if (!strcmp((const char *)connection->uri->string, "file:///dev/stdin")) {
		int fd = open("/dev/stdin", O_RDONLY);

		if (fd == -1) {
			abort_connection(connection, connection_state(-errno));
			return;
		}
		set_nonblocking_fd(fd);
		if (!init_http_connection_info(connection, 1, 0, 1)) {
			abort_connection(connection, connection_state(S_OUT_OF_MEM));
			close(fd);
			return;
		}
		connection->socket->fd = fd;
		connection->data_socket->fd = -1;
		read_from_stdin(connection);
		return;
	}


	/* This function works on already simplified file-scheme URI pre-chewed
	 * by transform_file_url(). By now, the function contains no hostname
	 * part anymore, possibly relative path is converted to an absolute one
	 * and uri->data is just the final path to file/dir we should try to
	 * show. */

	if (!init_string(&name)
	    || !add_uri_to_string(&name, connection->uri, URI_PATH)) {
		done_string(&name);
		abort_connection(connection, connection_state(S_OUT_OF_MEM));
		return;
	}

	decode_uri_string(&name);

	/* In Win32, file_is_dir seems to always return 0 if the name
	 * ends with a directory separator.  */
	if ((name.length > 0 && dir_sep(name.source[name.length - 1]))
	    || file_is_dir(name.source)) {
		/* In order for global history and directory listing to
		 * function properly the directory url must end with a
		 * directory separator. */
		if (name.source[0] && !dir_sep(name.source[name.length - 1])) {
			redirect_location = (unsigned char *)STRING_DIR_SEP;
			state = connection_state(S_OK);
		} else {
			state = list_directory(connection, name.source, &page);
			set_dir_content_type = 1;
		}

	} else {
		state = read_encoded_file(&name, &page);
		/* FIXME: If state is now S_ENCODE_ERROR we should try loading
		 * the file undecoded. --jonas */
	}

	done_string(&name);

	if (is_in_state(state, S_OK)) {
		struct cache_entry *cached;

		/* Try to add fragment data to the connection cache if either
		 * file reading or directory listing worked out ok. */
		cached = connection->cached = get_cache_entry(connection->uri);
		if (!connection->cached) {
			if (!redirect_location) done_string(&page);
			state = connection_state(S_OUT_OF_MEM);

		} else if (redirect_location) {
			if (!redirect_cache(cached, redirect_location, 1, 0))
				state = connection_state(S_OUT_OF_MEM);

		} else {
			add_fragment(cached, 0, page.source, page.length);
			connection->from += page.length;

			if (!cached->head && set_dir_content_type) {
				unsigned char *head;

				/* If the system charset somehow
				 * changes after the directory listing
				 * has been generated, it should be
				 * parsed with the original charset.  */
				head = straconcat((const unsigned char *)"\r\nContent-Type: text/html; charset=",
						  get_cp_mime_name(get_cp_index((const unsigned char *)"System")),
						  "\r\n", (unsigned char *) NULL);

				/* Not so gracefully handle failed memory
				 * allocation. */
				if (!head)
					state = connection_state(S_OUT_OF_MEM);

				/* Setup directory listing for viewing. */
				mem_free_set(&cached->head, head);
			}

			done_string(&page);
		}
	}

	abort_connection(connection, state);
}
Esempio n. 13
0
// 处理客户端请求,服务器核心控制逻辑
void accept_request(int client)
{
 char buf[1024];
 int numchars;
 char method[255];
 char url[255];
 char path[512];
 size_t i, j;
 struct stat st;
 int cgi = 0;      /* becomes true if server decides this is a CGI
                    * program */
 char *query_string = NULL;

 numchars = get_line(client, buf, sizeof(buf)); // 读取请求行
 i = 0; j = 0;
 while (!ISspace(buf[j]) && (i < sizeof(method) - 1))
 {
  method[i] = buf[j];
  i++; j++;
 } // 循环截取出请求方法
 method[i] = '\0';

 if (strcasecmp(method, "GET") && strcasecmp(method, "POST")) // 只接收GET和POST请求
 {
  unimplemented(client); // 响应未实现页面
  return;
 }

 if (strcasecmp(method, "POST") == 0) // POST请求
  cgi = 1;

 i = 0;
 while (ISspace(buf[j]) && (j < sizeof(buf))) // 刚才截取method后j定位到后面的一个空格处,现在一直向后移动j直到指向非空白字符
  j++;
 while (!ISspace(buf[j]) && (i < sizeof(url) - 1) && (j < sizeof(buf)))
 {
  url[i] = buf[j];
  i++; j++;
 } // 循环截取出请求的url资源
 url[i] = '\0';

 if (strcasecmp(method, "GET") == 0) // GET请求
 {
  query_string = url; // 查询字符串在url中的?号后面
  while ((*query_string != '?') && (*query_string != '\0')) // 一直移动到?号处
   query_string++;
  if (*query_string == '?')
  {
   cgi = 1;
   *query_string = '\0'; // ?号置为\0,url就切出来了
   query_string++; // 查询字符串从?后面一个字符开始
  }
 }

 sprintf(path, "htdocs%s", url); // htdocs/url/   htdocs/res.html
 if (path[strlen(path) - 1] == '/') // 最后一个字符是‘/’,默认访问该目录下的 index.html 页面
  strcat(path, "index.html");
 if (stat(path, &st) == -1) { // 获取文件详细信息失败
  while ((numchars > 0) && strcmp("\n", buf))  /* read & discard headers */ // 读取剩下的请求头
   numchars = get_line(client, buf, sizeof(buf));
  not_found(client); // 404
 }
 else
 {
  if ((st.st_mode & S_IFMT) == S_IFDIR) // 是一个目录,默认访问该目录下的 index.html 页面
   strcat(path, "/index.html");
  if ((st.st_mode & S_IXUSR) ||
      (st.st_mode & S_IXGRP) ||
      (st.st_mode & S_IXOTH)    ) // 这个资源有执行权限 包括 所有者 同组 其他人
   cgi = 1;
  if (!cgi)
   serve_file(client, path); // 请求的是个页面,返回这页面
  else
   execute_cgi(client, path, method, query_string); // cgi程序,可以执行这个程序,处理过程交给cgi程序
 }

 close(client); // 关闭client socket
}