diff --git a/src/SupervisedID.cpp b/src/SupervisedID.cpp index c5aa89f965bf8c66bd90ca5871c70c6778d7a63a..15b77d2a91366465f797ecf0bce150a6a914de23 100644 --- a/src/SupervisedID.cpp +++ b/src/SupervisedID.cpp @@ -1,5 +1,5 @@ /*----- PROTECTED REGION ID(SupervisedID.cpp) ENABLED START -----*/ -static const char *RcsId = "$Id: SupervisedID.cpp,v 1.2 2014-04-14 14:51:54 claudio Exp $"; + //============================================================================= // // file : SupervisedID.cpp @@ -142,16 +142,87 @@ void SupervisedID::init_device() /*----- PROTECTED REGION END -----*/ // SupervisedID::init_device_before - // No device property to be read from database - + // Get the device properties from database + get_device_property(); + /*----- PROTECTED REGION ID(SupervisedID::init_device) ENABLED START -----*/ // Initialize device - + //init hostMap from hostPriviliges + { + vector<string>::const_iterator i; + for (i = hostPrivileges.begin(); i != hostPrivileges.end(); i++) { + int pos = (*i).find(':'); + if (pos <= 0) { + ERROR_STREAM + << "SupervisedID::init() hostPrivileges syntax error " + << (*i) << endl; + } else { + string h = (*i).substr(0, pos); + string val = (*i).substr(pos + 1); + int valint = atoi(val.c_str()); + DEBUG_STREAM << "host: " << h << " privilege: " << valint + << endl; + pair<string, int> mypair(h, valint); + hostMap.insert(mypair); + } + } + } /*----- PROTECTED REGION END -----*/ // SupervisedID::init_device } +//-------------------------------------------------------- +/** + * Method : SupervisedID::get_device_property() + * Description : Read database to initialize property data members. + */ +//-------------------------------------------------------- +void SupervisedID::get_device_property() +{ + /*----- PROTECTED REGION ID(SupervisedID::get_device_property_before) ENABLED START -----*/ + + // Initialize property data members + + /*----- PROTECTED REGION END -----*/ // SupervisedID::get_device_property_before + + + // Read device properties from database. + Tango::DbData dev_prop; + dev_prop.push_back(Tango::DbDatum("HostPrivileges")); + + // is there at least one property to be read ? + if (dev_prop.size()>0) + { + // Call database and extract values + if (Tango::Util::instance()->_UseDb==true) + get_db_device()->get_property(dev_prop); + + // get instance on SupervisedIDClass to get class property + Tango::DbDatum def_prop, cl_prop; + SupervisedIDClass *ds_class = + (static_cast<SupervisedIDClass *>(get_device_class())); + int i = -1; + + // Try to initialize HostPrivileges from class property + cl_prop = ds_class->get_class_property(dev_prop[++i].name); + if (cl_prop.is_empty()==false) cl_prop >> hostPrivileges; + else { + // Try to initialize HostPrivileges from default device value + def_prop = ds_class->get_default_device_property(dev_prop[i].name); + if (def_prop.is_empty()==false) def_prop >> hostPrivileges; + } + // And try to extract HostPrivileges value from database + if (dev_prop[i].is_empty()==false) dev_prop[i] >> hostPrivileges; + + } + + /*----- PROTECTED REGION ID(SupervisedID::get_device_property_after) ENABLED START -----*/ + + // Check device property data members init + + /*----- PROTECTED REGION END -----*/ // SupervisedID::get_device_property_after +} //-------------------------------------------------------- /** @@ -161,7 +232,7 @@ void SupervisedID::init_device() //-------------------------------------------------------- void SupervisedID::always_executed_hook() { - INFO_STREAM << "SupervisedID::always_executed_hook() " << device_name << endl; + DEBUG_STREAM << "SupervisedID::always_executed_hook() " << device_name << endl; /*----- PROTECTED REGION ID(SupervisedID::always_executed_hook) ENABLED START -----*/ // code always executed before all requests @@ -217,10 +288,94 @@ void SupervisedID::add_dynamic_attributes() /*----- PROTECTED REGION END -----*/ // SupervisedID::add_dynamic_attributes } +//-------------------------------------------------------- +/** + * Method : SupervisedID::add_dynamic_commands() + * Description : Create the dynamic commands if any + * for specified device. + */ +//-------------------------------------------------------- +void SupervisedID::add_dynamic_commands() +{ + /*----- PROTECTED REGION ID(SupervisedID::add_dynamic_commands) ENABLED START -----*/ + + // Add your own code to create and add dynamic commands if any + + /*----- PROTECTED REGION END -----*/ // SupervisedID::add_dynamic_commands +} /*----- PROTECTED REGION ID(SupervisedID::namespace_ending) ENABLED START -----*/ // Additional Methods - +//------------------------------------------------------------------------------- + /** + * assign privileges elevel based on host name from which the call is generated + * PRIVILEGED : can change the enable bit and set gap/tapering + * AUTHORIZED : can set gap/tapering when enabled + * NORMAL : can only read; + */ +int SupervisedID::caller_privileges(void) +{ + //if no privileges are configured, run unimpeded + if(hostMap.size() == 0)return PRIVILEGED; + + Tango::DevVarStringArray blackbox = black_box(1)[0]; + string last_msg(blackbox[0].in()); + string::size_type loc = last_msg.find( " requested from ", 0 ); + if( loc != string::npos ) + { + clientAddress = last_msg.substr(loc + strlen(" requested from ")); + loc=clientAddress.find(" ",0); + clientAddress =clientAddress.substr(0,loc); + INFO_STREAM<<"checking call from "<<clientAddress<<endl; + // std::set<std::string> client_ips; + // get_ips_from_host(clientAddress, client_ips); + // + // for (std::set<std::string>::const_iterator it = client_ips.begin(); it != client_ips.end(); ++it ) + // { + // if (std::find(allowed_ips.begin(), allowed_ips.end(), *it) != allowed_ips.end()) + // return; // found the IP in the allowed list of IPs + // } + map<string,int>::iterator it; + it=hostMap.find(clientAddress); + if (it == hostMap.end()) { + INFO_STREAM << clientAddress<< " host not foud" << endl; + return NORMAL; + } + else { + INFO_STREAM << "host: "<< clientAddress<< " privilges="<< it->second << endl; + return it->second; + } + + } + else + { + WARN_STREAM << "Cannot extract client IP or hostname from tango blackbox, denying access."; + clientAddress=""; + return NORMAL; //do not grant special privileges + } + return NORMAL; //do not grant special privilege - but we should NOT arrive at this line +} +//-------------------------------------------------------------------- +/** + * check privileges level based on host name from which the call is generated + * formats warning/ error messages and throw exception in case of vilotaions + * privilege levels: + * PRIVILEGED : can change the enable bit and set gap/tapering + * AUTHORIZED : can set gap/tapering when enabled + * NORMAL : can only read; + */ + +int SupervisedID::check_privileges(int level, string msg) +{ + int priv=caller_privileges(); + if (priv < level){ + INFO_STREAM << msg << " from "<< clientAddress <<" REJECTED"<<endl; + TangoSys_OMemStream o; + o << msg << " from "<< clientAddress <<" REJECTED"<<ends; + Tango::Except::throw_exception((const char *)"Host not allowed",o.str(),msg); + } + return priv; +} /*----- PROTECTED REGION END -----*/ // SupervisedID::namespace_ending } // namespace diff --git a/src/SupervisedID.h b/src/SupervisedID.h index 6ad1865a03630fe891fad19365d3e472e899feb4..d7945609201f906eb95c887705b4b2819e5b098d 100644 --- a/src/SupervisedID.h +++ b/src/SupervisedID.h @@ -36,7 +36,10 @@ #include <tango.h> - +#include <map> +#define PRIVILEGED 2 +#define AUTHORIZED 1 +#define NORMAL 0 /*----- PROTECTED REGION END -----*/ // SupervisedID.h /** @@ -60,9 +63,22 @@ class SupervisedID : public TANGO_BASE_CLASS /*----- PROTECTED REGION ID(SupervisedID::Data Members) ENABLED START -----*/ // Add your own data members +protected: + int caller_privileges(void); + bool is_privileged; //true is the caller has all privileges - must be handled in alawys_executed + string clientAddress; + map<string,int> hostMap; + int check_privileges(int, string); //check privileges , emits diagnostics and throw exception, returns actual privileges /*----- PROTECTED REGION END -----*/ // SupervisedID::Data Members +// Device property data members +public: + // HostPrivileges: list of host:privileges + // host:2 host is privileged can read and write and change limits and change permission + // host:1 host is authorized can read and write when permitted + // host:0 host can only read + vector<string> hostPrivileges; // Attribute data members public: @@ -93,7 +109,7 @@ public: SupervisedID(Tango::DeviceClass *cl,const char *s,const char *d); /** * The device object destructor. - */ + */ ~SupervisedID() {delete_device();}; @@ -107,6 +123,10 @@ public: * Initialize the device */ virtual void init_device(); + /* + * Read the device properties from database + */ + void get_device_property(); /* * Always executed method before execution command method. */ @@ -172,10 +192,19 @@ public: + // Command related methods public: + //-------------------------------------------------------- + /** + * Method : SupervisedID::add_dynamic_commands() + * Description : Add dynamic commands if any. + */ + //-------------------------------------------------------- + void add_dynamic_commands(); + /*----- PROTECTED REGION ID(SupervisedID::Additional Method prototypes) ENABLED START -----*/ // Additional Method prototypes diff --git a/src/SupervisedID.xmi b/src/SupervisedID.xmi index cc61afb88c48e48f4e7b38e4f6747fb58e63295f..ea06ef117d019491637091d81883588f9d7be768 100644 --- a/src/SupervisedID.xmi +++ b/src/SupervisedID.xmi @@ -1,10 +1,14 @@ <?xml version="1.0" encoding="ASCII"?> <pogoDsl:PogoSystem xmi:version="2.0" xmlns:xmi="http://www.omg.org/XMI" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:pogoDsl="http://www.esrf.fr/tango/pogo/PogoDsl"> - <classes name="SupervisedID" pogoRevision="8.3"> - <description description="This abstract class incapsulates the common interface for insertion devices used
under ID supervisor. The "supervisor" can inhibi/allow the operations on the insertion device
and impose limits on the permited range." title="Supervised ID: common interface for supervised insertion devices" sourcePath="/home/claudio/devel/AbstractClasses7/SupervisedID" language="Cpp" filestogenerate="XMI file,Code files" hasMandatoryProperty="false" hasConcreteProperty="false" hasAbstractCommand="false" hasAbstractAttribute="true"> + <classes name="SupervisedID" pogoRevision="9.6"> + <description description="This abstract class incapsulates the common interface for insertion devices used
under ID supervisor. The "supervisor" can inhibi/allow the operations on the insertion device
and impose limits on the permited range." title="Supervised ID: common interface for supervised insertion devices" sourcePath="/home/claudio/src/gitlab/cs/cls/supervisedid/src" language="Cpp" filestogenerate="XMI file,Code files,Protected Regions" hasMandatoryProperty="false" hasConcreteProperty="true" hasAbstractCommand="false" hasAbstractAttribute="true"> <inheritances classname="Device_4Impl" sourcePath=""/> <identification contact="at elettra.trieste.it - claudio.scafuri" author="claudio.scafuri" emailDomain="elettra.trieste.it" classFamily="Controllers" siteSpecific="" platform="All Platforms" bus="Not Applicable" manufacturer="none" reference=""/> </description> + <deviceProperties name="HostPrivileges" description="list of host:privileges
host:2 host is privileged can read and write and change limits and change permission
host:1 host is authorized can read and write when permitted
host:0 host can only read"> + <type xsi:type="pogoDsl:StringVectorType"/> + <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> + </deviceProperties> <commands name="State" description="This command gets the device state (stored in its <i>device_state</i> data member) and returns it to the caller." execMethod="dev_state" displayLevel="OPERATOR" polledPeriod="0"> <argin description="none."> <type xsi:type="pogoDsl:VoidType"/> @@ -52,12 +56,9 @@ <states name="UNKNOWN" description="Device not working - unknow reason/condition"> <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> </states> - <states name="RUNNING" description="Device gap is moving"> - <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> - </states> - <states name="DISABLE" description="Device not remotely operable"> + <states name="MOVING" description="Device gap is moving"> <status abstract="false" inherited="false" concrete="true" concreteHere="true"/> </states> - <preferences docHome="./doc_html" makefileHome="/usr/local/tango-8.1.2.c/share/pogo/preferences"/> + <preferences docHome="./doc_html" makefileHome="/usr/local/tango-9.3.3/share/pogo/preferences"/> </classes> </pogoDsl:PogoSystem> diff --git a/src/SupervisedIDClass.cpp b/src/SupervisedIDClass.cpp index 663cb330ab69e176f9e9b31b7139eef11ef45024..d22c4270b308eaa993b05f14aa8cd0e6757c5a85 100644 --- a/src/SupervisedIDClass.cpp +++ b/src/SupervisedIDClass.cpp @@ -1,9 +1,4 @@ /*----- PROTECTED REGION ID(SupervisedIDClass.cpp) ENABLED START -----*/ -static const char *RcsId = "$Id: SupervisedIDClass.cpp,v 1.2 2014-04-14 14:51:54 claudio Exp $"; -static const char *TagName = "$Name: $"; -static const char *CvsPath = "$Source: /home/cvsadm/cvsroot/AbstractClasses7/SupervisedID/SupervisedIDClass.cpp,v $"; -static const char *SvnPath = "$HeadURL: $"; -static const char *HttpServer = "http://www.esrf.eu/computing/cs/tango/tango_doc/ds_doc/"; //============================================================================= // // file : SupervisedIDClass.cpp @@ -11,7 +6,7 @@ static const char *HttpServer = "http://www.esrf.eu/computing/cs/tango/tango_doc // description : C++ source for the SupervisedIDClass. A singleton // class derived from DeviceClass. It implements the // command list and all properties and methods required -// by the «name» once per process. +// by the �name� once per process. // // project : Supervised ID: common interface for supervised insertion devices. // @@ -126,8 +121,8 @@ SupervisedIDClass *SupervisedIDClass::init(const char *name) catch (bad_alloc &) { throw; - } - } + } + } return _instance; } @@ -222,6 +217,19 @@ void SupervisedIDClass::set_default_property() // Set Default Class Properties // Set Default device Properties + prop_name = "HostPrivileges"; + prop_desc = "list of host:privileges\nhost:2 host is privileged can read and write and change limits and change permission\nhost:1 host is authorized can read and write when permitted\nhost:0 host can only read"; + prop_def = ""; + vect_data.clear(); + if (prop_def.length()>0) + { + Tango::DbDatum data(prop_name); + data << vect_data ; + dev_def_prop.push_back(data); + add_wiz_dev_prop(prop_name, prop_desc, prop_def); + } + else + add_wiz_dev_prop(prop_name, prop_desc); } //-------------------------------------------------------- @@ -266,6 +274,7 @@ void SupervisedIDClass::attribute_factory(vector<Tango::Attr *> &att_list) + /*----- PROTECTED REGION ID(SupervisedIDClass::attribute_factory_after) ENABLED START -----*/ // Add your own code @@ -273,6 +282,26 @@ void SupervisedIDClass::attribute_factory(vector<Tango::Attr *> &att_list) /*----- PROTECTED REGION END -----*/ // SupervisedIDClass::attribute_factory_after } //-------------------------------------------------------- +/** + * Method : SupervisedIDClass::pipe_factory() + * Description : Create the pipe object(s) + * and store them in the pipe list + */ +//-------------------------------------------------------- +void SupervisedIDClass::pipe_factory() +{ + /*----- PROTECTED REGION ID(SupervisedIDClass::pipe_factory_before) ENABLED START -----*/ + + // Add your own code + + /*----- PROTECTED REGION END -----*/ // SupervisedIDClass::pipe_factory_before + /*----- PROTECTED REGION ID(SupervisedIDClass::pipe_factory_after) ENABLED START -----*/ + + // Add your own code + + /*----- PROTECTED REGION END -----*/ // SupervisedIDClass::pipe_factory_after +} +//-------------------------------------------------------- /** * Method : SupervisedIDClass::command_factory() * Description : Create the command object(s) diff --git a/src/SupervisedIDClass.h b/src/SupervisedIDClass.h index 25d7c94abf07fa98a3bf9d3a0d829457193efc41..ea5fb6409dab734ef4c110022c6a0d3b7fc0b90b 100644 --- a/src/SupervisedIDClass.h +++ b/src/SupervisedIDClass.h @@ -87,6 +87,7 @@ class SupervisedIDClass : public Tango::DeviceClass static SupervisedIDClass *_instance; void command_factory(); void attribute_factory(vector<Tango::Attr *> &); + void pipe_factory(); void write_class_property(); void set_default_property(); void get_class_property(); diff --git a/src/SupervisedIDStateMachine.cpp b/src/SupervisedIDStateMachine.cpp index d41f8cfa598beeabe42e5952156148caaa6bfd79..d9ebf5bd98e5e96df597827c0f37fc09ad971782 100644 --- a/src/SupervisedIDStateMachine.cpp +++ b/src/SupervisedIDStateMachine.cpp @@ -1,5 +1,4 @@ /*----- PROTECTED REGION ID(SupervisedIDStateMachine.cpp) ENABLED START -----*/ -static const char *RcsId = "$Id: SupervisedIDStateMachine.cpp,v 1.2 2014-04-14 14:52:01 claudio Exp $"; //============================================================================= // // file : SupervisedIDStateMachine.cpp @@ -45,8 +44,7 @@ static const char *RcsId = "$Id: SupervisedIDStateMachine.cpp,v 1.2 2014-04-14 1 // ON | Device OK // FAULT | Device not working - broken ID // UNKNOWN | Device not working - unknow reason/condition -// RUNNING | Device gap is moving -// DISABLE | Device not remotely operable +// MOVING | Device gap is moving namespace SupervisedID_ns @@ -107,8 +105,16 @@ bool SupervisedID::is_StatRF_allowed(TANGO_UNUSED(Tango::AttReqType type)) return true; } + //================================================= // Commands Allowed Methods //================================================= + +/*----- PROTECTED REGION ID(SupervisedID::SupervisedIDStateAllowed.AdditionalMethods) ENABLED START -----*/ + +// Additional Methods + +/*----- PROTECTED REGION END -----*/ // SupervisedID::SupervisedIDStateAllowed.AdditionalMethods + } // End of namespace