[omniORB] Security/Authentication/Interceptors

Bill Noon noon@snow.nrcc.cornell.edu
Thu Feb 27 14:33:01 2003


--Apple-Mail-2--670267162
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
	charset=US-ASCII;
	format=flowed

Darryl -- I am doing something similar to Thomas and Jan.  I have a 
server that the client must register with to get a token.  This token 
is set in the client and added to a service context.  The other 
services use this token to authorize calls.  Since the token is passed 
in the clear, it is shortlived and tied to the client's ip address.

All the client/server code is in python so I have made a c++ module to 
add the interceptors and get/set the token.

Attached is the module and the setup.py file for compiling/installing 
it.


--Apple-Mail-2--670267162
Content-Disposition: attachment;
	filename=ucanSecure.cc
Content-Transfer-Encoding: 7bit
Content-Type: application/text;
	x-unix-mode=0644;
	x-mac-type=54455854;
	name="ucanSecure.cc"

// -*- Mode: C++; -*-
//                            Package   : omniORBpy
// ucanSecure.cc              Created on: 2002/02/24
//                            Author    : Bill Noon

#ifndef USE_omniORB_logStream
#define USE_omniORB_logStream
#endif
#include <omniORB4/CORBA.h>
#include <omniORB4/internal/initialiser.h>

// For interceptors
#include <omniORB4/omniInterceptors.h>

// Thread specific data
#include <omnithread.h>

// Specifically for use of info in giop_s in serverReceiveRequest_T::info_T
#include <giopStrand.h>
#include <giopStream.h>
#include <GIOP_S.h>

#include <Python.h>
OMNI_USING_NAMESPACE(omni)

class ucanToken : public omni_thread::value_t {
public:
  ucanToken(const char * token, const char * addr) {
    _token = new char [16];
    memset(_token, 0, 16);
    memcpy(_token, token, 16);
    _remoteaddress = new char [strlen(addr)+1];
    strcpy(_remoteaddress, addr);
    if (omniORB::trace(25)) {
      omniORB::logger log;
      log << "Creating thread specific data (" << _token << ")\n";
      log << "   remote address (" << _remoteaddress << ")\n";
    }
  };
  
  ~ucanToken() { 
    if (omniORB::trace(25)) {
      omniORB::logger log;
      log << "Delete thread specific data (" << _token << ")\n";
      log << "   and remoteaddress (" << _remoteaddress << ")\n";
    }
    delete[] _token;
	delete[] _remoteaddress; };
  
  char *remoteaddress() { return _remoteaddress;};
  char *token() { return _token;};
private:
  char *_remoteaddress;
  char *_token;
};

omni_thread::key_t key;
const IOP::ServiceID UCAN_SECURE = 0x52434301;
char * ucan_secure_ticket = 0;


/////////////////////////////////////////////////////////////////////////////
//            Client side interceptor for security service context         //
/////////////////////////////////////////////////////////////////////////////
CORBA::Boolean
setUcanSecureServiceContext(omniInterceptors::clientSendRequest_T::info_T& info) {
  GIOP::Version ver = info.giopstream.version();

  if (ver.minor < 2) {
    // possibly raise error
    return 1;
  }

  if (ucan_secure_ticket) {
  	
    cdrEncapsulationStream s(CORBA::ULong(0),1);
	_CORBA_Unbounded_Sequence_Octet ticket;
	ticket.replace(16,16,(CORBA::Octet *)ucan_secure_ticket);
	ticket >>= s;

    CORBA::Octet* data;
    CORBA::ULong max,datalen;
    s.getOctetStream(data,max,datalen);

    CORBA::ULong len = info.service_contexts.length() + 1;
    info.service_contexts.length(len);
    info.service_contexts[len-1].context_id = UCAN_SECURE;
    info.service_contexts[len-1].context_data.replace(max,datalen,data,1);

    if (omniORB::trace(25)) {
      omniORB::logger log;
      log << " send ucan secure service context: ("
	  << ticket.get_buffer() << ")\n";
    }
  }
  return 1;
}

/////////////////////////////////////////////////////////////////////////////
//            Server side interceptor for ucan secure service context         //
/////////////////////////////////////////////////////////////////////////////
CORBA::Boolean
getUcanSecureServiceContext(omniInterceptors::serverReceiveRequest_T::info_T& info) {
  GIOP::Version ver = info.giop_s.version();

  if (ver.minor < 2) {
    // possibly raise error
    return 1;
  }

  IOP::ServiceContextList& svclist = info.giop_s.receive_service_contexts();
  CORBA::ULong total = svclist.length();
  for (CORBA::ULong index = 0; index < total; index++) {
    if (svclist[index].context_id == UCAN_SECURE) {
      cdrEncapsulationStream e(svclist[index].context_data.get_buffer(),
			       svclist[index].context_data.length(),1);

      _CORBA_Unbounded_Sequence_Octet ticket;
	  ticket <<=e;
      
      omni_thread::self()->set_value(key, 
      	new ucanToken((const char*) ticket.get_buffer(),
      	((omni::giopStrand&)info.giop_s).connection->peeraddress()));
      
      if (omniORB::trace(25)) {
        omniORB::logger log;
        log << " recieve ucan secure service context ("
	        << ticket.get_buffer() << ")\n";
        log << " recieve remote address("
	        << ((ucanToken*)omni_thread::self()->get_value(key))->remoteaddress() << ")\n";
      }
      return 1;
    }
  }

  omni_thread::self()->set_value(key, 
	new ucanToken("                ",
	((omni::giopStrand&)info.giop_s).connection->peeraddress()));
  
  if (omniORB::trace(25)) {
	omniORB::logger log;
	log << " No remote ucan secure context (" << ")\n";
	log << " recieve remote address("
		<< ((ucanToken*)omni_thread::self()->get_value(key))->remoteaddress() << ")\n";
  }
  return 1;
}


////////////////////////////////////////////////////////////////////////////
// Module inititaliser to hook orb destruction                            //
////////////////////////////////////////////////////////////////////////////

class ucanSecure_initialiser : public omniInitialiser {
public:
  
  void attach() {
    // install interceptors
    omni::omniInterceptors* interceptors = omniORB::getInterceptors();
    interceptors->clientSendRequest.add(setUcanSecureServiceContext);
    interceptors->serverReceiveRequest.add(getUcanSecureServiceContext);
  }
  	
  void detach() { }
};

static ucanSecure_initialiser the_ucanSecure_initialiser;

static PyObject*
raiseNoContext(PyObject* pyPC)
{
  PyObject* excc = PyObject_GetAttrString(pyPC, (char*)"NoContext");
  OMNIORB_ASSERT(excc);
  PyObject* exci = PyEval_CallObject(excc, PyTuple_New(0));
  PyErr_SetObject(excc, exci);
  return 0;
}

// Things visible to Python:

extern "C" {


  static PyObject*
  ucan_getToken(PyObject* self, PyObject* args)
  {
    if (!PyArg_ParseTuple(args, (char*)""))
      return 0;
    ucanToken *ut = (ucanToken *)omni_thread::self()->get_value(key);
    PyObject* r_o = PyString_FromStringAndSize(ut->token(),16);
    return r_o;
  }

  static PyObject*
  ucan_getRemoteAddr(PyObject* self, PyObject* args)
  {
    if (!PyArg_ParseTuple(args, (char*)""))
      return 0;
    char *ra = ((ucanToken *)omni_thread::self()->get_value(key))->remoteaddress();
    PyObject* r_o = PyString_FromStringAndSize(ra,strlen(ra));
    return r_o;
  }

  static PyObject*
  ucan_setToken(PyObject* self, PyObject* args)
  {
  	PyObject *ticket;
  	char *t;
  	int len;
  	
    if (!PyArg_ParseTuple(args, (char*)"O", &ticket))
      return NULL;
    if (!PyString_Check(ticket)) return raiseNoContext(self);
    if (!ucan_secure_ticket) ucan_secure_ticket = new char[16];
    len = PyString_GET_SIZE(ticket);
    t = PyString_AsString(ticket);
    memset(ucan_secure_ticket, 0, 16);
    if (len > 16) len = 16;
    memcpy(ucan_secure_ticket, t, len);
    Py_INCREF(Py_None);
    return Py_None;
  }


  ////////////////////////////////////////////////////////////////////////////
  // Python method table                                                    //
  ////////////////////////////////////////////////////////////////////////////

  static PyMethodDef ucanSecure_methods[] = {

    {(char*)"getToken",          ucan_getToken,                  METH_VARARGS},
    {(char*)"setToken",          ucan_setToken,                  METH_VARARGS},
    {(char*)"getRemoteAddr",     ucan_getRemoteAddr,             METH_VARARGS},
    {0,0}
  };

  void initucanSecure()
  {
    // Make sure Python is running multi-threaded
    PyEval_InitThreads();

    PyObject* m = Py_InitModule((char*)"ucanSecure", ucanSecure_methods);
    PyObject* d = PyModule_GetDict(m);
    key = omni_thread::allocate_key();
    omniInitialiser::install(&the_ucanSecure_initialiser);
  }
}

--Apple-Mail-2--670267162
Content-Disposition: attachment;
	filename=setup.py
Content-Transfer-Encoding: 7bit
Content-Type: application/octet-stream;
	x-unix-mode=0644;
	name="setup.py"

from distutils.core import setup, Extension

setup(name="ucanSecure",
	ext_modules=[Extension("ucanSecure",
		['ucanSecure.cc',],
		include_dirs=['.','/usr/local/include',
			'/usr/local/include/omniORB4/internal',],
		define_macros=[('__OSVERSION__',1),('__darwin__',1),],
		library_dirs=['/usr/local/lib'],
		libraries=['omniORB4','omnithread'],
	)])

--Apple-Mail-2--670267162
Content-Transfer-Encoding: 7bit
Content-Type: text/plain;
	charset=US-ASCII;
	format=flowed



--Bill Noon
Northeast Regional Climate Center
Cornell University


On Thursday, February 27, 2003, at 09:27 AM, darryl wrote:

> One question, i gathered from the mailing list that
> at tne time the python bindings couldn't do interceptors.
> Is this still the case or can you use interceptors with python?
>
> -Darryl
>
>
>>> Can you post an example of how you do this? It sounds interesting.
>>
>> Sure. Although this code is in Object Pascal, it should be general
>> enough CORBA-wise to translate well to C++. "High(sc.context_data) + 
>> 1"
>> returns the length of a service context octet sequence, and 
>> "Move(....)"
>> is a mem -> mem copy function.
>>
>> This is still a work in progress, but I have the authenticator running
>> and the interceptors shown here work fine. The authentication service
>> has an IDL like
>>
>
>
> _______________________________________________
> omniORB-list mailing list
> omniORB-list@omniorb-support.com
> http://www.omniorb-support.com/mailman/listinfo/omniorb-list

--Apple-Mail-2--670267162--