Test Failed
Push — master ( 9dc220...59de9a )
by Tomasz
10:00
created

DeviceXML   F

Complexity

Total Complexity 97

Size/Duplication

Total Lines 714
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 1
Metric Value
wmc 97
eloc 358
c 2
b 0
f 1
dl 0
loc 714
rs 2

23 Methods

Rating   Name   Duplication   Size   Complexity  
A eapIdp() 0 17 2
A writeDeviceInfo() 0 7 1
A getSimpleMLAttribute() 0 19 5
B getDisplayName() 0 30 8
A __construct() 0 3 1
A setORtou() 0 5 2
F writeInstaller() 0 98 20
A innerAuth() 0 25 5
A getServerSideCredentials() 0 34 5
A getEapMethod() 0 16 3
A getAuthenticationMethodParams() 0 14 4
A getProviderInfo() 0 10 1
A getProviderLocation() 0 16 3
A getProviderLogo() 0 17 3
A getClientSideCredentials() 0 22 4
A getClientCertificate() 0 6 1
A setClientSideRealm() 0 13 4
A getCredentialApplicability() 0 22 6
A getAuthMethodsList() 0 17 5
A getHelpdesk() 0 7 1
B scaleLogo() 0 42 6
A getProviderTou() 0 21 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
     * 
88
     * @var string
89
     */
90
    public $langScope;
91
92
    /**
93
     * whether all EAP types should be included in the file or only the 
94
     * preferred one
95
     * 
96
     * @var boolean
97
     */
98
    public $allEaps = false;
99
100
    /**
101
     * vendor-specific additional information, this is nit yest fully
102
     * implemented due to lack of use cases.
103
     * 
104
     * @var array
105
     */
106
    public $VendorSpecific;
107
    
108
    /**
109
     * A flag to preserve backwards compatibility for eduroamCAT application
110
     */
111
    public $eduroamCATcompatibility = false; 
112
    public $singleEAPProvider = false;
113
114
    private $eapId;
115
    private $namespace;
116
    private $providerInfo;
117
    private $authMethodsList;
118
    
119
    /**
120
     * create HTML code explaining the installer
121
     * 
122
     * @return string
123
     */
124
    public function writeDeviceInfo()
125
    {
126
        \core\common\Entity::intoThePotatoes();
127
        $out = "<p>";
128
        $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");
129
        \core\common\Entity::outOfThePotatoes();
130
        return $out;
131
    }
132
133
    /**
134
     * create the actual XML file
135
     * 
136
     * @return string filename of the generated installer
137
     * @throws Exception
138
     *
139
     */
140
    public function writeInstaller()
141
    {
142
        \core\common\Entity::intoThePotatoes();
143
        $rootname = 'EAPIdentityProviderList';
144
        $dom = new \DOMDocument('1.0', 'utf-8');
145
        $root = $dom->createElement($rootname);
146
        $dom->appendChild($root);
147
        $ns = $dom->createAttributeNS( 'http://www.w3.org/2001/XMLSchema-instance', 'xsi:noNamespaceSchemaLocation' );
148
        $ns->value = "eap-metadata.xsd";
149
        $root->appendChild($ns);
150
        $this->openRoamingToU = sprintf(_("I have read and agree to OpenRoaming Terms of Use at %s."), "https://wballiance.com/openroaming/toc-2020/");
151
        foreach ($this->languageInstance->getAllTranslations("I have read and agree to OpenRoaming Terms of Use at %s", "device") as $lang => $message) {
152
            $this->openRoamingToUArray[$lang] = sprintf($message, "https://wballiance.com/openroaming/toc-2020/");
153
        }
154
        
155
        if (empty($this->attributes['internal:realm'][0])) {
156
            $this->eapId = 'undefined';
157
            $this->namespace = 'urn:undefined';
158
        } else {
159
            $this->eapId = $this->attributes['internal:realm'][0];
160
            $this->namespace = 'urn:RFC4282:realm';
161
        }
162
        
163
        $this->authMethodsList = $this->getAuthMethodsList();
164
        $this->loggerInstance->debug(5, $this->attributes['internal:networks'], "NETWORKS:", "\n");
165
        /*
166
         * This approach is forced by geteduroam compatibility. We pack all networks into a single Provider
167
         * with the exception of the openroaming one which we pack separately.
168
         */
169
        
170
        if ($this->singleEAPProvider === true) {
171
            /*
172
             * if "condition" is set to openroaming, OpenRoaming terms of use must be mentioned
173
             * unless the preagreed is set for openroaming
174
             * if "ask" is set then we generate a separate OR profile which needs to contain the OR ToU
175
             * the ToU is not needed in the eduroam-only profile
176
             */
177
            $ssids = [];
178
            $ois = [];
179
            $orNetwork = [];
180
            foreach ($this->attributes['internal:networks'] as $netName => $netDefinition) {
181
                if ($netDefinition['condition'] === 'internal:openroaming' &&
182
                        $this->attributes['internal:openroaming']) {
183
                    $this->setORtou();
184
                    if (preg_match("/^ask/",$this->attributes['media:openroaming'][0])) {
185
                        $orNetwork = $netDefinition;
186
                        continue;                        
187
                    }
188
                }
189
                foreach ($netDefinition['ssid'] as $ssid) {
190
                    $ssids[] = $ssid;
191
                }
192
                foreach ($netDefinition['oi'] as $oi) {
193
                    $ois[] = $oi;
194
                }
195
            }
196
197
            if (!empty($orNetwork)) {
198
                $this->addORtou = false;
199
            }
200
            $this->providerInfo = $this->getProviderInfo();
201
            
202
            if (!empty($ssids) || !empty($ois)) {
203
                \core\DeviceXMLmain::marshalObject($dom, $root, 'EAPIdentityProvider', $this->eapIdp($ssids, $ois));
204
            }
205
            
206
            if (!empty($orNetwork)) {
207
                // here we need to add the Tou unless preagreed is set
208
                $this->setORtou();
209
                $this->providerInfo = $this->getProviderInfo();
210
                \core\DeviceXMLmain::marshalObject($dom, $root, 'EAPIdentityProvider', $this->eapIdp($orNetwork['ssid'], $orNetwork['oi']));
211
            }
212
        } else {
213
214
            foreach ($this->attributes['internal:networks'] as $netName => $netDefinition) {
215
                if ($netDefinition['condition'] === 'internal:openroaming' &&
216
                        $this->attributes['internal:openroaming']) {
217
                    $this->setORtou();
218
                } else {
219
                    $this->addORtou = false;
220
                }
221
                $this->providerInfo = $this->getProviderInfo();
222
                $ssids = $netDefinition['ssid'];
223
                $ois = $netDefinition['oi'];
224
                if (!empty($ssids) || !empty($ois)) {
225
                    \core\DeviceXMLmain::marshalObject($dom, $root, 'EAPIdentityProvider', $this->eapIdp($ssids, $ois));
226
                }
227
            }
228
        }
229
        
230
        if ($dom->schemaValidate(ROOT.'/devices/eap_config/eap-metadata.xsd') === FALSE) {
231
            throw new Exception("Schema validation failed for eap-metadata");
232
        }
233
234
        $dom->formatOutput = true;
235
        file_put_contents($this->installerBasename.'.eap-config', $dom->saveXML($dom));
236
        \core\common\Entity::outOfThePotatoes();
237
        return($this->installerBasename.'.eap-config');
238
    }
239
    
240
    private function setORtou() {
241
        if (preg_match("/preagreed/",$this->attributes['media:openroaming'][0])) {
242
            $this->addORtou = false;
243
        } else {
244
            $this->addORtou = true;
245
        }
246
    }
247
    
248
    /**
249
     * determines the inner authentication. Is it EAP, and which mechanism is used to convey actual auth data
250
     * @param array $eap the EAP type for which we want to get the inner auth
251
     * @return array
252
     */    
253
    private function eapIdp($ssids, $oids)
254
    {
255
        $eapIdp = new \core\DeviceXMLmain();
256
        $eapIdp->setAttribute('version', '1');
257
        if ($this->langScope === 'single') {
258
            $eapIdp->setAttribute('lang', $this->languageInstance->getLang());
259
        }
260
        $eapIdp->setAttribute('ID', $this->eapId);
261
        $eapIdp->setAttribute('namespace', $this->namespace);
262
        $authMethods = new \core\DeviceXMLmain();
263
        $authMethods->setChild('AuthenticationMethod', $this->authMethodsList);
264
        $eapIdp->setChild('AuthenticationMethods', $authMethods);
265
        $eapIdp->setChild('CredentialApplicability', $this->getCredentialApplicability($ssids,$oids));
266
// TODO   $eap_idp->setChild('ValidUntil',$this->getValidUntil());
267
        $eapIdp->setChild('ProviderInfo', $this->providerInfo);
268
// TODO   $eap_idp->setChild('VendorSpecific',$this->getVendorSpecific());
269
        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...
270
    }
271
272
    /**
273
     * determines the inner authentication. Is it EAP, and which mechanism is used to convey actual auth data
274
     * @param array $eap the EAP type for which we want to get the inner auth
275
     * @return array
276
     */  
277
    private function innerAuth($eap)
278
    {
279
        $out = [];
280
        $out['EAP'] = 0;
281
        switch ($eap["INNER"]) {
282
            case \core\common\EAP::NE_MSCHAP2:
283
                if ($this->eduroamCATcompatibility === TRUE) {
284
                    $out['METHOD'] = \core\common\EAP::MSCHAP2;
285
                    $out['EAP'] = 1;
286
                } else {
287
                    $out['METHOD'] = $eap["INNER"];
288
                }
289
                break;
290
            case \core\common\EAP::NE_SILVERBULLET:
291
                $out['METHOD'] = \core\common\EAP::NONE;
292
                break;
293
            default:
294
                $out['METHOD'] = $eap["INNER"];
295
                break;
296
        }
297
        // override if there is an inner EAP
298
        if ($eap["INNER"] > 0) { // there is an inner EAP method
299
            $out['EAP'] = 1;
300
        }
301
        return $out;
302
    }
303
    
304
    /**
305
     * 
306
     * @param string $attrName the attribute name
307
     * @return array of values for this attribute
308
     */
309
    private function getSimpleMLAttribute($attrName)
310
    {
311
        if (empty($this->attributes[$attrName][0])) {
312
            return([]);
313
        }
314
        $attributeList = $this->attributes[$attrName];
315
        $objs = [];
316
        if ($this->langScope === 'global') {
317
            foreach ($attributeList['langs'] as $language => $value) {
318
                $language = ($language === 'C' ? 'any' : $language);
319
                $obj = new \core\DeviceXMLmain();
320
                $obj->setValue($value);
321
                $obj->setAttributes(['lang' => $language]);
322
                $objs[] = $obj;
323
            }
324
        } else {
325
            $objs[] = $attributeList[0];
326
        }
327
        return($objs);
328
    }
329
    
330
    /**
331
     * constructs the name of the institution and puts it into the XML.
332
     * consists of the best-language-match inst name, and if the inst has more 
333
     * than one profile also the best-language-match profile name
334
     * 
335
     * @return \core\DeviceXMLmain[]
336
     */
337
    private function getDisplayName()
338
    {
339
        $attr = $this->attributes;
340
        $objs = [];
341
        if ($this->langScope === 'global') {
342
            $instNameLangs = $attr['general:instname']['langs'];
343
            if ($attr['internal:profile_count'][0] > 1) {
344
                $profileNameLangs = $attr['profile:name']['langs'];
345
            }
346
            foreach ($instNameLangs as $language => $value) {
347
                $language = ($language === 'C' ? 'any' : $language);
348
                $displayname = new \core\DeviceXMLmain();
349
                if (isset($profileNameLangs)) {
350
                    $langOrC = isset($profileNameLangs[$language]) ? $profileNameLangs[$language] : $profileNameLangs['C'];
351
                    $value .= ' - '.$langOrC;
352
                }
353
                $displayname->setValue($value);
354
                $displayname->setAttributes(['lang' => $language]);
355
                $objs[] = $displayname;
356
            }
357
        } else {
358
            $displayname = new \core\DeviceXMLmain();
359
            $value = $attr['general:instname'][0];
360
            if ($attr['internal:profile_count'][0] > 1) {
361
                $value .= ' - '.$attr['profile:name'][0];
362
            }
363
            $displayname->setValue($value);
364
            $objs[] = $displayname;
365
        }
366
        return $objs;
367
    }
368
369
    /**
370
     * retrieves the provider logo and puts it into the XML structure
371
     * 
372
     * @return \core\DeviceXMLmain
373
     */
374
    private function getProviderLogo()
375
    {
376
        $attr = $this->attributes;
377
        if (isset($attr['general:logo_file'][0])) {
378
            $rawLogoBlob = $attr['general:logo_file'][0];
379
            $logoMime= $attr['internal:logo_file'][0]['mime'];
380
            [$scaledBlob, $scaledMime] = $this->scaleLogo($rawLogoBlob, $logoMime);
381
            if ($scaledMime == 'none') {
382
                return NULL;
383
            }
384
            $logoString = base64_encode($scaledBlob);
385
            $providerlogo = new \core\DeviceXMLmain();
386
            $providerlogo->setAttributes(['mime' => 'image/'.$scaledMime, 'encoding' => 'base64']);
387
            $providerlogo->setValue($logoString);
388
            return $providerlogo;
389
        }
390
        return NULL;
391
    }
392
    
393
    /**
394
     * Scales a logo to the desired byte imag size if necessary.
395
     * If the image size is below tha alowed maximum, nothing is done;
396
     * if the image is larger than we run a series of scaling iterations to sizes
397
     * specified in $maxPixelSize and the moment we manage to end up below the $maxByte
398
     * we returm the scaled blob - we always use png as the output format since it seems
399
     * to behave best in scaling.
400
     * 
401
     * @param string $blob the image data
402
     * @param string $mime the mime type of the original image
403
     * @return array the scaled blob, the resulting mime type
404
     */
405
    private function scaleLogo($blob, $mime)
406
    {
407
        $maxByte = 1024*50;
408
        $maxPixelSize = [400,300,200,100];
409
        // start with the actual file size
410
        $logoSize = strlen($blob);
411
        \core\common\Logging::debug_s(4, $logoSize, "Logo file size: ", "\n");
412
        if ($logoSize <= $maxByte) {
413
            return [$blob, $mime];
414
        }
415
        // resize logo if necessary
416
        /* Gmagic implementation would require method naming changes
417
        if (class_exists('\\Gmagick')) { 
418
            $imageObject = new \Gmagick(); 
419
        } else {
420
         * 
421
         */
422
            $imageObject = new \Imagick();
423
//        }
424
        try {
425
            $imageObject->readImageBlob($blob);
426
        } catch (Exception $e) {
427
            return ['', 'none'];
428
        }
429
        $imageSize = $imageObject->getImageGeometry();
430
        \core\common\Logging::debug_s(4, $imageSize, "Input logo pixel size: ","\n");        
431
        foreach ($maxPixelSize as $size) {
432
            $tmpImage = $imageObject;
433
            $tmpImage->setImageFormat('PNG');
434
            \core\common\Logging::debug_s(4, $size, "Reducing size to: ", "\n");
435
            if ($imageSize['width'] > $imageSize['height']) {
436
                $tmpImage->thumbnailImage($size, 0);
437
            } else {
438
                $tmpImage->thumbnailImage(0, $size);
439
            }
440
            $outBlob = $tmpImage->getImageBlob();
441
            if (strlen($outBlob) <= $maxByte) {
442
                break;
443
            }
444
        }
445
        \core\common\Logging::debug_s(4, strlen($outBlob), "Scaled size: ", "\n");
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $outBlob seems to be defined by a foreach iteration on line 431. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
446
        return [$outBlob, 'png'];
447
    }
448
449
    /**
450
     * retrieves provider information and puts it into the XML structure.
451
     * contains the profile description and the ToU file, if any
452
     * 
453
     * @return \core\DeviceXMLmain
454
     */
455
    private function getProviderInfo()
456
    {
457
        $providerinfo = new \core\DeviceXMLmain();
458
        $providerinfo->setChild('DisplayName', $this->getDisplayName());
459
        $providerinfo->setChild('Description', $this->getSimpleMLAttribute('profile:description'));
460
        $providerinfo->setChild('ProviderLocation', $this->getProviderLocation());
461
        $providerinfo->setChild('ProviderLogo', $this->getProviderLogo());
462
        $providerinfo->setChild('TermsOfUse', $this->getProviderTou(), null, 'cdata');
463
        $providerinfo->setChild('Helpdesk', $this->getHelpdesk());
464
        return $providerinfo; 
465
    }
466
    
467
    private function getProviderTou() {
468
        $standardTou = $this->getSimpleMLAttribute('support:info_file');
469
        if ($this->addORtou === false) {
470
            return $standardTou;
471
        }
472
        $out = [];
473
        if ($this->langScope === 'global') {
474
            foreach ($standardTou as $touObj) {
475
                $tou = $touObj->getValue();
476
                $lngAttr = $touObj->getAttributes();
477
                $lng = $lngAttr['lang'] === 'any' ? \config\Master::APPEARANCE['defaultlocale'] : $lngAttr['lang'];
478
                $tou .= "\n".$this->openRoamingToUArray[$lng];
479
                $touObj->setValue($tou);
480
                $out[] =  $touObj;
481
            } 
482
        } else {
483
            $tou = $standardTou[0];
484
            $tou .= "\n".$this->openRoamingToU;
485
            $out = [$tou];
486
        }
487
        return $out;
488
    }
489
490
    /**
491
     * retrieves the location information and puts it into the XML structure
492
     * 
493
     * @return \core\DeviceXMLmain[]
494
     */
495
    private function getProviderLocation()
496
    {
497
        $attr = $this->attributes;
498
        if (isset($attr['general:geo_coordinates'])) {
499
            $attrCoordinates = $attr['general:geo_coordinates'];
500
            $location = [];
501
            foreach ($attrCoordinates as $a) {
502
                $providerlocation = new \core\DeviceXMLmain();
503
                $b = json_decode($a, true);
504
                $providerlocation->setChild('Longitude', $b['lon']);
505
                $providerlocation->setChild('Latitude', $b['lat']);
506
                $location[] = $providerlocation;
507
            }           
508
            return $location;
509
        }
510
        return NULL;
511
    }
512
513
    /**
514
     * retrieves helpdesk contact information and puts it into the XML structure
515
     * 
516
     * @return \core\DeviceXMLmain
517
     */
518
    private function getHelpdesk()
519
    {
520
        $helpdesk = new \core\DeviceXMLmain();
521
        $helpdesk->setChild('EmailAddress', $this->getSimpleMLAttribute('support:email'));
522
        $helpdesk->setChild('WebAddress', $this->getSimpleMLAttribute('support:url'));
523
        $helpdesk->setChild('Phone', $this->getSimpleMLAttribute('support:phone'));
524
        return $helpdesk;
525
    }
526
527
    /**
528
     * determine where this credential should be applicable
529
     * 
530
     * @return \core\DeviceXMLmain
531
     */
532
    private function getCredentialApplicability($ssids, $oids)
533
    {
534
        $setWired = isset($this->attributes['media:wired'][0]) && 
535
                $this->attributes['media:wired'][0] == 'on' ? 1 : 0;        
536
        $credentialapplicability = new \core\DeviceXMLmain();
537
        $ieee80211s = [];
538
        foreach ($ssids as $ssid) {
539
            $ieee80211 = new \core\DeviceXMLmain();
540
            $ieee80211->setChild('SSID', $ssid);
541
            $ieee80211->setChild('MinRSNProto', 'CCMP');
542
            $ieee80211s[] = $ieee80211;
543
        }
544
        foreach ($oids as $oid) {
545
            $ieee80211 = new \core\DeviceXMLmain();
546
            $ieee80211->setChild('ConsortiumOID', $oid);
547
            $ieee80211s[] = $ieee80211;
548
        }
549
        $credentialapplicability->setChild('IEEE80211', $ieee80211s);
550
        if ($setWired) {
551
            $credentialapplicability->setChild('IEEE8023', '');
552
        }
553
        return $credentialapplicability;
554
    }
555
556
    /**
557
     * retrieves the parameters needed for the given EAP method and creates
558
     * appropriate nodes in the XML structure for them
559
     * 
560
     * @param array $eap the EAP type in question
561
     * @return array a recap of the findings
562
     */
563
    private function getAuthenticationMethodParams($eap)
564
    {
565
        $inner = $this->innerAuth($eap);
566
        $outerMethod = $eap["OUTER"];
567
568
        if (isset($inner["METHOD"]) && $inner["METHOD"]) {
569
            $innerauthmethod = new \core\DeviceXMLmain();
570
            $typeOfInner = ($inner["EAP"] ? 'EAPMethod' : 'NonEAPAuthMethod');
571
            $eapmethod = new \core\DeviceXMLmain();
572
            $eapmethod->setChild('Type', abs($inner['METHOD']));
573
            $innerauthmethod->setChild($typeOfInner, $eapmethod);
574
            return ['inner_method' => $innerauthmethod, 'methodID' => $outerMethod, 'inner_methodID' => $inner['METHOD']];
575
        } else {
576
            return ['inner_method' => 0, 'methodID' => $outerMethod, 'inner_methodID' => 0];
577
        }
578
    }
579
580
    /**
581
     * sets the server-side credentials for a given EAP type
582
     * 
583
     * @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...
584
     * @return \core\DeviceXMLmain
585
     */
586
    private function getServerSideCredentials($eap)
587
    {
588
        $attr = $this->attributes;
589
        $children = $this->authMethodElements['server'][$eap];
590
        $serversidecredential = new \core\DeviceXMLmain();
591
// Certificates and server names
592
        $cAlist = [];
593
        $attrCaList = $attr['internal:CAs'][0];
594
        foreach ($attrCaList as $ca) {
595
            /* possibly we will want to stop sending server certificates in the future
596
            if ($ca['full_details']['type'] == 'server') {
597
                continue;
598
            }
599
             * 
600
             */
601
            $caObject = new \core\DeviceXMLmain();
602
            $caObject->setValue(base64_encode($ca['der']));
603
            $caObject->setAttributes(['format' => 'X.509', 'encoding' => 'base64']);
604
            $cAlist[] = $caObject;
605
        }
606
        $serverids = [];
607
        $servers = $attr['eap:server_name'];
608
        foreach ($servers as $server) {
609
            $serverid = new \core\DeviceXMLmain();
610
            $serverid->setValue($server);
611
            $serverids[] = $serverid;
612
        }
613
        if (in_array('CA', $children)) {
614
            $serversidecredential->setChild('CA', $cAlist);
615
        }
616
        if (in_array('ServerID', $children)) {
617
            $serversidecredential->setChild('ServerID', $serverids);
618
        }
619
        return $serversidecredential;
620
    }
621
622
    /**
623
     * sets the realm information for the client-side credential
624
     * 
625
     * @param \core\DeviceXMLmain $clientsidecredential the ClientSideCredential to which the realm info is to be added
626
     * @return void
627
     */
628
    private function setClientSideRealm($clientsidecredential)
629
    {
630
        $attr = $this->attributes;
631
        $realm = \core\common\Entity::getAttributeValue($attr, 'internal:realm', 0);
632
        if ($realm === NULL) {
633
            return;
634
        }
635
        if (\core\common\Entity::getAttributeValue($attr, 'internal:verify_userinput_suffix', 0) !== 1) {
636
            return;
637
        }
638
        $clientsidecredential->setChild('InnerIdentitySuffix', $realm);
639
        if (\core\common\Entity::getAttributeValue($attr, 'internal:hint_userinput_suffix', 0) === 1) {
640
            $clientsidecredential->setChild('InnerIdentityHint', 'true');
641
        }
642
    }
643
644
    /**
645
     * sets the client certificate
646
     * 
647
     * @return \core\DeviceXMLmain
648
     */
649
    private function getClientCertificate()
650
    {
651
        $clientCertificateObject = new \core\DeviceXMLmain();
652
        $clientCertificateObject->setValue(base64_encode($this->clientCert["certdata"]));
653
        $clientCertificateObject->setAttributes(['format' => 'PKCS12', 'encoding' => 'base64']);
654
        return $clientCertificateObject;
655
    }
656
657
    /**
658
     * sets the client-side credentials for the given EAP type
659
     * 
660
     * @param array $eapParams the EAP parameters
661
     * @return \core\DeviceXMLmain
662
     */
663
    private function getClientSideCredentials($eap)
664
    {
665
        $children = $this->authMethodElements['client'][$eap];
666
        $clientsidecredential = new \core\DeviceXMLmain();
667
        $outerId = $this->determineOuterIdString();
668
        $this->loggerInstance->debug(5, $eap, "XMLOI:", "\n");
669
        if (in_array('OuterIdentity', $children)) {
670
            if ($outerId !== NULL) {
671
                $clientsidecredential->setChild('OuterIdentity', $outerId);
672
            }
673
        }
674
        $this->setClientSideRealm($clientsidecredential);
675
//        $clientsidecredential->setChild('EAPType', $eapParams['inner_methodID'] ? $eapParams['inner_methodID'] : $eapParams['methodID']);
676
677
        // Client Certificate
678
        if ($this->selectedEap == \core\common\EAP::EAPTYPE_SILVERBULLET) {
679
            $attr = $this->attributes;
680
            $outerId = \core\common\Entity::getAttributeValue($attr, 'internal:username', 0);
681
            $clientsidecredential->setChild('OuterIdentity', $outerId);
682
            $clientsidecredential->setChild('ClientCertificate', $this->getClientCertificate());
683
        }
684
        return $clientsidecredential;
685
    }
686
687
    /**
688
     * sets the EAP method
689
     * 
690
     * @param \devices\XML\Type $eaptype the EAP type XMLObject
691
     * @return \core\DeviceXMLmain
692
     */
693
    private function getEapMethod($eaptype)
694
    {
695
        $eapmethod = new \core\DeviceXMLmain();
696
        $eapmethod->setChild('Type', $eaptype);
697
        if (isset($this->VendorSpecific)) {
698
            $vendorspecifics = [];
699
            foreach ($this->VendorSpecific as $vs) {
700
                $vendorspecific = new \core\DeviceXMLmain();
701
                $vs['value']->addAttribute('xsi:noNamespaceSchemaLocation', "xxx.xsd");
702
                $vendorspecific->setValue($vs['value']);
703
                $vendorspecific->setAttributes(['vendor' => $vs['vendor']]);
704
                $vendorspecifics[] = $vendorspecific;
705
            }
706
            $eapmethod->setChild('VendorSpecific', $vendorspecifics);
707
        }
708
        return($eapmethod);
709
    }
710
711
    /**
712
     * determines the authentication method to use
713
     * 
714
     * @param array $eap the EAP methods, in array representation
715
     * @return \core\DeviceXMLmain
716
     */
717
    private function getAuthMethod($eap)
718
    {
719
        $authmethod = new \core\DeviceXMLmain();
720
        $eapParams = $this->getAuthenticationMethodParams($eap);
721
        $eaptype = new \core\DeviceXMLmain();
722
        $eaptype->setValue($eapParams['methodID']);
723
// Type
724
        $authmethod->setChild('EAPMethod', $this->getEapMethod($eaptype));
725
726
// ServerSideCredentials
727
        $authmethod->setChild('ServerSideCredential', $this->getServerSideCredentials($eap['OUTER']));
728
729
// ClientSideCredentials
730
        $authmethod->setChild('ClientSideCredential', $this->getClientSideCredentials($eap['INNER']));
731
732
        if ($eapParams['inner_method']) {
733
            $authmethod->setChild('InnerAuthenticationMethod', $eapParams['inner_method']);
734
        }
735
        return $authmethod;
736
    }
737
    
738
    private function getAuthMethodsList() {
739
        $methodList = [];
740
        if ($this->allEaps) {
741
            $eapmethods = [];
742
            foreach ($this->attributes['all_eaps'] as $eap) {
743
                $eapRep = $eap->getArrayRep();
744
                if (in_array($eapRep, $this->supportedEapMethods)) {
745
                    $eapmethods[] = $eapRep;
746
                }
747
            }
748
        } else {
749
            $eapmethods = [$this->selectedEap];
750
        }
751
        foreach ($eapmethods as $eap) {
752
            $methodList[] = $this->getAuthMethod($eap);
753
        }
754
        return $methodList;
755
    }
756
    
757
    private $openRoamingToUArray;
758
    private $openRoamingToU;
759
    private $addORtou = false;
760
761
}
762