use FS::export_svc;
use Carp qw( cluck );
use NEXT;
+use Net::OpenSSH;
@ISA = qw(FS::part_export);
@EXPORT_OK = qw( sqlradius_connect );
'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';
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;
'';
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;
'';
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;
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) : '';
}
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
$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 '';
}