28
28
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29
29
*/
30
30
31
- #include " auth_mysql41 .h"
31
+ #include " auth_hash .h"
32
32
#include < stdint.h>
33
33
#include < stdexcept>
34
34
#include < string.h> // memset
58
58
#define PVERSION41_CHAR ' *'
59
59
#define SCRAMBLE_LENGTH 20
60
60
#define SHA1_HASH_SIZE 20
61
+ #define SHA256_HASH_SIZE 32
61
62
62
63
#if defined( WITH_SSL_YASSL)
63
64
using namespace TaoCrypt ;
@@ -77,6 +78,9 @@ class SHA
77
78
}
78
79
79
80
public:
81
+
82
+ enum { DIGEST_SIZE = SHA1_HASH_SIZE }; // in Bytes
83
+
80
84
SHA ()
81
85
{
82
86
init ();
@@ -92,6 +96,40 @@ class SHA
92
96
SHA1_Final (hash, &m_sha);
93
97
init ();
94
98
}
99
+
100
+ size_t getDigestSize () const {return SHA1_HASH_SIZE; }
101
+ };
102
+
103
+ class SHA256
104
+ {
105
+ SHA256_CTX m_sha;
106
+
107
+ void init ()
108
+ {
109
+ SHA256_Init (&m_sha);
110
+ }
111
+
112
+ public:
113
+
114
+ enum { DIGEST_SIZE = SHA256_HASH_SIZE }; // in Bytes
115
+
116
+ SHA256 ()
117
+ {
118
+ init ();
119
+ }
120
+
121
+ void Update (byte* data, length_t length)
122
+ {
123
+ SHA256_Update (&m_sha, data, length);
124
+ }
125
+
126
+ void Final (byte* hash)
127
+ {
128
+ SHA256_Final (hash, &m_sha);
129
+ init ();
130
+ }
131
+
132
+ size_t getDigestSize () const {return SHA256_HASH_SIZE; }
95
133
};
96
134
#endif
97
135
@@ -106,37 +144,47 @@ static void my_crypt(uint8_t *to, const uint8_t *s1, const uint8_t *s2, size_t l
106
144
107
145
108
146
147
+ template <class SHA_Crypt >
109
148
static std::string scramble (const std::string &scramble_data, const std::string &password)
110
149
{
111
- class SHA sha1 ;
150
+ SHA_Crypt sha ;
112
151
113
152
if (scramble_data.length () != SCRAMBLE_LENGTH)
114
153
throw std::invalid_argument (" Password scramble data is invalid" );
115
154
116
- byte hash_stage1[SHA1_HASH_SIZE ];
117
- byte hash_stage2[SHA1_HASH_SIZE ];
118
- byte result_buf[SHA1_HASH_SIZE +1 ];
155
+ byte hash_stage1[SHA_Crypt::DIGEST_SIZE ];
156
+ byte hash_stage2[SHA_Crypt::DIGEST_SIZE ];
157
+ byte result_buf[SHA_Crypt::DIGEST_SIZE +1 ];
119
158
120
159
memset (result_buf, 0 , sizeof (result_buf));
121
160
122
161
/* Two stage SHA1 hash of the pwd */
123
162
/* Stage 1: hash pwd */
124
- sha1 .Update ((byte*)password.data (), (length_t )password.length ());
125
- sha1 .Final (hash_stage1);
163
+ sha .Update ((byte*)password.data (), (length_t )password.length ());
164
+ sha .Final (hash_stage1);
126
165
127
166
/* Stage 2 : hash first stage's output. */
128
- sha1 .Update (hash_stage1, SHA1_HASH_SIZE );
129
- sha1 .Final (hash_stage2);
167
+ sha .Update (hash_stage1, sha. getDigestSize () );
168
+ sha .Final (hash_stage2);
130
169
131
170
/* create crypt string as sha1(message, hash_stage2) */ ;
132
- sha1.Update ((byte*)scramble_data.data (), (length_t )scramble_data.length ());
133
- sha1.Update (hash_stage2, SHA1_HASH_SIZE);
134
- sha1.Final (result_buf);
135
- result_buf[SHA1_HASH_SIZE] = ' \0 ' ;
171
+ /* MYSQL41 and SHA256_PASSWORD have different behaviors here! Bug? */
172
+ if (sha.getDigestSize () == SHA1_HASH_SIZE)
173
+ {
174
+ sha.Update ((byte*)scramble_data.data (), (length_t )scramble_data.length ());
175
+ sha.Update (hash_stage2, sha.getDigestSize ());
176
+ }
177
+ else
178
+ {
179
+ sha.Update (hash_stage2, sha.getDigestSize ());
180
+ sha.Update ((byte*)scramble_data.data (), (length_t )scramble_data.length ());
181
+ }
182
+ sha.Final (result_buf);
183
+ result_buf[sha.getDigestSize ()] = ' \0 ' ;
136
184
137
- my_crypt (result_buf, result_buf, hash_stage1, SCRAMBLE_LENGTH );
185
+ my_crypt (result_buf, result_buf, hash_stage1, sha. getDigestSize () );
138
186
139
- return std::string ((char *)result_buf, SCRAMBLE_LENGTH );
187
+ return std::string ((char *)result_buf, sha. getDigestSize () );
140
188
}
141
189
142
190
static char *octet2hex (char *to, const char *str, size_t len)
@@ -153,8 +201,9 @@ static char *octet2hex(char *to, const char *str, size_t len)
153
201
return to;
154
202
}
155
203
204
+ // MYSQL41 specific
156
205
157
- static std::string get_password_from_salt (const std::string &hash_stage2)
206
+ static std::string get_password_from_salt_mysql41 (const std::string &hash_stage2)
158
207
{
159
208
std::string result (2 *SHA1_HASH_SIZE + 1 , ' \0 ' );
160
209
@@ -168,18 +217,19 @@ static std::string get_password_from_salt(const std::string &hash_stage2)
168
217
}
169
218
170
219
171
- std::string mysqlx::build_mysql41_authentication_response (const std::string &salt_data,
172
- const std::string &user,
173
- const std::string &password,
174
- const std::string &schema)
220
+ std::string mysqlx::build_mysql41_authentication_response (
221
+ const std::string &salt_data,
222
+ const std::string &user,
223
+ const std::string &password,
224
+ const std::string &schema)
175
225
{
176
226
std::string data;
177
227
std::string password_hash;
178
228
179
229
if (password.length ())
180
230
{
181
- password_hash = scramble (salt_data, password);
182
- password_hash = get_password_from_salt (password_hash);
231
+ password_hash = scramble< class SHA > (salt_data, password);
232
+ password_hash = get_password_from_salt_mysql41 (password_hash);
183
233
}
184
234
185
235
data.append (schema).push_back (' \0 ' ); // authz
@@ -188,3 +238,38 @@ std::string mysqlx::build_mysql41_authentication_response(const std::string &sal
188
238
189
239
return data;
190
240
}
241
+
242
+ // SHA256_MEMORY specific
243
+
244
+ static std::string get_password_from_salt_sha256 (const std::string &hash_stage2)
245
+ {
246
+ std::string result (2 *SHA256_HASH_SIZE +1 , ' \0 ' );
247
+
248
+ if (hash_stage2.length () != SHA256_HASH_SIZE)
249
+ throw std::invalid_argument (" Wrong size of binary hash password" );
250
+
251
+ octet2hex (&result[0 ], &hash_stage2[0 ], SHA256_HASH_SIZE);
252
+
253
+ return result;
254
+ }
255
+
256
+ std::string mysqlx::build_sha256_authentication_response (
257
+ const std::string &salt_data,
258
+ const std::string &user,
259
+ const std::string &password,
260
+ const std::string &schema)
261
+ {
262
+ std::string password_hash;
263
+ std::string data;
264
+
265
+ password_hash = scramble<class SHA256 >(salt_data, password);
266
+ password_hash = get_password_from_salt_sha256 (password_hash);
267
+ // REMOVE ending \0
268
+ password_hash.pop_back ();
269
+
270
+ data.append (schema).push_back (' \0 ' ); // authz
271
+ data.append (user).push_back (' \0 ' ); // authc
272
+ data.append (password_hash); // pass
273
+
274
+ return data;
275
+ }
0 commit comments