1 /* radare - Copyright 2009-2020 - pancake, nibble */
2
3 #include "r_core.h"
4 #include "r_socket.h"
5 #include "gdb/include/libgdbr.h"
6 #include "gdb/include/gdbserver/core.h"
7
8 #if HAVE_LIBUV
9 #include <uv.h>
10 #endif
11
12 #if 0
13 SECURITY IMPLICATIONS
14 =====================
15 - no ssl
16 - no auth
17 - commands can be executed by anyone
18 - default is to listen on localhost
19 - can access full filesystem
20 - follow symlinks
21 #endif
22
23 #define rtr_n core->rtr_n
24 #define rtr_host core->rtr_host
25
26 static RSocket *s = NULL;
27 static RThread *httpthread = NULL;
28 static RThread *rapthread = NULL;
29 static const char *listenport = NULL;
30
31 typedef struct {
32 const char *host;
33 const char *port;
34 const char *file;
35 } TextLog;
36
37 typedef struct {
38 RCore *core;
39 int launch;
40 int browse;
41 char *path;
42 } HttpThread;
43
44 typedef struct {
45 RCore *core;
46 char* input;
47 } RapThread;
48
r_core_wait(RCore * core)49 R_API void r_core_wait(RCore *core) {
50 r_cons_singleton ()->context->breaked = true;
51 r_th_kill (httpthread, true);
52 r_th_kill (rapthread, true);
53 r_th_wait (httpthread);
54 r_th_wait (rapthread);
55 }
56
http_logf(RCore * core,const char * fmt,...)57 static void http_logf(RCore *core, const char *fmt, ...) {
58 bool http_log_enabled = r_config_get_i (core->config, "http.log");
59 va_list ap;
60 va_start (ap, fmt);
61 if (http_log_enabled) {
62 const char *http_log_file = r_config_get (core->config, "http.logfile");
63 if (http_log_file && *http_log_file) {
64 char * msg = calloc (4096, 1);
65 if (msg) {
66 vsnprintf (msg, 4095, fmt, ap);
67 r_file_dump (http_log_file, (const ut8*)msg, -1, true);
68 free (msg);
69 }
70 } else {
71 vfprintf (stderr, fmt, ap);
72 }
73 }
74 va_end (ap);
75 }
76
rtrcmd(TextLog T,const char * str)77 static char *rtrcmd (TextLog T, const char *str) {
78 char *res, *ptr2;
79 char *ptr = r_str_uri_encode (str);
80 char *uri = r_str_newf ("http://%s:%s/%s%s", T.host, T.port, T.file, ptr? ptr: str);
81 int len;
82 free (ptr);
83 ptr2 = r_socket_http_get (uri, NULL, &len);
84 free (uri);
85 if (ptr2) {
86 ptr2[len] = 0;
87 res = strstr (ptr2, "\n\n");
88 if (res) {
89 res = strstr (res + 1, "\n\n");
90 }
91 return res? res + 2: ptr2;
92 }
93 return NULL;
94 }
95
showcursor(RCore * core,int x)96 static void showcursor(RCore *core, int x) {
97 if (core && core->vmode) {
98 r_cons_show_cursor (x);
99 r_cons_enable_mouse (x? r_config_get_i (core->config, "scr.wheel"): false);
100 } else {
101 r_cons_enable_mouse (false);
102 }
103 r_cons_flush ();
104 }
105
106 // TODO: rename /name to /nick or /so?
107 // clone of textlog_chat () using rtrcmd()
rtr_textlog_chat(RCore * core,TextLog T)108 static void rtr_textlog_chat (RCore *core, TextLog T) {
109 char prompt[64];
110 char buf[1024];
111 int lastmsg = 0;
112 const char *me = r_config_get (core->config, "cfg.user");
113 char *ret, msg[1024];
114
115 eprintf ("Type '/help' for commands and ^D to quit:\n");
116 char *oldprompt = strdup (r_line_singleton ()->prompt);
117 snprintf (prompt, sizeof (prompt) - 1, "[%s]> ", me);
118 r_line_set_prompt (prompt);
119 ret = rtrcmd (T, msg);
120 for (;;) {
121 if (lastmsg >= 0) {
122 snprintf (msg, sizeof (msg) - 1, "T %d", lastmsg);
123 } else {
124 strcpy (msg, "T");
125 }
126 ret = rtrcmd (T, msg);
127 r_cons_println (ret);
128 free (ret);
129 ret = rtrcmd (T, "Tl");
130 lastmsg = atoi (ret)-1;
131 free (ret);
132 if (r_cons_fgets (buf, sizeof (buf), 0, NULL) < 0) {
133 goto beach;
134 }
135 if (!*buf) {
136 continue;
137 }
138 if (!strcmp (buf, "/help")) {
139 eprintf ("/quit quit the chat (same as ^D)\n");
140 eprintf ("/nick <nick> set cfg.user nick name\n");
141 eprintf ("/log show full log\n");
142 eprintf ("/clear clear text log messages\n");
143 } else if (!strncmp (buf, "/nick ", 6)) {
144 snprintf (msg, sizeof (msg) - 1, "* '%s' is now known as '%s'", me, buf+6);
145 r_cons_println (msg);
146 r_core_log_add (core, msg);
147 r_config_set (core->config, "cfg.user", buf+6);
148 me = r_config_get (core->config, "cfg.user");
149 snprintf (prompt, sizeof (prompt) - 1, "[%s]> ", me);
150 r_line_set_prompt (prompt);
151 } else if (!strcmp (buf, "/log")) {
152 char *ret = rtrcmd (T, "T");
153 if (ret) {
154 r_cons_println (ret);
155 free (ret);
156 }
157 } else if (!strcmp (buf, "/clear")) {
158 //r_core_log_del (core, 0);
159 free (rtrcmd (T, "T-"));
160 } else if (!strcmp (buf, "/quit")) {
161 goto beach;
162 } else if (*buf=='/') {
163 eprintf ("Unknown command: %s\n", buf);
164 } else {
165 char *cmd = r_str_newf ("T [%s] %s", me, buf);
166 free (rtrcmd (T, cmd));
167 free (cmd);
168 }
169 }
170 beach:
171 r_line_set_prompt (oldprompt);
172 free (oldprompt);
173 }
174
r_core_rtr_http_stop(RCore * u)175 R_API int r_core_rtr_http_stop(RCore *u) {
176 RCore *core = (RCore*)u;
177 const int timeout = 1; // 1 second
178 const char *port;
179 RSocket* sock;
180
181 #if __WINDOWS__
182 r_socket_http_server_set_breaked (&r_cons_singleton ()->context->breaked);
183 #endif
184 if (((size_t)u) > 0xff) {
185 port = listenport? listenport: r_config_get (
186 core->config, "http.port");
187 sock = r_socket_new (0);
188 (void)r_socket_connect (sock, "localhost",
189 port, R_SOCKET_PROTO_TCP, timeout);
190 r_socket_free (sock);
191 }
192 r_socket_free (s);
193 s = NULL;
194 return 0;
195 }
196
rtr_dir_files(const char * path)197 static char *rtr_dir_files(const char *path) {
198 char *ptr = strdup ("<html><body>\n");
199 const char *file;
200 RListIter *iter;
201 // list files
202 RList *files = r_sys_dir (path);
203 eprintf ("Listing directory %s\n", path);
204 r_list_foreach (files, iter, file) {
205 if (file[0] == '.') {
206 continue;
207 }
208 ptr = r_str_appendf (ptr, "<a href=\"%s%s\">%s</a><br />\n",
209 path, file, file);
210 }
211 r_list_free (files);
212 return r_str_append (ptr, "</body></html>\n");
213 }
214
215 #if __UNIX__
dietime(int sig)216 static void dietime(int sig) {
217 eprintf ("It's Die Time!\n");
218 exit (0);
219 }
220 #endif
221
activateDieTime(RCore * core)222 static void activateDieTime(RCore *core) {
223 int dt = r_config_get_i (core->config, "http.dietime");
224 if (dt > 0) {
225 #if __UNIX__
226 r_sys_signal (SIGALRM, dietime);
227 alarm (dt);
228 #else
229 eprintf ("http.dietime only works on *nix systems\n");
230 #endif
231 }
232 }
233
234 #include "rtr_http.c"
235 #include "rtr_shell.c"
236
write_reg_val(char * buf,ut64 sz,ut64 reg,int regsize,bool bigendian)237 static int write_reg_val(char *buf, ut64 sz, ut64 reg, int regsize, bool bigendian) {
238 if (!bigendian) {
239 switch (regsize) {
240 case 2:
241 reg = r_swap_ut16 (reg);
242 break;
243 case 4:
244 reg = r_swap_ut32 (reg);
245 break;
246 case 8:
247 reg = r_swap_ut64 (reg);
248 break;
249 default:
250 eprintf ("%s: Unsupported reg size: %d\n",
251 __func__, regsize);
252 return -1;
253 }
254 }
255 return snprintf (buf, sz, regsize == 2 ? "%04"PFMT64x
256 : regsize == 4 ? "%08"PFMT64x : "%016"PFMT64x, reg);
257 }
258
write_big_reg(char * buf,ut64 sz,const utX * val,int regsize,bool bigendian)259 static int write_big_reg(char *buf, ut64 sz, const utX *val, int regsize, bool bigendian) {
260 switch (regsize) {
261 case 10:
262 if (bigendian) {
263 return snprintf (buf, sz,
264 "%04x%016"PFMT64x, val->v80.High,
265 val->v80.Low);
266 }
267 return snprintf (buf, sz,
268 "%016"PFMT64x"%04x", r_swap_ut64 (val->v80.Low),
269 r_swap_ut16 (val->v80.High));
270 case 12:
271 if (bigendian) {
272 return snprintf (buf, sz,
273 "%08"PFMT32x"%016"PFMT64x, val->v96.High,
274 val->v96.Low);
275 }
276 return snprintf (buf, sz,
277 "%016"PFMT64x"%08"PFMT32x, r_swap_ut64 (val->v96.Low),
278 r_swap_ut32 (val->v96.High));
279 case 16:
280 if (bigendian) {
281 return snprintf (buf, sz,
282 "%016"PFMT64x"%016"PFMT64x, val->v128.High,
283 val->v128.Low);
284 }
285 return snprintf (buf, sz,
286 "%016"PFMT64x"%016"PFMT64x,
287 r_swap_ut64 (val->v128.Low),
288 r_swap_ut64 (val->v128.High));
289 default:
290 eprintf ("%s: big registers (%d byte(s)) not yet supported\n",
291 __func__, regsize);
292 return -1;
293 }
294 }
295
swap_big_regs(char * dest,ut64 sz,const char * src,int regsz)296 static int swap_big_regs(char *dest, ut64 sz, const char *src, int regsz) {
297 utX val;
298 char sdup[128] = {0};
299 if (!src || !src[0] || !src[1]) {
300 return -1;
301 }
302 strncpy (sdup, src + 2, sizeof (sdup) - 1);
303 int len = strlen (sdup);
304 memset (&val, 0, sizeof (val));
305 switch (regsz) {
306 case 10:
307 if (len <= 4) {
308 val.v80.High = (ut16) strtoul (sdup, NULL, 16);
309 } else {
310 val.v80.High = (ut16) strtoul (sdup + (len - 4), NULL, 16);
311 sdup[len - 4] = '\0';
312 val.v80.Low = (ut64) strtoull (sdup, NULL, 16);
313 }
314 return snprintf (dest, sz, "0x%04x%016"PFMT64x,
315 val.v80.High, val.v80.Low);
316 case 12:
317 if (len <= 8) {
318 val.v96.High = (ut32) strtoul (sdup, NULL, 16);
319 } else {
320 val.v96.High = (ut32) strtoul (sdup + (len - 8), NULL, 16);
321 sdup[len - 8] = '\0';
322 val.v96.Low = (ut64) strtoull (sdup, NULL, 16);
323 }
324 return snprintf (dest, sz, "0x%08x%016"PFMT64x,
325 val.v96.High, val.v96.Low);
326 case 16:
327 if (len <= 16) {
328 val.v128.High = (ut64) strtoul (sdup, NULL, 16);
329 } else {
330 val.v128.High = (ut64) strtoul (sdup + (len - 16), NULL, 16);
331 sdup[len - 16] = '\0';
332 val.v128.Low = (ut64) strtoull (sdup, NULL, 16);
333 }
334 return snprintf (dest, sz, "0x%016"PFMT64x"%016"PFMT64x,
335 val.v128.High, val.v128.Low);
336 default:
337 eprintf ("%s: big registers (%d byte(s)) not yet supported\n",
338 __func__, regsz);
339 return -1;
340 }
341 }
342
r_core_rtr_gdb_cb(libgdbr_t * g,void * core_ptr,const char * cmd,char * out_buf,size_t max_len)343 static int r_core_rtr_gdb_cb(libgdbr_t *g, void *core_ptr, const char *cmd,
344 char *out_buf, size_t max_len) {
345 int ret;
346 RList *list;
347 RListIter *iter;
348 gdb_reg_t *gdb_reg;
349 RRegItem *r;
350 utX val_big;
351 ut64 m_off, reg_val;
352 bool be;
353 RDebugPid *dbgpid;
354 if (!core_ptr || ! cmd) {
355 return -1;
356 }
357 RCore *core = (RCore*) core_ptr;
358 switch (cmd[0]) {
359 case '?': // Stop reason
360 if (!out_buf) {
361 return -1;
362 }
363 // dbg->reason.signum and dbg->reason.tid are not correct for native
364 // debugger. This is a hack
365 switch (core->dbg->reason.type) {
366 case R_DEBUG_REASON_BREAKPOINT:
367 case R_DEBUG_REASON_STEP:
368 case R_DEBUG_REASON_TRAP:
369 default: // remove when possible
370 return snprintf (out_buf, max_len - 1, "T05thread:%x;",
371 core->dbg->tid);
372 }
373 // Fallback for when it's fixed
374 /*
375 return snprintf (out_buf, max_len - 1, "T%02xthread:%x;",
376 core->dbg->reason.type, core->dbg->reason.tid);
377 */
378 case 'd':
379 switch (cmd[1]) {
380 case 'm': // dm
381 if (snprintf (out_buf, max_len - 1, "%"PFMT64x, r_debug_get_baddr (core->dbg, NULL)) < 0) {
382 return -1;
383 }
384 return 0;
385 case 'p': // dp
386 switch (cmd[2]) {
387 case '\0': // dp
388 // TODO support multiprocess
389 snprintf (out_buf, max_len - 1, "QC%x", core->dbg->tid);
390 return 0;
391 case 't':
392 switch (cmd[3]) {
393 case '\0': // dpt
394 if (!core->dbg->h->threads) {
395 return -1;
396 }
397 if (!(list = core->dbg->h->threads(core->dbg, core->dbg->pid))) {
398 return -1;
399 }
400 memset (out_buf, 0, max_len);
401 out_buf[0] = 'm';
402 ret = 1;
403 r_list_foreach (list, iter, dbgpid) {
404 // Max length of a hex pid = 8?
405 if (ret >= max_len - 9) {
406 break;
407 }
408 snprintf (out_buf + ret, max_len - ret - 1, "%x,", dbgpid->pid);
409 ret = strlen (out_buf);
410 }
411 if (ret > 1) {
412 ret--;
413 out_buf[ret] = '\0';
414 }
415 return 0;
416 case 'r': // dptr -> return current tid as int
417 return core->dbg->tid;
418 default:
419 return r_core_cmd (core, cmd, 0);
420 }
421 }
422 break;
423 case 'r': // dr
424 r_debug_reg_sync (core->dbg, R_REG_TYPE_ALL, false);
425 be = r_config_get_i (core->config, "cfg.bigendian");
426 if (isspace ((ut8)cmd[2])) { // dr reg
427 const char *name, *val_ptr;
428 char new_cmd[128] = { 0 };
429 int off = 0;
430 name = cmd + 3;
431 // Temporarily using new_cmd to store reg name
432 if ((val_ptr = strchr (name, '='))) {
433 strncpy (new_cmd, name, R_MIN (val_ptr - name, sizeof (new_cmd) - 1));
434 } else {
435 strncpy (new_cmd, name, sizeof (new_cmd) - 1);
436 }
437 if (!(r = r_reg_get (core->dbg->reg, new_cmd, -1))) {
438 return -1;
439 }
440 if (val_ptr) { // dr reg=val
441 val_ptr++;
442 off = val_ptr - cmd;
443 if (be) {
444 // We don't need to swap
445 r_core_cmd (core, cmd, 0);
446 }
447 // Previous contents are overwritten, since len(name) < off
448 strncpy (new_cmd, cmd, off);
449 if (r->size <= 64) {
450 reg_val = strtoll (val_ptr, NULL, 16);
451 if (write_reg_val (new_cmd + off, sizeof (new_cmd) - off - 1,
452 reg_val, r->size / 8, be) < 0) {
453 return -1;
454 }
455 return r_core_cmd (core, new_cmd, 0);
456 }
457 // Big registers
458 if (swap_big_regs (new_cmd + off, sizeof (new_cmd) - off - 1,
459 val_ptr, r->size / 8) < 0) {
460 return -1;
461 }
462 return r_core_cmd (core, new_cmd, 0);
463 }
464 if (r->size <= 64) {
465 reg_val = r_reg_get_value (core->dbg->reg, r);
466 return write_reg_val (out_buf, max_len - 1,
467 reg_val, r->size / 8, be);
468 }
469 r_reg_get_value_big (core->dbg->reg,
470 r, &val_big);
471 return write_big_reg (out_buf, max_len - 1,
472 &val_big, r->size / 8, be);
473 }
474 // dr - Print all registers
475 ret = 0;
476 if (!(gdb_reg = g->registers)) {
477 return -1;
478 }
479 while (*gdb_reg->name) {
480 if (ret + gdb_reg->size * 2 >= max_len - 1) {
481 return -1;
482 }
483 if (gdb_reg->size <= 8) {
484 reg_val = r_reg_getv (core->dbg->reg, gdb_reg->name);
485 if (write_reg_val (out_buf + ret,
486 gdb_reg->size * 2 + 1,
487 reg_val, gdb_reg->size, be) < 0) {
488 return -1;
489 }
490 } else {
491 r_reg_get_value_big (core->dbg->reg,
492 r_reg_get (core->dbg->reg, gdb_reg->name, -1),
493 &val_big);
494 if (write_big_reg (out_buf + ret, gdb_reg->size * 2 + 1,
495 &val_big, gdb_reg->size, be) < 0) {
496 return -1;
497 }
498 }
499 ret += gdb_reg->size * 2;
500 gdb_reg++;
501 }
502 out_buf[ret] = '\0';
503 return ret;
504 default:
505 return r_core_cmd (core, cmd, 0);
506 }
507 break;
508 case 'i':
509 switch (cmd[1]) {
510 case 'f':
511 {
512 ut64 off, len, sz, namelen;
513 RIODesc *desc = core->io->desc;
514 if (sscanf (cmd + 2, "%"PFMT64x",%"PFMT64x, &off, &len) != 2) {
515 strcpy (out_buf, "E00");
516 return 0;
517 }
518 namelen = desc ? strlen (desc->name) : 0;
519 if (off >= namelen) {
520 out_buf[0] = 'l';
521 return 0;
522 }
523 sz = R_MIN (max_len, len + 2);
524 len = snprintf (out_buf, sz, "l%s", desc ? (desc->name + off) : "");
525 if (len >= sz) {
526 // There's more left
527 out_buf[0] = 'm';
528 }
529 return 0;
530 }
531 }
532 break;
533 case 'm':
534 sscanf (cmd + 1, "%"PFMT64x",%x", &m_off, &ret);
535 if (r_io_read_at (core->io, m_off, (ut8*) out_buf, ret)) {
536 return ret;
537 }
538 return -1;
539 default:
540 return r_core_cmd (core, cmd, 0);
541 }
542 return -1;
543 }
544
545 // path = "<port> <file_name>"
r_core_rtr_gdb_run(RCore * core,int launch,const char * path)546 static int r_core_rtr_gdb_run(RCore *core, int launch, const char *path) {
547 RSocket *sock;
548 int p, ret;
549 bool debug_msg = false;
550 char port[10];
551 char *file = NULL, *args = NULL;
552 libgdbr_t *g;
553
554 if (!core || !path) {
555 return -1;
556 }
557 if (*path == '!') {
558 debug_msg = true;
559 path++;
560 }
561 if (!(path = r_str_trim_head_ro (path)) || !*path) {
562 eprintf ("gdbserver: Port not specified\n");
563 return -1;
564 }
565 if (!(p = atoi (path)) || p < 0 || p > 65535) {
566 eprintf ("gdbserver: Invalid port: %s\n", port);
567 return -1;
568 }
569 snprintf (port, sizeof (port) - 1, "%d", p);
570 if (!(file = strchr (path, ' '))) {
571 eprintf ("gdbserver: File not specified\n");
572 return -1;
573 }
574 if (!(file = (char *)r_str_trim_head_ro (file)) || !*file) {
575 eprintf ("gdbserver: File not specified\n");
576 return -1;
577 }
578 args = strchr (file, ' ');
579 if (args) {
580 *args++ = '\0';
581 if (!(args = (char *)r_str_trim_head_ro (args))) {
582 args = "";
583 }
584 } else {
585 args = "";
586 }
587
588 if (!r_core_file_open (core, file, R_PERM_RX, 0)) {
589 eprintf ("Cannot open file (%s)\n", file);
590 return -1;
591 }
592 r_core_file_reopen_debug (core, args);
593
594 if (!(sock = r_socket_new (false))) {
595 eprintf ("gdbserver: Could not open socket for listening\n");
596 return -1;
597 }
598 if (!r_socket_listen (sock, port, NULL)) {
599 r_socket_free (sock);
600 eprintf ("gdbserver: Cannot listen on port: %s\n", port);
601 return -1;
602 }
603 if (!(g = R_NEW0 (libgdbr_t))) {
604 r_socket_free (sock);
605 eprintf ("gdbserver: Cannot alloc libgdbr instance\n");
606 return -1;
607 }
608 gdbr_init (g, true);
609 g->server_debug = debug_msg;
610 int arch = r_sys_arch_id (r_config_get (core->config, "asm.arch"));
611 int bits = r_config_get_i (core->config, "asm.bits");
612 gdbr_set_architecture (g, arch, bits);
613 core->gdbserver_up = 1;
614 eprintf ("gdbserver started on port: %s, file: %s\n", port, file);
615
616 for (;;) {
617 if (!(g->sock = r_socket_accept (sock))) {
618 break;
619 }
620 g->connected = 1;
621 ret = gdbr_server_serve (g, r_core_rtr_gdb_cb, (void*) core);
622 r_socket_close (g->sock);
623 g->connected = 0;
624 if (ret < 0) {
625 break;
626 }
627 }
628 core->gdbserver_up = 0;
629 gdbr_cleanup (g);
630 free (g);
631 r_socket_free (sock);
632 return 0;
633 }
634
r_core_rtr_gdb(RCore * core,int launch,const char * path)635 R_API int r_core_rtr_gdb(RCore *core, int launch, const char *path) {
636 int ret;
637 if (r_sandbox_enable (0)) {
638 eprintf ("sandbox: connect disabled\n");
639 return -1;
640 }
641 // TODO: do stuff with launch
642 if (core->gdbserver_up) {
643 eprintf ("gdbserver is already running\n");
644 return -1;
645 }
646 ret = r_core_rtr_gdb_run (core, launch, path);
647 return ret;
648 }
649
r_core_rtr_pushout(RCore * core,const char * input)650 R_API void r_core_rtr_pushout(RCore *core, const char *input) {
651 int fd = atoi (input);
652 const char *cmd = NULL;
653 char *str = NULL;
654 if (fd) {
655 for (rtr_n = 0; rtr_host[rtr_n].fd && rtr_n < RTR_MAX_HOSTS - 1; rtr_n++) {
656 if (rtr_host[rtr_n].fd->fd != fd) {
657 continue;
658 }
659 }
660 if (!(cmd = strchr (input, ' '))) {
661 eprintf ("Error\n");
662 return;
663 }
664 } else {
665 cmd = input;
666 }
667
668 if (!rtr_host[rtr_n].fd || !rtr_host[rtr_n].fd->fd) {
669 eprintf ("Error: Unknown host\n");
670 return;
671 }
672
673 if (!(str = r_core_cmd_str (core, cmd))) {
674 eprintf ("Error: radare_cmd_str returned NULL\n");
675 return;
676 }
677
678 switch (rtr_host[rtr_n].proto) {
679 case RTR_PROTOCOL_RAP:
680 eprintf ("Error: Cannot use '=<' to a rap connection.\n");
681 break;
682 case RTR_PROTOCOL_UNIX:
683 r_socket_write (rtr_host[rtr_n].fd, str, strlen (str));
684 break;
685 case RTR_PROTOCOL_HTTP:
686 eprintf ("TODO\n");
687 break;
688 case RTR_PROTOCOL_TCP:
689 case RTR_PROTOCOL_UDP:
690 r_socket_write (rtr_host[rtr_n].fd, str, strlen (str));
691 break;
692 default:
693 eprintf ("Unknown protocol\n");
694 break;
695 }
696 free (str);
697 }
698
r_core_rtr_list(RCore * core)699 R_API void r_core_rtr_list(RCore *core) {
700 int i;
701 for (i = 0; i < RTR_MAX_HOSTS; i++) {
702 if (!rtr_host[i].fd) {
703 continue;
704 }
705 const char *proto = "rap";
706 switch (rtr_host[i].proto) {
707 case RTR_PROTOCOL_HTTP: proto = "http"; break;
708 case RTR_PROTOCOL_TCP: proto = "tcp"; break;
709 case RTR_PROTOCOL_UDP: proto = "udp"; break;
710 case RTR_PROTOCOL_RAP: proto = "rap"; break;
711 case RTR_PROTOCOL_UNIX: proto = "unix"; break;
712 }
713 r_cons_printf ("%d fd:%i %s://%s:%i/%s\n",
714 i, rtr_host[i].fd->fd, proto, rtr_host[i].host,
715 rtr_host[i].port, rtr_host[i].file);
716 }
717 }
718
r_core_rtr_add(RCore * core,const char * _input)719 R_API void r_core_rtr_add(RCore *core, const char *_input) {
720 char *port, input[1024], *file = NULL, *ptr = NULL;
721 int i, timeout, ret;
722 RSocket *fd;
723
724 timeout = r_config_get_i (core->config, "http.timeout");
725 strncpy (input, _input, sizeof (input) - 4);
726 input[sizeof (input) - 4] = '\0';
727
728 int proto = RTR_PROTOCOL_RAP;
729 char *host = (char *)r_str_trim_head_ro (input);
730 char *pikaboo = strstr (host, "://");
731 if (pikaboo) {
732 struct {
733 const char *name;
734 int protocol;
735 } uris[7] = {
736 {"tcp", RTR_PROTOCOL_TCP},
737 {"udp", RTR_PROTOCOL_UDP},
738 {"rap", RTR_PROTOCOL_RAP},
739 {"r2p", RTR_PROTOCOL_RAP},
740 {"http", RTR_PROTOCOL_HTTP},
741 {"unix", RTR_PROTOCOL_UNIX},
742 {NULL, 0}
743 };
744 char *s = r_str_ndup (input, pikaboo - input);
745 //int nlen = pikaboo - input;
746 for (i = 0; uris[i].name; i++) {
747 if (r_str_endswith (s, uris[i].name)) {
748 proto = uris[i].protocol;
749 host = pikaboo + 3;
750 break;
751 }
752 }
753 free (s);
754 }
755 if (host) {
756 if (!(ptr = strchr (host, ':'))) {
757 ptr = host;
758 port = "80";
759 } else {
760 *ptr++ = '\0';
761 port = ptr;
762 r_str_trim (port);
763 }
764 } else {
765 port = NULL;
766 }
767 file = strchr (ptr, '/');
768 if (file) {
769 *file = 0;
770 file = (char *)r_str_trim_head_ro (file + 1);
771 } else {
772 if (*host == ':' || strstr (host, "://:")) { // listen
773 // it's fine to listen without serving a file
774 } else {
775 file = "cmd/";
776 eprintf ("Error: Missing '/'\n");
777 //c:wreturn;
778 }
779 }
780
781 if (r_sandbox_enable (0)) {
782 eprintf ("sandbox: connect disabled\n");
783 return;
784 }
785
786 fd = r_socket_new (false);
787 if (!fd) {
788 eprintf ("Error: Cannot create new socket\n");
789 return;
790 }
791 switch (proto) {
792 case RTR_PROTOCOL_HTTP:
793 {
794 int len;
795 char *uri = r_str_newf ("http://%s:%s/%s", host, port, file);
796 char *str = r_socket_http_get (uri, NULL, &len);
797 if (!str) {
798 eprintf ("Cannot find peer\n");
799 return;
800 }
801 core->num->value = 0;
802 // eprintf ("Connected to: 'http://%s:%s'\n", host, port);
803 free (str);
804 }
805 break;
806 case RTR_PROTOCOL_RAP:
807 if (!r_socket_connect_tcp (fd, host, port, timeout)) { //TODO: Use rap.ssl
808 eprintf ("Error: Cannot connect to '%s' (%s)\n", host, port);
809 r_socket_free (fd);
810 return;
811 } else {
812 int n = r_socket_rap_client_open (fd, file, 0);
813 eprintf ("opened as fd = %d\n", n);
814 }
815 break;
816 case RTR_PROTOCOL_UNIX:
817 if (!r_socket_connect_unix (fd, host)) {
818 core->num->value = 1;
819 eprintf ("Error: Cannot connect to 'unix://%s'\n", host);
820 r_socket_free (fd);
821 return;
822 }
823 core->num->value = 0;
824 eprintf ("Connected to: 'unix://%s'\n", host);
825 break;
826 case RTR_PROTOCOL_TCP:
827 if (!r_socket_connect_tcp (fd, host, port, timeout)) { //TODO: Use rap.ssl
828 core->num->value = 1;
829 eprintf ("Error: Cannot connect to '%s' (%s)\n", host, port);
830 r_socket_free (fd);
831 return;
832 }
833 core->num->value = 0;
834 eprintf ("Connected to: %s at port %s\n", host, port);
835 break;
836 case RTR_PROTOCOL_UDP:
837 if (!r_socket_connect_udp (fd, host, port, timeout)) { //TODO: Use rap.ssl
838 core->num->value = 1;
839 eprintf ("Error: Cannot connect to '%s' (%s)\n", host, port);
840 r_socket_free (fd);
841 return;
842 }
843 core->num->value = 0;
844 eprintf ("Connected to: %s at port %s\n", host, port);
845 break;
846 }
847 ret = core->num->value;
848 for (i = 0; i < RTR_MAX_HOSTS; i++) {
849 if (rtr_host[i].fd) {
850 continue;
851 }
852 rtr_host[i].proto = proto;
853 strncpy (rtr_host[i].host, host, sizeof (rtr_host[i].host)-1);
854 rtr_host[i].port = r_num_get (core->num, port);
855 if (!file) {
856 file = "";
857 }
858 strncpy (rtr_host[i].file, file, sizeof (rtr_host[i].file)-1);
859 rtr_host[i].fd = fd;
860 rtr_n = i;
861 break;
862 }
863 core->num->value = ret;
864 // double free wtf is freed this here? r_socket_free(fd);
865 //r_core_rtr_list (core);
866 }
867
r_core_rtr_remove(RCore * core,const char * input)868 R_API void r_core_rtr_remove(RCore *core, const char *input) {
869 int i;
870
871 if (IS_DIGIT (input[0])) {
872 i = r_num_math (core->num, input);
873 if (i >= 0 && i < RTR_MAX_HOSTS) {
874 r_socket_free (rtr_host[i].fd);
875 rtr_host[i].fd = NULL;
876 }
877 } else {
878 for (i = 0; i < RTR_MAX_HOSTS; i++) {
879 if (rtr_host[i].fd) {
880 r_socket_free (rtr_host[i].fd);
881 rtr_host[i].fd = NULL;
882 }
883 }
884 memset (rtr_host, '\0', RTR_MAX_HOSTS * sizeof (RCoreRtrHost));
885 rtr_n = 0;
886 }
887 }
888
r_core_rtr_session(RCore * core,const char * input)889 R_API void r_core_rtr_session(RCore *core, const char *input) {
890 __rtr_shell (core, atoi (input));
891 }
892
r_core_rtr_rap_run(RCore * core,const char * input)893 static bool r_core_rtr_rap_run(RCore *core, const char *input) {
894 char *file = r_str_newf ("rap://%s", input);
895 int flags = R_PERM_RW;
896 RIODesc *fd = r_io_open_nomap (core->io, file, flags, 0644);
897 if (fd) {
898 if (r_io_is_listener (core->io)) {
899 if (!r_core_serve (core, fd)) {
900 r_cons_singleton ()->context->breaked = true;
901 }
902 r_io_desc_close (fd);
903 // avoid double free, we are not the owners of this fd so we can't destroy it
904 //r_io_desc_free (fd);
905 }
906 } else {
907 r_cons_singleton ()->context->breaked = true;
908 }
909 return !r_cons_singleton ()->context->breaked;
910 // r_core_cmdf (core, "o rap://%s", input);
911 }
912
r_core_rtr_rap_thread(RThread * th)913 static RThreadFunctionRet r_core_rtr_rap_thread(RThread *th) {
914 if (!th) {
915 return false;
916 }
917 RapThread *rt = th->user;
918 if (!rt || !rt->core) {
919 return false;
920 }
921 return r_core_rtr_rap_run (rt->core, rt->input) ? R_TH_REPEAT : R_TH_STOP;
922 }
923
r_core_rtr_cmd(RCore * core,const char * input)924 R_API void r_core_rtr_cmd(RCore *core, const char *input) {
925 unsigned int cmd_len = 0;
926 int fd = atoi (input);
927 if (!fd && *input != '0') {
928 fd = -1;
929 }
930 const char *cmd = strchr (r_str_trim_head_ro (input), ' ');
931 if (cmd) {
932 cmd ++;
933 cmd_len = strlen (cmd);
934 }
935 // "=:"
936 if (*input == ':' && !strchr (input + 1, ':')) {
937 void *bed = r_cons_sleep_begin ();
938 r_core_rtr_rap_run (core, input);
939 r_cons_sleep_end (bed);
940 return;
941 }
942
943 if (*input == '&') { // "=h&" "=&:9090"
944 if (rapthread) {
945 eprintf ("RAP Thread is already running\n");
946 eprintf ("This is experimental and probably buggy. Use at your own risk\n");
947 } else {
948 // TODO: use tasks
949 RapThread *RT = R_NEW0 (RapThread);
950 if (RT) {
951 RT->core = core;
952 RT->input = strdup (input + 1);
953 //RapThread rt = { core, strdup (input + 1) };
954 rapthread = r_th_new (r_core_rtr_rap_thread, RT, false);
955 int cpuaff = (int)r_config_get_i (core->config, "cfg.cpuaffinity");
956 r_th_setaffinity (rapthread, cpuaff);
957 r_th_setname (rapthread, "rapthread");
958 r_th_start (rapthread, true);
959 eprintf ("Background rap server started.\n");
960 }
961 }
962 return;
963 }
964
965 if (fd != -1) {
966 if (fd >= 0 && fd < RTR_MAX_HOSTS) {
967 rtr_n = fd;
968 } else {
969 fd = -1;
970 }
971 } else {
972 // XXX
973 cmd = input;
974 }
975
976 if (!rtr_host[rtr_n].fd) {
977 eprintf ("Error: Unknown host\n");
978 core->num->value = 1; // fail
979 return;
980 }
981
982 if (rtr_host[rtr_n].proto == RTR_PROTOCOL_TCP) {
983 RCoreRtrHost *rh = &rtr_host[rtr_n];
984 RSocket *s = rh->fd;
985 if (cmd_len < 1 || cmd_len > 16384) {
986 return;
987 }
988 r_socket_close (s);
989 if (!r_socket_connect (s, rh->host, sdb_fmt ("%d", rh->port), R_SOCKET_PROTO_TCP, 0)) {
990 eprintf ("Error: Cannot connect to '%s' (%d)\n", rh->host, rh->port);
991 r_socket_free (s);
992 return;
993 }
994 r_socket_write (s, (ut8*)cmd, cmd_len);
995 r_socket_write (s, "\n", 2);
996 int maxlen = 4096; // r_read_le32 (blen);
997 char *cmd_output = calloc (1, maxlen + 1);
998 if (!cmd_output) {
999 eprintf ("Error: Allocating cmd output\n");
1000 return;
1001 }
1002 (void)r_socket_read_block (s, (ut8*)cmd_output, maxlen);
1003 //ensure the termination
1004 r_socket_close (s);
1005 cmd_output[maxlen] = 0;
1006 r_cons_println (cmd_output);
1007 free ((void *)cmd_output);
1008 return;
1009 }
1010
1011 if (rtr_host[rtr_n].proto == RTR_PROTOCOL_HTTP) {
1012 RCoreRtrHost *rh = &rtr_host[rtr_n];
1013 if (cmd_len < 1 || cmd_len > 16384) {
1014 return;
1015 }
1016 int len;
1017 char *uri = r_str_newf ("http://%s:%d/cmd/%s", rh->host, rh->port, cmd);
1018 char *str = r_socket_http_get (uri, NULL, &len);
1019 if (!str) {
1020 eprintf ("Cannot find '%s'\n", uri);
1021 return;
1022 }
1023 core->num->value = 0;
1024 str[len] = 0;
1025 r_cons_print (str);
1026 free ((void *)str);
1027 free ((void *)uri);
1028 return;
1029 }
1030
1031 if (rtr_host[rtr_n].proto == RTR_PROTOCOL_RAP) {
1032 core->num->value = 0; // that's fine
1033 cmd = r_str_trim_head_ro (cmd);
1034 RSocket *fh = rtr_host[rtr_n].fd;
1035 if (!strlen (cmd)) {
1036 // just check if we can connect
1037 r_socket_close (fh);
1038 return;
1039 }
1040 char *cmd_output = r_socket_rap_client_command (fh, cmd, &core->anal->coreb);
1041 r_cons_println (cmd_output);
1042 free (cmd_output);
1043 return;
1044 }
1045 eprintf ("Error: Unknown protocol\n");
1046 }
1047
1048 // TODO: support len for binary data?
r_core_rtr_cmds_query(RCore * core,const char * host,const char * port,const char * cmd)1049 R_API char *r_core_rtr_cmds_query (RCore *core, const char *host, const char *port, const char *cmd) {
1050 RSocket *s = r_socket_new (0);
1051 const int timeout = 0;
1052 char *rbuf = NULL;
1053 int retries = 6;
1054 ut8 buf[1024];
1055
1056 for (; retries > 0; r_sys_usleep (10 * 1000)) {
1057 if (r_socket_connect (s, host, port, R_SOCKET_PROTO_TCP, timeout)) {
1058 break;
1059 }
1060 retries--;
1061 }
1062 if (retries > 0) {
1063 rbuf = strdup ("");
1064 r_socket_write (s, (void*)cmd, strlen (cmd));
1065 //r_socket_write (s, "px\n", 3);
1066 for (;;) {
1067 int ret = r_socket_read (s, buf, sizeof (buf));
1068 if (ret < 1) {
1069 break;
1070 }
1071 buf[ret] = 0;
1072 rbuf = r_str_append (rbuf, (const char *)buf);
1073 }
1074 } else {
1075 eprintf ("Cannot connect\n");
1076 }
1077 r_socket_free (s);
1078 return rbuf;
1079 }
1080
1081 #if HAVE_LIBUV
1082
1083 typedef struct rtr_cmds_context_t {
1084 uv_tcp_t server;
1085 RPVector clients;
1086 void *bed;
1087 } rtr_cmds_context;
1088
1089 typedef struct rtr_cmds_client_context_t {
1090 RCore *core;
1091 char buf[4096];
1092 char *res;
1093 size_t len;
1094 uv_tcp_t *client;
1095 } rtr_cmds_client_context;
1096
rtr_cmds_client_close(uv_tcp_t * client,bool remove)1097 static void rtr_cmds_client_close(uv_tcp_t *client, bool remove) {
1098 uv_loop_t *loop = client->loop;
1099 rtr_cmds_context *context = loop->data;
1100 if (remove) {
1101 size_t i;
1102 for (i = 0; i < r_pvector_len (&context->clients); i++) {
1103 if (r_pvector_at (&context->clients, i) == client) {
1104 r_pvector_remove_at (&context->clients, i);
1105 break;
1106 }
1107 }
1108 }
1109 rtr_cmds_client_context *client_context = client->data;
1110 uv_close ((uv_handle_t *) client, (uv_close_cb) free);
1111 free (client_context->res);
1112 free (client_context);
1113 }
1114
rtr_cmds_alloc_buffer(uv_handle_t * handle,size_t suggested_size,uv_buf_t * buf)1115 static void rtr_cmds_alloc_buffer(uv_handle_t *handle, size_t suggested_size, uv_buf_t *buf) {
1116 rtr_cmds_client_context *context = handle->data;
1117 buf->base = context->buf + context->len;
1118 buf->len = sizeof (context->buf) - context->len - 1;
1119 }
1120
rtr_cmds_write(uv_write_t * req,int status)1121 static void rtr_cmds_write(uv_write_t *req, int status) {
1122 rtr_cmds_client_context *context = req->data;
1123
1124 if (status) {
1125 eprintf ("Write error: %s\n", uv_strerror (status));
1126 }
1127
1128 free (req);
1129 rtr_cmds_client_close (context->client, true);
1130 }
1131
rtr_cmds_read(uv_stream_t * client,ssize_t nread,const uv_buf_t * buf)1132 static void rtr_cmds_read(uv_stream_t *client, ssize_t nread, const uv_buf_t *buf) {
1133 rtr_cmds_context *context = client->loop->data;
1134 rtr_cmds_client_context *client_context = client->data;
1135
1136 if (nread < 0) {
1137 if (nread != UV_EOF) {
1138 eprintf ("Failed to read: %s\n", uv_err_name ((int) nread));
1139 }
1140 rtr_cmds_client_close ((uv_tcp_t *) client, true);
1141 return;
1142 } else if (nread == 0) {
1143 return;
1144 }
1145
1146 buf->base[nread] = '\0';
1147 char *end = strchr (buf->base, '\n');
1148 if (!end) {
1149 return;
1150 }
1151 *end = '\0';
1152
1153 r_cons_sleep_end (context->bed);
1154 client_context->res = r_core_cmd_str (client_context->core, (const char *)client_context->buf);
1155 context->bed = r_cons_sleep_begin ();
1156
1157 if (!client_context->res || !*client_context->res) {
1158 free (client_context->res);
1159 client_context->res = strdup ("\n");
1160 }
1161
1162 if (!client_context->res || (!r_config_get_i (client_context->core->config, "scr.prompt") &&
1163 !strcmp ((char *)buf, "q!")) ||
1164 !strcmp ((char *)buf, ".--")) {
1165 rtr_cmds_client_close ((uv_tcp_t *) client, true);
1166 return;
1167 }
1168
1169 uv_write_t *req = R_NEW (uv_write_t);
1170 if (req) {
1171 req->data = client_context;
1172 uv_buf_t wrbuf = uv_buf_init (client_context->res, (unsigned int) strlen (client_context->res));
1173 uv_write (req, client, &wrbuf, 1, rtr_cmds_write);
1174 }
1175 uv_read_stop (client);
1176 }
1177
rtr_cmds_new_connection(uv_stream_t * server,int status)1178 static void rtr_cmds_new_connection(uv_stream_t *server, int status) {
1179 if (status < 0) {
1180 eprintf ("New connection error: %s\n", uv_strerror (status));
1181 return;
1182 }
1183
1184 rtr_cmds_context *context = server->loop->data;
1185
1186 uv_tcp_t *client = R_NEW (uv_tcp_t);
1187 if (!client) {
1188 return;
1189 }
1190
1191 uv_tcp_init (server->loop, client);
1192 if (uv_accept (server, (uv_stream_t *)client) == 0) {
1193 rtr_cmds_client_context *client_context = R_NEW (rtr_cmds_client_context);
1194 if (!client_context) {
1195 uv_close ((uv_handle_t *)client, NULL);
1196 return;
1197 }
1198
1199 client_context->core = server->data;
1200 client_context->len = 0;
1201 client_context->buf[0] = '\0';
1202 client_context->res = NULL;
1203 client_context->client = client;
1204 client->data = client_context;
1205
1206 uv_read_start ((uv_stream_t *)client, rtr_cmds_alloc_buffer, rtr_cmds_read);
1207
1208 r_pvector_push (&context->clients, client);
1209 } else {
1210 uv_close ((uv_handle_t *)client, NULL);
1211 }
1212 }
1213
rtr_cmds_stop(uv_async_t * handle)1214 static void rtr_cmds_stop(uv_async_t *handle) {
1215 uv_close ((uv_handle_t *) handle, NULL);
1216
1217 rtr_cmds_context *context = handle->loop->data;
1218
1219 uv_close ((uv_handle_t *) &context->server, NULL);
1220
1221 void **it;
1222 r_pvector_foreach (&context->clients, it) {
1223 uv_tcp_t *client = *it;
1224 rtr_cmds_client_close (client, false);
1225 }
1226 }
1227
rtr_cmds_break(uv_async_t * async)1228 static void rtr_cmds_break(uv_async_t *async) {
1229 uv_async_send (async);
1230 }
1231
r_core_rtr_cmds(RCore * core,const char * port)1232 R_API int r_core_rtr_cmds(RCore *core, const char *port) {
1233 if (!port || port[0] == '?') {
1234 r_cons_printf ("Usage: .:[tcp-port] run r2 commands for clients\n");
1235 return 0;
1236 }
1237
1238 uv_loop_t *loop = R_NEW (uv_loop_t);
1239 if (!loop) {
1240 return 0;
1241 }
1242 uv_loop_init (loop);
1243
1244 rtr_cmds_context context;
1245 r_pvector_init (&context.clients, NULL);
1246 loop->data = &context;
1247
1248 context.server.data = core;
1249 uv_tcp_init (loop, &context.server);
1250
1251 struct sockaddr_in addr;
1252 bool local = (bool) r_config_get_i(core->config, "tcp.islocal");
1253 int porti = r_socket_port_by_name (port);
1254 uv_ip4_addr (local ? "127.0.0.1" : "0.0.0.0", porti, &addr);
1255
1256 uv_tcp_bind (&context.server, (const struct sockaddr *) &addr, 0);
1257 int r = uv_listen ((uv_stream_t *)&context.server, 32, rtr_cmds_new_connection);
1258 if (r) {
1259 eprintf ("Failed to listen: %s\n", uv_strerror (r));
1260 goto beach;
1261 }
1262
1263 uv_async_t stop_async;
1264 uv_async_init (loop, &stop_async, rtr_cmds_stop);
1265
1266 r_cons_break_push ((RConsBreak) rtr_cmds_break, &stop_async);
1267 context.bed = r_cons_sleep_begin ();
1268 uv_run (loop, UV_RUN_DEFAULT);
1269 r_cons_sleep_end (context.bed);
1270 r_cons_break_pop ();
1271
1272 beach:
1273 uv_loop_close (loop);
1274 free (loop);
1275 r_pvector_clear (&context.clients);
1276 return 0;
1277 }
1278
1279 #else
1280
r_core_rtr_cmds(RCore * core,const char * port)1281 R_API int r_core_rtr_cmds (RCore *core, const char *port) {
1282 unsigned char buf[4097];
1283 RSocket *ch = NULL;
1284 int i, ret;
1285 char *str;
1286
1287 if (!port || port[0] == '?') {
1288 r_cons_printf ("Usage: .:[tcp-port] run r2 commands for clients\n");
1289 return false;
1290 }
1291
1292 RSocket *s = r_socket_new (0);
1293 s->local = r_config_get_i (core->config, "tcp.islocal");
1294
1295 if (!r_socket_listen (s, port, NULL)) {
1296 eprintf ("Error listening on port %s\n", port);
1297 r_socket_free (s);
1298 return false;
1299 }
1300
1301 eprintf ("Listening for commands on port %s\n", port);
1302 listenport = port;
1303 r_cons_break_push ((RConsBreak)r_core_rtr_http_stop, core);
1304 for (;;) {
1305 if (r_cons_is_breaked ()) {
1306 break;
1307 }
1308 void *bed = r_cons_sleep_begin ();
1309 ch = r_socket_accept (s);
1310 buf[0] = 0;
1311 ret = r_socket_read (ch, buf, sizeof (buf) - 1);
1312 r_cons_sleep_end (bed);
1313 if (ret > 0) {
1314 buf[ret] = 0;
1315 for (i = 0; buf[i]; i++) {
1316 if (buf[i] == '\n') {
1317 buf[i] = buf[i + 1]? ';': '\0';
1318 }
1319 }
1320 if ((!r_config_get_i (core->config, "scr.prompt") &&
1321 !strcmp ((char *)buf, "q!")) ||
1322 !strcmp ((char *)buf, ".--")) {
1323 r_socket_close (ch);
1324 break;
1325 }
1326 str = r_core_cmd_str (core, (const char *)buf);
1327 bed = r_cons_sleep_begin ();
1328 if (str && *str) {
1329 r_socket_write (ch, str, strlen (str));
1330 } else {
1331 r_socket_write (ch, "\n", 1);
1332 }
1333 r_cons_sleep_end (bed);
1334 free (str);
1335 }
1336 r_socket_close (ch);
1337 r_socket_free (ch);
1338 ch = NULL;
1339 }
1340 r_cons_break_pop ();
1341 r_socket_free (s);
1342 r_socket_free (ch);
1343 return 0;
1344 }
1345
1346 #endif
1347