Completed
Push — master ( 51adf2...24290f )
by Terrence
11:58
created

index-functions.php ➔ getCert()   C

Complexity

Conditions 14
Paths 96

Size

Total Lines 99

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 14
nc 96
nop 0
dl 0
loc 99
rs 5.0351
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
    }
70
    $func(
71
        @$shibarray['User Identifier'],
72
        @$shibarray['Identity Provider'],
73
        @$shibarray['Organization Name'],
74
        $firstname,
75
        $lastname,
76
        @$shibarray['Display Name'],
77
        @$shibarray['Email Address'],
78
        @$shibarray['Level of Assurance'],
79
        @$shibarray['ePPN'],
80
        @$shibarray['ePTID'],
81
        '', // OpenID 2.0 ID
82
        '', // OpenID Connect ID
83
        @$shibarray['Affiliation'],
84
        @$shibarray['OU'],
85
        @$shibarray['Member'],
86
        @$shibarray['Authn Context'],
87
        @$shibarray['Entitlement'],
88
        @$shibarray['iTrustUIN'],
89
        @$shibarray['Subject ID'],
90
        @$shibarray['Pairwise ID']
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
    // Verify myproxy-logon binary is configured
143
    $disabledbyconf = ((!defined('MYPROXY_LOGON')) || (empty(MYPROXY_LOGON)));
144
    if ($disabledbyconf) {
145
        $log->info('ECP PKCS12 error: Downloading certificates is ' .
146
            'disabled due to myproxy-logon not configured.');
147
        outputError('Downloading certificates is disabled.');
148
        Util::unsetAllUserSessionVars();
149
        return; // ERROR means no further processing is necessary
150
    }
151
152
    $shibarray = Util::getIdpList()->getShibInfo();
153
    if (Util::isEduGAINAndGetCert(@$shibarray['Identity Provider'], @$shibarray['Organization Name'])) {
154
        $log->info('ECP PKCS12 error: Failed to get cert due to eduGAIN IdP restriction.');
155
        outputError('Failed to get cert due to eduGAIN IdP restriction.');
156
        return; // ERROR means no further processing is necessary
157
    }
158
159
    $skin->setMyProxyInfo();
160
    Content::generateP12();  // Try to create the PKCS12 credential file on disk
161
162
    // Look for the p12error PHP session variable. If set, return it.
163
    $p12error = Util::getSessionVar('p12error');
164
    if (strlen($p12error) > 0) {
165
        $log->info('ECP PKCS12 error: ' . $p12error);
166
        outputError($p12error);
167
    } else { // Try to read the .p12 file from disk and return it
168
        $p12 = Util::getSessionVar('p12');
169
        $p12expire = '';
170
        $p12link = '';
171
        $p12file = '';
172
        if (preg_match('/([^\s]*)\s(.*)/', $p12, $match)) {
173
            $p12expire = $match[1];
174
            $p12link = $match[2];
175
        }
176
        if ((strlen($p12link) > 0) && (strlen($p12expire) > 0)) {
177
            $p12file = file_get_contents($p12link);
178
        }
179
180
        if (strlen($p12file) > 0) {
181
            $log->info('ECP PKCS12 success!');
182
            // CIL-507 Special log message for XSEDE
183
            $log->info('USAGE email="' . Util::getSessionVar('emailaddr') .
184
                       '" client="ECP"');
185
            header('Content-type: application/x-pkcs12');
186
            echo $p12file;
187
        } else {
188
            $log->info('ECP PKCS12 error: Missing or empty PKCS12 file.');
189
            outputError('Missing or empty PKCS12 file.');
190
        }
191
    }
192
}
193
194
/**
195
 * getCert
196
 *
197
 * This function is called when an ECP client wants to get a PEM-
198
 * formatted X.509 certificate by inputting a certificate request
199
 * generated by 'openssl req'.  It first attempts to get the user's
200
 * database UID. If successful, it calls out to myproxy-logon to get
201
 * a certificate. If successful, it returns the certificate by setting
202
 * the HTTP Content-type to 'text/plain'.  If there is an error, it
203
 * returns a plain text file and sets the HTTP response code to an
204
 * error code.
205
 */
206
function getCert()
207
{
208
    $log = new Loggit();
209
210
    // Verify that a non-empty certreq <form> variable was posted
211
    $certreq = Util::getPostVar('certreq');
212
    if (strlen($certreq) == 0) {
213
        $log->info('ECP certreq error: Missing certificate request.');
214
        outputError('Missing certificate request.');
215
        return; // ERROR means no further processing is necessary
216
    }
217
218
    getUID(); // Get the user's database user ID, put info in PHP session
219
220
    $skin = Util::getSkin();
221
    $skin->init(); // Check for forced skin
222
223
    // If 'status' is not STATUS_OK*, then return error message
224
    if (Util::getSessionVar('status') & 1) { // Bad status codes are odd
225
        $errstr = array_search(Util::getSessionVar('status'), DBService::$STATUS);
226
        $log->info('ECP certreq error: ' . $errstr . '.');
227
        outputError($errstr);
228
        Util::unsetAllUserSessionVars();
229
        return; // ERROR means no further processing is necessary
230
    }
231
    //
232
    // Verify myproxy-logon binary is configured
233
    $disabledbyconf = ((!defined('MYPROXY_LOGON')) || (empty(MYPROXY_LOGON)));
234
    if ($disabledbyconf) {
235
        $log->info('ECP certreq error: Downloading certificates is ' .
236
            'disabled due to myproxy-logon not configured.');
237
        outputError('Downloading certificates is disabled.');
238
        Util::unsetAllUserSessionVars();
239
        return; // ERROR means no further processing is necessary
240
    }
241
242
    $shibarray = Util::getIdpList()->getShibInfo();
243
    if (Util::isEduGAINAndGetCert(@$shibarray['Identity Provider'], @$shibarray['Organization Name'])) {
244
        $log->info('ECP certreq error: Failed to get cert due to eduGAIN IdP restriction.');
245
        outputError('Failed to get cert due to eduGAIN IdP restriction.');
246
        return; // ERROR means no further processing is necessary
247
    }
248
249
    // Get the certificate lifetime. Set to a default value if not set.
250
    $certlifetime = (int)(Util::getPostVar('certlifetime'));
251
    if ($certlifetime == 0) {  // If not specified, set to default value
252
        $defaultlifetime = $skin->getConfigOption('ecp', 'defaultlifetime');
253
        if ((!is_null($defaultlifetime)) && ((int)$defaultlifetime > 0)) {
254
            $certlifetime = (int)$defaultlifetime;
255
        } else {
256
            $certlifetime = MyProxy::getDefaultLifetime();
257
        }
258
    }
259
260
    // Make sure lifetime is within acceptable range. 277 hrs = 1000000 secs.
261
    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...
262
    if ($certlifetime < $minlifetime) {
263
        $certlifetime = $minlifetime;
264
    } elseif ($certlifetime > $maxlifetime) {
265
        $certlifetime = $maxlifetime;
266
    }
267
268
    // Make sure that the user's MyProxy username is available.
269
    $dn = Util::getSessionVar('dn');
270
    if (strlen($dn) > 0) {
271
        // Append extra info, such as 'skin', to be processed by MyProxy.
272
        $skin->setMyProxyInfo();
273
        $myproxyinfo = Util::getSessionVar('myproxyinfo');
274
        if (strlen($myproxyinfo) > 0) {
275
            $dn .= " $myproxyinfo";
276
        }
277
        // Attempt to fetch a credential from the MyProxy server
278
        $cert = MyProxy::getMyProxyCredential(
279
            $dn,
280
            '',
281
            MYPROXY_HOST,
282
            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...
283
            $certlifetime,
284
            '/var/www/config/hostcred.pem',
285
            '',
286
            $certreq
287
        );
288
289
        if (strlen($cert) > 0) { // Successfully got a certificate!
290
            $log->info('ECP getcert success!');
291
            // CIL-507 Special log message for XSEDE
292
            $log->info('USAGE email="' . Util::getSessionVar('emailaddr') .
293
                       '" client="ECP"');
294
            header('Content-type: text/plain');
295
            echo $cert;
296
        } else { // The myproxy-logon command failed - shouldn't happen!
297
            $log->info('ECP certreq error: MyProxy unable to create certificate.');
298
            outputError('Error! MyProxy unable to create certificate.');
299
        }
300
    } else { // Couldn't find the 'dn' PHP session value - shouldn't happen!
301
        $log->info('ECP certreq error: Missing \'dn\' session value.');
302
        outputError('Missing username. Please enable cookies.');
303
    }
304
}
305
306
/**
307
 * outputError
308
 *
309
 * This function sets the HTTP return type to 'text/plain' and also
310
 * sets the HTTP return code to 400, meaning there was an error of
311
 * some kind.  If there is also a passed in errstr, that is output as
312
 * the body of the HTTP return.
313
 * @param string $errstr (Optional) The error string to print in the
314
 *        text/plain return body.
315
 */
316
function outputError($errstr = '')
317
{
318
    header('Content-type: text/plain', true, 400);
319
    if (strlen($errstr) > 0) {
320
        echo $errstr;
321
    }
322
}
323