Back to index

nordugrid-arc-nox  1.1.0~rc6
Public Member Functions | Protected Member Functions | Protected Attributes | Private Member Functions | Private Attributes | Static Private Attributes
Arc::MCC_GSI_Client Class Reference

#include <MCCGSI.h>

Inheritance diagram for Arc::MCC_GSI_Client:
Inheritance graph
[legend]
Collaboration diagram for Arc::MCC_GSI_Client:
Collaboration graph
[legend]

List of all members.

Public Member Functions

 MCC_GSI_Client (Config &cfg, ModuleManager &mm)
virtual ~MCC_GSI_Client ()
virtual MCC_Status process (Message &, Message &)
 Dummy Message processing method.
virtual void Next (MCCInterface *next, const std::string &label="")
 Add reference to next MCC in chain.
virtual void AddSecHandler (Config *cfg, ArcSec::SecHandler *sechandler, const std::string &label="")
 Add security components/handlers to this MCC.
virtual void Unlink ()
 Removing all links.

Protected Member Functions

MCCInterfaceNext (const std::string &label="")
bool ProcessSecHandlers (Message &message, const std::string &label="") const
 Executes security handlers of specified queue.

Protected Attributes

std::map< std::string,
MCCInterface * > 
next_
 Set of labeled "next" components.
std::map< std::string,
std::list< ArcSec::SecHandler * > > 
sechandlers_
 Set of labeled authentication and authorization handlers.

Private Member Functions

MCC_Status InitContext ()

Private Attributes

gss_ctx_id_t ctx
std::string proxyPath
std::string certificatePath
std::string keyPath

Static Private Attributes

static Logger logger
 A logger for MCCs.

Detailed Description

Definition at line 28 of file MCCGSI.h.


Constructor & Destructor Documentation

Definition at line 291 of file MCCGSI.cpp.

    : MCC(&cfg),
      ctx(GSS_C_NO_CONTEXT) {
    //globus_module_activate(GLOBUS_GSI_GSSAPI_MODULE);
    globus_openldap_lock(mm);
    //if (!proxy_initialized)
    //  proxy_initialized = GlobusRecoverProxyOpenSSL();
    proxyPath = (std::string)cfg["ProxyPath"];
    certificatePath = (std::string)cfg["CertificatePath"];
    keyPath = (std::string)cfg["KeyPath"];
  }

Here is the call graph for this function:

Definition at line 303 of file MCCGSI.cpp.

                                  {
    if (ctx != GSS_C_NO_CONTEXT) {
      OM_uint32 majstat, minstat;
      majstat = gss_delete_sec_context(&minstat, &ctx, GSS_C_NO_BUFFER);
      ctx = GSS_C_NO_CONTEXT;
    }
    //globus_module_deactivate(GLOBUS_GSI_GSSAPI_MODULE);
  }

Member Function Documentation

void Arc::MCC::AddSecHandler ( Config cfg,
ArcSec::SecHandler sechandler,
const std::string &  label = "" 
) [virtual, inherited]

Add security components/handlers to this MCC.

Security handlers are stacked into a few queues with each queue identified by its label. The queue labelled 'incoming' is executed for every 'request' message after the message is processed by the MCC on the service side and before processing on the client side. The queue labelled 'outgoing' is run for response message before it is processed by MCC algorithms on the service side and after processing on the client side. Those labels are just a matter of agreement and some MCCs may implement different queues executed at various message processing steps.

Definition at line 35 of file MCC.cpp.

                                {
    if (sechandler) {
      sechandlers_[label].push_back(sechandler);
      // need polishing to put the SecHandlerFactory->getinstance here
      XMLNode cn = (*cfg)["SecHandler"];
      Config cfg_(cn);
    }
  }

Here is the caller graph for this function:

Definition at line 402 of file MCCGSI.cpp.

                                         {

    // Send empty payload in order to get access to message attributes
    MessageAttributes reqattr;
    MessageAttributes repattr;
    Message reqmsg;
    Message repmsg;
    MessageContext context;

    reqmsg.Attributes(&reqattr);
    reqmsg.Context(&context);
    repmsg.Attributes(&repattr);
    repmsg.Context(&context);

    PayloadRaw request;
    reqmsg.Payload(&request);

    MCC_Status status = MCC::Next()->process(reqmsg, repmsg);

    std::string remoteip = repmsg.Attributes()->get("TCP:REMOTEHOST");

    sockaddr_in sa;
    sa.sin_family = AF_INET;
    inet_pton(AF_INET, remoteip.c_str(), &sa.sin_addr);

    char host[NI_MAXHOST];
    memset(host,0,NI_MAXHOST);
    if(getnameinfo((sockaddr*)&sa, sizeof(sa), host, NI_MAXHOST, NULL, 0,
                NI_NAMEREQD)) {
      struct hostent* hp;
#ifndef WIN32
      hp = gethostbyaddr((void*)(&(sa.sin_addr.s_addr)), sizeof(sa.sin_addr.s_addr), AF_INET);
#else
      hp = gethostbyaddr((char*)(&(sa.sin_addr.s_addr)), sizeof(sa.sin_addr.s_addr), AF_INET);
#endif
      if(hp == NULL) {
        logger.msg(ERROR, "Could not resolve peer side's hostname");
        return MCC_Status();
      }
      std::string tmp(hp->h_name);
      memcpy(host, tmp.c_str(), tmp.length()); 
   }

    OM_uint32 majstat, minstat;

    GSSCredential cred(proxyPath, certificatePath, keyPath);

    gss_name_t target_name = GSS_C_NO_NAME;

    gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc recv_tok = GSS_C_EMPTY_BUFFER;

    OM_uint32 req_flags;
    OM_uint32 ret_flags;

    std::string hostname = "host@";
    hostname += host;

    gss_buffer_desc namebuf = GSS_C_EMPTY_BUFFER;
    namebuf.value = (void*)hostname.c_str();
    namebuf.length = hostname.size();

    logger.msg(VERBOSE, "Peer host name to which this client will access: %s", hostname.c_str());

    majstat = gss_import_name(&minstat, &namebuf, GSS_C_NT_HOSTBASED_SERVICE,
                              &target_name);
    if (GSS_ERROR(majstat)) {
      logger.msg(ERROR, "GSS import name failed: %i/%i%s", majstat, minstat, GSSCredential::ErrorStr(majstat, minstat));
      return MCC_Status();
    }

    //if(((gss_cred_id_t&)(cred)) == GSS_C_NO_CREDENTIAL) { 
    //  req_flags = GSS_C_ANON_FLAG;
    //  logger.msg(DEBUG, "Anonymous GSI communication (no client-side authentication)");
    //}
    //req_flags |= GSS_C_CONF_FLAG;
    //req_flags |= GSS_C_MUTUAL_FLAG;
    //req_flags |= GSS_C_INTEG_FLAG;
    //req_flags |= GSS_C_REPLAY_FLAG;
    //req_flags |= GSS_C_DELEG_FLAG;

    req_flags = (gss_cred_id_t&)(cred) == GSS_C_NO_CREDENTIAL ? 
        (GSS_C_ANON_FLAG | GSS_C_CONF_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG) :
        (GSS_C_CONF_FLAG | GSS_C_MUTUAL_FLAG | GSS_C_INTEG_FLAG);

    do {
      majstat = gss_init_sec_context(&minstat,
                                     cred,
                                     &ctx,
                                     target_name,
                                     GSS_C_NO_OID,
                                     req_flags,
                                     0,
                                     GSS_C_NO_CHANNEL_BINDINGS,
                                     &recv_tok,
                                     NULL,
                                     &send_tok,
                                     &ret_flags,
                                     NULL);
      if (GSS_ERROR(majstat)) {
        logger.msg(ERROR, "GSS init security context failed: %i/%i%s", majstat, minstat, GSSCredential::ErrorStr(majstat, minstat));
        return MCC_Status();
      }

      logger.msg(INFO, "GSS init security context: %i/%i", majstat, minstat);

      logger.msg(VERBOSE, "Sent token length: %i", send_tok.length);

      MessageAttributes reqattr;
      MessageAttributes repattr;
      Message reqmsg;
      Message repmsg;
      MessageContext context;

      reqmsg.Attributes(&reqattr);
      reqmsg.Context(&context);
      repmsg.Attributes(&repattr);
      repmsg.Context(&context);

      PayloadRaw request;
      if (send_tok.length > 0)
        request.Insert((const char*)send_tok.value, 0, send_tok.length);
      reqmsg.Payload(&request);

      MCC_Status status = MCC::Next()->process(reqmsg, repmsg);

      if ((majstat & GSS_C_SUPPLEMENTARY_MASK) == GSS_S_CONTINUE_NEEDED) {

        if (!repmsg.Payload()) {
          logger.msg(ERROR, "No payload during GSI context initialisation");
          return MCC_Status();
        }

        PayloadStreamInterface *response =
          dynamic_cast<PayloadStreamInterface*>(repmsg.Payload());

        int pos = 0;
        char readbuf[5];
        while (5 > pos) {
          int len = 5 - pos;
          response->Get(&readbuf[pos], len);
          pos += len;
        }

        if (readbuf[0] >= 20 && readbuf[0] <= 23)
          logger.msg(VERBOSE, "Transfer protocol is TLS or SSL3");
        else if (readbuf[0] == 26)
          logger.msg(VERBOSE, "Transfer protocol is GLOBUS SSL");
        else if (readbuf[0] & 0x80 && readbuf[0] <= 23)
          logger.msg(VERBOSE, "Transfer protocol is SSL2");
        else
          logger.msg(VERBOSE, "Transfer protocol is GSI");

        recv_tok.length = (unsigned char)readbuf[3] * 256 +
                          (unsigned char)readbuf[4] + 5;
        recv_tok.value = malloc(recv_tok.length);
        memcpy(recv_tok.value, readbuf, 5);

        logger.msg(VERBOSE, "Recieved token length: %i", recv_tok.length);

        while (recv_tok.length > pos) {
          int len = recv_tok.length - pos;
          response->Get(&((char*)recv_tok.value)[pos], len);
          pos += len;
        }
      }
    } while ((majstat & GSS_C_SUPPLEMENTARY_MASK) == GSS_S_CONTINUE_NEEDED);

    majstat = gss_release_buffer(&minstat, &send_tok);
    majstat = gss_release_buffer(&minstat, &recv_tok);

    return MCC_Status(STATUS_OK);
  }

Here is the call graph for this function:

Here is the caller graph for this function:

void Arc::MCC_GSI_Client::Next ( MCCInterface next,
const std::string &  label = "" 
) [virtual]

Add reference to next MCC in chain.

This method is called by Loader for every potentially labeled link to next component which implements MCCInterface. If next is NULL corresponding link is removed.

Reimplemented from Arc::MCC.

Definition at line 392 of file MCCGSI.cpp.

                                                                      {
    if (label.empty())
      if (ctx != GSS_C_NO_CONTEXT) {
        OM_uint32 majstat, minstat;
        majstat = gss_delete_sec_context(&minstat, &ctx, GSS_C_NO_BUFFER);
        ctx = GSS_C_NO_CONTEXT;
      }
    MCC::Next(next, label);
  }

Here is the caller graph for this function:

MCCInterface * Arc::MCC::Next ( const std::string &  label = "") [protected, inherited]

Definition at line 22 of file MCC.cpp.

                                                {
    std::map<std::string, MCCInterface *>::iterator n = next_.find(label);
    if (n == next_.end())
      return NULL;
    return n->second;
  }

Here is the caller graph for this function:

Dummy Message processing method.

Just a placeholder.

Reimplemented from Arc::MCC.

Definition at line 312 of file MCCGSI.cpp.

                                                                    {

    if (ctx == GSS_C_NO_CONTEXT) {
      MCC_Status status = InitContext();
      if (!status)
        return status;
    }

    if (!inmsg.Payload())
      return MCC_Status();

    PayloadRawInterface *inpayload =
      dynamic_cast<PayloadRawInterface*>(inmsg.Payload());

    if (!ProcessSecHandlers(inmsg, "outgoing")) {
      logger.msg(ERROR,
                 "Security check failed in GSI MCC for outgoing message");
      return MCC_Status();
    }

    PayloadRaw gsipayload;
    int size = 0;

    for (int n = 0; inpayload->Buffer(n); ++n) {

      gss_buffer_desc recv_tok = GSS_C_EMPTY_BUFFER;
      gss_buffer_desc send_tok = GSS_C_EMPTY_BUFFER;

      recv_tok.value = inpayload->Buffer(n);
      recv_tok.length = inpayload->BufferSize(n);

      logger.msg(VERBOSE, "Recieved token length: %i", recv_tok.length);

      OM_uint32 majstat, minstat;

      majstat = gss_wrap(&minstat,
                         ctx,
                         0,
                         GSS_C_QOP_DEFAULT,
                         &recv_tok,
                         NULL,
                         &send_tok);
      if (GSS_ERROR(majstat)) {
        logger.msg(ERROR, "GSS wrap failed: %i/%i%s", majstat, minstat, GSSCredential::ErrorStr(majstat, minstat));
        return MCC_Status();
      }

      logger.msg(INFO, "GSS wrap: %i/%i", majstat, minstat);

      logger.msg(VERBOSE, "Sent token length: %i", send_tok.length);

      gsipayload.Insert((const char*)send_tok.value, size, send_tok.length);
      size += send_tok.length;
    }

    Message nextinmsg = inmsg;
    nextinmsg.Payload(&gsipayload);
    Message nextoutmsg = outmsg;
    nextoutmsg.Payload(NULL);

    MCCInterface *next = MCC::Next();
    if (!next)
      return MCC_Status();
    MCC_Status ret = next->process(nextinmsg, nextoutmsg);
    // TODO: handle errors and incompatible payloads

    if (!ProcessSecHandlers(outmsg, "incoming")) {
      logger.msg(ERROR,
                 "Security check failed in GSI MCC for incoming message");
      return MCC_Status();
    }

    PayloadStreamInterface *payload =
      dynamic_cast<PayloadStreamInterface*>(nextoutmsg.Payload());

    outmsg.Payload(new PayloadGSIStream(payload, ctx, logger, true));

    return MCC_Status(STATUS_OK);
  }

Here is the call graph for this function:

bool Arc::MCC::ProcessSecHandlers ( Message message,
const std::string &  label = "" 
) const [protected, inherited]

Executes security handlers of specified queue.

Returns true if the message is authorized for further processing or if there are no security handlers which implement authorization functionality. This is a convenience method and has to be called by the implemention of the MCC.

Definition at line 45 of file MCC.cpp.

                                           {
    // Each MCC/Service can define security handler queues in the configuration
    // file, the queues have labels specified in handlers configuration 'event'
    // attribute.
    // Security handlers in one queue are called sequentially.
    // Each one should be configured carefully, because there can be some
    // relationship between them (e.g. authentication should be put in front
    // of authorization).
    // The SecHandler::Handle() only returns true/false with true meaning that
    // handler processed message successfuly. If SecHandler implements
    // authorization functionality, it returns false if message is disallowed
    // and true otherwise.
    // If any SecHandler in the handler chain produces some information which
    // will be used by some following handler, the information should be
    // stored in the attributes of message (e.g. the Identity extracted from
    // authentication will be used by authorization to make access control
    // decision).
    std::map<std::string, std::list<ArcSec::SecHandler *> >::const_iterator q =
      sechandlers_.find(label);
    if (q == sechandlers_.end()) {
      logger.msg(DEBUG,
     "No security processing/check requested for '%s'", label);
      return true;
    }
    for (std::list<ArcSec::SecHandler *>::const_iterator h = q->second.begin();
         h != q->second.end(); ++h) {
      const ArcSec::SecHandler *handler = *h;
      if (!handler)
        continue; // Shouldn't happen. Just a sanity check.
      if (!(handler->Handle(&message))) {
        logger.msg(INFO, "Security processing/check failed");
        return false;
      }
    }
    logger.msg(DEBUG, "Security processing/check passed");
    return true;
  }

Here is the call graph for this function:

Here is the caller graph for this function:

void Arc::MCC::Unlink ( ) [virtual, inherited]

Removing all links.

Useful for destroying chains.

Definition at line 29 of file MCC.cpp.

                   {
    for (std::map<std::string, MCCInterface *>::iterator n = next_.begin();
         n != next_.end(); n = next_.begin())
      next_.erase(n);
  }

Here is the caller graph for this function:


Member Data Documentation

std::string Arc::MCC_GSI_Client::certificatePath [private]

Definition at line 39 of file MCCGSI.h.

gss_ctx_id_t Arc::MCC_GSI_Client::ctx [private]

Definition at line 37 of file MCCGSI.h.

std::string Arc::MCC_GSI_Client::keyPath [private]

Definition at line 40 of file MCCGSI.h.

A logger for MCCs.

A logger intended to be the parent of loggers in the different MCCs.

Reimplemented from Arc::MCC.

Definition at line 41 of file MCCGSI.h.

std::map<std::string, MCCInterface *> Arc::MCC::next_ [protected, inherited]

Set of labeled "next" components.

Each implemented MCC must call process() method of corresponding MCCInterface from this set in own process() method.

Definition at line 50 of file MCC.h.

std::string Arc::MCC_GSI_Client::proxyPath [private]

Definition at line 38 of file MCCGSI.h.

std::map<std::string, std::list<ArcSec::SecHandler *> > Arc::MCC::sechandlers_ [protected, inherited]

Set of labeled authentication and authorization handlers.

MCC calls sequence of handlers at specific point depending on associated identifier. In most aces those are "in" and "out" for incoming and outgoing messages correspondingly.

Definition at line 57 of file MCC.h.


The documentation for this class was generated from the following files: