Il giorno lun 26 gen 2026 alle ore 07:35 Amos Jeffries
<[email protected]> ha scritto:
>
> On 26/01/2026 01:05, Gianluca Cannata wrote:
> > 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
> > +
>
> Still need to document that this value is relatively arbitrary. We only
> use the first 13 bytes of the first line.

What value do you suggest ?

> Technically the HTTP "Reason Phrase" string is unlimited length.

How to protect against it ?

>
> >  /* 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;
> > +       }
> >
>
> I suspect this is heading in a bad direction. AFAIK, system calls are
> quite expensive.
>
> We know that a minimum of 13 bytes are needed for this function, so you
> can start with that many and reduce by the amount actually received
> until that much is read in.

Ok.

> After which, you can do whatever to discard the remainder of the line.
> No need to even put that part in buf.

How to discard data ? There is a portable way of doing it ?

> AFAICS the header are currently being dropped so a bulk read to drop the
> status as well is fine ... for now.
>
>
>
> > -       *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." 
> > */
>
> We know that buf has more than 7 bytes/octets.
> Use memcmp() rather than strncmp().
>
>
> > +                       (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 */
>
> Sadly bare-CR is a thing from malicious services. We do have to check
> for "\r\n" together instead of just an '\r'.
>
> So IMO the above should be:
>
>    (i >= 13) &&
>    (memcmp (buf, "HTTP/1.", 7) == 0 && isdigit(buf[7])) && // HTTP version
>    (buf[8] == ' ') && // SP delimiter
>    (buf[9] >= '1' && buf[9] <= '5' && isdigit(buf[10]) &&
> isdigit(buf[10])) && // status code
>   (buf[12] == ' ' || (buf[12] == '\r' && buf[13] == 'n') || buf[12] ==
> '\n'); // SP delimiter or End of Line
>
> Note, with the change to which characters buf[9] is compared against we
> are no longer needing the extra (status < 100 || status >= 600) check below.
>
> >
> > -       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