@gjsify/tls 0.3.13 → 0.3.15

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 (2) hide show
  1. package/lib/esm/index.js +344 -351
  2. package/package.json +7 -7
package/lib/esm/index.js CHANGED
@@ -1,377 +1,370 @@
1
1
  import Gio from "@girs/gio-2.0";
2
2
  import GLib from "@girs/glib-2.0";
3
- import { Socket, Server } from "node:net";
3
+ import { Server, Socket } from "node:net";
4
4
  import { createNodeError, deferEmit } from "@gjsify/utils";
5
+
6
+ //#region src/index.ts
5
7
  const DEFAULT_MIN_VERSION = "TLSv1.2";
6
8
  const DEFAULT_MAX_VERSION = "TLSv1.3";
7
9
  const DEFAULT_CIPHERS = "TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384";
10
+ /** Returns a list of supported TLS cipher names (subset; implementation-defined). */
8
11
  function getCiphers() {
9
- return [
10
- "aes-128-gcm",
11
- "aes-256-gcm",
12
- "chacha20-poly1305",
13
- "aes-128-cbc",
14
- "aes-256-cbc"
15
- ];
12
+ return [
13
+ "aes-128-gcm",
14
+ "aes-256-gcm",
15
+ "chacha20-poly1305",
16
+ "aes-128-cbc",
17
+ "aes-256-cbc"
18
+ ];
16
19
  }
20
+ /** Removes a trailing dot from a fully-qualified domain name. */
17
21
  function unfqdn(host) {
18
- return host.endsWith(".") ? host.slice(0, -1) : host;
22
+ return host.endsWith(".") ? host.slice(0, -1) : host;
19
23
  }
24
+ /** Splits a hostname into parts, lower-cased, after removing trailing dots. */
20
25
  function splitHost(host) {
21
- return unfqdn(host).toLowerCase().split(".");
26
+ return unfqdn(host).toLowerCase().split(".");
22
27
  }
28
+ /** Wildcard-match a hostname part list against a pattern (supports leading *). */
23
29
  function checkWildcard(hostParts, pattern) {
24
- const patParts = splitHost(pattern);
25
- if (patParts.length !== hostParts.length) return false;
26
- if (patParts[0] === "*") {
27
- return patParts.slice(1).join(".") === hostParts.slice(1).join(".");
28
- }
29
- return patParts.every((p, i) => p === hostParts[i]);
30
+ const patParts = splitHost(pattern);
31
+ if (patParts.length !== hostParts.length) return false;
32
+ if (patParts[0] === "*") {
33
+ return patParts.slice(1).join(".") === hostParts.slice(1).join(".");
34
+ }
35
+ return patParts.every((p, i) => p === hostParts[i]);
30
36
  }
37
+ /**
38
+ * Verifies that the certificate `cert` is valid for `hostname`.
39
+ * Returns an Error if the check fails, or undefined on success.
40
+ *
41
+ * Reference: Node.js lib/tls.js exports.checkServerIdentity
42
+ */
31
43
  function checkServerIdentity(hostname, cert) {
32
- const subject = cert.subject;
33
- const altNames = cert.subjectaltname;
34
- const dnsNames = [];
35
- const ips = [];
36
- hostname = String(hostname);
37
- if (altNames) {
38
- const parts = altNames.split(", ");
39
- for (const name of parts) {
40
- if (name.startsWith("DNS:")) {
41
- dnsNames.push(name.slice(4));
42
- } else if (name.startsWith("IP Address:")) {
43
- ips.push(name.slice(11).trim());
44
- }
45
- }
46
- }
47
- let valid = false;
48
- let reason = "Unknown reason";
49
- hostname = unfqdn(hostname);
50
- const isIPv4 = /^(\d{1,3}\.){3}\d{1,3}$/.test(hostname);
51
- const isIPv6 = hostname.includes(":");
52
- if (isIPv4 || isIPv6) {
53
- valid = ips.some((ip) => ip.toLowerCase() === hostname.toLowerCase());
54
- if (!valid)
55
- reason = `IP: ${hostname} is not in the cert's list: ${ips.join(", ")}`;
56
- } else if (dnsNames.length > 0 || subject?.CN) {
57
- const hostParts = splitHost(hostname);
58
- if (dnsNames.length > 0) {
59
- valid = dnsNames.some((pattern) => checkWildcard(hostParts, pattern));
60
- if (!valid)
61
- reason = `Host: ${hostname}. is not in the cert's altnames: ${altNames}`;
62
- } else {
63
- const cn = subject.CN;
64
- if (Array.isArray(cn)) {
65
- valid = cn.some((c) => checkWildcard(hostParts, c));
66
- } else if (cn) {
67
- valid = checkWildcard(hostParts, cn);
68
- }
69
- if (!valid)
70
- reason = `Host: ${hostname}. is not cert's CN: ${cn}`;
71
- }
72
- } else {
73
- reason = "Cert does not contain a DNS name";
74
- }
75
- if (!valid) {
76
- const err = new Error(reason);
77
- err.reason = reason;
78
- err.host = hostname;
79
- err.cert = cert;
80
- return err;
81
- }
82
- return void 0;
83
- }
84
- class TLSSocket extends Socket {
85
- encrypted = true;
86
- authorized = false;
87
- authorizationError;
88
- alpnProtocol = false;
89
- /** @internal */
90
- _tlsConnection = null;
91
- constructor(socket, options) {
92
- super();
93
- }
94
- /**
95
- * @internal Wire the TLS connection's I/O streams into this socket
96
- * so that read/write operations go through the encrypted channel.
97
- */
98
- _setupTlsStreams(tlsConn) {
99
- this._tlsConnection = tlsConn;
100
- this._inputStream = tlsConn.get_input_stream();
101
- this._outputStream = tlsConn.get_output_stream();
102
- this._connection = tlsConn;
103
- }
104
- /** Get the peer certificate info. */
105
- getPeerCertificate(_detailed) {
106
- if (!this._tlsConnection) return {};
107
- try {
108
- const cert = this._tlsConnection.get_peer_certificate();
109
- if (!cert) return {};
110
- return {
111
- subject: {},
112
- issuer: {},
113
- valid_from: "",
114
- valid_to: ""
115
- };
116
- } catch {
117
- return {};
118
- }
119
- }
120
- /** Get the negotiated TLS protocol version. */
121
- getProtocol() {
122
- if (!this._tlsConnection) return null;
123
- try {
124
- const proto = this._tlsConnection.get_protocol_version();
125
- switch (proto) {
126
- case Gio.TlsProtocolVersion.TLS_1_0:
127
- return "TLSv1";
128
- case Gio.TlsProtocolVersion.TLS_1_1:
129
- return "TLSv1.1";
130
- case Gio.TlsProtocolVersion.TLS_1_2:
131
- return "TLSv1.2";
132
- case Gio.TlsProtocolVersion.TLS_1_3:
133
- return "TLSv1.3";
134
- default:
135
- return null;
136
- }
137
- } catch {
138
- return null;
139
- }
140
- }
141
- /** Get the cipher info. */
142
- getCipher() {
143
- if (!this._tlsConnection) return null;
144
- try {
145
- const name = this._tlsConnection.get_ciphersuite_name();
146
- return { name: name || "unknown", version: this.getProtocol() || "unknown" };
147
- } catch {
148
- return null;
149
- }
150
- }
151
- /** Get the negotiated ALPN protocol. */
152
- getAlpnProtocol() {
153
- if (!this._tlsConnection) return false;
154
- try {
155
- const proto = this._tlsConnection.get_negotiated_protocol();
156
- return proto || false;
157
- } catch {
158
- return false;
159
- }
160
- }
44
+ const subject = cert.subject;
45
+ const altNames = cert.subjectaltname;
46
+ const dnsNames = [];
47
+ const ips = [];
48
+ hostname = String(hostname);
49
+ if (altNames) {
50
+ const parts = altNames.split(", ");
51
+ for (const name of parts) {
52
+ if (name.startsWith("DNS:")) {
53
+ dnsNames.push(name.slice(4));
54
+ } else if (name.startsWith("IP Address:")) {
55
+ ips.push(name.slice(11).trim());
56
+ }
57
+ }
58
+ }
59
+ let valid = false;
60
+ let reason = "Unknown reason";
61
+ hostname = unfqdn(hostname);
62
+ const isIPv4 = /^(\d{1,3}\.){3}\d{1,3}$/.test(hostname);
63
+ const isIPv6 = hostname.includes(":");
64
+ if (isIPv4 || isIPv6) {
65
+ valid = ips.some((ip) => ip.toLowerCase() === hostname.toLowerCase());
66
+ if (!valid) reason = `IP: ${hostname} is not in the cert's list: ${ips.join(", ")}`;
67
+ } else if (dnsNames.length > 0 || subject?.CN) {
68
+ const hostParts = splitHost(hostname);
69
+ if (dnsNames.length > 0) {
70
+ valid = dnsNames.some((pattern) => checkWildcard(hostParts, pattern));
71
+ if (!valid) reason = `Host: ${hostname}. is not in the cert's altnames: ${altNames}`;
72
+ } else {
73
+ const cn = subject.CN;
74
+ if (Array.isArray(cn)) {
75
+ valid = cn.some((c) => checkWildcard(hostParts, c));
76
+ } else if (cn) {
77
+ valid = checkWildcard(hostParts, cn);
78
+ }
79
+ if (!valid) reason = `Host: ${hostname}. is not cert's CN: ${cn}`;
80
+ }
81
+ } else {
82
+ reason = "Cert does not contain a DNS name";
83
+ }
84
+ if (!valid) {
85
+ const err = new Error(reason);
86
+ err.reason = reason;
87
+ err.host = hostname;
88
+ err.cert = cert;
89
+ return err;
90
+ }
91
+ return undefined;
161
92
  }
93
+ /**
94
+ * TLSSocket wraps a net.Socket with TLS via Gio.TlsConnection.
95
+ */
96
+ var TLSSocket = class extends Socket {
97
+ encrypted = true;
98
+ authorized = false;
99
+ authorizationError;
100
+ alpnProtocol = false;
101
+ /** @internal */
102
+ _tlsConnection = null;
103
+ constructor(socket, options) {
104
+ super();
105
+ }
106
+ /**
107
+ * @internal Wire the TLS connection's I/O streams into this socket
108
+ * so that read/write operations go through the encrypted channel.
109
+ */
110
+ _setupTlsStreams(tlsConn) {
111
+ this._tlsConnection = tlsConn;
112
+ this._inputStream = tlsConn.get_input_stream();
113
+ this._outputStream = tlsConn.get_output_stream();
114
+ this._connection = tlsConn;
115
+ }
116
+ /** Get the peer certificate info. */
117
+ getPeerCertificate(_detailed) {
118
+ if (!this._tlsConnection) return {};
119
+ try {
120
+ const cert = this._tlsConnection.get_peer_certificate();
121
+ if (!cert) return {};
122
+ return {
123
+ subject: {},
124
+ issuer: {},
125
+ valid_from: "",
126
+ valid_to: ""
127
+ };
128
+ } catch {
129
+ return {};
130
+ }
131
+ }
132
+ /** Get the negotiated TLS protocol version. */
133
+ getProtocol() {
134
+ if (!this._tlsConnection) return null;
135
+ try {
136
+ const proto = this._tlsConnection.get_protocol_version();
137
+ switch (proto) {
138
+ case Gio.TlsProtocolVersion.TLS_1_0: return "TLSv1";
139
+ case Gio.TlsProtocolVersion.TLS_1_1: return "TLSv1.1";
140
+ case Gio.TlsProtocolVersion.TLS_1_2: return "TLSv1.2";
141
+ case Gio.TlsProtocolVersion.TLS_1_3: return "TLSv1.3";
142
+ default: return null;
143
+ }
144
+ } catch {
145
+ return null;
146
+ }
147
+ }
148
+ /** Get the cipher info. */
149
+ getCipher() {
150
+ if (!this._tlsConnection) return null;
151
+ try {
152
+ const name = this._tlsConnection.get_ciphersuite_name();
153
+ return {
154
+ name: name || "unknown",
155
+ version: this.getProtocol() || "unknown"
156
+ };
157
+ } catch {
158
+ return null;
159
+ }
160
+ }
161
+ /** Get the negotiated ALPN protocol. */
162
+ getAlpnProtocol() {
163
+ if (!this._tlsConnection) return false;
164
+ try {
165
+ const proto = this._tlsConnection.get_negotiated_protocol();
166
+ return proto || false;
167
+ } catch {
168
+ return false;
169
+ }
170
+ }
171
+ };
172
+ /**
173
+ * Create a TLS client connection.
174
+ *
175
+ * Connects via TCP first (using net.Socket.connect), then upgrades
176
+ * the connection to TLS using Gio.TlsClientConnection.
177
+ */
162
178
  function connect(options, callback) {
163
- const socket = new TLSSocket(void 0, options);
164
- if (callback) {
165
- socket.once("secureConnect", callback);
166
- }
167
- const port = options.port || 443;
168
- const host = options.host || "localhost";
169
- const servername = options.servername || host;
170
- const rejectUnauthorized = options.rejectUnauthorized !== false;
171
- socket.once("connect", () => {
172
- const rawConnection = socket._connection;
173
- if (!rawConnection) {
174
- socket.destroy(new Error("No underlying connection for TLS upgrade"));
175
- return;
176
- }
177
- try {
178
- const connectable = Gio.NetworkAddress.new(servername, port);
179
- const tlsConn = Gio.TlsClientConnection.new(
180
- rawConnection,
181
- connectable
182
- );
183
- tlsConn.set_server_identity(connectable);
184
- if (options.ALPNProtocols && options.ALPNProtocols.length > 0) {
185
- try {
186
- tlsConn.set_advertised_protocols(options.ALPNProtocols);
187
- } catch {
188
- }
189
- }
190
- if (!rejectUnauthorized) {
191
- tlsConn.connect(
192
- "accept-certificate",
193
- () => true
194
- );
195
- }
196
- const cancellable = new Gio.Cancellable();
197
- tlsConn.handshake_async(
198
- GLib.PRIORITY_DEFAULT,
199
- cancellable,
200
- (_source, asyncResult) => {
201
- try {
202
- tlsConn.handshake_finish(asyncResult);
203
- socket.authorized = true;
204
- socket._setupTlsStreams(tlsConn);
205
- socket.alpnProtocol = socket.getAlpnProtocol();
206
- socket._reading = false;
207
- socket._startReading();
208
- socket.emit("secureConnect");
209
- } catch (err) {
210
- socket.authorized = false;
211
- socket.authorizationError = err instanceof Error ? err.message : String(err);
212
- if (rejectUnauthorized) {
213
- socket.destroy(err instanceof Error ? err : new Error(String(err)));
214
- } else {
215
- socket._setupTlsStreams(tlsConn);
216
- socket.emit("secureConnect");
217
- }
218
- }
219
- }
220
- );
221
- } catch (err) {
222
- socket.destroy(err instanceof Error ? err : new Error(String(err)));
223
- }
224
- });
225
- socket.connect({ port, host });
226
- return socket;
179
+ const socket = new TLSSocket(undefined, options);
180
+ if (callback) {
181
+ socket.once("secureConnect", callback);
182
+ }
183
+ const port = options.port || 443;
184
+ const host = options.host || "localhost";
185
+ const servername = options.servername || host;
186
+ const rejectUnauthorized = options.rejectUnauthorized !== false;
187
+ socket.once("connect", () => {
188
+ const rawConnection = socket._connection;
189
+ if (!rawConnection) {
190
+ socket.destroy(new Error("No underlying connection for TLS upgrade"));
191
+ return;
192
+ }
193
+ try {
194
+ const connectable = Gio.NetworkAddress.new(servername, port);
195
+ const tlsConn = Gio.TlsClientConnection.new(rawConnection, connectable);
196
+ tlsConn.set_server_identity(connectable);
197
+ if (options.ALPNProtocols && options.ALPNProtocols.length > 0) {
198
+ try {
199
+ tlsConn.set_advertised_protocols(options.ALPNProtocols);
200
+ } catch {}
201
+ }
202
+ if (!rejectUnauthorized) {
203
+ tlsConn.connect("accept-certificate", () => true);
204
+ }
205
+ const cancellable = new Gio.Cancellable();
206
+ tlsConn.handshake_async(GLib.PRIORITY_DEFAULT, cancellable, (_source, asyncResult) => {
207
+ try {
208
+ tlsConn.handshake_finish(asyncResult);
209
+ socket.authorized = true;
210
+ socket._setupTlsStreams(tlsConn);
211
+ socket.alpnProtocol = socket.getAlpnProtocol();
212
+ socket._reading = false;
213
+ socket._startReading();
214
+ socket.emit("secureConnect");
215
+ } catch (err) {
216
+ socket.authorized = false;
217
+ socket.authorizationError = err instanceof Error ? err.message : String(err);
218
+ if (rejectUnauthorized) {
219
+ socket.destroy(err instanceof Error ? err : new Error(String(err)));
220
+ } else {
221
+ socket._setupTlsStreams(tlsConn);
222
+ socket.emit("secureConnect");
223
+ }
224
+ }
225
+ });
226
+ } catch (err) {
227
+ socket.destroy(err instanceof Error ? err : new Error(String(err)));
228
+ }
229
+ });
230
+ socket.connect({
231
+ port,
232
+ host
233
+ });
234
+ return socket;
227
235
  }
236
+ /**
237
+ * Create a TLS secure context.
238
+ */
228
239
  function createSecureContext(options) {
229
- return { context: options || {} };
240
+ return { context: options || {} };
230
241
  }
231
242
  const rootCertificates = [];
243
+ /**
244
+ * Build a Gio.TlsCertificate from PEM cert+key strings.
245
+ */
232
246
  function buildGioCertificate(cert, key) {
233
- const certStr = Array.isArray(cert) ? cert.map((c) => typeof c === "string" ? c : c.toString("utf-8")).join("\n") : typeof cert === "string" ? cert : cert.toString("utf-8");
234
- const keyStr = key ? Array.isArray(key) ? key.map((k) => typeof k === "string" ? k : k.toString("utf-8")).join("\n") : typeof key === "string" ? key : key.toString("utf-8") : "";
235
- const pem = keyStr ? `${certStr}
236
- ${keyStr}` : certStr;
237
- return Gio.TlsCertificate.new_from_pem(pem, pem.length);
238
- }
239
- class TLSServer extends Server {
240
- _tlsCertificate = null;
241
- _tlsOptions;
242
- _sniContexts = /* @__PURE__ */ new Map();
243
- constructor(options, secureConnectionListener) {
244
- super();
245
- this._tlsOptions = options || {};
246
- if (secureConnectionListener) {
247
- this.on("secureConnection", secureConnectionListener);
248
- }
249
- if (this._tlsOptions.cert) {
250
- try {
251
- this._tlsCertificate = buildGioCertificate(this._tlsOptions.cert, this._tlsOptions.key);
252
- } catch (err) {
253
- deferEmit(this, "error", createNodeError(err, "createServer", {}));
254
- }
255
- }
256
- }
257
- /**
258
- * Add a context for SNI (Server Name Indication).
259
- */
260
- addContext(hostname, context) {
261
- if (context.cert) {
262
- try {
263
- const cert = buildGioCertificate(context.cert, context.key);
264
- this._sniContexts.set(hostname, cert);
265
- } catch (err) {
266
- this.emit("error", createNodeError(err, "addContext", {}));
267
- }
268
- }
269
- }
270
- listen(...args) {
271
- this.on("connection", (socket) => {
272
- this._upgradeTls(socket);
273
- });
274
- return super.listen(...args);
275
- }
276
- /**
277
- * Upgrade a raw TCP socket to TLS using Gio.TlsServerConnection.
278
- */
279
- _upgradeTls(socket) {
280
- const rawConnection = socket._connection;
281
- if (!rawConnection) {
282
- const err = new Error("Cannot upgrade socket: no underlying connection");
283
- this.emit("tlsClientError", err, socket);
284
- socket.destroy();
285
- return;
286
- }
287
- if (!this._tlsCertificate) {
288
- const err = new Error("TLS server has no certificate configured");
289
- this.emit("tlsClientError", err, socket);
290
- socket.destroy();
291
- return;
292
- }
293
- try {
294
- const tlsConn = Gio.TlsServerConnection.new(
295
- rawConnection,
296
- this._tlsCertificate
297
- );
298
- if (this._tlsOptions.requestCert) {
299
- tlsConn.authenticationMode = this._tlsOptions.rejectUnauthorized !== false ? Gio.TlsAuthenticationMode.REQUIRED : Gio.TlsAuthenticationMode.REQUESTED;
300
- } else {
301
- tlsConn.authenticationMode = Gio.TlsAuthenticationMode.NONE;
302
- }
303
- if (this._tlsOptions.rejectUnauthorized === false) {
304
- tlsConn.connect(
305
- "accept-certificate",
306
- () => true
307
- );
308
- }
309
- if (this._tlsOptions.ALPNProtocols && this._tlsOptions.ALPNProtocols.length > 0) {
310
- try {
311
- tlsConn.set_advertised_protocols(this._tlsOptions.ALPNProtocols);
312
- } catch {
313
- }
314
- }
315
- const cancellable = new Gio.Cancellable();
316
- tlsConn.handshake_async(
317
- GLib.PRIORITY_DEFAULT,
318
- cancellable,
319
- (_source, asyncResult) => {
320
- try {
321
- tlsConn.handshake_finish(asyncResult);
322
- const tlsSocket = new TLSSocket();
323
- tlsSocket.encrypted = true;
324
- tlsSocket.authorized = true;
325
- tlsSocket._setupTlsStreams(tlsConn);
326
- tlsSocket.alpnProtocol = tlsSocket.getAlpnProtocol();
327
- tlsSocket._startReading();
328
- this.emit("secureConnection", tlsSocket);
329
- } catch (err) {
330
- const nodeErr = createNodeError(err, "handshake", {});
331
- this.emit("tlsClientError", nodeErr, socket);
332
- socket.destroy();
333
- }
334
- }
335
- );
336
- } catch (err) {
337
- const nodeErr = createNodeError(err, "tls_wrap", {});
338
- this.emit("tlsClientError", nodeErr, socket);
339
- socket.destroy();
340
- }
341
- }
247
+ const certStr = Array.isArray(cert) ? cert.map((c) => typeof c === "string" ? c : c.toString("utf-8")).join("\n") : typeof cert === "string" ? cert : cert.toString("utf-8");
248
+ const keyStr = key ? Array.isArray(key) ? key.map((k) => typeof k === "string" ? k : k.toString("utf-8")).join("\n") : typeof key === "string" ? key : key.toString("utf-8") : "";
249
+ const pem = keyStr ? `${certStr}\n${keyStr}` : certStr;
250
+ return Gio.TlsCertificate.new_from_pem(pem, pem.length);
342
251
  }
252
+ /**
253
+ * TLSServer wraps a net.Server to accept TLS connections.
254
+ */
255
+ var TLSServer = class extends Server {
256
+ _tlsCertificate = null;
257
+ _tlsOptions;
258
+ _sniContexts = new Map();
259
+ constructor(options, secureConnectionListener) {
260
+ super();
261
+ this._tlsOptions = options || {};
262
+ if (secureConnectionListener) {
263
+ this.on("secureConnection", secureConnectionListener);
264
+ }
265
+ if (this._tlsOptions.cert) {
266
+ try {
267
+ this._tlsCertificate = buildGioCertificate(this._tlsOptions.cert, this._tlsOptions.key);
268
+ } catch (err) {
269
+ deferEmit(this, "error", createNodeError(err, "createServer", {}));
270
+ }
271
+ }
272
+ }
273
+ /**
274
+ * Add a context for SNI (Server Name Indication).
275
+ */
276
+ addContext(hostname, context) {
277
+ if (context.cert) {
278
+ try {
279
+ const cert = buildGioCertificate(context.cert, context.key);
280
+ this._sniContexts.set(hostname, cert);
281
+ } catch (err) {
282
+ this.emit("error", createNodeError(err, "addContext", {}));
283
+ }
284
+ }
285
+ }
286
+ listen(...args) {
287
+ this.on("connection", (socket) => {
288
+ this._upgradeTls(socket);
289
+ });
290
+ return super.listen(...args);
291
+ }
292
+ /**
293
+ * Upgrade a raw TCP socket to TLS using Gio.TlsServerConnection.
294
+ */
295
+ _upgradeTls(socket) {
296
+ const rawConnection = socket._connection;
297
+ if (!rawConnection) {
298
+ const err = new Error("Cannot upgrade socket: no underlying connection");
299
+ this.emit("tlsClientError", err, socket);
300
+ socket.destroy();
301
+ return;
302
+ }
303
+ if (!this._tlsCertificate) {
304
+ const err = new Error("TLS server has no certificate configured");
305
+ this.emit("tlsClientError", err, socket);
306
+ socket.destroy();
307
+ return;
308
+ }
309
+ try {
310
+ const tlsConn = Gio.TlsServerConnection.new(rawConnection, this._tlsCertificate);
311
+ if (this._tlsOptions.requestCert) {
312
+ tlsConn.authenticationMode = this._tlsOptions.rejectUnauthorized !== false ? Gio.TlsAuthenticationMode.REQUIRED : Gio.TlsAuthenticationMode.REQUESTED;
313
+ } else {
314
+ tlsConn.authenticationMode = Gio.TlsAuthenticationMode.NONE;
315
+ }
316
+ if (this._tlsOptions.rejectUnauthorized === false) {
317
+ tlsConn.connect("accept-certificate", () => true);
318
+ }
319
+ if (this._tlsOptions.ALPNProtocols && this._tlsOptions.ALPNProtocols.length > 0) {
320
+ try {
321
+ tlsConn.set_advertised_protocols(this._tlsOptions.ALPNProtocols);
322
+ } catch {}
323
+ }
324
+ const cancellable = new Gio.Cancellable();
325
+ tlsConn.handshake_async(GLib.PRIORITY_DEFAULT, cancellable, (_source, asyncResult) => {
326
+ try {
327
+ tlsConn.handshake_finish(asyncResult);
328
+ const tlsSocket = new TLSSocket();
329
+ tlsSocket.encrypted = true;
330
+ tlsSocket.authorized = true;
331
+ tlsSocket._setupTlsStreams(tlsConn);
332
+ tlsSocket.alpnProtocol = tlsSocket.getAlpnProtocol();
333
+ tlsSocket._startReading();
334
+ this.emit("secureConnection", tlsSocket);
335
+ } catch (err) {
336
+ const nodeErr = createNodeError(err, "handshake", {});
337
+ this.emit("tlsClientError", nodeErr, socket);
338
+ socket.destroy();
339
+ }
340
+ });
341
+ } catch (err) {
342
+ const nodeErr = createNodeError(err, "tls_wrap", {});
343
+ this.emit("tlsClientError", nodeErr, socket);
344
+ socket.destroy();
345
+ }
346
+ }
347
+ };
343
348
  function createServer(optionsOrListener, secureConnectionListener) {
344
- if (typeof optionsOrListener === "function") {
345
- return new TLSServer(void 0, optionsOrListener);
346
- }
347
- return new TLSServer(optionsOrListener, secureConnectionListener);
349
+ if (typeof optionsOrListener === "function") {
350
+ return new TLSServer(undefined, optionsOrListener);
351
+ }
352
+ return new TLSServer(optionsOrListener, secureConnectionListener);
348
353
  }
349
- var index_default = {
350
- TLSSocket,
351
- TLSServer,
352
- Server: TLSServer,
353
- connect,
354
- createServer,
355
- createSecureContext,
356
- checkServerIdentity,
357
- getCiphers,
358
- rootCertificates,
359
- DEFAULT_MIN_VERSION,
360
- DEFAULT_MAX_VERSION,
361
- DEFAULT_CIPHERS
362
- };
363
- export {
364
- DEFAULT_CIPHERS,
365
- DEFAULT_MAX_VERSION,
366
- DEFAULT_MIN_VERSION,
367
- TLSServer as Server,
368
- TLSServer,
369
- TLSSocket,
370
- checkServerIdentity,
371
- connect,
372
- createSecureContext,
373
- createServer,
374
- index_default as default,
375
- getCiphers,
376
- rootCertificates
354
+ var src_default = {
355
+ TLSSocket,
356
+ TLSServer,
357
+ Server: TLSServer,
358
+ connect,
359
+ createServer,
360
+ createSecureContext,
361
+ checkServerIdentity,
362
+ getCiphers,
363
+ rootCertificates,
364
+ DEFAULT_MIN_VERSION,
365
+ DEFAULT_MAX_VERSION,
366
+ DEFAULT_CIPHERS
377
367
  };
368
+
369
+ //#endregion
370
+ export { DEFAULT_CIPHERS, DEFAULT_MAX_VERSION, DEFAULT_MIN_VERSION, TLSServer as Server, TLSServer, TLSSocket, checkServerIdentity, connect, createSecureContext, createServer, src_default as default, getCiphers, rootCertificates };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/tls",
3
- "version": "0.3.13",
3
+ "version": "0.3.15",
4
4
  "description": "Node.js tls module for Gjs",
5
5
  "type": "module",
6
6
  "module": "lib/esm/index.js",
@@ -30,15 +30,15 @@
30
30
  "tls"
31
31
  ],
32
32
  "devDependencies": {
33
- "@gjsify/cli": "^0.3.13",
34
- "@gjsify/unit": "^0.3.13",
33
+ "@gjsify/cli": "^0.3.15",
34
+ "@gjsify/unit": "^0.3.15",
35
35
  "@types/node": "^25.6.0",
36
36
  "typescript": "^6.0.3"
37
37
  },
38
38
  "dependencies": {
39
- "@girs/gio-2.0": "^2.88.0-4.0.0-rc.9",
40
- "@girs/glib-2.0": "^2.88.0-4.0.0-rc.9",
41
- "@gjsify/net": "^0.3.13",
42
- "@gjsify/utils": "^0.3.13"
39
+ "@girs/gio-2.0": "2.88.0-4.0.0-rc.9",
40
+ "@girs/glib-2.0": "2.88.0-4.0.0-rc.9",
41
+ "@gjsify/net": "^0.3.15",
42
+ "@gjsify/utils": "^0.3.15"
43
43
  }
44
44
  }