Example #1
0
/**
 * @short  Performs the processing of the request.
 * @memberof onion_server_t
 * 
 * Returns the OCS_KEEP_ALIVE or OCS_CLOSE_CONNECTION value. If on keep alive the struct is already reinitialized.
 * 
 * It calls the root_handler and if it returns an error of any type (or not processed), it calls the
 * default internal_error_handler.
 * 
 * Normally it could get the server from the request, but it is passed for homogenity, and
 * to allow unforseen posibilities.
 * 
 * @see onion_connection_status
 */
onion_connection_status onion_server_handle_request(onion_server *server, onion_request *req){
	onion_response *res=onion_response_new(req);
	
	// Call the main handler.
	onion_connection_status hs=onion_handler_handle(server->root_handler, req, res);

	if (hs==OCS_INTERNAL_ERROR || 
		hs==OCS_NOT_IMPLEMENTED || 
		hs==OCS_NOT_PROCESSED){
		if (hs==OCS_INTERNAL_ERROR)
			req->flags|=OR_INTERNAL_ERROR;
		if (hs==OCS_NOT_IMPLEMENTED)
			req->flags|=OR_NOT_IMPLEMENTED;
		if (hs==OCS_NOT_PROCESSED)
			req->flags|=OR_NOT_FOUND;
    if (hs==OCS_FORBIDDEN)
      req->flags|=OR_FORBIDDEN;
		
		hs=onion_handler_handle(server->internal_error_handler, req, res);
	}

	
	int rs=onion_response_free(res);
	if (hs>=0 && rs==OCS_KEEP_ALIVE) // if keep alive, reset struct to get the new petition.
		onion_request_clean(req);
	
	return hs>0 ? rs : hs;
}
Example #2
0
int onion_handler_auth_pam_handler(onion_handler_auth_pam_data *d, onion_request *request, onion_response *res){
	/// Use session to know if already logged in, so do not mess with PAM so often.
	if (onion_request_get_session(request, "pam_logged_in"))
		return onion_handler_handle(d->inside, request, res);
	
	const char *o=onion_request_get_header(request, "Authorization");
	char *auth=NULL;
	char *username=NULL;
	char *passwd=NULL;
	if (o && strncmp(o,"Basic",5)==0){
		//fprintf(stderr,"auth: '%s'\n",&o[6]);
		auth=onion_base64_decode(&o[6], NULL);
		username=auth;
		int i=0;
		while (auth[i]!='\0' && auth[i]!=':') i++;
		if (auth[i]==':'){
			auth[i]='\0'; // so i have user ready
			passwd=&auth[i+1];
		}
		else
			passwd=NULL;
	}
	
	// I have my data, try to authorize
	if (username && passwd){
		int ok=authorize(d->pamname, username, passwd);
		
		if (ok){ // I save the username at the session, so it can be accessed later.
			onion_dict *session=onion_request_get_session_dict(request);
			onion_dict_lock_write(session);
			onion_dict_add(session, "username", username, OD_REPLACE|OD_DUP_VALUE);
			onion_dict_add(session, "pam_logged_in", username, OD_REPLACE|OD_DUP_VALUE);
			onion_dict_unlock(session);
			
			free(auth);
			return onion_handler_handle(d->inside, request, res);
		}
	}
	if (auth)
		free(auth);

	
	// Not authorized. Ask for it.
	char temp[256];
	sprintf(temp, "Basic realm=\"%s\"",d->realm);
	onion_response_set_header(res, "WWW-Authenticate",temp);
	onion_response_set_code(res, HTTP_UNAUTHORIZED);
	onion_response_set_length(res,sizeof(RESPONSE_UNAUTHORIZED));
	
	onion_response_write(res,RESPONSE_UNAUTHORIZED,sizeof(RESPONSE_UNAUTHORIZED));
	return OCS_PROCESSED;
}
Example #3
0
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();
}
Example #4
0
File: url.c Project: cemonds/onion
/**
 * @short Performs the real request: checks if its for me, and then calls the inside level.
 */
int onion_url_handler(onion_url_data **dd, onion_request *request, onion_response *response){
	onion_url_data *next=*dd;
	regmatch_t match[16];
	int i;
	
	const char *path=onion_request_get_path(request);
	while (next){
		ONION_DEBUG0("Check %s against %s", onion_request_get_path(request), next->orig);
		if (next->flags&OUD_STRCMP){
			if (strcmp(path, next->str)==0){
				ONION_DEBUG0("Ok, simple match.");

				onion_request_advance_path(request, strlen(next->str));
				return onion_handler_handle(next->inside, request, response);
			}
		}
		else if (regexec(&next->regexp, onion_request_get_path(request), 16, match, 0)==0){
			//ONION_DEBUG("Ok,match");
			onion_dict *reqheader=request->GET;
			for (i=1;i<16;i++){
				regmatch_t *rm=&match[i];
				if (rm->rm_so!=-1){
					char *tmp=malloc(rm->rm_eo-rm->rm_so);
					memcpy(tmp, &path[rm->rm_so], rm->rm_eo-rm->rm_so);
					char tmpn[4];
					snprintf(tmpn,sizeof(tmpn),"%d",i);
					onion_dict_add(reqheader, tmpn, tmp, OD_DUP_KEY|OD_FREE_VALUE);
					ONION_DEBUG("Add group %d: %s (%d-%d)", i, tmp, rm->rm_so, rm->rm_eo);
				}
				else
					break;
			}
			onion_request_advance_path(request, match[0].rm_eo);
			ONION_DEBUG0("Ok, regexp match.");

			
			return onion_handler_handle(next->inside, request, response);
		}
		
		next=next->next;
	}
	return 0;
}
Example #5
0
int oterm_nopam(onion_handler *next, onion_request *req, onion_response *res){
	onion_dict *session=onion_request_get_session_dict(req);
	onion_dict_lock_write(session);
	const char *username=getenv("USER");
	if (username)
		onion_dict_add(session, "username", username, 0);
	onion_dict_add(session, "nopam", "true", 0);
	onion_dict_unlock(session);
	
	return onion_handler_handle(next, req, res);
}
Example #6
0
/**
 * @short Launches one handler for the given request
 * @ingroup request
 *
 * Once the request is ready, launch it.
 *
 * @returns The connection status: if it should be closed, error codes...
 */
onion_connection_status onion_request_process(onion_request *req){
	onion_response *res=onion_response_new(req);
	if (!req->path){
		onion_request_polish(req);
	}
	// Call the main handler.
	onion_connection_status hs=onion_handler_handle(req->connection.listen_point->server->root_handler, req, res);

	if (hs==OCS_INTERNAL_ERROR ||
		hs==OCS_NOT_IMPLEMENTED ||
		hs==OCS_NOT_PROCESSED){
		if (hs==OCS_INTERNAL_ERROR)
			req->flags|=OR_INTERNAL_ERROR;
		if (hs==OCS_NOT_IMPLEMENTED)
			req->flags|=OR_NOT_IMPLEMENTED;
		if (hs==OCS_NOT_PROCESSED)
			req->flags|=OR_NOT_FOUND;
		if (hs==OCS_FORBIDDEN)
			req->flags|=OR_FORBIDDEN;

		hs=onion_handler_handle(req->connection.listen_point->server->internal_error_handler, req, res);
	}

	if (hs==OCS_YIELD){
		// Remove from the poller, and yield thread to poller. From now on it will be processed somewhere else (longpoll thread).
		onion_poller *poller=onion_get_poller(req->connection.listen_point->server);
		onion_poller_slot *slot=onion_poller_get(poller, req->connection.fd);
		onion_poller_slot_set_shutdown(slot, NULL, NULL);

		return hs;
	}
	int rs=onion_response_free(res);
	if (hs>=0 && rs==OCS_KEEP_ALIVE) // if keep alive, reset struct to get the new petition.
		onion_request_clean(req);
	return hs>0 ? rs : hs;
}
Example #7
0
void t03_handle_path_request(){
	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_url_add_static(urls, "^$", "Test index\n", HTTP_OK);
	onion_url_add_static(urls, "^index.html$", "Index test", 200);

	onion_url *pathu=onion_url_new();
	onion_handler *path=onion_url_to_handler(pathu);
	onion_url_add_url(pathu, "^test/", urls);
	onion_handler_add(path, onion_handler_static("Internal error", 500 ) );
	onion_set_root_handler(server, path);
	
	onion_request *request;
	onion_response *response;
	
	request=onion_request_new(lp);
	FILL(request,"GET / HTTP/1.1\n");
  onion_request_polish(request);
	response=onion_response_new(request);
	onion_handler_handle(path, request, response);
	onion_response_free(response);
	const char *buffer=onion_buffer_listen_point_get_buffer_data(request);
	FAIL_IF_NOT_STRSTR(buffer, "HTTP/1.1 500 INTERNAL ERROR\r\n");
	FAIL_IF_NOT_STRSTR(buffer, "Content-Length: 14\r\n");
	FAIL_IF_NOT_STRSTR(buffer, "\r\n\r\nInternal error");
	onion_request_free(request);
	
	// gives error, as such url does not exist.
	request=onion_request_new(lp);
	FILL(request,"GET /test/ HTTP/1.1\n");
  onion_request_polish(request);
	response=onion_response_new(request);
	onion_handler_handle(path, request, response);
	onion_response_free(response);
	buffer=onion_buffer_listen_point_get_buffer_data(request);
	FAIL_IF_NOT_STRSTR(buffer, "HTTP/1.1 200 OK\r\n");
	FAIL_IF_NOT_STRSTR(buffer, "Content-Length: 11\r\n");
	FAIL_IF_NOT_STRSTR(buffer, "\r\n\r\nTest index\n");
	onion_request_free(request);

	request=onion_request_new(lp);
	FILL(request,"GET /test/index.html HTTP/1.1\n");
  onion_request_polish(request);
	response=onion_response_new(request);
	onion_handler_handle(path, request, response);
	onion_response_free(response);
	buffer=onion_buffer_listen_point_get_buffer_data(request);
	FAIL_IF_NOT_STRSTR(buffer, "HTTP/1.1 200 OK\r\n");
	FAIL_IF_NOT_STRSTR(buffer, "Content-Length: 10\r\n");
	FAIL_IF_NOT_STRSTR(buffer, "\r\n\r\nIndex test");
	onion_request_free(request);

	onion_free(server);

	END_LOCAL();
}
Example #8
0
/// Shortcut for fast internal redirect. It returns what the server would return with the new address.
onion_connection_status onion_shortcut_internal_redirect(const char *newurl, onion_request *req, onion_response *res){
  free(req->fullpath);
  req->fullpath=req->path=strdup(newurl);
  return onion_handler_handle(req->connection.listen_point->server->root_handler, req, res);
}