visaljs 0.0.9 → 0.0.11

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.
Files changed (232) hide show
  1. package/README.md +12 -4
  2. package/THIRD_PARTY_LICENSES +31 -1
  3. package/cli.js +3745 -890
  4. package/node/include/js_node.h +12 -1
  5. package/node/prelude/_http_common.js +29 -0
  6. package/node/prelude/async_hooks.js +50 -11
  7. package/node/prelude/child_process.js +31 -4
  8. package/node/prelude/console.js +311 -143
  9. package/node/prelude/crypto.js +6 -4
  10. package/node/prelude/dgram.js +1169 -0
  11. package/node/prelude/diagnostics_channel.js +3 -1
  12. package/node/prelude/dns.js +250 -45
  13. package/node/prelude/dns_promises.js +8 -2
  14. package/node/prelude/fs_promises.js +9 -1
  15. package/node/prelude/http.js +405 -94
  16. package/node/prelude/https.js +13 -4
  17. package/node/prelude/internal/console_class.js +7 -0
  18. package/node/prelude/internal/console_global.js +25 -0
  19. package/node/prelude/internal/crypto/key_encryption.js +217 -0
  20. package/node/prelude/internal/crypto/keys.js +161 -26
  21. package/node/prelude/internal/crypto/random.js +24 -0
  22. package/node/prelude/internal/crypto/util.js +2 -1
  23. package/node/prelude/internal/crypto_x509.js +161 -0
  24. package/node/prelude/internal/dns_classes.js +6 -0
  25. package/node/prelude/internal/dns_resolver.js +371 -0
  26. package/node/prelude/internal/errors.js +9 -0
  27. package/node/prelude/internal/events_on.js +82 -37
  28. package/node/prelude/internal/features.js +8 -4
  29. package/node/prelude/internal/fs_filehandle.js +10 -4
  30. package/node/prelude/internal/http_chars.ts +22 -0
  31. package/node/prelude/internal/perf_histogram.js +1 -1
  32. package/node/prelude/internal/process_more.js +32 -17
  33. package/node/prelude/internal/process_signals.js +8 -2
  34. package/node/prelude/internal/punycode.ts +163 -0
  35. package/node/prelude/internal/readline.js +648 -274
  36. package/node/prelude/internal/readline_editor.js +1240 -0
  37. package/node/prelude/internal/string_width.js +43 -0
  38. package/node/prelude/internal/tls/common.js +145 -33
  39. package/node/prelude/internal/tls/wrap.js +182 -49
  40. package/node/prelude/internal/tls/x509.js +4 -1
  41. package/node/prelude/internal/udp.js +177 -0
  42. package/node/prelude/net.js +30 -14
  43. package/node/prelude/os.js +24 -6
  44. package/node/prelude/perf_hooks.js +37 -2
  45. package/node/prelude/punycode.js +2 -130
  46. package/node/prelude/readline.js +113 -4
  47. package/node/prelude/readline_promises.js +56 -32
  48. package/node/prelude/tls.js +21 -4
  49. package/node/prelude/util.js +3 -16
  50. package/node/src/host_dns.c +623 -0
  51. package/node/src/host_http.c +12 -0
  52. package/node/src/host_net.c +46 -0
  53. package/node/src/host_os.c +1 -6
  54. package/node/src/host_sys.c +79 -0
  55. package/node/src/host_udp.c +418 -0
  56. package/node/third_party/c-ares/LICENSE.md +24 -0
  57. package/node/third_party/c-ares/config/darwin/ares_config.h +573 -0
  58. package/node/third_party/c-ares/config/freebsd/ares_config.h +573 -0
  59. package/node/third_party/c-ares/config/linux/ares_config.h +573 -0
  60. package/node/third_party/c-ares/config/openbsd/ares_config.h +583 -0
  61. package/node/third_party/c-ares/include/ares.h +1237 -0
  62. package/node/third_party/c-ares/include/ares_build.h +202 -0
  63. package/node/third_party/c-ares/include/ares_dns.h +127 -0
  64. package/node/third_party/c-ares/include/ares_dns_record.h +1119 -0
  65. package/node/third_party/c-ares/include/ares_nameser.h +510 -0
  66. package/node/third_party/c-ares/include/ares_version.h +47 -0
  67. package/node/third_party/c-ares/src/lib/ares_addrinfo2hostent.c +305 -0
  68. package/node/third_party/c-ares/src/lib/ares_addrinfo_localhost.c +245 -0
  69. package/node/third_party/c-ares/src/lib/ares_android.c +496 -0
  70. package/node/third_party/c-ares/src/lib/ares_android.h +38 -0
  71. package/node/third_party/c-ares/src/lib/ares_cancel.c +87 -0
  72. package/node/third_party/c-ares/src/lib/ares_close_sockets.c +137 -0
  73. package/node/third_party/c-ares/src/lib/ares_conn.c +511 -0
  74. package/node/third_party/c-ares/src/lib/ares_conn.h +202 -0
  75. package/node/third_party/c-ares/src/lib/ares_cookie.c +461 -0
  76. package/node/third_party/c-ares/src/lib/ares_data.c +168 -0
  77. package/node/third_party/c-ares/src/lib/ares_data.h +92 -0
  78. package/node/third_party/c-ares/src/lib/ares_destroy.c +159 -0
  79. package/node/third_party/c-ares/src/lib/ares_free_hostent.c +54 -0
  80. package/node/third_party/c-ares/src/lib/ares_free_string.c +33 -0
  81. package/node/third_party/c-ares/src/lib/ares_freeaddrinfo.c +67 -0
  82. package/node/third_party/c-ares/src/lib/ares_getaddrinfo.c +806 -0
  83. package/node/third_party/c-ares/src/lib/ares_getenv.c +38 -0
  84. package/node/third_party/c-ares/src/lib/ares_getenv.h +34 -0
  85. package/node/third_party/c-ares/src/lib/ares_gethostbyaddr.c +229 -0
  86. package/node/third_party/c-ares/src/lib/ares_gethostbyname.c +341 -0
  87. package/node/third_party/c-ares/src/lib/ares_getnameinfo.c +437 -0
  88. package/node/third_party/c-ares/src/lib/ares_hosts_file.c +960 -0
  89. package/node/third_party/c-ares/src/lib/ares_inet_net_pton.h +31 -0
  90. package/node/third_party/c-ares/src/lib/ares_init.c +631 -0
  91. package/node/third_party/c-ares/src/lib/ares_ipv6.h +115 -0
  92. package/node/third_party/c-ares/src/lib/ares_library_init.c +190 -0
  93. package/node/third_party/c-ares/src/lib/ares_metrics.c +261 -0
  94. package/node/third_party/c-ares/src/lib/ares_options.c +492 -0
  95. package/node/third_party/c-ares/src/lib/ares_parse_into_addrinfo.c +179 -0
  96. package/node/third_party/c-ares/src/lib/ares_private.h +648 -0
  97. package/node/third_party/c-ares/src/lib/ares_process.c +1649 -0
  98. package/node/third_party/c-ares/src/lib/ares_qcache.c +442 -0
  99. package/node/third_party/c-ares/src/lib/ares_query.c +151 -0
  100. package/node/third_party/c-ares/src/lib/ares_search.c +623 -0
  101. package/node/third_party/c-ares/src/lib/ares_send.c +300 -0
  102. package/node/third_party/c-ares/src/lib/ares_set_socket_functions.c +590 -0
  103. package/node/third_party/c-ares/src/lib/ares_setup.h +224 -0
  104. package/node/third_party/c-ares/src/lib/ares_socket.c +427 -0
  105. package/node/third_party/c-ares/src/lib/ares_socket.h +163 -0
  106. package/node/third_party/c-ares/src/lib/ares_sortaddrinfo.c +447 -0
  107. package/node/third_party/c-ares/src/lib/ares_strerror.c +91 -0
  108. package/node/third_party/c-ares/src/lib/ares_sysconfig.c +642 -0
  109. package/node/third_party/c-ares/src/lib/ares_sysconfig_files.c +851 -0
  110. package/node/third_party/c-ares/src/lib/ares_sysconfig_mac.c +373 -0
  111. package/node/third_party/c-ares/src/lib/ares_sysconfig_win.c +673 -0
  112. package/node/third_party/c-ares/src/lib/ares_timeout.c +162 -0
  113. package/node/third_party/c-ares/src/lib/ares_update_servers.c +1376 -0
  114. package/node/third_party/c-ares/src/lib/ares_version.c +36 -0
  115. package/node/third_party/c-ares/src/lib/config-dos.h +114 -0
  116. package/node/third_party/c-ares/src/lib/config-win32.h +396 -0
  117. package/node/third_party/c-ares/src/lib/dsa/ares_array.c +409 -0
  118. package/node/third_party/c-ares/src/lib/dsa/ares_htable.c +451 -0
  119. package/node/third_party/c-ares/src/lib/dsa/ares_htable.h +174 -0
  120. package/node/third_party/c-ares/src/lib/dsa/ares_htable_asvp.c +224 -0
  121. package/node/third_party/c-ares/src/lib/dsa/ares_htable_dict.c +230 -0
  122. package/node/third_party/c-ares/src/lib/dsa/ares_htable_strvp.c +210 -0
  123. package/node/third_party/c-ares/src/lib/dsa/ares_htable_szvp.c +188 -0
  124. package/node/third_party/c-ares/src/lib/dsa/ares_htable_vpstr.c +186 -0
  125. package/node/third_party/c-ares/src/lib/dsa/ares_htable_vpvp.c +194 -0
  126. package/node/third_party/c-ares/src/lib/dsa/ares_llist.c +385 -0
  127. package/node/third_party/c-ares/src/lib/dsa/ares_slist.c +479 -0
  128. package/node/third_party/c-ares/src/lib/dsa/ares_slist.h +207 -0
  129. package/node/third_party/c-ares/src/lib/event/ares_event.h +191 -0
  130. package/node/third_party/c-ares/src/lib/event/ares_event_configchg.c +746 -0
  131. package/node/third_party/c-ares/src/lib/event/ares_event_epoll.c +192 -0
  132. package/node/third_party/c-ares/src/lib/event/ares_event_kqueue.c +248 -0
  133. package/node/third_party/c-ares/src/lib/event/ares_event_poll.c +140 -0
  134. package/node/third_party/c-ares/src/lib/event/ares_event_select.c +159 -0
  135. package/node/third_party/c-ares/src/lib/event/ares_event_thread.c +575 -0
  136. package/node/third_party/c-ares/src/lib/event/ares_event_wake_pipe.c +172 -0
  137. package/node/third_party/c-ares/src/lib/event/ares_event_win32.c +981 -0
  138. package/node/third_party/c-ares/src/lib/event/ares_event_win32.h +161 -0
  139. package/node/third_party/c-ares/src/lib/include/ares_array.h +276 -0
  140. package/node/third_party/c-ares/src/lib/include/ares_buf.h +732 -0
  141. package/node/third_party/c-ares/src/lib/include/ares_htable_asvp.h +130 -0
  142. package/node/third_party/c-ares/src/lib/include/ares_htable_dict.h +123 -0
  143. package/node/third_party/c-ares/src/lib/include/ares_htable_strvp.h +130 -0
  144. package/node/third_party/c-ares/src/lib/include/ares_htable_szvp.h +118 -0
  145. package/node/third_party/c-ares/src/lib/include/ares_htable_vpstr.h +111 -0
  146. package/node/third_party/c-ares/src/lib/include/ares_htable_vpvp.h +128 -0
  147. package/node/third_party/c-ares/src/lib/include/ares_llist.h +239 -0
  148. package/node/third_party/c-ares/src/lib/include/ares_mem.h +41 -0
  149. package/node/third_party/c-ares/src/lib/include/ares_str.h +261 -0
  150. package/node/third_party/c-ares/src/lib/inet_net_pton.c +451 -0
  151. package/node/third_party/c-ares/src/lib/inet_ntop.c +219 -0
  152. package/node/third_party/c-ares/src/lib/legacy/ares_create_query.c +78 -0
  153. package/node/third_party/c-ares/src/lib/legacy/ares_expand_name.c +99 -0
  154. package/node/third_party/c-ares/src/lib/legacy/ares_expand_string.c +107 -0
  155. package/node/third_party/c-ares/src/lib/legacy/ares_fds.c +80 -0
  156. package/node/third_party/c-ares/src/lib/legacy/ares_getsock.c +85 -0
  157. package/node/third_party/c-ares/src/lib/legacy/ares_parse_a_reply.c +107 -0
  158. package/node/third_party/c-ares/src/lib/legacy/ares_parse_aaaa_reply.c +109 -0
  159. package/node/third_party/c-ares/src/lib/legacy/ares_parse_caa_reply.c +137 -0
  160. package/node/third_party/c-ares/src/lib/legacy/ares_parse_mx_reply.c +110 -0
  161. package/node/third_party/c-ares/src/lib/legacy/ares_parse_naptr_reply.c +132 -0
  162. package/node/third_party/c-ares/src/lib/legacy/ares_parse_ns_reply.c +154 -0
  163. package/node/third_party/c-ares/src/lib/legacy/ares_parse_ptr_reply.c +213 -0
  164. package/node/third_party/c-ares/src/lib/legacy/ares_parse_soa_reply.c +115 -0
  165. package/node/third_party/c-ares/src/lib/legacy/ares_parse_srv_reply.c +114 -0
  166. package/node/third_party/c-ares/src/lib/legacy/ares_parse_txt_reply.c +144 -0
  167. package/node/third_party/c-ares/src/lib/legacy/ares_parse_uri_reply.c +113 -0
  168. package/node/third_party/c-ares/src/lib/record/ares_dns_mapping.c +982 -0
  169. package/node/third_party/c-ares/src/lib/record/ares_dns_multistring.c +309 -0
  170. package/node/third_party/c-ares/src/lib/record/ares_dns_multistring.h +72 -0
  171. package/node/third_party/c-ares/src/lib/record/ares_dns_name.c +736 -0
  172. package/node/third_party/c-ares/src/lib/record/ares_dns_parse.c +1360 -0
  173. package/node/third_party/c-ares/src/lib/record/ares_dns_private.h +273 -0
  174. package/node/third_party/c-ares/src/lib/record/ares_dns_record.c +1701 -0
  175. package/node/third_party/c-ares/src/lib/record/ares_dns_write.c +1229 -0
  176. package/node/third_party/c-ares/src/lib/str/ares_buf.c +1510 -0
  177. package/node/third_party/c-ares/src/lib/str/ares_str.c +562 -0
  178. package/node/third_party/c-ares/src/lib/str/ares_strsplit.c +90 -0
  179. package/node/third_party/c-ares/src/lib/str/ares_strsplit.h +51 -0
  180. package/node/third_party/c-ares/src/lib/thirdparty/apple/dnsinfo.h +122 -0
  181. package/node/third_party/c-ares/src/lib/util/ares_iface_ips.c +640 -0
  182. package/node/third_party/c-ares/src/lib/util/ares_iface_ips.h +140 -0
  183. package/node/third_party/c-ares/src/lib/util/ares_math.c +167 -0
  184. package/node/third_party/c-ares/src/lib/util/ares_math.h +58 -0
  185. package/node/third_party/c-ares/src/lib/util/ares_rand.c +389 -0
  186. package/node/third_party/c-ares/src/lib/util/ares_rand.h +36 -0
  187. package/node/third_party/c-ares/src/lib/util/ares_threads.c +613 -0
  188. package/node/third_party/c-ares/src/lib/util/ares_threads.h +60 -0
  189. package/node/third_party/c-ares/src/lib/util/ares_time.h +49 -0
  190. package/node/third_party/c-ares/src/lib/util/ares_timeval.c +95 -0
  191. package/node/third_party/c-ares/src/lib/util/ares_uri.c +1627 -0
  192. package/node/third_party/c-ares/src/lib/util/ares_uri.h +252 -0
  193. package/node/third_party/c-ares/src/lib/windows_port.c +29 -0
  194. package/package.json +1 -1
  195. package/prebuilt/darwin-arm64/cares-a6286c65ca9374a3.a +0 -0
  196. package/prebuilt/darwin-x64/cares-a6286c65ca9374a3.a +0 -0
  197. package/prebuilt/linux-arm64/cares-4ba05ac8e948af8e.a +0 -0
  198. package/prebuilt/linux-arm64-musl/cares-4ba05ac8e948af8e.a +0 -0
  199. package/prebuilt/linux-x64/cares-4ba05ac8e948af8e.a +0 -0
  200. package/prebuilt/linux-x64-musl/cares-4ba05ac8e948af8e.a +0 -0
  201. package/prebuilt/win32-x64/boringssl-ce573858472b7fc9.a +0 -0
  202. package/prebuilt/win32-x64/brotli-20d86a61f30baeb3.a +0 -0
  203. package/prebuilt/win32-x64/cares-49c9ec95162b912d.a +0 -0
  204. package/prebuilt/win32-x64/uv-b11bae65d7fced82.a +0 -0
  205. package/prebuilt/win32-x64/zlib-4ce2317a4c3f5fb5.a +0 -0
  206. package/prebuilt/win32-x64/zstd-015315ac7c784c73.a +0 -0
  207. package/runtime/include/js_buffer.h +185 -0
  208. package/runtime/include/js_builtins.h +58 -0
  209. package/runtime/include/js_crypto.h +11 -0
  210. package/runtime/include/js_exception.h +3 -0
  211. package/runtime/include/js_function.h +1 -1
  212. package/runtime/include/js_gc.h +13 -10
  213. package/runtime/include/js_jobs.h +2 -0
  214. package/runtime/include/js_object.h +79 -3
  215. package/runtime/include/js_ops.h +27 -0
  216. package/runtime/include/js_runtime.h +1 -0
  217. package/runtime/include/js_web.h +0 -3
  218. package/runtime/include/jscontext.h +8 -0
  219. package/runtime/src/builtins.c +17 -4
  220. package/runtime/src/crypto_internal.h +1 -0
  221. package/runtime/src/crypto_subtle.c +66 -7
  222. package/runtime/src/crypto_tls.c +265 -19
  223. package/runtime/src/function.c +37 -10
  224. package/runtime/src/gc.c +76 -93
  225. package/runtime/src/inspect.c +18 -1
  226. package/runtime/src/iterator.c +5 -1
  227. package/runtime/src/jobs.c +37 -22
  228. package/runtime/src/object.c +91 -8
  229. package/runtime/src/os.c +16 -6
  230. package/runtime/src/os.h +2 -0
  231. package/runtime/src/process.c +97 -10
  232. package/runtime/src/typedarray.c +23 -0
@@ -20,6 +20,7 @@
20
20
  #include <openssl/err.h>
21
21
  #include <openssl/evp.h>
22
22
  #include <openssl/pem.h>
23
+ #include <openssl/pkcs8.h>
23
24
  #include <openssl/ssl.h>
24
25
  #include <openssl/x509.h>
25
26
 
@@ -263,27 +264,33 @@ PRIMITIVE(js_tls_context_set_cert) {
263
264
  return js_int32(0);
264
265
  }
265
266
 
266
- /* tlsContextSetKey(context, key handle) → 0 | 1 a key TLS can't use | 2 not the certificate's key */
267
- PRIMITIVE(js_tls_context_set_key) {
268
- UNUSED_ARGS;
269
- TlsContextObject *o = context_arg(ARG(0));
270
- JSKeyData *k = js_key_data(ARG(1));
271
- if (!o || !k) return js_throw_type_error(ctx, "tlsContextSetKey: a context and a key expected");
272
- if (k->type != JS_KEY_PRIVATE) return js_int32(1);
267
+ /* A key (handle) as BoringSSL's, from its PKCS#8 or SPKI DER, or NULL for one BoringSSL can't use */
268
+ static EVP_PKEY *pkey_of(const JSKeyData *k) {
269
+ bool private = k->type == JS_KEY_PRIVATE;
270
+ if (!private && k->type != JS_KEY_PUBLIC) return NULL;
273
271
  JSBytesOut der = { 0 };
274
- if (js_key_export_der(k, JS_KEY_ENC_PKCS8, &der) != 0) {
272
+ if (js_key_export_der(k, private ? JS_KEY_ENC_PKCS8 : JS_KEY_ENC_SPKI, &der) != 0) {
275
273
  free(der.p);
276
- return js_int32(1);
274
+ return NULL;
277
275
  }
278
276
  CBS cbs;
279
277
  CBS_init(&cbs, der.p, der.n);
280
- EVP_PKEY *pkey = EVP_parse_private_key(&cbs);
278
+ EVP_PKEY *pkey = private ? EVP_parse_private_key(&cbs) : EVP_parse_public_key(&cbs);
281
279
  memset(der.p, 0, der.n);
282
280
  free(der.p);
283
- if (!pkey) {
284
- ERR_clear_error();
285
- return js_int32(1);
286
- }
281
+ ERR_clear_error();
282
+ return pkey;
283
+ }
284
+
285
+ /* tlsContextSetKey(context, key handle) → 0 | 1 a key TLS can't use | 2 not the certificate's key */
286
+ PRIMITIVE(js_tls_context_set_key) {
287
+ UNUSED_ARGS;
288
+ TlsContextObject *o = context_arg(ARG(0));
289
+ JSKeyData *k = js_key_data(ARG(1));
290
+ if (!o || !k) return js_throw_type_error(ctx, "tlsContextSetKey: a context and a key expected");
291
+ if (k->type != JS_KEY_PRIVATE) return js_int32(1);
292
+ EVP_PKEY *pkey = pkey_of(k);
293
+ if (!pkey) return js_int32(1);
287
294
  int ok = SSL_CTX_use_PrivateKey(o->ctx, pkey);
288
295
  EVP_PKEY_free(pkey);
289
296
  ERR_clear_error();
@@ -291,6 +298,195 @@ PRIMITIVE(js_tls_context_set_key) {
291
298
  return js_int32(0);
292
299
  }
293
300
 
301
+ /* tlsContextAddCredential(context, [der, …], key handle) → 0 | 1 a key TLS can't use | 2 not the
302
+ * certificate's key: one of a server's identities (a chain, leaf first, and its key), which
303
+ * BoringSSL chooses among by what the client accepts, as OpenSSL does by key type */
304
+ PRIMITIVE(js_tls_context_add_credential) {
305
+ UNUSED_ARGS;
306
+ TlsContextObject *o = context_arg(ARG(0));
307
+ JSKeyData *k = js_key_data(ARG(2));
308
+ if (!o || !js_is_array(ARG(1)) || !k) return js_throw_type_error(ctx, "tlsContextAddCredential: a context, certificates and a key expected");
309
+ uint32_t n = js_array_length(js_as_object(ARG(1)));
310
+ if (n == 0 || n > 16) return js_throw_type_error(ctx, "tlsContextAddCredential: 1 to 16 certificates expected");
311
+ CRYPTO_BUFFER *certs[16] = { 0 };
312
+ int result = 0;
313
+ for (uint32_t i = 0; i < n && result == 0; i++) {
314
+ const uint8_t *p;
315
+ size_t len;
316
+ if (!bytes_arg(js_get_value(ctx, ARG(1), js_index_key(i)), &p, &len) || !(certs[i] = CRYPTO_BUFFER_new(p, len, NULL))) result = 1;
317
+ }
318
+ EVP_PKEY *pkey = result == 0 && k->type == JS_KEY_PRIVATE ? pkey_of(k) : NULL;
319
+ SSL_CREDENTIAL *cred = SSL_CREDENTIAL_new_x509();
320
+ if (result == 0 && (!pkey || !cred)) result = 1;
321
+ if (result == 0 && !SSL_CREDENTIAL_set1_cert_chain(cred, certs, n)) result = 1;
322
+ if (result == 0 && !SSL_CREDENTIAL_set1_private_key(cred, pkey)) result = 2;
323
+ if (result == 0 && !SSL_CTX_add1_credential(o->ctx, cred)) result = 1;
324
+ SSL_CREDENTIAL_free(cred);
325
+ EVP_PKEY_free(pkey);
326
+ for (uint32_t i = 0; i < n; i++) CRYPTO_BUFFER_free(certs[i]);
327
+ ERR_clear_error();
328
+ return js_int32(result);
329
+ }
330
+
331
+ /* tlsContextAllowPartialChain(context): a trusted intermediate ends a chain, as a root does
332
+ * (allowPartialTrustChain); on the context's parameters, as its store may be the shared roots' */
333
+ PRIMITIVE(js_tls_context_allow_partial_chain) {
334
+ UNUSED_ARGS;
335
+ TlsContextObject *o = context_arg(ARG(0));
336
+ if (!o) return js_throw_type_error(ctx, "tlsContextAllowPartialChain: a context expected");
337
+ X509_VERIFY_PARAM_set_flags(SSL_CTX_get0_param(o->ctx), X509_V_FLAG_PARTIAL_CHAIN);
338
+ return JS_UNDEFINED;
339
+ }
340
+
341
+ /* tlsContextTicketKeys(context, keys | null) → the 48 bytes the context's session tickets are
342
+ * encrypted with (after setting them to `keys`) */
343
+ PRIMITIVE(js_tls_context_ticket_keys) {
344
+ UNUSED_ARGS;
345
+ TlsContextObject *o = context_arg(ARG(0));
346
+ if (!o) return js_throw_type_error(ctx, "tlsContextTicketKeys: a context expected");
347
+ const uint8_t *p;
348
+ size_t n;
349
+ if (bytes_arg(ARG(1), &p, &n)) {
350
+ if (n != 48 || !SSL_CTX_set_tlsext_ticket_keys(o->ctx, p, n)) return js_throw_type_error(ctx, "tlsContextTicketKeys: 48 bytes expected");
351
+ }
352
+ uint8_t keys[48];
353
+ SSL_CTX_get_tlsext_ticket_keys(o->ctx, keys, sizeof keys);
354
+ return js_new_buffer_from_bytes(ctx, keys, sizeof keys);
355
+ }
356
+
357
+ /* tlsContextSetSessions(context, timeout | null, sessionIdContext | null): how long a session can
358
+ * be resumed (seconds), and the context its id is valid in */
359
+ PRIMITIVE(js_tls_context_set_sessions) {
360
+ UNUSED_ARGS;
361
+ TlsContextObject *o = context_arg(ARG(0));
362
+ if (!o) return js_throw_type_error(ctx, "tlsContextSetSessions: a context expected");
363
+ if (js_is_number(ARG(1))) SSL_CTX_set_timeout(o->ctx, (uint32_t)js_as_number(ARG(1)));
364
+ char *sid = string_dup(ctx, ARG(2));
365
+ if (sid) {
366
+ /* OpenSSL's limit, which Node passes through */
367
+ size_t n = strlen(sid);
368
+ SSL_CTX_set_session_id_context(o->ctx, (const uint8_t *)sid, n > SSL_MAX_SID_CTX_LENGTH ? SSL_MAX_SID_CTX_LENGTH : n);
369
+ free(sid);
370
+ }
371
+ return JS_UNDEFINED;
372
+ }
373
+
374
+ /* tlsPkcs12(der, password | null) → [private key (PKCS#8 DER) | null, certificate (DER) | null,
375
+ * [the other certificates' DER, …]] | the reason it can't be read (OpenSSL's words) */
376
+ PRIMITIVE(js_tls_pkcs12) {
377
+ UNUSED_ARGS;
378
+ const uint8_t *p;
379
+ size_t n;
380
+ if (!bytes_arg(ARG(0), &p, &n)) return js_throw_type_error(ctx, "tlsPkcs12: bytes expected");
381
+ char *password = string_dup(ctx, ARG(1));
382
+ PKCS12 *p12 = d2i_PKCS12(NULL, &p, (long)n);
383
+ EVP_PKEY *pkey = NULL;
384
+ X509 *cert = NULL;
385
+ STACK_OF(X509) *others = NULL;
386
+ bool ok = p12 && PKCS12_parse(p12, password, &pkey, &cert, &others);
387
+ if (password) {
388
+ memset(password, 0, strlen(password));
389
+ free(password);
390
+ }
391
+ PKCS12_free(p12);
392
+ if (!ok) {
393
+ const char *reason = ERR_reason_error_string(ERR_peek_last_error());
394
+ ERR_clear_error();
395
+ return js_new_string_cstr(ctx, reason ? reason : "Unknown error");
396
+ }
397
+ JSValue parts[3] = { JS_NULL, JS_NULL, JS_NULL };
398
+ if (pkey) {
399
+ CBB cbb;
400
+ uint8_t *der;
401
+ size_t len;
402
+ if (CBB_init(&cbb, 0) && EVP_marshal_private_key(&cbb, pkey) && CBB_finish(&cbb, &der, &len)) {
403
+ parts[0] = js_new_buffer_from_bytes(ctx, der, len);
404
+ OPENSSL_cleanse(der, len);
405
+ OPENSSL_free(der);
406
+ } else {
407
+ CBB_cleanup(&cbb);
408
+ }
409
+ }
410
+ uint8_t *der = NULL;
411
+ int len;
412
+ if (cert && (len = i2d_X509(cert, &der)) > 0) parts[1] = js_new_buffer_from_bytes(ctx, der, (size_t)len);
413
+ OPENSSL_free(der);
414
+ size_t count = others ? sk_X509_num(others) : 0;
415
+ parts[2] = js_new_array(ctx, 0);
416
+ for (size_t i = 0; i < count; i++) {
417
+ der = NULL;
418
+ if ((len = i2d_X509(sk_X509_value(others, i), &der)) > 0 &&
419
+ js_array_append(ctx, parts[2], js_new_buffer_from_bytes(ctx, der, (size_t)len)) < 0) {
420
+ OPENSSL_free(der);
421
+ parts[2] = JS_EXCEPTION;
422
+ break;
423
+ }
424
+ OPENSSL_free(der);
425
+ }
426
+ EVP_PKEY_free(pkey);
427
+ X509_free(cert);
428
+ sk_X509_pop_free(others, X509_free);
429
+ ERR_clear_error();
430
+ return js_is_exception(parts[2]) ? JS_EXCEPTION : js_new_array_from(ctx, parts, 3);
431
+ }
432
+
433
+ /* ---- Certificates (crypto.X509Certificate's checks, as OpenSSL's) ---------------------------------- */
434
+
435
+ /* x509Check(der, kind, value, flags) → the name matched (kind 0: a host, 1: an email address,
436
+ * 2: an IP address) or undefined; flags are X509_CHECK_FLAG_*'s */
437
+ PRIMITIVE(js_x509_check) {
438
+ UNUSED_ARGS;
439
+ X509 *x = x509_arg(ARG(0));
440
+ char *value = string_dup(ctx, ARG(2));
441
+ if (!x || !value || !js_is_number(ARG(1))) {
442
+ X509_free(x);
443
+ free(value);
444
+ ERR_clear_error();
445
+ return js_throw_type_error(ctx, "x509Check: a certificate, a kind and a value expected");
446
+ }
447
+ unsigned flags = js_is_number(ARG(3)) ? (unsigned)js_as_number(ARG(3)) : 0;
448
+ size_t n = strlen(value);
449
+ char *peer = NULL;
450
+ int r;
451
+ switch ((int)js_as_number(ARG(1))) {
452
+ case 0: r = X509_check_host(x, value, n, flags, &peer); break;
453
+ case 1: r = X509_check_email(x, value, n, flags); break;
454
+ default: r = X509_check_ip_asc(x, value, flags); break;
455
+ }
456
+ JSValue out = JS_UNDEFINED;
457
+ if (r == 1) out = js_new_string_utf8(ctx, peer ? peer : value, strlen(peer ? peer : value));
458
+ OPENSSL_free(peer);
459
+ free(value);
460
+ X509_free(x);
461
+ ERR_clear_error();
462
+ return out;
463
+ }
464
+
465
+ /* x509CheckIssued(der, issuerDer) → whether the issuer's name, key identifier and key usage fit (X509_check_issued) */
466
+ PRIMITIVE(js_x509_check_issued) {
467
+ UNUSED_ARGS;
468
+ X509 *x = x509_arg(ARG(0)), *issuer = x509_arg(ARG(1));
469
+ bool ok = x && issuer && X509_check_issued(issuer, x) == X509_V_OK;
470
+ X509_free(x);
471
+ X509_free(issuer);
472
+ ERR_clear_error();
473
+ return js_bool(ok);
474
+ }
475
+
476
+ /* x509CheckKey(der, key handle) → for a public key, whether it signed the certificate; for a
477
+ * private one, whether it is the certificate's */
478
+ PRIMITIVE(js_x509_check_key) {
479
+ UNUSED_ARGS;
480
+ X509 *x = x509_arg(ARG(0));
481
+ JSKeyData *k = js_key_data(ARG(1));
482
+ EVP_PKEY *pkey = k ? pkey_of(k) : NULL;
483
+ bool ok = x && pkey && (k->type == JS_KEY_PRIVATE ? X509_check_private_key(x, pkey) : X509_verify(x, pkey)) == 1;
484
+ EVP_PKEY_free(pkey);
485
+ X509_free(x);
486
+ ERR_clear_error();
487
+ return js_bool(ok);
488
+ }
489
+
294
490
  /* ---- Connections -------------------------------------------------------------------------------- */
295
491
 
296
492
  typedef struct TlsConnData {
@@ -301,10 +497,13 @@ typedef struct TlsConnData {
301
497
  uint32_t handshakes;
302
498
  bool in_handshake;
303
499
  SSL_SESSION *new_session; /* the last session (or ticket) the peer gave: tlsRun reports it once */
500
+ SSL_SESSION *offered_session; /* a client's, to resume */
304
501
  bool session_reported;
305
502
  uint8_t *alpn; /* a server's protocols, in the wire format */
306
503
  size_t alpn_len;
307
504
  bool alpn_strict;
505
+ bool keylog_on;
506
+ JSBytesOut keylog; /* NSS key log lines since tlsRun last reported them */
308
507
  } TlsConnData;
309
508
 
310
509
  typedef struct TlsConnObject {
@@ -346,7 +545,9 @@ static void conn_finalize(JSRuntime *rt, JSCell *cell) {
346
545
  if (!d) return;
347
546
  SSL_free(d->ssl); /* and its BIOs */
348
547
  SSL_SESSION_free(d->new_session);
548
+ SSL_SESSION_free(d->offered_session);
349
549
  free(d->alpn);
550
+ free(d->keylog.p);
350
551
  free(d);
351
552
  }
352
553
 
@@ -419,7 +620,7 @@ PRIMITIVE(js_tls_new) {
419
620
  if (bytes_arg(ARG(4), &sp, &spn)) {
420
621
  SSL_SESSION *s = SSL_SESSION_from_bytes(sp, spn, cx->ctx);
421
622
  if (s) SSL_set_session(d->ssl, s);
422
- SSL_SESSION_free(s);
623
+ d->offered_session = s; /* the reference from_bytes gave */
423
624
  }
424
625
  }
425
626
  ERR_clear_error();
@@ -437,7 +638,8 @@ static bool fatal(int e) {
437
638
 
438
639
  /* tlsRun(connection, records | null, data | null) → [records out | null, data received | null,
439
640
  * bytes of `data` taken, state (1 established, 2 failed, 4 the peer's close_notify, 8 a new
440
- * session to report), error ([library, reason, name] | 0), handshakes finished]: feeds the
641
+ * session to report), error ([library, reason, name] | 0), handshakes finished, key log lines |
642
+ * null]: feeds the
441
643
  * engine what it was given and runs it until it can't go on. `data` is taken once the handshake
442
644
  * is done (and not during a renegotiation); what isn't is given again later. */
443
645
  PRIMITIVE(js_tls_run) {
@@ -515,16 +717,18 @@ PRIMITIVE(js_tls_run) {
515
717
  d->session_reported = true;
516
718
  state |= TLS_NEW_SESSION;
517
719
  }
720
+ JSValue keylog = bytes_or_null(ctx, &d->keylog);
721
+ d->keylog = (JSBytesOut){ 0 };
518
722
  JSBytesOut out = { 0 };
519
723
  const uint8_t *p;
520
724
  size_t n;
521
725
  if (BIO_mem_contents(d->out, &p, &n) && n) out_append(&out, p, n);
522
726
  BIO_reset(d->out);
523
727
  ERR_clear_error();
524
- JSValue items[6] = { JS_NULL, JS_NULL, js_number((double)taken), js_int32(state), err, js_number(d->handshakes) };
728
+ JSValue items[7] = { JS_NULL, JS_NULL, js_number((double)taken), js_int32(state), err, js_number(d->handshakes), keylog };
525
729
  items[0] = bytes_or_null(ctx, &out);
526
730
  items[1] = bytes_or_null(ctx, &app);
527
- return js_new_array_from(ctx, items, 6);
731
+ return js_new_array_from(ctx, items, 7);
528
732
  }
529
733
 
530
734
  /* tlsShutdown(connection) → the records to send | null: our close_notify; reading goes on until
@@ -605,8 +809,9 @@ PRIMITIVE(js_tls_session) {
605
809
  UNUSED_ARGS;
606
810
  TlsConnData *d = conn_arg(ARG(0));
607
811
  if (!d || !d->established) return JS_UNDEFINED;
812
+ /* OpenSSL's, which Node returns: a TLS 1.3 session before its tickets too (it won't resume) */
608
813
  SSL_SESSION *s = d->new_session ? d->new_session : SSL_get_session(d->ssl);
609
- if (!s || !SSL_SESSION_is_resumable(s)) return JS_UNDEFINED;
814
+ if (!s) return JS_UNDEFINED;
610
815
  uint8_t *p;
611
816
  size_t n;
612
817
  if (!SSL_SESSION_to_bytes(s, &p, &n)) {
@@ -618,6 +823,21 @@ PRIMITIVE(js_tls_session) {
618
823
  return v;
619
824
  }
620
825
 
826
+ /* tlsTicket(connection) → Buffer | undefined: the session ticket a client was given */
827
+ PRIMITIVE(js_tls_ticket) {
828
+ UNUSED_ARGS;
829
+ TlsConnData *d = conn_arg(ARG(0));
830
+ if (!d) return JS_UNDEFINED;
831
+ /* resumed, a TLS 1.3 session is a copy without the ticket: the one offered had it */
832
+ SSL_SESSION *s = d->new_session ? d->new_session
833
+ : SSL_session_reused(d->ssl) && d->offered_session ? d->offered_session : SSL_get_session(d->ssl);
834
+ const uint8_t *p;
835
+ size_t n;
836
+ if (!s || !SSL_SESSION_has_ticket(s)) return JS_UNDEFINED;
837
+ SSL_SESSION_get0_ticket(s, &p, &n);
838
+ return js_new_buffer_from_bytes(ctx, p, n);
839
+ }
840
+
621
841
  /* tlsExportKeyingMaterial(connection, length, label, context | undefined) → Buffer | null (RFC 5705) */
622
842
  PRIMITIVE(js_tls_export_keying_material) {
623
843
  UNUSED_ARGS;
@@ -670,9 +890,35 @@ PRIMITIVE(js_tls_ciphers) {
670
890
 
671
891
  /* tlsSetNoRenegotiation(connection): a server's requests to renegotiate are refused (BoringSSL
672
892
  * renegotiates only as a client, when a server asks; it never starts one) */
893
+ static void on_keylog(const SSL *ssl, const char *line) {
894
+ TlsConnData *d = SSL_get_app_data(ssl);
895
+ if (!d || !d->keylog_on) return;
896
+ out_append(&d->keylog, line, strlen(line));
897
+ out_append(&d->keylog, "\n", 1);
898
+ }
899
+
900
+ /* tlsEnableKeylog(connection): its key log lines come with tlsRun's results (the 'keylog' event) */
901
+ PRIMITIVE(js_tls_enable_keylog) {
902
+ UNUSED_ARGS;
903
+ TlsConnData *d = conn_arg(ARG(0));
904
+ if (!d) return JS_UNDEFINED;
905
+ d->keylog_on = true;
906
+ /* the context's: BoringSSL forms the lines only for a context that has a callback */
907
+ SSL_CTX_set_keylog_callback(SSL_get_SSL_CTX(d->ssl), on_keylog);
908
+ return JS_UNDEFINED;
909
+ }
910
+
673
911
  PRIMITIVE(js_tls_set_no_renegotiation) {
674
912
  UNUSED_ARGS;
675
913
  TlsConnData *d = conn_arg(ARG(0));
676
914
  if (d && !d->server) SSL_set_renegotiate_mode(d->ssl, ssl_renegotiate_never);
677
915
  return JS_UNDEFINED;
678
916
  }
917
+
918
+ /* tlsSetMaxSendFragment(connection, size): the largest record's plaintext (512 to 16384) */
919
+ PRIMITIVE(js_tls_set_max_send_fragment) {
920
+ UNUSED_ARGS;
921
+ TlsConnData *d = conn_arg(ARG(0));
922
+ if (d && js_is_number(ARG(1))) SSL_set_max_send_fragment(d->ssl, (size_t)js_as_number(ARG(1)));
923
+ return JS_UNDEFINED;
924
+ }
@@ -222,10 +222,38 @@ JSValue js_get_prototype_from_constructor(JSContext *ctx, JSValue new_target, JS
222
222
  return realm ? realm->intrinsics[fallback] : JS_EXCEPTION;
223
223
  }
224
224
 
225
+ /* The root shape of the objects `new f` makes, with at least `slots` inline slots: kept on f, and
226
+ * grown by learn_instance_slots to what its instances end up holding. */
227
+ static JSShape *instance_root(JSContext *ctx, JSFunction *f, JSValue proto, uint16_t slots) {
228
+ JSShape *s = f->instance_shape;
229
+ if (JS_UNLIKELY(!s || !js_same_bits(s->proto, proto) || s->inline_cap < slots)) {
230
+ s = js_shape_root(ctx, &js_class_object, proto, slots);
231
+ js_store_ptr(ctx, &f->obj.cell, &f->instance_shape, s);
232
+ }
233
+ return s;
234
+ }
235
+
236
+ /* Slack tracking: when the constructors (a class's and its bases') left `v` with more properties
237
+ * than its root shape has inline slots, the next instances get room for them all. A derived
238
+ * class's `this` is made by its base, which can't count its subclasses' properties; the rest
239
+ * would sit out of line, where an inline cache's hit isn't inlined. */
240
+ static void learn_instance_slots(JSContext *ctx, JSFunction *f, JSValue v) {
241
+ JSShape *root = f->instance_shape;
242
+ if (!root || !js_is_object(v)) return;
243
+ JSShape *s = js_as_object(v)->shape;
244
+ if (JS_LIKELY(s->prop_count <= root->inline_cap || root->inline_cap >= JS_MAX_INLINE_SLOTS)) return;
245
+ JSShape *r = s;
246
+ while (r->parent) r = r->parent;
247
+ if (r != root) return; /* not made from it: an object the constructor returned, or a dictionary */
248
+ JSShape *grown = js_shape_root(ctx, &js_class_object, root->proto, (uint16_t)(s->prop_count < JS_MAX_INLINE_SLOTS ? s->prop_count : JS_MAX_INLINE_SLOTS));
249
+ js_store_ptr(ctx, &f->obj.cell, &f->instance_shape, grown);
250
+ }
251
+
225
252
  JSValue js_create_from_constructor(JSContext *ctx, JSValue new_target, JSIntrinsic fallback) {
226
253
  JSValue proto = js_get_prototype_from_constructor(ctx, new_target, fallback);
227
254
  if (js_is_exception(proto)) return JS_EXCEPTION;
228
- return js_new_object_proto(ctx, proto, JS_DEFAULT_INLINE_SLOTS);
255
+ if (!js_is_function(new_target)) return js_new_object_proto(ctx, proto, JS_DEFAULT_INLINE_SLOTS);
256
+ return js_object_value(js_alloc_object(ctx, JS_CELL_OBJECT, instance_root(ctx, js_as_function(new_target), proto, JS_DEFAULT_INLINE_SLOTS)));
229
257
  }
230
258
 
231
259
  JSValue js_new_instance(JSContext *ctx, JSValue fv, uint16_t slots, JSPropCache *ic) {
@@ -234,26 +262,25 @@ JSValue js_new_instance(JSContext *ctx, JSValue fv, uint16_t slots, JSPropCache
234
262
  : js_get_prop(ctx, fv, JS_ATOM(prototype), ic);
235
263
  if (js_is_exception(proto)) return JS_EXCEPTION;
236
264
  if (!js_is_object(proto)) proto = ctx->intrinsics[JS_INTRINSIC_OBJECT_PROTOTYPE]; /* OrdinaryCreateFromConstructor's fallback */
237
- JSFunction *f = js_as_function(fv);
238
- JSShape *s = f->instance_shape;
239
- if (JS_UNLIKELY(!s || !js_same_bits(s->proto, proto) || s->inline_cap != slots)) {
240
- s = js_shape_root(ctx, &js_class_object, proto, slots);
241
- js_store_ptr(ctx, &f->obj.cell, &f->instance_shape, s);
242
- }
243
- return js_object_value(js_alloc_object(ctx, JS_CELL_OBJECT, s));
265
+ return js_object_value(js_alloc_object(ctx, JS_CELL_OBJECT, instance_root(ctx, js_as_function(fv), proto, slots)));
244
266
  }
245
267
 
246
268
  JSValue js_construct(JSContext *ctx, JSValue f, uint32_t argc, const JSValue *argv, JSValue new_target, const char *callee_text) {
247
269
  if (JS_UNLIKELY(!js_is_constructor(f))) return not_callable(ctx, f, callee_text, "constructor");
248
270
  JSFunction *fn = js_as_function(f);
271
+ bool outermost = js_is_undefined(new_target) || js_same_bits(new_target, f); /* not a super() */
249
272
  if (js_is_undefined(new_target)) new_target = f;
250
- if (!(fn->flags & JS_FN_ORDINARY)) /* builtins create their own object; a derived constructor gets it from super() */
251
- return fn->entry(fn->flags & JS_FN_PROXY ? ctx : fn->realm, f, JS_UNDEFINED, argc, argv, new_target);
273
+ if (!(fn->flags & JS_FN_ORDINARY)) { /* builtins create their own object; a derived constructor gets it from super() */
274
+ JSValue r = fn->entry(fn->flags & JS_FN_PROXY ? ctx : fn->realm, f, JS_UNDEFINED, argc, argv, new_target);
275
+ if (outermost && (fn->flags & JS_FN_DERIVED) && !js_is_exception(r)) learn_instance_slots(ctx, fn, r);
276
+ return r;
277
+ }
252
278
  /* [[Construct]] of an ordinary function (§10.2.2): this = a new object; an object result wins */
253
279
  JSValue this_val = js_create_from_constructor(fn->realm, new_target, JS_INTRINSIC_OBJECT_PROTOTYPE);
254
280
  if (js_is_exception(this_val)) return JS_EXCEPTION;
255
281
  JSValue r = fn->entry(fn->realm, f, this_val, argc, argv, new_target);
256
282
  if (js_is_exception(r)) return JS_EXCEPTION;
283
+ if (outermost) learn_instance_slots(ctx, fn, this_val);
257
284
  return js_is_object(r) ? r : this_val;
258
285
  }
259
286