diff --git a/contrib/redhat/gitbucket.conf b/contrib/redhat/gitbucket.conf index c3959f3..1b60b32 100644 --- a/contrib/redhat/gitbucket.conf +++ b/contrib/redhat/gitbucket.conf @@ -16,5 +16,8 @@ # URL prefix for the GitBucket page (http://://) #GITBUCKET_PREFIX= +# Java keystore (for LDAP StartTLS) +#GITBUCKET_KEYSTORE=/var/lib/gitbucket/keystore + # Other Java option #GITBUCKET_JVM_OPTS= diff --git a/contrib/redhat/gitbucket.init b/contrib/redhat/gitbucket.init index 3aed802..75f7525 100644 --- a/contrib/redhat/gitbucket.init +++ b/contrib/redhat/gitbucket.init @@ -14,6 +14,7 @@ # Default values GITBUCKET_HOME=/var/lib/gitbucket GITBUCKET_WAR_FILE=/usr/share/gitbucket/lib/gitbucket.war +GITBUCKET_KEYSTORE=/var/lib/gitbucket/keystore # Pull in cq settings [ -f /etc/sysconfig/gitbucket ] && . /etc/sysconfig/gitbucket @@ -29,6 +30,8 @@ start() { echo -n $"Starting GitBucket server: " + GITBUCKET_JVM_OPTS="${GITBUCKET_JVM_OPTS} -Djavax.net.ssl.trustStore=${GITBUCKET_KEYSTORE}" + # Compile statup parameters if [ $GITBUCKET_PORT ]; then START_OPTS="${START_OPTS} --port=${GITBUCKET_PORT}" diff --git a/src/main/scala/app/SystemSettingsController.scala b/src/main/scala/app/SystemSettingsController.scala index 9466a83..560c54e 100644 --- a/src/main/scala/app/SystemSettingsController.scala +++ b/src/main/scala/app/SystemSettingsController.scala @@ -33,7 +33,8 @@ "bindPassword" -> trim(label("Bind Password", optional(text()))), "baseDN" -> trim(label("Base DN", text(required))), "userNameAttribute" -> trim(label("User name attribute", text(required))), - "mailAttribute" -> trim(label("Mail address attribute", text(required))) + "mailAttribute" -> trim(label("Mail address attribute", text(required))), + "tls" -> trim(label("Enable StartTLS", optional(boolean()))) )(Ldap.apply)) )(SystemSettings.apply) diff --git a/src/main/scala/service/SystemSettingsService.scala b/src/main/scala/service/SystemSettingsService.scala index 5ed9eb3..2c62047 100644 --- a/src/main/scala/service/SystemSettingsService.scala +++ b/src/main/scala/service/SystemSettingsService.scala @@ -32,6 +32,7 @@ props.setProperty(LdapBaseDN, ldap.baseDN) props.setProperty(LdapUserNameAttribute, ldap.userNameAttribute) props.setProperty(LdapMailAddressAttribute, ldap.mailAttribute) + ldap.tls.foreach(x => props.setProperty(LdapTls, x.toString)) } } props.store(new java.io.FileOutputStream(GitBucketConf), null) @@ -69,7 +70,8 @@ getOptionValue(props, LdapBindPassword, None), getValue(props, LdapBaseDN, ""), getValue(props, LdapUserNameAttribute, ""), - getValue(props, LdapMailAddressAttribute, ""))) + getValue(props, LdapMailAddressAttribute, ""), + getOptionValue[Boolean](props, LdapTls, None))) } else { None } @@ -97,7 +99,8 @@ bindPassword: Option[String], baseDN: String, userNameAttribute: String, - mailAttribute: String) + mailAttribute: String, + tls: Option[Boolean]) case class Smtp( host: String, @@ -129,6 +132,7 @@ private val LdapBaseDN = "ldap.baseDN" private val LdapUserNameAttribute = "ldap.username_attribute" private val LdapMailAddressAttribute = "ldap.mail_attribute" + private val LdapTls = "ldap.tls" private def getValue[A: ClassTag](props: java.util.Properties, key: String, default: A): A = defining(props.getProperty(key)){ value => diff --git a/src/main/scala/util/LDAPUtil.scala b/src/main/scala/util/LDAPUtil.scala index 4c6347c..d6ef2a9 100644 --- a/src/main/scala/util/LDAPUtil.scala +++ b/src/main/scala/util/LDAPUtil.scala @@ -3,6 +3,8 @@ import util.ControlUtil._ import service.SystemSettingsService import com.novell.ldap._ +import java.security.Security +import org.slf4j.LoggerFactory import service.SystemSettingsService.Ldap import scala.annotation.tailrec @@ -11,7 +13,8 @@ */ object LDAPUtil { - private val LDAP_VERSION: Int = 3 + private val LDAP_VERSION: Int = LDAPConnection.LDAP_V3 + private val logger = LoggerFactory.getLogger("LDAPUtil") /** * Try authentication by LDAP using given configuration. @@ -22,7 +25,8 @@ ldapSettings.host, ldapSettings.port.getOrElse(SystemSettingsService.DefaultLdapPort), ldapSettings.bindDN.getOrElse(""), - ldapSettings.bindPassword.getOrElse("") + ldapSettings.bindPassword.getOrElse(""), + ldapSettings.tls.getOrElse(false) ) match { case Some(conn) => { withConnection(conn) { conn => @@ -41,7 +45,8 @@ ldapSettings.host, ldapSettings.port.getOrElse(SystemSettingsService.DefaultLdapPort), userDN, - password + password, + ldapSettings.tls.getOrElse(false) ) match { case Some(conn) => { withConnection(conn) { conn => @@ -55,15 +60,35 @@ } } - private def bind(host: String, port: Int, dn: String, password: String): Option[LDAPConnection] = { - val conn: LDAPConnection = new LDAPConnection + private def bind(host: String, port: Int, dn: String, password: String, tls: Boolean): Option[LDAPConnection] = { + if (tls) { + // Dynamically set Sun as the security provider + Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider()) + } + + val conn: LDAPConnection = new LDAPConnection(new LDAPJSSEStartTLSFactory()) try { + // Connect to the server conn.connect(host, port) + + if (tls) { + // Secure the connection + conn.startTLS() + } + + // Bind to the server conn.bind(LDAP_VERSION, dn, password.getBytes) + Some(conn) } catch { case e: Exception => { - if (conn.isConnected) conn.disconnect() + // Provide more information if something goes wrong + logger.info("" + e) + + if (conn.isConnected) { + conn.disconnect() + } + None } } diff --git a/src/main/twirl/admin/system.scala.html b/src/main/twirl/admin/system.scala.html index 361138d..6344943 100644 --- a/src/main/twirl/admin/system.scala.html +++ b/src/main/twirl/admin/system.scala.html @@ -94,6 +94,13 @@ +
+
+ +
+