1 頁 (共 1 頁)

libssh2 (SFTP begin...)

發表於 : 2021-06-05, 12:49
admin
1. get libssl2 from url https://www.libssh2.org/ v1.9.0
2. compiler use Visual Studio 2019
open .\libssh2\win32\libssh2.dsw
creat .lib/.dll
use coff2omf.exe conversion for bcc74.

demo.prg connect remote server.

代碼: 選擇全部

// ssh2 test
#define AF_INET            2
#define SOCK_STREAM        1
#define IPPROTO_IP         0
Func    Test()
Local   nSession, nSock
Local   cUsername := 'username',;
        cPassword := 'password',;
        cIp       := '127.0.0.1'

        nSession := ssh2_session_init()
        If nSession == 0
           msgStop( 'ssh2 init Fail' )
           return
        EndIf
        msginfo( 'ssh2 init ok', 'ok' )
        do while .t.
           // 建立與遠端連線的 socket
           if WSASTARTUP() != 0 // 初始化
              msgStop('sock init fail!!','error')
              exit
           endif
           //
           if ( nSocket := Socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) == 0 // 建立 socket
              MsgStop( "Socket creation error: " + Str( WsaGetLastError() ) )
              exit
           endif
           //
           if ConnectTo( nSocket, 22, cIp ) <> 0
              msgStop( 'create connect fail!!' )
              exit
           endif
           //
           if ssh2_session_handshake( nSession, nSocket ) > 0
              msgstop( 'create handshake fail!!' )
           else
              msginfo( 'create handshate success!!' )
           endif
           //
           do while .t.
              fingerprint = ssh2_hostkey_hash(nSession ) // , LIBSSH2_HOSTKEY_HASH_SHA1)
msginfo( fingerprint, 'fingerprint' )
              userauthlist = ssh2_userauth_list(nSession, cUsername ) // 檢查需要那些認證資料?
msginfo( userauthlist, 'userauthlist' )
              if 'password' $ userauthlist
                 // 可以使用密碼方式登入
                 if SSH2_USERAUTH_PASSWORD( nSession, cUsername, cPassword ) > 0 // 設定密碼
                    msgStop( 'authentication by password fail' )
                    exit
                 else
                    msgInfo( '認證成功!!' )
                 endif
              else
                 if 'keyboad-interactive' $ userauthlist // 使用鍵盤方式輸入
                    // 強制 client 每次都使用鍵盤交互輸入,client 不能儲存密碼,避免被破解
                 else
                    if 'publickey' $ userauthlist
                       // 使用認證檔案方式
                    else
                       msgStop( 'no support any authentication method!!' )
                    endif
                 endif
              endif
              //
              exit
           enddo
           CloseSocket( nSock )
           //
           exit
           //
        enddo
        //
        ssh2_session_disconnect( nSession ) // 關閉連線
        ssh2_session_free( nSession )
        msginfo( 'ssh2 free ok', 'ok' )
        //
return  NIL
change cUsername, cPassword, cIP to test.


ssh2.c

代碼: 選擇全部

/*
  Copyright by WenSheng from Taiwan!!
*/
#include "hbapi.h" // add:WenSheng:2015.10.21
#include <hbapiitm.h>

// libssh2
#include <libssh2.h>
//-------------------------------------------------------------------------
// LIBSSH2_AGENT *libssh2_agent_init(LIBSSH2_SESSION *session);
//-------------------------------------------------------------------------
// 初始化
HB_FUNC( SSH2_SESSION_INIT ){
  LIBSSH2_SESSION *session;
  session = libssh2_session_init();
  if(session == NULL){
    hb_retnl(0);
  }else{
    hb_retnl( (LONG) session);
  }
}

// 關閉連線
// int libssh2_session_disconnect(LIBSSH2_SESSION *session, const char *description);
HB_FUNC( SSH2_SESSION_DISCONNECT ){
  LIBSSH2_SESSION *session = (LIBSSH2_SESSION *)hb_parnl(1);
  char * desc = (char *)(HB_ISCHAR(2) ? hb_parc( 2 ) : "Normal Shutdown" );
  hb_retni( libssh2_session_disconnect(session, desc)); // 0:success
}

// 釋放
HB_FUNC( SSH2_SESSION_FREE ){
  LIBSSH2_SESSION *session = (LIBSSH2_SESSION *)hb_parnl(1);
  hb_retni( libssh2_session_free( session ));
}

// 建立 handshake
HB_FUNC( SSH2_SESSION_HANDSHAKE ){
  LIBSSH2_SESSION *session = (LIBSSH2_SESSION *)hb_parnl(1); // session
  int sock = (HB_ISNUM(2) ? hb_parnl(2) : 0 ); // socket
  hb_retni( libssh2_session_handshake(session, sock));
}

// 取得遠端主機金鑰驗證方式
// const char * libssh2_hostkey_hash(LIBSSH2_SESSION *session, int hash_type);
HB_FUNC( SSH2_HOSTKEY_HASH ){
  LIBSSH2_SESSION *session = (LIBSSH2_SESSION *)hb_parnl(1);
  int hash_type = (HB_ISNUM(2) ? hb_parni(2) : LIBSSH2_HOSTKEY_HASH_SHA1);
  const char * fingerprint;
  fingerprint = libssh2_hostkey_hash(session, hash_type);
  hb_retc( fingerprint );
}

// 列出支援的認證方式
// char * libssh2_userauth_list(LIBSSH2_SESSION *session, const char *username, unsigned int username_len);
HB_FUNC( SSH2_USERAUTH_LIST ){
  LIBSSH2_SESSION *session = (LIBSSH2_SESSION *)hb_parnl(1);
  char * username = (char *)hb_parc( 2 );
  LONG iUlen = hb_parclen(2);
  char * userauthlist;
  userauthlist = libssh2_userauth_list(session, username, iUlen);
  hb_retc( userauthlist );
}

// 設定驗證密碼
// int libssh2_userauth_password(LIBSSH2_SESSION *session,   const char *username,   const char *password)
HB_FUNC( SSH2_USERAUTH_PASSWORD ){
  LIBSSH2_SESSION *session = (LIBSSH2_SESSION *)hb_parnl(1);
  char * username = (char *)hb_parc( 2 );
  char * password = (char *)hb_parc( 3 );
  hb_retni( libssh2_userauth_password(session, username, password)); // 0:success
}
if you can't compiler libssh2 and can download from: https://app.box.com/s/opqsirs7u6qxodcdau3y7ocway8ifea4
file is libssh2.lib and libssh2.dll for bcc74.

Re: libssh2

發表於 : 2021-06-05, 16:54
admin
sftp: remote read file:

代碼: 選擇全部

// ssh2 test
#define AF_INET            2
#define SOCK_STREAM        1
#define IPPROTO_IP         0
#define LIBSSH2_FXF_READ                        0x00000001
Func    Test()
Local   nSession, nSock,;
        nSftp_session, nSftp_handle,;
        cSftpPath := '/tmp/pnb.txt',;
        cBuffer   := '',;
        nLen      := 0,;
        cData     := ''
        //
Local   cUsername := 'username',;
        cPassword := 'password',;
        cIp       := '127.0.0.1'

        nSession := ssh2_session_init()
        If nSession == 0
           msgStop( 'ssh2 init Fail' )
           return
        EndIf
        msginfo( 'ssh2 init ok', 'ok' )
        do while .t.
           // 建立與遠端連線的 socket
           if WSASTARTUP() != 0 // 初始化
              msgStop('sock init fail!!','error')
              exit
           endif
           //
           if ( nSocket := Socket( AF_INET, SOCK_STREAM, IPPROTO_IP ) ) == 0 // 建立 socket
              MsgStop( "Socket creation error: " + Str( WsaGetLastError() ) )
              exit
           endif
           //
           if ConnectTo( nSocket, 22, cIp ) <> 0
              msgStop( 'create connect fail!!' )
              exit
           endif
           //
           if ssh2_session_handshake( nSession, nSocket ) > 0
              msgstop( 'create handshake fail!!' )
           else
              msginfo( 'create handshate success!!' )
           endif
           //
           do while .t.
              fingerprint = ssh2_hostkey_hash(nSession ) // , LIBSSH2_HOSTKEY_HASH_SHA1)
              msginfo( fingerprint, 'fingerprint' )
              userauthlist = ssh2_userauth_list(nSession, cUsername ) // 檢查需要那些認證資料?
              msginfo( userauthlist, 'userauthlist' )
              if 'password' $ userauthlist
                 // 可以使用密碼方式登入
                 if SSH2_USERAUTH_PASSWORD( nSession, cUsername, cPassword ) > 0 // 設定密碼
                    msgStop( 'authentication by password fail' )
                    exit
                 else
                    msgInfo( '認證成功!!' )
                 endif
              else
                 if 'keyboad-interactive' $ userauthlist // 使用鍵盤方式輸入
                    // 強制 client 每次都使用鍵盤交互輸入,client 不能儲存密碼,避免被破解
                 else
                    if 'publickey' $ userauthlist
                       // 使用認證檔案方式
                    else
                       msgStop( 'no support any authentication method!!' )
                    endif
                 endif
              endif
              // 測試 sftp
              nSftp_Session = ssh2_sftp_init( nSession )
              if nSftp_Session == 0
                 msgStop( 'sftp init fail!!')
                 exit
              else
                 msgInfo( 'sftp init success!!' )
              EndIf
              //
              do while .t.
                 //
                 nSftp_Handle := ssh2_sftp_open( nSftp_Session, cSftpPath, LIBSSH2_FXF_READ, 0)
                 If nSftp_Handle == 0
                    msgStop( 'sftp open fail!!['+ltrim(str( ssh2_sftp_last_error( nSftp_Session ) ))+']' )
                    exit
                 else
                    msgInfo( 'sftp open success!!' )
                 endif
                 //
                 i := 0
                 cData := ''
                 do while .T.
                    i++
                    cData += '['+ltrim(str(i))+']:'
                    cBuffer := Space(1024)
                    nLen := ssh2_sftp_read(nSftp_Handle, @cBuffer)
                    if nLen > 0
                       cData += cBuffer+hb_eol()
                    else
                       cData += 'data len is 0 and exit'+hb_eol()
                       exit // end
                    endif
                 enddo
                 ssh2_sftp_close(nSftp_handle);
                 //
                 if empty(cData)
                    cData := 'file:['+cSftpPath+'] not exist!!'
                 endif
                 msgInfo('read data:'+hb_eol()+cData)
                 //
                 exit
                 //
              enddo
              //
              ssh2_sftp_shutdown( nSftp_Session )
              //
              exit
              //
           enddo
           CloseSocket( nSock )
           //
           exit
           //
        enddo
        //
        ssh2_session_disconnect( nSession ) // 關閉連線
        ssh2_session_free( nSession )
        msginfo( 'ssh2 free ok', 'ok' )
        
return  NIL

// ssh2.c

代碼: 選擇全部

#include "hbapi.h"
#include <hbapiitm.h>

/*
  Copyright by WenSheng from Taiwan
  libssh2
*/
#include <libssh2.h>
#include <libssh2_sftp.h> // sftp
//-------------------------------------------------------------------------
// LIBSSH2_AGENT *libssh2_agent_init(LIBSSH2_SESSION *session);
//-------------------------------------------------------------------------
// 初始化
HB_FUNC( SSH2_SESSION_INIT ){
  LIBSSH2_SESSION *session;
  session = libssh2_session_init();
  if(session == NULL){
    hb_retnl(0);
  }else{
    hb_retnl( (LONG) session);
  }
}

// 關閉連線
// int libssh2_session_disconnect(LIBSSH2_SESSION *session, const char *description);
HB_FUNC( SSH2_SESSION_DISCONNECT ){
  LIBSSH2_SESSION *session = (LIBSSH2_SESSION *)hb_parnl(1);
  char * desc = (char *)(HB_ISCHAR(2) ? hb_parc( 2 ) : "Normal Shutdown" );
  hb_retni( libssh2_session_disconnect(session, desc)); // 0:success
}

// 釋放
HB_FUNC( SSH2_SESSION_FREE ){
  LIBSSH2_SESSION *session = (LIBSSH2_SESSION *)hb_parnl(1);
  hb_retni( libssh2_session_free( session ));
}

// 建立 handshake
HB_FUNC( SSH2_SESSION_HANDSHAKE ){
  LIBSSH2_SESSION *session = (LIBSSH2_SESSION *)hb_parnl(1); // session
  int sock = (HB_ISNUM(2) ? hb_parnl(2) : 0 ); // socket
  hb_retni( libssh2_session_handshake(session, sock));
}

// 取得遠端主機金鑰驗證方式
// const char * libssh2_hostkey_hash(LIBSSH2_SESSION *session, int hash_type);
HB_FUNC( SSH2_HOSTKEY_HASH ){
  LIBSSH2_SESSION *session = (LIBSSH2_SESSION *)hb_parnl(1);
  int hash_type = (HB_ISNUM(2) ? hb_parni(2) : LIBSSH2_HOSTKEY_HASH_SHA1);
  const char * fingerprint;
  fingerprint = libssh2_hostkey_hash(session, hash_type);
  hb_retc( fingerprint );
}

// 列出支援的認證方式
// char * libssh2_userauth_list(LIBSSH2_SESSION *session, const char *username, unsigned int username_len);
HB_FUNC( SSH2_USERAUTH_LIST ){
  LIBSSH2_SESSION *session = (LIBSSH2_SESSION *)hb_parnl(1);
  char * username = (char *)hb_parc( 2 );
  LONG iUlen = hb_parclen(2);
  char * userauthlist;
  userauthlist = libssh2_userauth_list(session, username, iUlen);
  hb_retc( userauthlist );
}

// 設定驗證密碼
// int libssh2_userauth_password(LIBSSH2_SESSION *session,   const char *username,   const char *password)
HB_FUNC( SSH2_USERAUTH_PASSWORD ){
  LIBSSH2_SESSION *session = (LIBSSH2_SESSION *)hb_parnl(1);
  char * username = (char *)hb_parc( 2 );
  char * password = (char *)hb_parc( 3 );
  hb_retni( libssh2_userauth_password(session, username, password)); // 0:success
}

// sftp session 初始化
// #include <libssh2_sftp.h>
// LIBSSH2_SFTP * libssh2_sftp_init(LIBSSH2_SESSION *session);
HB_FUNC( SSH2_SFTP_INIT ){
  LIBSSH2_SESSION *session = (LIBSSH2_SESSION *)hb_parnl(1);
  LIBSSH2_SFTP * sftp_session = libssh2_sftp_init(session);
  if(sftp_session == NULL){
    hb_retnl(0);
  }else{
    hb_retnl( (LONG) sftp_session);
  }
}

// 打開 sftp 連線
// LIBSSH2_SFTP_HANDLE * libssh2_sftp_open(LIBSSH2_SFTP *sftp, const char *path, unsigned long flags, long mode);
HB_FUNC( SSH2_SFTP_OPEN ){
  LIBSSH2_SFTP_HANDLE * sftp_handle;
  LIBSSH2_SESSION *sftp_session = (LIBSSH2_SESSION *)hb_parnl(1);
  const char *path = hb_parc(2);
  LONG flags = (HB_ISNUM(3) ? hb_parni(3) : LIBSSH2_FXF_READ );
  LONG mode = (HB_ISNUM(4) ? hb_parni(4) : 0 );
  sftp_handle = libssh2_sftp_open(sftp_session, path, flags, mode);
  if( sftp_handle == NULL ){
    hb_retnl(0);
  }else{
    hb_retnl( (LONG)sftp_handle );
  }
}

// 取得 sftp 錯誤訊息
// #include <libssh2_sftp.h>
// unsigned long libssh2_sftp_last_error(LIBSSH2_SFTP *sftp);
HB_FUNC( SSH2_SFTP_LAST_ERROR ){
  LIBSSH2_SFTP *sftp_session = (LIBSSH2_SFTP *)hb_parnl(1);
  hb_retnl( libssh2_sftp_last_error( sftp_session ));
}

// sftp 讀取資料
// #include <libssh2_sftp.h>
// ssize_t libssh2_sftp_read(LIBSSH2_SFTP_HANDLE *handle, char *buffer, size_t buffer_maxlen);
HB_FUNC( SSH2_SFTP_READ ){
  LIBSSH2_SFTP_HANDLE * sftp_handle = (LIBSSH2_SFTP_HANDLE *)hb_parnl(1);
  LONG nLen;
  char cBuffer[4096];
  nLen = libssh2_sftp_read(sftp_handle, cBuffer, sizeof(cBuffer));
  if(nLen > 0){
    hb_storclen( cBuffer, nLen, 2 ); // 藉由第二參數 buffer 回傳資料
  }else{
    hb_storclen( "", 0, 2 );
  }
  hb_retni( nLen );
}

// 關閉 sftp handle
// int libssh2_sftp_close_handle(LIBSSH2_SFTP_HANDLE *handle);
// int libssh2_sftp_close(LIBSSH2_SFTP_HANDLE *handle);
// int libssh2_sftp_closedir(LIBSSH2_SFTP_HANDLE *handle);
HB_FUNC( SSH2_SFTP_CLOSE ){
  LIBSSH2_SFTP_HANDLE * sftp_handle = (LIBSSH2_SFTP_HANDLE *)hb_parnl(1);
  hb_retni( libssh2_sftp_close( sftp_handle )); // 0:success
}

// 關閉 sftp session
// #include <libssh2_sftp.h>
// int libssh2_sftp_shutdown(LIBSSH2_SFTP *sftp);
HB_FUNC( SSH2_SFTP_SHUTDOWN ){
  LIBSSH2_SFTP * sftp_session = (LIBSSH2_SFTP *) hb_parnl(1);
  hb_retni( libssh2_sftp_shutdown( sftp_session )); // 0:success
}