Codebase list erlang-p1-tls / 2331a48
Imported Upstream version 1.0.3 Philipp Huebner 7 years ago
4 changed file(s) with 114 addition(s) and 38 deletion(s). Raw diff Collapse all Expand all
0 # Version 1.0.3
1
2 * Do not call internal erlang erl_exit function (Christophe Romain)
3
4 # Version 1.0.2
5
6 * Add support for cafile option (Evgeny Khramtsov)
7 * Better error checks (Michael Santos)
8
09 # Version 1.0.1
110
211 * Build improve, remove check on Erlang version for better build chain compliance (Mickaël Rémond)
5252
5353 #define CIPHERS "DEFAULT:!EXPORT:!LOW:!RC4:!SSLv2"
5454
55 /* Wrappers around driver_alloc() that check */
56 /* for OOM. */
57 void erl_exit(int n, char* v, ...) { abort(); }
58 void *ftls_alloc(ErlDrvSizeT size);
59 void *ftls_realloc(void *ptr, ErlDrvSizeT size);
60 ErlDrvBinary *ftls_alloc_binary(ErlDrvSizeT size);
61 ErlDrvBinary *ftls_realloc_binary(ErlDrvBinary *bin, ErlDrvSizeT size);
62
63 void *ftls_alloc(ErlDrvSizeT size) {
64 void *p = driver_alloc(size);
65 if (p == NULL) {
66 erl_exit(1, "fast_tls: Can't allocate %lu bytes of memory\n", size);
67 }
68 return p;
69 }
70
71 void *ftls_realloc(void *ptr, ErlDrvSizeT size) {
72 void *p = driver_realloc(ptr, size);
73 if (p == NULL) {
74 erl_exit(1, "fast_tls: Can't reallocate %lu bytes of memory\n", size);
75 }
76 return p;
77 }
78
79 ErlDrvBinary *ftls_alloc_binary(ErlDrvSizeT size) {
80 ErlDrvBinary *p = driver_alloc_binary(size);
81 if (p == NULL) {
82 erl_exit(1, "fast_tls: Can't allocate %lu binary\n", size);
83 }
84 return p;
85 }
86
87 ErlDrvBinary *ftls_realloc_binary(ErlDrvBinary *bin, ErlDrvSizeT size) {
88 ErlDrvBinary *p = driver_realloc_binary(bin, size);
89 if (p == NULL) {
90 erl_exit(1, "fast_tls: Can't reallocate %lu binary\n", size);
91 }
92 return p;
93 }
94
5595 /**
5696 * Prepare the SSL options flag.
5797 **/
108148 char *key;
109149 time_t key_mtime;
110150 time_t dh_mtime;
151 time_t ca_mtime;
111152 SSL_CTX *ssl_ctx;
112153 struct bucket *next;
113154 };
125166 {
126167 size_t size = 1 << (MIN_LEVEL + 1);
127168 size_t i;
128 ht.buckets = (struct bucket **)driver_alloc(sizeof(struct bucket *) * size);
169 ht.buckets = ftls_alloc(sizeof(struct bucket *) * size);
129170 ht.split = 0;
130171 ht.level = MIN_LEVEL;
131172 for (i = 0; i < size; i++)
134175 }
135176
136177 static void hash_table_insert(char *key, time_t key_mtime, time_t dh_mtime,
137 SSL_CTX *ssl_ctx)
178 time_t ca_mtime, SSL_CTX *ssl_ctx)
138179 {
139180 int level, split;
140181 uint32_t hash = str_hash(key);
155196 if (el->hash == hash && strcmp(el->key, key) == 0) {
156197 el->key_mtime = key_mtime;
157198 el->dh_mtime = dh_mtime;
199 el->ca_mtime = ca_mtime;
158200 if (el->ssl_ctx != NULL)
159201 SSL_CTX_free(el->ssl_ctx);
160202 el->ssl_ctx = ssl_ctx;
167209 if (ht.buckets[bucket] != NULL)
168210 do_split = !0;
169211
170 new_bucket_el = (struct bucket *)driver_alloc(sizeof(struct bucket));
212 new_bucket_el = ftls_alloc(sizeof(struct bucket));
171213 new_bucket_el->hash = hash;
172 new_bucket_el->key = (char *)driver_alloc(strlen(key) + 1);
214 new_bucket_el->key = ftls_alloc(strlen(key) + 1);
173215 strcpy(new_bucket_el->key, key);
174216 new_bucket_el->key_mtime = key_mtime;
175217 new_bucket_el->dh_mtime = dh_mtime;
218 new_bucket_el->ca_mtime = ca_mtime;
176219 new_bucket_el->ssl_ctx = ssl_ctx;
177220 new_bucket_el->next = ht.buckets[bucket];
178221 ht.buckets[bucket] = new_bucket_el;
200243 size = 1 << (level + 1);
201244 ht.split = split;
202245 ht.level = level;
203 ht.buckets = (struct bucket **)
204 driver_realloc(ht.buckets, sizeof(struct bucket *) * size);
246 ht.buckets = ftls_realloc(ht.buckets, sizeof(struct bucket *) * size);
205247 for (i = 1 << level; i < size; i++)
206248 ht.buckets[i] = NULL;
207249 } else
210252 }
211253
212254 static SSL_CTX *hash_table_lookup(char *key, time_t *key_mtime,
213 time_t *dh_mtime)
255 time_t *dh_mtime, time_t *ca_mtime)
214256 {
215257 int level, split;
216258 uint32_t hash = str_hash(key);
229271 if (el->hash == hash && strcmp(el->key, key) == 0) {
230272 *key_mtime = el->key_mtime;
231273 *dh_mtime = el->dh_mtime;
274 *ca_mtime = el->ca_mtime;
232275 return el->ssl_ctx;
233276 }
234277 el = el->next;
240283
241284 static ErlDrvData tls_drv_start(ErlDrvPort port, char *buff)
242285 {
243 tls_data *d = (tls_data *)driver_alloc(sizeof(tls_data));
286 tls_data *d = ftls_alloc(sizeof(tls_data));
244287 d->port = port;
245288 d->bio_read = NULL;
246289 d->bio_write = NULL;
446489 unsigned long error_code = ERR_get_error(); \
447490 char *error_string = error_code ? \
448491 ERR_error_string(error_code, NULL) : \
449 NULL; \
450 int error_string_length = error_string ? \
451 strlen(error_string) : 0; \
492 ""; \
493 int error_string_length = strlen(error_string); \
452494 if (error_code) \
453495 rlen = errstrlen + error_string_length + 3; \
454496 else \
455497 rlen = errstrlen + 1; \
456 b = driver_alloc_binary(rlen); \
498 b = ftls_alloc_binary(rlen); \
457499 b->orig_bytes[0] = 1; \
458500 strncpy(b->orig_bytes + 1, errstr, errstrlen); \
459501 if (error_code) { \
525567 case SET_CERTIFICATE_FILE_CONNECT: {
526568 time_t key_mtime = 0;
527569 time_t dh_mtime = 0;
570 time_t ca_mtime = 0;
528571 char *key_file = buf;
529572 size_t key_file_len = strlen(key_file);
530573 char *ciphers = key_file + key_file_len + 1;
533576 size_t protocol_options_len = strlen(protocol_options);
534577 char *dh_file = protocol_options + protocol_options_len + 1;
535578 size_t dh_file_len = strlen(dh_file);
536 char *hash_key = (char *)driver_alloc(key_file_len +
579 char *ca_file = dh_file + dh_file_len + 1;
580 size_t ca_file_len = strlen(ca_file);
581 char *hash_key = ftls_alloc(key_file_len +
537582 ciphers_len +
538583 protocol_options_len +
539 dh_file_len + 1);
584 dh_file_len +
585 ca_file_len + 1);
540586 long options = 0L;
541587
542588 if (protocol_options_len != 0) {
544590 char *popts = po;
545591 char *strtok_buf;
546592
593 if (!po) {
594 erl_exit(1, "fast_tls: strdup failed");
595 }
596
547597 while ((po = strtok_r(po, delim, &strtok_buf)) != NULL) {
548598 set_option_flag(po, &options);
549599 po = NULL;
552602 free(popts);
553603 }
554604
555 sprintf(hash_key, "%s%s%s%s", key_file, ciphers, protocol_options,
556 dh_file);
557 SSL_CTX *ssl_ctx = hash_table_lookup(hash_key, &key_mtime, &dh_mtime);
605 sprintf(hash_key, "%s%s%s%s%s", key_file, ciphers, protocol_options,
606 dh_file, ca_file);
607 SSL_CTX *ssl_ctx = hash_table_lookup(hash_key, &key_mtime, &dh_mtime, &ca_mtime);
558608
559609 if (dh_file_len == 0)
560610 dh_file = NULL;
561611
612 if (ca_file_len == 0)
613 ca_file = NULL;
614
562615 if (is_modified(key_file, &key_mtime) ||
563616 is_modified(dh_file, &dh_mtime) ||
617 is_modified(ca_file, &ca_mtime) ||
564618 ssl_ctx == NULL)
565619 {
566620 SSL_CTX *ctx;
567621
568 hash_table_insert(hash_key, key_mtime, dh_mtime, NULL);
622 hash_table_insert(hash_key, key_mtime, dh_mtime, ca_mtime, NULL);
569623
570624 ctx = SSL_CTX_new(SSLv23_method());
571625 die_unless(ctx, "SSL_CTX_new failed");
592646 #endif
593647
594648 SSL_CTX_set_session_cache_mode(ctx, SSL_SESS_CACHE_OFF);
595 SSL_CTX_set_default_verify_paths(ctx);
649 if (ca_file)
650 SSL_CTX_load_verify_locations(ctx, ca_file, NULL);
651 else
652 SSL_CTX_set_default_verify_paths(ctx);
596653 #ifdef SSL_MODE_RELEASE_BUFFERS
597654 SSL_CTX_set_mode(ctx, SSL_MODE_RELEASE_BUFFERS);
598655 #endif
610667 SSL_CTX_set_info_callback(ctx, &ssl_info_callback);
611668
612669 ssl_ctx = ctx;
613 hash_table_insert(hash_key, key_mtime, dh_mtime, ssl_ctx);
670 hash_table_insert(hash_key, key_mtime, dh_mtime, ca_mtime, ssl_ctx);
614671 }
615672
616673 driver_free(hash_key);
630687
631688 d->bio_read = BIO_new(BIO_s_mem());
632689 d->bio_write = BIO_new(BIO_s_mem());
690
691 die_unless(d->bio_read, "BIO_new failed");
692 die_unless(d->bio_write, "BIO_new failed");
633693
634694 SSL_set_bio(d->ssl, d->bio_read, d->bio_write);
635695
660720 if (d->send_buffer2 == NULL) {
661721 d->send_buffer2_len = len;
662722 d->send_buffer2_size = len;
663 d->send_buffer2 = driver_alloc(d->send_buffer2_size);
723 d->send_buffer2 = ftls_alloc(d->send_buffer2_size);
664724 memcpy(d->send_buffer2, buf, len);
665725 } else {
666726 if (d->send_buffer2_size <
669729 d->send_buffer2_len + len) {
670730 d->send_buffer2_size *= 2;
671731 }
672 d->send_buffer2 = driver_realloc(d->send_buffer2,
732 d->send_buffer2 = ftls_realloc(d->send_buffer2,
673733 d->send_buffer2_size);
674734 }
675735 memcpy(d->send_buffer2 + d->send_buffer2_len,
684744 res == SSL_ERROR_WANT_WRITE) {
685745 d->send_buffer_len = len;
686746 d->send_buffer_size = len;
687 d->send_buffer = driver_alloc(d->send_buffer_size);
747 d->send_buffer = ftls_alloc(d->send_buffer_size);
688748 memcpy(d->send_buffer, buf, len);
689749 } else {
690750 die_unless(0, "SSL_write failed");
696756 case GET_ENCRYPTED_OUTPUT:
697757 die_unless(d->ssl, "SSL not initialized");
698758 size = BIO_ctrl_pending(d->bio_write) + 1;
699 b = driver_alloc_binary(size);
759 b = ftls_alloc_binary(size);
700760 b->orig_bytes[0] = 0;
701761 BIO_read(d->bio_write, b->orig_bytes + 1, size - 1);
702762 *rbuf = (char *)b;
703763 return size;
704764 case GET_DECRYPTED_INPUT: {
705765 int retcode = 0;
766 die_unless(d->ssl, "SSL not initialized");
706767 if (!SSL_is_init_finished(d->ssl))
707768 {
708769 retcode = 2;
738799 }
739800 size = BUF_SIZE + 1;
740801 rlen = 1;
741 b = driver_alloc_binary(size);
802 b = ftls_alloc_binary(size);
742803 b->orig_bytes[0] = retcode;
743804
744805 res = 0;
753814 rlen += res;
754815 if (size - rlen < BUF_SIZE) {
755816 size *= 2;
756 b = driver_realloc_binary(b, size);
817 b = ftls_realloc_binary(b, size);
757818 }
758819 }
759820
761822 char *error = "client renegotiations forbidden";
762823 int error_len = strlen(error);
763824 rlen = error_len + 1;
764 b = driver_alloc_binary(rlen);
825 b = ftls_alloc_binary(rlen);
765826 b->orig_bytes[0] = 1;
766827 strncpy(b->orig_bytes + 1, error, error_len);
767828 *rbuf = (char *)b;
779840 }
780841 // TODO
781842 }
782 b = driver_realloc_binary(b, rlen);
843 b = ftls_realloc_binary(b, rlen);
783844 *rbuf = (char *)b;
784845 return rlen;
785846 } else {
786 b = driver_alloc_binary(1);
847 b = ftls_alloc_binary(1);
787848 b->orig_bytes[0] = 2;
788849 *rbuf = (char *)b;
789850 return 1;
794855 cert = SSL_get_peer_certificate(d->ssl);
795856 if (cert == NULL)
796857 {
797 b = driver_alloc_binary(1);
858 b = ftls_alloc_binary(1);
798859 b->orig_bytes[0] = 1;
799860 *rbuf = (char *)b;
800861 return 1;
801862 } else {
802863 unsigned char *tmp_buf;
803 rlen = i2d_X509(cert, NULL);
804 if (rlen >= 0)
864 int encode_len = i2d_X509(cert, NULL);
865 if (encode_len >= 0)
805866 {
806 rlen++;
807 b = driver_alloc_binary(rlen);
867 rlen = encode_len + 1;
868 b = ftls_alloc_binary(rlen);
808869 b->orig_bytes[0] = 0;
809870 tmp_buf = (unsigned char *)&b->orig_bytes[1];
810871 i2d_X509(cert, &tmp_buf);
816877 }
817878 break;
818879 case GET_VERIFY_RESULT:
819 b = driver_alloc_binary(1);
880 b = ftls_alloc_binary(1);
820881 b->orig_bytes[0] = SSL_get_verify_result(d->ssl);
821882 *rbuf = (char *)b;
822883 return 1;
823884 break;
824885 }
825886
826 b = driver_alloc_binary(1);
887 b = ftls_alloc_binary(1);
827888 b->orig_bytes[0] = 0;
828889 *rbuf = (char *)b;
829890 return 1;
2222
2323 {application, fast_tls,
2424 [{description, "TLS / SSL OpenSSL-based native driver for Erlang / Elixir"},
25 {vsn, "1.0.1"},
25 {vsn, "1.0.3"},
2626 {modules, []},
2727 {registered, []},
2828 {applications, [kernel, stdlib]},
141141 false ->
142142 <<>>
143143 end,
144 CAFile = case lists:keysearch(cafile, 1, Options) of
145 {value, {cafile, CF}} ->
146 iolist_to_binary(CF);
147 false ->
148 <<>>
149 end,
144150 CertFile1 = iolist_to_binary(CertFile),
145151 case catch port_control(Port, Command bor Flags,
146152 <<CertFile1/binary, 0, Ciphers/binary,
147153 0, ProtocolOpts/binary, 0, DHFile/binary,
148 0>>)
154 0, CAFile/binary, 0>>)
149155 of
150156 {'EXIT', {badarg, _}} -> {error, einval};
151157 <<0>> ->