35 const char * login_challenge_1 =
"Username:" ;
36 const char * login_challenge_2 =
"Password:" ;
60 bool init(
const std::string & mechanism ) ;
61 bool validate(
const std::string & secret ,
const std::string & response )
const ;
63 bool trustedCore(
const std::string & ,
const std::string & )
const ;
64 std::string
mechanisms(
const std::string & )
const ;
65 static std::string
cramDigest(
const std::string & secret ,
const std::string & challenge ) ;
66 static std::string
digest(
const std::string & secret ,
const std::string & challenge ) ;
74 m_authenticated(false) ,
75 m_advertise_login(false) ,
76 m_advertise_plain(false) ,
77 m_advertise_cram_md5(false) ,
78 m_advertise_force_one(force_one)
93 if( m_advertise_login ) m.push_back(
"LOGIN" ) ;
94 if( m_advertise_plain ) m.push_back(
"PLAIN" ) ;
95 if( m_advertise_cram_md5 ) m.push_back(
"CRAM-MD5" ) ;
101 m_authenticated = false ;
105 m_challenge.erase() ;
106 m_mechanism.erase() ;
108 if( mechanism ==
"LOGIN" || mechanism ==
"PLAIN" )
110 m_mechanism = mechanism ;
113 else if( mechanism ==
"CRAM-MD5" || mechanism ==
"APOP" )
115 m_mechanism = mechanism ;
116 std::ostringstream ss ;
118 m_challenge = ss.str() ;
132 G_ASSERT( m_mechanism ==
"CRAM-MD5" || m_mechanism ==
"APOP" ) ;
133 bool cram = m_mechanism ==
"CRAM-MD5" ;
134 std::string hash = cram ? cramDigest(secret,m_challenge) : digest(secret,m_challenge) ;
135 ok = response == hash ;
137 catch( std::exception & e )
139 std::string what = e.what() ;
140 G_DEBUG(
"GAuth::SaslServer: exception: " << what ) ;
159 for( G::Strings::iterator p = wc.begin() ; p != wc.end() ; ++p )
168 const std::string & address_to_log )
const
170 G_DEBUG(
"GAuth::SaslServerBasicImp::trustedCore: \"" << secrets_key <<
"\", \"" << address_to_log <<
"\"" ) ;
171 std::string secret = m_secrets.secret(
"NONE",secrets_key) ;
172 bool trusted = ! secret.empty() ;
175 G_LOG(
"GAuth::SaslServer::trusted: trusting \"" << address_to_log <<
"\" "
176 <<
"(matched on NONE/server/" << secrets_key <<
")" ) ;
186 return m_imp->mechanisms( std::string(1U,c) ) ;
191 return m_imp->m_mechanism ;
197 return m_imp->trusted(a) ;
207 return m_imp->m_secrets.valid() ;
217 return m_imp->m_mechanism ==
"CRAM-MD5" || m_imp->m_mechanism ==
"APOP" ;
222 bool rc = m_imp->init( mechanism ) ;
223 G_DEBUG(
"GAuth::SaslServerBasic::init: \"" << mechanism <<
"\" -> \"" << m_imp->m_mechanism <<
"\"" ) ;
229 std::string m = m_imp->m_mechanism ;
231 return login_challenge_1 ;
232 else if( m ==
"PLAIN" )
233 return std::string() ;
235 return m_imp->m_challenge ;
241 std::string next_challenge ;
242 if( m_imp->m_mechanism ==
"CRAM-MD5" || m_imp->m_mechanism ==
"APOP" )
244 G_DEBUG(
"GAuth::SaslServerBasic::apply: response: \"" << response <<
"\"" ) ;
247 if( part_list.size() == 2U )
249 m_imp->m_id = part_list.front() ;
250 std::string response_tail = part_list.back() ;
252 G_DEBUG(
"GAuth::SaslServerBasic::apply: id \"" << m_imp->m_id <<
"\"" ) ;
253 std::string secret = m_imp->m_secrets.secret(m_imp->m_mechanism,m_imp->m_id) ;
256 G_WARNING(
"GAuth::SaslServerBasic::apply: no " << m_imp->m_mechanism
257 <<
" authentication secret available for \"" << m_imp->m_id <<
"\"" ) ;
258 m_imp->m_authenticated = false ;
262 m_imp->m_authenticated = m_imp->validate( secret , response_tail ) ;
267 G_WARNING(
"GAuth::SaslServerBasic::apply: invalid authentication response" ) ;
271 else if( m_imp->m_mechanism ==
"PLAIN" )
274 std::string sep( 1U ,
'\0' ) ;
275 std::string s =
G::Str::tail( response , response.find(sep) , std::string() ) ;
276 std::string
id =
G::Str::head( s , s.find(sep) , std::string() ) ;
277 std::string pwd =
G::Str::tail( s , s.find(sep) , std::string() ) ;
278 std::string secret = m_imp->m_secrets.secret(
"PLAIN",
id).empty() ?
279 m_imp->m_secrets.secret(
"LOGIN",
id) : m_imp->m_secrets.secret(
"PLAIN",
id) ;
282 m_imp->m_authenticated = !
id.empty() && !pwd.empty() && pwd == secret ;
285 else if( m_imp->m_first )
287 G_ASSERT( m_imp->m_mechanism ==
"LOGIN" ) ;
289 m_imp->m_first = false ;
290 m_imp->m_id = response ;
291 if( !m_imp->m_id.empty() )
292 next_challenge = login_challenge_2 ;
296 G_ASSERT( m_imp->m_mechanism ==
"LOGIN" ) ;
297 G_DEBUG(
"GAuth::SaslServerBasic::apply: response: \"[password not logged]\"" ) ;
298 std::string secret = m_imp->m_secrets.secret(m_imp->m_mechanism,m_imp->m_id) ;
299 m_imp->m_first = true ;
300 m_imp->m_authenticated = !response.empty() && response == secret ;
306 G_DEBUG(
"GAuth::SaslServerBasic::apply: challenge \"" << next_challenge <<
"\"" ) ;
309 return next_challenge ;
314 return m_imp->m_authenticated ;
319 return m_imp->m_authenticated ? m_imp->m_id : m_imp->m_trustee ;
G::Strings wildcards() const
Returns an ordered list of wildcard strings that match this address.
virtual std::string mechanism() const
Final override from GAuth::SaslServer.
static EpochTime now()
Returns the current epoch time.
An overload discriminator for G::Md5::hmac()
static std::string printable(const std::string &in, char escape= '\\')
Returns a printable represention of the given input string.
bool validate(const std::string &secret, const std::string &response) const
virtual bool init(const std::string &mechanism)
Final override from GAuth::SaslServer.
virtual ~SaslServerBasic()
Destructor.
std::list< std::string > Strings
A std::list of std::strings.
virtual bool requiresEncryption() const
Final override from GAuth::SaslServer.
The Address class encapsulates an IP transport address.
static std::string fqdn()
Returns the fully-qualified-domain-name.
static void splitIntoTokens(const std::string &in, Strings &out, const std::string &ws)
Splits the string into 'ws'-delimited tokens.
virtual std::string initialChallenge() const
Final override from GAuth::SaslServer.
virtual std::string apply(const std::string &response, bool &done)
Final override from GAuth::SaslServer.
static std::string digest(const std::string &secret, const std::string &challenge)
static std::string tail(const std::string &in, std::string::size_type pos, const std::string &default_=std::string())
Returns the last part of the string after the given position.
SaslServerBasic(const Secrets &, bool ignored, bool force_one_mechanism)
Constructor.
bool init(const std::string &mechanism)
std::string mechanisms(const std::string &) const
bool m_advertise_cram_md5
static std::string hmac(const std::string &key, const std::string &input)
Computes a Hashed Message Authentication Code using MD5 as the hash function.
std::string displayString(bool with_port=true, bool with_scope_id=false) const
Returns a string which represents the address for debugging and diagnostics purposes.
bool m_advertise_force_one
static std::string head(const std::string &in, std::string::size_type pos, const std::string &default_=std::string())
Returns the first part of the string up to just before the given position.
virtual bool authenticated() const
Final override from GAuth::SaslServer.
A private pimple-pattern implementation class used by GAuth::SaslServerBasic.
const SaslServer::Secrets & m_secrets
static std::string digest(const std::string &input)
Creates an MD5 digest.
bool trusted(GNet::Address) const
static std::string cramDigest(const std::string &secret, const std::string &challenge)
virtual std::string id() const
Final override from GAuth::SaslServer.
virtual bool contains(const std::string &mechanism) const =0
SaslServerBasicImp(const SaslServer::Secrets &, bool, bool)
virtual bool mustChallenge() const
Final override from GAuth::SaslServer.
bool trustedCore(const std::string &, const std::string &) const
virtual bool trusted(GNet::Address) const
Final override from GAuth::SaslServer.
An interface used by GAuth::SaslServer to obtain authentication secrets.
virtual std::string mechanisms(char sep= ' ') const
Final override from GAuth::SaslServer.
virtual bool active() const
Final override from GAuth::SaslServer.
static std::string join(const Strings &strings, const std::string &sep)
Concatenates a set of strings.
static std::string printable(const std::string &input)
Converts a binary string into a printable form, using a lowercase hexadecimal encoding.