mirror of
https://github.com/bitwarden/directory-connector
synced 2025-12-10 13:23:18 +00:00
starttls: Support LDAP STARTTLS (#33)
* starttls: Support LDAP STARTTLS * starttls: Re-roll to preserve old config
This commit is contained in:
@@ -35,39 +35,54 @@
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="ssl" [(ngModel)]="ldap.ssl" name="SSL">
|
||||
<label class="form-check-label" for="ssl">{{'ldapSsl' | i18n}}</label>
|
||||
<input class="form-check-input" type="checkbox" id="ldapEncrypted" [(ngModel)]="ldap.ssl" name="Encrypted">
|
||||
<label class="form-check-label" for="ldapEncrypted">{{'ldapEncrypted' | i18n}}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="ml-4" *ngIf="ldap.ssl">
|
||||
<p>{{'ldapSslUntrustedDesc' | i18n}}</p>
|
||||
<div class="form-group">
|
||||
<label for="sslCertPath">{{'ldapSslCert' | i18n}}</label>
|
||||
<input type="file" class="form-control-file mb-2" id="sslCertPath_file"
|
||||
(change)="setSslPath('sslCertPath')">
|
||||
<input type="text" class="form-control" id="sslCertPath" name="SSLCertPath"
|
||||
[(ngModel)]="ldap.sslCertPath">
|
||||
<div class="form-radio">
|
||||
<input class="form-radio-input" type="radio" [value]=true id="starttls" [(ngModel)]="ldap.starttls" name="StartTls">
|
||||
<label class="form-radio-label" for="starttls">{{'ldapTls' | i18n}}</label>
|
||||
</div>
|
||||
<div class="form-radio">
|
||||
<input class="form-radio-input" type="radio" [value]=false id="ssl" [(ngModel)]="ldap.starttls" name="SSL">
|
||||
<label class="form-radio-label" for="ssl">{{'ldapSsl' | i18n}}</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="sslKeyPath">{{'ldapSslKey' | i18n}}</label>
|
||||
<input type="file" class="form-control-file mb-2" id="sslKeyPath_file"
|
||||
(change)="setSslPath('sslKeyPath')">
|
||||
<input type="text" class="form-control" id="sslKeyPath" name="SSLKeyPath"
|
||||
[(ngModel)]="ldap.sslKeyPath">
|
||||
<div class="ml-4" *ngIf="ldap.starttls">
|
||||
<p>{{'ldapTlsUntrustedDesc' | i18n}}</p>
|
||||
<div class="form-group">
|
||||
<label for="tlsCaPath">{{'ldapTlsCa' | i18n}}</label>
|
||||
<input type="file" class="form-control-file mb-2" id="tlsCaPath_file"
|
||||
(change)="setSslPath('tlsCaPath')">
|
||||
<input type="text" class="form-control" id="tlsCaPath" name="TLSCaPath" [(ngModel)]="ldap.tlsCaPath">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="sslCaPath">{{'ldapSslCa' | i18n}}</label>
|
||||
<input type="file" class="form-control-file mb-2" id="sslCaPath_file"
|
||||
(change)="setSslPath('sslCaPath')">
|
||||
<input type="text" class="form-control" id="sslCaPath" name="SSLCaPath"
|
||||
[(ngModel)]="ldap.sslCaPath">
|
||||
<div class="ml-4" *ngIf="!ldap.starttls">
|
||||
<p>{{'ldapSslUntrustedDesc' | i18n}}</p>
|
||||
<div class="form-group">
|
||||
<label for="sslCertPath">{{'ldapSslCert' | i18n}}</label>
|
||||
<input type="file" class="form-control-file mb-2" id="sslCertPath_file"
|
||||
(change)="setSslPath('sslCertPath')">
|
||||
<input type="text" class="form-control" id="sslCertPath" name="SSLCertPath" [(ngModel)]="ldap.sslCertPath">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="sslKeyPath">{{'ldapSslKey' | i18n}}</label>
|
||||
<input type="file" class="form-control-file mb-2" id="sslKeyPath_file" (change)="setSslPath('sslKeyPath')">
|
||||
<input type="text" class="form-control" id="sslKeyPath" name="SSLKeyPath" [(ngModel)]="ldap.sslKeyPath">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="sslCaPath">{{'ldapSslCa' | i18n}}</label>
|
||||
<input type="file" class="form-control-file mb-2" id="sslCaPath_file" (change)="setSslPath('sslCaPath')">
|
||||
<input type="text" class="form-control" id="sslCaPath" name="SSLCaPath" [(ngModel)]="ldap.sslCaPath">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="checkbox" id="sslAllowUnauthorized"
|
||||
[(ngModel)]="ldap.sslAllowUnauthorized" name="SSLAllowUnauthorized">
|
||||
<label class="form-check-label"
|
||||
for="sslAllowUnauthorized">{{'ldapSslAllowUnauthorized' | i18n}}</label>
|
||||
<input class="form-check-input" type="checkbox" id="certDoNotVerify"
|
||||
[(ngModel)]="ldap.sslAllowUnauthorized" name="CertDoNoVerify">
|
||||
<label class="form-check-label" for="certDoNotVerify">{{'ldapCertDoNotVerify' | i18n}}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -414,8 +414,20 @@
|
||||
"sync": {
|
||||
"message": "Sync"
|
||||
},
|
||||
"ldapEncrypted": {
|
||||
"message": "This server uses an encrypted connection"
|
||||
},
|
||||
"ldapTls": {
|
||||
"message": "Use TLS (STARTTLS)"
|
||||
},
|
||||
"ldapTlsCa": {
|
||||
"message": "Certificate CA Chain (PEM)"
|
||||
},
|
||||
"ldapSsl": {
|
||||
"message": "This server uses SSL (LDAPS)"
|
||||
"message": "Use SSL (LDAPS)"
|
||||
},
|
||||
"ldapTlsUntrustedDesc": {
|
||||
"message": "If your LDAP server uses a self-signed certificate for STARTTLS, you can configure certificate options below."
|
||||
},
|
||||
"ldapSslUntrustedDesc": {
|
||||
"message": "If your LDAPS server uses an untrusted certificate you can configure certificate options below."
|
||||
@@ -429,8 +441,8 @@
|
||||
"ldapSslKey": {
|
||||
"message": "Certificate Private Key (PEM)"
|
||||
},
|
||||
"ldapSslAllowUnauthorized": {
|
||||
"message": "Allow untrusted SSL connections (not recommended)."
|
||||
"ldapCertDoNotVerify": {
|
||||
"message": "Do not verify server certificates (not recommended)."
|
||||
},
|
||||
"ldapAd": {
|
||||
"message": "This server uses Active Directory"
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
export class LdapConfiguration {
|
||||
ssl = false;
|
||||
starttls = true;
|
||||
tlsCaPath: string;
|
||||
sslAllowUnauthorized = false;
|
||||
sslCertPath: string;
|
||||
sslKeyPath: string;
|
||||
|
||||
@@ -324,32 +324,41 @@ export class LdapDirectoryService implements DirectoryService {
|
||||
reject(this.i18nService.t('dirConfigIncomplete'));
|
||||
return;
|
||||
}
|
||||
|
||||
const url = 'ldap' + (this.dirConfig.ssl ? 's' : '') + '://' + this.dirConfig.hostname +
|
||||
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(),
|
||||
};
|
||||
|
||||
const tlsOptions: any = {};
|
||||
if (this.dirConfig.ssl) {
|
||||
const tlsOptions: any = {};
|
||||
if (this.dirConfig.sslAllowUnauthorized != null) {
|
||||
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.sslAllowUnauthorized) {
|
||||
tlsOptions.rejectUnauthorized = !this.dirConfig.sslAllowUnauthorized;
|
||||
}
|
||||
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);
|
||||
}
|
||||
if (Object.keys(tlsOptions).length > 0) {
|
||||
options.tlsOptions = tlsOptions;
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(tlsOptions).length > 0) {
|
||||
options.tlsOptions = tlsOptions;
|
||||
}
|
||||
|
||||
this.client = ldap.createClient(options);
|
||||
@@ -364,13 +373,29 @@ export class LdapDirectoryService implements DirectoryService {
|
||||
return;
|
||||
}
|
||||
|
||||
this.client.bind(user, pass, (err) => {
|
||||
if (err != null) {
|
||||
reject(err.message);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
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, (err) => {
|
||||
if (err != null) {
|
||||
reject(err.message);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
this.client.bind(user, pass, (err) => {
|
||||
if (err != null) {
|
||||
reject(err.message);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user