]> granicus.if.org Git - php/commitdiff
split mysqlnd_connect() in two parts, one doing the authorization
authorAndrey Hristov <andrey@php.net>
Thu, 17 Jun 2010 11:37:49 +0000 (11:37 +0000)
committerAndrey Hristov <andrey@php.net>
Thu, 17 Jun 2010 11:37:49 +0000 (11:37 +0000)
ext/mysqlnd/mysqlnd.c
ext/mysqlnd/mysqlnd_wireprotocol.c

index 10aa5a75c81fd4cbff2c21380ff43a78d11dbdd2..dbaf9d9fdb15a932eaafaa105f8ec181d0d8be69 100644 (file)
@@ -444,6 +444,123 @@ MYSQLND_METHOD(mysqlnd_conn, end_psession)(MYSQLND * conn TSRMLS_DC)
 /* }}} */
 
 
+#define MYSQLND_ASSEBLED_PACKET_MAX_SIZE 3UL*1024UL*1024UL*1024UL
+/* {{{ mysqlnd_connect_run_authentication */
+static enum_func_status
+mysqlnd_connect_run_authentication(
+                       MYSQLND * conn,
+                       const char * const user,
+                       const char * const passwd,
+                       const char * const db,
+                       size_t db_len,
+                       const MYSQLND_PACKET_GREET * const greet_packet,
+                       const MYSQLND_OPTIONS * const options,
+                       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_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) {
+               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;
+       }
+#endif
+       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 PHP_MAJOR_VERSION >= 6
+               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) {
+               SET_OOM_ERROR(conn->error_info);
+               goto err;
+       }
+       memcpy(auth_packet->server_scramble_buf, greet_packet->scramble_buf, SCRAMBLE_LENGTH);
+       
+       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;
+       }
+
+#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  !*/
+                       DBG_ERR(mysqlnd_old_passwd);
+                       SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, mysqlnd_old_passwd);
+               } else if (ok_packet->field_count == 0xFF) {
+                       if (ok_packet->sqlstate[0]) {
+                               strlcpy(conn->error_info.sqlstate, ok_packet->sqlstate, sizeof(conn->error_info.sqlstate));
+                               DBG_ERR_FMT("ERROR:%d [SQLSTATE:%s] %s", ok_packet->error_no, ok_packet->sqlstate, ok_packet->error);
+                       }
+                       conn->error_info.error_no = ok_packet->error_no;
+                       strlcpy(conn->error_info.error, ok_packet->error, sizeof(conn->error_info.error));
+               }
+               goto err;
+       }
+
+       SET_NEW_MESSAGE(conn->last_message, conn->last_message_len,
+                                       ok_packet->message, ok_packet->message_len,
+                                       conn->persistent);
+       conn->charset = mysqlnd_find_charset_nr(auth_packet->charset_no);
+       ret = PASS;
+err:
+       PACKET_FREE(auth_packet);
+       PACKET_FREE(ok_packet);
+       DBG_RETURN(ret);        
+}
+/* }}} */
+
+
+#define MYSQLND_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_TRANSACTIONS | \
+                               CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION | \
+                               CLIENT_MULTI_RESULTS)
+
+
+
 /* {{{ mysqlnd_conn::connect */
 static enum_func_status
 MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
@@ -457,15 +574,11 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
 {
        char *errstr = NULL;
        int errcode = 0, host_len;
-       zend_bool self_alloced = FALSE;
        zend_bool unix_socket = FALSE;
-       const MYSQLND_CHARSET * charset;
        zend_bool reconnect = FALSE;
        zend_bool saved_compression = FALSE;
 
        MYSQLND_PACKET_GREET * greet_packet = NULL;
-       MYSQLND_PACKET_AUTH * auth_packet = NULL;
-       MYSQLND_PACKET_OK * ok_packet = NULL;
 
        DBG_ENTER("mysqlnd_conn::connect");
 
@@ -536,7 +649,6 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
                        if (!port) {
                                port = 3306;
                        }
-
                        transport_len = spprintf(&transport, 0, "tcp://%s:%d", host, port);
                }
                if (!transport) {
@@ -554,9 +666,7 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
        }
 
        greet_packet = conn->protocol->m.get_greet_packet(conn->protocol, FALSE TSRMLS_CC);
-       auth_packet = conn->protocol->m.get_auth_packet(conn->protocol, FALSE TSRMLS_CC);
-       ok_packet = conn->protocol->m.get_ok_packet(conn->protocol, FALSE TSRMLS_CC);
-       if (!greet_packet || !auth_packet || !ok_packet) {
+       if (!greet_packet) {
                SET_OOM_ERROR(conn->error_info);
                goto err; /* OOM */
        }
@@ -590,7 +700,17 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
 
        conn->greet_charset = mysqlnd_find_charset_nr(greet_packet->charset_no);
        /* we allow load data local infile by default */
-       mysql_flags  |= CLIENT_LOCAL_FILES | CLIENT_PS_MULTI_RESULTS;
+       mysql_flags |= CLIENT_LOCAL_FILES | CLIENT_PS_MULTI_RESULTS;
+       mysql_flags |= MYSQLND_CAPABILITIES;
+
+       if (db) {
+               mysql_flags |= CLIENT_CONNECT_WITH_DB;
+       }
+
+       if (PG(open_basedir) && strlen(PG(open_basedir))) {
+               mysql_flags ^= CLIENT_LOCAL_FILES;
+       }
+
 #ifndef MYSQLND_COMPRESSION_ENABLED
        if (mysql_flags & CLIENT_COMPRESS) {
                mysql_flags &= ~CLIENT_COMPRESS;
@@ -606,81 +726,16 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
        {
                mysql_flags |= CLIENT_SSL;
        }
-       if ((greet_packet->server_capabilities & CLIENT_SSL) && (mysql_flags & CLIENT_SSL)) {
-               auth_packet->send_half_packet = TRUE;
-       }
 #endif
-       auth_packet->user               = user;
-       auth_packet->password   = passwd;
 
-       if (conn->options.charset_name && (charset = mysqlnd_find_charset_name(conn->options.charset_name))) {
-               auth_packet->charset_no = charset->nr;
-       } else {
-#if PHP_MAJOR_VERSION >= 6
-               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= 3UL*1024UL*1024UL*1024UL;
-       auth_packet->client_flags= mysql_flags;
-
-       conn->scramble = auth_packet->server_scramble_buf = mnd_pemalloc(SCRAMBLE_LENGTH, conn->persistent);
-       if (!conn->scramble) {
-               SET_OOM_ERROR(conn->error_info);
-               goto err; /* OOM */
-       }
-       memcpy(auth_packet->server_scramble_buf, greet_packet->scramble_buf, SCRAMBLE_LENGTH);
-       
-       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);
+       if (FAIL == mysqlnd_connect_run_authentication(conn, user, passwd, db, db_len, greet_packet, &conn->options, mysql_flags TSRMLS_CC)) {
                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  !*/
-                       DBG_ERR(mysqlnd_old_passwd);
-                       SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, mysqlnd_old_passwd);
-               } else if (ok_packet->field_count == 0xFF) {
-                       if (ok_packet->sqlstate[0]) {
-                               if (!self_alloced) {
-                                       strlcpy(conn->error_info.sqlstate, ok_packet->sqlstate, sizeof(conn->error_info.sqlstate));
-                               }
-                               DBG_ERR_FMT("ERROR:%d [SQLSTATE:%s] %s", ok_packet->error_no, ok_packet->sqlstate, ok_packet->error);
-                       }
-                       if (!self_alloced) {
-                               conn->error_info.error_no = ok_packet->error_no;
-                               strlcpy(conn->error_info.error, ok_packet->error, sizeof(conn->error_info.error));
-                       }
-               }
-       } else {
+       {
                CONN_SET_STATE(conn, CONN_READY);
 
-               if (!self_alloced && saved_compression) {
+               if (saved_compression) {
                        conn->net->compressed = TRUE;
                }
                /*
@@ -733,32 +788,18 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
                        }
                        conn->unix_socket_len = strlen(conn->unix_socket);
                }
-               conn->client_flag               = auth_packet->client_flags;
-               conn->max_packet_size   = auth_packet->max_packet_size;
+               conn->client_flag               = mysql_flags;
+               conn->max_packet_size   = MYSQLND_ASSEBLED_PACKET_MAX_SIZE;
                /* todo: check if charset is available */
-               conn->charset                   = mysqlnd_find_charset_nr(auth_packet->charset_no);
                conn->server_capabilities = greet_packet->server_capabilities;
                conn->upsert_status.warning_count = 0;
                conn->upsert_status.server_status = greet_packet->server_status;
                conn->upsert_status.affected_rows = 0;
-               SET_NEW_MESSAGE(conn->last_message, conn->last_message_len,
-                                               ok_packet->message, ok_packet->message_len,
-                                               conn->persistent);
 
                SET_EMPTY_ERROR(conn->error_info);
 
                mysqlnd_local_infile_default(conn);
 
-               MYSQLND_INC_CONN_STATISTIC_W_VALUE2(conn->stats, STAT_CONNECT_SUCCESS, 1, STAT_OPENED_CONNECTIONS, 1);
-               if (reconnect) {
-                       MYSQLND_INC_GLOBAL_STATISTIC(STAT_RECONNECT);
-               }
-               if (conn->persistent) {
-                       MYSQLND_INC_CONN_STATISTIC_W_VALUE2(conn->stats, STAT_PCONNECT_SUCCESS, 1, STAT_OPENED_PERSISTENT_CONNECTIONS, 1);
-               }
-
-               DBG_INF_FMT("connection_id=%llu", conn->thread_id);
-
 #if PHP_MAJOR_VERSION >= 6
                {
                        unsigned int as_unicode = 1;
@@ -786,16 +827,23 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn,
                        }
                }
 
+
+               MYSQLND_INC_CONN_STATISTIC_W_VALUE2(conn->stats, STAT_CONNECT_SUCCESS, 1, STAT_OPENED_CONNECTIONS, 1);
+               if (reconnect) {
+                       MYSQLND_INC_GLOBAL_STATISTIC(STAT_RECONNECT);
+               }
+               if (conn->persistent) {
+                       MYSQLND_INC_CONN_STATISTIC_W_VALUE2(conn->stats, STAT_PCONNECT_SUCCESS, 1, STAT_OPENED_PERSISTENT_CONNECTIONS, 1);
+               }
+
+               DBG_INF_FMT("connection_id=%llu", conn->thread_id);
+
                PACKET_FREE(greet_packet);
-               PACKET_FREE(auth_packet);
-               PACKET_FREE(ok_packet);
 
                DBG_RETURN(PASS);
        }
 err:
        PACKET_FREE(greet_packet);
-       PACKET_FREE(auth_packet);
-       PACKET_FREE(ok_packet);
 
        if (errstr) {
                DBG_ERR_FMT("[%d] %.64s (trying to connect via %s)", errcode, errstr, conn->scheme);
@@ -804,11 +852,6 @@ err:
                /* no mnd_ since we don't allocate it */
                efree(errstr);
        }
-       if (conn->scheme) {
-               /* no mnd_ since we don't allocate it */
-               mnd_pefree(conn->scheme, conn->persistent);
-               conn->scheme = NULL;
-       }
 
        MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_CONNECT_FAILURE);
 
index 0dd076d28e72e2eab613a79fc1ae1f70d123b6ca..b5887c2f81a4f74c2f8cbdbcdf7ddedba38f55ac 100644 (file)
@@ -405,11 +405,6 @@ void php_mysqlnd_greet_free_mem(void *_packet, zend_bool alloca TSRMLS_DC)
 /* }}} */
 
 
-#define MYSQLND_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_TRANSACTIONS | \
-                               CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION | \
-                               CLIENT_MULTI_RESULTS)
-
-
 /* {{{ php_mysqlnd_crypt */
 static void
 php_mysqlnd_crypt(zend_uchar *buffer, const zend_uchar *s1, const zend_uchar *s2, size_t len)
@@ -465,16 +460,6 @@ size_t php_mysqlnd_auth_write(void *_packet, MYSQLND * conn TSRMLS_DC)
 
        DBG_ENTER("php_mysqlnd_auth_write");
 
-       packet->client_flags |= MYSQLND_CAPABILITIES;
-
-       if (packet->db) {
-               packet->client_flags |= CLIENT_CONNECT_WITH_DB;
-       }
-
-       if (PG(open_basedir) && strlen(PG(open_basedir))) {
-               packet->client_flags ^= CLIENT_LOCAL_FILES;
-       }
-
        int4store(p, packet->client_flags);
        p+= 4;