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