Commit Diff
Diff:
6f7e337f505b89aa5e02fa8133eb9f443465fe83
817a3de15f20415ccc796cde724c24f5de6d442c
Commit:
817a3de15f20415ccc796cde724c24f5de6d442c
Tree:
fed627e704c57e4b27886c124e2c257cf23dbd47
Author:
jrmu <jrmu@lecturify.com>
Committer:
jrmu <jrmu@lecturify.com>
Date:
Wed Sep 16 06:59:03 2020 UTC
Message:
Added dns subroutines
blob - bd35192cfe3950f08929080d2f0d712cf393506b
blob + 2ba8ad4a955f4fcc3b25df011c8bf05b3bd554de
--- botnow.pl
+++ botnow.pl
@@ -41,6 +41,9 @@ my $zonedir = "/var/nsd/zones/master/";
# rDNS keys from Stallion in BuyVM
my ($key, $hash) = ("ABCDE-FGHIJ-KLMNO", "ABCDEFGHIJKLMNOPQRST");
+# ZNC install directory
+my $zncdir = "/home/znc/home/znc/";
+
# Network Interface Config File
my $hostnameif = "/etc/hostname.vio0";
@@ -82,6 +85,7 @@ my $sysname = "botnow"; # system username
my $wwwpath = "/var/www/htdocs/botnow"; # Web folder path
my $ipv6path = "ipv6s"; # ipv6 file path
my $database = "/var/www/botnow/"; # database path
+my $znclog = "$zncdir/.znc/moddata/adminlog/znc.log"; # znc.log path
unveil("./", "r") or die "Unable to unveil $!";
unveil("$ipv6path", "rwc") or die "Unable to unveil $!";
@@ -105,9 +109,15 @@ unveil("/usr/bin/doas", "rx") or die "Unable to unveil
#dependencies for encrypt
unveil("/usr/bin/encrypt", "rx") or die "Unable to unveil $!";
-#dependencies for blowfish
-#unveil("./blowfish.o", "rx") or die "Unable to unveil $!";
+#znc.log file
+unveil("$znclog", "r") or die "Unable to unveil $!";
+#dependencies for dig
+#unveil("/usr/bin/dig", "rx") or die "Unable to unveil $!";
+
+#dependencies for host
+unveil("/usr/bin/host", "rx") or die "Unable to unveil $!";
+
unveil() or die "Unable to lock unveil $!";
#dns and inet for sockets, proc and exec for figlet
@@ -122,6 +132,7 @@ my @months = qw( Jan Feb Mar Apr May Jun Jul Aug Sep O
my @days = qw(Sun Mon Tue Wed Thu Fri Sat Sun);
my @chans = split /,/m, $chans;
my @teamchans;
+my @logs;
if (defined($teamchans)) { @teamchans = split /,/m, $teamchans; }
# Load list of networks
@@ -375,7 +386,7 @@ sub parseserver {
# print "$server $code $reply\r\n";
} elsif ($code =~ /^464$/) { # Invalid password for oper
foreach my $chan (@teamchans) {
- sendmsg($bot, $chan, "ERROR: $nick oper password failed, unable to get IP addresses\r\n");
+ sendmsg($bot, $chan, "ERROR: $nick oper password failed; the bot will be unable to view uncloaked IP addresses\r\n");
}
} elsif ($code =~ /^477$/) { # Can't join channel
foreach my $chan (@teamchans) {
@@ -716,6 +727,56 @@ EOF
sendmsg($bot, $sender, $terms);
sendteam($bot->{name}, "Help *$sender* on ".$bot->{name});
}
+ } elsif ($reply =~ /^!linesmatching ([-_()|0-9A-Za-z:\.?*]{3,})/) {
+ my $pattern = $1; # arbitrary pattern
+ if ($staff !~ /$sender/) { return; }
+ my @lines = linesmatching($pattern);
+ foreach my $l (@lines) { print "$l\n"; }
+ } elsif ($reply =~ /^!usersmatching ([0-9A-Fa-f:\.,]{3,})/) {
+ my $ips = $1; # comma-separated list of IPs
+ if ($staff !~ /$sender/) { return; }
+ sendmsg($bot, $sender, usersmatching($ips));
+ } elsif ($reply =~ /^!ipsmatching ([0-9A-Za-z_-]{3,})/) {
+ my $usernames = $1; # comma-separated list of usernames
+ if ($staff !~ /$sender/) { return; }
+ sendmsg($bot, $sender, ipsmatching($usernames));
+ } elsif ($reply =~ /^!host ([-0-9A-Za-z:\.]{3,})/) {
+ my $name = $1;
+ if ($staff !~ /$sender/) { return; }
+ sendmsg($bot, $sender, host($name));
+ } elsif ($reply =~ /^!setrdns\s+([0-9A-Fa-f:\.]{3,})\s+([-0-9A-Za-z\.]+)/) {
+ my ($ip, $hostname) = ($1, $2);
+ if ($staff !~ /$sender/) { return; }
+ if (setrdns($ip, $hostname)) {
+ sendteam("", "$hostname set to $ip");
+ } else {
+ sendteam("", "Error: failed to set rDNS");
+ }
+ } elsif ($reply =~ /^!delrdns\s+([0-9A-Fa-f:\.]{3,})/) {
+ my $ip = $1;
+ if ($staff !~ /$sender/) { return; }
+ my $hostname = "notset";
+ if (setrdns($ip, $hostname)) {
+ sendteam("", "$ip rDNS deleted");
+ } else {
+ sendteam("", "Error: failed to set rDNS");
+ }
+ } elsif ($reply =~ /^!setdns\s+([-0-9A-Za-z\.]+)\s+([0-9A-Fa-f:\.]+)/) {
+ my ($hostname, $ip) = ($1, $2);
+ if ($staff !~ /$sender/) { return; }
+ if (setdns($hostname, $ip)) {
+ sendteam("", "$hostname set to $ip");
+ } else {
+ sendteam("", "Error: failed to set DNS");
+ }
+ } elsif ($reply =~ /^!deldns\s+([-0-9A-Za-z\.]+)/) {
+ my $hostname = $1;
+ if ($staff !~ /$sender/) { return; }
+ if (deldns($hostname)) {
+ sendteam("", "$hostname deleted");
+ } else {
+ sendteam("", "Error: failed to delete DNS records");
+ }
} elsif ($target !~ /^$nick.?/) {
# print "$hostmask: $target $reply\r\n";
} elsif (!defined(getkeyval($hostmask, "num"))) {
@@ -730,7 +791,7 @@ EOF
return;
} else {
setkeyval($hostmask, "terms", "no");
- sendmsg($bot, $sender, "Sorry. Contact staff or type !bnc to try again.");
+ sendmsg($bot, $sender, "Sorry, command not understood. Type !help or contact staff.");
}
} elsif (!defined(getkeyval($hostmask, "captcha"))) {
if ($reply =~ /^([0-9]+)$/ && $reply == getkeyval($hostmask, "num")) {
@@ -775,7 +836,10 @@ EOF
} else {
sendmsg($bot, $sender, "Invalid email. New email:");
}
- } elsif ($reply =~ /^!deluser (.*)$/i) { # Hidden functionality
+
+### Hidden functionality ###
+
+ } elsif ($reply =~ /^!deluser (.*)$/i) {
my $user = $1;
if ($staff !~ /$sender/) {
return;
@@ -788,14 +852,6 @@ EOF
print $socket "PRIVMSG *controlpanel :deluser cloneuser\r\n";
sleep 5;
print $socket "PRIVMSG *controlpanel :get Nick cloneuser\r\n";
- } elsif ($reply =~ /^!identify\s*(.*)?\s+(.*)$/i) {
- my $hash = getkeyval($hostmask, "password");
- #print "result = ".`./blowfish.o $2 '$hash'`;
-# if(system("./blowfish.o $2 '$hash' > /dev/null")) {
-# print "login failed\r\n";
-# } else {
-# print "logged in\r\n";
-# }
} elsif ($reply =~ /^!dns\s+([-.0-9a-z]+)\s+([:0-9a-f]+)/i) {
my ($fqdn, $ip6) = ($1, $2);
if ($staff !~ /$sender/) {
@@ -1003,4 +1059,167 @@ sub nextdns {
return "$username.$hostname";
}
return;
+}
+
+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 linesmatching {
+ my ($pattern) = @_;
+ if (!@logs) { loadlog(); }
+ return grep(/$pattern/, @logs);
+}
+
+# given a comma-separated list of IPs, return all matching users
+sub usersmatching {
+ my ($ips) = @_;
+ my @ips = split /,/m, $ips;
+ my $pattern = "(".join('|', @ips).")";
+ if (!@logs) { loadlog(); }
+ my @matches = grep(/$pattern/, @logs);
+ my @nicks;
+ foreach my $match (@matches) {
+ if ($match =~ /^\[\d{4}-\d\d-\d\d \d\d:\d\d:\d\d\] \[([^]\/]+)(\/[^]]+)?\].*/) {
+ push(@nicks, $1);
+ }
+ }
+ my @sorted = sort @nicks;
+ my @results = do { my %seen; grep { !$seen{$_}++ } @sorted }; # uniq
+ return join(',', @results);
+}
+
+# given a username, return all matching ips
+sub ipsmatching {
+ my ($usernames) = @_;
+ my @usernames = split /,/m, $usernames;
+ my $pattern = "(".join('|', @usernames).")";
+ if (!@logs) { loadlog(); }
+ my @matches = grep(/$pattern.*to ZNC/, @logs);
+ my @ips;
+ foreach my $match (@matches) {
+ if ($match =~ /^\[\d{4}-\d\d-\d\d \d\d:\d\d:\d\d\] \[([^]\/]+)(\/[^]]+)?\] connected to ZNC from (.*)/) {
+ push(@ips, $3);
+ }
+ }
+ my @sorted = sort @ips;
+ my @results = do { my %seen; grep { !$seen{$_}++ } @sorted }; # uniq
+ return join(',', @results);
+}
+
+# given hostname, return IP address; or given IP address, return hostname
+sub host {
+ my ($name) = @_;
+ my @matches;
+ my @lines = split /\n/m, `host $name`;
+ if ($name =~ /^[0-9\.]+$/ or $name =~ /^$/) { # IP address
+ foreach my $line (@lines) {
+ if ($line =~ /([\d\.]+).(in-addr|ip6).arpa domain name pointer (.*)/) {
+ push(@matches, $3);
+ }
+ }
+ } else { # hostname
+ foreach my $line (@lines) {
+ if ($line =~ /$name has (IPv6 )?address ([0-9a-fA-F\.:]+)/) {
+ push(@matches, $2);
+ }
+ }
+ }
+ return join(',', @matches);
+}
+
+#sub getrdns {
+# my ($ip) = @_;
+# my $lookup = `dig -x $ip`;
+# my $hostname;
+# if ($lookup =~ /;; ANSWER SECTION:\n.*\s+PTR\s+(.*)/m) {
+# return $1;
+# } else {
+# return "not found";
+# }
+#}
+
+# returns true upon success, false upon failure
+sub setrdns {
+ my ($ip, $hostname) = @_;
+ my $stdout = `curl -d \"key=$key&hash=$hash&action=rdns&ip=$ip&rdns=$hostname\" https://manage.buyvm.net/api/client/command.php`;
+ if ($stdout !~ /success/) {
+ return 0;
+ }
+ return 1;
+}
+
+# returns true upon success, false upon failure
+sub setdns {
+ my ($domain, $ip) = @_;
+ my $filename = "$zonedir/$hostname";
+ my $subdomain;
+ if ($domain =~ /^([a-zA-Z][-\.a-zA-Z0-9]+)\.$hostname$/) {
+ $subdomain = $1;
+ } else {
+ return 0;
+ }
+ my ($line, $lines);
+ open($fh, '+<', "$filename") or die "Could not read file '$filename' $!";
+ while(my $line = <$fh>){
+# increment the zone's serial number
+ if ($line =~ /([0-9]{10})( [0-9]+ [0-9]+ [0-9]+ [0-9]+ \).*)/) {
+ my $num = $1+1;
+ $line = " $num$2\n";
+ }
+ $lines .= $line;
+ }
+ close $fh;
+ if ($ip =~ /^([0-9\.]+)$/) { # if IPv4
+ $lines .= "$subdomain 3600 IN A $ip\n";
+ } else { # if IPv6
+ $lines .= "$subdomain 3600 IN AAAA $ip\n";
+ }
+ open($fh, '>', "$filename.bak") or die "Could not write file '$filename.bak' $!";
+ print $fh $lines;
+ close $fh;
+ copy "$filename.bak", $filename;
+ if (system("doas -u _nsd nsd-control reload")) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+sub deldns {
+ my ($domain) = @_;
+ my $filename = "$zonedir/$hostname";
+ my $subdomain;
+ if ($domain =~ /^([a-zA-Z][-\.a-zA-Z0-9]+)\.$hostname$/) {
+ $subdomain = $1;
+ } else {
+ sendteam("", "Error: not authoritative");
+ return 0;
+ }
+ my ($line, $lines);
+ open($fh, '+<', "$filename") or die "Could not read file '$filename' $!";
+ while(my $line = <$fh>){
+# increment the zone's serial number
+ if ($line =~ /([0-9]{10})( [0-9]+ [0-9]+ [0-9]+ [0-9]+ \).*)/) {
+ my $num = $1+1;
+ $line = " $num$2\n";
+ } elsif ($line =~ /$subdomain\s*3600\s*IN/) {
+ next;
+ } elsif ($line =~ /$subdomain\s*3600\s*IN/) {
+ next;
+ }
+ $lines .= $line;
+ }
+ close $fh;
+ open($fh, '>', "$filename.bak") or die "Could not write file '$filename.bak' $!";
+ print $fh $lines;
+ close $fh;
+ copy "$filename.bak", $filename;
+ if (system("doas -u _nsd nsd-control reload")) {
+ return 0;
+ } else {
+ return 1;
+ }
}
blob - 868b9f54a002f70a51de6f1c9cdcff8e676c9f8e
blob + ede77ec7e838ad079c5655994db4afe91da18e6f
--- makefile
+++ makefile
@@ -3,8 +3,10 @@ HOMEDIR="/home/botnow"
HTDOCS="/var/www/htdocs/botnow"
DATABASE="/var/www/botnow/"
ZONES="/var/nsd/zones/master/"
+ZNCUSER="znc"
+ZNCDIR="/home/znc/home/znc/"
-botnow: figlet php znc
+botnow: figlet php
useradd -m -g =uid -c ${USERNAME} -d ${HOMEDIR} -s /bin/ksh ${USERNAME}
mkdir ${DATABASE}
touch ${DATABASE}/www
@@ -22,6 +24,9 @@ botnow: figlet php znc
cp LICENSE README botnow.pl makefile networks register.php words ${HOMEDIR}/
chown -R ${USERNAME}:${USERNAME} ${HOMEDIR}
chmod u+x ${HOMEDIR}/botnow.pl
+ chown -R ${ZNCUSER}:daemon ${ZNCDIR}
+ chmod -R ug+r ${ZNCDIR}
+ find ${ZNCDIR} -type d -exec chmod ug+rx {} +
echo "Installation complete. To run botnow, type $ ./botnow.pl"
figlet:
pkg_add figlet-2.2.5
@@ -33,5 +38,6 @@ php:
rcctl enable httpd
rcctl restart httpd
-znc:
- echo Foo
+sqlite:
+ pkg_add p5-DBD-SQLite
+ pkg_add sqlite3
blob - 6e7549f6bf1a6c8329b3be2b0041fbff9ce18e87
blob + e7f1ae01a380a3699e0b061a1dcde3cdae779170
--- networks
+++ networks
@@ -109,8 +109,8 @@ evolu irc.evolu.net ~6697
exchat irc.exchat.net ~6697
explosionirc irc.explosionirc.net 6667
forumcerdas irc.forumcerdas.net ~6697
-#freenode chat.ipv6.freenode.net +6697
freenode ipv6.chat.freenode.net +6697
+#freenode chat.ipv6.freenode.net +6697
freeunibg irc.freeunibg.eu 6667
freshchat irc.freshchat.org +6697
gamesurge irc.gamesurge.net 6667