[asterisk-commits] dlee: branch dlee/ari-authn r392852 - in /team/dlee/ari-authn: configs/ main/...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Tue Jun 25 11:22:52 CDT 2013


Author: dlee
Date: Tue Jun 25 11:22:50 2013
New Revision: 392852

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=392852
Log:
User config parsing

Modified:
    team/dlee/ari-authn/configs/stasis_http.conf.sample
    team/dlee/ari-authn/main/features_config.c
    team/dlee/ari-authn/res/res_stasis_http.c

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=392852&r1=392851&r2=392852
==============================================================================
--- team/dlee/ari-authn/configs/stasis_http.conf.sample (original)
+++ team/dlee/ari-authn/configs/stasis_http.conf.sample Tue Jun 25 11:22:50 2013
@@ -11,15 +11,14 @@
 ;			; read-only requests
 ;
 ;allow_api_key = no	; When set to yes, user may authenticate by appending
-;			; ?api_key=username+password. Otherwise, the user may
-;			; use only HTTP basic authentication.
+;			; ?api_key=username+password to their requests.
 ;
-;password =		; Crypted or plaintext password (see crypt_password)
+;password =		; Crypted or plaintext password (see password_format)
 ;
-; crypt_password may be set to crypt (the default) or plain. When set to crypt,
-; crypt(3) is used to encrypt the password. A crypted password can be generated
+; password_format may be set to plain (the default) or crypt. When set to crypt,
+; crypt(3) is used to validate the password. A crypted password can be generated
 ; using mkpasswd -m sha-512.
 ;
 ; When set to plain, the password is in plaintext
 ;
-;crypt_password = plain
+;password_format = plain

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=392852&r1=392851&r2=392852
==============================================================================
--- team/dlee/ari-authn/main/features_config.c (original)
+++ team/dlee/ari-authn/main/features_config.c Tue Jun 25 11:22:50 2013
@@ -1792,23 +1792,26 @@
 	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;
-
-	res = load_config();
+	int res = 0;
+
+	//res = load_config();
+	nowarn = 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/res/res_stasis_http.c
URL: http://svnview.digium.com/svn/asterisk/team/dlee/ari-authn/res/res_stasis_http.c?view=diff&rev=392852&r1=392851&r2=392852
==============================================================================
--- team/dlee/ari-authn/res/res_stasis_http.c (original)
+++ team/dlee/ari-authn/res/res_stasis_http.c Tue Jun 25 11:22:50 2013
@@ -88,6 +88,22 @@
 					<synopsis>Responses from stasis-http are formatted to be human readable</synopsis>
 				</configOption>
 			</configObject>
+
+			<configObject name="user">
+				<synopsis>Per-user configuration settings</synopsis>
+				<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>
+				<configOption name="password_format">
+					<synopsis>password_format may be set to plain (the default) or crypt. When set to crypt, crypt(3) is used to validate the password. A crypted password can be generated using mkpasswd -m sha-512. When set to plain, the password is in plaintext</synopsis>
+				</configOption>
+			</configObject>
 		</configFile>
 	</configInfo>
 ***/
@@ -108,15 +124,83 @@
 /*! \brief Global configuration options for stasis http. */
 struct conf_global_options {
 	/*! Enabled by default, disabled if false. */
-	int enabled:1;
+	int enabled;
 	/*! Encoding format used during output (default compact). */
 	enum ast_json_encoding_format format;
 };
+
+/*! \brief Password format */
+enum password_format {
+	/*! \brief Plaintext password */
+	PASSWORD_FORMAT_PLAIN,
+	/*! crypt(3) password */
+	PASSWORD_FORMAT_CRYPT,
+};
+
+struct conf_user_options {
+	/*! Username for authentication */
+	char username[128];
+	/*! User's password. If 256 seems like a lot, a crypt SHA-512 has over
+	 *  100 characters */
+	char password[256];
+	/*! Format for the password field */
+	enum 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;
+};
+
+static void user_dtor(void *obj)
+{
+	struct conf_user_options *user = obj;
+
+	ast_debug(3, "Disposing of user %s", user->username);
+}
+
+static void *user_alloc(const char *cat)
+{
+	RAII_VAR(struct conf_user_options *, user, NULL, ao2_cleanup);
+	const char *username = strchr(cat, '-') + 1;
+
+	if (!username) {
+		ast_log(LOG_ERROR, "Invalid user category '%s'\n", cat);
+		return NULL;
+	}
+
+	ast_debug(3, "Allocating user %s\n", cat);
+
+	user = ao2_alloc(sizeof(*user), user_dtor);
+	if (!user) {
+		return NULL;
+	}
+
+	ao2_ref(user, +1);
+	return user;
+}
+
+static int user_sort_cmp(const void *obj_left, const void *obj_right, int flags)
+{
+	const struct conf_user_options *user_left = obj_left;
+	const struct conf_user_options *user_right = obj_right;
+	const char *right_key =
+		(flags & OBJ_KEY) ? obj_right : user_right->username;
+
+	return strcmp(user_left->username, right_key);
+}
+
+static void *user_find(struct ao2_container *tmp_container,
+	const char *category)
+{
+	return ao2_find(tmp_container, category, OBJ_KEY);
+}
 
 /*! \brief All configuration options for stasis http. */
 struct conf {
 	/*! The general section configuration options. */
 	struct conf_global_options *global;
+	/*! Configured users */
+	struct ao2_container *users;
 };
 
 /*! \brief Locking container for safe configuration access. */
@@ -129,32 +213,50 @@
 	.name = "global",
 	.item_offset = offsetof(struct conf, global),
 	.category = "^general$",
-	.category_match = ACO_WHITELIST
+	.category_match = ACO_WHITELIST,
 };
 
 static struct aco_type *global_options[] = ACO_TYPES(&global_option);
+
+static struct aco_type user_option = {
+	.type = ACO_ITEM,
+	.name = "user",
+	.category_match = ACO_WHITELIST,
+	.category = "^user-.+$",
+	.item_alloc = user_alloc,
+	.item_find = user_find,
+	.item_offset = offsetof(struct conf, users),
+};
+
+static struct aco_type *user_options[] = ACO_TYPES(&user_option);
 
 /*! \brief Disposes of the stasis http conf object */
 static void conf_destructor(void *obj)
 {
-    struct conf *cfg = obj;
-    ao2_cleanup(cfg->global);
+	struct conf *cfg = obj;
+	ao2_cleanup(cfg->global);
 }
 
 /*! \brief Creates the statis http conf object. */
 static void *conf_alloc(void)
 {
-    struct conf *cfg;
-
-    if (!(cfg = ao2_alloc(sizeof(*cfg), conf_destructor))) {
-        return NULL;
-    }
-
-    if (!(cfg->global = ao2_alloc(sizeof(*cfg->global), NULL))) {
-        ao2_ref(cfg, -1);
-        return NULL;
-    }
-    return cfg;
+	RAII_VAR(struct conf *, cfg, NULL, ao2_cleanup);
+
+	cfg = ao2_alloc(sizeof(*cfg), conf_destructor);
+	if (!cfg) {
+		return NULL;
+	}
+
+	cfg->global = ao2_alloc(sizeof(*cfg->global), NULL);
+	if (!cfg->global) {
+		return NULL;
+	}
+
+	cfg->users = ao2_container_alloc_rbtree(AO2_ALLOC_OPT_LOCK_NOLOCK,
+		AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE, user_sort_cmp, NULL);
+
+	ao2_ref(cfg, +1);
+	return cfg;
 }
 
 /*! \brief The conf file that's processed for the module. */
@@ -162,19 +264,19 @@
 	/*! The config file name. */
 	.filename = "stasis_http.conf",
 	/*! The mapping object types to be processed. */
-	.types = ACO_TYPES(&global_option),
+	.types = ACO_TYPES(&global_option, &user_option),
 };
 
 CONFIG_INFO_STANDARD(cfg_info, confs, conf_alloc,
 		     .files = ACO_FILES(&conf_file));
 
-/*! \brief Bitfield handler since it is not possible to take address. */
-static int conf_bitfield_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
+/*! \brief Encoding format handler converts from boolean to enum. */
+static int encoding_format_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
 {
 	struct conf_global_options *global = obj;
 
-	if (!strcasecmp(var->name, "enabled")) {
-		global->enabled = ast_true(var->value);
+	if (!strcasecmp(var->name, "pretty")) {
+		global->format = ast_true(var->value) ? AST_JSON_PRETTY : AST_JSON_COMPACT;
 	} else {
 		return -1;
 	}
@@ -182,13 +284,14 @@
 	return 0;
 }
 
-/*! \brief Encoding format handler converts from boolean to enum. */
-static int encoding_format_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
-{
-	struct conf_global_options *global = obj;
-
-	if (!strcasecmp(var->name, "pretty")) {
-		global->format = ast_true(var->value) ? AST_JSON_PRETTY : AST_JSON_COMPACT;
+static int password_format_handler(const struct aco_option *opt, struct ast_variable *var, void *obj)
+{
+	struct conf_user_options *user = obj;
+
+	if (strcasecmp(var->value, "plain") == 0) {
+		user->password_format = PASSWORD_FORMAT_PLAIN;
+	} else if (strcasecmp(var->value, "crypt") == 0) {
+		user->password_format = PASSWORD_FORMAT_CRYPT;
 	} else {
 		return -1;
 	}
@@ -881,10 +984,23 @@
 		return AST_MODULE_LOAD_DECLINE;
 	}
 
-	aco_option_register_custom(&cfg_info, "enabled", ACO_EXACT, global_options,
-				   "yes", conf_bitfield_handler, 0);
-	aco_option_register_custom(&cfg_info, "pretty", ACO_EXACT, global_options,
-				   "no",  encoding_format_handler, 0);
+	aco_option_register(&cfg_info, "enabled", ACO_EXACT, global_options,
+		"yes", OPT_BOOL_T, 1,
+		FLDSET(struct conf_global_options, enabled));
+	aco_option_register_custom(&cfg_info, "pretty", ACO_EXACT,
+		global_options, "no",  encoding_format_handler, 0);
+
+	aco_option_register(&cfg_info, "read_only", ACO_EXACT, user_options,
+		"no", OPT_BOOL_T, 1,
+		FLDSET(struct conf_user_options, read_only));
+	aco_option_register(&cfg_info, "allow_api_key", ACO_EXACT, user_options,
+		"no", OPT_BOOL_T, 1,
+		FLDSET(struct conf_user_options, allow_api_key));
+	aco_option_register(&cfg_info, "password", ACO_EXACT, user_options,
+		"", OPT_CHAR_ARRAY_T, 0,
+		FLDSET(struct conf_user_options, password));
+	aco_option_register_custom(&cfg_info, "password_format", ACO_EXACT,
+		user_options, "plain",  password_format_handler, 0);
 
 	if (aco_process_config(&cfg_info, 0)) {
 		aco_info_destroy(&cfg_info);
@@ -895,7 +1011,10 @@
 		"{s: s}", "message", "Allocation failed");
 
 	if (is_enabled()) {
+		ast_debug(3, "ARI enabled\n");
 		ast_http_uri_link(&http_uri);
+	} else {
+		ast_debug(3, "ARI disabled\n");
 	}
 
 	return AST_MODULE_LOAD_SUCCESS;
@@ -907,6 +1026,7 @@
 	alloc_failed_message = NULL;
 
 	if (is_enabled()) {
+		ast_debug(3, "Disabling ARI\n");
 		ast_http_uri_unlink(&http_uri);
 	}
 
@@ -929,8 +1049,10 @@
 	}
 
 	if (was_enabled && !is_enabled()) {
+		ast_debug(3, "Disabling ARI\n");
 		ast_http_uri_unlink(&http_uri);
 	} else if (!was_enabled && is_enabled()) {
+		ast_debug(3, "Enabling ARI\n");
 		ast_http_uri_link(&http_uri);
 	}
 




More information about the asterisk-commits mailing list