vector<pair<struct timeval, string> > g_confDelta;
std::string g_consoleKey;
bool g_logConsoleConnections{true};
+bool g_consoleEnabled{false};
// MUST BE CALLED UNDER A LOCK - right now the LuaLock
static void feedConfigDelta(const std::string& line)
return ret;
}
+static bool sendMessageToServer(int fd, const std::string& line, SodiumNonce& readingNonce, SodiumNonce& writingNonce, const bool outputEmptyLine)
+{
+ string msg = sodEncryptSym(line, g_consoleKey, writingNonce);
+ const auto msgLen = msg.length();
+ if (msgLen > std::numeric_limits<uint32_t>::max()) {
+ cout << "Encrypted essage is too long to be sent to the server, "<< std::to_string(msgLen) << " > " << std::numeric_limits<uint32_t>::max() << endl;
+ return true;
+ }
+
+ putMsgLen32(fd, static_cast<uint32_t>(msgLen));
+
+ if (!msg.empty()) {
+ cerr << "sending message of size " << msgLen << endl;
+ writen2(fd, msg);
+ }
+
+ uint32_t len;
+ if(!getMsgLen32(fd, &len)) {
+ cout << "Connection closed by the server." << endl;
+ return false;
+ }
+
+ if (len == 0) {
+ if (outputEmptyLine) {
+ cout << endl;
+ }
+
+ return true;
+ }
+
+ boost::scoped_array<char> resp(new char[len]);
+ readn2(fd, resp.get(), len);
+ msg.assign(resp.get(), len);
+ msg = sodDecryptSym(msg, g_consoleKey, readingNonce);
+ cout << msg;
+ cout.flush();
+
+ return true;
+}
+
void doClient(ComboAddress server, const std::string& command)
{
- if(g_verbose)
+ if (!sodIsValidKey(g_consoleKey)) {
+ cerr << "The currently configured console key is not valid, please configure a valid key using the setKey() directive" << endl;
+ return;
+ }
+
+ if(g_verbose) {
cout<<"Connecting to "<<server.toStringWithPort()<<endl;
+ }
int fd=socket(server.sin4.sin_family, SOCK_STREAM, 0);
if (fd < 0) {
readingNonce.merge(ours, theirs);
writingNonce.merge(theirs, ours);
- if(!command.empty()) {
- string msg=sodEncryptSym(command, g_consoleKey, writingNonce);
- putMsgLen32(fd, (uint32_t) msg.length());
- if(!msg.empty())
- writen2(fd, msg);
- uint32_t len;
- if(getMsgLen32(fd, &len)) {
- if (len > 0) {
- boost::scoped_array<char> resp(new char[len]);
- readn2(fd, resp.get(), len);
- msg.assign(resp.get(), len);
- msg=sodDecryptSym(msg, g_consoleKey, readingNonce);
- cout<<msg;
- cout.flush();
- }
- }
- else {
- cout << "Connection closed by the server." << endl;
- }
+ /* try sending an empty message, the server should send an empty
+ one back. If it closes the connection instead, we are probably
+ having a key mismatch issue. */
+ if (!sendMessageToServer(fd, "", readingNonce, writingNonce, false)) {
+ cerr<<"The server closed the connection right away, likely indicating a key mismatch. Please check your setKey() directive."<<endl;
+ close(fd);
+ return;
+ }
+
+ if (!command.empty()) {
+ sendMessageToServer(fd, command, readingNonce, writingNonce, false);
+
close(fd);
return;
}
if(line.empty())
continue;
- string msg=sodEncryptSym(line, g_consoleKey, writingNonce);
- putMsgLen32(fd, (uint32_t) msg.length());
- writen2(fd, msg);
- uint32_t len;
- if(!getMsgLen32(fd, &len)) {
- cout << "Connection closed by the server." << endl;
+ if (!sendMessageToServer(fd, line, readingNonce, writingNonce, true)) {
break;
}
-
- if (len > 0) {
- boost::scoped_array<char> resp(new char[len]);
- readn2(fd, resp.get(), len);
- msg.assign(resp.get(), len);
- msg=sodDecryptSym(msg, g_consoleKey, readingNonce);
- cout<<msg;
- cout.flush();
- }
- else {
- cout<<endl;
- }
}
close(fd);
}
boost::scoped_array<char> msg(new char[len]);
readn2(fd, msg.get(), len);
-
+
string line(msg.get(), len);
+
line = sodDecryptSym(line, g_consoleKey, readingNonce);
// cerr<<"Have decrypted line: "<<line<<endl;
string response;
while ((sock = SAccept(fd, client)) >= 0) {
+ if (!sodIsValidKey(g_consoleKey)) {
+ vinfolog("Control connection from %s dropped because we don't have a valid key configured, please configure one using setKey()", client.toStringWithPort());
+ close(sock);
+ continue;
+ }
+
if (!localACL->match(client)) {
vinfolog("Control connection from %s dropped because of ACL", client.toStringWithPort());
close(sock);
struct DNSDistStats g_stats;
uint16_t g_maxOutstanding{10240};
-bool g_console;
bool g_verboseHealthChecks{false};
uint32_t g_staleCacheEntriesTTL{0};
bool g_syslog{true};
signal(SIGPIPE, SIG_IGN);
signal(SIGCHLD, SIG_IGN);
openlog("dnsdist", LOG_PID, LOG_DAEMON);
- g_console=true;
#ifdef HAVE_LIBSODIUM
if (sodium_init() == -1) {
}
warnlog("dnsdist %s comes with ABSOLUTELY NO WARRANTY. This is free software, and you are welcome to redistribute it according to the terms of the GPL version 2", VERSION);
+
vector<string> vec;
std::string acls;
g_ACL.getLocal()->toStringVector(&vec);
}
infolog("Console ACL allowing connections from: %s", acls.c_str());
+#ifdef HAVE_LIBSODIUM
+ if (g_consoleEnabled && g_consoleKey.empty()) {
+ warnlog("Warning, the console has been enabled via 'controlSocket()' but no key has been set with 'setKey()' so all connections will fail until a key has been set");
+ }
+#endif
+
uid_t newgid=0;
gid_t newuid=0;
return "\""+Base64Encode(key)+"\"";
}
+bool sodIsValidKey(const std::string& key)
+{
+ return key.size() == crypto_secretbox_KEYBYTES;
+}
+
std::string sodEncryptSym(const std::string& msg, const std::string& key, SodiumNonce& nonce)
{
+ if (!sodIsValidKey(key)) {
+ throw std::runtime_error("Invalid encryption key of size " + std::to_string(key.size()) + ", use setKey() to set a valid key");
+ }
+
std::string ciphertext;
ciphertext.resize(msg.length() + crypto_secretbox_MACBYTES);
crypto_secretbox_easy(reinterpret_cast<unsigned char*>(&ciphertext.at(0)),
throw std::runtime_error("Could not decrypt message of size " + std::to_string(msg.length()));
}
+ if (!sodIsValidKey(key)) {
+ throw std::runtime_error("Invalid decryption key of size " + std::to_string(key.size()) + ", use setKey() to set a valid key");
+ }
+
decrypted.resize(msg.length() - crypto_secretbox_MACBYTES);
if (crypto_secretbox_open_easy(reinterpret_cast<unsigned char*>(const_cast<char *>(decrypted.data())),
msg.length(),
nonce.value,
reinterpret_cast<const unsigned char*>(key.c_str())) != 0) {
- throw std::runtime_error("Could not decrypt message");
+ throw std::runtime_error("Could not decrypt message, please check that the key configured with setKey() is correct");
}
nonce.increment();
return "\"plaintext\"";
}
+bool sodIsValidKey(const std::string& key)
+{
+ return true;
+}
#endif