otsune's SnakeOil RSSフィード

python -c "print''.join([chr(x) for x in 111&1101,110+~-~11,10^11*11,110+~-~11,-~101,-~11^11*11,~-110,111&11*11,11+11+10,11|~-0110,1-~11^11*11,10^11*11,-~11^11*11,110,101])"

2007-09-11

Plaggerのpassword:をMac OS XのKeyChain Accessから引っ張ってくるCryptモジュール書いた

| Plaggerのpassword:をMac OS XのKeyChain Accessから引っ張ってくるCryptモジュール書いた - otsune's SnakeOil  を含むブックマーク はてなブックマーク - Plaggerのpassword:をMac OS XのKeyChain Accessから引っ張ってくるCryptモジュール書いた - otsune's SnakeOil  Plaggerのpassword:をMac OS XのKeyChain Accessから引っ張ってくるCryptモジュール書いた - otsune's SnakeOil  のブックマークコメント

何でそうするのかと言うと、plaggerのconfig.yamlのpassword:は現状では単なる難読化しかサポートしていないから。認証データは一元管理したい。

ソースは /lang/perl/plagger/lib/Plagger/Crypt/Keychain.pm ? CodeRepos::Share ? Trac に。

package Plagger::Crypt::Keychain;
use strict;

use Mac::AppleScript qw(RunAppleScript);
use URI;

sub id { 'keychain' }

sub decrypt {
    my ($self, $text) = @_;
    my $u = URI->new($text);
#    my $protocol     = $u->scheme; 
    my $account_name = $u->userinfo;
    my $server_name  = $u->host; 
#    my $port         = $u->port;
    my $path_to      = $u->path;
    my $result =
    RunAppleScript(qq{tell application "Keychain Scripting"\nreturn password of last Internet key of current keychain whose server is "$server_name" and path is "$path_to"\nend tell});
    if ($@) {
        Plagger->context->log(error => "AppleScript error: $@");
        return;
    }
    return fixquote($result);
}

sub encrypt {
    my($self, $text) = @_;
    my $u = URI->new($text);
    my $protocol     = $u->scheme; 
    my ($account_name, $clr_password) = split /:/, $u->userinfo;
    my $server_name  = $u->host; 
#    my $port_num     = $u->port;
    my $path_to      = $u->path;
    RunAppleScript(qq/tell application "Keychain Scripting"\nmake new Internet key at current keychain with properties {account:"$account_name", password:"$clr_password", server:"$server_name", path:"$path_to", protocol:"$protocol"}\nend tell/);
    if ($@) {
        Plagger->context->log(error => "AppleScript error: $@");
        return;
    }
    $u->userinfo($account_name);
    return $u->as_string;
}

sub fixquote {
    $_[0] =~ s/(?:\xC2\xA5|\\)"/"/mg; # delete YEN SIGN or BACKSLASH
    return substr $_[0], 1, length($_[0])-2; # strip quotation
}

1;

__END__

=head1 NAME

Plagger::Crypy::Keychain - Plagger Crypt for Mac OS X Keychain Access

=head1 SYNOPSIS

  - module: Plugin::Foobar
      config:
        host: example.com
        username: username
        password: keychain::http://username:password@example.com/pathto/

=head1 DESCRIPTION

=head1 KNOWN BUGS
dont work contains '@' at username.

(あと t/core/keychain.t と Makeperl.PL でdependどうするかがよく分からん)

(2008-10-24追記:Perlからキーチェーンのパスワードを引っ張ってくるのはTatsuhiko Miyagawa / LWP-UserAgent-Keychain-0.01 - search.cpan.org

use Mac::Glue ':all';
use base qw( LWP::UserAgent );

my $keychain = Mac::Glue->new("Keychain Scripting");

sub get_basic_credentials {
    my($self, $realm, $uri, $isproxy) = @_;

    for my $key ($keychain->obj(keys => keychain => "Login.keychain")->get) {
        if ($key->prop('class')->get eq 'cint' and
            $key->prop('server')->get eq $uri->host and
            $key->prop('protocol')->get eq $uri->scheme) {

            my $username = $key->prop('account')->get;
            my $password = $key->prop('password')->get;
            return ($username, $password);
        }
    }

    return (undef, undef);
}

みたいにMac::Glue使うほうがスッキリ書けるので良いかも)

んで現状のplaggerはlib/Plagger/Plugin.pmを

sub decrypt_config {
    my($self, $data, $key) = @_;

    my $decrypted = Plagger::Crypt->decrypt($data->{$key});
    if ($decrypted eq $data->{$key}) {
#        Plagger->context->add_rewrite_task($key, $decrypted, Plagger::Crypt->encrypt($decrypted, 'base64'));
        Plagger->context->add_rewrite_task($key, $decrypted, Plagger::Crypt->encrypt($decrypted, 'keychain'));
    } else {
        $data->{$key} = $decrypted;
    }
}

という感じにbase64からkeychainに変えないとencryptでrewriteしてくれない。

このあたりはglobalのconfigを見るのが良いのかも?

--- lib/Plagger/Plugin.pm       (revision 1873)
+++ lib/Plagger/Plugin.pm       (local)
@@ -68,10 +68,10 @@
 
 sub decrypt_config {
     my($self, $data, $key) = @_;
-
+    my $context = Plagger->context;
     my $decrypted = Plagger::Crypt->decrypt($data->{$key});
     if ($decrypted eq $data->{$key}) {
-        Plagger->context->add_rewrite_task($key, $decrypted, Plagger::Crypt->encrypt($decrypted, 'base64'));
+        $context->add_rewrite_task($key, $decrypted, Plagger::Crypt->encrypt($decrypted, $context->conf->{encrypt} || 'base64'));
     } else {
         $data->{$key} = $decrypted;
     }
global:
  encrypt: keychain

こんな感じで。

トラックバック - http://subtech.g.hatena.ne.jp/otsune/20070911