From: divverent Date: Sat, 26 Apr 2008 09:49:21 +0000 (+0000) Subject: Extend rcon_restricted_commands to contain more complex patterns: X-Git-Tag: xonotic-v0.1.0preview~2263 X-Git-Url: https://git.rm.cloudns.org/?a=commitdiff_plain;h=7c264b15aec2bfbcf52ea8498bb240c23458a54a;p=xonotic%2Fdarkplaces.git Extend rcon_restricted_commands to contain more complex patterns: - Wildcards are supported. A * matches EXACTLY one arg. ? never matches whitespace. * wildcards match AT LEAST one character. - Multi-word patterns are supported - they then match EXACTLY the command. - Single-word non-wildcard patterns still match if the first word of the command matches. Currently, there is no way to enforce that a command is used ONLY without any args. Also, wildcard expressions currently NEVER match a command with quotes, as quotes could subvert the argument restrictions. Examples: foo * bar * * - matches: foo XXX bar XXX XXX - does not match: foo bar XXX XXX, foo XXX bar XXX XXX XXX, foo XXX bar XXX foo - matches: foo, foo XXX, foo XXX XXX - does not match: foobar foo bar - matches: foo bar - does not match: foo bar baz foo*bar - matches: foo42bar, foo1bar - does not match: foobar, foo bar git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@8267 d7cf8633-e32d-0410-b094-e92efae38249 --- diff --git a/common.h b/common.h index 9c20eb10..e8a363f5 100644 --- a/common.h +++ b/common.h @@ -313,6 +313,7 @@ typedef struct stringlist_s } stringlist_t; int matchpattern(const char *in, const char *pattern, int caseinsensitive); +int matchpattern_with_separator(const char *in, const char *pattern, int caseinsensitive, const char *separators, qboolean wildcard_least_one); void stringlistinit(stringlist_t *list); void stringlistfreecontents(stringlist_t *list); void stringlistappend(stringlist_t *list, const char *text); diff --git a/filematch.c b/filematch.c index 622f774b..1f5b1395 100644 --- a/filematch.c +++ b/filematch.c @@ -4,6 +4,11 @@ // LordHavoc: some portable directory listing code I wrote for lmp2pcx, now used in darkplaces to load id1/*.pak and such... int matchpattern(const char *in, const char *pattern, int caseinsensitive) +{ + return matchpattern_with_separator(in, pattern, caseinsensitive, "/\\:", false); +} + +int matchpattern_with_separator(const char *in, const char *pattern, int caseinsensitive, const char *separators, qboolean wildcard_least_one) { int c1, c2; while (*pattern) @@ -13,18 +18,21 @@ int matchpattern(const char *in, const char *pattern, int caseinsensitive) case 0: return 1; // end of pattern case '?': // match any single character - if (*in == 0 || *in == '/' || *in == '\\' || *in == ':') + if (*in == 0 || strchr(separators, *in)) return 0; // no match in++; pattern++; break; case '*': // match anything until following string + if(wildcard_least_one) + if (*in == 0 || strchr(separators, *in)) + return 0; // no match if (!*in) return 1; // match pattern++; while (*in) { - if (*in == '/' || *in == '\\' || *in == ':') + if (strchr(separators, *in)) break; // see if pattern matches at this offset if (matchpattern(in, pattern, caseinsensitive)) diff --git a/netconn.c b/netconn.c index b63c5282..f88dfdad 100755 --- a/netconn.c +++ b/netconn.c @@ -1979,6 +1979,7 @@ void NetConn_ClearConnectFlood(lhnetaddress_t *peeraddress) const char *RCon_Authenticate(const char *password, const char *s, const char *endpos) { const char *text; + qboolean hasquotes; if(!strcmp(rcon_password.string, password)) return "rcon"; @@ -1995,15 +1996,36 @@ const char *RCon_Authenticate(const char *password, const char *s, const char *e size_t l = strlen(s); if(l) { - text = s; - - if (!COM_ParseToken_Console(&text)) - return NULL; - - // com_token now contains the command - if(!strstr(va(" %s ", rcon_restricted_commands.string), va(" %s ", com_token))) - return NULL; + hasquotes = (strchr(s, '"') != NULL); + // sorry, we can't allow these substrings in wildcard expressions, + // as they can mess with the argument counts + text = rcon_restricted_commands.string; + while(COM_ParseToken_Console(&text)) + { + // com_token now contains a pattern to check for... + if(strchr(com_token, '*') || strchr(com_token, '?')) // wildcard expression, * can only match a SINGLE argument + { + if(!hasquotes) + if(matchpattern_with_separator(s, com_token, true, " ", true)) // note how we excluded tab, newline etc. above + goto match; + } + else if(strchr(com_token, ' ')) // multi-arg expression? must match in whole + { + if(!strcmp(com_token, s)) + goto match; + } + else // single-arg expression? must match the beginning of the command + { + if(!strcmp(com_token, s)) + goto match; + if(!memcmp(va("%s ", com_token), s, strlen(com_token) + 1)) + goto match; + } + } + // if we got here, nothing matched! + return NULL; } +match: s += l + 1; }