Skip to content

Instantly share code, notes, and snippets.

@ppkarwasz
Created February 16, 2020 21:05
Show Gist options
  • Save ppkarwasz/b5fd2c2686bb3f66e6f8681b2ff047c4 to your computer and use it in GitHub Desktop.
Save ppkarwasz/b5fd2c2686bb3f66e6f8681b2ff047c4 to your computer and use it in GitHub Desktop.
Small remote command execution
#include <stdio.h>
#include <stdlib.h>
#include "libwrapper.h"
int main(int argc, char *const argv[]) {
int ctrl = prepare_socket(true);
if (argc < 2) {
fprintf(stderr, "Usage: %s command\n", argv[0]);
exit(1);
}
if (write_args(ctrl, argv + 1)) {
printf("Arguments sent.\n");
}
}
#include "libwrapper.h"
#include <stdio.h>
#include <signal.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/wait.h>
#define BUF_LEN 1024
static const char *const sock_path = "socket";
static char buf[1024];
void spawn_new(pid_t* child, char *const argv[]) {
int wstatus;
int new_pid;
if (argv[0] == NULL) {
return;
}
/* Kill old child */
if (*child > 0) {
kill(*child, SIGTERM);
waitpid(*child, &wstatus, 0);
}
/* Spawn new child */
if ((new_pid = fork()) == -1) {
fprintf(stderr, "Unable to fork.\n");
} else if (new_pid > 0) {
*child = new_pid;
} else if (execv(argv[0], argv) == -1) {
fprintf(stderr, "Unable to run '%s'.\n", argv[0]);
}
}
int prepare_socket(bool is_client) {
int ctrl = socket(AF_UNIX, SOCK_STREAM, 0);
if (ctrl == -1) {
fprintf(stderr, "Unable to create UNIX socket.\n");
exit(1);
}
struct sockaddr_un addr;
memset(&addr, 0, sizeof(addr));
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, sock_path, sizeof(addr.sun_path) - 1);
if (is_client) {
if (connect(ctrl, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
fprintf(stderr, "Unable to connect to UNIX socket.\n");
exit(1);
}
} else {
if (bind(ctrl, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
fprintf(stderr, "Unable to bind UNIX socket.\n");
exit(1);
}
if (listen(ctrl, 10) == -1) {
fprintf(stderr, "Unable to listen on UNIX socket.\n");
exit(1);
}
printf("Listening.\n");
}
return ctrl;
}
char ** read_args(int fd) {
int bytes_read = read(fd, buf, sizeof(buf));
if (bytes_read == -1 || bytes_read > BUF_LEN) {
fprintf(stderr, "Unable to read from socket.\n");
return NULL;
}
int len = *(int*)buf;
char** result = (char**) malloc((len + 1) * sizeof(char*));
result[len] = NULL;
char* src = buf + sizeof(int);
for (int i = 0; i < len; i++) {
int param_len = strnlen(src, buf + BUF_LEN - src);
result[i] = strndup(src, buf + BUF_LEN - src);
src += param_len + 1;
}
return result;
}
static int arrlen(char *const array[]) {
int i = 0;
char *const *ptr = array;
while (*ptr != NULL) {
i++;
ptr++;
}
return i;
}
bool write_args(int fd, char *const argv[]) {
int len = arrlen(argv);
((int*)buf)[0] = len;
char* dst = buf + sizeof(int);
char *const *param = argv;
while (dst < buf + BUF_LEN && *param != NULL) {
int param_len = strlen(*param);
strncpy(dst, *param, buf + BUF_LEN - dst);
dst += param_len + 1;
param++;
}
if (dst >= buf + BUF_LEN) {
fprintf(stderr, "Buffer full.\n");
return false;
}
if (write(fd, buf, dst - buf) == -1) {
fprintf(stderr, "Write failed.\n");
return false;
}
return true;
}
#ifndef LIBWRAPPER_H
#define LIBWRAPPER_H
#include <stdbool.h>
#include <sys/types.h>
void spawn_new(pid_t* child, char *const argv[]);
int prepare_socket(bool is_client);
char** read_args(int fd);
bool write_args(int fd, char *const argv[]);
#endif
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/un.h>
#include "libwrapper.h"
int main(int argc, char *const argv[]) {
int ctrl = prepare_socket(false);
pid_t child = -1;
struct sockaddr_un remote;
socklen_t remote_len;
int client_fd;
while ((client_fd = accept(ctrl, (struct sockaddr *)&remote, &remote_len)) != -1) {
char** new_args = read_args(client_fd);
if (new_args != NULL) {
spawn_new(&child, new_args);
}
close(client_fd);
}
perror(NULL);
close(ctrl);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment