[v9_9] allow spaces in rndc arguments

4256.	[bug]		Allow rndc command arguments to be quoted so as
			to allow spaces. [RT #36665]

(cherry picked from commit b513918481)
(cherry picked from commit d1ce32ad70)
This commit is contained in:
Evan Hunt
2015-11-05 21:42:27 -08:00
parent 7124919ff3
commit 47a8327820
6 changed files with 322 additions and 177 deletions

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,39 +190,39 @@ 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);
result = ns_server_dumpsecroots(ns_g_server, lex);
} 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_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)) {
@@ -196,18 +231,18 @@ 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);
result = ns_server_validation(ns_g_server, lex);
} 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)) {
result = ns_server_add_zone(ns_g_server, command, text);
result = ns_server_add_zone(ns_g_server, cmdline, text);
} else if (command_compare(command, NS_COMMAND_DELZONE)) {
result = ns_server_del_zone(ns_g_server, command, text);
result = ns_server_del_zone(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 {
isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
NS_LOGMODULE_CONTROL, ISC_LOG_WARNING,
@@ -216,5 +251,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);
}