3


5

rootとして実行されているJavaスレッドで、ログインユーザーに固有のUnix権限をどのように適用できますか?

私たちはUnix上で* root *として実行されるJavaプログラムを持っています、それでそれは例えばフォルダ / home / user1`と / home / user2`の内容を読むことができます。 しかし、Unixユーザ "user1"が我々のアプリケーションにログインしているならば、彼は "/ home / user2"データにアクセスすることができないはずです。 私たちは直接UNIXの権利を使用し、私たちのアプリケーションのすべての許可を作り直さないことを望みます! だから、私たち…​

  1. ログインしているユーザーに応じてプログラムのUIDを変更してみませんか? 難しいように思えます、そして各ファイルアクセスは異なるスレッドにあるので、UIDは私たちのプログラムの各スレッドで異なるでしょう…​

  2. JNIを使​​用して "` / home / user2` "のアクセス許可を読み取ります…​ user1には「 / home / user2」に対する十分な権限がありますか? (どうやって ?)。

7 Answer


2


最も簡単で移植性の高い方法は、子プロセスを生成し、UIDを変更し、すべての特権を落とすC言語で書かれたラッパーを実行させることです(それを行うためのラッパーの作成は慎重です。 setuidラッパー)を呼び出し、RMIを介して会話する別のJavaインスタンスを実行します。 そのJavaインスタンスは、ユーザーに代わってすべてのファイルシステム操作を行います。

シングルスレッドのLinuxプログラムでは、代わりに setfsuid() / `setfsgid()`を使用することができますが、これは移植性のあるプログラムやマルチスレッドプログラムのオプションではありません。


2


  • SecurityManagerを使用してください。*

    1. 現在のUNIXユーザーIDをThreadLocalに入れます。

    2. checkRead()およびcheckWrite()でUNIXユーザーのアクセス許可を確認する独自のSecurityManagerを作成します。

    3. System.setSecurityManager(新しいMySecurityManager())

    4. 楽しい

更新

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

しかし、私は手短に使用できるライブラリを見つけようと試みました、そしてそれを見つけました:http://jan.newmarch.name/java/posix/それはJNIを使​​います、しかしあなたはあなた自身のJNIコードを書く必要はありません、大きな安心です。 :)他にもあるはずです。

そこからクラスStatはあなたにすべての必要なアクセス情報を与えます:http://jan.newmarch.name/java/posix/posix.Stat.html

*アップデート2 *

すでに述べたように、このアプローチではACLやPosix Capabilitiesなどの「非標準」のunixセキュリティ機能をチェックできません(ファイルに適用されるかどうかは不明)。 しかし、ホストOSのセキュリティと完全に同期するという目標が設定されている場合、JVM全体の保護メカニズムであるため、SecurityManagerを使用する必要があります。 はい、私たちはパーミッションを検証するために子SUIDプロセスを開始することができます(そしてそれを実行し続け、ユーザーがログインしている間パイプ実行を通してそれに話しかける)、*しかしSecurityManagerから*する必要があります!


0


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


0


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


0


不思議に思っていた人のために、それぞれの独立したスレッドに対してJNIで `setuid`を呼び出すことによってこれを行うことは*不可能*です。 `setuid`はそれを呼び出したスレッドだけではなくプロセス全体に影響します。

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


0


もう1つの選択肢は、アプローチを逆にすることです。ほとんどの場合rootとして実行され、制限されたリソースを使用する必要があるときはいつでもユーザーIDを変更するかアクセス権を確認することです。 rootだけができることをする必要があるときに、rootとして実行されている小さいデーモンに。 これには攻撃対象を減らすという追加の利点もあります。

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


0


私はまたミカエルとして正確な問題を抱えており、そして答えを探すためにこのページにたどり着きました。

答えのどれも私にとって100%満足です。 だから私は4つの選択肢を考えています:

  1. すべてのユーザーにアクセスできるLinuxグループを使用してください。 そのグループの下で単一のJavaアプリケーションを実行します。 このJavaアプリは、どのような手段でも「ルート」アプリと通信できます。 潜在的には、それは "ホテル"にすることができます。 例えば 100ユーザーあたり1つの「ホテル」(グループ許可を持つアプリ)(または必要に応じて)。 あなたが10,000人のユーザーを持っているのであれば、あなたは100ホテルを必要とし、それはかなり扱いやすいです。

  2. 独自のユーザーIDで、子アプリケーションごとにJVMを生成します。 これはスクリプトを呼び出すのと似ていますが、stdin / stdio / stderrを使用するのではなく、任意の通信プロトコルを使用します。 私の場合、私はXMPPと IO Dataを使用しています(これはすでに他のコンポーネントによって使用されているので、「どこ」とも呼ばれません)実行するJVM)

  3. Super-Server 'root’アプリを作成してください。 これは、元の「ルート」アプリの一部またはサービス管理専用の個別のサービスの一部にすることができます。 スーパーサーバは、着信要求(すなわち、すなわち、 これは実質的にはユーザー固有のサブアプリの リバースプロキシになり、実際の子アプリを起動し(まだ実行されていない場合)、メッセージを渡します。クライアントと子アプリケーションの間で行ったり来たり。 さらに、子アプリケーションは_pooled_(またはそのようなものがある場合は「パッシベーション」さえも)可能で、 Java EE EJBコンテナそれを行います。 そのため、1万人のユーザーと(潜在的に)1万人の子アプリケーションがサービスを提供していても、実行中の子アプリケーションの最大数には上限があります。 他の人のために空きを作るために、アイドル状態のアプリはシャットダウンされます。

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

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