<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"><channel><category>pcsoft.br.windev</category><copyright>Copyright 2026, PC SOFT</copyright><lastBuildDate>5 May 2025 13:51:56 Z</lastBuildDate><pubDate>5 May 2025 13:51:56 Z</pubDate><description>Solução do bloqueio de comandos no PostgreSQL para não executar os comandos:&#13;
 &#13;
 RENAME, &#13;
 ALTER TABLE, &#13;
 ALTER COLUMN&#13;
 GRANT, &#13;
 DROP, &#13;
 TRUNCATE &#13;
 DELETE, &#13;
&#13;
E com registro em log e suporte para Windows, macOS e Linux.&#13;
&#13;
Solução para Bloqueio de Comandos no PostgreSQL&#13;
Vamos implementar uma funcionalidade no PostgreSQL que bloqueia os comandos especificados (DROP, TRUNCATE, DELETE, RENAME, ALTER TABLE, ALTER COLUMN, GRANT) com base em um arquivo de configuração .ini e registra todas as tentativas bloqueadas em um log. A solução será portátil para Windows, macOS e Linux.&#13;
Visão Geral&#13;
	1	Arquivo de Configuração: Um arquivo restrict_commands.ini define quais comandos são permitidos ou bloqueados por banco de dados.&#13;
	2	Verificação de Permissões: Antes de executar cada comando, o código verifica se ele é permitido no banco de dados atual.&#13;
	3	Registro em Log: Tentativas bloqueadas são registradas em um arquivo de log específico para cada banco de dados.&#13;
	4	Portabilidade: O código usa funções do PostgreSQL que funcionam em todos os sistemas operacionais suportados.&#13;
&#13;
Código-Fonte Atualizado&#13;
1. `restrict_commands.c`&#13;
Este arquivo contém a lógica principal para verificar permissões e registrar tentativas bloqueadas.&#13;
&#13;
&#13;
#include "postgres.h"&#13;
#include "utils/guc.h"&#13;
#include "storage/fd.h"&#13;
#include &#13;
#include &#13;
#include &#13;
#include &#13;
&#13;
static char INI_PATH[1024];&#13;
static char LOG_PATH_BASE[1024];&#13;
&#13;
// Inicializa caminhos dinamicamente na inicialização do módulo&#13;
void _PG_init(void) {&#13;
    char share_path[MAXPGPATH];&#13;
    get_share_path(my_exec_path, share_path);&#13;
    snprintf(INI_PATH, sizeof(INI_PATH), "%s/restrict_commands.ini", share_path);&#13;
    snprintf(LOG_PATH_BASE, sizeof(LOG_PATH_BASE), "%s/", DataDir);&#13;
}&#13;
&#13;
bool check_command_permission(const char *dbname, const char *operation) {&#13;
    FILE *fp = AllocateFile(INI_PATH, "r");&#13;
    if (!fp) {&#13;
        ereport(WARNING, (errmsg("Cannot open INI file: %s", INI_PATH)));&#13;
        return true; // Permite por padrão se não conseguir ler&#13;
    }&#13;
&#13;
    char line[256];&#13;
    char section[128];&#13;
    bool in_section = false;&#13;
    snprintf(section, sizeof(section), "[%s]", dbname);&#13;
&#13;
    while (fgets(line, sizeof(line), fp)) {&#13;
        if (strncmp(line, section, strlen(section)) == 0) {&#13;
            in_section = true;&#13;
            continue;&#13;
        }&#13;
        if (in_section &amp;&amp; line[0] == '[')&#13;
            break;&#13;
&#13;
        if (in_section &amp;&amp; strstr(line, operation)) {&#13;
            if (strstr(line, "false")) {&#13;
                FreeFile(fp);&#13;
                log_blocked_command(dbname, operation);&#13;
                return false;&#13;
            }&#13;
        }&#13;
    }&#13;
&#13;
    FreeFile(fp);&#13;
    return true; // Permite por padrão se não especificado&#13;
}&#13;
&#13;
void log_blocked_command(const char *dbname, const char *operation) {&#13;
    char logpath[512];&#13;
    snprintf(logpath, sizeof(logpath), "%s%s_blocked.log", LOG_PATH_BASE, dbname);&#13;
&#13;
    // Verifica permissões de escrita&#13;
    if (access(LOG_PATH_BASE, W_OK) != 0) {&#13;
        ereport(WARNING, (errmsg("Cannot write to log directory: %s", LOG_PATH_BASE)));&#13;
        return;&#13;
    }&#13;
&#13;
    FILE *logf = AllocateFile(logpath, "a");&#13;
    if (!logf) {&#13;
        ereport(WARNING, (errmsg("Cannot open log file: %s", logpath)));&#13;
        return;&#13;
    }&#13;
&#13;
    time_t now = time(NULL);&#13;
    char *timestamp = ctime(&amp;now);&#13;
    timestamp[strlen(timestamp)-1] = '\0';&#13;
&#13;
    char *user = GetUserNameOrNull();&#13;
    if (!user) user = "unknown";&#13;
&#13;
    fprintf(logf, "[%s] USER: %s tried: %s (BLOCKED)\n", timestamp, user, operation);&#13;
    FreeFile(logf);&#13;
}&#13;
&#13;
&#13;
&#13;
2. `restrict_commands.h`&#13;
Cabeçalho para as funções definidas em restrict_commands.c.&#13;
#ifndef RESTRICT_COMMANDS_H&#13;
#define RESTRICT_COMMANDS_H&#13;
&#13;
bool check_command_permission(const char *dbname, const char *operation);&#13;
void log_blocked_command(const char *dbname, const char *operation);&#13;
&#13;
#endif /* RESTRICT_COMMANDS_H */&#13;
&#13;
Modificações nos Arquivos do PostgreSQL&#13;
Para bloquear os comandos especificados, modificamos os arquivos onde eles são processados, adicionando verificações de permissão.&#13;
&#13;
&#13;
&#13;
3.1. `DROP`&#13;
	•	Arquivo: src/backend/commands/dbcommands.c&#13;
	•	Função: DropDatabase()&#13;
	•	Modificação: Adicione no início da função:&#13;
#include "utils/restrict_commands.h"&#13;
if (!check_command_permission(dbname, "drop")) {&#13;
    ereport(ERROR, (errmsg("DROP DATABASE is blocked for this database by policy")));&#13;
}&#13;
	•	Nota: Para DROP TABLE e similares, use RemoveRelations em tablecmds.c:&#13;
#include "utils/restrict_commands.h"&#13;
if (!check_command_permission(get_database_name(MyDatabaseId), "drop")) {&#13;
    ereport(ERROR, (errmsg("DROP is blocked for this database by policy")));&#13;
}&#13;
&#13;
&#13;
&#13;
3.2. `TRUNCATE`&#13;
	•	Arquivo: src/backend/commands/tablecmds.c&#13;
	•	Função: ExecuteTruncateGuts()&#13;
	•	Modificação: Adicione no início da função:&#13;
#include "utils/restrict_commands.h"&#13;
if (!check_command_permission(get_database_name(MyDatabaseId), "truncate")) {&#13;
    ereport(ERROR, (errmsg("TRUNCATE is blocked for this database by policy")));&#13;
}&#13;
&#13;
&#13;
&#13;
3.3. `DELETE`&#13;
	•	Arquivo: src/backend/commands/delete.c&#13;
	•	Função: ExecDelete()&#13;
	•	Modificação: Adicione no início da função:&#13;
#include "utils/restrict_commands.h"&#13;
if (!check_command_permission(get_database_name(MyDatabaseId), "delete")) {&#13;
    ereport(ERROR, (errmsg("DELETE is blocked for this database by policy")));&#13;
}&#13;
&#13;
&#13;
&#13;
3.4. `RENAME`&#13;
	•	Arquivo: src/backend/commands/tablecmds.c&#13;
	•	Função: RenameRelation()&#13;
	•	Modificação: Adicione no início da função:&#13;
#include "utils/restrict_commands.h"&#13;
if (!check_command_permission(get_database_name(MyDatabaseId), "rename")) {&#13;
    ereport(ERROR, (errmsg("RENAME is blocked for this database by policy")));&#13;
}&#13;
&#13;
&#13;
&#13;
3.5. `ALTER TABLE` e `ALTER COLUMN`&#13;
	•	Arquivo: src/backend/commands/tablecmds.c&#13;
	•	Função: AlterTable()&#13;
	•	Modificação: Adicione no início da função uma verificação geral para ALTER TABLE. Para ALTER COLUMN, verifique o tipo de comando:&#13;
#include "utils/restrict_commands.h"&#13;
if (!check_command_permission(get_database_name(MyDatabaseId), "alter_table")) {&#13;
    ereport(ERROR, (errmsg("ALTER TABLE is blocked for this database by policy")));&#13;
}&#13;
// Verificação específica para ALTER COLUMN&#13;
if (cmd-&gt;subtype == AT_AlterColumnType &amp;&amp;&#13;
    !check_command_permission(get_database_name(MyDatabaseId), "alter_column")) {&#13;
    ereport(ERROR, (errmsg("ALTER COLUMN is blocked for this database by policy")));&#13;
}&#13;
&#13;
&#13;
&#13;
3.6. `GRANT`&#13;
	•	Arquivo: src/backend/commands/grant.c&#13;
	•	Função: ExecGrantStmt()&#13;
	•	Modificação: Adicione no início da função:&#13;
#include "utils/restrict_commands.h"&#13;
if (!check_command_permission(get_database_name(MyDatabaseId), "grant")) {&#13;
    ereport(ERROR, (errmsg("GRANT is blocked for this database by policy")));&#13;
}&#13;
&#13;
&#13;
&#13;
3.7. Atualização do Makefile&#13;
	•	Arquivo: src/backend/utils/misc/Makefile&#13;
	•	Modificação: Adicione restrict_commands.o à lista de objetos:&#13;
OBJS = ... restrict_commands.o ...&#13;
&#13;
&#13;
&#13;
Exemplo de `restrict_commands.ini`&#13;
&#13;
Coloque este arquivo no diretório share do PostgreSQL (ex.: /usr/local/pgsql/share/ no Linux/macOS ou &#13;
&#13;
C:\Program Files\PostgreSQL\15\share no Windows).&#13;
[db_financeiro]&#13;
drop=false&#13;
truncate=false&#13;
delete=false&#13;
rename=false&#13;
alter_table=false&#13;
alter_column=false&#13;
grant=false&#13;
&#13;
[db_erp]&#13;
drop=false&#13;
truncate=true&#13;
delete=true&#13;
rename=true&#13;
alter_table=true&#13;
alter_column=true&#13;
grant=true&#13;
&#13;
[db_analytics]&#13;
drop=true&#13;
truncate=false&#13;
delete=false&#13;
rename=false&#13;
alter_table=false&#13;
alter_column=false&#13;
grant=false&#13;
&#13;
&#13;
&#13;
&#13;
Portabilidade para Windows, macOS e Linux&#13;
	•	O código usa funções do PostgreSQL como AllocateFile, FreeFile, get_share_path e DataDir, que são portáteis entre Windows, macOS e Linux.&#13;
	•	O arquivo .ini é lido de um caminho relativo ao diretório share, e os logs são gravados no diretório de dados (DataDir), garantindo compatibilidade com a estrutura de arquivos de cada sistema operacional.&#13;
	•	Nenhuma modificação específica por SO é necessária.&#13;
&#13;
&#13;
&#13;
Como Aplicar as Mudanças&#13;
	1	Adicione os arquivos restrict_commands.c e restrict_commands.h em src/backend/utils/misc/.&#13;
	2	Aplique as modificações nos arquivos listados acima.&#13;
	3	Compile o PostgreSQL com ./configure, make e make install.&#13;
	4	Coloque o arquivo restrict_commands.ini no diretório share.&#13;
	5	Reinicie o servidor PostgreSQL.&#13;
Os logs de tentativas bloqueadas serão gravados em /_blocked.log.&#13;
&#13;
&#13;
&#13;
Arquivos Modificados&#13;
#############&#13;
&#13;
Aqui está a lista final dos arquivos que devem ser modificados no código-fonte do PostgreSQL:&#13;
	1	src/backend/utils/misc/restrict_commands.c: Código principal para verificação e logging.&#13;
	2	src/include/utils/restrict_commands.h: Cabeçalho.&#13;
	3	src/backend/commands/dbcommands.c: Para DROP DATABASE.&#13;
	4	src/backend/commands/tablecmds.c: Para TRUNCATE, RENAME, ALTER TABLE, ALTER COLUMN, &#13;
&#13;
DROP TABLE.&#13;
	5	src/backend/commands/delete.c: Para DELETE.&#13;
	6	src/backend/commands/grant.c: Para GRANT.&#13;
	7	src/backend/utils/misc/Makefile: Adicionar restrict_commands.o.&#13;
&#13;
Essa solução atende aos requisitos de bloquear os comandos solicitados, registrar tentativas bloqueadas e funcionar de forma portátil em Windows, macOS e Linux.&#13;
&#13;
--&#13;
Adriano José Boller&#13;
______________________________________________&#13;
Consultor e Representante Oficial da&#13;
PcSoft no Brasil&#13;
+55 (41) 99949 1800&#13;
adrianoboller@gmail.com&#13;
skype: adrianoboller&#13;
http://wxinformatica.com.br/</description><ttl>30</ttl><generator>WEBDEV</generator><language>pt_BR</language><link>https://forum.pcsoft.fr/en-US/pcsoft.br.windev/4590-postgresql-solucao-atende-aos-requisitos-bloquear-comandos-solicitados/read.awp</link><title>PostgreSQL: Solução atende aos requisitos de bloquear os comandos solicitados, registrar tentativas bloqueadas e funcionar de forma portátil em Windows, macOS e Linux.</title><managingEditor>moderateur@pcsoft.fr (The moderator)</managingEditor><webMaster>webmaster@pcsoft.fr (The webmaster)</webMaster></channel></rss>
