Passed
Push — master ( 17bffe...10bee5 )
by Stefan
06:13
created

Telepath::CATInternalTests()   B

Complexity

Conditions 9
Paths 36

Size

Total Lines 57
Code Lines 35

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 57
c 0
b 0
f 0
rs 7.0745
cc 9
eloc 35
nc 36
nop 0

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
3
/*
4
 * ******************************************************************************
5
 * Copyright 2011-2017 DANTE Ltd. and GÉANT on behalf of the GN3, GN3+, GN4-1 
6
 * and GN4-2 consortia
7
 *
8
 * License: see the web/copyright.php file in the file structure
9
 * ******************************************************************************
10
 */
11
12
namespace core\diag;
13
14
use \Exception;
15
16
require_once(dirname(dirname(__DIR__)) . "/config/_config.php");
17
18
/**
19
 * The overall coordination class that runs all kinds of tests to find out where
20
 * and what is wrong. Operates on the realm of a user. Can do more magic if it
21
 * also knows which federation the user is currently positioned in, or even 
22
 * which exact hotspot to analyse.
23
 */
24
class Telepath extends AbstractTest {
25
26
    private $realm;
27
    private $visitedFlr;
28
    private $visitedHotspot;
29
    private $catProfile;
30
    private $dbIdP;
31
    private $idPFederation;
32
    private $testsuite;
33
34
    /**
35
     * prime the Telepath with info it needs to know to successfully meditate over the problem
36
     * @param string $realm the realm of the user
37
     * @param string|null $visitedFlr which NRO is the user visiting
38
     * @param string|null $visitedHotspot external DB ID of the hotspot he visited
39
     */
40
    public function __construct(string $realm, $visitedFlr = NULL, $visitedHotspot = NULL) {
41
        // Telepath is the first one in a chain, no previous inputs allowed
42
        if (isset($_SESSION) && isset($_SESSION["SUSPECTS"])) {
43
            unset($_SESSION["SUSPECTS"]);
44
        }
45
        if (isset($_SESSION) && isset($_SESSION["EVIDENCE"])) {
46
            unset($_SESSION["EVIDENCE"]);
47
        }
48
        // now fill with default values
49
        parent::__construct();
50
        $this->realm = $realm;
51
        $this->visitedFlr = $visitedFlr;
52
        $this->visitedHotspot = $visitedHotspot;
53
        $links = \core\Federation::determineIdPIdByRealm($realm);
54
        $this->catProfile = $links["CAT"];
55
        $this->dbIdP = $links["EXTERNAL"];
56
        $this->idPFederation = $links["FEDERATION"];
57
        // this is NULL if the realm is not known in either DB
58
        // if so, let's try a regex to extract the ccTLD if any
59
        $matches = [];
60
        if ($this->idPFederation === NULL && preg_match("/\.(..)$/", $realm, $matches)) {
61
            $this->idPFederation = strtoupper($matches[1]);
62
        }
63
        $this->loggerInstance->debug(4, "XYZ: IdP-side NRO is " . $this->idPFederation . "\n");
64
    }
65
66
    /* The eduroam OT monitoring has the following return codes:
67
     * 
68
69
      Status codes
70
71
      0 - O.K.
72
      -1 - Accept O.K. Reject No
73
      -2 - Reject O.K. Accept No
74
      -3 - Accept No Reject No
75
      -9 - system error
76
      -10 - Accept O.K. Reject timeou
77
      -11 - Accept O.K. Reject no EAP
78
      -20 - Reject O.K. Accept timeou
79
      -21 - Reject O.K. Accept no EAP
80
      -31 - Accept No  Reject timeou
81
      -32 - Accept Timeout Reject no
82
      -33 - Accept Timeout Reject timeou
83
      -35 - Accept No Reject no EAP
84
      -36 - Reject No Accept no EAP
85
      -37 - Reject No EAP Accept no EAP
86
      -40 - UDP test error
87
88
     */
89
90
    /**
91
     * ask the monitoring API about the things it knows
92
     * @param string $type which type of test to execute
93
     * @param string $param1 test-specific parameter number 1, if any
94
     * @param string $param2 test-specific parameter number 2, if any
95
     * @return array
96
     */
97
    private function genericAPIStatus($type, $param1 = NULL, $param2 = NULL) {
98
        $endpoints = [
99
            'tlr_test' => "https://monitor.eduroam.org/mapi/index.php?type=tlr_test&tlr=$param1",
100
            'federation_via_tlr' => "https://monitor.eduroam.org/mapi/index.php?type=federation_via_tlr&federation=$param1",
101
            'flrs_test' => "https://monitor.eduroam.org/mapi/index.php?type=flrs_test&federation=$param1",
102
            'flr_by_federation' => "https://monitor.eduroam.org/mapi/index.php?type=flr_by_federation&federation=$param2&with=$param1",
103
        ];
104
        $ignore = [
105
            'tlr_test' => 'tlr',
106
            'federation_via_tlr' => 'fed',
107
            'flrs_test' => 'fed',
108
            'flr_by_federation' => 'fed',
109
        ];
110
        $this->loggerInstance->debug(4, "Doing Monitoring API check with $endpoints[$type]\n");
111
        $jsonResult = \core\common\OutsideComm::downloadFile($endpoints[$type]);
112
        $this->loggerInstance->debug(4, "Monitoring API Result: $jsonResult\n");
113
        $decoded = json_decode($jsonResult, TRUE);
114
        $retval = [];
115
        $retval["RAW"] = $decoded;
116
        $atLeastOneFunctional = FALSE;
117
        $allFunctional = TRUE;
118
        if (!isset($decoded[$type]) || isset($decoded['ERROR'])) {
119
            $retval["STATUS"] = AbstractTest::STATUS_MONITORINGFAIL;
120
            return $retval;
121
        }
122
        foreach ($decoded[$type] as $instance => $resultset) {
123
            if ($instance == $ignore[$type]) {
124
                // don't care
125
                continue;
126
            }
127
            // TLR test has statuscode on this level, otherwise need to recurse
128
            // one more level
129
            switch ($type) {
130
                case "tlr_test":
131 View Code Duplication
                    switch ($resultset['status_code']) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
132
                        case 0:
133
                            $atLeastOneFunctional = TRUE;
134
                            break;
135
                        case 9: // monitoring itself has an error, no effect on our verdict
136
                        case -1: // Reject test fails, but we diagnose supposed-working connection, so no effect on our verdict
137
                        case -10: // same as previous
138
                        case -11: // same as previous
139
                            break;
140
                        default:
141
                            $allFunctional = FALSE;
142
                    }
143
                    break;
144
                default:
145
                    foreach ($resultset as $particularInstance => $particularResultset) {
146 View Code Duplication
                        switch ($particularResultset['status_code']) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
147
                            case 0:
148
                                $atLeastOneFunctional = TRUE;
149
                                break;
150
                            case 9: // monitoring itself has an error, no effect on our verdict
151
                            case -1: // Reject test fails, but we diagnose supposed-working connection, so no effect on our verdict
152
                            case -10: // same as previous
153
                            case -11: // same as previous
154
                                break;
155
                            default:
156
                                $allFunctional = FALSE;
157
                        }
158
                    }
159
            }
160
        }
161
162
        if ($allFunctional) {
163
            $retval["STATUS"] = AbstractTest::STATUS_GOOD;
164
            return $retval;
165
        }
166
        if ($atLeastOneFunctional) {
167
            $retval["STATUS"] = AbstractTest::STATUS_PARTIAL;
168
            return $retval;
169
        }
170
        $retval["STATUS"] = AbstractTest::STATUS_DOWN;
171
        return $retval;
172
    }
173
174
    /**
175
     * Are the ETLR servers in order?
176
     * @return array
177
     */
178
    private function checkEtlrStatus() {
179
        // TODO: we always check the European TLRs even though the connection in question might go via others and/or this one
180
        // needs a table to determine what goes where :-(
181
        return $this->genericAPIStatus("tlr_test", "TLR_EU");
182
    }
183
184
    /**
185
     * Is the uplink between an NRO server and the ETLRs in order?
186
     * @param string $fed
187
     * @return array
188
     */
189
    private function checkFedEtlrUplink($fed) {
190
        // TODO: we always check the European TLRs even though the connection in question might go via others and/or this one
191
        // needs a table to determine what goes where :-(
192
        return $this->genericAPIStatus("federation_via_tlr", $fed);
193
    }
194
195
    /**
196
     * Is the NRO server itself in order?
197
     * @param string $fed
198
     * @return array
199
     */
200
    private function checkFlrServerStatus($fed) {
201
        // TODO: we always check the European TLRs even though the connection in question might go via others and/or this one
202
        // needs a table to determine what goes where :-(
203
        return $this->genericAPIStatus("flrs_test", $fed);
204
    }
205
206
    /**
207
     * Does authentication traffic flow between a given source and destination NRO?
208
     * @return array
209
     */
210
    private function checkNROFlow() {
211
        return $this->genericAPIStatus("flr_by_federation", $this->idPFederation, $this->visitedFlr);
212
    }
213
214
    /**
215
     * Runs the CAT-internal diagnostics tests. Determines the state of the 
216
     * realm (and indirectly that of the links and statuses of involved proxies
217
     * and returns a judgment whether external Monitoring API tests are warranted
218
     * or not
219
     * @return boolean TRUE if external tests have to be run
220
     */
221
    private function CATInternalTests() {
222
        // we are expecting to get a REJECT from all runs, because that means the packet got through to the IdP.
223
        // (the ETLR sometimes does a "Reject instead of Ignore" but that is filtered out and changed into a timeout
224
        // by the test suite automatically, so it does not disturb the measurement)
225
        // If that's true, we can exclude two sources of problems (both proxy levels). Hooray!
226
        $allAreConversationReject = TRUE;
227
        $atLeastOneConversationReject = FALSE;
228
229
        foreach (CONFIG_DIAGNOSTICS['RADIUSTESTS']['UDP-hosts'] as $probeindex => $probe) {
230
            $reachCheck = $this->testsuite->udpReachability($probeindex);
231
            if ($reachCheck != RADIUSTests::RETVAL_CONVERSATION_REJECT) {
232
                $allAreConversationReject = FALSE;
233
            } else {
234
                $atLeastOneConversationReject = TRUE;
235
            }
236
237
            $this->additionalFindings[AbstractTest::INFRA_ETLR][] = ["DETAIL" => $this->testsuite->consolidateUdpResult($probeindex)];
238
            $this->additionalFindings[AbstractTest::INFRA_NRO_IDP][] = ["DETAIL" => $this->testsuite->consolidateUdpResult($probeindex)];
239
            $this->additionalFindings[AbstractTest::INFRA_IDP_RADIUS][] = ["DETAIL" => $this->testsuite->consolidateUdpResult($probeindex)];
240
        }
241
242
        if ($allAreConversationReject) {
243
            $this->additionalFindings[AbstractTest::INFRA_ETLR][] = ["CONNCHECK" => RADIUSTests::RETVAL_CONVERSATION_REJECT];
244
            $this->additionalFindings[AbstractTest::INFRA_NRO_IDP][] = ["CONNCHECK" => RADIUSTests::RETVAL_CONVERSATION_REJECT];
245
            $this->additionalFindings[AbstractTest::INFRA_IDP_RADIUS][] = ["CONNCHECK" => RADIUSTests::RETVAL_CONVERSATION_REJECT];
246
            $this->additionalFindings[AbstractTest::INFRA_LINK_ETLR_NRO_IDP][] = ["LINKCHECK" => RADIUSTests::L_OK];
247
            // we have actually reached an IdP, so all links are good, and the
248
            // realm is routable in eduroam. So even if it exists in neither DB
249
            // we can exclude the NONEXISTENTREALM case
250
            unset($this->possibleFailureReasons[AbstractTest::INFRA_ETLR]);
251
            unset($this->possibleFailureReasons[AbstractTest::INFRA_NRO_IDP]);
252
            unset($this->possibleFailureReasons[AbstractTest::INFRA_LINK_ETLR_NRO_IDP]);
253
            unset($this->possibleFailureReasons[AbstractTest::INFRA_NONEXISTENTREALM]);
254
        }
255
256
        if ($atLeastOneConversationReject) {
257
            // at least we can be sure it exists
258
            unset($this->possibleFailureReasons[AbstractTest::INFRA_NONEXISTENTREALM]);
259
            // It could still be an IdP RADIUS problem in that some cert oddities 
260
            // in combination with the device lead to a broken auth
261
            // if there is nothing beyond the "REMARK" level, then it's not an IdP problem
262
            // otherwise, add the corresponding warnings and errors to $additionalFindings
263
            switch ($this->additionalFindings[AbstractTest::INFRA_IDP_RADIUS][0]['DETAIL']['level']) {
264
                case RADIUSTests::L_OK:
265
                case RADIUSTests::L_REMARK:
266
                    // both are fine - the IdP is working and the user problem
267
                    // is not on the IdP RADIUS level
268
                    $this->additionalFindings[AbstractTest::INFRA_IDP_RADIUS][] = ["ODDITYLEVEL" => $this->additionalFindings[AbstractTest::INFRA_IDP_RADIUS][0]['DETAIL']['level']];
269
                    unset($this->possibleFailureReasons[AbstractTest::INFRA_IDP_RADIUS]);
270
                    break;
271
                case RADIUSTests::L_WARN:
272
                    $this->additionalFindings[AbstractTest::INFRA_IDP_RADIUS][] = ["ODDITYLEVEL" => RADIUSTests::L_WARN];
273
                    $this->possibleFailureReasons[AbstractTest::INFRA_IDP_RADIUS] = 0.3; // possibly we found the culprit - if RADIUS server is misconfigured AND user is on a device which reacts picky about exactly this oddity.
274
                    break;
275
                case RADIUSTests::L_ERROR:
276
                    $this->additionalFindings[AbstractTest::INFRA_IDP_RADIUS][] = ["ODDITYLEVEL" => RADIUSTests::L_ERROR];
277
                    $this->possibleFailureReasons[AbstractTest::INFRA_IDP_RADIUS] = 0.8; // errors are never good, so we can be reasonably sure we've hit the spot!
278
            }
279
        }
280
    }
281
282
    /**
283
     * Does the main meditation job
284
     * @return array the findings
285
     */
286
    public function magic() {
287
288
        // simple things first: do we know anything about the realm, either
289
        // because it's a CAT participant or because it's in the eduroam DB?
290
        // if so, we can exclude the INFRA_NONEXISTENTREALM cause
291
292
        $this->additionalFindings[AbstractTest::INFRA_NONEXISTENTREALM]['DATABASE_STATUS'] = ["ID1" => $this->catProfile, "ID2" => $this->dbIdP];
293
294
        if ($this->catProfile != \core\Federation::UNKNOWN_IDP || $this->dbIdP != \core\Federation::UNKNOWN_IDP) {
295
            unset($this->possibleFailureReasons[AbstractTest::INFRA_NONEXISTENTREALM]);
296
        }
297
298
        // let's do the least amount of testing needed:
299
        // - The CAT reachability test already covers ELTRs, IdP NRO level and the IdP itself.
300
        //   if the realm maps to a CAT IdP, we can run the more thorough tests; otherwise just
301
        //   the normal shallow ones
302
303
        if ($this->catProfile > 0) {
304
            $profileObject = \core\ProfileFactory::instantiate($this->catProfile);
305
            $readinessLevel = $profileObject->readinessLevel();
306
307
            switch ($readinessLevel) {
308
                case \core\AbstractProfile::READINESS_LEVEL_SHOWTIME:
309
                case \core\AbstractProfile::READINESS_LEVEL_SUFFICIENTCONFIG:
310
                    $this->additionalFindings[AbstractTest::INFRA_IDP_RADIUS][] = ["Profile" => $profileObject->identifier];
311
                    $this->testsuite = new RADIUSTests($this->realm, $profileObject->getRealmCheckOuterUsername(), $profileObject->getEapMethodsinOrderOfPreference(1), $profileObject->getCollapsedAttributes()['eap:server_name'], $profileObject->getCollapsedAttributes()["eap:ca_file"]);
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment if this fall-through is intended.
Loading history...
312
313
                case \core\AbstractProfile::READINESS_LEVEL_NOTREADY:
314
                    $this->additionalFindings[AbstractTest::INFRA_IDP_RADIUS][] = ["Profile" => "UNCONCLUSIVE"];
315
                    $this->testsuite = new RADIUSTests($this->realm, "anonymous@" . $this->realm);
316
                    break;
317
                default:
318
            }
319
        } else {
320
            $this->testsuite = new RADIUSTests($this->realm, "anonymous@" . $this->realm);
321
        }
322
323
        // these are the normal "realm check" tests covering ETLR, LINK_NRO_IDP, NRO, IDP_RADIUS
324
        $this->CATInternalTests();
325
        // - if the test does NOT go through, we need to find out which of the three is guilty
326
        // - then, the international "via ETLR" check can be used to find out if the IdP alone
327
        //   is guilty. If that one fails, the direct monitoring of servers and ETLRs themselves
328
        //   closes the loop.
329
        // let's see if the ETLRs are up
330 View Code Duplication
        if (array_key_exists(AbstractTest::INFRA_ETLR, $this->possibleFailureReasons)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
331
332
            $etlrStatus = $this->checkEtlrStatus();
333
            $this->additionalFindings[AbstractTest::INFRA_ETLR][] = $etlrStatus;
334
            switch ($etlrStatus["STATUS"]) {
335
                case AbstractTest::STATUS_GOOD:
336
                    unset($this->possibleFailureReasons[AbstractTest::INFRA_ETLR]);
337
                    break;
338
                case AbstractTest::STATUS_PARTIAL:
339
                case AbstractTest::STATUS_MONITORINGFAIL:
340
                    // one of the ETLRs is down, or there is a failure in the monitoring system? 
341
                    // This probably doesn't impact the user unless he's unlucky and has his session fall into failover.
342
                    // keep ETLR as a possible problem with original probability
343
                    break;
344
                case AbstractTest::STATUS_DOWN:
345
                    // Oh! Well if it is not international roaming, that still doesn't have an effect /in this case/. 
346
                    if ($this->idPFederation == $this->visitedFlr) {
347
                        unset($this->possibleFailureReasons[AbstractTest::INFRA_ETLR]);
348
                        break;
349
                    }
350
                    // But it is about int'l roaming, and we are spot on here.
351
                    // Raise probability by much (even monitoring is sometimes wrong, or a few minutes behind reality)
352
                    $this->possibleFailureReasons[AbstractTest::INFRA_ETLR] = 0.95;
353
            }
354
        }
355
356
        // then let's check the IdP's FLR, if we know the IdP federation at all
357
        if ($this->idPFederation != NULL) {
0 ignored issues
show
Bug introduced by
It seems like you are loosely comparing $this->idPFederation of type mixed|string against null; this is ambiguous if the string can be empty. Consider using a strict comparison !== instead.
Loading history...
358
            if (array_key_exists(AbstractTest::INFRA_NRO_IDP, $this->possibleFailureReasons)) {
359
                // first the direct connectivity to the server
360
                $flrServerStatus = $this->checkFlrServerStatus($this->idPFederation);
361
                $this->additionalFindings[AbstractTest::INFRA_NRO_IDP][] = $flrServerStatus;
362 View Code Duplication
                switch ($flrServerStatus["STATUS"]) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
363
                    case AbstractTest::STATUS_GOOD:
364
                        unset($this->possibleFailureReasons[AbstractTest::INFRA_NRO_IDP]);
365
                        break;
366
                    case AbstractTest::STATUS_PARTIAL:
367
                        // a subset of the FLRs is down? This probably doesn't impact the user unless he's unlucky and has his session fall into failover.
368
                        // keep FLR as a possible problem with original probability
369
                        break;
370
                    case AbstractTest::STATUS_DOWN:
371
                        // Raise probability by much (even monitoring is sometimes wrong, or a few minutes behind reality)
372
                        $this->possibleFailureReasons[AbstractTest::INFRA_NRO_IDP] = 0.95;
373
                }
374
            }
375
376
            // now let's theck the link
377 View Code Duplication
            if (array_key_exists(AbstractTest::INFRA_LINK_ETLR_NRO_IDP, $this->possibleFailureReasons)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
378
                $flrUplinkStatus = $this->checkFedEtlrUplink($this->idPFederation);
379
                $this->additionalFindings[AbstractTest::INFRA_NRO_IDP][] = $flrUplinkStatus;
380
                switch ($flrUplinkStatus["STATUS"]) {
381
                    case AbstractTest::STATUS_GOOD:
382
                        unset($this->possibleFailureReasons[AbstractTest::INFRA_NRO_IDP]);
383
                        unset($this->possibleFailureReasons[AbstractTest::INFRA_LINK_ETLR_NRO_IDP]);
384
                        break;
385
                    case AbstractTest::STATUS_PARTIAL:
386
                        // a subset of the FLRs is down? This probably doesn't impact the user unless he's unlucky and has his session fall into failover.
387
                        // keep FLR as a possible problem with original probability
388
                        break;
389
                    case AbstractTest::STATUS_DOWN:
390
                        // Raise probability by much (even monitoring is sometimes wrong, or a few minutes behind reality)
391
                        // if earlier test found the server itself to be the problem, keep it, otherwise put the blame on the link
392
                        if ($this->possibleFailureReasons[AbstractTest::INFRA_NRO_IDP] != 0.95) {
393
                            $this->possibleFailureReasons[AbstractTest::INFRA_LINK_ETLR_NRO_IDP] = 0.95;
394
                        }
395
                }
396
            }
397
        }
398
        // now, if we know the country the user is currently in, let's see 
399
        // if the NRO SP-side is up
400
        if ($this->visitedFlr !== NULL) {
401
            $visitedFlrStatus = $this->checkFlrServerStatus($this->visitedFlr);
402
            $this->additionalFindings[AbstractTest::INFRA_NRO_SP][] = $visitedFlrStatus;
403
            // direct query to server
404 View Code Duplication
            switch ($visitedFlrStatus["STATUS"]) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
405
                case AbstractTest::STATUS_GOOD:
406
                    unset($this->possibleFailureReasons[AbstractTest::INFRA_NRO_SP]);
407
                    break;
408
                case AbstractTest::STATUS_PARTIAL:
409
                    // a subset of the FLRs is down? This probably doesn't impact the user unless he's unlucky and has his session fall into failover.
410
                    // keep FLR as a possible problem with original probability
411
                    break;
412
                case AbstractTest::STATUS_DOWN:
413
                    // Raise probability by much (even monitoring is sometimes wrong, or a few minutes behind reality)
414
                    $this->possibleFailureReasons[AbstractTest::INFRA_NRO_SP] = 0.95;
415
            }
416
            // and again its uplink to the ETLR
417
            $visitedFlrUplinkStatus = $this->checkFedEtlrUplink($this->visitedFlr);
418
            $this->additionalFindings[AbstractTest::INFRA_NRO_SP][] = $visitedFlrUplinkStatus;
419
            switch ($visitedFlrUplinkStatus["STATUS"]) {
420
                case AbstractTest::STATUS_GOOD:
421
                    unset($this->possibleFailureReasons[AbstractTest::INFRA_NRO_SP]);
422
                    unset($this->possibleFailureReasons[AbstractTest::INFRA_LINK_ETLR_NRO_SP]);
423
                    break;
424
                case AbstractTest::STATUS_PARTIAL:
425
                    // a subset of the FLRs is down? This probably doesn't impact the user unless he's unlucky and has his session fall into failover.
426
                    // keep FLR as a possible problem with original probability
427
                    break;
428
                case AbstractTest::STATUS_DOWN:
429
                    // Raise probability by much (even monitoring is sometimes wrong, or a few minutes behind reality)
430
                    // if earlier test found the server itself to be the problem, keep it, otherwise put the blame on the link
431
                    if ($this->possibleFailureReasons[AbstractTest::INFRA_NRO_SP] != 0.95) {
432
                        $this->possibleFailureReasons[AbstractTest::INFRA_LINK_ETLR_NRO_SP] = 0.95;
433
                    }
434
            }
435
        }
436
        // the last thing we can do (but it's a bit redundant): check the country-to-country link
437
        // it's only needed if all three and their links are up, but we want to exclude funny routing blacklists 
438
        // which occur only in the *combination* of source and dest
439
        // if there is an issue at that point, blame the SP: once a request
440
        // would have reached the ETLRs, things would be all good (assuming
441
        // perfection on the ETLRs here!). So the SP has a wrong config.
442
        if ($this->idPFederation !== NULL &&
443
                $this->visitedFlr !== NULL &&
444
                !array_key_exists(AbstractTest::INFRA_ETLR, $this->possibleFailureReasons) &&
445
                !array_key_exists(AbstractTest::INFRA_LINK_ETLR_NRO_IDP, $this->possibleFailureReasons) &&
446
                !array_key_exists(AbstractTest::INFRA_NRO_IDP, $this->possibleFailureReasons) &&
447
                !array_key_exists(AbstractTest::INFRA_LINK_ETLR_NRO_SP, $this->possibleFailureReasons) &&
448
                !array_key_exists(AbstractTest::INFRA_NRO_SP, $this->possibleFailureReasons)
449
        ) {
450
            $countryToCountryStatus = $this->checkNROFlow();
451
            $this->additionalFindings[AbstractTest::INFRA_NRO_SP][] = $countryToCountryStatus;
452
            $this->additionalFindings[AbstractTest::INFRA_ETLR][] = $countryToCountryStatus;
453
            $this->additionalFindings[AbstractTest::INFRA_NRO_IDP][] = $countryToCountryStatus;
454 View Code Duplication
            switch ($countryToCountryStatus["STATUS"]) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
455
                case AbstractTest::STATUS_GOOD:
456
                    // all routes work
457
                    break;
458
                case AbstractTest::STATUS_PARTIAL:
459
                // at least one, or even all have a routing problem
460
                case AbstractTest::STATUS_DOWN:
461
                    // that's rather telling.
462
                    $this->possibleFailureReasons[AbstractTest::INFRA_NRO_SP] = 0.95;
463
            }
464
        }
465
466
        $this->normaliseResultSet();
467
468
        $_SESSION["SUSPECTS"] = $this->possibleFailureReasons;
469
        $_SESSION["EVIDENCE"] = $this->additionalFindings;
470
        return ["SUSPECTS" => $this->possibleFailureReasons, "EVIDENCE" => $this->additionalFindings];
471
    }
472
473
}
474