Passed
Push — release-4-alpha ( 7ffb8e...684de5 )
by Jaime Pérez
02:24
created

HTTPArtifact::receive()   B

Complexity

Conditions 9
Paths 17

Size

Total Lines 69
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
eloc 35
nc 17
nop 0
dl 0
loc 69
rs 8.0555
c 0
b 0
f 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
declare(strict_types=1);
4
5
namespace SAML2;
6
7
use RobRichards\XMLSecLibs\XMLSecurityKey;
8
use SAML2\Utilities\Temporal;
9
use \SimpleSAML\Configuration;
1 ignored issue
show
Bug introduced by
The type SimpleSAML\Configuration 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\Metadata\MetaDataStorageHandler;
1 ignored issue
show
Bug introduced by
The type SimpleSAML\Metadata\MetaDataStorageHandler 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\Store;
1 ignored issue
show
Bug introduced by
The type SimpleSAML\Store 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
13
/**
14
 * Class which implements the HTTP-Artifact binding.
15
 *
16
 * @author  Danny Bollaert, UGent AS. <[email protected]>
17
 * @package SimpleSAMLphp
18
 */
19
class HTTPArtifact extends Binding
20
{
21
    /**
22
     * @var \SimpleSAML\Configuration
23
     */
24
    private $spMetadata;
25
26
27
    /**
28
     * Create the redirect URL for a message.
29
     *
30
     * @param  \SAML2\Message $message The message.
31
     * @throws \Exception
32
     * @return string        The URL the user should be redirected to in order to send a message.
33
     */
34
    public function getRedirectURL(Message $message) : string
35
    {
36
        $store = Store::getInstance();
37
        if ($store === false) {
38
            throw new \Exception('Unable to send artifact without a datastore configured.');
39
        }
40
41
        $generatedId = pack('H*', bin2hex(openssl_random_pseudo_bytes(20)));
42
        $issuer = $message->getIssuer();
43
        if ($issuer === null) {
44
            throw new \Exception('Cannot get redirect URL, no Issuer set in the message.');
45
        }
46
        $artifact = base64_encode("\x00\x04\x00\x00".sha1($issuer->getValue(), true).$generatedId);
47
        $artifactData = $message->toUnsignedXML();
48
        $artifactDataString = $artifactData->ownerDocument->saveXML($artifactData);
49
50
        $store->set('artifact', $artifact, $artifactDataString, Temporal::getTime() + 15*60);
51
52
        $params = [
53
            'SAMLart' => $artifact,
54
        ];
55
        $relayState = $message->getRelayState();
56
        if ($relayState !== null) {
57
            $params['RelayState'] = $relayState;
58
        }
59
60
        $destination = $message->getDestination();
61
        if ($destination === null) {
62
            throw new \Exception('Cannot get redirect URL, no destination set in the message.');
63
        }
64
        return \SimpleSAML\Utils\HTTP::addURLparameters($destination, $params);
1 ignored issue
show
Bug introduced by
The type SimpleSAML\Utils\HTTP 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...
65
    }
66
67
68
    /**
69
     * Send a SAML 2 message using the HTTP-Redirect binding.
70
     *
71
     * Note: This function never returns.
72
     *
73
     * @param \SAML2\Message $message The message we should send.
74
     * @return void
75
     */
76
    public function send(Message $message)
77
    {
78
        $destination = $this->getRedirectURL($message);
79
        Utils::getContainer()->redirect($destination);
80
    }
81
82
83
    /**
84
     * Receive a SAML 2 message sent using the HTTP-Artifact binding.
85
     *
86
     * Throws an exception if it is unable receive the message.
87
     *
88
     * @throws \Exception
89
     * @return \SAML2\Message|null The received message.
90
     */
91
    public function receive()
92
    {
93
        if (array_key_exists('SAMLart', $_REQUEST)) {
94
            $artifact = base64_decode($_REQUEST['SAMLart']);
95
            $endpointIndex = bin2hex(substr($artifact, 2, 2));
96
            $sourceId = bin2hex(substr($artifact, 4, 20));
97
        } else {
98
            throw new \Exception('Missing SAMLart parameter.');
99
        }
100
101
        $metadataHandler = MetaDataStorageHandler::getMetadataHandler();
102
103
        $idpMetadata = $metadataHandler->getMetaDataConfigForSha1($sourceId, 'saml20-idp-remote');
104
105
        if ($idpMetadata === null) {
106
            throw new \Exception('No metadata found for remote provider with SHA1 ID: '.var_export($sourceId, true));
107
        }
108
109
        $endpoint = null;
110
        foreach ($idpMetadata->getEndpoints('ArtifactResolutionService') as $ep) {
111
            if ($ep['index'] === hexdec($endpointIndex)) {
112
                $endpoint = $ep;
113
                break;
114
            }
115
        }
116
117
        if ($endpoint === null) {
118
            throw new \Exception('No ArtifactResolutionService with the correct index.');
119
        }
120
121
        Utils::getContainer()->getLogger()->debug("ArtifactResolutionService endpoint being used is := ".$endpoint['Location']);
122
123
        //Construct the ArtifactResolve Request
124
        $ar = new ArtifactResolve();
125
126
        /* Set the request attributes */
127
128
        $ar->setIssuer($this->spMetadata->getString('entityid'));
129
        $ar->setArtifact($_REQUEST['SAMLart']);
130
        $ar->setDestination($endpoint['Location']);
131
132
        /* Sign the request */
133
        \SimpleSAML\Module\saml\Message::addSign($this->spMetadata, $idpMetadata, $ar); // Shoaib - moved from the SOAPClient.
1 ignored issue
show
Bug introduced by
The type SimpleSAML\Module\saml\Message 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...
134
135
        $soap = new SOAPClient();
0 ignored issues
show
Bug introduced by
The type SAML2\SOAPClient was not found. Did you mean SOAPClient? If so, make sure to prefix the type with \.
Loading history...
136
137
        // Send message through SoapClient
138
        /** @var \SAML2\ArtifactResponse $artifactResponse */
139
        $artifactResponse = $soap->send($ar, $this->spMetadata);
140
141
        if (!$artifactResponse->isSuccess()) {
142
            throw new \Exception('Received error from ArtifactResolutionService.');
143
        }
144
145
        $xml = $artifactResponse->getAny();
146
        if ($xml === null) {
147
            /* Empty ArtifactResponse - possibly because of Artifact replay? */
148
149
            throw new \Exception('Empty ArtifactResponse received, maybe a replay?');
150
        }
151
152
        $samlResponse = Message::fromXML($xml);
153
        $samlResponse->addValidator([get_class($this), 'validateSignature'], $artifactResponse);
154
155
        if (isset($_REQUEST['RelayState'])) {
156
            $samlResponse->setRelayState($_REQUEST['RelayState']);
157
        }
158
159
        return $samlResponse;
160
    }
161
162
163
    /**
164
     * @param \SimpleSAML\Configuration $sp
165
     * @return void
166
     */
167
    public function setSPMetadata(Configuration $sp)
168
    {
169
        $this->spMetadata = $sp;
170
    }
171
172
173
    /**
174
     * A validator which returns true if the ArtifactResponse was signed with the given key
175
     *
176
     * @param \SAML2\ArtifactResponse $message
177
     * @param XMLSecurityKey $key
178
     * @return bool
179
     */
180
    public static function validateSignature(ArtifactResponse $message, XMLSecurityKey $key) : bool
181
    {
182
        return $message->validate($key);
183
    }
184
}
185