IPA authentication working.
[lgpl/argeo-commons.git] / org.argeo.enterprise / src / org / argeo / osgi / useradmin / UserAdminConf.java
index b3ead140c7b5aa641418d5ec54ca204ed853f585..ec41978dc3c441cb7f47ddc52cc392b902c23ca5 100644 (file)
@@ -1,24 +1,18 @@
 package org.argeo.osgi.useradmin;
 
-import java.io.IOException;
 import java.net.InetAddress;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.UnknownHostException;
 import java.util.Dictionary;
-import java.util.Enumeration;
 import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
 
 import javax.naming.Context;
-import javax.naming.NamingException;
+import javax.naming.ldap.LdapName;
 
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.argeo.naming.DnsBrowser;
 import org.argeo.naming.NamingUtils;
-import org.osgi.framework.Constants;
 
 /** Properties used to configure user admins. */
 public enum UserAdminConf {
@@ -43,13 +37,16 @@ public enum UserAdminConf {
        /** Read-only source */
        readOnly(null),
 
+       /** Disabled source */
+       disabled(null),
+
        /** Authentication realm */
        realm(null);
 
        public final static String FACTORY_PID = "org.argeo.osgi.useradmin.config";
-       private final static Log log = LogFactory.getLog(UserAdminConf.class);
 
        public final static String SCHEME_LDAP = "ldap";
+       public final static String SCHEME_LDAPS = "ldaps";
        public final static String SCHEME_FILE = "file";
        public final static String SCHEME_OS = "os";
        public final static String SCHEME_IPA = "ipa";
@@ -101,22 +98,39 @@ public enum UserAdminConf {
                StringBuilder query = new StringBuilder();
 
                boolean first = true;
-               for (Enumeration<String> keys = properties.keys(); keys.hasMoreElements();) {
-                       String key = keys.nextElement();
-                       // TODO clarify which keys are relevant (list only the enum?)
-                       if (!key.equals("service.factoryPid") && !key.equals("cn") && !key.equals("dn")
-                                       && !key.equals(Constants.SERVICE_PID) && !key.startsWith("java") && !key.equals(baseDn.name())
-                                       && !key.equals(uri.name())) {
-                               if (first)
-                                       first = false;
-                               else
-                                       query.append('&');
-                               query.append(valueOf(key).name());
-                               query.append('=').append(properties.get(key).toString());
-                       }
+//             for (Enumeration<String> keys = properties.keys(); keys.hasMoreElements();) {
+//                     String key = keys.nextElement();
+//                     // TODO clarify which keys are relevant (list only the enum?)
+//                     if (!key.equals("service.factoryPid") && !key.equals("cn") && !key.equals("dn")
+//                                     && !key.equals(Constants.SERVICE_PID) && !key.startsWith("java") && !key.equals(baseDn.name())
+//                                     && !key.equals(uri.name()) && !key.equals(Constants.OBJECTCLASS)
+//                                     && !key.equals(Constants.SERVICE_ID) && !key.equals("bundle.id")) {
+//                             if (first)
+//                                     first = false;
+//                             else
+//                                     query.append('&');
+//                             query.append(valueOf(key).name());
+//                             query.append('=').append(properties.get(key).toString());
+//                     }
+//             }
+
+               keys: for (UserAdminConf key : UserAdminConf.values()) {
+                       if (key.equals(baseDn) || key.equals(uri))
+                               continue keys;
+                       Object value = properties.get(key.name());
+                       if (value == null)
+                               continue keys;
+                       if (first)
+                               first = false;
+                       else
+                               query.append('&');
+                       query.append(key.name());
+                       query.append('=').append(value.toString());
+
                }
 
-               String bDn = (String) properties.get(baseDn.name());
+               Object bDnObj = properties.get(baseDn.name());
+               String bDn = bDnObj != null ? bDnObj.toString() : null;
                try {
                        return new URI(null, null, bDn != null ? '/' + bDn : null, query.length() != 0 ? query.toString() : null,
                                        null);
@@ -131,8 +145,8 @@ public enum UserAdminConf {
                        URI u = new URI(uriStr);
                        String scheme = u.getScheme();
                        if (scheme != null && scheme.equals(SCHEME_IPA)) {
-                               u = convertIpaConfig(u);
-                               scheme = u.getScheme();
+                               return IpaUtils.convertIpaUri(u);
+//                             scheme = u.getScheme();
                        }
                        String path = u.getPath();
                        // base DN
@@ -144,10 +158,13 @@ public enum UserAdminConf {
                        if (bDn.endsWith(".ldif"))
                                bDn = bDn.substring(0, bDn.length() - ".ldif".length());
 
+                       // Normalize base DN as LDAP name
+                       bDn = new LdapName(bDn).toString();
+
                        String principal = null;
                        String credentials = null;
                        if (scheme != null)
-                               if (scheme.equals(SCHEME_LDAP) || scheme.equals("ldaps")) {
+                               if (scheme.equals(SCHEME_LDAP) || scheme.equals(SCHEME_LDAPS)) {
                                        // TODO additional checks
                                        if (u.getUserInfo() != null) {
                                                String[] userInfo = u.getUserInfo().split(":");
@@ -191,57 +208,11 @@ public enum UserAdminConf {
                }
        }
 
-       private static URI convertIpaConfig(URI uri) {
-               String path = uri.getPath();
-               String kerberosRealm;
-               if (path == null || path.length() <= 1) {
-                       kerberosRealm = kerberosDomainFromDns();
-               } else {
-                       kerberosRealm = path.substring(1);
-               }
-
-               if (kerberosRealm == null)
-                       throw new UserDirectoryException("No Kerberos domain available for " + uri);
-               try (DnsBrowser dnsBrowser = new DnsBrowser()) {
-                       String ldapHostsStr = uri.getHost();
-                       if (ldapHostsStr == null || ldapHostsStr.trim().equals("")) {
-                               List<String> ldapHosts = dnsBrowser.getSrvRecordsAsHosts("_ldap._tcp." + kerberosRealm.toLowerCase());
-                               if (ldapHosts == null || ldapHosts.size() == 0) {
-                                       throw new UserDirectoryException("Cannot configure LDAP for IPA " + uri);
-                               } else {
-                                       ldapHostsStr = ldapHosts.get(0);
-                               }
-                       }
-                       URI convertedUri = new URI(
-                                       SCHEME_LDAP + "://" + ldapHostsStr + "/" + IpaUtils.domainToUserDirectoryConfigPath(kerberosRealm));
-                       if (log.isDebugEnabled())
-                               log.debug("Converted " + uri + " to " + convertedUri);
-                       return convertedUri;
-               } catch (NamingException | IOException | URISyntaxException e) {
-                       throw new UserDirectoryException("cannot convert IPA uri " + uri, e);
-               }
-       }
-
-       private static String kerberosDomainFromDns() {
-               String kerberosDomain;
-               try (DnsBrowser dnsBrowser = new DnsBrowser()) {
-                       InetAddress localhost = InetAddress.getLocalHost();
-                       String hostname = localhost.getHostName();
-                       String dnsZone = hostname.substring(hostname.indexOf('.') + 1);
-                       kerberosDomain = dnsBrowser.getRecord("_kerberos." + dnsZone, "TXT");
-                       return kerberosDomain;
-               } catch (Exception e) {
-                       throw new UserDirectoryException("Cannot determine Kerberos domain from DNS", e);
-               }
-
-       }
-
        private static String getBaseDnFromHostname() {
                String hostname;
                try {
                        hostname = InetAddress.getLocalHost().getHostName();
                } catch (UnknownHostException e) {
-                       log.warn("Using localhost as hostname", e);
                        hostname = "localhost.localdomain";
                }
                int dotIdx = hostname.indexOf('.');
@@ -254,4 +225,15 @@ public enum UserAdminConf {
                        return "dc=" + hostname;
                }
        }
+
+       /**
+        * Hash the base DN in order to have a deterministic string to be used as a cn
+        * for the underlying user directory.
+        */
+       public static String baseDnHash(Dictionary<String, Object> properties) {
+               String bDn = (String) properties.get(baseDn.name());
+               if (bDn == null)
+                       throw new UserDirectoryException("No baseDn in " + properties);
+               return DigestUtils.sha1str(bDn);
+       }
 }