| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
1 parent 520ab7a commit 1613c7f
4 files changed
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -304,6 +304,24 @@ When a `QuicError` is passed to [`stream.destroy()`][] or | |||
| 304 | 304 | `STOP_SENDING` frame sent to the peer. Any other error type falls back to | |
| 305 | 305 | the negotiated protocol's generic internal error code. | |
| 306 | 306 | ||
| 307 | + ### Permission model | ||
| 308 | + | ||
| 309 | + When using the [Permission Model][], the `--allow-net` flag must be passed to | ||
| 310 | + allow QUIC network operations. Without it, calling [`quic.connect()`][] or | ||
| 311 | + [`quic.listen()`][] will throw an `ERR_ACCESS_DENIED` error. | ||
| 312 | + | ||
| 313 | + ```console | ||
| 314 | + $ node --permission --allow-fs-read=* --experimental-quic index.mjs | ||
| 315 | + Error: Access to this API has been restricted. Use --allow-net to manage permissions. | ||
| 316 | + code: 'ERR_ACCESS_DENIED', | ||
| 317 | + permission: 'Net', | ||
| 318 | + } | ||
| 319 | + ``` | ||
| 320 | + | ||
| 321 | + Creating a [`QuicEndpoint`][] instance without connecting or listening | ||
| 322 | + is permitted even without `--allow-net`, since no network I/O occurs until | ||
| 323 | + [`quic.connect()`][] or [`quic.listen()`][] is called. | ||
| 324 | + | ||
| 307 | 325 | ## `quic.connect(address[, options])` | |
| 308 | 326 | ||
| 309 | 327 | <!-- YAML | |
@@ -3851,6 +3869,7 @@ throughput issues caused by flow control. | |||
| 3851 | 3869 | [Callback error handling]: #callback-error-handling | |
| 3852 | 3870 | [JSON-SEQ]: https://www.rfc-editor.org/rfc/rfc7464 | |
| 3853 | 3871 | [NSS Key Log Format]: https://udn.realityripple.com/docs/Mozilla/Projects/NSS/Key_Log_Format | |
| 3872 | + [Permission Model]: permissions.md#permission-model | ||
| 3854 | 3873 | [RFC 8999]: https://www.rfc-editor.org/rfc/rfc8999 | |
| 3855 | 3874 | [RFC 9000]: https://www.rfc-editor.org/rfc/rfc9000 | |
| 3856 | 3875 | [RFC 9001]: https://www.rfc-editor.org/rfc/rfc9001 | |
@@ -3870,6 +3889,7 @@ throughput issues caused by flow control. | |||
| 3870 | 3889 | [RFC 9443]: https://www.rfc-editor.org/rfc/rfc9443 | |
| 3871 | 3890 | [`PerformanceEntry`]: perf_hooks.md#class-performanceentry | |
| 3872 | 3891 | [`PerformanceObserver`]: perf_hooks.md#class-performanceobserver | |
| 3892 | + [`QuicEndpoint`]: #class-quicendpoint | ||
| 3873 | 3893 | [`QuicError`]: #class-quicerror | |
| 3874 | 3894 | [`application.enableConnectProtocol`]: #sessionoptionsapplication | |
| 3875 | 3895 | [`application.enableDatagrams`]: #sessionoptionsapplication | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -11,6 +11,7 @@ | |||
| 11 | 11 | #include <node_external_reference.h> | |
| 12 | 12 | #include <node_process-inl.h> | |
| 13 | 13 | #include <node_sockaddr-inl.h> | |
| 14 | + #include <permission/permission.h> | ||
| 14 | 15 | #include <timer_wrap-inl.h> | |
| 15 | 16 | #include <util-inl.h> | |
| 16 | 17 | #include <uv.h> | |
@@ -1745,6 +1746,9 @@ JS_METHOD_IMPL(Endpoint::DoConnect) { | |||
| 1745 | 1746 | SocketAddressBase* address; | |
| 1746 | 1747 | ASSIGN_OR_RETURN_UNWRAP(&address, args[0]); | |
| 1747 | 1748 | ||
| 1749 | + THROW_IF_INSUFFICIENT_PERMISSIONS( | ||
| 1750 | + env, permission::PermissionScope::kNet, address->address()->ToString()); | ||
| 1751 | + | ||
| 1748 | 1752 | DCHECK(args[1]->IsObject()); | |
| 1749 | 1753 | Session::Options options; | |
| 1750 | 1754 | if (!Session::Options::From(env, args[1]).To(&options)) { | |
@@ -1771,6 +1775,8 @@ JS_METHOD_IMPL(Endpoint::DoListen) { | |||
| 1771 | 1775 | ASSIGN_OR_RETURN_UNWRAP(&endpoint, args.This()); | |
| 1772 | 1776 | auto env = Environment::GetCurrent(args); | |
| 1773 | 1777 | ||
| 1778 | + THROW_IF_INSUFFICIENT_PERMISSIONS(env, permission::PermissionScope::kNet, ""); | ||
| 1779 | + | ||
| 1774 | 1780 | Session::Options options; | |
| 1775 | 1781 | if (Session::Options::From(env, args[0]).To(&options)) { | |
| 1776 | 1782 | endpoint->Listen(options); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -44,7 +44,7 @@ TEST(SocketAddress, SocketAddress) { | |||
| 44 | 44 | } | |
| 45 | 45 | ||
| 46 | 46 | TEST(SocketAddress, IpHashAndIpEqual) { | |
| 47 | - sockaddr_storage s1, s2, s3, s4; | ||
| 47 | + sockaddr_storage s1, s2, s3; | ||
| 48 | 48 | // Same IP, different ports. | |
| 49 | 49 | SocketAddress::ToSockAddr(AF_INET, "10.0.0.1", 443, &s1); | |
| 50 | 50 | SocketAddress::ToSockAddr(AF_INET, "10.0.0.1", 8080, &s2); | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
@@ -0,0 +1,50 @@ | |||
| 1 | + // Flags: --permission --allow-fs-read=* --experimental-quic --no-warnings | ||
| 2 | + import { hasQuic, skip, mustNotCall } from '../common/index.mjs'; | ||
| 3 | + import assert from 'node:assert'; | ||
| 4 | + import * as fixtures from '../common/fixtures.mjs'; | ||
| 5 | + | ||
| 6 | + if (!hasQuic) { | ||
| 7 | + skip('QUIC is not enabled'); | ||
| 8 | + } | ||
| 9 | + | ||
| 10 | + const { createPrivateKey } = await import('node:crypto'); | ||
| 11 | + const { connect, listen, QuicEndpoint } = await import('node:quic'); | ||
| 12 | + | ||
| 13 | + // Verify that the permission system correctly reports no net access. | ||
| 14 | + assert.ok(!process.permission.has('net')); | ||
| 15 | + | ||
| 16 | + const key = createPrivateKey(fixtures.readKey('agent1-key.pem')); | ||
| 17 | + const cert = fixtures.readKey('agent1-cert.pem'); | ||
| 18 | + | ||
| 19 | + // Test: connect() should reject with ERR_ACCESS_DENIED | ||
| 20 | + { | ||
| 21 | + await assert.rejects( | ||
| 22 | + connect('127.0.0.1:12345', { alpn: 'h3' }), | ||
| 23 | + { | ||
| 24 | + code: 'ERR_ACCESS_DENIED', | ||
| 25 | + permission: 'Net', | ||
| 26 | + }, | ||
| 27 | + ); | ||
| 28 | + } | ||
| 29 | + | ||
| 30 | + // Test: listen() should throw ERR_ACCESS_DENIED | ||
| 31 | + { | ||
| 32 | + await assert.rejects( | ||
| 33 | + listen(mustNotCall('onsession should not be called'), { | ||
| 34 | + alpn: ['h3'], | ||
| 35 | + sni: { '*': { keys: [key], certs: [cert] } }, | ||
| 36 | + }), | ||
| 37 | + { | ||
| 38 | + code: 'ERR_ACCESS_DENIED', | ||
| 39 | + permission: 'Net', | ||
| 40 | + }, | ||
| 41 | + ); | ||
| 42 | + } | ||
| 43 | + | ||
| 44 | + // Test: Creating a QuicEndpoint without connect/listen is allowed | ||
| 45 | + // since no network I/O occurs at construction time. | ||
| 46 | + { | ||
| 47 | + const endpoint = new QuicEndpoint(); | ||
| 48 | + // The endpoint exists but has not performed any network operations. | ||
| 49 | + await endpoint.close(); | ||
| 50 | + } | ||
| Back | FazBrowse Home | New Git URL |
0 commit comments