1
|
|
|
<?php |
|
|
|
|
2
|
|
|
|
3
|
|
|
ini_set('error_log', 'syslog'); |
4
|
|
|
|
5
|
|
|
function username() { |
6
|
|
|
if (isset ($_SERVER['REMOTE_USER'])) $user = $_SERVER['REMOTE_USER']; |
7
|
|
|
else if (isset ($_SERVER['USER'])) $user = $_SERVER['USER']; |
8
|
|
|
else $user='unknown'; |
9
|
|
|
return $user; |
10
|
|
|
} |
11
|
|
|
|
12
|
|
|
function checkSSL() { |
|
|
|
|
13
|
|
|
if ( empty( $_SERVER['HTTPS'] ) ) |
14
|
|
|
printf ('<div id="content">Ehi sysadmin! Your site is not secure. Please enable SSL on your server and configure a redirect, such as' . |
15
|
|
|
'<pre>' . |
16
|
|
|
htmlspecialchars('<VirtualHost *:80>' . "\n" . |
17
|
|
|
' ServerName %s' . "\n" . |
18
|
|
|
' Redirect permanent / https://%s/' . "\n" . |
19
|
|
|
'</VirtualHost>') . |
20
|
|
|
'</pre></div>', gethostname(), gethostname()); |
21
|
|
|
} |
22
|
|
|
|
23
|
|
|
function myConnect($host, $user, $pass, $db, $port, $tablelist, $typedesc, $loguser) { |
24
|
|
|
$db = ( $tablelist["$typedesc"]['milter'] ) ? $tablelist["$typedesc"]['name'] : $db; |
25
|
|
|
$mysqli = new mysqli($host, $user, $pass, $db, $port); |
26
|
|
|
if ($mysqli->connect_error) { |
27
|
|
|
syslog (LOG_EMERG, $loguser.': Connect Error to DB <'.$db.'> (' . $mysqli->connect_errno . ') ' |
28
|
|
|
. $mysqli->connect_error); |
29
|
|
|
return FALSE; |
30
|
|
|
} |
31
|
|
|
syslog(LOG_INFO, $loguser.': Successfully MySQL connected at DB <'.$db.'> to ' . $mysqli->host_info) ; |
32
|
|
|
return $mysqli; |
33
|
|
|
} |
34
|
|
|
|
35
|
|
|
function addtolist ($myconn,$user,$value,$tabledesc,$expUnit,$expQ,$myreason,&$err) { |
36
|
|
|
// See MySQL manual for $expQ and $expUnit at |
37
|
|
|
// https://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_timestampadd |
38
|
|
|
|
39
|
|
|
$result=FALSE; |
40
|
|
|
$sub=array(); |
41
|
|
|
$type = $tabledesc['field']; |
42
|
|
|
$milt = $tabledesc['milter']; |
43
|
|
|
$table = ($milt) ? milterTable($type) : $tabledesc['name']; |
44
|
|
|
|
45
|
|
|
switch ($type) { |
46
|
|
|
case 'ip': |
47
|
|
|
$query= sprintf("INSERT INTO `$table` ( |
48
|
|
|
`$type` , |
49
|
|
|
`date` , |
50
|
|
|
`exp` , |
51
|
|
|
`active` , |
52
|
|
|
`user` , |
53
|
|
|
`reason` |
54
|
|
|
) |
55
|
|
|
VALUES ( |
56
|
|
|
INET_ATON( '%s' ) , |
57
|
|
|
CURRENT_TIMESTAMP , TIMESTAMPADD(%s,%d,CURRENT_TIMESTAMP), '1', '%s', '%s' |
58
|
|
|
)" ,$value,$expUnit,$expQ,$user,$myreason); |
59
|
|
|
break; |
60
|
|
|
|
61
|
|
|
case 'network': |
62
|
|
|
if (!$milt) { |
63
|
|
|
if ( netOverlap($myconn, $tabledesc, $value, $overlappedNet, $user) ) { |
64
|
|
|
$err = "<$value> overlaps the existing network <$overlappedNet>"; |
65
|
|
|
return FALSE; |
66
|
|
|
} |
67
|
|
|
} |
68
|
|
|
list($sub['net'],$sub['mask'])=explode('/',$value); |
69
|
|
|
$query= sprintf("INSERT INTO `$table` ( |
70
|
|
|
`$type` , |
71
|
|
|
`netmask`, |
72
|
|
|
`date` , |
73
|
|
|
`exp` , |
74
|
|
|
`active` , |
75
|
|
|
`user` , |
76
|
|
|
`reason` |
77
|
|
|
) |
78
|
|
|
VALUES ( |
79
|
|
|
INET_ATON( '%s' ) , INET_ATON( '%s' ) , |
80
|
|
|
CURRENT_TIMESTAMP , TIMESTAMPADD(%s,%d,CURRENT_TIMESTAMP), '1', '%s', '%s' |
81
|
|
|
)" ,$sub['net'],$sub['mask'],$expUnit,$expQ,$user,$myreason); |
82
|
|
|
break; |
83
|
|
|
|
84
|
|
|
default: |
85
|
|
|
$query= sprintf("INSERT INTO `$table` ( |
86
|
|
|
`$type` , |
87
|
|
|
`date` , |
88
|
|
|
`exp` , |
89
|
|
|
`active` , |
90
|
|
|
`user` , |
91
|
|
|
`reason` |
92
|
|
|
) |
93
|
|
|
VALUES ( |
94
|
|
|
'%s' , |
95
|
|
|
CURRENT_TIMESTAMP , TIMESTAMPADD(%s,%d,CURRENT_TIMESTAMP), '1', '%s', '%s' |
96
|
|
|
)" ,$value,$expUnit,$expQ,$user,$myreason); |
97
|
|
|
} |
98
|
|
|
|
99
|
|
|
if ($myconn->query($query) === TRUE) { |
100
|
|
|
syslog(LOG_INFO, "$user: $type <$value> successfully listed on <$table> for $expQ $expUnit."); |
101
|
|
|
$result=TRUE; |
102
|
|
|
} |
103
|
|
|
else syslog(LOG_ERR, "$user: Error: ".$myconn->error); |
104
|
|
|
return $result; |
105
|
|
|
} |
106
|
|
|
|
107
|
|
|
function relist ($myconn,$user,$value,$type,$table,$expUnit,$expQ,$myreason, $exptime = 0) { |
108
|
|
|
|
109
|
|
|
$result=FALSE; |
110
|
|
|
if ( $exptime ) { /* Entry already listed */ |
111
|
|
|
$nlist = '`nlist`'; |
112
|
|
|
$exptime = sprintf('\'%s\'', $exptime); /* Eh MySQL... an hour lost to notice this */ |
113
|
|
|
} |
114
|
|
|
else { |
115
|
|
|
$exptime = 'CURRENT_TIMESTAMP'; |
116
|
|
|
$nlist = '`nlist` + 1'; |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
switch ($type) { |
120
|
|
View Code Duplication |
case 'ip': |
|
|
|
|
121
|
|
|
$query= sprintf("UPDATE `$table` SET |
122
|
|
|
`active` = '1', |
123
|
|
|
`user` = '%s', |
124
|
|
|
`exp` = TIMESTAMPADD(%s,%d,%s), |
125
|
|
|
`nlist` = %s, |
126
|
|
|
`reason` = '%s' |
127
|
|
|
WHERE `$table`.`$type` = INET_ATON('%s') LIMIT 1" ,$user,$expUnit,$expQ,$exptime,$nlist,$myreason,$value); |
128
|
|
|
break; |
129
|
|
|
case 'network': |
130
|
|
|
list($sub['net'],$sub['mask'])=explode('/',$value); |
131
|
|
|
$query= sprintf("UPDATE `$table` SET |
132
|
|
|
`active` = '1', |
133
|
|
|
`user` = '%s', |
134
|
|
|
`exp` = TIMESTAMPADD(%s,%d,%s), |
135
|
|
|
`nlist` = %s, |
136
|
|
|
`reason` = '%s' |
137
|
|
|
WHERE (`$table`.`$type` = INET_ATON('%s') AND `$table`.`netmask` = INET_ATON('%s')) LIMIT 1" ,$user,$expUnit,$expQ,$exptime,$nlist,$myreason,$sub['net'],$sub['mask']); |
|
|
|
|
138
|
|
|
break; |
139
|
|
View Code Duplication |
default: |
|
|
|
|
140
|
|
|
$query= sprintf("UPDATE `$table` SET |
141
|
|
|
`active` = '1', |
142
|
|
|
`user` = '%s', |
143
|
|
|
`exp` = TIMESTAMPADD(%s,%d,%s), |
144
|
|
|
`nlist` = %s, |
145
|
|
|
`reason` = '%s' |
146
|
|
|
WHERE `$table`.`$type` = '%s' LIMIT 1" ,$user,$expUnit,$expQ,$exptime,$nlist,$myreason,$value); |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
if ($myconn->query($query) === TRUE) { |
150
|
|
|
syslog(LOG_INFO, "$user: relist $type <$value> on <$table> for $expQ $expUnit from $exptime."); |
151
|
|
|
$result=TRUE; |
152
|
|
|
} |
153
|
|
|
else syslog (LOG_ERR, "$user: Error: ". $myconn->error); |
154
|
|
|
return $result; |
155
|
|
|
} |
156
|
|
|
|
157
|
|
|
function remove ($myconn,$user,$value,$type,$table) { |
158
|
|
|
|
159
|
|
|
switch ($type) { |
160
|
|
|
case 'ip': |
161
|
|
|
$query = sprintf("DELETE FROM `$table` WHERE |
162
|
|
|
`$table`.`$type` = INET_ATON('%s') LIMIT 1", $value); |
163
|
|
|
break; |
164
|
|
View Code Duplication |
case 'network': |
|
|
|
|
165
|
|
|
list($sub['net'],$sub['mask'])=explode('/',$value); |
166
|
|
|
$query = sprintf("DELETE FROM `$table` WHERE |
167
|
|
|
`$table`.`$type` = INET_ATON('%s') AND `$table`.`netmask` = INET_ATON('%s') LIMIT 1", |
168
|
|
|
$sub['net'],$sub['mask']); |
|
|
|
|
169
|
|
|
break; |
170
|
|
|
default: |
171
|
|
|
$query = sprintf("DELETE FROM `$table` WHERE |
172
|
|
|
`$table`.`$type` = %s LIMIT 1", $value); |
173
|
|
|
} |
174
|
|
|
|
175
|
|
|
|
176
|
|
|
if ($return=$myconn->query($query) === TRUE) |
177
|
|
|
syslog(LOG_INFO, "$user: permanently DELETED $type <$value> from <$table>."); |
178
|
|
|
else syslog(LOG_ERR, "$user: Error: ". $myconn->error); |
179
|
|
|
|
180
|
|
|
return $return; |
181
|
|
|
} |
182
|
|
|
|
183
|
|
|
|
184
|
|
|
function changestatus ($myconn,$user,$value,$status,$type,$table) { |
185
|
|
|
|
186
|
|
|
switch ($type) { |
187
|
|
|
case 'ip': |
188
|
|
|
$query= sprintf("UPDATE `$table` SET `active` = '$status', `user` = '%s' WHERE `$table`.`$type` = INET_ATON('%s') LIMIT 1" ,$user, $value); |
189
|
|
|
break; |
190
|
|
|
case 'network': |
191
|
|
|
list($sub['net'],$sub['mask'])=explode('/',$value); |
192
|
|
|
$query= sprintf("UPDATE `$table` SET `active` = '$status', `user` = '%s' WHERE (`$table`.`$type` = INET_ATON('%s') AND `$table`.`netmask` = INET_ATON('%s')) LIMIT 1" ,$user, $sub['net'],$sub['mask']); |
|
|
|
|
193
|
|
|
break; |
194
|
|
|
default: |
195
|
|
|
$query= sprintf("UPDATE `$table` SET `active` = '$status', `user` = '%s' WHERE `$table`.`$type` = '%s' LIMIT 1" ,$user, $value); |
196
|
|
|
} |
197
|
|
|
|
198
|
|
|
if ($return=$myconn->query($query) === TRUE) { |
199
|
|
|
syslog(LOG_INFO, "$user: change status of $type <$value>. The status is now <$status>"); |
200
|
|
|
} |
201
|
|
|
else syslog(LOG_ERR, "$user: Error: ". $myconn->error); |
202
|
|
|
return $return; |
203
|
|
|
} |
204
|
|
|
|
205
|
|
|
|
206
|
|
|
function expire ($myconn,$user,$tables,$expireTime) { |
207
|
|
|
$return=TRUE; |
208
|
|
|
$log=array(); |
209
|
|
|
$desc = array_keys($tables); |
210
|
|
|
foreach ($desc as $tdesc) { |
211
|
|
|
/* QUERY */ |
212
|
|
|
$query = 'DELETE FROM `'.$tables["$tdesc"]['name']."` WHERE `exp` < DATE_SUB( NOW(), INTERVAL $expireTime YEAR);"; |
213
|
|
|
$query .= 'DELETE FROM `'.$tables["$tdesc"]['name']."` WHERE `datemod` < DATE_SUB( NOW(), INTERVAL $expireTime YEAR) AND `active` = 0"; |
214
|
|
|
/* END OF QUERY */ |
215
|
|
|
$log[0] = 'expired for'; |
216
|
|
|
$log[1] = 'disabled for'; |
217
|
|
|
if ($myconn->multi_query($query)) { |
218
|
|
|
$j = 0; |
219
|
|
|
do { |
220
|
|
|
$numdel = $myconn->affected_rows; |
221
|
|
|
syslog(LOG_INFO, "Expire job - <$user> Permanently DELETED $numdel records ".$log[$j]." $expireTime YEARS from <".$tables["$tdesc"]['name'].'>.'); |
222
|
|
|
$j++; |
223
|
|
|
|
224
|
|
|
} while ($myconn->next_result()); |
225
|
|
|
} |
226
|
|
|
else { |
227
|
|
|
syslog(LOG_ERR, "Expire job - Error: ". $myconn->error); |
228
|
|
|
$return = FALSE; |
229
|
|
|
} |
230
|
|
|
} |
231
|
|
|
if ( !($return) ) syslog(LOG_EMERG, 'End of Expire job with error. See above logs. SQL Connection terminated'); |
232
|
|
|
else syslog(LOG_INFO, 'Successfully End of Expire job. SQL Connection successfully terminated.'); |
233
|
|
|
return $return; |
234
|
|
|
} |
235
|
|
|
|
236
|
|
|
|
237
|
|
|
function isListed($row) { |
238
|
|
|
|
239
|
|
|
$exp=new DateTime($row['exp']); |
240
|
|
|
$now=new DateTime('NOW'); |
241
|
|
|
if (($exp > $now) and ($row['active'])) return true; |
242
|
|
|
else return false; |
243
|
|
|
|
244
|
|
|
} |
245
|
|
|
|
246
|
|
|
|
247
|
|
|
function askMilter($myconn,$id,$obj,$typedesc,$miltId,$value,$user,$adm) { |
248
|
|
|
$milts = readMiltName($myconn,$user); |
249
|
|
|
$size = count($milts); |
250
|
|
|
if (in_array($user,array_keys($adm))) { |
251
|
|
|
$button = <<<END |
252
|
|
|
<form style="margin:0; display:inline;" name="Milter$id" enctype="text/plain" method="post" target="_self" action="changeMilter.php" onSubmit="xmlhttpPost('changeMilter.php', 'Milter$id', 'id$id', '<img src=\'/include/pleasewait.gif\'>'); return false;" /> |
253
|
|
|
<input name="object" type="hidden" value="$obj" /><input name="oldvalues" type="hidden" value="$value" /> |
254
|
|
|
<input name="type" type="hidden" value="$typedesc" /> |
255
|
|
|
<input name="user" type="hidden" value="$user" /> |
256
|
|
|
<input name="miltId" type="hidden" value="$miltId" /> |
257
|
|
|
<div class="noscroll"> |
258
|
|
|
<select class="input_text" name="newvalues[]" multiple size="$size"> |
259
|
|
|
END; |
260
|
|
|
$activeMilts = explode(',',$value); |
261
|
|
|
foreach ( $milts as $milter ) { |
|
|
|
|
262
|
|
|
if ( in_array($milter, $activeMilts) ) |
263
|
|
|
$selected= 'selected'; |
264
|
|
|
else |
265
|
|
|
$selected= NULL; |
266
|
|
|
$button .= sprintf('<option value="%s" %s>%s</option>', $milter, $selected, $milter); |
267
|
|
|
} |
268
|
|
|
$button .= '</select></div><input class="button" name="Change" type="submit" value="Change" /></form>'; |
269
|
|
|
return $button; |
270
|
|
|
} |
271
|
|
|
return $value; |
272
|
|
|
|
273
|
|
|
|
274
|
|
|
} |
275
|
|
|
|
276
|
|
|
|
277
|
|
|
function ask($myconn,$id,$what,$alltables,$typedesc,$value,$lock,$user,$adm) { |
278
|
|
|
|
279
|
|
|
$whynot=NULL; |
280
|
|
|
switch ($what) { |
281
|
|
|
case 'Ok': |
282
|
|
|
if ($lock) return NULL; |
283
|
|
|
if (in_array($user,array_keys($adm))) |
284
|
|
|
if ( consistentListing($myconn,$alltables,$typedesc,$value,$whynot) ) return require('relistButton.php'); |
285
|
|
|
return htmlspecialchars($whynot); |
286
|
|
|
case 'Listed': |
287
|
|
|
case 'WhiteListed': |
288
|
|
|
return require('delistButton.php'); |
289
|
|
|
} |
290
|
|
|
} |
291
|
|
|
|
292
|
|
|
|
293
|
|
|
function consistentListing($myconn,$alltables,$typed,$value,&$warn) { |
294
|
|
|
/* Check if there are no pending mislisting */ |
295
|
|
|
$warn = NULL; |
296
|
|
|
if (! isset($alltables["$typed"]['depend']) ) return TRUE; |
297
|
|
|
foreach ($alltables["$typed"]['depend'] as $listdep) { |
298
|
|
|
if ($alltables["$typed"]['field'] != $alltables["$listdep"]['field'] ) { |
299
|
|
|
$warn = "Config ERROR: <$typed> and <$listdep> are of different types! I can't check consistency!"; |
300
|
|
|
return FALSE; |
301
|
|
|
} |
302
|
|
|
$entry = searchentry($myconn,$value,$alltables["$listdep"]); |
303
|
|
|
if ( $entry->num_rows ) { |
304
|
|
|
if ( $entry->num_rows == 1 ) { |
305
|
|
|
$riga = $entry->fetch_array(MYSQLI_ASSOC); |
306
|
|
|
if (isListed($riga)) { |
307
|
|
|
$warn = "<$value> is already present in <$listdep> list!"; |
308
|
|
|
$entry->free(); |
309
|
|
|
return FALSE; |
310
|
|
|
} |
311
|
|
|
} |
312
|
|
|
if ( $entry->num_rows > 1 ) {$warn = "<$value> seems to be present more than once in <$listdep>. Contact a sysadmin NOW!";} |
313
|
|
|
} |
314
|
|
|
$entry->free(); |
315
|
|
|
} |
316
|
|
|
|
317
|
|
|
return TRUE; |
318
|
|
|
} |
319
|
|
|
|
320
|
|
|
function searchentry ($myconn,$value,$tablelist) { |
321
|
|
|
/* Make a MYSQL query and return result */ |
322
|
|
|
|
323
|
|
|
$type = $tablelist['field']; |
324
|
|
|
|
325
|
|
|
if ( $tablelist['milter'] ) { |
326
|
|
|
$table = milterTable($type); |
327
|
|
|
if ($value == 'ALL') |
328
|
|
|
$query = sprintf('SELECT *, GROUP_CONCAT(milt.name) as miltnames FROM `%s` LEFT JOIN milt ON (%s.idmilt=milt.id) GROUP by idmilt', |
329
|
|
|
$table,$table); |
330
|
|
|
else { |
331
|
|
|
switch ($type) { |
332
|
|
View Code Duplication |
case 'network': |
|
|
|
|
333
|
|
|
list($sub['net'],$sub['mask'])=explode('/',$value); |
334
|
|
|
$query = sprintf('SELECT * FROM ( |
335
|
|
|
SELECT *, GROUP_CONCAT(milt.name) as miltnames FROM `%s` LEFT JOIN milt ON (%s.idmilt=milt.id) |
336
|
|
|
WHERE ( |
337
|
|
|
inet_aton(\'%s\') >= network AND |
338
|
|
|
( inet_aton(\'%s\') | ( inet_aton(\'%s\') ^ (power(2,32)-1) ) ) |
339
|
|
|
<= network | ( netmask ^ (power(2,32)-1) ) |
340
|
|
|
) |
341
|
|
|
GROUP by idmilt |
342
|
|
|
) AS val WHERE val.network IS NOT null', $table, $table, $sub['net'], $sub['net'], $sub['mask']); |
|
|
|
|
343
|
|
|
break; |
344
|
|
|
case 'ip': |
345
|
|
|
$query = sprintf('SELECT * FROM ( |
346
|
|
|
SELECT *, GROUP_CONCAT(milt.name) as miltnames FROM `%s` LEFT JOIN milt ON (%s.idmilt=milt.id)' . |
347
|
|
|
'WHERE `ip` = INET_ATON(\'%s\') |
348
|
|
|
) AS val WHERE val.ip IS NOT null', $table, $table, $value); |
349
|
|
|
break; |
350
|
|
|
default: |
351
|
|
|
syslog(LOG_EMERG, 'ALERT: The type <'.$type.'> is not allowed for milter lists.' ); |
352
|
|
|
return FALSE; |
353
|
|
|
} |
354
|
|
|
} |
355
|
|
|
} |
356
|
|
|
|
357
|
|
|
else { |
358
|
|
|
$table = $tablelist['name']; |
359
|
|
|
if ($value == 'ALL') $query = 'select * from '.$table; |
360
|
|
|
else { |
361
|
|
|
switch ($type) { |
362
|
|
|
case 'ip': |
363
|
|
|
$query= "select * from $table where $type = INET_ATON('$value')"; |
364
|
|
|
break; |
365
|
|
View Code Duplication |
case 'network': |
|
|
|
|
366
|
|
|
list($sub['net'],$sub['mask'])=explode('/',$value); |
367
|
|
|
$query= sprintf('select * from `%s` |
368
|
|
|
WHERE ( |
369
|
|
|
inet_aton(\'%s\') >= network AND |
370
|
|
|
( inet_aton(\'%s\') | ( inet_aton(\'%s\') ^ (power(2,32)-1) ) ) |
371
|
|
|
<= network | ( netmask ^ (power(2,32)-1) ) |
372
|
|
|
)', $table, $sub['net'], $sub['net'], $sub['mask']); |
373
|
|
|
; |
374
|
|
|
break; |
375
|
|
|
default: |
376
|
|
|
$query= "select * from $table where $type = '$value'"; |
377
|
|
|
} |
378
|
|
|
} |
379
|
|
|
} |
380
|
|
|
|
381
|
|
|
$result = $myconn->query($query); |
382
|
|
|
if($result === false) |
383
|
|
|
syslog(LOG_EMERG, "ALERT: Query <$query> failed: ".$myconn->error); |
384
|
|
|
return $result; |
385
|
|
|
} |
386
|
|
|
|
387
|
|
|
function countListed ($myconn,$table) { |
388
|
|
|
/* Return number of current listed items into a rbl table */ |
389
|
|
|
$query = "SELECT COUNT(*) as `count` FROM `$table` WHERE (`active`=1 AND TIMESTAMPDIFF(MICROSECOND,NOW(),`exp`)>0) GROUP BY `active` ORDER BY `count` DESC LIMIT 1"; |
390
|
|
|
$row = $myconn->query($query); |
391
|
|
|
$number = $row->fetch_array(MYSQLI_ASSOC); |
392
|
|
|
$number = $number['count']; |
393
|
|
|
$row->free(); |
394
|
|
|
return $number; |
395
|
|
|
} |
396
|
|
|
|
397
|
|
|
|
398
|
|
|
function isFull($myconn,$typedesc,$alltables) { |
399
|
|
|
if (isset($alltables["$typedesc"]['limit'])) { |
400
|
|
|
if ( $alltables["$typedesc"]['milter'] ) |
401
|
|
|
$tab = 'net'; |
402
|
|
|
else |
403
|
|
|
$tab = $alltables["$typedesc"]['name']; |
404
|
|
|
if ( countListed($myconn,$tab) >= $alltables["$typedesc"]['limit'] ) |
405
|
|
|
return TRUE; |
406
|
|
|
} |
407
|
|
|
return FALSE; |
408
|
|
|
} |
409
|
|
|
|
410
|
|
|
function rlookup ($myconn,$user,$adm,$value,$typedesc,$tables) { |
411
|
|
|
|
412
|
|
|
$type = $tables["$typedesc"]['field']; |
413
|
|
|
$whynot=NULL; |
414
|
|
|
|
415
|
|
|
$tabhtm = <<<END |
416
|
|
|
<table><thead><tr><th>$type</th><th title="The date this object has been listed for the first time">DateAdd</th><th>DateMod</th><th>Exp</th><th>Status</th><th title="Number of times this object has been listed">#List</th> |
417
|
|
|
END; |
418
|
|
|
if ( $tables["$typedesc"]['milter'] ) |
419
|
|
|
$tabhtm .= '<th title="Milter active for this object">Milters</th>'; |
420
|
|
|
$tabhtm .= '<th>Authored by</th><th width="250">Reason</th><th>Action</th></tr></thead><tfoot><tr></tr></tfoot><tbody>'."\n"; |
421
|
|
|
|
422
|
|
|
if ($type == 'domain') |
423
|
|
|
$value = nsdom($value); |
424
|
|
|
if (is_null($value)) |
425
|
|
|
return FALSE; |
426
|
|
|
|
427
|
|
|
$result = searchentry ($myconn,$value,$tables["$typedesc"]); |
428
|
|
|
if ($result) { |
429
|
|
|
printf("<pre>Your request for $type <$value> returned %d items.\n</pre>", $result->num_rows); |
430
|
|
|
|
431
|
|
|
/* Check for limit in number of listed items */ |
432
|
|
|
$full = isFull($myconn,$typedesc,$tables); |
433
|
|
|
if ($full) print '<p>'.htmlspecialchars("$typedesc has reached maximum value of ".$tables["$typedesc"]['limit'].' listed items.').'</p>'; |
434
|
|
|
|
435
|
|
|
if ($result->num_rows) { |
436
|
|
|
print $tabhtm; |
437
|
|
|
$i=0; |
438
|
|
|
while ($riga = $result->fetch_array(MYSQLI_ASSOC)) { |
439
|
|
|
if (isListed($riga)) { |
440
|
|
|
if ($tables["$typedesc"]['bl']) $listed='Listed'; |
441
|
|
|
else $listed='WhiteListed'; |
442
|
|
|
} |
443
|
|
|
else |
444
|
|
|
$listed='Ok'; |
445
|
|
|
|
446
|
|
|
switch ($type) { |
447
|
|
|
case 'ip': |
448
|
|
|
$element = long2ip($riga['ip']); |
449
|
|
|
break; |
450
|
|
View Code Duplication |
case 'network': |
451
|
|
|
$element = long2ip($riga['network']).'/'.long2ip($riga['netmask']); |
452
|
|
|
break; |
453
|
|
|
default: |
454
|
|
|
$element = $riga["$type"]; |
455
|
|
|
} |
456
|
|
|
|
457
|
|
|
if ( $tables["$typedesc"]['milter'] AND checkMilterConf($tables["$typedesc"]) ) |
|
|
|
|
458
|
|
|
printf ("<tr id=id$i><td id='status$listed'>%s</td><td id='status$listed'>%s</td><td id='status$listed'>%s</td><td id='status$listed'>%s</td><td id='status$listed'>%s</td><td id='status$listed'>%s</td><td nowrap id='status$listed'>%s</td><td id='status$listed'>%s</td><td id='status$listed'>%s</td><td>%s</td></tr>\n", |
459
|
|
|
$element, $riga['date'], $riga['datemod'], $riga['exp'], $riga['active'], $riga['nlist'], askMilter($myconn,$i,$element,$typedesc,$riga['idmilt'],$riga['miltnames'],$user,$adm), $riga['user'],htmlspecialchars($riga['reason']),ask($myconn,$i,$listed,$tables,$typedesc,$element,$full,$user,$adm)); |
460
|
|
|
else |
461
|
|
|
printf ("<tr id=id$i><td id='status$listed'>%s</td><td id='status$listed'>%s</td><td id='status$listed'>%s</td><td id='status$listed'>%s</td><td id='status$listed'>%s</td><td id='status$listed'>%s</td><td id='status$listed'>%s</td><td id='status$listed'>%s</td><td>%s</td></tr>\n", |
462
|
|
|
$element, $riga['date'], $riga['datemod'], $riga['exp'], $riga['active'], $riga['nlist'], $riga['user'],htmlspecialchars($riga['reason']),ask($myconn,$i,$listed,$tables,$typedesc,$element,$full,$user,$adm)); |
463
|
|
|
$i++; |
464
|
|
|
} |
465
|
|
|
print '</tbody></table>'; |
466
|
|
|
} |
467
|
|
|
else { |
468
|
|
|
print "<pre>$type <$value> is not listed!\n</pre>"; |
469
|
|
|
if ( in_array($user,array_keys($adm)) AND ($value != 'ALL') ) |
470
|
|
|
if ( (!$full) AND (consistentListing($myconn,$tables,$typedesc,$value,$whynot)) ) require_once('listForm.php'); |
471
|
|
|
else print '<p>'.htmlspecialchars($whynot).'</p>'; |
472
|
|
|
|
473
|
|
|
} |
474
|
|
|
$result->free(); |
475
|
|
|
} |
476
|
|
|
else print '<pre>Query error or something wrong in DB schema'."\n</pre>"; |
477
|
|
|
} |
478
|
|
|
|
479
|
|
|
|
480
|
|
|
|
481
|
|
|
|
482
|
|
|
function sendEmailWarn($tplf,$from,$to,$sbj,$emailListed,$intervalToExpire,$detail) { |
483
|
|
|
$now = time(); |
484
|
|
|
setlocale (LC_TIME, 'it_IT'); |
485
|
|
|
$date = date("r",$now); |
486
|
|
|
$messageID = md5(uniqid($now,1)) . '@' . gethostname(); |
487
|
|
|
$mua = 'PHP/' . phpversion(); |
488
|
|
|
|
489
|
|
|
/* Parsing headers */ |
490
|
|
View Code Duplication |
if (!file_exists($tplf['header'])) { |
491
|
|
|
syslog(LOG_ERR, 'Sending email... template file <'.$tplf['header'].'> not found!'); |
492
|
|
|
exit; |
493
|
|
|
} |
494
|
|
|
|
495
|
|
|
$head_tmpl = file_get_contents($tplf['header']); |
496
|
|
|
$arr_tpl_vars = array('{from}','{to}','{date}','{messageID}','{mua}'); |
497
|
|
|
$arr_tpl_data = array($from,$to,$date,$messageID,$mua); |
498
|
|
|
$headers = str_replace($arr_tpl_vars, $arr_tpl_data, $head_tmpl); |
499
|
|
|
$headers = preg_replace( '/\r|\n/', "\r\n", $headers ); |
500
|
|
|
|
501
|
|
|
/* Parsing body */ |
502
|
|
|
|
503
|
|
View Code Duplication |
if (!file_exists($tplf['body'])) { |
504
|
|
|
syslog(LOG_ERR, 'Sending email... template file <'.$tplf['body'].'> not found!'); |
505
|
|
|
exit; |
506
|
|
|
} |
507
|
|
|
|
508
|
|
|
$body_tmpl = file_get_contents($tplf['body']); |
509
|
|
|
$arr_tpl_vars = array('{emailListed}','{expInterval}','{reason}'); |
510
|
|
|
$arr_tpl_data = array($emailListed,$intervalToExpire,$detail); |
511
|
|
|
$body = str_replace($arr_tpl_vars, $arr_tpl_data, $body_tmpl); |
512
|
|
|
$body = preg_replace( "/\r|\n/", "\r\n", $body ); |
513
|
|
|
$body = wordwrap ( $body, 75 , "\r\n" ); |
514
|
|
|
|
515
|
|
|
/* Send the mail! */ |
516
|
|
|
if ( strlen(ini_get("safe_mode"))< 1) { |
517
|
|
|
$old_mailfrom = ini_get("sendmail_from"); |
518
|
|
|
ini_set("sendmail_from", $from); |
519
|
|
|
$params = sprintf("-oi -f %s", '<>'); |
520
|
|
View Code Duplication |
if (!(mail($to,$sbj, $body,$headers,$params))) $flag=FALSE; |
521
|
|
|
else $flag=TRUE; |
522
|
|
|
if (isset($old_mailfrom)) |
523
|
|
|
ini_set("sendmail_from", $old_mailfrom); |
524
|
|
|
} |
525
|
|
View Code Duplication |
else { |
526
|
|
|
if (!(mail($to,$sbj, $body,$headers))) $flag=FALSE; |
527
|
|
|
else $flag=TRUE; |
528
|
|
|
} |
529
|
|
|
return $flag; |
530
|
|
|
} |
531
|
|
|
|
532
|
|
|
function emailToNotify($notify_file,$dom) { |
533
|
|
|
$ini_array = parse_ini_file($notify_file); |
534
|
|
|
if (in_array($dom,array_keys($ini_array))) |
535
|
|
|
return $ini_array["$dom"]; |
536
|
|
|
else return FALSE; |
537
|
|
|
} |
538
|
|
|
|
539
|
|
|
|
540
|
|
|
function searchAndList ($myconn,$loguser,$tables,$typedesc,$value,$unit,&$quantity,&$reason) { |
541
|
|
|
|
542
|
|
|
/* Search and list value */ |
543
|
|
|
$type = $tables["$typedesc"]['field']; |
544
|
|
|
$table = $tables["$typedesc"]['name']; |
545
|
|
|
$result = searchentry ($myconn,$value,$tables["$typedesc"]); |
546
|
|
|
|
547
|
|
|
/* Manage abnormal conditions */ |
548
|
|
|
/* Value already present in db more than once. This is absurd. Panic! */ |
549
|
|
|
if ($result->num_rows > 1) { |
550
|
|
|
syslog(LOG_EMERG,"$loguser: PANIC! Select for $type '$value' returned ". $result->num_rows ." items instead of one. Abnormal. Contact a sysadmin or a developer."); |
551
|
|
|
$result->free(); |
552
|
|
|
return FALSE; |
553
|
|
|
} |
554
|
|
|
|
555
|
|
|
/* Value already present in db or not present: to list anyway */ |
556
|
|
|
if ($result->num_rows >= 0) { |
557
|
|
|
/* First, check for limit in number of listed items */ |
558
|
|
|
if (isFull($myconn,$typedesc,$tables)) { |
559
|
|
|
syslog(LOG_EMERG,"$loguser: $typedesc has reached maximum value of ".$tables["$typedesc"]['limit'].' listed items. Abnormal exit.'); |
560
|
|
|
$result->free(); |
561
|
|
|
return FALSE; |
562
|
|
|
} |
563
|
|
|
/* Second, check if the (re)list would be consistent now */ |
564
|
|
|
if (! consistentListing($myconn,$tables,$typedesc,$value,$whynot) ) { |
565
|
|
|
syslog(LOG_ERR, $loguser.': '.$whynot); |
566
|
|
|
$result->free(); |
567
|
|
|
return FALSE; |
568
|
|
|
} |
569
|
|
|
} |
570
|
|
|
/* End of abnormal conditions */ |
571
|
|
|
|
572
|
|
|
|
573
|
|
|
/* Finally, here I can list the value! */ |
574
|
|
|
$thisentry = $result->fetch_array(MYSQLI_ASSOC); |
575
|
|
|
switch ($result->num_rows) { |
576
|
|
|
/* Relist value if already present */ |
577
|
|
|
case 1: |
578
|
|
|
if ( isListed($thisentry) ) { |
579
|
|
|
/* Entry already listed */ |
580
|
|
|
$expdate = $thisentry['exp']; |
581
|
|
|
$reason = sprintf('%s. Already listed. Adding 1 DAY to previous expire date.', |
582
|
|
|
$reason); |
583
|
|
|
$quantity = 1; |
584
|
|
|
$unit = 'DAY'; |
585
|
|
|
} |
586
|
|
|
else { |
587
|
|
|
/* Entry delisted */ |
588
|
|
|
$quantity *= $thisentry['nlist']; |
589
|
|
|
$expdate = 0; /* This forces expiration from CURRENT_TIMESTAMP */ |
590
|
|
|
} |
591
|
|
|
$result->free(); |
592
|
|
|
return relist ($myconn,$loguser,$value,$type,$table,$unit,$quantity,$reason, $expdate); |
593
|
|
|
|
594
|
|
|
/* First time list value */ |
595
|
|
|
case 0: |
596
|
|
|
$result->free(); |
597
|
|
|
return addtolist ($myconn,$loguser,$value,$tables["$typedesc"],$unit,$quantity,$reason,$_); |
598
|
|
|
} |
599
|
|
|
} |
600
|
|
|
|
601
|
|
|
|
602
|
|
|
/*************** Functions to check if two net overlap each other ********************/ |
603
|
|
|
|
604
|
|
|
function ipRange ($range) { |
605
|
|
|
/* List IP in range */ |
606
|
|
|
return array_map('long2ip', range( ip2long($range[0]), ip2long($range[1]) ) ); |
607
|
|
|
} |
608
|
|
|
|
609
|
|
|
function isIn($netA, $netB) { |
610
|
|
|
/* TRUE if an IP of $netA is contained in netB */ |
611
|
|
|
list($addressA,$maskA) = explode('/', $netA); |
612
|
|
|
list($addressB,$maskB) = explode('/', $netB); |
613
|
|
|
require_once 'vendor/autoload.php'; |
614
|
|
|
$net = new \dautkom\ipv4\IPv4(); |
615
|
|
|
$range = $net->address($addressA)->mask($maskA)->getRange(); |
616
|
|
|
$ips = ipRange($range); |
617
|
|
|
foreach ( $ips as $ip ) |
618
|
|
|
if ( $net->address($addressB)->mask($maskB)->has($ip) ) |
619
|
|
|
return TRUE; |
620
|
|
|
return FALSE; |
621
|
|
|
} |
622
|
|
|
|
623
|
|
|
function netOverlap($myconn, $tabletype, $net, &$thisNet, $loguser) { |
624
|
|
|
/* return TRUE if $net overlap an existing network into DB */ |
625
|
|
|
$thisNet = NULL; |
626
|
|
|
if ($tabletype['field'] != 'network') { |
627
|
|
|
syslog(LOG_ERR, $loguser.': '.$tabletype['name'].' is not a network list.'); |
628
|
|
|
return FALSE; |
629
|
|
|
} |
630
|
|
|
$result = searchentry ($myconn,'ALL',$tabletype); |
631
|
|
|
if ($result->num_rows) { |
632
|
|
|
while ($row = $result->fetch_array(MYSQLI_ASSOC)) { |
633
|
|
|
$thisNet = long2ip($row['network']).'/'.long2ip($row['netmask']); |
634
|
|
|
if ( isIn($thisNet, $net) ) { |
635
|
|
|
$result->free(); |
636
|
|
|
syslog(LOG_INFO, "$loguser: the net <$net> overlaps the existing network <$thisNet>."); |
637
|
|
|
return TRUE; |
638
|
|
|
} |
639
|
|
|
} |
640
|
|
|
} |
641
|
|
|
$result->free(); |
642
|
|
|
return FALSE; |
643
|
|
|
} |
644
|
|
|
|
645
|
|
|
/*********************************************************************************************/ |
646
|
|
|
|
647
|
|
|
|
648
|
|
|
/* For miltermap */ |
649
|
|
|
function checkMilterConf($table) { |
650
|
|
|
if (isset($table['milter'])) { |
651
|
|
|
if ($table['milter'] === TRUE) { |
652
|
|
|
switch ( $table['field'] ) { |
653
|
|
|
case 'network': |
654
|
|
|
case 'ip': |
655
|
|
|
return TRUE; |
656
|
|
|
} |
657
|
|
|
} |
658
|
|
|
} |
659
|
|
|
return FALSE; |
660
|
|
|
} |
661
|
|
|
|
662
|
|
|
/* |
663
|
|
|
function enterDBMilt($myconn,$tables,$loguser) { |
664
|
|
|
if (!($myconn->select_db($tables('name')))) { |
665
|
|
|
syslog(LOG_ERR, $loguser.': Can\'t enter into DB '.$tables('name')); |
666
|
|
|
return FALSE; |
667
|
|
|
} |
668
|
|
|
return TRUE; |
669
|
|
|
} |
670
|
|
|
*/ |
671
|
|
|
|
672
|
|
|
function milterTable($t) { |
673
|
|
|
/* Return the milter object table for type t or FALSE on error */ |
674
|
|
|
switch ($t) { |
675
|
|
|
case 'network': |
676
|
|
|
return 'net'; |
677
|
|
|
case 'ip': |
678
|
|
|
return 'ips'; |
679
|
|
|
default: |
680
|
|
|
syslog(LOG_EMERG, "ALERT: type <$t> not allowed in configuration. "); |
681
|
|
|
return FALSE; |
682
|
|
|
} |
683
|
|
|
} |
684
|
|
|
|
685
|
|
|
|
686
|
|
|
function readMiltName($myconn,$loguser) { |
687
|
|
|
$milters=array(); |
688
|
|
|
$query = 'SELECT `name` FROM `config`'; |
689
|
|
|
|
690
|
|
|
$result = $myconn->query($query); |
691
|
|
|
if($result === false) { |
692
|
|
|
syslog(LOG_EMERG, "$loguser: ALERT: Query <$query> failed: ".$myconn->error); |
693
|
|
|
return FALSE; |
694
|
|
|
} |
695
|
|
|
if ($result->num_rows) { |
696
|
|
|
while ($milt = $result->fetch_array(MYSQLI_ASSOC)) |
697
|
|
|
$milters[] = $milt['name']; |
698
|
|
|
} |
699
|
|
|
$result->free(); |
700
|
|
|
return $milters; |
701
|
|
|
} |
702
|
|
|
|
703
|
|
|
function changeMilter ($myconn,$loguser,$miltVal,$table,$miltID) { |
704
|
|
|
$query = array(); |
705
|
|
|
foreach ( $miltVal as $value => $action ) { |
706
|
|
|
switch ( $action ) { |
707
|
|
|
case 'keep': |
708
|
|
|
break; |
709
|
|
|
case 'add': |
710
|
|
|
$query[] = sprintf( "INSERT INTO `milt` ( |
711
|
|
|
`id` , |
712
|
|
|
`name` |
713
|
|
|
) |
714
|
|
|
VALUES ( |
715
|
|
|
%d , |
716
|
|
|
'%s' |
717
|
|
|
)",$miltID,$value); |
718
|
|
|
break; |
719
|
|
|
case 'del': |
720
|
|
|
$query[] = "DELETE FROM `milt` WHERE (`id` = '$miltID' AND `name` = '$value')"; |
721
|
|
|
} |
722
|
|
|
} |
723
|
|
|
if ( count($query) ) /* This "if" is redundant, because if I call this I already checked there is a change */ |
724
|
|
|
/* I update datemod because the user couldn't change */ |
725
|
|
|
$query[] = sprintf('UPDATE `%s` SET |
726
|
|
|
`user`=\'%s\', |
727
|
|
|
`datemod`= CURRENT_TIMESTAMP |
728
|
|
|
WHERE `idmilt`=%d', $table, $loguser, $miltID); |
729
|
|
|
|
730
|
|
|
|
731
|
|
|
/* Start a safe transaction: it commits only if all queries happen */ |
732
|
|
|
$myconn->autocommit(FALSE); |
733
|
|
|
$myconn->begin_transaction(MYSQLI_TRANS_START_READ_ONLY); |
734
|
|
|
$ok = TRUE; |
735
|
|
|
foreach ( $query as $q ) { |
736
|
|
|
if ($myconn->query($q) !== TRUE) { |
737
|
|
|
$ok = FALSE; |
738
|
|
|
syslog(LOG_ERR, "$loguser: Error: ".$myconn->error); |
739
|
|
|
} |
740
|
|
|
} |
741
|
|
|
if ( $ok ) { |
742
|
|
|
if ( $myconn->commit() ) |
743
|
|
|
syslog(LOG_INFO, "$loguser: Milter setting changed successfully."); |
744
|
|
|
else { |
745
|
|
|
syslog(LOG_ERR, "$loguser: Milter setting NOT changed for an unpredictable COMMIT error."); |
746
|
|
|
if ( $myconn->rollback() ) |
747
|
|
|
syslog(LOG_INFO, "$loguser: rollback succeeded."); |
748
|
|
|
else |
749
|
|
|
syslog(LOG_ERR, "$loguser: rollback failed. Your db could be compromized. Check it!"); |
750
|
|
|
$ok = FALSE; |
751
|
|
|
} |
752
|
|
|
} |
753
|
|
|
else |
754
|
|
|
syslog(LOG_ERR, "$loguser: Error: Milter setting NOT changed. See at above errors."); |
755
|
|
|
return $ok; |
756
|
|
|
|
757
|
|
|
} |
758
|
|
|
|
759
|
|
|
|
760
|
|
|
function curl_get($url, array $get = NULL, array $options = array(), $loguser) |
761
|
|
|
{ |
762
|
|
|
$defaults = array( |
763
|
|
|
CURLOPT_URL => $url. (strpos($url, '?') === FALSE ? '?' : ''). http_build_query($get), |
764
|
|
|
CURLOPT_HEADER => 0, |
765
|
|
|
CURLOPT_RETURNTRANSFER => TRUE, |
766
|
|
|
CURLOPT_TIMEOUT => 4 |
767
|
|
|
); |
768
|
|
|
|
769
|
|
|
$ch = curl_init(); |
770
|
|
|
curl_setopt_array($ch, ($options + $defaults)); |
771
|
|
|
if( ! $result = curl_exec($ch)) |
772
|
|
|
{ |
773
|
|
|
syslog(LOG_ERR, sprintf('%s: CURL Error: <%s>', $loguser, curl_error($ch))); |
774
|
|
|
} |
775
|
|
|
curl_close($ch); |
776
|
|
|
return $result; |
777
|
|
|
} |
778
|
|
|
|
779
|
|
|
|
780
|
|
|
function nsdom($dom) { |
781
|
|
|
/* Return the first upper domain (or domain itself) with NS record */ |
782
|
|
|
if (checkdnsrr ( $dom , 'NS' )) |
783
|
|
|
return rtrim($dom, '.'); |
784
|
|
|
if (checkdnsrr ( $dom , 'A' )) |
785
|
|
|
return nsdom( ltrim(strstr($dom, '.'), '.') ); |
786
|
|
|
return NULL; |
787
|
|
|
} |
788
|
|
|
|
789
|
|
|
function isValid($dom) { |
790
|
|
|
/* Return TRUE id domain has NS or A record */ |
791
|
|
|
if (checkdnsrr ( $dom , 'NS' )) |
792
|
|
|
return TRUE; |
793
|
|
|
if (checkdnsrr ( $dom , 'A' )) |
794
|
|
|
return TRUE; |
795
|
|
|
return FALSE; |
796
|
|
|
} |
797
|
|
|
|
798
|
|
|
/* |
|
|
|
|
799
|
|
|
function checkEmailAddress($email) { |
800
|
|
|
if(preg_match("/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$/", $email)) |
801
|
|
|
return true; |
802
|
|
|
return false; |
803
|
|
|
} |
804
|
|
|
|
805
|
|
|
function checkIP($ip) |
806
|
|
|
{ |
807
|
|
|
$cIP = ip2long($ip); |
808
|
|
|
$fIP = long2ip($cIP); |
809
|
|
|
if ($fIP == '0.0.0.0') return FALSE; |
810
|
|
|
return TRUE; |
811
|
|
|
} |
812
|
|
|
*/ |
813
|
|
|
?> |
814
|
|
|
|
815
|
|
|
|
The PSR-1: Basic Coding Standard recommends that a file should either introduce new symbols, that is classes, functions, constants or similar, or have side effects. Side effects are anything that executes logic, like for example printing output, changing ini settings or writing to a file.
The idea behind this recommendation is that merely auto-loading a class should not change the state of an application. It also promotes a cleaner style of programming and makes your code less prone to errors, because the logic is not spread out all over the place.
To learn more about the PSR-1, please see the PHP-FIG site on the PSR-1.