diff --git a/src/cfgfile.c b/src/cfgfile.c index e3a426ff..29477649 100644 --- a/src/cfgfile.c +++ b/src/cfgfile.c @@ -616,6 +616,7 @@ listener_t *config_clear_listener(listener_t *listener) if (listener->on_behalf_of) free(listener->on_behalf_of); if (listener->bind_address) xmlFree(listener->bind_address); if (listener->shoutcast_mount) xmlFree(listener->shoutcast_mount); + if (listener->authstack) auth_stack_release(listener->authstack); free (listener); } return next; @@ -1187,6 +1188,34 @@ static void _parse_limits(xmlDocPtr doc, } while ((node = node->next)); } +static void _parse_authentication_node(xmlNodePtr node, auth_stack_t **authstack) +{ + xmlChar *tmp; + + if (xmlStrcmp(node->name, XMLSTR("authentication")) != 0) + return; + + tmp = xmlGetProp(node, XMLSTR("type")); + if (tmp) { + ICECAST_LOG_ERROR("new style parser called on old style config."); + xmlFree(tmp); + return; + } + + xmlNodePtr child = node->xmlChildrenNode; + do { + if (child == NULL) + break; + if (xmlIsBlankNode(child)) + continue; + if (xmlStrcmp(child->name, XMLSTR("role")) == 0) { + auth_t *auth = auth_get_authenticator(child); + auth_stack_push(authstack, auth); + auth_release(auth); + } + } while ((child = child->next)); +} + static void _parse_mount_oldstyle_authentication(mount_proxy *mount, xmlNodePtr node, auth_stack_t **authstack) @@ -1473,18 +1502,7 @@ static void _parse_mount(xmlDocPtr doc, xmlFree(tmp); _parse_mount_oldstyle_authentication(mount, node, &authstack); } else { - xmlNodePtr child = node->xmlChildrenNode; - do { - if (child == NULL) - break; - if (xmlIsBlankNode(child)) - continue; - if (xmlStrcmp(child->name, XMLSTR("role")) == 0) { - auth_t *auth = auth_get_authenticator(child); - auth_stack_push(&authstack, auth); - auth_release(auth); - } - } while ((child = child->next)); + _parse_authentication_node(node, &authstack); } } else if (xmlStrcmp(node->name, XMLSTR("on-connect")) == 0) { tmp = (char *)xmlNodeListGetString(doc, node->xmlChildrenNode, 1); @@ -1893,6 +1911,8 @@ static void _parse_listen_socket(xmlDocPtr doc, node->xmlChildrenNode, 1); } else if (xmlStrcmp(node->name, XMLSTR("so-sndbuf")) == 0) { __read_int(doc, node, &listener->so_sndbuf, " must not be empty."); + } else if (xmlStrcmp(node->name, XMLSTR("authentication")) == 0) { + _parse_authentication_node(node, &(listener->authstack)); } } while ((node = node->next)); @@ -2613,5 +2633,9 @@ listener_t *config_copy_listener_one(const listener_t *listener) { n->shoutcast_mount = (char*)xmlStrdup(XMLSTR(listener->shoutcast_mount)); n->tls = listener->tls; + if (listener->authstack) { + auth_stack_addref(n->authstack = listener->authstack); + } + return n; } diff --git a/src/cfgfile.h b/src/cfgfile.h index f83ac78d..35a2e6e2 100644 --- a/src/cfgfile.h +++ b/src/cfgfile.h @@ -165,6 +165,7 @@ typedef struct _listener_t { int shoutcast_compat; char *shoutcast_mount; tlsmode_t tls; + auth_stack_t *authstack; } listener_t; typedef struct _config_tls_context { diff --git a/src/connection.c b/src/connection.c index 0abf4e31..b56bd5dc 100644 --- a/src/connection.c +++ b/src/connection.c @@ -1411,16 +1411,46 @@ static void _handle_authentication_mount_default(client_t *client, void *uri, au _handle_authentication_mount_generic(client, uri, MOUNT_TYPE_DEFAULT, _handle_authentication_global); } -static void _handle_authentication_mount_normal(client_t *client, char *uri) +static void _handle_authentication_mount_normal(client_t *client, void *uri, auth_result result) { + auth_stack_release(client->authstack); + client->authstack = NULL; + + if (result != AUTH_NOMATCH && + !(result == AUTH_OK && client->admin_command != ADMIN_COMMAND_ERROR && acl_test_admin(client->acl, client->admin_command) == ACL_POLICY_DENY)) { + _handle_authed_client(client, uri, result); + return; + } + ICECAST_LOG_DEBUG("Trying specific authenticators for client %p.", client); _handle_authentication_mount_generic(client, uri, MOUNT_TYPE_NORMAL, _handle_authentication_mount_default); } +static void _handle_authentication_listen_socket(client_t *client, char *uri) +{ + auth_stack_t *stack = NULL; + const listener_t *listener; + + listener = listensocket_get_listener(client->con->listensocket_effective); + if (listener) { + if (listener->authstack) { + auth_stack_addref(stack = listener->authstack); + } + listensocket_release_listener(client->con->listensocket_effective); + } + + if (stack) { + auth_stack_add_client(stack, client, _handle_authentication_mount_normal, uri); + auth_stack_release(stack); + } else { + _handle_authentication_mount_normal(client, uri, AUTH_NOMATCH); + } +} + static void _handle_authentication(client_t *client, char *uri) { fastevent_emit(FASTEVENT_TYPE_CLIENT_READY_FOR_AUTH, FASTEVENT_FLAG_MODIFICATION_ALLOWED, FASTEVENT_DATATYPE_CLIENT, client); - _handle_authentication_mount_normal(client, uri); + _handle_authentication_listen_socket(client, uri); } static void __prepare_shoutcast_admin_cgi_request(client_t *client)