206 |
206 |
function captiveportal_configure() {
|
207 |
207 |
global $config, $g;
|
208 |
208 |
|
209 |
|
$captiveportallck = lock('captiveportal');
|
|
209 |
$captiveportallck = lock('captiveportal', LOCK_EX);
|
210 |
210 |
|
211 |
211 |
if (isset($config['captiveportal']['enable'])) {
|
212 |
212 |
|
... | ... | |
233 |
233 |
captiveportal_init_rules(true);
|
234 |
234 |
|
235 |
235 |
/* stop accounting on all clients */
|
236 |
|
captiveportal_radius_stop_all(true);
|
|
236 |
captiveportal_radius_stop_all();
|
237 |
237 |
|
238 |
238 |
/* initialize minicron interval value */
|
239 |
239 |
$croninterval = $config['captiveportal']['croninterval'] ? $config['captiveportal']['croninterval'] : 60;
|
... | ... | |
415 |
415 |
"/etc/rc.prunecaptiveportal");
|
416 |
416 |
|
417 |
417 |
/* generate radius server database */
|
418 |
|
if ($config['captiveportal']['radiusip'] && (!isset($config['captiveportal']['auth_method']) ||
|
419 |
|
($config['captiveportal']['auth_method'] == "radius"))) {
|
420 |
|
$radiusip = $config['captiveportal']['radiusip'];
|
421 |
|
$radiusip2 = ($config['captiveportal']['radiusip2']) ? $config['captiveportal']['radiusip2'] : null;
|
422 |
|
|
423 |
|
if ($config['captiveportal']['radiusport'])
|
424 |
|
$radiusport = $config['captiveportal']['radiusport'];
|
425 |
|
else
|
426 |
|
$radiusport = 1812;
|
427 |
|
|
428 |
|
if ($config['captiveportal']['radiusacctport'])
|
429 |
|
$radiusacctport = $config['captiveportal']['radiusacctport'];
|
430 |
|
else
|
431 |
|
$radiusacctport = 1813;
|
432 |
|
|
433 |
|
if ($config['captiveportal']['radiusport2'])
|
434 |
|
$radiusport2 = $config['captiveportal']['radiusport2'];
|
435 |
|
else
|
436 |
|
$radiusport2 = 1812;
|
437 |
|
|
438 |
|
$radiuskey = $config['captiveportal']['radiuskey'];
|
439 |
|
$radiuskey2 = ($config['captiveportal']['radiuskey2']) ? $config['captiveportal']['radiuskey2'] : null;
|
440 |
|
|
441 |
|
$fd = @fopen("{$g['vardb_path']}/captiveportal_radius.db", "w");
|
442 |
|
if (!$fd) {
|
443 |
|
printf("Error: cannot open radius DB file in captiveportal_configure().\n");
|
444 |
|
return 1;
|
445 |
|
} else if (isset($radiusip2, $radiuskey2)) {
|
446 |
|
fwrite($fd,$radiusip . "," . $radiusport . "," . $radiusacctport . "," . $radiuskey . "\n"
|
447 |
|
. $radiusip2 . "," . $radiusport2 . "," . $radiusacctport . "," . $radiuskey2);
|
448 |
|
} else {
|
449 |
|
fwrite($fd,$radiusip . "," . $radiusport . "," . $radiusacctport . "," . $radiuskey);
|
450 |
|
}
|
451 |
|
fclose($fd);
|
452 |
|
}
|
|
418 |
captiveportal_init_radius_servers();
|
453 |
419 |
|
454 |
420 |
if ($g['booting'])
|
455 |
421 |
echo "done\n";
|
... | ... | |
458 |
424 |
killbypid("{$g['varrun_path']}/lighty-CaptivePortal.pid");
|
459 |
425 |
killbypid("{$g['varrun_path']}/minicron.pid");
|
460 |
426 |
|
461 |
|
captiveportal_radius_stop_all(true);
|
|
427 |
captiveportal_radius_stop_all();
|
462 |
428 |
|
463 |
429 |
mwexec("/sbin/sysctl net.link.ether.ipfw=0");
|
464 |
430 |
|
... | ... | |
732 |
698 |
!isset($config['captiveportal']['radiussession_timeout']) && !isset($config['voucher']['enable']))
|
733 |
699 |
return;
|
734 |
700 |
|
735 |
|
$captiveportallck = lock('captiveportal', LOCK_EX);
|
736 |
|
|
737 |
701 |
/* read database */
|
738 |
702 |
$cpdb = captiveportal_read_db();
|
739 |
703 |
|
... | ... | |
862 |
826 |
|
863 |
827 |
/* write database */
|
864 |
828 |
captiveportal_write_db($cpdb);
|
865 |
|
|
866 |
|
unlock($captiveportallck);
|
867 |
829 |
}
|
868 |
830 |
|
869 |
831 |
/* remove a single client according to the DB entry */
|
870 |
832 |
function captiveportal_disconnect($dbent, $radiusservers,$term_cause = 1,$stop_time = null) {
|
871 |
|
|
872 |
833 |
global $g, $config;
|
873 |
834 |
|
874 |
835 |
$stop_time = (empty($stop_time)) ? time() : $stop_time;
|
... | ... | |
876 |
837 |
/* this client needs to be deleted - remove ipfw rules */
|
877 |
838 |
if (isset($config['captiveportal']['radacct_enable']) && !empty($radiusservers)) {
|
878 |
839 |
RADIUS_ACCOUNTING_STOP($dbent[1], // ruleno
|
879 |
|
$dbent[4], // username
|
880 |
|
$dbent[5], // sessionid
|
881 |
|
$dbent[0], // start time
|
882 |
|
$radiusservers,
|
883 |
|
$dbent[2], // clientip
|
884 |
|
$dbent[3], // clientmac
|
885 |
|
$term_cause, // Acct-Terminate-Cause
|
886 |
|
false,
|
887 |
|
$stop_time);
|
|
840 |
$dbent[4], // username
|
|
841 |
$dbent[5], // sessionid
|
|
842 |
$dbent[0], // start time
|
|
843 |
$radiusservers,
|
|
844 |
$dbent[2], // clientip
|
|
845 |
$dbent[3], // clientmac
|
|
846 |
$term_cause, // Acct-Terminate-Cause
|
|
847 |
false,
|
|
848 |
$stop_time);
|
888 |
849 |
}
|
889 |
850 |
/* Delete client's ip entry from tables 3 and 4. */
|
890 |
851 |
mwexec("/sbin/ipfw table 1 delete {$dbent[2]}");
|
... | ... | |
910 |
871 |
|
911 |
872 |
/* remove a single client by ipfw rule number */
|
912 |
873 |
function captiveportal_disconnect_client($id,$term_cause = 1) {
|
913 |
|
|
914 |
874 |
global $g, $config;
|
915 |
875 |
|
916 |
|
$captiveportallck = lock('captiveportal', LOCK_EX);
|
917 |
|
|
918 |
876 |
/* read database */
|
919 |
877 |
$cpdb = captiveportal_read_db();
|
920 |
878 |
$radiusservers = captiveportal_get_radius_servers();
|
921 |
879 |
|
922 |
880 |
/* find entry */
|
923 |
|
$tmpindex = 0;
|
924 |
|
$cpdbcount = count($cpdb);
|
925 |
|
for ($i = 0; $i < $cpdbcount; $i++) {
|
926 |
|
if ($cpdb[$i][1] == $id) {
|
927 |
|
captiveportal_disconnect($cpdb[$i], $radiusservers, $term_cause);
|
928 |
|
captiveportal_logportalauth($cpdb[$i][4], $cpdb[$i][3], $cpdb[$i][2], "DISCONNECT");
|
|
881 |
foreach ($cpdb as $i => $cpentry) {
|
|
882 |
if ($cpentry[1] == $id) {
|
|
883 |
captiveportal_disconnect($cpentry, $radiusservers, $term_cause);
|
|
884 |
captiveportal_logportalauth($cpentry[4], $cpentry[3], $cpentry[2], "DISCONNECT");
|
929 |
885 |
unset($cpdb[$i]);
|
930 |
886 |
break;
|
931 |
887 |
}
|
... | ... | |
933 |
889 |
|
934 |
890 |
/* write database */
|
935 |
891 |
captiveportal_write_db($cpdb);
|
936 |
|
|
937 |
|
unlock($captiveportallck);
|
938 |
892 |
}
|
939 |
893 |
|
940 |
894 |
/* send RADIUS acct stop for all current clients */
|
941 |
|
function captiveportal_radius_stop_all($lock = false) {
|
942 |
|
global $g, $config;
|
|
895 |
function captiveportal_radius_stop_all() {
|
|
896 |
global $config;
|
943 |
897 |
|
944 |
898 |
if (!isset($config['captiveportal']['radacct_enable']))
|
945 |
899 |
return;
|
946 |
900 |
|
947 |
|
if (!$lock)
|
948 |
|
$captiveportallck = lock('captiveportal');
|
949 |
|
|
950 |
|
$cpdb = captiveportal_read_db();
|
951 |
|
|
952 |
901 |
$radiusservers = captiveportal_get_radius_servers();
|
953 |
902 |
if (!empty($radiusservers)) {
|
954 |
|
for ($i = 0; $i < count($cpdb); $i++) {
|
955 |
|
RADIUS_ACCOUNTING_STOP($cpdb[$i][1], // ruleno
|
956 |
|
$cpdb[$i][4], // username
|
957 |
|
$cpdb[$i][5], // sessionid
|
958 |
|
$cpdb[$i][0], // start time
|
959 |
|
$radiusservers,
|
960 |
|
$cpdb[$i][2], // clientip
|
961 |
|
$cpdb[$i][3], // clientmac
|
962 |
|
7); // Admin Reboot
|
|
903 |
$cpdb = captiveportal_read_db();
|
|
904 |
foreach ($cpdb as $cpentry) {
|
|
905 |
RADIUS_ACCOUNTING_STOP($cpentry[1], // ruleno
|
|
906 |
$cpentry[4], // username
|
|
907 |
$cpentry[5], // sessionid
|
|
908 |
$cpentry[0], // start time
|
|
909 |
$radiusservers,
|
|
910 |
$cpentry[2], // clientip
|
|
911 |
$cpentry[3], // clientmac
|
|
912 |
7); // Admin Reboot
|
963 |
913 |
}
|
964 |
914 |
}
|
965 |
|
if (!$lock)
|
966 |
|
unlock($captiveportallck);
|
967 |
915 |
}
|
968 |
916 |
|
969 |
917 |
function captiveportal_passthrumac_configure_entry($macent) {
|
... | ... | |
1125 |
1073 |
return 0;
|
1126 |
1074 |
}
|
1127 |
1075 |
|
|
1076 |
function captiveportal_init_radius_servers() {
|
|
1077 |
global $config, $g;
|
|
1078 |
|
|
1079 |
/* generate radius server database */
|
|
1080 |
if ($config['captiveportal']['radiusip'] && (!isset($config['captiveportal']['auth_method']) ||
|
|
1081 |
($config['captiveportal']['auth_method'] == "radius"))) {
|
|
1082 |
$radiusip = $config['captiveportal']['radiusip'];
|
|
1083 |
$radiusip2 = ($config['captiveportal']['radiusip2']) ? $config['captiveportal']['radiusip2'] : null;
|
|
1084 |
|
|
1085 |
if ($config['captiveportal']['radiusport'])
|
|
1086 |
$radiusport = $config['captiveportal']['radiusport'];
|
|
1087 |
else
|
|
1088 |
$radiusport = 1812;
|
|
1089 |
if ($config['captiveportal']['radiusacctport'])
|
|
1090 |
$radiusacctport = $config['captiveportal']['radiusacctport'];
|
|
1091 |
else
|
|
1092 |
$radiusacctport = 1813;
|
|
1093 |
if ($config['captiveportal']['radiusport2'])
|
|
1094 |
$radiusport2 = $config['captiveportal']['radiusport2'];
|
|
1095 |
else
|
|
1096 |
$radiusport2 = 1812;
|
|
1097 |
$radiuskey = $config['captiveportal']['radiuskey'];
|
|
1098 |
$radiuskey2 = ($config['captiveportal']['radiuskey2']) ? $config['captiveportal']['radiuskey2'] : null;
|
|
1099 |
|
|
1100 |
$cprdsrvlck = lock('captiveportalradius', LOCK_EX);
|
|
1101 |
$fd = @fopen("{$g['vardb_path']}/captiveportal_radius.db", "w");
|
|
1102 |
if (!$fd) {
|
|
1103 |
captiveportal_syslog("Error: cannot open radius DB file in captiveportal_configure().\n");
|
|
1104 |
unlock($cprdsrvlck);
|
|
1105 |
return 1;
|
|
1106 |
} else if (isset($radiusip2, $radiuskey2))
|
|
1107 |
fwrite($fd,$radiusip . "," . $radiusport . "," . $radiusacctport . "," . $radiuskey . "\n"
|
|
1108 |
. $radiusip2 . "," . $radiusport2 . "," . $radiusacctport . "," . $radiuskey2);
|
|
1109 |
else
|
|
1110 |
fwrite($fd,$radiusip . "," . $radiusport . "," . $radiusacctport . "," . $radiuskey);
|
|
1111 |
fclose($fd);
|
|
1112 |
unlock($cprdsrvlck);
|
|
1113 |
}
|
|
1114 |
}
|
|
1115 |
|
1128 |
1116 |
/* read RADIUS servers into array */
|
1129 |
1117 |
function captiveportal_get_radius_servers() {
|
1130 |
|
|
1131 |
1118 |
global $g;
|
1132 |
1119 |
|
|
1120 |
$cprdsrvlck = lock('captiveportalradius');
|
1133 |
1121 |
if (file_exists("{$g['vardb_path']}/captiveportal_radius.db")) {
|
1134 |
1122 |
$radiusservers = array();
|
1135 |
1123 |
$cpradiusdb = file("{$g['vardb_path']}/captiveportal_radius.db",
|
... | ... | |
1144 |
1132 |
}
|
1145 |
1133 |
}
|
1146 |
1134 |
|
|
1135 |
unlock('captiveportalradius');
|
1147 |
1136 |
return $radiusservers;
|
1148 |
1137 |
}
|
1149 |
1138 |
|
|
1139 |
unlock('captiveportalradius');
|
1150 |
1140 |
return false;
|
1151 |
1141 |
}
|
1152 |
1142 |
|
1153 |
1143 |
/* log successful captive portal authentication to syslog */
|
1154 |
1144 |
/* part of this code from php.net */
|
1155 |
1145 |
function captiveportal_logportalauth($user,$mac,$ip,$status, $message = null) {
|
1156 |
|
$message = trim($message);
|
1157 |
1146 |
// Log it
|
1158 |
1147 |
if (!$message)
|
1159 |
1148 |
$message = "$status: $user, $mac, $ip";
|
1160 |
|
else
|
|
1149 |
else {
|
|
1150 |
$message = trim($message);
|
1161 |
1151 |
$message = "$status: $user, $mac, $ip, $message";
|
|
1152 |
}
|
1162 |
1153 |
captiveportal_syslog($message);
|
1163 |
|
closelog();
|
1164 |
1154 |
}
|
1165 |
1155 |
|
1166 |
1156 |
/* log simple messages to syslog */
|
... | ... | |
1176 |
1166 |
function radius($username,$password,$clientip,$clientmac,$type) {
|
1177 |
1167 |
global $g, $config;
|
1178 |
1168 |
|
1179 |
|
/* Start locking from the beginning of an authentication session */
|
1180 |
|
$captiveportallck = lock('captiveportal');
|
1181 |
|
|
1182 |
1169 |
$ruleno = captiveportal_get_next_ipfw_ruleno();
|
1183 |
1170 |
|
1184 |
1171 |
/* If the pool is empty, return appropriate message and fail authentication */
|
... | ... | |
1186 |
1173 |
$auth_list = array();
|
1187 |
1174 |
$auth_list['auth_val'] = 1;
|
1188 |
1175 |
$auth_list['error'] = "System reached maximum login capacity";
|
1189 |
|
unlock($captiveportallck);
|
1190 |
1176 |
return $auth_list;
|
1191 |
1177 |
}
|
1192 |
1178 |
|
1193 |
|
/*
|
1194 |
|
* Drop the lock since radius takes some time to finish.
|
1195 |
|
* The implementation is reentrant so we gain speed with this.
|
1196 |
|
*/
|
1197 |
|
unlock($captiveportallck);
|
1198 |
|
|
1199 |
1179 |
$radiusservers = captiveportal_get_radius_servers();
|
1200 |
1180 |
|
1201 |
1181 |
$auth_list = RADIUS_AUTHENTICATION($username,
|
... | ... | |
1205 |
1185 |
$clientmac,
|
1206 |
1186 |
$ruleno);
|
1207 |
1187 |
|
1208 |
|
$captiveportallck = lock('captiveportal');
|
1209 |
|
|
1210 |
1188 |
if ($auth_list['auth_val'] == 2) {
|
1211 |
1189 |
captiveportal_logportalauth($username,$clientmac,$clientip,$type);
|
1212 |
1190 |
$sessionid = portal_allow($clientip,
|
... | ... | |
1217 |
1195 |
$ruleno);
|
1218 |
1196 |
}
|
1219 |
1197 |
|
1220 |
|
unlock($captiveportallck);
|
1221 |
|
|
1222 |
1198 |
return $auth_list;
|
1223 |
|
|
1224 |
1199 |
}
|
1225 |
1200 |
|
1226 |
1201 |
/* read captive portal DB into array */
|
1227 |
1202 |
function captiveportal_read_db() {
|
1228 |
|
|
1229 |
1203 |
global $g;
|
1230 |
1204 |
|
1231 |
1205 |
$cpdb = array();
|
|
1206 |
|
|
1207 |
$cpdblck = lock('captiveportaldb');
|
1232 |
1208 |
$fd = @fopen("{$g['vardb_path']}/captiveportal.db", "r");
|
1233 |
1209 |
if ($fd) {
|
1234 |
1210 |
while (!feof($fd)) {
|
... | ... | |
1239 |
1215 |
}
|
1240 |
1216 |
fclose($fd);
|
1241 |
1217 |
}
|
|
1218 |
unlock($cpdblck);
|
1242 |
1219 |
return $cpdb;
|
1243 |
1220 |
}
|
1244 |
1221 |
|
1245 |
1222 |
/* write captive portal DB */
|
1246 |
1223 |
function captiveportal_write_db($cpdb) {
|
1247 |
|
|
1248 |
1224 |
global $g;
|
1249 |
|
|
|
1225 |
|
|
1226 |
$cpdblck = lock('captiveportaldb', LOCK_EX);
|
1250 |
1227 |
$fd = @fopen("{$g['vardb_path']}/captiveportal.db", "w");
|
1251 |
|
if ($fd) {
|
|
1228 |
if ($fd) {
|
1252 |
1229 |
foreach ($cpdb as $cpent) {
|
1253 |
1230 |
fwrite($fd, join(",", $cpent) . "\n");
|
1254 |
|
}
|
|
1231 |
}
|
1255 |
1232 |
fclose($fd);
|
1256 |
|
}
|
|
1233 |
}
|
|
1234 |
unlock($cpdblck);
|
1257 |
1235 |
}
|
1258 |
1236 |
|
1259 |
1237 |
function captiveportal_write_elements() {
|
... | ... | |
1310 |
1288 |
if(!isset($config['captiveportal']['enable']))
|
1311 |
1289 |
return NULL;
|
1312 |
1290 |
|
|
1291 |
$cpruleslck = lock('captiveportalrules', LOCK_EX);
|
1313 |
1292 |
$ruleno = 0;
|
1314 |
1293 |
if (file_exists("{$g['vardb_path']}/captiveportal.rules")) {
|
1315 |
1294 |
$rules = unserialize(file_get_contents("{$g['vardb_path']}/captiveportal.rules"));
|
... | ... | |
1336 |
1315 |
$ruleno = 2;
|
1337 |
1316 |
}
|
1338 |
1317 |
file_put_contents("{$g['vardb_path']}/captiveportal.rules", serialize($rules));
|
|
1318 |
unlock($cpruleslck);
|
1339 |
1319 |
return $ruleno;
|
1340 |
1320 |
}
|
1341 |
1321 |
|
... | ... | |
1345 |
1325 |
if(!isset($config['captiveportal']['enable']))
|
1346 |
1326 |
return NULL;
|
1347 |
1327 |
|
|
1328 |
$cpruleslck = lock('captiveportalrules', LOCK_EX);
|
1348 |
1329 |
if (file_exists("{$g['vardb_path']}/captiveportal.rules")) {
|
1349 |
1330 |
$rules = unserialize(file_get_contents("{$g['vardb_path']}/captiveportal.rules"));
|
1350 |
1331 |
$rules[$ruleno] = false;
|
... | ... | |
1352 |
1333 |
$rules[++$ruleno] = false;
|
1353 |
1334 |
file_put_contents("{$g['vardb_path']}/captiveportal.rules", serialize($rules));
|
1354 |
1335 |
}
|
|
1336 |
unlock($cpruleslck);
|
1355 |
1337 |
}
|
1356 |
1338 |
|
1357 |
1339 |
function captiveportal_get_ipfw_passthru_ruleno($value) {
|
... | ... | |
1360 |
1342 |
if(!isset($config['captiveportal']['enable']))
|
1361 |
1343 |
return NULL;
|
1362 |
1344 |
|
|
1345 |
$cpruleslck = lock('captiveportalrules', LOCK_EX);
|
1363 |
1346 |
if (file_exists("{$g['vardb_path']}/captiveportal.rules")) {
|
1364 |
1347 |
$rules = unserialize(file_get_contents("{$g['vardb_path']}/captiveportal.rules"));
|
1365 |
1348 |
$ruleno = intval(`/sbin/ipfw show | /usr/bin/grep {$value} | /usr/bin/grep -v grep | /usr/bin/cut -d " " -f 1 | /usr/bin/head -n 1`);
|
1366 |
|
if ($rules[$ruleno])
|
|
1349 |
if ($rules[$ruleno]) {
|
|
1350 |
unlock($cpruleslck);
|
1367 |
1351 |
return $ruleno;
|
|
1352 |
}
|
1368 |
1353 |
}
|
1369 |
1354 |
|
|
1355 |
unlock($cpruleslck);
|
1370 |
1356 |
return NULL;
|
1371 |
1357 |
}
|
1372 |
1358 |
|
Make the CP locking more granular and make use correctly of exclusive/shared locks where appripriate. This speeds up CP login process.