Commit Diff
Diff:
fcbdb0ca312eb9df292aef3f230f5fd92e0888a6
6468046338fff24d077b691f2e56e1fcbc9c37a4
Commit:
6468046338fff24d077b691f2e56e1fcbc9c37a4
Tree:
9c338639db5a9886266a0a9d6b3cd7696d352263
Author:
jrmu <jrmu@ircnow.org>
Committer:
jrmu <jrmu@ircnow.org>
Date:
Tue Oct 20 07:25:59 2020 UTC
Message:
Added support for automated shell requests
blob - 1887104f1e0d878e22e7e62eb276563b5e627819
blob + 4900c6bf1ca600ebeea24190b1dcae21366a907d
--- BNC.pm
+++ BNC.pm
@@ -22,6 +22,7 @@ my $captchaURL = "https://guava.ircnow.org/captcha.php
my $hostname;
my $terms;
my @logs;
+my $time = "600";
sub init {
$chans = $main::conf{chans};
@@ -43,7 +44,6 @@ sub init {
main::cbind("pub", "-", "request", \&help);
main::cbind("pub", "-", "bnc", \&mbnc);
main::cbind("msg", "-", "bnc", \&mbnc);
- main::cbind("msg", "-", "delete", \&mdelete);
main::cbind("msg", "-", "regex", \&mregex);
main::cbind("msg", "-", "foreach", \&mforeach);
}
@@ -54,9 +54,15 @@ sub help {
my $msg = <<"EOF";
$terms
To request a free bouncer, type !bnc <username> <email>. For example, !bnc john john\@example.com.
-To reset the password, type !set password <password>.
-To change email, type !set email <email>.
EOF
+ if ($staff =~ /$nick/) {
+ $msg .= <<"EOF";
+To delete a bouncer, type !bnc delete <username>
+To get a list of usernames that match IPs, type !regex ips <ips>
+To get a list of IPs that match usernames, type !regex users <usernames>
+To regex search znc.log and output to the terminal, type !regex <regex>
+EOF
+ }
if (@args == 2) {
($chan, $text) = ($args[0], $args[1]);
if ($chans =~ $chan) {
@@ -81,55 +87,71 @@ sub mbnc {
if (defined($chan) && $chans =~ /$chan/) {
main::putserv($bot, "PRIVMSG $chan :$nick: Please check private message");
}
- if (defined(SQLite::userget("bnc", $hostmask, "date"))) {
- main::putserv($bot, "PRIVMSG $nick :Sorry, only one account per person. Please contact staff if you need help.");
- ### TODO: Check duplicate emails ###
- } elsif ($text =~ /^$/) {
+ if ($text =~ /^$/) {
main::putserv($bot, "PRIVMSG $nick :Type !help for new instructions");
foreach my $chan (@teamchans) {
main::putserv($bot, "PRIVMSG $chan :Help *$nick* on ".$bot->{name});
}
- } elsif ($text =~ /^captcha\s+([[:alnum:]]+)/) {
- my ($text) = ($1);
- my $captcha = SQLite::userget("bnc", $hostmask, "captcha");
- if ($text =~ /^$captcha$/i) {
- my $pass = Hash::newpass();
- chomp(my $encrypted = `encrypt $pass`);
- my $username = SQLite::userget("bnc", $hostmask, "username");
- my $email = SQLite::userget("bnc", $hostmask, "email");
- my $version = SQLite::userget("bnc", $hostmask, "version");
- my $bindhost = "$username.$hostname";
- SQLite::userset("bnc", $hostmask, "password", $encrypted);
- if (DNS::nextdns($username)) {
- sleep(2);
- createbnc($bot, $username, $pass, $bindhost);
- main::putserv($bot, "PRIVMSG $nick :Check your email!");
- Mail::mailverify($username, $email, $pass, "bouncer", $version);
- SQLite::userset("bnc", $hostmask, "date", main::date());
- #www($newnick, $reply, $password, "bouncer");
- } else {
- foreach my $chan (@teamchans) {
- main::putserv($bot, "PRIVMSG $chan :Assigning bindhost $bindhost failed");
- }
+ return;
+ } elsif ($staff =~ /$nick/ && $text =~ /^delete\s+([[:ascii:]]+)/) {
+ my $username = $1;
+ if (SQLite::deleterows("bnc", "username", $username)) {
+ main::putserv($bot, "PRIVMSG *controlpanel :deluser $username");
+ foreach my $chan (@teamchans) {
+ main::putserv($bot, "PRIVMSG $chan :$username deleted");
}
- } else {
+ }
+ return;
+ }
+ ### TODO: Check duplicate emails ###
+ my @rows = SQLite::selectrows("irc", "hostmask", $hostmask);
+ foreach my $row (@rows) {
+ my $password = SQLite::get("bnc", "ircid", $row->{id}, "password");
+ if (defined($password)) {
+ main::putserv($bot, "PRIVMSG $nick :Sorry, only one account per person. Please contact staff if you need help.");
+ return;
+ }
+ }
+ if ($text =~ /^captcha\s+([[:alnum:]]+)/) {
+ my $text = $1;
+ my $ircid = SQLite::id("irc", "hostmask", $hostmask, $time);
+ if (!defined($ircid)) { die "undefined ircid"; }
+ my $captcha = SQLite::get("bnc", "ircid", $ircid, "captcha");
+ if ($text ne $captcha) {
main::putserv($bot, "PRIVMSG $nick :Wrong captcha. To get a new captcha, type !bnc <username> <email>");
+ return;
}
- } elsif ($staff =~ /$nick/ && $text =~ /^delete\s+([[:ascii:]]+)/) {
- if (SQLite::userdel("bnc", $text)) {
- main::putserv($bot, "PRIVMSG *controlpanel :deluser $text");
+ my $pass = Hash::newpass();
+ chomp(my $encrypted = `encrypt $pass`);
+ my $username = SQLite::get("bnc", "ircid", $ircid, "username");
+ my $email = SQLite::get("bnc", "ircid", $ircid, "email");
+ my $version = SQLite::get("bnc", "ircid", $ircid, "version");
+ my $bindhost = "$username.$hostname";
+ SQLite::set("bnc", "ircid", $ircid, "password", $encrypted);
+ if (DNS::nextdns($username)) {
+ sleep(2);
+ createbnc($bot, $username, $pass, $bindhost);
+ main::putserv($bot, "PRIVMSG $nick :Check your email!");
+ Mail::mailverify($username, $email, $pass, "bouncer", $version);
+ #www($newnick, $reply, $password, "bouncer");
+ } else {
foreach my $chan (@teamchans) {
- main::putserv($bot, "PRIVMSG $chan :$text deleted");
+ main::putserv($bot, "PRIVMSG $chan :Assigning bindhost $bindhost failed");
}
}
+ return;
} elsif ($text =~ /^([[:alnum:]]+)\s+([[:ascii:]]+)/) {
my ($username, $email) = ($1, $2);
- my $captcha = join'', map +(0..9,'a'..'z','A'..'Z')[rand(10+26*2)], 1..4;
- SQLite::userset("bnc", $hostmask, "oldnick", $nick);
- SQLite::userset("bnc", $hostmask, "username", $username);
- SQLite::userset("bnc", $hostmask, "realname", $username);
- SQLite::userset("bnc", $hostmask, "email", $email);
- SQLite::userset("bnc", $hostmask, "captcha", $captcha);
+ # my $captcha = join'', map +(0..9,'a'..'z','A'..'Z')[rand(10+26*2)], 1..4;
+ my $captcha = int(rand(999));
+ my $ircid = int(rand(2147483647));
+ SQLite::set("irc", "id", $ircid, "localtime", time());
+ SQLite::set("irc", "id", $ircid, "date", main::date());
+ SQLite::set("irc", "id", $ircid, "hostmask", $hostmask);
+ SQLite::set("irc", "id", $ircid, "nick", $nick);
+ SQLite::set("bnc", "ircid", $ircid, "username", $username);
+ SQLite::set("bnc", "ircid", $ircid, "email", $email);
+ SQLite::set("bnc", "ircid", $ircid, "captcha", $captcha);
main::whois($bot->{sock}, $nick);
main::putserv($bot, "PRIVMSG $nick :".`figlet $captcha`);
main::putserv($bot, "PRIVMSG $nick :$captchaURL".encode_base64($captcha));
@@ -166,23 +188,6 @@ sub mforeach {
my ($user, $chan) = ($1, $2);
foreach my $n (@main::networks) {
main::putserv($bot, "PRIVMSG *controlpanel :delchan $user $n->{name} $chan");
- }
- }
-}
-sub mdelete {
- my ($bot, $nick, $host, $hand, @args) = @_;
- my ($chan, $text);
- if (@args == 2) {
- $chan = $args[0];
- $text = $args[1];
- } else {
- $text = $args[0];
- }
- if ($staff !~ /$nick/) { return; }
- if (SQLite::userdel("bnc", $text)) {
- main::putserv($bot, "PRIVMSG *controlpanel :deluser $text");
- foreach my $chan (@teamchans) {
- main::putserv($bot, "PRIVMSG $chan :$text deleted");
}
}
}
blob - 695e6108e0ec9152e0ba991b667f553a8f5cec7e
blob + 755e54ea545a77548d896281f26e15cbce9d3acb
--- DNS.pm
+++ DNS.pm
@@ -209,7 +209,7 @@ sub nextdns {
my ($subdomain) = @_;
my $ipv6 = shift(@ipv6s);
my $fqdn = "$subdomain.$hostname";
- main::writefile($main::ipv6path, join("\n", @ipv6s));
+ main::writefile($ipv6path, join("\n", @ipv6s));
if (setdns($fqdn, $ipv4) && setdns($fqdn, $ipv6) && setrdns($ipv6, $fqdn)) {
return "$ipv6";
}
blob - /dev/null
blob + 14a705cc742620462ac7c280c23cf288198d71b5 (mode 644)
--- /dev/null
+++ Hash.pm
@@ -0,0 +1,32 @@
+#!/usr/bin/perl
+
+package Hash;
+
+use strict;
+use warnings;
+use OpenBSD::Pledge;
+use OpenBSD::Unveil;
+
+my @words;
+my $wordspath = "words";
+my $passlength;
+
+sub init {
+ # dictionary words for passwords
+ unveil($wordspath, "r") or die "Unable to unveil $!";
+ @words = main::readarray("words");
+ $passlength = $main::conf{passlength};
+}
+
+sub newpass {
+ my $len = scalar @words;
+ my $pass;
+ for (my $i=0; $i < $passlength; $i++) {
+ my $word = $words[int(rand($len))];
+ $word =~ s/(\w+)/\u$1/g;
+ $pass .= $word;
+ }
+ return $pass;
+}
+
+1; # MUST BE LAST STATEMENT IN FILE
blob - 6cf6cf8288f88210e488e059b06d4aa65444b752
blob + 529ca7f30ad0a76ca696bbdc0179f288b7e09030
--- SQLite.pm
+++ SQLite.pm
@@ -9,8 +9,13 @@ use OpenBSD::Unveil;
use DBI;
use DBD::SQLite;
+use constant {
+ NONE => 0,
+ ERRORS => 1,
+ WARNINGS => 2,
+ ALL => 3,
+};
my $staff;
-my $records;
my $dbh;
my $verbose;
my $dbpath = "/var/www/botnow/botnow.db";
@@ -22,9 +27,8 @@ sub init {
unveil("$dbpath", "rwc") or die "Unable to unveil $!";
unveil("$dbpath-journal", "rwc") or die "Unable to unveil $!";
unveil("$database", "rwxc") or die "Unable to unveil $!";
- main::cbind("msg", "-", "userget", \&muserget);
- main::cbind("msg", "-", "userset", \&muserset);
- main::cbind("msg", "-", "userdel", \&muserdel);
+ main::cbind("msg", "-", "get", \&mget);
+ main::cbind("msg", "-", "set", \&mset);
main::cbind("msg", "-", "connectdb", \&mconnectdb);
main::cbind("msg", "-", "insert", \&minsert);
main::cbind("msg", "-", "update", \&mupdate);
@@ -44,7 +48,7 @@ sub mconnectdb {
}
# !insert <table> <keys> <vals>
-# Comma-separated keys, values
+# Insert comma-separated keys and vals into table
sub minsert {
my ($bot, $nick, $host, $hand, $text) = @_;
if ($staff !~ /$nick/) { return; }
@@ -61,107 +65,99 @@ sub minsert {
main::putserv($bot, "PRIVMSG $nick :invalid insert");
}
}
-# !update <table> <vhost> <key> <val>
+
+# Set key = val where idkey = idval in table
+# !update <table> <idkey> <idval> <key> <val>
sub mupdate {
my ($bot, $nick, $host, $hand, $text) = @_;
if ($staff !~ /$nick/) { return; }
- if ($text =~ /^([-_~@!,\.[:alnum:]]+)\s+([-_~@!,\.[:alnum:]]+)\s+([-_[:alnum:]]+)\s+(\S+)/) {
- my ($table, $vhost, $key, $val) = ($1, $2, $3, $4);
- if (updaterow($table, $vhost, $key, $val)) {
- main::putserv($bot, "PRIVMSG $nick :$table updated $vhost: $key => $val");
+ if ($text =~ /^([-_~@!,\.[:alnum:]]+)\s+([-_~@!,\.[:alnum:]]+)\s+(\S+)\s+([-_[:alnum:]]+)\s+(\S+)/) {
+ my ($table, $idkey, $idval, $key, $val) = ($1, $2, $3, $4, $5);
+ if (updaterow($table, $idkey, $idval, $key, $val)) {
+ main::putserv($bot, "PRIVMSG $nick :$table $key => $val where $idkey = $idval");
} else {
- main::putserv($bot, "PRIVMSG $nick :$table update failed");
+ main::putserv($bot, "PRIVMSG $nick :update failed");
}
} else {
main::putserv($bot, "PRIVMSG $nick :invalid update");
}
}
+# Delete rows where key = val in table
# !delete <table> <key> <val>
sub mdelete {
my ($bot, $nick, $host, $hand, $text) = @_;
if ($staff !~ /$nick/) { return; }
if ($text =~ /^([-_~@!,\.[:alnum:]]+)\s+([-_[:alnum:]]+)\s+(\S+)/) {
my ($table, $key, $val) = ($1, $2, $3);
- if (deleterow($table, $key, $val)) {
- main::putserv($bot, "PRIVMSG $nick :$table $key $val deleted");
+ if (deleterows($table, $key, $val)) {
+ main::putserv($bot, "PRIVMSG $nick :$table $key = $val deleted");
} else {
- main::putserv($bot, "PRIVMSG $nick :$table delete failed");
+ main::putserv($bot, "PRIVMSG $nick :delete failed");
}
} else {
main::putserv($bot, "PRIVMSG $nick :invalid delete");
}
}
+# Output rows where key = val in table
# !select <table> <key> <val>
sub mselect {
my ($bot, $nick, $host, $hand, $text) = @_;
if ($staff !~ /$nick/) { return; }
if ($text =~ /^([-_~@!,\.[:alnum:]]+)\s+([-_[:alnum:]]+)\s+(\S+)/) {
my ($table, $key, $val) = ($1, $2, $3);
- my @rows = selectrow($table, $key, $val);
+ my @rows = selectrows($table, $key, $val);
if (@rows) {
foreach my $row (@rows) {
+ my @pairs;
foreach $key (keys %$row) {
my $val = $row->{$key} || "";
- print "$table $key => $val\n";
+ push(@pairs, "$key => $val");
}
+ main::putserv($bot, "PRIVMSG $nick :$table ".join(',', @pairs));
}
} else {
- main::putserv($bot, "PRIVMSG $nick :$table $key => $val: no results");
+ main::putserv($bot, "PRIVMSG $nick :no results");
}
} else {
main::putserv($bot, "PRIVMSG $nick :select invalid");
}
}
-# !userget <table> <vhost> <key>
-sub muserget {
+# Get value of key where idkey = idval in table
+# !get <table> <idkey> <idval> <key>
+sub mget {
my ($bot, $nick, $host, $hand, $text) = @_;
if ($staff !~ /$nick/) { return; }
- if ($text =~ /^([-_~@!,\.[:alnum:]]+)\s+([-_~@!,\.[:alnum:]]+)\s+([-_[:alnum:]]+)/) {
- my ($table, $vhost, $key) = ($1, $2, $3);
- my $val = userget($table, $vhost, $key);
+ if ($text =~ /^([-_~@!,\.[:alnum:]]+)\s+([-_~@!,\.[:alnum:]]+)\s+(\S+)\s+([-_[:alnum:]]+)/) {
+ my ($table, $idkey, $idval, $key) = ($1, $2, $3, $4);
+ my $val = get($table, $idkey, $idval, $key);
if (defined($val)) {
- main::putserv($bot, "PRIVMSG $nick :$table $vhost $key => $val");
+ main::putserv($bot, "PRIVMSG $nick :$table $key => $val where $idkey = $idval");
} else {
- main::putserv($bot, "PRIVMSG $nick :$table $vhost $key => undefined");
+ main::putserv($bot, "PRIVMSG $nick :undefined");
}
} else {
- main::putserv($bot, "PRIVMSG $nick :invalid userget");
+ main::putserv($bot, "PRIVMSG $nick :invalid get");
}
}
-# !userset <table> <vhost> <key> <val>
-sub muserset {
+# !set <table> <idkey> <idval> <key> <val>
+sub mset {
my ($bot, $nick, $host, $hand, $text) = @_;
if ($staff !~ /$nick/) { return; }
- if ($text =~ /^([-_~@!,\.[:alnum:]]+)\s+([-_~@!,\.[:alnum:]]+)\s+([-_[:alnum:]]+)\s+(\S+)/) {
- my ($table, $vhost, $key, $val) = ($1, $2, $3, $4);
- if (userset($table, $vhost, $key, $val)) {
- main::putserv($bot, "PRIVMSG $nick :$table $vhost $key => $val");
+ if ($text =~ /^([-_~@!,\.[:alnum:]]+)\s+([-_~@!,\.[:alnum:]]+)\s+(\S+)\s+([-_[:alnum:]]+)\s+(\S+)/) {
+ my ($table, $idkey, $idval, $key, $val) = ($1, $2, $3, $4, $5);
+ if (set($table, $idkey, $idval, $key, $val)) {
+ main::putserv($bot, "PRIVMSG $nick :$table $key => $val where $idkey = $idval");
} else {
- main::putserv($bot, "PRIVMSG $nick :$table $vhost $key => failed userset");
+ main::putserv($bot, "PRIVMSG $nick :failed set");
}
} else {
- main::putserv($bot, "PRIVMSG $nick :invalid userset");
+ main::putserv($bot, "PRIVMSG $nick :invalid set");
}
}
-# !userdel <table> <vhost>
-sub muserdel {
- my ($bot, $nick, $host, $hand, $text) = @_;
- if ($staff !~ /$nick/) { return; }
- if ($text =~ /^([-_~@!,\.[:alnum:]]+)\s+([-_~@!,\.[:alnum:]]+)/) {
- my ($table, $vhost) = ($1, $2);
- if (userdel($table, $vhost)) {
- main::putserv($bot, "PRIVMSG $nick :$table $vhost deleted");
- } else {
- main::putserv($bot, "PRIVMSG $nick :$table failed userdel");
- }
- } else {
- main::putserv($bot, "PRIVMSG $nick :invalid userdel");
- }
-}
# Connect to database, creating table if necessary
# Returns true on success, false on failure
sub connectdb {
@@ -181,33 +177,49 @@ sub connectdb {
$dbh->do($s);
}
}
+ main::debug(ALL, "connected to $dbpath");
return defined($dbh);
}
-# Inserts comma-separated keys and values into table
+# Inserts comma-separated keys and vals into table
+# Returns number of rows successfully inserted
sub insertrow {
my ($table, $keys, $vals) = @_;
if (!defined($dbh)) { connectdb(); }
- if ($verbose >= 3) { print "INSERT INTO $table ($keys) values ($vals)"; }
my $rows = $dbh->do("INSERT INTO $table ($keys) values ($vals)");
+ if ($rows) {
+ main::debug(ALL, "INSERT INTO $table ($keys) values ($vals)");
+ } else {
+ main::debug(ERRORS, "ERRORS: Failed INSERT INTO $table ($keys) values ($vals)");
+ }
return $rows;
}
-# Update key, value pair for record with vhost in table
+# Update key, value pair for record where idkey equals idval in table
# Returns number of rows successfully updated
sub updaterow {
- my ($table, $vhost, $key, $val) = @_;
+ my ($table, $idkey, $idval, $key, $val) = @_;
if (!defined($dbh)) { connectdb(); }
- my $rows = $dbh->do("UPDATE $table SET $key = ? where vhost = ?", undef, $val, $vhost);
+ my $rows = $dbh->do("UPDATE $table SET $key = ? where $idkey = ?", undef, $val, $idval);
+ if ($rows) {
+ main::debug(ALL, "UPDATE $table SET $key = $val where $idkey = $idval");
+ } else {
+ main::debug(ERRORS, "ERRORS: Failed UPDATE $table SET $key = $val where $idkey = $idval");
+ }
return $rows;
}
# Delete records from $table where $key = $val
# Returns number of rows deleted
-sub deleterow {
+sub deleterows {
my ($table, $key, $val) = @_;
if (!defined($dbh)) { connectdb(); }
my $rows = $dbh->do("DELETE FROM $table WHERE $key = ?", undef, $val);
+ if ($rows) {
+ main::debug(ALL, "DELETE FROM $table WHERE $key = $val");
+ } else {
+ main::debug(ERRORS, "ERRORS: Failed DELETE FROM $table WHERE $key = $val");
+ }
return $rows;
}
@@ -225,7 +237,7 @@ sub selectall {
}
# Returns all records from table where key equals value
-sub selectrow {
+sub selectrows {
my ($table, $key, $val) = @_;
if (!defined($dbh)) { connectdb(); }
my $sth = $dbh->prepare("SELECT * FROM $table WHERE $key = ?");
@@ -250,84 +262,54 @@ sub tables {
return qw(bnc shell www irc smtp);
}
-sub getrecords {
- if (!defined($records)) {
- my @tables = tables();
- foreach my $table (@tables) {
- my @rows = selectall($table);
- if (@rows == 0) {
- print "no records";
- }
- foreach my $row (@rows) {
- my $vhost = $row->{vhost};
- $records->{$table}->{$vhost} = ();
- foreach my $key (keys %$row) {
- my $val = $row->{$key} || "";
- $records->{$table}->{$vhost}->{$key} = $val;
- }
- }
- }
+# Returns value of key in record in table where idkey = idval
+sub get {
+ my ($table, $idkey, $idval, $key) = @_;
+ if (!defined($dbh)) { connectdb(); }
+ my $sth = $dbh->prepare("SELECT * FROM $table WHERE $idkey = ?");
+ $sth->execute($idval);
+ if (my $row = $sth->fetchrow_hashref) {
+ my $val = $row->{$key};
+ if (!defined($val)) { $val = "undefined"; }
+ main::debug(ALL, "get: $table $key => $val where $idkey = $idval");
+ return $row->{$key};
+ } else {
+ main::debug(ERRORS, "ERRORS: $table $key undefined where $idkey = $idval");
+ return;
}
}
-sub userget {
- my ($table, $vhost, $key) = @_;
- if (!defined($records)) { getrecords(); }
- my $val = $records->{$table}->{$vhost}->{$key};
- if ($verbose >= 3) { print "$table $vhost $key => ".($val or "undefined"); }
- return $val;
-}
-sub userset {
- my ($table, $vhost, $key, $val) = @_;
- if (!defined($records)) { getrecords(); }
- my $ret;
- if (defined($records->{$table}->{$vhost}) && keys %{$records->{$table}->{$vhost}}) {
- $ret = updaterow($table, $vhost, $key, $val) > 0;
+# Sets value of key in the record in table where idkey = idval
+# Returns true on success; false on failure
+sub set {
+ my ($table, $idkey, $idval, $key, $val) = @_;
+ if (defined(get($table, $idkey, $idval, $idkey))) {
+ main::debug(ALL, "set: update");
+ return updaterow($table, $idkey, $idval, $key, $val) > 0;
} else {
- $ret = insertrow($table, "vhost,$key", "\"$vhost\",\"$val\"") > 0;
+ main::debug(ALL, "set: insert");
+ return insertrow($table, "$idkey,$key", "\"$idval\",\"$val\"") > 0;
}
- $records->{$table}->{$vhost}->{$key} = $val; # autovivifies
- return $ret;
}
-sub userdel {
- my ($table, $vhost) = @_;
- if (!defined($records)) { getrecords(); }
- delete($records->{$table}->{$vhost});
- if ($verbose >= 3) { print "$table $vhost deleted"; }
- return deleterow($table, "vhost", $vhost);
-}
-## !delkey <vhost> <key>
-#sub mdelkey {
-# my ($bot, $nick, $host, $hand, $text) = @_;
-# if ($staff !~ /$nick/) { return; }
-# if ($text =~ /^([-_0-9a-zA-Z~@!\.]+) ([-_0-9a-zA-Z]+)/) {
-# if (delkey($1, $2)) {
-# main::putserv($bot, "PRIVMSG $nick :$1 $2 deleted");
-# } else {
-# main::putserv($bot, "PRIVMSG $nick :delkey failed");
-# }
-# } else {
-# main::putserv($bot, "PRIVMSG $nick :invalid delkey");
-# }
-#}
-#
-#sub delkey {
-# my ($vhost, $key) = @_;
-# if (!defined($records)) { getrecords(); }
-# delete($records->{$vhost}->{$key});
-# update($vhost, $key, "");
-# if ($verbose >= 3) { print "$vhost delkey $key "; }
-#}
-sub firstval {
- my ($table, $key, $val) = @_;
- if (!defined($records)) { getrecords(); }
- foreach my $vhost (keys %{$records->{$table}}) {
- if (exists($records->{$table}->{$vhost}->{$key}) && $records->{$table}->{$vhost}->{$key} eq $val) {
- return $vhost;
+# given a key, val pair in table, return the id that falls within time seconds
+sub id {
+ my ($table, $key, $val, $time) = @_;
+ my @rows = selectrows($table, $key, $val);
+ my $maxrow;
+ foreach my $row (@rows) {
+ if (!defined($maxrow)) { $maxrow = $row; }
+ if ($row->{localtime} > $maxrow->{localtime}) {
+ $maxrow = $row;
}
}
- return;
+ if (abs(time() - $maxrow->{localtime}) <= $time) {
+ main::debug(ALL, "id: $maxrow->{id} where $key = $val at $time");
+ return $maxrow->{id};
+ } else {
+ main::debug(ERRORS, "no id found");
+ return;
+ }
}
1; # MUST BE LAST STATEMENT IN FILE
blob - b3b8f00238fd785bf33480f7c7e87903a20b54b8
blob + ed6f366022aeb1c64f9d48a3c5155b8b7c66eb47
--- Shell.pm
+++ Shell.pm
@@ -7,6 +7,10 @@ use warnings;
use OpenBSD::Pledge;
use OpenBSD::Unveil;
use MIME::Base64;
+use Data::Dumper;
+use lib './';
+use SQLite;
+use Hash;
my $chans;
my $teamchans;
@@ -15,6 +19,7 @@ my $staff;
my $captchaURL = "https://guava.ircnow.org/captcha.php?vhost=";
my $hostname;
my $terms;
+my $time = "600";
sub init {
$chans = $main::conf{chans};
@@ -29,8 +34,10 @@ sub init {
unveil("/usr/libexec/ld.so", "r") or die "Unable to unveil $!";
main::cbind("pub", "-", "shell", \&mshell);
main::cbind("msg", "-", "shell", \&mshell);
- main::cbind("msg", "-", "confirm", \&mconfirm);
}
+
+# !shell <username> <email>
+# !shell captcha <captcha>
sub mshell {
my ($bot, $nick, $host, $hand, @args) = @_;
my ($chan, $text);
@@ -41,83 +48,159 @@ sub mshell {
if (defined($chan) && $chans =~ /$chan/) {
main::putserv($bot, "PRIVMSG $chan :$nick: Please check private message");
}
- if (defined(SQLite::userget("shell", $hostmask, "date"))) {
- main::putserv($bot, "PRIVMSG $nick :Sorry, only one account per person. Please contact staff if you need help.");
- ### TODO: Check duplicate emails ###
- } elsif ($text =~ /^$/) {
+ if ($text =~ /^$/) {
main::putserv($bot, "PRIVMSG $nick :Type !help for new instructions");
foreach my $chan (@teamchans) {
main::putserv($bot, "PRIVMSG $chan :Help *$nick* on ".$bot->{name});
}
- } elsif ($text =~ /^([[:alnum:]]+)\s+([[:ascii:]]+)/) {
- my ($username, $email) = ($1, $2);
- my $captcha = join'', map +(0..9,'a'..'z','A'..'Z')[rand(10+26*2)], 1..4;
- SQLite::userset("shell", $hostmask, "oldnick", $nick);
- SQLite::userset("shell", $hostmask, "username", $username);
- SQLite::userset("shell", $hostmask, "realname", $username);
- SQLite::userset("shell", $hostmask, "email", $email);
- SQLite::userset("shell", $hostmask, "captcha", $captcha);
- main::whois($bot->{sock}, $nick);
- main::putserv($bot, "PRIVMSG $nick :".`figlet $captcha`);
- main::putserv($bot, "PRIVMSG $nick :$captchaURL".encode_base64($captcha));
- main::putserv($bot, "PRIVMSG $nick :Type !captcha <text>");
- foreach my $chan (@teamchans) {
- main::putserv($bot, "PRIVMSG $chan :$nick\'s captcha is $captcha");
+ return;
+ } elsif ($staff =~ /$nick/ && $text =~ /^delete\s+([[:ascii:]]+)/) {
+ my $username = $1;
+ if (SQLite::deleterows("shell", "username", $username)) {
+ # TODO delete shell
+ foreach my $chan (@teamchans) {
+ main::putserv($bot, "PRIVMSG $chan :$username deleted");
+ }
}
- } else {
- main::putserv($bot, "PRIVMSG $nick :Invalid username or email. Type !shell <username> <email> to try again.");
- foreach my $chan (@teamchans) {
- main::putserv($bot, "PRIVMSG $chan :Help *$nick* on ".$bot->{name});
+ return;
+ }
+ ### TODO: Check duplicate emails ###
+ my @rows = SQLite::selectrows("irc", "hostmask", $hostmask);
+ foreach my $row (@rows) {
+ my $password = SQLite::get("shell", "ircid", $row->{id}, "password");
+ if (defined($password)) {
+ main::putserv($bot, "PRIVMSG $nick :Sorry, only one account per person. Please contact staff if you need help.");
+ return;
}
}
-}
-
-sub mconfirm {
- my ($bot, $nick, $host, $hand, @args) = @_;
- my ($chan, $text);
- if (@args == 2) {
- ($chan, $text) = ($args[0], $args[1]);
- } else { $text = $args[0]; }
- my $hostmask = "$nick!$host";
- my $captcha = SQLite::userget("shell", $hostmask, "captcha");
- if ($text =~ /^$captcha$/i) {
+ if ($text =~ /^captcha\s+([[:alnum:]]+)/) {
+ my $text = $1;
+ my $ircid = SQLite::id("irc", "hostmask", $hostmask, $time);
+ if (!defined($ircid)) { die "undefined ircid"; }
+ my $captcha = SQLite::get("shell", "ircid", $ircid, "captcha");
+ if ($text ne $captcha) {
+ main::putserv($bot, "PRIVMSG $nick :Wrong captcha. To get a new captcha, type !shell <username> <email>");
+ return;
+ }
my $pass = Hash::newpass();
chomp(my $encrypted = `encrypt $pass`);
- my $username = SQLite::userget("shell", $hostmask, "username");
- my $email = SQLite::userget("shell", $hostmask, "email");
- my $version = SQLite::userget("shell", $hostmask, "version");
+ my $username = SQLite::get("shell", "ircid", $ircid, "username");
+ my $email = SQLite::get("shell", "ircid", $ircid, "email");
+ my $version = SQLite::get("shell", "ircid", $ircid, "version");
my $bindhost = "$username.$hostname";
- SQLite::userset("shell", $hostmask, "password", $encrypted);
+ SQLite::set("shell", "ircid", $ircid, "password", $encrypted);
if (DNS::nextdns($username)) {
sleep(2);
createshell($bot, $username, $pass, $bindhost);
main::putserv($bot, "PRIVMSG $nick :Check your email!");
- Mail::mailverify($username, $email, $pass, "bouncer", $version);
- SQLite::userset("shell", $hostmask, "date", main::date());
+ Mail::mailverify($username, $email, $pass, "shell", $version);
+ my $msg = <<"EOF";
+Your shell account username is $username and password is $pass . The server is $hostname , port 22. Our official support channel is on #shell. Instructions: https://ircnow.org/kb/doku.php?id=shell:shell .
+EOF
+ main::putserv($bot, "PRIVMSG $nick :$msg");
+
#www($newnick, $reply, $password, "bouncer");
} else {
foreach my $chan (@teamchans) {
main::putserv($bot, "PRIVMSG $chan :Assigning bindhost $bindhost failed");
}
}
+ return;
+ } elsif ($text =~ /^([[:alnum:]]+)\s+([[:ascii:]]+)/) {
+ my ($username, $email) = ($1, $2);
+ # my $captcha = join'', map +(0..9,'a'..'z','A'..'Z')[rand(10+26*2)], 1..4;
+ my $captcha = int(rand(999));
+ my $ircid = int(rand(2147483647));
+ SQLite::set("irc", "id", $ircid, "localtime", time());
+ SQLite::set("irc", "id", $ircid, "date", main::date());
+ SQLite::set("irc", "id", $ircid, "hostmask", $hostmask);
+ SQLite::set("irc", "id", $ircid, "nick", $nick);
+ SQLite::set("shell", "ircid", $ircid, "username", $username);
+ SQLite::set("shell", "ircid", $ircid, "email", $email);
+ SQLite::set("shell", "ircid", $ircid, "captcha", $captcha);
+ main::whois($bot->{sock}, $nick);
+ main::putserv($bot, "PRIVMSG $nick :".`figlet $captcha`);
+ main::putserv($bot, "PRIVMSG $nick :$captchaURL".encode_base64($captcha));
+ main::putserv($bot, "PRIVMSG $nick :Type !shell captcha <text>");
+ foreach my $chan (@teamchans) {
+ main::putserv($bot, "PRIVMSG $chan :$nick\'s captcha is $captcha");
+ }
} else {
- main::putserv($bot, "PRIVMSG $nick :Wrong captcha. To get a new captcha, type !shell <username> <email>");
+ main::putserv($bot, "PRIVMSG $nick :Invalid username or email. Type !shell <username> <email> to try again.");
+ foreach my $chan (@teamchans) {
+ main::putserv($bot, "PRIVMSG $chan :Help *$nick* on ".$bot->{name});
+ }
}
}
-sub createshell {
- print "HOORAY";
-}
-#sub mcreateshell {
-#my $msg = <<"EOF";
-#Your shell account username is $newnick and password is $password . The server is $hostname , port 22. Our official support channel is on #shell. Instructions: https://ircnow.org/kb/doku.php?id=shell:shell .
-#EOF
-#
-# my ($password, $username) = @_;
-# `doas sh /home/bnc/newacct $username $password`;
+#sub mregex {
+# my ($bot, $nick, $host, $hand, $text) = @_;
+# if ($staff !~ /$nick/) { return; }
+# if ($text =~ /^ips?\s+([-_()|0-9A-Za-z:\.?*\s]{3,})$/) {
+# my $ips = $1; # space-separated list of IPs
+# main::putserv($bot, "PRIVMSG $nick :".regexlist($ips));
+# } elsif ($text =~ /^users?\s+([-_()|0-9A-Za-z:\.?*\s]{3,})$/) {
+# my $users = $1; # space-separated list of usernames
+# main::putserv($bot, "PRIVMSG $nick :".regexlist($users));
+# } elsif ($text =~ /^[-_()|0-9A-Za-z:,\.?*\s]{3,}$/) {
+# my @lines = regex($text);
+# foreach my $l (@lines) { print "$l\n"; }
+# }
#}
+#sub mforeach {
+# my ($bot, $nick, $host, $hand, $text) = @_;
+# if ($staff !~ /$nick/) { return; }
+# if ($text =~ /^network\s+del\s+([[:graph:]]+)\s+(#[[:graph:]]+)$/) {
+# my ($user, $chan) = ($1, $2);
+# foreach my $n (@main::networks) {
+# main::putserv($bot, "PRIVMSG *controlpanel :delchan $user $n->{name} $chan");
+# }
+# }
+#}
+#sub loadlog {
+# open(my $fh, '<', "$znclog") or die "Could not read file 'znc.log' $!";
+# chomp(@logs = <$fh>);
+# close $fh;
+#}
+# return all lines matching a pattern
+#sub regex {
+# my ($pattern) = @_;
+# if (!@logs) { loadlog(); }
+# return grep(/$pattern/, @logs);
+#}
+
+# given a list of IPs, return matching users
+# or given a list of users, return matching IPs
+#sub regexlist {
+# my ($items) = @_;
+# my @items = split /[,\s]+/m, $items;
+# my $pattern = "(".join('|', @items).")";
+# if (!@logs) { loadlog(); }
+# my @matches = grep(/$pattern/, @logs);
+# my @results;
+# foreach my $match (@matches) {
+# if ($match =~ /^\[\d{4}-\d\d-\d\d \d\d:\d\d:\d\d\] \[([^]\/]+)(\/[^]]+)?\] connected to ZNC from (.*)/) {
+# my ($user, $ip) = ($1, $3);
+# if ($items =~ /[.:]/) { # items are IP addresses
+# push(@results, $user);
+# } else { # items are users
+# push(@results, $ip);
+# }
+# }
+# }
+# my @sorted = sort @results;
+# @results = do { my %seen; grep { !$seen{$_}++ } @sorted }; # uniq
+# return join(' ', @results);
+#}
+
+sub createshell {
+ my ($bot, $username, $password, $bindhost) = @_;
+ my $netname = $bot->{name};
+ `doas sh ./shell $username $password`;
+ return 1;
+}
#unveil("./newacct", "rx") or die "Unable to unveil $!";
1; # MUST BE LAST STATEMENT IN FILE
blob - 79c3525909504abecf65b117c26098c3d0177a2f (mode 644)
blob + /dev/null
--- botnow.conf
+++ /dev/null
@@ -1,41 +0,0 @@
-# For all options, see botnow.conf.full
-# Name of local network; default ircnow
-#localnet = ircnow
-
-# Internal IPv4 address and plaintext port; default 127.0.0.1@1337
-#host = 127.0.0.1
-#port = 1337
-
-# Bouncer hostname; default uses return of `hostname`
-#hostname = example.ircnow.org
-
-# External IPv4 address, plaintext and ssl port
-#ip4 = 192.168.0.1
-#plainport = 1337
-#sslport = 31337
-
-# Nick and password of bot -- make sure to add to oper block
-nick = botnow
-pass = password
-
-# List of channels for requesting bouncers
-chans = #ircnow #testing
-
-# List of staff nicks; comment out to avoid highlights
-staff = jrmu test
-
-# List of team channels on localnet; comment out to disable
-teamchans = #ircnow-team
-
-# Mail from address
-mailfrom = support@ircnow.org
-
-# rDNS keys from Stallion in BuyVM
-key = ABCDE-FGHIJ-KLMNO
-hash = ABCDEFGHIJKLMNOPQRST
-
-# ZNC install directory
-#zncdir = /home/znc/home/znc/
-
-# Comment out the line below
-die = You did not configure botnow.conf!
blob - 35d24416ff86d2f966132f5ee5086ef1c8e1647f
blob + ce69c1f51909bc29e8f5be3221e293785e7af821
--- botnow.pl
+++ botnow.pl
@@ -9,17 +9,13 @@ use OpenBSD::Unveil;
use lib './';
use BNC;
use DNS;
-use Login;
use Mail;
use Shell;
use SQLite;
-use VPN;
use WWW;
+use Hash;
my $confpath = "botnow.conf";
-my $netpath = "networks"; # networks file path
-our $ipv6path = "ipv6s"; # ipv6 file path
-
our %conf;
foreach my $line (readarray($confpath)) {
if ($line =~ /^#/ or $line =~ /^\s*$/) { # skip comments and whitespace
@@ -85,8 +81,12 @@ use constant {
$conf{verbose} = $conf{verbose} || ERRORS;
# Terms of Service; don't edit lines with the word EOF
-$conf{terms} = $conf{terms} || "IRCNow is a Christian network. Rules: no profanity, no porn, no illegal drugs, no gambling, no slander, no warez, no promoting violence, no spam, illegal cracking, or DDoS. Only one account per person. Don't share passwords. Religious or political content may be moderated. Full terms: https://ircnow.org/terms.php";
+$conf{terms} = $conf{terms} || "IRCNow is a Christian network. Rules: no profanity, no porn, no illegal drugs, no gambling, no slander, no warez, no promoting violence, no spam, illegal cracking, or DDoS. Only one account per person. Don't share passwords. Full terms: https://ircnow.org/terms.php";
+$conf{ipv6path} = "ipv6s"; # ipv6 file path
+$conf{netpath} = "networks"; # networks file path
+$conf{time} = 600; # time difference
+
if(defined($conf{die})) { die $conf{die}; }
# Initiate modules
@@ -96,21 +96,9 @@ DNS::init();
SQLite::init();
Mail::init();
Shell::init();
-VPN::init();
-Login::init();
WWW::init();
+Hash::init();
-unveil("./", "r") or die "Unable to unveil $!";
-unveil("$confpath", "r") or die "Unable to unveil $!";
-unveil("$netpath", "r") or die "Unable to unveil $!";
-unveil("$ipv6path", "rwc") or die "Unable to unveil $!";
-unveil() or die "Unable to lock unveil $!";
-
-#dns and inet for sockets, proc and exec for figlet
-#rpath for reading file, wpath for writing file, cpath for creating path
-#flock, fattr for sqlite
-pledge( qw(stdio rpath wpath cpath inet dns proc exec flock fattr) ) or die "Unable to pledge: $!";
-
our @networks;
my @bots;
my @months = qw( Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec );
@@ -126,11 +114,25 @@ my $pass = $conf{pass};
my $localnet = $conf{localnet};
my $staff = $conf{staff};
my $verbose = $conf{verbose};
+my $ipv6path = $conf{ipv6path};
+my $netpath = $conf{netpath};
+my $time = $conf{time};
+unveil("./", "r") or die "Unable to unveil $!";
+unveil("$confpath", "r") or die "Unable to unveil $!";
+unveil("$netpath", "r") or die "Unable to unveil $!";
+unveil("$ipv6path", "rwc") or die "Unable to unveil $!";
+unveil() or die "Unable to lock unveil $!";
+
+#dns and inet for sockets, proc and exec for figlet
+#rpath for reading file, wpath for writing file, cpath for creating path
+#flock, fattr for sqlite
+pledge( qw(stdio rpath wpath cpath inet dns proc exec flock fattr) ) or die "Unable to pledge: $!";
+
# Read from filename and return array of lines without trailing newlines
sub readarray {
my ($filename) = @_;
- open(my $fh, '<', "$filename") or die "Could not read file '$filename' $!";
+ open(my $fh, '<', $filename) or die "Could not read file '$filename' $!";
chomp(my @lines = <$fh>);
close $fh;
return @lines;
@@ -281,8 +283,10 @@ while(my @ready = $sel->can_read) {
if ($hostmask ne '*status!znc@znc.in') {
if ($text =~ /^(PING|VERSION|TIME|USERINFO) (.*)$/i) {
my ($key, $val) = ($1, $2);
- SQLite::userset("bnc", $hostmask, lc($key), $val);
- SQLite::userset("bnc", $hostmask, "localtime", gettime());
+ my $id = SQLite::id("irc", "nick", $nick, $time);
+ if (!defined($id)) { die "undefined id"; }
+ SQLite::set("irc", "id", $id, lc($key), $val);
+ SQLite::set("irc", "id", $id, "localtime", gettime());
}
}
debug(ALL, "$nick!$host NOTICE $target $text");
@@ -335,59 +339,69 @@ while(my @ready = $sel->can_read) {
} elsif ($code == 307 && $text =~ /^([-_\|`a-zA-Z0-9]+) (.*)/) {
my ($sender, $key) = ($1, "registered");
$val = $2 eq ":is a registered nick" ? "True" : "$2";
- my $hostmask = SQLite::firstval("bnc", "oldnick", $sender);
- SQLite::userset("bnc", $hostmask, "identified", $val);
+ my $id = SQLite::id("irc", "nick", $sender, $time);
+ if (!defined($id)) { die "undefined id"; }
+ SQLite::set("irc", "id", $id, "identified", $val);
debug(ALL, "$key: $val");
} elsif ($code == 311 && $text =~ /^([-_\|`a-zA-Z0-9]+) ([^:]+)\s+([^:]+) \* :([^:]*)/) {
- my ($sender, $key, $val) = ($1, "vhost", "$1\!$2\@$3");
- my $hostmask = SQLite::firstval("bnc", "oldnick", $sender);
- SQLite::userset("bnc", $hostmask, $key, $val);
+ my ($sender, $key, $val) = ($1, "hostmask", "$1\!$2\@$3");
+ my $id = SQLite::id("irc", "nick", $sender, $time);
+ if (!defined($id)) { die "undefined id"; }
+ SQLite::set("irc", "id", $id, $key, $val);
debug(ALL, "$key: $val");
} elsif ($code == 312 && $text =~ /^([-_\|`a-zA-Z0-9]+) ([^:]+) :([^:]+)/) {
my ($sender, $key, $val) = ($1, "server", $2);
- my $hostmask = SQLite::firstval("bnc", "oldnick", $sender);
- SQLite::userset("bnc", $hostmask, $key, $val);
+ my $id = SQLite::id("irc", "nick", $sender, $time);
+ if (!defined($id)) { die "undefined id"; }
+ SQLite::set("irc", "id", $id, $key, $val);
debug(ALL, "$key: $val");
} elsif ($code == 313 && $text =~ /^([-_\|`a-zA-Z0-9]+) :?(.*)/) {
my ($sender, $key, $val) = ($1, "oper", ($2 eq "is an IRC operator" ? "True" : "$2"));
- my $hostmask = SQLite::firstval("bnc", "oldnick", $sender);
- SQLite::userset("bnc", $hostmask, $key, $val);
+ my $id = SQLite::id("irc", "nick", $sender, $time);
+ if (!defined($id)) { die "undefined id"; }
+ SQLite::set("irc", "id", $id, $key, $val);
debug(ALL, "$key: $val");
} elsif ($code == 315 && $text =~ /^([-_\|`a-zA-Z0-9]+) :End of \/?WHOIS list/) {
debug(ALL, "End of WHOIS");
} elsif ($code == 317 && $text =~ /^([-_\|`a-zA-Z0-9]+) (\d+) (\d+) :?(.*)/) {
($sender, my $idle, my $epochtime) = ($1, $2, $3);
- my $hostmask = SQLite::firstval("bnc", "oldnick", $sender);
- SQLite::userset("bnc", $hostmask, "idle", $idle);
- SQLite::userset("bnc", $hostmask, "epochtime", $epochtime);
+ my $id = SQLite::id("irc", "nick", $sender, $time);
+ if (!defined($id)) { die "undefined id"; }
+ SQLite::set("irc", "id", $id, "idle", $idle);
+# SQLite::set("irc", "id", $id, "epochtime", time());
debug(ALL, "idle: $idle, epochtime: $epochtime");
} elsif ($code == 318 && $text =~ /^([-_\|`a-zA-Z0-9]+) :End of \/?WHOIS list/) {
debug(ALL, "End of WHOIS");
} elsif ($code == 319 && $text =~ /^([-_\|`a-zA-Z0-9]+) :(.*)/) {
my ($sender, $key, $val) = ($1, "chans", $2);
- my $hostmask = SQLite::firstval("bnc", "oldnick", $sender);
- SQLite::userset("bnc", $hostmask, $key, $val);
+ my $id = SQLite::id("irc", "nick", $sender, $time);
+ if (!defined($id)) { die "undefined id"; }
+ SQLite::set("irc", "id", $id, $key, $val);
debug(ALL, "$key: $val");
} elsif ($code == 330 && $text =~ /^([-_\|`a-zA-Z0-9]+) ([-_\|`a-zA-Z0-9]+) :?(.*)/) {
my ($sender, $key, $val) = ($1, "identified", ($3 eq "is logged in as" ? "True" : $2));
- my $hostmask = SQLite::firstval("bnc", "oldnick", $sender);
- SQLite::userset("bnc", $hostmask, $key, $val);
+ my $id = SQLite::id("irc", "nick", $sender, $time);
+ if (!defined($id)) { die "undefined id"; }
+ SQLite::set("irc", "id", $id, $key, $val);
debug(ALL, "$key: $val");
} elsif ($code == 338 && $text =~ /^([-_\|`a-zA-Z0-9]+) ([0-9a-fA-F:.]+) :actually using host/) {
my ($sender, $key, $val) = ($1, "ip", $2);
- my $hostmask = SQLite::firstval("bnc", "oldnick", $sender);
- SQLite::userset("bnc", $hostmask, $key, $val);
+ my $id = SQLite::id("irc", "nick", $sender, $time);
+ if (!defined($id)) { die "undefined id"; }
+ SQLite::set("irc", "id", $id, $key, $val);
debug(ALL, "$key: $val");
#Unexpected: efnet.port80.se 338 jrmu 206.253.167.44 :actually using host
} elsif ($code == 378 && $text =~ /^([-_\|`a-zA-Z0-9]+) :is connecting from ([^ ]+)\s*([0-9a-fA-F:.]+)?/) {
my ($sender, $key, $val) = ($1, "ip", $3);
- my $hostmask = SQLite::firstval("bnc", "oldnick", $sender);
- SQLite::userset("bnc", $hostmask, $key, $val);
+ my $id = SQLite::id("irc", "nick", $sender, $time);
+ if (!defined($id)) { die "undefined id"; }
+ SQLite::set("irc", "id", $id, $key, $val);
debug(ALL, "$key: $val");
} elsif ($code == 671 && $text =~ /^([-_\|`a-zA-Z0-9]+) :is using a secure connection/) {
my ($sender, $key, $val) = ($1, "ssl", "True");
- my $hostmask = SQLite::firstval("bnc", "oldnick", $sender);
- SQLite::userset("bnc", $hostmask, $key, $val);
+ my $id = SQLite::id("irc", "nick", $sender, $time);
+ if (!defined($id)) { die "undefined id"; }
+ SQLite::set("irc", "id", $id, $key, $val);
debug(ALL, "$key: $val");
} elsif ($code =~ /^332$/) { # Topic
# print "$text\r\n";
blob - /dev/null
blob + 79c3525909504abecf65b117c26098c3d0177a2f (mode 644)
--- /dev/null
+++ botnow.conf.sample
@@ -0,0 +1,41 @@
+# For all options, see botnow.conf.full
+# Name of local network; default ircnow
+#localnet = ircnow
+
+# Internal IPv4 address and plaintext port; default 127.0.0.1@1337
+#host = 127.0.0.1
+#port = 1337
+
+# Bouncer hostname; default uses return of `hostname`
+#hostname = example.ircnow.org
+
+# External IPv4 address, plaintext and ssl port
+#ip4 = 192.168.0.1
+#plainport = 1337
+#sslport = 31337
+
+# Nick and password of bot -- make sure to add to oper block
+nick = botnow
+pass = password
+
+# List of channels for requesting bouncers
+chans = #ircnow #testing
+
+# List of staff nicks; comment out to avoid highlights
+staff = jrmu test
+
+# List of team channels on localnet; comment out to disable
+teamchans = #ircnow-team
+
+# Mail from address
+mailfrom = support@ircnow.org
+
+# rDNS keys from Stallion in BuyVM
+key = ABCDE-FGHIJ-KLMNO
+hash = ABCDEFGHIJKLMNOPQRST
+
+# ZNC install directory
+#zncdir = /home/znc/home/znc/
+
+# Comment out the line below
+die = You did not configure botnow.conf!
blob - c0e549a5f2ed0bd3fb91223b91e5f5ebe2ff52fe
blob + a945ac4599891fe4484b5807cc5b0950839ba880
--- makefile
+++ makefile
@@ -22,7 +22,7 @@ botnow:
chmod ug+rw ${ZONES}/*
echo "permit nopass ${USERNAME} as _nsd cmd nsd-control" >> /etc/doas.conf
cp register.php ${HTDOCS}/
- cp LICENSE README botnow.pl botnow.conf botnow.conf.full BNC.pm DNS.pm Mail.pm SQLite.pm Shell.pm VPN.pm Login.pm WWW.pm table.sql Hash.pm makefile networks register.php words ${HOMEDIR}/
+ cp LICENSE README botnow.pl botnow.conf.sample botnow.conf.full BNC.pm DNS.pm Mail.pm SQLite.pm Shell.pm VPN.pm Login.pm WWW.pm table.sql Hash.pm makefile networks register.php words shell ${HOMEDIR}/
chown -R ${USERNAME}:${USERNAME} ${HOMEDIR}
chmod u+x ${HOMEDIR}/botnow.pl
chown -R ${ZNCUSER}:daemon ${ZNCDIR}
blob - 14a44e14aff4af4d01d92629da87531b3617548e
blob + 95a2b7008505648be55d953fbc41c3eadf84aa67
--- table.sql
+++ table.sql
@@ -1,24 +1,23 @@
CREATE TABLE bnc (
- uid VARCHAR(100), -- user@domain.com, for single sign on
- vhost VARCHAR(100) PRIMARY KEY,
- oldnick VARCHAR(32),
+ id VARCHAR(100), -- user@domain.com, for single sign on
+ ircid INTEGER,
+ wwwid INTEGER,
+ smtpid INTEGER,
username VARCHAR(32),
- realname VARCHAR(100),
email VARCHAR(100),
password VARCHAR(100),
- ip VARCHAR(40),
- server VARCHAR(100),
- identified INTEGER,
- ctcpversion VARCHAR(100),
- ctcptime VARCHAR(100),
+ captcha INTEGER
+);
+CREATE TABLE shell (
+ id VARCHAR(100), -- user@domain.com, for single sign on
+ ircid INTEGER,
+ wwwid INTEGER,
+ smtpid INTEGER,
+ username VARCHAR(32),
+ email VARCHAR(100),
+ password VARCHAR(100),
localtime VARCHAR(100),
- oper INTEGER,
- idle INTEGER,
- ssl INTEGER,
- epochtime INTEGER,
- captcha INTEGER,
- chans VARCHAR(100),
- date VARCHAR(100)
+ captcha INTEGER
);
CREATE TABLE www (
id INTEGER PRIMARY KEY,
@@ -46,13 +45,9 @@ CREATE TABLE www (
);
CREATE TABLE irc (
id INTEGER PRIMARY KEY,
- uid VARCHAR(100),
- vhost VARCHAR(100),
- username VARCHAR(32),
- ident VARCHAR(32),
+ hostmask VARCHAR(100),
+ nick VARCHAR(32),
realname VARCHAR(100),
- email VARCHAR(100),
- password VARCHAR(100),
ip VARCHAR(40),
server VARCHAR(100),
identified INTEGER,
@@ -63,8 +58,7 @@ CREATE TABLE irc (
idle INTEGER,
ssl INTEGER,
epochtime INTEGER,
- captcha INTEGER,
- chans VARCHAR(100),
+ chans VARCHAR(200),
date VARCHAR(100)
);
CREATE TABLE smtp (