Set<User> collectedUsers = new HashSet<>();
// try dn
User user = null;
+ user = null;
// try all indexes
for (String attr : indexedUserProperties) {
user = userAdmin.getUser(attr, providedUsername);
@Override
public void updated(String pid, Dictionary<String, ?> properties) throws ConfigurationException {
String uri = (String) properties.get(UserAdminConf.uri.name());
+ Object realm = properties.get(UserAdminConf.realm.name());
URI u;
try {
if (uri == null) {
String baseDn = (String) properties.get(UserAdminConf.baseDn.name());
u = KernelUtils.getOsgiInstanceUri(KernelConstants.DIR_NODE + '/' + baseDn + ".ldif");
- } else
+ } else if (realm != null) {
+ u = null;
+ } else {
u = new URI(uri);
+ }
} catch (URISyntaxException e) {
throw new IllegalArgumentException("Badly formatted URI " + uri, e);
}
// Create
AbstractUserDirectory userDirectory;
- if (UserAdminConf.SCHEME_LDAP.equals(u.getScheme())) {
+ if (realm != null || UserAdminConf.SCHEME_LDAP.equals(u.getScheme())
+ || UserAdminConf.SCHEME_LDAPS.equals(u.getScheme())) {
userDirectory = new LdapUserAdmin(properties);
} else if (UserAdminConf.SCHEME_FILE.equals(u.getScheme())) {
userDirectory = new LdifUserAdmin(u, properties);
} else {
throw new IllegalArgumentException("Unsupported scheme " + u.getScheme());
}
- Object realm = userDirectory.getProperties().get(UserAdminConf.realm.name());
addUserDirectory(userDirectory);
// OSGi
pidToBaseDn.put(pid, baseDn);
// pidToServiceRegs.put(pid, reg);
- if (log.isDebugEnabled())
- log.debug("User directory " + userDirectory.getBaseDn() + " [" + u.getScheme() + "] enabled."
- + (realm != null ? " " + realm + " realm." : ""));
+ if (log.isDebugEnabled()) {
+ log.debug("User directory " + userDirectory.getBaseDn() + (u != null ? " [" + u.getScheme() + "]" : "")
+ + " enabled." + (realm != null ? " " + realm + " realm." : ""));
+ }
if (isSystemRolesBaseDn(baseDn)) {
// publishes only when system roles are available
}
/** Ordered, with preferred first. */
- public List<String> getSrvRecordsAsHosts(String name) throws NamingException {
+ public List<String> getSrvRecordsAsHosts(String name, boolean withPort) throws NamingException {
List<String> raw = getRecords(name, "SRV");
if (raw.size() == 0)
return null;
}
List<String> lst = new ArrayList<>();
for (SrvRecord order : res) {
- lst.add(order.toHost());
+ lst.add(order.toHost(withPort));
}
return Collections.unmodifiableList(lst);
}
return priority - other.priority;
if (weight != other.weight)
return other.weight - other.weight;
- String host = toHost();
- String otherHost = other.toHost();
+ String host = toHost(false);
+ String otherHost = other.toHost(false);
if (host.length() == otherHost.length())
- return toHost().compareTo(other.toHost());
+ return host.compareTo(otherHost);
else
return host.length() - otherHost.length();
}
return priority + " " + weight;
}
- public String toHost() {
+ public String toHost(boolean withPort) {
String hostStr = hostname;
if (hostname.charAt(hostname.length() - 1) == '.')
hostStr = hostname.substring(0, hostname.length() - 1);
- return hostStr + ":" + port;
+ return hostStr + (withPort ? ":" + port : "");
}
}
private final boolean readOnly;
private final boolean disabled;
- private final URI uri;
+ private final String uri;
private UserAdmin externalRoles;
// private List<String> indexedUserProperties = Arrays
// .asList(new String[] { LdapAttrs.uid.name(), LdapAttrs.mail.name(),
// LdapAttrs.cn.name() });
+ private final boolean scoped;
+
private String memberAttributeId = "member";
private List<String> credentialAttributeIds = Arrays
.asList(new String[] { LdapAttrs.userPassword.name(), LdapAttrs.authPassword.name() });
private TransactionManager transactionManager;
private WcXaResource xaResource = new WcXaResource(this);
- public AbstractUserDirectory(URI uriArg, Dictionary<String, ?> props) {
+ AbstractUserDirectory(URI uriArg, Dictionary<String, ?> props, boolean scoped) {
+ this.scoped = scoped;
properties = new Hashtable<String, Object>();
for (Enumeration<String> keys = props.keys(); keys.hasMoreElements();) {
String key = keys.nextElement();
}
if (uriArg != null) {
- uri = uriArg;
+ uri = uriArg.toString();
// uri from properties is ignored
} else {
String uriStr = UserAdminConf.uri.getValue(properties);
if (uriStr == null)
uri = null;
else
- try {
- uri = new URI(uriStr);
- } catch (URISyntaxException e) {
- throw new UserDirectoryException("Badly formatted URI " + uriStr, e);
- }
+ uri = uriStr;
}
userObjectClass = UserAdminConf.userObjectClass.getValue(properties);
Attributes attrs = user.getAttributes();
// TODO centralize attribute name
Attribute memberOf = attrs.get(LdapAttrs.memberOf.name());
- if (memberOf != null) {
+ // if user belongs to this directory, we only check meberOf
+ if (memberOf != null && user.getDn().startsWith(getBaseDn())) {
try {
NamingEnumeration<?> values = memberOf.getAll();
while (values.hasMore()) {
Object value = values.next();
LdapName groupDn = new LdapName(value.toString());
DirectoryUser group = doGetRole(groupDn);
- allRoles.add(group);
+ if (group != null)
+ allRoles.add(group);
}
} catch (Exception e) {
throw new UserDirectoryException("Cannot get memberOf groups for " + user, e);
for (LdapName groupDn : getDirectGroups(user.getDn())) {
// TODO check for loops
DirectoryUser group = doGetRole(groupDn);
- allRoles.add(group);
- collectRoles(group, allRoles);
+ if (group != null) {
+ allRoles.add(group);
+ collectRoles(group, allRoles);
+ }
}
}
}
return credentialAttributeIds;
}
- protected URI getUri() {
+ protected String getUri() {
return uri;
}
- private static boolean readOnlyDefault(URI uri) {
- if (uri == null)
+ private static boolean readOnlyDefault(String uriStr) {
+ if (uriStr == null)
return true;
+ /// TODO make it more generic
+ URI uri;
+ try {
+ uri = new URI(uriStr.split(" ")[0]);
+ } catch (URISyntaxException e) {
+ throw new IllegalArgumentException(e);
+ }
if (uri.getScheme() == null)
return false;// assume relative file to be writable
if (uri.getScheme().equals(UserAdminConf.SCHEME_FILE)) {
return xaResource;
}
+ public boolean isScoped() {
+ return scoped;
+ }
+
}
public User getUser(String key, String value) {
List<User> res = new ArrayList<User>();
for (UserAdmin userAdmin : businessRoles.values()) {
- User u = userAdmin.getUser(key, value);
- if (u != null)
- res.add(u);
+ User u = userAdmin.getUser(key, value);
+ if (u != null)
+ res.add(u);
}
// Note: node roles cannot contain users, so it is not searched
return res.size() == 1 ? res.get(0) : null;
if (user == null) {// anonymous
return systemRoles.getAuthorization(null);
}
- UserAdmin userAdmin = findUserAdmin(user.getName());
- Authorization rawAuthorization = userAdmin.getAuthorization(user);
+ AbstractUserDirectory userReferentialOfThisUser = findUserAdmin(user.getName());
+ Authorization rawAuthorization = userReferentialOfThisUser.getAuthorization(user);
String usernameToUse;
String displayNameToUse;
if (user instanceof Group) {
+ // TODO check whether this is still working
String ownerDn = TokenUtils.userDn((Group) user);
if (ownerDn != null) {// tokens
UserAdmin ownerUserAdmin = findUserAdmin(ownerDn);
usernameToUse = rawAuthorization.getName();
displayNameToUse = rawAuthorization.toString();
}
- // gather system roles
- Set<String> sysRoles = new HashSet<String>();
- for (String role : rawAuthorization.getRoles()) {
- Authorization auth = systemRoles.getAuthorization((User) userAdmin.getRole(role));
- systemRoles: for (String systemRole : auth.getRoles()) {
- if (role.equals(systemRole))
- continue systemRoles;
- sysRoles.add(systemRole);
- }
+
+ // gather roles from other referentials
+ final AbstractUserDirectory userAdminToUse;// possibly scoped when authenticating
+ if (user instanceof DirectoryUser) {
+ userAdminToUse = userReferentialOfThisUser;
+ } else if (user instanceof AuthenticatingUser) {
+ userAdminToUse = userReferentialOfThisUser.scope(user);
+ } else {
+ throw new IllegalArgumentException("Unsupported user type " + user.getClass());
+ }
+
+ try {
+ Set<String> sysRoles = new HashSet<String>();
+ for (String role : rawAuthorization.getRoles()) {
+ User userOrGroup = (User) userAdminToUse.getRole(role);
+ Authorization auth = systemRoles.getAuthorization(userOrGroup);
+ systemRoles: for (String systemRole : auth.getRoles()) {
+ if (role.equals(systemRole))
+ continue systemRoles;
+ sysRoles.add(systemRole);
+ }
// sysRoles.addAll(Arrays.asList(auth.getRoles()));
+ }
+ addAbstractSystemRoles(rawAuthorization, sysRoles);
+ Authorization authorization = new AggregatingAuthorization(usernameToUse, displayNameToUse, sysRoles,
+ rawAuthorization.getRoles());
+ return authorization;
+ } finally {
+ if (userAdminToUse != null && userAdminToUse.isScoped()) {
+ userAdminToUse.destroy();
+ }
}
- addAbstractSystemRoles(rawAuthorization, sysRoles);
- Authorization authorization = new AggregatingAuthorization(usernameToUse, displayNameToUse, sysRoles,
- rawAuthorization.getRoles());
- return authorization;
}
/**
protected void postAdd(AbstractUserDirectory userDirectory) {
}
- private UserAdmin findUserAdmin(String name) {
+// private UserAdmin findUserAdmin(User user) {
+// if (user == null)
+// throw new IllegalArgumentException("User should not be null");
+// AbstractUserDirectory userAdmin = findUserAdmin(user.getName());
+// if (user instanceof DirectoryUser) {
+// return userAdmin;
+// } else {
+// return userAdmin.scope(user);
+// }
+// }
+
+ private AbstractUserDirectory findUserAdmin(String name) {
try {
- UserAdmin userAdmin = findUserAdmin(new LdapName(name));
- return userAdmin;
+ return findUserAdmin(new LdapName(name));
} catch (InvalidNameException e) {
throw new UserDirectoryException("Badly formatted name " + name, e);
}
}
- private UserAdmin findUserAdmin(LdapName name) {
+ private AbstractUserDirectory findUserAdmin(LdapName name) {
if (name.startsWith(systemRolesBaseDn))
return systemRoles;
if (tokensBaseDn != null && name.startsWith(tokensBaseDn))
package org.argeo.osgi.useradmin;
+import java.io.IOException;
+import java.net.InetAddress;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.List;
+
import javax.naming.InvalidNameException;
+import javax.naming.NamingException;
import javax.naming.ldap.LdapName;
+import org.argeo.naming.DnsBrowser;
import org.argeo.naming.LdapAttrs;
/** Free IPA specific conventions. */
public final static String IPA_USER_DIRECTORY_CONFIG = UserAdminConf.userBase + "=" + IPA_USER_BASE + "&"
+ UserAdminConf.groupBase + "=" + IPA_GROUP_BASE + "&" + UserAdminConf.readOnly + "=true";
+ @Deprecated
static String domainToUserDirectoryConfigPath(String realm) {
return domainToBaseDn(realm) + "?" + IPA_USER_DIRECTORY_CONFIG + "&" + UserAdminConf.realm.name() + "=" + realm;
}
+ public static void addIpaConfig(String realm, Dictionary<String, Object> properties) {
+ properties.put(UserAdminConf.baseDn.name(), domainToBaseDn(realm));
+ properties.put(UserAdminConf.realm.name(), realm);
+ properties.put(UserAdminConf.userBase.name(), IPA_USER_BASE);
+ properties.put(UserAdminConf.groupBase.name(), IPA_GROUP_BASE);
+ properties.put(UserAdminConf.readOnly.name(), Boolean.TRUE.toString());
+ }
+
public static String domainToBaseDn(String domain) {
String[] dcs = domain.split("\\.");
StringBuilder sb = new StringBuilder();
private IpaUtils() {
}
+
+ public 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);
+ }
+
+ }
+
+ public static Dictionary<String, Object> convertIpaUri(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);
+ // TODO intergrate CA certificate in truststore
+ // String schemeToUse = SCHEME_LDAPS;
+ String schemeToUse = UserAdminConf.SCHEME_LDAP;
+ List<String> ldapHosts;
+ String ldapHostsStr = uri.getHost();
+ if (ldapHostsStr == null || ldapHostsStr.trim().equals("")) {
+ try (DnsBrowser dnsBrowser = new DnsBrowser()) {
+ ldapHosts = dnsBrowser.getSrvRecordsAsHosts("_ldap._tcp." + kerberosRealm.toLowerCase(),
+ schemeToUse.equals(UserAdminConf.SCHEME_LDAP) ? true : false);
+ if (ldapHosts == null || ldapHosts.size() == 0) {
+ throw new UserDirectoryException("Cannot configure LDAP for IPA " + uri);
+ } else {
+ ldapHostsStr = ldapHosts.get(0);
+ }
+ } catch (NamingException | IOException e) {
+ throw new UserDirectoryException("cannot convert IPA uri " + uri, e);
+ }
+ } else {
+ ldapHosts = new ArrayList<>();
+ ldapHosts.add(ldapHostsStr);
+ }
+
+ StringBuilder uriStr = new StringBuilder();
+ try {
+ for (String host : ldapHosts) {
+ URI convertedUri = new URI(schemeToUse + "://" + host + "/");
+ uriStr.append(convertedUri).append(' ');
+ }
+ } catch (URISyntaxException e) {
+ throw new UserDirectoryException("cannot convert IPA uri " + uri, e);
+ }
+
+ Hashtable<String, Object> res = new Hashtable<>();
+ res.put(UserAdminConf.uri.name(), uriStr.toString());
+ addIpaConfig(kerberosRealm, res);
+ return res;
+ }
}
--- /dev/null
+package org.argeo.osgi.useradmin;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import javax.naming.CommunicationException;
+import javax.naming.Context;
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
+import javax.naming.ldap.InitialLdapContext;
+import javax.naming.ldap.LdapName;
+
+import org.argeo.naming.LdapAttrs;
+
+/** A synchronized wrapper for a single {@link InitialLdapContext}. */
+// TODO implement multiple contexts and connection pooling.
+class LdapConnection {
+ private InitialLdapContext initialLdapContext = null;
+
+ LdapConnection(String url, Dictionary<String, ?> properties) {
+ try {
+ Hashtable<String, Object> connEnv = new Hashtable<String, Object>();
+ connEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
+ connEnv.put(Context.PROVIDER_URL, url);
+ connEnv.put("java.naming.ldap.attributes.binary", LdapAttrs.userPassword.name());
+ // use pooling in order to avoid connection timeout
+// connEnv.put("com.sun.jndi.ldap.connect.pool", "true");
+// connEnv.put("com.sun.jndi.ldap.connect.pool.timeout", 300000);
+
+ initialLdapContext = new InitialLdapContext(connEnv, null);
+ // StartTlsResponse tls = (StartTlsResponse) ctx
+ // .extendedOperation(new StartTlsRequest());
+ // tls.negotiate();
+ 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());
+ Object creds = properties.get(Context.SECURITY_CREDENTIALS);
+ if (creds != null) {
+ initialLdapContext.addToEnvironment(Context.SECURITY_CREDENTIALS, creds.toString());
+ }
+ }
+ } catch (Exception e) {
+ throw new UserDirectoryException("Cannot connect to LDAP", e);
+ }
+
+ }
+
+ public void init() {
+
+ }
+
+ public void destroy() {
+ try {
+ // tls.close();
+ initialLdapContext.close();
+ initialLdapContext = null;
+ } catch (NamingException e) {
+ e.printStackTrace();
+ }
+ }
+
+ protected InitialLdapContext getLdapContext() {
+ return initialLdapContext;
+ }
+
+ protected void reconnect() throws NamingException {
+ initialLdapContext.reconnect(initialLdapContext.getConnectControls());
+ }
+
+ public synchronized NamingEnumeration<SearchResult> search(LdapName searchBase, String searchFilter,
+ SearchControls searchControls) throws NamingException {
+ NamingEnumeration<SearchResult> results;
+ try {
+ results = getLdapContext().search(searchBase, searchFilter, searchControls);
+ } catch (CommunicationException e) {
+ reconnect();
+ results = getLdapContext().search(searchBase, searchFilter, searchControls);
+ }
+ return results;
+ }
+
+ public synchronized Attributes getAttributes(LdapName name) throws NamingException {
+ try {
+ return getLdapContext().getAttributes(name);
+ } catch (CommunicationException e) {
+ reconnect();
+ return getLdapContext().getAttributes(name);
+ }
+ }
+
+ synchronized void prepareChanges(UserDirectoryWorkingCopy wc) throws NamingException {
+ // make sure connection will work
+ reconnect();
+
+ // delete
+ for (LdapName dn : wc.getDeletedUsers().keySet()) {
+ if (!entryExists(dn))
+ throw new UserDirectoryException("User to delete no found " + dn);
+ }
+ // add
+ for (LdapName dn : wc.getNewUsers().keySet()) {
+ if (entryExists(dn))
+ throw new UserDirectoryException("User to create found " + dn);
+ }
+ // modify
+ for (LdapName dn : wc.getModifiedUsers().keySet()) {
+ if (!wc.getNewUsers().containsKey(dn) && !entryExists(dn))
+ throw new UserDirectoryException("User to modify not found " + dn);
+ }
+
+ }
+
+ protected boolean entryExists(LdapName dn) throws NamingException {
+ try {
+ return getAttributes(dn).size() != 0;
+ } catch (NameNotFoundException e) {
+ return false;
+ }
+ }
+
+ synchronized void commitChanges(UserDirectoryWorkingCopy wc) throws NamingException {
+ // delete
+ for (LdapName dn : wc.getDeletedUsers().keySet()) {
+ getLdapContext().destroySubcontext(dn);
+ }
+ // add
+ for (LdapName dn : wc.getNewUsers().keySet()) {
+ DirectoryUser user = wc.getNewUsers().get(dn);
+ getLdapContext().createSubcontext(dn, user.getAttributes());
+ }
+ // modify
+ for (LdapName dn : wc.getModifiedUsers().keySet()) {
+ Attributes modifiedAttrs = wc.getModifiedUsers().get(dn);
+ getLdapContext().modifyAttributes(dn, DirContext.REPLACE_ATTRIBUTE, modifiedAttrs);
+ }
+ }
+}
import java.util.ArrayList;
import java.util.Dictionary;
-import java.util.Hashtable;
import java.util.List;
+import javax.naming.AuthenticationNotSupportedException;
import javax.naming.Binding;
import javax.naming.Context;
import javax.naming.InvalidNameException;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
-import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
-import javax.naming.ldap.InitialLdapContext;
import javax.naming.ldap.LdapName;
import javax.transaction.TransactionManager;
-import org.argeo.naming.LdapAttrs;
import org.osgi.framework.Filter;
import org.osgi.service.useradmin.Role;
import org.osgi.service.useradmin.User;
* and an open transaction for write access.
*/
public class LdapUserAdmin extends AbstractUserDirectory {
- private InitialLdapContext initialLdapContext = null;
-
-// private LdapName adminUserDn = null;
-// private LdifUser adminUser = null;
+ private LdapConnection ldapConnection;
public LdapUserAdmin(Dictionary<String, ?> properties) {
- super(null, properties);
- try {
- Hashtable<String, Object> connEnv = new Hashtable<String, Object>();
- connEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
- connEnv.put(Context.PROVIDER_URL, getUri().toString());
- connEnv.put("java.naming.ldap.attributes.binary", LdapAttrs.userPassword.name());
+ this(properties, false);
+ }
- initialLdapContext = new InitialLdapContext(connEnv, null);
- // StartTlsResponse tls = (StartTlsResponse) ctx
- // .extendedOperation(new StartTlsRequest());
- // tls.negotiate();
- 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());
-// adminUserDn = new LdapName(principal.toString());
-// BasicAttributes adminUserAttrs = new BasicAttributes();
-// adminUser = new LdifUser(this, adminUserDn, adminUserAttrs);
- Object creds = properties.get(Context.SECURITY_CREDENTIALS);
- if (creds != null) {
- initialLdapContext.addToEnvironment(Context.SECURITY_CREDENTIALS, creds.toString());
-// adminUserAttrs.put(LdapAttrs.userPassword.name(), adminUser.hash(creds.toString().toCharArray()));
- }
-// adminUserAttrs.put(LdapAttrs.memberOf.name(), "cn=admin,ou=roles,ou=node");
- }
- } catch (Exception e) {
- throw new UserDirectoryException("Cannot connect to LDAP", e);
- }
+ public LdapUserAdmin(Dictionary<String, ?> properties, boolean scoped) {
+ super(null, properties, scoped);
+ ldapConnection = new LdapConnection(getUri().toString(), properties);
}
public void destroy() {
- try {
- // tls.close();
- initialLdapContext.close();
- } catch (NamingException e) {
- e.printStackTrace();
- }
+ ldapConnection.destroy();
}
@Override
} else {
properties.put(Context.SECURITY_AUTHENTICATION, "GSSAPI");
}
- return new LdapUserAdmin(properties);
+ return new LdapUserAdmin(properties, true);
}
- protected InitialLdapContext getLdapContext() {
- return initialLdapContext;
- }
+// protected InitialLdapContext getLdapContext() {
+// return initialLdapContext;
+// }
@Override
protected Boolean daoHasRole(LdapName dn) {
@Override
protected DirectoryUser daoGetRole(LdapName name) throws NameNotFoundException {
try {
- Attributes attrs = getLdapContext().getAttributes(name);
+ Attributes attrs = ldapConnection.getAttributes(name);
if (attrs.size() == 0)
return null;
int roleType = roleType(name);
throw new UserDirectoryException("Unsupported LDAP type for " + name);
return res;
} catch (NameNotFoundException e) {
-// if (adminUserDn != null && adminUserDn.equals(name)) {
-// return adminUser;
-// }
throw e;
} catch (NamingException e) {
return null;
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
LdapName searchBase = getBaseDn();
- NamingEnumeration<SearchResult> results = getLdapContext().search(searchBase, searchFilter, searchControls);
+ NamingEnumeration<SearchResult> results = ldapConnection.search(searchBase, searchFilter, searchControls);
results: while (results.hasMoreElements()) {
SearchResult searchResult = results.next();
res.add(role);
}
return res;
-// } catch (NameNotFoundException e) {
-// return res;
+ } catch (AuthenticationNotSupportedException e) {
+ // ignore (typically an unsupported anonymous bind)
+ // TODO better logging
+ return res;
} catch (Exception e) {
+ e.printStackTrace();
throw new UserDirectoryException("Cannot get roles for filter " + f, e);
}
}
searchControls.setSearchScope(SearchControls.SUBTREE_SCOPE);
LdapName searchBase = getBaseDn();
- NamingEnumeration<SearchResult> results = getLdapContext().search(searchBase, searchFilter, searchControls);
+ NamingEnumeration<SearchResult> results = ldapConnection.search(searchBase, searchFilter, searchControls);
while (results.hasMoreElements()) {
SearchResult searchResult = (SearchResult) results.nextElement();
@Override
protected void prepare(UserDirectoryWorkingCopy wc) {
try {
- getLdapContext().reconnect(getLdapContext().getConnectControls());
- // delete
- for (LdapName dn : wc.getDeletedUsers().keySet()) {
- if (!entryExists(dn))
- throw new UserDirectoryException("User to delete no found " + dn);
- }
- // add
- for (LdapName dn : wc.getNewUsers().keySet()) {
- if (entryExists(dn))
- throw new UserDirectoryException("User to create found " + dn);
- }
- // modify
- for (LdapName dn : wc.getModifiedUsers().keySet()) {
- if (!wc.getNewUsers().containsKey(dn) && !entryExists(dn))
- throw new UserDirectoryException("User to modify not found " + dn);
- }
+ ldapConnection.prepareChanges(wc);
} catch (NamingException e) {
throw new UserDirectoryException("Cannot prepare LDAP", e);
}
}
- private boolean entryExists(LdapName dn) throws NamingException {
- try {
- return getLdapContext().getAttributes(dn).size() != 0;
- } catch (NameNotFoundException e) {
- return false;
- }
- }
-
@Override
protected void commit(UserDirectoryWorkingCopy wc) {
try {
- // delete
- for (LdapName dn : wc.getDeletedUsers().keySet()) {
- getLdapContext().destroySubcontext(dn);
- }
- // add
- for (LdapName dn : wc.getNewUsers().keySet()) {
- DirectoryUser user = wc.getNewUsers().get(dn);
- getLdapContext().createSubcontext(dn, user.getAttributes());
- }
- // modify
- for (LdapName dn : wc.getModifiedUsers().keySet()) {
- Attributes modifiedAttrs = wc.getModifiedUsers().get(dn);
- getLdapContext().modifyAttributes(dn, DirContext.REPLACE_ATTRIBUTE, modifiedAttrs);
- }
+ ldapConnection.commitChanges(wc);
} catch (NamingException e) {
throw new UserDirectoryException("Cannot commit LDAP", e);
}
private SortedMap<LdapName, DirectoryGroup> groups = new TreeMap<LdapName, DirectoryGroup>();
public LdifUserAdmin(String uri, String baseDn) {
- this(fromUri(uri, baseDn));
+ this(fromUri(uri, baseDn), false);
}
public LdifUserAdmin(Dictionary<String, ?> properties) {
- super(null, properties);
+ this(properties, false);
+ }
+
+ protected LdifUserAdmin(Dictionary<String, ?> properties, boolean scoped) {
+ super(null, properties, scoped);
}
public LdifUserAdmin(URI uri, Dictionary<String, ?> properties) {
- super(uri, properties);
+ super(uri, properties, false);
}
@Override
}
Dictionary<String, Object> properties = cloneProperties();
properties.put(UserAdminConf.readOnly.name(), "true");
- LdifUserAdmin scopedUserAdmin = new LdifUserAdmin(properties);
+ LdifUserAdmin scopedUserAdmin = new LdifUserAdmin(properties, true);
scopedUserAdmin.groups = Collections.unmodifiableSortedMap(groups);
scopedUserAdmin.users = Collections.unmodifiableSortedMap(users);
return scopedUserAdmin;
}
public void init() {
+
try {
- if (getUri().getScheme().equals("file")) {
- File file = new File(getUri());
+ URI u = new URI(getUri());
+ if (u.getScheme().equals("file")) {
+ File file = new File(u);
if (!file.exists())
return;
}
- load(getUri().toURL().openStream());
+ load(u.toURL().openStream());
} catch (Exception e) {
throw new UserDirectoryException("Cannot open URL " + getUri(), e);
}
private final LdifUser osUser;
public OsUserDirectory(URI uriArg, Dictionary<String, ?> props) {
- super(uriArg, props);
+ super(uriArg, props, false);
try {
osUserDn = new LdapName(LdapAttrs.uid.name() + "=" + osUsername + "," + getUserBase() + "," + getBaseDn());
Attributes attributes = new BasicAttributes();
@Override
protected List<DirectoryUser> doGetRoles(Filter f) {
List<DirectoryUser> res = new ArrayList<>();
- if (f==null || f.match(osUser.getProperties()))
+ if (f == null || f.match(osUser.getProperties()))
res.add(osUser);
return res;
}
package org.argeo.osgi.useradmin;
-import java.io.IOException;
import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map;
import javax.naming.Context;
-import javax.naming.NamingException;
import javax.naming.ldap.LdapName;
-import org.argeo.naming.DnsBrowser;
import org.argeo.naming.NamingUtils;
/** Properties used to configure user admins. */
public final static String FACTORY_PID = "org.argeo.osgi.useradmin.config";
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";
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
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(":");
}
}
- 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));
- 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 {
try {
userDirectory.prepare(wc);
} catch (Exception e) {
+ e.printStackTrace();
throw new XAException(XAException.XAER_RMERR);
}
return XA_OK;
userDirectory.prepare(wc);
userDirectory.commit(wc);
} catch (Exception e) {
+ e.printStackTrace();
throw new XAException(XAException.XAER_RMERR);
} finally {
cleanUp(xid);
checkXid(xid);
userDirectory.rollback(wc(xid));
} catch (Exception e) {
+ e.printStackTrace();
throw new XAException(XAException.XAER_RMERR);
} finally {
cleanUp(xid);