X-Git-Url: https://git.netwichtig.de/gitweb/?a=blobdiff_plain;f=src%2Fconfigreader.cpp;h=d93a1d4d8b843b43f00212ab0afa9a67cfbfbb09;hb=b7e299c2e10d915d5e59df4cb3f54951c8daa999;hp=1d027ae93dfe2f7315b772b2c6c2bde2b2b99381;hpb=0c73dcfdb1949735dd24b6ddb76499fc36fc6d91;p=user%2Fhenk%2Fcode%2Finspircd.git diff --git a/src/configreader.cpp b/src/configreader.cpp index 1d027ae93..d93a1d4d8 100644 --- a/src/configreader.cpp +++ b/src/configreader.cpp @@ -21,6 +21,9 @@ std::vector old_module_names, new_module_names, added_modules, removed_modules; +/* Needs forward declaration */ +bool ValidateDnsServer(ServerConfig* conf, const char* tag, const char* value, ValueItem &data); + ServerConfig::ServerConfig(InspIRCd* Instance) : ServerInstance(Instance) { this->ClearStack(); @@ -37,12 +40,13 @@ ServerConfig::ServerConfig(InspIRCd* Instance) : ServerInstance(Instance) NetBufferSize = 10240; SoftLimit = MAXCLIENTS; MaxConn = SOMAXCONN; - MaxWhoResults = 100; + MaxWhoResults = 0; debugging = 0; MaxChans = 20; OperMaxChans = 30; LogLevel = DEFAULT; maxbans.clear(); + DNSServerValidator = &ValidateDnsServer; } void ServerConfig::ClearStack() @@ -129,7 +133,7 @@ void ServerConfig::Update005() char buf[MAXBUF]; snprintf(buf, MAXBUF, "%s:are supported by this server", line5.c_str()); isupport.push_back(buf); - line5 = ""; + line5.clear(); token_counter = 0; } } @@ -222,12 +226,6 @@ bool ValidateDnsServer(ServerConfig* conf, const char* tag, const char* value, V if (!*(data.GetString())) { std::string nameserver; -#ifdef WINDOWS - conf->GetInstance()->Log(DEFAULT,"WARNING: not defined, attempting to find working server in the registry..."); - nameserver = FindNameServerWin(); - data.Set(nameserver.c_str()); - conf->GetInstance()->Log(DEFAULT," set to '%s' as first active resolver in registry.", nameserver.c_str()); -#else // attempt to look up their nameserver from /etc/resolv.conf conf->GetInstance()->Log(DEFAULT,"WARNING: not defined, attempting to find working server in /etc/resolv.conf..."); ifstream resolv("/etc/resolv.conf"); @@ -257,7 +255,6 @@ bool ValidateDnsServer(ServerConfig* conf, const char* tag, const char* value, V conf->GetInstance()->Log(DEFAULT,"/etc/resolv.conf can't be opened! Defaulting to nameserver '127.0.0.1'!"); data.Set("127.0.0.1"); } -#endif } return true; } @@ -292,9 +289,9 @@ bool ValidateNetBufferSize(ServerConfig* conf, const char* tag, const char* valu bool ValidateMaxWho(ServerConfig* conf, const char* tag, const char* value, ValueItem &data) { - if ((!data.GetInteger()) || (data.GetInteger() > 65535) || (data.GetInteger() < 1)) + if ((data.GetInteger() > 65535) || (data.GetInteger() < 1)) { - conf->GetInstance()->Log(DEFAULT,"No MaxWhoResults specified or size out of range, setting to default of 128."); + conf->GetInstance()->Log(DEFAULT," size out of range, setting to default of 128."); data.Set(128); } return true; @@ -407,16 +404,41 @@ bool DoConnect(ServerConfig* conf, const char* tag, char** entries, ValueList &v int recvq = values[8].GetInteger(); int localmax = values[9].GetInteger(); int globalmax = values[10].GetInteger(); + int port = values[11].GetInteger(); + const char* name = values[12].GetString(); + const char* parent = values[13].GetString(); + int maxchans = values[14].GetInteger(); - if (*allow) + if (*parent) { - ConnectClass c(timeout, flood, allow, pingfreq, password, threshold, sendq, recvq, localmax, globalmax); - conf->Classes.push_back(c); + /* Find 'parent' and inherit a new class from it, + * then overwrite any values that are set here + */ + for (ClassVector::iterator item = conf->Classes.begin(); item != conf->Classes.end(); ++item) + { + if (item->GetName() == name) + { + ConnectClass c(name, *item); + c.Update(timeout, flood, *allow ? allow : deny, pingfreq, password, threshold, sendq, recvq, localmax, globalmax, maxchans, port); + conf->Classes.push_back(c); + } + } + throw CoreException("Class name '" + std::string(name) + "' is configured to inherit from class '" + std::string(name) + "' which cannot be found."); } else { - ConnectClass c(deny); - conf->Classes.push_back(c); + if (*allow) + { + ConnectClass c(name, timeout, flood, allow, pingfreq, password, threshold, sendq, recvq, localmax, globalmax, maxchans); + c.SetPort(port); + conf->Classes.push_back(c); + } + else + { + ConnectClass c(name, deny); + c.SetPort(port); + conf->Classes.push_back(c); + } } return true; @@ -545,7 +567,7 @@ void ServerConfig::ReportConfigError(const std::string &errormessage, bool bail, { /* Unneeded because of the ServerInstance->Log() aboive? */ printf("There were errors in your configuration:\n%s\n\n",errormessage.c_str()); - InspIRCd::Exit(EXIT_STATUS_CONFIG); + ServerInstance->Exit(EXIT_STATUS_CONFIG); } else { @@ -593,6 +615,7 @@ void ServerConfig::Read(bool bail, userrec* user) InitialConfig Values[] = { {"options", "softlimit", MAXCLIENTS_S, new ValueContainerUInt (&this->SoftLimit), DT_INTEGER, ValidateSoftLimit}, {"options", "somaxconn", SOMAXCONN_S, new ValueContainerInt (&this->MaxConn), DT_INTEGER, ValidateMaxConn}, + {"options", "moronbanner", "Youre banned!", new ValueContainerChar (this->MoronBanner), DT_CHARPTR, NoValidation}, {"server", "name", "", new ValueContainerChar (this->ServerName), DT_CHARPTR, ValidateServerName}, {"server", "description", "Configure Me", new ValueContainerChar (this->ServerDesc), DT_CHARPTR, NoValidation}, {"server", "network", "Network", new ValueContainerChar (this->Network), DT_CHARPTR, NoValidation}, @@ -611,7 +634,7 @@ void ServerConfig::Read(bool bail, userrec* user) {"options", "netbuffersize","10240", new ValueContainerInt (&this->NetBufferSize), DT_INTEGER, ValidateNetBufferSize}, {"options", "maxwho", "128", new ValueContainerInt (&this->MaxWhoResults), DT_INTEGER, ValidateMaxWho}, {"options", "allowhalfop", "0", new ValueContainerBool (&this->AllowHalfop), DT_BOOLEAN, NoValidation}, - {"dns", "server", "", new ValueContainerChar (this->DNSServer), DT_CHARPTR, ValidateDnsServer}, + {"dns", "server", "", new ValueContainerChar (this->DNSServer), DT_CHARPTR, DNSServerValidator}, {"dns", "timeout", "5", new ValueContainerInt (&this->dns_timeout), DT_INTEGER, NoValidation}, {"options", "moduledir", MOD_PATH, new ValueContainerChar (this->ModPath), DT_CHARPTR, NoValidation}, {"disabled", "commands", "", new ValueContainerChar (this->DisabledCommands), DT_CHARPTR, NoValidation}, @@ -630,7 +653,7 @@ void ServerConfig::Read(bool bail, userrec* user) {"options", "hostintopic", "1", new ValueContainerBool (&this->FullHostInTopic), DT_BOOLEAN, NoValidation}, {"options", "hidemodes", "", new ValueContainerChar (hidemodes), DT_CHARPTR, ValidateModeLists}, {"options", "exemptchanops","", new ValueContainerChar (exemptchanops), DT_CHARPTR, ValidateExemptChanOps}, - {"options", "defaultmodes", "", new ValueContainerChar (this->DefaultModes), DT_CHARPTR, NoValidation}, + {"options", "defaultmodes", "nt", new ValueContainerChar (this->DefaultModes), DT_CHARPTR, NoValidation}, {"pid", "file", "", new ValueContainerChar (this->PID), DT_CHARPTR, NoValidation}, {"whowas", "groupsize", "10", new ValueContainerInt (&this->WhoWasGroupSize), DT_INTEGER, NoValidation}, {"whowas", "maxgroups", "10240", new ValueContainerInt (&this->WhoWasMaxGroups), DT_INTEGER, NoValidation}, @@ -649,12 +672,15 @@ void ServerConfig::Read(bool bail, userrec* user) {"connect", {"allow", "deny", "password", "timeout", "pingfreq", "flood", "threshold", "sendq", "recvq", "localmax", "globalmax", "port", + "name", "parent", "maxchans", NULL}, {"", "", "", "", "120", "", "", "", "", "3", "3", "0", + "", "", "0", NULL}, {DT_CHARPTR, DT_CHARPTR, DT_CHARPTR, DT_INTEGER, DT_INTEGER, DT_INTEGER, - DT_INTEGER, DT_INTEGER, DT_INTEGER, DT_INTEGER, DT_INTEGER, DT_INTEGER}, + DT_INTEGER, DT_INTEGER, DT_INTEGER, DT_INTEGER, DT_INTEGER, DT_INTEGER, + DT_CHARPTR, DT_CHARPTR, DT_INTEGER}, InitConnect, DoConnect, DoneConnect}, {"uline", @@ -866,7 +892,7 @@ void ServerConfig::Read(bool bail, userrec* user) FailedPortList pl; ServerInstance->BindPorts(false, found_ports, pl); - if (pl.size()) + if (pl.size() && user) { user->WriteServ("NOTICE %s :*** Not all your client ports could be bound.", user->nick); user->WriteServ("NOTICE %s :*** The following port(s) failed to bind:", user->nick); @@ -922,6 +948,9 @@ void ServerConfig::Read(bool bail, userrec* user) ServerInstance->Log(DEFAULT,"Successfully unloaded %lu of %lu modules and loaded %lu of %lu modules.",(unsigned long)rem,(unsigned long)removed_modules.size(),(unsigned long)add,(unsigned long)added_modules.size()); } + /** Note: This is safe, the method checks for user == NULL */ + ServerInstance->Parser->SetupCommandTable(user); + if (user) user->WriteServ("NOTICE %s :*** Successfully rehashed server.", user->nick); else @@ -967,7 +996,7 @@ bool ServerConfig::LoadConf(ConfigDataHash &target, const char* filename, std::o include_stack.push_back(filename); /* Start reading characters... */ - while(conf.get(ch)) + while (conf.get(ch)) { /* @@ -993,10 +1022,10 @@ bool ServerConfig::LoadConf(ConfigDataHash &target, const char* filename, std::o * no '>' then die with an error. */ - if((ch == '#') && !in_quote) + if ((ch == '#') && !in_quote) in_comment = true; - switch(ch) + switch (ch) { case '\n': if (in_quote) @@ -1043,11 +1072,11 @@ bool ServerConfig::LoadConf(ConfigDataHash &target, const char* filename, std::o if (ch != '\r') line += ch; - if(ch == '<') + if (ch == '<') { - if(in_tag) + if (in_tag) { - if(!in_quote) + if (!in_quote) { errorstream << "Got another opening < when the first one wasn't closed: " << filename << ":" << linenumber << std::endl; return false; @@ -1055,7 +1084,7 @@ bool ServerConfig::LoadConf(ConfigDataHash &target, const char* filename, std::o } else { - if(in_quote) + if (in_quote) { errorstream << "We're in a quote but outside a tag, interesting. " << filename << ":" << linenumber << std::endl; return false; @@ -1067,11 +1096,11 @@ bool ServerConfig::LoadConf(ConfigDataHash &target, const char* filename, std::o } } } - else if(ch == '"') + else if (ch == '"') { - if(in_tag) + if (in_tag) { - if(in_quote) + if (in_quote) { // errorstream << "Closing quote in config tag on line " << linenumber << std::endl; in_quote = false; @@ -1084,7 +1113,7 @@ bool ServerConfig::LoadConf(ConfigDataHash &target, const char* filename, std::o } else { - if(in_quote) + if (in_quote) { errorstream << "Found a (closing) \" outside a tag: " << filename << ":" << linenumber << std::endl; } @@ -1094,11 +1123,11 @@ bool ServerConfig::LoadConf(ConfigDataHash &target, const char* filename, std::o } } } - else if(ch == '>') + else if (ch == '>') { - if(!in_quote) + if (!in_quote) { - if(in_tag) + if (in_tag) { // errorstream << "Closing config tag on line " << linenumber << std::endl; in_tag = false; @@ -1108,7 +1137,7 @@ bool ServerConfig::LoadConf(ConfigDataHash &target, const char* filename, std::o * LoadConf() and load the included config into the same ConfigDataHash */ - if(!this->ParseLine(target, line, linenumber, errorstream)) + if (!this->ParseLine(target, line, linenumber, errorstream)) return false; line.clear(); @@ -1122,6 +1151,13 @@ bool ServerConfig::LoadConf(ConfigDataHash &target, const char* filename, std::o } } + /* Fix for bug #392 - if we reach the end of a file and we are still in a quote or comment, most likely the user fucked up */ + if (in_comment || in_quote) + { + errorstream << "Reached end of file whilst still inside a quoted section or tag. This is most likely an error or there \ + is a newline missing from the end of the file: " << filename << ":" << linenumber << std::endl; + } + return true; } @@ -1130,7 +1166,7 @@ bool ServerConfig::LoadConf(ConfigDataHash &target, const std::string &filename, return this->LoadConf(target, filename.c_str(), errorstream); } -bool ServerConfig::ParseLine(ConfigDataHash &target, std::string &line, long linenumber, std::ostringstream &errorstream) +bool ServerConfig::ParseLine(ConfigDataHash &target, std::string &line, long &linenumber, std::ostringstream &errorstream) { std::string tagname; std::string current_key; @@ -1142,17 +1178,15 @@ bool ServerConfig::ParseLine(ConfigDataHash &target, std::string &line, long lin got_name = got_key = in_quote = false; - //std::cout << "ParseLine(data, '" << line << "', " << linenumber << ", stream)" << std::endl; - for(std::string::iterator c = line.begin(); c != line.end(); c++) { - if(!got_name) + if (!got_name) { /* We don't know the tag name yet. */ - if(*c != ' ') + if (*c != ' ') { - if(*c != '<') + if (*c != '<') { tagname += *c; } @@ -1205,6 +1239,7 @@ bool ServerConfig::ParseLine(ConfigDataHash &target, std::string &line, long lin { /* Got a 'real' \n, treat it as part of the value */ current_value += '\n'; + linenumber++; continue; } else if ((*c == '\r') && (in_quote)) @@ -1228,9 +1263,9 @@ bool ServerConfig::ParseLine(ConfigDataHash &target, std::string &line, long lin in_quote = false; got_key = false; - if((tagname == "include") && (current_key == "file")) + if ((tagname == "include") && (current_key == "file")) { - if(!this->DoInclude(target, current_value, errorstream)) + if (!this->DoInclude(target, current_value, errorstream)) return false; } @@ -1240,7 +1275,7 @@ bool ServerConfig::ParseLine(ConfigDataHash &target, std::string &line, long lin } else { - if(in_quote) + if (in_quote) { current_value += *c; } @@ -1483,19 +1518,20 @@ bool ServerConfig::ReadFile(file_cache &F, const char* fname) F.clear(); - if (*fname != '/') + if ((*fname != '/') && (*fname != '\\')) { std::string::size_type pos; std::string confpath = ServerInstance->ConfigFileName; - if((pos = confpath.rfind("/")) != std::string::npos) - { - /* Leaves us with just the path */ - std::string newfile = confpath.substr(0, pos) + std::string("/") + fname; - if (!FileExists(newfile.c_str())) - return false; - file = fopen(newfile.c_str(), "r"); + std::string newfile = fname; - } + if ((pos = confpath.rfind("/")) != std::string::npos) + newfile = confpath.substr(0, pos) + std::string("/") + fname; + else if ((pos = confpath.rfind("\\")) != std::string::npos) + newfile = confpath.substr(0, pos) + std::string("\\") + fname; + + if (!FileExists(newfile.c_str())) + return false; + file = fopen(newfile.c_str(), "r"); } else { @@ -1549,7 +1585,7 @@ bool ServerConfig::FileExists(const char* file) char* ServerConfig::CleanFilename(char* name) { char* p = name + strlen(name); - while ((p != name) && (*p != '/')) p--; + while ((p != name) && (*p != '/') && (*p != '\\')) p--; return (p != name ? ++p : p); } @@ -1629,19 +1665,16 @@ std::string ServerConfig::GetFullProgDir() // Get the current working directory if (getcwd(buffer, PATH_MAX)) { - ServerInstance->Log(DEBUG,"getcwd='%s', argv[0]='%s'", buffer, this->argv[0]); std::string remainder = this->argv[0]; /* Does argv[0] start with /? its a full path, use it */ if (remainder[0] == '/') { - ServerInstance->Log(DEBUG,"argv starts with slash, using for full path."); std::string::size_type n = remainder.rfind("/inspircd"); return std::string(remainder, 0, n); } std::string fullpath = std::string(buffer) + "/" + remainder; - ServerInstance->Log(DEBUG,"Using concatenation: %s", fullpath.c_str()); std::string::size_type n = fullpath.rfind("/inspircd"); return std::string(fullpath, 0, n); }