mirror of
https://github.com/Ylianst/MeshAgent
synced 2025-12-11 05:43:33 +00:00
Fixed parsing bug of digest authenticate headers when multiple qop options are present. Added support for auth-int on the client side.
This commit is contained in:
@@ -2726,13 +2726,20 @@ duk_ret_t ILibDuktape_HttpStream_ServerResponse_Digest_SendUnauthorized(duk_cont
|
|||||||
char *realm;
|
char *realm;
|
||||||
duk_size_t realmLen, htmlLen = 0;
|
duk_size_t realmLen, htmlLen = 0;
|
||||||
void *hptr;
|
void *hptr;
|
||||||
|
char *qop = NULL;
|
||||||
|
|
||||||
|
if (!duk_is_null_or_undefined(ctx, 1) && duk_is_object(ctx, 1))
|
||||||
|
{
|
||||||
|
// Options Object is present
|
||||||
|
qop = Duktape_GetStringPropertyValue(ctx, 1, "qop", NULL);
|
||||||
|
if (qop != NULL) { duk_push_sprintf(ctx, ", qop=\"%s\"", qop); qop = (char*)duk_get_string(ctx, -1); }
|
||||||
|
}
|
||||||
|
|
||||||
if (nargs > 0)
|
if (nargs > 0)
|
||||||
{
|
{
|
||||||
duk_get_lstring(ctx, 1, &htmlLen);
|
duk_get_lstring(ctx, 1, &htmlLen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
duk_push_this(ctx); // [serverResponse]
|
duk_push_this(ctx); // [serverResponse]
|
||||||
duk_get_prop_string(ctx, -1, ILibDuktape_SR2HttpStream); // [serverResponse][httpStream]
|
duk_get_prop_string(ctx, -1, ILibDuktape_SR2HttpStream); // [serverResponse][httpStream]
|
||||||
duk_get_prop_string(ctx, -1, ILibDuktape_HTTPStream2HTTP); // [serverResponse][httpStream][http]
|
duk_get_prop_string(ctx, -1, ILibDuktape_HTTPStream2HTTP); // [serverResponse][httpStream][http]
|
||||||
@@ -2749,7 +2756,7 @@ duk_ret_t ILibDuktape_HttpStream_ServerResponse_Digest_SendUnauthorized(duk_cont
|
|||||||
duk_push_string(ctx, "Unauthorized"); // [writeHead][this][401][Unauthorized]
|
duk_push_string(ctx, "Unauthorized"); // [writeHead][this][401][Unauthorized]
|
||||||
duk_push_object(ctx); // [writeHead][this][401][Unauthorized][headers]
|
duk_push_object(ctx); // [writeHead][this][401][Unauthorized][headers]
|
||||||
duk_push_string(ctx, "WWW-Authenticate"); // [writeHead][this][401][Unauthorized][headers][name]
|
duk_push_string(ctx, "WWW-Authenticate"); // [writeHead][this][401][Unauthorized][headers][name]
|
||||||
int wwwLen = sprintf_s(ILibScratchPad, sizeof(ILibScratchPad), "Digest realm=\"%s\", nonce=\"%s\", opaque=\"%s\"", realm, nonce, opaque);
|
int wwwLen = sprintf_s(ILibScratchPad, sizeof(ILibScratchPad), "Digest realm=\"%s\", nonce=\"%s\", opaque=\"%s\"%s", realm, nonce, opaque, qop == NULL ? "" : qop);
|
||||||
duk_push_lstring(ctx, ILibScratchPad, wwwLen); // [writeHead][this][401][Unauthorized][headers][name][value]
|
duk_push_lstring(ctx, ILibScratchPad, wwwLen); // [writeHead][this][401][Unauthorized][headers][name][value]
|
||||||
duk_put_prop(ctx, -3); // [writeHead][this][401][Unauthorized][headers]
|
duk_put_prop(ctx, -3); // [writeHead][this][401][Unauthorized][headers]
|
||||||
if (htmlLen > 0)
|
if (htmlLen > 0)
|
||||||
@@ -2930,9 +2937,9 @@ duk_ret_t ILibDuktape_HttpStream_IncomingMessage_Digest_ValidatePassword(duk_con
|
|||||||
|
|
||||||
MD5_CTX mctx;
|
MD5_CTX mctx;
|
||||||
|
|
||||||
char *auth, *username, *password, *opaque, *response, *uri, *realm, *method;
|
char *auth, *username, *password, *opaque, *response, *uri, *realm, *method, *qop, *nc, *cnonce;
|
||||||
duk_size_t authLen, passwordLen, methodLen;
|
duk_size_t authLen, passwordLen, methodLen;
|
||||||
int usernameLen, opaqueLen, responseLen, uriLen, realmLen;
|
int usernameLen, opaqueLen, responseLen, uriLen, realmLen, qopLen, ncLen, cnonceLen;
|
||||||
|
|
||||||
void *DigestTable = ILibInitHashTree_CaseInSensitiveEx(ILibMemory_AllocateA(8000));
|
void *DigestTable = ILibInitHashTree_CaseInSensitiveEx(ILibMemory_AllocateA(8000));
|
||||||
void *hptr;
|
void *hptr;
|
||||||
@@ -2958,6 +2965,11 @@ duk_ret_t ILibDuktape_HttpStream_IncomingMessage_Digest_ValidatePassword(duk_con
|
|||||||
ILibGetEntryEx(DigestTable, "uri", 3, (void**)&uri, &uriLen);
|
ILibGetEntryEx(DigestTable, "uri", 3, (void**)&uri, &uriLen);
|
||||||
ILibGetEntryEx(DigestTable, "response", 8, (void**)&response, &responseLen);
|
ILibGetEntryEx(DigestTable, "response", 8, (void**)&response, &responseLen);
|
||||||
ILibGetEntryEx(DigestTable, "opaque", 6, (void**)&opaque, &opaqueLen);
|
ILibGetEntryEx(DigestTable, "opaque", 6, (void**)&opaque, &opaqueLen);
|
||||||
|
ILibGetEntryEx(DigestTable, "qop", 3, (void**)&qop, &qopLen);
|
||||||
|
ILibGetEntryEx(DigestTable, "nc", 2, (void**)&nc, &ncLen);
|
||||||
|
ILibGetEntryEx(DigestTable, "cnonce", 6, (void**)&cnonce, &cnonceLen);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if (username == NULL || uri == NULL || password == NULL || passwordLen == 0 || response == NULL || opaqueLen != 16)
|
if (username == NULL || uri == NULL || password == NULL || passwordLen == 0 || response == NULL || opaqueLen != 16)
|
||||||
{
|
{
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -42,7 +42,7 @@ function generateAuthHeaders(imsg, options, digest)
|
|||||||
{
|
{
|
||||||
auth = { realm: null, nonce: null, opaque: null, qop: null };
|
auth = { realm: null, nonce: null, opaque: null, qop: null };
|
||||||
var www = imsg.headers['WWW-Authenticate'];
|
var www = imsg.headers['WWW-Authenticate'];
|
||||||
var tokens = www.split(',');
|
var tokens = www.splitEx(',');
|
||||||
|
|
||||||
var pairs;
|
var pairs;
|
||||||
for (var i in tokens)
|
for (var i in tokens)
|
||||||
@@ -65,8 +65,13 @@ function generateAuthHeaders(imsg, options, digest)
|
|||||||
if (auth.opaque[0] == '"') { auth.opaque = auth.opaque.substring(1, auth.opaque.length - 1); }
|
if (auth.opaque[0] == '"') { auth.opaque = auth.opaque.substring(1, auth.opaque.length - 1); }
|
||||||
break;
|
break;
|
||||||
case 'qop':
|
case 'qop':
|
||||||
auth.qop = pairs[1];
|
var qop = pairs[1];
|
||||||
if (auth.qop[0] == '"') { auth.qop = auth.qop.substring(1, auth.qop.length - 1); }
|
if (qop[0] == '"') { qop = qop.substring(1, qop.length - 1); }
|
||||||
|
qop = qop.split(' ').join('').split(',');
|
||||||
|
if (options.qop != null) { auth.qop = qop.includes(options.qop) ? options.qop : null; }
|
||||||
|
else if (qop.includes('auth-int')) { auth.qop = 'auth-int'; }
|
||||||
|
else if (qop.includes('auth')) { auth.qop = 'auth'; }
|
||||||
|
console.log('QOP', auth.qop);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -78,13 +83,15 @@ function generateAuthHeaders(imsg, options, digest)
|
|||||||
if (!(auth = digest._auth)) { return; }
|
if (!(auth = digest._auth)) { return; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (digest._auth.qop == 'auth-int' && options.oneshotEntity == null) { return; } // For auth-int, we need to hash the entity body, so if we don't have it, we must return
|
||||||
|
|
||||||
var step1 = digest._options.username + ':' + auth.realm + ':' + digest._options.password;
|
var step1 = digest._options.username + ':' + auth.realm + ':' + digest._options.password;
|
||||||
auth.step1 = md5.syncHash(step1).toString('hex').toLowerCase();
|
auth.step1 = md5.syncHash(step1).toString('hex').toLowerCase();
|
||||||
|
|
||||||
var step2 = options.method + ':' + options.path;
|
var step2 = options.method + ':' + options.path;
|
||||||
|
if (qop == 'auth-int' && options.oneshotEntity != null) { step2 += (':' + md5.syncHash(options.oneshotEntity).toString('hex').toLowerCase()); }
|
||||||
auth.step2 = md5.syncHash(step2).toString('hex').toLowerCase();
|
auth.step2 = md5.syncHash(step2).toString('hex').toLowerCase();
|
||||||
|
|
||||||
|
|
||||||
if (auth.qop == null)
|
if (auth.qop == null)
|
||||||
{
|
{
|
||||||
var step3 = auth.step1 + ':' + auth.nonce + ':' + auth.step2;
|
var step3 = auth.step1 + ':' + auth.nonce + ':' + auth.step2;
|
||||||
@@ -245,6 +252,7 @@ function http_digest_instance(options)
|
|||||||
console.info1('response status code => ' + imsg.statusCode);
|
console.info1('response status code => ' + imsg.statusCode);
|
||||||
if (imsg.statusCode == 401)
|
if (imsg.statusCode == 401)
|
||||||
{
|
{
|
||||||
|
if (this.digRequest._buffered && this.digRequest._ended) { this.digRequest.options.oneshotEntity = this.digRequest._buffered; }
|
||||||
var callend = this.digRequest._request._callend;
|
var callend = this.digRequest._request._callend;
|
||||||
var auth = generateAuthHeaders(imsg, this.digRequest.options, this.digRequest._digest);
|
var auth = generateAuthHeaders(imsg, this.digRequest.options, this.digRequest._digest);
|
||||||
console.info1(JSON.stringify(auth, null, 1));
|
console.info1(JSON.stringify(auth, null, 1));
|
||||||
|
|||||||
Reference in New Issue
Block a user