DIRKRB-677 Add LDAP plugin for new authentication mechanism. Contributed by Songjun.
diff --git a/has-project/has-plugins/pom.xml b/has-project/has-plugins/pom.xml
index bc524ae..2d0a268 100644
--- a/has-project/has-plugins/pom.xml
+++ b/has-project/has-plugins/pom.xml
@@ -38,6 +38,12 @@
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
+
+ <dependency>
+ <groupId>org.ini4j</groupId>
+ <artifactId>ini4j</artifactId>
+ <version>0.5.4</version>
+ </dependency>
</dependencies>
</project>
\ No newline at end of file
diff --git a/has-project/has-plugins/src/main/java/org/apache/kerby/has/plugins/client/ldap/LDAPClientPlugin.java b/has-project/has-plugins/src/main/java/org/apache/kerby/has/plugins/client/ldap/LDAPClientPlugin.java
new file mode 100755
index 0000000..dffab6e
--- /dev/null
+++ b/has-project/has-plugins/src/main/java/org/apache/kerby/has/plugins/client/ldap/LDAPClientPlugin.java
@@ -0,0 +1,96 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.kerby.has.plugins.client.ldap;
+
+import org.apache.kerby.has.client.AbstractHasClientPlugin;
+import org.apache.kerby.has.client.HasLoginException;
+import org.apache.kerby.kerberos.kerb.type.base.AuthToken;
+import org.ini4j.Wini;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.util.Date;
+
+public class LDAPClientPlugin extends AbstractHasClientPlugin {
+ public static final Logger LOG = LoggerFactory.getLogger(LDAPClientPlugin.class);
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getLoginType() {
+ return "LDAP";
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ protected void doLogin(AuthToken authToken) throws HasLoginException {
+ String user = System.getenv("LDAP_USER");
+ String pwd = System.getenv("LDAP_PWD");
+ if (user == null || pwd == null) {
+ String ldapConfigDir = System.getenv("HAS_CONF_DIR");
+ if (ldapConfigDir == null) {
+ LOG.error("Get LDAP User/Secret failed, "
+ + "you can set them using export system environment(User/Secret),"
+ + "or export HAS_CONF_DIR which has a credential.xml file");
+ } else {
+ try {
+ String confFile = ldapConfigDir + "/ldap-client.ini";
+ Wini ini = new Wini(new File(confFile));
+ user = ini.get("user", "ldap_user");
+ pwd = ini.get("user", "ldap_pwd");
+ } catch (Exception e) {
+ LOG.error("parser ldap ini failed", e);
+ }
+
+ LOG.debug("Get LDAP User/Secret from " + ldapConfigDir
+ + "/ldap-client.ini, user:" + user);
+ }
+ } else {
+ LOG.debug("Get LDAP User/Secret from sys environment, user:" + user);
+ }
+
+ if (user == null) {
+ user = System.getProperty("user.name");
+ }
+
+ if (user == null || pwd == null) {
+ String errMsg = "Get LDAP User/Secret failed, "
+ + "you can set them using export system environment(User/Secret),"
+ + "or export HAS_CONF_DIR which has a credential.xml file";
+ LOG.error(errMsg);
+ throw new HasLoginException(errMsg);
+ }
+
+ authToken.setIssuer("has");
+
+ final Date now = new Date(new Date().getTime() / 1000 * 1000);
+ authToken.setIssueTime(now);
+ // Set expiration in 60 minutes
+ Date exp = new Date(now.getTime() + 1000 * 60 * 60);
+ authToken.setExpirationTime(exp);
+
+ authToken.addAttribute("ldap_user", user);
+ authToken.addAttribute("ldap_pwd", pwd);
+ authToken.addAttribute("passPhrase", pwd);
+ }
+
+}
diff --git a/has-project/has-plugins/src/main/java/org/apache/kerby/has/plugins/server/ldap/LDAPServerPlugin.java b/has-project/has-plugins/src/main/java/org/apache/kerby/has/plugins/server/ldap/LDAPServerPlugin.java
new file mode 100755
index 0000000..59d36d5
--- /dev/null
+++ b/has-project/has-plugins/src/main/java/org/apache/kerby/has/plugins/server/ldap/LDAPServerPlugin.java
@@ -0,0 +1,64 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.kerby.has.plugins.server.ldap;
+
+import org.apache.kerby.has.server.AbstractHasServerPlugin;
+import org.apache.kerby.has.server.HasAuthenException;
+import org.apache.kerby.kerberos.kerb.type.base.AuthToken;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class LDAPServerPlugin extends AbstractHasServerPlugin {
+ public static final Logger LOG = LoggerFactory.getLogger(LDAPServerPlugin.class);
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String getLoginType() {
+ return "LDAP";
+ }
+
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public void doAuthenticate(AuthToken userToken, AuthToken authToken) throws HasAuthenException {
+
+ String user = (String) userToken.getAttributes().get("ldap_user");
+ String pwd = (String) userToken.getAttributes().get("ldap_pwd");
+ if (user == null || pwd == null) {
+ LOG.error("LDAP: user or pwd is null");
+ throw new HasAuthenException("LDAP: user or pwd is null");
+ }
+
+ try {
+ if (LDAPUtils.doUserAuth(user, pwd)) {
+ authToken.setIssuer(userToken.getIssuer());
+ authToken.setSubject(user);
+ authToken.setExpirationTime(userToken.getExpiredTime());
+ authToken.addAttribute("passPhrase", pwd);
+ } else {
+ throw new HasAuthenException("LDAP do user auth failed");
+ }
+ } catch (Exception e) {
+ throw new HasAuthenException("LDAP do user auth failed", e);
+ }
+ }
+}
diff --git a/has-project/has-plugins/src/main/java/org/apache/kerby/has/plugins/server/ldap/LDAPUtils.java b/has-project/has-plugins/src/main/java/org/apache/kerby/has/plugins/server/ldap/LDAPUtils.java
new file mode 100644
index 0000000..300fb2e
--- /dev/null
+++ b/has-project/has-plugins/src/main/java/org/apache/kerby/has/plugins/server/ldap/LDAPUtils.java
@@ -0,0 +1,92 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.kerby.has.plugins.server.ldap;
+
+import org.apache.kerby.has.plugins.server.ldap.conf.LDAPServerConf;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.naming.Context;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.InitialDirContext;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.Map;
+
+public class LDAPUtils {
+ public static final Logger LOG = LoggerFactory.getLogger(LDAPUtils.class);
+
+ private static String ldapServerConfDir = "/etc/has/";
+ private static LDAPServerConf ldapServerConf = null;
+ static {
+ try {
+ ldapServerConf = new LDAPServerConf(ldapServerConfDir);
+ } catch (Exception e) {
+ LOG.error("load conf failed,", e);
+ }
+ }
+
+ public static boolean doUserAuth(String user, String pwd) throws NamingException {
+ Map env = new HashMap<>();
+ env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
+ env.put(Context.PROVIDER_URL, ldapServerConf.getLdapUrl());
+ env.put(Context.SECURITY_AUTHENTICATION, "simple");
+ env.put(Context.SECURITY_PRINCIPAL, ldapServerConf.getBindDN());
+ env.put(Context.SECURITY_CREDENTIALS, ldapServerConf.getBindPwd());
+ DirContext ctx = null;
+
+ boolean ret = false;
+ try {
+ ctx = new InitialDirContext(new Hashtable<>(env));
+ SearchControls ctls = new SearchControls();
+ ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
+ ctls.setReturningAttributes(new String[0]);
+ ctls.setReturningObjFlag(true);
+
+ String filter = String.format("(&(%s)(%s={0}))",
+ ldapServerConf.getUserFilter(), ldapServerConf.getUserNameAttr());
+ NamingEnumeration enm = ctx.search(
+ ldapServerConf.getBaseDN(), filter, new String[]{user}, ctls);
+ String dn = null;
+ if (enm.hasMore()) {
+ SearchResult result = (SearchResult) enm.next();
+ dn = result.getNameInNamespace();
+ System.out.println("dn: " + dn);
+ }
+ if (dn == null || enm.hasMore()) {
+ throw new NamingException("Duplication user, Authentication failed");
+ }
+ ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, dn);
+ ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, pwd);
+ ctx.lookup(dn);
+ enm.close();
+
+ ret = true;
+ } catch (NamingException e) {
+ System.out.println(e.getMessage());
+ } finally {
+ ctx.close();
+ }
+
+ return ret;
+ }
+}
diff --git a/has-project/has-plugins/src/main/java/org/apache/kerby/has/plugins/server/ldap/conf/LDAPServerConf.java b/has-project/has-plugins/src/main/java/org/apache/kerby/has/plugins/server/ldap/conf/LDAPServerConf.java
new file mode 100644
index 0000000..134711f
--- /dev/null
+++ b/has-project/has-plugins/src/main/java/org/apache/kerby/has/plugins/server/ldap/conf/LDAPServerConf.java
@@ -0,0 +1,95 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.kerby.has.plugins.server.ldap.conf;
+
+import org.ini4j.Wini;
+
+import java.io.File;
+
+public class LDAPServerConf {
+
+ private String userFilter = "objectclass=*";
+ private String userNameAttr = "sn";
+ private String ldapUrl = null;
+ private String baseDN = null;
+ private String bindDN = null;
+ private String bindPwd = null;
+
+ public LDAPServerConf(String confDir) throws Exception {
+ if (confDir == null) {
+ throw new RuntimeException("ldap server conf dir is null");
+ }
+
+ String confFile = confDir + "/ldap-server.ini";
+ Wini ini = new Wini(new File(confFile));
+ userFilter = ini.get("users", "user_filter");
+ userNameAttr = ini.get("users", "user_name_attr");
+ ldapUrl = ini.get("ldap", "ldap_url");
+ baseDN = ini.get("ldap", "base_dn");
+ bindDN = ini.get("ldap", "bind_dn");
+ bindPwd = ini.get("ldap", "bind_password");
+ }
+
+ public String getUserFilter() {
+ return userFilter;
+ }
+
+ public void setUserFilter(String userFilter) {
+ this.userFilter = userFilter;
+ }
+
+ public String getUserNameAttr() {
+ return userNameAttr;
+ }
+
+ public void setUserNameAttr(String userNameAttr) {
+ this.userNameAttr = userNameAttr;
+ }
+
+ public String getLdapUrl() {
+ return ldapUrl;
+ }
+
+ public void setLdapUrl(String ldapUrl) {
+ this.ldapUrl = ldapUrl;
+ }
+
+ public String getBaseDN() {
+ return baseDN;
+ }
+
+ public void setBaseDN(String baseDN) {
+ this.baseDN = baseDN;
+ }
+
+ public String getBindDN() {
+ return bindDN;
+ }
+
+ public void setBindDN(String bindDN) {
+ this.bindDN = bindDN;
+ }
+
+ public String getBindPwd() {
+ return bindPwd;
+ }
+
+ public void setBindPwd(String bindPwd) {
+ this.bindPwd = bindPwd;
+ }
+}
diff --git a/has-project/has-plugins/src/main/resources/META-INF/services/org.apache.kerby.has.client.HasClientPlugin b/has-project/has-plugins/src/main/resources/META-INF/services/org.apache.kerby.has.client.HasClientPlugin
index cc3cac3..25382fc 100644
--- a/has-project/has-plugins/src/main/resources/META-INF/services/org.apache.kerby.has.client.HasClientPlugin
+++ b/has-project/has-plugins/src/main/resources/META-INF/services/org.apache.kerby.has.client.HasClientPlugin
@@ -14,3 +14,4 @@
# limitations under the License.
org.apache.kerby.has.plugins.client.mysql.MySQLHasClientPlugin
+org.apache.kerby.has.plugins.client.ldap.LDAPClientPlugin
diff --git a/has-project/has-plugins/src/main/resources/META-INF/services/org.apache.kerby.has.server.HasServerPlugin b/has-project/has-plugins/src/main/resources/META-INF/services/org.apache.kerby.has.server.HasServerPlugin
index dfb9637..a7757ba 100644
--- a/has-project/has-plugins/src/main/resources/META-INF/services/org.apache.kerby.has.server.HasServerPlugin
+++ b/has-project/has-plugins/src/main/resources/META-INF/services/org.apache.kerby.has.server.HasServerPlugin
@@ -14,3 +14,4 @@
# limitations under the License.
org.apache.kerby.has.plugins.server.mysql.MySQLHasServerPlugin
+org.apache.kerby.has.plugins.server.ldap.LDAPServerPlugin
diff --git a/has-project/has-plugins/src/main/resources/ldap-client.ini b/has-project/has-plugins/src/main/resources/ldap-client.ini
new file mode 100644
index 0000000..888e27a
--- /dev/null
+++ b/has-project/has-plugins/src/main/resources/ldap-client.ini
@@ -0,0 +1,3 @@
+[ user ]
+ ldap_user=test
+ ldap_pwd=123456
\ No newline at end of file