====== Новый модуль авторизации mikbill.pl для Radius ======
Работает только с версии 3.09.02, на версиях ниже могут быть проблемы так как со стороны ядра биллинга нет контроля соединения
* Добавлена проверка соединения с ядром биллинга и его автоматическое восстановление
* Добавлено логирование о потери связи
\\ Данный код заменить в файле /etc/raddb/mikbill.pl или /etc/freeradius/3.0/mikbill.pl
\\ После чего перезапустить радиус.
Обратите внимание на $host="127.0.0.1" и $port="22007" если они у вас отличаются!
use strict;
use vars qw(%RAD_REQUEST %RAD_REPLY %RAD_CHECK);
use IO::Socket;
use locale;
use POSIX;
use serialize;
setlocale(LC_ALL, 'C');
use constant RLM_MODULE_REJECT=> 0;# /* immediately reject the request */
use constant RLM_MODULE_FAIL=> 1;# /* module failed, don't reply */
use constant RLM_MODULE_OK=> 2;# /* the module is OK, continue */
use constant RLM_MODULE_HANDLED=> 3;# /* the module handled the request, so stop. */
use constant RLM_MODULE_INVALID=> 4;# /* the module considers the request invalid. */
use constant RLM_MODULE_USERLOCK=> 5;# /* reject the request (user is locked out) */
use constant RLM_MODULE_NOTFOUND=> 6;# /* user not found */
use constant RLM_MODULE_NOOP=> 7;# /* module succeeded without doing anything */
use constant RLM_MODULE_UPDATED=> 8;# /* OK (pairs modified) */
use constant RLM_MODULE_NUMCODES=> 9;# /* How many return codes there are */
use constant RADIUS_L_DBG=> 0;# /* debug log */
use constant RADIUS_L_AUTH=> 1;# /* auth log */
use constant RADIUS_L_PROXY=> 2;# /* peroxy log */
use constant RADIUS_L_INFO=> 3;# /* info log */
use constant RADIUS_L_ERROR=> 4;# /* error log */
# mikbill daemon IP address and port
my $host="127.0.0.1";
my $port="22007";
# def
my $sock;
my $answer;
my $time=5;
sub socket_init {
my $sock = new IO::Socket::INET (
PeerAddr => $host,
PeerPort => $port,
Proto => 'tcp',
) or &radiusd::radlog(RADIUS_L_ERROR, "no connection with mikbill daemon ($host:$port)");
if( length $sock ) {
if( $sock->connected() ){
setsockopt($sock, SOL_SOCKET, SO_KEEPALIVE, 1);
}
}
return $sock;
}
sub StillConnected {
return unless defined $sock;
return unless $sock->connected();
return 1;
}
sub check_socket {
if (&StillConnected()) {
return 1;
} elsif(!&StillConnected()){
$sock=&socket_init;
}
}
sub CLONE {
$sock=&socket_init;
}
sub authorize {
if(&check_socket()){
print $sock "auth\n";
$answer=<$sock>;
print $sock serialize(\%RAD_REQUEST);
$answer=<$sock>;
print $sock serialize(\%RAD_REPLY);
$answer=<$sock>;
print $sock serialize(\%RAD_CHECK);
$answer=<$sock>;
if ($answer eq "reject\n") {
return RLM_MODULE_REJECT;
}
$answer=<$sock>;
%RAD_REPLY=%{unserialize($answer)};
$answer=<$sock>;
%RAD_CHECK=%{unserialize($answer)};
} else {
return RLM_MODULE_REJECT;
}
return RLM_MODULE_OK;
}
sub authenticate {
if ($RAD_REPLY{'Packet-Type'} eq "Access-Reject") {
return RLM_MODULE_REJECT;
} else {
return RLM_MODULE_OK;
}
}
sub preacct {
return RLM_MODULE_OK;
}
sub accounting {
if(&check_socket()){
print $sock "acct\n";
$answer=<$sock>;
print $sock serialize(\%RAD_REQUEST);
}
return RLM_MODULE_OK;
}
sub checksimul {
return RLM_MODULE_OK;
}
sub pre_proxy {
return RLM_MODULE_OK;
}
sub post_proxy {
return RLM_MODULE_OK;
}
sub post_auth {
if(&check_socket()){
print $sock "post_auth\n";
$answer=<$sock>;
print $sock serialize(\%RAD_REQUEST);
$answer=<$sock>;
print $sock serialize(\%RAD_REPLY);
$answer=<$sock>;
print $sock serialize(\%RAD_CHECK);
$answer=<$sock>;
if ($answer eq "reject\n") {
return RLM_MODULE_REJECT;
}
$answer=<$sock>;
%RAD_REPLY=%{unserialize($answer)};
$answer=<$sock>;
%RAD_CHECK=unserialize($answer);
} else {
return RLM_MODULE_REJECT;
}
return RLM_MODULE_OK;
}
sub xlat {
my ($filename,$a,$b,$c,$d) = @_;
&radiusd::radlog(1, "From xlat $filename ");
&radiusd::radlog(1,"From xlat $a $b $c $d ");
local *FH;
open FH, $filename or die "open '$filename' $!";
local($/) = undef;
my $sub = ;
close FH;
my $eval = qq{ sub handler{ $sub;} };
eval $eval;
eval {main->handler;};
}
sub detach {
&radiusd::radlog(0,"rlm_perl::Detaching. Reloading. Done.");
}
sub test_call {
}
sub log_request_attributes {
for (keys %RAD_REQUEST) {
&radiusd::radlog(1, "RAD_REQUEST: $_ = $RAD_REQUEST{$_}");
}
}