ユーザーとディレクトリをスクリプトに渡し、ユーザーに読み取り権限を持つそのディレクトリのフォルダ/ファイルのリストを表示させる必要があります。 MSにはこれを行うことができるWindows用AccessChkというツールがありますが、Unix側にも同様のツールはありますか?特定のフォルダまたはファイルに対してこれを行うことができるいくつかのコードが見つかりましたが、ディレクトリに移動するにはこのコードが必要です。
答え1
長い話を短く
find "$dir" ! -type l -print0 |
sudo -u "$user" perl -Mfiletest=access -l -0ne 'print if -r'
システムユーザーに読み取り権限があるかどうかを尋ねる必要があります。信頼できる唯一の方法は、有効なuid、有効なgid、および補足のgidをユーザーの有効なuid、有効なgid、および補足のgidに切り替えてシステムコールをaccess(R_OK)
使用することです(一部のシステム/構成にはいくつかの制限があるにもかかわらず)。
長いストーリー
$ userが読み取り権限を持つには何が必要かを考えてみましょう/foo/file.txt
(どちらもシンボリックリンクではないとします/foo
)/foo/file.txt
。
彼は以下が必要です:
- 探すアクセス
/
(不要読む) - 探すアクセス
/foo
(不要読む) - 読む入力する
/foo/file.txt
ユーザーにも検索権限もなくても読むことができるとされているfile.txt
ため、単に権限を確認するアプローチは機能しないことが既にわかります。file.txt
/
/foo
同様の方法:
sudo -u "$user" find / -readable
また、ユーザーが読み取り可能であるにもかかわらず、ユーザーが読み取り権限を持たない(コンテンツをリストできないためfind
実行中)、ディレクトリー内のファイルを報告しないため、機能しません。$user
ACLやその他のセキュリティ対策(衣類、SELinux...)を忘れて、既存の権限と所有権のプロパティに集中して特定の(検索または読み取り)権限を取得する場合、これはすでにかなり複雑で使いにくいですfind
。
以下を行う必要があります。
- ファイルが自分の所有である場合は、所有者の権限(またはuid 0)が必要です。
- ファイルがあなたに属していないがグループに属している場合は、グループの権限が必要です(またはuid 0が必要です)。
- あなたまたはあなたのグループに属していない場合その他権限が適用されます(uidが0以外の場合)。
構文の点では、find
たとえば、uid 1、gid 1、2を使用しているユーザーは次のとおりです。
find / -type d \
\( \
-user 1 \( -perm -u=x -o -prune \) -o \
\( -group 1 -o -group 2 \) \( -perm -g=x -o -prune \) -o \
-perm -o=x -o -prune \
\) ! -type d -o -type l -o \
-user 1 \( ! -perm -u=r -o -print \) -o \
\( -group 1 -o -group 2 \) \( ! -perm -g=r -o -print \) -o \
! -perm -o=r -o -print
それ打つユーザーが検索権限を持たないディレクトリおよび他の種類のファイルへの読み取りアクセス権を確認します(関連のないシンボリックリンクを除く)。
または、ユーザーデータベースから取得された1つ$user
のグループメンバーシップに対して、次の手順を実行します。
groups=$(id -G "$user" | sed 's/ / -o -group /g'); IFS=" "
find / -type d \
\( \
-user "$user" \( -perm -u=x -o -prune \) -o \
\( -group $groups \) \( -perm -g=x -o -prune \) -o \
-perm -o=x -o -prune \
\) ! -type d -o -type l -o \
-user "$user" \( ! -perm -u=r -o -print \) -o \
\( -group $groups \) \( ! -perm -g=r -o -print \) -o \
! -perm -o=r -o -print
最善の方法は、ルートとしてツリーを下げて、ユーザーとして各ファイルの権限を確認することです。
find / ! -type l -exec sudo -u "$user" sh -c '
for file do
[ -r "$file" ] && printf "%s\n" "$file"
done' sh {} +
または以下を使用してperl
:
find / ! -type l -print0 |
sudo -u "$user" perl -Mfiletest=access -l -0ne 'print if -r'
または以下を使用してzsh
:
files=(/**/*(D^@))
USERNAME=$user
for f ($files) {
[ -r $f ] && print -r -- $f
}
これらのソリューションはaccess(2)
システムコールに依存します。つまり、システムがアクセス権を検証するために使用するアルゴリズムを複製するのではなく、読み取り用にファイルを開こうとしたときと同じアルゴリズム(権限、ACLなどを考慮)を使用してファイルを確認するようにシステムに要求します。 、はい。信頼できるソリューションに最も近いです。
これらのソリューションはすべて、ユーザーが読み取り用に開くことができるファイルパスを識別しようとします。このパスは、ユーザーがコンテンツを読み取ることができるパスとは異なります。このより一般的な質問に答えるために考慮すべきいくつかの点は次のとおりです。
- $ userには$ userへの読み取りアクセス権がない可能性がありますが、
/a/b/file
$file
userへの検索アクセス権があり、システムへのシェルアクセス権がある場合は、$ userの権限を変更して自分にアクセス権を付与/a/b
できます。file
。 /a/b
検索権限があるが検索権限がない場合も同様です。- $ userには、またはへの検索アクセス権が
/a/b/file
ないため、アクセス権がない可能性がありますが、ファイルにハードリンクがある可能性があります。この場合、たとえば、そのパスを介してコンテンツを開いてコンテンツを読み取ることができます。/a
/a/b
/b/c/file
/a/b/file
/b/c/file
- 同じものバンドルのインストール。その人は検索権限を持っていないかも
/a
しれませんが、/a/b
バンドルのインストール、他のパスを介して読みやすいように開くことができ/c
ます。file
/c/file
$user
読みやすいパスを見つけます。 1回または2回を解決するためにシステムコールに頼ることはできませんaccess(2)
。find -perm
ディレクトリへの検索アクセス権を想定するか、所有者になるとすぐにファイルへの読み取りアクセス権を持つようにアプローチを調整できます。
groups=$(id -G "$user" | sed 's/ / -o -group /g'); IFS=" "
find / -type d \
\( \
-user "$user" -o \
\( -group $groups \) \( -perm -g=x -o -prune \) -o \
-perm -o=x -o -prune \
\) ! -type d -o -type l -o \
-user "$user" -print -o \
\( -group $groups \) \( ! -perm -g=r -o -print \) -o \
! -perm -o=r -o -print
デバイスとinode番号、または$ userが読み取り権限を持つすべてのファイルを記録し、そのdev + inode番号を含むすべてのファイルパスを報告することで、3回と4回の問題を解決できます。今回は、より信頼性の高い access(2)
ベースアプローチを使用できます。
それは次のとおりです。
find / ! -type l -print0 |
sudo -u "$user" perl -Mfiletest=access -0lne 'print 0+-r,$_' |
perl -l -0ne '
($w,$p) = /(.)(.*)/;
($dev,$ino) = stat$p or next;
$writable{"$dev,$ino"} = 1 if $w;
push @{$p{"$dev,$ino"}}, $p;
END {
for $i (keys %writable) {
for $p (@{$p{$i}}) {
print $p;
}
}
}'
両方のソリューションを次にマージします。
{ solution1; solution2
} | perl -l -0ne 'print unless $seen{$_}++'
これまでにすべての内容を読んだ場合、少なくともその一部は権限と所有権のみを扱い、読み取りアクセスを許可または制限できる他の機能(ACL、その他のセキュリティ機能...)は扱わないことを明確にする必要があります。複数の手順で処理するため、スクリプトの実行中にファイル/ディレクトリが作成/削除/名前が変更された場合、またはその権限/所有権が変更されると、一部の情報が失われる可能性があります。たとえば、何百万ものファイルがある忙しいファイルサーバーでは無効です。
移植性に関する注意
このコードはすべて以下を除いて標準(POSIX、t
ビット用Unix)です。
-print0
これはGNU拡張であり、他の多くの実装でもサポートされています。find
サポートが不足している実装では、-exec printf '%s\0' {} +
代わりに使用して置き換える-exec sh -c 'exec find "$@" -print0' sh {} +
ことができます-exec sh -c 'exec find "$@" -exec printf "%s\0" {\} +' sh {} +
。perl
POSIX 特定のコマンドではありませんが、広く利用可能です。あなたはperl-5.6.0
以上が必要です-Mfiletest=access
。zsh
POSIX 指定コマンドではありません。上記のコードはzsh
zsh-3(1995)以降で動作します。sudo
POSIX 指定コマンドではありません。コードは、システム構成でperl
特定のユーザーとして実行できるようにする限り、すべてのバージョンで動作する必要があります。
答え2
これは解決策を得る簡単な方法です。 「testuser」を自分のユーザーに置き換えます。 findの使い方を知っていて、「。」引数を置き換えて関連ディレクトリを見つけることができるとします。
x =テストユーザーを探す。 -type f |xargs ls -la | grep $ x |
test1-3.txtという名前のいくつかのファイルを使用して、3つのディレクトリ深層構造(dir1、dir2、dir3)を作成しました。私はユーザーまたはグループをいくつかのファイルにtestuserとしてランダムに割り当てます。
[root@myserver tmp]# x=testuser;検索。 -type f |xargs ls -la | grep $x クエリ awk '{print$9}'
./dir1/dir2/dir3/test2.txt
./dir1/test2.txt
./dir1/test3.txt
鍵は「ls」の再帰オプションです。以下は私のテストの構造の例です。
[root@det1svn01n tmp]# ls -laR dir1
カタログ 1:
合計12個
drwxr-xr-x 3ルートルート4096 6月17日14時55分。
drwxrwxrwt 4 gengen4096 6月17日14時54分 ..
drwxr-xr-x 3 testuser testuser 4096 6月17日 14:55 dir2
-rw-r--r-- 1 ルートルート 0 6月17日 14:55 test1.txt
-rw-r--r-- 1 root testuser 0 6月17日、14:55 test2.txt
-rw-r--r-- 1 testuser testuser 0 6月17日14:55 test3.txt
ディレクトリ 1/ディレクトリ 2:
合計12個
drwxr-xr-x 3 testuser testuser 4096 6月17日14時55分。
drwxr-xr-x 3 root4096 6月17日 14:55 ..
drwxr-xr-x 2 root root4096 6月17日14時55分 dir3
-rw-r--r-- 1 ルートルート 0 6月17日 14:55 test1.txt
-rw-r--r-- 1 root root 0 6月17日14:55 test2.txt
-rw-r--r-- 1 root root 0 6月17日14:55 test3.txt
ディレクトリ 1/ディレクトリ 2/ディレクトリ 3:
合計8個
drwxr-xr-x 2 root4096 6月17日14時55分。
drwxr-xr-x 3 testuser testuser 4096 6月17日14時55分 ..
-rw-r--r-- 1 ルートルート 0 6月17日 14:55 test1.txt
-rw-r--r-- 1 root root 0 6月17日14:55 test2.txt
-rw-r--r-- 1 root root 0 6月17日14:55 test3.txt