diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/CMakeLists.txt | 9 | ||||
-rw-r--r-- | src/client.c | 224 | ||||
-rw-r--r-- | src/client.h | 22 | ||||
-rw-r--r-- | src/main.c | 133 | ||||
-rw-r--r-- | src/mysql.c | 188 | ||||
-rw-r--r-- | src/mysql.h | 22 | ||||
-rw-r--r-- | src/proxy.c | 219 | ||||
-rw-r--r-- | src/proxy.h | 18 | ||||
-rw-r--r-- | src/recording.c | 126 | ||||
-rw-r--r-- | src/recording.h | 12 | ||||
-rw-r--r-- | src/session.c | 118 | ||||
-rw-r--r-- | src/session.h | 18 | ||||
-rw-r--r-- | src/state.c | 80 | ||||
-rw-r--r-- | src/state.h | 12 |
14 files changed, 0 insertions, 1201 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt deleted file mode 100644 index f885850..0000000 --- a/src/CMakeLists.txt +++ /dev/null @@ -1,9 +0,0 @@ -include_directories("${bastion_SOURCE_DIR}/termrec/libtty/") - -file(GLOB_RECURSE SOURCES *.c) - -add_executable(bastion ${SOURCES}) -add_library(libtty.a STATIC IMPORTED) -set_property(TARGET libtty.a PROPERTY IMPORTED_LOCATION "${bastion_SOURCE_DIR}/libtty.a") -target_link_libraries(bastion libtty.a) -target_link_libraries(bastion bz2 curl lzma mysqlclient pthread ssh z) diff --git a/src/client.c b/src/client.c deleted file mode 100644 index 11757fc..0000000 --- a/src/client.c +++ /dev/null @@ -1,224 +0,0 @@ -#include <libssh/callbacks.h> -#include <stdio.h> -#include <stdlib.h> - -#include "../config.h" -#include "client.h" -#ifdef SESSION_RECORDING -#include "recording.h" -#endif -#include "mysql.h" -#include "state.h" - -// callback function for channel data and exceptions -static int client_data_function(ssh_session session, ssh_channel channel, void *data, - uint32_t len, int is_stderr, void *userdata) { - struct client_channel_data_struct *cdata = (struct client_channel_data_struct *) userdata; - (void) session; - (void) channel; - (void) is_stderr; - - if (ssh_channel_is_open(cdata->proxy_channel)) { -#ifdef SESSION_RECORDING - record(data, len); -#endif - return ssh_channel_write(cdata->proxy_channel, (char*) data, len); - } else - return SSH_ERROR; -} - -static void client_channel_eof_callback (ssh_session session, ssh_channel channel, void *userdata) -{ - struct client_channel_data_struct *cdata = (struct client_channel_data_struct *) userdata; - (void) session; - (void) channel; - - if (ssh_channel_is_open(cdata->proxy_channel)) - ssh_channel_send_eof(cdata->proxy_channel); -} - -static void client_channel_close_callback (ssh_session session, ssh_channel channel, void *userdata) -{ - struct client_channel_data_struct *cdata = (struct client_channel_data_struct *) userdata; - (void) session; - (void) channel; - - if (ssh_channel_is_open(cdata->proxy_channel)) - ssh_channel_close(cdata->proxy_channel); -} - -static void client_channel_exit_status_callback (ssh_session session, ssh_channel channel, int exit_status, void *userdata) -{ - (void) session; - (void) channel; - (void) userdata; - printf("client exit status callback %d\n", exit_status); -} - -static void client_channel_signal_callback (ssh_session session, ssh_channel channel, - const char *signal, void *userdata) { - (void) session; - (void) channel; - (void) signal; - (void) userdata; - printf("client signal callback\n"); -} - -static void client_channel_exit_signal_callback (ssh_session session, ssh_channel channel, - const char *signal, int core, const char *errmsg, - const char *lang, void *userdata) { - (void) session; - (void) channel; - (void) signal; - (void) core; - (void) errmsg; - (void) lang; - (void) userdata; - printf("client exit signal callback\n"); -} - -struct client_channel_data_struct* client_dial(ssh_event event, struct proxy_channel_data_struct *pdata) -{ - const char * hostname = state_get_ssh_destination(); - struct client_channel_data_struct *cdata = malloc(sizeof(*cdata)); - cdata->event = event; - cdata->my_session = NULL; - cdata->my_channel = NULL; - cdata->proxy_channel = pdata->my_channel; - cdata->client_channel_cb = NULL; - - /* First we try to add the private key that the server will accept */ - struct db_host_info * info = db_get_host_info(hostname); - if (info == NULL) - goto host_info_clean; - - ssh_key privkey = NULL; - if (ssh_pki_import_privkey_base64(info->privkeytxt, NULL, NULL, NULL, &privkey) != SSH_OK) { - printf("Error importing private key"); - goto privkey_clean; - } - - /* We try to connect to the remote server */ - printf("Connecting to %s\n", hostname); - cdata->my_session = ssh_new(); - - ssh_options_set(cdata->my_session, SSH_OPTIONS_HOST, info->address); - ssh_options_set(cdata->my_session, SSH_OPTIONS_USER, info->username); -#ifdef LIBSSH_VERBOSE_OUTPOUT - int verbosity = SSH_LOG_PROTOCOL; - ssh_options_set(cdata->my_session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); -#endif - - if (ssh_connect(cdata->my_session) != SSH_OK) { - printf("Error connecting to %s: %s\n", hostname, ssh_get_error(cdata->my_session)); - goto session_clean; - } - - /* We now validate the remote server's public key */ - ssh_key server_pub_key = NULL; - unsigned char * hash = NULL; - size_t hlen; - char * hexa = NULL; - if (ssh_get_server_publickey(cdata->my_session, &server_pub_key) != SSH_OK) { - fprintf(stderr, "Error getting server publickey: %s\n", ssh_get_error(cdata->my_session)); - goto pubkey_clean; - } - if (ssh_get_publickey_hash(server_pub_key, SSH_PUBLICKEY_HASH_SHA1, &hash, &hlen) != SSH_OK) { - fprintf(stderr, "Error getting publickey hash: %s\n", ssh_get_error(cdata->my_session)); - goto pubkey_hash_clean; - } - hexa = ssh_get_hexa(hash, hlen); - if (strlen(info->hostkeyhash) > 0) { - if (strcmp(hexa, info->hostkeyhash) != 0) { - fprintf(stderr, "Error invalid host key for %s\n", hostname); - goto pubkey_hexa_clean; - } - } else { - // TODO we got a broken sshportal record, we need to fix it but only - // after we completed the migration from sshportal - //db_set_host_publickey_hash(hostname, hexa); - } - ssh_string_free_char(hexa); - ssh_clean_pubkey_hash(&hash); - ssh_key_free(server_pub_key); - - /* With the server checked, we can authenticate */ - if(ssh_userauth_publickey(cdata->my_session, NULL, privkey) == SSH_AUTH_SUCCESS){ - printf("Authentication success\n"); - } else { - printf("Error private key was rejected\n"); - goto session_clean; - } - - /* we open the client channel */ - cdata->my_channel = ssh_channel_new(cdata->my_session); - if (cdata->my_channel == NULL) { - printf("Couldn't open client channel to %s\n", hostname); - goto channel_clean; - } - - /* we open a session channel for the future shell, not suitable for tcp - * forwarding */ - if (ssh_channel_open_session(cdata->my_channel) != SSH_OK) { - printf("Couldn't open the session channel\n"); - goto channel_clean; - } - - cdata->client_channel_cb = malloc(sizeof(*cdata->client_channel_cb)); - memset(cdata->client_channel_cb, 0, sizeof(*cdata->client_channel_cb)); - cdata->client_channel_cb->userdata = cdata; - cdata->client_channel_cb->channel_data_function = client_data_function; - cdata->client_channel_cb->channel_eof_function = client_channel_eof_callback; - cdata->client_channel_cb->channel_close_function = client_channel_close_callback; - cdata->client_channel_cb->channel_exit_status_function = client_channel_exit_status_callback; - cdata->client_channel_cb->channel_signal_function = client_channel_signal_callback; - cdata->client_channel_cb->channel_exit_signal_function = client_channel_exit_signal_callback; - - ssh_callbacks_init(cdata->client_channel_cb); - ssh_set_channel_callbacks(cdata->my_channel, cdata->client_channel_cb); - ssh_event_add_session(event, cdata->my_session); - - // TODO only start recording upong shell_exec or pty_request in proxy.c. - // It will be important when we start supporting scp -#ifdef SESSION_RECORDING - if (init_recorder() != 0) { - goto channel_clean; - } -#endif - - ssh_key_free(privkey); - db_free_host_info(info); - return cdata; - -channel_clean: - ssh_channel_free(cdata->my_channel); - goto session_clean; -pubkey_hexa_clean: - ssh_string_free_char(hexa); -pubkey_hash_clean: - ssh_clean_pubkey_hash(&hash); -pubkey_clean: - ssh_key_free(server_pub_key); -session_clean: - ssh_disconnect(cdata->my_session); - ssh_free(cdata->my_session); - db_free_host_info(info); -privkey_clean: - ssh_key_free(privkey); -host_info_clean: - free(cdata); - return NULL; -} - -void client_cleanup(struct client_channel_data_struct *cdata) -{ -#ifdef SESSION_RECORDING - clean_recorder(); -#endif - ssh_event_remove_session(cdata->event, cdata->my_session); - ssh_channel_free(cdata->my_channel); - ssh_disconnect(cdata->my_session); - ssh_free(cdata->my_session); - free(cdata->client_channel_cb); - free(cdata); -} diff --git a/src/client.h b/src/client.h deleted file mode 100644 index 307b115..0000000 --- a/src/client.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef CLIENT_H_ -#define CLIENT_H_ - -#include <libssh/libssh.h> - -#include "proxy.h" -#include "session.h" - -/* A userdata struct for channel. */ -struct client_channel_data_struct { - /* Event which is used to poll */ - ssh_event event; - ssh_session my_session; - ssh_channel my_channel; - ssh_channel proxy_channel; - struct ssh_channel_callbacks_struct * client_channel_cb; -}; - -struct client_channel_data_struct* client_dial(ssh_event event, struct proxy_channel_data_struct *pdata); -void client_cleanup(struct client_channel_data_struct *cdata); - -#endif diff --git a/src/main.c b/src/main.c deleted file mode 100644 index 6ea6bcb..0000000 --- a/src/main.c +++ /dev/null @@ -1,133 +0,0 @@ -#include <libssh/callbacks.h> -#include <libssh/server.h> -#include <stdio.h> -#include <stdlib.h> -#include <sys/wait.h> - -#include "../config.h" -#include "mysql.h" -#include "session.h" - -/* SIGCHLD handler for cleaning up dead children. */ -static void sigchld_handler(int signo) { - (void) signo; - while (waitpid(-1, NULL, WNOHANG) > 0); -} - -/* SIGINT handler for cleaning up on forced exit. */ -static ssh_bind sshbind = NULL; -static ssh_session session = NULL; - -__attribute__((noreturn)) static void sigint_handler(int signo) -{ - (void) signo; - ssh_disconnect(session); - ssh_free(session); - ssh_bind_free(sshbind); - ssh_finalize(); - db_clean(); - exit(0); -} - -int main() -{ - // Set up SIGCHLD handler - struct sigaction sa; - sa.sa_handler = sigchld_handler; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_RESTART | SA_NOCLDSTOP; - if (sigaction(SIGCHLD, &sa, NULL) != 0) { - fprintf(stderr, "Failed to register SIGCHLD handler\n"); - return 1; - } - // Set up SIGINT handler - struct sigaction sa2; - sa2.sa_handler = sigint_handler; - sigemptyset(&sa2.sa_mask); - sa2.sa_flags = 0; - if (sigaction(SIGINT, &sa2, NULL) != 0) { - fprintf(stderr, "Failed to register SIGINT handler\n"); - return 1; - } - - // Initializing ssh context - ssh_init(); - - // Initializing ssh_bind - sshbind = ssh_bind_new(); - if (sshbind == NULL) { - fprintf(stderr, "Error initializing ssh_bind\n"); - exit(-1); - } - int listen_port = LISTEN_PORT; - ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT, &listen_port); - ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_DSAKEY, DSAKEY_PATH); - ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, RSAKEY_PATH); - ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_ECDSAKEY, ECDSAKEY_PATH); - - if (ssh_bind_listen(sshbind) < 0) { - printf("Error listening to socket: %s\n", ssh_get_error(sshbind)); - ssh_bind_free(sshbind); - ssh_finalize(); - return 1; - } - - while (1) { - session = ssh_new(); - if (session == NULL) { - fprintf(stderr, "Error initializing ssh_session\n"); - break; - } -#ifdef LIBSSH_VERBOSE_OUTPOUT - int verbosity = SSH_LOG_PROTOCOL; - ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity); -#endif - - // Blocks until there is a new incoming connection - if (ssh_bind_accept(sshbind,session) == SSH_OK){ - switch(fork()) { - case 0: - /* Remove the SIGCHLD handler inherited from parent. */ - sa.sa_handler = SIG_DFL; - sigaction(SIGCHLD, &sa, NULL); - /* Remove socket binding, which allows us to restart the parent process, without terminating existing sessions. */ - ssh_bind_free(sshbind); - sshbind = NULL; - - if (db_init() !=0) - goto child_cleaning; - - ssh_event event = ssh_event_new(); - if (event != NULL) { - /* Blocks until the SSH session ends */ - handle_session(event, session); - ssh_event_free(event); - } else { - fprintf(stderr, "Could not create polling context\n"); - } -child_cleaning: - ssh_disconnect(session); - ssh_free(session); - ssh_finalize(); - - return 0; - case -1: - fprintf(stderr, "Failed to fork\n"); - } - } else { - fprintf(stderr, "Error accepting a connection : %s\n", ssh_get_error(sshbind)); - ssh_disconnect(session); - ssh_free(session); - ssh_bind_free(sshbind); - ssh_finalize(); - return 1; - } - /* Since the session has been passed to a child fork, do some cleaning up at the parent process. */ - ssh_disconnect(session); - ssh_free(session); - } - ssh_bind_free(sshbind); - ssh_finalize(); - db_clean(); - return 0; -} diff --git a/src/mysql.c b/src/mysql.c deleted file mode 100644 index 0931116..0000000 --- a/src/mysql.c +++ /dev/null @@ -1,188 +0,0 @@ -#include <libssh/server.h> -#include <mysql/mysql.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "../config.h" -#include "mysql.h" - -static MYSQL *db; - -char // returns 0 if ok, greater than 0 otherwise -db_init(void) -{ - printf("MySQL client version: %s\n", mysql_get_client_info()); - db = mysql_init(NULL); - if (db == NULL) { - fprintf(stderr, "%s\n", mysql_error(db)); - return 1; - } - if (mysql_real_connect(db, MYSQL_HOST, MYSQL_USER, MYSQL_PASS, MYSQL_DB, 0, NULL, 0) == NULL) { - fprintf(stderr, "%s\n", mysql_error(db)); - mysql_close(db); - return 1; - } - return 0; -} - -void db_clean(void) -{ - mysql_close(db); - db = NULL; -} - -char * // returns NULL if no user found, this char * is to be freed from the calling code -db_get_username_from_pubkey(ssh_key pubkey) -{ - int res = mysql_query(db, "SELECT name, authorized_key FROM users, user_keys WHERE users.id = user_keys.user_id"); - if (res != 0) { - fprintf(stderr, "WARNING: Couldn't get usernames from database.\n"); - return NULL; - } - MYSQL_RES *result = mysql_store_result(db); - if (result == NULL) { - fprintf(stderr, "FATAL: Couldn't retrieve public keys from database.\n"); - return NULL; - } - - MYSQL_ROW row; - while ((row = mysql_fetch_row(result))) { - char * rsa = "ssh-rsa "; - if (strncmp (row[1], rsa, strlen(rsa)) != 0) { - fprintf(stderr, "Unsupported public key type for user %s : %s\n", row[0], row[1]); - } else { - ssh_key tmp_key; - if (ssh_pki_import_pubkey_base64(row[1] + strlen(rsa), SSH_KEYTYPE_RSA, &tmp_key) != SSH_OK) { - fprintf(stderr, "Error importing public key for user %s : %s\n", row[0], row[1]); - } else if (!ssh_key_cmp(pubkey, tmp_key, SSH_KEY_CMP_PUBLIC)) { - size_t len = strlen(row[0]); - char * username = malloc(len+1); - strcpy(username, row[0]); - ssh_key_free(tmp_key); - mysql_free_result(result); - return username; - } else { - ssh_key_free(tmp_key); - } - } - } - - fprintf(stderr, "ERROR: Didn't find public key in database.\n"); - mysql_free_result(result); - return NULL; -} - -struct db_host_info * // returns NULL if no key found, this char * is to be freed from the calling code -db_get_host_info(const char * hostname) -{ - char buff[255]; - sprintf(buff, "SELECT priv_key, url, host_key FROM ssh_keys, hosts WHERE ssh_keys.id = hosts.ssh_key_id and hosts.name = \"%s\"", hostname); - int res = mysql_query(db, buff); - if (res != 0) { - fprintf(stderr, "WARNING: Couldn't query db for server infos for host %s\n", hostname); - return NULL; - } - MYSQL_RES *result = mysql_store_result(db); - if (result == NULL) { - fprintf(stderr, "FATAL: Couldn't retrieve server infos for %s from database.\n", hostname); - return NULL; - } - - MYSQL_ROW row = mysql_fetch_row(result); - if (row == NULL) { - fprintf(stderr, "FATAL: Couldn't retrieve server db results for %s from database.\n", hostname); - mysql_free_result(result); - return NULL; - } - - struct db_host_info * info = malloc(sizeof(struct db_host_info)); - memset(info, 0, sizeof(struct db_host_info)); - - size_t len = strlen(row[0]); - info->privkeytxt = malloc(len+1); - strcpy(info->privkeytxt, row[0]); - - if (strncmp(row[1], "ssh://", 6) != 0) { - fprintf(stderr, "FATAL: invalid host url %s\n", row[1]); - return NULL; - } - size_t at_pos = 0; - char done = 0; - for(size_t i = 6; !done; ++i) { - switch(*(row[1]+i)) { - case '@': - info->username = malloc(i-6+1); - strncpy(info->username, row[1]+6, i-6); - info->username[i-6] = '\0'; - at_pos = i; - break; - case '\0': - info->address = malloc(i-at_pos); - strncpy(info->address, row[1]+at_pos+1, i-at_pos-1); - info->address[i-at_pos-1] = '\0'; - done = 1; - break; - } - if (i > MAX_HOSTNAME_LENGTH + MAX_USERNAME_LENGTH + 6 + 1) { - fprintf(stderr, "FATAL: Couldn't parse host url for host %s, too long.\n", hostname); - if (info->username != NULL) - free(info->username); - return NULL; - } - } - - len = strlen(row[2]); - info->hostkeyhash = malloc(len+1); - strcpy(info->hostkeyhash, row[2]); - - mysql_free_result(result); - return info; -} - -void db_set_host_publickey_hash(const char * hostname, const char * hash) -{ - char buff[255]; - sprintf(buff, "UPDATE ssh_keys, hosts SET host_key = \"%s\" WHERE ssh_keys.id = hosts.ssh_key_id and hosts.name = \"%s\"", hash, hostname); - int res = mysql_query(db, buff); - if (res != 0) { - fprintf(stderr, "WARNING: Couldn't set host key for host %s: %s\n", hostname, hash); - return; - } - res = mysql_commit(db); - if (res != 0) { - fprintf(stderr, "WARNING: Couldn't commit after setting host key for host %s: %s\n", hostname, hash); - } -} - -unsigned long long // returns 0 on error, or the session_id -db_init_session_and_get_id(const char * hostname, const char * username) -{ - char buff[255]; - sprintf(buff, "INSERT INTO sessions (created_at, status, user_id, host_id) SELECT NOW(), \"opened\", users.id, hosts.id from users, hosts WHERE users.name = \"%s\" and hosts.name = \"%s\"", username, hostname); - int res = mysql_query(db, buff); - if (res != 0) { - fprintf(stderr, "FATAL: Couldn't insert new session in database for %s to %s\n", username, hostname); - return 0; - } - unsigned long long id = mysql_insert_id(db); - if (id == 0) { - fprintf(stderr, "FATAL: Didn't get proper mysql last insert id after inserting new session for %s to %s\n", username, hostname); - return 0; - } - res = mysql_commit(db); - if (res != 0) { - fprintf(stderr, "FATAL: Couldn't commit after inserting session for %s to %s\n", username, hostname); - return 0; - } - return id; -} - -void db_free_host_info(struct db_host_info * info) -{ - free(info->privkeytxt); - free(info->address); - free(info->username); - free(info->hostkeyhash); - free(info); -} diff --git a/src/mysql.h b/src/mysql.h deleted file mode 100644 index 8c6040f..0000000 --- a/src/mysql.h +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef MYSQL_H_ -#define MYSQL_H_ - -struct db_host_info { - char * privkeytxt; - char * address; - char * username; - char * hostkeyhash; -}; - -char db_init(void); -void db_clean(void); -char * // returns NULL if no user found, this char * is to be freed from the calling code -db_get_username_from_pubkey(ssh_key pubkey); -struct db_host_info * // returns NULL if no key found, this char * is to be freed from the calling code -db_get_host_info(const char * hostname); -void db_set_host_publickey_hash(const char * hostname, const char * hash); -unsigned long long // returns 0 on error, or the session_id -db_init_session_and_get_id(const char * hostname, const char * username); -void db_free_host_info(struct db_host_info * info); - -#endif diff --git a/src/proxy.c b/src/proxy.c deleted file mode 100644 index 7d410db..0000000 --- a/src/proxy.c +++ /dev/null @@ -1,219 +0,0 @@ -#include <libssh/callbacks.h> -#include <stdio.h> -#include <stdlib.h> - -#include "client.h" -#include "mysql.h" -#include "proxy.h" -#include "state.h" - -// callback function for channel data and exceptions -static int proxy_data_function(ssh_session session, ssh_channel channel, void *data, - uint32_t len, int is_stderr, void *userdata) { - struct proxy_channel_data_struct *pdata = (struct proxy_channel_data_struct *) userdata; - (void) session; - (void) channel; - (void) is_stderr; - - if (ssh_channel_is_open(pdata->client_channel)) - return ssh_channel_write(pdata->client_channel, (char*) data, len); - else - return SSH_ERROR; -} - -// callback function for SSH channel PTY request from a client -static int proxy_pty_request(ssh_session session, ssh_channel channel, - const char *term, int cols, int rows, int py, int px, - void *userdata) { - struct proxy_channel_data_struct *pdata = (struct proxy_channel_data_struct *)userdata; - - (void) session; - (void) channel; - (void) py; - (void) px; - - // TODO record pty size in recorder - if (ssh_channel_is_open(pdata->client_channel)) { - if (ssh_channel_request_pty_size(pdata->client_channel, term, cols, rows) == SSH_OK) - return SSH_OK; - else - fprintf(stderr, "pty request failed\n"); - } else { - fprintf(stderr, "pty request while client_channel not opened\n"); - } - return SSH_ERROR; -} - -// callback function for SSH channel PTY resize from a client -static int proxy_pty_resize(ssh_session session, ssh_channel channel, int cols, - int rows, int py, int px, void *userdata) { - struct proxy_channel_data_struct *pdata = (struct proxy_channel_data_struct *)userdata; - - (void) session; - (void) channel; - (void) py; - (void) px; - - // TODO record pty size in recorder - if (ssh_channel_is_open(pdata->client_channel)) { - if (ssh_channel_change_pty_size(pdata->client_channel, cols, rows) == SSH_OK) - return SSH_OK; - else - fprintf(stderr, "pty resize failed\n"); - } else { - fprintf(stderr, "pty resize while client_channel not opened\n"); - } - return SSH_ERROR; -} - -static int proxy_exec_request(ssh_session session, ssh_channel channel, - const char *command, void *userdata) { - struct proxy_channel_data_struct *pdata = (struct proxy_channel_data_struct *) userdata; - - (void) session; - (void) channel; - - if (ssh_channel_is_open(pdata->client_channel)) { - if (ssh_channel_request_exec(pdata->client_channel, command) == SSH_OK) - return SSH_OK; - else - printf("exec request failed\n"); - } else { - fprintf(stderr, "exec request while client_channel not opened\n"); - } - return SSH_ERROR; -} - -static int proxy_shell_request(ssh_session session, ssh_channel channel, - void *userdata) { - struct proxy_channel_data_struct *pdata = (struct proxy_channel_data_struct *) userdata; - - (void) session; - (void) channel; - - if (ssh_channel_is_open(pdata->client_channel)) { - if (ssh_channel_request_shell(pdata->client_channel) == SSH_OK) - return SSH_OK; - else - fprintf(stderr, "shell request failed\n"); - } else { - fprintf(stderr, "shell request while client channel not opened\n"); - } - return SSH_ERROR; -} - -static int proxy_subsystem_request(ssh_session session, ssh_channel channel, - const char *subsystem, void *userdata) { - (void) session; - (void) channel; - (void) subsystem; - (void) userdata; - return SSH_ERROR; // TODO ssh subsystem request - //if (ssh_channel_is_open(pdata->client_channel)) { - //} -} - -static void proxy_channel_eof_callback (ssh_session session, ssh_channel channel, void *userdata) -{ - struct proxy_channel_data_struct *pdata = (struct proxy_channel_data_struct *) userdata; - (void) session; - (void) channel; - if (ssh_channel_is_open(pdata->client_channel)) - ssh_channel_send_eof(pdata->client_channel); -} - -static void proxy_channel_close_callback (ssh_session session, ssh_channel channel, void *userdata) -{ - struct proxy_channel_data_struct *pdata = (struct proxy_channel_data_struct *) userdata; - (void) session; - (void) channel; - if (ssh_channel_is_open(pdata->client_channel)) - ssh_channel_close(pdata->client_channel); -} - -static void proxy_channel_exit_status_callback (ssh_session session, ssh_channel channel, int exit_status, void *userdata) -{ - (void) session; - (void) channel; - (void) exit_status; - (void) userdata; - printf("proxy exit status callback\n"); -} - -static void proxy_channel_signal_callback (ssh_session session, ssh_channel channel, - const char *signal, void *userdata) { - (void) session; - (void) channel; - (void) signal; - (void) userdata; - printf("proxy signal callback\n"); -} - -static void proxy_channel_exit_signal_callback (ssh_session session, ssh_channel channel, - const char *signal, int core, const char *errmsg, - const char *lang, void *userdata) { - (void) session; - (void) channel; - (void) signal; - (void) core; - (void) errmsg; - (void) lang; - (void) userdata; - printf("proxy exit signal callback\n"); -} - -void handle_proxy_session(ssh_event event, ssh_session session, ssh_channel my_channel) -{ - struct client_channel_data_struct * cdata; - - struct proxy_channel_data_struct pdata = { - .event = event, - .my_session = session, - .my_channel = my_channel, - .client_channel = NULL, - }; - - cdata = client_dial(event, &pdata); - - if (cdata == NULL) { - return; - } - pdata.client_channel = cdata->my_channel; - - /* We tie everything together */ - struct ssh_channel_callbacks_struct channel_cb = { - .userdata = &pdata, - .channel_data_function = proxy_data_function, - .channel_eof_function = proxy_channel_eof_callback, - .channel_close_function = proxy_channel_close_callback, - .channel_signal_function = proxy_channel_signal_callback, - .channel_exit_status_function = proxy_channel_exit_status_callback, - .channel_exit_signal_function = proxy_channel_exit_signal_callback, - .channel_pty_request_function = proxy_pty_request, - .channel_shell_request_function = proxy_shell_request, - .channel_pty_window_change_function = proxy_pty_resize, - .channel_exec_request_function = proxy_exec_request, - .channel_subsystem_request_function = proxy_subsystem_request, - .channel_auth_agent_req_function = NULL, - .channel_x11_req_function = NULL, - .channel_env_request_function = NULL, - .channel_write_wontblock_function = NULL, - }; - ssh_callbacks_init(&channel_cb); - ssh_set_channel_callbacks(my_channel, &channel_cb); - - db_clean(); // we close the mysql connection before the main loop, as to not waste ressources - - do { - /* Poll the main event which takes care of the sessions and channels */ - if (ssh_event_dopoll(event, -1) == SSH_ERROR) { - break; - } - } while(ssh_channel_is_open(my_channel) && ssh_channel_is_open(pdata.client_channel)); - if (ssh_channel_is_open(my_channel)) - ssh_channel_close(my_channel); - if (ssh_channel_is_open(cdata->my_channel)) - ssh_channel_close(cdata->my_channel); - - client_cleanup(cdata); -} diff --git a/src/proxy.h b/src/proxy.h deleted file mode 100644 index 0e42bdc..0000000 --- a/src/proxy.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef PROXY_H_ -#define PROXY_H_ - -#include <libssh/libssh.h> - -#include "session.h" - -/* A userdata struct for channel. */ -struct proxy_channel_data_struct { - /* Event which is used to poll */ - ssh_event event; - ssh_session my_session; - ssh_channel my_channel; - ssh_channel client_channel; -}; -void handle_proxy_session(ssh_event event, ssh_session session, ssh_channel my_channel); - -#endif diff --git a/src/recording.c b/src/recording.c deleted file mode 100644 index 7692ff1..0000000 --- a/src/recording.c +++ /dev/null @@ -1,126 +0,0 @@ -#include <dirent.h> -#include <errno.h> -#include <fcntl.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <sys/stat.h> -#include <sys/types.h> -#include <sys/time.h> -#include <time.h> -#include <ttyrec.h> - -#include "../config.h" -#include "recording.h" -#include "state.h" - -#ifdef SESSION_RECORDING -static recorder recorder_handle = NULL; - -void clean_recorder(void) -{ - ttyrec_w_close(recorder_handle); - recorder_handle = NULL; -} - -static char * // returns NULL if error, this char * is to be freed from the calling code -make_filename(void) -{ - char * format = LOG_FILENAME_FORMAT; - char * filename = NULL; - unsigned int fname_pos = 0; - unsigned int format_pos = 0; - - filename = malloc(LOG_FILENAME_MAX_LEN+1); - - size_t format_len = strlen(format); - while (format_pos < format_len + 1 && fname_pos < LOG_FILENAME_MAX_LEN +1) { - if (format[format_pos] == '$') { - format_pos++; - if (format[format_pos] == 'd') { - time_t t; - struct tm * tm; - time(&t); - tm = localtime(&t); - fname_pos += strftime(filename + fname_pos, LOG_FILENAME_MAX_LEN - fname_pos, "%F", tm); - } else if (format[format_pos] == 'h') { - const char * hostname = state_get_ssh_destination(); - size_t len = strlen(hostname); - strcpy(filename + fname_pos, hostname); - fname_pos += len; - } else if (format[format_pos] == 'u') { - const char * username = state_get_bastion_username(); - size_t len = strlen(username); - strcpy(filename + fname_pos, username); - fname_pos += len; - } else if (format[format_pos] == 'i') { - sprintf(filename + fname_pos, "%llu", state_get_session_id()); - fname_pos += strlen(filename + fname_pos); - } - format_pos++; - } else { - filename[fname_pos] = format[format_pos]; - if (filename[fname_pos] == '/') { // We create the corresponding directory if it doesn't exist - filename[fname_pos+1] = '\0'; - DIR* dir = opendir(filename); - if (dir) - closedir(dir); - else { - int ret = mkdir(filename, LOG_DIRECTORY_MODE); - if (ret != 0) { - fprintf(stderr, "Couldn't create log directory %s : %s\n", filename, strerror( errno )); - } - } - } - format_pos++; - fname_pos++; - } - } - - if (filename[fname_pos-1] != '\0') { - fprintf(stderr, "Log file name is too long, check LOG_FILENAME_FORMAT and LOG_FILENAME_MAX_LEN\n"); - free(filename); - filename = NULL; - } - return filename; -} - -char // returns 0 if ok, 1 otherwise -init_recorder(void) -{ - char * filename = make_filename(); - if (filename == NULL) - return 1; - struct timeval tm; - if (gettimeofday(&tm, NULL) != 0) { - fprintf(stderr, "OUPS gettimeofday failed!\n"); - return 1; - } - recorder_handle = ttyrec_w_open(-1, "ttyrec", filename, &tm); - free(filename); - if (recorder_handle == NULL) { - fprintf(stderr, "Couldn't open the session termrec log file.\n"); - return 1; - } - - return 0; -} - -char // returns 0 if ok, greater than 0 otherwise -record(void* data, size_t len) -{ - if(recorder_handle == NULL) - return 0; - - struct timeval tm; - if (gettimeofday(&tm, NULL) != 0) { - fprintf(stderr, "OUPS gettimeofday failed!\n"); - return 1; - } - if (ttyrec_w_write(recorder_handle, &tm, data, (int) len) == 0) { - fprintf(stderr, "OUPS ttyrec_w_write failed!\n"); - return 2; - } - return 0; -} -#endif diff --git a/src/recording.h b/src/recording.h deleted file mode 100644 index fec76af..0000000 --- a/src/recording.h +++ /dev/null @@ -1,12 +0,0 @@ -#include "../config.h" - -#ifdef SESSION_RECORDING -#ifndef RECORDING_H_ -#define RECORDING_H_ - -void clean_recorder(void); -char init_recorder(void); -char record(void* data, size_t len); - -#endif -#endif diff --git a/src/session.c b/src/session.c deleted file mode 100644 index 3d3b1b7..0000000 --- a/src/session.c +++ /dev/null @@ -1,118 +0,0 @@ -#include <libssh/callbacks.h> -#include <libssh/server.h> -#include <poll.h> -#include <pty.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <sys/wait.h> - -#include "../config.h" -#include "mysql.h" -#include "proxy.h" -#include "session.h" -#include "state.h" - -static int auth_pubkey(ssh_session session, const char *user, ssh_key pubkey, char signature_state, - void *userdata) { - struct session_data_struct *sdata = (struct session_data_struct *) userdata; - (void) session; - - // For some reason, libssh can call this twice for the same key - if (sdata->authenticated == 1) - return SSH_ERROR; - - if (signature_state != SSH_PUBLICKEY_STATE_NONE && signature_state != SSH_PUBLICKEY_STATE_VALID) { - fprintf(stderr, "Invalid signature state\n"); - sdata->auth_attempts++; - return SSH_AUTH_DENIED; - } - - // TODO check for an invite - - char * bastion_username = db_get_username_from_pubkey(pubkey); - if (bastion_username != NULL) { - sdata->authenticated = 1; - if (state_set_ssh_destination(user) != 0) - return SSH_ERROR; - // TODO check access rights and host configs - state_set_bastion_username(bastion_username); - unsigned long long session_id = db_init_session_and_get_id(user, bastion_username); - state_set_session_id(session_id); - free(bastion_username); - return SSH_AUTH_SUCCESS; - } else { - free(bastion_username); - sdata->auth_attempts++; - return SSH_AUTH_DENIED; - } -} - -static ssh_channel channel_open(ssh_session session, void *userdata) { - struct session_data_struct *sdata = (struct session_data_struct *) userdata; - - if (sdata->channel == NULL) { - sdata->channel = ssh_channel_new(session); - return sdata->channel; - } else { - // Only one channel allowed - return NULL; - } -} - -void handle_session(ssh_event event, ssh_session session) { - /* Our struct holding information about the session. */ - struct session_data_struct sdata = { - .channel = NULL, - .auth_attempts = 0, - .authenticated = 0, - }; - - struct ssh_server_callbacks_struct server_cb = { - .userdata = &sdata, - .auth_pubkey_function = auth_pubkey, - .channel_open_request_session_function = channel_open, - }; - ssh_callbacks_init(&server_cb); - ssh_set_server_callbacks(session, &server_cb); - - if (ssh_handle_key_exchange(session) != SSH_OK) { - fprintf(stderr, "%s\n", ssh_get_error(session)); - return; - } - - ssh_set_auth_methods(session, SSH_AUTH_METHOD_PUBLICKEY); - ssh_event_add_session(event, session); - - for (int n=0; sdata.authenticated == 0 || sdata.channel == NULL; n++) { - /* If the user has used up all attempts, or if he hasn't been able to - * authenticate in 10 seconds (n * 100ms), disconnect. */ - if (sdata.auth_attempts >= 3) { - fprintf(stderr, "Closing connection after 3 failed auth attempts\n"); - return; - } - if (n >= 100) { - fprintf(stderr, "Closing connection after 10 seconds without successfull authentication\n"); - return; - } - - if (ssh_event_dopoll(event, 100) == SSH_ERROR) { - fprintf(stderr, "%s\n", ssh_get_error(session)); - return; - } - } - - handle_proxy_session(event, session, sdata.channel); - - if (ssh_channel_is_open(sdata.channel)) { - ssh_channel_close(sdata.channel); - } - - /* Wait up to 5 seconds for the client to terminate the session. */ - for (int n = 0; n < 50 && (ssh_get_status(session) & SESSION_END) == 0; n++) { - ssh_event_dopoll(event, 100); - } - state_clean(); - ssh_event_remove_session(event, session); -} diff --git a/src/session.h b/src/session.h deleted file mode 100644 index d0c8eab..0000000 --- a/src/session.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef SESSION_H_ -#define SESSION_H_ - -#include <libssh/libssh.h> - -#define SESSION_END (SSH_CLOSED | SSH_CLOSED_ERROR) - -/* A userdata struct for session. */ -struct session_data_struct { - /* Pointer to the channel the session will allocate. */ - ssh_channel channel; - int auth_attempts; - int authenticated; -}; - -void handle_session(ssh_event event, ssh_session session); - -#endif diff --git a/src/state.c b/src/state.c deleted file mode 100644 index dd9cbf3..0000000 --- a/src/state.c +++ /dev/null @@ -1,80 +0,0 @@ -#include <stdlib.h> -#include <stdio.h> -#include <string.h> - -#include "../config.h" -#include "state.h" - -struct state { - unsigned long long session_id; - char * destination; - char * bastion_username; -}; - -static struct state state = {0}; - -char // returns 0 if ok, greater than 0 otherwise -state_set_ssh_destination(const char * name) -{ - if (state.destination != NULL) { - fprintf(stderr, "BUG found, attempting to overwrite state.destination that has already been set\n"); - return 1; - } - size_t len = strnlen(name, MAX_HOSTNAME_LENGTH + 1); - if (len >= MAX_HOSTNAME_LENGTH + 1) { - fprintf(stderr, "Hostname too long, max length is %d.\n", MAX_HOSTNAME_LENGTH); - return 2; - } - state.destination = malloc(len+1); - strncpy(state.destination, name, len+1); - return 0; -} - -const char * state_get_ssh_destination(void) -{ - return state.destination; -} - -char // return 0 if ok, greater than 0 otherwise -state_set_bastion_username(const char * name) -{ - if (state.bastion_username != NULL) { - fprintf(stderr, "BUG found, attempting to overwrite state.bastion_username that has already been set\n"); - return 1; - } - size_t len = strnlen(name, MAX_USERNAME_LENGTH + 1); - if (len >= MAX_USERNAME_LENGTH + 1) { - fprintf(stderr, "Username too long, max length is %d.\n", MAX_USERNAME_LENGTH); - return 1; - } - state.bastion_username = malloc(len+1); - strncpy(state.bastion_username, name, len+1); - return 0; -} - -const char * state_get_bastion_username(void) -{ - return state.bastion_username; -} - -char // return 0 if ok, greater than 0 otherwise -state_set_session_id(const unsigned long long id) -{ - if (state.session_id != 0) { - fprintf(stderr, "BUG found, attempting to set a state.session_id that has already been set\n"); - return 1; - } - state.session_id = id; - return 0; -} - -unsigned long long state_get_session_id(void) -{ - return state.session_id; -} - -void state_clean(void) -{ - free(state.destination); - state.destination = NULL; -} diff --git a/src/state.h b/src/state.h deleted file mode 100644 index 0ab70bc..0000000 --- a/src/state.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef STATE_H_ -#define STATE_H_ - -char state_set_ssh_destination(const char * dest); -const char * state_get_ssh_destination(void); -char state_set_bastion_username(const char * name); -const char * state_get_bastion_username(void); -char state_set_session_id(const unsigned long long id); -unsigned long long state_get_session_id(void); -void state_clean(void); - -#endif |