diff --git a/Dockerfile b/Dockerfile index 9508d9c..dae368c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,13 +4,14 @@ ENV DEBIAN_FRONTEND=noninteractive RUN apt-get update && \ apt-get install \ - -y openssl libssl-dev make gcc pkg-config + -y openssl libssl-dev make gcc pkg-config php php-cgi COPY Makefile /src/ COPY src/ /src/src/ COPY cmd/ /src/cmd/ COPY include/ /src/include/ COPY ca/ /src/ca/ +COPY entrypoint.sh / COPY content/ /var/www/html @@ -25,3 +26,6 @@ RUN printf "y\ny\n" | make genCerts EXPOSE 8080/tcp +CMD ["--verbose"] +ENTRYPOINT ["/bin/bash", "/entrypoint.sh"] + diff --git a/Makefile b/Makefile index 2378588..a6acddc 100644 --- a/Makefile +++ b/Makefile @@ -40,7 +40,7 @@ dockerBuild: output_dir docker build . -t seaweb:latest dockerTestDeploy: dockerBuild - docker run -p8080:8080 --rm seaweb:latest seaweb & + docker run -p8080:8080 --rm -d seaweb:latest killTestDocker: docker stop -t 0 `docker ps | grep "seaweb:latest" | tail -n 1 | tr -s " " | cut -d " " -f 1` diff --git a/cmd/server.c b/cmd/server.c index 7b4159f..f537361 100644 --- a/cmd/server.c +++ b/cmd/server.c @@ -16,8 +16,8 @@ #include "server.h" #include "utils.h" -//#define WEB_ROOT "/var/www/html/" -#define WEB_ROOT "content/" +#define WEB_ROOT "/var/www/html/" +//#define WEB_ROOT "content/" #define BUFF_READ 1024 static int verbose_flag = 0; @@ -32,6 +32,51 @@ int printDebug(char message[]) { return 0; } +void php_cgi(char *sPath) { + int phpPipe[2]; + char *buf = NULL; + size_t bufLen = 1024; + + buf = malloc(bufLen); + pipe(phpPipe); + + pid_t pid; + pid = fork(); + + if (pid == 0) { + char script[500]; + close(phpPipe[0]); + dup2(phpPipe[1], STDOUT_FILENO); + strcpy(script, "SCRIPT_FILENAME="); + strcat(script, WEB_ROOT); + strcat(script, sPath); + putenv("GATEWAY_INTERFACE=CGI/1.1"); + putenv(script); + putenv("QUERY_STRING="); + putenv("REQUEST_METHOD=GET"); + putenv("REDIRECT_STATUS=true"); + putenv("SERVER_PROTOCOL=HTTP/1.1"); + putenv("REMOTE_HOST=127.0.0.1"); + execl("/usr/bin/php-cgi", "php-cgi", NULL); + } else if (pid < 0) { + printDebug("Error forking php exec"); + } else { + size_t buffCount; + close(phpPipe[1]); + do { + buffCount = read(phpPipe[0], buf, BUFF_READ); + if (strlen(buf) == bufLen) { + bufLen *= 2; + buf = realloc(buf, bufLen); + } + } while (buffCount == 0); + } + + close(phpPipe[0]); + printf("PHP: %s\n", buf); + return; +} + int parseHTTPRequest(unsigned char *buffer, struct HTTPRequest *r) { char temp[1]; // Used to check newlines char *token = calloc(8, sizeof(char)); @@ -96,6 +141,18 @@ int parseHTTPRequest(unsigned char *buffer, struct HTTPRequest *r) { token = strtok(NULL, ""); r->requestHost = malloc(strlen(token)); strcpy(r->requestHost, token); + } else if (!strcmp(token, "Content-Type")) { + token = strtok(NULL, ":"); + r->requestConType = malloc(strlen(token)); + strcpy(r->requestConType, token); + } else if (!strcmp(token, "Content-Length")) { + token = strtok(NULL, ":"); + if (token == NULL) { + printDebug("Content-length parsing error"); + return -1; + } + r->requestConLen = malloc(strlen(token)); + strcpy(r->requestConLen, token); } } } @@ -224,50 +281,68 @@ int handleDELETERequest(int socket, struct HTTPRequest *r, SSL *ssl) { } int handlePOSTRequest(int socket, struct HTTPRequest *r, SSL *ssl) { - return501Request(socket, ssl); - return 0; + // Supported data types application/x-www-form-urlencoded application/json + if (r->requestConLen == NULL) { // Return 411 if length var not specified + printDebug("Content Length was not sent in POST request"); + return return411Request(socket, ssl); + } + //r->requestBody[strlen((char *)r->requestBody) - 1] = '\0'; // Resetting request content length to remove trailing newline + + if (r->requestConType != NULL) { + if (!strcmp(r->requestConType, "application/json")) { + printf("JSON Request\n"); + } else if (!strcmp(r->requestConType, "application/x-www-form-utlencoded")) { + printf("Application form\n"); + } + } else { + printf("HERE\n"); + } + + php_cgi(r->requestDir); + + return return501Request(socket, ssl); } int handleRequest(unsigned char buffer[], int socket, SSL *ssl) { struct HTTPRequest r; // Holds relevant HTTP request information + r.requestConLen = malloc(sizeof(char)); + r.requestConType = NULL; int checkerr = 0; // Grabbing relevant information out of request checkerr = parseHTTPRequest(buffer, &r); if (checkerr != 0) { // Checking for HTTP parsing error + printDebug("Error ;("); if (checkerr == -1) { printDebug("Error reading request, returning empty 500"); - return return500Request(socket, ssl); + return500Request(socket, ssl); } else { printDebug("Error parsing, returning 501"); - return return501Request(socket, ssl); + return501Request(socket, ssl); } } else { checkerr = checkHTTPVersion(r.requestVersion); if (checkerr != 0) { - return return505Request(socket, ssl); + return505Request(socket, ssl); + } else { + if (!strcmp(r.requestType, "GET")) { + handleGetRequest(socket, &r, ssl); + } else if (!strcmp(r.requestType, "POST")) { + handlePOSTRequest(socket, &r, ssl); + } else if (!strcmp(r.requestType, "PUT")) { + handlePUTRequest(socket, &r, ssl); + } else if (!strcmp(r.requestType, "DELETE")) { + handleDELETERequest(socket, &r, ssl); + } else if (!strcmp(r.requestType, "CONNECT")) { + return200Request(socket, NULL, ssl); + } else { + return500Request(socket, ssl); + } } } - if (!strcmp(r.requestType, "GET")) { - handleGetRequest(socket, &r, ssl); - return 0; - } else if (!strcmp(r.requestType, "POST")) { - handlePOSTRequest(socket, &r, ssl); - return 0; - } else if (!strcmp(r.requestType, "PUT")) { - handlePUTRequest(socket, &r, ssl); - return 0; - } else if (!strcmp(r.requestType, "DELETE")) { - handleDELETERequest(socket, &r, ssl); - return 0; - } else if (!strcmp(r.requestType, "CONNECT")) { - return200Request(socket, NULL, ssl); - return 0; - } else { - return500Request(socket, ssl); - return 0; - } + free(r.requestConLen); + return 0; } void timeoutChild(int sig) { @@ -394,7 +469,6 @@ int main(int argc, char **argv) { perror("Accept connection error"); exit(EXIT_FAILURE); } - // Forking process pid_t pid; pid = fork(); @@ -420,7 +494,7 @@ int main(int argc, char **argv) { } while(buffCont == 0); if (strlen((char *)buffer) != 0) { handleRequest(buffer, new_socket, ssl); - buffer = calloc(bufSize, sizeof(unsigned char)); + free(buffer); } else { printDebug("Error reading from socket"); } @@ -435,7 +509,7 @@ int main(int argc, char **argv) { } while(buffCont == 0); handleRequest(buffer, new_socket, NULL); - buffer = calloc(bufSize, sizeof(unsigned char)); + free(buffer); } exit(EXIT_SUCCESS); } else if (pid2 < 0) { @@ -464,7 +538,6 @@ int main(int argc, char **argv) { continue; } } - free(privKeyFile); free(certFile); free(listenAddr); @@ -472,3 +545,4 @@ int main(int argc, char **argv) { close(server_fd); exit(EXIT_SUCCESS); } + diff --git a/content/helloworld.php b/content/helloworld.php new file mode 100644 index 0000000..824e8a7 --- /dev/null +++ b/content/helloworld.php @@ -0,0 +1,3 @@ + diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..aa847b3 --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +set -e + +echo "$@" + +exec seaweb $@ diff --git a/include/httpStruct.h b/include/httpStruct.h index 6a45214..e379ed1 100644 --- a/include/httpStruct.h +++ b/include/httpStruct.h @@ -8,5 +8,7 @@ struct HTTPRequest { char *requestHost; char *requestDir; char *requestVars; + char *requestConType; + char *requestConLen; unsigned char *requestBody; }; diff --git a/include/returnRequest.h b/include/returnRequest.h index c0b551d..a4ca3ef 100644 --- a/include/returnRequest.h +++ b/include/returnRequest.h @@ -9,6 +9,7 @@ int return400Request(int socket, SSL *ssl); int return403Request(int socket, SSL *ssl); int return404Request(int socket, SSL *ssl); int return411Request(int socket, SSL *ssl); +int return418Request(int socket, SSL *ssl); int return500Request(int socket, SSL *ssl); int return501Request(int socket, SSL *ssl); diff --git a/src/returnRequest.c b/src/returnRequest.c index 244302b..d313ad3 100644 --- a/src/returnRequest.c +++ b/src/returnRequest.c @@ -57,6 +57,18 @@ int return400Request(int socket, SSL *ssl) { return returnRequest(socket, message, 400, ssl); } +int return411Request(int socket, SSL *ssl) { + char *message = calloc(128, sizeof(char)); + sprintf(message, "HTTP/1.1 411 Length Required\nContent-Length: 0\nConnection: close\n\n"); + return returnRequest(socket, message, 411, ssl); +} + +int return418Request(int socket, SSL *ssl) { + char *message=calloc(128, sizeof(char)); + sprintf(message, "HTTP/1.1 418 I'm a teapotnContent-Length: 0\nConnection: close\n\n"); + return returnRequest(socket, message, 418, ssl); +} + int return500Request(int socket, SSL *ssl) { char *message = calloc(128, sizeof(char)); sprintf(message, "HTTP/1.1 500 Internal Server Error\nContent-Length: 0\nConnection: close\n\n"); diff --git a/test_requests/post_no_content_len.raw b/test_requests/post_no_content_len.raw new file mode 100644 index 0000000..cd189d4 --- /dev/null +++ b/test_requests/post_no_content_len.raw @@ -0,0 +1,10 @@ +POST / HTTP/1.1 +Host: localhost:8080 +User-Agent: curl/7.81.0 +Accept: */* +Referer: rbose +Content-Length: 40 +Content-Type: application/x-www-form-urlencoded + +name=linuxize&email=linuxize@example.com +