// GssCredential.cxx #include #include "dataset_util/PThreadMutex.h" #include "dataset_util/FileStatus.h" #include "dataset_util/Time.h" #include "dataset_credential/GssCredential.h" #include "gssapi.h" using std::string; using std::ostream; using std::cerr; using std::endl; using dset::GssCredential; typedef GssCredential::Name Name; //********************************************************************** // Local data. //********************************************************************** namespace { // Mutex to protect file access. PThreadMutex& file_mutex() { static PThreadMutex mtx; return mtx; } } // end unnamed namespace //********************************************************************** // Embedded classes. //********************************************************************** struct GssCredential::Imp { gss_cred_id_t pcred; string file; string errmsg; bool manage; Imp(); }; GssCredential::Imp::Imp() : pcred(0), manage(false) { } //********************************************************************** // Member functions. //********************************************************************** // Default constructor. GssCredential::GssCredential() : m_pimp(new Imp) { static gss_cred_id_t pcred = 0; OM_uint32 miner; OM_uint32 majer = gss_acquire_cred( &miner, // (out) minor status GSS_C_NO_NAME, // (in) desired name GSS_C_INDEFINITE, // (in) desired time valid GSS_C_NO_OID_SET, // (in) desired mechs GSS_C_BOTH, // (in) usage (GSS_C_BOTH, GSS_C_INITIATE, or // GSS_C_ACCEPT) &pcred, // (out) cred handle 0, // (out) actual mechs 0 // (out) actual time valid ); m_pimp->pcred = pcred; m_pimp->manage = true; } //********************************************************************** // GSS constructor. GssCredential::GssCredential(gss_cred_id_t pcred, bool makecopy) : m_pimp(new Imp) { string prefix = "GssCredential::ctor_gss: "; // Exit with this object invalid if argument is null. if ( pcred == 0 ) { return; } m_pimp->manage = false; if ( makecopy ) { // Copy GSI credential. OM_uint32 majer; OM_uint32 miner; gss_buffer_desc cred_buffer; majer = gss_export_cred(&miner, pcred, 0, 0, &cred_buffer); if ( majer != GSS_S_COMPLETE ) { assert(false); cerr << prefix << "Error importing credential" << endl; cerr << " gss_export_cred majer: " << majer << endl; cerr << " gss_export_cred miner: " << miner << endl; m_pimp->errmsg = "copy ctor: Unable to fetch credential"; return; } majer = gss_import_cred(&miner, &m_pimp->pcred, 0, 0, &cred_buffer, 0, 0); if ( majer != GSS_S_COMPLETE ) { cerr << prefix << "Error exporting credential" << endl; m_pimp->errmsg = "copy ctor: Unable to copy credential"; return; } majer = gss_release_buffer(&miner, &cred_buffer); assert( majer == GSS_S_COMPLETE); assert( m_pimp->pcred != 0 ); m_pimp->manage = true; } else { m_pimp->pcred = pcred; } } //********************************************************************** // Copy constructor. GssCredential::GssCredential(const GssCredential& rhs, bool makecopy) : m_pimp(new Imp) { if ( makecopy ) { m_pimp->pcred = GssCredential(rhs.gss_handle(), true).release_gss_handle(); m_pimp->manage = true; } else { m_pimp->pcred = rhs.gss_handle(); m_pimp->manage = false; } } //********************************************************************** // Destructor. GssCredential::~GssCredential() { string prefix = "GssCredential::dtor: "; // Release credential. if ( m_pimp->pcred != 0 && m_pimp->manage ) { OM_uint32 miner = 0; if ( file().size() ) { assert( FileStatus(file()).exists() ); } OM_uint32 majer = gss_release_cred(&miner, &m_pimp->pcred); } // Delete file. if ( file().size() && m_pimp->manage ) { int dstat = unlink(file().c_str()); if ( dstat ) { cerr << prefix << "Unable to delete file" << endl; cerr << " " << file() << endl; } } delete m_pimp; } //********************************************************************** // Export credential to file. int GssCredential::export_to_file() { string prefix = "GssCredential::export_to_file: "; if ( ! is_valid() ) return -1; if ( file().size() ) return 0; if ( ! m_pimp->manage ) return -2; OM_uint32 miner = 0; gss_buffer_desc gssdata; gss_OID mechanism = 0; OM_uint32 option_request = 1; // Generate standard file. // Protect with mutex. static PThreadMutex mtx; mtx.lock(); OM_uint32 majer = gss_export_cred(&miner, m_pimp->pcred, mechanism, option_request, &gssdata); mtx.unlock(); if ( majer != GSS_S_COMPLETE ) { cerr << prefix << "Unableto export credential" << endl; m_pimp->errmsg = "export_to_file: Unable to export credential"; if ( majer = 0 ) return -3; return majer; } string envline = (char*) gssdata.value; majer = gss_release_buffer(&miner, &gssdata); if ( majer != GSS_S_COMPLETE ) { cerr << prefix << "Error releasing GSS buffer" << endl; } string::size_type ipos = envline.find('='); if ( ipos == string::npos || (ipos+1)==envline.size() ) { cerr << prefix << "Unable parse credential line" << endl; m_pimp->errmsg = "Unable to parse credential description: " + envline; return -4; } m_pimp->file = envline.substr(ipos+1); return 0; } //********************************************************************** // Delete file. int GssCredential::delete_file() { string prefix = "GssCredential::delete_file: "; if ( file().size() ) { unlink(file().c_str()); if ( FileStatus(file()).exists() ) { cerr << prefix << "Unable to delete file" << endl; return 1; } m_pimp->file = ""; } return 0; } //********************************************************************** // Release the GSS handle. gss_cred_id_t GssCredential::release_gss_handle() { if ( ! manage() ) { return 0; } m_pimp->manage = false; return m_pimp->pcred; } //********************************************************************** // Validity. bool GssCredential::is_valid() const { if ( m_pimp->pcred == 0 ) { return false; } OM_uint32 majer; OM_uint32 miner; majer = gss_inquire_cred(&miner, m_pimp->pcred, 0, 0, 0, 0); return majer == GSS_S_COMPLETE; } //********************************************************************** // Manage? bool GssCredential::manage() const { return m_pimp->manage; } //********************************************************************** // Name. Name GssCredential::name() const { Name sname = ""; if ( m_pimp->pcred == 0 ) { return sname; } gss_name_t gname; OM_uint32 majer; OM_uint32 miner; majer = gss_inquire_cred(&miner, m_pimp->pcred, &gname, 0, 0, 0); if ( majer == GSS_S_COMPLETE ) { gss_buffer_desc bname; majer = gss_display_name(&miner, gname, &bname, 0); char* pch = (char*) bname.value; for ( size_t i=0; ipcred == 0 ) { return false; } OM_uint32 majer; OM_uint32 miner; OM_uint32 gtime; majer = gss_inquire_cred(&miner, m_pimp->pcred, 0, >ime, 0, 0); return gtime; } //********************************************************************** // File. Name GssCredential::file() const { return m_pimp->file; } //********************************************************************** // Error message. string GssCredential::error_message() const { return m_pimp->errmsg; } //********************************************************************** // Credential. gss_cred_id_t GssCredential::gss_handle() const { return m_pimp->pcred; } //********************************************************************** // Free functions. //********************************************************************** // Output stream. ostream& operator<<(ostream& lhs, const GssCredential& rhs) { if ( rhs.is_valid() ) { lhs << "Valid credential"; } else { lhs << "Invalid credential"; return lhs; } string name = rhs.name(); if ( name.size() ) { lhs << " for " << name; } else { lhs << " with no name"; } if ( rhs.is_valid() ) { TimeInterval dtim(rhs.timeleft()); lhs << "\n Time remaining: " << dtim; } return lhs; } //**********************************************************************