Passed
Push — master ( 9af84e...7cf688 )
by Tomasz
04:22
created

Device_XML::getSimpleMLAttribute()   C

Complexity

Conditions 7
Paths 4

Size

Total Lines 28
Code Lines 21

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 7
eloc 21
nc 4
nop 1
dl 0
loc 28
rs 6.7272
c 0
b 0
f 0
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());
0 ignored issues
show
Unused Code Comprehensibility introduced by
67% 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...
59
// ProviderInfo->
60
        $eapIdp->setProperty('ProviderInfo', $this->getProviderInfo());
61
// TODO    $eap_idp->setProperty('VendorSpecific',$this->getVendorSpecific());
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...
62
//AuthenticationMethods
63
// TODO
64
//ID attribute
65
//lang attribute
66
        $methodList = [];
67
        $this->loggerInstance->debug(4,"ALLEAP\n");
68
        $this->loggerInstance->debug(4,$attr['all_eaps']);
69
        if ($this->allEaps) {
70
            $eapmethods = [];
71
            foreach ($attr['all_eaps'] as $eap) {
72
                if (in_array($eap, $this->supportedEapMethods)) {
73
                    $eapmethods[] = $eap;
74
                }
75
            }
76
        } else {
77
            $eapmethods = [$this->selectedEap];
78
        }
79
        foreach ($eapmethods as $eap) {
80
            $methodList[] = $this->getAuthMethod($eap);
81
        }
82
        $authMethods = new AuthenticationMethods();
83
        $authMethods->setProperty('AuthenticationMethods', $methodList);
84
        $eapIdp->setProperty('AuthenticationMethods', $authMethods);
85
        if (empty($attr['internal:realm'][0])) {
86
            $eapIdp->setAttribute('ID', 'undefined');
87
            $eapIdp->setAttribute('namespace', 'urn:undefined');
88
        } else {
89
            $eapIdp->setAttribute('ID', $attr['internal:realm'][0]);
90
            $eapIdp->setAttribute('namespace', $NAMESPACE);
91
        }
92
        if ($this->langScope === 'single') {
93
            $eapIdp->setAttribute('lang', $this->languageInstance->getLang());
94
        }
95
        $eapIdp->setAttribute('version', '1');
96
97
98
// EAPIdentityProvider end
99
// Generate XML
100
101
        $rootname = 'EAPIdentityProviderList';
102
        $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}>");
103
104
        marshalObject($root, $eapIdp);
105
        $dom = dom_import_simplexml($root)->ownerDocument;
106
        //TODO schema validation makes sense so probably should be used
107
        $res = $dom->schemaValidate(ROOT . '/devices/xml/eap-metadata.xsd');
0 ignored issues
show
Unused Code introduced by
$res is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
108
        file_put_contents($this->installerBasename . '.eap-config', $dom->saveXML());
109
        return($this->installerBasename . '.eap-config');
110
    }
111
112
    private $AttributeNames = [
113
        'support:email' => 'EmailAddress',
114
        'support:url' => 'WebAddress',
115
        'support:phone' => 'Phone',
116
        'profile:description' => 'Description',
117
        'support:info_file' => 'TermsOfUse',
118
        'general:logo_file' => 'ProviderLogo',
119
    ];
120
121
    /**
122
     * 
123
     * @param string $attrName
124
     * @return array of values for this attribute
125
     */
126
    private function getSimpleMLAttribute($attrName) {
127
        if ((!isset($this->attributes[$attrName][0]) || !$this->attributes[$attrName][0])) {
128
            return '';
129
        }
130
131
        $attributeList = $this->attributes[$attrName];
132
        if (!isset($this->AttributeNames[$attrName])) {
133
            $this->loggerInstance->debug(4, "Missing class definition for $attrName\n");
134
            return;
135
        }
136
        $className = "\devices\xml\\" . $this->AttributeNames[$attrName];
137
        $objs = [];
138
        if ($this->langScope === 'global') {
139
            foreach ($attributeList['langs'] as $language => $value) {
140
                $language = ( $language === 'C' ? 'any' : $language );
141
                $obj = new $className();
142
                $obj->setValue($value);
143
                $obj->setAttributes(['lang' => $language]);
144
                $objs[] = $obj;
145
            }
146
        } else {
147
            $obj = new $className();
148
            $obj->setValue($attributeList[0]);
149
            $objs[] = $obj;
150
        }
151
152
        return($objs);
153
    }
154
155
    private function getDisplayName() {
156
        $attr = $this->attributes;
157
        $objs = [];
158
        if ($this->langScope === 'global') {
159
            $instNameLangs = $attr['general:instname']['langs'];
160
            if ($attr['internal:profile_count'][0] > 1) {
161
                $profileNameLangs = $attr['profile:name']['langs'];
162
            }
163
            foreach ($instNameLangs as $language => $value) {
164
                $language = ( $language === 'C' ? 'any' : $language );
165
                $displayname = new DisplayName();
166
                if (isset($profileNameLangs)) {
167
                    $langOrC = isset($profileNameLangs[$language]) ? $profileNameLangs[$language] : $profileNameLangs['C'];
168
                    $value .= ' - ' . $langOrC;
169
                }
170
                $displayname->setValue($value);
171
                $displayname->setAttributes(['lang' => $language]);
172
                $objs[] = $displayname;
173
            }
174
        } else {
175
            $displayname = new DisplayName();
176
            $value = $attr['general:instname'][0];
177
            if ($attr['internal:profile_count'][0] > 1) {
178
                $value .= ' - ' . $attr['profile:name'][0];
179
            }
180
            $displayname->setValue($value);
181
            $objs[] = $displayname;
182
        }
183
        return $objs;
184
    }
185
186
    private function getProviderLogo() {
187
        $attr = $this->attributes;
188
        if (isset($attr['general:logo_file'][0])) {
189
            $logoString = base64_encode($attr['general:logo_file'][0]);
190
            $logoMime = 'image/' . $attr['internal:logo_file'][0]['mime'];
191
            $providerlogo = new ProviderLogo();
192
            $providerlogo->setAttributes(['mime' => $logoMime, 'encoding' => 'base64']);
193
            $providerlogo->setValue($logoString);
194
            return $providerlogo;
195
        }
196
    }
197
198
    private function getProviderInfo() {
199
        $providerinfo = new ProviderInfo();
200
        $providerinfo->setProperty('DisplayName', $this->getDisplayName());
201
        $providerinfo->setProperty('Description', $this->getSimpleMLAttribute('profile:description'));
202
        $providerinfo->setProperty('ProviderLocation', $this->getProvideLocation());
203
        $providerinfo->setProperty('ProviderLogo', $this->getProviderLogo());
204
        $providerinfo->setProperty('TermsOfUse', $this->getSimpleMLAttribute('support:info_file'));
205
        $providerinfo->setProperty('Helpdesk', $this->getHelpdesk());
206
        return $providerinfo;
207
    }
208
209
    private function getProvideLocation() {
210
        $attr = $this->attributes;
211
        if (isset($attr['general:geo_coordinates'])) {
212
            $attrCoordinates = $attr['general:geo_coordinates'];
213
            if (count($attrCoordinates) > 1) {
214
                $location = [];
215
                foreach ($attrCoordinates as $a) {
216
                    $providerlocation = new ProviderLocation();
217
                    $b = json_decode($a, true);
218
                    $providerlocation->setProperty('Longitude', $b['lon']);
219
                    $providerlocation->setProperty('Latitude', $b['lat']);
220
                    $location[] = $providerlocation;
221
                }
222
            } else {
223
                $providerlocation = new ProviderLocation();
224
                $b = json_decode($attrCoordinates[0], true);
225
                $providerlocation->setProperty('Longitude', $b['lon']);
226
                $providerlocation->setProperty('Latitude', $b['lat']);
227
                $location = $providerlocation;
228
            }
229
            return $location;
230
        }
231
    }
232
233
    private function getHelpdesk() {
234
        $helpdesk = new Helpdesk();
235
        $helpdesk->setProperty('EmailAddress', $this->getSimpleMLAttribute('support:email'));
236
        $helpdesk->setProperty('WebAddress', $this->getSimpleMLAttribute('support:url'));
237
        $helpdesk->setProperty('Phone', $this->getSimpleMLAttribute('support:phone'));
238
        return $helpdesk;
239
    }
240
241
/* This function is not currently used.
0 ignored issues
show
Unused Code Comprehensibility introduced by
53% 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...
242
 * 
243
 *     private function getCompatibleUses() {
244
        $ssids = $this->attributes['internal:SSID'];
245
        $compatibleuses = new CompatibleUses();
246
        $ieee80211s = [];
247
        foreach ($ssids as $ssid => $ciph) {
248
            $ieee80211 = new IEEE80211();
249
            $ieee80211->setProperty('SSID', $ssid);
250
            $ieee80211->setProperty('MinRSNProto', $ciph == 'AES' ? 'CCMP' : 'TKIP');
251
            $ieee80211s[] = $ieee80211;
252
        }
253
        $compatibleuses->setProperty('IEEE80211', $ieee80211s);
254
        return($compatibleuses);
255
    }
256
257
*/
258
    private function getAuthenticationMethodParams($eap) {
259
        $inner = \core\common\EAP::innerAuth($eap);
260
        $outerMethod = $eap["OUTER"];
261
262
        if (isset($inner["METHOD"]) && $inner["METHOD"]) {
263
            $innerauthmethod = new InnerAuthenticationMethod();
264
            $typeOfInner = "\devices\xml\\" . ($inner["EAP"] ? 'EAPMethod' : 'NonEAPAuthMethod');
265
            $eapmethod = new $typeOfInner();
266
            $eaptype = new Type();
267
            $eaptype->setValue($inner['METHOD']);
268
            $eapmethod->setProperty('Type', $eaptype);
269
            $innerauthmethod->setProperty($typeOfInner, $eapmethod);
270
            return ['inner_method' => $innerauthmethod, 'methodID' => $outerMethod, 'inner_methodID' => $inner['METHOD']];
271
        } else {
272
            return ['inner_method' => 0, 'methodID' => $outerMethod, 'inner_methodID' => 0];
273
        }
274
    }
275
276
    private function setServerSideCredentials($eaptype) {
277
        $attr = $this->attributes;
278
        $serversidecredential = new ServerSideCredential();
279
// Certificates and server names
280
        $cAlist = [];
281
        $attrCaList = $attr['internal:CAs'][0];
282
        foreach ($attrCaList as $ca) {
283
            $caObject = new CA();
284
            $caObject->setValue(base64_encode($ca['der']));
285
            $caObject->setAttributes(['format' => 'X.509', 'encoding' => 'base64']);
286
            $cAlist[] = $caObject;
287
        }
288
        $serverids = [];
289
        $servers = $attr['eap:server_name'];
290
        foreach ($servers as $server) {
291
            $serverid = new ServerID();
292
            $serverid->setValue($server);
293
            $serverids[] = $serverid;
294
        }
295
        $serversidecredential->setProperty('EAPType', $eaptype->getValue());
296
        $serversidecredential->setProperty('CA', $cAlist);
297
        $serversidecredential->setProperty('ServerID', $serverids);
298
        return($serversidecredential);
299
    }
300
    
301
    private function setClientSideCredentials($eapParams) {
302
        $attr = $this->attributes;
303
        $clientsidecredential = new ClientSideCredential();
304
// OuterIdentity 
305
        if ($attr['internal:use_anon_outer'] [0]) {
306
            $clientsidecredential->setProperty('OuterIdentity', $attr['internal:anon_local_value'][0] . '@' . $attr['internal:realm'][0]);
307
        }
308
        $clientsidecredential->setProperty('EAPType', $eapParams['inner_methodID'] ? $eapParams['inner_methodID'] : $eapParams['methodID']);
309
        
310
        // Client Certificate
311
        if ($this->selectedEap == \core\common\EAP::EAPTYPE_SILVERBULLET) {
312
            $clientCertificateObject = new ClientCertificate();
313
            $clientCertificateObject->setValue(base64_encode($this->clientCert["certdata"]));
314
            $clientCertificateObject->setAttributes(['format' => 'PKCS12', 'encoding' => 'base64']);
315
            $clientsidecredential->setProperty('ClientCertificate',$clientCertificateObject);
316
        }
317
        return($clientsidecredential);
318
    }
319
    
320
    private function setEapMethod($eaptype) {
321
        $attr = $this->attributes;
0 ignored issues
show
Unused Code introduced by
$attr is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
322
        $eapmethod = new EAPMethod();
323
        $eapmethod->setProperty('Type', $eaptype);
324
        if (isset($this->VendorSpecific)) {
325
            $vendorspecifics = [];
326
            foreach ($this->VendorSpecific as $vs) {
327
                $vendorspecific = new VendorSpecific();
328
                $vs['value']->addAttribute('xsi:noNamespaceSchemaLocation', "xxx.xsd");
329
                $vendorspecific->setValue($vs['value']);
330
                $vendorspecific->setAttributes(['vendor' => $vs['vendor']]);
331
                $vendorspecifics[] = $vendorspecific;
332
            }
333
            $eapmethod->setProperty('VendorSpecific', $vendorspecifics);
334
        }
335
        return($eapmethod);
336
    }
337
    
338
    private function getAuthMethod($eap) {
339
 //       $attr = $this->attributes;
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...
340
        $authmethod = new AuthenticationMethod();
341
        $eapParams = $this->getAuthenticationMethodParams($eap);
342
        $eaptype = new Type();
343
        $eaptype->setValue($eapParams['methodID']);
344
// Type
345
        $authmethod->setProperty('EAPMethod', $this->setEapMethod($eaptype));
346
347
// ServerSideCredentials
348
        $authmethod->setProperty('ServerSideCredential', $this->setServerSideCredentials($eaptype));
349
350
// ClientSideCredentials
351
        $authmethod->setProperty('ClientSideCredential', $this->setClientSideCredentials($eapParams));
352
        
353
        if ($eapParams['inner_method']) {
354
            $authmethod->setProperty('InnerAuthenticationMethod', $eapParams['inner_method']);
355
        }
356
        return $authmethod;
357
358
359
    }
360
    
361
362
363
}
364