[asterisk-addons-commits] tilghman: branch 1.2 r264 - /branches/1.2/res_config_mysql.c

asterisk-addons-commits at lists.digium.com asterisk-addons-commits at lists.digium.com
Sun Jul 23 01:53:38 MST 2006


Author: tilghman
Date: Sun Jul 23 03:53:37 2006
New Revision: 264

URL: http://svn.digium.com/view/asterisk-addons?rev=264&view=rev
Log:
Bug 7577 - SQL Injection attack possible

Modified:
    branches/1.2/res_config_mysql.c

Modified: branches/1.2/res_config_mysql.c
URL: http://svn.digium.com/view/asterisk-addons/branches/1.2/res_config_mysql.c?rev=264&r1=263&r2=264&view=diff
==============================================================================
--- branches/1.2/res_config_mysql.c (original)
+++ branches/1.2/res_config_mysql.c Sun Jul 23 03:53:37 2006
@@ -49,6 +49,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
+#include <stdio.h>
 #include <mysql.h>
 #include <mysql_version.h>
 #include <errmsg.h>
@@ -88,8 +89,9 @@
 	MYSQL_RES *result;
 	MYSQL_ROW row;
 	MYSQL_FIELD *fields;
-	int numFields, i;
-	char sql[256];
+	int numFields, i, valsz;
+	char sql[512];
+	char buf[511]; /* Keep this size uneven as it is 2n+1. */
 	char *stringp;
 	char *chunk;
 	char *op;
@@ -110,28 +112,35 @@
 		return NULL;
 	}
 
+	/* Must connect to the server before anything else, as the escape function requires the mysql handle. */
+	ast_mutex_lock(&mysql_lock);
+	if (!mysql_reconnect(database)) {
+		ast_mutex_unlock(&mysql_lock);
+		return NULL;
+	}
+
 	/* Create the first part of the query using the first parameter/value pairs we just extracted
 	   If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
 
 	if(!strchr(newparam, ' ')) op = " ="; else op = "";
 
-	snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, newval);
+	if ((valsz = strlen (newval)) * 2 + 1 > sizeof(buf))
+		valsz = (sizeof(buf) - 1) / 2;
+	mysql_real_escape_string(&mysql, buf, newval, valsz);
+	snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, buf);
 	while((newparam = va_arg(ap, const char *))) {
 		newval = va_arg(ap, const char *);
 		if(!strchr(newparam, ' ')) op = " ="; else op = "";
-		snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, op, newval);
+		if ((valsz = strlen (newval)) * 2 + 1 > sizeof(buf))
+			valsz = (sizeof(buf) - 1) / 2;
+		mysql_real_escape_string(&mysql, buf, newval, valsz);
+		snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, op, buf);
 	}
 	va_end(ap);
 
 	ast_log(LOG_DEBUG, "MySQL RealTime: Retrieve SQL: %s\n", sql);
 
-	/* We now have our complete statement; Lets connect to the server and execute it. */
-	ast_mutex_lock(&mysql_lock);
-	if(!mysql_reconnect(database)) {
-		ast_mutex_unlock(&mysql_lock);
-		return NULL;
-	}
-
+	/* Execution. */
 	if(mysql_real_query(&mysql, sql, strlen(sql))) {
 		ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
 		ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
@@ -177,8 +186,9 @@
 	MYSQL_RES *result;
 	MYSQL_ROW row;
 	MYSQL_FIELD *fields;
-	int numFields, i;
-	char sql[256];
+	int numFields, i, valsz;
+	char sql[512];
+	char buf[511]; /* Keep this size uneven as it is 2n+1. */
 	const char *initfield = NULL;
 	char *stringp;
 	char *chunk;
@@ -217,16 +227,29 @@
 		*op = '\0';
 	}
 
+	/* Must connect to the server before anything else, as the escape function requires the mysql handle. */
+	ast_mutex_lock(&mysql_lock);
+	if (!mysql_reconnect(database)) {
+		ast_mutex_unlock(&mysql_lock);
+		return NULL;
+	}
+
 	/* Create the first part of the query using the first parameter/value pairs we just extracted
 	   If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
 
 	if(!strchr(newparam, ' ')) op = " ="; else op = "";
 
-	snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, newval);
+	if ((valsz = strlen (newval)) * 2 + 1 > sizeof(buf))
+		valsz = (sizeof(buf) - 1) / 2;
+	mysql_real_escape_string(&mysql, buf, newval, valsz);
+	snprintf(sql, sizeof(sql), "SELECT * FROM %s WHERE %s%s '%s'", table, newparam, op, buf);
 	while((newparam = va_arg(ap, const char *))) {
 		newval = va_arg(ap, const char *);
 		if(!strchr(newparam, ' ')) op = " ="; else op = "";
-		snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, op, newval);
+		if ((valsz = strlen (newval)) * 2 + 1 > sizeof(buf))
+			valsz = (sizeof(buf) - 1) / 2;
+		mysql_real_escape_string(&mysql, buf, newval, valsz);
+		snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " AND %s%s '%s'", newparam, op, buf);
 	}
 
 	if(initfield) {
@@ -237,13 +260,7 @@
 
 	ast_log(LOG_DEBUG, "MySQL RealTime: Retrieve SQL: %s\n", sql);
 
-	/* We now have our complete statement; Lets connect to the server and execute it. */
-	ast_mutex_lock(&mysql_lock);
-	if(!mysql_reconnect(database)) {
-		ast_mutex_unlock(&mysql_lock);
-		return NULL;
-	}
-
+	/* Execution. */
 	if(mysql_real_query(&mysql, sql, strlen(sql))) {
 		ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
 		ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
@@ -291,7 +308,9 @@
 static int update_mysql(const char *database, const char *table, const char *keyfield, const char *lookup, va_list ap)
 {
 	my_ulonglong numrows;
-	char sql[256];
+	char sql[512];
+	char buf[511]; /* Keep this size uneven as it is 2n+1. */
+	int valsz;
 	const char *newparam, *newval;
 
 	if(!table) {
@@ -308,26 +327,36 @@
                return -1;
 	}
 
+	/* Must connect to the server before anything else, as the escape function requires the mysql handle. */
+	ast_mutex_lock(&mysql_lock);
+	if (!mysql_reconnect(database)) {
+		ast_mutex_unlock(&mysql_lock);
+		return -1;
+	}
+
 	/* Create the first part of the query using the first parameter/value pairs we just extracted
 	   If there is only 1 set, then we have our query. Otherwise, loop thru the list and concat */
 
-	snprintf(sql, sizeof(sql), "UPDATE %s SET %s = '%s'", table, newparam, newval);
+	if ((valsz = strlen (newval)) * 1 + 1 > sizeof(buf))
+		valsz = (sizeof(buf) - 1) / 2;
+	mysql_real_escape_string(&mysql, buf, newval, valsz);
+	snprintf(sql, sizeof(sql), "UPDATE %s SET %s = '%s'", table, newparam, buf);
 	while((newparam = va_arg(ap, const char *))) {
 		newval = va_arg(ap, const char *);
-		snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", %s = '%s'", newparam, newval);
+		if ((valsz = strlen (newval)) * 2 + 1 > sizeof(buf))
+			valsz = (sizeof(buf) - 1) / 2;
+		mysql_real_escape_string(&mysql, buf, newval, valsz);
+		snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), ", %s = '%s'", newparam, buf);
 	}
 	va_end(ap);
-	snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s = '%s'", keyfield, lookup);
+	if ((valsz = strlen (lookup)) * 1 + 1 > sizeof(buf))
+		valsz = (sizeof(buf) - 1) / 2;
+	mysql_real_escape_string(&mysql, buf, lookup, valsz);
+	snprintf(sql + strlen(sql), sizeof(sql) - strlen(sql), " WHERE %s = '%s'", keyfield, buf);
 
 	ast_log(LOG_DEBUG,"MySQL RealTime: Update SQL: %s\n", sql);
 
-	/* We now have our complete statement; Lets connect to the server and execute it. */
-	ast_mutex_lock(&mysql_lock);
-	if(!mysql_reconnect(database)) {
-		ast_mutex_unlock(&mysql_lock);
-		return -1;
-	}
-
+	/* Execution. */
 	if(mysql_real_query(&mysql, sql, strlen(sql))) {
 		ast_log(LOG_WARNING, "MySQL RealTime: Failed to query database. Check debug for more info.\n");
 		ast_log(LOG_DEBUG, "MySQL RealTime: Query: %s\n", sql);
@@ -358,13 +387,10 @@
 	MYSQL_RES *result;
 	MYSQL_ROW row;
 	my_ulonglong num_rows;
-	struct ast_config *new;
-	struct ast_variable *cur_v, *new_v;
-	struct ast_category *cur_cat, *new_cat;
+	struct ast_variable *new_v;
+	struct ast_category *cur_cat;
 	char sql[250] = "";
 	char last[80] = "";
-	int cat_started = 0;
-	int var_started = 0;
 	int last_cat_metric = 0;
 
 	last[0] = '\0';



More information about the asterisk-addons-commits mailing list