Completed
Push — master ( d8f226...2424ca )
by Terrence
14:08
created

index-functions.php ➔ getCert()   F

Complexity

Conditions 16
Paths 276

Size

Total Lines 108

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 16
nc 276
nop 0
dl 0
loc 108
rs 3.0266
c 0
b 0
f 0

How to fix   Long Method    Complexity   

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\Loggit;
15
16
/**
17
 * getUID
18
 *
19
 * This function takes all of the various required SAML attributes (as
20
 * set in the current Shibboleth session) and makes a call to the
21
 * database (via the dbservice) to get the userid assoicated with
22
 * those attributes.  It sets several PHP session variables such as the
23
 * status code returned by the dbservice, the uid (if found), the
24
 * username to be passed to MyProxy ('dn'), etc.  If there is some kind
25
 * of error with the database call, an email is sent showing which
26
 * SAML attributes were missing.
27
 *
28
 * All 'returned' variables are stored in various  PHP session variables
29
 * (e.g. 'uid', 'dn', 'status').
30
 */
31
function getUID()
32
{
33
    $shibarray = Util::getIdpList()->getShibInfo();
34
35
    $firstname = @$shibarray['First Name'];
36
    $lastname = @$shibarray['Last Name'];
37
    if ((strlen($firstname) == 0) || (strlen($lastname) == 0)) {
38
        list($firstname, $lastname) = Util::getFirstAndLastName(
39
            @$shibarray['Display Name'],
40
            $firstname,
41
            $lastname
42
        );
43
    }
44
45
    // Hack for test IdP at boingo.ncsa.uiuc.edu
46
    if (strlen(@$shibarray['Organization Name']) == 0) {
47
        $shibarray['Organization Name'] = 'Unspecified';
48
    }
49
50
    // Extract Silver Level of Assurance from Shib-AuthnContext-Class
51
    if (
52
        preg_match(
53
            '%http://id.incommon.org/assurance/silver%',
54
            Util::getServerVar('Shib-AuthnContext-Class')
55
        )
56
    ) {
57
        $shibarray['Level of Assurance'] =
58
            'http://incommonfederation.org/assurance/silver';
59
    }
60
61
    // Check for session var 'storeattributes' which indicates to
62
    // simply store the user attributes in the PHP session.
63
    // If not set, then by default save the user attributes to
64
    // the database (which also stores the user attributes in
65
    // the PHP session).
66
    $func = 'CILogon\Service\Util::saveUserToDataStore';
67
    if (!empty(Util::getSessionVar('storeattributes'))) {
68
        $func = 'CILogon\Service\Util::setUserAttributeSessionVars';
69
        Util::unsetSessionVar('storeattributes');
70
    }
71
    $func(
72
        @$shibarray['User Identifier'],
73
        @$shibarray['Identity Provider'],
74
        @$shibarray['Organization Name'],
75
        $firstname,
76
        $lastname,
77
        @$shibarray['Display Name'],
78
        @$shibarray['Email Address'],
79
        @$shibarray['Level of Assurance'],
80
        @$shibarray['ePPN'],
81
        @$shibarray['ePTID'],
82
        '', // OpenID 2.0 ID
83
        '', // OpenID Connect ID
84
        @$shibarray['Affiliation'],
85
        @$shibarray['OU'],
86
        @$shibarray['Member'],
87
        @$shibarray['Authn Context'],
88
        @$shibarray['Entitlement'],
89
        @$shibarray['iTrustUIN']
90
    );
91
}
92
93
/**
94
 * getUserAndRespond
95
 *
96
 * This function gets the user's database UID puts several variables
97
 * in the current PHP session, and responds by redirecting to the
98
 * responseurl in the passed-in parameter.  If there are any issues
99
 * with the database call, an email is sent to the CILogon admins.
100
 *
101
 * @param string $responseurl The full URL to redirect to after getting
102
 *        the userid.
103
 */
104
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...
105
{
106
    getUID(); // Get the user's database user ID, put info in PHP session
107
108
    // Finally, redirect to the calling script.
109
    header('Location: ' . $responseurl);
110
    exit; // No further processing necessary
111
}
112
113
/**
114
 * getPKCS12
115
 *
116
 * This function is called when an ECP client wants to get a PKCS12
117
 * credential.  It first attempts to get the user's database UID. If
118
 * successful, it tries to create a PKCS12 file on disk by calling
119
 * MyProxy.  If successful, it returns the PKCS12 file by setting the
120
 * HTTP Content-type.  If there is an error, it returns a plain text
121
 * file and sets the HTTP response code to an error code.
122
 */
123
function getPKCS12()
124
{
125
    $log = new Loggit();
126
127
    getUID(); // Get the user's database user ID, put info in PHP session
128
129
    $skin = Util::getSkin();
130
    $skin->init(); // Check for forced skin
131
132
    // If 'status' is not STATUS_OK*, then return error message
133
    if (Util::getSessionVar('status') & 1) { // Bad status codes are odd
134
        $errstr = array_search(Util::getSessionVar('status'), DBService::$STATUS);
135
        $log->info('ECP PKCS12 error: ' . $errstr . '.');
136
        outputError($errstr);
137
        Util::unsetAllUserSessionVars();
138
        return; // ERROR means no further processing is necessary
139
    }
140
141
    // Verify myproxy-logon binary is configured
142
    $disabledbyconf = ((!defined(MYPROXY_LOGON)) || (empty(MYPROXY_LOGON)));
143
    if ($disabledbyconf) {
144
        $log->info('ECP PKCS12 error: Downloading certificates is ' .
145
            'disabled due to myproxy-logon not configured.');
146
        outputError('Downloading certificates is disabled.');
147
        Util::unsetAllUserSessionVars();
148
        return; // ERROR means no further processing is necessary
149
    }
150
151
    $shibarray = Util::getIdpList()->getShibInfo();
152
    if (Util::isEduGAINAndGetCert(@$shibarray['Identity Provider'], @$shibarray['Organization Name'])) {
153
        $log->info('ECP PKCS12 error: Failed to get cert due to eduGAIN IdP restriction.');
154
        outputError('Failed to get cert due to eduGAIN IdP restriction.');
155
        return; // ERROR means no further processing is necessary
156
    }
157
158
    $skin->setMyProxyInfo();
159
    Content::generateP12();  // Try to create the PKCS12 credential file on disk
160
161
    // Look for the p12error PHP session variable. If set, return it.
162
    $p12error = Util::getSessionVar('p12error');
163
    if (strlen($p12error) > 0) {
164
        $log->info('ECP PKCS12 error: ' . $p12error);
165
        outputError($p12error);
166
    } else { // Try to read the .p12 file from disk and return it
167
        $p12 = Util::getSessionVar('p12');
168
        $p12expire = '';
169
        $p12link = '';
170
        $p12file = '';
171
        if (preg_match('/([^\s]*)\s(.*)/', $p12, $match)) {
172
            $p12expire = $match[1];
173
            $p12link = $match[2];
174
        }
175
        if ((strlen($p12link) > 0) && (strlen($p12expire) > 0)) {
176
            $p12file = file_get_contents($p12link);
177
        }
178
179
        if (strlen($p12file) > 0) {
180
            $log->info('ECP PKCS12 success!');
181
            // CIL-507 Special log message for XSEDE
182
            $log->info('USAGE email="' . Util::getSessionVar('emailaddr') .
183
                       '" client="ECP"');
184
            header('Content-type: application/x-pkcs12');
185
            echo $p12file;
186
        } else {
187
            $log->info('ECP PKCS12 error: Missing or empty PKCS12 file.');
188
            outputError('Missing or empty PKCS12 file.');
189
        }
190
    }
191
}
192
193
/**
194
 * getCert
195
 *
196
 * This function is called when an ECP client wants to get a PEM-
197
 * formatted X.509 certificate by inputting a certificate request
198
 * generated by 'openssl req'.  It first attempts to get the user's
199
 * database UID. If successful, it calls out to myproxy-logon to get
200
 * a certificate. If successful, it returns the certificate by setting
201
 * the HTTP Content-type to 'text/plain'.  If there is an error, it
202
 * returns a plain text file and sets the HTTP response code to an
203
 * error code.
204
 */
205
function getCert()
206
{
207
    $log = new Loggit();
208
209
    // Verify that a non-empty certreq <form> variable was posted
210
    $certreq = Util::getPostVar('certreq');
211
    if (strlen($certreq) == 0) {
212
        $log->info('ECP certreq error: Missing certificate request.');
213
        outputError('Missing certificate request.');
214
        return; // ERROR means no further processing is necessary
215
    }
216
217
    getUID(); // Get the user's database user ID, put info in PHP session
218
219
    $skin = Util::getSkin();
220
    $skin->init(); // Check for forced skin
221
222
    // If 'status' is not STATUS_OK*, then return error message
223
    if (Util::getSessionVar('status') & 1) { // Bad status codes are odd
224
        $errstr = array_search(Util::getSessionVar('status'), DBService::$STATUS);
225
        $log->info('ECP certreq error: ' . $errstr . '.');
226
        outputError($errstr);
227
        Util::unsetAllUserSessionVars();
228
        return; // ERROR means no further processing is necessary
229
    }
230
    //
231
    // Verify myproxy-logon binary is configured
232
    $disabledbyconf = ((!defined(MYPROXY_LOGON)) || (empty(MYPROXY_LOGON)));
233
    if ($disabledbyconf) {
234
        $log->info('ECP certreq error: Downloading certificates is ' .
235
            'disabled due to myproxy-logon not configured.');
236
        outputError('Downloading certificates is disabled.');
237
        Util::unsetAllUserSessionVars();
238
        return; // ERROR means no further processing is necessary
239
    }
240
241
    $shibarray = Util::getIdpList()->getShibInfo();
242
    if (Util::isEduGAINAndGetCert(@$shibarray['Identity Provider'], @$shibarray['Organization Name'])) {
243
        $log->info('ECP certreq error: Failed to get cert due to eduGAIN IdP restriction.');
244
        outputError('Failed to get cert due to eduGAIN IdP restriction.');
245
        return; // ERROR means no further processing is necessary
246
    }
247
248
    // Set the port based on the Level of Assurance
249
    $port = 7512;
250
    $loa = Util::getSessionVar('loa');
251
    if ($loa == 'http://incommonfederation.org/assurance/silver') {
252
        $port = 7514;
253
    } elseif ($loa == 'openid') {
254
        $port = 7516;
255
    }
256
257
    // Get the certificate lifetime. Set to a default value if not set.
258
    $certlifetime = (int)(Util::getPostVar('certlifetime'));
259
    if ($certlifetime == 0) {  // If not specified, set to default value
260
        $defaultlifetime = $skin->getConfigOption('ecp', 'defaultlifetime');
261
        if ((!is_null($defaultlifetime)) && ((int)$defaultlifetime > 0)) {
262
            $certlifetime = (int)$defaultlifetime;
263
        } else {
264
            $certlifetime = MyProxy::getDefaultLifetime();
265
        }
266
    }
267
268
    // Make sure lifetime is within acceptable range. 277 hrs = 1000000 secs.
269
    list($minlifetime, $maxlifetime) = Content::getMinMaxLifetimes('ecp', 277);
270
    if ($certlifetime < $minlifetime) {
271
        $certlifetime = $minlifetime;
272
    } elseif ($certlifetime > $maxlifetime) {
273
        $certlifetime = $maxlifetime;
274
    }
275
276
    // Make sure that the user's MyProxy username is available.
277
    $dn = Util::getSessionVar('dn');
278
    if (strlen($dn) > 0) {
279
        // Append extra info, such as 'skin', to be processed by MyProxy.
280
        $skin->setMyProxyInfo();
281
        $myproxyinfo = Util::getSessionVar('myproxyinfo');
282
        if (strlen($myproxyinfo) > 0) {
283
            $dn .= " $myproxyinfo";
284
        }
285
        // Attempt to fetch a credential from the MyProxy server
286
        $cert = MyProxy::getMyProxyCredential(
287
            $dn,
288
            '',
289
            MYPROXY_HOST,
290
            $port,
291
            $certlifetime,
292
            '/var/www/config/hostcred.pem',
293
            '',
294
            $certreq
295
        );
296
297
        if (strlen($cert) > 0) { // Successfully got a certificate!
298
            $log->info('ECP getcert success!');
299
            // CIL-507 Special log message for XSEDE
300
            $log->info('USAGE email="' . Util::getSessionVar('emailaddr') .
301
                       '" client="ECP"');
302
            header('Content-type: text/plain');
303
            echo $cert;
304
        } else { // The myproxy-logon command failed - shouldn't happen!
305
            $log->info('ECP certreq error: MyProxy unable to create certificate.');
306
            outputError('Error! MyProxy unable to create certificate.');
307
        }
308
    } else { // Couldn't find the 'dn' PHP session value - shouldn't happen!
309
        $log->info('ECP certreq error: Missing \'dn\' session value.');
310
        outputError('Missing username. Please enable cookies.');
311
    }
312
}
313
314
/**
315
 * outputError
316
 *
317
 * This function sets the HTTP return type to 'text/plain' and also
318
 * sets the HTTP return code to 400, meaning there was an error of
319
 * some kind.  If there is also a passed in errstr, that is output as
320
 * the body of the HTTP return.
321
 * @param string $errstr (Optional) The error string to print in the
322
 *        text/plain return body.
323
 */
324
function outputError($errstr = '')
325
{
326
    header('Content-type: text/plain', true, 400);
327
    if (strlen($errstr) > 0) {
328
        echo $errstr;
329
    }
330
}
331