Skip to content

Commit ecce13b

Browse files
committed
nassh: sftp: improve server version packet parsing
The version packet from the server can be parsed like any other response packet, other than the fact that requestId is not set. Since we're already stuffing the pendingRequests_ with 'init' as a fake requestId, lets use that in our version packets too. This lets us drop the custom VERSION check in the onPacket call. While we're here, lets parse out the optional extensions the server might send over in its VERSION response. Bug: chromium:722175 Change-Id: I7c20b49f3e37aaa00767ea68674fffb8dda0a429 Reviewed-on: https://chromium-review.googlesource.com/c/1286249 Reviewed-by: Vitaliy Shipitsyn <[email protected]> Tested-by: Mike Frysinger <[email protected]>
1 parent ab6ec9f commit ecce13b

File tree

3 files changed

+86
-7
lines changed

3 files changed

+86
-7
lines changed

nassh/js/nassh_sftp_client.js

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,11 @@ nassh.sftp = {};
1313
*/
1414
nassh.sftp.Client = function(opt_basePath='') {
1515
// The version of the protocol we're using.
16-
this.protoVersion = 3;
16+
this.protocolClientVersion = 3;
17+
18+
// Extensions that the server supports.
19+
this.protocolServerVersion = null;
20+
this.protocolServerExtensions = {};
1721

1822
// The packet request id counter.
1923
this.requestId_ = 0;
@@ -99,10 +103,6 @@ nassh.sftp.Client.prototype.parseBuffer = function() {
99103
*/
100104
nassh.sftp.Client.prototype.onPacket = function(packet) {
101105
var packetType = packet.getUint8();
102-
if (packetType == nassh.sftp.packets.RequestPackets.VERSION) {
103-
this.pendingRequests_['init']();
104-
return true;
105-
}
106106

107107
// Obtain the response packet's constructor and create it.
108108
var ResponseType = nassh.sftp.packets.ResponsePackets[packetType]
@@ -234,11 +234,13 @@ nassh.sftp.Client.prototype.init = function() {
234234
var packet = new nassh.sftp.Packet();
235235
packet.setUint32(5); // length, 5 bytes for type and version fields
236236
packet.setUint8(nassh.sftp.packets.RequestPackets.INIT);
237-
packet.setUint32(this.protoVersion);
237+
packet.setUint32(this.protocolClientVersion);
238238

239-
this.pendingRequests_['init'] = () => {
239+
this.pendingRequests_['init'] = (packet) => {
240240
console.log('init: SFTP');
241241
this.onInit();
242+
this.protocolServerVersion = packet.version;
243+
this.protocolServerExtensions = packet.extensions;
242244
this.isInitialised = true;
243245
};
244246
this.sendToPlugin_('onRead', [0, btoa(packet.toString())]);

nassh/js/nassh_sftp_packet.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,15 @@ nassh.sftp.Packet.prototype.getLength = function() {
159159
return this.packet_.length;
160160
};
161161

162+
/**
163+
* Check whether the end of the packet data has been reached.
164+
*
165+
* @returns {!boolean} true If the end of the packet data has been reached.
166+
*/
167+
nassh.sftp.Packet.prototype.eod = function() {
168+
return this.offset_ === this.packet_.length;
169+
};
170+
162171
/**
163172
* Converts a byte array string to an int
164173
*/

nassh/js/nassh_sftp_packet_types.js

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,73 @@ nassh.sftp.packets.AttrsPacket = function(packet) {
7878
this.attrs = nassh.sftp.packets.getFileAttrs(packet);
7979
};
8080

81+
/**
82+
* Make sure the name conforms to the specification.
83+
*
84+
* The SFTP RFC defines the extension-name format:
85+
* https://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-4.2
86+
*
87+
* Which says to follow the SSH "Algorithm and Method Naming" RFC format:
88+
* https://tools.ietf.org/html/rfc4251#section-6
89+
*
90+
* Really we just need this func to filter out extensions that we don't care
91+
* about in our implementation. If another one shows up, we can revisit.
92+
*
93+
* @param {string} name The protocol name to check.
94+
* @return {boolean} True if the name is valid.
95+
*/
96+
nassh.sftp.packets.ValidExtension = function(ext) {
97+
// The RFC is a little ambiguous, but it uses "name" to refer to the entire
98+
// extension name, not just sub-components (when using the @ form).
99+
if (ext.length > 64) {
100+
return false;
101+
}
102+
103+
// Split apart the extension@domain format.
104+
const ary = ext.split('@');
105+
if (ary.length > 2) {
106+
return false;
107+
}
108+
const [name, domain] = ary;
109+
110+
// Names cannot contain control chars or whitespace (0x00-0x20), "@" (0x40),
111+
// "," (0x2c), or DEL (0x7f). So remove all valid chars and make sure the
112+
// result is an empty string.
113+
if (name.length == 0 ||
114+
name.replace(/[\x21-\x2b\x2d-\x3f\x41-\x7e]/g, '').length != 0) {
115+
return false;
116+
}
117+
118+
// The domain part is supposed to be a bit more strict ("a valid domain"),
119+
// but using the same form as above should be good enough.
120+
if (domain !== undefined) {
121+
if (domain.replace(/[\x21-\x2b\x2d-\x3f\x41-\x7e]/g, '').length != 0) {
122+
return false;
123+
}
124+
}
125+
126+
return true;
127+
};
128+
129+
/**
130+
* SFTP Version Packet containing the version and possible extensions.
131+
*/
132+
nassh.sftp.packets.VersionPacket = function(packet) {
133+
this.requestId = 'init';
134+
this.version = packet.getUint32();
135+
136+
// Pull out all the extensions that might exist.
137+
this.extensions = {};
138+
while (!packet.eod()) {
139+
const name = packet.getString();
140+
const data = packet.getString();
141+
// The SFTP RFC says we should silently ignore unknown/invalid entries.
142+
if (nassh.sftp.packets.ValidExtension(name)) {
143+
this.extensions[name] = data;
144+
}
145+
}
146+
};
147+
81148
/**
82149
* Unknown Packet containing the request id (potentially garbage) and associated
83150
* data (also potentially garbage).
@@ -284,6 +351,7 @@ nassh.sftp.packets.RequestPackets = {
284351
* Possible SFTP Response Packet types
285352
*/
286353
nassh.sftp.packets.ResponsePackets = {
354+
2: nassh.sftp.packets.VersionPacket,
287355
101: nassh.sftp.packets.StatusPacket,
288356
102: nassh.sftp.packets.HandlePacket,
289357
103: nassh.sftp.packets.DataPacket,

0 commit comments

Comments
 (0)