2 b42d807f 2023-09-02 op * This is free and unencumbered software released into the public domain.
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
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.
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.
26 b42d807f 2023-09-02 op #include "config.h"
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>
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"
39 b42d807f 2023-09-02 op #define WS_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
42 b42d807f 2023-09-02 op tob64(unsigned char ch)
45 b42d807f 2023-09-02 op return ('A' + ch);
48 b42d807f 2023-09-02 op return ('a' + ch);
51 b42d807f 2023-09-02 op return ('0' + ch);
57 b42d807f 2023-09-02 op errno = EINVAL;
62 b42d807f 2023-09-02 op b64encode(unsigned char *in, size_t ilen, char *out, size_t olen)
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); \
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;
79 b42d807f 2023-09-02 op switch (ilen) {
81 b42d807f 2023-09-02 op SET(in[0] >> 2);
82 b42d807f 2023-09-02 op SET(in[0] << 4);
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);
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);
107 b42d807f 2023-09-02 op if (olen < 1) {
108 b42d807f 2023-09-02 op errno = ENOSPC;
116 b42d807f 2023-09-02 op ws_accept_hdr(const char *secret, char *out, size_t olen)
118 b42d807f 2023-09-02 op SHA1_CTX ctx;
119 b42d807f 2023-09-02 op uint8_t hash[SHA1_DIGEST_LENGTH];
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);
126 b42d807f 2023-09-02 op return (b64encode(hash, sizeof(hash), out, olen));
130 b42d807f 2023-09-02 op ws_read(struct client *clt, int *type, size_t *len)
132 b42d807f 2023-09-02 op struct buffer *rbuf = &clt->bio.rbuf;
134 b42d807f 2023-09-02 op uint32_t mask;
135 b42d807f 2023-09-02 op uint8_t first, second, op, plen;
137 b42d807f 2023-09-02 op *type = WST_UNKNOWN, *len = 0;
139 b42d807f 2023-09-02 op if (rbuf->len < 2) {
140 b42d807f 2023-09-02 op errno = EAGAIN;
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));
147 b42d807f 2023-09-02 op /* for the close message this doesn't seem to be the case... */
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;
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;
162 b42d807f 2023-09-02 op op = first & 0x0F;
163 b42d807f 2023-09-02 op plen = second & 0x7F;
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;
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:
183 b42d807f 2023-09-02 op if (rbuf->len < sizeof(first) + sizeof(second) + sizeof(mask) + plen) {
184 b42d807f 2023-09-02 op errno = EAGAIN;
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);
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));
200 b42d807f 2023-09-02 op ws_compose(struct client *clt, int type, const void *data, size_t len)
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;
206 b42d807f 2023-09-02 op first = (type & 0x0F) | 0x80;
208 b42d807f 2023-09-02 op if (len < 126)
209 b42d807f 2023-09-02 op second = len;
211 b42d807f 2023-09-02 op second = 126;
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.
218 b42d807f 2023-09-02 op if (len > 0x7FFF) {
219 b42d807f 2023-09-02 op errno = ERANGE;
222 b42d807f 2023-09-02 op extlen = htons(len);
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)
229 b42d807f 2023-09-02 op if (extlen != 0 && bufio_compose(bio, &extlen, sizeof(extlen)) == -1)
232 b42d807f 2023-09-02 op if (bufio_compose(bio, data, len) == -1)
238 b42d807f 2023-09-02 op clt->err = 1;