UNIX 的なオブジェクトパーミッションの設定は、
CYGWIN 環境変数 に
(no)ntsec を設定することによって行われます。
デフォルトでは ntsec が設定されています。
ntsec のデザイン上のゴールは、Windows NT のセキュリティ機能を使ってより
UNIX 的なパーミッション構造を実現することにあります。
この変更について説明するため、項2.3.1. 「NT セキュリティ」
では NT セキュリティについての概略を示します。
プロセスの特権 では、プロセスの特権(privileges)に関する ntsec での変更点について議論します。
ファイルパーミッション では UNIX 的なファイルパーミッションの設定について示します。
Cygwin での NT SID
では、/etc/passwd 及び /etc/group
内での SID の利用方法について説明します。
マッピングの漏れ では Windows NT のパーミッションマッピングの漏れを例証します。
ACL API リリース 1.1 で導入された新しいアクセス制御リスト(ACL) API について簡単に記述します。
新しい setuid のコンセプト ではリリース 1.1.3 で導入された setuid のコンセプトに対する新たなサポートについて記述します。
ユーザコンテキストの切り替え では、SYSTEM ユーザを利用したユーザコンテキストの切り替えを行う方法に関する基本について説明します。
特別な値を持つユーザ ID 及びグループ ID
では、/etc/passwd 或いは /etc/group
に存在しないユーザ及びグループを Cygwin が表現する方法について説明します。
NT セキュリティでは、異なる種類の「オブジェクト」に対するアクセスの許可と拒否を規定することが出来ます。 「オブジェクト」とはファイル、プロセス、スレッド、セマフォなどです。
NT セキュリティの主要なデータ構造は「セキュリティ記述子(security descriptor; SD)」構造です。 この構造はオブジェクトが許可(又は拒否)されるパーミッションを明示し、「セキュリティ識別子(security identifiers; SID)」に関連付けられる情報を含んでいます。
SID はユーザ、グループ、ドメインに対するユニークな識別子です。SID は UNIX の UID 及び GID に相当しますが、SID はネットワークを越えてユニークとなるため、より複雑なものとなっています。 以下に例を挙げます。
システム「foo」の SID:
S-1-5-21-165875785-1005667432-441284377
システム「foo」におけるユーザ「johndoe」の SID:
S-1-5-21-165875785-1005667432-441284377-1023
上記の例は SID の表示方法に関する慣習を示しています。 最初の「S」はこれが SID であることを示しています。 次の数値はバージョン番号であり、常に 1 です。 次の番号は「トップレベル権限(top-level authority)」と呼ばれる、 SID の発行元を示す識別子です。
NT ネットワークに所属する個々のシステムは独自の SID を持っていますが、この状況は NT ドメインでは異なり、ドメインコントローラの SID が個々のドメインユーザのベース SID となります。 もしある NT ユーザがドメインユーザとして一つのアカウントを持っており、 それとは別に彼のローカルマシン上のアカウントを持っていた場合、 同じユーザ名とパスワードを使用していたとしても、これらのアカウントはあらゆる状況下で異なるものとなります!
ドメイン「bar」の SID:
S-1-5-21-186985262-1144665072-740312968
ドメイン「bar」におけるユーザ「johndoe」の SID:
S-1-5-21-186985262-1144665072-740312968-1207
SID の最後のパートは「相対識別子(relative identifier; RID)」 と呼ばれ、Cygwin ではデフォルトで UID 及び GID として扱われます。 その名称と上記の例が暗示するように、 この ID は一つのシステム又はドメイン中でのみユニークです。
一人のユーザが 2 つの異なったシステムの間で同じ RID を持つことが可能であるという点に注意して下さい。 それにも関わらず、結果として生成される SID は異なったものとなります。 二つの SID は、NT ネットワーク内での異なるユーザを示しているのです。
UNIX ID と NT SID の間には、「既知グループ(well known groups)」 の存在という非常に大きな違いがあります。 例えば、UNIX には「全てのユーザ」のグループに対する GID はありませんが、 NT ではそれに相当する「Everyone(英語版での名称)」と呼ばれる SID があります。 既知グループの SID は NT ネットワーク内でユニークではありませんが、 それらの意義は間違いようがありません。 既知グループの例としては、以下のようなものがあります。
everyone S-1-1-0 creator/owner S-1-3-0 batch process (「at」コマンドによる) S-1-5-3 authenticated users S-1-5-11 system S-1-5-18
SID の最後の重要なグループは「事前定義グループ(predefined groups)」です。 このグループはドメインの外部にあるシステムにおいて、 主にユーザパーミッションの管理を簡単にするために使われます。 対応する SID はネットワークを越えてユニークではないので、 これらはローカルでのみ解釈されます。
administrators S-1-5-32-544 users S-1-5-32-545 guests S-1-5-32-546 ...
それでは、 パーミッションはどのようにしてオブジェクトに対して与えられるのでしょう? プロセスは SD をオブジェクトに与えます。オブジェクトの SD は 3 つのパートから構成されています。
所有者の SID
グループの SID
これらのパーミッションに付随する、 「アクセス制御リスト(accesses control list: ACL)」と呼ばれる SID のリスト
UNIX は 3 つの異なるパーミッション、即ち、所有者、 グループ、全員に対するパーミッションを作り出すことが出来ます。 それに対して ACL は、潜在的には無限のメンバに対して存在し得ます。 各メンバはアクセス制御エントリ(access control element: ACE)と呼ばれます。 ACE は 3 つの部分から構成されています。
ACE のタイプ
DWORD で記述されるパーミッション
先に述べたパーミッションが設定された SID
ACE の 2 つの重要なタイプは「アクセス許可 ACE」と「アクセス拒否 ACE」です。 Cygwin バージョン 1.1.0 まで、ntsec の機能は「アクセス許可 ACE」しか使用していませんでした。 それ以降のバージョンでは、UNIX パーミッションを可能な限り反映するように「アクセス拒否 ACE」をも使用します。
オブジェクトに対して設定可能なパーミッションは UNIX に比べてより複雑です。 例えば、オブジェクトの削除パーミッションは書き込みパーミッションとは異なったものです。
前述の方法と共に、NT はオブジェクトへのパーミッションを更なる特別な方法で有効にしたり無効にすることが出来ます。 しかし Cygwin ではどうでしょう? POSIX 環境には POSIX システムのセキュリティ仕様がありますが、 NT セキュリティモデルは POSIX のモデルの殆どを再現することができます。 ntsec の手法はこれを Cygwin で実現しようとするものです。
「殆ど? どうして殆どなの???」そう質問されるかもしれませんが、 何故なら NT モデルには漏れがあるからです。詳細については第 5 章で説明します。
系統だったオブジェクトセキュリティの生成は少々分かりにくいものですが、 一般的には 2 つの単純なヴァリエーションだけが使われます。
オペレーティングシステムによって導出されるデフォルトのパーミッション
全員に対する個々のパーミッション
安全なオブジェクトの作成やオープンに利用される関数の引数には、 「セキュリティ属性(security attributes; SA)」 と呼ばれる別のデータ構造体が使われます。この構造体は SD と、 作成またはオープンされるオブジェクトに対して返されるハンドルが子プロセスに継承されるか否かを示すフラグから構成されます。 このプロパティは ntsec では重要ではないので、この文書では SD と SA の違いは無視されます。
Cygwin の制御の元で開始される全てのプロセスには、シグナルを送信する目的で使われるセマフォがアタッチされています。 このセマフォの生成は cigproc.cc の「getsem」関数内で行われています。 この関数に対する最初の引数「CreateSemaphore」は SA です。 ntsec が適用されていない場合、この SA はセマフォに対してデフォルトのセキュリティを割り当てます。 ここで単純な不都合が発生します。 プロセスの所有者だけしかそのプロセスに対してシグナルを送信できないのです。 言い換えれば、そのプロセスの所有者が Administrators グループに属していなければ、Administrator は決してそのプロセスを殺すことが出来ません! プロセスがサービスマネージャから起動されていた場合、これは特に問題となります。
現在の ntsec はプロセス制御セマフォに対し、プロセスのユーザ、Administrators グループ、そしてオペレーティングシステム自身を示す用語「SYSTEM」に対する個々のパーミッションを持った SA を割り当てます。 この SA の生成は「shared.cc」内の「sec_user」関数で行われています。 Administrators グループのメンバはプロセスの所有者に関わらず、Cygwin 上で生成された全プロセスに対してシグナルを送信することができます。
更に、今や「CreateProcess」 によって開始された個々のプロセスは適切なセキュリティ設定を持ちます。 これは「spawn.cc」の「spawn_guts」関数中で定義されています。 他のユーザコンテキストにおいて開始されたプロセスに対するセキュリティ設定も、 新しいユーザの SID を追加する必要があります。 「CreateProcessAsUser」呼び出しによってプロセスが開始された場合、 sec_user 関数は新しいユーザの SID に対する追加のエントリを含んだ SA を生成します。
ntsec が有効であれば、ファイルパーミッションは UNIX と同様に設定されます。 所有者とグループ、そして所有者、グループ、「Everyone」に対する ACE を含んだファイルに対しては SD が割り当てられます。
完全な UNIX 的なパーミッションの設定はファイル security.cc 中で行われます。2 つの関数「get_nt_attribute」と「set_nt_attribute」 がその主要なコードです。SD の読み取りと書き込みは関数「read_sd」と 「write_sd」にて行われます。 「write_sd」はより簡単な関数「SetFileSecurity」の代わりに関数 「BackupRead」を使用します。 なぜなら、「SetFileSecurity」では呼び出し元とは異なる所有者を設定出来ないからです。
Cygwin の外側でファイル「foo」を生成した場合、ls -ln
の結果は次のようになるでしょう。
Administrators グループのメンバとしてログインした場合:
rwxrwxrwx 1 544 513 ... foo
そうでない場合:
rwxrwxrwx 1 1000 513 ... foo
ユーザ ID とグループ ID に注目して下さい。544 は Administrators グループの UID です。これは
Windows NT の「仕様」:-P です。仮にあなたが Administrators
のメンバであったとした場合、あなたが作成した全てのファイルはあなたではなく、Administrators
グループの所有物となります。
第 2 の例は NT のユーザ管理ツールによって作成された最初のユーザの UID を示しています。ユーザとグループには 1000 から始まる連続した番号が振られます。 ユーザとグループは同じ番号体系を使用するので、ユーザとグループの間で同じ ID を共有することは出来ません。
両方の例において、GID 513 には特別な点があります。 この GID はローカルシステムとドメインにおいて異なる名称を持つ既知グループです。 ドメインの外ではこのグループは 「なし」(英語では「None」、ドイツ語では「Kein」、フランス語では「Aucun」などとなります) と呼ばれ、ドメイン内では「Domain Users」と呼ばれます。 不幸にして、グループ「なし」はドメインの外側ではユーザ管理ツール上に表示されません! これは大きな混乱を生じさせますが、マイナスの影響は与えないとは思われます。
ntsec を正しく動かすためには
/etc/passwd と /etc/group
が必要です。Cygwin リリース 1.0 では、
名前と ID は対応する NT の ID と一致していなければなりません!
既に述べたように、Cygwin での ID は NT SID の RID です。
私の NT ワークステーションのユーザ「corinna」の SID は以下の通りです。
S-1-5-21-165875785-1005667432-441284377-1000
最後の番号を覚えておいて下さい。RID は 1000 であり、 これが Cygwin 上での UID となります。
不幸なことに、ドメインに属していないワークステーションとサーバでは、プライマリグループを設定することが出来ません! この場合、ユーザとプライマリグループの間には何らの関連もありません。 NT はプライマリグループとして 513(なし)を返し、既存のローカルグループへのメンバシップについては関与しません。
このようなシステムにおいて、mkpasswd -l -g を使用した際に「なし」をプライマリグループとして使用したくないのであれば(恐らくしたくないですよね)、手作業でプライマリグループを変更する必要があります。
以下の例を見て下さい。これらは私の /etc/passwd 及び
/etc/group の一部分であり、SID を格納する前の状態です(詳細については次の章で説明します)。
私の個人ユーザのエントリ以外、全てのエントリは既知のエントリです。
everyone:*:0:0::: system:*:18:18::: administrator::500:544::/home/root:/bin/bash guest:*:501:546::: administrators:*:544:544::/home/root: corinna::1000:547:Corinna Vinschen:/home/corinna:/bin/tcsh
例 2.1. /etc/passwd
everyone::0: system::18: none::513: administrators::544: users::545: guests::546: powerusers::547:
例 2.2. /etc/group
私が自分のプライマリグループを 513(none)から 547(powerusers)へと変更したことがわかるでしょう。 これによって、Cygwin の内部で私が作成した全てのファイルの所有グループは、none ではなく powerusers となります。これこそが私が望んでいたことです。
passwd ファイル中にはグループも記述されています。これには二つの長所があります。
しばしば、ls -l がより読み取りやすくなります。
NT はグループもファイル所有者として割り当てるからです。
更に、Cygwin の chown によっても、ファイルの所有者としてグループを割り当てることが出来ます。
前述した通り、グループ「SYSTEM」はオペレーティングシステム自身の同義語であり、通常はサービスマネージャによって起動されたプロセスの所有者となります。 サービスマネージャによって起動されたプロセスによって作成されたファイルについても同様です。
Cygwin リリース 1.1 では、
/etc/passwd と /etc/group
の利用についての新しいテクニックが導入されました。
現在、両ファイルはユーザとグループの SID を含んでいます。
SID は /etc/passwd の pw_gecos フィールドの最後に、
そして /etc/group の gr_passwd
フィールドの最後に格納されています。
これには以下の利点があります:
ntsec がドメイン環境でよりよく動作します。
Cygwin における(ユーザ及びグループの)アカウントには、NT 上のアカウント名とは別の名称が利用出来ます。
/etc/passwd 又は /etc/group の名称は、Cygwin
アプリケーション(chown、chmod、ls など)
において透過的に扱われます。
adminstrator::500:513::/home/root:/bin/sh
の代わりに、このように出来ます。
root::500:513::/home/root:/bin/sh
注意: もしそのアカウントを telnet
などで使用するログインアカウントとするつもりであれば、
その名称を変更しないでおくか、或いは Cygwin リリース 1.1 以降にに含まれる
特別なバージョンの login を使用しなければならない点に注意して下さい。
現在、Cygwin の UID と GID は必ずしも NT の SID の RID 部分でなくとも構いません。
root::500:513::/home/root:/bin/sh
の代わりに、このように出来ます。
root::0:513:S-1-5-21-54355234-56236534-345635656-500:/home/root:/bin/sh
UNIX システムとしての UID と GID の採番スキームは、 現在では相互に影響し合うことはありません。そのため、 ユーザとグループで同じ ID を使用することが可能です。
mkpasswd と mkgroup
の両ツールは、必要となるエントリをデフォルトで作成します。
そうしたくなければ、オプション -s 又は --no-sids
を使用することが出来ますが、これはお奨め出来ません。
ntsec は SID を利用することによって、より正しく動作するからです。
/etc/passwd の pw_gecos
フィールドは、コンマ区切りのリストとして定義されていることに注意して下さい。
SID は最後のフィールドでなければなりません!
既に述べた通り、Cygwin でのアカウント名は NT でのアカウント名とは異なるものとすることが出来ます。
もし「telnet」又はそれ以外の方法でログインする場合、特別な login を使用しなければなりません。
そして pw_gecos フィールドには、ドメインを含めた NT
上のユーザ名を定義するために、もう一つのフィールドを追加することが出来ます。
そう、それぞれのドメインのユーザとしてログインすることが出来るのです。
このシンタックスは簡単です。pw_gecos フィールドに
U-ntdomain\ntusername の形式でエントリを追加するだけです。
SID はまだ pw_gecos の最後のフィールドとして残しておかねばならないことを覚えておいて下さい!
the_king::1:1:Elvis Presley,U-STILLHERE\elvis,S-1-5-21-1234-5678-9012-1000:/bin/sh
ローカルユーザに対しては、ドメインを落すだけです。
the_king::1:1:Elvis Presley,U-elvis,S-1-5-21-1234-5678-9012-1000:/bin/sh
どちらの場合でも、ユーザのパスワードは NT のユーザデータベースから取得されます。 passwd ファイルからではありません!
前章と同様、例として私個人の/etc/passwd
と /etc/group を提示します。
これらのファイルはかなり変更されている点に注意して下さい!
変更しなければならない理由はありませんが、
これはテストのためであり、そして…楽しみのためでもあります。
root:*:0:0:Administrators group,S-1-5-32-544:: SYSTEM:*:18:18:,S-1-5-18:/home/system:/bin/bash admin:*:500:513:,S-1-5-21-1844237615-436374069-1060284298-500:/home/Administrator:/bin/bash corinna:*:100:0:Corinna Vinschen,S-1-5-21-1844237615-436374069-1060284298-1003:/home/corinna:/bin/tcsh Guest:*:501:546:,S-1-5-21-1844237615-436374069-1060284298-501:/home/Guest:/bin/bash
例 2.5. /etc/passwd
root:S-1-5-32-544:0: local:S-1-2-0:2: network:S-1-5-2:3: interactive:S-1-5-4:4: authenticatedusers:S-1-5-11:5: SYSTEM:S-1-5-18:18: local_svc:S-1-5-19:19: netwrk_svc:S-1-5-20:20: none:S-1-5-21-1844237615-436374069-1060284298-513:513: bckup_op:S-1-5-32-551:551: guests:S-1-5-32-546:546: pwrusers:S-1-5-32-547:547: replicator:S-1-5-32-552:552: users:S-1-5-32-545:545:
例 2.6. /etc/group
同様の変更を行うのは、このコンセプトを理解している場合にのみにして下さい。 そうでない場合は、何かが正しく動作しなくなっても驚かないで下さい。 破滅を迎えてしまった場合、mkpasswd 及び mkgroup でファイルを作り直すことが出来ます。 特に、ユーザ SYSTEM の UID と名前は変更しないで下さい。 大部分は動作するでしょうが、SYSTEM アカウントの元でローカルサービスとして動作する幾つかの Cygwin アプリケーションは、突如として奇妙な振る舞いを示すかもしれません。
今こそ NT パーミッションにおける漏れについて説明するときです。 公式の文書では、以下のように簡単に説明されています。
アクセス許可 ACE は呼び出し元のグループメンバシップに関して蓄積される。
ACE の順番は重要である。 システムは何らかの必要な権利が拒否されるか、または全ての必要な権利が許可されるまで、順番に ACE を読み続ける。 それ以降に残された ACE は考慮に入れられない。
全てのアクセス拒否 ACE はどのアクセス許可 ACE よりも優先される。
最後のルールは推奨事項であり、決まりではありません。NT は順番とは無関係に ACL を正しく扱います。 希望する順番で ACE を取得するよう、第 2 のルールを修正することは出来ません。
不幸なことに、NT4 のエクスプローラのセキュリティタブでは、 完全にアクセス拒否 ACE を取り扱うことが出来ません。 Windows 2000 のエクスプローラは、ACE を読み込む前にその順番を再整理します。 困ったことに、この整列結果はキャンセルボタンをクリックしても戻りません。
まだ「どこに漏れがあるの?」と尋ねられることでしょう。NT の ACL は POSIX パーミッションの個々の可能な組み合わせを反映することが出来ません。 例えば、
rw-r-xrw-
1 回目の挑戦:
UserAllow: 110 GroupAllow: 101 OthersAllow: 110
ふーむ、許可の蓄積によって、group が実行可能であれば user も実行可能となります。
2 回目の挑戦:
UserDeny: 001 GroupAllow: 101 OthersAllow: 110
今度は user は読み書き可能ですが実行は出来ません。これでいいのでしょうか? いいえ! 不幸にも others が書き込み可能であるため、group も書き込み可能になってしまいます。
3 回目の挑戦:
UserDeny: 001 GroupDeny: 010 GroupAllow: 001 OthersAllow: 110
今度は group は意図した通り書き込み不可になりましたが、しかし不幸なことに、user もまたどこにも書き込み出来ません。どのようにすればこの問題が解決出来るのでしょう? 公式なルールによると、UserAllow は GroupDeny に従わねばなりませんが、しかしこの方法では解決することが出来ないのは明らかです。
唯一の方法:
UserDeny: 001 UserAllow: 010 GroupDeny: 010 GroupAllow: 001 OthersAllow: 110
繰り返します: これは NT4 と Windows 2000 の両方で動作します。GUI だけがこの順番を設定出来ないのです。
ACL を取り扱うため、現在の Cygwin には Solaris
の新しいバージョンで実装されたような ACL API が用意されています。
単純な ACL エントリ(NT の用語では ACE)に対応する新しいデータ構造は、sys/acl.h
中で以下のように定義されています。
typedef struct acl {
int a_type; /* エントリタイプ */
uid_t a_id; /* UID | GID */
mode_t a_perm; /* パーミッション */
} aclent_t;
aclent_t 型の a_perm メンバはファイルモードの読み込み、書き込み、そして実行の各ビットだけを含んでいます。 読み込み権限が許可されたなら、全ての読み込みビット(S_IRUSR、S_IRGRP、S_IROTH)がセットされます。 CLASS_OBJ 又は MASK ACL エントリは、まだ完全には実装されていません。
新しい API 呼び出しを以下に示します。
acl(2), facl(2) aclcheck(3), aclsort(3), acltomode(3), aclfrommode(3), acltopbits(3), aclfrompbits(3), acltotext(3), aclfromtext(3)
Solaris と同様、Cygwin は ACL と共にコマンドラインで動作する
2 つの新しいコマンドを備えています。
getfacl と setfacl です。
前述のコマンドと API 呼び出しに関するオンラインの man ページは、http://docs.sun.com などで見つかります。
ユーザコンテキストを変更する必要がある UNIX アプリケーションは、Windows API には存在しない
setuid 及び seteuid 呼び出しを使用します。
それにも関わらず、これらの呼び出しは Cygwin 1.1.3 以降、Windows NT/2000 の元ではサポートされています。
しかしながら NT セキュリティの性質により、この機能が必要なアプリケーションに対しては修正が必要となります。
NT はユーザとパーミッションを識別するために「アクセストークン」と呼ばれるものを使用します。
ユーザコンテキストを変更するためには、アプリケーションは「アクセストークン」を要求する必要があります。
これは通常、NT の API 関数 LogonUser
を呼び出すことによって実行されます。アクセストークンが返されると、アクセストークンは
ImpersonateLoggedOnUser によってユーザコンテキストを変更するために、
又は CreateProcessAsUser
によって生成された子プロセスのユーザコンテキストを変換するために使用されます。
但し、LogonUser を使用するアプリケーションは、以下の特殊なユーザ権利を持っていなければならないという重大な制限があります。
「オペレーティングシステムの一部として機能(Act as part of the operating system)」 「プロセスレベルトークンの置き換え(Replace process level token)」 「クォータの増加(Increase quotas)」
デフォルトで設定されているユーザ権利では、Administrators にもこの全ての権利が設定されていないということに注意して下さい。
setuid を使用するアプリケーションが最小の変更で移植出来るように、二つの新しい
Cygwin の呼び出しが導入されました。Cygwin に対して正しいアクセストークンを与えれば、POSIX
アプリケーションで利用するのと同様、普通に
seteuid 又は setuid を呼び出すことが出来ます。
sexec 呼び出しは何も必要としません。
setuid を使用するアプリケーションの移植は、以下の簡単な例で示すように行えます。
/* まず、全ての必要な Cygwin 関連ファイルをインクルードする */
#ifdef __CYGWIN__
#include <windows.h>
#include <sys/cygwin.h>
/* Windows のバージョンを決定するために以下の定義を使用する */
#define is_winnt (GetVersion() < 0x80000000)
#endif
[...]
struct passwd *user_pwd_entry = getpwnam (username);
char *cleartext_password = getpass ("Password:");
[...]
#ifdef __CYGWIN__
/* 典型的なパスワードのテストに対するパッチ */
if (is_winnt)
{
HANDLE token;
/* NT のアクセストークンを得ることが出来るかどうか */
token = cygwin_logon_user (user_pwd_entry, cleartext_password);
if (token == INVALID_HANDLE_VALUE)
error_exit;
/* 新しい偽装トークンを Cygwin に通知。
今や Cygwin は、setuid 又は seteuid 呼び出しを使用することに
よってユーザコンテキストを変更出来る。*/
cygwin_set_impersonation_token (token);
}
else
#endif /* CYGWIN */
/* Windows 9x でうまく動作させるための標準的な方法 */
hashed_password = crypt (cleartext_password, salt);
if (!user_pwd_entry ||
strcmp (hashed_password, user_pwd_entry->pw_password))
error_exit;
[...]
/* 後は全て同じです! */
setegid (user_pwd_entry->pw_gid);
seteuid (user_pwd_entry->pw_uid);
execl ("/bin/sh", ...);
アクセストークンを取得するための新しい Cygwin の呼び出しは、以下のように定義されています。
#include <windows.h> #include <sys/cygwin.h> HANDLE cygwin_logon_user (struct passwd *pw, const char *cleartext_password)
異なったユーザでのログオンを行う際には、常にこの関数を呼び出すことが出来ます。 また、更なる呼び出しに備えてアクセストークンを保持しておくためには、第二の関数を使用することが出来ます。
#include <windows.h> #include <sys/cygwin.h> void cygwin_set_impersonation_token (HANDLE hToken);
この呼び出しは、更なる setuid/seteuid
の呼び出しによって変更されるユーザコンテキストを Cygwin に対して通知します。
他のユーザコンテキストへ setuid/seteuid
するための正しいアクセストークンが必要になった場合は、パラメータに自身の UID を指定して
setuid/seteuid
を使用することで、自身のユーザコンテキストへ復帰することが出来ます。
cygwin_logon_user
呼び出しによって返される様々なアクセストークンを覚えていれば、
以下の順序に注意深く従うことにより、ユーザコンテキストを異なるものへと変更することが出来ます。
cygwin_set_impersonation_token (user1_token); seteuid (user1_uid); [...] seteuid (own_uid); cygwin_set_impersonation_token (user2_token); seteuid (user2_uid); [...] seteuid (own_uid); cygwin_set_impersonation_token (user1_token); seteuid (user1_uid); など。
Cygwin リリース 1.3.3 以降、ユーザ権利「プロセスレベルトークンの置き換え」を持つアプリケーションは、通常の setuid、seteuid、setgid
及び setegid
関数を単純に呼び出すだけで、パスワードなしでユーザコンテキストの変更が可能となりました。
一般的に、この権利は SYSTEM ユーザだけに与えられています。
しかしこれによって、例えば rhosts 認証、又は(SYSTEM アカウントを利用して
sshd をサービスとして実行している場合は)公開鍵認証を利用したユーザコンテキストの変更が可能となっています。
この方法における重要な制限は、SYSTEM アカウントで開始されたプロセスは、認証を必要とするネットワーク共有へとアクセス出来ないという点です。 この制限は、パスワードなしでユーザコンテキストを変更したサブプロセスにも及びます。 一般的に、パスワードなしで ssh 又は rsh を利用してログインした際、ユーザはネットワークホームドライブを利用することは出来ません。
現在のユーザのユーザ ID が 400 という特別な値に設定されている場合、そのユーザは
/etc/passwd には含まれませんが、ユーザ名は常に正しく表示されます。
他のユーザ(或いは、ユーザとして扱われる Windows グループ)で
/etc/passwd に含まれないものは、
そのユーザ ID が -1 という特別な値(ls の出力では 65535 となります)となります。
このような場合、そのユーザのユーザ名は「????????」と表示されます。
現在のユーザのログイングループ ID が 401 という特別な値に設定されている場合、そのユーザは
/etc/passwd には含まれません。
他のユーザで /etc/passwd に含まれないものは、
そのユーザのログイングループ ID が -1 という特別な値になっています。
/etc/passwd に含まれているユーザだが、そのユーザのグループが
/etc/group に含まれておらず、かつそのグループはそのユーザのログイングループではないという場合、そのグループのグループ ID は特別な値 -1 に設定されています。
このグループ(ID が -1 のグループ)のグループ名は、「????????」と表示されます。
Cygwin 1.3.20 以前のリリースでは、グループ ID 401
にはグループ名「なし」が与えられていました。Cygwin リリース 1.3.20 以降、グループ ID
401 には、この状況を少しでも解決するために実行するべきであるコマンド名である「mkpasswd」が表示されるようになりました。
また、Cygwin リリース 1.3.20 以降では、もし現在のユーザが
/etc/passwd に含まれているにも関わらず、ユーザのログイングループが
/etc/group に含まれていない場合、グループ名として同様に「mkgroup」を表示します。
要約すれば、次のようになります:
もし現在のユーザが /etc/passwd に含まれていない場合、
グループ名は「mkpasswd」となる。
そうでない場合、現在のログイングループは
/etc/group に含まれておらず、グループ名は「mkgroup」となる。
そうでない場合、/etc/group
に含まれていないグループは「????????」と表示され、
/etc/passwd に含まれていないユーザについても「????????」と表示される。
特別なユーザとグループの名称は表示に利用されるだけであり、
「mkpasswd」という名前を持つユーザが実際に /etc/passwd
に含まれる(或いは、「mkgroup」というユーザが
/etc/group に含まれる)ということを回避させるものではありません。
そのようなことをした場合は、混乱が発生するであろうことには注意して下さい。