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:
+3
-2
@@ -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);
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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 */
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user