vmime/src/security/sasl/SASLContext.cpp
2005-09-17 09:08:45 +00:00

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