#include <libssh2.h>
#include <libssh2_sftp.h>
#include<string>
#include <arpa/inet.h>
#include <sys/socket.h>
using std::string;
enum MSSH2ErrorCode{
socketError,
initSSH2Error,
connectError,
initSessionError,
passwordAuthenticationMethodNotAllow,
usernameOrPasswordError,
openSessionError,
requestPtyError,
openShellError,
noError
};
class MSSH2
{
private:
int sock;
int rc;
struct sockaddr_in sin;
LIBSSH2_SESSION *session;
LIBSSH2_CHANNEL *channel;
MSSH2ErrorCode initSSH2();
MSSH2ErrorCode connectSSH(const string &hostaddr);
MSSH2ErrorCode initSession();
MSSH2ErrorCode isAllowPasswordAuthenticationMethod(const string &username);
MSSH2ErrorCode userauthPassword(const string &username,const string &password);
MSSH2ErrorCode openSession();
MSSH2ErrorCode requestPty(); // 保留
MSSH2ErrorCode openShell(); // 保留
void closeChannel();
void closeSession();
public:
MSSH2();
MSSH2ErrorCode start(const string &hostaddr,const string &username,const string &password);
string execCmd(const string &cmd);
~MSSH2();
};
private中包含了一些初始化操作需要用到的函数,比如初始化ssh,初始化会话,初始化套接字等。
public中包含了启动mSSH2和执行命令的函数。
该类的使用过程是:创建一个mSSH2对象,然后start,然后execCmd即可。使用过程比较简单,但是需要提前安装libssh2。
#include "mSSH2.h"
MSSH2::MSSH2()
{
sock = socket(AF_INET, SOCK_STREAM, 0);
}
MSSH2ErrorCode MSSH2::initSSH2()
{
rc = libssh2_init(0);
if (rc != 0)
{
return MSSH2ErrorCode::initSSH2Error;
}
return MSSH2ErrorCode::noError;
}
MSSH2ErrorCode MSSH2::connectSSH(const string &hostAddr)
{
/* Ultra basic "connect to port 22 on localhost"
* Your code is responsible for creating the socket establishing the
* connection
*/
unsigned long hostaddr = inet_addr(hostAddr.c_str());
sin.sin_family = AF_INET;
sin.sin_port = htons(22);
sin.sin_addr.s_addr = hostaddr;
if (connect(sock, (struct sockaddr *)(&sin), sizeof(struct sockaddr_in)) != 0)
{
return MSSH2ErrorCode::connectError;
}
return MSSH2ErrorCode::noError;
}
MSSH2ErrorCode MSSH2::initSession()
{
/* Create a session instance */
session = libssh2_session_init();
/* 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
*/
if (libssh2_session_handshake(session, sock))
{
return MSSH2ErrorCode::initSessionError;
}
return MSSH2ErrorCode::noError;
}
MSSH2ErrorCode MSSH2::isAllowPasswordAuthenticationMethod(const string &username)
{
char *userauthlist = libssh2_userauth_list(session, username.c_str(), strlen(username.c_str()));
if (strstr(userauthlist, "password") == NULL)
{
return MSSH2ErrorCode::passwordAuthenticationMethodNotAllow;
}
return MSSH2ErrorCode::noError;
}
MSSH2ErrorCode MSSH2::userauthPassword(const string &username, const string &password)
{
if (libssh2_userauth_password(session, username.c_str(), password.c_str()))
{
return MSSH2ErrorCode::usernameOrPasswordError;
}
return MSSH2ErrorCode::noError;
}
MSSH2ErrorCode MSSH2::openSession()
{
channel = libssh2_channel_open_session(session);
if(!channel)
{
return MSSH2ErrorCode::openSessionError;
}
return MSSH2ErrorCode::noError;
}
// 弃用
MSSH2ErrorCode MSSH2::requestPty()
{
if(libssh2_channel_request_pty(channel, "vanilla")) {
return MSSH2ErrorCode::requestPtyError;
}
return MSSH2ErrorCode::noError;
}
//弃用
MSSH2ErrorCode MSSH2::openShell()
{
if(libssh2_channel_shell(channel)) {
return MSSH2ErrorCode::openShellError;
}
return MSSH2ErrorCode::noError;
}
MSSH2ErrorCode MSSH2::start(const string &hostaddr,const string &username,const string &password)
{
if(sock == -1)
{
return MSSH2ErrorCode::socketError;
}
MSSH2ErrorCode mSSH2ErrorCode = initSSH2();
if(mSSH2ErrorCode!=MSSH2ErrorCode::noError)
{
return mSSH2ErrorCode;
}
mSSH2ErrorCode = connectSSH(hostaddr);
if(mSSH2ErrorCode!=MSSH2ErrorCode::noError)
{
return mSSH2ErrorCode;
}
mSSH2ErrorCode = initSession();
if(mSSH2ErrorCode!=MSSH2ErrorCode::noError)
{
return mSSH2ErrorCode;
}
mSSH2ErrorCode = isAllowPasswordAuthenticationMethod(username);
if(mSSH2ErrorCode!=MSSH2ErrorCode::noError)
{
return mSSH2ErrorCode;
}
mSSH2ErrorCode = userauthPassword(username,password);
if(mSSH2ErrorCode!=MSSH2ErrorCode::noError)
{
return mSSH2ErrorCode;
}
mSSH2ErrorCode =openSession();
if(mSSH2ErrorCode!=MSSH2ErrorCode::noError)
{
return mSSH2ErrorCode;
}
/*
mSSH2ErrorCode =requestPty();
if(mSSH2ErrorCode!=MSSH2ErrorCode::noError)
{
return mSSH2ErrorCode;
}
mSSH2ErrorCode =openShell();
if(mSSH2ErrorCode!=MSSH2ErrorCode::noError)
{
return mSSH2ErrorCode;
}
*/
return MSSH2ErrorCode::noError;
}
string MSSH2::execCmd(const string &cmd)
{
// exec cmd
rc = libssh2_channel_exec(channel,cmd.c_str());
if(rc !=0)
{
return "";
}
// get end
char buffer[0x4000];
rc = libssh2_channel_read(channel, buffer, sizeof(buffer) );
if(rc >0)
{
return buffer;
}
else
{
return "";
}
}
void MSSH2::closeChannel()
{
int exitcode = 127;
rc = libssh2_channel_close(channel);
char *exitsignal = (char *)"none";
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\n", exitcode);
libssh2_channel_free(channel);
channel = NULL;
}
void MSSH2::closeSession()
{
libssh2_session_disconnect(session,
"Normal Shutdown, Thank you for playing");
libssh2_session_free(session);
}
MSSH2::~MSSH2()
{
if (channel)
{
closeChannel();
}
if (session)
{
closeSession();
}
close(sock);
libssh2_exit();
}
#include"mSSH2.h"
#include<iostream>
using std::cout;
int main(int argc,char *argv[])
{
MSSH2 mSSH2;
if(mSSH2.start("127.0.0.1","ubuntu","123456")!=MSSH2ErrorCode::noError)
{
cout<<"start error\n";
return 0;
}
std::cout<<mSSH2.execCmd("ls -ltr");
return 0;
}