33 const char * login_challenge_1 =
"Username:" ;
34 const char * login_challenge_2 =
"Password:" ;
46 const std::string & challenge ,
bool cram ,
bool & error ) ;
47 static std::string
digest(
const std::string & secret ,
const std::string & challenge ) ;
48 static std::string
cramDigest(
const std::string & secret ,
const std::string & challenge ) ;
59 const std::string & challenge ,
bool cram ,
bool & error )
63 G_DEBUG(
"GAuth::SaslClientImp::clientResponse: challenge=\"" << challenge <<
"\"" ) ;
64 return cram ? cramDigest(secret,challenge) : digest(secret,challenge) ;
66 catch( std::exception & e )
68 std::string what = e.what() ;
69 G_DEBUG(
"GAuth::SaslClient: " << what ) ;
72 return std::string() ;
90 G_IGNORE_PARAMETER(std::string,server_name) ;
91 G_DEBUG(
"GAuth::SaslClient::ctor: server-name=\"" << server_name <<
"\", active=" <<
active() ) ;
101 return m_imp->m_secrets.valid() ;
105 bool & error ,
bool & sensitive )
const
111 std::string auth(
"AUTH") ;
112 std::string sep(
" ") ;
115 if( mechanism ==
"XOAUTH2" )
117 std::string secret = m_imp->m_secrets.secret(mechanism) ;
118 rsp = auth + sep + mechanism + sep + secret ;
119 error = secret.empty() ;
125 rsp = auth + sep + mechanism ;
132 bool & done ,
bool & error ,
bool & sensitive )
const
139 if( mechanism ==
"CRAM-MD5" || mechanism ==
"APOP" )
141 const bool cram = mechanism ==
"CRAM-MD5" ;
142 std::string
id = m_imp->m_secrets.id(mechanism) ;
143 std::string secret = m_imp->m_secrets.secret(mechanism) ;
144 error =
id.empty() || secret.empty() ;
150 else if( mechanism ==
"PLAIN" )
152 std::string sep( 1U ,
'\0' ) ;
153 std::string
id = m_imp->m_secrets.id(mechanism) ;
154 std::string secret = m_imp->m_secrets.secret(mechanism) ;
155 rsp = sep +
id + sep + secret ;
156 error =
id.empty() || secret.empty() ;
160 else if( mechanism ==
"LOGIN" )
162 if( challenge == login_challenge_1 )
164 rsp = m_imp->m_secrets.id(mechanism) ;
165 error = rsp.empty() ;
168 else if( challenge == login_challenge_2 )
170 rsp = m_imp->m_secrets.secret(mechanism) ;
171 error = rsp.empty() ;
187 G_WARNING(
"GAuth::SaslClient: invalid challenge" ) ;
196 G_DEBUG(
"GAuth::SaslClient::preferred: server's mechanisms: [" <<
G::Str::join(mechanism_list,
",") <<
"]" ) ;
201 return std::string() ;
203 const std::string login(
"LOGIN" ) ;
204 const std::string plain(
"PLAIN" ) ;
205 const std::string xoauth2(
"XOAUTH2" ) ;
206 const std::string cram(
"CRAM-MD5" ) ;
209 std::set<std::string> them ;
210 for( G::Strings::const_iterator p = mechanism_list.begin() ; p != mechanism_list.end() ; ++p )
214 std::set<std::string> us ;
215 if( !m_imp->m_secrets.id(login).empty() ) us.insert(login) ;
216 if( !m_imp->m_secrets.id(plain).empty() ) us.insert(plain) ;
217 if( !m_imp->m_secrets.id(xoauth2).empty() ) us.insert(xoauth2) ;
218 if( !m_imp->m_secrets.id(cram).empty() ) us.insert(cram) ;
221 std::set<std::string> both ;
222 std::set_intersection( them.begin() , them.end() , us.begin() , us.end() , std::inserter(both,both.end()) ) ;
226 if( m.empty() && both.find(cram) != both.end() ) m = cram ;
227 if( m.empty() && both.find(xoauth2) != both.end() ) m = xoauth2 ;
228 if( m.empty() && both.find(plain) != both.end() ) m = plain ;
229 if( m.empty() && both.find(login) != both.end() ) m = login ;
230 G_DEBUG(
"GAuth::SaslClient::preferred: we prefer \"" << m <<
"\"" ) ;
An overload discriminator for G::Md5::hmac()
std::string preferred(const G::Strings &mechanisms) const
Returns the name of the preferred mechanism taken from the given set.
static std::string digest(const std::string &secret, const std::string &challenge)
std::string response(const std::string &mechanism, const std::string &challenge, bool &done, bool &error, bool &sensitive) const
Returns a response to the given challenge.
std::list< std::string > Strings
A std::list of std::strings.
SaslClientImp(const SaslClient::Secrets &)
SaslClient(const Secrets &secrets, const std::string &server_name)
Constructor. The secrets reference is kept.
bool active() const
Returns true if the constructor's secrets object is valid.
static std::string hmac(const std::string &key, const std::string &input)
Computes a Hashed Message Authentication Code using MD5 as the hash function.
A private pimple-pattern implementation class used by GAuth::SaslClient.
An interface used by GAuth::SaslClient to obtain authentication secrets.
static std::string cramDigest(const std::string &secret, const std::string &challenge)
static std::string upper(const std::string &s)
Returns a copy of 's' in which all lowercase characters have been replaced by uppercase characters...
static std::string digest(const std::string &input)
Creates an MD5 digest.
const SaslClient::Secrets & m_secrets
static std::string clientResponse(const std::string &secret, const std::string &challenge, bool cram, bool &error)
std::string initial_response(const std::string &mechanism, bool &done, bool &error, bool &sensitive) const
Returns an initial_response for authentication.
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.