Example #1
0
// This fixes that whenever a session is created, but no new data is added, it does not set the proper cookie
void t04_lot_of_sessionid(){
  INIT_LOCAL();

  onion *o=onion_new(O_ONE_LOOP);
  onion_server_set_write(o->server, empty_write);
  
  onion_url *url=onion_root_url(o);
  onion_url_add(url, "^.*", ask_session);
  char sessionid[256];
  char tmp[1024];
  char tmp2[4096];
  onion_request *req;
  int i;
  set_data_on_session=1;

  req=onion_request_new(o->server, NULL, NULL);
  req->fullpath="/";
  onion_request_process(req);
  FAIL_IF_NOT_EQUAL_INT(onion_dict_count(o->server->sessions->sessions), 1);
  FAIL_IF_EQUAL_STR(lastsessionid,"");
  strcpy(sessionid, lastsessionid);
  req->fullpath=NULL;
  onion_request_free(req);

  req=onion_request_new(o->server, NULL, NULL);
  req->fullpath="/";
  snprintf(tmp,sizeof(tmp)," sessionid=xx%sxx;",lastsessionid);
  strcpy(tmp2,"Cookie:");
  for(i=0;i<64;i++)
    strncat(tmp2, tmp, sizeof(tmp2));
  snprintf(tmp,sizeof(tmp)," sessionid=%s\n",lastsessionid);
  strncat(tmp2, tmp, sizeof(tmp2));
  ONION_DEBUG("Set cookies (%d bytes): %s",strlen(tmp2),tmp2);
  strcpy(tmp,"GET /\n");
  onion_request_write(req,tmp,strlen(tmp)); // Here is the problem, at parsing too long headers
  onion_request_write(req,tmp2,strlen(tmp2)); // Here is the problem, at parsing too long headers
	onion_request_write(req,"\n",1);
  //onion_dict_add(req->headers, "Cookie", tmp2, 0);
  
  onion_request_process(req);
  FAIL_IF_NOT_EQUAL_INT(onion_dict_count(o->server->sessions->sessions), 1);
  FAIL_IF_EQUAL_STR(lastsessionid,"");
  FAIL_IF_NOT_EQUAL_STR(lastsessionid, sessionid);
  FAIL_IF_NOT(has_set_cookie);
  onion_request_free(req);
  
  onion_free(o);
  
  END_LOCAL();
}
Example #2
0
/// Initializes the connection, create request, sets up the SSL...
static onion_request *onion_connection_start(onion *o, int clientfd, struct sockaddr_storage *cli_addr, socklen_t cli_len){
  signal(SIGPIPE, SIG_IGN); // FIXME. remove the thread better. Now it will try to write and fail on it.
  
	// sorry all the ifdefs, but here is the worst case where i would need it.. and both are almost the same.
#ifdef HAVE_GNUTLS
	gnutls_session_t session=NULL;
	if (o->flags&O_SSL_ENABLED){
		session=onion_prepare_gnutls_session(o, clientfd);
		if (session==NULL){
			ONION_ERROR("Could not create session");
			return NULL;
		}
	}
#endif

	onion_request *req;
#ifdef HAVE_GNUTLS
	if (o->flags&O_SSL_ENABLED){
		onion_server_set_write(o->server, (onion_write)gnutls_record_send); // Im lucky, has the same signature.
		onion_server_set_read(o->server, (onion_read)gnutls_record_recv); // Im lucky, has the same signature.
		onion_server_set_close(o->server, (onion_close)onion_ssl_close);
		req=onion_request_new_from_socket(o->server, session, cli_addr, cli_len);
	}
	else
#endif
	{
		onion_server_set_write(o->server, (onion_write)onion_write_to_socket);
		onion_server_set_read(o->server, (onion_read)onion_read_from_socket);
		onion_server_set_close(o->server, (onion_close)onion_close_socket);
		req=onion_request_new_from_socket(o->server, (void*)(long int)clientfd, cli_addr, cli_len);
	}
	req->fd=clientfd;
	if (!( (o->flags&O_THREADED) || (o->flags&O_POLL) ))
		onion_request_set_no_keep_alive(req);
	
	return req;
}
Example #3
0
/// A BUG were detected: transformed \n to \r\n on files.
void t03_post_carriage_return_new_lines_file(){
	INIT_LOCAL();
	
	buffer *b=buffer_new(1024);
	
	expected_post post={};;
	post.filename="file.dat";
	post.test_ok=0; // Not ok as not called processor yet
	post.tmpfilename=NULL;
	post.size=3;
	
	onion_server *server=onion_server_new();
	onion_server_set_write(server, (void*)&buffer_append);
	onion_server_set_root_handler(server, onion_handler_new((void*)&post_check,&post,NULL));
	
	onion_request *req=onion_request_new(server,b,"test");

#define POST_EMPTY "POST / HTTP/1.1\nContent-Type: multipart/form-data; boundary=end\nContent-Length:81\n\n--end\nContent-Disposition: text/plain; name=\"file\"; filename=\"file.dat\"\n\n\n\r\n\n--end--"
	//ONION_DEBUG("%s",POST_EMPTY);
	onion_request_write(req,POST_EMPTY,sizeof(POST_EMPTY));
	FAIL_IF_NOT_EQUAL(post.test_ok,1);
#undef POST_EMPTY

	onion_request_clean(req);
	post.test_ok=0; // Not ok as not called processor yet

#define POST_EMPTYR "POST / HTTP/1.1\r\nContent-Type: multipart/form-data; boundary=end\r\nContent-Length:85\r\n\r\n--end\r\nContent-Disposition: text/plain; name=\"file\"; filename=\"file.dat\"\r\n\r\n\n\r\n\r\n--end--"
	onion_request_write(req,POST_EMPTYR,sizeof(POST_EMPTYR));
	FAIL_IF_NOT_EQUAL(post.test_ok,1);
#undef POST_EMPTYR

	onion_request_free(req);

	if (post.tmpfilename){
		struct stat st;
		FAIL_IF_EQUAL(stat(post.tmpfilename,&st), 0); // Should not exist
		free(post.tmpfilename);
	}
	if (post.tmplink)
		free(post.tmplink);
	
	onion_server_free(server);
	buffer_free(b);
	END_LOCAL();
}
Example #4
0
void t05_server_with_pipes(){
	INIT_LOCAL();
	
	onion_server *server=onion_server_new();
	onion_server_set_write(server, (onion_write)write_p);
	onion_server_set_root_handler(server, onion_handler_static("Works with pipes", 200));
	
	int p[2];
	int error=pipe(p);
	if (error){
		FAIL("Could not create pipe.");
		END_LOCAL();
	}
	
	onion_request *req=onion_request_new(server, &p[1], NULL);
#define S "GET / HTTP/1.1\n\n"
	onion_request_write(req, S,sizeof(S)-1); // send it all, but the final 0.
#undef S
	
	close(p[1]);
	
	//fcntl(p[0],F_SETFL, O_NONBLOCK);
	
	// read from the pipe
	char buffer[1024];
	memset(buffer,0,sizeof(buffer)); // better clean it, because if this does not work, it might get an old value
	int r=read(p[0], buffer, sizeof(buffer));
	if (r<0){
		ONION_DEBUG("Read %d bytes",r);
		perror("Error");
	}
	
	FAIL_IF_EQUAL_STR(buffer,"");
	FAIL_IF_NOT_STRSTR(buffer,"HTTP/1.1 200 OK\r\n");
	FAIL_IF_NOT_STRSTR(buffer,"Content-Length: 16\r\n");
	FAIL_IF_NOT_STRSTR(buffer,"\r\n\r\nWorks with pipes");

	onion_request_free(req);
	onion_server_free(server);

	END_LOCAL();
}
Example #5
0
/**
 * @short Executes each script file passed as argument.
 * 
 * Optionally a -r sets the new lines to \r\n. It takes care of not changing content types.
 */
int main(int argc, char **argv){
	server=onion_server_new();
	onion_server_set_root_handler(server,onion_handler_new((void*)allinfo_handler,NULL,NULL));
	onion_server_set_write(server,(void*)buffer_append);
	
	int i;
	int do_r=0;
	for (i=1;i<argc;i++){
		if (strcmp(argv[i],"-r")==0){
			ONION_WARNING("Setting the end of lines to \\r\\n");
			do_r=1;
		}
		else{
			ONION_INFO("Launching test %s",argv[i]);
			prerecorded(argv[i], do_r);
		}
	}
	
	onion_server_free(server);
	END();
}
Example #6
0
/// There is a bug when posting large files. Introduced when change write 1 by 1, to write by blocks on the FILE parser
void t04_post_largefile(){
	INIT_LOCAL();
	
	int postfd=open(BIG_FILE, O_RDONLY);
	off_t filesize=lseek(postfd, 0, SEEK_END);
	lseek(postfd, 0, SEEK_SET);
	
	buffer *b=buffer_new(1024);
	expected_post post={};;
	post.filename=BIG_FILE_BASE;
	post.test_ok=0; // Not ok as not called processor yet
	post.tmpfilename=NULL;
	post.size=filesize;
	
	onion_server *server=onion_server_new();
	onion_server_set_write(server, (void*)&buffer_append);
	onion_server_set_root_handler(server, onion_handler_new((void*)&post_check,&post,NULL));
	
	onion_request *req=onion_request_new(server,b,"test");

#define POST_HEADER "POST / HTTP/1.1\nContent-Type: multipart/form-data; boundary=end\nContent-Length: %d\n\n--end\nContent-Disposition: text/plain; name=\"file\"; filename=\"" BIG_FILE_BASE "\"\n\n"
	char tmp[1024];
	ONION_DEBUG("Post size is about %d",filesize+73);
	snprintf(tmp, sizeof(tmp), POST_HEADER, (int)filesize+73);
	ONION_DEBUG("%s",tmp);
	onion_request_write(req,tmp,strlen(tmp));
	
	int r=read(postfd, tmp, sizeof(tmp));
	while ( r>0 ){
		onion_request_write(req, tmp, r);
		r=read(postfd, tmp, sizeof(tmp));
	}
	
	onion_request_write(req,"\n--end--",8);
	FAIL_IF_NOT_EQUAL_INT(post.test_ok,1);
#undef POST_HEADER

	post.test_ok=0; // Not ok as not called processor yet

	lseek(postfd, 0, SEEK_SET);

	int difffd=open(post.tmpfilename, O_RDONLY);
	FAIL_IF_NOT_EQUAL_INT(difffd,-1); // Orig file is removed at handler returns. But i have a copy
	difffd=open(post.tmplink, O_RDONLY);
	FAIL_IF_EQUAL_INT(difffd,-1);
	ONION_DEBUG("tmp filename %s",post.tmpfilename);
	int r1=1, r2=1;
	char c1=0, c2=0;
	int p=0;
	while ( r1 && r2 && c1==c2){
		r1=read(difffd, &c1, 1);
		r2=read(postfd, &c2, 1);
		//ONION_DEBUG("%d %d",c1,c2);
		FAIL_IF_NOT_EQUAL_INT(c1,c2);
		p++;
	}
	if ( r1 || r2 ){
		ONION_ERROR("At %d",p);
		FAIL_IF_NOT_EQUAL_INT(r1,0);
		FAIL_IF_NOT_EQUAL_INT(r2,0);
		FAIL_IF_NOT_EQUAL_INT(c1,c2);
		FAIL("Files are different");
	}
	else
		ONION_DEBUG("Files are ok");
	
	close(difffd);
	close(postfd);

	onion_request_clean(req);

	onion_request_free(req);

	if (post.tmpfilename){
		struct stat st;
		FAIL_IF_EQUAL(stat(post.tmpfilename,&st), 0); // Should not exist
	}
	
	onion_server_free(server);
	buffer_free(b);
	if (post.tmpfilename)
		free(post.tmpfilename);
	if (post.tmplink)
		free(post.tmplink);
	
	END_LOCAL();
}
Example #7
0
// This fixes that whenever a session is created, but no new data is added, it does not set the proper cookie, and should not create a new session.
void t03_bug_empty_session_is_new_session(){
  INIT_LOCAL();

  onion *o=onion_new(O_ONE_LOOP);
  onion_server_set_write(o->server, empty_write);
  
  onion_url *url=onion_root_url(o);
  onion_url_add(url, "^.*", ask_session);
  char sessionid[256];
  char tmp[256];

  set_data_on_session=1;
  onion_request *req=onion_request_new(o->server, NULL, NULL);
  req->fullpath="/";
  onion_request_process(req);
  FAIL_IF_EQUAL_STR(lastsessionid,"");
  strcpy(sessionid, lastsessionid);
  req->fullpath=NULL;
  onion_request_free(req);
  FAIL_IF_NOT_EQUAL_INT(onion_dict_count(o->server->sessions->sessions), 1);
  
  req=onion_request_new(o->server, NULL, NULL);
  req->fullpath="/";
  onion_dict_add(req->headers, "Cookie", "sessionid=xxx", 0);
  onion_request_process(req);
  FAIL_IF_EQUAL_STR(lastsessionid,"");
  FAIL_IF_EQUAL_STR(lastsessionid, sessionid);
  FAIL_IF_NOT(has_set_cookie);
  req->fullpath=NULL;
  onion_request_free(req);
  FAIL_IF_NOT_EQUAL_INT(onion_dict_count(o->server->sessions->sessions), 2);
  
  req=onion_request_new(o->server, NULL, NULL);
  req->fullpath="/";
  snprintf(tmp,sizeof(tmp),"sessionid=%s",lastsessionid);
  onion_dict_add(req->headers, "Cookie", tmp, 0);
  onion_request_process(req);
  FAIL_IF_EQUAL_STR(lastsessionid,"");
  FAIL_IF_EQUAL_STR(lastsessionid, sessionid);
  FAIL_IF_NOT(has_set_cookie);
  strcpy(sessionid, lastsessionid);
  req->fullpath=NULL;
  onion_request_free(req);
  FAIL_IF_NOT_EQUAL_INT(onion_dict_count(o->server->sessions->sessions), 2);
  
  req=onion_request_new(o->server, NULL, NULL);
  req->fullpath="/";
  snprintf(tmp,sizeof(tmp),"sessionid=%sxx",lastsessionid);
  onion_dict_add(req->headers, "Cookie", tmp, 0);
  onion_request_process(req);
  FAIL_IF_EQUAL_STR(lastsessionid,"");
  FAIL_IF_EQUAL_STR(lastsessionid, sessionid);
  FAIL_IF_NOT(has_set_cookie);
  req->fullpath=NULL;
  onion_request_free(req);
  FAIL_IF_NOT_EQUAL_INT(onion_dict_count(o->server->sessions->sessions), 3);

  // Ask for new, without session data, but I will not set data on session, so session is not created.
  set_data_on_session=0;
  req=onion_request_new(o->server, NULL, NULL);
  req->fullpath="/";
  onion_request_process(req);
  FAIL_IF_EQUAL_STR(lastsessionid,"");
  strcpy(sessionid, lastsessionid);
  req->fullpath=NULL;
  FAIL_IF_NOT_EQUAL_INT(onion_dict_count(o->server->sessions->sessions), 4); // For a moment it exists, until onion realizes is not necesary.
  onion_request_free(req);
  FAIL_IF_NOT_EQUAL_INT(onion_dict_count(o->server->sessions->sessions), 3);

  
  onion_free(o);
  
  END_LOCAL();
}