The HTTP RFC defines a header as:
message-header = field-name ":" [ field-value ]
       field-name     = token
       field-value    = *( field-content | LWS )

   The field-content does not include any leading or trailing LWS:
   linear white space occurring before the first non-whitespace
   character of the field-value or after the last non-whitespace
   character of the field-value. Such leading or trailing LWS MAY be
   removed without changing the semantics of the field value.

Plus there is this as well:
   The field value MAY be preceded by any amount of LWS, though a single
   SP is preferred.

Now rpki-client's http client does currently require exactly one space
between the ':' and the field-value. This works in most cases but is
incorrect and too strict.

The following diff fixes this for rpki-client. Now rpki-client does not
require any space at all (I assume that no space is also covered by any
amount of LWS).

Btw. ftp(1) has the same issue and it should be fixed there as well.
-- 
:wq Claudio

Index: http.c
===================================================================
RCS file: /cvs/src/usr.sbin/rpki-client/http.c,v
retrieving revision 1.65
diff -u -p -r1.65 http.c
--- http.c      30 Aug 2022 14:33:26 -0000      1.65
+++ http.c      7 Sep 2022 13:21:08 -0000
@@ -1164,11 +1164,11 @@ http_redirect(struct http_connection *co
 static int
 http_parse_header(struct http_connection *conn, char *buf)
 {
-#define CONTENTLEN "Content-Length: "
-#define LOCATION "Location: "
-#define CONNECTION "Connection: "
-#define TRANSFER_ENCODING "Transfer-Encoding: "
-#define LAST_MODIFIED "Last-Modified: "
+#define CONTENTLEN "Content-Length:"
+#define LOCATION "Location:"
+#define CONNECTION "Connection:"
+#define TRANSFER_ENCODING "Transfer-Encoding:"
+#define LAST_MODIFIED "Last-Modified:"
        const char *errstr;
        char *cp, *redirurl;
        char *locbase, *loctail;
@@ -1178,10 +1178,9 @@ http_parse_header(struct http_connection
        if (*cp == '\0')
                return 0;
        else if (strncasecmp(cp, CONTENTLEN, sizeof(CONTENTLEN) - 1) == 0) {
-               size_t s;
                cp += sizeof(CONTENTLEN) - 1;
-               if ((s = strcspn(cp, " \t")) != 0)
-                       *(cp + s) = 0;
+               cp += strspn(cp, " \t");
+               cp[strcspn(cp, " \t")] = '\0';
                conn->iosz = strtonum(cp, 0, MAX_CONTENTLEN, &errstr);
                if (errstr != NULL) {
                        warnx("Content-Length of %s is %s",
@@ -1191,6 +1190,7 @@ http_parse_header(struct http_connection
        } else if (http_isredirect(conn) &&
            strncasecmp(cp, LOCATION, sizeof(LOCATION) - 1) == 0) {
                cp += sizeof(LOCATION) - 1;
+               cp += strspn(cp, " \t");
                /*
                 * If there is a colon before the first slash, this URI
                 * is not relative. RFC 3986 4.2
@@ -1232,11 +1232,13 @@ http_parse_header(struct http_connection
        } else if (strncasecmp(cp, TRANSFER_ENCODING,
            sizeof(TRANSFER_ENCODING) - 1) == 0) {
                cp += sizeof(TRANSFER_ENCODING) - 1;
+               cp += strspn(cp, " \t");
                cp[strcspn(cp, " \t")] = '\0';
                if (strcasecmp(cp, "chunked") == 0)
                        conn->chunked = 1;
        } else if (strncasecmp(cp, CONNECTION, sizeof(CONNECTION) - 1) == 0) {
                cp += sizeof(CONNECTION) - 1;
+               cp += strspn(cp, " \t");
                cp[strcspn(cp, " \t")] = '\0';
                if (strcasecmp(cp, "close") == 0)
                        conn->keep_alive = 0;
@@ -1245,6 +1247,7 @@ http_parse_header(struct http_connection
        } else if (strncasecmp(cp, LAST_MODIFIED,
            sizeof(LAST_MODIFIED) - 1) == 0) {
                cp += sizeof(LAST_MODIFIED) - 1;
+               cp += strspn(cp, " \t");
                free(conn->last_modified);
                if ((conn->last_modified = strdup(cp)) == NULL)
                        err(1, NULL);

Reply via email to