【问题标题】:Send File via libssh (ssh_scp_push_file && ssh_scp_write)通过 libssh 发送文件 (ssh_scp_push_file && ssh_scp_write)
【发布时间】:2017-04-21 00:55:44
【问题描述】:

免责声明:我正在谷歌上搜索

  • 使用 C++
  • 两端都是Linux
  • 我可以通过 TCPDUMP 看到远端的 SSH 连接
  • 除 0 外没有构建错误或返回代码(调试表明一切正常)
  • TCPPDUMP 似乎无法传输足够的数据(它是一个 2MB 的文件*)
  • 据我所知,连接/身份验证/授权正在正常进行

当我去远端寻找应该被复制的文件时,它不存在。我试过更新b并找到“文件”,但找不到。

提前感谢您提供任何可能的见解!

SSH 功能(身份验证和连接)因“最小、完整和可验证示例”而被清除,因为它们似乎工作正常*

#include <cstdio>
#include <string>
#include <iostream>
#include <stdio.h>
#include <fstream>
#include <curl/curl.h>
#include <boost/regex.hpp>
#include <boost/system/error_code.hpp>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <x86_64-linux-gnu/sys/stat.h>
#define LIBSSH_STATIC 1
#include <libssh/libssh.h>

using namespace std;

int sourcePull(void)
{
    CURL *curl; 
    FILE *fp;
    CURLcode res;
    char *url = "https://raw.githubusercontent.com/firehol/blocklist-ipsets/master/firehol_level1.netset";
    char outfilename[FILENAME_MAX] = "fireHOL";
    curl = curl_easy_init();
    if (curl)
    {
        fp = fopen(outfilename, "wb");
        curl_easy_setopt(curl, CURLOPT_URL, url);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, NULL);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, fp);
        res = curl_easy_perform(curl);
        curl_easy_cleanup(curl);
        fclose(fp);
    }
    return 0;
}

int sourceParse()
{
    //Regex for IP's in sourcePull result
    ifstream infile("fireHOL");
    string ipAddress;
    boost::regex expr1("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$");
    boost::regex expr2("^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])(\\/([0-9]|[1-2][0-9]|3[0-2]))$");
    boost::smatch matches;

        while (infile >> ipAddress)
        {
            if (boost::regex_match(ipAddress, matches, expr1)) 
            {
                ofstream checkpoint;
                checkpoint.open("samp_batch.txt", ios::out | ios::app);
                checkpoint << "add -t 86400 -a d -l r -o icewall ip -s " << ipAddress << endl;
                checkpoint << "add -t 86400 -a r -l r -o icewall ip -d " << ipAddress << endl;
            }

            if (boost::regex_match(ipAddress, matches, expr2))
            {
                ofstream checkpoint;
                checkpoint.open("samp_batch.txt", ios::out | ios::app);
                checkpoint << "add -t 86400 -a d -l r -o icewall ip -s " << ipAddress << endl;
                checkpoint << "add -t 86400 -a r -l r -o icewall ip -d " << ipAddress << endl;
            }

        }

        ofstream terminate;
        terminate.open("samp_batch.txt", ios::out | ios::app);
        terminate << "EOF";

    return 0;
}

int fileSize()
{
    int size;
    streampos begin, end;
    ifstream inputFile("samp_batch", ios::binary);
    begin = inputFile.tellg();
    inputFile.seekg(0, ios::end);
    end = inputFile.tellg();
    inputFile.close();
    return size;
}

int ssh()
{
    ssh_session my_ssh_session;
    ssh_scp scp;
    int port = 22;
    int rc;
    int method;
    char password[128] = { 0 };
    char *banner;
    //open session & set options
    my_ssh_session = ssh_new();
    if (my_ssh_session == NULL)
        exit(-1);
    ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, "XXX.XXX.XXX.XXX");
    ssh_options_set(my_ssh_session, SSH_OPTIONS_PORT, &port);
    ssh_options_set(my_ssh_session, SSH_OPTIONS_USER, "security");

    //connect to server
    rc = ssh_connect(my_ssh_session);
    if (rc != SSH_OK)
    {
        fprintf(stderr, "Error connecting to host: %s\n", ssh_get_error(my_ssh_session));
        ssh_free(my_ssh_session);
        exit(-1);
    }

    //verify the servers identity
    if (verify_knownHost(my_ssh_session) < 0)
    {
        fprintf(stdout, "unkown host\n");
        ssh_disconnect(my_ssh_session);
        ssh_free(my_ssh_session);
        exit(-1);
    }


    // Try to authenticate
    rc = ssh_userauth_none(my_ssh_session, NULL);
    if (rc == SSH_AUTH_ERROR) {
        error(my_ssh_session);
        return rc;
    }

    method = ssh_auth_list(my_ssh_session);
    while (rc != SSH_AUTH_SUCCESS) {
        // Try to authenticate with public key first
        if (method & SSH_AUTH_METHOD_PUBLICKEY) {
            rc = ssh_userauth_autopubkey(my_ssh_session, NULL);
            if (rc == SSH_AUTH_ERROR) {
                error(my_ssh_session);
                return rc;
            }
            else if (rc == SSH_AUTH_SUCCESS) {
                break;
            }
        }

    return rc;

    //SCP samp_batch file here
    const int length = fileSize();
    const char *fileName = "samp_batch";


    ifstream inputFile(fileName);
    constexpr size_t bufferSize = 1024 * 1024 * 1024;
    unique_ptr<char[]> buffer(new char[bufferSize]);
    const void* cvp = &buffer;

    rc = ssh_scp_push_file(scp, "samp_batch", length, 0777);
    if (rc != SSH_OK)
    {
        fprintf(stderr, "Can't open remote file: %s\n", ssh_get_error(my_ssh_session));
        ssh_free(my_ssh_session);
        exit(-1);

    }

    while (inputFile)
    {

        inputFile.read(buffer.get(), 1024 * 1024 * 1024);

        rc = ssh_scp_write(scp, cvp, bufferSize);
        if (rc != SSH_OK)
        {
            fprintf(stderr, "Cant write to remote file: %s\n", ssh_get_error(my_ssh_session));
            ssh_free(my_ssh_session);
            exit(-1);

        }
    }

    return SSH_OK;

    ////execute remote command here


    //ssh_free(my_ssh_session);
}

int main()
{

    sourcePull();
    sourceParse();
    ssh();


    return 0;
}

【问题讨论】:

  • 为什么fileSize()不把文件名作为参数?就像现在一样,您正在查看两个不同的文件。一个用于获取大小,一个用于读取。
  • 我已经将它“编码”了,因为它将被设置在一个计时工作上并且不理会,但这是一个错误,谢谢。编辑帖子以反映它仍然无法正常工作:(。它也是一个不会改变的常量文件名*
  • 你能发个minimal reproducible example吗?
  • rc = ssh_scp_write(scp, cvp, bufferSize); 你在这里写出了整个缓冲区。您应该只写从输入文件中读取的字节数。还考虑到您的缓冲区大小为 1GB,如果您没有通过 tcpdump 看到那么多流量,则表明您的程序甚至没有达到这一点。你需要这么大的缓冲区吗?超过 32k-64k 的任何东西都可能是浪费。
  • 编辑了更多细节@Jonas

标签: c++ scp libssh


【解决方案1】:

解决了这个问题,当然,更多的阅读......

我实际上并没有在 SSH 系统“内”初始化 SCP 子系统。

通过添加;

    scp = ssh_scp_new(my_ssh_session, SSH_SCP_WRITE, "/");
    if (scp == NULL)
    {
        fprintf(stderr, "Error allocating scp session: %s\n", ssh_get_error(my_ssh_session));
        return SSH_ERROR;
    }
    rc = ssh_scp_init(scp);
    if (rc != SSH_OK)
    {
        fprintf(stderr, "Error initializing scp session: %s\n", ssh_get_error(my_ssh_session));
        ssh_scp_free(scp);
        return rc;
    }

在我的推送/写入功能之上,我能够让 SCP 子系统“启动”。现在还没有让她发挥作用(SCP 状态代码 1d 无效)错误,但我至少知道此时 scp 是“清醒”的......

【讨论】:

    猜你喜欢
    • 2012-09-16
    • 2015-01-26
    • 2017-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多