@honeybbq/teamspeak 0.0.1 → 1.0.0-beta.7
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.
- package/LICENSE +21 -0
- package/README.md +726 -2
- package/dist/client/abort.d.ts +5 -0
- package/dist/client/abort.d.ts.map +1 -0
- package/dist/client/abort.js +23 -0
- package/dist/client/abort.js.map +1 -0
- package/dist/client/address.d.ts +17 -0
- package/dist/client/address.d.ts.map +1 -0
- package/dist/client/address.js +66 -0
- package/dist/client/address.js.map +1 -0
- package/dist/client/api/voice.d.ts +24 -0
- package/dist/client/api/voice.d.ts.map +1 -0
- package/dist/client/api/voice.js +33 -0
- package/dist/client/api/voice.js.map +1 -0
- package/dist/client/capabilities.d.ts +68 -0
- package/dist/client/capabilities.d.ts.map +1 -0
- package/dist/client/capabilities.js +59 -0
- package/dist/client/capabilities.js.map +1 -0
- package/dist/client/client.d.ts +196 -0
- package/dist/client/client.d.ts.map +1 -0
- package/dist/client/client.js +1523 -0
- package/dist/client/client.js.map +1 -0
- package/dist/client/commands.d.ts +66 -0
- package/dist/client/commands.d.ts.map +1 -0
- package/dist/client/commands.js +162 -0
- package/dist/client/commands.js.map +1 -0
- package/dist/client/crypto/crypt-ops.d.ts +7 -0
- package/dist/client/crypto/crypt-ops.d.ts.map +1 -0
- package/dist/client/crypto/crypt-ops.js +2 -0
- package/dist/client/crypto/crypt-ops.js.map +1 -0
- package/dist/client/crypto/crypt.d.ts +37 -0
- package/dist/client/crypto/crypt.d.ts.map +1 -0
- package/dist/client/crypto/crypt.js +203 -0
- package/dist/client/crypto/crypt.js.map +1 -0
- package/dist/client/crypto/eax.d.ts +12 -0
- package/dist/client/crypto/eax.d.ts.map +1 -0
- package/dist/client/crypto/eax.js +118 -0
- package/dist/client/crypto/eax.js.map +1 -0
- package/dist/client/crypto/identity.d.ts +97 -0
- package/dist/client/crypto/identity.d.ts.map +1 -0
- package/dist/client/crypto/identity.js +412 -0
- package/dist/client/crypto/identity.js.map +1 -0
- package/dist/client/crypto/index.d.ts +7 -0
- package/dist/client/crypto/index.d.ts.map +1 -0
- package/dist/client/crypto/index.js +5 -0
- package/dist/client/crypto/index.js.map +1 -0
- package/dist/client/crypto/primitives.d.ts +43 -0
- package/dist/client/crypto/primitives.d.ts.map +1 -0
- package/dist/client/crypto/primitives.js +116 -0
- package/dist/client/crypto/primitives.js.map +1 -0
- package/dist/client/diagnostics.d.ts +45 -0
- package/dist/client/diagnostics.d.ts.map +1 -0
- package/dist/client/diagnostics.js +30 -0
- package/dist/client/diagnostics.js.map +1 -0
- package/dist/client/discovery/index.d.ts +2 -0
- package/dist/client/discovery/index.d.ts.map +1 -0
- package/dist/client/discovery/index.js +2 -0
- package/dist/client/discovery/index.js.map +1 -0
- package/dist/client/discovery/resolver.d.ts +26 -0
- package/dist/client/discovery/resolver.d.ts.map +1 -0
- package/dist/client/discovery/resolver.js +275 -0
- package/dist/client/discovery/resolver.js.map +1 -0
- package/dist/client/errors.d.ts +82 -0
- package/dist/client/errors.d.ts.map +1 -0
- package/dist/client/errors.js +201 -0
- package/dist/client/errors.js.map +1 -0
- package/dist/client/events.d.ts +3 -0
- package/dist/client/events.d.ts.map +1 -0
- package/dist/client/events.js +8 -0
- package/dist/client/events.js.map +1 -0
- package/dist/client/handshake/crypt-handshake.d.ts +17 -0
- package/dist/client/handshake/crypt-handshake.d.ts.map +1 -0
- package/dist/client/handshake/crypt-handshake.js +128 -0
- package/dist/client/handshake/crypt-handshake.js.map +1 -0
- package/dist/client/handshake/crypt-init2.d.ts +7 -0
- package/dist/client/handshake/crypt-init2.d.ts.map +1 -0
- package/dist/client/handshake/crypt-init2.js +37 -0
- package/dist/client/handshake/crypt-init2.js.map +1 -0
- package/dist/client/handshake/index.d.ts +4 -0
- package/dist/client/handshake/index.d.ts.map +1 -0
- package/dist/client/handshake/index.js +4 -0
- package/dist/client/handshake/index.js.map +1 -0
- package/dist/client/handshake/license.d.ts +35 -0
- package/dist/client/handshake/license.d.ts.map +1 -0
- package/dist/client/handshake/license.js +169 -0
- package/dist/client/handshake/license.js.map +1 -0
- package/dist/client/handshake.d.ts +27 -0
- package/dist/client/handshake.d.ts.map +1 -0
- package/dist/client/handshake.js +126 -0
- package/dist/client/handshake.js.map +1 -0
- package/dist/client/helpers.d.ts +6 -0
- package/dist/client/helpers.d.ts.map +1 -0
- package/dist/client/helpers.js +13 -0
- package/dist/client/helpers.js.map +1 -0
- package/dist/client/hooks.d.ts +7 -0
- package/dist/client/hooks.d.ts.map +1 -0
- package/dist/client/hooks.js +28 -0
- package/dist/client/hooks.js.map +1 -0
- package/dist/client/index.d.ts +26 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +28 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/reconnect.d.ts +12 -0
- package/dist/client/reconnect.d.ts.map +1 -0
- package/dist/client/reconnect.js +44 -0
- package/dist/client/reconnect.js.map +1 -0
- package/dist/client/throttle.d.ts +20 -0
- package/dist/client/throttle.d.ts.map +1 -0
- package/dist/client/throttle.js +83 -0
- package/dist/client/throttle.js.map +1 -0
- package/dist/client/trace.d.ts +223 -0
- package/dist/client/trace.d.ts.map +1 -0
- package/dist/client/trace.js +13 -0
- package/dist/client/trace.js.map +1 -0
- package/dist/client/transfer.d.ts +111 -0
- package/dist/client/transfer.d.ts.map +1 -0
- package/dist/client/transfer.js +243 -0
- package/dist/client/transfer.js.map +1 -0
- package/dist/client/transport/generation-window.d.ts +30 -0
- package/dist/client/transport/generation-window.d.ts.map +1 -0
- package/dist/client/transport/generation-window.js +97 -0
- package/dist/client/transport/generation-window.js.map +1 -0
- package/dist/client/transport/handler.d.ts +61 -0
- package/dist/client/transport/handler.d.ts.map +1 -0
- package/dist/client/transport/handler.js +793 -0
- package/dist/client/transport/handler.js.map +1 -0
- package/dist/client/transport/index.d.ts +6 -0
- package/dist/client/transport/index.d.ts.map +1 -0
- package/dist/client/transport/index.js +5 -0
- package/dist/client/transport/index.js.map +1 -0
- package/dist/client/transport/packet.d.ts +36 -0
- package/dist/client/transport/packet.d.ts.map +1 -0
- package/dist/client/transport/packet.js +55 -0
- package/dist/client/transport/packet.js.map +1 -0
- package/dist/client/transport/quicklz.d.ts +24 -0
- package/dist/client/transport/quicklz.d.ts.map +1 -0
- package/dist/client/transport/quicklz.js +179 -0
- package/dist/client/transport/quicklz.js.map +1 -0
- package/dist/client/types.d.ts +226 -0
- package/dist/client/types.d.ts.map +1 -0
- package/dist/client/types.js +39 -0
- package/dist/client/types.js.map +1 -0
- package/dist/core/api/channels.d.ts +182 -0
- package/dist/core/api/channels.d.ts.map +1 -0
- package/dist/core/api/channels.js +155 -0
- package/dist/core/api/channels.js.map +1 -0
- package/dist/core/api/clients.d.ts +304 -0
- package/dist/core/api/clients.d.ts.map +1 -0
- package/dist/core/api/clients.js +260 -0
- package/dist/core/api/clients.js.map +1 -0
- package/dist/core/api/command.d.ts +305 -0
- package/dist/core/api/command.d.ts.map +1 -0
- package/dist/core/api/command.js +363 -0
- package/dist/core/api/command.js.map +1 -0
- package/dist/core/api/files.d.ts +153 -0
- package/dist/core/api/files.d.ts.map +1 -0
- package/dist/core/api/files.js +181 -0
- package/dist/core/api/files.js.map +1 -0
- package/dist/core/api/groups.d.ts +248 -0
- package/dist/core/api/groups.d.ts.map +1 -0
- package/dist/core/api/groups.js +271 -0
- package/dist/core/api/groups.js.map +1 -0
- package/dist/core/api/moderation.d.ts +205 -0
- package/dist/core/api/moderation.d.ts.map +1 -0
- package/dist/core/api/moderation.js +209 -0
- package/dist/core/api/moderation.js.map +1 -0
- package/dist/core/api/parse.d.ts +16 -0
- package/dist/core/api/parse.d.ts.map +1 -0
- package/dist/core/api/parse.js +40 -0
- package/dist/core/api/parse.js.map +1 -0
- package/dist/core/api/server.d.ts +310 -0
- package/dist/core/api/server.d.ts.map +1 -0
- package/dist/core/api/server.js +290 -0
- package/dist/core/api/server.js.map +1 -0
- package/dist/core/command/command.d.ts +20 -0
- package/dist/core/command/command.d.ts.map +1 -0
- package/dist/core/command/command.js +112 -0
- package/dist/core/command/command.js.map +1 -0
- package/dist/core/command/ids.d.ts +125 -0
- package/dist/core/command/ids.d.ts.map +1 -0
- package/dist/core/command/ids.js +85 -0
- package/dist/core/command/ids.js.map +1 -0
- package/dist/core/command/parser.d.ts +17 -0
- package/dist/core/command/parser.d.ts.map +1 -0
- package/dist/core/command/parser.js +65 -0
- package/dist/core/command/parser.js.map +1 -0
- package/dist/core/command/request.d.ts +61 -0
- package/dist/core/command/request.d.ts.map +1 -0
- package/dist/core/command/request.js +64 -0
- package/dist/core/command/request.js.map +1 -0
- package/dist/core/command/responses.d.ts +59 -0
- package/dist/core/command/responses.d.ts.map +1 -0
- package/dist/core/command/responses.js +74 -0
- package/dist/core/command/responses.js.map +1 -0
- package/dist/core/command-name.d.ts +333 -0
- package/dist/core/command-name.d.ts.map +1 -0
- package/dist/core/command-name.js +331 -0
- package/dist/core/command-name.js.map +1 -0
- package/dist/core/enums.d.ts +146 -0
- package/dist/core/enums.d.ts.map +1 -0
- package/dist/core/enums.js +132 -0
- package/dist/core/enums.js.map +1 -0
- package/dist/core/errorcode.d.ts +413 -0
- package/dist/core/errorcode.d.ts.map +1 -0
- package/dist/core/errorcode.js +410 -0
- package/dist/core/errorcode.js.map +1 -0
- package/dist/core/errors.d.ts +111 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +233 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/events.d.ts +207 -0
- package/dist/core/events.d.ts.map +1 -0
- package/dist/core/events.js +6 -0
- package/dist/core/events.js.map +1 -0
- package/dist/core/helpers.d.ts +42 -0
- package/dist/core/helpers.d.ts.map +1 -0
- package/dist/core/helpers.js +156 -0
- package/dist/core/helpers.js.map +1 -0
- package/dist/core/index.d.ts +35 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +34 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/internal.d.ts +23 -0
- package/dist/core/internal.d.ts.map +1 -0
- package/dist/core/internal.js +20 -0
- package/dist/core/internal.js.map +1 -0
- package/dist/core/middleware.d.ts +14 -0
- package/dist/core/middleware.d.ts.map +1 -0
- package/dist/core/middleware.js +18 -0
- package/dist/core/middleware.js.map +1 -0
- package/dist/core/notification-name.d.ts +154 -0
- package/dist/core/notification-name.d.ts.map +1 -0
- package/dist/core/notification-name.js +152 -0
- package/dist/core/notification-name.js.map +1 -0
- package/dist/core/notifications.d.ts +43 -0
- package/dist/core/notifications.d.ts.map +1 -0
- package/dist/core/notifications.js +116 -0
- package/dist/core/notifications.js.map +1 -0
- package/dist/core/permission-name.d.ts +533 -0
- package/dist/core/permission-name.d.ts.map +1 -0
- package/dist/core/permission-name.js +531 -0
- package/dist/core/permission-name.js.map +1 -0
- package/dist/core/permission.d.ts +31 -0
- package/dist/core/permission.d.ts.map +1 -0
- package/dist/core/permission.js +20 -0
- package/dist/core/permission.js.map +1 -0
- package/dist/core/property-name.d.ts +403 -0
- package/dist/core/property-name.d.ts.map +1 -0
- package/dist/core/property-name.js +405 -0
- package/dist/core/property-name.js.map +1 -0
- package/dist/core/reason.d.ts +39 -0
- package/dist/core/reason.d.ts.map +1 -0
- package/dist/core/reason.js +36 -0
- package/dist/core/reason.js.map +1 -0
- package/dist/core/reconnect.d.ts +59 -0
- package/dist/core/reconnect.d.ts.map +1 -0
- package/dist/core/reconnect.js +55 -0
- package/dist/core/reconnect.js.map +1 -0
- package/dist/core/types.d.ts +110 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +27 -0
- package/dist/core/types.js.map +1 -0
- package/dist/query/client.d.ts +194 -0
- package/dist/query/client.d.ts.map +1 -0
- package/dist/query/client.js +967 -0
- package/dist/query/client.js.map +1 -0
- package/dist/query/errors.d.ts +61 -0
- package/dist/query/errors.d.ts.map +1 -0
- package/dist/query/errors.js +100 -0
- package/dist/query/errors.js.map +1 -0
- package/dist/query/index.d.ts +36 -0
- package/dist/query/index.d.ts.map +1 -0
- package/dist/query/index.js +34 -0
- package/dist/query/index.js.map +1 -0
- package/dist/query/knownhosts.d.ts +61 -0
- package/dist/query/knownhosts.d.ts.map +1 -0
- package/dist/query/knownhosts.js +223 -0
- package/dist/query/knownhosts.js.map +1 -0
- package/dist/query/lines.d.ts +14 -0
- package/dist/query/lines.d.ts.map +1 -0
- package/dist/query/lines.js +29 -0
- package/dist/query/lines.js.map +1 -0
- package/dist/query/options.d.ts +187 -0
- package/dist/query/options.d.ts.map +1 -0
- package/dist/query/options.js +213 -0
- package/dist/query/options.js.map +1 -0
- package/dist/query/reconnect.d.ts +29 -0
- package/dist/query/reconnect.d.ts.map +1 -0
- package/dist/query/reconnect.js +87 -0
- package/dist/query/reconnect.js.map +1 -0
- package/dist/query/ssh.d.ts +345 -0
- package/dist/query/ssh.d.ts.map +1 -0
- package/dist/query/ssh.js +241 -0
- package/dist/query/ssh.js.map +1 -0
- package/dist/query/stream.d.ts +38 -0
- package/dist/query/stream.d.ts.map +1 -0
- package/dist/query/stream.js +70 -0
- package/dist/query/stream.js.map +1 -0
- package/dist/query/tcp.d.ts +38 -0
- package/dist/query/tcp.d.ts.map +1 -0
- package/dist/query/tcp.js +53 -0
- package/dist/query/tcp.js.map +1 -0
- package/dist/query/transport.d.ts +36 -0
- package/dist/query/transport.d.ts.map +1 -0
- package/dist/query/transport.js +2 -0
- package/dist/query/transport.js.map +1 -0
- package/dist/query/web.d.ts +54 -0
- package/dist/query/web.d.ts.map +1 -0
- package/dist/query/web.js +146 -0
- package/dist/query/web.js.map +1 -0
- package/dist/versions/index.d.ts +3094 -0
- package/dist/versions/index.d.ts.map +1 -0
- package/dist/versions/index.js +9237 -0
- package/dist/versions/index.js.map +1 -0
- package/package.json +118 -4
- package/src/client/abort.ts +24 -0
- package/src/client/address.ts +74 -0
- package/src/client/api/voice.ts +61 -0
- package/src/client/capabilities.ts +106 -0
- package/src/client/client.ts +1809 -0
- package/src/client/commands.ts +193 -0
- package/src/client/crypto/crypt-ops.ts +6 -0
- package/src/client/crypto/crypt.ts +275 -0
- package/src/client/crypto/eax.ts +152 -0
- package/src/client/crypto/identity.ts +484 -0
- package/src/client/crypto/index.ts +21 -0
- package/src/client/crypto/primitives.ts +141 -0
- package/src/client/diagnostics.ts +58 -0
- package/src/client/discovery/index.ts +1 -0
- package/src/client/discovery/resolver.ts +325 -0
- package/src/client/errors.ts +217 -0
- package/src/client/events.ts +12 -0
- package/src/client/handshake/crypt-handshake.ts +157 -0
- package/src/client/handshake/crypt-init2.ts +48 -0
- package/src/client/handshake/index.ts +3 -0
- package/src/client/handshake/license.ts +208 -0
- package/src/client/handshake.ts +150 -0
- package/src/client/helpers.ts +10 -0
- package/src/client/hooks.ts +30 -0
- package/src/client/index.ts +93 -0
- package/src/client/reconnect.ts +43 -0
- package/src/client/throttle.ts +92 -0
- package/src/client/trace.ts +237 -0
- package/src/client/transfer.ts +436 -0
- package/src/client/transport/generation-window.ts +108 -0
- package/src/client/transport/handler.ts +926 -0
- package/src/client/transport/index.ts +14 -0
- package/src/client/transport/packet.ts +69 -0
- package/src/client/transport/quicklz.ts +209 -0
- package/src/client/types.ts +268 -0
- package/src/core/api/channels.ts +396 -0
- package/src/core/api/clients.ts +654 -0
- package/src/core/api/command.ts +563 -0
- package/src/core/api/files.ts +405 -0
- package/src/core/api/groups.ts +622 -0
- package/src/core/api/moderation.ts +525 -0
- package/src/core/api/parse.ts +52 -0
- package/src/core/api/server.ts +709 -0
- package/src/core/command/command.ts +125 -0
- package/src/core/command/ids.ts +149 -0
- package/src/core/command/parser.ts +68 -0
- package/src/core/command/request.ts +119 -0
- package/src/core/command/responses.ts +114 -0
- package/src/core/command-name.ts +334 -0
- package/src/core/enums.ts +167 -0
- package/src/core/errorcode.ts +412 -0
- package/src/core/errors.ts +258 -0
- package/src/core/events.ts +219 -0
- package/src/core/helpers.ts +161 -0
- package/src/core/index.ts +126 -0
- package/src/core/internal.ts +23 -0
- package/src/core/middleware.ts +24 -0
- package/src/core/notification-name.ts +155 -0
- package/src/core/notifications.ts +157 -0
- package/src/core/permission-name.ts +538 -0
- package/src/core/permission.ts +34 -0
- package/src/core/property-name.ts +411 -0
- package/src/core/reason.ts +38 -0
- package/src/core/reconnect.ts +98 -0
- package/src/core/types.ts +138 -0
- package/src/query/client.ts +1132 -0
- package/src/query/errors.ts +108 -0
- package/src/query/index.ts +65 -0
- package/src/query/knownhosts.ts +257 -0
- package/src/query/lines.ts +28 -0
- package/src/query/options.ts +388 -0
- package/src/query/reconnect.ts +84 -0
- package/src/query/ssh.ts +614 -0
- package/src/query/stream.ts +91 -0
- package/src/query/tcp.ts +85 -0
- package/src/query/transport.ts +35 -0
- package/src/query/web.ts +195 -0
- package/src/versions/index.ts +10774 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { TeamspeakError } from "@honeybbq/teamspeak";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* The `ssh` transport was asked for and `ssh2` is not installed.
|
|
5
|
+
*
|
|
6
|
+
* `ssh2` is an optional peer dependency — ServerQuery over raw TCP and over
|
|
7
|
+
* WebQuery need nothing but Node — so an application that only uses those has
|
|
8
|
+
* no reason to carry it. This says which package to add rather than failing
|
|
9
|
+
* with a module-not-found from inside the loader.
|
|
10
|
+
*
|
|
11
|
+
* @experimental Part of the `@honeybbq/teamspeak/query` entry, which may
|
|
12
|
+
* change in a minor release.
|
|
13
|
+
*/
|
|
14
|
+
export class MissingDependencyError extends TeamspeakError {
|
|
15
|
+
/** {@inheritDoc @honeybbq/teamspeak!TeamspeakError.kind} */
|
|
16
|
+
static override readonly kind: string = "MissingDependencyError";
|
|
17
|
+
static {
|
|
18
|
+
// On the prototype, not the instance, as built-in errors do: an own `name`
|
|
19
|
+
// would be enumerable and show up in JSON.stringify and object spread.
|
|
20
|
+
Object.defineProperty(this.prototype, "name", {
|
|
21
|
+
value: "MissingDependencyError",
|
|
22
|
+
writable: true,
|
|
23
|
+
configurable: true,
|
|
24
|
+
enumerable: false,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** The package to install. */
|
|
29
|
+
readonly package = "ssh2" as const;
|
|
30
|
+
|
|
31
|
+
constructor() {
|
|
32
|
+
super('the ssh transport needs the optional dependency "ssh2", which is not installed');
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* An SSH server's host key was not accepted, so nothing was sent to it: the
|
|
38
|
+
* caller's check refused it, or the `known_hosts` file it named does not know
|
|
39
|
+
* the host, records another key, revokes this one, or could not be read.
|
|
40
|
+
*
|
|
41
|
+
* The check runs before the login, so the query password has not left the
|
|
42
|
+
* process. What the check said is kept as this error's `cause`: an unknown host
|
|
43
|
+
* is told apart from a changed key there, and a changed key may be somebody
|
|
44
|
+
* else answering the port. Retrying cannot help, so the default reconnection
|
|
45
|
+
* policy does not.
|
|
46
|
+
*
|
|
47
|
+
* @experimental Part of the `@honeybbq/teamspeak/query` entry, which may
|
|
48
|
+
* change in a minor release.
|
|
49
|
+
*/
|
|
50
|
+
export class SshHostKeyError extends TeamspeakError {
|
|
51
|
+
/** {@inheritDoc @honeybbq/teamspeak!TeamspeakError.kind} */
|
|
52
|
+
static override readonly kind: string = "SshHostKeyError";
|
|
53
|
+
static {
|
|
54
|
+
// On the prototype, not the instance, as built-in errors do: an own `name`
|
|
55
|
+
// would be enumerable and show up in JSON.stringify and object spread.
|
|
56
|
+
Object.defineProperty(this.prototype, "name", {
|
|
57
|
+
value: "SshHostKeyError",
|
|
58
|
+
writable: true,
|
|
59
|
+
configurable: true,
|
|
60
|
+
enumerable: false,
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** The host that was dialled. */
|
|
65
|
+
readonly host: string;
|
|
66
|
+
/** The port that was dialled. */
|
|
67
|
+
readonly port: number;
|
|
68
|
+
|
|
69
|
+
constructor(host: string, port: number, message: string, options?: ErrorOptions) {
|
|
70
|
+
super(message, options);
|
|
71
|
+
this.host = host;
|
|
72
|
+
this.port = port;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* The server refused an SSH login: a wrong query login name or password, or an
|
|
78
|
+
* account the server does not accept over SSH.
|
|
79
|
+
*
|
|
80
|
+
* SSH logs in before the query protocol starts, so this is not a `ServerError`
|
|
81
|
+
* with a protocol code; the failure is the SSH client's own, kept as this
|
|
82
|
+
* error's `cause`.
|
|
83
|
+
*
|
|
84
|
+
* @experimental Part of the `@honeybbq/teamspeak/query` entry, which may
|
|
85
|
+
* change in a minor release.
|
|
86
|
+
*/
|
|
87
|
+
export class QueryAuthError extends TeamspeakError {
|
|
88
|
+
/** {@inheritDoc @honeybbq/teamspeak!TeamspeakError.kind} */
|
|
89
|
+
static override readonly kind: string = "QueryAuthError";
|
|
90
|
+
static {
|
|
91
|
+
// On the prototype, not the instance, as built-in errors do: an own `name`
|
|
92
|
+
// would be enumerable and show up in JSON.stringify and object spread.
|
|
93
|
+
Object.defineProperty(this.prototype, "name", {
|
|
94
|
+
value: "QueryAuthError",
|
|
95
|
+
writable: true,
|
|
96
|
+
configurable: true,
|
|
97
|
+
enumerable: false,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** The SSH login name whose authentication failed. */
|
|
102
|
+
readonly username: string;
|
|
103
|
+
|
|
104
|
+
constructor(username: string, message: string, options?: ErrorOptions) {
|
|
105
|
+
super(message, options);
|
|
106
|
+
this.username = username;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A TeamSpeak ServerQuery client.
|
|
3
|
+
*
|
|
4
|
+
* ServerQuery is the administrative interface to a TeamSpeak server: the voice
|
|
5
|
+
* protocol's commands, plus the ones only an administrator can run. This entry
|
|
6
|
+
* runs the same typed commands as `@honeybbq/teamspeak`,
|
|
7
|
+
* over raw TCP (10011), SSH (10022) or TeamSpeak 6's HTTP WebQuery (10080).
|
|
8
|
+
*
|
|
9
|
+
* Only what belongs to ServerQuery is exported here. The typed commands, ids
|
|
10
|
+
* and errors every client shares come from `@honeybbq/teamspeak`.
|
|
11
|
+
*
|
|
12
|
+
* SSH checks the server's host key before it sends the login, and has no
|
|
13
|
+
* default for how: one of `knownHosts`, `hostKey` or `insecureIgnoreHostKey`
|
|
14
|
+
* has to be given, because the query login is a credential and a client that
|
|
15
|
+
* accepts any key hands it to whatever answers the port.
|
|
16
|
+
*
|
|
17
|
+
* @experimental This entry point is new and may change in a minor release: the
|
|
18
|
+
* `QueryClient` API, its options and its event map are all still settling.
|
|
19
|
+
* Pin a version and read the changelog if you depend on it.
|
|
20
|
+
*
|
|
21
|
+
* @packageDocumentation
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
export { QueryClient } from "./client.js";
|
|
25
|
+
export type {
|
|
26
|
+
QueryClientOptions,
|
|
27
|
+
QueryEventCategory,
|
|
28
|
+
QueryEventMap,
|
|
29
|
+
QueryEventsOption,
|
|
30
|
+
QueryTransportOptions,
|
|
31
|
+
} from "./client.js";
|
|
32
|
+
|
|
33
|
+
export type { QueryTransport } from "./transport.js";
|
|
34
|
+
|
|
35
|
+
// Reconnection: the client's default retry decision, and the shared options.
|
|
36
|
+
export { defaultShouldRetry } from "./reconnect.js";
|
|
37
|
+
|
|
38
|
+
// Errors unique to ServerQuery.
|
|
39
|
+
export { MissingDependencyError, QueryAuthError, SshHostKeyError } from "./errors.js";
|
|
40
|
+
|
|
41
|
+
// The transports each `transport` kind builds on, for a caller that wants one
|
|
42
|
+
// directly or that is writing its own `custom` opener.
|
|
43
|
+
export { StreamTransport } from "./stream.js";
|
|
44
|
+
export type { QueryStream } from "./stream.js";
|
|
45
|
+
export { connectTcp } from "./tcp.js";
|
|
46
|
+
export type { TcpConnector, TcpOptions } from "./tcp.js";
|
|
47
|
+
export { connectSsh } from "./ssh.js";
|
|
48
|
+
export type {
|
|
49
|
+
SshChannel,
|
|
50
|
+
SshClient,
|
|
51
|
+
SshConnectOptions,
|
|
52
|
+
SshConnection,
|
|
53
|
+
SshDialOptions,
|
|
54
|
+
SshDialTarget,
|
|
55
|
+
SshHostKey,
|
|
56
|
+
SshHostKeyCallbackPolicy,
|
|
57
|
+
SshHostKeyPolicy,
|
|
58
|
+
SshHostKeyVerifier,
|
|
59
|
+
SshInsecureHostKeyPolicy,
|
|
60
|
+
SshKnownHostsPolicy,
|
|
61
|
+
SshOptions,
|
|
62
|
+
SshSuppliedConnectionOptions,
|
|
63
|
+
} from "./ssh.js";
|
|
64
|
+
export { WebQueryHttpError, WebQueryTransport } from "./web.js";
|
|
65
|
+
export type { WebQueryOptions } from "./web.js";
|
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
import { createHash, createHmac, timingSafeEqual } from "node:crypto";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* What a host key check needs to know about the key a server presented. A
|
|
5
|
+
* structural type, so this module reads no further than it uses.
|
|
6
|
+
*/
|
|
7
|
+
export interface PresentedHostKey {
|
|
8
|
+
/** The host that was dialled, as the caller wrote it. */
|
|
9
|
+
readonly host: string;
|
|
10
|
+
/** The port that was dialled. */
|
|
11
|
+
readonly port: number;
|
|
12
|
+
/** The key's wire encoding: the blob a `known_hosts` line carries in base64. */
|
|
13
|
+
readonly key: Uint8Array;
|
|
14
|
+
/** The key's algorithm, as its own encoding names it. */
|
|
15
|
+
readonly keyType: string;
|
|
16
|
+
/** The key's `SHA256:` fingerprint, as `ssh-keygen -lf` prints it. */
|
|
17
|
+
readonly fingerprint: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* The OpenSSH fingerprint of a key: `SHA256:` and the unpadded base64 of the
|
|
22
|
+
* SHA-256 of its wire encoding, which is what `ssh-keygen -lf` prints.
|
|
23
|
+
*/
|
|
24
|
+
export function fingerprintOf(key: Uint8Array): string {
|
|
25
|
+
return `SHA256:${createHash("sha256").update(key).digest("base64").replace(/=+$/, "")}`;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* The algorithm a key's wire encoding names, such as `ssh-ed25519`: the first
|
|
30
|
+
* field of the encoding, a length-prefixed string.
|
|
31
|
+
*
|
|
32
|
+
* Throws on an encoding that is too short to hold one, so that a key which
|
|
33
|
+
* cannot be read is refused rather than described as nothing.
|
|
34
|
+
*/
|
|
35
|
+
export function keyTypeOf(key: Uint8Array): string {
|
|
36
|
+
if (key.length >= 4) {
|
|
37
|
+
const length = new DataView(key.buffer, key.byteOffset, key.byteLength).getUint32(0);
|
|
38
|
+
if (length > 0 && length <= key.length - 4) {
|
|
39
|
+
return Buffer.from(key.subarray(4, 4 + length)).toString("latin1");
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
throw new Error("the host key is not a valid SSH public key encoding");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** The port OpenSSH leaves out of a `known_hosts` host: SSH's own. */
|
|
46
|
+
const DEFAULT_PORT = 22;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* A host as `known_hosts` writes it, and as hashed entries hash it: the bare
|
|
50
|
+
* name for port 22, `[name]:port` for any other. Lower-cased, since host names
|
|
51
|
+
* are not case sensitive and OpenSSH looks them up that way.
|
|
52
|
+
*/
|
|
53
|
+
function addressOf(host: string, port: number): string {
|
|
54
|
+
const name = (
|
|
55
|
+
host.startsWith("[") && host.endsWith("]") ? host.slice(1, -1) : host
|
|
56
|
+
).toLowerCase();
|
|
57
|
+
return port === DEFAULT_PORT ? name : `[${name}]:${port}`;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Whether `text` matches `pattern`, where `*` stands for any run of characters
|
|
62
|
+
* and `?` for exactly one.
|
|
63
|
+
*
|
|
64
|
+
* Written as a loop that backs up to the last `*` rather than as a regular
|
|
65
|
+
* expression: a pattern with several stars would make a regular expression
|
|
66
|
+
* backtrack exponentially on a name that does not match.
|
|
67
|
+
*/
|
|
68
|
+
function wildcardMatch(pattern: string, text: string): boolean {
|
|
69
|
+
let p = 0;
|
|
70
|
+
let t = 0;
|
|
71
|
+
let star = -1;
|
|
72
|
+
let resume = 0;
|
|
73
|
+
while (t < text.length) {
|
|
74
|
+
const wanted = pattern[p];
|
|
75
|
+
if (wanted === "*") {
|
|
76
|
+
star = p++;
|
|
77
|
+
resume = t;
|
|
78
|
+
} else if (wanted === "?" || wanted === text[t]) {
|
|
79
|
+
p++;
|
|
80
|
+
t++;
|
|
81
|
+
} else if (star >= 0) {
|
|
82
|
+
p = star + 1;
|
|
83
|
+
t = ++resume;
|
|
84
|
+
} else {
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
while (pattern[p] === "*") p++;
|
|
89
|
+
return p === pattern.length;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/** Whether a line's host field names this address. */
|
|
93
|
+
type HostMatcher = (address: string) => boolean;
|
|
94
|
+
|
|
95
|
+
/** One key a `known_hosts` file records, and where. */
|
|
96
|
+
interface Entry {
|
|
97
|
+
readonly line: number;
|
|
98
|
+
readonly matches: HostMatcher;
|
|
99
|
+
readonly keyType: string;
|
|
100
|
+
readonly key: Uint8Array;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** The base64 in a key field, strictly: `Buffer.from` would skip what it cannot read. */
|
|
104
|
+
function decodeBase64(text: string): Uint8Array | undefined {
|
|
105
|
+
if (!/^[A-Za-z0-9+/]+={0,2}$/.test(text)) return undefined;
|
|
106
|
+
const bytes = Buffer.from(text, "base64");
|
|
107
|
+
return bytes.toString("base64") === text ? new Uint8Array(bytes) : undefined;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function sameBytes(a: Uint8Array, b: Uint8Array): boolean {
|
|
111
|
+
return a.length === b.length && timingSafeEqual(a, b);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** `|1|salt|hash`: the host field `ssh-keygen -H` writes, an HMAC-SHA1 of the address. */
|
|
115
|
+
function hashedMatcher(field: string): HostMatcher | undefined {
|
|
116
|
+
const parts = field.split("|");
|
|
117
|
+
if (parts.length !== 4 || parts[1] !== "1") return undefined;
|
|
118
|
+
const salt = decodeBase64(parts[2] ?? "");
|
|
119
|
+
const hash = decodeBase64(parts[3] ?? "");
|
|
120
|
+
if (salt === undefined || hash === undefined) return undefined;
|
|
121
|
+
return (address) => sameBytes(createHmac("sha1", salt).update(address).digest(), hash);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* A comma-separated host field: patterns with `*` and `?`, `[host]:port` for a
|
|
126
|
+
* port other than 22, and `!` to exclude. An address matches when some pattern
|
|
127
|
+
* does and no excluded one does.
|
|
128
|
+
*/
|
|
129
|
+
function patternMatcher(field: string): HostMatcher | undefined {
|
|
130
|
+
const patterns: Array<{ readonly negated: boolean; readonly pattern: string }> = [];
|
|
131
|
+
for (const item of field.split(",")) {
|
|
132
|
+
if (item === "") continue;
|
|
133
|
+
const negated = item.startsWith("!");
|
|
134
|
+
const pattern = (negated ? item.slice(1) : item).toLowerCase();
|
|
135
|
+
if (pattern === "") return undefined;
|
|
136
|
+
patterns.push({ negated, pattern });
|
|
137
|
+
}
|
|
138
|
+
if (patterns.length === 0) return undefined;
|
|
139
|
+
return (address) => {
|
|
140
|
+
let matched = false;
|
|
141
|
+
for (const { negated, pattern } of patterns) {
|
|
142
|
+
if (!wildcardMatch(pattern, address)) continue;
|
|
143
|
+
if (negated) return false;
|
|
144
|
+
matched = true;
|
|
145
|
+
}
|
|
146
|
+
return matched;
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* An OpenSSH `known_hosts` file, read for the one question a client asks of it:
|
|
152
|
+
* is this the key the host is recorded with.
|
|
153
|
+
*
|
|
154
|
+
* Follows what `ssh` does with `StrictHostKeyChecking=yes`: a host the file
|
|
155
|
+
* does not mention is refused, so is one whose recorded keys do not include the
|
|
156
|
+
* key it presented, and so is any key a `@revoked` line names, whatever host
|
|
157
|
+
* presents it. Nothing is ever added to the file.
|
|
158
|
+
*
|
|
159
|
+
* `@cert-authority` lines are read and then ignored. They name a key that signs
|
|
160
|
+
* host certificates, and a presented plain key is not one, so they can neither
|
|
161
|
+
* accept nor refuse it.
|
|
162
|
+
*/
|
|
163
|
+
export class KnownHosts {
|
|
164
|
+
readonly #source: string;
|
|
165
|
+
readonly #entries: readonly Entry[];
|
|
166
|
+
readonly #revoked: readonly Entry[];
|
|
167
|
+
|
|
168
|
+
private constructor(source: string, entries: readonly Entry[], revoked: readonly Entry[]) {
|
|
169
|
+
this.#source = source;
|
|
170
|
+
this.#entries = entries;
|
|
171
|
+
this.#revoked = revoked;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Read the text of a `known_hosts` file. `source` names it in messages.
|
|
176
|
+
*
|
|
177
|
+
* Throws on a line it cannot read, naming the file and line, rather than
|
|
178
|
+
* skipping it: a skipped `@revoked` line would let the key it revokes
|
|
179
|
+
* through.
|
|
180
|
+
*/
|
|
181
|
+
static parse(text: string, source: string): KnownHosts {
|
|
182
|
+
const entries: Entry[] = [];
|
|
183
|
+
const revoked: Entry[] = [];
|
|
184
|
+
const lines = text.split(/\r?\n/);
|
|
185
|
+
for (const [index, raw] of lines.entries()) {
|
|
186
|
+
const line = raw.trim();
|
|
187
|
+
if (line === "" || line.startsWith("#")) continue;
|
|
188
|
+
const where = `${source}:${index + 1}`;
|
|
189
|
+
const fields = line.split(/[ \t]+/);
|
|
190
|
+
|
|
191
|
+
let marker: string | undefined;
|
|
192
|
+
if (fields[0]?.startsWith("@")) {
|
|
193
|
+
marker = fields.shift();
|
|
194
|
+
if (marker !== "@revoked" && marker !== "@cert-authority") {
|
|
195
|
+
throw new Error(`${where}: unknown marker ${JSON.stringify(marker)}`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
const [hostField, keyType, encoded] = fields;
|
|
199
|
+
if (hostField === undefined || keyType === undefined || encoded === undefined) {
|
|
200
|
+
throw new Error(`${where}: expected a host, a key type and a key`);
|
|
201
|
+
}
|
|
202
|
+
const key = decodeBase64(encoded);
|
|
203
|
+
if (key === undefined) throw new Error(`${where}: the key is not valid base64`);
|
|
204
|
+
let named: string;
|
|
205
|
+
try {
|
|
206
|
+
named = keyTypeOf(key);
|
|
207
|
+
} catch {
|
|
208
|
+
throw new Error(`${where}: the key is not a valid SSH public key encoding`);
|
|
209
|
+
}
|
|
210
|
+
if (named !== keyType) {
|
|
211
|
+
throw new Error(`${where}: the key is ${named}, but the line says ${keyType}`);
|
|
212
|
+
}
|
|
213
|
+
const matches = hostField.startsWith("|")
|
|
214
|
+
? hashedMatcher(hostField)
|
|
215
|
+
: patternMatcher(hostField);
|
|
216
|
+
if (matches === undefined) {
|
|
217
|
+
throw new Error(`${where}: cannot read the host ${JSON.stringify(hostField)}`);
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
const entry: Entry = { line: index + 1, matches, keyType, key };
|
|
221
|
+
if (marker === "@revoked") revoked.push(entry);
|
|
222
|
+
else if (marker === undefined) entries.push(entry);
|
|
223
|
+
}
|
|
224
|
+
return new KnownHosts(source, entries, revoked);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Accept the key by returning, or refuse it by throwing an `Error` that says
|
|
229
|
+
* why: revoked, a host the file does not know, or a key that differs from the
|
|
230
|
+
* recorded one.
|
|
231
|
+
*/
|
|
232
|
+
verify(presented: PresentedHostKey): void {
|
|
233
|
+
const label = `${presented.keyType} ${presented.fingerprint}`;
|
|
234
|
+
const revoked = this.#revoked.find((entry) => sameBytes(entry.key, presented.key));
|
|
235
|
+
if (revoked !== undefined) {
|
|
236
|
+
throw new Error(
|
|
237
|
+
`the host key ${label} is revoked in ${this.#source}:${revoked.line}, so it is not accepted from any host`,
|
|
238
|
+
);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
const address = addressOf(presented.host, presented.port);
|
|
242
|
+
const recorded = this.#entries.filter((entry) => entry.matches(address));
|
|
243
|
+
if (recorded.length === 0) {
|
|
244
|
+
throw new Error(
|
|
245
|
+
`${address} is not in ${this.#source}; its key ${label} has to be added before connecting`,
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
if (recorded.some((entry) => sameBytes(entry.key, presented.key))) return;
|
|
249
|
+
|
|
250
|
+
const known = recorded
|
|
251
|
+
.map((entry) => `${entry.keyType} ${fingerprintOf(entry.key)} (line ${entry.line})`)
|
|
252
|
+
.join(", ");
|
|
253
|
+
throw new Error(
|
|
254
|
+
`${address} presented ${label}, but ${this.#source} records ${known}: the server's key changed, or something else is answering this port`,
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Splits a byte stream into the lines ServerQuery speaks.
|
|
3
|
+
*
|
|
4
|
+
* A line ends at `\n`. The server writes `\n\r`, so the `\r` belongs to the
|
|
5
|
+
* start of the next line rather than the end of this one; both ends are
|
|
6
|
+
* trimmed. Bytes are decoded as UTF-8 only once a whole line is in, so a
|
|
7
|
+
* character split across two chunks arrives whole.
|
|
8
|
+
*/
|
|
9
|
+
export class LineReader {
|
|
10
|
+
#pending = Buffer.alloc(0);
|
|
11
|
+
|
|
12
|
+
/** Add a chunk and return the lines it completed, without their terminators. */
|
|
13
|
+
push(chunk: Uint8Array): string[] {
|
|
14
|
+
this.#pending = Buffer.concat([this.#pending, chunk]);
|
|
15
|
+
const lines: string[] = [];
|
|
16
|
+
for (;;) {
|
|
17
|
+
const end = this.#pending.indexOf(0x0a);
|
|
18
|
+
if (end < 0) break;
|
|
19
|
+
const line = this.#pending
|
|
20
|
+
.subarray(0, end)
|
|
21
|
+
.toString("utf8")
|
|
22
|
+
.replace(/^\r+|\r+$/g, "");
|
|
23
|
+
this.#pending = this.#pending.subarray(end + 1);
|
|
24
|
+
lines.push(line);
|
|
25
|
+
}
|
|
26
|
+
return lines;
|
|
27
|
+
}
|
|
28
|
+
}
|