Issues (204)

Security Analysis    13 potential vulnerabilities

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  Response Splitting (2)
Response Splitting can be used to send arbitrary responses.
  File Manipulation (6)
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Variable Injection (1)
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Cross-Site Scripting (1)
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

devices/eap_config/DeviceXML.php (3 issues)

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
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