iodine 0.7.57 → 0.7.59
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/CHANGELOG.md +6 -0
- data/README.md +17 -17
- data/SECURITY.md +32 -0
- data/ext/iodine/fio.c +1 -1
- data/ext/iodine/fio.h +12 -14
- data/ext/iodine/fio_json_parser.h +5 -4
- data/ext/iodine/fio_tls_openssl.c +140 -90
- data/ext/iodine/fiobj_data.c +13 -11
- data/ext/iodine/fiobj_str.h +1 -1
- data/ext/iodine/fiobject.h +5 -4
- data/ext/iodine/http1.c +92 -7
- data/ext/iodine/http1_parser.h +164 -1121
- data/ext/iodine/iodine_caller.c +25 -13
- data/ext/iodine/iodine_store.c +23 -19
- data/ext/iodine/websockets.c +7 -16
- data/lib/iodine/version.rb +1 -1
- data/lib/iodine.rb +4 -0
- metadata +5 -6
|
@@ -32,7 +32,7 @@ typedef struct {
|
|
|
32
32
|
/* *****************************************************************************
|
|
33
33
|
The SSL/TLS helper data types (can be left as is)
|
|
34
34
|
***************************************************************************** */
|
|
35
|
-
#define FIO_INCLUDE_STR
|
|
35
|
+
#define FIO_INCLUDE_STR 1
|
|
36
36
|
#define FIO_FORCE_MALLOC_TMP 1
|
|
37
37
|
#include <fio.h>
|
|
38
38
|
|
|
@@ -65,12 +65,12 @@ static inline void fio_tls_cert_destroy(cert_s *obj) {
|
|
|
65
65
|
fio_str_free(&obj->password);
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
#define FIO_ARY_NAME
|
|
69
|
-
#define FIO_ARY_TYPE
|
|
68
|
+
#define FIO_ARY_NAME cert_ary
|
|
69
|
+
#define FIO_ARY_TYPE cert_s
|
|
70
70
|
#define FIO_ARY_COMPARE(k1, k2) (fio_tls_cert_cmp(&(k1), &(k2)))
|
|
71
71
|
#define FIO_ARY_COPY(dest, obj) fio_tls_cert_copy(&(dest), &(obj))
|
|
72
|
-
#define FIO_ARY_DESTROY(key)
|
|
73
|
-
#define FIO_FORCE_MALLOC_TMP
|
|
72
|
+
#define FIO_ARY_DESTROY(key) fio_tls_cert_destroy(&(key))
|
|
73
|
+
#define FIO_FORCE_MALLOC_TMP 1
|
|
74
74
|
#include <fio.h>
|
|
75
75
|
|
|
76
76
|
typedef struct {
|
|
@@ -90,12 +90,12 @@ static inline void fio_tls_trust_destroy(trust_s *obj) {
|
|
|
90
90
|
fio_str_free(&obj->pem);
|
|
91
91
|
}
|
|
92
92
|
|
|
93
|
-
#define FIO_ARY_NAME
|
|
94
|
-
#define FIO_ARY_TYPE
|
|
93
|
+
#define FIO_ARY_NAME trust_ary
|
|
94
|
+
#define FIO_ARY_TYPE trust_s
|
|
95
95
|
#define FIO_ARY_COMPARE(k1, k2) (fio_tls_trust_cmp(&(k1), &(k2)))
|
|
96
96
|
#define FIO_ARY_COPY(dest, obj) fio_tls_trust_copy(&(dest), &(obj))
|
|
97
|
-
#define FIO_ARY_DESTROY(key)
|
|
98
|
-
#define FIO_FORCE_MALLOC_TMP
|
|
97
|
+
#define FIO_ARY_DESTROY(key) fio_tls_trust_destroy(&(key))
|
|
98
|
+
#define FIO_FORCE_MALLOC_TMP 1
|
|
99
99
|
#include <fio.h>
|
|
100
100
|
|
|
101
101
|
typedef struct {
|
|
@@ -123,12 +123,12 @@ static inline void fio_alpn_destroy(alpn_s *obj) {
|
|
|
123
123
|
fio_str_free(&obj->name);
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
#define FIO_SET_NAME
|
|
127
|
-
#define FIO_SET_OBJ_TYPE
|
|
126
|
+
#define FIO_SET_NAME alpn_list
|
|
127
|
+
#define FIO_SET_OBJ_TYPE alpn_s
|
|
128
128
|
#define FIO_SET_OBJ_COMPARE(k1, k2) fio_alpn_cmp(&(k1), &(k2))
|
|
129
129
|
#define FIO_SET_OBJ_COPY(dest, obj) fio_alpn_copy(&(dest), &(obj))
|
|
130
|
-
#define FIO_SET_OBJ_DESTROY(key)
|
|
131
|
-
#define FIO_FORCE_MALLOC_TMP
|
|
130
|
+
#define FIO_SET_OBJ_DESTROY(key) fio_alpn_destroy(&(key))
|
|
131
|
+
#define FIO_FORCE_MALLOC_TMP 1
|
|
132
132
|
#include <fio.h>
|
|
133
133
|
|
|
134
134
|
/* *****************************************************************************
|
|
@@ -167,10 +167,13 @@ FIO_FUNC inline alpn_s *alpn_find(fio_tls_s *tls, char *name, size_t len) {
|
|
|
167
167
|
}
|
|
168
168
|
|
|
169
169
|
/** Adds an ALPN data object to the ALPN "list" (set) */
|
|
170
|
-
FIO_FUNC inline void alpn_add(
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
170
|
+
FIO_FUNC inline void alpn_add(fio_tls_s *tls,
|
|
171
|
+
const char *protocol_name,
|
|
172
|
+
void (*on_selected)(intptr_t uuid,
|
|
173
|
+
void *udata_connection,
|
|
174
|
+
void *udata_tls),
|
|
175
|
+
void *udata_tls,
|
|
176
|
+
void (*on_cleanup)(void *udata_tls)) {
|
|
174
177
|
alpn_s tmp = {
|
|
175
178
|
.name = FIO_STR_INIT_STATIC(protocol_name),
|
|
176
179
|
.on_selected = on_selected,
|
|
@@ -212,7 +215,8 @@ FIO_FUNC inline void alpn_select___task(void *t_, void *ignr_) {
|
|
|
212
215
|
}
|
|
213
216
|
|
|
214
217
|
/** Schedules the ALPN protocol callback. */
|
|
215
|
-
FIO_FUNC inline void alpn_select(alpn_s *alpn,
|
|
218
|
+
FIO_FUNC inline void alpn_select(alpn_s *alpn,
|
|
219
|
+
intptr_t uuid,
|
|
216
220
|
void *udata_connection) {
|
|
217
221
|
if (!alpn || !alpn->on_selected)
|
|
218
222
|
return;
|
|
@@ -257,7 +261,8 @@ static void fio_tls_make_root_key(void) {
|
|
|
257
261
|
"OpenSSL failed to create RSA key.");
|
|
258
262
|
BN_free(e);
|
|
259
263
|
EVP_PKEY_assign_RSA(fio_tls_pkey, rsa);
|
|
260
|
-
fio_state_callback_add(FIO_CALL_AT_EXIT,
|
|
264
|
+
fio_state_callback_add(FIO_CALL_AT_EXIT,
|
|
265
|
+
fio_tls_clear_root_key,
|
|
261
266
|
fio_tls_pkey);
|
|
262
267
|
finish:
|
|
263
268
|
fio_unlock(&lock);
|
|
@@ -284,12 +289,27 @@ static X509 *fio_tls_create_self_signed(char *server_name) {
|
|
|
284
289
|
/* set identity details */
|
|
285
290
|
X509_NAME *s = X509_get_subject_name(cert);
|
|
286
291
|
size_t srv_name_len = strlen(server_name);
|
|
287
|
-
X509_NAME_add_entry_by_txt(s,
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
(unsigned char *)server_name,
|
|
291
|
-
|
|
292
|
-
|
|
292
|
+
X509_NAME_add_entry_by_txt(s,
|
|
293
|
+
"O",
|
|
294
|
+
MBSTRING_ASC,
|
|
295
|
+
(unsigned char *)server_name,
|
|
296
|
+
srv_name_len,
|
|
297
|
+
-1,
|
|
298
|
+
0);
|
|
299
|
+
X509_NAME_add_entry_by_txt(s,
|
|
300
|
+
"CN",
|
|
301
|
+
MBSTRING_ASC,
|
|
302
|
+
(unsigned char *)server_name,
|
|
303
|
+
srv_name_len,
|
|
304
|
+
-1,
|
|
305
|
+
0);
|
|
306
|
+
X509_NAME_add_entry_by_txt(s,
|
|
307
|
+
"CA",
|
|
308
|
+
MBSTRING_ASC,
|
|
309
|
+
(unsigned char *)server_name,
|
|
310
|
+
srv_name_len,
|
|
311
|
+
-1,
|
|
312
|
+
0);
|
|
293
313
|
X509_set_issuer_name(cert, s);
|
|
294
314
|
|
|
295
315
|
/* sign certificate */
|
|
@@ -324,12 +344,15 @@ static void fio_tls_alpn_fallback(fio_tls_connection_s *c) {
|
|
|
324
344
|
return;
|
|
325
345
|
/* set protocol to default protocol */
|
|
326
346
|
FIO_LOG_DEBUG("TLS ALPN handshake missing, falling back on %s for %p",
|
|
327
|
-
fio_str_info(&alpn->name).data,
|
|
347
|
+
fio_str_info(&alpn->name).data,
|
|
348
|
+
(void *)c->uuid);
|
|
328
349
|
alpn_select(alpn, c->uuid, c->alpn_arg);
|
|
329
350
|
}
|
|
330
|
-
static int fio_tls_alpn_selector_cb(SSL *ssl,
|
|
351
|
+
static int fio_tls_alpn_selector_cb(SSL *ssl,
|
|
352
|
+
const unsigned char **out,
|
|
331
353
|
unsigned char *outlen,
|
|
332
|
-
const unsigned char *in,
|
|
354
|
+
const unsigned char *in,
|
|
355
|
+
unsigned int inlen,
|
|
333
356
|
void *tls_) {
|
|
334
357
|
fio_tls_s *tls = tls_;
|
|
335
358
|
alpn_s *alpn;
|
|
@@ -358,7 +381,8 @@ static int fio_tls_alpn_selector_cb(SSL *ssl, const unsigned char **out,
|
|
|
358
381
|
alpn_select(alpn, c->uuid, c->alpn_arg);
|
|
359
382
|
FIO_LOG_DEBUG(
|
|
360
383
|
"TLS ALPN handshake failed, falling back on default (%s) for %p",
|
|
361
|
-
fio_str_data(&alpn->name),
|
|
384
|
+
fio_str_data(&alpn->name),
|
|
385
|
+
(void *)c->uuid);
|
|
362
386
|
return SSL_TLSEXT_ERR_NOACK;
|
|
363
387
|
(void)ssl;
|
|
364
388
|
(void)out;
|
|
@@ -380,7 +404,9 @@ static void fio_tls_destroy_context(fio_tls_s *tls) {
|
|
|
380
404
|
FIO_LOG_DEBUG("destroyed TLS context for OpenSSL %p", (void *)tls);
|
|
381
405
|
}
|
|
382
406
|
|
|
383
|
-
static int fio_tls_pem_passwd_cb(char *buf,
|
|
407
|
+
static int fio_tls_pem_passwd_cb(char *buf,
|
|
408
|
+
int size,
|
|
409
|
+
int rwflag,
|
|
384
410
|
void *password) {
|
|
385
411
|
fio_str_info_s *p = password;
|
|
386
412
|
if (!p || !p->len || !size)
|
|
@@ -407,7 +433,8 @@ static void fio_tls_build_context(fio_tls_s *tls) {
|
|
|
407
433
|
/* attach certificates */
|
|
408
434
|
FIO_ARY_FOR(&tls->sni, pos) {
|
|
409
435
|
fio_str_info_s keys[4] = {
|
|
410
|
-
fio_str_info(&pos->private_key),
|
|
436
|
+
fio_str_info(&pos->private_key),
|
|
437
|
+
fio_str_info(&pos->public_key),
|
|
411
438
|
fio_str_info(&pos->password),
|
|
412
439
|
/* empty password slot for public key */
|
|
413
440
|
};
|
|
@@ -416,8 +443,10 @@ static void fio_tls_build_context(fio_tls_s *tls) {
|
|
|
416
443
|
/* Extract private key from private key file */
|
|
417
444
|
BIO *bio = BIO_new_mem_buf(keys[0].data, keys[0].len);
|
|
418
445
|
if (bio) {
|
|
419
|
-
EVP_PKEY *k = PEM_read_bio_PrivateKey(
|
|
420
|
-
|
|
446
|
+
EVP_PKEY *k = PEM_read_bio_PrivateKey(bio,
|
|
447
|
+
NULL,
|
|
448
|
+
fio_tls_pem_passwd_cb,
|
|
449
|
+
keys + 2);
|
|
421
450
|
if (k) {
|
|
422
451
|
FIO_LOG_DEBUG("TLS read private key from PEM file.");
|
|
423
452
|
SSL_CTX_use_PrivateKey(tls->ctx, k);
|
|
@@ -430,15 +459,21 @@ static void fio_tls_build_context(fio_tls_s *tls) {
|
|
|
430
459
|
/* Extract as much data as possible from each file */
|
|
431
460
|
BIO *bio = BIO_new_mem_buf(keys[ki].data, keys[ki].len);
|
|
432
461
|
FIO_ASSERT(bio, "OpenSSL error allocating BIO.");
|
|
433
|
-
STACK_OF(X509_INFO) *inf = PEM_X509_INFO_read_bio(
|
|
434
|
-
|
|
462
|
+
STACK_OF(X509_INFO) *inf = PEM_X509_INFO_read_bio(bio,
|
|
463
|
+
NULL,
|
|
464
|
+
fio_tls_pem_passwd_cb,
|
|
465
|
+
keys + ki + 2);
|
|
435
466
|
if (inf) {
|
|
436
467
|
for (int i = 0; i < sk_X509_INFO_num(inf); ++i) {
|
|
437
468
|
/* for each element in PEM */
|
|
438
469
|
X509_INFO *tmp = sk_X509_INFO_value(inf, i);
|
|
439
470
|
if (tmp->x509) {
|
|
440
471
|
FIO_LOG_DEBUG("TLS adding certificate from PEM file.");
|
|
441
|
-
|
|
472
|
+
if (i == 0) {
|
|
473
|
+
SSL_CTX_use_certificate(tls->ctx, tmp->x509);
|
|
474
|
+
} else {
|
|
475
|
+
SSL_CTX_add1_chain_cert(tls->ctx, tmp->x509);
|
|
476
|
+
}
|
|
442
477
|
}
|
|
443
478
|
if (tmp->x_pkey) {
|
|
444
479
|
FIO_LOG_DEBUG("TLS adding private key from PEM file.");
|
|
@@ -541,7 +576,9 @@ static void fio_tls_delayed_close(void *uuid, void *ignr_) {
|
|
|
541
576
|
* Note: facil.io library functions MUST NEVER be called by any r/w hook, or a
|
|
542
577
|
* deadlock might occur.
|
|
543
578
|
*/
|
|
544
|
-
static ssize_t fio_tls_read(intptr_t uuid,
|
|
579
|
+
static ssize_t fio_tls_read(intptr_t uuid,
|
|
580
|
+
void *udata,
|
|
581
|
+
void *buf,
|
|
545
582
|
size_t count) {
|
|
546
583
|
fio_tls_connection_s *c = udata;
|
|
547
584
|
ssize_t ret = SSL_read(c->ssl, buf, count);
|
|
@@ -549,23 +586,19 @@ static ssize_t fio_tls_read(intptr_t uuid, void *udata, void *buf,
|
|
|
549
586
|
return ret;
|
|
550
587
|
ret = SSL_get_error(c->ssl, ret);
|
|
551
588
|
switch (ret) {
|
|
552
|
-
case SSL_ERROR_SSL:
|
|
553
|
-
case SSL_ERROR_ZERO_RETURN:
|
|
554
|
-
|
|
555
|
-
case
|
|
556
|
-
|
|
557
|
-
case
|
|
558
|
-
case
|
|
559
|
-
case
|
|
560
|
-
case
|
|
561
|
-
case SSL_ERROR_WANT_WRITE: /* overflow */
|
|
562
|
-
case SSL_ERROR_WANT_READ: /* overflow */
|
|
589
|
+
case SSL_ERROR_SSL: /* overflow */
|
|
590
|
+
case SSL_ERROR_ZERO_RETURN: return 0; /* EOF */
|
|
591
|
+
case SSL_ERROR_SYSCALL: /* allow errno to inform us */ break; /* return -1 */
|
|
592
|
+
case SSL_ERROR_NONE: /* overflow */
|
|
593
|
+
case SSL_ERROR_WANT_CONNECT: /* overflow */
|
|
594
|
+
case SSL_ERROR_WANT_ACCEPT: /* overflow */
|
|
595
|
+
case SSL_ERROR_WANT_X509_LOOKUP: /* overflow */
|
|
596
|
+
case SSL_ERROR_WANT_WRITE: /* overflow */
|
|
597
|
+
case SSL_ERROR_WANT_READ: /* overflow */
|
|
563
598
|
#ifdef SSL_ERROR_WANT_ASYNC
|
|
564
|
-
case SSL_ERROR_WANT_ASYNC:
|
|
599
|
+
case SSL_ERROR_WANT_ASYNC: /* overflow */
|
|
565
600
|
#endif
|
|
566
|
-
default:
|
|
567
|
-
errno = EWOULDBLOCK;
|
|
568
|
-
break;
|
|
601
|
+
default: errno = EWOULDBLOCK; break;
|
|
569
602
|
}
|
|
570
603
|
return -1;
|
|
571
604
|
(void)uuid;
|
|
@@ -597,7 +630,9 @@ static ssize_t fio_tls_flush(intptr_t uuid, void *udata) {
|
|
|
597
630
|
* Note: facil.io library functions MUST NEVER be called by any r/w hook, or a
|
|
598
631
|
* deadlock might occur.
|
|
599
632
|
*/
|
|
600
|
-
static ssize_t fio_tls_write(intptr_t uuid,
|
|
633
|
+
static ssize_t fio_tls_write(intptr_t uuid,
|
|
634
|
+
void *udata,
|
|
635
|
+
const void *buf,
|
|
601
636
|
size_t count) {
|
|
602
637
|
fio_tls_connection_s *c = udata;
|
|
603
638
|
ssize_t ret = SSL_write(c->ssl, buf, count);
|
|
@@ -605,23 +640,19 @@ static ssize_t fio_tls_write(intptr_t uuid, void *udata, const void *buf,
|
|
|
605
640
|
return ret;
|
|
606
641
|
ret = SSL_get_error(c->ssl, ret);
|
|
607
642
|
switch (ret) {
|
|
608
|
-
case SSL_ERROR_SSL:
|
|
609
|
-
case SSL_ERROR_ZERO_RETURN:
|
|
610
|
-
|
|
611
|
-
case
|
|
612
|
-
|
|
613
|
-
case
|
|
614
|
-
case
|
|
615
|
-
case
|
|
616
|
-
case
|
|
617
|
-
case SSL_ERROR_WANT_WRITE: /* overflow */
|
|
618
|
-
case SSL_ERROR_WANT_READ: /* overflow */
|
|
643
|
+
case SSL_ERROR_SSL: /* overflow */
|
|
644
|
+
case SSL_ERROR_ZERO_RETURN: return 0; /* EOF */
|
|
645
|
+
case SSL_ERROR_SYSCALL: /* allow errno to inform us */ break; /* return -1 */
|
|
646
|
+
case SSL_ERROR_NONE: /* overflow */
|
|
647
|
+
case SSL_ERROR_WANT_CONNECT: /* overflow */
|
|
648
|
+
case SSL_ERROR_WANT_ACCEPT: /* overflow */
|
|
649
|
+
case SSL_ERROR_WANT_X509_LOOKUP: /* overflow */
|
|
650
|
+
case SSL_ERROR_WANT_WRITE: /* overflow */
|
|
651
|
+
case SSL_ERROR_WANT_READ: /* overflow */
|
|
619
652
|
#ifdef SSL_ERROR_WANT_ASYNC
|
|
620
|
-
case SSL_ERROR_WANT_ASYNC:
|
|
653
|
+
case SSL_ERROR_WANT_ASYNC: /* overflow */
|
|
621
654
|
#endif
|
|
622
|
-
default:
|
|
623
|
-
errno = EWOULDBLOCK;
|
|
624
|
-
break;
|
|
655
|
+
default: errno = EWOULDBLOCK; break;
|
|
625
656
|
}
|
|
626
657
|
return -1;
|
|
627
658
|
(void)uuid;
|
|
@@ -664,9 +695,9 @@ static fio_rw_hook_s FIO_TLS_HOOKS = {
|
|
|
664
695
|
.cleanup = fio_tls_cleanup,
|
|
665
696
|
};
|
|
666
697
|
|
|
667
|
-
#define FIO_TLS_HANDSHAKE_ERROR
|
|
668
|
-
#define FIO_TLS_HANDSHAKE_OK
|
|
669
|
-
#define FIO_TLS_HANDSHAKE_NEED_READ
|
|
698
|
+
#define FIO_TLS_HANDSHAKE_ERROR 0
|
|
699
|
+
#define FIO_TLS_HANDSHAKE_OK 1
|
|
700
|
+
#define FIO_TLS_HANDSHAKE_NEED_READ 2
|
|
670
701
|
#define FIO_TLS_HANDSHAKE_NEED_WRITE 4
|
|
671
702
|
|
|
672
703
|
static size_t fio_tls_handshake(intptr_t uuid, void *udata) {
|
|
@@ -701,7 +732,8 @@ static size_t fio_tls_handshake(intptr_t uuid, void *udata) {
|
|
|
701
732
|
if (errno) {
|
|
702
733
|
FIO_LOG_DEBUG(
|
|
703
734
|
"SSL_accept/SSL_connect %p error: SSL_ERROR_SYSCALL, errno: %s",
|
|
704
|
-
(void *)uuid,
|
|
735
|
+
(void *)uuid,
|
|
736
|
+
strerror(errno));
|
|
705
737
|
}
|
|
706
738
|
break;
|
|
707
739
|
case SSL_ERROR_SSL:
|
|
@@ -741,7 +773,8 @@ static size_t fio_tls_handshake(intptr_t uuid, void *udata) {
|
|
|
741
773
|
#endif
|
|
742
774
|
default:
|
|
743
775
|
FIO_LOG_DEBUG("SSL_accept/SSL_connect %p error: unknown (%d).",
|
|
744
|
-
(void *)uuid,
|
|
776
|
+
(void *)uuid,
|
|
777
|
+
ri);
|
|
745
778
|
break;
|
|
746
779
|
}
|
|
747
780
|
fio_rw_hook_replace_unsafe(uuid, &FIO_TLS_HOOKS, udata);
|
|
@@ -766,7 +799,8 @@ static size_t fio_tls_handshake(intptr_t uuid, void *udata) {
|
|
|
766
799
|
}
|
|
767
800
|
if (alpn)
|
|
768
801
|
FIO_LOG_DEBUG("setting ALPN %s for TLS client %p",
|
|
769
|
-
fio_str_data(&alpn->name),
|
|
802
|
+
fio_str_data(&alpn->name),
|
|
803
|
+
(void *)uuid);
|
|
770
804
|
alpn_select(alpn, c->uuid, c->alpn_arg);
|
|
771
805
|
}
|
|
772
806
|
}
|
|
@@ -783,7 +817,8 @@ static size_t fio_tls_handshake(intptr_t uuid, void *udata) {
|
|
|
783
817
|
#if FIO_TLS_PRINT_SECRET
|
|
784
818
|
if (FIO_LOG_LEVEL >= FIO_LOG_LEVEL_DEBUG) {
|
|
785
819
|
unsigned char buff[SSL_MAX_MASTER_KEY_LENGTH + 2];
|
|
786
|
-
size_t ret = SSL_SESSION_get_master_key(SSL_get_session(c->ssl),
|
|
820
|
+
size_t ret = SSL_SESSION_get_master_key(SSL_get_session(c->ssl),
|
|
821
|
+
buff,
|
|
787
822
|
SSL_MAX_MASTER_KEY_LENGTH + 1);
|
|
788
823
|
buff[ret] = 0;
|
|
789
824
|
unsigned char buff2[(SSL_MAX_MASTER_KEY_LENGTH + 2) << 1];
|
|
@@ -794,7 +829,8 @@ static size_t fio_tls_handshake(intptr_t uuid, void *udata) {
|
|
|
794
829
|
: ('0' + (buff[i] & 15));
|
|
795
830
|
}
|
|
796
831
|
buff2[(ret << 1)] = 0;
|
|
797
|
-
FIO_LOG_DEBUG("OpenSSL Master Key for uuid %p:\n\t\t%s",
|
|
832
|
+
FIO_LOG_DEBUG("OpenSSL Master Key for uuid %p:\n\t\t%s",
|
|
833
|
+
(void *)uuid,
|
|
798
834
|
buff2);
|
|
799
835
|
}
|
|
800
836
|
#endif
|
|
@@ -802,7 +838,9 @@ static size_t fio_tls_handshake(intptr_t uuid, void *udata) {
|
|
|
802
838
|
return status;
|
|
803
839
|
}
|
|
804
840
|
|
|
805
|
-
static ssize_t fio_tls_read4handshake(intptr_t uuid,
|
|
841
|
+
static ssize_t fio_tls_read4handshake(intptr_t uuid,
|
|
842
|
+
void *udata,
|
|
843
|
+
void *buf,
|
|
806
844
|
size_t count) {
|
|
807
845
|
// FIO_LOG_DEBUG("TLS handshake from read %p", (void *)uuid);
|
|
808
846
|
size_t s = fio_tls_handshake(uuid, udata);
|
|
@@ -814,8 +852,10 @@ static ssize_t fio_tls_read4handshake(intptr_t uuid, void *udata, void *buf,
|
|
|
814
852
|
return -1;
|
|
815
853
|
}
|
|
816
854
|
|
|
817
|
-
static ssize_t fio_tls_write4handshake(intptr_t uuid,
|
|
818
|
-
|
|
855
|
+
static ssize_t fio_tls_write4handshake(intptr_t uuid,
|
|
856
|
+
void *udata,
|
|
857
|
+
const void *buf,
|
|
858
|
+
size_t count) {
|
|
819
859
|
// FIO_LOG_DEBUG("TLS handshake from write %p", (void *)uuid);
|
|
820
860
|
size_t s = fio_tls_handshake(uuid, udata);
|
|
821
861
|
if (s == FIO_TLS_HANDSHAKE_OK)
|
|
@@ -845,8 +885,10 @@ static fio_rw_hook_s FIO_TLS_HANDSHAKE_HOOKS = {
|
|
|
845
885
|
.flush = fio_tls_flush4handshake,
|
|
846
886
|
.cleanup = fio_tls_cleanup,
|
|
847
887
|
};
|
|
848
|
-
static inline void fio_tls_attach2uuid(intptr_t uuid,
|
|
849
|
-
|
|
888
|
+
static inline void fio_tls_attach2uuid(intptr_t uuid,
|
|
889
|
+
fio_tls_s *tls,
|
|
890
|
+
void *udata,
|
|
891
|
+
uint8_t is_server) {
|
|
850
892
|
fio_atomic_add(&tls->ref, 1);
|
|
851
893
|
/* create SSL connection context from global context */
|
|
852
894
|
fio_tls_connection_s *c = malloc(sizeof(*c));
|
|
@@ -891,8 +933,10 @@ SSL/TLS API implementation - this can be pretty much used as is...
|
|
|
891
933
|
* Creates a new SSL/TLS context / settings object with a default certificate
|
|
892
934
|
* (if any).
|
|
893
935
|
*/
|
|
894
|
-
fio_tls_s *FIO_TLS_WEAK fio_tls_new(const char *server_name,
|
|
895
|
-
const char *
|
|
936
|
+
fio_tls_s *FIO_TLS_WEAK fio_tls_new(const char *server_name,
|
|
937
|
+
const char *cert,
|
|
938
|
+
const char *key,
|
|
939
|
+
const char *pk_password) {
|
|
896
940
|
REQUIRE_LIBRARY();
|
|
897
941
|
fio_tls_s *tls = calloc(sizeof(*tls), 1);
|
|
898
942
|
tls->ref = 1;
|
|
@@ -903,8 +947,10 @@ fio_tls_s *FIO_TLS_WEAK fio_tls_new(const char *server_name, const char *cert,
|
|
|
903
947
|
/**
|
|
904
948
|
* Adds a certificate a new SSL/TLS context / settings object.
|
|
905
949
|
*/
|
|
906
|
-
void FIO_TLS_WEAK fio_tls_cert_add(fio_tls_s *tls,
|
|
907
|
-
const char *
|
|
950
|
+
void FIO_TLS_WEAK fio_tls_cert_add(fio_tls_s *tls,
|
|
951
|
+
const char *server_name,
|
|
952
|
+
const char *cert,
|
|
953
|
+
const char *key,
|
|
908
954
|
const char *pk_password) {
|
|
909
955
|
REQUIRE_LIBRARY();
|
|
910
956
|
cert_s c = {
|
|
@@ -929,7 +975,8 @@ void FIO_TLS_WEAK fio_tls_cert_add(fio_tls_s *tls, const char *server_name,
|
|
|
929
975
|
return;
|
|
930
976
|
file_missing:
|
|
931
977
|
FIO_LOG_FATAL("TLS certificate file missing for either %s or %s or both.",
|
|
932
|
-
key,
|
|
978
|
+
key,
|
|
979
|
+
cert);
|
|
933
980
|
exit(-1);
|
|
934
981
|
}
|
|
935
982
|
|
|
@@ -950,10 +997,13 @@ file_missing:
|
|
|
950
997
|
* Except for the `tls` and `protocol_name` arguments, all arguments can be
|
|
951
998
|
* NULL.
|
|
952
999
|
*/
|
|
953
|
-
void FIO_TLS_WEAK fio_tls_alpn_add(
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
1000
|
+
void FIO_TLS_WEAK fio_tls_alpn_add(fio_tls_s *tls,
|
|
1001
|
+
const char *protocol_name,
|
|
1002
|
+
void (*on_selected)(intptr_t uuid,
|
|
1003
|
+
void *udata_connection,
|
|
1004
|
+
void *udata_tls),
|
|
1005
|
+
void *udata_tls,
|
|
1006
|
+
void (*on_cleanup)(void *udata_tls)) {
|
|
957
1007
|
REQUIRE_LIBRARY();
|
|
958
1008
|
alpn_add(tls, protocol_name, on_selected, udata_tls, on_cleanup);
|
|
959
1009
|
fio_tls_build_context(tls);
|
data/ext/iodine/fiobj_data.c
CHANGED
|
@@ -63,6 +63,17 @@ Object required VTable and functions
|
|
|
63
63
|
} \
|
|
64
64
|
} while (0)
|
|
65
65
|
|
|
66
|
+
static inline int64_t fiobj_data_get_fd_size(const FIOBJ o) {
|
|
67
|
+
struct stat stat;
|
|
68
|
+
retry:
|
|
69
|
+
if (fstat(obj2io(o)->fd, &stat)) {
|
|
70
|
+
if (errno == EINTR)
|
|
71
|
+
goto retry;
|
|
72
|
+
return -1;
|
|
73
|
+
}
|
|
74
|
+
return stat.st_size;
|
|
75
|
+
}
|
|
76
|
+
|
|
66
77
|
static void fiobj_data_copy_buffer(FIOBJ o) {
|
|
67
78
|
obj2io(o)->capa = (((obj2io(o)->len) >> 12) + 1) << 12;
|
|
68
79
|
void *tmp = fio_malloc(obj2io(o)->capa);
|
|
@@ -145,17 +156,6 @@ static inline void fiobj_data_pre_write(FIOBJ o, uintptr_t length) {
|
|
|
145
156
|
REQUIRE_MEM(obj2io(o)->buffer);
|
|
146
157
|
}
|
|
147
158
|
|
|
148
|
-
static inline int64_t fiobj_data_get_fd_size(const FIOBJ o) {
|
|
149
|
-
struct stat stat;
|
|
150
|
-
retry:
|
|
151
|
-
if (fstat(obj2io(o)->fd, &stat)) {
|
|
152
|
-
if (errno == EINTR)
|
|
153
|
-
goto retry;
|
|
154
|
-
return -1;
|
|
155
|
-
}
|
|
156
|
-
return stat.st_size;
|
|
157
|
-
}
|
|
158
|
-
|
|
159
159
|
static FIOBJ fiobj_data_alloc(void *buffer, int fd) {
|
|
160
160
|
fiobj_data_s *io = fio_malloc(sizeof(*io));
|
|
161
161
|
REQUIRE_MEM(io);
|
|
@@ -963,6 +963,7 @@ intptr_t fiobj_data_write(FIOBJ io, void *buffer, uintptr_t length) {
|
|
|
963
963
|
/* Unslice slices */
|
|
964
964
|
if (obj2io(io)->fd == -2)
|
|
965
965
|
fiobj_data_assert_dynamic(io);
|
|
966
|
+
|
|
966
967
|
if (obj2io(io)->fd == -1) {
|
|
967
968
|
/* String Code */
|
|
968
969
|
fiobj_data_pre_write(io, length + 1);
|
|
@@ -971,6 +972,7 @@ intptr_t fiobj_data_write(FIOBJ io, void *buffer, uintptr_t length) {
|
|
|
971
972
|
obj2io(io)->buffer[obj2io(io)->len] = 0;
|
|
972
973
|
return length;
|
|
973
974
|
}
|
|
975
|
+
|
|
974
976
|
/* File Code */
|
|
975
977
|
return pwrite(obj2io(io)->fd, buffer, length, fiobj_data_get_fd_size(io));
|
|
976
978
|
}
|
data/ext/iodine/fiobj_str.h
CHANGED
|
@@ -38,7 +38,7 @@ static inline __attribute__((unused)) FIOBJ fiobj_str_copy(FIOBJ src) {
|
|
|
38
38
|
/**
|
|
39
39
|
* Creates a String object. Remember to use `fiobj_free`.
|
|
40
40
|
*
|
|
41
|
-
* It's possible to wrap a
|
|
41
|
+
* It's possible to wrap a previously allocated memory block in a FIOBJ String
|
|
42
42
|
* object, as long as it was allocated using `fio_malloc`.
|
|
43
43
|
*
|
|
44
44
|
* The ownership of the memory indicated by `str` will "move" to the object and
|
data/ext/iodine/fiobject.h
CHANGED
|
@@ -147,10 +147,10 @@ FIO_INLINE double fiobj_obj2float(const FIOBJ obj);
|
|
|
147
147
|
/**
|
|
148
148
|
* Returns a C String (NUL terminated) using the `fio_str_info_s` data type.
|
|
149
149
|
*
|
|
150
|
-
* The
|
|
151
|
-
* a terminating NUL.
|
|
150
|
+
* The String is binary safe and might contain NUL bytes in the middle as well
|
|
151
|
+
* as a terminating NUL.
|
|
152
152
|
*
|
|
153
|
-
* If a
|
|
153
|
+
* If a Number or a Float are passed to the function, they
|
|
154
154
|
* will be parsed as a *temporary*, thread-safe, String.
|
|
155
155
|
*
|
|
156
156
|
* Numbers will be represented in base 10 numerical data.
|
|
@@ -270,7 +270,8 @@ FIO_INLINE size_t fiobj_type_is(FIOBJ o, fiobj_type_enum type) {
|
|
|
270
270
|
switch (type) {
|
|
271
271
|
case FIOBJ_T_NUMBER:
|
|
272
272
|
return (o & FIOBJECT_NUMBER_FLAG) ||
|
|
273
|
-
((
|
|
273
|
+
(o && !(o & FIOBJECT_PRIMITIVE_FLAG) &&
|
|
274
|
+
((fiobj_type_enum *)o)[0] == FIOBJ_T_NUMBER);
|
|
274
275
|
case FIOBJ_T_NULL:
|
|
275
276
|
return !o || o == fiobj_null();
|
|
276
277
|
case FIOBJ_T_TRUE:
|
data/ext/iodine/http1.c
CHANGED
|
@@ -45,6 +45,8 @@ inline static void h1_reset(http1pr_s *p) { p->header_size = 0; }
|
|
|
45
45
|
#define http1_pr2handle(pr) (((http1pr_s *)(pr))->request)
|
|
46
46
|
#define handle2pr(h) ((http1pr_s *)h->private_data.flag)
|
|
47
47
|
|
|
48
|
+
static fio_str_info_s http1pr_status2str(uintptr_t status);
|
|
49
|
+
|
|
48
50
|
/* cleanup an HTTP/1.1 handler object */
|
|
49
51
|
static inline void http1_after_finish(http_s *h) {
|
|
50
52
|
http1pr_s *p = handle2pr(h);
|
|
@@ -110,10 +112,8 @@ static FIOBJ headers2str(http_s *h, uintptr_t padding) {
|
|
|
110
112
|
http1pr_s *p = handle2pr(h);
|
|
111
113
|
|
|
112
114
|
if (p->is_client == 0) {
|
|
113
|
-
fio_str_info_s t =
|
|
114
|
-
fiobj_str_write(w.dest, "HTTP/1.1 ", 9);
|
|
115
|
+
fio_str_info_s t = http1pr_status2str(h->status);
|
|
115
116
|
fiobj_str_write(w.dest, t.data, t.len);
|
|
116
|
-
fiobj_str_write(w.dest, "\r\n", 2);
|
|
117
117
|
FIOBJ tmp = fiobj_hash_get2(h->private_data.out_headers, connection_hash);
|
|
118
118
|
if (tmp) {
|
|
119
119
|
t = fiobj_obj2cstr(tmp);
|
|
@@ -787,8 +787,7 @@ fio_protocol_s *http1_new(uintptr_t uuid, http_settings_s *settings,
|
|
|
787
787
|
if (unread_data && unread_length > HTTP_MAX_HEADER_LENGTH)
|
|
788
788
|
return NULL;
|
|
789
789
|
http1pr_s *p = fio_malloc(sizeof(*p) + HTTP_MAX_HEADER_LENGTH);
|
|
790
|
-
// FIO_LOG_DEBUG("Allocated HTTP/1.1 protocol %p
|
|
791
|
-
// (int)fio_uuid2fd(uuid), (void *)p);
|
|
790
|
+
// FIO_LOG_DEBUG("Allocated HTTP/1.1 protocol at. %p", (void *)p);
|
|
792
791
|
FIO_ASSERT_ALLOC(p);
|
|
793
792
|
*p = (http1pr_s){
|
|
794
793
|
.p.protocol =
|
|
@@ -819,7 +818,93 @@ void http1_destroy(fio_protocol_s *pr) {
|
|
|
819
818
|
http1pr_s *p = (http1pr_s *)pr;
|
|
820
819
|
http1_pr2handle(p).status = 0;
|
|
821
820
|
http_s_destroy(&http1_pr2handle(p), 0);
|
|
822
|
-
// FIO_LOG_DEBUG("Deallocating HTTP/1.1 protocol %p(%d)=>%p", (void
|
|
823
|
-
// *)p->p.uuid, (int)fio_uuid2fd(p->p.uuid), (void *)p);
|
|
824
821
|
fio_free(p); // occasional Windows crash bug
|
|
822
|
+
// FIO_LOG_DEBUG("Deallocated HTTP/1.1 protocol at. %p", (void *)p);
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
/* *****************************************************************************
|
|
826
|
+
Protocol Data
|
|
827
|
+
***************************************************************************** */
|
|
828
|
+
|
|
829
|
+
// clang-format off
|
|
830
|
+
#define HTTP_SET_STATUS_STR(status, str) [((status)-100)] = { .data = (char*)("HTTP/1.1 " #status " " str "\r\n"), .len = (sizeof("HTTP/1.1 " #status " " str "\r\n") - 1) }
|
|
831
|
+
// #undef HTTP_SET_STATUS_STR
|
|
832
|
+
// clang-format on
|
|
833
|
+
|
|
834
|
+
static fio_str_info_s http1pr_status2str(uintptr_t status) {
|
|
835
|
+
static fio_str_info_s status2str[] = {
|
|
836
|
+
HTTP_SET_STATUS_STR(100, "Continue"),
|
|
837
|
+
HTTP_SET_STATUS_STR(101, "Switching Protocols"),
|
|
838
|
+
HTTP_SET_STATUS_STR(102, "Processing"),
|
|
839
|
+
HTTP_SET_STATUS_STR(103, "Early Hints"),
|
|
840
|
+
HTTP_SET_STATUS_STR(200, "OK"),
|
|
841
|
+
HTTP_SET_STATUS_STR(201, "Created"),
|
|
842
|
+
HTTP_SET_STATUS_STR(202, "Accepted"),
|
|
843
|
+
HTTP_SET_STATUS_STR(203, "Non-Authoritative Information"),
|
|
844
|
+
HTTP_SET_STATUS_STR(204, "No Content"),
|
|
845
|
+
HTTP_SET_STATUS_STR(205, "Reset Content"),
|
|
846
|
+
HTTP_SET_STATUS_STR(206, "Partial Content"),
|
|
847
|
+
HTTP_SET_STATUS_STR(207, "Multi-Status"),
|
|
848
|
+
HTTP_SET_STATUS_STR(208, "Already Reported"),
|
|
849
|
+
HTTP_SET_STATUS_STR(226, "IM Used"),
|
|
850
|
+
HTTP_SET_STATUS_STR(300, "Multiple Choices"),
|
|
851
|
+
HTTP_SET_STATUS_STR(301, "Moved Permanently"),
|
|
852
|
+
HTTP_SET_STATUS_STR(302, "Found"),
|
|
853
|
+
HTTP_SET_STATUS_STR(303, "See Other"),
|
|
854
|
+
HTTP_SET_STATUS_STR(304, "Not Modified"),
|
|
855
|
+
HTTP_SET_STATUS_STR(305, "Use Proxy"),
|
|
856
|
+
HTTP_SET_STATUS_STR(306, "(Unused), "),
|
|
857
|
+
HTTP_SET_STATUS_STR(307, "Temporary Redirect"),
|
|
858
|
+
HTTP_SET_STATUS_STR(308, "Permanent Redirect"),
|
|
859
|
+
HTTP_SET_STATUS_STR(400, "Bad Request"),
|
|
860
|
+
HTTP_SET_STATUS_STR(403, "Forbidden"),
|
|
861
|
+
HTTP_SET_STATUS_STR(404, "Not Found"),
|
|
862
|
+
HTTP_SET_STATUS_STR(401, "Unauthorized"),
|
|
863
|
+
HTTP_SET_STATUS_STR(402, "Payment Required"),
|
|
864
|
+
HTTP_SET_STATUS_STR(405, "Method Not Allowed"),
|
|
865
|
+
HTTP_SET_STATUS_STR(406, "Not Acceptable"),
|
|
866
|
+
HTTP_SET_STATUS_STR(407, "Proxy Authentication Required"),
|
|
867
|
+
HTTP_SET_STATUS_STR(408, "Request Timeout"),
|
|
868
|
+
HTTP_SET_STATUS_STR(409, "Conflict"),
|
|
869
|
+
HTTP_SET_STATUS_STR(410, "Gone"),
|
|
870
|
+
HTTP_SET_STATUS_STR(411, "Length Required"),
|
|
871
|
+
HTTP_SET_STATUS_STR(412, "Precondition Failed"),
|
|
872
|
+
HTTP_SET_STATUS_STR(413, "Payload Too Large"),
|
|
873
|
+
HTTP_SET_STATUS_STR(414, "URI Too Long"),
|
|
874
|
+
HTTP_SET_STATUS_STR(415, "Unsupported Media Type"),
|
|
875
|
+
HTTP_SET_STATUS_STR(416, "Range Not Satisfiable"),
|
|
876
|
+
HTTP_SET_STATUS_STR(417, "Expectation Failed"),
|
|
877
|
+
HTTP_SET_STATUS_STR(421, "Misdirected Request"),
|
|
878
|
+
HTTP_SET_STATUS_STR(422, "Unprocessable Entity"),
|
|
879
|
+
HTTP_SET_STATUS_STR(423, "Locked"),
|
|
880
|
+
HTTP_SET_STATUS_STR(424, "Failed Dependency"),
|
|
881
|
+
HTTP_SET_STATUS_STR(425, "Unassigned"),
|
|
882
|
+
HTTP_SET_STATUS_STR(426, "Upgrade Required"),
|
|
883
|
+
HTTP_SET_STATUS_STR(427, "Unassigned"),
|
|
884
|
+
HTTP_SET_STATUS_STR(428, "Precondition Required"),
|
|
885
|
+
HTTP_SET_STATUS_STR(429, "Too Many Requests"),
|
|
886
|
+
HTTP_SET_STATUS_STR(430, "Unassigned"),
|
|
887
|
+
HTTP_SET_STATUS_STR(431, "Request Header Fields Too Large"),
|
|
888
|
+
HTTP_SET_STATUS_STR(500, "Internal Server Error"),
|
|
889
|
+
HTTP_SET_STATUS_STR(501, "Not Implemented"),
|
|
890
|
+
HTTP_SET_STATUS_STR(502, "Bad Gateway"),
|
|
891
|
+
HTTP_SET_STATUS_STR(503, "Service Unavailable"),
|
|
892
|
+
HTTP_SET_STATUS_STR(504, "Gateway Timeout"),
|
|
893
|
+
HTTP_SET_STATUS_STR(505, "HTTP Version Not Supported"),
|
|
894
|
+
HTTP_SET_STATUS_STR(506, "Variant Also Negotiates"),
|
|
895
|
+
HTTP_SET_STATUS_STR(507, "Insufficient Storage"),
|
|
896
|
+
HTTP_SET_STATUS_STR(508, "Loop Detected"),
|
|
897
|
+
HTTP_SET_STATUS_STR(509, "Unassigned"),
|
|
898
|
+
HTTP_SET_STATUS_STR(510, "Not Extended"),
|
|
899
|
+
HTTP_SET_STATUS_STR(511, "Network Authentication Required"),
|
|
900
|
+
};
|
|
901
|
+
fio_str_info_s ret = (fio_str_info_s){.len = 0, .data = NULL};
|
|
902
|
+
if (status >= 100 &&
|
|
903
|
+
(status - 100) < sizeof(status2str) / sizeof(status2str[0]))
|
|
904
|
+
ret = status2str[status - 100];
|
|
905
|
+
if (!ret.data) {
|
|
906
|
+
ret = status2str[400];
|
|
907
|
+
}
|
|
908
|
+
return ret;
|
|
825
909
|
}
|
|
910
|
+
#undef HTTP_SET_STATUS_STR
|