#include <openssl/ssl.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <time.h>
#include <string.h>
#include <regex.h>
#include <libssh2.h>
//# include <netinet/in.h>
#ifdef HAVE_WINDOWS_H
# include <windows.h>
#endif
#ifdef HAVE_WINSOCK2_H
# include <winsock2.h>
#endif
/* FTP-SSL test
* -o sshssl sshssl.c -lssl -lcrypto -lssh2
*/
// Functions
void tunnel_read(int pass);
void tunnel_write(char *plaintext[]);
// Variables: core
char buffer[256];
clock_t time_start = 0;
// Variables: SSL
SSL *ssl;
SSL_METHOD *meth;
SSL_CTX *ctx;
BIO *ssl_side;
BIO *net_side;
// Variables: SSH
LIBSSH2_SESSION *test_ssh_session;
LIBSSH2_CHANNEL *test_ssh_channel;
struct hostent *test_ssh_host;
const char *ssh_hostname = "censored";
const char *test_ssh_user = "censored";
const char *test_ssh_pass = "censored";
int *test_ssh_sock;
struct sockaddr_in test_ssh_addr;
const char *remote_host = // censored
const char *local_host = "127.0.0.1";
int remote_port = 21;
int local_port = 21;
ssh_tunnel()
{
printf("----------setting up SSH \"tunnel\"----------\n");
// Setting up hostnames, IPs and ports
test_ssh_host = gethostbyname(ssh_hostname);
bzero((char *) &test_ssh_addr, sizeof(test_ssh_addr));
test_ssh_addr.sin_family = AF_INET;
bcopy((char *)test_ssh_host->h_addr, (char *)&test_ssh_addr.sin_addr.s_addr, test_ssh_host->h_length);
test_ssh_addr.sin_port = htons(22);
// Underlying SSH socket
test_ssh_sock = socket(AF_INET, SOCK_STREAM, 0);
// Connect socket to SSH host:port
if (connect(test_ssh_sock,&test_ssh_addr, sizeof(test_ssh_addr)) < 0)
printf("Couldn't connect to SSH server!\n");
else
printf("Connected to SSH server.\n");
// Setting up the SSH session for tunneling.
test_ssh_session = libssh2_session_init();
if (libssh2_session_startup(test_ssh_session, test_ssh_sock) != 0)
printf("Unable to start session.\n");
if (libssh2_userauth_password(test_ssh_session, test_ssh_user, test_ssh_pass) != 0)
printf("Bad user/pw.\n");
if (!(test_ssh_channel = libssh2_channel_open_session(test_ssh_session)))
printf("Failed to open session");
if (libssh2_channel_shell(test_ssh_channel))
printf("Failed requesting shell.\n");
// "Tunnel"
test_ssh_channel = libssh2_channel_direct_tcpip_ex(test_ssh_session, remote_host, remote_port, local_host, local_port);
if (test_ssh_channel == NULL) {
int error = libssh2_session_last_error(test_ssh_session, NULL, NULL, 0);
printf("Unable to set up \"tunnel\" channel. (%i)\n\n\n", error);
}
else
printf("SSH \"tunnel\" active.\n");
printf("-------------------DONE--------------------\n");
}
void tunnel_read(int pass)
{
// Illustration 2
bzero(buffer, 256);
libssh2_channel_read(test_ssh_channel, buffer, 255);
printf("CHANNEL_BUFFER:\t%s", buffer);
bzero(buffer, 256);
}
void tunnel_write(char *plaintext[])
{
libssh2_channel_write(test_ssh_channel, plaintext, strlen(plaintext));
}
/* Flush any data that SSL has written to the BIO, out to the network */
void ssl_wants_write(void)
{
char buf[1024];
size_t len;
while (BIO_ctrl_pending(net_side) > 0 )
{
len = BIO_read(net_side, buf, sizeof buf);
libssh2_channel_write(test_ssh_channel, buf, len);
}
}
/* SSL needs to read some data from the network to continue */
void ssl_wants_read(void)
{
char buf[1024];
size_t len;
/* First, flush out any written data - otherwise we may deadlock */
ssl_wants_write();
len = libssh2_channel_read(test_ssh_channel, buf, sizeof buf);
BIO_write(net_side, buf, len);
}
main()
{
int ret;
// Start SSH "tunnel"
ssh_tunnel();
// SSL setup
SSL_library_init();
meth = SSLv23_method();
ctx = SSL_CTX_new(meth);
ssl = SSL_new(ctx);
BIO_new_bio_pair(ssl_side, net_side);
SSL_set_bio(ssl, ssl_side, ssl_side);
// Communicate with FTP server. Get welcome note, ask for FTP server to turn on SSL encryption.
tunnel_read(0); // Reads FTP identification/welcome string
tunnel_write("AUTH SSL\n");
tunnel_read(0); // AUTH SSL successful
bzero(buffer, 256);
do {
ret = SSL_read(ssl, buffer, 255); // If necessary, SSL_read() will negotiate a TLS/SSL session, if not already explicitly performed
switch (SSL_get_error(ssl, ret))
{
case SSL_ERROR_WANT_READ:
ssl_wants_read();
continue;
case SSL_ERROR_WANT_WRITE:
ssl_wants_write();
continue;
default:
}
} while (ret < 0)
printf("SSL read:\t%s\n", buffer); // Empty
//printf("Handshake:\t%i\n", SSL_do_handshake(ssl)); // Currently -1: FATAL error.
printf("Shutting down.\n");
SSL_shutdown(ssl);
}