Aaron Jones [Tue, 10 Jan 2023 00:08:06 +0000 (00:08 +0000)]
Make login failure notices opt-in and add password-based login throttling functionality (#884)
* Make login failure notices opt-in
This introduces a new account flag which determines whether notices
about failed password-based login attempts are generated or not.
* Hook: user_can_login: Indicate login method
This allows hooks to permit or deny logins based upon the type
of credential being used.
This requires some rework of how SASLServ behaves. Specifically,
mechanism modules now indicate their login type at the point
where the hook is called, not when the mechanism is registered.
At the moment, there are four types of login credential:
- Certificate Fingerprints
- User introduction (not logged in, but has a certfp)
- SASL EXTERNAL
This can be triggered simply by a client beginning a pre-registration
SASL login, and then completing registration before completing the
login (for example, a timeout waiting for the server to respond to our
AUTHENTICATE command which then results in a CAP END).
As such, the log level and text of this message is wrong.
The OperServ IGNORE module (when CLEARing all ignores and reporting
them as it does so) frees these 2 pointers (which is correct), but
libathemecore did not on a per-ignore basis.
In other words, manually removing one ignore would leak memory, but
removing all of them at once would not.
Aaron Jones [Sat, 1 Oct 2022 23:02:41 +0000 (23:02 +0000)]
XMLRPC: Allow zero-length authcookie and account name
The existing code requires you to provide both, and then treats
a 1-character authcookie as though none were provided, while
also then ignoring the account given.
Just allow both to be zero-length instead of having to supply a
1-character cookie and an account that it's going to ignore.
Aaron Jones [Fri, 15 Jul 2022 01:09:02 +0000 (01:09 +0000)]
modules/chanserv/close: check correct flags variable for log target
A user reported that the ChanServ CLOSE command was not working for
their channel, saying that the channel could not be closed.
MC_HOLD and CHAN_LOG both have the same value (1), but the former is
for flags in `struct mychan`, and the latter is for `struct channel`.
This lead me to believe that the channel was defined as a log target,
when in reality it was checking the wrong flags field and deducing
that the channel was a log target because it was held.
Aaron Jones [Sat, 5 Mar 2022 05:16:23 +0000 (05:16 +0000)]
configure: --enable-warnings: check for -Wno-declaration-after-statement
Clang trunk is issuing dozens of these diagnostics for every single
compilation unit, warning that declaring variables after a statement
is not supported in versions of C before C99.
However, this is a C99 codebase, and we're using AC_PROG_CC_C99.
Disable this diagnostic.
Aaron Jones [Thu, 24 Feb 2022 00:25:04 +0000 (00:25 +0000)]
m4/atheme-featuretest-warnings.m4: check for -Wno-reserved-identifier
Clang 14 with --enable-warnings is emitting several of these
diagnostics for every single compilation unit, due to how
libmowgli names its variables. This is pointlessly annoying.
We're not just called from the periodic commit timer, but also
on rehash, which includes some modreloads too (when reloading a
module that has configuration options).
We should always use a blocking save regardless of what caused
the save to happen, rather than just test in the periodic commit
timer callback.
This makes running under Valgrind much more amenable.
Ed Kellett [Wed, 19 Jan 2022 20:51:53 +0000 (20:51 +0000)]
Don't save last seen times for logged-in nicks
Last seen times are currently updated by, amongst other things, the
expiry check, which has the effect of updating every logged in nick and
user's line in the database every hour. This makes life much harder for
incremental backup systems -- by my very rough measurement, if a DB save
without an expiry check costs 1MB, a save that includes one will cost
10. Atheme databases aren't huge to begin with, but I think a tenfold
reduction is still worth chasing.
Edited by @aaronmdjones: Add NEWS entry and script to migrate back to
the v7.2 database format, should people wish to downgrade.
Aaron Jones [Tue, 18 Jan 2022 12:14:27 +0000 (12:14 +0000)]
libathemecore/ptasks.c: stats c: show uplink host
This is already gated behind PRIV_SERVER_AUSPEX, which OperServ
SPECS describes as "view concealed information about servers".
Also, you can already obtain this information from `stats f`
(shows all active file descriptors associated with connections,
which includes endpoint IP addresses), which is gated behind the
same privilege.
jesopo [Sun, 28 Nov 2021 13:45:48 +0000 (13:45 +0000)]
Allow hooks to force account expire
Edited and committed by @aaronmdjones: Other general code cleanup;
clarify that if a hook forces account expiry, the destructor for
the myuser object will take care of logging them out (if they are
logged in). Also account for the fact that they may be logged in
by having the log message include their login count. Finally, don't
let a hook prevent the expiry of an unverified account.
If passed a list consisting entirely of non-reloadable modules, we would
leak approximately up to 24 bytes of memory each time. Discovered manually
during reading the function.
Ed Kellett [Sun, 17 Oct 2021 17:01:11 +0000 (18:01 +0100)]
saslserv/main: Preserve pending login on abort
The previous patch made SaslServ aware of pending logins (i.e. SASL
sessions which have succeeded and generated a SVSLOGIN). This one
ensures that aborting a SASL authentication attempt does not destroy
that information: if you successfully authenticate as user A, then begin
and abort another authentication attempt as user B, you will log in as
user A.
This is only relevant in the pre-registration case, when SASL logins
cannot be actioned immediately. It's also necessary to avoid a desync in
this case: if we have already sent a SVSLOGIN for a login, the user is
going to be informed that they've logged in, and the ircd is going treat
them as though they're logged in. Other solutions are possible, but I
think the cleanest one is to action the last SVSLOGIN we sent, mirroring
their effect ircd-side.
Ed Kellett [Sun, 17 Oct 2021 13:13:22 +0000 (14:13 +0100)]
saslserv/main: Track EID we're pending login to
The existing model does not remember that we've sent a SVSLOGIN for a
given SASL session, and simply assumes that if a client is introduced
with a SASL session open, that session must have succeeded. The security
of this approach requires ircd to implicitly abort SASL sessions on
client registration.
This also means that if a client successfully authenticates and then
does something else its pending login is forgotten about, even though a
SVSLOGIN has been sent for it, and the ircd is going to think it's
logged in.
This change removes the dependency on ircd's state machine by keeping
explicit track of the pending login, i.e. the one we've most recently
sent a SVSLOGIN for. The next commit will ensure that a client abort
(even an implicit one) doesn't blow that information away.
Aaron Jones [Sat, 7 Aug 2021 18:36:00 +0000 (18:36 +0000)]
libathemecore/connection: connection_add(): make fd non-inheritable
Grumble; Windows compatibility stuff, ew, etc. I just copied the
function below it. Windows compatibility is liable to get ripped
out of services entirely due to WSL being A Thing now, but for
now just follow the convention.
This means we now don't need to call connection_close_all_fds()
when forking to send e-mail.
Aaron Jones [Fri, 16 Jul 2021 15:31:21 +0000 (15:31 +0000)]
modules/saslserv/main: authxid_can_login: check for freeze early
Freezing an account should prevent a login attempt entirely, rather
than allowing the mechanism to succeed first, only for the login
itself to then fail.