commit b3c2bdef477a6d069b7bd73d3f0d6150d3e5bfbf
parent 3b759a5229fcfaaf3732f296bdda279507ef1081
Author: Jan Pobrislo <ccx@te2000.cz>
Date: Fri, 8 Nov 2024 12:39:58 +0000
Remove files unrelated to miniroon
Diffstat:
19 files changed, 3 insertions(+), 1611 deletions(-)
diff --git a/.gitignore b/.gitignore
@@ -0,0 +1 @@
+*.o
diff --git a/src/Makefile b/src/Makefile
@@ -1,11 +1,7 @@
-tools_simple:=argv0exec nosuid pidns_run safelink spawn-pty fdsend fdrecv fdrecvto socketpair ptsname mtime_to_uuidv7 ucspi-socksserver ucspi-socksserver-connected miniroon
+tools_simple:=miniroon
-tools_libcap:=applyuidgid-caps
-
-tools_libs6:=ucspi-socksserver-access
-
-tools=$(tools_simple) $(tools_libcap) $(tools_libs6)
+tools=$(tools_simple)
all: $(tools)
.PHONY: all
@@ -22,16 +18,3 @@ $(1): $(1).o ../link
../link -o '$$@' '$(1).o'
endef
$(foreach var,$(tools_simple),$(eval $(call link_simple,$(var))))
-
-define link_libcap =
-$(1): $(1).o ../link
- ../link -o '$$@' '$(1).o' -lcap
-endef
-$(foreach var,$(tools_libcap),$(eval $(call link_libcap,$(var))))
-
-define link_libs6 =
-$(1): $(1).o ../link
- ../link -o '$$@' '$(1).o' -ls6
-endef
-$(foreach var,$(tools_libs6),$(eval $(call link_libs6,$(var))))
-
diff --git a/src/applyuidgid-caps.c b/src/applyuidgid-caps.c
@@ -1,97 +0,0 @@
-/* ISC license. */
-
-#include <unistd.h>
-#include <grp.h>
-#include <limits.h>
-#include <stdlib.h>
-#include <sys/prctl.h>
-#include <sys/capability.h>
-#include <linux/securebits.h>
-
-#include <skalibs/types.h>
-#include <skalibs/setgroups.h>
-#include <skalibs/strerr.h>
-#include <skalibs/sgetopt.h>
-#include <skalibs/djbunix.h>
-#include <skalibs/exec.h>
-
-#define USAGE "applyuidgid-caps [ -z ] [ -u uid ] [ -g gid ] [ -G gidlist ] [ -U ] iab_caps prog..."
-#define dieusage() strerr_dieusage(100, USAGE)
-
-int main (int argc, char const *const *argv)
-{
- uid_t uid = 0 ;
- gid_t gid = 0 ;
- gid_t gids[NGROUPS_MAX+1] ;
- size_t gidn = (size_t)-1 ;
- int unexport = 0 ;
- PROG = "s6-applyuidgid" ;
- {
- subgetopt l = SUBGETOPT_ZERO ;
- for (;;)
- {
- int opt = subgetopt_r(argc, argv, "zUu:g:G:", &l) ;
- if (opt == -1) break ;
- switch (opt)
- {
- case 'z' : unexport = 1 ; break ;
- case 'u' : if (!uid0_scan(l.arg, &uid)) dieusage() ; break ;
- case 'g' : if (!gid0_scan(l.arg, &gid)) dieusage() ; break ;
- case 'G' : if (!gid_scanlist(gids, NGROUPS_MAX, l.arg, &gidn) && *l.arg) dieusage() ; break ;
- case 'U' :
- {
- char const *x = getenv("UID") ;
- if (!x) strerr_dienotset(100, "UID") ;
- if (!uid0_scan(x, &uid)) strerr_dieinvalid(100, "UID") ;
- x = getenv("GID") ;
- if (!x) strerr_dienotset(100, "GID") ;
- if (!gid0_scan(x, &gid)) strerr_dieinvalid(100, "GID") ;
- x = getenv("GIDLIST") ;
- if (!x) strerr_dienotset(100, "GIDLIST") ;
- if (!gid_scanlist(gids, NGROUPS_MAX+1, x, &gidn) && *x)
- strerr_dieinvalid(100, "GIDLIST") ;
- break ;
- }
- default : dieusage() ;
- }
- }
- argc -= l.ind ; argv += l.ind ;
- }
- if (argc < 2) dieusage() ;
-
- /*
- The IAB 3-tuple of capability vectors (Inh, Amb and Bound),
- captured in type cap_iab_t combine to pass capabilities
- from one process to another through execve(2) system calls.
- */
-
- /* parse the first argument to obtain a set of capabilities */
- cap_iab_t new_iab;
- new_iab = cap_iab_from_text(argv[0]);
- if (new_iab == NULL) {
- strerr_dieinvalid(100, "caps") ;
- // strerr_dief1sys(100, "requested capabilities were not recognized");
- }
-
- if (prctl(PR_SET_SECUREBITS,
- SECBIT_KEEP_CAPS | /* unneeded as NO_SETUID_FIXUP is superset */
- SECBIT_NO_SETUID_FIXUP |
- SECBIT_NOROOT | /* disables suid and filecap privilege gain */
- SECBIT_NOROOT_LOCKED) < 0) {
- strerr_dief1sys(111, "Failed to set securebits via prctl()");
- }
- /* set these capabilities for the current process */
- if (cap_iab_set_proc(new_iab) != 0) {
- strerr_dief1sys(111, "Failed to set capabilities via cap_set_proc()");
- }
-
- if (gidn != (size_t)-1 && setgroups_and_gid(gid ? gid : getegid(), gidn, gids) < 0)
- strerr_diefu1sys(111, "set supplementary group list") ;
- if (gid && setgid(gid) < 0)
- strerr_diefu1sys(111, "setgid") ;
- if (uid && setuid(uid) < 0)
- strerr_diefu1sys(111, "setuid") ;
-
- if (unexport) xmexec_n(argv, "UID\0GID\0GIDLIST", 16, 3) ;
- else xexec(&argv[1]) ;
-}
diff --git a/src/argv0exec.c b/src/argv0exec.c
@@ -1,17 +0,0 @@
-#include <skalibs/exec.h>
-
-int main (int argc, const char const **argv)
-{
- const char *new_argv[argc + 1];
- for(size_t i = 0; i < argc; i++) {
- new_argv[i] = argv[i];
- }
- new_argv[argc] = 0;
-
- for(size_t i = 0; argv[0][i]; i++) {
- if(argv[0][i] == '/') {
- new_argv[0] = &argv[0][i+1];
- }
- }
- xexec(new_argv);
-}
diff --git a/src/fdrecv.c b/src/fdrecv.c
@@ -1,55 +0,0 @@
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/select.h>
-
-#include <skalibs/types.h>
-#include <skalibs/strerr.h>
-#include <skalibs/djbunix.h>
-#include <skalibs/exec.h>
-#include <skalibs/ancil.h>
-
-#define USAGE "fdrecv socket_fd fd_env_var prog..."
-#define PROG "fdrecv"
-
-void wait_readable(int fd) {
- fd_set rfds, xfds;
- int retval = 0;
- FD_ZERO(&rfds);
- FD_ZERO(&xfds);
- while(retval < 1) {
- FD_SET(fd, &rfds);
- FD_SET(fd, &xfds);
- retval = select(fd+1, &rfds, NULL, &xfds, NULL);
- if (retval == -1 && errno != EINTR) {
- strerr_dief1sys(111, "select()");
- }
- }
-}
-
-int main (int argc, char const *const *argv)
-{
- unsigned int socket_fd;
- int fd = -1;
- if ((argc < 4)) strerr_dieusage(100, USAGE) ;
- if (!uint0_scan(argv[1], &socket_fd)) strerr_dieusage(100, USAGE) ;
-
- while(fd < 0) {
- wait_readable(socket_fd);
- fd = ancil_recv_fd(socket_fd, 42);
- if(fd < 0 && errno != EAGAIN) {
- strerr_dief1sys(111, "recvmsg()");
- }
- }
-
- /* disable close-on-exec flag if present on fd */
- if(fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, NULL) & ~FD_CLOEXEC) == -1) {
- strerr_dief1sys(111, "fcntl() disabling FD_CLOEXEC");
- }
-
- size_t env_size = strlen(argv[2]) + uint_fmt(0, fd) + 2;
- char envstr[env_size];
- char *p = stpncpy(envstr, argv[2], env_size);
- *p++ = '=';
- uint_fmt(p, fd);
- xmexec_n(argv+3, envstr, env_size-1, 1);
-}
diff --git a/src/fdrecvto.c b/src/fdrecvto.c
@@ -1,57 +0,0 @@
-#include <errno.h>
-#include <unistd.h>
-#include <sys/select.h>
-
-#include <skalibs/types.h>
-#include <skalibs/strerr.h>
-#include <skalibs/djbunix.h>
-#include <skalibs/exec.h>
-#include <skalibs/ancil.h>
-
-#define USAGE "fdrecv socket_fd fd_env_var prog..."
-#define PROG "fdrecv"
-
-void wait_readable(int fd) {
- fd_set rfds, xfds;
- int retval = 0;
- FD_ZERO(&rfds);
- FD_ZERO(&xfds);
- while(retval < 1) {
- FD_SET(fd, &rfds);
- FD_SET(fd, &xfds);
- retval = select(fd+1, &rfds, NULL, &xfds, NULL);
- if (retval == -1 && errno != EINTR) {
- strerr_dief1sys(111, "select()");
- }
- }
-}
-
-int main (int argc, char const *const *argv)
-{
- unsigned int socket_fd, target_fd;
- int fd = -1;
- if ((argc < 4)) strerr_dieusage(100, USAGE) ;
- if (!uint0_scan(argv[1], &socket_fd)) strerr_dieusage(100, USAGE) ;
- if (!uint0_scan(argv[2], &target_fd)) strerr_dieusage(100, USAGE) ;
-
- while(fd < 0) {
- wait_readable(socket_fd);
- fd = ancil_recv_fd(socket_fd, 42);
- if(fd < 0 && errno != EAGAIN) {
- strerr_dief1sys(111, "recvmsg()");
- }
- }
- if(fd == target_fd) {
- int tmp_fd = dup(fd);
- if(tmp_fd < 0) {
- strerr_dief1sys(111, "dup()");
- }
- close(fd);
- fd = tmp_fd;
- }
- if(dup2(fd, target_fd) < 0) {
- strerr_dief1sys(111, "dup2()");
- }
-
- xexec(argv+3) ;
-}
diff --git a/src/fdsend.c b/src/fdsend.c
@@ -1,45 +0,0 @@
-#include <errno.h>
-#include <sys/select.h>
-
-#include <skalibs/types.h>
-#include <skalibs/strerr.h>
-#include <skalibs/djbunix.h>
-#include <skalibs/exec.h>
-#include <skalibs/ancil.h>
-
-#define USAGE "fdsend socket_fd fd_to_send prog..."
-#define PROG "fdsend"
-
-void wait_writable(int fd) {
- fd_set wfds, xfds;
- int retval = 0;
- FD_ZERO(&wfds);
- FD_ZERO(&xfds);
- while(retval < 1) {
- FD_SET(fd, &wfds);
- FD_SET(fd, &xfds);
- retval = select(fd+1, NULL, &wfds, &xfds, NULL);
- if (retval == -1 && errno != EINTR) {
- strerr_dief1sys(111, "select()");
- }
- }
-}
-
-
-int main (int argc, char const *const *argv)
-{
- unsigned int socket_fd, fd_to_send ;
- if ((argc < 4)) strerr_dieusage(100, USAGE) ;
- if (!uint0_scan(argv[1], &socket_fd)) strerr_dieusage(100, USAGE) ;
- if (!uint0_scan(argv[2], &fd_to_send)) strerr_dieusage(100, USAGE) ;
-
- wait_writable(socket_fd);
- while(!ancil_send_fd(socket_fd, fd_to_send, 42)) {
- if(errno != EAGAIN) {
- strerr_dief1sys(111, "sendmsg()");
- }
- wait_writable(socket_fd);
- }
-
- xexec(argv+3) ;
-}
diff --git a/src/mtime_to_uuidv7.c b/src/mtime_to_uuidv7.c
@@ -1,63 +0,0 @@
-#include <stdint.h>
-#include <sys/stat.h> /* for stat(), struct stat */
-#include <unistd.h> /* for getentropy() */
-#include <stdio.h> /* for printf() */
-#include <fcntl.h> /* Definition of AT_* constants */
-
-#include <skalibs/strerr.h>
-
-#define PROG "mtime_to_uuidv7"
-#define USAGE "mtime_to_uuidv7 [filename]"
-
-
-void uuidv7(struct timespec *ts, uint8_t* value) {
- // timestamp in ms
- uint64_t timestamp = (uint64_t)ts->tv_sec * 1000 + ts->tv_nsec / 1000000;
-
- // random bytes
- if(getentropy(value, 16)) {
- strerr_dief1sys(111, "getentropy()");
- }
-
- // timestamp
- value[0] = (timestamp >> 40) & 0xFF;
- value[1] = (timestamp >> 32) & 0xFF;
- value[2] = (timestamp >> 24) & 0xFF;
- value[3] = (timestamp >> 16) & 0xFF;
- value[4] = (timestamp >> 8) & 0xFF;
- value[5] = timestamp & 0xFF;
-
- // version and variant
- value[6] = (value[6] & 0x0F) | 0x70;
- value[8] = (value[8] & 0x3F) | 0x80;
-}
-
-
-int main (int argc, char const *const *argv)
-{
- if (argc > 2) {
- strerr_dieusage(100, USAGE);
- }
- struct stat statinfo;
- if(argc == 2) {
- if(stat(argv[1], &statinfo)) {
- strerr_diefu2sys(111, "stat(): ", argv[1]);
- }
- } else {
- if(fstatat(0, "", &statinfo, AT_EMPTY_PATH)) {
- strerr_diefu1sys(111, "fstatat(stdin)");
- }
- }
-
- uint8_t uuid_val[16];
- uuidv7(&statinfo.st_mtim, uuid_val);
-
- for (size_t i = 0; i < 16; i++) {
- printf("%02x", uuid_val[i]);
- }
- printf("\n");
-
- return 0;
-}
-/* vim: sw=4 sts=4 et
-*/
diff --git a/src/nosuid.c b/src/nosuid.c
@@ -1,22 +0,0 @@
-/* ISC license. */
-
-#include <sys/prctl.h>
-#include <linux/securebits.h>
-
-#include <skalibs/exec.h>
-#include <skalibs/djbunix.h>
-#include <skalibs/strerr.h>
-
-#define USAGE "nosuid prog..."
-#define dieusage() strerr_dieusage(100, USAGE)
-
-int main (int argc, char const *const *argv)
-{
- if (argc < 2) dieusage() ;
-
- if (prctl(PR_SET_SECUREBITS, SECBIT_NOROOT | SECBIT_NOROOT_LOCKED) < 0) {
- strerr_dief1sys(111, "Failed to set securebits via prctl()");
- }
-
- else xexec(&argv[1]) ;
-}
diff --git a/src/pidns_run.c b/src/pidns_run.c
@@ -1,110 +0,0 @@
-#include <fcntl.h>
-#include <errno.h>
-#include <sched.h> /* Definition of CLONE_* constants & unshare */
-#include <unistd.h> /* fork(), getpid() */
-#include <sys/wait.h>
-#include <sys/select.h>
-#include <assert.h>
-#include <stdlib.h> /* exit() */
-
-#include <skalibs/exec.h>
-#include <skalibs/djbunix.h>
-#include <skalibs/strerr.h>
-
-#define PROG "pidns_run"
-
-void fd_cloexec(int fd) {
- int flags = fcntl(fd, F_GETFD);
- if(flags == -1) {
- strerr_dief1sys(111, "fcntl() getfd");
- }
- if(fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) {
- strerr_dief1sys(111, "fcntl() setfd");
- }
-}
-
-void fd_nonblock(int fd) {
- int flags = fcntl(fd, F_GETFL);
- if(flags == -1) {
- strerr_dief1sys(111, "fcntl() getfd");
- }
- if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
- strerr_dief1sys(111, "fcntl() setfd");
- }
-}
-
-void nonblock_cloexec(int fd) {
- fd_cloexec(fd);
- fd_nonblock(fd);
-}
-
-int main(const int argc, const char **argv) {
- int piperw[2];
- #define parent_rfd piperw[0]
- #define parent_wfd piperw[1]
- /* returns EINVAL for some reason
- if(pipe2(piperw, O_NONBLOCK | FD_CLOEXEC) != 0) {
- strerr_dief1sys(111, "pipe2()");
- }
- */
- if(pipe(piperw) != 0) {
- strerr_dief1sys(111, "pipe()");
- }
- nonblock_cloexec(parent_rfd);
- nonblock_cloexec(parent_wfd);
- if(unshare(CLONE_NEWPID) != 0) {
- strerr_dief1sys(111, "unshare()");
- }
- int fork1_pid = fork();
- if(fork1_pid < 0) {
- strerr_dief1sys(111, "first fork()");
- }
- if(fork1_pid == 0) {
- /* child */
- assert(getpid() == 1);
- if(close(parent_wfd) != 0) {
- strerr_dief1sys(111, "close(parent_wfd)");
- }
- int fork2_pid = fork();
- if(fork2_pid < 0) {
- strerr_dief1sys(111, "second fork()");
- }
- if(fork2_pid == 0) {
- /* child */
- exec(&argv[1]);
- } else {
- /* parent */
- fd_set rfds;
- struct timeval tv = {1, 0};
- int retval, wstatus;
- pid_t pid;
- FD_ZERO(&rfds);
- FD_SET(parent_rfd, &rfds);
- while(1) {
- pid = waitpid(0, &wstatus, WNOHANG);
- if(pid == fork2_pid) {
- exit(wait_estatus(wstatus));
- }
- retval = select(1, &rfds, NULL, NULL, &tv);
- if (retval == -1 && errno != EINTR) {
- strerr_dief1sys(111, "select()");
- }
- if(retval > 0) {
- const char term_msg[] = "pidns_run: parent died, terminating\n";
- write(2, "pidns_run: parent died, terminating\n", sizeof(term_msg));
- exit(111);
- }
- tv.tv_sec = 1;
- tv.tv_usec = 0;
- }
- }
- } else {
- /* parent */
- if(close(parent_rfd) != 0) {
- strerr_dief1sys(111, "close(parent_rfd)");
- }
- int wstatus;
- pid_t pid = waitpid(fork1_pid, &wstatus, 0);
- exit(wait_estatus(wstatus));
- }
-}
diff --git a/src/ptsname.c b/src/ptsname.c
@@ -1,30 +0,0 @@
-#include <unistd.h> /* write() */
-#include <stdlib.h> /* ptsname() */
-#include <string.h>
-
-#include <skalibs/types.h>
-#include <skalibs/strerr.h>
-
-#define USAGE "ptsname ptmx_fd"
-#define PROG "ptsname"
-
-
-int main (int argc, char const *const *argv)
-{
- unsigned int ptmx_fd;
- const char *pts_name;
- if ((argc != 2)) strerr_dieusage(100, USAGE) ;
- if (!uint0_scan(argv[1], &ptmx_fd)) strerr_dieusage(100, USAGE) ;
-
- pts_name = ptsname(ptmx_fd);
- if (pts_name == NULL) {
- strerr_dief1sys(111, "ptsname()");
- }
-
- if (write(1, pts_name, strlen(pts_name)) <= 0) {
- strerr_dief1sys(111, "write()");
- }
- if (write(1, "\n", 1) <= 0) {
- strerr_dief1sys(111, "write()");
- }
-}
diff --git a/src/safelink.c b/src/safelink.c
@@ -1,120 +0,0 @@
-#include <errno.h> /* for errno */
-#include <fcntl.h> /* for mkdirat() openat() */
-#include <unistd.h> /* for linkat() */
-#include <stdio.h> /* for renameat() */
-#include <stdbool.h> /* for bool */
-
-#include <skalibs/strerr.h>
-#include <skalibs/random.h>
-
-#define PROG "safelink"
-#define USAGE "safelink oldpath newpath"
-#define BUFLEN 260
-
-const char* opendir_nofollow(const char *pathname, int *fd, bool create_dirs)
-{
- char next[BUFLEN];
- int fd1, fd2;
- const char *base; /* final part (basename) to return */
- const char *s1 = pathname;
- char *s2 = next;
-
- if(pathname[0] == '/') {
- fd1 = open("/", O_NOFOLLOW | O_DIRECTORY | O_RDONLY);
- if(fd1 < 0) {
- strerr_diefu1sys(111, "open() root");
- }
- s1++;
- } else {
- fd1 = open(".", O_NOFOLLOW | O_DIRECTORY | O_RDONLY);
- if(fd1 < 0) {
- strerr_diefu1sys(111, "open() CWD");
- }
- }
- base = s1;
- while (*s1) {
- /* Copy character by character from pathname[] to next[]. */
- *(s2++) = *(s1++);
- if (s2 >= &next[BUFLEN]) {
- strerr_dief1x(100, "filename exceeded buffer size");
- }
- if(*s1 == 0) {
- /* end of string, return dir fd and final path component */
- *fd = fd1;
- return base;
- }
- if(*s1 == '/') {
- if(*s1) { s1++; }
- if(s2 == next) { continue; } /* skip empty filename or trailing slash */
- *s2 = 0; /* null-terminate the string in next[] */
- s2 = next; /* reset s2 pointer to the start of next[] for next dirname */
-
- /* Try opening the directory in next[]. */
- fd2 = openat(fd1, next, O_NOFOLLOW | O_DIRECTORY | O_RDONLY);
- if(fd2 < 1) {
- if(errno == ENOENT) {
- if(!create_dirs) {
- strerr_dief2x(111, "directory does not exist: ", next);
- }
- /* Create the missing directory. */
- if(mkdirat(fd1, next, 0777) != 0) {
- strerr_diefu2sys(111, "mkdirat(): ", next);
- }
- /* Open the newly created directory. */
- fd2 = openat(fd1, next, O_NOFOLLOW | O_DIRECTORY | O_RDONLY);
- if(fd2 < 1) {
- strerr_diefu2sys(111, "openat(): ", next);
- }
- } else {
- strerr_diefu2sys(111, "openat(): ", next);
- }
- }
-
- /* Close the parent directory and replace reference to it with the newly opened one. */
- close(fd1);
- fd1 = fd2;
- base = s1;
- }
- }
-}
-
-int main (int argc, char const *const *argv)
-{
- if (argc != 3) {
- strerr_dieusage(100, USAGE);
- }
- int old_fd, new_fd;
- const char *old_base, *new_base;
- old_base = opendir_nofollow(argv[1], &old_fd, false);
- if(old_base[0] == 0) {
- strerr_dief2x(100, "malformed path: ", argv[1]);
- }
- new_base = opendir_nofollow(argv[2], &new_fd, true);
- if(new_base[0] == 0) {
- strerr_dief2x(100, "malformed path: ", argv[2]);
- }
- if(linkat(old_fd, old_base, new_fd, new_base, 0) == 0) {
- return 0; /* created hardlink at the correct location */
- }
- if(errno != EEXIST) {
- strerr_diefu1sys(111, "linkat()");
- }
- /* file with such name already exists, so try again with different one and atomically replace */
- char tmp_base[BUFLEN];
- tmp_base[0] = '.';
- tmp_base[1] = 't';
- tmp_base[2] = 'm';
- tmp_base[3] = 'p';
- tmp_base[4] = '.';
- random_name(&tmp_base[5], 58);
- tmp_base[64] = 0;
- if(linkat(old_fd, old_base, new_fd, tmp_base, 0) != 0) {
- strerr_diefu2sys(111, "linkat() to temporary name: ", tmp_base);
- }
- if(renameat(new_fd, tmp_base, new_fd, new_base) != 0) {
- strerr_diefu4sys(111, "renameat() from temporary name: ", tmp_base, " to:", new_base);
- }
- return 0;
-}
-/* vim: sw=2 sts=2 et
-*/
diff --git a/src/socketpair.c b/src/socketpair.c
@@ -1,32 +0,0 @@
-#include <unistd.h>
-
-#include <skalibs/types.h>
-#include <skalibs/strerr.h>
-#include <skalibs/djbunix.h>
-#include <skalibs/exec.h>
-#include <skalibs/socket.h>
-
-#define USAGE "socketpair fd0 fd1 prog..."
-#define PROG "socketpair"
-
-int main (int argc, char const *const *argv)
-{
- int fd0, fd1;
- int sv[2];
- if ((argc < 4)
- || !uint0_scan(argv[1], (unsigned int *)&fd0)
- || !uint0_scan(argv[2], (unsigned int *)&fd1)
- || (fd0 == fd1))
- strerr_dieusage(100, USAGE) ;
-
- if (ipc_pair_b(sv) != 0) {
- strerr_diefu1sys(111, "create socketpair") ;
- }
-
- if (sv[1] == fd0) sv[1] = dup(sv[1]) ;
- if ((sv[1] == -1)
- || (fd_move(fd0, sv[0]) == -1)
- || (fd_move(fd1, sv[1]) == -1))
- strerr_diefu1sys(111, "move fds") ;
- xexec(argv+3) ;
-}
diff --git a/src/socks.h b/src/socks.h
@@ -1,53 +0,0 @@
-
-#define SOCKS_RESERVED 0x00
-#define SOCKS_VERSION_4 0x04
-#define SOCKS_VERSION_5 0x05
-
-typedef unsigned char socks5_auth_mode_t;
-#define SOCKS5_AUTH_METHOD_NOAUTH 0x00
-#define SOCKS5_AUTH_METHOD_USERPASS 0x02
-#define SOCKS5_AUTH_METHOD_NOMETHOD 0xff
-
-#define SOCKS5_AUTH_OK 0x00
-#define SOCKS5_AUTH_VERSION 0x01
-#define SOCKS5_AUTH_FAIL 0xff
-
-typedef unsigned char socks5_command_t;
-#define SOCKS5_CMD_CONNECT 0x01
-#define SOCKS5_BIND 0x02
-#define SOCKS5_UDP_ASSOCIATE 0x03
-
-typedef unsigned char socks5_addr_type_t;
-#define SOCKS5_ADDR_TYPE_IP4 0x01
-#define SOCKS5_ADDR_TYPE_DOMAIN 0x03
-#define SOCKS5_ADDR_TYPE_IP6 0x04
-
-typedef unsigned char socks5_reply_t;
-#define SOCKS5_REPLY_OK 0x00 // succeeded
-#define SOCKS5_REPLY_ERR_GENERAL 0x01 // general SOCKS server failure
-#define SOCKS5_REPLY_ERR_FORBIDDEN 0x02 // connection not allowed by ruleset
-#define SOCKS5_REPLY_ERR_NET_UNREACH 0x03 // Network unreachable
-#define SOCKS5_REPLY_ERR_HOST_UNREACH 0x04 // Host unreachable
-#define SOCKS5_REPLY_ERR_CONN_REFUSED 0x05 // Connection refused
-#define SOCKS5_REPLY_ERR_TTL 0x06 // TTL expired
-#define SOCKS5_REPLY_ERR_CMD 0x07 // Command not supported
-#define SOCKS5_REPLY_ERR_ATYPE 0x08 // Address type not supported
-
-#define SOCKS4_STATUS_OK 0x5a
-#define SOCKS4_STATUS_FAILED 0x5b
-
-typedef struct socks_header_s {
- unsigned char version;
- unsigned char methods;
-} socks_header;
-
-
-typedef struct socks5_request_header_s {
- unsigned char version;
- socks5_command_t cmd;
- unsigned char reserved;
- socks5_addr_type_t atyp;
-} socks5_request_header;
-
-/* vim: sw=4 sts=4 et
-*/
diff --git a/src/spawn-pty.c b/src/spawn-pty.c
@@ -1,139 +0,0 @@
-#include <pty.h>
-#include <fcntl.h>
-#include <signal.h>
-#include <errno.h>
-#include <unistd.h> /* fork(), getpid(), setsid(), tcsetpgrp() */
-#include <stdlib.h> /* grantpt(), unlockpt(), ptsname() */
-
-#include <skalibs/exec.h>
-#include <skalibs/djbunix.h>
-#include <skalibs/strerr.h>
-
-#define PROG "spawn-pty"
-#define USAGE "spawn-pty term_name { pty-prog ... } ptmx-prog ..."
-#define dieusage() strerr_dieusage(100, USAGE)
-
-#define resetsig(S) if(signal(S, SIG_DFL) == SIG_ERR) { \
- strerr_dief1sys(111, "resetting signal handler"); \
- }
-
-void exec_terminal(const char *term_env, const char **ptmx_argv, const char **pty_argv) {
- int ptmx_fd;
- const char *pts_name;
-
- ptmx_fd = posix_openpt(O_RDWR | O_NOCTTY);
- if (ptmx_fd < 0) {
- strerr_dief1sys(111, "posix_openpt()");
- }
- if (grantpt(ptmx_fd) != 0) {
- strerr_dief1sys(111, "grantpt()");
- }
- if (unlockpt(ptmx_fd) != 0) {
- strerr_dief1sys(111, "unlockpt()");
- }
- pts_name = ptsname(ptmx_fd);
- if (pts_name == NULL) {
- strerr_dief1sys(111, "ptsname()");
- }
-
- int fork_pid = fork();
- if(fork_pid < 0) {
- strerr_dief1sys(111, "fork()");
- }
- if(fork_pid == 0) {
- /* child */
- int pty_fd;
-
- resetsig(SIGHUP);
- resetsig(SIGINT);
- resetsig(SIGQUIT);
- resetsig(SIGPIPE);
- resetsig(SIGALRM);
- resetsig(SIGTERM);
- resetsig(SIGCHLD);
- resetsig(SIGCONT);
- resetsig(SIGTSTP);
- resetsig(SIGTTIN);
- resetsig(SIGTTOU);
-
- if(close(ptmx_fd) != 0) {
- strerr_dief1sys(111, "close(ptmx_fd) in child");
- }
-
- if(setsid() < 0) { /* create new session */
- strerr_dief1sys(111, "setsid");
- }
- /* open without O_NOCTTY so controlling terminal gets set */
- pty_fd = open(pts_name, O_RDWR);
- if (pty_fd < 0) {
- strerr_dief1sys(111, "open(pty)");
- }
- if (tcsetpgrp(pty_fd, getpid()) < 0) { /* set controlling terminal */
- strerr_dief1sys(111, "tcsetpgrp");
- }
-
- if(dup2(pty_fd, 0) < 0) {
- strerr_dief1sys(111, "dup2(pty_fd, 0) in child");
- }
- if(dup2(pty_fd, 1) < 0) {
- strerr_dief1sys(111, "dup2(pty_fd, 1) in child");
- }
- if(dup2(pty_fd, 2) < 0) {
- strerr_dief1sys(111, "dup2(pty_fd, 2) in child");
- }
- if(close(pty_fd) != 0) {
- strerr_dief1sys(111, "close(pty_fd) in child");
- }
- char envstr[6 + strlen(term_env)];
- memcpy(envstr, "TERM=", 5);
- strcpy(&envstr[5], term_env);
- xmexec_n(pty_argv, envstr, strlen(envstr), 1);
- } else {
- /* parent */
- if(dup2(ptmx_fd, 0) < 0) {
- strerr_dief1sys(111, "dup2(ptmx_fd, 0) in parent");
- }
- if(close(ptmx_fd) != 0) {
- strerr_dief1sys(111, "close(ptmx_fd) in parent");
- }
- char envstr[9 + strlen(pts_name)];
- memcpy(envstr, "PTS_NAME=", 9);
- strcpy(&envstr[8], term_env);
- xmexec_n(ptmx_argv, envstr, strlen(envstr), 1);
- }
-}
-
-typedef const char * arg_t;
-
-int main(const int argc, const char **argv) {
- if(argc < 2) {
- dieusage();
- }
- arg_t pty_argv[argc];
- const char *term_env = argv[1];
- int n = 2;
- if(term_env[0] == ' ') {
- dieusage();
- }
- if(argv[2][0] != ' ') {
- strerr_dieusage(100, USAGE "\nerror: missing block");
- }
- for(int n = 2; n < argc - 1; n++) {
- switch(argv[n][0]) {
- case 0:
- pty_argv[n - 2] = 0;
- exec_terminal(term_env, &argv[n + 1], pty_argv);
- return 111;
- case ' ':
- pty_argv[n - 2] = &argv[n][1];
- break;
- default:
- strerr_dieusage(100, USAGE "\nerror: improperly terminated block");
- return 100;
- }
- }
- strerr_dieusage(100, USAGE "\nerror: unterminated block");
-}
-
-/* vim: ft=c sts=2 sw=2 et
-*/
diff --git a/src/test-fdsend b/src/test-fdsend
@@ -1,13 +0,0 @@
-#!/bin/execlineb -P
-./socketpair 3 4
-#if { filan }
-background {
- fdclose 4
- redirfd -r 0 ./fdsend.c ./fdsend 3 0 true
-}
-fdclose 3
-# ./fdrecvto 4 0 cat
-./fdrecv 4 FD
-importas -i FD FD
-fdmove 0 $FD
-cat
diff --git a/src/ucspi-socksserver-access.c b/src/ucspi-socksserver-access.c
@@ -1,229 +0,0 @@
-#include <string.h>
-#include <stdint.h>
-#include <unistd.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <assert.h>
-
-#include <skalibs/exec.h>
-#include <skalibs/sgetopt.h>
-#include <skalibs/strerr.h>
-#include <skalibs/cdb.h>
-#include <skalibs/ip46.h>
-
-#include <s6/accessrules.h>
-
-#include "socks.h"
-
-#define PROG "ucspi-socksserver-access"
-#define USAGE "ucspi-socksserve-access [ -i rulesdir | -x rulesfile ] prog..."
-#define dieusage() strerr_dieusage(100, USAGE)
-#define X() strerr_dief1x(101, "internal error")
-
-typedef struct app_options_s {
- unsigned int rulestype;
- char const * rules;
- char const * port;
- char const * addr_type;
- char const * addr;
- unsigned char socks_version;
-} app_options;
-
-const app_options const * options = NULL;
-
-typedef struct check_result_s {
- s6_accessrules_result_t accepted;
- s6_accessrules_params_t params;
-} check_result;
-
-
-char * required_getenv(const char *name){
- char *x = getenv(name);
- if (!x) {
- strerr_dienotset(100, name);
- }
- return x;
-}
-
-void write1(const void *buf, ssize_t n)
-{
- ssize_t nwrite, left = n;
- while (left > 0) {
- if ((nwrite = write(STDOUT_FILENO, buf, left)) < 0) {
- if (errno == EINTR || errno == EAGAIN) {
- continue;
- }
- strerr_diefu1sys(111, "write(stdout)");
- } else {
- assert(left >= nwrite);
- left -= nwrite;
- buf += nwrite;
- }
- }
-}
-
-void socks5_reply_fail(socks5_reply_t status)
-{
- char reply[] = {
- SOCKS_VERSION_5,
- status,
- SOCKS_RESERVED,
- SOCKS5_ADDR_TYPE_DOMAIN,
- 0, /* domain length */
- 0, /* port MSB */
- 0 /* port LSB */
- };
- write1(reply, sizeof(reply));
- close(1);
-}
-
-void socks4_reply_fail()
-{
- const char resp[8] = {0x00, SOCKS4_STATUS_FAILED, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
- write1(resp, sizeof(resp));
- close(1);
-}
-
-void socks_reply_fail_generic(socks5_reply_t status) {
- if (options->socks_version == 5) {
- socks5_reply_fail(status);
- } else {
- socks4_reply_fail();
- }
-}
-
-void check_access_ip(check_result *result) {
- ip46 ip;
- if (!ip46_scan(options->addr, &ip)) {
- strerr_dieinvalid(100, "SOCKS_ADDR") ;
- }
- switch (options->rulestype)
- {
- case 1 :
- result->accepted = s6_accessrules_ip46_fs(&ip, (void *)options->rules, &result->params);
- break;
- case 2 :
- {
- cdb c = CDB_ZERO ;
- if (!cdb_init(&c, options->rules)) {
- strerr_diefu2sys(111, "cdb_init ", options->rules);
- }
- result->accepted = s6_accessrules_ip46_cdb(&ip, &c, &result->params);
- if (result->accepted == S6_ACCESSRULES_ALLOW) {
- cdb_free(&c);
- }
- }
- break;
- default : X();
- }
-}
-
-s6_accessrules_result_t check_access_dns(check_result *result) {
- switch (options->rulestype)
- {
- case 1 :
- result->accepted = s6_accessrules_reversedns_fs(options->addr, (void *)options->rules, &result->params);
- break;
- case 2 :
- {
- cdb c = CDB_ZERO ;
- if (!cdb_init(&c, options->rules)) {
- strerr_diefu2sys(111, "cdb_init ", options->rules);
- }
- result->accepted = s6_accessrules_reversedns_cdb(options->addr, &c, &result->params);
- if (result->accepted == S6_ACCESSRULES_ALLOW) {
- cdb_free(&c);
- }
- }
- break;
- default : X();
- }
-}
-
-
-
-int main (int argc, char const *const *argv)
-{
- char const *rulestypestr[3] = { "no", "fs", "cdb" } ;
- app_options opt;
- opt.rulestype = 0;
- opt.rules = 0;
-
- subgetopt l = SUBGETOPT_ZERO ;
- for (;;)
- {
- int o = subgetopt_r(argc, argv, "i:x:", &l) ;
- if (o == -1) break ;
- switch (o)
- {
- case 'i' : opt.rules = l.arg ; opt.rulestype = 1 ; break ;
- case 'x' : opt.rules = l.arg ; opt.rulestype = 2 ; break ;
- default : dieusage() ;
- }
- }
- argc -= l.ind ; argv += l.ind ;
- if (!argc) dieusage() ;
- if (!*argv[0]) dieusage() ;
-
- char const * env_socks_version = required_getenv("SOCKS_VERSION");
- if(strcmp(env_socks_version, "4") == 0) {
- opt.socks_version = 5;
- } else if (strcmp(env_socks_version, "5") == 0) {
- opt.socks_version = 5;
- } else {
- strerr_dieinvalid(100, "SOCKS_VERSION") ;
- }
-
- opt.port = required_getenv("SOCKS_PORT");
- opt.addr_type = required_getenv("SOCKS_ADDR_TYPE");
- opt.addr = required_getenv("SOCKS_ADDR");
-
- options = &opt;
-
- if(opt.rulestype == 0) {
- xexec(argv);
- }
-
- check_result result = { S6_ACCESSRULES_ALLOW, S6_ACCESSRULES_PARAMS_ZERO };
-
- if(strcmp(opt.addr_type, "dns") == 0) {
- check_access_dns(&result);
- } else if ( strcmp(opt.addr_type, "ip4") == 0 || strcmp(opt.addr_type, "ip6") == 0) {
- check_access_ip(&result);
- } else {
- strerr_dieinvalid(100, "SOCKS_ADDR_TYPE") ;
- }
-
- switch (result.accepted) {
- case S6_ACCESSRULES_ERROR:
- socks_reply_fail_generic(SOCKS5_REPLY_ERR_GENERAL);
- strerr_diefu6sys(111, "check ", rulestypestr[opt.rulestype], " ruleset for ", opt.addr_type, " in ", opt.rules);
- case S6_ACCESSRULES_ALLOW:
- break ;
- case S6_ACCESSRULES_DENY:
- socks_reply_fail_generic(SOCKS5_REPLY_ERR_FORBIDDEN);
- // if (verbosity >= 2) log_deny(getpid(), &remoteip) ;
- return 1;
- case S6_ACCESSRULES_NOTFOUND:
- socks_reply_fail_generic(SOCKS5_REPLY_ERR_FORBIDDEN);
- // if (flagdnslookup) {
- // break;
- // }
- // if (verbosity >= 2) {
- // log_deny(getpid(), opt.addr);
- // }
- return 1 ;
- default: X() ;
- }
-
- if (result.params.exec.len)
- {
- char *specialargv[4] = { "execlineb", "-c", result.params.exec.s, 0 } ;
- xmexec_m((char const *const *)specialargv, result.params.env.s, result.params.env.len) ;
- }
- xexec(argv);
-
-}
-
-/* vim: sw=4 sts=4 et
-*/
diff --git a/src/ucspi-socksserver-connected.c b/src/ucspi-socksserver-connected.c
@@ -1,152 +0,0 @@
-#include <assert.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-
-#include <skalibs/exec.h>
-#include <skalibs/strerr.h>
-#include <skalibs/types.h>
-
-#include "socks.h"
-
-#define PROG "ucspi-socketserver-connect"
-
-#define SOCKS_RESERVED 0x00
-#define SOCKS_VERSION_4 0x04
-#define SOCKS_VERSION_5 0x05
-
-typedef unsigned char socks5_addr_type_t;
-#define SOCKS5_ADDR_TYPE_IP4 0x01
-#define SOCKS5_ADDR_TYPE_DOMAIN 0x03
-#define SOCKS5_ADDR_TYPE_IP6 0x04
-
-typedef unsigned char socks5_reply_t;
-#define SOCKS5_REPLY_OK 0x00 // succeeded
-#define SOCKS5_REPLY_ERR_GENERAL 0x01 // general SOCKS server failure
-#define SOCKS5_REPLY_ERR_FORBIDDEN 0x02 // connection not allowed by ruleset
-#define SOCKS5_REPLY_ERR_NET_UNREACH 0x03 // Network unreachable
-#define SOCKS5_REPLY_ERR_HOST_UNREACH 0x04 // Host unreachable
-#define SOCKS5_REPLY_ERR_CONN_REFUSED 0x05 // Connection refused
-#define SOCKS5_REPLY_ERR_TTL 0x06 // TTL expired
-#define SOCKS5_REPLY_ERR_CMD 0x07 // Command not supported
-#define SOCKS5_REPLY_ERR_ATYPE 0x08 // Address type not supported
-
-void fd_block(int fd)
-{
- int flags = fcntl(fd, F_GETFL);
- if(flags == -1) {
- strerr_dief1sys(111, "fcntl() getfd");
- }
- if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
- strerr_dief1sys(111, "fcntl() setfd");
- }
-}
-
-void write1(const void *buf, ssize_t n)
-{
- ssize_t nwrite, left = n;
- while (left > 0) {
- if ((nwrite = write(STDOUT_FILENO, buf, left)) < 0) {
- if (errno == EINTR || errno == EAGAIN) {
- continue;
- }
- strerr_diefu1sys(111, "write(stdout)");
- } else {
- assert(left >= nwrite);
- left -= nwrite;
- buf += nwrite;
- }
- }
-}
-
-void socks5_reply_ok(socks5_addr_type_t addr_type, void *addr, in_port_t port)
-{
- size_t size;
- switch(addr_type) {
- case SOCKS5_ADDR_TYPE_IP4:
- size = 4;
- break;
- case SOCKS5_ADDR_TYPE_IP6:
- size = 16;
- break;
- case SOCKS5_ADDR_TYPE_DOMAIN:
- size = strlen(addr);
- if(size > 0xff) {
- strerr_dieinvalid(110, "local hostname too long") ;
- }
- break;
- }
-
- char reply[] = {
- SOCKS_VERSION_5,
- SOCKS5_REPLY_OK,
- SOCKS_RESERVED,
- addr_type,
- };
- write1(reply, sizeof(reply));
-
- if (addr_type == SOCKS5_ADDR_TYPE_DOMAIN) {
- /* prefix domain by length */
- unsigned char domain_len = size;
- write1(&domain_len, 1);
- }
- write1(addr, size);
-
- /* should be already in network byte order (from sin_port) */
- write1(&port, sizeof(port));
-}
-
-void socks4_send_reply(int status)
-{
- char resp[8] = {0x00, (char)status, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
- write1(resp, sizeof(resp));
-}
-
-int main (int argc, char const *const *argv)
-{
- char const *env_socks_version = getenv("SOCKS_VERSION");
- if (!env_socks_version) {
- strerr_dienotset(100, "SOCKS_VERSION");
- }
-
- /* fd_block(STDIN_FILENO); */
- fd_block(STDOUT_FILENO);
-
- if (strcmp(env_socks_version, "5") == 0) {
-
- struct sockaddr_storage local_addr;
- socklen_t addrlen = sizeof(local_addr);
- if(getsockname(6, (struct sockaddr *)&local_addr, &addrlen) != 0) {
- strerr_diefu1sys(111, "getsockname(6, ...)");
- }
- assert(addrlen <= sizeof(local_addr));
- switch(local_addr.ss_family) {
- case AF_INET:
- struct sockaddr_in *in_addr = (struct sockaddr_in *)&local_addr;
- socks5_reply_ok(SOCKS5_ADDR_TYPE_IP4, &in_addr->sin_addr, in_addr->sin_port);
- break;
- case AF_INET6:
- struct sockaddr_in6 *in6_addr = (struct sockaddr_in6 *)&local_addr;
- socks5_reply_ok(SOCKS5_ADDR_TYPE_IP6, &in6_addr->sin6_addr, in6_addr->sin6_port);
- break;
- default:
- socks5_reply_ok(SOCKS5_ADDR_TYPE_DOMAIN, "localhost", 0);
- break;
- }
-
- } else if (strcmp(env_socks_version, "4") == 0) {
- socks4_send_reply(SOCKS4_STATUS_OK);
-
- } else {
- strerr_dieinvalid(100, "SOCKS_VERSION") ;
-
- }
- xexec(argv+1);
- return 110;
-}
-
-/* vim: sw=4 sts=4 et
-*/
diff --git a/src/ucspi-socksserver.c b/src/ucspi-socksserver.c
@@ -1,358 +0,0 @@
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <stdbool.h>
-#include <stdio.h> /* for log_message */
-#include <stdarg.h> /* for log_message */
-#include <assert.h>
-#include <arpa/inet.h>
-
-#include <skalibs/exec.h>
-#include <skalibs/strerr.h>
-
-#include "socks.h"
-
-#define PROG "ucspi-socketserver"
-
-#define MAX_DOMAIN_LENGTH 256
-
-void fd_block(int fd);
-void read0(void *buf, ssize_t n);
-void write1(const void *buf, ssize_t n);
-void socks_read_header(socks_header *hdr);
-unsigned short socks_read_port(void);
-void interact(void);
-void handle_socks5(char methods);
-void socks5_auth(int methods_count, socks5_auth_mode_t supported_auth_method);
-void socks5_auth_userpass(void);
-void socks5_auth_noauth(void);
-void socks5_auth_notsupported(void);
-void socks5_command(socks5_request_header *rhdr);
-void handle_socks4(void);
-void do_connect(unsigned char socks_version, socks5_addr_type_t addr_type, char *buf, unsigned short int port);
-
-char const *const *new_argv = NULL;
-
-int main (int argc, char const *const *argv)
-{
- fd_block(STDIN_FILENO);
- fd_block(STDOUT_FILENO);
- new_argv = argv+1;
- interact();
-}
-
-// TODO: get rid of stdio dependency
-void log_message(const char *message, ...)
-{
- int ret;
- va_list args;
- va_start(args, message);
- ret = vdprintf(STDERR_FILENO, message, args);
- va_end(args);
- if (ret < 0) {
- strerr_dief1sys(111, "log_message() failed");
- }
- write(2, "\n", 1);
-}
-
-void fd_block(int fd)
-{
- int flags = fcntl(fd, F_GETFL);
- if(flags == -1) {
- strerr_dief1sys(111, "fcntl() getfd");
- }
- if(fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
- strerr_dief1sys(111, "fcntl() setfd");
- }
-}
-
-void read0(void *buf, ssize_t n)
-{
- ssize_t nread, left = n;
- while (left > 0) {
- if ((nread = read(STDIN_FILENO, buf, left)) < 0) {
- if (errno == EINTR || errno == EAGAIN) {
- continue;
- }
- strerr_diefu1sys(111, "read(stdin)");
- } else {
- if (nread == 0) {
- strerr_diefu1x(111, "read(stdin): end of file");
- } else {
- assert(left >= nread);
- left -= nread;
- buf += nread;
- }
- }
- }
-}
-
-void write1(const void *buf, ssize_t n)
-{
- ssize_t nwrite, left = n;
- while (left > 0) {
- if ((nwrite = write(STDOUT_FILENO, buf, left)) < 0) {
- if (errno == EINTR || errno == EAGAIN) {
- continue;
- }
- strerr_diefu1sys(111, "write(stdout)");
- } else {
- assert(left >= nwrite);
- left -= nwrite;
- buf += nwrite;
- }
- }
-}
-
-void read0_cstring(char *buf, size_t n)
-{
- size_t left = n;
- while (left > 0) {
- read0(buf, 1);
- if(*buf == 0) {
- return;
- }
- left--;
- buf++;
- }
- strerr_diefu1x(0, "read0_cstring: exceeded maximum buffer size");
-}
-
-/* start here */
-void interact(void)
-{
- socks_header hdr;
- socks_read_header(&hdr);
-
- switch (hdr.version) {
- case SOCKS_VERSION_5:
- handle_socks5(hdr.methods);
- break;
- case SOCKS_VERSION_4:
- if (hdr.methods == 1) {
- handle_socks4();
- } else {
- strerr_dief1x(0, "Unsupported SOCKS4 mode");
- }
- break;
- }
-}
-
-void socks_read_header(socks_header *hdr)
-{
- read0(hdr, sizeof(socks_header));
- // log_message("Received header: 0x%hhX 0x%hhX", hdr->version, hdr->method);
- if (hdr->version != SOCKS_VERSION_5 && hdr->version != SOCKS_VERSION_4) {
- strerr_dief1x(0, "Incompatible version!");
- }
-}
-
-unsigned short socks_read_port(void) {
- unsigned short port;
- read0(&port, sizeof(port));
- return ntohs(port);
-}
-
-void handle_socks5(char methods)
-{
- socks5_auth(methods, SOCKS5_AUTH_METHOD_NOAUTH); /* TODO: authentication support */
- socks5_request_header rhdr;
- socks5_command(&rhdr);
- unsigned short port;
-
- switch (rhdr.atyp) {
- case SOCKS5_ADDR_TYPE_IP4:
- char ip4[4];
- read0(ip4, sizeof(ip4));
- port = socks_read_port();
-
- do_connect(5, SOCKS5_ADDR_TYPE_IP4, ip4, port);
- break;
- case SOCKS5_ADDR_TYPE_IP6:
- char ip6[16];
- read0(ip6, sizeof(ip6));
- port = socks_read_port();
-
- do_connect(5, SOCKS5_ADDR_TYPE_IP6, ip6, port);
- break;
- case SOCKS5_ADDR_TYPE_DOMAIN:
- unsigned char size;
- char domain[MAX_DOMAIN_LENGTH];
- read0(&size, sizeof(size));
- assert(size < MAX_DOMAIN_LENGTH);
- read0(domain, size);
- domain[size] = 0;
- port = socks_read_port();
-
- do_connect(5, SOCKS5_ADDR_TYPE_DOMAIN, domain, port);
- break;
- default:
- strerr_dief1x(1, "Unsupported SOCKS5 command");
- break;
- }
-}
-
-void socks5_auth(int methods_count, socks5_auth_mode_t supported_auth_method)
-{
- bool supported = false;
- for (int i = 0; i < methods_count; i++) {
- char type;
- read0(&type, 1);
- // log_message("Method AUTH 0x%hhX", type);
- if (type == supported_auth_method) {
- supported = true;
- }
- }
- if (!supported) {
- socks5_auth_notsupported();
- strerr_dief1x(1, "No supported authentication method");
- }
- switch (supported_auth_method) {
- case SOCKS5_AUTH_METHOD_NOAUTH:
- socks5_auth_noauth();
- break;
- case SOCKS5_AUTH_METHOD_USERPASS:
- socks5_auth_userpass();
- break;
- default:
- strerr_dief1x(110, "Internal error: unhandled authentication method");
- break;
- }
-}
-
-void socks5_auth_userpass(void)
-{
- strerr_dief1x(110, "TODO: userpass auth");
-}
-
-void socks5_auth_noauth(void)
-{
- const char answer[2] = { SOCKS_VERSION_5, SOCKS5_AUTH_METHOD_NOAUTH };
- write1(answer, sizeof(answer));
-}
-
-void socks5_auth_notsupported(void)
-{
- const char answer[2] = { SOCKS_VERSION_5, SOCKS5_AUTH_METHOD_NOMETHOD };
- write1(answer, sizeof(answer));
-}
-
-void socks5_command(socks5_request_header *rhdr)
-{
- read0(rhdr, sizeof(socks5_request_header));
- // log_message("Command %02hhX %02hhX %02hhX %02hhX",
- // rhdr->version, rhdr->cmd, rhdr->reserved, rhdr->atyp);
- assert(rhdr->version == SOCKS_VERSION_5);
- assert(rhdr->cmd == SOCKS5_CMD_CONNECT);
-}
-
-
-void handle_socks4(void)
-{
- char ident[255];
- unsigned short int port;
- char ip[4];
-
- port = socks_read_port();
- read0(&ip, sizeof(ip));
- read0_cstring(ident, sizeof(ident));
-
- if (ip[0] == 0 && ip[1] == 0 && ip[2] == 0 && ip[3] != 0) {
- char domain[MAX_DOMAIN_LENGTH];
- read0_cstring(domain, sizeof(domain));
- // log_message("Socks4A: ident:%s; domain:%s;", ident, domain);
- do_connect(4, SOCKS5_ADDR_TYPE_DOMAIN, domain, port);
- } else {
- // log_message("Socks4: connect by ip & port");
- do_connect(4, SOCKS5_ADDR_TYPE_IP4, ip, port);
- }
-
-}
-
-void xenv(char const *s, char const *t) {
- if (!env_mexec(s, t)) {
- strerr_diefu1sys(111, "env_mexec");
- }
-}
-
-void socks_env_ip4(const char *ip) {
- char v4_address[16];
- snprintf(v4_address, sizeof(v4_address), "%hhu.%hhu.%hhu.%hhu",
- ip[0], ip[1], ip[2], ip[3]);
- xenv("SOCKS_ADDR", v4_address);
- xenv("SOCKS_ADDR_TYPE", "ip4");
-}
-
-void socks_env_ip6(const char *ip) {
- char v6_address[41];
- snprintf(v6_address, sizeof(v6_address),
- "%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx",
- ip[0x0], ip[0x1], ip[0x2], ip[0x3], ip[0x4], ip[0x5], ip[0x6], ip[0x7],
- ip[0x8], ip[0x9], ip[0xa], ip[0xb], ip[0xc], ip[0xd], ip[0xe], ip[0xf]);
- xenv("SOCKS_ADDR", v6_address);
- xenv("SOCKS_ADDR_TYPE", "ip6");
-}
-
-void socks_env_dns(const char *domain) {
- xenv("SOCKS_ADDR", domain);
- xenv("SOCKS_ADDR_TYPE", "dns");
-}
-
-void log_connect(unsigned char socks_version, socks5_addr_type_t addr_type, char *buf, unsigned short int port) {
- char address[43];
- switch (addr_type) {
- case SOCKS5_ADDR_TYPE_IP4:
- snprintf(address, sizeof(address), "%hhu.%hhu.%hhu.%hhu",
- buf[0], buf[1], buf[2], buf[3]);
- break;
- case SOCKS5_ADDR_TYPE_IP6:
- snprintf(address, sizeof(address),
- "[%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx:%02hhx%02hhx]",
- buf[0x0], buf[0x1], buf[0x2], buf[0x3], buf[0x4], buf[0x5], buf[0x6], buf[0x7],
- buf[0x8], buf[0x9], buf[0xa], buf[0xb], buf[0xc], buf[0xd], buf[0xe], buf[0xf]);
- break;
- case SOCKS5_ADDR_TYPE_DOMAIN:
- break;
- default:
- strerr_dief1x(110, "Internal error: unhandled address type");
- }
- log_message("SOCKS%hhd %s:%hd", socks_version, addr_type == SOCKS5_ADDR_TYPE_DOMAIN ? buf : address, port);
-}
-
-void do_connect(unsigned char socks_version, socks5_addr_type_t addr_type, char *buf, unsigned short int port) {
- switch(socks_version) {
- case 4:
- xenv("SOCKS_VERSION", "4");
- break;
- case 5:
- xenv("SOCKS_VERSION", "5");
- break;
- default:
- strerr_dief1x(110, "Internal error: unhandled protocol version");
- break;
- }
-
- char port_string[6];
- snprintf(port_string, sizeof(port_string), "%d", port);
- xenv("SOCKS_PORT", port_string);
-
- switch (addr_type) {
- case SOCKS5_ADDR_TYPE_IP4:
- socks_env_ip4(buf);
- break;
- case SOCKS5_ADDR_TYPE_IP6:
- socks_env_ip6(buf);
- break;
- case SOCKS5_ADDR_TYPE_DOMAIN:
- socks_env_dns(buf);
- break;
- default:
- strerr_dief1x(110, "Internal error: unhandled address type");
- }
-
- log_connect(socks_version, addr_type, buf, port);
- xmexec(new_argv);
-}
-
-/* vim: sw=4 sts=4 et
-*/