1
0
mirror of https://github.com/unrealircd/unrealircd.git synced 2026-07-09 01:43:12 +02:00
Commit Graph

3391 Commits

Author SHA1 Message Date
Bram Matthys ed16dad40e Add a bunch of crule functions:
* Boolean checks: is_oper, is_local, has_swhois
* Match functions: match_class, match_server, match_vhost,
  match_realhost, match_away, match_asname, match_operlogin,
  match_operclass, match_sni, match_tls_cipher
* Numeric counters: connections_from_ip, channel_count,
  channel_member_count, idle_time
* Traffic stats: messages_sent, messages_received, bytes_sent,
  bytes_received
* Text analysis: text_byte_count, text_character_count, word_count,
  uppercase_percentage, digit_percentage, non_ascii_percentage,
  max_repeat_count, mixed_utf8_score, unicode_block_count

Will do a more thorough audit and look at adding some kind of
tests tomorrow.
2026-03-24 19:33:55 +01:00
Bram Matthys f884bfe755 Another workaround for test suite. 2026-03-22 13:25:36 +01:00
Bram Matthys 806c883a7f Rename geoip_maxmind to geoip_mmdb with a backwards-compatible warn.
This is a mmdb backend which supports various GeoIP providers,
and we no longer use the maxmind library, so this makes sense.
2026-03-22 12:29:00 +01:00
Bram Matthys 172ace9750 geoip_maxmind: use our own mmdb implementation
This is mainly due to licensing. The libmaxminddb library uses the
Apache license, which meant if we would compile it in by default it
would effectively transform our "GPLv2 or later" to "GPLv3 or later".
Our implementation is ISC licensed, so we can include and enable it
by default and keep things at "GPLv2 or later". This is also why we
used geoip_classic in the first place as default and compiled in,
and not the mmdb variant.

The mmdb.c is based on the specification, using the Go implementation
as a reference during development (ISC licensed), initially implemented
with the help of Claude Opus 4.6. After that substantial changes were
made to make it match UnrealIRCd's style and to make things less error
prone: C style changes, allocation and zero termination of strings in
the library, auto-NULL in variadic functions so the caller cannot
forget NULL there (similar to our unreal_log/do_unreal_log), using
enums as the return type instead of int (similar to curl), adding
doxygen docs, etc.

This also means the old mmdb library dependency has been dropped,
including from configure/autoconf.

At the moment we still use the geoip classic library by default,
including those DB files. The idea is we will switch over sometime
later after this current new MMDB stuff has received more testing.

This also makes us more flexible, since .mmdb files have become the
de-facto standard for pretty much all geoip vendors.
2026-03-22 12:10:18 +01:00
Bram Matthys 89bce01c31 Fix OOB write in geoip_csv if the .csv file is bad / malicious.
This module is rarely used but analysis showed that there was an
OOB write in the country name, and two small off-by-ones in code
and continent.

Again, this only matters if the CSV file you are importing is bad
or malicious. And we use stack protection in UnrealIRCd so this
should then "only" cause a crash.
2026-03-16 14:10:29 +01:00
Bram Matthys f944990c54 Fix some flagged stray semicolon in C code (;;) 2026-03-16 09:53:22 +01:00
Bram Matthys 27a3fb8d97 unreal_server_compat: fix always using EXBTYPE_BAN even for +e/+I.
For the extbans that we ship, no problem, as this isn't used in
any of our extbans, but for third party it may matter, or for us
in the future.

Just something we came across while looking into the issue from
previous commit.
2026-03-14 10:20:24 +01:00
Bram Matthys 31005e18b1 Fix extbans in +I not being converted to letter bans to older servers.
This affects servers without NEXTBANS, such as anope 2.0.x series
(anope 2.1.x is not affected as it supports NEXTBANS).

Non-NEXTBANS servers only support letter extbans so we are supposed
to convert ~security-group:known-users to ~G:known-users when sending
to such a server, in unreal_server_compat. And we did this well for
the MODE command for +beI. In SJOIN we did this correctly for +b/+e
but not for +I due to a silly code mistake.

This bug is present since 6.0.0 but wasn't noticed until now.

To be a real problem you need something like:
1. Anope 2.0.x series (or other services without NEXTBANS)
2. A channel with +I extbans
3. KEEPMODES set on that channel

Then what happens is when services boot:
1. UnrealIRCd will sync with anope 2.0.x and incorrectly send
   named bans, which will confuse anope. But nothing strange
   happens yet at this point.
2. Then on next server sync (eg anope restart or unreal restart)
   anope will try to restore these but they end up with weird
   entries like +I *!*@~security-group:known-users
   (note the *!*@ prefix)

And it should be noted that this would also happen in a situation
with UnrealIRCd 5 + UnrealIRCd 6 servers, but UnrealIRCd 5 is
End Of Life anyway.

Reported by BlackBishop and Sadie two days ago. Thanks!
2026-03-13 13:57:41 +01:00
Bram Matthys 7865675917 Fix OOB write if a trusted linked server sends malicious data.
NOTE: Linked servers are considered trusted in UnrealIRCd.

This is not exploitable beyond a crash, due to -fstack-protector-all,
a hardening compiler flag we added many years ago. Even without
that flag it would be rather difficult, and i didn't manage to,
but this should never happen anyway since this flag is only
missing in gcc/clang versions that are more than 15 years old.

This issue was introduced by the move to CMD_BIGLINES in
6c5de62c18 in 6.2.2 release.
2026-03-06 07:14:10 +01:00
Bram Matthys 87e4249a09 extjwt: don't free modes/umodes, they are taken care of by payload. 2026-03-04 17:07:06 +01:00
k4be deff636c74 extjwt: Remove OpenSSL deprecation warnings 2026-03-04 09:38:05 +01:00
Bram Matthys 648a10494f Add -DTESTSUITE and use it from extras/build-tests/nix/build.
In particular, this disables default +F for #__SYNC__ channels.
The test suite has a "+F off" but when on 3 servers, each 75
clones are connecting, the MODE is too late and the join limit
is already reached sometimes. Causing tests to fail.
2026-02-28 15:26:57 +01:00
Bram Matthys 17037b0694 Fix build failing if DNS is not working. Building UnrealIRCd should never fail
because it has no internet access, like when fetching the repository
(modules.list file) of 3rd party modules.

Previously I had..
url_start_async(request);
synchronous_http_request_in_progress = 1;
.. which worked fine for the "cannot connect case", like port blocked
or timeout connecting. But if DNS fails then the step of setting
synchronous_http_request_in_progress = -1 (so failed) already happens
during the url_start_async(request); call, and then the line after it
sets 'synchronous_http_request_in_progress = 1;' so we miss that it
failed and wait in the I/O loop forever.
Simply swapping the two lines of code fixes this.

The other change is that when running the ModuleManager in "make" we should
ignore the exit code. I probably broke that while refactoring and adding
non-zero exit codes in de modulemanager past few months for this release.
2026-02-25 14:58:11 +01:00
Bram Matthys 3a96bdf6ec Add set::allow-setident (default: 'no'), set::allow-setname ('yes')
Two new settings that control the use of `SETIDENT` and `SETNAME`:
* [set::allow-setident](https://www.unrealircd.org/docs/Set_block#set::allow-setident)
  now defaults to 'no'. Previously all users were allowed to change their
  ident (taking into account
  [set::allow-userhost-change](https://www.unrealircd.org/docs/Set_block#set::allow-userhost-change)
  restrictions).
* [set::allow-setname])(https://www.unrealircd.org/docs/Set_block#set::allow-setname)
  has a default of 'yes' which matches older UnrealIRCd versions (no change).
  Perhaps some admins who use controlled (web)chats may want to set this
  to 'no' if users are not supposed to change their realname/gecos.
  This is probably rare, but they have the option now.
2026-02-23 08:58:39 +01:00
Bram Matthys 014925496b Forgot a few more of those [1] that need to be []
(see previous commit)
2026-02-22 16:24:55 +01:00
Bram Matthys 7d45e69fd2 Use C99 flexible array members, like name[], instead of name[1]
in NameList, Tag, Watch and HistoryLogLine.
This does mean the allocation routines need a +1 everywhere, but
I think I got all of them. I also don't see them being used directly
in such a way in 3rd party modules (which is logical, as they
should use the API and not allocate such structs directly).

Also, SpamExcept has been removed as it was not used anywhere.
2026-02-22 16:11:41 +01:00
Bram Matthys 19d17832fe Remove set::restrict-extendedbans as it didn't work. Simply don't load
the particular extended ban module if you don't want it.

For example, if you include the default modules.default.conf and, say,
you don't want ~quiet extbans then you add this in your unrealircd.conf:

blacklist-module "extbans/quiet";
2026-02-22 13:07:57 +01:00
Bram Matthys 979f44bde4 Linking: upon duplicate server we could SQUIT the wrong one.
This would cause a bit of a mess, that usually would be resolved a few
seconds later, but still a mess. I had this on irc*.unrealircd.org
myself when rerouting a server from a backup-hub to primary-hub
a few months ago.
2026-02-22 11:37:09 +01:00
Bram Matthys d79161019a Clear client->local->proto for users.
This is not an issue now in all code paths, but if someone accidentally uses
SupportXYZ() without checking IsServer() then it would be an issue.

In the past we used client->local->proto for client flags as well, but this
has been split off to client->local->caps a while ago.

I guess we should rename client->local->proto to something more server-ish
in a later major release to indicate this as well.
2026-02-22 10:37:01 +01:00
Bram Matthys 371cb487b9 Fix missing "return;" in "Bad ulines" rejection of a server. 2026-02-22 10:00:32 +01:00
Bram Matthys 059abc4b56 "STATS fdtable" is mostly for debugging. Simplify read/write handler display
and callback data in non-DEBUGMODE. Also because exposing pointers like
this can defeat ASLR. These STATS are oper-only though, but hey, defense in
depth... and the pointer values don't make sense to non-devs anyway,
so why show them in the first place.
2026-02-21 19:41:56 +01:00
Bram Matthys b467e4e147 JSON-RPC: Fix missing mtag issued by in user.part
We use mtag_add_issued_by() to prepare it but then pass NULL
in do_cmd() so it was basically useless.

Also compile fix for previous (forgot to git ammend)
2026-02-21 16:22:36 +01:00
Bram Matthys ec4ccbde82 Fix memory leak on JSON-RPC log.send and fix a small auth url parse thing.
Actually that auth url method is not documented, we should probably remove it.
2026-02-21 16:18:34 +01:00
Bram Matthys b93cb14623 Fix crash due to fix from a few hours ago (5580b294f4) 2026-02-21 16:04:50 +01:00
Bram Matthys d22f65364c Make duplicate deny link::rule items an error.
(as otherwise using duplicated generates only a warning and could memleak)
2026-02-21 14:57:41 +01:00
Bram Matthys b55a4b84e0 Blacklist hit with a soft ban action: fix memory leak if multiple hits occur.
So, if the IP was on multiple blacklists.
2026-02-21 14:43:41 +01:00
Bram Matthys f20b62ea3b Fix memory leak on blacklist hit if using soft bans 2026-02-21 13:59:10 +01:00
Bram Matthys 28a8bee041 Don't use 'client' in CENTRAL_BLOCKLIST_ERROR, prolly copy-paste error.
Not really important as it is not part of the normal log message (only JSON).
2026-02-21 13:49:26 +01:00
Bram Matthys f59b937f3b Fix leak if central-blocklist returns "error" JSON string (very rare) 2026-02-21 13:45:47 +01:00
Bram Matthys 5580b294f4 Fix memory leak if using spamfilter::except. 2026-02-21 13:20:17 +01:00
Bram Matthys be479aa890 The buffer in spamfilter_build_user_string() was too small causing cut off.
This affects the spamfilter 'u' target. It didn't overflow but was cut off,
potentially causing a NON-MATCH where it could have been a MATCH instead.
2026-02-21 13:18:30 +01:00
Bram Matthys 2ac09de148 Fix central spamfilter with "stop" action, due to using same &var twice. 2026-02-21 13:13:15 +01:00
Bram Matthys c24424bb50 JSON-RPC: throttle.set did not do anything
Reported by adator in https://bugs.unrealircd.org/view.php?id=6608
2026-01-30 07:39:37 +01:00
Bram Matthys 91d5114a1e Whitespace fix
[skip ci]
2026-01-28 09:38:39 +01:00
Bram Matthys a887de92ce Add extra safety in register_user() against shunned users. 2026-01-25 12:56:52 +01:00
Bram Matthys 8467969878 Don't show confusing CENTRAL_BLOCKLIST_TIMEOUT when user is shunned.
Previously it showed this warning and said "Allowing user .. in unchecked"
when the user got shunend by CBL. Usually harmless but.. had a report
where it possibly was not (though that was an older UnrealIRCd version).
In any case, confusing, solved now!
2026-01-25 12:54:30 +01:00
Bram Matthys 91930e3631 Bleh, just use "*" in ERR_INVALIDMODEPARAM for the param.
Otherwise you get into trouble if client does things like:
MODE #test +l ::a
MODE #test +l :a b c
And I am too lazy to handle these cases :D
2026-01-23 08:48:34 +01:00
Bram Matthys d413959e57 Chanmode +l: when coming from an IRC client, reject <=0 instead of transforming.
Reject it with an ERR_INVALIDMODEPARAM, just like we do for +k.

I think the higher number transforming is fine, but this <=0 transformation
is odd as it almost never is what the user actually intended.

In S2S traffic we still transform, as rejecting there is more problematic,
(causing a desync) and transforming it there is not a major issue, anyway.

Reported by ProgVal in https://bugs.unrealircd.org/view.php?id=6602
2026-01-23 08:45:34 +01:00
Bram Matthys 2dd23d13b7 Silently drop TAGMSG to users who refuse PRIVMSG/NOTICE also (umode +D, +R),
since the message/notice would not make it through either.
This also means someone can no longer iterate through users to see who
is +D/+R by sending a "silent" TAGMSG. (Silent in the sense that the
end-user usually would not have noticed)

Suggested in https://bugs.unrealircd.org/view.php?id=6579 by zw32h (I think)

This also means HOOKTYPE_CAN_SEND_TO_USER now allows you to NOT to
set errmsg, to silently drop a message. Previously we would crash
deliberately on such a situation to enforce that all modules would
set a proper errmsg.
2026-01-23 08:23:22 +01:00
Bram Matthys c2db2715c0 Fix post-registration SASL not working due to change from a few days ago.
(commit 0cf0c0faa2)

This was caused by register_user() being called twice, while it should
only have been called if !IsUser().

Reported by ProgVal in https://bugs.unrealircd.org/view.php?id=6606
My BuildBot screen was also all red :D.
2026-01-23 07:48:01 +01:00
Bram Matthys a5f1aa7f34 Print a [BUG] line if register_user() is called twice. Deliberately crash
when running in DEBUGMODE.
2026-01-23 07:42:57 +01:00
Bram Matthys 34e3469f91 Merge branch 'unreal60_dev' of github.com:unrealircd/unrealircd into unreal60_dev 2026-01-19 09:04:51 +01:00
Bram Matthys 96f4954e2b Compile ALL 3rd party modules through modulemanager, including unmanaged.
This gets rid of src/buildmod and unifies the process a little, which
i need later.

We still compile the 3rd party modules unconditionally and twice (during
both make and make install). Which is a quirk that is in there since U6
and maybe U5 already :D. That's because we don't check if header files
have changed. There was previously a "is the .c file newer than the .so"
in there, though, that is gone now. Anyway, that's something for later.

Another quirk is that we do not halt compile if a 3rd party module fails
to compile. Which was sortof intentional at one point but.. is not ideal,
so will probably changed as well.

Anyway, that's not why i am doing all this stuff right now...
2026-01-19 09:02:53 +01:00
Valerie Liu 1dd6e9b07b Fix indentation in sasl.c return statement (PR #333) 2026-01-18 19:32:11 +01:00
Bram Matthys 0cf0c0faa2 Wait for SASL to complete during handshake (success/fail/timeout).
This is to guard against clients that do like CAP LS 302, NICK, USER,
AUTHENTICATE, CAP END, without waiting for the SASL result.

Previously "CAP END" would abort SASL if the response was not in yet.

Now "CAP END" will cause us to wait for SASL success/fail/timeout
and when that happens we will end the handshake and the user will
come online (or not, if e.g. banned).

In other words, SASL is no longer canceled upon premature CAP END.

And yeah, clients should wait, as is mentioned in
https://ircv3.net/specs/extensions/sasl-3.1
"it is RECOMMENDED to only send CAP END when the SASL exchange is
 completed or needs to be aborted"
But since it is a recommendation and not a hard requirement, we'll
be nice and handle this situation server-side.

Of course, clients could still misbehave then by sending stuff
blindly after CAP END, like JOIN events, without even checking
if they got numeric 001 and so on... so in that sense it shifts
the problem a bit.. but.. at least that type of waiting is
hopefully more common :D
2026-01-18 19:06:59 +01:00
Bram Matthys 1c461db46d Call update_known_user_cache() right before HOOKTYPE_REMOTE_CONNECT.
Set known_users=NULL during a very limited period, just to be safe.
(Note that it can also be NULL during initial boot, which is a
 longer period, which is why we always NULL-check in the code that
 accesses it, but this aside)
2026-01-10 10:36:40 +01:00
Bram Matthys 0cf9fb1cb0 Also update_known_user_cache() from AllowClient(), just before
calling HOOKTYPE_ALLOW_CLIENT and (potentially) allowing the client in.
2026-01-10 10:32:07 +01:00
Bram Matthys 4235a183e3 Call update_known_user_cache() when reputation score reaches known-users
threshold.

* Possible transition to known-users:
* - logged in is already handled by HOOKTYPE_ACCOUNT_LOGIN so we don't care about those
* - score reached (or just over) the minimum reputation score
* Caveat: if having multiple connections from the same IP then
* the first one may theoretically not have crossed in some cases.
* Ah well, it is a cache, not some precise thingy.
2026-01-10 10:15:09 +01:00
Bram Matthys 34ab517d9e Fix possible problem with channel in config-file, such as security group
or elsewhere. I don't think this is an actual problem, but at least the
fix from 1abf73309a was inconsistent,
if we check for b->client further down, then we should not be reading
from it a few lines up. As said, don't think this code is reached in
practice, but hey...
2026-01-04 10:31:38 +01:00
Bram Matthys 4e3989f304 Add ban user { ....; soft yes; } as an easy way to add a soft-ban from
the config file, without having to resort to things like mask %~asn:XXX;
Now you can just use:
ban user {
	asn { 11111; 22222; 33333; 44444; }
	soft yes;
	reason "This ASN is not allowed. If you have an account you can still bypass";
}

Requested by nobody but sounds like a good idea :)
2026-01-03 19:59:52 +01:00