diff --git a/CHANGELOG b/CHANGELOG index e33223d78..b8852f6ad 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,10 @@ # Nmap Changelog ($Id$); -*-text-*- +o The command line in XML output (/nmaprun/@args attribute) now does + quoting of whitespace using double quotes and backslashes. This + allows recovering the original command line array even when + arguments contain whitespace. [David] + o XML output now excludes output for down hosts when doing host discovery only, except in verbose mode. This is how it already worked for normal scans, but the ping-only case was overlooked. diff --git a/nmap.cc b/nmap.cc index fe9e0d3b1..35282ca3c 100644 --- a/nmap.cc +++ b/nmap.cc @@ -1488,7 +1488,7 @@ int nmap_main(int argc, char *argv[]) { } xml_start_comment(); - xml_write_escaped(" %s %s scan initiated %s as: %s ", NMAP_NAME, NMAP_VERSION, mytime, command.c_str()); + xml_write_escaped(" %s %s scan initiated %s as: %s ", NMAP_NAME, NMAP_VERSION, mytime, join_quoted(fakeargv, argc).c_str()); xml_end_comment(); xml_newline(); @@ -1499,7 +1499,7 @@ int nmap_main(int argc, char *argv[]) { xml_open_start_tag("nmaprun"); xml_attribute("scanner", "nmap"); - xml_attribute("args", "%s", command.c_str()); + xml_attribute("args", "%s", join_quoted(fakeargv, argc).c_str()); xml_attribute("start", "%lu", (unsigned long) timep); xml_attribute("startstr", "%s", mytime); xml_attribute("version", "%s", NMAP_VERSION); diff --git a/output.cc b/output.cc index c46e44fc7..6e14e7b6a 100644 --- a/output.cc +++ b/output.cc @@ -1190,6 +1190,41 @@ static void doscaninfo(const char *type, const char *proto, xml_newline(); } +static std::string quote(const char *s) { + std::string result(""); + const char *p; + bool space; + + space = false; + for (p = s; *p != '\0'; p++) { + if (isspace(*p)) + space = true; + if (*p == '"' || *p == '\\') + result += "\\"; + result += *p; + } + + if (space) + result = "\"" + result + "\""; + + return result; +} + +/* Return a std::string containing all n strings separated by whitespace, and + individually quoted if needed. */ +std::string join_quoted(const char * const strings[], unsigned int n) { + std::string result(""); + unsigned int i; + + for (i = 0; i < n; i++) { + if (i > 0) + result += " "; + result += quote(strings[i]); + } + + return result; +} + /* Similar to output_ports_to_machine_parseable_output, this function outputs the XML version, which is scaninfo records of each scan requested and the ports which it will scan for */ diff --git a/output.h b/output.h index b4860d968..8ad7450f7 100644 --- a/output.h +++ b/output.h @@ -190,6 +190,10 @@ void output_ports_to_machine_parseable_output(struct scan_lists *ports, int tcpscan, int udpscan, int sctpscan, int protscan); +/* Return a std::string containing all n strings separated by whitespace, and + individually quoted if needed. */ +std::string join_quoted(const char * const strings[], unsigned int n); + /* Similar to output_ports_to_machine_parseable_output, this function outputs the XML version, which is scaninfo records of each scan requested and the ports which it will scan for */