Compare commits
29 commits
hermes-1.8
...
master
Author | SHA1 | Date | |
---|---|---|---|
cb2752889f | |||
b219eabe99 | |||
25dc10cbfd | |||
e9c7141d40 | |||
6b610aaa84 | |||
|
3b7a769021 | ||
|
56db33478e | ||
|
bf915141fd | ||
ccee3ef1c5 | |||
cbb4a1bdcd | |||
|
34360bcafc | ||
400777aaee | |||
9b2b7ccf0a | |||
4ff2575870 | |||
b627f7dcd0 | |||
ad0a63e275 | |||
|
8652af728d | ||
45c9272fce | |||
5627834132 | |||
98f429601a | |||
8460d525ae | |||
45c1fdbf33 | |||
7728f8dae0 | |||
62b6a5c5e0 | |||
f01b634ae3 | |||
53bd14e419 | |||
a96826a208 | |||
02bf18dbcd | |||
18dc796a8a |
27 changed files with 2796 additions and 1099 deletions
2
.dockerignore
Normal file
2
.dockerignore
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
build_dir/
|
||||||
|
build/
|
76
.drone.yml
Normal file
76
.drone.yml
Normal 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 graphviz doxygen gcc make openssl-dev libspf2-dev cmake g++ sqlite-dev gettext-dev python3
|
||||||
|
- cmake -B build_dir -D BUILD_DOCS=ON
|
||||||
|
- 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 graphviz doxygen gcc make openssl-dev libspf2-dev cmake g++ sqlite-dev gettext-dev python3
|
||||||
|
- 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}]
|
||||||
|
|
90
CMakeLists.txt
Normal file
90
CMakeLists.txt
Normal file
|
@ -0,0 +1,90 @@
|
||||||
|
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)
|
||||||
|
|
||||||
|
option(BUILD_DOC "Build documentation")
|
||||||
|
|
||||||
|
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} |
|
||||||
|
python ${CMAKE_CURRENT_SOURCE_DIR}/scripts/generate_config.py
|
||||||
|
DEPENDS src/Configfile.cpp.in src/Configfile.h.in src/Configfile.tmpl
|
||||||
|
docs/hermes-options.html.in scripts/generate_config.py)
|
||||||
|
|
||||||
|
|
||||||
|
# doxygen
|
||||||
|
if (BUILD_DOCS)
|
||||||
|
find_package (Doxygen)
|
||||||
|
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()
|
||||||
|
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)
|
|
@ -1,6 +1,12 @@
|
||||||
ChangeLog
|
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>
|
2014-06-28 18:46 Juan José Gutiérrez de Quevedo <juanjo@gutierrezdequevedo.com>
|
||||||
|
|
||||||
* add more information to the headers injected by hermes
|
* add more information to the headers injected by hermes
|
||||||
|
|
14
Dockerfile
Normal file
14
Dockerfile
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
FROM alpine:3.18
|
||||||
|
ADD . /hermes
|
||||||
|
WORKDIR /hermes
|
||||||
|
RUN apk add --no-cache graphviz doxygen gcc make openssl-dev libspf2-dev cmake g++ sqlite-dev gettext-dev python3
|
||||||
|
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"]
|
|
@ -1,3 +0,0 @@
|
||||||
EXTRA_DIST = scripts/generate_config.pl ChangeLog TODO
|
|
||||||
|
|
||||||
SUBDIRS = src docs dists
|
|
30
README.md
Normal file
30
README.md
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
[](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.
|
|
@ -1,3 +0,0 @@
|
||||||
#!/bin/bash
|
|
||||||
|
|
||||||
aclocal && autoconf && autoheader && automake --add-missing
|
|
134
configure.in
134
configure.in
|
@ -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
|
|
|
@ -1,2 +0,0 @@
|
||||||
doc_DATA = hermesrc.example
|
|
||||||
EXTRA_DIST = fc_init hermes.spec hermes.spec.in
|
|
2931
docs/Doxyfile
2931
docs/Doxyfile
File diff suppressed because it is too large
Load diff
|
@ -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
|
|
|
@ -1,123 +0,0 @@
|
||||||
#!/usr/bin/perl -w
|
|
||||||
|
|
||||||
# this small script generates the Configfile class from the
|
|
||||||
# Configfile.cpp.in and Configfile.h.in. this way when we want
|
|
||||||
# to add a new option to the config file, we just have to put it
|
|
||||||
# on Configfile.tmpl and automagically it will appear on our code
|
|
||||||
# It will also generate an example hermesrc from the same info.
|
|
||||||
# 2007-04-17 Now it also generates an html document for our webpage
|
|
||||||
|
|
||||||
my $hvar="";
|
|
||||||
my $cppvar1="",$cppvar2="",$cppvar3="",$conf_example="",$htmlvar="";
|
|
||||||
|
|
||||||
open HTMLIN, "<../docs/hermes-options.html.in";
|
|
||||||
$htmltempl=join("",<HTMLIN>);
|
|
||||||
close HTMLIN;
|
|
||||||
|
|
||||||
while(<>)
|
|
||||||
{
|
|
||||||
chomp;
|
|
||||||
if(! /^#/ && ! /^\t*$/ && ! /^\*/)
|
|
||||||
{
|
|
||||||
s/^\s+//;s/\s+$//;
|
|
||||||
@_=split ",";
|
|
||||||
my $camelcased=&camel_case($_[1]);
|
|
||||||
my $type=$_[0];
|
|
||||||
$type="list<string>" if($type =~ /list/);
|
|
||||||
$hvar1.="$type $_[1];\n";
|
|
||||||
$hvar2.="$type& get$camelcased();\n";
|
|
||||||
if($type =~ /list/)
|
|
||||||
{
|
|
||||||
$cppvar1.="$_[1]=Configfile::parseAsList($_[2]);\n";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$cppvar1.="$_[1]=$_[2];\n";
|
|
||||||
}
|
|
||||||
$cppvar2.="PARSE_".uc($_[0])."(\"$_[1]\",$_[1])\n";
|
|
||||||
$cppvar3.="GET_VAR(get$camelcased,$_[1],$type&)\n";
|
|
||||||
$conf_example.="$_[1] = $_[2]\n\n";
|
|
||||||
my $htmltemp=$htmltempl;
|
|
||||||
$htmltemp =~ s/%type%/$_[0]/;
|
|
||||||
$htmltemp =~ s/%name%/$_[1]/g;
|
|
||||||
$htmltemp =~ s/%default%/$_[2]/;
|
|
||||||
$htmltemp =~ s/%explanation%/$htmlexpl/;
|
|
||||||
$htmlexpl="";
|
|
||||||
$htmlvar.=$htmltemp;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(/^\*clean\*$/) # clean restarts our htmlexpl contents
|
|
||||||
{
|
|
||||||
$htmlexpl="";
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if(/^\*/)
|
|
||||||
{
|
|
||||||
s/^\*$//;
|
|
||||||
s/^\*/#/;
|
|
||||||
$conf_example.="$_\n";
|
|
||||||
chomp;
|
|
||||||
s/^#//;
|
|
||||||
s/>/>/;
|
|
||||||
$htmlexpl.="$_\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
chomp $cppvar1;
|
|
||||||
chomp $cppvar2;
|
|
||||||
chomp $cppvar3;
|
|
||||||
chomp $hvar1;
|
|
||||||
chomp $hvar2;
|
|
||||||
chomp $conf_example;
|
|
||||||
|
|
||||||
open CPPIN, "<Configfile.cpp.in";
|
|
||||||
$cppstr=join("",<CPPIN>);
|
|
||||||
close CPPIN;
|
|
||||||
open CPPOUT, ">Configfile.cpp";
|
|
||||||
$cppstr =~ s/%templ_default_values%/$cppvar1/;
|
|
||||||
$cppstr =~ s/%templ_parsevars%/$cppvar2/;
|
|
||||||
$cppstr =~ s/%templ_getmethods%/$cppvar3/;
|
|
||||||
print CPPOUT $cppstr;
|
|
||||||
close CPPOUT;
|
|
||||||
|
|
||||||
open HIN, "<Configfile.h.in";
|
|
||||||
$hstr=join("",<HIN>);
|
|
||||||
close HIN;
|
|
||||||
open HOUT, ">Configfile.h";
|
|
||||||
$hstr =~ s/%templ_privateattribs%/$hvar1/;
|
|
||||||
$hstr =~ s/%templ_publicmethods%/$hvar2/;
|
|
||||||
print HOUT $hstr;
|
|
||||||
close HOUT;
|
|
||||||
|
|
||||||
open RCEX, ">../dists/hermesrc.example";
|
|
||||||
print RCEX $conf_example;
|
|
||||||
close RCEX;
|
|
||||||
|
|
||||||
open HTML, ">../docs/hermes-options.html";
|
|
||||||
print HTML $htmlvar;
|
|
||||||
close HTML;
|
|
||||||
|
|
||||||
sub camel_case()
|
|
||||||
{
|
|
||||||
my $str=shift;
|
|
||||||
my $outstr="";
|
|
||||||
|
|
||||||
for($i=0;$i<length($str);$i++)
|
|
||||||
{
|
|
||||||
my $letter=substr($str,$i,1);
|
|
||||||
if($letter eq "_")
|
|
||||||
{
|
|
||||||
$i++;
|
|
||||||
$outstr.=uc(substr($str,$i,1));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$outstr.=$letter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ucfirst($outstr);
|
|
||||||
}
|
|
112
scripts/generate_config.py
Normal file
112
scripts/generate_config.py
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import re
|
||||||
|
import string
|
||||||
|
|
||||||
|
def camel_case(str_):
|
||||||
|
"""Convert snake_case to CamelCase."""
|
||||||
|
return string.capwords(str_, "_").replace("_", "")
|
||||||
|
|
||||||
|
def main():
|
||||||
|
# Read input files
|
||||||
|
with open('../docs/hermes-options.html.in', 'r') as f:
|
||||||
|
html_templ = f.read()
|
||||||
|
|
||||||
|
hvar1 = ""
|
||||||
|
hvar2 = ""
|
||||||
|
cppvar1 = ""
|
||||||
|
cppvar2 = ""
|
||||||
|
cppvar3 = ""
|
||||||
|
conf_example = ""
|
||||||
|
htmlvar = ""
|
||||||
|
htmlexpl = ""
|
||||||
|
|
||||||
|
# Process input
|
||||||
|
for line in sys.stdin:
|
||||||
|
line = line.strip()
|
||||||
|
|
||||||
|
if not line or line.startswith('#') or line.startswith('*'):
|
||||||
|
if line == '*clean*':
|
||||||
|
htmlexpl = ""
|
||||||
|
elif line.startswith('*'):
|
||||||
|
line = line.replace('*', '#')
|
||||||
|
conf_example += line + "\n"
|
||||||
|
|
||||||
|
# Convert line for HTML
|
||||||
|
line_html = line.lstrip('#').replace('>', '>')
|
||||||
|
htmlexpl += line_html + "\n"
|
||||||
|
continue
|
||||||
|
|
||||||
|
parts = line.split(',')
|
||||||
|
parts = [p.strip() for p in parts]
|
||||||
|
|
||||||
|
type_str = parts[0]
|
||||||
|
var_name = parts[1]
|
||||||
|
default_val = parts[2]
|
||||||
|
|
||||||
|
# Modify type for lists
|
||||||
|
if 'list' in type_str:
|
||||||
|
type_str = 'list<string>'
|
||||||
|
|
||||||
|
camel_name = camel_case(var_name)
|
||||||
|
|
||||||
|
# Generate header variables
|
||||||
|
hvar1 += f"{type_str} {var_name};\n"
|
||||||
|
hvar2 += f"{type_str}& get{camel_name}();\n"
|
||||||
|
|
||||||
|
# Generate cpp variables
|
||||||
|
if 'list' in type_str:
|
||||||
|
cppvar1 += f"{var_name} = Configfile::parseAsList({default_val});\n"
|
||||||
|
else:
|
||||||
|
cppvar1 += f"{var_name} = {default_val};\n"
|
||||||
|
|
||||||
|
cppvar2 += f"PARSE_{parts[0].upper()}(\"{var_name}\", {var_name})\n"
|
||||||
|
cppvar3 += f"GET_VAR(get{camel_name}, {var_name}, {type_str}&)\n"
|
||||||
|
|
||||||
|
# Generate config example
|
||||||
|
conf_example += f"{var_name} = {default_val}\n\n"
|
||||||
|
|
||||||
|
# Generate HTML
|
||||||
|
html_temp = html_templ.replace('%type%', parts[0]) \
|
||||||
|
.replace('%name%', var_name) \
|
||||||
|
.replace('%default%', default_val) \
|
||||||
|
.replace('%explanation%', htmlexpl)
|
||||||
|
htmlvar += html_temp
|
||||||
|
htmlexpl = ""
|
||||||
|
|
||||||
|
# Clean up variables
|
||||||
|
for var in [cppvar1, cppvar2, cppvar3, hvar1, hvar2, conf_example]:
|
||||||
|
var = var.rstrip()
|
||||||
|
|
||||||
|
# Read and write Configfile.cpp
|
||||||
|
with open('../src/Configfile.cpp.in', 'r') as f:
|
||||||
|
cpp_str = f.read()
|
||||||
|
|
||||||
|
cpp_str = cpp_str.replace('%templ_default_values%', cppvar1) \
|
||||||
|
.replace('%templ_parsevars%', cppvar2) \
|
||||||
|
.replace('%templ_getmethods%', cppvar3)
|
||||||
|
|
||||||
|
with open('Configfile.cpp', 'w') as f:
|
||||||
|
f.write(cpp_str)
|
||||||
|
|
||||||
|
# Read and write Configfile.h
|
||||||
|
with open('../src/Configfile.h.in', 'r') as f:
|
||||||
|
h_str = f.read()
|
||||||
|
|
||||||
|
h_str = h_str.replace('%templ_privateattribs%', hvar1) \
|
||||||
|
.replace('%templ_publicmethods%', hvar2)
|
||||||
|
|
||||||
|
with open('Configfile.h', 'w') as f:
|
||||||
|
f.write(h_str)
|
||||||
|
|
||||||
|
# Write hermesrc.example
|
||||||
|
with open('../dists/hermesrc.example', 'w') as f:
|
||||||
|
f.write(conf_example)
|
||||||
|
|
||||||
|
# Write hermes-options.html
|
||||||
|
with open('../docs/hermes-options.html', 'w') as f:
|
||||||
|
f.write(htmlvar)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
|
@ -108,17 +108,6 @@ void Configfile::validateConfig()
|
||||||
throw Exception("Directory "+chroot+" doesn't exist, can't chroot to it.",__FILE__,__LINE__);
|
throw Exception("Directory "+chroot+" doesn't exist, can't chroot to it.",__FILE__,__LINE__);
|
||||||
#endif //WIN32
|
#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)
|
string Configfile::parseAsString(string str)
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
#include "../config.h"
|
|
||||||
|
|
||||||
* comments MUST begin with a #.
|
* 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
|
* # openssl req -new -x509 -nodes -sha1 -days 365 -key private.key > certificate.crt
|
||||||
* and answer the questions
|
* and answer the questions
|
||||||
string,certificate_file,"/etc/hermes/hermes.cert"
|
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
|
#endif //HAVE_SSL
|
||||||
|
|
||||||
* whether to add headers to the email sent or no.
|
* whether to add headers to the email sent or no.
|
||||||
|
|
|
@ -392,7 +392,7 @@ unsigned long Database::getIntValue(string& p_sql)
|
||||||
|
|
||||||
if(NULL==result)
|
if(NULL==result)
|
||||||
throw SQLException("SQL: "+p_sql+" didn't return any data, SQL query may be wrong",__FILE__,__LINE__);
|
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?
|
value=0; //why sqlite doesn't return 0 when there are no rows?
|
||||||
else
|
else
|
||||||
value=strtoul(result[ncolumn],NULL,10);
|
value=strtoul(result[ncolumn],NULL,10);
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
*/
|
*/
|
||||||
#include "FileLogger.h"
|
#include "FileLogger.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
extern Configfile cfg;
|
extern Configfile cfg;
|
||||||
extern __thread unsigned long connection_id;
|
extern __thread unsigned long connection_id;
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
#ifndef FILELOGGER_H
|
#ifndef FILELOGGER_H
|
||||||
#define FILELOGGER_H
|
#define FILELOGGER_H
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
|
@ -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
|
|
|
@ -261,8 +261,10 @@ void Proxy::run(string &peer_address)
|
||||||
outside.writeLine(strtemp);
|
outside.writeLine(strtemp);
|
||||||
strtemp="";
|
strtemp="";
|
||||||
string ssltls="";
|
string ssltls="";
|
||||||
|
#ifdef HAVE_SSL
|
||||||
if (outside.is_ssl_enabled())
|
if (outside.is_ssl_enabled())
|
||||||
ssltls=" (SSL/TLS)";
|
ssltls=" (SSL/TLS)";
|
||||||
|
#endif //HAVE_SSL
|
||||||
|
|
||||||
if(cfg.getAddHeaders())
|
if(cfg.getAddHeaders())
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
#ifndef SERVERSOCKET_H
|
#ifndef SERVERSOCKET_H
|
||||||
#define SERVERSOCKET_H
|
#define SERVERSOCKET_H
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
*/
|
*/
|
||||||
#include "Socket.h"
|
#include "Socket.h"
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
int Socket::created_sockets=0;
|
int Socket::created_sockets=0;
|
||||||
|
|
||||||
|
@ -59,8 +60,33 @@ Socket::Socket():fd(-1)
|
||||||
if(!ssl_ctx_server)
|
if(!ssl_ctx_server)
|
||||||
throw Exception(_("Error creating SSL context"),__FILE__,__LINE__);
|
throw Exception(_("Error creating SSL context"),__FILE__,__LINE__);
|
||||||
/* load certificate */
|
/* 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__);
|
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 */
|
/* load private key */
|
||||||
if(SSL_CTX_use_PrivateKey_file(ssl_ctx_server,cfg.getPrivateKeyFile().c_str(),SSL_FILETYPE_PEM)==-1)
|
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__);
|
throw Exception(_("Error loading private key"),__FILE__,__LINE__);
|
||||||
|
@ -228,21 +254,33 @@ ssize_t Socket::readBytes(void *buf,ssize_t lon)
|
||||||
|
|
||||||
#ifdef HAVE_SSL
|
#ifdef HAVE_SSL
|
||||||
if(ssl_enabled)
|
if(ssl_enabled)
|
||||||
|
{
|
||||||
retval=SSL_read(ssl,buf,lon);
|
retval=SSL_read(ssl,buf,lon);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
#endif //HAVE_SSL
|
#endif //HAVE_SSL
|
||||||
|
{
|
||||||
retval=recv(fd,(char *)buf,lon,MSG_NOSIGNAL);
|
retval=recv(fd,(char *)buf,lon,MSG_NOSIGNAL);
|
||||||
|
}
|
||||||
|
|
||||||
if(!retval)
|
if(!retval)
|
||||||
|
{
|
||||||
throw NetworkException(_("Peer closed connection"),__FILE__,__LINE__);
|
throw NetworkException(_("Peer closed connection"),__FILE__,__LINE__);
|
||||||
|
}
|
||||||
|
|
||||||
if(retval<0)
|
if(retval<0)
|
||||||
|
{
|
||||||
#ifdef HAVE_SSL
|
#ifdef HAVE_SSL
|
||||||
if(ssl_enabled)
|
if(ssl_enabled)
|
||||||
|
{
|
||||||
throw NetworkException(_("SSL error number: ")+Utils::inttostr(SSL_get_error(ssl,retval)),__FILE__,__LINE__);
|
throw NetworkException(_("SSL error number: ")+Utils::inttostr(SSL_get_error(ssl,retval)),__FILE__,__LINE__);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
#endif //HAVE_SSL
|
#endif //HAVE_SSL
|
||||||
|
{
|
||||||
throw NetworkException(_(Utils::errnotostrerror(errno)),__FILE__,__LINE__);
|
throw NetworkException(_(Utils::errnotostrerror(errno)),__FILE__,__LINE__);
|
||||||
|
}
|
||||||
|
}
|
||||||
readed+=lon;
|
readed+=lon;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,6 +310,10 @@ string Socket::readLine()
|
||||||
{
|
{
|
||||||
char c=0;
|
char c=0;
|
||||||
stringstream s;
|
stringstream s;
|
||||||
|
string ssl_debug_string="";
|
||||||
|
#ifdef HAVE_SSL
|
||||||
|
if (ssl_enabled) ssl_debug_string = "s";
|
||||||
|
#endif //HAVE_SSL
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
|
@ -282,7 +324,7 @@ string Socket::readLine()
|
||||||
}
|
}
|
||||||
while(c!=10&&!isClosed());
|
while(c!=10&&!isClosed());
|
||||||
|
|
||||||
LDEB("r" + string(ssl_enabled?"s":"") + ">" + s.str());
|
LDEB(string("r") + ssl_debug_string + ">" + s.str());
|
||||||
|
|
||||||
return s.str();
|
return s.str();
|
||||||
}
|
}
|
||||||
|
@ -308,12 +350,18 @@ void Socket::writeBytes(void *bytes,ssize_t len)
|
||||||
throw NetworkException(_("Peer closed connection"),__FILE__,__LINE__);
|
throw NetworkException(_("Peer closed connection"),__FILE__,__LINE__);
|
||||||
|
|
||||||
if(retval<0)
|
if(retval<0)
|
||||||
|
{
|
||||||
#ifdef HAVE_SSL
|
#ifdef HAVE_SSL
|
||||||
if(ssl_enabled)
|
if(ssl_enabled)
|
||||||
|
{
|
||||||
throw NetworkException(_("SSL error number: ")+Utils::inttostr(SSL_get_error(ssl,retval)),__FILE__,__LINE__);
|
throw NetworkException(_("SSL error number: ")+Utils::inttostr(SSL_get_error(ssl,retval)),__FILE__,__LINE__);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
#endif //HAVE_SSL
|
#endif //HAVE_SSL
|
||||||
|
{
|
||||||
throw NetworkException(_(Utils::errnotostrerror(errno)),__FILE__,__LINE__);
|
throw NetworkException(_(Utils::errnotostrerror(errno)),__FILE__,__LINE__);
|
||||||
|
}
|
||||||
|
}
|
||||||
written+=len;
|
written+=len;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -325,8 +373,12 @@ void Socket::writeByte(char c)
|
||||||
|
|
||||||
void Socket::writeLine(string s)
|
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";
|
s+="\r\n";
|
||||||
|
|
||||||
writeBytes((void *)s.c_str(),s.length());
|
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);
|
error=getnameinfo(&addr,sizeof(struct sockaddr),hostname,NI_MAXHOST,NULL,0,NI_NAMEREQD);
|
||||||
|
|
||||||
if(error)
|
if(error)
|
||||||
|
{
|
||||||
if(error==EAI_NONAME) //if the problem is that we didn't get a hostname, return empty string
|
if(error==EAI_NONAME) //if the problem is that we didn't get a hostname, return empty string
|
||||||
|
{
|
||||||
hostname[0]='\0';
|
hostname[0]='\0';
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
#ifdef HAVE_GAI_STRERROR
|
#ifdef HAVE_GAI_STRERROR
|
||||||
throw Exception(gai_strerror(error)+Utils::inttostr(error),__FILE__,__LINE__);
|
throw Exception(gai_strerror(error)+Utils::inttostr(error),__FILE__,__LINE__);
|
||||||
#else
|
#else
|
||||||
|
@ -477,6 +533,8 @@ string Socket::resolveInverselyToString(string ip)
|
||||||
throw Exception("Socket error number "+Utils::inttostr(error),__FILE__,__LINE__);
|
throw Exception("Socket error number "+Utils::inttostr(error),__FILE__,__LINE__);
|
||||||
#endif //WIN32
|
#endif //WIN32
|
||||||
#endif //HAVE_GAI_STRERROR
|
#endif //HAVE_GAI_STRERROR
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return string(hostname);
|
return string(hostname);
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ void UnixLogger::addMessage(string file,int line,int loglevel,string logmessage)
|
||||||
|
|
||||||
if(loglevel<=cfg.getLogLevel())
|
if(loglevel<=cfg.getLogLevel())
|
||||||
{
|
{
|
||||||
|
sloglevel = LOG_INFO;
|
||||||
switch(loglevel)
|
switch(loglevel)
|
||||||
{
|
{
|
||||||
case HERMES_LOG_INFO: sloglevel=LOG_INFO;break;
|
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;
|
message=file+":"+Utils::inttostr(line)+" [" + Utils::inttostr(connection_id) + "] " + logmessage;
|
||||||
if(false==cfg.getBackground())
|
if(false==cfg.getBackground())
|
||||||
cout << message << endl;
|
cout << message << endl;
|
||||||
syslog(sloglevel,message.c_str());
|
syslog(sloglevel, "%s", message.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
extern Configfile cfg;
|
extern Configfile cfg;
|
||||||
extern LOGGER_CLASS hermes_log;
|
extern LOGGER_CLASS hermes_log;
|
||||||
|
@ -418,10 +419,16 @@ string Utils::errnotostrerror(int errnum)
|
||||||
{
|
{
|
||||||
char buf[2048]="";
|
char buf[2048]="";
|
||||||
char *strerr;
|
char *strerr;
|
||||||
// if(strerror_r(errnum,strerr,1024)!=-1)
|
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
|
#ifdef __GLIBC__
|
||||||
strerr=strerror_r(errnum,buf,2048);
|
strerr=strerror_r(errnum,buf,2048);
|
||||||
#else
|
#else
|
||||||
|
int retval = strerror_r(errnum, buf, sizeof buf);
|
||||||
|
strerr = buf;
|
||||||
|
if(retval != 0)
|
||||||
|
strcpy(buf, "error fetching error description");
|
||||||
|
#endif
|
||||||
|
#else
|
||||||
strerr="Error ";
|
strerr="Error ";
|
||||||
#endif //WIN32
|
#endif //WIN32
|
||||||
return string(strerr)+" ("+inttostr(errnum)+")";
|
return string(strerr)+" ("+inttostr(errnum)+")";
|
||||||
|
@ -611,7 +618,7 @@ string Utils::gethostname()
|
||||||
if('\0'==buf[0])
|
if('\0'==buf[0])
|
||||||
{
|
{
|
||||||
if(cfg.getHostname()!="")
|
if(cfg.getHostname()!="")
|
||||||
strncpy(buf,cfg.getHostname().c_str(),HOST_NAME_MAX);
|
strncpy(buf,cfg.getHostname().c_str(),HOST_NAME_MAX - 1);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if(-1==::gethostname(buf,HOST_NAME_MAX))
|
if(-1==::gethostname(buf,HOST_NAME_MAX))
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
*
|
*
|
||||||
* @author Juan José Gutiérrez de Quevedo <juanjo@gutierrezdequevedo.com>
|
* @author Juan José Gutiérrez de Quevedo <juanjo@gutierrezdequevedo.com>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <stack>
|
#include <stack>
|
||||||
|
@ -62,13 +63,13 @@ __thread unsigned long connection_id;
|
||||||
|
|
||||||
list<unsigned long> children;
|
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};
|
pthread_mutex_t ssl_locks[CRYPTO_NUM_LOCKS]={PTHREAD_MUTEX_INITIALIZER};
|
||||||
|
|
||||||
void ssl_locking_function(int mode,int n,const char *file,int line)
|
void ssl_locking_function(int mode,int n,const char *file,int line)
|
||||||
{
|
{
|
||||||
if(n>CRYPTO_NUM_LOCKS)
|
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)
|
if(mode&CRYPTO_LOCK)
|
||||||
pthread_mutex_lock(&ssl_locks[n]);
|
pthread_mutex_lock(&ssl_locks[n]);
|
||||||
else
|
else
|
||||||
|
@ -93,7 +94,7 @@ main
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef HAVE_SSL
|
#if defined(HAVE_SSL) && OPENSSL_VERSION_NUMBER < 0x10100000L
|
||||||
CRYPTO_set_locking_callback(ssl_locking_function);
|
CRYPTO_set_locking_callback(ssl_locking_function);
|
||||||
#ifndef WIN32 //getpid() returns different values for threads on windows, therefor this is not needed
|
#ifndef WIN32 //getpid() returns different values for threads on windows, therefor this is not needed
|
||||||
CRYPTO_set_id_callback(pthread_self);
|
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__);
|
throw Exception(string(_("Config file "))+argv[1]+_(" doesn't exist or is not readable."),__FILE__,__LINE__);
|
||||||
cfg.parse(argv[1]);
|
cfg.parse(argv[1]);
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
throw Exception(_("Config file not specified"), __FILE__, __LINE__);
|
||||||
cfg.validateConfig();
|
cfg.validateConfig();
|
||||||
}
|
}
|
||||||
catch(Exception &e)
|
catch(Exception &e)
|
||||||
|
@ -119,8 +122,10 @@ main
|
||||||
|
|
||||||
signal(SIGTERM,exit_requested);
|
signal(SIGTERM,exit_requested);
|
||||||
signal(SIGINT,exit_requested);
|
signal(SIGINT,exit_requested);
|
||||||
|
#ifndef WIN32
|
||||||
signal(SIGCHLD,SIG_IGN);
|
signal(SIGCHLD,SIG_IGN);
|
||||||
signal(SIGPIPE,SIG_IGN);
|
signal(SIGPIPE,SIG_IGN);
|
||||||
|
#endif //WIN32
|
||||||
|
|
||||||
//we have to create the server socket BEFORE chrooting, because if we don't,
|
//we have to create the server socket BEFORE chrooting, because if we don't,
|
||||||
//SSL cannot initialize because it's missing libz
|
//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
|
//this is needed to get hermes to load the dns resolver BEFORE chrooting
|
||||||
(void)gethostbyname("hermes-project.com");
|
(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()))
|
if(-1==chroot(cfg.getChroot().c_str()))
|
||||||
{
|
{
|
||||||
LERR(_("Couldn't chroot ") + Utils::errnotostrerror(errno));
|
LERR(_("Couldn't chroot ") + Utils::errnotostrerror(errno));
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
chdir("/");
|
if(-1 == chdir("/"))
|
||||||
|
{
|
||||||
|
LERR(_("Couldn't chdir into /, this shouldn't happen: " + Utils::errnotostrerror(errno)) );
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif //WIN32
|
#endif //WIN32
|
||||||
|
|
||||||
|
@ -187,10 +200,26 @@ main
|
||||||
if(cfg.getDropPrivileges())
|
if(cfg.getDropPrivileges())
|
||||||
{
|
{
|
||||||
//drop privileges once we have opened the listening port
|
//drop privileges once we have opened the listening port
|
||||||
setgroups(0,NULL);
|
if(-1 == setgroups(0,NULL))
|
||||||
setgid(cfg.getGid());
|
{
|
||||||
setuid(cfg.getUid());
|
LERR(_("Error dropping priviledges " + Utils::errnotostrerror(errno)) );
|
||||||
setuid(cfg.getUid());
|
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
|
#endif //WIN32
|
||||||
|
|
||||||
|
@ -303,38 +332,6 @@ void *cleaner_thread_run(void *)
|
||||||
{
|
{
|
||||||
LERR("Error cleaning the database: " + string(e));
|
LERR("Error cleaning the database: " + string(e));
|
||||||
}
|
}
|
||||||
if(spamcount>0&&cfg.getSubmitStats())
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Socket s;
|
|
||||||
string server_response;
|
|
||||||
|
|
||||||
s.init();
|
|
||||||
s.connect("stats.hermes-project.com",11125);
|
|
||||||
#ifdef HAVE_SSL
|
|
||||||
if(cfg.getSubmitStatsSsl())
|
|
||||||
{
|
|
||||||
s.writeLine("ssl");
|
|
||||||
s.prepareSSL(false);
|
|
||||||
s.startSSL(false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif //HAVE_SSL
|
|
||||||
s.writeLine("non-ssl");
|
|
||||||
s.writeLine(cfg.getSubmitStatsUsername());
|
|
||||||
s.writeLine(cfg.getSubmitStatsPassword());
|
|
||||||
s.writeLine(Utils::inttostr(spamcount));
|
|
||||||
server_response=s.readLine();
|
|
||||||
s.close();
|
|
||||||
if("OK"!=server_response)
|
|
||||||
throw Exception(server_response,__FILE__,__LINE__);
|
|
||||||
}
|
|
||||||
catch(Exception &e)
|
|
||||||
{
|
|
||||||
LDEB("Exception sending stats: "+string(e));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#ifndef WIN32
|
#ifndef WIN32
|
||||||
if(false==cfg.getBackground())
|
if(false==cfg.getBackground())
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
#ifndef SMTPPROXY_H
|
#ifndef SMTPPROXY_H
|
||||||
#define SMTPPROXY_H
|
#define SMTPPROXY_H
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "Exception.h"
|
#include "Exception.h"
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
Loading…
Add table
Reference in a new issue