Получение пользователя, но не 100%
This commit is contained in:
parent
bc02ac8518
commit
2876a45a85
3 changed files with 159 additions and 1 deletions
16
source/app.d
16
source/app.d
|
@ -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);
|
||||||
|
|
|
@ -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
139
source/event_actor.d
Normal 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;
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue