#include "FtSshTool.h"
#include <libssh2.h>
#include "FtSshChannel.h"
#include <libssh2.h>
#include <libssh2_sftp.h>
#ifdef WIN32
#include <windows.h>
#include <winsock2.h>
#else
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#include <arpa/inet.h>
#endif
#include <sys/stat.h>
#include <iostream>
#include <string>
#include <sys/types.h>
#include <fcntl.h>
#include <errno.h>
#include <stdio.h>
#include <ctype.h>
#include <filesystem>
#include <libssh2.h>
#include <libssh2_sftp.h>
#define _CRT_SECURE_NO_WARNINGS
FtSshTool::FtSshTool(std::string srvIp, int srvPort)
:m_srvIp(srvIp), m_srvPort(srvPort)
{
m_sock = -1;
m_session = NULL;
SetConsoleOutputCP(65001); //65001 是设置UTF编码
}
FtSshTool::~FtSshTool(void)
{
Disconnect();
libssh2_exit();
}
//void FtSshTool::S_KbdCallback(const char* name, int name_len,
// const char* instruction, int instruction_len,
// int num_prompts,
// const LIBSSH2_USERAUTH_KBDINT_PROMPT* prompts,
// LIBSSH2_USERAUTH_KBDINT_RESPONSE* responses,
// void** abstract)
//{
// (void)name;
// (void)name_len;
// (void)instruction;
// (void)instruction_len;
// if (num_prompts == 1)
// {
// // responses[0].text = strdup(s_password.c_str());
// // responses[0].length = (int)s_password.size();
// }
// (void)prompts;
// (void)abstract;
//}
bool FtSshTool::Connect(std::string userName, std::string userPwd)
{
//WSAData wsdData;
//int wsaRes = WSAStartup(MAKEWORD(2, 2), &wsdData);
//if (wsaRes != 0)
//{
// printf("0000");
//}
m_sock = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(22);
sin.sin_addr.s_addr = inet_addr(m_srvIp.c_str());
if (connect(m_sock, (sockaddr*)(&sin), sizeof(sockaddr_in)) != 0)
{
Disconnect();
return false;
}
// 初始化libssh2库
//flag 默认初始化选项
int rc = libssh2_init(0);
m_session = libssh2_session_init();
if (libssh2_session_handshake(m_session, m_sock))//会话握手
{
Disconnect();
return false;
}
// libssh2_session_set_blocking(m_session, 0); // 0非阻塞模式 1// 阻塞模式
int auth_pw = 0;
std::string fingerprint = libssh2_hostkey_hash(m_session, LIBSSH2_HOSTKEY_HASH_SHA1);
/* check what authentication methods are available */
std::string userauthlist = libssh2_userauth_list(m_session, userName.c_str(), (int)userName.size());
if (strstr(userauthlist.c_str(), "password") != NULL)
{
auth_pw |= 1;
}
if (strstr(userauthlist.c_str(), "keyboard-interactive") != NULL)
{
auth_pw |= 2;
}
if (strstr(userauthlist.c_str(), "publickey") != NULL)
{
auth_pw |= 4;
}
if (auth_pw & 1)
{
/* We could authenticate via password */
// 使用用户名和密码进行身份验证
if (libssh2_userauth_password(m_session, userName.c_str(), userPwd.c_str()))
{
Disconnect();
return false;
}
}
else if (auth_pw & 2)
{
/* Or via keyboard-interactive */
// s_password = userPwd;
/* if (libssh2_userauth_keyboard_interactive(m_session, userName.c_str(), &S_KbdCallback))
{
Disconnect();
return false;
}*/
}
else
{
Disconnect();
return false;
}
return true;
}
int FtSshTool::Connect(std::string srvIp, std::string userName, std::string userPwd)
{
//WSAData wsdData;
//int wsaRes = WSAStartup(MAKEWORD(2, 2), &wsdData);
//if (wsaRes != 0)
//{
// printf("0000");
//}
m_sock = socket(AF_INET, SOCK_STREAM, 0);
if (m_sock < 0) {
std::cerr << "Cannot create socket" << std::endl;
return -5;
}
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(22);
sin.sin_addr.s_addr = inet_addr(srvIp.c_str());
if (connect(m_sock, (sockaddr*)(&sin), sizeof(sockaddr_in)) != 0)
{
std::cout << "connect Failed " << std::endl;
Disconnect();
return -3;
}
// 初始化libssh2库
//flag 默认初始化选项
int rc = libssh2_init(0);
if (rc != 0) {
Disconnect();
return -1; // 初始化失败
}
// 创建SSH会话
m_session = libssh2_session_init();
if (!m_session) {
Disconnect();
return -2; // 创建会话失败
}
// 设置会话选项
libssh2_session_set_blocking(m_session, 1);// 0非阻塞模式 1// 阻塞模式
libssh2_session_set_timeout(m_session,30*1000);
// 连接到远程主机
rc = libssh2_session_startup(m_session, m_sock);
if (rc != 0) {
// 连接失败
Disconnect();
return -3;
}
// 使用用户名和密码进行身份验证(用户名和密码)
rc = libssh2_userauth_password(m_session, userName.c_str(), userPwd.c_str());
if (rc != 0) {
// 身份验证失败
libssh2_session_disconnect(m_session, "Authentication failed");
libssh2_session_free(m_session);
Disconnect();
return -4;
}
return 0;
}
int FtSshTool::Connect(std::string localIp, std::string srvIp, std::string userName, std::string userPwd)
{
// 很重要,否则m_sock 创建失败
//WSAData wsdData;
//int wsaRes = WSAStartup(MAKEWORD(2, 2), &wsdData);
//if (wsaRes != 0)
//{
// printf("0000");
//}
m_sock = socket(AF_INET, SOCK_STREAM, 0);
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(22);
sin.sin_addr.s_addr = inet_addr(srvIp.c_str());
// 绑定客户端socket到特定的本地IP地址
struct sockaddr_in local_addr;
memset(&local_addr, 0, sizeof(local_addr));
local_addr.sin_family = AF_INET;
local_addr.sin_port = htons(0); // 随机选择一个可用的本地端口
local_addr.sin_addr.s_addr = inet_addr(localIp.c_str()); // 客户端的本地IP地址
if (bind(m_sock, (struct sockaddr*)&local_addr, sizeof(local_addr)) == SOCKET_ERROR) {
// std::cerr << "Bind failed" << std::endl;
perror("Bind ");
//return 1;
}
else
{
std::cout << "Bind Success" << localIp<< std::endl;
}
if (connect(m_sock, (sockaddr*)(&sin), sizeof(sockaddr_in)) != 0)
{
perror("connect ");
Disconnect();
return -3;
}
// 初始化libssh2库
//flag 默认初始化选项
int rc = libssh2_init(0);
if (rc != 0) {
Disconnect();
return -1; // 初始化失败
}
// 创建SSH会话
m_session = libssh2_session_init();
if (!m_session) {
Disconnect();
return -2; // 创建会话失败
}
// 设置会话选项
libssh2_session_set_blocking(m_session, 1);// 0非阻塞模式 1// 阻塞模式
libssh2_session_set_timeout(m_session, 30 * 1000);
// 连接到远程主机
rc = libssh2_session_startup(m_session, m_sock);
if (rc != 0) {
// 连接失败
Disconnect();
return -3;
}
// 使用用户名和密码进行身份验证(用户名和密码)
rc = libssh2_userauth_password(m_session, userName.c_str(), userPwd.c_str());
if (rc != 0) {
// 身份验证失败
libssh2_session_disconnect(m_session, "Authentication failed");
//libssh2_session_free(m_session);
Disconnect();
return -4;
}
return 0;
}
bool FtSshTool::Disconnect(void)
{
//WSACleanup();
if (m_session)
{
libssh2_session_disconnect(m_session, "Bye bye, Thank you");
libssh2_session_free(m_session);
m_session = NULL;
}
if (m_sock != -1)
{
#ifdef WIN32
closesocket(m_sock);
#else
close(m_sock);
#endif
m_sock = -1;
}
return true;
}
std::shared_ptr<Channel> FtSshTool::CreateChannel(const std::string& ptyType)
{
if (NULL == m_session)
{
return NULL;
}
LIBSSH2_CHANNEL* channel = NULL;
/* Request a shell */
if (!(channel = libssh2_channel_open_session(m_session)))
{
return NULL;
}
/* Request a terminal with 'vanilla' terminal emulation
* See /etc/termcap for more options
*/
if (libssh2_channel_request_pty(channel, ptyType.c_str()))
{
libssh2_channel_free(channel);
return NULL;
}
/* Open a SHELL on that pty */
if (libssh2_channel_shell(channel))
{
libssh2_channel_free(channel);
return NULL;
}
std::shared_ptr < Channel> pChannel = std::make_shared<Channel>(channel);
// Channel* ret = new Channel(channel);
std::cout << pChannel->Read() << std::endl;
return pChannel;
}
bool FtSshTool::Scp(std::string localfile, std::string remotefile)
{
FILE* local = NULL;
int size = 0;
try
{
struct stat file_info;
size = std::filesystem::file_size(localfile);
// Send the file
struct stat file_status;
// 获取文件状态
if (stat(localfile.c_str(), &file_status) == -1) {
std::cerr << "Error: Unable to get file status for " << localfile << std::endl;
return 1;
}
LIBSSH2_CHANNEL* channel = libssh2_scp_send64(m_session, remotefile.c_str(), 0644, size, file_status.st_mtime, file_status.st_atime);
if (!channel) {
char* errmsg;
int errlen;
int err = libssh2_session_last_error(m_session, &errmsg, &errlen, 0);
fprintf(stderr, "Unable to open a session: (%d) %s\n", err, errmsg);
}
char mem[1024];
size_t nread;
char* ptr;
fprintf(stderr, "SCP session waiting to send file\n");
local = fopen(localfile.c_str(), "rb");
if (!local) {
fprintf(stderr, "Cannot open local file %s\n", localfile.c_str());
return 1;
}
do {
nread = fread(mem, 1, sizeof(mem), local);
if (nread <= 0) {
fclose(local);
break;
}
ptr = mem;
do {
ssize_t nwritten;
/* write the same data over and over, until error or completion */
nwritten = libssh2_channel_write(channel, ptr, nread);
if (nwritten < 0) {
fprintf(stderr, "ERROR %ld\n", (long)nwritten);
break;
}
else {
/* nwritten indicates how many bytes were written this time */
ptr += nwritten;
nread -= (size_t)nwritten;
}
} while (nread);
} while (1);
if (local)
fclose(local);
libssh2_channel_send_eof(channel);
fprintf(stderr, "Waiting for EOF\n");
libssh2_channel_wait_eof(channel);
fprintf(stderr, "Waiting for channel to close\n");
libssh2_channel_wait_closed(channel);
libssh2_channel_free(channel);
channel = NULL;
return true;
}
catch (...)
{
if (local)
fclose(local);
return false;
}
}
bool FtSshTool::ScpAll(std::string localpath, std::string remotePath)
{ // 检查路径是否存在
if (!std::filesystem::exists(localpath)) {
std::cerr << "Directory does not exist: " << localpath << std::endl;
return false;
}
// 遍历文件夹中的所有项
for (const auto& entry : std::filesystem::directory_iterator(localpath)) {
if (std::filesystem::is_directory(entry)) {
}
else {
Scp(entry.path().string(), remotePath + "/"+ entry.path().filename().string());
}
}
return false;
}
bool FtSshTool::ScpDirectory(std::string localdirectory, std::string remotedirectory)
{
// 检查路径是否存在
if (!std::filesystem::exists(localdirectory)) {
std::cerr << "Directory does not exist: " << localdirectory << std::endl;
return false;
}
std::shared_ptr<Channel>pchannel = this->CreateChannel();
std::string cmd_cd = "mkdir -p " + remotedirectory;
pchannel->Write(cmd_cd);
// 遍历文件夹中的所有项
for (const auto& entry : std::filesystem::directory_iterator(localdirectory)) {
if (std::filesystem::is_directory(entry)) {
std::string cmd_cd = "mkdir -p " + remotedirectory + "/" + entry.path().filename().string();
pchannel->Write(cmd_cd);
Scp(entry.path().string(), remotedirectory + "/" + entry.path().filename().string());
std::cout << cmd_cd << std::endl;
}
else {
Scp(entry.path().string(), remotedirectory + "/" + entry.path().filename().string());
std::string cmd_cd = "cd "+ remotedirectory +"; chmod 777 -R ./*;";
pchannel->Write(cmd_cd);
std::cout << cmd_cd << std::endl;
}
}
return true;
}
bool FtSshTool::KillProcessByName(std::string processName)
{
// 构建完整的WinSCP命令
//std::string commandLine = mWinscpPath + " /command "
// "open ssh://" + mUsername + ":" + mPassword + "@" + mHost +
// "call ps -ef|grep " + processName + " |grep -v grep |awk '{print $2}'|xargs kill -2"
// " /log=log.txt exit"; // 将执行结果保存到日志文件
//// 执行命令
//system(commandLine.c_str());
return true;
}
是用scp方法的时候,libssh2_channel_write返回-39的错误原因
最新发布