Lines 317-331
Link Here
|
317 |
*/ |
317 |
*/ |
318 |
protected MessageFormat[] userPatternFormatArray = null; |
318 |
protected MessageFormat[] userPatternFormatArray = null; |
319 |
|
319 |
|
320 |
|
|
|
321 |
/** |
320 |
/** |
322 |
* The maximum recursion depth when resolving roles recursively. |
|
|
323 |
* By default we don't resolve roles recursively. |
324 |
*/ |
325 |
protected int roleRecursionLimit = 0; |
326 |
|
327 |
|
328 |
/** |
329 |
* The base element for role searches. |
321 |
* The base element for role searches. |
330 |
*/ |
322 |
*/ |
331 |
protected String roleBase = ""; |
323 |
protected String roleBase = ""; |
Lines 362-368
Link Here
|
362 |
* Should we search the entire subtree for matching memberships? |
354 |
* Should we search the entire subtree for matching memberships? |
363 |
*/ |
355 |
*/ |
364 |
protected boolean roleSubtree = false; |
356 |
protected boolean roleSubtree = false; |
|
|
357 |
|
358 |
/** |
359 |
* Should we look for nested group in order to determine roles? |
360 |
*/ |
361 |
protected boolean roleNested = false; |
365 |
|
362 |
|
|
|
363 |
|
366 |
/** |
364 |
/** |
367 |
* An alternate URL, to which, we should connect if connectionURL fails. |
365 |
* An alternate URL, to which, we should connect if connectionURL fails. |
368 |
*/ |
366 |
*/ |
Lines 652-679
Link Here
|
652 |
|
650 |
|
653 |
|
651 |
|
654 |
/** |
652 |
/** |
655 |
* Return the maximum recursion depth for role searches. |
|
|
656 |
*/ |
657 |
public int getRoleRecursionLimit() { |
658 |
|
659 |
return (this.roleRecursionLimit); |
660 |
|
661 |
} |
662 |
|
663 |
|
664 |
/** |
665 |
* Set the maximum recursion depth for role searches. |
666 |
* |
667 |
* @param roleRecursionLimit The new recursion limit |
668 |
*/ |
669 |
public void setRoleRecursionLimit(int roleRecursionLimit) { |
670 |
|
671 |
this.roleRecursionLimit = roleRecursionLimit; |
672 |
|
673 |
} |
674 |
|
675 |
|
676 |
/** |
677 |
* Return the base element for role searches. |
653 |
* Return the base element for role searches. |
678 |
*/ |
654 |
*/ |
679 |
public String getRoleBase() { |
655 |
public String getRoleBase() { |
Lines 763-771
Link Here
|
763 |
this.roleSubtree = roleSubtree; |
739 |
this.roleSubtree = roleSubtree; |
764 |
|
740 |
|
765 |
} |
741 |
} |
|
|
742 |
|
743 |
/** |
744 |
* Return the "The nested group search flag" flag. |
745 |
*/ |
746 |
public boolean getRoleNested() { |
766 |
|
747 |
|
|
|
748 |
return (this.roleNested); |
767 |
|
749 |
|
|
|
750 |
} |
751 |
|
752 |
|
768 |
/** |
753 |
/** |
|
|
754 |
* Set the "search subtree for roles" flag. |
755 |
* |
756 |
* @param roleNested The nested group search flag |
757 |
*/ |
758 |
public void setRoleNested(boolean roleNested) { |
759 |
|
760 |
this.roleNested = roleNested; |
761 |
|
762 |
} |
763 |
|
764 |
|
765 |
|
766 |
/** |
769 |
* Return the password attribute used to retrieve the user password. |
767 |
* Return the password attribute used to retrieve the user password. |
770 |
*/ |
768 |
*/ |
771 |
public String getUserPassword() { |
769 |
public String getUserPassword() { |
Lines 1546-1617
Link Here
|
1546 |
return (validated); |
1544 |
return (validated); |
1547 |
} |
1545 |
} |
1548 |
|
1546 |
|
1549 |
|
|
|
1550 |
/** |
1547 |
/** |
1551 |
* Add roles to a user and search for other roles containing them themselves. |
|
|
1552 |
* We search recursively with a limited depth. |
1553 |
* By default the depth is 0, and we only use direct roles. |
1554 |
* The search needs to use the distinguished role names, |
1555 |
* but to return the role names. |
1556 |
* |
1557 |
* @param depth Recursion depth, starting at zero |
1558 |
* @param context The directory context we are searching |
1559 |
* @param recursiveMap The cumulative result map of role names and DNs. |
1560 |
* @param recursiveSet The cumulative result set of role names. |
1561 |
* @param groupName The role name to add to the list. |
1562 |
* @param groupDName The distinguished name of the role. |
1563 |
* |
1564 |
* @exception NamingException if a directory server error occurs |
1565 |
*/ |
1566 |
private void getRolesRecursive(int depth, DirContext context, Map<String, String> recursiveMap, Set<String> recursiveSet, |
1567 |
String groupName, String groupDName) throws NamingException { |
1568 |
if (containerLog.isTraceEnabled()) |
1569 |
containerLog.trace("Recursive search depth " + depth + " for group '" + groupDName + " (" + groupName + ")'"); |
1570 |
// Adding the given group to the result set if not already found |
1571 |
if (!recursiveSet.contains(groupDName)) { |
1572 |
recursiveSet.add(groupDName); |
1573 |
recursiveMap.put(groupDName, groupName); |
1574 |
if (depth >= roleRecursionLimit) { |
1575 |
if (roleRecursionLimit > 0) |
1576 |
containerLog.warn("Terminating recursive role search because of recursion limit " + |
1577 |
roleRecursionLimit + ", results might be incomplete"); |
1578 |
return; |
1579 |
} |
1580 |
// Prepare the parameters for searching groups |
1581 |
String filter = roleFormat.format(new String[] { groupDName }); |
1582 |
SearchControls controls = new SearchControls(); |
1583 |
controls.setSearchScope(roleSubtree ? SearchControls.SUBTREE_SCOPE : SearchControls.ONELEVEL_SCOPE); |
1584 |
controls.setReturningAttributes(new String[] { roleName }); |
1585 |
if (containerLog.isTraceEnabled()) { |
1586 |
containerLog.trace("Recursive search in role base '" + roleBase + "' for attribute '" + roleName + "'" + |
1587 |
" with filter expression '" + filter + "'"); |
1588 |
} |
1589 |
// Searching groups that assign the given group |
1590 |
NamingEnumeration<SearchResult> results = |
1591 |
context.search(roleBase, filter, controls); |
1592 |
if (results != null) { |
1593 |
// Iterate over the resulting groups |
1594 |
try { |
1595 |
while (results.hasMore()) { |
1596 |
SearchResult result = results.next(); |
1597 |
Attributes attrs = result.getAttributes(); |
1598 |
if (attrs == null) |
1599 |
continue; |
1600 |
String dname = getDistinguishedName(context, roleBase, result); |
1601 |
String name = getAttributeValue(roleName, attrs); |
1602 |
if (name != null && dname != null) { |
1603 |
getRolesRecursive(depth+1, context, recursiveMap, recursiveSet, name, dname); |
1604 |
} |
1605 |
} |
1606 |
} catch (PartialResultException ex) { |
1607 |
if (!adCompat) |
1608 |
throw ex; |
1609 |
} |
1610 |
} |
1611 |
} |
1612 |
} |
1613 |
|
1614 |
/** |
1615 |
* Return a List of roles associated with the given User. Any |
1548 |
* Return a List of roles associated with the given User. Any |
1616 |
* roles present in the user's directory entry are supplemented by |
1549 |
* roles present in the user's directory entry are supplemented by |
1617 |
* a directory search. If no roles are associated with this user, |
1550 |
* a directory search. If no roles are associated with this user, |
Lines 1654-1660
Link Here
|
1654 |
// Are we configured to do role searches? |
1587 |
// Are we configured to do role searches? |
1655 |
if ((roleFormat == null) || (roleName == null)) |
1588 |
if ((roleFormat == null) || (roleName == null)) |
1656 |
return (list); |
1589 |
return (list); |
1657 |
|
1590 |
|
1658 |
// Set up parameters for an appropriate search |
1591 |
// Set up parameters for an appropriate search |
1659 |
String filter = roleFormat.format(new String[] { doRFC2254Encoding(dn), username }); |
1592 |
String filter = roleFormat.format(new String[] { doRFC2254Encoding(dn), username }); |
1660 |
SearchControls controls = new SearchControls(); |
1593 |
SearchControls controls = new SearchControls(); |
Lines 1691-1720
Link Here
|
1691 |
Set<String> keys = groupMap.keySet(); |
1624 |
Set<String> keys = groupMap.keySet(); |
1692 |
if (containerLog.isTraceEnabled()) { |
1625 |
if (containerLog.isTraceEnabled()) { |
1693 |
containerLog.trace(" Found " + keys.size() + " direct roles"); |
1626 |
containerLog.trace(" Found " + keys.size() + " direct roles"); |
1694 |
for (Iterator<String> i = keys.iterator(); i.hasNext();) { |
1627 |
for (String key: keys) { |
1695 |
Object k = i.next(); |
1628 |
containerLog.trace( " Found direct role " + key + " -> " + groupMap.get(key)); |
1696 |
containerLog.trace( " Found direct role " + k + " -> " + groupMap.get(k)); |
|
|
1697 |
} |
1629 |
} |
1698 |
} |
1630 |
} |
|
|
1631 |
|
1632 |
// if nested group search is enabled, perform searches for nested groups until no new group is found |
1633 |
if (getRoleNested()) { |
1634 |
|
1635 |
// The following efficient algorithm is known as memberOf Algorithm, as described in "Practices in |
1636 |
// Directory Groups". It avoids group slurping and handles cyclic group memberships as well. |
1637 |
// See http://middleware.internet2.edu/dir/ for details |
1638 |
|
1639 |
Set<String> newGroupDNs = new HashSet<String>(groupMap.keySet()); |
1640 |
while (!newGroupDNs.isEmpty()) { |
1641 |
Set<String> newThisRound = new HashSet<String>(); // Stores the groups we find in this iteration |
1642 |
|
1643 |
for (String groupDN : newGroupDNs) { |
1644 |
filter = roleFormat.format(new String[] { groupDN }); |
1645 |
|
1646 |
if (containerLog.isTraceEnabled()) { |
1647 |
containerLog.trace("Perform a nested group search with base "+ roleBase + " and filter " + filter); |
1648 |
} |
1649 |
|
1650 |
results = context.search(roleBase, filter, controls); |
1651 |
|
1652 |
try { |
1653 |
while (results.hasMore()) { |
1654 |
SearchResult result = results.next(); |
1655 |
Attributes attrs = result.getAttributes(); |
1656 |
if (attrs == null) |
1657 |
continue; |
1658 |
String dname = getDistinguishedName(context, roleBase, result); |
1659 |
String name = getAttributeValue(roleName, attrs); |
1660 |
if (name != null && dname != null && !groupMap.keySet().contains(dname)) { |
1661 |
groupMap.put(dname, name); |
1662 |
newThisRound.add(dname); |
1663 |
|
1664 |
if (containerLog.isTraceEnabled()) { |
1665 |
containerLog.trace(" Found nested role " + dname + " -> " + name); |
1666 |
} |
1667 |
|
1668 |
} |
1669 |
} |
1670 |
} catch (PartialResultException ex) { |
1671 |
if (!adCompat) |
1672 |
throw ex; |
1673 |
} |
1674 |
} |
1675 |
|
1676 |
newGroupDNs = newThisRound; |
1677 |
} |
1678 |
} |
1699 |
|
1679 |
|
1700 |
HashSet<String> recursiveSet = new HashSet<String>(); |
1680 |
return new ArrayList<String>(groupMap.values()); |
1701 |
HashMap<String, String> recursiveMap = new HashMap<String, String>(); |
|
|
1702 |
|
1703 |
for (Iterator<String> i = keys.iterator(); i.hasNext();) { |
1704 |
String k = i.next(); |
1705 |
getRolesRecursive(0, context, recursiveMap, recursiveSet, groupMap.get(k), k); |
1706 |
} |
1707 |
|
1708 |
HashSet<String> resultSet = new HashSet<String>(list); |
1709 |
resultSet.addAll(recursiveMap.values()); |
1710 |
|
1711 |
if (containerLog.isTraceEnabled()) { |
1712 |
containerLog.trace(" Returning " + resultSet.size() + " roles"); |
1713 |
for (Iterator<String> i = resultSet.iterator(); i.hasNext();) |
1714 |
containerLog.trace( " Found role " + i.next()); |
1715 |
} |
1716 |
|
1717 |
return new ArrayList<String>(resultSet); |
1718 |
} |
1681 |
} |
1719 |
|
1682 |
|
1720 |
|
1683 |
|