1
0
mirror of https://github.com/unrealircd/unrealircd.git synced 2026-07-09 23:03:13 +02:00

Move match_user() to module (efunc in m_tkl)

This commit is contained in:
Bram Matthys
2017-03-18 15:00:34 +01:00
parent 000f9e10fc
commit ec9db8fd5f
5 changed files with 180 additions and 174 deletions
+3 -2
View File
@@ -122,7 +122,6 @@ extern OperPermission ValidatePermissionsForPath(char *path, aClient *sptr, aCli
extern void OperClassValidatorDel(OperClassValidator *validator);
extern int AllowClient(aClient *cptr, struct hostent *hp, char *sockhost, char *username);
extern int match_user(char *rmask, aClient *acptr, int options);
extern ConfigItem_ban *Find_ban_ip(aClient *sptr);
extern void add_ListItem(ListStruct *, ListStruct **);
extern void add_ListItemPrio(ListStructPrio *, ListStructPrio **, int);
@@ -614,6 +613,7 @@ extern int __attribute__((warn_unused_result)) do_cmd(aClient *cptr, aClient *sp
extern void create_snomask(aClient *sptr, anUser *user, char *snomask);
extern MODVAR char *me_hash;
extern MODVAR int dontspread;
/* Efuncs */
extern MODVAR int (*do_join)(aClient *, aClient *, int, char **);
extern MODVAR void (*join_channel)(aChannel *chptr, aClient *cptr, aClient *sptr, int flags);
@@ -666,8 +666,9 @@ extern MODVAR void (*broadcast_moddata_client)(aClient *acptr);
extern MODVAR int (*check_banned)(aClient *cptr);
extern MODVAR void (*introduce_user)(aClient *to, aClient *acptr);
extern MODVAR int (*check_deny_version)(aClient *cptr, char *version_string, int protocol, char *flags);
extern MODVAR int (*match_user)(char *rmask, aClient *acptr, int options);
/* /Efuncs */
extern MODVAR aMotdFile opermotd, svsmotd, motd, botmotd, smotd, rules;
extern MODVAR int max_connection_count;
extern int add_listmode(Ban **list, aClient *cptr, aChannel *chptr, char *banid);
+1
View File
@@ -1042,6 +1042,7 @@ _UNREAL_ERROR(_hook_error_incompatible, "Incompatible hook function. Check argum
#define EFUNC_SEND_MODDATA_CHANNEL 50
#define EFUNC_SEND_MODDATA_MEMBERS 51
#define EFUNC_BROADCAST_MODDATA_CLIENT 52
#define EFUNC_MATCH_USER 53
/* Module flags */
#define MODFLAG_NONE 0x0000
-171
View File
@@ -579,174 +579,3 @@ char *unreal_match_method_valtostr(int val)
return "unknown";
}
/* compares the first 'mask' bits. returns 1 if equal, 0 if not.
* taken from atheme
*/
static int comp_with_mask(void *addr, void *dest, u_int mask)
{
if (memcmp(addr, dest, mask / 8) == 0)
{
int n = mask / 8;
int m = ((-1) << (8 - (mask % 8)));
if (mask % 8 == 0 || (((u_char *) addr)[n] & m) == (((u_char *) dest)[n] & m))
{
return (1);
}
}
return (0);
}
#define IPSZ 16
/** Match a user against a mask.
* This will deal with 'nick!user@host', 'user@host' and just 'host'.
* We try to match the 'host' portion against the client IP, real host, etc...
* CIDR support is available so 'host' may be like '1.2.0.0/16'.
* @returns 1 on match, 0 on no match.
*/
int match_user(char *rmask, aClient *acptr, int options)
{
char mask[NICKLEN+USERLEN+HOSTLEN+8];
char clientip[IPSZ], maskip[IPSZ];
char *p = NULL;
char *nmask = NULL, *umask = NULL, *hmask = NULL;
int cidr = -1; /* CIDR length, -1 for no CIDR */
strlcpy(mask, rmask, sizeof(mask));
if (!(options & MATCH_MASK_IS_UHOST))
{
p = strchr(mask, '!');
if (p)
{
*p++ = '\0';
if (!*mask)
return 0; /* NOMATCH: '!...' */
nmask = mask;
umask = p;
/* Could just as well check nick right now */
if (match(nmask, acptr->name) != 0)
return 0; /* NOMATCH: nick mask did not match */
}
}
if (!(options & (MATCH_MASK_IS_HOST)))
{
p = strchr(p ? p : mask, '@');
if (p)
{
char *client_username = (acptr->user && *acptr->user->username) ? acptr->user->username : acptr->username;
*p++ = '\0';
if (!*p || !*mask)
return 0; /* NOMATCH: '...@' or '@...' */
hmask = p;
if (!umask)
umask = mask;
/* Check user portion right away */
if (match(umask, client_username) != 0)
return 0; /* NOMATCH: user mask did not match */
} else {
if (nmask)
return 0; /* NOMATCH: 'abc!def' (or even just 'abc!') */
hmask = mask;
}
} else {
hmask = mask;
}
/* If we get here then we have done checking nick / ident (if it was needed)
* and now need to match the 'host' portion.
*/
/**** Check visible host ****/
if (options & MATCH_CHECK_VISIBLE_HOST)
{
char *hostname = acptr->user ? GetHost(acptr) : (MyClient(acptr) ? acptr->local->sockhost : NULL);
if (hostname && (match(hmask, hostname) == 0))
return 1; /* MATCH: visible host */
}
/**** Check cloaked host ****/
if (options & MATCH_CHECK_CLOAKED_HOST)
{
if (acptr->user && (match(hmask, acptr->user->cloakedhost) == 0))
return 1; /* MATCH: cloaked host */
}
/**** check on IP ****/
if (options & MATCH_CHECK_IP)
{
p = strchr(hmask, '/');
if (p)
{
*p++ = '\0';
cidr = atoi(p);
if (cidr <= 0)
return 0; /* NOMATCH: invalid CIDR */
}
if (strchr(hmask, '?') || strchr(hmask, '*'))
{
/* Wildcards */
if (acptr->ip && (match(hmask, acptr->ip) == 0))
return 1; /* MATCH (IP with wildcards) */
} else
if (strchr(hmask, ':'))
{
/* IPv6 hostmask */
/* We can actually return here on match/nomatch as we don't need to check the
* virtual host and things like that since ':' can never be in a hostname.
*/
if (!acptr->ip || !strchr(acptr->ip, ':'))
return 0; /* NOMATCH: hmask is IPv6 address and client is not IPv6 */
if (!inet_pton6(acptr->ip, clientip))
return 0; /* NOMATCH: unusual failure */
if (!inet_pton6(hmask, maskip))
return 0; /* NOMATCH: invalid IPv6 IP in hostmask */
if (cidr < 0)
return comp_with_mask(clientip, maskip, 128); /* MATCH/NOMATCH by exact IP */
if (cidr > 128)
return 0; /* NOMATCH: invalid CIDR */
return comp_with_mask(clientip, maskip, cidr);
} else
{
/* Host is not IPv6 and does not contain wildcards.
* So could be a literal IPv4 address or IPv4 CIDR.
* NOTE: could also be neither (like a real hostname), so don't return 0 on nomatch,
* in that case we should just continue...
* The exception is CIDR. If we have CIDR mask then don't bother checking for
* virtual hosts and things like that since '/' can never be in a hostname.
*/
if (acptr->ip && inet_pton4(acptr->ip, clientip) && inet_pton4(hmask, maskip))
{
if (cidr < 0)
{
if (comp_with_mask(clientip, maskip, 32))
return 1; /* MATCH: exact IP */
}
else if (cidr > 32)
return 0; /* NOMATCH: invalid CIDR */
else
return comp_with_mask(clientip, maskip, cidr); /* MATCH/NOMATCH by CIDR */
}
}
}
/**** Check real host ****/
if (options & MATCH_CHECK_REAL_HOST)
{
char *hostname = acptr->user ? acptr->user->realhost : (MyClient(acptr) ? acptr->local->sockhost : NULL);
if (hostname && (match(hmask, hostname) == 0))
return 1; /* MATCH: hostname match */
}
return 0; /* NOMATCH: nothing of the above matched */
}
+3 -1
View File
@@ -131,6 +131,7 @@ void (*send_moddata_client)(aClient *srv, aClient *acptr);
void (*send_moddata_channel)(aClient *srv, aChannel *chptr);
void (*send_moddata_members)(aClient *srv);
void (*broadcast_moddata_client)(aClient *acptr);
int (*match_user)(char *rmask, aClient *acptr, int options);
static const EfunctionsList efunction_table[MAXEFUNCTIONS] = {
/* 00 */ {NULL, NULL},
@@ -186,7 +187,8 @@ static const EfunctionsList efunction_table[MAXEFUNCTIONS] = {
/* 50 */ {"send_moddata_channel", (void *)&send_moddata_channel},
/* 51 */ {"send_moddata_members", (void *)&send_moddata_members},
/* 52 */ {"broadcast_moddata_client", (void *)&broadcast_moddata_client},
/* 53 */ {NULL, NULL}
/* 53 */ {"match_user", (void *)&match_user},
/* 54 */ {NULL, NULL}
};
#ifdef UNDERSCORE
+173
View File
@@ -71,6 +71,7 @@ int _place_host_ban(aClient *sptr, int action, char *reason, long duration);
int _dospamfilter(aClient *sptr, char *str_in, int type, char *target, int flags, aTKline **rettk);
int _dospamfilter_viruschan(aClient *sptr, aTKline *tk, int type);
void _spamfilter_build_user_string(char *buf, char *nick, aClient *acptr);
int _match_user(char *rmask, aClient *acptr, int options);
extern MODVAR char zlinebuf[BUFSIZE];
extern MODVAR aTKline *tklines[TKLISTLEN];
@@ -121,6 +122,7 @@ MOD_TEST(m_tkl)
EfunctionAdd(modinfo->handle, EFUNC_DOSPAMFILTER, _dospamfilter);
EfunctionAdd(modinfo->handle, EFUNC_DOSPAMFILTER_VIRUSCHAN, _dospamfilter_viruschan);
EfunctionAddVoid(modinfo->handle, EFUNC_SPAMFILTER_BUILD_USER_STRING, _spamfilter_build_user_string);
EfunctionAdd(modinfo->handle, EFUNC_MATCH_USER, _match_user);
return MOD_SUCCESS;
}
@@ -2625,3 +2627,174 @@ long ms_past;
return 0; /* NOTREACHED */
}
/* compares the first 'mask' bits. returns 1 if equal, 0 if not.
* taken from atheme
*/
static int comp_with_mask(void *addr, void *dest, u_int mask)
{
if (memcmp(addr, dest, mask / 8) == 0)
{
int n = mask / 8;
int m = ((-1) << (8 - (mask % 8)));
if (mask % 8 == 0 || (((u_char *) addr)[n] & m) == (((u_char *) dest)[n] & m))
{
return (1);
}
}
return (0);
}
#define IPSZ 16
/** Match a user against a mask.
* This will deal with 'nick!user@host', 'user@host' and just 'host'.
* We try to match the 'host' portion against the client IP, real host, etc...
* CIDR support is available so 'host' may be like '1.2.0.0/16'.
* @returns 1 on match, 0 on no match.
*/
int _match_user(char *rmask, aClient *acptr, int options)
{
char mask[NICKLEN+USERLEN+HOSTLEN+8];
char clientip[IPSZ], maskip[IPSZ];
char *p = NULL;
char *nmask = NULL, *umask = NULL, *hmask = NULL;
int cidr = -1; /* CIDR length, -1 for no CIDR */
strlcpy(mask, rmask, sizeof(mask));
if (!(options & MATCH_MASK_IS_UHOST))
{
p = strchr(mask, '!');
if (p)
{
*p++ = '\0';
if (!*mask)
return 0; /* NOMATCH: '!...' */
nmask = mask;
umask = p;
/* Could just as well check nick right now */
if (match(nmask, acptr->name) != 0)
return 0; /* NOMATCH: nick mask did not match */
}
}
if (!(options & (MATCH_MASK_IS_HOST)))
{
p = strchr(p ? p : mask, '@');
if (p)
{
char *client_username = (acptr->user && *acptr->user->username) ? acptr->user->username : acptr->username;
*p++ = '\0';
if (!*p || !*mask)
return 0; /* NOMATCH: '...@' or '@...' */
hmask = p;
if (!umask)
umask = mask;
/* Check user portion right away */
if (match(umask, client_username) != 0)
return 0; /* NOMATCH: user mask did not match */
} else {
if (nmask)
return 0; /* NOMATCH: 'abc!def' (or even just 'abc!') */
hmask = mask;
}
} else {
hmask = mask;
}
/* If we get here then we have done checking nick / ident (if it was needed)
* and now need to match the 'host' portion.
*/
/**** Check visible host ****/
if (options & MATCH_CHECK_VISIBLE_HOST)
{
char *hostname = acptr->user ? GetHost(acptr) : (MyClient(acptr) ? acptr->local->sockhost : NULL);
if (hostname && (match(hmask, hostname) == 0))
return 1; /* MATCH: visible host */
}
/**** Check cloaked host ****/
if (options & MATCH_CHECK_CLOAKED_HOST)
{
if (acptr->user && (match(hmask, acptr->user->cloakedhost) == 0))
return 1; /* MATCH: cloaked host */
}
/**** check on IP ****/
if (options & MATCH_CHECK_IP)
{
p = strchr(hmask, '/');
if (p)
{
*p++ = '\0';
cidr = atoi(p);
if (cidr <= 0)
return 0; /* NOMATCH: invalid CIDR */
}
if (strchr(hmask, '?') || strchr(hmask, '*'))
{
/* Wildcards */
if (acptr->ip && (match(hmask, acptr->ip) == 0))
return 1; /* MATCH (IP with wildcards) */
} else
if (strchr(hmask, ':'))
{
/* IPv6 hostmask */
/* We can actually return here on match/nomatch as we don't need to check the
* virtual host and things like that since ':' can never be in a hostname.
*/
if (!acptr->ip || !strchr(acptr->ip, ':'))
return 0; /* NOMATCH: hmask is IPv6 address and client is not IPv6 */
if (!inet_pton6(acptr->ip, clientip))
return 0; /* NOMATCH: unusual failure */
if (!inet_pton6(hmask, maskip))
return 0; /* NOMATCH: invalid IPv6 IP in hostmask */
if (cidr < 0)
return comp_with_mask(clientip, maskip, 128); /* MATCH/NOMATCH by exact IP */
if (cidr > 128)
return 0; /* NOMATCH: invalid CIDR */
return comp_with_mask(clientip, maskip, cidr);
} else
{
/* Host is not IPv6 and does not contain wildcards.
* So could be a literal IPv4 address or IPv4 CIDR.
* NOTE: could also be neither (like a real hostname), so don't return 0 on nomatch,
* in that case we should just continue...
* The exception is CIDR. If we have CIDR mask then don't bother checking for
* virtual hosts and things like that since '/' can never be in a hostname.
*/
if (acptr->ip && inet_pton4(acptr->ip, clientip) && inet_pton4(hmask, maskip))
{
if (cidr < 0)
{
if (comp_with_mask(clientip, maskip, 32))
return 1; /* MATCH: exact IP */
}
else if (cidr > 32)
return 0; /* NOMATCH: invalid CIDR */
else
return comp_with_mask(clientip, maskip, cidr); /* MATCH/NOMATCH by CIDR */
}
}
}
/**** Check real host ****/
if (options & MATCH_CHECK_REAL_HOST)
{
char *hostname = acptr->user ? acptr->user->realhost : (MyClient(acptr) ? acptr->local->sockhost : NULL);
if (hostname && (match(hmask, hostname) == 0))
return 1; /* MATCH: hostname match */
}
return 0; /* NOMATCH: nothing of the above matched */
}