mirror of
https://github.com/warmcat/libwebsockets.git
synced 2025-03-09 00:00:04 +01:00
SNI-vhost-matching-fallback-to-wildcard
This commit is contained in:
parent
5ab523ec3f
commit
5f73048d58
3 changed files with 59 additions and 2 deletions
|
@ -534,6 +534,25 @@ There are some new members but mainly it's stuff you used to set at
|
|||
context creation time.
|
||||
|
||||
|
||||
How lws matches hostname or SNI to a vhost
|
||||
------------------------------------------
|
||||
|
||||
LWS first strips any trailing :port number.
|
||||
|
||||
Then it tries to find an exact name match for a vhost listening on the correct
|
||||
port, ie, if SNI or the Host: header provided abc.com:1234, it will match on a
|
||||
vhost named abc.com that is listening on port 1234.
|
||||
|
||||
If there is no exact match, lws will consider wildcard matches, for example
|
||||
if cats.abc.com:1234 is provided by the client by SNI or Host: header, it will
|
||||
accept a vhost "abc.com" listening on port 1234. If there was a better, exact,
|
||||
match, it will have been chosen in preference to this.
|
||||
|
||||
Connections with SSL will still have the client go on to check the
|
||||
certificate allows wildcards and error out if not.
|
||||
|
||||
|
||||
|
||||
Using lws v2 mounts on a vhost
|
||||
------------------------------
|
||||
|
||||
|
|
|
@ -197,6 +197,11 @@ space" as a virtual filesystem that may or may not be backed by a regular filesy
|
|||
<div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno"> 1</span> LWS_VISIBLE struct lws_vhost *</div><div class="line"><a name="l00002"></a><span class="lineno"> 2</span> lws_create_vhost(struct lws_context *context,</div><div class="line"><a name="l00003"></a><span class="lineno"> 3</span>  struct lws_context_creation_info *info,</div><div class="line"><a name="l00004"></a><span class="lineno"> 4</span>  struct lws_http_mount *mounts);</div></div><!-- fragment --><p><a class="el" href="group__context-and-vhost.html#ga0c54c667ccd9b8b3dddcd123ca72f87c">lws_create_vhost()</a> uses the same info struct as <a class="el" href="group__context-and-vhost.html#gaf2fff58562caab7510c41eeac85a8648">lws_create_context()</a>, it ignores members related to context and uses the ones meaningful for vhost (marked with VH in <a class="el" href="libwebsockets_8h.html">libwebsockets.h</a>).</p>
|
||||
<div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno"> 1</span> struct lws_context_creation_info {</div><div class="line"><a name="l00002"></a><span class="lineno"> 2</span>  int port; /* VH */</div><div class="line"><a name="l00003"></a><span class="lineno"> 3</span>  const char *iface; /* VH */</div><div class="line"><a name="l00004"></a><span class="lineno"> 4</span>  const struct lws_protocols *protocols; /* VH */</div><div class="line"><a name="l00005"></a><span class="lineno"> 5</span>  const struct lws_extension *extensions; /* VH */</div><div class="line"><a name="l00006"></a><span class="lineno"> 6</span> ...</div></div><!-- fragment --><p>When you attach the vhost, if the vhost's port already has a listen socket then both vhosts share it and use SNI (is SSL in use) or the Host: header from the client to select the right one. Or if no other vhost already listening the a new listen socket is created.</p>
|
||||
<p>There are some new members but mainly it's stuff you used to set at context creation time.</p>
|
||||
<h2>How lws matches hostname or SNI to a vhost </h2>
|
||||
<p>LWS first strips any trailing :port number.</p>
|
||||
<p>Then it tries to find an exact name match for a vhost listening on the correct port, ie, if SNI or the Host: header provided abc.com:1234, it will match on a vhost named abc.com that is listening on port 1234.</p>
|
||||
<p>If there is no exact match, lws will consider wildcard matches, for example if cats.abc.com:1234 is provided by the client by SNI or Host: header, it will accept a vhost "abc.com" listening on port 1234. If there was a better, exact, match, it will have been chosen in preference to this.</p>
|
||||
<p>Connections with SSL will still have the client go on to check the certificate allows wildcards and error out if not.</p>
|
||||
<h2>Using lws v2 mounts on a vhost </h2>
|
||||
<p>The last argument to <a class="el" href="group__context-and-vhost.html#ga0c54c667ccd9b8b3dddcd123ca72f87c">lws_create_vhost()</a> lets you associate a linked list of <a class="el" href="structlws__http__mount.html">lws_http_mount</a> structures with that vhost's URL 'namespace', in a similar way that unix lets you mount filesystems into areas of your / filesystem how you like and deal with the contents transparently.</p>
|
||||
<div class="fragment"><div class="line"><a name="l00001"></a><span class="lineno"> 1</span> struct lws_http_mount {</div><div class="line"><a name="l00002"></a><span class="lineno"> 2</span>  struct lws_http_mount *mount_next;</div><div class="line"><a name="l00003"></a><span class="lineno"> 3</span>  const char *mountpoint; /* mountpoint in http pathspace, eg, "/" */</div><div class="line"><a name="l00004"></a><span class="lineno"> 4</span>  const char *origin; /* path to be mounted, eg, "/var/www/warmcat.com" */</div><div class="line"><a name="l00005"></a><span class="lineno"> 5</span>  const char *def; /* default target, eg, "index.html" */</div><div class="line"><a name="l00006"></a><span class="lineno"> 6</span> </div><div class="line"><a name="l00007"></a><span class="lineno"> 7</span>  struct lws_protocol_vhost_options *cgienv;</div><div class="line"><a name="l00008"></a><span class="lineno"> 8</span> </div><div class="line"><a name="l00009"></a><span class="lineno"> 9</span>  int cgi_timeout;</div><div class="line"><a name="l00010"></a><span class="lineno"> 10</span>  int cache_max_age;</div><div class="line"><a name="l00011"></a><span class="lineno"> 11</span> </div><div class="line"><a name="l00012"></a><span class="lineno"> 12</span>  unsigned int cache_reusable:1;</div><div class="line"><a name="l00013"></a><span class="lineno"> 13</span>  unsigned int cache_revalidate:1;</div><div class="line"><a name="l00014"></a><span class="lineno"> 14</span>  unsigned int cache_intermediaries:1;</div><div class="line"><a name="l00015"></a><span class="lineno"> 15</span> </div><div class="line"><a name="l00016"></a><span class="lineno"> 16</span>  unsigned char origin_protocol;</div><div class="line"><a name="l00017"></a><span class="lineno"> 17</span>  unsigned char mountpoint_len;</div><div class="line"><a name="l00018"></a><span class="lineno"> 18</span> };</div></div><!-- fragment --><p>The last mount structure should have a NULL mount_next, otherwise it should point to the 'next' mount structure in your list.</p>
|
||||
|
|
37
lib/server.c
37
lib/server.c
|
@ -193,16 +193,48 @@ struct lws_vhost *
|
|||
lws_select_vhost(struct lws_context *context, int port, const char *servername)
|
||||
{
|
||||
struct lws_vhost *vhost = context->vhost_list;
|
||||
const char *p;
|
||||
int n, m, colon;
|
||||
|
||||
n = strlen(servername);
|
||||
colon = n;
|
||||
p = strchr(servername, ':');
|
||||
if (p)
|
||||
colon = p - servername;
|
||||
|
||||
/* first try exact matches */
|
||||
|
||||
while (vhost) {
|
||||
if (port == vhost->listen_port &&
|
||||
!strcmp(vhost->name, servername)) {
|
||||
!strncmp(vhost->name, servername, colon)) {
|
||||
lwsl_info("SNI: Found: %s\n", servername);
|
||||
return vhost;
|
||||
}
|
||||
vhost = vhost->vhost_next;
|
||||
}
|
||||
|
||||
/*
|
||||
* if no exact matches, try matching *.vhost-name
|
||||
* unintentional matches are possible but resolve to x.com for *.x.com
|
||||
* which is reasonable. If exact match exists we already chose it and
|
||||
* never reach here. SSL will still fail it if the cert doesn't allow
|
||||
* *.x.com.
|
||||
*/
|
||||
|
||||
vhost = context->vhost_list;
|
||||
while (vhost) {
|
||||
m = strlen(vhost->name);
|
||||
if (port == vhost->listen_port &&
|
||||
m <= (colon - 2) &&
|
||||
servername[colon - m - 1] == '.' &&
|
||||
!strncmp(vhost->name, servername + colon - m, m)) {
|
||||
lwsl_info("SNI: Found %s on wildcard: %s\n",
|
||||
servername, vhost->name);
|
||||
return vhost;
|
||||
}
|
||||
vhost = vhost->vhost_next;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -990,7 +1022,8 @@ lws_handshake_server(struct lws *wsi, unsigned char **buf, size_t len)
|
|||
|
||||
if (vhost)
|
||||
wsi->vhost = vhost;
|
||||
}
|
||||
} else
|
||||
lwsl_info("no host\n");
|
||||
|
||||
wsi->vhost->trans++;
|
||||
if (!wsi->conn_stat_done) {
|
||||
|
|
Loading…
Add table
Reference in a new issue