R_API int r_socket_connect (RSocket *s, const char *host, const char *port, int proto, unsigned int timeout) { #if __WINDOWS__ && !defined(__CYGWIN__) && !defined(__MINGW64__) struct sockaddr_in sa; struct hostent *he; WSADATA wsadata; if (WSAStartup (MAKEWORD (1, 1), &wsadata) == SOCKET_ERROR) { eprintf ("Error creating socket."); return false; } s->fd = socket (AF_INET, SOCK_STREAM, 0); if (s->fd == -1) return false; memset (&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; he = (struct hostent *)gethostbyname (host); if (he == (struct hostent*)0) { close (s->fd); return false; } sa.sin_addr = *((struct in_addr *)he->h_addr); s->port = r_socket_port_by_name (port); sa.sin_port = htons (s->port); #warning TODO: implement connect timeout on w32 if (connect (s->fd, (const struct sockaddr*)&sa, sizeof (struct sockaddr))) { close (s->fd); return false; } return true; #elif __UNIX__ || defined(__CYGWIN__) int gai, ret; struct addrinfo hints, *res, *rp; if (!proto) proto = R_SOCKET_PROTO_TCP; signal (SIGPIPE, SIG_IGN); if (proto == R_SOCKET_PROTO_UNIX) { if (!r_socket_unix_connect (s, host)) return false; } else { memset (&hints, 0, sizeof (struct addrinfo)); hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ hints.ai_protocol = proto; gai = getaddrinfo (host, port, &hints, &res); if (gai != 0) { //eprintf ("Error in getaddrinfo: %s\n", gai_strerror (gai)); return false; } for (rp = res; rp != NULL; rp = rp->ai_next) { int flag = 1; s->fd = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (s->fd == -1) continue; ret = setsockopt (s->fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(flag)); if (ret < 0) { close (s->fd); s->fd = -1; continue; } if (timeout>0) { r_socket_block_time (s, 1, timeout); //fcntl (s->fd, F_SETFL, O_NONBLOCK, 1); } ret = connect (s->fd, rp->ai_addr, rp->ai_addrlen); if (timeout == 0 && ret == 0) { freeaddrinfo (res); return true; } else if (ret == 0 /* || nonblocking */) { struct timeval tv; fd_set fdset, errset; FD_ZERO (&fdset); FD_SET (s->fd, &fdset); tv.tv_sec = 1; //timeout; tv.tv_usec = 0; if (r_socket_is_connected (s)) { freeaddrinfo (res); return true; } if (select (s->fd + 1, NULL, NULL, &errset, &tv) == 1) { int so_error; socklen_t len = sizeof so_error; ret = getsockopt (s->fd, SOL_SOCKET, SO_ERROR, &so_error, &len); if (ret == 0 && so_error == 0) { //fcntl (s->fd, F_SETFL, O_NONBLOCK, 0); //r_socket_block_time (s, 0, 0); freeaddrinfo (res); return true; } } } close (s->fd); s->fd = -1; } freeaddrinfo (res); if (rp == NULL) { eprintf ("Could not resolve address '%s'\n", host); return false; } } #endif #if HAVE_LIB_SSL if (s->is_ssl) { s->ctx = SSL_CTX_new (SSLv23_client_method ()); if (s->ctx == NULL) { r_socket_free (s); return false; } s->sfd = SSL_new (s->ctx); SSL_set_fd (s->sfd, s->fd); if (SSL_connect (s->sfd) != 1) { r_socket_free (s); return false; } } #endif return true; }
R_API int r_socket_listen (RSocket *s, const char *port, const char *certfile) { #if __UNIX__ || defined(__CYGWIN__) int optval = 1; int ret; struct linger linger = { 0 }; #endif if (r_sandbox_enable (0)) return false; #if __WINDOWS__ && !defined(__CYGWIN__) && !defined(__MINGW64__) WSADATA wsadata; if (WSAStartup (MAKEWORD (1, 1), &wsadata) == SOCKET_ERROR) { eprintf ("Error creating socket."); return false; } #endif if ((s->fd = socket (AF_INET, SOCK_STREAM, IPPROTO_TCP))<0) return false; #if __UNIX__ || defined(__CYGWIN__) linger.l_onoff = 1; linger.l_linger = 1; ret = setsockopt (s->fd, SOL_SOCKET, SO_LINGER, (void*)&linger, sizeof (linger)); if (ret < 0) return false; { // fix close after write bug // int x = 1500; // FORCE MTU ret = setsockopt (s->fd, SOL_SOCKET, SO_SNDBUF, (void*)&x, sizeof (int)); if (ret < 0) return false; } ret = setsockopt (s->fd, SOL_SOCKET, SO_REUSEADDR, (void*)&optval, sizeof optval); if (ret < 0) return false; #endif memset (&s->sa, 0, sizeof (s->sa)); s->sa.sin_family = AF_INET; s->sa.sin_addr.s_addr = htonl (s->local? INADDR_LOOPBACK: INADDR_ANY); s->port = r_socket_port_by_name (port); if (s->port <1) return false; s->sa.sin_port = htons (s->port); // TODO honor etc/services if (bind (s->fd, (struct sockaddr *)&s->sa, sizeof(s->sa)) < 0) { r_sys_perror ("bind"); close (s->fd); return false; } #if __UNIX__ || defined(__CYGWIN__) signal (SIGPIPE, SIG_IGN); #endif if (listen (s->fd, 32) < 0) { close (s->fd); return false; } #if HAVE_LIB_SSL if (s->is_ssl) { s->ctx = SSL_CTX_new (SSLv23_method ()); if (s->ctx == NULL) { r_socket_free (s); return false; } if (!SSL_CTX_use_certificate_chain_file (s->ctx, certfile)) { r_socket_free (s); return false; } if (!SSL_CTX_use_PrivateKey_file (s->ctx, certfile, SSL_FILETYPE_PEM)) { r_socket_free (s); return false; } SSL_CTX_set_verify_depth (s->ctx, 1); } #endif return true; }
int main(int argc, char **argv) { RSocket *s; RSocketHTTPRequest *rs; int c, timeout = 3; int dodaemon = 0; int dosandbox = 0; const char *port = "8080"; // TODO: add flag to specify if listen in local or 0.0.0.0 while ((c = getopt (argc, argv, "hp:ds")) != -1) { switch (c) { case 's': dosandbox = 1; break; case 'd': dodaemon = 1; break; case 'h': return usage (1); case 'p': port = optarg; break; } } if (dodaemon) { int pid = fork (); if (pid >0) { printf ("%d\n", pid); return 0; } } s = r_socket_new (R_FALSE); s->local = 1; // by default if (!r_socket_listen (s, port, NULL)) { eprintf ("Cannot listen on http.port\n"); return 1; } r_sandbox_enable (dosandbox); while (!r_cons_singleton ()->breaked) { char *result_heap = NULL; const char *result = page_index; rs = r_socket_http_accept (s, timeout); if (!rs) continue; if (!strcmp (rs->method, "GET")) { if (!memcmp (rs->path, "/proc/kill/", 11)) { // TODO: show page here? int pid = atoi (rs->path+11); if (pid>0) kill (pid, 9); } else if (!memcmp (rs->path, "/file/open/", 11)) { int pid; int session_port = 3000 + r_num_rand (1024); char *filename = rs->path +11; int filename_len = strlen (filename); char *cmd; if (!(cmd = malloc (filename_len+40))) { perror ("malloc"); return 1; } sprintf (cmd, "r2 -q -e http.port=%d -c=h \"%s\"", session_port, filename); // TODO: use r_sys api to get pid when running in bg pid = r_sys_cmdbg (cmd); free (cmd); result = result_heap = malloc (1024+filename_len); if (!result) { perror ("malloc"); return 1; } sprintf (result_heap, "<html><body>" "<a href='/'>back</a><hr size=1/>" " - <a target='_blank' href='http://localhost:%d/'>open</a><br />" " - <a href='/proc/kill/%d'>kill</a><br />" "</body></html>", session_port, pid); eprintf ("\nchild pid %d\n\n", pid); } } r_socket_http_response (rs, 200, result, 0, NULL); r_socket_http_close (rs); free (result_heap); } r_socket_free (s); return 0; }
R_API int r_run_start(RRunProfile *p) { #if __APPLE__ posix_spawnattr_t attr = {0}; pid_t pid = -1; #endif int ret; if (!p->_program && !p->_system) { printf ("No program or system rule defined\n"); return 1; } if (p->_stdin) { int f = open (p->_stdin, O_RDONLY); if (f < 0) return 1; close (0); dup2 (f, 0); } if (p->_stdout) { int f = open (p->_stdout, O_WRONLY); if (f < 0) return 1; close (1); dup2 (f, 1); } if (p->_stderr) { int f = open (p->_stderr, O_WRONLY); if (f < 0) return 1; close (2); dup2 (f, 2); } if (p->_aslr != -1) setASLR (p->_aslr); #if __UNIX__ set_limit (p->_docore, RLIMIT_CORE, RLIM_INFINITY); if (p->_maxfd) set_limit (p->_maxfd, RLIMIT_NOFILE, p->_maxfd); #ifdef RLIMIT_NPROC if (p->_maxproc) set_limit (p->_maxproc, RLIMIT_NPROC, p->_maxproc); #endif if (p->_maxstack) set_limit (p->_maxstack, RLIMIT_STACK, p->_maxstack); #else if (p->_docore || p->_maxfd || p->_maxproc || p->_maxstack) eprintf ("Warning: setrlimits not supported for this platform\n"); #endif if (p->_connect) { char *q = strchr (p->_connect, ':'); if (q) { RSocket *fd = r_socket_new (0); *q = 0; if (!r_socket_connect_tcp (fd, p->_connect, q+1, 30)) { eprintf ("Cannot connect\n"); return 1; } eprintf ("connected\n"); close (0); close (1); close (2); dup2 (fd->fd, 0); dup2 (fd->fd, 1); dup2 (fd->fd, 2); } else { eprintf ("Invalid format for connect. missing ':'\n"); return 1; } } if (p->_listen) { RSocket *child, *fd = r_socket_new (0); if (!r_socket_listen (fd, p->_listen, NULL)) { eprintf ("rarun2: cannot listen\n"); r_socket_free (fd); return 1; } child = r_socket_accept (fd); if (child) { eprintf ("connected\n"); close (0); close (1); close (2); dup2 (child->fd, 0); dup2 (child->fd, 1); dup2 (child->fd, 2); } } if (p->_r2sleep != 0) { r_sys_sleep (p->_r2sleep); } if (p->_chgdir) { ret = chdir (p->_chgdir); if (ret < 0) return 1; } if (p->_chroot) { ret = chdir (p->_chroot); if (ret < 0) return 1; } #if __UNIX__ if (p->_chroot) { if (chroot (p->_chroot)) { eprintf ("rarun2: cannot chroot\n"); return 1; } chdir("/"); } if (p->_setuid) { ret = setgroups(0, NULL); if (ret < 0) return 1; ret = setuid (atoi (p->_setuid)); if (ret < 0) return 1; } if (p->_seteuid) { ret = seteuid (atoi (p->_seteuid)); if (ret < 0) return 1; } if (p->_setgid) { ret = setgid (atoi (p->_setgid)); if (ret < 0) return 1; } if (p->_input) { int f2[2]; pipe (f2); close (0); dup2 (f2[0], 0); parseinput (p->_input); write (f2[1], p->_input, strlen (p->_input)); } #endif if (p->_r2preload) { if (p->_preload) { eprintf ("WARNING: Only one library can be opened at a time\n"); } p->_preload = R2_LIBDIR"/libr2."R_LIB_EXT; } if (p->_libpath) { #if __WINDOWS__ eprintf ("rarun2: libpath unsupported for this platform\n"); #elif __HAIKU__ r_sys_setenv ("LIBRARY_PATH", p->_libpath); #elif __APPLE__ r_sys_setenv ("DYLD_LIBRARY_PATH", p->_libpath); #else r_sys_setenv ("LD_LIBRARY_PATH", p->_libpath); #endif } if (p->_preload) { #if __APPLE__ // 10.6 r_sys_setenv ("DYLD_PRELOAD", p->_preload); r_sys_setenv ("DYLD_INSERT_LIBRARIES", p->_preload); // 10.8 r_sys_setenv ("DYLD_FORCE_FLAT_NAMESPACE", "1"); #else r_sys_setenv ("LD_PRELOAD", p->_preload); #endif } if (p->_timeout) { #if __UNIX__ int mypid = getpid (); if (!fork ()) { sleep (p->_timeout); if (!kill (mypid, 0)) eprintf ("\nrarun2: Interrupted by timeout\n"); kill (mypid, SIGKILL); exit (0); } #else eprintf ("timeout not supported for this platform\n"); #endif } #if __APPLE__ posix_spawnattr_init (&attr); if (p->_args[0]) { char **envp = r_sys_get_environ(); ut32 spflags = 0; //POSIX_SPAWN_START_SUSPENDED; spflags |= POSIX_SPAWN_SETEXEC; if (p->_aslr == 0) { #define _POSIX_SPAWN_DISABLE_ASLR 0x0100 spflags |= _POSIX_SPAWN_DISABLE_ASLR; } (void)posix_spawnattr_setflags (&attr, spflags); if (p->_bits) { size_t copied = 1; cpu_type_t cpu; #if __i386__ || __x86_64__ cpu = CPU_TYPE_I386; if (p->_bits == 64) cpu |= CPU_ARCH_ABI64; #else cpu = CPU_TYPE_ANY; #endif posix_spawnattr_setbinpref_np ( &attr, 1, &cpu, &copied); } ret = posix_spawnp (&pid, p->_args[0], NULL, &attr, p->_args, envp); switch (ret) { case 0: break; case 22: eprintf ("posix_spawnp: Invalid argument\n"); break; case 86: eprintf ("posix_spawnp: Unsupported architecture\n"); break; default: eprintf ("posix_spawnp: unknown error %d\n", ret); perror ("posix_spawnp"); break; } exit (ret); } #endif if (p->_system) { if (p->_pid) { eprintf ("PID: Cannot determine pid with 'system' directive. Use 'program'.\n"); } exit (r_sys_cmd (p->_system)); } if (p->_program) { if (!r_file_exists (p->_program)) { char *progpath = r_file_path (p->_program); if (progpath && *progpath) { free (p->_program); p->_program = progpath; } else { free (progpath); eprintf ("rarun2: %s: file not found\n", p->_program); return 1; } } #if __UNIX__ // XXX HACK close all non-tty fds { int i; for (i=3; i<10; i++) close (i); } // TODO: use posix_spawn if (p->_setgid) { ret = setgid (atoi (p->_setgid)); if (ret < 0) return 1; } if (p->_pid) { eprintf ("PID: %d\n", getpid ()); } if (p->_pidfile) { char pidstr[32]; snprintf (pidstr, sizeof (pidstr), "%d\n", getpid ()); r_file_dump (p->_pidfile, (const ut8*)pidstr, strlen (pidstr), 0); } #endif if (p->_nice) { #if __UNIX__ errno = 0; ret = nice(p->_nice); if (ret == -1) { if (errno != 0) { return 1; } } #else eprintf ("nice not supported for this platform\n"); #endif } exit (execv (p->_program, (char* const*)p->_args)); } return 0; }
R_API void r_socket_rap_server_free (RSocketRapServer *rap_s) { if (rap_s) r_socket_free (rap_s->fd); free (rap_s); }
static RIODesc *rap__open(struct r_io_t *io, const char *pathname, int rw, int mode) { RSocket *rap_fd; RIORap *rior; const char *ptr; char *file, *port; char buf[1024]; int i, p, listenmode, is_ssl; if (!rap__plugin_open (io, pathname,0)) return NULL; is_ssl = (!strncmp (pathname, "raps://", 7)); ptr = pathname + (is_ssl? 7: 6); if (!(port = strchr (ptr, ':'))) { eprintf ("rap: wrong uri\n"); return NULL; } listenmode = (*ptr==':'); *port++ = 0; if (!*port) { return NULL; } p = atoi (port); if ((file = strchr (port+1, '/'))) { *file = 0; file++; } if (r_sandbox_enable (0)) { eprintf ("sandbox: Cannot use network\n"); return NULL; } if (listenmode) { if (p<=0) { eprintf ("rap: cannot listen here. Try rap://:9999\n"); return NULL; } //TODO: Handle ^C signal (SIGINT, exit); // ??? eprintf ("rap: listening at port %s ssl %s\n", port, (is_ssl)?"on":"off"); rior = R_NEW0 (RIORap); rior->listener = true; rior->client = rior->fd = r_socket_new (is_ssl); if (rior->fd == NULL) { free (rior); return NULL; } if (is_ssl) { if (file && *file) { if (!r_socket_listen (rior->fd, port, file)) { free (rior); return NULL; } } else { free (rior); return NULL; } } else { if (!r_socket_listen (rior->fd, port, NULL)) return NULL; } return r_io_desc_new (&r_io_plugin_rap, rior->fd->fd, pathname, rw, mode, rior); } if ((rap_fd = r_socket_new (is_ssl)) == NULL) { eprintf ("Cannot create new socket\n"); return NULL; } if (r_socket_connect_tcp (rap_fd, ptr, port, 30) == false) { eprintf ("Cannot connect to '%s' (%d)\n", ptr, p); r_socket_free (rap_fd); return NULL; } eprintf ("Connected to: %s at port %s\n", ptr, port); rior = R_NEW (RIORap); rior->listener = false; rior->client = rior->fd = rap_fd; if (file && *file) { // send buf[0] = RMT_OPEN; buf[1] = rw; buf[2] = (ut8)strlen (file); memcpy (buf+3, file, buf[2]); r_socket_write (rap_fd, buf, 3+buf[2]); r_socket_flush (rap_fd); // read eprintf ("waiting... "); buf[0] = 0; r_socket_read_block (rap_fd, (ut8*)buf, 5); if (buf[0] != (char)(RMT_OPEN|RMT_REPLY)) { eprintf ("rap: Expecting OPEN|REPLY packet. got %02x\n", buf[0]); r_socket_free (rap_fd); free (rior); return NULL; } r_mem_copyendian ((ut8 *)&i, (ut8*)buf+1, 4, ENDIAN); if (i>0) eprintf ("ok\n"); #if 0 /* Read meta info */ r_socket_read (rap_fd, (ut8 *)&buf, 4); r_mem_copyendian ((ut8 *)&i, (ut8*)buf, 4, ENDIAN); while (i>0) { int n = r_socket_read (rap_fd, (ut8 *)&buf, i); if (n<1) break; buf[i] = 0; io->core_cmd_cb (io->user, buf); n = r_socket_read (rap_fd, (ut8 *)&buf, 4); if (n<1) break; r_mem_copyendian ((ut8 *)&i, (ut8*)buf, 4, ENDIAN); i -= n; } #endif } else { r_socket_free (rap_fd); free (rior); return NULL; } //r_socket_free (rap_fd); return r_io_desc_new (&r_io_plugin_rap, rior->fd->fd, pathname, rw, mode, rior); }
int main(int argc, char **argv) { RSocket *s; RSocketHTTPRequest *rs; int c, timeout = 3; int dodaemon = 0; int dosandbox = 0; bool listenlocal = true; const char *port = "8080"; while ((c = getopt (argc, argv, "adhp:sv")) != -1) { switch (c) { case 'a': listenlocal = false; break; case 's': dosandbox = 1; break; case 'd': dodaemon = 1; break; case 'h': return usage (1); case 'v': return showversion (); case 'p': port = optarg; break; default: return usage (0); } } if (optind != argc) { return usage (0); } #if USE_IOS_JETSAM memorystatus_control (MEMORYSTATUS_CMD_SET_JETSAM_TASK_LIMIT, getpid (), 256, NULL, 0); #endif if (dodaemon) { #if LIBC_HAVE_FORK int pid = fork (); #else int pid = -1; #endif if (pid > 0) { printf ("%d\n", pid); return 0; } } s = r_socket_new (false); s->local = listenlocal; if (!r_socket_listen (s, port, NULL)) { eprintf ("Cannot listen on %d\n", s->port); r_socket_free (s); return 1; } eprintf ("http://localhost:%d/\n", s->port); if (dosandbox && !r_sandbox_enable (true)) { eprintf ("sandbox: Cannot be enabled.\n"); return 1; } while (!r_cons_singleton ()->breaked) { char *result_heap = NULL; const char *result = page_index; rs = r_socket_http_accept (s, timeout); if (!rs) continue; if (!strcmp (rs->method, "GET")) { if (!strncmp (rs->path, "/proc/kill/", 11)) { // TODO: show page here? int pid = atoi (rs->path + 11); if (pid > 0) { kill (pid, 9); } } else if (!strncmp (rs->path, "/file/open/", 11)) { int pid; int session_port = 3000 + r_num_rand (1024); char *filename = rs->path + 11; int filename_len = strlen (filename); char *cmd; if (!(cmd = malloc (filename_len + 40))) { perror ("malloc"); return 1; } sprintf (cmd, "r2 -q %s-e http.port=%d -c=h \"%s\"", listenlocal? "": "-e http.bind=public ", session_port, filename); // TODO: use r_sys api to get pid when running in bg pid = r_sys_cmdbg (cmd); free (cmd); result = result_heap = malloc (1024 + filename_len); if (!result) { perror ("malloc"); return 1; } sprintf (result_heap, "<html><body>" "<a href='/'>back</a><hr size=1/>" " - <a target='_blank' href='http://localhost:%d/'>open</a><br />" " - <a href='/proc/kill/%d'>kill</a><br />" "</body></html>", session_port, pid); eprintf ("\nchild pid %d\n\n", pid); } } r_socket_http_response (rs, 200, result, 0, NULL); r_socket_http_close (rs); free (result_heap); result_heap = NULL; } r_socket_free (s); return 0; }
R_API bool r_socket_connect(RSocket *s, const char *host, const char *port, int proto, unsigned int timeout) { #if __WINDOWS__ struct sockaddr_in sa; struct hostent *he; WSADATA wsadata; TIMEVAL Timeout; Timeout.tv_sec = timeout; Timeout.tv_usec = 0; if (WSAStartup (MAKEWORD (1, 1), &wsadata) == SOCKET_ERROR) { eprintf ("Error creating socket."); return false; } s->fd = socket (AF_INET, SOCK_STREAM, 0); #ifdef _MSC_VER if (s->fd == INVALID_SOCKET) { #else if (s->fd == -1) { #endif return false; } unsigned long iMode = 1; int iResult = ioctlsocket (s->fd, FIONBIO, &iMode); if (iResult != NO_ERROR) { eprintf ("ioctlsocket error: %d\n", iResult); } memset (&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; he = (struct hostent *)gethostbyname (host); if (he == (struct hostent*)0) { #ifdef _MSC_VER closesocket (s->fd); #else close (s->fd); #endif return false; } sa.sin_addr = *((struct in_addr *)he->h_addr); s->port = r_socket_port_by_name (port); sa.sin_port = htons (s->port); if (!connect (s->fd, (const struct sockaddr*)&sa, sizeof (struct sockaddr))) { #ifdef _MSC_VER closesocket (s->fd); #else close (s->fd); #endif return false; } iMode = 0; iResult = ioctlsocket (s->fd, FIONBIO, &iMode); if (iResult != NO_ERROR) { eprintf ("ioctlsocket error: %d\n", iResult); } if (timeout > 0) { r_socket_block_time (s, 1, timeout); } fd_set Write, Err; FD_ZERO (&Write); FD_ZERO (&Err); FD_SET (s->fd, &Write); FD_SET (s->fd, &Err); select (0, NULL, &Write, &Err, &Timeout); if (FD_ISSET (s->fd, &Write)) { return true; } return false; #elif __UNIX__ int ret; struct addrinfo hints = {0}; struct addrinfo *res, *rp; if (!proto) { proto = R_SOCKET_PROTO_TCP; } signal (SIGPIPE, SIG_IGN); if (proto == R_SOCKET_PROTO_UNIX) { if (!r_socket_unix_connect (s, host)) { return false; } } else { hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ hints.ai_protocol = proto; int gai = getaddrinfo (host, port, &hints, &res); if (gai != 0) { eprintf ("Error in getaddrinfo: %s\n", gai_strerror (gai)); return false; } for (rp = res; rp != NULL; rp = rp->ai_next) { int flag = 1; s->fd = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (s->fd == -1) { perror ("socket"); continue; } ret = setsockopt (s->fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof (flag)); if (ret < 0) { perror ("setsockopt"); close (s->fd); s->fd = -1; continue; } if (timeout > 0) { r_socket_block_time (s, 1, timeout); //fcntl (s->fd, F_SETFL, O_NONBLOCK, 1); } ret = connect (s->fd, rp->ai_addr, rp->ai_addrlen); if (timeout == 0 && ret == 0) { freeaddrinfo (res); return true; } if (ret == 0 /* || nonblocking */) { struct timeval tv; fd_set fdset, errset; FD_ZERO (&fdset); FD_SET (s->fd, &fdset); tv.tv_sec = 1; //timeout; tv.tv_usec = 0; if (r_socket_is_connected (s)) { freeaddrinfo (res); return true; } if (select (s->fd + 1, NULL, NULL, &errset, &tv) == 1) { int so_error; socklen_t len = sizeof so_error; ret = getsockopt (s->fd, SOL_SOCKET, SO_ERROR, &so_error, &len); if (ret == 0 && so_error == 0) { //fcntl (s->fd, F_SETFL, O_NONBLOCK, 0); //r_socket_block_time (s, 0, 0); freeaddrinfo (res); return true; } } } close (s->fd); s->fd = -1; } freeaddrinfo (res); if (!rp) { eprintf ("Could not resolve address '%s' or failed to connect\n", host); return false; } } #endif #if HAVE_LIB_SSL if (s->is_ssl) { s->ctx = SSL_CTX_new (SSLv23_client_method ()); if (!s->ctx) { r_socket_free (s); return false; } s->sfd = SSL_new (s->ctx); SSL_set_fd (s->sfd, s->fd); if (SSL_connect (s->sfd) != 1) { r_socket_free (s); return false; } } #endif return true; } /* close the file descriptor associated with the RSocket s */ R_API int r_socket_close_fd(RSocket *s) { #ifdef _MSC_VER return s->fd != INVALID_SOCKET ? closesocket (s->fd) : false; #else return s->fd != -1 ? close (s->fd) : false; #endif } /* shutdown the socket and close the file descriptor */ R_API int r_socket_close(RSocket *s) { int ret = false; if (!s) { return false; } if (s->fd != -1) { #if __UNIX__ shutdown (s->fd, SHUT_RDWR); #endif #if __WINDOWS__ // https://msdn.microsoft.com/en-us/library/windows/desktop/ms740481(v=vs.85).aspx shutdown (s->fd, SD_SEND); if (r_socket_ready (s, 0, 250)) { do { char buf = 0; ret = recv (s->fd, &buf, 1, 0); } while (ret != 0 && ret != SOCKET_ERROR); } ret = closesocket (s->fd); #else ret = close (s->fd); #endif } #if HAVE_LIB_SSL if (s->is_ssl && s->sfd) { SSL_free (s->sfd); s->sfd = NULL; } #endif return ret; }
static int redirect_socket_to_pty(RSocket *sock) { #if HAVE_PTY // directly duplicating the fds using dup2() creates problems // in case of interactive applications int fdm, fds; if (openpty (&fdm, &fds, NULL, NULL, NULL) == -1) { perror ("opening pty"); return -1; } pid_t child_pid = r_sys_fork (); if (child_pid == -1) { eprintf ("cannot fork\n"); close(fdm); close(fds); return -1; } if (child_pid == 0) { // child process close (fds); char *buff = NULL; int sockfd = sock->fd; int max_fd = fdm > sockfd ? fdm : sockfd; while (true) { fd_set readfds; FD_ZERO (&readfds); FD_SET (fdm, &readfds); FD_SET (sockfd, &readfds); if (select (max_fd + 1, &readfds, NULL, NULL, NULL) == -1) { perror ("select error"); break; } if (FD_ISSET (fdm, &readfds)) { if (fd_forward (fdm, sockfd, &buff) != 0) { break; } } if (FD_ISSET (sockfd, &readfds)) { if (fd_forward (sockfd, fdm, &buff) != 0) { break; } } } free (buff); close (fdm); r_socket_free (sock); exit (0); } // parent r_socket_close_fd (sock); login_tty (fds); close (fdm); // disable the echo on slave stdin struct termios t; tcgetattr (0, &t); cfmakeraw (&t); tcsetattr (0, TCSANOW, &t); return 0; #else // Fallback to socket to I/O redirection return redirect_socket_to_stdio (sock); #endif }
R_API int r_run_config_env(RRunProfile *p) { int ret; if (!p->_program && !p->_system && !p->_runlib) { printf ("No program, system or runlib rule defined\n"); return 1; } // when IO is redirected to a process, handle them together if (handle_redirection (p->_stdio, true, true, false) != 0) { return 1; } if (handle_redirection (p->_stdin, true, false, false) != 0) { return 1; } if (handle_redirection (p->_stdout, false, true, false) != 0) { return 1; } if (handle_redirection (p->_stderr, false, false, true) != 0) { return 1; } if (p->_aslr != -1) { setASLR (p, p->_aslr); } #if __UNIX__ set_limit (p->_docore, RLIMIT_CORE, RLIM_INFINITY); if (p->_maxfd) { set_limit (p->_maxfd, RLIMIT_NOFILE, p->_maxfd); } #ifdef RLIMIT_NPROC if (p->_maxproc) { set_limit (p->_maxproc, RLIMIT_NPROC, p->_maxproc); } #endif if (p->_maxstack) { set_limit (p->_maxstack, RLIMIT_STACK, p->_maxstack); } #else if (p->_docore || p->_maxfd || p->_maxproc || p->_maxstack) eprintf ("Warning: setrlimits not supported for this platform\n"); #endif if (p->_connect) { char *q = strchr (p->_connect, ':'); if (q) { RSocket *fd = r_socket_new (0); *q = 0; if (!r_socket_connect_tcp (fd, p->_connect, q+1, 30)) { eprintf ("Cannot connect\n"); return 1; } if (p->_pty) { if (redirect_socket_to_pty (fd) != 0) { eprintf ("socket redirection failed\n"); r_socket_free (fd); return 1; } } else { redirect_socket_to_stdio (fd); } } else { eprintf ("Invalid format for connect. missing ':'\n"); return 1; } } if (p->_listen) { RSocket *child, *fd = r_socket_new (0); bool is_child = false; if (!r_socket_listen (fd, p->_listen, NULL)) { eprintf ("rarun2: cannot listen\n"); r_socket_free (fd); return 1; } while (true) { child = r_socket_accept (fd); if (child) { is_child = true; if (p->_dofork && !p->_dodebug) { #ifdef _MSC_VER int child_pid = r_sys_fork (); #else pid_t child_pid = r_sys_fork (); #endif if (child_pid == -1) { eprintf("rarun2: cannot fork\n"); r_socket_free (child); r_socket_free (fd); return 1; } else if (child_pid != 0){ // parent code is_child = false; } } if (is_child) { r_socket_close_fd (fd); eprintf ("connected\n"); if (p->_pty) { if (redirect_socket_to_pty (child) != 0) { eprintf ("socket redirection failed\n"); r_socket_free (child); r_socket_free (fd); return 1; } } else { redirect_socket_to_stdio (child); } break; } else { r_socket_close_fd (child); } } } if (!is_child) { r_socket_free (child); } r_socket_free (fd); } if (p->_r2sleep != 0) { r_sys_sleep (p->_r2sleep); } #if __UNIX__ if (p->_chroot) { if (chdir (p->_chroot) == -1) { eprintf ("Cannot chdir to chroot in %s\n", p->_chroot); return 1; } else { if (chroot (".") == -1) { eprintf ("Cannot chroot to %s\n", p->_chroot); return 1; } else { // Silenting pedantic meson flags... if (chdir ("/") == -1) { eprintf ("Cannot chdir to /\n"); return 1; } if (p->_chgdir) { if (chdir (p->_chgdir) == -1) { eprintf ("Cannot chdir after chroot to %s\n", p->_chgdir); return 1; } } } } } else if (p->_chgdir) { if (chdir (p->_chgdir) == -1) { eprintf ("Cannot chdir after chroot to %s\n", p->_chgdir); return 1; } } #else if (p->_chgdir) { ret = chdir (p->_chgdir); if (ret < 0) { return 1; } } if (p->_chroot) { ret = chdir (p->_chroot); if (ret < 0) { return 1; } } #endif #if __UNIX__ if (p->_setuid) { ret = setgroups (0, NULL); if (ret < 0) { return 1; } ret = setuid (atoi (p->_setuid)); if (ret < 0) { return 1; } } if (p->_seteuid) { ret = seteuid (atoi (p->_seteuid)); if (ret < 0) { return 1; } } if (p->_setgid) { ret = setgid (atoi (p->_setgid)); if (ret < 0) { return 1; } } if (p->_input) { char *inp; int f2[2]; if (pipe (f2) != -1) { close (0); dup2 (f2[0], 0); } else { eprintf ("[ERROR] rarun2: Cannot create pipe\n"); return 1; } inp = getstr (p->_input); if (inp) { size_t inpl = strlen (inp); if (write (f2[1], inp, inpl) != inpl) { eprintf ("[ERROR] rarun2: Cannot write to the pipe\n"); } close (f2[1]); free (inp); } else { eprintf ("Invalid input\n"); } } #endif if (p->_r2preload) { if (p->_preload) { eprintf ("WARNING: Only one library can be opened at a time\n"); } p->_preload = R2_LIBDIR"/libr2."R_LIB_EXT; } if (p->_libpath) { #if __WINDOWS__ eprintf ("rarun2: libpath unsupported for this platform\n"); #elif __HAIKU__ r_sys_setenv ("LIBRARY_PATH", p->_libpath); #elif __APPLE__ r_sys_setenv ("DYLD_LIBRARY_PATH", p->_libpath); #else r_sys_setenv ("LD_LIBRARY_PATH", p->_libpath); #endif } if (p->_preload) { #if __APPLE__ // 10.6 #ifndef __MAC_10_7 r_sys_setenv ("DYLD_PRELOAD", p->_preload); #endif r_sys_setenv ("DYLD_INSERT_LIBRARIES", p->_preload); // 10.8 r_sys_setenv ("DYLD_FORCE_FLAT_NAMESPACE", "1"); #else r_sys_setenv ("LD_PRELOAD", p->_preload); #endif } if (p->_timeout) { #if __UNIX__ int mypid = getpid (); if (!r_sys_fork ()) { int use_signal = p->_timeout_sig; if (use_signal < 1) { use_signal = SIGKILL; } sleep (p->_timeout); if (!kill (mypid, 0)) { eprintf ("\nrarun2: Interrupted by timeout\n"); } kill (mypid, use_signal); exit (0); } #else eprintf ("timeout not supported for this platform\n"); #endif } return 0; }
static int runfile () { int ret; if (!_program && !_system) { printf ("No program or system rule defined\n"); return 1; } if (_stdin) { int f = open (_stdin, O_RDONLY); if (f < 0) return 1; close (0); dup2 (f, 0); } if (_stdout) { int f = open (_stdout, O_WRONLY); if (f < 0) return 1; close (1); dup2 (f, 1); } if (_stderr) { int f = open (_stderr, O_WRONLY); if (f < 0) return 1; close (2); dup2 (f, 2); } #if __UNIX__ set_limit (_docore, RLIMIT_CORE, RLIM_INFINITY); set_limit (_maxfd, RLIMIT_NOFILE, _maxfd); set_limit (_maxproc, RLIMIT_NPROC, _maxproc); set_limit (_maxstack, RLIMIT_STACK, _maxstack); #else if (_docore || _maxfd || _maxproc || _maxstack) eprintf ("Warning: setrlimits not supported for this platform\n"); #endif if (_connect) { char *p = strchr (_connect, ':'); if (p) { RSocket *fd = r_socket_new (0); *p=0; if (!r_socket_connect_tcp (fd, _connect, p+1, 30)) { eprintf ("Cannot connect\n"); return 1; } eprintf ("connected\n"); close (0); close (1); close (2); dup2 (fd->fd, 0); dup2 (fd->fd, 1); dup2 (fd->fd, 2); } else { eprintf ("Invalid format for connect. missing ':'\n"); return 1; } } if (_listen) { RSocket *child, *fd = r_socket_new (0); if (!r_socket_listen (fd, _listen, NULL)) { eprintf ("rarun2: cannot listen\n"); r_socket_free (fd); return 1; } child = r_socket_accept (fd); if (child) { eprintf ("connected\n"); close (0); close (1); close (2); dup2 (child->fd, 0); dup2 (child->fd, 1); dup2 (child->fd, 2); } } if (_r2sleep != 0) { r_sys_sleep (_r2sleep); } if (_chgdir) { ret = chdir (_chgdir); if (ret < 0) return 1; } if (_chroot) { ret = chdir (_chroot); if (ret < 0) return 1; } #if __UNIX__ if (_chroot) { if (chroot (_chroot)) { eprintf ("rarun2: cannot chroot\n"); return 1; } } if (_setuid) { ret = setuid (atoi (_setuid)); if (ret < 0) return 1; } if (_seteuid) { ret = seteuid (atoi (_seteuid)); if (ret < 0) return 1; } if (_setgid) { ret = setgid (atoi (_setgid)); if (ret < 0) return 1; } if (_input) { int f2[2]; pipe (f2); close (0); dup2 (f2[0], 0); parseinput (_input); write (f2[1], _input, strlen (_input)); } #endif if (_r2preload) { if (_preload) { eprintf ("WARNING: Only one library can be opened at a time\n"); } _preload = R2_LIBDIR"/libr2."R_LIB_EXT; } if (_libpath) { #if __WINDOWS__ eprintf ("rarun2: libpath unsupported for this platform\n"); #elif __APPLE__ r_sys_setenv ("DYLD_LIBRARY_PATH", _libpath); #else r_sys_setenv ("LD_LIBRARY_PATH", _libpath); #endif } if (_preload) { #if __APPLE__ // 10.6 r_sys_setenv ("DYLD_PRELOAD", _preload); r_sys_setenv ("DYLD_INSERT_LIBRARIES", _preload); // 10.8 r_sys_setenv ("DYLD_FORCE_FLAT_NAMESPACE", "1"); #else r_sys_setenv ("LD_PRELOAD", _preload); #endif } if (_timeout) { #if __UNIX__ int mypid = getpid (); if (!fork ()) { sleep (_timeout); if (!kill (mypid, 0)) eprintf ("\nrarun2: Interrupted by timeout\n"); kill (mypid, SIGKILL); exit (0); } #else eprintf ("timeout not supported for this platform\n"); #endif } if (_system) { exit (r_sys_cmd (_system)); } if (!r_file_exists (_program)) { eprintf ("rarun2: %s: file not found\n", _program); return 1; } exit (execv (_program, _args)); }
/* TODO: simplify using r_write */ static int cmd_write(void *data, const char *input) { int wseek, i, size, len; RCore *core = (RCore *)data; char *tmp, *str, *ostr; const char *arg, *filename = ""; char _fn[32]; ut64 off; ut8 *buf; st64 num = 0; const char* help_msg[] = { "Usage:","w[x] [str] [<file] [<<EOF] [@addr]","", "w","[1248][+-][n]","increment/decrement byte,word..", "w"," foobar","write string 'foobar'", "w0"," [len]","write 'len' bytes with value 0x00", "w6","[de] base64/hex","write base64 [d]ecoded or [e]ncoded string", "wa","[?] push ebp","write opcode, separated by ';' (use '\"' around the command)", "waf"," file","assemble file and write bytes", "wao"," [?] op","modify opcode (change conditional of jump. nop, etc)", "wA"," [?] r 0","alter/modify opcode at current seek (see wA?)", "wb"," 010203","fill current block with cyclic hexpairs", "wB","[-]0xVALUE","set or unset bits with given value", "wc","","list all write changes", "wc","[?][ir*?]","write cache undo/commit/reset/list (io.cache)", "wd"," [off] [n]","duplicate N bytes from offset at current seek (memcpy) (see y?)", "we","[?] [nNsxX] [arg]","extend write operations (insert instead of replace)", "wf"," -|file","write contents of file at current offset", "wh"," r2","whereis/which shell command", "wm"," f0ff","set binary mask hexpair to be used as cyclic write mask", "wo","[?] hex","write in block with operation. 'wo?' fmi", "wp"," [?] -|file","apply radare patch file. See wp? fmi", "wr"," 10","write 10 random bytes", "ws"," pstring","write 1 byte for length and then the string", "wt[f]"," [?] file [sz]","write to file (from current seek, blocksize or sz bytes)", "wts"," host:port [sz]", "send data to remote host:port via tcp://", "ww"," foobar","write wide string 'f\\x00o\\x00o\\x00b\\x00a\\x00r\\x00'", "wx","[?][fs] 9090","write two intel nops (from wxfile or wxseek)", "wv","[?] eip+34","write 32-64 bit value", "wz"," string","write zero terminated string (like w + \\x00)", NULL }; if (!input) { return 0; } len = strlen (input); wseek = r_config_get_i (core->config, "cfg.wseek"); str = ostr = strdup (*input? input + 1: ""); _fn[0] = 0; switch (*input) { case 'B': switch (input[1]) { case ' ': cmd_write_bits (core, 1, r_num_math (core->num, input + 2)); break; case '-': cmd_write_bits (core, 0, r_num_math (core->num, input + 2)); break; default: eprintf ("Usage: wB 0x2000 # or wB-0x2000\n"); break; } break; case '0': { ut64 len = r_num_math (core->num, input+1); if (len>0) { ut8 *buf = calloc (1, len); if (buf) { r_io_write_at (core->io, core->offset, buf, len); r_core_block_read (core); free (buf); } else eprintf ("Cannot allocate %d bytes\n", (int)len); } } break; case '1': case '2': case '4': case '8': if (input[1] && input[2]) { if (input[1]==input[2]) { num = 1; } else num = r_num_math (core->num, input+2); } switch (input[2] ? input[1] : 0) { case '+': cmd_write_inc (core, *input-'0', num); break; case '-': cmd_write_inc (core, *input-'0', -num); break; default: eprintf ("Usage: w[1248][+-][num] # inc/dec byte/word/..\n"); } break; case '6': { int fail = 0; ut8 *buf = NULL; int len = 0, str_len; const char *str; if (input[1] && input[2] != ' ') fail = 1; if (input[1] && input[2] && input[3]) str = input + 3; else str = ""; str_len = strlen (str) + 1; if (!fail) { switch (input[1]) { case 'd': buf = malloc (str_len); len = r_base64_decode (buf, str, 0); if(len == 0) { free(buf); fail = 1; } break; case 'e': { ut8 *bin_buf = malloc (str_len); const int bin_len = r_hex_str2bin (str, bin_buf); if (bin_len <= 0) { fail = 1; } else { buf = calloc (str_len + 1, 4); len = r_base64_encode ((char *)buf, bin_buf, bin_len); if(len == 0) { free (buf); fail = 1; } } free (bin_buf); break; } default: fail = 1; break; } } if (!fail) { r_core_write_at (core, core->offset, buf, len); WSEEK (core, len); r_core_block_read (core); free (buf); } else { eprintf ("Usage: w6[de] base64/hex\n"); } break; } case 'h': { char *p = strchr (input, ' '); if (p) { while (*p==' ') p++; p = r_file_path (p); if (p) { r_cons_println (p); free (p); } } } break; case 'e': { ut64 addr = 0, len = 0, b_size = 0; st64 dist = 0; ut8* bytes = NULL; int cmd_suc = false; char *input_shadow = NULL, *p = NULL; switch (input[1]) { case 'n': if (input[2] == ' ') { len = *input ? r_num_math (core->num, input+3) : 0; if (len > 0) { const ut64 cur_off = core->offset; cmd_suc = r_core_extend_at (core, core->offset, len); core->offset = cur_off; r_core_block_read (core); } } break; case 'N': if (input[2] == ' ') { input += 3; while (*input && *input == ' ') input++; addr = r_num_math (core->num, input); while (*input && *input != ' ') input++; input++; len = *input ? r_num_math (core->num, input) : 0; if (len > 0){ ut64 cur_off = core->offset; cmd_suc = r_core_extend_at (core, addr, len); cmd_suc = r_core_seek (core, cur_off, 1); core->offset = addr; r_core_block_read (core); } } break; case 'x': if (input[2] == ' ') { input += 2; len = *input ? strlen (input) : 0; bytes = len > 1? malloc (len+1) : NULL; len = bytes ? r_hex_str2bin (input, bytes) : 0; if (len > 0) { ut64 cur_off = core->offset; cmd_suc = r_core_extend_at (core, cur_off, len); if (cmd_suc) { r_core_write_at (core, cur_off, bytes, len); } core->offset = cur_off; r_core_block_read (core); } free (bytes); } break; case 'X': if (input[2] == ' ') { addr = r_num_math (core->num, input+3); input += 3; while (*input && *input != ' ') input++; input++; len = *input ? strlen (input) : 0; bytes = len > 1? malloc (len+1) : NULL; len = bytes ? r_hex_str2bin (input, bytes) : 0; if (len > 0) { //ut64 cur_off = core->offset; cmd_suc = r_core_extend_at (core, addr, len); if (cmd_suc) { r_core_write_at (core, addr, bytes, len); } core->offset = addr; r_core_block_read (core); } free (bytes); } break; case 's': input += 3; while (*input && *input == ' ') input++; len = strlen (input); input_shadow = len > 0? malloc (len+1): 0; // since the distance can be negative, // the r_num_math will perform an unwanted operation // the solution is to tokenize the string :/ if (input_shadow) { strncpy (input_shadow, input, len+1); p = strtok (input_shadow, " "); addr = p && *p ? r_num_math (core->num, p) : 0; p = strtok (NULL, " "); dist = p && *p ? r_num_math (core->num, p) : 0; p = strtok (NULL, " "); b_size = p && *p ? r_num_math (core->num, p) : 0; if (dist != 0){ r_core_shift_block (core, addr, b_size, dist); r_core_seek (core, addr, 1); cmd_suc = true; } } free (input_shadow); break; case '?': default: cmd_suc = false; } if (cmd_suc == false) { const char* help_msg[] = { "Usage", "", "write extend", "wen", " <num>", "insert num null bytes at current offset", "wex", " <hex_bytes>", "insert bytes at current offset", "weN", " <addr> <len>", "insert bytes at address", "weX", " <addr> <hex_bytes>", "insert bytes at address", "wes", " <addr> <dist> <block_size>", "shift a blocksize left or write in the editor", NULL}; r_core_cmd_help (core, help_msg); } } break; case 'p': if (input[1]=='-' || (input[1]==' ' && input[2]=='-')) { char *out = r_core_editor (core, NULL, NULL); if (out) { r_core_patch (core, out); free (out); } } else { if (input[1]==' ' && input[2]) { char *data = r_file_slurp (input+2, NULL); if (data) { r_core_patch (core, data); free (data); } } else { r_cons_printf ("Usage: wp [-|r2patch-file]\n" " ^# -> comments\n" " . -> execute command\n" " ! -> execute command\n" " OFFSET { code block }\n" " OFFSET \"string\"\n" " OFFSET 01020304\n" " OFFSET : assembly\n" " + {code}|\"str\"|0210|: asm\n"); } } break; case 'u': // TODO: implement it in an API RCore.write_unified_hexpatch() is ETOOLONG if (input[1]==' ') { char *data = r_file_slurp (input+2, NULL); if (data) { char sign = ' '; int line = 0, offs = 0, hexa = 0; int newline = 1; for (i=0; data[i]; i++) { switch (data[i]) { case '+': if (newline) sign = 1; break; case '-': if (newline) { sign = 0; offs = i + ((data[i+1]==' ')?2:1); } break; case ' ': data[i] = 0; if (sign) { if (!line) line = i+1; else if (!hexa) hexa = i+1; } break; case '\r': break; case '\n': newline = 1; if (sign == -1) { offs = 0; line = 0; hexa = 0; } else if (sign) { if (offs && hexa) { r_cons_printf ("wx %s @ %s\n", data+hexa, data+offs); } else eprintf ("food\n"); offs = 0; line = 0; } else hexa = 0; sign = -1; continue; } newline = 0; } free (data); } } else { eprintf ("|Usage: wu [unified-diff-patch] # see 'cu'\n"); } break; case 'r': //wr off = r_num_math (core->num, input+1); len = (int)off; if (len > 0) { buf = malloc (len); if (buf != NULL) { r_num_irand (); for (i=0; i<len; i++) buf[i] = r_num_rand (256); r_core_write_at (core, core->offset, buf, len); WSEEK (core, len); free (buf); } else eprintf ("Cannot allocate %d bytes\n", len); } break; case 'A': switch (input[1]) { case ' ': if (input[2] && input[3]==' ') { r_asm_set_pc (core->assembler, core->offset); eprintf ("modify (%c)=%s\n", input[2], input+4); len = r_asm_modify (core->assembler, core->block, input[2], r_num_math (core->num, input+4)); eprintf ("len=%d\n", len); if (len>0) { r_core_write_at (core, core->offset, core->block, len); WSEEK (core, len); } else eprintf ("r_asm_modify = %d\n", len); } else eprintf ("Usage: wA [type] [value]\n"); break; case '?': default: { const char* help_msg[] = { "Usage:", " wA", "[type] [value]", "Types", "", "", "r", "", "raw write value", "v", "", "set value (taking care of current address)", "d", "", "destination register", "0", "", "1st src register", "1", "", "2nd src register", "Example:", "wA r 0", "# e800000000", NULL}; r_core_cmd_help (core, help_msg); break; } } break; case 'c': switch (input[1]) { case 'i': r_io_cache_commit (core->io, 0, UT64_MAX); r_core_block_read (core); break; case 'r': r_io_cache_reset (core->io, true); /* Before loading the core block we have to make sure that if * the cache wrote past the original EOF these changes are no * longer displayed. */ memset (core->block, 0xff, core->blocksize); r_core_block_read (core); break; case '+': if (input[2]=='*') { //r_io_cache_reset (core->io, true); eprintf ("TODO\n"); } else if (input[2]==' ') { char *p = strchr (input+3, ' '); ut64 to, from; from = r_num_math (core->num, input+3); if (p) { *p = 0; to = r_num_math (core->num, input+3); if (to<from) { eprintf ("Invalid range (from>to)\n"); return 0; } } else { to = from + core->blocksize; } r_io_cache_commit (core->io, from, to); } else { eprintf ("Invalidate write cache at 0x%08"PFMT64x"\n", core->offset); r_io_cache_commit (core->io, core->offset, core->offset+1); } break; case '-': if (input[2]=='*') { r_io_cache_reset (core->io, true); } else if (input[2]==' ') { char *p = strchr (input+3, ' '); ut64 to, from; if (p) { *p = 0; from = r_num_math (core->num, input+3); to = r_num_math (core->num, input+3); if (to<from) { eprintf ("Invalid range (from>to)\n"); return 0; } } else { from = r_num_math (core->num, input+3); to = from + core->blocksize; } r_io_cache_invalidate (core->io, from, to); } else { eprintf ("Invalidate write cache at 0x%08"PFMT64x"\n", core->offset); r_io_cache_invalidate (core->io, core->offset, core->offset+core->blocksize); } /* See 'r' above. */ memset (core->block, 0xff, core->blocksize); r_core_block_read (core); break; case '?': { const char* help_msg[] = { "Usage:", "wc[ir+-*?]"," # NOTE: Uses io.cache=true", "wc","","list all write changes", "wc-"," [from] [to]","remove write op at curseek or given addr", "wc+"," [addr]","commit change from cache to io", "wc*","","\"\" in radare commands", "wcr","","reset all write changes in cache", "wci","","commit write cache", NULL }; r_core_cmd_help (core, help_msg); } break; case '*': r_io_cache_list (core->io, 1); break; case 'j': r_io_cache_list (core->io, 2); break; case '\0': //if (!r_config_get_i (core->config, "io.cache")) // eprintf ("[warning] e io.cache must be true\n"); r_io_cache_list (core->io, 0); break; } break; case ' ': // "w" /* write string */ len = r_str_unescape (str); r_core_write_at (core, core->offset, (const ut8*)str, len); #if 0 r_io_use_desc (core->io, core->file->desc); r_io_write_at (core->io, core->offset, (const ut8*)str, len); #endif WSEEK (core, len); r_core_block_read (core); break; case 'z': // "wz" /* write zero-terminated string */ len = r_str_unescape (str); r_core_write_at (core, core->offset, (const ut8*)str + 1, len); if (len > 0) { core->num->value = len; } else { core->num->value = 0; } #if 0 r_io_use_desc (core->io, core->file->desc); #endif WSEEK (core, len + 1); r_core_block_read (core); break; case 't': // "wt" if (*str == 's') { // "wts" if (str[1] == ' ') { eprintf ("Write to server\n"); st64 sz = r_io_size (core->io); if (sz > 0) { ut64 addr = 0; char *host = str + 2; char *port = strchr (host, ':'); if (port) { *port ++= 0; char *space = strchr (port, ' '); if (space) { *space++ = 0; sz = r_num_math (core->num, space); addr = core->offset; } ut8 *buf = calloc (1, sz); r_io_read_at (core->io, addr, buf, sz); RSocket *s = r_socket_new (false); if (r_socket_connect (s, host, port, R_SOCKET_PROTO_TCP, 0)) { int done = 0; eprintf ("Transfering file to the end-point...\n"); while (done < sz) { int rc = r_socket_write (s, buf + done, sz - done); if (rc <1) { eprintf ("oops\n"); break; } done += rc; } } else { eprintf ("Cannot connect\n"); } r_socket_free (s); free (buf); } else { eprintf ("Usage wts host:port [sz]\n"); } } else { eprintf ("Unknown file size\n"); } } else { eprintf ("Usage wts host:port [sz]\n"); } } else if (*str == '?' || *str == '\0') { const char* help_msg[] = { "Usage:", "wt[a] file [size]", " Write 'size' bytes in current blok to 'file'", "wta", " [filename]", "append to 'filename'", "wtf", " [filename] [size]", "write to file (see also 'wxf' and 'wf?')", "wtf!", " [filename]", "write to file from current addresss to eof", NULL}; r_core_cmd_help (core, help_msg); free (ostr); return 0; } else { bool append = false; bool toend = false; st64 sz = core->blocksize; if (*str == 'f') { // "wtf" str++; if (*str == '!') { toend = true; str++; } if (*str) { filename = str + ((*str == ' ')? 1: 0); } else { filename = ""; } } else if (*str=='a') { // "wta" append = 1; str++; if (str[0] == ' ') { filename = str + 1; } else { const char* prefix = r_config_get (core->config, "cfg.prefixdump"); snprintf (_fn, sizeof (_fn), "%s.0x%08"PFMT64x, prefix, core->offset); filename = _fn; } } else if (*str != ' ') { const char* prefix = r_config_get (core->config, "cfg.prefixdump"); snprintf (_fn, sizeof (_fn), "%s.0x%08"PFMT64x, prefix, core->offset); filename = _fn; } else { filename = str + 1; } tmp = strchr (str + 1, ' '); if (!filename || !*filename) { const char* prefix = r_config_get (core->config, "cfg.prefixdump"); snprintf (_fn, sizeof (_fn), "%s.0x%08"PFMT64x, prefix, core->offset); filename = _fn; } if (tmp) { if (toend) { sz = r_io_desc_size (core->io, core->file->desc) - core->offset; } else { sz = (st64) r_num_math (core->num, tmp + 1); if (!sz) { sz = core->blocksize; } *tmp = 0; } if (sz < 1) { eprintf ("Invalid length\n"); } else { r_core_dump (core, filename, core->offset, (ut64)sz, append); } } else { if (toend) { sz = r_io_desc_size (core->io, core->file->desc) - core->offset; r_core_dump (core, filename, core->offset, (ut64)sz, append); } else { if (!r_file_dump (filename, core->block, core->blocksize, append)) { sz = 0; } else { sz = core->blocksize; } } } eprintf ("Dumped %"PFMT64d" bytes from 0x%08"PFMT64x" into %s\n", sz, core->offset, filename); } break; case 'f': cmd_wf (core, input); break; case 'w': str++; len = (len - 1) << 1; tmp = (len > 0) ? malloc (len + 1) : NULL; if (tmp) { for (i=0; i<len; i++) { if (i%2) tmp[i] = 0; else tmp[i] = str[i>>1]; } str = tmp; r_io_use_desc (core->io, core->file->desc); r_io_write_at (core->io, core->offset, (const ut8*)str, len); WSEEK (core, len); r_core_block_read (core); free (tmp); } else { eprintf ("Cannot malloc %d\n", len); } break; case 'x': // "wx" switch (input[1]) { case 'f': // "wxf" arg = (const char *)(input + ((input[2]==' ')? 3: 2)); if (!strcmp (arg, "-")) { int len; ut8 *out; char *in = r_core_editor (core, NULL, NULL); if (in) { out = (ut8 *)strdup (in); if (out) { len = r_hex_str2bin (in, out); if (len > 0) { r_io_write_at (core->io, core->offset, out, len); core->num->value = len; } else { core->num->value = 0; } free (out); } free (in); } } else if (r_file_exists (arg)) { if ((buf = r_file_slurp_hexpairs (arg, &size))) { r_io_use_desc (core->io, core->file->desc); if (r_io_write_at (core->io, core->offset, buf, size) > 0) { core->num->value = size; WSEEK (core, size); } free (buf); r_core_block_read (core); } else { eprintf ("This file doesnt contains hexpairs\n"); } } else { eprintf ("Cannot open file '%s'\n", arg); } break; case 's': // "wxs" { int len = cmd_write_hexpair (core, input + 2); if (len > 0) { r_core_seek_delta (core, len); core->num->value = len; } else { core->num->value = 0; } } break; case ' ': // "wx ..." cmd_write_hexpair (core, input + 1); break; default: { const char* help_msg[] = { "Usage:", "wx[f] [arg]", "", "wx", " 9090", "write two intel nops", "wxf", " -|file", "write contents of hexpairs file here", "wxs", " 9090", "write hexpairs and seek at the end", NULL}; r_core_cmd_help (core, help_msg); break; } } break; case 'a': // "wa" switch (input[1]) { case 'o': // "wao" if (input[2] == ' ') r_core_hack (core, input+3); else r_core_hack_help (core); break; case ' ': case '*': { const char *file = input[1]=='*'? input+2: input+1; RAsmCode *acode; r_asm_set_pc (core->assembler, core->offset); acode = r_asm_massemble (core->assembler, file); if (acode) { if (input[1]=='*') { cmd_write_hexpair(core, acode->buf_hex); } else { if (r_config_get_i (core->config, "scr.prompt")) eprintf ("Written %d bytes (%s) = wx %s\n", acode->len, input+2, acode->buf_hex); r_core_write_at (core, core->offset, acode->buf, acode->len); WSEEK (core, acode->len); r_core_block_read (core); } r_asm_code_free (acode); } } break; case 'f': // "wof" if ((input[2]==' '||input[2]=='*')) { const char *file = input[2]=='*'? input+4: input+3; RAsmCode *acode; r_asm_set_pc (core->assembler, core->offset); acode = r_asm_assemble_file (core->assembler, file); if (acode) { if (input[2]=='*') { cmd_write_hexpair(core, acode->buf_hex); } else { if (r_config_get_i (core->config, "scr.prompt")) eprintf ("Written %d bytes (%s)=wx %s\n", acode->len, input+1, acode->buf_hex); r_core_write_at (core, core->offset, acode->buf, acode->len); WSEEK (core, acode->len); r_core_block_read (core); } r_asm_code_free (acode); } else eprintf ("Cannot assemble file\n"); } else eprintf ("Wrong argument\n"); break; default: { const char* help_msg[] = { "Usage:", "wa[of*] [arg]", "", "wa", " nop", "write nopcode using asm.arch and asm.bits", "wa*", " mov eax, 33", "show 'wx' op with hexpair bytes of assembled opcode", "\"wa nop;nop\"", "" , "assemble more than one instruction (note the quotes)", "waf", "foo.asm" , "assemble file and write bytes", "wao?", "", "show help for assembler operation on current opcode (hack)", NULL}; r_core_cmd_help (core, help_msg); break; } } break; case 'b': // "wb" { int len = strlen (input); ut8 *buf = malloc (len+1); if (buf) { len = r_hex_str2bin (input+1, buf); if (len > 0) { r_mem_copyloop (core->block, buf, core->blocksize, len); r_core_write_at (core, core->offset, core->block, core->blocksize); WSEEK (core, core->blocksize); r_core_block_read (core); } else eprintf ("Wrong argument\n"); free (buf); } else eprintf ("Cannot malloc %d\n", len+1); } break; case 'm': size = r_hex_str2bin (input+1, (ut8*)str); switch (input[1]) { case '\0': eprintf ("Current write mask: TODO\n"); // TODO break; case '?': break; case '-': r_io_set_write_mask (core->io, 0, 0); eprintf ("Write mask disabled\n"); break; case ' ': if (size>0) { r_io_use_desc (core->io, core->file->desc); r_io_set_write_mask (core->io, (const ut8*)str, size); WSEEK (core, size); eprintf ("Write mask set to '"); for (i=0; i<size; i++) eprintf ("%02x", str[i]); eprintf ("'\n"); } else eprintf ("Invalid string\n"); break; } break; case 'v': cmd_write_value (core, input); break; case 'o': cmd_write_op (core, input); break; case 'd': if (input[1] && input[1]==' ') { char *arg, *inp = strdup (input+2); arg = strchr (inp, ' '); if (arg) { *arg = 0; ut64 addr = r_num_math (core->num, input+2); ut64 len = r_num_math (core->num, arg+1); ut8 *data = malloc (len); r_io_read_at (core->io, addr, data, len); r_io_write_at (core->io, core->offset, data, len); free (data); } else eprintf ("See wd?\n"); free (inp); } else eprintf ("Usage: wd [source-offset] [length] @ [dest-offset]\n"); break; case 's': if (str && *str && str[1]) { len = r_str_unescape (str+1); if (len>255) { eprintf ("Too large\n"); } else { ut8 ulen = (ut8)len; r_core_write_at (core, core->offset, &ulen, 1); r_core_write_at (core, core->offset+1, (const ut8*)str+1, len); WSEEK (core, len); r_core_block_read (core); } } else eprintf ("Too short.\n"); break; default: case '?': if (core->oobi) { eprintf ("Writing oobi buffer!\n"); r_io_use_desc (core->io, core->file->desc); r_io_write (core->io, core->oobi, core->oobi_len); WSEEK (core, core->oobi_len); r_core_block_read (core); } else { r_core_cmd_help (core, help_msg); } break; }
R_API int r_socket_connect (RSocket *s, const char *host, const char *port, int proto) { #if __WINDOWS__ struct sockaddr_in sa; struct hostent *he; WSADATA wsadata; if (WSAStartup (MAKEWORD (1, 1), &wsadata) == SOCKET_ERROR) { eprintf ("Error creating socket."); return R_FALSE; } s->fd = socket (AF_INET, SOCK_STREAM, 0); if (s->fd == -1) return R_FALSE; memset (&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; he = (struct hostent *)gethostbyname (host); if (he == (struct hostent*)0) { close (s->fd); return R_FALSE; } sa.sin_addr = *((struct in_addr *)he->h_addr); sa.sin_port = htons (atoi (port)); if (connect (s->fd, (const struct sockaddr*)&sa, sizeof (struct sockaddr))) { close (s->fd); return R_FALSE; } return R_TRUE; #elif __UNIX__ int gai; struct addrinfo hints, *res, *rp; signal (SIGPIPE, SIG_IGN); if (proto == R_SOCKET_PROTO_UNIX) { if (!r_socket_unix_connect (s, host)) return R_FALSE; } else { memset (&hints, 0, sizeof (struct addrinfo)); hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */ hints.ai_protocol = proto; gai = getaddrinfo (host, port, &hints, &res); if (gai != 0) { eprintf ("Error in getaddrinfo: %s\n", gai_strerror (gai)); return R_FALSE; } for (rp = res; rp != NULL; rp = rp->ai_next) { s->fd = socket (rp->ai_family, rp->ai_socktype, rp->ai_protocol); if (s->fd == -1) continue; if (connect (s->fd, rp->ai_addr, rp->ai_addrlen) != -1) break; close (s->fd); } if (rp == NULL) { eprintf ("Could not connect\n"); return R_FALSE; } freeaddrinfo (res); } #endif #if HAVE_LIB_SSL if (s->is_ssl) { s->ctx = SSL_CTX_new (SSLv23_client_method ()); if (s->ctx == NULL) { r_socket_free (s); return R_FALSE; } s->sfd = SSL_new (s->ctx); SSL_set_fd (s->sfd, s->fd); if (SSL_connect (s->sfd) != 1) { r_socket_free (s); return R_FALSE; } } #endif return R_TRUE; }
R_API int r_core_rtr_http(RCore *core, int launch, const char *path) { char buf[32]; RSocketHTTPRequest *rs; int iport, oldsandbox = -1; int timeout = r_config_get_i (core->config, "http.timeout"); int x = r_config_get_i (core->config, "scr.html"); int y = r_config_get_i (core->config, "scr.color"); int z = r_config_get_i (core->config, "asm.bytes"); int u = r_config_get_i (core->config, "scr.interactive"); int v = r_config_get_i (core->config, "asm.cmtright"); const char *port = r_config_get (core->config, "http.port"); char *allow = (char *)r_config_get (core->config, "http.allow"); if (core->http_up) { eprintf ("http server is already running\n"); return 1; } if (r_sandbox_enable (0)) { eprintf ("sandbox: connect disabled\n"); return 1; } if (path && atoi (path)) { port = path; path = NULL; } if (!strcmp (port, "0")) { r_num_irand (); iport = 1024+r_num_rand (45256); snprintf (buf, sizeof (buf), "%d", iport); port = buf; } s = r_socket_new (R_FALSE); s->local = !r_config_get_i (core->config, "http.public"); if (!r_socket_listen (s, port, NULL)) { eprintf ("Cannot listen on http.port\n"); return 1; } if (launch) { char cmd[128]; const char *browser = r_config_get (core->config, "http.browser"); snprintf (cmd, sizeof (cmd)-1, "%s http://localhost:%d/%s &", browser, atoi (port), path?path:""); r_sys_cmd (cmd); } r_config_set (core->config, "asm.cmtright", "false"); r_config_set (core->config, "scr.html", "true"); r_config_set (core->config, "scr.color", "false"); r_config_set (core->config, "asm.bytes", "false"); r_config_set (core->config, "scr.interactive", "false"); if (r_config_get_i (core->config, "http.sandbox")) { oldsandbox = r_config_get_i (core->config, "cfg.sandbox"); r_config_set (core->config, "cfg.sandbox", "true"); } eprintf ("Starting http server...\n"); eprintf ("http://localhost:%d/\n", atoi (port)); core->http_up = R_TRUE; while (!r_cons_singleton ()->breaked) { r_cons_break ((RConsBreak)http_break, core); rs = r_socket_http_accept (s, timeout); if (!rs) { if (!s) break; r_sys_usleep (100); continue; } if (allow && *allow) { int accepted = R_FALSE; const char *host; char *p, *peer = r_socket_to_string (rs->s); char *allows = strdup (allow); //eprintf ("Firewall (%s)\n", allows); int i, count = r_str_split (allows, ','); p = strchr (peer, ':'); if (p) *p = 0; for (i=0; i<count; i++) { host = r_str_word_get0 (allows, i); //eprintf ("--- (%s) (%s)\n", host, peer); if (!strcmp (host, peer)) { accepted = R_TRUE; break; } } free (peer); free (allows); if (!accepted) { r_socket_http_close (rs); continue; } } if (!rs->method || !rs->path) { eprintf ("Invalid http headers received from client\n"); r_socket_http_close (rs); continue; } char *dir = NULL; if (r_config_get_i (core->config, "http.dirlist")) if (r_file_is_directory (rs->path)) dir = strdup (rs->path); if (!strcmp (rs->method, "GET")) { if (!memcmp (rs->path, "/up", 3)) { if (r_config_get_i (core->config, "http.upget")) { const char *uproot = r_config_get (core->config, "http.uproot"); if (!rs->path[3] || (rs->path[3]=='/'&&!rs->path[4])) { char *ptr = rtr_dir_files (uproot); r_socket_http_response (rs, 200, ptr, 0, NULL); free (ptr); } else { char *path = r_file_root (uproot, rs->path + 4); if (r_file_exists (path)) { int sz = 0; char *f = r_file_slurp (path, &sz); if (f) { r_socket_http_response (rs, 200, f, sz, NULL); free (f); } else { r_socket_http_response (rs, 403, "Permission denied", 0, NULL); eprintf ("http: Cannot open '%s'\n", path); } } else { if (dir) { char *resp = rtr_dir_files (dir); r_socket_http_response (rs, 404, resp, 0, NULL); free (resp); } else { eprintf ("File '%s' not found\n", path); r_socket_http_response (rs, 404, "File not found\n", 0, NULL); } } free (path); } } else { r_socket_http_response (rs, 403, "Permission denied\n", 0, NULL); } } else if (!memcmp (rs->path, "/cmd/", 5)) { char *cmd = rs->path +5; char foo[32]; const char *httpcmd = r_config_get (core->config, "http.uri"); while (*cmd=='/') cmd++; if (httpcmd && *httpcmd) { int len; char *res; // do remote http query and proxy response snprintf (foo, sizeof (foo), "%s/%s", httpcmd, cmd); res = r_socket_http_get (foo, NULL, &len); if (res) { res[len]=0; r_cons_printf ("%s\n", res); } } else { char *out, *cmd = rs->path+5; r_str_uri_decode (cmd); // eprintf ("CMD (%s)\n", cmd); out = r_core_cmd_str_pipe (core, cmd); // eprintf ("\nOUT LEN = %d\n", strlen (out)); if (out) { char *res = r_str_uri_encode (out); r_socket_http_response (rs, 200, out, 0, "Content-Type: text/plain\n"); free (out); free (res); } else r_socket_http_response (rs, 200, "", 0, NULL); } } else { const char *root = r_config_get (core->config, "http.root"); char *path = r_file_root (root, rs->path); // FD IS OK HERE if (rs->path [strlen (rs->path)-1] == '/') { path = r_str_concat (path, "index.html"); //rs->path = r_str_concat (rs->path, "index.html"); } else { //snprintf (path, sizeof (path), "%s/%s", root, rs->path); if (r_file_is_directory (path)) { char res[128]; snprintf (res, sizeof (res), "Location: %s/\n", rs->path); r_socket_http_response (rs, 302, NULL, 0, res); r_socket_http_close (rs); free (path); free (dir); dir = NULL; continue; } } if (r_file_exists (path)) { int sz = 0; char *f = r_file_slurp (path, &sz); if (f) { const char *contenttype = NULL; if (strstr (path, ".js")) contenttype = "Content-Type: application/javascript\n"; if (strstr (path, ".css")) contenttype = "Content-Type: text/css\n"; if (strstr (path, ".html")) contenttype = "Content-Type: text/html\n"; r_socket_http_response (rs, 200, f, sz, contenttype); free (f); } else { r_socket_http_response (rs, 403, "Permission denied", 0, NULL); eprintf ("http: Cannot open '%s'\n", path); } } else { if (dir) { char *resp = rtr_dir_files (dir); eprintf ("Dirlisting %s\n", dir); r_socket_http_response (rs, 404, resp, 0, NULL); free (resp); } else { eprintf ("File '%s' not found\n", path); r_socket_http_response (rs, 404, "File not found\n", 0, NULL); } } free (path); } } else if (!strcmp (rs->method, "POST")) { ut8 *ret; int retlen; char buf[128]; if (r_config_get_i (core->config, "http.upload")) { ret = r_socket_http_handle_upload ( rs->data, rs->data_length, &retlen); if (ret) { ut64 size = r_config_get_i (core->config, "http.maxsize"); if (size && retlen > size) { r_socket_http_response (rs, 403, "403 File too big\n", 0, NULL); } else { char *filename = r_file_root ( r_config_get (core->config, "http.uproot"), rs->path + 4); eprintf ("UPLOADED '%s'\n", filename); r_file_dump (filename, ret, retlen); free (filename); snprintf (buf, sizeof (buf), "<html><body><h2>uploaded %d bytes. Thanks</h2>\n", retlen); r_socket_http_response (rs, 200, buf, 0, NULL); } free (ret); } } else { r_socket_http_response (rs, 403, "403 Forbidden\n", 0, NULL); } } else { r_socket_http_response (rs, 404, "Invalid protocol", 0, NULL); } r_socket_http_close (rs); free (dir); } core->http_up = R_FALSE; r_socket_free (s); r_cons_break_end (); r_config_set_i (core->config, "scr.html", x); r_config_set_i (core->config, "scr.color", y); r_config_set_i (core->config, "asm.bytes", z); r_config_set_i (core->config, "scr.interactive", u); r_config_set_i (core->config, "asm.cmtright", v); if (oldsandbox != -1) r_config_set_i (core->config, "cfg.sandbox", oldsandbox); return 0; }
R_API void r_core_rtr_add(RCore *core, const char *_input) { char *port, input[1024], *host = NULL, *file = NULL, *ptr = NULL, buf[1024]; int proto, i, timeout, ret; RSocket *fd; timeout = r_config_get_i (core->config, "http.timeout"); strncpy (input, _input, sizeof (input)-4); /* Parse uri */ if ((ptr = strstr (input, "tcp://"))) { proto = RTR_PROT_TCP; host = ptr+6; } else if ((ptr = strstr(input, "http://"))) { proto = RTR_PROT_HTTP; host = ptr+7; } else if ((ptr = strstr(input, "udp://"))) { proto = RTR_PROT_UDP; host = ptr+6; } else if ((ptr = strstr(input, "rap://"))) { proto = RTR_PROT_RAP; host = ptr+6; } else { proto = RTR_PROT_RAP; host = input; } while (*host && iswhitechar (*host)) host++; if (!(ptr = strchr (host, ':'))) { ptr = host; port = "80"; } else { *ptr++ = '\0'; port = ptr; } if (!(file = strchr (ptr, '/'))) { eprintf("Error: Missing '/'\n"); return; } *file++ = 0; port = r_str_chop (port); while (*file==' ') file++; if (r_sandbox_enable (0)) { eprintf ("sandbox: connect disabled\n"); return; } fd = r_socket_new (R_FALSE); if (!fd) { eprintf ("Error: Cannot create new socket\n"); return; } switch (proto) { case RTR_PROT_HTTP: { char uri[1024], prompt[64]; int len; char *str, *res; if (file[strlen (file)-1]=='/') { snprintf (prompt, sizeof (prompt), "[http://%s:%s/%s]> ", host, port, file); r_line_set_prompt (prompt); for (;;) { char *ptr, *str = r_line_readline (); if (!str || !*str) break; if (*str == 'q') break; ptr = r_str_uri_encode (str); if (ptr) str = ptr; snprintf (uri, sizeof (uri), "http://%s:%s/%s%s", host, port, file, str); if (ptr == str) free (ptr); str = r_socket_http_get (uri, NULL, &len); if (str) { str[len] = 0; res = strstr (str, "\n\n"); if (res) res = strstr (res+1, "\n\n"); if (res) res += 2; else res = str; printf ("%s%s", res, (res[strlen (res)-1]=='\n')?"":"\n"); r_line_hist_add (str); free (str); } } r_socket_free (fd); return; } snprintf (uri, sizeof (uri), "http://%s:%s/%s", host, port, file); str = r_socket_http_get (uri, NULL, &len); if (str) { str[len] = 0; res = strstr (str, "\n\n"); if (res) res = strstr (res+1, "\n\n"); if (res) res += 2; else res = str; printf ("%s", res); free (str); } else eprintf ("HTTP connection has failed\n"); // do not add connection. wtf return; } break; case RTR_PROT_RAP: if (!r_socket_connect_tcp (fd, host, port, timeout)) { //TODO: Use rap.ssl eprintf ("Error: Cannot connect to '%s' (%s)\n", host, port); return; } eprintf ("Connected to %s at port %s\n", host, port); /* send */ buf[0] = RTR_RAP_OPEN; buf[1] = 0; buf[2] = (ut8)(strlen (file)+1); memcpy (buf+3, file, buf[2]); r_socket_write(fd, buf, 3+buf[2]); /* read */ eprintf ("waiting... "); fflush(stdout); r_socket_read (fd, (ut8*)buf, 5); r_mem_copyendian ((ut8 *)&i, (ut8*)buf+1, 4, core->assembler->big_endian); if (buf[0] != (char)(RTR_RAP_OPEN|RTR_RAP_REPLY) || i<= 0) { eprintf ("Error: Wrong reply\n"); return; } eprintf ("ok\n"); break; case RTR_PROT_TCP: if (!r_socket_connect_tcp (fd, host, port, timeout)) { //TODO: Use rap.ssl core->num->value = 1; eprintf("Error: Cannot connect to '%s' (%s)\n", host, port); return; } core->num->value = 0; eprintf ("Connected to: %s at port %s\n", host, port); break; case RTR_PROT_UDP: if (!r_socket_connect_udp (fd, host, port, timeout)) { //TODO: Use rap.ssl core->num->value = 1; eprintf ("Error: Cannot connect to '%s' (%s)\n", host, port); return; } core->num->value = 0; eprintf("Connected to: %s at port %s\n", host, port); break; } ret = core->num->value; for (i = 0; i < RTR_MAX_HOSTS; i++) if (!rtr_host[i].fd) { rtr_host[i].proto = proto; memcpy (rtr_host[i].host, host, 512); rtr_host[i].port = r_num_get (core->num, port); memcpy (rtr_host[i].file, file, 1024); rtr_host[i].fd = fd; rtr_n = i; break; } core->num->value = ret; r_socket_free(fd); //r_core_rtr_list (core); }