AttributeQuery::toUnsignedXML()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 4
nc 2
nop 1
dl 0
loc 9
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace SimpleSAML\SAML2\XML\samlp;
6
7
use DOMElement;
8
use SimpleSAML\SAML2\Assert\Assert;
9
use SimpleSAML\SAML2\Constants as C;
0 ignored issues
show
Bug introduced by
The type SimpleSAML\SAML2\Constants was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
10
use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooHighException;
0 ignored issues
show
Bug introduced by
The type SimpleSAML\SAML2\Excepti...VersionTooHighException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
11
use SimpleSAML\SAML2\Exception\Protocol\RequestVersionTooLowException;
0 ignored issues
show
Bug introduced by
The type SimpleSAML\SAML2\Excepti...tVersionTooLowException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
12
use SimpleSAML\SAML2\Exception\ProtocolViolationException;
13
use SimpleSAML\SAML2\Type\SAMLAnyURIValue;
14
use SimpleSAML\SAML2\Type\SAMLDateTimeValue;
0 ignored issues
show
Bug introduced by
The type SimpleSAML\SAML2\Type\SAMLDateTimeValue was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
15
use SimpleSAML\SAML2\Type\SAMLStringValue;
16
use SimpleSAML\SAML2\XML\saml\Attribute;
17
use SimpleSAML\SAML2\XML\saml\Issuer;
18
use SimpleSAML\SAML2\XML\saml\Subject;
19
use SimpleSAML\XML\SchemaValidatableElementInterface;
20
use SimpleSAML\XML\SchemaValidatableElementTrait;
21
use SimpleSAML\XMLSchema\Exception\InvalidDOMElementException;
22
use SimpleSAML\XMLSchema\Exception\MissingElementException;
23
use SimpleSAML\XMLSchema\Exception\TooManyElementsException;
24
use SimpleSAML\XMLSchema\Type\IDValue;
0 ignored issues
show
Bug introduced by
The type SimpleSAML\XMLSchema\Type\IDValue was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
25
use SimpleSAML\XMLSecurity\XML\ds\Signature;
26
27
use function array_pop;
28
use function in_array;
29
30
/**
31
 * Class for SAML 2 attribute query messages.
32
 *
33
 * An attribute query asks for a set of attributes. The following
34
 * rules apply:
35
 *
36
 * - If no attributes are present in the query, all attributes should be
37
 *   returned.
38
 * - If any attributes are present, only those attributes which are present
39
 *   in the query should be returned.
40
 * - If an attribute contains any attribute values, only the attribute values
41
 *   which match those in the query should be returned.
42
 *
43
 * @package simplesamlphp/saml2
44
 */
45
class AttributeQuery extends AbstractSubjectQuery implements SchemaValidatableElementInterface
46
{
47
    use SchemaValidatableElementTrait;
48
49
50
    /**
51
     * Constructor for SAML 2 AttributeQuery.
52
     *
53
     * @param \SimpleSAML\XMLSchema\Type\IDValue $id
54
     * @param \SimpleSAML\SAML2\XML\saml\Subject $subject
55
     * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue $issueInstant
56
     * @param \SimpleSAML\SAML2\XML\saml\Attribute[] $attributes
57
     * @param \SimpleSAML\SAML2\XML\saml\Issuer $issuer
58
     * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $destination
59
     * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $consent
60
     * @param \SimpleSAML\SAML2\XML\samlp\Extensions $extensions
61
     */
62
    final public function __construct(
63
        IDValue $id,
64
        Subject $subject,
65
        SAMLDateTimeValue $issueInstant,
66
        protected array $attributes = [],
67
        ?Issuer $issuer = null,
68
        ?SAMLAnyURIValue $destination = null,
69
        ?SAMLAnyURIValue $consent = null,
70
        ?Extensions $extensions = null,
0 ignored issues
show
Bug introduced by
The type SimpleSAML\SAML2\XML\samlp\Extensions was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
71
    ) {
72
        Assert::maxCount($attributes, C::UNBOUNDED_LIMIT);
73
        Assert::allIsInstanceOf($attributes, Attribute::class);
74
75
        $cache = [];
76
        foreach ($attributes as $attribute) {
77
            $name = $attribute->getName();
78
            $nameFormat = $attribute->getNameFormat()?->getValue() ?? C::NAMEFORMAT_UNSPECIFIED;
79
80
            if (isset($cache[$nameFormat])) {
81
                Assert::true(
82
                    !in_array($name, $cache[$nameFormat], true),
83
                    'A single query MUST NOT contain two <saml:Attribute> elements with the same Name and NameFormat.',
84
                    ProtocolViolationException::class,
85
                );
86
            }
87
            $cache[$nameFormat][] = $name;
88
        }
89
        unset($cache);
90
91
        parent::__construct($id, $subject, $issuer, $issueInstant, $destination, $consent, $extensions);
92
    }
93
94
95
    /**
96
     * Retrieve all requested attributes.
97
     *
98
     * @return \SimpleSAML\SAML2\XML\saml\Attribute[] All requested attributes, as an associative array.
99
     */
100
    public function getAttributes(): array
101
    {
102
        return $this->attributes;
103
    }
104
105
106
    /**
107
     * Create a class from XML
108
     *
109
     * @throws \SimpleSAML\XMLSchema\Exception\InvalidDOMElementException
110
     *   if the qualified name of the supplied element is wrong
111
     * @throws \SimpleSAML\XMLSchema\Exception\MissingAttributeException
112
     *   if the supplied element is missing one of the mandatory attributes
113
     * @throws \SimpleSAML\XMLSchema\Exception\MissingElementException
114
     *   if one of the mandatory child-elements is missing
115
     * @throws \SimpleSAML\XMLSchema\Exception\TooManyElementsException
116
     *   if too many child-elements of a type are specified
117
     */
118
    public static function fromXML(DOMElement $xml): static
119
    {
120
        Assert::same($xml->localName, 'AttributeQuery', InvalidDOMElementException::class);
121
        Assert::same($xml->namespaceURI, AttributeQuery::NS, InvalidDOMElementException::class);
122
123
        $version = self::getAttribute($xml, 'Version', SAMLStringValue::class);
124
        Assert::true(version_compare('2.0', strval($version), '<='), RequestVersionTooLowException::class);
125
        Assert::true(version_compare('2.0', strval($version), '>='), RequestVersionTooHighException::class);
126
127
        $issuer = Issuer::getChildrenOfClass($xml);
128
        Assert::countBetween($issuer, 0, 1);
129
130
        $extensions = Extensions::getChildrenOfClass($xml);
131
        Assert::maxCount(
132
            $extensions,
133
            1,
134
            'Only one saml:Extensions element is allowed.',
135
            TooManyElementsException::class,
136
        );
137
138
        $subject = Subject::getChildrenOfClass($xml);
139
        Assert::notEmpty($subject, 'Missing subject in subject query.', MissingElementException::class);
140
        Assert::maxCount(
141
            $subject,
142
            1,
143
            'More than one <saml:Subject> in AttributeQuery',
144
            TooManyElementsException::class,
145
        );
146
147
        $signature = Signature::getChildrenOfClass($xml);
148
        Assert::maxCount($signature, 1, 'Only one ds:Signature element is allowed.', TooManyElementsException::class);
149
150
        $request = new static(
151
            self::getAttribute($xml, 'ID', IDValue::class),
152
            array_pop($subject),
153
            self::getAttribute($xml, 'IssueInstant', SAMLDateTimeValue::class),
154
            Attribute::getChildrenOfClass($xml),
155
            array_pop($issuer),
156
            self::getOptionalAttribute($xml, 'Destination', SAMLAnyURIValue::class, null),
157
            self::getOptionalAttribute($xml, 'Consent', SAMLAnyURIValue::class, null),
158
            array_pop($extensions),
159
        );
160
161
        if (!empty($signature)) {
162
            $request->setSignature($signature[0]);
163
            $request->setXML($xml);
164
        }
165
166
        return $request;
167
    }
168
169
170
    /**
171
     * Convert this message to an unsigned XML document.
172
     * This method does not sign the resulting XML document.
173
     */
174
    protected function toUnsignedXML(?DOMElement $parent = null): DOMElement
175
    {
176
        $e = parent::toUnsignedXML($parent);
177
178
        foreach ($this->getAttributes() as $attribute) {
179
            $attribute->toXML($e);
180
        }
181
182
        return $e;
183
    }
184
}
185