1 /*
2 * libwebsockets - small server side websockets and web server implementation
3 *
4 * Copyright (C) 2010 - 2020 Andy Green <andy@warmcat.com>
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to
8 * deal in the Software without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22 * IN THE SOFTWARE.
23 */
24
25 /*
26 * You can leave buf NULL, if so it will be allocated on the heap once the
27 * actual length is known. nf should be 0, it will be set at allocation time.
28 *
29 * Or you can ensure no allocation and use an external buffer by setting buf
30 * and lim. But buf must be in the ep context somehow, since it may have to
31 * survive returns to the event loop unchanged. Set nf to 0 in this case.
32 *
33 * Or you can set buf to an externally allocated buffer, in which case you may
34 * set nf so it will be freed when the string is "freed".
35 */
36
37 #include "private-lib-core.h"
38 /* #include "lws-mqtt.h" */
39 /* 3.1.3.1-5: MUST allow... that contain only the characters... */
40
41 static const uint8_t *code = (const uint8_t *)
42 "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
43
44 static int
lws_mqtt_generate_id(struct lws * wsi,lws_mqtt_str_t ** ms,const char * client_id)45 lws_mqtt_generate_id(struct lws* wsi, lws_mqtt_str_t **ms, const char *client_id)
46 {
47 struct lws_context *context = wsi->context;
48 uint16_t ran[24]; /* 16-bit so wrap bias from %62 diluted by ~1000 */
49 size_t n, len;
50 uint8_t *buf;
51
52 if (client_id)
53 len = strlen(client_id);
54 else
55 len = 23;
56
57 if (len > 23) /* 3.1.3.1-5: Server MUST... between 1 and 23 chars... */
58 return 1;
59
60 *ms = lws_mqtt_str_create((uint16_t)(len + 1));
61 if (!*ms)
62 return 1;
63
64 buf = lws_mqtt_str_next(*ms, NULL);
65
66 if (client_id) {
67 lws_strnncpy((char *)buf, client_id, len, len + 1);
68 lwsl_notice("%s: User space provided a client ID '%s'\n",
69 __func__, (const char *)buf);
70 } else {
71 lwsl_notice("%s: generating random client id\n", __func__);
72 n = len * sizeof(ran[0]);
73 if (lws_get_random(context, ran, n) != n) {
74 lws_mqtt_str_free(ms);
75
76 return 1;
77 }
78
79 for (n = 0; n < len; n++)
80 buf[n] = code[ran[n] % 62];
81 buf[len] = '\0';
82 }
83
84 lws_mqtt_str_advance(*ms, (uint16_t)len);
85
86 return 0;
87 }
88
89 int
lws_read_mqtt(struct lws * wsi,unsigned char * buf,lws_filepos_t len)90 lws_read_mqtt(struct lws *wsi, unsigned char *buf, lws_filepos_t len)
91 {
92 lws_mqttc_t *c = &wsi->mqtt->client;
93
94 return _lws_mqtt_rx_parser(wsi, &c->par, buf, len);
95 }
96
97 int
lws_create_client_mqtt_object(const struct lws_client_connect_info * i,struct lws * wsi)98 lws_create_client_mqtt_object(const struct lws_client_connect_info *i,
99 struct lws *wsi)
100 {
101 lws_mqttc_t *c;
102 const lws_mqtt_client_connect_param_t *cp = i->mqtt_cp;
103
104 /* allocate the ws struct for the wsi */
105 wsi->mqtt = lws_zalloc(sizeof(*wsi->mqtt), "client mqtt struct");
106 if (!wsi->mqtt)
107 goto oom;
108
109 wsi->mqtt->wsi = wsi;
110 c = &wsi->mqtt->client;
111
112 if (lws_mqtt_generate_id(wsi, &c->id, cp->client_id)) {
113 lwsl_err("%s: Error generating client ID\n", __func__);
114 return 1;
115 }
116 lwsl_info("%s: using client id '%.*s'\n", __func__, c->id->len,
117 (const char *)c->id->buf);
118
119 if (cp->clean_start || !cp->client_id[0])
120 c->conn_flags = LMQCFT_CLEAN_START;
121
122 c->keep_alive_secs = cp->keep_alive;
123
124 if (cp->will_param.topic &&
125 *cp->will_param.topic) {
126 c->will.topic = lws_mqtt_str_create_cstr_dup(
127 cp->will_param.topic, 0);
128 if (!c->will.topic)
129 goto oom1;
130 c->conn_flags |= LMQCFT_WILL_FLAG;
131 if (cp->will_param.message) {
132 c->will.message = lws_mqtt_str_create_cstr_dup(
133 cp->will_param.message, 0);
134 if (!c->will.message)
135 goto oom2;
136 }
137 c->conn_flags |= (cp->will_param.qos << 3) & LMQCFT_WILL_QOS_MASK;
138 c->conn_flags |= (!!cp->will_param.retain) * LMQCFT_WILL_RETAIN;
139 }
140
141 if (cp->username &&
142 *cp->username) {
143 c->username = lws_mqtt_str_create_cstr_dup(cp->username, 0);
144 if (!c->username)
145 goto oom3;
146 c->conn_flags |= LMQCFT_USERNAME;
147 if (cp->password) {
148 c->password =
149 lws_mqtt_str_create_cstr_dup(cp->password, 0);
150 if (!c->password)
151 goto oom4;
152 c->conn_flags |= LMQCFT_PASSWORD;
153 }
154 }
155
156 return 0;
157 oom4:
158 lws_mqtt_str_free(&c->username);
159 oom3:
160 lws_mqtt_str_free(&c->will.message);
161 oom2:
162 lws_mqtt_str_free(&c->will.topic);
163 oom1:
164 lws_mqtt_str_free(&c->id);
165 oom:
166 lwsl_err("%s: OOM!\n", __func__);
167 return 1;
168 }
169
170 int
lws_mqtt_client_socket_service(struct lws * wsi,struct lws_pollfd * pollfd,struct lws * wsi_conn)171 lws_mqtt_client_socket_service(struct lws *wsi, struct lws_pollfd *pollfd,
172 struct lws *wsi_conn)
173 {
174 struct lws_context *context = wsi->context;
175 struct lws_context_per_thread *pt = &context->pt[(int)wsi->tsi];
176 int n = 0, m = 0;
177 struct lws_tokens ebuf;
178 int buffered = 0;
179 char pending = 0;
180 #if defined(LWS_WITH_TLS)
181 char erbuf[128];
182 #endif
183 const char *cce = NULL;
184
185 switch (lwsi_state(wsi)) {
186 #if defined(LWS_WITH_SOCKS5)
187 /* SOCKS Greeting Reply */
188 case LRS_WAITING_SOCKS_GREETING_REPLY:
189 case LRS_WAITING_SOCKS_AUTH_REPLY:
190 case LRS_WAITING_SOCKS_CONNECT_REPLY:
191
192 switch (lws_socks5c_handle_state(wsi, pollfd, &cce)) {
193 case LW5CHS_RET_RET0:
194 return 0;
195 case LW5CHS_RET_BAIL3:
196 goto bail3;
197 case LW5CHS_RET_STARTHS:
198
199 /*
200 * Now we got the socks5 connection, we need to go down
201 * the tls path on it if that's what we want
202 */
203
204 if (!(wsi->tls.use_ssl & LCCSCF_USE_SSL))
205 goto start_ws_handshake;
206
207 switch (lws_client_create_tls(wsi, &cce, 0)) {
208 case 0:
209 break;
210 case 1:
211 return 0;
212 default:
213 goto bail3;
214 }
215
216 break;
217
218 default:
219 break;
220 }
221 break;
222 #endif
223 case LRS_WAITING_DNS:
224 /*
225 * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
226 * timeout protection set in client-handshake.c
227 */
228 if (!lws_client_connect_2_dnsreq(wsi)) {
229 /* closed */
230 lwsl_client("closed\n");
231 return -1;
232 }
233
234 /* either still pending connection, or changed mode */
235 return 0;
236
237 case LRS_WAITING_CONNECT:
238
239 /*
240 * we are under PENDING_TIMEOUT_SENT_CLIENT_HANDSHAKE
241 * timeout protection set in client-handshake.c
242 */
243 if (pollfd->revents & LWS_POLLOUT)
244 lws_client_connect_3_connect(wsi, NULL, NULL, 0, NULL);
245 break;
246
247 #if defined(LWS_WITH_TLS)
248 case LRS_WAITING_SSL:
249
250 if (wsi->tls.use_ssl & LCCSCF_USE_SSL) {
251 n = lws_ssl_client_connect2(wsi, erbuf, sizeof(erbuf));
252 if (!n)
253 return 0;
254 if (n < 0) {
255 cce = erbuf;
256 goto bail3;
257 }
258 } else
259 wsi->tls.ssl = NULL;
260 #endif /* LWS_WITH_TLS */
261
262 #if defined(LWS_WITH_DETAILED_LATENCY)
263 if (context->detailed_latency_cb) {
264 wsi->detlat.type = LDLT_TLS_NEG_CLIENT;
265 wsi->detlat.latencies[LAT_DUR_PROXY_CLIENT_REQ_TO_WRITE] =
266 lws_now_usecs() -
267 wsi->detlat.earliest_write_req_pre_write;
268 wsi->detlat.latencies[LAT_DUR_USERCB] = 0;
269 lws_det_lat_cb(wsi->context, &wsi->detlat);
270 }
271 #endif
272 #if 0
273 if (wsi->client_h2_alpn) {
274 /*
275 * We connected to the server and set up tls, and
276 * negotiated "h2".
277 *
278 * So this is it, we are an h2 master client connection
279 * now, not an h1 client connection.
280 */
281 #if defined(LWS_WITH_TLS)
282 lws_tls_server_conn_alpn(wsi);
283 #endif
284
285 /* send the H2 preface to legitimize the connection */
286 if (lws_h2_issue_preface(wsi)) {
287 cce = "error sending h2 preface";
288 goto bail3;
289 }
290
291 break;
292 }
293 #endif
294
295 /* fallthru */
296
297 #if defined(LWS_WITH_SOCKS5)
298 start_ws_handshake:
299 #endif
300 lwsi_set_state(wsi, LRS_MQTTC_IDLE);
301 lws_set_timeout(wsi, PENDING_TIMEOUT_AWAITING_CLIENT_HS_SEND,
302 context->timeout_secs);
303
304 /* fallthru */
305
306 case LRS_MQTTC_IDLE:
307 /*
308 * we should be ready to send out MQTT CONNECT
309 */
310 lwsl_info("%s: wsi %p: Transport established, send out CONNECT\n",
311 __func__, wsi);
312 if (lws_change_pollfd(wsi, LWS_POLLOUT, 0))
313 return -1;
314 if (!lws_mqtt_client_send_connect(wsi)) {
315 lwsl_err("%s: Unable to send MQTT CONNECT\n", __func__);
316 return -1;
317 }
318 if (lws_change_pollfd(wsi, 0, LWS_POLLIN))
319 return -1;
320
321 lwsi_set_state(wsi, LRS_MQTTC_AWAIT_CONNACK);
322 return 0;
323
324 case LRS_ESTABLISHED:
325 case LRS_MQTTC_AWAIT_CONNACK:
326 buffered = 0;
327 ebuf.token = pt->serv_buf;
328 ebuf.len = wsi->context->pt_serv_buf_size;
329
330 if ((unsigned int)ebuf.len > wsi->context->pt_serv_buf_size)
331 ebuf.len = wsi->context->pt_serv_buf_size;
332
333 if ((int)pending > ebuf.len)
334 pending = ebuf.len;
335
336 ebuf.len = lws_ssl_capable_read(wsi, ebuf.token,
337 pending ? (int)pending :
338 ebuf.len);
339 switch (ebuf.len) {
340 case 0:
341 lwsl_info("%s: zero length read\n",
342 __func__);
343 goto fail;
344 case LWS_SSL_CAPABLE_MORE_SERVICE:
345 lwsl_info("SSL Capable more service\n");
346 return 0;
347 case LWS_SSL_CAPABLE_ERROR:
348 lwsl_info("%s: LWS_SSL_CAPABLE_ERROR\n",
349 __func__);
350 goto fail;
351 }
352
353 if (ebuf.len < 0)
354 n = -1;
355 else
356 n = lws_read_mqtt(wsi, ebuf.token, ebuf.len);
357 if (n < 0) {
358 lwsl_err("%s: Parsing packet failed\n", __func__);
359 goto fail;
360 }
361
362 m = ebuf.len - n;
363 // lws_buflist_describe(&wsi->buflist, wsi, __func__);
364 lwsl_debug("%s: consuming %d / %d\n", __func__, n, ebuf.len);
365 if (lws_buflist_aware_finished_consuming(wsi, &ebuf, m,
366 buffered,
367 __func__))
368 return -1;
369
370 return 0;
371
372 #if defined(LWS_WITH_TLS) || defined(LWS_WITH_SOCKS5)
373 bail3:
374 #endif
375 lwsl_info("closing conn at LWS_CONNMODE...SERVER_REPLY\n");
376 if (cce)
377 lwsl_info("reason: %s\n", cce);
378 lws_inform_client_conn_fail(wsi, (void *)cce, strlen(cce));
379
380 lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "cbail3");
381 return -1;
382
383 default:
384 break;
385 }
386
387 return 0;
388 fail:
389 lws_close_free_wsi(wsi, LWS_CLOSE_STATUS_NOSTATUS, "mqtt svc fail");
390
391 return LWS_HPI_RET_WSI_ALREADY_DIED;
392 }
393