Получение пользователя, но не 100%

This commit is contained in:
Alexander Zhirov 2025-08-29 02:33:55 +03:00
parent bc02ac8518
commit 2876a45a85
Signed by: alexander
GPG key ID: C8D8BE544A27C511
3 changed files with 159 additions and 1 deletions

View file

@ -2,6 +2,7 @@ module app;
import dfanotify; // твой модуль сверху import dfanotify; // твой модуль сверху
import depoll; // новый модуль для epoll import depoll; // новый модуль для epoll
import event_actor;
import core.sys.posix.fcntl : O_RDONLY, O_LARGEFILE; import core.sys.posix.fcntl : O_RDONLY, O_LARGEFILE;
import core.stdc.errno : errno; import core.stdc.errno : errno;
@ -277,7 +278,16 @@ void main(string[] args)
foreach (ev; events) foreach (ev; events)
{ {
auto pname = eventProcessName(ev.pid); auto pname = eventProcessName(ev.pid);
writeln("pid = ", ev.pid, "\tproc = ", pname, "\tmask = ", maskToStr(ev.mask)); // writeln("pid = ", ev.pid, "\tproc = ", pname, "\tmask = ", maskToStr(ev.mask));
writefln("[%s] pid = %s proc = %s mask = %s",
(tag == TAG_PRE) ? "PRE" : "NOTIF",
ev.pid, pname,
maskToStr(ev.mask)
);
auto actor = eventActorFromPid(ev.pid);
writeln("user=", actor.user, " uid=", actor.uid,
" ruid=", actor.ruid, "(", actor.ruser, ")",
" euid=", actor.euid, "(", actor.euser, ")");
if (tag == TAG_PRE && (ev.isOpenPerm || ev.isAccessPerm)) if (tag == TAG_PRE && (ev.isOpenPerm || ev.isAccessPerm))
{ {
@ -329,6 +339,10 @@ void main(string[] args)
// snag --config ... create --comment "CLOSE_WRITE - <name>" ... // snag --config ... create --comment "CLOSE_WRITE - <name>" ...
writefln(" -> HANDLE CLOSE_WRITE for: %s", ev.name); writefln(" -> HANDLE CLOSE_WRITE for: %s", ev.name);
} }
else if (ev.isMoved)
{
writefln(" -> HANDLE MOVED for: %s", ev.name);
}
else if (ev.isModify) else if (ev.isModify)
{ {
writefln(" -> HANDLE MODIFY for: %s", ev.name); writefln(" -> HANDLE MODIFY for: %s", ev.name);

View file

@ -83,6 +83,11 @@ class FanotifyEvent
return (mask & FAN_ACCESS) != 0; return (mask & FAN_ACCESS) != 0;
} }
bool isMoved() const
{
return (mask & FAN_MOVED_FROM) != 0;
}
bool isCreate() const bool isCreate() const
{ {
return (mask & FAN_CREATE) != 0; return (mask & FAN_CREATE) != 0;

139
source/event_actor.d Normal file
View file

@ -0,0 +1,139 @@
module event_actor;
import core.sys.posix.pwd : passwd, getpwuid_r;
import core.sys.posix.sys.types : uid_t;
import core.stdc.stdlib : malloc, free;
import core.stdc.string : strlen;
import std.file : readText, exists;
import std.string : splitLines, strip;
import std.conv : to;
// для токенизации по пробельным
import std.ascii : isWhite;
import std.algorithm.iteration : splitter;
import std.array : array;
struct EventActor
{
uid_t uid; // выбранный UID (loginuid если есть, иначе ruid)
string user; // имя пользователя для uid (может быть пустым)
uid_t ruid, euid, suid, fsuid;
string ruser, euser, suser, fsuser;
bool hasLoginuid;
uid_t loginuid;
string loginuser;
}
private string userName(uid_t uid)
{
enum BUF = 4096;
auto buf = cast(char*) malloc(BUF);
scope (exit)
if (buf)
free(buf);
passwd pwd;
passwd* outp;
auto rc = getpwuid_r(uid, &pwd, buf, BUF, &outp);
if (rc == 0 && outp !is null)
{
return pwd.pw_name[0 .. strlen(pwd.pw_name)].idup;
}
return "";
}
/// Парсит строку вида: "Uid:\t<ruid>\t<euid>\t<suid>\t<fsuid>"
private bool parseUidLine(string line, out uid_t r, out uid_t e, out uid_t s, out uid_t f)
{
// разобьём по любым пробельным символам
auto toks = line.splitter!isWhite.array; // ["Uid:", "1000", "1000", "1000", "1000"]
if (toks.length >= 5 && toks[0] == "Uid:")
{
try
{
r = toks[1].to!uid_t;
e = toks[2].to!uid_t;
s = toks[3].to!uid_t;
f = toks[4].to!uid_t;
return true;
}
catch (Exception e)
{
}
}
return false;
}
/// Главная функция: кто инициировал событие (по PID из fanotify_event_metadata)
EventActor eventActorFromPid(int pid)
{
EventActor a;
if (pid <= 0)
return a;
const base = "/proc/" ~ pid.to!string ~ "/";
const statusPath = base ~ "status";
if (exists(statusPath))
{
try
{
auto txt = readText(statusPath);
uid_t r = 0, e = 0, s = 0, f = 0;
foreach (line; txt.splitLines())
{
// ищем строку "Uid:"
if (line.length >= 4 && line[0 .. 4] == "Uid:")
{
if (parseUidLine(line, r, e, s, f))
{
a.ruid = r;
a.euid = e;
a.suid = s;
a.fsuid = f;
a.ruser = userName(r);
a.euser = userName(e);
a.suser = userName(s);
a.fsuser = userName(f);
}
break;
}
}
}
catch (Exception e)
{
}
}
// loginuid — владелец сессии (если audit включён)
const loginPath = base ~ "loginuid";
if (exists(loginPath))
{
try
{
auto s = readText(loginPath).strip;
if (s.length)
{
a.loginuid = s.to!uid_t;
a.loginuser = userName(a.loginuid);
a.hasLoginuid = true;
}
}
catch (Exception e)
{
}
}
// выбираем «итогового» пользователя
if (a.hasLoginuid)
{
a.uid = a.loginuid;
a.user = a.loginuser.length ? a.loginuser : ("uid:" ~ a.loginuid.to!string);
}
else
{
a.uid = a.ruid;
a.user = a.ruser.length ? a.ruser : ("uid:" ~ a.ruid.to!string);
}
return a;
}