--- lbbs/src/test_ssh_server.c 2025/06/03 13:58:21 1.1 +++ lbbs/src/test_ssh_server.c 2025/06/05 05:24:56 1.4 @@ -4,26 +4,103 @@ #include #include -static int ssh_auth_password_cb(ssh_session session, const char *user, const char *password, void *userdata) +#ifndef BUF_SIZE +#define BUF_SIZE 2048 +#endif + +#define SSH_HOST_KEYFILE "../conf/ssh_host_rsa_key" + +#define USER "test" +#define PASSWORD "123456" + +static ssh_channel SSH_channel; +static int authenticated = 0; +static int tries = 0; +static int error = 0; + +static int auth_password(ssh_session session, const char *user, + const char *password, void *userdata) { - if (strcmp(user, "test") == 0 && strcmp(password, "123456") == 0) + (void)userdata; + + log_common("Authenticating user %s pwd %s\n", user, password); + if (strcmp(user, USER) == 0 && strcmp(password, PASSWORD) == 0) { + authenticated = 1; + log_common("Authenticated\n"); return SSH_AUTH_SUCCESS; } - - log_std("Debug: SSH Auth OK\n"); + if (tries >= 3) + { + log_error("Too many authentication tries\n"); + ssh_disconnect(session); + error = 1; + return SSH_AUTH_DENIED; + } + tries++; return SSH_AUTH_DENIED; } +static int pty_request(ssh_session session, ssh_channel channel, const char *term, + int x, int y, int px, int py, void *userdata) +{ + (void)session; + (void)channel; + (void)term; + (void)x; + (void)y; + (void)px; + (void)py; + (void)userdata; + log_common("Allocated terminal\n"); + return 0; +} + +static int shell_request(ssh_session session, ssh_channel channel, void *userdata) +{ + (void)session; + (void)channel; + (void)userdata; + log_common("Allocated shell\n"); + return 0; +} + +struct ssh_channel_callbacks_struct channel_cb = { + .channel_pty_request_function = pty_request, + .channel_shell_request_function = shell_request}; + +static ssh_channel new_session_channel(ssh_session session, void *userdata) +{ + (void)session; + (void)userdata; + + if (SSH_channel != NULL) + return NULL; + + log_common("Allocated session channel\n"); + SSH_channel = ssh_channel_new(session); + ssh_callbacks_init(&channel_cb); + ssh_set_channel_callbacks(SSH_channel, &channel_cb); + + return SSH_channel; +} + int ssh_server(const char *hostaddr, unsigned int port) { ssh_bind sshbind; ssh_session session; - ssh_channel channel; - int ssh_log_level = SSH_LOG_PROTOCOL; + ssh_event event; + struct ssh_server_callbacks_struct cb = { .userdata = NULL, - .auth_password_function = ssh_auth_password_cb}; + .auth_password_function = auth_password, + .channel_open_request_session_function = new_session_channel}; + + char buf[BUF_SIZE]; + char host[128] = ""; + int i, r; + + int ssh_log_level = SSH_LOG_WARNING; ssh_init(); @@ -31,16 +108,18 @@ int ssh_server(const char *hostaddr, uns if (ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, hostaddr) < 0 || ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT, &port) < 0 || - ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, "ssh_host_rsa_key") < 0 || + ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_HOSTKEY, SSH_HOST_KEYFILE) < 0 || ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY, &ssh_log_level) < 0) { log_error("Error setting SSH bind options: %s\n", ssh_get_error(sshbind)); + ssh_bind_free(sshbind); return -1; } if (ssh_bind_listen(sshbind) < 0) { log_error("Error listening at SSH server port: %s\n", ssh_get_error(sshbind)); + ssh_bind_free(sshbind); return -1; } @@ -48,37 +127,95 @@ int ssh_server(const char *hostaddr, uns { session = ssh_new(); - if (ssh_bind_accept(sshbind, session) != SSH_OK) - { - log_error("Error accept SSH connection: %s\n", ssh_get_error(sshbind)); - } - - ssh_callbacks_init(&cb); - if (ssh_set_server_callbacks(session, &cb) != SSH_OK) - { - log_error("Error set SSH callback: %s\n", ssh_get_error(sshbind)); - } - - ssh_set_auth_methods(session, SSH_AUTH_METHOD_PASSWORD); - - if (ssh_handle_key_exchange(session) != SSH_OK) + if (ssh_bind_accept(sshbind, session) == SSH_OK) { - log_error("Error exchanging SSH keys: %s\n", ssh_get_error(sshbind)); - ssh_disconnect(session); - continue; + pid_t pid = fork(); + switch (pid) + { + case 0: + ssh_bind_free(sshbind); + + ssh_callbacks_init(&cb); + ssh_set_server_callbacks(session, &cb); + + if (ssh_handle_key_exchange(session)) + { + log_error("ssh_handle_key_exchange: %s\n", ssh_get_error(session)); + return 1; + } + ssh_set_auth_methods(session, SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_GSSAPI_MIC); + + event = ssh_event_new(); + ssh_event_add_session(event, session); + + while (!(authenticated && SSH_channel != NULL)) + { + if (error) + break; + r = ssh_event_dopoll(event, -1); + if (r == SSH_ERROR) + { + log_error("Error : %s\n", ssh_get_error(session)); + ssh_disconnect(session); + _exit(1); + } + } + + if (error) + { + log_error("Error, exiting loop\n"); + _exit(1); + } + else + { + log_common("Authenticated and got a channel\n"); + } + + snprintf(buf, sizeof(buf), "Hello, welcome to the Sample SSH proxy.\r\nPlease select your destination: "); + ssh_channel_write(SSH_channel, buf, (uint32_t)strlen(buf)); + do + { + i = ssh_channel_read(SSH_channel, buf, sizeof(buf), 0); + if (i > 0) + { + ssh_channel_write(SSH_channel, buf, (uint32_t)i); + if (strlen(host) + (size_t)i < sizeof(host)) + { + strncat(host, buf, (size_t)i); + } + if (strchr(host, '\x0d')) + { + *strchr(host, '\x0d') = '\0'; + ssh_channel_write(SSH_channel, "\n", 1); + break; + } + } + else + { + log_error("Error: %s\n", ssh_get_error(session)); + _exit(1); + } + } while (i > 0); + snprintf(buf, sizeof(buf), "Trying to connect to \"%s\"\r\n", host); + ssh_channel_write(SSH_channel, buf, (uint32_t)strlen(buf)); + log_common("%s", buf); + + ssh_disconnect(session); + ssh_free(session); + + _exit(0); + case -1: + log_error("Failed to fork\n"); + break; + } } - - channel = ssh_channel_new(session); - if (channel == NULL || ssh_channel_open_session(channel) != SSH_OK) + else { - log_error("Error opening SSH channel: %s\n", ssh_get_error(sshbind)); - ssh_channel_free(channel); - continue; + log_error("%s\n", ssh_get_error(sshbind)); } - log_std("Debug: #\n"); - - ssh_channel_close(channel); + /* Since the session has been passed to a child fork, do some cleaning + * up at the parent process. */ ssh_disconnect(session); ssh_free(session); } @@ -97,8 +234,8 @@ int main(int argc, char *argv[]) return -1; } - log_std_redirect(STDOUT_FILENO); - log_err_redirect(STDERR_FILENO); + log_common_redir(STDOUT_FILENO); + log_error_redir(STDERR_FILENO); ssh_server("0.0.0.0", 2322);