PluginProbe ʕ •ᴥ•ʔ
NinjaFirewall (WP Edition) – Advanced Security Plugin and Firewall / 4.9
NinjaFirewall (WP Edition) – Advanced Security Plugin and Firewall v4.9
4.9 4.8.8 4.8.7 4.8.6 trunk 4.5 4.5.1 4.5.10 4.5.11 4.5.2 4.5.3 4.5.4 4.5.5 4.5.6 4.5.7 4.5.8 4.5.9 4.6 4.6.1 4.7 4.7.1 4.7.2 4.7.3 4.7.4 4.7.5 4.8 4.8.1 4.8.2 4.8.3 4.8.4 4.8.5
ninjafirewall / lib / settings_monitoring_file_check.php
ninjafirewall / lib Last commit date
share 9 years ago .htaccess 11 years ago anti_malware.php 5 years ago class-api.php 4 weeks ago class-centralised-logging.php 4 weeks ago class-coupon.php 7 months ago class-email-sodium.php 4 weeks ago class-firewall-log.php 4 weeks ago class-helpers.php 9 months ago class-import-export.php 5 months ago class-ip.php 5 months ago class-nfw-database.php 7 months ago class-plugin-upgrade.php 4 weeks ago class-security-updates.php 4 weeks ago class-session.php 4 weeks ago class_mail.php 4 weeks ago firewall.php 4 weeks ago fw_fileguard.php 5 months ago fw_livelog.php 1 year ago help.php 4 weeks ago helpers.php 4 weeks ago i18n-extra.php 4 weeks ago i18n.php 1 year ago index.html 13 years ago init_update.php 2 years ago install.php 1 year ago install_default.php 4 weeks ago loader.php 7 months ago mail_template_firewall.php 1 year ago mail_template_plugin.php 4 weeks ago scheduled_tasks.php 3 years ago settings_dashboard.php 4 weeks ago settings_dashboard_about.php 4 weeks ago settings_dashboard_statistics.php 2 months ago settings_event_notifications.php 4 weeks ago settings_events.php 2 months ago settings_firewall_options.php 2 months ago settings_firewall_policies.php 4 weeks ago settings_login_protection.php 2 months ago settings_logs.php 4 weeks ago settings_logs_firewall_log.php 4 weeks ago settings_logs_live_log.php 2 months ago settings_monitoring.php 4 weeks ago settings_monitoring_file_check.php 2 months ago settings_monitoring_file_guard.php 2 months ago settings_network.php 2 months ago settings_security_rules.php 2 months ago settings_security_rules_editor.php 4 weeks ago settings_security_rules_update.php 4 weeks ago sign.pub 7 years ago thickbox.php 4 years ago widget.php 3 years ago wpplus.php 5 months ago
settings_monitoring_file_check.php
813 lines
1 <?php
2 /*
3 +=====================================================================+
4 | _ _ _ _ _____ _ _ _ |
5 | | \ | (_)_ __ (_) __ _| ___(_)_ __ _____ ____ _| | | |
6 | | \| | | '_ \ | |/ _` | |_ | | '__/ _ \ \ /\ / / _` | | | |
7 | | |\ | | | | || | (_| | _| | | | | __/\ V V / (_| | | | |
8 | |_| \_|_|_| |_|/ |\__,_|_| |_|_| \___| \_/\_/ \__,_|_|_| |
9 | |__/ |
10 | (c) NinTechNet Limited ~ https://nintechnet.com/ |
11 +=====================================================================+
12 */
13
14 if (! defined('NFW_ENGINE_VERSION') ) {
15 die('Forbidden');
16 }
17
18 $log_dir = NFW_LOG_DIR . '/nfwlog/cache/';
19 $nfmon_snapshot = $log_dir . 'nfilecheck_snapshot.php';
20 $nfmon_diff = $log_dir . 'nfilecheck_diff.php';
21 $err = '';
22 $success = '';
23
24 // Scheduled scan ?
25 if (defined('NFSCANDO') ) {
26
27 $snapproc = nf_fc_metrics('start');
28 $err = nf_sub_monitoring_scan($nfmon_snapshot, $nfmon_diff );
29 if (! empty( $err ) ) {
30 nfw_log_error( $err );
31 }
32 $nfw_options = nfw_get_option('nfw_options');
33 if (empty($nfw_options['enabled']) ) { return; }
34 $nfw_options['snapproc'] = nf_fc_metrics('stop', $snapproc );
35 nfw_update_option('nfw_options', $nfw_options);
36
37 // Changes detected :
38 if (! $err && file_exists($nfmon_diff) ) {
39 nf_scan_email($nfmon_diff, $log_dir);
40 // No changes detected :
41 } else {
42 // Always send a report after a scan ?
43 if (! empty($nfw_options['report_scan']) ) {
44 nf_scan_email(0, 0);
45 }
46 }
47 return;
48 }
49
50 // Block immediately if user is not allowed :
51 nf_not_allowed( 'block', __LINE__ );
52
53 if (! empty($_REQUEST['nfw_act'])) {
54 if ( empty($_POST['nfwnonce']) || ! wp_verify_nonce($_POST['nfwnonce'], 'filecheck_save') ) {
55 wp_nonce_ays('filecheck_save');
56 }
57 if ( $_REQUEST['nfw_act'] == 'create') {
58 if (! $err = nf_sub_monitoring_create($nfmon_snapshot) ) {
59 $success = __('Snapshot successfully created.', 'ninjafirewall');
60 if (file_exists($nfmon_diff) ) {
61 unlink($nfmon_diff);
62 }
63 }
64 } elseif ( $_REQUEST['nfw_act'] == 'delete') {
65 // Delete de current snapshot file :
66 if (file_exists($nfmon_snapshot) ) {
67 unlink ($nfmon_snapshot);
68 $success = __('Snapshot file successfully deleted.', 'ninjafirewall');
69 // Remove old diff file as well :
70 if ( file_exists($nfmon_diff . '.php') ) {
71 unlink($nfmon_diff . '.php');
72 }
73 // Clear scheduled scan (if any) and its options :
74 if ( wp_next_scheduled('nfscanevent') ) {
75 wp_clear_scheduled_hook('nfscanevent');
76 }
77 $nfw_options = nfw_get_option('nfw_options');
78 $nfw_options['report_scan'] = 0;
79 $nfw_options['sched_scan'] = 0;
80 nfw_update_option('nfw_options', $nfw_options);
81 }
82 } elseif ( $_REQUEST['nfw_act'] == 'scan') {
83 // Scan disk for changes :
84 if (! file_exists($nfmon_snapshot) ) {
85 $err = __('You must create a snapshot first.', 'ninjafirewall');
86 } else {
87
88 $snapproc = nf_fc_metrics('start');
89 $err = nf_sub_monitoring_scan($nfmon_snapshot, $nfmon_diff);
90 if (! empty( $err ) ) {
91 nfw_log_error( $err );
92 }
93 $nfw_options = nfw_get_option('nfw_options');
94 $nfw_options['snapproc'] = nf_fc_metrics('stop', $snapproc );
95 nfw_update_option('nfw_options', $nfw_options);
96
97 if (! $err) {
98 if (file_exists($nfmon_diff) ) {
99 $err = __('NinjaFirewall detected that changes were made to your files.', 'ninjafirewall');
100 $changes = 1;
101 } else {
102 $success = __('No changes detected.', 'ninjafirewall');
103 }
104 }
105 }
106 } elseif ( $_REQUEST['nfw_act'] == 'scheduled') {
107 nf_scheduled_scan();
108 $success = __('Your changes have been saved.', 'ninjafirewall');
109 }
110 }
111
112 $nfw_options = nfw_get_option('nfw_options');
113
114 if ( empty($nfw_options['snapdir']) ) {
115 $nfw_options['snapdir'] = '';
116 if ( file_exists($nfmon_snapshot) ) {
117 unlink($nfmon_snapshot);
118 }
119 }
120 if (! isset($nfw_options['snapexclude']) ) {
121 $nfw_options['snapexclude'] = '/'. basename(WP_CONTENT_DIR) .'/nfwlog/';
122 if ( is_dir( WP_CONTENT_DIR .'/ninjascanner/' ) ) {
123 $nfw_options['snapexclude'] .= ',/'. basename(WP_CONTENT_DIR) .'/ninjascanner/';
124 }
125 }
126
127
128 if ( $err ) {
129 echo '<div class="error notice is-dismissible"><p>' . $err . '</p></div>';
130 } elseif ( $success ) {
131 echo '<div class="updated notice is-dismissible"><p>' . $success . '</p></div>';
132 }
133
134 // If we don't have a snapshopt, offer to create one :
135 if (! file_exists($nfmon_snapshot) ) {
136 ?>
137 <div class="nfw-notice nfw-notice-orange">
138 <p><?php _e('File Check lets you perform file integrity monitoring upon request or on a specific interval. To start, create a snapshot of your files by clicking the button below.', 'ninjafirewall' ) ?></p>
139 </div>
140
141 <form method="post" name="monitor_form">
142 <?php wp_nonce_field('filecheck_save', 'nfwnonce', 0); ?>
143 <table class="form-table nfw-table">
144 <tr>
145 <th scope="row" class="row-med"><?php _e('Create a snapshot of all files stored in that directory', 'ninjafirewall') ?></th>
146 <td><input class="large-text" type="text" name="snapdir" value="<?php
147 if (! empty($nfw_options['snapdir']) ) {
148 echo htmlspecialchars($nfw_options['snapdir']);
149 } else {
150 echo htmlspecialchars(ABSPATH);
151 }
152 ?>" required />
153 <p class="description"><?php printf( __('Default: %s', 'ninjafirewall'), htmlentities( rtrim( ABSPATH, '/\\ ' ) ) ) ?></p>
154 </td>
155 </tr>
156
157 <tr>
158 <th scope="row" class="row-med"><?php _e('Exclude the following files/folders (optional)', 'ninjafirewall') ?></th>
159 <td><input class="large-text" type="text" name="snapexclude" value="<?php echo htmlentities($nfw_options['snapexclude']); ?>" placeholder="<?php _e('e.g.,', 'ninjafirewall') ?> /wp-content/nfwlog/" maxlength="255"><br /><p class="description"><?php _e('Full or partial case-sensitive string(s). Multiple values must be comma-separated', 'ninjafirewall') ?> (<code>,</code>).</p></td>
160 </tr>
161
162 <tr>
163 <th scope="row" class="row-med">&nbsp;</th>
164 <td>
165 <label><input type="checkbox" name="snapnoslink" value="1" checked="checked" /><?php _e('Do not follow symbolic links (default)', 'ninjafirewall') ?></label>
166 </td>
167 </tr>
168
169 </table>
170 <input type="hidden" name="nfw_act" value="create" />
171 <p><input type="submit" class="button-primary" value="<?php _e('Create Snapshot', 'ninjafirewall') ?>" /></p>
172 <input type="hidden" name="tab" value="filecheck" />
173 </form>
174 <?php
175 return;
176 }
177
178 // We have a snapshot :
179 $stat = stat($nfmon_snapshot);
180 $count = -2;
181 $fh = fopen($nfmon_snapshot, 'r');
182 while (! feof($fh) ) {
183 fgets($fh);
184 ++$count;
185 }
186 fclose($fh);
187 // Look for new/mod/del files :
188 $res = $new_file = $del_file = $mod_file = array();
189 // If no changes were detected, we display the last ones (if any) :
190 if (! file_exists($nfmon_diff) && file_exists($nfmon_diff . '.php') ) {
191 $nfmon_diff = $nfmon_diff . '.php';
192 }
193 if (file_exists($nfmon_diff) ) {
194 $fh = fopen($nfmon_diff, 'r');
195 while (! feof($fh) ) {
196 $res = explode('::', fgets($fh) );
197 if ( empty($res[1]) ) { continue; }
198 // New file :
199 if ($res[1] == 'N') {
200 $s_tmp = explode(':', rtrim($res[2]));
201 $new_file[$res[0]] = $s_tmp[0] .':'.
202 $s_tmp[1] .':'.
203 $s_tmp[2] .':'.
204 $s_tmp[3] .':'.
205 date('Y-m-d H~i~s O', $s_tmp[4]) .':'.
206 date('Y-m-d H~i~s O', $s_tmp[5]);
207 // Deleted file :
208 } elseif ($res[1] == 'D') {
209 $del_file[$res[0]] = 1;
210 // Modified file:
211 } elseif ($res[1] == 'M') {
212 $s_tmp = explode(':', $res[2]);
213 $mod_file[$res[0]] = $s_tmp[0] .':'.
214 $s_tmp[1] .':'.
215 $s_tmp[2] .':'.
216 $s_tmp[3] .':'.
217 date('Y-m-d H~i~s O', $s_tmp[4]) .':'.
218 date('Y-m-d H~i~s O', $s_tmp[5]) .'::';
219 $s_tmp = explode(':', rtrim($res[3]));
220 $mod_file[$res[0]] .= $s_tmp[0] .':'.
221 $s_tmp[1] .':'.
222 $s_tmp[2] .':'.
223 $s_tmp[3] .':'.
224 date('Y-m-d H~i~s O', $s_tmp[4]) .':'.
225 date('Y-m-d H~i~s O', $s_tmp[5]);
226 }
227 }
228 fclose($fh);
229 $mod = 1;
230 } else {
231 $mod = 0;
232 }
233 ?>
234 <table class="form-table nfw-table">
235 <tr>
236 <th scope="row" class="row-med"><?php _e('Last snapshot', 'ninjafirewall') ?></th>
237 <td>
238 <p><?php printf( __('Created on: %s', 'ninjafirewall'), date_i18n('M d, Y @ H:i:s O', $stat['ctime'])); ?></p>
239 <p><?php printf( __('Total files: %s ', 'ninjafirewall'), number_format_i18n($count) ); ?></p>
240
241 <p><?php _e('Directory:', 'ninjafirewall') ?> <code><?php echo htmlspecialchars($nfw_options['snapdir']) ?></code></p>
242 <?php
243 if (! empty($nfw_options['snapexclude']) ) {
244 $res = @explode(',', $nfw_options['snapexclude']);
245 echo '<p>' . __('Exclusion:', 'ninjafirewall') . ' ';
246 foreach ($res as $exc) {
247 echo '<code>' . htmlspecialchars($exc) . '</code>&nbsp;';
248 }
249 echo '</p>';
250 }
251 echo '<p>' . __('Symlinks:', 'ninjafirewall') . ' ';
252 if ( empty($nfw_options['snapnoslink']) ) {
253 echo __('follow', 'ninjafirewall');
254 } else {
255 echo __('do not follow', 'ninjafirewall');
256 }
257 echo '</p>';
258 if (! empty($nfw_options['snapproc']) ) {
259 echo '<p>' . sprintf( __('Processing time: %s seconds', 'ninjafirewall'), $nfw_options['snapproc']) . '</p>';
260 }
261 ?>
262 <form method="post">
263 <?php wp_nonce_field('filecheck_save', 'nfwnonce', 0); ?>
264 <p><input type="submit" name="dlsnap" value="<?php _e('Download Snapshot', 'ninjafirewall') ?>" class="button-secondary" />&nbsp;&nbsp;&nbsp;<input type="submit" class="button-secondary" onClick="return nfwjs_del_snapshot();" value="<?php _e('Delete Snapshot', 'ninjafirewall') ?>" /><input type="hidden" name="nfw_act" value="delete" /></p>
265 <input type="hidden" name="tab" value="filecheck" />
266 </form>
267 </td>
268 </tr>
269 <tr>
270 <th scope="row" class="row-med"><?php _e('Last changes', 'ninjafirewall') ?></th>
271 <td>
272
273 <?php
274 // Show info about last changes, if any :
275 if ($mod) {
276 ?>
277 <p><?php printf( __('New files: %s', 'ninjafirewall'), count($new_file) ) ?></p>
278 <p><?php printf( __('Deleted files: %s', 'ninjafirewall'), count($del_file) ) ?></p>
279 <p><?php printf( __('Modified files: %s', 'ninjafirewall'), count($mod_file) ) ?></p>
280
281 <form method="post">
282 <?php wp_nonce_field('filecheck_save', 'nfwnonce', 0); ?>
283 <p><input type="button" value="<?php _e('View Changes', 'ninjafirewall') ?>" onClick="nfwjs_show_changes();" class="button-secondary" id="vcbtn" <?php
284 if (! empty($changes)) {
285 echo 'disabled="disabled" ';
286 }
287 ?>/>&nbsp;&nbsp;&nbsp;<input type="submit" name="dlmods" value="<?php _e('Download Changes', 'ninjafirewall') ?>" class="button-secondary" /></p>
288 </form>
289 <br />
290 <?php
291 if (empty($changes)) {
292 echo '<div id="changes_table" style="display:none">';
293 } else {
294 echo '<div id="changes_table">';
295 }
296
297 echo '<table border="0" width="100%">';
298
299 $more_info = __('Click a file to get more info about it.', 'ninjafirewall');
300 if ($new_file) {
301 echo '<tr><td>';
302 echo __('New files:', 'ninjafirewall') . ' ' . count($new_file). '<br />';
303 echo '<select id="select-1" name="sometext" multiple="multiple" style="min-width:100%;width:100%;height:150px" onchange="nfwjs_file_info(this.value, 1);">';
304 foreach($new_file as $k => $v) {
305 echo '<option value="' . htmlspecialchars($v) . '" title="' . htmlspecialchars($k) . '">' . htmlspecialchars($k) . '</option>';
306 }
307 echo'</select>
308 <p class="description">' . $more_info . '</p>
309 <table id="table_new" style="width:100%;background-color:#F7F7F7;border:solid 1px #DFDFDF;display:none;">
310 <tr>
311 <th style="padding:2px;width:25%;">' . __('Size', 'ninjafirewall') .'</th>
312 <td style="padding:2px" id="new_size"></td>
313 </tr>
314 <tr>
315 <th style="padding:2px;width:25%;">' . __('Access', 'ninjafirewall') .'</th>
316 <td style="padding:2px" id="new_chmod"></td>
317 </tr>
318 <tr>
319 <th style="padding:2px;width:25%;">' . __('Uid / Gid', 'ninjafirewall') .'</th>
320 <td style="padding:2px" id="new_uidgid"></td>
321 </tr>
322 <tr>
323 <th style="padding:2px;width:25%;">' . __('Modify', 'ninjafirewall') .'</th>
324 <td style="padding:2px" id="new_mtime"></td>
325 </tr>
326 <tr>
327 <th style="padding:2px;width:25%;">' . __('Change', 'ninjafirewall') .'</th>
328 <td style="padding:2px" id="new_ctime"></td>
329 </tr>
330 </table>
331 </td></tr>';
332
333 }
334 if ($del_file) {
335 echo '
336 <tr>
337 <td>' . __('Deleted files:', 'ninjafirewall') .' '. count($del_file). '<br />' .
338 '<select name="sometext" multiple="multiple" style="min-width:100%;width:100%;height:150px">';
339 foreach($del_file as $k => $v) {
340 echo '<option title="' . htmlspecialchars($k) . '">' . htmlspecialchars($k) . '</option>';
341 }
342 echo'</select>
343 </td>
344 </tr>';
345
346 }
347 if ($mod_file) {
348 echo '
349 <tr>
350 <td>' . __('Modified files:', 'ninjafirewall') .' '. count($mod_file). '<br />' .
351 '<select id="select-2" name="sometext" multiple="multiple" style="min-width:100%;width:100%;height:150px" onchange="nfwjs_file_info(this.value, 2);">';
352 foreach($mod_file as $k => $v) {
353 echo '<option value="' . htmlspecialchars($v) . '" title="' . htmlspecialchars($k) . '">' . htmlspecialchars($k) . '</option>';
354 }
355 echo'</select>
356 <p class="description">' . $more_info . '</p>
357 <table id="table_mod" style="width:100%;background-color:#F7F7F7;border:solid 1px #DFDFDF;display:none;">
358 <tr>
359 <th style="padding:2px;width:25%;">&nbsp;</th>
360 <td style="padding:2px"><b>' . __('Old', 'ninjafirewall') .'</b></td>
361 <td style="padding:2px"><b>' . __('New', 'ninjafirewall') .'</b></td>
362 </tr>
363 <tr>
364 <th style="padding:2px;width:25%;">' . __('Size', 'ninjafirewall') .'</th>
365 <td style="padding:2px" id="mod_size"></td>
366 <td style="padding:2px" id="mod_size2"></td>
367 </tr>
368 <tr>
369 <th style="padding:2px;width:25%;">' . __('Access', 'ninjafirewall') .'</th>
370 <td style="padding:2px" id="mod_chmod"></td>
371 <td style="padding:2px" id="mod_chmod2"></td>
372 </tr>
373 <tr>
374 <th style="padding:2px;width:25%;">' . __('Uid / Gid', 'ninjafirewall') .'</th>
375 <td style="padding:2px" id="mod_uidgid"></td>
376 <td style="padding:2px" id="mod_uidgid2"></td>
377 </tr>
378 <tr>
379 <th style="padding:2px;width:25%;">' . __('Modify', 'ninjafirewall') .'</th>
380 <td style="padding:2px" id="mod_mtime"></td>
381 <td style="padding:2px" id="mod_mtime2"></td>
382 </tr>
383 <tr>
384 <th style="padding:2px;width:25%;">' . __('Change', 'ninjafirewall') .'</th>
385 <td style="padding:2px" id="mod_ctime"></td>
386 <td style="padding:2px" id="mod_ctime2"></td>
387 </tr>
388 </table>
389 </td>
390 </tr>';
391 }
392 echo '
393 </table>
394 </div>
395
396 </td>
397 </tr>
398 </table>';
399 } else {
400 echo __('None', 'ninjafirewall') . '
401 </td>
402 </tr>
403 </table>
404 <br />';
405 }
406 ?>
407 <form method="post">
408 <?php wp_nonce_field('filecheck_save', 'nfwnonce', 0); ?>
409 <input type="hidden" name="nfw_act" value="scan" />
410 <p><input type="submit" class="button-primary" value="<?php _e('Scan System For File Changes', 'ninjafirewall') ?> &#187;" /></p>
411 <input type="hidden" name="tab" value="filecheck" />
412 </form>
413
414 <br />
415 <br />
416 <?php
417 if (! isset($nfw_options['sched_scan']) ) {
418 $sched_scan = 0;
419 } else {
420 $sched_scan = $nfw_options['sched_scan'];
421 }
422 if ( empty($nfw_options['report_scan']) ) {
423 $report_scan = 0;
424 } else {
425 $report_scan = 1;
426 }
427 ?>
428 <h3><?php _e('Options', 'ninjafirewall') ?></h3>
429 <form method="post">
430 <?php
431 wp_nonce_field('filecheck_save', 'nfwnonce', 0);
432 // If WP cron is disabled, we simply warn the user :
433 if ( defined('DISABLE_WP_CRON') ) {
434 ?>
435 <p class="description" style="color:red"><?php printf( __('It seems that %s is set. Ensure you have another way to run WP-Cron, otherwise NinjaFirewall scheduled scans will not work.', 'ninjafirewall'), '<code>DISABLE_WP_CRON</code>' ) ?></p>
436 <?php
437 }
438 ?>
439 <table class="form-table nfw-table">
440 <tr>
441 <th scope="row" class="row-med"><?php _e('Enable scheduled scans', 'ninjafirewall') ?></th>
442 <td>
443 <p><label><input type="radio" name="sched_scan" value="0"<?php checked($sched_scan, 0) ?> /><?php _e('No (default)', 'ninjafirewall') ?></label></p>
444 <p><label><input type="radio" name="sched_scan" value="1"<?php checked($sched_scan, 1) ?> /><?php _e('Hourly', 'ninjafirewall') ?></label></p>
445 <p><label><input type="radio" name="sched_scan" value="2"<?php checked($sched_scan, 2) ?> /><?php _e('Twicedaily', 'ninjafirewall') ?></label></p>
446 <p><label><input type="radio" name="sched_scan" value="3"<?php checked($sched_scan, 3) ?> /><?php _e('Daily', 'ninjafirewall') ?></label></p>
447 <?php
448 if ( $nextscan = wp_next_scheduled('nfscanevent') ) {
449 $sched = new DateTime( date('M d, Y H:i:s', $nextscan) );
450 $now = new DateTime( date('M d, Y H:i:s', time() ) );
451 $diff = $now->diff($sched);
452 ?>
453 <p class="description"><?php printf( __('Next scan will start in approximately %s day(s), %s hour(s), %s minute(s) and %s second(s).', 'ninjafirewall'), $diff->format('%a') % 7, $diff->format('%h'), $diff->format('%i'), $diff->format('%s') ) ?></p>
454 <?php
455 // Ensure that the scheduled scan time is in the future,
456 // not in the past, otherwise send a warning because wp-cron
457 // is obviously not working as expected :
458 if ( $nextscan < time() ) {
459 ?>
460 <p class="description" style="color:red"><?php _e('The next scheduled scan date is in the past! WordPress wp-cron may not be working or may have been disabled.', 'ninjafirewall'); ?></p>
461 <?php
462 }
463 }
464 ?>
465 </td>
466 </tr>
467 <tr>
468 <th scope="row" class="row-med"><?php _e('Scheduled scan report', 'ninjafirewall') ?></th>
469 <td>
470 <p><label><input type="radio" name="report_scan" value="0"<?php checked($report_scan, 0) ?> /><?php _e('Send me a report by email only if changes are detected (default)', 'ninjafirewall') ?></label></p>
471 <p><label><input type="radio" name="report_scan" value="1"<?php checked($report_scan, 1) ?> /><?php _e('Always send me a report by email after a scheduled scan', 'ninjafirewall') ?></label></p>
472 </td>
473 </tr>
474 </table>
475 <input type="hidden" name="nfw_act" value="scheduled" />
476 <p><input type="submit" class="button-primary" value="<?php _e('Save Scan Options', 'ninjafirewall') ?>" /></p>
477 <input type="hidden" name="tab" value="filecheck" />
478 </form>
479
480 <?php
481
482 // ---------------------------------------------------------------------
483
484 function nf_sub_monitoring_create($nfmon_snapshot) {
485
486 // Check POST data:
487 if ( empty($_POST['snapdir']) ) {
488 return __('Enter the full path to the directory to be scanned.', 'ninjafirewall');
489 }
490 if ( strpos( $_POST['snapdir'], '://' ) !== false ) {
491 return sprintf( __('The directory %s is not correct.', 'ninjafirewall'), '<code>'. htmlspecialchars($_POST['snapdir']) .'</code>');
492 }
493 if ( strlen($_POST['snapdir']) > 1 ) {
494 $_POST['snapdir'] = trim($_POST['snapdir'], ' ');
495 $_POST['snapdir'] = rtrim($_POST['snapdir'], '/');
496 }
497 if (! file_exists($_POST['snapdir']) ) {
498 return sprintf( __('The directory %s does not exist.', 'ninjafirewall'), '<code>'. htmlspecialchars($_POST['snapdir']) .'</code>');
499 }
500 if (! is_readable($_POST['snapdir']) ) {
501 return sprintf( __('The directory %s is not readable.', 'ninjafirewall'), '<code>'. htmlspecialchars($_POST['snapdir']) .'</code>');
502 }
503 if ( isset($_POST['snapnoslink']) ) {
504 $snapnoslink = 1;
505 } else {
506 $snapnoslink = 0;
507 }
508
509 $snapexclude = '';
510 if (! empty( $_POST['snapexclude'] ) ) {
511 $_POST['snapexclude'] = trim( $_POST['snapexclude'] );
512 $_POST['snapexclude'] = preg_replace( '/\s*,\s*/', ',', $_POST['snapexclude'] );
513 $tmp = preg_quote( $_POST['snapexclude'], '/' );
514 $snapexclude = str_replace(',', '|', $tmp);
515 }
516
517 @ini_set('max_execution_time', 0);
518 $snapproc = nf_fc_metrics('start');
519
520 if ($fh = fopen($nfmon_snapshot, 'w') ) {
521 fwrite($fh, '<?php die("Forbidden"); ?>' . "\n");
522 $res = scd($_POST['snapdir'], $snapexclude, $fh, $snapnoslink);
523 fclose($fh);
524
525 // Error ?
526 if ($res) {
527 if (file_exists($nfmon_snapshot) ) {
528 unlink($nfmon_snapshot);
529 }
530 return $res;
531 }
532
533 // Save scan dir :
534 $nfw_options = nfw_get_option('nfw_options');
535 $nfw_options['snapproc'] = nf_fc_metrics('stop', $snapproc );
536 $nfw_options['snapexclude'] = $_POST['snapexclude'];
537 $nfw_options['snapdir'] = $_POST['snapdir'];
538 $nfw_options['snapnoslink'] = $snapnoslink;
539 nfw_update_option('nfw_options', $nfw_options);
540
541 } else {
542 return sprintf( __('Cannot write to %s.', 'ninjafirewall'), '<code>'. $nfmon_snapshot .'</code>');
543 }
544 }
545
546 // ---------------------------------------------------------------------
547
548 function scd($snapdir, $snapexclude, $fh, $snapnoslink) {
549
550 if (is_readable($snapdir) ) {
551 if ($dh = opendir($snapdir) ) {
552 while ( FALSE !== ($file = readdir($dh)) ) {
553 if ( $file == '.' || $file == '..') { continue; }
554 $full_path = $snapdir . '/' . $file;
555 if ( $snapexclude ) {
556 if ( preg_match("/$snapexclude/", $full_path) ) { continue; }
557 }
558 if (is_readable($full_path)) {
559 if ( $snapnoslink && is_link($full_path)) { continue; }
560 if ( is_dir($full_path) ) {
561 scd($full_path, $snapexclude, $fh, $snapnoslink);
562 } elseif (is_file($full_path) ) {
563 $file_stat = stat($full_path);
564 fwrite($fh, $full_path . '::' . sprintf ("%04o", $file_stat['mode'] & 0777) . ':' . $file_stat['uid'] . ':' .
565 $file_stat['gid'] . ':' . $file_stat['size'] . ':' . $file_stat['mtime'] . ':' .
566 $file_stat['ctime'] . "\n");
567 }
568 }
569 }
570 closedir($dh);
571 } else {
572 return sprintf(__('Error : cannot open %s directory.', 'ninjafirewall'), '<code>'. htmlspecialchars($snapdir) .'</code>');
573 }
574 } else {
575 return sprintf(__('Error : %s directory is not readable.', 'ninjafirewall'), '<code>'. htmlspecialchars($snapdir) .'</code>');
576 }
577 }
578
579 // ---------------------------------------------------------------------
580
581 function nf_sub_monitoring_scan($nfmon_snapshot, $nfmon_diff) {
582
583 $nfw_options = nfw_get_option('nfw_options');
584
585 if (empty($nfw_options['enabled']) ) { return; }
586
587 @ini_set('max_execution_time', 0);
588
589 if (! isset($nfw_options['snapexclude']) || ! isset($nfw_options['snapdir']) || ! isset($nfw_options['snapnoslink']) ) {
590 return sprintf( __('Missing options line %s, please try again.', 'ninjafirewall'), __LINE__ );
591 }
592 $tmp = preg_quote($nfw_options['snapexclude'], '/');
593 $snapexclude = str_replace(',', '|', $tmp);
594
595 if ($fh = fopen($nfmon_snapshot . '_tmp', 'w') ) {
596 fwrite($fh, '<?php die("Forbidden"); ?>' . "\n");
597 $res = scd($nfw_options['snapdir'], $snapexclude, $fh, $nfw_options['snapnoslink']);
598 fclose($fh);
599 } else {
600 return sprintf( __('Cannot create %s.', 'ninjafirewall'), '<code>'. $nfmon_snapshot . '_tmp</code>');
601 }
602
603 // Error ?
604 if ($res) {
605 if (file_exists($nfmon_snapshot . '_tmp') ) {
606 unlink($nfmon_snapshot . '_tmp');
607 }
608 return $res;
609 }
610
611 // Compare both snapshots :
612
613 $old_files = $file = $new_files = array();
614 $modified_files = $match = array();
615
616 if (! $fh = fopen($nfmon_snapshot, 'r') ) {
617 return __('Error reading old snapshot file.', 'ninjafirewall');
618 }
619 while (! feof($fh) ) {
620 $match = explode('::', rtrim(fgets($fh)) . '::' );
621 if (! empty($match[1]) ) {
622 $old_files[$match[0]] = $match[1];
623 }
624 }
625 fclose($fh);
626
627 if (! $fh = fopen($nfmon_snapshot . '_tmp', 'r') ) {
628 return __('Error reading new snapshot file.', 'ninjafirewall');
629 }
630 while (! feof($fh) ) {
631 $match = explode('::', rtrim(fgets($fh)) . '::' );
632
633 if ( empty($match[1]) ) {
634 continue;
635 }
636
637 // New file ?
638 if ( empty( $old_files[$match[0]] ) ) {
639 $new_files[$match[0]] = $match[1];
640 continue;
641 }
642
643 // Modified file ?
644 if ( $old_files[$match[0]] != $match[1] ) {
645 $modified_files[$match[0]] = $old_files[$match[0]] . '::' . $match[1];
646 }
647
648 // Delete it from old files list :
649 unset( $old_files[$match[0]] );
650 }
651 fclose ($fh);
652
653 // Write changes to file, if any :
654 if ($new_files || $modified_files || $old_files) {
655
656 $fh = fopen($nfmon_diff, 'w');
657 fwrite($fh, '<?php die("Forbidden"); ?>' . "\n");
658
659 if ( $new_files ) {
660 foreach ( $new_files as $fkey => $fvalue ) {
661 fwrite($fh, $fkey . '::N::' . $fvalue . "\n");
662 }
663 }
664
665 if ( $modified_files ) {
666 foreach ( $modified_files as $fkey => $fvalue ) {
667 fwrite($fh, $fkey . '::M::' . $fvalue . "\n");
668 }
669 }
670
671 if ( $old_files ) {
672 foreach ( $old_files as $fkey => $fvalue ) {
673 fwrite($fh, $fkey . '::D::' . $fvalue . "\n");
674 }
675 }
676 fclose($fh);
677 rename( $nfmon_snapshot . '_tmp', $nfmon_snapshot);
678
679 } else {
680 if (file_exists($nfmon_diff) ) {
681 // Keep last changes :
682 rename($nfmon_diff, $nfmon_diff. '.php');
683 }
684 unlink( $nfmon_snapshot . '_tmp');
685 }
686 }
687
688 // ---------------------------------------------------------------------
689
690 function nf_scheduled_scan() {
691
692 $nfw_options = nfw_get_option('nfw_options');
693
694 if (! isset($_POST['sched_scan']) || ! preg_match('/^[1-3]$/', $_POST['sched_scan']) ) {
695 $nfw_options['sched_scan'] = 0;
696 } else {
697 $nfw_options['sched_scan'] = $_POST['sched_scan'];
698 }
699
700 if ( empty($_POST['report_scan']) ) {
701 $nfw_options['report_scan'] = 0;
702 } else {
703 $nfw_options['report_scan'] = 1;
704 }
705 nfw_update_option('nfw_options', $nfw_options);
706
707 // Update cronjobs
708 nfw_create_scheduled_tasks('nfscanevent');
709
710 }
711
712 // ---------------------------------------------------------------------
713
714 function nf_scan_email( $nfmon_diff, $log_dir ) {
715
716 if ( is_multisite() ) {
717 $url = network_home_url('/');
718 } else {
719 $url = home_url('/');
720 }
721
722 /**
723 * Changes were detected.
724 */
725 if ( $nfmon_diff ) {
726 $stat = stat( $nfmon_diff );
727 $data = '== NinjaFirewall File Check (diff)'."\n";
728 $data.= '== ' . site_url() ."\n";
729 $data.= '== ' . date_i18n('M d, Y @ H:i:s O', $stat['ctime'] ) ."\n\n";
730 $data.= '[+] = ' . __('New file', 'ninjafirewall') .
731 ' [!] = ' . __('Modified file', 'ninjafirewall') .
732 ' [-] = ' . __('Deleted file', 'ninjafirewall') .
733 "\n\n";
734 $n = 0;
735 $m = 0;
736 $d = 0;
737 $fh = fopen( $nfmon_diff, 'r');
738 while (! feof( $fh ) ) {
739 $res = explode('::', fgets( $fh ) );
740 if ( empty( $res[1] ) ) {
741 continue;
742 }
743 /**
744 * New file.
745 */
746 if ( $res[1] == 'N') {
747 $data .= "[+] {$res[0]}\n";
748 ++$n;
749 /**
750 * Deleted file.
751 */
752 } elseif ( $res[1] == 'D') {
753 $data .= "[-] {$res[0]}\n";
754 ++$d;
755 /**
756 * Modified file.
757 */
758 } elseif ( $res[1] == 'M') {
759 $data .= "[!] {$res[0]}\n";
760 ++$m;
761 }
762 }
763 fclose( $fh );
764 $data .= "\n== EOF\n";
765 @file_put_contents( "{$log_dir}nf_filecheck.txt", $data, LOCK_EX );
766
767 /**
768 * Email notification.
769 */
770 $subject = [ ];
771 $content = [ $url, ucfirst( date_i18n('M d, Y @ H:i:s O') ), $n, $m, $d ];
772 NinjaFirewall_mail::send(
773 'fc_detection', $subject, $content, '', "{$log_dir}nf_filecheck.txt", 1
774 );
775
776 /**
777 * User asked to always receive a report after a scheduled scan.
778 */
779 } else {
780 /**
781 * Email notification.
782 */
783 $subject = [ ];
784 $content = [ $url, ucfirst( date_i18n('M d, Y @ H:i:s O') ) ];
785 NinjaFirewall_mail::send('fc_report', $subject, $content, '', [], 1 );
786 }
787 }
788
789 // ---------------------------------------------------------------------
790 function nf_fc_metrics( $action = 'start', $starttime = 0 ) {
791
792 if ( function_exists('hrtime') ) {
793 $metrics = 'hrtime';
794 } else {
795 $metrics = 'microtime';
796 }
797
798 // Start chrono
799 if ( $action == 'start') {
800 return $metrics( true );
801 }
802
803 // Stop chrono and return elapsed time
804 if ( $metrics == 'hrtime') {
805 return number_format( ( $metrics( true ) - $starttime ) / 1000000000, 2 );
806 } else {
807 return number_format( $metrics( true ) - $starttime, 2 );
808 }
809 }
810
811 // ---------------------------------------------------------------------
812 // EOF
813