Completed
Push — master ( 0dd51b...0db328 )
by Terrence
14:19
created

index-functions.php ➔ getCert()   D

Complexity

Conditions 16
Paths 97

Size

Total Lines 108

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 16
nc 97
nop 0
dl 0
loc 108
rs 4.4532
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 ('distinguished_name'), etc.  If
25
 * there is some kind of error with the database call, an email is
26
 * sent showing which SAML attributes were missing.
27
 *
28
 * All 'returned' variables are stored in various  PHP session variables
29
 * (e.g. 'user_uid', 'distinguished_name', 'status').
30
 */
31
function getUID()
32
{
33
    $shibarray = Util::getIdpList()->getShibInfo();
34
35
    // Don't allow Organization Name to be empty
36
    if (strlen(@$shibarray['Organization Name']) == 0) {
37
        $shibarray['Organization Name'] = 'Unspecified';
38
    }
39
40
    // Extract Silver Level of Assurance from Shib-AuthnContext-Class
41
    if (
42
        preg_match(
43
            '%http://id.incommon.org/assurance/silver%',
44
            Util::getServerVar('Shib-AuthnContext-Class')
45
        )
46
    ) {
47
        $shibarray['Level of Assurance'] =
48
            'http://incommonfederation.org/assurance/silver';
49
    }
50
51
    // Check for session var 'storeattributes' which indicates to
52
    // simply store the user attributes in the PHP session.
53
    // If not set, then by default save the user attributes to
54
    // the database (which also stores the user attributes in
55
    // the PHP session).
56
    $func = 'CILogon\Service\Util::saveUserToDataStore';
57
    if (!empty(Util::getSessionVar('storeattributes'))) {
58
        $func = 'CILogon\Service\Util::setUserAttributeSessionVars';
59
    }
60
    $func(
61
        @$shibarray['User Identifier'],
62
        @$shibarray['Identity Provider'],
63
        @$shibarray['Organization Name'],
64
        @$shibarray['First Name'],
65
        @$shibarray['Last Name'],
66
        @$shibarray['Display Name'],
67
        @$shibarray['Email Address'],
68
        @$shibarray['Level of Assurance'],
69
        @$shibarray['ePPN'],
70
        @$shibarray['ePTID'],
71
        '', // OpenID 2.0 ID
72
        '', // OpenID Connect ID
73
        @$shibarray['Subject ID'],
74
        @$shibarray['Pairwise ID'],
75
        @$shibarray['Affiliation'],
76
        @$shibarray['OU'],
77
        @$shibarray['Member'],
78
        @$shibarray['Authn Context'],
79
        @$shibarray['Entitlement'],
80
        @$shibarray['iTrustUIN']
81
    );
82
}
83
84
/**
85
 * getUserAndRespond
86
 *
87
 * This function gets the user's database UID puts several variables
88
 * in the current PHP session, and responds by redirecting to the
89
 * responseurl in the passed-in parameter.  If there are any issues
90
 * with the database call, an email is sent to the CILogon admins.
91
 *
92
 * @param string $responseurl The full URL to redirect to after getting
93
 *        the userid.
94
 */
95
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-116) 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...
96
{
97
    getUID(); // Get the user's database user ID, put info in PHP session
98
99
    // Finally, redirect to the calling script.
100
    header('Location: ' . $responseurl);
101
    exit; // No further processing necessary
102
}
103
104
/**
105
 * getPKCS12
106
 *
107
 * This function is called when an ECP client wants to get a PKCS12
108
 * credential.  It first attempts to get the user's database UID. If
109
 * successful, it tries to create a PKCS12 file on disk by calling
110
 * MyProxy.  If successful, it returns the PKCS12 file by setting the
111
 * HTTP Content-type.  If there is an error, it returns a plain text
112
 * file and sets the HTTP response code to an error code.
113
 */
114
function getPKCS12()
115
{
116
    $log = new Loggit();
117
118
    getUID(); // Get the user's database user ID, put info in PHP session
119
120
    $skin = Util::getSkin();
121
    $skin->init(); // Check for forced skin
122
123
    // If 'status' is not STATUS_OK*, then return error message
124
    if (Util::getSessionVar('status') & 1) { // Bad status codes are odd
125
        $errstr = array_search(Util::getSessionVar('status'), DBService::$STATUS);
126
        $log->info('ECP PKCS12 error: ' . $errstr . '.');
127
        outputError($errstr);
128
        Util::unsetAllUserSessionVars();
129
        return; // ERROR means no further processing is necessary
130
    }
131
132
    // CIL-624 Check if X509 certs are disabled
133
    if ((defined('DISABLE_X509')) && (DISABLE_X509 === true)) {
134
        $log->info('ECP PKCS12 error: Downloading certificates is ' .
135
            'disabled due to DISABLE_X509.');
136
        outputError('Downloading certificates is disabled.');
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('email') .
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
    // CIL-624 Check if X509 certs are disabled
232
    if ((defined('DISABLE_X509')) && (DISABLE_X509 === true)) {
233
        $log->info('ECP certreq error: Downloading certificates is ' .
234
            'disabled due to DISABLE_X509.');
235
        outputError('Downloading certificates is disabled.');
236
        Util::unsetAllUserSessionVars();
237
        return; // ERROR means no further processing is necessary
238
    }
239
240
    // Verify myproxy-logon binary is configured
241
    $disabledbyconf = ((!defined('MYPROXY_LOGON')) || (empty(MYPROXY_LOGON)));
242
    if ($disabledbyconf) {
243
        $log->info('ECP certreq error: Downloading certificates is ' .
244
            'disabled due to myproxy-logon not configured.');
245
        outputError('Downloading certificates is disabled.');
246
        Util::unsetAllUserSessionVars();
247
        return; // ERROR means no further processing is necessary
248
    }
249
250
    $shibarray = Util::getIdpList()->getShibInfo();
251
    if (Util::isEduGAINAndGetCert(@$shibarray['Identity Provider'], @$shibarray['Organization Name'])) {
252
        $log->info('ECP certreq error: Failed to get cert due to eduGAIN IdP restriction.');
253
        outputError('Failed to get cert due to eduGAIN IdP restriction.');
254
        return; // ERROR means no further processing is necessary
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) = Util::getMinMaxLifetimes('ecp', 277);
0 ignored issues
show
Bug introduced by
The method getMinMaxLifetimes() does not seem to exist on object<CILogon\Service\Util>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
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('distinguished_name');
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
            Util::getLOAPort(),
0 ignored issues
show
Bug introduced by
The method getLOAPort() does not seem to exist on object<CILogon\Service\Util>.

This check looks for calls to methods that do not seem to exist on a given type. It looks for the method on the type itself as well as in inherited classes or implemented interfaces.

This is most likely a typographical error or the method has been renamed.

Loading history...
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('email') .
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 'distinguished_name' PHP session value
309
        $log->info('ECP certreq error: Missing \'distinguished_name\' session value.');
310
        outputError('Cannot create certificate due to missing attributes.');
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