Ejemplo n.º 1
0
    message::error_code request_header::end_of_request()
    {
        const header* const host_header = find_header_impl("host");

        if ( host_header == 0 )
            return bad_request();

        const tools::substring host = host_header->value();

        tools::substring::const_iterator pos = host.end();
        for ( ; pos != host.begin() && std::isdigit(*(pos-1)) != 0; --pos )
            ;

        if ( pos != host.begin() && *(pos-1) == ':' )
        {
            if ( pos != host.end() && !parse_number(pos, host.end(), port_) || port_ > 0xffff )
                return bad_request();

            host_ = tools::substring(host.begin(), pos-1);
        }
        else
        {
            host_ = host;
        }

        return ok;
    }
Ejemplo n.º 2
0
void TCGI::start(TBuffer * rb_, TBuffer * wb_) {
    rb = rb_;
    wb = wb_;
    r = new TRequest(rb);
    if (r->status < 0) {
        bad_request();
    } else {
        std::string path = r->path;
        std::string fpath = folder + path;

        std::ifstream * f = new std::ifstream(fpath, std::ios::in );
        if (!f->is_open()) {
            wb->append(t404);
        } else {
            std::string content;
            getline(*f, content, '\0');
            f->close();
            std::stringstream ss;
            ss  << "HTTP/1.0 200 OK\r\nContent-length: " << content.size()
                << "\r\nConnection: close\r\nContent-Type: text/html\r\n\r\n" << content;
            wb->append(ss.str());
        }
        delete f;

    }
    return;
}
Ejemplo n.º 3
0
Archivo: cgi.c Proyecto: NUOG/ejudge
/**
 * NAME:    cgi_read
 * PURPOSE: read all the given CGI parameters
 * ARGS:    charset - character set to report errors
 * RETURN:   0 - OK,
 *          -1 - error
 * NOTE:    parse routines write error messages directly to stderr
 */
int
cgi_read(char const *charset)
{
  char *ct = 0;
  query = getenv("QUERY_STRING");
  if (query) {
    source = 0;
    if (do_cgi_read() < 0) return -1;
  }
  ct = getenv("CONTENT_TYPE");
  if (ct && !strncmp(ct, multipart, sizeof(multipart) - 1)) {
    /* got a multipart/form-data */
    return parse_multipart(charset);
  }

  const unsigned char *cl = getenv("CONTENT_LENGTH");
  if (cl) {
    errno = 0;
    char *eptr = NULL;
    int val = strtol(cl, &eptr, 10);
    if (errno || *eptr || val < 0) {
      bad_request(charset);
      exit(0);
    }
    if (val > MAX_CONTENT_LENGTH) {
      request_too_large(charset);
      exit(0);
    }
    content_length = val;
  }

  source = 1;
  if (do_cgi_read() < 0) return -1;
  return 0;
}
Ejemplo n.º 4
0
void accept_request(dino_http_site_t *dino_site, dino_handle_t *dhandle) {
    // Setup DHANDLE:
    //
    if (!read_request(&dhandle->http)) {
        bad_request(dhandle->http.socket);
    }
    else {
        // Parse the URL Parameters.
        //
        stack_char_ptr_t *url_stack = stack_ptr_parse(NULL, string_buffer_c_string(dhandle->http.request.url), "/");

        // Search for a match...
        //
        dino_route_t *route = list_method_find(dino_site->list, dhandle->http.request.method, url_stack);

        // Do we have a route?
        //
        if (NULL != route) {
            invoke_method(route, &dhandle->http, url_stack);
        }
        else {
            fprintf(stderr, "[ERROR] Path %s not found; \n\r", string_buffer_c_string(dhandle->http.request.url));
        }

        stack_ptr_free(url_stack);
    }
}
Ejemplo n.º 5
0
int cmd_main(int argc, const char **argv)
{
	char *method = getenv("REQUEST_METHOD");
	char *dir;
	struct service_cmd *cmd = NULL;
	char *cmd_arg = NULL;
	int i;
	struct strbuf hdr = STRBUF_INIT;

	set_die_routine(die_webcgi);
	set_die_is_recursing_routine(die_webcgi_recursing);

	if (!method)
		die("No REQUEST_METHOD from server");
	if (!strcmp(method, "HEAD"))
		method = "GET";
	dir = getdir();

	for (i = 0; i < ARRAY_SIZE(services); i++) {
		struct service_cmd *c = &services[i];
		regex_t re;
		regmatch_t out[1];

		if (regcomp(&re, c->pattern, REG_EXTENDED))
			die("Bogus regex in service table: %s", c->pattern);
		if (!regexec(&re, dir, 1, out, 0)) {
			size_t n;

			if (strcmp(method, c->method))
				return bad_request(&hdr, c);

			cmd = c;
			n = out[0].rm_eo - out[0].rm_so;
			cmd_arg = xmemdupz(dir + out[0].rm_so + 1, n - 1);
			dir[out[0].rm_so] = 0;
			break;
		}
		regfree(&re);
	}

	if (!cmd)
		not_found(&hdr, "Request not supported: '%s'", dir);

	setup_path();
	if (!enter_repo(dir, 0))
		not_found(&hdr, "Not a git repository: '%s'", dir);
	git_config(git_default_config, NULL);
	if (!getenv("GIT_HTTP_EXPORT_ALL") &&
	    access("git-daemon-export-ok", F_OK) )
		not_found(&hdr, "Repository not exported: '%s'", dir);

	http_config();
	max_request_buffer = git_env_ulong("GIT_HTTP_MAX_REQUEST_BUFFER",
					   max_request_buffer);

	cmd->imp(&hdr, cmd_arg);
	return 0;
}
Ejemplo n.º 6
0
void do_request(struct wen_request *request)
{
	if(!parse_request(request)){
		bad_request(request);
		wen_free(request);
		return ;
	}

	//wen_free(request);
}
Ejemplo n.º 7
0
char *
tracker_handle_request (char *pkey, char *req, announce_info_t *ai,
		char *info_hash)
{
	if ((strcmp (pkey, "announce") == 0)
			|| (strcmp (pkey, "scrape") == 0)) {
		return missing_pass_key ();
	}

	if ((strcmp (req, "announce") != 0) && (strcmp (req, "scrape") != 0)) {
		return bad_request ();
	}

	debug_unimplemented ();
	return NULL;
}
Ejemplo n.º 8
0
/* Consumes connection file descriptors from the shared buffer and 
 * processes them.
 */
void *thread(void *vargp){
    // avoid memory leak
    Pthread_detach(pthread_self());
    req_t request;
    int result;
    while(1){
        int connfd = sbuf_remove(&sbuf);
        if((result = process_request(connfd, &request)) == -1){
            fprintf(stderr,"process_request failed\n");
            bad_request(connfd);
            free_req(request);
            Close(connfd);
            continue;
        }

        forward_request(connfd, request);
        Close(connfd);	
    }	
}
Ejemplo n.º 9
0
void server::HttpServer::worker(server::TcpServerConnection* connection)
{
  server::HttpServerSession session;
  session.connection = connection;

  try
  {
    process_request(&session);
    check_request(&session);
    prepare_session(&session);
    request_handler(session);
    check_session_response(&session);
    send_response(&session);
  }
  catch(Exception& e)
  {
    bad_request(&session, e);
  }
  catch(std::bad_alloc& e)
  {
  }
}
Ejemplo n.º 10
0
void echo_error_to_client(int client, int error_code)
{
    switch(error_code)
    {
        case 400: // request error
            bad_request(client);
            break;
        case 404: // not found
            not_found(client);
            break;
        case 500: // server error
            //server_error(client);
            break;
        case 503: // server unavailable
            //server_unavailable(client);
            break;
        
        //...............................
        default:
            //default_error(client);
            break;
    }
}
Ejemplo n.º 11
0
void execute_cgi(int client, const char *path,
                 const char *method, const char *query_string)
{
 char buf[1024];
 int cgi_output[2];
 int cgi_input[2];
 pid_t pid;
 int status;
 int i;
 char c;
 int numchars = 1;
 int content_length = -1;
 
 //往 buf 中填东西以保证能进入下面的 while
 buf[0] = 'A'; buf[1] = '\0';
 //如果是 http 请求是 GET 方法的话读取并忽略请求剩下的内容
 if (strcasecmp(method, "GET") == 0)
  while ((numchars > 0) && strcmp("\n", buf))  /* read & discard headers */
   numchars = get_line(client, buf, sizeof(buf));
 else    /* POST */
 {
  //只有 POST 方法才继续读内容
  numchars = get_line(client, buf, sizeof(buf));
  //这个循环的目的是读出指示 body 长度大小的参数,并记录 body 的长度大小。其余的 header 里面的参数一律忽略
  //注意这里只读完 header 的内容,body 的内容没有读
  while ((numchars > 0) && strcmp("\n", buf))
  {
   buf[15] = '\0';
   if (strcasecmp(buf, "Content-Length:") == 0)
    content_length = atoi(&(buf[16])); //记录 body 的长度大小
   numchars = get_line(client, buf, sizeof(buf));
  }
  
  //如果 http 请求的 header 没有指示 body 长度大小的参数,则报错返回
  if (content_length == -1) {
   bad_request(client);
   return;
  }
 }

 sprintf(buf, "HTTP/1.0 200 OK\r\n");
 send(client, buf, strlen(buf), 0);

 //下面这里创建两个管道,用于两个进程间通信
 if (pipe(cgi_output) < 0) {
  cannot_execute(client);
  return;
 }
 if (pipe(cgi_input) < 0) {
  cannot_execute(client);
  return;
 }

 //创建一个子进程
 if ( (pid = fork()) < 0 ) {
  cannot_execute(client);
  return;
 }
 
 //子进程用来执行 cgi 脚本
 if (pid == 0)  /* child: CGI script */
 {
  char meth_env[255];
  char query_env[255];
  char length_env[255];

  //dup2()包含<unistd.h>中,参读《TLPI》P97
  //将子进程的输出由标准输出重定向到 cgi_ouput 的管道写端上
  dup2(cgi_output[1], 1);
  //将子进程的输出由标准输入重定向到 cgi_ouput 的管道读端上
  dup2(cgi_input[0], 0);
  //关闭 cgi_ouput 管道的读端与cgi_input 管道的写端
  close(cgi_output[0]);
  close(cgi_input[1]);
  
  //构造一个环境变量
  sprintf(meth_env, "REQUEST_METHOD=%s", method);
  //putenv()包含于<stdlib.h>中,参读《TLPI》P128
  //将这个环境变量加进子进程的运行环境中
  putenv(meth_env);
  
  //根据http 请求的不同方法,构造并存储不同的环境变量
  if (strcasecmp(method, "GET") == 0) {
   sprintf(query_env, "QUERY_STRING=%s", query_string);
   putenv(query_env);
  }
  else {   /* POST */
   sprintf(length_env, "CONTENT_LENGTH=%d", content_length);
   putenv(length_env);
  }
  
  //execl()包含于<unistd.h>中,参读《TLPI》P567
  //最后将子进程替换成另一个进程并执行 cgi 脚本
  execl(path, path, NULL);
  exit(0);
  
 } else {    /* parent */
  //父进程则关闭了 cgi_output管道的写端和 cgi_input 管道的读端
  close(cgi_output[1]);
  close(cgi_input[0]);
  
  //如果是 POST 方法的话就继续读 body 的内容,并写到 cgi_input 管道里让子进程去读
  if (strcasecmp(method, "POST") == 0)
   for (i = 0; i < content_length; i++) {
    recv(client, &c, 1, 0);
    write(cgi_input[1], &c, 1);
   }
   
  //然后从 cgi_output 管道中读子进程的输出,并发送到客户端去
  while (read(cgi_output[0], &c, 1) > 0)
   send(client, &c, 1, 0);

  //关闭管道
  close(cgi_output[0]);
  close(cgi_input[1]);
  //等待子进程的退出
  waitpid(pid, &status, 0);
 }
}
Ejemplo n.º 12
0
int handle_client_connection() {
    char buffer[8096];
    int buffer_len; // Length of buffer

    char method[256];
    char url[256];
    char version[256];

    int i = 0, // Used to iterate over the first line to get method, url, version
        j = 0;

    // Read first line
    buffer_len = read_line(client_sockfd, buffer, sizeof(buffer));

    // Unable to read from socket, not sure what to do in this case
    if (buffer_len <= 0) {
        return -1;
    }

    fprintf(stderr, "==== Read Next Request ====\n");

    // Get Method (e.g. GET, POST, etc)
    while ((i < (sizeof(method) - 1)) && (!isspace(buffer[i]))) {
        method[i] = buffer[i];
        i++;
    }
    method[i] = '\0';

    // fprintf(stderr, "method: %s\n", method);

    // Skip over spaces
    while (i < buffer_len && isspace(buffer[i])) {
        i++;
    }

    // Get URL
    j = 0;
    while (i < buffer_len && (j < (sizeof(url) - 1)) && !isspace(buffer[i])) {
        url[j] = buffer[i];
        i++;
        j++;
    }
    url[j] = '\0';

    // fprintf(stderr, "url: %s\n", url);

    // Skip over spaces
    while (i < buffer_len && isspace(buffer[i])) {
        i++;
    }

    j = 0;
    while (j < sizeof(version) - 1 && !isspace(buffer[i])) {
        version[j] = buffer[i];
        i++;
        j++;
    }
    version[j] = '\0';

    // fprintf(stderr, "version: %s\n", version);

    read_headers();

    if (header_err_flag) {
        keep_alive = FALSE;
        bad_request();
        return -1;
    }

    if (content_length > 0) {
        content = (char*) malloc(content_length + 1);
        read_socket(client_sockfd, content, content_length);
    }

    // fprintf(stderr, "Content-Length: %d\n", content_length);
    // fprintf(stderr, "Connection (keep_alive): %d\n", keep_alive);
    // fprintf(stderr, "Cookie: %d\n", cookie);
    // fprintf(stderr, "If-Modified-Since Valid Time: %d\n", time_is_valid);
    // fprintf(stderr, "If-Modified-Since Time: %p\n", if_modified_since);
    if (content != NULL) {
        // fprintf(stderr, "Content: %s\n", content);
    }

    /***********************************************************/
    /*       Full message has been read, respond to client     */
    /***********************************************************/

    if (strcmp(method, "GET") != 0) {
        // Inform client we don't support method
        fprintf(stderr, "Method Not Allowed: %s\n", method);
        method_not_allowed();    
        return 0;
    }

    if (cookie) {
        // Inform client we don't support cookies
        not_implemented();
        return 0;
    }

    if (not_eng) {
        // Inform client we only support English
        not_implemented();
        return 0;
    }

    if (!acceptable_text) {
        // Inform client we only support plain text
        not_implemented();
        return 0;
    }

    if (!acceptable_charset) {
        // Inform client we only support ASCII
        not_implemented();
        return 0;
    }

    // Fix filename
    char file_path[512];
    sprintf(file_path, "htdocs%s", url);
    if (file_path[strlen(file_path)-1] == '/') {
        file_path[strlen(file_path)-1] = '\0';
    }

    // fprintf(stderr, "%s\n", file_path);

    int fname_valid = is_valid_fname(file_path);

    struct stat file_info;

    if (!fname_valid) {
        // invalid filename
        fprintf(stderr, "403 Forbidden: Invalid file name\n");
        forbidden();
        return 0;
    }

    if (stat(file_path, &file_info)) {
        fprintf(stderr, "404 Not Found: Stat failed\n");
        // Stat failed
        not_found();
        return 1;
    }

    if (!S_ISREG(file_info.st_mode)) {
        // Not a file
        forbidden();
        fprintf(stderr, "403 Forbidden: Not a regular file\n");
        return 0;
    }


    if (!(file_info.st_mode & S_IRUSR)) {
        // No read permissions
        forbidden();
        fprintf(stderr, "403 Forbidden: No read permissions\n");
        return 0;
    }

    FILE *f = fopen(file_path, "r");
    if (f == NULL) {
        // No file
        not_found();
        fprintf(stderr, "404 Not Found: Unable to open file\n");
        return 0;
    }

    if (if_modified_since != NULL) {
        struct tm *last_modified = gmtime(&file_info.st_mtime);

        time_t last = mktime(last_modified);
        time_t since = mktime(if_modified_since);

        double diff = difftime(last, since);
        if (diff <= 0) {
            fprintf(stderr, "304 Not Modified\n");
            not_modified();
            return 0;
        }
    }

    fprintf(stderr, "All looks good, serving up content in %s\n", file_path);

    char *file_contents = NULL;
    int contents_length = 0;
    char line[512];

    while (fgets(line, sizeof(line), f) != NULL) {
        if (file_contents != NULL) {
            char *new_contents = (char*) malloc(contents_length + strlen(line) + 1);
            strcpy(new_contents, file_contents);
            strcpy(new_contents + strlen(new_contents), line);
            contents_length += strlen(line);

            free(file_contents);
            file_contents = new_contents;
        } else {
            file_contents = (char*) malloc(strlen(line) + 1);
            strcpy(file_contents, line);
            contents_length += strlen(line);
        }
    }
    fclose(f);

    // fprintf(stderr, "File Contents:\n");

    // fprintf(stderr, "%s\n", file_contents);

    ok(file_contents);

    return 0;
}
Ejemplo n.º 13
0
gboolean li_request_validate_header(liConnection *con) {
	liRequest *req = &con->mainvr->request;
	liHttpHeader *hh;
	GList *l;

	if (con->info.is_ssl) {
		g_string_append_len(req->uri.scheme, CONST_STR_LEN("https"));
	} else {
		g_string_append_len(req->uri.scheme, CONST_STR_LEN("http"));
	}

	switch (req->http_version) {
	case LI_HTTP_VERSION_1_0:
		if (!li_http_header_is(req->headers, CONST_STR_LEN("connection"), CONST_STR_LEN("keep-alive")))
			con->info.keep_alive = FALSE;
		break;
	case LI_HTTP_VERSION_1_1:
		if (li_http_header_is(req->headers, CONST_STR_LEN("connection"), CONST_STR_LEN("close")))
			con->info.keep_alive = FALSE;
		break;
	case LI_HTTP_VERSION_UNSET:
		bad_request(con, 505); /* Version not Supported */
		return FALSE;
	}

	if (req->uri.raw->len == 0) {
		bad_request(con, 400); /* bad request */
		return FALSE;
	}

	/* get hostname */
	l = li_http_header_find_first(req->headers, CONST_STR_LEN("host"));
	if (NULL != l) {
		if (NULL != li_http_header_find_next(l, CONST_STR_LEN("host"))) {
			/* more than one "host" header */
			bad_request(con, 400); /* bad request */
			return FALSE;
		}

		hh = (liHttpHeader*) l->data;
		g_string_append_len(req->uri.authority, LI_HEADER_VALUE_LEN(hh));
		/* check header after we parsed the url, as it may override uri.authority */
	}

	/* Need hostname in HTTP/1.1 */
	if (req->uri.authority->len == 0 && req->http_version == LI_HTTP_VERSION_1_1) {
		bad_request(con, 400); /* bad request */
		return FALSE;
	}

	/* may override hostname */
	if (!request_parse_url(con->mainvr)) {
		bad_request(con, 400); /* bad request */
		return FALSE;
	}

	if (req->uri.host->len == 0 && req->uri.authority->len != 0) {
		if (!li_parse_hostname(&req->uri)) {
			bad_request(con, 400); /* bad request */
			return FALSE;
		}
	}

	/* remove trailing dots from hostname */
	{
		guint i = req->uri.host->len;
		while (i > 0 && req->uri.host->str[i-1] == '.') i--;
		g_string_truncate(req->uri.host, i);
	}

	/* content-length */
	hh = li_http_header_lookup(req->headers, CONST_STR_LEN("content-length"));
	if (hh) {
		const gchar *val = LI_HEADER_VALUE(hh);
		gint64 r;
		char *err;

		r = g_ascii_strtoll(val, &err, 10);
		if (*err != '\0') {
			_VR_DEBUG(con->srv, con->mainvr, "content-length is not a number: %s (Status: 400)", err);
			bad_request(con, 400); /* bad request */
			return FALSE;
		}

		/**
			* negative content-length is not supported
			* and is a bad request
			*/
		if (r < 0) {
			bad_request(con, 400); /* bad request */
			return FALSE;
		}

		/**
			* check if we had a over- or underrun in the string conversion
			*/
		if (r == G_MININT64 || r == G_MAXINT64) {
			if (errno == ERANGE) {
				bad_request(con, 413); /* Request Entity Too Large */
				return FALSE;
			}
		}

		con->mainvr->request.content_length = r;
	}

	/* Expect: 100-continue */
	l = li_http_header_find_first(req->headers, CONST_STR_LEN("expect"));
	if (l) {
		gboolean expect_100_cont = FALSE;

		for ( ; l ; l = li_http_header_find_next(l, CONST_STR_LEN("expect")) ) {
			hh = (liHttpHeader*) l->data;
			if (0 == g_ascii_strcasecmp( LI_HEADER_VALUE(hh), "100-continue" )) {
				expect_100_cont = TRUE;
			} else {
				/* we only support 100-continue */
				bad_request(con, 417); /* Expectation Failed */
				return FALSE;
			}
		}

		if (expect_100_cont && req->http_version == LI_HTTP_VERSION_1_0) {
			/* only HTTP/1.1 clients can send us this header */
			bad_request(con, 417); /* Expectation Failed */
			return FALSE;
		}
		con->expect_100_cont = expect_100_cont;
	}

	/* TODO: headers:
	 * - If-Modified-Since (different duplicate check)
	 * - If-None-Match (different duplicate check)
	 * - Range (duplicate check)
	 */

	switch(con->mainvr->request.http_method) {
	case LI_HTTP_METHOD_GET:
	case LI_HTTP_METHOD_HEAD:
		/* content-length is forbidden for those */
		if (con->mainvr->request.content_length > 0) {
			VR_ERROR(con->mainvr, "%s", "GET/HEAD with content-length -> 400");

			bad_request(con, 400); /* bad request */
			return FALSE;
		}
		con->mainvr->request.content_length = 0;
		break;
	case LI_HTTP_METHOD_POST:
		/* content-length is required for them */
		if (con->mainvr->request.content_length == -1) {
			/* content-length is missing */
			VR_ERROR(con->mainvr, "%s", "POST-request, but content-length missing -> 411");

			bad_request(con, 411); /* Length Required */
			return FALSE;
		}
		break;
	default:
		if (con->mainvr->request.content_length == -1)
			con->mainvr->request.content_length = 0;
		/* the may have a content-length */
		break;
	}

	return TRUE;
}
Ejemplo n.º 14
0
int parse_request(struct wen_request *request)
{
	char *head = NULL;
	struct stat sbuf;
	int remain_size;
	for(;;)
	{
		head = request->BUF[request->pos_last % MAX_REQUEST];
		remain_size = MIN(MAX_REQUEST - (request->pos_last - request->pos_first) - 1,MAX_REQUEST\
				- request->pos_last % MAX_REQUEST);
		
		int n = read(request->wen_fd,head,remain_size);

		if(n == 0){
			wen_free(request);
			return 0;
		}

		else if(n < 0)
		{
			wen_free(request);
			return 0;
		}

		request->pos_last += n;
		
		int res_line = parse_http_request_line(request);

		if(res_line == AGAIN)
		{
			continue;
		}
		else if(res_line != OK)
		{
			wen_free(request);
		}

		int res_body = parse_http_request_body(request);

		if(res_body == AGAIN)
			continue;
		else if(res_body != OK)
		{
			wen_free(request);
		}
		
		/*handle http request*/
		char  filename[1024];
		parse_http_uri(request,filename);
		if(stat(filename,&sbuf) < 0){
			bad_request(request);
			return 0;
		}

		http_response(request,filename);

                wen_free(request);
		break;
	}

	return 1;
}	
Ejemplo n.º 15
0
void client_request(int clientsd, char * timec, char * clientip) 
{
	FILE * requestfile;
	FILE * logfile;
	char read_output[BUFFER_SIZE] = {0};
	char method[80];
	char dir[80];
	char http[80];
	char line[100];
	char finaldir[BUFFER_SIZE] = {0};
	struct stat buf;
	int httpint;
	int readint;
	int totalsize;
	char totalsizec[20];
	int totalwrite;
	char totalwritec[20];
	char okstr[80];

	logfile = fopen(logdir, "a");

	readint = read_request(clientsd, read_output);
	
	if (readint == -1)
	{
		internal_server_error(clientsd, timec);
		return;
	}

	getlinec(read_output, line);
	httpint = is_http_get(line, method, dir, http);
	
	if (httpint == -1)
	{
		bad_request(clientsd, timec);
		write_log(timec, line, "400 Bad Request", logfile, clientip);
		return;
	}
	
	getdir(docdir, dir, finaldir);

	requestfile = fopen(finaldir, "r");
	
	if (requestfile == NULL)
	{
		file_not_found(clientsd, timec);
		write_log(timec, line, "404 Not Found", logfile, clientip);
		return;
	}

	if (errno = EACCES)
	{
		forbidden(clientsd, timec);
		write_log(timec, line, "403 Forbidden", logfile, clientip);
		return;
	}
	/*
	 * Gets file size from buffer file to be used as total write size
	 * for ok response
	 *
	 * Code adapted from
	 * http://stackoverflow.com/a/238644
	 */
	fstat(requestfile, &buf);
	totalsize = buf.st_size;
	/*
	 * Converts int to char
	 *
	 * Code adapted from
	 * http://stackoverflow.com/a/1114752
	 */
	sprintf(totalsizec, "%d", totalsize);
	totalwrite = ok(clientsd, timec, requestfile, totalsizec);
	sprintf(totalwritec, "%d", totalwrite);
	strncat(okstr, "200 OK ", sizeof(okstr));	
	strncat(okstr, totalwritec, sizeof(okstr));
	strncat(okstr, "/", sizeof(okstr));
	strncat(okstr, totalsizec, sizeof(okstr));
	write_log(timec, line, okstr, logfile, clientip);
	return;

}
Ejemplo n.º 16
0
void execute_cgi(int client, const char *path, const char *method, const char *query_string)  
{  
    char buf[1024];  
    int cgi_output[2];  
    int cgi_input[2];  
    pid_t pid;  
    int status;  
    int i;  
    char c;  
    int numchars = 1;  
    int content_length = -1;  
  
    buf[0] = 'A'; buf[1] = '\0';  
    if (strcasecmp(method, "GET") == 0)  
        /*把所有的 HTTP header 读取并丢弃*/  
        while ((numchars > 0) && strcmp("\n", buf))  /* read & discard headers */  
            numchars = get_line(client, buf, sizeof(buf));  
    else    /* POST */  
    {  
        /* 对 POST 的 HTTP 请求中找出 content_length */  
        numchars = get_line(client, buf, sizeof(buf));  
        while ((numchars > 0) && strcmp("\n", buf))  
        {  
            /*利用 \0 进行分隔 */  
            buf[15] = '\0';  
            /* HTTP 请求的特点*/  
            if (strcasecmp(buf, "Content-Length:") == 0)  
                content_length = atoi(&(buf[16]));  
            numchars = get_line(client, buf, sizeof(buf));  
        }  
        /*没有找到 content_length */  
        if (content_length == -1) {  
            /*错误请求*/  
            bad_request(client);  
            return;  
        }  
    }  
  
    /* 正确,HTTP 状态码 200 */  
    sprintf(buf, "HTTP/1.0 200 OK\r\n");  
    send(client, buf, strlen(buf), 0);  
  
    /* 建立管道*/  
    if (pipe(cgi_output) < 0) {  
        /*错误处理*/  
        cannot_execute(client);  
        return;  
    }  
    /*建立管道*/  
    if (pipe(cgi_input) < 0) {  
        /*错误处理*/  
        cannot_execute(client);  
        return;  
    }  
  
    if ((pid = fork()) < 0 ) {  
        /*错误处理*/  
        cannot_execute(client);  
        return;  
    }  
    if (pid == 0)  /* child: CGI script */  
    {  
        char meth_env[255];  
        char query_env[255];  
        char length_env[255];  
  
        /* 把 STDOUT 重定向到 cgi_output 的写入端 */  
        dup2(cgi_output[1], 1);  
        /* 把 STDIN 重定向到 cgi_input 的读取端 */  
        dup2(cgi_input[0], 0);  
        /* 关闭 cgi_input 的写入端 和 cgi_output 的读取端 */  
        close(cgi_output[0]);  
        close(cgi_input[1]);  
        /*设置 request_method 的环境变量*/  
        sprintf(meth_env, "REQUEST_METHOD=%s", method);  
        putenv(meth_env);  
        if (strcasecmp(method, "GET") == 0) {  
            /*设置 query_string 的环境变量*/  
            sprintf(query_env, "QUERY_STRING=%s", query_string);  
            putenv(query_env);  
        }  
        else {   /* POST */  
            /*设置 content_length 的环境变量*/  
            sprintf(length_env, "CONTENT_LENGTH=%d", content_length);  
            putenv(length_env);  
        }  
        /*用 execl 运行 cgi 程序*/  
        execl(path, path, NULL);  
        exit(0);  
    } else {    /* parent */  
        /* 关闭 cgi_input 的读取端 和 cgi_output 的写入端 */  
        close(cgi_output[1]);  
        close(cgi_input[0]);  
        if (strcasecmp(method, "POST") == 0)  
            /*接收 POST 过来的数据*/  
            for (i = 0; i < content_length; i++) {  
                recv(client, &c, 1, 0);  
                /*把 POST 数据写入 cgi_input,现在重定向到 STDIN */  
                write(cgi_input[1], &c, 1);  
            }  
        /*读取 cgi_output 的管道输出到客户端,该管道输入是 STDOUT */  
        while (read(cgi_output[0], &c, 1) > 0)  
            send(client, &c, 1, 0);  
  
        /*关闭管道*/  
        close(cgi_output[0]);  
        close(cgi_input[1]);  
        /*等待子进程*/  
        waitpid(pid, &status, 0);  
    }  
}  
Ejemplo n.º 17
0
int
main(int argc, char *argv[])
{
	
	int client_sock = -1;
	int client_name_len = sizeof (client_name);
	int request=0;
	
	struct nunetwork_headerstruct *header_buf;
	header_buf = (struct nunetwork_headerstruct*)malloc( sizeof(*header_buf) );
	/********************
         * Don't forget to make pointer to variable cast (*pointer)
         * When using sizeof(). Otherwise it may cost you a week of
	 * debug time.
         *******************/
	

	if (geteuid()) {
		printf("Netustad must be run as root.\n");
		exit(1);
	}
	
	conffile	= (char *)strdup(default_conf_file);
	
	
	/*setlocale (LC_ALL, "");*/
	bindtextdomain (PACKAGE, PACKAGE_LOCALE_DIR);
	textdomain ( PACKAGE );
	

	/*******************/
	/* Check Arguments */
	/*******************/
	if (argc==2) {	
			
			if (strcmp(argv[1], "-h") == 0 ||
				strcmp(argv[1], "--help") == 0) {
				printf( gettext("\nnetUstad: Network Ustadi (Network Master)\n"));
				printf( gettext("Copyright (C) 2004   by Ozkan KIRIK\n"));
				printf( gettext("Usage: netustad [options]\n"));
				printf( gettext("\n"));
				printf( "%s:\n", gettext("Options"));
				printf( gettext("\t-h\tShow this help screen\n"));
				printf( gettext("\t-v\tShow version\n"));
				printf
					(gettext("\t-c\tUse following parameter as configuration file"));
				printf("\n");
				exit(0);
			} else if (strcmp(argv[1], "-v") == 0 ||
				   strcmp(argv[1], "--version") == 0) {
				printf(gettext("\nnetUstad: Network Ustadi (Network Master)\n"));
				printf(gettext("Copyright (C) 2004  by Ozkan KIRIK\n\n"));
				printf(gettext("Version: %s\n\n"), NUVERSION);
				exit(0);
			}
				
	} else if (argc == 3 && strcmp(argv[1], "-c") == 0) {
			conffile = strdup(argv[2]);

	}  else if (argc!=1) {
			if (strcmp(argv[1], "-c") == 0) {
				printf (gettext("\nnetUstad: Invalid Number Of Arguments\n\n"));
			} else {
				printf(gettext("\nnetUstad: Invalid Argument\n\n"));
			}
			exit(1);

	}


	/**********************/
	/* Start Main Program */
	/**********************/

	readconfig(conffile);
	if (setlocale (LC_ALL, (const char*) lc_all) == NULL) {
		log_msg(mainlogfile, gettext("setlocale failed\n"), 1);
		printf(gettext("setlocale failed\n"));
	}
	bindtextdomain (PACKAGE, PACKAGE_LOCALE_DIR);
	textdomain ( PACKAGE );
	nameoftty = ttyname(0);
	daemonize();

	#ifndef WITHOUT_SSL
        	ssl = nunetwork_init_ssl( nunetwork_init_ctx( cert_file, key_file) );
	#endif

	server_sock = startup(&port);	/* Open Socket & Listen */

	log_msg(mainlogfile, "<<<<<<<<<<<<<<<<<<<<<<>>>>>>>>>>>>>>>>>>>>>>\n", 0);
	snprintf(log_msg_text, sizeof(log_msg_text)-1, "netUstad-%s\n", NUVERSION);
        log_msg(mainlogfile, log_msg_text, 0);
	snprintf(log_msg_text, sizeof (log_msg_text)-1, "%s",
		 gettext("netUstad is started\n"));
	log_msg(mainlogfile, log_msg_text, 1);
	snprintf(log_msg_text, sizeof (log_msg_text)-1, gettext("\nListening port %d\n"), port);
	log_msg(mainlogfile, log_msg_text, 0);
	log_msg(mainlogfile, gettext("Ready for requests...\n\n"), 0);
	snprintf(log_msg_text, sizeof(log_msg_text)-1, "netUstad-%s\n", NUVERSION);
	log_msg(nameoftty, log_msg_text, 0);
	snprintf(log_msg_text, sizeof (log_msg_text)-1,
		 gettext("\nnetUstad is started\nListening port %d\n"), port);
	log_msg(nameoftty, log_msg_text, 0);

	while (1) {
		client_sock = accept(server_sock,
				     (struct sockaddr *) &client_name,
				     (socklen_t *)&client_name_len);

		if (client_sock == -1)
			continue;
	
		 #ifndef WITHOUT_SSL
		        SSL_set_fd(ssl, client_sock);
		        sslerror = SSL_accept(ssl);
		
		        if ( sslerror <= 0 ) {
		                sslerror= SSL_get_error(ssl, sslerror);
		                ERR_error_string(sslerror, log_msg_text);
		
		                log_msg(mainlogfile, log_msg_text, 1);
				log_msg(mainlogfile, "\n",0);
				SSL_shutdown(ssl);
				SSL_free(ssl);
				close(client_sock);
				ssl = nunetwork_init_ssl(ctx);
				continue;
		        }
			
			request =  nunetwork_getheaders(ssl, header_buf, nu_acceptedheaders); 
			if (request > 0) 
				accept_request(ssl, header_buf);
			else if (request==-2 || request==0)
				bad_request(ssl);
			nunetwork_close(ssl);
		 #else
			request = nunetwork_getheaders(client_sock, header_buf, nu_acceptedheaders);
		        if (request > 0)
				accept_request(client_sock, header_buf);
			else if (request==-2 || request==0 )
				bad_request(ssl);
		 	nunetwork_close(client_sock);
		 #endif
		
	
	
	}
	#ifndef WITHOUT_SSL
		SSL_shutdown(ssl);
		SSL_free(ssl);
		SSL_CTX_free(ctx);
	#else
		close(server_sock);
	#endif


	return (0);
}
Ejemplo n.º 18
0
Archivo: cgi.c Proyecto: NUOG/ejudge
static int
parse_multipart(char const *charset)
{
  static char const mp2[] = "multipart/form-data; boundary=";
  static char const s3[] = "content-disposition:";
  static char const s4[] = "form-data;";
  static char const s5[] = "name=\"";
  static char const s6[] = "content-type:";

  char const *boundary;
  char *ct, *cl;
  int   content_length, n;
  char lbuf[1024];
  int  llen;
  char *p, *q;
  int  linestart;
  int  boundary_len;
  int  c;

  ct = getenv("CONTENT_TYPE");
  if (!ct) return -1;
  if (strncmp(ct, mp2, sizeof(mp2) - 1)) {
    err("parse_multipart: cannot parse CONTENT_TYPE");
    bad_request(charset);
    exit(0);
  }
  boundary = ct + sizeof(mp2) - 1;
  boundary_len = strlen(boundary);

  cl = getenv("CONTENT_LENGTH");
  if (!cl || sscanf(cl, "%d%n", &content_length, &n) != 1 || cl[n]) {
    //err("parse_multipart: cannot parse CONTENT_LENGTH");
    //bad_request(charset);
    //exit(0);
    return 0;
  }
  if (content_length > MAX_CONTENT_LENGTH) {
    request_too_large(charset);
    exit(0);
  }

  name_u = 0;
  value_u = 0;
  fgets(lbuf, sizeof(lbuf), stdin);

  llen = strlen(lbuf);
  if (llen == sizeof(lbuf) - 1 && lbuf[llen - 1] != '\n') {
    err("parse_multipart: boundary string too long");
    bad_request(charset);
    exit(0);
  }
  lbuf[--llen] = 0;
  if (lbuf[llen - 1] == '\r') lbuf[--llen] = 0;
  if (lbuf[0] != '-' || lbuf[1] != '-' || strcmp(boundary, lbuf + 2)) {
    err("got: %s(%zu)", lbuf, strlen(lbuf));
    bad_request(charset);
    exit(0);
  }
  while (1) {
    /* read and parse header lines */
    while (1) {
      fgets(lbuf, sizeof(lbuf), stdin);
      //fprintf(stderr, ">>%s<\n", lbuf);
      llen = strlen(lbuf);
      if (llen == sizeof(lbuf) - 1 && lbuf[llen - 1] != '\n') {
        err("parse_multipart: header string too long");
        bad_request(charset);
        exit(0);
      }
      lbuf[--llen] = 0;
      if (lbuf[llen - 1] == '\r') lbuf[--llen] = 0;
      if (!lbuf[0]) break;
      if (!strncasecmp(lbuf, s3, sizeof(s3) - 1)) {
        /* content-disposition header */
        p = lbuf + sizeof(s3) - 1;
        while (*p == ' ' || *p == '\t') p++;
        if (!strncasecmp(p, s4, sizeof(s4) - 1)) {
          p += sizeof(s4) - 1;
          while (*p == ' ' || *p == '\t') p++;
          if (!strncasecmp(p, s5, sizeof(s5) - 1)) {
            p += sizeof(s5) - 1;
            q = p;
            while (*q != '\"' && *q != 0) q++;
            if (!*q) {
              err("unexpected EOLN: %s", lbuf);
              bad_request(charset);
              exit(0);
            }
            /* get parameter name */
            if (q - p + 1 > name_a) {
              name_a = ((q - p + 1) + 3) & ~3;
              name_buf = xrealloc(name_buf, name_a);
            }
            name_u = q - p;
            memcpy(name_buf, p, name_u);
            name_buf[name_u] = 0;
          } else {
            err("name= expected: %s\n", lbuf);
            bad_request(charset);
            exit(0);
          }
        } else {
          err("unknown content disposition: %s", lbuf);
          bad_request(charset);
          exit(0);
        }
      } else if (!strncasecmp(s6, lbuf, sizeof(s6) - 1)) {
        //err("ignored header: %s", lbuf);
      } else {
        err("unknown header: <%s>", lbuf);
        bad_request(charset);
        exit(0);
      }
    }

    /* read and parse data stream */
    linestart = 0; value_u = 0;
    if (!value_a) {
      value_a = 128;
      value_buf = xmalloc(value_a);
    }
    while (1) {
      c = getchar();
      if (c == EOF) {
        err("unexpected EOF");
        bad_request(charset);
        exit(0);
      }
      if (value_u >= value_a) {
        value_a *= 2;
        value_buf = xrealloc(value_buf, value_a);
      }
      value_buf[value_u++] = c;
      if (value_u - linestart - 2 == boundary_len
          && value_buf[linestart] == '-'
          && value_buf[linestart + 1] == '-'
          && !strncmp(value_buf + linestart + 2, boundary, boundary_len)) {
        /* data ended */
        value_u = linestart;
        if (value_u > 0 && value_buf[value_u - 1] == '\n') value_u--;
        if (value_u > 0 && value_buf[value_u - 1] == '\r') value_u--;
        value_buf[value_u] = 0;
        break;
      }
      if (c == '\n') {
        linestart = value_u;
      }
    }

    /* add variable to list */
    add_to_param_list(name_buf, value_buf, value_u);
    /* skip whitespaces */
    c = getchar();
    if (c == '-') {
      c = getchar();
      if (c == '-') break;
      err("oops: only one '-' after boundary");
      bad_request(charset);
      exit(0);
    } else {
      ungetc(c, stdin);
    }
    while ((c = getchar()) == ' ' || c == '\t' || c == '\n' || c == '\r');
    ungetc(c, stdin);
  }

#if 0
  {
    int i;

    fprintf(stderr, "total: %d\n", param_u);
    for (i = 0; i < param_u; i++) {
      fprintf(stderr, "%s = '%s'\n", params[i].name, params[i].value);
    }
  }
#endif

  return 0;
}
Ejemplo n.º 19
0
void execute_cgi(int client, const char *path,
		const char *method, const char *query_string)
{
	char buf[1024];
	int cgi_output[2];
	int cgi_input[2];
	pid_t pid;
	int status;
	int i;
	char c;
	int numchars = 1;
	int content_length = -1;

	buf[0] = 'A'; buf[1] = '\0';
	if (strcasecmp(method, "GET") == 0)
		while ((numchars > 0) && strcmp("\n", buf))  /* read & discard headers */
			numchars = get_line(client, buf, sizeof(buf));
	else    /* POST */
	{
		numchars = get_line(client, buf, sizeof(buf));
		while ((numchars > 0) && strcmp("\n", buf))
		{
			buf[15] = '\0';
			if (strcasecmp(buf, "Content-Length:") == 0)
				content_length = atoi(&(buf[16]));
			numchars = get_line(client, buf, sizeof(buf));
		}
		if (content_length == -1) {
			bad_request(client);
			return;
		}
	}

	sprintf(buf, "HTTP/1.0 200 OK\r\n");
	send(client, buf, strlen(buf), 0);

	if (pipe(cgi_output) < 0) {
		cannot_execute(client);
		return;
	}
	if (pipe(cgi_input) < 0) {
		cannot_execute(client);
		return;
	}

	if ( (pid = fork()) < 0 ) {
		cannot_execute(client);
		return;
	}
	if (pid == 0)  /* child: CGI script */
	{
		char meth_env[255];
		char query_env[255];
		char length_env[255];

		dup2(cgi_output[1], 1);
		dup2(cgi_input[0], 0);
		close(cgi_output[0]);
		close(cgi_input[1]);
		sprintf(meth_env, "REQUEST_METHOD=%s", method);
		putenv(meth_env);
		if (strcasecmp(method, "GET") == 0) {
			sprintf(query_env, "QUERY_STRING=%s", query_string);
			putenv(query_env);
		}
		else {   /* POST */
			sprintf(length_env, "CONTENT_LENGTH=%d", content_length);
			putenv(length_env);
		}
		execl(path, path, NULL);
		exit(0);
	} else {    /* parent */
		close(cgi_output[1]);
		close(cgi_input[0]);
		if (strcasecmp(method, "POST") == 0)
			for (i = 0; i < content_length; i++) {
				recv(client, &c, 1, 0);
				write(cgi_input[1], &c, 1);
			}
		while (read(cgi_output[0], &c, 1) > 0)
			send(client, &c, 1, 0);

		close(cgi_output[0]);
		close(cgi_input[1]);
		waitpid(pid, &status, 0);
	}
}
Ejemplo n.º 20
0
Archivo: erq.c Proyecto: amotzkau/ldmud
/*-------------------------------------------------------------------------*/
void
erq_cmd (void)

/* There is data ready from the driver - read and execute it when complete.
 * The function maintains a static buffer for the data read - incomplete
 * messages are buffered until they are complete.
 */

{
    static char buf[ERQ_MAX_SEND];
    static int pos = 0;
      /* Position in buf[]. If it extends beyond the end of buf,
       * it is because the message is too long and the function
       * is in the process of skipping the extraneous characters.
       */

    int len, mesg_len;
    char request;

    /* Clear the buffer so that errors can be detected more easily */
    memset(buf, 0, sizeof(buf));

    /* Read the message header */
    if (pos < 9)
    {
        len = read(0, buf+pos, 9-pos);
        if (len <= 0)
        {
            perror("[xerq] read");
            die();
        }
        XPRINTF((stderr, "%s Read %d of the missing %d header bytes.\n"
                       , time_stamp(), len, 9-pos));
        pos += len;
        if (pos < 9)
            return;
    }

    mesg_len = read_32(buf);
    if (mesg_len > sizeof(buf))
    {
        /* This doesn't happen in a functioning system */
        fprintf(stderr
               , "%s Received too long packet: %d bytes.\n"
               , time_stamp(), mesg_len);
        die();
    }

    /* Get the rest of the message */

    if (pos < mesg_len)
    {
        len = read(0, buf+pos, mesg_len-pos);
        if (len <= 0)
        {
            perror("read");
            die();
        }
        XPRINTF((stderr, "%s Read %d of the missing %d message bytes.\n"
                       , time_stamp(), len, mesg_len-pos));
        pos += len;
        if (pos < mesg_len)
            return;
    }

    XPRINTF((stderr, "%s Message complete.\n", time_stamp()));
    pos = 0; /* Message complete */

    /* Branch on the request */
    request = buf[8];
    if (request <= ERQ_REQUEST_MAX)
    {
#if ERQ_DEBUG > 0
        char *mesg, *mesgs[]={
            "rlookup","execute","fork","auth","spawn","send","kill",
            "open_udp","open_tcp","listen","accept","lookup", "rlookupv6"};
        mesg=mesgs[(int)request];
        fprintf(stderr, "%s command: %s\n", time_stamp(), mesg);
#endif
        (*erq_table[(int)request])(buf, mesg_len);
    }
    else
        bad_request(buf);
} /* erq_cmd() */
Ejemplo n.º 21
0
// 配置环境变量,创建子进程,执行cgi程序
void execute_cgi(int client, const char *path,
                 const char *method, const char *query_string)
{
 char buf[1024];
 int cgi_output[2];
 int cgi_input[2];
 pid_t pid;
 int status;
 int i;
 char c;
 int numchars = 1;
 int content_length = -1;

 buf[0] = 'A'; buf[1] = '\0';
 if (strcasecmp(method, "GET") == 0) // GET
  while ((numchars > 0) && strcmp("\n", buf))  /* read & discard headers */
   numchars = get_line(client, buf, sizeof(buf)); // 只处理了请求首行,忽略后面的请求头
 else    /* POST */
 {
  numchars = get_line(client, buf, sizeof(buf)); // 读取请求头中的header属性
  while ((numchars > 0) && strcmp("\n", buf))
  {
   buf[15] = '\0';
   if (strcasecmp(buf, "Content-Length:") == 0) // Content-Length:后面的数字切出来
    content_length = atoi(&(buf[16]));
   numchars = get_line(client, buf, sizeof(buf));
  }
  if (content_length == -1) { // Content-Length获取失败,该请求有问题
   bad_request(client); // 400
   return;
  }
 }

 sprintf(buf, "HTTP/1.0 200 OK\r\n"); // 响应首行
 send(client, buf, strlen(buf), 0);

 if (pipe(cgi_output) < 0) { // 打开管道
  cannot_execute(client);
  return;
 }
 if (pipe(cgi_input) < 0) { // 打开管道
  cannot_execute(client);
  return;
 }

 if ( (pid = fork()) < 0 ) { // 创建子进程
  cannot_execute(client);
  return;
 }
 if (pid == 0)  /* child: CGI script */
 { // 子进程开始执行
  char meth_env[255];
  char query_env[255];
  char length_env[255];

  dup2(cgi_output[1], 1); // 复制到标准输出
  dup2(cgi_input[0], 0); // 复制到标准输入
  close(cgi_output[0]);
  close(cgi_input[1]); // 关闭不需要的描述符
  
  // 添加几个环境变量
  sprintf(meth_env, "REQUEST_METHOD=%s", method);
  putenv(meth_env);
  if (strcasecmp(method, "GET") == 0) {
   sprintf(query_env, "QUERY_STRING=%s", query_string);
   putenv(query_env);
  }
  else {   /* POST */
   sprintf(length_env, "CONTENT_LENGTH=%d", content_length);
   putenv(length_env);
  }

  // 准备工作完毕,开始执行cgi程序
  execl(path, path, NULL);
  exit(0);
 } else {    /* parent */ // 父进程代码
  close(cgi_output[1]);
  close(cgi_input[0]); // 关闭不需要的描述符

  if (strcasecmp(method, "POST") == 0)
   for (i = 0; i < content_length; i++) {
    recv(client, &c, 1, 0);
    write(cgi_input[1], &c, 1); // 读取剩下的请求头写给子进程的cgi程序
   }
  while (read(cgi_output[0], &c, 1) > 0)
   send(client, &c, 1, 0); // 读取cgi程序的输出发送给客户端

  close(cgi_output[0]);
  close(cgi_input[1]); // 使用完毕,关闭描述符
  waitpid(pid, &status, 0); // 等待子进程退出
 }
}