diff options
author | Jason Parker <jparker@digium.com> | 2013-07-12 17:52:52 +0000 |
---|---|---|
committer | Jason Parker <jparker@digium.com> | 2013-07-12 17:52:52 +0000 |
commit | 2bad69006f8ea6bec50c94e8e1ec90a6684ef9ab (patch) | |
tree | 1f36d11ae2113ef78a9ce1bf816186c18dafcb2a /res | |
parent | f5a1058316c1529f11dc22562286afa39fe78eec (diff) |
ARI: Add support for Cross-Origin Resource Sharing (CORS), origin headers
This rejects requests from any unknown origins.
(closes issue ASTERISK-21278)
Review: https://reviewboard.asterisk.org/r/2667/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@394189 65c4cc65-6c06-0410-ace0-fbb531ad65f3
Diffstat (limited to 'res')
-rw-r--r-- | res/res_stasis_http.c | 53 | ||||
-rw-r--r-- | res/stasis_http/cli.c | 1 | ||||
-rw-r--r-- | res/stasis_http/config.c | 10 | ||||
-rw-r--r-- | res/stasis_http/internal.h | 4 |
4 files changed, 53 insertions, 15 deletions
diff --git a/res/res_stasis_http.c b/res/res_stasis_http.c index 7cd92f48f..e9dab79f5 100644 --- a/res/res_stasis_http.c +++ b/res/res_stasis_http.c @@ -293,6 +293,26 @@ static void add_allow_header(struct stasis_rest_handlers *handler, ast_str_append(&response->headers, 0, "\r\n"); } +static int origin_allowed(const char *origin) +{ + RAII_VAR(struct ari_conf *, cfg, ari_config_get(), ao2_cleanup); + + char *allowed = ast_strdupa(cfg->general->allowed_origins); + char *current; + + while ((current = strsep(&allowed, ","))) { + if (!strcmp(current, "*")) { + return 1; + } + + if (!strcmp(current, origin)) { + return 1; + } + } + + return 0; +} + #define ACR_METHOD "Access-Control-Request-Method" #define ACR_HEADERS "Access-Control-Request-Headers" #define ACA_METHODS "Access-Control-Allow-Methods" @@ -333,7 +353,7 @@ static void handle_options(struct stasis_rest_handlers *handler, } /* CORS 6.2, #1 - "If the Origin header is not present terminate this - * set of steps. + * set of steps." */ if (origin == NULL) { return; @@ -343,14 +363,16 @@ static void handle_options(struct stasis_rest_handlers *handler, * case-sensitive match for any of the values in list of origins do not * set any additional headers and terminate this set of steps. * - * "Always matching is acceptable since the list of origins can be + * Always matching is acceptable since the list of origins can be * unbounded. * - * "The Origin header can only contain a single origin as the user agent - * will not follow redirects. - * - * TODO - pull list of allowed origins from config + * The Origin header can only contain a single origin as the user agent + * will not follow redirects." */ + if (!origin_allowed(origin)) { + ast_log(LOG_NOTICE, "Origin header '%s' does not match an allowed origin.\n", origin); + return; + } /* CORS 6.2, #3 - "If there is no Access-Control-Request-Method header * or if parsing failed, do not set any additional headers and terminate @@ -397,7 +419,7 @@ static void handle_options(struct stasis_rest_handlers *handler, * case-insensitive match for any of the values in list of headers do * not set any additional headers and terminate this set of steps. * - * "Note: Always matching is acceptable since the list of headers can be + * Note: Always matching is acceptable since the list of headers can be * unbounded." */ @@ -423,7 +445,7 @@ static void handle_options(struct stasis_rest_handlers *handler, /* CORS 6.2, #10 - "Add one or more Access-Control-Allow-Headers headers * consisting of (a subset of) the list of headers. * - * "Since the list of headers can be unbounded simply returning headers + * Since the list of headers can be unbounded simply returning headers * can be enough." */ if (!ast_strlen_zero(acr_headers)) { @@ -700,25 +722,26 @@ static void process_cors_request(struct ast_variable *headers, * case-sensitive match for any of the values in list of origins, do not * set any additional headers and terminate this set of steps. * - * "Note: Always matching is acceptable since the list of origins can be + * Note: Always matching is acceptable since the list of origins can be * unbounded." - * - * TODO - pull list of allowed origins from config */ + if (!origin_allowed(origin)) { + ast_log(LOG_NOTICE, "Origin header '%s' does not match an allowed origin.\n", origin); + return; + } /* CORS 6.1, #3 - "If the resource supports credentials add a single * Access-Control-Allow-Origin header, with the value of the Origin * header as value, and add a single Access-Control-Allow-Credentials * header with the case-sensitive string "true" as value. * - * "Otherwise, add a single Access-Control-Allow-Origin header, with + * Otherwise, add a single Access-Control-Allow-Origin header, with * either the value of the Origin header or the string "*" as value." - * - * TODO - when we add authentication, this will change to - * Access-Control-Allow-Credentials. */ ast_str_append(&response->headers, 0, "Access-Control-Allow-Origin: %s\r\n", origin); + ast_str_append(&response->headers, 0, + "Access-Control-Allow-Credentials: true\r\n"); /* CORS 6.1, #4 - "If the list of exposed headers is not empty add one * or more Access-Control-Expose-Headers headers, with as values the diff --git a/res/stasis_http/cli.c b/res/stasis_http/cli.c index 98d082b2c..ac974dc14 100644 --- a/res/stasis_http/cli.c +++ b/res/stasis_http/cli.c @@ -71,6 +71,7 @@ static char *ari_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a) } ast_cli(a->fd, "\n"); ast_cli(a->fd, "Auth realm: %s\n", conf->general->auth_realm); + ast_cli(a->fd, "Allowed Origins: %s\n", conf->general->allowed_origins); ast_cli(a->fd, "User count: %d\n", ao2_container_count(conf->users)); return CLI_SUCCESS; } diff --git a/res/stasis_http/config.c b/res/stasis_http/config.c index 2181907d5..7ccfe8e59 100644 --- a/res/stasis_http/config.c +++ b/res/stasis_http/config.c @@ -158,6 +158,9 @@ static struct aco_type *user[] = ACO_TYPES(&user_option); static void conf_destructor(void *obj) { struct ari_conf *cfg = obj; + + ast_string_field_free_memory(cfg->general); + ao2_cleanup(cfg->general); ao2_cleanup(cfg->users); } @@ -180,6 +183,10 @@ static void *conf_alloc(void) } aco_set_defaults(&general_option, "general", cfg->general); + if (ast_string_field_init(cfg->general, 64)) { + return NULL; + } + cfg->users = ao2_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_NOLOCK, AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE, user_sort_cmp, NULL); @@ -308,6 +315,9 @@ int ari_config_init(void) "Asterisk REST Interface", OPT_CHAR_ARRAY_T, 0, FLDSET(struct ari_conf_general, auth_realm), ARI_AUTH_REALM_LEN); + aco_option_register(&cfg_info, "allowed_origins", ACO_EXACT, general_options, + "", OPT_STRINGFIELD_T, 0, + STRFLDSET(struct ari_conf_general, allowed_origins)); aco_option_register(&cfg_info, "type", ACO_EXACT, user, NULL, OPT_NOOP_T, 0, 0); diff --git a/res/stasis_http/internal.h b/res/stasis_http/internal.h index 659f4a2ae..7cc67cfbf 100644 --- a/res/stasis_http/internal.h +++ b/res/stasis_http/internal.h @@ -67,6 +67,10 @@ struct ari_conf_general { enum ast_json_encoding_format format; /*! Authentication realm */ char auth_realm[ARI_AUTH_REALM_LEN]; + + AST_DECLARE_STRING_FIELDS( + AST_STRING_FIELD(allowed_origins); + ); }; /*! \brief Password format */ |