Skip to content

Feature/capsasl#66

Merged
Ratler merged 4 commits intoUndernetIRC:mainfrom
MrIron-no:feature/capsasl
Mar 27, 2026
Merged

Feature/capsasl#66
Ratler merged 4 commits intoUndernetIRC:mainfrom
MrIron-no:feature/capsasl

Conversation

@MrIron-no
Copy link
Copy Markdown
Contributor

  • Adds support for CAP LS 302 (incl CAP NEW / CAP DEL and cap-notify)
  • Added support for SASL authentication. Authentication layer set by new netconf feature.

@MrIron-no MrIron-no mentioned this pull request Mar 17, 2026
@MrIron-no MrIron-no force-pushed the feature/capsasl branch 6 times, most recently from dcb889a to 6da057e Compare March 26, 2026 08:31
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/s_err.c Outdated
{ ERR_SASLFAIL, ":%s", "904" },
/* 905 */
{ ERR_SASLTOOLONG, ":SASL message too long", "905" },
/* 909 */
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Misleading comment, should be 906. There seems to be quite a few mismatching comments, won't cause errors, but could cause confusion :)

Suggested change
/* 909 */
/* 906 */

ircd/m_sasl.c Outdated
if (!sasl_mechanism_supported(parv[1]))
return send_reply(cptr, RPL_SASLMECHS, netconf_str(NETCONF_SASL_MECHANISMS));

cli_sasl(cptr) = ++routing_ticker;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Quite unlikely to happen, but if ticker wraps, it goes back to 0, which is no session?

Safer approach could be

Suggested change
cli_sasl(cptr) = ++routing_ticker;
if (++routing_ticker == 0)
++routing_ticker;
cli_sasl(cptr) = routing_ticker;

ircd/sasl.c Outdated
return NULL;

/* Search through all local clients */
for (i = 0; i < MAXCONNECTIONS; i++) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is an costly O(n) operation that will always iterate configured max connections. I see one quick fix that makes it a little bit better, but it still becomes a scan operation (see suggestion below).

Suggested change
for (i = 0; i < MAXCONNECTIONS; i++) {
for (i = 0; i < HighestFd; i++) {

Another approach which eliminate scans completely, would be to refactor this part into storing client pointers in a struct like:

#define SASL_SESSION_MAX 256

struct SaslSession {
    uint64_t        cookie;
    struct Client*  client;
};

static struct SaslSession sasl_sessions[SASL_SESSION_MAX];

Add two methods to add and remove from the that hash table, and modify find_sasl_client() to do a direct lookup in sasl_sessions using the cookie, which eliminate the scan completely.

ircd/m_cap.c Outdated
if (capab_list[i].cap == (1u << cap)) {
cap_index = i;
cap_name = capab_list[i].name;
flags = capab_list[i].flags;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Assigned but never used?

ircd/m_cap.c Outdated
return;

/* Iterate through all local clients */
for (i = 0; i < MAXCONNECTIONS; i++) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another O(n) scan. Maybe use HighestFd instead.

ircd/m_cap.c Outdated
}

/* Iterate through all local clients */
for (i = 0; i < MAXCONNECTIONS; i++) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another O(n) scan. Maybe use HighestFd instead.

ircd/m_sasl.c Outdated
static void sasl_start_timeout(struct Client* cptr)
{
struct Timer* timer;
const char* timeout_str;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

timeout_str and timeout_seconds appear to be unused.

ircd/s_bsd.c Outdated
det_confs_butmask(cptr, 0);

/* Clean up SASL timer if it exists */
if (cli_sasl_timer(cptr) && t_active(cli_sasl_timer(cptr))) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is redundant check, should be enough with:

Suggested change
if (cli_sasl_timer(cptr) && t_active(cli_sasl_timer(cptr))) {
if (t_active(cli_sasl_timer(cptr))) {

send_reply(cptr, ERR_SASLFAIL, "Authentication timed out");

/* Clear SASL session */
cli_sasl(cptr) = 0;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this also clean up it's own timer?

E.g. adding timer_del(cli_sasl_timer(cptr));

@Ratler Ratler merged commit 0277167 into UndernetIRC:main Mar 27, 2026
1 check passed
@MrIron-no MrIron-no deleted the feature/capsasl branch March 27, 2026 15:57
Ratler added a commit that referenced this pull request Mar 27, 2026
Add integration tests for PR #66 (CAP LS 302, cap-notify, SASL capability).
Move pyproject.toml and uv.lock into tests/ so the Python test harness
is self-contained — run with `cd tests && uv sync && uv run pytest`.
Update all imports from `tests.irc_client` to `irc_client` and fix
conftest.py to run docker compose from the repo root.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants