mirror of
https://github.com/unrealircd/unrealircd.git
synced 2026-07-04 20:03:12 +02:00
Add an option to check websocket Origin header via
listen {
websocket {
allow-origin { *.example.net; }
}
}
This allows you to limit websockets to a particular domain, IF the
user is using a normal browser.
Note that any non-browser (eg a websocket command line program) could
just spoof the Origin header, so for that case it doesn't really add
any security or real restriction.
This commit is contained in:
@@ -1993,6 +1993,7 @@ struct ConfigItem_listen {
|
||||
WebServer *webserver; /**< For the webserver module */
|
||||
void (*start_handshake)(Client *client); /**< Function to call on accept() */
|
||||
int websocket_options; /**< Websocket options (for the websocket module) */
|
||||
NameList *websocket_origin; /**< List of permitted Origin */
|
||||
int rpc_options; /**< For the RPC module */
|
||||
};
|
||||
|
||||
|
||||
+5
-1
@@ -5325,7 +5325,9 @@ void conf_listen_configure(const char *ip, int port, SocketType socket_type, int
|
||||
free_tls_options(listen->tls_options);
|
||||
listen->tls_options = NULL;
|
||||
}
|
||||
safe_free(listen->webserver);
|
||||
safe_free_webserver(listen->webserver);
|
||||
free_entire_name_list(listen->websocket_origin);
|
||||
// NOTE: duplicate code overlap with listen_cleanup()
|
||||
|
||||
/* Now set the new settings: */
|
||||
if (tlsconfig)
|
||||
@@ -11268,6 +11270,8 @@ void listen_cleanup()
|
||||
free_tls_options(listener->tls_options);
|
||||
/* listener->ssl_ctx is already freed by close_listener() */
|
||||
safe_free_webserver(listener->webserver);
|
||||
free_entire_name_list(listener->websocket_origin);
|
||||
// NOTE: duplicate code overlap with conf_listen_configure() - but not 100% identical
|
||||
safe_free(listener);
|
||||
} else {
|
||||
/* Still has clients */
|
||||
|
||||
@@ -143,6 +143,8 @@ int websocket_config_test(ConfigFile *cf, ConfigEntry *ce, int type, int *errs)
|
||||
"See https://www.unrealircd.org/docs/Proxy_block",
|
||||
cep->file->filename, cep->line_number);
|
||||
errors++;
|
||||
} else if (!strcmp(cep->name, "allow-origin"))
|
||||
{
|
||||
} else
|
||||
{
|
||||
config_error("%s:%i: unknown directive listen::options::websocket::%s",
|
||||
@@ -201,6 +203,10 @@ int websocket_config_run_ex(ConfigFile *cf, ConfigEntry *ce, int type, void *ptr
|
||||
warned_once_channel = 1;
|
||||
}
|
||||
}
|
||||
} else if (!strcmp(cep->name, "allow-origin"))
|
||||
{
|
||||
for (cepp = cep->items; cepp; cepp = cepp->next)
|
||||
add_name_list(l->websocket_origin, cepp->name);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
@@ -350,6 +356,32 @@ int websocket_handle_request(Client *client, WebRequest *web)
|
||||
}
|
||||
|
||||
/** Finally, validate the websocket request (handshake) and proceed or reject. */
|
||||
if (client->local->listener->websocket_origin)
|
||||
{
|
||||
const char *origin = get_nvplist(web->headers, "Origin");
|
||||
char origin_host[256];
|
||||
|
||||
*origin_host = '\0';
|
||||
if (origin)
|
||||
{
|
||||
char *start = strstr(origin, "://");
|
||||
char *p;
|
||||
if (start)
|
||||
{
|
||||
start += 3;
|
||||
p = strchr(start, '/');
|
||||
if (p)
|
||||
strlncpy(origin_host, start, sizeof(origin_host), p - start);
|
||||
else
|
||||
strlcpy(origin_host, start, sizeof(origin_host));
|
||||
}
|
||||
}
|
||||
if (!find_name_list_match(client->local->listener->websocket_origin, origin_host))
|
||||
{
|
||||
webserver_send_response(client, 403, "This site is not permitted to connect to us with websockets");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Not websocket and webredir loaded? Let that module serve a redirect. */
|
||||
if (!WSU(client)->handshake_key)
|
||||
|
||||
Reference in New Issue
Block a user