Blame


1 b42d807f 2023-09-02 op /*
2 b42d807f 2023-09-02 op * This is free and unencumbered software released into the public domain.
3 b42d807f 2023-09-02 op *
4 b42d807f 2023-09-02 op * Anyone is free to copy, modify, publish, use, compile, sell, or
5 b42d807f 2023-09-02 op * distribute this software, either in source code form or as a compiled
6 b42d807f 2023-09-02 op * binary, for any purpose, commercial or non-commercial, and by any
7 b42d807f 2023-09-02 op * means.
8 b42d807f 2023-09-02 op *
9 b42d807f 2023-09-02 op * In jurisdictions that recognize copyright laws, the author or authors
10 b42d807f 2023-09-02 op * of this software dedicate any and all copyright interest in the
11 b42d807f 2023-09-02 op * software to the public domain. We make this dedication for the benefit
12 b42d807f 2023-09-02 op * of the public at large and to the detriment of our heirs and
13 b42d807f 2023-09-02 op * successors. We intend this dedication to be an overt act of
14 b42d807f 2023-09-02 op * relinquishment in perpetuity of all present and future rights to this
15 b42d807f 2023-09-02 op * software under copyright law.
16 b42d807f 2023-09-02 op *
17 b42d807f 2023-09-02 op * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 b42d807f 2023-09-02 op * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 b42d807f 2023-09-02 op * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
20 b42d807f 2023-09-02 op * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 b42d807f 2023-09-02 op * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 b42d807f 2023-09-02 op * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 b42d807f 2023-09-02 op * OTHER DEALINGS IN THE SOFTWARE.
24 b42d807f 2023-09-02 op */
25 b42d807f 2023-09-02 op
26 b42d807f 2023-09-02 op #include "config.h"
27 b42d807f 2023-09-02 op
28 b42d807f 2023-09-02 op #include <arpa/inet.h>
29 b42d807f 2023-09-02 op #include <errno.h>
30 b42d807f 2023-09-02 op #include <stdio.h>
31 b42d807f 2023-09-02 op #include <stdint.h>
32 b42d807f 2023-09-02 op #include <string.h>
33 b42d807f 2023-09-02 op #include <sha1.h>
34 b42d807f 2023-09-02 op
35 b42d807f 2023-09-02 op #include "bufio.h"
36 b42d807f 2023-09-02 op #include "http.h"
37 b42d807f 2023-09-02 op #include "ws.h"
38 b42d807f 2023-09-02 op
39 b42d807f 2023-09-02 op #define WS_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
40 b42d807f 2023-09-02 op
41 b42d807f 2023-09-02 op static int
42 b42d807f 2023-09-02 op tob64(unsigned char ch)
43 b42d807f 2023-09-02 op {
44 b42d807f 2023-09-02 op if (ch < 26)
45 b42d807f 2023-09-02 op return ('A' + ch);
46 b42d807f 2023-09-02 op ch -= 26;
47 b42d807f 2023-09-02 op if (ch < 26)
48 b42d807f 2023-09-02 op return ('a' + ch);
49 b42d807f 2023-09-02 op ch -= 26;
50 b42d807f 2023-09-02 op if (ch < 10)
51 b42d807f 2023-09-02 op return ('0' + ch);
52 b42d807f 2023-09-02 op ch -= 10;
53 b42d807f 2023-09-02 op if (ch == 0)
54 b42d807f 2023-09-02 op return ('+');
55 b42d807f 2023-09-02 op if (ch == 1)
56 b42d807f 2023-09-02 op return ('/');
57 b42d807f 2023-09-02 op errno = EINVAL;
58 b42d807f 2023-09-02 op return (-1);
59 b42d807f 2023-09-02 op }
60 b42d807f 2023-09-02 op
61 b42d807f 2023-09-02 op static int
62 b42d807f 2023-09-02 op b64encode(unsigned char *in, size_t ilen, char *out, size_t olen)
63 b42d807f 2023-09-02 op {
64 b42d807f 2023-09-02 op int r;
65 b42d807f 2023-09-02 op
66 b42d807f 2023-09-02 op #define SET(x) { \
67 b42d807f 2023-09-02 op if ((r = tob64((x) & 0x3F)) == -1) \
68 b42d807f 2023-09-02 op return (-1); \
69 b42d807f 2023-09-02 op *out++ = r; \
70 b42d807f 2023-09-02 op }
71 b42d807f 2023-09-02 op
72 b42d807f 2023-09-02 op while (ilen > 0) {
73 b42d807f 2023-09-02 op if (olen < 4) {
74 b42d807f 2023-09-02 op errno = ENOSPC;
75 b42d807f 2023-09-02 op return (-1);
76 b42d807f 2023-09-02 op }
77 b42d807f 2023-09-02 op olen -= 4;
78 b42d807f 2023-09-02 op
79 b42d807f 2023-09-02 op switch (ilen) {
80 b42d807f 2023-09-02 op case 1:
81 b42d807f 2023-09-02 op SET(in[0] >> 2);
82 b42d807f 2023-09-02 op SET(in[0] << 4);
83 b42d807f 2023-09-02 op *out++ = '=';
84 b42d807f 2023-09-02 op *out++ = '=';
85 b42d807f 2023-09-02 op ilen = 0;
86 b42d807f 2023-09-02 op break;
87 b42d807f 2023-09-02 op case 2:
88 b42d807f 2023-09-02 op SET(in[0] >> 2);
89 b42d807f 2023-09-02 op SET(in[0] << 4 | in[1] >> 4);
90 b42d807f 2023-09-02 op SET(in[1] << 2);
91 b42d807f 2023-09-02 op *out++ = '=';
92 b42d807f 2023-09-02 op ilen = 0;
93 b42d807f 2023-09-02 op break;
94 b42d807f 2023-09-02 op default:
95 b42d807f 2023-09-02 op SET(in[0] >> 2);
96 b42d807f 2023-09-02 op SET(in[0] << 4 | in[1] >> 4);
97 b42d807f 2023-09-02 op SET(in[1] << 2 | in[2] >> 6);
98 b42d807f 2023-09-02 op SET(in[2]);
99 b42d807f 2023-09-02 op ilen -= 3;
100 b42d807f 2023-09-02 op in += 3;
101 b42d807f 2023-09-02 op break;
102 b42d807f 2023-09-02 op }
103 b42d807f 2023-09-02 op }
104 b42d807f 2023-09-02 op
105 b42d807f 2023-09-02 op #undef SET
106 b42d807f 2023-09-02 op
107 b42d807f 2023-09-02 op if (olen < 1) {
108 b42d807f 2023-09-02 op errno = ENOSPC;
109 b42d807f 2023-09-02 op return (-1);
110 b42d807f 2023-09-02 op }
111 b42d807f 2023-09-02 op *out = '\0';
112 b42d807f 2023-09-02 op return (0);
113 b42d807f 2023-09-02 op }
114 b42d807f 2023-09-02 op
115 b42d807f 2023-09-02 op int
116 b42d807f 2023-09-02 op ws_accept_hdr(const char *secret, char *out, size_t olen)
117 b42d807f 2023-09-02 op {
118 b42d807f 2023-09-02 op SHA1_CTX ctx;
119 b42d807f 2023-09-02 op uint8_t hash[SHA1_DIGEST_LENGTH];
120 b42d807f 2023-09-02 op
121 b42d807f 2023-09-02 op SHA1Init(&ctx);
122 b42d807f 2023-09-02 op SHA1Update(&ctx, secret, strlen(secret));
123 b42d807f 2023-09-02 op SHA1Update(&ctx, WS_GUID, strlen(WS_GUID));
124 b42d807f 2023-09-02 op SHA1Final(hash, &ctx);
125 b42d807f 2023-09-02 op
126 b42d807f 2023-09-02 op return (b64encode(hash, sizeof(hash), out, olen));
127 b42d807f 2023-09-02 op }
128 b42d807f 2023-09-02 op
129 b42d807f 2023-09-02 op int
130 b42d807f 2023-09-02 op ws_read(struct client *clt, int *type, size_t *len)
131 b42d807f 2023-09-02 op {
132 6be81433 2024-04-14 op struct buf *rbuf = &clt->bio.rbuf;
133 b42d807f 2023-09-02 op size_t i;
134 b42d807f 2023-09-02 op uint32_t mask;
135 b42d807f 2023-09-02 op uint8_t first, second, op, plen;
136 b42d807f 2023-09-02 op
137 b42d807f 2023-09-02 op *type = WST_UNKNOWN, *len = 0;
138 b42d807f 2023-09-02 op
139 b42d807f 2023-09-02 op if (rbuf->len < 2) {
140 b42d807f 2023-09-02 op errno = EAGAIN;
141 b42d807f 2023-09-02 op return (-1);
142 b42d807f 2023-09-02 op }
143 b42d807f 2023-09-02 op
144 b42d807f 2023-09-02 op memcpy(&first, &rbuf->buf[0], sizeof(first));
145 b42d807f 2023-09-02 op memcpy(&second, &rbuf->buf[1], sizeof(second));
146 b42d807f 2023-09-02 op
147 b42d807f 2023-09-02 op /* for the close message this doesn't seem to be the case... */
148 b42d807f 2023-09-02 op #if 0
149 b42d807f 2023-09-02 op /* the reserved bits must be zero, don't care about FIN */
150 b42d807f 2023-09-02 op if ((first & 0x0E) != 0) {
151 b42d807f 2023-09-02 op errno = EINVAL;
152 b42d807f 2023-09-02 op return (-1);
153 b42d807f 2023-09-02 op }
154 b42d807f 2023-09-02 op #endif
155 b42d807f 2023-09-02 op
156 b42d807f 2023-09-02 op /* mask must be set for messages sent by the clients */
157 b42d807f 2023-09-02 op if ((second >> 7) != 1) {
158 b42d807f 2023-09-02 op errno = EINVAL;
159 b42d807f 2023-09-02 op return (-1);
160 b42d807f 2023-09-02 op }
161 b42d807f 2023-09-02 op
162 b42d807f 2023-09-02 op op = first & 0x0F;
163 b42d807f 2023-09-02 op plen = second & 0x7F;
164 b42d807f 2023-09-02 op
165 b42d807f 2023-09-02 op /* don't support extended payload length for now */
166 b42d807f 2023-09-02 op if (plen >= 126) {
167 b42d807f 2023-09-02 op errno = E2BIG;
168 b42d807f 2023-09-02 op return (-1);
169 b42d807f 2023-09-02 op }
170 b42d807f 2023-09-02 op
171 b42d807f 2023-09-02 op *len = plen;
172 b42d807f 2023-09-02 op
173 b42d807f 2023-09-02 op switch (op) {
174 b42d807f 2023-09-02 op case WST_CONT:
175 b42d807f 2023-09-02 op case WST_TEXT:
176 b42d807f 2023-09-02 op case WST_BINARY:
177 b42d807f 2023-09-02 op case WST_CLOSE:
178 b42d807f 2023-09-02 op case WST_PING:
179 b42d807f 2023-09-02 op *type = op;
180 b42d807f 2023-09-02 op break;
181 b42d807f 2023-09-02 op }
182 b42d807f 2023-09-02 op
183 b42d807f 2023-09-02 op if (rbuf->len < sizeof(first) + sizeof(second) + sizeof(mask) + plen) {
184 b42d807f 2023-09-02 op errno = EAGAIN;
185 b42d807f 2023-09-02 op return (-1);
186 b42d807f 2023-09-02 op }
187 b42d807f 2023-09-02 op
188 b42d807f 2023-09-02 op buf_drain(rbuf, 2); /* header */
189 b42d807f 2023-09-02 op memcpy(&mask, rbuf->buf, sizeof(mask));
190 b42d807f 2023-09-02 op buf_drain(rbuf, 4);
191 b42d807f 2023-09-02 op
192 b42d807f 2023-09-02 op /* decode the payload */
193 b42d807f 2023-09-02 op for (i = 0; i < plen; ++i)
194 b42d807f 2023-09-02 op rbuf->buf[i] ^= mask >> (8 * (i % 4));
195 b42d807f 2023-09-02 op
196 b42d807f 2023-09-02 op return (0);
197 b42d807f 2023-09-02 op }
198 b42d807f 2023-09-02 op
199 b42d807f 2023-09-02 op int
200 b42d807f 2023-09-02 op ws_compose(struct client *clt, int type, const void *data, size_t len)
201 b42d807f 2023-09-02 op {
202 b42d807f 2023-09-02 op struct bufio *bio = &clt->bio;
203 b42d807f 2023-09-02 op uint16_t extlen = 0;
204 b42d807f 2023-09-02 op uint8_t first, second;
205 b42d807f 2023-09-02 op
206 b42d807f 2023-09-02 op first = (type & 0x0F) | 0x80;
207 b42d807f 2023-09-02 op
208 b42d807f 2023-09-02 op if (len < 126)
209 b42d807f 2023-09-02 op second = len;
210 b42d807f 2023-09-02 op else {
211 b42d807f 2023-09-02 op second = 126;
212 b42d807f 2023-09-02 op
213 b42d807f 2023-09-02 op /*
214 b42d807f 2023-09-02 op * for the extended length, the most significant bit
215 b42d807f 2023-09-02 op * must be zero. We could use the 64 bit field but
216 b42d807f 2023-09-02 op * it's a waste.
217 b42d807f 2023-09-02 op */
218 b42d807f 2023-09-02 op if (len > 0x7FFF) {
219 b42d807f 2023-09-02 op errno = ERANGE;
220 b42d807f 2023-09-02 op return (-1);
221 b42d807f 2023-09-02 op }
222 b42d807f 2023-09-02 op extlen = htons(len);
223 b42d807f 2023-09-02 op }
224 b42d807f 2023-09-02 op
225 b42d807f 2023-09-02 op if (bufio_compose(bio, &first, 1) == -1 ||
226 b42d807f 2023-09-02 op bufio_compose(bio, &second, 1) == -1)
227 b42d807f 2023-09-02 op goto err;
228 b42d807f 2023-09-02 op
229 b42d807f 2023-09-02 op if (extlen != 0 && bufio_compose(bio, &extlen, sizeof(extlen)) == -1)
230 b42d807f 2023-09-02 op goto err;
231 b42d807f 2023-09-02 op
232 b42d807f 2023-09-02 op if (bufio_compose(bio, data, len) == -1)
233 b42d807f 2023-09-02 op goto err;
234 b42d807f 2023-09-02 op
235 b42d807f 2023-09-02 op return (0);
236 b42d807f 2023-09-02 op
237 b42d807f 2023-09-02 op err:
238 b42d807f 2023-09-02 op clt->err = 1;
239 b42d807f 2023-09-02 op return (-1);
240 b42d807f 2023-09-02 op }