ページ

2010年3月12日金曜日

Keychain Services 調査 (12) コーディング #2 パスワードを取得する

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク

(前回)Cocoaの日々: Keychain Services 調査 (11) コーディング #1 パスワードを格納する

前回 Keychainへ格納したパスワードを取得してみる。取得には SecKeychainFindGenericPassword を使う。

Mac Dev Center: Keychain Services Reference SecKeychainFindGenericPassword






OSStatus SecKeychainFindGenericPassword (
   CFTypeRef keychainOrArray,
   UInt32 serviceNameLength,
   const char *serviceName,
   UInt32 accountNameLength,
   const char *accountName,
   UInt32 *passwordLength,
   void **passwordData,
   SecKeychainItemRef *itemRef
);
前回作成した KeychainManager クラスにパスワード取得のメソッドを追加する。

KeychainManager.m
-(NSString*)getPasswordWithServiceName:(NSString*)serviceName accountName:(NSString*)accountName
{
OSStatus status;
const char *serviceNameUTF8 = [serviceName UTF8String];
const char *accountNameUTF8 = [accountName UTF8String];
void *passwordData = nil;
UInt32 passwordLength;
SecKeychainItemRef *itemRef = nil;

status = SecKeychainFindGenericPassword(NULL,
strlen(serviceNameUTF8),
serviceNameUTF8,
strlen(accountNameUTF8),
accountNameUTF8,
&passwordLength,
&passwordData,
itemRef);
NSString* password = [NSString stringWithUTF8String:passwordData];

status = SecKeychainItemFreeContent(NULL, passwordData);
return password;
}


取得した passwordData は SecKeychainItemFreeContent を使って開放しておく。
Mac Dev Center: Keychain Services Reference - SecKeychainItemFreeContent

OSStatus SecKeychainItemFreeContent (
SecKeychainAttributeList *attrList,
   void *data
);


KeychainManager では開放前に NSString へコピーしている。


実行してみよう。
Keychain には前回格納されたパスワードがあるはずなので、"GET"を押す。

すると認証ダイアログが出てきた。
同じアプリにも関わらず、「真正性を確認できません」と出てきた。

これは前回格納した後、プログラムに手を加えて新しい実行バイナリをビルドした為。以前、ドキュメントを読んだ時にこの件の記述があった。

(参考)Cocoaの日々: Keychain Services 調査 (4) ドキュメントを読む #2 - ACL

Keychain に信頼されたアプリが登録される場合、実行ファイルのハッシュ値(と思われる)も一緒に格納され、アプリからアクセスがあった場合にはこのハッシュ値を比較する。これはアプリが改ざんされたケースを検出する為の機構だと思われる。正規のアプリであってもこのようにバージョンが異なると、認証ダイアログが表示される仕組みとなっている。

ここでは許可を選択して次へ進む。するとパスワードが無事に取得できた。

KeychainSample1[10336:80f] password=1234567


なお一旦 キーチェーン.app でこのパスワードを削除後に、"TEST"ボタンでパスワードを登録し、その後 "GET" を押すと、今度は認証ダイアログが表示されずパスワードが取得できた。


この辺り、バージョンが変わる毎にダイアログが出るのは実用上煩雑。Safari などはこれに該当しないようなので(Software Upadateでアップデートされるものはそうらしい)、セキュリティを保ちつつ頻繁な確認をさせない回避策を見つけたいところだ。