Passed
Push — master ( 54cc30...cc7767 )
by Maja
08:24
created

EAP::isClientCertOptional()   B

Complexity

Conditions 9
Paths 9

Size

Total Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
nc 9
nop 0
dl 0
loc 14
rs 8.0555
c 0
b 0
f 0
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
/**
13
 * This file contains the EAP class and some constants for EAP types.
14
 *
15
 * @author Stefan Winter <[email protected]>
16
 * @author Tomasz Wolniewicz <[email protected]>
17
 *
18
 * @package Developer
19
 * 
20
 */
21
22
namespace core\common;
23
24
use \Exception;
25
26
/**
27
 * Convenience functions for EAP types
28
 *
29
 * @author Stefan Winter <[email protected]>
30
 * @author Tomasz Wolniewicz <[email protected]>
31
 *
32
 * @license see LICENSE file in root directory
33
 *
34
 * @package Developer
35
 */
36
class EAP {
37
38
    /**
39
     * some EAP-related constants.
40
     */
41
    const PEAP = 25;
42
    const MSCHAP2 = 26;
43
    const TTLS = 21;
44
    const TLS = 13;
45
    const NONE = 0;
46
    const GTC = 6;
47
    const FAST = 43;
48
    const PWD = 52;
49
    const NE_PAP = 1;
50
    const NE_MSCHAP = 2;
51
    const NE_MSCHAP2 = 3;
52
    const NE_SILVERBULLET = 999;
53
    const INTEGER_TTLS_PAP = 1;
54
    const INTEGER_PEAP_MSCHAPv2 = 2;
55
    const INTEGER_TLS = 3;
56
    const INTEGER_FAST_GTC = 4;
57
    const INTEGER_TTLS_GTC = 5;
58
    const INTEGER_TTLS_MSCHAP2 = 6;
59
    const INTEGER_EAP_PWD = 7;
60
    const INTEGER_SILVERBULLET = 8;
61
62
// PHP7 allows to define constants with arrays as value. Hooray! This makes
63
// lots of public static members of the EAP class obsolete
64
65
    /**
66
     * PEAP-MSCHAPv2: Outer EAP Type = 25, Inner EAP Type = 26
67
     */
68
    const EAPTYPE_PEAP_MSCHAP2 = ["OUTER" => EAP::PEAP, "INNER" => EAP::MSCHAP2];
69
70
    /**
71
     * EAP-TLS: Outer EAP Type = 13, no inner EAP
72
     */
73
    const EAPTYPE_TLS = ["OUTER" => EAP::TLS, "INNER" => EAP::NONE];
74
75
    /**
76
     * EAP-TLS: Outer EAP Type = 13, no inner EAP
77
     */
78
    const EAPTYPE_SILVERBULLET = ["OUTER" => EAP::TLS, "INNER" => EAP::NE_SILVERBULLET];
79
80
    /**
81
     * TTLS-PAP: Outer EAP type = 21, no inner EAP, inner non-EAP = 1
82
     */
83
    const EAPTYPE_TTLS_PAP = ["OUTER" => EAP::TTLS, "INNER" => EAP::NONE];
84
85
    /**
86
     * TTLS-MSCHAP-v2: Outer EAP type = 21, no inner EAP, inner non-EAP = 3
87
     */
88
    const EAPTYPE_TTLS_MSCHAP2 = ["OUTER" => EAP::TTLS, "INNER" => EAP::MSCHAP2];
89
90
    /**
91
     * TTLS-GTC: Outer EAP type = 21, Inner EAP Type = 6
92
     */
93
    const EAPTYPE_TTLS_GTC = ["OUTER" => EAP::TTLS, "INNER" => EAP::GTC];
94
95
    /**
96
     * EAP-FAST (GTC): Outer EAP type = 43, Inner EAP Type = 6
97
     */
98
    const EAPTYPE_FAST_GTC = ["OUTER" => EAP::FAST, "INNER" => EAP::GTC];
99
100
    /**
101
     * PWD: Outer EAP type = 52, no inner EAP
102
     */
103
    const EAPTYPE_PWD = ["OUTER" => EAP::PWD, "INNER" => EAP::NONE];
104
105
    /**
106
     * NULL: no outer EAP, no inner EAP
107
     */
108
    const EAPTYPE_NONE = ["OUTER" => EAP::NONE, "INNER" => EAP::NONE];
109
110
    /**
111
     *  ANY: not really an EAP method, but the term to use when needing to express "any EAP method we know"
112
     */
113
    const EAPTYPE_ANY = ["OUTER" => 255, "INNER" => 255];
114
115
    /**
116
     * conversion table between array and integer representations
117
     */
118
    const EAPTYPES_CONVERSION = [
119
        EAP::INTEGER_FAST_GTC => EAP::EAPTYPE_FAST_GTC,
120
        EAP::INTEGER_PEAP_MSCHAPv2 => EAP::EAPTYPE_PEAP_MSCHAP2,
121
        EAP::INTEGER_EAP_PWD => EAP::EAPTYPE_PWD,
122
        EAP::INTEGER_TLS => EAP::EAPTYPE_TLS,
123
        EAP::INTEGER_TTLS_GTC => EAP::EAPTYPE_TTLS_GTC,
124
        EAP::INTEGER_TTLS_MSCHAP2 => EAP::EAPTYPE_TTLS_MSCHAP2,
125
        EAP::INTEGER_TTLS_PAP => EAP::EAPTYPE_TTLS_PAP,
126
        EAP::INTEGER_SILVERBULLET => EAP::EAPTYPE_SILVERBULLET,
127
    ];
128
129
    /**
130
     * The array representation of the EAP type
131
     * @var array
132
     */
133
    private $arrayRep;
134
135
    /**
136
     * The integer representation of the EAP type
137
     * @var int
138
     */
139
    private $intRep;
140
141
    /**
142
     * Instantiates the EAP class for a concrete EAP type. Only call it to 
143
     * instantiate *real* EAP types, i.e. not EAPTYPE::ANY or EAPTYPE::NONE
144
     * 
145
     * @param mixed $eapType the EAP type, either in its integer or array representation
146
     */
147
    public function __construct($eapType) {
148
        if (is_numeric($eapType) && array_key_exists($eapType, EAP::EAPTYPES_CONVERSION)) {
149
            $key = array_keys(EAP::EAPTYPES_CONVERSION, EAP::EAPTYPES_CONVERSION[$eapType]);
150
            $this->intRep = $key[0];
151
            $this->arrayRep = EAP::EAPTYPES_CONVERSION[$this->intRep];
152
            return;
153
        }
154
        if (is_array($eapType)) {
155
            $key = array_search($eapType, EAP::EAPTYPES_CONVERSION);
156
            if ($key !== FALSE) {
157
                // add a type cast to int to make Scrutinizer realise that the key found is always an integer
158
                $this->intRep = (int)$key; // array index is always an integer
159
                $this->arrayRep = EAP::EAPTYPES_CONVERSION[(int)$key];
160
                return;
161
            }
162
        }
163
        throw new Exception("Unable to instantiate the EAP class - the EAP type is bogus.");
164
    }
165
166
    /**
167
     * Is this a password-based EAP method?
168
     * @return boolean
169
     * @throws Exception
170
     */
171
    public function isPasswordRequired() {
172
        switch ($this->intRep) {
173
            case EAP::INTEGER_EAP_PWD:
174
            case EAP::INTEGER_FAST_GTC:
175
            case EAP::INTEGER_PEAP_MSCHAPv2:
176
            case EAP::INTEGER_TTLS_GTC:
177
            case EAP::INTEGER_TTLS_MSCHAP2:
178
            case EAP::INTEGER_TTLS_PAP:
179
                return TRUE;
180
            case EAP::INTEGER_TLS:
181
            case EAP::INTEGER_SILVERBULLET:
182
                return FALSE;
183
            default:
184
                throw new Exception("Unable to determine if the EAP type required a password or not!");
185
        }
186
    }
187
188
    /**
189
     * There could be EAP methods which have an optional need for a password.
190
     * Not aware of any, so this is a simple function :-)
191
     * @return boolean
192
     */
193
    public function isPasswordOptional() {
194
        return FALSE;
195
    }
196
197
    /**
198
     * Is this a certificate-based EAP method?
199
     * @return boolean
200
     * @throws Exception
201
     */
202
    public function isClientCertRequired() {
203
        switch ($this->intRep) {
204
            case EAP::INTEGER_EAP_PWD:
205
            case EAP::INTEGER_FAST_GTC:
206
            case EAP::INTEGER_PEAP_MSCHAPv2:
207
            case EAP::INTEGER_TTLS_GTC:
208
            case EAP::INTEGER_TTLS_MSCHAP2:
209
            case EAP::INTEGER_TTLS_PAP:
210
                return FALSE;
211
            case EAP::INTEGER_TLS:
212
            case EAP::INTEGER_SILVERBULLET:
213
                return TRUE;
214
            default:
215
                throw new Exception("Unable to determine if the EAP type requires client-certificates or not!");
216
        }
217
    }
218
219
    /**
220
     * Does an EAP type optionally allow to send a client certificate?
221
     * @return boolean
222
     * @throws Exception
223
     */
224
    public function isClientCertOptional() {
225
        switch ($this->intRep) {
226
            case EAP::INTEGER_EAP_PWD:
227
            case EAP::INTEGER_TLS:
228
            case EAP::INTEGER_SILVERBULLET:
229
                return FALSE;
230
            case EAP::INTEGER_FAST_GTC:
231
            case EAP::INTEGER_PEAP_MSCHAPv2:
232
            case EAP::INTEGER_TTLS_GTC:
233
            case EAP::INTEGER_TTLS_MSCHAP2:
234
            case EAP::INTEGER_TTLS_PAP:
235
                return TRUE;
236
            default:
237
                throw new Exception("Unable to determine if the EAP type has optional client-certificates or not!");
238
        }
239
    }
240
241
    /**
242
     * Does the EAP type require the specification of trusted CAs to be secure?
243
     * @return boolean
244
     * @throws Exception
245
     */
246
    public function needsServerCACert() {
247
        switch ($this->intRep) {
248
            case EAP::INTEGER_EAP_PWD:
249
                return FALSE;
250
            case EAP::INTEGER_FAST_GTC:
251
            case EAP::INTEGER_PEAP_MSCHAPv2:
252
            case EAP::INTEGER_TTLS_GTC:
253
            case EAP::INTEGER_TTLS_MSCHAP2:
254
            case EAP::INTEGER_TTLS_PAP:
255
            case EAP::INTEGER_TLS:
256
            case EAP::INTEGER_SILVERBULLET:
257
                return TRUE;
258
            default:
259
                throw new Exception("Unable to determine if the EAP type requires a CA trust base for secure functioning or not!");
260
        }
261
    }
262
263
    /**
264
     * Does the EAP type require the specification of a server name to be secure?
265
     * EAP-pwd has one, but it is not really required.
266
     * @return boolean
267
     * @throws Exception
268
     */
269
    public function needsServerName() {
270
        switch ($this->intRep) {
271
            case EAP::INTEGER_FAST_GTC:
272
            case EAP::INTEGER_PEAP_MSCHAPv2:
273
            case EAP::INTEGER_TTLS_GTC:
274
            case EAP::INTEGER_TTLS_MSCHAP2:
275
            case EAP::INTEGER_TTLS_PAP:
276
            case EAP::INTEGER_TLS:
277
            case EAP::INTEGER_SILVERBULLET:
278
                return TRUE;
279
            case EAP::INTEGER_EAP_PWD:
280
                return FALSE;
281
            default:
282
                throw new Exception("Unable to determine if the EAP type requires a server name trust base for secure functioning or not!");
283
        }
284
    }
285
286
    /**
287
     * Returns the Array representation of the EAP type.
288
     * 
289
     * @return array
290
     */
291
    public function getArrayRep() {
292
        return $this->arrayRep;
293
    }
294
295
    /**
296
     * Returns the int representation of the EAP type.
297
     * 
298
     * @return int
299
     */
300
    public function getIntegerRep() {
301
        return $this->intRep;
302
    }
303
304
    /**
305
     * This function takes the EAP method in array representation (OUTER/INNER) and returns it in a custom format for the
306
     * Linux installers (not numbers, but strings as values).
307
     * @param array EAP method in array representation (OUTER/INNER)
308
     * @return array EAP method in array representation (OUTER as string/INNER as string)
309
     */
310
    public static function eapDisplayName($eap) {
311
        $eapDisplayName = [];
312
        $eapDisplayName[serialize(EAP::EAPTYPE_PEAP_MSCHAP2)] = ["OUTER" => 'PEAP', "INNER" => 'MSCHAPV2'];
313
        $eapDisplayName[serialize(EAP::EAPTYPE_TLS)] = ["OUTER" => 'TLS', "INNER" => ''];
314
        $eapDisplayName[serialize(EAP::EAPTYPE_TTLS_PAP)] = ["OUTER" => 'TTLS', "INNER" => 'PAP'];
315
        $eapDisplayName[serialize(EAP::EAPTYPE_TTLS_MSCHAP2)] = ["OUTER" => 'TTLS', "INNER" => 'MSCHAPV2'];
316
        $eapDisplayName[serialize(EAP::EAPTYPE_TTLS_GTC)] = ["OUTER" => 'TTLS', "INNER" => 'GTC'];
317
        $eapDisplayName[serialize(EAP::EAPTYPE_FAST_GTC)] = ["OUTER" => 'FAST', "INNER" => 'GTC'];
318
        $eapDisplayName[serialize(EAP::EAPTYPE_PWD)] = ["OUTER" => 'PWD', "INNER" => ''];
319
        $eapDisplayName[serialize(EAP::EAPTYPE_NONE)] = ["OUTER" => '', "INNER" => ''];
320
        $eapDisplayName[serialize(EAP::EAPTYPE_SILVERBULLET)] = ["OUTER" => 'TLS', "INNER" => 'SILVERBULLET'];
321
        $eapDisplayName[serialize(EAP::EAPTYPE_ANY)] = ["OUTER" => 'PEAP TTLS TLS', "INNER" => 'MSCHAPV2 PAP GTC'];
322
        return($eapDisplayName[serialize($eap)]);
323
    }
324
325
    /**
326
     * determines the inner authentication. Is it EAP, and which mechanism is used to convey actual auth data
327
     * @param array $eap
328
     * @return array
329
     */
330
    public static function innerAuth($eap) {
331
        $out = [];
332
        if ($eap["INNER"]) { // there is an inner EAP method
333
            $out['EAP'] = 1;
334
            $out['METHOD'] = $eap["INNER"];
335
            return $out;
336
        }
337
        // there is none
338
        $out['EAP'] = 0;
339
        switch ($eap) {
340
            case EAP::EAPTYPE_TTLS_PAP:
341
                $out['METHOD'] = EAP::NE_PAP;
342
                break;
343
            case EAP::EAPTYPE_TTLS_MSCHAP2:
344
                $out['METHOD'] = EAP::NE_MSCHAP2;
345
        }
346
        return $out;
347
    }
348
349
    /**
350
     * This function enumerates all known EAP types and returns them as array
351
     * 
352
     * @return array of all EAP types the CAT knows about, as objects
353
     */
354
    public static function listKnownEAPTypes() {
355
        $retval = [];
356
357
        foreach (array_values(EAP::EAPTYPES_CONVERSION) as $oneArrayRep) {
358
            $retval[] = new EAP($oneArrayRep);
359
        }
360
        return $retval;
361
    }
362
363
    /**
364
     * returns a printable ("pretty-print") version of the EAP type
365
     * @return string
366
     */
367
    public function getPrintableRep() {
368
        $nameMapping = [
369
            _("PEAP-MSCHAPv2") => \core\common\EAP::EAPTYPE_PEAP_MSCHAP2,
370
            _("TLS") => \core\common\EAP::EAPTYPE_TLS,
371
            _("TTLS-PAP") => \core\common\EAP::EAPTYPE_TTLS_PAP,
372
            _("TTLS-MSCHAPv2") => \core\common\EAP::EAPTYPE_TTLS_MSCHAP2,
373
            _("TTLS-GTC") => \core\common\EAP::EAPTYPE_TTLS_GTC,
374
            _("FAST-GTC") => \core\common\EAP::EAPTYPE_FAST_GTC,
375
            _("EAP-pwd") => \core\common\EAP::EAPTYPE_PWD,
376
            \core\ProfileSilverbullet::PRODUCTNAME => \core\common\EAP::EAPTYPE_SILVERBULLET,
377
        ];
378
        $find = array_keys($nameMapping, $this->arrayRep, TRUE);
379
        return $find[0];
380
    }
381
382
}
383