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
------------------------------
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;
}
if (vhost)
wsi->vhost = vhost;
- }
+ } else
+ lwsl_info("no host\n");
wsi->vhost->trans++;
if (!wsi->conn_stat_done) {