SFTP協議

galdys發表於2011-08-23
 

SCP協議本身開啟SSH通道時指定的是scp命令,而是用SFTP時指定的sftp。以下是一些具體的介紹,詳細內容需要參考對應的RFC檔案。

下面是目前整理的使用的一份:

1) 協議中資料包格式

通過安全通道傳輸的所有包的格式如下:

     uint32           length

     byte             type

     uint32           request-id

     ... 具體型別域 ...

length:整個包的長度,不包括長度域本身。因此,例如一個不包含具體型別域的包的長度域是5個位元組,那麼將有9個位元組傳送到路線上。實際上包的最大尺寸由客戶端決定(它傳送的讀寫請求包最大尺寸,外加一些位元組的包開銷)。所有伺服器應當支援至少34000位元組的包(這裡的包尺寸是指全長,包括上述頭部)。也就是允許讀寫最多32768個位元組。

 

type:包的型別碼。

 

request-id:從客戶端來的每一個請求包含一個請求ID域,從服務端返回的每個響應也包含和伺服器應答的請求一樣的請求ID。一個可能的是實現是客戶提供給我們一個單調遞增的序號(模除2^32)。然而沒有特殊的要求請求ID域是唯一的。

     

SFTP協議中只有兩個包,INIT和VERSION,不需要使用請求ID。

 

2) 協議中各種包具體格式和響應

包的型別type如下:

SSH_FXP_INIT                1

SSH_FXP_VERSION             2

SSH_FXP_OPEN                3

SSH_FXP_CLOSE               4

SSH_FXP_READ                5

SSH_FXP_WRITE               6

SSH_FXP_LSTAT               7

SSH_FXP_FSTAT               8

SSH_FXP_SETSTAT             9

SSH_FXP_FSETSTAT           10

SSH_FXP_OPENDIR            11

SSH_FXP_READDIR            12

SSH_FXP_REMOVE             13

SSH_FXP_MKDIR              14

SSH_FXP_RMDIR              15

SSH_FXP_REALPATH           16

SSH_FXP_STAT               17

SSH_FXP_RENAME             18

SSH_FXP_READLINK           19

SSH_FXP_LINK               21

SSH_FXP_BLOCK              22

SSH_FXP_UNBLOCK            23

 

SSH_FXP_STATUS            101

SSH_FXP_HANDLE            102

SSH_FXP_DATA              103

SSH_FXP_NAME              104

SSH_FXP_ATTRS             105

 

SSH_FXP_EXTENDED          200

SSH_FXP_EXTENDED_REPLY    201

 

客戶端初始化包

type    SSH_FXP_INIT

uint32  version

 

對這個訊息的響應是下面的伺服器初始化版本包SSH_FXP_VERSION。

 

伺服器初始化包

type    SSH_FXP_VERSION

uint32  version

 

開啟檔案包

byte     SSH_FXP_OPEN

uint32   request-id

string   filename [UTF-8]

uint32   desired-access

uint32   flags

ATTRS  attrs

 

對這個訊息的響應將會是SSH_FXP_HANDLE(如果操作成功的話)或者SSH_FXP_STATUS(如果操作失敗)

 

關閉控制程式碼

byte     SSH_FXP_CLOSE

uint32   request-id

string   handle

 

handle是以前SSH_FXP_OPEN或SSH_FXP_OPENDIR返回的控制程式碼。控制程式碼變為無效後立即請求已傳送。

對此請求的響應將是一個SSH_FXP_STATUS訊息。請注意,在一些伺服器平臺上關閉操作可能會失敗。例如,如果伺服器作業系統快取寫入,在沖洗快取寫入時發生錯誤,關閉操作就可能失敗。

注意不論SSH_FXP_STATUS的結果,控制程式碼是無效的。沒有辦法為客戶恢復關閉失敗的控制程式碼。客戶端必須釋放與控制程式碼關聯的所有資源,無論狀態。伺服器應採取的任何步驟,它可以恢復從關閉失敗,以確保伺服器上的處理相關聯的所有資源正確釋放。

 

讀取檔案

byte     SSH_FXP_READ

uint32   request-id

string   handle

uint64   offset

uint32   length

 

handle 是被SSH_FXP_OPEN返回開啟的檔案控制程式碼。如果不是被SSH_FXP_OPEN返回的控制程式碼,伺服器必須返回SSH_FX_INVALID_HANDLE。

   offset是偏移量(以位元組為單位)相對於讀取檔案開始的地方。此欄位被忽略,如果SSH_FXF_TEXT_MODE指定在開啟的時候。

   length 是讀取的最大位元組數。

      伺服器不能響應比的“length”引數指定的更多的資料。但是,伺服器的響應可能較少的資料,如果達到EOF,遇到一個錯誤,或內部緩衝區的伺服器無法處理這麼大的要求。

      如果伺服器指定一個非零的max-read-size在它的supported2擴充套件中,並且length小於max-read-size,沒有返回length個位元組暗示EOF或者錯誤發生。

 

寫入檔案

byte     SSH_FXP_WRITE

uint32   request-id

string    handle

uint64    offset

string    data

 

   handle是一個開啟檔案控制程式碼被SSH_FXP_OPEN返回的。如果handle不是一個SSH_FXP_OPEN返回的控制程式碼,伺服器必須返回SSH_FX_INVALID_HANDLE。

   offset是偏移量(以位元組為單位),相對於檔案的開頭寫必須開始。此欄位被忽略,如果SSH_FXF_TEXT_MODE是在開啟期間指定。如果超出檔案末尾寫的話,會擴充套件檔案。它是合法的,寫一個偏移量超出該檔案的末尾擴充套件的語義是從檔案末尾寫位元組值0x00指定的偏移,然後是資料。在大多數作業系統上,如寫不分配磁碟空間,而是建立一個稀疏檔案。

   data是要寫入檔案的資料。

   伺服器響應一個寫請求一個SSH_FXP_STATUS訊息。

 

獲取檔案屬性

很多時候,檔案屬性是SSH_FXP_READDIR自動返回的。然而,有些時候需要專門獲得命名檔案的屬性。可以使用SSH_FXP_STAT,SSH_FXP_LSTAT和SSH_FXP_FSTAT請求。

   SSH_FXP_STAT和SSH_FXP_LSTAT不同,僅僅在於SSH_FXP_STAT遵循在伺服器上的符號連結,然而SSH_FXP_LSTAT不遵循符號連結。兩者的有一樣的格式:

  byte     SSH_FXP_STAT or SSH_FXP_LSTAT

  uint32   request-id

  string   path [UTF-8]

  uint32   flags

 

   其中request-id是請求識別符號,path指定狀態被返回的檔案系統物件。伺服器用SSH_FXP_ATTRS或者SSH_FXP_STATUS返回請求。

   flag欄位指定客戶端有特別興趣的屬性標誌。這是到伺服器的提示。例如,在某些作業系統上獲取ower、group和acl資訊是昂貴的操作,伺服器可能不獲取它們除非客戶端表達出特別的興趣。

   客戶端不能保證伺服器提供所有它感興趣的欄位。

  

   SSH_FXP_FSTAT不同於其他在於它返回一個開啟的檔案(檔案控制程式碼標識)的狀態資訊。

   byte      SSH_FXP_FSTAT

   uint32    request-id

   string    handle

   uint32    flags

 

      handle是一個SSH_FXP_OPEN或者SSH_FXP_OPENDIR開啟的檔案控制程式碼。

   伺服器用SSH_FXP_ATTRS或者SSH_FXP_STATUS來響應這個請求。

 

設定檔案屬性

檔案屬性可以使用SSH_FXP_SETSTAT和SSH_FXP_FSETSTAT請求來修改。

byte      SSH_FXP_SETSTAT

uint32    request-id

string    path [UTF-8]

ATTRS     attrs

 

byte      SSH_FXP_FSETSTAT

uint32    request-id

string    handle

ATTRS     attrs

 

path是屬性被修改的檔案系統物件(例如,檔案或者目錄)。如果物件不存在,或者使用者沒有足夠的訪問許可權去改寫屬性,請求會失敗。

handle是SSH_FXP_OPEN或者SSH_FXP_OPENDIR開啟的檔案控制程式碼。如果控制程式碼沒有被足夠的訪問許可權開啟去改寫請求的熟悉,請求會失敗。

attrs指定被應用的修改屬性。更多細節參看File Attributes節。

伺服器用SSH_FXP_STATUS訊息響應。

因為某些系統可能使用分離的系統呼叫來設定各種屬性,可能某些屬性已經被修改了,仍然返回一個失敗的響應。如果可能,伺服器應該避免這種情況;然而,客戶端必須清楚這種可能性。

 

開啟目錄

byte     SSH_FXP_OPENDIR

uint32   request-id

string   path [UTF-8]

 

path欄位是列舉的(沒有任何尾隨的斜線)的目錄的路徑名。更多資訊參看“File Names”。

如果“路徑”並不是指到一個目錄,伺服器必須返回SSH_FX_NOT_A_DIRECTORY。

此訊息的響應,將要麼SSH_FXP_HANDLE(如果操作成功)或SSH_FXP_STATUS(如果操作失敗)。

 

讀取目錄

byte     SSH_FXP_READDIR

uint32   request-id

string   handle

 

handle是由SSH_FXP_OPENDIR返回的控制程式碼。如果handle是一個SSH_FXP_OPEN返回普通的檔案控制程式碼,伺服器必須返回SSH_FX_INVALID_HANDLE。

伺服器用一個SSH_FXP_NAME或SSH_FXP_STATUS訊息響應這個請求。在一段時間,可能會返回一個或多個名稱。完整的狀態資訊返回每個名稱,以加速典型的目錄清單。

如果沒有更多的名字可以讀取,伺服器必須響應一個SSH_FXP_STATUS訊息,錯誤程式碼的SSH_FX_EOF

 

刪除檔案

byte      SSH_FXP_REMOVE

uint32    request-id

string    filename [UTF-8]

filename是要刪除的檔名稱。更多資訊參考“File Names”。

如果filename是一個符號連結,連結被刪除,指向的檔案不會被刪除。

這個請求不能被用於移除目錄,在這種情況下,伺服器必須返回SSH_FX_FILE_IS_A_DIRECTORY。

伺服器將會用SSH_FXP_STATUS訊息響應這個請求。

 

重新命名檔案

byte       SSH_FXP_RENAME

uint32     request-id

string     oldpath [UTF-8]

string     newpath [UTF-8]

uint32     flags

 

  其中“request-id”是請求識別符號,“oldpath“是現有的檔案或目錄的名稱,”newpath“是為新的檔案或目錄名稱。

   'flags' 是 0 或者以下值的組合:

   SSH_FXF_RENAME_OVERWRITE  0x00000001

   SSH_FXF_RENAME_ATOMIC     0x00000002

   SSH_FXF_RENAME_NATIVE     0x00000004

   如果伺服器不支援請求的操作模式,它必須返回SSH_FX_OP_UNSUPPORTED。

   如果flags不包括SSH_FXP_RENAME_OVERWRITE,newpath指定的名稱已經存在一個檔案,伺服器必須響應SSH_FX_FILE_ALREADY_EXISTS。

   如果flags包括SSH_FXP_RENAME_ATOMIC,目標檔案已存在,它是在一個原子的方式取代。例如,有沒有在時間上觀察到的瞬間,其中的名稱並不是指無論是舊的或新的檔案。 SSH_FXP_RENAME_ATOMIC意味著SSH_FXP_RENAME_OVERWRITE。

   伺服器將用SSH_FXP_STATUS訊息來回應這個請求。

 

建立目錄

byte      SSH_FXP_MKDIR

uint32    request-id

string    path [UTF-8]

ATTRS  attrs

其中request-id是請求識別符號,path指定被建立的目錄,attrs指定了應該被應用到建立上的屬性。

伺服器將用SSH_FXP_STATUS訊息來響應這個請求。如果指定的檔案或者目錄已經存在了,錯誤將被返回。

 

移除目錄

byte     SSH_FXP_RMDIR

uint32   request-id

string   path [UTF-8]

 

其中request-id是請求識別符號,path指定被移除的目錄。

伺服器用SSH_FXP_STATUS訊息響應請求。

 

狀態響應

SSH_FXP_STATUS響應資料部分的格式如下:

byte     SSH_FXP_STATUS

uint32   request-id

uint32   error/status code

string   error message (ISO-10646 UTF-8 [RFC-2279])

string   language tag (as defined in [RFC-1766])

error-specific data

 

request-id指示服務端響應的客戶端請求。

error/status code是機器可讀的狀態程式碼指示請求的結果。值SSH_FX_OK指示成功,其他值指示失敗。實現必須準備能收到意想不到的錯誤程式碼,他們理智地處理(如他們視為等同於SSH_FX_FAILURE)。

error message是人類可讀的錯誤描述。

language tag指示錯誤使用的語言。

error-specific data可能是空的,可能包含附加的錯誤資訊。

 

控制程式碼響應

SSH_FXP_HANDLE響應的格式如下:

byte      SSH_FXP_HANDLE

uint32    request-id

string    handle

 

handle是一個任意的字串,用於標識一個開啟的檔案或伺服器上的目錄。控制程式碼對客戶端是不透明的,不要試圖以任何方式解釋或修改它。控制程式碼字串的長度不能超過256個位元組的資料。

 

資料響應

SSH_FXP_DATA響應的格式如下:

byte     SSH_FXP_DATA

uint32   request-id

string   data

bool     end-of-file [optional]

      

data是一個任意位元組的字串,其中包含請求的資料。資料字串最多可能被要求在SSH_FXP_READ請求的位元組數,但也可能較短。

end-of-file此欄位是可選的,如果是存在和為真的,它表明,EOF的是讀期間到達的。這可以幫助客戶避免了往返,以確定短讀是否正常(由於EOF)或一些其他問題(例如有限的伺服器的緩衝區。)

名稱響應

SSH_FXP_NAME響應的格式如下:

byte     SSH_FXP_NAME

uint32   request-id

uint32   count

repeats  count times:

    string       filename [UTF-8]

    ATTRS        attrs

bool     end-of-list [optional]

 

count在這個響應中返回的名稱的數目,filename和attrs重複count次。

filename是被返回的檔名。

attrs是該檔案的屬性。

end-of-list如果這個欄位是存在的和為真,沒有更多的讀取條目了。除非請求是SSH_FXP_READDIR,否則欄位應該被省略或為真。

 

屬性響應

SSH_FXP_ATTRS響應的格式如下:

byte      SSH_FXP_ATTRS

uint32    request-id

ATTRS     attrs

 

attrs返回的檔案屬性。

 

1) 協議工作流程

客戶端向伺服器端上傳送檔案

 

客戶端從伺服器端上獲取檔案

 

 

相關文章