Compare commits

..

23 commits

Author SHA1 Message Date
Matthew Martin
5c01fc8bd7 Cast time_t to long long when printing 2022-07-01 03:43:36 -04:00
Jess Porter
12cee8ab78
global masktrace doesn't need to be an operspy action 2022-07-01 00:07:02 +01:00
Jess Porter
9d2e66c08d
ERROR instead of NOTICE for failed WEBIRC 2022-07-01 00:02:53 +01:00
Jess Porter
5a3e99829a
refuse opers setting an invalidly long k-line reason 2022-06-30 23:59:17 +01:00
Aaron Jones
3fdf26aa19 ircd/listener: return a TLS record layer alert to D-Lined TLS clients 2022-06-30 18:55:41 -04:00
Matthew Martin
c0d93064a6 chmode: Use original string when removing a mask 2022-06-30 21:00:46 +01:00
JailBird
62f6351d90 Illumos fixes
- getexecname(3) returns const char *
- pid_t is long
2022-06-29 20:28:11 -04:00
Matthew Martin
57aa79acb8 Normalize snprintf size to use sizeof where possible 2022-06-24 01:42:08 -04:00
Matthew Martin
e239ac8785 chmode: Fix snprintf size 2022-06-24 01:42:08 -04:00
Doug Freed
fae8f2517c valid_temp_time: more simplification and test fixes 2022-06-20 16:35:03 +01:00
Ed Kellett
4f46809305 valid_temp_time: simplify/correct overflow check
the logic for trying to detect the maximum value of time_t was broken;
since we target a lower maximum time anyway, just use that for the
overflow check
2022-06-20 16:35:03 +01:00
Jess Porter
8e239de831
don't truncate operspy WHO 2022-06-10 18:15:56 +01:00
jailbird777
e73eade529
Remove stray semicolons (#339) 2022-06-10 18:07:25 +01:00
Bernhard M. Wiedemann
2681c7d2e4 Normalize generation for reproducible builds
While working on reproducible builds for openSUSE, I found that
our package varied even when building in clean VMs
with as little non-determinism as possible.
This was because of

+++ solanum-0~ch560/ircd/version.c.last
@@ -25,7 +25,7 @@
 #include "serno.h"
 #include "stdinc.h"

-const char *generation = "6";
+const char *generation = "5";
 const char *creation = "1653004800";
 const char *ircd_version = PATCHLEVEL;
 const char *serno = SERNO;
2022-05-29 10:16:00 +01:00
Eric Mertens
48a06ae3d7
Add description parameter to auth blocks (#327) 2022-04-14 14:39:45 -07:00
Eric Mertens
b2fa28dd95
Apply cmode C to replies (#328) 2022-04-14 13:14:12 -07:00
Ed Kellett
ba95896969 Make valid_temp_time overflow-resistant 2022-04-13 01:09:27 +01:00
Ed Kellett
1fcdacb424 Test some edge cases of valid_temp_time 2022-04-13 01:09:27 +01:00
Stephen Bennett
2f596395fa
Make opers talking through +g controllable by user mode +M (#275)
Times out after 30 minutes, and adds oper:always_message privilege for
bots and services to always talk through +g
2022-04-12 17:54:58 -04:00
Jess Porter
099d470763
show IPs in remote /stats i (#312)
Co-authored-by: Eric Mertens <emertens@galois.com>
2022-04-08 10:06:43 -07:00
Aaron Jones
80d71456cf
authd/providers/opm.c: include <netinet/tcp.h> (#318)
This header defines the TCP_NODELAY flag, which this compilation
unit uses.

Other C libraries implicitly include this header from some other
header we are using (I have not investigated which), but musl's
system headers do not, which breaks building on musl.

Reported-by: 0x5c <dev@0x5c.io>
2022-04-08 09:47:18 -07:00
David Schultz
9dd98618d0
whowas.c: store account name in whowas (#323)
Co-authored-by: Eric Mertens <emertens@galois.com>
2022-04-01 14:58:43 -07:00
Ed Kellett
c2fdb023a9 Remove the subset ban restriction
I think this was always pretty questionable. You can set redundant bans
in various ways anyway, and preventing all of them would only make the
situation worse, as wide temporary bans would destroy narrow permanent
ones, for example.
2022-04-01 22:49:54 +01:00
38 changed files with 386 additions and 157 deletions

View file

@ -26,6 +26,8 @@
#include "notice.h" #include "notice.h"
#include "provider.h" #include "provider.h"
#include <netinet/tcp.h> // TCP_NODELAY
#define SELF_PID (opm_provider.id) #define SELF_PID (opm_provider.id)
#define OPM_READSIZE 128 #define OPM_READSIZE 128

View file

@ -514,7 +514,7 @@ static void do_query_number(struct DNSQuery *query, const struct rb_sockaddr_sto
request->name = (char *)rb_malloc(IRCD_RES_HOSTLEN + 1); request->name = (char *)rb_malloc(IRCD_RES_HOSTLEN + 1);
} }
build_rdns(request->queryname, IRCD_RES_HOSTLEN + 1, addr, NULL); build_rdns(request->queryname, sizeof request->queryname, addr, NULL);
request->type = T_PTR; request->type = T_PTR;
query_name(request); query_name(request);

View file

@ -344,6 +344,11 @@ listen {
/* auth {}: allow users to connect to the ircd (OLD I:) */ /* auth {}: allow users to connect to the ircd (OLD I:) */
auth { auth {
/* description: descriptive text to help recognize this auth block in
* stats i output.
*/
description = "example oper";
/* user: the user@host allowed to connect. Multiple IPv4/IPv6 user /* user: the user@host allowed to connect. Multiple IPv4/IPv6 user
* lines are permitted per auth block. This is matched against the * lines are permitted per auth block. This is matched against the
* hostname and IP address (using :: shortening for IPv6 and * hostname and IP address (using :: shortening for IPv6 and

View file

@ -41,7 +41,7 @@ static int eb_extended(const char *data, struct Client *client_p,
if (data == NULL) if (data == NULL)
return EXTBAN_INVALID; return EXTBAN_INVALID;
snprintf(buf, BUFSIZE, "%s!%s@%s#%s", snprintf(buf, sizeof buf, "%s!%s@%s#%s",
client_p->name, client_p->username, client_p->host, client_p->info); client_p->name, client_p->username, client_p->host, client_p->info);
return match(data, buf) ? EXTBAN_MATCH : EXTBAN_NOMATCH; return match(data, buf) ? EXTBAN_MATCH : EXTBAN_NOMATCH;

View file

@ -134,7 +134,7 @@ mo_ojoin(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
sendto_one(source_p, form_str(RPL_TOPIC), me.name, sendto_one(source_p, form_str(RPL_TOPIC), me.name,
source_p->name, chptr->chname, chptr->topic); source_p->name, chptr->chname, chptr->topic);
sendto_one(source_p, form_str(RPL_TOPICWHOTIME), me.name, sendto_one(source_p, form_str(RPL_TOPICWHOTIME), me.name,
source_p->name, chptr->chname, chptr->topic_info, chptr->topic_time); source_p->name, chptr->chname, chptr->topic_info, (long long)chptr->topic_time);
} }
source_p->localClient->last_join_time = rb_current_time(); source_p->localClient->last_join_time = rb_current_time();

View file

@ -106,17 +106,17 @@ mr_webirc(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
if (!IsConfDoSpoofIp(aconf) || irccmp(aconf->info.name, "webirc.")) if (!IsConfDoSpoofIp(aconf) || irccmp(aconf->info.name, "webirc."))
{ {
/* XXX */ /* XXX */
sendto_one(source_p, "NOTICE * :Not a CGI:IRC auth block"); exit_client(client_p, source_p, &me, "Not a CGI:IRC auth block");
return; return;
} }
if (EmptyString(aconf->passwd)) if (EmptyString(aconf->passwd))
{ {
sendto_one(source_p, "NOTICE * :CGI:IRC auth blocks must have a password"); exit_client(client_p, source_p, &me, "CGI:IRC auth blocks must have a password");
return; return;
} }
if (!IsSecure(source_p) && aconf->flags & CONF_FLAGS_NEED_SSL) if (!IsSecure(source_p) && aconf->flags & CONF_FLAGS_NEED_SSL)
{ {
sendto_one(source_p, "NOTICE * :Your CGI:IRC block requires TLS"); exit_client(client_p, source_p, &me, "Your CGI:IRC block requires TLS");
return; return;
} }
@ -129,13 +129,13 @@ mr_webirc(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sourc
if (encr == NULL || strcmp(encr, aconf->passwd)) if (encr == NULL || strcmp(encr, aconf->passwd))
{ {
sendto_one(source_p, "NOTICE * :CGI:IRC password incorrect"); exit_client(client_p, source_p, &me, "CGI:IRC password incorrect");
return; return;
} }
if (rb_inet_pton_sock(parv[4], &addr) <= 0) if (rb_inet_pton_sock(parv[4], &addr) <= 0)
{ {
sendto_one(source_p, "NOTICE * :Invalid IP"); exit_client(client_p, source_p, &me, "Invalid IP");
return; return;
} }

View file

@ -49,7 +49,7 @@
#define NUMERIC_STR_209 "Class %s %d" #define NUMERIC_STR_209 "Class %s %d"
#define NUMERIC_STR_212 "%s %u %lu :%u" #define NUMERIC_STR_212 "%s %u %lu :%u"
#define NUMERIC_STR_213 "C %s %s %s %d %s %s" #define NUMERIC_STR_213 "C %s %s %s %d %s %s"
#define NUMERIC_STR_215 "I %s %s %s@%s %d %s" #define NUMERIC_STR_215 "I %s %s %s@%s %d %s :%s"
#define NUMERIC_STR_216 "%c %s * %s :%s%s%s" #define NUMERIC_STR_216 "%c %s * %s :%s%s%s"
#define NUMERIC_STR_217 "%c %d %s :%s" #define NUMERIC_STR_217 "%c %d %s :%s"
#define NUMERIC_STR_218 "Y %s %d %d %d %u %d.%d %d.%d %u" #define NUMERIC_STR_218 "Y %s %d %d %d %u %d.%d %d.%d %u"
@ -101,11 +101,11 @@
#define NUMERIC_STR_323 ":%s 323 %s :End of /LIST" #define NUMERIC_STR_323 ":%s 323 %s :End of /LIST"
#define NUMERIC_STR_324 ":%s 324 %s %s %s" #define NUMERIC_STR_324 ":%s 324 %s %s %s"
#define NUMERIC_STR_325 ":%s 325 %s %s %s :is the current channel mode-lock" #define NUMERIC_STR_325 ":%s 325 %s %s %s :is the current channel mode-lock"
#define NUMERIC_STR_329 ":%s 329 %s %s %lu" #define NUMERIC_STR_329 ":%s 329 %s %s %lld"
#define NUMERIC_STR_330 "%s %s :is logged in as" #define NUMERIC_STR_330 "%s %s :is logged in as"
#define NUMERIC_STR_331 ":%s 331 %s %s :No topic is set." #define NUMERIC_STR_331 ":%s 331 %s %s :No topic is set."
#define NUMERIC_STR_332 ":%s 332 %s %s :%s" #define NUMERIC_STR_332 ":%s 332 %s %s :%s"
#define NUMERIC_STR_333 ":%s 333 %s %s %s %lu" #define NUMERIC_STR_333 ":%s 333 %s %s %s %lld"
#define NUMERIC_STR_337 "%s :%s" #define NUMERIC_STR_337 "%s :%s"
#define NUMERIC_STR_338 "%s %s :actually using host" #define NUMERIC_STR_338 "%s %s :actually using host"
#define NUMERIC_STR_341 ":%s 341 %s %s %s" #define NUMERIC_STR_341 ":%s 341 %s %s %s"

View file

@ -65,6 +65,7 @@ struct ConfItem
char *passwd; /* doubles as kline reason *ugh* */ char *passwd; /* doubles as kline reason *ugh* */
char *spasswd; /* Password to send. */ char *spasswd; /* Password to send. */
char *user; /* user part of user@host */ char *user; /* user part of user@host */
char *desc; /* description */
int port; int port;
time_t hold; /* Hold action until this time (calendar time) */ time_t hold; /* Hold action until this time (calendar time) */
time_t created; /* Creation time (for klines etc) */ time_t created; /* Creation time (for klines etc) */
@ -384,7 +385,7 @@ extern int detach_conf(struct Client *);
extern struct ConfItem *find_tkline(const char *, const char *, struct sockaddr *); extern struct ConfItem *find_tkline(const char *, const char *, struct sockaddr *);
extern char *show_iline_prefix(struct Client *, struct ConfItem *, char *); extern char *show_iline_prefix(struct Client *, struct ConfItem *, char *);
extern void get_printable_conf(struct ConfItem *, extern void get_printable_conf(struct ConfItem *,
char **, char **, const char **, char **, int *, char **); char **, char **, const char **, char **, int *, char **, char **);
extern char *get_user_ban_reason(struct ConfItem *aconf); extern char *get_user_ban_reason(struct ConfItem *aconf);
extern void get_printable_kline(struct Client *, struct ConfItem *, extern void get_printable_kline(struct Client *, struct ConfItem *,
char **, char **, char **, char **); char **, char **, char **, char **);

View file

@ -40,6 +40,8 @@
#include <openssl/rsa.h> #include <openssl/rsa.h>
#endif #endif
#define MAX_TEMP_TIME (52 * 7 * 24 * 60 * 60)
struct Client; struct Client;
struct ConfItem; struct ConfItem;

View file

@ -249,9 +249,7 @@ add_id(struct Client *source_p, struct Channel *chptr, const char *banid, const
char *realban = LOCAL_COPY(banid); char *realban = LOCAL_COPY(banid);
rb_dlink_node *ptr; rb_dlink_node *ptr;
/* dont let local clients overflow the banlist, or set redundant /* dont let local clients overflow the banlist */
* bans
*/
if(MyClient(source_p)) if(MyClient(source_p))
{ {
if((rb_dlink_list_length(&chptr->banlist) + rb_dlink_list_length(&chptr->exceptlist) + rb_dlink_list_length(&chptr->invexlist) + rb_dlink_list_length(&chptr->quietlist)) >= (unsigned long)((chptr->mode.mode & MODE_EXLIMIT) ? ConfigChannel.max_bans_large : ConfigChannel.max_bans)) if((rb_dlink_list_length(&chptr->banlist) + rb_dlink_list_length(&chptr->exceptlist) + rb_dlink_list_length(&chptr->invexlist) + rb_dlink_list_length(&chptr->quietlist)) >= (unsigned long)((chptr->mode.mode & MODE_EXLIMIT) ? ConfigChannel.max_bans_large : ConfigChannel.max_bans))
@ -260,26 +258,16 @@ add_id(struct Client *source_p, struct Channel *chptr, const char *banid, const
me.name, source_p->name, chptr->chname, realban); me.name, source_p->name, chptr->chname, realban);
return false; return false;
} }
RB_DLINK_FOREACH(ptr, list->head)
{
actualBan = ptr->data;
if(mask_match(actualBan->banstr, realban))
return false;
}
} }
/* dont let remotes set duplicates */
else /* don't let anyone set duplicate bans */
RB_DLINK_FOREACH(ptr, list->head)
{ {
RB_DLINK_FOREACH(ptr, list->head) actualBan = ptr->data;
{ if(!irccmp(actualBan->banstr, realban))
actualBan = ptr->data; return false;
if(!irccmp(actualBan->banstr, realban))
return false;
}
} }
if(IsPerson(source_p)) if(IsPerson(source_p))
sprintf(who, "%s!%s@%s", source_p->name, source_p->username, source_p->host); sprintf(who, "%s!%s@%s", source_p->name, source_p->username, source_p->host);
else else
@ -937,9 +925,9 @@ chm_ban(struct Client *source_p, struct Channel *chptr,
} }
if (removed && removed->forward) if (removed && removed->forward)
removed_mask_pos += snprintf(buf + old_removed_mask_pos, sizeof(buf), "%s$%s", removed->banstr, removed->forward) + 1; removed_mask_pos += snprintf(buf + old_removed_mask_pos, sizeof(buf) - old_removed_mask_pos, "%s$%s", removed->banstr, removed->forward) + 1;
else else
removed_mask_pos += rb_strlcpy(buf + old_removed_mask_pos, mask, sizeof(buf)) + 1; removed_mask_pos += rb_strlcpy(buf + old_removed_mask_pos, removed ? removed->banstr : mask, sizeof(buf)) + 1;
if (removed) if (removed)
{ {
free_ban(removed); free_ban(removed);

View file

@ -1573,11 +1573,11 @@ exit_local_server(struct Client *client_p, struct Client *source_p, struct Clien
remove_dependents(client_p, source_p, from, IsPerson(from) ? newcomment : comment, comment1); remove_dependents(client_p, source_p, from, IsPerson(from) ? newcomment : comment, comment1);
sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s was connected" sendto_realops_snomask(SNO_GENERAL, L_ALL, "%s was connected"
" for %ld seconds. %d/%d sendK/recvK.", " for %lld seconds. %d/%d sendK/recvK.",
source_p->name, (long) rb_current_time() - source_p->localClient->firsttime, sendk, recvk); source_p->name, (long long)(rb_current_time() - source_p->localClient->firsttime), sendk, recvk);
ilog(L_SERVER, "%s was connected for %ld seconds. %d/%d sendK/recvK.", ilog(L_SERVER, "%s was connected for %lld seconds. %d/%d sendK/recvK.",
source_p->name, (long) rb_current_time() - source_p->localClient->firsttime, sendk, recvk); source_p->name, (long long)(rb_current_time() - source_p->localClient->firsttime), sendk, recvk);
if(has_id(source_p)) if(has_id(source_p))
del_from_id_hash(source_p->id, source_p); del_from_id_hash(source_p->id, source_p);
@ -1844,7 +1844,7 @@ show_ip_conf(struct ConfItem *aconf, struct Client *source_p)
{ {
if(IsConfDoSpoofIp(aconf)) if(IsConfDoSpoofIp(aconf))
{ {
if(!ConfigFileEntry.hide_spoof_ips && MyOper(source_p)) if(!ConfigFileEntry.hide_spoof_ips && IsOper(source_p))
return 1; return 1;
return 0; return 0;
@ -1857,7 +1857,7 @@ int
show_ip_whowas(struct Whowas *whowas, struct Client *source_p) show_ip_whowas(struct Whowas *whowas, struct Client *source_p)
{ {
if(whowas->flags & WHOWAS_IP_SPOOFING) if(whowas->flags & WHOWAS_IP_SPOOFING)
if(ConfigFileEntry.hide_spoof_ips || !MyOper(source_p)) if(ConfigFileEntry.hide_spoof_ips || !IsOper(source_p))
return 0; return 0;
if(whowas->flags & WHOWAS_DYNSPOOF) if(whowas->flags & WHOWAS_DYNSPOOF)
if(!IsOper(source_p)) if(!IsOper(source_p))

View file

@ -723,7 +723,7 @@ show_iline_prefix(struct Client *sptr, struct ConfItem *aconf, char *name)
void void
report_auth(struct Client *client_p) report_auth(struct Client *client_p)
{ {
char *name, *host, *user, *classname; char *name, *host, *user, *classname, *desc;
const char *pass; const char *pass;
struct AddressRec *arec; struct AddressRec *arec;
struct ConfItem *aconf; struct ConfItem *aconf;
@ -739,7 +739,7 @@ report_auth(struct Client *client_p)
continue; continue;
get_printable_conf(aconf, &name, &host, &pass, &user, &port, get_printable_conf(aconf, &name, &host, &pass, &user, &port,
&classname); &classname, &desc);
if(!EmptyString(aconf->spasswd)) if(!EmptyString(aconf->spasswd))
pass = aconf->spasswd; pass = aconf->spasswd;
@ -748,7 +748,7 @@ report_auth(struct Client *client_p)
form_str(RPL_STATSILINE), form_str(RPL_STATSILINE),
name, pass, show_iline_prefix(client_p, aconf, user), name, pass, show_iline_prefix(client_p, aconf, user),
show_ip_conf(aconf, client_p) ? host : "255.255.255.255", show_ip_conf(aconf, client_p) ? host : "255.255.255.255",
port, classname); port, classname, desc);
} }
} }

View file

@ -756,8 +756,8 @@ solanum_main(int argc, char * const argv[])
check_splitmode_ev = rb_event_add("check_splitmode", check_splitmode, NULL, 5); check_splitmode_ev = rb_event_add("check_splitmode", check_splitmode, NULL, 5);
if(server_state_foreground) if(server_state_foreground)
inotice("now running in foreground mode from %s as pid %d ...", inotice("now running in foreground mode from %s as pid %ld ...",
ConfigFileEntry.dpath, getpid()); ConfigFileEntry.dpath, (long)getpid());
rb_lib_loop(0); rb_lib_loop(0);

View file

@ -572,8 +572,6 @@ accept_sslcallback(struct Client *client_p, int status)
return 0; /* use default handler if status != RB_OK */ return 0; /* use default handler if status != RB_OK */
} }
static const char *toofast = "ERROR :Reconnecting too fast, throttled.\r\n";
static int static int
accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, void *data) accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, void *data)
{ {
@ -583,6 +581,13 @@ accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, voi
static time_t last_oper_notice = 0; static time_t last_oper_notice = 0;
int len; int len;
static const char *toofast = "ERROR :Reconnecting too fast, throttled.\r\n";
static const unsigned char sslerrcode[] = {
// SSLv3.0 Fatal Alert: Access Denied
0x15, 0x03, 0x00, 0x00, 0x02, 0x02, 0x31
};
if(listener->ssl && (!ircd_ssl_ok || !get_ssld_count())) if(listener->ssl && (!ircd_ssl_ok || !get_ssld_count()))
{ {
rb_close(F); rb_close(F);
@ -618,7 +623,11 @@ accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, voi
{ {
ServerStats.is_ref++; ServerStats.is_ref++;
if(ConfigFileEntry.dline_with_reason) if(listener->ssl)
{
rb_write(F, sslerrcode, sizeof(sslerrcode));
}
else if(ConfigFileEntry.dline_with_reason)
{ {
len = snprintf(buf, sizeof(buf), "ERROR :*** Banned: %s\r\n", get_user_ban_reason(aconf)); len = snprintf(buf, sizeof(buf), "ERROR :*** Banned: %s\r\n", get_user_ban_reason(aconf));
if (len >= (int)(sizeof(buf)-1)) if (len >= (int)(sizeof(buf)-1))
@ -627,11 +636,14 @@ accept_precallback(rb_fde_t *F, struct sockaddr *addr, rb_socklen_t addrlen, voi
buf[sizeof(buf) - 2] = '\n'; buf[sizeof(buf) - 2] = '\n';
buf[sizeof(buf) - 1] = '\0'; buf[sizeof(buf) - 1] = '\0';
} }
rb_write(F, buf, strlen(buf));
} }
else else
{
strcpy(buf, "ERROR :You have been D-lined.\r\n"); strcpy(buf, "ERROR :You have been D-lined.\r\n");
rb_write(F, buf, strlen(buf));
}
rb_write(F, buf, strlen(buf));
rb_close(F); rb_close(F);
return 0; return 0;
} }

View file

@ -1037,6 +1037,9 @@ conf_end_auth(struct TopConf *tc)
if(yy_aconf->className) if(yy_aconf->className)
yy_tmp->className = rb_strdup(yy_aconf->className); yy_tmp->className = rb_strdup(yy_aconf->className);
if(yy_aconf->desc)
yy_tmp->desc = rb_strdup(yy_aconf->desc);
yy_tmp->flags = yy_aconf->flags; yy_tmp->flags = yy_aconf->flags;
yy_tmp->port = yy_aconf->port; yy_tmp->port = yy_aconf->port;
@ -1172,6 +1175,13 @@ conf_set_auth_spoof(void *data)
yy_aconf->flags |= CONF_FLAGS_SPOOF_IP; yy_aconf->flags |= CONF_FLAGS_SPOOF_IP;
} }
static void
conf_set_auth_desc(void *data)
{
rb_free(yy_aconf->desc);
yy_aconf->desc = rb_strdup(data);
}
static void static void
conf_set_auth_flags(void *data) conf_set_auth_flags(void *data)
{ {
@ -2318,7 +2328,7 @@ conf_report_error(const char *fmt, ...)
char msg[BUFSIZE + 1] = { 0 }; char msg[BUFSIZE + 1] = { 0 };
va_start(ap, fmt); va_start(ap, fmt);
vsnprintf(msg, BUFSIZE, fmt, ap); vsnprintf(msg, sizeof msg, fmt, ap);
va_end(ap); va_end(ap);
if (testing_conf) if (testing_conf)
@ -2338,7 +2348,7 @@ conf_report_warning(const char *fmt, ...)
char msg[BUFSIZE + 1] = { 0 }; char msg[BUFSIZE + 1] = { 0 };
va_start(ap, fmt); va_start(ap, fmt);
vsnprintf(msg, BUFSIZE, fmt, ap); vsnprintf(msg, sizeof msg, fmt, ap);
va_end(ap); va_end(ap);
if (testing_conf) if (testing_conf)
@ -2640,6 +2650,7 @@ static struct ConfEntry conf_auth_table[] =
{ "redirport", CF_INT, conf_set_auth_redir_port, 0, NULL }, { "redirport", CF_INT, conf_set_auth_redir_port, 0, NULL },
{ "flags", CF_STRING | CF_FLIST, conf_set_auth_flags, 0, NULL }, { "flags", CF_STRING | CF_FLIST, conf_set_auth_flags, 0, NULL },
{ "umodes", CF_QSTRING, conf_set_auth_umodes, 0, NULL}, { "umodes", CF_QSTRING, conf_set_auth_umodes, 0, NULL},
{ "description",CF_QSTRING, conf_set_auth_desc, 0, NULL},
{ "\0", 0, NULL, 0, NULL } { "\0", 0, NULL, 0, NULL }
}; };

View file

@ -100,7 +100,7 @@ reject_exit(void *unused)
if (ddata->aconf) if (ddata->aconf)
{ {
snprintf(dynamic_reason, BUFSIZE, form_str(ERR_YOUREBANNEDCREEP) "\r\n", snprintf(dynamic_reason, sizeof dynamic_reason, form_str(ERR_YOUREBANNEDCREEP) "\r\n",
me.name, "*", get_user_ban_reason(ddata->aconf)); me.name, "*", get_user_ban_reason(ddata->aconf));
rb_write(ddata->F, dynamic_reason, strlen(dynamic_reason)); rb_write(ddata->F, dynamic_reason, strlen(dynamic_reason));
@ -108,7 +108,7 @@ reject_exit(void *unused)
} }
else if (ddata->reason) else if (ddata->reason)
{ {
snprintf(dynamic_reason, BUFSIZE, ":%s 465 %s :%s\r\n", snprintf(dynamic_reason, sizeof dynamic_reason, ":%s 465 %s :%s\r\n",
me.name, "*", ddata->reason); me.name, "*", ddata->reason);
rb_write(ddata->F, dynamic_reason, strlen(dynamic_reason)); rb_write(ddata->F, dynamic_reason, strlen(dynamic_reason));
} }

View file

@ -154,6 +154,7 @@ free_conf(struct ConfItem *aconf)
rb_free(aconf->className); rb_free(aconf->className);
rb_free(aconf->user); rb_free(aconf->user);
rb_free(aconf->host); rb_free(aconf->host);
rb_free(aconf->desc);
if(IsConfBan(aconf)) if(IsConfBan(aconf))
operhash_delete(aconf->info.oper); operhash_delete(aconf->info.oper);
@ -1346,7 +1347,8 @@ get_oper_name(struct Client *client_p)
*/ */
void void
get_printable_conf(struct ConfItem *aconf, char **name, char **host, get_printable_conf(struct ConfItem *aconf, char **name, char **host,
const char **pass, char **user, int *port, char **classname) const char **pass, char **user, int *port,
char **classname, char **desc)
{ {
static char null[] = "<NULL>"; static char null[] = "<NULL>";
static char zero[] = "default"; static char zero[] = "default";
@ -1356,6 +1358,7 @@ get_printable_conf(struct ConfItem *aconf, char **name, char **host,
*pass = EmptyString(aconf->passwd) ? null : aconf->passwd; *pass = EmptyString(aconf->passwd) ? null : aconf->passwd;
*user = EmptyString(aconf->user) ? null : aconf->user; *user = EmptyString(aconf->user) ? null : aconf->user;
*classname = EmptyString(aconf->className) ? zero : aconf->className; *classname = EmptyString(aconf->className) ? zero : aconf->className;
*desc = CheckEmpty(aconf->desc);
*port = (int) aconf->port; *port = (int) aconf->port;
} }

View file

@ -689,40 +689,51 @@ valid_temp_time(const char *p)
while (*p) { while (*p) {
char *endp; char *endp;
int mul;
errno = 0; errno = 0;
current = strtol(p, &endp, 10); current = strtol(p, &endp, 10);
if (errno == ERANGE)
return -1;
if (endp == p) if (endp == p)
return -1; return -1;
if (current < 0)
return -1;
switch (*endp) { switch (*endp) {
case '\0': /* No unit was given so send it back as minutes */ case '\0': /* No unit was given so send it back as minutes */
case 'm': case 'm':
result += current * 60; mul = 60;
break; break;
case 'h': case 'h':
result += current * 3600; mul = 3600;
break; break;
case 'd': case 'd':
result += current * 86400; mul = 86400;
break; break;
case 'w': case 'w':
result += current * 604800; mul = 604800;
break; break;
default: default:
return -1; return -1;
} }
if (current > LONG_MAX / mul)
return MAX_TEMP_TIME;
current *= mul;
if (current > MAX_TEMP_TIME - result)
return MAX_TEMP_TIME;
result += current;
if (*endp == '\0') if (*endp == '\0')
break; break;
p = endp + 1; p = endp + 1;
} }
return MIN(result, 60 * 60 * 24 * 7 * 52); return MIN(result, MAX_TEMP_TIME);
} }
/* Propagated bans are expired elsewhere. */ /* Propagated bans are expired elsewhere. */

View file

@ -1640,7 +1640,7 @@ change_nick_user_host(struct Client *target_p, const char *nick, const char *use
if(do_qjm) if(do_qjm)
{ {
va_start(ap, format); va_start(ap, format);
vsnprintf(reason, 255, format, ap); vsnprintf(reason, sizeof reason, format, ap);
va_end(ap); va_end(ap);
sendto_common_channels_local_butone(target_p, NOCAPS, CLICAP_CHGHOST, ":%s!%s@%s QUIT :%s", sendto_common_channels_local_butone(target_p, NOCAPS, CLICAP_CHGHOST, ":%s!%s@%s QUIT :%s",

View file

@ -26,6 +26,7 @@ else \
{ print $1 " " $2 " " $3 " " $7 " at " $4 " " $5 " " $6 }}'` { print $1 " " $2 " " $3 " " $7 " at " $4 " " $5 " " $6 }}'`
else else
creation="$EXTERNAL_BUILD_TIMESTAMP" creation="$EXTERNAL_BUILD_TIMESTAMP"
generation=1
fi fi
$spitshell >version.c <<!SUB!THIS! $spitshell >version.c <<!SUB!THIS!

View file

@ -112,6 +112,7 @@ whowas_add_history(struct Client *client_p, int online)
rb_strlcpy(who->hostname, client_p->host, sizeof(who->hostname)); rb_strlcpy(who->hostname, client_p->host, sizeof(who->hostname));
rb_strlcpy(who->realname, client_p->info, sizeof(who->realname)); rb_strlcpy(who->realname, client_p->info, sizeof(who->realname));
rb_strlcpy(who->sockhost, client_p->sockhost, sizeof(who->sockhost)); rb_strlcpy(who->sockhost, client_p->sockhost, sizeof(who->sockhost));
rb_strlcpy(who->suser, client_p->user->suser, sizeof(who->suser));
who->flags = (IsIPSpoof(client_p) ? WHOWAS_IP_SPOOFING : 0) | who->flags = (IsIPSpoof(client_p) ? WHOWAS_IP_SPOOFING : 0) |
(IsDynSpoof(client_p) ? WHOWAS_DYNSPOOF : 0); (IsDynSpoof(client_p) ? WHOWAS_DYNSPOOF : 0);

View file

@ -52,7 +52,7 @@ rb_crypt(const char *key, const char *salt)
return rb_sha512_crypt(key, salt); return rb_sha512_crypt(key, salt);
default: default:
return NULL; return NULL;
}; }
} }
else else
return rb_des_crypt(key, salt); return rb_des_crypt(key, salt);

View file

@ -294,23 +294,21 @@ rb_event_init(void)
void void
rb_dump_events(void (*func) (char *, void *), void *ptr) rb_dump_events(void (*func) (char *, void *), void *ptr)
{ {
int len;
char buf[512]; char buf[512];
rb_dlink_node *dptr; rb_dlink_node *dptr;
struct ev_entry *ev; struct ev_entry *ev;
len = sizeof(buf);
snprintf(buf, len, "Last event to run: %s", last_event_ran); snprintf(buf, sizeof buf, "Last event to run: %s", last_event_ran);
func(buf, ptr); func(buf, ptr);
rb_strlcpy(buf, "Operation Next Execution", len); rb_strlcpy(buf, "Operation Next Execution", sizeof buf);
func(buf, ptr); func(buf, ptr);
RB_DLINK_FOREACH(dptr, event_list.head) RB_DLINK_FOREACH(dptr, event_list.head)
{ {
ev = dptr->data; ev = dptr->data;
snprintf(buf, len, "%-28s %-4ld seconds (frequency=%d)", ev->name, snprintf(buf, sizeof buf, "%-28s %-4lld seconds (frequency=%d)", ev->name,
ev->when - (long)rb_current_time(), (int)ev->frequency); (long long)(ev->when - rb_current_time()), (int)ev->frequency);
func(buf, ptr); func(buf, ptr);
} }
} }

View file

@ -172,7 +172,7 @@ int
rb_ports_supports_event(void) rb_ports_supports_event(void)
{ {
return 1; return 1;
}; }
void void
rb_ports_init_event(void) rb_ports_init_event(void)

View file

@ -162,7 +162,7 @@ rb_path_to_self(void)
{ {
static char path_buf[4096]; static char path_buf[4096];
#if defined(HAVE_GETEXECNAME) #if defined(HAVE_GETEXECNAME)
char *s = getexecname(); const char *s = getexecname();
if (s == NULL) if (s == NULL)
return NULL; return NULL;
realpath(s, path_buf); realpath(s, path_buf);

View file

@ -51,10 +51,12 @@ chm_noctcp_process(void *data_)
{ {
hook_data_privmsg_channel *data = data_; hook_data_privmsg_channel *data = data_;
/* don't waste CPU if message is already blocked */ /* don't waste CPU if message is already blocked */
if (data->approved || data->msgtype == MESSAGE_TYPE_NOTICE) if (data->approved)
return; return;
if (*data->text == '\001' && rb_strncasecmp(data->text + 1, "ACTION ", 7) && data->chptr->mode.mode & mode_noctcp) if (*data->text == '\001' &&
data->chptr->mode.mode & mode_noctcp &&
!(data->msgtype == MESSAGE_TYPE_PRIVMSG && !rb_strncasecmp(data->text + 1, "ACTION ", 7)))
{ {
sendto_one_numeric(data->source_p, ERR_CANNOTSENDTOCHAN, form_str(ERR_CANNOTSENDTOCHAN), data->chptr->chname); sendto_one_numeric(data->source_p, ERR_CANNOTSENDTOCHAN, form_str(ERR_CANNOTSENDTOCHAN), data->chptr->chname);
data->approved = ERR_CANNOTSENDTOCHAN; data->approved = ERR_CANNOTSENDTOCHAN;

View file

@ -374,7 +374,7 @@ m_join(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p
sendto_one(source_p, form_str(RPL_TOPICWHOTIME), sendto_one(source_p, form_str(RPL_TOPICWHOTIME),
me.name, source_p->name, chptr->chname, me.name, source_p->name, chptr->chname,
chptr->topic_info, chptr->topic_info,
(unsigned long)chptr->topic_time); (long long)chptr->topic_time);
} }
channel_member_names(chptr, source_p, 1); channel_member_names(chptr, source_p, 1);

View file

@ -132,7 +132,7 @@ m_mode(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_p
operspy ? channel_modes(chptr, &me) : channel_modes(chptr, source_p)); operspy ? channel_modes(chptr, &me) : channel_modes(chptr, source_p));
sendto_one(source_p, form_str(RPL_CREATIONTIME), sendto_one(source_p, form_str(RPL_CREATIONTIME),
me.name, source_p->name, parv[1], chptr->channelts); me.name, source_p->name, parv[1], (long long)chptr->channelts);
} }
else else
{ {

View file

@ -340,20 +340,10 @@ mo_masktrace(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *so
const char *parv[]) const char *parv[])
{ {
char *name, *username, *hostname, *gecos; char *name, *username, *hostname, *gecos;
const char *mask;
int operspy = 0;
mask = parv[1];
name = LOCAL_COPY(parv[1]); name = LOCAL_COPY(parv[1]);
collapse(name); collapse(name);
if(IsOperSpy(source_p) && parv[1][0] == '!')
{
name++;
mask++;
operspy = 1;
}
if(parc > 2 && !EmptyString(parv[2])) if(parc > 2 && !EmptyString(parv[2]))
{ {
gecos = LOCAL_COPY(parv[2]); gecos = LOCAL_COPY(parv[2]);
@ -383,21 +373,6 @@ mo_masktrace(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *so
return; return;
} }
if(operspy) { match_masktrace(source_p, &global_client_list, username, hostname, name, gecos);
if (!ConfigFileEntry.operspy_dont_care_user_info)
{
char buf[512];
rb_strlcpy(buf, mask, sizeof(buf));
if(!EmptyString(gecos)) {
rb_strlcat(buf, " ", sizeof(buf));
rb_strlcat(buf, gecos, sizeof(buf));
}
report_operspy(source_p, "MASKTRACE", buf);
}
match_masktrace(source_p, &global_client_list, username, hostname, name, gecos);
} else
match_masktrace(source_p, &lclient_list, username, hostname, name, gecos);
sendto_one_numeric(source_p, RPL_ENDOFTRACE, form_str(RPL_ENDOFTRACE), me.name); sendto_one_numeric(source_p, RPL_ENDOFTRACE, form_str(RPL_ENDOFTRACE), me.name);
} }

View file

@ -165,6 +165,11 @@ mo_kline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
} }
reason = LOCAL_COPY(parv[loc]); reason = LOCAL_COPY(parv[loc]);
if(strlen(reason) > BANREASONLEN)
{
sendto_one_notice(source_p, ":K-Line reason exceeds %d characters", BANREASONLEN);
return;
}
if(parse_netmask_strict(host, NULL, NULL) == HM_ERROR) if(parse_netmask_strict(host, NULL, NULL) == HM_ERROR)
{ {
@ -234,9 +239,6 @@ mo_kline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source
aconf->port = 0; aconf->port = 0;
aconf->info.oper = operhash_add(get_oper_name(source_p)); aconf->info.oper = operhash_add(get_oper_name(source_p));
if(strlen(reason) > BANREASONLEN)
reason[BANREASONLEN] = '\0';
/* Look for an oper reason */ /* Look for an oper reason */
if((oper_reason = strchr(reason, '|')) != NULL) if((oper_reason = strchr(reason, '|')) != NULL)
{ {

View file

@ -108,7 +108,7 @@ dump_map(struct Client *client_p, struct Client *root_p, char *pbuf)
} }
frac = (1000 * rb_dlink_list_length(&root_p->serv->users) + Count.total / 2) / Count.total; frac = (1000 * rb_dlink_list_length(&root_p->serv->users) + Count.total / 2) / Count.total;
snprintf(buf + USER_COL, BUFSIZE - USER_COL, snprintf(buf + USER_COL, sizeof buf - USER_COL,
" | Users: %5lu (%2d.%1d%%)", rb_dlink_list_length(&root_p->serv->users), " | Users: %5lu (%2d.%1d%%)", rb_dlink_list_length(&root_p->serv->users),
frac / 10, frac % 10); frac / 10, frac % 10);
@ -172,7 +172,7 @@ flattened_map(struct Client *client_p)
} }
} }
snprintf(buf + USER_COL, BUFSIZE - USER_COL, snprintf(buf + USER_COL, sizeof buf - USER_COL,
" | Users: %5lu (%4.1f%%)", rb_dlink_list_length(&me.serv->users), " | Users: %5lu (%4.1f%%)", rb_dlink_list_length(&me.serv->users),
100 * (float) rb_dlink_list_length(&me.serv->users) / (float) Count.total); 100 * (float) rb_dlink_list_length(&me.serv->users) / (float) Count.total);
@ -210,7 +210,7 @@ flattened_map(struct Client *client_p)
} }
} }
snprintf(buf + USER_COL, BUFSIZE - USER_COL, snprintf(buf + USER_COL, sizeof buf - USER_COL,
" | Users: %5lu (%4.1f%%)", rb_dlink_list_length(&target_p->serv->users), " | Users: %5lu (%4.1f%%)", rb_dlink_list_length(&target_p->serv->users),
100 * (float) rb_dlink_list_length(&target_p->serv->users) / (float) Count.total); 100 * (float) rb_dlink_list_length(&target_p->serv->users) / (float) Count.total);

View file

@ -237,7 +237,7 @@ scan_umodes(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sou
if (mask != NULL) if (mask != NULL)
{ {
snprintf(maskbuf, BUFSIZE, "%s!%s@%s", snprintf(maskbuf, sizeof maskbuf, "%s!%s@%s",
target_p->name, target_p->username, target_p->host); target_p->name, target_p->username, target_p->host);
if (!match(mask, maskbuf)) if (!match(mask, maskbuf))

View file

@ -453,7 +453,7 @@ stats_deny (struct Client *source_p)
static void static void
stats_exempt(struct Client *source_p) stats_exempt(struct Client *source_p)
{ {
char *name, *host, *user, *classname; char *name, *host, *user, *classname, *desc;
const char *pass; const char *pass;
struct AddressRec *arec; struct AddressRec *arec;
struct ConfItem *aconf; struct ConfItem *aconf;
@ -474,7 +474,7 @@ stats_exempt(struct Client *source_p)
{ {
aconf = arec->aconf; aconf = arec->aconf;
get_printable_conf (aconf, &name, &host, &pass, get_printable_conf (aconf, &name, &host, &pass,
&user, &port, &classname); &user, &port, &classname, &desc);
sendto_one_numeric(source_p, RPL_STATSDLINE, sendto_one_numeric(source_p, RPL_STATSDLINE,
form_str(RPL_STATSDLINE), form_str(RPL_STATSDLINE),
@ -533,7 +533,7 @@ stats_auth (struct Client *source_p)
else if((ConfigFileEntry.stats_i_oper_only == 1) && !IsOperGeneral (source_p)) else if((ConfigFileEntry.stats_i_oper_only == 1) && !IsOperGeneral (source_p))
{ {
struct ConfItem *aconf; struct ConfItem *aconf;
char *name, *host, *user, *classname; char *name, *host, *user, *classname, *desc;
const char *pass = "*"; const char *pass = "*";
int port; int port;
@ -550,13 +550,13 @@ stats_auth (struct Client *source_p)
if(aconf == NULL) if(aconf == NULL)
return; return;
get_printable_conf (aconf, &name, &host, &pass, &user, &port, &classname); get_printable_conf (aconf, &name, &host, &pass, &user, &port, &classname, &desc);
if(!EmptyString(aconf->spasswd)) if(!EmptyString(aconf->spasswd))
pass = aconf->spasswd; pass = aconf->spasswd;
sendto_one_numeric(source_p, RPL_STATSILINE, form_str(RPL_STATSILINE), sendto_one_numeric(source_p, RPL_STATSILINE, form_str(RPL_STATSILINE),
name, pass, show_iline_prefix(source_p, aconf, user), name, pass, show_iline_prefix(source_p, aconf, user),
host, port, classname); host, port, classname, desc);
} }
/* Theyre opered, or allowed to see all auth blocks */ /* Theyre opered, or allowed to see all auth blocks */
@ -908,8 +908,8 @@ stats_ssld_foreach(void *data, pid_t pid, int cli_count, enum ssld_status status
struct Client *source_p = data; struct Client *source_p = data;
sendto_one_numeric(source_p, RPL_STATSDEBUG, sendto_one_numeric(source_p, RPL_STATSDEBUG,
"S :%u %c %u :%s", "S :%ld %c %u :%s",
pid, (long)pid,
status == SSLD_DEAD ? 'D' : (status == SSLD_SHUTDOWN ? 'S' : 'A'), status == SSLD_DEAD ? 'D' : (status == SSLD_SHUTDOWN ? 'S' : 'A'),
cli_count, cli_count,
version); version);
@ -960,8 +960,8 @@ stats_usage (struct Client *source_p)
(int) (rus.ru_stime.tv_sec % 60)); (int) (rus.ru_stime.tv_sec % 60));
sendto_one_numeric(source_p, RPL_STATSDEBUG, sendto_one_numeric(source_p, RPL_STATSDEBUG,
"R :RSS %ld ShMem %ld Data %ld Stack %ld", "R :RSS %ld ShMem %ld Data %ld Stack %ld",
rus.ru_maxrss, (rus.ru_ixrss / rup), rus.ru_maxrss, (long)(rus.ru_ixrss / rup),
(rus.ru_idrss / rup), (rus.ru_isrss / rup)); (long)(rus.ru_idrss / rup), (long)(rus.ru_isrss / rup));
sendto_one_numeric(source_p, RPL_STATSDEBUG, sendto_one_numeric(source_p, RPL_STATSDEBUG,
"R :Swaps %d Reclaims %d Faults %d", "R :Swaps %d Reclaims %d Faults %d",
(int) rus.ru_nswap, (int) rus.ru_minflt, (int) rus.ru_majflt); (int) rus.ru_nswap, (int) rus.ru_minflt, (int) rus.ru_majflt);

View file

@ -235,7 +235,8 @@ mo_testline(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *sou
sendto_one_numeric(source_p, RPL_STATSILINE, form_str(RPL_STATSILINE), sendto_one_numeric(source_p, RPL_STATSILINE, form_str(RPL_STATSILINE),
aconf->info.name, EmptyString(aconf->spasswd) ? "<NULL>" : aconf->spasswd, aconf->info.name, EmptyString(aconf->spasswd) ? "<NULL>" : aconf->spasswd,
show_iline_prefix(source_p, aconf, aconf->user), show_iline_prefix(source_p, aconf, aconf->user),
aconf->host, aconf->port, aconf->className); aconf->host, aconf->port, aconf->className,
CheckEmpty(aconf->desc));
return; return;
} }

View file

@ -173,7 +173,7 @@ m_topic(struct MsgBuf *msgbuf_p, struct Client *client_p, struct Client *source_
sendto_one(source_p, form_str(RPL_TOPICWHOTIME), sendto_one(source_p, form_str(RPL_TOPICWHOTIME),
me.name, source_p->name, chptr->chname, me.name, source_p->name, chptr->chname,
chptr->topic_info, chptr->topic_info,
(unsigned long)chptr->topic_time); (long long)chptr->topic_time);
} }
} }
} }

View file

@ -367,8 +367,12 @@ who_global(struct Client *source_p, const char *mask, int server_oper, int opers
who_common_channel(source_p, msptr->chptr, mask, server_oper, &maxmatches, fmt); who_common_channel(source_p, msptr->chptr, mask, server_oper, &maxmatches, fmt);
} }
} }
else if (!ConfigFileEntry.operspy_dont_care_user_info) else
report_operspy(source_p, "WHO", mask); {
maxmatches = INT_MAX;
if (!ConfigFileEntry.operspy_dont_care_user_info)
report_operspy(source_p, "WHO", mask);
}
/* second, list all matching visible clients and clear all marks /* second, list all matching visible clients and clear all marks
* on invisible clients * on invisible clients

View file

@ -44,49 +44,78 @@
#include "supported.h" #include "supported.h"
#include "logger.h" #include "logger.h"
static int
um_callerid_modinit(void)
{
user_modes['g'] = find_umode_slot();
if (!user_modes['g'])
{
ierror("um_callerid: unable to allocate usermode slot for +g; unloading module.");
return -1;
}
user_modes['G'] = find_umode_slot();
if (!user_modes['G'])
{
user_modes['g'] = 0;
ierror("um_callerid: unable to allocate usermode slot for +G; unloading module.");
return -1;
}
construct_umodebuf();
add_isupport("CALLERID", isupport_umode, "g");
return 0;
}
static void
um_callerid_moddeinit(void)
{
user_modes['g'] = 0;
user_modes['G'] = 0;
construct_umodebuf();
delete_isupport("CALLERID");
}
#define IsSetStrictCallerID(c) ((c->umodes & user_modes['g']) == user_modes['g']) #define IsSetStrictCallerID(c) ((c->umodes & user_modes['g']) == user_modes['g'])
#define IsSetRelaxedCallerID(c) ((c->umodes & user_modes['G']) == user_modes['G']) #define IsSetRelaxedCallerID(c) ((c->umodes & user_modes['G']) == user_modes['G'])
#define IsSetAnyCallerID(c) (IsSetStrictCallerID(c) || IsSetRelaxedCallerID(c)) #define IsSetAnyCallerID(c) (IsSetStrictCallerID(c) || IsSetRelaxedCallerID(c))
#define IsSetTalkThroughCallerID(c) ((c->umodes & user_modes['M']) == user_modes['M'])
static const char um_callerid_desc[] = static const char um_callerid_desc[] =
"Provides usermodes +g and +G which restrict messages from unauthorized users."; "Provides usermodes +g and +G which restrict messages from unauthorized users.";
struct CallerIDOverrideSession {
rb_dlink_node node;
struct Client *client;
time_t deadline;
};
static rb_dlink_list callerid_overriding_opers = { NULL, NULL, 0 };
struct ev_entry *expire_callerid_override_deadlines_ev = NULL;
static void
update_session_deadline(struct Client *source_p)
{
struct CallerIDOverrideSession *session_p = NULL;
rb_dlink_node *n;
RB_DLINK_FOREACH(n, callerid_overriding_opers.head)
{
struct CallerIDOverrideSession *s = n->data;
if (s->client == source_p)
{
session_p = s;
break;
}
}
if (session_p != NULL)
{
rb_dlinkDelete(&session_p->node, &callerid_overriding_opers);
}
else
{
session_p = rb_malloc(sizeof(struct CallerIDOverrideSession));
session_p->client = source_p;
}
session_p->deadline = rb_current_time() + 1800;
rb_dlinkAddTail(session_p, &session_p->node, &callerid_overriding_opers);
}
static void
expire_callerid_override_deadlines(void *unused)
{
rb_dlink_node *n, *tn;
RB_DLINK_FOREACH_SAFE(n, tn, callerid_overriding_opers.head)
{
struct CallerIDOverrideSession *session_p = n->data;
if (session_p->deadline >= rb_current_time())
{
break;
}
else
{
const char *parv[4] = {session_p->client->name, session_p->client->name, "-M", NULL};
user_mode(session_p->client, session_p->client, 3, parv);
}
}
}
static bool static bool
allow_message(struct Client *source_p, struct Client *target_p) allow_message(struct Client *source_p, struct Client *target_p)
{ {
@ -105,7 +134,7 @@ allow_message(struct Client *source_p, struct Client *target_p)
return true; return true;
/* XXX: controversial? allow opers to send through +g */ /* XXX: controversial? allow opers to send through +g */
if (MayHavePrivilege(source_p, "oper:message")) if (IsSetTalkThroughCallerID(source_p) || MayHavePrivilege(source_p, "oper:always_message"))
return true; return true;
if (accept_message(source_p, target_p)) if (accept_message(source_p, target_p))
@ -227,11 +256,156 @@ h_hdl_privmsg_user(void *vdata)
data->approved = ERR_TARGUMODEG; data->approved = ERR_TARGUMODEG;
} }
static void
check_umode_change(void *vdata)
{
hook_data_umode_changed *data = (hook_data_umode_changed *)vdata;
bool changed = false;
struct Client *source_p = data->client;
if (!MyClient(source_p))
return;
if (data->oldumodes & UMODE_OPER && !IsOper(source_p))
source_p->umodes &= ~user_modes['M'];
changed = ((data->oldumodes ^ source_p->umodes) & user_modes['M']);
if (changed && source_p->umodes & user_modes['M'])
{
if (!HasPrivilege(source_p, "oper:message"))
{
sendto_one_notice(source_p, ":*** You need oper:message privilege for +M");
source_p->umodes &= ~user_modes['M'];
return;
}
update_session_deadline(source_p);
}
else if (changed)
{
// Unsetting +M; remove the timeout session
rb_dlink_node *n, *tn;
RB_DLINK_FOREACH_SAFE(n, tn, callerid_overriding_opers.head)
{
struct CallerIDOverrideSession *session_p = n->data;
if (session_p->client != source_p)
continue;
rb_dlinkDelete(n, &callerid_overriding_opers);
rb_free(session_p);
}
}
}
static void check_priv_change(void *vdata)
{
hook_data_priv_change *data = (hook_data_priv_change*)vdata;
struct Client *source_p = data->client;
const char *fakeparv[4];
if (!MyClient(source_p))
return;
if (source_p->umodes & user_modes['M'] && !HasPrivilege(source_p, "oper:message"))
{
sendto_one_notice(source_p, ":*** You need oper:message privilege for +M");
fakeparv[0] = fakeparv[1] = source_p->name;
fakeparv[2] = "-M";
fakeparv[3] = NULL;
user_mode(source_p, source_p, 3, fakeparv);
}
}
static void
handle_client_exit(void *vdata)
{
hook_data_client_exit *data = (hook_data_client_exit *) vdata;
rb_dlink_node *n, *tn;
struct Client *source_p = data->target;
RB_DLINK_FOREACH_SAFE(n, tn, callerid_overriding_opers.head)
{
struct CallerIDOverrideSession *session_p = n->data;
if (session_p->client != source_p)
continue;
rb_dlinkDelete(n, &callerid_overriding_opers);
rb_free(session_p);
}
}
static mapi_hfn_list_av1 um_callerid_hfnlist[] = { static mapi_hfn_list_av1 um_callerid_hfnlist[] = {
{ "umode_changed", check_umode_change },
{ "priv_change", check_priv_change },
{ "invite", h_hdl_invite }, { "invite", h_hdl_invite },
{ "privmsg_user", h_hdl_privmsg_user }, { "privmsg_user", h_hdl_privmsg_user },
{ "client_exit", handle_client_exit },
{ NULL, NULL } { NULL, NULL }
}; };
static int
um_callerid_modinit(void)
{
rb_dlink_node *ptr;
user_modes['g'] = find_umode_slot();
if (!user_modes['g'])
{
ierror("um_callerid: unable to allocate usermode slot for +g; unloading module.");
return -1;
}
user_modes['G'] = find_umode_slot();
if (!user_modes['G'])
{
user_modes['g'] = 0;
ierror("um_callerid: unable to allocate usermode slot for +G; unloading module.");
return -1;
}
user_modes['M'] = find_umode_slot();
if (!user_modes['M'])
{
user_modes['g'] = 0;
user_modes['G'] = 0;
ierror("um_callerid: unable to allocate usermode slot for +M; unloading module.");
return -1;
}
construct_umodebuf();
add_isupport("CALLERID", isupport_umode, "g");
RB_DLINK_FOREACH(ptr, lclient_list.head)
{
struct Client *client_p = ptr->data;
if (IsPerson(client_p) && (client_p->umodes & user_modes['M']))
update_session_deadline(client_p);
}
expire_callerid_override_deadlines_ev = rb_event_add("expire_callerid_override_deadlines", expire_callerid_override_deadlines, NULL, 60);
return 0;
}
static void
um_callerid_moddeinit(void)
{
user_modes['g'] = 0;
user_modes['G'] = 0;
user_modes['M'] = 0;
construct_umodebuf();
delete_isupport("CALLERID");
rb_event_delete(expire_callerid_override_deadlines_ev);
}
DECLARE_MODULE_AV2(um_callerid, um_callerid_modinit, um_callerid_moddeinit, DECLARE_MODULE_AV2(um_callerid, um_callerid_modinit, um_callerid_moddeinit,
NULL, NULL, um_callerid_hfnlist, NULL, NULL, um_callerid_desc); NULL, NULL, um_callerid_hfnlist, NULL, NULL, um_callerid_desc);

View file

@ -42,11 +42,47 @@ static void valid_temp_time1(void)
is_int(52 * WEEK, t, MSG); is_int(52 * WEEK, t, MSG);
} }
static void valid_temp_time_invalid(void)
{
time_t t;
t = valid_temp_time("-2w");
is_int(-1, t, MSG);
t = valid_temp_time("hello");
is_int(-1, t, MSG);
t = valid_temp_time("m");
is_int(-1, t, MSG);
t = valid_temp_time("1w-1w");
is_int(-1, t, MSG);
}
static void valid_temp_time_overflow(void)
{
char s[100];
time_t t;
snprintf(s, sizeof s, "%" PRIuMAX "m", UINTMAX_MAX / 60 + 2);
t = valid_temp_time(s);
is_int(52 * WEEK, t, MSG);
snprintf(s, sizeof s, "%ldm", LONG_MAX / 60 + 2);
t = valid_temp_time(s);
is_int(52 * WEEK, t, MSG);
snprintf(s, sizeof s, "%ldm%ldm", LONG_MAX / 60 - 1, LONG_MAX / 60 - 1);
t = valid_temp_time(s);
is_int(52 * WEEK, t, MSG);
}
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
plan_lazy(); plan_lazy();
valid_temp_time1(); valid_temp_time1();
valid_temp_time_invalid();
valid_temp_time_overflow();
return 0; return 0;
} }