321 lines
6.7 KiB
Perl
321 lines
6.7 KiB
Perl
#!/usr/bin/perl
|
|
|
|
# This script manipulate the user table in the codepot datbase.
|
|
# It doesn't handle LDAP.
|
|
|
|
use strict;
|
|
|
|
use Switch;
|
|
use Config::Simple;
|
|
use DBI;
|
|
use Digest::SHA;
|
|
|
|
my $CFG_FILE = '@CFGDIR@/codepot.ini';
|
|
my $QC = '';
|
|
|
|
sub get_config
|
|
{
|
|
my $cfg = new Config::Simple();
|
|
|
|
if (!$cfg->read ($CFG_FILE))
|
|
{
|
|
return undef;
|
|
}
|
|
|
|
my $config = {
|
|
database_hostname => $cfg->param("database_hostname"),
|
|
database_port => $cfg->param("database_port"),
|
|
database_username => $cfg->param("database_username"),
|
|
database_password => $cfg->param("database_password"),
|
|
database_name => $cfg->param("database_name"),
|
|
database_driver => $cfg->param("database_driver"),
|
|
database_prefix => $cfg->param("database_prefix"),
|
|
|
|
codepot_user_executor => $cfg->param("codepot_user_executor")
|
|
};
|
|
|
|
return $config;
|
|
}
|
|
|
|
sub open_database
|
|
{
|
|
my ($cfg) = @_;
|
|
|
|
my $dbtype = $cfg->{database_driver};
|
|
my $dbname = $cfg->{database_name};
|
|
my $dbhost = $cfg->{database_hostname};
|
|
my $dbport = $cfg->{database_port};
|
|
my $dbprefix = $cfg->{database_prefix};
|
|
|
|
if ($dbtype eq 'postgre') { $dbtype = 'Pg'; }
|
|
elsif ($dbtype eq 'oci8') { $dbtype = 'Oracle'; }
|
|
elsif ($dbtype eq 'mysqli') { $dbtype = 'mysql'; }
|
|
elsif ($dbtype eq 'sqlite') { $dbtype = 'SQLite'; }
|
|
|
|
my $dbstr;
|
|
my $dbuser;
|
|
my $dbpass;
|
|
if ($dbtype eq 'Oracle')
|
|
{
|
|
$QC = '"';
|
|
$dbstr = "DBI:$dbtype:";
|
|
$dbuser = $cfg->{database_username} . '/' . $cfg->{database_password} . '@' . $dbhost;
|
|
$dbpass = '';
|
|
}
|
|
elsif ($dbtype eq 'SQLite')
|
|
{
|
|
$dbstr = "DBI:$dbtype:database=$dbhost;";
|
|
$dbuser = $cfg->{database_username};
|
|
$dbpass = $cfg->{database_password};
|
|
}
|
|
else
|
|
{
|
|
$dbstr = "DBI:$dbtype:database=$dbname;";
|
|
if (length($dbhost) > 0) { $dbstr .= "host=$dbhost;"; }
|
|
if (length($dbport) > 0) { $dbstr .= "port=$dbport;"; }
|
|
|
|
$dbuser = $cfg->{database_username};
|
|
$dbpass = $cfg->{database_password};
|
|
}
|
|
|
|
my $dbh = DBI->connect(
|
|
$dbstr, $dbuser, $dbpass,
|
|
{ RaiseError => 0, PrintError => 0, AutoCommit => 0 }
|
|
);
|
|
|
|
return $dbh;
|
|
}
|
|
|
|
sub close_database
|
|
{
|
|
my ($dbh) = @_;
|
|
$dbh->disconnect ();
|
|
}
|
|
|
|
sub rand_string
|
|
{
|
|
my ($length) = @_;
|
|
|
|
my $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
|
|
|
my $str = '';
|
|
my $size = length ($chars);
|
|
for( my $i = 0; $i < $length; $i++ )
|
|
{
|
|
$str = $str . substr ($chars, rand($size), 1) ;
|
|
}
|
|
|
|
return $str;
|
|
}
|
|
|
|
sub format_passwd
|
|
{
|
|
my ($password, $binsalt, $hexsalt) = @_;
|
|
my $fmt_pw = '{ssha1}' . Digest::SHA::sha1_hex($password . $binsalt) . $hexsalt;
|
|
return $fmt_pw;
|
|
}
|
|
|
|
sub authenticate_database
|
|
{
|
|
my ($dbh, $prefix, $userid, $password) = @_;
|
|
|
|
my $query = $dbh->prepare ("SELECT ${QC}userid${QC},${QC}passwd${QC} FROM ${QC}${prefix}user_account${QC} WHERE ${QC}userid${QC}=? and ${QC}enabled${QC}='N'");
|
|
if (!$query || !$query->execute ($userid))
|
|
{
|
|
return (-1, $dbh->errstr());
|
|
}
|
|
|
|
my @row = $query->fetchrow_array;
|
|
$query->finish ();
|
|
|
|
if (scalar(@row) <= 0) { return (0, undef); }
|
|
|
|
my $db_pw = $row[1];
|
|
if (length($db_pw) < 10) { return (0, undef); }
|
|
|
|
my $hexsalt = substr ($db_pw, -10);
|
|
my $binsalt = pack ('H*', $hexsalt);
|
|
|
|
#my $fmt_pw = '{ssha1}' . sha1_hex ($password . $binsalt) . $hexsalt;
|
|
my $fmt_pw = format_passwd ($password, $binsalt, $hexsalt);
|
|
return (($fmt_pw eq $db_pw? 1: 0), undef);
|
|
}
|
|
|
|
sub add_user
|
|
{
|
|
my ($dbh, $prefix, $userid, $passwd, $email) = @_;
|
|
|
|
my $binsalt = rand_string (5);
|
|
my $hexsalt = unpack ("H*", $binsalt);
|
|
my $fmt_pw = format_passwd ($passwd, $binsalt, $hexsalt);
|
|
|
|
$dbh->begin_work ();
|
|
|
|
my $query = $dbh->prepare ("INSERT INTO ${QC}${prefix}user_account${QC} (${QC}userid${QC},${QC}passwd${QC},${QC}email${QC},${QC}enabled${QC}) VALUES (?, ?, ?, ?)");
|
|
if (!$query || !$query->execute ($userid, $fmt_pw, $email, 'N'))
|
|
{
|
|
my $errstr = $dbh->errstr();
|
|
$dbh->rollback ();
|
|
print (STDERR "Cannot add a user - $errstr\n");
|
|
return -1;
|
|
}
|
|
|
|
$query->finish ();
|
|
$dbh->commit ();
|
|
return 0;
|
|
}
|
|
|
|
sub delete_user
|
|
{
|
|
my ($dbh, $prefix, $userid) = @_;
|
|
|
|
$dbh->begin_work ();
|
|
|
|
my $query = $dbh->prepare ("DELETE FROM ${QC}${prefix}user_account${QC} WHERE ${QC}userid${QC}=?");
|
|
if (!$query || !$query->execute ($userid) || $query->rows() <= 0)
|
|
{
|
|
my $errstr = $dbh->errstr();
|
|
$dbh->rollback ();
|
|
print (STDERR "Cannot delete a user - $errstr\n");
|
|
return -1;
|
|
}
|
|
|
|
$query->finish ();
|
|
$dbh->commit ();
|
|
return 0;
|
|
}
|
|
|
|
sub toggle_user
|
|
{
|
|
my ($dbh, $prefix, $userid, $enabled) = @_;
|
|
|
|
$dbh->begin_work ();
|
|
|
|
my $query = $dbh->prepare("UPDATE ${QC}${prefix}user_account${QC} SET ${QC}enabled${QC}=? WHERE ${QC}userid${QC}=?");
|
|
my $execok = undef;
|
|
if (!$query || !($execok = $query->execute($enabled, $userid)) || $query->rows() <= 0)
|
|
{
|
|
my $errstr = $execok? "user not found": $dbh->errstr();
|
|
$dbh->rollback ();
|
|
print (STDERR "Cannot enable/disable the user '$userid' - $errstr\n");
|
|
return -1;
|
|
}
|
|
|
|
$query->finish ();
|
|
$dbh->commit ();
|
|
return 0;
|
|
}
|
|
|
|
sub print_usage
|
|
{
|
|
print (STDERR "Usage: codepot-user add user-id password email\n");
|
|
print (STDERR " codepot-user delete user-id\n");
|
|
print (STDERR " codepot-user enable user-id\n");
|
|
print (STDERR " codepot-user disable user-id\n");
|
|
}
|
|
|
|
#------------------------------------------------------------
|
|
# MAIN
|
|
#------------------------------------------------------------
|
|
|
|
my $ARGC = scalar(@ARGV);
|
|
my $USERID;
|
|
my $PASSWD;
|
|
my $EMAIL;
|
|
my $op = 0;
|
|
my $ret = 0;
|
|
|
|
if ($ARGC >= 1)
|
|
{
|
|
if ($ARGV[0] eq 'add')
|
|
{
|
|
if ($ARGC == 4)
|
|
{
|
|
$USERID = $ARGV[1];
|
|
$PASSWD = $ARGV[2];
|
|
$EMAIL = $ARGV[3];
|
|
$op = 1;
|
|
}
|
|
}
|
|
elsif ($ARGV[0] eq 'delete')
|
|
{
|
|
if ($ARGC == 2)
|
|
{
|
|
$USERID = $ARGV[1];
|
|
$op = 2;
|
|
}
|
|
}
|
|
elsif ($ARGV[0] eq 'enable')
|
|
{
|
|
if ($ARGC == 2)
|
|
{
|
|
$USERID = $ARGV[1];
|
|
$op = 3;
|
|
}
|
|
}
|
|
elsif ($ARGV[0] eq 'disable')
|
|
{
|
|
if ($ARGC == 2)
|
|
{
|
|
$USERID = $ARGV[1];
|
|
$op = 4;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($op <= 0)
|
|
{
|
|
print_usage ();
|
|
exit (2);
|
|
}
|
|
|
|
my $cfg = get_config();
|
|
if (!defined($cfg))
|
|
{
|
|
print (STDERR "Cannot load codepot configuration file\n");
|
|
exit (1);
|
|
}
|
|
|
|
my $allowed_to_execute = 1;
|
|
my @executors = split (/\s*,\s*/, $cfg->{codepot_user_executor});
|
|
if (scalar(@executors) > 0)
|
|
{
|
|
for my $executor (@executors)
|
|
{
|
|
my $uid = getpwnam ($executor);
|
|
if (defined($uid) && $> == $uid)
|
|
{
|
|
$allowed_to_execute = 1;
|
|
last;
|
|
}
|
|
else
|
|
{
|
|
$allowed_to_execute = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($allowed_to_execute == 0)
|
|
{
|
|
print (STDERR "Not allowed to run this program\n");
|
|
exit (1);
|
|
}
|
|
|
|
my $dbh = open_database($cfg);
|
|
if (!defined($dbh))
|
|
{
|
|
printf (STDERR "Cannot open database - %s\n", $DBI::errstr);
|
|
exit (1);
|
|
}
|
|
|
|
switch ($op)
|
|
{
|
|
case 1 { $ret = add_user($dbh, $cfg->{database_prefix}, $USERID, $PASSWD, $EMAIL); }
|
|
case 2 { $ret = delete_user($dbh, $cfg->{database_prefix}, $USERID); }
|
|
case 3 { $ret = toggle_user($dbh, $cfg->{database_prefix}, $USERID, 'Y'); }
|
|
case 4 { $ret = toggle_user($dbh, $cfg->{database_prefix}, $USERID, 'N'); }
|
|
}
|
|
|
|
close_database ($dbh);
|
|
exit ($ret);
|