diff -Nurp ircu2.10.12.10/doc/example.conf ircu2.10.12.10-fakehosts/doc/example.conf --- ircu2.10.12.10/doc/example.conf 2007-02-25 16:40:22.000000000 +0100 +++ ircu2.10.12.10-fakehosts/doc/example.conf 2007-03-13 02:14:07.000000000 +0100 @@ -227,10 +227,11 @@ Class { # badchan (can issue Gchans to other servers) # force_opmode (can use OPMODE/CLEARMODE on quarantined global channels) # apass_opmode (can use OPMODE/CLEARMODE on +A and +U keys) + # set_fakehost (can set own fakehost with /fake) # # For global opers (with propagate = yes or local = no), the default # is to grant all of the above privileges EXCEPT walk_lchan, - # unlimit_query, set, badchan, local_badchan and apass_opmode. + # unlimit_query, set, badchan, local_badchan, apass_opmode and set_fakehost. # For local opers, the default is to grant ONLY the following # privileges: # chan_limit, mode_lchan, show_invis, show_all_invis, local_kill, diff -Nurp ircu2.10.12.10/include/class.h ircu2.10.12.10-fakehosts/include/class.h --- ircu2.10.12.10/include/class.h 2005-10-05 03:51:34.000000000 +0200 +++ ircu2.10.12.10-fakehosts/include/class.h 2007-03-13 02:14:07.000000000 +0100 @@ -42,6 +42,8 @@ struct ConnectionClass { char *cc_name; /**< Name of connection class. */ char *default_umode; /**< Default usermode for users in this class. */ + char *default_fakehost; /**< Default fakehost for users + in this class */ struct Privs privs; /**< Privilege bits that are set on or off. */ struct Privs privs_dirty; /**< Indication of which bits in @@ -86,6 +88,8 @@ struct ConnectionClass { #define ConfLinks(x) ((x)->conn_class->ref_count) /** Get default usermode for ConfItem \a x. */ #define ConfUmode(x) ((x)->conn_class->default_umode) +/** Get default fakehost for ConfItem \a x. */ +#define ConfFakehost(x) ((x)->conn_class->default_fakehost) /** Find a valid configuration class by name. */ #define find_class(name) do_find_class((name), 0) diff -Nurp ircu2.10.12.10/include/client.h ircu2.10.12.10-fakehosts/include/client.h --- ircu2.10.12.10/include/client.h 2006-02-16 04:49:54.000000000 +0100 +++ ircu2.10.12.10-fakehosts/include/client.h 2007-03-13 02:14:07.000000000 +0100 @@ -126,6 +126,7 @@ enum Priv PRIV_FORCE_OPMODE, /**< can hack modes on quarantined channels */ PRIV_FORCE_LOCAL_OPMODE, /**< can hack modes on quarantined local channels */ PRIV_APASS_OPMODE, /**< can hack modes +A/-A/+U/-U */ + PRIV_SET_FAKEHOST, /**< can set own fakehost with /fake */ PRIV_LAST_PRIV /**< number of privileges */ }; @@ -166,6 +167,7 @@ enum Flag FLAG_DEBUG, /**< send global debug/anti-hack info */ FLAG_ACCOUNT, /**< account name has been set */ FLAG_HIDDENHOST, /**< user's host is hidden */ + FLAG_FAKEHOST, /**< user has been assigned a fake host */ FLAG_LAST_FLAG, /**< number of flags */ FLAG_LOCAL_UMODES = FLAG_LOCOP, /**< First local mode flag */ FLAG_GLOBAL_UMODES = FLAG_OPER /**< First global mode flag */ @@ -585,7 +587,8 @@ struct Client { /** Return non-zero if the client has operator or server privileges. */ #define IsPrivileged(x) (IsAnOper(x) || IsServer(x)) /** Return non-zero if the client's host is hidden. */ -#define HasHiddenHost(x) (IsHiddenHost(x) && IsAccount(x)) +#define HasHiddenHost(x) (IsHiddenHost(x) && (IsAccount(x) || HasFakeHost(x))) +#define HasFakeHost(x) HasFlag(x, FLAG_FAKEHOST) /** Mark a client as having an in-progress net.burst. */ #define SetBurst(x) SetFlag(x, FLAG_BURST) @@ -625,6 +628,8 @@ struct Client { #define SetAccount(x) SetFlag(x, FLAG_ACCOUNT) /** Mark a client as having mode +x (hidden host). */ #define SetHiddenHost(x) SetFlag(x, FLAG_HIDDENHOST) +/** Mark a client as having a fake host. */ +#define SetFakeHost(x) SetFlag(x, FLAG_FAKEHOST) /** Mark a client as having a pending PING. */ #define SetPingSent(x) SetFlag(x, FLAG_PINGSENT) @@ -658,6 +663,8 @@ struct Client { #define ClearServNotice(x) ClrFlag(x, FLAG_SERVNOTICE) /** Remove mode +x (hidden host) from the client. */ #define ClearHiddenHost(x) ClrFlag(x, FLAG_HIDDENHOST) +/** Remove fake host flag from the flient. */ +#define ClearFakeHost(x) ClrFlag(x, FLAG_FAKEHOST) /** Clear the client's pending PING flag. */ #define ClearPingSent(x) ClrFlag(x, FLAG_PINGSENT) @@ -727,6 +734,7 @@ struct Client { extern const char* get_client_name(const struct Client* sptr, int showip); extern const char* client_get_default_umode(const struct Client* sptr); +extern const char* client_get_default_fakehost(const struct Client* sptr); extern int client_get_ping(const struct Client* local_client); extern void client_drop_sendq(struct Connection* con); extern void client_add_sendq(struct Connection* con, diff -Nurp ircu2.10.12.10/include/handlers.h ircu2.10.12.10-fakehosts/include/handlers.h --- ircu2.10.12.10/include/handlers.h 2005-04-02 04:50:12.000000000 +0200 +++ ircu2.10.12.10-fakehosts/include/handlers.h 2007-03-13 02:14:07.000000000 +0100 @@ -91,6 +91,7 @@ extern int m_away(struct Client*, struct extern int m_cap(struct Client*, struct Client*, int, char*[]); extern int m_cnotice(struct Client*, struct Client*, int, char*[]); extern int m_cprivmsg(struct Client*, struct Client*, int, char*[]); +extern int m_fakehost(struct Client*, struct Client*, int, char*[]); extern int m_gline(struct Client*, struct Client*, int, char*[]); extern int m_help(struct Client*, struct Client*, int, char*[]); extern int m_ignore(struct Client*, struct Client*, int, char*[]); @@ -187,6 +188,7 @@ extern int ms_desynch(struct Client*, st extern int ms_end_of_burst(struct Client*, struct Client*, int, char*[]); extern int ms_end_of_burst_ack(struct Client*, struct Client*, int, char*[]); extern int ms_error(struct Client*, struct Client*, int, char*[]); +extern int ms_fakehost(struct Client*, struct Client*, int, char*[]); extern int ms_gline(struct Client*, struct Client*, int, char*[]); extern int ms_info(struct Client*, struct Client*, int, char*[]); extern int ms_invite(struct Client*, struct Client*, int, char*[]); diff -Nurp ircu2.10.12.10/include/msg.h ircu2.10.12.10-fakehosts/include/msg.h --- ircu2.10.12.10/include/msg.h 2005-04-02 04:50:13.000000000 +0200 +++ ircu2.10.12.10-fakehosts/include/msg.h 2007-03-13 02:14:07.000000000 +0100 @@ -340,6 +340,10 @@ struct Client; #define TOK_ASLL "LL" #define CMD_ASLL MSG_ASLL, TOK_ASLL +#define MSG_FAKEHOST "FAKE" /* FAKE */ +#define TOK_FAKEHOST "FA" +#define CMD_FAKEHOST MSG_FAKEHOST, TOK_FAKEHOST + #define MSG_POST "POST" /* POST */ #define TOK_POST "POST" diff -Nurp ircu2.10.12.10/include/s_user.h ircu2.10.12.10-fakehosts/include/s_user.h --- ircu2.10.12.10/include/s_user.h 2006-02-16 04:49:54.000000000 +0100 +++ ircu2.10.12.10-fakehosts/include/s_user.h 2007-03-13 02:14:07.000000000 +0100 @@ -75,7 +75,8 @@ extern int whisper(struct Client* source extern void send_user_info(struct Client* to, char* names, int rpl, InfoFormatter fmt); -extern int hide_hostmask(struct Client *cptr, unsigned int flags); +extern void make_hidden_hostmask(char *buffer, struct Client *cptr); +extern int hide_hostmask(struct Client *cptr); extern int set_user_mode(struct Client *cptr, struct Client *sptr, int parc, char *parv[]); extern int is_silenced(struct Client *sptr, struct Client *acptr); diff -Nurp ircu2.10.12.10/include/struct.h ircu2.10.12.10-fakehosts/include/struct.h --- ircu2.10.12.10/include/struct.h 2007-01-15 04:08:23.000000000 +0100 +++ ircu2.10.12.10-fakehosts/include/struct.h 2007-03-13 02:14:07.000000000 +0100 @@ -82,6 +82,7 @@ struct User { char username[USERLEN + 1]; char host[HOSTLEN + 1]; /**< displayed hostname */ char realhost[HOSTLEN + 1]; /**< actual hostname */ + char fakehost[HOSTLEN + 1]; /**< fake hostname */ char account[ACCOUNTLEN + 1]; /**< IRC account name */ time_t acc_create; /**< IRC account timestamp */ }; Files ircu2.10.12.10/ircd/.s_user.c.swp and ircu2.10.12.10-fakehosts/ircd/.s_user.c.swp differ diff -Nurp ircu2.10.12.10/ircd/Makefile.in ircu2.10.12.10-fakehosts/ircd/Makefile.in --- ircu2.10.12.10/ircd/Makefile.in 2006-05-18 05:48:41.000000000 +0200 +++ ircu2.10.12.10-fakehosts/ircd/Makefile.in 2007-03-13 02:14:07.000000000 +0100 @@ -130,6 +130,7 @@ IRCD_SRC = \ m_die.c \ m_endburst.c \ m_error.c \ + m_fakehost.c \ m_get.c \ m_gline.c \ m_help.c \ @@ -599,6 +600,13 @@ m_asll.o: m_asll.c ../config.h ../includ ../include/ircd_string.h ../include/ircd_chattr.h ../include/numeric.h \ ../include/numnicks.h ../include/match.h ../include/msg.h \ ../include/send.h ../include/s_bsd.h ../include/s_user.h +m_fakehost.o: m_fakehost.c ../config.h ../include/client.h \ + ../include/ircd_defs.h ../include/dbuf.h ../include/msgq.h \ + ../include/ircd_events.h ../include/ircd_handler.h ../include/hash.h \ + ../include/ircd.h ../include/struct.h ../include/ircd_reply.h \ + ../include/ircd_string.h ../include/ircd_chattr.h ../include/msg.h \ + ../include/numeric.h ../include/numnicks.h ../include/s_conf.h \ + ../include/s_user.h ../include/send.h m_away.o: m_away.c ../config.h ../include/client.h ../include/ircd_defs.h \ ../include/dbuf.h ../include/msgq.h ../include/ircd_events.h \ ../config.h ../include/ircd_handler.h ../include/res.h \ diff -Nurp ircu2.10.12.10/ircd/channel.c ircu2.10.12.10-fakehosts/ircd/channel.c --- ircu2.10.12.10/ircd/channel.c 2007-02-04 05:11:08.000000000 +0100 +++ ircu2.10.12.10-fakehosts/ircd/channel.c 2007-03-13 02:14:07.000000000 +0100 @@ -374,17 +374,26 @@ struct Ban *find_ban(struct Client *cptr char tmphost[HOSTLEN + 1]; char iphost[SOCKIPLEN + 1]; char *hostmask; - char *sr; + char *sr, *sr2; struct Ban *found; /* Build nick!user and alternate host names. */ ircd_snprintf(0, nu, sizeof(nu), "%s!%s", cli_name(cptr), cli_user(cptr)->username); ircd_ntoa_r(iphost, &cli_ip(cptr)); + sr2 = NULL; if (!IsAccount(cptr)) sr = NULL; else if (HasHiddenHost(cptr)) + { sr = cli_user(cptr)->realhost; + if (HasFakeHost(cptr)) + { + ircd_snprintf(0, tmphost, HOSTLEN, "%s.%s", + cli_user(cptr)->account, feature_str(FEAT_HIDDEN_HOST)); + sr2 = tmphost; + } + } else { ircd_snprintf(0, tmphost, HOSTLEN, "%s.%s", @@ -409,7 +418,8 @@ struct Ban *find_ban(struct Client *cptr if (!((banlist->flags & BAN_IPMASK) && ipmask_check(&cli_ip(cptr), &banlist->address, banlist->addrbits)) && match(hostmask, cli_user(cptr)->host) - && !(sr && !match(hostmask, sr))) + && !(sr && !match(hostmask, sr)) + && !(sr2 && !match(hostmask, sr2))) continue; /* If an exception matches, no ban can match. */ if (banlist->flags & BAN_EXCEPTION) diff -Nurp ircu2.10.12.10/ircd/client.c ircu2.10.12.10-fakehosts/ircd/client.c --- ircu2.10.12.10/ircd/client.c 2005-10-13 01:50:04.000000000 +0200 +++ ircu2.10.12.10-fakehosts/ircd/client.c 2007-03-13 02:14:07.000000000 +0100 @@ -88,6 +88,25 @@ const char* client_get_default_umode(con return NULL; } +/* + * client_get_default_fakehost + * returns default fakehost in attached client connection class + */ +const char* client_get_default_fakehost(const struct Client* sptr) +{ + struct ConfItem* aconf; + struct SLink* link; + + assert(cli_verify(sptr)); + + for (link = cli_confs(sptr); link; link = link->next) { + aconf = link->value.aconf; + if ((aconf->status & CONF_CLIENT) && ConfFakehost(aconf)) + return ConfFakehost(aconf); + } + return NULL; +} + /** Remove a connection from the list of connections with queued data. * @param[in] con Connection with no queued data. */ @@ -158,6 +177,7 @@ client_set_privs(struct Client *client, FlagClr(&privs_global, PRIV_BADCHAN); FlagClr(&privs_global, PRIV_LOCAL_BADCHAN); FlagClr(&privs_global, PRIV_APASS_OPMODE); + FlagClr(&privs_global, PRIV_SET_FAKEHOST); memset(&privs_local, 0, sizeof(privs_local)); FlagSet(&privs_local, PRIV_CHAN_LIMIT); @@ -235,7 +255,7 @@ static struct { P(OPMODE), P(LOCAL_OPMODE), P(SET), P(WHOX), P(BADCHAN), P(LOCAL_BADCHAN), P(SEE_CHAN), P(PROPAGATE), P(DISPLAY), P(SEE_OPERS), P(WIDE_GLINE), P(LIST_CHAN), - P(FORCE_OPMODE), P(FORCE_LOCAL_OPMODE), P(APASS_OPMODE), + P(FORCE_OPMODE), P(FORCE_LOCAL_OPMODE), P(APASS_OPMODE), P(SET_FAKEHOST), #undef P { 0, 0 } }; diff -Nurp ircu2.10.12.10/ircd/ircd_lexer.l ircu2.10.12.10-fakehosts/ircd/ircd_lexer.l --- ircu2.10.12.10/ircd/ircd_lexer.l 2007-02-25 16:41:48.000000000 +0100 +++ ircu2.10.12.10-fakehosts/ircd/ircd_lexer.l 2007-03-13 02:14:07.000000000 +0100 @@ -100,6 +100,7 @@ static struct lexer_token { TOKEN(PSEUDO), TOKEN(PREPEND), TOKEN(USERMODE), + TOKEN(FAKEHOST), TOKEN(FAST), TOKEN(AUTOCONNECT), TOKEN(PROGRAM), @@ -143,6 +144,7 @@ static struct lexer_token { { "see_chan", TPRIV_SEE_CHAN }, { "see_opers", TPRIV_SEE_OPERS }, { "set", TPRIV_SET }, + { "set_fakehost", TPRIV_SET_FAKEHOST }, { "show_all_invis", TPRIV_SHOW_ALL_INVIS }, { "show_invis", TPRIV_SHOW_INVIS }, { "tb", TBYTES }, diff -Nurp ircu2.10.12.10/ircd/ircd_parser.y ircu2.10.12.10-fakehosts/ircd/ircd_parser.y --- ircu2.10.12.10/ircd/ircd_parser.y 2007-02-25 16:41:48.000000000 +0100 +++ ircu2.10.12.10-fakehosts/ircd/ircd_parser.y 2007-03-13 02:14:07.000000000 +0100 @@ -157,6 +157,7 @@ static void parse_error(char *pattern,.. %token PSEUDO %token PREPEND %token USERMODE +%token FAKEHOST %token IAUTH %token TIMEOUT %token FAST @@ -171,7 +172,7 @@ static void parse_error(char *pattern,.. %token TPRIV_LOCAL_OPMODE TPRIV_OPMODE TPRIV_SET TPRIV_WHOX TPRIV_BADCHAN %token TPRIV_SEE_CHAN TPRIV_SHOW_INVIS TPRIV_SHOW_ALL_INVIS TPRIV_PROPAGATE %token TPRIV_UNLIMIT_QUERY TPRIV_DISPLAY TPRIV_SEE_OPERS TPRIV_WIDE_GLINE -%token TPRIV_FORCE_OPMODE TPRIV_FORCE_LOCAL_OPMODE TPRIV_APASS_OPMODE +%token TPRIV_FORCE_OPMODE TPRIV_FORCE_LOCAL_OPMODE TPRIV_APASS_OPMODE TPRIV_SET_FAKEHOST %token TPRIV_LIST_CHAN /* and some types... */ %type sizespec @@ -406,6 +407,7 @@ classblock: CLASS { c_class = find_class(name); MyFree(c_class->default_umode); c_class->default_umode = pass; + c_class->default_fakehost = host; memcpy(&c_class->privs, &privs, sizeof(c_class->privs)); memcpy(&c_class->privs_dirty, &privs_dirty, sizeof(c_class->privs_dirty)); } @@ -414,6 +416,7 @@ classblock: CLASS { } name = NULL; pass = NULL; + host = NULL; tconn = 0; maxlinks = 0; sendq = 0; @@ -422,7 +425,7 @@ classblock: CLASS { }; classitems: classitem classitems | classitem; classitem: classname | classpingfreq | classconnfreq | classmaxlinks | - classsendq | classusermode | priv; + classsendq | classusermode | classfakehost | priv; classname: NAME '=' QSTRING ';' { MyFree(name); @@ -449,6 +452,12 @@ classusermode: USERMODE '=' QSTRING ';' MyFree(pass); pass = $3; }; +classfakehost: FAKEHOST '=' QSTRING ';' +{ + if (host) + MyFree(host); + DupString(host, yylval.text); +} connectblock: CONNECT { @@ -665,7 +674,8 @@ privtype: TPRIV_CHAN_LIMIT { $$ = PRIV_C LOCAL { $$ = PRIV_PROPAGATE; invert = 1; } | TPRIV_FORCE_OPMODE { $$ = PRIV_FORCE_OPMODE; } | TPRIV_FORCE_LOCAL_OPMODE { $$ = PRIV_FORCE_LOCAL_OPMODE; } | - TPRIV_APASS_OPMODE { $$ = PRIV_APASS_OPMODE; } ; + TPRIV_APASS_OPMODE { $$ = PRIV_APASS_OPMODE; } | + TPRIV_SET_FAKEHOST { $$ = PRIV_SET_FAKEHOST; } ; yesorno: YES { $$ = 1; } | NO { $$ = 0; }; diff -Nurp ircu2.10.12.10/ircd/m_account.c ircu2.10.12.10-fakehosts/ircd/m_account.c --- ircu2.10.12.10/ircd/m_account.c 2004-12-11 06:13:46.000000000 +0100 +++ ircu2.10.12.10-fakehosts/ircd/m_account.c 2007-03-13 02:14:07.000000000 +0100 @@ -106,6 +106,7 @@ int ms_account(struct Client* cptr, stru char* parv[]) { struct Client *acptr; + int hidden; if (parc < 3) return need_more_params(sptr, "ACCOUNT"); @@ -136,8 +137,11 @@ int ms_account(struct Client* cptr, stru "timestamp %Tu", parv[2], cli_user(acptr)->acc_create)); } + hidden = HasHiddenHost(acptr); + SetAccount(acptr); ircd_strncpy(cli_user(acptr)->account, parv[2], ACCOUNTLEN); - hide_hostmask(acptr, FLAG_ACCOUNT); + if (!hidden) + hide_hostmask(acptr); sendcmdto_serv_butone(sptr, CMD_ACCOUNT, cptr, cli_user(acptr)->acc_create ? "%C %s %Tu" : "%C %s", diff -Nurp ircu2.10.12.10/ircd/m_fakehost.c ircu2.10.12.10-fakehosts/ircd/m_fakehost.c --- ircu2.10.12.10/ircd/m_fakehost.c 1970-01-01 01:00:00.000000000 +0100 +++ ircu2.10.12.10-fakehosts/ircd/m_fakehost.c 2007-03-13 02:14:07.000000000 +0100 @@ -0,0 +1,161 @@ +/* + * IRC - Internet Relay Chat, ircd/m_fakehost.c + * Copyright (C) 2004 Zoot + * + * See file AUTHORS in IRC package for additional names of + * the programmers. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 1, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * $Id$ + */ + +/* + * m_functions execute protocol messages on this server: + * + * cptr is always NON-NULL, pointing to a *LOCAL* client + * structure (with an open socket connected!). This + * identifies the physical socket where the message + * originated (or which caused the m_function to be + * executed--some m_functions may call others...). + * + * sptr is the source of the message, defined by the + * prefix part of the message if present. If not + * or prefix not found, then sptr==cptr. + * + * (!IsServer(cptr)) => (cptr == sptr), because + * prefixes are taken *only* from servers... + * + * (IsServer(cptr)) + * (sptr == cptr) => the message didn't + * have the prefix. + * + * (sptr != cptr && IsServer(sptr) means + * the prefix specified servername. (?) + * + * (sptr != cptr && !IsServer(sptr) means + * that message originated from a remote + * user (not local). + * + * combining + * + * (!IsServer(sptr)) means that, sptr can safely + * taken as defining the target structure of the + * message in this server. + * + * *Always* true (if 'parse' and others are working correct): + * + * 1) sptr->from == cptr (note: cptr->from == cptr) + * + * 2) MyConnect(sptr) <=> sptr == cptr (e.g. sptr + * *cannot* be a local connection, unless it's + * actually cptr!). [MyConnect(x) should probably + * be defined as (x == x->from) --msa ] + * + * parc number of variable parameter strings (if zero, + * parv is allowed to be NULL) + * + * parv a NULL terminated list of parameter pointers, + * + * parv[0], sender (prefix string), if not present + * this points to an empty string. + * parv[1]...parv[parc-1] + * pointers to additional parameters + * parv[parc] == NULL, *always* + * + * note: it is guaranteed that parv[0]..parv[parc-1] are all + * non-NULL pointers. + */ +#include "config.h" + +#include "client.h" +#include "hash.h" +#include "ircd.h" +#include "ircd_reply.h" +#include "ircd_string.h" +#include "msg.h" +#include "numeric.h" +#include "numnicks.h" +#include "s_conf.h" +#include "s_user.h" +#include "send.h" +#include + +/* + * m_fakehost - fakehost user message handler + * + * parv[0] = sender prefix + * parv[1] = new fake host + */ +int m_fakehost(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) +{ + if (!HasPriv(sptr, PRIV_SET_FAKEHOST)) + return send_reply(sptr, ERR_NOPRIVILEGES); + + if (parc < 2) + return need_more_params(sptr, "FAKEHOST"); + + /* Ignore the assignment if it changes nothing */ + if (HasFakeHost(cptr) && + ircd_strcmp(cli_user(cptr)->fakehost, parv[1]) == 0) + { + return 0; + } + + /* Assign and propagate the fakehost */ + SetFakeHost(cptr); + ircd_strncpy(cli_user(cptr)->fakehost, parv[1], HOSTLEN); + hide_hostmask(cptr); + + sendcmdto_serv_butone(sptr, CMD_FAKEHOST, cptr, "%C %s", sptr, + cli_user(cptr)->fakehost); + return 0; +} + +/* + * ms_fakehost - fakehost server message handler + * + * parv[0] = sender prefix + * parv[1] = target user numeric + * parv[2] = target user's new fake host + */ +int ms_fakehost(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) +{ + struct Client *target; + + if (parc < 3) + return need_more_params(sptr, "FAKEHOST"); + + /* Locate our target user; ignore the message if we can't */ + if(!(target = findNUser(parv[1]))) + return 0; + + /* Ignore the assignment if it changes nothing */ + if (HasFakeHost(target) && + ircd_strcmp(cli_user(target)->fakehost, parv[2]) == 0) + { + return 0; + } + + /* Assign and propagate the fakehost */ + SetFakeHost(target); + ircd_strncpy(cli_user(target)->fakehost, parv[2], HOSTLEN); + hide_hostmask(target); + + sendcmdto_serv_butone(sptr, CMD_FAKEHOST, cptr, "%C %s", target, + cli_user(target)->fakehost); + return 0; +} + diff -Nurp ircu2.10.12.10/ircd/parse.c ircu2.10.12.10-fakehosts/ircd/parse.c --- ircu2.10.12.10/ircd/parse.c 2005-09-27 05:54:46.000000000 +0200 +++ ircu2.10.12.10-fakehosts/ircd/parse.c 2007-03-13 02:14:07.000000000 +0100 @@ -626,6 +626,13 @@ struct Message msgtab[] = { { m_cap, m_cap, m_ignore, m_cap, m_ignore } }, #endif + { + MSG_FAKEHOST, + TOK_FAKEHOST, + 0, MAXPARA, MFLG_SLOW, 0, NULL, + /* UNREG, CLIENT, SERVER, OPER, SERVICE */ + { m_ignore, m_not_oper, ms_fakehost, m_fakehost, m_ignore } + }, /* This command is an alias for QUIT during the unregistered part of * of the server. This is because someone jumping via a broken web * proxy will send a 'POST' as their first command - which we will diff -Nurp ircu2.10.12.10/ircd/s_auth.c ircu2.10.12.10-fakehosts/ircd/s_auth.c --- ircu2.10.12.10/ircd/s_auth.c 2007-01-16 02:21:37.000000000 +0100 +++ ircu2.10.12.10-fakehosts/ircd/s_auth.c 2007-03-13 02:14:07.000000000 +0100 @@ -365,6 +365,7 @@ static int check_auth_finished(struct Au { enum AuthRequestFlag flag; int res; + const char *fakehost; /* Check non-iauth registration blocking flags. */ for (flag = 0; flag <= AR_LAST_SCAN; ++flag) @@ -381,6 +382,14 @@ static int check_auth_finished(struct Au && preregister_user(auth->client)) return CPTR_KILLED; + /* Set fakehost if client's connection class has a default fakehost. */ + fakehost = client_get_default_fakehost(auth->client); + if (fakehost) + { + ircd_strncpy(cli_user(auth->client)->fakehost, fakehost, HOSTLEN); + SetFakeHost(auth->client); + } + /* If we have not done so, check client password. Do this as soon * as possible so that iauth's challenge/response (which uses PASS * for responses) is not confused with the client's password. diff -Nurp ircu2.10.12.10/ircd/s_user.c ircu2.10.12.10-fakehosts/ircd/s_user.c --- ircu2.10.12.10/ircd/s_user.c 2007-01-13 19:43:41.000000000 +0100 +++ ircu2.10.12.10-fakehosts/ircd/s_user.c 2007-03-13 02:14:29.000000000 +0100 @@ -339,10 +339,12 @@ int hunt_server_prio_cmd(struct Client * */ int register_user(struct Client *cptr, struct Client *sptr) { + const char* fakehost; char* parv[4]; char* tmpstr; struct User* user = cli_user(sptr); char ip_base64[25]; + struct Flags setflags; user->last = CurrentTime; parv[0] = cli_name(sptr); @@ -387,6 +389,7 @@ int register_user(struct Client *cptr, s /* * Set user's initial modes */ + setflags = cli_flags(sptr); tmpstr = (char*)client_get_default_umode(sptr); if (tmpstr) for (; *tmpstr; ++tmpstr) { switch (*tmpstr) { @@ -410,6 +413,11 @@ int register_user(struct Client *cptr, s if (!feature_bool(FEAT_HIS_DEBUG_OPER_ONLY)) SetDebug(sptr); break; + case 'x': + SetHiddenHost(sptr); + if (!FlagHas(&setflags, FLAG_HIDDENHOST)) + hide_hostmask(sptr); + break; } } } @@ -511,7 +519,8 @@ static const struct UserMode { { FLAG_CHSERV, 'k' }, { FLAG_DEBUG, 'g' }, { FLAG_ACCOUNT, 'r' }, - { FLAG_HIDDENHOST, 'x' } + { FLAG_HIDDENHOST, 'x' }, + { FLAG_FAKEHOST, 'f' } }; /** Length of #userModeList. */ @@ -537,6 +546,7 @@ int set_nick_name(struct Client* cptr, s { if (IsServer(sptr)) { int i; + const char* fakehost = 0; const char* account = 0; const char* p; @@ -550,6 +560,7 @@ int set_nick_name(struct Client* cptr, s cli_lastnick(new_client) = atoi(parv[3]); if (Protocol(cptr) > 9 && parc > 7 && *parv[6] == '+') { + int argi = 7; for (p = parv[6] + 1; *p; p++) { for (i = 0; i < USERMODELIST_SIZE; ++i) @@ -557,8 +568,10 @@ int set_nick_name(struct Client* cptr, s if (userModeList[i].c == *p) { SetFlag(new_client, userModeList[i].flag); - if (userModeList[i].flag == FLAG_ACCOUNT) - account = parv[7]; + if (userModeList[i].flag == FLAG_ACCOUNT) + account = parv[argi++]; + else if (userModeList[i].flag == FLAG_FAKEHOST) + fakehost = parv[argi++]; break; } } @@ -598,9 +611,7 @@ int set_nick_name(struct Client* cptr, s ircd_strncpy(cli_user(new_client)->account, account, len); } if (HasHiddenHost(new_client)) - ircd_snprintf(0, cli_user(new_client)->host, HOSTLEN, "%s.%s", - cli_user(new_client)->account, - feature_str(FEAT_HIDDEN_HOST)); + make_hidden_hostmask(cli_user(new_client)->host, new_client); return register_user(cptr, new_client); } @@ -908,39 +919,53 @@ void send_user_info(struct Client* sptr, msgq_clean(mb); } +/* + * make_hidden_hostmask() + * + * Generates a user's hidden hostmask based on their account unless + * they have a custom [vanity] host set. This function expects a + * buffer of sufficient size to hold the resulting hostmask. + */ +void make_hidden_hostmask(char *buffer, struct Client *cptr) +{ + assert(HasFakeHost(cptr) || IsAccount(cptr)); + + if (HasFakeHost(cptr)) { + /* The user has a fake host; make that their hidden hostmask. */ + ircd_strncpy(buffer, cli_user(cptr)->fakehost, HOSTLEN); + return; + } + + if (IsAccount(cptr)) { + /* Generate a hidden host based on the user's account name. */ + ircd_snprintf(0, buffer, HOSTLEN, "%s.%s", cli_user(cptr)->account, + feature_str(FEAT_HIDDEN_HOST)); + return; + } +} + /** Set \a flag on \a cptr and possibly hide the client's hostmask. * @param[in,out] cptr User who is getting a new flag. * @param[in] flag Some flag that affects host-hiding (FLAG_HIDDENHOST, FLAG_ACCOUNT). * @return Zero. */ int -hide_hostmask(struct Client *cptr, unsigned int flag) +hide_hostmask(struct Client *cptr) { struct Membership *chan; - switch (flag) { - case FLAG_HIDDENHOST: - /* Local users cannot set +x unless FEAT_HOST_HIDING is true. */ - if (MyConnect(cptr) && !feature_bool(FEAT_HOST_HIDING)) - return 0; - break; - case FLAG_ACCOUNT: - /* Invalidate all bans against the user so we check them again */ - for (chan = (cli_user(cptr))->channel; chan; - chan = chan->next_channel) - ClearBanValid(chan); - break; - default: + if (MyConnect(cptr) && !feature_bool(FEAT_HOST_HIDING)) return 0; - } - SetFlag(cptr, flag); - if (!HasFlag(cptr, FLAG_HIDDENHOST) || !HasFlag(cptr, FLAG_ACCOUNT)) + if (!HasHiddenHost(cptr)) return 0; + /* Invalidate all bans against the user so we check them again */ + for (chan = (cli_user(cptr))->channel; chan; chan = chan->next_channel) + ClearBanValid(chan); + sendcmdto_common_channels_butone(cptr, CMD_QUIT, cptr, ":Registered"); - ircd_snprintf(0, cli_user(cptr)->host, HOSTLEN, "%s.%s", - cli_user(cptr)->account, feature_str(FEAT_HIDDEN_HOST)); + make_hidden_hostmask(cli_user(cptr)->host, cptr); /* ok, the client is now fully hidden, so let them know -- hikari */ if (MyConnect(cptr)) @@ -954,8 +979,11 @@ hide_hostmask(struct Client *cptr, unsig { if (IsZombie(chan)) continue; - /* Send a JOIN unless the user's join has been delayed. */ - if (!IsDelayedJoin(chan)) + /* For a user with no modes in a join-delayed channel, do not show + * the rejoin. */ + if (!IsChanOp(chan) && !HasVoice(chan) && (chan->channel->mode.mode & MODE_DELJOINS)) + SetDelayedJoin(chan); + else sendcmdto_channel_butserv_butone(cptr, CMD_JOIN, chan->channel, cptr, 0, "%H", chan->channel); if (IsChanOp(chan) && HasVoice(chan)) @@ -1024,7 +1052,8 @@ int set_user_mode(struct Client *cptr, s for (i = 0; i < USERMODELIST_SIZE; i++) { if (HasFlag(sptr, userModeList[i].flag) && - userModeList[i].flag != FLAG_ACCOUNT) + (userModeList[i].flag != FLAG_ACCOUNT) && + (userModeList[i].flag != FLAG_FAKEHOST)) *m++ = userModeList[i].c; } *m = '\0'; @@ -1129,9 +1158,12 @@ int set_user_mode(struct Client *cptr, s ClearDebug(sptr); break; case 'x': - if (what == MODE_ADD) - do_host_hiding = 1; - break; + if (what == MODE_ADD) { + SetHiddenHost(sptr); + if (!FlagHas(&setflags, FLAG_HIDDENHOST)) + do_host_hiding = 1; + } + break; default: send_reply(sptr, ERR_UMODEUNKNOWNFLAG, *m); break; @@ -1209,8 +1241,8 @@ int set_user_mode(struct Client *cptr, s --UserStats.inv_clients; if (!FlagHas(&setflags, FLAG_INVISIBLE) && IsInvisible(sptr)) ++UserStats.inv_clients; - if (!FlagHas(&setflags, FLAG_HIDDENHOST) && do_host_hiding) - hide_hostmask(sptr, FLAG_HIDDENHOST); + if (do_host_hiding) + hide_hostmask(sptr); send_umode_out(cptr, sptr, &setflags, prop); return 0; @@ -1244,6 +1276,15 @@ char *umode_str(struct Client *cptr) *m++ = ' '; while ((*m++ = *t++)) ; /* Empty loop */ + m--; /* back up to '\0' */ + } + + if (HasFakeHost(cptr)) { + char* t = cli_user(cptr)->fakehost; + + *m++ = ' '; + while ((*m++ = *t++)) + ; /* Empty loop */ if (cli_user(cptr)->acc_create) { char nbuf[20]; @@ -1292,6 +1333,8 @@ void send_umode(struct Client *cptr, str if (FlagHas(old, flag) == HasFlag(sptr, flag)) continue; + if (flag == FLAG_ACCOUNT || flag == FLAG_FAKEHOST) + continue; switch (sendset) { case ALL_UMODES: