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)
remote sethost can come from any server, does not need to have a Uworld block or be a service (ACCOUNT doesnt require that either)
+allow chars -. 0-9 A-Z [\]^_ a-Z {|} ~: in user and host part of sethost (only change is that : is allowed because of IPv6)
+
STATS s
show if spoofhost is valid or not (S = valid, s = invalid)
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/numeric.h
---- a/include/numeric.h
-+++ b/include/numeric.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. */
+ #define IsHostChar(c) (IRCD_CharAttrTab[(c) - CHAR_MIN] & NTL_IRCHN)
++/** Test whether a character is valid in a sethost - snircd */
++#define IsSetHostChar(c) (IRCD_CharAttrTab[(c) - CHAR_MIN] & (NTL_IRCHN|NTL_IRCIP6))
+ /** Test whether a character is valid in an IPv4 address. */
+ #define IsIPChar(c) (IRCD_CharAttrTab[(c) - CHAR_MIN] & NTL_IRCIP)
+ /** Test whether a character is valid in an IPv6 address. */
+@@ -127,4 +129,5 @@
+ #define IsKTimeChar(c) (IRCD_CharAttrTab[(c) - CHAR_MIN] & NTL_KTIME)
+
+
++
+ #endif /* INCLUDED_ircd_chattr_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,221 @@
+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])) {
+ set_hostmask(sptr, user, host);
+
+ /* log freeform */
-+ if (freeform)
-+ log_write(LS_SETHOST, L_NOTICE, 0,
-+ "SETHOST (%s@%s) by (%#R) using freeform",
-+ cli_user(cptr)->username, cli_user(cptr)->host, cptr);
++ if (freeform) {
++
++ sendto_opmask_butone(0, SNO_OLDSNO,
++ "%C SETHOST %s%s%s (freeform)", sptr,
++ user ? user : "", user ? "@" : "", host);
++
++ log_write(LS_SETHOST, L_NOTICE, LOG_NOSNOTICE,
++ "%s SETHOST %s%s%s (freeform)", get_client_name(sptr, SHOW_IP),
++ user ? user : "", user ? "@" : "", host);
++ }
+
+ /* send the mode out */
+ send_umode_out(cptr, sptr, &setflags, 0, alreadyh);
+ struct Client *acptr;
struct Flags setflags;
++ /* not from a server */
++ if (!IsServer(sptr))
++ return protocol_violation(cptr, "Received SETHOST from user %C", sptr);
++
+ /* check paramaters */
if (parc < 4)
- return need_more_params(sptr, "SETHOST");
+- return need_more_params(sptr, "SETHOST");
++ return protocol_violation(cptr, "Received too few parameters for SETHOST from %C (got %d - need 4)", sptr, parc);
+- if (!IsServer(sptr))
+- return protocol_violation(cptr, "SETHOST from non-server %s",
+- cli_name(sptr));
+ target = parv[1];
+ user = parv[2];
+ host = parv[3];
-+
-+ /* not from a server */
- if (!IsServer(sptr))
-- return protocol_violation(cptr, "SETHOST from non-server %s",
-- cli_name(sptr));
-+ return protocol_violation(cptr, "SETHOST from non-server %s", cli_name(sptr));
- /* Locate our target user; ignore the message if we can't */
- if(!(target = findNUser(parv[1])))
+ /* check user and host are valid */
+ if (!is_validsethost(user, host))
+ return protocol_violation(cptr,
-+ "Server %C tried to SETHOST user %C with a badmask: %s@%s",
-+ sptr, acptr, user, host);
++ "Received SETHOST for %C with invalid user host '%s %s' from %C",
++ acptr, user, host, sptr);
+
+ /* 'user host' is '0 0' - undo sethost */
+ if (user[0] == '0' && user[1] == '\0' &&
+
+ /* user has no sethost or has no account
+ *
-+ * user has +h their host is hidden, do not remove it
++ * user has +h - their host is hidden, do not remove it
+ * unless the user has an account set
+ * we should not out of the blue expose the real host
+ */
}
- 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,162 @@
- * -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 *sconf;
+ *
+ */
++struct sline *find_spoofblock(struct Client *cptr, char *host, char *password) {
+
+-int
+-conf_check_slines(struct Client *cptr)
+-{
+ struct sline *sconf;
+- char *hostonly;
+ int result = 0;
+ int r = 0;
-
-+ Debug((DEBUG_INFO, "find_spoofblock() cptr=%C spoofhost=%s password=%s",
-+ cptr, spoofhost, password));
++ char *error;
+
-+ 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;
+ }
+ continue;
+
+ /* got one */
-+ log_write(LS_SETHOST, L_INFO, 0,
-+ "SETHOST (%s) by (%#R): ", sconf->spoofhost, cptr);
++ log_write(LS_SETHOST, L_INFO, 0, "%s SETHOST %s (ok) [password: %s]",
++ get_client_name(cptr, SHOW_IP), sconf->spoofhost,
++ password ? "yes" : "no");
+ return sconf;
+ }
+
++ /* set error messages */
++ switch (result) {
++ case 0:
++ error = "no such Spoof block";
++ break;
++ case 1:
++ error = "IP / host mismatch";
++ break;
++ case 2:
++ error = "username mismatch";
++ break;
++ case 3:
++ error = password ? "password mismatch" : "password required";
++ break;
++ default:
++ error = "unknown failure";
++ }
++
+ /* TODO: lookup LOG stuff */
+ /* TODO: L_INFO LOG_NOSNOTICE */
-+ /* log of best result we got */
-+ if (result == 0)
-+ log_write(LS_SETHOST, L_INFO, 0,
-+ "SETHOST (%s) by (%#R): no such Spoof block", spoofhost, cptr);
-+ if (result == 1)
-+ log_write(LS_SETHOST, L_INFO, 0,
-+ "SETHOST (%s) by (%#R): IP / host mismatch", spoofhost, cptr);
-+ if (result == 2)
-+ log_write(LS_SETHOST, L_INFO, 0,
-+ "SETHOST (%s) by (%#R): username mismatch", spoofhost, cptr);
-+ if (result == 3)
-+ log_write(LS_SETHOST, L_INFO, 0,
-+ "SETHOST (%s) by (%#R): %s", spoofhost, cptr,
-+ password ? "password mismatch" : "password required");
++ /* 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), 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))
+ /* TODO: */
+ if (IsServer(cptr)) {
+ if (!*(p + 1))
-+ protocol_violation(cptr, "Received MODE +h for user %C without sethost parameter", sptr);
++ protocol_violation(cptr, "Received MODE +h for %C without sethost parameter", sptr);
else {
- send_reply(sptr, ERR_BADHOSTMASK, *(p+1));
- p++; /* Swallow the arg anyway */
}
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,40 @@
+@@ -1521,11 +1432,38 @@
}
if (!FlagHas(&setflags, FLAG_HIDDENHOST) && do_host_hiding && allow_modes != ALLOWMODES_DEFAULT)
hide_hostmask(sptr, FLAG_HIDDENHOST);
+ else
+ host = hostmask;
+
-+ /* invalid */
-+ /* if (!user || !is_validsethost(user, USERLEN) || !is_validsethost(host, HOSTLEN)) */
-+ /* dont check if sethost from remote users is valid,
-+ * do check that user is not emtpy and
++ /* dont check if sethost from remote users is valid with is_validsethost(),
++ * do check that user and host are not emtpy and
+ * do check if they start with a : as things go horribly wrong then
+ */
-+ if (*user == 0 || user[0] == ':' || host[0] == ':')
-+ protocol_violation(cptr, "Received MODE +h for user %C with an invalid sethost parameter '%s@%s'",
-+ sptr, user ? user : "", host);
++ 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 ? host : "");
+
+ /* apply it */
+ else {
}
if (IsRegistered(sptr)) {
-@@ -1577,7 +1505,7 @@
+@@ -1577,7 +1515,7 @@
}
assert(UserStats.opers <= UserStats.clients + UserStats.unknowns);
assert(UserStats.inv_clients <= UserStats.clients + UserStats.unknowns);
}
return 0;
-@@ -1652,9 +1580,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 +1627,15 @@
+@@ -1697,12 +1637,15 @@
}
/* Special case for SETHOST.. */
if (flag == FLAG_SETHOST) {
needhost++;
}
if (FlagHas(old, flag))
-@@ -1741,7 +1674,7 @@
+@@ -1741,7 +1684,7 @@
}
if (needhost) {
*m++ = ' ';
cli_user(sptr)->host);
} else
*m = '\0';
-@@ -1769,108 +1702,85 @@
+@@ -1769,108 +1712,53 @@
return 0;
}
{
- int i = 0;
- char *host;
-+ int i;
-+ int validhost = 1;
++ int i; /* loop variable */
- Debug((DEBUG_INFO, "is_hostmask() %s", word));
+ assert(host != NULL);
- if (strlen(word) > (HOSTLEN + USERLEN + 1) || strlen(word) <= 0)
-+ /* must not be empty, not longer than HOSTLEN, must not start with a : */
++ /* must not be empty, not longer than HOSTLEN, not start with a : */
+ if (*host == 0 || strlen(host) > HOSTLEN || host[0] == ':')
return 0;
+ /* got a user part */
+ if (user) {
+
-+ /* must not be empty, not longer than USERLEN, must not just be '~' */
-+ if (*user == 0 || strlen(user) > USERLEN || (user[0] == '~' && user[1] == '\0'))
++ /* must not be empty, not longer than USERLEN, not start with a : */
++ if (*user == 0 || strlen(user) > USERLEN || user[0] == ':')
+ return 0;
+
-+ /* dont allow []{}\|^ chars (they are allowed by IsHostChar) */
-+ for (i = 0; user[i]; i++) {
-+ if (user[i] == '[' || user[i] == ']' ||
-+ user[i] == '{' || user[i] == '}' ||
-+ user[i] == '\\' || user[i] == '|' ||
-+ (i > 0 && user[i] == '~') || /* only allow ~ at the start */
-+ user[i] == '^' || user[i] == '.')
-+ return 0;
-+ }
-+
-+ /* check if chars in user part are valid for a username
-+ * use IsHostChar instead of IsUserChar
++ /* check user chars
++ * use IsSetHostChar instead of IsUserChar
+ * as the latter allows a lot more chars
+ * we dont want in a sethost
+ */
+ for (i = 0; user[i]; i++) {
-+ if (!IsHostChar(user[i]))
++ if (!IsSetHostChar(user[i]))
+ return 0;
+ }
}
- return sconf->spoofhost;
- }
- return NULL;
-+ /* dont allow []{}\|~^ chars (they are allowed by IsHostChar) */
++ /* check host chars
++ * IsSetHostChar allows -. 0-9 A-Z [\]^_ a-Z {|} ~ and :
++ */
+ for (i = 0; host[i]; i++) {
-+ if (host[i] == '[' || host[i] == ']' ||
-+ host[i] == '{' || host[i] == '}' ||
-+ host[i] == '\\' || host[i] == '|' ||
-+ host[i] == '~' || host[i] == '^')
++ if (!IsSetHostChar(host[i]))
+ return 0;
}
- for (sconf = GlobalSList; sconf; sconf = sconf->next)
- if (strCasediff(hostmask, sconf->spoofhost) == 0)
- return sconf->spoofhost;
-+ /* check host chars
-+ * IsHostChar allows -. 0-9 A-Z [\]^_ a-Z {|} ~
-+ */
-+ for (i = 0; host[i]; i++) {
-+ if (IsHostChar(host[i]))
-+ continue;
-+ validhost = 0;
-+ break;
-+ }
-+ if (validhost) /* valid host */
-+ return 1;
-
+-
- return NULL;
-}
-+ /* check ipv6 chars
-+ * IsIP6Char allows 0-9 a-f A-F :.
-+ */
-+ for (i = 0; host[i]; i++) {
-+ if (!IsIP6Char(host[i]))
-+ return 0;
-+ }
-
+-
- /*
- * IsVhostPass() - Check if given spoofhost has a password
- * associated with it, and if, return the password (cleartext)
- }
-
- return NULL;
-+ /* valid ipv6 */
++ /* valid */
+ return 1;
}
/** 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)