home link download back number special issue

HMDT - Back Number / September, 2001


September, 2001


September 25 - Authorization API 完全理解 - その 5 の続き
keywords: structures, constants

◆ AuthorizationItemSet

AuthorizationItem が複数あるのが AuthorizationItemSet だ。

Security/Authorization.h
typedef struct {
    UInt32 count;
    AuthorizationItem *items;
} AuthorizationItemSet;

◆ AuthorizationRights

AuthorizationRights は AuthorizationItemSet のことね。

Security/Authorization.h
typedef AuthorizationItemSet AuthorizationRights;

◆ AuthorizationEnivironment

AuthorizationEnvirionment も AuthorizationItemSet のこと。この 3 つは実体は同じ物だね。

Security/Authorization.h
typedef AuthorizationItemSet AuthorizationEnvironment;

◆ kAuthorizationEmptyEnvironment

kAuthorizationEmptyEnvironment は AuthorizationEnvironment に指定できる定数だ。何も指定しないときに使えるよ。

Security/Authorization.h
#define kAuthorizationEmptyEnvironment	NULL

September 24 - Authorization API 完全理解 - その 5
keywords: flags, structures

今回は Authorization API で使われる、構造体やフラグや定数だ。

◆ AuthorizationRef

認証に使われるオブジェクトだ。Authorization API は、すべてこの AuthorizationRef を使って処理をするんだ。

Security/Authorization.h
typedef const struct AuthorizationOpaqueRef *AuthorizationRef;

こいつを作るには AuthorizationCreate() を呼ぶ。使い終わって破棄するときは AuthorizationFree() だ。

◆ AuthorizationFlags

これは Authorization API を呼ぶときに設定するフラグなんだ。

Security/Authorization.h
enum {
    kAuthorizationFlagDefaults           = 0,
    kAuthorizationFlagInteractionAllowed = (1 << 0),
    kAuthorizationFlagExtendRights       = (1 << 1),
    kAuthorizationFlagPartialRights      = (1 << 2),
    kAuthorizationFlagDestroyRights      = (1 << 3),
    kAuthorizationFlagPreAuthorize       = (1 << 4),
	
    // private bits (do not use)
    kAuthorizationFlagNoData             = (1 << 20)
};

各フラグの意味は、だいたいこんな感じだ。もちろん、各 API でちょっとずつフラグの解釈は違うけどね。

kAuthorizationFlagDefaults
読んでそのまま、デフォルトのフラグね。特に何も指定しないときに使われるんだ。

kAuthorizationFlagInteractionAllowd
これを指定すると、必要なときに認証ダイアログを表示するんだ。あの、ユーザ名とパスワードを求めるやつね。ダイアログの準備、生成と後片付けは、Authorization API にまかせてしまっていいんだ。

kAuthorizationFlagExtendRights
自分の権限を拡張するんだ。たとえば、いまは一介のユーザに過ぎないけど admin の権限が欲しいんだー、というときに設定するんだ。

kAuthorizationFlagDestroyRights
これには意味が 2 つある。1 つは、AuthorizationFree() で使われるときで、メモリと権限を解放する、という意味。もう 1 つは、AuthorizationCreate() とかで使われるときで、権限を変えないことを保証する、という意味があるんだ。例えば、いまの自分の権限を調べたいだけで、絶対に変えたくないんだ、っていうときに使えるんだ。

◆ AuthorizationItem

認証に必要な情報を格納するのがこの AuthorizationItem だ。たとえばユーザ名とかパスワードとかね。

Security/Authorization.h
typedef struct {
    AuthorizationString name;
    UInt32 valueLength;
    void *value;
    UInt32 flags;
} AuthorizationItem;

name のところには情報の種類を指定するんだけど、こんなものがあるんだ。

kAuthorizationEnvironmentUsername
ユーザ名だ。そのままだな。

kAuthorizationEnvironmentPassword
パスワードだ。これもそのままだぞ。

kAuthorizationEnvironmentShared
これはユーザ名とパスワードの両方らしい。

kAuthorizationRightExecute
これは将来使われるみたい。いまはまだサポートされてない。

September 23 - Authorization API 完全理解 - 番外
keywords: process ID

◆ 認証されたプロセスの ID

AuthorizationExecuteWithPrivileges() で起動されたプロセスの process ID を得る方法はないのか?それじゃ起動した後はパイプしか通信手段がないの?それじゃ、ちゃんと制御できないじゃん。

September 20 - Authorization API 完全理解 - その 4
keywords: time limit

◆ Authorization の有効期間

認証には有効期間が設定してあるらしい。認証した後、ぼーっとほっておいて、もう一回アクセスしようとすると再認証を求められるんだ。その時間は?どうやって設定するんだ?うーむ、どこに書いてあるのか見つからないぞ。ただ、sudo の man を見てみると、デフォルト 5 分って書いてある。Authorization API を使ったときも、経験的にそのくらいだから、そういうことかも。じゃ、時間を変えるには?どうも Authorization API からは設定する術がないようだ。将来の拡張に期待しましょう。

September 17 - Authorization API 完全理解 - その 3
keywords: AuthorizationRef

◆ Authorization API でできること

Authorization API でできることは、結論からいうと、ある実行ファイルを実行することだ。実行後はパイプを使って、やりとりできる。つまり、この API は、UNIX ライクな(つーか、UNIX そのもの)コマンドを実行することを念頭に置いたものなんだ。

まず Authorization API は、きみが、いま、どれぐらいの権限を持ってるか調べるんだ。そして、それはあるコマンドを実行するのに十分な権限なのか?ってことも調査できる。もし足りなかったら、それを拡大することもできる。おっと、もちろん適切なパスワードが必要だぜ。そのパスワードの入力をうながすためのダイアログも Authorization API が提供するんだ。

処理の流れを簡単に見てみよう。まず認証オブジェクト AuthorizationRef を作ってやんないといけない。これは AuthorizationCreate() で作れるぜ。

認証オブジェクトができたら、きみがどのくらいの権限を持っているかどうか調べることができる。たとえば /sbin/shutdown を実行できるか?とか。<いきなり shutdown かい。それには AuthorizationCopyRights() を使う。これで、実行できるかどうかが調べられる。

もし、十分な権限がなかったらどうするんだ?その場合は、権限を広げることができるんだ。もちろんパスワードが要求されるぜ。これも AuthorizationCopyRights() を使うんだ。

これで十分な権限を確保していることを確認したら、実行だ!AuthorizationExecuteWithPrivileges() で実行できる。

使い終わった後は、認証オブジェクトを削除するのを忘れずに。AuthorizationFree() だ。

September 16 - Authorization API 完全理解 - その 2
keywords: permission denided

◆ Permission denided を乗りこえる

じゃ、デスクトップ・アプリケーションを作るときのことを考えてみよう。この場合でも root 権限が欲しい場合がある。たとえばインストールの時とか、/usr/sbin の下のファイルを削除するときとか<良い子はそんなことしちゃいかん。喜びいさんでやろうとすると、無情の Permission denided が表示されることになるだろう。やかましいわ、おれはこのマシンの所有者だぞ、一人で使ってるんだぞ、ネットワークにも公開してないぞ、だから好きにファイルをいぢらせろー、ぜぃぜぃ、はぁはぁ。と、文句をいっても解決しないのである。だって Mac OS X は UNIX だから。

現実的な解決策は、コマンドラインから操作しているならば sudo を使うことだ。これで root 権限が得られる。じゃ GUI ベースの場合は?Cocoa アプリならば sudo を NSTask で呼び出してもいいけど、めんどくさいよね。そこで Apple から提供されたのが Authorization API なんだ。これを使えば GUI ベースで楽々認証ができるんだぜ!

September 15 - Authorization API 完全理解 - その 1
keywords: root, su, sudo

◆ su 禁止

つまるところ UNIX に皮を被せたものである Mac OS X には、“ユーザ”と“ログイン”っていう概念があるんだ。そして“root”っていう概念もある。ある特定のファイルやディレクトリには root しか触ることができないんだ。しかし、classic の Mac OS にはそんな考え方がなかったので、普通のユーザはそんなことを気にしないだろう。機能拡張やコントロールパネルを外して楽しむように、/bin や /usr/sbin の下のファイルを外して、使用メモリを減らそうと試みるかもしれない。おぉぅ、それはやめてくれぇ。そんなことが流行りはじめたら、混乱を極めることは間違いないだろう。

そこで Apple がとった手段は、10.0 以降の Mac OS X では、デフォルトでの root でのログインを禁止することだった。Oh, my! これは英断と見るべきなのか、暴挙と見るべきなのか?さらにさらに、Apple は su までも禁止したのだった。su というのは、root の権限を得るためのコマンドね。Terminal で su を打つと、次のように表示されるんだ。

Welcome to Darwin!
[localhost:~] mkino% su
Password:
Sorry
[localhost:~] mkino% 

root になろうとすると、ひとこと "Sorry"。クール過ぎるぜ!

さて、当然このままで終わるわけはなくて、Apple は別の手段を推賞している。それは sudo を使うこと。sudo を使うとコマンドを root 権限で実行することができる。su と違うのは、sudo はすべてのログが残る、ということらしい。つまり su だと、Telnet で侵入されて root になられて好き放題やられちゃうけど、sudo ならばその場合でもログが残るぜ、ということなのだ。うーん、あまり変わらんような気もするが。別の効用もあるのか?

September 14 - Security APIs
keywords: Security API, Authorization

Security.framework をきちんと理解しよう、と思って Authrization.h のヘッダを見てたんだ。結構コメントが充実しているんだよ。もったいないから(?)ちょっと訳してみた、、、あー、時間がないや。走り書きだけ載せていくね。近日中にきちんと訳してみる予定。会社行かんと。じゃ。

AuthorizationCreate

新しい認証オブジェクトを作るんだ。その認証がもういらなくなったら、AuthorizationFree を呼ばないとだめだかんね。

kAuthorizationFlagInteractionAllowed フラグが設定されたときは、必要なときにユーザからの入力を、おらおら早くパスワード入れんかいって、要求するんだ。これの設定に失敗したりすると、ほんとうに必要なときに、errAuthorizationInteractionNotAllowed っていうエラーが起こるんだ。

AuthorizationFree

認証オブジェクトを壊すんだ。kAuthorizationFreeFlagDestroy が設定されたときは、認証に関する権利がすべてなくなるんだ。設定しなかったら、ローカルのだけがなくなって、他のクライアントの分は残るんだ。(訳注:この他のクライアントってのは、他のユーザのことか?それとも他の種類の認証のことか?)

AuthorizationCopyRights

いま認証されているのはなにか?を、調べるためのものなんだ。

AuthorizationCopyInfo

sideband 情報(たとえばアクセス credentials とか)を調べるためのものだ(訳注:わかんねーよ!access credentials ってなに?)

AuthorizationMakeExternalForm

認証を外部の "byte blob" の形に変えるんだ。これで他のプロセスに送ることができるぜ(訳注:これもわからんよー)

AuthorizationCreateFromExternalForm

(訳注:これは上と同じかな。認証の作成も込みみたい)

AuthorizationFreeItemSet

API を呼んで確保された AuthorizationItemSet のメモリを解放するんだ。

AuthhorizationExecuteWithPrivileges

適切な認証処理が終わった後に、その権限で実行ファイルを実行するんだ。

AuthorizationCopyPrivilegedReference

AuthorizationExecuteWithPrivileges で実行されてるツールから、認証オブジェクトを取り出すんだ。

September 12 - NSArray にオブジェクトを突っ込む
keywords: NSArray, copyWithZone

NSArray の話だ。正しいかどうか、ちょっと不安だけど。

NSArray ってのは、Foundation にある配列をあらわすクラスだよね。NSArray には NSObject を入れることができる。さて、自分で NSObject を継承するクラスを作ったら、それを簡単に NSArray に入れることができるのか?

そうではない。らしい。NSArray に入れるオブジェクトは copyWithZone: を実装しておかないといけない。実装していなければ、runtime error が発生するんだ。つまり、NSArray に突っ込んだ時点でコピーしているんだね、きっと。参照の保持ではなくて、値の保持である、と。

じゃあ、copyWithZone: を実装するときになにか気をつけることはあるのか?copyWithZone: は、自分のクラスのコピーを作って返すメソッドだ。返り値として id を返すんだけど、このインスタンスは retain されていないといけない。autorelease されてはいけない

- (id)copyWithZone:(NSZone*)zone
{
    id copy = [[MyClass alloc] autorelease]; // NG !!!
    return copy;
}

正しくは、こう。

- (id)copyWithZone:(NSZone*)zone
{
    id copy = [MyClass alloc];
    return copy;
}

alloc を直接使っている場合は間違えないと思うけど、自前のファクトリメソッドを作って、その中で autorelease している場合は注意が必要だ、と思う。

今回の話は、ドキュメントで確かめたわけではなくて、実際にコードを書いていて気付いただけなので、ほんとに正しいかどうか不安です。よかったら、どなたか、これで正しいのかどうか教えて下さい。

September 10 - System Preference パネルを作る
keywords: NSPreferencePane

ごぶさた!バケーションを取ってました。南の島で、身も心もリラックスしてきたよ。

さて、どういうわけか、最近英語のメールが多く届くようになりました。どこかで紹介されたのか?ま、その全部が「日本語だからわからねーよ」っていうメールなんですが。

その中に、「OS X 10.1 で NSPreferecnePane ってのが追加されたでしょ。使い方知らない?」っていうのが混じってました。ほうほう、そんなものがあったのか。じゃ、っていうんで System/Library/Frameworks を探してみると、、、おっ、確かに PreferencePanes.framework っていうのものがある。なるほど、これを使えば初期設定パネルが作れるのか。ざっと見ると、うんうん、nib を関連づければいいわけね。10.1 がリリースされたら、フリーウェアで初期設定パネルを作るのが流行りそう。

September 1 - きょうの挫折、コンテキストメニュー、その 3
keywords: context menu

先日、マウス押しっぱなしでコンテキストメニューを表示できないかなー、と書いたところ、やまかわさんから、performSelector:object:afterDelay: を使えばいいじゃん、と教えていただきました。Thanks! てなわけで、やってみました。

こんな感じのコードを書いてみた。

- (void)mouseDown:(NSEvent*)event {
    NSArray*	array;
    
    array = [NSArray arrayWithObject:
                    NSEventTrackingRunLoopMode];
    [self performSelector:@selector(showContextMenu:) 
                    withObject:event 
                    afterDelay:1.5 
                    inModes:array];
    
    [super mouseDown:event];
    
    [NSObject cancelPreviousPerformRequestsWithTarget:self 
                    selector:@selector(showContextMenu:) 
                    object:event];
}

- (void)showContextMenu:(id)event
{
    NSMenu*	menu;
    
    menu = [self menu];
    
    [NSMenu popUpContextMenu:menu 
                    withEvent:event 
                    forView:self];
}

まず、mouseDown: の中で performSelector:::: を呼び出す。その際、inModes に NSEventTrackingRunLoopMode を設定するのがコツ。これで Cocoa がイベントのトラッキングをしている間でも呼び出される。その後、親の mouseDown: を呼び出す。最後に cancelPreviousPerformRequestsWithTarget::: でセレクタの呼び出しをキャンセルする。

じゃ、動かしてみよう。おっ、でたでた。メニューが出た。やったじゃん。あり?でも、その後の挙動がおかしいぞ、、、

どう動いているのかいろいろ調べてみたところ、設定したメソッドが呼ばれた後、この場合は showContextMenu: ね、親の mouseDown: の中から抜け出てこないようだ。

流れは、まず mouseDown: が呼ばれる。performSelector を設定して、親に制御を移す。その中で Tracking Event Loop が回る。一定時間がたつと、showContextMenu: が呼ばれる。ここでいったん確認するけど、いまはマウスボタン押しっぱなしの状態だよね?で、メニューが表示されるでしょ。その後、マウスボタンを離す。でもこのイベントは、mouseDown: の中の Tracking Event Loop に通知されないようだ。だから、そこから抜けるには、どこかでもう一度クリックしてやらないといけない。これじゃ、まずいでしょー。

うーむ、もうひとひねり必要だな。


Home | Link | Download | Back Number | Speciall Issue

mailto: mkino@xd5.so-net.ne.jp

HMDT