trilogy 2.9.0 → 2.11.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/README.md +1 -1
- data/Rakefile +16 -1
- data/ext/trilogy-ruby/cext.c +266 -49
- data/ext/trilogy-ruby/extconf.rb +5 -3
- 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/src/buffer.c +22 -3
- data/ext/trilogy-ruby/src/client.c +407 -97
- data/ext/trilogy-ruby/src/packet_parser.c +1 -1
- data/ext/trilogy-ruby/src/socket.c +6 -0
- data/lib/trilogy/encoding.rb +2 -0
- data/lib/trilogy/error.rb +7 -0
- data/lib/trilogy/result.rb +2 -0
- data/lib/trilogy/version.rb +1 -1
- data/lib/trilogy.rb +76 -1
- data/trilogy.gemspec +3 -2
- metadata +10 -28
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#include <stdint.h>
|
|
2
2
|
#include <stdlib.h>
|
|
3
|
+
#include <string.h>
|
|
3
4
|
|
|
4
5
|
#include "trilogy/buffer.h"
|
|
5
6
|
#include "trilogy/error.h"
|
|
@@ -23,6 +24,9 @@ int trilogy_buffer_expand(trilogy_buffer_t *buffer, size_t needed)
|
|
|
23
24
|
{
|
|
24
25
|
// expand buffer if necessary
|
|
25
26
|
if (buffer->len + needed > buffer->cap) {
|
|
27
|
+
if (buffer->buff == NULL)
|
|
28
|
+
return TRILOGY_MEM_ERROR;
|
|
29
|
+
|
|
26
30
|
size_t new_cap = buffer->cap;
|
|
27
31
|
|
|
28
32
|
while (buffer->len + needed > new_cap) {
|
|
@@ -57,9 +61,24 @@ int trilogy_buffer_putc(trilogy_buffer_t *buffer, uint8_t c)
|
|
|
57
61
|
return TRILOGY_OK;
|
|
58
62
|
}
|
|
59
63
|
|
|
64
|
+
int trilogy_buffer_write(trilogy_buffer_t *buffer, const uint8_t *ptr, size_t len)
|
|
65
|
+
{
|
|
66
|
+
int rc = trilogy_buffer_expand(buffer, len);
|
|
67
|
+
if (rc) {
|
|
68
|
+
return rc;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
memcpy(buffer->buff + buffer->len, ptr, len);
|
|
72
|
+
buffer->len += len;
|
|
73
|
+
|
|
74
|
+
return TRILOGY_OK;
|
|
75
|
+
}
|
|
76
|
+
|
|
60
77
|
void trilogy_buffer_free(trilogy_buffer_t *buffer)
|
|
61
78
|
{
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
79
|
+
if (buffer->buff) {
|
|
80
|
+
free(buffer->buff);
|
|
81
|
+
buffer->buff = NULL;
|
|
82
|
+
buffer->len = buffer->cap = 0;
|
|
83
|
+
}
|
|
65
84
|
}
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
#include <fcntl.h>
|
|
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>
|
|
2
9
|
|
|
3
10
|
#include "trilogy/client.h"
|
|
4
11
|
#include "trilogy/error.h"
|
|
@@ -117,10 +124,40 @@ static int begin_write(trilogy_conn_t *conn)
|
|
|
117
124
|
return trilogy_flush_writes(conn);
|
|
118
125
|
}
|
|
119
126
|
|
|
120
|
-
int
|
|
127
|
+
static int flush_current_packet(trilogy_conn_t *conn)
|
|
128
|
+
{
|
|
129
|
+
int rc = begin_write(conn);
|
|
130
|
+
|
|
131
|
+
while (rc == TRILOGY_AGAIN) {
|
|
132
|
+
rc = trilogy_sock_wait_write(conn->socket);
|
|
133
|
+
|
|
134
|
+
if (rc != TRILOGY_OK) {
|
|
135
|
+
return rc;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
rc = trilogy_flush_writes(conn);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return rc;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
static int read_packet_blocking(trilogy_conn_t *conn)
|
|
121
145
|
{
|
|
122
146
|
int rc;
|
|
123
147
|
|
|
148
|
+
while ((rc = read_packet(conn)) == TRILOGY_AGAIN) {
|
|
149
|
+
rc = trilogy_sock_wait_read(conn->socket);
|
|
150
|
+
|
|
151
|
+
if (rc != TRILOGY_OK) {
|
|
152
|
+
return rc;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return rc;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
int trilogy_init_no_buffer(trilogy_conn_t *conn)
|
|
160
|
+
{
|
|
124
161
|
conn->affected_rows = 0;
|
|
125
162
|
conn->last_insert_id = 0;
|
|
126
163
|
conn->warning_count = 0;
|
|
@@ -142,8 +179,14 @@ int trilogy_init(trilogy_conn_t *conn)
|
|
|
142
179
|
trilogy_packet_parser_init(&conn->packet_parser, &packet_parser_callbacks);
|
|
143
180
|
conn->packet_parser.user_data = &conn->packet_buffer;
|
|
144
181
|
|
|
145
|
-
|
|
182
|
+
return TRILOGY_OK;
|
|
183
|
+
}
|
|
146
184
|
|
|
185
|
+
int trilogy_init(trilogy_conn_t *conn)
|
|
186
|
+
{
|
|
187
|
+
int rc;
|
|
188
|
+
trilogy_init_no_buffer(conn);
|
|
189
|
+
CHECKED(trilogy_buffer_init(&conn->packet_buffer, TRILOGY_DEFAULT_BUF_SIZE));
|
|
147
190
|
return TRILOGY_OK;
|
|
148
191
|
}
|
|
149
192
|
|
|
@@ -217,7 +260,7 @@ static int read_err_packet(trilogy_conn_t *conn)
|
|
|
217
260
|
return TRILOGY_ERR;
|
|
218
261
|
}
|
|
219
262
|
|
|
220
|
-
static int
|
|
263
|
+
static int read_deprecated_eof_packet(trilogy_conn_t *conn)
|
|
221
264
|
{
|
|
222
265
|
trilogy_eof_packet_t eof_packet;
|
|
223
266
|
|
|
@@ -236,6 +279,21 @@ static int read_eof_packet(trilogy_conn_t *conn)
|
|
|
236
279
|
return TRILOGY_EOF;
|
|
237
280
|
}
|
|
238
281
|
|
|
282
|
+
static int read_eof_packet(trilogy_conn_t *conn)
|
|
283
|
+
{
|
|
284
|
+
int rc;
|
|
285
|
+
|
|
286
|
+
if (conn->capabilities & TRILOGY_CAPABILITIES_DEPRECATE_EOF) {
|
|
287
|
+
return read_ok_packet(conn);
|
|
288
|
+
} else {
|
|
289
|
+
if ((rc = read_deprecated_eof_packet(conn)) != TRILOGY_EOF) {
|
|
290
|
+
return rc;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return TRILOGY_OK;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
239
297
|
static int read_auth_switch_packet(trilogy_conn_t *conn, trilogy_handshake_t *handshake)
|
|
240
298
|
{
|
|
241
299
|
trilogy_auth_switch_request_packet_t auth_switch_packet;
|
|
@@ -259,7 +317,8 @@ static int read_auth_switch_packet(trilogy_conn_t *conn, trilogy_handshake_t *ha
|
|
|
259
317
|
return TRILOGY_AUTH_SWITCH;
|
|
260
318
|
}
|
|
261
319
|
|
|
262
|
-
static int handle_generic_response(trilogy_conn_t *conn)
|
|
320
|
+
static int handle_generic_response(trilogy_conn_t *conn)
|
|
321
|
+
{
|
|
263
322
|
switch (current_packet_type(conn)) {
|
|
264
323
|
case TRILOGY_PACKET_OK:
|
|
265
324
|
return read_ok_packet(conn);
|
|
@@ -310,6 +369,16 @@ int trilogy_connect_send_socket(trilogy_conn_t *conn, trilogy_sock_t *sock)
|
|
|
310
369
|
return TRILOGY_OK;
|
|
311
370
|
}
|
|
312
371
|
|
|
372
|
+
int trilogy_connect_set_fd(trilogy_conn_t *conn, trilogy_sock_t *sock, int fd)
|
|
373
|
+
{
|
|
374
|
+
trilogy_sock_set_fd(sock, fd);
|
|
375
|
+
|
|
376
|
+
conn->socket = sock;
|
|
377
|
+
conn->packet_parser.sequence_number = 0;
|
|
378
|
+
|
|
379
|
+
return TRILOGY_OK;
|
|
380
|
+
}
|
|
381
|
+
|
|
313
382
|
int trilogy_connect_recv(trilogy_conn_t *conn, trilogy_handshake_t *handshake_out)
|
|
314
383
|
{
|
|
315
384
|
int rc = read_packet(conn);
|
|
@@ -407,9 +476,294 @@ void trilogy_auth_clear_password(trilogy_conn_t *conn)
|
|
|
407
476
|
}
|
|
408
477
|
}
|
|
409
478
|
|
|
479
|
+
#define CACHING_SHA2_REQUEST_PUBLIC_KEY 2
|
|
480
|
+
#define CACHING_SHA2_SCRAMBLE_LEN 20
|
|
410
481
|
#define FAST_AUTH_OK 3
|
|
411
482
|
#define FAST_AUTH_FAIL 4
|
|
412
483
|
|
|
484
|
+
static int read_auth_result(trilogy_conn_t *conn)
|
|
485
|
+
{
|
|
486
|
+
int rc = read_packet_blocking(conn);
|
|
487
|
+
|
|
488
|
+
if (rc < 0) {
|
|
489
|
+
return rc;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
trilogy_auth_clear_password(conn);
|
|
493
|
+
return handle_generic_response(conn);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
static int send_cleartext_password(trilogy_conn_t *conn)
|
|
497
|
+
{
|
|
498
|
+
trilogy_builder_t builder;
|
|
499
|
+
|
|
500
|
+
int rc = begin_command_phase(&builder, conn, conn->packet_parser.sequence_number);
|
|
501
|
+
|
|
502
|
+
if (rc < 0) {
|
|
503
|
+
return rc;
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
if (conn->socket->opts.password_len == 0) {
|
|
507
|
+
rc = trilogy_builder_write_uint8(&builder, 0);
|
|
508
|
+
|
|
509
|
+
if (rc < 0) {
|
|
510
|
+
return rc;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
trilogy_builder_finalize(&builder);
|
|
514
|
+
return flush_current_packet(conn);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
rc = trilogy_build_auth_clear_password(&builder, conn->socket->opts.password, conn->socket->opts.password_len);
|
|
518
|
+
|
|
519
|
+
if (rc < 0) {
|
|
520
|
+
return rc;
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
return flush_current_packet(conn);
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
static int send_auth_buffer(trilogy_conn_t *conn, const void *buff, size_t buff_len)
|
|
527
|
+
{
|
|
528
|
+
trilogy_builder_t builder;
|
|
529
|
+
int rc = begin_command_phase(&builder, conn, conn->packet_parser.sequence_number);
|
|
530
|
+
|
|
531
|
+
if (rc < 0) {
|
|
532
|
+
return rc;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
rc = trilogy_builder_write_buffer(&builder, buff, buff_len);
|
|
536
|
+
if (rc < 0) {
|
|
537
|
+
return rc;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
trilogy_builder_finalize(&builder);
|
|
541
|
+
|
|
542
|
+
return flush_current_packet(conn);
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
static int send_public_key_request(trilogy_conn_t *conn)
|
|
546
|
+
{
|
|
547
|
+
uint8_t request = CACHING_SHA2_REQUEST_PUBLIC_KEY;
|
|
548
|
+
|
|
549
|
+
return send_auth_buffer(conn, &request, sizeof(request));
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
static int encrypt_password_with_public_key(const uint8_t *scramble, size_t scramble_len, trilogy_conn_t *conn,
|
|
553
|
+
const uint8_t *key_data, size_t key_data_len, uint8_t **encrypted_out,
|
|
554
|
+
size_t *encrypted_len)
|
|
555
|
+
{
|
|
556
|
+
int rc = TRILOGY_OK;
|
|
557
|
+
uint8_t *ciphertext = NULL;
|
|
558
|
+
size_t ciphertext_len = 0;
|
|
559
|
+
|
|
560
|
+
if (key_data_len == 0 || key_data_len > INT_MAX) {
|
|
561
|
+
return TRILOGY_AUTH_PLUGIN_ERROR;
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
size_t password_len = conn->socket->opts.password_len;
|
|
565
|
+
if (password_len == SIZE_MAX) {
|
|
566
|
+
return TRILOGY_MEM_ERROR;
|
|
567
|
+
}
|
|
568
|
+
size_t plaintext_len = password_len + 1;
|
|
569
|
+
uint8_t *plaintext = malloc(plaintext_len);
|
|
570
|
+
|
|
571
|
+
if (plaintext == NULL) {
|
|
572
|
+
return TRILOGY_MEM_ERROR;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
if (password_len > 0) {
|
|
576
|
+
memcpy(plaintext, conn->socket->opts.password, password_len);
|
|
577
|
+
}
|
|
578
|
+
plaintext[plaintext_len - 1] = '\0';
|
|
579
|
+
|
|
580
|
+
if (scramble_len > 0) {
|
|
581
|
+
for (size_t i = 0; i < plaintext_len; i++) {
|
|
582
|
+
plaintext[i] ^= scramble[i % scramble_len];
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
BIO *bio = BIO_new_mem_buf((void *)key_data, (int)key_data_len);
|
|
587
|
+
if (bio == NULL) {
|
|
588
|
+
free(plaintext);
|
|
589
|
+
return TRILOGY_OPENSSL_ERR;
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
|
593
|
+
EVP_PKEY *public_key = PEM_read_bio_PUBKEY(bio, NULL, NULL, NULL);
|
|
594
|
+
#else
|
|
595
|
+
RSA *public_key = PEM_read_bio_RSA_PUBKEY(bio, NULL, NULL, NULL);
|
|
596
|
+
#endif
|
|
597
|
+
|
|
598
|
+
BIO_free(bio);
|
|
599
|
+
|
|
600
|
+
if (public_key == NULL) {
|
|
601
|
+
ERR_clear_error();
|
|
602
|
+
memset(plaintext, 0, plaintext_len);
|
|
603
|
+
free(plaintext);
|
|
604
|
+
return TRILOGY_AUTH_PLUGIN_ERROR;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
|
608
|
+
int key_size = EVP_PKEY_get_size(public_key);
|
|
609
|
+
if (key_size <= 0) {
|
|
610
|
+
EVP_PKEY_free(public_key);
|
|
611
|
+
memset(plaintext, 0, plaintext_len);
|
|
612
|
+
free(plaintext);
|
|
613
|
+
return TRILOGY_AUTH_PLUGIN_ERROR;
|
|
614
|
+
}
|
|
615
|
+
ciphertext_len = (size_t)key_size;
|
|
616
|
+
#else
|
|
617
|
+
ciphertext_len = (size_t)RSA_size(public_key);
|
|
618
|
+
#endif
|
|
619
|
+
|
|
620
|
+
/*
|
|
621
|
+
When using RSA_PKCS1_OAEP_PADDING the password length must be less
|
|
622
|
+
than RSA_size(rsa) - 41.
|
|
623
|
+
*/
|
|
624
|
+
if (ciphertext_len == 0 || plaintext_len + 41 >= ciphertext_len) {
|
|
625
|
+
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
|
626
|
+
EVP_PKEY_free(public_key);
|
|
627
|
+
#else
|
|
628
|
+
RSA_free(public_key);
|
|
629
|
+
#endif
|
|
630
|
+
memset(plaintext, 0, plaintext_len);
|
|
631
|
+
free(plaintext);
|
|
632
|
+
return TRILOGY_AUTH_PLUGIN_ERROR;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
ciphertext = malloc(ciphertext_len);
|
|
636
|
+
|
|
637
|
+
if (ciphertext == NULL) {
|
|
638
|
+
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
|
639
|
+
EVP_PKEY_free(public_key);
|
|
640
|
+
#else
|
|
641
|
+
RSA_free(public_key);
|
|
642
|
+
#endif
|
|
643
|
+
memset(plaintext, 0, plaintext_len);
|
|
644
|
+
free(plaintext);
|
|
645
|
+
return TRILOGY_MEM_ERROR;
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
#if OPENSSL_VERSION_NUMBER >= 0x30000000L
|
|
649
|
+
EVP_PKEY_CTX *ctx = EVP_PKEY_CTX_new(public_key, NULL);
|
|
650
|
+
if (ctx == NULL || EVP_PKEY_encrypt_init(ctx) <= 0 ||
|
|
651
|
+
EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_OAEP_PADDING) <= 0) {
|
|
652
|
+
rc = TRILOGY_OPENSSL_ERR;
|
|
653
|
+
} else {
|
|
654
|
+
size_t out_len = ciphertext_len;
|
|
655
|
+
|
|
656
|
+
if (EVP_PKEY_encrypt(ctx, ciphertext, &out_len, plaintext, plaintext_len) <= 0) {
|
|
657
|
+
rc = TRILOGY_OPENSSL_ERR;
|
|
658
|
+
} else {
|
|
659
|
+
*encrypted_len = out_len;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
|
|
663
|
+
if (ctx) {
|
|
664
|
+
EVP_PKEY_CTX_free(ctx);
|
|
665
|
+
}
|
|
666
|
+
EVP_PKEY_free(public_key);
|
|
667
|
+
#else
|
|
668
|
+
int out_len = RSA_public_encrypt((int)plaintext_len, plaintext, ciphertext, public_key, RSA_PKCS1_OAEP_PADDING);
|
|
669
|
+
RSA_free(public_key);
|
|
670
|
+
|
|
671
|
+
if (out_len < 0) {
|
|
672
|
+
rc = TRILOGY_OPENSSL_ERR;
|
|
673
|
+
} else {
|
|
674
|
+
*encrypted_len = (size_t)out_len;
|
|
675
|
+
}
|
|
676
|
+
#endif
|
|
677
|
+
|
|
678
|
+
memset(plaintext, 0, plaintext_len);
|
|
679
|
+
free(plaintext);
|
|
680
|
+
|
|
681
|
+
if (rc == TRILOGY_OK) {
|
|
682
|
+
*encrypted_out = ciphertext;
|
|
683
|
+
} else {
|
|
684
|
+
memset(ciphertext, 0, ciphertext_len);
|
|
685
|
+
free(ciphertext);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
return rc;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
static int handle_fast_auth_fail(trilogy_conn_t *conn, trilogy_handshake_t *handshake, const uint8_t *auth_data,
|
|
692
|
+
size_t auth_data_len)
|
|
693
|
+
{
|
|
694
|
+
int rc;
|
|
695
|
+
bool use_ssl = (conn->socket->opts.flags & TRILOGY_CAPABILITIES_SSL) != 0;
|
|
696
|
+
bool has_unix_socket = (conn->socket->opts.path != NULL);
|
|
697
|
+
|
|
698
|
+
// No password to send, so we can safely respond even without TLS.
|
|
699
|
+
if (conn->socket->opts.password_len == 0) {
|
|
700
|
+
rc = send_cleartext_password(conn);
|
|
701
|
+
if (rc < 0) {
|
|
702
|
+
return rc;
|
|
703
|
+
}
|
|
704
|
+
|
|
705
|
+
return read_auth_result(conn);
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
if (use_ssl || has_unix_socket) {
|
|
709
|
+
rc = send_cleartext_password(conn);
|
|
710
|
+
if (rc < 0) {
|
|
711
|
+
return rc;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
return read_auth_result(conn);
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
const uint8_t *public_key_data = NULL;
|
|
718
|
+
size_t public_key_len = 0;
|
|
719
|
+
|
|
720
|
+
if (auth_data_len > 1) {
|
|
721
|
+
public_key_data = auth_data + 1;
|
|
722
|
+
public_key_len = auth_data_len - 1;
|
|
723
|
+
} else {
|
|
724
|
+
rc = send_public_key_request(conn);
|
|
725
|
+
if (rc < 0) {
|
|
726
|
+
return rc;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
rc = read_packet_blocking(conn);
|
|
730
|
+
if (rc < 0) {
|
|
731
|
+
return rc;
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
if (current_packet_type(conn) == TRILOGY_PACKET_ERR) {
|
|
735
|
+
return read_err_packet(conn);
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
if (current_packet_type(conn) != TRILOGY_PACKET_AUTH_MORE_DATA || conn->packet_buffer.len < 2) {
|
|
739
|
+
return TRILOGY_PROTOCOL_VIOLATION;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
public_key_data = conn->packet_buffer.buff + 1;
|
|
743
|
+
public_key_len = conn->packet_buffer.len - 1;
|
|
744
|
+
}
|
|
745
|
+
|
|
746
|
+
uint8_t *encrypted = NULL;
|
|
747
|
+
size_t encrypted_len = 0;
|
|
748
|
+
|
|
749
|
+
rc = encrypt_password_with_public_key((const uint8_t *)handshake->scramble, CACHING_SHA2_SCRAMBLE_LEN, conn,
|
|
750
|
+
public_key_data, public_key_len, &encrypted, &encrypted_len);
|
|
751
|
+
|
|
752
|
+
if (rc < 0) {
|
|
753
|
+
return rc;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
rc = send_auth_buffer(conn, encrypted, encrypted_len);
|
|
757
|
+
memset(encrypted, 0, encrypted_len);
|
|
758
|
+
free(encrypted);
|
|
759
|
+
|
|
760
|
+
if (rc < 0) {
|
|
761
|
+
return rc;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
return read_auth_result(conn);
|
|
765
|
+
}
|
|
766
|
+
|
|
413
767
|
int trilogy_auth_recv(trilogy_conn_t *conn, trilogy_handshake_t *handshake)
|
|
414
768
|
{
|
|
415
769
|
int rc = read_packet(conn);
|
|
@@ -420,67 +774,24 @@ int trilogy_auth_recv(trilogy_conn_t *conn, trilogy_handshake_t *handshake)
|
|
|
420
774
|
|
|
421
775
|
switch (current_packet_type(conn)) {
|
|
422
776
|
case TRILOGY_PACKET_AUTH_MORE_DATA: {
|
|
423
|
-
|
|
424
|
-
|
|
777
|
+
const uint8_t *auth_data = conn->packet_buffer.buff + 1;
|
|
778
|
+
size_t auth_data_len = conn->packet_buffer.len - 1;
|
|
425
779
|
|
|
426
|
-
if (
|
|
427
|
-
return
|
|
780
|
+
if (auth_data_len < 1) {
|
|
781
|
+
return TRILOGY_PROTOCOL_VIOLATION;
|
|
428
782
|
}
|
|
429
783
|
|
|
430
|
-
uint8_t byte =
|
|
784
|
+
uint8_t byte = auth_data[0];
|
|
431
785
|
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);
|
|
786
|
+
case FAST_AUTH_OK:
|
|
787
|
+
return read_auth_result(conn);
|
|
470
788
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
}
|
|
474
|
-
else if (rc == TRILOGY_AGAIN) {
|
|
475
|
-
rc = trilogy_sock_wait_read(conn->socket);
|
|
476
|
-
}
|
|
789
|
+
case FAST_AUTH_FAIL:
|
|
790
|
+
return handle_fast_auth_fail(conn, handshake, auth_data, auth_data_len);
|
|
477
791
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
}
|
|
792
|
+
default:
|
|
793
|
+
return TRILOGY_UNEXPECTED_PACKET;
|
|
481
794
|
}
|
|
482
|
-
trilogy_auth_clear_password(conn);
|
|
483
|
-
return handle_generic_response(conn);
|
|
484
795
|
}
|
|
485
796
|
|
|
486
797
|
case TRILOGY_PACKET_EOF:
|
|
@@ -535,7 +846,8 @@ int trilogy_set_option_send(trilogy_conn_t *conn, const uint16_t option)
|
|
|
535
846
|
return begin_write(conn);
|
|
536
847
|
}
|
|
537
848
|
|
|
538
|
-
int trilogy_set_option_recv(trilogy_conn_t *conn)
|
|
849
|
+
int trilogy_set_option_recv(trilogy_conn_t *conn)
|
|
850
|
+
{
|
|
539
851
|
int rc = read_packet(conn);
|
|
540
852
|
|
|
541
853
|
if (rc < 0) {
|
|
@@ -555,7 +867,6 @@ int trilogy_set_option_recv(trilogy_conn_t *conn) {
|
|
|
555
867
|
}
|
|
556
868
|
}
|
|
557
869
|
|
|
558
|
-
|
|
559
870
|
int trilogy_ping_send(trilogy_conn_t *conn)
|
|
560
871
|
{
|
|
561
872
|
trilogy_builder_t builder;
|
|
@@ -646,15 +957,7 @@ static int read_eof(trilogy_conn_t *conn)
|
|
|
646
957
|
return rc;
|
|
647
958
|
}
|
|
648
959
|
|
|
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
|
-
}
|
|
960
|
+
return read_eof_packet(conn);
|
|
658
961
|
}
|
|
659
962
|
|
|
660
963
|
int trilogy_read_row(trilogy_conn_t *conn, trilogy_value_t *values_out)
|
|
@@ -679,14 +982,12 @@ int trilogy_read_row(trilogy_conn_t *conn, trilogy_value_t *values_out)
|
|
|
679
982
|
return rc;
|
|
680
983
|
}
|
|
681
984
|
|
|
682
|
-
if (conn
|
|
683
|
-
if ((rc =
|
|
985
|
+
if (current_packet_type(conn) == TRILOGY_PACKET_EOF && conn->packet_buffer.len < 9) {
|
|
986
|
+
if ((rc = read_eof_packet(conn)) != TRILOGY_OK) {
|
|
684
987
|
return rc;
|
|
685
988
|
}
|
|
686
989
|
|
|
687
990
|
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
991
|
} else if (current_packet_type(conn) == TRILOGY_PACKET_ERR) {
|
|
691
992
|
return read_err_packet(conn);
|
|
692
993
|
} else {
|
|
@@ -717,12 +1018,13 @@ int trilogy_drain_results(trilogy_conn_t *conn)
|
|
|
717
1018
|
}
|
|
718
1019
|
|
|
719
1020
|
if (current_packet_type(conn) == TRILOGY_PACKET_EOF && conn->packet_buffer.len < 9) {
|
|
1021
|
+
read_eof_packet(conn);
|
|
720
1022
|
return TRILOGY_OK;
|
|
721
1023
|
}
|
|
722
1024
|
}
|
|
723
1025
|
}
|
|
724
1026
|
|
|
725
|
-
static uint8_t escape_lookup_table[256] = {
|
|
1027
|
+
static const uint8_t escape_lookup_table[256] = {
|
|
726
1028
|
['"'] = '"', ['\0'] = '0', ['\''] = '\'', ['\\'] = '\\', ['\n'] = 'n', ['\r'] = 'r', [26] = 'Z',
|
|
727
1029
|
};
|
|
728
1030
|
|
|
@@ -735,28 +1037,40 @@ int trilogy_escape(trilogy_conn_t *conn, const char *str, size_t len, const char
|
|
|
735
1037
|
|
|
736
1038
|
b->len = 0;
|
|
737
1039
|
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
1040
|
+
// Escaped string will be at least as large as the source string,
|
|
1041
|
+
// so might as well pre-expand the buffer.
|
|
1042
|
+
CHECKED(trilogy_buffer_expand(b, len));
|
|
741
1043
|
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
1044
|
+
const uint8_t *cursor = (const uint8_t *)str;
|
|
1045
|
+
const uint8_t *end = cursor + len;
|
|
1046
|
+
|
|
1047
|
+
if (conn->server_status & TRILOGY_SERVER_STATUS_NO_BACKSLASH_ESCAPES) {
|
|
1048
|
+
while (cursor < end) {
|
|
1049
|
+
uint8_t *next_escape = memchr(cursor, '\'', (size_t)(end - cursor));
|
|
1050
|
+
if (next_escape) {
|
|
1051
|
+
CHECKED(trilogy_buffer_write(b, cursor, (size_t)(next_escape - cursor)));
|
|
1052
|
+
CHECKED(trilogy_buffer_write(b, (uint8_t *)"\'\'", 2));
|
|
1053
|
+
cursor = next_escape + 1;
|
|
745
1054
|
} else {
|
|
746
|
-
CHECKED(
|
|
1055
|
+
CHECKED(trilogy_buffer_write(b, cursor, (size_t)(end - cursor)));
|
|
1056
|
+
break;
|
|
747
1057
|
}
|
|
748
1058
|
}
|
|
749
1059
|
} else {
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
1060
|
+
while (cursor < end) {
|
|
1061
|
+
uint8_t escaped = 0;
|
|
1062
|
+
const uint8_t *start = cursor;
|
|
1063
|
+
while (cursor < end && !(escaped = escape_lookup_table[*cursor])) {
|
|
1064
|
+
cursor++;
|
|
1065
|
+
}
|
|
754
1066
|
|
|
1067
|
+
CHECKED(trilogy_buffer_write(b, start, (size_t)(cursor - start)));
|
|
755
1068
|
if (escaped) {
|
|
756
1069
|
CHECKED(trilogy_buffer_putc(b, '\\'));
|
|
757
1070
|
CHECKED(trilogy_buffer_putc(b, escaped));
|
|
1071
|
+
cursor++;
|
|
758
1072
|
} else {
|
|
759
|
-
|
|
1073
|
+
break;
|
|
760
1074
|
}
|
|
761
1075
|
}
|
|
762
1076
|
}
|
|
@@ -940,20 +1254,18 @@ int trilogy_stmt_bind_data_send(trilogy_conn_t *conn, trilogy_stmt_t *stmt, uint
|
|
|
940
1254
|
int trilogy_stmt_read_row(trilogy_conn_t *conn, trilogy_stmt_t *stmt, trilogy_column_packet_t *columns,
|
|
941
1255
|
trilogy_binary_value_t *values_out)
|
|
942
1256
|
{
|
|
943
|
-
int
|
|
1257
|
+
int rc = read_packet(conn);
|
|
944
1258
|
|
|
945
|
-
if (
|
|
946
|
-
return
|
|
1259
|
+
if (rc < 0) {
|
|
1260
|
+
return rc;
|
|
947
1261
|
}
|
|
948
1262
|
|
|
949
|
-
if (conn
|
|
950
|
-
if ((
|
|
951
|
-
return
|
|
1263
|
+
if (current_packet_type(conn) == TRILOGY_PACKET_EOF && conn->packet_buffer.len < 9) {
|
|
1264
|
+
if ((rc = read_eof_packet(conn)) != TRILOGY_OK) {
|
|
1265
|
+
return rc;
|
|
952
1266
|
}
|
|
953
1267
|
|
|
954
1268
|
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
1269
|
} else if (current_packet_type(conn) == TRILOGY_PACKET_ERR) {
|
|
958
1270
|
return read_err_packet(conn);
|
|
959
1271
|
} else {
|
|
@@ -978,9 +1290,7 @@ int trilogy_stmt_reset_send(trilogy_conn_t *conn, trilogy_stmt_t *stmt)
|
|
|
978
1290
|
return begin_write(conn);
|
|
979
1291
|
}
|
|
980
1292
|
|
|
981
|
-
int trilogy_stmt_reset_recv(trilogy_conn_t *conn) {
|
|
982
|
-
return read_generic_response(conn);
|
|
983
|
-
}
|
|
1293
|
+
int trilogy_stmt_reset_recv(trilogy_conn_t *conn) { return read_generic_response(conn); }
|
|
984
1294
|
|
|
985
1295
|
int trilogy_stmt_close_send(trilogy_conn_t *conn, trilogy_stmt_t *stmt)
|
|
986
1296
|
{
|
|
@@ -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
|
}
|