From: Mathieu Baudier Date: Tue, 1 Nov 2016 15:18:18 +0000 (+0000) Subject: Introduce IPA support. X-Git-Tag: argeo-commons-2.1.51~19 X-Git-Url: https://git.argeo.org/?a=commitdiff_plain;h=a2ad417ed1d0219ac29d70ae985939764c13ce38;p=lgpl%2Fargeo-commons.git Introduce IPA support. git-svn-id: https://svn.argeo.org/commons/trunk@9301 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- diff --git a/org.argeo.cms.ui/src/org/argeo/cms/util/LoginEntryPoint.java b/org.argeo.cms.ui/src/org/argeo/cms/util/LoginEntryPoint.java index 1f46f100e..6b26b3728 100644 --- a/org.argeo.cms.ui/src/org/argeo/cms/util/LoginEntryPoint.java +++ b/org.argeo.cms.ui/src/org/argeo/cms/util/LoginEntryPoint.java @@ -2,7 +2,6 @@ package org.argeo.cms.util; import java.util.Locale; -import javax.security.auth.login.CredentialNotFoundException; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; import javax.servlet.http.HttpServletRequest; @@ -38,25 +37,13 @@ public class LoginEntryPoint implements EntryPoint, CmsView { // try pre-auth loginContext = new LoginContext(NodeConstants.LOGIN_CONTEXT_USER, loginShell); loginContext.login(); - } catch (CredentialNotFoundException e) { + } catch (LoginException e) { loginShell.createUi(); loginShell.open(); while (!loginShell.getShell().isDisposed()) { - // try { if (!display.readAndDispatch()) display.sleep(); - // } catch (Exception e1) { - // try { - // Thread.sleep(3000); - // } catch (InterruptedException e2) { - // // silent - // } - // ErrorFeedback.show("Login failed", e1); - // return -1; - // } } - } catch (LoginException e) { - throw new CmsException("Cannot log in", e); } if (CurrentUser.getUsername() == null) @@ -76,8 +63,6 @@ public class LoginEntryPoint implements EntryPoint, CmsView { protected HttpServletRequest getRequest() { return RWT.getRequest(); } - - protected CmsLoginShell createCmsLoginShell() { return new CmsLoginShell(this) { @@ -132,19 +117,6 @@ public class LoginEntryPoint implements EntryPoint, CmsView { throw new CmsException("Cannot log out", e); } } - - - - // @Override - // public final Subject getSubject() { - // return subject; - // } - -// @Override -// public void registerCallbackHandler(CallbackHandler callbackHandler) { -// throw new UnsupportedOperationException(); -// -// } @Override public void exception(Throwable e) { @@ -167,5 +139,4 @@ public class LoginEntryPoint implements EntryPoint, CmsView { public UxContext getUxContext() { return uxContext; } - -} +} \ No newline at end of file diff --git a/org.argeo.cms/src/org/argeo/cms/auth/AuthConstants.java b/org.argeo.cms/src/org/argeo/cms/auth/AuthConstants.java index 113e0830c..a5a2d49d4 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/AuthConstants.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/AuthConstants.java @@ -3,8 +3,11 @@ package org.argeo.cms.auth; import org.argeo.node.NodeConstants; /** Public properties of the CMS Kernel */ -@Deprecated interface AuthConstants { + + static final String SHARED_STATE_USERNAME = "javax.security.auth.login.name"; + static final String SHARED_STATE_PASSWORD = "javax.security.auth.login.password"; + // LOGIN CONTEXTS /** * @deprecated Use {@link NodeConstants#LOGIN_CONTEXT_USER} instead diff --git a/org.argeo.cms/src/org/argeo/cms/auth/AuthenticatingUser.java b/org.argeo.cms/src/org/argeo/cms/auth/AuthenticatingUser.java new file mode 100644 index 000000000..814c87567 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/auth/AuthenticatingUser.java @@ -0,0 +1,87 @@ +package org.argeo.cms.auth; + +import java.nio.ByteBuffer; +import java.nio.CharBuffer; +import java.nio.charset.Charset; +import java.util.Arrays; +import java.util.Dictionary; +import java.util.Hashtable; + +import javax.naming.ldap.LdapName; + +import org.osgi.service.useradmin.User; + +/** + * A special user type used during authentication in order to provide the + * credentials required for scoping the user admin. + */ +class AuthenticatingUser implements User { + private final String name; + private final Dictionary credentials; + + public AuthenticatingUser(LdapName name) { + this.name = name.toString(); + this.credentials = new Hashtable<>(); + } + + public AuthenticatingUser(String name, Dictionary credentials) { + this.name = name; + this.credentials = credentials; + } + + public AuthenticatingUser(String name, char[] password) { + this.name = name; + credentials = new Hashtable<>(); + credentials.put(AuthConstants.SHARED_STATE_USERNAME, name); + byte[] pwd = charsToBytes(password); + credentials.put(AuthConstants.SHARED_STATE_PASSWORD, pwd); + } + + @Override + public String getName() { + return name; + } + + @Override + public int getType() { + return User.USER; + } + + @SuppressWarnings("rawtypes") + @Override + public Dictionary getProperties() { + throw new UnsupportedOperationException(); + } + + @SuppressWarnings("rawtypes") + @Override + public Dictionary getCredentials() { + return credentials; + } + + @Override + public boolean hasCredential(String key, Object value) { + throw new UnsupportedOperationException(); + } + + + static byte[] charsToBytes(char[] chars) { + CharBuffer charBuffer = CharBuffer.wrap(chars); + ByteBuffer byteBuffer = Charset.forName("UTF-8").encode(charBuffer); + byte[] bytes = Arrays.copyOfRange(byteBuffer.array(), byteBuffer.position(), byteBuffer.limit()); + Arrays.fill(charBuffer.array(), '\u0000'); // clear sensitive data + Arrays.fill(byteBuffer.array(), (byte) 0); // clear sensitive data + return bytes; + } + + static char[] bytesToChars(byte[] bytes) { + ByteBuffer byteBuffer = ByteBuffer.wrap(bytes); + CharBuffer charBuffer = Charset.forName("UTF-8").decode(byteBuffer); + char[] chars = Arrays.copyOfRange(charBuffer.array(), charBuffer.position(), charBuffer.limit()); + Arrays.fill(charBuffer.array(), '\u0000'); // clear sensitive data + Arrays.fill(byteBuffer.array(), (byte) 0); // clear sensitive data + return chars; + } + + +} diff --git a/org.argeo.cms/src/org/argeo/cms/auth/IpaLoginModule.java b/org.argeo.cms/src/org/argeo/cms/auth/IpaLoginModule.java new file mode 100644 index 000000000..3ed485619 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/auth/IpaLoginModule.java @@ -0,0 +1,98 @@ +package org.argeo.cms.auth; + +import java.security.PrivilegedAction; +import java.util.Map; +import java.util.Set; + +import javax.naming.InvalidNameException; +import javax.naming.ldap.LdapName; +import javax.security.auth.Subject; +import javax.security.auth.callback.CallbackHandler; +import javax.security.auth.kerberos.KerberosPrincipal; +import javax.security.auth.login.LoginException; +import javax.security.auth.spi.LoginModule; + +import org.argeo.cms.CmsException; +import org.argeo.naming.LdapAttrs; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.osgi.service.useradmin.Authorization; +import org.osgi.service.useradmin.UserAdmin; + +public class IpaLoginModule implements LoginModule { + private BundleContext bc; + private Subject subject; + + @Override + public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, + Map options) { + this.subject = subject; + try { + bc = FrameworkUtil.getBundle(IpaLoginModule.class).getBundleContext(); + assert bc != null; + } catch (Exception e) { + throw new CmsException("Cannot initialize login module", e); + } + } + + @Override + public boolean login() throws LoginException { + return true; + } + + @Override + public boolean commit() throws LoginException { + UserAdmin userAdmin = bc.getService(bc.getServiceReference(UserAdmin.class)); + Authorization authorization = null; + Set kerberosPrincipals = subject.getPrincipals(KerberosPrincipal.class); + if (kerberosPrincipals.isEmpty()) { + authorization = userAdmin.getAuthorization(null); + } else { + KerberosPrincipal kerberosPrincipal = kerberosPrincipals.iterator().next(); + LdapName dn = kerberosToIpa(kerberosPrincipal); + AuthenticatingUser authenticatingUser = new AuthenticatingUser(dn); + authorization = Subject.doAs(subject, new PrivilegedAction() { + + @Override + public Authorization run() { + Authorization authorization = userAdmin.getAuthorization(authenticatingUser); + return authorization; + } + + }); + } + if (authorization == null) + return false; + CmsAuthUtils.addAuthentication(subject, authorization); + return true; + } + + private LdapName kerberosToIpa(KerberosPrincipal kerberosPrincipal) { + String[] kname = kerberosPrincipal.getName().split("@"); + String username = kname[0]; + String[] dcs = kname[1].split("\\."); + StringBuilder sb = new StringBuilder(); + for (String dc : dcs) { + sb.append(',').append(LdapAttrs.dc.name()).append('=').append(dc.toLowerCase()); + } + String dn = LdapAttrs.uid + "=" + username + ",cn=users,cn=accounts" + sb; + try { + return new LdapName(dn); + } catch (InvalidNameException e) { + throw new CmsException("Badly formatted name for " + kerberosPrincipal + ": " + dn); + } + } + + @Override + public boolean abort() throws LoginException { + // TODO Auto-generated method stub + return false; + } + + @Override + public boolean logout() throws LoginException { + // TODO Auto-generated method stub + return false; + } + +} diff --git a/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java b/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java index 243eb0fec..f5883a54f 100644 --- a/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java +++ b/org.argeo.cms/src/org/argeo/cms/auth/UserAdminLoginModule.java @@ -74,8 +74,10 @@ public class UserAdminLoginModule implements LoginModule { if (sharedState.containsKey(CmsAuthUtils.SHARED_STATE_NAME) && sharedState.containsKey(CmsAuthUtils.SHARED_STATE_PWD)) { username = (String) sharedState.get(CmsAuthUtils.SHARED_STATE_NAME); - password = (char[]) sharedState.get(CmsAuthUtils.SHARED_STATE_NAME); + password = (char[]) sharedState.get(CmsAuthUtils.SHARED_STATE_PWD); // TODO locale? + AuthenticatingUser authenticatingUser = new AuthenticatingUser(username, password); + authorization = userAdmin.getAuthorization(authenticatingUser); } else { // ask for username and password @@ -114,24 +116,23 @@ public class UserAdminLoginModule implements LoginModule { password = passwordCallback.getPassword(); else throw new CredentialNotFoundException("No credentials provided"); + // FIXME move Argeo specific convention from user admin to here + User user = userAdmin.getUser(null, username); + if (user == null) + throw new FailedLoginException("Invalid credentials"); + if (!user.hasCredential(null, password)) + throw new FailedLoginException("Invalid credentials"); + // return false; + + // Log and monitor new login + // if (log.isDebugEnabled()) + // log.debug("Logged in to CMS with username [" + username + + // "]"); + + authorization = userAdmin.getAuthorization(user); + assert authorization != null; } - // FIXME move Argeo specific convention from user admin to here - User user = userAdmin.getUser(null, username); - if (user == null) - throw new FailedLoginException("Invalid credentials"); - if (!user.hasCredential(null, password)) - throw new FailedLoginException("Invalid credentials"); - // return false; - - // Log and monitor new login - // if (log.isDebugEnabled()) - // log.debug("Logged in to CMS with username [" + username + - // "]"); - - authorization = userAdmin.getAuthorization(user); - assert authorization != null; - // } // if // (!sharedState.containsKey(CmsAuthUtils.SHARED_STATE_AUTHORIZATION)) diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/Activator.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/Activator.java index 7dd668c38..51a4cc7a5 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/Activator.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/Activator.java @@ -8,6 +8,8 @@ import java.util.Dictionary; import java.util.List; import java.util.Locale; +import javax.security.auth.login.Configuration; + import org.argeo.cms.CmsException; import org.argeo.node.ArgeoLogger; import org.argeo.node.NodeConstants; @@ -44,9 +46,9 @@ public class Activator implements BundleActivator { this.logReaderService = getService(LogReaderService.class); // this.configurationAdmin = getService(ConfigurationAdmin.class); - initSecurity();// must be first - initArgeoLogger(); try { + initSecurity();// must be first + initArgeoLogger(); initNode(); } catch (Exception e) { e.printStackTrace(); @@ -55,10 +57,10 @@ public class Activator implements BundleActivator { } private void initSecurity() { - URL url = getClass().getClassLoader().getResource( - KernelConstants.JAAS_CONFIG); - System.setProperty("java.security.auth.login.config", - url.toExternalForm()); + URL url = getClass().getClassLoader().getResource(KernelConstants.JAAS_CONFIG); +// URL url = getClass().getClassLoader().getResource(KernelConstants.JAAS_CONFIG_IPA); + System.setProperty("java.security.auth.login.config", url.toExternalForm()); + Configuration.getConfiguration(); } private void initArgeoLogger() { @@ -77,8 +79,7 @@ public class Activator implements BundleActivator { Files.write(stateUuidPath, stateUuid.getBytes()); } nodeState = new CmsState(stateUuid); - Dictionary regProps = LangUtils.dico( - Constants.SERVICE_PID, NodeConstants.NODE_STATE_PID); + Dictionary regProps = LangUtils.dico(Constants.SERVICE_PID, NodeConstants.NODE_STATE_PID); regProps.put(NodeConstants.CN, stateUuid); bc.registerService(NodeState.class, nodeState, regProps); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelConstants.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelConstants.java index 5fc138d4d..4ed9e4efd 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelConstants.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelConstants.java @@ -18,6 +18,7 @@ public interface KernelConstants { // Security // String DEFAULT_SECURITY_KEY = "argeo"; String JAAS_CONFIG = "/org/argeo/cms/internal/kernel/jaas.cfg"; + String JAAS_CONFIG_IPA = "/org/argeo/cms/internal/kernel/jaas-ipa.cfg"; // String LOGIN_CONTEXT_KERNEL = "KERNEL"; // String LOGIN_CONTEXT_HARDENED_KERNEL = "HARDENED_KERNEL"; diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelUtils.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelUtils.java index d9e09bba3..8f736d0a3 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelUtils.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/KernelUtils.java @@ -109,7 +109,6 @@ class KernelUtils implements KernelConstants { } // Security - @Deprecated static Subject anonymousLogin() { Subject subject = new Subject(); LoginContext lc; diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeLogger.java b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeLogger.java index 5fa0d07cd..14d88144d 100644 --- a/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeLogger.java +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/NodeLogger.java @@ -150,7 +150,8 @@ class NodeLogger implements ArgeoLogger, LogListener { } private String msg(LogEntry status) { - StringBuilder sb = new StringBuilder(status.getMessage()); + StringBuilder sb = new StringBuilder(); + sb.append(status.getMessage()); ServiceReference sr = status.getServiceReference(); if (sr != null) { sb.append(' '); diff --git a/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas-ipa.cfg b/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas-ipa.cfg new file mode 100644 index 000000000..33c556f57 --- /dev/null +++ b/org.argeo.cms/src/org/argeo/cms/internal/kernel/jaas-ipa.cfg @@ -0,0 +1,20 @@ +USER { + com.sun.security.auth.module.Krb5LoginModule required clearPass=true; + org.argeo.cms.auth.IpaLoginModule requisite; +}; + +ANONYMOUS { + org.argeo.cms.auth.UserAdminLoginModule requisite anonymous=true; +}; + +DATA_ADMIN { + org.argeo.cms.auth.DataAdminLoginModule requisite; +}; + +KEYRING { + org.argeo.cms.auth.KeyringLoginModule required; +}; + +Jackrabbit { + org.argeo.security.jackrabbit.SystemJackrabbitLoginModule requisite; +}; diff --git a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java index 5e7cbc61c..f76f49d51 100644 --- a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java +++ b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/AbstractUserDirectory.java @@ -46,7 +46,7 @@ public abstract class AbstractUserDirectory implements UserAdmin, UserDirectory private final static Log log = LogFactory.getLog(AbstractUserDirectory.class); private final Hashtable properties; - private final LdapName baseDn; + private final LdapName baseDn, userBaseDn, groupBaseDn; private final String userObjectClass, userBase, groupObjectClass, groupBase; private final boolean readOnly; @@ -80,8 +80,14 @@ public abstract class AbstractUserDirectory implements UserAdmin, UserDirectory throw new UserDirectoryException("Badly formatted URI " + uriStr, e); } + userObjectClass = UserAdminConf.userObjectClass.getValue(properties); + userBase = UserAdminConf.userBase.getValue(properties); + groupObjectClass = UserAdminConf.groupObjectClass.getValue(properties); + groupBase = UserAdminConf.groupBase.getValue(properties); try { baseDn = new LdapName(UserAdminConf.baseDn.getValue(properties)); + userBaseDn = new LdapName(userBase + "," + baseDn); + groupBaseDn = new LdapName(groupBase + "," + baseDn); } catch (InvalidNameException e) { throw new UserDirectoryException("Badly formated base DN " + UserAdminConf.baseDn.getValue(properties), e); } @@ -91,11 +97,6 @@ public abstract class AbstractUserDirectory implements UserAdmin, UserDirectory properties.put(UserAdminConf.readOnly.name(), Boolean.toString(readOnly)); } else readOnly = new Boolean(readOnlyStr); - - userObjectClass = UserAdminConf.userObjectClass.getValue(properties); - userBase = UserAdminConf.userBase.getValue(properties); - groupObjectClass = UserAdminConf.groupObjectClass.getValue(properties); - groupBase = UserAdminConf.groupBase.getValue(properties); } /** Returns the groups this user is a direct member of. */ @@ -397,9 +398,13 @@ public abstract class AbstractUserDirectory implements UserAdmin, UserDirectory return externalRoles; } - public LdapName getBaseDn() { - // always clone so that the property is not modified by reference - return (LdapName) baseDn.clone(); + protected int roleType(LdapName dn) { + if (dn.startsWith(groupBaseDn)) + return Role.GROUP; + else if (dn.startsWith(userBaseDn)) + return Role.USER; + else + return Role.GROUP; } /** dn can be null, in that case a default should be returned. */ @@ -423,6 +428,10 @@ public abstract class AbstractUserDirectory implements UserAdmin, UserDirectory return groupBase; } + public LdapName getBaseDn() { + return (LdapName) baseDn.clone(); + } + public Dictionary getProperties() { return properties; } diff --git a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/LdapUserAdmin.java b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/LdapUserAdmin.java index 000cfab0c..456342e04 100644 --- a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/LdapUserAdmin.java +++ b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/LdapUserAdmin.java @@ -26,6 +26,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.argeo.naming.LdapAttrs; import org.osgi.framework.Filter; +import org.osgi.service.useradmin.Role; import org.osgi.service.useradmin.User; /** @@ -49,7 +50,11 @@ public class LdapUserAdmin extends AbstractUserDirectory { // StartTlsResponse tls = (StartTlsResponse) ctx // .extendedOperation(new StartTlsRequest()); // tls.negotiate(); - initialLdapContext.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple"); + Object securityAuthentication = properties.get(Context.SECURITY_AUTHENTICATION); + if (securityAuthentication != null) + initialLdapContext.addToEnvironment(Context.SECURITY_AUTHENTICATION, securityAuthentication); + else + initialLdapContext.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple"); Object principal = properties.get(Context.SECURITY_PRINCIPAL); if (principal != null) { initialLdapContext.addToEnvironment(Context.SECURITY_PRINCIPAL, principal.toString()); @@ -59,10 +64,6 @@ public class LdapUserAdmin extends AbstractUserDirectory { } } - // initialLdapContext.addToEnvironment(Context.SECURITY_PRINCIPAL, - // "uid=admin,ou=system"); - // initialLdapContext.addToEnvironment(Context.SECURITY_CREDENTIALS, - // "secret"); } catch (Exception e) { throw new UserDirectoryException("Cannot connect to LDAP", e); } @@ -76,19 +77,21 @@ public class LdapUserAdmin extends AbstractUserDirectory { log.error("Cannot destroy LDAP user admin", e); } } - - @SuppressWarnings("unchecked") @Override protected AbstractUserDirectory scope(User user) { Dictionary credentials = user.getCredentials(); // FIXME use arrays - Object usernameObj = credentials.get(SHARED_STATE_USERNAME); - Object passwordObj = credentials.get(SHARED_STATE_PASSWORD); + String username = (String) credentials.get(SHARED_STATE_USERNAME); + if (username == null) + username = user.getName(); + // byte[] pwd = (byte[]) credentials.get(SHARED_STATE_PASSWORD); + // char[] password = DigestUtils.bytesToChars(pwd); Dictionary properties = cloneProperties(); - properties.put(Context.SECURITY_PRINCIPAL, usernameObj.toString()); - properties.put(Context.SECURITY_CREDENTIALS, passwordObj.toString()); + properties.put(Context.SECURITY_PRINCIPAL, username.toString()); + // properties.put(Context.SECURITY_CREDENTIALS, password); + properties.put(Context.SECURITY_AUTHENTICATION, "GSSAPI"); return new LdapUserAdmin(properties); } @@ -107,15 +110,17 @@ public class LdapUserAdmin extends AbstractUserDirectory { Attributes attrs = getLdapContext().getAttributes(name); if (attrs.size() == 0) return null; + int roleType = roleType(name); LdifUser res; - if (attrs.get(objectClass.name()).contains(getGroupObjectClass())) + if (roleType == Role.GROUP) res = new LdifGroup(this, name, attrs); - else if (attrs.get(objectClass.name()).contains(getUserObjectClass())) + else if (roleType == Role.USER) res = new LdifUser(this, name, attrs); else throw new UserDirectoryException("Unsupported LDAP type for " + name); return res; } catch (NamingException e) { + log.error("Cannot get role: "+e.getMessage()); return null; } } diff --git a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/UserAdminConf.java b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/UserAdminConf.java index 316941ea8..eef527b00 100644 --- a/org.argeo.enterprise/src/org/argeo/osgi/useradmin/UserAdminConf.java +++ b/org.argeo.enterprise/src/org/argeo/osgi/useradmin/UserAdminConf.java @@ -127,9 +127,11 @@ public enum UserAdminConf { if (scheme != null) if (scheme.equals("ldap") || scheme.equals("ldaps")) { // TODO additional checks - String[] userInfo = u.getUserInfo().split(":"); - principal = userInfo.length > 0 ? userInfo[0] : null; - credentials = userInfo.length > 1 ? userInfo[1] : null; + if (u.getUserInfo() != null) { + String[] userInfo = u.getUserInfo().split(":"); + principal = userInfo.length > 0 ? userInfo[0] : null; + credentials = userInfo.length > 1 ? userInfo[1] : null; + } } else if (scheme.equals("file")) { } else throw new UserDirectoryException("Unsupported scheme " + scheme);