Merge branch 'master' of ssh://down/oryx/aox
[aox:aox.git] / sasl / saslconnection.cpp
1 // Copyright Oryx Mail Systems GmbH. All enquiries to info@oryx.com, please.
2
3 #include "saslconnection.h"
4
5 #include "user.h"
6 #include "query.h"
7 #include "estring.h"
8 #include "endpoint.h"
9 #include "eventloop.h"
10
11 // time
12 #include <time.h>
13
14
15 /*! \class SaslConnection saslconnection.h
16     A connection that can engage in a SASL negotiation.
17 */
18
19 /*! Creates an Inactive \a type connection using \a fd. */
20
21 SaslConnection::SaslConnection( int fd, Type type )
22     : Connection( fd, type )
23 {
24 }
25
26
27 /*! Obligatory virtual destructor. */
28
29 SaslConnection::~SaslConnection()
30 {
31 }
32
33
34 /*! \fn virtual void SaslConnection::sendChallenge( const EString & s ) = 0
35
36     This virtual function must be defined by SaslConnection subclasses.
37     It is called by a SaslMechanism to send the challenge \a s, and is
38     responsible for enqueue()ing a correctly-encoded version of it.
39 */
40
41
42 /*! Returns a pointer to the authenticated User for this Connection, or
43     0 if a user has not yet been authenticated.
44 */
45
46 User * SaslConnection::user() const
47 {
48     return u;
49 }
50
51
52 /*! Informs this Connection that \a user has been authenticated using
53     the named \a mechanism. After a call to this function, user() will
54     return the specified \a user.
55 */
56
57 void SaslConnection::setUser( User * user, const EString & mechanism )
58 {
59     u = user;
60     m = mechanism;
61     s = (uint)time(0);
62 }
63
64
65 /*! This reimplementation logs the connection in the connections table
66     and cancels any other queries still running.
67
68     If the connection is closed as part of server shutdown, then it's
69     probably too late to execute a new Query. We're tolerant of that.
70 */
71
72 void SaslConnection::close()
73 {
74     if ( state() == Invalid )
75         return;
76
77     Endpoint client = peer();
78     Connection::close();
79
80     Database::cancelQueries( log() );
81
82     if ( !u || client.protocol() == Endpoint::Unix ||
83          !Configuration::toggle( Configuration::Security ) )
84         return;
85
86     Query * q = new Query(
87         "insert into connections "
88         "(userid,address,port,mechanism,authfailures,"
89         "syntaxerrors,started_at,ended_at) "
90         "values ($1,$2,$3,$4,$5,$6,"
91         "$7::interval + 'epoch'::timestamptz,"
92         "$8::interval + 'epoch'::timestamptz)", 0
93     );
94
95     q->bind( 1, u->id() );
96     q->bind( 2, client.address() );
97     q->bind( 3, client.port() );
98     q->bind( 4, m );
99     q->bind( 5, af );
100     q->bind( 6, sf );
101     q->bind( 7, s );
102     q->bind( 8, (uint)time( 0 ) );
103     q->execute();
104 }
105
106
107 /*! Used to count authentication failures for logging and
108     statistics.
109 */
110
111 void SaslConnection::recordAuthenticationFailure()
112 {
113     af++;
114 }
115
116
117 /*! Used to count protocol syntax errors for logging and
118     statistics.
119 */
120
121 void SaslConnection::recordSyntaxError()
122 {
123     sf++;
124 }