Merge pull request #1163 from Barenboim/mysql

Support MySQL 8 sha256 and caching_sha2 auth plugin.
This commit is contained in:
xiehan
2023-02-10 17:58:28 +08:00
committed by GitHub
5 changed files with 615 additions and 107 deletions
+1 -4
View File
@@ -550,10 +550,7 @@ CommMessageIn *ComplexHttpProxyTask::message_in()
return get_ssl_handshaker();
auto *msg = (ProtocolMessage *)this->ComplexHttpTask::message_in();
if (is_ssl_)
return get_ssl_wrapper(msg);
return msg;
return is_ssl_ ? get_ssl_wrapper(msg) : msg;
}
int ComplexHttpProxyTask::keep_alive_timeout()
+153 -43
View File
@@ -13,8 +13,8 @@
See the License for the specific language governing permissions and
limitations under the License.
Authors: Wu Jiaxu (wujiaxu@sogou-inc.com)
Xie Han (xiehan@sogou-inc.com)
Authors: Xie Han (xiehan@sogou-inc.com)
Wu Jiaxu (wujiaxu@sogou-inc.com)
Li Yingxin (liyingxin@sogou-inc.com)
*/
@@ -68,6 +68,11 @@ private:
{
ST_SSL_REQUEST,
ST_AUTH_REQUEST,
ST_AUTH_SWITCH_REQUEST,
ST_CLEAR_PASSWORD_REQUEST,
ST_SHA256_PUBLIC_KEY_REQUEST,
ST_CSHA2_PUBLIC_KEY_REQUEST,
ST_RSA_AUTH_REQUEST,
ST_CHARSET_REQUEST,
ST_FIRST_USER_REQUEST,
ST_USER_REQUEST
@@ -75,9 +80,10 @@ private:
struct MyConnection : public WFConnection
{
char challenge[20];
unsigned char mysql_seqid;
std::string str; // shared by auth, auth_swich and rsa_auth requests
unsigned char seed[20];
enum ConnState state;
unsigned char mysql_seqid;
SSL *ssl;
SSLWrapper wrapper;
MyConnection(SSL *ssl) : wrapper(&wrapper, ssl)
@@ -86,19 +92,8 @@ private:
}
};
int check_handshake();
SSL *get_ssl() const
{
return ((MyConnection *)this->get_connection())->ssl;
}
SSLWrapper *get_ssl_wrapper(ProtocolMessage *msg) const
{
auto *conn = (MyConnection *)this->get_connection();
conn->wrapper = SSLWrapper(msg, conn->ssl);
return &conn->wrapper;
}
int check_handshake(MySQLHandshakeResponse *resp);
int auth_switch(MySQLAuthResponse *resp, MyConnection *conn);
struct MySSLWrapper : public SSLWrapper
{
@@ -184,6 +179,8 @@ static SSL *__create_ssl(SSL_CTX *ssl_ctx)
CommMessageOut *ComplexMySQLTask::message_out()
{
MySQLAuthSwitchRequest *auth_switch_req;
MySQLRSAAuthRequest *rsa_auth_req;
MySQLAuthRequest *auth_req;
MySQLRequest *req;
@@ -195,16 +192,44 @@ CommMessageOut *ComplexMySQLTask::message_out()
switch (conn->state)
{
case ST_SSL_REQUEST:
req = new MySQLSSLRequest(character_set_, get_ssl());
req->set_seqid(conn->mysql_seqid++);
req = new MySQLSSLRequest(character_set_, conn->ssl);
req->set_seqid(conn->mysql_seqid);
return req;
case ST_AUTH_REQUEST:
req = new MySQLAuthRequest;
auth_req = (MySQLAuthRequest *)req;
auth_req->set_challenge(conn->challenge);
auth_req->set_auth(username_, password_, db_, character_set_);
req->set_seqid(conn->mysql_seqid++);
auth_req->set_auth_plugin_name(std::move(conn->str));
auth_req->set_seed(conn->seed);
break;
case ST_CLEAR_PASSWORD_REQUEST:
conn->str = "mysql_clear_password";
case ST_AUTH_SWITCH_REQUEST:
req = new MySQLAuthSwitchRequest;
auth_switch_req = (MySQLAuthSwitchRequest *)req;
auth_switch_req->set_password(password_);
auth_switch_req->set_auth_plugin_name(std::move(conn->str));
auth_switch_req->set_seed(conn->seed);
break;
case ST_SHA256_PUBLIC_KEY_REQUEST:
req = new MySQLPublicKeyRequest;
((MySQLPublicKeyRequest *)req)->set_sha256();
break;
case ST_CSHA2_PUBLIC_KEY_REQUEST:
req = new MySQLPublicKeyRequest;
((MySQLPublicKeyRequest *)req)->set_caching_sha2();
break;
case ST_RSA_AUTH_REQUEST:
req = new MySQLRSAAuthRequest;
rsa_auth_req = (MySQLRSAAuthRequest *)req;
rsa_auth_req->set_password(password_);
rsa_auth_req->set_public_key(std::move(conn->str));
rsa_auth_req->set_seed(conn->seed);
break;
case ST_CHARSET_REQUEST:
@@ -238,13 +263,19 @@ CommMessageOut *ComplexMySQLTask::message_out()
return NULL;
}
if (!is_user_request_ && conn->state != ST_CHARSET_REQUEST)
req->set_seqid(conn->mysql_seqid);
if (!is_ssl_)
return req;
if (is_user_request_)
return get_ssl_wrapper(req);
{
conn->wrapper = SSLWrapper(req, conn->ssl);
return &conn->wrapper;
}
else
return new MySSLWrapper(req, get_ssl());
return new MySSLWrapper(req, conn->ssl);
}
CommMessageIn *ComplexMySQLTask::message_in()
@@ -258,12 +289,23 @@ CommMessageIn *ComplexMySQLTask::message_in()
switch (conn->state)
{
case ST_SSL_REQUEST:
return new SSLHandshaker(get_ssl());
return new SSLHandshaker(conn->ssl);
case ST_AUTH_REQUEST:
case ST_AUTH_SWITCH_REQUEST:
resp = new MySQLAuthResponse;
break;
case ST_CLEAR_PASSWORD_REQUEST:
case ST_RSA_AUTH_REQUEST:
resp = new MySQLResponse;
break;
case ST_SHA256_PUBLIC_KEY_REQUEST:
case ST_CSHA2_PUBLIC_KEY_REQUEST:
resp = new MySQLPublicKeyResponse;
break;
case ST_CHARSET_REQUEST:
resp = new MySQLResponse;
break;
@@ -282,14 +324,16 @@ CommMessageIn *ComplexMySQLTask::message_in()
return resp;
if (is_user_request_)
return get_ssl_wrapper(resp);
{
conn->wrapper = SSLWrapper(resp, conn->ssl);
return &conn->wrapper;
}
else
return new MySSLWrapper(resp, get_ssl());
return new MySSLWrapper(resp, conn->ssl);
}
int ComplexMySQLTask::check_handshake()
int ComplexMySQLTask::check_handshake(MySQLHandshakeResponse *resp)
{
auto *resp = (MySQLHandshakeResponse *)this->get_message_in();
SSL *ssl = NULL;
if (resp->host_disallowed())
@@ -324,9 +368,13 @@ int ComplexMySQLTask::check_handshake()
auto *conn = this->get_connection();
auto *my_conn = new MyConnection(ssl);
my_conn->mysql_seqid = resp->get_seqid() + 1;
resp->get_challenge(my_conn->challenge);
my_conn->str = resp->get_auth_plugin_name();
if (my_conn->str == "sha256_password")
my_conn->str = "caching_sha2_password";
resp->get_seed(my_conn->seed);
my_conn->state = is_ssl_ ? ST_SSL_REQUEST : ST_AUTH_REQUEST;
my_conn->mysql_seqid = resp->get_seqid() + 1;
conn->set_context(my_conn, [](void *ctx) {
auto *my_conn = (MyConnection *)ctx;
if (my_conn->ssl)
@@ -337,16 +385,54 @@ int ComplexMySQLTask::check_handshake()
return MYSQL_KEEPALIVE_DEFAULT;
}
int ComplexMySQLTask::auth_switch(MySQLAuthResponse *resp, MyConnection *conn)
{
std::string name = resp->get_auth_plugin_name();
if (conn->state != ST_AUTH_REQUEST ||
(name == "mysql_clear_password" && !is_ssl_))
{
state_ = WFT_STATE_SYS_ERROR;
error_ = EBADMSG;
return 0;
}
if (name == "sha256_password")
{
if (is_ssl_)
conn->state = ST_CLEAR_PASSWORD_REQUEST;
else
conn->state = ST_SHA256_PUBLIC_KEY_REQUEST;
}
else
{
conn->str = std::move(name);
conn->state = ST_AUTH_SWITCH_REQUEST;
}
resp->get_seed(conn->seed);
conn->mysql_seqid = resp->get_seqid() + 1;
return MYSQL_KEEPALIVE_DEFAULT;
}
int ComplexMySQLTask::keep_alive_timeout()
{
auto *msg = (ProtocolMessage *)this->get_message_in();
MySQLAuthResponse *auth_resp;
MySQLResponse *resp;
state_ = WFT_STATE_SUCCESS;
error_ = 0;
if (this->get_seq() == 0)
return check_handshake();
return check_handshake((MySQLHandshakeResponse *)msg);
auto *conn = (MyConnection *)this->get_connection();
auto *msg = (ProtocolMessage *)this->get_message_in();
MySQLResponse *resp;
if (conn->state == ST_SSL_REQUEST)
{
conn->state = ST_AUTH_REQUEST;
conn->mysql_seqid++;
return MYSQL_KEEPALIVE_DEFAULT;
}
if (is_ssl_)
resp = (MySQLResponse *)((MySSLWrapper *)msg)->get_msg();
@@ -355,12 +441,23 @@ int ComplexMySQLTask::keep_alive_timeout()
switch (conn->state)
{
case ST_SSL_REQUEST:
conn->state = ST_AUTH_REQUEST;
break;
case ST_AUTH_REQUEST:
if (!resp->is_ok_packet())
case ST_AUTH_SWITCH_REQUEST:
case ST_CLEAR_PASSWORD_REQUEST:
case ST_RSA_AUTH_REQUEST:
if (resp->is_ok_packet())
{
if (!res_charset_.empty())
conn->state = ST_CHARSET_REQUEST;
else
conn->state = ST_FIRST_USER_REQUEST;
break;
}
if (resp->is_error_packet() ||
conn->state == ST_CLEAR_PASSWORD_REQUEST ||
conn->state == ST_RSA_AUTH_REQUEST)
{
this->resp = std::move(*resp);
state_ = WFT_STATE_TASK_ERROR;
@@ -368,11 +465,23 @@ int ComplexMySQLTask::keep_alive_timeout()
return 0;
}
if (res_charset_.size() != 0)
conn->state = ST_CHARSET_REQUEST;
else
conn->state = ST_FIRST_USER_REQUEST;
auth_resp = (MySQLAuthResponse *)resp;
if (auth_resp->is_continue())
{
if (is_ssl_)
conn->state = ST_CLEAR_PASSWORD_REQUEST;
else
conn->state = ST_CSHA2_PUBLIC_KEY_REQUEST;
break;
}
return auth_switch(auth_resp, conn);
case ST_SHA256_PUBLIC_KEY_REQUEST:
case ST_CSHA2_PUBLIC_KEY_REQUEST:
conn->str = ((MySQLPublicKeyResponse *)resp)->get_public_key();
conn->state = ST_RSA_AUTH_REQUEST;
break;
case ST_CHARSET_REQUEST:
@@ -385,7 +494,7 @@ int ComplexMySQLTask::keep_alive_timeout()
}
conn->state = ST_FIRST_USER_REQUEST;
break;
return MYSQL_KEEPALIVE_DEFAULT;
case ST_FIRST_USER_REQUEST:
conn->state = ST_USER_REQUEST;
@@ -397,6 +506,7 @@ int ComplexMySQLTask::keep_alive_timeout()
return 0;
}
conn->mysql_seqid = resp->get_seqid() + 1;
return MYSQL_KEEPALIVE_DEFAULT;
}
+262 -35
View File
@@ -13,11 +13,10 @@
See the License for the specific language governing permissions and
limitations under the License.
Authors: Wu Jiaxu (wujiaxu@sogou-inc.com)
Xie Han (xiehan@sogou-inc.com)
Authors: Xie Han (xiehan@sogou-inc.com)
Wu Jiaxu (wujiaxu@sogou-inc.com)
*/
#include <sys/uio.h>
#include <stdint.h>
#include <string.h>
#include <errno.h>
@@ -36,6 +35,10 @@ namespace protocol
#define MYSQL_PAYLOAD_MAX ((1 << 24) - 1)
#define MYSQL_NATIVE_PASSWORD "mysql_native_password"
#define CACHING_SHA2_PASSWORD "caching_sha2_password"
#define MYSQL_CLEAR_PASSWORD "mysql_clear_password"
MySQLMessage::~MySQLMessage()
{
if (parser_)
@@ -186,17 +189,27 @@ int MySQLHandshakeResponse::encode(struct iovec vectors[], int max)
buf_.append((const char *)&protocol_version_, 1);
buf_.append(server_version_.c_str(), server_version_.size() + 1);
buf_.append((const char *)&connection_id_, 4);
buf_.append((const char *)auth_plugin_data_part_1_, 8);
buf_.append((const char *)auth_plugin_data_, 8);
buf_.append(empty, 1);
buf_.append((const char *)&cap_flags_lower, 2);
buf_.append((const char *)&character_set_, 1);
buf_.append((const char *)&status_flags_, 2);
buf_.append((const char *)&cap_flags_upper, 2);
buf_.append(empty, 11);
buf_.append((const char *)auth_plugin_data_part_2_, 12);
buf_.append((const char *)auth_plugin_data_ + 8, 12);
return this->MySQLMessage::encode(vectors, max);
}
#define MYSQL_CAPFLAG_CLIENT_SSL 0x00000800
#define MYSQL_CAPFLAG_CLIENT_PROTOCOL_41 0x00000200
#define MYSQL_CAPFLAG_CLIENT_SECURE_CONNECTION 0x00008000
#define MYSQL_CAPFLAG_CLIENT_CONNECT_WITH_DB 0x00000008
#define MYSQL_CAPFLAG_CLIENT_MULTI_STATEMENTS 0x00010000
#define MYSQL_CAPFLAG_CLIENT_MULTI_RESULTS 0x00020000
#define MYSQL_CAPFLAG_CLIENT_PS_MULTI_RESULTS 0x00040000
#define MYSQL_CAPFLAG_CLIENT_PLUGIN_AUTH 0x00080000
#define MYSQL_CAPFLAG_CLIENT_LOCAL_FILES 0x00000080
int MySQLHandshakeResponse::decode_packet(const unsigned char *buf, size_t buflen)
{
const unsigned char *end = buf + buflen;
@@ -228,14 +241,15 @@ int MySQLHandshakeResponse::decode_packet(const unsigned char *buf, size_t bufle
while (pos < end && *pos)
pos++;
if (pos >= end || end - pos < 43)
if (pos >= end || end - pos < 45)
return -2;
server_version_.assign((const char *)buf, pos - buf);
buf = pos + 1;
connection_id_ = uint4korr(buf);
buf += 4;
memcpy(auth_plugin_data_part_1_, buf, 8);
memcpy(auth_plugin_data_, buf, 8);
buf += 9;
cap_flags_lower = uint2korr(buf);
buf += 2;
@@ -243,30 +257,63 @@ int MySQLHandshakeResponse::decode_packet(const unsigned char *buf, size_t bufle
status_flags_ = uint2korr(buf);
buf += 2;
cap_flags_upper = uint2korr(buf);
buf += 13;
memcpy(auth_plugin_data_part_2_, buf, 12);
buf += 2;
capability_flags_ = (cap_flags_upper << 16U) + cap_flags_lower;
auth_plugin_data_len_ = *buf++;
// 10 bytes reserved. All 0s.
buf += 10;
// auth_plugin_data always 20 bytes
if (auth_plugin_data_len_ > 21)
return -2;
memcpy(auth_plugin_data_ + 8, buf, 12);
buf += 13;
if (capability_flags_ & MYSQL_CAPFLAG_CLIENT_PLUGIN_AUTH)
{
if (buf == end || *(end - 1) != '\0')
return -2;
auth_plugin_name_.assign((const char *)buf, end - 1 - buf);
}
return 1;
}
static inline std::string __sha1_str(const std::string& str)
static std::string __native_password_encrypt(const std::string& password,
unsigned char seed[20])
{
unsigned char sha1[20];
SHA_CTX ctx;
SHA1_Init(&ctx);
SHA1_Update(&ctx, str.c_str(), str.size());
SHA1_Final(sha1, &ctx);
return std::string((const char *)sha1, 20);
unsigned char buf1[20];
unsigned char buf2[40];
int i;
// SHA1( password ) ^ SHA1( seed + SHA1( SHA1( password ) ) )
SHA1((unsigned char *)password.c_str(), password.size(), buf1);
SHA1(buf1, 20, buf2 + 20);
memcpy(buf2, seed, 20);
SHA1(buf2, 40, buf2);
for (i = 0; i < 20; i++)
buf1[i] ^= buf2[i];
return std::string((const char *)buf1, 20);
}
#define MYSQL_CAPFLAG_CLIENT_SSL 0x00000800
#define MYSQL_CAPFLAG_CLIENT_PROTOCOL_41 0x00000200
#define MYSQL_CAPFLAG_CLIENT_SECURE_CONNECTION 0x00008000
#define MYSQL_CAPFLAG_CLIENT_CONNECT_WITH_DB 0x00000008
#define MYSQL_CAPFLAG_CLIENT_MULTI_STATEMENTS 0x00010000
#define MYSQL_CAPFLAG_CLIENT_MULTI_RESULTS 0x00020000
#define MYSQL_CAPFLAG_CLIENT_PS_MULTI_RESULTS 0x00040000
#define MYSQL_CAPFLAG_CLIENT_LOCAL_FILES 0x00000080
static std::string __caching_sha2_password_encrypt(const std::string& password,
unsigned char seed[20])
{
unsigned char buf1[32];
unsigned char buf2[52];
int i;
// SHA256( password ) ^ SHA256( SHA256( SHA256( password ) ) + seed)
SHA256((unsigned char *)password.c_str(), password.size(), buf1);
SHA256(buf1, 32, buf2);
memcpy(buf2 + 32, seed, 20);
SHA256(buf2, 52, buf2);
for (i = 0; i < 32; i++)
buf1[i] ^= buf2[i];
return std::string((const char *)buf1, 32);
}
int MySQLSSLRequest::encode(struct iovec vectors[], int max)
{
@@ -281,7 +328,8 @@ int MySQLSSLRequest::encode(struct iovec vectors[], int max)
MYSQL_CAPFLAG_CLIENT_MULTI_RESULTS|
MYSQL_CAPFLAG_CLIENT_LOCAL_FILES |
MYSQL_CAPFLAG_CLIENT_MULTI_STATEMENTS |
MYSQL_CAPFLAG_CLIENT_PS_MULTI_RESULTS);
MYSQL_CAPFLAG_CLIENT_PS_MULTI_RESULTS |
MYSQL_CAPFLAG_CLIENT_PLUGIN_AUTH);
pos += 4;
int4store(pos, 0);
pos += 4;
@@ -308,9 +356,9 @@ int MySQLSSLRequest::encode(struct iovec vectors[], int max)
int MySQLAuthRequest::encode(struct iovec vectors[], int max)
{
std::string native;
unsigned char header[32] = {0};
unsigned char *pos = header;
std::string str;
int4store(pos, MYSQL_CAPFLAG_CLIENT_PROTOCOL_41 |
MYSQL_CAPFLAG_CLIENT_SECURE_CONNECTION |
@@ -318,29 +366,34 @@ int MySQLAuthRequest::encode(struct iovec vectors[], int max)
MYSQL_CAPFLAG_CLIENT_MULTI_RESULTS|
MYSQL_CAPFLAG_CLIENT_LOCAL_FILES |
MYSQL_CAPFLAG_CLIENT_MULTI_STATEMENTS |
MYSQL_CAPFLAG_CLIENT_PS_MULTI_RESULTS);
MYSQL_CAPFLAG_CLIENT_PS_MULTI_RESULTS |
MYSQL_CAPFLAG_CLIENT_PLUGIN_AUTH);
pos += 4;
int4store(pos, 0);
pos += 4;
*pos = (uint8_t)character_set_;
if (password_.empty())
native.push_back((char)0);
str.push_back(0);
else if (auth_plugin_name_ == CACHING_SHA2_PASSWORD)
{
str.push_back(32);
str += __caching_sha2_password_encrypt(password_, seed_);
}
else
{
native.push_back((char)20);
std::string first = __sha1_str(password_);
std::string second = __sha1_str(challenge_ + __sha1_str(first));
for (int i = 0; i < 20; i++)
native.push_back(first[i] ^ second[i]);
str.push_back(20);
str += __native_password_encrypt(password_, seed_);
}
buf_.clear();
buf_.append((char *)header, 32);
buf_.append(username_.c_str(), username_.size() + 1);
buf_.append(native);
buf_.append(str);
buf_.append(db_.c_str(), db_.size() + 1);
if (auth_plugin_name_.size() != 0)
buf_.append(auth_plugin_name_.c_str(), auth_plugin_name_.size() + 1);
return this->MySQLMessage::encode(vectors, max);
}
@@ -374,6 +427,180 @@ int MySQLAuthRequest::decode_packet(const unsigned char *buf, size_t buflen)
return 1;
}
int MySQLAuthResponse::decode_packet(const unsigned char *buf, size_t buflen)
{
const unsigned char *end = buf + buflen;
const unsigned char *pos;
const unsigned char *str;
unsigned long long len;
int ret;
if (end == buf)
return -2;
switch (*buf)
{
case 0x00:
case 0xff:
return MySQLResponse::decode_packet(buf, buflen);
case 0xfe:
pos = ++buf;
while (pos < end && *pos)
pos++;
if (pos >= end)
return -2;
auth_plugin_name_.assign((const char *)buf, pos - buf);
buf = pos + 1;
if (buf == end || *(end - 1) != '\0')
return -2;
if (end - 1 - buf != 20)
return -2;
memcpy(seed_, buf, 20);
return 1;
default:
pos = buf;
ret = decode_string(&str, &len, &pos, end);
if (ret <= 0)
return ret;
if (len == 1)
{
if (*str == 0x03)
{
if (end > pos)
return MySQLResponse::decode_packet(pos, end - pos);
else
return 0;
}
else if (*str == 0x04)
{
continue_ = true;
return 1;
}
}
return -2;
}
}
int MySQLAuthSwitchRequest::encode(struct iovec vectors[], int max)
{
if (auth_plugin_name_ == MYSQL_NATIVE_PASSWORD)
{
buf_ = __native_password_encrypt(password_, seed_);
}
else if (auth_plugin_name_ == CACHING_SHA2_PASSWORD)
{
buf_ = __caching_sha2_password_encrypt(password_, seed_);
}
else if (auth_plugin_name_ == MYSQL_CLEAR_PASSWORD)
{
buf_ = password_;
buf_.push_back('\0');
}
else
{
errno = EINVAL;
return -1;
}
return this->MySQLMessage::encode(vectors, max);
}
int MySQLPublicKeyResponse::decode_packet(const unsigned char *buf,
size_t buflen)
{
if (buflen == 0 || *buf != 0x01)
return -2;
if (buflen == 1)
return 0;
public_key_.assign((const char *)buf + 1, buflen - 1);
return 1;
}
int MySQLPublicKeyResponse::encode(struct iovec vectors[], int max)
{
buf_.clear();
buf_.push_back(0x01);
buf_ += public_key_;
return MySQLMessage::encode(vectors, max);
}
int MySQLRSAAuthRequest::rsa_encrypt(void *ctx)
{
EVP_PKEY_CTX *pkey_ctx = (EVP_PKEY_CTX *)ctx;
unsigned char out[256];
size_t outlen = 256;
std::string pass;
unsigned char *p;
size_t i;
if (EVP_PKEY_encrypt_init(pkey_ctx) > 0 &&
EVP_PKEY_CTX_set_rsa_padding(pkey_ctx, RSA_PKCS1_OAEP_PADDING) > 0)
{
pass.reserve(password_.size() + 1);
p = (unsigned char *)pass.c_str();
for (i = 0; i <= password_.size(); i++)
p[i] = (unsigned char)password_[i] ^ seed_[i % 20];
if (EVP_PKEY_encrypt(pkey_ctx, out, &outlen, p, i) > 0)
{
buf_.assign((char *)out, 256);
return 0;
}
}
return -1;
}
int MySQLRSAAuthRequest::encode(struct iovec vectors[], int max)
{
RSA *rsa;
BIO *bio;
bio = BIO_new_mem_buf(public_key_.c_str(), public_key_.size());
if (!bio)
return -1;
rsa = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL);
BIO_free(bio);
if (!rsa)
return -1;
EVP_PKEY_CTX *pkey_ctx;
EVP_PKEY *pkey;
int ret = -1;
pkey = EVP_PKEY_new();
if (pkey)
{
EVP_PKEY_assign_RSA(pkey, rsa);
pkey_ctx = EVP_PKEY_CTX_new(pkey, NULL);
if (pkey_ctx)
{
ret = rsa_encrypt(pkey_ctx);
EVP_PKEY_CTX_free(pkey_ctx);
}
EVP_PKEY_free(pkey);
}
else
RSA_free(rsa);
if (ret < 0)
return -1;
return MySQLMessage::encode(vectors, max);
}
void MySQLResponse::set_ok_packet()
{
uint16_t zero16 = 0;
+197 -23
View File
@@ -13,12 +13,13 @@
See the License for the specific language governing permissions and
limitations under the License.
Authors: Wu Jiaxu (wujiaxu@sogou-inc.com)
Xie Han (xiehan@sogou-inc.com)
Authors: Xie Han (xiehan@sogou-inc.com)
Wu Jiaxu (wujiaxu@sogou-inc.com)
*/
#include <stdint.h>
#include <string.h>
#include <utility>
#include <string>
#include <openssl/ssl.h>
#include "SSLWrapper.h"
@@ -35,27 +36,28 @@ private:
class MySQLHandshakeResponse : public MySQLResponse
{
public:
void get_challenge(char *arr) const
std::string get_server_version() const { return server_version_; }
std::string get_auth_plugin_name() const { return auth_plugin_name_; }
void get_seed(unsigned char seed[20]) const
{
memcpy(arr, auth_plugin_data_part_1_, 8);
memcpy(arr + 8, auth_plugin_data_part_2_, 12);
memcpy(seed, auth_plugin_data_, 20);
}
virtual int encode(struct iovec vectors[], int max);
void server_set(uint8_t protocol_version, const std::string server_version,
uint32_t connection_id, const uint8_t *auth1,
uint32_t connection_id, const unsigned char seed[20],
uint32_t capability_flags, uint8_t character_set,
uint16_t status_flags, const uint8_t *auth2)
uint16_t status_flags)
{
protocol_version_ = protocol_version;
server_version_ = server_version;
connection_id_ = connection_id;
memcpy(auth_plugin_data_part_1_, auth1, 8);
memcpy(auth_plugin_data_, seed, 20);
capability_flags_ = capability_flags;
character_set_ = character_set;
status_flags_ = status_flags;
memcpy(auth_plugin_data_part_2_, auth2, 12);
}
bool host_disallowed() const { return disallowed_; }
@@ -65,14 +67,15 @@ public:
private:
virtual int decode_packet(const unsigned char *buf, size_t buflen);
uint8_t protocol_version_;
std::string server_version_;
std::string auth_plugin_name_;
unsigned char auth_plugin_data_[20];
uint32_t connection_id_;
uint8_t auth_plugin_data_part_1_[8];
uint32_t capability_flags_;
uint8_t character_set_;
uint16_t status_flags_;
uint8_t auth_plugin_data_part_2_[12];
uint8_t character_set_;
uint8_t auth_plugin_data_len_;
uint8_t protocol_version_;
bool disallowed_;
public:
@@ -111,20 +114,25 @@ public:
class MySQLAuthRequest : public MySQLRequest
{
public:
void set_auth(const std::string& username,
const std::string& password,
const std::string& db,
void set_auth(const std::string username,
const std::string password,
const std::string db,
int character_set)
{
username_ = username;
password_ = password;
db_ = db;
username_ = std::move(username);
password_ = std::move(password);
db_ = std::move(db);
character_set_ = character_set;
}
void set_challenge(const char *arr)
void set_auth_plugin_name(std::string name)
{
challenge_.assign(arr, 20);
auth_plugin_name_ = std::move(name);
}
void set_seed(const unsigned char seed[20])
{
memcpy(seed_, seed, 20);
}
private:
@@ -134,7 +142,8 @@ private:
std::string username_;
std::string password_;
std::string db_;
std::string challenge_;
std::string auth_plugin_name_;
unsigned char seed_[20];
int character_set_;
public:
@@ -145,7 +154,172 @@ public:
MySQLAuthRequest& operator= (MySQLAuthRequest&& move) = default;
};
using MySQLAuthResponse = MySQLResponse;
class MySQLAuthResponse : public MySQLResponse
{
public:
std::string get_auth_plugin_name() const { return auth_plugin_name_; }
void get_seed(unsigned char seed[20]) const
{
memcpy(seed, seed_, 20);
}
bool is_continue() const
{
return continue_;
}
private:
virtual int decode_packet(const unsigned char *buf, size_t buflen);
private:
std::string auth_plugin_name_;
unsigned char seed_[20];
bool continue_;
public:
MySQLAuthResponse() : continue_(false) { }
//move constructor
MySQLAuthResponse(MySQLAuthResponse&& move) = default;
//move operator
MySQLAuthResponse& operator= (MySQLAuthResponse&& move) = default;
};
class MySQLAuthSwitchRequest : public MySQLRequest
{
public:
void set_password(std::string password)
{
password_ = std::move(password);
}
void set_auth_plugin_name(std::string name)
{
auth_plugin_name_ = std::move(name);
}
void set_seed(const unsigned char seed[20])
{
memcpy(seed_, seed, 20);
}
private:
virtual int encode(struct iovec vectors[], int max);
/* Not implemented. */
virtual int decode_packet(const unsigned char *buf, size_t buflen)
{
return -2;
}
std::string password_;
std::string auth_plugin_name_;
unsigned char seed_[20];
public:
MySQLAuthSwitchRequest() { }
//move constructor
MySQLAuthSwitchRequest(MySQLAuthSwitchRequest&& move) = default;
//move operator
MySQLAuthSwitchRequest& operator= (MySQLAuthSwitchRequest&& move) = default;
};
class MySQLPublicKeyRequest : public MySQLRequest
{
public:
void set_caching_sha2() { byte_ = 0x02; }
void set_sha256() { byte_ = 0x01; }
private:
virtual int encode(struct iovec vectors[], int max)
{
buf_.assign(&byte_, 1);
return MySQLRequest::encode(vectors, max);
}
/* Not implemented. */
virtual int decode_packet(const unsigned char *buf, size_t buflen)
{
return -2;
}
char byte_;
public:
MySQLPublicKeyRequest() : byte_(0x01) { }
//move constructor
MySQLPublicKeyRequest(MySQLPublicKeyRequest&& move) = default;
//move operator
MySQLPublicKeyRequest& operator= (MySQLPublicKeyRequest&& move) = default;
};
class MySQLPublicKeyResponse : public MySQLResponse
{
public:
std::string get_public_key() const
{
return public_key_;
}
void set_public_key(std::string key)
{
public_key_ = std::move(key);
}
private:
virtual int encode(struct iovec vectors[], int max);
virtual int decode_packet(const unsigned char *buf, size_t buflen);
std::string public_key_;
public:
MySQLPublicKeyResponse() { }
//move constructor
MySQLPublicKeyResponse(MySQLPublicKeyResponse&& move) = default;
//move operator
MySQLPublicKeyResponse& operator= (MySQLPublicKeyResponse&& move) = default;
};
class MySQLRSAAuthRequest : public MySQLRequest
{
public:
void set_password(std::string password)
{
password_ = std::move(password);
}
void set_public_key(std::string key)
{
public_key_ = std::move(key);
}
void set_seed(const unsigned char seed[20])
{
memcpy(seed_, seed, 20);
}
private:
virtual int encode(struct iovec vectors[], int max);
/* Not implemented. */
virtual int decode_packet(const unsigned char *buf, size_t buflen)
{
return -2;
}
int rsa_encrypt(void *ctx);
std::string password_;
std::string public_key_;
unsigned char seed_[20];
public:
MySQLRSAAuthRequest() { }
//move constructor
MySQLRSAAuthRequest(MySQLRSAAuthRequest&& move) = default;
//move operator
MySQLRSAAuthRequest& operator= (MySQLRSAAuthRequest&& move) = default;
};
//////////
+2 -2
View File
@@ -29,8 +29,8 @@ WFConnection *WFMySQLServer::new_connection(int accept_fd)
struct iovec vec[8];
int count;
resp.server_set(0x0a, "5.5", 1, (const uint8_t *)"12345678",
0, 33, 0, (const uint8_t *)"123456789abc");
resp.server_set(0x0a, "5.5", 1, (const uint8_t *)"12345678901234567890",
0, 33, 0);
count = resp.encode(vec, 8);
if (count >= 0)
{