E-MailRelay

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

gsaslserverpam.cpp
1 //
2 // Copyright (C) 2001-2018 Graeme Walker <graeme_walker@users.sourceforge.net>
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 // ===
17 //
18 // gsaslserverpam.cpp
19 //
20
21 #include "gdef.h"
22 #include "gpam.h"
23 #include "gsaslserverpam.h"
24 #include "gexception.h"
25 #include "gstr.h"
26 #include "gdebug.h"
27
28 namespace GAuth
29 {
30 class PamImp ;
31 class SaslServerPamImp ;
32 }
33
34 /// \class GAuth::SaslServerPamImp
35 /// A private implementation class used by GAuth::SaslServerPam.
36 ///
37 class GAuth::SaslServerPamImp
38 {
39 public:
40 SaslServerPamImp( bool valid , bool allow_apop ) ;
41 virtual ~SaslServerPamImp() ;
42 bool active() const ;
43 bool init( const std::string & mechanism ) ;
44 std::string apply( const std::string & pwd , bool & done ) ;
45 std::string id() const ;
46 bool authenticated() const ;
47
48 private:
49 SaslServerPamImp( const SaslServerPamImp & ) ;
50 void operator=( const SaslServerPamImp & ) ;
51
52 private:
53 bool m_active ;
54 bool m_allow_apop ;
55 unique_ptr<PamImp> m_pam ;
56 } ;
57
58 /// \class GAuth::PamImp
59 /// A private implementation of the G::Pam interface used by
60 /// GAuth::SaslServerPamImp, which is itself a private implementation
61 /// class used by GAuth::SaslServerPam.
62 ///
63 class GAuth::PamImp : public G::Pam
64 {
65 public:
66 typedef GAuth::PamImp::ItemArray ItemArray ;
67 G_EXCEPTION_CLASS( NoPrompt , "no password prompt received from pam module" ) ;
68
69 PamImp( const std::string & app , const std::string & id ) ;
70 virtual ~PamImp() ;
71 void fail() ;
72 void apply( const std::string & ) ;
73 std::string id() const ;
74
75 protected:
76 virtual void converse( ItemArray & ) override ;
77 virtual void delay( unsigned int usec ) override ;
78
79 private:
80 PamImp( const PamImp & ) ;
81 void operator=( const PamImp & ) ;
82
83 private:
84 std::string m_app ;
85 std::string m_id ;
86 std::string m_pwd ;
87 } ;
88
89 GAuth::PamImp::PamImp( const std::string & app , const std::string & id ) :
90 G::Pam(app,id,true) ,
91 m_app(app) ,
92 m_id(id)
93 {
94 G_DEBUG( "GAuth::PamImp::ctor: [" << app << "] [" << id << "]" ) ;
95 }
96
97 GAuth::PamImp::~PamImp()
98 {
99 }
100
101 std::string GAuth::PamImp::id() const
102 {
103 return m_id ;
104 }
105
106 void GAuth::PamImp::converse( ItemArray & items )
107 {
108 bool done = false ;
109 for( ItemArray::iterator p = items.begin() ; p != items.end() ; ++p )
110 {
111 if( (*p).in_type == "password" )
112 {
113 (*p).out = m_pwd ;
114 (*p).out_defined = true ;
115 done = true ;
116 }
117 }
118 if( !done )
119 {
120 throw NoPrompt() ;
121 }
122 }
123
124 void GAuth::PamImp::apply( const std::string & pwd )
125 {
126 m_pwd = pwd ;
127 authenticate( true ) ; // base class -- calls converse() -- thows on error
128 }
129
130 void GAuth::PamImp::delay( unsigned int )
131 {
132 // TODO asynchronous implementation of pam delay callback
133 // ... but that would require the SaslServer interface be made asynchronous
134 // so the result of the apply() (ie. the next challenge) gets delivered
135 // via a callback -- the complexity trade-off is not compelling
136 }
137
138 // ==
139
140 GAuth::SaslServerPamImp::SaslServerPamImp( bool active , bool allow_apop ) :
141 m_active(active) ,
142 m_allow_apop(allow_apop)
143 {
144 }
145
146 GAuth::SaslServerPamImp::~SaslServerPamImp()
147 {
148 }
149
150 bool GAuth::SaslServerPamImp::active() const
151 {
152 return m_active ;
153 }
154
155 bool GAuth::SaslServerPamImp::init( const std::string & mechanism )
156 {
157 return
158 G::Str::upper(mechanism) == "PLAIN" ||
159 ( m_allow_apop && G::Str::upper(mechanism) == "APOP" ) ;
160 }
161
162 std::string GAuth::SaslServerPamImp::id() const
163 {
164 return m_pam.get() ? m_pam->id() : std::string() ;
165 }
166
167 std::string GAuth::SaslServerPamImp::apply( const std::string & response , bool & done )
168 {
169 // parse the PLAIN response
170 std::string sep( 1U , '\0' ) ;
171 std::string s = G::Str::tail( response , response.find(sep) , std::string() ) ;
172 std::string id = G::Str::head( s , s.find(sep) , std::string() ) ;
173 std::string pwd = G::Str::tail( s , s.find(sep) , std::string() ) ;
174
175 m_pam.reset( new PamImp( "emailrelay" , id ) ) ;
176
177 try
178 {
179 m_pam->apply( pwd ) ;
180 }
181 catch( G::PamError & e )
182 {
183 G_WARNING( "GAuth::SaslServer::apply: " << e.what() ) ;
184 m_pam.reset() ;
185 }
186 catch( PamImp::NoPrompt & e )
187 {
188 G_WARNING( "GAuth::SaslServer::apply: pam error: " << e.what() ) ;
189 m_pam.reset() ;
190 }
191
192 done = true ; // (only single challenge-response supported)
193 return std::string() ; // challenge
194 }
195
196 // ==
197
198 GAuth::SaslServerPam::SaslServerPam( const SaslServerSecrets & secrets , bool allow_apop ) :
199 m_imp(new SaslServerPamImp(secrets.valid(),allow_apop))
200 {
201 }
202
203 GAuth::SaslServerPam::~SaslServerPam()
204 {
205 delete m_imp ;
206 }
207
208 std::string GAuth::SaslServerPam::mechanisms( char ) const
209 {
210 return "PLAIN" ;
211 }
212
213 std::string GAuth::SaslServerPam::mechanism() const
214 {
215 return "PLAIN" ;
216 }
217
218 bool GAuth::SaslServerPam::trusted( const GNet::Address & ) const
219 {
220 return false ;
221 }
222
223 bool GAuth::SaslServerPam::active() const
224 {
225 return m_imp->active() ;
226 }
227
228 bool GAuth::SaslServerPam::mustChallenge() const
229 {
230 return false ;
231 }
232
233 bool GAuth::SaslServerPam::init( const std::string & mechanism )
234 {
235 return m_imp->init( mechanism ) ;
236 }
237
238 std::string GAuth::SaslServerPam::initialChallenge() const
239 {
240 return std::string() ;
241 }
242
243 std::string GAuth::SaslServerPam::apply( const std::string & response , bool & done )
244 {
245 return m_imp->apply( response , done ) ;
246 }
247
248 bool GAuth::SaslServerPam::authenticated() const
249 {
250 return !m_imp->id().empty() ;
251 }
252
253 std::string GAuth::SaslServerPam::id() const
254 {
255 return m_imp->id() ;
256 }
257
258 bool GAuth::SaslServerPam::requiresEncryption() const
259 {
260 return true ;
261 }
262
G::Exception::what
virtual const char * what() const g__noexcept override
Override from std::exception.
Definition: gexception.cpp:65
G::Str::tail
static std::string tail(const std::string &in, size_type pos, const std::string &default_=std::string())
Returns the last part of the string after the given position.
Definition: gstr.cpp:1102
GAuth::SaslServerPam::initialChallenge
virtual std::string initialChallenge() const override
Override from GAuth::SaslServer.
Definition: gsaslserverpam.cpp:238
GAuth::SaslServerPam::id
virtual std::string id() const override
Override from GAuth::SaslServer.
Definition: gsaslserverpam.cpp:253
GAuth::SaslServerPam::init
virtual bool init(const std::string &mechanism) override
Override from GAuth::SaslServer.
Definition: gsaslserverpam.cpp:233
G::Str::head
static std::string head(const std::string &in, size_type pos, const std::string &default_=std::string())
Returns the first part of the string up to just before the given position.
Definition: gstr.cpp:1088
gsaslserverpam.h
GNet::Address
The GNet::Address class encapsulates a TCP/UDP transport address.
Definition: gaddress.h:54
GAuth::SaslServerPam::requiresEncryption
virtual bool requiresEncryption() const override
Override from GAuth::SaslServer.
Definition: gsaslserverpam.cpp:258
GAuth::SaslServerPam::authenticated
virtual bool authenticated() const override
Override from GAuth::SaslServer.
Definition: gsaslserverpam.cpp:248
GAuth::SaslServerPam::active
virtual bool active() const override
Override from GAuth::SaslServer.
Definition: gsaslserverpam.cpp:223
gpam.h
GAuth::SaslServerSecrets
An interface used by GAuth::SaslServer to obtain authentication secrets.
Definition: gsaslserversecrets.h:39
GAuth::SaslServerPam::~SaslServerPam
virtual ~SaslServerPam()
Destructor.
Definition: gsaslserverpam.cpp:203
GAuth::PamImp::delay
virtual void delay(unsigned int usec) override
Called when the pam library wants the application to introduce a delay to prevent brute-force attacks...
Definition: gsaslserverpam.cpp:130
GAuth::SaslServerPam::mechanism
virtual std::string mechanism() const override
Override from GAuth::SaslServer.
Definition: gsaslserverpam.cpp:213
GAuth::PamImp::converse
virtual void converse(ItemArray &) override
Called to pass a message to the user, or request a password etc.
Definition: gsaslserverpam.cpp:106
gstr.h
G
Low-level classes.
Definition: garg.h:29
GAuth::SaslServerPamImp
A private implementation class used by GAuth::SaslServerPam.
Definition: gsaslserverpam.cpp:37
G::Str::upper
static std::string upper(const std::string &s)
Returns a copy of 's' in which all Latin-1 lowercase characters have been replaced by uppercase chara...
Definition: gstr.cpp:619
GAuth::SaslServerPam::apply
virtual std::string apply(const std::string &response, bool &done) override
Override from GAuth::SaslServer.
Definition: gsaslserverpam.cpp:243
gexception.h
GAuth::PamImp
A private implementation of the G::Pam interface used by GAuth::SaslServerPamImp, which is itself a p...
Definition: gsaslserverpam.cpp:63
GAuth::SaslServerPam::SaslServerPam
SaslServerPam(const SaslServerSecrets &, bool allow_apop)
Constructor.
Definition: gsaslserverpam.cpp:198
G::PamError
An exception class used by G::Pam.
Definition: gpamerror.h:36
GAuth::SaslServerPam::trusted
virtual bool trusted(const GNet::Address &) const override
Override from GAuth::SaslServer.
Definition: gsaslserverpam.cpp:218
GAuth::SaslServerPam::mustChallenge
virtual bool mustChallenge() const override
Override from GAuth::SaslServer.
Definition: gsaslserverpam.cpp:228
GAuth::SaslServerPam::mechanisms
virtual std::string mechanisms(char sep= ' ') const override
Override from GAuth::SaslServer.
Definition: gsaslserverpam.cpp:208
GAuth
SASL authentication classes.
Definition: gcram.h:30
gdebug.h
G::Pam
A thin interface to the system PAM library, with two pure virtual methods that derived classes should...
Definition: gpam.h:58