andrey                                   Tue, 11 Jan 2011 13:02:57 +0000

Revision: http://svn.php.net/viewvc?view=revision&revision=307377

Log:
Use common code to handle initial authentication and
COM_CHANGE_USER

Changed paths:
    U   php/php-src/trunk/ext/mysqlnd/mysqlnd.c
    U   php/php-src/trunk/ext/mysqlnd/mysqlnd_wireprotocol.c
    U   php/php-src/trunk/ext/mysqlnd/mysqlnd_wireprotocol.h

Modified: php/php-src/trunk/ext/mysqlnd/mysqlnd.c
===================================================================
--- php/php-src/trunk/ext/mysqlnd/mysqlnd.c	2011-01-11 13:01:30 UTC (rev 307376)
+++ php/php-src/trunk/ext/mysqlnd/mysqlnd.c	2011-01-11 13:02:57 UTC (rev 307377)
@@ -427,7 +427,63 @@
 /* }}} */


-#define MYSQLND_ASSEBLED_PACKET_MAX_SIZE 3UL*1024UL*1024UL*1024UL
+#define MYSQLND_ASSEMBLED_PACKET_MAX_SIZE 3UL*1024UL*1024UL*1024UL
+/* {{{ mysqlnd_switch_to_ssl_if_needed */
+static MYSQLND_PACKET_AUTH *
+mysqlnd_switch_to_ssl_if_needed(
+			MYSQLND * conn,
+			const MYSQLND_PACKET_GREET * const greet_packet,
+			const MYSQLND_OPTIONS * const options,
+			unsigned long mysql_flags
+			TSRMLS_DC
+		)
+{
+	const MYSQLND_CHARSET * charset = NULL;
+	MYSQLND_PACKET_AUTH * auth_packet = conn->protocol->m.get_auth_packet(conn->protocol, FALSE TSRMLS_CC);
+	DBG_ENTER("mysqlnd_switch_to_ssl_if_needed");
+
+	if (!auth_packet) {
+		SET_OOM_ERROR(conn->error_info);
+		goto err;
+	}
+	auth_packet->client_flags = mysql_flags;
+	auth_packet->max_packet_size = MYSQLND_ASSEMBLED_PACKET_MAX_SIZE;
+
+	if (options->charset_name && (charset = mysqlnd_find_charset_name(options->charset_name))) {
+		auth_packet->charset_no	= charset->nr;
+	} else {
+#if MYSQLND_UNICODE
+		auth_packet->charset_no	= 200;/* utf8 - swedish collation, check mysqlnd_charset.c */
+#else
+		auth_packet->charset_no	= greet_packet->charset_no;
+#endif
+	}
+
+#ifdef MYSQLND_SSL_SUPPORTED
+	if ((greet_packet->server_capabilities & CLIENT_SSL) && (mysql_flags & CLIENT_SSL)) {
+		zend_bool verify = mysql_flags & CLIENT_SSL_VERIFY_SERVER_CERT? TRUE:FALSE;
+		DBG_INF("Switching to SSL");
+		if (!PACKET_WRITE(auth_packet, conn)) {
+			CONN_SET_STATE(conn, CONN_QUIT_SENT);
+			SET_CLIENT_ERROR(conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
+			goto err;
+		}
+
+		conn->net->m.set_client_option(conn->net, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (const char *) &verify TSRMLS_CC);
+
+		if (FAIL == conn->net->m.enable_ssl(conn->net TSRMLS_CC)) {
+			goto err;
+		}
+	}
+#endif
+	DBG_RETURN(auth_packet);
+err:
+	PACKET_FREE(auth_packet);
+	DBG_RETURN(NULL);
+}
+/* }}} */
+
+
 /* {{{ mysqlnd_connect_run_authentication */
 static enum_func_status
 mysqlnd_connect_run_authentication(
@@ -441,39 +497,28 @@
 			unsigned long mysql_flags
 			TSRMLS_DC)
 {
-	const MYSQLND_CHARSET * charset = NULL;
 	enum_func_status ret = FAIL;
-	MYSQLND_PACKET_AUTH * auth_packet = conn->protocol->m.get_auth_packet(conn->protocol, FALSE TSRMLS_CC);
+	MYSQLND_PACKET_AUTH * auth_packet = NULL;
 	MYSQLND_PACKET_OK * ok_packet = conn->protocol->m.get_ok_packet(conn->protocol, FALSE TSRMLS_CC);

 	DBG_ENTER("mysqlnd_connect_run_authentication");

-	if (!auth_packet || !ok_packet) {
+	if (!ok_packet) {
 		SET_OOM_ERROR(conn->error_info);
 		goto err;
 	}

-#ifdef MYSQLND_SSL_SUPPORTED
-	if ((greet_packet->server_capabilities & CLIENT_SSL) && (mysql_flags & CLIENT_SSL)) {
-		auth_packet->send_half_packet = TRUE;
+	auth_packet = mysqlnd_switch_to_ssl_if_needed(conn, greet_packet, options, mysql_flags TSRMLS_CC);
+
+	if (!auth_packet) {
+		goto err;
 	}
-#endif
+
+	auth_packet->send_auth_data = TRUE;
 	auth_packet->user		= user;
 	auth_packet->password	= passwd;
-
-	if (options->charset_name && (charset = mysqlnd_find_charset_name(options->charset_name))) {
-		auth_packet->charset_no	= charset->nr;
-	} else {
-#if MYSQLND_UNICODE
-		auth_packet->charset_no	= 200;/* utf8 - swedish collation, check mysqlnd_charset.c */
-#else
-		auth_packet->charset_no	= greet_packet->charset_no;
-#endif
-	}
 	auth_packet->db			= db;
 	auth_packet->db_len		= db_len;
-	auth_packet->max_packet_size= MYSQLND_ASSEBLED_PACKET_MAX_SIZE;
-	auth_packet->client_flags= mysql_flags;

 	conn->scramble = auth_packet->server_scramble_buf = mnd_pemalloc(SCRAMBLE_LENGTH, conn->persistent);
 	if (!conn->scramble) {
@@ -488,27 +533,6 @@
 		goto err;
 	}

-#ifdef MYSQLND_SSL_SUPPORTED
-	if (auth_packet->send_half_packet) {
-		zend_bool verify = mysql_flags & CLIENT_SSL_VERIFY_SERVER_CERT? TRUE:FALSE;
-		DBG_INF("Switching to SSL");
-
-		conn->net->m.set_client_option(conn->net, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (const char *) &verify TSRMLS_CC);
-
-		if (FAIL == conn->net->m.enable_ssl(conn->net TSRMLS_CC)) {
-			goto err;
-		}
-
-		auth_packet->send_half_packet = FALSE;
-		if (!PACKET_WRITE(auth_packet, conn)) {
-			CONN_SET_STATE(conn, CONN_QUIT_SENT);
-			SET_CLIENT_ERROR(conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
-			goto err;
-		}
-	}
-#endif
-
-
 	if (FAIL == PACKET_READ(ok_packet, conn) || ok_packet->field_count >= 0xFE) {
 		if (ok_packet->field_count == 0xFE) {
 			/* old authentication with new server  !*/
@@ -800,7 +824,7 @@
 			conn->unix_socket_len = strlen(conn->unix_socket);
 		}
 		conn->client_flag		= mysql_flags;
-		conn->max_packet_size	= MYSQLND_ASSEBLED_PACKET_MAX_SIZE;
+		conn->max_packet_size	= MYSQLND_ASSEMBLED_PACKET_MAX_SIZE;
 		/* todo: check if charset is available */
 		conn->server_capabilities = greet_packet->server_capabilities;
 		conn->upsert_status.warning_count = 0;
@@ -1912,19 +1936,27 @@
 	  Stack space is not that expensive, so use a bit more to be protected against
 	  buffer overflows.
 	*/
-	size_t user_len;
+	size_t user_len, db_len;
 	enum_func_status ret = FAIL;
-	MYSQLND_PACKET_CHG_USER_RESPONSE * chg_user_resp;
+	MYSQLND_PACKET_CHG_USER_RESPONSE * chg_user_resp = NULL;
 	char buffer[MYSQLND_MAX_ALLOWED_USER_LEN + 1 + SCRAMBLE_LENGTH + MYSQLND_MAX_ALLOWED_DB_LEN + 1 + 2 /* charset*/ ];
 	char *p = buffer;
 	const MYSQLND_CHARSET * old_cs = conn->charset;

+	MYSQLND_PACKET_AUTH * auth_packet = conn->protocol->m.get_auth_packet(conn->protocol, FALSE TSRMLS_CC);
+
+
 	DBG_ENTER("mysqlnd_conn::change_user");
 	DBG_INF_FMT("conn=%llu user=%s passwd=%s db=%s silent=%u",
 				conn->thread_id, user?user:"", passwd?"***":"null", db?db:"", (silent == TRUE)?1:0 );

 	SET_ERROR_AFF_ROWS(conn);

+	if (!auth_packet) {
+		SET_OOM_ERROR(conn->error_info);
+		goto end;
+	}
+
 	if (!user) {
 		user = "";
 	}
@@ -1934,44 +1966,25 @@
 	if (!db) {
 		db = "";
 	}
+	user_len = strlen(user);
+	db_len = strlen(db);

-	/* 1. user ASCIIZ */
-	user_len = MIN(strlen(user), MYSQLND_MAX_ALLOWED_USER_LEN);
-	memcpy(p, user, user_len);
-	p += user_len;
-	*p++ = '\0';
-
-	/* 2. password SCRAMBLE_LENGTH followed by the scramble or \0 */
-	if (passwd[0]) {
-		*p++ = SCRAMBLE_LENGTH;
-		php_mysqlnd_scramble((unsigned char *)p, conn->scramble, (unsigned char *)passwd);
-		p += SCRAMBLE_LENGTH;
-	} else {
-		*p++ = '\0';
-	}
-
-	/* 3. db ASCIIZ */
-	if (db[0]) {
-		size_t db_len = MIN(strlen(db), MYSQLND_MAX_ALLOWED_DB_LEN);
-		memcpy(p, db, db_len);
-		p += db_len;
-	}
-	*p++ = '\0';
-
-	/*
-	  4. request the current charset, or it will be reset to the system one.
-	  5.0 doesn't support it. Support added in 5.1.23 by fixing the following bug :
-	  Bug #30472 libmysql doesn't reset charset, insert_id after succ. mysql_change_user() call
-	*/
+	auth_packet->is_change_user_packet = TRUE;
+	auth_packet->user		= user;
+	auth_packet->password	= passwd;
+	auth_packet->db			= db;
+	auth_packet->db_len		= db_len;
+	auth_packet->server_scramble_buf = conn->scramble;
+	auth_packet->silent		= silent;
 	if (mysqlnd_get_server_version(conn) >= 50123) {
-		int2store(p, conn->charset->nr);
+		auth_packet->charset_no	= conn->charset->nr;
 		p+=2;
 	}
-
-	if (PASS != conn->m->simple_command(conn, COM_CHANGE_USER, buffer, p - buffer,
-									   PROT_LAST /* we will handle the OK packet*/,
-									   silent, TRUE TSRMLS_CC)) {
-		DBG_RETURN(FAIL);
+
+	if (!PACKET_WRITE(auth_packet, conn)) {
+		CONN_SET_STATE(conn, CONN_QUIT_SENT);
+		SET_CLIENT_ERROR(conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
+		goto end;
 	}

 	chg_user_resp = conn->protocol->m.get_change_user_response_packet(conn->protocol, FALSE TSRMLS_CC);
@@ -2030,6 +2043,7 @@
 		SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, mysqlnd_old_passwd);
 	}
 end:
+	PACKET_FREE(auth_packet);
 	PACKET_FREE(chg_user_resp);

 	/*

Modified: php/php-src/trunk/ext/mysqlnd/mysqlnd_wireprotocol.c
===================================================================
--- php/php-src/trunk/ext/mysqlnd/mysqlnd_wireprotocol.c	2011-01-11 13:01:30 UTC (rev 307376)
+++ php/php-src/trunk/ext/mysqlnd/mysqlnd_wireprotocol.c	2011-01-11 13:02:57 UTC (rev 307377)
@@ -447,7 +447,7 @@
 /* }}} */


-#define AUTH_WRITE_BUFFER_LEN (MYSQLND_HEADER_SIZE + MYSQLND_MAX_ALLOWED_USER_LEN + SHA1_MAX_LENGTH + MYSQLND_MAX_ALLOWED_DB_LEN + 1 + 128)
+#define AUTH_WRITE_BUFFER_LEN (MYSQLND_HEADER_SIZE + MYSQLND_MAX_ALLOWED_USER_LEN + SCRAMBLE_LENGTH + MYSQLND_MAX_ALLOWED_DB_LEN + 1 + 128)

 /* {{{ php_mysqlnd_auth_write */
 static
@@ -460,19 +460,21 @@

 	DBG_ENTER("php_mysqlnd_auth_write");

-	int4store(p, packet->client_flags);
-	p+= 4;
+	if (!packet->is_change_user_packet) {
+		int4store(p, packet->client_flags);
+		p+= 4;

-	int4store(p, packet->max_packet_size);
-	p+= 4;
+		int4store(p, packet->max_packet_size);
+		p+= 4;

-	int1store(p, packet->charset_no);
-	p++;
+		int1store(p, packet->charset_no);
+		p++;

-	memset(p, 0, 23); /* filler */
-	p+= 23;
+		memset(p, 0, 23); /* filler */
+		p+= 23;
+	}

-	if (!packet->send_half_packet) {
+	if (packet->send_auth_data || packet->is_change_user_packet) {
 		len = MIN(strlen(packet->user), MYSQLND_MAX_ALLOWED_USER_LEN);
 		memcpy(p, packet->user, len);
 		p+= len;
@@ -481,10 +483,10 @@
 		/* copy scrambled pass*/
 		if (packet->password && packet->password[0]) {
 			/* In 4.1 we use CLIENT_SECURE_CONNECTION and thus the len of the buf should be passed */
-			int1store(p, SHA1_MAX_LENGTH);
+			int1store(p, SCRAMBLE_LENGTH);
 			p++;
 			php_mysqlnd_scramble((zend_uchar*)p, packet->server_scramble_buf, (zend_uchar*)packet->password);
-			p+= SHA1_MAX_LENGTH;
+			p+= SCRAMBLE_LENGTH;
 		} else {
 			/* Zero length */
 			int1store(p, 0);
@@ -492,16 +494,29 @@
 		}

 		if (packet->db) {
+			/* CLIENT_CONNECT_WITH_DB should have been set */
 			size_t real_db_len = MIN(MYSQLND_MAX_ALLOWED_DB_LEN, packet->db_len);
 			memcpy(p, packet->db, real_db_len);
 			p+= real_db_len;
 			*p++= '\0';
 		}
-		/* Handle CLIENT_CONNECT_WITH_DB */
 		/* no \0 for no DB */
+
+		if (packet->is_change_user_packet && packet->charset_no) {
+			int2store(p, packet->charset_no);
+			p+= 2;
+		}
 	}
-
-	DBG_RETURN(conn->net->m.send(conn, buffer, p - buffer - MYSQLND_HEADER_SIZE TSRMLS_CC));
+	if (packet->is_change_user_packet) {
+		if (PASS != conn->m->simple_command(conn, COM_CHANGE_USER, buffer + MYSQLND_HEADER_SIZE, p - buffer - MYSQLND_HEADER_SIZE,
+										   PROT_LAST /* the caller will handle the OK packet */,
+										   packet->silent, TRUE TSRMLS_CC)) {
+			DBG_RETURN(0);
+		}
+		DBG_RETURN(p - buffer - MYSQLND_HEADER_SIZE);
+	} else {
+		DBG_RETURN(conn->net->m.send(conn, buffer, p - buffer - MYSQLND_HEADER_SIZE TSRMLS_CC));
+	}
 }
 /* }}} */


Modified: php/php-src/trunk/ext/mysqlnd/mysqlnd_wireprotocol.h
===================================================================
--- php/php-src/trunk/ext/mysqlnd/mysqlnd_wireprotocol.h	2011-01-11 13:01:30 UTC (rev 307376)
+++ php/php-src/trunk/ext/mysqlnd/mysqlnd_wireprotocol.h	2011-01-11 13:02:57 UTC (rev 307377)
@@ -101,7 +101,9 @@
 	/* +1 for \0 because of scramble() */
 	unsigned char	*server_scramble_buf;
 	size_t			db_len;
-	zend_bool		send_half_packet;
+	zend_bool		send_auth_data;
+	zend_bool		is_change_user_packet;
+	zend_bool		silent;
 } MYSQLND_PACKET_AUTH;

 /* OK packet */
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to