disallow client to use MODE +h [<user>@]<host> [<pass>] (bug: mode +h took 2 parameters, even from remote users!)
sethost can only be unset with "MODE <nick> -h"
+and only if the sethost was not remotely set by a service (unless the user is an oper)
+and only if the user has an account set, and is +x (or is allowed to set +x)
+so the +x host becomes visible, and never the realhost
sethost #N no longer supported (N being the Nth configured spoof block)
removed numbering (not required anymore?)
merged showing of user@host
-diff -r c6f3803ee169 include/client.h
---- a/include/client.h
-+++ b/include/client.h
+diff -r 103be431b156 include/client.h
+--- a/include/client.h Sat Jul 20 12:01:10 2013 +0100
++++ b/include/client.h Sat Jul 20 13:18:35 2013 +0100
@@ -90,7 +90,7 @@
#define FlagClr(set,flag) ((set)->bits[FLAGSET_INDEX(flag)] &= ~FLAGSET_MASK(flag))
/** Character to indicate no oper name available */
#define NOOPERNAMECHARACTER '-'
-@@ -627,7 +627,6 @@
+@@ -171,6 +171,7 @@
+ FLAG_BURST, /**< Server is receiving a net.burst */
+ FLAG_BURST_ACK, /**< Server is waiting for eob ack */
+ FLAG_IPCHECK, /**< Added or updated IPregistry data */
++ FLAG_REMOTESETHOST, /**< user has a remote sethost */
+ FLAG_LOCOP, /**< Local operator -- SRB */
+ FLAG_SERVNOTICE, /**< server notices such as kill */
+ FLAG_OPER, /**< Operator */
+@@ -627,7 +628,8 @@
#define HasHiddenHost(x) (IsHiddenHost(x) && IsAccount(x))
/** Return non-zero if the client is using a spoofhost */
#define IsSetHost(x) HasFlag(x, FLAG_SETHOST)
-#define HasSetHost(x) (IsSetHost(x))
++/** Return non-zero if the client is using a spoofhost that was set by a service */
++#define IsRemoteSetHost(x) HasFlag(x, FLAG_REMOTESETHOST)
/** Mark a client as having an in-progress net.burst. */
#define SetBurst(x) SetFlag(x, FLAG_BURST)
-diff -r c6f3803ee169 include/ircd_chattr.h
---- a/include/ircd_chattr.h
-+++ b/include/ircd_chattr.h
+@@ -671,6 +673,8 @@
+ #define SetHiddenHost(x) SetFlag(x, FLAG_HIDDENHOST)
+ /** Mark a client as having mode +h (spoofhost). */
+ #define SetSetHost(x) SetFlag(x, FLAG_SETHOST)
++/** Mark a client as having a remote sethost. */
++#define SetRemoteSetHost(x) SetFlag(x, FLAG_REMOTESETHOST)
+ /** Mark a client as having mode +X (xtraop). */
+ #define SetXtraOp(x) SetFlag(x, FLAG_XTRAOP)
+ /** Mark a client as having mode +n (hide channels). */
+@@ -716,6 +720,8 @@
+ #define ClearHiddenHost(x) ClrFlag(x, FLAG_HIDDENHOST)
+ /** Remove mode +h (spoofhost) from a client. */
+ #define ClearSetHost(x) ClrFlag(x, FLAG_SETHOST)
++/** Clear the client's remote SETHOST flag. */
++#define ClearRemoteSetHost(x) ClrFlag(x, FLAG_REMOTESETHOST)
+ /** Remove mode +X (xtraop) from a client. */
+ #define ClearXtraOp(x) ClrFlag(x, FLAG_XTRAOP)
+ /** Remove mode +n (hide channels) from a client. */
+diff -r 103be431b156 include/ircd_chattr.h
+--- a/include/ircd_chattr.h Sat Jul 20 12:01:10 2013 +0100
++++ b/include/ircd_chattr.h Sat Jul 20 13:18:35 2013 +0100
@@ -117,6 +117,8 @@
#define IsUserChar(c) (IRCD_CharAttrTab[(c) - CHAR_MIN] & NTL_IRCUI)
/** Test whether a character is valid in a hostname. */
+
#endif /* INCLUDED_ircd_chattr_h */
-diff -r c6f3803ee169 include/numeric.h
---- a/include/numeric.h
-+++ b/include/numeric.h
+diff -r 103be431b156 include/numeric.h
+--- a/include/numeric.h Sat Jul 20 12:01:10 2013 +0100
++++ b/include/numeric.h Sat Jul 20 13:18:35 2013 +0100
@@ -314,7 +314,7 @@
/* RPL_NOUSERS 395 Dalnet/EFnet/IRCnet */
#define RPL_HOSTHIDDEN 396 /* UMODE +x completed succesfuly */
/*
* Errors are in the range from 400-599 currently and are grouped by what
-diff -r c6f3803ee169 include/s_conf.h
---- a/include/s_conf.h
-+++ b/include/s_conf.h
+diff -r 103be431b156 include/s_conf.h
+--- a/include/s_conf.h Sat Jul 20 12:01:10 2013 +0100
++++ b/include/s_conf.h Sat Jul 20 13:18:35 2013 +0100
@@ -205,7 +205,8 @@
extern void conf_add_sline(const char* const* fields, int count);
extern void clear_slines(void);
-extern int conf_check_slines(struct Client *cptr);
-+extern struct sline *find_spoofblock(struct Client *cptr, char *spoofhost, char *password);
++extern struct sline *find_spoofblock(struct Client *cptr, char *host, char *password);
+extern int apply_spoofblock(struct Client *cptr);
extern void free_spoofhost(struct sline *spoof);
extern void yyerror(const char *msg);
-diff -r c6f3803ee169 include/s_user.h
---- a/include/s_user.h
-+++ b/include/s_user.h
+diff -r 103be431b156 include/s_user.h
+--- a/include/s_user.h Sat Jul 20 12:01:10 2013 +0100
++++ b/include/s_user.h Sat Jul 20 13:18:35 2013 +0100
@@ -79,15 +79,15 @@
extern int set_nick_name(struct Client* cptr, struct Client* sptr,
const char* nick, int parc, char* parv[]);
extern void set_snomask(struct Client *, unsigned int, int);
extern int is_snomask(char *);
extern int check_target_limit(struct Client *sptr, void *target, const char *name,
-diff -r c6f3803ee169 ircd/channel.c
---- a/ircd/channel.c
-+++ b/ircd/channel.c
+diff -r 103be431b156 ircd/channel.c
+--- a/ircd/channel.c Sat Jul 20 12:01:10 2013 +0100
++++ b/ircd/channel.c Sat Jul 20 13:18:35 2013 +0100
@@ -384,12 +384,12 @@
ircd_ntoa_r(iphost, &cli_ip(cptr));
sa = cli_user(cptr)->realhost;
} else {
ircd_snprintf(0, tmphost, HOSTLEN, "%s.%s",
-diff -r c6f3803ee169 ircd/m_oper.c
---- a/ircd/m_oper.c
-+++ b/ircd/m_oper.c
+diff -r 103be431b156 ircd/m_oper.c
+--- a/ircd/m_oper.c Sat Jul 20 12:01:10 2013 +0100
++++ b/ircd/m_oper.c Sat Jul 20 13:18:35 2013 +0100
@@ -189,7 +189,7 @@
set_snomask(sptr, SNO_OPERDEFAULT, SNO_ADD);
send_reply(sptr, RPL_YOUREOPER);
sendto_opmask_butone(0, SNO_OLDSNO, "%s (%s@%s) is now operator (%c) as %s",
-diff -r c6f3803ee169 ircd/m_sethost.c
---- a/ircd/m_sethost.c
-+++ b/ircd/m_sethost.c
-@@ -82,174 +82,227 @@
+diff -r 103be431b156 ircd/m_remotemode.c
+--- a/ircd/m_remotemode.c Sat Jul 20 12:01:10 2013 +0100
++++ b/ircd/m_remotemode.c Sat Jul 20 13:18:35 2013 +0100
+@@ -126,6 +126,7 @@
+ int what = MODE_ADD;
+ int do_host_hiding = 0;
+ int do_set_host = 0;
++ int alreadyh = 0;
+
+ /* not from a server */
+ if (!IsServer(sptr))
+@@ -216,17 +217,15 @@
+ break;
+ case 'h':
+ if (what == MODE_ADD) {
+- if (*(p + 1) && is_hostmask(*(p + 1))) {
+- do_set_host = 1;
+- hostmask = *++p;
+- } else {
+- if (!*(p+1))
+- protocol_violation(sptr, "Received REMOTEMODE +h without host parameter for user %C", acptr);
+- else {
+- protocol_violation(sptr, "Received REMOTEMODE +h with invalid host parameter %s for user %C", *(p+1), acptr);
+- p++; /* Swallow the arg anyway */
+- }
+- }
++ /* TODO: */
++ if (IsServer(cptr)) {
++ if (!*(p + 1))
++ protocol_violation(cptr, "Received MODE +h for %C without sethost parameter", sptr);
++ else {
++ hostmask = *++p;
++ do_set_host = 1;
++ }
++ }
+ } else { /* MODE_DEL */
+ do_set_host = 1;
+ hostmask = NULL;
+@@ -275,10 +274,12 @@
+ host = hostmask;
+
+ /* check if new sethost is different from before */
+- if (IsSetHost(acptr) &&
+- (!user || strcmp(cli_user(acptr)->username, user) == 0) &&
+- strcmp(cli_user(acptr)->host, host) == 0)
+- do_set_host = 0;
++ if (IsSetHost(acptr)) {
++ alreadyh = 1;
++ if ((!user || strcmp(cli_user(acptr)->username, user) == 0) &&
++ strcmp(cli_user(acptr)->host, host) == 0)
++ do_set_host = 0;
++ }
+ }
+
+ /* do host hiding for +h/-h */
+@@ -353,7 +354,7 @@
+ assert(UserStats.inv_clients <= UserStats.clients + UserStats.unknowns);
+
+ /* send out the mode */
+- send_umode_out(acptr, acptr, &setflags, 0);
++ send_umode_out(acptr, acptr, &setflags, 0, alreadyh);
+
+ return 0;
+ }
+diff -r 103be431b156 ircd/m_sethost.c
+--- a/ircd/m_sethost.c Sat Jul 20 12:01:10 2013 +0100
++++ b/ircd/m_sethost.c Sat Jul 20 13:18:35 2013 +0100
+@@ -82,175 +82,233 @@
#include "config.h"
#include "client.h"
+ /* need hostmask parameter
+ * and need password parameter from an ordinary user
+ */
-+ if (parc < 2 || EmptyString(parv[1]) || (parc < 3 && !IsAnOper(sptr)))
++ if (parc < 2 || *parv[1] == 0 || (parc < 3 && !IsAnOper(sptr)))
+ return need_more_params(sptr, "SETHOST");
+
+ hostmask = parv[1];
+ else
+ host = hostmask;
+
-+ /* got a pasword */
-+ if (parc > 2 && !EmptyString(parv[2]))
++ /* got a pasword and not empty */
++ if (parc > 2 && *parv[2])
+ password = parv[2];
+
+ /* freeform - do not bother with password */
- if (parc < 2)
- return need_more_params(sptr, "SETHOST");
-+ /* already +h, clear flag to force mode +h to be sent out again */
++ /* already +h, clear flag to force mode +h to be sent out again, and clear remote sethost flag */
+ if (IsSetHost(sptr)) {
+ FlagClr(&setflags, FLAG_SETHOST);
+ alreadyh = 1;
++ ClearRemoteSetHost(sptr);
+ }
- if (0 == ircd_strcmp("undo", parv[1])) {
}
- send_umode_out(target, target, &setflags, 0);
++ /* setting remote sethost, set flag */
++ if (host)
++ SetRemoteSetHost(acptr);
++
+ /* do it */
+ set_hostmask(acptr, user, host);
+
+
return 0;
}
-diff -r c6f3803ee169 ircd/m_userhost.c
---- a/ircd/m_userhost.c
-+++ b/ircd/m_userhost.c
+
+diff -r 103be431b156 ircd/m_userhost.c
+--- a/ircd/m_userhost.c Sat Jul 20 12:01:10 2013 +0100
++++ b/ircd/m_userhost.c Sat Jul 20 13:18:35 2013 +0100
@@ -104,7 +104,7 @@
* of +x. If an oper wants the real host, he should go to
* /whois to get it.
cli_user(cptr)->host : cli_user(cptr)->realhost);
}
-diff -r c6f3803ee169 ircd/m_userip.c
---- a/ircd/m_userip.c
-+++ b/ircd/m_userip.c
+diff -r 103be431b156 ircd/m_userip.c
+--- a/ircd/m_userip.c Sat Jul 20 12:01:10 2013 +0100
++++ b/ircd/m_userip.c Sat Jul 20 13:18:35 2013 +0100
@@ -106,7 +106,7 @@
* of +x. If an oper wants the real IP, he should go to
* /whois to get it.
feature_str(FEAT_HIDDEN_IP) :
ircd_ntoa(&cli_ip(cptr)));
}
-diff -r c6f3803ee169 ircd/m_who.c
---- a/ircd/m_who.c
-+++ b/ircd/m_who.c
+diff -r 103be431b156 ircd/m_who.c
+--- a/ircd/m_who.c Sat Jul 20 12:01:10 2013 +0100
++++ b/ircd/m_who.c Sat Jul 20 13:18:35 2013 +0100
@@ -394,14 +394,14 @@
&& ((!(matchsel & WHO_FIELD_HOS))
|| matchexec(cli_user(acptr)->host, mymask, minlen))
|| !ipmask_check(&cli_ip(acptr), &imask, ibits))
&& ((!(matchsel & WHO_FIELD_ACC))
|| matchexec(cli_user(acptr)->account, mymask, minlen)))
-diff -r c6f3803ee169 ircd/m_whois.c
---- a/ircd/m_whois.c
-+++ b/ircd/m_whois.c
+diff -r 103be431b156 ircd/m_whois.c
+--- a/ircd/m_whois.c Sat Jul 20 12:01:10 2013 +0100
++++ b/ircd/m_whois.c Sat Jul 20 13:18:35 2013 +0100
@@ -214,7 +214,7 @@
if (IsAccount(acptr))
send_reply(sptr, RPL_WHOISACCOUNT, name, user->account);
send_reply(sptr, RPL_WHOISACTUALLY, name, user->realusername,
user->realhost, ircd_ntoa(&cli_ip(acptr)));
-diff -r c6f3803ee169 ircd/s_conf.c
---- a/ircd/s_conf.c
-+++ b/ircd/s_conf.c
+diff -r 103be431b156 ircd/s_conf.c
+--- a/ircd/s_conf.c Sat Jul 20 12:01:10 2013 +0100
++++ b/ircd/s_conf.c Sat Jul 20 13:18:35 2013 +0100
@@ -52,6 +52,7 @@
#include "s_bsd.h"
#include "s_debug.h"
#include "send.h"
#include "struct.h"
#include "sys.h"
-@@ -1239,44 +1240,173 @@
- * -froo 1/2003
- *
- */
+@@ -1206,6 +1207,10 @@
+ return 0;
+ }
+
++/**
++ * clear spoof blocks
++ *
++ */
+ void clear_slines(void)
+ {
+ struct sline *sline;
+@@ -1222,61 +1227,164 @@
+ }
+ }
+
+-/*
+- * conf_check_slines()
+/**
+ * find_spoofblock
-+ *
+ *
+- * Check S lines for the specified client, passed in cptr struct.
+- * If the client's IP is S-lined, process the substitution here.
+ * Find matching spoof block for a user for the given spoofhost and password
-+ *
+ *
+- * Precondition
+- * cptr != NULL
+ * @param cptr User wanting to get a spoof host.
-+ * @param spoofhost Spoof host to look for.
++ * @param host Spoof host to look for.
+ * @param password Password given by user (can be NULL).
-+ *
+ *
+- * Returns
+- * 0 = No S-line found
+- * 1 = S-line found and substitution done.
+- *
+- * -mbuna 9/2001
+- * -froo 1/2003
+ * @return pointer to the matching spoofblock is found, else NULL
-+ *
-+ */
-+struct sline *find_spoofblock(struct Client *cptr, char *spoofhost, char *password) {
+ *
+ */
++struct sline *find_spoofblock(struct Client *cptr, char *host, char *password) {
-+ struct sline *sconf;
+-int
+-conf_check_slines(struct Client *cptr)
+-{
+ struct sline *sconf;
+- char *hostonly;
+ int result = 0;
+ int r = 0;
+ char *error;
+
-+ Debug((DEBUG_INFO, "find_spoofblock() cptr=%C spoofhost=%s password=%s",
-+ cptr, spoofhost, password));
-+
-+ for (sconf = GlobalSList; sconf; sconf = sconf->next) {
++ Debug((DEBUG_INFO, "find_spoofblock() cptr=%C host=%s password=%s",
++ cptr, host, password));
+
+ for (sconf = GlobalSList; sconf; sconf = sconf->next) {
+
+ /* check result of previous loop */
+ if (r > result)
+ result = r;
+
+ /* check spoofhost */
-+ if (strcasecmp(sconf->spoofhost, spoofhost) != 0)
++ if (strcasecmp(sconf->spoofhost, host) != 0)
+ continue;
+ r = 1;
+
+ /* check cptr's host */
+ /* cidr mask */
-+ if (sconf->flags == SLINE_FLAGS_IP) {
-+ if (!ipmask_check(&(cli_ip(cptr)), &(sconf->address), sconf->bits))
-+ continue;
+ if (sconf->flags == SLINE_FLAGS_IP) {
+ if (!ipmask_check(&(cli_ip(cptr)), &(sconf->address), sconf->bits))
+ continue;
+- } else if (sconf->flags == SLINE_FLAGS_HOSTNAME) {
+- if ((match(sconf->realhost, cli_sockhost(cptr)) != 0) &&
+- (match(sconf->realhost, cli_sock_ip(cptr)) != 0)) /* wildcarded IP address */
+- continue;
+- } else {
+ }
+
+ /* hostname */
+ else if (sconf->flags == SLINE_FLAGS_HOSTNAME) {
+ if ((match(sconf->realhost, cli_sockhost(cptr)) != 0) &&
+ (match(sconf->realhost, cli_sock_ip(cptr)) != 0)) /* wildcarded IP address */
-+ continue;
-+ }
-+
+ continue;
+ }
+
+- if (match(sconf->username, cli_user(cptr)->username) == 0) {
+- /* Ignore user part if u@h. */
+- if ((hostonly = strchr(sconf->spoofhost, '@')))
+- hostonly++;
+- else
+- hostonly = sconf->spoofhost;
+ /* not cidr or hostname.. */
+ else
+ continue;
+ r = 2;
-+
+
+- if(!*hostonly)
+ /* check cptr's username */
+ if (!EmptyString(sconf->username) && match(sconf->username, cli_user(cptr)->realusername) != 0)
+ continue;
+ r = 3;
+
+ /* check password */
-+ if (password) {
++ if (!EmptyString(password)) {
+ if (EmptyString(sconf->passwd) || strcmp(sconf->passwd, password) != 0)
+ continue;
+ }
+ /* TODO: L_INFO LOG_NOSNOTICE */
+ /* log best result we got */
+ log_write(LS_SETHOST, L_INFO, 0, "%s SETHOST %s (failed: %s) [password: %s]",
-+ get_client_name(cptr, SHOW_IP), spoofhost,
++ get_client_name(cptr, SHOW_IP), host,
+ error, password ? "yes" : "no");
+ return NULL;
+}
+
-+
-+
+/**
+ * apply_spoofblock
+ *
+ * @return 1 for success, else 0
+ *
+ */
- int
--conf_check_slines(struct Client *cptr)
++int
+apply_spoofblock(struct Client *cptr)
- {
- struct sline *sconf;
- char *hostonly;
-
++{
++ struct sline *sconf;
++
+ /* disabled */
+ if(!feature_bool(FEAT_SETHOST_AUTO))
+ return 0;
+
+ /* go over spoof blocks */
- for (sconf = GlobalSList; sconf; sconf = sconf->next) {
++ for (sconf = GlobalSList; sconf; sconf = sconf->next) {
+
+ /* check IP */
- if (sconf->flags == SLINE_FLAGS_IP) {
- if (!ipmask_check(&(cli_ip(cptr)), &(sconf->address), sconf->bits))
++ if (sconf->flags == SLINE_FLAGS_IP) {
++ if (!ipmask_check(&(cli_ip(cptr)), &(sconf->address), sconf->bits))
continue;
-+
-+ /* check host */
- } else if (sconf->flags == SLINE_FLAGS_HOSTNAME) {
- if ((match(sconf->realhost, cli_sockhost(cptr)) != 0) &&
-- (match(sconf->realhost, cli_sock_ip(cptr)) != 0)) /* wildcarded IP address */
-+ (match(sconf->realhost, cli_sock_ip(cptr)) != 0)) /* wildcarded IP address */
- continue;
-- } else {
-- continue;
-- }
-+ } else
-+ continue;
-
-- if (match(sconf->username, cli_user(cptr)->username) == 0) {
-- /* Ignore user part if u@h. */
-- if ((hostonly = strchr(sconf->spoofhost, '@')))
-- hostonly++;
-- else
-- hostonly = sconf->spoofhost;
-+ /* check username */
-+ if (match(sconf->username, cli_user(cptr)->username) != 0)
-+ continue;
-
-- if(!*hostonly)
-- continue;
-+ /* Ignore user part if u@h. */
-+ if ((hostonly = strchr(sconf->spoofhost, '@')))
-+ hostonly++;
-+ else
-+ hostonly = sconf->spoofhost;
- ircd_strncpy(cli_user(cptr)->host, hostonly, HOSTLEN);
- log_write(LS_USER, L_INFO, LOG_NOSNOTICE, "S-Line (%s@%s) by (%#R)",
- cli_user(cptr)->username, hostonly, cptr);
- return 1;
- }
++ /* check host */
++ } else if (sconf->flags == SLINE_FLAGS_HOSTNAME) {
++ if ((match(sconf->realhost, cli_sockhost(cptr)) != 0) &&
++ (match(sconf->realhost, cli_sock_ip(cptr)) != 0)) /* wildcarded IP address */
++ continue;
++ } else
++ continue;
++
++ /* check username */
++ if (match(sconf->username, cli_user(cptr)->realusername) != 0)
++ continue;
++
+ /* invalid */
-+ if (!is_validsethost(NULL, hostonly))
++ if (!is_validsethost(NULL, sconf->spoofhost))
+ continue;
+
-+ /* do it and log */
-+ set_hostmask(cptr, NULL, hostonly);
-+ /* LOG_NOSNOTICE */
-+ log_write(LS_USER, L_INFO, 0, "AUTO SETHOST %s on %s",
-+ hostonly, get_client_name(cptr, SHOW_IP));
++ /* do it */
++ set_hostmask(cptr, NULL, sconf->spoofhost);
++
++ /* TODO: LOG_NOSNOTICE */
++ /* log it */
++ log_write(LS_USER, L_INFO, 0, "%s SETHOST %s (auto)",
++ get_client_name(cptr, SHOW_IP), sconf->spoofhost);
+ return 1;
}
return 0;
}
-+
-+
+/**
-+ *
++ * free a spoofblock
+ *
+ */
void free_spoofhost(struct sline *spoof) {
MyFree(spoof->spoofhost);
MyFree(spoof->passwd);
-diff -r c6f3803ee169 ircd/s_err.c
---- a/ircd/s_err.c
-+++ b/ircd/s_err.c
+diff -r 103be431b156 ircd/s_err.c
+--- a/ircd/s_err.c Sat Jul 20 12:01:10 2013 +0100
++++ b/ircd/s_err.c Sat Jul 20 13:18:35 2013 +0100
@@ -824,13 +824,13 @@
/* 395 */
{ 0 },
/* 532 */
{ 0 },
/* 533 */
-diff -r c6f3803ee169 ircd/s_stats.c
---- a/ircd/s_stats.c
-+++ b/ircd/s_stats.c
+diff -r 103be431b156 ircd/s_stats.c
+--- a/ircd/s_stats.c Sat Jul 20 12:01:10 2013 +0100
++++ b/ircd/s_stats.c Sat Jul 20 13:18:35 2013 +0100
@@ -400,41 +400,37 @@
}
}
}
}
-diff -r c6f3803ee169 ircd/s_user.c
---- a/ircd/s_user.c
-+++ b/ircd/s_user.c
+diff -r 103be431b156 ircd/s_user.c
+--- a/ircd/s_user.c Sat Jul 20 12:01:10 2013 +0100
++++ b/ircd/s_user.c Sat Jul 20 13:18:35 2013 +0100
@@ -73,9 +73,6 @@
#include <string.h>
#include <sys/stat.h>
- char hiddenhost[USERLEN + HOSTLEN + 2];
+
+ int userchange = 0;
-+ char hiddenhost[USERLEN + 1 + HOSTLEN + 1];
+ char *msg = "Host change";
struct Membership *chan;
+ /* remove sethost */
+ if (!host) {
+
-+ /* clear flag */
++ /* clear flags */
+ ClearSetHost(cptr);
++ ClearRemoteSetHost(cptr);
+
+ /* restore user and host */
+ if (HasHiddenHost(cptr))
}
break;
case 'R':
-@@ -1468,6 +1362,11 @@
+@@ -1468,6 +1362,23 @@
if (!FlagHas(&setflags, FLAG_PARANOID) && !(IsOper(sptr) && HasPriv(sptr, PRIV_PARANOID)))
ClearParanoid(sptr);
+ /* TODO: */
-+ /* only opers can remove a sethost */
-+ if (do_set_host && !hostmask && !FlagHas(&setflags, FLAG_LOCOP) && !FlagHas(&setflags, FLAG_OPER))
-+ do_set_host = 0;
++ /* setting -h */
++ if (do_set_host && !hostmask && IsSetHost(sptr)) {
++ /* cannot do -h if user has a remote sethost, unless they are an oper */
++ if (!FlagHas(&setflags, FLAG_LOCOP) && !FlagHas(&setflags, FLAG_OPER) && IsRemoteSetHost(sptr))
++ do_set_host = 0;
++ /* cannot do -h if user has no account set */
++ else if (!IsAccount(sptr))
++ do_set_host = 0;
++ /* cannot do -h if user does not have +x set and is not allowed to set it */
++ else if (!IsHiddenHost(sptr) && !feature_bool(FEAT_HOST_HIDING))
++ do_set_host = 0;
++ /* all ok, set user +x */
++ else
++ SetHiddenHost(sptr);
++ }
+
/*
* only send wallops to opers
*/
-@@ -1521,11 +1420,38 @@
+@@ -1521,11 +1432,38 @@
}
if (!FlagHas(&setflags, FLAG_HIDDENHOST) && do_host_hiding && allow_modes != ALLOWMODES_DEFAULT)
hide_hostmask(sptr, FLAG_HIDDENHOST);
+ */
+ if (*user == 0 || user[0] == ':' || *host == 0 || host[0] == ':')
+ protocol_violation(cptr, "Received MODE +h for %C with an invalid user@host '%s@%s'",
-+ sptr, user ? user : "", host);
++ sptr, user ? user : "", host ? host : "");
+
+ /* apply it */
+ else {
}
if (IsRegistered(sptr)) {
-@@ -1577,7 +1503,7 @@
+@@ -1577,7 +1515,7 @@
}
assert(UserStats.opers <= UserStats.clients + UserStats.unknowns);
assert(UserStats.inv_clients <= UserStats.clients + UserStats.unknowns);
}
return 0;
-@@ -1652,9 +1578,11 @@
+@@ -1652,9 +1590,11 @@
* @param[in] old Pre-change set of modes for \a sptr.
* @param[in] sendset One of ALL_UMODES, SEND_UMODES_BUT_OPER,
* SEND_UMODES, to select which changed user modes to send.
{
int i;
int flag;
-@@ -1697,12 +1625,15 @@
+@@ -1697,12 +1637,15 @@
}
/* Special case for SETHOST.. */
if (flag == FLAG_SETHOST) {
needhost++;
}
if (FlagHas(old, flag))
-@@ -1741,7 +1672,7 @@
+@@ -1741,7 +1684,7 @@
}
if (needhost) {
*m++ = ' ';
cli_user(sptr)->host);
} else
*m = '\0';
-@@ -1769,108 +1700,53 @@
+@@ -1769,108 +1712,53 @@
return 0;
}
}
/** Update snomask \a oldmask according to \a arg and \a what.
-diff -r c6f3803ee169 ircd/send.c
---- a/ircd/send.c
-+++ b/ircd/send.c
+diff -r 103be431b156 ircd/send.c
+--- a/ircd/send.c Sat Jul 20 12:01:10 2013 +0100
++++ b/ircd/send.c Sat Jul 20 13:18:35 2013 +0100
@@ -281,7 +281,7 @@
{
case MATCH_HOST:
case MATCH_SERVER:
default:
return (match(mask, cli_name(cli_user(one)->server)) == 0);
-diff -r c6f3803ee169 ircd/whocmds.c
---- a/ircd/whocmds.c
-+++ b/ircd/whocmds.c
+diff -r 103be431b156 ircd/whocmds.c
+--- a/ircd/whocmds.c Sat Jul 20 12:01:10 2013 +0100
++++ b/ircd/whocmds.c Sat Jul 20 13:18:35 2013 +0100
@@ -134,7 +134,7 @@
if (fields & WHO_FIELD_NIP)