1*1c60b9acSAndroid Build Coastguard Worker /*
2*1c60b9acSAndroid Build Coastguard Worker * libwebsockets - small server side websockets and web server implementation
3*1c60b9acSAndroid Build Coastguard Worker *
4*1c60b9acSAndroid Build Coastguard Worker * Copyright (C) 2010 - 2019 Andy Green <[email protected]>
5*1c60b9acSAndroid Build Coastguard Worker *
6*1c60b9acSAndroid Build Coastguard Worker * Permission is hereby granted, free of charge, to any person obtaining a copy
7*1c60b9acSAndroid Build Coastguard Worker * of this software and associated documentation files (the "Software"), to
8*1c60b9acSAndroid Build Coastguard Worker * deal in the Software without restriction, including without limitation the
9*1c60b9acSAndroid Build Coastguard Worker * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10*1c60b9acSAndroid Build Coastguard Worker * sell copies of the Software, and to permit persons to whom the Software is
11*1c60b9acSAndroid Build Coastguard Worker * furnished to do so, subject to the following conditions:
12*1c60b9acSAndroid Build Coastguard Worker *
13*1c60b9acSAndroid Build Coastguard Worker * The above copyright notice and this permission notice shall be included in
14*1c60b9acSAndroid Build Coastguard Worker * all copies or substantial portions of the Software.
15*1c60b9acSAndroid Build Coastguard Worker *
16*1c60b9acSAndroid Build Coastguard Worker * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17*1c60b9acSAndroid Build Coastguard Worker * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18*1c60b9acSAndroid Build Coastguard Worker * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19*1c60b9acSAndroid Build Coastguard Worker * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20*1c60b9acSAndroid Build Coastguard Worker * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21*1c60b9acSAndroid Build Coastguard Worker * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22*1c60b9acSAndroid Build Coastguard Worker * IN THE SOFTWARE.
23*1c60b9acSAndroid Build Coastguard Worker */
24*1c60b9acSAndroid Build Coastguard Worker
25*1c60b9acSAndroid Build Coastguard Worker #include "private-lib-core.h"
26*1c60b9acSAndroid Build Coastguard Worker
27*1c60b9acSAndroid Build Coastguard Worker /*
28*1c60b9acSAndroid Build Coastguard Worker * fakes POLLIN on all tls guys with buffered rx
29*1c60b9acSAndroid Build Coastguard Worker *
30*1c60b9acSAndroid Build Coastguard Worker * returns nonzero if any tls guys had POLLIN faked
31*1c60b9acSAndroid Build Coastguard Worker */
32*1c60b9acSAndroid Build Coastguard Worker
33*1c60b9acSAndroid Build Coastguard Worker int
lws_tls_fake_POLLIN_for_buffered(struct lws_context_per_thread * pt)34*1c60b9acSAndroid Build Coastguard Worker lws_tls_fake_POLLIN_for_buffered(struct lws_context_per_thread *pt)
35*1c60b9acSAndroid Build Coastguard Worker {
36*1c60b9acSAndroid Build Coastguard Worker int ret = 0;
37*1c60b9acSAndroid Build Coastguard Worker
38*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_dll_safe(struct lws_dll2 *, p, p1,
39*1c60b9acSAndroid Build Coastguard Worker lws_dll2_get_head(&pt->tls.dll_pending_tls_owner)) {
40*1c60b9acSAndroid Build Coastguard Worker struct lws *wsi = lws_container_of(p, struct lws,
41*1c60b9acSAndroid Build Coastguard Worker tls.dll_pending_tls);
42*1c60b9acSAndroid Build Coastguard Worker
43*1c60b9acSAndroid Build Coastguard Worker if (wsi->position_in_fds_table >= 0) {
44*1c60b9acSAndroid Build Coastguard Worker
45*1c60b9acSAndroid Build Coastguard Worker pt->fds[wsi->position_in_fds_table].revents = (short)
46*1c60b9acSAndroid Build Coastguard Worker (pt->fds[wsi->position_in_fds_table].revents |
47*1c60b9acSAndroid Build Coastguard Worker (pt->fds[wsi->position_in_fds_table].events & LWS_POLLIN));
48*1c60b9acSAndroid Build Coastguard Worker ret |= pt->fds[wsi->position_in_fds_table].revents & LWS_POLLIN;
49*1c60b9acSAndroid Build Coastguard Worker }
50*1c60b9acSAndroid Build Coastguard Worker
51*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_dll_safe(p, p1);
52*1c60b9acSAndroid Build Coastguard Worker
53*1c60b9acSAndroid Build Coastguard Worker return !!ret;
54*1c60b9acSAndroid Build Coastguard Worker }
55*1c60b9acSAndroid Build Coastguard Worker
56*1c60b9acSAndroid Build Coastguard Worker void
__lws_ssl_remove_wsi_from_buffered_list(struct lws * wsi)57*1c60b9acSAndroid Build Coastguard Worker __lws_ssl_remove_wsi_from_buffered_list(struct lws *wsi)
58*1c60b9acSAndroid Build Coastguard Worker {
59*1c60b9acSAndroid Build Coastguard Worker lws_dll2_remove(&wsi->tls.dll_pending_tls);
60*1c60b9acSAndroid Build Coastguard Worker }
61*1c60b9acSAndroid Build Coastguard Worker
62*1c60b9acSAndroid Build Coastguard Worker void
lws_ssl_remove_wsi_from_buffered_list(struct lws * wsi)63*1c60b9acSAndroid Build Coastguard Worker lws_ssl_remove_wsi_from_buffered_list(struct lws *wsi)
64*1c60b9acSAndroid Build Coastguard Worker {
65*1c60b9acSAndroid Build Coastguard Worker struct lws_context_per_thread *pt = &wsi->a.context->pt[(int)wsi->tsi];
66*1c60b9acSAndroid Build Coastguard Worker
67*1c60b9acSAndroid Build Coastguard Worker lws_pt_lock(pt, __func__);
68*1c60b9acSAndroid Build Coastguard Worker __lws_ssl_remove_wsi_from_buffered_list(wsi);
69*1c60b9acSAndroid Build Coastguard Worker lws_pt_unlock(pt);
70*1c60b9acSAndroid Build Coastguard Worker }
71*1c60b9acSAndroid Build Coastguard Worker
72*1c60b9acSAndroid Build Coastguard Worker #if defined(LWS_WITH_SERVER)
73*1c60b9acSAndroid Build Coastguard Worker int
lws_tls_check_cert_lifetime(struct lws_vhost * v)74*1c60b9acSAndroid Build Coastguard Worker lws_tls_check_cert_lifetime(struct lws_vhost *v)
75*1c60b9acSAndroid Build Coastguard Worker {
76*1c60b9acSAndroid Build Coastguard Worker time_t now = (time_t)lws_now_secs(), life = 0;
77*1c60b9acSAndroid Build Coastguard Worker struct lws_acme_cert_aging_args caa;
78*1c60b9acSAndroid Build Coastguard Worker union lws_tls_cert_info_results ir;
79*1c60b9acSAndroid Build Coastguard Worker int n;
80*1c60b9acSAndroid Build Coastguard Worker
81*1c60b9acSAndroid Build Coastguard Worker if (v->tls.ssl_ctx && !v->tls.skipped_certs) {
82*1c60b9acSAndroid Build Coastguard Worker
83*1c60b9acSAndroid Build Coastguard Worker if (now < 1542933698) /* Nov 23 2018 00:42 UTC */
84*1c60b9acSAndroid Build Coastguard Worker /* our clock is wrong and we can't judge the certs */
85*1c60b9acSAndroid Build Coastguard Worker return -1;
86*1c60b9acSAndroid Build Coastguard Worker
87*1c60b9acSAndroid Build Coastguard Worker n = lws_tls_vhost_cert_info(v, LWS_TLS_CERT_INFO_VALIDITY_TO,
88*1c60b9acSAndroid Build Coastguard Worker &ir, 0);
89*1c60b9acSAndroid Build Coastguard Worker if (n)
90*1c60b9acSAndroid Build Coastguard Worker return 1;
91*1c60b9acSAndroid Build Coastguard Worker
92*1c60b9acSAndroid Build Coastguard Worker life = (ir.time - now) / (24 * 3600);
93*1c60b9acSAndroid Build Coastguard Worker lwsl_vhost_notice(v, " vhost %s: cert expiry: %dd", v->name,
94*1c60b9acSAndroid Build Coastguard Worker (int)life);
95*1c60b9acSAndroid Build Coastguard Worker } else
96*1c60b9acSAndroid Build Coastguard Worker lwsl_vhost_info(v, " vhost %s: no cert", v->name);
97*1c60b9acSAndroid Build Coastguard Worker
98*1c60b9acSAndroid Build Coastguard Worker memset(&caa, 0, sizeof(caa));
99*1c60b9acSAndroid Build Coastguard Worker caa.vh = v;
100*1c60b9acSAndroid Build Coastguard Worker lws_broadcast(&v->context->pt[0], LWS_CALLBACK_VHOST_CERT_AGING, (void *)&caa,
101*1c60b9acSAndroid Build Coastguard Worker (size_t)(ssize_t)life);
102*1c60b9acSAndroid Build Coastguard Worker
103*1c60b9acSAndroid Build Coastguard Worker return 0;
104*1c60b9acSAndroid Build Coastguard Worker }
105*1c60b9acSAndroid Build Coastguard Worker
106*1c60b9acSAndroid Build Coastguard Worker int
lws_tls_check_all_cert_lifetimes(struct lws_context * context)107*1c60b9acSAndroid Build Coastguard Worker lws_tls_check_all_cert_lifetimes(struct lws_context *context)
108*1c60b9acSAndroid Build Coastguard Worker {
109*1c60b9acSAndroid Build Coastguard Worker struct lws_vhost *v = context->vhost_list;
110*1c60b9acSAndroid Build Coastguard Worker
111*1c60b9acSAndroid Build Coastguard Worker while (v) {
112*1c60b9acSAndroid Build Coastguard Worker if (lws_tls_check_cert_lifetime(v) < 0)
113*1c60b9acSAndroid Build Coastguard Worker return -1;
114*1c60b9acSAndroid Build Coastguard Worker v = v->vhost_next;
115*1c60b9acSAndroid Build Coastguard Worker }
116*1c60b9acSAndroid Build Coastguard Worker
117*1c60b9acSAndroid Build Coastguard Worker return 0;
118*1c60b9acSAndroid Build Coastguard Worker }
119*1c60b9acSAndroid Build Coastguard Worker
120*1c60b9acSAndroid Build Coastguard Worker /*
121*1c60b9acSAndroid Build Coastguard Worker * LWS_TLS_EXTANT_NO : skip adding the cert
122*1c60b9acSAndroid Build Coastguard Worker * LWS_TLS_EXTANT_YES : use the cert and private key paths normally
123*1c60b9acSAndroid Build Coastguard Worker * LWS_TLS_EXTANT_ALTERNATIVE: normal paths not usable, try alternate if poss
124*1c60b9acSAndroid Build Coastguard Worker */
125*1c60b9acSAndroid Build Coastguard Worker enum lws_tls_extant
lws_tls_generic_cert_checks(struct lws_vhost * vhost,const char * cert,const char * private_key)126*1c60b9acSAndroid Build Coastguard Worker lws_tls_generic_cert_checks(struct lws_vhost *vhost, const char *cert,
127*1c60b9acSAndroid Build Coastguard Worker const char *private_key)
128*1c60b9acSAndroid Build Coastguard Worker {
129*1c60b9acSAndroid Build Coastguard Worker int n, m;
130*1c60b9acSAndroid Build Coastguard Worker
131*1c60b9acSAndroid Build Coastguard Worker /*
132*1c60b9acSAndroid Build Coastguard Worker * The user code can choose to either pass the cert and
133*1c60b9acSAndroid Build Coastguard Worker * key filepaths using the info members like this, or it can
134*1c60b9acSAndroid Build Coastguard Worker * leave them NULL; force the vhost SSL_CTX init using the info
135*1c60b9acSAndroid Build Coastguard Worker * options flag LWS_SERVER_OPTION_CREATE_VHOST_SSL_CTX; and
136*1c60b9acSAndroid Build Coastguard Worker * set up the cert himself using the user callback
137*1c60b9acSAndroid Build Coastguard Worker * LWS_CALLBACK_OPENSSL_LOAD_EXTRA_SERVER_VERIFY_CERTS, which
138*1c60b9acSAndroid Build Coastguard Worker * happened just above and has the vhost SSL_CTX * in the user
139*1c60b9acSAndroid Build Coastguard Worker * parameter.
140*1c60b9acSAndroid Build Coastguard Worker */
141*1c60b9acSAndroid Build Coastguard Worker
142*1c60b9acSAndroid Build Coastguard Worker if (!cert || !private_key)
143*1c60b9acSAndroid Build Coastguard Worker return LWS_TLS_EXTANT_NO;
144*1c60b9acSAndroid Build Coastguard Worker
145*1c60b9acSAndroid Build Coastguard Worker n = (int)lws_tls_use_any_upgrade_check_extant(cert);
146*1c60b9acSAndroid Build Coastguard Worker if (n == LWS_TLS_EXTANT_ALTERNATIVE)
147*1c60b9acSAndroid Build Coastguard Worker return LWS_TLS_EXTANT_ALTERNATIVE;
148*1c60b9acSAndroid Build Coastguard Worker m = (int)lws_tls_use_any_upgrade_check_extant(private_key);
149*1c60b9acSAndroid Build Coastguard Worker if (m == LWS_TLS_EXTANT_ALTERNATIVE)
150*1c60b9acSAndroid Build Coastguard Worker return LWS_TLS_EXTANT_ALTERNATIVE;
151*1c60b9acSAndroid Build Coastguard Worker
152*1c60b9acSAndroid Build Coastguard Worker if ((n == LWS_TLS_EXTANT_NO || m == LWS_TLS_EXTANT_NO) &&
153*1c60b9acSAndroid Build Coastguard Worker (vhost->options & LWS_SERVER_OPTION_IGNORE_MISSING_CERT)) {
154*1c60b9acSAndroid Build Coastguard Worker lwsl_vhost_notice(vhost, "Ignoring missing %s or %s", cert, private_key);
155*1c60b9acSAndroid Build Coastguard Worker vhost->tls.skipped_certs = 1;
156*1c60b9acSAndroid Build Coastguard Worker
157*1c60b9acSAndroid Build Coastguard Worker return LWS_TLS_EXTANT_NO;
158*1c60b9acSAndroid Build Coastguard Worker }
159*1c60b9acSAndroid Build Coastguard Worker
160*1c60b9acSAndroid Build Coastguard Worker /*
161*1c60b9acSAndroid Build Coastguard Worker * the cert + key exist
162*1c60b9acSAndroid Build Coastguard Worker */
163*1c60b9acSAndroid Build Coastguard Worker
164*1c60b9acSAndroid Build Coastguard Worker return LWS_TLS_EXTANT_YES;
165*1c60b9acSAndroid Build Coastguard Worker }
166*1c60b9acSAndroid Build Coastguard Worker
167*1c60b9acSAndroid Build Coastguard Worker /*
168*1c60b9acSAndroid Build Coastguard Worker * update the cert for every vhost using the given path
169*1c60b9acSAndroid Build Coastguard Worker */
170*1c60b9acSAndroid Build Coastguard Worker
171*1c60b9acSAndroid Build Coastguard Worker int
lws_tls_cert_updated(struct lws_context * context,const char * certpath,const char * keypath,const char * mem_cert,size_t len_mem_cert,const char * mem_privkey,size_t len_mem_privkey)172*1c60b9acSAndroid Build Coastguard Worker lws_tls_cert_updated(struct lws_context *context, const char *certpath,
173*1c60b9acSAndroid Build Coastguard Worker const char *keypath,
174*1c60b9acSAndroid Build Coastguard Worker const char *mem_cert, size_t len_mem_cert,
175*1c60b9acSAndroid Build Coastguard Worker const char *mem_privkey, size_t len_mem_privkey)
176*1c60b9acSAndroid Build Coastguard Worker {
177*1c60b9acSAndroid Build Coastguard Worker struct lws wsi;
178*1c60b9acSAndroid Build Coastguard Worker
179*1c60b9acSAndroid Build Coastguard Worker wsi.a.context = context;
180*1c60b9acSAndroid Build Coastguard Worker
181*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_ll(struct lws_vhost *, v, context->vhost_list) {
182*1c60b9acSAndroid Build Coastguard Worker wsi.a.vhost = v; /* not a real bound wsi */
183*1c60b9acSAndroid Build Coastguard Worker if (v->tls.alloc_cert_path && v->tls.key_path &&
184*1c60b9acSAndroid Build Coastguard Worker !strcmp(v->tls.alloc_cert_path, certpath) &&
185*1c60b9acSAndroid Build Coastguard Worker !strcmp(v->tls.key_path, keypath)) {
186*1c60b9acSAndroid Build Coastguard Worker lws_tls_server_certs_load(v, &wsi, certpath, keypath,
187*1c60b9acSAndroid Build Coastguard Worker mem_cert, len_mem_cert,
188*1c60b9acSAndroid Build Coastguard Worker mem_privkey, len_mem_privkey);
189*1c60b9acSAndroid Build Coastguard Worker
190*1c60b9acSAndroid Build Coastguard Worker if (v->tls.skipped_certs)
191*1c60b9acSAndroid Build Coastguard Worker lwsl_vhost_notice(v, "vhost %s: cert unset", v->name);
192*1c60b9acSAndroid Build Coastguard Worker }
193*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_ll(v, vhost_next);
194*1c60b9acSAndroid Build Coastguard Worker
195*1c60b9acSAndroid Build Coastguard Worker return 0;
196*1c60b9acSAndroid Build Coastguard Worker }
197*1c60b9acSAndroid Build Coastguard Worker
198*1c60b9acSAndroid Build Coastguard Worker int
lws_gate_accepts(struct lws_context * context,int on)199*1c60b9acSAndroid Build Coastguard Worker lws_gate_accepts(struct lws_context *context, int on)
200*1c60b9acSAndroid Build Coastguard Worker {
201*1c60b9acSAndroid Build Coastguard Worker struct lws_vhost *v = context->vhost_list;
202*1c60b9acSAndroid Build Coastguard Worker
203*1c60b9acSAndroid Build Coastguard Worker lwsl_notice("%s: on = %d\n", __func__, on);
204*1c60b9acSAndroid Build Coastguard Worker
205*1c60b9acSAndroid Build Coastguard Worker if (context->tls_gate_accepts == (char)on)
206*1c60b9acSAndroid Build Coastguard Worker return 0;
207*1c60b9acSAndroid Build Coastguard Worker
208*1c60b9acSAndroid Build Coastguard Worker context->tls_gate_accepts = (char)on;
209*1c60b9acSAndroid Build Coastguard Worker
210*1c60b9acSAndroid Build Coastguard Worker while (v) {
211*1c60b9acSAndroid Build Coastguard Worker lws_start_foreach_dll(struct lws_dll2 *, d,
212*1c60b9acSAndroid Build Coastguard Worker lws_dll2_get_head(&v->listen_wsi)) {
213*1c60b9acSAndroid Build Coastguard Worker struct lws *wsi = lws_container_of(d, struct lws,
214*1c60b9acSAndroid Build Coastguard Worker listen_list);
215*1c60b9acSAndroid Build Coastguard Worker
216*1c60b9acSAndroid Build Coastguard Worker if (v->tls.use_ssl &&
217*1c60b9acSAndroid Build Coastguard Worker lws_change_pollfd(wsi, on ? LWS_POLLIN : 0,
218*1c60b9acSAndroid Build Coastguard Worker on ? 0 : LWS_POLLIN))
219*1c60b9acSAndroid Build Coastguard Worker lwsl_cx_notice(context, "Unable to set POLLIN %d", on);
220*1c60b9acSAndroid Build Coastguard Worker } lws_end_foreach_dll(d);
221*1c60b9acSAndroid Build Coastguard Worker
222*1c60b9acSAndroid Build Coastguard Worker v = v->vhost_next;
223*1c60b9acSAndroid Build Coastguard Worker }
224*1c60b9acSAndroid Build Coastguard Worker
225*1c60b9acSAndroid Build Coastguard Worker return 0;
226*1c60b9acSAndroid Build Coastguard Worker }
227*1c60b9acSAndroid Build Coastguard Worker #endif
228*1c60b9acSAndroid Build Coastguard Worker
229*1c60b9acSAndroid Build Coastguard Worker /* comma-separated alpn list, like "h2,http/1.1" to openssl alpn format */
230*1c60b9acSAndroid Build Coastguard Worker
231*1c60b9acSAndroid Build Coastguard Worker int
lws_alpn_comma_to_openssl(const char * comma,uint8_t * os,int len)232*1c60b9acSAndroid Build Coastguard Worker lws_alpn_comma_to_openssl(const char *comma, uint8_t *os, int len)
233*1c60b9acSAndroid Build Coastguard Worker {
234*1c60b9acSAndroid Build Coastguard Worker uint8_t *oos = os, *plen = NULL;
235*1c60b9acSAndroid Build Coastguard Worker
236*1c60b9acSAndroid Build Coastguard Worker if (!comma)
237*1c60b9acSAndroid Build Coastguard Worker return 0;
238*1c60b9acSAndroid Build Coastguard Worker
239*1c60b9acSAndroid Build Coastguard Worker while (*comma && len > 2) {
240*1c60b9acSAndroid Build Coastguard Worker if (!plen && *comma == ' ') {
241*1c60b9acSAndroid Build Coastguard Worker comma++;
242*1c60b9acSAndroid Build Coastguard Worker continue;
243*1c60b9acSAndroid Build Coastguard Worker }
244*1c60b9acSAndroid Build Coastguard Worker if (!plen) {
245*1c60b9acSAndroid Build Coastguard Worker plen = os++;
246*1c60b9acSAndroid Build Coastguard Worker len--;
247*1c60b9acSAndroid Build Coastguard Worker }
248*1c60b9acSAndroid Build Coastguard Worker
249*1c60b9acSAndroid Build Coastguard Worker if (*comma == ',') {
250*1c60b9acSAndroid Build Coastguard Worker *plen = (uint8_t)lws_ptr_diff(os, plen + 1);
251*1c60b9acSAndroid Build Coastguard Worker plen = NULL;
252*1c60b9acSAndroid Build Coastguard Worker comma++;
253*1c60b9acSAndroid Build Coastguard Worker } else {
254*1c60b9acSAndroid Build Coastguard Worker *os++ = (uint8_t)*comma++;
255*1c60b9acSAndroid Build Coastguard Worker len--;
256*1c60b9acSAndroid Build Coastguard Worker }
257*1c60b9acSAndroid Build Coastguard Worker }
258*1c60b9acSAndroid Build Coastguard Worker
259*1c60b9acSAndroid Build Coastguard Worker if (plen)
260*1c60b9acSAndroid Build Coastguard Worker *plen = (uint8_t)lws_ptr_diff(os, plen + 1);
261*1c60b9acSAndroid Build Coastguard Worker
262*1c60b9acSAndroid Build Coastguard Worker *os = 0;
263*1c60b9acSAndroid Build Coastguard Worker
264*1c60b9acSAndroid Build Coastguard Worker return lws_ptr_diff(os, oos);
265*1c60b9acSAndroid Build Coastguard Worker }
266*1c60b9acSAndroid Build Coastguard Worker
267*1c60b9acSAndroid Build Coastguard Worker
268*1c60b9acSAndroid Build Coastguard Worker
269