void TraceSvcUtil::setAttachInfo(const string& service_name, const string& user, const string& role, const string& pwd, const AuthReader::AuthBlock& /*authBlock*/, bool isAdmin) { ISC_STATUS_ARRAY status = {0}; ClumpletWriter spb(ClumpletWriter::spbList, MAXBUF); if (user.hasData()) { spb.insertString(isc_spb_user_name, user); } if (pwd.hasData()) { spb.insertString(isc_spb_password, pwd); } if (role.hasData()) { spb.insertString(isc_spb_sql_role_name, role); } if (isAdmin) { spb.insertTag(isc_spb_trusted_auth); } if (isc_service_attach(status, 0, service_name.c_str(), &m_svcHandle, static_cast<USHORT>(spb.getBufferLength()), reinterpret_cast<const char*>(spb.getBuffer()))) { status_exception::raise(status); } }
void TraceSvcJrd::startSession(TraceSession& session, bool interactive) { if (!TraceManager::pluginsCount()) { m_svc.printf(false, "Can not start trace session. There are no trace plugins loaded\n"); return; } ConfigStorage* storage = TraceManager::getStorage(); { // scope StorageGuard guard(storage); session.ses_auth = m_authBlock; session.ses_user = m_user.hasData() ? m_user : m_svc.getUserName(); MetaName role = m_role.hasData() ? m_role : m_svc.getRoleName(); UserId::makeRoleName(role, SQL_DIALECT_V6); session.ses_role = role.c_str(); session.ses_flags = trs_active; if (m_admin) { session.ses_flags |= trs_admin; } if (interactive) { Guid guid; GenerateGuid(&guid); char* buff = session.ses_logfile.getBuffer(GUID_BUFF_SIZE); GuidToString(buff, &guid); session.ses_logfile.insert(0, "fb_trace."); } storage->addSession(session); m_chg_number = storage->getChangeNumber(); } m_svc.started(); m_svc.printf(false, "Trace session ID %ld started\n", session.ses_id); if (interactive) { readSession(session); { StorageGuard guard(storage); storage->removeSession(session.ses_id); } } }
void RecordSource::printInversion(thread_db* tdbb, const InversionNode* inversion, string& plan, bool detailed, unsigned level, bool navigation) { if (detailed) plan += printIndent(++level); switch (inversion->type) { case InversionNode::TYPE_AND: if (detailed) plan += "Bitmap And"; printInversion(tdbb, inversion->node1, plan, detailed, level); printInversion(tdbb, inversion->node2, plan, detailed, level); break; case InversionNode::TYPE_OR: case InversionNode::TYPE_IN: if (detailed) plan += "Bitmap Or"; printInversion(tdbb, inversion->node1, plan, detailed, level); printInversion(tdbb, inversion->node2, plan, detailed, level); break; case InversionNode::TYPE_DBKEY: if (detailed) plan += "DBKEY"; break; case InversionNode::TYPE_INDEX: { MetaName indexName; MET_lookup_index(tdbb, indexName, inversion->retrieval->irb_relation->rel_name, (USHORT) (inversion->retrieval->irb_index + 1)); if (detailed) { if (!navigation) plan += "Bitmap" + printIndent(++level); plan += "Index \"" + printName(tdbb, indexName.c_str()) + "\" Scan"; } else { plan += (plan.hasData() ? ", " : "") + printName(tdbb, indexName.c_str()); } } break; default: fb_assert(false); } }
bool TraceSvcJrd::checkPrivileges(TraceSession& session) { // Our service run in embedded mode and have no auth info - trust user name as is if (m_admin || m_user.hasData() && (m_user == session.ses_user)) return true; // Other session is fully authorized - try to map our auth info using other's // security database if (session.ses_auth.hasData()) { AuthReader::Info info; for (AuthReader rdr(session.ses_auth); rdr.getInfo(info); rdr.moveNext()) { string s_user, t_role; PathName dummy; RefPtr<const Config> config; expandDatabaseName(info.secDb.hasData() ? info.secDb.ToPathName() : m_svc.getExpectedDb(), dummy, &config); Mapping mapping(Mapping::MAP_NO_FLAGS, m_svc.getCryptCallback()); UserId::Privileges priv; mapping.needSystemPrivileges(priv); mapping.setAuthBlock(m_authBlock); mapping.setErrorMessagesContextName("services manager"); mapping.setSqlRole(m_svc.getRoleName()); mapping.setSecurityDbAlias(config->getSecurityDatabase(), nullptr); if (mapping.mapUser(s_user, t_role) & Mapping::MAP_ERROR_NOT_THROWN) { // Error in mapUser() means missing context, therefore... continue; } t_role.upper(); // TODO: add privileges for list\manage sessions and check it here if (s_user == DBA_USER_NAME || t_role == ADMIN_ROLE || s_user == session.ses_user) return true; } } // Other session's service run in embedded mode - check our user name as is else if (m_svc.getUserName() == session.ses_user || m_svc.getUserAdminFlag()) return true; return false; }
void Monitoring::putRequest(SnapshotData::DumpRecord& record, const jrd_req* request, const string& plan) { fb_assert(request); record.reset(rel_mon_statements); // request id record.storeInteger(f_mon_stmt_id, request->req_id); // attachment id if (request->req_attachment) record.storeInteger(f_mon_stmt_att_id, request->req_attachment->att_attachment_id); // state, transaction ID, timestamp if (request->req_flags & req_active) { const bool is_stalled = (request->req_flags & req_stall); record.storeInteger(f_mon_stmt_state, is_stalled ? mon_state_stalled : mon_state_active); if (request->req_transaction) record.storeInteger(f_mon_stmt_tra_id, request->req_transaction->tra_number); record.storeTimestamp(f_mon_stmt_timestamp, request->req_timestamp); } else record.storeInteger(f_mon_stmt_state, mon_state_idle); const JrdStatement* const statement = request->getStatement(); // sql text if (statement->sqlText) record.storeString(f_mon_stmt_sql_text, *statement->sqlText); // explained plan if (plan.hasData()) record.storeString(f_mon_stmt_expl_plan, plan); // statistics const int stat_id = fb_utils::genUniqueId(); record.storeGlobalId(f_mon_stmt_stat_id, getGlobalId(stat_id)); record.write(); putStatistics(record, request->req_stats, stat_id, stat_statement); putMemoryUsage(record, request->req_memory_stats, stat_id, stat_statement); }
void RecordSource::printInversion(thread_db* tdbb, const InversionNode* inversion, string& plan, bool detailed, unsigned level, bool navigation) { if (detailed) plan += printIndent(++level); switch (inversion->type) { case InversionNode::TYPE_AND: if (detailed) plan += "Bitmap And"; printInversion(tdbb, inversion->node1, plan, detailed, level); printInversion(tdbb, inversion->node2, plan, detailed, level); break; case InversionNode::TYPE_OR: case InversionNode::TYPE_IN: if (detailed) plan += "Bitmap Or"; printInversion(tdbb, inversion->node1, plan, detailed, level); printInversion(tdbb, inversion->node2, plan, detailed, level); break; case InversionNode::TYPE_DBKEY: if (detailed) plan += "DBKEY"; break; case InversionNode::TYPE_INDEX: { const IndexRetrieval* const retrieval = inversion->retrieval; const jrd_rel* const relation = retrieval->irb_relation; MetaName indexName; if (retrieval->irb_name && retrieval->irb_name->hasData()) indexName = *retrieval->irb_name; else indexName.printf("<index id %d>", retrieval->irb_index + 1); if (detailed) { if (!navigation) plan += "Bitmap" + printIndent(++level); const index_desc& idx = retrieval->irb_desc; const bool uniqueIdx = (idx.idx_flags & idx_unique); const USHORT segCount = idx.idx_count; const USHORT minSegs = MIN(retrieval->irb_lower_count, retrieval->irb_upper_count); const USHORT maxSegs = MAX(retrieval->irb_lower_count, retrieval->irb_upper_count); const bool equality = (retrieval->irb_generic & irb_equality); const bool partial = (retrieval->irb_generic & irb_partial); const bool fullscan = (maxSegs == 0); const bool unique = uniqueIdx && equality && (minSegs == segCount); string bounds; if (!unique && !fullscan) { if (retrieval->irb_lower_count && retrieval->irb_upper_count) { if (equality) { if (partial) bounds.printf(" (partial match: %d/%d)", maxSegs, segCount); else bounds.printf(" (full match)"); } else { bounds.printf(" (lower bound: %d/%d, upper bound: %d/%d)", retrieval->irb_lower_count, segCount, retrieval->irb_upper_count, segCount); } } else if (retrieval->irb_lower_count) { bounds.printf(" (lower bound: %d/%d)", retrieval->irb_lower_count, segCount); } else if (retrieval->irb_upper_count) { bounds.printf(" (upper bound: %d/%d)", retrieval->irb_upper_count, segCount); } } plan += "Index " + printName(tdbb, indexName.c_str()) + (fullscan ? " Full" : unique ? " Unique" : " Range") + " Scan" + bounds; } else { plan += (plan.hasData() ? ", " : "") + printName(tdbb, indexName.c_str(), false); } } break; default: fb_assert(false); } }