ログインデーモンを作成するには?

ログインデーモンを作成するには?

Stevensの章のように、デーモンを正しく起動するための多くのガイドがあります。UNIX環境の高度なプログラミング。デーモン化後にどのステップを実行すべきかについての合意はありませんが、ルートプロセスでユーザープロセスを開始する別のアプローチが取られます。

歴史的に、ログインまたは telnetd 呼び出しの詳細はプラットフォームごとに異なります。 SSHサーバーはログインデーモンの現代的な例です。しかし、SSHサーバーの実装によっては正しいステップの解釈が異なり、これはしばしば各プラットフォームのステップに大きく依存します。

ログインを提供し、ユーザーコマンドを実行するための権限とコンテキストを設定するために(おそらくリモート入力に基づいて)最新のデーモンを作成するにはどうすればよいですか?

答え1

紹介する

ログインを提供するデーモンの基本的なタスクは、そのシステム・ユーザーに対して正しいコンテキストで 1 つ以上のコマンドを実行することです。端末ログインの歴史的要件とプラットフォーム間のプロセス属性と資格情報の違いを考慮すると、これは思ったよりも困難です。正しい設定を保証するには、さまざまな手順の順序を正確に指定する必要があります。

実際のケース

これgithubプロジェクトnetlogindこれらのデーモンの動作を示す簡単なテストアプリケーションです。以下の手順を説明します。

特定のユーザーとして実行されるプロセスを作成する基本手順

struct passwd pw; //< the user
setgid(pw.pw_gid);
initgroups(pw.pw_name, pw.pw_gid);
setuid(pw.pw_uid);

(エラーチェックを実行する必要があります。)また、セキュリティにとって非常に重要な呼び出し(setuidなど)の場合は、呼び出しgetuid後にgeteuid正しい資格情報が設定されていることを確認してください。間違ったuidでコードを実行し続けるのは最悪の災害です。setuidこの機能をサポートするすべてのプラットフォームで保存されている設定ユーザーIDをリセットします。

ポリアクリルアミド

PAMは、システム管理者がアプリケーションが認証を実行し、ユーザープロセスを開始する方法を設定できるAPIです。 PAMは広く配布されています。

pam_setcredPAMは、機能を介してセッション環境を構築するために使用されますpam_open_session。これらの関数を移植可能に呼び出すには問題が多く、順序に制限があります。

  • 認証を実行するために使用されたのと同じ実行スレッドで呼び出す必要がありますpam_authenticate。一部のモジュールは、認証セッション中に資格情報を収集し、それを使用してセッションフェーズで操作を実行するように動作します(例pam_mount:)。具体的には、内部で使用されているPAMモジュールは、他のプロセス(たとえば、特定のバージョンまたは「pam_krb5」)で呼び出されるとpam_set_data機能しません。pam_setcred/open_sessionpam_authenticatepam_afs
  • ルートと呼ぶ必要があります。
  • initgroups追加のグループメンバーシップを設定するために使用できるため、後で呼び出す必要があります。
  • pam_setcredpam_open_sessionどのコマンドを呼び出すべきかについての議論があります。ほとんどの最新プラットフォームでは、一部のモジュールでこれを合理的に要求するため、最初にpam_setcred呼び出す方が良いようです。pam_open_session[*]しかし、別の方法で注文したい理由があります。[*]とにかく最も深刻な制限は、pam_setcred2番目のモジュールでない限り、一部のモジュールでSolarisおよびHP-UX PAMが失敗するため、そのプラットフォームでは選択肢が少ないことです(つまり、実際に上記の順序に従う必要があります)。 LinuxPAMのドキュメントには、OpenPAMのドキュメントとは異なり、「pam_setcredが最初に来る必要があります」と記載されています。
  • 分岐による順序pam_open_session/setcred:2つのPAM関数呼び出しの間で分岐しないでくださいsetuidpam_limits呼び出しプロセスにリソース制限を適用すると、ルートはターゲットユーザーが実行できるよりも多くのプロセスを実行する可能性が高く、この場合フォークは常に失敗します。
  • 注意が必要なPAMのバグ:一部のベンダー提供モジュール(HP-UXなど)は、appdataパラメータをダイアログ機能に渡しません。移植性のためにappdataパラメータに依存しないように静的変数を使用してください。その他の注目すべき実際の互換性の問題:赤いハット#126985赤いハット#127054PAM_TTYSun関連の問題(例:オープンSSH#687)、ruidの制限pam_chauthtok(AIXではruidは0でなければならず、Solarisではruidは0ではない)。

ユーザープロセスの実行環境設定

closefrom

ユーザーコマンドを実行する前に、すべてのfdを閉じてください。これを行うべきかどうかは議論の余地があります。posix_traceたとえば、次のような多くの実装が終了するためです。時々悪魔化のステップの1つとしてリストされますが、これは非常に厄介な仕事です。ただし、ユーザーセッションを作成するときにこれを行う方が合理的です。

プラットフォーム:このシステムはSolarisとFreeBSDで動作します。それ以外の場合は、可能であればリストされているfdを使用してprocシミュレートしてください。getrlimit(RLIMIT_NOFILE)数字が大きすぎて繰り返すことができないので、素直に近づいたり、同様に近づけたりしないでください。

電話してください:いつでも

また見なさい: Austin Group Defect Tracker、「fdwalkシステムインターフェースの追加」

setlogin

setlogin(pw.pw_name)セッションに関連付けられている名前が正しいことを確認するために呼び出されます。

呼ぶ:;すぐ後ろはsetsid間違いなくデーモンが実行されているのと同じセッションではありません。ルートとして呼び出されます。

プラットフォーム:FreeBSD、Mac OSX。 uidにはパスワードデータベースに異なる名前を持つ複数のエントリがある可能性があるため、getpwuid(getuid())ログインに使用されたユーザー名を知らせることができない可能性があるため、getloginこれを行うには他の機能を提供する必要があります。実装はutmp(信頼できない)または$LOGNAME(安全でない)という点で実行できます。 BSD派生システムは、セッション固有のカーネルデータ構造にユーザー名を格納することで、理想的な方法でこの問題を解決します。 AIXはusrinfo(以下)を使用してこの問題を解決しました。

usrinfosetpcred

AIX では、usrinfo(SETUINFO, "LOGIN=<name>\0LOGNAME=<name>\0NAME=name\0", ...)機能的にsetloginBSD 派生物に似ています。ルートとして呼び出されます。

setpcred(pw.pw_name, NULL)ユーザーデータベースの資格情報に基づいてプロセス制限を正しく設定するために使用されます。

環境変数

$USER、、、、、 (以前$HOMEのバージョン、$PATHAIX $LOGNAME$LOGIN

選択科目:$MAIL$TZ

デフォルト値はにあります/etc/environment

環境変数の詳細が必要です!編集してください!

SELinux

Linuxシステムでサブプロセスの実行コンテキストを設定することは、PAMを介して実行するのが最善です。ただし、PAM 構成に関係なく、デーモンの権限がユーザー・プロセスに適用されないように手動で設定できます。この場合、次のように設定されます。今後電話してくださいinitgroups

ユーザーIDの確認

一部のLinuxカーネルでは、プロセスはユーザーがユーザーIDを切り替えたときに維持される追加のユーザーIDであるauidを維持しますsu(1)。これにより、実行されたタスクを記録し、そのタスクを実行したユーザーを追跡できます。

auidは通常を使用して設定されますpam_loginid。 PAMが正しく設定されていなくても設定できるようにするには、ユーザーのuidを作成します/proc/self/loginuid

追加ビュー: 「Linux監査システム、または誰がファイルを変更しましたか?」、ライナービヒマン

ソラリスcontract(4)

デーモンで開始されたプロセスの新しい契約を作成します。

例をご覧ください。 「Solaris 10の新しい契約で子プロセスを作成する」、フローリス・ブルノッグ

setusercontext

login(1)これらの操作の多くはBSDシステムのlibutilで区切られています。マニュアルを参照してくださいsetusercontext

関連情報