// WsClient.cxx #include "dial_ws/WsClient.h" #include #include "../gsoap/dial_ws_baseH.h" #include "dial_ws/dial_ws_flags.h" #include "dataset_credential/GssCredentialManager.h" #include "dataset_credential/Gsoap.h" #ifdef WITH_GSI #define GLOBUS_DEBUG_H #include "gsi.h" #endif extern SOAP_NMAC struct Namespace dial_ws_base_namespaces[]; using std::string; using std::ostream; using std::cout; using std::cerr; using std::endl; using dset::GssCredential; using dset::GssCredentialManager; using dset::Gsoap; using dial::WsClient; typedef WsClient::FunPtr FunPtr; //********************************************************************** // Local definitions. //********************************************************************** class WsClient::Imp { public: int stat; bool usegsi; string url; struct soap soap; Imp(string inurl) : stat(0), url(inurl) { } const char* curl() const { return url.c_str(); } string server_dn; bool delreq; bool delset; FunPtr pfun; void* pobj; }; //********************************************************************** #ifdef WITH_GSI int client_authorization(struct soap* psoap, char* dn) { struct gsi_plugin_data* pgsiplug = (struct gsi_plugin_data *) soap_lookup_plugin(psoap, GSI_PLUGIN_ID); //string client_identity = pgsiplug->client_identity; //string service_identity = pgsiplug->server_identity; //cout << "GSI Client ID: " << client_identity << endl; //cout << "GSI Service ID: " << service_identity << endl; return 0; } #endif //********************************************************************** // Methods. //********************************************************************** // Constructor. WsClient::WsClient(string url, bool usegsi, bool dele) : pimp(new Imp(url)) { #ifndef WITH_GSI assert( usegsi == false ); #endif pimp->usegsi = usegsi; pimp->delreq = dele; pimp->delset = false; pimp->pfun = 0; pimp->pobj = 0; if ( url == "" ) { std::cerr << "WsClient::ctor: URL undefined" << endl; set_client_status(-1); return; } struct soap& soap = pimp->soap; soap_init(&soap); soap_set_namespaces(&soap, dial_ws_base_namespaces); #ifdef WITH_GSI if ( usegsi ) { // Register the GSI plugin. if ( soap_register_plugin(&soap, globus_gsi) ) { std::cerr << "WsClient: Unable to register GSI plugin" << endl; set_client_status(-2); return; } // Set authorization callback. struct gsi_plugin_data* gsiplug = (struct gsi_plugin_data*) soap_lookup_plugin(&soap, GSI_PLUGIN_ID); gsiplug->gsi_authorization_callback = client_authorization; // Setup GSI channel. /* if ( dele ) { set_delegation(true); } else { cerr << "WsClient::ctor: GSI without delegation" << endl; } */ gsi_set_replay(&soap, GLOBUS_TRUE); gsi_set_sequence(&soap, GLOBUS_TRUE); gsi_set_confidentiality(&soap, GLOBUS_TRUE); gsi_set_integrity(&soap, GLOBUS_TRUE); } #endif soap.connect_timeout = 10; set_timeout(10); } //********************************************************************** // Destructor. WsClient::~WsClient() { if ( ! client_status() ) { soap_done(&pimp->soap); soap_end(&pimp->soap); soap_destroy(&pimp->soap); } delete pimp; } //********************************************************************** // Set the timeout. void WsClient::set_timeout(int time) { pimp->soap.connect_timeout = time; } //********************************************************************** // Return the timeout. int WsClient::timeout() const { return psoap()->connect_timeout; } //********************************************************************** // Validity. bool WsClient::is_valid() const { return client_status() == 0; } //********************************************************************** // Ping. bool WsClient::ping() const { if ( pimp->pfun != 0 ) { return pimp->pfun(pimp->pobj); } // We should probably simply return false to force clients to // implement ping. The is_valid method is not required to contact // the service. However we do the following for backward // compatibility. return is_valid(); } //********************************************************************** // Set status. int WsClient::set_client_status(int stat) const { return pimp->stat = stat; } //********************************************************************** // Return the status. int WsClient::client_status() const { return pimp->stat; } //********************************************************************** // Gsoap object. struct soap* WsClient::psoap() const { soap& rsoap = pimp->soap; // Acquire the credential for this thread. GssCredential* pcred = GssCredentialManager::credential(); if ( pcred != 0 && pcred->is_valid() ) { Gsoap(rsoap).set_credential(*pcred); } if ( pimp->delset != pimp->delreq ) { WsClient& mthis = const_cast(*this); mthis.set_delegation(pimp->delreq); if ( pimp->delset != pimp->delreq ) { cerr << "WsClient::psoap: Attempt to set delegation to " << pimp->delreq << " failed" << endl; } } return &rsoap; } //********************************************************************** // URL. const char* WsClient::curl() const { return pimp->url.c_str(); } //********************************************************************** // Return the server DN. string WsClient::server_dn() { if ( ! pimp->usegsi ) { return ""; } struct gsi_plugin_data* gsiplug = (struct gsi_plugin_data*) soap_lookup_plugin(&pimp->soap, GSI_PLUGIN_ID); if ( gsiplug == 0 ) { cerr << "WsClient::server_dn: GSI plugin is missing!" << endl; return ""; } // Make a server call if the server field is null. if ( gsiplug->server_identity == 0 ) { //cerr << "WsClient::server_dn: Acquiring server identity..."; //cerr.flush(); ping(); gsiplug = (struct gsi_plugin_data*) soap_lookup_plugin(&pimp->soap, GSI_PLUGIN_ID); if ( gsiplug == 0 ) { cerr << "WsClient::server_dn: GSI plugin 2 is missing!" << endl; return ""; } if ( gsiplug->server_identity == 0 ) { cerr << "WsClient::server_dn: " << "Unable to acquire service identity" << endl; //cerr << "FAILED" << endl; return ""; } else { //cerr << "OK\n " << gsiplug->server_identity << endl; } } return gsiplug->server_identity; } //********************************************************************** // Set the delegation. int WsClient::set_delegation(bool del) { //cerr << "WsClient::set_delegation: " << del << endl; if ( ! pimp->usegsi ) { cerr << "WsClient::set_delegation: Not GSI." << endl; return 4; } pimp->delreq = del; if ( pimp->delreq == pimp->delset ) return 0; int stat = 0; if ( pimp->delreq ) { // Set set to match req so we don't get stuck in a loop. pimp->delset = true; if ( server_dn().size() ) { char* cdn = const_cast(server_dn().c_str()); int gstat = gsi_set_delegation(&pimp->soap, true, cdn); if ( gstat ) { cerr << "WsClient::set_delegation: gsoap_gsi call failed" << endl; pimp->delset = false; stat = 2; } else { pimp->delset = true; } } else { cerr << "WsClient::set_delegation: server not set" << endl; pimp->delset = false; stat = 1; } } else { // Gsoap-gsi does not yet provide unset of delegation. // This could easily be added--see gsoap-gsi code. stat = 3; cerr << "WsClient::set_delegation: unset not enabled" << endl; // Set authorization callback. struct gsi_plugin_data* gsiplug = (struct gsi_plugin_data*) soap_lookup_plugin(&pimp->soap, GSI_PLUGIN_ID); } return stat; } //********************************************************************** // Fetch the delegation state. bool WsClient::is_delegating() { return pimp->delreq; } //********************************************************************** // Cleanup gsoap. void WsClient::clean_soap() const { //cerr << "Cleaning" << endl; //WsClient& mthis = const_cast(*this); //cerr << " before: " << mthis.server_dn() << endl; soap_destroy(psoap()); soap_end(psoap()); //cerr << " after: " << mthis.server_dn() << endl; } //********************************************************************** // Callback. int WsClient::set_ping_callback(FunPtr pfun, void* pobj) { pimp->pfun = pfun; pimp->pobj = pobj; return 0; } //**********************************************************************