aboutsummaryrefslogtreecommitdiff
path: root/src/server_ssh.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/server_ssh.c')
-rw-r--r--src/server_ssh.c142
1 files changed, 137 insertions, 5 deletions
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 */
+}