Allow serving files without known mimetype
authorPatrick Gansterer <paroga@paroga.com>
Sat, 13 Aug 2016 09:17:53 +0000 (11:17 +0200)
committerAndy Green <andy@warmcat.com>
Sun, 14 Aug 2016 11:28:29 +0000 (19:28 +0800)
RFC2616 only says that any HTTP/1.1 message containing an entity-body
SHOULD include a Content-Type header field defining the media type of
that body.
RFC2119 defines SHOULD as: This word mean that there may exist valid
reasons in particular circumstances to ignore a particular item, but
the full implications must be understood and carefully weighed before
choosing a different course.

AG: this isn't an oversight, it's paranoia about sending out /etc/passwd
or /etc/shadow accidentally.

I agree it should be allowed if people really want to override it.  But
the default should remain like it is I think.

I adapted the patch to allow the extra mimetype "*": "" to be declared on
a mount, as a wildcard match that serves the file without a Content-Type.

README.lwsws.md
doc/html/md_README.lwsws.html
lib/server.c

index b15dcd0..e223837 100644 (file)
@@ -328,6 +328,18 @@ options are given, the content is marked uncacheable.
                 }
 ```
 
+Normally a file suffix MUST match one of the canned mimetypes or one of the extra
+mimetypes, or the file is not served.  This adds a little bit of security because
+even if there is a bug somewhere and the mount dirs are circumvented, lws will not
+serve, eg, /etc/passwd.
+
+If you provide an extra mimetype entry
+
+                       "*": ""
+
+Then any file is served, if the mimetype was not known then it is served without a
+Content-Type: header.
+
 @section lwswspl Lwsws Plugins
 
 Protcols and extensions may also be provided from "plugins", these are
index 86223ae..a3447b8 100644 (file)
@@ -148,7 +148,10 @@ Lwsws Other mount options</h1>
 <p>3) It's also possible to set the cgi timeout (in secs) per cgi:// mount, like this </p><div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno">    1</span>&#160;&quot;cgi-timeout&quot;: &quot;30&quot;</div></div><!-- fragment --><p> 4) <code>callback://</code> protocol may be used when defining a mount to associate a named protocol callback with the URL namespace area. For example </p><div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno">    1</span>&#160;{</div><div class="line"><a name="l00002"></a><span class="lineno">    2</span>&#160; &quot;mountpoint&quot;: &quot;/formtest&quot;,</div><div class="line"><a name="l00003"></a><span class="lineno">    3</span>&#160; &quot;origin&quot;: &quot;callback://protocol-post-demo&quot;</div><div class="line"><a name="l00004"></a><span class="lineno">    4</span>&#160;}</div></div><!-- fragment --><p> All handling of client access to /formtest[anything] will be passed to the callback registered to the protocol "protocol-post-demo".</p>
 <p>This is useful for handling POST http body content or general non-cgi http payload generation inside a plugin.</p>
 <p>See the related notes in README.coding.md</p>
-<p>5) Cache policy of the files in the mount can also be set. If no options are given, the content is marked uncacheable. </p><div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno">    1</span>&#160;{</div><div class="line"><a name="l00002"></a><span class="lineno">    2</span>&#160; &quot;mountpoint&quot;: &quot;/&quot;,</div><div class="line"><a name="l00003"></a><span class="lineno">    3</span>&#160; &quot;origin&quot;: &quot;file:///var/www/mysite.com&quot;,</div><div class="line"><a name="l00004"></a><span class="lineno">    4</span>&#160; &quot;cache-max-age&quot;: &quot;60&quot;,      # seconds</div><div class="line"><a name="l00005"></a><span class="lineno">    5</span>&#160; &quot;cache-reuse&quot;: &quot;1&quot;,         # allow reuse at client at all</div><div class="line"><a name="l00006"></a><span class="lineno">    6</span>&#160; &quot;cache-revalidate&quot;: &quot;1&quot;,    # check it with server each time</div><div class="line"><a name="l00007"></a><span class="lineno">    7</span>&#160; &quot;cache-intermediaries&quot;: &quot;1&quot; # allow intermediary caches to hold</div><div class="line"><a name="l00008"></a><span class="lineno">    8</span>&#160;}</div></div><!-- fragment --><p>6) You can also define a list of additional mimetypes per-mount </p><div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno">    1</span>&#160;&quot;extra-mimetypes&quot;: {</div><div class="line"><a name="l00002"></a><span class="lineno">    2</span>&#160;         &quot;.zip&quot;: &quot;application/zip&quot;,</div><div class="line"><a name="l00003"></a><span class="lineno">    3</span>&#160;         &quot;.doc&quot;: &quot;text/evil&quot;</div><div class="line"><a name="l00004"></a><span class="lineno">    4</span>&#160; }</div></div><!-- fragment --><h1><a class="anchor" id="lwswspl"></a>
+<p>5) Cache policy of the files in the mount can also be set. If no options are given, the content is marked uncacheable. </p><div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno">    1</span>&#160;{</div><div class="line"><a name="l00002"></a><span class="lineno">    2</span>&#160; &quot;mountpoint&quot;: &quot;/&quot;,</div><div class="line"><a name="l00003"></a><span class="lineno">    3</span>&#160; &quot;origin&quot;: &quot;file:///var/www/mysite.com&quot;,</div><div class="line"><a name="l00004"></a><span class="lineno">    4</span>&#160; &quot;cache-max-age&quot;: &quot;60&quot;,      # seconds</div><div class="line"><a name="l00005"></a><span class="lineno">    5</span>&#160; &quot;cache-reuse&quot;: &quot;1&quot;,         # allow reuse at client at all</div><div class="line"><a name="l00006"></a><span class="lineno">    6</span>&#160; &quot;cache-revalidate&quot;: &quot;1&quot;,    # check it with server each time</div><div class="line"><a name="l00007"></a><span class="lineno">    7</span>&#160; &quot;cache-intermediaries&quot;: &quot;1&quot; # allow intermediary caches to hold</div><div class="line"><a name="l00008"></a><span class="lineno">    8</span>&#160;}</div></div><!-- fragment --><p>6) You can also define a list of additional mimetypes per-mount </p><div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno">    1</span>&#160;&quot;extra-mimetypes&quot;: {</div><div class="line"><a name="l00002"></a><span class="lineno">    2</span>&#160;         &quot;.zip&quot;: &quot;application/zip&quot;,</div><div class="line"><a name="l00003"></a><span class="lineno">    3</span>&#160;         &quot;.doc&quot;: &quot;text/evil&quot;</div><div class="line"><a name="l00004"></a><span class="lineno">    4</span>&#160; }</div></div><!-- fragment --><p>Normally a file suffix MUST match one of the canned mimetypes or one of the extra mimetypes, or the file is not served. This adds a little bit of security because even if there is a bug somewhere and the mount dirs are circumvented, lws will not serve, eg, /etc/passwd.</p>
+<p>If you provide an extra mimetype entry </p><pre class="fragment">                    "*": ""
+</pre><p>Then any file is served, if the mimetype was not known then it is served without a Content-Type: header.</p>
+<h1><a class="anchor" id="lwswspl"></a>
 Lwsws Plugins</h1>
 <p>Protcols and extensions may also be provided from "plugins", these are lightweight dynamic libraries. They are scanned for at init time, and any protocols and extensions found are added to the list given at context creation time.</p>
 <p>Protocols receive init (LWS_CALLBACK_PROTOCOL_INIT) and destruction (LWS_CALLBACK_PROTOCOL_DESTROY) callbacks per-vhost, and there are arrangements they can make per-vhost allocations and get hold of the correct pointer from the wsi at the callback.</p>
index 66e3035..480824d 100644 (file)
@@ -325,6 +325,9 @@ lws_get_mimetype(const char *file, const struct lws_http_mount *m)
                return "application/xml";
 
        while (pvo) {
+               if (pvo->name[0] == '*') /* ie, match anything */
+                       return pvo->value;
+
                if (!strcmp(&file[n - strlen(pvo->name)], pvo->name))
                        return pvo->value;
 
@@ -430,8 +433,10 @@ lws_http_serve(struct lws *wsi, char *uri, const char *origin,
        mimetype = lws_get_mimetype(path, m);
        if (!mimetype) {
                lwsl_err("unknown mimetype for %s\n", path);
-               goto bail;
+               goto bail;
        }
+       if (!mimetype[0])
+               lwsl_debug("sending no mimetype for %s\n", path);
 
        wsi->sending_chunked = 0;
 
@@ -1958,10 +1963,12 @@ lws_serve_http_file(struct lws *wsi, const char *file, const char *content_type,
 
        if (lws_add_http_header_status(wsi, 200, &p, end))
                return -1;
-       if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
-                                        (unsigned char *)content_type,
-                                        strlen(content_type), &p, end))
-               return -1;
+       if (content_type && content_type[0]) {
+               if (lws_add_http_header_by_token(wsi, WSI_TOKEN_HTTP_CONTENT_TYPE,
+                                                (unsigned char *)content_type,
+                                                strlen(content_type), &p, end))
+                       return -1;
+       }
 
        if (!wsi->sending_chunked) {
                if (lws_add_http_header_content_length(wsi, wsi->u.http.filelen, &p, end))