I have this function which can connect to a remote system via ssh:
std::string _ErrMsg;
int _RetVal = 0;
MyException errMsg;
int port = 22;
try
{
if (my_ssh_session == NULL) {
std::cout << "Error creating ssh session" << std::endl;
throw MyException("Error in creating session");
_RetVal = -1;
return _RetVal;
}
ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, (const void*)(authentication.ip));
ssh_options_set(my_ssh_session, SSH_OPTIONS_USER, (const void*)(authentication.userName));
ssh_options_set(my_ssh_session, SSH_OPTIONS_PORT, &port);
int rc = ssh_connect(my_ssh_session);
if (rc != SSH_OK) {
std::cout << "Error with connecting" << std::endl;
_ErrMsg = ssh_get_error(my_ssh_session);
ssh_free(my_ssh_session);
_RetVal = -2;
throw MyException(_ErrMsg);
}
rc = ssh_userauth_password(my_ssh_session, NULL, (const char*)(authentication.pw));
if (rc != SSH_AUTH_SUCCESS) {
std::cout << "Authentication failed " << ssh_get_error(my_ssh_session) << std::endl;
_ErrMsg = ssh_get_error(my_ssh_session);
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);
_RetVal = -3;
throw MyException(_ErrMsg);
}
}
catch (MyException& e)
{
throw e;
}
return _RetVal;
and this function which executes a command through ssh channel:
std::string ssh::exec_ssh_command(char* command)
{
std::string receive = "";
std::string err;
int rc, nbytes;
char buffer[2000];
MyException errMsg;
try {
my_ssh_session = ssh_new();
ssh_channel channel = ssh_channel_new(my_ssh_session);
if (channel == NULL)
{
receive = "Channel allocation failed.";
throw MyException(receive);
}
rc = ssh_channel_open_session(channel);
if (rc != SSH_OK)
{
free_channel(channel);
receive = "Opening session channel failed.";
throw MyException(receive);
}
rc = ssh_channel_request_exec(channel, command);
if (rc != SSH_OK) {
receive = "Channel's request executing failed.";
free_channel(channel);
throw MyException(receive);
}
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
receive = buffer;
if (nbytes > 0)
{
receive.erase(nbytes - 1, 2000);
}
else
{
receive = "Error in command: not found or wrong syntax";
throw MyException(receive);
}
if (nbytes < 0)
{
receive = "Error in reading data from channel ";
throw MyException(receive);
}
free_channel(channel);
free_session(my_ssh_session);
}
catch (MyException& err)
{
throw err;
}
return receive;
}
I want to throw an exception when a wrong command is sent to this function. for example, if I send this command: ls /sys/class/net | se -n - 1p. if I run this command on terminal, I got this error : se: command not found.when I run it like this : ls /sys/class/net | sed -n -s 1p | grep 'something irrelevant', it gives nothing. it gives nothing as output in both ways. and nbytes will be 0. is there any way to take that se: command not found ??
Errors are printed on the stderr channel, which is distinct from the default stdout channel.
The last argument of ssh_channel_read determines which is read: 0 for stdout, 1 for stderr.
I suggest you read from both channels by calling ssh_channel_read twice.
Related
I'm trying to sniff all TCP SYN packets received by any of my network adapters and I treid doing so by using the free npcap library available online.
You can see my code below
pcap_if_t* allNetworkDevices;
std::vector<pcap_t*> networkInterfacesHandles;
std::vector<WSAEVENT> sniffEvents;
void packet_handler(u_char* user, const struct pcap_pkthdr* header, const u_char* packet) {
cout << "here" << endl;
}
BOOL openAllInterfaceHandles()
{
char errbuf[PCAP_ERRBUF_SIZE];
pcap_t* curNetworkHandle;
if (pcap_findalldevs(&allNetworkDevices, errbuf) == -1) {
printf("Error in pcap_findalldevs: %s\n", errbuf);
return FALSE;
}
for (pcap_if_t* d = allNetworkDevices; d != NULL; d = d->next) {
//curNetworkHandle = pcap_open(d->name, 65536, PCAP_OPENFLAG_PROMISCUOUS, 1000, NULL, errbuf);
printf("%s\n", d->description);
curNetworkHandle = pcap_open_live(d->name, BUFSIZ, 1, 1000, errbuf);
if (curNetworkHandle == NULL) {
printf("Couldn't open device %s: %s\n", d->name, errbuf);
continue;
}
networkInterfacesHandles.push_back(curNetworkHandle);
// Compile and set the filter
struct bpf_program fp;
char filter_exp[] = "(tcp[tcpflags] & tcp-syn) != 0";
if (pcap_compile(curNetworkHandle, &fp, filter_exp, 1, PCAP_NETMASK_UNKNOWN) < 0) {
printf("Couldn't parse filter %s: %s\n", filter_exp, pcap_geterr(curNetworkHandle));
continue;
}
if (pcap_setfilter(curNetworkHandle, &fp) == -1) {
printf("Couldn't install filter %s: %s\n", filter_exp, pcap_geterr(curNetworkHandle));
continue;
}
// Create an event for the handle
sniffEvents.push_back(pcap_getevent(curNetworkHandle));
}
}
int main()
{
openAllInterfaceHandles();
while (TRUE)
{
DWORD result = WaitForMultipleObjects(sniffEvents.size(), sniffEvents.data(), FALSE, INFINITE);
if (result == WAIT_FAILED) {
printf("Error in WaitForMultipleObjects: %d\n", GetLastError());
break;
}
// Dispatch packets for the handle associated with the triggered event
int index = result - WAIT_OBJECT_0;
pcap_dispatch(networkInterfacesHandles[index], -1, &packet_handler, NULL);
if (cond)
{
cout << "done" << endl;
break;
}
}
while (!networkInterfacesHandles.empty())
{
pcap_close(networkInterfacesHandles.back());
networkInterfacesHandles.pop_back();
}
pcap_freealldevs(allNetworkDevices);
return 0;
}
cond is some condition I'm using which is irrelevant to the problem.
For some reason it won't go into the packet_handler even when I receive TCP SYN packets (which I check by using Wireshark) and I tried sending them either via the loopback and also from another PC in the same LAN.
Any help to find the problem would be greatly appreciated.
I have these class that I had mentioned in this question : catch in exception handling doesn't stop program and these is the coreNumbers functions that I had in there :
std::string info::coreNumbers()
{
int retValue;
std::string cpuSpeed = "";
getSSHState();
try {
num = exec_ssh_command(my_ssh_session, "ca /pro/cpuinfo | grep processor");
}
catch (MyException &err)
{
//exit(0);
throw err;
}
return num;
}
I have written "ca" in command on purpose. to get error and exception thrown. and these is my exec_ssh_command function :
std::string info::exec_ssh_command(ssh_session session, char *command) {
std::string receive = "";
int rc, nbytes;
char buffer[2000];
MyException errMsg;
try {
ssh_channel channel = ssh_channel_new(session);
if (channel == NULL)
{
receive = "Channel allocation failed.";
errMsg = MyException(receive);
throw errMsg;
}
rc = ssh_channel_open_session(channel);
if (rc != SSH_OK)
{
ssh_channel_free(channel);
receive = "Opening session channel failed.";
errMsg = MyException(receive);
throw errMsg;
}
rc = ssh_channel_request_exec(channel, command);
if (rc != SSH_OK) {
receive = "Channel's request executing failed.";
errMsg = MyException(receive);
ssh_channel_close(channel);
ssh_channel_free(channel);
throw errMsg;
}
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
receive = buffer;
if (nbytes > 0)
{
receive.erase(nbytes - 1, 2000);
}
else
{
receive = "Error in command: not found or wrong syntax";
errMsg = MyException(receive);
throw errMsg;
}
while (nbytes > 0)
{
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
}
if (nbytes < 0)
{
receive = "Error in reading data from channel. ";
errMsg = MyException(receive);
throw errMsg;
}
ssh_channel_send_eof(channel);
ssh_channel_close(channel);
ssh_channel_free(channel);
}
catch (MyException &err)
{
// std::cerr << err.what()<<flush;
throw err;
}
return receive;
}
when I run my code, I got unhandled exception in the throw that I have in coreNumbers function. after the exception in exec_ssh_command is thrown. am I misunderstood and using something wrong here?
I have this function which if you connect to a system with ssh, you can call it to execute your given command on that system.
std::string sshconnection::exec_ssh_command(ssh_session session, char *command) {
string receive = "";
int rc, nbytes;
char buffer[256];
ssh_channel channel = ssh_channel_new(session);
if( channel == NULL )
return NULL;
rc = ssh_channel_open_session(channel);
if( rc != SSH_OK ) {
ssh_channel_free(channel);
return NULL;
}
rc = ssh_channel_request_exec(channel, command);
if( rc != SSH_OK ) {
ssh_channel_close(channel);
ssh_channel_free(channel);
cout << "Error";
return NULL;
}
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
while (nbytes > 0)
{
if (write(1, buffer, nbytes) != (unsigned int) nbytes)
{
ssh_channel_close(channel);
ssh_channel_free(channel);
return NULL;
}
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
}
if( nbytes < 0 )
return NULL;
ssh_channel_send_eof(channel);
ssh_channel_close(channel);
ssh_channel_free(channel);
return receive;
}
this function works great. I just don't understand that part which is about to write from buffer into a file descriptor=1 . we haven't filled receive anywhere but it is the return value. if we call this function like below:
s = exec_ssh_command(my_ssh_session, "cat /proc/stat" );
the s won't have any value, but if we do this:
std::cout<<s;
this will print s value. and of course we can't save s in a file. can someone explain to me how is this happening?
EDIT:function to connect to ssh:
int sshconnection::sshConnection()
{
if( my_ssh_session == NULL ) {
cout << "Error creating ssh session" << endl;
return 1;
}
ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "yourip");
ssh_options_set(my_ssh_session, SSH_OPTIONS_USER, "username");
int rc = ssh_connect(my_ssh_session);
if( rc != SSH_OK ) {
cout << "Error with connecting" << endl;
ssh_free(my_ssh_session);
return -1;
}
rc = ssh_userauth_password(my_ssh_session, NULL, "yourpassword");
if( rc != SSH_AUTH_SUCCESS) {
cout << "Error with authorization " << ssh_get_error(my_ssh_session) << endl;
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);
return -1;
}
// ssh_disconnect(my_ssh_session);
// ssh_free(my_ssh_session);
}
I know this is old, but I had the same issue. I came up with the following solution.
Use std::string::append like so receive.append(buffer, nbytes).
std::string sshconnection::exec_ssh_command(ssh_session session, char *command) {
string receive = "";
int rc, nbytes;
char buffer[256];
ssh_channel channel = ssh_channel_new(session);
if( channel == NULL )
return NULL;
rc = ssh_channel_open_session(channel);
if( rc != SSH_OK ) {
ssh_channel_free(channel);
return NULL;
}
rc = ssh_channel_request_exec(channel, command);
if( rc != SSH_OK ) {
ssh_channel_close(channel);
ssh_channel_free(channel);
cout << "Error";
return NULL;
}
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
while (nbytes > 0)
{
receive.append(buffer, nbytes);
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
}
if( nbytes < 0 )
return NULL;
ssh_channel_send_eof(channel);
ssh_channel_close(channel);
ssh_channel_free(channel);
return receive;
}
When I'm trying to run command on server (router) I get
[C] Jan 3 05:32:16 ndm: bin::ndmc: invalid option "-c".
Most of the code is taken from the documentation.
There is the code:
#include <iostream>
#include <string.h>
#include <libssh/libssh.h>
using std::string;
using std::cout;
using std::endl;
using std::cin;
string exec_ssh_command(ssh_session
session, char *command) {
string receive = "";
int rc, nbytes;
char buffer[256];
ssh_channel channel = ssh_channel_new(session);
if( channel == NULL )
return NULL;
rc = ssh_channel_open_session(channel);
if( rc != SSH_OK ) {
ssh_channel_free(channel);
return NULL;
}
rc = ssh_channel_request_exec(channel, command);
if( rc != SSH_OK ) {
ssh_channel_close(channel);
ssh_channel_free(channel);
cout << "Error";
return NULL;
}
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
while (nbytes > 0)
{
if (write(1, buffer, nbytes) != (unsigned int) nbytes)
{
ssh_channel_close(channel);
ssh_channel_free(channel);
return NULL;
}
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
}
if( nbytes < 0 )
return NULL;
ssh_channel_send_eof(channel);
ssh_channel_close(channel);
ssh_channel_free(channel);
return receive;
}
int main() {
ssh_session my_ssh_session = ssh_new();
if( my_ssh_session == NULL ) {
cout << "Error creating ssh session" << endl;
return 1;
}
ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "192.168.1.1");
ssh_options_set(my_ssh_session, SSH_OPTIONS_USER, "admin");
int rc = ssh_connect(my_ssh_session);
if( rc != SSH_OK ) {
cout << "Error with connecting" << endl;
ssh_free(my_ssh_session);
return -1;
}
rc = ssh_userauth_password(my_ssh_session, NULL, "pass");
if( rc != SSH_AUTH_SUCCESS) {
cout << "Error with authorization " << ssh_get_error(my_ssh_session) << endl;
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);
return -1;
}
string ip_hotspot = exec_ssh_command(my_ssh_session, "show ip hotspot");
cout << ip_hotspot << endl;
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);
return 0;
}
My router is zyxel keenetic ultra.
uname -a: Linux localhost 4.9.112-perf-gfb7749d #1 SMP PREEMPT Thu Dec 6 16:06:30 WIB 2018 aarch64 Android
g++ -v:
clang version 7.0.1 (tags/RELEASE_701/final)
Target: aarch64--linux-android
Thread model: posix
I'm a beginner at libssh so please explain easier. :)
Thank you in advance!
It was fixed. On version 3.3.2 of Keenetic OS it works fine.
I'm trying to get the output of the command 'df' which I'll replace later, from a remote server:
#include <libssh/libssh.h>
#include <stdlib.h>
#include <stdio.h>
int main()
{
ssh_session my_ssh_session;
int rc;
ssh_channel channel;
char buffer[256];
int nbytes;
int port = 22;
my_ssh_session = ssh_new();
if (my_ssh_session == NULL)
exit(-1);
ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "192.168.2.2");
ssh_options_set(my_ssh_session, SSH_OPTIONS_PORT, &port);
rc = ssh_connect(my_ssh_session);
if (rc != SSH_OK)
{
fprintf(stderr, "Failed %s\n",
ssh_get_error(my_ssh_session));
exit(-1);
}
channel = ssh_channel_new(my_ssh_session);
if (channel == NULL)
return SSH_ERROR;
rc = ssh_channel_open_session(channel);
if (rc != SSH_OK)
{
ssh_channel_free(channel);
return rc;
}
rc = ssh_channel_request_exec(channel, "df");
if (rc != SSH_OK)
{
ssh_channel_close(channel);
ssh_channel_free(channel);
return rc;
}
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
while (nbytes > 0)
{
if (write(1, buffer, nbytes) != nbytes)
{
ssh_channel_close(channel);
ssh_channel_free(channel);
return SSH_ERROR;
}
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
}
if (nbytes < 0)
{
ssh_channel_close(channel);
ssh_channel_free(channel);
return SSH_ERROR;
}
ssh_channel_send_eof(channel);
ssh_channel_close(channel);
ssh_channel_free(channel);
return SSH_OK;
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);
}
The compiler didn't show any errors,
but there were no results when I run the program,
I checked the syslog of the remote server and I found the following line:
sshd[12794]: dispatch_protocol_error: type 90 seq 3
Please advise what could be the problem,
Thank you.
It seems like you are trying to get to the remote server without functions of host authentification (e.g. checking information from /.ssh/known_hosts) and user authentificationa through public keys or password. You should place these two functions after the
if (rc != SSH_OK)
{
fprintf(stderr, "Failed %s\n", ssh_get_error(my_ssh_session));
exit(-1);
}
Look through the chapters 1 and 2 in libssh tutorial.