1<?php
2
3/**
4 * SAML authentication plugin
5 *
6 * @author     Andreas Gohr <gohr@cosmocode.de>
7 * @author     Sam Yelman <sam.yelman@temple.edu>
8 */
9class admin_plugin_saml extends DokuWiki_Admin_Plugin
10{
11    protected $xml = '';
12
13    public function handle()
14    {
15        global $INPUT;
16        if ($INPUT->str('url')) {
17            $http = new DokuHTTPClient();
18            $xml = $http->get($INPUT->str('url'));
19            if ($xml === false) {
20                msg('Failed to download metadata. ' . hsc($http->error), -1);
21            } else {
22                $this->xml = $xml;
23            }
24        } elseif ($INPUT->has('xml')) {
25            header("X-XSS-Protection: 0");
26            $this->xml = $INPUT->str('xml');
27        }
28
29    }
30
31    public function html()
32    {
33        echo $this->locale_xhtml('intro');
34
35        $form = new \dokuwiki\Form\Form();
36        $form->addFieldsetOpen('Federation Metadata');
37        $urlinput = $form->addTextInput('url', 'Metadata Endpoint');
38        if ($this->xml) $urlinput->val('')->useInput(false);
39        $form->addTextarea('xml', 'The XML Metadata')->val($this->xml)->useInput(false);
40        $form->addButton('go', 'Submit')->attr('type', 'submit');
41        $form->addFieldsetClose();
42        echo $form->toHTML();
43
44        if ($this->xml) {
45            $data = $this->metaData($this->xml);
46            if (count($data)) {
47                echo $this->locale_xhtml('found');
48
49                echo '<dl>';
50                foreach ($data as $key => $val) {
51                    echo '<dt>' . hsc($key) . '</dt>';
52                    echo '<dd><code>' . hsc($val) . '</code></dd>';
53                }
54                echo '</dl>';
55            } else {
56                echo $this->locale_xhtml('notfound');
57            }
58        }
59    }
60
61    /**
62     * Parse the metadata and return the configuration values
63     */
64    public function metaData($xml)
65    {
66
67        $xml = @simplexml_load_string($xml);
68        if ($xml === false) {
69            msg('Failed to parse the the XML', -1);
70            return [];
71        }
72
73        $xml->registerXPathNamespace('md', 'urn:oasis:names:tc:SAML:2.0:metadata');
74        $xml->registerXPathNamespace('ds', 'http://www.w3.org/2000/09/xmldsig#');
75
76        $proto = '/md:EntityDescriptor/md:IDPSSODescriptor[@protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol"]';
77        $data['idPEntityID'] = (string)$xml['entityID'];
78        $data['endpoint'] = (string)($xml->xpath($proto . '/md:SingleSignOnService[@Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect"]'))[0]['Location'];
79        $data['certificate'] = (string)($xml->xpath($proto . '/md:KeyDescriptor[@use="signing"]/ds:KeyInfo/ds:X509Data/ds:X509Certificate'))[0];
80
81        return $data;
82    }
83
84
85}
86