Passed
Push — master ( 5c87ed...e4bb53 )
by Stefan
04:05
created

mobileconfigSuperclass::generalPayload()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 22
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 22
c 0
b 0
f 0
rs 9.2
cc 3
eloc 10
nc 4
nop 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 installer for iOS devices and Apple 10.7 Lion
14
 *
15
 *
16
 * @author Stefan Winter <[email protected]>
17
 * @package Developer
18
 */
19
20
namespace devices\apple_mobileconfig;
21
22
use \Exception;
23
24
/**
25
 * This is the main implementation class of the module
26
 *
27
 * The class should only define one public method: writeInstaller.
28
 *
29
 * All other methods and properties should be private. This example sets zipInstaller method to protected, so that it can be seen in the documentation.
30
 *
31
 * @package Developer
32
 */
33
abstract class mobileconfigSuperclass extends \core\DeviceConfig {
34
35
    private $instName;
36
    private $profileName;
37
    private $massagedInst;
38
    private $massagedProfile;
39
    private $massagedCountry;
40
    private $massagedConsortium;
41
    private $lang;
42
    static private $iPhonePayloadPrefix = "org.1x-config";
43
44
    public function __construct() {
45
        parent::__construct();
46
        // that's what all variants support. Sub-classes can change it.
47
        $this->setSupportedEapMethods([\core\common\EAP::EAPTYPE_PEAP_MSCHAP2, \core\common\EAP::EAPTYPE_TTLS_PAP, \core\common\EAP::EAPTYPE_TTLS_MSCHAP2, \core\common\EAP::EAPTYPE_SILVERBULLET]);
48
        $this->specialities['internal:verify_userinput_suffix'] = _("It is not possible to actively verify the user input for suffix match; but if there is no 'Terms of Use' configured, the installer will display a corresponding hint to the user instead.");
49
    }
50
51
    private function massageName($input) {
52
        return htmlspecialchars(strtolower(iconv("UTF-8", "US-ASCII//TRANSLIT", preg_replace(['/ /', '/\//'], '_', $input))), ENT_XML1, 'UTF-8');
53
    }
54
55
    private function generalPayload() {
56
        $tagline = sprintf(_("Network configuration profile '%s' of '%s' - provided by %s"), htmlspecialchars($this->profileName, ENT_XML1, 'UTF-8'), htmlspecialchars($this->instName, ENT_XML1, 'UTF-8'), CONFIG_CONFASSISTANT['CONSORTIUM']['display_name']);
0 ignored issues
show
Bug introduced by
The constant devices\apple_mobileconfig\CONFIG_CONFASSISTANT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
57
58
        $eapType = $this->selectedEap;
59
        // simpler message for silverbullet
60
        if ($eapType['INNER'] == \core\common\EAP::NE_SILVERBULLET) {
61
            $tagline = sprintf(_("%s configuration for IdP '%s' - provided by %s"), \core\ProfileSilverbullet::PRODUCTNAME, htmlspecialchars($this->instName, ENT_XML1, 'UTF-8'), CONFIG_CONFASSISTANT['CONSORTIUM']['display_name']);
62
        }
63
64
        return "
65
      <key>PayloadDescription</key>
66
         <string>$tagline</string>
67
      <key>PayloadDisplayName</key>
68
         <string>" . CONFIG_CONFASSISTANT['CONSORTIUM']['display_name'] . "</string>
69
      <key>PayloadIdentifier</key>
70
         <string>" . self::$iPhonePayloadPrefix . ".$this->massagedConsortium.$this->massagedCountry.$this->massagedInst.$this->massagedProfile.$this->lang</string>
71
      <key>PayloadOrganization</key>
72
         <string>" . htmlspecialchars(iconv("UTF-8", "UTF-8//IGNORE", $this->attributes['general:instname'][0]), ENT_XML1, 'UTF-8') . ( $this->attributes['internal:profile_count'][0] > 1 ? " (" . htmlspecialchars(iconv("UTF-8", "UTF-8//IGNORE", $this->attributes['profile:name'][0]), ENT_XML1, 'UTF-8') . ")" : "") . "</string>
73
      <key>PayloadType</key>
74
         <string>Configuration</string>
75
      <key>PayloadUUID</key>
76
         <string>" . $this->uuid('', self::$iPhonePayloadPrefix . $this->massagedConsortium . $this->massagedCountry . $this->massagedInst . $this->massagedProfile) . "</string>
77
      <key>PayloadVersion</key>
78
         <integer>1</integer>";
79
    }
80
81
    const FILE_START = "<?xml version=\"1.0\" encoding=\"utf-8\"?>
82
<!DOCTYPE plist PUBLIC \"-//Apple Computer//DTD PLIST 1.0//EN\"
83
\"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">
84
<plist version=\"1.0\">
85
<dict>";
86
    const FILE_END = "</dict></plist>";
87
    const BUFFER_CONSENT_PRE = "
88
      <key>ConsentText</key>
89
         <dict>
90
            <key>default</key>
91
               <string>";
92
    const BUFFER_CONSENT_POST = "</string>
93
         </dict>
94
         ";
95
96
    protected function consentBlock() {
97
        if (isset($this->attributes['support:info_file'])) {
98
            return mobileconfigSuperclass::BUFFER_CONSENT_PRE . htmlspecialchars(iconv("UTF-8", "UTF-8//TRANSLIT", $this->attributes['support:info_file'][0]), ENT_XML1, 'UTF-8') . mobileconfigSuperclass::BUFFER_CONSENT_POST;
99
        }
100
        if (isset($this->attributes['internal:verify_userinput_suffix'])) {
101
            if (isset($this->attributes['internal:realm'])) {
102
                return mobileconfigSuperclass::BUFFER_CONSENT_PRE . sprintf(_("Important Notice: your username must end with @%s!"), $this->attributes['internal:realm'][0]) . mobileconfigSuperclass::BUFFER_CONSENT_POST;
103
            }
104
            return mobileconfigSuperclass::BUFFER_CONSENT_PRE . _("Important Notice: your username MUST be in the form of xxx@yyy where the yyy is a common suffix identifying your Identity Provider. Please find out what to use there and enter the username in the correct format.") . mobileconfigSuperclass::BUFFER_CONSENT_POST;
105
        }
106
        return "";
107
    }
108
109
    /**
110
     * prepare a zip archive containing files and settings which normally would be used inside the module to produce an installer
111
     *
112
     */
113
    public function writeInstaller() {
114
        /** run innitial setup
115
          this will:
116
          - create the temporary directory and save its path as $this->FPATH
117
          - process the CA certificates and store results in $this->attributes['internal:CAs'][0]
118
          $this->attributes['internal:CAs'][0] is an array of processed CA certificates
119
          a processed certifincate is an array
120
          'pem' points to pem feromat certificate
121
          'der' points to der format certificate
122
          'md5' points to md5 fingerprint
123
          'sha1' points to sha1 fingerprint
124
          'name' points to the certificate subject
125
          'root' can be 1 for self-signed certificate or 0 otherwise
126
127
          - save the info_file (if exists) and put the name in $this->attributes['internal:info_file_name'][0]
128
         */
129
        $dom = textdomain(NULL);
130
        textdomain("devices");
131
132
        $this->loggerInstance->debug(4, "mobileconfig Module Installer start\n");
133
134
        // remove spaces and slashes (filename!), make sure it's simple ASCII only, then lowercase it
135
        // also escape htmlspecialchars
136
        // not all names and profiles have a name, so be prepared
137
138
        $this->loggerInstance->debug(5, "List of available attributes: " . var_export($this->attributes, TRUE));
139
140
        $this->instName = $this->attributes['general:instname'][0] ?? sprintf(_("Unnamed %s"), $this->nomenclature_inst);
141
        $this->profileName = $this->attributes['profile:name'][0] ?? _("Unnamed Profile");
142
143
        $this->massagedInst = $this->massageName($this->instName);
144
        $this->massagedProfile = $this->massageName($this->profileName);
145
        $this->massagedCountry = $this->massageName($this->attributes['internal:country'][0]);
146
        $this->massagedConsortium = $this->massageName(CONFIG_CONFASSISTANT['CONSORTIUM']['name']);
0 ignored issues
show
Bug introduced by
The constant devices\apple_mobileconfig\CONFIG_CONFASSISTANT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
147
        $this->lang = preg_replace('/\..+/', '', setlocale(LC_ALL, "0"));
148
149
        $eapType = $this->selectedEap;
150
151
        $outputXml = self::FILE_START;
152
        $outputXml .= "<key>PayloadContent</key>
153
         <array>";
154
155
        // did the admin want wired config?
156
        $includeWired = FALSE;
157
        if (isset($this->attributes['media:wired']) && get_class($this) == "Device_mobileconfig_os_x") {
158
            $includeWired = TRUE;
159
        }
160
161
        // if we are in silverbullet, we will need a whole own block for the client credential
162
        // and also for the profile expiry
163
164
        $clientCertUUID = NULL;
165
        if ($eapType['INNER'] == \core\common\EAP::NE_SILVERBULLET) {
166
            $blockinfo = $this->clientP12Block();
167
            $outputXml .= $blockinfo['block'];
168
            $clientCertUUID = $blockinfo['UUID'];
169
        }
170
171
        $outputXml .= $this->allCA($this->attributes['internal:CAs'][0]);
172
173
        $outputXml .= $this->allNetworkBlocks(
174
                $this->attributes['internal:SSID'], $this->attributes['internal:consortia'], $this->attributes['eap:server_name'], $this->listCAUuids($this->attributes['internal:CAs'][0]), $this->selectedEap, $includeWired, $clientCertUUID, $this->determineOuterIdString());
175
176
        $outputXml .= "</array>";
177
        $outputXml .= $this->generalPayload();
178
        $outputXml .= $this->consentBlock();
179
180
        if ($eapType['INNER'] == \core\common\EAP::NE_SILVERBULLET) {
181
            $outputXml .= $this->expiryBlock();
182
        }
183
        $outputXml .= self::FILE_END;
184
185
        file_put_contents('installer_profile', $outputXml);
186
187
        textdomain($dom);
188
189
        $fileName = $this->installerBasename . '.mobileconfig';
190
191
        if (!$this->sign) {
192
            rename("installer_profile", $fileName);
193
            return $fileName;
194
        }
195
        // still here? Then we are signing.
196
        $signing = system($this->sign . " installer_profile '$fileName' > /dev/null");
197
        if ($signing === FALSE) {
198
            $this->loggerInstance->debug(2, "Signing the mobileconfig installer $fileName FAILED!\n");
199
        }
200
        return $fileName;
201
    }
202
203
    public function writeDeviceInfo() {
204
        $ssidCount = count($this->attributes['internal:SSID']);
205
        $certCount = count($this->attributes['internal:CAs'][0]);
206
        $out = "<p>" . _("For best results, please use the built-in browser (Safari) to open the configuration file.") . "</p>";
207
        $out .= "<p>";
208
        $out .= _("The profile will install itself after you click (or tap) the button. You will be asked for confirmation/input at several points:");
209
        $out .= "<ul>";
210
        $out .= "<li>" . _("to install the profile") . "</li>";
211
        $out .= "<li>" . ngettext("to accept the server certificate authority", "to accept the server certificate authorities", $certCount);
212
        if ($certCount > 1) {
213
            $out .= " " . sprintf(_("(%d times)"), $certCount);
214
        }
215
        $out .= "</li>";
216
        $out .= "<li>" . sprintf(_("to enter the username and password of your %s"), $this->nomenclature_inst);
217
        if ($ssidCount > 1) {
218
            $out .= " " . sprintf(_("(%d times each, because %s is installed for %d SSIDs)"), $ssidCount, CONFIG_CONFASSISTANT['CONSORTIUM']['display_name'], $ssidCount);
0 ignored issues
show
Bug introduced by
The constant devices\apple_mobileconfig\CONFIG_CONFASSISTANT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
219
        }
220
        $out .= "</li>";
221
        $out .= "</ul>";
222
        $out .= "</p>";
223
        return $out;
224
    }
225
226
    private function listCAUuids($caArray) {
227
        $retval = [];
228
        foreach ($caArray as $ca) {
229
            $retval[] = $ca['uuid'];
230
        }
231
        return $retval;
232
    }
233
234
    private function passPointBlock($consortiumOi) {
235
        $retval = "
236
               <key>IsHotspot</key>
237
               <true/>
238
               <key>ServiceProviderRoamingEnabled</key>
239
               <true/>
240
               <key>DisplayedOperatorName</key>
241
               <string>" . CONFIG_CONFASSISTANT['CONSORTIUM']['display_name'] . " via Passpoint</string>";
0 ignored issues
show
Bug introduced by
The constant devices\apple_mobileconfig\CONFIG_CONFASSISTANT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
242
        // if we don't know the realm, omit the entire DomainName key
243
        if (isset($this->attributes['internal:realm'])) {
244
            $retval .= "<key>DomainName</key>
245
               <string>";
246
            $retval .= $this->attributes['internal:realm'][0];
247
            $retval .= "</string>
248
                ";
249
        }
250
        $retval .= "                <key>RoamingConsortiumOIs</key>
251
                <array>";
252
        foreach ($consortiumOi as $oiValue) {
253
            $retval .= "<string>$oiValue</string>";
254
        }
255
        $retval .= "</array>";
256
        // this is an undocmented value found on the net. Does it do something useful?
257
        $retval .= "<key>_UsingHotspot20</key>
258
                <true/>
259
                ";
260
        // do we need to set NAIRealmName ? In Rel 1, probably yes, in Rel 2, 
261
        // no because ConsortiumOI is enough.
262
        // but which release is OS X doing? And what should we fill in, given
263
        // that we have thousands of realms? Try just eduroam.org
264
        if (CONFIG_CONFASSISTANT['CONSORTIUM']['name'] == "eduroam") {
265
            $retval .= "<key>NAIRealmNames</key>
266
                <array>
267
                    <string>eduroam.org</string>
268
                </array>";
269
        }
270
        return $retval;
271
    }
272
273
    private $serial;
274
275
    private function eapBlock($eapType, $realm, $cAUUIDList, $serverList) {
276
        $retval = "<key>EAPClientConfiguration</key>
277
                  <dict>
278
                      <key>AcceptEAPTypes</key>
279
                         <array>
280
                            <integer>" . $eapType['OUTER'] . "</integer>
281
                         </array>
282
                      <key>EAPFASTProvisionPAC</key>
283
                            <true />
284
                      <key>EAPFASTUsePAC</key>
285
                            <true />
286
                      <key>EAPFastProvisionPACAnonymously</key>
287
                            <false />
288
                      <key>OneTimeUserPassword</key>
289
                            <false />
290
";
291
        if ($realm !== 0) {
292
            $retval .= "<key>OuterIdentity</key>
293
                                    <string>" . htmlspecialchars($realm, ENT_XML1, 'UTF-8') . "</string>
294
";
295
        }
296
        $retval .= "<key>PayloadCertificateAnchorUUID</key>
297
                         <array>";
298
        foreach ($cAUUIDList as $uuid) {
299
            $retval .= "
300
<string>$uuid</string>";
301
        }
302
        $retval .= "
303
                         </array>
304
                      <key>TLSAllowTrustExceptions</key>
305
                         <false />
306
                      <key>TLSTrustedServerNames</key>
307
                         <array>";
308
        foreach ($serverList as $commonName) {
309
            $retval .= "
310
<string>$commonName</string>";
311
        }
312
        $retval .= "
313
                         </array>";
314
        if ($eapType['INNER'] == \core\common\EAP::NE_SILVERBULLET) {
315
            $retval .= "<key>UserName</key><string>" . $this->clientCert["username"] . "</string>";
316
        }
317
        $retval .= "
318
                      <key>TTLSInnerAuthentication</key>
319
                         <string>" . ($eapType['INNER'] == \core\common\EAP::NONE ? "PAP" : "MSCHAPv2") . "</string>
320
                   </dict>";
321
        return $retval;
322
    }
323
324
    private function networkBlock($ssid, $consortiumOi, $serverList, $cAUUIDList, $eapType, $wired, $clientCertUUID, $realm = 0) {
325
        $escapedSSID = htmlspecialchars($ssid, ENT_XML1, 'UTF-8');
326
327
        $payloadIdentifier = "wifi." . $this->serial;
328
        $payloadShortName = sprintf(_("SSID %s"), $escapedSSID);
329
        $payloadName = sprintf(_("%s configuration for network name %s"), CONFIG_CONFASSISTANT['CONSORTIUM']['display_name'], $escapedSSID);
0 ignored issues
show
Bug introduced by
The constant devices\apple_mobileconfig\CONFIG_CONFASSISTANT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
330
        $encryptionTypeString = "WPA";
331
        $setupModesString = "";
332
        $wifiNetworkIdentification = "<key>SSID_STR</key>
333
                  <string>$escapedSSID</string>";
334
335
        if ($wired) { // override the above defaults for wired interfaces
336
            $payloadIdentifier = "firstactiveethernet";
337
            $payloadShortName = _("Wired Network");
338
            $payloadName = sprintf(_("%s configuration for wired network"), CONFIG_CONFASSISTANT['CONSORTIUM']['display_name']);
339
            $encryptionTypeString = "any";
340
            $setupModesString = "
341
               <key>SetupModes</key>
342
                  <array>
343
                     <string>System</string>
344
                  </array>";
345
            $wifiNetworkIdentification = "";
346
        }
347
348
        if (count($consortiumOi) > 0) { // override the above defaults for HS20 configuration
349
            $payloadIdentifier = "hs20";
350
            $payloadShortName = _("Hotspot 2.0 Settings");
351
            $payloadName = sprintf(_("%s Hotspot 2.0 configuration"), CONFIG_CONFASSISTANT['CONSORTIUM']['display_name']);
352
            $encryptionTypeString = "WPA";
353
            $wifiNetworkIdentification = $this->passPointBlock($consortiumOi);
354
        }
355
356
        $retval = "<dict>";
357
        $retval .= $this->eapBlock($eapType, $realm, $cAUUIDList, $serverList);
358
        $retval .= "<key>EncryptionType</key>
359
                  <string>$encryptionTypeString</string>
360
               <key>HIDDEN_NETWORK</key>
361
                  <true />
362
               <key>PayloadDescription</key>
363
                  <string>$payloadName</string>
364
               <key>PayloadDisplayName</key>
365
                  <string>$payloadShortName</string>
366
               <key>PayloadIdentifier</key>
367
                  <string>" . self::$iPhonePayloadPrefix . ".$this->massagedConsortium.$this->massagedCountry.$this->massagedInst.$this->massagedProfile.$this->lang.$payloadIdentifier</string>
368
               <key>PayloadOrganization</key>
369
                  <string>" . $this->massagedConsortium . ".1x-config.org</string>
370
               <key>PayloadType</key>
371
                  <string>com.apple." . ($wired ? "firstactiveethernet" : "wifi") . ".managed</string>";
372
        $this->loggerInstance->debug(2, get_class($this));
373
        if (get_class($this) != "Device_mobileconfig_ios_56") {
374
            $retval .= "<key>ProxyType</key>
375
                  <string>Auto</string>
376
                  <key>ProxyPACFallbackAllowed</key>
377
                  <true/>
378
                ";
379
        }
380
        $retval .= $setupModesString;
381
        if ($eapType['INNER'] == \core\common\EAP::NE_SILVERBULLET) {
382
            if ($clientCertUUID === NULL) {
383
                throw new Exception("Silverbullet REQUIRES a client certificate and we need to know the UUID!");
384
            }
385
            $retval .= "<key>PayloadCertificateUUID</key>
386
                        <string>$clientCertUUID</string>";
387
        }
388
        $retval .= "
389
               <key>PayloadUUID</key>
390
                  <string>" . $this->uuid() . "</string>
391
               <key>PayloadVersion</key>
392
                  <integer>1</integer>
393
                  $wifiNetworkIdentification</dict>";
394
        $this->serial = $this->serial + 1;
395
        return $retval;
396
    }
397
398
    private function removenetworkBlock($ssid, $sequence) {
399
        $retval = "
400
<dict>
401
	<key>AutoJoin</key>
402
	<false/>
403
	<key>EncryptionType</key>
404
	<string>None</string>
405
	<key>HIDDEN_NETWORK</key>
406
	<false/>
407
	<key>IsHotspot</key>
408
	<false/>
409
	<key>PayloadDescription</key>
410
	<string>" . sprintf(_("This SSID should not be used after bootstrapping %s"), CONFIG_CONFASSISTANT['CONSORTIUM']['display_name']) . "</string>
0 ignored issues
show
Bug introduced by
The constant devices\apple_mobileconfig\CONFIG_CONFASSISTANT was not found. Maybe you did not declare it correctly or list all dependencies?
Loading history...
411
	<key>PayloadDisplayName</key>
412
	<string>" . _("Disabled WiFi network") . "</string>
413
	<key>PayloadIdentifier</key>
414
	<string>" . self::$iPhonePayloadPrefix . ".$this->massagedConsortium.$this->massagedCountry.$this->massagedInst.$this->massagedProfile.$this->lang.wifi.disabled.$sequence</string>
415
	<key>PayloadType</key>
416
	<string>com.apple.wifi.managed</string>
417
	<key>PayloadUUID</key>
418
	<string>" . $this->uuid() . "</string>
419
	<key>PayloadVersion</key>
420
	<real>1</real>";
421
        if (get_class($this) != "Device_mobileconfig_ios_56") {
422
            $retval .= "<key>ProxyType</key>
423
	<string>Auto</string>";
424
        }
425
        $retval .= "<key>SSID_STR</key>
426
	<string>$ssid</string>
427
</dict>
428
";
429
        return $retval;
430
    }
431
432
    private function allNetworkBlocks($sSIDList, $consortiumOIList, $serverNameList, $cAUUIDList, $eapType, $includeWired, $clientcertUUID, $realm = 0) {
433
        $retval = "";
434
        $this->serial = 0;
435
        foreach (array_keys($sSIDList) as $ssid) {
436
            $retval .= $this->networkBlock($ssid, NULL, $serverNameList, $cAUUIDList, $eapType, FALSE, $clientcertUUID, $realm);
437
        }
438
        if ($includeWired) {
439
            $retval .= $this->networkBlock("IRRELEVANT", NULL, $serverNameList, $cAUUIDList, $eapType, TRUE, $clientcertUUID, $realm);
440
        }
441
        if (count($consortiumOIList) > 0) {
442
            $retval .= $this->networkBlock("IRRELEVANT", $consortiumOIList, $serverNameList, $cAUUIDList, $eapType, FALSE, $clientcertUUID, $realm);
443
        }
444
        if (isset($this->attributes['media:remove_SSID'])) {
445
            foreach ($this->attributes['media:remove_SSID'] as $index => $removeSSID) {
446
                $retval .= $this->removenetworkBlock($removeSSID, $index);
447
            }
448
        }
449
        return $retval;
450
    }
451
452
    private function allCA($caArray) {
453
        $retval = "";
454
        $iterator = 0;
455
        foreach ($caArray as $ca) {
456
            $retval .= $this->caBlob($ca['uuid'], $ca['pem'], $iterator);
457
            $iterator = $iterator + 1;
458
        }
459
        return $retval;
460
    }
461
462
    private function clientP12Block() {
463
        if (!is_array($this->clientCert)) {
464
            throw new Exception("the client block was called but there is no client certificate!");
465
        }
466
        $binaryBlob = $this->clientCert["certdata"];
467
        $mimeBlob = base64_encode($binaryBlob);
468
        $mimeFormatted = chunk_split($mimeBlob, 52, "\r\n");
469
        $payloadUUID = $this->uuid('', $mimeBlob);
470
        return ["block" => "<dict>" .
471
            // we don't include the import password. It's displayed on screen, and should be input by the user.
472
            // <key>Password</key>
473
            //   <string>" . $this->clientCert['password'] . "</string>
474
            "<key>PayloadCertificateFileName</key>
475
                     <string>cert-cli.pfx</string>
476
                  <key>PayloadContent</key>
477
                     <data>
478
$mimeFormatted
479
                     </data>
480
                  <key>PayloadDescription</key>
481
                     <string>MIME Base-64 encoded PKCS#12 Client Certificate</string>
482
                  <key>PayloadDisplayName</key>
483
                     <string>" . _("eduroam user certificate") . "</string>
484
                  <key>PayloadIdentifier</key>
485
                     <string>com.apple.security.pkcs12.$payloadUUID</string>
486
                  <key>PayloadType</key>
487
                     <string>com.apple.security.pkcs12</string>
488
                  <key>PayloadUUID</key>
489
                     <string>$payloadUUID</string>
490
                  <key>PayloadVersion</key>
491
                     <integer>1</integer>
492
                </dict>",
493
            "UUID" => $payloadUUID,];
494
    }
495
496
    private function expiryBlock() {
497
        if (!is_array($this->clientCert)) {
498
            throw new Exception("the expiry block was called but there is no client certificate!");
499
        }
500
        $expiryTime = $this->clientCert['expiry'];
501
        return "<key>RemovalDate</key>
502
        <date>$expiryTime</date>";
503
    }
504
505
    private function caBlob($uuid, $pem, $serial) {
506
        // cut lines with CERTIFICATE
507
        $stage1 = preg_replace('/-----BEGIN CERTIFICATE-----/', '', $pem);
508
        $stage2 = preg_replace('/-----END CERTIFICATE-----/', '', $stage1);
509
        $trimmedPem = trim($stage2);
510
511
        $stream = "
512
            <dict>
513
               <key>PayloadCertificateFileName</key>
514
               <string>$uuid.der</string>
515
               <key>PayloadContent</key>
516
               <data>
517
" . $trimmedPem . "</data>
518
               <key>PayloadDescription</key>
519
               <string>" . _("Your Identity Providers Certification Authority") . "</string>
520
               <key>PayloadDisplayName</key>
521
               <string>" . _("Identity Provider's CA") . "</string>
522
               <key>PayloadIdentifier</key>
523
               <string>" . self::$iPhonePayloadPrefix . ".$this->massagedConsortium.$this->massagedCountry.$this->massagedInst.$this->massagedProfile.credential.$serial</string>
524
               <key>PayloadOrganization</key>
525
               <string>" . $this->massagedConsortium . ".1x-config.org</string>
526
               <key>PayloadType</key>
527
               <string>com.apple.security.root</string>
528
               <key>PayloadUUID</key><string>" . $uuid . "</string>
529
               <key>PayloadVersion</key>
530
               <integer>1</integer>
531
            </dict>";
532
533
        return $stream;
534
    }
535
536
}
537