@mcp-abap-adt/connection 1.9.0 → 1.9.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detect whether a WWW-Authenticate header (or a Negotiate challenge token) indicates NTLM.
|
|
3
|
+
* NTLM is rejected: only Kerberos/SPNEGO Negotiate is acceptable.
|
|
4
|
+
*
|
|
5
|
+
* Two cases:
|
|
6
|
+
* - the header offers the NTLM scheme directly: `WWW-Authenticate: NTLM`
|
|
7
|
+
* - an NTLM token tunneled via Negotiate: `Negotiate <base64>` where the base64 decodes to
|
|
8
|
+
* bytes starting with the NTLM signature "NTLMSSP\0" (base64 prefix "TlRMTVNTUAA").
|
|
9
|
+
*/
|
|
10
|
+
export declare function isNtlmChallenge(wwwAuthenticate: string | undefined): boolean;
|
|
11
|
+
//# sourceMappingURL=ntlm.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ntlm.d.ts","sourceRoot":"","sources":["../../src/auth/ntlm.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,eAAe,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAiB5E"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isNtlmChallenge = isNtlmChallenge;
|
|
4
|
+
/**
|
|
5
|
+
* Detect whether a WWW-Authenticate header (or a Negotiate challenge token) indicates NTLM.
|
|
6
|
+
* NTLM is rejected: only Kerberos/SPNEGO Negotiate is acceptable.
|
|
7
|
+
*
|
|
8
|
+
* Two cases:
|
|
9
|
+
* - the header offers the NTLM scheme directly: `WWW-Authenticate: NTLM`
|
|
10
|
+
* - an NTLM token tunneled via Negotiate: `Negotiate <base64>` where the base64 decodes to
|
|
11
|
+
* bytes starting with the NTLM signature "NTLMSSP\0" (base64 prefix "TlRMTVNTUAA").
|
|
12
|
+
*/
|
|
13
|
+
function isNtlmChallenge(wwwAuthenticate) {
|
|
14
|
+
if (!wwwAuthenticate)
|
|
15
|
+
return false;
|
|
16
|
+
const value = wwwAuthenticate.trim();
|
|
17
|
+
if (!value)
|
|
18
|
+
return false;
|
|
19
|
+
// Split on commas to handle multiple offered schemes, e.g. "Negotiate, NTLM"
|
|
20
|
+
const parts = value.split(',').map((p) => p.trim());
|
|
21
|
+
for (const part of parts) {
|
|
22
|
+
const lower = part.toLowerCase();
|
|
23
|
+
// direct NTLM scheme offer (word-boundary, not e.g. "Negotiate")
|
|
24
|
+
if (/^ntlm\b/i.test(part))
|
|
25
|
+
return true;
|
|
26
|
+
// NTLM tunneled inside a Negotiate token
|
|
27
|
+
if (lower.startsWith('negotiate ')) {
|
|
28
|
+
const token = part.slice('negotiate '.length).trim();
|
|
29
|
+
if (token.startsWith('TlRMTVNTUAA'))
|
|
30
|
+
return true; // base64("NTLMSSP\0")
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"KerberosAbapConnection.d.ts","sourceRoot":"","sources":["../../src/connection/KerberosAbapConnection.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"KerberosAbapConnection.d.ts","sourceRoot":"","sources":["../../src/connection/KerberosAbapConnection.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,sBAAsB,EAAE,MAAM,6BAA6B,CAAC;AAErE,uGAAuG;AACvG,qBAAa,sBAAuB,SAAQ,sBAAsB;IAChE,OAAO,CAAC,GAAG,CAAS;IACpB,OAAO,CAAC,YAAY,CAAM;gBAEd,MAAM,EAAE,SAAS,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,EAAE,SAAS,CAAC,EAAE,MAAM;IAQ1E,OAAO,CAAC,MAAM,CAAC,cAAc;IAa7B,mDAAmD;cACnC,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAK5C;;;;OAIG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAiC9B,SAAS,CAAC,wBAAwB,IAAI,MAAM;CAS7C"}
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.KerberosAbapConnection = void 0;
|
|
4
4
|
const axios_1 = require("axios");
|
|
5
5
|
const kerberosSpnego_js_1 = require("../auth/kerberosSpnego.js");
|
|
6
|
+
const ntlm_js_1 = require("../auth/ntlm.js");
|
|
6
7
|
const AbstractAbapConnection_js_1 = require("./AbstractAbapConnection.js");
|
|
7
8
|
/** Kerberos / SPNEGO single-leg auth: send Negotiate token, reuse the resulting SAP session cookie. */
|
|
8
9
|
class KerberosAbapConnection extends AbstractAbapConnection_js_1.AbstractAbapConnection {
|
|
@@ -43,12 +44,17 @@ class KerberosAbapConnection extends AbstractAbapConnection_js_1.AbstractAbapCon
|
|
|
43
44
|
this.setCsrfToken(token);
|
|
44
45
|
}
|
|
45
46
|
catch (error) {
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
47
|
+
if (error instanceof axios_1.AxiosError && error.response?.headers) {
|
|
48
|
+
const wwwAuth = error.response.headers['www-authenticate'];
|
|
49
|
+
if ((0, ntlm_js_1.isNtlmChallenge)(wwwAuth)) {
|
|
50
|
+
throw new Error('KerberosAbapConnection: server offered NTLM authentication, which is rejected. ' +
|
|
51
|
+
'Only Kerberos/SPNEGO is supported. Ensure the SAP system accepts Kerberos (SPNEGO) for your user.');
|
|
52
|
+
}
|
|
53
|
+
if (this.getCookies()) {
|
|
54
|
+
this.logger?.debug('[DEBUG] KerberosAbapConnection - cookies captured from error response during connect');
|
|
55
|
+
}
|
|
51
56
|
}
|
|
57
|
+
this.logger?.warn(`[WARN] KerberosAbapConnection - connect deferred: ${error instanceof Error ? error.message : String(error)}`);
|
|
52
58
|
}
|
|
53
59
|
}
|
|
54
60
|
buildAuthorizationHeader() {
|