Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass-through authentication - DONOTMERGE #4221

Draft
wants to merge 2 commits into
base: v2.x
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions include/MySQL_Protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@ class MySQL_Protocol {
void PPHR_5passwordFalse_auth2(unsigned char *pkt, unsigned int len, bool& ret, MyProt_tmp_auth_vars& vars1, char * reply, MyProt_tmp_auth_attrs& attr1 , void *& sha1_pass);
void PPHR_6auth2(bool& ret, MyProt_tmp_auth_vars& vars1);
void PPHR_sha2full(bool& ret, MyProt_tmp_auth_vars& vars1, enum proxysql_auth_plugins passformat);
void PPHR_sha2full_unknown_user(bool& ret, MyProt_tmp_auth_vars& vars1, enum proxysql_auth_plugins passformat);
void PPHR_7auth1(unsigned char *pkt, unsigned int len, bool& ret, MyProt_tmp_auth_vars& vars1, char * reply, MyProt_tmp_auth_attrs& attr1 , void *& sha1_pass);
void PPHR_7auth2(unsigned char *pkt, unsigned int len, bool& ret, MyProt_tmp_auth_vars& vars1, char * reply, MyProt_tmp_auth_attrs& attr1 , void *& sha1_pass);
void PPHR_SetConnAttrs(MyProt_tmp_auth_vars& vars1, MyProt_tmp_auth_attrs& attr1);
Expand Down
1 change: 1 addition & 0 deletions include/MySQL_Session.h
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,7 @@ class MySQL_Session
// this variable is relevant only if status == SETTING_VARIABLE
enum mysql_variable_name changing_variable_idx;


MySQL_Session();
~MySQL_Session();

Expand Down
1 change: 1 addition & 0 deletions include/proxysql_structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -226,6 +226,7 @@ enum mysql_variable_name {

enum session_status {
CONNECTING_CLIENT,
CONNECTING_CLIENT_RESUME,
CONNECTING_SERVER,
LDAP_AUTH_CLIENT,
PINGING_SERVER,
Expand Down
115 changes: 77 additions & 38 deletions lib/MySQL_Protocol.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -446,6 +446,15 @@ bool MySQL_Protocol::generate_pkt_ERR(bool send, void **ptr, unsigned int *len,
break;
}
default:
if (sess->status == CONNECTING_SERVER) {
if (sess->previous_status.empty() == false) {
if (sess->previous_status.top() == CONNECTING_CLIENT_RESUME) {
// this is an exception. We are trying to shortcut the
// client authentication against the server
break;
}
}
}
// LCOV_EXCL_START
assert(0);
// LCOV_EXCL_STOP
Expand Down Expand Up @@ -2226,6 +2235,56 @@ void MySQL_Protocol::PPHR_sha2full(
}
}

void MySQL_Protocol::PPHR_sha2full_unknown_user(
bool& ret,
MyProt_tmp_auth_vars& vars1,
enum proxysql_auth_plugins passformat
) {
if ((*myds)->switching_auth_stage == 0) {
const unsigned char perform_full_authentication = '\4';
generate_one_byte_pkt(perform_full_authentication);
(*myds)->switching_auth_type = auth_plugin_id;
(*myds)->switching_auth_stage = 4;
(*myds)->auth_in_progress = 1;
} else if ((*myds)->switching_auth_stage == 5) {
if (passformat == AUTH_MYSQL_CACHING_SHA2_PASSWORD) {
//assert(strlen(vars1.password) == 70);
(*myds)->switching_auth_stage = 6;
(*myds)->auth_in_progress = 1;
assert(vars1.password == NULL);
userinfo->password=strdup((const char *)vars1.pass);
if (vars1.db != NULL) {
userinfo->schemaname=strdup((const char *)vars1.db);
} else {
userinfo->schemaname=strdup((const char *)mysql_thread___default_schema);
}
sess->default_hostgroup = 0;
sess->current_hostgroup = sess->default_hostgroup;
sess->mybe = sess->find_or_create_backend(sess->current_hostgroup);
// TODO: add timeout
sess->mybe->server_myds->connect_retries_on_failure = 0;
sess->previous_status.push(CONNECTING_CLIENT_RESUME);
sess->set_status(CONNECTING_SERVER);
} else {
assert(0);
}
} else if ((*myds)->switching_auth_stage == 6) {
if (passformat == AUTH_MYSQL_CACHING_SHA2_PASSWORD) {
if (sess->mybe) {
if (sess->mybe->server_myds) {
if (sess->mybe->server_myds->myconn) {
GloMyAuth->set_clear_text_password((char *)vars1.user, USERNAME_FRONTEND, sess->mybe->server_myds->myconn->userinfo->password);
ret = true;
}
}
}
}
(*myds)->auth_in_progress = 0;
} else {
assert(0);
}
}

void MySQL_Protocol::PPHR_SetConnAttrs(MyProt_tmp_auth_vars& vars1, MyProt_tmp_auth_attrs& attr1) {
MySQL_Connection *myconn = NULL;
myconn=sess->client_myds->myconn;
Expand Down Expand Up @@ -2338,41 +2397,6 @@ bool MySQL_Protocol::process_pkt_handshake_response(unsigned char *pkt, unsigned
assert(0);
break;
}
/*
if (auth_plugin_id == AUTH_UNKNOWN_PLUGIN) { // unknown plugin
*/
/*
ret = false;
proxy_debug(PROXY_DEBUG_MYSQL_AUTH, 5, "Session=%p , DS=%p , user='%s' . goto __exit_process_pkt_handshake_response . Unknown auth plugin\n", (*myds), (*myds)->sess, vars1.user);
goto __exit_process_pkt_handshake_response;
} else if (auth_plugin_id == AUTH_UNKNOWN_PLUGIN) {
*/
/*
} else if (auth_plugin_id == AUTH_MYSQL_NATIVE_PASSWORD) {
} else if (auth_plugin_id == AUTH_MYSQL_CLEAR_PASSWORD) {
} else if (auth_plugin_id == AUTH_MYSQL_CACHING_SHA2_PASSWORD) { // caching_sha2_password
*/
/*
unsigned char a[SHA256_DIGEST_LENGTH];
unsigned char b[SHA256_DIGEST_LENGTH];
unsigned char c[SHA256_DIGEST_LENGTH+20];
unsigned char d[SHA256_DIGEST_LENGTH];
unsigned char e[SHA256_DIGEST_LENGTH];
SHA256((const unsigned char *)"admin", strlen("admin"), a);
SHA256(a, SHA256_DIGEST_LENGTH, b);
memcpy(c,b,SHA256_DIGEST_LENGTH);
memcpy(c+SHA256_DIGEST_LENGTH, (*myds)->myconn->scramble_buff, 20);
SHA256(c, SHA256_DIGEST_LENGTH+20, d);
for (int i=0; i<SHA256_DIGEST_LENGTH; i++) {
e[i] = a[i] ^ d[i];
}
assert(1);
*/
/*
} else {
assert(0);
}
*/
} else if (sent_auth_plugin_id == AUTH_MYSQL_CACHING_SHA2_PASSWORD) {
switch (auth_plugin_id) {
case AUTH_UNKNOWN_PLUGIN:
Expand Down Expand Up @@ -2442,6 +2466,12 @@ bool MySQL_Protocol::process_pkt_handshake_response(unsigned char *pkt, unsigned
// try LDAP
if (auth_plugin_id == AUTH_MYSQL_CLEAR_PASSWORD) {
PPHR_5passwordFalse_auth2(pkt, len, ret, vars1, reply, attr1, sha1_pass);
} else if (
auth_plugin_id == AUTH_MYSQL_CACHING_SHA2_PASSWORD
&&
((*myds)->sess->session_type == PROXYSQL_SESSION_MYSQL)
) { // caching_sha2_password
PPHR_sha2full_unknown_user(ret, vars1, AUTH_MYSQL_CACHING_SHA2_PASSWORD);
}
}
} else {
Expand All @@ -2461,7 +2491,13 @@ bool MySQL_Protocol::process_pkt_handshake_response(unsigned char *pkt, unsigned
if (
auth_plugin_id == AUTH_MYSQL_CACHING_SHA2_PASSWORD
&&
strlen(vars1.password) > 60
vars1.password == NULL
) {
assert(0);
} else if (
auth_plugin_id == AUTH_MYSQL_CACHING_SHA2_PASSWORD
&&
strlen(vars1.password) == 70
&&
strncasecmp(vars1.password,"$A$0",4)==0
) {
Expand Down Expand Up @@ -2541,13 +2577,16 @@ bool MySQL_Protocol::process_pkt_handshake_response(unsigned char *pkt, unsigned

if (!userinfo->username) // if set already, ignore
userinfo->username=strdup((const char *)vars1.user);
userinfo->password=strdup((const char *)vars1.password);
if (userinfo->password == NULL)
userinfo->password=strdup((const char *)vars1.password);
if (vars1.db) userinfo->set_schemaname(vars1.db,strlen(vars1.db));
} else {
// we always duplicate username and password, or crashes happen
if (!userinfo->username) // if set already, ignore
userinfo->username=strdup((const char *)vars1.user);
if (vars1.pass_len) userinfo->password=strdup((const char *)"");
if (vars1.pass_len)
if (userinfo->password == NULL)
userinfo->password=strdup((const char *)"");
}
userinfo->set(NULL,NULL,NULL,NULL); // just to call compute_hash()

Expand Down
50 changes: 44 additions & 6 deletions lib/MySQL_Session.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -611,6 +611,7 @@ MySQL_Session::MySQL_Session() {
last_HG_affected_rows = -1; // #1421 : advanced support for LAST_INSERT_ID()
proxysql_node_address = NULL;
use_ldap_auth = false;

}

void MySQL_Session::init() {
Expand Down Expand Up @@ -664,6 +665,7 @@ void MySQL_Session::reset() {
client_myds->myconn->reset();
}
}

}

MySQL_Session::~MySQL_Session() {
Expand Down Expand Up @@ -2983,9 +2985,18 @@ bool MySQL_Session::handler_again___status_CONNECTING_SERVER(int *_rc) {
// see bug #979
RequestEnd(myds);
}
while (previous_status.size()) {
st=previous_status.top();
previous_status.pop();
if (previous_status.empty() == false) {
if (previous_status.top() == CONNECTING_CLIENT_RESUME) {
myds->destroy_MySQL_Connection_From_Pool( myerr ? true : false );
st=previous_status.top();
previous_status.pop();
NEXT_IMMEDIATE_NEW(st);
} else {
while (previous_status.size()) {
st=previous_status.top();
previous_status.pop();
}
}
}
if (mirror) {
PROXY_TRACE();
Expand Down Expand Up @@ -4749,6 +4760,27 @@ int MySQL_Session::handler() {
//fprintf(stderr,"CONNECTING_CLIENT\n");
// FIXME: to implement
break;
case CONNECTING_CLIENT_RESUME:
if (mybe != NULL) {
if (mybe->server_myds != NULL) {
if (mybe->server_myds->myconn != NULL) {
proxy_warning("Resuming client connection\n");
set_status(CONNECTING_CLIENT);
uint8_t _pid = client_myds->pkt_sid; _pid++;
GloMyLogger->log_audit_entry(PROXYSQL_MYSQL_AUTH_OK, this, NULL);
client_myds->DSS = STATE_CLIENT_HANDSHAKE;
client_myds->myprot.generate_pkt_OK(true, NULL, NULL, _pid, 0, 0, 2, 0, NULL);
status=WAITING_CLIENT_DATA;
client_myds->DSS=STATE_CLIENT_AUTH_OK;
mybe->server_myds->return_MySQL_Connection_To_Pool();
break;
}
}
}
// something was wrong , we destroy the session
handler_ret = -1;
return handler_ret;
break;
case PINGING_SERVER:
{
int rc=handler_again___status_PINGING_SERVER();
Expand Down Expand Up @@ -6971,7 +7003,13 @@ void MySQL_Session::handler___client_DSS_QUERY_SENT___server_DSS_NOT_INITIALIZED
}
}
}
if (session_fast_forward == false && qpo->create_new_conn == false) {
bool resume_client_authentication = false;
if (previous_status.empty() == false) {
if (previous_status.top() == CONNECTING_CLIENT_RESUME) {
resume_client_authentication = true;
}
}
if (session_fast_forward == false && qpo->create_new_conn == false && resume_client_authentication == false) {
if (qpo->min_gtid) {
gtid_uuid = qpo->min_gtid;
with_gtid = true;
Expand Down Expand Up @@ -7031,9 +7069,9 @@ void MySQL_Session::handler___client_DSS_QUERY_SENT___server_DSS_NOT_INITIALIZED

if (mc==NULL) {
if (trxid) {
mc=MyHGM->get_MyConn_from_pool(mybe->hostgroup_id, this, (session_fast_forward || qpo->create_new_conn), uuid, trxid, -1);
mc=MyHGM->get_MyConn_from_pool(mybe->hostgroup_id, this, (session_fast_forward || qpo->create_new_conn || resume_client_authentication), uuid, trxid, -1);
} else {
mc=MyHGM->get_MyConn_from_pool(mybe->hostgroup_id, this, (session_fast_forward || qpo->create_new_conn), NULL, 0, (int)qpo->max_lag_ms);
mc=MyHGM->get_MyConn_from_pool(mybe->hostgroup_id, this, (session_fast_forward || qpo->create_new_conn || resume_client_authentication), NULL, 0, (int)qpo->max_lag_ms);
}
#ifdef STRESSTEST_POOL
if (mc && (loops < NUM_SLOW_LOOPS - 1)) {
Expand Down