Passed
Push — master ( cf2311...a67231 )
by Stefan
06:24
created

Device_XML::getSimpleMLAttribute()   B

Complexity

Conditions 6
Paths 4

Size

Total Lines 25
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 25
rs 8.439
cc 6
eloc 20
nc 4
nop 1
1
<?php
2
/* 
3
 *******************************************************************************
4
 * Copyright 2011-2017 DANTE Ltd. and GÉANT on behalf of the GN3, GN3+, GN4-1 
5
 * and GN4-2 consortia
6
 *
7
 * License: see the web/copyright.php file in the file structure
8
 *******************************************************************************
9
 */
10
11
/**
12
 * This file defines an abstract class used for generic XML
13
 * devices
14
 * actual modules only define available EAP types.
15
 *
16
 * @author Maja Gorecka-Wolniewicz <[email protected]>
17
 * @author Tomasz Wolniewicz <[email protected]>
18
 *
19
 * @package ModuleWriting
20
 */
21
namespace devices\xml;
22
require_once(dirname(__FILE__) . '/XML.inc.php');
23
24
/**
25
 * This class implements full functionality of the generic XML device
26
 * the only fuction of the extenstions of this class is to specify
27
 * supported EAP methods.
28
 * Instead of specifying supported EAPS an extension can set $all_eaps to true
29
 * this will cause the installer to configure all EAP methods supported by 
30
 * the current profile and declared by the given device.
31
 */
32
abstract class Device_XML extends \core\DeviceConfig {
33
34
    public function __construct() {
35
        parent::__construct();
36
    }
37
38
    /**
39
     * $lang_scope can be 'global' wheb all lang and all lang-specific information
40
     * is dumped or 'single' when only the selected lang (and defaults) are passed
41
     * NOTICE: 'global' is not yet supported
42
     */
43
    public $langScope;
44
    public $allEaps = FALSE;
45
    public $VendorSpecific;
46
47
    public function writeDeviceInfo() {
48
        $out = "<p>";
49
        $out .= sprintf(_("This is a generic configuration file in the IETF <a href='%s'>EAP Metadata -00</a> XML format."), "https://tools.ietf.org/html/draft-winter-opsawg-eap-metadata-00");
50
        return $out;
51
    }
52
53
    public function writeInstaller() {
54
        $attr = $this->attributes;
55
        $NAMESPACE = 'urn:RFC4282:realm';
56
//EAPIdentityProvider  begin
57
        $eapIdp = new EAPIdentityProvider();
58
//    $eap_idp->setProperty('ValidUntil',$this->getValidUntil());
59
// ProviderInfo->
60
        $eapIdp->setProperty('ProviderInfo', $this->getProviderInfo());
61
// TODO    $eap_idp->setProperty('VendorSpecific',$this->getVendorSpecific());
62
//AuthenticationMethods
63
// TODO
64
//ID attribute
65
//lang attribute
66
        $methodList = [];
67
        if ($this->allEaps) {
68
            $eapmethods = [];
69
            foreach ($attr['all_eaps'] as $eap) {
70
                $eapRep = $eap->getArrayRep();
71
                if (in_array($eapRep, $this->supportedEapMethods)) {
72
                    $eapmethods[] = $eapRep;
73
                }
74
            }
75
        } else {
76
            $eapmethods = [$this->selectedEap];
77
        }
78
        foreach ($eapmethods as $eap) {
79
            $methodList[] = $this->getAuthMethod($eap);
80
        }
81
        $authMethods = new AuthenticationMethods();
82
        $authMethods->setProperty('AuthenticationMethods', $methodList);
83
        $eapIdp->setProperty('AuthenticationMethods', $authMethods);
84
        if (empty($attr['internal:realm'][0])) {
85
            $eapIdp->setAttribute('ID', 'undefined');
86
            $eapIdp->setAttribute('namespace', 'urn:undefined');
87
        } else {
88
            $eapIdp->setAttribute('ID', $attr['internal:realm'][0]);
89
            $eapIdp->setAttribute('namespace', $NAMESPACE);
90
        }
91
        if ($this->langScope === 'single') {
92
            $eapIdp->setAttribute('lang', $this->languageInstance->getLang());
93
        }
94
        $eapIdp->setAttribute('version', '1');
95
96
97
// EAPIdentityProvider end
98
// Generate XML
99
100
        $rootname = 'EAPIdentityProviderList';
101
        $root = new \SimpleXMLElement("<?xml version=\"1.0\" encoding=\"utf-8\" ?><{$rootname} xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:noNamespaceSchemaLocation=\"eap-metadata.xsd\"></{$rootname}>");
102
103
        marshalObject($root, $eapIdp);
104
        $dom = dom_import_simplexml($root)->ownerDocument;
105
        //TODO schema validation makes sense so probably should be used
106
        $res = $dom->schemaValidate(ROOT . '/devices/xml/eap-metadata.xsd');
0 ignored issues
show
Unused Code introduced by
The assignment to $res is dead and can be removed.
Loading history...
107
        file_put_contents($this->installerBasename . '.eap-config', $dom->saveXML());
108
        return($this->installerBasename . '.eap-config');
109
    }
110
111
    private $AttributeNames = [
112
        'support:email' => 'EmailAddress',
113
        'support:url' => 'WebAddress',
114
        'support:phone' => 'Phone',
115
        'profile:description' => 'Description',
116
        'support:info_file' => 'TermsOfUse',
117
        'general:logo_file' => 'ProviderLogo',
118
    ];
119
120
    /**
121
     * 
122
     * @param string $attrName
123
     * @return array of values for this attribute
124
     */
125
    private function getSimpleMLAttribute($attrName) {
126
        if (empty($this->attributes[$attrName][0])) {
127
            return([]);
128
        }
129
        $attributeList = $this->attributes[$attrName];
130
        if (!isset($this->AttributeNames[$attrName])) {
131
            $this->loggerInstance->debug(4, "Missing class definition for $attrName\n");
132
            return([]);
133
        }
134
        $className = "\devices\xml\\" . $this->AttributeNames[$attrName];
135
        $objs = [];
136
        if ($this->langScope === 'global') {
137
            foreach ($attributeList['langs'] as $language => $value) {
138
                $language = ($language === 'C' ? 'any' : $language);
139
                $obj = new $className();
140
                $obj->setValue($value);
141
                $obj->setAttributes(['lang' => $language]);
142
                $objs[] = $obj;
143
            }
144
        } else {
145
            $obj = new $className();
146
            $obj->setValue($attributeList[0]);
147
            $objs[] = $obj;
148
        }
149
        return($objs);
150
    }
151
152
    private function getDisplayName() {
153
        $attr = $this->attributes;
154
        $objs = [];
155
        if ($this->langScope === 'global') {
156
            $instNameLangs = $attr['general:instname']['langs'];
157
            if ($attr['internal:profile_count'][0] > 1) {
158
                $profileNameLangs = $attr['profile:name']['langs'];
159
            }
160
            foreach ($instNameLangs as $language => $value) {
161
                $language = ($language === 'C' ? 'any' : $language);
162
                $displayname = new DisplayName();
163
                if (isset($profileNameLangs)) {
164
                    $langOrC = isset($profileNameLangs[$language]) ? $profileNameLangs[$language] : $profileNameLangs['C'];
165
                    $value .= ' - ' . $langOrC;
166
                }
167
                $displayname->setValue($value);
168
                $displayname->setAttributes(['lang' => $language]);
169
                $objs[] = $displayname;
170
            }
171
        } else {
172
            $displayname = new DisplayName();
173
            $value = $attr['general:instname'][0];
174
            if ($attr['internal:profile_count'][0] > 1) {
175
                $value .= ' - ' . $attr['profile:name'][0];
176
            }
177
            $displayname->setValue($value);
178
            $objs[] = $displayname;
179
        }
180
        return $objs;
181
    }
182
183
    private function getProviderLogo() {
184
        $attr = $this->attributes;
185
        if (isset($attr['general:logo_file'][0])) {
186
            $logoString = base64_encode($attr['general:logo_file'][0]);
187
            $logoMime = 'image/' . $attr['internal:logo_file'][0]['mime'];
188
            $providerlogo = new ProviderLogo();
189
            $providerlogo->setAttributes(['mime' => $logoMime, 'encoding' => 'base64']);
190
            $providerlogo->setValue($logoString);
191
            return $providerlogo;
192
        }
193
    }
194
195
    private function getProviderInfo() {
196
        $providerinfo = new ProviderInfo();
197
        $providerinfo->setProperty('DisplayName', $this->getDisplayName());
198
        $providerinfo->setProperty('Description', $this->getSimpleMLAttribute('profile:description'));
199
        $providerinfo->setProperty('ProviderLocation', $this->getProvideLocation());
200
        $providerinfo->setProperty('ProviderLogo', $this->getProviderLogo());
201
        $providerinfo->setProperty('TermsOfUse', $this->getSimpleMLAttribute('support:info_file'));
202
        $providerinfo->setProperty('Helpdesk', $this->getHelpdesk());
203
        return $providerinfo;
204
    }
205
206
    private function getProvideLocation() {
207
        $attr = $this->attributes;
208
        if (isset($attr['general:geo_coordinates'])) {
209
            $attrCoordinates = $attr['general:geo_coordinates'];
210
            if (count($attrCoordinates) > 1) {
211
                $location = [];
212
                foreach ($attrCoordinates as $a) {
213
                    $providerlocation = new ProviderLocation();
214
                    $b = json_decode($a, true);
215
                    $providerlocation->setProperty('Longitude', $b['lon']);
216
                    $providerlocation->setProperty('Latitude', $b['lat']);
217
                    $location[] = $providerlocation;
218
                }
219
            } else {
220
                $providerlocation = new ProviderLocation();
221
                $b = json_decode($attrCoordinates[0], true);
222
                $providerlocation->setProperty('Longitude', $b['lon']);
223
                $providerlocation->setProperty('Latitude', $b['lat']);
224
                $location = $providerlocation;
225
            }
226
            return $location;
227
        }
228
    }
229
230
    private function getHelpdesk() {
231
        $helpdesk = new Helpdesk();
232
        $helpdesk->setProperty('EmailAddress', $this->getSimpleMLAttribute('support:email'));
233
        $helpdesk->setProperty('WebAddress', $this->getSimpleMLAttribute('support:url'));
234
        $helpdesk->setProperty('Phone', $this->getSimpleMLAttribute('support:phone'));
235
        return $helpdesk;
236
    }
237
238
/* This function is not currently used.
239
 * 
240
 *     private function getCompatibleUses() {
241
        $ssids = $this->attributes['internal:SSID'];
242
        $compatibleuses = new CompatibleUses();
243
        $ieee80211s = [];
244
        foreach ($ssids as $ssid => $ciph) {
245
            $ieee80211 = new IEEE80211();
246
            $ieee80211->setProperty('SSID', $ssid);
247
            $ieee80211->setProperty('MinRSNProto', $ciph == 'AES' ? 'CCMP' : 'TKIP');
248
            $ieee80211s[] = $ieee80211;
249
        }
250
        $compatibleuses->setProperty('IEEE80211', $ieee80211s);
251
        return($compatibleuses);
252
    }
253
254
*/
255
    private function getAuthenticationMethodParams($eap) {
256
        $inner = \core\common\EAP::innerAuth($eap);
257
        $outerMethod = $eap["OUTER"];
258
259
        if (isset($inner["METHOD"]) && $inner["METHOD"]) {
260
            $innerauthmethod = new InnerAuthenticationMethod();
261
            $typeOfInner = "\devices\xml\\" . ($inner["EAP"] ? 'EAPMethod' : 'NonEAPAuthMethod');
262
            $eapmethod = new $typeOfInner();
263
            $eaptype = new Type();
264
            $eaptype->setValue($inner['METHOD']);
265
            $eapmethod->setProperty('Type', $eaptype);
266
            $innerauthmethod->setProperty($typeOfInner, $eapmethod);
267
            return ['inner_method' => $innerauthmethod, 'methodID' => $outerMethod, 'inner_methodID' => $inner['METHOD']];
268
        } else {
269
            return ['inner_method' => 0, 'methodID' => $outerMethod, 'inner_methodID' => 0];
270
        }
271
    }
272
273
    private function setServerSideCredentials($eaptype) {
274
        $attr = $this->attributes;
275
        $serversidecredential = new ServerSideCredential();
276
// Certificates and server names
277
        $cAlist = [];
278
        $attrCaList = $attr['internal:CAs'][0];
279
        foreach ($attrCaList as $ca) {
280
            $caObject = new CA();
281
            $caObject->setValue(base64_encode($ca['der']));
282
            $caObject->setAttributes(['format' => 'X.509', 'encoding' => 'base64']);
283
            $cAlist[] = $caObject;
284
        }
285
        $serverids = [];
286
        $servers = $attr['eap:server_name'];
287
        foreach ($servers as $server) {
288
            $serverid = new ServerID();
289
            $serverid->setValue($server);
290
            $serverids[] = $serverid;
291
        }
292
        $serversidecredential->setProperty('EAPType', $eaptype->getValue());
293
        $serversidecredential->setProperty('CA', $cAlist);
294
        $serversidecredential->setProperty('ServerID', $serverids);
295
        return($serversidecredential);
296
    }
297
    
298
    private function setClientSideCredentials($eapParams) {
299
        $attr = $this->attributes;
300
        $clientsidecredential = new ClientSideCredential();
301
// OuterIdentity 
302
        if ($attr['internal:use_anon_outer'] [0]) {
303
            $clientsidecredential->setProperty('OuterIdentity', $attr['internal:anon_local_value'][0] . '@' . $attr['internal:realm'][0]);
304
        }
305
        $clientsidecredential->setProperty('EAPType', $eapParams['inner_methodID'] ? $eapParams['inner_methodID'] : $eapParams['methodID']);
306
        
307
        // Client Certificate
308
        if ($this->selectedEap == \core\common\EAP::EAPTYPE_SILVERBULLET) {
309
            $clientCertificateObject = new ClientCertificate();
310
            $clientCertificateObject->setValue(base64_encode($this->clientCert["certdata"]));
311
            $clientCertificateObject->setAttributes(['format' => 'PKCS12', 'encoding' => 'base64']);
312
            $clientsidecredential->setProperty('ClientCertificate', $clientCertificateObject);
313
        }
314
        return($clientsidecredential);
315
    }
316
    
317
    private function setEapMethod($eaptype) {
318
        $attr = $this->attributes;
0 ignored issues
show
Unused Code introduced by
The assignment to $attr is dead and can be removed.
Loading history...
319
        $eapmethod = new EAPMethod();
320
        $eapmethod->setProperty('Type', $eaptype);
321
        if (isset($this->VendorSpecific)) {
322
            $vendorspecifics = [];
323
            foreach ($this->VendorSpecific as $vs) {
324
                $vendorspecific = new VendorSpecific();
325
                $vs['value']->addAttribute('xsi:noNamespaceSchemaLocation', "xxx.xsd");
326
                $vendorspecific->setValue($vs['value']);
327
                $vendorspecific->setAttributes(['vendor' => $vs['vendor']]);
328
                $vendorspecifics[] = $vendorspecific;
329
            }
330
            $eapmethod->setProperty('VendorSpecific', $vendorspecifics);
331
        }
332
        return($eapmethod);
333
    }
334
    
335
    private function getAuthMethod($eap) {
336
 //       $attr = $this->attributes;
337
        $authmethod = new AuthenticationMethod();
338
        $eapParams = $this->getAuthenticationMethodParams($eap);
339
        $eaptype = new Type();
340
        $eaptype->setValue($eapParams['methodID']);
341
// Type
342
        $authmethod->setProperty('EAPMethod', $this->setEapMethod($eaptype));
343
344
// ServerSideCredentials
345
        $authmethod->setProperty('ServerSideCredential', $this->setServerSideCredentials($eaptype));
346
347
// ClientSideCredentials
348
        $authmethod->setProperty('ClientSideCredential', $this->setClientSideCredentials($eapParams));
349
        
350
        if ($eapParams['inner_method']) {
351
            $authmethod->setProperty('InnerAuthenticationMethod', $eapParams['inner_method']);
352
        }
353
        return $authmethod;
354
355
356
    }
357
    
358
359
360
}
361