Commit 4b7d8773 authored by Julien Fontanet's avatar Julien Fontanet

chore: format with Prettier

parent 0d4574ab
{
"singleQuote": true,
"trailingComma": "es5"
}
var SMB2Connection = require('../tools/smb2-connection');
/*
* close
* =====
......@@ -13,8 +9,6 @@ var SMB2Connection = require('../tools/smb2-connection');
* - close TCP connection
*
*/
module.exports = function(){
module.exports = function() {
SMB2Connection.close(this);
}
};
var SMB2Forge = require('../tools/smb2-forge')
, SMB2Request = SMB2Forge.request
;
var SMB2Forge = require('../tools/smb2-forge'),
SMB2Request = SMB2Forge.request;
/*
* exists
......@@ -15,15 +12,14 @@ var SMB2Forge = require('../tools/smb2-forge')
* - close the file
*
*/
module.exports = function(path, cb){
module.exports = function(path, cb) {
var connection = this;
SMB2Request('open', {path:path}, connection, function(err, file){
if(err) cb && cb(null, false);
else SMB2Request('close', file, connection, function(err){
cb && cb(null, true);
});
SMB2Request('open', { path: path }, connection, function(err, file) {
if (err) cb && cb(null, false);
else
SMB2Request('close', file, connection, function(err) {
cb && cb(null, true);
});
});
}
};
var SMB2Forge = require('../tools/smb2-forge')
, SMB2Request = SMB2Forge.request
;
var SMB2Forge = require('../tools/smb2-forge'),
SMB2Request = SMB2Forge.request;
/*
* mkdir
......@@ -15,37 +12,31 @@ var SMB2Forge = require('../tools/smb2-forge')
* - close the folder
*
*/
module.exports = function(path, mode, cb){
if(typeof mode == 'function'){
module.exports = function(path, mode, cb) {
if (typeof mode == 'function') {
cb = mode;
mode = '0777';
}
var connection = this;
connection.exists(path, function(err, exists){
if(err) cb && cb(err);
else if(!exists){
connection.exists(path, function(err, exists) {
if (err) cb && cb(err);
else if (!exists) {
// SMB2 open file
SMB2Request('create_folder', {path:path}, connection, function(err, file){
if(err) cb && cb(err);
SMB2Request('create_folder', { path: path }, connection, function(
err,
file
) {
if (err) cb && cb(err);
// SMB2 query directory
else SMB2Request('close', file, connection, function(err){
cb && cb(null);
});
else
SMB2Request('close', file, connection, function(err) {
cb && cb(null);
});
});
} else {
cb(new Error('File/Folder already exists'));
}
});
}
};
var SMB2Forge = require('../tools/smb2-forge')
, SMB2Request = SMB2Forge.request
;
var SMB2Forge = require('../tools/smb2-forge'),
SMB2Request = SMB2Forge.request;
/*
* readdir
......@@ -17,27 +14,31 @@ var SMB2Forge = require('../tools/smb2-forge')
* - close the directory
*
*/
module.exports = function(path, cb){
module.exports = function(path, cb) {
var connection = this;
// SMB2 open directory
SMB2Request('open', {path:path}, connection, function(err, file){
if(err) cb && cb(err);
SMB2Request('open', { path: path }, connection, function(err, file) {
if (err) cb && cb(err);
// SMB2 query directory
else SMB2Request('query_directory', file, connection, function(err, files){
if(err) cb && cb(err);
// SMB2 close directory
else SMB2Request('close', file, connection, function(err){
cb && cb(
null
, files
.map(function(v){ return v.Filename }) // get the filename only
.filter(function(v){ return v!='.' && v!='..' }) // remove '.' and '..' values
);
else
SMB2Request('query_directory', file, connection, function(err, files) {
if (err) cb && cb(err);
// SMB2 close directory
else
SMB2Request('close', file, connection, function(err) {
cb &&
cb(
null,
files
.map(function(v) {
return v.Filename;
}) // get the filename only
.filter(function(v) {
return v != '.' && v != '..';
}) // remove '.' and '..' values
);
});
});
});
});
}
};
var SMB2Forge = require('../tools/smb2-forge')
, SMB2Request = SMB2Forge.request
, bigint = require('../tools/bigint')
;
var SMB2Forge = require('../tools/smb2-forge'),
SMB2Request = SMB2Forge.request,
bigint = require('../tools/bigint');
/*
* readFile
......@@ -18,34 +15,33 @@ var SMB2Forge = require('../tools/smb2-forge')
* - close the file
*
*/
module.exports = function(filename, options, cb){
module.exports = function(filename, options, cb) {
var connection = this;
if(typeof options == 'function'){
if (typeof options == 'function') {
cb = options;
options = {};
}
SMB2Request('open', {path:filename}, connection, function(err, file){
if(err) cb && cb(err);
SMB2Request('open', { path: filename }, connection, function(err, file) {
if (err) cb && cb(err);
// SMB2 read file content
else {
var fileLength = 0
, offset = new bigint(8)
, stop = false
, nbRemainingPackets = 0
, maxPacketSize = 0x00010000
;
var fileLength = 0,
offset = new bigint(8),
stop = false,
nbRemainingPackets = 0,
maxPacketSize = 0x00010000;
// get file length
for(var i=0;i<file.EndofFile.length;i++){
for (var i = 0; i < file.EndofFile.length; i++) {
fileLength += file.EndofFile[i] * Math.pow(2, i * 8);
}
var result = new Buffer(fileLength);
// callback manager
function callback(offset){
return function(err, content){
if(stop) return;
if(err) {
function callback(offset) {
return function(err, content) {
if (stop) return;
if (err) {
cb && cb(err);
stop = true;
} else {
......@@ -53,33 +49,43 @@ module.exports = function(filename, options, cb){
nbRemainingPackets--;
checkDone();
}
}
};
}
// callback manager
function checkDone(){
if(stop) return;
function checkDone() {
if (stop) return;
createPackets();
if(nbRemainingPackets==0 && offset.ge(fileLength)) {
SMB2Request('close', file, connection, function(err){
if(options.encoding){
if (nbRemainingPackets == 0 && offset.ge(fileLength)) {
SMB2Request('close', file, connection, function(err) {
if (options.encoding) {
result = result.toString(options.encoding);
}
cb && cb(null, result);
})
});
}
}
// create packets
function createPackets(){
while(nbRemainingPackets<connection.packetConcurrency && offset.lt(fileLength)){
function createPackets() {
while (
nbRemainingPackets < connection.packetConcurrency &&
offset.lt(fileLength)
) {
// process packet size
var rest = offset.sub(fileLength).neg();
var packetSize = rest.gt(maxPacketSize) ? maxPacketSize : rest.toNumber();
var packetSize = rest.gt(maxPacketSize)
? maxPacketSize
: rest.toNumber();
// generate buffer
SMB2Request('read', {
'FileId':file.FileId
, 'Length':packetSize
, 'Offset':offset.toBuffer()
}, connection, callback(offset));
SMB2Request(
'read',
{
FileId: file.FileId,
Length: packetSize,
Offset: offset.toBuffer(),
},
connection,
callback(offset)
);
offset = offset.add(packetSize);
nbRemainingPackets++;
}
......@@ -87,4 +93,4 @@ module.exports = function(filename, options, cb){
checkDone();
}
});
}
};
var bigint = require('../tools/bigint')
var SMB2Request = require('../tools/smb2-forge').request
var FILE_OPEN_IF = require('../structures/constants').FILE_OPEN_IF
var bigint = require('../tools/bigint');
var SMB2Request = require('../tools/smb2-forge').request;
var FILE_OPEN_IF = require('../structures/constants').FILE_OPEN_IF;
/*
* rename
......@@ -15,55 +15,66 @@ var FILE_OPEN_IF = require('../structures/constants').FILE_OPEN_IF
* - close the file
*
*/
module.exports = function(oldPath, newPath, cb){
module.exports = function(oldPath, newPath, cb) {
var connection = this;
// SMB2 open the folder / file
SMB2Request('open_folder', {path:oldPath}, connection, function(err, file){
if (err) SMB2Request('create', { path: oldPath, createDisposition: FILE_OPEN_IF }, connection, function (err, file) {
if(err) cb && cb(err);
else rename(connection, file, newPath, cb);
});
SMB2Request('open_folder', { path: oldPath }, connection, function(
err,
file
) {
if (err)
SMB2Request(
'create',
{ path: oldPath, createDisposition: FILE_OPEN_IF },
connection,
function(err, file) {
if (err) cb && cb(err);
else rename(connection, file, newPath, cb);
}
);
else rename(connection, file, newPath, cb);
});
};
}
function rename (connection, file, newPath, cb) {
function rename(connection, file, newPath, cb) {
// SMB2 rename
SMB2Request('set_info', {FileId:file.FileId, FileInfoClass:'FileRenameInformation',Buffer:renameBuffer(newPath)}, connection, function(err){
if(err) cb && cb(err);
// SMB2 close file
else SMB2Request('close', file, connection, function(err){
cb && cb(null);
});
});
SMB2Request(
'set_info',
{
FileId: file.FileId,
FileInfoClass: 'FileRenameInformation',
Buffer: renameBuffer(newPath),
},
connection,
function(err) {
if (err) cb && cb(err);
// SMB2 close file
else
SMB2Request('close', file, connection, function(err) {
cb && cb(null);
});
}
);
}
function renameBuffer (newPath) {
function renameBuffer(newPath) {
var filename = new Buffer(newPath, 'ucs2');
return Buffer.concat([
// ReplaceIfExists 1 byte
(new bigint(1,0)).toBuffer()
new bigint(1, 0).toBuffer(),
// Reserved 7 bytes
, (new bigint(7,0)).toBuffer()
new bigint(7, 0).toBuffer(),
// RootDirectory 8 bytes
, (new bigint(8,0)).toBuffer()
new bigint(8, 0).toBuffer(),
// FileNameLength 4 bytes
, (new bigint(4,filename.length)).toBuffer()
new bigint(4, filename.length).toBuffer(),
// FileName
, filename
filename,
]);
}
var SMB2Forge = require('../tools/smb2-forge')
, SMB2Request = SMB2Forge.request
, bigint = require('../tools/bigint')
;
var SMB2Forge = require('../tools/smb2-forge'),
SMB2Request = SMB2Forge.request,
bigint = require('../tools/bigint');
/*
* rmdir
......@@ -18,34 +15,40 @@ var SMB2Forge = require('../tools/smb2-forge')
* - close the folder
*
*/
module.exports = function(path, cb){
module.exports = function(path, cb) {
var connection = this;
connection.exists(path, function(err, exists){
if(err) cb && cb(err);
else if(exists){
connection.exists(path, function(err, exists) {
if (err) cb && cb(err);
else if (exists) {
// SMB2 open file
SMB2Request('open_folder', {path:path}, connection, function(err, file){
if(err) cb && cb(err);
SMB2Request('open_folder', { path: path }, connection, function(
err,
file
) {
if (err) cb && cb(err);
// SMB2 query directory
else SMB2Request('set_info', {FileId:file.FileId, FileInfoClass:'FileDispositionInformation',Buffer:(new bigint(1,1)).toBuffer()}, connection, function(err, files){
if(err) cb && cb(err);
// SMB2 close directory
else SMB2Request('close', file, connection, function(err){
cb && cb(null, files);
});
});
else
SMB2Request(
'set_info',
{
FileId: file.FileId,
FileInfoClass: 'FileDispositionInformation',
Buffer: new bigint(1, 1).toBuffer(),
},
connection,
function(err, files) {
if (err) cb && cb(err);
// SMB2 close directory
else
SMB2Request('close', file, connection, function(err) {
cb && cb(null, files);
});
}
);
});
} else {
cb(new Error('Folder does not exists'));
}
});
}
};
import Bigint from '../tools/bigint'
import Bluebird from 'bluebird'
import {Readable} from 'stream'
import {request} from '../tools/smb2-forge'
import Bigint from '../tools/bigint';
import Bluebird from 'bluebird';
import { Readable } from 'stream';
import { request } from '../tools/smb2-forge';
const requestAsync = Bluebird.promisify(request)
const requestAsync = Bluebird.promisify(request);
const maxPacketSize = 0x00010000
const maxPacketSize = 0x00010000;
class SmbReadableStream extends Readable {
constructor (connection, file, options = {}) {
super(options)
constructor(connection, file, options = {}) {
super(options);
const {
start = 0,
end,
encoding
} = options
const { start = 0, end, encoding } = options;
this.connection = connection
this.encoding = encoding
this.file = file
this.offset = new Bigint(8, start)
this.connection = connection;
this.encoding = encoding;
this.file = file;
this.offset = new Bigint(8, start);
let fileLength = 0
let fileLength = 0;
for (let i = 0; i < file.EndofFile.length; i++) {
fileLength += file.EndofFile[i] * Math.pow(2, i * 8)
fileLength += file.EndofFile[i] * Math.pow(2, i * 8);
}
this.fileLength = fileLength
this.wait = false
this.fileLength = fileLength;
this.wait = false;
if (end >= 0 && end < fileLength) {
this.fileLength = end + 1
this.fileLength = end + 1;
}
}
async _read (size) {
while (this.offset.lt(this.fileLength)/* && size > 0*/) {
async _read(size) {
while (this.offset.lt(this.fileLength) /* && size > 0*/) {
if (this.wait) {
return
return;
}
const rest = this.offset.sub(this.fileLength).neg()
const packetSize = Math.min(maxPacketSize, rest.toNumber()/*, size*/)
const rest = this.offset.sub(this.fileLength).neg();
const packetSize = Math.min(maxPacketSize, rest.toNumber() /*, size*/);
const offset = new Bigint(this.offset)
this.wait = true
let content = await requestAsync('read', {
FileId: this.file.FileId,
Length: packetSize,
Offset: offset.toBuffer()
}, this.connection)
this.wait = false
const offset = new Bigint(this.offset);
this.wait = true;
let content = await requestAsync(
'read',
{
FileId: this.file.FileId,
Length: packetSize,
Offset: offset.toBuffer(),
},
this.connection
);
this.wait = false;
if (this.encoding) {
content = content.toString(this.encoding)
content = content.toString(this.encoding);
}
this.offset = this.offset.add(packetSize)
this.offset = this.offset.add(packetSize);
// size -= packetSize
if (!this.push(content)) {
return
return;
}
}
if (this.offset.ge(this.fileLength)) {
this.push(null)
await requestAsync('close', this.file, this.connection)
this.push(null);
await requestAsync('close', this.file, this.connection);
}
}
}
export default function (path, options, cb) {
export default function(path, options, cb) {
if (typeof options === 'function') {
cb = options
options = {}
cb = options;
options = {};
}
request('open', {path}, this, (err, file) => {
request('open', { path }, this, (err, file) => {
if (err) {
if (err.code === 'STATUS_OBJECT_NAME_NOT_FOUND') {
err.code = 'ENOENT'
err.code = 'ENOENT';
}
cb(err)
cb(err);
} else {
cb(null, new SmbReadableStream(this, file, options))
cb(null, new SmbReadableStream(this, file, options));
}
})
});
}
import Bigint from '../tools/bigint'
import Bluebird from 'bluebird'
import {request} from '../tools/smb2-forge'
import {Writable} from 'stream'
import Bigint from '../tools/bigint';
import Bluebird from 'bluebird';
import { request } from '../tools/smb2-forge';
import { Writable } from 'stream';
import {
FILE_OPEN,
FILE_OPEN_IF,
FILE_OVERWRITE_IF,
FILE_CREATE
} from '../structures/constants'
FILE_CREATE,
} from '../structures/constants';
const requestAsync = Bluebird.promisify(request)
const requestAsync = Bluebird.promisify(request);
const maxPacketSize = new Bigint(8, 0x00010000 - 0x71)
const maxPacketSize = new Bigint(8, 0x00010000 - 0x71);
function * fibonacci () {
let a = 1
let b = 2
function* fibonacci() {
let a = 1;
let b = 2;
for (;;) {
const c = a
a = b
b = c + a
yield c
const c = a;
a = b;
b = c + a;
yield c;
}
}
class SmbWritableStream extends Writable {
constructor (connection, file, options = {}) {
super(options)
const {
encoding = 'utf8',
start = 0
} = options
this.connection = connection
this.encoding = encoding
this.file = file
this.offset = new Bigint(8, start)
constructor(connection, file, options = {}) {
super(options);
const { encoding = 'utf8', start = 0 } = options;
this.connection = connection;
this.encoding = encoding;
this.file = file;
this.offset = new Bigint(8, start);
}
async _write (chunk, encoding, next) {
encoding = this.encoding || encoding
chunk = Buffer.isBuffer(chunk) ? chunk : new Buffer(chunk, encoding)
async _write(chunk, encoding, next) {
encoding = this.encoding || encoding;
chunk = Buffer.isBuffer(chunk) ? chunk : new Buffer(chunk, encoding);
while (chunk.length > 0) {
const packetSize = Math.min(maxPacketSize.toNumber(), chunk.length)
const packet = chunk.slice(0, packetSize)
chunk = chunk.slice(packetSize)
const offset = new Bigint(this.offset)
this.offset = this.offset.add(packetSize)
const packetSize = Math.min(maxPacketSize.toNumber(), chunk.length);
const packet = chunk.slice(0, packetSize);
chunk = chunk.slice(packetSize);
const offset = new Bigint(this.offset);
this.offset = this.offset.add(packetSize);
const retryInterval = fibonacci()
let pending = true
const retryInterval = fibonacci();
let pending = true;
while (pending) {
try {
await requestAsync('write', {
FileId: this.file.FileId,
Offset: offset.toBuffer(),
Buffer: packet
}, this.connection)
pending = false
await requestAsync(
'write',
{
FileId: this.file.FileId,
Offset: offset.toBuffer(),
Buffer: packet,
},
this.connection
);
pending = false;
} catch (error) {
if (error.code === 'STATUS_PENDING') {
await new Promise((resolve, reject) => {
setTimeout(resolve, retryInterval.next().value)
})
setTimeout(resolve, retryInterval.next().value);
});
} else {
throw error
throw error;
}
}
}
}
next()
next();
}
async end (...args) {
async end(...args) {
try {
super.end(...args)
super.end(...args);
} finally {
await requestAsync('close', this.file, this.connection)
await requestAsync('close', this.file, this.connection);
}
}
}
export default function (path, options, cb) {
export default function(path, options, cb) {
if (typeof options === 'function') {
cb = options
options = {}
cb = options;
options = {};
}
let createDisposition
const flags = options && options.flags
let createDisposition;
const flags = options && options.flags;
if (flags === 'r') {
createDisposition = FILE_OPEN
createDisposition = FILE_OPEN;
} else if (flags === 'r+') {
createDisposition = FILE_OPEN_IF
createDisposition = FILE_OPEN_IF;
} else if (flags === 'w' || flags === 'w+') {
createDisposition = FILE_OVERWRITE_IF
createDisposition = FILE_OVERWRITE_IF;
} else if (flags === 'wx' || flags === 'w+x') {
createDisposition = FILE_CREATE
createDisposition = FILE_CREATE;
}
request('create', { path, createDisposition }, this, (err, file) => {
if (err) {
cb(err)
cb(err);
} else {
cb(null, new SmbWritableStream(this, file, options))
cb(null, new SmbWritableStream(this, file, options));
}
})
});
}
import {request} from '../tools/smb2-forge'
import Bluebird from 'bluebird'
import { request } from '../tools/smb2-forge';
import Bluebird from 'bluebird';
const requestAsync = Bluebird.promisify(request)
const requestAsync = Bluebird.promisify(request);
const ensureOneDir = async function (path, connection) {
const ensureOneDir = async function(path, connection) {
try {
const fileOrDir = await requestAsync('open', {path}, connection)
if (fileOrDir.FileAttributes.readIntBE(0, 1) === 0x00000010) { // See http://download.microsoft.com/DOWNLOAD/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/[MS-FSCC].pdf Section 2.6
await requestAsync('close', fileOrDir, connection)
const fileOrDir = await requestAsync('open', { path }, connection);
if (fileOrDir.FileAttributes.readIntBE(0, 1) === 0x00000010) {
// See http://download.microsoft.com/DOWNLOAD/9/5/E/95EF66AF-9026-4BB0-A41D-A4F81802D92C/[MS-FSCC].pdf Section 2.6
await requestAsync('close', fileOrDir, connection);
} else {
throw new Error(`${path} exists but is not a directory`)
throw new Error(`${path} exists but is not a directory`);
}
} catch (err) {
if (err.code === 'STATUS_OBJECT_NAME_NOT_FOUND') {
try {
await requestAsync('create_folder', {path}, connection)
await requestAsync('create_folder', { path }, connection);
} catch (err) {
if (err.code !== 'STATUS_OBJECT_NAME_COLLISION') {
throw err
throw err;
}
}
} else {
throw err
throw err;
}
}
}
};
export default async function (path, cb) {
const structure = path.split('\\')
const base = []
export default async function(path, cb) {
const structure = path.split('\\');
const base = [];
try {
while (structure.length) {
base.push(structure.shift())
const basePath = base.join('\\')
base.push(structure.shift());
const basePath = base.join('\\');
if (!basePath.length) {
continue
continue;
}
await ensureOneDir(basePath, this)
await ensureOneDir(basePath, this);
}
cb(null)
cb(null);
} catch (error) {
cb(error)
cb(error);
}
}
import {request} from '../tools/smb2-forge'
import { request } from '../tools/smb2-forge';
export default function (path, cb) {
request('open', {path}, this, (err, file) => {
export default function(path, cb) {
request('open', { path }, this, (err, file) => {
if (err) {
if (err.code === 'STATUS_OBJECT_NAME_NOT_FOUND') {
err.code = 'ENOENT'
err.code = 'ENOENT';
}
cb(err)
cb(err);
} else {
let fileLength = 0
let fileLength = 0;
for (let i = 0; i < file.EndofFile.length; i++) {
fileLength += file.EndofFile[i] * Math.pow(2, i * 8)
fileLength += file.EndofFile[i] * Math.pow(2, i * 8);
}
cb(null, fileLength)
cb(null, fileLength);
}
})
});
}
var SMB2Forge = require('../tools/smb2-forge')
, SMB2Request = SMB2Forge.request
, bigint = require('../tools/bigint')
;
var SMB2Forge = require('../tools/smb2-forge'),
SMB2Request = SMB2Forge.request,
bigint = require('../tools/bigint');
/*
* unlink
......@@ -18,34 +15,37 @@ var SMB2Forge = require('../tools/smb2-forge')
* - close the file
*
*/
module.exports = function(path, cb){
module.exports = function(path, cb) {
var connection = this;
connection.exists(path, function(err, exists){
if(err) cb && cb(err);
else if(exists){
connection.exists(path, function(err, exists) {
if (err) cb && cb(err);
else if (exists) {
// SMB2 open file
SMB2Request('create', {path:path}, connection, function(err, file){
if(err) cb && cb(err);
SMB2Request('create', { path: path }, connection, function(err, file) {
if (err) cb && cb(err);
// SMB2 query directory
else SMB2Request('set_info', {FileId:file.FileId, FileInfoClass:'FileDispositionInformation',Buffer:(new bigint(1,1)).toBuffer()}, connection, function(err, files){
if(err) cb && cb(err);
// SMB2 close directory
else SMB2Request('close', file, connection, function(err){
cb && cb(null, files);
});
});
else
SMB2Request(
'set_info',
{
FileId: file.FileId,
FileInfoClass: 'FileDispositionInformation',
Buffer: new bigint(1, 1).toBuffer(),
},
connection,
function(err, files) {
if (err) cb && cb(err);
// SMB2 close directory
else
SMB2Request('close', file, connection, function(err) {
cb && cb(null, files);
});
}
);
});
} else {
cb(new Error('File does not exists'));
}
});
}
\ No newline at end of file
};
var SMB2Forge = require('../tools/smb2-forge')
, SMB2Request = SMB2Forge.request
, bigint = require('../tools/bigint')
;
var SMB2Forge = require('../tools/smb2-forge'),
SMB2Request = SMB2Forge.request,
bigint = require('../tools/bigint');
/*
* writeFile
......@@ -20,24 +17,24 @@ var SMB2Forge = require('../tools/smb2-forge')
* - close the file
*
*/
module.exports = function(filename, data, options, cb){
if(typeof options == 'function'){
module.exports = function(filename, data, options, cb) {
if (typeof options == 'function') {
cb = options;
options = {};
}
options.encoding = options.encoding || 'utf8';
var connection = this
, file
, fileContent = Buffer.isBuffer(data) ? data : new Buffer(data, options.encoding)
, fileLength = new bigint(8, fileContent.length)
;
var connection = this,
file,
fileContent = Buffer.isBuffer(data)
? data
: new Buffer(data, options.encoding),
fileLength = new bigint(8, fileContent.length);
function createFile(fileCreated){
SMB2Request('create', {path:filename}, connection, function(err, f){
if(err) cb && cb(err);
function createFile(fileCreated) {
SMB2Request('create', { path: filename }, connection, function(err, f) {
if (err) cb && cb(err);
// SMB2 set file size
else {
file = f;
......@@ -46,9 +43,9 @@ module.exports = function(filename, data, options, cb){
});
}
function closeFile(fileClosed){
SMB2Request('close', file, connection, function(err){
if(err) cb && cb(err);
function closeFile(fileClosed) {
SMB2Request('close', file, connection, function(err) {
if (err) cb && cb(err);
else {
file = null;
fileClosed();
......@@ -56,52 +53,71 @@ module.exports = function(filename, data, options, cb){
});
}
function setFileSize(fileSizeSetted){
SMB2Request('set_info', {FileId:file.FileId, FileInfoClass:'FileEndOfFileInformation', Buffer:fileLength.toBuffer()}, connection, function(err){
if(err) cb && cb(err);
else fileSizeSetted();
});
function setFileSize(fileSizeSetted) {
SMB2Request(
'set_info',
{
FileId: file.FileId,
FileInfoClass: 'FileEndOfFileInformation',
Buffer: fileLength.toBuffer(),
},
connection,
function(err) {
if (err) cb && cb(err);
else fileSizeSetted();
}
);
}
function writeFile(fileWritten){
var offset = new bigint(8)
, stop = false
, nbRemainingPackets = 0
, maxPacketSize = new bigint(8, 0x00010000 - 0x71)
;
function writeFile(fileWritten) {
var offset = new bigint(8),
stop = false,
nbRemainingPackets = 0,
maxPacketSize = new bigint(8, 0x00010000 - 0x71);
// callback manager
function callback(offset){
return function(err){
if(stop) return;
if(err) {
function callback(offset) {
return function(err) {
if (stop) return;
if (err) {
cb && cb(err);
stop = true;
} else {
nbRemainingPackets--;
checkDone();
}
}
};
}
// callback manager
function checkDone(){
if(stop) return;
function checkDone() {
if (stop) return;
createPackets();
if(nbRemainingPackets==0 && offset.ge(fileLength)) {
if (nbRemainingPackets == 0 && offset.ge(fileLength)) {
fileWritten();
}
}
// create packets
function createPackets(){
while(nbRemainingPackets<connection.packetConcurrency && offset.lt(fileLength)){
function createPackets() {
while (
nbRemainingPackets < connection.packetConcurrency &&
offset.lt(fileLength)
) {
// process packet size
var rest = fileLength.sub(offset);
var packetSize = rest.gt(maxPacketSize) ? maxPacketSize : rest;
// generate buffer
SMB2Request('write', {
'FileId':file.FileId
, 'Offset':offset.toBuffer()
, 'Buffer':fileContent.slice(offset.toNumber(), offset.add(packetSize).toNumber())
}, connection, callback(offset));
SMB2Request(
'write',
{
FileId: file.FileId,
Offset: offset.toBuffer(),
Buffer: fileContent.slice(
offset.toNumber(),
offset.add(packetSize).toNumber()
),
},
connection,
callback(offset)
);
offset = offset.add(packetSize);
nbRemainingPackets++;
}
......@@ -109,13 +125,11 @@ module.exports = function(filename, data, options, cb){
checkDone();
}
createFile(function(){
setFileSize(function(){
writeFile(function(){
createFile(function() {
setFileSize(function() {
writeFile(function() {
closeFile(cb);
});
});
});
}
};
var SMB2Message = require('../tools/smb2-message')
, message = require('../tools/message')
;
var SMB2Message = require('../tools/smb2-message'),
message = require('../tools/message');
module.exports = message({
generate:function(connection, params){
generate: function(connection, params) {
return new SMB2Message({
headers:{
'Command':'CLOSE'
, 'SessionId':connection.SessionId
, 'TreeId':connection.TreeId
, 'ProcessId':connection.ProcessId
}
, request:{
'FileId':params.FileId
}
headers: {
Command: 'CLOSE',
SessionId: connection.SessionId,
TreeId: connection.TreeId,
ProcessId: connection.ProcessId,
},
request: {
FileId: params.FileId,
},
});
}
},
});
var SMB2Message = require('../tools/smb2-message')
var message = require('../tools/message')
var FILE_OVERWRITE_IF = require('../structures/constants').FILE_OVERWRITE_IF
var SMB2Message = require('../tools/smb2-message');
var message = require('../tools/message');
var FILE_OVERWRITE_IF = require('../structures/constants').FILE_OVERWRITE_IF;
module.exports = message({
generate:function(connection, params){
generate: function(connection, params) {
var buffer = new Buffer(params.path, 'ucs2');
var createDisposition = params.createDisposition
var createDisposition = params.createDisposition;
/* See: https://msdn.microsoft.com/en-us/library/cc246502.aspx
6 values for CreateDisposition. */
if (!(createDisposition >= 0 && createDisposition <= 5)) {
createDisposition = FILE_OVERWRITE_IF
createDisposition = FILE_OVERWRITE_IF;
}
return new SMB2Message({
headers:{
'Command':'CREATE'
, 'SessionId':connection.SessionId
, 'TreeId':connection.TreeId
, 'ProcessId':connection.ProcessId
}
, request:{
'Buffer':buffer
, 'DesiredAccess':0x001701DF
, 'FileAttributes':0x00000080
, 'ShareAccess':0x00000000
, 'CreateDisposition': createDisposition
, 'CreateOptions':0x00000044
, 'NameOffset':0x0078
, 'CreateContextsOffset':0x007A+buffer.length
}
headers: {
Command: 'CREATE',
SessionId: connection.SessionId,
TreeId: connection.TreeId,
ProcessId: connection.ProcessId,
},
request: {
Buffer: buffer,
DesiredAccess: 0x001701df,
FileAttributes: 0x00000080,
ShareAccess: 0x00000000,
CreateDisposition: createDisposition,
CreateOptions: 0x00000044,
NameOffset: 0x0078,
CreateContextsOffset: 0x007a + buffer.length,
},
});
}
},
});
var SMB2Message = require('../tools/smb2-message')
, message = require('../tools/message')
;
var SMB2Message = require('../tools/smb2-message'),
message = require('../tools/message');
module.exports = message({
generate:function(connection, params){
generate: function(connection, params) {
var buffer = new Buffer(params.path, 'ucs2');
return new SMB2Message({
headers:{
'Command':'CREATE'
, 'SessionId':connection.SessionId
, 'TreeId':connection.TreeId
, 'ProcessId':connection.ProcessId
}
, request:{
'Buffer':buffer
, 'DesiredAccess':0x001701DF
, 'FileAttributes':0x00000000
, 'ShareAccess':0x00000000
, 'CreateDisposition':0x00000002
, 'CreateOptions':0x00000021
, 'NameOffset':0x0078
, 'CreateContextsOffset':0x007A+buffer.length
}
headers: {
Command: 'CREATE',
SessionId: connection.SessionId,
TreeId: connection.TreeId,
ProcessId: connection.ProcessId,
},
request: {
Buffer: buffer,
DesiredAccess: 0x001701df,
FileAttributes: 0x00000000,
ShareAccess: 0x00000000,
CreateDisposition: 0x00000002,
CreateOptions: 0x00000021,
NameOffset: 0x0078,
CreateContextsOffset: 0x007a + buffer.length,
},
});
}
},
});
var SMB2Message = require('../tools/smb2-message')
, message = require('../tools/message')
;
var SMB2Message = require('../tools/smb2-message'),
message = require('../tools/message');
module.exports = message({
generate:function(connection){
generate: function(connection) {
return new SMB2Message({
headers:{
'Command':'NEGOTIATE'
, 'ProcessId':connection.ProcessId
}
headers: {
Command: 'NEGOTIATE',
ProcessId: connection.ProcessId,
},
});
}
},
});
var SMB2Message = require('../tools/smb2-message')
, message = require('../tools/message')
;
var SMB2Message = require('../tools/smb2-message'),
message = require('../tools/message');
module.exports = message({
generate:function(connection, params){
generate: function(connection, params) {
var buffer = new Buffer(params.path, 'ucs2');
return new SMB2Message({
headers:{
'Command':'CREATE'
, 'SessionId':connection.SessionId
, 'TreeId':connection.TreeId
, 'ProcessId':connection.ProcessId
}
, request:{
'Buffer':buffer
, 'NameOffset':0x0078
, 'CreateContextsOffset':0x007A+buffer.length
}
headers: {
Command: 'CREATE',
SessionId: connection.SessionId,
TreeId: connection.TreeId,
ProcessId: connection.ProcessId,
},
request: {
Buffer: buffer,
NameOffset: 0x0078,
CreateContextsOffset: 0x007a + buffer.length,
},
});
}
},
});
var SMB2Message = require('../tools/smb2-message')
, message = require('../tools/message')
;
var SMB2Message = require('../tools/smb2-message'),
message = require('../tools/message');
module.exports = message({
generate:function(connection, params){
generate: function(connection, params) {
var buffer = new Buffer(params.path, 'ucs2');
return new SMB2Message({
headers:{
'Command':'CREATE'
, 'SessionId':connection.SessionId
, 'TreeId':connection.TreeId
, 'ProcessId':connection.ProcessId
}
, request:{
'Buffer':buffer
, 'DesiredAccess':0x001701DF
, 'FileAttributes':0x00000000
, 'ShareAccess':0x00000007
, 'CreateDisposition':0x00000001
, 'CreateOptions':0x00200021
, 'NameOffset':0x0078
, 'CreateContextsOffset':0x007A+buffer.length
}
headers: {
Command: 'CREATE',
SessionId: connection.SessionId,
TreeId: connection.TreeId,
ProcessId: connection.ProcessId,
},
request: {
Buffer: buffer,
DesiredAccess: 0x001701df,
FileAttributes: 0x00000000,
ShareAccess: 0x00000007,
CreateDisposition: 0x00000001,
CreateOptions: 0x00200021,
NameOffset: 0x0078,
CreateContextsOffset: 0x007a + buffer.length,
},
});
}
},
});
var SMB2Message = require('../tools/smb2-message')
, message = require('../tools/message')
;
var SMB2Message = require('../tools/smb2-message'),
message = require('../tools/message');
module.exports = message({
generate:function(connection, params){
generate: function(connection, params) {
return new SMB2Message({
headers:{
'Command':'QUERY_DIRECTORY'
, 'SessionId':connection.SessionId
, 'TreeId':connection.TreeId
, 'ProcessId':connection.ProcessId
}
, request:{
'FileId':params.FileId
, 'Buffer':new Buffer('*', 'ucs2')
}
headers: {
Command: 'QUERY_DIRECTORY',
SessionId: connection.SessionId,
TreeId: connection.TreeId,
ProcessId: connection.ProcessId,
},
request: {
FileId: params.FileId,
Buffer: new Buffer('*', 'ucs2'),
},
});
},
}
, parseResponse:function(response){
parseResponse: function(response) {
return parseFiles(response.getResponse().Buffer);
}
},
});
/*
* HELPERS
*/
function parseFiles(buffer){
var files = []
, offset = 0
, nextFileOffset = -1
;
while(nextFileOffset!=0){
function parseFiles(buffer) {
var files = [],
offset = 0,
nextFileOffset = -1;
while (nextFileOffset != 0) {
// extract next file offset
nextFileOffset = buffer.readUInt32LE(offset);
// extract the file
files.push(
parseFile(
buffer.slice(offset+4, nextFileOffset ? offset+nextFileOffset : buffer.length)
buffer.slice(
offset + 4,
nextFileOffset ? offset + nextFileOffset : buffer.length
)
)
);
// move to nex file
......@@ -58,65 +47,66 @@ function parseFiles(buffer){
return files;
}
function parseFile(buffer){
var file = {}
, offset = 0
;
function parseFile(buffer) {
var file = {},
offset = 0;
// index
file.Index = buffer.readUInt32LE(offset);
offset+=4;
offset += 4;
// CreationTime
file.CreationTime = buffer.slice(offset, offset+8);
offset+=8;
file.CreationTime = buffer.slice(offset, offset + 8);
offset += 8;
// LastAccessTime
file.LastAccessTime = buffer.slice(offset, offset+8);
offset+=8;
file.LastAccessTime = buffer.slice(offset, offset + 8);
offset += 8;
// LastWriteTime
file.LastWriteTime = buffer.slice(offset, offset+8);
offset+=8;
file.LastWriteTime = buffer.slice(offset, offset + 8);
offset += 8;
// ChangeTime
file.ChangeTime = buffer.slice(offset, offset+8);
offset+=8;
file.ChangeTime = buffer.slice(offset, offset + 8);
offset += 8;
// EndofFile
file.EndofFile = buffer.slice(offset, offset+8);
offset+=8;
file.EndofFile = buffer.slice(offset, offset + 8);
offset += 8;
// AllocationSize
file.AllocationSize = buffer.slice(offset, offset+8);
offset+=8;
file.AllocationSize = buffer.slice(offset, offset + 8);
offset += 8;
// FileAttributes
file.FileAttributes = buffer.readUInt32LE(offset);
offset+=4;
offset += 4;
// FilenameLength
file.FilenameLength = buffer.readUInt32LE(offset);
offset+=4;
offset += 4;
// EASize
file.EASize = buffer.readUInt32LE(offset);
offset+=4;
offset += 4;
// ShortNameLength
file.ShortNameLength = buffer.readUInt8(offset);
offset+=1;
offset += 1;
// FileId
file.FileId = buffer.slice(offset, offset+8);
offset+=8;
file.FileId = buffer.slice(offset, offset + 8);
offset += 8;
// Reserved
offset+=27;
offset += 27;
// Filename
file.Filename = buffer.slice(offset, offset+file.FilenameLength).toString('ucs2');
offset+=file.FilenameLength;
file.Filename = buffer
.slice(offset, offset + file.FilenameLength)
.toString('ucs2');
offset += file.FilenameLength;
return file;
}
\ No newline at end of file
}
var SMB2Message = require('../tools/smb2-message')
, message = require('../tools/message')
;
var SMB2Message = require('../tools/smb2-message'),
message = require('../tools/message');
module.exports = message({
generate:function(connection, file){
generate: function(connection, file) {
return new SMB2Message({
headers:{
'Command':'READ'
, 'SessionId':connection.SessionId
, 'TreeId':connection.TreeId
, 'ProcessId':connection.ProcessId
}
, request:{
'FileId':file.FileId
, 'Length':file.Length
, 'Offset':file.Offset
}
headers: {
Command: 'READ',
SessionId: connection.SessionId,
TreeId: connection.TreeId,
ProcessId: connection.ProcessId,
},
request: {
FileId: file.FileId,
Length: file.Length,
Offset: file.Offset,
},
});
},
}
, parseResponse:function(response){
parseResponse: function(response) {
return response.getResponse().Buffer;
}
},
});
var SMB2Message = require('../tools/smb2-message')
, message = require('../tools/message')
, ntlm = require('ntlm')
;
var SMB2Message = require('../tools/smb2-message'),
message = require('../tools/message'),
ntlm = require('ntlm');
module.exports = message({
generate:function(connection){
generate: function(connection) {
return new SMB2Message({
headers:{
'Command':'SESSION_SETUP'
, 'ProcessId':connection.ProcessId
}
, request:{
'Buffer':ntlm.encodeType1(
connection.ip
, connection.domain
)
}
headers: {
Command: 'SESSION_SETUP',
ProcessId: connection.ProcessId,
},
request: {
Buffer: ntlm.encodeType1(connection.ip, connection.domain),
},
});
},
}
, successCode: 'STATUS_MORE_PROCESSING_REQUIRED'
successCode: 'STATUS_MORE_PROCESSING_REQUIRED',
, onSuccess:function(connection, response){
onSuccess: function(connection, response) {
var h = response.getHeaders();
connection.SessionId = h.SessionId;
connection.nonce = ntlm.decodeType2(response.getResponse().Buffer);
}
},
});
var SMB2Message = require('../tools/smb2-message')
, message = require('../tools/message')
, ntlm = require('ntlm')
;
var SMB2Message = require('../tools/smb2-message'),
message = require('../tools/message'),
ntlm = require('ntlm');
module.exports = message({
generate:function(connection){
generate: function(connection) {
return new SMB2Message({
headers:{
'Command':'SESSION_SETUP'
, 'SessionId':connection.SessionId
, 'ProcessId':connection.ProcessId
}
, request:{
'Buffer':ntlm.encodeType3(
connection.username
, connection.ip
, connection.domain
, connection.nonce
, connection.password
)
}
headers: {
Command: 'SESSION_SETUP',
SessionId: connection.SessionId,
ProcessId: connection.ProcessId,
},
request: {
Buffer: ntlm.encodeType3(
connection.username,
connection.ip,
connection.domain,
connection.nonce,
connection.password
),
},
});
}
},
});
var SMB2Message = require('../tools/smb2-message')
, message = require('../tools/message')
;
var SMB2Message = require('../tools/smb2-message'),
message = require('../tools/message');
var fileInfoClasses = {
'FileAllocationInformation': 19
, 'FileBasicInformation': 4
, 'FileDispositionInformation': 13
, 'FileEndOfFileInformation': 20
, 'FileFullEaInformation': 15
, 'FileLinkInformation': 11
, 'FileModeInformation': 16
, 'FilePipeInformation': 23
, 'FilePositionInformation': 14
, 'FileRenameInformation': 10
, 'FileShortNameInformation': 40
, 'FileValidDataLengthInformation': 39
FileAllocationInformation: 19,
FileBasicInformation: 4,
FileDispositionInformation: 13,
FileEndOfFileInformation: 20,
FileFullEaInformation: 15,
FileLinkInformation: 11,
FileModeInformation: 16,
FilePipeInformation: 23,
FilePositionInformation: 14,
FileRenameInformation: 10,
FileShortNameInformation: 40,
FileValidDataLengthInformation: 39,
};
module.exports = message({
generate:function(connection, params){
generate: function(connection, params) {
return new SMB2Message({
headers:{
'Command':'SET_INFO'
, 'SessionId':connection.SessionId
, 'TreeId':connection.TreeId
, 'ProcessId':connection.ProcessId
}
, request:{
'FileInfoClass':fileInfoClasses[params.FileInfoClass]
, 'FileId':params.FileId
, 'Buffer':params.Buffer
}
headers: {
Command: 'SET_INFO',
SessionId: connection.SessionId,
TreeId: connection.TreeId,
ProcessId: connection.ProcessId,
},
request: {
FileInfoClass: fileInfoClasses[params.FileInfoClass],
FileId: params.FileId,
Buffer: params.Buffer,
},
});
}
},
});
var SMB2Message = require('../tools/smb2-message')
, message = require('../tools/message')
;
var SMB2Message = require('../tools/smb2-message'),
message = require('../tools/message');
module.exports = message({
generate:function(connection){
generate: function(connection) {
return new SMB2Message({
headers:{
'Command':'TREE_CONNECT'
, 'SessionId':connection.SessionId
, 'ProcessId':connection.ProcessId
}
, request:{
'Buffer':new Buffer(connection.fullPath, 'ucs2')
}
headers: {
Command: 'TREE_CONNECT',
SessionId: connection.SessionId,
ProcessId: connection.ProcessId,
},
request: {
Buffer: new Buffer(connection.fullPath, 'ucs2'),
},
});
},
}
, onSuccess:function(connection, response){
onSuccess: function(connection, response) {
var h = response.getHeaders();
connection.TreeId = h.TreeId;
}
},
});
var SMB2Message = require('../tools/smb2-message')
, message = require('../tools/message')
;
var SMB2Message = require('../tools/smb2-message'),
message = require('../tools/message');
module.exports = message({
generate:function(connection, params){
generate: function(connection, params) {
return new SMB2Message({
headers:{
'Command':'WRITE'
, 'SessionId':connection.SessionId
, 'TreeId':connection.TreeId
, 'ProcessId':connection.ProcessId
}
, request:{
'FileId':params.FileId
, 'Offset':params.Offset
, 'Buffer':params.Buffer
}
headers: {
Command: 'WRITE',
SessionId: connection.SessionId,
TreeId: connection.TreeId,
ProcessId: connection.ProcessId,
},
request: {
FileId: params.FileId,
Offset: params.Offset,
Buffer: params.Buffer,
},
});
},
}
, parseResponse:function(response){
parseResponse: function(response) {
return response.getResponse().Buffer;
}
},
});
/*
* CONSTANTS
*/
var shareRegExp = /\\\\([^\\]*)\\([^\\]*)\\?/
, port = 445
, packetConcurrency = 20
, autoCloseTimeout = 10000
;
var shareRegExp = /\\\\([^\\]*)\\([^\\]*)\\?/,
port = 445,
packetConcurrency = 20,
autoCloseTimeout = 10000;
/*
* DEPENDENCIES
*/
var SMB2Connection = require('./tools/smb2-connection');
/*
* CONSTRUCTOR
*/
var SMB = module.exports = function(opt){
var SMB = (module.exports = function(opt) {
opt = opt || {};
// Parse share-string
var matches;
if(!opt.share || !(matches = opt.share.match(shareRegExp))){
if (!opt.share || !(matches = opt.share.match(shareRegExp))) {
throw new Error('the share is not valid');
}
......@@ -50,26 +44,26 @@ var SMB = module.exports = function(opt){
// close timeout default 10s
if (opt.autoCloseTimeout !== undefined) {
this.autoCloseTimeout = opt.autoCloseTimeout
this.autoCloseTimeout = opt.autoCloseTimeout;
} else {
this.autoCloseTimeout = autoCloseTimeout
this.autoCloseTimeout = autoCloseTimeout;
}
// store authentification
this.domain = opt.domain;
this.domain = opt.domain;
this.username = opt.username;
this.password = opt.password;
// set session id
this.SessionId = Math.floor(Math.random()*256) & 0xFF;
this.SessionId = Math.floor(Math.random() * 256) & 0xff;
// set the process id
// https://msdn.microsoft.com/en-us/library/ff470100.aspx
this.ProcessId = new Buffer([
Math.floor(Math.random()*256) & 0xFF,
Math.floor(Math.random()*256) & 0xFF,
Math.floor(Math.random()*256) & 0xFF,
Math.floor(Math.random()*256) & 0xFE
Math.floor(Math.random() * 256) & 0xff,
Math.floor(Math.random() * 256) & 0xff,
Math.floor(Math.random() * 256) & 0xff,
Math.floor(Math.random() * 256) & 0xfe,
]);
// activate debug mode
......@@ -77,29 +71,32 @@ var SMB = module.exports = function(opt){
// init connection (socket)
SMB2Connection.init(this);
};
});
/*
* PROTOTYPE
*/
var proto = SMB.prototype = {};
var proto = (SMB.prototype = {});
proto.close = require('./api/close');
proto.exists = SMB2Connection.requireConnect(require('./api/exists'));
proto.exists = SMB2Connection.requireConnect(require('./api/exists'));
proto.rename = SMB2Connection.requireConnect(require('./api/rename'));
proto.rename = SMB2Connection.requireConnect(require('./api/rename'));
proto.readFile = SMB2Connection.requireConnect(require('./api/readfile'));
proto.createReadStream = SMB2Connection.requireConnect(require('./api/createReadStream'));
proto.createWriteStream = SMB2Connection.requireConnect(require('./api/createWriteStream'));
proto.readFile = SMB2Connection.requireConnect(require('./api/readfile'));
proto.createReadStream = SMB2Connection.requireConnect(
require('./api/createReadStream')
);
proto.createWriteStream = SMB2Connection.requireConnect(
require('./api/createWriteStream')
);
proto.writeFile = SMB2Connection.requireConnect(require('./api/writefile'));
proto.unlink = SMB2Connection.requireConnect(require('./api/unlink'));
proto.unlink = SMB2Connection.requireConnect(require('./api/unlink'));
proto.readdir = SMB2Connection.requireConnect(require('./api/readdir'));
proto.rmdir = SMB2Connection.requireConnect(require('./api/rmdir'));
proto.mkdir = SMB2Connection.requireConnect(require('./api/mkdir'));
proto.readdir = SMB2Connection.requireConnect(require('./api/readdir'));
proto.rmdir = SMB2Connection.requireConnect(require('./api/rmdir'));
proto.mkdir = SMB2Connection.requireConnect(require('./api/mkdir'));
proto.ensureDir = SMB2Connection.requireConnect(require('./api/ensureDir'));
proto.getSize = SMB2Connection.requireConnect(require('./api/getSize'));
proto.getSize = SMB2Connection.requireConnect(require('./api/getSize'));
module.exports = {
request: [
['StructureSize', 2, 24],
['Flags', 2, 0],
['Reserved', 4, 0],
['FileId', 16],
],
request:[
['StructureSize', 2, 24]
, ['Flags', 2, 0]
, ['Reserved', 4, 0]
, ['FileId', 16]
]
, response:[
['StructureSize', 2]
, ['Flags', 2]
, ['Reserved', 4]
, ['CreationTime', 8]
, ['LastAccessTime', 8]
, ['LastWriteTime', 8]
, ['ChangeTime', 8]
, ['AllocationSize', 8]
, ['EndofFile', 8]
, ['FileAttributes', 4]
]
}
response: [
['StructureSize', 2],
['Flags', 2],
['Reserved', 4],
['CreationTime', 8],
['LastAccessTime', 8],
['LastWriteTime', 8],
['ChangeTime', 8],
['AllocationSize', 8],
['EndofFile', 8],
['FileAttributes', 4],
],
};
......@@ -8,5 +8,5 @@ module.exports = {
FILE_CREATE: 0x00000002,
FILE_OPEN_IF: 0x00000003,
FILE_OVERWRITE: 0x00000004,
FILE_OVERWRITE_IF: 0x00000005
}
FILE_OVERWRITE_IF: 0x00000005,
};
module.exports = {
request:[
['StructureSize', 2, 57]
, ['SecurityFlags', 1, 0]
, ['RequestedOplockLevel', 1, 0]
, ['ImpersonationLevel', 4, 0x00000002]
, ['SmbCreateFlags', 8, 0]
, ['Reserved', 8, 0]
, ['DesiredAccess', 4, 0x00100081]
, ['FileAttributes', 4, 0x00000000]
, ['ShareAccess', 4, 0x00000007]
, ['CreateDisposition', 4, 0x00000001]
, ['CreateOptions', 4, 0x00000020]
, ['NameOffset', 2]
, ['NameLength', 2]
, ['CreateContextsOffset', 4]
, ['CreateContextsLength', 4]
, ['Buffer', 'NameLength']
, ['Reserved2', 2, 0x4200]
, ['CreateContexts', 'CreateContextsLength', '']
]
, response:[
['StructureSize', 2]
, ['OplockLevel', 1]
, ['Flags', 1]
, ['CreateAction', 4]
, ['CreationTime', 8]
, ['LastAccessTime', 8]
, ['LastWriteTime', 8]
, ['ChangeTime', 8]
, ['AllocationSize', 8]
, ['EndofFile', 8]
, ['FileAttributes', 4]
, ['Reserved2', 4]
, ['FileId', 16]
, ['CreateContextsOffset', 4]
, ['CreateContextsLength', 4]
, ['Buffer', 'CreateContextsLength']
]
}
request: [
['StructureSize', 2, 57],
['SecurityFlags', 1, 0],
['RequestedOplockLevel', 1, 0],
['ImpersonationLevel', 4, 0x00000002],
['SmbCreateFlags', 8, 0],
['Reserved', 8, 0],
['DesiredAccess', 4, 0x00100081],
['FileAttributes', 4, 0x00000000],
['ShareAccess', 4, 0x00000007],
['CreateDisposition', 4, 0x00000001],
['CreateOptions', 4, 0x00000020],
['NameOffset', 2],
['NameLength', 2],
['CreateContextsOffset', 4],
['CreateContextsLength', 4],
['Buffer', 'NameLength'],
['Reserved2', 2, 0x4200],
['CreateContexts', 'CreateContextsLength', ''],
],
response: [
['StructureSize', 2],
['OplockLevel', 1],
['Flags', 1],
['CreateAction', 4],
['CreationTime', 8],
['LastAccessTime', 8],
['LastWriteTime', 8],
['ChangeTime', 8],
['AllocationSize', 8],
['EndofFile', 8],
['FileAttributes', 4],
['Reserved2', 4],
['FileId', 16],
['CreateContextsOffset', 4],
['CreateContextsLength', 4],
['Buffer', 'CreateContextsLength'],
],
};
module.exports = {
request: [
['StructureSize', 2, 36],
['DialectCount', 2, 2],
['SecurityMode', 2, 1],
['Reserved', 2, 0],
['Capabilities', 4, 0],
['ClientGuid', 16, 0],
['ClientStartTime', 8, 0],
['Dialects', 4, new Buffer([0x02, 0x02, 0x10, 0x02])],
],
request:[
['StructureSize', 2, 36]
, ['DialectCount', 2, 2]
, ['SecurityMode', 2, 1]
, ['Reserved', 2, 0]
, ['Capabilities', 4, 0]
, ['ClientGuid', 16, 0]
, ['ClientStartTime', 8, 0]
, ['Dialects', 4, new Buffer([0x02,0x02,0x10,0x02])]
]
, response:[
['StructureSize', 2]
, ['SecurityMode', 2]
, ['DialectRevision', 2]
, ['Reserved', 2]
, ['ServerGuid', 16]
, ['Capabilities', 4]
, ['MaxTransactSize', 4]
, ['MaxReadSize', 4]
, ['MaxWriteSize', 4]
, ['SystemTime', 8]
, ['ServerStartTime', 8]
, ['SecurityBufferOffset', 2]
, ['SecurityBufferLength', 2]
, ['Reserved2', 4]
, ['Buffer', 'SecurityBufferLength']
]
}
response: [
['StructureSize', 2],
['SecurityMode', 2],
['DialectRevision', 2],
['Reserved', 2],
['ServerGuid', 16],
['Capabilities', 4],
['MaxTransactSize', 4],
['MaxReadSize', 4],
['MaxWriteSize', 4],
['SystemTime', 8],
['ServerStartTime', 8],
['SecurityBufferOffset', 2],
['SecurityBufferLength', 2],
['Reserved2', 4],
['Buffer', 'SecurityBufferLength'],
],
};
module.exports = {
request: [
['StructureSize', 2, 33],
['FileInformationClass', 1, 0x25], // FileBothDirectoryInformation plus volume file ID about a file or directory.
['Flags', 1, 0],
['FileIndex', 4, 0],
['FileId', 16],
['FileNameOffset', 2, 96],
['FileNameLength', 2],
['OutputBufferLength', 4, 0x00010000],
['Buffer', 'FileNameLength'],
],
request:[
['StructureSize', 2, 33]
, ['FileInformationClass', 1, 0x25] // FileBothDirectoryInformation plus volume file ID about a file or directory.
, ['Flags', 1, 0]
, ['FileIndex', 4, 0]
, ['FileId', 16]
, ['FileNameOffset', 2, 96]
, ['FileNameLength', 2]
, ['OutputBufferLength', 4, 0x00010000]
, ['Buffer', 'FileNameLength']
]
, response:[
['StructureSize', 2]
, ['OutputBufferOffset', 2]
, ['OutputBufferLength', 4]
, ['Buffer', 'OutputBufferLength']
]
}
response: [
['StructureSize', 2],
['OutputBufferOffset', 2],
['OutputBufferLength', 4],
['Buffer', 'OutputBufferLength'],
],
};
module.exports = {
request: [
['StructureSize', 2, 49],
['Padding', 1, 0x50],
['Flags', 1, 0],
['Length', 4],
['Offset', 8],
['FileId', 16],
['MinimumCount', 4, 0],
['Channel', 4, 0],
['RemainingBytes', 4, 0],
['ReadChannelInfoOffset', 2, 0],
['ReadChannelInfoLength', 2, 0],
['Buffer', 1, 0],
],
request:[
['StructureSize', 2, 49]
, ['Padding', 1, 0x50]
, ['Flags', 1, 0]
, ['Length', 4]
, ['Offset', 8]
, ['FileId', 16]
, ['MinimumCount', 4, 0]
, ['Channel', 4, 0]
, ['RemainingBytes', 4, 0]
, ['ReadChannelInfoOffset', 2, 0]
, ['ReadChannelInfoLength', 2, 0]
, ['Buffer', 1, 0]
]
, response:[
['StructureSize', 2]
, ['DataOffset', 1]
, ['Reserved', 1]
, ['DataLength', 4]
, ['DataRemaining', 4]
, ['Reserved2', 4]
, ['Buffer', 'DataLength']
]
}
response: [
['StructureSize', 2],
['DataOffset', 1],
['Reserved', 1],
['DataLength', 4],
['DataRemaining', 4],
['Reserved2', 4],
['Buffer', 'DataLength'],
],
};
module.exports = {
request: [
['StructureSize', 2, 25],
['Flags', 1, 0],
['SecurityMode', 1, 1],
['Capabilities', 4, 1],
['Channel', 4, 0],
['SecurityBufferOffset', 2, 88],
['SecurityBufferLength', 2],
['PreviousSessionId', 8, 0],
['Buffer', 'SecurityBufferLength'],
],
request:[
['StructureSize', 2, 25]
, ['Flags', 1, 0]
, ['SecurityMode', 1, 1]
, ['Capabilities', 4, 1]
, ['Channel', 4, 0]
, ['SecurityBufferOffset', 2, 88]
, ['SecurityBufferLength', 2]
, ['PreviousSessionId', 8, 0]
, ['Buffer','SecurityBufferLength']
]
, response:[
['StructureSize', 2]
, ['SessionFlags', 2]
, ['SecurityBufferOffset', 2]
, ['SecurityBufferLength', 2]
, ['Buffer', 'SecurityBufferLength']
]
}
response: [
['StructureSize', 2],
['SessionFlags', 2],
['SecurityBufferOffset', 2],
['SecurityBufferLength', 2],
['Buffer', 'SecurityBufferLength'],
],
};
module.exports = {
request:[
['StructureSize', 2, 33]
, ['InfoType', 1, 1]
, ['FileInfoClass', 1]
, ['BufferLength', 4]
, ['BufferOffset', 2, 0x0060]
, ['Reserved', 2, 0]
, ['AdditionalInformation', 4, 0]
, ['FileId', 16]
, ['Buffer','BufferLength']
]
, response:[
['StructureSize', 2]
]
}
request: [
['StructureSize', 2, 33],
['InfoType', 1, 1],
['FileInfoClass', 1],
['BufferLength', 4],
['BufferOffset', 2, 0x0060],
['Reserved', 2, 0],
['AdditionalInformation', 4, 0],
['FileId', 16],
['Buffer', 'BufferLength'],
],
response: [['StructureSize', 2]],
};
module.exports = {
request: [
['StructureSize', 2, 9],
['Reserved', 2, 0],
['PathOffset', 2, 72],
['PathLength', 2],
['Buffer', 'PathLength'],
],
request:[
['StructureSize', 2, 9]
, ['Reserved', 2, 0]
, ['PathOffset', 2, 72]
, ['PathLength', 2]
, ['Buffer', 'PathLength']
]
, response:[
['StructureSize', 2]
, ['ShareType', 1]
, ['Reserved', 1]
, ['ShareFlags', 4]
, ['Capabilities', 4]
, ['MaximalAccess', 4]
]
}
response: [
['StructureSize', 2],
['ShareType', 1],
['Reserved', 1],
['ShareFlags', 4],
['Capabilities', 4],
['MaximalAccess', 4],
],
};
module.exports = {
request: [
['StructureSize', 2, 49],
['DataOffset', 2, 0x70],
['Length', 4, 0],
['Offset', 8],
['FileId', 16],
['Channel', 4, 0],
['RemainingBytes', 4, 0],
['WriteChannelInfoOffset', 2, 0],
['WriteChannelInfoLength', 2, 0],
['Flags', 4, 0],
['Buffer', 'Length'],
],
request:[
['StructureSize', 2, 49]
, ['DataOffset', 2, 0x70]
, ['Length', 4, 0]
, ['Offset', 8]
, ['FileId', 16]
, ['Channel', 4, 0]
, ['RemainingBytes', 4, 0]
, ['WriteChannelInfoOffset', 2, 0]
, ['WriteChannelInfoLength', 2, 0]
, ['Flags', 4, 0]
, ['Buffer', 'Length']
]
, response:[
['StructureSize', 2]
, ['Reserved', 2]
, ['Count', 4]
, ['Remaining', 4]
, ['WriteChannelInfoOffset', 2]
, ['WriteChannelInfoLength', 2]
]
}
response: [
['StructureSize', 2],
['Reserved', 2],
['Count', 4],
['Remaining', 4],
['WriteChannelInfoOffset', 2],
['WriteChannelInfoLength', 2],
],
};
var BigInt = module.exports = function(n, v){
if(BigInt.isBigInt(n)){
var BigInt = (module.exports = function(n, v) {
if (BigInt.isBigInt(n)) {
this.buffer = new Buffer(n.buffer.length);
n.buffer.copy(this.buffer, 0);
this.sign = n.sign;
} else {
this.buffer = new Buffer(n);
this.buffer.fill(0);
this.sign = 1;
v = v || 0;
if(v != 0){
if(v<0) {
if (v != 0) {
if (v < 0) {
this.sign = -1;
v = -v;
}
v = v.toString(16);
var size = Math.ceil(v.length/2)
, carry = size*2 - v.length
;
var size = Math.ceil(v.length / 2),
carry = size * 2 - v.length;
for(var i=0; i<size; i++) {
for (var i = 0; i < size; i++) {
var start = (size - i - 1) * 2 - carry;
this.buffer.writeUInt8(
parseInt( start == -1 ? v.substr(0,1) : v.substr(start, 2), 16)
, i
parseInt(start == -1 ? v.substr(0, 1) : v.substr(start, 2), 16),
i
);
}
}
}
}
});
/*
* STATICS
*/
BigInt.isBigInt = function(v){
BigInt.isBigInt = function(v) {
return v && v.buffer && Buffer.isBuffer(v.buffer);
}
};
BigInt.toBigInt = function(n, v){
BigInt.toBigInt = function(n, v) {
return new BigInt(n, v);
}
};
BigInt.fromBuffer = function(b, sign){
BigInt.fromBuffer = function(b, sign) {
sign = typeof sign == 'undefined' ? 1 : sign;
var bi = new BigInt(0);
bi.sign = sign;
bi.buffer = b;
return bi;
}
};
/*
* ADD / SUB
*/
BigInt.prototype.add = function(v){
if(!BigInt.isBigInt(v)) {
BigInt.prototype.add = function(v) {
if (!BigInt.isBigInt(v)) {
v = BigInt.toBigInt(this.buffer.length, v);
}
if(this.sign != v.sign){
if (this.sign != v.sign) {
return this.neg().sub(v);
}
var carry = 0
, n = Math.max(v.buffer.length, this.buffer.length)
, result = new BigInt(n);
;
for(var i=0;i<n;i++){
var r = ( i<this.buffer.length ? this.buffer.readUInt8(i) : 0 )
+ ( i<v.buffer.length ? v.buffer.readUInt8(i) : 0 )
+ carry
;
result.buffer.writeUInt8(r & 0xFF, i);
var carry = 0,
n = Math.max(v.buffer.length, this.buffer.length),
result = new BigInt(n);
for (var i = 0; i < n; i++) {
var r =
(i < this.buffer.length ? this.buffer.readUInt8(i) : 0) +
(i < v.buffer.length ? v.buffer.readUInt8(i) : 0) +
carry;
result.buffer.writeUInt8(r & 0xff, i);
carry = r >> 8;
}
result.sign = this.sign;
return result;
}
return result;
};
BigInt.prototype.neg = function(v){
BigInt.prototype.neg = function(v) {
var result = new BigInt(this);
result.sign *= -1;
return result;
}
};
BigInt.prototype.abs = function(v){
BigInt.prototype.abs = function(v) {
var result = new BigInt(this);
result.sign = 1;
return result;
}
BigInt.prototype.sub = function(v){
};
if(!BigInt.isBigInt(v)) {
BigInt.prototype.sub = function(v) {
if (!BigInt.isBigInt(v)) {
v = BigInt.toBigInt(this.buffer.length, v);
}
if(this.sign != v.sign) {
if (this.sign != v.sign) {
return this.add(v.neg());
}
var carry = 0
, a = new BigInt(this)
, b = new BigInt(v)
, n = Math.max(a.buffer.length, b.buffer.length)
, result = new BigInt(n)
, sign = this.sign
;
var carry = 0,
a = new BigInt(this),
b = new BigInt(v),
n = Math.max(a.buffer.length, b.buffer.length),
result = new BigInt(n),
sign = this.sign;
if(a.abs().lt(b.abs())){
if (a.abs().lt(b.abs())) {
var t = a;
a = b;
b = t;
sign *= -1;
}
for(var i=0; i<n; i++){
var va = ( i<a.buffer.length ? a.buffer.readUInt8(i) : 0 )
, vb = ( i<b.buffer.length ? b.buffer.readUInt8(i) : 0 )
, c = 0
, r = va-vb-carry
;
for (var i = 0; i < n; i++) {
var va = i < a.buffer.length ? a.buffer.readUInt8(i) : 0,
vb = i < b.buffer.length ? b.buffer.readUInt8(i) : 0,
c = 0,
r = va - vb - carry;
while(r<0){
r+=0xFF;
while (r < 0) {
r += 0xff;
c--;
}
result.buffer.writeUInt8(r & 0xFF, i);
result.buffer.writeUInt8(r & 0xff, i);
carry = (r >> 8) + c;
}
result.sign = sign;
return result;
}
};
/*
* EXPORTS
*/
BigInt.prototype.toBuffer = function(){ return this.buffer }
BigInt.prototype.toNumber = function(){
BigInt.prototype.toBuffer = function() {
return this.buffer;
};
BigInt.prototype.toNumber = function() {
var b = new Buffer(this.buffer.length);
for(var i=0; i<this.buffer.length; i++){
for (var i = 0; i < this.buffer.length; i++) {
b.writeUInt8(this.buffer.readUInt8(this.buffer.length - i - 1), i);
}
return parseInt(b.toString('hex'), 16);
}
};
/*
* COMPARE
*/
BigInt.prototype.compare = function(v){
if(!BigInt.isBigInt(v)) {
BigInt.prototype.compare = function(v) {
if (!BigInt.isBigInt(v)) {
v = BigInt.toBigInt(this.buffer.length, v);
}
var n = Math.max(v.buffer.length, this.buffer.length);
if(this.sign > v.sign) return 1;
if(this.sign < v.sign) return -1;
if (this.sign > v.sign) return 1;
if (this.sign < v.sign) return -1;
for(var i=n-1;i>=0;i--){
var a = ( i<this.buffer.length ? this.buffer.readUInt8(i) : 0 )
, b = ( i<v.buffer.length ? v.buffer.readUInt8(i) : 0 )
;
if(a!=b){
for (var i = n - 1; i >= 0; i--) {
var a = i < this.buffer.length ? this.buffer.readUInt8(i) : 0,
b = i < v.buffer.length ? v.buffer.readUInt8(i) : 0;
if (a != b) {
return a > b ? this.sign : -this.sign;
}
}
return 0;
};
}
BigInt.prototype.lt = function(v){
BigInt.prototype.lt = function(v) {
return this.compare(v) < 0;
}
};
BigInt.prototype.le = function(v){
BigInt.prototype.le = function(v) {
return this.compare(v) <= 0;
}
};
BigInt.prototype.gt = function(v){
BigInt.prototype.gt = function(v) {
return this.compare(v) > 0;
}
};
BigInt.prototype.ge = function(v){
BigInt.prototype.ge = function(v) {
return this.compare(v) >= 0;
}
};
var MsErref = require('./ms_erref')
, bigint = require('./bigint')
;
var MsErref = require('./ms_erref'),
bigint = require('./bigint');
var defaults = {
successCode: 'STATUS_SUCCESS',
successCode: 'STATUS_SUCCESS'
, parse:function(connection, cb){
parse: function(connection, cb) {
var self = this;
return function(response){
var h = response.getHeaders()
, err = MsErref.getStatus(bigint.fromBuffer(h.Status).toNumber())
;
if(err.code == self.successCode){
return function(response) {
var h = response.getHeaders(),
err = MsErref.getStatus(bigint.fromBuffer(h.Status).toNumber());
if (err.code == self.successCode) {
self.onSuccess && self.onSuccess(connection, response);
cb && cb(
null
, self.parseResponse && self.parseResponse(response)
);
cb && cb(null, self.parseResponse && self.parseResponse(response));
} else {
var error = new Error(MsErref.getErrorMessage(err))
error.code = err.code
var error = new Error(MsErref.getErrorMessage(err));
error.code = err.code;
cb && cb(error);
}
};
},
}
, parseResponse:function(response){
parseResponse: function(response) {
return response.getResponse();
}
},
};
module.exports = function(obj){
for ( var key in defaults ) {
module.exports = function(obj) {
for (var key in defaults) {
obj[key] = obj[key] || defaults[key];
}
return obj;
};
This diff is collapsed.
/*
* DEPENDENCIES
*/
var net = require('net')
, SMB2Forge = require('./smb2-forge')
, SMB2Request = SMB2Forge.request
;
var net = require('net'),
SMB2Forge = require('./smb2-forge'),
SMB2Request = SMB2Forge.request;
/*
* CONNECTION MANAGER
*/
var SMB2Connection = module.exports = {};
var SMB2Connection = (module.exports = {});
/*
* CLOSE CONNECTION
*/
SMB2Connection.close = function(connection){
SMB2Connection.close = function(connection) {
clearAutoCloseTimeout(connection);
if(connection.connected){
if (connection.connected) {
connection.connected = false;
connection.socket.end();
}
}
};
/*
* OPEN CONNECTION
*/
SMB2Connection.requireConnect = function(method){
return function(){
SMB2Connection.requireConnect = function(method) {
return function() {
var connection = this;
var args = Array.prototype.slice.call(arguments);
connect(connection, function(err){
// process the cb
var cb = args.pop();
if (typeof cb !== 'function') {
args.push(cb)
cb = function (err) {
if (err) {
if (!err instanceof Error) {
err = new Error(String(err))
connect(
connection,
function(err) {
// process the cb
var cb = args.pop();
if (typeof cb !== 'function') {
args.push(cb);
cb = function(err) {
if (err) {
if (!err instanceof Error) {
err = new Error(String(err));
}
throw err;
}
throw err
}
};
}
}
cb = scheduleAutoClose(connection, cb);
args.push(cb);
// manage the connection error
if(err) cb(err);
else method.apply(connection, args);
});
}
}
cb = scheduleAutoClose(connection, cb);
args.push(cb);
// manage the connection error
if (err) cb(err);
else method.apply(connection, args);
}
);
};
};
/*
* INIT CONNECTION
*/
SMB2Connection.init = function(connection){
SMB2Connection.init = function(connection) {
// create a socket
connection.connected = false;
connection.socket = new net.Socket({
allowHalfOpen:true
allowHalfOpen: true,
});
// attach data events to socket
connection.socket.on('data', SMB2Forge.response(connection));
connection.errorHandler = [];
connection.socket.on('error', function(err){
if(connection.errorHandler.length > 0){
connection.errorHandler[0].call(null, err)
connection.socket.on('error', function(err) {
if (connection.errorHandler.length > 0) {
connection.errorHandler[0].call(null, err);
}
if(connection.debug){
if (connection.debug) {
console.log('-- error');
console.log(arguments);
}
});
}
};
/*
* PRIVATE FUNCTION TO HANDLE CONNECTION
*/
function connect(connection, cb){
if(connection.connected){
function connect(connection, cb) {
if (connection.connected) {
cb && cb(null);
return;
}
......@@ -100,67 +91,69 @@ function connect(connection, cb){
cb = scheduleAutoClose(connection, cb);
// open TCP socket
connection.socket.connect(connection.port, connection.ip);
connection.socket.connect(
connection.port,
connection.ip
);
// SMB2 negotiate connection
SMB2Request('negotiate', {}, connection, function(err){
if(err) cb && cb(err);
SMB2Request('negotiate', {}, connection, function(err) {
if (err) cb && cb(err);
// SMB2 setup session / negotiate ntlm
else SMB2Request('session_setup_step1', {}, connection, function(err){
if(err) cb && cb(err);
// SMB2 setup session / autheticate with ntlm
else SMB2Request('session_setup_step2', {}, connection, function(err){
if(err) cb && cb(err);
// SMB2 tree connect
else SMB2Request('tree_connect', {}, connection, function(err){
if(err) cb && cb(err);
else {
connection.connected = true;
cb && cb(null);
}
});
else
SMB2Request('session_setup_step1', {}, connection, function(err) {
if (err) cb && cb(err);
// SMB2 setup session / autheticate with ntlm
else
SMB2Request('session_setup_step2', {}, connection, function(err) {
if (err) cb && cb(err);
// SMB2 tree connect
else
SMB2Request('tree_connect', {}, connection, function(err) {
if (err) cb && cb(err);
else {
connection.connected = true;
cb && cb(null);
}
});
});
});
});
});
}
/*
* PRIVATE FUNCTION TO HANDLE CLOSING THE CONNECTION
*/
function clearAutoCloseTimeout(connection){
if(connection.scheduledAutoClose){
function clearAutoCloseTimeout(connection) {
if (connection.scheduledAutoClose) {
clearTimeout(connection.scheduledAutoClose);
connection.scheduledAutoClose = null;
}
}
function setAutoCloseTimeout(connection){
function setAutoCloseTimeout(connection) {
clearAutoCloseTimeout(connection);
if(connection.autoCloseTimeout != 0){
connection.scheduledAutoClose = setTimeout(function(){
if (connection.autoCloseTimeout != 0) {
connection.scheduledAutoClose = setTimeout(function() {
connection.close();
}, connection.autoCloseTimeout);
}
}
function scheduleAutoClose(connection, cb){
function scheduleAutoClose(connection, cb) {
addErrorListener(connection, cb);
clearAutoCloseTimeout(connection);
return function(){
return function() {
removeErrorListener(connection);
setAutoCloseTimeout(connection);
cb.apply(null, arguments);
}
};
}
/*
* PRIVATE FUNCTIONS TO HANDLE ERRORS
*/
function addErrorListener(connection, callback){
function addErrorListener(connection, callback) {
connection.errorHandler.unshift(callback);
}
function removeErrorListener(connection){
function removeErrorListener(connection) {
connection.errorHandler.shift();
}
......@@ -3,64 +3,56 @@
*/
var SMB2Message = require('./smb2-message');
/*
* SMB2 MESSAGE FORGE
*/
var SMB2Forge = module.exports = {};
var SMB2Forge = (module.exports = {});
/*
* SMB2 MESSAGE FORGE
*/
SMB2Forge.request = function(messageName, params, connection, cb){
var msg = require('../messages/'+messageName)
, smbMessage = msg.generate(connection, params)
;
SMB2Forge.request = function(messageName, params, connection, cb) {
var msg = require('../messages/' + messageName),
smbMessage = msg.generate(connection, params);
// send
sendNetBiosMessage(
connection
, smbMessage
);
sendNetBiosMessage(connection, smbMessage);
// wait for the response
getResponse(
connection
, smbMessage.getHeaders().MessageId
, msg.parse(connection, cb)
connection,
smbMessage.getHeaders().MessageId,
msg.parse(connection, cb)
);
}
};
/*
* SMB2 RESPONSE MESSAGE PARSER
*/
SMB2Forge.response = function(c){
SMB2Forge.response = function(c) {
c.responses = {};
c.responsesCB = {};
c.responseBuffer = new Buffer(0);
return function(response){
return function(response) {
// concat new response
c.responseBuffer = Buffer.concat([c.responseBuffer, response]);
// extract complete messages
var extract = true;
while(extract){
while (extract) {
extract = false;
// has a message header
if(c.responseBuffer.length >= 4) {
if (c.responseBuffer.length >= 4) {
// message is complete
var msgLength = (c.responseBuffer.readUInt8(1) << 16) + c.responseBuffer.readUInt16BE(2);
if(c.responseBuffer.length >= msgLength + 4) {
var msgLength =
(c.responseBuffer.readUInt8(1) << 16) +
c.responseBuffer.readUInt16BE(2);
if (c.responseBuffer.length >= msgLength + 4) {
// set the flags
extract = true;
// parse message
var r = c.responseBuffer.slice(4, msgLength+4)
, message = new SMB2Message()
;
var r = c.responseBuffer.slice(4, msgLength + 4),
message = new SMB2Message();
message.parseBuffer(r);
//debug
if(c.debug){
if (c.debug) {
console.log('--response');
console.log(r.toString('hex'));
}
......@@ -68,22 +60,19 @@ SMB2Forge.response = function(c){
var mId = message.getHeaders().MessageId.toString('hex');
// check if the message can be dispatched
// or store it
if(c.responsesCB[mId]) {
if (c.responsesCB[mId]) {
c.responsesCB[mId](message);
delete c.responsesCB[mId];
} else {
c.responses[mId] = message;
}
// remove from response buffer
c.responseBuffer = c.responseBuffer.slice(msgLength+4);
c.responseBuffer = c.responseBuffer.slice(msgLength + 4);
}
}
}
}
}
};
};
/*
* HELPERS
......@@ -91,39 +80,36 @@ SMB2Forge.response = function(c){
function sendNetBiosMessage(connection, message) {
var smbRequest = message.getBuffer(connection);
if(connection.debug){
if (connection.debug) {
console.log('--request');
console.log(smbRequest.toString('hex'));
}
// create NetBios package
var buffer = new Buffer(smbRequest.length+4);
var buffer = new Buffer(smbRequest.length + 4);
// write NetBios cmd
buffer.writeUInt8(0x00, 0);
// write message length
buffer.writeUInt8((0xFF0000 & smbRequest.length) >> 16, 1);
buffer.writeUInt16BE(0xFFFF & smbRequest.length, 2);
buffer.writeUInt8((0xff0000 & smbRequest.length) >> 16, 1);
buffer.writeUInt16BE(0xffff & smbRequest.length, 2);
// write message content
smbRequest.copy(buffer, 4, 0, smbRequest.length);
// Send it !!!
connection.newResponse = false;
connection.socket.write(buffer);
return true;
}
function getResponse(c, mId, cb) {
var messageId = new Buffer(4);
messageId.writeUInt32LE(mId, 0);
messageId = messageId.toString('hex');
if(c.responses[messageId]) {
if (c.responses[messageId]) {
cb(c.responses[messageId]);
delete c.responses[messageId];
} else {
......
This diff is collapsed.
......@@ -39,6 +39,7 @@
"devDependencies": {
"babel": "^5.8.34",
"babel-eslint": "^4.1.6",
"prettier": "^1.13.7",
"source-map-support": "^0.4.0",
"standard": "^5.4.1"
},
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment