diff --git a/include/client.h b/include/client.h index 3c904a6c..79cb0af5 100644 --- a/include/client.h +++ b/include/client.h @@ -161,6 +161,7 @@ enum Flag FLAG_INVISIBLE, /**< makes user invisible */ FLAG_WALLOP, /**< send wallops to them */ FLAG_DEAF, /**< Makes user deaf */ + FLAG_BLOCK_UNAUTH_USERS, /**< Block msgs from unauthenticated users */ FLAG_CHSERV, /**< Disallow KICK or MODE -o on the user; don't display channels in /whois */ FLAG_DEBUG, /**< send global debug/anti-hack info */ @@ -558,6 +559,8 @@ struct Client { #define IsDead(x) HasFlag(x, FLAG_DEADSOCKET) /** Return non-zero if the client has set mode +d (deaf). */ #define IsDeaf(x) HasFlag(x, FLAG_DEAF) +/** Return non-zero if the client has mode +R (block unauthed users). */ +#define IsBlockUnauthUsers(x) HasFlag(x, FLAG_BLOCK_UNAUTH_USERS) /** Return non-zero if the client has been IP-checked for clones. */ #define IsIPChecked(x) HasFlag(x, FLAG_IPCHECK) /** Return non-zero if we have received an ident response for the client. */ @@ -608,6 +611,8 @@ struct Client { #define SetChannelService(x) SetFlag(x, FLAG_CHSERV) /** Mark a client as having mode +d (deaf). */ #define SetDeaf(x) SetFlag(x, FLAG_DEAF) +/** Mark a client as having mode +R (block unregistered users). */ +#define SetBlockUnauthUsers(x) SetFlag(x, FLAG_BLOCK_UNAUTH_USERS) /** Mark a client as having mode +g (debugging). */ #define SetDebug(x) SetFlag(x, FLAG_DEBUG) /** Mark a client as having ident looked up. */ @@ -646,35 +651,37 @@ struct Client { || HasPriv(sptr, PRIV_SEE_OPERS))) /** Clear the client's net.burst in-progress flag. */ -#define ClearBurst(x) ClrFlag(x, FLAG_BURST) +#define ClearBurst(x) ClrFlag(x, FLAG_BURST) /** Clear the client's between EOB and EOB ACK flag. */ -#define ClearBurstAck(x) ClrFlag(x, FLAG_BURST_ACK) +#define ClearBurstAck(x) ClrFlag(x, FLAG_BURST_ACK) /** Remove mode +k (channel service) from the client. */ -#define ClearChannelService(x) ClrFlag(x, FLAG_CHSERV) +#define ClearChannelService(x) ClrFlag(x, FLAG_CHSERV) /** Remove mode +d (deaf) from the client. */ -#define ClearDeaf(x) ClrFlag(x, FLAG_DEAF) +#define ClearDeaf(x) ClrFlag(x, FLAG_DEAF) +/** Remove mode +R (block unregistered users) from the client. */ +#define ClearBlockUnauthUsers(x) ClrFlag(x, FLAG_BLOCK_UNAUTH_USERS) /** Remove mode +g (debugging) from the client. */ -#define ClearDebug(x) ClrFlag(x, FLAG_DEBUG) +#define ClearDebug(x) ClrFlag(x, FLAG_DEBUG) /** Remove the client's IP-checked flag. */ -#define ClearIPChecked(x) ClrFlag(x, FLAG_IPCHECK) +#define ClearIPChecked(x) ClrFlag(x, FLAG_IPCHECK) /** Remove mode +i (invisible) from the client. */ -#define ClearInvisible(x) ClrFlag(x, FLAG_INVISIBLE) +#define ClearInvisible(x) ClrFlag(x, FLAG_INVISIBLE) /** Remove mode +O (local operator) from the client. */ -#define ClearLocOp(x) ClrFlag(x, FLAG_LOCOP) +#define ClearLocOp(x) ClrFlag(x, FLAG_LOCOP) /** Remove mode +o (global operator) from the client. */ -#define ClearOper(x) ClrFlag(x, FLAG_OPER) +#define ClearOper(x) ClrFlag(x, FLAG_OPER) /** Clear the client's pending UDP ping flag. */ -#define ClearUPing(x) ClrFlag(x, FLAG_UPING) +#define ClearUPing(x) ClrFlag(x, FLAG_UPING) /** Remove mode +w (wallops) from the client. */ -#define ClearWallops(x) ClrFlag(x, FLAG_WALLOP) +#define ClearWallops(x) ClrFlag(x, FLAG_WALLOP) /** Remove mode +s (server notices) from the client. */ -#define ClearServNotice(x) ClrFlag(x, FLAG_SERVNOTICE) +#define ClearServNotice(x) ClrFlag(x, FLAG_SERVNOTICE) /** Remove mode +x (hidden host) from the client. */ -#define ClearHiddenHost(x) ClrFlag(x, FLAG_HIDDENHOST) +#define ClearHiddenHost(x) ClrFlag(x, FLAG_HIDDENHOST) /** Clear the client's pending PING flag. */ -#define ClearPingSent(x) ClrFlag(x, FLAG_PINGSENT) +#define ClearPingSent(x) ClrFlag(x, FLAG_PINGSENT) /** Clear the client's HUB flag. */ -#define ClearHub(x) ClrFlag(x, FLAG_HUB) +#define ClearHub(x) ClrFlag(x, FLAG_HUB) /* free flags */ #define FREEFLAG_SOCKET 0x0001 /**< socket needs to be freed */ diff --git a/include/s_user.h b/include/s_user.h index 680a8261..a9924970 100644 --- a/include/s_user.h +++ b/include/s_user.h @@ -104,6 +104,9 @@ extern unsigned int umode_make_snomask(unsigned int oldmask, char *arg, int what); extern int send_supported(struct Client *cptr); +int should_block_unauth_user(struct Client *source, struct Client *dest); +int send_reply_blocked_unauth_user(struct Client *source, struct Client *dest); + #define NAMES_ALL 1 /**< List all users in channel */ #define NAMES_VIS 2 /**< List only visible users in non-secret channels */ #define NAMES_EON 4 /**< Add an 'End Of Names' reply to the end */ diff --git a/ircd/ircd_relay.c b/ircd/ircd_relay.c index 325d3d73..d9d6c751 100644 --- a/ircd/ircd_relay.c +++ b/ircd/ircd_relay.c @@ -310,6 +310,11 @@ void relay_directed_message(struct Client* sptr, char* name, char* server, const if (host) *--host = '%'; + if (should_block_unauth_user(sptr, acptr)) { + send_reply_blocked_unauth_user(sptr, acptr); + return; + } + if (!(is_silenced(sptr, acptr))) sendcmdto_one(sptr, CMD_PRIVATE, acptr, "%s :%s", name, text); } @@ -374,6 +379,11 @@ void relay_directed_notice(struct Client* sptr, char* name, char* server, const if (host) *--host = '%'; + if (should_block_unauth_user(sptr, acptr)) { + send_reply_blocked_unauth_user(sptr, acptr); + return; + } + if (!(is_silenced(sptr, acptr))) sendcmdto_one(sptr, CMD_NOTICE, acptr, "%s :%s", name, text); } @@ -398,10 +408,17 @@ void relay_private_message(struct Client* sptr, const char* name, const char* te send_reply(sptr, ERR_NOSUCHNICK, name); return; } + /* Note: X does silence users who flood it. */ - if ((!IsChannelService(acptr) && - check_target_limit(sptr, acptr, NULL)) || - is_silenced(sptr, acptr)) + if (!IsChannelService(acptr) && check_target_limit(sptr, acptr, NULL)) + return; + + if (should_block_unauth_user(sptr, acptr)) { + send_reply_blocked_unauth_user(sptr, acptr); + return; + } + + if (is_silenced(sptr, acptr)) return; /* @@ -435,10 +452,18 @@ void relay_private_notice(struct Client* sptr, const char* name, const char* tex if (0 == (acptr = FindUser(name))) return; - if ((!IsChannelService(acptr) && - check_target_limit(sptr, acptr, NULL)) || - is_silenced(sptr, acptr)) + + if (!IsChannelService(acptr) && check_target_limit(sptr, acptr, NULL)) + return; + + if (should_block_unauth_user(sptr, acptr)) { + send_reply_blocked_unauth_user(sptr, acptr); return; + } + + if (is_silenced(sptr, acptr)) + return; + /* * deliver the message */ @@ -469,6 +494,12 @@ void server_relay_private_message(struct Client* sptr, const char* name, const c text); return; } + + if (should_block_unauth_user(sptr, acptr)) { + send_reply_blocked_unauth_user(sptr, acptr); + return; + } + if (is_silenced(sptr, acptr)) return; @@ -497,6 +528,11 @@ void server_relay_private_notice(struct Client* sptr, const char* name, const ch if (0 == (acptr = findNUser(name)) || !IsUser(acptr)) return; + if (should_block_unauth_user(sptr, acptr)) { + send_reply_blocked_unauth_user(sptr, acptr); + return; + } + if (is_silenced(sptr, acptr)) return; diff --git a/ircd/m_invite.c b/ircd/m_invite.c index 9a40498a..f0b128cb 100644 --- a/ircd/m_invite.c +++ b/ircd/m_invite.c @@ -139,6 +139,9 @@ int m_invite(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) return 0; } + if (should_block_unauth_user(sptr, acptr)) + return send_reply_blocked_unauth_user(sptr, acptr); + if (is_silenced(sptr, acptr)) return 0; @@ -276,6 +279,9 @@ int ms_invite(struct Client* cptr, struct Client* sptr, int parc, char* parv[]) return 0; } + if (should_block_unauth_user(sptr, acptr)) + return send_reply_blocked_unauth_user(sptr, acptr); + if (is_silenced(sptr, acptr)) return 0; diff --git a/ircd/s_user.c b/ircd/s_user.c index bc53b030..ea68e936 100644 --- a/ircd/s_user.c +++ b/ircd/s_user.c @@ -490,16 +490,17 @@ static const struct UserMode { unsigned int flag; /**< User mode constant. */ char c; /**< Character corresponding to the mode. */ } userModeList[] = { - { FLAG_OPER, 'o' }, - { FLAG_LOCOP, 'O' }, - { FLAG_INVISIBLE, 'i' }, - { FLAG_WALLOP, 'w' }, - { FLAG_SERVNOTICE, 's' }, - { FLAG_DEAF, 'd' }, - { FLAG_CHSERV, 'k' }, - { FLAG_DEBUG, 'g' }, - { FLAG_ACCOUNT, 'r' }, - { FLAG_HIDDENHOST, 'x' } + { FLAG_OPER, 'o' }, + { FLAG_LOCOP, 'O' }, + { FLAG_INVISIBLE, 'i' }, + { FLAG_WALLOP, 'w' }, + { FLAG_SERVNOTICE, 's' }, + { FLAG_DEAF, 'd' }, + { FLAG_CHSERV, 'k' }, + { FLAG_DEBUG, 'g' }, + { FLAG_ACCOUNT, 'r' }, + { FLAG_BLOCK_UNAUTH_USERS, 'R' }, + { FLAG_HIDDENHOST, 'x' } }; /** Length of #userModeList. */ @@ -799,9 +800,13 @@ int whisper(struct Client* source, const char* nick, const char* channel, if (0 == membership || IsZombie(membership)) { return send_reply(source, ERR_USERNOTINCHANNEL, cli_name(dest), chptr->chname); } + + if (should_block_unauth_user(source, dest)) + return send_reply_blocked_unauth_user(source, dest); + if (is_silenced(source, dest)) return 0; - + if (is_notice) sendcmdto_one(source, CMD_NOTICE, dest, "%C :%s", dest, text); else @@ -813,6 +818,31 @@ int whisper(struct Client* source, const char* nick, const char* channel, return 0; } +/** Return true if the source client isn't authenticated to a registered + * username, and the dest client has mode +R (block unauthed users). + * @param[in] source Client sending the message. + * @param[in] dest Destination of the message. + */ +int should_block_unauth_user(struct Client *source, struct Client *dest) +{ + // Only block regular users. + if (IsServer(source) || IsChannelService(source)) + return 0; + + return IsBlockUnauthUsers(dest) && !IsAccount(source); +} + +/** Sends an error message telling the source that the dest doesn't allow + * unauthed users to contact them. + * @param[in] source Client whose message was blocked. + * @param[in] dest Client who rejected the message. + */ +int send_reply_blocked_unauth_user(struct Client *source, struct Client *dest) +{ + return send_reply(source, SND_EXPLICIT | ERR_NEEDREGGEDNICK, + "%s :You need to be identified to a registered account to contact this user -- you can obtain an account from %s", + cli_name(dest), feature_str(FEAT_URLREG)); +} /** Send a user mode change for \a cptr to neighboring servers. * @param[in] cptr User whose mode is changing. @@ -1056,6 +1086,12 @@ int set_user_mode(struct Client *cptr, struct Client *sptr, int parc, else ClearDeaf(sptr); break; + case 'R': + if (what == MODE_ADD) + SetBlockUnauthUsers(sptr); + else + ClearBlockUnauthUsers(sptr); + break; case 'k': if (what == MODE_ADD) SetChannelService(sptr);