diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/main.c | 2 | ||||
-rw-r--r-- | src/server_ssh.c | 142 |
2 files changed, 138 insertions, 6 deletions
@@ -25,7 +25,7 @@ int main(int argc, char *argv[]) { ABORT_ON_FATAL( fwd_init_ctx(&ssh_fwd, ssh_init_cb), "Forwarder initialisation" ); - ABORT_ON_FATAL( fwd_setup(ssh_fwd, "127.0.0.1", "22"), + ABORT_ON_FATAL( fwd_setup(ssh_fwd, "127.0.0.1", "22222"), "Forwarder setup" ); ABORT_ON_FATAL( fwd_validate_ctx( ssh_fwd ), "Forwarder validation" ); diff --git a/src/server_ssh.c b/src/server_ssh.c index a8afeec..81dddc6 100644 --- a/src/server_ssh.c +++ b/src/server_ssh.c @@ -1,6 +1,13 @@ #include <stdio.h> #include <stdlib.h> #include <assert.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <signal.h> +#include <pthread.h> +#include <poll.h> +#include <pty.h> +#include <utmp.h> #include <libssh/callbacks.h> #include <libssh/server.h> @@ -13,8 +20,8 @@ #endif typedef struct ssh_data { + pthread_t self; ssh_bind sshbind; - ssh_session session; } ssh_data; struct fwd_callbacks potd_ssh_callbacks = { @@ -27,11 +34,23 @@ 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 int authenticate(ssh_session session); +static int auth_password(const char *user, const char *password); int ssh_init_cb(struct forward_ctx *ctx) { N("libssh version: %s", ssh_version(0)); + if (ssh_version(SSH_VERSION_INT(LIBSSH_VERSION_MAJOR, + LIBSSH_VERSION_MINOR, + LIBSSH_VERSION_MICRO)) == NULL) + { + W("This software was compiled/linked for libssh %d.%d.%d," + " which your arent currently using.", + LIBSSH_VERSION_MAJOR, LIBSSH_VERSION_MINOR, LIBSSH_VERSION_MICRO); + } if (ssh_version(SSH_VERSION_INT(0,7,3)) == NULL) { W("%s", "Unsupported libssh version < 0.7.3"); @@ -51,13 +70,12 @@ int ssh_init_cb(struct forward_ctx *ctx) ssh_data *d = (ssh_data *) calloc(1, sizeof(*d)); assert(d); d->sshbind = ssh_bind_new(); - d->session = ssh_new(); ctx->data = d; ssh_set_log_callback(ssh_log_cb); ssh_set_log_level(SSH_LOG_FUNCTIONS); - if (!d->sshbind || !d->session) + if (!d->sshbind) return 1; if (gen_default_keys()) return 1; @@ -70,6 +88,7 @@ int ssh_init_cb(struct forward_ctx *ctx) int ssh_on_listen(struct forward_ctx *ctx, const char *host, const char *port) { + int s; ssh_data *d = (ssh_data *) ctx->data; if (ssh_bind_options_set(d->sshbind, SSH_BIND_OPTIONS_BINDADDR, @@ -82,8 +101,14 @@ int ssh_on_listen(struct forward_ctx *ctx, const char *host, if (ssh_bind_listen(d->sshbind) < 0) { E("Error listening to SSH socket: %s", ssh_get_error(d->sshbind)); } + N("SSH bind and listen on %s:%s: %d", host, port, ssh_bind_get_fd(d->sshbind)); - return 0; + s = pthread_create(&d->self, NULL, ssh_thread_mainloop, d); + if (s) { + E_STRERR("pthread_create"); + } + + return s; } int ssh_on_shutdown(struct forward_ctx *ctx) @@ -115,7 +140,6 @@ static int set_default_keys(ssh_bind sshbind, int rsa_already_set, return 1; } } - return 0; } @@ -200,3 +224,111 @@ static void ssh_log_cb(int priority, const char *function, break; } } + +static void * +ssh_thread_mainloop(void *arg) +{ + int s, auth = 0; + ssh_session ses; + + assert(arg); + ssh_data *d = (ssh_data *) arg; + pthread_detach(d->self); + + while (1) { + ses = ssh_new(); + assert(ses); + + s = ssh_bind_accept(d->sshbind, ses); + if (s == SSH_ERROR) { + W("SSH error while accepting a connection: %s", + ssh_get_error(ses)); + goto failed; + } + + if (ssh_handle_key_exchange(ses)) { + W("SSH key exchange failed: %s", ssh_get_error(ses)); + goto failed; + } + + /* proceed to authentication */ + auth = authenticate(ses); + if (!auth) { + W("SSH authentication error: %s", ssh_get_error(ses)); + goto failed; + } + +failed: + ssh_disconnect(ses); + ssh_free(ses); + } + + return NULL; +} + +static int authenticate(ssh_session session) +{ + ssh_message message; + + do { + message = ssh_message_get(session); + if (!message) + break; + + switch (ssh_message_type(message)) { + + case SSH_REQUEST_AUTH: + switch (ssh_message_subtype(message)) { + case SSH_AUTH_METHOD_PASSWORD: + N("SSH: user '%s' wants to auth with pass '%s'", + ssh_message_auth_user(message), + ssh_message_auth_password(message)); + if (auth_password(ssh_message_auth_user(message), + ssh_message_auth_password(message))) + { + ssh_message_auth_reply_success(message,0); + ssh_message_free(message); + return 1; + } + ssh_message_auth_set_methods(message, + SSH_AUTH_METHOD_PASSWORD | + SSH_AUTH_METHOD_INTERACTIVE); + /* not authenticated, send default message */ + ssh_message_reply_default(message); + break; + + case SSH_AUTH_METHOD_NONE: + default: + N("SSH: User '%s' wants to auth with unknown auth '%d'\n", + ssh_message_auth_user(message), + ssh_message_subtype(message)); + ssh_message_auth_set_methods(message, + SSH_AUTH_METHOD_PASSWORD | + SSH_AUTH_METHOD_INTERACTIVE); + ssh_message_reply_default(message); + break; + } + break; + + default: + ssh_message_auth_set_methods(message, + SSH_AUTH_METHOD_PASSWORD | + SSH_AUTH_METHOD_INTERACTIVE); + ssh_message_reply_default(message); + } + ssh_message_free(message); + } while (1); + + return 0; +} + +static int auth_password(const char *user, const char *password) +{ +/* + if(strcmp(user, SSHD_USER)) + return 0; + if(strcmp(password, SSHD_PASSWORD)) + return 0; +*/ + return 1; /* authenticated */ +} |