Completed
Push — master ( 5a053e...8eeafe )
by Terrence
10:16
created

index-functions.php ➔ getPKCS12()   B

Complexity

Conditions 9
Paths 12

Size

Total Lines 65

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 9
nc 12
nop 0
dl 0
loc 65
rs 7.208
c 0
b 0
f 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
 * This file contains functions called by index.php. The index.php
5
 * file should include this file with the following statement at the top:
6
 *
7
 * require_once __DIR__ . '/index-functions.php';
8
 */
9
10
use CILogon\Service\Util;
11
use CILogon\Service\Content;
12
use CILogon\Service\DBService;
13
use CILogon\Service\MyProxy;
14
use CILogon\Service\TwoFactor;
15
use CILogon\Service\Loggit;
16
17
/**
18
 * getUID
19
 *
20
 * This function takes all of the various required SAML attributes (as
21
 * set in the current Shibboleth session) and makes a call to the
22
 * database (via the dbservice) to get the userid assoicated with
23
 * those attributes.  It sets several PHP session variables such as the
24
 * status code returned by the dbservice, the uid (if found), the
25
 * username to be passed to MyProxy ('dn'), etc.  If there is some kind
26
 * of error with the database call, an email is sent showing which
27
 * SAML attributes were missing.
28
 *
29
 * All 'returned' variables are stored in various  PHP session variables
30
 * (e.g. 'uid', 'dn', 'status').
31
 */
32
function getUID()
33
{
34
    $shibarray = Util::getIdpList()->getShibInfo();
35
36
    $firstname = @$shibarray['First Name'];
37
    $lastname = @$shibarray['Last Name'];
38
    if ((strlen($firstname) == 0) || (strlen($lastname) == 0)) {
39
        list($firstname, $lastname) = Util::getFirstAndLastName(
40
            @$shibarray['Display Name'],
41
            $firstname,
42
            $lastname
43
        );
44
    }
45
46
    // Hack for test IdP at boingo.ncsa.uiuc.edu
47
    if (strlen(@$shibarray['Organization Name']) == 0) {
48
        $shibarray['Organization Name'] = 'Unspecified';
49
    }
50
51
    // Extract Silver Level of Assurance from Shib-AuthnContext-Class
52
    if (
53
        preg_match(
54
            '%http://id.incommon.org/assurance/silver%',
55
            Util::getServerVar('Shib-AuthnContext-Class')
56
        )
57
    ) {
58
        $shibarray['Level of Assurance'] =
59
            'http://incommonfederation.org/assurance/silver';
60
    }
61
62
    // Check for session var 'storeattributes' which indicates to
63
    // simply store the user attributes in the PHP session.
64
    // If not set, then by default save the user attributes to
65
    // the database (which also stores the user attributes in
66
    // the PHP session).
67
    $func = 'CILogon\Service\Util::saveUserToDataStore';
68
    if (!empty(Util::getSessionVar('storeattributes'))) {
69
        $func = 'CILogon\Service\Util::setUserAttributeSessionVars';
70
        Util::unsetSessionVar('storeattributes');
71
    }
72
    $func(
73
        @$shibarray['User Identifier'],
74
        @$shibarray['Identity Provider'],
75
        @$shibarray['Organization Name'],
76
        $firstname,
77
        $lastname,
78
        @$shibarray['Display Name'],
79
        @$shibarray['Email Address'],
80
        @$shibarray['Level of Assurance'],
81
        @$shibarray['ePPN'],
82
        @$shibarray['ePTID'],
83
        '', // OpenID 2.0 ID
84
        '', // OpenID Connect ID
85
        @$shibarray['Affiliation'],
86
        @$shibarray['OU'],
87
        @$shibarray['Member'],
88
        @$shibarray['Authn Context'],
89
        @$shibarray['Entitlement'],
90
        @$shibarray['iTrustUIN']
91
    );
92
}
93
94
/**
95
 * getUserAndRespond
96
 *
97
 * This function gets the user's database UID puts several variables
98
 * in the current PHP session, and responds by redirecting to the
99
 * responseurl in the passed-in parameter.  If there are any issues
100
 * with the database call, an email is sent to the CILogon admins.
101
 *
102
 * @param string $responseurl The full URL to redirect to after getting
103
 *        the userid.
104
 */
105
function getUserAndRespond($responseurl)
0 ignored issues
show
Best Practice introduced by
The function getUserAndRespond() has been defined more than once; this definition is ignored, only the first definition in getuser/index-functions.php (L22-120) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
106
{
107
    getUID(); // Get the user's database user ID, put info in PHP session
108
109
    // Finally, redirect to the calling script.
110
    header('Location: ' . $responseurl);
111
    exit; // No further processing necessary
112
}
113
114
/**
115
 * getPKCS12
116
 *
117
 * This function is called when an ECP client wants to get a PKCS12
118
 * credential.  It first attempts to get the user's database UID. If
119
 * successful, it tries to create a PKCS12 file on disk by calling
120
 * MyProxy.  If successful, it returns the PKCS12 file by setting the
121
 * HTTP Content-type.  If there is an error, it returns a plain text
122
 * file and sets the HTTP response code to an error code.
123
 */
124
function getPKCS12()
125
{
126
    $log = new Loggit();
127
128
    getUID(); // Get the user's database user ID, put info in PHP session
129
130
    $skin = Util::getSkin();
131
    $skin->init(); // Check for forced skin
132
133
    // If 'status' is not STATUS_OK*, then return error message
134
    if (Util::getSessionVar('status') & 1) { // Bad status codes are odd
135
        $errstr = array_search(Util::getSessionVar('status'), DBService::$STATUS);
136
        $log->info('ECP PKCS12 error: ' . $errstr . '.');
137
        outputError($errstr);
138
        Util::unsetAllUserSessionVars();
139
        return; // ERROR means no further processing is necessary
140
    }
141
142
    if (!TwoFactor::ecpCheck()) {
143
        $log->info('ECP PKCS12 error: Two-factor check failed.');
144
        outputError('2FA check failed.');
145
        return; // ERROR means no further processing is necessary
146
    }
147
148
    $shibarray = Util::getIdpList()->getShibInfo();
149
    if (Util::isEduGAINAndGetCert(@$shibarray['Identity Provider'], @$shibarray['Organization Name'])) {
150
        $log->info('ECP PKCS12 error: Failed to get cert due to eduGAIN IdP restriction.');
151
        outputError('Failed to get cert due to eduGAIN IdP restriction.');
152
        return; // ERROR means no further processing is necessary
153
    }
154
155
    $skin->setMyProxyInfo();
156
    Content::generateP12();  // Try to create the PKCS12 credential file on disk
157
158
    // Look for the p12error PHP session variable. If set, return it.
159
    $p12error = Util::getSessionVar('p12error');
160
    if (strlen($p12error) > 0) {
161
        $log->info('ECP PKCS12 error: ' . $p12error);
162
        outputError($p12error);
163
    } else { // Try to read the .p12 file from disk and return it
164
        $p12 = Util::getSessionVar('p12');
165
        $p12expire = '';
166
        $p12link = '';
167
        $p12file = '';
168
        if (preg_match('/([^\s]*)\s(.*)/', $p12, $match)) {
169
            $p12expire = $match[1];
170
            $p12link = $match[2];
171
        }
172
        if ((strlen($p12link) > 0) && (strlen($p12expire) > 0)) {
173
            $p12file = file_get_contents($p12link);
174
        }
175
176
        if (strlen($p12file) > 0) {
177
            $log->info('ECP PKCS12 success!');
178
            // CIL-507 Special log message for XSEDE
179
            $log->info('USAGE email="' . Util::getSessionVar('emailaddr') .
180
                       '" client="ECP"');
181
            header('Content-type: application/x-pkcs12');
182
            echo $p12file;
183
        } else {
184
            $log->info('ECP PKCS12 error: Missing or empty PKCS12 file.');
185
            outputError('Missing or empty PKCS12 file.');
186
        }
187
    }
188
}
189
190
/**
191
 * getCert
192
 *
193
 * This function is called when an ECP client wants to get a PEM-
194
 * formatted X.509 certificate by inputting a certificate request
195
 * generated by 'openssl req'.  It first attempts to get the user's
196
 * database UID. If successful, it calls out to myproxy-logon to get
197
 * a certificate. If successful, it returns the certificate by setting
198
 * the HTTP Content-type to 'text/plain'.  If there is an error, it
199
 * returns a plain text file and sets the HTTP response code to an
200
 * error code.
201
 */
202
function getCert()
203
{
204
    $log = new Loggit();
205
206
    // Verify that a non-empty certreq <form> variable was posted
207
    $certreq = Util::getPostVar('certreq');
208
    if (strlen($certreq) == 0) {
209
        $log->info('ECP certreq error: Missing certificate request.');
210
        outputError('Missing certificate request.');
211
        return; // ERROR means no further processing is necessary
212
    }
213
214
    getUID(); // Get the user's database user ID, put info in PHP session
215
216
    $skin = Util::getSkin();
217
    $skin->init(); // Check for forced skin
218
219
    // If 'status' is not STATUS_OK*, then return error message
220
    if (Util::getSessionVar('status') & 1) { // Bad status codes are odd
221
        $errstr = array_search(Util::getSessionVar('status'), DBService::$STATUS);
222
        $log->info('ECP certreq error: ' . $errstr . '.');
223
        outputError($errstr);
224
        Util::unsetAllUserSessionVars();
225
        return; // ERROR means no further processing is necessary
226
    }
227
228
    if (!TwoFactor::ecpCheck()) {
229
        $log->info('ECP certreq error: Two-factor check failed.');
230
        outputError('2FA check failed.');
231
        return; // ERROR means no further processing is necessary
232
    }
233
234
    $shibarray = Util::getIdpList()->getShibInfo();
235
    if (Util::isEduGAINAndGetCert(@$shibarray['Identity Provider'], @$shibarray['Organization Name'])) {
236
        $log->info('ECP certreq error: Failed to get cert due to eduGAIN IdP restriction.');
237
        outputError('Failed to get cert due to eduGAIN IdP restriction.');
238
        return; // ERROR means no further processing is necessary
239
    }
240
241
    // Set the port based on the Level of Assurance
242
    $port = 7512;
243
    $loa = Util::getSessionVar('loa');
244
    if ($loa == 'http://incommonfederation.org/assurance/silver') {
245
        $port = 7514;
246
    } elseif ($loa == 'openid') {
247
        $port = 7516;
248
    }
249
250
    // Get the certificate lifetime. Set to a default value if not set.
251
    $certlifetime = (int)(Util::getPostVar('certlifetime'));
252
    if ($certlifetime == 0) {  // If not specified, set to default value
253
        $defaultlifetime = $skin->getConfigOption('ecp', 'defaultlifetime');
254
        if ((!is_null($defaultlifetime)) && ((int)$defaultlifetime > 0)) {
255
            $certlifetime = (int)$defaultlifetime;
256
        } else {
257
            $certlifetime = MyProxy::getDefaultLifetime();
258
        }
259
    }
260
261
    // Make sure lifetime is within acceptable range. 277 hrs = 1000000 secs.
262
    list($minlifetime, $maxlifetime) = Content::getMinMaxLifetimes('ecp', 277);
263
    if ($certlifetime < $minlifetime) {
264
        $certlifetime = $minlifetime;
265
    } elseif ($certlifetime > $maxlifetime) {
266
        $certlifetime = $maxlifetime;
267
    }
268
269
    // Make sure that the user's MyProxy username is available.
270
    $dn = Util::getSessionVar('dn');
271
    if (strlen($dn) > 0) {
272
        // Append extra info, such as 'skin', to be processed by MyProxy.
273
        $skin->setMyProxyInfo();
274
        $myproxyinfo = Util::getSessionVar('myproxyinfo');
275
        if (strlen($myproxyinfo) > 0) {
276
            $dn .= " $myproxyinfo";
277
        }
278
        // Attempt to fetch a credential from the MyProxy server
279
        $cert = MyProxy::getMyProxyCredential(
280
            $dn,
281
            '',
282
            'myproxy.cilogon.org,myproxy2.cilogon.org',
283
            $port,
284
            $certlifetime,
285
            '/var/www/config/hostcred.pem',
286
            '',
287
            $certreq
288
        );
289
290
        if (strlen($cert) > 0) { // Successfully got a certificate!
291
            $log->info('ECP getcert success!');
292
            // CIL-507 Special log message for XSEDE
293
            $log->info('USAGE email="' . Util::getSessionVar('emailaddr') .
294
                       '" client="ECP"');
295
            header('Content-type: text/plain');
296
            echo $cert;
297
        } else { // The myproxy-logon command failed - shouldn't happen!
298
            $log->info('ECP certreq error: MyProxy unable to create certificate.');
299
            outputError('Error! MyProxy unable to create certificate.');
300
        }
301
    } else { // Couldn't find the 'dn' PHP session value - shouldn't happen!
302
        $log->info('ECP certreq error: Missing \'dn\' session value.');
303
        outputError('Missing username. Please enable cookies.');
304
    }
305
}
306
307
/**
308
 * outputError
309
 *
310
 * This function sets the HTTP return type to 'text/plain' and also
311
 * sets the HTTP return code to 400, meaning there was an error of
312
 * some kind.  If there is also a passed in errstr, that is output as
313
 * the body of the HTTP return.
314
 * @param string $errstr (Optional) The error string to print in the
315
 *        text/plain return body.
316
 */
317
function outputError($errstr = '')
318
{
319
    header('Content-type: text/plain', true, 400);
320
    if (strlen($errstr) > 0) {
321
        echo $errstr;
322
    }
323
}
324