示例#1
0
文件: usb.c 项目: brucetsao/ukbdc
static inline void handle_setup_packet()
{
	bool all_ok = false;
	struct setup_packet s;
	USB_OUT_read_buffer(&s, 8);
	/* acknowledge setup *after* reading, because it clears the bank */
	USB_ack_SETUP();
	/* process all Standard Device Requests */
	if        (request_type(&s, TYPE | RECIPIENT, STANDARD | DEVICE)) {
		all_ok = process_standard_device_requests(&s);
	} else if (request_type(&s, TYPE | RECIPIENT, STANDARD | INTERFACE)) {
		all_ok = process_standard_interface_requests(&s);
	} else if (request_type(&s, TYPE | RECIPIENT, STANDARD | ENDPOINT)) {
		all_ok = process_standard_endpoint_requests(&s);
	} else if (request_type(&s, TYPE | RECIPIENT, CLASS    | INTERFACE)) {
		all_ok = process_class_interface_requests(&s);
	}
	if (!all_ok)
		USB_stall_endpoint();
}
示例#2
0
文件: usb.c 项目: brucetsao/ukbdc
/* static inline just for size optimization */
static inline bool process_class_interface_requests(struct setup_packet *s)
{
	bool found = false;
	for (uint8_t i = 0; i < NUM_INTERFACE_REQUEST_HANDLERS; ++i) {
		if (get_pgm_struct_field(&iface_req_handlers[i], iface_num) ==
				(s->wIndex & 0xFF)) {
			interface_request_handler_fun handler = (void*)(uint16_t)
				get_pgm_struct_field(&iface_req_handlers[i], f);
			found = (*handler)(s);
			break;
		}
	}
	if (!found)
		return false;
	if (request_type(s, DIRECTION, DEVICE_TO_HOST))
		USB_control_read_complete_status_stage();
	else
		USB_control_write_complete_status_stage();
	return true;
}
示例#3
0
int process_logline(request * req)
{
	char *stop, *stop2;
	static char *SIMPLE_HTTP_VERSION = "HTTP/0.9";
	
	req->logline = req->header_line;
	req->method = request_type(req);
	if (req->method == M_INVALID || req->method == M_SHORT) {
#ifdef BOA_TIME_LOG
		log_error_time();
		fprintf(stderr, "malformed request: \"%s\"\n", req->logline);
#endif
		syslog(LOG_ERR, "malformed request: \"%s\" from %s\n", req->logline, req->remote_ip_addr);
		send_r_bad_request(req);
		return 0;
	}
	
	/* Guaranteed to find ' ' since we matched a method above */
	stop = req->logline + 3;
	if (*stop != ' ')
		++stop;
	
	/* scan to start of non-whitespace */
	while (*(++stop) == ' ');

	stop2 = stop;

	/* scan to end of non-whitespace */
	while (*stop2 != '\0' && *stop2 != ' ')
		++stop2;

	if (stop2 - stop > MAX_HEADER_LENGTH) {
#ifdef BOA_TIME_LOG
		log_error_time();
		fprintf(stderr, "URI too long %d: \"%s\"\n", MAX_HEADER_LENGTH,
				req->logline);
#endif
		syslog(LOG_ERR, "URI too long %d: \"%s\" from %s\n", MAX_HEADER_LENGTH,
				req->logline, req->remote_ip_addr);
		send_r_bad_request(req);
		return 0;
	}
	memcpy(req->request_uri, stop, stop2 - stop);
	req->request_uri[stop2 - stop] = '\0';

	if (*stop2 == ' ') {		
		/* if found, we should get an HTTP/x.x */
		int p1, p2;

		if (sscanf(++stop2, "HTTP/%d.%d", &p1, &p2) == 2 && p1 >= 1) {
			req->http_version = stop2;
			req->simple = 0;
		} else {
#ifdef BOA_TIME_LOG
			log_error_time();
			fprintf(stderr, "bogus HTTP version: \"%s\"\n", stop2);
#endif
			syslog(LOG_ERR, "bogus HTTP version: \"%s\" from %s\n", stop2, req->remote_ip_addr);
			send_r_bad_request(req);
			return 0;
		}
		
	} else {
		req->http_version = SIMPLE_HTTP_VERSION;
		req->simple = 1;
	}
	
	if (req->method == M_HEAD && req->simple) {
		syslog(LOG_ERR, "Simple HEAD request not allowed from %s\n", req->remote_ip_addr);
		send_r_bad_request(req);
		return 0;
	}
	create_env(req);    /* create cgi env[], we don't know if url is cgi */
	return 1;
}
示例#4
0
int read_header(request * req)
{
	int bytes, buf_bytes_left;
	char *check, *buffer;

	if (req->pipeline_start){
		buffer = req->client_stream;
		bytes = req->client_stream_pos = req->pipeline_start;
		req->pipeline_start = 0;
	} else { /* first from free_request */
		buffer = req->client_stream + req->client_stream_pos;
		buf_bytes_left = CLIENT_STREAM_SIZE - req->client_stream_pos;
		if (buf_bytes_left < 0) {
#ifdef BOA_TIME_LOG
			log_error_time();
			fputs("buffer overrun - read.c, read_header - closing\n", stderr);
#endif
			return 0;
		}
		/*MN stuff to support ssl*/
#ifdef SERVER_SSL
		if(req->ssl == NULL){
#endif /*SERVER_SSL*/
			bytes = read(req->fd, buffer, buf_bytes_left);
#ifdef SERVER_SSL
		}
		else{
			char tmp;
			bytes = SSL_read(req->ssl, buffer, buf_bytes_left);
#if 0
			printf("SSL_read 1\n");
			if(bytes > 0){
				tmp = buffer[bytes-1];
				buffer[bytes-1] = '\0';
				printf("buffer-\n %s\n----------\n", buffer);
				buffer[bytes-1] = tmp;
			}
#endif /*0*/
		}
#endif /*SERVER_SSL*/

		if (bytes == -1) {
			if (errno == EINTR)
				return 1;
			if (errno == EAGAIN || errno == EWOULDBLOCK)	/* request blocked */
				return -1;
			else if (errno == EBADF || errno == EPIPE) {
				SQUASH_KA(req);		/* force close fd */
				return 0;
			} else {
#if 0
				boa_perror(req, "header read");
#endif
				return 0;
			}
		} else if (bytes == 0)
			return 0;
		req->client_stream_pos += bytes;
	}

	check = buffer;

	while (check < (buffer + bytes)) {
		switch (req->status) {
		case READ_HEADER:
			if (*check == '\r') {
				req->status = ONE_CR;
				req->header_end = check;
			} else if (*check == '\n') {
				req->status = ONE_LF;
				req->header_end = check;
			}
			break;

		case ONE_CR:
			if (*check == '\n')
				req->status = ONE_LF;
			else
				req->status = READ_HEADER;
			break;

		case ONE_LF:			/* if here, we've found the end (for sure) of a header */
			if (*check == '\r')	/* could be end o headers */
				req->status = TWO_CR;
			else if (*check == '\n')
				req->status = BODY_READ;
			else
				req->status = READ_HEADER;
			break;

		case TWO_CR:
			if (*check == '\n')
				req->status = BODY_READ;
			else
				req->status = READ_HEADER;
			break;

		default:
			break;
		}

		++check;

		if (req->status == ONE_LF) {
			*req->header_end = '\0';
			/* terminate string that begins at req->header_line */
			/* (or at req->data_mem, if we've never been here before */

			/* the following logic still needs work, esp. after req->simple */
			if (req->logline)
				process_option_line(req);
			else {
				if (process_logline(req) == 0)
					return 0;
				if (req->simple)
					return process_header_end(req);
			}
			req->header_line = check; /* start of unprocessed data */
		} else if (req->status == BODY_READ) {
			int retval = process_header_end(req);
			/* process_header_end inits non-POST cgi's */
			
			req->pipeline_start = (check - req->client_stream);

			if (retval && req->method == M_POST) {

				/* rest of non-header data is contained in
				   the area following check

				   check now points to data 
				 */

				if (req->content_length)
					req->filesize = atoi(req->content_length);
				else {
#ifdef BOA_TIME_LOG
					log_error_time();
					fprintf(stderr, "Unknown Content-Length POST\n");
#endif
				}
				
				/* buffer + bytes is 1 past the end of the data */
				req->filepos = (buffer + bytes) - check;

				/* copy the remainder into req->buffer, otherwise
				 * we don't have a full BUFFER_SIZE to play with,
				 * and buffer overruns occur */
				memcpy(req->buffer, check, req->filepos);
				req->header_line = req->buffer;
				req->header_end = req->buffer + req->filepos;				

				if (req->filepos >= req->filesize)
					req->cgi_status = CGI_CLOSE;	/* close after write */
			}
			return retval;		/* 0 - close it done, 1 - keep on ready */
		}
	}

	/* check for bogus requests */
	if (req->status == READ_HEADER && request_type(req) == M_INVALID) {
		syslog(LOG_ERR, "malformed request: \"%s\"\n", req->logline);
		send_r_bad_request(req);
		return 0;
	}

	/* only reached if request is split across more than one packet */
	return 1;
}
示例#5
0
void webhit(struct hitArgs *args)
{
	int j;
	http_verb type;
	long i, body_size = 0, request_size = 0, body_start, headers_end;
    char tmp_buf[READ_BUF_LEN+1];
	char *body;
    struct http_header content_length;
    args->buffer = new_string(READ_BUF_LEN);
    
    // we need to read the HTTP headers first...
    // so loop until we receive "\r\n\r\n"
    while (get_body_start(string_chars(args->buffer)) < 0
           && args->buffer->used_bytes <= MAX_INCOMING_REQUEST)
    {
        memset(tmp_buf, 0, READ_BUF_LEN+1);
        request_size += read(args->socketfd, tmp_buf, READ_BUF_LEN);
        string_add(args->buffer, tmp_buf);
        if (tmp_buf[0]==0) break;
    }
    
    if (request_size == 0)
    {
        finish_hit(args, 3);
        return;
    }
    
    content_length = get_header("Content-Length", string_chars(args->buffer));
    args->content_length = atoi(content_length.value);
    body_start = get_body_start(string_chars(args->buffer));
    headers_end = body_start-4;
    
    if (headers_end > 0)
    {
        args->headers = mallocx((int)headers_end+1);
        strncpy(args->headers, string_chars(args->buffer), headers_end);
        args->headers[headers_end]=0;
    }
    else
    {
        args->headers = mallocx(1);
        args->headers[0] = 0;
    }
    
    if (body_start >= 0)
    {
        body_size = request_size - body_start;
    }
    
    // safari seems to send the headers, and then the body slightly later
    while (body_size < args->content_length
           && args->buffer->used_bytes <= MAX_INCOMING_REQUEST)
    {
        memset(tmp_buf, 0, READ_BUF_LEN+1);
        i = read(args->socketfd, tmp_buf, READ_BUF_LEN);
        if (i>0)
        {
            request_size += i;
            string_add(args->buffer, tmp_buf);
            body_size = request_size - body_start;
        }
        else
        {
            // stop looping if we cannot read any more bytes
            break;
        }
    }
    
    if (request_size <= 0)
	{
		// cannot read request, so we'll stop
		forbidden_403(args, "failed to read http request");
        finish_hit(args, 3);
        return;
	}
    
    args->logger_function(LOG, "request", string_chars(args->buffer), args->hit);
    
	if (type = request_type(string_chars(args->buffer)), type == HTTP_NOT_SUPPORTED)
	{
		forbidden_403(args, "Only simple GET and POST operations are supported");
        finish_hit(args, 3);
        return;
	}
	
	// get a pointer to the request body (or NULL if it's not there)
    body = (type==HTTP_GET) ? NULL : args->buffer->ptr+get_body_start(string_chars(args->buffer));
	
	// the request will be "GET [URL] " or "POST [URL] " followed by other details
	// we will terminate after the second space, to ignore everything else
	for (i = (type==HTTP_GET) ? 4 : 5; i < args->buffer->used_bytes; i++)
	{
		if (string_chars(args->buffer)[i] == ' ')
		{
			string_chars(args->buffer)[i] = 0; // second space, terminate string here
			break;
		}
	}

    j = (type==HTTP_GET) ? 4 : 5;
    
    // check for an absolute directory
    if (string_chars(args->buffer)[j+1] == '/')
    {
        forbidden_403(args, "Sorry, absolute paths are not permitted");
        finish_hit(args, 3);
        return;
    }
    
	for (; j<i-1; j++)
	{
		// check for any parent directory use
		if (string_chars(args->buffer)[j] == '.' && string_chars(args->buffer)[j+1] == '.')
		{
			forbidden_403(args, "Sorry, parent paths (..) are not permitted");
            finish_hit(args, 3);
	        return;
		}
	}
    
    struct http_header ctype = get_header("Content-Type", args->headers);
    j = (int)strlen(ctype.value);
    if (j > 0)
    {
        args->content_type = mallocx(j+1);
        strncpy(args->content_type, ctype.value, j);
        
        if (string_matches_value(args->content_type, "application/x-www-form-urlencoded"))
        {
            get_form_values(args, body);
        }
    }
    else
    {
        args->content_type = mallocx(1);
        args->content_type[0] = 0;
    }
    
	// call the "responder function" which has been provided to do the rest
    args->responder_function(args, string_chars(args->buffer) + ((type==HTTP_GET) ? 5 : 6), body, type);
    finish_hit(args, 1);
}