// 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(); }
void t01_handle_static_request(){ INIT_LOCAL(); char ok; onion *server=onion_new(0); onion_listen_point *lp=onion_buffer_listen_point_new(); onion_add_listen_point(server, NULL, NULL, lp); onion_request *request=onion_request_new(lp); FILL(request,"GET / HTTP/1.1\n"); onion_handler *handler=onion_handler_static("Not ready",302); FAIL_IF_NOT(handler); onion_set_root_handler(server, handler); onion_response *response=onion_response_new(request); ok=onion_handler_handle(handler, request, response); FAIL_IF_NOT_EQUAL(ok, OCS_PROCESSED); onion_response_free(response); const char *buffer=onion_buffer_listen_point_get_buffer_data(request); FAIL_IF_EQUAL_STR(buffer,""); FAIL_IF_NOT_STRSTR(buffer, "HTTP/1.1 302 REDIRECT\r\n"); FAIL_IF_NOT_STRSTR(buffer, "\r\nContent-Length: 9\r\n"); FAIL_IF_NOT_STRSTR(buffer, "libonion"); FAIL_IF_STRSTR(buffer, "License: AGPL"); // License is now LGPL, no need to advertise FAIL_IF_STRSTR(buffer, "License"); FAIL_IF_NOT_STRSTR(buffer, "\r\n\r\nNot ready"); onion_request_free(request); onion_free(server); END_LOCAL(); }
void t02_server_full(){ INIT_LOCAL(); onion *server=onion_new(0); onion_listen_point *lp=onion_buffer_listen_point_new(); onion_add_listen_point(server,NULL,NULL,lp); onion_set_root_handler(server, onion_handler_static("Succedded", 200)); onion_request *req=onion_request_new(lp); #define S "GET / HTTP/1.1\r\nHeader-1: This is header1\r\nHeader-2: This is header 2\r\n" onion_request_write(req, S,sizeof(S)-1); // send it all, but the final 0. #undef S const char *buffer=onion_buffer_listen_point_get_buffer_data(req); FAIL_IF_NOT_EQUAL_STR(buffer,""); onion_request_write(req, "\n",1); // finish this request. no \n\n before to check possible bugs. buffer=onion_buffer_listen_point_get_buffer_data(req); FAIL_IF_EQUAL_STR(buffer,""); FAIL_IF_NOT_STRSTR(buffer, "HTTP/1.1 200 OK\r\n"); FAIL_IF_NOT_STRSTR(buffer, "\r\nContent-Length: 9\r\n"); FAIL_IF_NOT_STRSTR(buffer, "libonion"); FAIL_IF_NOT_STRSTR(buffer, "\r\n\r\nSuccedded"); onion_request_free(req); onion_free(server); END_LOCAL(); }
void t01_server_min(){ INIT_LOCAL(); onion *server=onion_new(0); onion_listen_point *lp=onion_buffer_listen_point_new(); onion_add_listen_point(server,NULL,NULL,lp); onion_set_root_handler(server, onion_handler_static("Succedded", 200)); onion_request *req=onion_request_new(lp); onion_request_write(req, "GET ",4); onion_request_write(req, "/",1); onion_request_write(req, " HTTP/1.1\r\n",11); onion_request_write(req, "\r\n",2); const char *buffer=onion_buffer_listen_point_get_buffer_data(req); FAIL_IF_EQUAL_STR(buffer,""); FAIL_IF_NOT_STRSTR(buffer, "HTTP/1.1 200 OK\r\n"); FAIL_IF_NOT_STRSTR(buffer, "\r\nContent-Length: 9\r\n"); FAIL_IF_NOT_STRSTR(buffer, "libonion"); FAIL_IF_NOT_STRSTR(buffer, "\r\n\r\nSuccedded"); onion_request_free(req); onion_free(server); END_LOCAL(); }
void t08_server_with_error_404(){ INIT_LOCAL(); onion *server=onion_new(0); onion_listen_point *lp=onion_buffer_listen_point_new(); onion_add_listen_point(server,NULL,NULL,lp); onion_url *urls=onion_url_new(); onion_set_root_handler(server, onion_url_to_handler(urls)); onion_request *req=onion_request_new(lp); #define S "GET / HTTP/1.1" onion_request_write(req, S,sizeof(S)-1); // send it all, but the final 0. #undef S const char *buffer=onion_buffer_listen_point_get_buffer_data(req); FAIL_IF_NOT_EQUAL_STR(buffer,""); onion_request_write(req, "\n",1); // finish this request. no \n\n before to check possible bugs. onion_request_write(req, "\n",1); // finish this request. no \n\n before to check possible bugs. The last \n was not processed, as was overflowing. buffer=onion_buffer_listen_point_get_buffer_data(req); FAIL_IF_EQUAL_STR(buffer,""); FAIL_IF_NOT_STRSTR(buffer, "HTTP/1.1 404 NOT FOUND\r\n"); FAIL_IF_NOT_STRSTR(buffer, "libonion"); onion_request_free(req); onion_free(server); END_LOCAL(); }
void t04_server_overflow(){ INIT_LOCAL(); onion *server=onion_new(0); onion_listen_point *lp=onion_buffer_listen_point_new(); onion_add_listen_point(server,NULL,NULL,lp); onion_set_root_handler(server, onion_handler_static("Succedded", 200)); onion_block *long_req=onion_block_new(); onion_block_add_str(long_req,"GET / HTTP/1.1\n"); int i; for(i=0;i<1000;i++){ onion_block_add_str(long_req,"Header-1: This is header1 Header-2: This is header 2 "); } onion_request *req=onion_request_new(lp); onion_request_write(req, onion_block_data(long_req),onion_block_size(long_req)-1); // send it all, but the final 0. const char *buffer=onion_buffer_listen_point_get_buffer_data(req); FAIL_IF_NOT_EQUAL_STR(buffer,""); onion_request_write(req, "\n\n",2); // finish this request. no \n\n before to check possible bugs. buffer=onion_buffer_listen_point_get_buffer_data(req); FAIL_IF_EQUAL_STR(buffer,""); FAIL_IF_NOT_STRSTR(buffer, "HTTP/1.1 200 OK\r\n"); FAIL_IF_NOT_STRSTR(buffer, "\r\nContent-Length: 9\r\n"); FAIL_IF_NOT_STRSTR(buffer, "libonion"); FAIL_IF_NOT_STRSTR(buffer, "\r\n\r\nSuccedded"); onion_block_free(long_req); onion_request_free(req); onion_free(server); END_LOCAL(); }
void t01_url() { INIT_LOCAL(); onion_url *url = onion_url_new(); onion_url_add_handler(url, "^handler1.$", onion_handler_new((onion_handler_handler) handler1, NULL, NULL)); onion_url_add(url, "handler2/", handler2); onion_url_add_with_data(url, "^handler(3|4)/", handler3, NULL, NULL); onion_set_root_handler(server, onion_url_to_handler(url)); onion_request *req = onion_request_new(onion_get_listen_point(server, 0)); #define R "GET /handler1/ HTTP/1.1\n\n" onion_request_write(req, R, sizeof(R)); onion_request_process(req); FAIL_IF_NOT_EQUAL_INT(handler_called, 1); FAIL_IF_NOT_EQUAL_STR(urltxt, ""); free(urltxt); urltxt = NULL; onion_request_clean(req); onion_request_write(req, "GET /handler2/ HTTP/1.1\n\n", sizeof(R)); onion_request_process(req); FAIL_IF_NOT_EQUAL_INT(handler_called, 2); ONION_DEBUG("%s", urltxt); FAIL_IF_NOT_EQUAL_STR(urltxt, ""); free(urltxt); urltxt = NULL; onion_request_clean(req); onion_request_write(req, "GET /handler3/hello HTTP/1.1\n\n", sizeof(R) + 5); onion_request_process(req); FAIL_IF_NOT_EQUAL_INT(handler_called, 3); FAIL_IF_NOT_EQUAL_STR(urltxt, "hello"); free(urltxt); urltxt = NULL; handler_called = 0; onion_request_clean(req); onion_request_write(req, "GET /handler2/hello HTTP/1.1\n\n", sizeof(R) + 5); onion_request_process(req); FAIL_IF_NOT_EQUAL_INT(handler_called, 0); FAIL_IF_EQUAL_STR(urltxt, ""); free(urltxt); urltxt = NULL; onion_request_free(req); onion_url_free(url); onion_set_root_handler(server, NULL); END_LOCAL(); }
void t02_cookies(){ INIT_LOCAL(); onion_response *res=onion_response_new(NULL); onion_dict *h=onion_response_get_headers(res); onion_response_add_cookie(res, "key1", "value1", -1, NULL, NULL, 0); FAIL_IF_NOT_EQUAL_STR(onion_dict_get(h, "Set-Cookie"), "key1=value1"); onion_dict_remove(h, "Set-Cookie"); onion_response_add_cookie(res, "key2", "value2", -1, "/", "*.example.org", OC_HTTP_ONLY|OC_SECURE); FAIL_IF_NOT_EQUAL_STR(onion_dict_get(h, "Set-Cookie"), "key2=value2; path=/; domain=*.example.org; HttpOnly; Secure"); onion_dict_remove(h, "Set-Cookie"); onion_response_add_cookie(res, "key3", "value3", 0, "/", "*.example.org", OC_HTTP_ONLY|OC_SECURE); FAIL_IF_NOT_EQUAL_STR(onion_dict_get(h, "Set-Cookie"), "key3=value3; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=*.example.org; HttpOnly; Secure"); onion_dict_remove(h, "Set-Cookie"); onion_response_add_cookie(res, "key4", "value4", 60, "/", "*.example.org", OC_HTTP_ONLY|OC_SECURE); FAIL_IF_EQUAL_STR(onion_dict_get(h, "Set-Cookie"), "key4=value4; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/; domain=*.example.org; HttpOnly; Secure"); FAIL_IF_EQUAL_STR(onion_dict_get(h, "Set-Cookie"), "key4=value4; domain=*.example.org; HttpOnly; path=/; Secure"); int i; int valid_expires=0; char tmpdate[100]; const char *setcookie=onion_dict_get(h, "Set-Cookie"); for(i=59;i<62;i++){ struct tm *tmp; time_t t=time(NULL) + i; tmp = localtime(&t); strftime(tmpdate, sizeof(tmpdate), "key4=value4; expires=%a, %d %b %Y %H:%M:%S %Z; path=/; domain=*.example.org; HttpOnly; Secure", tmp); ONION_DEBUG("\ntest %s =? \nonion %s", tmpdate, setcookie); if (strcmp(tmpdate, setcookie)==0) valid_expires=1; } FAIL_IF_NOT(valid_expires); onion_response_free(res); END_LOCAL(); }
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(); }
void t11_cookies(){ INIT_LOCAL(); onion_request *req; int ok; req=onion_request_new(custom_io); FAIL_IF_EQUAL(req,NULL); FAIL_IF_NOT_EQUAL(req->connection.fd, -1); { const char *query="GET / HTTP/1.0\n" "Content-Type: application/x-www-form-urlencoded\n" "Host: 127.0.0.1\n\r" "Cookie: key1=value1; key2=value2;\n" "Accept-Language: en\n"; // Missing \n caused memleak, to check with valgrind ok=onion_request_write(req,query,strlen(query)); } FAIL_IF_EQUAL(ok,OCS_INTERNAL_ERROR); FAIL_IF_NOT_EQUAL_STR(onion_request_get_header(req,"Host"),"127.0.0.1"); FAIL_IF_NOT_EQUAL_STR(onion_request_get_header(req,"Cookie"), "key1=value1; key2=value2;"); FAIL_IF_NOT_EQUAL_STR(onion_request_get_cookie(req,"key1"), "value1"); FAIL_IF_NOT_EQUAL_STR(onion_request_get_cookie(req,"key2"), "value2"); FAIL_IF_EQUAL_STR(onion_request_get_cookie(req," key2"), "value2"); onion_dict *cookies=onion_request_get_cookies_dict(req); FAIL_IF_EQUAL(cookies, NULL); FAIL_IF_NOT_EQUAL_STR(onion_dict_get(cookies,"key1"), "value1"); FAIL_IF_NOT_EQUAL_STR(onion_dict_get(cookies,"key2"), "value2"); onion_request_free(req); END_LOCAL(); }
void t00_server_empty(){ INIT_LOCAL(); onion *server=onion_new(0); onion_listen_point *lp=onion_buffer_listen_point_new(); onion_add_listen_point(server,NULL,NULL,lp); onion_request *req=onion_request_new(lp); onion_request_write(req, "GET ",4); onion_request_write(req, "/",1); onion_request_write(req, " HTTP/1.1\r\n",11); onion_request_write(req, "\r\n",2); const char *buffer=onion_buffer_listen_point_get_buffer_data(req); FAIL_IF_EQUAL_STR(buffer,""); FAIL_IF_NOT_STRSTR(buffer,"404"); onion_request_free(req); onion_free(server); END_LOCAL(); }
void t02_cookies(){ INIT_LOCAL(); onion *o=onion_new(O_ONE_LOOP); onion_request *req; onion_dict *session; char *cookieid; char tmp[256]; req=onion_request_new(o->server, NULL, NULL); FAIL_IF_NOT_EQUAL(req->session_id, NULL); session=onion_request_get_session_dict(req); onion_dict_add(session,"Test","tseT", 0); FAIL_IF_EQUAL(req->session_id, NULL); cookieid=strdup(req->session_id); onion_request_free(req); req=onion_request_new(o->server, NULL, NULL); FAIL_IF_NOT_EQUAL(req->session_id, NULL); session=onion_request_get_session_dict(req); FAIL_IF_EQUAL(req->session_id, NULL); session=onion_request_get_session_dict(req); onion_dict_add(session,"Test","Another value", 0); FAIL_IF_EQUAL_STR(req->session_id, cookieid); onion_request_free(req); req=onion_request_new(o->server, NULL, NULL); snprintf(tmp,sizeof(tmp),"sessionid=%s",cookieid); onion_dict_add(req->headers,"Cookie",tmp, OD_DUP_VALUE); FAIL_IF_NOT_EQUAL(req->session_id, NULL); session=onion_request_get_session_dict(req); FAIL_IF_NOT_EQUAL_STR(req->session_id, cookieid); FAIL_IF_NOT_EQUAL_STR(onion_dict_get(session,"Test"),"tseT"); onion_request_free(req); req=onion_request_new(o->server, NULL, NULL); snprintf(tmp,sizeof(tmp),"trashthingish=nothing interesting; sessionid=%s; wtf=ianal",cookieid); onion_dict_add(req->headers,"Cookie",tmp, OD_DUP_VALUE); FAIL_IF_NOT_EQUAL(req->session_id, NULL); session=onion_request_get_session_dict(req); FAIL_IF_NOT_EQUAL_STR(req->session_id, cookieid); FAIL_IF_NOT_EQUAL_STR(onion_dict_get(session,"Test"),"tseT"); onion_request_free(req); req=onion_request_new(o->server, NULL, NULL); snprintf(tmp,sizeof(tmp),"sessionid=nothing interesting; sessionid=%s; other_sessionid=ianal",cookieid); onion_dict_add(req->headers,"Cookie",tmp, OD_DUP_VALUE); FAIL_IF_NOT_EQUAL(req->session_id, NULL); session=onion_request_get_session_dict(req); FAIL_IF_NOT_EQUAL_STR(req->session_id, cookieid); FAIL_IF_NOT_EQUAL_STR(onion_dict_get(session,"Test"),"tseT"); onion_request_free(req); req=onion_request_new(o->server, NULL, NULL); snprintf(tmp,sizeof(tmp),"sessionid=nothing interesting; xsessionid=%s; other_sessionid=ianal",cookieid); onion_dict_add(req->headers,"Cookie",tmp, OD_DUP_VALUE); FAIL_IF_NOT_EQUAL(req->session_id, NULL); session=onion_request_get_session_dict(req); FAIL_IF_EQUAL_STR(req->session_id, cookieid); FAIL_IF_EQUAL_STR(onion_dict_get(session,"Test"),"tseT"); onion_request_free(req); onion_free(o); free(cookieid); END_LOCAL(); }
void t01_test_session(){ INIT_LOCAL(); onion_sessions *sessions=onion_sessions_new(); // create a session onion_dict *ses=onion_sessions_get(sessions, "s01"); FAIL_IF_NOT_EQUAL(ses, NULL); // It does not auto create the sessions, to avoid problems char *s01=onion_sessions_create(sessions); ses=onion_sessions_get(sessions, s01); FAIL_IF_EQUAL(ses, NULL); // It does not auto create the sessions, to avoid problems // get another pointer to the same session onion_dict *ses2=onion_sessions_get(sessions, s01); FAIL_IF_NOT_EQUAL(ses, ses2); //Check it is really the same onion_dict_add(ses, "foo", "bar", 0); FAIL_IF_NOT_EQUAL_STR("bar", onion_dict_get(ses2, "foo")); // When removed, it should refcount-- onion_dict_free(ses2); ses2=onion_sessions_get(sessions, s01); FAIL_IF_NOT_EQUAL(ses, ses2); // also all removal, should stay at the sessions onion_dict_free(ses); onion_dict_free(ses2); ses2=onion_sessions_get(sessions, s01); FAIL_IF_NOT_EQUAL_STR("bar", onion_dict_get(ses2, "foo")); onion_dict_free(ses2); // Create a second session char *s02=onion_sessions_create(sessions); ses2=onion_sessions_get(sessions, s02); onion_dict_add(ses2, "hello", "world", 0); ses=onion_sessions_get(sessions, s01); FAIL_IF_EQUAL_STR(onion_dict_get(ses, "hello"), onion_dict_get(ses2, "hello")); FAIL_IF_EQUAL_STR(onion_dict_get(ses, "foo"), onion_dict_get(ses2, "foo")); onion_dict_free(ses); onion_dict_free(ses2); // And finally really remove it onion_sessions_remove(sessions, s01); ses2=onion_sessions_get(sessions, s01); FAIL_IF_NOT_EQUAL(ses2, NULL); // this created a new one free(s01); s01=onion_sessions_create(sessions); ses2=onion_sessions_get(sessions, s01); FAIL_IF_EQUAL_STR("bar", onion_dict_get(ses2, "foo")); onion_dict_free(ses2); // This should remove the sessions, and still hanging s02 onion_sessions_free(sessions); free(s01); free(s02); END_LOCAL(); }
// 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(); }