static void stuff_stack_trace(const jrd_req* request) { Firebird::string sTrace; bool isEmpty = true; for (const jrd_req* req = request; req; req = req->req_caller) { const JrdStatement* statement = req->getStatement(); Firebird::string name; if (statement->triggerName.length()) { name = "At trigger '"; name += statement->triggerName.c_str(); } else if (statement->procedure) { name = statement->parentStatement ? "At sub procedure '" : "At procedure '"; name += statement->procedure->getName().toString().c_str(); } else if (statement->function) { name = statement->parentStatement ? "At sub function '" : "At function '"; name += statement->function->getName().toString().c_str(); } if (! name.isEmpty()) { name.trim(); if (sTrace.length() + name.length() + 2 > MAX_STACK_TRACE) break; if (isEmpty) { isEmpty = false; sTrace += name + "'"; } else { sTrace += "\n" + name + "'"; } if (req->req_src_line) { Firebird::string src_info; src_info.printf(" line: %"ULONGFORMAT", col: %"ULONGFORMAT, req->req_src_line, req->req_src_column); if (sTrace.length() + src_info.length() > MAX_STACK_TRACE) break; sTrace += src_info; } } } if (!isEmpty) ERR_post_nothrow(Arg::Gds(isc_stack_trace) << Arg::Str(sTrace)); }
void grantRevokeAdmin(Firebird::IUser* user, bool ignoreRevoke = false) { if (!user->admin()->entered()) { return; } Firebird::LocalStatus s; Firebird::CheckStatusWrapper statusWrapper(&s); Firebird::string userName(user->userName()->get()); prepareName(userName, '"'); Firebird::string sql; if (user->admin()->get() == 0) { Firebird::string userName2(user->userName()->get()); prepareName(userName2, '\''); Firebird::string selGrantor; selGrantor.printf("SELECT RDB$GRANTOR FROM RDB$USER_PRIVILEGES " "WHERE RDB$USER = '******' AND RDB$RELATION_NAME = '%s' AND RDB$PRIVILEGE = 'M'", userName2.c_str(), ADMIN_ROLE); Message out; Field<Varying> grantor(out, MAX_SQL_IDENTIFIER_SIZE); Firebird::IResultSet* curs = att->openCursor(&statusWrapper, tra, selGrantor.length(), selGrantor.c_str(), SQL_DIALECT_V6, NULL, NULL, out.getMetadata(), NULL, 0); check(&statusWrapper); bool hasGrant = curs->fetchNext(&statusWrapper, out.getBuffer()) == Firebird::IStatus::RESULT_OK; curs->close(&statusWrapper); check(&statusWrapper); if (hasGrant) { selGrantor = grantor; prepareName(selGrantor, '"'); sql.printf("REVOKE %s FROM \"%s\" GRANTED BY \"%s\"", ADMIN_ROLE, userName.c_str(), selGrantor.c_str()); } else { if (ignoreRevoke) return; // no grant - let engine produce correct error message sql.printf("REVOKE %s FROM \"%s\"", ADMIN_ROLE, userName.c_str()); } } else { sql.printf("GRANT %s TO \"%s\"", ADMIN_ROLE, userName.c_str()); } att->execute(&statusWrapper, tra, sql.length(), sql.c_str(), SQL_DIALECT_V6, NULL, NULL, NULL, NULL); check(&statusWrapper); }
bool readenv(const char* env_name, Firebird::PathName& env_value) { Firebird::string result; bool rc = readenv(env_name, result); env_value.assign(result.c_str(), result.length()); return rc; }
void PreparedStatement::init(thread_db* tdbb, Attachment* attachment, jrd_tra* transaction, const Firebird::string& text, bool isInternalRequest) { AutoSetRestore<SSHORT> autoAttCharset(&attachment->att_charset, (isInternalRequest ? CS_METADATA : attachment->att_charset)); request = NULL; try { const Database& dbb = *tdbb->getDatabase(); const int dialect = isInternalRequest || (dbb.dbb_flags & DBB_DB_SQL_dialect_3) ? SQL_DIALECT_V6 : SQL_DIALECT_V5; request = DSQL_prepare(tdbb, attachment, transaction, text.length(), text.c_str(), dialect, NULL, NULL, isInternalRequest); const DsqlCompiledStatement* statement = request->getStatement(); if (statement->getSendMsg()) parseDsqlMessage(statement->getSendMsg(), inValues, inMetadata, inMessage); if (statement->getReceiveMsg()) parseDsqlMessage(statement->getReceiveMsg(), outValues, outMetadata, outMessage); } catch (const Exception&) { if (request) { DSQL_free_statement(tdbb, request, DSQL_drop); } throw; } }
TracePlugin* FB_CARG TraceFactoryImpl::trace_create(Firebird::IStatus* status, TraceInitInfo* initInfo) { Firebird::MasterInterfacePtr master; const char* dbname = NULL; try { master->upgradeInterface(initInfo, FB_TRACE_INIT_INFO_VERSION, upInfo); dbname = initInfo->getDatabaseName(); if (!dbname) dbname = ""; TracePluginConfig config; TraceCfgReader::readTraceConfiguration(initInfo->getConfigText(), dbname, config); TraceDatabaseConnection* connection = initInfo->getConnection(); if (connection) master->upgradeInterface(connection, FB_TRACE_CONNECTION_VERSION, upInfo); if (!config.enabled || (config.connection_id && connection && (connection->getConnectionID() != SLONG(config.connection_id)))) { return NULL; // Plugin is not needed, no error happened. } Firebird::AutoPtr<TraceLogWriter, Firebird::SimpleRelease<TraceLogWriter> > logWriter(initInfo->getLogWriter()); if (logWriter) config.log_filename = ""; return new TracePluginImpl(config, initInfo); // Everything is ok, we created a plugin } catch (Firebird::Exception& ex) { // put error into trace log TraceLogWriter* logWriter = initInfo->getLogWriter(); if (logWriter) { master->upgradeInterface(logWriter, FB_TRACE_LOG_WRITER_VERSION, upInfo); const char* strEx = TracePluginImpl::marshal_exception(ex); Firebird::string err; if (dbname) err.printf("Error creating trace session for database \"%s\":\n%s\n", dbname, strEx); else err.printf("Error creating trace session for service manager attachment:\n%s\n", strEx); logWriter->write(err.c_str(), err.length()); logWriter->release(); } else ex.stuffException(status); } return NULL; }
void prepareName(Firebird::string& s, char c) { for (unsigned i = 0; i < s.length(); ++i) { if (s[i] == c) { s.insert(i++, 1, c); } } }
// static function bool Switches::matchSwitch(const Firebird::string& sw, const char* target, size_t n) { /************************************** * * m a t c h S w i t c h * ************************************** * * Functional description * Returns true if switch matches target * **************************************/ if (n < sw.length()) { return false; } n = sw.length(); return memcmp(sw.c_str(), target, n) == 0; }
ISC_STATUS API_ROUTINE isc_delete_user(ISC_STATUS* status, const USER_SEC_DATA* input_user_data) { /************************************** * * i s c _ d e l e t e _ u s e r * ************************************** * * Functional description * Deletes a user from the server's security * database. * Return 0 if the user was deleted * * Return > 0 if any error occurs. * **************************************/ Auth::StackUserData userInfo; userInfo.op = Auth::DEL_OPER; Firebird::LocalStatus s; Firebird::CheckStatusWrapper statusWrapper(&s); if (input_user_data->user_name) { Firebird::string work = input_user_data->user_name; if (work.length() > USERNAME_LENGTH) { return user_error(status, isc_usrname_too_long); } Firebird::string::size_type l = work.find(' '); if (l != Firebird::string::npos) { work.resize(l); } userInfo.user.set(&statusWrapper, work.c_str()); Firebird::check(&statusWrapper); userInfo.user.setEntered(&statusWrapper, 1); Firebird::check(&statusWrapper); } else { return user_error(status, isc_usrname_required); } return executeSecurityCommand(status, input_user_data, userInfo); }
// fetch password from file FetchPassResult fetchPassword(const Firebird::PathName& name, const char*& password) { InputFile file(name); if (!file) { return FETCH_PASS_FILE_OPEN_ERROR; } Firebird::string pwd; if (! pwd.LoadFromFile(file.getStdioFile())) { return ferror(file.getStdioFile()) ? FETCH_PASS_FILE_READ_ERROR : FETCH_PASS_FILE_EMPTY; } // this is planned leak of a few bytes of memory in utilities char* pass = FB_NEW_POOL(*getDefaultMemoryPool()) char[pwd.length() + 1]; pwd.copyTo(pass, pwd.length() + 1); password = pass; return FETCH_PASS_OK; }
size_t PAR_name(CompilerScratch* csb, Firebird::string& name) { /************************************** * * P A R _ n a m e * ************************************** * * Functional description * Parse a counted string of virtually unlimited size * (up to 64K, actually <= 255), returning count. * **************************************/ size_t l = csb->csb_blr_reader.getByte(); char* s = name.getBuffer(l); while (l--) *s++ = csb->csb_blr_reader.getByte(); return name.length(); }
int CLIB_ROUTINE main( int argc, char **argv) { /************************************** * * m a i n * ************************************** * * Functional description * If there is no command line, prompt for one, read it * and make an artificial argc/argv. Otherwise, pass * the specified argc/argv to IBMGR_exec_line (see below). * **************************************/ fprintf(stderr, "*** fbmgr is deprecated, will be removed soon ***\n"); gds__log("*** fbmgr is deprecated, will be removed soon ***"); // Let's see if we have something in environment variables Firebird::string user, password; fb_utils::readenv(ISC_USER, user); fb_utils::readenv(ISC_PASSWORD, password); Firebird::string host; // MMM - do not allow to change host now //fb_utils::readenv("ISC_HOST", host); TEXT msg[MSG_LEN]; // Let's get a real user name. This info is used by // START server command. Because server is not running // we can not check the password, thus we require a // real user to be root or FIREBIRD_USER_NAME or // INTERBASE_USER_NAME or INTERBASE_USER_SHORT const struct passwd* pw = getpwuid(getuid()); if (pw == NULL) { perror("getpwuid"); SRVRMGR_msg_get(MSG_GETPWFAIL, msg); fprintf(OUTFILE, "%s\n", msg); exit(FINI_ERROR); } strcpy(ibmgr_data.real_user, pw->pw_name); if (!strcmp(pw->pw_name, "root") || !strcmp(pw->pw_name, FIREBIRD_USER_NAME) || !strcmp(pw->pw_name, INTERBASE_USER_NAME) || !strcmp(pw->pw_name, INTERBASE_USER_SHORT)) { strcpy(ibmgr_data.user, SYSDBA_USER_NAME); } else copy_str_upper(ibmgr_data.user, pw->pw_name); if (user.length()) copy_str_upper(ibmgr_data.user, user.c_str()); if (password.length()) strcpy(ibmgr_data.password, password.c_str()); else ibmgr_data.password[0] = '\0'; if (host.length()) strcpy(ibmgr_data.host, host.c_str()); else strcpy(ibmgr_data.host, "localhost"); // Shutdown is not in progress and we are not attached to service yet. // But obviously we will need attachment. ibmgr_data.shutdown = false; ibmgr_data.attached = 0; ibmgr_data.reattach |= (REA_HOST | REA_USER | REA_PASSWORD); // No pidfile by default ibmgr_data.pidfile[0] = 0; // Special case a solitary -z switch. // Print the version and then drop into prompt mode. if (argc == 2 && *argv[1] == '-' && (argv[1][1] == 'Z' || argv[1][1] == 'z')) { parse_cmd_line(argc, argv, false); argc--; } SSHORT ret; if (argc > 1) { ret = parse_cmd_line(argc, argv, true); if (ret == FB_SUCCESS) { ret = SRVRMGR_exec_line(&ibmgr_data); if (ret) { SRVRMGR_msg_get(ret, msg); fprintf(OUTFILE, "%s\n", msg); } // We also need to check the shutdown flag here (if operation was // -shut -[noat|notr]) and, depending on what we want to do, either // wait here on some sort of a shutdown event, or go to the prompt mode SRVRMGR_cleanup(&ibmgr_data); exit(FINI_OK); } else if (ret != ACT_PROMPT) exit(FINI_OK); } int local_argc; SCHAR* local_argv[MAXARGS]; TEXT stuff[MAXSTUFF]; for (;;) { if (get_line(&local_argc, local_argv, stuff)) break; if (local_argc > 1) { ret = parse_cmd_line(local_argc, local_argv, false); if (ret == ACT_QUIT) break; if (ret == FB_SUCCESS) { ret = SRVRMGR_exec_line(&ibmgr_data); if (ret) { SRVRMGR_msg_get(ret, msg); fprintf(OUTFILE, "%s\n", msg); } } } } SRVRMGR_cleanup(&ibmgr_data); exit(FINI_OK); }
void CryptoManager::changeCryptState(thread_db* tdbb, const Firebird::string& plugName) { if (plugName.length() > 31) { (Arg::Gds(isc_cp_name_too_long) << Arg::Num(31)).raise(); } bool newCryptState = plugName.hasData(); { // window scope Header hdr(tdbb, LCK_write); // Check header page for flags if (hdr->hdr_flags & Ods::hdr_crypt_process) { (Arg::Gds(isc_cp_process_active)).raise(); } bool headerCryptState = hdr->hdr_flags & Ods::hdr_encrypted; if (headerCryptState == newCryptState) { (Arg::Gds(isc_cp_already_crypted)).raise(); } fb_assert(stateLock); // Take exclusive stateLock bool ret = needLock ? LCK_lock(tdbb, stateLock, LCK_PW, LCK_WAIT) : LCK_convert(tdbb, stateLock, LCK_PW, LCK_WAIT); if (!ret) { fb_assert(tdbb->tdbb_status_vector[1]); ERR_punt(); } fb_utils::init_status(tdbb->tdbb_status_vector); needLock = false; // Load plugin if (newCryptState) { loadPlugin(plugName.c_str()); } crypt = newCryptState; // Write modified header page Ods::header_page* header = hdr.write(); if (crypt) { header->hdr_flags |= Ods::hdr_encrypted; plugName.copyTo(header->hdr_crypt_plugin, sizeof header->hdr_crypt_plugin); } else { header->hdr_flags &= ~Ods::hdr_encrypted; } header->hdr_flags |= Ods::hdr_crypt_process; process = true; } // Trigger lock on ChangeCryptState if (!LCK_convert(tdbb, stateLock, LCK_EX, LCK_WAIT)) { ERR_punt(); } if (!LCK_convert(tdbb, stateLock, LCK_SR, LCK_WAIT)) { ERR_punt(); } fb_utils::init_status(tdbb->tdbb_status_vector); // Now we may set hdr_crypt_page for crypt thread { // window scope Header hdr(tdbb, LCK_write); Ods::header_page* header = hdr.write(); header->hdr_crypt_page = 1; } startCryptThread(tdbb); }
ISC_STATUS API_ROUTINE isc_modify_user(ISC_STATUS* status, const USER_SEC_DATA* input_user_data) { /************************************** * * i s c _ m o d i f y _ u s e r * ************************************** * * Functional description * Adds a user to the server's security * database. * Return 0 if the user was added * * Return > 0 if any error occurs. * **************************************/ Auth::StackUserData userInfo; userInfo.op = Auth::MOD_OPER; Firebird::LocalStatus s; Firebird::CheckStatusWrapper statusWrapper(&s); if (input_user_data->user_name) { Firebird::string work = input_user_data->user_name; if (work.length() > USERNAME_LENGTH) { return user_error(status, isc_usrname_too_long); } Firebird::string::size_type l = work.find(' '); if (l != Firebird::string::npos) { work.resize(l); } userInfo.user.set(&statusWrapper, work.c_str()); check(&statusWrapper); userInfo.user.setEntered(&statusWrapper, 1); check(&statusWrapper); } else { return user_error(status, isc_usrname_required); } if (input_user_data->password) { userInfo.pass.set(&statusWrapper, input_user_data->password); check(&statusWrapper); userInfo.pass.setEntered(&statusWrapper, 1); check(&statusWrapper); } else { return user_error(status, isc_password_required); } copyField(userInfo.u, input_user_data->uid, input_user_data->sec_flags & sec_uid_spec); copyField(userInfo.g, input_user_data->gid, input_user_data->sec_flags & sec_gid_spec); copyField(userInfo.group, input_user_data->group_name, input_user_data->sec_flags & sec_group_name_spec); copyField(userInfo.first, input_user_data->first_name, input_user_data->sec_flags & sec_first_name_spec); copyField(userInfo.middle, input_user_data->middle_name, input_user_data->sec_flags & sec_middle_name_spec); copyField(userInfo.last, input_user_data->last_name, input_user_data->sec_flags & sec_last_name_spec); return executeSecurityCommand(status, input_user_data, userInfo); }