in src/qpid/SaslFactory.cpp [245:330]
bool CyrusSasl::start(const std::string& mechanisms, std::string& response, const SecuritySettings* externalSettings)
{
QPID_LOG(debug, "CyrusSasl::start(" << mechanisms << ")");
int result = sasl_client_new(settings.service.c_str(),
settings.host.c_str(),
0, 0, /* Local and remote IP address strings */
callbacks,
0, /* security flags */
&conn);
if (result != SASL_OK) throw InternalErrorException(QPID_MSG("Sasl error: " << sasl_errdetail(conn)));
sasl_security_properties_t secprops;
if (externalSettings) {
sasl_ssf_t external_ssf = (sasl_ssf_t) externalSettings->ssf;
if (external_ssf) {
int result = sasl_setprop(conn, SASL_SSF_EXTERNAL, &external_ssf);
if (result != SASL_OK) {
throw framing::InternalErrorException(QPID_MSG("SASL error: unable to set external SSF: " << result));
}
QPID_LOG(debug, "external SSF detected and set to " << external_ssf);
}
if (externalSettings->authid.size()) {
const char* external_authid = externalSettings->authid.c_str();
result = sasl_setprop(conn, SASL_AUTH_EXTERNAL, external_authid);
if (result != SASL_OK) {
throw framing::InternalErrorException(QPID_MSG("SASL error: unable to set external auth: " << result));
}
QPID_LOG(debug, "external auth detected and set to " << external_authid);
}
}
secprops.min_ssf = settings.minSsf;
secprops.max_ssf = settings.maxSsf;
secprops.maxbufsize = 65535;
QPID_LOG(debug, "min_ssf: " << secprops.min_ssf << ", max_ssf: " << secprops.max_ssf);
secprops.property_names = 0;
secprops.property_values = 0;
secprops.security_flags = 0;//TODO: provide means for application to configure these
result = sasl_setprop(conn, SASL_SEC_PROPS, &secprops);
if (result != SASL_OK) {
throw framing::InternalErrorException(QPID_MSG("SASL error: " << sasl_errdetail(conn)));
}
sasl_interact_t* client_interact = 0;
const char *out = 0;
unsigned outlen = 0;
const char *chosenMechanism = 0;
do {
result = sasl_client_start(conn,
mechanisms.c_str(),
&client_interact,
&out,
&outlen,
&chosenMechanism);
if (result == SASL_INTERACT) {
interact(client_interact);
}
} while (result == SASL_INTERACT);
if (result == SASL_NOMECH) {
if (mechanisms.size()) {
throw qpid::Exception(std::string("Can't authenticate using ") + mechanisms);
} else {
throw qpid::Exception("No mutually acceptable authentication mechanism");
}
} else if (result != SASL_CONTINUE && result != SASL_OK) {
throw InternalErrorException(QPID_MSG("Sasl error: " << sasl_errdetail(conn)));
}
mechanism = std::string(chosenMechanism);
QPID_LOG(debug, "CyrusSasl::start(" << mechanisms << "): selected "
<< mechanism << " response: '" << std::string(out, outlen) << "'");
if (out) {
response = std::string(out, outlen);
return true;
} else {
return false;
}
}