Compare commits

..

6 commits

Author SHA1 Message Date
7735c201d3 Remove wrongly checked in files
Some checks failed
continuous-integration/drone/push Build is failing
2025-03-25 14:10:22 +01:00
b795877967 Rearrange stuff 2025-03-25 14:08:57 +01:00
0e2f09c629 Refactor Spf 2025-03-25 14:08:57 +01:00
2580bd7d99 some tests and more preliminary stuff 2025-03-25 14:08:57 +01:00
aba96da4b1 preliminar status, still need to make it work 2025-03-25 14:08:57 +01:00
8179025bb7 Rewrite of generate_config in python
Some checks failed
continuous-integration/drone/push Build is failing
2025-03-25 14:07:04 +01:00
3 changed files with 1 additions and 459 deletions

View file

@ -55,7 +55,7 @@ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Configfile.cpp
${CMAKE_CURRENT_BINARY_DIR} | ${CMAKE_CURRENT_BINARY_DIR} |
python ${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_config.py python ${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_config.py
DEPENDS src/Configfile.cpp.in src/Configfile.h.in src/Configfile.tmpl DEPENDS src/Configfile.cpp.in src/Configfile.h.in src/Configfile.tmpl
docs/hermes-options.html.in scripts/generate_config.pl) docs/hermes-options.html.in scripts/generate_config.py)
# doxygen # doxygen

View file

@ -1,144 +0,0 @@
/**
* hermes antispam proxy
* Copyright (C) 2006, 2007 Juan José Gutiérrez de Quevedo <juanjo@gutierrezdequevedo.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* @author Juan José Gutiérrez de Quevedo <juanjo@gutierrezdequevedo.com>
*/
#ifndef CONFIGFILE_H
#define CONFIGFILE_H
#include "hermes.h"
#include <list>
#include <string>
#include <iostream>
#include <fstream>
#include "Utils.h"
using namespace std;
class Configfile
{
private:
static string parseAsString(string);
static bool parseAsBool(string);
static long parseAsInt(string);
static list<string> parseAsList(string);
int uid;
int gid;
bool background;
string chroot;
bool drop_privileges;
string user;
string group;
string pid_file;
int listening_port;
string bind_to;
string server_host;
int server_port;
string database_file;
bool greylist;
bool throttle;
int throttling_time;
int number_of_unimplemented_commands_allowed;
bool allow_data_before_banner;
list<string> dns_blacklist_domains;
int dns_blacklist_percentage;
list<string> dns_whitelist_domains;
int dns_whitelist_percentage;
bool add_status_header;
int banner_delay_time;
int initial_expiry;
int initial_blacklist;
int whitelist_expiry;
bool submit_stats;
bool submit_stats_ssl;
string submit_stats_username;
string submit_stats_password;
int log_level;
string file_logger_filename;
bool keep_file_locked;
int log_rotation_frequency;
string rotate_filename;
bool clean_db;
bool outgoing_ssl;
bool incoming_ssl;
string private_key_file;
string certificate_file;
string dhparams_file;
bool add_headers;
string hostname;
bool whitelisted_disables_everything;
bool reject_no_reverse_resolution;
bool check_helo_against_reverse;
bool query_spf;
bool return_temp_error_on_reject;
public:
Configfile();
void parse(string);
void validateConfig();
int getUid();
int getGid();
bool& getBackground();
string& getChroot();
bool& getDropPrivileges();
string& getUser();
string& getGroup();
string& getPidFile();
int& getListeningPort();
string& getBindTo();
string& getServerHost();
int& getServerPort();
string& getDatabaseFile();
bool& getGreylist();
bool& getThrottle();
int& getThrottlingTime();
int& getNumberOfUnimplementedCommandsAllowed();
bool& getAllowDataBeforeBanner();
list<string>& getDnsBlacklistDomains();
int& getDnsBlacklistPercentage();
list<string>& getDnsWhitelistDomains();
int& getDnsWhitelistPercentage();
bool& getAddStatusHeader();
int& getBannerDelayTime();
int& getInitialExpiry();
int& getInitialBlacklist();
int& getWhitelistExpiry();
bool& getSubmitStats();
bool& getSubmitStatsSsl();
string& getSubmitStatsUsername();
string& getSubmitStatsPassword();
int& getLogLevel();
string& getFileLoggerFilename();
bool& getKeepFileLocked();
int& getLogRotationFrequency();
string& getRotateFilename();
bool& getCleanDb();
bool& getOutgoingSsl();
bool& getIncomingSsl();
string& getPrivateKeyFile();
string& getCertificateFile();
string& getDhparamsFile();
bool& getAddHeaders();
string& getHostname();
bool& getWhitelistedDisablesEverything();
bool& getRejectNoReverseResolution();
bool& getCheckHeloAgainstReverse();
bool& getQuerySpf();
bool& getReturnTempErrorOnReject();
};
#endif //CONFIGFILE_H

View file

@ -1,314 +0,0 @@
/**
* hermes antispam proxy
* Copyright (C) 2006, 2007 Juan José Gutiérrez de Quevedo <juanjo@gutierrezdequevedo.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* @author Juan José Gutiérrez de Quevedo <juanjo@gutierrezdequevedo.com>
*/
#include "Configfile.h"
#include <unistd.h>
extern LOGGER_CLASS hermes_log;
/**
* default config
*
*/
Configfile::Configfile()
{
background=true;
chroot="";
drop_privileges=true;
user="nobody";
group="nobody";
pid_file="/var/run/hermes.pid";
listening_port=25;
bind_to="";
server_host="localhost";
server_port=2525;
database_file="/var/hermes/greylisting.db";
greylist=true;
throttle=true;
throttling_time=1;
number_of_unimplemented_commands_allowed=-1;
allow_data_before_banner=false;
dns_blacklist_domains=Configfile::parseAsList("");
dns_blacklist_percentage=100;
dns_whitelist_domains=Configfile::parseAsList("");
dns_whitelist_percentage=100;
add_status_header=false;
banner_delay_time=5;
initial_expiry=240;
initial_blacklist=5;
whitelist_expiry=36;
submit_stats=true;
submit_stats_ssl=true;
submit_stats_username="anonymous";
submit_stats_password="anonymous";
log_level=1;
file_logger_filename="hermes.log";
keep_file_locked=true;
log_rotation_frequency=1440;
rotate_filename="hermes-%%year%%-%%month%%-%%day%%-%%hour%%:%%minute%%.log";
clean_db=true;
outgoing_ssl=false;
incoming_ssl=false;
private_key_file="/etc/hermes/hermes.key";
certificate_file="/etc/hermes/hermes.cert";
dhparams_file="";
add_headers=true;
hostname="";
whitelisted_disables_everything=true;
reject_no_reverse_resolution=false;
check_helo_against_reverse=false;
query_spf=false;
return_temp_error_on_reject=false;
}
void Configfile::parse(string file)
{
ifstream f;
char line[255];
int equalpos;
LINF("parsing "+Utils::get_canonical_filename(file)+" configuration file");
f.open(file.c_str(),ios::in);
while(!f.eof())
{
f.getline(line,255);
string l=Utils::trim(line);
if('#'!=l[0]&&l!=""&&l.find("="))
{
equalpos=l.find("=");
string option=Utils::trim(l.substr(0,equalpos));
string value=Utils::trim(l.substr(equalpos+1));
//if(false==cfg.getBackground())
// cout << option << " -> " << value << endl;
//this is a bit of a hack, but simplifies a lot this function
#define PARSE_INT(x,y) if(x==option) y=Configfile::parseAsInt(value); else
#define PARSE_BOOL(x,y) if(x==option) y=Configfile::parseAsBool(value); else
#define PARSE_STRING(x,y) if(x==option) y=Configfile::parseAsString(value); else
#define PARSE_LIST(x,y) if(x==option) y=Configfile::parseAsList(value); else
PARSE_BOOL("background",background)
PARSE_STRING("chroot",chroot)
PARSE_BOOL("drop_privileges",drop_privileges)
PARSE_STRING("user",user)
PARSE_STRING("group",group)
PARSE_STRING("pid_file",pid_file)
PARSE_INT("listening_port",listening_port)
PARSE_STRING("bind_to",bind_to)
PARSE_STRING("server_host",server_host)
PARSE_INT("server_port",server_port)
PARSE_STRING("database_file",database_file)
PARSE_BOOL("greylist",greylist)
PARSE_BOOL("throttle",throttle)
PARSE_INT("throttling_time",throttling_time)
PARSE_INT("number_of_unimplemented_commands_allowed",number_of_unimplemented_commands_allowed)
PARSE_BOOL("allow_data_before_banner",allow_data_before_banner)
PARSE_LIST("dns_blacklist_domains",dns_blacklist_domains)
PARSE_INT("dns_blacklist_percentage",dns_blacklist_percentage)
PARSE_LIST("dns_whitelist_domains",dns_whitelist_domains)
PARSE_INT("dns_whitelist_percentage",dns_whitelist_percentage)
PARSE_BOOL("add_status_header",add_status_header)
PARSE_INT("banner_delay_time",banner_delay_time)
PARSE_INT("initial_expiry",initial_expiry)
PARSE_INT("initial_blacklist",initial_blacklist)
PARSE_INT("whitelist_expiry",whitelist_expiry)
PARSE_BOOL("submit_stats",submit_stats)
PARSE_BOOL("submit_stats_ssl",submit_stats_ssl)
PARSE_STRING("submit_stats_username",submit_stats_username)
PARSE_STRING("submit_stats_password",submit_stats_password)
PARSE_INT("log_level",log_level)
PARSE_STRING("file_logger_filename",file_logger_filename)
PARSE_BOOL("keep_file_locked",keep_file_locked)
PARSE_INT("log_rotation_frequency",log_rotation_frequency)
PARSE_STRING("rotate_filename",rotate_filename)
PARSE_BOOL("clean_db",clean_db)
PARSE_BOOL("outgoing_ssl",outgoing_ssl)
PARSE_BOOL("incoming_ssl",incoming_ssl)
PARSE_STRING("private_key_file",private_key_file)
PARSE_STRING("certificate_file",certificate_file)
PARSE_STRING("dhparams_file",dhparams_file)
PARSE_BOOL("add_headers",add_headers)
PARSE_STRING("hostname",hostname)
PARSE_BOOL("whitelisted_disables_everything",whitelisted_disables_everything)
PARSE_BOOL("reject_no_reverse_resolution",reject_no_reverse_resolution)
PARSE_BOOL("check_helo_against_reverse",check_helo_against_reverse)
PARSE_BOOL("query_spf",query_spf)
PARSE_BOOL("return_temp_error_on_reject",return_temp_error_on_reject)
{
throw Exception("Option \""+option+"\" with value \""+value+"\" is not recognized",__FILE__,__LINE__);
}
#undef PARSE_INT
#undef PARSE_BOOL
#undef PARSE_STRING
#undef PARSE_LIST
}
}
#ifndef WIN32
uid=Utils::usertouid(user);
gid=Utils::grouptogid(group);
#endif //WIN32
f.close();
}
//again, this is a BIG HACK, but it simplifies code a lot
#define GET_VAR(x,y,z) z Configfile::x(){ return y;}
GET_VAR(getUid,uid,int)
GET_VAR(getGid,gid,int)
GET_VAR(getBackground,background,bool&)
GET_VAR(getChroot,chroot,string&)
GET_VAR(getDropPrivileges,drop_privileges,bool&)
GET_VAR(getUser,user,string&)
GET_VAR(getGroup,group,string&)
GET_VAR(getPidFile,pid_file,string&)
GET_VAR(getListeningPort,listening_port,int&)
GET_VAR(getBindTo,bind_to,string&)
GET_VAR(getServerHost,server_host,string&)
GET_VAR(getServerPort,server_port,int&)
GET_VAR(getDatabaseFile,database_file,string&)
GET_VAR(getGreylist,greylist,bool&)
GET_VAR(getThrottle,throttle,bool&)
GET_VAR(getThrottlingTime,throttling_time,int&)
GET_VAR(getNumberOfUnimplementedCommandsAllowed,number_of_unimplemented_commands_allowed,int&)
GET_VAR(getAllowDataBeforeBanner,allow_data_before_banner,bool&)
GET_VAR(getDnsBlacklistDomains,dns_blacklist_domains,list<string>&)
GET_VAR(getDnsBlacklistPercentage,dns_blacklist_percentage,int&)
GET_VAR(getDnsWhitelistDomains,dns_whitelist_domains,list<string>&)
GET_VAR(getDnsWhitelistPercentage,dns_whitelist_percentage,int&)
GET_VAR(getAddStatusHeader,add_status_header,bool&)
GET_VAR(getBannerDelayTime,banner_delay_time,int&)
GET_VAR(getInitialExpiry,initial_expiry,int&)
GET_VAR(getInitialBlacklist,initial_blacklist,int&)
GET_VAR(getWhitelistExpiry,whitelist_expiry,int&)
GET_VAR(getSubmitStats,submit_stats,bool&)
GET_VAR(getSubmitStatsSsl,submit_stats_ssl,bool&)
GET_VAR(getSubmitStatsUsername,submit_stats_username,string&)
GET_VAR(getSubmitStatsPassword,submit_stats_password,string&)
GET_VAR(getLogLevel,log_level,int&)
GET_VAR(getFileLoggerFilename,file_logger_filename,string&)
GET_VAR(getKeepFileLocked,keep_file_locked,bool&)
GET_VAR(getLogRotationFrequency,log_rotation_frequency,int&)
GET_VAR(getRotateFilename,rotate_filename,string&)
GET_VAR(getCleanDb,clean_db,bool&)
GET_VAR(getOutgoingSsl,outgoing_ssl,bool&)
GET_VAR(getIncomingSsl,incoming_ssl,bool&)
GET_VAR(getPrivateKeyFile,private_key_file,string&)
GET_VAR(getCertificateFile,certificate_file,string&)
GET_VAR(getDhparamsFile,dhparams_file,string&)
GET_VAR(getAddHeaders,add_headers,bool&)
GET_VAR(getHostname,hostname,string&)
GET_VAR(getWhitelistedDisablesEverything,whitelisted_disables_everything,bool&)
GET_VAR(getRejectNoReverseResolution,reject_no_reverse_resolution,bool&)
GET_VAR(getCheckHeloAgainstReverse,check_helo_against_reverse,bool&)
GET_VAR(getQuerySpf,query_spf,bool&)
GET_VAR(getReturnTempErrorOnReject,return_temp_error_on_reject,bool&)
#undef GET_VAR
void Configfile::validateConfig()
{
#ifndef WIN32
//check if we are root if we want to bind to a port lower than 1024
if(getuid()!=0&&listening_port<1024)
throw Exception(_("You can't bind to a port lower than 1024 without being root"),__FILE__,__LINE__);
#endif //WIN32
#ifdef HAVE_SSL
//check if ssl is usable
if(!Utils::file_exists(certificate_file))
throw Exception("Certificate file "+certificate_file+" doesn't exist.\nTo generate a certificate look in hermesrc.example, there is an example there.",__FILE__,__LINE__);
if(!Utils::file_exists(private_key_file))
throw Exception("Private key file "+private_key_file+" doesn't exist.\nTo generate a private key look in hermesrc.example, there is an example there.",__FILE__,__LINE__);
#endif //HAVE_SSL
#ifndef WIN32
//check if chroot dir exist //TODO: check that files needed in chroot exist
//for now only /etc/resolv.conf, but we're working on it :-D
if(""!=chroot&&!Utils::dir_exists(chroot))
throw Exception("Directory "+chroot+" doesn't exist, can't chroot to it.",__FILE__,__LINE__);
#endif //WIN32
//check if we have submit_stats on but no user and password
if(getSubmitStats()&&(""==getSubmitStatsUsername()||""==getSubmitStatsPassword()))
throw Exception("You have configured hermes to send stats, but have not configured a username or password.\n"
"If you don't have one, go to http://www.hermes-project.com and register there",__FILE__,__LINE__);
#ifndef HAVE_SSL
//check if we have activated submit_stats_ssl not having ssl activated
if(getSubmitStatsSsl())
throw Exception("You have configured stats submission through SSL, but hermes was compiled without SSL support",__FILE__,__LINE__);
#endif //HAVE_SSL
}
string Configfile::parseAsString(string str)
{
//remove "" round the string
if('"'==str[0])
str=str.substr(1);
if('"'==str[str.length()-1])
str=str.substr(0,str.length()-1);
return str;
}
bool Configfile::parseAsBool(string str)
{
if("yes"==str||"on"==str||"1"==str||"true"==str)
return true;
else
return false;
}
long int Configfile::parseAsInt(string str)
{
long int value;
errno=0; //to know why we do this, read NOTES on strtol(3)
value=strtol(str.c_str(),NULL,10);
if(errno)
throw Exception("Error parsing as int ("+Utils::errnotostrerror(errno)+")",__FILE__,__LINE__);
return value;
}
list<string> Configfile::parseAsList(string str)
{
list<string> tmpList;
string::size_type startpos=0,endpos=0,len;
string tmpstr;
str=Configfile::parseAsString(str); //remove quotes around string
len=str.length();
while(startpos<len&&string::npos!=endpos)
{
endpos=str.find(',',startpos);
if(string::npos==endpos)
tmpstr=str.substr(startpos);
else
tmpstr=str.substr(startpos,endpos-startpos);
tmpList.push_back(Utils::trim(tmpstr));
startpos=endpos+1;
}
return tmpList;
}