[master] allow spaces in rndc arguments

4256.	[bug]		Allow rndc command arguments to be quoted so as
			to allow spaces. [RT #36665]
This commit is contained in:
Evan Hunt 2015-11-05 19:51:54 -08:00
parent e62b9c9ce6
commit b513918481
6 changed files with 367 additions and 238 deletions

View file

@ -1,3 +1,6 @@
4256. [bug] Allow rndc command arguments to be quoted so as
to allow spaces. [RT #36665]
4255. [func] Add 'message-compression' option to disable DNS
compression in responses. [RT #40726]

View file

@ -24,6 +24,7 @@
#include <isc/app.h>
#include <isc/event.h>
#include <isc/lex.h>
#include <isc/mem.h>
#include <isc/string.h>
#include <isc/timer.h>
@ -36,6 +37,7 @@
#include <isccc/result.h>
#include <named/control.h>
#include <named/globals.h>
#include <named/log.h>
#include <named/os.h>
#include <named/server.h>
@ -43,15 +45,30 @@
#include <named/ns_smf_globals.h>
#endif
static isc_boolean_t
command_compare(const char *text, const char *command) {
unsigned int commandlen = strlen(command);
if (strncasecmp(text, command, commandlen) == 0 &&
(text[commandlen] == '\0' ||
text[commandlen] == ' ' ||
text[commandlen] == '\t'))
return (ISC_TRUE);
return (ISC_FALSE);
static isc_result_t
getcommand(isc_lex_t *lex, char **cmdp) {
isc_result_t result;
isc_token_t token;
REQUIRE(cmdp != NULL && *cmdp == NULL);
result = isc_lex_gettoken(lex, ISC_LEXOPT_EOF, &token);
if (result != ISC_R_SUCCESS)
return (result);
isc_lex_ungettoken(lex, &token);
if (token.type != isc_tokentype_string)
return (ISC_R_FAILURE);
*cmdp = token.value.as_textregion.base;
return (ISC_R_SUCCESS);
}
static inline isc_boolean_t
command_compare(const char *str, const char *command) {
return ISC_TF(strcasecmp(str, command) == 0);
}
/*%
@ -61,9 +78,12 @@ command_compare(const char *text, const char *command) {
isc_result_t
ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t **text) {
isccc_sexpr_t *data;
char *cmdline = NULL;
char *command = NULL;
isc_result_t result;
int log_level;
isc_buffer_t src;
isc_lex_t *lex = NULL;
#ifdef HAVE_LIBSCF
ns_smf_want_disable = 0;
#endif
@ -76,7 +96,7 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t **text) {
return (ISC_R_FAILURE);
}
result = isccc_cc_lookupstring(data, "type", &command);
result = isccc_cc_lookupstring(data, "type", &cmdline);
if (result != ISC_R_SUCCESS) {
/*
* We have no idea what this is.
@ -84,6 +104,20 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t **text) {
return (result);
}
result = isc_lex_create(ns_g_mctx, strlen(cmdline), &lex);
if (result != ISC_R_SUCCESS)
return (result);
isc_buffer_init(&src, cmdline, strlen(cmdline));
isc_buffer_add(&src, strlen(cmdline));
result = isc_lex_openbuffer(lex, &src);
if (result != ISC_R_SUCCESS)
goto cleanup;
result = getcommand(lex, &command);
if (result != ISC_R_SUCCESS)
goto cleanup;
/*
* Compare the 'command' parameter against all known control commands.
*/
@ -93,20 +127,21 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t **text) {
} else {
log_level = ISC_LOG_INFO;
}
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_CONTROL, log_level,
"received control channel command '%s'",
command);
if (command_compare(command, NS_COMMAND_RELOAD)) {
result = ns_server_reloadcommand(ns_g_server, command, text);
result = ns_server_reloadcommand(ns_g_server, lex, text);
} else if (command_compare(command, NS_COMMAND_RECONFIG)) {
result = ns_server_reconfigcommand(ns_g_server);
} else if (command_compare(command, NS_COMMAND_REFRESH)) {
result = ns_server_refreshcommand(ns_g_server, command, text);
result = ns_server_refreshcommand(ns_g_server, lex, text);
} else if (command_compare(command, NS_COMMAND_RETRANSFER)) {
result = ns_server_retransfercommand(ns_g_server,
command, text);
lex, text);
} else if (command_compare(command, NS_COMMAND_HALT)) {
#ifdef HAVE_LIBSCF
/*
@ -116,7 +151,7 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t **text) {
*/
if (ns_smf_got_instance == 1 && ns_smf_chroot == 1) {
result = ns_smf_add_message(text);
return (result);
goto cleanup;
}
/*
* If we are managed by smf(5) but not in chroot,
@ -143,7 +178,7 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t **text) {
#ifdef HAVE_LIBSCF
if (ns_smf_got_instance == 1 && ns_smf_chroot == 1) {
result = ns_smf_add_message(text);
return (result);
goto cleanup;
}
if (ns_smf_got_instance == 1 && ns_smf_chroot == 0)
ns_smf_want_disable = 1;
@ -155,42 +190,42 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t **text) {
} else if (command_compare(command, NS_COMMAND_DUMPSTATS)) {
result = ns_server_dumpstats(ns_g_server);
} else if (command_compare(command, NS_COMMAND_QUERYLOG)) {
result = ns_server_togglequerylog(ns_g_server, command);
result = ns_server_togglequerylog(ns_g_server, lex);
} else if (command_compare(command, NS_COMMAND_DUMPDB)) {
ns_server_dumpdb(ns_g_server, command);
ns_server_dumpdb(ns_g_server, lex);
result = ISC_R_SUCCESS;
} else if (command_compare(command, NS_COMMAND_SECROOTS)) {
result = ns_server_dumpsecroots(ns_g_server, command, text);
result = ns_server_dumpsecroots(ns_g_server, lex, text);
} else if (command_compare(command, NS_COMMAND_TRACE)) {
result = ns_server_setdebuglevel(ns_g_server, command);
result = ns_server_setdebuglevel(ns_g_server, lex);
} else if (command_compare(command, NS_COMMAND_NOTRACE)) {
ns_g_debuglevel = 0;
isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel);
result = ISC_R_SUCCESS;
} else if (command_compare(command, NS_COMMAND_FLUSH)) {
result = ns_server_flushcache(ns_g_server, command);
result = ns_server_flushcache(ns_g_server, lex);
} else if (command_compare(command, NS_COMMAND_FLUSHNAME)) {
result = ns_server_flushnode(ns_g_server, command, ISC_FALSE);
result = ns_server_flushnode(ns_g_server, lex, ISC_FALSE);
} else if (command_compare(command, NS_COMMAND_FLUSHTREE)) {
result = ns_server_flushnode(ns_g_server, command, ISC_TRUE);
result = ns_server_flushnode(ns_g_server, lex, ISC_TRUE);
} else if (command_compare(command, NS_COMMAND_STATUS)) {
result = ns_server_status(ns_g_server, text);
} else if (command_compare(command, NS_COMMAND_TSIGLIST)) {
result = ns_server_tsiglist(ns_g_server, text);
} else if (command_compare(command, NS_COMMAND_TSIGDELETE)) {
result = ns_server_tsigdelete(ns_g_server, command, text);
result = ns_server_tsigdelete(ns_g_server, lex, text);
} else if (command_compare(command, NS_COMMAND_FREEZE)) {
result = ns_server_freeze(ns_g_server, ISC_TRUE, command,
result = ns_server_freeze(ns_g_server, ISC_TRUE, lex,
text);
} else if (command_compare(command, NS_COMMAND_UNFREEZE) ||
command_compare(command, NS_COMMAND_THAW)) {
result = ns_server_freeze(ns_g_server, ISC_FALSE, command,
result = ns_server_freeze(ns_g_server, ISC_FALSE, lex,
text);
} else if (command_compare(command, NS_COMMAND_SCAN)) {
result = ISC_R_SUCCESS;
ns_server_scan_interfaces(ns_g_server);
} else if (command_compare(command, NS_COMMAND_SYNC)) {
result = ns_server_sync(ns_g_server, command, text);
result = ns_server_sync(ns_g_server, lex, text);
} else if (command_compare(command, NS_COMMAND_RECURSING)) {
result = ns_server_dumprecursing(ns_g_server);
} else if (command_compare(command, NS_COMMAND_TIMERPOKE)) {
@ -199,29 +234,29 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t **text) {
} else if (command_compare(command, NS_COMMAND_NULL)) {
result = ISC_R_SUCCESS;
} else if (command_compare(command, NS_COMMAND_NOTIFY)) {
result = ns_server_notifycommand(ns_g_server, command, text);
result = ns_server_notifycommand(ns_g_server, lex, text);
} else if (command_compare(command, NS_COMMAND_VALIDATION)) {
result = ns_server_validation(ns_g_server, command, text);
result = ns_server_validation(ns_g_server, lex, text);
} else if (command_compare(command, NS_COMMAND_SIGN) ||
command_compare(command, NS_COMMAND_LOADKEYS)) {
result = ns_server_rekey(ns_g_server, command, text);
result = ns_server_rekey(ns_g_server, lex, text);
} else if (command_compare(command, NS_COMMAND_ADDZONE) ||
command_compare(command, NS_COMMAND_MODZONE)) {
result = ns_server_changezone(ns_g_server, command, text);
result = ns_server_changezone(ns_g_server, cmdline, text);
} else if (command_compare(command, NS_COMMAND_DELZONE)) {
result = ns_server_delzone(ns_g_server, command, text);
result = ns_server_delzone(ns_g_server, lex, text);
} else if (command_compare(command, NS_COMMAND_SHOWZONE)) {
result = ns_server_showzone(ns_g_server, command, text);
result = ns_server_showzone(ns_g_server, lex, text);
} else if (command_compare(command, NS_COMMAND_SIGNING)) {
result = ns_server_signing(ns_g_server, command, text);
result = ns_server_signing(ns_g_server, lex, text);
} else if (command_compare(command, NS_COMMAND_ZONESTATUS)) {
result = ns_server_zonestatus(ns_g_server, command, text);
result = ns_server_zonestatus(ns_g_server, lex, text);
} else if (command_compare(command, NS_COMMAND_NTA)) {
result = ns_server_nta(ns_g_server, command, text);
result = ns_server_nta(ns_g_server, lex, text);
} else if (command_compare(command, NS_COMMAND_TESTGEN)) {
result = ns_server_testgen(command, text);
result = ns_server_testgen(lex, text);
} else if (command_compare(command, NS_COMMAND_MKEYS)) {
result = ns_server_mkeys(ns_g_server, command, text);
result = ns_server_mkeys(ns_g_server, lex, text);
} else {
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_CONTROL, ISC_LOG_WARNING,
@ -230,5 +265,9 @@ ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t **text) {
result = DNS_R_UNKNOWNCOMMAND;
}
cleanup:
if (lex != NULL)
isc_lex_destroy(&lex);
return (result);
}

View file

@ -534,7 +534,8 @@ ns_server_flushonshutdown(ns_server_t *server, isc_boolean_t flush);
*/
isc_result_t
ns_server_reloadcommand(ns_server_t *server, char *args, isc_buffer_t **text);
ns_server_reloadcommand(ns_server_t *server, isc_lex_t *lex,
isc_buffer_t **text);
/*%<
* Act on a "reload" command from the command channel.
*/
@ -546,26 +547,28 @@ ns_server_reconfigcommand(ns_server_t *server);
*/
isc_result_t
ns_server_notifycommand(ns_server_t *server, char *args, isc_buffer_t **text);
ns_server_notifycommand(ns_server_t *server, isc_lex_t *lex,
isc_buffer_t **text);
/*%<
* Act on a "notify" command from the command channel.
*/
isc_result_t
ns_server_refreshcommand(ns_server_t *server, char *args, isc_buffer_t **text);
ns_server_refreshcommand(ns_server_t *server, isc_lex_t *lex,
isc_buffer_t **text);
/*%<
* Act on a "refresh" command from the command channel.
*/
isc_result_t
ns_server_retransfercommand(ns_server_t *server, char *args,
ns_server_retransfercommand(ns_server_t *server, isc_lex_t *lex,
isc_buffer_t **text);
/*%<
* Act on a "retransfer" command from the command channel.
*/
isc_result_t
ns_server_togglequerylog(ns_server_t *server, char *args);
ns_server_togglequerylog(ns_server_t *server, isc_lex_t *lex);
/*%<
* Enable/disable logging of queries. (Takes "yes" or "no" argument,
* but can also be used as a toggle for backward comptibility.)
@ -593,25 +596,26 @@ ns_server_dumpstats(ns_server_t *server);
* Dump the current cache to the dump file.
*/
isc_result_t
ns_server_dumpdb(ns_server_t *server, char *args);
ns_server_dumpdb(ns_server_t *server, isc_lex_t *lex);
/*%
* Dump the current security roots to the secroots file.
*/
isc_result_t
ns_server_dumpsecroots(ns_server_t *server, char *args, isc_buffer_t **text);
ns_server_dumpsecroots(ns_server_t *server, isc_lex_t *lex,
isc_buffer_t **text);
/*%
* Change or increment the server debug level.
*/
isc_result_t
ns_server_setdebuglevel(ns_server_t *server, char *args);
ns_server_setdebuglevel(ns_server_t *server, isc_lex_t *lex);
/*%
* Flush the server's cache(s)
*/
isc_result_t
ns_server_flushcache(ns_server_t *server, char *args);
ns_server_flushcache(ns_server_t *server, isc_lex_t *lex);
/*%
* Flush a particular name from the server's cache. If 'tree' is false,
@ -619,7 +623,8 @@ ns_server_flushcache(ns_server_t *server, char *args);
* flush all the names under the specified name.
*/
isc_result_t
ns_server_flushnode(ns_server_t *server, char *args, isc_boolean_t tree);
ns_server_flushnode(ns_server_t *server, isc_lex_t *lex,
isc_boolean_t tree);
/*%
* Report the server's status.
@ -637,20 +642,21 @@ ns_server_tsiglist(ns_server_t *server, isc_buffer_t **text);
* Delete a specific key (with optional view).
*/
isc_result_t
ns_server_tsigdelete(ns_server_t *server, char *command, isc_buffer_t **text);
ns_server_tsigdelete(ns_server_t *server, isc_lex_t *lex,
isc_buffer_t **text);
/*%
* Enable or disable updates for a zone.
*/
isc_result_t
ns_server_freeze(ns_server_t *server, isc_boolean_t freeze, char *args,
isc_buffer_t **text);
ns_server_freeze(ns_server_t *server, isc_boolean_t freeze,
isc_lex_t *lex, isc_buffer_t **text);
/*%
* Dump zone updates to disk, optionally removing the journal file
*/
isc_result_t
ns_server_sync(ns_server_t *server, char *args, isc_buffer_t **text);
ns_server_sync(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text);
/*%
* Update a zone's DNSKEY set from the key repository. If
@ -660,7 +666,7 @@ ns_server_sync(ns_server_t *server, char *args, isc_buffer_t **text);
* take place incrementally.
*/
isc_result_t
ns_server_rekey(ns_server_t *server, char *args, isc_buffer_t **text);
ns_server_rekey(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text);
/*%
* Dump the current recursive queries.
@ -678,57 +684,57 @@ ns_add_reserved_dispatch(ns_server_t *server, const isc_sockaddr_t *addr);
* Enable or disable dnssec validation.
*/
isc_result_t
ns_server_validation(ns_server_t *server, char *args, isc_buffer_t **text);
ns_server_validation(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text);
/*%
* Add a zone to a running process, or modify an existing zone
*/
isc_result_t
ns_server_changezone(ns_server_t *server, char *args, isc_buffer_t **text);
ns_server_changezone(ns_server_t *server, char *command, isc_buffer_t **text);
/*%
* Deletes a zone from a running process
*/
isc_result_t
ns_server_delzone(ns_server_t *server, char *args, isc_buffer_t **text);
ns_server_delzone(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text);
/*%
* Show current configuration for a given zone
*/
isc_result_t
ns_server_showzone(ns_server_t *server, char *args, isc_buffer_t **text);
ns_server_showzone(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text);
/*%
* Lists the status of the signing records for a given zone.
*/
isc_result_t
ns_server_signing(ns_server_t *server, char *args, isc_buffer_t **text);
ns_server_signing(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text);
/*%
* Lists status information for a given zone (e.g., name, type, files,
* load time, expiry, etc).
*/
isc_result_t
ns_server_zonestatus(ns_server_t *server, char *args, isc_buffer_t **text);
ns_server_zonestatus(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text);
/*%
* Adds a Negative Trust Anchor (NTA) for a specified name and
* duration, in a particular view if specified, or in all views.
*/
isc_result_t
ns_server_nta(ns_server_t *server, char *args, isc_buffer_t **text);
ns_server_nta(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text);
/*%
* Generates a test sequence that is only for use in system tests. The
* argument is the size of required output in bytes.
*/
isc_result_t
ns_server_testgen(char *args, isc_buffer_t **text);
ns_server_testgen(isc_lex_t *lex, isc_buffer_t **text);
/*%
* Force fefresh or print status for managed keys zones.
*/
isc_result_t
ns_server_mkeys(ns_server_t *server, char *args, isc_buffer_t **text);
ns_server_mkeys(ns_server_t *server, isc_lex_t *lex, isc_buffer_t **text);
#endif /* NAMED_SERVER_H */

File diff suppressed because it is too large Load diff

View file

@ -14,8 +14,6 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
/* $Id$ */
controls { /* empty */ };
options {
@ -26,3 +24,10 @@ options {
recursion yes;
};
view normal {
match-clients { any; };
};
view "view with a space" {
match-clients { none; };
};

View file

@ -344,7 +344,7 @@ status=`expr $status + $ret`
echo "I:testing automatic zones are reported"
ret=0
$RNDC -s 10.53.0.4 -p 9956 -c ns4/key6.conf status > rndc.status || ret=1
grep "number of zones: 99 (98 automatic)" rndc.status > /dev/null || ret=1
grep "number of zones: 198 (196 automatic)" rndc.status > /dev/null || ret=1
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
@ -411,6 +411,13 @@ grep "ISC_R_SUCCESS 0" rndc.output > /dev/null || ret=1
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:testing rndc with a token containing a space"
ret=0
$RNDC -s 10.53.0.4 -p 9956 -c ns4/key6.conf -r flush '"view with a space"' 2>&1 > rndc.output || ret=1
grep "not found" rndc.output > /dev/null && ret=1
if [ $ret != 0 ]; then echo "I:failed"; fi
status=`expr $status + $ret`
echo "I:test 'rndc reconfig' with a broken config"
ret=0
$RNDC -s 10.53.0.4 -p 9956 -c ns4/key6.conf reconfig > /dev/null || ret=1