trilogy 2.7.0 → 2.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|