Hi Amos,

thank you for your feedback.

I have tried to address all of your comments.

Let me know what you think.

Gianluca
Index: httpfs/http.c
===================================================================
--- httpfs.orig/http.c
+++ httpfs/http.c
@@ -34,6 +34,8 @@
 #include <hurd/hurd_types.h>
 #include <hurd/netfs.h>
 
+#define MAX_HTTP_STATUS_LINE 256
+
 /* do a DNS lookup for HOST and store result in *DEST */
 error_t lookup_host (const char *host, struct sockaddr_storage *dest, socklen_t *dest_len, int *socktype, int *protocol) 
 {
@@ -100,34 +102,73 @@ error_t lookup_host (const char *host, s
        return 0;
 }
 
-/* read the first line from the socket and return an error_t error */
+/* read the first line from the socket or return an error_t error */
 static error_t translate_http_status (int fd, ssize_t *nread)
 {
-       char buf[32];
+       char buf[MAX_HTTP_STATUS_LINE];
+       size_t i = 0;
+       ssize_t n;
+       char c;
+       int status;
+
+       *nread = 0;
+
+       /* 1. byte-per-byte read until \n */
+       while (i < sizeof (buf) - 1) {
+               n = read (fd, &c, 1);
+               if (n <= 0) return EIO;
+               buf[i++] = c;
+               if (c == '\n') break;
+       }
 
-       *nread = read (fd, buf, sizeof (buf) - 1);
-       if (*nread < 12) return EIO;
-       buf[*nread] = '\0';
+       buf[i] = '\0';
+       *nread = i;
 
-       if (strncmp (buf, "HTTP/", 5) != 0)
-               return EPROTO;
+       /* 2. Positional validation: "HTTP/1.N SSS" */
+       int valid = (i >= 12) &&
+                       (strncmp (buf, "HTTP/1.", 7) == 0) && /* "HTTP/1." */
+                       (buf[7] >= '0' && buf[7] <= '9') && /* N (digit) */
+                       (buf[8] == ' ') && /* SP */
+                       (buf[9] >= '0' && buf[9] <= '9') && /* S (digit 1) */
+                       (buf[10] >= '0' && buf[10] <= '9') && /* S (digit 2) */
+                       (buf[11] >= '0' && buf[11] <= '9') && /* S (digit 3) */
+                       (buf[12] == ' ' || buf[12] == '\r' || buf[12] == '\n'); /* End of line */
 
-       int status = atoi (buf + 9);
+       if (!valid) return EPROTO;
+
+       /* 3. HTTP status code conversion */
+       status = atoi (buf + 9);
 
        if (debug_flag)
-               fprintf (stderr, "HTTP Status: %d\n", status);
+               fprintf (stderr, "HTTP Protocol Verified. Status: %d\n", status);
+
+       /* 4. RFC 9110 - POSIX mappings */
+       if (status < 100 || status >= 600) return EPROTO;
+       if (status < 200) return EIO; /* 1xx not supported */
+       if (status < 300) return 0; /* 2xx Success */
+
+       if (status < 400) { /* 3xx Redirection */
+               switch (status) {
+                       case 301: case 302: case 303: case 307: case 308: return EAGAIN;
+                       default: return EIO;
+               }
+       }
+
+       if (status < 500) { /* 4xx Client Errors */
+               switch (status) {
+                       case 401: case 402: case 403: case 405:
+                       case 407: case 421: case 451: return EACCES;
+                       case 404: case 410: case 406: case 412: case 415: case 428: return ENOENT;
+                       case 426: return EPROTO;
+                       default: return EINVAL;
+               }
+       }
 
-       switch (status)
-       {
-               case 200: return 0;
-               case 301:
-               case 302: return EAGAIN;
-               case 401:
-               case 403: return EACCES; 
-               case 404: return ENOENT;
-               case 410: return ENOENT;
-               default:
-                       return (status >= 500) ? EIO : EINVAL;
+       /* 5xx Server Errors */
+       switch (status) {
+               case 501: case 505: case 510: return EINVAL;
+               case 503: return EACCES; 
+               default: return EIO;
        }
 }

Reply via email to