001 /* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2008 Sun Microsystems, Inc. 026 */ 027 028 package org.opends.server.authorization.dseecompat; 029 import org.opends.messages.Message; 030 031 import static org.opends.messages.AccessControlMessages.*; 032 import static org.opends.server.authorization.dseecompat.Aci.*; 033 import org.opends.server.types.*; 034 import org.opends.server.api.Group; 035 import org.opends.server.core.GroupManager; 036 import org.opends.server.core.DirectoryServer; 037 import java.util.Iterator; 038 import java.util.LinkedList; 039 import java.util.List; 040 import java.util.LinkedHashSet; 041 import java.util.regex.Matcher; 042 import java.util.regex.Pattern; 043 044 045 /** 046 * This class implements the groupdn bind rule keyword. 047 */ 048 public class GroupDN implements KeywordBindRule { 049 050 /* 051 * List of group DNs. 052 */ 053 LinkedList<DN> groupDNs=null; 054 055 /* 056 * Enumeration representing the groupdn operator type. 057 */ 058 private EnumBindRuleType type=null; 059 060 /** 061 * Regular expression matching one or more LDAP URLs separated by 062 * "||". 063 */ 064 public static final String LDAP_URLS = LDAP_URL + 065 ZERO_OR_MORE_WHITESPACE + "(" + LOGICAL_OR + 066 ZERO_OR_MORE_WHITESPACE + LDAP_URL + ")*"; 067 068 /** 069 * Create a class representing a groupdn bind rule keyword. 070 * @param type An enumeration representing the bind rule type. 071 * @param groupDNs A list of the dns representing groups. 072 */ 073 private GroupDN(EnumBindRuleType type, LinkedList<DN> groupDNs ) { 074 this.groupDNs=groupDNs; 075 this.type=type; 076 } 077 078 /** 079 * Decode an string expression representing a groupdn bind rule. 080 * @param expr A string representation of the bind rule. 081 * @param type An enumeration of the type of the bind rule. 082 * @return A keyword bind rule class that can be used to evaluate 083 * this bind rule. 084 * @throws AciException If the expression string is invalid. 085 */ 086 public static KeywordBindRule decode(String expr, EnumBindRuleType type) 087 throws AciException { 088 if (!Pattern.matches(LDAP_URLS, expr)) { 089 Message message = 090 WARN_ACI_SYNTAX_INVALID_GROUPDN_EXPRESSION.get(expr); 091 throw new AciException(message); 092 } 093 LinkedList<DN>groupDNs=new LinkedList<DN>(); 094 int ldapURLPos = 1; 095 Pattern ldapURLPattern = Pattern.compile(LDAP_URL); 096 Matcher ldapURLMatcher = ldapURLPattern.matcher(expr); 097 while (ldapURLMatcher.find()) { 098 try { 099 String value = ldapURLMatcher.group(ldapURLPos).trim(); 100 DN dn=LDAPURL.decode(value, true).getBaseDN(); 101 groupDNs.add(dn); 102 } catch (DirectoryException ex) { 103 Message message = WARN_ACI_SYNTAX_INVALID_GROUPDN_URL.get( 104 ex.getMessageObject()); 105 throw new AciException(message); 106 } 107 } 108 return new GroupDN(type, groupDNs); 109 } 110 111 /** 112 * Performs the evaluation of a groupdn bind rule based on the 113 * evaluation context passed to it. The evaluation stops when there 114 * are no more group DNs to evaluate, or if a group DN evaluates to true 115 * if it contains the client DN. 116 * @param evalCtx An evaluation context to use in the evaluation. 117 * @return Enumeration evaluation result. 118 */ 119 public EnumEvalResult evaluate(AciEvalContext evalCtx) { 120 EnumEvalResult matched = EnumEvalResult.FALSE; 121 Iterator<DN> it=groupDNs.iterator(); 122 for(; it.hasNext() && matched != EnumEvalResult.TRUE;) { 123 DN groupDN=it.next(); 124 Group group = getGroupManager().getGroupInstance(groupDN); 125 if((group != null) && (evalCtx.isMemberOf(group))) 126 matched = EnumEvalResult.TRUE; 127 } 128 return matched.getRet(type, false); 129 } 130 131 /** 132 * Performs an evaluation of a group that was specified in an attribute 133 * type value of the specified entry and attribute type. Each 134 * value of the attribute type is assumed to be a group DN and evaluation 135 * stops when there are no more values or if the group DN evaluates to 136 * true if it contains the client DN. 137 * @param e The entry to use in the evaluation. 138 * @param evalCtx The evaluation context to use in the evaluation. 139 * @param attributeType The attribute type of the entry to use to get the 140 * values for the groupd DNs. 141 * @param suffixDN The suffix that the groupDN must be under. If it's null, 142 * then the groupDN can be anywhere in the DIT. 143 * @return Enumeration evaluation result. 144 */ 145 public static EnumEvalResult evaluate (Entry e, AciEvalContext evalCtx, 146 AttributeType attributeType, 147 DN suffixDN) { 148 EnumEvalResult matched= EnumEvalResult.FALSE; 149 List<Attribute> attrs = e.getAttribute(attributeType); 150 LinkedHashSet<AttributeValue> vals = attrs.get(0).getValues(); 151 for(AttributeValue v : vals) { 152 try { 153 DN groupDN=DN.decode(v.getStringValue()); 154 if(suffixDN != null && 155 !groupDN.isDescendantOf(suffixDN)) 156 continue; 157 Group group = getGroupManager().getGroupInstance(groupDN); 158 if((group != null) && (evalCtx.isMemberOf(group))) { 159 matched=EnumEvalResult.TRUE; 160 break; 161 } 162 } catch (DirectoryException ex) { 163 break; 164 } 165 } 166 return matched; 167 } 168 169 private static GroupManager getGroupManager() { 170 return DirectoryServer.getGroupManager(); 171 } 172 }