#include "channel.h"
#include "class.h"
#include "client.h"
-#include "common.h"
#include "hash.h"
#include "match.h"
#include "ircd.h"
#include "hook.h"
#include "monitor.h"
#include "snomask.h"
-#include "blacklist.h"
#include "substitution.h"
#include "chmode.h"
#include "s_assert.h"
0, /* O */
0, /* P */
UMODE_NOFORWARD, /* Q */
- UMODE_REGONLYMSG, /* R */
+ 0, /* R */
UMODE_SERVICE, /* S */
0, /* T */
0, /* U */
0, /* W */
0, /* X */
0, /* Y */
- UMODE_SSLCLIENT, /* Z */
+ UMODE_SECURE, /* Z */
/* 0x5B */ 0, 0, 0, 0, 0, 0, /* 0x60 */
UMODE_ADMIN, /* a */
0, /* b */
0, /* d */
0, /* e */
0, /* f */
- UMODE_CALLERID, /* g */
+ 0, /* g */
0, /* h */
UMODE_INVISIBLE, /* i */
0, /* j */
* output -
* side effects - display to client user counts etc.
*/
-int
+void
show_lusers(struct Client *source_p)
{
if(rb_dlink_list_length(&lclient_list) > (unsigned long)MaxClientCount)
form_str(RPL_STATSCONN),
MaxConnectionCount, MaxClientCount,
Count.totalrestartcount);
+}
- return 0;
+/* check if we should exit a client due to authd decision
+ * inputs - client server, client connecting
+ * outputs - true if exited, false if not
+ * side effects - messages/exits client if authd rejected and not exempt
+ */
+static bool
+authd_check(struct Client *client_p, struct Client *source_p)
+{
+ struct ConfItem *aconf = source_p->localClient->att_conf;
+ rb_dlink_list varlist = { NULL, NULL, 0 };
+ bool reject = false;
+ char *reason;
+
+ if(source_p->preClient->auth.accepted == true)
+ return reject;
+
+ substitution_append_var(&varlist, "nick", source_p->name);
+ substitution_append_var(&varlist, "ip", source_p->sockhost);
+ substitution_append_var(&varlist, "host", source_p->host);
+ substitution_append_var(&varlist, "dnsbl-host", source_p->preClient->auth.data);
+ substitution_append_var(&varlist, "network-name", ServerInfo.network_name);
+ reason = substitution_parse(source_p->preClient->auth.reason, &varlist);
+
+ switch(source_p->preClient->auth.cause)
+ {
+ case 'B': /* DNSBL */
+ {
+ struct DNSBLEntryStats *stats;
+ char *dnsbl_name = source_p->preClient->auth.data;
+
+ if(dnsbl_stats != NULL)
+ if((stats = rb_dictionary_retrieve(dnsbl_stats, dnsbl_name)) != NULL)
+ stats->hits++;
+
+ if(IsExemptKline(source_p) || IsConfExemptDNSBL(aconf))
+ {
+ sendto_one_notice(source_p, ":*** Your IP address %s is listed in %s, but you are exempt",
+ source_p->sockhost, dnsbl_name);
+ break;
+ }
+
+ sendto_realops_snomask(SNO_REJ, L_NETWIDE,
+ "Listed on DNSBL %s: %s (%s@%s) [%s] [%s]",
+ dnsbl_name, source_p->name, source_p->username, source_p->host,
+ IsIPSpoof(source_p) ? "255.255.255.255" : source_p->sockhost,
+ source_p->info);
+
+ sendto_one(source_p, form_str(ERR_YOUREBANNEDCREEP),
+ me.name, source_p->name, reason);
+
+ sendto_one_notice(source_p, ":*** Your IP address %s is listed in %s",
+ source_p->sockhost, dnsbl_name);
+ add_reject(source_p, NULL, NULL, NULL, "Banned (listed in a DNSBL)");
+ exit_client(client_p, source_p, &me, "Banned (listed in a DNSBL)");
+ reject = true;
+ }
+ break;
+ case 'O': /* OPM */
+ {
+ char *proxy = source_p->preClient->auth.data;
+ char *port = strrchr(proxy, ':');
+
+ if(port == NULL)
+ {
+ /* This shouldn't happen, better tell the ops... */
+ ierror("authd sent us a malformed OPM string %s", proxy);
+ sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
+ "authd sent us a malformed OPM string %s", proxy);
+ break;
+ }
+
+ /* Terminate the proxy type */
+ *(port++) = '\0';
+
+ if(IsExemptKline(source_p) || IsConfExemptProxy(aconf))
+ {
+ sendto_one_notice(source_p,
+ ":*** Your IP address %s has been detected as an open proxy (type %s, port %s), but you are exempt",
+ source_p->sockhost, proxy, port);
+ break;
+ }
+ sendto_realops_snomask(SNO_REJ, L_NETWIDE,
+ "Open proxy %s/%s: %s (%s@%s) [%s] [%s]",
+ proxy, port,
+ source_p->name,
+ source_p->username, source_p->host,
+ IsIPSpoof(source_p) ? "255.255.255.255" : source_p->sockhost,
+ source_p->info);
+
+ sendto_one(source_p, form_str(ERR_YOUREBANNEDCREEP),
+ me.name, source_p->name, reason);
+
+ sendto_one_notice(source_p,
+ ":*** Your IP address %s has been detected as an open proxy (type %s, port %s)",
+ source_p->sockhost, proxy, port);
+ add_reject(source_p, NULL, NULL, NULL, "Banned (Open proxy)");
+ exit_client(client_p, source_p, &me, "Banned (Open proxy)");
+ reject = true;
+ }
+ break;
+ default: /* Unknown, but handle the case properly */
+ if(IsExemptKline(source_p))
+ {
+ sendto_one_notice(source_p,
+ ":*** You were rejected, but you are exempt (reason: %s)",
+ reason);
+ break;
+ }
+ sendto_realops_snomask(SNO_REJ, L_NETWIDE,
+ "Rejected by authentication system (reason %s): %s (%s@%s) [%s] [%s]",
+ reason, source_p->name, source_p->username, source_p->host,
+ IsIPSpoof(source_p) ? "255.255.255.255" : source_p->sockhost,
+ source_p->info);
+
+ sendto_one(source_p, form_str(ERR_YOUREBANNEDCREEP),
+ me.name, source_p->name, reason);
+
+ sendto_one_notice(source_p, ":*** Rejected by authentication system: %s",
+ reason);
+ add_reject(source_p, NULL, NULL, NULL, "Banned (authentication system)");
+ exit_client(client_p, source_p, &me, "Banned (authentication system)");
+ reject = true;
+ break;
+ }
+
+ if(reject)
+ ServerStats.is_ref++;
+
+ substitution_free(&varlist);
+
+ return reject;
}
/*
** this is not fair. It should actually request another
** nick from local user or kill him/her...
*/
-
int
register_local_user(struct Client *client_p, struct Client *source_p)
{
struct ConfItem *aconf, *xconf;
- struct User *user = source_p->user;
- char tmpstr2[IRCD_BUFSIZE];
+ char tmpstr2[BUFSIZE];
char ipaddr[HOSTIPLEN];
char myusername[USERLEN+1];
- int status;
+ int status, umodes;
s_assert(NULL != source_p);
s_assert(MyConnect(source_p));
{
if(!(source_p->flags & FLAGS_PINGSENT) && source_p->localClient->random_ping == 0)
{
- source_p->localClient->random_ping = (unsigned long) (rand() * rand()) << 1;
- sendto_one(source_p, "PING :%08lX",
- (unsigned long) source_p->localClient->random_ping);
+ source_p->localClient->random_ping = (uint32_t)(((rand() * rand()) << 1) | 1);
+ sendto_one(source_p, "PING :%08X",
+ (unsigned int) source_p->localClient->random_ping);
source_p->flags |= FLAGS_PINGSENT;
return -1;
}
if(source_p->flags & FLAGS_CLICAP)
return -1;
- /* still has DNSbls to validate against */
- if(rb_dlink_list_length(&source_p->preClient->dnsbl_queries) > 0)
+ /* Waiting on authd */
+ if(source_p->preClient->auth.cid)
return -1;
- client_p->localClient->last = rb_current_time();
+ /* Set firsttime here so that post_registration_delay works from registration,
+ * rather than initial connection. */
+ source_p->localClient->firsttime = client_p->localClient->last = rb_current_time();
/* XXX - fixme. we shouldnt have to build a users buffer twice.. */
if(!IsGotId(source_p) && (strchr(source_p->username, '[') != NULL))
/* Apply nick override */
if(*source_p->preClient->spoofnick)
{
- char note[NICKLEN + 10];
+ char note[NAMELEN + 10];
del_from_client_hash(source_p->name, source_p);
rb_strlcpy(source_p->name, source_p->preClient->spoofnick, NICKLEN + 1);
add_to_client_hash(source_p->name, source_p);
- snprintf(note, NICKLEN + 10, "Nick: %s", source_p->name);
+ snprintf(note, sizeof(note), "Nick: %s", source_p->name);
rb_note(source_p->localClient->F, note);
}
if(!valid_hostname(source_p->host))
{
- sendto_one_notice(source_p, ":*** Notice -- You have an illegal character in your hostname");
+ const char *illegal_hostname_client_message = ConfigFileEntry.illegal_hostname_client_message;
+
+ if (illegal_hostname_client_message == NULL)
+ illegal_hostname_client_message = "You have an illegal character in your hostname.";
+
+ sendto_one_notice(source_p, ":*** Notice -- %s", illegal_hostname_client_message);
rb_strlcpy(source_p->host, source_p->sockhost, sizeof(source_p->host));
}
-
aconf = source_p->localClient->att_conf;
if(aconf == NULL)
{
- exit_client(client_p, source_p, &me, "*** Not Authorised");
+ const char *not_authorised_client_message = ConfigFileEntry.not_authorised_client_message;
+
+ if (not_authorised_client_message == NULL)
+ not_authorised_client_message = "You are not authorised to access this server.";
+
+ exit_client(client_p, source_p, &me, not_authorised_client_message);
+ return (CLIENT_EXITED);
+ }
+
+ if(IsConfSSLNeeded(aconf) && !IsSecure(source_p))
+ {
+ const char *ssltls_only_client_message = ConfigFileEntry.ssltls_only_client_message;
+
+ if (ssltls_only_client_message == NULL)
+ ssltls_only_client_message = "You need to use SSL/TLS to use this server.";
+
+ ServerStats.is_ref++;
+ sendto_one_notice(source_p, ":*** Notice -- %s", ssltls_only_client_message);
+
+ exit_client(client_p, source_p, &me, ssltls_only_client_message);
return (CLIENT_EXITED);
}
- if(IsConfSSLNeeded(aconf) && !IsSSL(source_p))
+ if(IsSCTP(source_p) && !IsConfAllowSCTP(aconf))
{
+ const char *sctp_forbidden_client_message = ConfigFileEntry.sctp_forbidden_client_message;
+
+ if (sctp_forbidden_client_message == NULL)
+ sctp_forbidden_client_message = "You are not allowed to use SCTP on this server.";
+
ServerStats.is_ref++;
- sendto_one_notice(source_p, ":*** Notice -- You need to use SSL/TLS to use this server");
- exit_client(client_p, source_p, &me, "Use SSL/TLS");
+ sendto_one_notice(source_p, ":*** Notice -- %s", sctp_forbidden_client_message);
+
+ exit_client(client_p, source_p, &me, sctp_forbidden_client_message);
return (CLIENT_EXITED);
}
if(IsNeedIdentd(aconf))
{
+
+ const char *identd_only_client_message = ConfigFileEntry.identd_only_client_message;
+
+ if (identd_only_client_message == NULL)
+ identd_only_client_message = "You need to install identd to use this server.";
+
ServerStats.is_ref++;
- sendto_one_notice(source_p, ":*** Notice -- You need to install identd to use this server");
- exit_client(client_p, source_p, &me, "Install identd");
+ sendto_one_notice(source_p, ":*** Notice -- %s", identd_only_client_message);
+
+ exit_client(client_p, source_p, &me, identd_only_client_message);
return (CLIENT_EXITED);
}
}
}
- if(IsNeedSasl(aconf) && !*user->suser)
+ if(IsNeedSasl(aconf) && !*source_p->user->suser)
{
+
+ const char *sasl_only_client_message = ConfigFileEntry.sasl_only_client_message;
+
+ if (sasl_only_client_message == NULL)
+ sasl_only_client_message = "You need to identify via SASL to use this server.";
+
ServerStats.is_ref++;
- sendto_one_notice(source_p, ":*** Notice -- You need to identify via SASL to use this server");
- exit_client(client_p, source_p, &me, "SASL access only");
+ sendto_one_notice(source_p, ":*** Notice -- %s", sasl_only_client_message);
+
+ exit_client(client_p, source_p, &me, sasl_only_client_message);
return (CLIENT_EXITED);
}
}
}
- /* report if user has &^>= etc. and set flags as needed in source_p */
+ /* report and set flags (kline exempt etc.) as needed in source_p */
report_and_set_user_flags(source_p, aconf);
/* Limit clients */
if(rb_dlink_list_length(&lclient_list) >=
(unsigned long)GlobalSetOptions.maxclients && !IsConfExemptLimits(aconf))
{
- sendto_realops_snomask(SNO_FULL, L_ALL,
+ sendto_realops_snomask(SNO_FULL, L_NETWIDE,
"Too many clients, rejecting %s[%s].", source_p->name, source_p->host);
+ const char *server_full_client_message = ConfigFileEntry.server_full_client_message;
+
+ if (server_full_client_message == NULL)
+ server_full_client_message = "Sorry, server is full - try later";
+
ServerStats.is_ref++;
- exit_client(client_p, source_p, &me, "Sorry, server is full - try later");
+ exit_client(client_p, source_p, &me, server_full_client_message);
return (CLIENT_EXITED);
}
(xconf = find_xline(source_p->info, 1)) != NULL)
{
ServerStats.is_ref++;
- add_reject(source_p, xconf->host, NULL);
+ sendto_realops_snomask(SNO_BANNED, L_NETWIDE,
+ "Rejecting X-Lined user %s [%s] (%s)", get_client_name(source_p, HIDE_IP),
+ show_ip(NULL, source_p) ? source_p->sockhost : "255.255.255.255", xconf->host);
+
+ add_reject(source_p, xconf->host, NULL, NULL, NULL);
exit_client(client_p, source_p, &me, "Bad user info");
return CLIENT_EXITED;
}
- /* dnsbl check */
- if (source_p->preClient->dnsbl_listed != NULL)
- {
- if (IsExemptKline(source_p) || IsConfExemptDNSBL(aconf))
- sendto_one_notice(source_p, ":*** Your IP address %s is listed in %s, but you are exempt",
- source_p->sockhost, source_p->preClient->dnsbl_listed->host);
- else
- {
- sendto_realops_snomask(SNO_REJ, L_NETWIDE,
- "Listed on DNSBL %s: %s (%s@%s) [%s] [%s]",
- source_p->preClient->dnsbl_listed->host,
- source_p->name,
- source_p->username, source_p->host,
- IsIPSpoof(source_p) ? "255.255.255.255" : source_p->sockhost,
- source_p->info);
-
- rb_dlink_list varlist = { NULL, NULL, 0 };
-
- substitution_append_var(&varlist, "nick", source_p->name);
- substitution_append_var(&varlist, "ip", source_p->sockhost);
- substitution_append_var(&varlist, "host", source_p->host);
- substitution_append_var(&varlist, "dnsbl-host", source_p->preClient->dnsbl_listed->host);
- substitution_append_var(&varlist, "network-name", ServerInfo.network_name);
-
- ServerStats.is_ref++;
-
- sendto_one(source_p, form_str(ERR_YOUREBANNEDCREEP),
- me.name, source_p->name,
- substitution_parse(source_p->preClient->dnsbl_listed->reject_reason, &varlist));
-
- substitution_free(&varlist);
-
- sendto_one_notice(source_p, ":*** Your IP address %s is listed in %s",
- source_p->sockhost, source_p->preClient->dnsbl_listed->host);
- source_p->preClient->dnsbl_listed->hits++;
- add_reject(source_p, NULL, NULL);
- exit_client(client_p, source_p, &me, "*** Banned (DNS blacklist)");
- return CLIENT_EXITED;
- }
- }
+ /* authd rejection check */
+ if(authd_check(client_p, source_p))
+ return CLIENT_EXITED;
/* valid user name check */
if(!valid_username(source_p->username))
{
- sendto_realops_snomask(SNO_REJ, L_ALL,
+ sendto_realops_snomask(SNO_REJ, L_NETWIDE,
"Invalid username: %s (%s@%s)",
source_p->name, source_p->username, source_p->host);
+
+ const char *illegal_name_long_client_message = ConfigFileEntry.illegal_name_long_client_message;
+ const char *illegal_name_short_client_message = ConfigFileEntry.illegal_name_short_client_message;
+
+ if (illegal_name_long_client_message == NULL)
+ illegal_name_long_client_message = "Your username is invalid. Please make sure that your username contains "
+ "only alphanumeric characters.";
+ if (illegal_name_short_client_message == NULL)
+ illegal_name_short_client_message = "Invalid username";
+
ServerStats.is_ref++;
- sendto_one_notice(source_p, ":*** Your username is invalid. Please make sure that your username contains "
- "only alphanumeric characters.");
- sprintf(tmpstr2, "Invalid username [%s]", source_p->username);
+ sendto_one_notice(source_p, ":*** %s", illegal_name_long_client_message);
+ sprintf(tmpstr2, "%s [%s]", illegal_name_short_client_message, source_p->username);
exit_client(client_p, source_p, &me, tmpstr2);
return (CLIENT_EXITED);
}
SetDynSpoof(source_p);
}
- source_p->umodes |= ConfigFileEntry.default_umodes & ~ConfigFileEntry.oper_only_umodes & ~orphaned_umodes;
+ umodes = ConfigFileEntry.default_umodes & ~aconf->umodes_mask;
+ umodes |= aconf->umodes;
+ umodes &= ~ConfigFileEntry.oper_only_umodes;
+ umodes &= ~orphaned_umodes;
+ source_p->umodes |= umodes;
call_hook(h_new_local_user, source_p);
rb_inet_ntop_sock((struct sockaddr *)&source_p->localClient->ip, ipaddr, sizeof(ipaddr));
sendto_realops_snomask(SNO_CCONN, L_ALL,
- "Client connecting: %s (%s@%s) [%s] {%s} [%s]",
+ "Client connecting: %s (%s@%s) [%s] {%s} <%s> [%s]",
source_p->name, source_p->username, source_p->orighost,
show_ip(NULL, source_p) ? ipaddr : "255.255.255.255",
- get_client_class(source_p), source_p->info);
+ get_client_class(source_p),
+ *source_p->user->suser ? source_p->user->suser : "*",
+ source_p->info);
sendto_realops_snomask(SNO_CCONNEXT, L_ALL,
- "CLICONN %s %s %s %s %s %s 0 %s",
+ "CLICONN %s %s %s %s %s %s 0 %s %s",
source_p->name, source_p->username, source_p->orighost,
show_ip(NULL, source_p) ? ipaddr : "255.255.255.255",
get_client_class(source_p),
/* mirc can sometimes send ips here */
show_ip(NULL, source_p) ? source_p->localClient->fullcaps : "<hidden> <hidden>",
+ *source_p->user->suser ? source_p->user->suser : "*",
source_p->info);
add_to_hostname_hash(source_p->orighost, source_p);
*/
if(!*source_p->id)
{
- strcpy(source_p->id, generate_uid());
+ rb_strlcpy(source_p->id, generate_uid(), sizeof(source_p->id));
add_to_id_hash(source_p->id, source_p);
}
- if (IsSSL(source_p))
- source_p->umodes |= UMODE_SSLCLIENT;
+ if (IsSecure(source_p))
+ source_p->umodes |= UMODE_SECURE;
if (source_p->umodes & UMODE_INVISIBLE)
Count.invisi++;
{
Count.max_loc = rb_dlink_list_length(&lclient_list);
if(!(Count.max_loc % 10))
- sendto_realops_snomask(SNO_GENERAL, L_ALL,
+ sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
"New Max Local Clients: %d", Count.max_loc);
}
free_pre_client(source_p);
- return (introduce_client(client_p, source_p, user, source_p->name, 1));
+ introduce_client(client_p, source_p, source_p->user, source_p->name, 1);
+ return 0;
}
/*
* of the net, either from a local client connect or
* from a remote connect.
*/
-int
+void
introduce_client(struct Client *client_p, struct Client *source_p, struct User *user, const char *nick, int use_euid)
{
char ubuf[BUFSIZE];
hdata2.client = client_p;
hdata2.target = source_p;
call_hook(h_introduce_client, &hdata2);
-
- return 0;
}
/*
* valid_hostname - check hostname for validity
*
* Inputs - pointer to user
- * Output - YES if valid, NO if not
+ * Output - true if valid, false if not
* Side effects - NONE
*
* NOTE: this doesn't allow a hostname to begin with a dot and
* will not allow more dots than chars.
*/
-int
+bool
valid_hostname(const char *hostname)
{
const char *p = hostname, *last_slash = 0;
s_assert(NULL != p);
if(hostname == NULL)
- return NO;
+ return false;
if(!strcmp(hostname, "localhost"))
- return YES;
+ return true;
if('.' == *p || ':' == *p || '/' == *p)
- return NO;
+ return false;
while (*p)
{
if(!IsHostChar(*p))
- return NO;
+ return false;
if(*p == '.' || *p == ':')
found_sep++;
else if(*p == '/')
}
if(found_sep == 0)
- return NO;
+ return false;
if(last_slash && IsDigit(last_slash[1]))
- return NO;
+ return false;
- return YES;
+ return true;
}
/*
* valid_username - check username for validity
*
* Inputs - pointer to user
- * Output - YES if valid, NO if not
+ * Output - true if valid, false if not
* Side effects - NONE
*
* Absolutely always reject any '*' '!' '?' '@' in an user name
* Allow '.' in username to allow for "first.last"
* style of username
*/
-int
+bool
valid_username(const char *username)
{
int dots = 0;
s_assert(NULL != p);
if(username == NULL)
- return NO;
+ return false;
if('~' == *p)
++p;
* or "-hi-@somehost", "h-----@somehost" would still be accepted.
*/
if(!IsAlNum(*p))
- return NO;
+ return false;
while (*++p)
{
{
dots++;
if(dots > ConfigFileEntry.dots_in_ident)
- return NO;
+ return false;
if(!IsUserChar(p[1]))
- return NO;
+ return false;
}
else if(!IsUserChar(*p))
- return NO;
+ return false;
}
- return YES;
+ return true;
}
/* report_and_set_user_flags
if(IsConfExemptDNSBL(aconf))
/* kline exempt implies this, don't send both */
if(!IsConfExemptKline(aconf))
- sendto_one_notice(source_p, ":*** You are exempt from DNS blacklists");
+ sendto_one_notice(source_p, ":*** You are exempt from DNSBL listings");
/* If this user is exempt from user limits set it F lined" */
if(IsConfExemptLimits(aconf))
}
}
+void
+report_priv_change(struct Client *client, struct PrivilegeSet *old, struct PrivilegeSet *new)
+{
+ struct privset_diff diff = privilegeset_diff(old, new);
+
+ hook_data_priv_change hdata = {
+ .client = client,
+ .new = new,
+ .old = old,
+ .unchanged = diff.unchanged,
+ .added = diff.added,
+ .removed = diff.removed,
+ };
+ call_hook(h_priv_change, &hdata);
+}
+
static void
show_other_user_mode(struct Client *source_p, struct Client *target_p)
{
const char *pm;
struct Client *target_p;
int what, setflags;
- int badflag = NO; /* Only send one bad flag notice */
- int showsnomask = NO;
+ bool badflag = false; /* Only send one bad flag notice */
+ bool showsnomask = false;
unsigned int setsnomask;
char buf[BUFSIZE];
hook_data_umode_changed hdata;
if(IsServer(source_p))
{
- sendto_realops_snomask(SNO_GENERAL, L_ADMIN,
+ sendto_realops_snomask(SNO_GENERAL, L_NETWIDE,
"*** Mode for User %s from %s", parv[1], source_p->name);
return 0;
}
if(source_p != target_p)
{
- if (MyOper(source_p) && parc < 3)
+ if (HasPrivilege(source_p, "auspex:umodes") && parc < 3)
show_other_user_mode(source_p, target_p);
else
sendto_one(source_p, form_str(ERR_USERSDONTMATCH), me.name, source_p->name);
if(MyConnect(source_p))
{
source_p->umodes &= ~ConfigFileEntry.oper_only_umodes;
- if (!(source_p->umodes & UMODE_SERVNOTICE) && source_p->snomask != 0)
- {
- source_p->snomask = 0;
- showsnomask = YES;
- }
- source_p->flags2 &= ~OPER_FLAGS;
-
- rb_free(source_p->localClient->opername);
- source_p->localClient->opername = NULL;
+ source_p->flags &= ~OPER_FLAGS;
rb_dlinkFindDestroy(source_p, &local_oper_list);
- privilegeset_unref(source_p->localClient->privset);
- source_p->localClient->privset = NULL;
+ }
+
+ if(source_p->user->opername != NULL)
+ {
+ rb_free(source_p->user->opername);
+ source_p->user->opername = NULL;
+ }
+
+ if(source_p->user->privset != NULL)
+ {
+ report_priv_change(source_p, source_p->user->privset, NULL);
+
+ privilegeset_unref(source_p->user->privset);
+ source_p->user->privset = NULL;
}
rb_dlinkFindDestroy(source_p, &oper_list);
case 's':
if (MyConnect(source_p))
{
- if(!IsOper(source_p)
- && (ConfigFileEntry.oper_only_umodes & UMODE_SERVNOTICE))
+ if((ConfigFileEntry.oper_only_umodes & UMODE_SERVNOTICE) &&
+ (!IsOper(source_p) || !HasPrivilege(source_p, "usermode:servnotice")))
{
if (what == MODE_ADD || source_p->umodes & UMODE_SERVNOTICE)
- badflag = YES;
+ badflag = true;
continue;
}
- showsnomask = YES;
+ showsnomask = true;
if(what == MODE_ADD)
{
if (parc > 3)
default:
if (MyConnect(source_p) && *pm == 'Q' && !ConfigChannel.use_forward)
{
- badflag = YES;
+ badflag = true;
break;
}
|| (orphaned_umodes & flag)))
{
if (what == MODE_ADD || source_p->umodes & flag)
- badflag = YES;
+ badflag = true;
}
else
{
else
{
if(MyConnect(source_p))
- badflag = YES;
+ badflag = true;
}
break;
}
if(badflag)
sendto_one(source_p, form_str(ERR_UMODEUNKNOWNFLAG), me.name, source_p->name);
+ if(MyClient(source_p))
+ {
+ if ((ConfigFileEntry.oper_only_umodes & UMODE_SERVNOTICE) &&
+ !HasPrivilege(source_p, "usermode:servnotice"))
+ source_p->umodes &= ~UMODE_SERVNOTICE;
+ if (!(source_p->umodes & UMODE_SERVNOTICE) && source_p->snomask != 0)
+ {
+ source_p->snomask = 0;
+ showsnomask = true;
+ }
+ }
+
if(MyClient(source_p) && (source_p->snomask & SNO_NCHANGE) && !IsOperN(source_p))
{
sendto_one_notice(source_p, ":*** You need oper and nick_changes flag for +s +n");
source_p->umodes &= ~UMODE_ADMIN;
}
+ if(MyClient(source_p))
+ source_p->handler = IsOperGeneral(source_p) ? OPER_HANDLER : CLIENT_HANDLER;
+
/* let modules providing usermodes know that we've changed our usermode --nenolod */
hdata.client = source_p;
hdata.oldumodes = setflags;
* output - none
* side effects - opers up source_p using aconf for reference
*/
-int
+void
oper_up(struct Client *source_p, struct oper_conf *oper_p)
{
unsigned int old = source_p->umodes, oldsnomask = source_p->snomask;
SetExtendChans(source_p);
SetExemptKline(source_p);
- source_p->flags2 |= oper_p->flags;
- source_p->localClient->opername = rb_strdup(oper_p->name);
- source_p->localClient->privset = privilegeset_ref(oper_p->privset);
+ source_p->flags |= oper_p->flags;
+ source_p->user->opername = rb_strdup(oper_p->name);
+ source_p->user->privset = privilegeset_ref(oper_p->privset);
+
+ report_priv_change(source_p, NULL, source_p->user->privset);
rb_dlinkAddAlloc(source_p, &local_oper_list);
rb_dlinkAddAlloc(source_p, &oper_list);
source_p->snomask &= ~SNO_NCHANGE;
if(!IsOperOperwall(source_p))
source_p->umodes &= ~UMODE_OPERWALL;
+ if((ConfigFileEntry.oper_only_umodes & UMODE_SERVNOTICE) &&
+ !HasPrivilege(source_p, "usermode:servnotice"))
+ {
+ source_p->umodes &= ~UMODE_SERVNOTICE;
+ source_p->snomask = 0;
+ }
hdata.client = source_p;
hdata.oldumodes = old;
hdata.oldsnomask = oldsnomask;
call_hook(h_umode_changed, &hdata);
+ source_p->handler = IsOperGeneral(source_p) ? OPER_HANDLER : CLIENT_HANDLER;
+
sendto_realops_snomask(SNO_GENERAL, L_ALL,
"%s (%s!%s@%s) is now an operator", oper_p->name, source_p->name,
source_p->username, source_p->host);
+ sendto_server(NULL, NULL, CAP_TS6, NOCAPS, ":%s OPER %s %s",
+ use_id(source_p), oper_p->name, oper_p->privset->name);
if(!(old & UMODE_INVISIBLE) && IsInvisible(source_p))
++Count.invisi;
if((old & UMODE_INVISIBLE) && !IsInvisible(source_p))
construct_snobuf(source_p->snomask));
sendto_one(source_p, form_str(RPL_YOUREOPER), me.name, source_p->name);
sendto_one_notice(source_p, ":*** Oper privilege set is %s", oper_p->privset->name);
- sendto_one_notice(source_p, ":*** Oper privs are %s", oper_p->privset->privs);
+ send_multiline_init(source_p, " ", ":%s NOTICE %s :*** Oper privs are ", me.name, source_p->name);
+ for (const char *const *s = privilegeset_privs(oper_p->privset); *s != NULL; s++)
+ send_multiline_item(source_p, "%s", *s);
+ send_multiline_fini(source_p, NULL);
send_oper_motd(source_p);
-
- return (1);
}
/*
if (user_modes[i] == 0)
{
orphaned_umodes |= prev_user_modes[i];
- sendto_realops_snomask(SNO_DEBUG, L_ALL, "Umode +%c is now orphaned", i);
+ sendto_realops_snomask(SNO_DEBUG, L_NETWIDE, "Umode +%c is now orphaned", i);
}
else
{
orphaned_umodes &= ~prev_user_modes[i];
- sendto_realops_snomask(SNO_DEBUG, L_ALL, "Orphaned umode +%c is picked up by module", i);
+ sendto_realops_snomask(SNO_DEBUG, L_NETWIDE, "Orphaned umode +%c is picked up by module", i);
}
user_modes[i] = prev_user_modes[i];
}
target_p->info);
if(*mode)
- sendto_channel_local_butone(target_p, ALL_MEMBERS, chptr,
- ":%s MODE %s +%s %s",
- target_p->servptr->name,
- chptr->chname, mode, modeval);
+ sendto_channel_local_with_capability_butone(target_p, ALL_MEMBERS, NOCAPS, CLICAP_CHGHOST, chptr,
+ ":%s MODE %s +%s %s", target_p->servptr->name, chptr->chname, mode, modeval);
*modeval = '\0';
}
del_all_accepts(target_p);
}
}
+
+bool
+has_common_channel(struct Client *source_p, struct Client *target_p)
+{
+ rb_dlink_node *ps, *pt;
+ struct membership *ms, *mt;
+ struct Channel *chptr;
+
+ ITER_COMM_CHANNELS(ps, pt, source_p->user->channel.head, target_p->user->channel.head, ms, mt, chptr)
+ {
+ if (ms != NULL && mt != NULL)
+ return true;
+ }
+
+ return false;
+}
+