1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package edu.internet2.middleware.shibboleth.common.attribute.filtering.provider.match.saml;
19
20 import java.util.List;
21
22 import org.opensaml.saml2.core.Attribute;
23 import org.opensaml.saml2.metadata.EntityDescriptor;
24 import org.opensaml.samlext.saml2mdattr.EntityAttributes;
25 import org.opensaml.xml.XMLObject;
26 import org.opensaml.xml.schema.XSAny;
27 import org.opensaml.xml.schema.XSString;
28 import org.opensaml.xml.util.DatatypeHelper;
29 import org.slf4j.Logger;
30 import org.slf4j.LoggerFactory;
31
32 import edu.internet2.middleware.shibboleth.common.attribute.filtering.provider.FilterProcessingException;
33 import edu.internet2.middleware.shibboleth.common.attribute.filtering.provider.ShibbolethFilteringContext;
34 import edu.internet2.middleware.shibboleth.common.attribute.filtering.provider.match.basic.AbstractMatchFunctor;
35
36
37
38
39
40 public abstract class AbstractEntityAttributeMatchFunctor extends AbstractMatchFunctor {
41
42
43 private final Logger log = LoggerFactory.getLogger(AbstractEntityAttributeMatchFunctor.class);
44
45
46 private String name;
47
48
49 private String nameFormat;
50
51
52
53
54
55
56 public String getName() {
57 return name;
58 }
59
60
61
62
63
64
65 public void setName(String attributeName) {
66 name = attributeName;
67 }
68
69
70
71
72
73
74 public String getNameFormat() {
75 return nameFormat;
76 }
77
78
79
80
81
82
83 public void setNameFormat(String attributeNameFormat) {
84 nameFormat = DatatypeHelper.safeTrimOrNullString(attributeNameFormat);
85 }
86
87
88 protected boolean doEvaluatePolicyRequirement(ShibbolethFilteringContext filterContext)
89 throws FilterProcessingException {
90 return hasEntityAttribute(filterContext);
91 }
92
93
94 protected boolean doEvaluateValue(ShibbolethFilteringContext filterContext, String attributeId,
95 Object attributeValue) throws FilterProcessingException {
96 return hasEntityAttribute(filterContext);
97 }
98
99
100
101
102
103
104
105
106
107 protected boolean hasEntityAttribute(ShibbolethFilteringContext filterContext) {
108 EntityDescriptor entityDescriptor = getEntityMetadata(filterContext);
109 if (entityDescriptor == null) {
110 log.debug("No metadata available for the entity");
111 return false;
112 }
113
114 Attribute entityAttribute = getEntityAttribute(entityDescriptor);
115 if (entityAttribute == null) {
116 return false;
117 }
118
119 List<XMLObject> attributeValues = entityAttribute.getAttributeValues();
120 if (attributeValues == null || attributeValues.isEmpty()) {
121 log.debug("Entity attribute {} for entity {} does not contain any values", getName(),
122 entityDescriptor.getEntityID());
123 return false;
124 }
125
126 log.debug("Checking if entity attribute {} contains the required value.", getName());
127 String valueString;
128 for (XMLObject attributeValue : attributeValues) {
129 if (attributeValue instanceof XSAny) {
130 valueString = ((XSAny) attributeValue).getTextContent();
131 } else if (attributeValue instanceof XSString) {
132 valueString = ((XSString) attributeValue).getValue();
133 } else {
134 log.debug("Entity attribute {} contains the unsupported value type {}, skipping it", getName(),
135 attributeValue.getClass().getName());
136 continue;
137 }
138
139 if (valueString != null) {
140 if (entityAttributeValueMatches(valueString)) {
141 log.debug("Entity attribute {} value {} meets matching requirements", getName(), valueString);
142 return true;
143 }
144 log.debug("Entity attribute {} value {} does not meet matching requirements", getName(), valueString);
145 }
146 }
147
148 return false;
149 }
150
151
152
153
154
155
156
157
158 protected abstract EntityDescriptor getEntityMetadata(ShibbolethFilteringContext filterContext);
159
160
161
162
163
164
165
166
167
168 protected Attribute getEntityAttribute(EntityDescriptor entityDescriptor) {
169 List<XMLObject> entityAttributesCollection = entityDescriptor.getExtensions().getUnknownXMLObjects(
170 EntityAttributes.DEFAULT_ELEMENT_NAME);
171 if (entityAttributesCollection == null || entityAttributesCollection.isEmpty()) {
172 log.debug("Descriptor for {} does not contain any EntityAttributes", entityDescriptor.getEntityID());
173 return null;
174 }
175
176 if (entityAttributesCollection.size() > 1) {
177 log.debug("Descriptor for {} contains more than EntityAttributes extension, only using the first one",
178 entityDescriptor.getEntityID());
179 }
180
181 List<Attribute> entityAttributes = ((EntityAttributes) entityAttributesCollection.get(0)).getAttributes();
182 if (entityAttributes == null || entityAttributes.isEmpty()) {
183 log.debug("EntityAttributes extension for {} does not contain any Attributes",
184 entityDescriptor.getEntityID());
185 return null;
186 }
187
188 for (Attribute entityAttribute : entityAttributes) {
189 if (!DatatypeHelper.safeEquals(getName(), entityAttribute.getName())) {
190 continue;
191 }
192
193 if (getNameFormat() == null
194 || (DatatypeHelper.safeEquals(getNameFormat(), entityAttribute.getNameFormat()))) {
195 log.debug("Descriptor for {} contains an entity attribute with the name {} and the format {}",
196 new Object[] { entityDescriptor.getEntityID(), getName(), getNameFormat() });
197 return entityAttribute;
198 }
199 }
200
201 log.debug("Descriptor for {} does not contain an entity attribute with the name {} and the format {}",
202 new Object[] { entityDescriptor.getEntityID(), getName(), getNameFormat() });
203 return null;
204 }
205
206
207
208
209
210
211
212
213 protected abstract boolean entityAttributeValueMatches(String entityAttributeValue);
214 }