trilogy 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of trilogy might be problematic. Click here for more details.
- checksums.yaml +7 -0
- data/LICENSE +22 -0
- data/README.md +74 -0
- data/Rakefile +18 -0
- data/ext/trilogy-ruby/cast.c +272 -0
- data/ext/trilogy-ruby/cext.c +933 -0
- data/ext/trilogy-ruby/extconf.rb +16 -0
- data/ext/trilogy-ruby/inc/trilogy/blocking.h +163 -0
- data/ext/trilogy-ruby/inc/trilogy/buffer.h +64 -0
- data/ext/trilogy-ruby/inc/trilogy/builder.h +161 -0
- data/ext/trilogy-ruby/inc/trilogy/charset.h +277 -0
- data/ext/trilogy-ruby/inc/trilogy/client.h +546 -0
- data/ext/trilogy-ruby/inc/trilogy/error.h +43 -0
- data/ext/trilogy-ruby/inc/trilogy/packet_parser.h +34 -0
- data/ext/trilogy-ruby/inc/trilogy/protocol.h +756 -0
- data/ext/trilogy-ruby/inc/trilogy/reader.h +212 -0
- data/ext/trilogy-ruby/inc/trilogy/socket.h +111 -0
- data/ext/trilogy-ruby/inc/trilogy/vendor/curl_hostcheck.h +29 -0
- data/ext/trilogy-ruby/inc/trilogy/vendor/openssl_hostname_validation.h +51 -0
- data/ext/trilogy-ruby/inc/trilogy.h +8 -0
- data/ext/trilogy-ruby/src/blocking.c +241 -0
- data/ext/trilogy-ruby/src/buffer.c +60 -0
- data/ext/trilogy-ruby/src/builder.c +198 -0
- data/ext/trilogy-ruby/src/charset.c +212 -0
- data/ext/trilogy-ruby/src/client.c +728 -0
- data/ext/trilogy-ruby/src/error.c +17 -0
- data/ext/trilogy-ruby/src/packet_parser.c +140 -0
- data/ext/trilogy-ruby/src/protocol.c +676 -0
- data/ext/trilogy-ruby/src/reader.c +244 -0
- data/ext/trilogy-ruby/src/socket.c +623 -0
- data/ext/trilogy-ruby/src/vendor/curl_hostcheck.c +206 -0
- data/ext/trilogy-ruby/src/vendor/openssl_hostname_validation.c +175 -0
- data/ext/trilogy-ruby/trilogy-ruby.h +36 -0
- data/lib/trilogy/version.rb +3 -0
- data/lib/trilogy.rb +61 -0
- data/trilogy.gemspec +27 -0
- metadata +106 -0
@@ -0,0 +1,212 @@
|
|
1
|
+
#ifndef TRILOGY_READER_H
|
2
|
+
#define TRILOGY_READER_H
|
3
|
+
|
4
|
+
#include <stdbool.h>
|
5
|
+
#include <stddef.h>
|
6
|
+
#include <stdint.h>
|
7
|
+
|
8
|
+
/* Trilogy Packet Reader API
|
9
|
+
*
|
10
|
+
* The packet reader API is used to parse MySQL-compatible protocol packets.
|
11
|
+
*/
|
12
|
+
|
13
|
+
/* trilogy_reader_t - The reader API's instance type.
|
14
|
+
*/
|
15
|
+
typedef struct {
|
16
|
+
const uint8_t *buff;
|
17
|
+
size_t len;
|
18
|
+
size_t pos;
|
19
|
+
} trilogy_reader_t;
|
20
|
+
|
21
|
+
/* trilogy_reader_init - Initialize a pre-allocated trilogy_reader_t.
|
22
|
+
*
|
23
|
+
* reader - A pointer to a pre-allocated trilogy_reader_t.
|
24
|
+
* buff - A pointer to a buffer containing MySQL-compatible protocol packet data.
|
25
|
+
* len - The length of `buff` in bytes.
|
26
|
+
*
|
27
|
+
* Returns nothing.
|
28
|
+
*/
|
29
|
+
void trilogy_reader_init(trilogy_reader_t *reader, const uint8_t *buff, size_t len);
|
30
|
+
|
31
|
+
#define TRILOGY_READER(buffer, length) ((trilogy_reader_t){.buff = (buffer), .len = (length), .pos = 0});
|
32
|
+
|
33
|
+
/* trilogy_reader_get_uint8 - Parse an unsigned 8-bit integer.
|
34
|
+
*
|
35
|
+
* reader - A pointer to a pre-initialized trilogy_reader_t.
|
36
|
+
* out - Out parameter; A pointer to a uint8_t which will be set to the
|
37
|
+
* value read from the buffer.
|
38
|
+
*
|
39
|
+
* Return values:
|
40
|
+
* TRILOGY_OK - The value was parsed.
|
41
|
+
* TRILOGY_TRUNCATED_PACKET - There isn't enough data left in the buffer.
|
42
|
+
*/
|
43
|
+
int trilogy_reader_get_uint8(trilogy_reader_t *reader, uint8_t *out);
|
44
|
+
|
45
|
+
/* trilogy_reader_get_uint16 - Parse an unsigned 16-bit integer.
|
46
|
+
*
|
47
|
+
* reader - A pointer to a pre-initialized trilogy_reader_t.
|
48
|
+
* out - Out parameter; A pointer to a uint16_t which will be set to the
|
49
|
+
* value read from the buffer.
|
50
|
+
*
|
51
|
+
* Return values:
|
52
|
+
* TRILOGY_OK - The value was parsed.
|
53
|
+
* TRILOGY_TRUNCATED_PACKET - There isn't enough data left in the buffer.
|
54
|
+
*/
|
55
|
+
int trilogy_reader_get_uint16(trilogy_reader_t *reader, uint16_t *out);
|
56
|
+
|
57
|
+
/* trilogy_reader_get_uint24 - Parse an unsigned 24-bit integer.
|
58
|
+
*
|
59
|
+
* reader - A pointer to a pre-initialized trilogy_reader_t.
|
60
|
+
* out - Out parameter; A pointer to a uint32_t which will be set to the
|
61
|
+
* value read from the buffer.
|
62
|
+
*
|
63
|
+
* Return values:
|
64
|
+
* TRILOGY_OK - The value was parsed.
|
65
|
+
* TRILOGY_TRUNCATED_PACKET - There isn't enough data left in the buffer.
|
66
|
+
*/
|
67
|
+
int trilogy_reader_get_uint24(trilogy_reader_t *reader, uint32_t *out);
|
68
|
+
|
69
|
+
/* trilogy_reader_get_uint32 - Parse an unsigned 32-bit integer.
|
70
|
+
*
|
71
|
+
* reader - A pointer to a pre-initialized trilogy_reader_t.
|
72
|
+
* out - Out parameter; A pointer to a uint32_t which will be set to the
|
73
|
+
* value read from the buffer.
|
74
|
+
*
|
75
|
+
* Return values:
|
76
|
+
* TRILOGY_OK - The value was parsed.
|
77
|
+
* TRILOGY_TRUNCATED_PACKET - There isn't enough data left in the buffer.
|
78
|
+
*/
|
79
|
+
int trilogy_reader_get_uint32(trilogy_reader_t *reader, uint32_t *out);
|
80
|
+
|
81
|
+
/* trilogy_reader_get_uint64 - Parse an unsigned 64-bit integer.
|
82
|
+
*
|
83
|
+
* reader - A pointer to a pre-initialized trilogy_reader_t.
|
84
|
+
* out - Out parameter; A pointer to a uint64_t which will be set to the
|
85
|
+
* value read from the buffer.
|
86
|
+
*
|
87
|
+
* Return values:
|
88
|
+
* TRILOGY_OK - The value was parsed.
|
89
|
+
* TRILOGY_TRUNCATED_PACKET - There isn't enough data left in the buffer.
|
90
|
+
*/
|
91
|
+
int trilogy_reader_get_uint64(trilogy_reader_t *reader, uint64_t *out);
|
92
|
+
|
93
|
+
/* trilogy_reader_get_lenenc - Parse an unsigned, length-encoded integer.
|
94
|
+
*
|
95
|
+
* reader - A pointer to a pre-initialized trilogy_reader_t.
|
96
|
+
* out - Out parameter; A pointer to a uint64_t which will be set to the
|
97
|
+
* value read from the buffer.
|
98
|
+
*
|
99
|
+
* Return values:
|
100
|
+
* TRILOGY_OK - The value was parsed.
|
101
|
+
* TRILOGY_TRUNCATED_PACKET - There isn't enough data left in the buffer.
|
102
|
+
*/
|
103
|
+
int trilogy_reader_get_lenenc(trilogy_reader_t *reader, uint64_t *out);
|
104
|
+
|
105
|
+
/* trilogy_reader_get_buffer - Parse an opaque set of bytes from the packet,
|
106
|
+
* pointing the dereferenced value of `out` to the beginning of the set.
|
107
|
+
*
|
108
|
+
* reader - A pointer to a pre-initialized trilogy_reader_t.
|
109
|
+
* len - The number of bytes to attempt to read from the buffer.
|
110
|
+
* out - Out parameter; A pointer to a void* which will be set to the
|
111
|
+
* beginning of the opaque buffer. This will be a pointer into the
|
112
|
+
* buffer that was originally passed to trilogy_reader_init. No copies
|
113
|
+
* are made internally.
|
114
|
+
*
|
115
|
+
* Return values:
|
116
|
+
* TRILOGY_OK - The value was parsed and the dereferenced value of
|
117
|
+
* `out` now points to it.
|
118
|
+
* TRILOGY_TRUNCATED_PACKET - There isn't enough data left in the buffer.
|
119
|
+
*/
|
120
|
+
int trilogy_reader_get_buffer(trilogy_reader_t *reader, size_t len, const void **out);
|
121
|
+
|
122
|
+
/* trilogy_reader_copy_buffer - Parse an opaque set of bytes from the packet and
|
123
|
+
* copy them into `out`. `out` must be allocated with at least `len` bytes.
|
124
|
+
*
|
125
|
+
* reader - A pointer to a pre-initialized trilogy_reader_t.
|
126
|
+
* len - The number of bytes to attempt to read from the buffer.
|
127
|
+
* out - A pointer to the address to copy `len` bytes from the packet buffer
|
128
|
+
* to.
|
129
|
+
*
|
130
|
+
* Return values:
|
131
|
+
* TRILOGY_OK - The value was parsed and copied into the location
|
132
|
+
* `out` points to.
|
133
|
+
* TRILOGY_TRUNCATED_PACKET - There isn't enough data left in the buffer.
|
134
|
+
*/
|
135
|
+
int trilogy_reader_copy_buffer(trilogy_reader_t *reader, size_t len, void *out);
|
136
|
+
|
137
|
+
/* trilogy_reader_get_lenenc_buffer - Parse an opaque set of bytes from the
|
138
|
+
* packet, pointing the dereferenced value of `out` to the beginning of the set.
|
139
|
+
* The length of the buffer is defined by a preceding length-encoded integer,
|
140
|
+
* who's value will be copied in to `out_len`.
|
141
|
+
*
|
142
|
+
* reader - A pointer to a pre-initialized trilogy_reader_t.
|
143
|
+
* out_len - Out parameter; The length of the read buffer in bytes.
|
144
|
+
* out - Out parameter; A pointer to a void* which will be set to the
|
145
|
+
* beginning of the opaque buffer.
|
146
|
+
*
|
147
|
+
* Return values:
|
148
|
+
* TRILOGY_OK - The value was parsed and the dereferenced value of
|
149
|
+
* `out` now points to it.
|
150
|
+
* TRILOGY_TRUNCATED_PACKET - There isn't enough data left in the buffer.
|
151
|
+
*/
|
152
|
+
int trilogy_reader_get_lenenc_buffer(trilogy_reader_t *reader, size_t *out_len, const void **out);
|
153
|
+
|
154
|
+
/* trilogy_reader_get_string - Parse a C-string from the packet, pointing the
|
155
|
+
* dereferenced value of `out` to the beginning of the set.
|
156
|
+
*
|
157
|
+
* reader - A pointer to a pre-initialized trilogy_reader_t.
|
158
|
+
* out_len - Out parameter; The length of the C-string read from the buffer in
|
159
|
+
* bytes.
|
160
|
+
* out - Out parameter; A pointer to a void* which will be set to the
|
161
|
+
* beginning of the C-string.
|
162
|
+
*
|
163
|
+
* Return values:
|
164
|
+
* TRILOGY_OK - The value was parsed and the dereferenced value of
|
165
|
+
* `out` now points to it.
|
166
|
+
* TRILOGY_TRUNCATED_PACKET - There isn't enough data left in the buffer.
|
167
|
+
*/
|
168
|
+
int trilogy_reader_get_string(trilogy_reader_t *reader, const char **out, size_t *out_len);
|
169
|
+
|
170
|
+
/* trilogy_reader_get_eof_buffer - Parse an opaque set of bytes from the packet,
|
171
|
+
* pointing the dereferenced value of `out` to the beginning of the set. The
|
172
|
+
* buffer pointed to by `out` will contain the remaining un-parsed bytes from
|
173
|
+
* the packet buffer.
|
174
|
+
*
|
175
|
+
* This will just hand the caller back a pointer into the remainder of the
|
176
|
+
* buffer, even if there aren't any more bytes left to read. As a result, this
|
177
|
+
* function will only ever return TRILOGY_OK.
|
178
|
+
*
|
179
|
+
* reader - A pointer to a pre-initialized trilogy_reader_t.
|
180
|
+
* out_len - Out parameter; The length of the read buffer in bytes.
|
181
|
+
* out - Out parameter; A pointer to a void* which will be set to the
|
182
|
+
* beginning of the opaque buffer.
|
183
|
+
*
|
184
|
+
* Return values:
|
185
|
+
* TRILOGY_OK - The value was parsed and the dereferenced value of
|
186
|
+
* `out` now points to it.
|
187
|
+
*/
|
188
|
+
int trilogy_reader_get_eof_buffer(trilogy_reader_t *reader, size_t *out_len, const void **out);
|
189
|
+
|
190
|
+
/* trilogy_reader_eof - Check if the reader is at the end of the buffer.
|
191
|
+
*
|
192
|
+
* reader - A pointer to a pre-initialized trilogy_reader_t.
|
193
|
+
*
|
194
|
+
* Returns true if the reader is at the end of the buffer it's reading from,
|
195
|
+
* or false if not
|
196
|
+
*/
|
197
|
+
bool trilogy_reader_eof(trilogy_reader_t *reader);
|
198
|
+
|
199
|
+
/* trilogy_reader_finish - Finalize the reader. This will ensure the entire buffer
|
200
|
+
* was parsed, otherwise TRILOGY_EXTRA_DATA_IN_PACKET will be returned.
|
201
|
+
*
|
202
|
+
* This can be useful to ensure an entire packet is fully read.
|
203
|
+
*
|
204
|
+
* reader - A pointer to a pre-initialized trilogy_reader_t.
|
205
|
+
*
|
206
|
+
* Return values:
|
207
|
+
* TRILOGY_OK - The entire buffer was parsed.
|
208
|
+
* TRILOGY_EXTRA_DATA_IN_PACKET - There are unparsed bytes left in the buffer.
|
209
|
+
*/
|
210
|
+
int trilogy_reader_finish(trilogy_reader_t *reader);
|
211
|
+
|
212
|
+
#endif
|
@@ -0,0 +1,111 @@
|
|
1
|
+
#ifndef TRILOGY_SOCKET_H
|
2
|
+
#define TRILOGY_SOCKET_H
|
3
|
+
|
4
|
+
#include "trilogy/error.h"
|
5
|
+
#include "trilogy/protocol.h"
|
6
|
+
#include <openssl/err.h>
|
7
|
+
#include <openssl/ssl.h>
|
8
|
+
#include <openssl/x509v3.h>
|
9
|
+
#include <stdbool.h>
|
10
|
+
#include <sys/time.h>
|
11
|
+
|
12
|
+
typedef enum {
|
13
|
+
TRILOGY_WAIT_READ = 0,
|
14
|
+
TRILOGY_WAIT_WRITE = 1,
|
15
|
+
TRILOGY_WAIT_HANDSHAKE = 2,
|
16
|
+
} trilogy_wait_t;
|
17
|
+
|
18
|
+
// We use the most strict mode as value 1 so if anyone ever
|
19
|
+
// treats this as a boolean, they get the most strict behavior
|
20
|
+
// by default.
|
21
|
+
typedef enum {
|
22
|
+
TRILOGY_SSL_DISABLED = 0,
|
23
|
+
TRILOGY_SSL_VERIFY_IDENTITY = 1,
|
24
|
+
TRILOGY_SSL_VERIFY_CA = 2,
|
25
|
+
TRILOGY_SSL_REQUIRED_NOVERIFY = 3,
|
26
|
+
TRILOGY_SSL_PREFERRED_NOVERIFY = 4,
|
27
|
+
} trilogy_ssl_mode_t;
|
28
|
+
|
29
|
+
typedef enum {
|
30
|
+
TRILOGY_TLS_VERSION_UNDEF = 0,
|
31
|
+
TRILOGY_TLS_VERSION_10 = 1,
|
32
|
+
TRILOGY_TLS_VERSION_11 = 2,
|
33
|
+
TRILOGY_TLS_VERSION_12 = 3,
|
34
|
+
TRILOGY_TLS_VERSION_13 = 4,
|
35
|
+
} trilogy_tls_version_t;
|
36
|
+
|
37
|
+
typedef struct {
|
38
|
+
char *hostname;
|
39
|
+
char *path;
|
40
|
+
char *database;
|
41
|
+
char *username;
|
42
|
+
char *password;
|
43
|
+
size_t password_len;
|
44
|
+
|
45
|
+
trilogy_ssl_mode_t ssl_mode;
|
46
|
+
trilogy_tls_version_t tls_min_version;
|
47
|
+
trilogy_tls_version_t tls_max_version;
|
48
|
+
uint16_t port;
|
49
|
+
|
50
|
+
char *ssl_ca;
|
51
|
+
char *ssl_capath;
|
52
|
+
char *ssl_cert;
|
53
|
+
char *ssl_cipher;
|
54
|
+
char *ssl_crl;
|
55
|
+
char *ssl_crlpath;
|
56
|
+
char *ssl_key;
|
57
|
+
char *tls_ciphersuites;
|
58
|
+
|
59
|
+
struct timeval connect_timeout;
|
60
|
+
struct timeval read_timeout;
|
61
|
+
struct timeval write_timeout;
|
62
|
+
|
63
|
+
bool keepalive_enabled;
|
64
|
+
uint16_t keepalive_idle;
|
65
|
+
uint16_t keepalive_count;
|
66
|
+
uint16_t keepalive_interval;
|
67
|
+
|
68
|
+
TRILOGY_CAPABILITIES_t flags;
|
69
|
+
} trilogy_sockopt_t;
|
70
|
+
|
71
|
+
typedef struct trilogy_sock_t {
|
72
|
+
int (*connect_cb)(struct trilogy_sock_t *self);
|
73
|
+
ssize_t (*read_cb)(struct trilogy_sock_t *self, void *buf, size_t nread);
|
74
|
+
ssize_t (*write_cb)(struct trilogy_sock_t *self, const void *buf, size_t nwrite);
|
75
|
+
int (*wait_cb)(struct trilogy_sock_t *self, trilogy_wait_t wait);
|
76
|
+
int (*shutdown_cb)(struct trilogy_sock_t *self);
|
77
|
+
int (*close_cb)(struct trilogy_sock_t *self);
|
78
|
+
int (*fd_cb)(struct trilogy_sock_t *self);
|
79
|
+
|
80
|
+
trilogy_sockopt_t opts;
|
81
|
+
} trilogy_sock_t;
|
82
|
+
|
83
|
+
static inline int trilogy_sock_connect(trilogy_sock_t *sock) { return sock->connect_cb(sock); }
|
84
|
+
|
85
|
+
static inline ssize_t trilogy_sock_read(trilogy_sock_t *sock, void *buf, size_t n)
|
86
|
+
{
|
87
|
+
return sock->read_cb(sock, buf, n);
|
88
|
+
}
|
89
|
+
|
90
|
+
static inline ssize_t trilogy_sock_write(trilogy_sock_t *sock, const void *buf, size_t n)
|
91
|
+
{
|
92
|
+
return sock->write_cb(sock, buf, n);
|
93
|
+
}
|
94
|
+
|
95
|
+
static inline int trilogy_sock_wait(trilogy_sock_t *sock, trilogy_wait_t wait) { return sock->wait_cb(sock, wait); }
|
96
|
+
|
97
|
+
static inline int trilogy_sock_wait_read(trilogy_sock_t *sock) { return sock->wait_cb(sock, TRILOGY_WAIT_READ); }
|
98
|
+
|
99
|
+
static inline int trilogy_sock_wait_write(trilogy_sock_t *sock) { return sock->wait_cb(sock, TRILOGY_WAIT_WRITE); }
|
100
|
+
|
101
|
+
static inline int trilogy_sock_shutdown(trilogy_sock_t *sock) { return sock->shutdown_cb(sock); }
|
102
|
+
|
103
|
+
static inline int trilogy_sock_close(trilogy_sock_t *sock) { return sock->close_cb(sock); }
|
104
|
+
|
105
|
+
static inline int trilogy_sock_fd(trilogy_sock_t *sock) { return sock->fd_cb(sock); }
|
106
|
+
|
107
|
+
trilogy_sock_t *trilogy_sock_new(const trilogy_sockopt_t *opts);
|
108
|
+
int trilogy_sock_resolve(trilogy_sock_t *raw);
|
109
|
+
int trilogy_sock_upgrade_ssl(trilogy_sock_t *raw);
|
110
|
+
|
111
|
+
#endif
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#ifndef HEADER_CURL_HOSTCHECK_H
|
2
|
+
#define HEADER_CURL_HOSTCHECK_H
|
3
|
+
/***************************************************************************
|
4
|
+
* _ _ ____ _
|
5
|
+
* Project ___| | | | _ \| |
|
6
|
+
* / __| | | | |_) | |
|
7
|
+
* | (__| |_| | _ <| |___
|
8
|
+
* \___|\___/|_| \_\_____|
|
9
|
+
*
|
10
|
+
* Copyright (C) 1998 - 2012, Daniel Stenberg, <daniel@haxx.se>, et al.
|
11
|
+
*
|
12
|
+
* This software is licensed as described in the file COPYING, which
|
13
|
+
* you should have received as part of this distribution. The terms
|
14
|
+
* are also available at http://curl.haxx.se/docs/copyright.html.
|
15
|
+
*
|
16
|
+
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
|
17
|
+
* copies of the Software, and permit persons to whom the Software is
|
18
|
+
* furnished to do so, under the terms of the COPYING file.
|
19
|
+
*
|
20
|
+
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
21
|
+
* KIND, either express or implied.
|
22
|
+
*
|
23
|
+
***************************************************************************/
|
24
|
+
|
25
|
+
#define CURL_HOST_NOMATCH 0
|
26
|
+
#define CURL_HOST_MATCH 1
|
27
|
+
int Curl_cert_hostcheck(const char *match_pattern, const char *hostname);
|
28
|
+
|
29
|
+
#endif /* HEADER_CURL_HOSTCHECK_H */
|
@@ -0,0 +1,51 @@
|
|
1
|
+
#ifndef HEADER_OPENSSL_HOSTNAME_VALIDATION_H
|
2
|
+
#define HEADER_OPENSSL_HOSTNAME_VALIDATION_H
|
3
|
+
/* Obtained from: https://github.com/iSECPartners/ssl-conservatory */
|
4
|
+
|
5
|
+
/*
|
6
|
+
Copyright (C) 2012, iSEC Partners.
|
7
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
8
|
+
this software and associated documentation files (the "Software"), to deal in
|
9
|
+
the Software without restriction, including without limitation the rights to
|
10
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
11
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
12
|
+
so, subject to the following conditions:
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
14
|
+
copies or substantial portions of the Software.
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
22
|
+
*/
|
23
|
+
|
24
|
+
/*
|
25
|
+
* Helper functions to perform basic hostname validation using OpenSSL.
|
26
|
+
*
|
27
|
+
* Please read "everything-you-wanted-to-know-about-openssl.pdf" before
|
28
|
+
* attempting to use this code. This whitepaper describes how the code works,
|
29
|
+
* how it should be used, and what its limitations are.
|
30
|
+
*
|
31
|
+
* Author: Alban Diquet
|
32
|
+
* License: See LICENSE
|
33
|
+
*
|
34
|
+
*/
|
35
|
+
|
36
|
+
typedef enum { MatchFound, MatchNotFound, NoSANPresent, MalformedCertificate, Error } HostnameValidationResult;
|
37
|
+
|
38
|
+
/**
|
39
|
+
* Validates the server's identity by looking for the expected hostname in the
|
40
|
+
* server's certificate. As described in RFC 6125, it first tries to find a
|
41
|
+
* match in the Subject Alternative Name extension. If the extension is not
|
42
|
+
* present in the certificate, it checks the Common Name instead.
|
43
|
+
*
|
44
|
+
* Returns MatchFound if a match was found.
|
45
|
+
* Returns MatchNotFound if no matches were found.
|
46
|
+
* Returns MalformedCertificate if any of the hostnames had a NUL character
|
47
|
+
* embedded in it. Returns Error if there was an error.
|
48
|
+
*/
|
49
|
+
HostnameValidationResult validate_hostname(const char *hostname, const X509 *server_cert);
|
50
|
+
|
51
|
+
#endif /* HEADER_OPENSSL_HOSTNAME_VALIDATION_H */
|
@@ -0,0 +1,241 @@
|
|
1
|
+
#include <errno.h>
|
2
|
+
#include <poll.h>
|
3
|
+
|
4
|
+
#include "trilogy/blocking.h"
|
5
|
+
#include "trilogy/client.h"
|
6
|
+
#include "trilogy/error.h"
|
7
|
+
|
8
|
+
#define CHECKED(expr) \
|
9
|
+
if ((rc = (expr)) < 0) { \
|
10
|
+
return rc; \
|
11
|
+
}
|
12
|
+
|
13
|
+
static int flush_full(trilogy_conn_t *conn)
|
14
|
+
{
|
15
|
+
int rc;
|
16
|
+
|
17
|
+
while (1) {
|
18
|
+
CHECKED(trilogy_sock_wait_write(conn->socket));
|
19
|
+
|
20
|
+
rc = trilogy_flush_writes(conn);
|
21
|
+
|
22
|
+
if (rc != TRILOGY_AGAIN) {
|
23
|
+
return rc;
|
24
|
+
}
|
25
|
+
}
|
26
|
+
}
|
27
|
+
|
28
|
+
static int trilogy_connect_auth_switch(trilogy_conn_t *conn, trilogy_handshake_t *handshake)
|
29
|
+
{
|
30
|
+
int rc = trilogy_auth_switch_send(conn, handshake);
|
31
|
+
|
32
|
+
if (rc == TRILOGY_AGAIN) {
|
33
|
+
rc = flush_full(conn);
|
34
|
+
}
|
35
|
+
|
36
|
+
if (rc < 0) {
|
37
|
+
return rc;
|
38
|
+
}
|
39
|
+
|
40
|
+
while (1) {
|
41
|
+
rc = trilogy_auth_recv(conn, handshake);
|
42
|
+
|
43
|
+
if (rc != TRILOGY_AGAIN) {
|
44
|
+
break;
|
45
|
+
}
|
46
|
+
|
47
|
+
CHECKED(trilogy_sock_wait_read(conn->socket));
|
48
|
+
}
|
49
|
+
return rc;
|
50
|
+
}
|
51
|
+
|
52
|
+
static int trilogy_connect_handshake(trilogy_conn_t *conn)
|
53
|
+
{
|
54
|
+
trilogy_handshake_t handshake;
|
55
|
+
int rc;
|
56
|
+
|
57
|
+
while (1) {
|
58
|
+
rc = trilogy_connect_recv(conn, &handshake);
|
59
|
+
|
60
|
+
if (rc == TRILOGY_OK) {
|
61
|
+
break;
|
62
|
+
}
|
63
|
+
|
64
|
+
if (rc != TRILOGY_AGAIN) {
|
65
|
+
return rc;
|
66
|
+
}
|
67
|
+
|
68
|
+
CHECKED(trilogy_sock_wait_read(conn->socket));
|
69
|
+
}
|
70
|
+
|
71
|
+
rc = trilogy_auth_send(conn, &handshake);
|
72
|
+
|
73
|
+
if (rc == TRILOGY_AGAIN) {
|
74
|
+
rc = flush_full(conn);
|
75
|
+
}
|
76
|
+
|
77
|
+
if (rc < 0) {
|
78
|
+
return rc;
|
79
|
+
}
|
80
|
+
|
81
|
+
while (1) {
|
82
|
+
rc = trilogy_auth_recv(conn, &handshake);
|
83
|
+
|
84
|
+
if (rc != TRILOGY_AGAIN) {
|
85
|
+
break;
|
86
|
+
}
|
87
|
+
|
88
|
+
CHECKED(trilogy_sock_wait_read(conn->socket));
|
89
|
+
}
|
90
|
+
|
91
|
+
if (rc == TRILOGY_AUTH_SWITCH) {
|
92
|
+
return trilogy_connect_auth_switch(conn, &handshake);
|
93
|
+
}
|
94
|
+
return rc;
|
95
|
+
}
|
96
|
+
|
97
|
+
int trilogy_connect(trilogy_conn_t *conn, const trilogy_sockopt_t *opts)
|
98
|
+
{
|
99
|
+
int rc = trilogy_connect_send(conn, opts);
|
100
|
+
|
101
|
+
if (rc < 0) {
|
102
|
+
return rc;
|
103
|
+
}
|
104
|
+
|
105
|
+
return trilogy_connect_handshake(conn);
|
106
|
+
}
|
107
|
+
|
108
|
+
int trilogy_connect_sock(trilogy_conn_t *conn, trilogy_sock_t *sock)
|
109
|
+
{
|
110
|
+
int rc = trilogy_connect_send_socket(conn, sock);
|
111
|
+
|
112
|
+
if (rc < 0) {
|
113
|
+
return rc;
|
114
|
+
}
|
115
|
+
|
116
|
+
return trilogy_connect_handshake(conn);
|
117
|
+
}
|
118
|
+
|
119
|
+
int trilogy_change_db(trilogy_conn_t *conn, const char *name, size_t name_len)
|
120
|
+
{
|
121
|
+
int rc = trilogy_change_db_send(conn, name, name_len);
|
122
|
+
|
123
|
+
if (rc == TRILOGY_AGAIN) {
|
124
|
+
rc = flush_full(conn);
|
125
|
+
}
|
126
|
+
|
127
|
+
if (rc < 0) {
|
128
|
+
return rc;
|
129
|
+
}
|
130
|
+
|
131
|
+
while (1) {
|
132
|
+
rc = trilogy_change_db_recv(conn);
|
133
|
+
|
134
|
+
if (rc != TRILOGY_AGAIN) {
|
135
|
+
return rc;
|
136
|
+
}
|
137
|
+
|
138
|
+
CHECKED(trilogy_sock_wait_read(conn->socket));
|
139
|
+
}
|
140
|
+
}
|
141
|
+
|
142
|
+
int trilogy_ping(trilogy_conn_t *conn)
|
143
|
+
{
|
144
|
+
int rc = trilogy_ping_send(conn);
|
145
|
+
|
146
|
+
if (rc == TRILOGY_AGAIN) {
|
147
|
+
rc = flush_full(conn);
|
148
|
+
}
|
149
|
+
|
150
|
+
if (rc < 0) {
|
151
|
+
return rc;
|
152
|
+
}
|
153
|
+
|
154
|
+
while (1) {
|
155
|
+
rc = trilogy_ping_recv(conn);
|
156
|
+
|
157
|
+
if (rc != TRILOGY_AGAIN) {
|
158
|
+
return rc;
|
159
|
+
}
|
160
|
+
|
161
|
+
CHECKED(trilogy_sock_wait_read(conn->socket));
|
162
|
+
}
|
163
|
+
}
|
164
|
+
|
165
|
+
int trilogy_query(trilogy_conn_t *conn, const char *query, size_t query_len, uint64_t *column_count_out)
|
166
|
+
{
|
167
|
+
int rc = trilogy_query_send(conn, query, query_len);
|
168
|
+
|
169
|
+
if (rc == TRILOGY_AGAIN) {
|
170
|
+
rc = flush_full(conn);
|
171
|
+
}
|
172
|
+
|
173
|
+
if (rc < 0) {
|
174
|
+
return rc;
|
175
|
+
}
|
176
|
+
|
177
|
+
while (1) {
|
178
|
+
rc = trilogy_query_recv(conn, column_count_out);
|
179
|
+
|
180
|
+
if (rc != TRILOGY_AGAIN) {
|
181
|
+
return rc;
|
182
|
+
}
|
183
|
+
|
184
|
+
CHECKED(trilogy_sock_wait_read(conn->socket));
|
185
|
+
}
|
186
|
+
}
|
187
|
+
|
188
|
+
int trilogy_read_full_column(trilogy_conn_t *conn, trilogy_column_t *column_out)
|
189
|
+
{
|
190
|
+
int rc;
|
191
|
+
|
192
|
+
while (1) {
|
193
|
+
rc = trilogy_read_column(conn, column_out);
|
194
|
+
|
195
|
+
if (rc != TRILOGY_AGAIN) {
|
196
|
+
return rc;
|
197
|
+
}
|
198
|
+
|
199
|
+
CHECKED(trilogy_sock_wait_read(conn->socket));
|
200
|
+
}
|
201
|
+
}
|
202
|
+
|
203
|
+
int trilogy_read_full_row(trilogy_conn_t *conn, trilogy_value_t *values_out)
|
204
|
+
{
|
205
|
+
int rc;
|
206
|
+
|
207
|
+
while (1) {
|
208
|
+
rc = trilogy_read_row(conn, values_out);
|
209
|
+
|
210
|
+
if (rc != TRILOGY_AGAIN) {
|
211
|
+
return rc;
|
212
|
+
}
|
213
|
+
|
214
|
+
CHECKED(trilogy_sock_wait_read(conn->socket));
|
215
|
+
}
|
216
|
+
}
|
217
|
+
|
218
|
+
int trilogy_close(trilogy_conn_t *conn)
|
219
|
+
{
|
220
|
+
int rc = trilogy_close_send(conn);
|
221
|
+
|
222
|
+
if (rc == TRILOGY_AGAIN) {
|
223
|
+
rc = flush_full(conn);
|
224
|
+
}
|
225
|
+
|
226
|
+
if (rc < 0) {
|
227
|
+
return rc;
|
228
|
+
}
|
229
|
+
|
230
|
+
while (1) {
|
231
|
+
rc = trilogy_close_recv(conn);
|
232
|
+
|
233
|
+
if (rc != TRILOGY_AGAIN) {
|
234
|
+
return rc;
|
235
|
+
}
|
236
|
+
|
237
|
+
CHECKED(trilogy_sock_wait_read(conn->socket));
|
238
|
+
}
|
239
|
+
}
|
240
|
+
|
241
|
+
#undef CHECKED
|