Skip to content

Commit

Permalink
Fix MySQL 8 auth
Browse files Browse the repository at this point in the history
  • Loading branch information
johannes committed Jun 5, 2018
1 parent 6c3b70e commit d6e81f0
Show file tree
Hide file tree
Showing 7 changed files with 414 additions and 29 deletions.
292 changes: 285 additions & 7 deletions ext/mysqlnd/mysqlnd_auth.c
Expand Up @@ -89,6 +89,7 @@ mysqlnd_run_authentication(
}
}


{
zend_uchar * switch_to_auth_protocol_data = NULL;
size_t switch_to_auth_protocol_data_len = 0;
Expand All @@ -113,10 +114,11 @@ mysqlnd_run_authentication(
DBG_INF_FMT("salt(%d)=[%.*s]", plugin_data_len, plugin_data_len, plugin_data);
/* The data should be allocated with malloc() */
if (auth_plugin) {
scrambled_data =
auth_plugin->methods.get_auth_data(NULL, &scrambled_data_len, conn, user, passwd, passwd_len,
plugin_data, plugin_data_len, session_options,
conn->protocol_frame_codec->data, mysql_flags);
scrambled_data = auth_plugin->methods.get_auth_data(
NULL, &scrambled_data_len, conn, user, passwd,
passwd_len, plugin_data, plugin_data_len,
session_options, conn->protocol_frame_codec->data,
mysql_flags);
}

if (conn->error_info->error_no) {
Expand All @@ -127,6 +129,7 @@ mysqlnd_run_authentication(
charset_no,
first_call,
requested_protocol,
auth_plugin, plugin_data, plugin_data_len,
scrambled_data, scrambled_data_len,
&switch_to_auth_protocol, &switch_to_auth_protocol_len,
&switch_to_auth_protocol_data, &switch_to_auth_protocol_data_len
Expand Down Expand Up @@ -248,6 +251,9 @@ mysqlnd_auth_handshake(MYSQLND_CONN_DATA * conn,
unsigned int server_charset_no,
zend_bool use_full_blown_auth_packet,
const char * const auth_protocol,
struct st_mysqlnd_authentication_plugin * auth_plugin,
const zend_uchar * const orig_auth_plugin_data,
const size_t orig_auth_plugin_data_len,
const zend_uchar * const auth_plugin_data,
const size_t auth_plugin_data_len,
char ** switch_to_auth_protocol,
Expand Down Expand Up @@ -318,6 +324,11 @@ mysqlnd_auth_handshake(MYSQLND_CONN_DATA * conn,
conn->charset = mysqlnd_find_charset_nr(auth_packet->charset_no);
}

if (auth_plugin && auth_plugin->methods.handle_server_response) {
auth_plugin->methods.handle_server_response(auth_plugin, conn,
orig_auth_plugin_data, orig_auth_plugin_data_len, passwd, passwd_len);
}

if (FAIL == PACKET_READ(auth_resp_packet) || auth_resp_packet->response_code >= 0xFE) {
if (auth_resp_packet->response_code == 0xFE) {
/* old authentication with new server !*/
Expand Down Expand Up @@ -613,7 +624,8 @@ static struct st_mysqlnd_authentication_plugin mysqlnd_native_auth_plugin =
}
},
{/* methods */
mysqlnd_native_auth_get_auth_data
mysqlnd_native_auth_get_auth_data,
NULL
}
};

Expand Down Expand Up @@ -662,7 +674,8 @@ static struct st_mysqlnd_authentication_plugin mysqlnd_pam_authentication_plugin
}
},
{/* methods */
mysqlnd_pam_auth_get_auth_data
mysqlnd_pam_auth_get_auth_data,
NULL
}
};

Expand Down Expand Up @@ -846,17 +859,282 @@ static struct st_mysqlnd_authentication_plugin mysqlnd_sha256_authentication_plu
}
},
{/* methods */
mysqlnd_sha256_auth_get_auth_data
mysqlnd_sha256_auth_get_auth_data,
NULL
}
};
#endif

/*************************************** CACHING SHA2 Password *******************************/

#undef L64

#include "ext/hash/php_hash.h"
#include "ext/hash/php_hash_sha.h"

#define SHA256_LENGTH 32

/* {{{ php_mysqlnd_scramble_sha2 */
void php_mysqlnd_scramble_sha2(zend_uchar * const buffer, const zend_uchar * const scramble, const zend_uchar * const password, const size_t password_len)
{
PHP_SHA256_CTX context;
zend_uchar sha1[SHA256_LENGTH];
zend_uchar sha2[SHA256_LENGTH];

/* Phase 1: hash password */
PHP_SHA256Init(&context);
PHP_SHA256Update(&context, password, password_len);
PHP_SHA256Final(sha1, &context);

/* Phase 2: hash sha1 */
PHP_SHA256Init(&context);
PHP_SHA256Update(&context, (zend_uchar*)sha1, SHA256_LENGTH);
PHP_SHA256Final(sha2, &context);

/* Phase 3: hash scramble + sha2 */
PHP_SHA256Init(&context);
PHP_SHA256Update(&context, (zend_uchar*)sha2, SHA256_LENGTH);
PHP_SHA256Update(&context, scramble, SCRAMBLE_LENGTH);
PHP_SHA256Final(buffer, &context);

/* let's crypt buffer now */
php_mysqlnd_crypt(buffer, (const zend_uchar *)sha1, (const zend_uchar *)buffer, SHA256_LENGTH);
}
/* }}} */


/* {{{ mysqlnd_native_auth_get_auth_data */
static zend_uchar *
mysqlnd_caching_sha2_get_auth_data(struct st_mysqlnd_authentication_plugin * self,
size_t * auth_data_len,
MYSQLND_CONN_DATA * conn, const char * const user, const char * const passwd,
const size_t passwd_len, zend_uchar * auth_plugin_data, size_t auth_plugin_data_len,
const MYSQLND_SESSION_OPTIONS * const session_options,
const MYSQLND_PFC_DATA * const pfc_data,
zend_ulong mysql_flags
)
{
zend_uchar * ret = NULL;
DBG_ENTER("mysqlnd_caching_sha2_get_auth_data");
DBG_INF_FMT("salt(%d)=[%.*s]", auth_plugin_data_len, auth_plugin_data_len, auth_plugin_data);
*auth_data_len = 0;

DBG_INF("First auth step: send hashed password");
/* copy scrambled pass*/
if (passwd && passwd_len) {
ret = malloc(SHA256_LENGTH + 1);
*auth_data_len = SHA256_LENGTH;
php_mysqlnd_scramble_sha2((zend_uchar*)ret, auth_plugin_data, (zend_uchar*)passwd, passwd_len);
ret[SHA256_LENGTH] = '\0';
DBG_INF_FMT("hash(%d)=[%.*s]", *auth_data_len, *auth_data_len, ret);
}

DBG_RETURN(ret);
}
/* }}} */

#ifdef MYSQLND_HAVE_SSL
static RSA *
mysqlnd_caching_sha2_get_key(MYSQLND_CONN_DATA *conn)
{
RSA * ret = NULL;
const MYSQLND_PFC_DATA * const pfc_data = conn->protocol_frame_codec->data;
const char * fname = (pfc_data->sha256_server_public_key && pfc_data->sha256_server_public_key[0] != '\0')?
pfc_data->sha256_server_public_key:
MYSQLND_G(sha256_server_public_key);
php_stream * stream;
DBG_ENTER("mysqlnd_cached_sha2_get_key");
DBG_INF_FMT("options_s256_pk=[%s] MYSQLND_G(sha256_server_public_key)=[%s]",
pfc_data->sha256_server_public_key? pfc_data->sha256_server_public_key:"n/a",
MYSQLND_G(sha256_server_public_key)? MYSQLND_G(sha256_server_public_key):"n/a");
if (!fname || fname[0] == '\0') {
MYSQLND_PACKET_CACHED_SHA2_RESULT *req_packet = NULL;
MYSQLND_PACKET_SHA256_PK_REQUEST_RESPONSE *pk_resp_packet = NULL;

do {
DBG_INF("requesting the public key from the server");
req_packet = conn->payload_decoder_factory->m.get_cached_sha2_result_packet(conn->payload_decoder_factory, FALSE);
pk_resp_packet = conn->payload_decoder_factory->m.get_sha256_pk_request_response_packet(conn->payload_decoder_factory, FALSE);
req_packet->request = 1;

if (! PACKET_WRITE(req_packet)) {
DBG_ERR_FMT("Error while sending public key request packet");
php_error(E_WARNING, "Error while sending public key request packet. PID=%d", getpid());
SET_CONNECTION_STATE(&conn->state, CONN_QUIT_SENT);
break;
}
if (FAIL == PACKET_READ(pk_resp_packet) || NULL == pk_resp_packet->public_key) {
DBG_ERR_FMT("Error while receiving public key");
php_error(E_WARNING, "Error while receiving public key. PID=%d", getpid());
SET_CONNECTION_STATE(&conn->state, CONN_QUIT_SENT);
break;
}
DBG_INF_FMT("Public key(%d):\n%s", pk_resp_packet->public_key_len, pk_resp_packet->public_key);
/* now extract the public key */
{
BIO * bio = BIO_new_mem_buf(pk_resp_packet->public_key, pk_resp_packet->public_key_len);
ret = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL);
BIO_free(bio);
}
} while (0);
PACKET_FREE(req_packet);
PACKET_FREE(pk_resp_packet);

DBG_INF_FMT("ret=%p", ret);
DBG_RETURN(ret);

SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE,
"caching_sha2_server_public_key is not set for the connection or as mysqlnd.sha256_server_public_key");
DBG_ERR("server_public_key is not set");
DBG_RETURN(NULL);
} else {
zend_string * key_str;
DBG_INF_FMT("Key in a file. [%s]", fname);
stream = php_stream_open_wrapper((char *) fname, "rb", REPORT_ERRORS, NULL);

if (stream) {
if ((key_str = php_stream_copy_to_mem(stream, PHP_STREAM_COPY_ALL, 0)) != NULL) {
BIO * bio = BIO_new_mem_buf(ZSTR_VAL(key_str), ZSTR_LEN(key_str));
ret = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL);
BIO_free(bio);
DBG_INF("Successfully loaded");
DBG_INF_FMT("Public key:%*.s", ZSTR_LEN(key_str), ZSTR_VAL(key_str));
zend_string_release(key_str);
}
php_stream_close(stream);
}
}
DBG_RETURN(ret);

}
#endif


/* {{{ mysqlnd_caching_sha2_get_key */
static size_t
mysqlnd_caching_sha2_get_and_use_key(MYSQLND_CONN_DATA *conn,
const zend_uchar * auth_plugin_data, size_t auth_plugin_data_len,
unsigned char **crypted,
const char * const passwd,
const size_t passwd_len)
{
#ifdef MYSQLND_HAVE_SSL
static RSA *server_public_key;
server_public_key = mysqlnd_caching_sha2_get_key(conn);

DBG_ENTER("mysqlnd_caching_sha2_get_and_use_key(");

if (server_public_key) {
int server_public_key_len;
char xor_str[passwd_len + 1];
memcpy(xor_str, passwd, passwd_len);
xor_str[passwd_len] = '\0';
mysqlnd_xor_string(xor_str, passwd_len, (char *) auth_plugin_data, auth_plugin_data_len);

server_public_key_len = RSA_size(server_public_key);
/*
Because RSA_PKCS1_OAEP_PADDING is used there is a restriction on the passwd_len.
RSA_PKCS1_OAEP_PADDING is recommended for new applications. See more here:
http://www.openssl.org/docs/crypto/RSA_public_encrypt.html
*/
if ((size_t) server_public_key_len - 41 <= passwd_len) {
/* password message is to long */
SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "password is too long");
DBG_ERR("password is too long");
DBG_RETURN(0);
}

*crypted = emalloc(server_public_key_len);
RSA_public_encrypt(passwd_len + 1, (zend_uchar *) xor_str, *crypted, server_public_key, RSA_PKCS1_OAEP_PADDING);
DBG_RETURN(server_public_key_len);
}
DBG_RETURN(0);
#else
php_error_docref(NULL, E_WARNING, "PHP was built without openssl extension, can't send password encrypted");
DBG_RETURN(0);
#endif
}
/* }}} */

/* {{{ mysqlnd_native_auth_get_auth_data */
static void
mysqlnd_caching_sha2_handle_server_response(struct st_mysqlnd_authentication_plugin *self,
MYSQLND_CONN_DATA * conn,
const zend_uchar * auth_plugin_data, size_t auth_plugin_data_len,
const char * const passwd,
const size_t passwd_len)
{
DBG_ENTER("mysqlnd_caching_sha2_handle_server_response");
MYSQLND_PACKET_CACHED_SHA2_RESULT *result_packet;
result_packet = conn->payload_decoder_factory->m.get_cached_sha2_result_packet(conn->payload_decoder_factory, FALSE);

if (FAIL == PACKET_READ(result_packet)) {
DBG_VOID_RETURN;
}

switch (result_packet->response_code) {
case 3:
DBG_INF("fast path suceeded");
PACKET_FREE(result_packet);
DBG_VOID_RETURN;
case 4:
if (conn->vio->data->ssl || conn->unix_socket.s) {
DBG_INF("fast path failed, doing full auth via SSL");
result_packet->password = (zend_uchar *)passwd;
result_packet->password_len = passwd_len + 1;
PACKET_WRITE(result_packet);
} else {
DBG_INF("fast path failed, doing full auth without SSL");
result_packet->password_len = mysqlnd_caching_sha2_get_and_use_key(conn, auth_plugin_data, auth_plugin_data_len, &result_packet->password, passwd, passwd_len);
PACKET_WRITE(result_packet);
efree(result_packet->password);
}
PACKET_FREE(result_packet);
DBG_VOID_RETURN;
case 2:
// The server tried to send a key, which we didn't expect
// fall-through
default:
php_error_docref(NULL, E_WARNING, "Unexpected server respose while doing caching_sha2 auth: %i", result_packet->response_code);
}

PACKET_FREE(result_packet);

DBG_VOID_RETURN;
}
/* }}} */

static struct st_mysqlnd_authentication_plugin mysqlnd_caching_sha2_auth_plugin =
{
{
MYSQLND_PLUGIN_API_VERSION,
"auth_plugin_caching_sha2_password",
MYSQLND_VERSION_ID,
PHP_MYSQLND_VERSION,
"PHP License 3.01",
"Johannes SchlΓΌter <johannes.schlueter@php.net>",
{
NULL, /* no statistics , will be filled later if there are some */
NULL, /* no statistics */
},
{
NULL /* plugin shutdown */
}
},
{/* methods */
mysqlnd_caching_sha2_get_auth_data,
mysqlnd_caching_sha2_handle_server_response
}
};


/* {{{ mysqlnd_register_builtin_authentication_plugins */
void
mysqlnd_register_builtin_authentication_plugins(void)
{
mysqlnd_plugin_register_ex((struct st_mysqlnd_plugin_header *) &mysqlnd_native_auth_plugin);
mysqlnd_plugin_register_ex((struct st_mysqlnd_plugin_header *) &mysqlnd_pam_authentication_plugin);
mysqlnd_plugin_register_ex((struct st_mysqlnd_plugin_header *) &mysqlnd_caching_sha2_auth_plugin);
#ifdef MYSQLND_HAVE_SSL
mysqlnd_plugin_register_ex((struct st_mysqlnd_plugin_header *) &mysqlnd_sha256_authentication_plugin);
#endif
Expand Down
23 changes: 3 additions & 20 deletions ext/mysqlnd/mysqlnd_auth.h
Expand Up @@ -31,26 +31,9 @@ mysqlnd_auth_handshake(MYSQLND_CONN_DATA * conn,
unsigned int server_charset_no,
zend_bool use_full_blown_auth_packet,
const char * const auth_protocol,
const zend_uchar * const auth_plugin_data,
const size_t auth_plugin_data_len,
char ** switch_to_auth_protocol,
size_t * switch_to_auth_protocol_len,
zend_uchar ** switch_to_auth_protocol_data,
size_t * switch_to_auth_protocol_data_len
);

enum_func_status
mysqlnd_auth_handshake(MYSQLND_CONN_DATA * conn,
const char * const user,
const char * const passwd,
const size_t passwd_len,
const char * const db,
const size_t db_len,
const MYSQLND_SESSION_OPTIONS * const session_options,
zend_ulong mysql_flags,
unsigned int server_charset_no,
zend_bool use_full_blown_auth_packet,
const char * const auth_protocol,
struct st_mysqlnd_authentication_plugin * auth_plugin,
const zend_uchar * const orig_auth_plugin_data,
const size_t orig_auth_plugin_data_len,
const zend_uchar * const auth_plugin_data,
const size_t auth_plugin_data_len,
char ** switch_to_auth_protocol,
Expand Down
3 changes: 3 additions & 0 deletions ext/mysqlnd/mysqlnd_connection.c
Expand Up @@ -678,7 +678,10 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn,

{
const MYSQLND_CSTRING scheme = { transport.s, transport.l };
/* This will be overwritten below with a copy, but we can use it during authentication */
conn->unix_socket.s = (char *)socket_or_pipe.s;
if (FAIL == conn->m->connect_handshake(conn, &scheme, &username, &password, &database, mysql_flags)) {
conn->unix_socket.s = NULL;
goto err;
}
}
Expand Down

25 comments on commit d6e81f0

@MauricioFauth
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@johannes
Copy link
Member Author

@johannes johannes commented on d6e81f0 Jun 13, 2018 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@motecshine
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it is only patching 7.3 version?

@Majkl578
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@motecshine This was backported down to 7.1.19. It missed 7.2 RC by a day so it should be available in 7.1.19 + 7.2.8 + 7.3.0.

@t-zuehlsdorff
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@johannes
When trying to build PHP 7.3 on FreeBSD 11.1 i end up with this error after the commit:

ext/mysqlnd/.libs/mysqlnd_auth.o: In function `php_mysqlnd_scramble_sha2':
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0xfd9): undefined reference to `PHP_SHA256Init'
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0xfe7): undefined reference to `PHP_SHA256Update'
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0xff9): undefined reference to `PHP_SHA256Final'
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0x1001): undefined reference to `PHP_SHA256Init'
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0x1011): undefined reference to `PHP_SHA256Update'
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0x1023): undefined reference to `PHP_SHA256Final'
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0x102b): undefined reference to `PHP_SHA256Init'
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0x103b): undefined reference to `PHP_SHA256Update'
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0x104b): undefined reference to `PHP_SHA256Update'
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0x1056): undefined reference to `PHP_SHA256Final'
cc: error: linker command failed with exit code 1 (use -v to see invocation)
*** [sapi/cli/php] Error code 1

make[1]: stopped in /wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2
--- sapi/phpdbg/phpdbg ---
ext/mysqlnd/.libs/mysqlnd_auth.o: In function `php_mysqlnd_scramble_sha2':
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0xfd9): undefined reference to `PHP_SHA256Init'
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0xfe7): undefined reference to `PHP_SHA256Update'
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0xff9): undefined reference to `PHP_SHA256Final'
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0x1001): undefined reference to `PHP_SHA256Init'
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0x1011): undefined reference to `PHP_SHA256Update'
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0x1023): undefined reference to `PHP_SHA256Final'
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0x102b): undefined reference to `PHP_SHA256Init'
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0x103b): undefined reference to `PHP_SHA256Update'
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0x104b): undefined reference to `PHP_SHA256Update'
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0x1056): undefined reference to `PHP_SHA256Final'
cc: error: linker command failed with exit code 1 (use -v to see invocation)
*** [sapi/phpdbg/phpdbg] Error code 1

make[1]: stopped in /wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2
--- sapi/fpm/php-fpm ---
ext/mysqlnd/.libs/mysqlnd_auth.o: In function `php_mysqlnd_scramble_sha2':
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0xfd9): undefined reference to `PHP_SHA256Init'
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0xfe7): undefined reference to `PHP_SHA256Update'
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0xff9): undefined reference to `PHP_SHA256Final'
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0x1001): undefined reference to `PHP_SHA256Init'
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0x1011): undefined reference to `PHP_SHA256Update'
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0x1023): undefined reference to `PHP_SHA256Final'
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0x102b): undefined reference to `PHP_SHA256Init'
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0x103b): undefined reference to `PHP_SHA256Update'
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0x104b): undefined reference to `PHP_SHA256Update'
/wrkdirs/usr/ports/lang/php73/work/php-7.3.0alpha2/ext/mysqlnd/mysqlnd_auth.c:(.text+0x1056): undefined reference to `PHP_SHA256Final'
cc: error: linker command failed with exit code 1 (use -v to see invocation)
*** [sapi/fpm/php-fpm] Error code 1

Did the code changes the build-requirements to for example MySQL 8.x? How can i fix it?

@KalleZ
Copy link
Member

@KalleZ KalleZ commented on d6e81f0 Jul 9, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@t-zuehlsdorff curious, does your build include the compilation of the hash extension?

@t-zuehlsdorff
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@KalleZ
No, hash is disabled per default on FreeBSD. When enabling it building works fine. This makes hash no longer optional. Unsure if this is a bug or not :D

@KalleZ
Copy link
Member

@KalleZ KalleZ commented on d6e81f0 Jul 9, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aha, because the code was directly including the hashing functions but the code does not take into account that it may disabled and therefore the headers included is essentially empty.

I think that this entire block should have guards for whether or not the hash extension is available, much like we do other places or simply make mysqlnd have a dependency on the hash extension. Personally I prefer the first option here.

I would report it as a bug at the bugs website so we can easily track this issue in case @johannes or one of the other mysql guys doesn't get around to do it. I also think its something that should be resolved before PHP 7.3 is released (cc @cmb69).

@cmb69
Copy link
Contributor

@cmb69 cmb69 commented on d6e81f0 Jul 9, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indeed, a bug report should be filed – unfortunately, bug.php.net appears to be unavailable presently.

@johannes
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my opinion we should treat the hash extension like date and always enforce it (same also for openssl imo) having such security-related features should be a key feature users can rely upon in 2018.

As a work-around one might add a guard (maybe extracting the hashing into mysqlnd as fallback ... otherwise it's hard to predict for users what will work and leaves users in the cold when a distributor, for whatever reason, decides to build hash as shared extension ...)

@cmb69
Copy link
Contributor

@cmb69 cmb69 commented on d6e81f0 Jul 10, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For reference: this issue has now been filed under https://bugs.php.net/76600 (thanks!)

In my opinion we should treat the hash extension like date and always enforce it (same also for openssl imo) having such security-related features should be a key feature users can rely upon in 2018.

IMO, that should be discussed on internals@ and might need an RFC.

@t-zuehlsdorff
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are welcome :)
Sadly i just noticed last week, that the chance was committed to 7.1 and 7.2. Now both versions are broken at FreeBSD.

Do you think that it will break more if i just patch this out? :D

@johannes
Copy link
Member Author

@johannes johannes commented on d6e81f0 Jul 23, 2018 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@t-zuehlsdorff
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It does not compile anymore. This commit enforces the - normally optional - hash extension to be compiled, but in FreeBSD it is disabled by default. Also the hash extension is an separate module to install, so i can't just switch it to on (and violate the POLA rule).

@cmb69
Copy link
Contributor

@cmb69 cmb69 commented on d6e81f0 Jul 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@johannes You can't compile mysqlnd anymore without ext/hash.

@nikic
Copy link
Member

@nikic nikic commented on d6e81f0 Jul 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd suggest reverting this change from 7.1 and 7.2 entirely. Considering that we already had to apply a number of followup fixes after this change was committed (I remember both some more build issues and segfaults), and the fact that this is more enhancement than bugfix, I'd say it does not belong on stable branches.

@nikic
Copy link
Member

@nikic nikic commented on d6e81f0 Jul 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's also https://bugs.php.net/bug.php?id=76651, which is quite likely related to this change as well.

@andrerom
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be missing from NEWS and http://www.php.net/ChangeLog-7.php#7.2.8, is that on purpose?

@nikic
Copy link
Member

@nikic nikic commented on d6e81f0 Sep 4, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've reverted these changes from 7.1+ via 03740ef. The merge to 7.3 was tricky because there were many other changes in the meantime. Hope nothing went wrong there.

We can reapply these changes once the issue from https://bugs.php.net/bug.php?id=76651 has been resolved (though I'd recommend to go for 7.3+ only).

@KalleZ
Copy link
Member

@KalleZ KalleZ commented on d6e81f0 Sep 7, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I posted an RFC to make the hash extension permanent in PHP which cannot be disabled:
https://wiki.php.net/rfc/permanent_hash_ext

If it passes, I suppose this commit could be re-applied

@breisig
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like making the hash extension permanent passed. We should get it re-applied to php 7.1+

@nikic
Copy link
Member

@nikic nikic commented on d6e81f0 Dec 27, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The hash extension is only required as of PHP 7.4, and this change has already been reapplied there with fixed openssl handling via 4f06e67.

@vv12131415
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've reverted these changes from 7.1+ via 03740ef. The merge to 7.3 was tricky because there were many other changes in the meantime. Hope nothing went wrong there.

We can reapply these changes once the issue from https://bugs.php.net/bug.php?id=76651 has been resolved (though I'd recommend to go for 7.3+ only).

though I'd recommend to go for 7.3+ only - but then you will be able to use MySQL 8 only when on php 7.3 , correct? I think it should be supported on all currently supported versions.

@cmb69
Copy link
Contributor

@cmb69 cmb69 commented on d6e81f0 May 5, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@vladyslavstartsev The mysqlnd_caching_sha2_auth_plugin is still not even supported on PHP 7.3.

@breisig
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any update on getting this supported in php 7.2+? We use mysql 8 for everything now.

Please sign in to comment.