mirror of
https://github.com/owntone/owntone-server.git
synced 2025-04-16 09:08:04 -04:00
[httpd] Implement "trusted_networks" option
Some clients aren't really capable of authenticating + some users probably don't want to enter a password for the web interface. This option allows clients on for instance the local network to connect without authentication.
This commit is contained in:
parent
6d937469f5
commit
3d5aeda7aa
@ -22,16 +22,18 @@ general {
|
|||||||
loglevel = log
|
loglevel = log
|
||||||
|
|
||||||
# Admin password for the web interface
|
# Admin password for the web interface
|
||||||
# If not set (default), access to the web interface is only permitted
|
# Note that access to the web interface from computers in
|
||||||
# from localhost (except in promiscuous mode)
|
# "trusted_network" (see below) does not require password
|
||||||
# admin_password = ""
|
# admin_password = ""
|
||||||
|
|
||||||
# Websocket port for the web interface.
|
# Websocket port for the web interface.
|
||||||
# websocket_port = 3688
|
# websocket_port = 3688
|
||||||
|
|
||||||
# Let clients connect without checking their credentials. This applies
|
# Sets who is allowed to connect without authorisation. This applies to
|
||||||
# both to Remotes, DAAP clients and the web interface.
|
# client types like Remotes, DAAP clients (iTunes) and to the web
|
||||||
# promiscuous_mode = no
|
# interface. Options are "any", "localhost" or the prefix to one or
|
||||||
|
# more ipv4/6 networks. The default is { "localhost", "192.168", "fd" }
|
||||||
|
# trusted_networks = { "localhost", "192.168", "fd" }
|
||||||
|
|
||||||
# Enable/disable IPv6
|
# Enable/disable IPv6
|
||||||
ipv6 = yes
|
ipv6 = yes
|
||||||
|
@ -50,7 +50,7 @@ static cfg_opt_t sec_general[] =
|
|||||||
CFG_INT_CB("loglevel", E_LOG, CFGF_NONE, &cb_loglevel),
|
CFG_INT_CB("loglevel", E_LOG, CFGF_NONE, &cb_loglevel),
|
||||||
CFG_STR("admin_password", NULL, CFGF_NONE),
|
CFG_STR("admin_password", NULL, CFGF_NONE),
|
||||||
CFG_INT("websocket_port", 3688, CFGF_NONE),
|
CFG_INT("websocket_port", 3688, CFGF_NONE),
|
||||||
CFG_BOOL("promiscuous_mode", cfg_false, CFGF_NONE),
|
CFG_STR_LIST("trusted_networks", "{localhost,192.168,fd}", CFGF_NONE),
|
||||||
CFG_BOOL("ipv6", cfg_true, CFGF_NONE),
|
CFG_BOOL("ipv6", cfg_true, CFGF_NONE),
|
||||||
CFG_STR("cache_path", STATEDIR "/cache/" PACKAGE "/cache.db", CFGF_NONE),
|
CFG_STR("cache_path", STATEDIR "/cache/" PACKAGE "/cache.db", CFGF_NONE),
|
||||||
CFG_INT("cache_daap_threshold", 1000, CFGF_NONE),
|
CFG_INT("cache_daap_threshold", 1000, CFGF_NONE),
|
||||||
|
78
src/httpd.c
78
src/httpd.c
@ -277,10 +277,7 @@ serve_file(struct evhttp_request *req, const char *uri)
|
|||||||
|
|
||||||
/* Check authentication */
|
/* Check authentication */
|
||||||
if (!httpd_admin_check_auth(req))
|
if (!httpd_admin_check_auth(req))
|
||||||
{
|
|
||||||
DPRINTF(E_DBG, L_HTTPD, "Remote web interface request denied;\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
ret = snprintf(path, sizeof(path), "%s%s", WEB_ROOT, uri);
|
ret = snprintf(path, sizeof(path), "%s%s", WEB_ROOT, uri);
|
||||||
if ((ret < 0) || (ret >= sizeof(path)))
|
if ((ret < 0) || (ret >= sizeof(path)))
|
||||||
@ -1403,40 +1400,79 @@ httpd_redirect_to_index(struct evhttp_request *req, const char *uri)
|
|||||||
httpd_send_reply(req, HTTP_MOVETEMP, "Moved", NULL, HTTPD_SEND_NO_GZIP);
|
httpd_send_reply(req, HTTP_MOVETEMP, "Moved", NULL, HTTPD_SEND_NO_GZIP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
httpd_peer_is_trusted(struct evhttp_request *req)
|
||||||
|
{
|
||||||
|
struct evhttp_connection *evcon;
|
||||||
|
cfg_t *section;
|
||||||
|
const char *network;
|
||||||
|
char *addr;
|
||||||
|
uint16_t port;
|
||||||
|
int i;
|
||||||
|
int n;
|
||||||
|
|
||||||
|
evcon = evhttp_request_get_connection(req);
|
||||||
|
if (!evcon)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_HTTPD, "Connection to client lost or missing\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
evhttp_connection_get_peer(evcon, &addr, &port);
|
||||||
|
if (strncmp(addr, "::ffff:", strlen("::ffff:")) == 0)
|
||||||
|
addr += strlen("::ffff:");
|
||||||
|
|
||||||
|
section = cfg_getsec(cfg, "general");
|
||||||
|
|
||||||
|
n = cfg_size(section, "trusted_networks");
|
||||||
|
for (i = 0; i < n; i++)
|
||||||
|
{
|
||||||
|
network = cfg_getnstr(section, "trusted_networks", i);
|
||||||
|
|
||||||
|
if (strncmp(network, addr, strlen(network)) == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if ((strcmp(network, "localhost") == 0) && (strcmp(addr, "127.0.0.1") == 0 || strcmp(addr, "::1") == 0))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
if (strcmp(network, "any") == 0)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
httpd_admin_check_auth(struct evhttp_request *req)
|
httpd_admin_check_auth(struct evhttp_request *req)
|
||||||
{
|
{
|
||||||
const char *host;
|
|
||||||
const char *passwd;
|
const char *passwd;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (cfg_getbool(cfg_getsec(cfg, "general"), "promiscuous_mode"))
|
if (httpd_peer_is_trusted(req))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
passwd = cfg_getstr(cfg_getsec(cfg, "general"), "admin_password");
|
passwd = cfg_getstr(cfg_getsec(cfg, "general"), "admin_password");
|
||||||
if (passwd)
|
if (!passwd)
|
||||||
{
|
{
|
||||||
DPRINTF(E_DBG, L_HTTPD, "Checking web interface authentication\n");
|
DPRINTF(E_LOG, L_HTTPD, "Web interface request to '%s' denied: No password set in the config\n", evhttp_request_get_uri(req));
|
||||||
|
|
||||||
ret = httpd_basic_auth(req, "admin", passwd, PACKAGE " web interface");
|
|
||||||
if (ret != 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
DPRINTF(E_DBG, L_HTTPD, "Authentication successful\n");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
host = evhttp_request_get_host(req);
|
|
||||||
if ((strcmp(host, "::1") != 0)
|
|
||||||
&& (strcmp(host, "127.0.0.1") != 0))
|
|
||||||
{
|
|
||||||
DPRINTF(E_LOG, L_HTTPD, "Remote web interface request denied; no password set\n");
|
|
||||||
|
|
||||||
httpd_send_error(req, 403, "Forbidden");
|
httpd_send_error(req, 403, "Forbidden");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DPRINTF(E_DBG, L_HTTPD, "Checking web interface authentication\n");
|
||||||
|
|
||||||
|
ret = httpd_basic_auth(req, "admin", passwd, PACKAGE " web interface");
|
||||||
|
if (ret != 0)
|
||||||
|
{
|
||||||
|
DPRINTF(E_LOG, L_HTTPD, "Web interface request to '%s' denied: Incorrect password\n", evhttp_request_get_uri(req));
|
||||||
|
|
||||||
|
// httpd_basic_auth has sent a reply
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DPRINTF(E_DBG, L_HTTPD, "Authentication successful\n");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,12 +147,15 @@ httpd_redirect_to_admin(struct evhttp_request *req);
|
|||||||
void
|
void
|
||||||
httpd_redirect_to_index(struct evhttp_request *req, const char *uri);
|
httpd_redirect_to_index(struct evhttp_request *req, const char *uri);
|
||||||
|
|
||||||
int
|
bool
|
||||||
httpd_basic_auth(struct evhttp_request *req, const char *user, const char *passwd, const char *realm);
|
httpd_peer_is_trusted(struct evhttp_request *req);
|
||||||
|
|
||||||
bool
|
bool
|
||||||
httpd_admin_check_auth(struct evhttp_request *req);
|
httpd_admin_check_auth(struct evhttp_request *req);
|
||||||
|
|
||||||
|
int
|
||||||
|
httpd_basic_auth(struct evhttp_request *req, const char *user, const char *passwd, const char *realm);
|
||||||
|
|
||||||
int
|
int
|
||||||
httpd_init(void);
|
httpd_init(void);
|
||||||
|
|
||||||
|
@ -715,7 +715,7 @@ daap_request_authorize(struct httpd_request *hreq)
|
|||||||
char *passwd;
|
char *passwd;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (cfg_getbool(cfg_getsec(cfg, "general"), "promiscuous_mode"))
|
if (httpd_peer_is_trusted(hreq->req))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
param = evhttp_find_header(hreq->query, "session-id");
|
param = evhttp_find_header(hreq->query, "session-id");
|
||||||
@ -913,7 +913,7 @@ daap_reply_login(struct httpd_request *hreq)
|
|||||||
CHECK_ERR(L_DAAP, evbuffer_expand(hreq->reply, 32));
|
CHECK_ERR(L_DAAP, evbuffer_expand(hreq->reply, 32));
|
||||||
|
|
||||||
param = evhttp_find_header(hreq->query, "pairing-guid");
|
param = evhttp_find_header(hreq->query, "pairing-guid");
|
||||||
if (param && !cfg_getbool(cfg_getsec(cfg, "general"), "promiscuous_mode"))
|
if (param && !httpd_peer_is_trusted(hreq->req))
|
||||||
{
|
{
|
||||||
if (strlen(param) < 3)
|
if (strlen(param) < 3)
|
||||||
{
|
{
|
||||||
|
@ -547,7 +547,7 @@ dacp_request_authorize(struct httpd_request *hreq)
|
|||||||
int32_t id;
|
int32_t id;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (cfg_getbool(cfg_getsec(cfg, "general"), "promiscuous_mode"))
|
if (httpd_peer_is_trusted(hreq->req))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
param = evhttp_find_header(hreq->query, "session-id");
|
param = evhttp_find_header(hreq->query, "session-id");
|
||||||
@ -566,7 +566,7 @@ dacp_request_authorize(struct httpd_request *hreq)
|
|||||||
|
|
||||||
if (!daap_session_is_valid(id))
|
if (!daap_session_is_valid(id))
|
||||||
{
|
{
|
||||||
DPRINTF(E_LOG, L_DACP, "Invalid session-id (%d) specified in request\n", id);
|
DPRINTF(E_LOG, L_DACP, "Session %d does not exist\n", id);
|
||||||
goto invalid;
|
goto invalid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -519,10 +519,7 @@ jsonapi_request(struct evhttp_request *req, struct httpd_uri_parsed *uri_parsed)
|
|||||||
DPRINTF(E_DBG, L_WEB, "JSON api request: '%s'\n", uri_parsed->uri);
|
DPRINTF(E_DBG, L_WEB, "JSON api request: '%s'\n", uri_parsed->uri);
|
||||||
|
|
||||||
if (!httpd_admin_check_auth(req))
|
if (!httpd_admin_check_auth(req))
|
||||||
{
|
|
||||||
DPRINTF(E_DBG, L_WEB, "JSON api request denied\n");
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
hreq = httpd_request_parse(req, uri_parsed, NULL, adm_handlers);
|
hreq = httpd_request_parse(req, uri_parsed, NULL, adm_handlers);
|
||||||
if (!hreq)
|
if (!hreq)
|
||||||
|
@ -284,7 +284,7 @@ rsp_request_authorize(struct httpd_request *hreq)
|
|||||||
char *passwd;
|
char *passwd;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (cfg_getbool(cfg_getsec(cfg, "general"), "promiscuous_mode"))
|
if (httpd_peer_is_trusted(hreq->req))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
passwd = cfg_getstr(cfg_getsec(cfg, "library"), "password");
|
passwd = cfg_getstr(cfg_getsec(cfg, "library"), "password");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user