Ich bin root Ich möchte wissen, ob ein Nicht-Root-Benutzer Schreibzugriff auf einige Dateien hat - Tausende von ihnen. Wie kann man effizient vorgehen und gleichzeitig die Erstellung von Prozessen vermeiden?
shell
files
permissions
users
Howard
quelle
quelle
access(2)
mit einer entsprechend eingestellten realen UID an (z. B. übersetresuid(2)
oder das tragbare Äquivalent)? Ich meine, ich würde es schwer haben, das von Bash aus zu tun, aber ich bin mir sicher, dass Perl / Python damit umgehen kann.[ -w
verwenden im Allgemeinen den Zugriff (2) oder einen gleichwertigen Wert . Sie müssen zusätzlich zu uid auch die Gids einstellen (wie su oder sudo). bash hat dafür keine eingebaute Unterstützung, zsh jedoch.chgrp
in jeder Shell verwenden.Antworten:
Vielleicht so:
Das obige Programm führt für jede Datei ein einzelnes externes Programm aus, nämlich
stat(1)
.Hinweis: Dies setzt voraus
bash(1)
, und die Linux-Inkarnation vonstat(1)
.Anmerkung 2: Bitte lesen Sie die nachstehenden Kommentare von Stéphane Chazelas zu Vergangenheit, Gegenwart, Zukunft und möglichen Gefahren und Einschränkungen dieses Ansatzes.
quelle
-
. Man könnte es ändern , um eine NUL getrennte Liste zu akzeptieren , statt mitread -d ''
util-linux
) gibt, die speziell für Linux geschrieben wurden, ist das, auf dasstat
Sie sich beziehen, kein GNU-Befehl, der auf die meisten Systeme portiert wurde, nicht nur auf Linux. Beachten Sie auch, dass Sie unterstat
Linux einen Befehl hatten, lange bevor GNUstat
geschrieben wurde (stat
zsh builtin).stat(1)
" geschrieben. Ich beziehe mich auf einestat(1)
, die die-c <format>
Syntax akzeptiert , im Gegensatz zu beispielsweise BSD-Syntax-f <format>
. Ich glaube auch, dass es ziemlich klar war, dass ich mich nicht darauf bezogstat(2)
. Ich bin mir sicher, dass eine Wiki-Seite über die Geschichte der allgemeinen Befehle sehr interessant wäre.TL; DR
Sie müssen das System fragen, ob der Benutzer über Schreibrechte verfügt. Die einzig zuverlässige Möglichkeit besteht darin, die effektive Benutzer-ID, die effektive Benutzer-ID und die ergänzende Benutzer-ID auf die des Benutzers umzustellen und den
access(W_OK)
Systemaufruf zu verwenden (auch wenn dies bei einigen Systemen / Konfigurationen Einschränkungen aufweist).Beachten Sie außerdem, dass das Fehlen einer Schreibberechtigung für eine Datei nicht unbedingt garantiert, dass Sie den Inhalt der Datei unter diesem Pfad nicht ändern können.
Die längere Geschichte
Lassen Sie uns überlegen , was es zum Beispiel für einen $ Benutzer nimmt Schreibzugriff zu haben , um
/foo/file.txt
(unter der Annahme keiner/foo
und/foo/file.txt
Symlinks sind)?Er braucht:
/
(keine Notwendigkeit fürread
)/foo
(keine Notwendigkeit fürread
)/foo/file.txt
Sie können bereits sehen, dass Ansätze (wie @ lcd047 oder @ apaul ), die nur die Berechtigung von überprüfen
file.txt
, nicht funktionieren, weil sie sagen könnten, dass siefile.txt
beschreibbar sind, selbst wenn der Benutzer keine Suchberechtigung für/
oder hat/foo
.Und ein Ansatz wie:
Funktioniert auch nicht, da keine Dateien in Verzeichnissen gemeldet werden, auf die der Benutzer keinen Lesezugriff hat (da
find
ausgeführt wird, weil der$user
Inhalt nicht aufgelistet werden kann), selbst wenn er darauf schreiben kann.Vergessen wir ACLs, schreibgeschützte Dateisysteme, FS-Flags (wie unveränderlich), andere Sicherheitsmaßnahmen (Apparmor, SELinux, die sogar zwischen verschiedenen Schreibweisen unterscheiden können) und konzentrieren wir uns nur auf traditionelle Berechtigungs- und Eigentumsattribute, um eine zu erhalten mit der erlaubnis (suchen oder schreiben) ist das schon ziemlich kompliziert und schwer auszudrücken
find
.Du brauchst:
In der
find
Syntax, hier als Beispiel mit einem Benutzer von UID 1 und GID 1 und 2, wäre das:Dass man Pflaumen die Verzeichnisse der Benutzer suchen haben , nicht direkt für und für andere Arten von Dateien (Symlinks ausgeschlossen , da sie nicht relevant sind), Schecks für den Schreibzugriff.
Wenn Sie auch den Schreibzugriff auf Verzeichnisse in Betracht ziehen möchten:
Oder für eine beliebige
$user
und deren Gruppenmitgliedschaft, die aus der Benutzerdatenbank abgerufen wird:(das ist 3 - Prozesse insgesamt:
id
,sed
undfind
)Am besten ist es, wenn Sie den Baum als root absteigen und die Berechtigungen als Benutzer für jede Datei prüfen.
(Das ist ein
find
Prozess plus einssudo
undsh
verarbeitet alle paar tausend Dateien[
undprintf
wird normalerweise in der Shell erstellt.)Oder mit
perl
:(3 Prozesse insgesamt:
find
,sudo
undperl
).Oder mit
zsh
:(0 Prozess insgesamt, speichert aber die gesamte Dateiliste im Speicher)
Diese Lösungen basieren auf dem
access(2)
Systemaufruf. Das heißt, anstatt den Algorithmus zu reproduzieren, den das System verwendet, um nach Zugriffsberechtigungen zu suchen, bitten wir das System, diese Überprüfung mit demselben Algorithmus durchzuführen (der Berechtigungen, ACLs, unveränderliche Flags, schreibgeschützte Dateisysteme berücksichtigt ...). ) Wenn Sie versuchen würden, die Datei zum Schreiben zu öffnen, ist dies die zuverlässigste Lösung.Um die hier angegebenen Lösungen mit den verschiedenen Kombinationen von Benutzern, Gruppen und Berechtigungen zu testen, können Sie Folgendes tun:
Variieren Sie den Benutzer zwischen 1 und 2 und die Gruppe zwischen 1, 2 und 3 und beschränken Sie sich auf die unteren 9 Bits der Berechtigungen, da bereits 9458694 Dateien erstellt wurden. Das für Verzeichnisse und dann nochmal für Dateien.
Das schafft alle möglichen Kombinationen von
u<x>g<y>/<mode1>/u<z>g<w>/<mode2>
. Der Benutzer mit Benutzer-ID 1 und Benutzer-ID 1 und Benutzer-ID 2 hätte beispielsweise Schreibzugriff auf,u2g1/010/u2g3/777
jedoch nichtu1g2/677/u1g1/777
auf.Alle diese Lösungen versuchen nun, die Pfade der Dateien zu identifizieren, die der Benutzer möglicherweise zum Schreiben öffnet. Dies unterscheidet sich von den Pfaden, unter denen der Benutzer möglicherweise den Inhalt ändern kann. Um diese allgemeinere Frage zu beantworten, gibt es mehrere Dinge zu berücksichtigen:
/a/b/file
aber wenn er Eigentümer istfile
(und Suchzugriff auf/a/b
hat und das Dateisystem nicht schreibgeschützt ist und die Datei nicht das unveränderliche Flag hat und Shell-Zugriff auf das System hat), dann könnte er die Berechtigungen des ändernfile
und sich selbst Zugriff gewähren./a/b
aber keinen Suchzugriff darauf hat./a/b/file
weil er keinen Suchzugriff auf/a
oder/a/b
hat. Diese Datei verfügt jedoch möglicherweise über einen festen Link/b/c/file
. In diesem Fall kann er den Inhalt möglicherweise ändern,/a/b/file
indem er ihn über seinen/b/c/file
Pfad öffnet ./a
, sondern/a/b
kann sein bind montierte in/c
, so dass er öffnen konntefile
für das Schreiben über seinen/c/file
anderen Weg./a/b/file
, aber wenn er Schreibrechte hat,/a/b
kann er diese entfernen oder umbenennenfile
und durch seine eigene Version ersetzen. Er würde den Inhalt der Datei ändern,/a/b/file
selbst wenn dies eine andere Datei wäre./a
(er umbenennen könnte/a/b
zu/a/c
erstellen Sie ein neues/a/b
Verzeichnis und ein neuesfile
drin.Um die Pfade zu finden, die geändert
$user
werden könnten. Für Adresse 1 oder 2 können wir uns nicht mehr auf denaccess(2)
Systemaufruf verlassen . Wir könnten unserenfind -perm
Ansatz anpassen , um den Suchzugriff auf Verzeichnisse oder den Schreibzugriff auf Dateien zu übernehmen, sobald Sie der Eigentümer sind:Wir könnten die Adressen 3 und 4 ansprechen, indem wir die Geräte- und Inode-Nummern oder alle Dateien aufzeichnen, für die der Benutzer Schreibrechte besitzt, und alle Dateipfade mit diesen dev + -Inode-Nummern melden. Dieses Mal können wir die zuverlässigeren
access(2)
Ansätze verwenden:So etwas wie:
5 und 6 werden auf den ersten Blick durch das
t
bisschen der Berechtigungen kompliziert . Bei der Anwendung auf Verzeichnisse ist dies das eingeschränkte Löschbit, das verhindert, dass Benutzer (außer dem Eigentümer des Verzeichnisses) die Dateien entfernen oder umbenennen, deren Eigentümer sie nicht sind (obwohl sie Schreibzugriff auf das Verzeichnis haben).Zum Beispiel, wenn wir zurück zu unserem früheren Beispiel gehen, wenn Sie Schreibzugriff haben
/a
, dann sollten Sie in der Lage sein , umbenennen/a/b
zu/a/c
, und dann ein neu -/a/b
Verzeichnis und ein neufile
drin. Aber wenn dast
Bit gesetzt ist/a
und Sie es nicht besitzen/a
, können Sie es nur tun, wenn Sie es besitzen/a/b
. Das gibt:t
Bit nicht gesetzt, und Sie sind im selben Fall wie oben (alle Dateipfade gehören Ihnen).So können wir alle von 1, 2, 5 und 6 ansprechen mit:
Das und die Lösung für 3 und 4 sind unabhängig, Sie können ihre Ausgabe zusammenführen, um eine vollständige Liste zu erhalten:
Wie klar sein sollte, wenn Sie bisher alles gelesen haben, befasst sich ein Teil davon zumindest nur mit Berechtigungen und Eigentumsrechten, nicht aber mit den anderen Funktionen, die möglicherweise Schreibzugriff gewähren oder einschränken (schreibgeschütztes FS, ACLs, unveränderliches Flag, andere Sicherheitsfunktionen) ...). Und da wir es in mehreren Schritten verarbeiten, können einige dieser Informationen falsch sein, wenn die Dateien / Verzeichnisse erstellt / gelöscht / umbenannt werden oder ihre Berechtigungen / Eigentümer geändert werden, während das Skript ausgeführt wird, wie auf einem ausgelasteten Dateiserver mit Millionen von Dateien .
Hinweise zur Portabilität
Der gesamte Code ist Standard (POSIX, Unix für
t
Bit), außer:-print0
ist eine GNU-Erweiterung, die jetzt auch von einigen anderen Implementierungen unterstützt wird. Mitfind
Implementierungen , die Unterstützung für sie fehlt, können Sie-exec printf '%s\0' {} +
stattdessen und ersetzen-exec sh -c 'exec find "$@" -print0' sh {} +
mit-exec sh -c 'exec find "$@" -exec printf "%s\0" {\} +' sh {} +
.perl
ist kein POSIX-spezifizierter Befehl, ist aber weit verbreitet. Sie benötigenperl-5.6.0
oder über-Mfiletest=access
.zsh
ist kein POSIX-angegebener Befehl. Derzsh
obige Code sollte mit zsh-3 (1995) und höher funktionieren.sudo
ist kein POSIX-angegebener Befehl. Der Code sollte mit jeder Version funktionieren, sofern die Systemkonfiguration die Ausführungperl
als angegebener Benutzer zulässt .quelle
x
Bit) für das Verzeichnis. Sie können auch über Suchberechtigungen verfügen, diese jedoch nicht lesen . Dies bedeutet, dass die darin enthaltenen Dateien für Sie verborgen sind. Wenn Sie jedoch ihren Namen kennen, können Sie auf sie zugreifen. Ein typisches Beispiel ist das PHP-Sitzungsdateiverzeichnis (so etwas wie / var / lib / php).Sie können Optionen mit dem
find
Befehl kombinieren , damit die Dateien mit dem angegebenen Modus und Eigentümer ermittelt werden. Zum Beispiel:Der obige Befehl listet alle Einträge auf, die zur Gruppe "Mitarbeiter" oder "Benutzer" gehören und Schreibberechtigung für diese Gruppe haben.
Sie sollten auch nach Einträgen suchen, die Ihrem Benutzer gehören, und nach Dateien, die weltweit beschreibbar sind.
Dieser Befehl stimmt jedoch nicht mit Einträgen mit erweiterter ACL überein. So können Sie
su
dann alle beschreibbaren Einträge herausfinden:quelle
r-xrwxrwx yourusername:anygroup
oder beschreibbarr-xr-xrwx anyone:staff
ist.yourusername
kein Zugriff besteht.Der Ansatz hängt davon ab, was Sie wirklich testen.
Dies liegt daran, dass es so viele Möglichkeiten gibt, zu 2) und Stéphanes Antwort diese gut abdeckt (unveränderlich ist eine, an die man sich erinnern muss) Hardware-Level (Floppy-Tabs). Ich vermute, Ihre Tausenden von Dateien befinden sich in unterschiedlichen Verzeichnissen und Sie möchten einen Bericht oder Sie vergleichen eine Master-Liste. (Ein weiterer Missbrauch von Puppet, der nur darauf wartet, geschehen zu können).
Sie möchten wahrscheinlich, dass Stéphanes Perl-Tree-Traversal die Ausgabe bei Bedarf mit einer Liste "verbindet" (su fängt auch die fehlende Ausführung in übergeordneten Verzeichnissen auf?). Wenn Leihmutterschaft ein Leistungsproblem ist, tun Sie dies für eine "große Anzahl" von Benutzern? Oder ist es eine Online-Abfrage? Wenn dies eine ständige Anforderung ist, ist es möglicherweise an der Zeit, ein Produkt von Drittanbietern in Betracht zu ziehen.
quelle
Du kannst tun...
... für eine Liste aller Dateien, in die der Benutzer nicht schreiben kann , wie in der Form in stderr geschrieben ...
...o.ä.
In den Kommentaren unten finden Sie Hinweise zu den Problemen, die bei diesem Ansatz auftreten können, und eine Erläuterung, warum dies möglicherweise funktioniert. Noch vernünftiger sollten Sie jedoch wahrscheinlich nur
find
reguläre Dateien wie die folgenden verwenden:Kurz gesagt,
tee
werden Fehler ausgegeben, wenn versucht wird,open()
eine Datei mit einem der beiden Flags zu erstellen.... und Begegnungen ...
... wie hier angegeben :
Weil es auf die gleiche Weise zu überprüfen hat,
test -w
tut ...Beide prüfen auf EACCESS .
quelle
tee
es hängen bleibt, wenn nicht einmal pro Lauf explizit unterbrochen wird. Es war das Nächste, woran ich denken konnte[ -w
... obwohl - seine Auswirkungen sollten dahingehend ähnlich sein, dass es dem Benutzer garantiert, dass er die Datei anhängen kann. Viel einfacher als jede Option wäre espax
mit-o
Formatoptionen und / oder-t
zum AbgleichenEACCESS
- aber jedes Mal, wenn ich vorschlagepax
, scheinen die Leute mit den Schultern zuzucken. Und das Einzige, waspax
ich gefunden habe und das der Norm entspricht, sind ASTs - in diesem Fall können Sie auch deren verwendenls
.