Esempio n. 1
0
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));
}
Esempio n. 2
0
	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);
	}
Esempio n. 3
0
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;
}
Esempio n. 4
0
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;
	}
}
Esempio n. 5
0
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;
}
Esempio n. 6
0
	void prepareName(Firebird::string& s, char c)
	{
		for (unsigned i = 0; i < s.length(); ++i)
		{
			if (s[i] == c)
			{
				s.insert(i++, 1, c);
			}
		}
	}
Esempio n. 7
0
// 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;
}
Esempio n. 8
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);
}
Esempio n. 9
0
// 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;
}
Esempio n. 10
0
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();
}
Esempio n. 11
0
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);
}
Esempio n. 12
0
	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);
	}
Esempio n. 13
0
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);
}