Dean Dean - 5 months ago 77
Linux Question

Libssh2 session through SOCKS 5 in C (Linux)

I'd like to create libssh2 session through SOCKS 5 in C (Linux).

I'm trying to connect STREAM socket to the SOCKS 5 server, then after the connection is created, use this pre-connected socket to initialize the libssh2 session, but I got an error:

Failure establishing SSH session: -13


It means (https://github.com/libssh2/libssh2/blob/master/include/libssh2.h):

#define LIBSSH2_ERROR_SOCKET_DISCONNECT -13


Finally, I enabled libssh2_trace - https://www.libssh2.org/libssh2_trace.html

// Debug libssh2
libssh2_trace(session, LIBSSH2_TRACE_SOCKET);


I got:

res = -1
10.10.10.10:22 open
Step 1
Numbytes = 2
Client: received '5' 0'
Step 2
numbytes = 4
Received: 5 0 0 1
Numbytes = 4
Client: received '5' '0' '0' 1'
Case 1
Data Send

numbytes = 32
Received: SSH-2.0-OpenSSH_7.2p2 Debian-5
Start ssh
[libssh2] 0.254995 Socket: Sent 23/23 bytes at 0x7fb75655f49d+0
[libssh2] 0.314917 Socket: Recved 0 bytes banner
Failure establishing SSH session: -13


My code:



// Create a socket
soc = socket(AF_INET, SOCK_STREAM, 0);

// Connect it to the SOCKS 5 server
....

// Use the pre-connected socket
while ((rc = libssh2_session_handshake(session, soc)) == LIBSSH2_ERROR_EAGAIN);

if (rc) {
fprintf(stderr, "Failure establishing SSH session: %d\n", rc);
return -1;
}


My full code:



#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <unistd.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <errno.h>
#include <ctype.h>
#include <sys/time.h>
#include "libssh2_config.h"
#include <libssh2.h>

#define PUT_BYTE(ptr,data) (*(unsigned char*)ptr = data)

static int waitsocket(int socket_fd, LIBSSH2_SESSION *session)
{
struct timeval timeout;
int rc;
fd_set fd;
fd_set *writefd = NULL;
fd_set *readfd = NULL;
int dir;

timeout.tv_sec = 10;
timeout.tv_usec = 0;

FD_ZERO(&fd);

FD_SET(socket_fd, &fd);

/* now make sure we wait in the correct direction */
dir = libssh2_session_block_directions(session);


if(dir & LIBSSH2_SESSION_BLOCK_INBOUND)
readfd = &fd;

if(dir & LIBSSH2_SESSION_BLOCK_OUTBOUND)
writefd = &fd;

rc = select(socket_fd + 1, readfd, writefd, NULL, &timeout);

return rc;
}


int sshconnect(char *hostname, int portno, int intreval_sec, char *login, char *pass, int sshwait, int issocks, int retry) {

int res, dest_port, valopt, numbytes, timeouts = 0;
struct sockaddr_in addr, saddr, destaddr;
long arg;
fd_set myset;
struct timeval tv;
socklen_t lon;
dest_port = portno;

int soc;
//printf("hostname = %s\n",hostname);

// Create socket
soc = socket(AF_INET, SOCK_STREAM, 0);
if (soc < 0) {
//fprintf(fp, " %s:%d Error creating socket (%d %s)\n", hostname, portno, errno, strerror(errno));
printf(" %s:%d Error creating socket (%d %s)\n", hostname, portno, errno, strerror(errno));
//exit(0);

/* close the socket */
close(soc);
return 1;
}

destaddr.sin_family = AF_INET;
destaddr.sin_port = htons(portno);
//addr.sin_addr.s_addr = inet_addr("193.110.77.13");
destaddr.sin_addr.s_addr = inet_addr(hostname);

// SOCKS TOR
addr.sin_port = htons(9050);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("127.0.0.1");

// Set non-blocking
if ((arg = fcntl(soc, F_GETFL, NULL)) < 0) {
//fprintf(fp, " %s:%d Error fcntl(..., F_GETFL) (%s)\n", hostname, portno, strerror(errno));
printf(" %s:%d Error fcntl(..., F_GETFL) (%s)\n", hostname, portno, strerror(errno));
//exit(0);

// close the socket
close(soc);
return 2;
}
arg |= O_NONBLOCK;
if (fcntl(soc, F_SETFL, arg) < 0) {
//fprintf(fp, " %s:%d Error fcntl(..., F_SETFL) (%s)\n", hostname, portno, strerror(errno));
printf(" %s:%d Error fcntl(..., F_SETFL) (%s)\n", hostname, portno, strerror(errno));
//exit(0);

// close the socket
close(soc);
return 3;
}

// Trying to connect with timeout
res = connect(soc, (struct sockaddr * ) & addr, sizeof(addr));
//res = connect(soc, (struct sockaddr * ) & destaddr, sizeof(destaddr));

printf("res = %d\n", res);
if (res < 0) {
if (errno == EINPROGRESS) {
//fprintf(stderr, "EINPROGRESS in connect() - selecting\n");
do {
//tv.tv_sec = 5;
tv.tv_sec = intreval_sec;
tv.tv_usec = 0;
FD_ZERO( & myset);
FD_SET(soc, & myset);
res = select(soc + 1, NULL, & myset, NULL, & tv);
if (res < 0 && errno != EINTR) {
//fprintf(fp, " %s:%d Error connecting %d - %s\n", hostname, portno, errno, strerror(errno));
printf(" %s:%d Error connecting %d - %s\n", hostname, portno, errno, strerror(errno));
//exit(0);

/* close the socket */
close(soc);
return 4;
} else if (res > 0) {
// Socket selected for write
lon = sizeof(int);
if (getsockopt(soc, SOL_SOCKET, SO_ERROR, (void * )( & valopt), & lon) < 0) {
//fprintf(fp, " %s:%d Error in getsockopt() %d - %s\n", hostname, portno, errno, strerror(errno));
printf(" %s:%d Error in getsockopt() %d - %s\n", hostname, portno, errno, strerror(errno));
//exit(0);

// close the socket
close(soc);
return 5;
}
// Check the value returned...
if (valopt) {
//fprintf(fp, " %s:%d Error in delayed connection() %d - %s\n", hostname, portno, valopt, strerror(valopt));
printf(" %s:%d Error in delayed connection() %d - %s\n", hostname, portno, valopt, strerror(valopt));
//exit(0);

// close the socket
close(soc);
return 6;
}
//fprintf(fp," %s:%d open\n", hostname, portno);
printf(" %s:%d open\n", hostname, portno);

break;
} else {
//fprintf(fp, " %s:%d Timeout\n", hostname, portno);
printf(" %s:%d Timeout\n", hostname, portno);
//exit(0);

/* close the socket */
close(soc);
return 7;
}
} while (1);
} else {
//fprintf(fp, " %s:%d Error connecting %d - %s\n", hostname, portno, errno, strerror(errno));
printf(" %s:%d Error connecting %d - %s\n", hostname, portno, errno, strerror(errno));
//exit(0);

/* close the socket */
close(soc);
return 8;
}
}

// Set to blocking mode again...
if ((arg = fcntl(soc, F_GETFL, NULL)) < 0) {
//fprintf(fp, " %s:%d Error fcntl(..., F_GETFL) (%s)\n", hostname, portno, strerror(errno));
printf(" %s:%d Error fcntl(..., F_GETFL) (%s)\n", hostname, portno, strerror(errno));
//exit(0);

/* close the socket */
close(soc);
return 9;
}
arg &= (~O_NONBLOCK);
if (fcntl(soc, F_SETFL, arg) < 0) {
//fprintf(fp, " %s:%d Error fcntl(..., F_SETFL) (%s)\n", hostname, portno, strerror(errno));
printf(" %s:%d Error fcntl(..., F_SETFL) (%s)\n", hostname, portno, strerror(errno));
//exit(0);

/* close the socket */
close(soc);
return 10;
}

printf("Step 1\n");

char buf[256], * ptr;
ptr = buf;
PUT_BYTE(ptr++, 5);
PUT_BYTE(ptr++, 1);
PUT_BYTE(ptr++, 0x00);
send(soc, buf, ptr - buf, 0);
//recv(fd,buf,2,0);
if ((numbytes = recv(soc, buf, 2, 0)) == -1) {
perror("recv");
exit(1);
}
printf(" Numbytes = %d\n", numbytes);
printf(" Client: received '%d' %d'\n", buf[0], buf[1]);

if ((buf[0] != 5) || buf[1] == 0xFF) {
return 1;
}

printf("Step 2\n");

ptr = buf;
PUT_BYTE(ptr++, 5);
PUT_BYTE(ptr++, 1);
PUT_BYTE(ptr++, 0);
PUT_BYTE(ptr++, 1);
memcpy(ptr, & destaddr.sin_addr.s_addr, sizeof(destaddr.sin_addr));
ptr += sizeof(destaddr.sin_addr);
PUT_BYTE(ptr++, dest_port >> 8);
PUT_BYTE(ptr++, dest_port & 0xFF);
send(soc, buf, ptr - buf, 0);
//recv(fd,buf,4,0);

// Set the time out
struct timeval tv_recv;

tv_recv.tv_sec = intreval_sec; // 30 Secs Timeout
tv_recv.tv_usec = 0; // Not init'ing this can cause strange errors

if (setsockopt(soc, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv_recv, sizeof(struct timeval)) < 0) {
perror("Error");
}

// Continuous
//if ((numbytes = recv(soc, buf, 4, 0)) == -1) {
//perror("recv");
//exit(1);
//}

while (((numbytes = recv(soc, buf, 4, 0)) == -1) && (++timeouts <= retry) && (buf[1] != 0)) { // loop to retry in case it timed out; added by davekw7x
perror("recv");
printf("After timeout #%d, trying again:\n", timeouts);
}
printf("numbytes = %d\n", numbytes);
buf[numbytes] = '\0';
printf("Received: %d %d %d %d\n", buf[0], buf[1], buf[2], buf[3]);

if (buf[1] != 0x00) {
return 1;
}
printf(" Numbytes = %d\n", numbytes);
printf(" Client: received '%d' '%d' '%d' %d'\n", buf[0], buf[1], buf[2], buf[3]);

ptr = buf + 4;
switch (buf[3]) {
case 1:
recv(soc, ptr, 4 + 2, 0);
printf("Case 1\n");

break;
case 3:
recv(soc, ptr, 1, 0);
recv(soc, ptr + 1, * (unsigned char * ) ptr + 2, 0);
printf("Case 2\n");

break;
case 4:
recv(soc, ptr, 16 + 2, 0);
printf("Case 3\n");

break;
}

//Send some data
char * message, server_reply[2000];

//message = "GET / HTTP/1.1\r\n\r\n";
message = "GET / HTTP/1.0\r\n\r\n";
if (send(soc, message, strlen(message), 0) < 0) {
puts("Send failed");
return 1;
}
puts("Data Send\n");

char second_symbol = ' ';
while (((numbytes = recv(soc, server_reply, 2000, 0)) == -1) && (++timeouts < retry)) { // loop to retry in case it timed out; added by davekw7x
perror("recv");
printf("After timeout #%d, trying again:\n", timeouts);
}
printf("numbytes = %d\n", numbytes);
server_reply[numbytes] = '\0';
printf("Received: %s", server_reply); //- See more at: https:www.gidforums.com/t-16791.html#sthash.4bFv5mY8.dpu

/**/
//////////////////////////////
// Start ssh
//////////////////////////////
/*// Set non-blocking
if ((arg = fcntl(soc, F_GETFL, NULL)) < 0) {
//fprintf(fp, " %s:%d Error fcntl(..., F_GETFL) (%s)\n", hostname, portno, strerror(errno));
printf(" %s:%d Error fcntl(..., F_GETFL) (%s)\n", hostname, portno, strerror(errno));
//exit(0);

// close the socket
close(soc);
return 2;
}
arg |= O_NONBLOCK;
if (fcntl(soc, F_SETFL, arg) < 0) {
//fprintf(fp, " %s:%d Error fcntl(..., F_SETFL) (%s)\n", hostname, portno, strerror(errno));
printf(" %s:%d Error fcntl(..., F_SETFL) (%s)\n", hostname, portno, strerror(errno));
//exit(0);

// close the socket
close(soc);
return 3;
}*/

printf("Start ssh\n");

const char *hostname_ssh = "10.10.10.10";
const char *commandline = "ls";
const char *username = "root";
const char *password = "root";
unsigned long hostaddr;
struct sockaddr_in sin;
const char *fingerprint;
LIBSSH2_SESSION *session;
LIBSSH2_CHANNEL *channel;
int rc;
int exitcode;
char *exitsignal=(char *)"none";
int bytecount = 0;
size_t len;
LIBSSH2_KNOWNHOSTS *nh;
int type;

rc = libssh2_init (0);

if (rc != 0) {
fprintf (stderr, "libssh2 initialization failed (%d)\n", rc);
return 1;
}

/* Create a session instance */
session = libssh2_session_init();

// Debug libssh2
libssh2_trace(session, LIBSSH2_TRACE_SOCKET);

if (!session)
return -1;

/* tell libssh2 we want it all done non-blocking */
libssh2_session_set_blocking(session, 0);

/* ... start it up. This will trade welcome banners, exchange keys,
* and setup crypto, compression, and MAC layers
*/
while ((rc = libssh2_session_handshake(session, soc)) == LIBSSH2_ERROR_EAGAIN);

if (rc) {
fprintf(stderr, "Failure establishing SSH session: %d\n", rc);
return -1;
}
printf("Start session 6\n");

nh = libssh2_knownhost_init(session);

if(!nh) {
/* eeek, do cleanup here */
return 2;
}

/* read all hosts from here */
libssh2_knownhost_readfile(nh, "known_hosts",
LIBSSH2_KNOWNHOST_FILE_OPENSSH);

/* store all known hosts to here */
libssh2_knownhost_writefile(nh, "dumpfile",
LIBSSH2_KNOWNHOST_FILE_OPENSSH);

fingerprint = libssh2_session_hostkey(session, &len, &type);

if(fingerprint) {
struct libssh2_knownhost *host;
#if LIBSSH2_VERSION_NUM >= 0x010206
/* introduced in 1.2.6 */
int check = libssh2_knownhost_checkp(nh, hostname, 22,
fingerprint, len,
LIBSSH2_KNOWNHOST_TYPE_PLAIN|
LIBSSH2_KNOWNHOST_KEYENC_RAW,
&host);
#else
/* 1.2.5 or older */
int check = libssh2_knownhost_check(nh, hostname,
fingerprint, len,
LIBSSH2_KNOWNHOST_TYPE_PLAIN|
LIBSSH2_KNOWNHOST_KEYENC_RAW,
&host);
#endif
fprintf(stderr, "Host check: %d, key: %s\n", check,
(check <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH)?
host->key:"<none>");

/*****
* At this point, we could verify that 'check' tells us the key is
* fine or bail out.
*****/
}
else {
/* eeek, do cleanup here */
return 3;
}
libssh2_knownhost_free(nh);

if ( strlen(password) != 0 ) {
/* We could authenticate via password */
while ((rc = libssh2_userauth_password(session, username, password)) ==
LIBSSH2_ERROR_EAGAIN);
if (rc) {
fprintf(stderr, "Authentication by password failed.\n");
goto shutdown;
}
}
else {
/* Or by public key */
while ((rc = libssh2_userauth_publickey_fromfile(session, username,
"/home/user/"
".ssh/id_rsa.pub",
"/home/user/"
".ssh/id_rsa",
password)) ==
LIBSSH2_ERROR_EAGAIN);
if (rc) {
fprintf(stderr, "\tAuthentication by public key failed\n");
goto shutdown;
}
}

#if 0
libssh2_trace(session, ~0 );
#endif

/* Exec non-blocking on the remove host */
while( (channel = libssh2_channel_open_session(session)) == NULL &&
libssh2_session_last_error(session,NULL,NULL,0) ==
LIBSSH2_ERROR_EAGAIN )
{
waitsocket(soc, session);
}
if( channel == NULL )
{
fprintf(stderr,"Error\n");
exit( 1 );
}
while( (rc = libssh2_channel_exec(channel, commandline)) ==
LIBSSH2_ERROR_EAGAIN )
{
waitsocket(soc, session);
}
if( rc != 0 )
{
fprintf(stderr,"Error\n");
exit( 1 );
}
for( ;; )
{
/* loop until we block */
int rc;
do
{
char buffer[0x4000];
rc = libssh2_channel_read( channel, buffer, sizeof(buffer) );

if( rc > 0 )
{
int i;
bytecount += rc;
fprintf(stderr, "We read:\n");
for( i=0; i < rc; ++i )
fputc( buffer[i], stderr);
fprintf(stderr, "\n");
}
else {
if( rc != LIBSSH2_ERROR_EAGAIN )
/* no need to output this for the EAGAIN case */
fprintf(stderr, "libssh2_channel_read returned %d\n", rc);
}
}
while( rc > 0 );

/* this is due to blocking that would occur otherwise so we loop on
this condition */
if( rc == LIBSSH2_ERROR_EAGAIN )
{
waitsocket(soc, session);
}
else
break;
}
exitcode = 127;
while( (rc = libssh2_channel_close(channel)) == LIBSSH2_ERROR_EAGAIN )
waitsocket(soc, session);

if( rc == 0 )
{
exitcode = libssh2_channel_get_exit_status( channel );

libssh2_channel_get_exit_signal(channel, &exitsignal,
NULL, NULL, NULL, NULL, NULL);
}

if (exitsignal)
fprintf(stderr, "\nGot signal: %s\n", exitsignal);
else
fprintf(stderr, "\nEXIT: %d bytecount: %d\n", exitcode, bytecount);

libssh2_channel_free(channel);

channel = NULL;

shutdown:

libssh2_session_disconnect(session,
"Normal Shutdown, Thank you for playing");
libssh2_session_free(session);

fprintf(stderr, "all done\n");

libssh2_exit();

/* close the socket */
close(soc);

return 0;
}

int main(int argc, char * argv[]) {

printf("argc=%d\n", argc);
if (argc != 9) {
fprintf(stderr, "usage: client hostname port intreval_sec login pass waittime issocks retry\n");
exit(1);
} else {
sshconnect(argv[1], atoi(argv[2]), atoi(argv[3]), argv[4], argv[5], atoi(argv[6]), atoi(argv[7]), atoi(argv[8]));
}

return 0;
}

Answer

Just comment this code and everything will be working fine:

//Send some data
char * message, server_reply[2000];

//message = "GET / HTTP/1.1\r\n\r\n";
message = "GET / HTTP/1.0\r\n\r\n";
if (send(soc, message, strlen(message), 0) < 0) {
    puts("Send failed");
    return 1;
}
puts("Data Send\n");

char second_symbol = ' ';
while (((numbytes = recv(soc, server_reply, 2000, 0)) == -1) && (++timeouts < retry)) { // loop to retry in case it timed out; added by davekw7x
    perror("recv");
    printf("After timeout #%d, trying again:\n", timeouts);
}
printf("numbytes = %d\n", numbytes);
server_reply[numbytes] = '\0';
printf("Received: %s", server_reply);

You are sending HTTP GET request to the ssh server :)