1 /* radare - LGPL - Copyright 2012-2021 - pancake */
2 
3 #include <r_socket.h>
4 #include <r_util.h>
5 
6 static bool *breaked = NULL;
7 
r_socket_http_server_set_breaked(bool * b)8 R_API void r_socket_http_server_set_breaked(bool *b) {
9 	breaked = b;
10 }
11 
r_socket_http_accept(RSocket * s,RSocketHTTPOptions * so)12 R_API RSocketHTTPRequest *r_socket_http_accept (RSocket *s, RSocketHTTPOptions *so) {
13 	int content_length = 0, xx, yy;
14 	int pxx = 1, first = 0;
15 	char buf[1500], *p, *q;
16 	RSocketHTTPRequest *hr = R_NEW0 (RSocketHTTPRequest);
17 	if (!hr) {
18 		return NULL;
19 	}
20 	if (so->accept_timeout) {
21 		hr->s = r_socket_accept_timeout (s, 1);
22 	} else {
23 		hr->s = r_socket_accept (s);
24 	}
25 	if (!hr->s) {
26 		free (hr);
27 		return NULL;
28 	}
29 	if (so->timeout > 0) {
30 		r_socket_block_time (hr->s, true, so->timeout, 0);
31 	}
32 	hr->auth = !so->httpauth;
33 	for (;;) {
34 #if __WINDOWS__
35 		if (breaked && *breaked) {
36 			r_socket_http_close (hr);
37 			return NULL;
38 		}
39 #endif
40 		memset (buf, 0, sizeof (buf));
41 		xx = r_socket_gets (hr->s, buf, sizeof (buf));
42 		yy = r_socket_ready (hr->s, 0, 20 * 1000); //this function uses usecs as argument
43 //		eprintf ("READ %d (%s) READY %d\n", xx, buf, yy);
44 		if (!yy || (!xx && !pxx)) {
45 			break;
46 		}
47 		pxx = xx;
48 
49 		if (first == 0) {
50 			first = 1;
51 			if (strlen (buf)<3) {
52 				r_socket_http_close (hr);
53 				return NULL;
54 			}
55 			p = strchr (buf, ' ');
56 			if (p) {
57 				*p = 0;
58 			}
59 			hr->method = strdup (buf);
60 			if (p) {
61 				q = strstr (p+1, " HTTP"); //strchr (p+1, ' ');
62 				if (q) {
63 					*q = 0;
64 				}
65 				hr->path = strdup (p+1);
66 			}
67 		} else {
68 			if (!hr->referer && !strncmp (buf, "Referer: ", 9)) {
69 				hr->referer = strdup (buf + 9);
70 			} else if (!hr->agent && !strncmp (buf, "User-Agent: ", 12)) {
71 				hr->agent = strdup (buf + 12);
72 			} else if (!hr->host && !strncmp (buf, "Host: ", 6)) {
73 				hr->host = strdup (buf + 6);
74 			} else if (!strncmp (buf, "Content-Length: ", 16)) {
75 				content_length = atoi (buf + 16);
76 			} else if (so->httpauth && !strncmp (buf, "Authorization: Basic ", 21)) {
77 				char *authtoken = buf + 21;
78 				size_t authlen = strlen (authtoken);
79 				char *curauthtoken;
80 				RListIter *iter;
81 				char *decauthtoken = calloc (4, authlen + 1);
82 				if (!decauthtoken) {
83 					eprintf ("Could not allocate decoding buffer\n");
84 					return hr;
85 				}
86 
87 				if (r_base64_decode ((ut8 *)decauthtoken, authtoken, authlen) == -1) {
88 					eprintf ("Could not decode authorization token\n");
89 				} else {
90 					r_list_foreach (so->authtokens, iter, curauthtoken) {
91 						if (!strcmp (decauthtoken, curauthtoken)) {
92 							hr->auth = true;
93 							break;
94 						}
95 					}
96 				}
97 
98 				free (decauthtoken);
99 
100 				if (!hr->auth) {
101 					eprintf ("Failed attempt login from '%s'\n", hr->host);
102 				}
103 			}
104 		}
105 	}
106 	if (content_length>0) {
107 		r_socket_read_block (hr->s, (ut8*)buf, 1); // one missing byte wtf
108 		if (ST32_ADD_OVFCHK (content_length, 1)) {
109 			r_socket_http_close (hr);
110 			eprintf ("Could not allocate hr data\n");
111 			return NULL;
112 		}
113 		hr->data = malloc (content_length+1);
114 		hr->data_length = content_length;
115 		r_socket_read_block (hr->s, hr->data, hr->data_length);
116 		hr->data[content_length] = 0;
117 	}
118 	return hr;
119 }
120 
r_socket_http_response(RSocketHTTPRequest * rs,int code,const char * out,int len,const char * headers)121 R_API void r_socket_http_response(RSocketHTTPRequest *rs, int code, const char *out, int len, const char *headers) {
122 	const char *strcode = \
123 		code==200?"ok":
124 		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 	r_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 		r_socket_write (rs->s, (void *)out, len);
141 	}
142 }
143 
r_socket_http_handle_upload(const ut8 * str,int len,int * retlen)144 R_API ut8 *r_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 
r_socket_http_close(RSocketHTTPRequest * rs)190 R_API void r_socket_http_close(RSocketHTTPRequest *rs) {
191 	r_socket_close (rs->s);
192 }
193 
194 /* close client socket and free struct */
r_socket_http_free(RSocketHTTPRequest * rs)195 R_API void r_socket_http_free(RSocketHTTPRequest *rs) {
196 	r_socket_free (rs->s);
197 	free (rs->path);
198 	free (rs->host);
199 	free (rs->agent);
200 	free (rs->method);
201 	free (rs->data);
202 	free (rs);
203 }
204 
205 #if MAIN
main()206 int main() {
207 	RSocket *s = r_socket_new (false);
208 	if (!r_socket_listen (s, "8080", NULL)) {
209 		eprintf ("Cannot listen here\n");
210 		return 1;
211 	}
212 	for (;;) {
213 		RSocketHTTPRequest *rs = r_socket_http_accept (s, 0);
214 		if (!rs) continue;
215 		if (!strcmp (rs->method, "GET")) {
216 			r_socket_http_response (rs, 200,
217 			"<html><body><form method=post action=/>"
218 			"<input name=a /><input type=button></form></body>");
219 		} else
220 		if (!strcmp (rs->method, "POST")) {
221 			char *buf = malloc (rs->data_length+ 50);
222 			strcpy (buf, "<html><body><h2>XSS test</h2>\n");
223 			r_str_unescape (rs->data);
224 			strcat (buf, rs->data);
225 			r_socket_http_response (rs, 200, buf);
226 			free (buf);
227 		} else
228 		if (!strcmp (rs->method, "OPTIONS")) {
229 			r_socket_http_response (rs, 200,"");
230 		} else {
231 			r_socket_http_response (rs, 404, "Invalid protocol");
232 		}
233 		r_socket_http_close (rs);
234 		r_socket_http_free (rs);
235 	}
236 }
237 #endif
238