diff --git a/c/httpserver.c b/c/httpserver.c index 8e17220e2..d80b2e2e5 100644 --- a/c/httpserver.c +++ b/c/httpserver.c @@ -3360,6 +3360,27 @@ static int handleServiceFailed(HttpConversation *conversation, return HTTP_SERVICE_FAILED; } +static int checkAuthorization(HttpServer *server, HttpService *service, HttpRequest *request, HttpResponse *response) { + if (!request->authenticated) { + return FALSE; + } + if (service->authorizationType == SERVICE_AUTHORIZATION_TYPE_NONE) { + return TRUE; + } + int authorized = TRUE; + HttpAuthorizationHandler *handler = server->authorizationHandlerList; + while (handler) { + if (handler->authorizationType == service->authorizationType) { + authorized = handler->authorizeFunction(service, request, response, handler->userData); + if (!authorized) { + break; + } + } + handler = handler->next; + } + return authorized; +} + static int handleHttpService(HttpServer *server, HttpService *service, HttpRequest *request, @@ -3443,8 +3464,9 @@ static int handleHttpService(HttpServer *server, } break; } + int authorized = checkAuthorization(server, service, request, response); #ifdef DEBUG - printf("service=%s authenticated=%d\n",service->name,request->authenticated); + printf("service=%s authenticated=%d authorized=%d\n",service->name,request->authenticated,authorized); #endif if (request->authenticated == FALSE){ if (service->authFlags & SERVICE_AUTH_FLAG_OPTIONAL) { @@ -3453,6 +3475,8 @@ static int handleHttpService(HttpServer *server, } else { respondWithAuthError(response, &authResponse); } + } else if (!authorized) { + respondWithError(response, HTTP_STATUS_FORBIDDEN, "Forbidden"); // Response is finished on return } else { @@ -6011,7 +6035,29 @@ int mainHttpLoop(HttpServer *server){ return stcBaseMainLoop(base, MAIN_WAIT_MILLIS); } - +int registerHttpAuthorizationHandler(HttpServer *server, int authorizationType, HttpAuthorize *authorizeFunction, void *userData) { + if (authorizationType == SERVICE_AUTHORIZATION_TYPE_NONE) { + return 0; + } + HttpAuthorizationHandler *handler = (HttpAuthorizationHandler*) safeMalloc(sizeof(*handler), "HttpAuthorizationHandler"); + if (handler) { + handler->authorizationType = authorizationType; + handler->authorizeFunction = authorizeFunction; + handler->userData = userData; + handler->next = NULL; + HttpAuthorizationHandler *head = server->authorizationHandlerList; + if (!head) { + server->authorizationHandlerList = handler; + } else { + while (head->next != NULL) { + head = head->next; + } + head->next = handler; + } + return 0; + } + return -1; +} /* diff --git a/h/httpserver.h b/h/httpserver.h index 053f52bdb..c2657022f 100644 --- a/h/httpserver.h +++ b/h/httpserver.h @@ -146,6 +146,7 @@ typedef int HttpServiceServe(struct HttpService_tag *service, HttpResponse *resp typedef int AuthExtract(struct HttpService_tag *service, HttpRequest *request); typedef int AuthValidate(struct HttpService_tag *service, HttpRequest *request); typedef int HttpServiceInsertCustomHeaders(struct HttpService_tag *service, HttpResponse *response); +typedef int HttpAuthorize(struct HttpService_tag *service, HttpRequest *request, HttpResponse *response, void *userData); /* returns HTTP_SERVICE_SUCCESS or other fail codes in same group @@ -205,8 +206,21 @@ typedef struct HttpService_tag{ AuthValidate *authValidateFunction; #define SERVICE_AUTH_FLAG_OPTIONAL 1 int authFlags; +#define SERVICE_AUTHORIZATION_TYPE_DEFAULT 0 +#define SERVICE_AUTHORIZATION_TYPE_NONE 1 +// Range 2..99 is reserved for future use +#define SERVICE_AUTHORIZATION_TYPE_FIRST_CUSTOM 100 +// SERVICE_AUTHORIZATION_TYPE_FIRST_CUSTOM and higher can be defined and used by an application. + int authorizationType; } HttpService; +typedef struct HttpAuthorizationHandler_tag { + int authorizationType; + HttpAuthorize *authorizeFunction; + void *userData; + struct HttpAuthorizationHandler_tag *next; +} HttpAuthorizationHandler; + typedef struct HTTPServerConfig_tag { int port; HttpService *serviceList; @@ -229,6 +243,7 @@ typedef struct HttpServer_tag{ uint64 serverInstanceUID; /* may be something smart at some point. Now just startup STCK */ void *sharedServiceMem; /* address shared by all HttpServices */ hashtable *loggingIdsByName; /* contains a map of pluginID -> loggingID */ + HttpAuthorizationHandler *authorizationHandlerList; } HttpServer; typedef struct WSReadMachine_tag{ @@ -417,6 +432,18 @@ int httpServerSetSessionTokenKey(HttpServer *server, unsigned int size, int registerHttpService(HttpServer *server, HttpService *service); + +/* + * @brief Register an Authorization handler. + * @param server HTTP Server + * @param authorizationType + * @param authorizeFunction Function that performs authorization. + * The function has to return TRUE if the user successfully authorized, otherwise - FALSE. + * @param userData Additional data for authorizeFunction + * @return 0 on success, -1 on failure. + */ +int registerHttpAuthorizationHandler(HttpServer *server, int authorizationType, HttpAuthorize *authorizeFunction, void *userData); + HttpRequest *dequeueHttpRequest(HttpRequestParser *parser); HttpRequestParser *makeHttpRequestParser(ShortLivedHeap *slh); HttpResponse *makeHttpResponse(HttpRequest *request, ShortLivedHeap *slh, Socket *socket);