You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

429 lines
9.3 KiB
Perl

# all the user stuff
#
# kevin lenzo
#
sub parseUserfile {
$file = $param{'confdir'}.$filesep.$param{'userList'};
%user = ();
@userList = ();
open(FH, $file);
while (<FH>) {
if (!/^#/ && defined $_) {
if (/^UserEntry\s+(.+?)\s/) {
push @userList, $1;
$workname = $1;
if (/\s*\{\s*/) {
while (<FH>) {
if (/^\s*(\w+)\s+(.+);$/) {
$opt = $1; $val = $2;
$val =~ s/\"//g;
if ($opt =~ /^mask$/i) {
push @{$workname."masks"}, $val;
} elsif ($opt =~ /^flags$/i) {
$val =~ s/\+//;
$user{$workname."flags"} = $val;
} else {
$opt =~ tr/A-Z/a-z/;
$user{$workname.$opt} = $val;
}
} elsif (/^\s*\}\s*$/) {
last;
}
}
} else {
status("parse error: User Entry $workname without right brace");
}
}
}
}
my $u;
foreach $u (@userList) {
status("found user $user: flags +".$user{$u."flags"})
if $param{VERBOSITY} > 1;
if ($param{VERBOSITY} > 2) {
my $h;
foreach $h (@{$u."masks"}) {
status(" -> hostmask: $h");
}
}
}
}
sub IsFlag {
my $flags = $_[0];
my ($ret, $f, $o);
my @ind = split //, $flags;
foreach $f (split //, $uFlags) {
foreach $o (@ind) {
if ($f eq $o) {
$ret .= $f;
last;
}
}
}
$ret;
}
sub verifyUser {
my $lnuh = $_[0];
my ($u, $m);
my $VerifWho;
foreach $u (@userList) {
foreach (@{$u."masks"}) {
$m = $_;
$m =~ s/\*/.*?/g;
$m =~ s/([\@\(\)\[\]])/\\$1/g;
if ($lnuh =~ /^$m$/i) {
$VerifWho = $u;
last;
}
}
}
my $now = time();
my $m = $message;
if ($msgType !~ /public/) {
$m = "<private message>";
}
&set('seen', lc $who, $now.$;.channel().$;.$m);
if ($VerifWho) {
$uFlags = $user{$VerifWho."flags"};
$uPasswd = $user{$VerifWho."pass"};
$uTitle = $user{$VerifWho."title"};
if (exists $seenVerif{$VerifWho} and
(time()-$seenVerif{$VerifWho} > 360)) {
status("mask verified for $VerifWho");
}
$seenVerif{$VerifWho} = $now;
}
return $VerifWho;
}
sub mkpasswd {
my $what = $_[0];
my $salt = chr(33+rand(64)).chr(33+rand(64));
$salt =~ s/:/;/g;
return crypt($what, $salt);
}
sub ckuser {
# returns user level if matched, zero otherwise
my ($nuh, $plaintextpass) = @_;
if (!$plaintextpass) {
($nuh, $plaintextpass) = split(/\s+/, $nuh);
}
return '' unless $nuh;
my ($level, $cryptedpass, $rest, $nuh2) = &userinfo($nuh);
if (&ckpasswd($plaintextpass, $cryptedpass)) {
# password matched for user nick!user@host
&status("confirmed user: $nuh");
return $level;
} else {
# no match
return 0;
}
}
sub ckpasswd {
# returns true if arg1 encrypts to arg2
my ($plain, $encrypted) = @_;
if (!$encrypted) {
($plain, $encrypted) = split(/\s+/, $plain, 2);
}
return '' unless ($plain && $encrypted);
return ($encrypted eq crypt($plain, $encrypted));
}
sub userinfo {
my $lnuh = $_[0];
my $k;
if (!$lnuh) {
$lnuh = $nuh;
}
foreach $k (keys %userList) {
my $n = $k;
$n =~ s/\*/.*/g;
$n =~ s/([\@\(\)\[\]])/\\$1/g;
if ($lnuh =~ /^$n$/i) {
# this may expand later
my ($userlevel, $pass, $rest) = split(/:/, $userList{$k}, 3);
return ($userlevel, $pass, $rest, $k);
}
}
return ();
}
sub users {
my @stuff;
foreach (sort keys %userList) {
push(@stuff, "$_ => $userList{$_}\n");
}
return @stuff;
}
sub adduser {
my($nuh, $level, $plainpass, $rest) = @_;
if (!$level) {
($nuh, $level, $plainpass, $rest) = split(/\s+/, $nuh, 4);
}
if (!$plainpass && ($level =~ /\D/)) {
my $x = $level;
if ($plainpass =~ /^\D+/) {
$level = $plainpass;
$plainpass = $level;
}
}
if (($level =~ /^\d+/) && $plainpass) {
my $cryptedpass = mkpasswd($plainpass);
my $i = join(":", $level, $cryptedpass, $rest);
$userLevel{$nuh} = $i;
&status("user $nuh added at level $i");
return "user $nuh added at level $i";
} else {
&status("bad params to adduser");
return '';
}
}
sub writeUserFile {
my $where = $_[0];
chomp $where;
if (!$where) {
$where = $param{'confdir'}.$filesep.$param{'userList'};
}
if (!$where) {
return "no file given and no param set for writing user file\n";
}
if (open(UF, ">$where")) {
foreach (sort keys %userLevel) {
print UF "$_:$userLevel{$_}\n";
}
close UF;
&status("wrote user file to $where");
return "wrote user file";
} else {
&status("failed to write user file to $where");
return "couldn't write user file";
}
}
sub changepass {
my ($nuh, $oldpass, $newpass) = @_;
if (&ckuser($nuh, $oldpass)) {
my $cryptednew = mkpasswd($newpass);
my ($level, $pass, $rest, $nuh2) = &userinfo($nuh);
my $i = join(":", $level, $newpass, $rest);
$userList{$nuh2} = $i;
&status("password changed for $nuh");
return "password changed for $nuh";
} else {
&status("password change failed for $nuh");
return "password did not match you: $nuh";
}
}
sub removeuser {
my $nuh = $_[0];
if ($userList{$nuh}) {
delete $userList{$nuh};
&status("deleted $nuh from userlist");
return "deleted $nuh from the userlist";
} else {
return 'No match for $nuh';
}
}
sub setlevel {
my ($nuh, $newlevel) = @_;
if (!$newlevel) {
($nuh, $newlevel) = split(/\s+/, $nuh, 2);
}
my ($level, $pass, $rest, $nuh2) = &userinfo($nuh);
if ($newlevel !~ /^\d+/) {
return "bad user level: $newlevel";
}
if ($userList{$nuh}) {
($level, $pass, $rest) = split(/:/, $userList{$nuh});
$nuh2 = $nuh;
}
if ($nuh2) {
my $i = join(":", $newlevel, $pass, $rest);
$userList{$nuh2} = $i;
&status("level for $nuh changed to $newlevel (was $level)");
} else {
&status("no match for $nuh");
}
0;
}
sub userProcessing {
my $now = time();
if ($VerifWho) {
if ($msgType =~ /private/) {
my $unverified_message = "you must identify yourself; /msg $param{nick} <pass> <command>";
if (IsFlag("e")) { # eval
if ($message =~ s/^(\S+) eval//) {
if (!exists $verified{$VerifWho}) {
&status("unverified <$who> $message");
&msg($who, $unverified_message);
return 'NOREPLY';
}
my ($pass, $m) = ($1, $message);
$_ = "";
&msg($who, "WARNING: exposed eval security risk");
$x = eval($m);
&msg($who, $x);
}
}
if (IsFlag("o")) { # owner/operator flag
if ($message =~ /^die/) {
if (!exists $verified{$VerifWho}) {
&status("unverified <$who> $message");
&msg($who, $unverified_message);
return 'NOREPLY';
}
&rawout("QUIT :$who");
&closeDBMAll();
sleep 2;
status("Dying by $who\'s request");
exit(0);
}
if ($message =~ /^reload$/i) {
if (!exists $verified{$VerifWho}) {
&status("unverified <$who> $message");
&msg($who, $unverified_message);
return 'NOREPLY';
}
&status("RELOAD <$who>");
opendir DIR, $infobot_src_dir;
while ($file = readdir DIR) {
next unless $file =~ /\.pl$/;
next if $file eq 'Process.pl';
if (!do $file) {
&status("Error reloading $file: "
. ($@ || "did not return a true value"));
}
}
close DIR;
&msg($who, "reloaded init files");
return 'NOREPLY';
}
if ($message =~ /^rehash$/i) {
if (!exists $verified{$VerifWho}) {
&status("unverified <$who> $message");
&msg($who, $unverified_message);
return 'NOREPLY';
}
&status("REHASH <$who>\n");
&setup();
&msg($who, "rehashed");
return 'NOREPLY';
}
if ($message =~ /^modes$/) {
if (!exists $verified{$VerifWho}) {
&status("unverified <$who> $message");
&msg($who, $unverified_message);
return 'NOREPLY';
}
my ($chan, $mode, $user, $msg, $m1);
foreach $chan (keys %channels) {
my $msg = "$chan: ";
foreach $mode (keys %{$channels{$chan}}) {
my $m1 = $msg." $mode: ";
foreach $user (keys %{$channels{$chan}{$mode}}) {
$m1 .= "$user ";
}
&msg($who, $m1);
}
}
return 'NOREPLY';
}
}
if (IsFlag("p") eq "p") { # oP on channel
if ($message =~ s/^op( me)?$//i or $message =~ s/^op //i) {
if (!exists $verified{$VerifWho}) {
&status("unverified <$who> $message");
&msg($who, $unverified_message);
return 'NOREPLY';
}
&status("trying to op $who at their request");
foreach $chan (keys %channels) {
if ($message) {
&op($chan, $message);
} else {
&op($chan, $who);
}
}
return 'NOREPLY';
}
my $regex = 0;
if ($message =~ /^ignore\s+(.*)/) {
my $what = $1;
&postInc(ignore => $what);
&status("ignoring $what at $VerifWho's request");
&msg($who, "added $what to the ignore list");
return 'NOREPLY';
}
if ($message =~ /^ignorelist$/) {
&status("$who asked for the ignore list");
my $all = join " ", &getDBMKeys('ignore');
while (length($all) > 200) {
$all =~ s/(.{0,200}) //;
&msg($who, $1);
}
&msg($who, $all);
return 'NOREPLY';
}
if ($message =~ /^unignore\s+(.*)/) {
my $what = $1;
if (&clear(ignore => $what)) {
&status("unignoring $what at $VerifWho's request");
&msg($who, "removed $what from the ignore list");
} else {
&status("unignore FAILED for $1 at $who's request");
&msg($who, "no entry for $1 on the ignore list");
}
return 'NOREPLY';
}
}
}
} else {
$uFlags = $user{"defaultflags"};
}
}
1;