问题
In my project i need to transfer files between a server and multiple clients. The communication between client and server should be encrypted, there should be an authentication by username and password and the protocol should be a common one, so i thought about sftp.
There are two c/c++ libraries for ssh: libssh and libssh2, where only the first one provides also server functionality.
There is a API documentation for libssh where the client module, involving the submodule sftp, is well documented. But for the server API I can only find basic ssh functions.
Does libssh provide server side sftp support at all?
回答1:
Yes, you can implement a sftp server using libssh. It just isn't doucmented.
See the functions at the end of the sftp.h file:
http://git.libssh.org/projects/libssh.git/tree/include/libssh/sftp.h
and also
http://git.libssh.org/projects/libssh.git/tree/src/sftpserver.c
We will soon release a new version of libssh with improved server support.
回答2:
you can use libssh for sftp. I can put some code here for you which is supporting Pause/Resume and works on windows. I cannot copy the entire class because it will exceed this website limit. change username and password and hostname to proper equivalents of your sftp server:
int main(array<System::String ^> ^args)
{
//Console::WriteLine(L"Hello World");
pSFTPConnector sshc = new SFTPConnector(L".\\", L"127.0.0.1", 22, L"iman", L"iman"); // change the hostname , port , username, password to your sftp server, your credentials
//FILE *nullfile = fopen("null", "w");
//sshc->setLogFile(nullfile);
sshc->setVerbosity(SSH_LOG_RARE); // you can change the verbosity as appropriate for you
int i= sshc->InitSession();
i=sshc->ConnectSession();
i = sshc->InitSFTP();
//i = sshc->SFTPrename("renamed_myfile.txt", "myfile.txt"); //change these file names
//i = sshc->Makedir("sftpdir");
//i = sshc->testUploadFile("myfile2.txt", "1234567890testfile");
// change these file names to whatever appropriate
//i = sshc->SFTPget("c:\\testdir\\Got_CAR_HIRE_FINAL_test.jpg", "CAR_HIRE_FINAL_test.jpg", 64*1024 );
i = sshc->SFTPget("c:\\testdir\\get_downloaded_CAR_HIRE_FINAL.jpg", "CAR_HIRE_FINAL.jpg", 64 *1024);
i = sshc->SFTPreget("c:\\testdir\\reget_downloaded_CAR_HIRE_FINAL.jpg", "CAR_HIRE_FINAL.jpg", 64 * 1024);
i = sshc->SFTPput("c:\\testdir\\CAR_HIRE_FINAL.jpg", "put_CAR_HIRE_FINAL.jpg", 64 * 1024);
i = sshc->SFTPreput("c:\\testdir\\CAR_HIRE_FINAL.jpg", "reput_CAR_HIRE_FINAL.jpg", 64 * 1024);
delete sshc;
return 0;
}
typedef enum sshconerr{
E_OK = 1, E_SESSION_ALOC = -1, E_SSH_CONNECT_ERR = -2, E_SFTP_ALLOC = -3, E_INIT_SFTP = -4, E_CREATE_DIR = -5, E_FILEOPEN_WRITE = -6, E_WRITE_ERR = -7
, E_FILE_CLOSE = -8, E_FILE_OPEN_READ = -9, E_INVALID_PARAMS = -10, E_SFTP_ERR = -11, E_SFTP_READ_ERR = -12, E_SFTP_READBYTES_ERR = -13, E_GET_FILEINF = -14
, E_LOCAL_FILE_NOTFOUND = -15, E_RENAME_ERR = -16, E_MEM_ALLOC = -17, E_LOCAL_FILE_READ = -18, E_LOCAL_FILE_RDWR = -19, E_REMOTEFILE_SEEK = -20
, E_REMOTE_FILE_OPEN = -21, E_DELETE_ERR = -22, E_RENAME_LOCAL_FILE = -23, E_LOCAL_DELETE_FILE = -24, E_FILEOPEN_RDONLY = -25, E_SFTP_READ_EOF=-26
,E_UNKNOWN=-999 } ESSHERR;
// status of transfers;
typedef enum sftpstat{ ES_DONE=0 , ES_INPROGRESS , ES_FAILED, ES_STARTING, ES_PAUSED, ES_RESUMING, ES_CANCELLED, ES_NONE } ESFTPSTAT;
using namespace std;
// statistics about the transfer;
typedef struct transferstatstruct {
string remote_file_name;
string local_file_name;
__int64 total_size;
__int64 transferred;
__int64 averagebps;
long long seconds_elapsed;
long long seconds_remained;
int percent;
ESFTPSTAT transferstate;
} TTransStat;
#define E_SESSION_NEW -1
// these libraries are required
#pragma comment(lib, "ssh.lib")
// this is the main class that does the majority of the work
typedef class CSFTPConnector{
private:
ssh_session session; // ssh session
sftp_session sftp; // sftp session
sftp_file file; // structure for a remote file
FILE *localfile; // not used in windows but could be local file pointer in UNIX
FILE *logfile; // the file for writing logs, default is set to stderr
string filename; // file name of the transfer;
string localfilename; // file name of local file;
string tempfilename; // a temporaty file name will be used during the transfer which is renamed when transfer is completed.
ESFTPSTAT transferstatus; // state of the transfer which has one of the above values (ESFTPSTAT)
time_t transferstarttime; // time of start of the transfer
wchar_t username[SHORT_BUFF_LEN];
wchar_t password[SHORT_BUFF_LEN];
wchar_t hostname[SHORT_BUFF_LEN]; // hostname of the sftp server
wchar_t basedir[SHORT_BUFF_LEN]; // this base dir is the directory of public and private key structur ( NOT USED IN THIS VERSION)
int port; // port of the server;
int verbosity; // degree of verbosity of libssh
__int64 filesize; // total number of bytes to be transfered;
DWORD local_file_size_hiDWORD; // Bill Gates cannot accept the file size without twisting the programmers, so he accepts them in 2 separate words like this
DWORD local_file_size_lowDWORD; // these 2 DWORDs when connected together comprise a 64 bit file size.
__int64 lfilesize; // local file size
__int64 rfilesize; // remote file size
__int64 transfered; // number of bytes already transfered
bool pause; // pause flag
TTransStat stats; // statistics of the transfer
HANDLE localfilehandle; // windows uses handles to manipulate files. this is the handle to local file.
ESSHERR CSFTPConnector::rwopen_existing_SFTPfile(char *fn); // open a file on remote ( server ) read/write for upload
ESSHERR CSFTPConnector::rdopen_existing_SFTPfile(char *fn); // open a file on remote ( server ) read only for download
ESSHERR createSFTPfile(char *fn); // create a file on server;
ESSHERR writeSFTPfile(char *block, size_t blocksize); // write a block of data to the open remote file
ESSHERR readSFTPfile(char *block, size_t len, size_t *bytesread); // read a block of data from the open remote file
ESSHERR readSFTPfile(char *block, __int64 len, DWORD *bytesread);
ESSHERR closeSFTPfile(); // closes the remote file;
ESSHERR openSFTPfile(char *fn); // opens the remote file
ESSHERR getSFTPfileinfo(); // gets information about the remote file
public:
wstring errstring; // the string describing last error
ESSHERR Err; // error code of last error
CSFTPConnector(); // default constructor;
CSFTPConnector(wchar_t *dir, wchar_t *hn, int hostport, wchar_t *un, wchar_t *pass); // constructor
void setVerbosity(int v);
int getVerbosity();
ESSHERR InitSession(); // must be called befor doing any transfer
ESSHERR ConnectSession(); // connnects to the ssh server
ESSHERR InitSFTP(); // must be called befor doing any transfer
ESSHERR Makedir(char *newdir);
ESSHERR testUploadFile(char *fn, char *block); // do not use this , only for test purposes for myself
ESSHERR SFTPput(char *lfn, char *rfn, size_t blocksize); // Upload a file from start
ESSHERR SFTPreput(char *lfn, char *rfn, size_t blocksize); // checks for previouse interrupted transfer, then either continues the previouse transfer ( if there was any) or starts a new one (UPLOAD)
ESSHERR SFTPrename(char *newname, char *oldname); // renames a remote file( must be closed)
ESSHERR CSFTPConnector::SFTPdelete(char *remfile); // deletes a remote file
TTransStat getStatus(); // gets statistics of the transfer
ESSHERR CSFTPConnector::SFTPget(char *lfn, char *rfn, size_t blocksize); // Downloads a file from sftp server
ESSHERR CSFTPConnector::SFTPreget(char *lfn, char *rfn, size_t blocksize); // checks for previouse interrupted transfer, then either continues the previouse transfer ( if there was any) or starts a new one (DOWNLOAD)
void CancelTransfer();
void PauseTransfer();
void setLogFile(FILE *logf); // sets the log file, if not set stderr will be used. by default.
void CloseLocalFile();
void CloseRemoteFile();
~CSFTPConnector();
} SFTPConnector, *pSFTPConnector ;
void CSFTPConnector::CloseLocalFile()
{
CloseHandle(localfilehandle);
}
void CSFTPConnector::CloseRemoteFile()
{
sftp_close(file);
}
void CSFTPConnector::setLogFile(FILE *logf)
{
logfile = logf;
}
void CSFTPConnector::CancelTransfer()
{
transferstatus = ES_CANCELLED;
}
void CSFTPConnector::PauseTransfer()
{
transferstatus = ES_PAUSED;
pause = true;
}
//----------------------------------------
ESSHERR CSFTPConnector::SFTPget(char *lfn, char *rfn, size_t blocksize)
{
DWORD result;
int rc;
BOOL bresult;
DWORD bytesread;
filesize = 0;
transfered = 0;
pause = false;
transferstatus = ES_NONE;
char *block;
struct stat st;
wchar_t temp[SHORT_BUFF_LEN];
size_t tempsize;
wstring wlfn;
int loopcounter = 0;
localfilename = lfn;
filename = rfn;
tempfilename = string(lfn) + ".sftp_temp";
mbstowcs_s(&tempsize, temp, tempfilename.c_str(), SHORT_BUFF_LEN);
localfilehandle = CreateFile(temp, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (localfilehandle == INVALID_HANDLE_VALUE)
{
transferstatus = ES_FAILED;
errstring = L"Could not open local file:" + wstring(temp) + L" for read and write";
Err = E_LOCAL_FILE_RDWR;
return E_LOCAL_FILE_RDWR;
}
lfilesize =0;
transfered =0;
block = (char*)malloc(blocksize + 1);
if (block == NULL) {
Err = E_MEM_ALLOC;
transferstatus = ES_FAILED;
errstring = L"Could not allocate memory for file block size";
CloseLocalFile();
return E_MEM_ALLOC;
}
result = rdopen_existing_SFTPfile((char *)rfn);
if (result == E_OK){
getSFTPfileinfo();
filesize = rfilesize;
}
else
{
Err = E_REMOTE_FILE_OPEN;
transferstatus = ES_FAILED;
errstring = L"Could not open remote file";
CloseLocalFile();
delete block;
return E_REMOTEFILE_SEEK;
}
transferstatus = ES_STARTING;
sftp_file_set_blocking(file);
transferstarttime = time(NULL);
transferstatus = ES_INPROGRESS;
while (transferstatus != ES_FAILED && transferstatus != ES_PAUSED && transferstatus != ES_CANCELLED &&transferstatus != ES_DONE)
{
loopcounter++;
result = readSFTPfile(block, blocksize, (size_t *)&bytesread);
if (result != E_OK && result!= E_SFTP_READ_EOF )
{
errstring = L"Error reading from remote sftp server file.";
Err = (ESSHERR)result;
transferstatus = ES_FAILED;
CloseRemoteFile();
CloseLocalFile();
delete block;
return (ESSHERR)result;
}
if (result == E_SFTP_READ_EOF) transferstatus = ES_DONE;
fprintf(logfile, "Read %d bytes from input file. Number of packets: %d , %llu from %llu bytes\n", bytesread, loopcounter, transfered, filesize);
bresult = WriteFile(localfilehandle, (LPVOID)block, bytesread, &bytesread, NULL);
if (bytesread < blocksize)
{
if (bresult == FALSE)
{
errstring = L"Error writing to local file.";
Err = E_LOCAL_FILE_RDWR;
transferstatus = ES_FAILED;
CloseRemoteFile();
CloseLocalFile();
delete block;
return E_LOCAL_FILE_RDWR;
}
else if (bytesread == 0)
{
errstring = L"Transfer done.";
Err = E_OK;
transferstatus = ES_DONE;
continue;
}
}
Err = E_OK;
if (pause == true) transferstatus = ES_PAUSED;
if (bresult == TRUE && bytesread == 0)
{
// at the end of the file
transferstatus = ES_DONE;
}
Sleep(BLOCKTRANSDELAY);
if (loopcounter % 331 == 0)Sleep(77 * BLOCKTRANSDELAY);
if (loopcounter % 3331 == 0)Sleep(777 * BLOCKTRANSDELAY);
}
// closing files
result = closeSFTPfile();
CloseHandle(localfilehandle);
Sleep(1000);
if (transferstatus == ES_DONE)
{
wchar_t temp2[SHORT_BUFF_LEN];
mbstowcs_s(&tempsize, temp2, lfn, SHORT_BUFF_LEN);
bresult = MoveFile(temp, temp2);
if (bresult != TRUE)
{
Err = E_RENAME_LOCAL_FILE;
errstring = L"Could not rename local file: " + wstring(temp);
transferstatus = ES_FAILED;
delete block;
return E_RENAME_LOCAL_FILE;
}
}
if (transferstatus == ES_CANCELLED)
{
wchar_t temp2[SHORT_BUFF_LEN];
mbstowcs_s(&tempsize, temp2, lfn, SHORT_BUFF_LEN);
bresult = DeleteFile(temp);
if (bresult != TRUE)
{
Err = E_LOCAL_DELETE_FILE;
errstring = L"Could not rename local file: " + wstring(temp);
transferstatus = ES_FAILED;
delete block;
return E_LOCAL_DELETE_FILE;
}
}
delete block;
return (ESSHERR) result;
}
TTransStat CSFTPConnector::getStatus()
{
stats.seconds_elapsed = time(NULL) - transferstarttime;
stats.averagebps = (transfered * 8) / stats.seconds_elapsed;
if (filesize > 0) {
stats.percent = (transfered *100)/ filesize;
stats.seconds_remained = ((filesize - transfered) * 8) / stats.averagebps;
}
else
{
stats.percent = -1;
stats.seconds_remained = -1;
}
stats.total_size = filesize;
stats.transferstate = transferstatus;
stats.remote_file_name = filename;
stats.local_file_name = localfilename;
return stats;
}
ESSHERR CSFTPConnector::SFTPrename(char *newname, char *oldname)
{
int rc=sftp_rename(sftp, oldname, newname);
if (rc !=SSH_OK){
return E_RENAME_ERR;
}
return E_OK;
}
ESSHERR CSFTPConnector::SFTPdelete(char *remfile)
{
int rc = sftp_unlink(sftp,remfile);
if (rc != SSH_OK){
return E_DELETE_ERR;
}
return E_OK;
}
ESSHERR CSFTPConnector::SFTPreput(char *lfn, char *rfn, size_t blocksize)
{
ESSHERR result;
BOOL bresult;
DWORD bytesread;
filesize = 0;
transfered = 0;
pause = false;
transferstatus = ES_NONE;
char *block;
struct stat st;
wchar_t temp[SHORT_BUFF_LEN];
size_t tempsize;
wstring wlfn;
int loopcounter = 0;
localfilename = lfn;
//wlfn = wstring(lfn);
//localfile = fopen(lfn, L"r");
filename = rfn;
mbstowcs_s(&tempsize, temp, lfn, SHORT_BUFF_LEN);
//filesize = getFileSize(localfilename);
/*if(filesize < 0) {
transferstatus = ES_FAILED;
Err = E_LOCAL_FILE_NOTFOUND;
return E_LOCAL_FILE_NOTFOUND;
}*/
localfilehandle = CreateFile(temp, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (localfilehandle == INVALID_HANDLE_VALUE)
{
transferstatus = ES_FAILED;
Err = E_LOCAL_FILE_NOTFOUND;
return E_LOCAL_FILE_NOTFOUND;
}
local_file_size_lowDWORD = GetFileSize(localfilehandle, &local_file_size_hiDWORD);
filesize = (local_file_size_hiDWORD * 0x100000000) + local_file_size_lowDWORD;
if (filesize < 0) {
transferstatus = ES_FAILED;
Err = E_LOCAL_FILE_NOTFOUND;
CloseLocalFile();
return E_LOCAL_FILE_NOTFOUND;
}
block = (char*)malloc(blocksize + 1);
if (block == NULL) {
Err = E_MEM_ALLOC;
transferstatus = ES_FAILED;
errstring = L"Could not allocate memory for file block size";
CloseLocalFile();
return E_MEM_ALLOC;
}
tempfilename = string(rfn) + ".sftp_temp";
result = rwopen_existing_SFTPfile((char *)tempfilename.c_str());
if (result == E_OK){
getSFTPfileinfo();
sftp_seek64(file, rfilesize);
__int64 tempi64 = rfilesize & 0x00000000FFFFFFFF;
DWORD dwlow = tempi64;
tempi64 = (rfilesize & 0x7FFFFFFF00000000);
tempi64 = tempi64 >> 32;
long dwhi = tempi64;
DWORD dwResult=SetFilePointer(localfilehandle, dwlow,&dwhi , FILE_BEGIN);
if (dwResult == INVALID_SET_FILE_POINTER)
{
transferstatus = ES_FAILED; Err = result; return result;
}
transferstatus = ES_RESUMING;
transfered = rfilesize;
}
else{
result = createSFTPfile((char *)tempfilename.c_str());
transferstatus = ES_STARTING;
if (result != E_OK) {
transferstatus = ES_FAILED;
Err = result;
CloseLocalFile();
return result;
}
}
sftp_file_set_blocking(file);
transferstarttime = time(NULL);
transferstatus = ES_INPROGRESS;
while (transferstatus != ES_FAILED && transferstatus != ES_PAUSED && transferstatus != ES_DONE)
{
loopcounter++;
bresult = ReadFile(localfilehandle, (LPVOID)block, blocksize, &bytesread, NULL);
fprintf(logfile, "Read %d bytes from input file. Number of packets: %d , %llu from %llu bytes\n", bytesread, loopcounter, transfered, filesize);
if (bytesread < blocksize)
{
if (bresult == FALSE)
{
errstring = L"Error reading from local file.";
Err = E_LOCAL_FILE_READ;
transferstatus = ES_FAILED;
CloseRemoteFile();
CloseLocalFile();
return E_LOCAL_FILE_READ;
}
else if (bytesread == 0)
{
errstring = L"Transfer done.";
Err = E_OK;
transferstatus = ES_DONE;
continue;
}
}
result = writeSFTPfile(block, bytesread);
if (result != E_OK && bytesread>0 )
{
errstring = L"Error transmitting to remote sftp server file.";
Err = result;
transferstatus = ES_FAILED;
CloseRemoteFile();
CloseLocalFile();
return result;
}
Err = E_OK;
//transfered = transfered + bytesread;
if (pause == true) transferstatus = ES_PAUSED;
if (bresult == TRUE && bytesread == 0)
{
// at the end of the file
transferstatus = ES_DONE;
}
Sleep(BLOCKTRANSDELAY);
if (loopcounter % 331 == 0)Sleep(77 * BLOCKTRANSDELAY);
if (loopcounter % 3331 == 0)Sleep(777 * BLOCKTRANSDELAY);
}
CloseRemoteFile();
CloseLocalFile();
Sleep(1000);
if (transferstatus == ES_CANCELLED)
{
result = SFTPdelete((char *)tempfilename.c_str());
if (bresult != E_OK)
{
Err = E_DELETE_ERR;
errstring = L"Could not delete remote file.";
transferstatus = ES_FAILED;
return E_DELETE_ERR;
}
}
if (transferstatus == ES_DONE) result = SFTPrename(rfn, (char *)tempfilename.c_str());
delete block;
return result;
}
ESSHERR CSFTPConnector::getSFTPfileinfo()
{
sftp_attributes fileinf = sftp_fstat(file);
if (fileinf == NULL){
return E_GET_FILEINF;
}
rfilesize = fileinf->size;
sftp_attributes_free(fileinf);
return E_OK;
}
ESSHERR CSFTPConnector::closeSFTPfile()
{
int rc = sftp_close(file);
if (rc != SSH_OK)
{
fprintf(logfile, "Can't close the written file: %s\n",
ssh_get_error(session));
return E_FILE_CLOSE;
}
return E_OK;
}
ESSHERR CSFTPConnector::writeSFTPfile(char *block, size_t blocksize)
{
size_t nwritten = sftp_write(file, block, blocksize);
if (nwritten != blocksize)
{
fprintf(logfile, "Can't write data to file: %s\n",
ssh_get_error(session));
//sftp_close(file);
transfered = transfered + nwritten;
return E_WRITE_ERR;
}
transfered = transfered + nwritten;
return E_OK;
}
ESSHERR CSFTPConnector::readSFTPfile(char *block, size_t len, size_t *bytesread)
{
DWORD readbytes;
*bytesread = 0;
if (len <= 0) return E_INVALID_PARAMS;
if (bytesread == NULL || block == NULL) return E_INVALID_PARAMS;
readbytes = sftp_read(file, block, len);
if (readbytes < 0)
{
fprintf(logfile, "Can't read from remote file: %s %s\n", filename.c_str(), ssh_get_error(session));
*bytesread = 0;
return E_SFTP_READ_ERR;
}
if (readbytes < len)
{
*bytesread = readbytes;
transfered = transfered + readbytes;
return E_SFTP_READ_EOF;
}
*bytesread = readbytes;
transfered = transfered + readbytes;
return E_OK;
}
ESSHERR CSFTPConnector::readSFTPfile(char *block, __int64 len, DWORD *bytesread)
{
DWORD readbytes;
*bytesread = 0;
if (len <= 0) return E_INVALID_PARAMS;
if (bytesread == NULL || block == NULL) return E_INVALID_PARAMS;
readbytes = sftp_read(file, block, len);
if (readbytes < 0)
{
fprintf(logfile, "Can't read from remote file: %s %s\n", filename.c_str(), ssh_get_error(session));
*bytesread = 0;
return E_SFTP_READ_ERR;
}
if (readbytes < len)
{
*bytesread = readbytes;
return E_SFTP_READ_EOF;
}
*bytesread = readbytes;
transfered = transfered + readbytes;
return E_OK;
}
ESSHERR CSFTPConnector::createSFTPfile(char *fn)
{
int access_type = O_CREAT | O_RDWR;
int rc, nwritten;
filename = string(fn);
file = sftp_open(sftp, fn,
access_type, S_IWRITE);
if (file == NULL)
{
fprintf(logfile, "Can't open file for writing: %s\n",
ssh_get_error(session));
return E_FILEOPEN_WRITE;
}
return E_OK;
}
ESSHERR CSFTPConnector::rdopen_existing_SFTPfile(char *fn)
{
int access_type = O_RDONLY ;
int rc, nwritten;
filename = string(fn);
file = sftp_open(sftp, fn,
access_type, S_IREAD);
if (file == NULL)
{
fprintf(logfile, "Can't open file for writing: %s\n",
ssh_get_error(session));
return E_FILEOPEN_RDONLY;
}
return E_OK;
}
ESSHERR CSFTPConnector::openSFTPfile(char *fn)
{
int access_type = O_RDONLY;
int rc, nwritten;
filename = string(fn);
file = sftp_open(sftp, fn,
access_type, S_IWRITE);
if (file == NULL)
{
fprintf(logfile, "Can't open file for writing: %s\n",
ssh_get_error(session));
return E_FILE_OPEN_READ;
}
return E_OK;
}
ESSHERR CSFTPConnector::Makedir(char *newdir)
{
int rc;
rc = sftp_mkdir(sftp, newdir, S_IFDIR);
if (rc != SSH_OK)
{
if (sftp_get_error(sftp) != SSH_FX_FILE_ALREADY_EXISTS)
{
fprintf(logfile, "Can't create directory: %s\n",
ssh_get_error(session));
return E_CREATE_DIR;
}
}
return E_OK;
}
SFTPConnector::CSFTPConnector()
{
//libssh2_init(0);
session = ssh_new();
if (session == NULL)
{
Err = E_SESSION_ALOC;
errstring = L"Could not allocate a session.";
}
wcscpy(hostname, L"localhost" );
wcscpy(username, L"User");
wcscpy(password, L"Password");
wcscpy(basedir, L".\\");
port = 22;
verbosity = SSH_LOG_RARE;
filesize = 0;
transfered = 0;
pause = false;
transferstatus = ES_NONE;
logfile = stderr;
}
CSFTPConnector::CSFTPConnector(wchar_t *dir, wchar_t *hn, int hostport, wchar_t *un, wchar_t *pass)
{
session = ssh_new();
if (session == NULL)
{
Err = E_SESSION_ALOC;
errstring = L"Could not allocate a session.";
}
wcscpy(hostname, hn);
wcscpy(username, un);
wcscpy(password, pass);
wcscpy(basedir, dir);
port = hostport;
verbosity = SSH_LOG_RARE;
filesize=0;
transfered=0;
pause=false;
transferstatus = ES_NONE;
logfile = stderr;
}
ESSHERR CSFTPConnector::InitSFTP()
{
int rc;
sftp= sftp_new(session);
if (session == NULL)
{
Err = E_SFTP_ALLOC;
errstring = L"Could not allocate a sftp session.";
}
rc = sftp_init(sftp);
if (rc != SSH_OK)
{
fprintf(logfile, "Error initializing SFTP session: %s.\n",
sftp_get_error(sftp));
sftp_free(sftp);
return E_INIT_SFTP;
}
return E_OK;
}
ESSHERR CSFTPConnector::ConnectSession()
{
char temp[SHORT_BUFF_LEN];
size_t n_of_chars;
wcstombs_s(&n_of_chars, temp, SHORT_BUFF_LEN, (const wchar_t *)password, SHORT_BUFF_LEN);
int ir;
ir=ssh_connect(session);
if (ir != SSH_OK){
errstring = L"Could not connect the ssh session.";
return E_SSH_CONNECT_ERR;
}
ir=ssh_userauth_password(session, NULL, temp);
if (ir != SSH_OK){
errstring = L"Could not connect the ssh session.";
return E_SSH_CONNECT_ERR;
}
return E_OK;
}
ESSHERR CSFTPConnector::InitSession()
{
char temp[SHORT_BUFF_LEN];
size_t n_of_chars;
wcstombs_s(&n_of_chars, temp,SHORT_BUFF_LEN, (const wchar_t *) hostname, SHORT_BUFF_LEN);
ssh_options_set(session, SSH_OPTIONS_HOST,temp);
ssh_options_set(session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
ssh_options_set(session, SSH_OPTIONS_PORT, &port);
wcstombs_s(&n_of_chars, temp, SHORT_BUFF_LEN, (const wchar_t *)username, SHORT_BUFF_LEN);
ssh_options_set(session, SSH_OPTIONS_USER,temp);
wcstombs_s(&n_of_chars, temp, SHORT_BUFF_LEN, (const wchar_t *)basedir, SHORT_BUFF_LEN);
ssh_options_set(session, SSH_OPTIONS_SSH_DIR, temp);
return E_OK;
}
CSFTPConnector::~CSFTPConnector()
{
sftp_free(sftp);
ssh_disconnect(session);
ssh_free(session);
return;
}
来源:https://stackoverflow.com/questions/16510204/does-libssh-supports-sftp-server-functionality