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

Send version information in SERVER command like before (VL). Expand PROTOCTL EAUTH.

PROTOCTL EAUTH=servername,protocolversion,flags,unrealversiontext
This makes deny link { } work again and gives a bit more information too.
Bug reported by GLolol (#4408).
This commit is contained in:
Bram Matthys
2015-09-05 12:06:55 +02:00
parent 8c9ddb4767
commit 15469cae2e
5 changed files with 153 additions and 110 deletions
+1
View File
@@ -660,6 +660,7 @@ extern MODVAR void (*send_md_member)(ModDataInfo *mdi, aChannel *chptr, Member *
extern MODVAR void (*send_md_membership)(ModDataInfo *mdi, aClient *acptr, Membership *m, ModData *md);
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);
/* /Efuncs */
extern MODVAR aMotdFile opermotd, svsmotd, motd, botmotd, smotd, rules;
+1
View File
@@ -824,6 +824,7 @@ extern char *moddata_client_get(aClient *acptr, char *varname);
#define EFUNC_SEND_MD_MEMBERSHIP 41
#define EFUNC_CHECK_BANNED 42
#define EFUNC_INTRODUCE_USER 43
#define EFUNC_CHECK_DENY_VERSION 44
/* Module flags */
#define MODFLAG_NONE 0x0000
+3 -1
View File
@@ -122,6 +122,7 @@ void (*send_md_channel)(ModDataInfo *mdi, aChannel *chptr, ModData *md);
void (*send_md_member)(ModDataInfo *mdi, aChannel *chptr, Member *m, ModData *md);
void (*send_md_membership)(ModDataInfo *mdi, aClient *acptr, Membership *m, ModData *md);
int (*check_banned)(aClient *cptr);
int (*check_deny_version)(aClient *cptr, char *version_string, int protocol, char *flags);
static const EfunctionsList efunction_table[MAXEFUNCTIONS] = {
/* 00 */ {NULL, NULL},
@@ -168,7 +169,8 @@ static const EfunctionsList efunction_table[MAXEFUNCTIONS] = {
/* 41 */ {"send_md_membership", (void *)&send_md_membership},
/* 42 */ {"check_banned", (void *)&check_banned},
/* 43 */ {"introduce_user", (void *)&introduce_user},
/* 44 */ {NULL, NULL}
/* 44 */ {"check_deny_version", (void *)&check_deny_version},
/* 45 */ {NULL, NULL}
};
#ifdef UNDERSCORE
+33 -26
View File
@@ -301,35 +301,25 @@ CMD_FUNC(m_protoctl)
}
else if ((strncmp(s, "EAUTH=", 6) == 0) && NEW_LINKING_PROTOCOL)
{
/* Early authorization: EAUTH=servername[,options] */
/* Early authorization: EAUTH=servername,protocol,flags,versiontext
* (Only servername is mandatory, rest is optional)
*/
int ret;
int protocol = 0;
char *servername = s+6, *p;
char *p;
char *servername = NULL, *protocol = NULL, *flags = NULL, *versiontext = NULL;
char buf[512];
ConfigItem_link *aconf = NULL;
if (strlen(servername) > HOSTLEN)
servername[HOSTLEN] = '\0';
for (p = servername; *p; p ++)
strlcpy(buf, s+6, sizeof(buf));
p = strchr(buf, ' ');
if (p)
{
if (*p == ',')
{
char *x;
*p = '\0';
/* upwards compatible */
x = strchr(p+1, ',');
if (x)
*x = '\0';
protocol = atoi(p+1);
break;
}
if (*p <= ' ' || *p > '~')
break;
*p = '\0';
p = NULL;
}
if (*p || !index(servername, '.'))
servername = strtoken(&p, buf, ",");
if (!servername || (strlen(servername) > HOSTLEN) || !index(servername, '.'))
{
sendto_one(sptr, "ERROR :Bogus server name in EAUTH (%s)", servername);
sendto_snomask
@@ -339,14 +329,31 @@ CMD_FUNC(m_protoctl)
return exit_client(cptr, sptr, &me, "Bogus server name");
}
protocol = strtoken(&p, NULL, ",");
if (protocol)
{
flags = strtoken(&p, NULL, ",");
if (flags)
{
versiontext = strtoken(&p, NULL, ",");
}
}
ret = verify_link(cptr, sptr, servername, &aconf);
if (ret < 0)
return ret; /* FLUSH_BUFFER */
ret = verify_link(cptr, sptr, s+6, &aconf);
/* note: versiontext, protocol and flags may be NULL */
ret = check_deny_version(sptr, versiontext, protocol ? atoi(protocol) : 0, flags);
if (ret < 0)
return ret; /* FLUSH_BUFFER */
SetEAuth(cptr);
make_server(cptr); /* allocate and set cptr->serv */
cptr->serv->features.protocol = protocol;
if (protocol)
cptr->serv->features.protocol = atoi(protocol);
if (!IsHandshake(cptr) && aconf) /* Send PASS early... */
sendto_one(sptr, "PASS :%s", (aconf->auth->type == AUTHTYPE_PLAINTEXT) ? aconf->auth->data : "*");
}
+115 -83
View File
@@ -48,6 +48,7 @@ int _verify_link(aClient *cptr, aClient *sptr, char *servername, ConfigItem_link
void _send_protoctl_servers(aClient *sptr, int response);
void _send_server_message(aClient *sptr);
void _introduce_user(aClient *to, aClient *acptr);
int _check_deny_version(aClient *cptr, char *version_string, int protocol, char *flags);
static char buf[BUFSIZE];
@@ -70,6 +71,7 @@ MOD_TEST(m_server)
EfunctionAddVoid(modinfo->handle, EFUNC_SEND_SERVER_MESSAGE, _send_server_message);
EfunctionAdd(modinfo->handle, EFUNC_VERIFY_LINK, _verify_link);
EfunctionAddVoid(modinfo->handle, EFUNC_INTRODUCE_USER, _introduce_user);
EfunctionAdd(modinfo->handle, EFUNC_CHECK_DENY_VERSION, _check_deny_version);
return MOD_SUCCESS;
}
@@ -95,6 +97,87 @@ MOD_UNLOAD(m_server)
int m_server_synch(aClient *cptr, ConfigItem_link *conf);
/** Check deny version { } blocks.
* NOTE: cptr will always be valid, but all the other values may be NULL or 0 !!!
*/
int _check_deny_version(aClient *cptr, char *version_string, int protocol, char *flags)
{
ConfigItem_deny_version *vlines;
for (vlines = conf_deny_version; vlines; vlines = (ConfigItem_deny_version *) vlines->next)
{
if (!match(vlines->mask, cptr->name))
break;
}
if (vlines)
{
char *proto = vlines->version;
char *vflags = vlines->flags;
int result = 0, i;
switch (*proto)
{
case '<':
proto++;
if (protocol < atoi(proto))
result = 1;
break;
case '>':
proto++;
if (protocol > atoi(proto))
result = 1;
break;
case '=':
proto++;
if (protocol == atoi(proto))
result = 1;
break;
case '!':
proto++;
if (protocol != atoi(proto))
result = 1;
break;
default:
if (protocol == atoi(proto))
result = 1;
break;
}
if (protocol == 0 || *proto == '*')
result = 0;
if (result)
return exit_client(cptr, cptr, cptr, "Denied by deny version { } block");
if (flags)
{
for (i = 0; vflags[i]; i++)
{
if (vflags[i] == '!')
{
i++;
if (strchr(flags, vflags[i])) {
result = 1;
break;
}
}
else if (!strchr(flags, vflags[i]))
{
result = 1;
break;
}
}
if (*vflags == '*' || !strcmp(flags, "0"))
result = 0;
}
if (result)
return exit_client(cptr, cptr, cptr, "Denied by deny version { } block");
}
return 0;
}
/** Send our PROTOCTL SERVERS=x,x,x,x stuff.
* When response is set, it will be PROTOCTL SERVERS=*x,x,x (mind the asterisk).
*/
@@ -106,8 +189,10 @@ void _send_protoctl_servers(aClient *sptr, int response)
if (!NEW_LINKING_PROTOCOL)
return;
ircsnprintf(buf, sizeof(buf), "PROTOCTL EAUTH=%s,%d SERVERS=%s",
me.name, UnrealProtocol, response ? "*" : "");
sendto_one(sptr, "PROTOCTL EAUTH=%s,%d,%s%s,%s",
me.name, UnrealProtocol, serveropts, extraflags ? extraflags : "", version);
ircsnprintf(buf, sizeof(buf), "PROTOCTL SERVERS=%s", response ? "*" : "");
list_for_each_entry(acptr, &global_server_list, client_node)
{
@@ -126,7 +211,7 @@ void _send_protoctl_servers(aClient *sptr, int response)
void _send_server_message(aClient *sptr)
{
if (sptr->serv->flags.server_sent)
if (sptr->serv && sptr->serv->flags.server_sent)
{
#ifdef DEBUGMODE
abort();
@@ -134,9 +219,17 @@ void _send_server_message(aClient *sptr)
return;
}
sendto_one(sptr, "SERVER %s 1 :%s",
me.name, me.info);
sptr->serv->flags.server_sent = 1;
if (1) /* SupportVL(sptr)) -- always send like 3.2.x for now. */
{
sendto_one(sptr, "SERVER %s 1 :U%d-%s %s",
me.name, UnrealProtocol, serveropts, me.info);
} else {
sendto_one(sptr, "SERVER %s 1 :%s",
me.name, me.info);
}
if (sptr->serv)
sptr->serv->flags.server_sent = 1;
}
@@ -391,7 +484,6 @@ CMD_FUNC(m_server)
/* we also have a fail safe incase they say they are sending
* VL stuff and don't -- codemastr
*/
ConfigItem_deny_version *vlines;
inf = NULL;
protocol = NULL;
flags = NULL;
@@ -403,83 +495,24 @@ CMD_FUNC(m_server)
num = (char *)strtok((char *)NULL, " ");
if (num)
inf = (char *)strtok((char *)NULL, "");
if (inf) {
strlcpy(cptr->info, inf[0] ? inf : me.name,
sizeof(cptr->info));
for (vlines = conf_deny_version; vlines; vlines = (ConfigItem_deny_version *) vlines->next) {
if (!match(vlines->mask, cptr->name))
break;
}
if (vlines) {
char *proto = vlines->version;
char *vflags = vlines->flags;
int version, result = 0, i;
protocol++;
version = atoi(protocol);
switch (*proto) {
case '<':
proto++;
if (version < atoi(proto))
result = 1;
break;
case '>':
proto++;
if (version > atoi(proto))
result = 1;
break;
case '=':
proto++;
if (version == atoi(proto))
result = 1;
break;
case '!':
proto++;
if (version != atoi(proto))
result = 1;
break;
default:
if (version == atoi(proto))
result = 1;
break;
}
if (version == 0 || *proto == '*')
result = 0;
if (result)
return exit_client(cptr, cptr, cptr,
"Denied by V:line");
for (i = 0; vflags[i]; i++) {
if (vflags[i] == '!') {
i++;
if (strchr(flags, vflags[i])) {
result = 1;
break;
}
}
else if (!strchr(flags, vflags[i])) {
result = 1;
break;
}
}
if (*vflags == '*' || !strcmp(flags, "0"))
result = 0;
if (result)
return exit_client(cptr, cptr, cptr,
"Denied by V:line");
}
if (inf)
{
int ret;
strlcpy(cptr->info, inf[0] ? inf : me.name, sizeof(cptr->info)); /* set real description */
ret = _check_deny_version(cptr, NULL, atoi(protocol), flags);
if (ret < 0)
return ret;
} else {
strlcpy(cptr->info, info[0] ? info : me.name, sizeof(cptr->info));
}
else
strlcpy(cptr->info, info[0] ? info : me.name,
sizeof(cptr->info));
} else {
strlcpy(cptr->info, info[0] ? info : me.name, sizeof(cptr->info));
}
else
strlcpy(cptr->info, info[0] ? info : me.name,
sizeof(cptr->info));
for (deny = conf_deny_link; deny; deny = (ConfigItem_deny_link *) deny->next) {
for (deny = conf_deny_link; deny; deny = (ConfigItem_deny_link *) deny->next)
{
if (deny->flag.type == CRULE_ALL && !match(deny->mask, servername)
&& crule_eval(deny->rule)) {
sendto_ops("Refused connection from %s.",
@@ -686,8 +719,7 @@ int m_server_synch(aClient *cptr, ConfigItem_link *aconf)
sendto_one(cptr, "PASS :%s", (aconf->auth->type == AUTHTYPE_PLAINTEXT) ? aconf->auth->data : "*");
send_proto(cptr, aconf);
sendto_one(cptr, "SERVER %s 1 :%s",
me.name, me.info);
send_server_message(cptr);
}
/* Set up server structure */