Compare commits

...

25 commits

Author SHA1 Message Date
Juan José Gutiérrez de Quevedo Pérez 6b610aaa84 Simplify docker setup
All checks were successful
continuous-integration/drone Build is passing
2023-10-17 14:37:28 +02:00
Juanjo Gutiérrez 3b7a769021 Build for new platform (arm) and notifications 2023-10-12 12:03:24 +02:00
Juanjo Gutiérrez 56db33478e
Use the new drone CI build server 2022-01-31 12:44:39 +01:00
Juanjo Gutiérrez bf915141fd
Add maybe missing syntax 2022-01-31 09:09:42 +01:00
Juan José Gutiérrez de Quevedo Pérez ccee3ef1c5 Add a build file for drone CI 2022-01-30 18:49:48 +01:00
Juan José Gutiérrez de Quevedo Pérez cbb4a1bdcd
Merge pull request #7 from jjguti/feature/add-jenkinsfile
Add a Jenkinsfile
2021-06-30 14:39:56 +02:00
Juanjo Gutiérrez 34360bcafc Add a Jenkinsfile 2021-06-30 13:52:35 +02:00
Juan José Gutiérrez de Quevedo Pérez 400777aaee Implement cmake build system 2021-05-19 22:37:38 +02:00
Juan José Gutiérrez de Quevedo Pérez 9b2b7ccf0a fix formatting 2019-10-20 23:03:14 +02:00
Juan José Gutiérrez de Quevedo Pérez 4ff2575870 rename readme and add travis status 2019-10-20 23:02:20 +02:00
Juan José Gutiérrez de Quevedo Pérez b627f7dcd0 add travis integration to hermes
fix also some problems with openssl building
2019-10-20 22:58:08 +02:00
Juan José Gutiérrez de Quevedo Pérez ad0a63e275 fix build issues on newer compilers 2019-10-20 22:01:30 +02:00
root 8652af728d FIX: building without gnu's strerror_r 2015-11-12 10:33:03 +01:00
Juan José Gutiérrez de Quevedo Pérez 45c9272fce ADD: support for Perfect Forward Security (patch by Michael Brunnbauer) 2014-10-09 15:24:48 +02:00
Juan José Gutiérrez de Quevedo Pérez 5627834132 FIX: building without SSL 2014-09-09 21:52:03 +02:00
Juan José Gutiérrez de Quevedo Pérez 98f429601a UPD: changelog 2014-09-09 06:56:29 +02:00
Juan José Gutiérrez de Quevedo Pérez 8460d525ae CHG: update release number 2014-09-09 06:52:56 +02:00
Juan José Gutiérrez de Quevedo Pérez 45c1fdbf33 FIX: load a full certificate chain and not just the first one 2014-09-08 10:07:48 +02:00
Juan José Gutiérrez de Quevedo Pérez 7728f8dae0 FIX: don't redirect signals on win32 2014-09-05 13:45:44 +02:00
Juan José Gutiérrez de Quevedo Pérez 62b6a5c5e0 FIX: throw an Exception if we don't specify a config file 2014-09-05 11:57:22 +02:00
Juan José Gutiérrez de Quevedo Pérez f01b634ae3 FIX: warning in usage of syslog(3) 2014-06-29 21:35:03 +02:00
Juan José Gutiérrez de Quevedo Pérez 53bd14e419 FIX: check return values of some important functions 2014-06-29 21:32:56 +02:00
Juan José Gutiérrez de Quevedo Pérez a96826a208 FIX: add braces to remove warnings 2014-06-29 21:24:59 +02:00
Juan José Gutiérrez de Quevedo Pérez 02bf18dbcd FIX: formatting 2014-06-29 12:30:12 +02:00
Juan José Gutiérrez de Quevedo Pérez 18dc796a8a ADD: README, taken from website 2014-06-29 12:29:07 +02:00
25 changed files with 2294 additions and 928 deletions

2
.dockerignore Normal file
View file

@ -0,0 +1,2 @@
build_dir/
build/

76
.drone.yml Normal file
View file

@ -0,0 +1,76 @@
---
kind: pipeline
type: docker
name: amd64
platform:
os: linux
arch: amd64
steps:
- name: prepare workspace
image: alpine
commands:
- rm -fr build_dir
- name: build hermes
image: alpine
commands:
- apk add -t hermes-build-deps --no-cache perl graphviz doxygen gcc make openssl-dev libspf2-dev cmake g++ sqlite-dev gettext-dev
- cmake -B build_dir
- cmake --build build_dir
- name: docker image build
image: plugins/docker
settings:
tags:
- latest
repo: docker.gutierrezdequevedo.com/ps/hermes
---
kind: pipeline
type: docker
name: arm64
platform:
os: linux
arch: arm64
steps:
- name: prepare workspace
image: alpine
commands:
- rm -fr build_dir
- name: build hermes
image: alpine
commands:
- apk add -t hermes-build-deps --no-cache perl graphviz doxygen gcc make openssl-dev libspf2-dev cmake g++ sqlite-dev gettext-dev
- cmake -B build_dir
- cmake --build build_dir
- name: docker image build
image: plugins/docker
settings:
tags:
- latest-arm64
repo: docker.gutierrezdequevedo.com/ps/hermes
---
kind: pipeline
type: docker
name: notification
depends_on:
- amd64
- arm64
steps:
- name: notify matrix
image: spotlightkid/drone-matrixchat-notify
settings:
homeserver: 'https://grava.work'
roomid: '!wMVeFx6jwwF0TWA18h:grava.work'
userid: '@juanjo:grava.work'
deviceid: 'drone CI'
accesstoken: G66FRa3fG7qNfM4KKoW5wx6TWophvvtF
markdown: 'yes'
template: |
`${DRONE_REPO}` build #${DRONE_BUILD_NUMBER} status: **${DRONE_BUILD_STATUS}**
[${DRONE_BUILD_LINK}]

86
CMakeLists.txt Normal file
View file

@ -0,0 +1,86 @@
cmake_minimum_required(VERSION 3.12)
project (hermes)
set(LOGGER_CLASS UnixLogger CACHE STRING "One of UnixLogger, FileLogger or NullLogger")
add_executable (hermes
${CMAKE_CURRENT_BINARY_DIR}/Configfile.cpp
src/Exception.cpp
src/hermes.cpp
src/ServerSocket.cpp
src/Utils.cpp
src/Database.cpp
src/Proxy.cpp
src/Socket.cpp)
if(WIN32)
set(SOURCES ${SOURCES}
src/FileLogger.cpp
src/win32-service.cpp)
target_compile_definitions(hermes PRIVATE WIN32)
endif()
target_compile_definitions(hermes PRIVATE LOGGER_CLASS=${LOGGER_CLASS})
target_sources(hermes PRIVATE src/${LOGGER_CLASS}.cpp)
# required dependency sqlite3
find_library (SQLITE3_LIBRARY NAMES libsqlite3 sqlite3)
# optional dependency libspf2
find_library (SPF2_LIBRARY NAMES spf2 libspf2)
if(SPF2_LIB)
target_compile_definitions(hermes PRIVATE HAVE_SPF2)
target_sources(hermes PRIVATE src/Spf.cpp)
set(OPT_DEFS ${OPT_DEFS} -DHAVE_SPF2)
endif()
# optional dependency openssl
find_package (OpenSSL)
if(OPENSSL_FOUND)
target_compile_definitions(hermes PRIVATE HAVE_SSL)
set(OPT_DEFS ${OPT_DEFS} -DHAVE_SSL)
endif()
include_directories(
${CMAKE_CURRENT_BINARY_DIR}
src)
# generation of various files
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/Configfile.cpp
COMMAND cpp ${OPT_DEFS} ${CMAKE_CURRENT_SOURCE_DIR}/src/Configfile.tmpl -I
${CMAKE_CURRENT_BINARY_DIR} |
${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_config.pl
DEPENDS src/Configfile.cpp.in src/Configfile.h.in src/Configfile.tmpl
docs/hermes-options.html.in scripts/generate_config.pl)
# doxygen
find_package (Doxygen REQUIRED dot)
if(DOXYGEN_FOUND)
add_custom_target(doc ALL
doxygen
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/docs)
install(
DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/docs/html
TYPE DOC)
endif()
target_link_libraries(hermes
${SQLITE3_LIBRARY}
${OPENSSL_LIBRARIES}
${SPF2_LIBRARY}
pthread)
install(TARGETS hermes
RUNTIME DESTINATION bin)
install(FILES dists/hermesrc.example
TYPE SYSCONF)
install(FILES
dists/hermesrc.example
docs/gpl.txt
docs/installing-hermes.txt
docs/hermes-options.html
TYPE DOC)

View file

@ -1,6 +1,12 @@
ChangeLog
---------
2014-10-09 06:54 Juan José Gutiérrez de Quevedo <juanjo@gutierrezdequevedo.com>
* fix a bug with certificate handling, load a full chain from a file if a
availabe
* fix building on win32
2014-06-28 18:46 Juan José Gutiérrez de Quevedo <juanjo@gutierrezdequevedo.com>
* add more information to the headers injected by hermes

14
Dockerfile Normal file
View file

@ -0,0 +1,14 @@
FROM alpine:3.18
ADD . /hermes
WORKDIR /hermes
RUN apk add --no-cache perl graphviz doxygen gcc make openssl-dev libspf2-dev cmake g++ sqlite-dev gettext-dev
RUN cmake -B build
RUN cmake --build build
RUN mkdir /hermes-installation
RUN cmake --install build --prefix /hermes-installation
FROM alpine:3.18
EXPOSE 25
COPY --from=0 /hermes-installation /hermes
RUN apk add --no-cache openssl libspf2 sqlite-libs libstdc++ libgcc
CMD ["/hermes/bin/hermes", "/config/hermesrc"]

View file

@ -1,3 +0,0 @@
EXTRA_DIST = scripts/generate_config.pl ChangeLog TODO
SUBDIRS = src docs dists

30
README.md Normal file
View file

@ -0,0 +1,30 @@
[![Build Status](https://ci.gutierrezdequevedo.com/api/badges/ps/hermes/status.svg)](https://ci.gutierrezdequevedo.com/ps/hermes)
hermes is a GPL anti-spam solution that will help you get rid of (most) UCE.
It's key features are:
* Multiplatform:
hermes runs on Linux, Solaris and even on Windows.
* Transparent:
Although clients will connect to hermes, hermes won't display any message of
its own or alter in any way the communications with your real mail server,
except at the moment of greylisting.
* Efficient:
We have gone to great lengths to make hermes as efficient as possible, both
for your computer and for the SMTP server that it proxies.
* Configurable:
hermes is highly configurable, from greylisting time to logging method and
everything in between.
* Extension friendly:
We support most SMTP extensions such as SMTP-AUTH and STARTTLS.
* Compatible:
You can use hermes in combination with other techniques such as nolisting or
Bayesian Filtering either on the client side or on the server side (or both
if you prefer). You can also use fakehermes to fake a secondary smtp server
and further reduce your spam.

View file

@ -1,3 +0,0 @@
#!/bin/bash
aclocal && autoconf && autoheader && automake --add-missing

View file

@ -1,134 +0,0 @@
dnl Process this file with autoconf to produce a configure script.
AC_PREREQ(2.57)
AC_INIT([hermes], [1.8], [juanjo@gutierrezdequevedo.com])
dnl AC_CONFIG_AUX_DIR=([./config])
AM_CONFIG_HEADER([config.h])
AM_INIT_AUTOMAKE([1.7.8 foreign])
AC_PROG_CXX
AC_PROG_INSTALL
dnl
dnl check libraries and functions
dnl
AC_CHECK_FUNCS(getaddrinfo gai_strerror)
PKG_CHECK_MODULES(SQLite3, sqlite3, [], AC_MSG_ERROR("sqlite3 is required"))
PKG_CHECK_MODULES(OpenSSL, openssl, have_ssl=yes, have_ssl=no)
AC_CHECK_LIB(spf2,SPF_server_new, have_spf=yes, have_spf=no)
dnl
dnl end of libraries and functions
dnl
dnl
dnl check parameters
dnl
AC_ARG_WITH(logger-module,
[ --with-logger-module=module Module to log errors with. module is one of unix, file or null. default=unix],
[loggermodule=$withval],
[loggermodule=unix]
)
if test "$loggermodule" = unix; then
AC_DEFINE(LOGGER_CLASS,UnixLogger)
fi
if test "$loggermodule" = file; then
AC_DEFINE(LOGGER_CLASS,FileLogger)
fi
if test "$loggermodule" = null; then
AC_DEFINE(LOGGER_CLASS,NullLogger,[Define what logger we are using])
fi
AC_ARG_ENABLE(openssl,
[ --enable-openssl Enable OpenSSL support ],
[
if test x$enableval = xyes; then
if test x$have_ssl = xno; then
AC_MSG_ERROR("OpenSSL support requested but not detected")
fi
have_ssl=yes
else
have_ssl=no
fi
]
)
AC_ARG_ENABLE(spf,
[ --enable-spf Enable SPF support ],
[
if test x$enableval = xyes; then
if test x$have_spf = xno; then
AC_MSG_ERROR("SPF support requested but not detected")
fi
have_spf=yes
else
have_spf=no
fi
]
)
win32_service=no
AC_ARG_ENABLE(win32-service,
[ --enable-win32-service Enable win32 service support ],
[
if test x$enableval = xyes; then
win32_service=yes
fi
]
)
dnl
dnl end of parameters check
dnl
dnl
dnl config.h variables
dnl
if test x$have_ssl = xyes; then
AC_DEFINE(HAVE_SSL,1,[Defined if using openssl for SSL support])
fi
if test x$have_spf = xyes; then
AC_DEFINE(HAVE_SPF,1,[Defined if system has libspf2])
fi
if test x$win32_service = xyes; then
AC_DEFINE(WIN32_SERVICE,1,[Defined if we want to compile win32 service support])
fi
dnl
dnl end of config.h variables
dnl
dnl
dnl conditionals for makefiles
dnl
AM_CONDITIONAL(HAVE_SPF, test "$have_spf" = yes)
AM_CONDITIONAL(LOGGER_UNIX, test "$loggermodule" = unix)
AM_CONDITIONAL(LOGGER_NULL, test "$loggermodule" = null)
AM_CONDITIONAL(LOGGER_FILE, test "$loggermodule" = file)
AM_CONDITIONAL(WIN32_SERVICE, test "$win32_service" = yes)
dnl
dnl end of conditionals for makefiles
dnl
AC_CONFIG_FILES([Makefile src/Makefile docs/Makefile dists/Makefile dists/hermes.spec])
AC_OUTPUT
echo
echo
echo "Configuration for $PACKAGE_STRING"
echo
echo " SSL: $have_ssl"
echo " SPF: $have_spf"
echo " Logger: $loggermodule"
echo " Win32: $win32_service"
echo

View file

@ -1,2 +0,0 @@
doc_DATA = hermesrc.example
EXTRA_DIST = fc_init hermes.spec hermes.spec.in

File diff suppressed because it is too large Load diff

View file

@ -1,6 +0,0 @@
EXTRA_DIST = Doxyfile gpl.txt installing-hermes.txt hermes-options.html hermes-options.html.in
doc_DATA = gpl.txt installing-hermes.txt hermes-options.html hermes-options.html.in
docs:
doxygen

View file

@ -74,7 +74,7 @@ chomp $hvar1;
chomp $hvar2;
chomp $conf_example;
open CPPIN, "<Configfile.cpp.in";
open CPPIN, "<../src/Configfile.cpp.in";
$cppstr=join("",<CPPIN>);
close CPPIN;
open CPPOUT, ">Configfile.cpp";
@ -84,7 +84,7 @@ $cppstr =~ s/%templ_getmethods%/$cppvar3/;
print CPPOUT $cppstr;
close CPPOUT;
open HIN, "<Configfile.h.in";
open HIN, "<../src/Configfile.h.in";
$hstr=join("",<HIN>);
close HIN;
open HOUT, ">Configfile.h";

View file

@ -1,4 +1,3 @@
#include "../config.h"
* comments MUST begin with a #.
*
@ -230,6 +229,12 @@ string,private_key_file,"/etc/hermes/hermes.key"
* # openssl req -new -x509 -nodes -sha1 -days 365 -key private.key > certificate.crt
* and answer the questions
string,certificate_file,"/etc/hermes/hermes.cert"
* optional file with Diffie-Hellman parameters for Perfect Forward Secrecy.
* to generate, execute:
* # openssl dhparam -out dhparam.pem <numbits>
* (replace <numbits> with the number of bits suitable for you, e.G. 1024)
string,dhparams_file,""
#endif //HAVE_SSL
* whether to add headers to the email sent or no.

View file

@ -392,7 +392,7 @@ unsigned long Database::getIntValue(string& p_sql)
if(NULL==result)
throw SQLException("SQL: "+p_sql+" didn't return any data, SQL query may be wrong",__FILE__,__LINE__);
if('\0'==result[ncolumn])
if('\0'==result[ncolumn][0])
value=0; //why sqlite doesn't return 0 when there are no rows?
else
value=strtoul(result[ncolumn],NULL,10);

View file

@ -19,6 +19,8 @@
*/
#include "FileLogger.h"
#include <cstring>
extern Configfile cfg;
extern __thread unsigned long connection_id;

View file

@ -20,7 +20,6 @@
#ifndef FILELOGGER_H
#define FILELOGGER_H
#include "config.h"
#include <stdio.h>
#include <pthread.h>
#include <string>

View file

@ -1,33 +0,0 @@
INCLUDES = $(OpenSSL_CFLAGS) $(SQLite3_CFLAGS)
LIBS = $(OpenSSL_LIBS) $(SQLite3_LIBS)
CXXFLAGS += -Wall -ansi -pedantic -Wshadow -pthread
bin_PROGRAMS = hermes
nodist_hermes_SOURCES = Configfile.cpp
hermes_SOURCES = Proxy.cpp ServerSocket.cpp Socket.cpp Database.cpp Utils.cpp Exception.cpp hermes.cpp
noinst_HEADERS = Proxy.h ServerSocket.h Socket.h Database.h UnixLogger.cpp FileLogger.h NullLogger.h Logger.h Utils.h Exception.h hermes.h Spf.h
EXTRA_DIST = Configfile.cpp.in Configfile.h.in Configfile.tmpl UnixLogger.cpp UnixLogger.h FileLogger.cpp FileLogger.h
if LOGGER_UNIX
hermes_SOURCES += UnixLogger.cpp
endif
if LOGGER_FILE
hermes_SOURCES += FileLogger.cpp
endif
if HAVE_SPF
hermes_SOURCES += Spf.cpp
LIBS += -lspf2
endif
if WIN32_SERVICE
hermes_SOURCES += win32-service.cpp
endif
Configfile.h: Configfile.cpp.in Configfile.h.in Configfile.tmpl ../docs/hermes-options.html.in ../scripts/generate_config.pl ../config.h
cpp Configfile.tmpl|../scripts/generate_config.pl
Configfile.cpp: Configfile.h Configfile.cpp.in Configfile.h.in Configfile.tmpl ../docs/hermes-options.html.in ../scripts/generate_config.pl ../config.h
*.cpp: Configfile.h

View file

@ -261,8 +261,10 @@ void Proxy::run(string &peer_address)
outside.writeLine(strtemp);
strtemp="";
string ssltls="";
#ifdef HAVE_SSL
if (outside.is_ssl_enabled())
ssltls=" (SSL/TLS)";
#endif //HAVE_SSL
if(cfg.getAddHeaders())
{

View file

@ -20,7 +20,6 @@
#ifndef SERVERSOCKET_H
#define SERVERSOCKET_H
#include "config.h"
#include <sys/types.h>
#ifdef WIN32

View file

@ -19,6 +19,7 @@
*/
#include "Socket.h"
#include <unistd.h>
#include <cstring>
int Socket::created_sockets=0;
@ -59,8 +60,33 @@ Socket::Socket():fd(-1)
if(!ssl_ctx_server)
throw Exception(_("Error creating SSL context"),__FILE__,__LINE__);
/* load certificate */
if(SSL_CTX_use_certificate_file(ssl_ctx_server,cfg.getCertificateFile().c_str(),SSL_FILETYPE_PEM)==-1)
if(SSL_CTX_use_certificate_chain_file(ssl_ctx_server,cfg.getCertificateFile().c_str())==-1)
throw Exception(_("Error loading certificate"),__FILE__,__LINE__);
/* load DH params */
BIO *bio;
DH *dh;
if (cfg.getDhparamsFile().size())
{
if ((bio=BIO_new_file(cfg.getDhparamsFile().c_str(), "r")) != 0)
{
if ((dh=PEM_read_bio_DHparams(bio, NULL, NULL, NULL)) != 0)
{
SSL_CTX_set_tmp_dh(ssl_ctx_server, dh);
DH_free(dh);
}
else
{
throw Exception(_("Error loading DH params"),__FILE__,__LINE__);
}
BIO_free(bio);
}
else
{
throw Exception(_("Error opening DH params file"),__FILE__,__LINE__);
}
}
/* load private key */
if(SSL_CTX_use_PrivateKey_file(ssl_ctx_server,cfg.getPrivateKeyFile().c_str(),SSL_FILETYPE_PEM)==-1)
throw Exception(_("Error loading private key"),__FILE__,__LINE__);
@ -228,21 +254,33 @@ ssize_t Socket::readBytes(void *buf,ssize_t lon)
#ifdef HAVE_SSL
if(ssl_enabled)
{
retval=SSL_read(ssl,buf,lon);
}
else
#endif //HAVE_SSL
{
retval=recv(fd,(char *)buf,lon,MSG_NOSIGNAL);
}
if(!retval)
{
throw NetworkException(_("Peer closed connection"),__FILE__,__LINE__);
}
if(retval<0)
{
#ifdef HAVE_SSL
if(ssl_enabled)
{
throw NetworkException(_("SSL error number: ")+Utils::inttostr(SSL_get_error(ssl,retval)),__FILE__,__LINE__);
}
else
#endif //HAVE_SSL
{
throw NetworkException(_(Utils::errnotostrerror(errno)),__FILE__,__LINE__);
}
}
readed+=lon;
}
@ -272,6 +310,10 @@ string Socket::readLine()
{
char c=0;
stringstream s;
string ssl_debug_string="";
#ifdef HAVE_SSL
if (ssl_enabled) ssl_debug_string = "s";
#endif //HAVE_SSL
do
{
@ -282,7 +324,7 @@ string Socket::readLine()
}
while(c!=10&&!isClosed());
LDEB("r" + string(ssl_enabled?"s":"") + ">" + s.str());
LDEB(string("r") + ssl_debug_string + ">" + s.str());
return s.str();
}
@ -308,12 +350,18 @@ void Socket::writeBytes(void *bytes,ssize_t len)
throw NetworkException(_("Peer closed connection"),__FILE__,__LINE__);
if(retval<0)
{
#ifdef HAVE_SSL
if(ssl_enabled)
{
throw NetworkException(_("SSL error number: ")+Utils::inttostr(SSL_get_error(ssl,retval)),__FILE__,__LINE__);
}
else
#endif //HAVE_SSL
{
throw NetworkException(_(Utils::errnotostrerror(errno)),__FILE__,__LINE__);
}
}
written+=len;
}
}
@ -325,8 +373,12 @@ void Socket::writeByte(char c)
void Socket::writeLine(string s)
{
string ssl_debug_string="";
#ifdef HAVE_SSL
if (ssl_enabled) ssl_debug_string = "s";
#endif //HAVE_SSL
LDEB("w" + string(ssl_enabled?"s":"") + ">" + s);
LDEB(string("w") + ssl_debug_string + ">" + s);
s+="\r\n";
writeBytes((void *)s.c_str(),s.length());
@ -465,9 +517,13 @@ string Socket::resolveInverselyToString(string ip)
error=getnameinfo(&addr,sizeof(struct sockaddr),hostname,NI_MAXHOST,NULL,0,NI_NAMEREQD);
if(error)
{
if(error==EAI_NONAME) //if the problem is that we didn't get a hostname, return empty string
{
hostname[0]='\0';
}
else
{
#ifdef HAVE_GAI_STRERROR
throw Exception(gai_strerror(error)+Utils::inttostr(error),__FILE__,__LINE__);
#else
@ -477,6 +533,8 @@ string Socket::resolveInverselyToString(string ip)
throw Exception("Socket error number "+Utils::inttostr(error),__FILE__,__LINE__);
#endif //WIN32
#endif //HAVE_GAI_STRERROR
}
}
return string(hostname);
}

View file

@ -39,6 +39,7 @@ void UnixLogger::addMessage(string file,int line,int loglevel,string logmessage)
if(loglevel<=cfg.getLogLevel())
{
sloglevel = LOG_INFO;
switch(loglevel)
{
case HERMES_LOG_INFO: sloglevel=LOG_INFO;break;
@ -48,6 +49,6 @@ void UnixLogger::addMessage(string file,int line,int loglevel,string logmessage)
message=file+":"+Utils::inttostr(line)+" [" + Utils::inttostr(connection_id) + "] " + logmessage;
if(false==cfg.getBackground())
cout << message << endl;
syslog(sloglevel,message.c_str());
syslog(sloglevel, "%s", message.c_str());
}
}

View file

@ -20,6 +20,7 @@
#include "Utils.h"
#include <unistd.h>
#include <cstring>
extern Configfile cfg;
extern LOGGER_CLASS hermes_log;
@ -418,10 +419,16 @@ string Utils::errnotostrerror(int errnum)
{
char buf[2048]="";
char *strerr;
// if(strerror_r(errnum,strerr,1024)!=-1)
#ifndef WIN32
#ifdef __GLIBC__
strerr=strerror_r(errnum,buf,2048);
#else
int retval = strerror_r(errnum, buf, sizeof buf);
strerr = buf;
if(retval != 0)
strcpy(buf, "error fetching error description");
#endif
#else
strerr="Error ";
#endif //WIN32
return string(strerr)+" ("+inttostr(errnum)+")";
@ -611,7 +618,7 @@ string Utils::gethostname()
if('\0'==buf[0])
{
if(cfg.getHostname()!="")
strncpy(buf,cfg.getHostname().c_str(),HOST_NAME_MAX);
strncpy(buf,cfg.getHostname().c_str(),HOST_NAME_MAX - 1);
else
{
if(-1==::gethostname(buf,HOST_NAME_MAX))

View file

@ -17,6 +17,7 @@
*
* @author Juan José Gutiérrez de Quevedo <juanjo@gutierrezdequevedo.com>
*/
#include <iostream>
#include <list>
#include <stack>
@ -62,13 +63,13 @@ __thread unsigned long connection_id;
list<unsigned long> children;
#ifdef HAVE_SSL
#if defined(HAVE_SSL) && OPENSSL_VERSION_NUMBER < 0x10100000L
pthread_mutex_t ssl_locks[CRYPTO_NUM_LOCKS]={PTHREAD_MUTEX_INITIALIZER};
void ssl_locking_function(int mode,int n,const char *file,int line)
{
if(n>CRYPTO_NUM_LOCKS)
throw Exception(_("Error, "+Utils::inttostr(n)+" is bigger than CRYPTO_NUM_LOCKS("+Utils::inttostr(CRYPTO_NUM_LOCKS)+")"),__FILE__,__LINE__);
throw Exception(_("Error, "+Utils::inttostr(n)+" is bigger than CRYPTO_NUM_LOCKS()("+Utils::inttostr(CRYPTO_NUM_LOCKS)+")"),__FILE__,__LINE__);
if(mode&CRYPTO_LOCK)
pthread_mutex_lock(&ssl_locks[n]);
else
@ -93,7 +94,7 @@ main
}
*/
#ifdef HAVE_SSL
#if defined(HAVE_SSL) && OPENSSL_VERSION_NUMBER < 0x10100000L
CRYPTO_set_locking_callback(ssl_locking_function);
#ifndef WIN32 //getpid() returns different values for threads on windows, therefor this is not needed
CRYPTO_set_id_callback(pthread_self);
@ -107,6 +108,8 @@ main
throw Exception(string(_("Config file "))+argv[1]+_(" doesn't exist or is not readable."),__FILE__,__LINE__);
cfg.parse(argv[1]);
}
else
throw Exception(_("Config file not specified"), __FILE__, __LINE__);
cfg.validateConfig();
}
catch(Exception &e)
@ -119,8 +122,10 @@ main
signal(SIGTERM,exit_requested);
signal(SIGINT,exit_requested);
#ifndef WIN32
signal(SIGCHLD,SIG_IGN);
signal(SIGPIPE,SIG_IGN);
#endif //WIN32
//we have to create the server socket BEFORE chrooting, because if we don't,
//SSL cannot initialize because it's missing libz
@ -160,13 +165,21 @@ main
{
//this is needed to get hermes to load the dns resolver BEFORE chrooting
(void)gethostbyname("hermes-project.com");
chdir(cfg.getChroot().c_str());
if(-1 == chdir(cfg.getChroot().c_str()))
{
LERR(_("Couldn't chdir into ") + cfg.getChroot() + " " + Utils::errnotostrerror(errno) );
return -1;
}
if(-1==chroot(cfg.getChroot().c_str()))
{
LERR(_("Couldn't chroot ") + Utils::errnotostrerror(errno));
return -1;
}
chdir("/");
if(-1 == chdir("/"))
{
LERR(_("Couldn't chdir into /, this shouldn't happen: " + Utils::errnotostrerror(errno)) );
return -1;
}
}
#endif //WIN32
@ -187,10 +200,26 @@ main
if(cfg.getDropPrivileges())
{
//drop privileges once we have opened the listening port
setgroups(0,NULL);
setgid(cfg.getGid());
setuid(cfg.getUid());
setuid(cfg.getUid());
if(-1 == setgroups(0,NULL))
{
LERR(_("Error dropping priviledges " + Utils::errnotostrerror(errno)) );
return -1;
}
if(-1 == setgid(cfg.getGid()))
{
LERR(_("Error setting gid " + Utils::inttostr(cfg.getGid()) + " " + Utils::errnotostrerror(errno)) );
return -1;
}
if(-1 == setuid(cfg.getUid()))
{
LERR(_("Error setting uid " + Utils::inttostr(cfg.getUid()) + " " + Utils::errnotostrerror(errno)) );
return -1;
}
if(-1 == setuid(cfg.getUid()))
{
LERR(_("Error setting uid " + Utils::inttostr(cfg.getUid()) + " " + Utils::errnotostrerror(errno)) );
return -1;
}
}
#endif //WIN32

View file

@ -20,7 +20,6 @@
#ifndef SMTPPROXY_H
#define SMTPPROXY_H
#include "config.h"
#include "Exception.h"
#include <assert.h>
#include <string>