[svn-commits] dlee: branch dlee/ari-authn r393061 - in /team/dlee/ari-authn: configs/ main/...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Thu Jun 27 13:59:08 CDT 2013


Author: dlee
Date: Thu Jun 27 13:59:06 2013
New Revision: 393061

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=393061
Log:
Clean ups; removed allow_api_key option, because it was silly to have in the first place

Modified:
    team/dlee/ari-authn/configs/stasis_http.conf.sample
    team/dlee/ari-authn/main/features_config.c
    team/dlee/ari-authn/main/http.c
    team/dlee/ari-authn/res/res_stasis_http.c
    team/dlee/ari-authn/res/stasis_http/cli.c
    team/dlee/ari-authn/res/stasis_http/config.c
    team/dlee/ari-authn/res/stasis_http/internal.h

Modified: team/dlee/ari-authn/configs/stasis_http.conf.sample
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-authn/configs/stasis_http.conf.sample?view=diff&rev=393061&r1=393060&r2=393061
==============================================================================
--- team/dlee/ari-authn/configs/stasis_http.conf.sample (original)
+++ team/dlee/ari-authn/configs/stasis_http.conf.sample Thu Jun 27 13:59:06 2013
@@ -12,9 +12,6 @@
 ;read_only = no		; When set to yes, user is only authorized for
 ;			; read-only requests.
 ;
-;allow_api_key = no	; When set to yes, user may authenticate by appending
-;			; ?api_key=username:password to their requests.
-;
 ;password =		; Crypted or plaintext password (see password_format).
 ;
 ; password_format may be set to plain (the default) or crypt. When set to crypt,

Modified: team/dlee/ari-authn/main/features_config.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-authn/main/features_config.c?view=diff&rev=393061&r1=393060&r2=393061
==============================================================================
--- team/dlee/ari-authn/main/features_config.c (original)
+++ team/dlee/ari-authn/main/features_config.c Thu Jun 27 13:59:06 2013
@@ -1792,26 +1792,23 @@
 	ast_custom_function_unregister(&featuremap_function);
 	ast_custom_function_unregister(&feature_function);
 	ast_cli_unregister_multiple(cli_features_config, ARRAY_LEN(cli_features_config));
-	//aco_info_destroy(&cfg_info);
+	aco_info_destroy(&cfg_info);
 	ao2_global_obj_release(globals);
 }
 
 int ast_features_config_reload(void)
 {
-	//if (aco_process_config(&cfg_info, 1) == ACO_PROCESS_ERROR) {
-	//	return -1;
-	//}
+	if (aco_process_config(&cfg_info, 1) == ACO_PROCESS_ERROR) {
+		return -1;
+	}
 	return 0;
 }
 
-static int (*nowarn)(void);
-
 int ast_features_config_init(void)
 {
-	int res = 0;
-
-	//res = load_config();
-	nowarn = load_config;
+	int res;
+
+	res = load_config();
 	res |= __ast_custom_function_register(&feature_function, NULL);
 	res |= __ast_custom_function_register(&featuremap_function, NULL);
 	res |= ast_cli_register_multiple(cli_features_config, ARRAY_LEN(cli_features_config));

Modified: team/dlee/ari-authn/main/http.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-authn/main/http.c?view=diff&rev=393061&r1=393060&r2=393061
==============================================================================
--- team/dlee/ari-authn/main/http.c (original)
+++ team/dlee/ari-authn/main/http.c Thu Jun 27 13:59:06 2013
@@ -900,7 +900,8 @@
 	return auth;
 }
 
-#define BASIC_LEN 6 /*!< "Basic " */
+#define BASIC_PREFIX "Basic "
+#define BASIC_LEN 6 /*!< strlen(BASIC_PREFIX) */
 
 struct ast_http_auth *ast_http_get_auth(struct ast_variable *headers)
 {
@@ -908,7 +909,7 @@
 
 	for (v = headers; v; v = v->next) {
 		const char *base64;
-		char decoded[256];
+		char decoded[256] = {};
 		int cnt;
 		char *colon;
 
@@ -916,18 +917,30 @@
 			continue;
 		}
 
-		if (strncasecmp("Basic ", v->value, BASIC_LEN) != 0) {
-			ast_log(LOG_WARNING, "Unsuppored Authorization scheme\n");
+		if (!ast_begins_with(v->value, BASIC_PREFIX)) {
+			ast_log(LOG_DEBUG,
+				"Unsupported Authorization scheme\n");
 			continue;
 		}
 
+		/* Basic auth header parsing. RFC 2617, section 2.
+		 *   credentials = "Basic" basic-credentials
+		 *   basic-credentials = base64-user-pass
+		 *   base64-user-pass  = <base64 encoding of user-pass,
+		 *                        except not limited to 76 char/line>
+		 *   user-pass   = userid ":" password
+		 */
+
 		base64 = v->value + BASIC_LEN;
 
+		/* This will truncate "userid:password" lines to
+		 * sizeof(decoded). The array is long enough that this shouldn't
+		 * be a problem */
 		cnt = ast_base64decode((unsigned char*)decoded, base64,
 			sizeof(decoded) - 1);
 		ast_assert(cnt < sizeof(decoded));
-		decoded[cnt] = '\0';
-
+
+		/* Split the string at the colon */
 		colon = strchr(decoded, ':');
 		if (!colon) {
 			ast_log(LOG_WARNING, "Invalid Authorization header\n");

Modified: team/dlee/ari-authn/res/res_stasis_http.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-authn/res/res_stasis_http.c?view=diff&rev=393061&r1=393060&r2=393061
==============================================================================
--- team/dlee/ari-authn/res/res_stasis_http.c (original)
+++ team/dlee/ari-authn/res/res_stasis_http.c Thu Jun 27 13:59:06 2013
@@ -97,9 +97,6 @@
 				<configOption name="read_only">
 					<synopsis>When set to yes, user is only authorized for read-only requests</synopsis>
 				</configOption>
-				<configOption name="allow_api_key">
-					<synopsis>When set to yes, user may authenticate by appending ?api_key=username+password to their requests.</synopsis>
-				</configOption>
 				<configOption name="password">
 					<synopsis>Crypted or plaintext password (see password_format)</synopsis>
 				</configOption>
@@ -129,13 +126,7 @@
 static int is_enabled(void)
 {
 	RAII_VAR(struct ari_conf *, cfg, ari_config_get(), ao2_cleanup);
-	return cfg->general->enabled;
-}
-
-static enum ast_json_encoding_format json_format(void)
-{
-	RAII_VAR(struct ari_conf *, cfg, ari_config_get(), ao2_cleanup);
-	return cfg->general->format;
+	return cfg && cfg->general && cfg->general->enabled;
 }
 
 /*! Lock for \ref root_handler */
@@ -700,6 +691,37 @@
 }
 
 /*!
+ * \brief Authenticate a <code>?api_key=userid:password</code>
+ *
+ * \param api_key API key query parameter
+ * \return User object for the authenticated user.
+ * \return \c NULL if authentication failed.
+ */
+static struct ari_conf_user *authenticate_api_key(const char *api_key)
+{
+	RAII_VAR(char *, username, NULL, ast_free);
+	RAII_VAR(struct ari_conf_user *, user, NULL, ao2_cleanup);
+	char *colon;
+
+	username = ast_strdup(api_key);
+	if (!username) {
+		return NULL;
+	}
+
+	/* Split the string */
+	colon = strchr(username, ':');
+	if (!colon) {
+		return NULL;
+	}
+	*colon = '\0';
+
+	user = ari_config_validate_user(username, colon + 1);
+
+	ao2_ref(user, +1);
+	return user;
+}
+
+/*!
  * \brief Authenticate an HTTP request.
  *
  * \param get_params GET parameters of the request.
@@ -723,21 +745,7 @@
 	/* ?api_key authentication */
 	for (v = get_params; v; v = v->next) {
 		if (strcasecmp("api_key", v->name) == 0) {
-			RAII_VAR(char *, username, NULL, ast_free);
-			char *colon;
-
-			username = ast_strdup(v->value);
-			if (!username) {
-				return NULL;
-			}
-
-			colon = strchr(username, ':');
-			if (!colon) {
-				return NULL;
-			}
-
-			*colon = '\0';
-			return ari_config_validate_user(username, colon + 1);
+			return authenticate_api_key(v->value);
 		}
 	}
 
@@ -782,7 +790,7 @@
 	}
 
 	conf = ari_config_get();
-	if (!conf) {
+	if (!conf || !conf->general) {
 		return -1;
 	}
 
@@ -790,13 +798,26 @@
 
 	user = authenticate_user(get_params, headers);
 	if (!user) {
-		response.message = ast_json_pack("{s: s}",
-			"error", "Authentication required");
+		/* Per RFC 2617, section 1.2: The 401 (Unauthorized) response
+		 * message is used by an origin server to challenge the
+		 * authorization of a user agent. This response MUST include a
+		 * WWW-Authenticate header field containing at least one
+		 * challenge applicable to the requested resource.
+		 */
 		response.response_code = 401;
 		response.response_text = "Unauthorized";
+
+		/* Section 1.2:
+		 *   realm       = "realm" "=" realm-value
+		 *   realm-value = quoted-string
+		 * Section 2:
+		 *   challenge   = "Basic" realm
+		 */
 		ast_str_append(&response.headers, 0,
 			"WWW-Authenticate: Basic realm=\"%s\"\r\n",
 			conf->general->auth_realm);
+		response.message = ast_json_pack("{s: s}",
+			"error", "Authentication required");
 	} else if (user->read_only && method != AST_HTTP_GET && method != AST_HTTP_OPTIONS) {
 		response.message = ast_json_pack("{s: s}",
 			"error", "Write access denied");
@@ -837,7 +858,7 @@
 		ast_str_append(&response_headers, 0,
 			       "Content-type: application/json\r\n");
 		if (ast_json_dump_str_format(response.message, &response_body, 
-				json_format()) != 0) {
+				conf->general->format) != 0) {
 			/* Error encoding response */
 			response.response_code = 500;
 			response.response_text = "Internal Server Error";

Modified: team/dlee/ari-authn/res/stasis_http/cli.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-authn/res/stasis_http/cli.c?view=diff&rev=393061&r1=393060&r2=393061
==============================================================================
--- team/dlee/ari-authn/res/stasis_http/cli.c (original)
+++ team/dlee/ari-authn/res/stasis_http/cli.c Thu Jun 27 13:59:06 2013
@@ -80,9 +80,8 @@
 	struct ari_conf_user *user = obj;
 	struct ast_cli_args *a = arg;
 
-	ast_cli(a->fd, "%-*s  %-*s  %s\n",
-		4, AST_CLI_YESNO(user->read_only),
-		7, AST_CLI_YESNO(user->allow_api_key),
+	ast_cli(a->fd, "%-4s  %s\n",
+		AST_CLI_YESNO(user->read_only),
 		user->username);
 	return 0;
 }
@@ -115,8 +114,8 @@
 		return CLI_FAILURE;
 	}
 
-	ast_cli(a->fd, "r/o?  API key  Username\n");
-	ast_cli(a->fd, "----  -------  --------\n");
+	ast_cli(a->fd, "r/o?  Username\n");
+	ast_cli(a->fd, "----  --------\n");
 
 	ao2_callback(conf->users, OBJ_NODATA, show_users_cb, a);
 
@@ -208,8 +207,6 @@
 
 	ast_cli(a->fd, "Username: %s\n", user->username);
 	ast_cli(a->fd, "Read only?: %s\n", AST_CLI_YESNO(user->read_only));
-	ast_cli(a->fd, "Allow api_key?: %s\n",
-		AST_CLI_YESNO(user->allow_api_key));
 
 	return CLI_SUCCESS;
 }
@@ -241,6 +238,8 @@
 		return CLI_FAILURE;
 	}
 
+	ast_cli(a->fd,
+		"; Copy the following two lines into stasis_http.conf\n");
 	ast_cli(a->fd, "password_format = crypt\n");
 	ast_cli(a->fd, "password = %s\n", crypted);
 

Modified: team/dlee/ari-authn/res/stasis_http/config.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-authn/res/stasis_http/config.c?view=diff&rev=393061&r1=393060&r2=393061
==============================================================================
--- team/dlee/ari-authn/res/stasis_http/config.c (original)
+++ team/dlee/ari-authn/res/stasis_http/config.c Thu Jun 27 13:59:06 2013
@@ -77,6 +77,7 @@
 	return 0;
 }
 
+/*! \brief Destructor for \ref ari_conf_user */
 static void user_dtor(void *obj)
 {
 	struct ari_conf_user *user = obj;
@@ -84,10 +85,17 @@
 	ast_free(user->username);
 }
 
+/*! \brief Allocate an \ref ari_conf_user for config parsing */
 static void *user_alloc(const char *cat)
 {
 	RAII_VAR(struct ari_conf_user *, user, NULL, ao2_cleanup);
-	const char *username = strchr(cat, '-') + 1;
+	const char *username;
+
+	if (!cat) {
+		return NULL;
+	}
+
+	username = strchr(cat, '-') + 1;
 
 	if (!username) {
 		ast_log(LOG_ERROR, "Invalid user category '%s'\n", cat);
@@ -110,6 +118,7 @@
 	return user;
 }
 
+/*! \brief Sorting function for use with red/black tree */
 static int user_sort_cmp(const void *obj_left, const void *obj_right, int flags)
 {
 	const struct ari_conf_user *user_left = obj_left;
@@ -128,10 +137,17 @@
 	}
 }
 
-static void *user_find(struct ao2_container *tmp_container,
-	const char *category)
-{
-	return ao2_find(tmp_container, category, OBJ_KEY);
+/*! \brief \ref aco_type item_find function */
+static void *user_find(struct ao2_container *tmp_container, const char *cat)
+{
+	const char *username;
+
+	if (!cat) {
+		return NULL;
+	}
+
+	username = strchr(cat, '-') + 1;
+	return ao2_find(tmp_container, username, OBJ_KEY);
 }
 
 static struct aco_type user_option = {
@@ -146,7 +162,7 @@
 
 static struct aco_type *user[] = ACO_TYPES(&user_option);
 
-/*! \brief Disposes of the stasis http conf object */
+/*! \brief \ref ari_conf destructor. */
 static void conf_destructor(void *obj)
 {
 	struct ari_conf *cfg = obj;
@@ -154,7 +170,7 @@
 	ao2_cleanup(cfg->users);
 }
 
-/*! \brief Creates the statis http conf object. */
+/*! \brief Allocate an \ref ari_conf for config parsing */
 static void *conf_alloc(void)
 {
 	RAII_VAR(struct ari_conf *, cfg, NULL, ao2_cleanup);
@@ -189,7 +205,11 @@
 
 struct ari_conf *ari_config_get(void)
 {
-	return ao2_global_obj_ref(confs);
+	struct ari_conf *res = ao2_global_obj_ref(confs);
+	if (!res) {
+		ast_log(LOG_ERROR, "Error accessing configuration\n");
+	}
+	return res;
 }
 
 struct ari_conf_user *ari_config_validate_user(const char *username,
@@ -233,7 +253,8 @@
 	return user;
 }
 
-static int check_passwords_cb(void *obj, void *arg, int flags)
+/*! \brief Callback to validate a user object */
+static int validate_user_cb(void *obj, void *arg, int flags)
 {
 	struct ari_conf_user *user = obj;
 
@@ -245,6 +266,7 @@
 	return 0;
 }
 
+/*! \brief Load (or reload) configuration. */
 static int process_config(int reload)
 {
 	RAII_VAR(struct ari_conf *, conf, NULL, ao2_cleanup);
@@ -267,7 +289,7 @@
 		ast_log(LOG_ERROR, "No configured users for ARI\n");
 	}
 
-	ao2_callback(conf->users, OBJ_NODATA, check_passwords_cb, NULL);
+	ao2_callback(conf->users, OBJ_NODATA, validate_user_cb, NULL);
 
 	return 0;
 }
@@ -292,9 +314,6 @@
 	aco_option_register(&cfg_info, "read_only", ACO_EXACT, user,
 		"no", OPT_BOOL_T, 1,
 		FLDSET(struct ari_conf_user, read_only));
-	aco_option_register(&cfg_info, "allow_api_key", ACO_EXACT, user,
-		"no", OPT_BOOL_T, 1,
-		FLDSET(struct ari_conf_user, allow_api_key));
 	aco_option_register(&cfg_info, "password", ACO_EXACT, user,
 		"", OPT_CHAR_ARRAY_T, 0,
 		FLDSET(struct ari_conf_user, password), ARI_PASSWORD_LEN);

Modified: team/dlee/ari-authn/res/stasis_http/internal.h
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-authn/res/stasis_http/internal.h?view=diff&rev=393061&r1=393060&r2=393061
==============================================================================
--- team/dlee/ari-authn/res/stasis_http/internal.h (original)
+++ team/dlee/ari-authn/res/stasis_http/internal.h Thu Jun 27 13:59:06 2013
@@ -94,8 +94,6 @@
 	enum ari_password_format password_format;
 	/*! If true, user cannot execute change operations */
 	int read_only;
-	/*! If true, user allowed to authenticate with ?api_key=user+password */
-	int allow_api_key;
 };
 
 /*!




More information about the svn-commits mailing list