You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
111 lines
2.4 KiB
111 lines
2.4 KiB
var createHash = require('crypto').createHash; |
|
|
|
function get_header(header, credentials, opts) { |
|
var type = header.split(' ')[0], |
|
user = credentials[0], |
|
pass = credentials[1]; |
|
|
|
if (type == 'Digest') { |
|
return digest.generate(header, user, pass, opts.method, opts.path); |
|
} else if (type == 'Basic') { |
|
return basic(user, pass); |
|
} |
|
} |
|
|
|
//////////////////// |
|
// basic |
|
|
|
function md5(string) { |
|
return createHash('md5').update(string).digest('hex'); |
|
} |
|
|
|
function basic(user, pass) { |
|
var str = typeof pass == 'undefined' ? user : [user, pass].join(':'); |
|
return 'Basic ' + Buffer.from(str).toString('base64'); |
|
} |
|
|
|
//////////////////// |
|
// digest |
|
// logic inspired from https://github.com/simme/node-http-digest-client |
|
|
|
var digest = {}; |
|
|
|
digest.parse_header = function(header) { |
|
var challenge = {}, |
|
matches = header.match(/([a-z0-9_-]+)="?([a-z0-9_=\/\.@\s-\+:)()]+)"?/gi); |
|
|
|
for (var i = 0, l = matches.length; i < l; i++) { |
|
var parts = matches[i].split('='), |
|
key = parts.shift(), |
|
val = parts.join('=').replace(/^"/, '').replace(/"$/, ''); |
|
|
|
challenge[key] = val; |
|
} |
|
|
|
return challenge; |
|
} |
|
|
|
digest.update_nc = function(nc) { |
|
var max = 99999999; |
|
nc++; |
|
|
|
if (nc > max) |
|
nc = 1; |
|
|
|
var padding = new Array(8).join('0') + ''; |
|
nc = nc + ''; |
|
return padding.substr(0, 8 - nc.length) + nc; |
|
} |
|
|
|
digest.generate = function(header, user, pass, method, path) { |
|
|
|
var nc = 1, |
|
cnonce = null, |
|
challenge = digest.parse_header(header); |
|
|
|
var ha1 = md5(user + ':' + challenge.realm + ':' + pass), |
|
ha2 = md5(method.toUpperCase() + ':' + path), |
|
resp = [ha1, challenge.nonce]; |
|
|
|
if (typeof challenge.qop === 'string') { |
|
cnonce = md5(Math.random().toString(36)).substr(0, 8); |
|
nc = digest.update_nc(nc); |
|
resp = resp.concat(nc, cnonce); |
|
resp = resp.concat(challenge.qop, ha2); |
|
} else { |
|
resp = resp.concat(ha2); |
|
} |
|
|
|
var params = { |
|
uri : path, |
|
realm : challenge.realm, |
|
nonce : challenge.nonce, |
|
username : user, |
|
response : md5(resp.join(':')) |
|
} |
|
|
|
if (challenge.qop) { |
|
params.qop = challenge.qop; |
|
} |
|
|
|
if (challenge.opaque) { |
|
params.opaque = challenge.opaque; |
|
} |
|
|
|
if (cnonce) { |
|
params.nc = nc; |
|
params.cnonce = cnonce; |
|
} |
|
|
|
header = [] |
|
for (var k in params) |
|
header.push(k + '="' + params[k] + '"') |
|
|
|
return 'Digest ' + header.join(', '); |
|
} |
|
|
|
module.exports = { |
|
header : get_header, |
|
basic : basic, |
|
digest : digest.generate |
|
}
|
|
|