X-Git-Url: https://git.argeo.org/?a=blobdiff_plain;f=org.argeo.util%2Fsrc%2Forg%2Fargeo%2Fosgi%2Fuseradmin%2FDirectoryUserAdmin.java;h=3903a23f434212c6e5de3aac0c2c8f8fe1f3fa56;hb=d2bca81ff63496bf1d879f4cbcd6a531f598e69c;hp=6f3bd1a6865695cbdbc48729c10a7fda745fc156;hpb=e921c662016dd893e60f3e801eb86d676adcb77d;p=lgpl%2Fargeo-commons.git diff --git a/org.argeo.util/src/org/argeo/osgi/useradmin/DirectoryUserAdmin.java b/org.argeo.util/src/org/argeo/osgi/useradmin/DirectoryUserAdmin.java index 6f3bd1a68..3903a23f4 100644 --- a/org.argeo.util/src/org/argeo/osgi/useradmin/DirectoryUserAdmin.java +++ b/org.argeo.util/src/org/argeo/osgi/useradmin/DirectoryUserAdmin.java @@ -8,11 +8,13 @@ import static org.argeo.util.naming.LdapObjs.person; 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; @@ -21,7 +23,10 @@ import javax.naming.directory.BasicAttribute; 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; @@ -43,12 +48,8 @@ import org.osgi.service.useradmin.UserAdmin; public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdmin, UserDirectory { private UserAdmin externalRoles; - // private List indexedUserProperties = Arrays - // .asList(new String[] { LdapAttrs.uid.name(), LdapAttrs.mail.name(), - // LdapAttrs.cn.name() }); // Transaction -// private TransactionManager transactionManager; public DirectoryUserAdmin(URI uriArg, Dictionary props) { this(uriArg, props, false); } @@ -65,7 +66,7 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm * ABSTRACT METHODS */ - protected AbstractLdapDirectory scope(User user) { + protected Optional scope(User user) { if (getDirectoryDao() instanceof LdapDao) { return scopeLdap(user); } else if (getDirectoryDao() instanceof LdifDao) { @@ -75,7 +76,7 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm } } - protected DirectoryUserAdmin scopeLdap(User user) { + protected Optional scopeLdap(User user) { Dictionary credentials = user.getCredentials(); String username = (String) credentials.get(SHARED_STATE_USERNAME); if (username == null) @@ -92,10 +93,13 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm } DirectoryUserAdmin scopedDirectory = new DirectoryUserAdmin(null, properties, true); scopedDirectory.init(); - return scopedDirectory; + // check connection + if (!scopedDirectory.getDirectoryDao().checkConnection()) + return Optional.empty(); + return Optional.of(scopedDirectory); } - protected DirectoryUserAdmin scopeLdif(User user) { + protected Optional scopeLdif(User user) { Dictionary credentials = user.getCredentials(); String username = (String) credentials.get(SHARED_STATE_USERNAME); if (username == null) @@ -113,12 +117,11 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm Dictionary 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()); + // no need to check authentication scopedUserAdmin.init(); - return scopedUserAdmin; + return Optional.of(scopedUserAdmin); } @Override @@ -137,7 +140,8 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm public Role getRoleByPath(String path) { LdapEntry entry = doGetRole(pathToName(path)); if (!(entry instanceof Role)) { - throw new IllegalStateException("Path must be a UserAdmin Role."); + return null; +// throw new IllegalStateException("Path must be a UserAdmin Role."); } else { return (Role) entry; } @@ -146,48 +150,21 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm protected List getAllRoles(DirectoryUser user) { List allRoles = new ArrayList(); if (user != null) { - collectRoles(user, allRoles); + collectRoles((LdapEntry) user, allRoles); allRoles.add(user); } else collectAnonymousRoles(allRoles); return allRoles; } - private void collectRoles(DirectoryUser user, List allRoles) { + private void collectRoles(LdapEntry user, List allRoles) { List allEntries = new ArrayList<>(); - LdapEntry entry = (LdapEntry) user; + LdapEntry entry = user; collectGroups(entry, allEntries); for (LdapEntry e : allEntries) { 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 allRoles) { @@ -229,21 +206,6 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm // 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; } @@ -275,24 +237,54 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm @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 allRoles = new ArrayList(); + 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(); @@ -312,13 +304,13 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm 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) { @@ -333,14 +325,14 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm 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; @@ -349,22 +341,6 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm @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; } /* @@ -382,7 +358,7 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm @Override public Iterable 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) { @@ -393,13 +369,13 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm /* * ROLES CREATION */ - protected LdapEntry newUser(LdapName name, Attributes attrs) { + protected LdapEntry newUser(LdapName name) { // TODO support devices, applications, etc. - return new LdifUser(this, name, attrs); + return new LdifUser(this, name); } - protected LdapEntry newGroup(LdapName name, Attributes attrs) { - return new LdifGroup(this, name, attrs); + protected LdapEntry newGroup(LdapName name) { + return new LdifGroup(this, name); } @@ -412,10 +388,6 @@ public class DirectoryUserAdmin extends AbstractLdapDirectory implements UserAdm this.externalRoles = externalRoles; } -// public void setTransactionManager(TransactionManager transactionManager) { -// this.transactionManager = transactionManager; -// } - /* * STATIC UTILITIES */