Rizin
unix-like reverse engineering framework and cli tools
socket_http_server.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2012-2021 pancake <pancake@nopcode.org>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include <rz_socket.h>
5 #include <rz_util.h>
6 
7 static bool *breaked = NULL;
8 
10  breaked = b;
11 }
12 
14  int content_length = 0, xx, yy;
15  int pxx = 1, first = 0;
16  char buf[1500], *p, *q;
18  if (!hr) {
19  return NULL;
20  }
21  if (so->accept_timeout) {
22  hr->s = rz_socket_accept_timeout(s, 1);
23  } else {
24  hr->s = rz_socket_accept(s);
25  }
26  if (!hr->s) {
27  free(hr);
28  return NULL;
29  }
30  if (so->timeout > 0) {
31  rz_socket_block_time(hr->s, true, so->timeout, 0);
32  }
33  hr->auth = !so->httpauth;
34  for (;;) {
35 #if __WINDOWS__
36  if (breaked && *breaked) {
38  return NULL;
39  }
40 #endif
41  memset(buf, 0, sizeof(buf));
42  xx = rz_socket_gets(hr->s, buf, sizeof(buf));
43  yy = rz_socket_ready(hr->s, 0, 20 * 1000); // this function uses usecs as argument
44  // eprintf ("READ %d (%s) READY %d\n", xx, buf, yy);
45  if (!yy || (!xx && !pxx)) {
46  break;
47  }
48  pxx = xx;
49 
50  if (first == 0) {
51  first = 1;
52  if (strlen(buf) < 3) {
54  return NULL;
55  }
56  p = strchr(buf, ' ');
57  if (p) {
58  *p = 0;
59  }
60  hr->method = strdup(buf);
61  if (p) {
62  q = strstr(p + 1, " HTTP"); // strchr (p+1, ' ');
63  if (q) {
64  *q = 0;
65  }
66  hr->path = strdup(p + 1);
67  }
68  } else {
69  if (!hr->referer && !strncmp(buf, "Referer: ", 9)) {
70  hr->referer = strdup(buf + 9);
71  } else if (!hr->agent && !strncmp(buf, "User-Agent: ", 12)) {
72  hr->agent = strdup(buf + 12);
73  } else if (!hr->host && !strncmp(buf, "Host: ", 6)) {
74  hr->host = strdup(buf + 6);
75  } else if (!strncmp(buf, "Content-Length: ", 16)) {
76  content_length = atoi(buf + 16);
77  } else if (so->httpauth && !strncmp(buf, "Authorization: Basic ", 21)) {
78  char *authtoken = buf + 21;
79  size_t authlen = strlen(authtoken);
80  char *curauthtoken;
82  char *decauthtoken = calloc(4, authlen + 1);
83  if (!decauthtoken) {
84  eprintf("Could not allocate decoding buffer\n");
85  return hr;
86  }
87 
88  if (rz_base64_decode((ut8 *)decauthtoken, authtoken, authlen) == -1) {
89  eprintf("Could not decode authorization token\n");
90  } else {
91  rz_list_foreach (so->authtokens, iter, curauthtoken) {
92  if (!strcmp(decauthtoken, curauthtoken)) {
93  hr->auth = true;
94  break;
95  }
96  }
97  }
98 
99  free(decauthtoken);
100 
101  if (!hr->auth) {
102  eprintf("Failed attempt login from '%s'\n", hr->host);
103  }
104  }
105  }
106  }
107  if (content_length > 0) {
108  rz_socket_read_block(hr->s, (ut8 *)buf, 1); // one missing byte
109  if (ST32_ADD_OVFCHK(content_length, 1)) {
111  eprintf("Could not allocate hr data\n");
112  return NULL;
113  }
114  hr->data = malloc(content_length + 1);
115  hr->data_length = content_length;
116  rz_socket_read_block(hr->s, hr->data, hr->data_length);
117  hr->data[content_length] = 0;
118  }
119  return hr;
120 }
121 
122 RZ_API void rz_socket_http_response(RzSocketHTTPRequest *rs, int code, const char *out, int len, const char *headers) {
123  const char *strcode =
124  code == 200 ? "ok" : code == 301 ? "Moved permanently"
125  : code == 302 ? "Found"
126  : code == 401 ? "Unauthorized"
127  : code == 403 ? "Permission denied"
128  : code == 404 ? "not found"
129  : "UNKNOWN";
130  if (len < 1) {
131  len = out ? strlen(out) : 0;
132  }
133  if (!headers) {
134  headers = code == 401 ? "WWW-Authenticate: Basic realm=\"R2 Web UI Access\"\n" : "";
135  }
136  rz_socket_printf(rs->s, "HTTP/1.0 %d %s\r\n%s"
137  "Connection: close\r\nContent-Length: %d\r\n\r\n",
138  code, strcode, headers, len);
139  if (out && len > 0) {
140  rz_socket_write(rs->s, (void *)out, len);
141  }
142 }
143 
144 RZ_API ut8 *rz_socket_http_handle_upload(const ut8 *str, int len, int *retlen) {
145  if (retlen) {
146  *retlen = 0;
147  }
148  if (!strncmp((const char *)str, "----------", 10)) {
149  int datalen;
150  char *ret;
151  const char *data, *token = (const char *)str + 10;
152  const char *end = strchr(token, '\n');
153  if (!end) {
154  return NULL;
155  }
156  data = strstr(end, "Content-Disposition: form-data; ");
157  if (data) {
158  data = strchr(data, '\n');
159  if (data) {
160  data = strchr(data + 1, '\n');
161  }
162  }
163  if (data) {
164  while (*data == 10 || *data == 13) {
165  data++;
166  }
167  end = (const char *)str + len - 40;
168  while (*end == '-') {
169  end--;
170  }
171  if (*end == 10 || *end == 13) {
172  end--;
173  }
174  datalen = (size_t)(end - data);
175  ret = malloc(datalen + 1);
176  if (!ret) {
177  return NULL;
178  }
179  memcpy(ret, data, datalen);
180  ret[datalen] = 0;
181  if (retlen) {
182  *retlen = datalen;
183  }
184  return (ut8 *)ret;
185  }
186  }
187  return NULL;
188 }
189 
190 /* close client socket and free struct */
192  rz_socket_free(rs->s);
193  free(rs->path);
194  free(rs->host);
195  free(rs->agent);
196  free(rs->method);
197  free(rs->data);
198  free(rs);
199 }
200 
201 #if MAIN
202 int main() {
203  RzSocket *s = rz_socket_new(false);
204  if (!rz_socket_listen(s, "8080", NULL)) {
205  eprintf("Cannot listen here\n");
206  return 1;
207  }
208  for (;;) {
210  if (!rs)
211  continue;
212  if (!strcmp(rs->method, "GET")) {
214  "<html><body><form method=post action=/>"
215  "<input name=a /><input type=button></form></body>");
216  } else if (!strcmp(rs->method, "POST")) {
217  char *buf = malloc(rs->data_length + 50);
218  strcpy(buf, "<html><body><h2>XSS test</h2>\n");
219  rz_str_unescape(rs->data);
220  strcat(buf, rs->data);
222  free(buf);
223  } else if (!strcmp(rs->method, "OPTIONS")) {
224  rz_socket_http_response(rs, 200, "");
225  } else {
226  rz_socket_http_response(rs, 404, "Invalid protocol");
227  }
229  }
230 }
231 #endif
size_t len
Definition: 6502dis.c:15
#define rs()
const lzma_allocator const uint8_t size_t uint8_t * out
Definition: block.h:528
#define RZ_API
#define NULL
Definition: cris-opc.c:27
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void * buf
Definition: ioapi.h:138
uint8_t ut8
Definition: lh5801.h:11
return memset(p, 0, total)
void * p
Definition: libc.cpp:67
memcpy(mem, inblock.get(), min(CONTAINING_RECORD(inblock.get(), MEMBLOCK, data) ->size, size))
void * malloc(size_t size)
Definition: malloc.c:123
void * calloc(size_t number, size_t size)
Definition: malloc.c:102
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
#define eprintf(x, y...)
Definition: rlcc.c:7
static RzSocket * s
Definition: rtr.c:28
int main(int argc, char **argv)
Definition: rz-bb.c:29
RZ_API int rz_base64_decode(ut8 *bout, const char *bin, int len)
Definition: ubase64.c:48
RZ_API int rz_socket_read_block(RzSocket *s, unsigned char *buf, int len)
Definition: socket.c:808
RZ_API int rz_socket_ready(RzSocket *s, int secs, int usecs)
Definition: socket.c:688
RZ_API RzSocket * rz_socket_accept(RzSocket *s)
Definition: socket.c:582
RZ_API bool rz_socket_listen(RzSocket *s, const char *port, const char *certfile)
Definition: socket.c:474
RZ_API bool rz_socket_block_time(RzSocket *s, bool block, int sec, int usec)
Definition: socket.c:649
RZ_API int rz_socket_gets(RzSocket *s, char *buf, int size)
Definition: socket.c:830
RZ_API void rz_socket_printf(RzSocket *s, const char *fmt,...) RZ_PRINTF_CHECK(2
RZ_API RzSocket * rz_socket_accept_timeout(RzSocket *s, unsigned int timeout)
Definition: socket.c:626
RZ_API RzSocket * rz_socket_new(bool is_ssl)
Definition: socket.c:179
RZ_API int rz_socket_free(RzSocket *s)
Definition: socket.c:453
RZ_API int rz_socket_write(RzSocket *s, void *buf, int len)
Definition: socket.c:724
RZ_API int rz_str_unescape(char *buf)
Definition: str.c:1300
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define ST32_ADD_OVFCHK(a, x)
int size_t
Definition: sftypes.h:40
#define b(i)
Definition: sha256.c:42
RZ_API RzSocketHTTPRequest * rz_socket_http_accept(RzSocket *s, RzSocketHTTPOptions *so)
static bool * breaked
RZ_API void rz_socket_http_response(RzSocketHTTPRequest *rs, int code, const char *out, int len, const char *headers)
RZ_API void rz_socket_http_server_set_breaked(bool *b)
RZ_API ut8 * rz_socket_http_handle_upload(const ut8 *str, int len, int *retlen)
RZ_API void rz_socket_http_close(RzSocketHTTPRequest *rs)
Definition: inftree9.h:24