import static org.argeo.util.naming.LdapObjs.top;
import java.net.URI;
-import java.nio.channels.UnsupportedAddressTypeException;
+import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Dictionary;
+import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
+import java.util.Optional;
import javax.naming.Context;
import javax.naming.InvalidNameException;
import javax.naming.directory.BasicAttributes;
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
+import javax.security.auth.Subject;
+import javax.security.auth.kerberos.KerberosTicket;
+import org.argeo.util.CurrentSubject;
import org.argeo.util.directory.DirectoryConf;
import org.argeo.util.directory.DirectoryDigestUtils;
import org.argeo.util.directory.HierarchyUnit;
import org.argeo.util.directory.ldap.AbstractLdapDirectory;
+import org.argeo.util.directory.ldap.LdapDao;
import org.argeo.util.directory.ldap.LdapEntry;
import org.argeo.util.directory.ldap.LdapEntryWorkingCopy;
import org.argeo.util.directory.ldap.LdapNameUtils;
import org.argeo.util.directory.ldap.LdifDao;
-import org.argeo.util.naming.LdapObjs;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdmin, UserDirectory {
private UserAdmin externalRoles;
- // private List<String> indexedUserProperties = Arrays
- // .asList(new String[] { LdapAttrs.uid.name(), LdapAttrs.mail.name(),
- // LdapAttrs.cn.name() });
// Transaction
-// private TransactionManager transactionManager;
public DirectoryUserAdmin(URI uriArg, Dictionary<String, ?> props) {
this(uriArg, props, false);
}
* ABSTRACT METHODS
*/
- protected AbstractLdapDirectory scope(User user) {
- throw new UnsupportedAddressTypeException();
+ protected Optional<DirectoryUserAdmin> scope(User user) {
+ if (getDirectoryDao() instanceof LdapDao) {
+ return scopeLdap(user);
+ } else if (getDirectoryDao() instanceof LdifDao) {
+ return scopeLdif(user);
+ } else {
+ throw new IllegalStateException("Unsupported DAO " + getDirectoryDao().getClass());
+ }
}
- protected DirectoryUserAdmin scopeLdap(User user) {
+ protected Optional<DirectoryUserAdmin> scopeLdap(User user) {
Dictionary<String, Object> credentials = user.getCredentials();
String username = (String) credentials.get(SHARED_STATE_USERNAME);
if (username == null)
username = user.getName();
- Dictionary<String, Object> properties = cloneProperties();
+ Dictionary<String, Object> properties = cloneConfigProperties();
properties.put(Context.SECURITY_PRINCIPAL, username.toString());
Object pwdCred = credentials.get(SHARED_STATE_PASSWORD);
byte[] pwd = (byte[]) pwdCred;
} else {
properties.put(Context.SECURITY_AUTHENTICATION, "GSSAPI");
}
- return new DirectoryUserAdmin(null, properties, true);
+ DirectoryUserAdmin scopedDirectory = new DirectoryUserAdmin(null, properties, true);
+ scopedDirectory.init();
+ // check connection
+ if (!scopedDirectory.getDirectoryDao().checkConnection())
+ return Optional.empty();
+ return Optional.of(scopedDirectory);
}
- protected DirectoryUserAdmin scopeLdif(User user) {
+ protected Optional<DirectoryUserAdmin> scopeLdif(User user) {
Dictionary<String, Object> credentials = user.getCredentials();
String username = (String) credentials.get(SHARED_STATE_USERNAME);
if (username == null)
} else {
throw new IllegalStateException("Password is required");
}
- Dictionary<String, Object> properties = cloneProperties();
+ Dictionary<String, Object> properties = cloneConfigProperties();
properties.put(DirectoryConf.readOnly.name(), "true");
DirectoryUserAdmin scopedUserAdmin = new DirectoryUserAdmin(null, properties, true);
-// scopedUserAdmin.groups = Collections.unmodifiableNavigableMap(groups);
-// scopedUserAdmin.users = Collections.unmodifiableNavigableMap(users);
// FIXME do it better
((LdifDao) getDirectoryDao()).scope((LdifDao) scopedUserAdmin.getDirectoryDao());
- return scopedUserAdmin;
+ // no need to check authentication
+ scopedUserAdmin.init();
+ return Optional.of(scopedUserAdmin);
}
@Override
@Override
public Role getRoleByPath(String path) {
- return (Role) doGetRole(pathToName(path));
+ LdapEntry entry = doGetRole(pathToName(path));
+ if (!(entry instanceof Role)) {
+ return null;
+// throw new IllegalStateException("Path must be a UserAdmin Role.");
+ } else {
+ return (Role) entry;
+ }
}
protected List<Role> getAllRoles(DirectoryUser user) {
List<Role> allRoles = new ArrayList<Role>();
if (user != null) {
- collectRoles(user, allRoles);
+ collectRoles((LdapEntry) user, allRoles);
allRoles.add(user);
} else
collectAnonymousRoles(allRoles);
return allRoles;
}
- private void collectRoles(DirectoryUser user, List<Role> allRoles) {
+ private void collectRoles(LdapEntry user, List<Role> allRoles) {
List<LdapEntry> allEntries = new ArrayList<>();
- LdapEntry entry = (LdapEntry) user;
+ LdapEntry entry = user;
collectGroups(entry, allEntries);
for (LdapEntry e : allEntries) {
- allRoles.add((Role) e);
+ if (e instanceof Role)
+ allRoles.add((Role) e);
}
-// Attributes attrs = user.getAttributes();
-// // TODO centralize attribute name
-// Attribute memberOf = attrs.get(LdapAttrs.memberOf.name());
-// // if user belongs to this directory, we only check memberOf
-// 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);
-// if (group != null)
-// allRoles.add(group);
-// }
-// } catch (NamingException e) {
-// throw new IllegalStateException("Cannot get memberOf groups for " + user, e);
-// }
-// } else {
-// for (LdapName groupDn : getDirectoryDao().getDirectGroups(user.getDn())) {
-// // TODO check for loops
-// DirectoryUser group = doGetRole(groupDn);
-// if (group != null) {
-// allRoles.add(group);
-// collectRoles(group, allRoles);
-// }
-// }
-// }
}
private void collectAnonymousRoles(List<Role> allRoles) {
// no need to check modified users,
// since doGetRoles was already based on the modified attributes
}
-
- // if non deep we also search users and groups
-// if (!deep) {
-// try {
-// if (!(searchBase.endsWith(new LdapName(getUserBase()))
-// || searchBase.endsWith(new LdapName(getGroupBase())))) {
-// LdapName usersBase = (LdapName) ((LdapName) searchBase.clone()).add(getUserBase());
-// res.addAll(getRoles(usersBase, filter, false));
-// LdapName groupsBase = (LdapName) ((LdapName) searchBase.clone()).add(getGroupBase());
-// res.addAll(getRoles(groupsBase, filter, false));
-// }
-// } catch (InvalidNameException e) {
-// throw new IllegalStateException("Cannot search users and groups", e);
-// }
-// }
return res;
}
@Override
public Authorization getAuthorization(User user) {
- if (user == null || user instanceof DirectoryUser) {
- return new LdifAuthorization(user, getAllRoles((DirectoryUser) user));
+ if (user == null) {// anonymous
+ return new LdifAuthorization(user, getAllRoles(null));
+ }
+ LdapName userName = toLdapName(user.getName());
+ if (isExternal(userName) && user instanceof LdapEntry) {
+ List<Role> allRoles = new ArrayList<Role>();
+ collectRoles((LdapEntry) user, allRoles);
+ return new LdifAuthorization(user, allRoles);
} else {
- // bind
- DirectoryUserAdmin scopedUserAdmin = (DirectoryUserAdmin) scope(user);
- try {
- DirectoryUser directoryUser = (DirectoryUser) scopedUserAdmin.getRole(user.getName());
- if (directoryUser == null)
- throw new IllegalStateException("No scoped user found for " + user);
- LdifAuthorization authorization = new LdifAuthorization(directoryUser,
- scopedUserAdmin.getAllRoles(directoryUser));
- return authorization;
- } finally {
- scopedUserAdmin.destroy();
+
+ Subject currentSubject = CurrentSubject.current();
+ if (currentSubject != null //
+ && getRealm().isPresent() //
+ && !currentSubject.getPrivateCredentials(Authorization.class).isEmpty() //
+ && !currentSubject.getPrivateCredentials(KerberosTicket.class).isEmpty()) //
+ {
+ // TODO not only Kerberos but also bind scope with kept password ?
+ Authorization auth = currentSubject.getPrivateCredentials(Authorization.class).iterator().next();
+ // bind with authenticating user
+ DirectoryUserAdmin scopedUserAdmin = CurrentSubject.callAs(currentSubject, () -> {
+ return scope(new AuthenticatingUser(auth.getName(), new Hashtable<>())).orElseThrow();
+ });
+ return getAuthorizationFromScoped(scopedUserAdmin, user);
+ }
+
+ if (user instanceof DirectoryUser) {
+ return new LdifAuthorization(user, getAllRoles((DirectoryUser) user));
+ } else {
+ // bind with authenticating user
+ DirectoryUserAdmin scopedUserAdmin = scope(user).orElseThrow();
+ return getAuthorizationFromScoped(scopedUserAdmin, user);
}
}
}
+ private Authorization getAuthorizationFromScoped(DirectoryUserAdmin scopedUserAdmin, User user) {
+ try {
+ DirectoryUser directoryUser = (DirectoryUser) scopedUserAdmin.getRole(user.getName());
+ if (directoryUser == null)
+ throw new IllegalStateException("No scoped user found for " + user);
+ LdifAuthorization authorization = new LdifAuthorization(directoryUser,
+ scopedUserAdmin.getAllRoles(directoryUser));
+ return authorization;
+ } finally {
+ scopedUserAdmin.destroy();
+ }
+ }
+
@Override
public Role createRole(String name, int type) {
checkEdit();
LdapEntryWorkingCopy wc = getWorkingCopy();
LdapName dn = toLdapName(name);
- if ((getDirectoryDao().daoHasEntry(dn) && !wc.getDeletedData().containsKey(dn))
+ if ((getDirectoryDao().entryExists(dn) && !wc.getDeletedData().containsKey(dn))
|| wc.getNewData().containsKey(dn))
throw new IllegalArgumentException("Already a role " + name);
BasicAttributes attrs = new BasicAttributes(true);
return getRole(name);
} else {
wc.getModifiedData().put(dn, attrs);
- LdapEntry newRole = newRole(dn, type, attrs);
+ LdapEntry newRole = doCreateRole(dn, type, attrs);
wc.getNewData().put(dn, newRole);
return (Role) newRole;
}
}
- protected LdapEntry newRole(LdapName dn, int type, Attributes attrs) {
+ private LdapEntry doCreateRole(LdapName dn, int type, Attributes attrs) {
LdapEntry newRole;
BasicAttribute objClass = new BasicAttribute(objectClass.name());
if (type == Role.USER) {
objClass.add(top.name());
objClass.add(extensibleObject.name());
attrs.put(objClass);
- newRole = newUser(dn, attrs);
+ newRole = newUser(dn);
} else if (type == Role.GROUP) {
String groupObjClass = getGroupObjectClass();
objClass.add(groupObjClass);
// objClass.add(LdifName.extensibleObject.name());
objClass.add(top.name());
attrs.put(objClass);
- newRole = newGroup(dn, attrs);
+ newRole = newGroup(dn);
} else
throw new IllegalArgumentException("Unsupported type " + type);
return newRole;
@Override
public boolean removeRole(String name) {
return removeEntry(LdapNameUtils.toLdapName(name));
-// checkEdit();
-// LdapEntryWorkingCopy wc = getWorkingCopy();
-// LdapName dn = toLdapName(name);
-// boolean actuallyDeleted;
-// if (getDirectoryDao().daoHasEntry(dn) || wc.getNewData().containsKey(dn)) {
-// DirectoryUser user = (DirectoryUser) getRole(name);
-// wc.getDeletedData().put(dn, user);
-// actuallyDeleted = true;
-// } else {// just removing from groups (e.g. system roles)
-// actuallyDeleted = false;
-// }
-// for (LdapName groupDn : getDirectoryDao().getDirectGroups(dn)) {
-// LdapEntry group = doGetRole(groupDn);
-// group.getAttributes().get(getMemberAttributeId()).remove(dn.toString());
-// }
-// return actuallyDeleted;
}
/*
@Override
public Iterable<? extends Role> getHierarchyUnitRoles(HierarchyUnit hierarchyUnit, String filter, boolean deep) {
- LdapName dn = LdapNameUtils.toLdapName(hierarchyUnit.getContext());
+ LdapName dn = LdapNameUtils.toLdapName(hierarchyUnit.getBase());
try {
return getRoles(dn, filter, deep);
} catch (InvalidSyntaxException e) {
/*
* ROLES CREATION
*/
- protected LdapEntry newUser(LdapName name, Attributes attrs) {
+ protected LdapEntry newUser(LdapName name) {
// TODO support devices, applications, etc.
- return new LdifUser.LdifPerson(this, name, attrs);
+ return new LdifUser(this, name);
}
- protected LdapEntry newGroup(LdapName name, Attributes attrs) {
- if (LdapNameUtils.getParentRdn(name).equals(getSystemRoleBaseRdn()))
- return new LdifGroup.LdifSystemPermissions(this, name, attrs);
-
- if (hasObjectClass(attrs, LdapObjs.organization))
- return new LdifGroup.LdifOrganization(this, name, attrs);
- else
- return new LdifGroup.LdifFunctionalGroup(this, name, attrs);
+ protected LdapEntry newGroup(LdapName name) {
+ return new LdifGroup(this, name);
}
this.externalRoles = externalRoles;
}
-// public void setTransactionManager(TransactionManager transactionManager) {
-// this.transactionManager = transactionManager;
-// }
-
/*
* STATIC UTILITIES
*/