Skip to content

Commit 46b9967

Browse files
author
Boy Baukema
committed
Merge branch 'release/4.6'
# Conflicts: # composer.json # composer.lock # vendor/openconext/engineblock-metadata/composer.lock
2 parents 5ecc283 + a5298ed commit 46b9967

File tree

11 files changed

+107
-58
lines changed

11 files changed

+107
-58
lines changed
Lines changed: 63 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,15 @@
11
<?php
22

33
use OpenConext\Component\EngineBlockMetadata\Entity\Assembler\JanusPushMetadataAssembler;
4-
use OpenConext\Component\EngineBlockMetadata\Entity\IdentityProvider;
5-
use OpenConext\Component\EngineBlockMetadata\Entity\ServiceProvider;
64
use OpenConext\Component\EngineBlockMetadata\MetadataRepository\DoctrineMetadataRepository;
7-
use OpenConext\Component\EngineBlockMetadata\Service\JanusPushMetadataSynchronizer;
85

96
class Api_Controller_Connections extends EngineBlock_Controller_Abstract
107
{
118
public function indexAction()
129
{
1310
$this->setNoRender();
1411

15-
$configuration = EngineBlock_ApplicationSingleton::getInstance()->getConfigurationValue('engineApi');
16-
17-
if (!$configuration) {
18-
throw new EngineBlock_Exception('API access disabled');
19-
}
20-
21-
if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW'])) {
22-
header('WWW-Authenticate: Basic realm="EngineBlock API"');
23-
header('HTTP/1.1 401 Unauthorized');
24-
echo json_encode('Unauthenticated');
25-
exit;
26-
}
27-
28-
if ($_SERVER['PHP_AUTH_USER'] !== $configuration->user) {
29-
header('WWW-Authenticate: Basic realm="EngineBlock API"');
30-
header('HTTP/1.1 401 Unauthorized');
31-
echo json_encode('Invalid credentials');
32-
exit;
33-
}
34-
35-
if ($_SERVER['PHP_AUTH_PW'] !== $configuration->password) {
36-
header('WWW-Authenticate: Basic realm="EngineBlock API"');
37-
header('HTTP/1.1 401 Unauthorized');
38-
echo json_encode('Invalid credentials');
39-
exit;
40-
}
41-
42-
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
43-
header('HTTP/1.1 400 Bad Request');
44-
echo json_encode('Not a POST request');
12+
if (!$this->requireApiAuth()) {
4513
return;
4614
}
4715

@@ -58,15 +26,19 @@ public function indexAction()
5826
$connections = json_decode($body);
5927

6028
if (!$connections) {
61-
header('HTTP/1.1 400 Bad Request');
62-
echo json_encode('Unable to decode body as JSON');
63-
exit;
29+
$this->_getResponse()->setStatus(400, 'Bad Request');
30+
$this->_getResponse()->setBody(
31+
json_encode('Unable to decode body as JSON')
32+
);
33+
return;
6434
}
6535

6636
if (!is_object($connections) || !isset($connections->connections) && !is_object($connections->connections)) {
67-
header('HTTP/1.1 400 Bad Request');
68-
echo json_encode('Unrecognized structure for JSON');
69-
exit;
37+
$this->_getResponse()->setStatus(400, 'Bad Request');
38+
$this->_getResponse()->setBody(
39+
json_encode('Unrecognized structure for JSON')
40+
);
41+
return;
7042
}
7143

7244
$assembler = new JanusPushMetadataAssembler();
@@ -78,6 +50,57 @@ public function indexAction()
7850
);
7951
$result = $doctrineRepository->synchronize($roles);
8052

81-
echo json_encode($result);
53+
$this->_getResponse()->setBody(json_encode($result));
54+
}
55+
56+
public function testAction()
57+
{
58+
if (!$this->requireApiAuth()) {
59+
return;
60+
}
61+
}
62+
63+
private function requireApiAuth()
64+
{
65+
$configuration = EngineBlock_ApplicationSingleton::getInstance()->getConfigurationValue('engineApi');
66+
67+
if (!$configuration) {
68+
throw new EngineBlock_Exception('API access disabled');
69+
}
70+
71+
if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW'])) {
72+
$this->setNoRender();
73+
$this->_getResponse()->setHeader(
74+
'WWW-Authenticate',
75+
'Basic realm="EngineBlock API'
76+
);
77+
$this->_getResponse()->setStatus(401, 'Unauthorized');
78+
$this->_getResponse()->setBody(json_encode('Unauthenticated'));
79+
return false;
80+
}
81+
82+
if ($_SERVER['PHP_AUTH_USER'] !== $configuration->user) {
83+
$this->setNoRender();
84+
$this->_getResponse()->setHeader(
85+
'WWW-Authenticate',
86+
'Basic realm="EngineBlock API'
87+
);
88+
$this->_getResponse()->setStatus(401, 'Unauthorized');
89+
$this->_getResponse()->setBody(json_encode('Invalid credentials'));
90+
return false;
91+
}
92+
93+
if ($_SERVER['PHP_AUTH_PW'] !== $configuration->password) {
94+
$this->setNoRender();
95+
$this->_getResponse()->setHeader(
96+
'WWW-Authenticate',
97+
'Basic realm="EngineBlock API'
98+
);
99+
$this->_getResponse()->setStatus(401, 'Unauthorized');
100+
$this->_getResponse()->setBody(json_encode('Invalid credentials'));
101+
return false;
102+
}
103+
104+
return true;
82105
}
83106
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<div style="text-align: center; margin-bottom: 1rem">
2+
<button class="submit c-button" style="padding: 1em">PUSH</button>
3+
</div>
4+
5+
<label for="connections-json" style="font-size: large; font-weight: bolder; display: block">JSON:</label>
6+
<textarea id="connections-json" rows="50" cols="120"></textarea>
7+
8+
<div style="text-align: center; margin-top: 1rem">
9+
<button class="submit c-button" style="padding: 1em">PUSH</button>
10+
</div>
11+
12+
<script>
13+
window.setTimeout(
14+
function() {
15+
$('button').on('click', function() {
16+
$.post('index', $('textarea').val());
17+
});
18+
},
19+
3000
20+
);
21+
</script>

application/modules/Api/View/Index/Index.phtml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,11 @@ $layout->footerText = $this->t('footer');
1515
<div class="main">
1616
<h1>Welcome to the EngineBlock API index page!</h1>
1717
<p>
18-
We currently only support 1 action, pushing metadata configuration.
19-
To do this POST a valid JSON document with 'connections' to /connections,
20-
using the engineApi.user and engineApi.password in HTTP Basic authentication.
18+
We currently only support 1 action, pushing metadata configuration. <br>
19+
To do this POST a valid JSON document with 'connections' to /connections, <br>
20+
using the engineApi.user and engineApi.password in HTTP Basic authentication. <br><br>
21+
22+
To test this go here: <a href="/api/connections/test">/api/connections/test</a>
2123
</p>
2224
</div>
2325
</div>

docs/release_notes/4.6.4.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# OpenConext EngineBlock v4.6.4 Release Notes #
2+
3+
Push Metadata improvements.
4+
5+
* Downgrade notice about multivalued attributes to info
6+
* [Remove `libxml_disable_entity_loader()` call #180](https://github.com/OpenConext/OpenConext-engineblock/issues/180)
7+
* [error while pushing metadata #212](https://github.com/OpenConext/OpenConext-engineblock/issues/212)
8+
* [Metadata Push: DisplayName missing #223](https://github.com/OpenConext/OpenConext-engineblock/issues/223)
9+
* Added metadata push test client on `/api/connections/test`.

library/EngineBlock/Application/Bootstrapper.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -186,8 +186,6 @@ protected function _bootstrapPhpSettings()
186186
{
187187
$settings = $this->_application->getConfiguration()->phpSettings->toArray();
188188
$this->_setIniSettings($settings);
189-
// prevent any XXE attacks when processing XML
190-
libxml_disable_entity_loader();
191189
}
192190

193191
protected function _setIniSettings($settings, $prefix = '')

library/EngineBlock/Corto/Filter/Command/AddEduPersonTargettedId.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,7 @@ public function execute()
3434
);
3535

3636
// EPTID requires us to embed the <saml:NameID> element instead of just the value, so we generate that here.
37-
$document = new DOMDocument();
38-
$document->loadXML('<base />');
37+
$document = SAML2_DOMDocumentFactory::fromString('<base />');
3938
SAML2_Utils::addNameId($document->documentElement, $nameId);
4039

4140
// Add the eduPersonTargetedId attribute.

library/EngineBlock/Corto/Mapper/Legacy/ResponseTranslator.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,7 @@ public function fromOldFormat(array $legacyResponse)
4343
$legacyResponse = EngineBlock_Corto_XmlToArray::registerNamespaces($legacyResponse);
4444
$xml = EngineBlock_Corto_XmlToArray::array2xml($legacyResponse);
4545

46-
$document = new DOMDocument();
47-
$document->loadXML($xml);
46+
$document = SAML2_DOMDocumentFactory::fromString($xml);
4847

4948
$response = new SAML2_Response($document->firstChild);
5049
$annotatedResponse = new EngineBlock_Saml2_ResponseAnnotationDecorator($response);

library/EngineBlock/Corto/Module/Bindings.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -460,8 +460,7 @@ protected function validateXml($xml)
460460
{
461461
$schemaUrl = 'http://docs.oasis-open.org/security/saml/v2.0/saml-schema-protocol-2.0.xsd';
462462
if ($this->_server->getConfig('debug') && ini_get('allow_url_fopen') && file_exists($schemaUrl)) {
463-
$dom = new DOMDocument();
464-
$dom->loadXML($xml);
463+
$dom = SAML2_DOMDocumentFactory::fromString($xml);
465464
if (!$dom->schemaValidate($schemaUrl)) {
466465
throw new Exception('Message XML doesnt validate against XSD at Oasis-open.org?!');
467466
}

library/EngineBlock/Corto/ProxyServer.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -925,7 +925,7 @@ public function sign(array $element)
925925
);
926926

927927
// Convert the XMl object to actual XML and get a reference to what we're about to sign
928-
$canonicalXmlDom = new DOMDocument();
928+
$canonicalXmlDom = SAML2_DOMDocumentFactory::create();
929929
$canonicalXmlDom->loadXML(EngineBlock_Corto_XmlToArray::array2xml($element));
930930

931931
// Note that the current element may not be the first or last, because we might include comments, so look for
@@ -948,8 +948,9 @@ public function sign(array $element)
948948

949949
// Now we start the actual signing, instead of signing the entire (possibly large) document,
950950
// we only sign the 'SignedInfo' which includes the 'Reference' hash
951-
$canonicalXml2Dom = new DOMDocument();
952-
$canonicalXml2Dom->loadXML(EngineBlock_Corto_XmlToArray::array2xml($signature['ds:SignedInfo']));
951+
$canonicalXml2Dom = SAML2_DOMDocumentFactory::fromString(
952+
EngineBlock_Corto_XmlToArray::array2xml($signature['ds:SignedInfo'])
953+
);
953954
$canonicalXml2 = $canonicalXml2Dom->firstChild->C14N(true, false);
954955

955956
$signatureValue = null;

library/EngineBlock/Saml2/MessageSerializer.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@ public function serialize(SAML2_Message $samlMessage)
2828
public function deserialize($samlMessageXml, $class)
2929
{
3030
$elementName = $this->getElementForClass($class);
31-
$document = new DOMDocument();
32-
$document->loadXML($samlMessageXml);
31+
$document = SAML2_DOMDocumentFactory::fromString($samlMessageXml);
3332
$messageDomElement = $document->getElementsByTagNameNs('urn:oasis:names:tc:SAML:2.0:protocol', $elementName)->item(0);
3433
if ($class === 'SAML2_AuthnRequest') {
3534
return SAML2_AuthnRequest::fromXML($messageDomElement);

0 commit comments

Comments
 (0)