I'm trying to to update a DNS using a C++ code. My method is to use a string with a pipe with nsupdate.

When i call my system with "echo -e "" the trace file says "incorrect section name -e, and i don't understand what is the problem because if i paste the string into my linux terminal, it add correctly the DNS record.

std::ostringstream oss;
oss << "echo -e \"update add " << enumName << ".";
oss << m_configuration.m_zone << ". ";
oss << m_configuration.m_ttl << " NAPTR ";
oss << m_configuration.m_priority << " ";
oss << m_configuration.m_weight << " ";
oss << "\\\"S\\\" ";
oss << "\\\"" << boost::to_upper_copy<std::string>(service) <<m_configuration.m_serviceSuffix << "\\\" ";
oss << "\\\"" << m_configuration.m_regex << "\\\" ";
oss << "_" << service << "._" << m_configuration.m_srvRecord << "." << m_configuration.m_zone << ".\\n";
oss << "send\\nquit\" | nsupdate -l -v";
std::string msg = oss.str();
TRACE_DEBUG("msg: '%s'", msg.c_str());
 res = (system((msg).c_str()) == 0);

the Trace Debug shows msg and when i paste msg on my terminal it works... but the Jenkins debugger shows this : "incorrect section name: -e syntax error"

Any help would be appreciated

1 Answers

Michael Veksler On Best Solutions

This is because system calls /bin/sh instead of $SHELL like your terminal. Some /bin/sh implementations will simply echo the characters -e just like any other text that the builtin echo will print to stdout. This -e is passed to nsupdate as is, and confuses it. This confusion causes the error.

The correct solution is to avoid using system altogether, and especially avoid constructing a string that you pass to echo. Of course, you can use /bin/echo if you want to avoid the builtin echo, but using echo in this manner is not advised in order to avoid command injection.

A better solution would be to either one of:

  1. put the text into a file and use /bin/cat, or simply use <some_temp_file to redirect the input. Using a file, safely, is tricky. Someone might read sensitive data, or manipulate the file, unless you do it right.
  2. Use popen instead of system, only calling /usr/bin/nsupdate -l -v
  3. Use fork and one of execve variants, only calling /usr/bin/nsupdate -l -v.

Note, use full path /usr/bin/nsupdate and don't rely on PATH, since PATH could be manipulated by a malicious third party.