use FS::part_export;
use FS::svc_acct;
use FS::export_svc;
-use Carp qw( cluck );
+use Carp qw( carp cluck );
use NEXT;
+use Net::OpenSSH;
@ISA = qw(FS::part_export);
@EXPORT_OK = qw( sqlradius_connect );
type => 'select',
options => [qw( usergroup radusergroup ) ],
},
+ 'skip_provisioning' => {
+ type => 'checkbox',
+ label => 'Skip provisioning records to this database'
+ },
'ignore_accounting' => {
type => 'checkbox',
label => 'Ignore accounting records from this database'
'disconnect_port' => {
label => 'Port to send disconnection requests to, default 1700',
},
- 'disconnect_log' => {
- label => 'Print disconnect output and errors to the queue log (will otherwise fail silently)',
- type => 'checkbox',
- },
;
$notes1 = <<'END';
sub _export_insert {
my($self, $svc_x) = (shift, shift);
+ return '' if $self->option('skip_provisioning');
+
foreach my $table (qw(reply check)) {
my $method = "radius_$table";
my %attrib = $self->$method($svc_x);
sub _export_replace {
my( $self, $new, $old ) = (shift, shift, shift);
+ return '' if $self->option('skip_provisioning');
+
local $SIG{HUP} = 'IGNORE';
local $SIG{INT} = 'IGNORE';
local $SIG{QUIT} = 'IGNORE';
my $dbh = dbh;
my $jobnum = '';
-
- # disconnect users before changing username
- if ($self->option('disconnect_ssh')) {
- my $err_or_queue = $self->sqlradius_queue( $new->svcnum, 'user_disconnect',
- 'disconnect_ssh' => $self->option('disconnect_ssh'),
- 'svc_acct_username' => $old->username,
- 'disconnect_port' => $self->option('disconnect_port'),
- 'disconnect_log' => $self->option('disconnect_log'),
- );
- unless ( ref($err_or_queue) ) {
- $dbh->rollback if $oldAutoCommit;
- return $err_or_queue;
- }
- $jobnum = $err_or_queue->jobnum; # chain all of these dependencies
- }
-
if ( $self->export_username($old) ne $self->export_username($new) ) {
my $usergroup = $self->option('usergroup') || 'usergroup';
my $err_or_queue = $self->sqlradius_queue( $new->svcnum, 'rename',
$dbh->rollback if $oldAutoCommit;
return $err_or_queue;
}
- if ( $jobnum ) {
- my $error = $err_or_queue->depend_insert( $jobnum );
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
- }
$jobnum = $err_or_queue->jobnum;
}
my $error;
my (@oldgroups) = $old->radius_groups('hashref');
my (@newgroups) = $new->radius_groups('hashref');
- $error = $self->sqlreplace_usergroups( $new->svcnum,
+ ($error,$jobnum) = $self->sqlreplace_usergroups( $new->svcnum,
$self->export_username($new),
$jobnum ? $jobnum : '',
\@oldgroups,
return $error;
}
+ # radius database is used for authorization, so to avoid users reauthorizing
+ # before the database changes, disconnect users after changing database
+ if ($self->option('disconnect_ssh')) {
+ my $err_or_queue = $self->sqlradius_queue( $new->svcnum, 'user_disconnect',
+ 'disconnect_ssh' => $self->option('disconnect_ssh'),
+ 'svc_acct_username' => $old->username,
+ 'disconnect_port' => $self->option('disconnect_port'),
+ );
+ unless ( ref($err_or_queue) ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $err_or_queue;
+ }
+ if ( $jobnum ) {
+ my $error = $err_or_queue->depend_insert( $jobnum );
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+ }
+
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
'';
sub _export_suspend {
my( $self, $svc_acct ) = (shift, shift);
+ return '' if $self->option('skip_provisioning');
+
my $new = $svc_acct->clone_suspended;
local $SIG{HUP} = 'IGNORE';
my $jobnum = '';
- # disconnect users before changing anything
- if ($self->option('disconnect_ssh')) {
- my $err_or_queue = $self->sqlradius_queue( $new->svcnum, 'user_disconnect',
- 'disconnect_ssh' => $self->option('disconnect_ssh'),
- 'svc_acct_username' => $svc_acct->username,
- 'disconnect_port' => $self->option('disconnect_port'),
- 'disconnect_log' => $self->option('disconnect_log'),
- );
- unless ( ref($err_or_queue) ) {
- $dbh->rollback if $oldAutoCommit;
- return $err_or_queue;
- }
- $jobnum = $err_or_queue->jobnum;
- }
-
my @newgroups = $self->suspended_usergroups($svc_acct);
unless (@newgroups) { #don't change password if assigning to a suspended group
$dbh->rollback if $oldAutoCommit;
return $err_or_queue;
}
- if ( $jobnum ) {
- my $error = $err_or_queue->depend_insert( $jobnum );
- if ( $error ) {
- $dbh->rollback if $oldAutoCommit;
- return $error;
- }
- }
+ $jobnum = $err_or_queue->jobnum;
}
- my $error =
+ my $error;
+ ($error,$jobnum) =
$self->sqlreplace_usergroups(
$new->svcnum,
$self->export_username($new),
$dbh->rollback if $oldAutoCommit;
return $error;
}
+
+ # radius database is used for authorization, so to avoid users reauthorizing
+ # before the database changes, disconnect users after changing database
+ if ($self->option('disconnect_ssh')) {
+ my $err_or_queue = $self->sqlradius_queue( $new->svcnum, 'user_disconnect',
+ 'disconnect_ssh' => $self->option('disconnect_ssh'),
+ 'svc_acct_username' => $svc_acct->username,
+ 'disconnect_port' => $self->option('disconnect_port'),
+ );
+ unless ( ref($err_or_queue) ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $err_or_queue;
+ }
+ if ( $jobnum ) {
+ my $error = $err_or_queue->depend_insert( $jobnum );
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+ }
+
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
'';
sub _export_unsuspend {
my( $self, $svc_x ) = (shift, shift);
+ return '' if $self->option('skip_provisioning');
+
local $SIG{HUP} = 'IGNORE';
local $SIG{INT} = 'IGNORE';
local $SIG{QUIT} = 'IGNORE';
sub _export_delete {
my( $self, $svc_x ) = (shift, shift);
+ return '' if $self->option('skip_provisioning');
+
my $jobnum = '';
- # disconnect users before changing anything
+ my $usergroup = $self->option('usergroup') || 'usergroup';
+ my $err_or_queue = $self->sqlradius_queue( $svc_x->svcnum, 'delete',
+ $self->export_username($svc_x), $usergroup );
+ $jobnum = $err_or_queue->jobnum;
+
+ # radius database is used for authorization, so to avoid users reauthorizing
+ # before the database changes, disconnect users after changing database
if ($self->option('disconnect_ssh')) {
my $err_or_queue = $self->sqlradius_queue( $svc_x->svcnum, 'user_disconnect',
'disconnect_ssh' => $self->option('disconnect_ssh'),
'svc_acct_username' => $svc_x->username,
'disconnect_port' => $self->option('disconnect_port'),
- 'disconnect_log' => $self->option('disconnect_log'),
);
return $err_or_queue unless ref($err_or_queue);
- $jobnum = $err_or_queue->jobnum;
- }
-
- my $usergroup = $self->option('usergroup') || 'usergroup';
- my $err_or_queue = $self->sqlradius_queue( $svc_x->svcnum, 'delete',
- $self->export_username($svc_x), $usergroup );
- if ( $jobnum ) {
- my $error = $err_or_queue->depend_insert( $jobnum );
- return $error if $error;
+ if ( $jobnum ) {
+ my $error = $err_or_queue->depend_insert( $jobnum );
+ return $error if $error;
+ }
}
ref($err_or_queue) ? '' : $err_or_queue;
}
sub sqlradius_insert { #subroutine, not method
+
+ if ( $FS::svc_Common::noexport_hack ) {
+ carp 'sqlradius_insert() suppressed by noexport_hack' if $DEBUG;
+ return;
+ }
+
my $dbh = sqlradius_connect(shift, shift, shift);
my( $table, $username, %attributes ) = @_;
}
sub sqlradius_usergroup_insert { #subroutine, not method
+
+ if ( $FS::svc_Common::noexport_hack ) {
+ carp 'sqlradius_usergroup_insert() suppressed by noexport_hack' if $DEBUG;
+ return;
+ }
+
my $dbh = sqlradius_connect(shift, shift, shift);
my $username = shift;
my $usergroup = ( $_[0] =~ /^(rad)?usergroup/i ) ? shift : 'usergroup';
}
sub sqlradius_usergroup_delete { #subroutine, not method
+
+ if ( $FS::svc_Common::noexport_hack ) {
+ carp 'sqlradius_usergroup_delete() suppressed by noexport_hack' if $DEBUG;
+ return;
+ }
+
my $dbh = sqlradius_connect(shift, shift, shift);
my $username = shift;
my $usergroup = ( $_[0] =~ /^(rad)?usergroup/i ) ? shift : 'usergroup';
}
sub sqlradius_rename { #subroutine, not method
+
+ if ( $FS::svc_Common::noexport_hack ) {
+ carp 'sqlradius_rename() suppressed by noexport_hack' if $DEBUG;
+ return;
+ }
+
my $dbh = sqlradius_connect(shift, shift, shift);
my($new_username, $old_username) = (shift, shift);
my $usergroup = ( $_[0] =~ /^(rad)?usergroup/i ) ? shift : 'usergroup';
}
sub sqlradius_attrib_delete { #subroutine, not method
+
+ if ( $FS::svc_Common::noexport_hack ) {
+ carp 'sqlradius_attrib_delete() suppressed by noexport_hack' if $DEBUG;
+ return;
+ }
+
my $dbh = sqlradius_connect(shift, shift, shift);
my( $table, $username, @attrib ) = @_;
}
sub sqlradius_delete { #subroutine, not method
+
+ if ( $FS::svc_Common::noexport_hack ) {
+ carp 'sqlradius_delete() suppressed by noexport_hack' if $DEBUG;
+ return;
+ }
+
my $dbh = sqlradius_connect(shift, shift, shift);
my $username = shift;
my $usergroup = ( $_[0] =~ /^(rad)?usergroup/i ) ? shift : 'usergroup';
DBI->connect(@_) or die $DBI::errstr;
}
+# on success, returns '' in scalar context, ('',$jobnum) in list context
+# on error, always just returns error
sub sqlreplace_usergroups {
my ($self, $svcnum, $username, $jobnum, $old, $new) = @_;
my $error = $err_or_queue->depend_insert( $jobnum );
return $error if $error;
}
+ $jobnum = $err_or_queue->jobnum; # chain all of these dependencies
}
- '';
+ wantarray ? ('',$jobnum) : '';
}
sub update_svc {
my $self = shift;
+ if ( $FS::svc_Common::noexport_hack ) {
+ carp 'update_svc() suppressed by noexport_hack'
+ if $self->option('debug') || $DEBUG;
+ return;
+ }
+
my $conf = new FS::Conf;
my $fdbh = dbh;
sub export_nas_action {
my $self = shift;
my ($action, $new, $old) = @_;
+
+ if ( $FS::svc_Common::noexport_hack ) {
+ carp "export_nas_action($action) suppressed by noexport_hack"
+ if $self->option('debug') || $DEBUG;
+ return;
+ }
+
# find the NAS in the target table by its name
my $nasname = ($action eq 'replace') ? $old->nasname : $new->nasname;
my $nasnum = $new->nasnum;
}
sub sqlradius_nas_insert {
+
+ if ( $FS::svc_Common::noexport_hack ) {
+ carp 'sqlradius_nas_insert() suppressed by noexport_hack' if $DEBUG;
+ return;
+ }
+
my $dbh = sqlradius_connect(shift, shift, shift);
my %opt = @_;
my $nas = qsearchs('nas', { nasnum => $opt{'nasnum'} })
}
sub sqlradius_nas_delete {
+
+ if ( $FS::svc_Common::noexport_hack ) {
+ carp 'sqlradius_nas_delete() suppressed by noexport_hack' if $DEBUG;
+ return;
+ }
+
my $dbh = sqlradius_connect(shift, shift, shift);
my %opt = @_;
my $sth = $dbh->prepare('DELETE FROM nas WHERE nasname = ?');
}
sub sqlradius_nas_replace {
+
+ if ( $FS::svc_Common::noexport_hack ) {
+ carp 'sqlradius_nas_replace() suppressed by noexport_hack' if $DEBUG;
+ return;
+ }
+
my $dbh = sqlradius_connect(shift, shift, shift);
my %opt = @_;
my $nas = qsearchs('nas', { nasnum => $opt{'nasnum'} })
}
sub sqlradius_attr_insert {
+
+ if ( $FS::svc_Common::noexport_hack ) {
+ carp 'sqlradius_attr_insert() suppressed by noexport_hack' if $DEBUG;
+ return;
+ }
+
my $dbh = sqlradius_connect(shift, shift, shift);
my %opt = @_;
}
sub sqlradius_attr_delete {
+
+ if ( $FS::svc_Common::noexport_hack ) {
+ carp 'sqlradius_attr_delete() suppressed by noexport_hack' if $DEBUG;
+ return;
+ }
+
my $dbh = sqlradius_connect(shift, shift, shift);
my %opt = @_;
}
sub sqlradius_group_replace {
+
+ if ( $FS::svc_Common::noexport_hack ) {
+ carp 'sqlradius_group_replace() suppressed by noexport_hack' if $DEBUG;
+ return;
+ }
+
my $dbh = sqlradius_connect(shift, shift, shift);
my $usergroup = shift;
$usergroup =~ /^(rad)?usergroup$/
I<disconnect_port> - the port (on the nas) to send disconnect requests to (defaults to 1700)
-I<disconnect_log> - if true, print disconnect command & output to the error log
-
Note this is NOT the opposite of sqlradius_connect.
=cut
sub sqlradius_user_disconnect {
+
+ if ( $FS::svc_Common::noexport_hack ) {
+ carp 'sqlradius_user_disconnect() suppressed by noexport_hack' if $DEBUG;
+ return;
+ }
+
my $dbh = sqlradius_connect(shift, shift, shift);
my %opt = @_;
# get list of nas
$dbh->disconnect();
die "No nas found in radius db" unless @$nas;
# set up ssh connection
- eval "use Net::SSH";
my $ssh = Net::OpenSSH->new($opt{'disconnect_ssh'});
die "Couldn't establish SSH connection: " . $ssh->error
if $ssh->error;
# send individual disconnect requests
my $user = $opt{'svc_acct_username'}; #svc_acct username
my $port = $opt{'disconnect_port'} || 1700; #or should we pull this from the db?
+ my $error = '';
foreach my $nas (@$nas) {
my $nasname = $nas->{'nasname'};
my $secret = $nas->{'secret'};
my $command = qq(echo "User-Name=$user" | radclient -r 1 $nasname:$port disconnect '$secret');
my ($output, $errput) = $ssh->capture2($command);
- warn $command . "\n" . $output . $errput . $ssh->error . "\n"
- if $opt{'disconnect_log'};
+ $error .= "Error running $command: $errput " . $ssh->error . " "
+ if $errput || $ssh->error;
}
+ $error .= "Some clients may have successfully disconnected"
+ if $error && (@$nas > 1);
+ $error = "No clients found"
+ unless @$nas;
+ die $error if $error;
return '';
}