@gjsify/tls 0.64.12-next.281 → 0.64.12

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.
@@ -1 +1 @@
1
- import"./_virtual/_rolldown/runtime.js";import{tlsCertToPeerCert as e}from"./internal/cert-utils.js";import{createSecureContext as t}from"./secure-context.js";import{createSessionAccess as n,hasTlsSessionAccess as r}from"./session-access.js";import{createPeerVerifier as i,resolveRejectUnauthorized as a}from"./verify.js";import o from"@girs/gio-2.0";import s from"@girs/glib-2.0";import{Buffer as c}from"node:buffer";import{Socket as l}from"node:net";import u from"node:process";function claimGjsifyConnection(e){let t=e;return typeof t?._claimConnection==`function`?t._claimConnection():null}var TLSSocket=class extends l{encrypted=!0;authorized=!1;authorizationError;alpnProtocol=!1;servername;_tlsConnection=null;_secureContext=null;_sessionAccess=null;_adoptedSocket=null;_awaitingSecure=!1;_afterSecure=[];_handshakeClaim=null;constructor(e,t){super(),e&&this._startClient(e,t??{})}_claimSocketStreams(e){let t=claimGjsifyConnection(e);return t||this.destroy(foreignSocketError()),t}_startClient(e,t){this.servername=t.servername||t.host||`localhost`,this._adoptedSocket=e,this._awaitingSecure=!0,this.once(`close`,()=>{e.destroyed||e.destroy()});let begin=()=>{this._adoptConnection(e).then(e=>{e&&this._performHandshake(t)})};e.connecting?e.once(`connect`,begin):u.nextTick(begin)}async _adoptConnection(e){if(this.destroyed||e.destroyed)return!1;let t=e;if(typeof t._detachReader!=`function`)return this.destroy(foreignSocketError()),!1;let n=this._claimSocketStreams(t);if(!n)return!1;let r=await t._detachReader();if(this.destroyed){try{(n.connection??n.ioStream)?.close(null)}catch{}return!1}if(r&&r.length>0){this.destroy(_upgradeRaceError());try{(n.connection??n.ioStream)?.close(null)}catch{}return!1}let i=this;i._connection=n.connection,i._ioStream=n.ioStream,i._inputStream=n.inputStream,i._outputStream=n.outputStream;let a=this,o=e;return a.remoteAddress=o.remoteAddress,a.remotePort=o.remotePort,a.remoteFamily=o.remoteFamily,a.localAddress=o.localAddress,a.localPort=o.localPort,a.connecting=!1,a.pending=!1,!0}_performHandshake(e){let n=this.servername||e.servername||e.host||`localhost`;this.servername=n;let c=e.port||this.remotePort||443,l=a(e.rejectUnauthorized),u=e.secureContext??t(e);this._secureContext=u;let d=i({caCertificates:u.caCertificates,rejectUnauthorized:e.rejectUnauthorized,host:n,checkServerIdentity:e.checkServerIdentity}),f=this,p=this._claimSocketStreams(f);if(!p)return;let m=p.connection;if(!m){this.destroy(Error(`No underlying connection for TLS upgrade`));return}this._handshakeClaim=p;let fail=e=>{this.destroy(e instanceof Error?e:Error(String(e)))};try{let t=o.NetworkAddress.new(n,c),i=o.TlsClientConnection.new(m,t);if(i.set_server_identity(t),e.session&&r())try{this._tlsConnection=i,this.setSession(e.session)}catch{}if(u.certificate)try{i.set_certificate(u.certificate)}catch(e){console.warn(`[tls] failed to set client certificate:`,e)}e.ALPNProtocols&&e.ALPNProtocols.length>0&&i.set_advertised_protocols(e.ALPNProtocols),i.set_validation_flags(o.TlsCertificateFlags.NO_FLAGS),i.session_resumption_enabled=!1,f._pendingIo++,i.handshake_async(s.PRIORITY_DEFAULT,f._cancellable,(t,n)=>{let r=null;try{i.handshake_finish(n)}catch(e){r=e}if(this.destroyed){f._ioSettled();return}this._handshakeClaim=null,f._ioSettled();let a=r?null:this._verifyPeer(i,d,!!e.session),o=r??(l?a:null);if(o){this.authorized=!1,this.authorizationError=_authorizationError(o),f._connection=i,f._ioStream=i,fail(o);return}this._secureEstablished(i,a?_authorizationError(a):null)})}catch(e){fail(e)}}_verifyPeer(e,t,n){let r=e.get_peer_certificate();return r?(t.accept(r),t.error):n?null:_noPeerCertificateError()}_secureEstablished(e,t){this.authorized=t===null,this.authorizationError=t??void 0,this._setupTlsStreams(e),this.alpnProtocol=this.getAlpnProtocol();let n=this;if(n._reading=!1,n._startReading(),r()){let e=this.getSession();e&&this.emit(`session`,e)}this.emit(`secureConnect`),this._flushAfterSecure()}_write(e,t,n){if(this._awaitingSecure){this._afterSecure.push({run:()=>super._write(e,t,n),abort:()=>n(_destroyedError())});return}super._write(e,t,n)}_flushAfterSecure(){let e=this._afterSecure;this._afterSecure=[];for(let t of e)t.run()}_destroy(e,t){let n=this._handshakeClaim;if(n){this._handshakeClaim=null;let e=this;e._connection=n.connection,e._ioStream=n.ioStream}let r=this._afterSecure;this._afterSecure=[];for(let e of r)e.abort();super._destroy(e,t)}_final(e){if(this._awaitingSecure){this._afterSecure.push({run:()=>this._final(e),abort:()=>{}});return}let t=this._tlsConnection;if(!t){super._final(e);return}let n=this,r=t.get_output_stream();n._pendingIo++,r.close_async(s.PRIORITY_DEFAULT,null,(t,i)=>{try{r.close_finish(i)}catch{}n._ioSettled(),e()})}_setupTlsStreams(e){this._awaitingSecure=!1,this._tlsConnection=e;let t=this;t._inputStream=e.get_input_stream(),t._outputStream=e.get_output_stream(),t._connection=e}_getSessionAccess(){if(this._sessionAccess)return this._sessionAccess;if(!this._tlsConnection)return null;try{this._sessionAccess=n(this._tlsConnection)}catch{this._sessionAccess=null}return this._sessionAccess}getPeerCertificate(t=!1){if(!this._tlsConnection)return{};try{let n=this._tlsConnection.get_peer_certificate();return n?e(n,t):{}}catch{return{}}}getProtocol(){if(!this._tlsConnection)return null;switch(this._tlsConnection.get_protocol_version()){case o.TlsProtocolVersion.TLS_1_0:return`TLSv1`;case o.TlsProtocolVersion.TLS_1_1:return`TLSv1.1`;case o.TlsProtocolVersion.TLS_1_2:return`TLSv1.2`;case o.TlsProtocolVersion.TLS_1_3:return`TLSv1.3`;default:return null}}getCipher(){return this._tlsConnection?{name:this._tlsConnection.get_ciphersuite_name()||`unknown`,version:this.getProtocol()||`unknown`}:null}getAlpnProtocol(){return this._tlsConnection&&this._tlsConnection.get_negotiated_protocol()||!1}getFinished(){if(!r())return;let e=this._getSessionAccess();if(e)try{return _bytesToBuffer(e.get_finished())}catch{return}}getPeerFinished(){if(!r())return;let e=this._getSessionAccess();if(e)try{return _bytesToBuffer(e.get_peer_finished())}catch{return}}getSession(){if(!r())return;let e=this._getSessionAccess();if(e)try{return _bytesToBuffer(e.get_session_data())}catch{return}}setSession(e){if(!r())return;let t=this._getSessionAccess();if(t)try{t.set_session_data(_bufferToBytes(e))}catch{}}isSessionReused(){if(!r())return!1;let e=this._getSessionAccess();if(!e)return!1;try{return e.is_session_reused()}catch{return!1}}};function _destroyedError(){let e=Error(`Cannot call write after a stream was destroyed`);return e.code=`ERR_STREAM_DESTROYED`,e}function _authorizationError(e){return e instanceof Error?e.code??e.message:String(e)}function _noPeerCertificateError(){let e=Error(`the peer presented no certificate (resumed TLS session); nothing to verify`);return e.code=`ERR_GJSIFY_TLS_NO_PEER_CERTIFICATE`,e}function _upgradeRaceError(){let e=Error(`tls: data arrived on the socket before the TLS handshake could take over reading its input stream — Gio.TlsClientConnection has no API to replay already-read bytes into the handshake. This should not happen for a well-behaved STARTTLS peer.`);return e.code=`ERR_GJSIFY_TLS_UPGRADE_RACE`,e}function foreignSocketError(){let e=Error(`tls.connect({socket}) / new tls.TLSSocket(socket, …) can only upgrade a @gjsify/net Socket today — the given socket doesn't carry the Gio connection needed to build a Gio.TlsClientConnection. Generic Duplex support (Node's real contract) is tracked in status/open-todos/README.md.`);return e.code=`ERR_GJSIFY_TLS_FOREIGN_SOCKET`,e}function _bytesToBuffer(e){if(e==null)return;if(e instanceof Uint8Array)return c.from(e);let t=e;if(typeof t.toArray==`function`)try{return c.from(t.toArray())}catch{return}}function _bufferToBytes(e){return e}export{TLSSocket,claimGjsifyConnection,foreignSocketError};
1
+ import"./_virtual/_rolldown/runtime.js";import{tlsCertToPeerCert as e}from"./internal/cert-utils.js";import{createSecureContext as t}from"./secure-context.js";import{createSessionAccess as n,hasTlsSessionAccess as r}from"./session-access.js";import{createPeerVerifier as i,resolveRejectUnauthorized as a}from"./verify.js";import o from"@girs/gio-2.0";import s from"@girs/glib-2.0";import{Buffer as c}from"node:buffer";import{Socket as l}from"node:net";import u from"node:process";function claimGjsifyConnection(e){let t=e;return typeof t?._claimConnection==`function`?t._claimConnection():null}var TLSSocket=class extends l{encrypted=!0;authorized=!1;authorizationError;alpnProtocol=!1;servername;_tlsConnection=null;_secureContext=null;_sessionAccess=null;_adoptedSocket=null;_awaitingSecure=!1;_afterSecure=[];_handshakeClaim=null;constructor(e,t){super(),e&&this._startClient(e,t??{})}_claimSocketStreams(e){let t=claimGjsifyConnection(e);return t||this.destroy(foreignSocketError()),t}_startClient(e,t){this.servername=t.servername||t.host||`localhost`,this._adoptedSocket=e,this._awaitingSecure=!0,this.once(`close`,()=>{e.destroyed||e.destroy()});let begin=()=>{this._adoptConnection(e).then(e=>{e&&(t.isServer?this._performServerHandshake(t):this._performHandshake(t))})};e.connecting?e.once(`connect`,begin):u.nextTick(begin)}async _adoptConnection(e){if(this.destroyed||e.destroyed)return!1;let t=e;if(typeof t._detachReader!=`function`)return this.destroy(foreignSocketError()),!1;let n=this._claimSocketStreams(t);if(!n)return!1;let r=await t._detachReader();if(this.destroyed){try{(n.connection??n.ioStream)?.close(null)}catch{}return!1}if(r&&r.length>0){this.destroy(_upgradeRaceError());try{(n.connection??n.ioStream)?.close(null)}catch{}return!1}let i=this;i._connection=n.connection,i._ioStream=n.ioStream,i._inputStream=n.inputStream,i._outputStream=n.outputStream;let a=this,o=e;return a.remoteAddress=o.remoteAddress,a.remotePort=o.remotePort,a.remoteFamily=o.remoteFamily,a.localAddress=o.localAddress,a.localPort=o.localPort,a.connecting=!1,a.pending=!1,!0}_performHandshake(e){let n=this.servername||e.servername||e.host||`localhost`;this.servername=n;let c=e.port||this.remotePort||443,l=a(e.rejectUnauthorized),u=e.secureContext??t(e);this._secureContext=u;let d=i({caCertificates:u.caCertificates,rejectUnauthorized:e.rejectUnauthorized,host:n,checkServerIdentity:e.checkServerIdentity}),f=this,p=this._claimSocketStreams(f);if(!p)return;let m=p.connection;if(!m){this.destroy(Error(`No underlying connection for TLS upgrade`));return}this._handshakeClaim=p;let fail=e=>{this.destroy(e instanceof Error?e:Error(String(e)))};try{let t=o.NetworkAddress.new(n,c),i=o.TlsClientConnection.new(m,t);if(i.set_server_identity(t),e.session&&r())try{this._tlsConnection=i,this.setSession(e.session)}catch{}if(u.certificate)try{i.set_certificate(u.certificate)}catch(e){console.warn(`[tls] failed to set client certificate:`,e)}e.ALPNProtocols&&e.ALPNProtocols.length>0&&i.set_advertised_protocols(e.ALPNProtocols),i.set_validation_flags(o.TlsCertificateFlags.NO_FLAGS),i.session_resumption_enabled=!1,f._pendingIo++,i.handshake_async(s.PRIORITY_DEFAULT,f._cancellable,(t,n)=>{let r=null;try{i.handshake_finish(n)}catch(e){r=e}if(this.destroyed){f._ioSettled();return}this._handshakeClaim=null,f._ioSettled();let a=r?null:this._verifyPeer(i,d,!!e.session),o=r??(l?a:null);if(o){this.authorized=!1,this.authorizationError=_authorizationError(o),f._connection=i,f._ioStream=i,fail(o);return}this._secureEstablished(i,a?_authorizationError(a):null)})}catch(e){fail(e)}}_performServerHandshake(e){let n=e.secureContext??t(e);this._secureContext=n;let r=this,i=this._claimSocketStreams(r);if(!i)return;let a=i.connection;if(!a){this.destroy(Error(`No underlying connection for TLS upgrade`));return}this._handshakeClaim=i;let fail=e=>{this.destroy(e instanceof Error?e:Error(String(e)))};if(!n.certificate){fail(Error(`TLS server socket has no certificate configured`));return}try{let t=o.TlsServerConnection.new(a,n.certificate),i=!!e.requestCert&&e.rejectUnauthorized!==!1;t.authenticationMode=e.requestCert?i?o.TlsAuthenticationMode.REQUIRED:o.TlsAuthenticationMode.REQUESTED:o.TlsAuthenticationMode.NONE,t.connect(`accept-certificate`,(e,t)=>{if(!i)return!0;for(let e of n.caCertificates)try{if(t.verify(null,e)===o.TlsCertificateFlags.NO_FLAGS)return!0}catch{}return!1}),e.ALPNProtocols&&e.ALPNProtocols.length>0&&t.set_advertised_protocols(e.ALPNProtocols),r._pendingIo++,t.handshake_async(s.PRIORITY_DEFAULT,r._cancellable,(e,n)=>{let i=null;try{t.handshake_finish(n)}catch(e){i=e}if(this.destroyed){r._ioSettled();return}if(this._handshakeClaim=null,r._ioSettled(),i){this.authorized=!1,this.authorizationError=_authorizationError(i),r._connection=t,r._ioStream=t,fail(i);return}this.authorized=!0,this._setupTlsStreams(t),this.alpnProtocol=this.getAlpnProtocol(),r._reading=!1,r._startReading(),this.emit(`secure`),this._flushAfterSecure()})}catch(e){fail(e)}}_verifyPeer(e,t,n){let r=e.get_peer_certificate();return r?(t.accept(r),t.error):n?null:_noPeerCertificateError()}_secureEstablished(e,t){this.authorized=t===null,this.authorizationError=t??void 0,this._setupTlsStreams(e),this.alpnProtocol=this.getAlpnProtocol();let n=this;if(n._reading=!1,n._startReading(),r()){let e=this.getSession();e&&this.emit(`session`,e)}this.emit(`secureConnect`),this._flushAfterSecure()}_write(e,t,n){if(this._awaitingSecure){this._afterSecure.push({run:()=>super._write(e,t,n),abort:()=>n(_destroyedError())});return}super._write(e,t,n)}_flushAfterSecure(){let e=this._afterSecure;this._afterSecure=[];for(let t of e)t.run()}_destroy(e,t){let n=this._handshakeClaim;if(n){this._handshakeClaim=null;let e=this;e._connection=n.connection,e._ioStream=n.ioStream}let r=this._afterSecure;this._afterSecure=[];for(let e of r)e.abort();super._destroy(e,t)}_final(e){if(this._awaitingSecure){this._afterSecure.push({run:()=>this._final(e),abort:()=>{}});return}let t=this._tlsConnection;if(!t){super._final(e);return}let n=this,r=t.get_output_stream();n._pendingIo++,r.close_async(s.PRIORITY_DEFAULT,null,(t,i)=>{try{r.close_finish(i)}catch{}n._ioSettled(),e()})}_setupTlsStreams(e){this._awaitingSecure=!1,this._tlsConnection=e;let t=this;t._inputStream=e.get_input_stream(),t._outputStream=e.get_output_stream(),t._connection=e}_getSessionAccess(){if(this._sessionAccess)return this._sessionAccess;if(!this._tlsConnection)return null;try{this._sessionAccess=n(this._tlsConnection)}catch{this._sessionAccess=null}return this._sessionAccess}getPeerCertificate(t=!1){if(!this._tlsConnection)return{};try{let n=this._tlsConnection.get_peer_certificate();return n?e(n,t):{}}catch{return{}}}getProtocol(){if(!this._tlsConnection)return null;switch(this._tlsConnection.get_protocol_version()){case o.TlsProtocolVersion.TLS_1_0:return`TLSv1`;case o.TlsProtocolVersion.TLS_1_1:return`TLSv1.1`;case o.TlsProtocolVersion.TLS_1_2:return`TLSv1.2`;case o.TlsProtocolVersion.TLS_1_3:return`TLSv1.3`;default:return null}}getCipher(){return this._tlsConnection?{name:this._tlsConnection.get_ciphersuite_name()||`unknown`,version:this.getProtocol()||`unknown`}:null}getAlpnProtocol(){return this._tlsConnection&&this._tlsConnection.get_negotiated_protocol()||!1}getFinished(){if(!r())return;let e=this._getSessionAccess();if(e)try{return _bytesToBuffer(e.get_finished())}catch{return}}getPeerFinished(){if(!r())return;let e=this._getSessionAccess();if(e)try{return _bytesToBuffer(e.get_peer_finished())}catch{return}}getSession(){if(!r())return;let e=this._getSessionAccess();if(e)try{return _bytesToBuffer(e.get_session_data())}catch{return}}setSession(e){if(!r())return;let t=this._getSessionAccess();if(t)try{t.set_session_data(_bufferToBytes(e))}catch{}}isSessionReused(){if(!r())return!1;let e=this._getSessionAccess();if(!e)return!1;try{return e.is_session_reused()}catch{return!1}}};function _destroyedError(){let e=Error(`Cannot call write after a stream was destroyed`);return e.code=`ERR_STREAM_DESTROYED`,e}function _authorizationError(e){return e instanceof Error?e.code??e.message:String(e)}function _noPeerCertificateError(){let e=Error(`the peer presented no certificate (resumed TLS session); nothing to verify`);return e.code=`ERR_GJSIFY_TLS_NO_PEER_CERTIFICATE`,e}function _upgradeRaceError(){let e=Error(`tls: data arrived on the socket before the TLS handshake could take over reading its input stream — Gio.TlsClientConnection has no API to replay already-read bytes into the handshake. This should not happen for a well-behaved STARTTLS peer.`);return e.code=`ERR_GJSIFY_TLS_UPGRADE_RACE`,e}function foreignSocketError(){let e=Error(`tls.connect({socket}) / new tls.TLSSocket(socket, …) can only upgrade a @gjsify/net Socket today — the given socket doesn't carry the Gio connection needed to build a Gio.TlsClientConnection. Generic Duplex support (Node's real contract) is tracked in status/open-todos/README.md.`);return e.code=`ERR_GJSIFY_TLS_FOREIGN_SOCKET`,e}function _bytesToBuffer(e){if(e==null)return;if(e instanceof Uint8Array)return c.from(e);let t=e;if(typeof t.toArray==`function`)try{return c.from(t.toArray())}catch{return}}function _bufferToBytes(e){return e}export{TLSSocket,claimGjsifyConnection,foreignSocketError};
@@ -0,0 +1,2 @@
1
+ declare const _default: () => Promise<void>;
2
+ export default _default;
@@ -23,6 +23,10 @@ export interface TlsConnectOptions extends SecureContextOptions {
23
23
  * yet) — the connection falls back to a full handshake.
24
24
  */
25
25
  session?: Buffer | Uint8Array;
26
+ /** Upgrade the given `socket` as the TLS server (STARTTLS on the accepting side). */
27
+ isServer?: boolean;
28
+ /** Server side: ask the client for a certificate. */
29
+ requestCert?: boolean;
26
30
  }
27
31
  /**
28
32
  * Internal cast for Socket's private-field shape. We own `node:net`'s
@@ -183,6 +187,14 @@ export declare class TLSSocket extends Socket {
183
187
  * Reference: Node.js `lib/internal/tls/wrap.js` `TLSSocket.prototype._init`.
184
188
  */
185
189
  _performHandshake(options: TlsConnectOptions): void;
190
+ /**
191
+ * @internal Server-side counterpart of {@link _performHandshake}: run
192
+ * the TLS handshake as the accepting end over the connection
193
+ * `_adoptConnection` took from the plain socket, i.e.
194
+ * `new tls.TLSSocket(socket, { isServer: true, key, cert })`.
195
+ * Emits 'secure' (Node's server-side event) instead of 'secureConnect'.
196
+ */
197
+ private _performServerHandshake;
186
198
  /**
187
199
  * The error the peer's certificate earns, or null when it is authorized.
188
200
  * A resumed session carries no certificate, so there is nothing to verify:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/tls",
3
- "version": "0.64.12-next.281",
3
+ "version": "0.64.12",
4
4
  "description": "Node.js tls module for Gjs",
5
5
  "type": "module",
6
6
  "module": "lib/esm/index.js",
@@ -41,17 +41,17 @@
41
41
  "tls"
42
42
  ],
43
43
  "devDependencies": {
44
- "@gjsify/cli": "0.64.12-next.281",
45
- "@gjsify/unit": "0.64.12-next.281",
44
+ "@gjsify/cli": "^0.64.12",
45
+ "@gjsify/unit": "^0.64.12",
46
46
  "@types/node": "^25.9.2",
47
47
  "typescript": "^6.0.3"
48
48
  },
49
49
  "dependencies": {
50
50
  "@girs/gio-2.0": "5.4.0",
51
51
  "@girs/glib-2.0": "5.4.0",
52
- "@gjsify/net": "0.64.12-next.281",
53
- "@gjsify/tls-native": "0.64.12-next.281",
54
- "@gjsify/utils": "0.64.12-next.281"
52
+ "@gjsify/net": "^0.64.12",
53
+ "@gjsify/tls-native": "^0.64.12",
54
+ "@gjsify/utils": "^0.64.12"
55
55
  },
56
56
  "gjsify": {
57
57
  "runtimes": {
@@ -74,6 +74,5 @@
74
74
  "bugs": {
75
75
  "url": "https://github.com/gjsify/gjsify/issues"
76
76
  },
77
- "homepage": "https://github.com/gjsify/gjsify/tree/main/packages/node/tls#readme",
78
- "gitHead": "c4d2e266c0d9849860b9828c14ebfe37b6d493b8"
77
+ "homepage": "https://github.com/gjsify/gjsify/tree/main/packages/node/tls#readme"
79
78
  }