Detect password usage based on token length

The client protocol module can resolve whether a password was used based
on the information the authenticators gather before authentication is
done. It uses the authentication token length as the basis on which it
makes the decision.
This commit is contained in:
Markus Mäkelä
2017-03-13 18:56:23 +02:00
parent 9c325104b7
commit 4d561c5f6a
5 changed files with 34 additions and 59 deletions

View File

@ -407,7 +407,7 @@ bool protocol_get_response_status (MySQLProtocol* p, int* npackets, ssize_t* nby
void protocol_set_response_status (MySQLProtocol* p, int npackets, ssize_t nbytes); void protocol_set_response_status (MySQLProtocol* p, int npackets, ssize_t nbytes);
void protocol_archive_srv_command(MySQLProtocol* p); void protocol_archive_srv_command(MySQLProtocol* p);
char* create_auth_fail_str(char *username, char *hostaddr, char *sha1, char *db, int); char* create_auth_fail_str(char *username, char *hostaddr, bool password, char *db, int);
void init_response_status ( void init_response_status (
GWBUF* buf, GWBUF* buf,

View File

@ -238,12 +238,6 @@ int validate_mysql_user(sqlite3 *handle, DCB *dcb, MYSQL_session *session,
rval = MXS_AUTH_FAILED_DB; rval = MXS_AUTH_FAILED_DB;
} }
} }
else if (session->auth_token_len)
{
/** If authentication fails, this will trigger the right
* error message with `Using password : YES` */
session->client_sha1[0] = '_';
}
} }
return rval; return rval;

View File

@ -1510,7 +1510,7 @@ static int gw_change_user(DCB *backend,
message = create_auth_fail_str(username, message = create_auth_fail_str(username,
backend->session->client_dcb->remote, backend->session->client_dcb->remote,
password_set, password_set,
"", false,
auth_ret); auth_ret);
if (message == NULL) if (message == NULL)
{ {

View File

@ -83,7 +83,6 @@ static void mysql_client_auth_error_handling(DCB *dcb, int auth_val, int packet_
static int gw_read_do_authentication(DCB *dcb, GWBUF *read_buffer, int nbytes_read); static int gw_read_do_authentication(DCB *dcb, GWBUF *read_buffer, int nbytes_read);
static int gw_read_normal_data(DCB *dcb, GWBUF *read_buffer, int nbytes_read); static int gw_read_normal_data(DCB *dcb, GWBUF *read_buffer, int nbytes_read);
static int gw_read_finish_processing(DCB *dcb, GWBUF *read_buffer, uint64_t capabilities); static int gw_read_finish_processing(DCB *dcb, GWBUF *read_buffer, uint64_t capabilities);
extern char* create_auth_fail_str(char *username, char *hostaddr, char *sha1, char *db, int);
static bool ensure_complete_packet(DCB *dcb, GWBUF **read_buffer, int nbytes_read); static bool ensure_complete_packet(DCB *dcb, GWBUF **read_buffer, int nbytes_read);
static void gw_process_one_new_client(DCB *client_dcb); static void gw_process_one_new_client(DCB *client_dcb);
@ -1072,86 +1071,67 @@ mysql_client_auth_error_handling(DCB *dcb, int auth_val, int packet_number)
{ {
int message_len; int message_len;
char *fail_str = NULL; char *fail_str = NULL;
MYSQL_session *session = (MYSQL_session*)dcb->data;
switch (auth_val) switch (auth_val)
{ {
case MXS_AUTH_NO_SESSION: case MXS_AUTH_NO_SESSION:
MXS_DEBUG("%lu [gw_read_client_event] session " MXS_DEBUG("%lu [gw_read_client_event] session creation failed. fd %d, "
"creation failed. fd %d, " "state = MYSQL_AUTH_NO_SESSION.", pthread_self(), dcb->fd);
"state = MYSQL_AUTH_NO_SESSION.",
pthread_self(),
dcb->fd);
/** Send ERR 1045 to client */ /** Send ERR 1045 to client */
mysql_send_auth_error(dcb, mysql_send_auth_error(dcb, packet_number, 0, "failed to create new session");
packet_number,
0,
"failed to create new session");
break; break;
case MXS_AUTH_FAILED_DB: case MXS_AUTH_FAILED_DB:
MXS_DEBUG("%lu [gw_read_client_event] database " MXS_DEBUG("%lu [gw_read_client_event] database specified was not valid. fd %d, "
"specified was not valid. fd %d, " "state = MYSQL_FAILED_AUTH_DB.", pthread_self(), dcb->fd);
"state = MYSQL_FAILED_AUTH_DB.",
pthread_self(),
dcb->fd);
/** Send error 1049 to client */ /** Send error 1049 to client */
message_len = 25 + MYSQL_DATABASE_MAXLEN; message_len = 25 + MYSQL_DATABASE_MAXLEN;
fail_str = MXS_CALLOC(1, message_len + 1); fail_str = MXS_CALLOC(1, message_len + 1);
MXS_ABORT_IF_NULL(fail_str); MXS_ABORT_IF_NULL(fail_str);
snprintf(fail_str, message_len, "Unknown database '%s'", snprintf(fail_str, message_len, "Unknown database '%s'", session->db);
(char*)((MYSQL_session *)dcb->data)->db);
modutil_send_mysql_err_packet(dcb, packet_number, 0, 1049, "42000", fail_str); modutil_send_mysql_err_packet(dcb, packet_number, 0, 1049, "42000", fail_str);
break; break;
case MXS_AUTH_FAILED_SSL: case MXS_AUTH_FAILED_SSL:
MXS_DEBUG("%lu [gw_read_client_event] client is " MXS_DEBUG("%lu [gw_read_client_event] client is "
"not SSL capable for SSL listener. fd %d, " "not SSL capable for SSL listener. fd %d, "
"state = MYSQL_FAILED_AUTH_SSL.", "state = MYSQL_FAILED_AUTH_SSL.", pthread_self(), dcb->fd);
pthread_self(),
dcb->fd);
/** Send ERR 1045 to client */ /** Send ERR 1045 to client */
mysql_send_auth_error(dcb, mysql_send_auth_error(dcb, packet_number, 0, "Access without SSL denied");
packet_number,
0,
"Access without SSL denied");
break; break;
case MXS_AUTH_SSL_INCOMPLETE: case MXS_AUTH_SSL_INCOMPLETE:
MXS_DEBUG("%lu [gw_read_client_event] unable to " MXS_DEBUG("%lu [gw_read_client_event] unable to "
"complete SSL authentication. fd %d, " "complete SSL authentication. fd %d, "
"state = MYSQL_AUTH_SSL_INCOMPLETE.", "state = MYSQL_AUTH_SSL_INCOMPLETE.", pthread_self(), dcb->fd);
pthread_self(),
dcb->fd);
/** Send ERR 1045 to client */ /** Send ERR 1045 to client */
mysql_send_auth_error(dcb, mysql_send_auth_error(dcb, packet_number, 0,
packet_number,
0,
"failed to complete SSL authentication"); "failed to complete SSL authentication");
break; break;
case MXS_AUTH_FAILED: case MXS_AUTH_FAILED:
MXS_DEBUG("%lu [gw_read_client_event] authentication failed. fd %d, " MXS_DEBUG("%lu [gw_read_client_event] authentication failed. fd %d, "
"state = MYSQL_FAILED_AUTH.", "state = MYSQL_FAILED_AUTH.", pthread_self(), dcb->fd);
pthread_self(),
dcb->fd);
/** Send error 1045 to client */ /** Send error 1045 to client */
fail_str = create_auth_fail_str((char *)((MYSQL_session *)dcb->data)->user, fail_str = create_auth_fail_str(session->user, dcb->remote,
dcb->remote, session->auth_token_len > 0,
(char*)((MYSQL_session *)dcb->data)->client_sha1, session->db, auth_val);
(char*)((MYSQL_session *)dcb->data)->db, auth_val);
modutil_send_mysql_err_packet(dcb, packet_number, 0, 1045, "28000", fail_str); modutil_send_mysql_err_packet(dcb, packet_number, 0, 1045, "28000", fail_str);
break; break;
default: default:
MXS_DEBUG("%lu [gw_read_client_event] authentication failed. fd %d, " MXS_DEBUG("%lu [gw_read_client_event] authentication failed. fd %d, "
"state unrecognized.", "state unrecognized.", pthread_self(), dcb->fd);
pthread_self(),
dcb->fd);
/** Send error 1045 to client */ /** Send error 1045 to client */
fail_str = create_auth_fail_str((char *)((MYSQL_session *)dcb->data)->user, fail_str = create_auth_fail_str(session->user, dcb->remote,
dcb->remote, session->auth_token_len > 0,
(char*)((MYSQL_session *)dcb->data)->client_sha1, session->db, auth_val);
(char*)((MYSQL_session *)dcb->data)->db, auth_val);
modutil_send_mysql_err_packet(dcb, packet_number, 0, 1045, "28000", fail_str); modutil_send_mysql_err_packet(dcb, packet_number, 0, 1045, "28000", fail_str);
} }
MXS_FREE(fail_str); MXS_FREE(fail_str);

View File

@ -925,16 +925,17 @@ char* create_auth_failed_msg(GWBUF*readbuf,
/** /**
* Create a message error string to send via MySQL ERR packet. * Create a message error string to send via MySQL ERR packet.
* *
* @param username the MySQL user * @param username The MySQL user
* @param hostaddr the client IP * @param hostaddr The client IP
* @param sha1 authentication scramble data * @param password If client provided a password
* @param db the MySQL db to connect to * @param db The default database the client requested
* @param errcode Authentication error code
* *
* @return Pointer to the allocated string or NULL on failure * @return Pointer to the allocated string or NULL on failure
*/ */
char *create_auth_fail_str(char *username, char *create_auth_fail_str(char *username,
char *hostaddr, char *hostaddr,
char *sha1, bool password,
char *db, char *db,
int errcode) int errcode)
{ {
@ -974,7 +975,7 @@ char *create_auth_fail_str(char *username,
if (db_len > 0) if (db_len > 0)
{ {
sprintf(errstr, ferrstr, username, hostaddr, (*sha1 == '\0' ? "NO" : "YES"), db); sprintf(errstr, ferrstr, username, hostaddr, password ? "YES": "NO", db);
} }
else if (errcode == MXS_AUTH_FAILED_SSL) else if (errcode == MXS_AUTH_FAILED_SSL)
{ {
@ -982,7 +983,7 @@ char *create_auth_fail_str(char *username,
} }
else else
{ {
sprintf(errstr, ferrstr, username, hostaddr, (*sha1 == '\0' ? "NO" : "YES")); sprintf(errstr, ferrstr, username, hostaddr, password ? "YES" : "NO");
} }
retblock: retblock: