3

Unix でルートとして実行される Java プログラムがあるため、たとえば、フォルダーの内容を読み取ることができ/home/user1ます/home/user2。ただし、Unix ユーザー「user1」がアプリケーションにログインしている場合、「/home/user2」データにアクセスできないはずです。アプリケーションですべての権限を再作成するのではなく、Unix 権限を直接使用したいと考えています。それで、私たちは...

  1. ログインしているユーザーに応じて、プログラムの UID を変更してみませんか? 難しそうに聞こえますが、各ファイル アクセスは異なるスレッドで行われるため、UID はプログラムのスレッドごとに異なります...
  2. JNI を使用して " /home/user2" のパーミッションを読み取ります...そして、user1 が " /home/user2" に対して十分なパーミッションを持っているかどうかを判断しますか? (どうやって ?)。
4

7 に答える 7

2

SecurityManagerを使用してください!

  1. 現在のUNIXユーザーIDをThreadLocalに入れます
  2. checkRead()およびcheckWrite()でUNIXユーザー権限をチェックする独自のSecurityManagerを作成します
  3. System.setSecurityManager(new MySecurityManager())
  4. 楽しみ

アップデート

もちろん、unixファイルのパーミッションを読み取るための標準ライブラリはありません。WORAではありません。

しかし、すぐに使用できるライブラリを簡単に見つけて、次のライブラリを見つけました。http: //jan.newmarch.name/java/posix/ JNIを使​​用していますが、独自のJNIコードを作成する必要はありません。大きな安心です。:)私は他にもあるに違いないと確信しています。

そこからのクラス統計は、必要なすべてのアクセス情報を提供します:http: //jan.newmarch.name/java/posix/posix.Stat.html

アップデート2

人々が言及したように、このアプローチは、ACLやPosix機能などの「非標準」のUNIXセキュリティ機能をチェックできません(ファイルに適用されるかどうかはわかりません)。ただし、ホストOSのセキュリティと完全に同期するという目標が設定されている場合は、JVM全体の保護メカニズムであるSecurityManagerを使用する必要があります。はい、子SUIDプロセスを開始して権限を確認できます(そして、ユーザーがログインしている間、パイプを実行して通信し、実行を継続します)が、SecurityManagerから行う必要があります

于 2008-11-05T12:14:32.487 に答える
2

最も簡単で最も移植性の高い方法は、子プロセスを生成し、UID を変更する C で記述されたラッパーを実行し、すべての権限を削除することです (注意してください。それを行うためにラッパーを書くのは難しいです - 書くのと同じくらい難しいです) setuid ラッパー) を実行し、RMI 経由で対話する別の Java インスタンスを実行します。その Java インスタンスは、ユーザーに代わってすべてのファイルシステム操作を行います。

シングルスレッドの Linux プログラムの場合は、代わりにsetfsuid()/を使用できsetfsgid()ますが、移植可能なプログラムやマルチスレッドのプログラムでは使用できません。

于 2008-11-05T10:09:11.773 に答える
0

私もミカエルと同じ問題を抱えており、答えを探してこのページにたどり着きました。

私にとって100%満足できる答えはありません。だから私は4つの選択肢を考えています:

  1. すべてのユーザーにアクセスできる Linux グループを使用します。そのグループの下で単一の Java アプリを実行します。この Java アプリは、あらゆる手段を使用して「ルート」アプリと通信できます。

    潜在的に、それは「ホテル」編である可能性があります。たとえば、ユーザー 100 人あたり (または必要に応じて) 1 つの「ホテル」(グループ権限を持つアプリ)。したがって、10,000 人のユーザーがいる場合、100 のホテルが必要になりますが、これはかなり管理しやすいものです。

  2. それぞれの子アプリの JVM を独自のユーザー ID で生成します。これはスクリプトの呼び出しに似ていますが、stdin/stdio/stderr を使用するのではなく、任意の通信プロトコルを使用します。私の場合、XMPP とIO Dataを使用しています(これは、他のコンポーネントで既に使用されているため、「どこで」、つまりどの JVM を実行するかは問題ではありません)。

  3. スーパーサーバーの「ルート」アプリを作成します。これは、元の「ルート」アプリの一部にすることも、サービス管理専用の別のサービスにすることもできます。

    スーパーサーバーは、ユーザー固有のサブアプリの着信要求を処理し (実際にはリバース プロキシになります)、実際の子アプリを起動し (まだ実行されていない場合)、メッセージをやり取りします。クライアントと子アプリの間。

    さらに、子アプリは、 Java EE EJB Containerと同じようにプールできます(または、そのようなものがある場合は「パッシベーション」することもできます) 。したがって、10,000 人のユーザーと (潜在的に) 10,000 の子アプリがサービスを提供している場合でも、実行中の子アプリの最大数には上限があります。アイドル状態のアプリはシャットダウンされ、他のアプリのためのスペースが確保されます。

  4. #3 と同じですが、独自のサービス管理メカニズムを作成するのではなく、Upstart (または基盤となる OS のサービス管理フレームワーク) と統合します。つまり、Upstart を制御できる「ルート」サービスがあります。Upstart は、mysqld や Apache などを制御できるように、開始、停止、再起動、子サービスのステータスのクエリを実行できます。

私にとって、今、実装するのが最も速くて簡単なのは#1です。ただし、私の理想的な解決策は #4 ですが、時間がかかり、うまく機能するかどうかをテストする必要があります。(概念自体は inetd/xinetd と EJB から借用しているので、基本的にはかなり健全だと思います)

于 2011-07-16T16:08:29.500 に答える
0

アプリが user1 によるファイルの読み取りのみを許可されるようにする場合は、アプリを user1 として実行することを強くお勧めします。

于 2008-11-05T09:54:51.940 に答える
0

他のすべてが失敗した場合は、Java からシェルスクリプトを実行して結果を解析できます。

ここに例として説明

于 2008-11-05T10:00:29.853 に答える
0

疑問に思っている人のために説明すると、独立したスレッドごとに JNI を 呼び出してこれを行うことは明らかに不可能です。それを呼び出したスレッドだけでなく、プロセス全体に影響します。setuidsetuid

シングルスレッド Java プログラム内で呼び出したい場合は、 http://www2.sys-con.com/itsg/virtualcd/Java/archives/0510/Silverman/index.htmlsetuidに良い例があります。

于 2008-11-05T10:09:47.793 に答える
0

別のオプションは、アプローチを逆にすることです。ほとんどの場合、コードをルートとして実行し、ユーザー ID を変更するか、何らかの制限されたリソースを使用する必要があるときはいつでもパーミッションをチェックする代わりに、ほとんどの場合ユーザーとして実行して話します。 root だけができることを実行する必要がある場合に、root として実行される小さなデーモンに。これには、攻撃面を減らすという追加の利点もあります。

もちろん、ユーザーとして実行されているプロセスからルートとして実行されているプロセスへの接続を認証する必要があります。

于 2008-11-05T12:37:43.033 に答える