Inserito un inizio di esempio dell'uso delle funzioni delle capabilities.
[gapil.git] / sources / wwwd.c
index 3379486e08a431d0e8febd3f003632e369120537..16838882a4fd8820eaf1317157f4adc04a6f9761 100644 (file)
@@ -53,10 +53,17 @@ int demonize  = 1;  /* daemon use option: default is daemon */
 int debugging = 0;  /* debug info printing option: default is no debug */
 
 /* Subroutines declaration */
+struct code_page {
+    char * code; 
+    char * name;
+    char * body;
+};
+
 void usage(void);
 void ServPage(int sockfd);
 void PrintErr(char * error);
-void print_headers(FILE *file);
+void print_headers(FILE *file, struct code_page code);
+void print_error(FILE *file, struct code_page page, char * string);
 
 /* Program beginning */
 int main(int argc, char *argv[])
@@ -65,8 +72,10 @@ int main(int argc, char *argv[])
  * Variables definition  
  */
     int list_fd, conn_fd;
-    int waiting = 0;
     int compat = 0;
+    int reroot = 0;
+    int reuse = 1;
+    char * rootdir;
     pid_t pid;
     struct sockaddr_in cli_add;
     socklen_t len;
@@ -77,7 +86,7 @@ int main(int argc, char *argv[])
      */
     int i;
     opterr = 0;         /* don't want writing to stderr */
-    while ( (i = getopt(argc, argv, "hdicw:")) != -1) {
+    while ( (i = getopt(argc, argv, "hwdicr:")) != -1) {
        switch (i) {
        /* 
         * Handling options 
@@ -97,7 +106,11 @@ int main(int argc, char *argv[])
            debugging = 1;
            break;
        case 'w':
-           waiting = strtol(optarg, NULL, 10);
+           reuse = 0;
+           break;
+       case 'r':
+           reroot = 1;
+           rootdir = optarg;
            break;
        case '?':   /* unrecognized options */
            printf("Unrecognized options -%c\n",optopt);
@@ -120,9 +133,21 @@ int main(int argc, char *argv[])
        SignalRestart(SIGCHLD, HandSigCHLD);  /* restarting handler */
     }
     /* create and bind socket */
-    if ( (list_fd = sockbind2(argv[optind], "www", 6, SOCK_STREAM)) < 0) {
+    if ( (list_fd = sockbindopt(argv[optind], "www", 6, 
+                               SOCK_STREAM, reuse)) < 0) {
        return 1;
     }   
+    /* chroot if requested */
+    if (reroot) {
+       if (chdir(rootdir)) {
+           perror("Cannot find directory to chroot");
+           exit(1);
+       }
+       if (chroot(rootdir)) {
+           perror("Cannot chroot");
+           exit(1);
+       }
+    }
     /* release privileges and go daemon */
     if (setgid(65534) !=0) { /* first give away group privileges */
        perror("cannot give away group privileges");
@@ -144,7 +169,6 @@ int main(int argc, char *argv[])
        PrintErr("listen error");
        exit(1);
     }
-    if (waiting) sleep(waiting);
     /* handle echo to client */
     while (1) {
        /* accept connection */
@@ -200,7 +224,7 @@ void usage(void)
     printf("  -d          write debug info\n");
     printf("  -i          use interactively\n");
     printf("  -c          disable BSD semantics\n");
-    printf("  -w N        wait N sec. before calling accept\n");
+    printf("  -r /path    chroot on /path\n");
     exit(1);
 }
 /*
@@ -212,37 +236,46 @@ void ServPage(int sockfd)
     char outbuf[1024];
     FILE *sock, *file;
     char *line, *copy, *method, *ptr, *filename, *version;
-    char *methods[] = { "GET", "PUT", NULL };
-    char *codes[] = {
-       "200 OK",
-       "404 Not Found",
-       NULL
+    char *methods[] = { "GET", "HEAD", NULL };
+    struct code_page codes[] = {
+       { "200", "OK", "%s"},
+       { "400", "Bad Request", 
+          "Your browser sent a request that this server could not understand."
+         "<P>The request line<P>%s<P> is invalid following the protocol<P>"}, 
+       { "404", "Not Found", 
+          "The requested URL %s was not found on this server.<P>"},
+       { "500", "Internal Server Error", 
+          "We got an error processing your request.<P>Error is: %s<P>"},
+       { "405", "Method Not Allowed", "Method %s not allowed.<P>"},
+       { "403", "Forbidden", "You cannot access %s.<P>"}
     };
     int nleft;
-    int i, j;
+    int i;
 
     sock = fdopen(sockfd, "w+");
     /* main loop, reading 0 char means client close connection */
     line = fgets(buffer, MAXLINE, sock);
-    copy = strndupa(line, MAXLINE);
-
     if (line == NULL) {
        PrintErr("Errore in lettura");
        return;
     }
+    /* parsing first line, getting method and filename */
+    copy = strndupa(line, MAXLINE);
     if ((method = strtok_r(copy, " ", &ptr)) == NULL) {
-       PrintErr("Non ho trovato il metodo");
+       print_headers(sock, codes[1]);
+       print_error(sock, codes[1], line);
        return;
     }
     if ((filename = strtok_r(NULL, " ", &ptr)) == NULL) {
-       PrintErr("Non ho trovato il file");
+       print_headers(sock, codes[1]);
+       print_error(sock, codes[1], line);
        return;
     }
     if ((version = strtok_r(NULL, " ", &ptr)) == NULL) {
-       PrintErr("Non ho trovato la versione");
+       print_headers(sock, codes[1]);
+       print_error(sock, codes[1], line);
        return;
     }
-    printf("metodo %s -- file %s -- versione %s\n", method, filename, version);
     i = 0;
     while ( (ptr = methods[i]) != NULL) {
        if ( (strncmp(ptr, method, strlen(ptr)) == 0)) {
@@ -251,45 +284,44 @@ void ServPage(int sockfd)
        i++;
     }
     if (i>=2) {
-       printf("No method %s found\n", method);
+       print_headers(sock, codes[4]);
+       print_error(sock, codes[4], method);
        return;
     }
 
     while (strcmp(line,"\r\n")) {
-       line =  fgets(buffer, MAXLINE, sock);
-       printf("letto: %s\n", line);
+       line = fgets(buffer, MAXLINE, sock);
     }
 
     if ( (file = fopen(filename, "r")) == NULL) {
-       printf("file %s", filename);
-       perror("Error opening");
-       fprintf(sock, "HTTP/1.0 %s\n", codes[1]);
-       print_headers(sock);
+       if ( (errno == EACCES)||(errno == EPERM) ) {
+           print_headers(sock, codes[5]);
+           print_error(sock, codes[5], filename);
+       } else {
+           print_headers(sock, codes[2]);
+           print_error(sock, codes[2], filename);
+       }
        return;
     }
-    fprintf(sock, "HTTP/1.0 %s\n", codes[0]);
-    //PrintHeader(sock);
-    print_headers(sock);
-
-    j = 0;
+    print_headers(sock, codes[0]);
     while (!feof(file)) {
-       printf("Loop %d\n", j++);
        if ( (nleft = full_fread(file, outbuf, 1024)) != 0) {
            if (ferror(file)) {
-               printf("Errore in lettura");
+               strncpy(buffer, strerror(errno), MAXLINE);
+               print_headers(sock, codes[3]);
+               print_error(sock, codes[3], buffer);
                return;
            }
        }
-       printf("Loop %d rimasti %d\n", j, nleft);
        if (full_fwrite(sock, outbuf, 1024-nleft) != 0) {
            if (ferror(file)) {
-               printf("Errore in scrittura");
+               strncpy(buffer, strerror(errno), MAXLINE);
+               print_headers(sock, codes[3]);
+               print_error(sock, codes[3], buffer);
                return;
            }   
        }
     }
-    printf("Ok fin qui!");
-//    line = fgets(buffer, MAXLINE, sock);
     fclose(file);
     fclose(sock);
     return;
@@ -307,20 +339,27 @@ void PrintErr(char * error)
     return;
 }
 
-void print_headers(FILE *file)
+void print_headers(FILE *file, struct code_page code)
 {
     time_t tempo;
 
+    fprintf(file, "HTTP/1.0 %s %s \n", code.code, code.name);
     time(&tempo);
     fprintf(file, "Date: %s", ctime(&tempo));
     fprintf(file, "Server: WWWd test server\n");
     fprintf(file, "Connection: close\n");
     fprintf(file, "Content-Type: text/html; charset=iso-8859-1\n");
     fprintf(file, "\n");
-    printf("Date: %s", ctime(&tempo));
-    printf("Server: WWWd test server\n");
-    printf("Connection: close\n");
-    printf("Content-Type: text/html; charset=iso-8859-1\n");
-    printf("\n");
     return;
 }
+
+void print_error(FILE *file, struct code_page page, char * string)
+{
+    fprintf(file, "<HTML><HEAD><TITLE>%s %s</TITLE></HEAD>\n",
+           page.code, page.name);
+    fprintf(file, "<BODY><H1>%s</H1>\n", page.name);
+    fprintf(file, page.body, string);
+    fprintf(file, "<HR><ADDRESS>WWWd by S. Piccardi</ADDRESS></BODY></HTML>");
+    return;
+}
+