Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
options = options || {};
var type2Message = 'NTLM ' +
'TlRMTVNTUAACAAAAHgAeADgAAAAFgoqiBevywvJykjAAAAAAAAAAAJgAmABWAAAA' +
'CgC6RwAAAA9EAEUAUwBLAFQATwBQAC0ASgBTADQAVQBKAFQARAACAB4ARABFAFMA' +
'SwBUAE8AUAAtAEoAUwA0AFUASgBUAEQAAQAeAEQARQBTAEsAVABPAFAALQBKAFMA' +
'NABVAEoAVABEAAQAHgBEAEUAUwBLAFQATwBQAC0ASgBTADQAVQBKAFQARAADAB4A' +
'RABFAFMASwBUAE8AUAAtAEoAUwA0AFUASgBUAEQABwAIADmguzCHn9UBAAAAAA==',
parsedType2Message = ntlmUtils.parseType2Message(type2Message, _.noop),
username = options.username || 'username',
password = options.password || 'password',
domain = options.domain || '',
workstation = options.workstation || '',
type1Message = ntlmUtils.createType1Message({
domain,
workstation
}),
type3Message = ntlmUtils.createType3Message(parsedType2Message, {
domain,
workstation,
username,
password
}),
handler = function (req, res) {
var authHeaders = req.headers.authorization;
// send type2 message and ask for type3 message
if (authHeaders && authHeaders.startsWith(type1Message.slice(0, 20))) {
res.writeHead(401, {
'CgC6RwAAAA9EAEUAUwBLAFQATwBQAC0ASgBTADQAVQBKAFQARAACAB4ARABFAFMA' +
'SwBUAE8AUAAtAEoAUwA0AFUASgBUAEQAAQAeAEQARQBTAEsAVABPAFAALQBKAFMA' +
'NABVAEoAVABEAAQAHgBEAEUAUwBLAFQATwBQAC0ASgBTADQAVQBKAFQARAADAB4A' +
'RABFAFMASwBUAE8AUAAtAEoAUwA0AFUASgBUAEQABwAIADmguzCHn9UBAAAAAA==',
parsedType2Message = ntlmUtils.parseType2Message(type2Message, _.noop),
username = options.username || 'username',
password = options.password || 'password',
domain = options.domain || '',
workstation = options.workstation || '',
type1Message = ntlmUtils.createType1Message({
domain,
workstation
}),
type3Message = ntlmUtils.createType3Message(parsedType2Message, {
domain,
workstation,
username,
password
}),
handler = function (req, res) {
var authHeaders = req.headers.authorization;
// send type2 message and ask for type3 message
if (authHeaders && authHeaders.startsWith(type1Message.slice(0, 20))) {
res.writeHead(401, {
// @note we're sending a 'Negotiate' header here to make
// sure that runtime can handle it.
'www-authenticate': [type2Message, 'Negotiate']
if (!challengeMatch) {
return callback(this._formatError('Invalid login sequence while waiting for server challenge string', 'EAUTH', str, 'AUTH NTLM'));
} else {
challengeString = challengeMatch[1];
}
if (!/^NTLM/i.test(challengeString)) {
challengeString = 'NTLM ' + challengeString;
}
let type2Message = ntlm.parseType2Message(challengeString, callback);
if (!type2Message) {
return;
}
let type3Message = ntlm.createType3Message(type2Message, {
domain: this._auth.domain || '',
workstation: this._auth.workstation || '',
username: this._auth.user,
password: this._auth.pass
});
type3Message = type3Message.substring(5); // remove the "NTLM " prefix
this._responseActions.push(str => {
this._actionAUTH_NTLM_TYPE3(str, callback);
});
this._sendCommand(type3Message);
}
if (!challengeMatch) {
return callback(this._formatError('Invalid login sequence while waiting for server challenge string', 'EAUTH', str, 'AUTH NTLM'));
} else {
challengeString = challengeMatch[1];
}
if (!/^NTLM/i.test(challengeString)) {
challengeString = 'NTLM ' + challengeString;
}
var type2Message = ntlm.parseType2Message(challengeString, callback);
if (!type2Message) {
return;
}
var type3Message = ntlm.createType3Message(type2Message, {
domain: this._auth.domain || '',
workstation: this._auth.workstation || '',
username: this._auth.user,
password: this._auth.pass
});
type3Message = type3Message.substring(5); // remove the "NTLM " prefix
this._responseActions.push(function (str) {
this._actionAUTH_NTLM_TYPE3(str, callback);
}.bind(this));
this._sendCommand(type3Message);
};
_actionAUTH_NTLM_TYPE1(str, callback) {
let challengeMatch = str.match(/^334\s+(.+)$/);
let challengeString = '';
if (!challengeMatch) {
return callback(this._formatError('Invalid login sequence while waiting for server challenge string', 'EAUTH', str, 'AUTH NTLM'));
} else {
challengeString = challengeMatch[1];
}
if (!/^NTLM/i.test(challengeString)) {
challengeString = 'NTLM ' + challengeString;
}
let type2Message = ntlm.parseType2Message(challengeString, callback);
if (!type2Message) {
return;
}
let type3Message = ntlm.createType3Message(type2Message, {
domain: this._auth.domain || '',
workstation: this._auth.workstation || '',
username: this._auth.user,
password: this._auth.pass
});
type3Message = type3Message.substring(5); // remove the "NTLM " prefix
this._responseActions.push(str => {
this._actionAUTH_NTLM_TYPE3(str, callback);
});
SMTPConnection.prototype._actionAUTH_NTLM_TYPE1 = function (str, callback) {
var challengeMatch = str.match(/^334\s+(.+)$/);
var challengeString = '';
if (!challengeMatch) {
return callback(this._formatError('Invalid login sequence while waiting for server challenge string', 'EAUTH', str, 'AUTH NTLM'));
} else {
challengeString = challengeMatch[1];
}
if (!/^NTLM/i.test(challengeString)) {
challengeString = 'NTLM ' + challengeString;
}
var type2Message = ntlm.parseType2Message(challengeString, callback);
if (!type2Message) {
return;
}
var type3Message = ntlm.createType3Message(type2Message, {
domain: this._auth.domain || '',
workstation: this._auth.workstation || '',
username: this._auth.user,
password: this._auth.pass
});
type3Message = type3Message.substring(5); // remove the "NTLM " prefix
this._responseActions.push(function (str) {
this._actionAUTH_NTLM_TYPE3(str, callback);
}.bind(this));
if (!domain) {
parsedParameters = parseParametersFromUsername(username) || {};
username = parsedParameters.username;
domain = parsedParameters.domain;
}
if (state === STATES.INITIALIZED) {
// Nothing to do if the server does not ask us for auth in the first place.
if (!(response.headers.has(WWW_AUTHENTICATE, NTLM) ||
response.headers.has(WWW_AUTHENTICATE, NEGOTIATE))) {
return done(null, true);
}
// Create a type 1 message to send to the server
negotiateMessage = ntlmUtil.createType1Message({
domain: domain,
workstation: workstation
});
// Add the type 1 message as the auth header
auth.set(NTLM_HEADER, negotiateMessage);
// Update the state
auth.set(STATE, STATES.T1_MSG_CREATED);
// ask runtime to replay the request
return done(null, false);
}
else if (state === STATES.T1_MSG_CREATED) {
// At this point, we can assume that the type 1 message was sent to the server
ntlmType2Header = response.headers.find(function (header) {
return String(header.key).toLowerCase() === WWW_AUTHENTICATE &&
header.valueOf().startsWith('NTLM ');
});
if (!ntlmType2Header) {
return done(new Error('ntlm: server did not send NTLM type 2 message'));
}
challengeMessage = ntlmUtil.parseType2Message(ntlmType2Header.valueOf(), _.noop);
if (!challengeMessage) {
return done(new Error('ntlm: server did not correctly process authentication request'));
}
authenticateMessage = ntlmUtil.createType3Message(challengeMessage, {
domain: domain,
workstation: workstation,
username: username,
password: password
});
// Now create the type 3 message, and add it to the request
auth.set(NTLM_HEADER, authenticateMessage);
auth.set(STATE, STATES.T3_MSG_CREATED);
// ask runtime to replay the request
return done(null, false);
}
else if (state === STATES.T3_MSG_CREATED) {
// Means we have tried to authenticate, so we should stop here without worrying about anything
return done(null, true);
else if (state === STATES.T1_MSG_CREATED) {
// At this point, we can assume that the type 1 message was sent to the server
// there can be multiple headers present with key `www-authenticate`.
// iterate to get the one which has the NTLM hash. if multiple
// headers have the NTLM hash, use the first one.
ntlmType2Header = response.headers.find(function (header) {
return String(header.key).toLowerCase() === WWW_AUTHENTICATE &&
header.valueOf().startsWith('NTLM ');
});
if (!ntlmType2Header) {
return done(new Error('ntlm: server did not send NTLM type 2 message'));
}
challengeMessage = ntlmUtil.parseType2Message(ntlmType2Header.valueOf(), _.noop);
if (!challengeMessage) {
return done(new Error('ntlm: server did not correctly process authentication request'));
}
authenticateMessage = ntlmUtil.createType3Message(challengeMessage, {
domain: domain,
workstation: workstation,
username: username,
password: password
});
// Now create the type 3 message, and add it to the request
auth.set(NTLM_HEADER, authenticateMessage);
auth.set(STATE, STATES.T3_MSG_CREATED);
//this._auth.user+'\u0000'+
'\u0000' + // skip authorization identity as it causes problems with some servers
this._auth.user + '\u0000' +
this._auth.pass, 'utf-8').toString('base64'));
return;
case 'CRAM-MD5':
this._responseActions.push(function (str) {
this._actionAUTH_CRAM_MD5(str, callback);
}.bind(this));
this._sendCommand('AUTH CRAM-MD5');
return;
case 'NTLM':
this._responseActions.push(function (str) {
this._actionAUTH_NTLM_TYPE1(str, callback);
}.bind(this));
this._sendCommand('AUTH ' + ntlm.createType1Message({
domain: this._auth.domain || '',
workstation: this._auth.workstation || ''
}));
return;
}
return callback(this._formatError('Unknown authentication method "' + this._authMethod + '"', 'EAUTH', false, 'API'));
};