Skip to content

Commit

Permalink
fix(auth): handle qop="auth-int, auth" header
Browse files Browse the repository at this point in the history
  • Loading branch information
madhavilosetty-intel committed Nov 10, 2022
1 parent fcc823d commit ce8ddb2
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 14 deletions.
24 changes: 14 additions & 10 deletions src/amt/HttpHandler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import { logger, messages } from '../logging'
import { createHash } from 'crypto'
import * as xml2js from 'xml2js'
import { Common } from '@open-amt-cloud-toolkit/wsman-messages'
import { DigestChallenge } from '@open-amt-cloud-toolkit/wsman-messages/models/common'

export class connectionParams {
port: number
Expand All @@ -16,7 +16,7 @@ export class connectionParams {
nonce?: string
nonceCounter?: number
consoleNonce?: string
digestChallenge?: Common.Models.DigestChallenge
digestChallenge?: DigestChallenge
}

export class HttpHandler {
Expand Down Expand Up @@ -92,14 +92,18 @@ export class HttpHandler {
return `Digest ${paramNames.reduce((s1, ii) => `${s1},${ii}="${params[ii]}"`, '').substring(1)}`
}

parseAuthenticateResponseHeader = (value: string): Common.Models.DigestChallenge => {
const params = value.replace('Digest realm', 'realm').split(',')
const challengeParams = params.reduce((obj: any, s: string) => {
const parts = s.split('=')
obj[parts[0].trim()] = parts[1].replace(/"/g, '')
return obj
}, {})
return challengeParams
parseAuthenticateResponseHeader = (value: string): DigestChallenge => {
const params = value.replace('Digest realm', 'realm').split(/([^=,]*)=("[^"]*"|[^,"]*)/)
const obj: DigestChallenge = {}
for (let idx = 0; idx < params.length; idx = idx + 3) {
if (params[idx + 1] != null) {
obj[params[idx + 1].trim()] = params[idx + 2].replace(/"/g, '')
}
}
if (obj.qop != null) {
obj.qop = 'auth'
}
return obj
}

parseXML (xmlBody: string): any {
Expand Down
57 changes: 53 additions & 4 deletions src/amt/httpHandler.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
* SPDX-License-Identifier: Apache-2.0
**********************************************************************/

import { CIM, Common } from '@open-amt-cloud-toolkit/wsman-messages'
import { CIM } from '@open-amt-cloud-toolkit/wsman-messages'
import { DigestChallenge } from '@open-amt-cloud-toolkit/wsman-messages/models/common'
import { connectionParams, HttpHandler } from './HttpHandler'

const httpHandler = new HttpHandler()
Expand All @@ -18,17 +19,65 @@ it('should throw an error and return null when it parse invalid xml', async () =
const result = httpHandler.parseXML(xml)
expect(result).toBe(null)
})
it('should parse authentication response header', async () => {
it('should parse authentication response header with 1 comma in value', async () => {
const digestChallenge = {
realm: 'Digest:56ABC7BE224EF620C69EB88F01071DC8',
nonce: 'fVNueyEAAAAAAAAAcO8WqJ8s+WdyFUIY',
stale: 'false',
qop: 'auth'
}
const value: string = 'Digest realm="Digest:56ABC7BE224EF620C69EB88F01071DC8", nonce="fVNueyEAAAAAAAAAcO8WqJ8s+WdyFUIY",stale="false",qop="auth"'
const result: Common.Models.DigestChallenge = httpHandler.parseAuthenticateResponseHeader(value)
const value: string = 'Digest realm="Digest:56ABC7BE224EF620C69EB88F01071DC8", nonce="fVNueyEAAAAAAAAAcO8WqJ8s+WdyFUIY",stale="false",qop="auth-int, auth"'
const result: DigestChallenge = httpHandler.parseAuthenticateResponseHeader(value)
expect(JSON.stringify(result)).toBe(JSON.stringify(digestChallenge))
})

it('should parse authentication response header with 2 commas in value', async () => {
const digestChallenge = {
realm: 'Digest:56ABC7BE224EF620C69EB88F01071DC8',
nonce: 'fVNueyEAAAAAAAAAcO8WqJ8s+WdyFUIY',
stale: 'false',
qop: 'auth'
}
const value: string = 'Digest realm="Digest:56ABC7BE224EF620C69EB88F01071DC8", nonce="fVNueyEAAAAAAAAAcO8WqJ8s+WdyFUIY",stale="false",qop="auth-int, auth, hot-mess"'
const result: DigestChallenge = httpHandler.parseAuthenticateResponseHeader(value)
expect(JSON.stringify(result)).toBe(JSON.stringify(digestChallenge))
})
it('should parse authentication response header with no value', async () => {
const digestChallenge = {
realm: 'Digest:56ABC7BE224EF620C69EB88F01071DC8',
nonce: 'fVNueyEAAAAAAAAAcO8WqJ8s+WdyFUIY',
stale: 'false',
qop: 'auth'
}
const value: string = 'Digest realm="Digest:56ABC7BE224EF620C69EB88F01071DC8", nonce="fVNueyEAAAAAAAAAcO8WqJ8s+WdyFUIY",stale="false",qop=""'
const result: DigestChallenge = httpHandler.parseAuthenticateResponseHeader(value)
expect(JSON.stringify(result)).toBe(JSON.stringify(digestChallenge))
})

it('should parse authentication response header with rogue comma', async () => {
const digestChallenge = {
realm: 'Digest:56ABC7BE224EF620C69EB88F01071DC8',
nonce: 'fVNueyEAAAAAAAAAcO8WqJ8s+WdyFUIY',
stale: 'false',
qop: 'auth'
}
const value: string = 'Digest realm="Digest:56ABC7BE224EF620C69EB88F01071DC8", nonce="fVNueyEAAAAAAAAAcO8WqJ8s+WdyFUIY",stale="false",qop="auth",'
const result: DigestChallenge = httpHandler.parseAuthenticateResponseHeader(value)
expect(JSON.stringify(result)).toBe(JSON.stringify(digestChallenge))
})

it('should parse authentication response header with rogue double comma', async () => {
const digestChallenge = {
realm: 'Digest:56ABC7BE224EF620C69EB88F01071DC8',
nonce: 'fVNueyEAAAAAAAAAcO8WqJ8s+WdyFUIY',
stale: 'false',
qop: 'auth'
}
const value: string = 'Digest realm="Digest:56ABC7BE224EF620C69EB88F01071DC8", nonce="fVNueyEAAAAAAAAAcO8WqJ8s+WdyFUIY",stale="false",,qop="auth",'
const result: DigestChallenge = httpHandler.parseAuthenticateResponseHeader(value)
expect(JSON.stringify(result)).toBe(JSON.stringify(digestChallenge))
})

it('should return a WSMan request', async () => {
const cim = new CIM.Messages()
const xmlRequestBody = cim.ServiceAvailableToElement(CIM.Methods.ENUMERATE, '1')
Expand Down

0 comments on commit ce8ddb2

Please sign in to comment.