Compare commits

...

10 commits

Author SHA1 Message Date
Firepup650
519d9bc0f4 Fix small typo
authdd -> authd
2024-04-13 15:42:39 -05:00
Doug Freed
dd3355732b m_starttls: advertise tls cap only if SSL is possible 2024-03-12 04:39:52 -05:00
Aaron Jones
1ccc642277 doc/reference.conf: document the auth::umodes configuration option
Fixes: 4d8088c386 ("Allow auth{} to apply extra umodes")
2024-01-16 15:54:29 +00:00
Aaron Jones
a9505057c5 MODRESTART/MODRELOAD: Defer reloading more quickly
Commit 41390bfe5f fixed a bug whereby the processing
of a MODRESTART command could result in a crash. The approach
taken in this fix was to defer the reloading of all modules
so that the call stack does not contain functions located in
modules that are being reloaded. It did this by scheduling a
one-shot timer event for 1 second in the future, in the absense
of any better deferral mechanism at the time. Timers are
processed by the event loop, which is core to IRCd and cannot
be reloaded.

Commit 59ea3c6753 introduced a mechanism to defer the
execution of a function until all events have been processed by
the event loop, in order to fix a REHASH bug that could result
in a crash due to closing and reopening listener sockets with a
pending socket connection event to process after the REHASH was
completed.

Rework commit 41390bfe5f to use the new deferral
mechanism introduced by commit 59ea3c6753 and do the
same for module reloads.
2023-11-20 14:01:33 +00:00
Aaron Jones
eaf922d427 doc/reference.conf: document connect::flags sctp 2023-11-20 13:55:21 +00:00
Aaron Jones
4d12e65469 extensions/invite_notify: make the NOTICE optional, configurable
This adds a configuration option that determines whether the NOTICE is
sent to clients that do not support the IRCv3 invite-notify capability.

Requested by LiberaChat MGM.
2023-11-08 13:12:49 +00:00
Aaron Jones
642c73dddb ircd/listener: return a fatal TLS alert for early rejected TLS clients
This is in furtherance of commit 3fdf26aa19 which added
functionality to reply with a TLS record layer alert for D-Lined TLS
clients. It turns out that there are other plaintext error messages
in this same function that should receive the same treatment.

Also move another error string to a variable and use a compile-time
optimised-out strlen for it too, to use the same approach as an
existing error string.

Finally, use a different alert (internal_error) for the case where
IRCd is simply unable to accept more connections.
2023-11-07 23:52:41 +00:00
Doug Freed
c1b01bf5ec client: refactor del_all_accepts to allow skipping own accept list
This allows reusing this function for other uses that just need to
remove this client from others' accept lists on nick change and not have
duplicates of this code everywhere
2023-11-06 17:31:44 +00:00
Aaron Jones
fd241b5fc8 modules/m_oper.c: give a better error message for failure to find o:line
The snotice sent to other opers can be misleading. For example, it will say
host mismatch even if the host is correct but the username is wrong, or if
the oper name given does not exist in the configuration.
2023-11-06 14:47:16 +00:00
Aaron Jones
3b24363e91 modules/m_challenge.c: give a better error message for failure to find o:line
The snotice sent to other opers can be misleading. For example, it will say
host mismatch even if the host is correct but the username is wrong, or if
the oper name given does not exist in the configuration.
2023-11-06 14:47:16 +00:00
20 changed files with 110 additions and 55 deletions

View file

@ -371,6 +371,7 @@ channel {
displayed_usercount = 3;
strip_topic_colors = no;
opmod_send_statusmsg = no;
invite_notify_notice = yes;
};
serverhide {

View file

@ -360,6 +360,11 @@ auth {
user = "*@198.51.100.0/24";
user = "*test@2001:db8:1:*";
/* umodes; the user mode character string to apply to users
* when they get placed into this auth block.
*/
#umodes = "+w";
/* auth_user: This allows specifying a username:password instead of
* just a password in PASS, so that a fixed user@host is not
* necessary for a specific auth{} block.
@ -605,6 +610,7 @@ connect "irc.uplink.com" {
* autoconn - automatically connect to this server
* topicburst - burst topics between servers
* ssl - ssl/tls encrypted server connections
* sctp - use SCTP instead of TCP to connect to the server
* no-export - marks the link as a no-export link (not exported to other links)
*/
flags = topicburst;
@ -815,6 +821,11 @@ channel {
/* ip_bans_through_vhost: should channel IP bans see through dynamic spoofed hosts? */
ip_bans_through_vhost = yes;
/* invite_notify_notice: when using extensions/invite_notify, should
* we send a NOTICE to clients that don't support IRCv3 invite-notify
*/
invite_notify_notice = yes;
};

View file

@ -4,6 +4,7 @@
#include <client.h>
#include <hash.h>
#include <send.h>
#include <s_conf.h>
#include <s_serv.h>
static const char inv_notify_desc[] = "Notifies channel on /invite and provides the invite-notify client capability";
@ -32,12 +33,16 @@ mapi_clist_av1 inv_notify_clist[] = { &invited_msgtab, NULL };
static void
invite_notify(struct Client *source, struct Client *target, struct Channel *channel)
{
sendto_channel_local_with_capability(source, CHFL_CHANOP, 0, CAP_INVITE_NOTIFY, channel,
":%s NOTICE %s :%s is inviting %s to %s.",
me.name, channel->chname, source->name, target->name, channel->chname);
sendto_channel_local_with_capability(source, CHFL_CHANOP, CAP_INVITE_NOTIFY, 0, channel,
":%s!%s@%s INVITE %s %s", source->name, source->username,
source->host, target->name, channel->chname);
if (!ConfigChannel.invite_notify_notice)
return;
sendto_channel_local_with_capability(source, CHFL_CHANOP, 0, CAP_INVITE_NOTIFY, channel,
":%s NOTICE %s :%s is inviting %s to %s.",
me.name, channel->chname, source->name, target->name, channel->chname);
}
static void

View file

@ -603,7 +603,7 @@ extern struct Client *find_named_person(const char *);
extern struct Client *next_client(struct Client *, const char *);
#define accept_message(s, t) ((s) == (t) || (rb_dlinkFind((s), &((t)->localClient->allow_list))))
extern void del_all_accepts(struct Client *client_p);
extern void del_all_accepts(struct Client *client_p, bool self_too);
extern void dead_link(struct Client *client_p, int sendqex);
extern int show_ip(struct Client *source_p, struct Client *target_p);

View file

@ -28,7 +28,7 @@
#define DELAYED_EXIT_TIME 10
void init_reject(void);
int check_reject(rb_fde_t *F, struct sockaddr *addr);
int check_reject(rb_fde_t *F, struct sockaddr *addr, bool ssl);
void add_reject(struct Client *, const char *mask1, const char *mask2, struct ConfItem *aconf, const char *reason);
int is_reject_ip(struct sockaddr *addr);
void flush_reject(void);

View file

@ -297,6 +297,7 @@ struct config_channel_entry
int strip_topic_colors;
int opmod_send_statusmsg;
int ip_bans_through_vhost;
int invite_notify_notice;
};
struct config_server_hide

View file

@ -396,7 +396,7 @@ static void
restart_authd_cb(rb_helper * helper)
{
iwarn("authd helper died - attempting to restart");
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "authdd helper died - attempting to restart");
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE, "authd helper died - attempting to restart");
if(helper != NULL)
{

View file

@ -1385,7 +1385,7 @@ exit_generic_client(struct Client *client_p, struct Client *source_p, struct Cli
}
/* Clean up allow lists */
del_all_accepts(source_p);
del_all_accepts(source_p, true);
whowas_add_history(source_p, 0);
whowas_off_history(source_p);
@ -1793,19 +1793,19 @@ count_remote_client_memory(size_t * count, size_t * remote_client_memory_used)
/*
* del_all_accepts
*
* inputs - pointer to exiting client
* inputs - pointer to exiting client, flag to include own allow_list
* output - NONE
* side effects - Walk through given clients allow_list and on_allow_list
* remove all references to this client
*/
void
del_all_accepts(struct Client *client_p)
del_all_accepts(struct Client *client_p, bool self_too)
{
rb_dlink_node *ptr;
rb_dlink_node *next_ptr;
struct Client *target_p;
if(MyClient(client_p) && client_p->localClient->allow_list.head)
if(self_too && MyClient(client_p) && client_p->localClient->allow_list.head)
{
/* clear this clients accept list, and remove them from
* everyones on_accept_list
@ -1813,6 +1813,7 @@ del_all_accepts(struct Client *client_p)
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->localClient->allow_list.head)
{
target_p = ptr->data;
rb_dlinkFindDestroy(client_p, &target_p->on_allow_list);
rb_dlinkDestroy(ptr, &client_p->localClient->allow_list);
}
@ -1822,6 +1823,13 @@ del_all_accepts(struct Client *client_p)
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, client_p->on_allow_list.head)
{
target_p = ptr->data;
/* If we're not doing our own, we're doing this because of a nick change.
* Skip those that would see the nick change anyway
*/
if(!self_too && has_common_channel(client_p, target_p))
continue;
rb_dlinkFindDestroy(client_p, &target_p->localClient->allow_list);
rb_dlinkDestroy(ptr, &client_p->on_allow_list);
}

View file

@ -581,13 +581,19 @@ accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, voi
static time_t last_oper_notice = 0;
int len;
static const char *allinuse = "ERROR :All connections in use\r\n";
static const char *toofast = "ERROR :Reconnecting too fast, throttled.\r\n";
static const unsigned char sslerrcode[] = {
static const unsigned char ssldeniederrcode[] = {
// SSLv3.0 Fatal Alert: Access Denied
0x15, 0x03, 0x00, 0x00, 0x02, 0x02, 0x31
};
static const unsigned char sslinternalerrcode[] = {
// SSLv3.0 Fatal Alert: Internal Error
0x15, 0x03, 0x00, 0x00, 0x02, 0x02, 0x50
};
if(listener->ssl && (!ircd_ssl_ok || !get_ssld_count()))
{
rb_close(F);
@ -608,7 +614,11 @@ accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, voi
last_oper_notice = rb_current_time();
}
rb_write(F, "ERROR :All connections in use\r\n", 31);
if(listener->ssl)
rb_write(F, sslinternalerrcode, sizeof(sslinternalerrcode));
else
rb_write(F, allinuse, strlen(allinuse));
rb_close(F);
return 0;
}
@ -625,7 +635,7 @@ accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, voi
if(listener->ssl)
{
rb_write(F, sslerrcode, sizeof(sslerrcode));
rb_write(F, ssldeniederrcode, sizeof(ssldeniederrcode));
}
else if(ConfigFileEntry.dline_with_reason)
{
@ -648,7 +658,7 @@ accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, voi
return 0;
}
if(check_reject(F, addr)) {
if(check_reject(F, addr, listener->ssl)) {
/* Reject the connection without closing the socket
* because it is now on the delay_exit list. */
return 0;
@ -656,7 +666,11 @@ accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, voi
if(throttle_add(addr))
{
rb_write(F, toofast, strlen(toofast));
if(listener->ssl)
rb_write(F, ssldeniederrcode, sizeof(ssldeniederrcode));
else
rb_write(F, toofast, strlen(toofast));
rb_close(F);
return 0;
}

View file

@ -2821,6 +2821,7 @@ static struct ConfEntry conf_channel_table[] =
{ "strip_topic_colors", CF_YESNO, NULL, 0, &ConfigChannel.strip_topic_colors },
{ "opmod_send_statusmsg", CF_YESNO, NULL, 0, &ConfigChannel.opmod_send_statusmsg },
{ "ip_bans_through_vhost", CF_YESNO, NULL, 0, &ConfigChannel.ip_bans_through_vhost },
{ "invite_notify_notice", CF_YESNO, NULL, 0, &ConfigChannel.invite_notify_notice },
{ "\0", 0, NULL, 0, NULL }
};

View file

@ -58,6 +58,7 @@ typedef struct _delay_data
rb_fde_t *F;
struct ConfItem *aconf;
const char *reason;
bool ssl;
} delay_t;
typedef struct _throttle
@ -92,28 +93,39 @@ reject_exit(void *unused)
delay_t *ddata;
static const char *errbuf = "ERROR :Closing Link: (*** Banned (cache))\r\n";
static const unsigned char ssldeniederrcode[] = {
// SSLv3.0 Fatal Alert: Access Denied
0x15, 0x03, 0x00, 0x00, 0x02, 0x02, 0x31
};
RB_DLINK_FOREACH_SAFE(ptr, ptr_next, delay_exit.head)
{
ddata = ptr->data;
*dynamic_reason = '\0';
if (ddata->ssl)
{
rb_write(ddata->F, ssldeniederrcode, sizeof(ssldeniederrcode));
}
else
{
*dynamic_reason = '\0';
if (ddata->aconf)
snprintf(dynamic_reason, sizeof dynamic_reason, form_str(ERR_YOUREBANNEDCREEP) "\r\n",
me.name, "*", get_user_ban_reason(ddata->aconf));
else if (ddata->reason)
snprintf(dynamic_reason, sizeof dynamic_reason, ":%s 465 %s :%s\r\n",
me.name, "*", ddata->reason);
if (*dynamic_reason)
rb_write(ddata->F, dynamic_reason, strlen(dynamic_reason));
rb_write(ddata->F, errbuf, strlen(errbuf));
}
if (ddata->aconf)
{
snprintf(dynamic_reason, sizeof dynamic_reason, form_str(ERR_YOUREBANNEDCREEP) "\r\n",
me.name, "*", get_user_ban_reason(ddata->aconf));
rb_write(ddata->F, dynamic_reason, strlen(dynamic_reason));
deref_conf(ddata->aconf);
}
else if (ddata->reason)
{
snprintf(dynamic_reason, sizeof dynamic_reason, ":%s 465 %s :%s\r\n",
me.name, "*", ddata->reason);
rb_write(ddata->F, dynamic_reason, strlen(dynamic_reason));
}
rb_write(ddata->F, errbuf, strlen(errbuf));
rb_close(ddata->F);
rb_free(ddata);
}
@ -228,7 +240,7 @@ add_reject(struct Client *client_p, const char *mask1, const char *mask2, struct
}
int
check_reject(rb_fde_t *F, struct sockaddr *addr)
check_reject(rb_fde_t *F, struct sockaddr *addr, bool ssl)
{
rb_patricia_node_t *pnode;
reject_t *rdata;
@ -276,6 +288,7 @@ check_reject(rb_fde_t *F, struct sockaddr *addr)
ddata->reason = NULL;
}
ddata->F = F;
ddata->ssl = ssl;
rb_dlinkAdd(ddata, &ddata->node, &delay_exit);
return 1;
}

View file

@ -829,7 +829,8 @@ set_default_conf(void)
ConfigChannel.disable_local_channels = false;
ConfigChannel.displayed_usercount = 3;
ConfigChannel.opmod_send_statusmsg = false;
ConfigChannel.ip_bans_through_vhost= true;
ConfigChannel.ip_bans_through_vhost = true;
ConfigChannel.invite_notify_notice = true;
ConfigChannel.autochanmodes = MODE_TOPICLIMIT | MODE_NOPRIVMSGS;

View file

@ -1725,7 +1725,7 @@ change_nick_user_host(struct Client *target_p, const char *nick, const char *use
if(changed)
{
monitor_signon(target_p);
del_all_accepts(target_p);
del_all_accepts(target_p, false);
}
}

View file

@ -286,7 +286,7 @@ do_modreload(struct Client *source_p, const char *module)
struct modreload *info = rb_malloc(sizeof *info);
strcpy(info->module, module);
strcpy(info->id, source_p->id);
rb_event_addonce("modules_do_reload", modules_do_reload, info, 1);
rb_defer(&modules_do_reload, info);
}
static void
@ -304,7 +304,7 @@ do_modrestart(struct Client *source_p)
*
* So, defer the restart to the event loop and return now.
*/
rb_event_addonce("modules_do_restart", modules_do_restart, NULL, 1);
rb_defer(&modules_do_restart, NULL);
}
static void

View file

@ -619,8 +619,6 @@ static void
change_local_nick(struct Client *client_p, struct Client *source_p,
char *nick, int dosend)
{
struct Client *target_p;
rb_dlink_node *ptr, *next_ptr;
struct Channel *chptr;
char note[NICKLEN + 10];
int samenick;
@ -704,20 +702,7 @@ change_local_nick(struct Client *client_p, struct Client *source_p,
/* Make sure everyone that has this client on its accept list
* loses that reference.
*/
/* we used to call del_all_accepts() here, but theres no real reason
* to clear a clients own list of accepted clients. So just remove
* them from everyone elses list --anfl
*/
RB_DLINK_FOREACH_SAFE(ptr, next_ptr, source_p->on_allow_list.head)
{
target_p = ptr->data;
if (!has_common_channel(source_p, target_p))
{
rb_dlinkFindDestroy(source_p, &target_p->localClient->allow_list);
rb_dlinkDestroy(ptr, &source_p->on_allow_list);
}
}
del_all_accepts(source_p, false);
snprintf(note, sizeof(note), "Nick: %s", nick);
rb_note(client_p->localClient->F, note);

View file

@ -226,8 +226,8 @@ m_challenge(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sou
if(ConfigFileEntry.failed_oper_notice)
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
"Failed CHALLENGE attempt - host mismatch by %s (%s@%s)",
source_p->name, source_p->username, source_p->host);
"Failed CHALLENGE attempt - user@host mismatch or no operator block for %s by %s (%s@%s)",
parv[1], source_p->name, source_p->username, source_p->host);
return;
}

View file

@ -636,6 +636,11 @@ static struct InfoStruct info_table[] = {
"Channel IP bans see through dynamic spoofs",
INFO_INTBOOL_YN(&ConfigChannel.ip_bans_through_vhost),
},
{
"invite_notify_notice",
"NOTICEs are sent to clients that do not support invite-notify",
INFO_INTBOOL_YN(&ConfigChannel.invite_notify_notice),
},
{
"hide_opers",
"Hide all opers from unprivileged users",

View file

@ -107,8 +107,8 @@ m_oper(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p
if(ConfigFileEntry.failed_oper_notice)
{
sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
"Failed OPER attempt - host mismatch by %s (%s@%s)",
source_p->name, source_p->username, source_p->host);
"Failed OPER attempt - user@host mismatch or no operator block for %s by %s (%s@%s)",
name, source_p->name, source_p->username, source_p->host);
}
return;

View file

@ -280,7 +280,10 @@ doit:
monitor_signon(target_p);
del_all_accepts(target_p);
/* Make sure everyone that has this client on its accept list
* loses that reference.
*/
del_all_accepts(target_p, false);
snprintf(note, sizeof(note), "Nick: %s", target_p->name);
rb_note(target_p->localClient->F, note);

View file

@ -45,7 +45,14 @@ mapi_clist_av1 starttls_clist[] = { &starttls_msgtab, NULL };
unsigned int CLICAP_TLS = 0;
static bool
tls_visible(struct Client *ignored)
{
return ircd_ssl_ok && get_ssld_count();
}
static struct ClientCapability capdata_tls = {
.visible = tls_visible,
.flags = CLICAP_FLAGS_PRIORITY,
};