aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorToni Uhlig <matzeton@googlemail.com>2018-05-06 14:40:52 +0200
committerToni Uhlig <matzeton@googlemail.com>2018-05-06 14:40:52 +0200
commit9653d78388348ebd47b820a0d9d95bbd885973a0 (patch)
treedf3d51baa08075f44b6c18596730ac21714e5139
parent4f66937b2bfadfa54aa099ea9bbb9f2f0dc2416f (diff)
POTD skeleton #42.
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
-rw-r--r--src/Makefile.am2
-rw-r--r--src/forward.c7
-rw-r--r--src/forward.h4
-rw-r--r--src/jail.c85
-rw-r--r--src/pterm.c186
-rw-r--r--src/pterm.h25
-rw-r--r--src/server.c2
-rw-r--r--src/socket.c11
-rw-r--r--src/utils.c16
-rw-r--r--src/utils.h2
10 files changed, 86 insertions, 254 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 76a8c38..f6c7a20 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -2,4 +2,4 @@ AM_CFLAGS = -pedantic -Wall -std=gnu99 -fstrict-aliasing -D_GNU_SOURCE=1 $(libss
AM_LDFLAGS = $(libssh_LIBS)
sbin_PROGRAMS = potd
-potd_SOURCES = utils.c log.c log_colored.c socket.c pterm.c jail.c forward.c server.c server_ssh.c main.c
+potd_SOURCES = utils.c log.c log_colored.c socket.c jail.c forward.c server.c server_ssh.c main.c
diff --git a/src/forward.c b/src/forward.c
index 5fc0857..86f4fb6 100644
--- a/src/forward.c
+++ b/src/forward.c
@@ -67,10 +67,15 @@ int fwd_validate_ctx(const forward_ctx *ctx)
return 0;
}
-int fwd_connect(forward_ctx *ctx, psocket *fwd_client)
+int fwd_connect_sock(forward_ctx *ctx, psocket *fwd_client)
{
assert(ctx);
socket_clone(&ctx->sock, fwd_client);
return socket_reconnect_in(fwd_client);
}
+
+int fwd_listen_fd(forward_ctx *ctx, int fwd_fd)
+{
+ return 0;
+}
diff --git a/src/forward.h b/src/forward.h
index 386dc94..60c7500 100644
--- a/src/forward.h
+++ b/src/forward.h
@@ -30,6 +30,8 @@ int fwd_setup(forward_ctx *ctx, const char *host, const char *port);
int fwd_validate_ctx(const forward_ctx *ctx);
-int fwd_connect(forward_ctx *ctx, psocket *fwd_client);
+int fwd_connect_sock(forward_ctx *ctx, psocket *fwd_client);
+
+int fwd_listen_fd(forward_ctx *ctx, int fwd_fd);
#endif
diff --git a/src/jail.c b/src/jail.c
index e879c2c..b45f7c8 100644
--- a/src/jail.c
+++ b/src/jail.c
@@ -12,7 +12,6 @@
#include "jail.h"
#include "socket.h"
#include "server.h"
-#include "pterm.h"
#include "utils.h"
#include "log.h"
@@ -26,8 +25,9 @@ static int jail_mainloop_epoll(int epoll_fd, jail_ctx *ctx[], size_t siz)
__attribute__((noreturn));
static int jail_accept_client(jail_ctx *ctx[],
size_t siz, struct epoll_event *event);
-static int jail_childfn(void *arg)
+static int jail_childfn(jail_prisoner_process *ctx)
__attribute__((noreturn));
+static int jail_socket_tty_epoll(jail_prisoner_process *ctx, int tty_fd);
void jail_init_ctx(jail_ctx **ctx, size_t stacksize)
@@ -259,85 +259,78 @@ error:
return rc;
}
-static int jail_childfn(void *arg)
+static int jail_childfn(jail_prisoner_process *ctx)
{
- jail_prisoner_process *args;
const char *path_dev = "/dev";
const char *path_devpts = "/dev/pts";
const char *path_proc = "/proc";
const char *path_shell = "/bin/sh";
- char tty_name[TTYSZ+sizeof(long)];
- int s, pty_fd, tty_fd;
+ int s, master_fd;
int unshare_flags = CLONE_NEWUTS|CLONE_NEWPID|CLONE_NEWIPC|
CLONE_NEWNS|CLONE_NEWNET;
pid_t self_pid, child_pid;
- assert(arg);
- args = (jail_prisoner_process *) arg;
+ assert(ctx);
self_pid = getpid();
if (prctl(PR_SET_PDEATHSIG, SIGKILL) != 0)
FATAL("Jail child prctl for pid %d", self_pid);
- if (!args->newroot)
+ if (!ctx->newroot)
FATAL("New root set for pid %d", self_pid);
D2("Unshare prisoner %d", self_pid);
if (unshare(unshare_flags))
FATAL("Unshare prisoner %d", self_pid);
- D2("Safe change root to: '%s'", args->newroot);
- if (safe_chroot(args->newroot))
- FATAL("Safe jail chroot to '%s' failed", args->newroot);
+ D2("Safe change root to: '%s'", ctx->newroot);
+ if (safe_chroot(ctx->newroot))
+ FATAL("Safe jail chroot to '%s' failed", ctx->newroot);
- D2("Mounting rootfs to '%s'", args->newroot);
+ D2("Mounting rootfs to '%s'", ctx->newroot);
mount_root();
- D2("Mounting devtmpfs to '%s%s'", args->newroot, path_dev);
+ D2("Mounting devtmpfs to '%s%s'", ctx->newroot, path_dev);
s = mkdir(path_dev, S_IRUSR|S_IWUSR|S_IXUSR|
S_IRGRP|S_IXGRP|
S_IROTH|S_IXOTH);
if (s && errno != EEXIST)
FATAL("Create directory '%s'", path_dev);
if (!dir_is_mountpoint(path_dev) && mount_dev(path_dev))
- FATAL("Mount devtmpfs to '%s%s'", args->newroot, path_dev);
+ FATAL("Mount devtmpfs to '%s%s'", ctx->newroot, path_dev);
- D2("Mounting devpts to '%s%s'", args->newroot, path_devpts);
+ D2("Mounting devpts to '%s%s'", ctx->newroot, path_devpts);
s = mkdir(path_devpts, S_IRUSR|S_IWUSR|S_IXUSR|
S_IRGRP|S_IXGRP|
S_IROTH|S_IXOTH);
if (s && errno != EEXIST)
FATAL("Create directory '%s'", path_devpts);
if (!dir_is_mountpoint(path_devpts) && mount_pts(path_devpts))
- FATAL("Mount devpts to '%s%s'", args->newroot, path_devpts);
+ FATAL("Mount devpts to '%s%s'", ctx->newroot, path_devpts);
- D2("Mounting proc to '%s%s'", args->newroot, path_proc);
+ D2("Mounting proc to '%s%s'", ctx->newroot, path_proc);
s = mkdir(path_proc, S_IRUSR|S_IWUSR|S_IXUSR|
S_IRGRP|S_IXGRP|
S_IROTH|S_IXOTH);
if (s && errno != EEXIST)
FATAL("Create directory '%s'", path_proc);
if (!dir_is_mountpoint(path_proc) && mount_proc(path_proc))
- FATAL("Mount devpts to '%s%s'", args->newroot, path_proc)
+ FATAL("Mount devpts to '%s%s'", ctx->newroot, path_proc)
- D2("Creating device files in '%s%s'", args->newroot, path_dev);
+ D2("Creating device files in '%s%s'", ctx->newroot, path_dev);
if (create_device_files(path_dev)) {
E2("Device file creation failed for rootfs '%s%s'",
- args->newroot, path_dev);
+ ctx->newroot, path_dev);
exit(EXIT_FAILURE);
}
- if (pty_allocate(&pty_fd, &tty_fd, tty_name, TTYSZ))
- FATAL("%s", "TTY allocation");
-
- D2("Forking a new process for the slave tty from "
- "parent pty with pid %d",
- self_pid);
- child_pid = fork();
+ D2("Forking a new pty process for "
+ "parent %d", self_pid);
+ child_pid = forkpty(&master_fd, NULL, NULL, NULL);
switch (child_pid) {
case -1:
FATAL("Forking a new process for the slave tty from "
- "parent pty with pid %d",
- self_pid);
+ "parent pty with pid %d",
+ self_pid);
break;
case 0:
D2("Executing '%s'", path_shell);
@@ -345,8 +338,40 @@ static int jail_childfn(void *arg)
FATAL("Execute a shell for pid %d", self_pid);
break;
default:
+ if (set_fd_nonblock(master_fd))
+ FATAL("Pty master fd nonblock for prisoner pid %d",
+ child_pid);
+ N("Socket to tty I/O loop for prisoner pid %d",
+ child_pid);
+ if (jail_socket_tty_epoll(ctx, master_fd))
+ FATAL("Socket to tty I/O loop for prisoner pid %d",
+ child_pid);
waitpid(child_pid, &s, 0);
}
exit(EXIT_FAILURE);
}
+
+static int jail_socket_tty_epoll(jail_prisoner_process *ctx, int tty_fd)
+{
+ int s, fd = epoll_create1(0);
+ struct epoll_event event = {0,{0}};
+
+ assert(ctx);
+ if (fd < 0)
+ return -1;
+
+ event.events = EPOLLIN | EPOLLET;
+ event.data.fd = ctx->client_psock.fd;
+ s = epoll_ctl(fd, EPOLL_CTL_ADD, ctx->client_psock.fd, &event);
+ if (s)
+ FATAL("Jail Socket Epoll for client %s:%s",
+ ctx->host_buf, ctx->service_buf);
+ event.data.fd = tty_fd;
+ s = epoll_ctl(fd, EPOLL_CTL_ADD, tty_fd, &event);
+ if (s)
+ FATAL("Jail TTY Epoll for client %s:%s",
+ ctx->host_buf, ctx->service_buf);
+
+ return 0;
+}
diff --git a/src/pterm.c b/src/pterm.c
deleted file mode 100644
index 050e9b2..0000000
--- a/src/pterm.c
+++ /dev/null
@@ -1,186 +0,0 @@
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/ioctl.h>
-#include <sys/stat.h>
-#include <signal.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <grp.h>
-#include <pwd.h>
-#include <stdarg.h>
-#include <string.h>
-#include <termios.h>
-#include <pty.h>
-
-#include "pterm.h"
-#include "log.h"
-
-#ifndef _PATH_TTY
-#define _PATH_TTY "/dev/tty"
-#endif
-#ifndef O_NOCTTY
-#define O_NOCTTY 0
-#endif
-
-
-int
-pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen)
-{
- /* openpty(3) exists in OSF/1 and some other os'es */
- char *name;
- int i;
-
- i = openpty(ptyfd, ttyfd, NULL, NULL, NULL);
- if (i < 0) {
- E_STRERR("%s", "Allocate pseudo terminal");
- return 1;
- }
- name = ttyname(*ttyfd);
- if (!name) {
- E_STRERR("%s", "Invalid ttyname for pseudo terminal");
- abort();
- }
-
- strncpy(namebuf, name, namebuflen); /* possible truncation */
- return 0;
-}
-
-void
-pty_release(const char *tty)
-{
- if (chown(tty, (uid_t) 0, (gid_t) 0) < 0) {
- E_STRERR("Change tty owner for '%s'", tty);
- }
- if (chmod(tty, (mode_t) 0666) < 0) {
- E_STRERR("Change tty mode for '%s'", tty);
- }
-}
-
-void
-pty_make_controlling_tty(int *ttyfd, const char *tty)
-{
- int fd;
-
- /* First disconnect from the old controlling tty. */
- fd = open(_PATH_TTY, O_RDWR | O_NOCTTY);
- if (fd >= 0) {
- (void) ioctl(fd, TIOCNOTTY, NULL);
- close(fd);
- }
- if (setsid() < 0)
- E_STRERR("%s", "New session");
-
- /*
- * Verify that we are successfully disconnected from the controlling
- * tty.
- */
- fd = open(_PATH_TTY, O_RDWR | O_NOCTTY);
- if (fd >= 0) {
- E2("%s", "Failed to disconnect from controlling tty.");
- close(fd);
- }
- /* Make it our controlling tty. */
- D("%s", "Setting controlling tty using TIOCSCTTY.");
- if (ioctl(*ttyfd, TIOCSCTTY, NULL) < 0)
- E_STRERR("%s", "ioctl(TIOCSCTTY)");
- if (setpgrp() < 0)
- E_STRERR("%s", "Set new process group");
- fd = open(tty, O_RDWR);
- if (fd < 0)
- E_STRERR("Open tty '%s'", tty);
- else
- close(fd);
-
- /* Verify that we now have a controlling tty. */
- fd = open(_PATH_TTY, O_WRONLY);
- if (fd < 0)
- E_STRERR("Could not set controlling tty - Open '%s'", tty);
- else
- close(fd);
-}
-
-/* Changes the window size associated with the pty. */
-
-void
-pty_change_window_size(int ptyfd, unsigned int row,
- unsigned int col,
- unsigned int xpixel,
- unsigned int ypixel)
-{
- struct winsize w;
-
- /* may truncate unsigned int -> unsigned short */
- w.ws_row = row;
- w.ws_col = col;
- w.ws_xpixel = xpixel;
- w.ws_ypixel = ypixel;
- (void) ioctl(ptyfd, TIOCSWINSZ, &w);
-}
-
-void
-pty_setowner(struct passwd *pw, const char *tty)
-{
- struct group *grp;
- gid_t gid;
- mode_t mode;
- struct stat st;
-
- /* Determine the group to make the owner of the tty. */
- grp = getgrnam("tty");
- gid = (grp != NULL) ? grp->gr_gid : pw->pw_gid;
- mode = (grp != NULL) ? 0620 : 0600;
-
- /*
- * Change owner and mode of the tty as required.
- * Warn but continue if filesystem is read-only and the uids match/
- * tty is owned by root.
- */
- if (stat(tty, &st))
- FATAL("Change owner of %s", tty);
-
-#ifdef WITH_SELINUX
- ssh_selinux_setup_pty(pw->pw_name, tty);
-#endif
-
- if (st.st_uid != pw->pw_uid || st.st_gid != gid) {
- if (chown(tty, pw->pw_uid, gid) < 0) {
- if (errno == EROFS &&
- (st.st_uid == pw->pw_uid || st.st_uid == 0))
- {
- D("Change owner of '%s' to %u:%u",
- tty, (unsigned) pw->pw_uid,
- (unsigned) gid);
- } else {
- FATAL("Change owner of '%s' to %u:%u",
- tty, (unsigned) pw->pw_uid,
- (unsigned) gid);
- }
- }
- }
-
- if ((st.st_mode & (S_IRWXU|S_IRWXG|S_IRWXO)) != mode) {
- if (chmod(tty, mode) < 0) {
- if (errno == EROFS &&
- (st.st_mode & (S_IRGRP | S_IROTH)) == 0)
- {
- D("Change mode of '%s' to 0%o",
- tty, (unsigned) mode);
- } else {
- FATAL("Change mode of '%s' to 0%o",
- tty, (unsigned) mode);
- }
- }
- }
-}
-
-/* Disconnect from the controlling tty. */
-void
-disconnect_controlling_tty(void)
-{
- int fd;
-
- if ((fd = open(_PATH_TTY, O_RDWR | O_NOCTTY)) >= 0) {
- (void) ioctl(fd, TIOCNOTTY, NULL);
- close(fd);
- }
-}
diff --git a/src/pterm.h b/src/pterm.h
deleted file mode 100644
index 87ce8bc..0000000
--- a/src/pterm.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef POTD_PTY_H
-#define POTD_PTY_H 1
-
-#include <stdlib.h>
-#include <pwd.h>
-
-#define TTYSZ 64
-
-
-int pty_allocate(int *ptyfd, int *ttyfd, char *namebuf, size_t namebuflen);
-
-void pty_release(const char *tty);
-
-void pty_make_controlling_tty(int *ttyfd, const char *tty);
-
-void pty_change_window_size(int ptyfd, unsigned int row,
- unsigned int col,
- unsigned int xpixel,
- unsigned int ypixel);
-
-void pty_setowner(struct passwd *pw, const char *tty);
-
-void disconnect_controlling_tty(void);
-
-#endif
diff --git a/src/server.c b/src/server.c
index 9bf41f7..0edfe70 100644
--- a/src/server.c
+++ b/src/server.c
@@ -271,7 +271,7 @@ client_mainloop_epoll(void *arg)
goto finish;
}
- if (fwd_connect(args->server_ctx->fwd_ctx, &fwd)) {
+ if (fwd_connect_sock(args->server_ctx->fwd_ctx, &fwd)) {
E_STRERR("Forward connection to %s:%s server fd %d",
args->server_ctx->fwd_ctx->host_buf,
args->server_ctx->fwd_ctx->service_buf,
diff --git a/src/socket.c b/src/socket.c
index 7fe5cbc..e9b8584 100644
--- a/src/socket.c
+++ b/src/socket.c
@@ -8,19 +8,12 @@
#include <assert.h>
#include "socket.h"
+#include "utils.h"
int socket_nonblock(const psocket *psock)
{
- int flags;
-
- flags = fcntl(psock->fd, F_GETFL, 0);
- if (flags < 0)
- return 1;
- flags |= O_NONBLOCK;
- if (fcntl(psock->fd, F_SETFL, flags) == -1)
- return 1;
- return 0;
+ return set_fd_nonblock(psock->fd);
}
int socket_init_in(const char *addr,
diff --git a/src/utils.c b/src/utils.c
index 9e09216..8d775cb 100644
--- a/src/utils.c
+++ b/src/utils.c
@@ -24,6 +24,22 @@
char *arg0 = NULL;
static int null_fd = -1;
+static void sighandler_child(int signo);
+
+
+int set_fd_nonblock(int fd)
+{
+ int flags;
+
+ flags = fcntl(fd, F_GETFL, 0);
+ if (flags < 0)
+ return 1;
+ flags |= O_NONBLOCK;
+ if (fcntl(fd, F_SETFL, flags) == -1)
+ return 1;
+
+ return 0;
+}
static void sighandler_child(int signo)
{
diff --git a/src/utils.h b/src/utils.h
index fb6f28c..3b075e5 100644
--- a/src/utils.h
+++ b/src/utils.h
@@ -8,6 +8,8 @@
extern char *arg0;
+int set_fd_nonblock(int fd);
+
int set_child_sighandler(void);
void set_procname(const char *new_arg0);