1 // Copyright 2009 The Archiveopteryx Developers <info@aox.org>
2 
3 #include "smtp.h"
4 
5 #include "smtpmailrcpt.h"
6 #include "smtpcommand.h"
7 #include "transaction.h"
8 #include "eventloop.h"
9 #include "address.h"
10 #include "mailbox.h"
11 #include "buffer.h"
12 #include "query.h"
13 #include "scope.h"
14 #include "sieve.h"
15 #include "date.h"
16 #include "user.h"
17 
18 // getpid()
19 #include <sys/types.h>
20 #include <unistd.h>
21 
22 
23 class SMTPData
24     : public Garbage
25 {
26 public:
SMTPData()27     SMTPData():
28         executing( false ), executeAgain( false ),
29         inputState( SMTP::Command ),
30         dialect( SMTP::Smtp ),
31         sieve( 0 ), user( 0 ), permittedAddresses( 0 ),
32         recipients( new List<SmtpRcptTo> ), now( 0 ) {}
33 
34     bool executing;
35     bool executeAgain;
36     SMTP::InputState inputState;
37     SMTP::Dialect dialect;
38     Sieve * sieve;
39     List<SmtpCommand> commands;
40     EString heloName;
41     User * user;
42     List<Address> * permittedAddresses;
43     List<SmtpRcptTo> * recipients;
44     EString body;
45     Date * now;
46     EString id;
47 
48     class AddressFinder
49         : public EventHandler
50     {
51     public:
AddressFinder(List<Address> * addresses)52         AddressFinder( List<Address> * addresses ) : q( 0 ), a( addresses ) {}
53         void execute();
54         Query * q;
55     private:
56         List<Address> * a;
57     };
58 };
59 
60 
61 /*! \class SMTP smtp.h
62     The SMTP class implements a basic SMTP server.
63 
64     This is not a classic MTA. It implements all that's needed to
65     deliver to local users, and for local users to submit messages to
66     others. Nothing more.
67 
68     This class implements SMTP as specified by RFC 2821, with the
69     extensions specified by RFC 1651 (EHLO), RFC 1652 (8BITMIME), RFC
70     2487 (STARTTLS), RFC 2554 (AUTH), RFC 3030 (BINARYMIME and
71     CHUNKING) and RFC 4468 (BURL).
72 */
73 
74 /*! \class LMTP smtp.h
75     This subclass of SMTP implements LMTP (RFC 2033).
76 */
77 
78 /*! \class SMTPSubmit smtp.h
79     This subclass of SMTP implements SMTP submission (RFC 4409).
80 */
81 
82 /*!  Constructs an (E)SMTP server for socket \a s, speaking \a dialect. */
83 
SMTP(int s,Dialect dialect)84 SMTP::SMTP( int s, Dialect dialect )
85     : SaslConnection( s, Connection::SmtpServer ), d( new SMTPData )
86 {
87     Scope x( log() );
88     d->dialect = dialect;
89     switch( dialect ) {
90     case Smtp:
91         enqueue( "220 ESMTP " );
92         break;
93     case Lmtp:
94         enqueue( "220 LMTP " );
95         break;
96     case Submit:
97         enqueue( "220 SMTP Submission " );
98         break;
99     }
100     enqueue( Configuration::hostname() );
101     enqueue( "\r\n" );
102     setTimeoutAfter( 1800 );
103     EventLoop::global()->addConnection( this );
104 }
105 
106 
107 /*! Constructs an LMTP server of socket \a s. */
108 
LMTP(int s)109 LMTP::LMTP( int s )
110     : SMTP( s, SMTP::Lmtp )
111 {
112 }
113 
114 
115 /*!  Constructs a SMTP/submit server (see RFC 4409) for socket \a s. */
116 
SMTPSubmit(int s)117 SMTPSubmit::SMTPSubmit( int s )
118     : SMTP( s, SMTP::Submit )
119 {
120 }
121 
122 
react(Event e)123 void SMTP::react( Event e )
124 {
125     switch ( e ) {
126     case Read:
127         setTimeoutAfter( 1800 );
128         parse();
129         break;
130 
131     case Timeout:
132         log( "Idle timeout" );
133         enqueue( "421 Tempus fugit\r\n" );
134         Connection::setState( Closing );
135         break;
136 
137     case Connect:
138     case Error:
139     case Close:
140         break;
141 
142     case Shutdown:
143         enqueue( "421 Server shutdown\r\n" );
144         break;
145     }
146     execute();
147 }
148 
149 
150 /*! Parses the SMTP/LMTP input stream.
151 */
152 
parse()153 void SMTP::parse()
154 {
155     Buffer * r = readBuffer();
156     bool progress = true;
157     while ( progress && Connection::state() == Connected ) {
158         uint n = r->size();
159         if ( inputState() == Command )
160             parseCommand();
161         else
162             d->commands.last()->execute();
163         if ( r->size() >= n )
164             progress = false;
165     }
166 }
167 
168 
169 /*! Reads a single SMTP/LMTP/Submit command from the client and
170     creates an execution object for it.
171 
172     Line length is limited to 4096 (for SMTP commands, not for message
173     bodies): RFC 2821 section 4.5.3 says 512 is acceptable and various
174     SMTP extensions may increase it. RFC 2822 declares that line
175     lengths should be limited to 998 characters.
176 */
177 
parseCommand()178 void SMTP::parseCommand()
179 {
180     Buffer * r = readBuffer();
181     EString * line = r->removeLine( 4096 );
182     if ( !line && r->size() > 4096 ) {
183         log( "Connection closed due to overlong line", Log::Error );
184         enqueue( "500 Line too long (legal maximum is 998 bytes)\r\n" );
185         Connection::setState( Closing );
186         return;
187     }
188     if ( !line )
189         return;
190 
191     d->commands.append( SmtpCommand::create( this, *line ) );
192 }
193 
194 
195 /*! Runs all outstanding commands. When the oldest command is done,
196     execute() removes it from the list and sends its responses to the
197     client.
198 */
199 
execute()200 void SMTP::execute()
201 {
202     // make sure we don't call execute() recursively.
203     if ( d->executing ) {
204         d->executeAgain = true;
205         return;
206     }
207     d->executing = true;
208     d->executeAgain = true;
209 
210     // run each command, and do the whole loop again if execute() is
211     // called recursively meanwhile.
212     while ( d->executeAgain ) {
213         d->executeAgain = false;
214         List<SmtpCommand>::Iterator i( d->commands );
215         while ( i ) {
216             SmtpCommand * c = i;
217             ++i;
218             if ( !c->done() )
219                 c->notify();
220         }
221 
222         // see if any old commands may be retired
223         i = d->commands.first();
224         while ( i && i->done() ) {
225             d->executeAgain = true;
226             i->emitResponses();
227             d->commands.take( i );
228         }
229     }
230 
231     // allow execute() to be called again
232     d->executing = false;
233 }
234 
235 
236 /*! Returns the dialect used, ie. SMTP, LMTP or SMTP/Submit. */
237 
dialect() const238 SMTP::Dialect SMTP::dialect() const
239 {
240     return d->dialect;
241 }
242 
243 
244 /*! Records that the client claims to be called \a name. \a name isn't
245     used for anything, just logged and recorded in any received fields
246     generated.
247 */
248 
setHeloName(const EString & name)249 void SMTP::setHeloName( const EString & name )
250 {
251     d->heloName = name;
252 }
253 
254 
255 /*! Returns the recorded HELO name, as recorded by setHeloName(). The
256     initial value is an empty string.
257 */
258 
heloName() const259 EString SMTP::heloName() const
260 {
261     return d->heloName;
262 }
263 
264 
265 /*! Resets most transaction variables, so a new mail from/rcpt to/data
266     cycle can begin. Leaves the heloName() untouched, since some
267     clients do not resend helo/ehlo/lhlo.
268 */
269 
reset()270 void SMTP::reset()
271 {
272     if ( d->sieve ||
273          ( d->recipients && !d->recipients->isEmpty() ) ||
274          !d->body.isEmpty() )
275         log( "State reset" );
276     d->sieve = 0;
277     d->recipients = new List<SmtpRcptTo>;
278     d->body.truncate();
279     d->id.truncate();
280     d->now = 0;
281 }
282 
283 
284 /*! Returns a pointer to the Sieve that manages local delivery for
285     this SMTP server.
286 
287 */
288 
sieve() const289 class Sieve * SMTP::sieve() const
290 {
291     if ( !d->sieve ) {
292         Scope x( log() );
293         d->sieve = new Sieve;
294     }
295     return d->sieve;
296 }
297 
298 
299 /*! Returns a pointer to the authenticated user, or a null pointer if
300     the connection is unauthenticated.
301 */
302 
user() const303 class User * SMTP::user() const
304 {
305     return d->user;
306 }
307 
308 
309 /*! Sets this server's authenticated user to \a user. */
310 
authenticated(User * user)311 void SMTP::authenticated( User * user )
312 {
313     d->user = user;
314     if ( !user )
315         return;
316 
317     log( "Authenticated as " + user->login().ascii() );
318 
319     d->permittedAddresses = new List<Address>;
320     d->permittedAddresses->append( d->user->address() );
321 
322     SMTPData::AddressFinder * af
323         = new SMTPData::AddressFinder( d->permittedAddresses );
324     af->q = new Query( "select distinct a.localpart::text, a.domain::text "
325                        "from addresses a "
326                        "join aliases al on (a.id=al.address) "
327                        "join mailboxes mb on (al.mailbox=mb.id) "
328                        "where mb.owner=$1 or mb.id in"
329                        "(select mailbox from permissions "
330                        "where rights ilike '%p%' "
331                        "and (identifier='anyone' or identifier=$2))",
332                        af );
333     af->q->bind( 1, d->user->id() );
334     af->q->bind( 2, d->user->login() );
335     af->q->execute();
336 }
337 
338 
execute()339 void SMTPData::AddressFinder::execute()
340 {
341     Row * r = q->nextRow();
342     while ( r ) {
343         a->append( new Address( "",
344                                 r->getEString( "localpart" ),
345                                 r->getEString( "domain" ) ) );
346         r = q->nextRow();
347     }
348 }
349 
350 
351 /*! Returns a pointer to the list of addresses the currently
352     authenticated User is permitted to use, or a null pointer if the
353     list is not yet known.
354 */
355 
permittedAddresses()356 List<Address> * SMTP::permittedAddresses()
357 {
358     return d->permittedAddresses;
359 }
360 
361 
362 /*! Returns the current input state, which is Command initially. */
363 
inputState() const364 SMTP::InputState SMTP::inputState() const
365 {
366     return d->inputState;
367 }
368 
369 
370 /*! Notifies this SMTP server that its input state is now \a s. If the
371     state is anything other than Command, the SMTP server calls the
372     last SmtpCommand every time there's more input. Eventually, the
373     SmtpCommand has to call setInputState( Command ) again.
374 
375 */
376 
setInputState(InputState s)377 void SMTP::setInputState( InputState s )
378 {
379     d->inputState = s;
380 }
381 
382 
383 /*! Notifies this SMTP server that \a r is a valid rcpt to
384     command. SMTP records that so the LMTP SmtpData command can use
385     the list later.
386 */
387 
addRecipient(SmtpRcptTo * r)388 void SMTP::addRecipient( SmtpRcptTo * r )
389 {
390     log( "Recipient: " + r->address()->lpdomain() );
391     d->recipients->append( r );
392 }
393 
394 
395 /*! Returns a list of all valid SmtpRcptTo commands. This is never a
396     null pointer, but may be an empty list.
397 */
398 
rcptTo() const399 List<SmtpRcptTo> * SMTP::rcptTo() const
400 {
401     return d->recipients;
402 }
403 
404 
405 /*! Records \a b for later recall. reset() clears this. */
406 
setBody(const EString & b)407 void SMTP::setBody( const EString & b )
408 {
409     d->body = b;
410 }
411 
412 
413 /*! Returns what setBody() set. Used for SmtpBdat instances to
414     coordinate the body.
415 */
416 
body() const417 EString SMTP::body() const
418 {
419     return d->body;
420 }
421 
422 
423 /*! Returns true if \a c is the oldest command in the SMTP server's
424     queue of outstanding commands, and false if the queue is empty or
425     there is a command older than \a c in the queue.
426 */
427 
isFirstCommand(SmtpCommand * c) const428 bool SMTP::isFirstCommand( SmtpCommand * c ) const
429 {
430     if ( c == d->commands.firstElement() )
431         return true;
432     return false;
433 }
434 
435 
436 class SMTPSData
437     : public Garbage
438 {
439 public:
SMTPSData()440     SMTPSData() : helper( 0 ) {}
441     EString banner;
442     class SmtpsHelper * helper;
443 };
444 
445 class SmtpsHelper: public EventHandler
446 {
447 public:
SmtpsHelper(SMTPS * connection)448     SmtpsHelper( SMTPS * connection ) : c( connection ) {}
execute()449     void execute() { c->finish(); }
450 
451 private:
452     SMTPS * c;
453 };
454 
455 /*! \class SMTPS smtp.h
456 
457     The SMTPS class implements the old wrapper trick still commonly
458     used on port 465. As befits a hack, it is a bit of a hack, and
459     depends on the ability to empty its writeBuffer().
460 */
461 
462 /*! Constructs an SMTPS server on file descriptor \a s, and starts to
463     negotiate TLS immediately.
464 */
465 
SMTPS(int s)466 SMTPS::SMTPS( int s )
467     : SMTPSubmit( s ), d( new SMTPSData )
468 {
469     EString * tmp = writeBuffer()->removeLine();
470     if ( tmp )
471         d->banner = *tmp;
472     startTls();
473     enqueue( d->banner + "\r\n" );
474 }
475 
476 
477 /*! Handles completion of TLS negotiation and sends the banner. */
478 
finish()479 void SMTPS::finish()
480 {
481 }
482 
483 
484 /*! Uses \a id as transaction id for this message. Reset by rset. Used
485     for debugging.
486 */
487 
setTransactionId(const EString & id)488 void SMTP::setTransactionId( const EString & id )
489 {
490     d->id = id;
491 }
492 
493 
494 /*! Return an ESMTP id, either based on an internal algorithm or on
495     something the client specified using an Archiveopteryx-specific
496     extension.
497 
498     This function returns the same ID even if called several times.
499     Rset resets it.
500 */
501 
transactionId()502 EString SMTP::transactionId()
503 {
504     if ( !d->id.isEmpty() )
505         return d->id;
506 
507     Scope x( log() );
508     d->id = fn( transactionTime()->unixTime() );
509     d->id.append( '-' );
510     d->id.appendNumber( getpid() );
511     d->id.append( '-' );
512     d->id.append( log()->id() );
513     log( "Assigned transaction ID " + d->id );
514     return d->id;
515 }
516 
517 
518 /*! Records the current time, \a now. The rest of the SMTP transaction
519     will be considered to happen at the specified time. Used for
520     debugging, when we want mail to be injected at known times.
521 */
522 
setTransactionTime(class Date * now)523 void SMTP::setTransactionTime( class Date * now )
524 {
525     d->now = now;
526 }
527 
528 
529 /*! Returns the current time and date, except that if you call it
530     more than once for the same object, it returns the same value.
531 */
532 
transactionTime() const533 class Date * SMTP::transactionTime() const
534 {
535     if ( d->now )
536         return d->now;
537 
538     d->now = new Date;
539     d->now->setCurrentTime();
540     return d->now;
541 }
542 
543 
sendChallenge(const EString & s)544 void SMTP::sendChallenge( const EString &s )
545 {
546     enqueue( "334 "+ s +"\r\n" );
547 }
548