diff --git a/source/app.d b/source/app.d index 977c0ca..3b56af9 100644 --- a/source/app.d +++ b/source/app.d @@ -11,10 +11,30 @@ import std.conv : to; import std.stdio : writeln, writefln; import std.getopt; import std.algorithm : canFind; +import core.sys.posix.unistd : readlink; import core.stdc.stdint; import std.exception; +import std.path : baseName; + +/// Вернуть путь для fd из события PRE_CONTENT. +/// Может вернуть "(deleted)" или пустую строку, если объект без имени. +string pathFromEventFd(int fd) +{ + // Конструируем путь в /proc/self/fd + auto linkPath = "/proc/self/fd/" ~ fd.to!string; + char[4096] buf; + + // readlink не добавляет '\0' + auto n = readlink(linkPath.toStringz, buf.ptr, buf.length); + if (n < 0) + { + return ""; + } + return cast(string) buf[0 .. n].idup; +} + // Удобная печать маски (для живых логов) string maskToStr(uint64_t m) { @@ -184,6 +204,15 @@ void main(string[] args) foreach (ev; events) { + if (tag == TAG_PRE && (ev.isOpenPerm || ev.isAccessPerm)) + { + string path = pathFromEventFd(ev.eventFd); + writeln("Попытка доступа к: ", path.length ? path + : "<неизвестно>"); + // ev.respond(FAN_ALLOW); // или FAN_DENY по своей политике + baseName(path) == "test" ? ev.respond(FAN_DENY) : ev.respond(FAN_ALLOW); + } + // Лог writefln("[%s] pid=%s mask=%s name=%s", (tag == TAG_PRE) ? "PRE" : "NOTIF", @@ -192,28 +221,28 @@ void main(string[] args) ev.name.length ? ev.name : "(unknown)"); // --- ВЕТКА РЕШЕНИЯ ДЛЯ PERM-СОБЫТИЙ --- - if (tag == TAG_PRE && - (ev.isOpenPerm || ev.isAccessPerm || ev.isOpenExecPerm)) - { - // Пример «политики»: запрещать выполнение из временных директорий - // (поменяй на свои условия) - bool deny = false; + // if (tag == TAG_PRE && + // (ev.isOpenPerm || ev.isAccessPerm || ev.isOpenExecPerm)) + // { + // // Пример «политики»: запрещать выполнение из временных директорий + // // (поменяй на свои условия) + // bool deny = false; - // простейший сэмпл-правил - auto nm = ev.name; - if (nm.length) - { - if (nm.canFind("/tmp/") && ev.isOpenExecPerm) - { - deny = true; - } - } + // // простейший сэмпл-правил + // auto nm = ev.name; + // if (nm.length) + // { + // if (nm.canFind("/tmp/") && ev.isOpenExecPerm) + // { + // deny = true; + // } + // } - // Отправляем решение ядру - ev.respond(deny ? FAN_DENY : FAN_ALLOW); + // // Отправляем решение ядру + // ev.respond(deny ? FAN_DENY : FAN_ALLOW); - writefln(" -> %s", deny ? "DENY" : "ALLOW"); - } + // writefln(" -> %s", deny ? "DENY" : "ALLOW"); + // } // --- ПОСТ-ФАКТУМ УВЕДОМЛЕНИЯ --- if (tag == TAG_NOTIF)