mirror of
https://github.com/gitbucket/gitbucket.git
synced 2025-11-06 13:35:50 +01:00
105 lines
3.3 KiB
Scala
105 lines
3.3 KiB
Scala
package util
|
|
|
|
import util.ControlUtil._
|
|
import service.SystemSettingsService
|
|
import com.novell.ldap._
|
|
import service.SystemSettingsService.Ldap
|
|
import scala.annotation.tailrec
|
|
|
|
/**
|
|
* Utility for LDAP authentication.
|
|
*/
|
|
object LDAPUtil {
|
|
|
|
private val LDAP_VERSION: Int = 3
|
|
|
|
/**
|
|
* Try authentication by LDAP using given configuration.
|
|
* Returns Right(mailAddress) if authentication is successful, otherwise Left(errorMessage).
|
|
*/
|
|
def authenticate(ldapSettings: Ldap, userName: String, password: String): Either[String, String] = {
|
|
bind(
|
|
ldapSettings.host,
|
|
ldapSettings.port.getOrElse(SystemSettingsService.DefaultLdapPort),
|
|
ldapSettings.bindDN.getOrElse(""),
|
|
ldapSettings.bindPassword.getOrElse("")
|
|
) match {
|
|
case Some(conn) => {
|
|
withConnection(conn) { conn =>
|
|
findUser(conn, userName, ldapSettings.baseDN, ldapSettings.userNameAttribute) match {
|
|
case Some(userDN) => userAuthentication(ldapSettings, userDN, password)
|
|
case None => Left("User does not exist")
|
|
}
|
|
}
|
|
}
|
|
case None => Left("System LDAP authentication failed.")
|
|
}
|
|
}
|
|
|
|
private def userAuthentication(ldapSettings: Ldap, userDN: String, password: String): Either[String, String] = {
|
|
bind(
|
|
ldapSettings.host,
|
|
ldapSettings.port.getOrElse(SystemSettingsService.DefaultLdapPort),
|
|
userDN,
|
|
password
|
|
) match {
|
|
case Some(conn) => {
|
|
withConnection(conn) { conn =>
|
|
findMailAddress(conn, userDN, ldapSettings.mailAttribute) match {
|
|
case Some(mailAddress) => Right(mailAddress)
|
|
case None => Left("Can't find mail address.")
|
|
}
|
|
}
|
|
}
|
|
case None => Left("User LDAP Authentication Failed.")
|
|
}
|
|
}
|
|
|
|
private def bind(host: String, port: Int, dn: String, password: String): Option[LDAPConnection] = {
|
|
val conn: LDAPConnection = new LDAPConnection
|
|
try {
|
|
conn.connect(host, port)
|
|
conn.bind(LDAP_VERSION, dn, password.getBytes)
|
|
Some(conn)
|
|
} catch {
|
|
case e: Exception => {
|
|
if (conn.isConnected) conn.disconnect()
|
|
None
|
|
}
|
|
}
|
|
}
|
|
|
|
private def withConnection[T](conn: LDAPConnection)(f: LDAPConnection => T): T = {
|
|
try {
|
|
f(conn)
|
|
} finally {
|
|
conn.disconnect()
|
|
}
|
|
}
|
|
|
|
private def findUser(conn: LDAPConnection, userName: String, baseDN: String, userNameAttribute: String): Option[String] = {
|
|
@tailrec
|
|
def getEntries(results: LDAPSearchResults, entries: List[Option[LDAPEntry]] = Nil): List[LDAPEntry] = {
|
|
if(results.hasMore){
|
|
getEntries(results, entries :+ (try {
|
|
Option(results.next)
|
|
} catch {
|
|
case ex: LDAPReferralException => None // NOTE(tanacasino): Referral follow is off. so ignores it.(for AD)
|
|
}))
|
|
} else {
|
|
entries.flatten
|
|
}
|
|
}
|
|
getEntries(conn.search(baseDN, LDAPConnection.SCOPE_SUB, userNameAttribute + "=" + userName, null, false)).collectFirst {
|
|
case x => x.getDN
|
|
}
|
|
}
|
|
|
|
private def findMailAddress(conn: LDAPConnection, userDN: String, mailAttribute: String): Option[String] =
|
|
defining(conn.search(userDN, LDAPConnection.SCOPE_BASE, null, Array[String](mailAttribute), false)){ results =>
|
|
optionIf (results.hasMore) {
|
|
Option(results.next.getAttribute(mailAttribute)).map(_.getStringValue)
|
|
}
|
|
}
|
|
}
|