Skip to content

Commit a14e5f2

Browse files
committed
starttls
1 parent a2482ee commit a14e5f2

6 files changed

Lines changed: 239 additions & 74 deletions

File tree

include/libwebsockets/lws-client.h

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,23 @@ enum lws_client_connect_ssl_connection_flags {
113113
* http cookies in a Netscape Cookie Jar on this connection */
114114
};
115115

116+
/*
117+
* All lws_tls...() functions must return this type, converting the
118+
* native backend result and doing the extra work to determine which one
119+
* as needed.
120+
*
121+
* Native TLS backend return codes are NOT ALLOWED outside the backend.
122+
*
123+
* Non-SSL mode also uses these types.
124+
*/
125+
enum lws_ssl_capable_status {
126+
LWS_SSL_CAPABLE_ERROR = -1, /* it failed */
127+
LWS_SSL_CAPABLE_DONE = 0, /* it succeeded */
128+
LWS_SSL_CAPABLE_MORE_SERVICE_READ = -2, /* retry WANT_READ */
129+
LWS_SSL_CAPABLE_MORE_SERVICE_WRITE = -3, /* retry WANT_WRITE */
130+
LWS_SSL_CAPABLE_MORE_SERVICE = -4, /* general retry */
131+
};
132+
116133
/** struct lws_client_connect_info - parameters to connect with when using
117134
* lws_client_connect_via_info() */
118135

@@ -500,4 +517,32 @@ lws_http_basic_auth_gen2(const char *user, const void *pw, size_t pwd_len,
500517
LWS_VISIBLE LWS_EXTERN int
501518
lws_tls_session_is_reused(struct lws *wsi);
502519

520+
/**
521+
* lws_tls_client_connect() - perform/progress TLS handshake on client connection
522+
*
523+
* \param wsi: client connection
524+
* \param errbuf: buffer for error string
525+
* \param len: length of errbuf
526+
*
527+
* This is usually handled automatically by lws if LCCSCF_USE_SSL was set on
528+
* the connection. However for STARTTLS type protocols, the connection
529+
* starts in cleartext and this can be called manually later to perform the
530+
* TLS handshake.
531+
*/
532+
LWS_VISIBLE LWS_EXTERN enum lws_ssl_capable_status
533+
lws_tls_client_connect(struct lws *wsi, char *errbuf, size_t len);
534+
535+
/**
536+
* lws_tls_client_upgrade() - upgrade a non-TLS client connection to TLS
537+
*
538+
* \param wsi: client connection
539+
* \param ssl_flags: LCCSCF_ flags to apply
540+
*
541+
* For STARTTLS type protocols, this can be called to transition a RAW
542+
* connection to TLS. It handles structure initialization and starts the
543+
* handshake.
544+
*/
545+
LWS_VISIBLE LWS_EXTERN int
546+
lws_tls_client_upgrade(struct lws *wsi, int ssl_flags);
547+
503548
///@}

lib/core/private-lib-core.h

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -255,22 +255,9 @@ struct lws_tx_credit {
255255

256256
#undef X509_NAME
257257

258-
/*
259-
* All lws_tls...() functions must return this type, converting the
260-
* native backend result and doing the extra work to determine which one
261-
* as needed.
262-
*
263-
* Native TLS backend return codes are NOT ALLOWED outside the backend.
264-
*
265-
* Non-SSL mode also uses these types.
266-
*/
267-
enum lws_ssl_capable_status {
268-
LWS_SSL_CAPABLE_ERROR = -1, /* it failed */
269-
LWS_SSL_CAPABLE_DONE = 0, /* it succeeded */
270-
LWS_SSL_CAPABLE_MORE_SERVICE_READ = -2, /* retry WANT_READ */
271-
LWS_SSL_CAPABLE_MORE_SERVICE_WRITE = -3, /* retry WANT_WRITE */
272-
LWS_SSL_CAPABLE_MORE_SERVICE = -4, /* general retry */
273-
};
258+
/*
259+
* the rest is managed per-context, that includes
260+
*/
274261

275262
enum lws_context_destroy {
276263
LWSCD_NO_DESTROY, /* running */

lib/tls/private-network.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -185,8 +185,6 @@ lws_tls_server_abort_connection(struct lws *wsi);
185185
enum lws_ssl_capable_status
186186
__lws_tls_shutdown(struct lws *wsi);
187187

188-
enum lws_ssl_capable_status
189-
lws_tls_client_connect(struct lws *wsi, char *errbuf, size_t len);
190188
int
191189
lws_tls_client_confirm_peer_cert(struct lws *wsi, char *ebuf, size_t ebuf_len);
192190
int

lib/tls/tls-client.c

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,3 +236,16 @@ lws_client_create_tls(struct lws *wsi, const char **pcce, int do_c1)
236236

237237
return CCTLS_RETURN_DONE; /* OK */
238238
}
239+
240+
int
241+
lws_tls_client_upgrade(struct lws *wsi, int ssl_flags)
242+
{
243+
const char *cce = NULL;
244+
245+
wsi->tls.use_ssl = (unsigned int)ssl_flags;
246+
247+
if (lws_client_create_tls(wsi, &cce, 1) == CCTLS_RETURN_ERROR)
248+
return -1;
249+
250+
return 0;
251+
}

plugins/protocol_lws_dht_dnssec_monitor/assets/monitor.js

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,9 @@ function connect() {
233233
};
234234
}
235235

236+
window.activeTls = [];
237+
window.certStatusCache = {};
238+
236239
function sendReq(obj) {
237240
if (ws && ws.readyState === WebSocket.OPEN) {
238241
ws.send(JSON.stringify(obj));
@@ -325,6 +328,7 @@ function handleResponse(data) {
325328
// We don't fetch get_tls again because we update window.activeTls synchronously.
326329
break;
327330
case 'cert_status':
331+
window.certStatusCache[data.subdomain + ':' + data.port] = data;
328332
let span = document.getElementById(`cert-status-${data.subdomain}`);
329333
if (certCheckTimers[data.subdomain]) {
330334
clearTimeout(certCheckTimers[data.subdomain]);
@@ -419,9 +423,6 @@ function renderZoneTable() {
419423
if (!currentZone) return;
420424

421425
certCheckQueue = [];
422-
Object.values(certCheckTimers).forEach(t => clearTimeout(t));
423-
certCheckTimers = {};
424-
concurrentChecks = 0;
425426
window.renderedTlsFqdns = new Set();
426427
const records = currentZone.records.filter(r => r.type !== 'comment' && r.type !== 'macro');
427428

@@ -457,10 +458,22 @@ function renderZoneTable() {
457458
window.renderedTlsFqdns.add(fqdn);
458459
let activeConfig = window.activeTls ? window.activeTls.find(t => t.fqdn === fqdn) : null;
459460
let portVal = activeConfig ? activeConfig.port : '';
461+
let cacheKey = fqdn + ':' + portVal;
462+
let cached = window.certStatusCache[cacheKey];
463+
let initStatus = '';
464+
let initColor = '#aaa';
465+
if (cached) {
466+
initStatus = cached.msg;
467+
initColor = (cached.status === 'ok') ? '#34d399' : '#f87171';
468+
} else if (certCheckTimers[fqdn]) {
469+
initStatus = 'Checking...';
470+
}
471+
460472
tlsTd = `<td class="ext-tls-cell">
461-
<div style="display:flex; align-items:center; justify-content:flex-start; gap: 0.5rem">
473+
<div style="display:block; text-align: right;">
462474
<input type="number" class="tls-port ext-port" data-fqdn="${fqdn}" value="${portVal}" maxlength="5" placeholder="Port" style="width:70px; background: rgba(0,0,0,0.2); color:#fff; border:1px solid #444; border-radius:4px; padding:2px;">
463-
<span id="cert-status-${fqdn}" class="cert-status" style="font-size:0.8em; color:#aaa;"></span>
475+
<br>
476+
<span id="cert-status-${fqdn}" class="cert-status" style="font-size:0.8em; color:${initColor};">${initStatus}</span>
464477
</div>
465478
</td>`;
466479
}
@@ -483,21 +496,32 @@ function renderZoneTable() {
483496
sendReq({ req: 'delete_tls', domain: currentDomain, subdomain: fqdn });
484497
if (window.activeTls) window.activeTls = window.activeTls.filter(x => x.fqdn !== fqdn);
485498
document.getElementById(`cert-status-${fqdn}`).innerText = '';
499+
Object.keys(window.certStatusCache).forEach(k => {
500+
if (k.startsWith(fqdn + ':')) delete window.certStatusCache[k];
501+
});
486502
} else {
487503
sendReq({ req: 'create_tls', domain: currentDomain, subdomain: fqdn, port: pnum });
488504
if (!window.activeTls) window.activeTls = [];
489505
let exist = window.activeTls.find(x => x.fqdn === fqdn);
490506
if (exist) exist.port = pnum;
491507
else window.activeTls.push({fqdn: fqdn, port: pnum});
492-
508+
509+
if (certCheckTimers[fqdn]) {
510+
clearTimeout(certCheckTimers[fqdn]);
511+
delete certCheckTimers[fqdn];
512+
concurrentChecks = Math.max(0, concurrentChecks - 1);
513+
}
514+
delete window.certStatusCache[fqdn + ':' + pnum];
493515
certCheckQueue.push({fqdn: fqdn, port: pnum});
494516
processCertQueue();
495517
}
496518
};
497519

498520
if (portInput.value) {
499521
let pnum = parseInt(portInput.value, 10);
500-
certCheckQueue.push({fqdn: fqdn, port: pnum});
522+
if (!window.certStatusCache[fqdn + ':' + pnum] && !certCheckTimers[fqdn]) {
523+
certCheckQueue.push({fqdn: fqdn, port: pnum});
524+
}
501525
}
502526
}
503527

0 commit comments

Comments
 (0)