未验证 提交 c958c46f 编写于 作者: F Fabian Strachanski 提交者: GitHub

Add LDAPS-support to LDAP-Authcontroller (#7014)

* Add LDAPS-support to LDAP-Authcontroller

* Add Testcase that failed with valid certificate but wrong credendtials to LDAP-Authcontroller

* change scope of 'error' and remove 'case undefined', because it's not needed anymore
上级 ccb045b6
const ldap = require('../lib/Adapters/Auth/ldap');
const mockLdapServer = require('./MockLdapServer');
const fs = require('fs');
const port = 12345;
const sslport = 12346;
it('Should fail with missing options', done => {
ldap
......@@ -31,6 +33,86 @@ it('Should succeed with right credentials', done => {
});
});
it('Should succeed with right credentials when LDAPS is used and certifcate is not checked', done => {
mockLdapServer(sslport, 'uid=testuser, o=example', false, true).then(server => {
const options = {
suffix: 'o=example',
url: `ldaps://localhost:${sslport}`,
dn: 'uid={{id}}, o=example',
tlsOptions: { rejectUnauthorized: false }
};
ldap
.validateAuthData({ id: 'testuser', password: 'secret' }, options)
.then(done)
.catch(done.fail)
.finally(() => server.close());
});
});
it('Should succeed when LDAPS is used and the presented certificate is the expected certificate', done => {
mockLdapServer(sslport, 'uid=testuser, o=example', false, true).then(server => {
const options = {
suffix: 'o=example',
url: `ldaps://localhost:${sslport}`,
dn: 'uid={{id}}, o=example',
tlsOptions: {
ca: fs.readFileSync(__dirname + '/support/cert/cert.pem'),
rejectUnauthorized: true
}
};
ldap
.validateAuthData({ id: 'testuser', password: 'secret' }, options)
.then(done)
.catch(done.fail)
.finally(() => server.close());
});
});
it('Should fail when LDAPS is used and the presented certificate is not the expected certificate', done => {
mockLdapServer(sslport, 'uid=testuser, o=example', false, true).then(server => {
const options = {
suffix: 'o=example',
url: `ldaps://localhost:${sslport}`,
dn: 'uid={{id}}, o=example',
tlsOptions: {
ca: fs.readFileSync(__dirname + '/support/cert/anothercert.pem'),
rejectUnauthorized: true
}
};
ldap
.validateAuthData({ id: 'testuser', password: 'secret' }, options)
.then(done.fail)
.catch(err => {
jequal(err.message, 'LDAPS: Certificate mismatch');
done();
})
.finally(() => server.close());
});
});
it('Should fail when LDAPS is used certifcate matches but credentials are wrong', done => {
mockLdapServer(sslport, 'uid=testuser, o=example', false, true).then(server => {
const options = {
suffix: 'o=example',
url: `ldaps://localhost:${sslport}`,
dn: 'uid={{id}}, o=example',
tlsOptions: {
ca: fs.readFileSync(__dirname + '/support/cert/cert.pem'),
rejectUnauthorized: true
}
};
ldap
.validateAuthData({ id: 'testuser', password: 'wrong!' }, options)
.then(done.fail)
.catch(err => {
jequal(err.message, 'LDAP: Wrong username or password');
done();
})
.finally(() => server.close());
});
});
it('Should fail with wrong credentials', done => {
mockLdapServer(port, 'uid=testuser, o=example').then(server => {
const options = {
......
const ldapjs = require('ldapjs');
const fs = require('fs');
function newServer(port, dn, provokeSearchError = false) {
const server = ldapjs.createServer();
const tlsOptions = {
key: fs.readFileSync(__dirname + '/support/cert/key.pem'),
certificate: fs.readFileSync(__dirname + '/support/cert/cert.pem')
}
function newServer(port, dn, provokeSearchError = false, ssl = false) {
const server = ssl ? ldapjs.createServer(tlsOptions) : ldapjs.createServer();
server.bind('o=example', function (req, res, next) {
if (req.dn.toString() !== dn || req.credentials !== 'secret')
......
-----BEGIN CERTIFICATE-----
MIIE8DCCAtgCCQDjXCYv/hK1rjANBgkqhkiG9w0BAQsFADA5MRIwEAYDVQQDDAls
b2NhbGhvc3QxIzAhBgkqhkiG9w0BCQEWFG5vLXJlcGx5QGV4YW1wbGUuY29tMCAX
DTIwMTExNzEzMTAwMFoYDzIxMjAxMDI0MTMxMDAwWjA5MRIwEAYDVQQDDAlsb2Nh
bGhvc3QxIzAhBgkqhkiG9w0BCQEWFG5vLXJlcGx5QGV4YW1wbGUuY29tMIICIjAN
BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAmsOhxCNw3cEA3TLyqZXMI5p/LNSu
W9doIvLEs1Ah8L/Gbl7xmSagkTZYzkTJDxITy0d45NVfmDsm0ctQrPV5MEbFE571
lLQRnCFMpB3dqejfqQWpVCMfJKR1p8p5FTtcC5u5g7bcf2YeujwbUVDEtbeHwUeo
XBnKfmv0UdGiLQf0uel5dcGWNp8dFo+hO4wCTA/risIdWawG8RHtzfhRIT2PqUa8
ljgPyuPU2NQ19gUkV1LkXKJby+6VHhD6pSfzptbsJjalaGawTku7ZgBoZiax8wRk
Bdwyd3ScMQg2VLGIn7YaMwb4ANtHqREekl0q7tPTu+PBmYqGXqa3lKa/s1OebUyS
GQQXZB5T/Brm2fvJWqO9oJjZiTZzZIkBWDP0Cn+pmW/T4dADUms/vONEJE9IPFn1
id5Q8vjSf5V1MaZJjWek38Y98xfYlKecHIqBAYQAydxdxuzG/DJu+2GzOZeffETD
lzNwrLZp5lBzSrOwVntonvFo04lIq+DepVF+OqK8qV+7pnKCij5bGvdwxaY290pW
+VTzK8kw0VUmpyYrDWIr7C52txaleY/AqsHy6wlVgdMbwXDjQ00twkJJT3tecL9I
eWtLOuh7BeokvDFOXRVI2ZB2KN0sOBXsPfM6G4o9RK305Q9TFEXARnly9cwoV/i9
8yeJ5teQHw3dm7kCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAIWUqZSMCGlzWsCtU
Xayr4qshfhqhm6PzgCWGjg8Xsm8gwrbYtQRwsKdJvw7ynLhbeX65i7p3/3AO0W6k
8Zpf58MHgepMOHmVT/KVBy7tUb83wJuoEvZzH50sO0rcA32c3p2FFUvt3JW+Dfo5
BMX6GDlymtZPAplD9Rw5S5CXkZAgraDCbx1JMGFh0FfbP9v7jdo+so35y8UqmJ10
3U0NX2UJoWGE6RvV2P/1TE0v4pWyFzz1dF2k/gcmzYtMgIkJGGO8qhIGo2rSVJhC
gVlYxyW/Rxogxz4wN0EqPIJNnkRby/g40OkPN8ATkHs09F4Jyax+cU0iJ3Hbn5t/
0Ou5oaAs4t1+u11iahUMP6evaXooZONawM7h0RT4HHHZkXT95+kmaMz/+JZRp9DA
Cafp9IsTjLzHvRy5DLX2kithqXaKRdpgTylx0qwW+8HxRjCcJEsFN3lXWqX12R8D
OM8DnVsFX61Ygp7kTj2CQ+Y3Wqrj+jEkyJLRvMeTNPlxfazwudgFuDYsDErMCUwG
U67vPoCkvIShFrnR9X4ojpG8aqWF8M/o8nvKIQp+FEW0Btm6rZT9lGba6nZw76Yj
+48bsJCQ7UzhKkeFO4Bmj0fDkBTAElV2oEJXbHbB6+0DQE48uLWAr4xb7Vswph8c
wHgxPsgsd2h0gr21doWB1BsdAu8=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIE8DCCAtgCCQDaLjopNQCJuTANBgkqhkiG9w0BAQsFADA5MRIwEAYDVQQDDAls
b2NhbGhvc3QxIzAhBgkqhkiG9w0BCQEWFG5vLXJlcGx5QGV4YW1wbGUuY29tMCAX
DTIwMTExNzExNDEzM1oYDzIxMjAxMDI0MTE0MTMzWjA5MRIwEAYDVQQDDAlsb2Nh
bGhvc3QxIzAhBgkqhkiG9w0BCQEWFG5vLXJlcGx5QGV4YW1wbGUuY29tMIICIjAN
BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAvFf3I2RnIbp82Dd0AooAMamxMCgu
g4zurMdA40mV8G+MA4Y5XFcGmOYT7LC94Z2nZ4tI+MNSiLKQY3Zq+OYGGmn/zVkr
e8+02afxTjGmLVJWJXxXV2rsf8+UuJMOPbmVq87nJmD2gs9T6czOE3eQdDTRUzTg
ubWhp3hV291gMfCIQeBbSqfbBscz0Nboj8NHStWDif5Io94l08tdW9oHIu99NYE0
DMWIfBeztHpmSfkgPKH8lNar1dMsuCRW2Q/b01TNPKCNp8ZxyIhzkOq2gC5l60i5
/iALWeEJii8g71V3DMbU5KoPEB+jFZ/z7qAi8TH9VqgaUycs/M96VXMIZbDhXywJ
pg7qHxG/RT16bXwFotreThcla2M3VxsZEnYPEVmQEyVQeG7XyvqFMC3DhGCflW35
dumJlkuGn9e9Lg6oiidp2RMnZuTsie+y3e3XJz2ZjFihGQNy2VzUrDz4ymi2fosV
GMeHn3iK2nEqxf1mx021j3v40/8I5gtkS+zZuchclae0gRHaNN1tO0osedUdlV7D
0dvi9xezsfelqSqJjChLfl4R3HqC8k7cwUfK4RmKXhI5GX4ESr+1KWPIaqH5AxYB
+ee2WYBQGhi6aXKpVcj9dvq+OAmDMPCJr0xnWMMZqR5dnxY1eEq2x28n2b1SyIw1
+IctNX0nLwGAMgUCAwEAATANBgkqhkiG9w0BAQsFAAOCAgEAEYTLXvHWmNuYlG6e
CAiK1ubJ98nO6PSJsl+qosB1kWKlPeWPOLLAeZxSDh0tKRPvQoXoH/AtMRGHFGLS
lk7fbCAbgEqvfA9+8VhgpWSRXD2iodt444P+m93NiMNeusiRFzozXKZZvU4Ie97H
mDuwLjpGgi8DUShebM2Ngif8t4DmSgSfLQ3OEac7oKUP6ffHMXbqnDwjh8ZCCh1m
DN+0i4Y5WpKD7Z+JjGHJRm1Cx/G5pwP16Et6YejQMnNU70VDOzGSvNABmiexiR5p
m8pOTkyxrYViYqamLZG5to5vpI6RmEoA/5vbU59dZ5DzPmSoyNbIeaz+dkSGoy6D
SWKZMwGTf++xS5y+oy2lNS2iddc845qCcDy4jeel3N9JPlJPwrArfapATcrX3Rpy
GsVPvWsKA3q7kwIQo3qscg0CkYwHo5VCnWHDNqgOeFo35J7y+CKxYRolD9/lCtAU
Pw8CBGp1x8jgIv7yKNiPVDtWYztqfsFrplLf/yiZSH53zghSY3v5qnFRkmGq1HRC
G6lz0yjI7RUEA2a/XA2dv9Hv6CdmWUzrsXvocH5VgQz2RtkyvSaLFzRv8gnESrY1
7qq55D1QIkO8UzzmCSpYPi5tUTGAYE1aHP/B1S5LpBrpaJ8Q9nfqA/9Bb+aho2ze
N0vpdSSemKGQcrzquNqDJhUoXgQ=
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
MIIJKQIBAAKCAgEAvFf3I2RnIbp82Dd0AooAMamxMCgug4zurMdA40mV8G+MA4Y5
XFcGmOYT7LC94Z2nZ4tI+MNSiLKQY3Zq+OYGGmn/zVkre8+02afxTjGmLVJWJXxX
V2rsf8+UuJMOPbmVq87nJmD2gs9T6czOE3eQdDTRUzTgubWhp3hV291gMfCIQeBb
SqfbBscz0Nboj8NHStWDif5Io94l08tdW9oHIu99NYE0DMWIfBeztHpmSfkgPKH8
lNar1dMsuCRW2Q/b01TNPKCNp8ZxyIhzkOq2gC5l60i5/iALWeEJii8g71V3DMbU
5KoPEB+jFZ/z7qAi8TH9VqgaUycs/M96VXMIZbDhXywJpg7qHxG/RT16bXwFotre
Thcla2M3VxsZEnYPEVmQEyVQeG7XyvqFMC3DhGCflW35dumJlkuGn9e9Lg6oiidp
2RMnZuTsie+y3e3XJz2ZjFihGQNy2VzUrDz4ymi2fosVGMeHn3iK2nEqxf1mx021
j3v40/8I5gtkS+zZuchclae0gRHaNN1tO0osedUdlV7D0dvi9xezsfelqSqJjChL
fl4R3HqC8k7cwUfK4RmKXhI5GX4ESr+1KWPIaqH5AxYB+ee2WYBQGhi6aXKpVcj9
dvq+OAmDMPCJr0xnWMMZqR5dnxY1eEq2x28n2b1SyIw1+IctNX0nLwGAMgUCAwEA
AQKCAgAEsuEche24vrFMp52CTrUQiB4+iFIYwBRYRSROR1CxTecdU2Ts89LbT6oh
los2LLu3bpckdaMCfAn0IUkr6nkugYR7OAVIsnbdkz4G6GAv80To7IA1UxqRWblp
HWoWiiG8xo2nvHWJ7+g1BgICJFJ7Q7IRNFmC6JAe4Har5Ir40/piQlmktClXsvKM
/D+TDpkhuc/tSmW/iNRCw2kR2I+jBHyIMC//PZJZHjJCh2cz4z41pQjrIavpyrnr
4iQ0iBvA2vW/1HWUQPQnv5e6ftCMxBuQ0iCpwVznIiEdzG0y61vr+q3nAoMbsN5d
tL7eLiqQ/+FFHy6A8pJBwF9Z8GO+MsN0GbD4Ttd2WkXVM4AJwWsB6SWx7znrgWhy
JHy/5r20/0J0VniX63qjt8RRUG9VyHxr8Vx0/jkd+3z23cn/ecBf41sLFy30HsIN
Gg2KJf4Wf1kFaEgdT2xO2fahBWOeN7uKJokNaSkocE6NRdfoxhj/r/RLcJJqE4V9
a4FOMmdZtCgxvNN2Cb3GS76ImQjfJpA8wrBOWxW+XFuQi5ohory9mdLjbnk9/w/v
6yT76DN+gcgfrgHW1w5ttwfnyQF9fQ2hRobbGqbYFOMaxE1Qds46Vl+GN9KlMhhO
S0zK7ZSKE9pqaLTo5Hb4po/0A4TXAL0v2iap+9bD3NKoRnDBoQKCAQEA5IDHxRGu
mgAuW29PidvrNcRDQBMmkm89BvPr1Om50l6Zk/DuwgE7/73eiCBA/yXuqkjUTJXT
iAuQE0yLjU6YFGdl7lNncfD+Zl9CztOkNpfO6z5vyvvvkLXU3pL0ytTW4RNaV0fQ
ccGF0gnzOp6DoWCSkNz1Pz3VLyn1m4rnOaFu2a2O2Ljs1Nrc+FGP1LFrsiQnpPP9
ArXpjSqTs5tUMKNJ1y3Y1bkpfx9B+LWXLTP2eLNlIjiCEzbyEtAldSZFfz30Tjmx
3Yr4aqgdHGcMm66MeLCXGdnuoBLpll6UpDC6oZT9Nh8uFlQXrhiy+0Gsxw4UjAZd
ilY+jqHQqmqFSQKCAQEA0wIKnmKYIc76niu3fUAN3iuO3bZ5Q0k/OBonVMNnwBc4
1YWG4p2ecEQrA2CJmoz0J6rEm+y+DHRw6LH1zBjl3riCDbomwIVGZ/puub7Ibcbc
t0P6DzUeP0jz2o+JaPWClZxFOlikhjkWwmAWl+iyx3hh/sRXtrmkKkhSxEk8CUAa
yM78AG3maI36LpGEYf3sP5EZV/EsyEAV0uKJpmuHGcgkytq/x893R37HfzDdMlN6
ejk6rbCbCOaXO8AXrKwWpUuudlfDBzPgQ/kl8dKJwgv8u5NlshjknkhKi6Hoprsi
N/zhR7Rns/Z/N4g5zNtKTrQXh4reFF2CWREssMwS3QKCAQA6tvyeHtUGrVU8GXYO
rnvZ7Px60nDu37aGuta2dvhQng5IfXhcUYThSiCMSf1pko2pI92pcDZSluYGj3ys
aq2ZUJhYjQXfuVUlaQT5sFhZzthUik6fke0U+iQgrRJJrDcqzpZAJyvgjyGbvwLI
5UJdjTscDirWfUTyQY3i0eZoYJrjRD2YYqw4ZaSyCgMzXAOYWsH1GNzCfYvtwisB
07/mX47xw84b3OBU0etZxQ97hganLTGngW2rEktRmjqFx7fD4l+MWjbh/numrFwO
mEwdFNTzjizFb8JpT3LGOLdpGTxbmLUX2xs0kZckHSSge1eyLmQJNvmCOncIn3vG
zmhBAoIBAQDBZxyegZYZXuIdOcqr9ZsAaQJAu3C4OJnGbUphid09lstUAlhYu8mt
8v1N0h0t2EYtWXttw3eKaOvYjMzTLnr7QjiKJnZAfafDxCna/EAvRlelbpvzdmdr
8Az65hc3adgwExTs3rSmBguTS4lJ4VKEPBXt8r7Gz67lxnZ+TPXHMMecCQO3zQOk
D4YhSuWA/8Gbnf4Rug+m1/5o1ZT/QY2KFwWKHSgtFz6n/E8UiJAmAZfAEVZ0PuxL
Ize431+TuAPlq9GTzOsIXgcPpnyeArCbeGtE7lwG+oQJhA83nsZklB9QG+vM0lE/
BQ8jsivwVYrtSmpKpQDav76qrnA8+D/NAoIBAQCm80sB4L+2gIb/Qg/rvTW7atc2
q7GCZ/YHmHb3TeV8QiKEr7lXIAS9tFrCbWLUwBqXJIkOJUFmk2BQg/78OPJyorcE
7qTptaO0qnp9BjxvZimE3wwM7WVa8pQCAYt96unHlQoQoT9xeyti/ZKMzHaoMVuL
J0DfPa71yW7uTCWoyVCNQwqIourHFv6sKsiERE/OjhRVLyXG/5uLZjc0lYY/qaQ1
ax/UxjyTOakil8MBnta/q1NpSv8SQmFXCWjrREepkJF0/CzC7/1AULBdy0h1132C
B5CWnSKpHPePuczojgXjmw+Xg6vAXwsA4CXVJF1AUBlg7q91PtZYpCAqMPwA
-----END RSA PRIVATE KEY-----
......@@ -12,23 +12,32 @@ function validateAuthData(authData, options) {
);
});
}
const clientOptions = (options.url.startsWith("ldaps://")) ?
{ url: options.url, tlsOptions: options.tlsOptions } : { url: options.url };
const client = ldapjs.createClient({ url: options.url });
const client = ldapjs.createClient(clientOptions);
const userCn =
typeof options.dn === 'string'
? options.dn.replace('{{id}}', authData.id)
: `uid=${authData.id},${options.suffix}`;
return new Promise((resolve, reject) => {
client.bind(userCn, authData.password, err => {
if (err) {
client.destroy(err);
return reject(
new Parse.Error(
Parse.Error.OBJECT_NOT_FOUND,
'LDAP: Wrong username or password'
)
);
client.bind(userCn, authData.password, ldapError => {
if (ldapError) {
let error;
switch (ldapError.code) {
case 49:
error = new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'LDAP: Wrong username or password');
break;
case "DEPTH_ZERO_SELF_SIGNED_CERT":
error = new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'LDAPS: Certificate mismatch');
break;
default:
error = new Parse.Error(Parse.Error.OBJECT_NOT_FOUND, 'LDAP: Somthing went wrong (' + ldapError.code + ')');
}
reject(error);
client.destroy(ldapError);
return;
}
if (
......@@ -50,7 +59,8 @@ function optionsAreValid(options) {
typeof options === 'object' &&
typeof options.suffix === 'string' &&
typeof options.url === 'string' &&
options.url.startsWith('ldap://')
(options.url.startsWith('ldap://') ||
options.url.startsWith('ldaps://') && typeof options.tlsOptions === 'object')
);
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册