diff options
author | Adam <Adam@anope.org> | 2012-10-22 00:54:30 -0400 |
---|---|---|
committer | Adam <Adam@anope.org> | 2012-10-22 00:54:30 -0400 |
commit | 0b9db15efc322336ddb08671ce68a3d45fb22520 (patch) | |
tree | 2e8149f370c63f08f2f197eaa92b1b36e857b0e9 /src | |
parent | d5b2f9cfa78ed176ffe1d9f2923799fdd37217a5 (diff) |
Add os_dns, a way to control your DNS zone via services
Diffstat (limited to 'src')
-rw-r--r-- | src/config.cpp | 39 | ||||
-rw-r--r-- | src/dns.cpp | 94 | ||||
-rw-r--r-- | src/init.cpp | 18 | ||||
-rw-r--r-- | src/main.cpp | 11 | ||||
-rw-r--r-- | src/users.cpp | 5 |
5 files changed, 110 insertions, 57 deletions
diff --git a/src/config.cpp b/src/config.cpp index b90c8598a..6347754fb 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -17,6 +17,14 @@ #include "opertype.h" #include "channels.h" #include "hashcomp.h" +#include "dns.h" + +#ifndef _WIN32 +#include <errno.h> +#include <sys/types.h> +#include <pwd.h> +#include <grp.h> +#endif /*************************************************************************/ @@ -200,6 +208,9 @@ ServerConfig::ServerConfig() : config_data(), NSDefFlags(NickCoreFlagStrings), C this->NameServer = "127.0.0.1"; } } + if (DNSEngine) + DNSEngine->SetFlag(SF_DEAD); + DNSEngine = new DNSManager(this->NameServer, this->DNSPort); if (this->CaseMap == "ascii") Anope::casemap = std::locale(std::locale(), new Anope::ascii_ctype<char>()); @@ -219,6 +230,31 @@ ServerConfig::ServerConfig() : config_data(), NSDefFlags(NickCoreFlagStrings), C if (this->SessionIPv4CIDR > 32 || this->SessionIPv6CIDR > 128) throw ConfigException("Session CIDR value out of range"); + +#ifndef _WIN32 + if (!this->User.empty()) + { + errno = 0; + struct passwd *u = getpwnam(this->User.c_str()); + if (u == NULL) + Log() << "Unable to setuid to " << this->User << ": " << Anope::LastError(); + else if (setuid(u->pw_uid) == -1) + Log() << "Unable to setuid to " << this->User << ": " << Anope::LastError(); + else + Log() << "Successfully set user to " << this->User; + } + if (!this->Group.empty()) + { + errno = 0; + struct group *g = getgrnam(this->Group.c_str()); + if (g == NULL) + Log() << "Unable to setgid to " << this->Group << ": " << Anope::LastError(); + else if (setuid(g->gr_gid) == -1) + Log() << "Unable to setgid to " << this->Group << ": " << Anope::LastError(); + else + Log() << "Successfully set group to " << this->Group; + } +#endif } bool ServerConfig::CheckOnce(const Anope::string &tag) @@ -1191,6 +1227,8 @@ ConfigItems::ConfigItems(ServerConfig *conf) {"networkinfo", "userlen", "10", new ValueContainerUInt(&conf->UserLen), DT_UINTEGER | DT_NORELOAD, NoValidation}, {"networkinfo", "hostlen", "64", new ValueContainerUInt(&conf->HostLen), DT_UINTEGER | DT_NORELOAD, NoValidation}, {"networkinfo", "chanlen", "32", new ValueContainerUInt(&conf->ChanLen), DT_UINTEGER | DT_NORELOAD, NoValidation}, + {"options", "user", "", new ValueContainerString(&conf->User), DT_STRING, NoValidation}, + {"options", "group", "", new ValueContainerString(&conf->Group), DT_STRING, NoValidation}, {"options", "casemap", "ascii", new ValueContainerString(&conf->CaseMap), DT_STRING, NoValidation}, {"options", "passlen", "32", new ValueContainerUInt(&conf->PassLen), DT_UINTEGER | DT_NORELOAD, NoValidation}, {"options", "seed", "0", new ValueContainerLUInt(&conf->Seed), DT_LUINTEGER, NoValidation}, @@ -1264,6 +1302,7 @@ ConfigItems::ConfigItems(ServerConfig *conf) {"mail", "memo_message", "", new ValueContainerString(&conf->MailMemoMessage), DT_STRING | DT_ALLOW_NEWLINE, ValidateMail}, {"dns", "nameserver", "127.0.0.1", new ValueContainerString(&conf->NameServer), DT_STRING, NoValidation}, {"dns", "timeout", "5", new ValueContainerTime(&conf->DNSTimeout), DT_TIME, NoValidation}, + {"dns", "port", "53", new ValueContainerInt(&conf->DNSPort), DT_INTEGER, NoValidation}, {"chanserv", "name", "", new ValueContainerString(&conf->ChanServ), DT_STRING, NoValidation}, {"chanserv", "defaults", "keeptopic secure securefounder signkick", new ValueContainerString(&CSDefaults), DT_STRING, ValidateChanServ}, {"chanserv", "maxregistered", "0", new ValueContainerUInt(&conf->CSMaxReg), DT_UINTEGER, ValidateChanServ}, diff --git a/src/dns.cpp b/src/dns.cpp index f21453ddd..519e02b8f 100644 --- a/src/dns.cpp +++ b/src/dns.cpp @@ -56,20 +56,11 @@ DNSQuery::DNSQuery(const Question &q) this->error = DNS_ERROR_NONE; } -DNSQuery::DNSQuery(const DNSPacket &p) -{ - this->questions = p.questions; - this->answers = p.answers; - this->authorities = p.authorities; - this->additional = p.additional; - this->error = DNS_ERROR_NONE; -} - DNSRequest::DNSRequest(const Anope::string &addr, QueryType qt, bool cache, Module *c) : Timer(Config->DNSTimeout), Question(addr, qt), use_cache(cache), id(0), creator(c) { if (!DNSEngine) - DNSEngine = new DNSManager(Config->NameServer, DNSManager::DNSPort); - if (DNSEngine->packets.size() == 65535) + throw SocketException("No DNSEngine"); + if (DNSEngine->GetPackets().size() == 65535) throw SocketException("DNS queue full"); do @@ -101,14 +92,12 @@ void DNSRequest::Process() return; } - DNSPacket *p = new DNSPacket(); + DNSPacket *p = new DNSPacket(DNSEngine->addrs); p->flags = DNS_QUERYFLAGS_RD; p->id = this->id; p->questions.push_back(*this); - DNSEngine->packets.push_back(p); - - SocketEngine::MarkWritable(DNSEngine); + DNSEngine->SendPacket(p); } void DNSRequest::OnError(const DNSQuery *r) @@ -239,12 +228,12 @@ ResourceRecord DNSPacket::UnpackResourceRecord(const unsigned char *input, unsig if (pos + 4 > input_size) throw SocketException("Unable to unpack resource record"); - in_addr addr; - addr.s_addr = input[pos] | (input[pos + 1] << 8) | (input[pos + 2] << 16) | (input[pos + 3] << 24); + in_addr a; + a.s_addr = input[pos] | (input[pos + 1] << 8) | (input[pos + 2] << 16) | (input[pos + 3] << 24); pos += 4; sockaddrs addrs; - addrs.ntop(AF_INET, &addr); + addrs.ntop(AF_INET, &a); record.rdata = addrs.addr(); break; @@ -254,13 +243,13 @@ ResourceRecord DNSPacket::UnpackResourceRecord(const unsigned char *input, unsig if (pos + 16 > input_size) throw SocketException("Unable to unpack resource record"); - in6_addr addr; + in6_addr a; for (int j = 0; j < 16; ++j) - addr.s6_addr[j] = input[pos + j]; + a.s6_addr[j] = input[pos + j]; pos += 16; sockaddrs addrs; - addrs.ntop(AF_INET6, &addr); + addrs.ntop(AF_INET6, &a); record.rdata = addrs.addr(); break; @@ -280,9 +269,8 @@ ResourceRecord DNSPacket::UnpackResourceRecord(const unsigned char *input, unsig return record; } -DNSPacket::DNSPacket() : DNSQuery() +DNSPacket::DNSPacket(const sockaddrs &a) : DNSQuery(), addr(a), id(0), flags(0) { - this->id = this->flags = 0; } void DNSPacket::Fill(const unsigned char *input, const unsigned short len) @@ -426,13 +414,13 @@ unsigned short DNSPacket::Pack(unsigned char *output, unsigned short output_size if (pos + 6 > output_size) throw SocketException("Unable to pack packet"); - sockaddrs addr(rr.rdata); + sockaddrs a(rr.rdata); s = htons(4); memcpy(&output[pos], &s, 2); pos += 2; - memcpy(&output[pos], &addr.sa4.sin_addr, 4); + memcpy(&output[pos], &a.sa4.sin_addr, 4); pos += 4; break; } @@ -441,13 +429,13 @@ unsigned short DNSPacket::Pack(unsigned char *output, unsigned short output_size if (pos + 18 > output_size) throw SocketException("Unable to pack packet"); - sockaddrs addr(rr.rdata); + sockaddrs a(rr.rdata); s = htons(16); memcpy(&output[pos], &s, 2); pos += 2; - memcpy(&output[pos], &addr.sa6.sin6_addr, 16); + memcpy(&output[pos], &a.sa6.sin6_addr, 16); pos += 16; break; } @@ -477,6 +465,15 @@ unsigned short DNSPacket::Pack(unsigned char *output, unsigned short output_size DNSManager::DNSManager(const Anope::string &nameserver, int port) : Timer(300, Anope::CurTime, true), Socket(-1, nameserver.find(':') != Anope::string::npos, SOCK_DGRAM) { this->addrs.pton(this->IPv6 ? AF_INET6 : AF_INET, nameserver, port); + try + { + this->Bind("0.0.0.0", port); + } + catch (const SocketException &ex) + { + /* This error can be from normal operation as most people don't use services to handle DNS queries, so put it in debug log */ + Log(LOG_DEBUG) << "Unable to bind DNSManager to port " << port << ": " << ex.GetReason(); + } } DNSManager::~DNSManager() @@ -514,13 +511,7 @@ bool DNSManager::ProcessRead() if (length < DNSPacket::HEADER_LENGTH) return true; - if (this->addrs != from_server) - { - Log(LOG_DEBUG_2) << "Resolver: Received an answer from the wrong nameserver, Bad NAT or DNS forging attempt? '" << this->addrs.addr() << "' != '" << from_server.addr() << "'"; - return true; - } - - DNSPacket recv_packet; + DNSPacket recv_packet(from_server); try { @@ -532,6 +523,18 @@ bool DNSManager::ProcessRead() return true; } + if (!(recv_packet.flags & DNS_QUERYFLAGS_QR)) + { + FOREACH_MOD(I_OnDnsRequest, OnDnsRequest(recv_packet)); + return true; + } + + if (this->addrs != from_server) + { + Log(LOG_DEBUG_2) << "Resolver: Received an answer from the wrong nameserver, Bad NAT or DNS forging attempt? '" << this->addrs.addr() << "' != '" << from_server.addr() << "'"; + return true; + } + std::map<unsigned short, DNSRequest *>::iterator it = DNSEngine->requests.find(recv_packet.id); if (it == DNSEngine->requests.end()) { @@ -540,13 +543,7 @@ bool DNSManager::ProcessRead() } DNSRequest *request = it->second; - if (!(recv_packet.flags & DNS_QUERYFLAGS_QR)) - { - Log(LOG_DEBUG_2) << "Resolver: Received a non-answer"; - recv_packet.error = DNS_ERROR_NOT_AN_ANSWER; - request->OnError(&recv_packet); - } - else if (recv_packet.flags & DNS_QUERYFLAGS_OPCODE) + if (recv_packet.flags & DNS_QUERYFLAGS_OPCODE) { Log(LOG_DEBUG_2) << "Resolver: Received a nonstandard query"; recv_packet.error = DNS_ERROR_NONSTANDARD_QUERY; @@ -614,7 +611,7 @@ bool DNSManager::ProcessWrite() unsigned char buffer[524]; unsigned short len = r->Pack(buffer, sizeof(buffer)); - sendto(this->GetFD(), reinterpret_cast<char *>(buffer), len, 0, &this->addrs.sa, this->addrs.size()); + sendto(this->GetFD(), reinterpret_cast<char *>(buffer), len, 0, &r->addr.sa, r->addr.size()); } catch (const SocketException &) { } @@ -698,6 +695,19 @@ void DNSManager::Cleanup(Module *mod) } } +std::deque<DNSPacket *>& DNSManager::GetPackets() +{ + return this->packets; +} + +void DNSManager::SendPacket(DNSPacket *p) +{ + Log(LOG_DEBUG_2) << "Resolver: Queueing packet " << p->id; + this->packets.push_back(p); + + SocketEngine::MarkWritable(this); +} + DNSQuery DNSManager::BlockingQuery(const Anope::string &mask, QueryType qt) { Question question(mask, qt); diff --git a/src/init.cpp b/src/init.cpp index 4f0f8bac3..c2c44ec16 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -422,6 +422,9 @@ void Init(int ac, char **av) Log(LOG_TERMINAL) << "Using configuration file " << conf_dir << "/" << services_conf.GetName(); #endif + /* Initialize the socket engine */ + SocketEngine::Init(); + /* Read configuration file; exit if there are problems. */ try { @@ -441,6 +444,15 @@ void Init(int ac, char **av) if (!SupportedWindowsVersion()) throw FatalException(GetWindowsVersion() + " is not a supported version of Windows"); #else + /* If we're root, issue a warning now */ + if (!getuid() && !getgid()) + { + std::cerr << "WARNING: You are currently running Anope as the root superuser. Anope does not" << std::endl; + std::cerr << " require root privileges to run, and it is discouraged that you run Anope" << std::endl; + std::cerr << " as the root superuser." << std::endl; + sleep(3); + } + if (!nofork && AtTerm()) { /* Install these before fork() - it is possible for the child to @@ -478,16 +490,16 @@ void Init(int ac, char **av) } #endif - /* Initialize the socket engine */ - SocketEngine::Init(); - /* Write our PID to the PID file. */ write_pidfile(); /* Create me */ Me = new Server(NULL, Config->ServerName, 0, Config->ServerDesc, Config->Numeric); for (botinfo_map::const_iterator it = BotListByNick->begin(), it_end = BotListByNick->end(); it != it_end; ++it) + { it->second->server = Me; + ++Me->Users; + } /* Announce ourselves to the logfile. */ Log() << "Anope " << Anope::Version() << " starting up" << (debug || readonly ? " (options:" : "") << (debug ? " debug" : "") << (readonly ? " readonly" : "") << (debug || readonly ? ")" : ""); diff --git a/src/main.cpp b/src/main.cpp index d43bda2bc..26e7e67ff 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -362,17 +362,6 @@ Anope::string GetFullProgDir(const Anope::string &argv0) int main(int ac, char **av, char **envp) { -#ifndef _WIN32 - /* If we're root, issue a warning now */ - if (!getuid() && !getgid()) - { - std::cerr << "WARNING: You are currently running Anope as the root superuser. Anope does not" << std::endl; - std::cerr << " require root privileges to run, and it is discouraged that you run Anope" << std::endl; - std::cerr << " as the root superuser." << std::endl; - sleep(3); - } -#endif - binary_dir = GetFullProgDir(av[0]); if (binary_dir[binary_dir.length() - 1] == '.') binary_dir = binary_dir.substr(0, binary_dir.length() - 2); diff --git a/src/users.cpp b/src/users.cpp index fac00d723..187e55808 100644 --- a/src/users.cpp +++ b/src/users.cpp @@ -66,7 +66,10 @@ User::User(const Anope::string &snick, const Anope::string &sident, const Anope: this->nc = NULL; if (sserver) // Our bots are introduced on startup with no server + { + ++sserver->Users; Log(this, "connect") << (!svhost.empty() ? Anope::string("(") + svhost + ") " : "") << "(" << srealname << ") " << sip << " connected to the network (" << sserver->GetName() << ")"; + } ++usercnt; if (usercnt > maxusercnt) @@ -241,7 +244,7 @@ User::~User() Log(LOG_DEBUG_2) << "User::~User() called"; Log(this, "disconnect") << "(" << this->realname << ") " << "disconnected from the network (" << this->server->GetName() << ")"; - + --this->server->Users; FOREACH_MOD(I_OnUserLogoff, OnUserLogoff(this)); |