This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /** |
||
4 | * /updateidplist/ |
||
5 | * |
||
6 | * The '/updateidplist/' endpoint updates the CILogon idplist.xml and |
||
7 | * idplist.json files. These are 'pared down' versions of the IdP-specific |
||
8 | * InCommon-metadata.xml file, extracting just the useful portions of XML |
||
9 | * for display on CILogon. This endpoint downloads the InCommon metadata and |
||
10 | * creates both idplist.xml and idplist.json. It then looks for existing |
||
11 | * idplist.{json,xml} files and sees if there are any differences. If so, |
||
12 | * it prints out the differences and sends email. It also checks for newly |
||
13 | * added IdPs and sends email. Finally, it copies the newly created idplist |
||
14 | * files to the old location. |
||
15 | */ |
||
16 | |||
17 | // error_reporting(E_ALL); ini_set('display_errors',1); |
||
18 | |||
19 | require_once __DIR__ . '/../vendor/autoload.php'; |
||
20 | require_once __DIR__ . '/../config.php'; |
||
21 | include_once __DIR__ . '/../config.secrets.php'; |
||
22 | |||
23 | use CILogon\Service\Util; |
||
24 | use CILogon\Service\Content; |
||
25 | use CILogon\Service\IdpList; |
||
26 | |||
27 | Util::startPHPSession(); |
||
28 | |||
29 | // Use a semaphore to prevent multiple processes running at the same time |
||
30 | $idplist_dir = dirname(DEFAULT_IDP_JSON); |
||
31 | $last_checked = $idplist_dir . '/.last_checked'; |
||
32 | $key = ftok($last_checked, '1'); |
||
33 | $semaphore = sem_get($key, 1); |
||
34 | if (@sem_acquire($semaphore, 1) === false) { |
||
35 | echo "<p>Another process is running.</p>\n"; |
||
36 | return; |
||
37 | } |
||
38 | |||
39 | // Declare a few configuration constants |
||
40 | $mailto = EMAIL_ALERTS; |
||
41 | $mailtoidp = defined('EMAIL_IDP_UPDATES') ? |
||
42 | EMAIL_ALERTS . ',' . EMAIL_IDP_UPDATES : ''; |
||
43 | $mailfrom = 'From: ' . EMAIL_ALERTS . "\r\n" . 'X-Mailer: PHP/' . phpversion(); |
||
44 | $check_timeout = 300; // in seconds |
||
45 | $httphost = Util::getHN(); |
||
46 | |||
47 | // Load the '.last_checked' file and find the last time the endpoint |
||
48 | // was hit. If the file doesn't exist, then this is the first time. |
||
49 | // If the last time checked is less than a timeout, do nothing. |
||
50 | $lastcheck = file_get_contents($last_checked); |
||
51 | $difftime = abs(time() - (int)$lastcheck); |
||
52 | if ($difftime < $check_timeout) { |
||
53 | echo "<p>Please wait " . ($check_timeout - $difftime) . " seconds.</p>\n"; |
||
54 | return; |
||
55 | } |
||
56 | |||
57 | // Download InCommon metadata to a new temporary directory in /tmp/. |
||
58 | // Be sure to delete the temporary directory before script exit. |
||
59 | $incommon_url = 'https://mdq.incommon.org/entities/idps/all'; |
||
60 | $tmpdir = ''; |
||
61 | $tmpincommon = ''; |
||
62 | if (($incommon_xml = file_get_contents($incommon_url)) === false) { |
||
63 | $errmsg = "Error: Unable to download InCommon-metadata.xml."; |
||
64 | echo "<p>$errmsg</p>\n"; |
||
65 | mail($mailto, "/updateidplist/ failed on $httphost", $errmsg, $mailfrom); |
||
66 | http_response_code(500); |
||
67 | return; |
||
68 | } else { |
||
69 | $tmpdir = Util::tempDir('/tmp/'); |
||
70 | $tmpincommon = $tmpdir . '/InCommon-metadata.xml'; |
||
71 | if ((file_put_contents($tmpincommon, $incommon_xml)) === false) { |
||
72 | $errmsg = "Error: Unable to save InCommon-metadata.xml to temporary directory."; |
||
73 | echo "<p>$errmsg</p>\n"; |
||
74 | mail($mailto, "/updateidplist/ failed on $httphost", $errmsg, $mailfrom); |
||
75 | http_response_code(500); |
||
76 | Util::deleteDir($tmpdir); |
||
77 | return; |
||
78 | } |
||
79 | } |
||
80 | |||
81 | // Now, create new idplist.xml and idplist.json files from the |
||
82 | // InCommon Metadata. |
||
83 | $tmpxml = $tmpdir . '/idplist.xml'; |
||
84 | $idplist = new IdpList($tmpxml, $tmpincommon, false, 'xml'); |
||
85 | $idplist->create(); |
||
86 | if (!$idplist->write('xml')) { |
||
0 ignored issues
–
show
|
|||
87 | $errmsg = "Error: Unable to create temporary idplist.xml file."; |
||
88 | echo "<p>$errmsg</p>\n"; |
||
89 | mail($mailto, "/updateidplist/ failed on $httphost", $errmsg, $mailfrom); |
||
90 | http_response_code(500); |
||
91 | Util::deleteDir($tmpdir); |
||
92 | return; |
||
93 | } |
||
94 | $tmpjson = $tmpdir . '/idplist.json'; |
||
95 | $idplist->setFilename($tmpjson); |
||
96 | if (!$idplist->write('json')) { |
||
97 | $errmsg = "Error: Unable to create temporary idplist.json file."; |
||
98 | echo "<p>$errmsg</p>\n"; |
||
99 | mail($mailto, "/updateidplist/ failed on $httphost", $errmsg, $mailfrom); |
||
100 | http_response_code(500); |
||
101 | Util::deleteDir($tmpdir); |
||
102 | return; |
||
103 | } |
||
104 | |||
105 | // Try to read in an existing idplist.xml file so we can do a 'diff' later. |
||
106 | $idpxml_filename = preg_replace('/\.json$/', '.xml', DEFAULT_IDP_JSON); |
||
107 | $oldidplist = new IdpList($idpxml_filename, '', false, 'xml'); |
||
108 | |||
109 | // If we successfully read in an existing idplist.xml file, |
||
110 | // check for differences, and also look for newly added IdPs. |
||
111 | $oldidplistempty = true; |
||
112 | $oldidplistdiff = false; |
||
113 | $newidpemail = ''; |
||
114 | if (!empty($oldidplist->idparray)) { |
||
115 | $oldidplistempty = false; |
||
116 | |||
117 | // Check for differences using weird json_encode method found at |
||
118 | // https://stackoverflow.com/a/42530586/12381604 |
||
119 | $diffarray = array_map( |
||
120 | 'json_decode', |
||
121 | array_merge( |
||
122 | array_diff( |
||
123 | array_map('json_encode', $idplist->idparray), |
||
124 | array_map('json_encode', $oldidplist->idparray) |
||
125 | ), |
||
126 | array_diff( |
||
127 | array_map('json_encode', $oldidplist->idparray), |
||
128 | array_map('json_encode', $idplist->idparray) |
||
129 | ) |
||
130 | ) |
||
131 | ); |
||
132 | |||
133 | if (!empty($diffarray)) { |
||
134 | $oldidplistdiff = true; |
||
135 | |||
136 | // Check to see if any new IdPs were added to the InCommon metadata. |
||
137 | $newIdPList = array(); |
||
138 | $oldEntityIDList = $oldidplist->getEntityIDs(); |
||
139 | if (!empty($oldEntityIDList)) { |
||
140 | $entityIDList = $idplist->getEntityIDs(); |
||
141 | foreach ($entityIDList as $value) { |
||
142 | if (!in_array($value, $oldEntityIDList)) { |
||
143 | $newIdPList[$value] = 1; |
||
144 | } |
||
145 | } |
||
146 | } |
||
147 | |||
148 | // If we found some new InCommon metadata entries, save them in a |
||
149 | // string to be sent to [email protected]. |
||
150 | if (!empty($newIdPList)) { |
||
151 | $plural = (count($newIdPList) > 1); |
||
152 | $newidpemail .= ($plural ? 'New' : 'A new') . ' Identity Provider' . |
||
153 | ($plural ? 's were' : ' was') . ' found in metadata ' . |
||
154 | "and added to the \nlist of available IdPs.\n" . |
||
155 | '--------------------------------------------------------------' . |
||
156 | "\n\n"; |
||
157 | foreach ($newIdPList as $entityID => $value) { |
||
158 | $newidpemail .= "EntityId = $entityID\n"; |
||
159 | $newidpemail .= "Organization Name = " . |
||
160 | $idplist->getOrganizationName($entityID) . "\n"; |
||
161 | $newidpemail .= "Display Name = " . |
||
162 | $idplist->getDisplayName($entityID) . "\n"; |
||
163 | if ($idplist->isRegisteredByInCommon($entityID)) { |
||
164 | $newidpemail .= "Registered by InCommon = Yes\n"; |
||
165 | } |
||
166 | if ($idplist->isInCommonRandS($entityID)) { |
||
167 | $newidpemail .= "InCommon R & S = Yes\n"; |
||
168 | } |
||
169 | if ($idplist->isREFEDSRandS($entityID)) { |
||
170 | $newidpemail .= "REFEDS R & S = Yes\n"; |
||
171 | } |
||
172 | if ($idplist->isSIRTFI($entityID)) { |
||
173 | $newidpemail .= "SIRTFI = Yes\n"; |
||
174 | } |
||
175 | $newidpemail .= "\n"; |
||
176 | } |
||
177 | } |
||
178 | } |
||
179 | } |
||
180 | |||
181 | // If we found new IdPs, print them out and send email (if on prod). |
||
182 | if (strlen($newidpemail) > 0) { |
||
183 | echo "<xmp>\n"; |
||
184 | echo $newidpemail; |
||
185 | echo "</xmp>\n"; |
||
186 | |||
187 | if (strlen($mailtoidp) > 0) { |
||
188 | // Send "New IdPs Added" email only from production server |
||
189 | if ( |
||
190 | ($httphost == 'cilogon.org') || |
||
191 | ($httphost == 'polo1.cilogon.org') |
||
192 | ) { |
||
193 | mail( |
||
194 | $mailtoidp, |
||
195 | "CILogon Service on $httphost - New IdP Automatically Added", |
||
196 | $newidpemail, |
||
197 | $mailfrom |
||
198 | ); |
||
199 | } |
||
200 | } |
||
201 | } |
||
202 | |||
203 | // If other differences were found, do an actual 'diff' and send email. |
||
204 | if ($oldidplistdiff) { |
||
205 | $idpdiff = `diff -u $idpxml_filename $tmpxml 2>&1`; |
||
206 | echo "<xmp>\n\n"; |
||
207 | echo $idpdiff; |
||
208 | echo "</xmp>\n"; |
||
209 | |||
210 | mail( |
||
211 | $mailto, |
||
212 | "idplist.xml changed on $httphost", |
||
213 | "idplist.xml changed on $httphost\n\n" . $idpdiff, |
||
214 | $mailfrom |
||
215 | ); |
||
216 | } |
||
217 | |||
218 | // Copy temporary idplist.{json,xml} files to production directory. |
||
219 | if ($oldidplistempty || $oldidplistdiff) { |
||
220 | if (copy($tmpxml, $idplist_dir . '/idplist.xml')) { |
||
221 | chmod($idpxml_filename, 0664); |
||
222 | chgrp($idpxml_filename, 'apache'); |
||
223 | } else { |
||
224 | $errmsg = "Error: Unable to copy idplist.xml to destination."; |
||
225 | echo "<p>$errmsg</p>\n"; |
||
226 | mail($mailto, "/updateidplist/ failed on $httphost", $errmsg, $mailfrom); |
||
227 | http_response_code(500); |
||
228 | Util::deleteDir($tmpdir); |
||
229 | return; |
||
230 | } |
||
231 | if (copy($tmpjson, $idplist_dir . '/idplist.json')) { |
||
232 | chmod(DEFAULT_IDP_JSON, 0664); |
||
233 | chgrp(DEFAULT_IDP_JSON, 'apache'); |
||
234 | } else { |
||
235 | $errmsg = "Error: Unable to copy idplist.json to destination."; |
||
236 | echo "<p>$errmsg</p>\n"; |
||
237 | mail($mailto, "/updateidplist/ failed on $httphost", $errmsg, $mailfrom); |
||
238 | http_response_code(500); |
||
239 | Util::deleteDir($tmpdir); |
||
240 | return; |
||
241 | } |
||
242 | |||
243 | if ($oldidplistempty) { |
||
244 | echo "<h3>New idplist.{json,xml} files were created.</h3>\n"; |
||
245 | } else { |
||
246 | echo "<h3>Existing idplist.{json,xml} files were updated.</h3>\n"; |
||
247 | } |
||
248 | } else { |
||
249 | echo "<p>No change detected in InCommon metadata.</p>\n"; |
||
250 | } |
||
251 | |||
252 | // Final clean up. Delete the tempdir for the InCommon-metadata.xml and |
||
253 | // write the current time to .last_checked. |
||
254 | Util::deleteDir($tmpdir); |
||
255 | file_put_contents($last_checked, time()); |
||
256 | @sem_release($semaphore); |
||
0 ignored issues
–
show
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.
If you suppress an error, we recommend checking for the error condition explicitly: // For example instead of
@mkdir($dir);
// Better use
if (@mkdir($dir) === false) {
throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
![]() |
|||
257 |
If an expression can have both
false
, andnull
as possible values. It is generally a good practice to always use strict comparison to clearly distinguish between those two values.