|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
declare(strict_types=1); |
|
4
|
|
|
|
|
5
|
|
|
namespace SAML2\XML\md; |
|
6
|
|
|
|
|
7
|
|
|
use SAML2\Constants; |
|
8
|
|
|
use SAML2\SignedElementHelper; |
|
9
|
|
|
use SAML2\Utils; |
|
10
|
|
|
use SAML2\XML\Chunk; |
|
11
|
|
|
|
|
12
|
|
|
/** |
|
13
|
|
|
* Class representing SAML 2 RoleDescriptor element. |
|
14
|
|
|
* |
|
15
|
|
|
* @package SimpleSAMLphp |
|
16
|
|
|
*/ |
|
17
|
|
|
class RoleDescriptor extends SignedElementHelper |
|
18
|
|
|
{ |
|
19
|
|
|
/** |
|
20
|
|
|
* The name of this descriptor element. |
|
21
|
|
|
* |
|
22
|
|
|
* @var string |
|
23
|
|
|
*/ |
|
24
|
|
|
private $elementName; |
|
25
|
|
|
|
|
26
|
|
|
/** |
|
27
|
|
|
* The ID of this element. |
|
28
|
|
|
* |
|
29
|
|
|
* @var string|null |
|
30
|
|
|
*/ |
|
31
|
|
|
private $ID = null; |
|
32
|
|
|
|
|
33
|
|
|
/** |
|
34
|
|
|
* List of supported protocols. |
|
35
|
|
|
* |
|
36
|
|
|
* @var array |
|
37
|
|
|
*/ |
|
38
|
|
|
public $protocolSupportEnumeration = []; |
|
39
|
|
|
|
|
40
|
|
|
/** |
|
41
|
|
|
* Error URL for this role. |
|
42
|
|
|
* |
|
43
|
|
|
* @var string|null |
|
44
|
|
|
*/ |
|
45
|
|
|
private $errorURL = null; |
|
46
|
|
|
|
|
47
|
|
|
/** |
|
48
|
|
|
* Extensions on this element. |
|
49
|
|
|
* |
|
50
|
|
|
* Array of extension elements. |
|
51
|
|
|
* |
|
52
|
|
|
* @var array |
|
53
|
|
|
*/ |
|
54
|
|
|
public $Extensions = []; |
|
55
|
|
|
|
|
56
|
|
|
/** |
|
57
|
|
|
* KeyDescriptor elements. |
|
58
|
|
|
* |
|
59
|
|
|
* Array of \SAML2\XML\md\KeyDescriptor elements. |
|
60
|
|
|
* |
|
61
|
|
|
* @var \SAML2\XML\md\KeyDescriptor[] |
|
62
|
|
|
*/ |
|
63
|
|
|
public $KeyDescriptor = []; |
|
64
|
|
|
|
|
65
|
|
|
/** |
|
66
|
|
|
* Organization of this role. |
|
67
|
|
|
* |
|
68
|
|
|
* @var \SAML2\XML\md\Organization|null |
|
69
|
|
|
*/ |
|
70
|
|
|
public $Organization = null; |
|
71
|
|
|
|
|
72
|
|
|
/** |
|
73
|
|
|
* ContactPerson elements for this role. |
|
74
|
|
|
* |
|
75
|
|
|
* Array of \SAML2\XML\md\ContactPerson objects. |
|
76
|
|
|
* |
|
77
|
|
|
* @var \SAML2\XML\md\ContactPerson[] |
|
78
|
|
|
*/ |
|
79
|
|
|
public $ContactPerson = []; |
|
80
|
|
|
|
|
81
|
|
|
|
|
82
|
|
|
/** |
|
83
|
|
|
* Initialize a RoleDescriptor. |
|
84
|
|
|
* |
|
85
|
|
|
* @param string $elementName The name of this element. |
|
86
|
|
|
* @param \DOMElement|null $xml The XML element we should load. |
|
87
|
|
|
* @throws \Exception |
|
88
|
|
|
*/ |
|
89
|
|
|
protected function __construct(string $elementName, \DOMElement $xml = null) |
|
90
|
|
|
{ |
|
91
|
|
|
parent::__construct($xml); |
|
92
|
|
|
$this->elementName = $elementName; |
|
93
|
|
|
|
|
94
|
|
|
if ($xml === null) { |
|
95
|
|
|
return; |
|
96
|
|
|
} |
|
97
|
|
|
|
|
98
|
|
|
if ($xml->hasAttribute('ID')) { |
|
99
|
|
|
$this->ID = $xml->getAttribute('ID'); |
|
100
|
|
|
} |
|
101
|
|
|
if ($xml->hasAttribute('validUntil')) { |
|
102
|
|
|
$this->validUntil = Utils::xsDateTimeToTimestamp($xml->getAttribute('validUntil')); |
|
103
|
|
|
} |
|
104
|
|
|
if ($xml->hasAttribute('cacheDuration')) { |
|
105
|
|
|
$this->cacheDuration = $xml->getAttribute('cacheDuration'); |
|
106
|
|
|
} |
|
107
|
|
|
|
|
108
|
|
|
if (!$xml->hasAttribute('protocolSupportEnumeration')) { |
|
109
|
|
|
throw new \Exception('Missing protocolSupportEnumeration attribute on '.$xml->localName); |
|
110
|
|
|
} |
|
111
|
|
|
$this->protocolSupportEnumeration = preg_split('/[\s]+/', $xml->getAttribute('protocolSupportEnumeration')); |
|
|
|
|
|
|
112
|
|
|
|
|
113
|
|
|
if ($xml->hasAttribute('errorURL')) { |
|
114
|
|
|
$this->errorURL = $xml->getAttribute('errorURL'); |
|
115
|
|
|
} |
|
116
|
|
|
|
|
117
|
|
|
$this->Extensions = Extensions::getList($xml); |
|
118
|
|
|
|
|
119
|
|
|
foreach (Utils::xpQuery($xml, './saml_metadata:KeyDescriptor') as $kd) { |
|
120
|
|
|
/** @var \DOMElement $kd */ |
|
121
|
|
|
$this->KeyDescriptor[] = new KeyDescriptor($kd); |
|
122
|
|
|
} |
|
123
|
|
|
|
|
124
|
|
|
$organization = Utils::xpQuery($xml, './saml_metadata:Organization'); |
|
125
|
|
|
if (count($organization) > 1) { |
|
126
|
|
|
throw new \Exception('More than one Organization in the entity.'); |
|
127
|
|
|
} elseif (!empty($organization)) { |
|
128
|
|
|
/** @var \DOMElement $organization[0] */ |
|
129
|
|
|
$this->Organization = new Organization($organization[0]); |
|
130
|
|
|
} |
|
131
|
|
|
|
|
132
|
|
|
foreach (Utils::xpQuery($xml, './saml_metadata:ContactPerson') as $cp) { |
|
133
|
|
|
/** @var \DOMElement $cp */ |
|
134
|
|
|
$this->ContactPerson[] = new ContactPerson($cp); |
|
135
|
|
|
} |
|
136
|
|
|
} |
|
137
|
|
|
|
|
138
|
|
|
|
|
139
|
|
|
/** |
|
140
|
|
|
* Collect the value of the ID property. |
|
141
|
|
|
* |
|
142
|
|
|
* @return string|null |
|
143
|
|
|
*/ |
|
144
|
|
|
public function getID() |
|
145
|
|
|
{ |
|
146
|
|
|
return $this->ID; |
|
147
|
|
|
} |
|
148
|
|
|
|
|
149
|
|
|
|
|
150
|
|
|
/** |
|
151
|
|
|
* Set the value of the ID property. |
|
152
|
|
|
* |
|
153
|
|
|
* @param string|null $Id |
|
154
|
|
|
* @return void |
|
155
|
|
|
*/ |
|
156
|
|
|
public function setID(string $Id = null) |
|
157
|
|
|
{ |
|
158
|
|
|
$this->ID = $Id; |
|
159
|
|
|
} |
|
160
|
|
|
|
|
161
|
|
|
|
|
162
|
|
|
/** |
|
163
|
|
|
* Collect the value of the validUntil-property |
|
164
|
|
|
* @return int|null |
|
165
|
|
|
*/ |
|
166
|
|
|
public function getValidUntil() |
|
167
|
|
|
{ |
|
168
|
|
|
return $this->validUntil; |
|
169
|
|
|
} |
|
170
|
|
|
|
|
171
|
|
|
|
|
172
|
|
|
/** |
|
173
|
|
|
* Set the value of the validUntil-property |
|
174
|
|
|
* @param int|null $validUntil |
|
175
|
|
|
* @return void |
|
176
|
|
|
*/ |
|
177
|
|
|
public function setValidUntil(int $validUntil = null) |
|
178
|
|
|
{ |
|
179
|
|
|
$this->validUntil = $validUntil; |
|
180
|
|
|
} |
|
181
|
|
|
|
|
182
|
|
|
|
|
183
|
|
|
/** |
|
184
|
|
|
* Collect the value of the cacheDuration-property |
|
185
|
|
|
* @return string|null |
|
186
|
|
|
*/ |
|
187
|
|
|
public function getCacheDuration() |
|
188
|
|
|
{ |
|
189
|
|
|
return $this->cacheDuration; |
|
190
|
|
|
} |
|
191
|
|
|
|
|
192
|
|
|
|
|
193
|
|
|
/** |
|
194
|
|
|
* Set the value of the cacheDuration-property |
|
195
|
|
|
* @param string|null $cacheDuration |
|
196
|
|
|
* @return void |
|
197
|
|
|
*/ |
|
198
|
|
|
public function setCacheDuration(string $cacheDuration = null) |
|
199
|
|
|
{ |
|
200
|
|
|
$this->cacheDuration = $cacheDuration; |
|
201
|
|
|
} |
|
202
|
|
|
|
|
203
|
|
|
|
|
204
|
|
|
/** |
|
205
|
|
|
* Collect the value of the Extensions property. |
|
206
|
|
|
* |
|
207
|
|
|
* @return \SAML2\XML\Chunk[] |
|
208
|
|
|
*/ |
|
209
|
|
|
public function getExtensions() : array |
|
210
|
|
|
{ |
|
211
|
|
|
return $this->Extensions; |
|
212
|
|
|
} |
|
213
|
|
|
|
|
214
|
|
|
|
|
215
|
|
|
/** |
|
216
|
|
|
* Set the value of the Extensions property. |
|
217
|
|
|
* |
|
218
|
|
|
* @param array $extensions |
|
219
|
|
|
* @return void |
|
220
|
|
|
*/ |
|
221
|
|
|
public function setExtensions(array $extensions) |
|
222
|
|
|
{ |
|
223
|
|
|
$this->Extensions = $extensions; |
|
224
|
|
|
} |
|
225
|
|
|
|
|
226
|
|
|
|
|
227
|
|
|
/** |
|
228
|
|
|
* Add an Extension. |
|
229
|
|
|
* |
|
230
|
|
|
* @param \SAML2\XML\Chunk $extensions The Extensions |
|
231
|
|
|
* @return void |
|
232
|
|
|
*/ |
|
233
|
|
|
public function addExtension(Extensions $extension) |
|
234
|
|
|
{ |
|
235
|
|
|
$this->Extensions[] = $extension; |
|
236
|
|
|
} |
|
237
|
|
|
|
|
238
|
|
|
|
|
239
|
|
|
/** |
|
240
|
|
|
* Set the value of the errorURL property. |
|
241
|
|
|
* |
|
242
|
|
|
* @param string|null $errorURL |
|
243
|
|
|
* @return void |
|
244
|
|
|
*/ |
|
245
|
|
|
public function setErrorURL(string $errorURL = null) |
|
246
|
|
|
{ |
|
247
|
|
|
if (!is_null($errorURL) && !filter_var($errorURL, FILTER_VALIDATE_URL)) { |
|
248
|
|
|
throw new \InvalidArgumentException('RoleDescriptor errorURL is not a valid URL.'); |
|
249
|
|
|
} |
|
250
|
|
|
$this->errorURL = $errorURL; |
|
251
|
|
|
} |
|
252
|
|
|
|
|
253
|
|
|
|
|
254
|
|
|
/** |
|
255
|
|
|
* Collect the value of the errorURL property. |
|
256
|
|
|
* |
|
257
|
|
|
* @return string|null |
|
258
|
|
|
*/ |
|
259
|
|
|
public function getErrorURL() |
|
260
|
|
|
{ |
|
261
|
|
|
return $this->errorURL; |
|
262
|
|
|
} |
|
263
|
|
|
|
|
264
|
|
|
|
|
265
|
|
|
/** |
|
266
|
|
|
* Collect the value of the ProtocolSupportEnumeration property. |
|
267
|
|
|
* |
|
268
|
|
|
* @return string[] |
|
269
|
|
|
*/ |
|
270
|
|
|
public function getProtocolSupportEnumeration() : array |
|
271
|
|
|
{ |
|
272
|
|
|
return $this->protocolSupportEnumeration; |
|
273
|
|
|
} |
|
274
|
|
|
|
|
275
|
|
|
|
|
276
|
|
|
/** |
|
277
|
|
|
* Set the value of the ProtocolSupportEnumeration property. |
|
278
|
|
|
* |
|
279
|
|
|
* @param array $protocols |
|
280
|
|
|
* @return void |
|
281
|
|
|
*/ |
|
282
|
|
|
public function setProtocolSupportEnumeration(array $protocols) |
|
283
|
|
|
{ |
|
284
|
|
|
$this->protocolSupportEnumeration = $protocols; |
|
285
|
|
|
} |
|
286
|
|
|
|
|
287
|
|
|
|
|
288
|
|
|
/** |
|
289
|
|
|
* Add the value to the ProtocolSupportEnumeration property. |
|
290
|
|
|
* |
|
291
|
|
|
* @param string $protocol |
|
292
|
|
|
* @return void |
|
293
|
|
|
*/ |
|
294
|
|
|
public function addProtocolSupportEnumeration(string $protocol) |
|
295
|
|
|
{ |
|
296
|
|
|
$this->protocolSupportEnumeration[] = $protocol; |
|
297
|
|
|
} |
|
298
|
|
|
|
|
299
|
|
|
|
|
300
|
|
|
/** |
|
301
|
|
|
* Collect the value of the Organization property. |
|
302
|
|
|
* |
|
303
|
|
|
* @return \SAML2\XML\md\Organization|null |
|
304
|
|
|
*/ |
|
305
|
|
|
public function getOrganization() |
|
306
|
|
|
{ |
|
307
|
|
|
return $this->Organization; |
|
308
|
|
|
} |
|
309
|
|
|
|
|
310
|
|
|
|
|
311
|
|
|
/** |
|
312
|
|
|
* Set the value of the Organization property. |
|
313
|
|
|
* |
|
314
|
|
|
* @param \SAML2\XML\md\Organization|null $organization |
|
315
|
|
|
* @return void |
|
316
|
|
|
*/ |
|
317
|
|
|
public function setOrganization(Organization $organization = null) |
|
318
|
|
|
{ |
|
319
|
|
|
$this->Organization = $organization; |
|
320
|
|
|
} |
|
321
|
|
|
|
|
322
|
|
|
|
|
323
|
|
|
/** |
|
324
|
|
|
* Collect the value of the ContactPerson property. |
|
325
|
|
|
* |
|
326
|
|
|
* @return \SAML2\XML\md\ContactPerson[] |
|
327
|
|
|
*/ |
|
328
|
|
|
public function getContactPerson() : array |
|
329
|
|
|
{ |
|
330
|
|
|
return $this->ContactPerson; |
|
331
|
|
|
} |
|
332
|
|
|
|
|
333
|
|
|
|
|
334
|
|
|
/** |
|
335
|
|
|
* Set the value of the ContactPerson property. |
|
336
|
|
|
* |
|
337
|
|
|
* @param array $contactPerson |
|
338
|
|
|
* @return void |
|
339
|
|
|
*/ |
|
340
|
|
|
public function setContactPerson(array $contactPerson) |
|
341
|
|
|
{ |
|
342
|
|
|
$this->ContactPerson = $contactPerson; |
|
343
|
|
|
} |
|
344
|
|
|
|
|
345
|
|
|
|
|
346
|
|
|
/** |
|
347
|
|
|
* Add the value to the ContactPerson property. |
|
348
|
|
|
* |
|
349
|
|
|
* @param \SAML2\XML\md\ContactPerson $contactPerson |
|
350
|
|
|
* @return void |
|
351
|
|
|
*/ |
|
352
|
|
|
public function addContactPerson(ContactPerson $contactPerson) |
|
353
|
|
|
{ |
|
354
|
|
|
$this->ContactPerson[] = $contactPerson; |
|
355
|
|
|
} |
|
356
|
|
|
|
|
357
|
|
|
|
|
358
|
|
|
/** |
|
359
|
|
|
* Collect the value of the KeyDescriptor property. |
|
360
|
|
|
* |
|
361
|
|
|
* @return \SAML2\XML\md\KeyDescriptor[] |
|
362
|
|
|
*/ |
|
363
|
|
|
public function getKeyDescriptor() : array |
|
364
|
|
|
{ |
|
365
|
|
|
return $this->KeyDescriptor; |
|
366
|
|
|
} |
|
367
|
|
|
|
|
368
|
|
|
|
|
369
|
|
|
/** |
|
370
|
|
|
* Set the value of the KeyDescriptor property. |
|
371
|
|
|
* |
|
372
|
|
|
* @param array $keyDescriptor |
|
373
|
|
|
* @return void |
|
374
|
|
|
*/ |
|
375
|
|
|
public function setKeyDescriptor(array $keyDescriptor) |
|
376
|
|
|
{ |
|
377
|
|
|
$this->KeyDescriptor = $keyDescriptor; |
|
378
|
|
|
} |
|
379
|
|
|
|
|
380
|
|
|
|
|
381
|
|
|
/** |
|
382
|
|
|
* Add the value to the KeyDescriptor property. |
|
383
|
|
|
* |
|
384
|
|
|
* @param \SAML2\XML\md\KeyDescriptor $keyDescriptor |
|
385
|
|
|
* @return void |
|
386
|
|
|
*/ |
|
387
|
|
|
public function addKeyDescriptor(KeyDescriptor $keyDescriptor) |
|
388
|
|
|
{ |
|
389
|
|
|
$this->KeyDescriptor[] = $keyDescriptor; |
|
390
|
|
|
} |
|
391
|
|
|
|
|
392
|
|
|
|
|
393
|
|
|
/** |
|
394
|
|
|
* Add this RoleDescriptor to an EntityDescriptor. |
|
395
|
|
|
* |
|
396
|
|
|
* @param \DOMElement $parent The EntityDescriptor we should append this endpoint to. |
|
397
|
|
|
* @return \DOMElement |
|
398
|
|
|
*/ |
|
399
|
|
|
protected function toXML(\DOMElement $parent) : \DOMElement |
|
400
|
|
|
{ |
|
401
|
|
|
$e = $parent->ownerDocument->createElementNS(Constants::NS_MD, $this->elementName); |
|
402
|
|
|
$parent->appendChild($e); |
|
403
|
|
|
|
|
404
|
|
|
if ($this->ID !== null) { |
|
405
|
|
|
$e->setAttribute('ID', $this->ID); |
|
406
|
|
|
} |
|
407
|
|
|
|
|
408
|
|
|
if ($this->validUntil !== null) { |
|
409
|
|
|
$e->setAttribute('validUntil', gmdate('Y-m-d\TH:i:s\Z', $this->validUntil)); |
|
410
|
|
|
} |
|
411
|
|
|
|
|
412
|
|
|
if ($this->cacheDuration !== null) { |
|
413
|
|
|
$e->setAttribute('cacheDuration', $this->cacheDuration); |
|
414
|
|
|
} |
|
415
|
|
|
|
|
416
|
|
|
$e->setAttribute('protocolSupportEnumeration', implode(' ', $this->protocolSupportEnumeration)); |
|
417
|
|
|
|
|
418
|
|
|
if ($this->errorURL !== null) { |
|
419
|
|
|
$e->setAttribute('errorURL', $this->errorURL); |
|
420
|
|
|
} |
|
421
|
|
|
|
|
422
|
|
|
Extensions::addList($e, $this->Extensions); |
|
423
|
|
|
|
|
424
|
|
|
foreach ($this->KeyDescriptor as $kd) { |
|
425
|
|
|
$kd->toXML($e); |
|
426
|
|
|
} |
|
427
|
|
|
|
|
428
|
|
|
if ($this->Organization !== null) { |
|
429
|
|
|
$this->Organization->toXML($e); |
|
430
|
|
|
} |
|
431
|
|
|
|
|
432
|
|
|
foreach ($this->ContactPerson as $cp) { |
|
433
|
|
|
$cp->toXML($e); |
|
434
|
|
|
} |
|
435
|
|
|
|
|
436
|
|
|
return $e; |
|
437
|
|
|
} |
|
438
|
|
|
} |
|
439
|
|
|
|
Our type inference engine has found a suspicous assignment of a value to a property. This check raises an issue when a value that can be of a mixed type is assigned to a property that is type hinted more strictly.
For example, imagine you have a variable
$accountIdthat can either hold an Id object or false (if there is no account id yet). Your code now assigns that value to theidproperty of an instance of theAccountclass. This class holds a proper account, so the id value must no longer be false.Either this assignment is in error or a type check should be added for that assignment.