I am trying to write my own mysql client.but I send data to server always receive: “packets out of or …”
I have been resolve server info and are successfully.
env:
mysql 8.0.32
Protocol::HandshakeV10
this is my code:
unsigned char stage0[SHA256_DIGEST_LENGTH];
unsigned char stage1[SHA256_DIGEST_LENGTH];
unsigned char stage2[SHA256_DIGEST_LENGTH];
unsigned char stage3[SHA256_DIGEST_LENGTH];
unsigned char stageAll[SHA256_DIGEST_LENGTH];
if (strcmp(MySQLServInfo.MySQLServInfoData.AuthPluginName.c_str(), MySQLPluginName.cachingSha2Password) == 0) {
// using caching_sha2_password
// XOR(SHA256(password), SHA256(SHA256(SHA256(password)), Nonce))
// globalVar.MySQL_Password is string, is mysql password.
// first sha256 -> SHA256(password) general sha256 digest.
SHA256((const unsigned char*) globalVar.MySQL_Password.c_str(), strlen(globalVar.MySQL_Password.c_str()), stage0);
// second sha256 inner -> SHA256(password)
SHA256((const unsigned char*) globalVar.MySQL_Password.c_str(), strlen(globalVar.MySQL_Password.c_str()), stage1);
// SHA256(SHA256(password))
SHA256((const unsigned char*) stage1, sizeof(stage1)/sizeof(stage1[0]), stage2);
// stage2 + nonce
// MySQLServInfo.MySQLServInfoData.ServerAuthDataPart: client recived
exchange number.contain tow part.length: 8(one of part) + 12(two of part).
for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
MySQLServInfo.MySQLServInfoData.ServerAuthDataPart += stage2[i];
}
// SHA256(SHA256(SHA256(password)), Nonce)
SHA256((const unsigned char*)MySQLServInfo.MySQLServInfoData.ServerAuthDataPart.c_str(), strlen(MySQLServInfo.MySQLServInfoData.ServerAuthDataPart.c_str()), stage3);
// stage0 ^ stage3 -> XOR(SHA256(password), SHA256(SHA256(SHA256(password)), Nonce))
for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
stageAll[i] = stage0[i] ^ stage3[i];
}
} else if (strcmp(MySQLServInfo.MySQLServInfoData.AuthPluginName.c_str(), MySQLPluginName.mysqlNativePassword) == 0) {
// sha1
...
} else {
printf("unknown auth plugin: %s", MySQLServInfo.MySQLServInfoData.AuthPluginName.c_str());
return 0;
}
// CapabilityFlags1
// length of stage3
const int authRespLen = sizeof(stage3);
uint8_t authRespLEIBuf[9];
// return authRespLEI = 32. SHA256_DIGEST_LENGTH's length
uint8_t* authRespLEI = appendLengthEncodedInteger(authRespLEIBuf, authRespLen);
// send data length
const int pktLen = 4 + 4 + 4 + 1 + 23 + strlen(MySQLClientSendInfo.MySQLClientSendInfoData.UserName.c_str()) + 1 + 33 +
strlen(MySQLClientSendInfo.MySQLClientSendInfoData.DataBaseName.c_str()) + 1 + strlen(MySQLClientSendInfo.MySQLClientSendInfoData.ClientPluginName.c_str()) + 1;
uint8_t data[pktLen];
// From mysql source code: CLIENT_BASIC_FLAGS, define:
// #define CLIENT_BASIC_FLAGS
// (CLIENT_ALL_FLAGS &
// ~(CLIENT_SSL | CLIENT_COMPRESS | CLIENT_SSL_VERIFY_SERVER_CERT |
// CLIENT_ZSTD_COMPRESSION_ALGORITHM))
MySQLClientSendInfo.MySQLClientSendInfoData.CapabilityFlagsAll = CLIENT_BASIC_FLAGS;
int position = 0;
for(int i = 0; i < 3; i++){
data[position] = (pktLen-4 >> (i * 8)) & 0b11111111;
position += 1;
}
data[position] = 1;
position += 1; // 4
data[position] = MySQLClientSendInfo.MySQLClientSendInfoData.CapabilityFlagsAll;
position += 1;
data[position] = 0x00;
position += 1;
data[position] = 0x00;
position += 1;
data[position] = 0x00;
position += 1;
// max packet length
data[position] = pktLen;
position += 1;
data[position] = 0x00;
position += 1;
data[position] = 0x00;
position += 1;
data[position] = 0x00;
position += 1;
// character set
for (int i = 0; i < 23; ++i) {
data[position] = MySQLClientSendInfo.MySQLClientSendInfoData.Filler[i];
position += 1;
}
// username
for(int i = 0; i < strlen(MySQLClientSendInfo.MySQLClientSendInfoData.UserName.c_str()) + 1; i++) {
data[position] = MySQLClientSendInfo.MySQLClientSendInfoData.UserName[i];
position += 1;
}
data[position] = authRespLEI; // stageAll length 32
position += 1;
// append to data
for (int i = 0; i < SHA256_DIGEST_LENGTH; ++i) {
data[position] = stageAll[i];
position += 1;
}
// database name
for(int i = 0; i < strlen(MySQLClientSendInfo.MySQLClientSendInfoData.DataBaseName.c_str()) + 1; i++) {
data[position] = MySQLClientSendInfo.MySQLClientSendInfoData.DataBaseName[i];
position += 1;
}
// plugin name: caching_sha2_password
for(int i = 0; i < strlen(MySQLClientSendInfo.MySQLClientSendInfoData.ClientPluginName.c_str()) + 1; i++) {
data[position] = MySQLClientSendInfo.MySQLClientSendInfoData.ClientPluginName[i];
position += 1;
}
int len = send(fd, data, sizeof(data)/sizeof(data[0]), 0);
thank you for reply me.
all format in Protocol::HandshakeV10.i can not recv correct message.
New contributor
yuuki is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.