1
0
mirror of https://github.com/unrealircd/unrealircd.git synced 2026-06-27 02:56:38 +02:00
Commit Graph

2837 Commits

Author SHA1 Message Date
Bram Matthys c0a46abd60 ModData API: add ModDataInfo .priority item and use it to speed up
things by making the keys with the most lookups first, e.g. "reputation",
"geoip", "certfp". This order is based on actual lookup counts during a
quick test with 250 clones doing some typical IRC traffic.

Key:		Lookups:	Position before:	After split:	After split+order:
"reputation"	20362		37			14		1
"geoip"		10555		44			15		2
"certfp"	9264		23			8		3
"webirc"	7407		27			10		4
"websocket"	7110		55			19		5

We could also consider going for a hash table, but this may be "good enough" for now.
2025-09-29 16:50:44 +02:00
Bram Matthys db6476e1ab ModData API (internal): split the single linked list into 7 lists, to speed
up moddata_client_get() etc -> findmoddata_byname().
Apparently we have 52 moddata registrations (that is without 3rd party modules)
so otherwise it is a loooong linked list.
2025-09-29 16:22:08 +02:00
Bram Matthys c8431b7cb8 Make client->local->caps a 64 bit unsigned int on all archs.
This was previously a "long", which could cause issues on 32 bit archs.
We ship with 28 CAPs now, and that's without 3rd party modules, so...

This is similar to the client->flags bumping in 2023
(a3ed1eabd9).
2025-09-28 10:03:04 +02:00
Bram Matthys 602f6c7238 URL API: add .minimum_tls_version, and use TLS1_3_VERSION for central-blocklist.
Something like:

 #ifdef TLS1_3_VERSION
        w->minimum_tls_version = TLS1_3_VERSION;
 #endif
        url_start_async(w);

Require TLSv1.3 for central-blocklist and spamreport calls, unless your
OpenSSL does not support it, which should be rare.

At some point in the future I will make this endpoint TLSv1.3+ only.
2025-09-21 14:24:06 +02:00
Bram Matthys 507061af46 Add tls-options::signature-algorithms for those who want to override the default.
We don't set it in UnrealIRCd at the moment, so this is just to override
the OpenSSL defaults at the moment. It is good to have this exposed, in
case some vulnerability is discovered or you need some flexibility in
tweaking this.
2025-09-21 13:55:24 +02:00
Bram Matthys b0b6cc81e2 This belongs to the autoconf upgrade too (see previous) 2025-09-21 13:39:12 +02:00
Bram Matthys 4c6e259681 You can now use "password" multiple times in the conf (eg in allow::password).
allow {
	mask *;
	password "secret";
	password "letmein";
}

This is always an "OR" type of match, any match means you pass.

I was actually doing this for the dual-cert stuff from previous commit,
where this can come in handy:

link irc1.example.org {
...
    password "AHMYBevUxXKU/S3pdBSjXP4zi4VOetYQQVJXoNYiBR0=" { spkifp; };
    password "jNw8P4QMg9tqjEJ4/lFikXBNHdIGSeN2B4/T322VjIo=" { spkifp; };
...
}
2025-09-21 11:42:59 +02:00
Bram Matthys 877d151da4 Support multiple TLS certificates/keys, e.g. ECDSA + ML-DSA (PQC).
In the past a dual cert/key setup could have been useful for RSA + ECDSA
but nowadays all clients support ECDSA so that makes little sense.
The reason it is added now is so you can use ECDSA + ML-DSA or some
other [regular crypto] + [post quantum crypto] combination.
Actually, you could even use more than two.

To use this in the config file, simply use the certificate and key
directive multiple times. Just be sure to load the certificates and keys
in the same order. We will print a helpful error if you fail to do so.

Note that for Post Quantum Cryptography the most important step today
was/is to protect against the "Harvest now, decrypt later" scenario
https://en.wikipedia.org/wiki/Harvest_now,_decrypt_later which is a
"passive attack". That's why in UnrealIRCd 6.2.0 we enabled
X25519MLKEM768 if it is available (OpenSSL 3.5.0 and later).
While, this commit, and this talk about dual ECDSA and ML-DSA, is about
when a quantum computer exists and actively does a man in the middle
attack. That's not a realistic scenario in 2025 and according to experts
also not in the next few years. We just make the UnrealIRCd code-
base ready to have this feature for when it is needed / will be used,
and to get this tested properly.

For testing the dual ECDSA and ML-DSA setup I used the following
command to create the 2nd cert/key (self-signed):

openssl req -x509 -nodes -newkey mldsa65 \
  -keyout ~/unrealircd/conf/tls/server.key.mdsa65.pem \
  -out ~/unrealircd/conf/tls/server.cert.mdsa65.pem \
  -days 3650

And then:

listen {
        ip *;
        port 6697;
        options { tls; }
        tls-options {
                certificate "ssl/server.cert.pem";
                key "ssl/server.key.pem";
                certificate "ssl/server.cert.mdsa65.pem";
                key "ssl/server.key.mdsa65.pem";
        }
}

When running openssl s_client -connect 127.0.0.1:6697 it shows ML-DSA is used:
...
Peer signature type: mldsa65
Negotiated TLS1.3 group: X25519MLKEM768
...

And with openssl s_client -connect 127.0.0.1:6697 -sigalgs "RSA+SHA256:RSA+SHA384:ECDSA+SHA256:ECDSA+SHA384"
it shows ECDSA is used:
..
Peer signature type: ecdsa_secp384r1_sha384
Negotiated TLS1.3 group: X25519MLKEM768
..

This is just for testing purposes (self signed cert). As of right
now (Sep 2025), you can not get a trusted certificate with ML-DSA,
as the CA/Browser Forum only allows issueing RSA and ECDSA keys.
Also, all the trusted Certificate Authorities use RSA or ECDSA.
And, again, all this is not ML-DSA specific, it should work for
other dual/multi combinations, and.. who knows they even go for
something hybrid.

A downside of dual certs is that this makes the whole spkifp thing more
complicated because if you use 2 certs/keys you now have 2 possible
fingerprints (spkifp) that could match in e.g. server linking.

While coding this, I also changed the 'STATS P' output to use the txt
numeric instead of notice, and be more verbose in its output for TLS
listeners: printing the certificate(s) and key(s).
2025-09-21 10:32:29 +02:00
Bram Matthys dbb2d1a5c8 Move isupport_check_for_changes() to the 'isupport' module.
This function was added a short while ago, and well it seems to be
able to be possible in a module. Since the 'isupport' module is mandatory
and this is ISUPPORT related, it is the right place.
Can't move isupport_snapshot() because modules might not be loaded yet
or things are currently unloading, i think. Not important anyway.

Also, make things work if there are more changes than would fit
on one isupport line. Although I didn't really test this..
Ended up splitting things in 3 helper functions to avoid some
goto and/or duplicate code and stuff. The alternative was, surprisingly,
even more ugly.
2025-09-20 15:44:56 +02:00
Bram Matthys e78a6a6dbf isupport & extended-isupport module, work in progress.
This is mostly from Valware PR https://github.com/unrealircd/unrealircd/pull/310
Will do more changes in later commits..
2025-09-20 14:34:28 +02:00
Bram Matthys 9e490196a8 set::send-isupport-updates: Valware added this, but this is now expanded
to all ISUPPORT tokens, instead of only CHANMODES, PREFIX and STATUSMSG.
E.g. changing set::min-nick-length would also broadcast the change.

Technically we will call isupport_snapshot() before the rehash (or before
delayed module unload) and then after modules were reloaded/unloaded we
call isupport_check_for_changes(). This uses the ISUPPORT system in a
general way, so works the same for all tokens.

https://www.unrealircd.org/docs/Set_block#set::send-isupport-updates

TODO: Deal with more than X changes (is currently an abort, crash)

TODO: batch for draft/extended-isupport
2025-09-20 14:05:35 +02:00
Bram Matthys f22f8d0dcd Add set::utf8-only: if set to 'yes' this means all IRC traffic is UTF only.
See https://www.unrealircd.org/docs/Set_block#set::utf8-only and the
UTF8ONLY specification at https://ircv3.net/specs/extensions/utf8-only
for more information.

Reported by PeGaSuS, who reported it based on a #unreal-support message
from uMut, who reported it based on a message from itsonlybinary.
This closes https://bugs.unrealircd.org/view.php?id=6458

This feature still needs to go through our internal tests.
2025-09-20 09:00:52 +02:00
Bram Matthys 0c17276039 Move https_new_ctx() from src/url_unreal.c to src/tls.c so it is
always available (also w/cURL) so it can be used by the crash
reporter. And delete duplicate code crashreport_init_tls()
function since it is now unused.

As always, duplicate code causes problems when one is changed and
the other is not. This also happened here, where the curves or
TLS groups where set in url_unreal but not in the crash reporter.
Now that one is minor, but the danger is clear.
2025-09-17 19:57:03 +02:00
Bram Matthys 82bf4a6beb Add logging category "advice" that is used by best practices (color: blue).
Maybe a bit odd since only <10 things use this category but it makes it
stand out as a separate thing much better. As for a level (not that it
matters) it is between 'info' and 'warn'.
2025-09-15 14:21:51 +02:00
Bram Matthys 817abc4101 Add security-group::server-port and similary in match item, to match
users by server port (eg 6667, 6697, 8000, etc).

This also adds security-group::exclude-server-port for consistency.

And in crules the function server_port() returns the server port number,
so you can use rule 'server_port()>6690' for example.

Note that for remote clients this will only work after previous
commit (b2d0ec1af3) is loaded on all
servers, otherwise all remote clients are seen as having a server_port
of zero (0). Though you probably usually only care about this on local
users anyway.
2025-09-14 17:28:04 +02:00
Bram Matthys b2d0ec1af3 Move/add local_port & server_port to ModData, so remote clients can be tracked.
This is sent over the wire as early moddata, just like "operlogin" and "operclass"
2025-09-14 17:03:34 +02:00
Bram Matthys 8c26cec5fc Fix 'const' in various functions: various arguments were const char *
in the EFunction but not in the actual function. That's bad since it
means the "const guarantee" got lost. And one or two similar cases with
incorrect parameter types and mismatching return types. This was
found with some analyzer, we had no bugreports with regards to this.
2025-09-14 15:01:39 +02:00
Bram Matthys 13217cc6ff Bump version to 6.2.1-git 2025-09-14 14:57:43 +02:00
Bram Matthys 9042dd21c0 ** UnrealIRCd 6.2.0.2 ** 2025-09-14 14:21:47 +02:00
Bram Matthys 4cc51af280 ** UnrealIRCd 6.2.0.1 **
This version (only) fixes some incorrect "best practices" warnings
2025-09-12 07:55:33 +02:00
Bram Matthys 74538e77d4 Another best practices fix: this one is with listen-nontls-port.
It could cause a spurious
"Your config has NO errors, but you received some best practices tips above, in summary"
even though no best practices were displayed... which was a bit mysterious.

Also, ::listen-nontls-port was actually meant to be called ::listen-tls-only
so accept both forms from now on. The reason it was supposed to be like that
is that all best-practices options are... best practices...
hashed passwords, trusted cert, trusted cert with valid hostname,
listening on a nontls port... ? NOPE! listen-tls-only! Aaaaa.
2025-09-10 16:45:52 +02:00
Bram Matthys bc27eb48fb ** UnrealIRCd 6.2.0 ** 2025-09-09 18:10:49 +02:00
Bram Matthys aa8a8ee135 ** UnrealIRCd 6.2.0-beta3 **
This one will also be announced on the mailing list (beta1 and beta2 were not)
2025-08-01 11:28:37 +02:00
Bram Matthys 84a1e59a44 Best practices: check if the certificate is actually valid for me::name.
That is, if the set::best-practices::trusted-cert check is on and passed
("certificate is valid and issued by a trusted CA") then we also
do this new set::best-practices::trusted-cert-valid-hostname check:

/* If the trusted-cert check passes, then we do another check to see if
 * the certificate is valid for me::name. Since users usually connect to your
 * server by your server name it is important for the certificate to be
 * valid for that name. Unless you really only care about e.g. irc.example.net,
 * and not about individual irc2.example.net server names, in which case you
 * can turn this off, but not sure if that is good practice.
 */
trusted-cert-valid-hostname yes;
2025-07-28 09:55:01 +02:00
Bram Matthys 990fe22e64 Print a best practices message if any plaintext port is open (eg 6667).
Ports that listen on 127.0.0.1 or ::1 are ignored (useful for e.g. services)

Looks like this:
[info] You have at least one IRC plaintext port open (such as 5668). Nowadays, everyone should be using SSL/TLS (on port 6697). See https://www.unrealircd.org/docs/Use_TLS.

See that https://www.unrealircd.org/docs/Use_TLS for more info (feedback welcome)

All this is in addition to somewhat related 29ce0ce29a:
[info] Your SSL/TLS certificate is not issued by a trusted Certificate Authority.
[info] It is highly recommended to use a 'real certificate'. To get a free one, see: https://www.unrealircd.org/docs/Using_Let's_Encrypt_with_UnrealIRCd

If applicable, that message is printed first, the 6667 one comes after ;)

Suggested in https://bugs.unrealircd.org/view.php?id=6500
and numerous times / discussions on IRC over the past years
It's finally time.. no.. it's overdue..
2025-07-26 16:02:33 +02:00
Bram Matthys a73186362b * Add link::options::no-certificate-verification
* Code cleanup: split connect flags in CONNECT_OUTGOING_* and CONNECT_*
* Don't print tls_link_notification_verify() stuff for localhost conns
2025-07-26 13:26:46 +02:00
Bram Matthys 26fb6b70d6 Fix localhost S2S link downgrading link-security.
On the incoming side it was correctly identified as link sec 2,
but on the outgoing side the localhost check failed and caused link sec 1 or 0.

Bug has beent here for a while but I don't think many people
link two UnrealIRCd servers over localhost that are on production
(i do, when dev'ing, but then I don't care about linksec, obviously)

Also, this wouldn't flag services from 2 to 0 because this bug only
affected outgoing UnrealIRCd server connections.
2025-07-26 13:24:00 +02:00
Bram Matthys fe569346b0 Call unrealircd_set_tls_groups() from url_unreal (remote includes) as well.
For url_curl it seems too complicated, added a comment there.
2025-07-25 14:03:54 +02:00
Bram Matthys 6178e2b94f *** UnrealIRCd 6.2.0-beta2 *** 2025-07-25 10:31:44 +02:00
Bram Matthys d146da4a07 Change the cipherinfo, such as in [secure: TLSv1.3...] and in WHOIS.
Previously this was like:
TLSv1.3-TLS_CHACHA20_POLY1305_SHA256
It is now changed to be like:
TLSv1.3/X25519/TLS_CHACHA20_POLY1305_SHA256

So:
* Changed from '-' to '/' because sometimes the cipher(suite)
  contains a hyphen (TLSv1.2 and earlier)
* Show the key exchange "group" in the middle, such as X25519
  for the usual non-PQC case and X25519MLKEM768 for hybrid group
  with PQC.
* The group is shown in OpenSSL 3.0.0+ (and obviously you need
  OpenSSL 3.5.0 to ever see X25519MLKEM768 there, but that is
  something different)
2025-07-24 15:32:00 +02:00
Bram Matthys 0729382ba2 Rename ::ecdh-curves to groups and add X25519MLKEM768 to group list.
Post-quantum cryptography (PQC). Release notes will follow later.
2025-07-24 14:47:49 +02:00
Bram Matthys d135e687c3 Add TextAnalysis on spamfilter hit in the JSON logs. 2025-07-14 18:11:59 +02:00
Bram Matthys e8b5a831e1 ** UnrealIRCd 6.2.0-beta1 **
(Possibly some Windows build fixes after this, but..)
2025-07-13 11:39:00 +02:00
Bram Matthys 29ce0ce29a Best Practices: If zero SSL/TLS certs are issued by a trusted CA, complain and
suggest to use Let's Encrypt.

This can be turned off via set::best-practices::trusted-cert, see
https://www.unrealircd.org/docs/Set_block#set::best-practices

Oh yeah, and this only works at OpenSSL 1.1.0 and higher, i didn't bother
with people running ancient versions.
2025-07-13 09:26:54 +02:00
Bram Matthys 96a2ea5c02 Add HOOKTYPE_BANNED_CLIENT 2025-07-12 18:06:52 +02:00
Bram Matthys 301fb911e8 When submitting to Central Spamreport, include TextAnalysis and
bump sending of last commands from "last 10" to "last 20".
2025-07-12 17:21:56 +02:00
Val Lorentz 5aec83b444 Fix mismatched closing parenthesis (#314) 2025-07-06 14:53:00 +00:00
Bram Matthys ba8c587e44 Update to previous commit: disable by default, enable via set { send-isupport-updates yes; }
I totally agree with the goal to have this enabled, but let's do some more
testing with more clients first to see if they misbehave. Last thing I want
is a similar situation to when we were the first IRCd that sent "CAP DEL sasl"
and "CAP NEW sasl" when services went offline and online and it caused all
mIRC clients to reconnect. I don't expect this one to be so bad (also because
users would get the 005's when they typed /VERSION) but... let's test to be sure.

Should probably deploy this with enabled on irc.unrealircd.org and such :)
2025-07-06 09:28:38 +02:00
Bram Matthys cb17d58db0 Some small changes to previous commit:
* Calling from source is now in a separate function: int can_use_nick(Client *client, const char *nick)
* For hooks: don't free the reject reason, must use static storage like all other hooks
  (TODO: clarify in all hooks?)
* Move it up a bit, right before find_qline

TODO (not necessarily me :D):
* Make it an efunc
* Also call it from some other places that do find_qline, like rpc/user.c
* You may want to prod 3rd party modules like SANICK
2025-07-06 09:19:04 +02:00
Valerie Liu 6a6dd66c84 Add HOOKTYPE_CAN_USE_NICK to allow modules to reject certain nicks (#313)
* Add `HOOKTYPE_CAN_USE_NICK` for modules to disallow certain "internal-use" nicks
* Run the hook on local NICK commands
2025-07-06 07:10:58 +00:00
Valerie Liu 5d7feff725 Fix HOOKTYPE_PRE_CHANMSG refering to hooktype_can_send_to_user()
as an alternative. It should mention hooktype_can_send_to_channel() instead.
2025-04-14 15:30:51 +00:00
Bram Matthys 641413cfa9 Update Unicode block lists with Unicode 16.0.0 from 2024-02-02.
And provide instructions on how to generate this thing.
2025-03-24 09:32:50 +01:00
Bram Matthys cc75840189 Add unicode_count() crule, e.g. unicode_count('Emoticons')
This will return the number of characters that are in the unicode block
with that name.

spamfilter {
	rule "unicode_count('Emoticons')>2";
	target { private; channel; private-notice; channel-notice; }
	action block;
	reason "Too much emotion";
}

In this commit we also make it so we pass the ClientContext (including
clictx->textanalysis) in crule_context.
2025-03-23 18:14:32 +01:00
Bram Matthys 74e17b7a26 Make SPAMINFO show the UTF8 block names a text uses.
Example output:
*** SPAMINFO ***
This will show the original text and the deconfused text which can be used in a spamfilter block with input-conversion deconfused;
Original spam text: ẔŽŽẐ𝞕ȤℤΖℨℨ𝒁𝓩ẒŹƵᏃŻẒŽℨŹ𝒵𝛧Ż𝝛𝛧ℨℤ𝜡Ƶ𝞕𝘡ŹẐ𝑍ẔẐẐΖ𝜡Ẕ𝜡Ẕ𝞕ꓜ𝚭ᏃẐẔ𝙕
Deconfused spam text: ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
AntiMixedUTF8 points: 64
Number of Unicode characters in total: 50
Number of different Unicode blocks used: 8
Unicode Block breakdown (name: bytes [capped at 255]):
- Latin Extended-A: 8
- Latin Extended-B: 3
- Greek and Coptic: 2
- Cherokee: 2
- Latin Extended Additional: 12
- Letterlike Symbols: 6
- Lisu: 1
- Mathematical Alphanumeric Symbols: 16
2025-03-23 13:03:58 +01:00
Bram Matthys 6bd6e974d4 Add num_bytes and num_unicode_characters to TextAnalysis struct.
Also so you can easily put the unicode_blockmap[] in perspective
e.g. if you want to do percentages.
2025-03-23 12:43:01 +01:00
Bram Matthys 3142b57f77 Move text analysis to main command handler (parse2()).
In CommandAdd() the flag CMD_TEXTANALYSIS now means that the last
parameter of the command will run through the text analysis system.

This flag is set in PRIVMSG NOTICE PART QUIT AWAY SETNAME TOPIC
2025-03-23 12:28:43 +01:00
Bram Matthys 9b89166280 Add deconfused to TextAnalysis. Add ClientContext * to match_spamfilter().
Make match_spamfilter use the clictx->textanalysis->deconfused rather than
calculating its own. The latter will probably disappear altogether.

Unrelated but also fixed: properly set e->unicode_blocks.
2025-03-23 12:13:38 +01:00
Bram Matthys 9691a6d819 Create TextAnalysis framework (hook), this counts the unicode block
switches like antimixedutf8 did, and counts the number of characters
used per unicode block. Potentially more can be added later, this is
flexible and modules can add stuff (..well not yet.. the struct is
missing some members..).

Use it from antimixedutf8 so that it now uses the new code, which is
similar to what I made and then reverted in July 2023:
https://github.com/unrealircd/unrealircd/commit/3e2f668f10fccedfd035526d7b20d7ca6819a8ae
..except that it now calculated in src/modules/utf8functions.c.
But yeah, this needs more testing and possibly (default) score
adjustments to deal with false positives !! And a warning in release notes :D

Put the text analysis in ClientContext member textanalysis,
so typically accessed through clictx->textanalysis.
Note that this struct can (and often is) NULL, for example if it is
a remote client, if it is not a PRIVMSG/NOTICE (will improve later)
or if the utf8functions module is not loaded (to keep things optional).

BREAKING CHANGE is that ClientContext is now passed in the
HOOKTYPE_CAN_SEND_TO_CHANNEL and HOOKTYPE_CAN_SEND_TO_USER hooks.

So HOOKTYPE_CAN_SEND_TO_USER prototype changed from:
int hooktype_can_send_to_user(Client *client, Client *target, const char **text, const char **errmsg, SendType sendtype);
To:
int hooktype_can_send_to_user(Client *client, Client *target, const char **text, const char **errmsg, SendType sendtype, ClientContext *clictx);

And HOOKTYPE_CAN_SEND_TO_CHANNEL prototype changes from:
int hooktype_can_send_to_channel(Client *client, Channel *channel, Membership *member, const char **text, const char **errmsg, SendType sendtype);
To:
int hooktype_can_send_to_channel(Client *client, Channel *channel, Membership *member, const char **text, const char **errmsg, SendType sendtype, ClientContext *clictx);

A side-affect of this change for antimixedutf8 purposes is that,
while the analysis is only done once per line, the 'actions' are
performed for each target, so the action will run 4 times for
"PRIVMSG a,b,c,d :text" although that may not be important in
practice. Just mentioning.
2025-03-23 11:44:24 +01:00
Bram Matthys 6fd77ae572 Fix unreal_expand_string declaration 2025-03-23 08:12:40 +01:00
Bram Matthys e1fac402d5 Add spamfilter { input-conversion confusables; ..... } for UTF8 conversion
of lookalike characters to simple latin characters.

Also add SPAMINFO command so you can see the result of the conversion.
2025-03-22 08:31:22 +01:00