[svn-commits] rmudgett: trunk r432405 - in /trunk: ./ include/asterisk/ main/ res/ res/ari/...

SVN commits to the Digium repositories svn-commits at lists.digium.com
Fri Feb 27 12:31:34 CST 2015


Author: rmudgett
Date: Fri Feb 27 12:31:31 2015
New Revision: 432405

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=432405
Log:
ARI: Fix crash if integer values used in JSON payload 'variables' object.

Sending the following ARI commands caused Asterisk to crash if the JSON
body 'variables' object passes values of types other than strings.

POST /ari/channels
POST /ari/channels/{channelid}
PUT /ari/endpoints/sendMessage
PUT /ari/endpoints/{tech}/{resource}/sendMessage

* Eliminated RAII_VAR usage in ast_ari_channels_originate_with_id(),
ast_ari_channels_originate(), ast_ari_endpoints_send_message(), and
ast_ari_endpoints_send_message_to_endpoint().

ASTERISK-24751 #close
Reported by:  jeffrey putnam

Review: https://reviewboard.asterisk.org/r/4447/
........

Merged revisions 432404 from http://svn.asterisk.org/svn/asterisk/branches/13

Modified:
    trunk/   (props changed)
    trunk/include/asterisk/json.h
    trunk/main/json.c
    trunk/res/ari/resource_channels.c
    trunk/res/ari/resource_endpoints.c
    trunk/res/res_ari_endpoints.c
    trunk/rest-api/api-docs/endpoints.json

Propchange: trunk/
------------------------------------------------------------------------------
Binary property 'branch-13-merged' - no diff available.

Modified: trunk/include/asterisk/json.h
URL: http://svnview.digium.com/svn/asterisk/trunk/include/asterisk/json.h?view=diff&rev=432405&r1=432404&r2=432405
==============================================================================
--- trunk/include/asterisk/json.h (original)
+++ trunk/include/asterisk/json.h Fri Feb 27 12:31:31 2015
@@ -1010,13 +1010,24 @@
  */
 struct ast_json *ast_json_party_id(struct ast_party_id *party);
 
+enum ast_json_to_ast_vars_code {
+	/*! \brief Conversion successful */
+	AST_JSON_TO_AST_VARS_CODE_SUCCESS,
+	/*!
+	 * \brief Conversion failed because invalid value type supplied.
+	 * \note Only string values allowed.
+	 */
+	AST_JSON_TO_AST_VARS_CODE_INVALID_TYPE,
+	/*! \brief Conversion failed because of allocation failure. (Out Of Memory) */
+	AST_JSON_TO_AST_VARS_CODE_OOM,
+};
+
 /*!
  * \brief Convert a \c ast_json list of key/value pair tuples into a \c ast_variable list
  * \since 12.5.0
  *
  * \param json_variables The JSON blob containing the variable
  * \param variables An out reference to the variables to populate.
- *        The pointer to the variables should be NULL when calling this.
  *
  * \code
  * struct ast_json *json_variables = ast_json_pack("[ { s: s } ]", "foo", "bar");
@@ -1026,10 +1037,9 @@
  * res = ast_json_to_ast_variables(json_variables, &variables);
  * \endcode
  *
- * \retval 0 success
- * \retval -1 error
- */
-int ast_json_to_ast_variables(struct ast_json *json_variables, struct ast_variable **variables);
+ * \return Conversion enum ast_json_to_ast_vars_code status
+ */
+enum ast_json_to_ast_vars_code ast_json_to_ast_variables(struct ast_json *json_variables, struct ast_variable **variables);
 
 /*!@}*/
 

Modified: trunk/main/json.c
URL: http://svnview.digium.com/svn/asterisk/trunk/main/json.c?view=diff&rev=432405&r1=432404&r2=432405
==============================================================================
--- trunk/main/json.c (original)
+++ trunk/main/json.c Fri Feb 27 12:31:31 2015
@@ -882,32 +882,47 @@
 	return ast_json_ref(json_party_id);
 }
 
-int ast_json_to_ast_variables(struct ast_json *json_variables, struct ast_variable **variables)
+enum ast_json_to_ast_vars_code ast_json_to_ast_variables(struct ast_json *json_variables, struct ast_variable **variables)
 {
 	struct ast_json_iter *it_json_var;
 
 	*variables = NULL;
 
 	for (it_json_var = ast_json_object_iter(json_variables); it_json_var;
-		 it_json_var = ast_json_object_iter_next(json_variables, it_json_var)) {
+		it_json_var = ast_json_object_iter_next(json_variables, it_json_var)) {
 		struct ast_variable *new_var;
 		const char *key = ast_json_object_iter_key(it_json_var);
+		const char *value;
+		struct ast_json *json_value;
 
 		if (ast_strlen_zero(key)) {
 			continue;
 		}
 
-		new_var = ast_variable_new(key,
-		                           ast_json_string_get(ast_json_object_iter_value(it_json_var)),
-		                           "");
-		if (!new_var) {
+		json_value = ast_json_object_iter_value(it_json_var);
+		if (ast_json_typeof(json_value) != AST_JSON_STRING) {
+			/* Error: Only strings allowed */
 			ast_variables_destroy(*variables);
 			*variables = NULL;
-			return -1;
+			return AST_JSON_TO_AST_VARS_CODE_INVALID_TYPE;
 		}
+		value = ast_json_string_get(json_value);
+		/* Should never be NULL.  Otherwise, how could it be a string type? */
+		ast_assert(value != NULL);
+		if (!value) {
+			/* To be safe. */
+			continue;
+		}
+		new_var = ast_variable_new(key, value, "");
+		if (!new_var) {
+			/* Error: OOM */
+			ast_variables_destroy(*variables);
+			*variables = NULL;
+			return AST_JSON_TO_AST_VARS_CODE_OOM;
+		}
 
 		ast_variable_list_append(variables, new_var);
 	}
 
-	return 0;
-}
+	return AST_JSON_TO_AST_VARS_CODE_SUCCESS;
+}

Modified: trunk/res/ari/resource_channels.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/ari/resource_channels.c?view=diff&rev=432405&r1=432404&r2=432405
==============================================================================
--- trunk/res/ari/resource_channels.c (original)
+++ trunk/res/ari/resource_channels.c Fri Feb 27 12:31:31 2015
@@ -1147,11 +1147,44 @@
 	return;
 }
 
+/*!
+ * \internal
+ * \brief Convert a \c ast_json list of key/value pair tuples into a \c ast_variable list
+ * \since 13.3.0
+ *
+ * \param[out] response HTTP response if error
+ * \param json_variables The JSON blob containing the variable
+ * \param[out] variables An out reference to the variables to populate.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int json_to_ast_variables(struct ast_ari_response *response, struct ast_json *json_variables, struct ast_variable **variables)
+{
+	enum ast_json_to_ast_vars_code res;
+
+	res = ast_json_to_ast_variables(json_variables, variables);
+	switch (res) {
+	case AST_JSON_TO_AST_VARS_CODE_SUCCESS:
+		return 0;
+	case AST_JSON_TO_AST_VARS_CODE_INVALID_TYPE:
+		ast_ari_response_error(response, 400, "Bad Request",
+			"Only string values in the 'variables' object allowed");
+		break;
+	case AST_JSON_TO_AST_VARS_CODE_OOM:
+		ast_ari_response_alloc_failed(response);
+		break;
+	}
+	ast_log(AST_LOG_ERROR, "Unable to convert 'variables' in JSON body to channel variables\n");
+
+	return -1;
+}
+
 void ast_ari_channels_originate_with_id(struct ast_variable *headers,
 	struct ast_ari_channels_originate_with_id_args *args,
 	struct ast_ari_response *response)
 {
-	RAII_VAR(struct ast_variable *, variables, NULL, ast_variables_destroy);
+	struct ast_variable *variables = NULL;
 
 	/* Parse any query parameters out of the body parameter */
 	if (args->variables) {
@@ -1159,12 +1192,9 @@
 
 		ast_ari_channels_originate_with_id_parse_body(args->variables, args);
 		json_variables = ast_json_object_get(args->variables, "variables");
-		if (json_variables) {
-			if (ast_json_to_ast_variables(json_variables, &variables)) {
-				ast_log(AST_LOG_ERROR, "Unable to convert 'variables' in JSON body to channel variables\n");
-				ast_ari_response_alloc_failed(response);
-				return;
-			}
+		if (json_variables
+			&& json_to_ast_variables(response, json_variables, &variables)) {
+			return;
 		}
 	}
 
@@ -1183,13 +1213,14 @@
 		args->other_channel_id,
 		args->originator,
 		response);
+	ast_variables_destroy(variables);
 }
 
 void ast_ari_channels_originate(struct ast_variable *headers,
 	struct ast_ari_channels_originate_args *args,
 	struct ast_ari_response *response)
 {
-	RAII_VAR(struct ast_variable *, variables, NULL, ast_variables_destroy);
+	struct ast_variable *variables = NULL;
 
 	/* Parse any query parameters out of the body parameter */
 	if (args->variables) {
@@ -1197,12 +1228,9 @@
 
 		ast_ari_channels_originate_parse_body(args->variables, args);
 		json_variables = ast_json_object_get(args->variables, "variables");
-		if (json_variables) {
-			if (ast_json_to_ast_variables(json_variables, &variables)) {
-				ast_log(AST_LOG_ERROR, "Unable to convert 'variables' in JSON body to channel variables\n");
-				ast_ari_response_alloc_failed(response);
-				return;
-			}
+		if (json_variables
+			&& json_to_ast_variables(response, json_variables, &variables)) {
+			return;
 		}
 	}
 
@@ -1221,6 +1249,7 @@
 		args->other_channel_id,
 		args->originator,
 		response);
+	ast_variables_destroy(variables);
 }
 
 void ast_ari_channels_get_channel_var(struct ast_variable *headers,

Modified: trunk/res/ari/resource_endpoints.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/ari/resource_endpoints.c?view=diff&rev=432405&r1=432404&r2=432405
==============================================================================
--- trunk/res/ari/resource_endpoints.c (original)
+++ trunk/res/ari/resource_endpoints.c Fri Feb 27 12:31:31 2015
@@ -220,35 +220,66 @@
 	response->response_text = "Accepted";
 }
 
+/*!
+ * \internal
+ * \brief Convert a \c ast_json list of key/value pair tuples into a \c ast_variable list
+ * \since 13.3.0
+ *
+ * \param[out] response HTTP response if error
+ * \param json_variables The JSON blob containing the variable
+ * \param[out] variables An out reference to the variables to populate.
+ *
+ * \retval 0 on success.
+ * \retval -1 on error.
+ */
+static int json_to_ast_variables(struct ast_ari_response *response, struct ast_json *json_variables, struct ast_variable **variables)
+{
+	enum ast_json_to_ast_vars_code res;
+
+	res = ast_json_to_ast_variables(json_variables, variables);
+	switch (res) {
+	case AST_JSON_TO_AST_VARS_CODE_SUCCESS:
+		return 0;
+	case AST_JSON_TO_AST_VARS_CODE_INVALID_TYPE:
+		ast_ari_response_error(response, 400, "Bad Request",
+			"Only string values in the 'variables' object allowed");
+		break;
+	case AST_JSON_TO_AST_VARS_CODE_OOM:
+		ast_ari_response_alloc_failed(response);
+		break;
+	}
+	ast_log(AST_LOG_ERROR, "Unable to convert 'variables' in JSON body to Asterisk variables\n");
+
+	return -1;
+}
+
 void ast_ari_endpoints_send_message(struct ast_variable *headers,
 	struct ast_ari_endpoints_send_message_args *args,
 	struct ast_ari_response *response)
 {
-	RAII_VAR(struct ast_variable *, variables, NULL, ast_variables_destroy);
+	struct ast_variable *variables = NULL;
 
 	if (args->variables) {
 		struct ast_json *json_variables;
 
 		ast_ari_endpoints_send_message_parse_body(args->variables, args);
 		json_variables = ast_json_object_get(args->variables, "variables");
-		if (json_variables) {
-			if (ast_json_to_ast_variables(json_variables, &variables)) {
-				ast_log(AST_LOG_ERROR, "Unable to convert 'variables' in JSON body to Asterisk variables\n");
-				ast_ari_response_alloc_failed(response);
-				return;
-			}
+		if (json_variables
+			&& json_to_ast_variables(response, json_variables, &variables)) {
+			return;
 		}
 	}
 
 	send_message(args->to, args->from, args->body, variables, response);
+	ast_variables_destroy(variables);
 }
 
 void ast_ari_endpoints_send_message_to_endpoint(struct ast_variable *headers,
 	struct ast_ari_endpoints_send_message_to_endpoint_args *args,
 	struct ast_ari_response *response)
 {
-	RAII_VAR(struct ast_variable *, variables, NULL, ast_variables_destroy);
-	RAII_VAR(struct ast_endpoint_snapshot *, snapshot, NULL, ao2_cleanup);
+	struct ast_variable *variables = NULL;
+	struct ast_endpoint_snapshot *snapshot;
 	char msg_to[128];
 	char *tech = ast_strdupa(args->tech);
 
@@ -259,23 +290,21 @@
 			"Endpoint not found");
 		return;
 	}
+	ao2_ref(snapshot, -1);
 
 	if (args->variables) {
 		struct ast_json *json_variables;
 
 		ast_ari_endpoints_send_message_to_endpoint_parse_body(args->variables, args);
 		json_variables = ast_json_object_get(args->variables, "variables");
-
-		if (json_variables) {
-			if (ast_json_to_ast_variables(json_variables, &variables)) {
-				ast_log(AST_LOG_ERROR, "Unable to convert 'variables' in JSON body to Asterisk variables\n");
-				ast_ari_response_alloc_failed(response);
-				return;
-			}
+		if (json_variables
+			&& json_to_ast_variables(response, json_variables, &variables)) {
+			return;
 		}
 	}
 
 	snprintf(msg_to, sizeof(msg_to), "%s:%s", ast_str_to_lower(tech), args->resource);
 
 	send_message(msg_to, args->from, args->body, variables, response);
-}
+	ast_variables_destroy(variables);
+}

Modified: trunk/res/res_ari_endpoints.c
URL: http://svnview.digium.com/svn/asterisk/trunk/res/res_ari_endpoints.c?view=diff&rev=432405&r1=432404&r2=432405
==============================================================================
--- trunk/res/res_ari_endpoints.c (original)
+++ trunk/res/res_ari_endpoints.c Fri Feb 27 12:31:31 2015
@@ -181,6 +181,7 @@
 		break;
 	case 500: /* Internal Server Error */
 	case 501: /* Not Implemented */
+	case 400: /* Invalid parameters for sending a message. */
 	case 404: /* Endpoint not found */
 		is_valid = 1;
 		break;

Modified: trunk/rest-api/api-docs/endpoints.json
URL: http://svnview.digium.com/svn/asterisk/trunk/rest-api/api-docs/endpoints.json?view=diff&rev=432405&r1=432404&r2=432405
==============================================================================
--- trunk/rest-api/api-docs/endpoints.json (original)
+++ trunk/rest-api/api-docs/endpoints.json Fri Feb 27 12:31:31 2015
@@ -63,6 +63,10 @@
 						}
 					],
 					"errorResponses": [
+						{
+							"code": 400,
+							"reason": "Invalid parameters for sending a message."
+						},
 						{
 							"code": 404,
 							"reason": "Endpoint not found"




More information about the svn-commits mailing list