190 lines
4.3 KiB
C++
190 lines
4.3 KiB
C++
//
|
|
// VMime library (http://www.vmime.org)
|
|
// Copyright (C) 2002-2005 Vincent Richard <vincent@vincent-richard.net>
|
|
//
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU General Public License as
|
|
// published by the Free Software Foundation; either version 2 of
|
|
// the License, or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
// General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program; if not, write to the Free Software
|
|
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
//
|
|
|
|
#include <sstream>
|
|
|
|
#include <gsasl.h>
|
|
|
|
#include "vmime/security/sasl/SASLContext.hpp"
|
|
#include "vmime/security/sasl/SASLMechanism.hpp"
|
|
|
|
#include "vmime/base.hpp"
|
|
#include "vmime/encoderFactory.hpp"
|
|
|
|
#include "vmime/utility/stream.hpp"
|
|
|
|
|
|
namespace vmime {
|
|
namespace security {
|
|
namespace sasl {
|
|
|
|
|
|
SASLContext::SASLContext()
|
|
{
|
|
if (gsasl_init(&m_gsaslContext) != GSASL_OK)
|
|
throw std::bad_alloc();
|
|
}
|
|
|
|
|
|
SASLContext::~SASLContext()
|
|
{
|
|
gsasl_done(m_gsaslContext);
|
|
}
|
|
|
|
|
|
ref <SASLSession> SASLContext::createSession
|
|
(const string& serviceName,
|
|
ref <authenticator> auth, ref <SASLMechanism> mech)
|
|
{
|
|
return vmime::create <SASLSession>
|
|
(serviceName, thisRef().dynamicCast <SASLContext>(), auth, mech);
|
|
}
|
|
|
|
|
|
ref <SASLMechanism> SASLContext::createMechanism(const string& name)
|
|
{
|
|
return SASLMechanismFactory::getInstance()->create
|
|
(thisRef().dynamicCast <SASLContext>(), name);
|
|
}
|
|
|
|
|
|
ref <SASLMechanism> SASLContext::suggestMechanism
|
|
(const std::vector <ref <SASLMechanism> >& mechs)
|
|
{
|
|
if (mechs.empty())
|
|
return 0;
|
|
|
|
std::ostringstream oss;
|
|
|
|
for (unsigned int i = 0 ; i < mechs.size() ; ++i)
|
|
oss << mechs[i]->getName() << " ";
|
|
|
|
const string mechList = oss.str();
|
|
const char* suggested = gsasl_client_suggest_mechanism
|
|
(m_gsaslContext, mechList.c_str());
|
|
|
|
if (suggested)
|
|
{
|
|
for (unsigned int i = 0 ; i < mechs.size() ; ++i)
|
|
{
|
|
if (mechs[i]->getName() == suggested)
|
|
return mechs[i];
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
void SASLContext::decodeB64(const string& input, byte** output, int* outputLen)
|
|
{
|
|
string res;
|
|
|
|
utility::inputStreamStringAdapter is(input);
|
|
utility::outputStreamStringAdapter os(res);
|
|
|
|
ref <encoder> dec = encoderFactory::getInstance()->create("base64");
|
|
|
|
dec->decode(is, os);
|
|
|
|
byte* out = new byte[res.length()];
|
|
|
|
std::copy(res.begin(), res.end(), out);
|
|
|
|
*output = out;
|
|
*outputLen = res.length();
|
|
}
|
|
|
|
|
|
const string SASLContext::encodeB64(const byte* input, const int inputLen)
|
|
{
|
|
string res;
|
|
|
|
utility::inputStreamByteBufferAdapter is(input, inputLen);
|
|
utility::outputStreamStringAdapter os(res);
|
|
|
|
ref <encoder> enc = encoderFactory::getInstance()->create("base64");
|
|
|
|
enc->encode(is, os);
|
|
|
|
return res;
|
|
}
|
|
|
|
|
|
const string SASLContext::getErrorMessage(const string& fname, const int code)
|
|
{
|
|
string msg = fname + "() returned ";
|
|
|
|
#define ERROR(x) \
|
|
case x: msg += #x; break;
|
|
|
|
switch (code)
|
|
{
|
|
ERROR(GSASL_NEEDS_MORE)
|
|
ERROR(GSASL_UNKNOWN_MECHANISM)
|
|
ERROR(GSASL_MECHANISM_CALLED_TOO_MANY_TIMES)
|
|
ERROR(GSASL_MALLOC_ERROR)
|
|
ERROR(GSASL_BASE64_ERROR)
|
|
ERROR(GSASL_CRYPTO_ERROR)
|
|
ERROR(GSASL_SASLPREP_ERROR)
|
|
ERROR(GSASL_MECHANISM_PARSE_ERROR)
|
|
ERROR(GSASL_AUTHENTICATION_ERROR)
|
|
ERROR(GSASL_INTEGRITY_ERROR)
|
|
ERROR(GSASL_NO_CLIENT_CODE)
|
|
ERROR(GSASL_NO_SERVER_CODE)
|
|
ERROR(GSASL_NO_CALLBACK)
|
|
ERROR(GSASL_NO_ANONYMOUS_TOKEN)
|
|
ERROR(GSASL_NO_AUTHID)
|
|
ERROR(GSASL_NO_AUTHZID)
|
|
ERROR(GSASL_NO_PASSWORD)
|
|
ERROR(GSASL_NO_PASSCODE)
|
|
ERROR(GSASL_NO_PIN)
|
|
ERROR(GSASL_NO_SERVICE)
|
|
ERROR(GSASL_NO_HOSTNAME)
|
|
ERROR(GSASL_GSSAPI_RELEASE_BUFFER_ERROR)
|
|
ERROR(GSASL_GSSAPI_IMPORT_NAME_ERROR)
|
|
ERROR(GSASL_GSSAPI_INIT_SEC_CONTEXT_ERROR)
|
|
ERROR(GSASL_GSSAPI_ACCEPT_SEC_CONTEXT_ERROR)
|
|
ERROR(GSASL_GSSAPI_UNWRAP_ERROR)
|
|
ERROR(GSASL_GSSAPI_WRAP_ERROR)
|
|
ERROR(GSASL_GSSAPI_ACQUIRE_CRED_ERROR)
|
|
ERROR(GSASL_GSSAPI_DISPLAY_NAME_ERROR)
|
|
ERROR(GSASL_GSSAPI_UNSUPPORTED_PROTECTION_ERROR)
|
|
ERROR(GSASL_KERBEROS_V5_INIT_ERROR)
|
|
ERROR(GSASL_KERBEROS_V5_INTERNAL_ERROR)
|
|
ERROR(GSASL_SECURID_SERVER_NEED_ADDITIONAL_PASSCODE)
|
|
ERROR(GSASL_SECURID_SERVER_NEED_NEW_PIN)
|
|
|
|
default:
|
|
|
|
msg += "unknown error";
|
|
break;
|
|
}
|
|
|
|
#undef ERROR
|
|
|
|
return msg;
|
|
}
|
|
|
|
|
|
} // sasl
|
|
} // security
|
|
} // vmime
|
|
|