Skip to content

Instantly share code, notes, and snippets.

@bilby91

bilby91/client.c Secret

Created March 26, 2018 06:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bilby91/22d5cc5db0e6118f06d6d35051c32cc6 to your computer and use it in GitHub Desktop.
Save bilby91/22d5cc5db0e6118f06d6d35051c32cc6 to your computer and use it in GitHub Desktop.
SSH Reverse Tunnel
#include <libssh/callbacks.h>
#include <libssh/libssh.h>
#include <libssh/server.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/**
* @brief The default ssh user
*
*/
#define SSHD_USER "libssh"
/**
* @brief The default ssh password
*
*/
#define SSHD_PASSWORD "password"
/**
* @brief sshd address
*
*/
static char *sshd_address = "0.0.0.0";
/**
* @brief sshd port
*
*/
static char *sshd_port = "2000";
/**
* @brief Remote forward address
*
*/
static char *remote_address = "0.0.0.0";
/**
* @brief Remote forward port
*
*/
static int remote_port = 2000;
/**
* @brief libssh log level. 3 is the most verbose one
*
*/
static char *log_verbosity = "3";
/**
* @brief Hardcoded web server response
*
*/
static char *http_response =
""
"HTTP/1.1 200 OK\n"
"Content-Type: text/html\n"
"Content-Length: 113\n"
"\n"
"<html>\n"
" <head>\n"
" <title>Hello, World!</title>\n"
" </head>\n"
" <body>\n"
" <h1>Hello, World!</h1>\n"
" </body>\n"
"</html>\n";
/**
* @brief Configure the ssh_session
*
* @param session
*/
static void configure_session(ssh_session session) {
ssh_options_set(session, SSH_OPTIONS_HOST, sshd_address);
ssh_options_set(session, SSH_OPTIONS_PORT_STR, sshd_port);
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &log_verbosity);
}
/**
* @brief Connect to the sshd using default configurations
*
* @return ssh_session
*/
static ssh_session connect_ssh_server() {
ssh_session session = ssh_new();
configure_session(session);
if (session == NULL) {
return NULL;
}
if (ssh_connect(session)) {
fprintf(stderr, "Connection failed: %s\n", ssh_get_error(session));
ssh_disconnect(session);
return NULL;
}
return session;
}
/**
* @brief Authenticate user with default user and password
*
* @param session
* @return int
*/
static int authenticate(ssh_session session) {
switch (ssh_userauth_password(session, SSHD_USER, SSHD_PASSWORD)) {
case SSH_AUTH_SUCCESS:
return 0;
case SSH_AUTH_DENIED:
fprintf(stderr, "Authentication failed\n");
return 1;
default:
return 1;
}
}
/**
* @brief Make global request for forwarding and wait for channel.
*
* @param session
* @return ssh_channel
*/
static ssh_channel open_reverse_channel(ssh_session session) {
int port;
if (ssh_channel_listen_forward(session, remote_address, remote_port, NULL)) {
return NULL;
}
ssh_channel channel = ssh_channel_accept_forward(session, 100000, &port);
return channel;
}
/**
* @brief Forward channel to upstream and respond to channel back.
*
* @param session
* @param channel
* @return int
*/
int forward_channel(ssh_session session, ssh_channel channel) {
char buffer[256];
int r_bytes, w_bytes, sz_response;
while (1) {
r_bytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
if (r_bytes < 0) {
return SSH_ERROR;
}
if (strncmp(buffer, "GET /", 5))
continue;
sz_response = strlen(http_response);
w_bytes = ssh_channel_write(channel, http_response, sz_response);
if (w_bytes != sz_response) {
return SSH_ERROR;
}
return 0;
}
}
int main(void) {
ssh_session session;
ssh_channel channel;
session = connect_ssh_server();
if (session == NULL) {
return 1;
}
if (authenticate(session)) {
return 1;
}
channel = open_reverse_channel(session);
if (channel == NULL) {
fprintf(stderr, "Error opening reverse forward channel: %s\n", ssh_get_error(session));
ssh_channel_close(channel);
ssh_disconnect(session);
return 1;
}
if(forward_channel(session, channel)) {
fprintf(stderr, "Error during channel forwarding: %s\n", ssh_get_error(session));
ssh_channel_close(channel);
ssh_disconnect(session);
}
ssh_channel_send_eof(channel);
ssh_channel_close(channel);
ssh_disconnect(session);
ssh_channel_free(channel);
ssh_free(session);
return 0;
}
#include <libssh/callbacks.h>
#include <libssh/libssh.h>
#include <libssh/server.h>
#include <errno.h>
#include <poll.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/**
* @brief The default ssh user
*
*/
#define SSHD_USER "libssh"
/**
* @brief The default ssh password
*
*/
#define SSHD_PASSWORD "password"
/**
* @brief The default ssh key
*
*/
#define RSA_KEY "/Users/bilby91/.ssh/id_rsa"
/**
* @brief Bind address for sshd
*
*/
static char *listen_address = "0.0.0.0";
/**
* @brief Bind port for sshd
*
*/
static char *listen_port = "2000";
/**
* @brief libssh log level. 3 is the most verbose one
*
*/
static char *log_verbosity = "3";
/**
* @brief Authenticate the user using hardcoded user/pass
*
* @param user
* @param password
* @return 0 if verified
* @return 1 if not verified
*/
static int verify_password(const char *user, const char *password) {
if (strcmp(user, SSHD_USER))
return 1;
if (strcmp(password, SSHD_PASSWORD))
return 1;
return 0;
}
/**
* @brief Authentication callback
*
* @param session
* @param user
* @param password
* @param userdata
* @return int
*/
static int handle_authentication_request(ssh_session session, const char *user, const char *password, void *userdata) {
if (verify_password(user, password)) {
return SSH_AUTH_DENIED;
}
return SSH_AUTH_SUCCESS;
}
static int pty_request(ssh_session session, ssh_channel channel, const char *term, int x, int y, int px, int py,
void *userdata) {
printf("Allocated terminal\n");
return 0;
}
static int shell_request(ssh_session session, ssh_channel channel, void *userdata) {
printf("Allocated shell\n");
return 0;
}
struct ssh_channel_callbacks_struct channel_callbacks = {.channel_pty_request_function = pty_request,
.channel_shell_request_function = shell_request};
/**
* @brief Open channel request callback
*
* @param session
* @param userdata
* @return ssh_channel
*/
static ssh_channel handle_open_channel_request(ssh_session session, void *userdata) {
printf("FOOO\n");
ssh_channel channel = ssh_channel_new(session);
ssh_callbacks_init(&channel_callbacks);
ssh_set_channel_callbacks(channel, &channel_callbacks);
return channel;
}
/**
* @brief Service request callback
*
* @param session
* @param service
* @param userdata
* @return int
*/
static int handle_service_request(ssh_session session, const char *service, void *userdata) {
printf("HERE\n");
return 0;
}
/**
* @brief Global request callback
*
* @param session
* @param message
* @param userdata
*/
static void handle_global_request(ssh_session session, ssh_message message, void *userdata) {
ssh_message_global_request_reply_success(message, 8080);
}
struct ssh_callbacks_struct callbacks = {.userdata = NULL, .global_request_function = handle_global_request};
struct ssh_server_callbacks_struct server_cb = {.userdata = NULL,
.auth_password_function = handle_authentication_request,
.service_request_function = handle_service_request,
.channel_open_request_session_function = handle_open_channel_request};
/**
* @brief Set default configurations to ssh_bind
*
* @param sshbind
*/
static void configure_ssh_binding(ssh_bind sshbind) {
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_RSAKEY, RSA_KEY);
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDPORT_STR, listen_port);
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_BINDADDR, listen_address);
ssh_bind_options_set(sshbind, SSH_BIND_OPTIONS_LOG_VERBOSITY_STR, log_verbosity);
}
int main(int argc, char **argv) {
ssh_bind sshbind = ssh_bind_new();
ssh_session session = ssh_new();
configure_ssh_binding(sshbind);
if (ssh_bind_listen(sshbind) < 0) {
printf("Error listening to socket: %s\n", ssh_get_error(sshbind));
return 1;
}
if (ssh_bind_accept(sshbind, session) < 0) {
printf("Error accepting a connection: %s\n", ssh_get_error(sshbind));
return 1;
}
ssh_callbacks_init(&server_cb);
ssh_set_server_callbacks(session, &server_cb);
ssh_callbacks_init(&callbacks);
ssh_set_callbacks(session, &callbacks);
if (ssh_handle_key_exchange(session)) {
printf("ssh_handle_key_exchange: %s\n", ssh_get_error(session));
return 1;
}
ssh_set_auth_methods(session, SSH_AUTH_METHOD_PASSWORD);
ssh_event next_event = ssh_event_new();
ssh_event_add_session(next_event, session);
int status;
do {
status = ssh_event_dopoll(next_event, 1000);
} while (status == SSH_OK || status == SSH_AGAIN);
switch (status) {
case SSH_ERROR:
printf("Disconnecting with error:: %s\n", ssh_get_error(session));
break;
}
ssh_disconnect(session);
ssh_free(session);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment