From 510fe721c85b1a127a744dae5e57168324553899 Mon Sep 17 00:00:00 2001 From: MrIron Date: Fri, 17 Oct 2025 23:06:21 +0200 Subject: [PATCH 1/5] Network configuration feature will allow services to set network-wide options --- ircd/ircd_netconf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ircd/ircd_netconf.c b/ircd/ircd_netconf.c index ac89c3fe..f3b6f914 100644 --- a/ircd/ircd_netconf.c +++ b/ircd/ircd_netconf.c @@ -282,7 +282,7 @@ void config_burst(struct Client *cptr) entry->timestamp, entry->key, entry->value); } - Debug((DEBUG_INFO, "Config burst: %d entries sent to %s", + Debug((DEBUG_DEBUG, "Config burst: %d entries sent to %s", config_count(), cli_name(cptr))); } From 6e851b7b131e77a4b495f0ca6f0eef3b3a4abd23 Mon Sep 17 00:00:00 2001 From: MrIron Date: Wed, 25 Mar 2026 01:13:08 +0100 Subject: [PATCH 2/5] feat: SASL via netconf and IRCv3 CAP 302 (NEW/DEL) Introduce SASL authentication integrated with the network configuration (netconf) feature so services can drive auth settings across the mesh. Introduce IRCv3 CAP LS 302 support, including CAP NEW and CAP DEL (cap-notify), alongside the SASL client flow. --- ircd/m_sasl.c | 1 - 1 file changed, 1 deletion(-) diff --git a/ircd/m_sasl.c b/ircd/m_sasl.c index 5c971661..9693a936 100644 --- a/ircd/m_sasl.c +++ b/ircd/m_sasl.c @@ -95,7 +95,6 @@ #include - /** SASL timeout callback - called when a SASL session times out * @param[in] ev Timer event (contains client pointer in timer data) */ From 5db8642b0ad728be7d8f00a00c615a701d561b80 Mon Sep 17 00:00:00 2001 From: MrIron Date: Wed, 22 Oct 2025 09:41:15 +0200 Subject: [PATCH 3/5] Pass account onto iauth for sasl authentication during registration. Make the iauth session not terminate until after capability negotiations. --- include/s_auth.h | 1 + ircd/s_auth.c | 49 +++++++++++++++++++++++++++++++++++++++++++++++- ircd/sasl.c | 33 ++------------------------------ 3 files changed, 51 insertions(+), 32 deletions(-) diff --git a/include/s_auth.h b/include/s_auth.h index 657e925a..fd6e7cbe 100644 --- a/include/s_auth.h +++ b/include/s_auth.h @@ -39,6 +39,7 @@ extern int auth_set_pong(struct AuthRequest *auth, unsigned int cookie); extern int auth_set_user(struct AuthRequest *auth, const char *username, const char *hostname, const char *servername, const char *userinfo); extern int auth_set_nick(struct AuthRequest *auth, const char *nickname); extern int auth_set_password(struct AuthRequest *auth, const char *password); +extern int auth_set_account(struct AuthRequest *auth, const char *account_info); extern int auth_cap_start(struct AuthRequest *auth); extern int auth_cap_done(struct AuthRequest *auth); extern int auth_spoof_user(struct AuthRequest *auth, const char *username, const char *hostname, const char *ip); diff --git a/ircd/s_auth.c b/ircd/s_auth.c index dd762ca7..07e2aa26 100644 --- a/ircd/s_auth.c +++ b/ircd/s_auth.c @@ -363,6 +363,50 @@ static int auth_set_username(struct AuthRequest *auth) return exit_client(sptr, sptr, &me, "USER: Bad username"); } +/** Set account for user associated with \a auth. + * @param[in] auth Authorization request for client. + */ +int auth_set_account(struct AuthRequest *auth, const char *account_info) +{ + assert(auth != NULL); + + struct Client *sptr = auth->client; + char *account_copy = NULL, *account = NULL, *id_str = NULL, *flags_str = NULL, *extra = NULL; + + /* Parse account information: username:id:flags */ + DupString(account_copy, account_info); + if (!account_copy) + return 1; + + account = strtok(account_copy, ":"); + id_str = strtok(NULL, ":"); + flags_str = strtok(NULL, " "); + extra = strtok(NULL, ""); + + /* Copy account name to User structure */ + ircd_strncpy(cli_user(sptr)->account, account, ACCOUNTLEN); + + /* Parse account ID if provided */ + if (id_str) { + cli_user(sptr)->acc_id = strtoul(id_str, NULL, 10); + } + + if (flags_str) { + cli_user(sptr)->acc_flags = strtoul(flags_str, NULL, 10); + } + + SetAccount(sptr); + + /* Check for +x flag (host hiding) */ + if (extra && strstr(extra, "+x") && feature_bool(FEAT_HOST_HIDING)) { + SetHiddenHost(sptr); + } + + sendto_iauth(sptr, "A %s", cli_user(sptr)->account); + MyFree(account_copy); + return 0; +} + /** Notifies IAuth of a status change for the client. * * @param[in] auth Authorization request that was updated. @@ -399,7 +443,8 @@ static void iauth_notify(struct AuthRequest *auth, enum AuthRequestFlag flag) break; case AR_IAUTH_PENDING: - sendto_iauth(sptr, "T"); + if (!FlagHas(&auth->flags, AR_CAP_PENDING)) + sendto_iauth(sptr, "T"); break; default: @@ -1296,6 +1341,7 @@ int auth_cap_start(struct AuthRequest *auth) { assert(auth != NULL); FlagSet(&auth->flags, AR_CAP_PENDING); + sendto_iauth(auth->client, "c"); return 0; } @@ -1307,6 +1353,7 @@ int auth_cap_start(struct AuthRequest *auth) int auth_cap_done(struct AuthRequest *auth) { assert(auth != NULL); + sendto_iauth(auth->client, "e"); return check_auth_finished(auth, AR_CAP_PENDING); } diff --git a/ircd/sasl.c b/ircd/sasl.c index b602a10b..570d469a 100644 --- a/ircd/sasl.c +++ b/ircd/sasl.c @@ -35,6 +35,7 @@ #include "msg.h" #include "capab.h" #include "numnicks.h" +#include "s_auth.h" #include "s_debug.h" #include "s_bsd.h" #include "numeric.h" @@ -253,37 +254,7 @@ void sasl_send_xreply(struct Client* sptr, const char* routing, const char* repl * If this is a SASL authentication after registration, the username will be set by the service using AC. */ if (!IsUser(cli)) { - /* Parse account information: username:id:flags */ - DupString(account_copy, account_info); - if (!account_copy) - return; - - username = strtok(account_copy, ":"); - id_str = strtok(NULL, ":"); - flags_str = strtok(NULL, " "); - extra = strtok(NULL, ""); - - /* Copy account name to User structure */ - ircd_strncpy(cli_user(cli)->account, username, ACCOUNTLEN); - - /* Parse account ID if provided */ - if (id_str) { - cli_user(cli)->acc_id = strtoul(id_str, NULL, 10); - } - - /* Parse account flags if provided */ - if (flags_str) { - cli_user(cli)->acc_flags = strtoul(flags_str, NULL, 10); - } - - SetAccount(cli); - - /* Check for +x flag (host hiding) */ - if (extra && strstr(extra, "+x") && feature_bool(FEAT_HOST_HIDING)) { - SetHiddenHost(cli); - } - - MyFree(account_copy); + auth_set_account(cli_auth(cli), account_info); /** * For already registered users, we send RPL_LOGGEDIN. For non-registered users, From d56fc6e88be41dc7b75df99c0534e5d5cf2ef817 Mon Sep 17 00:00:00 2001 From: MrIron Date: Wed, 22 Oct 2025 11:06:20 +0200 Subject: [PATCH 4/5] Kill connections also having soft_done --- ircd/s_auth.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ircd/s_auth.c b/ircd/s_auth.c index 07e2aa26..6d75ed98 100644 --- a/ircd/s_auth.c +++ b/ircd/s_auth.c @@ -966,8 +966,7 @@ int auth_ping_timeout(struct Client *cptr) /* Check for iauth timeout. */ if (FlagHas(&auth->flags, AR_IAUTH_PENDING)) { - if (IAuthHas(iauth, IAUTH_REQUIRED) - && !FlagHas(&auth->flags, AR_IAUTH_SOFT_DONE)) { + if (IAuthHas(iauth, IAUTH_REQUIRED)) { sendheader(cptr, REPORT_FAIL_IAUTH); return exit_client_msg(cptr, cptr, &me, "Authorization Timeout"); } From 2b56110d64844f42e84c8b7b732f11c983334e46 Mon Sep 17 00:00:00 2001 From: MrIron Date: Fri, 24 Oct 2025 22:19:58 +0200 Subject: [PATCH 5/5] We only send cap start once to IAuth --- ircd/s_auth.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/ircd/s_auth.c b/ircd/s_auth.c index 6d75ed98..ed45b255 100644 --- a/ircd/s_auth.c +++ b/ircd/s_auth.c @@ -1339,8 +1339,10 @@ void auth_send_xreply(struct Client *sptr, const char *routing, int auth_cap_start(struct AuthRequest *auth) { assert(auth != NULL); - FlagSet(&auth->flags, AR_CAP_PENDING); - sendto_iauth(auth->client, "c"); + if (!FlagHas(&auth->flags, AR_CAP_PENDING)) { + FlagSet(&auth->flags, AR_CAP_PENDING); + sendto_iauth(auth->client, "c"); + } return 0; }