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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f36747c1d61f440a5ff6b5d37981b0a11ad26a1b973ebeb9bab84e832b2841a3
4
- data.tar.gz: b654bac6dbc4d3451c5101e9f8574de4aee4044d6aa280c0736e3e18ad09c723
3
+ metadata.gz: dc0ed0331bd27abe2cf82b8c1e334dbd0d68ac93ae2bbd73fac5fe12874ee324
4
+ data.tar.gz: 457d93059c16e539c9b79f901269476f9380b0141e13edfd0624a0de6b5e06d1
5
5
  SHA512:
6
- metadata.gz: 81aefe81cfe750d70a42915c6a16f6d7211455b255a6588088c8ac6c682240636df5c2269b7090e78ba2ce6f991e3266f1c2b57711130e84fde85a8d38b22a1c
7
- data.tar.gz: 3df0441086b141c6c0ebb0d3a216d14205547bd340c06cf0884e1985ac6550023ea8960200c5afe31821160883a3cd96a07a942efb05a9d335153dcdafa83976
6
+ metadata.gz: d77b2c84b0fec65762a591e3685ac50f8a031cb74a7fee90ca4b1bf02173a8abd2d6c7b9be410c0bab7b71b6e85c5c13de8db21bddb93eb265aeeda395184f46
7
+ data.tar.gz: 668737a977f8d831fbb1509e4e9695e0d3ca83e7a60859a485d3ae7bed0d4c2659994fd0d33ac12cf73a74b09400a3ef7ee631e9c7bc3cccfcfb70b19dff745b
@@ -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
- handle_trilogy_error(ctx, rc, "trilogy_auth_recv");
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
- // Only support native password & caching sha2 password here.
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 read_generic_response(trilogy_conn_t *conn)
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, use_ssl ? 2 : 1);
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, 1);
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
- bool use_ssl = (conn->socket->opts.flags & TRILOGY_CAPABILITIES_SSL) != 0;
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 TRILOGY_PACKET_OK:
418
- trilogy_auth_clear_password(conn);
419
- return read_ok_packet(conn);
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
- case TRILOGY_PACKET_ERR:
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 read_err_packet(conn);
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 TRILOGY_UNEXPECTED_PACKET;
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
- return TRILOGY_OK;
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("caching_sha2_password", auth_plugin)) {
611
- trilogy_pack_scramble_sha2_hash(scramble, pass, pass_len, auth_response, &auth_response_len);
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
- trilogy_pack_scramble_native_hash(scramble, pass, pass_len, auth_response, &auth_response_len);
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 = trilogy_sock_wait_write((trilogy_sock_t *)sock)) < 0) {
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
@@ -1,3 +1,3 @@
1
1
  class Trilogy
2
- VERSION = "2.7.0"
2
+ VERSION = "2.8.0"
3
3
  end
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.7.0
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-01-23 00:00:00.000000000 Z
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.4.7
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