feat: ✨ Created a mini nodeJS server with NewMan for testing without PostMan GUI.
This will mimic a run in a CD/CI environment or docker container.
This commit is contained in:
4
node_modules/httpntlm/.jshintrc
generated
vendored
Normal file
4
node_modules/httpntlm/.jshintrc
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"node": true,
|
||||
"laxbreak": true
|
||||
}
|
20
node_modules/httpntlm/LICENSE
generated
vendored
Normal file
20
node_modules/httpntlm/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2013 Sam
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
208
node_modules/httpntlm/README.md
generated
vendored
Normal file
208
node_modules/httpntlm/README.md
generated
vendored
Normal file
@@ -0,0 +1,208 @@
|
||||
# httpntlm
|
||||
|
||||
__httpntlm__ is a Node.js library to do HTTP NTLM authentication
|
||||
|
||||
It's a port from the Python libary [python-ntml](https://code.google.com/p/python-ntlm/)
|
||||
|
||||
## Install
|
||||
|
||||
You can install __httpntlm__ using the Node Package Manager (npm):
|
||||
|
||||
npm install httpntlm
|
||||
|
||||
## How to use
|
||||
|
||||
```js
|
||||
var httpntlm = require('httpntlm');
|
||||
|
||||
httpntlm.get({
|
||||
url: "https://someurl.com",
|
||||
username: 'm$',
|
||||
password: 'stinks',
|
||||
workstation: 'choose.something',
|
||||
domain: ''
|
||||
}, function (err, res){
|
||||
if(err) return err;
|
||||
|
||||
console.log(res.headers);
|
||||
console.log(res.body);
|
||||
});
|
||||
```
|
||||
|
||||
It supports __http__ and __https__.
|
||||
|
||||
## pre-encrypt the password
|
||||
```js
|
||||
|
||||
var httpntlm = require('httpntlm');
|
||||
var ntlm = httpntlm.ntlm;
|
||||
var lm = ntlm.create_LM_hashed_password('Azx123456');
|
||||
var nt = ntlm.create_NT_hashed_password('Azx123456');
|
||||
console.log(lm);
|
||||
console.log(Array.prototype.slice.call(lm, 0));
|
||||
lm = new Buffer([ 183, 180, 19, 95, 163, 5, 118, 130, 30, 146, 159, 252, 1, 57, 81, 39 ]);
|
||||
console.log(lm);
|
||||
|
||||
console.log(nt);
|
||||
console.log(Array.prototype.slice.call(nt, 0));
|
||||
nt = new Buffer([150, 27, 7, 219, 220, 207, 134, 159, 42, 60, 153, 28, 131, 148, 14, 1]);
|
||||
console.log(nt);
|
||||
|
||||
|
||||
httpntlm.get({
|
||||
url: "https://someurl.com",
|
||||
username: 'm$',
|
||||
lm_password: lm,
|
||||
nt_password: nt,
|
||||
workstation: 'choose.something',
|
||||
domain: ''
|
||||
}, function (err, res){
|
||||
if(err) return err;
|
||||
|
||||
console.log(res.headers);
|
||||
console.log(res.body);
|
||||
});
|
||||
|
||||
/* you can save the array into your code and use it when you need it
|
||||
|
||||
<Buffer b7 b4 13 5f a3 05 76 82 1e 92 9f fc 01 39 51 27>// before convert to array
|
||||
[ 183, 180, 19, 95, 163, 5, 118, 130, 30, 146, 159, 252, 1, 57, 81, 39 ]// convert to array
|
||||
<Buffer b7 b4 13 5f a3 05 76 82 1e 92 9f fc 01 39 51 27>//convert back to buffer
|
||||
|
||||
<Buffer 96 1b 07 db dc cf 86 9f 2a 3c 99 1c 83 94 0e 01>
|
||||
[ 150, 27, 7, 219, 220, 207, 134, 159, 42, 60, 153, 28, 131, 148, 14, 1 ]
|
||||
<Buffer 96 1b 07 db dc cf 86 9f 2a 3c 99 1c 83 94 0e 01>
|
||||
*/
|
||||
|
||||
```
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
- `url:` _{String}_ URL to connect. (Required)
|
||||
- `username:` _{String}_ Username. (Required)
|
||||
- `password:` _{String}_ Password. (Required)
|
||||
- `workstation:` _{String}_ Name of workstation or `''`.
|
||||
- `domain:` _{String}_ Name of domain or `''`.
|
||||
|
||||
if you already got the encrypted password,you should use this two param to replace the 'password' param.
|
||||
|
||||
- `lm_password` _{Buffer}_ encrypted lm password.(Required)
|
||||
- `nt_password` _{Buffer}_ encrypted nt password. (Required)
|
||||
|
||||
You can also pass along all other options of [httpreq](https://github.com/SamDecrock/node-httpreq), including custom headers, cookies, body data, ... and use POST, PUT or DELETE instead of GET.
|
||||
|
||||
|
||||
|
||||
|
||||
## Advanced
|
||||
|
||||
If you want to use the NTLM-functions yourself, you can access the ntlm-library like this (https example):
|
||||
|
||||
```js
|
||||
var ntlm = require('httpntlm').ntlm;
|
||||
var async = require('async');
|
||||
var httpreq = require('httpreq');
|
||||
var HttpsAgent = require('agentkeepalive').HttpsAgent;
|
||||
var keepaliveAgent = new HttpsAgent();
|
||||
|
||||
var options = {
|
||||
url: "https://someurl.com",
|
||||
username: 'm$',
|
||||
password: 'stinks',
|
||||
workstation: 'choose.something',
|
||||
domain: ''
|
||||
};
|
||||
|
||||
async.waterfall([
|
||||
function (callback){
|
||||
var type1msg = ntlm.createType1Message(options);
|
||||
|
||||
httpreq.get(options.url, {
|
||||
headers:{
|
||||
'Connection' : 'keep-alive',
|
||||
'Authorization': type1msg
|
||||
},
|
||||
agent: keepaliveAgent
|
||||
}, callback);
|
||||
},
|
||||
|
||||
function (res, callback){
|
||||
if(!res.headers['www-authenticate'])
|
||||
return callback(new Error('www-authenticate not found on response of second request'));
|
||||
|
||||
var type2msg = ntlm.parseType2Message(res.headers['www-authenticate']);
|
||||
var type3msg = ntlm.createType3Message(type2msg, options);
|
||||
|
||||
setImmediate(function() {
|
||||
httpreq.get(options.url, {
|
||||
headers:{
|
||||
'Connection' : 'Close',
|
||||
'Authorization': type3msg
|
||||
},
|
||||
allowRedirects: false,
|
||||
agent: keepaliveAgent
|
||||
}, callback);
|
||||
});
|
||||
}
|
||||
], function (err, res) {
|
||||
if(err) return console.log(err);
|
||||
|
||||
console.log(res.headers);
|
||||
console.log(res.body);
|
||||
});
|
||||
```
|
||||
|
||||
## Download binary files
|
||||
|
||||
```javascript
|
||||
httpntlm.get({
|
||||
url: "https://someurl.com/file.xls",
|
||||
username: 'm$',
|
||||
password: 'stinks',
|
||||
workstation: 'choose.something',
|
||||
domain: '',
|
||||
binary: true
|
||||
}, function (err, response) {
|
||||
if(err) return console.log(err);
|
||||
fs.writeFile("file.xls", response.body, function (err) {
|
||||
if(err) return console.log("error writing file");
|
||||
console.log("file.xls saved!");
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
## More information
|
||||
|
||||
* [python-ntlm](https://code.google.com/p/python-ntlm/)
|
||||
* [NTLM Authentication Scheme for HTTP](http://www.innovation.ch/personal/ronald/ntlm.html)
|
||||
* [LM hash on Wikipedia](http://en.wikipedia.org/wiki/LM_hash)
|
||||
|
||||
## Donate
|
||||
|
||||
If you like this module or you want me to update it faster, feel free to donate. It helps increasing my dedication to fixing bugs :-)
|
||||
|
||||
[](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=LPYD83FGC7XPW)
|
||||
|
||||
|
||||
## License (MIT)
|
||||
|
||||
Copyright (c) Sam Decrock <https://github.com/SamDecrock/>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
112
node_modules/httpntlm/httpntlm.js
generated
vendored
Normal file
112
node_modules/httpntlm/httpntlm.js
generated
vendored
Normal file
@@ -0,0 +1,112 @@
|
||||
/**
|
||||
* Copyright (c) 2013 Sam Decrock https://github.com/SamDecrock/
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var url = require('url');
|
||||
var httpreq = require('httpreq');
|
||||
var ntlm = require('./ntlm');
|
||||
var _ = require('underscore');
|
||||
var http = require('http');
|
||||
var https = require('https');
|
||||
|
||||
exports.method = function(method, options, finalCallback){
|
||||
if(!options.workstation) options.workstation = '';
|
||||
if(!options.domain) options.domain = '';
|
||||
|
||||
// extract non-ntlm-options:
|
||||
var httpreqOptions = _.omit(options, 'url', 'username', 'password', 'workstation', 'domain');
|
||||
|
||||
// is https?
|
||||
var isHttps = false;
|
||||
var reqUrl = url.parse(options.url);
|
||||
if(reqUrl.protocol == 'https:') isHttps = true;
|
||||
|
||||
// set keepaliveAgent (http or https):
|
||||
var keepaliveAgent;
|
||||
|
||||
if(isHttps){
|
||||
keepaliveAgent = new https.Agent({keepAlive: true});
|
||||
}else{
|
||||
keepaliveAgent = new http.Agent({keepAlive: true});
|
||||
}
|
||||
|
||||
// build type1 request:
|
||||
|
||||
function sendType1Message (callback) {
|
||||
var type1msg = ntlm.createType1Message(options);
|
||||
|
||||
var type1options = {
|
||||
headers:{
|
||||
'Connection' : 'keep-alive',
|
||||
'Authorization': type1msg
|
||||
},
|
||||
timeout: options.timeout || 0,
|
||||
agent: keepaliveAgent,
|
||||
allowRedirects: false // don't redirect in httpreq, because http could change to https which means we need to change the keepaliveAgent
|
||||
};
|
||||
|
||||
// pass along other options:
|
||||
type1options = _.extend({}, _.omit(httpreqOptions, 'headers', 'body'), type1options);
|
||||
|
||||
// send type1 message to server:
|
||||
httpreq[method](options.url, type1options, callback);
|
||||
}
|
||||
|
||||
function sendType3Message (res, callback) {
|
||||
// catch redirect here:
|
||||
if(res.headers.location) {
|
||||
options.url = res.headers.location;
|
||||
return exports[method](options, finalCallback);
|
||||
}
|
||||
|
||||
|
||||
if(!res.headers['www-authenticate'])
|
||||
return callback(new Error('www-authenticate not found on response of second request'));
|
||||
|
||||
// parse type2 message from server:
|
||||
var type2msg = ntlm.parseType2Message(res.headers['www-authenticate'], callback); //callback only happens on errors
|
||||
if(!type2msg) return; // if callback returned an error, the parse-function returns with null
|
||||
|
||||
// create type3 message:
|
||||
var type3msg = ntlm.createType3Message(type2msg, options);
|
||||
|
||||
// build type3 request:
|
||||
var type3options = {
|
||||
headers: {
|
||||
'Connection': 'Close',
|
||||
'Authorization': type3msg
|
||||
},
|
||||
allowRedirects: false,
|
||||
agent: keepaliveAgent
|
||||
};
|
||||
|
||||
// pass along other options:
|
||||
type3options.headers = _.extend(type3options.headers, httpreqOptions.headers);
|
||||
type3options = _.extend(type3options, _.omit(httpreqOptions, 'headers'));
|
||||
|
||||
// send type3 message to server:
|
||||
httpreq[method](options.url, type3options, callback);
|
||||
}
|
||||
|
||||
|
||||
sendType1Message(function (err, res) {
|
||||
if(err) return finalCallback(err);
|
||||
setImmediate(function () { // doesn't work without setImmediate()
|
||||
sendType3Message(res, finalCallback);
|
||||
});
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
['get', 'put', 'patch', 'post', 'delete', 'options'].forEach(function(method){
|
||||
exports[method] = exports.method.bind(exports, method);
|
||||
});
|
||||
|
||||
exports.ntlm = ntlm; //if you want to use the NTML functions yourself
|
||||
|
408
node_modules/httpntlm/ntlm.js
generated
vendored
Normal file
408
node_modules/httpntlm/ntlm.js
generated
vendored
Normal file
@@ -0,0 +1,408 @@
|
||||
/**
|
||||
* Copyright (c) 2013 Sam Decrock https://github.com/SamDecrock/
|
||||
* All rights reserved.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
var crypto = require('crypto');
|
||||
|
||||
var flags = {
|
||||
NTLM_NegotiateUnicode : 0x00000001,
|
||||
NTLM_NegotiateOEM : 0x00000002,
|
||||
NTLM_RequestTarget : 0x00000004,
|
||||
NTLM_Unknown9 : 0x00000008,
|
||||
NTLM_NegotiateSign : 0x00000010,
|
||||
NTLM_NegotiateSeal : 0x00000020,
|
||||
NTLM_NegotiateDatagram : 0x00000040,
|
||||
NTLM_NegotiateLanManagerKey : 0x00000080,
|
||||
NTLM_Unknown8 : 0x00000100,
|
||||
NTLM_NegotiateNTLM : 0x00000200,
|
||||
NTLM_NegotiateNTOnly : 0x00000400,
|
||||
NTLM_Anonymous : 0x00000800,
|
||||
NTLM_NegotiateOemDomainSupplied : 0x00001000,
|
||||
NTLM_NegotiateOemWorkstationSupplied : 0x00002000,
|
||||
NTLM_Unknown6 : 0x00004000,
|
||||
NTLM_NegotiateAlwaysSign : 0x00008000,
|
||||
NTLM_TargetTypeDomain : 0x00010000,
|
||||
NTLM_TargetTypeServer : 0x00020000,
|
||||
NTLM_TargetTypeShare : 0x00040000,
|
||||
NTLM_NegotiateExtendedSecurity : 0x00080000,
|
||||
NTLM_NegotiateIdentify : 0x00100000,
|
||||
NTLM_Unknown5 : 0x00200000,
|
||||
NTLM_RequestNonNTSessionKey : 0x00400000,
|
||||
NTLM_NegotiateTargetInfo : 0x00800000,
|
||||
NTLM_Unknown4 : 0x01000000,
|
||||
NTLM_NegotiateVersion : 0x02000000,
|
||||
NTLM_Unknown3 : 0x04000000,
|
||||
NTLM_Unknown2 : 0x08000000,
|
||||
NTLM_Unknown1 : 0x10000000,
|
||||
NTLM_Negotiate128 : 0x20000000,
|
||||
NTLM_NegotiateKeyExchange : 0x40000000,
|
||||
NTLM_Negotiate56 : 0x80000000
|
||||
};
|
||||
var typeflags = {
|
||||
NTLM_TYPE1_FLAGS : flags.NTLM_NegotiateUnicode
|
||||
+ flags.NTLM_NegotiateOEM
|
||||
+ flags.NTLM_RequestTarget
|
||||
+ flags.NTLM_NegotiateNTLM
|
||||
+ flags.NTLM_NegotiateOemDomainSupplied
|
||||
+ flags.NTLM_NegotiateOemWorkstationSupplied
|
||||
+ flags.NTLM_NegotiateAlwaysSign
|
||||
+ flags.NTLM_NegotiateExtendedSecurity
|
||||
+ flags.NTLM_NegotiateVersion
|
||||
+ flags.NTLM_Negotiate128
|
||||
+ flags.NTLM_Negotiate56,
|
||||
|
||||
NTLM_TYPE2_FLAGS : flags.NTLM_NegotiateUnicode
|
||||
+ flags.NTLM_RequestTarget
|
||||
+ flags.NTLM_NegotiateNTLM
|
||||
+ flags.NTLM_NegotiateAlwaysSign
|
||||
+ flags.NTLM_NegotiateExtendedSecurity
|
||||
+ flags.NTLM_NegotiateTargetInfo
|
||||
+ flags.NTLM_NegotiateVersion
|
||||
+ flags.NTLM_Negotiate128
|
||||
+ flags.NTLM_Negotiate56
|
||||
};
|
||||
|
||||
function createType1Message(options){
|
||||
var domain = escape(options.domain.toUpperCase());
|
||||
var workstation = escape(options.workstation.toUpperCase());
|
||||
var protocol = 'NTLMSSP\0';
|
||||
|
||||
var BODY_LENGTH = 40;
|
||||
|
||||
var type1flags = typeflags.NTLM_TYPE1_FLAGS;
|
||||
if(!domain || domain === '')
|
||||
type1flags = type1flags - flags.NTLM_NegotiateOemDomainSupplied;
|
||||
|
||||
var pos = 0;
|
||||
var buf = new Buffer(BODY_LENGTH + domain.length + workstation.length);
|
||||
|
||||
|
||||
buf.write(protocol, pos, protocol.length); pos += protocol.length; // protocol
|
||||
buf.writeUInt32LE(1, pos); pos += 4; // type 1
|
||||
buf.writeUInt32LE(type1flags, pos); pos += 4; // TYPE1 flag
|
||||
|
||||
buf.writeUInt16LE(domain.length, pos); pos += 2; // domain length
|
||||
buf.writeUInt16LE(domain.length, pos); pos += 2; // domain max length
|
||||
buf.writeUInt32LE(BODY_LENGTH + workstation.length, pos); pos += 4; // domain buffer offset
|
||||
|
||||
buf.writeUInt16LE(workstation.length, pos); pos += 2; // workstation length
|
||||
buf.writeUInt16LE(workstation.length, pos); pos += 2; // workstation max length
|
||||
buf.writeUInt32LE(BODY_LENGTH, pos); pos += 4; // workstation buffer offset
|
||||
|
||||
buf.writeUInt8(5, pos); pos += 1; //ProductMajorVersion
|
||||
buf.writeUInt8(1, pos); pos += 1; //ProductMinorVersion
|
||||
buf.writeUInt16LE(2600, pos); pos += 2; //ProductBuild
|
||||
|
||||
buf.writeUInt8(0 , pos); pos += 1; //VersionReserved1
|
||||
buf.writeUInt8(0 , pos); pos += 1; //VersionReserved2
|
||||
buf.writeUInt8(0 , pos); pos += 1; //VersionReserved3
|
||||
buf.writeUInt8(15, pos); pos += 1; //NTLMRevisionCurrent
|
||||
|
||||
|
||||
// length checks is to fix issue #46 and possibly #57
|
||||
if(workstation.length !=0) buf.write(workstation, pos, workstation.length, 'ascii'); pos += workstation.length; // workstation string
|
||||
if(domain.length !=0) buf.write(domain , pos, domain.length , 'ascii'); pos += domain.length; // domain string
|
||||
|
||||
return 'NTLM ' + buf.toString('base64');
|
||||
}
|
||||
|
||||
function parseType2Message(rawmsg, callback){
|
||||
var match = rawmsg.match(/NTLM (.+)?/);
|
||||
if(!match || !match[1]) {
|
||||
callback(new Error("Couldn't find NTLM in the message type2 comming from the server"));
|
||||
return null;
|
||||
}
|
||||
|
||||
var buf = new Buffer(match[1], 'base64');
|
||||
|
||||
var msg = {};
|
||||
|
||||
msg.signature = buf.slice(0, 8);
|
||||
msg.type = buf.readInt16LE(8);
|
||||
|
||||
if(msg.type != 2) {
|
||||
callback(new Error("Server didn't return a type 2 message"));
|
||||
return null;
|
||||
}
|
||||
|
||||
msg.targetNameLen = buf.readInt16LE(12);
|
||||
msg.targetNameMaxLen = buf.readInt16LE(14);
|
||||
msg.targetNameOffset = buf.readInt32LE(16);
|
||||
msg.targetName = buf.slice(msg.targetNameOffset, msg.targetNameOffset + msg.targetNameMaxLen);
|
||||
|
||||
msg.negotiateFlags = buf.readInt32LE(20);
|
||||
msg.serverChallenge = buf.slice(24, 32);
|
||||
msg.reserved = buf.slice(32, 40);
|
||||
|
||||
if(msg.negotiateFlags & flags.NTLM_NegotiateTargetInfo){
|
||||
msg.targetInfoLen = buf.readInt16LE(40);
|
||||
msg.targetInfoMaxLen = buf.readInt16LE(42);
|
||||
msg.targetInfoOffset = buf.readInt32LE(44);
|
||||
msg.targetInfo = buf.slice(msg.targetInfoOffset, msg.targetInfoOffset + msg.targetInfoLen);
|
||||
}
|
||||
return msg;
|
||||
}
|
||||
|
||||
function createType3Message(msg2, options){
|
||||
var nonce = msg2.serverChallenge;
|
||||
var username = options.username;
|
||||
var password = options.password;
|
||||
var lm_password = options.lm_password;
|
||||
var nt_password = options.nt_password;
|
||||
var negotiateFlags = msg2.negotiateFlags;
|
||||
|
||||
var isUnicode = negotiateFlags & flags.NTLM_NegotiateUnicode;
|
||||
var isNegotiateExtendedSecurity = negotiateFlags & flags.NTLM_NegotiateExtendedSecurity;
|
||||
|
||||
var BODY_LENGTH = 72;
|
||||
|
||||
var domainName = escape(options.domain.toUpperCase());
|
||||
var workstation = escape(options.workstation.toUpperCase());
|
||||
|
||||
var workstationBytes, domainNameBytes, usernameBytes, encryptedRandomSessionKeyBytes;
|
||||
|
||||
var encryptedRandomSessionKey = "";
|
||||
if(isUnicode){
|
||||
workstationBytes = new Buffer(workstation, 'utf16le');
|
||||
domainNameBytes = new Buffer(domainName, 'utf16le');
|
||||
usernameBytes = new Buffer(username, 'utf16le');
|
||||
encryptedRandomSessionKeyBytes = new Buffer(encryptedRandomSessionKey, 'utf16le');
|
||||
}else{
|
||||
workstationBytes = new Buffer(workstation, 'ascii');
|
||||
domainNameBytes = new Buffer(domainName, 'ascii');
|
||||
usernameBytes = new Buffer(username, 'ascii');
|
||||
encryptedRandomSessionKeyBytes = new Buffer(encryptedRandomSessionKey, 'ascii');
|
||||
}
|
||||
|
||||
var lmChallengeResponse = calc_resp((lm_password!=null)?lm_password:create_LM_hashed_password_v1(password), nonce);
|
||||
var ntChallengeResponse = calc_resp((nt_password!=null)?nt_password:create_NT_hashed_password_v1(password), nonce);
|
||||
|
||||
if(isNegotiateExtendedSecurity){
|
||||
var pwhash = (nt_password!=null)?nt_password:create_NT_hashed_password_v1(password);
|
||||
var clientChallenge = "";
|
||||
for(var i=0; i < 8; i++){
|
||||
clientChallenge += String.fromCharCode( Math.floor(Math.random()*256) );
|
||||
}
|
||||
var clientChallengeBytes = new Buffer(clientChallenge, 'ascii');
|
||||
var challenges = ntlm2sr_calc_resp(pwhash, nonce, clientChallengeBytes);
|
||||
lmChallengeResponse = challenges.lmChallengeResponse;
|
||||
ntChallengeResponse = challenges.ntChallengeResponse;
|
||||
}
|
||||
|
||||
var signature = 'NTLMSSP\0';
|
||||
|
||||
var pos = 0;
|
||||
var buf = new Buffer(BODY_LENGTH + domainNameBytes.length + usernameBytes.length + workstationBytes.length + lmChallengeResponse.length + ntChallengeResponse.length + encryptedRandomSessionKeyBytes.length);
|
||||
|
||||
buf.write(signature, pos, signature.length); pos += signature.length;
|
||||
buf.writeUInt32LE(3, pos); pos += 4; // type 1
|
||||
|
||||
buf.writeUInt16LE(lmChallengeResponse.length, pos); pos += 2; // LmChallengeResponseLen
|
||||
buf.writeUInt16LE(lmChallengeResponse.length, pos); pos += 2; // LmChallengeResponseMaxLen
|
||||
buf.writeUInt32LE(BODY_LENGTH + domainNameBytes.length + usernameBytes.length + workstationBytes.length, pos); pos += 4; // LmChallengeResponseOffset
|
||||
|
||||
buf.writeUInt16LE(ntChallengeResponse.length, pos); pos += 2; // NtChallengeResponseLen
|
||||
buf.writeUInt16LE(ntChallengeResponse.length, pos); pos += 2; // NtChallengeResponseMaxLen
|
||||
buf.writeUInt32LE(BODY_LENGTH + domainNameBytes.length + usernameBytes.length + workstationBytes.length + lmChallengeResponse.length, pos); pos += 4; // NtChallengeResponseOffset
|
||||
|
||||
buf.writeUInt16LE(domainNameBytes.length, pos); pos += 2; // DomainNameLen
|
||||
buf.writeUInt16LE(domainNameBytes.length, pos); pos += 2; // DomainNameMaxLen
|
||||
buf.writeUInt32LE(BODY_LENGTH, pos); pos += 4; // DomainNameOffset
|
||||
|
||||
buf.writeUInt16LE(usernameBytes.length, pos); pos += 2; // UserNameLen
|
||||
buf.writeUInt16LE(usernameBytes.length, pos); pos += 2; // UserNameMaxLen
|
||||
buf.writeUInt32LE(BODY_LENGTH + domainNameBytes.length, pos); pos += 4; // UserNameOffset
|
||||
|
||||
buf.writeUInt16LE(workstationBytes.length, pos); pos += 2; // WorkstationLen
|
||||
buf.writeUInt16LE(workstationBytes.length, pos); pos += 2; // WorkstationMaxLen
|
||||
buf.writeUInt32LE(BODY_LENGTH + domainNameBytes.length + usernameBytes.length, pos); pos += 4; // WorkstationOffset
|
||||
|
||||
buf.writeUInt16LE(encryptedRandomSessionKeyBytes.length, pos); pos += 2; // EncryptedRandomSessionKeyLen
|
||||
buf.writeUInt16LE(encryptedRandomSessionKeyBytes.length, pos); pos += 2; // EncryptedRandomSessionKeyMaxLen
|
||||
buf.writeUInt32LE(BODY_LENGTH + domainNameBytes.length + usernameBytes.length + workstationBytes.length + lmChallengeResponse.length + ntChallengeResponse.length, pos); pos += 4; // EncryptedRandomSessionKeyOffset
|
||||
|
||||
buf.writeUInt32LE(typeflags.NTLM_TYPE2_FLAGS, pos); pos += 4; // NegotiateFlags
|
||||
|
||||
buf.writeUInt8(5, pos); pos++; // ProductMajorVersion
|
||||
buf.writeUInt8(1, pos); pos++; // ProductMinorVersion
|
||||
buf.writeUInt16LE(2600, pos); pos += 2; // ProductBuild
|
||||
buf.writeUInt8(0, pos); pos++; // VersionReserved1
|
||||
buf.writeUInt8(0, pos); pos++; // VersionReserved2
|
||||
buf.writeUInt8(0, pos); pos++; // VersionReserved3
|
||||
buf.writeUInt8(15, pos); pos++; // NTLMRevisionCurrent
|
||||
|
||||
domainNameBytes.copy(buf, pos); pos += domainNameBytes.length;
|
||||
usernameBytes.copy(buf, pos); pos += usernameBytes.length;
|
||||
workstationBytes.copy(buf, pos); pos += workstationBytes.length;
|
||||
lmChallengeResponse.copy(buf, pos); pos += lmChallengeResponse.length;
|
||||
ntChallengeResponse.copy(buf, pos); pos += ntChallengeResponse.length;
|
||||
encryptedRandomSessionKeyBytes.copy(buf, pos); pos += encryptedRandomSessionKeyBytes.length;
|
||||
|
||||
return 'NTLM ' + buf.toString('base64');
|
||||
}
|
||||
|
||||
function create_LM_hashed_password_v1(password){
|
||||
// fix the password length to 14 bytes
|
||||
password = password.toUpperCase();
|
||||
var passwordBytes = new Buffer(password, 'ascii');
|
||||
|
||||
var passwordBytesPadded = new Buffer(14);
|
||||
passwordBytesPadded.fill("\0");
|
||||
var sourceEnd = 14;
|
||||
if(passwordBytes.length < 14) sourceEnd = passwordBytes.length;
|
||||
passwordBytes.copy(passwordBytesPadded, 0, 0, sourceEnd);
|
||||
|
||||
// split into 2 parts of 7 bytes:
|
||||
var firstPart = passwordBytesPadded.slice(0,7);
|
||||
var secondPart = passwordBytesPadded.slice(7);
|
||||
|
||||
function encrypt(buf){
|
||||
var key = insertZerosEvery7Bits(buf);
|
||||
var des = crypto.createCipheriv('DES-ECB', key, '');
|
||||
return des.update("KGS!@#$%"); // page 57 in [MS-NLMP]);
|
||||
}
|
||||
|
||||
var firstPartEncrypted = encrypt(firstPart);
|
||||
var secondPartEncrypted = encrypt(secondPart);
|
||||
|
||||
return Buffer.concat([firstPartEncrypted, secondPartEncrypted]);
|
||||
}
|
||||
|
||||
function insertZerosEvery7Bits(buf){
|
||||
var binaryArray = bytes2binaryArray(buf);
|
||||
var newBinaryArray = [];
|
||||
for(var i=0; i<binaryArray.length; i++){
|
||||
newBinaryArray.push(binaryArray[i]);
|
||||
|
||||
if((i+1)%7 === 0){
|
||||
newBinaryArray.push(0);
|
||||
}
|
||||
}
|
||||
return binaryArray2bytes(newBinaryArray);
|
||||
}
|
||||
|
||||
function bytes2binaryArray(buf){
|
||||
var hex2binary = {
|
||||
0: [0,0,0,0],
|
||||
1: [0,0,0,1],
|
||||
2: [0,0,1,0],
|
||||
3: [0,0,1,1],
|
||||
4: [0,1,0,0],
|
||||
5: [0,1,0,1],
|
||||
6: [0,1,1,0],
|
||||
7: [0,1,1,1],
|
||||
8: [1,0,0,0],
|
||||
9: [1,0,0,1],
|
||||
A: [1,0,1,0],
|
||||
B: [1,0,1,1],
|
||||
C: [1,1,0,0],
|
||||
D: [1,1,0,1],
|
||||
E: [1,1,1,0],
|
||||
F: [1,1,1,1]
|
||||
};
|
||||
|
||||
var hexString = buf.toString('hex').toUpperCase();
|
||||
var array = [];
|
||||
for(var i=0; i<hexString.length; i++){
|
||||
var hexchar = hexString.charAt(i);
|
||||
array = array.concat(hex2binary[hexchar]);
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
function binaryArray2bytes(array){
|
||||
var binary2hex = {
|
||||
'0000': 0,
|
||||
'0001': 1,
|
||||
'0010': 2,
|
||||
'0011': 3,
|
||||
'0100': 4,
|
||||
'0101': 5,
|
||||
'0110': 6,
|
||||
'0111': 7,
|
||||
'1000': 8,
|
||||
'1001': 9,
|
||||
'1010': 'A',
|
||||
'1011': 'B',
|
||||
'1100': 'C',
|
||||
'1101': 'D',
|
||||
'1110': 'E',
|
||||
'1111': 'F'
|
||||
};
|
||||
|
||||
var bufArray = [];
|
||||
|
||||
for(var i=0; i<array.length; i +=8 ){
|
||||
if((i+7) > array.length)
|
||||
break;
|
||||
|
||||
var binString1 = '' + array[i] + '' + array[i+1] + '' + array[i+2] + '' + array[i+3];
|
||||
var binString2 = '' + array[i+4] + '' + array[i+5] + '' + array[i+6] + '' + array[i+7];
|
||||
var hexchar1 = binary2hex[binString1];
|
||||
var hexchar2 = binary2hex[binString2];
|
||||
|
||||
var buf = new Buffer(hexchar1 + '' + hexchar2, 'hex');
|
||||
bufArray.push(buf);
|
||||
}
|
||||
|
||||
return Buffer.concat(bufArray);
|
||||
}
|
||||
|
||||
function create_NT_hashed_password_v1(password){
|
||||
var buf = new Buffer(password, 'utf16le');
|
||||
var md4 = crypto.createHash('md4');
|
||||
md4.update(buf);
|
||||
return new Buffer(md4.digest());
|
||||
}
|
||||
|
||||
function calc_resp(password_hash, server_challenge){
|
||||
// padding with zeros to make the hash 21 bytes long
|
||||
var passHashPadded = new Buffer(21);
|
||||
passHashPadded.fill("\0");
|
||||
password_hash.copy(passHashPadded, 0, 0, password_hash.length);
|
||||
|
||||
var resArray = [];
|
||||
|
||||
var des = crypto.createCipheriv('DES-ECB', insertZerosEvery7Bits(passHashPadded.slice(0,7)), '');
|
||||
resArray.push( des.update(server_challenge.slice(0,8)) );
|
||||
|
||||
des = crypto.createCipheriv('DES-ECB', insertZerosEvery7Bits(passHashPadded.slice(7,14)), '');
|
||||
resArray.push( des.update(server_challenge.slice(0,8)) );
|
||||
|
||||
des = crypto.createCipheriv('DES-ECB', insertZerosEvery7Bits(passHashPadded.slice(14,21)), '');
|
||||
resArray.push( des.update(server_challenge.slice(0,8)) );
|
||||
|
||||
return Buffer.concat(resArray);
|
||||
}
|
||||
|
||||
function ntlm2sr_calc_resp(responseKeyNT, serverChallenge, clientChallenge){
|
||||
// padding with zeros to make the hash 16 bytes longer
|
||||
var lmChallengeResponse = new Buffer(clientChallenge.length + 16);
|
||||
lmChallengeResponse.fill("\0");
|
||||
clientChallenge.copy(lmChallengeResponse, 0, 0, clientChallenge.length);
|
||||
|
||||
var buf = Buffer.concat([serverChallenge, clientChallenge]);
|
||||
var md5 = crypto.createHash('md5');
|
||||
md5.update(buf);
|
||||
var sess = md5.digest();
|
||||
var ntChallengeResponse = calc_resp(responseKeyNT, sess.slice(0,8));
|
||||
|
||||
return {
|
||||
lmChallengeResponse: lmChallengeResponse,
|
||||
ntChallengeResponse: ntChallengeResponse
|
||||
};
|
||||
}
|
||||
|
||||
exports.createType1Message = createType1Message;
|
||||
exports.parseType2Message = parseType2Message;
|
||||
exports.createType3Message = createType3Message;
|
||||
exports.create_NT_hashed_password = create_NT_hashed_password_v1;
|
||||
exports.create_LM_hashed_password = create_LM_hashed_password_v1;
|
||||
|
||||
|
||||
|
||||
|
33
node_modules/httpntlm/package.json
generated
vendored
Normal file
33
node_modules/httpntlm/package.json
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "httpntlm",
|
||||
"description": "httpntlm is a Node.js library to do HTTP NTLM authentication",
|
||||
"version": "1.7.7",
|
||||
"dependencies": {
|
||||
"httpreq": ">=0.4.22",
|
||||
"underscore": "~1.12.1"
|
||||
},
|
||||
"author": {
|
||||
"name": "Sam Decrock",
|
||||
"url": "https://github.com/SamDecrock/"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/SamDecrock/node-http-ntlm/issues"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.8.0"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git://github.com/SamDecrock/node-http-ntlm.git"
|
||||
},
|
||||
"main": "./httpntlm",
|
||||
"licenses": [
|
||||
{
|
||||
"type": "MIT",
|
||||
"url": "http://www.opensource.org/licenses/mit-license.php"
|
||||
}
|
||||
],
|
||||
"scripts": {
|
||||
"jshint": "jshint *.js"
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user