RADIUSTestsUI   F
last analyzed

Complexity

Total Complexity 112

Size/Duplication

Total Lines 554
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 112
eloc 375
dl 0
loc 554
rs 2
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
C printStatic() 0 54 12
A isDynamic() 0 6 2
F printOverview() 0 96 20
B printDynamic() 0 33 8
F collectCAPath() 0 76 20
C setGlobalDynamicResult() 0 46 17
D collectClients() 0 99 21
B __construct() 0 61 9
A setGlobalStaticResult() 0 4 2
A getTimeStamp() 0 3 1

How to fix   Complexity   

Complex Class

Complex classes like RADIUSTestsUI 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 RADIUSTestsUI, 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 contains code for testing presenting tests result
25
 *
26
 * @author Maja Gorecka-Wolniewicz <[email protected]>
27
 *
28
 * @package Developer
29
 * 
30
 */
31
32
namespace core\diag;
33
34
use \Exception;
0 ignored issues
show
Bug introduced by
The type \Exception 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...
35
36
class RADIUSTestsUI extends AbstractTest
37
{
38
39
    /**
40
     * This private variable contains the realm to be checked. Is filled in the
41
     * class constructor.
42
     * 
43
     * @var string
44
     */
45
    public $realm = NULL;
46
    public $outerUser = NULL;
47
48
    /**
49
     * result of the reachability tests
50
     * 
51
     * @var array
52
     */
53
    public $allReachabilityResults = [];
54
    
55
    private $hostMap = [];
56
    private $protocolsMap = [];
57
    private $globalLevelStatic = \core\common\Entity::L_OK;
58
    private $globalLevelDynamic = \core\common\Entity::L_OK;
59
    private $rfc7585suite = NULL;
60
    private $srv;
61
    private $naptr;
62
    private $naptrValid;
63
    private $hosts;
64
    private $testSuite;
65
    private $areFailed = FALSE;
66
    private $allCApathFailed = FALSE;
67
    private $globalInfo = [];
68
    private $stateIcons = [];
69
    private $states;
70
    private $certFields;
71
    private $timestamp;
72
    const RADIUS_TEST_OPERATION_MODE_SHALLOW = 1;
73
    const RADIUS_TEST_OPERATION_MODE_THOROUGH = 2;
74
    
75
    
76
77
    /**
78
     * Constructor for the RADIUSTestsUI class. The single mandatory parameter is the
79
     * token indicating tests that were carried out and saved as JSON files.
80
     * 
81
     * @param string $token                  the token which points to a directory
82
     * @throws Exception
83
     */
84
    public function __construct($token)
85
    {
86
        parent::__construct();
87
        $this->globalInfo = [
88
            \core\common\Entity::L_OK => _("All tests passed."),
89
            \core\common\Entity::L_WARN => _("There were some warnings."),
90
            \core\common\Entity::L_ERROR => _("There were some errors."),
91
            \core\common\Entity::L_REMARK => _("There were some remarks.")
92
        ]; 
93
        $this->stateIcons = [
94
            \core\common\Entity::L_OK => '../resources/images/icons/Tabler/square-rounded-check-filled-green.svg',
95
            \core\common\Entity::L_WARN => '../resources/images/icons/Tabler/alert-square-rounded-filled-yellow.svg',
96
            \core\common\Entity::L_ERROR => '../resources/images/icons/Tabler/square-rounded-x-filled-red.svg',
97
            \core\common\Entity::L_REMARK => '../resources/images/icons/Tabler/info-square-rounded-filled-blue.svg'
98
        ];
99
        $this->states = [
100
            'PASS' => _("PASS"),
101
            'FAIL' => _("FAIL")
102
        ];
103
        $this->certFields = [
104
            'subject' => _("Subject:"),
105
            'issuer' => _("Issuer:"),
106
            'validFrom' =>  _("Valid from:"),
107
            'validTo' => _("Valid to:"),
108
            'serialNumber' => _("Serial number:"),
109
            'sha1' => _("SHA1 fingerprint:"),
110
            'public_key_length' => _("Public key length:"),
111
            'title' => _("Server certificate"),
112
            'policies' => _("Policies:"),
113
            'crldistributionpoints' =>  _("crlDistributionPoint:"),
114
            'authorityinfoaccess' => _("authorityInfoAccess:"),
115
            'subjectaltname' => _("SubjectAltName:"),
116
        ];
117
        $jsondir = dirname(dirname(dirname(__FILE__)))."/var/json_cache";
118
        if ($token && is_dir($jsondir.'/'.$token)) {
119
            foreach (['realm', 'udp', 'clients', 'capath'] as $test_type) {
120
                foreach (glob("$jsondir/$token/$test_type*") as $filename) {
121
                    $this->loggerInstance->debug(4, "\nIS_DIR $filename\n");
122
                    if (!array_key_exists($test_type, $this->allReachabilityResults)) {
123
                        $this->allReachabilityResults[$test_type] = array();
124
                    }
125
                    $this->allReachabilityResults[$test_type][] = json_decode(file_get_contents($filename));
126
                }   
127
            }
128
            if ($this->allReachabilityResults['realm'][0]->realm) {
129
                $this->realm = $this->allReachabilityResults['realm'][0]->realm;
130
                $this->outerUser = $this->allReachabilityResults['realm'][0]->outeruser;
131
                foreach ($this->allReachabilityResults['realm'][0]->totest as $totest) {
132
                    $this->hostMap[$totest->host] = $totest->bracketaddr;
133
                    if (property_exists($totest, 'protocols')) {
134
                        $this->protocolsMap[$totest->host] = $totest->protocols;
135
                    }
136
                }
137
                $this->rfc7585suite = unserialize(base64_decode($this->allReachabilityResults['realm'][0]->rfc7585suite));
138
                $this->srv = $this->allReachabilityResults['realm'][0]->srv;
139
                $this->naptr = $this->allReachabilityResults['realm'][0]->naptr;
140
                $this->naptrValid = $this->allReachabilityResults['realm'][0]->naptr_valid;
141
                $this->hosts = $this->allReachabilityResults['realm'][0]->hosts;
142
                $this->testSuite = unserialize(base64_decode($this->allReachabilityResults['realm'][0]->testsuite));
143
            }
144
            $this->timestamp = $this->allReachabilityResults['realm'][0]->datetime;
145
        }
146
    }
147
    
148
    public function getTimeStamp()
149
    { 
150
        return $this->timestamp;
151
    }
152
    /**
153
     * sets the global status for static tests
154
     */
155
    public function setGlobalStaticResult()
156
    { 
157
        foreach ($this->allReachabilityResults['udp'] as $udp) {
158
            $this->globalLevelStatic = max($this->globalLevelStatic, $udp->result[0]->level);
159
        }
160
    }
161
    
162
    public function setGlobalDynamicResult()
163
    {
164
        if (isset($this->allReachabilityResults['capath'])) {
165
            foreach ($this->allReachabilityResults['capath'] as $capath) {
166
                $this->globalLevelDynamic = max($this->globalLevelDynamic, $capath->level);
167
            }
168
        }
169
        if (isset($this->allReachabilityResults['clients'])) {
170
            foreach ($this->allReachabilityResults['clients'] as $clients) {
171
                $srefused = FALSE;
172
                $level = \core\common\Entity::L_OK;
173
                $maxlevel = $level;
174
                foreach ($clients->ca as $ca) {
175
                    foreach ($ca->certificate as $certificate) {
176
                        if ($certificate->returncode == \core\diag\RADIUSTests::RETVAL_CONNECTION_REFUSED) {
177
                            $srefused = $this->areFailed = TRUE;
178
                        }
179
                    }
180
                    if (!$srefused) {
181
                        foreach ($clients->ca as $cca) {
182
                            foreach ($cca->certificate as $certificate) {
183
                                $level = $certificate->returncode;
184
                                if ($level < 0) {
185
                                    $level = \core\common\Entity::L_ERROR;
186
                                    $this->areFailed = TRUE;
187
                                }
188
                                if ($certificate->expected != 'PASS') {
189
                                    if ($certificate->connected == 1) {
190
                                        $level = \core\common\Entity::L_WARN;
191
                                    } else {
192
                                        
193
                                        if ($certificate->status == 'EXPIRED' && property_exists($certificate, 'reason')) {
194
                                            $level = \core\common\Entity::L_WARN;
195
                                        } else {
196
                                            $level = \core\common\Entity::L_OK;
197
                                        }
198
                                    }
199
                                }
200
                                if ($level > $maxlevel) {
201
                                    $maxlevel = $level;
202
                                }
203
                            }
204
                        }
205
                    } 
206
                }
207
                $this->globalLevelDynamic = max($this->globalLevelDynamic, $maxlevel);
208
            }
209
        }
210
    }           
211
212
    public function isDynamic()
213
    {
214
        if ($this->naptr > 0) {
215
            return TRUE;
216
        }
217
        return FALSE;
218
    }
219
    /**
220
     * prints tabs-1
221
     * 
222
     * 
223
     */
224
    public function printOverview()
225
    {
226
        $out = [];
227
        $out[] = "<fieldset class='option_container'>
228
        <legend>
229
        <strong>"._("Overview").'</strong> 
230
        </legend>';
231
        $out[] = "<strong>"._("DNS checks")."</strong><div>";
232
        if ($this->naptr != \core\diag\RADIUSTests::RETVAL_NOTCONFIGURED) {
233
            $out[] = "<table>";
234
            $out[] = "<tr><td>"._("Checking NAPTR existence:")."</td><td>";
235
            switch ($this->naptr) {
236
                case \core\diag\RFC7585Tests::RETVAL_NONAPTR:
237
                    $out[] = _("This realm has no NAPTR records.");
238
                    break;
239
                case \core\diag\RFC7585Tests::RETVAL_ONLYUNRELATEDNAPTR:
240
                    $out[] = _("This realm has NAPTR records, but none are related to this roaming consortium.");
241
                    break;
242
                default: // if none of the possible negative retvals, then we have matching NAPTRs
243
                    $out[] = sprintf(_("This realm has %d NAPTR records relating to this roaming consortium."), $this->naptr);
244
            }
245
            $out[] = "</td></tr>";
246
          
247
            if ($this->naptr > 0) {
248
                $out[] = "<tr><td>"._("Checking NAPTR compliance (flag = S and regex = {empty}):")."</td><td>";
249
                switch ($this->naptrValid) {
250
                    case \core\diag\RADIUSTests::RETVAL_OK:
251
                        $out[] = "No issues found.";
252
                        break;
253
                    case \core\diag\RADIUSTests::RETVAL_INVALID:
254
                        $out[] = _("At least one NAPTR with invalid content found!");
255
                        break;
256
                }
257
                $out[] = "</td></tr>";
258
            }
259
            // SRV resolution
260
            if ($this->naptr > 0 && $this->naptrValid == \core\diag\RADIUSTests::RETVAL_OK) {
261
                $out[] = "<tr><td>"._("Checking SRVs:")."</td><td>";
262
                switch ($this->srv) {
263
                    case \core\diag\RADIUSTests::RETVAL_SKIPPED:
264
                        $out[] = _("This check was skipped.");
265
                        break;
266
                    case \core\diag\RADIUSTests::RETVAL_INVALID:
267
                        $out[] = _("At least one NAPTR with invalid content found!");
268
                        break;
269
                    default: // print number of successfully retrieved SRV targets
270
                        $out[] = sprintf(_("%d host names discovered."), $this->srv);
271
                }
272
                $out[] = "</td></tr>";
273
            }
274
            // IP addresses for the hosts
275
            if ($this->naptr > 0 && $this->naptrValid == \core\diag\RADIUSTests::RETVAL_OK && $this->srv > 0) {
276
                $out[] = "<tr><td>"._("Checking IP address resolution:")."</td><td>";
277
                switch ($this->srv) {
278
                    case \core\diag\RADIUSTests::RETVAL_SKIPPED:
279
                        $out[] = _("This check was skipped.");
280
                        break;
281
                    case \core\diag\RADIUSTests::RETVAL_INVALID:
282
                        $out[] = _("At least one hostname could not be resolved!");
283
                        break;
284
                    default: // print number of successfully retrieved SRV targets
285
                        $out[] = sprintf(_("%d IP addresses resolved."), $this->hosts);
286
                }
287
                $out[] = "</td></tr>";
288
            }
289
290
            $out[] = "</table><br/>";
291
            $out[] = sprintf(_("Realm is <strong>%s</strong> "), _(($this->naptr > 0 ? "DYNAMIC" : "STATIC")));
292
            if (count($this->testSuite->listerrors()) == 0) {
293
                $out[] = _("with no DNS errors encountered. Congratulations!");
294
            } else {
295
                $out[] = _("but there were DNS errors! Check them!")." "._("You should re-run the tests after fixing the errors; more errors might be uncovered at that point. The exact error causes are listed below.");
296
                $out[] = "<div class='notacceptable'><table>";
297
                foreach ($this->testSuite->listerrors() as $details) {
298
                    $out[] = "<tr><td>".$details['TYPE']."</td><td>".$details['TARGET']."</td></tr>";
299
                }
300
                $out[] = "</table></div>";
301
            }
302
            $out[] = '</div>';
303
        } else {
304
            $out[] = "<tr><td>"._("Dynamic discovery test is not configured")."</td><td>";
305
        }
306
        $out[] = "<hr><strong>"._("Static connectivity tests")."</strong>
307
         <table><tr>
308
         <td class='icon_td'>";
309
        $out[] = "<img src='".$this->stateIcons[$this->globalLevelStatic]."' id='main_static_ico' class='icon'></td><td id='main_static_result'>".
310
                            $this->globalInfo[$this->globalLevelStatic].' '. _("See the appropriate tab for details.").'</td>
311
         </tr></table>';
312
        if ($this->naptr > 0) {
313
            $out[] = "<hr><strong>"._("Dynamic connectivity tests")."</strong>
314
            <table><tr>
315
            <td class='icon_td'><img src='".$this->stateIcons[$this->globalLevelDynamic]."' id='main_dynamic_ico' class='icon'></td><td id='main_dynamic_result'>".
316
            $this->globalInfo[$this->globalLevelDynamic].' '._("See the appropriate tab for details.").'</td></tr></table>';
317
        }
318
        $out[] = '</fieldset>';
319
        return join('', $out);
320
    }
321
    
322
    public function printStatic()
323
    {
324
        $out = [];
325
        $out[] = '<fieldset class="option_container" id="static_tests">
326
                  <legend><strong>';
327
        $out[] = _("STATIC connectivity tests");
328
        $out[] = '</strong> </legend>';
329
        $out[] = _("This check sends a request for the realm through various entry points of the roaming consortium infrastructure. The request will contain the 'Operator-Name' attribute, and will be larger than 1500 Bytes to catch two common configuration problems.<br/>Since we don't have actual credentials for the realm, we can't authenticate successfully - so the expected outcome is to get an Access-Reject after having gone through an EAP conversation.");
330
        $out[] = '<p>';
331
        foreach ($this->allReachabilityResults['udp'] as $udp) {
332
            $hostindex = $udp->hostindex;
333
            $result = $udp->result[0];
334
            $out[] = '<hr>';
335
            $out[] = sprintf(_("Testing from: <strong>%s"), \config\Diagnostics::RADIUSTESTS['UDP-hosts'][$hostindex]['display_name']).'</strong>';
336
            $out[] = '<ul style="list-style-type: none;"><li>';
337
            $out[] = "<table id='results$hostindex'  style='width:100%' class='udp_results'>
338
<tr>
339
<td class='icon_td'><img src='".$this->stateIcons[$result->level]."' id='src".$hostindex."_img'></td>
340
<td id='src$hostindex' colspan=2>
341
";
342
            $out[] = '<strong>'.($result->server ? $result->server : _("Connected to undetermined server")).'</strong><br/>'.sprintf (_("elapsed time: %sms."), $result->time_millisec).'<div>'.$result->message.'</div>';
343
                    
344
            if ($result->level > \core\common\Entity::L_OK && property_exists($result, 'cert_oddities')) {
345
                foreach ($result->cert_oddities as $oddities) {
346
                    $out[] = '<tr class="results_tr"><td>&nbsp;</td><td class="icon_td"><img src="'.$this->stateIcons[$oddities->level].'"></td><td>'.$oddities->message.'</td></tr>';
347
                }
348
            }
349
            $more = '';
350
            if ($result->server_cert) {
351
                $more .= '<div class="more">';
352
                $certdesc = '<br>'.$this->certFields['title'].'<ul>';
353
                foreach ($result->server_cert as $sckey => $sc) {
354
                    if (array_key_exists($sckey, $this->certFields)) {
355
                        $certdesc .= '<li>'.$this->certFields[$sckey].' '.$sc;
356
                    }
357
                }
358
                if ($result->server_cert->extensions) {
359
                    $certdesc .= '<li>' . _('Extensions') . '<ul>';
360
                    foreach ($result->server_cert->extensions as $ekey => $eval) {
361
                        $certdesc .= '<li>' . $ekey . ': ' . $eval;
362
                    }
363
                    $certdesc .= '</ul>';
364
                }
365
                $certdesc .= '</ul>';
366
                $more .= '<span class="morecontent"><span>'.$certdesc.
367
                        '</span><a href="" class="morelink">'._("show server certificate details").'&raquo;</a></span></div>';
368
            }     
369
            if ($more != '' ) {
370
                $out[] = '<tr><td>&nbsp;</td><td colspan="2">'.$more.'</td></tr>';
371
            }
372
            $out[] = "</table></ul>";
373
        }
374
        $out[] = '</fieldset>';
375
        return join('', $out);            
376
    }
377
    
378
    private function collectCAPath()
379
    {
380
        $capathtest = [];
381
        $capathtest[] = '<p><strong>'._("Checking server handshake...")."</strong><p>";
382
        $allfailed = TRUE;
383
        foreach ($this->allReachabilityResults['capath'] as $capath) {
384
            $hostindex = $capath->hostindex;          
385
            if ($capath->level == \core\common\Entity::L_OK && $capath->result == \core\diag\RADIUSTests::RETVAL_INVALID) {
386
                $capath->level = \core\common\Entity::L_ERROR;
387
            }
388
            $level = $capath->level; 
389
            if ($level == \core\common\Entity::L_OK) {
390
                $allfailed = FALSE;
391
            }
392
            $capathtest[] = '<p><strong>'.$this->hostMap[$capath->IP].'</strong> ('.$capath->name.') ';
393
            $prots = [];
394
            if (isset($this->protocolsMap[$capath->IP]) && $this->protocolsMap[$capath->IP] != '') {
395
                $prots = explode(';', $this->protocolsMap[$capath->IP]);
396
                if (!empty($prots)) {
397
                    $capathtest[] = ' ' . _("supported TLS protocols: ");
398
                    $capathtest[] = implode(', ', $prots);
399
                    if (!in_array("TLS1.3", $prots)) {
400
                        $capathtest[] =  ' ' . '<font color="red">' . _("not supported: ") . 'TLS1.3</font>';
401
                    }
402
                }
403
            }
404
            $capathtest[] = '<ul style="list-style-type: none;" class="caresult"><li>';
405
            $capathtest[] = "<table id='caresults$hostindex'  style='width:100%'>
406
<tr>
407
<td class='icon_td'><img src='";
408
            $capathtest[] = $this->stateIcons[$level]."' id='srcca".$hostindex."_img'></td>
409
<td id='srcca$hostindex'>";
410
            $more = '';
411
            if ($capath->certdata && $capath->certdata->subject != '') {
412
                $more .= '<div class="more">';
413
                $certdesc = '<br>'.$this->certFields['title'].'<ul>';
414
                if ($capath->certdata->subject) {
415
                    $certdesc .= '<li>'.$this->certFields['subject'].' '.$capath->certdata->subject;
416
                }
417
                if ($capath->certdata->issuer) {
418
                    $certdesc .= '<li>'.$this->certFields['issuer'].' '.$capath->certdata->issuer;
419
                }
420
                if ($capath->certdata->validTo) {
421
                    $certdesc .= '<li>'.$this->certFields['validTo'].' '.
422
                            date_create_from_format('ymdGis', 
423
                                    substr($capath->certdata->validTo, 0, -1))->format('Y-m-d H:i:s'). ' UTC';
424
                }
425
                if ($capath->certdata->extensions) {
426
                    if ($capath->certdata->extensions->subjectaltname) {                     
427
                        $certdesc .= '<li>'.$this->certFields['subjectaltname'].' '.$capath->certdata->extensions->subjectaltname;
428
                    }
429
                }
430
                if ($capath->certdata->extensions->policies) {
431
                    $certdesc .= '<li>'.$this->certFields['policies'].' '.$capath->certdata->extensions->policies;
432
                }
433
                if ($capath->certdata->extensions->crldistributionpoints) {
434
                    $certdesc .= '<li>'.$this->certFields['crldistributionpoints'].' '.$capath->certdata->extensions->crldistributionpoints;
435
                }
436
                if ($capath->certdata->extensions->authorityinfoaccess) {
437
                    $certdesc .= '<li>'.$this->certFields['authorityinfoaccess'].' '.$capath->certdata->extensions->authorityinfoaccess;
438
                }
439
                            
440
                $certdesc .= '</ul>';
441
                $more .= '<span class="morecontent"><span>'.$certdesc.$protocoldesc.
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $protocoldesc seems to be never defined.
Loading history...
442
                        '</span>&nbsp;&nbsp;<a href="" class="morelink">'._("more").'&raquo;</a></span></td></tr>';
443
            } else {
444
                $certdesc = '<br>';
445
            }
446
            $capathtest[] = '<div>'.($capath->message!='' ? $capath->message : _('Test failed')).'</div>'.$more;
447
            $capathtest[] = '</td>
448
</tr>
449
</table>';
450
            $capathtest[] = '</li></ul>';
451
        }
452
        $this->allCApathFailed = $allfailed;
453
        return $capathtest;
454
    }
455
456
    private function collectClients()
457
    {
458
        $clientstest = [];
459
        foreach ($this->allReachabilityResults['clients'] as $clients) {
460
            if ($clients->result == RADIUSTests::RETVAL_SKIPPED) {
461
                continue;
462
            }
463
            $hostindex = $clients->hostindex; 
464
            $clientstest[] = '<p><strong>'.$this->hostMap[$clients->IP].'</strong></p>';
465
            $clientstest[] = "<span id='clientresults$hostindex'>";
466
            $clientstest[] = '<p></p>';
467
            if ($this->globalLevelDynamic != \core\common\Entity::L_ERROR) {
468
                if (property_exists($clients, 'ca')) {
469
                    $clientstest[] = '<ol>';
470
                    foreach ($clients->ca as $ca) {                     
471
                        $srefused = 0;
472
                        $cliinfo = '';
473
                        $cliinfo .= '<li>'._('Client certificate').' <b>'.$ca->clientcertinfo->from.
474
                                    '</b>'.', '.$ca->clientcertinfo->message .
475
                                    '<br> (CA: '.$ca->clientcertinfo->issuer.')<ul>';
476
                        foreach ($ca->certificate as $certificate) {
477
                            if ($certificate->returncode == \core\diag\RADIUSTests::RETVAL_CONNECTION_REFUSED) {
478
                                $srefused = 1;
479
                            }
480
                        }
481
                        if ($srefused == 0) {
482
                            foreach ($ca->certificate as $certificate) {                           
483
                                $cliinfo .= '<li><i>'.$certificate->message. 
484
                                            ', '._("expected result: ").$this->states[$certificate->expected].'</i>';
485
                                $cliinfo .= '<ul style="list-style-type: none;">';
486
                                if (property_exists($certificate, 'finalerror') && $certificate->finalerror == 2) {
487
                                        $cliinfo .= '<li>'._('this test was skipped - no appropriate client certificate').'</li></ul>';
488
                                        continue;
489
                                }
490
                                $level = $certificate->returncode;
491
                                if ($level < 0) {
492
                                    $level = \core\common\Entity::L_ERROR;
493
                                }
494
                                $add = '';
495
                                if ($certificate->expected == 'PASS') {
496
                                    if ($certificate->connected == 1) {
497
                                        $state = _("Server accepted this client certificate");
498
                                    } else {
499
                                        if (property_exists($certificate, 'reason') && $certificate->reason == \core\diag\RADIUSTests::CERTPROB_UNKNOWN_CA) {
500
                                            $add = '<br>'._('You should update your list of accredited CAs').
501
                                                            ' <a href=\"'.\config\Diagnostics::RADIUSTESTS['accreditedCAsURL'].'\">'.
502
                                                            _('Get it from here.').'</a>';
503
                                        }
504
                                        $state = _('Server did not accept this client certificate - reason').': '.
505
                                                    $certificate->resultcomment;
506
                                    }
507
                                } else {
508
                                    if ($certificate->connected == 1) {
509
                                        $level = \core\common\Entity::L_WARN;
510
                                        $state = _('Server accepted this client certificate, but should not have');
511
                                    } else {
512
                                        $level = \core\common\Entity::L_OK;
513
                                        $state = _('Server did not accept this client certificate').': '.$certificate->resultcomment;
514
                                    }
515
                                }
516
                                $cliinfo .= '<li><table><tbody><tr><td class="icon_td"><img class="icon" src="'.$this->stateIcons[$level].'" style="width: 24px;"></td><td>'.$state;
517
                                $cliinfo .= ' ('.sprintf(_('elapsed time: %sms.'), $certificate->time_millisec).'&nbsp;) '.$add.'</td></tr>';
518
                                $cliinfo .= '</tbody></table></ul></li>';
519
                                if (property_exists($certificate, 'finalerror')) {
520
                                    if ($certificate->finalerror == 1) {
521
                                        $cliinfo .= '<li>'._('Rest of tests for this CA skipped').'</li>';
522
                                    }
523
                                }
524
                            }
525
                            $cliinfo .= '</ul>';
526
                        }
527
                                    
528
                        if ($srefused > 0) {
529
                            $cliinfo = _('Connection refused');
530
                            $clientstest[] = "<table><tr><td class='icon_td' id='srcclient".$hostindex."_img'><img src='".$this->stateIcons[\core\common\Entity::L_ERROR]."'></td>".
531
                                        "<td id='srcclient$hostindex'><p>$cliinfo</p></td></tr></table>";
532
                        } else {
533
                            $clientstest[] = "<p>$cliinfo</p>";
534
                        }
535
                    }
536
                    
537
                } else {
538
                    $cliinfo = _('Test failed');
539
                    $clientstest[] = "<table><tr><td class='icon_td' id='srcclient".$hostindex."_img'><img src='".
540
                                    $this->stateIcons[\core\common\Entity::L_WARN]."'></td>" .
541
                                    "<td id='srcclient$hostindex'>$cliinfo</td></tr></table>";
542
                }
543
            } else {
544
                $clientstest[] = '<ul style="list-style-type: none;" class="clientsresult"><li>';
545
                $clientstest[] = "<table id='clientsresults$hostindex'  style='width:100%'>
546
<tr>
547
<td class='icon_td'><img src='";
548
                $clientstest[] = $this->stateIcons[\core\common\Entity::L_ERROR]."' id='srcclients".$hostindex."_img'></td>
549
<td id='srcclient$hostindex'>";
550
                $clientstest[] = _("These tests were skipped because of previous errors.").'</td></tr></table></ul>';
551
            }
552
            $clientstest[] = '</ol><p></p>';
553
        }
554
        return $clientstest;
555
    }
556
    
557
    public function printDynamic()
558
    {
559
        $out = [];
560
        $out[] = "<div id='dynamic_tests'><fieldset class='option_container'>
561
            <legend><strong>"._("DYNAMIC connectivity tests")."</strong></legend>";
562
        if (count($this->rfc7585suite->NAPTR_hostname_records) > 0) {    
563
            $capathtest = $this->collectCAPath();
564
            $clientstest = $this->collectClients();
565
            $out[] = '<div style="align:right;">';            
566
            $out[] = '<div style="align:right; display: ';
567
            if ($this->globalLevelDynamic == \core\common\Entity::L_OK && !$this->areFailed) {
568
                $out[] = 'none';
569
            }
570
            $out[] = ';" id="dynamic_result_fail"><b>'._("Some errors were found during the tests, see below").'</b></div>';
571
            $out[] = '<div style="align:right; display: ';
572
            if ($this->globalLevelDynamic != \core\common\Entity::L_OK || $this->areFailed) {
573
                $out[] = 'none';
574
            }
575
            $out[] = '" id="dynamic_result_pass"><b>'.
576
                                _("All tests passed, congratulations!").'</b></div>';
577
            if (!$this->allCApathFailed) {
578
                $out[] = '<div style="align:left;"><a href="" class="moreall"><i>'._('Show detailed information for all tests').'&raquo;</i></a></div>';
579
            }
580
            $out[] = join('', $capathtest);
581
            if (!empty($clientstest)) {
582
                $out[] = '<span id="clientstest" style="display: ;"><p><hr><b>'._('Checking if certificates from CAs are accepted...').'</b><p>'._('A few client certificates will be tested to check if servers are resistant to some certificate problems.').'<p>';
583
                $out[] = join('', $clientstest);
584
                $out[] = '</span>';
585
            }
586
            $out[] = '</div>';
587
        }
588
        $out[] = "</fieldset></div></div>";
589
        return join('', $out);
590
    }
591
    
592
}
593