How to establish a simple ssh connection with c++ - c++

I am trying to make a c++ program which will connect to an ssh server (my laptop). The server is ok because I can get connected via putty. Although the program I wrote so far can not. In my code I am using the library libssh.h and for development I used visual studio 2015. The error I get is: crypt_set_algorithms2: no crypto algorithm function found for 3des-cbc
I haven't found anything so far so I hope to your help.
The code I use:
#include <libssh/libssh.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
ssh_session my_ssh_session;
int rc;
int port = 22;
int verbosity = SSH_LOG_PROTOCOL;
char *password;
// Open session and set options
my_ssh_session = ssh_new();
if (my_ssh_session == NULL)
exit(-1);
ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "192.168.1.6");
ssh_options_set(my_ssh_session, SSH_OPTIONS_USER, "john");
ssh_options_set(my_ssh_session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
ssh_options_set(my_ssh_session, SSH_OPTIONS_CIPHERS_C_S,"aes128-ctr");
//ssh_options_set(my_ssh_session, SSH_OPTIONS_PORT, &port);
// Connect to server
rc = ssh_connect(my_ssh_session);
if (rc != SSH_OK)
{
fprintf(stderr, "Error: %s\n", ssh_get_error(my_ssh_session)); //HERE IS WHERE I GET THE ERROR
ssh_free(my_ssh_session);
exit(-1);
}
// Verify the server's identity
// For the source code of verify_knowhost(), check previous example
/* if (verify_knownhost(my_ssh_session) < 0)
{
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);
exit(-1);
}
*/
// Authenticate ourselves
password = "pass";
rc = ssh_userauth_password(my_ssh_session, NULL, password);
if (rc != SSH_AUTH_SUCCESS)
{
fprintf(stderr, "Error authenticating with password: %s\n",
ssh_get_error(my_ssh_session));
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);
exit(-1);
}
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);
}

Try to use different cipher. 3des-cbc is broken and probably disabled on your server already.
There is really nice tutorial with simple session.
Removing the line makes it working for me on Ubuntu (don't know where you found it):
ssh_options_set(my_ssh_session, SSH_OPTIONS_CIPHERS_C_S,"aes128-ctr");
If not, what version of libssh are you using? Isn't it some obsolete one?

Finally got it! I removed the line
ssh_options_set(my_ssh_session, SSH_OPTIONS_CIPHERS_C_S,"aes128-ctr");
Then I used the ssh.dll from libssh v0-7.2 instead of the ssh.dll of v0-7.1 I used before. The ssh.dll is located in libssh-0.7.2\bin. If you take an error like the msvcr120d.dll is missing try to change from debug to release in visual studio.

Related

How to scp(transfer) file by a libssh?

I am trying to transfer compiled executable file (compiled code c++, that prints 'Hello World!') to openssh linux server by using library libssh(I cant use terminal scp of openssh). I know, that libssh has a scp functions to transfer file from and to remoted ssh server. However there is some errors. This is a code of scp:
void ext(const char*c){
std::cout<<c;
exit(-5);
}
int scp_do(ssh_session session);
int scp_copy(ssh_session session, ssh_scp scp);
int main(){
int p = 22;
ssh_session session = ssh_new();
if (session == NULL)
exit(-1);
ssh_options_set(session, SSH_OPTIONS_HOST, "192.168.0.106");
ssh_options_set(session, SSH_OPTIONS_PORT, &p);
ssh_options_set(session, SSH_OPTIONS_USER, "user");
int rc = ssh_connect(session);
if (rc != SSH_OK){ //if not connected - exit
ssh_disconnect(session);
ext("Error connecting");
}
rc = ssh_userauth_password(session, NULL, "passwd");
if(rc != SSH_AUTH_SUCCESS){ //if not authed - exit
ssh_disconnect(session);
ssh_free(session);
return 0;
}
scp_do(session); //copying file, main task of this code
ssh_disconnect(session);
ssh_free(session);
return 0 ;
}
int scp_do(ssh_session session){ //copying file, main task of this code
ssh_scp scp;
int rc;
scp = ssh_scp_new(session, SSH_SCP_WRITE | SSH_SCP_RECURSIVE, ".");
if (scp == NULL)
ext("Error allocating scp session");
rc = ssh_scp_init(scp);
if (rc != SSH_OK)
ext("Error initializing scp session");
char buffer[1024];
std::ifstream fin("hello"); // compiled executable file('hello world'), that I want to sent to server
rc = ssh_scp_push_file(scp, "hello", 1024, S_IRUSR | S_IWUSR); //creating server's file to copy there
if (rc != SSH_OK)
ext("Can't open remote file");
fin.get(buffer, 1024); //reading from client's file
rc = ssh_scp_write(scp, buffer, 1024); //copying all compiled code to server file
if (rc != SSH_OK)
ext("Can't write to remote file");
ssh_scp_close(scp);
ssh_scp_free(scp);
return SSH_OK;
}
When I am trying to execute a transferred file on server, Firstly, I discover it is not
executable. So I am doing chmod +x for file. Secondly, When i am executing file, I am getting error:
[1] 6867 segmentation fault ./hello
However, when I am using scp of openssh to transfer file, there's no errors and it's executable. What can I do to solve my problems?
The size of file is like
4 62 17168 hello
I was thinking it will be less 1024 bytes, bcs it's a just hello world). So, i need only to send 17168 bytes.

How to link .so file to a cpp program

I have libssh2.so.1.0.1(.so) binary on my local machine and I don't have any header files present on my machine.
This is the basic ssh program I have been trying to connect to my server through ssh protocol.
Reference: How to establish a simple ssh connection with c++
Now I am unable to link library (libssh2.so.1.0.1) to the below sample program.
Following is the sample program I have written and followed by errors.
sshsample.cpp:
#include <stdlib.h>
#include <stdio.h>
int main()
{
ssh_session my_ssh_session;
int rc;
int port = 22;
int verbosity = SSH_LOG_PROTOCOL;
char *password;
// Open session and set options
my_ssh_session = ssh_new();
if (my_ssh_session == NULL)
exit(-1);
ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "192.168.1.6");
ssh_options_set(my_ssh_session, SSH_OPTIONS_USER, "john");
ssh_options_set(my_ssh_session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
// Connect to server
rc = ssh_connect(my_ssh_session);
if (rc != SSH_OK)
{
fprintf(stderr, "Error: %s\n", ssh_get_error(my_ssh_session));
ssh_free(my_ssh_session);
exit(-1);
}
// Authenticate ourselves
password = "pass";
rc = ssh_userauth_password(my_ssh_session, NULL, password);
if (rc != SSH_AUTH_SUCCESS)
{
fprintf(stderr, "Error authenticating with password: %s\n",
ssh_get_error(my_ssh_session));
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);
exit(-1);
}
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);
}
I have compiled the above file with below command
g++ -L. -llibssh2 -o main sshsample.cpp
but I get the following error
sshsample.cpp: In function 'int main()':
sshsample.cpp:8: error: 'ssh_session' was not declared in this scope
sshsample.cpp:8: error: expected `;' before 'my_ssh_session'
sshsample.cpp:11: error: 'SSH_LOG_PROTOCOL' was not declared in this scope
sshsample.cpp:14: error: 'my_ssh_session' was not declared in this scope
sshsample.cpp:14: error: 'ssh_new' was not declared in this scope
Any suggestions/help would be of great use
Thanks in advance ...
You need to include the libssh2 header file into your compilation units where ssh APIs are invoked. You cannot expect the compiler to resolve what an ssh_session is without this. If you have the library properly installed, you should have access to the header files to invoke it.
#include <libssh2.h>
Edit: Honestly the APIs you are using in your example belong to the original libssh library I don't see anything in your example that would need to link with libssh2.
#include <libssh/libssh.h>

GetAddrInfo example from Wikipedia won't work

I've been learning how to use getaddrinfo() recently. I referred to Wikipedia for an example:
http://en.wikipedia.org/wiki/Getaddrinfo
I made some small modifications to the example code to compile it with Visual C++ 2005.
The modified version is as follows:
int main(){
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
struct addrinfo *res;
int error;
/* resolve the domain name into a list of addresses */
error = getaddrinfo("www.example.com", NULL, NULL, &result);
if (error != 0)
{
fprintf(stderr, "%d\n", error);
fprintf(stderr, "error in getaddrinfo: %s\n", gai_strerror(error));
exit(EXIT_FAILURE);
}
/* loop over all returned results and do inverse lookup */
for (res = result; res != NULL; res = res->ai_next)
{
char hostname[NI_MAXHOST] = "";
error = getnameinfo(res->ai_addr, res->ai_addrlen, hostname, NI_MAXHOST, NULL, 0, 0);
if (error != 0)
{
fprintf(stderr, "%d\n", WSAGetLastError());
fprintf(stderr, "error in getnameinfo: %s\n", gai_strerror(error));
continue;
}
if (*hostname != '\0')
printf("hostname: %s\n", hostname);
}
freeaddrinfo(result);
getchar();
return 0;
}
The execution result is surprisingly failed with a return error:WSANO_DATA.
Nevertheless, I can connect to www.example.com with Google Chrome.
I've also replaced www.example.com with other domain names in the code and done tests. Some of the results are expected while some others are strange:
test: localhost
hostname: localhost
test: www.yahoo.com.tw
hostname: w2.rc.vip.gq1.yahoo.com
hostname: w2.rc.vip.sp1.yahoo.com
The first result is as expected, but the second(www.yahoo.com.tw) is strange. I can't connect to "w2.rc.vip.gq1.yahoo.com" and "w2.rc.vip.sp1.yahoo.com" via the browser.
Could anyone explain why I got the above results and why the original example from Wikipedia didn't work? Thanks a lot.
The example and your code work just fine.
Connecting directly to the address of Yahoo's load balancer should not work as it's meant to forward your request to a front end delivery server based on the domain, subdomain and route.
You can find more info on wiki about Load balancing and how it works.
As for the error, try flushing your DNS cache before retesting. It can be done with ipconfig /flushdns on Windows.

gSoap + SSL : CRL & certificate name check

I'm developing a webservice using gSOAP with SSL support. It works fine as long as I COPY (that's it!) the code provided as gSOAP documentation. Trying to add some feature I collide with a lot of difficulties! I don't have a good knowledge of OpenSSL libraries, so I'm here to ask your help.
I should add a CRL list to check the certificate sent by the client. How can I do it? Moreover, I changed the function pointed by soap.fsslverify with this one:
int servlet_fsslverify(int ok, X509_STORE_CTX *store)
{
ok = 1;
char buf[1024];
X509 *cert = X509_STORE_CTX_get_current_cert(store);
fprintf(stderr, "SSL verify error or warning with certificate at depth %d: %s\n",
X509_STORE_CTX_get_error_depth(store),
X509_verify_cert_error_string(X509_STORE_CTX_get_error(store)));
X509_NAME_oneline(X509_get_issuer_name(cert), buf, sizeof(buf));
fprintf(stderr, "certificate issuer %s\n", buf);
X509_NAME_oneline(X509_get_subject_name(cert), buf, sizeof(buf));
fprintf(stderr, "certificate subject %s\n", buf);
/* Note: return 1 to continue, but unsafe progress will be terminated by OpenSSL */
return ok;
}
It is called everytime a client tries to authenticate. As you can see, I'm able to check the fields in client's certificate, but I really don't know how to check if the particular certificate is present or not in a CRL.
That's all, thanks a lot to everyone would be so nice to answer.
I found the solution on the internet! Sorry I don't remember where, but I'll try to find it back and I'll edit this post - credits to the solver.
Code to be inserted right after server-context creation.
X509_STORE *store;
store = SSL_CTX_get_cert_store(ServicePtr->ctx);
if (store)
{
X509_LOOKUP *lookup;
X509_STORE_set_flags(store, X509_V_FLAG_CRL_CHECK);
lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
if (lookup)
{
if ( X509_load_crl_file(lookup, globals.pki_crl, X509_FILETYPE_ASN1) < 1 )
{
std::cerr << "CRL not found or invalid" << std::endl;
}
}
else
{
std::cerr << "Unable to create a valid lookup" << std::endl;
}
}
else
{
std::cerr << "Unable to get X509_STORE" << std::endl;
}

problem of using ssh_connect API in windows

I have tested a simple code using libssh on OS X and it worked simply find.
But when I port this code on Windows7 using vc10 it doesn't work correctly.
The ssh_connect API blocks and not progress any more.
The following code is part of the my test program.
#include <libssh/libssh.h>
...
int _tmain(..)
{
ssh_session session;
session = ssh_new();
if (session == NULL)
exit(EXIT_FAILURE);
ssh_options_set(session, SSH_OPTIONS_HOST, "localhost");
int port = 1234;
ssh_options_set(session, SSH_OPTIONS_PORT, &port); // <-block here !!!
int rc = ssh_connect(session);
if (rc != SSH_OK)
{
...
}
}
I downloaded include, lib and dll files from www.libssh.org no compile and link errors.
What's wrong with my code or do I miss something important?
Maybe it blocks cause the port is wrong? The timeout is 30 min by default iirc. libssh 0.6 will have better timeout handling.