C   23

BuggyServer

Guest on 1st June 2022 01:24:33 AM

  1. #include <signal.h>
  2. #include <unistd.h>
  3. #include <string.h>
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <sys/types.h>
  7. #include <sys/socket.h>
  8. #include <netinet/in.h>
  9. #include <arpa/inet.h>
  10. #include <sys/stat.h>
  11.  
  12. /*
  13. BuggyServer v. 2.0
  14. Copyright (c) , Matt Jacobson [mhj32]
  15. All Rights Reserved.
  16. */
  17.  
  18. typedef unsigned char byte;
  19.  
  20. int main(int, char*[]);
  21. char* handle(char*, int*);
  22. int check_filename_length(byte);
  23. void sigint(int);
  24. void sigsegv(int);
  25.  
  26. char* port_arg;
  27. int sock = 0;
  28. const char* prefix = "GET /";
  29. const char* resp_ok = "HTTP/1.1 200 OK\nServer: BuggyServer/1.0\n";
  30. const char* resp_bad = "HTTP/1.1 404 Not Found\nServer: BuggyServer/1.0\n\n";
  31. const char* content_html = "Content-type: text/html\n\n";
  32. const char* content_text = "Content-type: text/plain\n\n";
  33.  
  34. const char* www_path = "./www/";
  35.  
  36. int main(int argc, char* argv[]) {
  37.         int port;
  38.  
  39.         if (argc < 2 || (port = atoi(argv[1])) < 1 || port > 65535) {
  40.                 printf("Usage: webserver port\n");
  41.                 exit(1);
  42.         }
  43.  
  44.         port_arg = (char*) malloc(6*sizeof (char));
  45.         memset(port_arg, '\0', 6);
  46.         strncpy(port_arg, argv[1], 5);
  47.  
  48.         signal(SIGINT, &sigint);
  49.         signal(SIGSEGV, &sigsegv);
  50.  
  51.         struct sockaddr_in socket_addr;
  52.         sock = socket(PF_INET, SOCK_STREAM, 0);
  53.  
  54.         memset(&socket_addr, 0, sizeof socket_addr);
  55.         socket_addr.sin_family = PF_INET;
  56.         socket_addr.sin_port = htons(port);
  57.         socket_addr.sin_addr.s_addr = htonl(INADDR_ANY);
  58.  
  59.         if (bind(sock, (struct sockaddr *) &socket_addr, sizeof socket_addr) < 0) {
  60.                 perror("couldn't bind");
  61.                 exit(1);
  62.         }
  63.         listen(sock, 10);
  64.  
  65.         while (1) {
  66.                 int acceptsock = accept(sock, NULL, NULL);
  67.                 char* input = (char*) malloc(1024*sizeof (char));
  68.                 recv(acceptsock, input, 1024, 0);
  69.                 int is_html = 0;
  70.                 char* contents = handle(input,&is_html);
  71.                 free(input);
  72.  
  73.                 if (contents != NULL) {
  74.                         send(acceptsock, resp_ok, strlen(resp_ok), 0);
  75.                         if (is_html)
  76.                                 send(acceptsock, content_html, strlen(content_html), 0);
  77.                         else
  78.                                 send(acceptsock, content_text, strlen(content_text), 0);
  79.                         send(acceptsock, contents, strlen(contents), 0);
  80.                         send(acceptsock, "\n", 1, 0);
  81.                         free(contents);
  82.                 } else
  83.                         send(acceptsock, resp_bad, strlen(resp_bad), 0);
  84.  
  85.                 shutdown(acceptsock, SHUT_RDWR); // fixed strange buffering issues (related to kernel or Firefox?)
  86.                 close(acceptsock);
  87.         }
  88.  
  89.         return 0;
  90. }
  91.  
  92. char* handle(char* request, int* is_html) {
  93.         char filename[100];
  94.  
  95.         memset(filename, '\0', 100*sizeof (char));
  96.         if (strstr(request, prefix) == request) {
  97.                 char* start = request + strlen(prefix);
  98.                 char* end = strstr(start, " HTTP");
  99.                 if (end == NULL) {
  100.                         printf("Unsupported command (malformed end).\n");
  101.                         return NULL;
  102.                 }
  103.                 int len = (int) (end - start);
  104.                 if (check_filename_length(len))
  105.                         strncpy(filename, start, len);
  106.                 else
  107.                         return NULL;
  108.         } else {
  109.                 printf("BEGIN: Unsupported command (malformed beginning).\n");
  110.                 return NULL;
  111.         }
  112.  
  113.  
  114.         if (strstr(filename,"/") != NULL)
  115.                 return NULL;
  116.  
  117.         if (!strcmp(filename, ""))
  118.                 strcpy(filename,"index.html");
  119.         if (strstr(filename,".html") != NULL)
  120.                 *is_html = 1;
  121.  
  122.         char* path = (char*) malloc((strlen(www_path) + strlen(filename))*sizeof (char));
  123.         strcpy(path, www_path);
  124.         strcpy(path + strlen(www_path), filename);
  125.  
  126.         struct stat file_status;
  127.         if (stat(path, &file_status) != 0)
  128.         {
  129.                 return NULL;
  130.         }
  131.  
  132.         char* contents = (char*) malloc((file_status.st_size+1)*sizeof (char));
  133.         memset(contents, '\0', file_status.st_size+1);
  134.  
  135.         FILE *readfile = fopen(path, "r");
  136.         int i;
  137.         for (i=0;i<file_status.st_size;i++)
  138.                 contents[i] = fgetc(readfile);
  139.         fclose(readfile);
  140.         return contents;
  141. }
  142.  
  143. int check_filename_length(byte len) {
  144.         if (len < 100)
  145.                 return 1;
  146.         return 0;
  147. }
  148.  
  149. void sigint(int arg) {
  150.         if (sock)
  151.                 close(sock);
  152.         printf("Shutting down peacefully.\n");
  153.         exit(0);
  154. }
  155.  
  156. void sigsegv(int arg) {
  157.         if (sock)
  158.                 close(sock);
  159.         printf("Segmentation violation.  Shutting down peacefully, then rebooting.\n");
  160.  
  161.         sleep(2);
  162.         char* argv[3];
  163.         argv[0] = "./webserver";
  164.         argv[1] = port_arg;
  165.         argv[2] = NULL;
  166.         execv(argv[0], argv);
  167.         free(port_arg);
  168.         exit(1);
  169. }

Raw Paste


Login or Register to edit or fork this paste. It's free.