simplesamlphp /
saml2
This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include, or for example
via PHP's auto-loading mechanism.
| 1 | <?php |
||
| 2 | |||
| 3 | declare(strict_types=1); |
||
| 4 | |||
| 5 | namespace SimpleSAML\SAML2\XML\samlp; |
||
| 6 | |||
| 7 | use DOMElement; |
||
| 8 | use SimpleSAML\SAML2\Constants as C; |
||
| 9 | use SimpleSAML\SAML2\Type\SAMLAnyURIValue; |
||
| 10 | use SimpleSAML\SAML2\Type\SAMLDateTimeValue; |
||
| 11 | use SimpleSAML\SAML2\Utils\XPath; |
||
| 12 | use SimpleSAML\SAML2\XML\ExtendableElementTrait; |
||
| 13 | use SimpleSAML\SAML2\XML\saml\Issuer; |
||
| 14 | use SimpleSAML\SAML2\XML\SignableElementTrait; |
||
| 15 | use SimpleSAML\SAML2\XML\SignedElementTrait; |
||
| 16 | use SimpleSAML\XMLSchema\Type\IDValue; |
||
| 17 | use SimpleSAML\XMLSecurity\XML\SignableElementInterface; |
||
| 18 | use SimpleSAML\XMLSecurity\XML\SignedElementInterface; |
||
| 19 | |||
| 20 | use function array_pop; |
||
| 21 | |||
| 22 | /** |
||
| 23 | * Base class for all SAML 2 messages. |
||
| 24 | * |
||
| 25 | * Implements what is common between the samlp:RequestAbstractType and |
||
| 26 | * samlp:StatusResponseType element types. |
||
| 27 | * |
||
| 28 | * @package simplesamlphp/saml2 |
||
| 29 | */ |
||
| 30 | abstract class AbstractMessage extends AbstractSamlpElement implements SignableElementInterface, SignedElementInterface |
||
| 31 | { |
||
| 32 | use ExtendableElementTrait; |
||
| 33 | use SignableElementTrait; |
||
|
0 ignored issues
–
show
introduced
by
Loading history...
|
|||
| 34 | use SignedElementTrait { |
||
|
0 ignored issues
–
show
|
|||
| 35 | SignedElementTrait::getBlacklistedAlgorithms insteadof SignableElementTrait; |
||
| 36 | } |
||
| 37 | |||
| 38 | |||
| 39 | /** @var bool */ |
||
| 40 | protected bool $messageContainedSignatureUponConstruction = false; |
||
| 41 | |||
| 42 | /** |
||
| 43 | * The original signed XML |
||
| 44 | * |
||
| 45 | * @var \DOMElement |
||
| 46 | * @psalm-suppress PropertyNotSetInConstructor |
||
| 47 | */ |
||
| 48 | protected DOMElement $xml; |
||
| 49 | |||
| 50 | |||
| 51 | /** |
||
| 52 | * Initialize a message. |
||
| 53 | * |
||
| 54 | * @param \SimpleSAML\SAML2\XML\saml\Issuer|null $issuer |
||
| 55 | * @param \SimpleSAML\XMLSchema\Type\IDValue $id |
||
| 56 | * @param \SimpleSAML\SAML2\Type\SAMLDateTimeValue|null $issueInstant |
||
| 57 | * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $destination |
||
| 58 | * @param \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null $consent |
||
| 59 | * @param \SimpleSAML\SAML2\XML\samlp\Extensions $extensions |
||
| 60 | * |
||
| 61 | * @throws \Exception |
||
| 62 | */ |
||
| 63 | protected function __construct( |
||
| 64 | protected IDValue $id, |
||
| 65 | protected ?Issuer $issuer = null, |
||
| 66 | protected ?SAMLDateTimeValue $issueInstant = null, |
||
| 67 | protected ?SAMLAnyURIValue $destination = null, |
||
| 68 | protected ?SAMLAnyURIValue $consent = null, |
||
| 69 | ?Extensions $extensions = null, |
||
| 70 | ) { |
||
| 71 | $this->setExtensions($extensions); |
||
| 72 | } |
||
| 73 | |||
| 74 | |||
| 75 | /** |
||
| 76 | * Retrieve the identifier of this message. |
||
| 77 | * |
||
| 78 | * @return \SimpleSAML\XMLSchema\Type\IDValue The identifier of this message |
||
| 79 | */ |
||
| 80 | public function getId(): IDValue |
||
| 81 | { |
||
| 82 | return $this->id; |
||
| 83 | } |
||
| 84 | |||
| 85 | |||
| 86 | /** |
||
| 87 | * Retrieve the issue timestamp of this message. |
||
| 88 | * |
||
| 89 | * @return \SimpleSAML\SAML2\Type\SAMLDateTimeValue The issue timestamp of this message, as an UNIX timestamp |
||
| 90 | */ |
||
| 91 | public function getIssueInstant(): SAMLDateTimeValue |
||
| 92 | { |
||
| 93 | return $this->issueInstant; |
||
|
0 ignored issues
–
show
|
|||
| 94 | } |
||
| 95 | |||
| 96 | |||
| 97 | /** |
||
| 98 | * Retrieve the destination of this message. |
||
| 99 | * |
||
| 100 | * @return \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null The destination of this message, |
||
| 101 | * or NULL if no destination is given |
||
| 102 | */ |
||
| 103 | public function getDestination(): ?SAMLAnyURIValue |
||
| 104 | { |
||
| 105 | return $this->destination; |
||
| 106 | } |
||
| 107 | |||
| 108 | |||
| 109 | /** |
||
| 110 | * Get the given consent for this message. |
||
| 111 | * Most likely (though not required) a value of urn:oasis:names:tc:SAML:2.0:consent. |
||
| 112 | * |
||
| 113 | * @see \SimpleSAML\SAML2\Constants |
||
| 114 | * @return \SimpleSAML\SAML2\Type\SAMLAnyURIValue|null Consent |
||
| 115 | */ |
||
| 116 | public function getConsent(): ?SAMLAnyURIValue |
||
| 117 | { |
||
| 118 | return $this->consent; |
||
| 119 | } |
||
| 120 | |||
| 121 | |||
| 122 | /** |
||
| 123 | * Retrieve the issuer if this message. |
||
| 124 | * |
||
| 125 | * @return \SimpleSAML\SAML2\XML\saml\Issuer|null The issuer of this message, or NULL if no issuer is given |
||
| 126 | */ |
||
| 127 | public function getIssuer(): ?Issuer |
||
| 128 | { |
||
| 129 | return $this->issuer; |
||
| 130 | } |
||
| 131 | |||
| 132 | |||
| 133 | /** |
||
| 134 | * Query whether or not the message contained a signature at the root level when the object was constructed. |
||
| 135 | * |
||
| 136 | * @return bool |
||
| 137 | */ |
||
| 138 | public function isMessageConstructedWithSignature(): bool |
||
| 139 | { |
||
| 140 | return $this->messageContainedSignatureUponConstruction; |
||
| 141 | } |
||
| 142 | |||
| 143 | |||
| 144 | /** |
||
| 145 | * Get the XML element. |
||
| 146 | * |
||
| 147 | * @return \DOMElement |
||
| 148 | */ |
||
| 149 | public function getXML(): DOMElement |
||
| 150 | { |
||
| 151 | return $this->xml; |
||
| 152 | } |
||
| 153 | |||
| 154 | |||
| 155 | /** |
||
| 156 | * Set the XML element. |
||
| 157 | * |
||
| 158 | * @param \DOMElement $xml |
||
| 159 | */ |
||
| 160 | protected function setXML(DOMElement $xml): void |
||
| 161 | { |
||
| 162 | $this->xml = $xml; |
||
| 163 | } |
||
| 164 | |||
| 165 | |||
| 166 | /** |
||
| 167 | * @return \DOMElement |
||
| 168 | */ |
||
| 169 | protected function getOriginalXML(): DOMElement |
||
| 170 | { |
||
| 171 | return $this->xml ?? $this->toUnsignedXML(); |
||
| 172 | } |
||
| 173 | |||
| 174 | |||
| 175 | /** |
||
| 176 | * Convert this message to an unsigned XML document. |
||
| 177 | * This method does not sign the resulting XML document. |
||
| 178 | * |
||
| 179 | * @return \DOMElement The root element of the DOM tree |
||
| 180 | */ |
||
| 181 | protected function toUnsignedXML(?DOMElement $parent = null): DOMElement |
||
| 182 | { |
||
| 183 | $root = $this->instantiateParentElement($parent); |
||
| 184 | |||
| 185 | /* Ugly hack to add another namespace declaration to the root element. */ |
||
| 186 | // $root->setAttributeNS(C::NS_SAML, 'saml:tmp', 'tmp'); |
||
| 187 | // $root->removeAttributeNS(C::NS_SAML, 'tmp'); |
||
| 188 | |||
| 189 | $root->setAttribute('Version', '2.0'); |
||
| 190 | $root->setAttribute('ID', $this->getId()->getValue()); |
||
| 191 | $root->setAttribute('IssueInstant', $this->getIssueInstant()->getValue()); |
||
| 192 | |||
| 193 | if ($this->getDestination() !== null) { |
||
| 194 | $root->setAttribute('Destination', $this->getDestination()->getValue()); |
||
| 195 | } |
||
| 196 | |||
| 197 | if ($this->getConsent() !== null && $this->getConsent()->getValue() !== C::CONSENT_UNSPECIFIED) { |
||
| 198 | $root->setAttribute('Consent', $this->getConsent()->getValue()); |
||
| 199 | } |
||
| 200 | |||
| 201 | $this->getIssuer()?->toXML($root); |
||
| 202 | |||
| 203 | $extensions = $this->getExtensions(); |
||
| 204 | if ($extensions !== null && !$extensions->isEmptyElement()) { |
||
| 205 | $extensions->toXML($root); |
||
| 206 | } |
||
| 207 | |||
| 208 | return $root; |
||
| 209 | } |
||
| 210 | |||
| 211 | |||
| 212 | /** |
||
| 213 | * Create XML from this class |
||
| 214 | * |
||
| 215 | * @param \DOMElement|null $parent |
||
| 216 | * @return \DOMElement |
||
| 217 | */ |
||
| 218 | public function toXML(?DOMElement $parent = null): DOMElement |
||
| 219 | { |
||
| 220 | if ($this->isSigned() === true && $this->signer === null) { |
||
| 221 | // We already have a signed document and no signer was set to re-sign it |
||
| 222 | if ($parent === null) { |
||
| 223 | return $this->xml; |
||
| 224 | } |
||
| 225 | |||
| 226 | $node = $parent->ownerDocument?->importNode($this->getXML(), true); |
||
| 227 | $parent->appendChild($node); |
||
| 228 | return $parent; |
||
| 229 | } |
||
| 230 | |||
| 231 | $e = $this->toUnsignedXML($parent); |
||
| 232 | |||
| 233 | if ($this->signer !== null) { |
||
| 234 | $signedXML = $this->doSign($e); |
||
| 235 | |||
| 236 | // Test for an Issuer |
||
| 237 | $messageElements = XPath::xpQuery($signedXML, './saml_assertion:Issuer', XPath::getXPath($signedXML)); |
||
| 238 | $issuer = array_pop($messageElements); |
||
| 239 | |||
| 240 | $signedXML->insertBefore($this->signature?->toXML($signedXML), $issuer->nextSibling); |
||
| 241 | return $signedXML; |
||
| 242 | } |
||
| 243 | |||
| 244 | return $e; |
||
| 245 | } |
||
| 246 | } |
||
| 247 |