1
0
mirror of https://github.com/bitwarden/directory-connector synced 2025-12-05 23:53:21 +00:00

Compare commits

...

3 Commits

Author SHA1 Message Date
Thomas Rittson
01e894b5bc uninstall ldapjs 2024-09-30 11:14:02 +10:00
Thomas Rittson
aa5a9f3e2f Initial implementation of ldapts 2024-09-30 11:13:16 +10:00
Thomas Rittson
f4181b13f7 Install ldapts 2024-09-30 09:54:04 +10:00
3 changed files with 183 additions and 243 deletions

183
package-lock.json generated
View File

@@ -32,7 +32,7 @@
"https-proxy-agent": "7.0.4",
"inquirer": "8.2.6",
"keytar": "7.9.0",
"ldapjs": "2.3.3",
"ldapts": "7.2.0",
"lowdb": "1.0.0",
"ngx-toastr": "16.2.0",
"node-fetch": "2.7.0",
@@ -53,7 +53,6 @@
"@ngtools/webpack": "16.2.12",
"@types/inquirer": "8.2.10",
"@types/jest": "29.5.11",
"@types/ldapjs": "2.2.5",
"@types/lowdb": "1.0.15",
"@types/node": "18.19.50",
"@types/node-fetch": "2.6.11",
@@ -4652,6 +4651,14 @@
"node": ">= 10"
}
},
"node_modules/@types/asn1": {
"version": "0.2.4",
"resolved": "https://registry.npmjs.org/@types/asn1/-/asn1-0.2.4.tgz",
"integrity": "sha512-V91DSJ2l0h0gRhVP4oBfBzRBN9lAbPUkGDMCnwedqPKX2d84aAMc9CulOvxdw1f7DfEYx99afab+Rsm3e52jhA==",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/babel__core": {
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
@@ -4934,15 +4941,6 @@
"@types/node": "*"
}
},
"node_modules/@types/ldapjs": {
"version": "2.2.5",
"resolved": "https://registry.npmjs.org/@types/ldapjs/-/ldapjs-2.2.5.tgz",
"integrity": "sha512-Lv/nD6QDCmcT+V1vaTRnEKE8UgOilVv5pHcQuzkU1LcRe4mbHHuUo/KHi0LKrpdHhQY8FJzryF38fcVdeUIrzg==",
"dev": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/lodash": {
"version": "4.14.202",
"resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.202.tgz",
@@ -4980,7 +4978,6 @@
"version": "18.19.50",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.50.tgz",
"integrity": "sha512-xonK+NRrMBRtkL1hVCc3G+uXtjh1Al4opBLjqVmipe5ZAaBYWW6cNAiBVZ1BvmkBhep698rP3UM3aRAdSALuhg==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~5.26.4"
@@ -5940,11 +5937,6 @@
"node": ">=6.5"
}
},
"node_modules/abstract-logging": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/abstract-logging/-/abstract-logging-2.0.1.tgz",
"integrity": "sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA=="
},
"node_modules/accepts": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
@@ -6520,6 +6512,8 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
"dev": true,
"optional": true,
"engines": {
"node": ">=0.8"
}
@@ -6803,17 +6797,6 @@
"@babel/core": "^7.0.0"
}
},
"node_modules/backoff": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/backoff/-/backoff-2.5.0.tgz",
"integrity": "sha512-wC5ihrnUXmR2douXmXLCe5O3zg3GKIyvRi/hi58a/XyRxVI+3/yM0PYueQOZXPXQ9pxBislYkw+sF9b7C/RuMA==",
"dependencies": {
"precond": "0.2"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -8237,7 +8220,8 @@
"node_modules/core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ=="
"integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==",
"dev": true
},
"node_modules/cosmiconfig": {
"version": "8.3.6",
@@ -8574,12 +8558,11 @@
}
},
"node_modules/debug": {
"version": "4.3.6",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz",
"integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==",
"license": "MIT",
"version": "4.3.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
"integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
"dependencies": {
"ms": "2.1.2"
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
@@ -10628,9 +10611,11 @@
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz",
"integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==",
"dev": true,
"engines": [
"node >=0.6.0"
]
],
"optional": true
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
@@ -14238,33 +14223,71 @@
"integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==",
"dev": true
},
"node_modules/ldap-filter": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/ldap-filter/-/ldap-filter-0.3.3.tgz",
"integrity": "sha512-/tFkx5WIn4HuO+6w9lsfxq4FN3O+fDZeO9Mek8dCD8rTUpqzRa766BOBO7BcGkn3X86m5+cBm1/2S/Shzz7gMg==",
"node_modules/ldapts": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/ldapts/-/ldapts-7.2.0.tgz",
"integrity": "sha512-jFo3JI46nveXgILcEhUxR7N9it9d6gIooGAaem5OdXbXFjb6kIGdtI6FE2Y6SnT+XRvZvHy3diM5sdWzMsMK5w==",
"dependencies": {
"assert-plus": "^1.0.0"
"@types/asn1": ">=0.2.4",
"asn1": "~0.2.6",
"debug": "~4.3.7",
"strict-event-emitter-types": "~2.0.0",
"uuid": "~10.0.0",
"whatwg-url": "~14.0.0"
},
"engines": {
"node": ">=0.8"
"node": ">=18"
}
},
"node_modules/ldapjs": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/ldapjs/-/ldapjs-2.3.3.tgz",
"integrity": "sha512-75QiiLJV/PQqtpH+HGls44dXweviFwQ6SiIK27EqzKQ5jU/7UFrl2E5nLdQ3IYRBzJ/AVFJI66u0MZ0uofKYwg==",
"node_modules/ldapts/node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
"engines": {
"node": ">=6"
}
},
"node_modules/ldapts/node_modules/tr46": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-5.0.0.tgz",
"integrity": "sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==",
"dependencies": {
"abstract-logging": "^2.0.0",
"asn1": "^0.2.4",
"assert-plus": "^1.0.0",
"backoff": "^2.5.0",
"ldap-filter": "^0.3.3",
"once": "^1.4.0",
"vasync": "^2.2.0",
"verror": "^1.8.1"
"punycode": "^2.3.1"
},
"engines": {
"node": ">=10.13.0"
"node": ">=18"
}
},
"node_modules/ldapts/node_modules/uuid": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz",
"integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/ldapts/node_modules/webidl-conversions": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
"integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
"engines": {
"node": ">=12"
}
},
"node_modules/ldapts/node_modules/whatwg-url": {
"version": "14.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.0.0.tgz",
"integrity": "sha512-1lfMEm2IEr7RIV+f4lUNPOqfFL+pO+Xw3fJSqmjX9AbXcXcYOkCe1P6+9VBZB6n94af16NfZf+sSk0JCBZC9aw==",
"dependencies": {
"tr46": "^5.0.0",
"webidl-conversions": "^7.0.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/less": {
@@ -15499,9 +15522,9 @@
}
},
"node_modules/ms": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
"node_modules/multicast-dns": {
"version": "7.2.5",
@@ -17069,14 +17092,6 @@
"node": ">=10"
}
},
"node_modules/precond": {
"version": "0.2.3",
"resolved": "https://registry.npmjs.org/precond/-/precond-0.2.3.tgz",
"integrity": "sha512-QCYG84SgGyGzqJ/vlMsxeXd/pgL/I94ixdNFyh1PusWmTCyVfPJjZ1K1jvHtsbfnXQs2TSkEP2fR7QiMZAnKFQ==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
@@ -18340,12 +18355,6 @@
"node": ">=4"
}
},
"node_modules/send/node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true
},
"node_modules/serialize-error": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz",
@@ -18916,6 +18925,11 @@
"safe-buffer": "~5.1.0"
}
},
"node_modules/strict-event-emitter-types": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strict-event-emitter-types/-/strict-event-emitter-types-2.0.0.tgz",
"integrity": "sha512-Nk/brWYpD85WlOgzw5h173aci0Teyv8YdIAEtV+N88nDB0dLlazZyJMIsN6eo1/AR61l+p6CJTG1JIyFaoNEEA=="
},
"node_modules/string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
@@ -20027,7 +20041,6 @@
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
"dev": true,
"license": "MIT"
},
"node_modules/unicode-canonical-property-names-ecmascript": {
@@ -20250,34 +20263,12 @@
"node": ">= 0.8"
}
},
"node_modules/vasync": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/vasync/-/vasync-2.2.1.tgz",
"integrity": "sha512-Hq72JaTpcTFdWiNA4Y22Amej2GH3BFmBaKPPlDZ4/oC8HNn2ISHLkFrJU4Ds8R3jcUi7oo5Y9jcMHKjES+N9wQ==",
"engines": [
"node >=0.6.0"
],
"dependencies": {
"verror": "1.10.0"
}
},
"node_modules/vasync/node_modules/verror": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
"integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==",
"engines": [
"node >=0.6.0"
],
"dependencies": {
"assert-plus": "^1.0.0",
"core-util-is": "1.0.2",
"extsprintf": "^1.2.0"
}
},
"node_modules/verror": {
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz",
"integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==",
"dev": true,
"optional": true,
"dependencies": {
"assert-plus": "^1.0.0",
"core-util-is": "1.0.2",

View File

@@ -81,7 +81,6 @@
"@ngtools/webpack": "16.2.12",
"@types/inquirer": "8.2.10",
"@types/jest": "29.5.11",
"@types/ldapjs": "2.2.5",
"@types/lowdb": "1.0.15",
"@types/node": "18.19.50",
"@types/node-fetch": "2.6.11",
@@ -161,7 +160,7 @@
"https-proxy-agent": "7.0.4",
"inquirer": "8.2.6",
"keytar": "7.9.0",
"ldapjs": "2.3.3",
"ldapts": "7.2.0",
"lowdb": "1.0.0",
"ngx-toastr": "16.2.0",
"node-fetch": "2.7.0",

View File

@@ -1,7 +1,7 @@
import * as fs from "fs";
import { checkServerIdentity, PeerCertificate } from "tls";
import * as tls from "tls";
import * as ldap from "ldapjs";
import * as ldapts from "ldapts";
import { I18nService } from "@/jslib/common/src/abstractions/i18n.service";
import { LogService } from "@/jslib/common/src/abstractions/log.service";
@@ -19,7 +19,7 @@ import { IDirectoryService } from "./directory.service";
const UserControlAccountDisabled = 2;
export class LdapDirectoryService implements IDirectoryService {
private client: ldap.Client;
private client: ldapts.Client;
private dirConfig: LdapConfiguration;
private syncConfig: SyncConfiguration;
@@ -48,21 +48,25 @@ export class LdapDirectoryService implements IDirectoryService {
await this.bind();
let users: UserEntry[];
if (this.syncConfig.users) {
users = await this.getUsers(force, test);
}
let groups: GroupEntry[];
if (this.syncConfig.groups) {
let groupForce = force;
if (!groupForce && users != null) {
const activeUsers = users.filter((u) => !u.deleted && !u.disabled);
groupForce = activeUsers.length > 0;
try {
if (this.syncConfig.users) {
users = await this.getUsers(force, test);
}
groups = await this.getGroups(groupForce);
if (this.syncConfig.groups) {
let groupForce = force;
if (!groupForce && users != null) {
const activeUsers = users.filter((u) => !u.deleted && !u.disabled);
groupForce = activeUsers.length > 0;
}
groups = await this.getGroups(groupForce);
}
} finally {
await this.client.unbind();
}
await this.unbind();
return [groups, users];
}
@@ -101,10 +105,7 @@ export class LdapDirectoryService implements IDirectoryService {
const deletedPath = this.makeSearchPath("CN=Deleted Objects");
this.logService.info("Deleted user search: " + deletedPath + " => " + deletedFilter);
const delControl = new (ldap as any).Control({
type: "1.2.840.113556.1.4.417",
criticality: true,
});
const delControl = new ldapts.Control("1.2.840.113556.1.4.417", { critical: true });
const deletedUsers = await this.search<UserEntry>(
deletedPath,
deletedFilter,
@@ -334,144 +335,93 @@ export class LdapDirectoryService implements IDirectoryService {
path: string,
filter: string,
processEntry: (searchEntry: any) => T,
controls: ldap.Control[] = [],
controls: ldapts.Control[] = [],
): Promise<T[]> {
const options: ldap.SearchOptions = {
const options: ldapts.SearchOptions = {
filter: filter,
scope: "sub",
paged: this.dirConfig.pagedSearch,
};
const entries: T[] = [];
return new Promise<T[]>((resolve, reject) => {
this.client.search(path, options, controls, (err, res) => {
if (err != null) {
reject(err);
return;
}
res.on("error", (resErr) => {
reject(resErr);
});
res.on("searchEntry", (entry) => {
const e = processEntry(entry);
if (e != null) {
entries.push(e);
}
});
res.on("end", (result) => {
resolve(entries);
});
});
});
const { searchEntries } = await this.client.search(path, options, controls);
return searchEntries.map((e) => processEntry(e)).filter((e) => e != null);
}
private async bind(): Promise<any> {
return new Promise<void>((resolve, reject) => {
if (this.dirConfig.hostname == null || this.dirConfig.port == null) {
reject(this.i18nService.t("dirConfigIncomplete"));
return;
}
const protocol = "ldap" + (this.dirConfig.ssl && !this.dirConfig.startTls ? "s" : "");
const url = protocol + "://" + this.dirConfig.hostname + ":" + this.dirConfig.port;
const options: ldap.ClientOptions = {
url: url.trim().toLowerCase(),
};
if (this.dirConfig.hostname == null || this.dirConfig.port == null) {
throw new Error(this.i18nService.t("dirConfigIncomplete"));
}
const tlsOptions: any = {};
if (this.dirConfig.ssl) {
if (this.dirConfig.sslAllowUnauthorized) {
tlsOptions.rejectUnauthorized = !this.dirConfig.sslAllowUnauthorized;
const protocol = "ldap" + (this.dirConfig.ssl && !this.dirConfig.startTls ? "s" : "");
const url = protocol + "://" + this.dirConfig.hostname + ":" + this.dirConfig.port;
const options: ldapts.ClientOptions = {
url: url.trim().toLowerCase(),
};
const tlsOptions: tls.ConnectionOptions = {};
if (this.dirConfig.ssl) {
if (this.dirConfig.sslAllowUnauthorized) {
tlsOptions.rejectUnauthorized = !this.dirConfig.sslAllowUnauthorized;
}
if (!this.dirConfig.startTls) {
if (
this.dirConfig.sslCaPath != null &&
this.dirConfig.sslCaPath !== "" &&
fs.existsSync(this.dirConfig.sslCaPath)
) {
tlsOptions.ca = [fs.readFileSync(this.dirConfig.sslCaPath)];
}
if (!this.dirConfig.startTls) {
if (
this.dirConfig.sslCaPath != null &&
this.dirConfig.sslCaPath !== "" &&
fs.existsSync(this.dirConfig.sslCaPath)
) {
tlsOptions.ca = [fs.readFileSync(this.dirConfig.sslCaPath)];
}
if (
this.dirConfig.sslCertPath != null &&
this.dirConfig.sslCertPath !== "" &&
fs.existsSync(this.dirConfig.sslCertPath)
) {
tlsOptions.cert = fs.readFileSync(this.dirConfig.sslCertPath);
}
if (
this.dirConfig.sslKeyPath != null &&
this.dirConfig.sslKeyPath !== "" &&
fs.existsSync(this.dirConfig.sslKeyPath)
) {
tlsOptions.key = fs.readFileSync(this.dirConfig.sslKeyPath);
}
} else {
if (
this.dirConfig.tlsCaPath != null &&
this.dirConfig.tlsCaPath !== "" &&
fs.existsSync(this.dirConfig.tlsCaPath)
) {
tlsOptions.ca = [fs.readFileSync(this.dirConfig.tlsCaPath)];
}
if (
this.dirConfig.sslCertPath != null &&
this.dirConfig.sslCertPath !== "" &&
fs.existsSync(this.dirConfig.sslCertPath)
) {
tlsOptions.cert = fs.readFileSync(this.dirConfig.sslCertPath);
}
if (
this.dirConfig.sslKeyPath != null &&
this.dirConfig.sslKeyPath !== "" &&
fs.existsSync(this.dirConfig.sslKeyPath)
) {
tlsOptions.key = fs.readFileSync(this.dirConfig.sslKeyPath);
}
}
tlsOptions.checkServerIdentity = this.checkServerIdentityAltNames;
options.tlsOptions = tlsOptions;
this.client = ldap.createClient(options);
const user =
this.dirConfig.username == null || this.dirConfig.username.trim() === ""
? null
: this.dirConfig.username;
const pass =
this.dirConfig.password == null || this.dirConfig.password.trim() === ""
? null
: this.dirConfig.password;
if (user == null || pass == null) {
reject(this.i18nService.t("usernamePasswordNotConfigured"));
return;
}
if (this.dirConfig.startTls && this.dirConfig.ssl) {
this.client.starttls(options.tlsOptions, undefined, (err, res) => {
if (err != null) {
reject(err.message);
} else {
this.client.bind(user, pass, (err2) => {
if (err2 != null) {
reject(err2.message);
} else {
resolve();
}
});
}
});
} else {
this.client.bind(user, pass, (err) => {
if (err != null) {
reject(err.message);
} else {
resolve();
}
});
}
});
}
private async unbind(): Promise<void> {
return new Promise((resolve, reject) => {
this.client.unbind((err) => {
if (err != null) {
reject(err);
} else {
resolve();
if (
this.dirConfig.tlsCaPath != null &&
this.dirConfig.tlsCaPath !== "" &&
fs.existsSync(this.dirConfig.tlsCaPath)
) {
tlsOptions.ca = [fs.readFileSync(this.dirConfig.tlsCaPath)];
}
});
});
}
}
tlsOptions.checkServerIdentity = this.checkServerIdentityAltNames;
options.tlsOptions = tlsOptions;
this.client = new ldapts.Client(options);
const user =
this.dirConfig.username == null || this.dirConfig.username.trim() === ""
? null
: this.dirConfig.username;
const pass =
this.dirConfig.password == null || this.dirConfig.password.trim() === ""
? null
: this.dirConfig.password;
if (user == null || pass == null) {
throw new Error(this.i18nService.t("usernamePasswordNotConfigured"));
}
if (this.dirConfig.startTls && this.dirConfig.ssl) {
await this.client.startTLS(options.tlsOptions);
}
try {
await this.client.bind(user, pass);
} finally {
await this.client.unbind();
}
}
private bufToGuid(buf: Buffer) {
@@ -494,7 +444,7 @@ export class LdapDirectoryService implements IDirectoryService {
return guid.toLowerCase();
}
private checkServerIdentityAltNames(host: string, cert: PeerCertificate) {
private checkServerIdentityAltNames(host: string, cert: tls.PeerCertificate) {
// Fixes the cert representation when subject is empty and altNames are present
// Required for node versions < 12.14.1 (which could be used for bwdc cli)
// Adapted from: https://github.com/auth0/ad-ldap-connector/commit/1f4dd2be6ed93dda591dd31ed5483a9b452a8d2a
@@ -510,6 +460,6 @@ export class LdapDirectoryService implements IDirectoryService {
};
}
return checkServerIdentity(host, cert);
return tls.checkServerIdentity(host, cert);
}
}