@vinothnb/smb2
Version:
160 lines (145 loc) • 4.13 kB
JavaScript
/*
* DEPENDENCIES
*/
var net = require('net');
var SMB2Forge = require('./smb2-forge');
var SMB2Request = SMB2Forge.request;
/*
* CONNECTION MANAGER
*/
var SMB2Connection = (module.exports = {});
/*
* CLOSE CONNECTION
*/
SMB2Connection.close = function(connection) {
clearAutoCloseTimeout(connection);
if (connection.connected) {
connection.connected = false;
connection.socket.end();
}
};
/*
* OPEN CONNECTION
*/
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));
}
throw err;
}
};
}
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) {
// create a socket
connection.connected = false;
connection.socket = new net.Socket({
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);
}
if (connection.debug) {
console.log('-- error'); // eslint-disable-line no-console
console.log(arguments); // eslint-disable-line no-console
}
});
};
/*
* PRIVATE FUNCTION TO HANDLE CONNECTION
*/
function connect(connection, cb) {
if (connection.connected) {
cb && cb(null);
return;
}
cb = scheduleAutoClose(connection, cb);
// set message id
connection.messageId = 0;
// set session id
connection.SessionId = Math.floor(Math.random() * 256) & 0xff;
// open TCP socket
connection.socket.connect(connection.port, connection.ip);
// SMB2 negotiate connection
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);
}
});
});
});
});
}
/*
* PRIVATE FUNCTION TO HANDLE CLOSING THE CONNECTION
*/
function clearAutoCloseTimeout(connection) {
if (connection.scheduledAutoClose) {
clearTimeout(connection.scheduledAutoClose);
connection.scheduledAutoClose = null;
}
}
function setAutoCloseTimeout(connection) {
clearAutoCloseTimeout(connection);
if (connection.autoCloseTimeout !== 0) {
connection.scheduledAutoClose = setTimeout(function() {
SMB2Connection.close(connection);
}, connection.autoCloseTimeout);
}
}
function scheduleAutoClose(connection, cb) {
addErrorListener(connection, cb);
clearAutoCloseTimeout(connection);
return function() {
removeErrorListener(connection);
setAutoCloseTimeout(connection);
cb.apply(null, arguments);
};
}
/*
* PRIVATE FUNCTIONS TO HANDLE ERRORS
*/
function addErrorListener(connection, callback) {
connection.errorHandler.unshift(callback);
}
function removeErrorListener(connection) {
connection.errorHandler.shift();
}