* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-#include <map>
-#include <string>
-#include "namespaces.hh"
-#include "dns.hh"
-#include "dnsparser.hh"
-#include "dnspacket.hh"
-#include "dnsrecords.hh"
-#include "logger.hh"
-#include "lock.hh"
-#include "arguments.hh"
-#include <boost/shared_ptr.hpp>
-#include <boost/make_shared.hpp>
#include "gss_context.hh"
+#include "logger.hh"
#ifndef ENABLE_GSS_TSIG
+std::tuple<size_t, size_t, size_t> GssContext::getCounts() { return std::tuple<size_t, size_t, size_t>(0, 0, 0); }
bool GssContext::supported() { return false; }
-GssContext::GssContext() { d_error = GSS_CONTEXT_UNSUPPORTED; d_type = GSS_CONTEXT_NONE; }
-GssContext::GssContext(const DNSName& label) { d_error = GSS_CONTEXT_UNSUPPORTED; d_type = GSS_CONTEXT_NONE; }
-void GssContext::setLocalPrincipal(const std::string& name) {}
-bool GssContext::getLocalPrincipal(std::string& name) { return false; }
-void GssContext::setPeerPrincipal(const std::string& name) {}
-bool GssContext::getPeerPrincipal(std::string& name) { return false; }
-void GssContext::generateLabel(const std::string& suffix) {}
-void GssContext::setLabel(const DNSName& label) {}
-bool GssContext::init(const std::string &input, std::string& output) { return false; }
-bool GssContext::accept(const std::string &input, std::string& output) { return false; }
+GssContext::GssContext() :
+ d_error(GSS_CONTEXT_UNSUPPORTED), d_type(GSS_CONTEXT_NONE) {}
+GssContext::GssContext(const DNSName& /* label */) :
+ d_error(GSS_CONTEXT_UNSUPPORTED), d_type(GSS_CONTEXT_NONE) {}
+void GssContext::setLocalPrincipal(const std::string& /* name */) {}
+bool GssContext::getLocalPrincipal(std::string& /* name */) { return false; }
+void GssContext::setPeerPrincipal(const std::string& /* name */) {}
+bool GssContext::getPeerPrincipal(std::string& /* name */) { return false; }
+void GssContext::generateLabel(const std::string& /* suffix */) {}
+void GssContext::setLabel(const DNSName& /* label */) {}
+bool GssContext::init(const std::string& /* input */, std::string& /* output */) { return false; }
+bool GssContext::accept(const std::string& /* input */, std::string& /* output */) { return false; }
bool GssContext::destroy() { return false; }
bool GssContext::expired() { return false; }
bool GssContext::valid() { return false; }
-bool GssContext::sign(const std::string &input, std::string& output) { return false; }
-bool GssContext::verify(const std::string &input, const std::string &signature) { return false; }
+bool GssContext::sign(const std::string& /* input */, std::string& /* output */) { return false; }
+bool GssContext::verify(const std::string& /* input */, const std::string& /* signature */) { return false; }
GssContextError GssContext::getError() { return GSS_CONTEXT_UNSUPPORTED; }
#else
-class GssCredential : boost::noncopyable {
+#include <unordered_map>
+
+#include "lock.hh"
+
+#define TSIG_GSS_EXPIRE_INTERVAL 60
+
+class GssCredential : boost::noncopyable
+{
public:
- GssCredential(const std::string& name, const gss_cred_usage_t usage) {
+ GssCredential(const std::string& name, const gss_cred_usage_t usage) :
+ d_nameS(name), d_usage(usage)
+ {
gss_buffer_desc buffer;
- d_name = GSS_C_NO_NAME;
- d_nameS = name;
- d_cred = GSS_C_NO_CREDENTIAL;
-
- d_usage = usage;
- d_valid = false;
-
- if (name.empty() == false) {
+
+ if (!name.empty()) {
buffer.length = name.size();
- buffer.value = (void*)name.c_str();
- d_maj = gss_import_name(&d_min, &buffer, (gss_OID)GSS_KRB5_NT_PRINCIPAL_NAME, &d_name);
- if (d_maj != GSS_S_COMPLETE) {
+ buffer.value = const_cast<void*>(static_cast<const void*>(name.c_str()));
+ OM_uint32 min;
+ auto maj = gss_import_name(&min, &buffer, (gss_OID)GSS_KRB5_NT_PRINCIPAL_NAME, &d_name);
+ if (maj != GSS_S_COMPLETE) {
+ d_name = GSS_C_NO_NAME;
d_valid = false;
- return;
+ return;
}
}
renew();
};
- ~GssCredential() {
- OM_uint32 tmp_maj __attribute__((unused)), tmp_min __attribute__((unused));
- if (d_cred != GSS_C_NO_CREDENTIAL)
- tmp_maj = gss_release_cred(&tmp_min, &d_cred);
- if (d_name != GSS_C_NO_NAME)
- tmp_maj = gss_release_name(&tmp_min, &d_name);
+ ~GssCredential()
+ {
+ OM_uint32 tmp_min __attribute__((unused));
+ if (d_cred != GSS_C_NO_CREDENTIAL) {
+ (void)gss_release_cred(&tmp_min, &d_cred);
+ }
+ if (d_name != GSS_C_NO_NAME) {
+ (void)gss_release_name(&tmp_min, &d_name);
+ }
};
- bool expired() const {
- if (d_expires == -1) return false;
- return time((time_t*)NULL)>d_expires;
+ bool expired() const
+ {
+ if (d_expires == -1) {
+ return false;
+ }
+ return time(nullptr) > d_expires;
}
- bool renew() {
- OM_uint32 time_rec, tmp_maj __attribute__((unused)), tmp_min __attribute__((unused));
- d_maj = gss_acquire_cred(&d_min, d_name, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, d_usage, &d_cred, NULL, &time_rec);
+ bool renew()
+ {
+ OM_uint32 time_rec, tmp_maj, tmp_min __attribute__((unused));
+ tmp_maj = gss_acquire_cred(&tmp_min, d_name, GSS_C_INDEFINITE, GSS_C_NO_OID_SET, d_usage, &d_cred, nullptr, &time_rec);
- if (d_maj != GSS_S_COMPLETE) {
+ if (tmp_maj != GSS_S_COMPLETE) {
d_valid = false;
- tmp_maj = gss_release_name(&tmp_min, &d_name);
+ (void)gss_release_name(&tmp_min, &d_name);
d_name = GSS_C_NO_NAME;
return false;
}
d_valid = true;
- if (time_rec > GSS_C_INDEFINITE) {
- d_expires = time((time_t*)NULL)+time_rec;
- } else {
- d_expires = -1;
+ // We do not want forever, but a good time
+ if (time_rec == GSS_C_INDEFINITE) {
+ time_rec = 24 * 60 * 60;
}
+ d_expires = time(nullptr) + time_rec;
return true;
}
- bool valid() {
+ bool valid()
+ {
return d_valid && !expired();
}
- OM_uint32 d_maj,d_min;
-
- bool d_valid;
- int64_t d_expires;
std::string d_nameS;
- gss_name_t d_name;
- gss_cred_id_t d_cred;
gss_cred_usage_t d_usage;
-};
+ gss_name_t d_name{GSS_C_NO_NAME};
+ gss_cred_id_t d_cred{GSS_C_NO_CREDENTIAL};
+ time_t d_expires{time(nullptr) + 60}; // partly initialized will be cleaned up
+ bool d_valid{false};
+}; // GssCredential
-std::map<std::string, boost::shared_ptr<GssCredential> > s_gss_accept_creds;
-std::map<std::string, boost::shared_ptr<GssCredential> > s_gss_init_creds;
+static LockGuarded<std::unordered_map<std::string, std::shared_ptr<GssCredential>>> s_gss_accept_creds;
+static LockGuarded<std::unordered_map<std::string, std::shared_ptr<GssCredential>>> s_gss_init_creds;
-class GssSecContext : boost::noncopyable {
+class GssSecContext : boost::noncopyable
+{
public:
- GssSecContext(boost::shared_ptr<GssCredential> cred) {
- if (cred->valid() == false) throw PDNSException("Invalid credential " + cred->d_nameS);
- d_cred = cred;
- d_state = GssStateInitial;
- d_ctx = GSS_C_NO_CONTEXT;
- d_expires = 0;
- d_maj = d_min = 0;
- d_peer_name = GSS_C_NO_NAME;
- d_type = GSS_CONTEXT_NONE;
- }
-
- ~GssSecContext() {
- OM_uint32 tmp_maj __attribute__((unused)), tmp_min __attribute__((unused));
+ GssSecContext(std::shared_ptr<GssCredential> cred)
+ {
+ if (!cred->valid()) {
+ throw PDNSException("Invalid credential " + cred->d_nameS);
+ }
+ d_cred = std::move(cred);
+ }
+
+ ~GssSecContext()
+ {
+ OM_uint32 tmp_maj __attribute__((unused)), tmp_min __attribute__((unused));
if (d_ctx != GSS_C_NO_CONTEXT) {
tmp_maj = gss_delete_sec_context(&tmp_min, &d_ctx, GSS_C_NO_BUFFER);
}
}
}
- GssContextType d_type;
- gss_ctx_id_t d_ctx;
- gss_name_t d_peer_name;
- int64_t d_expires;
- boost::shared_ptr<GssCredential> d_cred;
- OM_uint32 d_maj,d_min;
+ std::shared_ptr<GssCredential> d_cred;
+ GssContextType d_type{GSS_CONTEXT_NONE};
+ gss_ctx_id_t d_ctx{GSS_C_NO_CONTEXT};
+ gss_name_t d_peer_name{GSS_C_NO_NAME};
+ time_t d_expires{time(nullptr) + 60}; // partly initialized wil be cleaned up
- enum {
+ enum
+ {
GssStateInitial,
GssStateNegotiate,
GssStateComplete,
GssStateError
- } d_state;
-
-};
+ } d_state{GssStateInitial};
+}; // GssSecContext
+
+static LockGuarded<std::unordered_map<DNSName, std::shared_ptr<GssSecContext>>> s_gss_sec_context;
+
+template <typename T>
+static void doExpire(T& m, time_t now)
+{
+ auto lock = m.lock();
+ for (auto i = lock->begin(); i != lock->end();) {
+ if (now > i->second->d_expires) {
+ i = lock->erase(i);
+ }
+ else {
+ ++i;
+ }
+ }
+}
-std::map<DNSName, boost::shared_ptr<GssSecContext> > s_gss_sec_context;
+static void expire()
+{
+ static time_t s_last_expired;
+ time_t now = time(nullptr);
+ if (now - s_last_expired < TSIG_GSS_EXPIRE_INTERVAL) {
+ return;
+ }
+ s_last_expired = now;
+ doExpire(s_gss_init_creds, now);
+ doExpire(s_gss_accept_creds, now);
+ doExpire(s_gss_sec_context, now);
+}
bool GssContext::supported() { return true; }
-void GssContext::initialize() {
+void GssContext::initialize()
+{
d_peerPrincipal = "";
d_localPrincipal = "";
d_error = GSS_CONTEXT_NO_ERROR;
d_type = GSS_CONTEXT_NONE;
-}
+}
-GssContext::GssContext() {
+GssContext::GssContext()
+{
initialize();
generateLabel("pdns.tsig.");
}
-GssContext::GssContext(const DNSName& label) {
+GssContext::GssContext(const DNSName& label)
+{
initialize();
setLabel(label);
}
-void GssContext::generateLabel(const std::string& suffix) {
+void GssContext::generateLabel(const std::string& suffix)
+{
std::ostringstream oss;
- oss << std::hex << time((time_t*)NULL) << "." << suffix;
+ oss << std::hex << time(nullptr) << "." << suffix;
setLabel(DNSName(oss.str()));
}
-void GssContext::setLabel(const DNSName& label) {
+void GssContext::setLabel(const DNSName& label)
+{
d_label = label;
- if (s_gss_sec_context.find(d_label) != s_gss_sec_context.end()) {
- d_ctx = s_gss_sec_context[d_label];
- d_type = d_ctx->d_type;
+ auto lock = s_gss_sec_context.lock();
+ auto it = lock->find(d_label);
+ if (it != lock->end()) {
+ d_secctx = it->second;
+ d_type = d_secctx->d_type;
}
}
-bool GssContext::expired() {
- return (!d_ctx || (d_ctx->d_expires > -1 && d_ctx->d_expires < time((time_t*)NULL)));
+bool GssContext::expired()
+{
+ return (!d_secctx || (d_secctx->d_expires > -1 && d_secctx->d_expires < time(nullptr)));
}
-bool GssContext::valid() {
- return (d_ctx && !expired() && d_ctx->d_state == GssSecContext::GssStateComplete);
+bool GssContext::valid()
+{
+ return (d_secctx && !expired() && d_secctx->d_state == GssSecContext::GssStateComplete);
}
-bool GssContext::init(const std::string &input, std::string& output) {
- OM_uint32 tmp_maj __attribute__((unused)), tmp_min __attribute__((unused));
- OM_uint32 maj,min;
+bool GssContext::init(const std::string& input, std::string& output)
+{
+ expire();
+
+ OM_uint32 tmp_maj __attribute__((unused)), tmp_min __attribute__((unused));
+ OM_uint32 maj, min;
gss_buffer_desc recv_tok, send_tok, buffer;
OM_uint32 flags;
OM_uint32 expires;
- boost::shared_ptr<GssCredential> cred;
if (d_label.empty()) {
d_error = GSS_CONTEXT_INVALID;
return false;
}
d_type = GSS_CONTEXT_INIT;
-
- if (s_gss_init_creds.find(d_localPrincipal) != s_gss_init_creds.end()) {
- cred = s_gss_init_creds[d_localPrincipal];
- } else {
- s_gss_init_creds[d_localPrincipal] = boost::make_shared<GssCredential>(d_localPrincipal, GSS_C_INITIATE);
- cred = s_gss_init_creds[d_localPrincipal];
+ std::shared_ptr<GssCredential> cred;
+ {
+ auto lock = s_gss_init_creds.lock();
+ auto it = lock->find(d_localPrincipal);
+ if (it == lock->end()) {
+ it = lock->emplace(d_localPrincipal, std::make_shared<GssCredential>(d_localPrincipal, GSS_C_INITIATE)).first;
+ }
+ cred = it->second;
}
// see if we can find a context in non-completed state
- if (d_ctx) {
- if (d_ctx->d_state != GssSecContext::GssStateNegotiate) {
+ if (d_secctx) {
+ if (d_secctx->d_state != GssSecContext::GssStateNegotiate) {
d_error = GSS_CONTEXT_INVALID;
return false;
}
- } else {
+ }
+ else {
// make context
- s_gss_sec_context[d_label] = boost::make_shared<GssSecContext>(cred);
- s_gss_sec_context[d_label]->d_type = d_type;
- d_ctx = s_gss_sec_context[d_label];
- d_ctx->d_state = GssSecContext::GssStateNegotiate;
+ auto lock = s_gss_sec_context.lock();
+ d_secctx = std::make_shared<GssSecContext>(cred);
+ d_secctx->d_state = GssSecContext::GssStateNegotiate;
+ d_secctx->d_type = d_type;
+ (*lock)[d_label] = d_secctx;
}
recv_tok.length = input.size();
- recv_tok.value = (void*)input.c_str();
+ recv_tok.value = const_cast<void*>(static_cast<const void*>(input.c_str()));
- if (d_peerPrincipal.empty() == false) {
- buffer.value = (void*)d_peerPrincipal.c_str();
+ if (!d_peerPrincipal.empty()) {
+ buffer.value = const_cast<void*>(static_cast<const void*>(d_peerPrincipal.c_str()));
buffer.length = d_peerPrincipal.size();
- maj = gss_import_name(&min, &buffer, (gss_OID)GSS_KRB5_NT_PRINCIPAL_NAME, &(d_ctx->d_peer_name));
+ maj = gss_import_name(&min, &buffer, (gss_OID)GSS_KRB5_NT_PRINCIPAL_NAME, &(d_secctx->d_peer_name));
if (maj != GSS_S_COMPLETE) {
processError("gss_import_name", maj, min);
return false;
}
}
- maj = gss_init_sec_context(&min, cred->d_cred, &(d_ctx->d_ctx), d_ctx->d_peer_name, GSS_C_NO_OID, GSS_C_MUTUAL_FLAG|GSS_C_REPLAY_FLAG, GSS_C_INDEFINITE, GSS_C_NO_CHANNEL_BINDINGS, &recv_tok, NULL, &send_tok, &flags, &expires);
+ maj = gss_init_sec_context(&min, cred->d_cred, &d_secctx->d_ctx, d_secctx->d_peer_name, GSS_C_NO_OID, GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG, GSS_C_INDEFINITE, GSS_C_NO_CHANNEL_BINDINGS, &recv_tok, nullptr, &send_tok, &flags, &expires);
- if (send_tok.length>0) {
- output.assign((const char*)send_tok.value, send_tok.length);
+ if (send_tok.length > 0) {
+ output.assign(static_cast<char*>(send_tok.value), send_tok.length);
tmp_maj = gss_release_buffer(&tmp_min, &send_tok);
}
if (maj == GSS_S_COMPLETE) {
- if (expires > GSS_C_INDEFINITE) {
- d_ctx->d_expires = time((time_t*)NULL) + expires;
- } else {
- d_ctx->d_expires = -1;
+ // We do not want forever
+ if (expires == GSS_C_INDEFINITE) {
+ expires = 60;
}
- d_ctx->d_state = GssSecContext::GssStateComplete;
+ d_secctx->d_expires = time(nullptr) + expires;
+ d_secctx->d_state = GssSecContext::GssStateComplete;
return true;
- } else if (maj != GSS_S_CONTINUE_NEEDED) {
- processError("gss_init_sec_context", maj,min);
+ }
+ else if (maj != GSS_S_CONTINUE_NEEDED) {
+ processError("gss_init_sec_context", maj, min);
}
return (maj == GSS_S_CONTINUE_NEEDED);
}
-bool GssContext::accept(const std::string &input, std::string& output) {
- OM_uint32 tmp_maj __attribute__((unused)), tmp_min __attribute__((unused));
- OM_uint32 maj,min;
+bool GssContext::accept(const std::string& input, std::string& output)
+{
+ expire();
+
+ OM_uint32 tmp_maj __attribute__((unused)), tmp_min __attribute__((unused));
+ OM_uint32 maj, min;
gss_buffer_desc recv_tok, send_tok;
OM_uint32 flags;
OM_uint32 expires;
- boost::shared_ptr<GssCredential> cred;
if (d_label.empty()) {
d_error = GSS_CONTEXT_INVALID;
return false;
}
d_type = GSS_CONTEXT_ACCEPT;
-
- if (s_gss_accept_creds.find(d_localPrincipal) != s_gss_accept_creds.end()) {
- cred = s_gss_accept_creds[d_localPrincipal];
- } else {
- s_gss_accept_creds[d_localPrincipal] = boost::make_shared<GssCredential>(d_localPrincipal, GSS_C_ACCEPT);
- cred = s_gss_accept_creds[d_localPrincipal];
+ std::shared_ptr<GssCredential> cred;
+ {
+ auto lock = s_gss_accept_creds.lock();
+ auto it = lock->find(d_localPrincipal);
+ if (it == lock->end()) {
+ it = lock->emplace(d_localPrincipal, std::make_shared<GssCredential>(d_localPrincipal, GSS_C_ACCEPT)).first;
+ }
+ cred = it->second;
}
// see if we can find a context in non-completed state
- if (d_ctx) {
- if (d_ctx->d_state != GssSecContext::GssStateNegotiate) {
+ if (d_secctx) {
+ if (d_secctx->d_state != GssSecContext::GssStateNegotiate) {
d_error = GSS_CONTEXT_INVALID;
return false;
- }
- } else {
+ }
+ }
+ else {
// make context
- s_gss_sec_context[d_label] = boost::make_shared<GssSecContext>(cred);
- s_gss_sec_context[d_label]->d_type = d_type;
- d_ctx = s_gss_sec_context[d_label];
- d_ctx->d_state = GssSecContext::GssStateNegotiate;
+ auto lock = s_gss_sec_context.lock();
+ d_secctx = std::make_shared<GssSecContext>(cred);
+ d_secctx->d_state = GssSecContext::GssStateNegotiate;
+ d_secctx->d_type = d_type;
+ (*lock)[d_label] = d_secctx;
}
recv_tok.length = input.size();
- recv_tok.value = (void*)input.c_str();
+ recv_tok.value = const_cast<void*>(static_cast<const void*>(input.c_str()));
- maj = gss_accept_sec_context(&min, &(d_ctx->d_ctx), cred->d_cred, &recv_tok, GSS_C_NO_CHANNEL_BINDINGS, &(d_ctx->d_peer_name), NULL, &send_tok, &flags, &expires, NULL);
+ maj = gss_accept_sec_context(&min, &d_secctx->d_ctx, cred->d_cred, &recv_tok, GSS_C_NO_CHANNEL_BINDINGS, &d_secctx->d_peer_name, nullptr, &send_tok, &flags, &expires, nullptr);
- if (send_tok.length>0) {
- output.assign((const char*)send_tok.value, send_tok.length);
+ if (send_tok.length > 0) {
+ output.assign(static_cast<char*>(send_tok.value), send_tok.length);
tmp_maj = gss_release_buffer(&tmp_min, &send_tok);
}
if (maj == GSS_S_COMPLETE) {
- if (expires > GSS_C_INDEFINITE) {
- d_ctx->d_expires = time((time_t*)NULL) + expires;
- } else {
- d_ctx->d_expires = -1;
+ // We do not want forever
+ if (expires == GSS_C_INDEFINITE) {
+ expires = 60;
}
- d_ctx->d_state = GssSecContext::GssStateComplete;
+ d_secctx->d_expires = time(nullptr) + expires;
+ d_secctx->d_state = GssSecContext::GssStateComplete;
return true;
- } else if (maj != GSS_S_CONTINUE_NEEDED) {
- processError("gss_accept_sec_context", maj,min);
+ }
+ else if (maj != GSS_S_CONTINUE_NEEDED) {
+ processError("gss_accept_sec_context", maj, min);
}
return (maj == GSS_S_CONTINUE_NEEDED);
};
-bool GssContext::sign(const std::string& input, std::string& output) {
- OM_uint32 tmp_maj __attribute__((unused)), tmp_min __attribute__((unused));
- OM_uint32 maj,min;
+bool GssContext::sign(const std::string& input, std::string& output)
+{
+ OM_uint32 tmp_maj __attribute__((unused)), tmp_min __attribute__((unused));
+ OM_uint32 maj, min;
gss_buffer_desc recv_tok = GSS_C_EMPTY_BUFFER;
gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
recv_tok.length = input.size();
- recv_tok.value = (void*)input.c_str();
+ recv_tok.value = const_cast<void*>(static_cast<const void*>(input.c_str()));
- maj = gss_get_mic(&min, d_ctx->d_ctx, GSS_C_QOP_DEFAULT, &recv_tok, &send_tok);
+ maj = gss_get_mic(&min, d_secctx->d_ctx, GSS_C_QOP_DEFAULT, &recv_tok, &send_tok);
- if (send_tok.length>0) {
- output.assign((const char*)send_tok.value, send_tok.length);
+ if (send_tok.length > 0) {
+ output.assign(static_cast<char*>(send_tok.value), send_tok.length);
tmp_maj = gss_release_buffer(&tmp_min, &send_tok);
}
if (maj != GSS_S_COMPLETE) {
- processError("gss_get_mic", maj,min);
+ processError("gss_get_mic", maj, min);
}
return (maj == GSS_S_COMPLETE);
}
-bool GssContext::verify(const std::string& input, const std::string& signature) {
- OM_uint32 maj,min;
+bool GssContext::verify(const std::string& input, const std::string& signature)
+{
+ OM_uint32 maj, min;
gss_buffer_desc recv_tok = GSS_C_EMPTY_BUFFER;
gss_buffer_desc sign_tok = GSS_C_EMPTY_BUFFER;
recv_tok.length = input.size();
- recv_tok.value = (void*)input.c_str();
+ recv_tok.value = const_cast<void*>(static_cast<const void*>(input.c_str()));
sign_tok.length = signature.size();
- sign_tok.value = (void*)signature.c_str();
+ sign_tok.value = const_cast<void*>(static_cast<const void*>(signature.c_str()));
- maj = gss_verify_mic(&min, d_ctx->d_ctx, &recv_tok, &sign_tok, NULL);
+ maj = gss_verify_mic(&min, d_secctx->d_ctx, &recv_tok, &sign_tok, nullptr);
if (maj != GSS_S_COMPLETE) {
- processError("gss_get_mic", maj,min);
+ processError("gss_get_mic", maj, min);
}
return (maj == GSS_S_COMPLETE);
}
-bool GssContext::destroy() {
- return false;
+bool GssContext::destroy()
+{
+ if (d_label.empty()) {
+ return false;
+ }
+ auto lock = s_gss_sec_context.lock();
+ return lock->erase(d_label) == 1;
}
-void GssContext::setLocalPrincipal(const std::string& name) {
+void GssContext::setLocalPrincipal(const std::string& name)
+{
d_localPrincipal = name;
}
-bool GssContext::getLocalPrincipal(std::string& name) {
+bool GssContext::getLocalPrincipal(std::string& name)
+{
name = d_localPrincipal;
- return name.size()>0;
+ return name.size() > 0;
}
-void GssContext::setPeerPrincipal(const std::string& name) {
+void GssContext::setPeerPrincipal(const std::string& name)
+{
d_peerPrincipal = name;
}
-bool GssContext::getPeerPrincipal(std::string& name) {
+bool GssContext::getPeerPrincipal(std::string& name)
+{
gss_buffer_desc value;
- OM_uint32 maj,min;
+ OM_uint32 maj, min;
- if (d_ctx->d_peer_name != GSS_C_NO_NAME) {
- maj = gss_display_name(&min, d_ctx->d_peer_name, &value, NULL);
+ if (d_secctx->d_peer_name != GSS_C_NO_NAME) {
+ maj = gss_display_name(&min, d_secctx->d_peer_name, &value, nullptr);
if (maj == GSS_S_COMPLETE && value.length > 0) {
- name.assign((const char*)value.value, value.length);
+ name.assign(static_cast<char*>(value.value), value.length);
maj = gss_release_buffer(&min, &value);
return true;
- } else {
+ }
+ else {
return false;
}
- } else {
+ }
+ else {
return false;
}
}
-void GssContext::processError(const std::string& method, OM_uint32 maj, OM_uint32 min) {
- OM_uint32 tmp_min;
- gss_buffer_desc msg;
- OM_uint32 msg_ctx;
-
- msg_ctx = 0;
- while (1) {
- ostringstream oss;
- gss_display_status(&tmp_min, maj, GSS_C_GSS_CODE, GSS_C_NULL_OID, &msg_ctx, &msg);
- oss << method << ": " << (char*)msg.value;
- d_gss_errors.push_back(oss.str());
- if (!msg_ctx) break;
- }
- msg_ctx = 0;
- while (1) {
- ostringstream oss;
- gss_display_status(&tmp_min, min, GSS_C_MECH_CODE, GSS_C_NULL_OID, &msg_ctx, &msg);
- oss << method << ": " << (char*)msg.value;
- d_gss_errors.push_back(oss.str());
- if (!msg_ctx) break;
- }
+std::tuple<size_t, size_t, size_t> GssContext::getCounts()
+{
+ return {s_gss_init_creds.lock()->size(), s_gss_accept_creds.lock()->size(), s_gss_sec_context.lock()->size()};
+}
+
+void GssContext::processError(const std::string& method, OM_uint32 maj, OM_uint32 min)
+{
+ OM_uint32 tmp_min;
+ gss_buffer_desc msg;
+ OM_uint32 msg_ctx;
+
+ msg_ctx = 0;
+ while (1) {
+ ostringstream oss;
+ if (gss_display_status(&tmp_min, maj, GSS_C_GSS_CODE, GSS_C_NULL_OID, &msg_ctx, &msg) == GSS_S_COMPLETE) {
+ oss << method << ": " << msg.value;
+ }
+ else {
+ oss << method << ": ?";
+ }
+ if (msg.length != 0) {
+ gss_release_buffer(&tmp_min, &msg);
+ }
+ d_gss_errors.push_back(oss.str());
+ if (!msg_ctx)
+ break;
+ }
+ msg_ctx = 0;
+ while (1) {
+ ostringstream oss;
+ if (gss_display_status(&tmp_min, min, GSS_C_MECH_CODE, GSS_C_NULL_OID, &msg_ctx, &msg) == GSS_S_COMPLETE) {
+ oss << method << ": " << msg.value;
+ }
+ else {
+ oss << method << ": ?";
+ }
+ if (msg.length != 0) {
+ gss_release_buffer(&tmp_min, &msg);
+ }
+ d_gss_errors.push_back(oss.str());
+ if (!msg_ctx)
+ break;
+ }
}
#endif
-bool gss_add_signature(const DNSName& context, const std::string& message, std::string& mac) {
+bool gss_add_signature(const DNSName& context, const std::string& message, std::string& mac)
+{
string tmp_mac;
GssContext gssctx(context);
if (!gssctx.valid()) {
- L<<Logger::Error<<"GSS context '"<<context<<"' is not valid"<<endl;
- for(const string& error : gssctx.getErrorStrings()) {
- L<<Logger::Error<<"GSS error: "<<error<<endl;;
+ g_log << Logger::Error << "GSS context '" << context << "' is not valid" << endl;
+ for (const string& error : gssctx.getErrorStrings()) {
+ g_log << Logger::Error << "GSS error: " << error << endl;
+ ;
}
return false;
}
if (!gssctx.sign(message, tmp_mac)) {
- L<<Logger::Error<<"Could not sign message using GSS context '"<<context<<"'"<<endl;
- for(const string& error : gssctx.getErrorStrings()) {
- L<<Logger::Error<<"GSS error: "<<error<<endl;;
+ g_log << Logger::Error << "Could not sign message using GSS context '" << context << "'" << endl;
+ for (const string& error : gssctx.getErrorStrings()) {
+ g_log << Logger::Error << "GSS error: " << error << endl;
+ ;
}
return false;
}
- mac = tmp_mac;
+ mac = std::move(tmp_mac);
return true;
}
-bool gss_verify_signature(const DNSName& context, const std::string& message, const std::string& mac) {
+bool gss_verify_signature(const DNSName& context, const std::string& message, const std::string& mac)
+{
GssContext gssctx(context);
if (!gssctx.valid()) {
- L<<Logger::Error<<"GSS context '"<<context<<"' is not valid"<<endl;
- for(const string& error : gssctx.getErrorStrings()) {
- L<<Logger::Error<<"GSS error: "<<error<<endl;;
+ g_log << Logger::Error << "GSS context '" << context << "' is not valid" << endl;
+ for (const string& error : gssctx.getErrorStrings()) {
+ g_log << Logger::Error << "GSS error: " << error << endl;
+ ;
}
return false;
}
if (!gssctx.verify(message, mac)) {
- L<<Logger::Error<<"Could not verify message using GSS context '"<<context<<"'"<<endl;
- for(const string& error : gssctx.getErrorStrings()) {
- L<<Logger::Error<<"GSS error: "<<error<<endl;;
+ g_log << Logger::Error << "Could not verify message using GSS context '" << context << "'" << endl;
+ for (const string& error : gssctx.getErrorStrings()) {
+ g_log << Logger::Error << "GSS error: " << error << endl;
+ ;
}
return false;
}