bool DNSResolver::GetEmailServers(const String &sDomainName, std::vector<HostNameAndIpAddress> &saFoundNames ) { String message = Formatter::Format("DNS MX lookup: {0}", sDomainName); LOG_TCPIP(message); std::vector<String> vecFoundMXRecords; if (!Resolve_(sDomainName, vecFoundMXRecords, DNS_TYPE_MX, 0)) { String logMessage; logMessage.Format(_T("Failed to resolve email servers (MX lookup). Domain name: %s."), sDomainName.c_str()); LOG_DEBUG(logMessage); return false; } if (vecFoundMXRecords.empty()) { /* RFC 2821: If no MX records are found, but an A RR is found, the A RR is treated as if it was associated with an implicit MX RR, with a preference of 0, pointing to that host. If one or more MX RRs are found for a given name, SMTP systems MUST NOT utilize any A RRs associated with that name unless they are located using the MX RRs; (implemented here) */ std::vector<String> a_records; if (!GetIpAddresses(sDomainName, a_records)) { String logMessage; logMessage.Format(_T("Failed to resolve email servers (A lookup). Domain name: %s."), sDomainName.c_str()); LOG_DEBUG(logMessage); return false; } for(String record : a_records) { HostNameAndIpAddress hostAndAddress; hostAndAddress.SetHostName(sDomainName); hostAndAddress.SetIpAddress(record); saFoundNames.push_back(hostAndAddress); } } else { // We've been able to find host names in the MX records. We should // now translate them to IP addresses. Some host names may result // in several IP addreses. auto iterDomain = vecFoundMXRecords.begin(); bool dnsSuccess = false; for(String domain : vecFoundMXRecords) { // Resolve to domain name to IP address and put it in the list. size_t iCountBefore = saFoundNames.size(); std::vector<String> a_records; if (!GetIpAddresses(domain, a_records)) continue; dnsSuccess = true; if (saFoundNames.size() == iCountBefore) { // No mx records were found for this host name. Check if the host // name is actually an IP address? It shouldn't be but.... if (StringParser::IsValidIPAddress(domain)) { // Okay, this is an invalid MX record. The MX record should always contain // a host name but in this case it appears an IP address. We'll be kind to // the domain owner and still deliver the email to him. a_records.push_back(domain); } } for(String record : a_records) { HostNameAndIpAddress hostAndAddress; hostAndAddress.SetHostName(domain); hostAndAddress.SetIpAddress(record); saFoundNames.push_back(hostAndAddress); } } if (!dnsSuccess) { // All dns queries failed. String logMessage; logMessage.Format(_T("Failed to resolve email servers (A lookup). Domain name: %s."), sDomainName.c_str()); LOG_DEBUG(logMessage); return false; } } String sLogMsg; sLogMsg.Format(_T("DNS - MX Result: %d IP addresses were found."), saFoundNames.size()); LOG_TCPIP(sLogMsg); // Remove duplicate names. auto iter = saFoundNames.begin(); std::set<String> duplicateCheck; while (iter != saFoundNames.end()) { String name = (*iter).GetIpAddress(); if (duplicateCheck.find(name) != duplicateCheck.end()) { // We found a duplicate. Remove it. iter = saFoundNames.erase(iter); } else { // This is not a duplicate. Move to next. iter++; duplicateCheck.insert(name); } } return true; }
ExecConfig *ExecConfigNew(bool scheduled_run, const EvalContext *ctx, const Policy *policy) { ExecConfig *exec_config = xcalloc(1, sizeof(ExecConfig)); exec_config->scheduled_run = scheduled_run; exec_config->exec_command = xstrdup(""); exec_config->agent_expireafter = 2 * 60; /* two hours */ exec_config->mail_server = xstrdup(""); exec_config->mail_from_address = xstrdup(""); exec_config->mail_to_address = xstrdup(""); exec_config->mail_subject = xstrdup(""); exec_config->mail_max_lines = 30; exec_config->mailfilter_include = SeqNew(0, &free); exec_config->mailfilter_include_regex = SeqNew(0, &RegexFree); exec_config->mailfilter_exclude = SeqNew(0, &free); exec_config->mailfilter_exclude_regex = SeqNew(0, &RegexFree); exec_config->fq_name = xstrdup(VFQNAME); exec_config->ip_address = xstrdup(VIPADDRESS); exec_config->ip_addresses = GetIpAddresses(ctx); Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_EXECUTOR); if (constraints) { for (size_t i = 0; i < SeqLength(constraints); i++) { Constraint *cp = SeqAt(constraints, i); if (!IsDefinedClass(ctx, cp->classes)) { continue; } VarRef *ref = VarRefParseFromScope(cp->lval, "control_executor"); DataType t; const void *value = EvalContextVariableGet(ctx, ref, &t); VarRefDestroy(ref); if (t == CF_DATA_TYPE_NONE) { ProgrammingError("Unknown attribute '%s' in control body," " should have already been stopped by the parser", cp->lval); } if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_MAILFROM].lval) == 0) { free(exec_config->mail_from_address); exec_config->mail_from_address = xstrdup(value); Log(LOG_LEVEL_DEBUG, "mailfrom '%s'", exec_config->mail_from_address); } else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_MAILTO].lval) == 0) { free(exec_config->mail_to_address); exec_config->mail_to_address = xstrdup(value); Log(LOG_LEVEL_DEBUG, "mailto '%s'", exec_config->mail_to_address); } else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_MAILSUBJECT].lval) == 0) { free(exec_config->mail_subject); exec_config->mail_subject = xstrdup(value); Log(LOG_LEVEL_DEBUG, "mailsubject '%s'", exec_config->mail_subject); } else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_SMTPSERVER].lval) == 0) { free(exec_config->mail_server); exec_config->mail_server = xstrdup(value); Log(LOG_LEVEL_DEBUG, "smtpserver '%s'", exec_config->mail_server); } else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_EXECCOMMAND].lval) == 0) { free(exec_config->exec_command); exec_config->exec_command = xstrdup(value); Log(LOG_LEVEL_DEBUG, "exec_command '%s'", exec_config->exec_command); } else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_AGENT_EXPIREAFTER].lval) == 0) { exec_config->agent_expireafter = IntFromString(value); Log(LOG_LEVEL_DEBUG, "agent_expireafter %d", exec_config->agent_expireafter); } else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_MAILMAXLINES].lval) == 0) { exec_config->mail_max_lines = IntFromString(value); Log(LOG_LEVEL_DEBUG, "maxlines %d", exec_config->mail_max_lines); } else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_MAILFILTER_INCLUDE].lval) == 0) { SeqDestroy(exec_config->mailfilter_include); SeqDestroy(exec_config->mailfilter_include_regex); RlistMailFilterFill(value, &exec_config->mailfilter_include, &exec_config->mailfilter_include_regex, "include"); } else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_MAILFILTER_EXCLUDE].lval) == 0) { SeqDestroy(exec_config->mailfilter_exclude); SeqDestroy(exec_config->mailfilter_exclude_regex); RlistMailFilterFill(value, &exec_config->mailfilter_exclude, &exec_config->mailfilter_exclude_regex, "exclude"); } } } return exec_config; }
ExecConfig *ExecConfigNew(bool scheduled_run, const EvalContext *ctx, const Policy *policy) { ExecConfig *exec_config = xcalloc(1, sizeof(ExecConfig)); exec_config->scheduled_run = scheduled_run; exec_config->exec_command = xstrdup(""); exec_config->agent_expireafter = 2 * 60; /* two hours */ exec_config->mail_server = xstrdup(""); exec_config->mail_from_address = xstrdup(""); exec_config->mail_to_address = xstrdup(""); exec_config->mail_subject = xstrdup(""); exec_config->mail_max_lines = 30; exec_config->fq_name = xstrdup(VFQNAME); exec_config->ip_address = xstrdup(VIPADDRESS); exec_config->ip_addresses = GetIpAddresses(ctx); Seq *constraints = ControlBodyConstraints(policy, AGENT_TYPE_EXECUTOR); if (constraints) { for (size_t i = 0; i < SeqLength(constraints); i++) { Constraint *cp = SeqAt(constraints, i); if (!IsDefinedClass(ctx, cp->classes)) { continue; } VarRef *ref = VarRefParseFromScope(cp->lval, "control_executor"); const void *value = EvalContextVariableGet(ctx, ref, NULL); if (!value) { /* Has already been checked by the parser. */ ProgrammingError( "Unknown attribute in body executor control: %s", cp->lval); VarRefDestroy(ref); continue; } VarRefDestroy(ref); if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_MAILFROM].lval) == 0) { free(exec_config->mail_from_address); exec_config->mail_from_address = xstrdup(value); Log(LOG_LEVEL_DEBUG, "mailfrom '%s'", exec_config->mail_from_address); } else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_MAILTO].lval) == 0) { free(exec_config->mail_to_address); exec_config->mail_to_address = xstrdup(value); Log(LOG_LEVEL_DEBUG, "mailto '%s'", exec_config->mail_to_address); } else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_MAILSUBJECT].lval) == 0) { free(exec_config->mail_subject); exec_config->mail_subject = xstrdup(value); Log(LOG_LEVEL_DEBUG, "mailsubject '%s'", exec_config->mail_subject); } else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_SMTPSERVER].lval) == 0) { free(exec_config->mail_server); exec_config->mail_server = xstrdup(value); Log(LOG_LEVEL_DEBUG, "smtpserver '%s'", exec_config->mail_server); } else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_EXECCOMMAND].lval) == 0) { free(exec_config->exec_command); exec_config->exec_command = xstrdup(value); Log(LOG_LEVEL_DEBUG, "exec_command '%s'", exec_config->exec_command); } else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_AGENT_EXPIREAFTER].lval) == 0) { exec_config->agent_expireafter = IntFromString(value); Log(LOG_LEVEL_DEBUG, "agent_expireafter %d", exec_config->agent_expireafter); } else if (strcmp(cp->lval, CFEX_CONTROLBODY[EXEC_CONTROL_MAILMAXLINES].lval) == 0) { exec_config->mail_max_lines = IntFromString(value); Log(LOG_LEVEL_DEBUG, "maxlines %d", exec_config->mail_max_lines); } } } return exec_config; }