Compare commits

...

15 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
24 changed files with 2200 additions and 920 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)

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

View file

@ -1,3 +1,5 @@
[![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:

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.9], [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;
@ -61,6 +62,31 @@ Socket::Socket():fd(-1)
/* load certificate */
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__);
@ -284,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
{
@ -294,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();
}
@ -343,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());

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;

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);

View file

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