diff options
-rw-r--r-- | src/jail.c | 4 | ||||
-rw-r--r-- | src/protocol_ssh.c | 71 |
2 files changed, 47 insertions, 28 deletions
@@ -134,11 +134,11 @@ pid_t jail_daemonize(event_ctx **ev_ctx, jail_ctx *ctx[], size_t siz) p = fork(); switch (p) { case -1: - W_STRERR("%s", "Jail daemonize"); + E_STRERR("%s", "Jail daemonize"); return -1; case 0: - N("Jail daemon child pid %d", getpid()); jail_mainloop(ev_ctx, (const jail_ctx **) ctx, siz); + break; } D2("Jail daemon pid: %d", p); diff --git a/src/protocol_ssh.c b/src/protocol_ssh.c index 94149d4..e3c123f 100644 --- a/src/protocol_ssh.c +++ b/src/protocol_ssh.c @@ -4,13 +4,13 @@ #include <sys/types.h> #include <sys/wait.h> #include <signal.h> -#include <pthread.h> #include <poll.h> #include <libssh/callbacks.h> #include <libssh/server.h> #include "protocol_ssh.h" #include "protocol.h" +#include "utils.h" #include "log.h" #if LIBSSH_VERSION_MAJOR != 0 || LIBSSH_VERSION_MINOR < 7 || \ @@ -19,11 +19,15 @@ #endif typedef struct ssh_data { - pthread_t self; ssh_bind sshbind; protocol_ctx *ctx; } ssh_data; +typedef struct ssh_client { + ssh_channel chan; + forward_ctx dst; +} ssh_client; + struct protocol_cbs potd_ssh_callbacks = { .on_listen = ssh_on_listen, .on_shutdown = ssh_on_shutdown @@ -34,11 +38,11 @@ static int set_default_keys(ssh_bind sshbind, int rsa_already_set, static int gen_default_keys(void); static int gen_export_sshkey(enum ssh_keytypes_e type, int length, const char *path); static void ssh_log_cb(int priority, const char *function, const char *buffer, void *userdata); -static void * -ssh_thread_mainloop(void *arg); +static void ssh_mainloop(ssh_data *arg) + __attribute__((noreturn)); static int authenticate(ssh_session session); static int auth_password(const char *user, const char *password); -static int client_mainloop(ssh_channel chan, ssh_data *data); +static int client_mainloop(ssh_client *arg); static int copy_fd_to_chan(socket_t fd, int revents, void *userdata); static int copy_chan_to_fd(ssh_session session, ssh_channel channel, void *data, uint32_t len, int is_stderr, void *userdata); @@ -100,6 +104,7 @@ int ssh_init_cb(protocol_ctx *ctx) int ssh_on_listen(protocol_ctx *ctx) { + pid_t p; int s; ssh_data *d = (ssh_data *) ctx->src.data; @@ -120,14 +125,20 @@ int ssh_on_listen(protocol_ctx *ctx) socket_close(&ctx->src.sock); - s = pthread_create(&d->self, NULL, ssh_thread_mainloop, d); - if (s) { - E_STRERR("SSH Thread creation on %s:%s fd %d", - ctx->src.host_buf, ctx->src.service_buf, - ssh_bind_get_fd(d->sshbind)); + p = fork(); + switch (p) { + case -1: + E_STRERR("SSH protocol daemonize on %s:%s fd %d", + ctx->src.host_buf, ctx->src.service_buf, + ssh_bind_get_fd(d->sshbind)); + return 1; + case 0: + ssh_mainloop(d); + break; } + D2("SSH protocol pid: %d", p); - return s; + return s != 0; } int ssh_on_shutdown(protocol_ctx *ctx) @@ -244,23 +255,23 @@ static void ssh_log_cb(int priority, const char *function, } } -static void * -ssh_thread_mainloop(void *arg) +static void ssh_mainloop(ssh_data *arg) { int s, auth = 0, shell = 0; ssh_session ses; ssh_message message; ssh_channel chan = NULL; + ssh_client data; assert(arg); - ssh_data *d = (ssh_data *) arg; - pthread_detach(d->self); + set_procname("[potd] ssh"); + assert( set_child_sighandler() == 0 ); while (1) { ses = ssh_new(); assert(ses); - s = ssh_bind_accept(d->sshbind, ses); + s = ssh_bind_accept(arg->sshbind, ses); if (s == SSH_ERROR) { W("SSH error while accepting a connection: %s", ssh_get_error(ses)); @@ -333,14 +344,19 @@ ssh_thread_mainloop(void *arg) } N("%s", "Dropping user into shell"); - client_mainloop(chan, d); + + data.chan = chan; + data.dst = arg->ctx->dst; + if (client_mainloop(&data)) + W2("Client mainloop for fd %d failed", + ssh_bind_get_fd(arg->sshbind)); failed: ssh_disconnect(ses); ssh_free(ses); } - return NULL; + exit(EXIT_FAILURE); } static int authenticate(ssh_session session) @@ -410,18 +426,21 @@ static int auth_password(const char *user, const char *password) return 1; /* authenticated */ } -static int client_mainloop(ssh_channel chan, ssh_data *data) +static int client_mainloop(ssh_client *data) { + ssh_channel chan = data->chan; ssh_session session = ssh_channel_get_session(chan); ssh_event event; short events; - protocol_ctx *ctx = data->ctx; - psocket fwd; + forward_ctx *ctx = &data->dst; - if (fwd_connect_sock(&ctx->dst, &fwd)) + if (fwd_connect_sock(ctx, NULL)) { + E_STRERR("Connection to %s:%s", + ctx->host_buf, ctx->service_buf); return 1; + } - ssh_channel_cb.userdata = &fwd.fd; + ssh_channel_cb.userdata = &ctx->sock.fd; ssh_callbacks_init(&ssh_channel_cb); ssh_set_channel_callbacks(chan, &ssh_channel_cb); @@ -432,8 +451,8 @@ static int client_mainloop(ssh_channel chan, ssh_data *data) E2("%s", "Couldn't get a event"); return 1; } - if (ssh_event_add_fd(event, fwd.fd, events, copy_fd_to_chan, chan) != SSH_OK) { - E2("Couldn't add fd %d to the event queue", fwd.fd); + if (ssh_event_add_fd(event, ctx->sock.fd, events, copy_fd_to_chan, chan) != SSH_OK) { + E2("Couldn't add fd %d to the event queue", ctx->sock.fd); return 1; } if (ssh_event_add_session(event, session) != SSH_OK) { @@ -445,7 +464,7 @@ static int client_mainloop(ssh_channel chan, ssh_data *data) ssh_event_dopoll(event, 1000); } while (!ssh_channel_is_closed(chan)); - ssh_event_remove_fd(event, fwd.fd); + ssh_event_remove_fd(event, ctx->sock.fd); ssh_event_remove_session(event, session); ssh_event_free(event); return 0; |