Blame
Date:
Sun Oct 8 22:28:02 2023 UTC
Message:
Now prevents creating accounts that exist in database with a password
001
2021-12-17
jrmu
#!/usr/bin/perl
002
2021-12-17
jrmu
003
2021-12-17
jrmu
package Mail;
004
2021-12-17
jrmu
005
2021-12-17
jrmu
use strict;
006
2021-12-17
jrmu
use warnings;
007
2021-12-17
jrmu
use OpenBSD::Pledge;
008
2021-12-17
jrmu
use OpenBSD::Unveil;
009
2023-03-06
jrmu
use File::Copy qw(copy);
010
2021-12-17
jrmu
use MIME::Base64;
011
2021-12-17
jrmu
use Digest::SHA qw(sha256_hex);
012
2021-12-17
jrmu
013
2021-12-17
jrmu
my %conf = %main::conf;
014
2023-03-06
jrmu
my $chans = $conf{chans};
015
2021-12-17
jrmu
my $staff = $conf{staff};
016
2023-03-07
jrmu
my $mailhostname = $conf{mailhostname};
017
2021-12-17
jrmu
my $mailfrom = $conf{mailfrom};
018
2021-12-17
jrmu
my $mailname = $conf{mailname};
019
2023-03-06
jrmu
my $imapport = $conf{imapport};
020
2023-03-06
jrmu
my $smtpport = $conf{smtpport};
021
2023-03-06
jrmu
my $teamchans = $conf{teamchans};
022
2023-03-06
jrmu
my @teamchans = split /[,\s]+/m, $teamchans;
023
2023-03-07
jrmu
my $webmail = $conf{webmail};
024
2023-03-06
jrmu
my $approval = $conf{approval};
025
2023-03-06
jrmu
my $expires = $conf{expires};
026
2023-03-06
jrmu
my $passwdpath = "/etc/mail/passwd";
027
2023-03-06
jrmu
my $virtualspath = "/etc/mail/virtuals";
028
2023-03-06
jrmu
my $senderspath = "/etc/mail/users";
029
2023-03-06
jrmu
my @users;
030
2023-03-06
jrmu
031
2023-03-06
jrmu
main::cbind("msg", "-", "mail", \&mmail);
032
2021-12-17
jrmu
033
2021-12-17
jrmu
sub init {
034
2021-12-17
jrmu
#dependencies for encrypt
035
2021-12-17
jrmu
unveil("/usr/bin/encrypt", "rx") or die "Unable to unveil $!";
036
2021-12-17
jrmu
#dependencies for mail
037
2021-12-17
jrmu
unveil("/usr/sbin/sendmail", "rx") or die "Unable to unveil $!";
038
2023-03-06
jrmu
unveil($passwdpath, "rwc") or die "Unable to unveil $!";
039
2023-03-06
jrmu
unveil($virtualspath, "rwc") or die "Unable to unveil $!";
040
2023-03-06
jrmu
unveil($senderspath, "rwc") or die "Unable to unveil $!";
041
2023-03-06
jrmu
unveil("$passwdpath.bak", "rwc") or die "Unable to unveil $!";
042
2023-03-06
jrmu
unveil("$virtualspath.bak", "rwc") or die "Unable to unveil $!";
043
2023-03-06
jrmu
unveil("$senderspath.bak", "rwc") or die "Unable to unveil $!";
044
2021-12-17
jrmu
unveil("/usr/lib/libutil.so.13.1", "r") or die "Unable to unveil $!";
045
2021-12-17
jrmu
unveil("/bin/sh", "rx") or die "Unable to unveil $!";
046
2021-12-17
jrmu
}
047
2023-03-05
jrmu
048
2021-12-17
jrmu
sub mmail {
049
2023-03-05
jrmu
my ($bot, $nick, $host, $hand, @args) = @_;
050
2023-03-05
jrmu
my ($chan, $text);
051
2023-03-05
jrmu
if (@args == 2) {
052
2023-03-05
jrmu
($chan, $text) = ($args[0], $args[1]);
053
2023-03-05
jrmu
} else { $text = $args[0]; }
054
2023-03-05
jrmu
my $hostmask = "$nick!$host";
055
2023-03-05
jrmu
if (defined($chan) && $chans =~ /$chan/) {
056
2023-03-05
jrmu
main::putserv($bot, "PRIVMSG $chan :$nick: Please check private message");
057
2023-03-05
jrmu
}
058
2023-03-05
jrmu
if ($text =~ /^$/) {
059
2023-03-05
jrmu
main::putserv($bot, "PRIVMSG $nick :Type !help for new instructions");
060
2023-03-05
jrmu
foreach my $chan (@teamchans) {
061
2023-03-06
jrmu
main::putservlocalnet($bot, "PRIVMSG $chan :$staff: Help *$nick* on network ".$bot->{name}." with mail");
062
2021-12-17
jrmu
}
063
2023-03-05
jrmu
return;
064
2023-03-05
jrmu
} elsif (main::isstaff($bot, $nick) && $text =~ /^delete\s+([[:ascii:]]+)/) {
065
2023-03-05
jrmu
my $username = $1;
066
2023-03-05
jrmu
if (SQLite::deleterows("mail", "username", $username)) {
067
2023-03-05
jrmu
deletemail($username);
068
2023-03-05
jrmu
foreach my $chan (@teamchans) {
069
2023-03-05
jrmu
main::putserv($bot, "PRIVMSG $chan :$username email deleted");
070
2023-03-05
jrmu
}
071
2023-03-05
jrmu
}
072
2023-03-05
jrmu
return;
073
2023-03-05
jrmu
} elsif (main::isstaff($bot, $nick) && $text =~ /^approve\s+([[:ascii:]]+)/) {
074
2023-03-05
jrmu
my $username = $1;
075
2023-03-06
jrmu
my @passwd = main::readarray($passwdpath);
076
2023-03-06
jrmu
foreach my $line (@passwd) {
077
2023-03-07
jrmu
$line =~ s/^#(${username}\@${mailhostname}.*)/$1/;
078
2023-03-06
jrmu
}
079
2023-03-06
jrmu
# trailing newline necessary
080
2023-03-06
jrmu
`doas touch $passwdpath.bak`;
081
2023-03-06
jrmu
`doas chmod g+w $passwdpath.bak`;
082
2023-03-06
jrmu
main::writefile("$passwdpath.bak", join("\n", @passwd)."\n");
083
2023-03-06
jrmu
copy "${passwdpath}.bak", $passwdpath;
084
2023-03-06
jrmu
085
2023-03-05
jrmu
foreach my $chan (@teamchans) {
086
2023-03-05
jrmu
main::putserv($bot, "PRIVMSG $chan :$username mail approved");
087
2023-03-05
jrmu
}
088
2023-03-05
jrmu
return;
089
2021-12-17
jrmu
}
090
2023-03-05
jrmu
### Check duplicate hostmasks ###
091
2023-03-05
jrmu
my @rows = SQLite::selectrows("irc", "hostmask", $hostmask);
092
2023-03-05
jrmu
foreach my $row (@rows) {
093
2023-03-05
jrmu
my $password = SQLite::get("mail", "ircid", $row->{id}, "password");
094
2023-03-05
jrmu
if (defined($password)) {
095
2023-03-05
jrmu
main::putserv($bot, "PRIVMSG $nick :Sorry, only one account per person. Please contact staff if you need help.");
096
2023-03-05
jrmu
return;
097
2023-03-05
jrmu
}
098
2023-03-05
jrmu
}
099
2023-03-05
jrmu
100
2023-03-05
jrmu
if ($text =~ /^captcha\s+([[:alnum:]]+)/) {
101
2023-03-05
jrmu
my $text = $1;
102
2023-03-05
jrmu
# TODO avoid using host mask because cloaking can cause problems
103
2023-03-05
jrmu
my $ircid = SQLite::id("irc", "nick", $nick, $expires);
104
2023-03-05
jrmu
my $captcha = SQLite::get("mail", "ircid", $ircid, "captcha");
105
2023-03-05
jrmu
if ($text ne $captcha) {
106
2023-03-05
jrmu
main::putserv($bot, "PRIVMSG $nick :Wrong captcha. To get a new captcha, type !mail <username> <email>");
107
2023-03-05
jrmu
return;
108
2023-03-05
jrmu
}
109
2023-03-05
jrmu
my $pass = Hash::newpass();
110
2023-03-05
jrmu
chomp(my $encrypted = `encrypt $pass`);
111
2023-03-05
jrmu
my $username = SQLite::get("mail", "ircid", $ircid, "username");
112
2023-03-05
jrmu
my $email = SQLite::get("mail", "ircid", $ircid, "email");
113
2023-03-05
jrmu
my $hashirc = SQLite::get("irc", "id", $ircid, "hashid");
114
2023-03-05
jrmu
SQLite::set("mail", "ircid", $ircid, "password", $encrypted);
115
2023-03-05
jrmu
sleep(2);
116
2023-03-05
jrmu
createmail($pass, $username);
117
2023-03-05
jrmu
main::putserv($bot, "PRIVMSG $nick :Check your email!");
118
2023-03-06
jrmu
sleep(5);
119
2023-03-05
jrmu
mailmail($username, $pass, $email);
120
2023-03-07
jrmu
if ($approval) {
121
2023-03-06
jrmu
my @passwd = main::readarray($passwdpath);
122
2023-03-06
jrmu
foreach my $line (@passwd) {
123
2023-03-07
jrmu
$line =~ s/^(${username}\@${mailhostname}.*)/#$1/;
124
2023-03-06
jrmu
}
125
2023-03-06
jrmu
# trailing newline necessary
126
2023-03-06
jrmu
`doas touch $passwdpath.bak`;
127
2023-03-06
jrmu
`doas chmod g+w $passwdpath.bak`;
128
2023-03-06
jrmu
main::writefile("$passwdpath.bak", join("\n", @passwd)."\n");
129
2023-03-06
jrmu
copy "${passwdpath}.bak", $passwdpath;
130
2023-03-06
jrmu
131
2023-03-05
jrmu
main::putserv($bot, "PRIVMSG $nick :Your account has been created but must be manually approved by your admins ($staff) before it can be used.");
132
2023-03-05
jrmu
foreach my $chan (@teamchans) {
133
2023-03-05
jrmu
main::putservlocalnet($bot, "PRIVMSG $chan :$staff: $nick\'s account $username must be manually unblocked before it can be used.");
134
2023-03-05
jrmu
}
135
2023-03-05
jrmu
}
136
2023-03-05
jrmu
foreach my $chan (@teamchans) {
137
2023-03-07
jrmu
main::putservlocalnet($bot, "PRIVMSG $chan :$staff: $nick\'s mail registration of $username\@$mailhostname on $bot->{name} was successful, but you *must* help him to connect. Most users are unable to connect. Show him https://wiki.ircnow.org/?n=Email.Email");
138
2023-03-05
jrmu
}
139
2023-03-05
jrmu
#www($newnick, $reply, $password, "bouncer");
140
2023-03-05
jrmu
return;
141
2023-03-05
jrmu
} elsif ($text =~ /^([[:alnum:]]+)\s+([[:ascii:]]+)/) {
142
2023-03-05
jrmu
my ($username, $email) = ($1, $2);
143
2023-03-05
jrmu
my @userrows = SQLite::selectrows("mail", "username", $username);
144
2023-03-05
jrmu
foreach my $row (@userrows) {
145
2023-03-05
jrmu
my $password = SQLite::get("mail", "ircid", $row->{id}, "password");
146
2023-03-05
jrmu
if (defined($password)) {
147
2023-03-05
jrmu
main::putserv($bot, "PRIVMSG $nick :Sorry, only one account per person. Please contact staff if you need help.");
148
2023-03-05
jrmu
return;
149
2023-03-05
jrmu
}
150
2023-03-05
jrmu
}
151
2023-03-05
jrmu
my @emailrows = SQLite::selectrows("mail", "email", $email);
152
2023-03-05
jrmu
foreach my $row (@userrows) {
153
2023-03-05
jrmu
my $password = SQLite::get("mail", "ircid", $row->{id}, "password");
154
2023-03-05
jrmu
if (defined($password)) {
155
2023-03-05
jrmu
main::putserv($bot, "PRIVMSG $nick :Sorry, only one account per person. Please contact staff if you need help.");
156
2023-03-05
jrmu
return;
157
2023-03-05
jrmu
}
158
2023-03-05
jrmu
}
159
2023-03-05
jrmu
160
2023-03-05
jrmu
# my @users = treeget($znctree, "User", "Node");
161
2023-03-05
jrmu
foreach my $user (@users) {
162
2023-03-05
jrmu
if ($user eq $username) {
163
2023-03-05
jrmu
main::putserv($bot, "PRIVMSG $nick :Sorry, username taken. Please contact staff if you need help.");
164
2023-03-05
jrmu
return;
165
2023-03-05
jrmu
}
166
2023-03-05
jrmu
}
167
2023-03-05
jrmu
168
2023-03-05
jrmu
#my $captcha = join'', map +(0..9,'a'..'z','A'..'Z')[rand(10+26*2)], 1..4;
169
2023-03-05
jrmu
my $captcha = int(rand(999));
170
2023-03-05
jrmu
my $ircid = int(rand(9223372036854775807));
171
2023-03-05
jrmu
my $hashid = sha256_hex("$ircid");
172
2023-03-05
jrmu
SQLite::set("irc", "id", $ircid, "localtime", time());
173
2023-03-05
jrmu
SQLite::set("irc", "id", $ircid, "hashid", sha256_hex($ircid));
174
2023-03-05
jrmu
SQLite::set("irc", "id", $ircid, "date", main::date());
175
2023-03-05
jrmu
SQLite::set("irc", "id", $ircid, "hostmask", $hostmask);
176
2023-03-05
jrmu
SQLite::set("irc", "id", $ircid, "nick", $nick);
177
2023-03-05
jrmu
SQLite::set("mail", "ircid", $ircid, "username", $username);
178
2023-03-05
jrmu
SQLite::set("mail", "ircid", $ircid, "email", $email);
179
2023-03-05
jrmu
SQLite::set("mail", "ircid", $ircid, "captcha", $captcha);
180
2023-03-05
jrmu
SQLite::set("mail", "ircid", $ircid, "hashid", $hashid);
181
2023-08-01
jrmu
main::whois($bot, $nick);
182
2023-08-01
jrmu
main::ctcp($bot, $nick);
183
2023-03-05
jrmu
main::putserv($bot, "PRIVMSG $nick :".`figlet $captcha`);
184
2023-03-05
jrmu
#main::putserv($bot, "PRIVMSG $nick :https://$hostname/$hashid/captcha.png");
185
2023-03-05
jrmu
#main::putserv($bot, "PRIVMSG $nick :https://$hostname/register.php?hashirc=$hashid");
186
2023-03-05
jrmu
main::putserv($bot, "PRIVMSG $nick :Type !mail captcha <text>");
187
2023-03-05
jrmu
foreach my $chan (@teamchans) {
188
2023-03-05
jrmu
main::putservlocalnet($bot, "PRIVMSG $chan :$nick\'s on $bot->{name} mail captcha is $captcha");
189
2023-03-05
jrmu
}
190
2023-03-05
jrmu
} else {
191
2023-03-05
jrmu
main::putserv($bot, "PRIVMSG $nick :Invalid username or email. Type !mail <username> <email> to try again.");
192
2023-03-05
jrmu
foreach my $chan (@teamchans) {
193
2023-03-06
jrmu
main::putservlocalnet($bot, "PRIVMSG $chan :$staff: Help *$nick* on network ".$bot->{name}." with mail");
194
2023-03-05
jrmu
}
195
2023-03-05
jrmu
}
196
2021-12-17
jrmu
}
197
2021-12-17
jrmu
198
2023-03-05
jrmu
sub mailmail {
199
2023-03-05
jrmu
my( $username, $password, $email )=@_;
200
2023-03-06
jrmu
my $approvemsg;
201
2023-03-06
jrmu
if ($approval eq "true") {
202
2023-03-06
jrmu
$approvemsg = <<"EOF";
203
2023-03-06
jrmu
204
2023-03-06
jrmu
*IMPORTANT*: Your account has been created but it has not yet been
205
2023-03-06
jrmu
approved. To get your account approved, please contact your admins
206
2023-03-06
jrmu
$staff on IRC and by email.
207
2023-03-06
jrmu
208
2023-03-06
jrmu
EOF
209
2023-03-06
jrmu
}
210
2023-03-05
jrmu
my $body = <<"EOF";
211
2023-03-05
jrmu
Welcome to IRCNow!
212
2021-12-17
jrmu
213
2023-03-05
jrmu
You created an email account:
214
2021-12-17
jrmu
215
2023-03-07
jrmu
Username: $username\@$mailhostname
216
2023-03-05
jrmu
Password: $password
217
2023-03-07
jrmu
Server: $mailhostname
218
2023-03-05
jrmu
IMAP Port: $imapport (STARTTLS)
219
2023-03-05
jrmu
SMTP Port: $smtpport (STARTTLS)
220
2023-03-07
jrmu
Webpanel: $webmail
221
2023-03-05
jrmu
$approvemsg
222
2023-03-05
jrmu
*IMPORTANT*: Verify your email address:
223
2023-03-05
jrmu
224
2023-03-05
jrmu
Please reply to this email to indicate you have received the email. You must
225
2023-03-05
jrmu
reply in order to keep your account.
226
2023-03-05
jrmu
227
2023-03-05
jrmu
Connection Instructions: https://wiki.ircnow.org/?n=Email.Email
228
2023-03-05
jrmu
229
2023-03-05
jrmu
IRCNow
230
2023-03-05
jrmu
EOF
231
2023-03-07
jrmu
main::mail($mailfrom, $email, $mailname, "Verify IRCNow Account", $body);
232
2023-03-05
jrmu
}
233
2023-03-05
jrmu
234
2023-03-05
jrmu
235
2023-03-05
jrmu
sub createmail {
236
2023-03-05
jrmu
my ($password, $username) = @_;
237
2023-03-05
jrmu
chomp(my $encrypted = `encrypt $password`);
238
2023-03-07
jrmu
my $line = "${username}\@$mailhostname:${encrypted}::::::userdb_quota_rule=*:storage=1G";
239
2023-03-05
jrmu
$line =~ s{\$}{\\\$}g;
240
2023-03-07
jrmu
my $line2 = "${username}\@$mailhostname vmail";
241
2023-03-07
jrmu
my $line3 = "${username}\@$mailhostname: ${username}\@$mailhostname";
242
2023-03-06
jrmu
`doas sh -c 'echo $line >> $passwdpath'`;
243
2023-03-06
jrmu
`doas sh -c 'echo $line2 >> $virtualspath'`;
244
2023-03-06
jrmu
`doas sh -c 'echo $line3 >> $senderspath'`;
245
2023-03-07
jrmu
`doas smtpctl update table passwd`;
246
2023-03-07
jrmu
`doas smtpctl update table virtuals`;
247
2023-03-07
jrmu
`doas smtpctl update table users`;
248
2023-03-05
jrmu
`doas rcctl reload dovecot`;
249
2023-03-05
jrmu
}
250
2023-03-05
jrmu
251
2023-03-05
jrmu
sub deletemail {
252
2023-03-05
jrmu
my ($username) = @_;
253
2023-03-06
jrmu
my @passwd = main::readarray($passwdpath);
254
2023-03-06
jrmu
my @virtuals = main::readarray($virtualspath);
255
2023-03-06
jrmu
my @senders = main::readarray($senderspath);
256
2023-03-07
jrmu
@passwd = grep !/^${username}\@${mailhostname}/, @passwd;
257
2023-03-07
jrmu
@virtuals = grep !/^${username}\@${mailhostname}/, @virtuals;
258
2023-03-07
jrmu
@senders = grep !/^${username}\@${mailhostname}/, @senders;
259
2023-03-05
jrmu
260
2023-03-05
jrmu
# trailing newline necessary
261
2023-03-06
jrmu
`doas touch $passwdpath.bak`;
262
2023-03-06
jrmu
`doas touch $virtualspath.bak`;
263
2023-03-06
jrmu
`doas touch $senderspath.bak`;
264
2023-03-06
jrmu
`doas chmod g+w $passwdpath.bak $virtualspath.bak $senderspath.bak`;
265
2023-03-06
jrmu
main::writefile("$passwdpath.bak", join("\n", @passwd)."\n");
266
2023-03-06
jrmu
copy "${passwdpath}.bak", $passwdpath;
267
2023-03-06
jrmu
main::writefile("$virtualspath.bak", join("\n", @virtuals)."\n");
268
2023-03-06
jrmu
copy "${virtualspath}.bak", $virtualspath;
269
2023-03-06
jrmu
main::writefile("$senderspath.bak", join("\n", @senders)."\n");
270
2023-03-06
jrmu
copy "${senderspath}.bak", $senderspath;
271
2023-03-05
jrmu
272
2023-03-07
jrmu
`doas smtpctl update table passwd`;
273
2023-03-07
jrmu
`doas smtpctl update table virtuals`;
274
2023-03-07
jrmu
`doas smtpctl update table users`;
275
2023-03-05
jrmu
`doas rcctl reload dovecot`;
276
2023-03-05
jrmu
}
277
2021-12-17
jrmu
1; # MUST BE LAST STATEMENT IN FILE
IRCNow