11 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. |
11 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for details. |
12 */ |
12 */ |
13 |
13 |
14 function page_Admin_SecurityLog() |
14 function page_Admin_SecurityLog() |
15 { |
15 { |
16 global $db, $session, $paths, $template, $plugins; // Common objects |
16 global $db, $session, $paths, $template, $plugins; // Common objects |
17 global $lang; |
17 global $lang; |
18 if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN ) |
18 if ( $session->auth_level < USER_LEVEL_ADMIN || $session->user_level < USER_LEVEL_ADMIN ) |
19 { |
19 { |
20 $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true); |
20 $login_link = makeUrlNS('Special', 'Login/' . $paths->nslist['Special'] . 'Administration', 'level=' . USER_LEVEL_ADMIN, true); |
21 echo '<h3>' . $lang->get('adm_err_not_auth_title') . '</h3>'; |
21 echo '<h3>' . $lang->get('adm_err_not_auth_title') . '</h3>'; |
22 echo '<p>' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '</p>'; |
22 echo '<p>' . $lang->get('adm_err_not_auth_body', array( 'login_link' => $login_link )) . '</p>'; |
23 return; |
23 return; |
24 } |
24 } |
25 |
25 |
26 // if ( defined('ENANO_DEMO_MODE') && substr($_SERVER['REMOTE_ADDR'], 0, 8) != '192.168.' ) |
26 // if ( defined('ENANO_DEMO_MODE') && substr($_SERVER['REMOTE_ADDR'], 0, 8) != '192.168.' ) |
27 // { |
27 // { |
28 // die('Security log is disabled in demo mode.'); |
28 // die('Security log is disabled in demo mode.'); |
29 // } |
29 // } |
30 |
30 |
31 echo '<h3>' . $lang->get('acpsl_heading_main') . '</h3>'; |
31 echo '<h3>' . $lang->get('acpsl_heading_main') . '</h3>'; |
32 |
32 |
33 // Not calling the real fetcher because we have to paginate the results |
33 // Not calling the real fetcher because we have to paginate the results |
34 $offset = ( isset($_GET['offset']) ) ? intval($_GET['offset']) : 0; |
34 $offset = ( isset($_GET['offset']) ) ? intval($_GET['offset']) : 0; |
35 $q = $db->sql_query('SELECT COUNT(time_id) as num FROM '.table_prefix.'logs WHERE log_type=\'security\' GROUP BY log_id, time_id, log_type, action ORDER BY time_id DESC, action ASC;'); |
35 $q = $db->sql_query('SELECT COUNT(time_id) as num FROM '.table_prefix.'logs WHERE log_type=\'security\' GROUP BY log_id, time_id, log_type, action ORDER BY time_id DESC, action ASC;'); |
36 if ( !$q ) |
36 if ( !$q ) |
37 $db->_die(); |
37 $db->_die(); |
38 $row = $db->fetchrow(); |
38 $row = $db->fetchrow(); |
39 $db->free_result(); |
39 $db->free_result(); |
40 $count = intval($row['num']); |
40 $count = intval($row['num']); |
41 |
41 |
42 $l = 'SELECT action,date_string,author,author_uid,u.username,edit_summary,time_id,page_text FROM '.table_prefix."logs AS l\n" |
42 $l = 'SELECT action,date_string,author,author_uid,u.username,edit_summary,time_id,page_text FROM '.table_prefix."logs AS l\n" |
43 . " LEFT JOIN " . table_prefix . "users AS u\n" |
43 . " LEFT JOIN " . table_prefix . "users AS u\n" |
44 . " ON ( u.user_id = l.author_uid OR u.user_id IS NULL )\n" |
44 . " ON ( u.user_id = l.author_uid OR u.user_id IS NULL )\n" |
45 . " WHERE log_type='security'\n" |
45 . " WHERE log_type='security'\n" |
46 . " ORDER BY time_id DESC, action ASC;"; |
46 . " ORDER BY time_id DESC, action ASC;"; |
47 |
47 |
48 $q = $db->sql_query($l); |
48 $q = $db->sql_query($l); |
49 if ( !$q ) |
49 if ( !$q ) |
50 $db->_die(); |
50 $db->_die(); |
51 |
51 |
52 $html = paginate( |
52 $html = paginate( |
53 $q, |
53 $q, |
54 '{time_id}', |
54 '{time_id}', |
55 $count, |
55 $count, |
56 makeUrlNS('Special', 'Administration', 'module=' . $paths->nslist['Admin'] . 'SecurityLog&offset=%s'), |
56 makeUrlNS('Special', 'Administration', 'module=' . $paths->nslist['Admin'] . 'SecurityLog&offset=%s'), |
57 $offset, |
57 $offset, |
58 50, |
58 50, |
59 array('time_id' => 'seclog_format_inner'), |
59 array('time_id' => 'seclog_format_inner'), |
60 '<div class="tblholder" style="/* max-height: 500px; clip: rect(0px,auto,auto,0px); overflow: auto; */"><table border="0" cellspacing="1" cellpadding="4" width="100%"> |
60 '<div class="tblholder" style="/* max-height: 500px; clip: rect(0px,auto,auto,0px); overflow: auto; */"><table border="0" cellspacing="1" cellpadding="4" width="100%"> |
61 <tr> |
61 <tr> |
62 <th style="width: 60%;">' . $lang->get('acpsl_col_type') . '</th> |
62 <th style="width: 60%;">' . $lang->get('acpsl_col_type') . '</th> |
63 <th>' . $lang->get('acpsl_col_date') . '</th> |
63 <th>' . $lang->get('acpsl_col_date') . '</th> |
64 <th>' . $lang->get('acpsl_col_username') . '</th> |
64 <th>' . $lang->get('acpsl_col_username') . '</th> |
65 <th>' . $lang->get('acpsl_col_ip') . '</th> |
65 <th>' . $lang->get('acpsl_col_ip') . '</th> |
66 </tr>', |
66 </tr>', |
67 '</table></div>' |
67 '</table></div>' |
68 ); |
68 ); |
69 |
69 |
70 echo $html; |
70 echo $html; |
71 |
71 |
72 } |
72 } |
73 |
73 |
74 function get_security_log($num = false) |
74 function get_security_log($num = false) |
75 { |
75 { |
76 global $db, $session, $paths, $template, $plugins; // Common objects |
76 global $db, $session, $paths, $template, $plugins; // Common objects |
77 global $lang; |
77 global $lang; |
78 |
78 |
79 if ( $session->auth_level < USER_LEVEL_ADMIN ) |
79 if ( $session->auth_level < USER_LEVEL_ADMIN ) |
80 { |
80 { |
81 $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,author_uid) VALUES(\'security\',\'seclog_unauth\',' . time() . ', \'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\', \'' . $db->escape($session->username) . '\', ' . $session->user_id . ');'); |
81 $q = $db->sql_query('INSERT INTO '.table_prefix.'logs(log_type,action,time_id,edit_summary,author,author_uid) VALUES(\'security\',\'seclog_unauth\',' . time() . ', \'' . $db->escape($_SERVER['REMOTE_ADDR']) . '\', \'' . $db->escape($session->username) . '\', ' . $session->user_id . ');'); |
82 if ( !$q ) |
82 if ( !$q ) |
83 $db->_die(); |
83 $db->_die(); |
84 die('Security log: unauthorized attempt to fetch. Call has been logged and reported to the administrators.'); |
84 die('Security log: unauthorized attempt to fetch. Call has been logged and reported to the administrators.'); |
85 } |
85 } |
86 |
86 |
87 $return = '<div class="tblholder" style="/* max-height: 500px; clip: rect(0px,auto,auto,0px); overflow: auto; */"><table border="0" cellspacing="1" cellpadding="4" width="100%">'; |
87 $return = '<div class="tblholder" style="/* max-height: 500px; clip: rect(0px,auto,auto,0px); overflow: auto; */"><table border="0" cellspacing="1" cellpadding="4" width="100%">'; |
88 $cls = 'row2'; |
88 $cls = 'row2'; |
89 $return .= '<tr><th style="width: 60%;">' . $lang->get('acpsl_col_type') . '</th><th>' . $lang->get('acpsl_col_date') . '</th><th>' . $lang->get('acpsl_col_username') . '</th><th>' . $lang->get('acpsl_col_ip') . '</th></tr>'; |
89 $return .= '<tr><th style="width: 60%;">' . $lang->get('acpsl_col_type') . '</th><th>' . $lang->get('acpsl_col_date') . '</th><th>' . $lang->get('acpsl_col_username') . '</th><th>' . $lang->get('acpsl_col_ip') . '</th></tr>'; |
90 $hash = sha1(microtime()); |
90 $hash = sha1(microtime()); |
91 if ( defined('ENANO_DEMO_MODE') ) |
91 if ( defined('ENANO_DEMO_MODE') ) |
92 { |
92 { |
93 require('config.php'); |
93 require('config.php'); |
94 $hash = md5($dbpasswd); |
94 $hash = md5($dbpasswd); |
95 unset($dbname, $dbhost, $dbuser, $dbpasswd); |
95 unset($dbname, $dbhost, $dbuser, $dbpasswd); |
96 unset($dbname, $dbhost, $dbuser, $dbpasswd); // PHP5 Zend bug |
96 unset($dbname, $dbhost, $dbuser, $dbpasswd); // PHP5 Zend bug |
97 } |
97 } |
98 // if ( defined('ENANO_DEMO_MODE') && !isset($_GET[ $hash ]) && substr($_SERVER['REMOTE_ADDR'], 0, 8) != '192.168.' ) |
98 // if ( defined('ENANO_DEMO_MODE') && !isset($_GET[ $hash ]) && substr($_SERVER['REMOTE_ADDR'], 0, 8) != '192.168.' ) |
99 // { |
99 // { |
100 // $return .= '<tr><td class="row1" colspan="4">Logs are recorded but not displayed for privacy purposes in the demo.</td></tr>'; |
100 // $return .= '<tr><td class="row1" colspan="4">Logs are recorded but not displayed for privacy purposes in the demo.</td></tr>'; |
101 // } |
101 // } |
102 // else |
102 // else |
103 // { |
103 // { |
104 $limit_clause = is_int($num) ? " LIMIT $num" : ''; |
104 $limit_clause = is_int($num) ? " LIMIT $num" : ''; |
105 $l = 'SELECT action,date_string,author,author_uid,u.username,edit_summary,time_id,page_text FROM '.table_prefix."logs AS l\n" |
105 $l = 'SELECT action,date_string,author,author_uid,u.username,edit_summary,time_id,page_text FROM '.table_prefix."logs AS l\n" |
106 . " LEFT JOIN " . table_prefix . "users AS u\n" |
106 . " LEFT JOIN " . table_prefix . "users AS u\n" |
107 . " ON ( u.user_id = l.author_uid OR u.user_id IS NULL )\n" |
107 . " ON ( u.user_id = l.author_uid OR u.user_id IS NULL )\n" |
108 . " WHERE log_type='security'\n" |
108 . " WHERE log_type='security'\n" |
109 . " ORDER BY time_id DESC, action ASC{$limit_clause};"; |
109 . " ORDER BY time_id DESC, action ASC{$limit_clause};"; |
110 |
110 |
111 $q = $db->sql_query($l); |
111 $q = $db->sql_query($l); |
112 while($r = $db->fetchrow($q)) |
112 while($r = $db->fetchrow($q)) |
113 { |
113 { |
114 $return .= seclog_format_inner($r); |
114 $return .= seclog_format_inner($r); |
115 } |
115 } |
116 $db->free_result(); |
116 $db->free_result(); |
117 // } |
117 // } |
118 $return .= '</table></div>'; |
118 $return .= '</table></div>'; |
119 |
119 |
120 return $return; |
120 return $return; |
121 } |
121 } |
122 |
122 |
123 function seclog_format_inner($r, $f = false) |
123 function seclog_format_inner($r, $f = false) |
124 { |
124 { |
125 if ( is_array($f) ) |
125 if ( is_array($f) ) |
126 { |
126 { |
127 unset($r); |
127 unset($r); |
128 $r =& $f; |
128 $r =& $f; |
129 } |
129 } |
130 global $db, $session, $paths, $template, $plugins; // Common objects |
130 global $db, $session, $paths, $template, $plugins; // Common objects |
131 global $lang; |
131 global $lang; |
132 $return = ''; |
132 $return = ''; |
133 static $cls = 'row2'; |
133 static $cls = 'row2'; |
134 if ( substr($_SERVER['REMOTE_ADDR'], 0, 8) != '192.168.' && defined('ENANO_DEMO_MODE') ) |
134 if ( substr($_SERVER['REMOTE_ADDR'], 0, 8) != '192.168.' && defined('ENANO_DEMO_MODE') ) |
135 { |
135 { |
136 $r['edit_summary'] = preg_replace('/([0-9])/', 'x', $r['edit_summary']); |
136 $r['edit_summary'] = preg_replace('/([0-9])/', 'x', $r['edit_summary']); |
137 } |
137 } |
138 if ( $r['action'] == 'illegal_page' ) |
138 if ( $r['action'] == 'illegal_page' ) |
139 { |
139 { |
140 list($illegal_id, $illegal_ns) = unserialize($r['page_text']); |
140 list($illegal_id, $illegal_ns) = unserialize($r['page_text']); |
141 $url = makeUrlNS($illegal_ns, $illegal_id, false, true); |
141 $url = makeUrlNS($illegal_ns, $illegal_id, false, true); |
142 $title = get_page_title_ns($illegal_id, $illegal_ns); |
142 $title = get_page_title_ns($illegal_id, $illegal_ns); |
143 $class = ( isPage($paths->nslist[$illegal_ns] . $illegal_id) ) ? '' : ' class="wikilink-nonexistent"'; |
143 $class = ( isPage($paths->nslist[$illegal_ns] . $illegal_id) ) ? '' : ' class="wikilink-nonexistent"'; |
144 $illegal_link = '<a href="' . $url . '"' . $class . ' onclick="window.open(this.href); return false;">' . $title . '</a>'; |
144 $illegal_link = '<a href="' . $url . '"' . $class . ' onclick="window.open(this.href); return false;">' . $title . '</a>'; |
145 } |
145 } |
146 else if ( $r['action'] == 'plugin_enable' || $r['action'] == 'plugin_disable' ) |
146 else if ( $r['action'] == 'plugin_enable' || $r['action'] == 'plugin_disable' ) |
147 { |
147 { |
148 $r['page_text'] = htmlspecialchars($r['page_text']); |
148 $r['page_text'] = htmlspecialchars($r['page_text']); |
149 } |
149 } |
150 $cls = ( $cls == 'row2' ) ? 'row1' : 'row2'; |
150 $cls = ( $cls == 'row2' ) ? 'row1' : 'row2'; |
151 $return .= '<tr><td class="'.$cls.'">'; |
151 $return .= '<tr><td class="'.$cls.'">'; |
152 switch($r['action']) |
152 switch($r['action']) |
153 { |
153 { |
154 case "admin_auth_good" : $return .= $lang->get('acpsl_entry_admin_auth_good' , array('level' => $session->userlevel_to_string( intval($r['page_text']) ))); break; |
154 case "admin_auth_good" : $return .= $lang->get('acpsl_entry_admin_auth_good' , array('level' => $session->userlevel_to_string( intval($r['page_text']) ))); break; |
155 case "admin_auth_bad" : $return .= $lang->get('acpsl_entry_admin_auth_bad' , array('level' => $session->userlevel_to_string( intval($r['page_text']) ))); break; |
155 case "admin_auth_bad" : $return .= $lang->get('acpsl_entry_admin_auth_bad' , array('level' => $session->userlevel_to_string( intval($r['page_text']) ))); break; |
156 case "activ_good" : $return .= $lang->get('acpsl_entry_activ_good') ; break; |
156 case "activ_good" : $return .= $lang->get('acpsl_entry_activ_good') ; break; |
157 case "auth_good" : $return .= $lang->get('acpsl_entry_auth_good') ; break; |
157 case "auth_good" : $return .= $lang->get('acpsl_entry_auth_good') ; break; |
158 case "activ_bad" : $return .= $lang->get('acpsl_entry_activ_bad') ; break; |
158 case "activ_bad" : $return .= $lang->get('acpsl_entry_activ_bad') ; break; |
159 case "auth_bad" : $return .= $lang->get('acpsl_entry_auth_bad') ; break; |
159 case "auth_bad" : $return .= $lang->get('acpsl_entry_auth_bad') ; break; |
160 case "sql_inject" : $return .= $lang->get('acpsl_entry_sql_inject' , array('query' => htmlspecialchars($r['page_text']))); break; |
160 case "sql_inject" : $return .= $lang->get('acpsl_entry_sql_inject' , array('query' => htmlspecialchars($r['page_text']))); break; |
161 case "db_backup" : $return .= $lang->get('acpsl_entry_db_backup' , array('tables' => $r['page_text'])) ; break; |
161 case "db_backup" : $return .= $lang->get('acpsl_entry_db_backup' , array('tables' => $r['page_text'])) ; break; |
162 case "install_enano" : $return .= $lang->get('acpsl_entry_install_enano' , array('version' => $r['page_text'])); break; // version is in $r['page_text'] |
162 case "install_enano" : $return .= $lang->get('acpsl_entry_install_enano' , array('version' => $r['page_text'])); break; // version is in $r['page_text'] |
163 case "upgrade_enano" : $return .= $lang->get('acpsl_entry_upgrade_enano' , array('version' => $r['page_text'])); break; // version is in $r['page_text'] |
163 case "upgrade_enano" : $return .= $lang->get('acpsl_entry_upgrade_enano' , array('version' => $r['page_text'])); break; // version is in $r['page_text'] |
164 case "illegal_page" : $return .= $lang->get('acpsl_entry_illegal_page' , array('illegal_link' => $illegal_link)) ; break; |
164 case "illegal_page" : $return .= $lang->get('acpsl_entry_illegal_page' , array('illegal_link' => $illegal_link)) ; break; |
165 case "upload_enable" : $return .= $lang->get('acpsl_entry_upload_enable') ; break; |
165 case "upload_enable" : $return .= $lang->get('acpsl_entry_upload_enable') ; break; |
166 case "upload_disable" : $return .= $lang->get('acpsl_entry_upload_disable') ; break; |
166 case "upload_disable" : $return .= $lang->get('acpsl_entry_upload_disable') ; break; |
167 case "magick_enable" : $return .= $lang->get('acpsl_entry_magick_enable') ; break; |
167 case "magick_enable" : $return .= $lang->get('acpsl_entry_magick_enable') ; break; |
168 case "magick_disable" : $return .= $lang->get('acpsl_entry_magick_disable') ; break; |
168 case "magick_disable" : $return .= $lang->get('acpsl_entry_magick_disable') ; break; |
169 case "filehist_enable" : $return .= $lang->get('acpsl_entry_filehist_enable') ; break; |
169 case "filehist_enable" : $return .= $lang->get('acpsl_entry_filehist_enable') ; break; |
170 case "filehist_disable": $return .= $lang->get('acpsl_entry_filehist_disable'); break; |
170 case "filehist_disable": $return .= $lang->get('acpsl_entry_filehist_disable'); break; |
171 case "magick_path" : $return .= $lang->get('acpsl_entry_magick_path') ; break; |
171 case "magick_path" : $return .= $lang->get('acpsl_entry_magick_path') ; break; |
172 case "plugin_disable" : $return .= $lang->get('acpsl_entry_plugin_disable' , array('plugin' => $r['page_text'])); break; |
172 case "plugin_disable" : $return .= $lang->get('acpsl_entry_plugin_disable' , array('plugin' => $r['page_text'])); break; |
173 case "plugin_enable" : $return .= $lang->get('acpsl_entry_plugin_enable' , array('plugin' => $r['page_text'])); break; |
173 case "plugin_enable" : $return .= $lang->get('acpsl_entry_plugin_enable' , array('plugin' => $r['page_text'])); break; |
174 case "plugin_install" : $return .= $lang->get('acpsl_entry_plugin_install' , array('plugin' => $r['page_text'])); break; |
174 case "plugin_install" : $return .= $lang->get('acpsl_entry_plugin_install' , array('plugin' => $r['page_text'])); break; |
175 case "plugin_uninstall": $return .= $lang->get('acpsl_entry_plugin_uninstall' , array('plugin' => $r['page_text'])); break; |
175 case "plugin_uninstall": $return .= $lang->get('acpsl_entry_plugin_uninstall' , array('plugin' => $r['page_text'])); break; |
176 case "plugin_upgrade" : $return .= $lang->get('acpsl_entry_plugin_upgrade' , array('plugin' => $r['page_text'])); break; |
176 case "plugin_upgrade" : $return .= $lang->get('acpsl_entry_plugin_upgrade' , array('plugin' => $r['page_text'])); break; |
177 case "seclog_unauth" : $return .= $lang->get('acpsl_entry_seclog_unauth') ; break; |
177 case "seclog_unauth" : $return .= $lang->get('acpsl_entry_seclog_unauth') ; break; |
178 case "u_from_admin" : $return .= $lang->get('acpsl_entry_u_from_admin' , array('username' => $r['page_text'])); break; |
178 case "u_from_admin" : $return .= $lang->get('acpsl_entry_u_from_admin' , array('username' => $r['page_text'])); break; |
179 case "u_from_mod" : $return .= $lang->get('acpsl_entry_u_from_mod' , array('username' => $r['page_text'])); break; |
179 case "u_from_mod" : $return .= $lang->get('acpsl_entry_u_from_mod' , array('username' => $r['page_text'])); break; |
180 case "u_to_admin" : $return .= $lang->get('acpsl_entry_u_to_admin' , array('username' => $r['page_text'])); break; |
180 case "u_to_admin" : $return .= $lang->get('acpsl_entry_u_to_admin' , array('username' => $r['page_text'])); break; |
181 case "u_to_mod" : $return .= $lang->get('acpsl_entry_u_to_mod' , array('username' => $r['page_text'])); break; |
181 case "u_to_mod" : $return .= $lang->get('acpsl_entry_u_to_mod' , array('username' => $r['page_text'])); break; |
182 case "view_comment_ip" : $return .= $lang->get('acpsl_entry_view_comment_ip' , array('username' => htmlspecialchars($r['page_text']))); break; |
182 case "view_comment_ip" : $return .= $lang->get('acpsl_entry_view_comment_ip' , array('username' => htmlspecialchars($r['page_text']))); break; |
183 } |
183 } |
184 $author_bit = '<span style="'; |
184 $author_bit = '<span style="'; |
185 $rank_info = $session->get_user_rank($r['author_uid']); |
185 $rank_info = $session->get_user_rank($r['author_uid']); |
186 $author_bit .= $rank_info['rank_style']; |
186 $author_bit .= $rank_info['rank_style']; |
187 $author_bit .= '">'; |
187 $author_bit .= '">'; |
188 $author_bit .= $r['author_uid'] > 1 && !empty($r['username']) ? htmlspecialchars($r['username']) : htmlspecialchars($r['author']); |
188 $author_bit .= $r['author_uid'] > 1 && !empty($r['username']) ? htmlspecialchars($r['username']) : htmlspecialchars($r['author']); |
189 $author_bit .= '</span>'; |
189 $author_bit .= '</span>'; |
190 $return .= '</td><td class="'.$cls.'">'.enano_date(ED_DATE | ED_TIME, $r['time_id']).'</td><td class="'.$cls.'">'.$author_bit.'</td><td class="'.$cls.'" style="cursor: pointer;" onclick="ajaxReverseDNS(this);" title="' . $lang->get('acpsl_tip_reverse_dns') . '">'.$r['edit_summary'].'</td></tr>'; |
190 $return .= '</td><td class="'.$cls.'">'.enano_date(ED_DATE | ED_TIME, $r['time_id']).'</td><td class="'.$cls.'">'.$author_bit.'</td><td class="'.$cls.'" style="cursor: pointer;" onclick="ajaxReverseDNS(this);" title="' . $lang->get('acpsl_tip_reverse_dns') . '">'.$r['edit_summary'].'</td></tr>'; |
191 return $return; |
191 return $return; |
192 } |
192 } |
193 |
193 |
194 ?> |
194 ?> |