trilogy 2.7.0 → 2.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/ext/trilogy-ruby/cext.c +48 -4
- data/ext/trilogy-ruby/inc/trilogy/error.h +2 -1
- data/ext/trilogy-ruby/inc/trilogy/protocol.h +6 -1
- data/ext/trilogy-ruby/inc/trilogy/socket.h +19 -0
- data/ext/trilogy-ruby/src/client.c +86 -22
- data/ext/trilogy-ruby/src/protocol.c +26 -6
- data/ext/trilogy-ruby/src/socket.c +24 -1
- data/lib/trilogy/error.rb +5 -0
- data/lib/trilogy/version.rb +1 -1
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc0ed0331bd27abe2cf82b8c1e334dbd0d68ac93ae2bbd73fac5fe12874ee324
|
4
|
+
data.tar.gz: 457d93059c16e539c9b79f901269476f9380b0141e13edfd0624a0de6b5e06d1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d77b2c84b0fec65762a591e3685ac50f8a031cb74a7fee90ca4b1bf02173a8abd2d6c7b9be410c0bab7b71b6e85c5c13de8db21bddb93eb265aeeda395184f46
|
7
|
+
data.tar.gz: 668737a977f8d831fbb1509e4e9695e0d3ca83e7a60859a485d3ae7bed0d4c2659994fd0d33ac12cf73a74b09400a3ef7ee631e9c7bc3cccfcfb70b19dff745b
|
data/ext/trilogy-ruby/cext.c
CHANGED
@@ -18,12 +18,12 @@
|
|
18
18
|
VALUE Trilogy_CastError;
|
19
19
|
static VALUE Trilogy_BaseConnectionError, Trilogy_ProtocolError, Trilogy_SSLError, Trilogy_QueryError,
|
20
20
|
Trilogy_ConnectionClosedError,
|
21
|
-
Trilogy_TimeoutError, Trilogy_SyscallError, Trilogy_Result, Trilogy_EOFError;
|
21
|
+
Trilogy_TimeoutError, Trilogy_SyscallError, Trilogy_Result, Trilogy_EOFError, Trilogy_AuthPluginError;
|
22
22
|
|
23
23
|
static ID id_socket, id_host, id_port, id_username, id_password, id_found_rows, id_connect_timeout, id_read_timeout,
|
24
24
|
id_write_timeout, id_keepalive_enabled, id_keepalive_idle, id_keepalive_interval, id_keepalive_count,
|
25
25
|
id_ivar_affected_rows, id_ivar_fields, id_ivar_last_insert_id, id_ivar_rows, id_ivar_query_time, id_password,
|
26
|
-
id_database, id_ssl_ca, id_ssl_capath, id_ssl_cert, id_ssl_cipher, id_ssl_crl, id_ssl_crlpath, id_ssl_key,
|
26
|
+
id_database, id_enable_cleartext_plugin, id_ssl_ca, id_ssl_capath, id_ssl_cert, id_ssl_cipher, id_ssl_crl, id_ssl_crlpath, id_ssl_key,
|
27
27
|
id_ssl_mode, id_tls_ciphersuites, id_tls_min_version, id_tls_max_version, id_multi_statement, id_multi_result,
|
28
28
|
id_from_code, id_from_errno, id_connection_options, id_max_allowed_packet;
|
29
29
|
|
@@ -156,6 +156,14 @@ static void handle_trilogy_error(struct trilogy_ctx *ctx, int rc, const char *ms
|
|
156
156
|
rb_raise(Trilogy_EOFError, "%" PRIsVALUE ": TRILOGY_CLOSED_CONNECTION", rbmsg);
|
157
157
|
}
|
158
158
|
|
159
|
+
case TRILOGY_AUTH_PLUGIN_ERROR: {
|
160
|
+
rb_raise(Trilogy_AuthPluginError, "%" PRIsVALUE ": TRILOGY_AUTH_PLUGIN_ERROR", rbmsg);
|
161
|
+
}
|
162
|
+
|
163
|
+
case TRILOGY_UNSUPPORTED: {
|
164
|
+
rb_raise(Trilogy_BaseConnectionError, "%" PRIsVALUE ": TRILOGY_UNSUPPORTED", rbmsg);
|
165
|
+
}
|
166
|
+
|
159
167
|
default:
|
160
168
|
rb_raise(Trilogy_QueryError, "%" PRIsVALUE ": %s", rbmsg, trilogy_error(rc));
|
161
169
|
}
|
@@ -239,7 +247,18 @@ static int _cb_ruby_wait(trilogy_sock_t *sock, trilogy_wait_t wait)
|
|
239
247
|
wait_flag = RB_WAITFD_OUT;
|
240
248
|
break;
|
241
249
|
|
250
|
+
case TRILOGY_WAIT_CONNECT:
|
251
|
+
// wait for connection to be writable
|
252
|
+
timeout = &sock->opts.connect_timeout;
|
253
|
+
if (timeout->tv_sec == 0 && timeout->tv_usec == 0) {
|
254
|
+
// We used to use the write timeout for this, so if a connect timeout isn't configured, default to that.
|
255
|
+
timeout = &sock->opts.write_timeout;
|
256
|
+
}
|
257
|
+
wait_flag = RB_WAITFD_OUT;
|
258
|
+
break;
|
259
|
+
|
242
260
|
case TRILOGY_WAIT_HANDSHAKE:
|
261
|
+
// wait for handshake packet on initial connection
|
243
262
|
timeout = &sock->opts.connect_timeout;
|
244
263
|
wait_flag = RB_WAITFD_IN;
|
245
264
|
break;
|
@@ -408,7 +427,12 @@ static void authenticate(struct trilogy_ctx *ctx, trilogy_handshake_t *handshake
|
|
408
427
|
}
|
409
428
|
|
410
429
|
if (rc != TRILOGY_AGAIN) {
|
411
|
-
|
430
|
+
if (rc == TRILOGY_UNSUPPORTED) {
|
431
|
+
handle_trilogy_error(ctx, rc, "trilogy_auth_recv: caching_sha2_password requires either TCP with TLS or a unix socket");
|
432
|
+
}
|
433
|
+
else {
|
434
|
+
handle_trilogy_error(ctx, rc, "trilogy_auth_recv");
|
435
|
+
}
|
412
436
|
}
|
413
437
|
|
414
438
|
rc = trilogy_sock_wait_read(ctx->conn.socket);
|
@@ -511,6 +535,10 @@ static VALUE rb_trilogy_connect(VALUE self, VALUE encoding, VALUE charset, VALUE
|
|
511
535
|
connopt.flags |= TRILOGY_CAPABILITIES_CONNECT_WITH_DB;
|
512
536
|
}
|
513
537
|
|
538
|
+
if (RTEST(rb_hash_aref(opts, ID2SYM(id_enable_cleartext_plugin)))) {
|
539
|
+
connopt.enable_cleartext_plugin = true;
|
540
|
+
}
|
541
|
+
|
514
542
|
if (RTEST(rb_hash_aref(opts, ID2SYM(id_found_rows)))) {
|
515
543
|
connopt.flags |= TRILOGY_CAPABILITIES_FOUND_ROWS;
|
516
544
|
}
|
@@ -1014,6 +1042,17 @@ static VALUE rb_trilogy_closed(VALUE self)
|
|
1014
1042
|
}
|
1015
1043
|
}
|
1016
1044
|
|
1045
|
+
static VALUE rb_trilogy_check(VALUE self)
|
1046
|
+
{
|
1047
|
+
struct trilogy_ctx *ctx = get_open_ctx(self);
|
1048
|
+
|
1049
|
+
int rc = trilogy_sock_check(ctx->conn.socket);
|
1050
|
+
if (rc != TRILOGY_OK && rc != TRILOGY_AGAIN) {
|
1051
|
+
handle_trilogy_error(ctx, rc, "trilogy_sock_check");
|
1052
|
+
}
|
1053
|
+
return Qtrue;
|
1054
|
+
}
|
1055
|
+
|
1017
1056
|
static VALUE rb_trilogy_discard(VALUE self)
|
1018
1057
|
{
|
1019
1058
|
struct trilogy_ctx *ctx = get_ctx(self);
|
@@ -1092,7 +1131,7 @@ static VALUE rb_trilogy_server_status(VALUE self) { return LONG2FIX(get_open_ctx
|
|
1092
1131
|
|
1093
1132
|
static VALUE rb_trilogy_server_version(VALUE self) { return rb_str_new_cstr(get_open_ctx(self)->server_version); }
|
1094
1133
|
|
1095
|
-
RUBY_FUNC_EXPORTED void Init_cext()
|
1134
|
+
RUBY_FUNC_EXPORTED void Init_cext(void)
|
1096
1135
|
{
|
1097
1136
|
VALUE Trilogy = rb_const_get(rb_cObject, rb_intern("Trilogy"));
|
1098
1137
|
rb_define_alloc_func(Trilogy, allocate_trilogy);
|
@@ -1105,6 +1144,7 @@ RUBY_FUNC_EXPORTED void Init_cext()
|
|
1105
1144
|
rb_define_method(Trilogy, "escape", rb_trilogy_escape, 1);
|
1106
1145
|
rb_define_method(Trilogy, "close", rb_trilogy_close, 0);
|
1107
1146
|
rb_define_method(Trilogy, "closed?", rb_trilogy_closed, 0);
|
1147
|
+
rb_define_method(Trilogy, "check", rb_trilogy_check, 0);
|
1108
1148
|
rb_define_method(Trilogy, "discard!", rb_trilogy_discard, 0);
|
1109
1149
|
rb_define_method(Trilogy, "last_insert_id", rb_trilogy_last_insert_id, 0);
|
1110
1150
|
rb_define_method(Trilogy, "affected_rows", rb_trilogy_affected_rows, 0);
|
@@ -1170,6 +1210,9 @@ RUBY_FUNC_EXPORTED void Init_cext()
|
|
1170
1210
|
Trilogy_EOFError = rb_const_get(Trilogy, rb_intern("EOFError"));
|
1171
1211
|
rb_global_variable(&Trilogy_EOFError);
|
1172
1212
|
|
1213
|
+
rb_global_variable(&Trilogy_AuthPluginError);
|
1214
|
+
Trilogy_AuthPluginError = rb_const_get(Trilogy, rb_intern("AuthPluginError"));
|
1215
|
+
|
1173
1216
|
id_socket = rb_intern("socket");
|
1174
1217
|
id_host = rb_intern("host");
|
1175
1218
|
id_port = rb_intern("port");
|
@@ -1185,6 +1228,7 @@ RUBY_FUNC_EXPORTED void Init_cext()
|
|
1185
1228
|
id_keepalive_count = rb_intern("keepalive_count");
|
1186
1229
|
id_keepalive_interval = rb_intern("keepalive_interval");
|
1187
1230
|
id_database = rb_intern("database");
|
1231
|
+
id_enable_cleartext_plugin = rb_intern("enable_cleartext_plugin");
|
1188
1232
|
id_ssl_ca = rb_intern("ssl_ca");
|
1189
1233
|
id_ssl_capath = rb_intern("ssl_capath");
|
1190
1234
|
id_ssl_cert = rb_intern("ssl_cert");
|
@@ -24,7 +24,8 @@
|
|
24
24
|
XX(TRILOGY_AUTH_SWITCH, -19) \
|
25
25
|
XX(TRILOGY_MAX_PACKET_EXCEEDED, -20) \
|
26
26
|
XX(TRILOGY_UNKNOWN_TYPE, -21) \
|
27
|
-
XX(TRILOGY_TIMEOUT, -22)
|
27
|
+
XX(TRILOGY_TIMEOUT, -22) \
|
28
|
+
XX(TRILOGY_AUTH_PLUGIN_ERROR, -23)
|
28
29
|
|
29
30
|
enum {
|
30
31
|
#define XX(name, code) name = code,
|
@@ -367,6 +367,7 @@ typedef enum {
|
|
367
367
|
// Typical response packet types
|
368
368
|
typedef enum {
|
369
369
|
TRILOGY_PACKET_OK = 0x0,
|
370
|
+
TRILOGY_PACKET_AUTH_MORE_DATA = 0x01,
|
370
371
|
TRILOGY_PACKET_EOF = 0xfe,
|
371
372
|
TRILOGY_PACKET_ERR = 0xff,
|
372
373
|
TRILOGY_PACKET_UNKNOWN
|
@@ -442,14 +443,16 @@ int trilogy_build_auth_packet(trilogy_builder_t *builder, const char *user, cons
|
|
442
443
|
* pass_len - The length of password in bytes.
|
443
444
|
* auth_plugin - Plugin authentication mechanism that the server requested.
|
444
445
|
* scramble - The scramble value received from the server.
|
446
|
+
* enable_cleartext_plugin - Send cleartext password if requested by server.
|
445
447
|
*
|
446
448
|
* Return values:
|
447
449
|
* TRILOGY_OK - The packet was successfully built and written to the
|
448
450
|
* builder's internal buffer.
|
449
451
|
* TRILOGY_SYSERR - A system error occurred, check errno.
|
452
|
+
* TRILOGY_AUTH_PLUGIN_ERROR - The server requested auth plugin is not supported.
|
450
453
|
*/
|
451
454
|
int trilogy_build_auth_switch_response_packet(trilogy_builder_t *builder, const char *pass, size_t pass_len,
|
452
|
-
const char *auth_plugin, const char *scramble);
|
455
|
+
const char *auth_plugin, const char *scramble, const bool enable_cleartext_plugin);
|
453
456
|
|
454
457
|
/* trilogy_build_change_db_packet - Build a change database command packet. This
|
455
458
|
* command will change the default database for the connection.
|
@@ -1035,4 +1038,6 @@ int trilogy_parse_stmt_ok_packet(const uint8_t *buff, size_t len, trilogy_stmt_o
|
|
1035
1038
|
int trilogy_parse_stmt_row_packet(const uint8_t *buff, size_t len, trilogy_column_packet_t *columns,
|
1036
1039
|
uint64_t column_count, trilogy_binary_value_t *out_values);
|
1037
1040
|
|
1041
|
+
int trilogy_build_auth_clear_password(trilogy_builder_t *builder, const char *pass, size_t pass_len);
|
1042
|
+
|
1038
1043
|
#endif
|
@@ -13,6 +13,7 @@ typedef enum {
|
|
13
13
|
TRILOGY_WAIT_READ = 0,
|
14
14
|
TRILOGY_WAIT_WRITE = 1,
|
15
15
|
TRILOGY_WAIT_HANDSHAKE = 2,
|
16
|
+
TRILOGY_WAIT_CONNECT = 3,
|
16
17
|
} trilogy_wait_t;
|
17
18
|
|
18
19
|
// We use the most strict mode as value 1 so if anyone ever
|
@@ -66,6 +67,8 @@ typedef struct {
|
|
66
67
|
uint16_t keepalive_count;
|
67
68
|
uint16_t keepalive_interval;
|
68
69
|
|
70
|
+
bool enable_cleartext_plugin;
|
71
|
+
|
69
72
|
TRILOGY_CAPABILITIES_t flags;
|
70
73
|
|
71
74
|
size_t max_allowed_packet;
|
@@ -111,4 +114,20 @@ trilogy_sock_t *trilogy_sock_new(const trilogy_sockopt_t *opts);
|
|
111
114
|
int trilogy_sock_resolve(trilogy_sock_t *raw);
|
112
115
|
int trilogy_sock_upgrade_ssl(trilogy_sock_t *raw);
|
113
116
|
|
117
|
+
/* trilogy_sock_check - Verify if the socket is still alive and not disconnected.
|
118
|
+
*
|
119
|
+
* This check is very cheap to do and reduces the number of errors when for
|
120
|
+
* example the server has restarted since the connection was opened. In connection
|
121
|
+
* pooling implementations, this check can be done before the connection is
|
122
|
+
* returned.
|
123
|
+
*
|
124
|
+
* raw - A connected trilogy_sock_t pointer. Using a disconnected trilogy_sock_t is undefined.
|
125
|
+
*
|
126
|
+
* Return values:
|
127
|
+
* TRILOGY_OK - The connection is alive on the client side and can be.
|
128
|
+
* TRILOGY_CLOSED_CONNECTION - The connection is closed.
|
129
|
+
* TRILOGY_SYSERR - A system error occurred, check errno.
|
130
|
+
*/
|
131
|
+
int trilogy_sock_check(trilogy_sock_t *raw);
|
132
|
+
|
114
133
|
#endif
|
@@ -248,8 +248,9 @@ static int read_auth_switch_packet(trilogy_conn_t *conn, trilogy_handshake_t *ha
|
|
248
248
|
}
|
249
249
|
|
250
250
|
if (strcmp("mysql_native_password", auth_switch_packet.auth_plugin) &&
|
251
|
-
strcmp("caching_sha2_password", auth_switch_packet.auth_plugin)
|
252
|
-
|
251
|
+
strcmp("caching_sha2_password", auth_switch_packet.auth_plugin) &&
|
252
|
+
strcmp("mysql_clear_password", auth_switch_packet.auth_plugin)) {
|
253
|
+
// Only support native password, caching sha2 and cleartext password here.
|
253
254
|
return TRILOGY_PROTOCOL_VIOLATION;
|
254
255
|
}
|
255
256
|
|
@@ -258,14 +259,7 @@ static int read_auth_switch_packet(trilogy_conn_t *conn, trilogy_handshake_t *ha
|
|
258
259
|
return TRILOGY_AUTH_SWITCH;
|
259
260
|
}
|
260
261
|
|
261
|
-
static int
|
262
|
-
{
|
263
|
-
int rc = read_packet(conn);
|
264
|
-
|
265
|
-
if (rc < 0) {
|
266
|
-
return rc;
|
267
|
-
}
|
268
|
-
|
262
|
+
static int handle_generic_response(trilogy_conn_t *conn) {
|
269
263
|
switch (current_packet_type(conn)) {
|
270
264
|
case TRILOGY_PACKET_OK:
|
271
265
|
return read_ok_packet(conn);
|
@@ -278,6 +272,17 @@ static int read_generic_response(trilogy_conn_t *conn)
|
|
278
272
|
}
|
279
273
|
}
|
280
274
|
|
275
|
+
static int read_generic_response(trilogy_conn_t *conn)
|
276
|
+
{
|
277
|
+
int rc = read_packet(conn);
|
278
|
+
|
279
|
+
if (rc < 0) {
|
280
|
+
return rc;
|
281
|
+
}
|
282
|
+
|
283
|
+
return handle_generic_response(conn);
|
284
|
+
}
|
285
|
+
|
281
286
|
int trilogy_connect_send(trilogy_conn_t *conn, const trilogy_sockopt_t *opts)
|
282
287
|
{
|
283
288
|
trilogy_sock_t *sock = trilogy_sock_new(opts);
|
@@ -336,9 +341,8 @@ int trilogy_connect_recv(trilogy_conn_t *conn, trilogy_handshake_t *handshake_ou
|
|
336
341
|
int trilogy_auth_send(trilogy_conn_t *conn, const trilogy_handshake_t *handshake)
|
337
342
|
{
|
338
343
|
trilogy_builder_t builder;
|
339
|
-
bool use_ssl = (conn->socket->opts.flags & TRILOGY_CAPABILITIES_SSL) != 0;
|
340
344
|
|
341
|
-
int rc = begin_command_phase(&builder, conn,
|
345
|
+
int rc = begin_command_phase(&builder, conn, conn->packet_parser.sequence_number);
|
342
346
|
|
343
347
|
if (rc < 0) {
|
344
348
|
return rc;
|
@@ -360,7 +364,7 @@ int trilogy_ssl_request_send(trilogy_conn_t *conn)
|
|
360
364
|
{
|
361
365
|
trilogy_builder_t builder;
|
362
366
|
|
363
|
-
int rc = begin_command_phase(&builder, conn,
|
367
|
+
int rc = begin_command_phase(&builder, conn, conn->packet_parser.sequence_number);
|
364
368
|
|
365
369
|
if (rc < 0) {
|
366
370
|
return rc;
|
@@ -380,8 +384,7 @@ int trilogy_auth_switch_send(trilogy_conn_t *conn, const trilogy_handshake_t *ha
|
|
380
384
|
{
|
381
385
|
trilogy_builder_t builder;
|
382
386
|
|
383
|
-
|
384
|
-
int rc = begin_command_phase(&builder, conn, use_ssl ? 4 : 3);
|
387
|
+
int rc = begin_command_phase(&builder, conn, conn->packet_parser.sequence_number);
|
385
388
|
|
386
389
|
if (rc < 0) {
|
387
390
|
return rc;
|
@@ -389,7 +392,7 @@ int trilogy_auth_switch_send(trilogy_conn_t *conn, const trilogy_handshake_t *ha
|
|
389
392
|
|
390
393
|
rc = trilogy_build_auth_switch_response_packet(&builder, conn->socket->opts.password,
|
391
394
|
conn->socket->opts.password_len, handshake->auth_plugin,
|
392
|
-
handshake->scramble);
|
395
|
+
handshake->scramble, conn->socket->opts.enable_cleartext_plugin);
|
393
396
|
|
394
397
|
if (rc < 0) {
|
395
398
|
return rc;
|
@@ -405,6 +408,9 @@ void trilogy_auth_clear_password(trilogy_conn_t *conn)
|
|
405
408
|
}
|
406
409
|
}
|
407
410
|
|
411
|
+
#define FAST_AUTH_OK 3
|
412
|
+
#define FAST_AUTH_FAIL 4
|
413
|
+
|
408
414
|
int trilogy_auth_recv(trilogy_conn_t *conn, trilogy_handshake_t *handshake)
|
409
415
|
{
|
410
416
|
int rc = read_packet(conn);
|
@@ -414,13 +420,69 @@ int trilogy_auth_recv(trilogy_conn_t *conn, trilogy_handshake_t *handshake)
|
|
414
420
|
}
|
415
421
|
|
416
422
|
switch (current_packet_type(conn)) {
|
417
|
-
case
|
418
|
-
|
419
|
-
|
423
|
+
case TRILOGY_PACKET_AUTH_MORE_DATA: {
|
424
|
+
bool use_ssl = (conn->socket->opts.flags & TRILOGY_CAPABILITIES_SSL) != 0;
|
425
|
+
bool has_unix_socket = (conn->socket->opts.path != NULL);
|
420
426
|
|
421
|
-
|
427
|
+
if (!use_ssl && !has_unix_socket) {
|
428
|
+
return TRILOGY_UNSUPPORTED;
|
429
|
+
}
|
430
|
+
|
431
|
+
uint8_t byte = conn->packet_buffer.buff[1];
|
432
|
+
switch (byte) {
|
433
|
+
case FAST_AUTH_OK:
|
434
|
+
break;
|
435
|
+
case FAST_AUTH_FAIL:
|
436
|
+
{
|
437
|
+
trilogy_builder_t builder;
|
438
|
+
int err = begin_command_phase(&builder, conn, conn->packet_parser.sequence_number);
|
439
|
+
|
440
|
+
if (err < 0) {
|
441
|
+
return err;
|
442
|
+
}
|
443
|
+
|
444
|
+
err = trilogy_build_auth_clear_password(&builder, conn->socket->opts.password, conn->socket->opts.password_len);
|
445
|
+
|
446
|
+
if (err < 0) {
|
447
|
+
return err;
|
448
|
+
}
|
449
|
+
|
450
|
+
int rc = begin_write(conn);
|
451
|
+
|
452
|
+
while (rc == TRILOGY_AGAIN) {
|
453
|
+
rc = trilogy_sock_wait_write(conn->socket);
|
454
|
+
if (rc != TRILOGY_OK) {
|
455
|
+
return rc;
|
456
|
+
}
|
457
|
+
|
458
|
+
rc = trilogy_flush_writes(conn);
|
459
|
+
}
|
460
|
+
if (rc != TRILOGY_OK) {
|
461
|
+
return rc;
|
462
|
+
}
|
463
|
+
|
464
|
+
break;
|
465
|
+
}
|
466
|
+
default:
|
467
|
+
return TRILOGY_UNEXPECTED_PACKET;
|
468
|
+
}
|
469
|
+
while (1) {
|
470
|
+
rc = read_packet(conn);
|
471
|
+
|
472
|
+
if (rc == TRILOGY_OK) {
|
473
|
+
break;
|
474
|
+
}
|
475
|
+
else if (rc == TRILOGY_AGAIN) {
|
476
|
+
rc = trilogy_sock_wait_read(conn->socket);
|
477
|
+
}
|
478
|
+
|
479
|
+
if (rc != TRILOGY_OK) {
|
480
|
+
return rc;
|
481
|
+
}
|
482
|
+
}
|
422
483
|
trilogy_auth_clear_password(conn);
|
423
|
-
return
|
484
|
+
return handle_generic_response(conn);
|
485
|
+
}
|
424
486
|
|
425
487
|
case TRILOGY_PACKET_EOF:
|
426
488
|
// EOF is returned here if an auth switch is requested.
|
@@ -428,9 +490,11 @@ int trilogy_auth_recv(trilogy_conn_t *conn, trilogy_handshake_t *handshake)
|
|
428
490
|
// in a follow up call to this function after the switch.
|
429
491
|
return read_auth_switch_packet(conn, handshake);
|
430
492
|
|
493
|
+
case TRILOGY_PACKET_OK:
|
494
|
+
case TRILOGY_PACKET_ERR:
|
431
495
|
default:
|
432
496
|
trilogy_auth_clear_password(conn);
|
433
|
-
return
|
497
|
+
return handle_generic_response(conn);
|
434
498
|
}
|
435
499
|
|
436
500
|
return read_generic_response(conn);
|
@@ -593,28 +593,48 @@ int trilogy_build_auth_packet(trilogy_builder_t *builder, const char *user, cons
|
|
593
593
|
|
594
594
|
trilogy_builder_finalize(builder);
|
595
595
|
|
596
|
-
|
596
|
+
fail:
|
597
|
+
return rc;
|
598
|
+
}
|
599
|
+
|
600
|
+
int trilogy_build_auth_clear_password(trilogy_builder_t *builder, const char *pass, size_t pass_len) {
|
601
|
+
int rc = TRILOGY_OK;
|
602
|
+
|
603
|
+
CHECKED(trilogy_builder_write_buffer(builder, pass, pass_len));
|
604
|
+
CHECKED(trilogy_builder_write_uint8(builder, 0));
|
605
|
+
trilogy_builder_finalize(builder);
|
597
606
|
|
598
607
|
fail:
|
599
608
|
return rc;
|
600
609
|
}
|
601
610
|
|
602
611
|
int trilogy_build_auth_switch_response_packet(trilogy_builder_t *builder, const char *pass, size_t pass_len,
|
603
|
-
const char *auth_plugin, const char *scramble)
|
612
|
+
const char *auth_plugin, const char *scramble, const bool enable_cleartext_plugin)
|
604
613
|
{
|
605
614
|
int rc = TRILOGY_OK;
|
606
615
|
unsigned int auth_response_len = 0;
|
607
616
|
uint8_t auth_response[EVP_MAX_MD_SIZE];
|
608
617
|
|
609
618
|
if (pass_len > 0) {
|
610
|
-
if (!strcmp("
|
611
|
-
|
619
|
+
if (!strcmp("mysql_clear_password", auth_plugin)) {
|
620
|
+
if (enable_cleartext_plugin) {
|
621
|
+
CHECKED(trilogy_builder_write_buffer(builder, pass, pass_len));
|
622
|
+
} else {
|
623
|
+
return TRILOGY_AUTH_PLUGIN_ERROR;
|
624
|
+
}
|
612
625
|
} else {
|
613
|
-
|
626
|
+
if (!strcmp("caching_sha2_password", auth_plugin)) {
|
627
|
+
trilogy_pack_scramble_sha2_hash(scramble, pass, pass_len, auth_response, &auth_response_len);
|
628
|
+
} else if (!strcmp("mysql_native_password", auth_plugin)) {
|
629
|
+
trilogy_pack_scramble_native_hash(scramble, pass, pass_len, auth_response, &auth_response_len);
|
630
|
+
} else {
|
631
|
+
return TRILOGY_AUTH_PLUGIN_ERROR;
|
632
|
+
}
|
633
|
+
|
634
|
+
CHECKED(trilogy_builder_write_buffer(builder, auth_response, auth_response_len));
|
614
635
|
}
|
615
636
|
}
|
616
637
|
|
617
|
-
CHECKED(trilogy_builder_write_buffer(builder, auth_response, auth_response_len));
|
618
638
|
trilogy_builder_finalize(builder);
|
619
639
|
|
620
640
|
return TRILOGY_OK;
|
@@ -40,6 +40,7 @@ static int _cb_wait(trilogy_sock_t *_sock, trilogy_wait_t wait)
|
|
40
40
|
case TRILOGY_WAIT_READ:
|
41
41
|
pfd.events = POLLIN;
|
42
42
|
break;
|
43
|
+
case TRILOGY_WAIT_CONNECT:
|
43
44
|
case TRILOGY_WAIT_WRITE:
|
44
45
|
pfd.events = POLLOUT;
|
45
46
|
break;
|
@@ -252,7 +253,7 @@ static int raw_connect_internal(struct trilogy_sock *sock, const struct addrinfo
|
|
252
253
|
}
|
253
254
|
}
|
254
255
|
|
255
|
-
if ((rc =
|
256
|
+
if ((rc = trilogy_sock_wait((trilogy_sock_t *)sock, TRILOGY_WAIT_CONNECT)) < 0) {
|
256
257
|
goto failrc;
|
257
258
|
}
|
258
259
|
|
@@ -724,3 +725,25 @@ fail:
|
|
724
725
|
sock->ssl = NULL;
|
725
726
|
return TRILOGY_OPENSSL_ERR;
|
726
727
|
}
|
728
|
+
|
729
|
+
int trilogy_sock_check(trilogy_sock_t *_sock)
|
730
|
+
{
|
731
|
+
struct trilogy_sock *sock = (struct trilogy_sock *)_sock;
|
732
|
+
char buf[1];
|
733
|
+
while (1) {
|
734
|
+
ssize_t data_read = recv(sock->fd, buf, 1, MSG_PEEK);
|
735
|
+
if (data_read > 0) {
|
736
|
+
return TRILOGY_OK;
|
737
|
+
}
|
738
|
+
if (data_read == 0) {
|
739
|
+
return TRILOGY_CLOSED_CONNECTION;
|
740
|
+
}
|
741
|
+
if (errno == EINTR) {
|
742
|
+
continue;
|
743
|
+
}
|
744
|
+
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
745
|
+
return TRILOGY_OK;
|
746
|
+
}
|
747
|
+
return TRILOGY_SYSERR;
|
748
|
+
}
|
749
|
+
}
|
data/lib/trilogy/error.rb
CHANGED
@@ -115,4 +115,9 @@ class Trilogy
|
|
115
115
|
# attempted on a socket which previously encountered an error.
|
116
116
|
class EOFError < BaseConnectionError
|
117
117
|
end
|
118
|
+
|
119
|
+
# Occurs when the server request an auth switch to an incompatible
|
120
|
+
# authentication plugin
|
121
|
+
class AuthPluginError < Trilogy::BaseConnectionError
|
122
|
+
end
|
118
123
|
end
|
data/lib/trilogy/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: trilogy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- GitHub Engineering
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-04-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake-compiler
|
@@ -102,7 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
102
102
|
- !ruby/object:Gem::Version
|
103
103
|
version: '0'
|
104
104
|
requirements: []
|
105
|
-
rubygems_version: 3.
|
105
|
+
rubygems_version: 3.5.3
|
106
106
|
signing_key:
|
107
107
|
specification_version: 4
|
108
108
|
summary: A friendly MySQL-compatible library for Ruby, binding to libtrilogy
|