Commit Diff
Diff:
c7c613d21716617e05b0eec44970b67a6a44a2c4
7435271743bcc02de7ae03458bec65305bc4f974
Commit:
7435271743bcc02de7ae03458bec65305bc4f974
Tree:
ab2b83ad7d699b5705716ed5359f74a780630d67
Author:
jrmu <jrmu@ircnow.org>
Committer:
jrmu <jrmu@ircnow.org>
Date:
Tue Oct 27 13:48:35 2020 UTC
Message:
Added support for shell accounts
blob - ea47d84b8c32ca18588943332c7d85e9b7a62eea
blob + c09df7abc79b5e393d4d22f936b7885d52eb88f2
--- BNC.pm
+++ BNC.pm
@@ -221,6 +221,7 @@ sub mbnc {
SQLite::set("bnc", "ircid", $ircid, "email", $email);
SQLite::set("bnc", "ircid", $ircid, "captcha", $captcha);
main::whois($bot->{sock}, $nick);
+ main::ctcp($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 !bnc captcha <text>");
blob - 14a705cc742620462ac7c280c23cf288198d71b5
blob + 4fb614eaa509862f21324fca8ea95f713cbd981d
--- Hash.pm
+++ Hash.pm
@@ -28,5 +28,16 @@ sub newpass {
}
return $pass;
}
+#dependencies for blowfish
+#unveil("./blowfish.o", "rx") or die "Unable to unveil $!";
+# } 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";
+# }
+
1; # MUST BE LAST STATEMENT IN FILE
blob - 2e744ee9dd4100c7d4b9a996075c6d131c759add
blob + 787df431680b37e12c699719f8197f33ee9a8a62
--- Help.pm
+++ Help.pm
@@ -43,7 +43,12 @@ To recreate cloneuser, type !bnc cloneuser
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>
+To delete a shell account, type !shell delete <username>
+To verify a captcha, type !shell captcha <username>
EOF
+#To get a list of usernames that match IPs, type !shell regex ips <ips>
+#To get a list of IPs that match usernames, type !shell regex users <usernames>
+#To regex search znc.log and output to the terminal, type !shell regex <regex>
}
if (@args == 2) {
($chan, $text) = ($args[0], $args[1]);
blob - dac48eecbb00eba2a87fd094d98cf0225f4551f1
blob + 44e7c746404c2f3bfd6ca124450d9b8d790f685b
--- Mail.pm
+++ Mail.pm
@@ -88,21 +88,6 @@ return "true";
#close $fh;
#}
#
-# if ($reply =~ /^!email (.*) ([-_0-9a-zA-Z]+)$/i) {
-# my $ircnick = $1;
-# my $newnick = $2;
-# if ($staff !~ /$sender/) {
-# return;
-# }
-# my $password = newpass();
-# createmail($password, $newnick);
-# sendmsg($bot, $sender, "email created for $newnick");
-#my $msg = <<"EOF";
-#Your email account has been created! Username: $newnick with password: $password
-#Our official support channel is #email. To connect, please follow these instructions: https://ircnow.org/kb/doku.php?id=email:email .
-#EOF
-# sendmsg($bot, $ircnick, $msg);
-# }
#sub createmail {
# my ($password, $username) = @_;
blob - f3719a4f4c4bdff09ade56ae521a742e9893e7be
blob + b405c88d9bfa395969132d2a16c6951e3ba01540
--- README
+++ README
@@ -21,6 +21,7 @@ $ cd botnow
$ doas make
$ doas su botnow
$ cd /home/botnow/
+$ cp botnow.conf.example botnow.conf
Fill the file ipv6s with all the unused IPv6 addresses available on your server.
@@ -50,6 +51,7 @@ $ doas make -i
### Changelog ###
+Version 0.07: Added support for requesting shell accounts
Version 0.06: Refactored code to be modular
Version 0.05: Refactored conf file out of the script and supplied sensible defaults
Version 0.04: Switched from flatfiles to sqlite for user metadata
blob - 17661f53c256f6eba2c8f884521d410c8b9cc748
blob + 53c524758e1e96c1a8aa01a66760bdae51ff98e6
--- Shell.pm
+++ Shell.pm
@@ -24,6 +24,8 @@ my $time = "600";
my $mailfrom;
my $mailname;
my $passpath = "/etc/passwd";
+my $httpdconfpath = "/etc/httpd.conf";
+my $acmeconfpath = "/etc/acme-client.conf";
sub init {
$chans = $main::conf{chans};
@@ -40,6 +42,17 @@ sub init {
unveil("/usr/libexec/ld.so", "r") or die "Unable to unveil $!";
#dependencies for shell account
unveil($passpath, "r") or die "Unable to unveil $!";
+ unveil($httpdconfpath, "rwxc") or die "Unable to unveil $!";
+ unveil($acmeconfpath, "rwxc") or die "Unable to unveil $!";
+ unveil("/usr/sbin/chown", "rx") or die "Unable to unveil $!";
+ unveil("/bin/chmod", "rx") or die "Unable to unveil $!";
+ unveil("/usr/sbin/groupadd", "rx") or die "Unable to unveil $!";
+ unveil("/usr/sbin/useradd", "rx") or die "Unable to unveil $!";
+ unveil("/usr/sbin/groupdel", "rx") or die "Unable to unveil $!";
+ unveil("/usr/sbin/userdel", "rx") or die "Unable to unveil $!";
+ unveil("/bin/mkdir", "rx") or die "Unable to unveil $!";
+ unveil("/bin/ln", "rx") or die "Unable to unveil $!";
+ unveil("/home/", "rwxc") or die "Unable to unveil $!";
main::cbind("pub", "-", "shell", \&mshell);
main::cbind("msg", "-", "shell", \&mshell);
}
@@ -66,6 +79,7 @@ sub mshell {
my $username = $1;
if (SQLite::deleterows("shell", "username", $username)) {
# TODO delete shell
+ deleteshell($bot, $username);
foreach my $chan (@teamchans) {
main::putserv($bot, "PRIVMSG $chan :$username deleted");
}
@@ -116,6 +130,7 @@ sub mshell {
my @matches = grep(/^$username$/i, @users);
if (scalar(@matches) > 0) {
main::putserv($bot, "PRIVMSG $nick :Sorry, username taken. Please choose another username, or contact staff for help.");
+ return;
}
# my $captcha = join'', map +(0..9,'a'..'z','A'..'Z')[rand(10+26*2)], 1..4;
my $captcha = int(rand(999));
@@ -128,6 +143,7 @@ sub mshell {
SQLite::set("shell", "ircid", $ircid, "email", $email);
SQLite::set("shell", "ircid", $ircid, "captcha", $captcha);
main::whois($bot->{sock}, $nick);
+ main::ctcp($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>");
@@ -232,7 +248,88 @@ EOF
sub createshell {
my ($bot, $username, $password, $bindhost) = @_;
my $netname = $bot->{name};
- `doas sh ./shell $username $password`;
+ system "doas groupadd $username";
+ system "doas adduser -batch $username $username $username `encrypt $password`";
+ system "doas chmod 700 /home/$username /home/$username/.ssh";
+ system "doas chmod 600 /home/$username/{.Xdefaults,.cshrc,.cvsrc,.login,.mailrc,.profile}";
+ system "doas mkdir /var/www/htdocs/$username";
+ system "doas ln -s /var/www/htdocs/$username /home/$username/htdocs";
+ system "doas chown -R $username:www /var/www/htdocs/$username /home/$username/htdocs";
+ system "doas chmod -R o-rx /var/www/htdocs/$username /home/$username/htdocs";
+ system "doas chmod -R g+rwx /var/www/htdocs/$username /home/$username/htdocs";
+ my $block = <<"EOF";
+server "$username.$hostname" {
+ listen on * tls port 443
+ tls {
+ certificate "/etc/ssl/$username.$hostname.fullchain.pem"
+ key "/etc/ssl/private/$username.$hostname.key"
+ }
+ location "/.well-known/acme-challenge/*" {
+ root "/acme"
+ }
+ location "*.php" {
+ fastcgi socket "/run/php-fpm.sock"
+ }
+ root "/htdocs/$username"
+}
+EOF
+ main::appendfile($httpdconfpath, $block);
+ $block = <<"EOF";
+domain "$username.$hostname" {
+ domain key "/etc/ssl/private/$username.$hostname.key"
+ domain full chain certificate "/etc/ssl/$username.$hostname.fullchain.pem"
+ sign with letsencrypt
+}
+EOF
+ main::appendfile($acmeconfpath, $block);
+#edquota $username
+ return 1;
+}
+
+sub deleteshell {
+ my ($bot, $username, $bindhost) = @_;
+ my $netname = $bot->{name};
+ system "doas groupdel $username";
+ system "doas userdel $username";
+ my $httpdconf = main::readstr($httpdconfpath);
+ my $block = <<"EOF";
+server "$username.$hostname" {
+ listen on * tls port 443
+ tls {
+ certificate "/etc/ssl/$username.$hostname.fullchain.pem"
+ key "/etc/ssl/private/$username.$hostname.key"
+ }
+ location "/.well-known/acme-challenge/*" {
+ root "/acme"
+ }
+ location "*.php" {
+ fastcgi socket "/run/php-fpm.sock"
+ }
+ root "/htdocs/$username"
+}
+EOF
+ $block =~ s/{/\\{/gm;
+ $block =~ s/}/\\}/gm;
+ $block =~ s/\./\\./gm;
+ $block =~ s/\*/\\*/gm;
+ $httpdconf =~ s{$block}{}gm;
+ print $httpdconf;
+ main::writefile($httpdconfpath, $httpdconf);
+
+ my $acmeconf = main::readstr($acmeconfpath);
+ $block = <<"EOF";
+domain "$username.$hostname" {
+ domain key "/etc/ssl/private/$username.$hostname.key"
+ domain full chain certificate "/etc/ssl/$username.$hostname.fullchain.pem"
+ sign with letsencrypt
+}
+EOF
+ $block =~ s/{/\\{/gm;
+ $block =~ s/}/\\}/gm;
+ $block =~ s/\./\\./gm;
+ $block =~ s/\*/\\*/gm;
+ $acmeconf =~ s{$block}{}gm;
+ main::writefile($acmeconfpath, $acmeconf);
return 1;
}
blob - 87767b047c025a8b27374b06946e51c9352befe1
blob + c85d654700ef0e5057cc94a8948f6f89b69ab6cd
--- botnow.pl
+++ botnow.pl
@@ -159,6 +159,14 @@ sub writefile {
close $fh;
}
+# Append str to filename
+sub appendfile {
+ my ($filename, $str) = @_;
+ open(my $fh, '>>', "$filename") or die "Could not append to $filename";
+ print $fh $str;
+ close $fh;
+}
+
# Return list of networks from filename
# To add multiple servers for a single network, simply create a new entry with
# the same net name; znc ignores addnetwork commands when a network already exists
@@ -311,7 +319,7 @@ while(my @ready = $sel->can_read) {
my ($key, $val) = ($1, $2);
my $id = SQLite::id("irc", "nick", $nick, $time);
SQLite::set("irc", "id", $id, "ctcp".lc($key), $val);
- SQLite::set("irc", "id", $id, "localtime", gettime());
+ SQLite::set("irc", "id", $id, "localtime", time());
}
}
debug(ALL, "$nick!$host NOTICE $target $text");
blob - 89d7d761481ea78e31572163a841e71e2d7ad6c8
blob + 130008e30faaff5537075a20ba8e95f5c2f0f0c5
--- makefile
+++ makefile
@@ -5,6 +5,8 @@ DATABASE="/var/www/botnow/"
ZONES="/var/nsd/zones/master/"
ZNCUSER="znc"
ZNCDIR="/home/znc/home/znc/"
+HTTPDCONF="/etc/httpd.conf"
+ACMECONF="/etc/acme-client.conf"
botnow: figlet php sqlite
useradd -m -g =uid -c ${USERNAME} -d ${HOMEDIR} -s /bin/ksh ${USERNAME}
@@ -17,9 +19,11 @@ botnow: figlet php sqlite
cp register.php ${HTDOCS}/
chown -R www:daemon ${HTDOCS}
usermod -G daemon ${USERNAME}
+ usermod -G wheel ${USERNAME}
chown -R _nsd:daemon ${ZONES}
chmod ug+rwx ${ZONES}
chmod ug+rw ${ZONES}/*
+ chmod g+rw ${HTTPDCONF} ${ACMECONF}
echo "permit nopass ${USERNAME} as _nsd cmd nsd-control" >> /etc/doas.conf
cp register.php ${HTDOCS}/
cp LICENSE README botnow.pl botnow.conf.example BNC.pm DNS.pm Mail.pm SQLite.pm Shell.pm VPN.pm Login.pm WWW.pm table.sql Hash.pm Help.pm makefile networks register.php words shell ${HOMEDIR}/