@@ -4,12 +4,13 @@ package controllers
44import java .nio .charset .StandardCharsets
55import java .security .SecureRandom
66import java .util .UUID
7-
87import akka .stream .Materializer
98import com .typesafe .config .ConfigValueType
109import com .unboundid .ldap .sdk ._
10+ import com .unboundid .ldap .sdk .extensions .StartTLSExtendedRequest
1111import com .unboundid .util .ssl .{SSLUtil , TrustAllTrustManager }
1212import grizzled .slf4j .Logging
13+
1314import javax .crypto .Mac
1415import javax .net .ssl
1516import org .apache .commons .codec .binary .Base64
@@ -143,19 +144,49 @@ case class LDAPAuthenticator(config: LDAPAuthenticationConfig)(implicit val mat:
143144 private lazy val unauthorizedResult = Future successful Unauthorized .withHeaders(WWW_AUTHENTICATE -> realm)
144145 private lazy val ldapConnectionPool : LDAPConnectionPool = {
145146 val (address, port) = (config.address, config.port)
147+
148+ if (config.sslEnabled && config.startTLSEnabled) {
149+ logger.error(" SSL and StartTLS enabled together. Most LDAP Server implementations will not handle this as it initializes an encrypted context over an already encrypted channel" )
150+ }
151+
146152 val connection = if (config.sslEnabled) {
147153 if (config.sslTrustAll) {
148154 val sslUtil = new SSLUtil (null , new TrustAllTrustManager (true ))
149155 val sslSocketFactory = sslUtil.createSSLSocketFactory
150- new LDAPConnection (sslSocketFactory, address, port, config.username, config.password )
156+ new LDAPConnection (sslSocketFactory, address, port)
151157 } else {
152158 val sslSocketFactory = ssl.SSLSocketFactory .getDefault
153- new LDAPConnection (sslSocketFactory, address, port, config.username, config.password )
159+ new LDAPConnection (sslSocketFactory, address, port)
154160 }
155161 } else {
156- new LDAPConnection (address, port, config.username, config.password)
162+ new LDAPConnection (address, port)
163+ }
164+
165+ var startTLSPostConnectProcessor : StartTLSPostConnectProcessor = null
166+ if (config.startTLSEnabled) {
167+ if (config.sslTrustAll) {
168+ val sslUtil = new SSLUtil (null , new TrustAllTrustManager (true ))
169+ val sslContext = sslUtil.createSSLContext
170+ connection.processExtendedOperation(new StartTLSExtendedRequest (sslContext))
171+ startTLSPostConnectProcessor = new StartTLSPostConnectProcessor (sslContext)
172+ } else {
173+ val sslContext = new SSLUtil ().createSSLContext
174+ connection.processExtendedOperation(new StartTLSExtendedRequest (sslContext))
175+ startTLSPostConnectProcessor = new StartTLSPostConnectProcessor (sslContext)
176+ }
177+ }
178+
179+ try {
180+ connection.bind(config.username, config.password)
181+ } catch {
182+ case e : LDAPException => {
183+ connection.setDisconnectInfo(DisconnectType .BIND_FAILED , null , e)
184+ connection.close()
185+ logger.error(s " Bind failed with ldap server ${config.address}: ${config.port}" , e)
186+ }
157187 }
158- new LDAPConnectionPool (connection, config.connectionPoolSize)
188+
189+ new LDAPConnectionPool (connection, 1 , config.connectionPoolSize, startTLSPostConnectProcessor)
159190 }
160191
161192 def salt : Array [Byte ] = config.salt
@@ -275,7 +306,8 @@ case class LDAPAuthenticationConfig(salt: Array[Byte]
275306 , groupFilter : String
276307 , connectionPoolSize : Int
277308 , sslEnabled : Boolean
278- , sslTrustAll : Boolean ) extends AuthenticationConfig
309+ , sslTrustAll : Boolean
310+ , startTLSEnabled : Boolean ) extends AuthenticationConfig
279311
280312sealed trait AuthType [T <: AuthenticationConfig ] {
281313 def getConfig (config : AuthenticationConfig ): T
@@ -357,13 +389,14 @@ object BasicAuthenticationFilterConfiguration {
357389 val connectionPoolSize = int(" ldap.connection-pool-size" ).getOrElse(10 )
358390 val sslEnabled = boolean(" ldap.ssl" ).getOrElse(false )
359391 val sslTrustAll = boolean(" ldap.ssl-trust-all" ).getOrElse(false )
392+ val startTLSEnabled = boolean(" ldap.starttls" ).getOrElse(false )
360393
361394 BasicAuthenticationFilterConfiguration (
362395 enabled,
363396 LDAPAuth ,
364397 LDAPAuthenticationConfig (salt, iv, secret,
365398 string(" realm" ).getOrElse(defaultRealm),
366- server, port, username, password, searchDN, searchFilter, groupFilter, connectionPoolSize, sslEnabled, sslTrustAll
399+ server, port, username, password, searchDN, searchFilter, groupFilter, connectionPoolSize, sslEnabled, sslTrustAll, startTLSEnabled
367400 ),
368401 excluded
369402 )
0 commit comments