v0.9.8
This commit is contained in:
parent
4905d3db56
commit
a21313453c
@ -1,6 +1,12 @@
|
||||
E-MailRelay Change Log
|
||||
======================
|
||||
|
||||
0.9.7 -> 0.9.8
|
||||
--------------
|
||||
* Fix for running preprocessor ("--filter") as root.
|
||||
* Ignore bogus "AUTH=LOGIN" lines in EHLO response.
|
||||
* Submit utility improved to work with mutt.
|
||||
|
||||
0.9.6 -> 0.9.7
|
||||
--------------
|
||||
* CRAM-MD5 authentication mechanism added.
|
||||
|
2
configure
vendored
2
configure
vendored
@ -1124,7 +1124,7 @@ fi
|
||||
|
||||
PACKAGE=emailrelay
|
||||
|
||||
VERSION=0.9.7
|
||||
VERSION=0.9.8
|
||||
|
||||
if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then
|
||||
{ { echo "$as_me:1130: error: source directory already configured; run \"make distclean\" there first" >&5
|
||||
|
@ -39,7 +39,7 @@ dnl ===
|
||||
dnl Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_INIT(src/main/gsmtp.h)
|
||||
AM_INIT_AUTOMAKE(emailrelay,0.9.7)
|
||||
AM_INIT_AUTOMAKE(emailrelay,0.9.8)
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
|
||||
dnl ===
|
||||
|
1
doc/Makefile.am
Normal file → Executable file
1
doc/Makefile.am
Normal file → Executable file
@ -63,6 +63,7 @@ install-data-local:
|
||||
$(INSTALL) $(top_srcdir)/doc/emailrelay.1 $(destdir)$(mandir)/man1/emailrelay.1
|
||||
$(INSTALL) $(top_srcdir)/doc/emailrelay-passwd.1 $(destdir)$(mandir)/man1/emailrelay-passwd.1
|
||||
$(INSTALL) $(top_srcdir)/doc/emailrelay-poke.1 $(destdir)$(mandir)/man1/emailrelay-poke.1
|
||||
$(INSTALL) $(top_srcdir)/doc/emailrelay-submit.1 $(destdir)$(mandir)/man1/emailrelay-submit.1
|
||||
$(mkinstalldirs) $(destdir)$(pkgdatadir)/graphics
|
||||
$(INSTALL) $(top_srcdir)/doc/graphics/bullet.gif $(destdir)$(pkgdatadir)/graphics/bullet.gif
|
||||
$(mkinstalldirs) $(destdir)$(pkgdatadir)/html
|
||||
|
@ -264,6 +264,7 @@ install-data-local:
|
||||
$(INSTALL) $(top_srcdir)/doc/emailrelay.1 $(destdir)$(mandir)/man1/emailrelay.1
|
||||
$(INSTALL) $(top_srcdir)/doc/emailrelay-passwd.1 $(destdir)$(mandir)/man1/emailrelay-passwd.1
|
||||
$(INSTALL) $(top_srcdir)/doc/emailrelay-poke.1 $(destdir)$(mandir)/man1/emailrelay-poke.1
|
||||
$(INSTALL) $(top_srcdir)/doc/emailrelay-submit.1 $(destdir)$(mandir)/man1/emailrelay-submit.1
|
||||
$(mkinstalldirs) $(destdir)$(pkgdatadir)/graphics
|
||||
$(INSTALL) $(top_srcdir)/doc/graphics/bullet.gif $(destdir)$(pkgdatadir)/graphics/bullet.gif
|
||||
$(mkinstalldirs) $(destdir)$(pkgdatadir)/html
|
||||
|
@ -23,11 +23,13 @@ emailrelay-submit \- a submission utility for E-MailRelay
|
||||
.B emailrelay-submit
|
||||
[--help] [--from
|
||||
.IR from-address ]
|
||||
.I to-address
|
||||
.RI [ to-address \ ...]
|
||||
.SH DESCRIPTION
|
||||
.I emailrelay-submit
|
||||
is a utility which reads an RFC822 email message from the standard
|
||||
input, and writes it into the
|
||||
input, with SMTP envelope recipient addresses passed on the
|
||||
command-line, and writes it into the
|
||||
.B E-MailRelay
|
||||
spool directory.
|
||||
.SH SEE ALSO
|
||||
|
@ -39,8 +39,8 @@ or to people who are on the same local area network.
|
||||
|
||||
Also be careful with programs like "fetchmail" which will fetch incoming mail
|
||||
using POP3 or IMAP, but then use a local SMTP server to deliver to local
|
||||
mailboxes. If your local SMTP server is E-MailRelay then your incoming e-mail
|
||||
will bounce back out.
|
||||
mailboxes. E-MailRelay does not act as a delivery agent, so if your local SMTP
|
||||
server is E-MailRelay then your incoming e-mail will bounce back out.
|
||||
|
||||
Why use it?
|
||||
-----------
|
||||
|
@ -1,10 +1,10 @@
|
||||
Summary: Simple e-mail message transfer agent using SMTP
|
||||
Name: emailrelay
|
||||
Version: 0.9.7
|
||||
Version: 0.9.8
|
||||
Release: 1
|
||||
Copyright: GPL
|
||||
Group: System Environment/Daemons
|
||||
Source: http://emailrelay.sourceforge.net/.../emailrelay-src-0.9.7.tar.gz
|
||||
Source: http://emailrelay.sourceforge.net/.../emailrelay-src-0.9.8.tar.gz
|
||||
BuildRoot: /tmp/emailrelay-install
|
||||
|
||||
%description
|
||||
@ -35,7 +35,9 @@ rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%files
|
||||
|
||||
/usr/local/libexec/emailrelay-passwd
|
||||
/usr/local/libexec/emailrelay-poke
|
||||
/usr/local/libexec/emailrelay-submit
|
||||
/usr/local/libexec/emailrelay.sh
|
||||
/usr/local/sbin/emailrelay
|
||||
/usr/local/var/spool/emailrelay/empty_file
|
||||
@ -49,9 +51,10 @@ rm -rf $RPM_BUILD_ROOT
|
||||
/usr/local/share/emailrelay/man.html
|
||||
/usr/local/share/emailrelay/index.html
|
||||
/usr/local/share/emailrelay/windows.html
|
||||
/usr/local/share/emailrelay/changelog.html
|
||||
/usr/local/share/emailrelay/graphics/bullet.gif
|
||||
/usr/local/share/emailrelay/html/
|
||||
/usr/local/man/man1/emailrelay.1
|
||||
/usr/local/man/man1/emailrelay-passwd.1
|
||||
/usr/local/man/man1/emailrelay-poke.1
|
||||
|
||||
%changelog
|
||||
|
@ -296,7 +296,8 @@ gpath.o: gpath.cpp gdef.h ../../config.h ../../lib/gcc2.95/iostream \
|
||||
gprocess_unix.o: gprocess_unix.cpp gdef.h ../../config.h \
|
||||
../../lib/gcc2.95/iostream ../../lib/gcc2.95/sstream \
|
||||
../../lib/gcc2.95/xlocale ../../lib/gcc2.95/limits gprocess.h \
|
||||
gexception.h gpath.h gstrings.h gfs.h glog.h
|
||||
gexception.h gpath.h gstrings.h gassert.h glogoutput.h glog.h \
|
||||
gfs.h
|
||||
groot.o: groot.cpp gdef.h ../../config.h ../../lib/gcc2.95/iostream \
|
||||
../../lib/gcc2.95/sstream ../../lib/gcc2.95/xlocale \
|
||||
../../lib/gcc2.95/limits groot.h gprocess.h gexception.h \
|
||||
|
@ -94,33 +94,16 @@ public:
|
||||
// error.
|
||||
|
||||
static Who fork() ;
|
||||
// Forks a new process.
|
||||
// Forks a child process.
|
||||
|
||||
static Who fork( Id & child ) ;
|
||||
// Forks a new process. In the parent process
|
||||
// the child process-id is returned by reference.
|
||||
// Forks a child process. Returns the child
|
||||
// pid to the parent.
|
||||
|
||||
static void exec( const Path & exe , const std::string & arg = std::string() ) ;
|
||||
// Executes a program taking reasonable security
|
||||
// precautions.
|
||||
|
||||
static int wait( const Id & child ) ;
|
||||
// Waits for a child process to terminate.
|
||||
// Returns the exit code. Throws exceptions
|
||||
// on error.
|
||||
|
||||
static int wait( const Id & child , int error_return ) ;
|
||||
// Waits for a child process to terminate.
|
||||
// Returns the exit code, or returns 'error_return'
|
||||
// on error.
|
||||
|
||||
static int spawn( const Path & exe , const std::string & arg , int error_return = 127 ) ;
|
||||
// Runs a command in a child process. Returns the
|
||||
static int spawn( Identity nobody , const Path & exe , const std::string & arg , int error_return = 127 ) ;
|
||||
// Runs a command in an unprivileged child process. Returns the
|
||||
// child process's exit code, or 'error_return' on error.
|
||||
|
||||
static bool privileged() ;
|
||||
// Returns true if this process has enhanced security
|
||||
// privileges.
|
||||
// The identity should have come from beOrdinary().
|
||||
|
||||
static int errno_() ;
|
||||
// Returns the process's current 'errno' value.
|
||||
@ -142,7 +125,10 @@ public:
|
||||
|
||||
private:
|
||||
Process() ;
|
||||
static int wait( const Id & child ) ;
|
||||
static int wait( const Id & child , int error_return ) ;
|
||||
static void execCore( const Path & , const std::string & ) ;
|
||||
static void beNobody( Identity ) ;
|
||||
} ;
|
||||
|
||||
namespace G
|
||||
|
@ -23,6 +23,7 @@
|
||||
|
||||
#include "gdef.h"
|
||||
#include "gprocess.h"
|
||||
#include "gassert.h"
|
||||
#include "gfs.h"
|
||||
#include "glog.h"
|
||||
#include <errno.h>
|
||||
@ -176,17 +177,27 @@ int G::Process::errno_()
|
||||
return errno ; // not ::errno or std::errno for gcc2.95
|
||||
}
|
||||
|
||||
void G::Process::exec( const G::Path & exe , const std::string & arg )
|
||||
int G::Process::spawn( Identity nobody , const G::Path & exe , const std::string & arg , int error_return )
|
||||
{
|
||||
if( exe.isRelative() )
|
||||
throw InvalidPath( exe.str() ) ;
|
||||
|
||||
if( privileged() )
|
||||
if( ::geteuid() == 0U || nobody.uid == 0U )
|
||||
throw Insecure() ;
|
||||
|
||||
closeFiles() ;
|
||||
|
||||
execCore( exe , arg ) ;
|
||||
Id child_pid ;
|
||||
if( fork(child_pid) == Child )
|
||||
{
|
||||
beNobody( nobody ) ;
|
||||
G_ASSERT( ::getuid() != 0U && ::geteuid() != 0U ) ;
|
||||
closeFiles() ;
|
||||
execCore( exe , arg ) ;
|
||||
::_exit( error_return ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
return wait( child_pid , error_return ) ;
|
||||
}
|
||||
}
|
||||
|
||||
void G::Process::execCore( const G::Path & exe , const std::string & arg )
|
||||
@ -209,31 +220,6 @@ void G::Process::execCore( const G::Path & exe , const std::string & arg )
|
||||
G_WARNING( "G::Process::exec: execve() returned: errno=" << error << ": " << exe ) ;
|
||||
}
|
||||
|
||||
int G::Process::spawn( const G::Path & exe , const std::string & arg , int error_return )
|
||||
{
|
||||
if( exe.isRelative() )
|
||||
throw InvalidPath( exe.str() ) ;
|
||||
|
||||
if( privileged() )
|
||||
throw Insecure() ;
|
||||
|
||||
Id child_pid ;
|
||||
if( fork(child_pid) == Child )
|
||||
{
|
||||
exec( exe , arg ) ;
|
||||
::_exit( error_return ) ;
|
||||
}
|
||||
else
|
||||
{
|
||||
return wait( child_pid , error_return ) ;
|
||||
}
|
||||
}
|
||||
|
||||
bool G::Process::privileged()
|
||||
{
|
||||
return ::getuid() == 0U || ::geteuid() == 0U ;
|
||||
}
|
||||
|
||||
void G::Process::beSpecial( Identity identity )
|
||||
{
|
||||
// try to change our effective id -- this
|
||||
@ -270,6 +256,17 @@ G::Process::Identity G::Process::beOrdinary( Identity nobody )
|
||||
return special_identity ;
|
||||
}
|
||||
|
||||
void G::Process::beNobody( Identity nobody )
|
||||
{
|
||||
if( ::getuid() == 0 )
|
||||
{
|
||||
// set the *real* userid
|
||||
if( ::seteuid(0) ) throw UidError("0") ; // first
|
||||
if( ::setgid(nobody.gid) ) throw GidError(nobody.str()) ; // second
|
||||
if( ::setuid(nobody.uid) ) throw UidError(nobody.str()) ; // third
|
||||
}
|
||||
}
|
||||
|
||||
// ===
|
||||
|
||||
G::Process::Id::Id() : m_imp(NULL)
|
||||
|
@ -59,9 +59,16 @@ G::Root::~Root()
|
||||
}
|
||||
}
|
||||
|
||||
//static
|
||||
void G::Root::init( const std::string & nobody )
|
||||
{
|
||||
m_nobody = G::Process::Identity( nobody ) ;
|
||||
m_nobody = Process::Identity( nobody ) ;
|
||||
m_special = Process::beOrdinary( m_nobody ) ;
|
||||
}
|
||||
|
||||
//static
|
||||
G::Process::Identity G::Root::nobody()
|
||||
{
|
||||
return m_nobody ;
|
||||
}
|
||||
|
||||
|
@ -54,6 +54,10 @@ public:
|
||||
// gives a non-privileged username which
|
||||
// is used if the real user-id is root.
|
||||
|
||||
static Process::Identity nobody() ;
|
||||
// Returns the 'nobody' identity.
|
||||
// Precondition: init() called
|
||||
|
||||
private:
|
||||
void * operator new( size_t ) ;
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
# General configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
PROJECT_NAME = E-MailRelay
|
||||
PROJECT_NUMBER = 0.9.7
|
||||
PROJECT_NUMBER = 0.9.8
|
||||
OUTPUT_DIRECTORY =
|
||||
OUTPUT_LANGUAGE = English
|
||||
EXTRACT_ALL = YES
|
||||
@ -67,7 +67,7 @@ EXCLUDE = src/glib/gdef.h gdef.h \
|
||||
src/gnet/gresolve_ipv6.cpp gresolve_ipv6.cpp \
|
||||
src/gnet/grequest.cpp grequest.cpp \
|
||||
src/gnet/grequest.h grequest.h
|
||||
EXCLUDE_PATTERNS = */*_win32.* */*_ipv6.cpp */old/* */resolverd.cpp
|
||||
EXCLUDE_PATTERNS = */*_win32.* */*_ipv6.cpp */old/* */resolverd.cpp */gsasl_cyrus.cpp
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATTERNS =
|
||||
IMAGE_PATH =
|
||||
|
@ -325,10 +325,10 @@ void GSmtp::ClientProtocol::onTimeout()
|
||||
G::Strings GSmtp::ClientProtocol::serverAuthMechanisms( const ClientProtocolReply & reply ) const
|
||||
{
|
||||
G::Strings result ;
|
||||
std::string auth_line = reply.textLine("AUTH") ;
|
||||
std::string auth_line = reply.textLine("AUTH ") ; // trailing space to avoid "AUTH="
|
||||
if( ! auth_line.empty() )
|
||||
{
|
||||
G::Str::splitIntoTokens( auth_line , result , " \t" ) ;
|
||||
G::Str::splitIntoTokens( auth_line , result , " " ) ;
|
||||
if( result.size() )
|
||||
result.pop_front() ; // remove "AUTH" ;
|
||||
}
|
||||
@ -415,6 +415,7 @@ GSmtp::ClientProtocolReply::ClientProtocolReply( const std::string & line ) :
|
||||
{
|
||||
m_text = line.substr(4U) ;
|
||||
G::Str::trimLeft( m_text , " \t" ) ;
|
||||
G::Str::replaceAll( m_text , "\t" , " " ) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -78,18 +78,49 @@ public:
|
||||
BadSequence_503 = 503 ,
|
||||
Invalid = 0 ,
|
||||
} ;
|
||||
|
||||
explicit ClientProtocolReply( const std::string & line = std::string() ) ;
|
||||
bool incomplete() const ;
|
||||
// Constructor for one line of text.
|
||||
|
||||
bool add( const ClientProtocolReply & other ) ;
|
||||
// Adds more lines to this reply. Returns
|
||||
// false if the numeric values are different.
|
||||
|
||||
bool incomplete() const ;
|
||||
// Returns true if the reply is incomplete.
|
||||
|
||||
bool validFormat() const ;
|
||||
bool positive() const ; // <400
|
||||
// Returns true if
|
||||
|
||||
bool positive() const ;
|
||||
// Returns true if the numeric value of the
|
||||
// reply is less that four hundred.
|
||||
|
||||
bool is( Value v ) const ;
|
||||
// Returns true if the reply value is 'v'.
|
||||
|
||||
unsigned int value() const ;
|
||||
// Returns the numeric value of the reply.
|
||||
|
||||
std::string text() const ;
|
||||
std::string textLine( const std::string & prefix ) const ;
|
||||
Type type() const ;
|
||||
SubType subType() const ;
|
||||
// Returns the complete text of the reply,
|
||||
// excluding the numeric part, and with
|
||||
// embedded newlines.
|
||||
|
||||
bool textContains( std::string s ) const ;
|
||||
// Returns true if the text() contains
|
||||
// the given substring.
|
||||
|
||||
std::string textLine( const std::string & prefix ) const ;
|
||||
// Returns a line of text() which starts with
|
||||
// prefix.
|
||||
|
||||
Type type() const ;
|
||||
// Returns the reply type (category).
|
||||
|
||||
SubType subType() const ;
|
||||
// Returns the reply sub-type.
|
||||
|
||||
private:
|
||||
bool m_complete ;
|
||||
bool m_valid ;
|
||||
|
@ -164,7 +164,7 @@ bool GSmtp::NewFile::preprocess( const G::Path & path , bool & cancelled )
|
||||
int GSmtp::NewFile::preprocessCore( const G::Path & path )
|
||||
{
|
||||
G_LOG( "GSmtp::NewFile::preprocess: " << m_preprocessor << " " << path ) ;
|
||||
int exit_code = G::Process::spawn( m_preprocessor , path.str() ) ;
|
||||
int exit_code = G::Process::spawn( G::Root::nobody() , m_preprocessor , path.str() ) ;
|
||||
G_LOG( "GSmtp::NewFile::preprocess: exit status " << exit_code ) ;
|
||||
return exit_code ;
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ namespace Main
|
||||
} ;
|
||||
|
||||
// Class: Main::Legal
|
||||
// Description:
|
||||
// Description: A static class providing warranty and copyright text.
|
||||
//
|
||||
class Main::Legal
|
||||
{
|
||||
|
@ -48,7 +48,7 @@
|
||||
//static
|
||||
std::string Main::Run::versionNumber()
|
||||
{
|
||||
return "0.9.7" ;
|
||||
return "0.9.8" ;
|
||||
}
|
||||
|
||||
Main::Run::Run( const G::Arg & arg ) :
|
||||
|
@ -24,7 +24,7 @@
|
||||
// directory.
|
||||
//
|
||||
// It works a bit like sendmail...
|
||||
// * additional recipient addresses can be put on the command-line
|
||||
// * envelope recipient addresses are taken from the command-line
|
||||
// * content (header+body) is read from stdin up to "." or EOF
|
||||
// * the envelope "From" field can be specified on the command-line
|
||||
// * the envelope "From" field is defaulted from the header "From:" line
|
||||
@ -42,11 +42,14 @@
|
||||
#include "gpath.h"
|
||||
#include "gfilestore.h"
|
||||
#include "gnewmessage.h"
|
||||
#include "gexception.h"
|
||||
#include "legal.h"
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
#include <memory>
|
||||
|
||||
G_EXCEPTION( NoBody , "no body text" ) ;
|
||||
|
||||
static void process( const G::Path & path , std::istream & stream ,
|
||||
const G::Strings & to_list , std::string from , G::Strings header )
|
||||
{
|
||||
@ -76,26 +79,14 @@ static void process( const G::Path & path , std::istream & stream ,
|
||||
GSmtp::FileStore store( path ) ;
|
||||
std::auto_ptr<GSmtp::NewMessage> msg = store.newMessage( envelope_from ) ;
|
||||
|
||||
// add additional "To:" lines to the header
|
||||
// add "To:" lines to the envelope
|
||||
//
|
||||
for( G::Strings::const_iterator to_p = to_list.begin() ; to_p != to_list.end() ; ++to_p )
|
||||
{
|
||||
header.push_back( std::string("To: ") + *to_p ) ;
|
||||
}
|
||||
|
||||
// add "To:" lines to the envelope
|
||||
{
|
||||
for( G::Strings::const_iterator header_p = header.begin() ; header_p != header.end() ; ++header_p )
|
||||
{
|
||||
const std::string & line = *header_p ;
|
||||
if( line.find("To: ") == 0U )
|
||||
{
|
||||
std::string to = line.substr(3U) ;
|
||||
G::Str::trim( to , " \t\r\n" ) ;
|
||||
const bool is_local = false ;
|
||||
msg->addTo( to , is_local ) ;
|
||||
}
|
||||
}
|
||||
std::string to = *to_p ;
|
||||
G::Str::trim( to , " \t\r\n" ) ;
|
||||
const bool is_local = false ;
|
||||
msg->addTo( to , is_local ) ;
|
||||
}
|
||||
|
||||
// stream out the header
|
||||
@ -145,7 +136,7 @@ static void run( const G::Arg & arg )
|
||||
else if( getopt.contains("help") )
|
||||
{
|
||||
std::ostream & stream = std::cerr ;
|
||||
getopt.showUsage( stream , arg.prefix() , " [<to-address> ...]" ) ;
|
||||
getopt.showUsage( stream , arg.prefix() , " <to-address> [<to-address> ...]" ) ;
|
||||
stream
|
||||
<< std::endl
|
||||
<< Main::Legal::warranty()
|
||||
@ -153,6 +144,12 @@ static void run( const G::Arg & arg )
|
||||
<< Main::Legal::copyright()
|
||||
<< std::endl ;
|
||||
}
|
||||
else if( getopt.args().c() == 1U )
|
||||
{
|
||||
std::cerr
|
||||
<< getopt.usageSummary( arg.prefix() , " <to-address> [<to-address> ...]" )
|
||||
<< std::endl ;
|
||||
}
|
||||
else
|
||||
{
|
||||
G::Path path = GSmtp::MessageStore::defaultDirectory() ;
|
||||
@ -181,6 +178,8 @@ static void run( const G::Arg & arg )
|
||||
while( stream.good() )
|
||||
{
|
||||
std::string line = G::Str::readLineFrom( stream ) ;
|
||||
if( line == "." )
|
||||
throw NoBody() ;
|
||||
if( line.empty() )
|
||||
break ;
|
||||
header.push_back( line ) ;
|
||||
|
Loading…
x
Reference in New Issue
Block a user