Completed
Pull Request — master (#9)
by Asmir
148:13 queued 118:12
created

WsSecurityFilterRequest::filterDom()   C

Complexity

Conditions 9
Paths 24

Size

Total Lines 47
Code Lines 29

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 47
rs 5.2941
c 0
b 0
f 0
cc 9
eloc 29
nc 24
nop 2
1
<?php
2
3
namespace GoetasWebservices\SoapServices\SoapClient\WssWsSecurity;
4
5
use ass\XmlSecurity\DSig as XmlSecurityDSig;
6
use ass\XmlSecurity\Enc as XmlSecurityEnc;
7
8
class WsSecurityFilterRequest extends AbstractWsSecurityFilter
9
{
10
    /**
11
     * Web Services Security: SOAP Message Security 1.0 (WS-Security 2004)
12
     */
13
    const NAME_WSS_SMS = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0';
14
15
    /**
16
     * Web Services Security UsernameToken Profile 1.0
17
     */
18
    const NAME_WSS_UTP = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0';
19
20
    /**
21
     * Web Services Security X.509 Certificate Token Profile
22
     */
23
    const NAME_WSS_X509 = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0';
24
25
    /**
26
     * The date format to be used with {@link \DateTime}
27
     */
28
    const DATETIME_FORMAT = 'Y-m-d\TH:i:s.000\Z';
29
30
    /**
31
     * (X509 3.2.1) Reference to a Subject Key Identifier
32
     */
33
    const TOKEN_REFERENCE_SUBJECT_KEY_IDENTIFIER = 0;
34
35
    /**
36
     * (X509 3.2.1) Reference to a Security Token
37
     */
38
    const TOKEN_REFERENCE_SECURITY_TOKEN = 1;
39
40
    /**
41
     * (SMS_1.1 7.3) Key Identifiers
42
     */
43
    const TOKEN_REFERENCE_THUMBPRINT_SHA1 = 2;
44
45
    /**
46
     * (SMS 10) Add security timestamp.
47
     *
48
     * @var boolean
49
     */
50
    private $addTimestamp = true;
51
52
    /**
53
     * Encrypt the signature?
54
     *
55
     * @var boolean
56
     */
57
    private $encryptSignature = false;
58
59
    /**
60
     * (SMS 10) Security timestamp expires time in seconds.
61
     *
62
     * @var int
63
     */
64
    private $expires = 300;
65
66
    /**
67
     * Sign all headers.
68
     *
69
     * @var boolean
70
     */
71
    private $signAllHeaders = false;
72
73
    /**
74
     * @var \DateTime
75
     */
76
    private $initialTimestamp;
77
78
    /**
79
     * (X509 3.2) Token reference type for encryption.
80
     *
81
     * @var int
82
     */
83
    private $tokenReferenceEncryption = null;
84
85
    /**
86
     * (X509 3.2) Token reference type for signature.
87
     *
88
     * @var int
89
     */
90
    private $tokenReferenceSignature = null;
91
92
93
    public function setTimestampOptions($addTimestamp = true, $expires = 300)
94
    {
95
        $this->addTimestamp = $addTimestamp;
96
        $this->expires = $expires;
97
    }
98
99
    /**
100
     * @param \DateTime $initialTimestamp
101
     */
102
    public function __construct(\DateTime $initialTimestamp = null)
103
    {
104
        $this->initialTimestamp = $initialTimestamp;
105
    }
106
107
    /**
108
     * Set security options.
109
     *
110
     * @param int $tokenReference self::TOKEN_REFERENCE_SUBJECT_KEY_IDENTIFIER | self::TOKEN_REFERENCE_SECURITY_TOKEN | self::TOKEN_REFERENCE_THUMBPRINT_SHA1
111
     * @param boolean $encryptSignature Encrypt signature
112
     *
113
     * @return void
114
     */
115
    public function setSecurityOptionsEncryption($tokenReference, $encryptSignature = false)
116
    {
117
        $this->tokenReferenceEncryption = $tokenReference;
118
        $this->encryptSignature = $encryptSignature;
119
    }
120
121
    /**
122
     * Set security options.
123
     *
124
     * @param int $tokenReference self::TOKEN_REFERENCE_SUBJECT_KEY_IDENTIFIER | self::TOKEN_REFERENCE_SECURITY_TOKEN | self::TOKEN_REFERENCE_THUMBPRINT_SHA1
125
     * @param boolean $signAllHeaders Sign all headers?
126
     *
127
     * @return void
128
     */
129
    public function setSecurityOptionsSignature($tokenReference, $signAllHeaders = false)
130
    {
131
        $this->tokenReferenceSignature = $tokenReference;
132
        $this->signAllHeaders = $signAllHeaders;
133
    }
134
135
    /**
136
     * Adds the configured KeyInfo to the parentNode.
137
     *
138
     * @param \DOMDocument $dom
139
     * @param int $tokenReference Token reference type
140
     * @param string $guid Unique ID
141
     * @param XmlSecurityKey $xmlSecurityKey XML security key
142
     *
143
     * @return \DOMElement
144
     */
145
    private function createKeyInfo(\DOMDocument $dom, $tokenReference, $guid, XmlSecurityKey $xmlSecurityKey = null)
146
    {
147
        $keyInfo = $dom->createElementNS(XmlSecurityDSig::NS_XMLDSIG, 'KeyInfo');
148
        $securityTokenReference = $dom->createElementNS(self::NS_WSS, 'SecurityTokenReference');
149
        $keyInfo->appendChild($securityTokenReference);
150
        // security token
151
        if (self::TOKEN_REFERENCE_SECURITY_TOKEN === $tokenReference) {
152
            $reference = $dom->createElementNS(self::NS_WSS, 'Reference');
153
            $reference->setAttribute('URI', '#' . $guid);
154
            if (null !== $xmlSecurityKey) {
155
                $reference->setAttribute('ValueType', self::NAME_WSS_X509 . '#X509v3');
156
            }
157
            $securityTokenReference->appendChild($reference);
158
            // subject key identifier
159
        } elseif (self::TOKEN_REFERENCE_SUBJECT_KEY_IDENTIFIER === $tokenReference && null !== $xmlSecurityKey) {
160
            $keyIdentifier = $dom->createElementNS(self::NS_WSS, 'KeyIdentifier');
161
            $keyIdentifier->setAttribute('EncodingType', self::NAME_WSS_SMS . '#Base64Binary');
162
            $keyIdentifier->setAttribute('ValueType', self::NAME_WSS_X509 . '#509SubjectKeyIdentifier');
163
            $securityTokenReference->appendChild($keyIdentifier);
164
            $certificate = $xmlSecurityKey->getX509SubjectKeyIdentifier();
165
            $dataNode = new \DOMText($certificate);
166
            $keyIdentifier->appendChild($dataNode);
167
            // thumbprint sha1
168
        } elseif (self::TOKEN_REFERENCE_THUMBPRINT_SHA1 === $tokenReference && null !== $xmlSecurityKey) {
169
            $keyIdentifier = $dom->createElementNS(self::NS_WSS, 'KeyIdentifier');
170
            $keyIdentifier->setAttribute('EncodingType', self::NAME_WSS_SMS . '#Base64Binary');
171
            $keyIdentifier->setAttribute('ValueType', self::NAME_WSS_SMS_1_1 . '#ThumbprintSHA1');
172
            $securityTokenReference->appendChild($keyIdentifier);
173
            $thumbprintSha1 = base64_encode(sha1(base64_decode($xmlSecurityKey->getX509Certificate(true)), true));
174
            $dataNode = new \DOMText($thumbprintSha1);
175
            $keyIdentifier->appendChild($dataNode);
176
        }
177
178
        return $keyInfo;
179
    }
180
181
    /**
182
     * Create a list of \DOMNodes that should be encrypted.
183
     *
184
     * @param \DOMDocument $dom DOMDocument to query
185
     *
186
     * @return \DOMNodeList
187
     */
188
    private function createNodeListForEncryption(\DOMDocument $dom)
189
    {
190
        $xpath = new \DOMXPath($dom);
191
        $xpath->registerNamespace('SOAP-ENV', $dom->documentElement->namespaceURI);
192
        $xpath->registerNamespace('ds', XmlSecurityDSig::NS_XMLDSIG);
193
        if ($this->encryptSignature === true) {
194
            $query = '//ds:Signature | //SOAP-ENV:Body';
195
        } else {
196
            $query = '//SOAP-ENV:Body';
197
        }
198
199
        return $xpath->query($query);
200
    }
201
202
    /**
203
     * Create a list of \DOMNodes that should be signed.
204
     *
205
     * @param \DOMDocument $dom DOMDocument to query
206
     * @param \DOMElement $security Security element
207
     *
208
     * @return array(\DOMNode)
0 ignored issues
show
Documentation introduced by
The doc-type array(\DOMNode) could not be parsed: Expected "|" or "end of type", but got "(" at position 5. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
209
     */
210
    private function createNodeListForSigning(\DOMDocument $dom, \DOMElement $security)
211
    {
212
        $nodes = array();
213
        $body = $dom->getElementsByTagNameNS($dom->documentElement->namespaceURI, 'Body')->item(0);
214
        if (null !== $body) {
215
            $nodes[] = $body;
216
        }
217
        foreach ($security->childNodes as $node) {
218
            if (XML_ELEMENT_NODE === $node->nodeType) {
219
                $nodes[] = $node;
220
            }
221
        }
222
        if ($this->signAllHeaders) {
223
            foreach ($security->parentNode->childNodes as $node) {
224
                if (XML_ELEMENT_NODE === $node->nodeType &&
225
                    self::NS_WSS !== $node->namespaceURI
226
                ) {
227
                    $nodes[] = $node;
228
                }
229
            }
230
        }
231
        return $nodes;
232
    }
233
234
235
    /**
236
     * Modify the given request XML.
237
     *
238
     * @param \DOMDocument $dom
239
     * @param Security $securityData
240
     *
241
     * @return \DOMElement
242
     */
243
    public function filterDom(\DOMDocument $dom, Security $securityData)
244
    {
245
        $security = $dom->createElementNS(self::NS_WSS, 'Security');
246
247
        $root = $dom->documentElement;
248
        $root->setAttributeNS(
249
            'http://www.w3.org/2000/xmlns/', // xmlns namespace URI
250
            'xmlns:wssu',
251
            self::NS_WSU
252
        );
253
        $root->setAttributeNS(
254
            'http://www.w3.org/2000/xmlns/', // xmlns namespace URI
255
            'xmlns:wsss',
256
            self::NS_WSS
257
        );
258
        $root->setAttributeNS(
259
            'http://www.w3.org/2000/xmlns/', // xmlns namespace URI
260
            'xmlns:dsig',
261
            XmlSecurityDSig::NS_XMLDSIG
262
        );
263
        $root->setAttributeNS(
264
            'http://www.w3.org/2000/xmlns/', // xmlns namespace URI
265
            'xmlns:xenc',
266
            XmlSecurityEnc::NS_XMLENC
267
        );
268
269
        // init timestamp
270
        $dt = $this->initialTimestamp ?: new \DateTime('now', new \DateTimeZone('UTC'));
271
272
        if (true === $this->addTimestamp || null !== $this->expires) {
273
            $this->handleTimestamp($security, $dt);
274
        }
275
276
        if (null !== $securityData->getUsername()) {
277
            $this->handleUsername($security, $dt, $securityData);
278
        }
279
280
        if (null !== $this->userSecurityKey && $this->userSecurityKey->hasKeys()) {
281
            $signature = $this->handleSignature($security);
282
283
            // encrypt soap document
284
            if (null !== $this->serviceSecurityKey && $this->serviceSecurityKey->hasKeys()) {
285
                $this->handleEncryption($security, $signature);
286
            }
287
        }
288
        return $security;
289
    }
290
291
    /**
292
     * Generate a pseudo-random version 4 UUID.
293
     *
294
     * @see http://de.php.net/manual/en/function.uniqid.php#94959
295
     *
296
     * @return string
297
     */
298
    private static function generateUUID()
299
    {
300
        return sprintf(
301
            '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
302
            // 32 bits for "time_low"
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
303
            mt_rand(0, 0xffff), mt_rand(0, 0xffff),
304
            // 16 bits for "time_mid"
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
305
            mt_rand(0, 0xffff),
306
            // 16 bits for "time_hi_and_version",
0 ignored issues
show
Unused Code Comprehensibility introduced by
45% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
307
            // four most significant bits holds version number 4
308
            mt_rand(0, 0x0fff) | 0x4000,
309
            // 16 bits, 8 bits for "clk_seq_hi_res",
0 ignored issues
show
Unused Code Comprehensibility introduced by
43% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
310
            // 8 bits for "clk_seq_low",
0 ignored issues
show
Unused Code Comprehensibility introduced by
45% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
311
            // two most significant bits holds zero and one for variant DCE1.1
312
            mt_rand(0, 0x3fff) | 0x8000,
313
            // 48 bits for "node"
0 ignored issues
show
Unused Code Comprehensibility introduced by
38% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
314
            mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
315
        );
316
    }
317
318
    /**
319
     * @param \DOMElement $security
320
     * @param \DateTime $dt
321
     */
322
    private function handleTimestamp(\DOMElement $security, \DateTime $dt)
323
    {
324
        $dom = $security->ownerDocument;
325
        $timestamp = $dom->createElementNS(self::NS_WSU, 'Timestamp');
326
        $created = $dom->createElementNS(self::NS_WSU, 'Created', $dt->format(self::DATETIME_FORMAT));
327
        $timestamp->appendChild($created);
328
        if (null !== $this->expires) {
329
            $dt = clone $dt;
330
            $dt->modify('+' . $this->expires . ' seconds');
331
            $expiresTimestamp = $dt->format(self::DATETIME_FORMAT);
332
            $expires = $dom->createElementNS(self::NS_WSU, 'Expires', $expiresTimestamp);
333
            $timestamp->appendChild($expires);
334
        }
335
        $security->appendChild($timestamp);
336
    }
337
338
    /**
339
     * @param \DOMElement $security
340
     * @param $dt
341
     * @param Security $securityData
342
     */
343
    private function handleUsername(\DOMElement $security, $dt, Security $securityData)
344
    {
345
        $dom = $security->ownerDocument;
346
        $usernameToken = $dom->createElementNS(self::NS_WSS, 'UsernameToken');
347
        $security->appendChild($usernameToken);
348
349
        $username = $dom->createElementNS(self::NS_WSS, 'Username', $securityData->getUsername());
350
        $usernameToken->appendChild($username);
351
352
        if (null !== $securityData->getPassword()
353
            && (null === $this->userSecurityKey
354
                || (null !== $this->userSecurityKey && !$this->userSecurityKey->hasPrivateKey()))
355
        ) {
356
357
            if ($securityData->isPasswordDigest()) {
358
                $nonce = mt_rand();
359
                $password = base64_encode(sha1($nonce . $dt->format(self::DATETIME_FORMAT) . $securityData->getPassword(), true));
360
                $passwordType = self::NAME_WSS_UTP . '#PasswordDigest';
361
            } else {
362
                $password = $securityData->getPassword();
363
                $passwordType = self::NAME_WSS_UTP . '#PasswordText';
364
            }
365
366
            $password = $dom->createElementNS(self::NS_WSS, 'Password', $password);
367
            $password->setAttribute('Type', $passwordType);
368
            $usernameToken->appendChild($password);
369
            if ($securityData->isPasswordDigest()) {
370
                $nonce = $dom->createElementNS(self::NS_WSS, 'Nonce', base64_encode($nonce));
0 ignored issues
show
Bug introduced by
The variable $nonce does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
371
                $usernameToken->appendChild($nonce);
372
373
                $created = $dom->createElementNS(self::NS_WSU, 'Created', $dt->format(self::DATETIME_FORMAT));
374
                $usernameToken->appendChild($created);
375
            }
376
        }
377
    }
378
379
    /**
380
     * @param \DOMElement $security
381
     * @return \DOMElement
382
     */
383
    private function handleSignature(\DOMElement $security)
384
    {
385
        $dom = $security->ownerDocument;
386
        $guid = 'CertId-' . self::generateUUID();
387
        // add token references
388
        $keyInfo = null;
389
        if (null !== $this->tokenReferenceSignature) {
390
            $keyInfo = $this->createKeyInfo($dom, $this->tokenReferenceSignature, $guid, $this->userSecurityKey->getPublicKey());
0 ignored issues
show
Documentation introduced by
$this->userSecurityKey->getPublicKey() is of type object<ass\XmlSecurity\Key>, but the function expects a null|object<GoetasWebser...ecurity\XmlSecurityKey>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
391
        }
392
        $nodes = $this->createNodeListForSigning($dom, $security);
393
        $signature = XmlSecurityDSig::createSignature($this->userSecurityKey->getPrivateKey(), XmlSecurityDSig::EXC_C14N, $security, null, $keyInfo);
394
395
        if ((!$prefix = $security->lookupPrefix(self::NS_WSU)) && (!$prefix = $security->ownerDocument->lookupPrefix(self::NS_WSU))) {
396
            $prefix = 'ns-'.  substr(sha1(self::NS_WSU), 0, 8);
397
        }
398
399
        $options = array(
400
            'id_ns_prefix' => $prefix ?: 'wsu',
401
            'id_prefix_ns' => self::NS_WSU,
402
        );
403
        foreach ($nodes as $node) {
404
            XmlSecurityDSig::addNodeToSignature($signature, $node, XmlSecurityDSig::SHA1, XmlSecurityDSig::EXC_C14N, $options);
405
        }
406
        XmlSecurityDSig::signDocument($signature, $this->userSecurityKey->getPrivateKey(), XmlSecurityDSig::EXC_C14N);
407
408
        $publicCertificate = $this->userSecurityKey->getPublicKey()->getX509Certificate(true);
0 ignored issues
show
Bug introduced by
It seems like you code against a specific sub-type and not the parent class ass\XmlSecurity\Key as the method getX509Certificate() does only exist in the following sub-classes of ass\XmlSecurity\Key: ass\XmlSecurity\Key\PrivatePublic, ass\XmlSecurity\Key\Rsa15, ass\XmlSecurity\Key\RsaOaepMgf1p, ass\XmlSecurity\Key\RsaSha1, ass\XmlSecurity\Key\RsaSha256, ass\XmlSecurity\Key\RsaSha384, ass\XmlSecurity\Key\RsaSha512. Maybe you want to instanceof check for one of these explicitly?

Let’s take a look at an example:

abstract class User
{
    /** @return string */
    abstract public function getPassword();
}

class MyUser extends User
{
    public function getPassword()
    {
        // return something
    }

    public function getDisplayName()
    {
        // return some name.
    }
}

class AuthSystem
{
    public function authenticate(User $user)
    {
        $this->logger->info(sprintf('Authenticating %s.', $user->getDisplayName()));
        // do something.
    }
}

In the above example, the authenticate() method works fine as long as you just pass instances of MyUser. However, if you now also want to pass a different sub-classes of User which does not have a getDisplayName() method, the code will break.

Available Fixes

  1. Change the type-hint for the parameter:

    class AuthSystem
    {
        public function authenticate(MyUser $user) { /* ... */ }
    }
    
  2. Add an additional type-check:

    class AuthSystem
    {
        public function authenticate(User $user)
        {
            if ($user instanceof MyUser) {
                $this->logger->info(/** ... */);
            }
    
            // or alternatively
            if ( ! $user instanceof MyUser) {
                throw new \LogicException(
                    '$user must be an instance of MyUser, '
                   .'other instances are not supported.'
                );
            }
    
        }
    }
    
Note: PHP Analyzer uses reverse abstract interpretation to narrow down the types inside the if block in such a case.
  1. Add the method to the parent class:

    abstract class User
    {
        /** @return string */
        abstract public function getPassword();
    
        /** @return string */
        abstract public function getDisplayName();
    }
    
Loading history...
409
        $binarySecurityToken = $dom->createElementNS(self::NS_WSS, 'BinarySecurityToken', $publicCertificate);
410
        $binarySecurityToken->setAttribute('EncodingType', self::NAME_WSS_SMS . '#Base64Binary');
411
        $binarySecurityToken->setAttribute('ValueType', self::NAME_WSS_X509 . '#X509v3');
412
413
        $security->insertBefore($binarySecurityToken, $signature);
414
415
        $binarySecurityToken->setAttributeNs(self::NS_WSU, $prefix.':Id', $guid);
416
417
418
        return $signature;
419
    }
420
421
    /**
422
     * @param \DOMElement $security
423
     * @param \DOMElement $signature
424
     */
425
    private function handleEncryption(\DOMElement $security, \DOMElement $signature)
426
    {
427
        $dom = $security->ownerDocument;
428
        $guid = 'EncKey-' . self::generateUUID();
429
        // add token references
430
        $keyInfo = null;
431
        if (null !== $this->tokenReferenceEncryption) {
432
            $keyInfo = $this->createKeyInfo($dom, $this->tokenReferenceEncryption, $guid, $this->serviceSecurityKey->getPublicKey());
0 ignored issues
show
Documentation introduced by
$this->serviceSecurityKey->getPublicKey() is of type object<ass\XmlSecurity\Key>, but the function expects a null|object<GoetasWebser...ecurity\XmlSecurityKey>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
433
        }
434
        $encryptedKey = XmlSecurityEnc::createEncryptedKey($guid, $this->serviceSecurityKey->getPrivateKey(), $this->serviceSecurityKey->getPublicKey(), $security, $signature, $keyInfo);
435
        $referenceList = XmlSecurityEnc::createReferenceList($encryptedKey);
436
        // token reference to encrypted key
437
        $keyInfo = $this->createKeyInfo($dom, self::TOKEN_REFERENCE_SECURITY_TOKEN, $guid);
438
        $nodes = $this->createNodeListForEncryption($dom);
439
        foreach ($nodes as $node) {
440
            $type = XmlSecurityEnc::ELEMENT;
441
            if ($node->localName == 'Body') {
442
                $type = XmlSecurityEnc::CONTENT;
443
            }
444
            XmlSecurityEnc::encryptNode($node, $type, $this->serviceSecurityKey->getPrivateKey(), $referenceList, $keyInfo);
445
        }
446
    }
447
}
448