trilogy 2.9.0 → 2.12.4
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/README.md +1 -1
- data/Rakefile +16 -1
- data/ext/trilogy-ruby/cast.c +181 -55
- data/ext/trilogy-ruby/cext.c +337 -125
- data/ext/trilogy-ruby/extconf.rb +15 -3
- data/ext/trilogy-ruby/inc/trilogy/allocator.h +61 -0
- data/ext/trilogy-ruby/inc/trilogy/buffer.h +13 -0
- data/ext/trilogy-ruby/inc/trilogy/client.h +11 -0
- data/ext/trilogy-ruby/inc/trilogy/error.h +2 -1
- data/ext/trilogy-ruby/inc/trilogy/socket.h +2 -0
- data/ext/trilogy-ruby/inc/trilogy.h +1 -0
- data/ext/trilogy-ruby/src/buffer.c +25 -5
- data/ext/trilogy-ruby/src/client.c +425 -99
- data/ext/trilogy-ruby/src/packet_parser.c +1 -1
- data/ext/trilogy-ruby/src/socket.c +39 -29
- data/ext/trilogy-ruby/trilogy-ruby.h +4 -2
- data/ext/trilogy-ruby/trilogy_xallocator.h +1 -0
- data/lib/trilogy/encoding.rb +2 -0
- data/lib/trilogy/error.rb +7 -0
- data/lib/trilogy/result.rb +18 -0
- data/lib/trilogy/version.rb +1 -1
- data/lib/trilogy.rb +81 -1
- data/trilogy.gemspec +3 -2
- metadata +12 -24
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
#include <fcntl.h>
|
|
2
|
-
|
|
2
|
+
#include <limits.h>
|
|
3
|
+
#include <openssl/err.h>
|
|
4
|
+
#include <openssl/evp.h>
|
|
5
|
+
#include <openssl/pem.h>
|
|
6
|
+
#include <openssl/rsa.h>
|
|
7
|
+
#include <stdlib.h>
|
|
8
|
+
#include <string.h>
|
|
9
|
+
|
|
10
|
+
#include "trilogy/allocator.h"
|
|
3
11
|
#include "trilogy/client.h"
|
|
4
12
|
#include "trilogy/error.h"
|
|
5
13
|
|
|
@@ -117,10 +125,40 @@ static int begin_write(trilogy_conn_t *conn)
|
|
|
117
125
|
return trilogy_flush_writes(conn);
|
|
118
126
|
}
|
|
119
127
|
|
|
120
|
-
int
|
|
128
|
+
static int flush_current_packet(trilogy_conn_t *conn)
|
|
129
|
+
{
|
|
130
|
+
int rc = begin_write(conn);
|
|
131
|
+
|
|
132
|
+
while (rc == TRILOGY_AGAIN) {
|
|
133
|
+
rc = trilogy_sock_wait_write(conn->socket);
|
|
134
|
+
|
|
135
|
+
if (rc != TRILOGY_OK) {
|
|
136
|
+
return rc;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
rc = trilogy_flush_writes(conn);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
return rc;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
static int read_packet_blocking(trilogy_conn_t *conn)
|
|
121
146
|
{
|
|
122
147
|
int rc;
|
|
123
148
|
|
|
149
|
+
while ((rc = read_packet(conn)) == TRILOGY_AGAIN) {
|
|
150
|
+
rc = trilogy_sock_wait_read(conn->socket);
|
|
151
|
+
|
|
152
|
+
if (rc != TRILOGY_OK) {
|
|
153
|
+
return rc;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return rc;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
int trilogy_init_no_buffer(trilogy_conn_t *conn)
|
|
161
|
+
{
|
|
124
162
|
conn->affected_rows = 0;
|
|
125
163
|
conn->last_insert_id = 0;
|
|
126
164
|
conn->warning_count = 0;
|
|
@@ -142,8 +180,14 @@ int trilogy_init(trilogy_conn_t *conn)
|
|
|
142
180
|
trilogy_packet_parser_init(&conn->packet_parser, &packet_parser_callbacks);
|
|
143
181
|
conn->packet_parser.user_data = &conn->packet_buffer;
|
|
144
182
|
|
|
145
|
-
|
|
183
|
+
return TRILOGY_OK;
|
|
184
|
+
}
|
|
146
185
|
|
|
186
|
+
int trilogy_init(trilogy_conn_t *conn)
|
|
187
|
+
{
|
|
188
|
+
int rc;
|
|
189
|
+
trilogy_init_no_buffer(conn);
|
|
190
|
+
CHECKED(trilogy_buffer_init(&conn->packet_buffer, TRILOGY_DEFAULT_BUF_SIZE));
|
|
147
191
|
return TRILOGY_OK;
|
|
148
192
|
}
|
|
149
193
|
|
|
@@ -217,7 +261,7 @@ static int read_err_packet(trilogy_conn_t *conn)
|
|
|
217
261
|
return TRILOGY_ERR;
|
|
218
262
|
}
|
|
219
263
|
|
|
220
|
-
static int
|
|
264
|
+
static int read_deprecated_eof_packet(trilogy_conn_t *conn)
|
|
221
265
|
{
|
|
222
266
|
trilogy_eof_packet_t eof_packet;
|
|
223
267
|
|
|
@@ -236,6 +280,36 @@ static int read_eof_packet(trilogy_conn_t *conn)
|
|
|
236
280
|
return TRILOGY_EOF;
|
|
237
281
|
}
|
|
238
282
|
|
|
283
|
+
bool is_eof_packet(trilogy_conn_t *conn)
|
|
284
|
+
{
|
|
285
|
+
// An EOF packet first byte can mark an EOF/OK packet, a deprecated EOF packet, or a huge data packet.
|
|
286
|
+
if (current_packet_type(conn) == TRILOGY_PACKET_EOF) {
|
|
287
|
+
if (conn->capabilities & TRILOGY_CAPABILITIES_DEPRECATE_EOF) {
|
|
288
|
+
// The EOF/OK packet can contain an info message and/or session state info up to max packet length.
|
|
289
|
+
return conn->packet_buffer.len <= TRILOGY_MAX_PACKET_LEN;
|
|
290
|
+
} else {
|
|
291
|
+
// The deprecated EOF packet must be smaller than 9 bytes (one 8-byte length-encoded integer).
|
|
292
|
+
return conn->packet_buffer.len < 9;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
return false;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
static int read_eof_packet(trilogy_conn_t *conn)
|
|
299
|
+
{
|
|
300
|
+
int rc;
|
|
301
|
+
|
|
302
|
+
if (conn->capabilities & TRILOGY_CAPABILITIES_DEPRECATE_EOF) {
|
|
303
|
+
return read_ok_packet(conn);
|
|
304
|
+
} else {
|
|
305
|
+
if ((rc = read_deprecated_eof_packet(conn)) != TRILOGY_EOF) {
|
|
306
|
+
return rc;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return TRILOGY_OK;
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
|
|
239
313
|
static int read_auth_switch_packet(trilogy_conn_t *conn, trilogy_handshake_t *handshake)
|
|
240
314
|
{
|
|
241
315
|
trilogy_auth_switch_request_packet_t auth_switch_packet;
|
|
@@ -259,7 +333,8 @@ static int read_auth_switch_packet(trilogy_conn_t *conn, trilogy_handshake_t *ha
|
|
|
259
333
|
return TRILOGY_AUTH_SWITCH;
|
|
260
334
|
}
|
|
261
335
|
|
|
262
|
-
static int handle_generic_response(trilogy_conn_t *conn)
|
|
336
|
+
static int handle_generic_response(trilogy_conn_t *conn)
|
|
337
|
+
{
|
|
263
338
|
switch (current_packet_type(conn)) {
|
|
264
339
|
case TRILOGY_PACKET_OK:
|
|
265
340
|
return read_ok_packet(conn);
|
|
@@ -310,6 +385,16 @@ int trilogy_connect_send_socket(trilogy_conn_t *conn, trilogy_sock_t *sock)
|
|
|
310
385
|
return TRILOGY_OK;
|
|
311
386
|
}
|
|
312
387
|
|
|
388
|
+
int trilogy_connect_set_fd(trilogy_conn_t *conn, trilogy_sock_t *sock, int fd)
|
|
389
|
+
{
|
|
390
|
+
trilogy_sock_set_fd(sock, fd);
|
|
391
|
+
|
|
392
|
+
conn->socket = sock;
|
|
393
|
+
conn->packet_parser.sequence_number = 0;
|
|
394
|
+
|
|
395
|
+
return TRILOGY_OK;
|
|
396
|
+
}
|
|
397
|
+
|
|
313
398
|
int trilogy_connect_recv(trilogy_conn_t *conn, trilogy_handshake_t *handshake_out)
|
|
314
399
|
{
|
|
315
400
|
int rc = read_packet(conn);
|
|
@@ -407,9 +492,294 @@ void trilogy_auth_clear_password(trilogy_conn_t *conn)
|
|
|
407
492
|
}
|
|
408
493
|
}
|
|
409
494
|
|
|
495
|
+
#define CACHING_SHA2_REQUEST_PUBLIC_KEY 2
|
|
496
|
+
#define CACHING_SHA2_SCRAMBLE_LEN 20
|
|
410
497
|
#define FAST_AUTH_OK 3
|
|
411
498
|
#define FAST_AUTH_FAIL 4
|
|
412
499
|
|
|
500
|
+
static int read_auth_result(trilogy_conn_t *conn)
|
|
501
|
+
{
|
|
502
|
+
int rc = read_packet_blocking(conn);
|
|
503
|
+
|
|
504
|
+
if (rc < 0) {
|
|
505
|
+
return rc;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
trilogy_auth_clear_password(conn);
|
|
509
|
+
return handle_generic_response(conn);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
static int send_cleartext_password(trilogy_conn_t *conn)
|
|
513
|
+
{
|
|
514
|
+
trilogy_builder_t builder;
|
|
515
|
+
|
|
516
|
+
int rc = begin_command_phase(&builder, conn, conn->packet_parser.sequence_number);
|
|
517
|
+
|
|
518
|
+
if (rc < 0) {
|
|
519
|
+
return rc;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
if (conn->socket->opts.password_len == 0) {
|
|
523
|
+
rc = trilogy_builder_write_uint8(&builder, 0);
|
|
524
|
+
|
|
525
|
+
if (rc < 0) {
|
|
526
|
+
return rc;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
trilogy_builder_finalize(&builder);
|
|
530
|
+
return flush_current_packet(conn);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
rc = trilogy_build_auth_clear_password(&builder, conn->socket->opts.password, conn->socket->opts.password_len);
|
|
534
|
+
|
|
535
|
+
if (rc < 0) {
|
|
536
|
+
return rc;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
return flush_current_packet(conn);
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
static int send_auth_buffer(trilogy_conn_t *conn, const void *buff, size_t buff_len)
|
|
543
|
+
{
|
|
544
|
+
trilogy_builder_t builder;
|
|
545
|
+
int rc = begin_command_phase(&builder, conn, conn->packet_parser.sequence_number);
|
|
546
|
+
|
|
547
|
+
if (rc < 0) {
|
|
548
|
+
return rc;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
rc = trilogy_builder_write_buffer(&builder, buff, buff_len);
|
|
552
|
+
if (rc < 0) {
|
|
553
|
+
return rc;
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
trilogy_builder_finalize(&builder);
|
|
557
|
+
|
|
558
|
+
return flush_current_packet(conn);
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
static int send_public_key_request(trilogy_conn_t *conn)
|
|
562
|
+
{
|
|
563
|
+
uint8_t request = CACHING_SHA2_REQUEST_PUBLIC_KEY;
|
|
564
|
+
|
|
565
|
+
return send_auth_buffer(conn, &request, sizeof(request));
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
static int encrypt_password_with_public_key(const uint8_t *scramble, size_t scramble_len, trilogy_conn_t *conn,
|
|
569
|
+
const uint8_t *key_data, size_t key_data_len, uint8_t **encrypted_out,
|
|
570
|
+
size_t *encrypted_len)
|
|
571
|
+
{
|
|
572
|
+
int rc = TRILOGY_OK;
|
|
573
|
+
uint8_t *ciphertext = NULL;
|
|
574
|
+
size_t ciphertext_len = 0;
|
|
575
|
+
|
|
576
|
+
if (key_data_len == 0 || key_data_len > INT_MAX) {
|
|
577
|
+
return TRILOGY_AUTH_PLUGIN_ERROR;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
size_t password_len = conn->socket->opts.password_len;
|
|
581
|
+
if (password_len == SIZE_MAX) {
|
|
582
|
+
return TRILOGY_MEM_ERROR;
|
|
583
|
+
}
|
|
584
|
+
size_t plaintext_len = password_len + 1;
|
|
585
|
+
uint8_t *plaintext = xmalloc(plaintext_len);
|
|
586
|
+
|
|
587
|
+
if (plaintext == NULL) {
|
|
588
|
+
return TRILOGY_MEM_ERROR;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
if (password_len > 0) {
|
|
592
|
+
memcpy(plaintext, conn->socket->opts.password, password_len);
|
|
593
|
+
}
|
|
594
|
+
plaintext[plaintext_len - 1] = '\0';
|
|
595
|
+
|
|
596
|
+
if (scramble_len > 0) {
|
|
597
|
+
for (size_t i = 0; i < plaintext_len; i++) {
|
|
598
|
+
plaintext[i] ^= scramble[i % scramble_len];
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
BIO *bio = BIO_new_mem_buf((void *)key_data, (int)key_data_len);
|
|
603
|
+
if (bio == NULL) {
|
|
604
|
+
xfree(plaintext);
|
|
605
|
+
return TRILOGY_OPENSSL_ERR;
|
|
606
|
+
}
|
|
607
|
+
|
|
608
|
+
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
|
609
|
+
EVP_PKEY *public_key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
|
|
610
|
+
#else
|
|
611
|
+
RSA *public_key = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL);
|
|
612
|
+
#endif
|
|
613
|
+
|
|
614
|
+
BIO_free(bio);
|
|
615
|
+
|
|
616
|
+
if (public_key == NULL) {
|
|
617
|
+
ERR_clear_error();
|
|
618
|
+
memset(plaintext, 0, plaintext_len);
|
|
619
|
+
xfree(plaintext);
|
|
620
|
+
return TRILOGY_AUTH_PLUGIN_ERROR;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
|
624
|
+
int key_size = EVP_PKEY_get_size(public_key);
|
|
625
|
+
if (key_size <= 0) {
|
|
626
|
+
EVP_PKEY_free(public_key);
|
|
627
|
+
memset(plaintext, 0, plaintext_len);
|
|
628
|
+
xfree(plaintext);
|
|
629
|
+
return TRILOGY_AUTH_PLUGIN_ERROR;
|
|
630
|
+
}
|
|
631
|
+
ciphertext_len = (size_t)key_size;
|
|
632
|
+
#else
|
|
633
|
+
ciphertext_len = (size_t)RSA_size(public_key);
|
|
634
|
+
#endif
|
|
635
|
+
|
|
636
|
+
/*
|
|
637
|
+
When using RSA_PKCS1_OAEP_PADDING the password length must be less
|
|
638
|
+
than RSA_size(rsa) - 41.
|
|
639
|
+
*/
|
|
640
|
+
if (ciphertext_len == 0 || plaintext_len + 41 >= ciphertext_len) {
|
|
641
|
+
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
|
642
|
+
EVP_PKEY_free(public_key);
|
|
643
|
+
#else
|
|
644
|
+
RSA_free(public_key);
|
|
645
|
+
#endif
|
|
646
|
+
memset(plaintext, 0, plaintext_len);
|
|
647
|
+
xfree(plaintext);
|
|
648
|
+
return TRILOGY_AUTH_PLUGIN_ERROR;
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
ciphertext = xmalloc(ciphertext_len);
|
|
652
|
+
|
|
653
|
+
if (ciphertext == NULL) {
|
|
654
|
+
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
|
655
|
+
EVP_PKEY_free(public_key);
|
|
656
|
+
#else
|
|
657
|
+
RSA_free(public_key);
|
|
658
|
+
#endif
|
|
659
|
+
memset(plaintext, 0, plaintext_len);
|
|
660
|
+
xfree(plaintext);
|
|
661
|
+
return TRILOGY_MEM_ERROR;
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
|
665
|
+
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(public_key, NULL);
|
|
666
|
+
if (ctx == NULL || EVP_PKEY_encrypt_init(ctx) <= 0 ||
|
|
667
|
+
EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0) {
|
|
668
|
+
rc = TRILOGY_OPENSSL_ERR;
|
|
669
|
+
} else {
|
|
670
|
+
size_t out_len = ciphertext_len;
|
|
671
|
+
|
|
672
|
+
if (EVP_PKEY_encrypt(ctx, ciphertext, &out_len, plaintext, plaintext_len) <= 0) {
|
|
673
|
+
rc = TRILOGY_OPENSSL_ERR;
|
|
674
|
+
} else {
|
|
675
|
+
*encrypted_len = out_len;
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
if (ctx) {
|
|
680
|
+
EVP_PKEY_CTX_free(ctx);
|
|
681
|
+
}
|
|
682
|
+
EVP_PKEY_free(public_key);
|
|
683
|
+
#else
|
|
684
|
+
int out_len = RSA_public_encrypt((int)plaintext_len, plaintext, ciphertext, public_key, RSA_PKCS1_OAEP_PADDING);
|
|
685
|
+
RSA_free(public_key);
|
|
686
|
+
|
|
687
|
+
if (out_len < 0) {
|
|
688
|
+
rc = TRILOGY_OPENSSL_ERR;
|
|
689
|
+
} else {
|
|
690
|
+
*encrypted_len = (size_t)out_len;
|
|
691
|
+
}
|
|
692
|
+
#endif
|
|
693
|
+
|
|
694
|
+
memset(plaintext, 0, plaintext_len);
|
|
695
|
+
xfree(plaintext);
|
|
696
|
+
|
|
697
|
+
if (rc == TRILOGY_OK) {
|
|
698
|
+
*encrypted_out = ciphertext;
|
|
699
|
+
} else {
|
|
700
|
+
memset(ciphertext, 0, ciphertext_len);
|
|
701
|
+
xfree(ciphertext);
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
return rc;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
static int handle_fast_auth_fail(trilogy_conn_t *conn, trilogy_handshake_t *handshake, const uint8_t *auth_data,
|
|
708
|
+
size_t auth_data_len)
|
|
709
|
+
{
|
|
710
|
+
int rc;
|
|
711
|
+
bool use_ssl = (conn->socket->opts.flags & TRILOGY_CAPABILITIES_SSL) != 0;
|
|
712
|
+
bool has_unix_socket = (conn->socket->opts.path != NULL);
|
|
713
|
+
|
|
714
|
+
// No password to send, so we can safely respond even without TLS.
|
|
715
|
+
if (conn->socket->opts.password_len == 0) {
|
|
716
|
+
rc = send_cleartext_password(conn);
|
|
717
|
+
if (rc < 0) {
|
|
718
|
+
return rc;
|
|
719
|
+
}
|
|
720
|
+
|
|
721
|
+
return read_auth_result(conn);
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
if (use_ssl || has_unix_socket) {
|
|
725
|
+
rc = send_cleartext_password(conn);
|
|
726
|
+
if (rc < 0) {
|
|
727
|
+
return rc;
|
|
728
|
+
}
|
|
729
|
+
|
|
730
|
+
return read_auth_result(conn);
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
const uint8_t *public_key_data = NULL;
|
|
734
|
+
size_t public_key_len = 0;
|
|
735
|
+
|
|
736
|
+
if (auth_data_len > 1) {
|
|
737
|
+
public_key_data = auth_data + 1;
|
|
738
|
+
public_key_len = auth_data_len - 1;
|
|
739
|
+
} else {
|
|
740
|
+
rc = send_public_key_request(conn);
|
|
741
|
+
if (rc < 0) {
|
|
742
|
+
return rc;
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
rc = read_packet_blocking(conn);
|
|
746
|
+
if (rc < 0) {
|
|
747
|
+
return rc;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
if (current_packet_type(conn) == TRILOGY_PACKET_ERR) {
|
|
751
|
+
return read_err_packet(conn);
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
if (current_packet_type(conn) != TRILOGY_PACKET_AUTH_MORE_DATA || conn->packet_buffer.len < 2) {
|
|
755
|
+
return TRILOGY_PROTOCOL_VIOLATION;
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
public_key_data = conn->packet_buffer.buff + 1;
|
|
759
|
+
public_key_len = conn->packet_buffer.len - 1;
|
|
760
|
+
}
|
|
761
|
+
|
|
762
|
+
uint8_t *encrypted = NULL;
|
|
763
|
+
size_t encrypted_len = 0;
|
|
764
|
+
|
|
765
|
+
rc = encrypt_password_with_public_key((const uint8_t *)handshake->scramble, CACHING_SHA2_SCRAMBLE_LEN, conn,
|
|
766
|
+
public_key_data, public_key_len, &encrypted, &encrypted_len);
|
|
767
|
+
|
|
768
|
+
if (rc < 0) {
|
|
769
|
+
return rc;
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
rc = send_auth_buffer(conn, encrypted, encrypted_len);
|
|
773
|
+
memset(encrypted, 0, encrypted_len);
|
|
774
|
+
xfree(encrypted);
|
|
775
|
+
|
|
776
|
+
if (rc < 0) {
|
|
777
|
+
return rc;
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
return read_auth_result(conn);
|
|
781
|
+
}
|
|
782
|
+
|
|
413
783
|
int trilogy_auth_recv(trilogy_conn_t *conn, trilogy_handshake_t *handshake)
|
|
414
784
|
{
|
|
415
785
|
int rc = read_packet(conn);
|
|
@@ -420,67 +790,24 @@ int trilogy_auth_recv(trilogy_conn_t *conn, trilogy_handshake_t *handshake)
|
|
|
420
790
|
|
|
421
791
|
switch (current_packet_type(conn)) {
|
|
422
792
|
case TRILOGY_PACKET_AUTH_MORE_DATA: {
|
|
423
|
-
|
|
424
|
-
|
|
793
|
+
const uint8_t *auth_data = conn->packet_buffer.buff + 1;
|
|
794
|
+
size_t auth_data_len = conn->packet_buffer.len - 1;
|
|
425
795
|
|
|
426
|
-
if (
|
|
427
|
-
return
|
|
796
|
+
if (auth_data_len < 1) {
|
|
797
|
+
return TRILOGY_PROTOCOL_VIOLATION;
|
|
428
798
|
}
|
|
429
799
|
|
|
430
|
-
uint8_t byte =
|
|
800
|
+
uint8_t byte = auth_data[0];
|
|
431
801
|
switch (byte) {
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
case FAST_AUTH_FAIL:
|
|
435
|
-
{
|
|
436
|
-
trilogy_builder_t builder;
|
|
437
|
-
int err = begin_command_phase(&builder, conn, conn->packet_parser.sequence_number);
|
|
438
|
-
|
|
439
|
-
if (err < 0) {
|
|
440
|
-
return err;
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
err = trilogy_build_auth_clear_password(&builder, conn->socket->opts.password, conn->socket->opts.password_len);
|
|
444
|
-
|
|
445
|
-
if (err < 0) {
|
|
446
|
-
return err;
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
int rc = begin_write(conn);
|
|
450
|
-
|
|
451
|
-
while (rc == TRILOGY_AGAIN) {
|
|
452
|
-
rc = trilogy_sock_wait_write(conn->socket);
|
|
453
|
-
if (rc != TRILOGY_OK) {
|
|
454
|
-
return rc;
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
rc = trilogy_flush_writes(conn);
|
|
458
|
-
}
|
|
459
|
-
if (rc != TRILOGY_OK) {
|
|
460
|
-
return rc;
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
break;
|
|
464
|
-
}
|
|
465
|
-
default:
|
|
466
|
-
return TRILOGY_UNEXPECTED_PACKET;
|
|
467
|
-
}
|
|
468
|
-
while (1) {
|
|
469
|
-
rc = read_packet(conn);
|
|
802
|
+
case FAST_AUTH_OK:
|
|
803
|
+
return read_auth_result(conn);
|
|
470
804
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
}
|
|
474
|
-
else if (rc == TRILOGY_AGAIN) {
|
|
475
|
-
rc = trilogy_sock_wait_read(conn->socket);
|
|
476
|
-
}
|
|
805
|
+
case FAST_AUTH_FAIL:
|
|
806
|
+
return handle_fast_auth_fail(conn, handshake, auth_data, auth_data_len);
|
|
477
807
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
}
|
|
808
|
+
default:
|
|
809
|
+
return TRILOGY_UNEXPECTED_PACKET;
|
|
481
810
|
}
|
|
482
|
-
trilogy_auth_clear_password(conn);
|
|
483
|
-
return handle_generic_response(conn);
|
|
484
811
|
}
|
|
485
812
|
|
|
486
813
|
case TRILOGY_PACKET_EOF:
|
|
@@ -535,7 +862,8 @@ int trilogy_set_option_send(trilogy_conn_t *conn, const uint16_t option)
|
|
|
535
862
|
return begin_write(conn);
|
|
536
863
|
}
|
|
537
864
|
|
|
538
|
-
int trilogy_set_option_recv(trilogy_conn_t *conn)
|
|
865
|
+
int trilogy_set_option_recv(trilogy_conn_t *conn)
|
|
866
|
+
{
|
|
539
867
|
int rc = read_packet(conn);
|
|
540
868
|
|
|
541
869
|
if (rc < 0) {
|
|
@@ -555,7 +883,6 @@ int trilogy_set_option_recv(trilogy_conn_t *conn) {
|
|
|
555
883
|
}
|
|
556
884
|
}
|
|
557
885
|
|
|
558
|
-
|
|
559
886
|
int trilogy_ping_send(trilogy_conn_t *conn)
|
|
560
887
|
{
|
|
561
888
|
trilogy_builder_t builder;
|
|
@@ -646,15 +973,7 @@ static int read_eof(trilogy_conn_t *conn)
|
|
|
646
973
|
return rc;
|
|
647
974
|
}
|
|
648
975
|
|
|
649
|
-
|
|
650
|
-
return read_ok_packet(conn);
|
|
651
|
-
} else {
|
|
652
|
-
if ((rc = read_eof_packet(conn)) != TRILOGY_EOF) {
|
|
653
|
-
return rc;
|
|
654
|
-
}
|
|
655
|
-
|
|
656
|
-
return TRILOGY_OK;
|
|
657
|
-
}
|
|
976
|
+
return read_eof_packet(conn);
|
|
658
977
|
}
|
|
659
978
|
|
|
660
979
|
int trilogy_read_row(trilogy_conn_t *conn, trilogy_value_t *values_out)
|
|
@@ -679,14 +998,12 @@ int trilogy_read_row(trilogy_conn_t *conn, trilogy_value_t *values_out)
|
|
|
679
998
|
return rc;
|
|
680
999
|
}
|
|
681
1000
|
|
|
682
|
-
if (
|
|
683
|
-
if ((rc =
|
|
1001
|
+
if (is_eof_packet(conn)) {
|
|
1002
|
+
if ((rc = read_eof_packet(conn)) != TRILOGY_OK) {
|
|
684
1003
|
return rc;
|
|
685
1004
|
}
|
|
686
1005
|
|
|
687
1006
|
return TRILOGY_EOF;
|
|
688
|
-
} else if (current_packet_type(conn) == TRILOGY_PACKET_EOF && conn->packet_buffer.len < 9) {
|
|
689
|
-
return read_eof_packet(conn);
|
|
690
1007
|
} else if (current_packet_type(conn) == TRILOGY_PACKET_ERR) {
|
|
691
1008
|
return read_err_packet(conn);
|
|
692
1009
|
} else {
|
|
@@ -716,13 +1033,14 @@ int trilogy_drain_results(trilogy_conn_t *conn)
|
|
|
716
1033
|
return rc;
|
|
717
1034
|
}
|
|
718
1035
|
|
|
719
|
-
if (
|
|
1036
|
+
if (is_eof_packet(conn)) {
|
|
1037
|
+
read_eof_packet(conn);
|
|
720
1038
|
return TRILOGY_OK;
|
|
721
1039
|
}
|
|
722
1040
|
}
|
|
723
1041
|
}
|
|
724
1042
|
|
|
725
|
-
static uint8_t escape_lookup_table[256] = {
|
|
1043
|
+
static const uint8_t escape_lookup_table[256] = {
|
|
726
1044
|
['"'] = '"', ['\0'] = '0', ['\''] = '\'', ['\\'] = '\\', ['\n'] = 'n', ['\r'] = 'r', [26] = 'Z',
|
|
727
1045
|
};
|
|
728
1046
|
|
|
@@ -735,28 +1053,40 @@ int trilogy_escape(trilogy_conn_t *conn, const char *str, size_t len, const char
|
|
|
735
1053
|
|
|
736
1054
|
b->len = 0;
|
|
737
1055
|
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
1056
|
+
// Escaped string will be at least as large as the source string,
|
|
1057
|
+
// so might as well pre-expand the buffer.
|
|
1058
|
+
CHECKED(trilogy_buffer_expand(b, len));
|
|
741
1059
|
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
1060
|
+
const uint8_t *cursor = (const uint8_t *)str;
|
|
1061
|
+
const uint8_t *end = cursor + len;
|
|
1062
|
+
|
|
1063
|
+
if (conn->server_status & TRILOGY_SERVER_STATUS_NO_BACKSLASH_ESCAPES) {
|
|
1064
|
+
while (cursor < end) {
|
|
1065
|
+
uint8_t *next_escape = memchr(cursor, '\'', (size_t)(end - cursor));
|
|
1066
|
+
if (next_escape) {
|
|
1067
|
+
CHECKED(trilogy_buffer_write(b, cursor, (size_t)(next_escape - cursor)));
|
|
1068
|
+
CHECKED(trilogy_buffer_write(b, (uint8_t *)"\'\'", 2));
|
|
1069
|
+
cursor = next_escape + 1;
|
|
745
1070
|
} else {
|
|
746
|
-
CHECKED(
|
|
1071
|
+
CHECKED(trilogy_buffer_write(b, cursor, (size_t)(end - cursor)));
|
|
1072
|
+
break;
|
|
747
1073
|
}
|
|
748
1074
|
}
|
|
749
1075
|
} else {
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
1076
|
+
while (cursor < end) {
|
|
1077
|
+
uint8_t escaped = 0;
|
|
1078
|
+
const uint8_t *start = cursor;
|
|
1079
|
+
while (cursor < end && !(escaped = escape_lookup_table[*cursor])) {
|
|
1080
|
+
cursor++;
|
|
1081
|
+
}
|
|
754
1082
|
|
|
1083
|
+
CHECKED(trilogy_buffer_write(b, start, (size_t)(cursor - start)));
|
|
755
1084
|
if (escaped) {
|
|
756
1085
|
CHECKED(trilogy_buffer_putc(b, '\\'));
|
|
757
1086
|
CHECKED(trilogy_buffer_putc(b, escaped));
|
|
1087
|
+
cursor++;
|
|
758
1088
|
} else {
|
|
759
|
-
|
|
1089
|
+
break;
|
|
760
1090
|
}
|
|
761
1091
|
}
|
|
762
1092
|
}
|
|
@@ -940,20 +1270,18 @@ int trilogy_stmt_bind_data_send(trilogy_conn_t *conn, trilogy_stmt_t *stmt, uint
|
|
|
940
1270
|
int trilogy_stmt_read_row(trilogy_conn_t *conn, trilogy_stmt_t *stmt, trilogy_column_packet_t *columns,
|
|
941
1271
|
trilogy_binary_value_t *values_out)
|
|
942
1272
|
{
|
|
943
|
-
int
|
|
1273
|
+
int rc = read_packet(conn);
|
|
944
1274
|
|
|
945
|
-
if (
|
|
946
|
-
return
|
|
1275
|
+
if (rc < 0) {
|
|
1276
|
+
return rc;
|
|
947
1277
|
}
|
|
948
1278
|
|
|
949
|
-
if (
|
|
950
|
-
if ((
|
|
951
|
-
return
|
|
1279
|
+
if (is_eof_packet(conn)) {
|
|
1280
|
+
if ((rc = read_eof_packet(conn)) != TRILOGY_OK) {
|
|
1281
|
+
return rc;
|
|
952
1282
|
}
|
|
953
1283
|
|
|
954
1284
|
return TRILOGY_EOF;
|
|
955
|
-
} else if (current_packet_type(conn) == TRILOGY_PACKET_EOF && conn->packet_buffer.len < 9) {
|
|
956
|
-
return read_eof_packet(conn);
|
|
957
1285
|
} else if (current_packet_type(conn) == TRILOGY_PACKET_ERR) {
|
|
958
1286
|
return read_err_packet(conn);
|
|
959
1287
|
} else {
|
|
@@ -978,9 +1306,7 @@ int trilogy_stmt_reset_send(trilogy_conn_t *conn, trilogy_stmt_t *stmt)
|
|
|
978
1306
|
return begin_write(conn);
|
|
979
1307
|
}
|
|
980
1308
|
|
|
981
|
-
int trilogy_stmt_reset_recv(trilogy_conn_t *conn) {
|
|
982
|
-
return read_generic_response(conn);
|
|
983
|
-
}
|
|
1309
|
+
int trilogy_stmt_reset_recv(trilogy_conn_t *conn) { return read_generic_response(conn); }
|
|
984
1310
|
|
|
985
1311
|
int trilogy_stmt_close_send(trilogy_conn_t *conn, trilogy_stmt_t *stmt)
|
|
986
1312
|
{
|
|
@@ -74,7 +74,7 @@ size_t trilogy_packet_parser_execute(trilogy_packet_parser_t *parser, const uint
|
|
|
74
74
|
break;
|
|
75
75
|
}
|
|
76
76
|
case S_SEQ: {
|
|
77
|
-
if (cur_byte != parser->sequence_number) {
|
|
77
|
+
if (cur_byte != parser->sequence_number && cur_byte > 0) {
|
|
78
78
|
*error = TRILOGY_INVALID_SEQUENCE_ID;
|
|
79
79
|
return i;
|
|
80
80
|
}
|