]> granicus.if.org Git - php/commitdiff
MNDR:
authorAndrey Hristov <andrey@php.net>
Thu, 5 Nov 2015 14:26:33 +0000 (15:26 +0100)
committerAndrey Hristov <andrey@php.net>
Thu, 12 Nov 2015 15:19:16 +0000 (16:19 +0100)
- move connection establishment code to own command - COM_HANDSHAKE

ext/mysqlnd/mysqlnd.c
ext/mysqlnd/mysqlnd.h
ext/mysqlnd/mysqlnd_enum_n_def.h
ext/mysqlnd/mysqlnd_priv.h
ext/mysqlnd/mysqlnd_structs.h
ext/mysqlnd/mysqlnd_wireprotocol.c
ext/mysqlnd/mysqlnd_wireprotocol.h

index a8394ab2d233d2720c831720a61aa8f7de3a6cca..80ca681ea0a64b491511d97009178da6ba31a317 100644 (file)
@@ -305,9 +305,9 @@ MYSQLND_METHOD(mysqlnd_conn_data, free_contents)(MYSQLND_CONN_DATA * conn)
                mnd_pefree(conn->host_info, pers);
                conn->host_info = NULL;
        }
-       if (conn->auth_plugin_data) {
-               mnd_pefree(conn->auth_plugin_data, pers);
-               conn->auth_plugin_data = NULL;
+       if (conn->authentication_plugin_data.s) {
+               mnd_pefree(conn->authentication_plugin_data.s, pers);
+               conn->authentication_plugin_data.s = NULL;
        }
        if (conn->last_message.s) {
                mnd_pefree(conn->last_message.s, pers);
@@ -408,24 +408,21 @@ MYSQLND_METHOD(mysqlnd_conn_data, end_psession)(MYSQLND_CONN_DATA * conn)
 static enum_func_status
 mysqlnd_switch_to_ssl_if_needed(
                        MYSQLND_CONN_DATA * conn,
-                       const MYSQLND_PACKET_GREET * const greet_packet,
+                       unsigned int charset_no,
+                       size_t server_capabilities,
                        const MYSQLND_SESSION_OPTIONS * const session_options,
                        zend_ulong mysql_flags)
 {
        enum_func_status ret = FAIL;
        const MYSQLND_CHARSET * charset;
-       unsigned int charset_no;
        DBG_ENTER("mysqlnd_switch_to_ssl_if_needed");
 
        if (session_options->charset_name && (charset = mysqlnd_find_charset_name(session_options->charset_name))) {
                charset_no      = charset->nr;
-       } else {
-               charset_no      = greet_packet->charset_no;
        }
 
        {
                size_t client_capabilities = mysql_flags;
-               size_t server_capabilities = greet_packet->server_capabilities;
                struct st_mysqlnd_protocol_command * command = conn->command_factory(COM_ENABLE_SSL, conn, client_capabilities, server_capabilities, charset_no);
                if (command) {
                        ret = command->run(command);
@@ -464,8 +461,7 @@ mysqlnd_run_authentication(
                        const size_t passwd_len,
                        const char * const db,
                        const size_t db_len,
-                       const zend_uchar * const auth_plugin_data,
-                       const size_t auth_plugin_data_len,
+                       const MYSQLND_STRING auth_plugin_data,
                        const char * const auth_protocol,
                        unsigned int charset_no,
                        const MYSQLND_SESSION_OPTIONS * const session_options,
@@ -485,12 +481,12 @@ mysqlnd_run_authentication(
 
        DBG_ENTER("mysqlnd_run_authentication");
 
-       plugin_data_len = auth_plugin_data_len;
+       plugin_data_len = auth_plugin_data.l;
        plugin_data = mnd_emalloc(plugin_data_len + 1);
        if (!plugin_data) {
                goto end;
        }
-       memcpy(plugin_data, auth_plugin_data, plugin_data_len);
+       memcpy(plugin_data, auth_plugin_data.s, plugin_data_len);
        plugin_data[plugin_data_len] = '\0';
 
        requested_protocol = mnd_pestrdup(auth_protocol? auth_protocol : MYSQLND_DEFAULT_AUTH_PROTOCOL, FALSE);
@@ -517,17 +513,17 @@ mysqlnd_run_authentication(
                        switch_to_auth_protocol = NULL;
                        switch_to_auth_protocol_len = 0;
 
-                       if (conn->auth_plugin_data) {
-                               mnd_pefree(conn->auth_plugin_data, conn->persistent);
-                               conn->auth_plugin_data = NULL;
+                       if (conn->authentication_plugin_data.s) {
+                               mnd_pefree(conn->authentication_plugin_data.s, conn->persistent);
+                               conn->authentication_plugin_data.s = NULL;
                        }
-                       conn->auth_plugin_data_len = plugin_data_len;
-                       conn->auth_plugin_data = mnd_pemalloc(conn->auth_plugin_data_len, conn->persistent);
-                       if (!conn->auth_plugin_data) {
+                       conn->authentication_plugin_data.l = plugin_data_len;
+                       conn->authentication_plugin_data.s = mnd_pemalloc(conn->authentication_plugin_data.l, conn->persistent);
+                       if (!conn->authentication_plugin_data.s) {
                                SET_OOM_ERROR(conn->error_info);
                                goto end;
                        }
-                       memcpy(conn->auth_plugin_data, plugin_data, plugin_data_len);
+                       memcpy(conn->authentication_plugin_data.s, plugin_data, plugin_data_len);
 
                        DBG_INF_FMT("salt(%d)=[%.*s]", plugin_data_len, plugin_data_len, plugin_data);
                        /* The data should be allocated with malloc() */
@@ -592,7 +588,7 @@ end:
 
 
 /* {{{ mysqlnd_connect_run_authentication */
-static enum_func_status
+enum_func_status
 mysqlnd_connect_run_authentication(
                        MYSQLND_CONN_DATA * conn,
                        const char * const user,
@@ -600,7 +596,10 @@ mysqlnd_connect_run_authentication(
                        const char * const db,
                        size_t db_len,
                        size_t passwd_len,
-                       const MYSQLND_PACKET_GREET * const greet_packet,
+                       MYSQLND_STRING authentication_plugin_data,
+                       const char * const authentication_protocol,
+                       const unsigned int charset_no,
+                       size_t server_capabilities,
                        const MYSQLND_SESSION_OPTIONS * const session_options,
                        zend_ulong mysql_flags
                        )
@@ -608,11 +607,11 @@ mysqlnd_connect_run_authentication(
        enum_func_status ret = FAIL;
        DBG_ENTER("mysqlnd_connect_run_authentication");
 
-       ret = mysqlnd_switch_to_ssl_if_needed(conn, greet_packet, session_options, mysql_flags);
+       ret = mysqlnd_switch_to_ssl_if_needed(conn, charset_no, server_capabilities, session_options, mysql_flags);
        if (PASS == ret) {
                ret = mysqlnd_run_authentication(conn, user, passwd, passwd_len, db, db_len,
-                                                                                greet_packet->auth_plugin_data, greet_packet->auth_plugin_data_len, greet_packet->auth_protocol,
-                                                                                greet_packet->charset_no, session_options, mysql_flags, FALSE /*silent*/, FALSE/*is_change*/);
+                                                                                authentication_plugin_data, authentication_protocol,
+                                                                                charset_no, session_options, mysql_flags, FALSE /*silent*/, FALSE/*is_change*/);
        }
        DBG_RETURN(ret);
 }
@@ -696,77 +695,25 @@ MYSQLND_METHOD(mysqlnd_conn_data, get_updated_connect_flags)(MYSQLND_CONN_DATA *
 /* {{{ mysqlnd_conn_data::connect_handshake */
 static enum_func_status
 MYSQLND_METHOD(mysqlnd_conn_data, connect_handshake)(MYSQLND_CONN_DATA * conn,
-                                               const char * const host, const char * const user,
-                                               const char * const passwd, const unsigned int passwd_len,
-                                               const char * const db, const unsigned int db_len,
+                                               const MYSQLND_CSTRING * const username,
+                                               const MYSQLND_CSTRING * const password,
+                                               const MYSQLND_CSTRING * const database,
                                                const unsigned int mysql_flags)
 {
-       MYSQLND_PACKET_GREET * greet_packet;
-       MYSQLND_NET * net = conn->net;
-
+       enum_func_status ret = FAIL;
+       size_t client_flags = mysql_flags;
        DBG_ENTER("mysqlnd_conn_data::connect_handshake");
 
-       greet_packet = conn->payload_decoder_factory->m.get_greet_packet(conn->payload_decoder_factory, FALSE);
-       if (!greet_packet) {
-               SET_OOM_ERROR(conn->error_info);
-               DBG_RETURN(FAIL); /* OOM */
-       }
-
-       if (FAIL == net->data->m.connect_ex(conn->net, conn->scheme, conn->persistent,
-                                                                               conn->stats, conn->error_info))
-       {
-               goto err;
-       }
-
-       DBG_INF_FMT("stream=%p", net->data->m.get_stream(net));
-
-       if (FAIL == PACKET_READ(greet_packet)) {
-               DBG_ERR("Error while reading greeting packet");
-               php_error_docref(NULL, E_WARNING, "Error while reading greeting packet. PID=%d", getpid());
-               goto err;
-       } else if (greet_packet->error_no) {
-               DBG_ERR_FMT("errorno=%u error=%s", greet_packet->error_no, greet_packet->error);
-               SET_CLIENT_ERROR(conn->error_info, greet_packet->error_no, greet_packet->sqlstate, greet_packet->error);
-               goto err;
-       } else if (greet_packet->pre41) {
-               DBG_ERR_FMT("Connecting to 3.22, 3.23 & 4.0 is not supported. Server is %-.32s", greet_packet->server_version);
-               php_error_docref(NULL, E_WARNING, "Connecting to 3.22, 3.23 & 4.0 "
-                                               " is not supported. Server is %-.32s", greet_packet->server_version);
-               SET_CLIENT_ERROR(conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE,
-                                                "Connecting to 3.22, 3.23 & 4.0 servers is not supported");
-               goto err;
-       }
-
-       conn->thread_id                 = greet_packet->thread_id;
-       conn->protocol_version  = greet_packet->protocol_version;
-       conn->server_version    = mnd_pestrdup(greet_packet->server_version, conn->persistent);
-
-       conn->greet_charset = mysqlnd_find_charset_nr(greet_packet->charset_no);
-       if (!conn->greet_charset) {
-               php_error_docref(NULL, E_WARNING,
-                       "Server sent charset (%d) unknown to the client. Please, report to the developers", greet_packet->charset_no);
-               SET_CLIENT_ERROR(conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE,
-                       "Server sent charset unknown to the client. Please, report to the developers");
-               goto err;
-       }
-
-       conn->server_capabilities       = greet_packet->server_capabilities;
-
-       if (FAIL == mysqlnd_connect_run_authentication(conn, user, passwd, db, db_len, (size_t) passwd_len,
-                                                                                                  greet_packet, conn->options, mysql_flags))
-       {
-               goto err;
+       if (FAIL == conn->net->data->m.connect_ex(conn->net, conn->scheme, conn->persistent, conn->stats, conn->error_info)) {
+               DBG_RETURN(FAIL);
+       } else {
+               struct st_mysqlnd_protocol_command * command = conn->command_factory(COM_HANDSHAKE, conn, username, password, database, client_flags);
+               if (command) {
+                       ret = command->run(command);
+                       command->free_command(command);
+               }
        }
-
-       UPSERT_STATUS_RESET(conn->upsert_status);
-       UPSERT_STATUS_SET_SERVER_STATUS(conn->upsert_status, greet_packet->server_status);
-
-       PACKET_FREE(greet_packet);
-       DBG_RETURN(PASS);
-err:
-       conn->server_capabilities = 0;
-       PACKET_FREE(greet_packet);
-       DBG_RETURN(FAIL);
+       DBG_RETURN(ret);
 }
 /* }}} */
 
@@ -774,16 +721,16 @@ err:
 /* {{{ mysqlnd_conn_data::connect */
 static enum_func_status
 MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn,
-                                                const char *host, const char *user,
-                                                const char *passwd, unsigned int passwd_len,
-                                                const char *db, unsigned int db_len,
-                                                unsigned int port,
-                                                const char *socket_or_pipe,
-                                                unsigned int mysql_flags
-                                               )
+                                               MYSQLND_CSTRING hostname,
+                                               MYSQLND_CSTRING username,
+                                               MYSQLND_CSTRING password,
+                                               MYSQLND_CSTRING database,
+                                               unsigned int port,
+                                               MYSQLND_CSTRING socket_or_pipe,
+                                               unsigned int mysql_flags
+                                       )
 {
        const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), connect);
-       size_t host_len;
        zend_bool unix_socket = FALSE;
        zend_bool named_pipe = FALSE;
        zend_bool reconnect = FALSE;
@@ -803,7 +750,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn,
        UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
 
        DBG_INF_FMT("host=%s user=%s db=%s port=%u flags=%u persistent=%u state=%u",
-                               host?host:"", user?user:"", db?db:"", port, mysql_flags,
+                               hostname.s?hostname.s:"", username.s?username.s:"", database.s?database.s:"", port, mysql_flags,
                                conn? conn->persistent:0, conn? GET_CONNECTION_STATE(&conn->state):-1);
 
        if (GET_CONNECTION_STATE(&conn->state) > CONN_ALLOCED && GET_CONNECTION_STATE(&conn->state) ) {
@@ -838,52 +785,55 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn,
                conn->m->set_client_option(conn, MYSQLND_OPT_MAX_ALLOWED_PACKET, (char *)&max_allowed_size);
        }
 
-       if (!host || !host[0]) {
-               host = "localhost";
+       if (!hostname.s || !hostname.s[0]) {
+               hostname.s = "localhost";
+               hostname.l = strlen(hostname.s);
        }
-       if (!user) {
+       if (!username.s) {
                DBG_INF_FMT("no user given, using empty string");
-               user = "";
+               username.s = "";
+               username.l = 0;
        }
-       if (!passwd) {
+       if (!password.s) {
                DBG_INF_FMT("no password given, using empty string");
-               passwd = "";
-               passwd_len = 0;
+               password.s = "";
+               password.l = 0;
        }
-       if (!db) {
+       if (!database.s) {
                DBG_INF_FMT("no db given, using empty string");
-               db = "";
-               db_len = 0;
+               database.s = "";
+               database.l = 0;
        } else {
                mysql_flags |= CLIENT_CONNECT_WITH_DB;
        }
 
-       host_len = strlen(host);
        {
                char * transport = NULL;
                int transport_len;
 #ifndef PHP_WIN32
-               if (host_len == sizeof("localhost") - 1 && !strncasecmp(host, "localhost", host_len)) {
-                       DBG_INF_FMT("socket=%s", socket_or_pipe? socket_or_pipe:"n/a");
-                       if (!socket_or_pipe) {
-                               socket_or_pipe = "/tmp/mysql.sock";
+               if (hostname.l == sizeof("localhost") - 1 && !strncasecmp(hostname.s, "localhost", hostname.l)) {
+                       DBG_INF_FMT("socket=%s", socket_or_pipe.s? socket_or_pipe.s:"n/a");
+                       if (!socket_or_pipe.s) {
+                               socket_or_pipe.s = "/tmp/mysql.sock";
+                               socket_or_pipe.l = strlen(socket_or_pipe.s);
                        }
-                       transport_len = mnd_sprintf(&transport, 0, "unix://%s", socket_or_pipe);
+                       transport_len = mnd_sprintf(&transport, 0, "unix://%s", socket_or_pipe.s);
                        unix_socket = TRUE;
 #else
-               if (host_len == sizeof(".") - 1 && host[0] == '.') {
+               if (hostname.l == sizeof(".") - 1 && hostname.s[0] == '.') {
                        /* named pipe in socket */
-                       if (!socket_or_pipe) {
-                               socket_or_pipe = "\\\\.\\pipe\\MySQL";
+                       if (!socket_or_pipe.s) {
+                               socket_or_pipe.s = "\\\\.\\pipe\\MySQL";
+                               socket_or_pipe.l = strlen(socket_or_pipe.s);
                        }
-                       transport_len = mnd_sprintf(&transport, 0, "pipe://%s", socket_or_pipe);
+                       transport_len = mnd_sprintf(&transport, 0, "pipe://%s", socket_or_pipe.s);
                        named_pipe = TRUE;
 #endif
                } else {
                        if (!port) {
                                port = 3306;
                        }
-                       transport_len = mnd_sprintf(&transport, 0, "tcp://%s:%u", host, port);
+                       transport_len = mnd_sprintf(&transport, 0, "tcp://%s:%u", hostname.s, port);
                }
                if (!transport) {
                        SET_OOM_ERROR(conn->error_info);
@@ -901,8 +851,11 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn,
 
        mysql_flags = conn->m->get_updated_connect_flags(conn, mysql_flags);
 
-       if (FAIL == conn->m->connect_handshake(conn, host, user, passwd, passwd_len, db, db_len, mysql_flags)) {
-               goto err;
+       {
+       
+               if (FAIL == conn->m->connect_handshake(conn, &username, &password, &database, mysql_flags)) {
+                       goto err;
+               }
        }
 
        {
@@ -918,13 +871,13 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn,
                */
                net->data->compressed = mysql_flags & CLIENT_COMPRESS? TRUE:FALSE;
 
-               conn->user_len                  = strlen(user);
-               conn->user                              = mnd_pestrndup(user, conn->user_len, conn->persistent);
-               conn->passwd                    = mnd_pestrndup(passwd, passwd_len, conn->persistent);
-               conn->passwd_len                = passwd_len;
+               conn->user_len                  = username.l;
+               conn->user                              = mnd_pestrndup(username.s, conn->user_len, conn->persistent);
+               conn->passwd                    = mnd_pestrndup(password.s, password.l, conn->persistent);
+               conn->passwd_len                = password.l;
                conn->port                              = port;
-               conn->connect_or_select_db.s = mnd_pestrndup(db, db_len, conn->persistent);
-               conn->connect_or_select_db.l = db_len;
+               conn->connect_or_select_db.s = mnd_pestrndup(database.s, database.l, conn->persistent);
+               conn->connect_or_select_db.l = database.l;
 
                if (!conn->user || !conn->passwd || !conn->connect_or_select_db.s) {
                        SET_OOM_ERROR(conn->error_info);
@@ -932,12 +885,12 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn,
                }
 
                if (!unix_socket && !named_pipe) {
-                       conn->host = mnd_pestrndup(host, host_len, conn->persistent);
+                       conn->host = mnd_pestrndup(hostname.s, hostname.l, conn->persistent);
                        if (!conn->host) {
                                SET_OOM_ERROR(conn->error_info);
                                goto err; /* OOM */
                        }
-                       conn->host_len = host_len;
+                       conn->host_len = hostname.l;
                        {
                                char *p;
                                mnd_sprintf(&p, 0, "%s via TCP/IP", conn->host);
@@ -953,7 +906,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn,
                                }
                        }
                } else {
-                       conn->unix_socket = mnd_pestrdup(socket_or_pipe, conn->persistent);
+                       conn->unix_socket = mnd_pestrdup(socket_or_pipe.s, conn->persistent);
                        if (unix_socket) {
                                conn->host_info = mnd_pestrdup("Localhost via UNIX socket", conn->persistent);
                        } else if (named_pipe) {
@@ -1024,12 +977,13 @@ err:
 /* {{{ mysqlnd_conn::connect */
 static enum_func_status
 MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn_handle,
-                                                const char * host, const char * user,
-                                                const char * passwd, unsigned int passwd_len,
-                                                const char * db, unsigned int db_len,
-                                                unsigned int port,
-                                                const char * socket_or_pipe,
-                                                unsigned int mysql_flags
+                                               const MYSQLND_CSTRING hostname,
+                                               const MYSQLND_CSTRING username,
+                                               const MYSQLND_CSTRING password,
+                                               const MYSQLND_CSTRING database,
+                                               unsigned int port,
+                                               const MYSQLND_CSTRING socket_or_pipe,
+                                               unsigned int mysql_flags
                                                )
 {
        const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), connect);
@@ -1040,7 +994,7 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn_handle,
 
        if (PASS == conn->m->local_tx_start(conn, this_func)) {
                mysqlnd_options4(conn_handle, MYSQL_OPT_CONNECT_ATTR_ADD, "_client_name", "mysqlnd");
-               ret = conn->m->connect(conn, host, user, passwd, passwd_len, db, db_len, port, socket_or_pipe, mysql_flags);
+               ret = conn->m->connect(conn, hostname, username, password, database, port, socket_or_pipe, mysql_flags);
 
                conn->m->local_tx_end(conn, this_func, FAIL);
        }
@@ -1051,20 +1005,26 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn_handle,
 
 /* {{{ mysqlnd_connect */
 PHPAPI MYSQLND * mysqlnd_connection_connect(MYSQLND * conn_handle,
-                                                                                       const char * host, const char * user,
-                                                                                       const char * passwd, unsigned int passwd_len,
-                                                                                       const char * db, unsigned int db_len,
+                                                                                       const char * const host,
+                                                                                       const char * const user,
+                                                                                       const char * const passwd, unsigned int passwd_len,
+                                                                                       const char * const db, unsigned int db_len,
                                                                                        unsigned int port,
-                                                                                       const char * socket_or_pipe,
+                                                                                       const char * const sock_or_pipe,
                                                                                        unsigned int mysql_flags,
                                                                                        unsigned int client_api_flags
                                                )
 {
        enum_func_status ret = FAIL;
        zend_bool self_alloced = FALSE;
+       MYSQLND_CSTRING hostname = { host, host? strlen(host) : 0 };
+       MYSQLND_CSTRING username = { user, user? strlen(user) : 0 };
+       MYSQLND_CSTRING password = { passwd, passwd_len };
+       MYSQLND_CSTRING database = { db, db_len };
+       MYSQLND_CSTRING socket_or_pipe = { sock_or_pipe, sock_or_pipe? strlen(sock_or_pipe) : 0 };
 
        DBG_ENTER("mysqlnd_connect");
-       DBG_INF_FMT("host=%s user=%s db=%s port=%u flags=%u", host?host:"", user?user:"", db?db:"", port, mysql_flags);
+       DBG_INF_FMT("host=%s user=%s db=%s port=%u flags=%u", host? host:"", user? user:"", db? db:"", port, mysql_flags);
 
        if (!conn_handle) {
                self_alloced = TRUE;
@@ -1074,7 +1034,7 @@ PHPAPI MYSQLND * mysqlnd_connection_connect(MYSQLND * conn_handle,
                }
        }
 
-       ret = conn_handle->m->connect(conn_handle, host, user, passwd, passwd_len, db, db_len, port, socket_or_pipe, mysql_flags);
+       ret = conn_handle->m->connect(conn_handle, hostname, username, password, database, port, socket_or_pipe, mysql_flags);
 
        if (ret == FAIL) {
                if (self_alloced) {
@@ -2087,7 +2047,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, change_user)(MYSQLND_CONN_DATA * const conn,
 
        /* XXX: passwords that have \0 inside work during auth, but in this case won't work with change user */
        ret = mysqlnd_run_authentication(conn, user, passwd, passwd_len, db, strlen(db),
-                                                                       conn->auth_plugin_data, conn->auth_plugin_data_len, conn->options->auth_protocol,
+                                                                        conn->authentication_plugin_data, conn->options->auth_protocol,
                                                                        0 /*charset not used*/, conn->options, conn->server_capabilities, silent, TRUE/*is_change*/);
 
        /*
index d49f7651081de3adb79296889a0eb04fbf60aba6..f683562811112c34e82770785417957c86d5dc1c 100644 (file)
@@ -89,11 +89,12 @@ PHPAPI const MYSQLND_CHARSET * mysqlnd_find_charset_name(const char * const char
 
 PHPAPI MYSQLND * mysqlnd_connection_init(unsigned int client_flags, zend_bool persistent, struct st_mysqlnd_object_factory_methods * object_factory);
 PHPAPI MYSQLND * mysqlnd_connection_connect(MYSQLND * conn,
-                                                                                       const char * host, const char * user,
-                                                                                       const char * passwd, unsigned int passwd_len,
-                                                                                       const char * db, unsigned int db_len,
+                                                                                       const char * const host,
+                                                                                       const char * const user,
+                                                                                       const char * const passwd, unsigned int passwd_len,
+                                                                                       const char * const db, unsigned int db_len,
                                                                                        unsigned int port,
-                                                                                       const char * socket_or_pipe,
+                                                                                       const char * const socket_or_pipe,
                                                                                        unsigned int mysql_flags,
                                                                                        unsigned int client_api_flags
                                                                                );
index ad64fc1a414a261321fb4a3d8ffec641ebbdc5f3..f48ae1d96837cd09086d8f0d4ab2b0309591d0c3 100644 (file)
@@ -640,8 +640,9 @@ enum php_mysqlnd_server_command
        COM_STMT_EXECUTE_BATCH = 32,
        COM_END,
        /* Here follow own, non-protocol, commands */
-       COM_REAP_RESULT=240, /* own command */
-       COM_ENABLE_SSL,
+       COM_REAP_RESULT=240,    /* own command */
+       COM_ENABLE_SSL,                 /* own command */
+       COM_HANDSHAKE,                  /* own command */
 };
 
 
index e737d9cac51440975add87a5117c93a0b41df5a8..a0a061f4ee9f8e60fff0fc3e8102922ddffbf428 100644 (file)
@@ -232,6 +232,23 @@ send_command_handle_response(
                MYSQLND_STRING * last_message,
                zend_bool last_message_persistent
        );
+
+enum_func_status
+mysqlnd_connect_run_authentication(
+                       MYSQLND_CONN_DATA * conn,
+                       const char * const user,
+                       const char * const passwd,
+                       const char * const db,
+                       size_t db_len,
+                       size_t passwd_len,
+                       MYSQLND_STRING authentication_plugin_data,
+                       const char * const authentication_protocol,
+                       const unsigned int charset_no,
+                       size_t server_capabilities,
+                       const MYSQLND_SESSION_OPTIONS * const session_options,
+                       zend_ulong mysql_flags
+                       );
+
 #endif /* MYSQLND_PRIV_H */
 
 
index 27d2d0e5e71f6d90fe2eb7c4280abdfe31eecd2e..61a6fdfae1c73cad778b5b9cb00617b9c2eb5fbe 100644 (file)
@@ -460,7 +460,7 @@ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_object_factory)
 };
 
 
-typedef enum_func_status       (*func_mysqlnd_conn_data__connect)(MYSQLND_CONN_DATA * conn, const char * host, const char * user, const char * passwd, unsigned int passwd_len, const char * db, unsigned int db_len, unsigned int port, const char * socket_or_pipe, unsigned int mysql_flags);
+typedef enum_func_status       (*func_mysqlnd_conn_data__connect)(MYSQLND_CONN_DATA * conn, MYSQLND_CSTRING hostname, MYSQLND_CSTRING username, MYSQLND_CSTRING password, MYSQLND_CSTRING database, unsigned int port, MYSQLND_CSTRING socket_or_pipe, unsigned int mysql_flags);
 typedef zend_ulong                     (*func_mysqlnd_conn_data__escape_string)(MYSQLND_CONN_DATA * const conn, char *newstr, const char *escapestr, size_t escapestr_len);
 typedef enum_func_status       (*func_mysqlnd_conn_data__set_charset)(MYSQLND_CONN_DATA * const conn, const char * const charset);
 typedef enum_func_status       (*func_mysqlnd_conn_data__query)(MYSQLND_CONN_DATA * conn, const char * query, unsigned int query_len);
@@ -539,7 +539,7 @@ typedef enum_func_status    (*func_mysqlnd_conn_data__local_tx_start)(MYSQLND_CONN_
 typedef enum_func_status       (*func_mysqlnd_conn_data__local_tx_end)(MYSQLND_CONN_DATA * conn, size_t this_func, enum_func_status status);
 typedef enum_func_status       (*func_mysqlnd_conn_data__execute_init_commands)(MYSQLND_CONN_DATA * conn);
 typedef unsigned int           (*func_mysqlnd_conn_data__get_updated_connect_flags)(MYSQLND_CONN_DATA * conn, unsigned int mysql_flags);
-typedef enum_func_status       (*func_mysqlnd_conn_data__connect_handshake)(MYSQLND_CONN_DATA * conn, const char * const host, const char * const user, const char * const passwd, const unsigned int passwd_len, const char * const db, const unsigned int db_len, const unsigned int mysql_flags);
+typedef enum_func_status       (*func_mysqlnd_conn_data__connect_handshake)(MYSQLND_CONN_DATA * conn, const MYSQLND_CSTRING * const username, const MYSQLND_CSTRING * const password, const MYSQLND_CSTRING * const database, const unsigned int mysql_flags);
 typedef struct st_mysqlnd_authentication_plugin * (*func_mysqlnd_conn_data__fetch_auth_plugin_by_name)(const char * const requested_protocol);
 
 typedef enum_func_status       (*func_mysqlnd_conn_data__set_client_option_2d)(MYSQLND_CONN_DATA * const conn, enum_mysqlnd_client_option option, const char * const key, const char * const value);
@@ -640,7 +640,7 @@ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data)
 };
 
 
-typedef enum_func_status       (*func_mysqlnd_data__connect)(MYSQLND * conn, const char * host, const char * user, const char * passwd, unsigned int passwd_len, const char * db, unsigned int db_len, unsigned int port, const char * socket_or_pipe, unsigned int mysql_flags);
+typedef enum_func_status       (*func_mysqlnd_data__connect)(MYSQLND * conn, const MYSQLND_CSTRING hostname, const MYSQLND_CSTRING username, const MYSQLND_CSTRING password, const MYSQLND_CSTRING database, unsigned int port, const MYSQLND_CSTRING socket_or_pipe, unsigned int mysql_flags);
 typedef MYSQLND *                      (*func_mysqlnd_conn__clone_object)(MYSQLND * const conn);
 typedef void                           (*func_mysqlnd_conn__dtor)(MYSQLND * conn);
 typedef enum_func_status       (*func_mysqlnd_conn__close)(MYSQLND * conn, enum_connection_close_type close_type);
@@ -982,8 +982,7 @@ struct st_mysqlnd_connection_data
        uint64_t                thread_id;
        char                    *server_version;
        char                    *host_info;
-       zend_uchar              *auth_plugin_data;
-       size_t                  auth_plugin_data_len;
+       MYSQLND_STRING  authentication_plugin_data;
        const MYSQLND_CHARSET *charset;
        const MYSQLND_CHARSET *greet_charset;
        MYSQLND_STRING  connect_or_select_db;
index 5f7838d9834fadea05b2054b86fe4959d801b6f3..c6b53e43238309e9955352783517e772eb61c1df 100644 (file)
@@ -347,8 +347,8 @@ php_mysqlnd_greet_read(void * _packet)
        }
        BAIL_IF_NO_MORE_DATA;
 
-       packet->auth_plugin_data = packet->intern_auth_plugin_data;
-       packet->auth_plugin_data_len = sizeof(packet->intern_auth_plugin_data);
+       packet->authentication_plugin_data.s = packet->intern_auth_plugin_data;
+       packet->authentication_plugin_data.l = sizeof(packet->intern_auth_plugin_data);
 
        if (packet->header.size < sizeof(buf)) {
                /*
@@ -386,7 +386,7 @@ php_mysqlnd_greet_read(void * _packet)
        p+=4;
        BAIL_IF_NO_MORE_DATA;
 
-       memcpy(packet->auth_plugin_data, p, SCRAMBLE_LENGTH_323);
+       memcpy(packet->authentication_plugin_data.s, p, SCRAMBLE_LENGTH_323);
        p+= SCRAMBLE_LENGTH_323;
        BAIL_IF_NO_MORE_DATA;
 
@@ -413,7 +413,7 @@ php_mysqlnd_greet_read(void * _packet)
 
        if ((size_t) (p - buf) < packet->header.size) {
                /* auth_plugin_data is split into two parts */
-               memcpy(packet->auth_plugin_data + SCRAMBLE_LENGTH_323, p, SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
+               memcpy(packet->authentication_plugin_data.s + SCRAMBLE_LENGTH_323, p, SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
                p+= SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323;
                p++; /* 0x0 at the end of the scramble and thus last byte in the packet in 5.1 and previous */
        } else {
@@ -428,19 +428,19 @@ php_mysqlnd_greet_read(void * _packet)
        /* Additional 16 bits for server capabilities */
                packet->server_capabilities |= uint2korr(pad_start) << 16;
                /* And a length of the server scramble in one byte */
-               packet->auth_plugin_data_len = uint1korr(pad_start + 2);
-               if (packet->auth_plugin_data_len > SCRAMBLE_LENGTH) {
+               packet->authentication_plugin_data.l = uint1korr(pad_start + 2);
+               if (packet->authentication_plugin_data.l > SCRAMBLE_LENGTH) {
                        /* more data*/
-                       zend_uchar * new_auth_plugin_data = emalloc(packet->auth_plugin_data_len);
+                       char * new_auth_plugin_data = emalloc(packet->authentication_plugin_data.l);
                        if (!new_auth_plugin_data) {
                                goto premature_end;
                        }
                        /* copy what we already have */
-                       memcpy(new_auth_plugin_data, packet->auth_plugin_data, SCRAMBLE_LENGTH);
+                       memcpy(new_auth_plugin_data, packet->authentication_plugin_data.s, SCRAMBLE_LENGTH);
                        /* add additional scramble data 5.5+ sent us */
-                       memcpy(new_auth_plugin_data + SCRAMBLE_LENGTH, p, packet->auth_plugin_data_len - SCRAMBLE_LENGTH);
-                       p+= (packet->auth_plugin_data_len - SCRAMBLE_LENGTH);
-                       packet->auth_plugin_data = new_auth_plugin_data;
+                       memcpy(new_auth_plugin_data + SCRAMBLE_LENGTH, p, packet->authentication_plugin_data.l - SCRAMBLE_LENGTH);
+                       p+= (packet->authentication_plugin_data.l - SCRAMBLE_LENGTH);
+                       packet->authentication_plugin_data.s = new_auth_plugin_data;
                }
        }
 
@@ -456,7 +456,7 @@ php_mysqlnd_greet_read(void * _packet)
 
        DBG_INF_FMT("server_capabilities=%u charset_no=%u server_status=%i auth_protocol=%s scramble_length=%u",
                                packet->server_capabilities, packet->charset_no, packet->server_status,
-                               packet->auth_protocol? packet->auth_protocol:"n/a", packet->auth_plugin_data_len);
+                               packet->auth_protocol? packet->auth_protocol:"n/a", packet->authentication_plugin_data.l);
 
        DBG_RETURN(PASS);
 premature_end:
@@ -477,9 +477,9 @@ void php_mysqlnd_greet_free_mem(void * _packet, zend_bool stack_allocation)
                efree(p->server_version);
                p->server_version = NULL;
        }
-       if (p->auth_plugin_data && p->auth_plugin_data != p->intern_auth_plugin_data) {
-               efree(p->auth_plugin_data);
-               p->auth_plugin_data = NULL;
+       if (p->authentication_plugin_data.s && p->authentication_plugin_data.s != p->intern_auth_plugin_data) {
+               efree(p->authentication_plugin_data.s);
+               p->authentication_plugin_data.s = NULL;
        }
        if (p->auth_protocol) {
                efree(p->auth_protocol);
@@ -2782,7 +2782,7 @@ send_command(
 
        cmd_packet->command = command;
        if (arg && arg_len) {
-               cmd_packet->argument.s = arg;
+               cmd_packet->argument.s = (char *) arg;
                cmd_packet->argument.l = arg_len;
        }
 
@@ -4171,6 +4171,125 @@ mysqlnd_com_enable_ssl_create_command(va_list args)
 }
 /* }}} */
 
+/************************** COM_READ_HANDSHAKE ******************************************/
+struct st_mysqlnd_protocol_com_handshake_command
+{
+       struct st_mysqlnd_protocol_command parent;
+       struct st_mysqlnd_com_handshake_context
+       {
+               MYSQLND_CONN_DATA * conn;
+               MYSQLND_CSTRING user;
+               MYSQLND_CSTRING passwd;
+               MYSQLND_CSTRING database;
+               size_t client_flags;
+       } context;
+};
+
+
+/* {{{ mysqlnd_com_handshake_run */
+static enum_func_status
+mysqlnd_com_handshake_run(void *cmd)
+{
+       struct st_mysqlnd_protocol_com_handshake_command * command = (struct st_mysqlnd_protocol_com_handshake_command *) cmd;
+       const char * user = command->context.user.s;
+
+       const char * passwd = command->context.passwd.s;
+       size_t passwd_len = command->context.passwd.l;
+
+       const char * db = command->context.database.s;
+       size_t db_len = command->context.database.l;
+
+       size_t mysql_flags =  command->context.client_flags;
+
+       MYSQLND_CONN_DATA * conn = command->context.conn;
+       MYSQLND_PACKET_GREET * greet_packet;
+
+       DBG_ENTER("mysqlnd_conn_data::connect_handshake");
+       DBG_INF_FMT("stream=%p", conn->net->data->m.get_stream(conn->net));
+       DBG_INF_FMT("[user=%s] [db=%s:%d] [flags=%llu]", user, db, db_len, mysql_flags);
+
+       greet_packet = conn->payload_decoder_factory->m.get_greet_packet(conn->payload_decoder_factory, FALSE);
+       if (!greet_packet) {
+               SET_OOM_ERROR(conn->error_info);
+               DBG_RETURN(FAIL); /* OOM */
+       }
+
+       if (FAIL == PACKET_READ(greet_packet)) {
+               DBG_ERR("Error while reading greeting packet");
+               php_error_docref(NULL, E_WARNING, "Error while reading greeting packet. PID=%d", getpid());
+               goto err;
+       } else if (greet_packet->error_no) {
+               DBG_ERR_FMT("errorno=%u error=%s", greet_packet->error_no, greet_packet->error);
+               SET_CLIENT_ERROR(conn->error_info, greet_packet->error_no, greet_packet->sqlstate, greet_packet->error);
+               goto err;
+       } else if (greet_packet->pre41) {
+               DBG_ERR_FMT("Connecting to 3.22, 3.23 & 4.0 is not supported. Server is %-.32s", greet_packet->server_version);
+               php_error_docref(NULL, E_WARNING, "Connecting to 3.22, 3.23 & 4.0 "
+                                               " is not supported. Server is %-.32s", greet_packet->server_version);
+               SET_CLIENT_ERROR(conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE,
+                                                "Connecting to 3.22, 3.23 & 4.0 servers is not supported");
+               goto err;
+       }
+
+       conn->thread_id                 = greet_packet->thread_id;
+       conn->protocol_version  = greet_packet->protocol_version;
+       conn->server_version    = mnd_pestrdup(greet_packet->server_version, conn->persistent);
+
+       conn->greet_charset = mysqlnd_find_charset_nr(greet_packet->charset_no);
+       if (!conn->greet_charset) {
+               php_error_docref(NULL, E_WARNING,
+                       "Server sent charset (%d) unknown to the client. Please, report to the developers", greet_packet->charset_no);
+               SET_CLIENT_ERROR(conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE,
+                       "Server sent charset unknown to the client. Please, report to the developers");
+               goto err;
+       }
+
+       conn->server_capabilities       = greet_packet->server_capabilities;
+
+       if (FAIL == mysqlnd_connect_run_authentication(conn, user, passwd, db, db_len, (size_t) passwd_len,
+                                                                                                  greet_packet->authentication_plugin_data, greet_packet->auth_protocol,
+                                                                                                  greet_packet->charset_no, greet_packet->server_capabilities,
+                                                                                                  conn->options, mysql_flags))
+       {
+               goto err;
+       }
+
+       UPSERT_STATUS_RESET(conn->upsert_status);
+       UPSERT_STATUS_SET_SERVER_STATUS(conn->upsert_status, greet_packet->server_status);
+
+       PACKET_FREE(greet_packet);
+       DBG_RETURN(PASS);
+err:
+       conn->server_capabilities = 0;
+       PACKET_FREE(greet_packet);
+       DBG_RETURN(FAIL);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_com_handshake_create_command */
+static struct st_mysqlnd_protocol_command *
+mysqlnd_com_handshake_create_command(va_list args)
+{
+       struct st_mysqlnd_protocol_com_handshake_command * command;
+       DBG_ENTER("mysqlnd_com_handshake_create_command");
+       command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_handshake_command));
+       if (command) {
+               command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
+               command->context.user = *va_arg(args, const MYSQLND_CSTRING *);
+               command->context.passwd = *va_arg(args, const MYSQLND_CSTRING *);
+               command->context.database = *va_arg(args, const MYSQLND_CSTRING *);
+               command->context.client_flags = va_arg(args, size_t);
+
+               command->parent.free_command = mysqlnd_com_no_params_free_command;
+               command->parent.run = mysqlnd_com_handshake_run;
+       }
+
+       DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
+}
+/* }}} */
+
+
 
 /* {{{ mysqlnd_get_command */
 static struct st_mysqlnd_protocol_command *
@@ -4239,6 +4358,9 @@ mysqlnd_get_command(enum php_mysqlnd_server_command command, ...)
                case COM_ENABLE_SSL:
                        ret = mysqlnd_com_enable_ssl_create_command(args);
                        break;
+               case COM_HANDSHAKE:
+                       ret = mysqlnd_com_handshake_create_command(args);
+                       break;
                default:
                        break;
        }
index cace621d3fe4f608b0a095fe907c6eee2e2f83e1..58ef62c645bc86b1a99763f7c2c3192bc4c1fe50 100644 (file)
@@ -78,9 +78,8 @@ typedef struct st_mysqlnd_packet_greet {
        uint8_t         protocol_version;
        char            *server_version;
        uint32_t        thread_id;
-       zend_uchar      intern_auth_plugin_data[SCRAMBLE_LENGTH];
-       zend_uchar      * auth_plugin_data;
-       size_t          auth_plugin_data_len;
+       char            intern_auth_plugin_data[SCRAMBLE_LENGTH];
+       MYSQLND_STRING authentication_plugin_data;
        /* 1 byte pad */
        uint32_t        server_capabilities;
        uint8_t         charset_no;