DeviceXML   F
last analyzed

Complexity

Total Complexity 90

Size/Duplication

Total Lines 648
Duplicated Lines 0 %

Importance

Changes 6
Bugs 1 Features 1
Metric Value
wmc 90
eloc 328
c 6
b 1
f 1
dl 0
loc 648
rs 2

22 Methods

Rating   Name   Duplication   Size   Complexity  
A setORtou() 0 5 2
A eapIdp() 0 17 2
A getProviderTou() 0 21 5
A getServerSideCredentials() 0 28 5
A getEapMethod() 0 16 3
A __construct() 0 3 1
A getAuthenticationMethodParams() 0 14 4
F writeInstaller() 0 98 20
B getDisplayName() 0 30 8
A getProviderInfo() 0 10 1
A getProviderLocation() 0 16 3
A getProviderLogo() 0 12 2
A getClientSideCredentials() 0 22 4
A getClientCertificate() 0 6 1
A setClientSideRealm() 0 13 4
A writeDeviceInfo() 0 7 1
A getCredentialApplicability() 0 22 6
A getSimpleMLAttribute() 0 19 5
A getAuthMethodsList() 0 17 5
A getHelpdesk() 0 7 1
A innerAuth() 0 25 5
A getAuthMethod() 0 19 2

How to fix   Complexity   

Complex Class

Complex classes like DeviceXML often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use DeviceXML, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
/*
4
 * *****************************************************************************
5
 * Contributions to this work were made on behalf of the GÉANT project, a 
6
 * project that has received funding from the European Union’s Framework 
7
 * Programme 7 under Grant Agreements No. 238875 (GN3) and No. 605243 (GN3plus),
8
 * Horizon 2020 research and innovation programme under Grant Agreements No. 
9
 * 691567 (GN4-1) and No. 731122 (GN4-2).
10
 * On behalf of the aforementioned projects, GEANT Association is the sole owner
11
 * of the copyright in all material which was developed by a member of the GÉANT
12
 * project. GÉANT Vereniging (Association) is registered with the Chamber of 
13
 * Commerce in Amsterdam with registration number 40535155 and operates in the 
14
 * UK as a branch of GÉANT Vereniging.
15
 * 
16
 * Registered office: Hoekenrode 3, 1102BR Amsterdam, The Netherlands. 
17
 * UK branch address: City House, 126-130 Hills Road, Cambridge CB2 1PQ, UK
18
 *
19
 * License: see the web/copyright.inc.php file in the file structure or
20
 *          <base_url>/copyright.php after deploying the software
21
 */
22
23
/**
24
 * This file defines an abstract class used for generic XML
25
 * devices
26
 * actual modules only define available EAP types.
27
 *
28
 * @author Maja Gorecka-Wolniewicz <[email protected]>
29
 * @author Tomasz Wolniewicz <[email protected]>
30
 *
31
 * @package ModuleWriting
32
 */
33
34
namespace devices\eap_config;
35
36
use Exception;
37
38
/**
39
 * This class implements full functionality of the generic XML device
40
 * the only function of the extensions of this class is to specify
41
 * supported EAP methods.
42
 * Instead of specifying supported EAPS an extension can set $all_eaps to true
43
 * this will cause the installer to configure all EAP methods supported by 
44
 * the current profile and declared by the given device.
45
 */
46
abstract class DeviceXML extends \core\DeviceConfig
47
{
48
    
49
    /**
50
     *  @var array $AuthMethodElements is used to limit
51
     *  XML elements present within ServerSideCredentials and
52
     *  ClientSideCredentials to ones which are relevant
53
     *  for a given EAP method.
54
     *  @var array of XLM element names which are allowed
55
     *  EAP method names are defined in core/EAP.php
56
     */
57
    private $authMethodElements = [
58
        'server' => [
59
            \core\common\EAP::TLS => ['CA', 'ServerID'],
60
            \core\common\EAP::FAST => ['CA', 'ServerID'],
61
            \core\common\EAP::PEAP => ['CA', 'ServerID'],
62
            \core\common\EAP::TTLS => ['CA', 'ServerID'],
63
            \core\common\EAP::PWD => ['ServerID'],
64
        ],
65
        'client' => [
66
            \core\common\EAP::TLS => ['UserName', 'Password', 'ClientCertificate'],
67
            \core\common\EAP::NE_MSCHAP2 => ['UserName', 'Password', 'OuterIdentity', 'InnerIdentitySuffix', 'InnerIdentityHint'],
68
            \core\common\EAP::MSCHAP2 => ['UserName', 'Password', 'OuterIdentity', 'InnerIdentitySuffix', 'InnerIdentityHint'],
69
            \core\common\EAP::GTC => ['UserName', 'OneTimeToken'],
70
            \core\common\EAP::NE_PAP => ['UserName', 'Password', 'OuterIdentity', 'InnerIdentitySuffix', 'InnerIdentityHint'],
71
            \core\common\EAP::NE_SILVERBULLET => ['UserName', 'ClientCertificate', 'OuterIdentity'],
72
            \core\common\EAP::NONE => [],
73
        ]
74
    ];
75
76
    /**
77
     * construct the device
78
     */
79
    public function __construct()
80
    {
81
        parent::__construct();
82
    }
83
84
    /**
85
     * $langScope can be 'global' when all lang and all lang-specific information
86
     * is dumped or 'single' when only the selected lang (and defaults) are passed
87
     * NOTICE: 'global' is not yet supported
88
     * 
89
     * @var string
90
     */
91
    public $langScope;
92
93
    /**
94
     * whether all EAP types should be included in the file or only the 
95
     * preferred one
96
     * 
97
     * @var boolean
98
     */
99
    public $allEaps = false;
100
101
    /**
102
     * vendor-specific additional information, this is nit yest fully
103
     * implemented due to lack of use cases.
104
     * 
105
     * @var array
106
     */
107
    public $VendorSpecific;
108
    
109
    /**
110
     * A flag to preserve backwards compatibility for eduroamCAT application
111
     */
112
    public $eduroamCATcompatibility = false; 
113
    public $singleEAPProvider = false;
114
115
    private $eapId;
116
    private $namespace;
117
    private $providerInfo;
118
    private $authMethodsList;
119
    
120
    /**
121
     * create HTML code explaining the installer
122
     * 
123
     * @return string
124
     */
125
    public function writeDeviceInfo()
126
    {
127
        \core\common\Entity::intoThePotatoes();
128
        $out = "<p>";
129
        $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");
130
        \core\common\Entity::outOfThePotatoes();
131
        return $out;
132
    }
133
134
    /**
135
     * create the actual XML file
136
     * 
137
     * @return string filename of the generated installer
138
     * @throws Exception
139
     *
140
     */
141
    public function writeInstaller()
142
    {
143
        \core\common\Entity::intoThePotatoes();
144
        $rootname = 'EAPIdentityProviderList';
145
        $dom = new \DOMDocument('1.0', 'utf-8');
146
        $root = $dom->createElement($rootname);
147
        $dom->appendChild($root);
148
        $ns = $dom->createAttributeNS( 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:noNamespaceSchemaLocation' );
149
        $ns->value = "eap-metadata.xsd";
150
        $root->appendChild($ns);
151
        $this->openRoamingToU = sprintf(_("I have read and agree to OpenRoaming Terms of Use at %s."), "https://wballiance.com/openroaming/toc-2020/");
152
        foreach ($this->languageInstance->getAllTranslations("I have read and agree to OpenRoaming Terms of Use at %s", "device") as $lang => $message) {
153
            $this->openRoamingToUArray[$lang] = sprintf($message, "https://wballiance.com/openroaming/toc-2020/");
154
        }
155
        
156
        if (empty($this->attributes['internal:realm'][0])) {
157
            $this->eapId = 'undefined';
158
            $this->namespace = 'urn:undefined';
159
        } else {
160
            $this->eapId = $this->attributes['internal:realm'][0];
161
            $this->namespace = 'urn:RFC4282:realm';
162
        }
163
        
164
        $this->authMethodsList = $this->getAuthMethodsList();
165
        $this->loggerInstance->debug(5, $this->attributes['internal:networks'], "NETWORKS:", "\n");
166
        /*
167
         * This approach is forced by geteduroam compatibility. We pack all networks into a single Provider
168
         * with the exception of the openroaming one which we pack separately.
169
         */
170
        
171
        if ($this->singleEAPProvider === true) {
172
            /*
173
             * if "condition" is set to openroaming, OpenRoaming terms of use must be mentioned
174
             * unless the preagreed is set for openroaming
175
             * if "ask" is set then we generate a separate OR profile which needs to contain the OR ToU
176
             * the ToU is not needed in the eduroam-only profile
177
             */
178
            $ssids = [];
179
            $ois = [];
180
            $orNetwork = [];
181
            foreach ($this->attributes['internal:networks'] as $netName => $netDefinition) {
182
                if ($netDefinition['condition'] === 'internal:openroaming' &&
183
                        $this->attributes['internal:openroaming']) {
184
                    $this->setORtou();
185
                    if (preg_match("/^ask/",$this->attributes['media:openroaming'][0])) {
186
                        $orNetwork = $netDefinition;
187
                        continue;                        
188
                    }
189
                }
190
                foreach ($netDefinition['ssid'] as $ssid) {
191
                    $ssids[] = $ssid;
192
                }
193
                foreach ($netDefinition['oi'] as $oi) {
194
                    $ois[] = $oi;
195
                }
196
            }
197
198
            if (!empty($orNetwork)) {
199
                $this->addORtou = false;
200
            }
201
            $this->providerInfo = $this->getProviderInfo();
202
            
203
            if (!empty($ssids) || !empty($ois)) {
204
                \core\DeviceXMLmain::marshalObject($dom, $root, 'EAPIdentityProvider', $this->eapIdp($ssids, $ois));
205
            }
206
            
207
            if (!empty($orNetwork)) {
208
                // here we need to add the Tou unless preagreed is set
209
                $this->setORtou();
210
                $this->providerInfo = $this->getProviderInfo();
211
                \core\DeviceXMLmain::marshalObject($dom, $root, 'EAPIdentityProvider', $this->eapIdp($orNetwork['ssid'], $orNetwork['oi']));
212
            }
213
        } else {
214
215
            foreach ($this->attributes['internal:networks'] as $netName => $netDefinition) {
216
                if ($netDefinition['condition'] === 'internal:openroaming' &&
217
                        $this->attributes['internal:openroaming']) {
218
                    $this->setORtou();
219
                } else {
220
                    $this->addORtou = false;
221
                }
222
                $this->providerInfo = $this->getProviderInfo();
223
                $ssids = $netDefinition['ssid'];
224
                $ois = $netDefinition['oi'];
225
                if (!empty($ssids) || !empty($ois)) {
226
                    \core\DeviceXMLmain::marshalObject($dom, $root, 'EAPIdentityProvider', $this->eapIdp($ssids, $ois));
227
                }
228
            }
229
        }
230
        
231
        if ($dom->schemaValidate(ROOT.'/devices/eap_config/eap-metadata.xsd') === FALSE) {
232
            throw new Exception("Schema validation failed for eap-metadata");
233
        }
234
235
        $dom->formatOutput = true;
236
        file_put_contents($this->installerBasename.'.eap-config', $dom->saveXML($dom));
237
        \core\common\Entity::outOfThePotatoes();
238
        return($this->installerBasename.'.eap-config');
239
    }
240
    
241
    private function setORtou() {
242
        if (preg_match("/preagreed/",$this->attributes['media:openroaming'][0])) {
243
            $this->addORtou = false;
244
        } else {
245
            $this->addORtou = true;
246
        }
247
    }
248
    
249
    /**
250
     * determines the inner authentication. Is it EAP, and which mechanism is used to convey actual auth data
251
     * @param array $eap the EAP type for which we want to get the inner auth
252
     * @return array
253
     */    
254
    private function eapIdp($ssids, $oids)
255
    {
256
        $eapIdp = new \core\DeviceXMLmain();
257
        $eapIdp->setAttribute('version', '1');
258
        if ($this->langScope === 'single') {
259
            $eapIdp->setAttribute('lang', $this->languageInstance->getLang());
260
        }
261
        $eapIdp->setAttribute('ID', $this->eapId);
262
        $eapIdp->setAttribute('namespace', $this->namespace);
263
        $authMethods = new \core\DeviceXMLmain();
264
        $authMethods->setChild('AuthenticationMethod', $this->authMethodsList);
265
        $eapIdp->setChild('AuthenticationMethods', $authMethods);
266
        $eapIdp->setChild('CredentialApplicability', $this->getCredentialApplicability($ssids,$oids));
267
// TODO   $eap_idp->setChild('ValidUntil',$this->getValidUntil());
268
        $eapIdp->setChild('ProviderInfo', $this->providerInfo);
269
// TODO   $eap_idp->setChild('VendorSpecific',$this->getVendorSpecific());
270
        return($eapIdp);
0 ignored issues
show
Bug Best Practice introduced by
The expression return $eapIdp returns the type core\DeviceXMLmain which is incompatible with the documented return type array.
Loading history...
271
    }
272
273
    /**
274
     * determines the inner authentication. Is it EAP, and which mechanism is used to convey actual auth data
275
     * @param array $eap the EAP type for which we want to get the inner auth
276
     * @return array
277
     */  
278
    private function innerAuth($eap)
279
    {
280
        $out = [];
281
        $out['EAP'] = 0;
282
        switch ($eap["INNER"]) {
283
            case \core\common\EAP::NE_MSCHAP2:
284
                if ($this->eduroamCATcompatibility === TRUE) {
285
                    $out['METHOD'] = \core\common\EAP::MSCHAP2;
286
                    $out['EAP'] = 1;
287
                } else {
288
                    $out['METHOD'] = $eap["INNER"];
289
                }
290
                break;
291
            case \core\common\EAP::NE_SILVERBULLET:
292
                $out['METHOD'] = \core\common\EAP::NONE;
293
                break;
294
            default:
295
                $out['METHOD'] = $eap["INNER"];
296
                break;
297
        }
298
        // override if there is an inner EAP
299
        if ($eap["INNER"] > 0) { // there is an inner EAP method
300
            $out['EAP'] = 1;
301
        }
302
        return $out;
303
    }
304
    
305
    /**
306
     * 
307
     * @param string $attrName the attribute name
308
     * @return array of values for this attribute
309
     */
310
    private function getSimpleMLAttribute($attrName)
311
    {
312
        if (empty($this->attributes[$attrName][0])) {
313
            return([]);
314
        }
315
        $attributeList = $this->attributes[$attrName];
316
        $objs = [];
317
        if ($this->langScope === 'global') {
318
            foreach ($attributeList['langs'] as $language => $value) {
319
                $language = ($language === 'C' ? 'any' : $language);
320
                $obj = new \core\DeviceXMLmain();
321
                $obj->setValue($value);
322
                $obj->setAttributes(['lang' => $language]);
323
                $objs[] = $obj;
324
            }
325
        } else {
326
            $objs[] = $attributeList[0];
327
        }
328
        return($objs);
329
    }
330
    
331
    /**
332
     * constructs the name of the institution and puts it into the XML.
333
     * consists of the best-language-match inst name, and if the inst has more 
334
     * than one profile also the best-language-match profile name
335
     * 
336
     * @return \core\DeviceXMLmain[]
337
     */
338
    private function getDisplayName()
339
    {
340
        $attr = $this->attributes;
341
        $objs = [];
342
        if ($this->langScope === 'global') {
343
            $instNameLangs = $attr['general:instname']['langs'];
344
            if ($attr['internal:profile_count'][0] > 1) {
345
                $profileNameLangs = $attr['profile:name']['langs'];
346
            }
347
            foreach ($instNameLangs as $language => $value) {
348
                $language = ($language === 'C' ? 'any' : $language);
349
                $displayname = new \core\DeviceXMLmain();
350
                if (isset($profileNameLangs)) {
351
                    $langOrC = isset($profileNameLangs[$language]) ? $profileNameLangs[$language] : $profileNameLangs['C'];
352
                    $value .= ' - '.$langOrC;
353
                }
354
                $displayname->setValue($value);
355
                $displayname->setAttributes(['lang' => $language]);
356
                $objs[] = $displayname;
357
            }
358
        } else {
359
            $displayname = new \core\DeviceXMLmain();
360
            $value = $attr['general:instname'][0];
361
            if ($attr['internal:profile_count'][0] > 1) {
362
                $value .= ' - '.$attr['profile:name'][0];
363
            }
364
            $displayname->setValue($value);
365
            $objs[] = $displayname;
366
        }
367
        return $objs;
368
    }
369
370
    /**
371
     * retrieves the provider logo and puts it into the XML structure
372
     * 
373
     * @return \core\DeviceXMLmain
374
     */
375
    private function getProviderLogo()
376
    {
377
        $attr = $this->attributes;
378
        if (isset($attr['general:logo_file'][0])) {
379
            $logoString = base64_encode($attr['general:logo_file'][0]);
380
            $logoMime = 'image/'.$attr['internal:logo_file'][0]['mime'];
381
            $providerlogo = new \core\DeviceXMLmain();
382
            $providerlogo->setAttributes(['mime' => $logoMime, 'encoding' => 'base64']);
383
            $providerlogo->setValue($logoString);
384
            return $providerlogo;
385
        }
386
        return NULL;
387
    }
388
389
    /**
390
     * retrieves provider information and puts it into the XML structure.
391
     * contains the profile description and the ToU file, if any
392
     * 
393
     * @return \core\DeviceXMLmain
394
     */
395
    private function getProviderInfo()
396
    {
397
        $providerinfo = new \core\DeviceXMLmain();
398
        $providerinfo->setChild('DisplayName', $this->getDisplayName());
399
        $providerinfo->setChild('Description', $this->getSimpleMLAttribute('profile:description'));
400
        $providerinfo->setChild('ProviderLocation', $this->getProviderLocation());
401
        $providerinfo->setChild('ProviderLogo', $this->getProviderLogo());
402
        $providerinfo->setChild('TermsOfUse', $this->getProviderTou(), null, 'cdata');
403
        $providerinfo->setChild('Helpdesk', $this->getHelpdesk());
404
        return $providerinfo; 
405
    }
406
    
407
    private function getProviderTou() {
408
        $standardTou = $this->getSimpleMLAttribute('support:info_file');
409
        if ($this->addORtou === false) {
410
            return $standardTou;
411
        }
412
        $out = [];
413
        if ($this->langScope === 'global') {
414
            foreach ($standardTou as $touObj) {
415
                $tou = $touObj->getValue();
416
                $lngAttr = $touObj->getAttributes();
417
                $lng = $lngAttr['lang'] === 'any' ? \config\Master::APPEARANCE['defaultlocale'] : $lngAttr['lang'];
418
                $tou .= "\n".$this->openRoamingToUArray[$lng];
419
                $touObj->setValue($tou);
420
                $out[] =  $touObj;
421
            } 
422
        } else {
423
            $tou = $standardTou[0];
424
            $tou .= "\n".$this->openRoamingToU;
425
            $out = [$tou];
426
        }
427
        return $out;
428
    }
429
430
    /**
431
     * retrieves the location information and puts it into the XML structure
432
     * 
433
     * @return \core\DeviceXMLmain[]
434
     */
435
    private function getProviderLocation()
436
    {
437
        $attr = $this->attributes;
438
        if (isset($attr['general:geo_coordinates'])) {
439
            $attrCoordinates = $attr['general:geo_coordinates'];
440
            $location = [];
441
            foreach ($attrCoordinates as $a) {
442
                $providerlocation = new \core\DeviceXMLmain();
443
                $b = json_decode($a, true);
444
                $providerlocation->setChild('Longitude', $b['lon']);
445
                $providerlocation->setChild('Latitude', $b['lat']);
446
                $location[] = $providerlocation;
447
            }           
448
            return $location;
449
        }
450
        return NULL;
451
    }
452
453
    /**
454
     * retrieves helpdesk contact information and puts it into the XML structure
455
     * 
456
     * @return \core\DeviceXMLmain
457
     */
458
    private function getHelpdesk()
459
    {
460
        $helpdesk = new \core\DeviceXMLmain();
461
        $helpdesk->setChild('EmailAddress', $this->getSimpleMLAttribute('support:email'));
462
        $helpdesk->setChild('WebAddress', $this->getSimpleMLAttribute('support:url'));
463
        $helpdesk->setChild('Phone', $this->getSimpleMLAttribute('support:phone'));
464
        return $helpdesk;
465
    }
466
467
    /**
468
     * determine where this credential should be applicable
469
     * 
470
     * @return \core\DeviceXMLmain
471
     */
472
    private function getCredentialApplicability($ssids, $oids)
473
    {
474
        $setWired = isset($this->attributes['media:wired'][0]) && 
475
                $this->attributes['media:wired'][0] == 'on' ? 1 : 0;        
476
        $credentialapplicability = new \core\DeviceXMLmain();
477
        $ieee80211s = [];
478
        foreach ($ssids as $ssid) {
479
            $ieee80211 = new \core\DeviceXMLmain();
480
            $ieee80211->setChild('SSID', $ssid);
481
            $ieee80211->setChild('MinRSNProto', 'CCMP');
482
            $ieee80211s[] = $ieee80211;
483
        }
484
        foreach ($oids as $oid) {
485
            $ieee80211 = new \core\DeviceXMLmain();
486
            $ieee80211->setChild('ConsortiumOID', $oid);
487
            $ieee80211s[] = $ieee80211;
488
        }
489
        $credentialapplicability->setChild('IEEE80211', $ieee80211s);
490
        if ($setWired) {
491
            $credentialapplicability->setChild('IEEE8023', '');
492
        }
493
        return $credentialapplicability;
494
    }
495
496
    /**
497
     * retrieves the parameters needed for the given EAP method and creates
498
     * appropriate nodes in the XML structure for them
499
     * 
500
     * @param array $eap the EAP type in question
501
     * @return array a recap of the findings
502
     */
503
    private function getAuthenticationMethodParams($eap)
504
    {
505
        $inner = $this->innerAuth($eap);
506
        $outerMethod = $eap["OUTER"];
507
508
        if (isset($inner["METHOD"]) && $inner["METHOD"]) {
509
            $innerauthmethod = new \core\DeviceXMLmain();
510
            $typeOfInner = ($inner["EAP"] ? 'EAPMethod' : 'NonEAPAuthMethod');
511
            $eapmethod = new \core\DeviceXMLmain();
512
            $eapmethod->setChild('Type', abs($inner['METHOD']));
513
            $innerauthmethod->setChild($typeOfInner, $eapmethod);
514
            return ['inner_method' => $innerauthmethod, 'methodID' => $outerMethod, 'inner_methodID' => $inner['METHOD']];
515
        } else {
516
            return ['inner_method' => 0, 'methodID' => $outerMethod, 'inner_methodID' => 0];
517
        }
518
    }
519
520
    /**
521
     * sets the server-side credentials for a given EAP type
522
     * 
523
     * @param \devices\XML\Type $eaptype the EAP type
0 ignored issues
show
Bug introduced by
The type devices\XML\Type was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
524
     * @return \core\DeviceXMLmain
525
     */
526
    private function getServerSideCredentials($eap)
527
    {
528
        $attr = $this->attributes;
529
        $children = $this->authMethodElements['server'][$eap];
530
        $serversidecredential = new \core\DeviceXMLmain();
531
// Certificates and server names
532
        $cAlist = [];
533
        $attrCaList = $attr['internal:CAs'][0];
534
        foreach ($attrCaList as $ca) {
535
            $caObject = new \core\DeviceXMLmain();
536
            $caObject->setValue(base64_encode($ca['der']));
537
            $caObject->setAttributes(['format' => 'X.509', 'encoding' => 'base64']);
538
            $cAlist[] = $caObject;
539
        }
540
        $serverids = [];
541
        $servers = $attr['eap:server_name'];
542
        foreach ($servers as $server) {
543
            $serverid = new \core\DeviceXMLmain();
544
            $serverid->setValue($server);
545
            $serverids[] = $serverid;
546
        }
547
        if (in_array('CA', $children)) {
548
            $serversidecredential->setChild('CA', $cAlist);
549
        }
550
        if (in_array('ServerID', $children)) {
551
            $serversidecredential->setChild('ServerID', $serverids);
552
        }
553
        return $serversidecredential;
554
    }
555
556
    /**
557
     * sets the realm information for the client-side credential
558
     * 
559
     * @param \core\DeviceXMLmain $clientsidecredential the ClientSideCredential to which the realm info is to be added
560
     * @return void
561
     */
562
    private function setClientSideRealm($clientsidecredential)
563
    {
564
        $attr = $this->attributes;
565
        $realm = \core\common\Entity::getAttributeValue($attr, 'internal:realm', 0);
566
        if ($realm === NULL) {
567
            return;
568
        }
569
        if (\core\common\Entity::getAttributeValue($attr, 'internal:verify_userinput_suffix', 0) !== 1) {
570
            return;
571
        }
572
        $clientsidecredential->setChild('InnerIdentitySuffix', $realm);
573
        if (\core\common\Entity::getAttributeValue($attr, 'internal:hint_userinput_suffix', 0) === 1) {
574
            $clientsidecredential->setChild('InnerIdentityHint', 'true');
575
        }
576
    }
577
578
    /**
579
     * sets the client certificate
580
     * 
581
     * @return \core\DeviceXMLmain
582
     */
583
    private function getClientCertificate()
584
    {
585
        $clientCertificateObject = new \core\DeviceXMLmain();
586
        $clientCertificateObject->setValue(base64_encode($this->clientCert["certdata"]));
587
        $clientCertificateObject->setAttributes(['format' => 'PKCS12', 'encoding' => 'base64']);
588
        return $clientCertificateObject;
589
    }
590
591
    /**
592
     * sets the client-side credentials for the given EAP type
593
     * 
594
     * @param array $eapParams the EAP parameters
595
     * @return \core\DeviceXMLmain
596
     */
597
    private function getClientSideCredentials($eap)
598
    {
599
        $children = $this->authMethodElements['client'][$eap];
600
        $clientsidecredential = new \core\DeviceXMLmain();
601
        $outerId = $this->determineOuterIdString();
602
        $this->loggerInstance->debug(5, $eap, "XMLOI:", "\n");
603
        if (in_array('OuterIdentity', $children)) {
604
            if ($outerId !== NULL) {
605
                $clientsidecredential->setChild('OuterIdentity', $outerId);
606
            }
607
        }
608
        $this->setClientSideRealm($clientsidecredential);
609
//        $clientsidecredential->setChild('EAPType', $eapParams['inner_methodID'] ? $eapParams['inner_methodID'] : $eapParams['methodID']);
610
611
        // Client Certificate
612
        if ($this->selectedEap == \core\common\EAP::EAPTYPE_SILVERBULLET) {
613
            $attr = $this->attributes;
614
            $outerId = \core\common\Entity::getAttributeValue($attr, 'internal:username', 0);
615
            $clientsidecredential->setChild('OuterIdentity', $outerId);
616
            $clientsidecredential->setChild('ClientCertificate', $this->getClientCertificate());
617
        }
618
        return $clientsidecredential;
619
    }
620
621
    /**
622
     * sets the EAP method
623
     * 
624
     * @param \devices\XML\Type $eaptype the EAP type XMLObject
625
     * @return \core\DeviceXMLmain
626
     */
627
    private function getEapMethod($eaptype)
628
    {
629
        $eapmethod = new \core\DeviceXMLmain();
630
        $eapmethod->setChild('Type', $eaptype);
631
        if (isset($this->VendorSpecific)) {
632
            $vendorspecifics = [];
633
            foreach ($this->VendorSpecific as $vs) {
634
                $vendorspecific = new \core\DeviceXMLmain();
635
                $vs['value']->addAttribute('xsi:noNamespaceSchemaLocation', "xxx.xsd");
636
                $vendorspecific->setValue($vs['value']);
637
                $vendorspecific->setAttributes(['vendor' => $vs['vendor']]);
638
                $vendorspecifics[] = $vendorspecific;
639
            }
640
            $eapmethod->setChild('VendorSpecific', $vendorspecifics);
641
        }
642
        return($eapmethod);
643
    }
644
645
    /**
646
     * determines the authentication method to use
647
     * 
648
     * @param array $eap the EAP methods, in array representation
649
     * @return \core\DeviceXMLmain
650
     */
651
    private function getAuthMethod($eap)
652
    {
653
        $authmethod = new \core\DeviceXMLmain();
654
        $eapParams = $this->getAuthenticationMethodParams($eap);
655
        $eaptype = new \core\DeviceXMLmain();
656
        $eaptype->setValue($eapParams['methodID']);
657
// Type
658
        $authmethod->setChild('EAPMethod', $this->getEapMethod($eaptype));
659
660
// ServerSideCredentials
661
        $authmethod->setChild('ServerSideCredential', $this->getServerSideCredentials($eap['OUTER']));
662
663
// ClientSideCredentials
664
        $authmethod->setChild('ClientSideCredential', $this->getClientSideCredentials($eap['INNER']));
665
666
        if ($eapParams['inner_method']) {
667
            $authmethod->setChild('InnerAuthenticationMethod', $eapParams['inner_method']);
668
        }
669
        return $authmethod;
670
    }
671
    
672
    private function getAuthMethodsList() {
673
        $methodList = [];
674
        if ($this->allEaps) {
675
            $eapmethods = [];
676
            foreach ($this->attributes['all_eaps'] as $eap) {
677
                $eapRep = $eap->getArrayRep();
678
                if (in_array($eapRep, $this->supportedEapMethods)) {
679
                    $eapmethods[] = $eapRep;
680
                }
681
            }
682
        } else {
683
            $eapmethods = [$this->selectedEap];
684
        }
685
        foreach ($eapmethods as $eap) {
686
            $methodList[] = $this->getAuthMethod($eap);
687
        }
688
        return $methodList;
689
    }
690
    
691
    private $openRoamingToUArray;
692
    private $openRoamingToU;
693
    private $addORtou = false;
694
695
}
696