diff --git a/src/auth.c b/src/auth.c index 7ddbd42b..eda1a34f 100644 --- a/src/auth.c +++ b/src/auth.c @@ -182,6 +182,8 @@ static void queue_auth_client (auth_client *auth_user) * refcounted and only actual freed after the last use */ void auth_release (auth_t *authenticator) { + size_t i; + if (authenticator == NULL) return; @@ -216,6 +218,12 @@ void auth_release (auth_t *authenticator) { free(authenticator->mount); acl_release(authenticator->acl); config_clear_http_header(authenticator->http_headers); + + for (i = 0; i < authenticator->filter_origin_len; i++) { + free(authenticator->filter_origin[i].origin); + } + free(authenticator->filter_origin); + free(authenticator); } @@ -436,6 +444,8 @@ static void *auth_run_thread (void *arg) static void auth_add_client(auth_t *auth, client_t *client, void (*on_no_match)(client_t *client, void (*on_result)(client_t *client, void *userdata, auth_result result), void *userdata), void (*on_result)(client_t *client, void *userdata, auth_result result), void *userdata) { auth_client *auth_user; auth_matchtype_t matchtype; + const char *origin; + size_t i; ICECAST_LOG_DEBUG("Trying to add client %p to auth %p's (role %s) queue.", client, auth, auth->role); @@ -455,6 +465,31 @@ static void auth_add_client(auth_t *auth, client_t *client, void (*on_no_match)( return; } + /* Filter for CORS "Origin". + * + * CORS actually knows about non-CORS requests and assigned the "null" + * location to them. + */ + origin = httpp_getvar(client->parser, "origin"); + if (!origin) + origin = "null"; + + matchtype = auth->filter_origin_policy; + for (i = 0; i < auth->filter_origin_len; i++) { + if (strcmp(auth->filter_origin[i].origin, origin) == 0) { + matchtype = auth->filter_origin[i].type; + break; + } + } + if (matchtype == AUTH_MATCHTYPE_NOMATCH) { + if (on_no_match) { + on_no_match(client, on_result, userdata); + } else if (on_result) { + on_result(client, userdata, AUTH_NOMATCH); + } + return; + } + if (client->admin_command == ADMIN_COMMAND_ERROR) { /* this is a web/ client */ matchtype = auth->filter_web_policy; @@ -612,6 +647,49 @@ static inline void auth_get_authenticator__filter_admin(auth_t *auth, xmlNodePtr } } +static inline void auth_get_authenticator__filter_origin(auth_t *auth, xmlNodePtr node, const char *name, auth_matchtype_t matchtype) +{ + char * tmp = (char*)xmlGetProp(node, XMLSTR(name)); + + if (tmp) { + char *cur = tmp; + char *next; + + while (cur) { + next = strstr(cur, ","); + if (next) { + *next = 0; + next++; + for (; *next == ' '; next++); + } + + if (strcmp(cur, "*") == 0) { + auth->filter_origin_policy = matchtype; + } else { + void *n = realloc(auth->filter_origin, (auth->filter_origin_len + 1)*sizeof(*auth->filter_origin)); + if (!n) { + ICECAST_LOG_ERROR("Can not allocate memory. BAD."); + break; + } + + auth->filter_origin = n; + auth->filter_origin[auth->filter_origin_len].type = matchtype; + auth->filter_origin[auth->filter_origin_len].origin = strdup(cur); + if (auth->filter_origin[auth->filter_origin_len].origin) { + auth->filter_origin_len++; + } else { + ICECAST_LOG_ERROR("Can not allocate memory. BAD."); + break; + } + } + + cur = next; + } + + free(tmp); + } +} + static inline void auth_get_authenticator__init_method(auth_t *auth, int *method_inited, auth_matchtype_t init_with) { size_t i; @@ -815,6 +893,10 @@ auth_t *auth_get_authenticator(xmlNodePtr node) auth_get_authenticator__filter_admin(auth, node, &filter_admin_index, "match-admin", AUTH_MATCHTYPE_MATCH); auth_get_authenticator__filter_admin(auth, node, &filter_admin_index, "nomatch-admin", AUTH_MATCHTYPE_NOMATCH); + auth->filter_origin_policy = AUTH_MATCHTYPE_MATCH; + auth_get_authenticator__filter_origin(auth, node, "match-origin", AUTH_MATCHTYPE_MATCH); + auth_get_authenticator__filter_origin(auth, node, "nomatch-origin", AUTH_MATCHTYPE_NOMATCH); + auth_get_authenticator__permission_alter(auth, node, "may-alter", AUTH_MATCHTYPE_MATCH); auth_get_authenticator__permission_alter(auth, node, "may-not-alter", AUTH_MATCHTYPE_NOMATCH); diff --git a/src/auth.h b/src/auth.h index c054a13a..91c4715c 100644 --- a/src/auth.h +++ b/src/auth.h @@ -116,6 +116,13 @@ struct auth_tag admin_command_id_t command; } filter_admin[MAX_ADMIN_COMMANDS]; + struct { + auth_matchtype_t type; + char *origin; + } *filter_origin; + size_t filter_origin_len; + auth_matchtype_t filter_origin_policy; + /* permissions */ auth_matchtype_t permission_alter[AUTH_ALTER_SEND_ERROR+1];