[Mew-dist 2009] Re: Get Password from File patch for IM-65
Motonori Nakamura
motonori at example.com
1997年 9月 14日 (日) 09:29:49 JST
>>>>> On Wed, 27 Aug 1997 08:23:32 +0900, AOSASA Shigeru <aozasa at example.com> said:
aozasa> IM-65 で pop/POP, pop/APOP, imap/AUTH, imap/LOGIN, (http/???)
aozasa> のパスワードをファイルに書いておけるようにするパッチです。
ssh-agent 的にプロセスでパスワードを記憶し、unix domain socket で
通信する方式を実装してみました。
HTTP の場合に directory matching していないとか、プロセス内に保存する
パスワードが生のままだとかいろいろ問題は残っていると思うので、
そのへんの contribution を期待しています (^_^)
IM-66 へのパッチになっています。Config に、UsePwAgent=yes と記述し、
impwagent を起動すると、それ以降は各コマンドが、impwagent と通信
して一度入力したパスワードを再利用するようになります。
impwagent の操作:
起動
impwagent
終了
impwagent quit
パスワードキャッシュのクリア
impwagent clear
です。unix domain socket は /tmp/im-motonori/pw に作られ、
モードは og-rwx になります。
まず、手動で impwagent を起動しておき、最初に一度だけ行われる
パスワードの入力要求に答えてください。以後、そのパスワードは
impwagent が忘れるかいなくなるまで再利用されます。impwagent が
動いていないときは、warning message を出しながら従来通りの
動作になります。
それから、ご推察通り、windows 方面ではうまく動かないような気がします。
どうしましょ :-)
# imput に --NoMsgIdForNews が追加されています。
- motonori
diff -ur ../im-66-/IM.in/Config.pm.in ./IM.in/Config.pm.in
--- ../im-66-/IM.in/Config.pm.in Sun Aug 24 16:56:17 1997
+++ ./IM.in/Config.pm.in Sun Sep 14 08:58:11 1997
@@ -41,7 +41,7 @@
msgdbfile msgdbtype getsbrfile scansbrfile petnamefile
mbox_style
nntpservers nntphistoryfile
- popaccount pophistoryfile imapaccount httpproxy noproxy
+ popaccount pophistoryfile imapaccount httpproxy noproxy usepwagent
unixp win95p wntp os2p
im_msg im_info im_debug im_notice im_warn im_err im_die im_die2
im_save_error im_saved_errors
@@ -139,7 +139,7 @@
'trashfolder;f;+trash;TrashFolder' => 'Trash folder',
'foldermode;i;0700;FolderMode' => 'Folder directory mode when created',
'msgmode;i;0600;MsgMode' => 'Message file mode when created',
- 'preservedot;b;off;PreserveDot' => 'Not substitute "." with "/"',
+ 'preservedot;b;;PreserveDot' => 'Not substitute "." with "/"',
'contextfile;s;Context;ContextFile' => 'Context file',
'address;s;;Address' => 'Email addresses',
'addrregex;s;;AddrRegex' => 'Email addresses by regex',
@@ -156,6 +156,7 @@
'imapaccount;s;;IMAPaccount' => 'Account info for IMAP access',
'httpproxy;s;;HTTPproxy' => 'Proxy server for HTTP access',
'noproxy;s;;Noproxy' => 'URL regex not to use Proxy server',
+ 'usepwagent;b;;UsePwAgent' => 'Use password agent',
);
##
@@ -752,6 +753,10 @@
sub noproxy {
return $Noproxy;
+}
+
+sub usepwagent () {
+ return $UsePwAgent;
}
###
diff -ur ../im-66-/IM.in/GetPass.pm.in ./IM.in/GetPass.pm.in
--- ../im-66-/IM.in/GetPass.pm.in Mon Aug 25 15:04:27 1997
+++ ./IM.in/GetPass.pm.in Sun Sep 14 08:58:11 1997
@@ -23,7 +23,7 @@
use IM::Stdio;
@ISA = qw(Exporter);
- at example.com = qw(getpass);
+ at example.com = qw(getpass loadpass savepass connect_agent);
=head1 NAME
@@ -64,6 +64,69 @@
}
return $secret;
+}
+
+sub loadpass ($$$$) {
+ my ($proto, $auth, $path, $user) = @_;
+ my $pass = &connect_agent("LOAD\t$proto\t$auth\t$path\t$user\n", 0);
+ if ($pass =~ /^PASS\t(.*)/) {
+ # decrypt pass ?
+ return $1;
+ } else {
+ return '';
+ }
+}
+
+sub savepass ($$$$$) {
+ my ($proto, $auth, $path, $user, $pass) = @_;
+ # encrypt pass ?
+ &connect_agent("SAVE\t$proto\t$auth\t$path\t$user\nPASS\t$pass\n", 0);
+}
+
+sub connect_agent ($$) {
+ my ($msg, $surpresserror) = @_;
+ require Socket && import Socket;
+
+ my $realuser = getlogin || (getpwuid($<))[0];
+ unless ($realuser) {
+ im_warn("pwagent: can not get login name\n") unless ($surpresserror);
+ return '';
+ }
+ my $dir = "/tmp/im-$realuser";
+ my $name = "$dir/pw";
+
+ unless (-S $name) {
+ im_warn("pwagent: can not access to socket: $name\n")
+ unless ($surpresserror);
+ return '';
+ }
+
+ my ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev) = stat($dir);
+ if ($mode & 0077) {
+ im_warn("pwagent: invalid mode: $dir\n") unless ($surpresserror);
+ return '';
+ }
+ ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev) = stat($name);
+ if ($mode & 0077) {
+ im_warn("pwagent: invalid mode: $name\n") unless ($surpresserror);
+ return '';
+ }
+
+ unless (socket(SOCK, &AF_UNIX, &SOCK_STREAM, 0)) {
+ im_warn("pwagent: socket: $!\n") unless ($surpresserror);
+ return '';
+ }
+ my $sun = sockaddr_un($name);
+ unless (connect(SOCK, $sun)) {
+ im_warn("pwagent: connect: $!\n") unless ($surpresserror);
+ return '';
+ }
+ select(SOCK); $| = 1; select(STDOUT);
+ print SOCK $msg;
+ my $res = <SOCK>;
+ shutdown (SOCK, 2);
+ close(SOCK);
+ return $res;
}
1;
diff -ur ../im-66-/IM.in/Http.pm.in ./IM.in/Http.pm.in
--- ../im-66-/IM.in/Http.pm.in Sat Aug 30 11:19:48 1997
+++ ./IM.in/Http.pm.in Sun Sep 14 08:58:11 1997
@@ -119,6 +119,8 @@
my $pass = '';
my $retry = 3;
+ my $first = 1;
+ my $found = 0;
while (1) {
($user, $host, $port, $path) = &http_spec($spec);
@@ -161,8 +163,20 @@
next if ($rcode == 302 && $new_spec);
if ($rcode == 401 && $auth =~ /Basic/i && $retry--) {
require IM::GetPass && import IM::GetPass;
+ if ($first && &usepwagent()) {
+ $first = 0;
+ $pass = &loadpass('http', $auth, $path, $user);
+ if ($pass ne '') {
+ $found = 1;
+ next;
+ }
+ }
+# last if ($found && $NoPwQueryOnFail);
$pass = &getpass("Password: ");
next if ($pass ne '');
+ }
+ if ($rcode == 200 && $pass ne '' && &usepwagent()) {
+ &savepass('http', $auth, $path, $user, $pass);
}
last;
}
diff -ur ../im-66-/IM.in/Imap.pm.in ./IM.in/Imap.pm.in
--- ../im-66-/IM.in/Imap.pm.in Sat Aug 30 11:19:48 1997
+++ ./IM.in/Imap.pm.in Sun Sep 14 09:01:21 1997
@@ -531,10 +531,18 @@
my ($folder, $auth, $user, $host) = &imap_spec($src);
return -1 if ($folder eq '');
- $pass = &getpass('Password: ');
+ my $pass = '';
+ my $found = 0;
+ if (&usepwagent()) {
+ $pass = &loadpass('imap', $auth, $host, $user);
+ found = 1 if ($pass ne '');
+ }
+ $pass = &getpass('Password: ') if ($pass eq '');
im_notice("accessing IMAP/$auth:$user\@$host for $how\n");
if (&imap_open($auth, $host, $user, $pass) == 0) {
+ &savepass('imap', $auth, $host, $user, $pass)
+ if ($pass ne '' && !$found && &usepwagent());
my $msgs = &imap_process($how, $host, $folder, $dst);
if ($msgs < 0) {
im_warn("IMAP processing error.\n");
@@ -542,7 +550,9 @@
&imap_close();
return $msgs;
} else {
- im_warn("$ErrMsg\n");
+ im_err("IMAP connection was not established.\n");
+ &savepass('imap', $auth, $host, $user, '')
+ if ($found && &usepwagent());
im_warn("IMAP connection was not established.\n");
return -1;
}
diff -ur ../im-66-/IM.in/Message.pm.in ./IM.in/Message.pm.in
--- ../im-66-/IM.in/Message.pm.in Fri Aug 29 16:12:06 1997
+++ ./IM.in/Message.pm.in Sun Sep 14 08:58:11 1997
@@ -486,6 +486,7 @@
foreach $del (@main::Del_headers_on_news) {
next hdr if ($line =~ /^$del:/i);
}
+ next hdr if ($line =~ /Message-Id:/i && $main::NoMsgIdForNews);
if ($main::Obey_MTA_domain
&& ($line =~ /^(From|Sender|Reply-To):\s*(.*)/i)) {
my $val = &rewrite_addr_list(1, $2, 1);
diff -ur ../im-66-/IM.in/Pop.pm.in ./IM.in/Pop.pm.in
--- ../im-66-/IM.in/Pop.pm.in Sat Aug 30 11:19:49 1997
+++ ./IM.in/Pop.pm.in Sun Sep 14 09:02:36 1997
@@ -475,17 +478,28 @@
my ($auth, $user, $host) = &pop_spec($src);
- $pass = &getpass('Password: ') unless ($auth eq 'RPOP');
+ my $pass = '';
+ my $found = 0;
+ unless ($auth eq 'RPOP') {
+ if (&usepwagent()) {
+ $pass = &loadpass('pop', $auth, $host, $user);
+ $found = 1 if ($pass ne '');
+ }
+ $pass = &getpass('Password: ') if ($pass eq '');
+ }
im_notice("accessing POP/$auth:$user\@$host for $how\n");
my $rc = &pop_open($auth, $host, $user, $pass);
unless ($rc) {
+ &savepass('pop', $auth, $host, $user, $pass)
+ if ($auth ne 'RPOP' && !$found && $pass ne '' && &usepwagent());
if (&pop_process($how, $host, $dst) < 0) {
im_warn("POP processing error.\n");
}
&pop_close();
} else {
- im_err($ErrMsg);
+ &savepass('pop', $auth, $host, $user, '')
+ if ($auth ne 'RPOP' && $found && &usepwagent());
im_err("POP connection was not established.\n");
}
}
diff -ur ../im-66-/Makefile.in ./Makefile.in
--- ../im-66-/Makefile.in Fri Aug 29 15:22:40 1997
+++ ./Makefile.in Sun Sep 14 08:58:12 1997
@@ -50,6 +50,7 @@
$(INSTALL) -m 555 impack $(bindir)
$(INSTALL) -m 555 impath $(bindir)
$(INSTALL) -m 555 imput $(bindir)
+ $(INSTALL) -m 555 impwagent $(bindir)
$(INSTALL) -m 555 imrm $(bindir)
$(INSTALL) -m 555 imsetup $(bindir)
$(INSTALL) -m 555 imsort $(bindir)
@@ -76,7 +77,7 @@
clean::
$(rm) -f imali imcat imcd imrm imget imgrep imhist imls immv \
- impack impath imput imsetup imsort imstore
+ impack impath imput impwagent imsetup imsort imstore
$(rm) -rf IM
$(mkdir) IM
diff -ur ../im-66-/cnf.im/Config ./cnf.im/Config
--- ../im-66-/cnf.im/Config Sun Aug 24 12:12:39 1997
+++ ./cnf.im/Config Sun Sep 14 08:58:12 1997
@@ -46,8 +46,8 @@
Src=$InboxFolder
Imrm.Src=$TrashFolder
Imget.Src=local
-#Imget.Src=local:${HOME}/MailDir
#MBoxStyle=qmail
+#Imget.Src=local:${HOME}/MailDir
##
## Command depend
##
@@ -58,6 +58,7 @@
Indent=2 # --indent
FromDomain=_domain_of_your_mail_address_
ToDomain=_domain_when_domain_part_is_omitted_
+#MsgIdDomain=${HOST}
Smtpservers=localhost # --smtpservers
NntpServers=localhost # --nntpservers
##
diff -ur ../im-66-/configure ./configure
--- ../im-66-/configure Sat Aug 30 11:22:58 1997
+++ ./configure Sun Sep 14 08:58:12 1997
@@ -999,6 +999,7 @@
imget:imget.in imgrep:imgrep.in imhist:imhist.in \
imls:imls.in immv:immv.in \
impack:impack.in impath:impath.in imput:imput.in \
+ impwagent:impwagent.in \
imrm:imrm.in imsetup:imsetup.in imsort:imsort.in \
imstore:imstore.in \
Makefile:Makefile.in \
@@ -1118,6 +1119,7 @@
imget:imget.in imgrep:imgrep.in imhist:imhist.in \
imls:imls.in immv:immv.in \
impack:impack.in impath:impath.in imput:imput.in \
+ impwagent:impwagent.in \
imrm:imrm.in imsetup:imsetup.in imsort:imsort.in \
imstore:imstore.in \
Makefile:Makefile.in \
@@ -1210,7 +1212,7 @@
EOF
cat >> $CONFIG_STATUS <<\EOF
chmod 555 imali imcat imcd imget imgrep imhist \
- imls immv impack impath imput imrm imsetup imsort imstore
+ imls immv impack impath imput impwagent imrm imsetup imsort imstore
exit 0
EOF
chmod +x $CONFIG_STATUS
diff -ur ../im-66-/configure.in ./configure.in
--- ../im-66-/configure.in Sat Aug 30 11:22:22 1997
+++ ./configure.in Sun Sep 14 08:58:12 1997
@@ -56,6 +56,7 @@
imget:imget.in imgrep:imgrep.in imhist:imhist.in \
imls:imls.in immv:immv.in \
impack:impack.in impath:impath.in imput:imput.in \
+ impwagent:impwagent.in \
imrm:imrm.in imsetup:imsetup.in imsort:imsort.in \
imstore:imstore.in \
Makefile:Makefile.in \
@@ -84,4 +85,4 @@
IM/Stdio.pm:IM.in/Stdio.pm.in \
IM/TcpTransaction.pm:IM.in/TcpTransaction.pm.in \
, chmod 555 imali imcat imcd imget imgrep imhist \
- imls immv impack impath imput imrm imsetup imsort imstore)
+ imls immv impack impath imput impwagent imrm imsetup imsort imstore)
diff -ur ../im-66-/imcat.in ./imcat.in
--- ../im-66-/imcat.in Thu Aug 28 10:44:48 1997
+++ ./imcat.in Sun Sep 14 09:03:51 1997
@@ -153,16 +153,25 @@
my ($folder, $auth, $user, $host) = &imap_spec($1);
- my $pass = &getpass('Password: ');
+ my $pass = '';
+ my $found = 0;
+ if (&usepwagent()) {
+ $pass = &loadpass('imap', $auth, $host, $user);
+ $found = 1 if ($pass ne '');
+ }
+ $pass = &getpass('Password: ') if ($pass eq '');
im_warn("accessing IMAP/$auth:$user\@$host\n") if (&verbose);
if (&imap_open($auth, $host, $user, $pass) < 0) {
- im_warn("$ErrMsg\n");
+ &savepass('imap', $auth, $host, $user, '')
+ if ($found && &usepwagent());
im_warn("IMAP connection was not established.\n")
if (&debug('imap') || &verbose);
exit $EXIT_ERROR;
}
+ &savepass('imap', $auth, $host, $user, $pass)
+ if (!$found && $pass ne '' && &usepwagent());
my $msgs = &imap_select($folder, 1);
if ($msgs < 0) {
&imap_close;
diff -ur ../im-66-/imget.in ./imget.in
--- ../im-66-/imget.in Sat Aug 30 11:19:50 1997
+++ ./imget.in Sun Sep 14 08:58:12 1997
@@ -69,6 +69,8 @@
'protokeep;s;UIDL;'=> "Protocol type to use for keeping messages on POP.\n".
"\t\t(UIDL, LAST, STATUS, MSGID)\n" .
"\t\tTimed out deletion is not supported with LAST.",
+ 'usecl;b;;Obey_CL' => "Use value of Content-Length header for delimitation".
+ ".\n\t\t(effective only if source of messages is local).\n" ,
'src;s;;' =>
"Message source: 'local[:path_of_mbox]'\n" .
"\t\t\t\t'pop[/APOP|/RPOP|/POP][:user][\@host]'\n" .
@@ -168,13 +170,14 @@
&exec_getsbrfile();
}
+sub alarm_func () {
+# no operation
+}
+
### ToDo list
# code conversion
-# CRLF conversion
# auto refile
# filter execution
-# config
-# get date information from message
### Local Variables:
### mode: perl
diff -ur ../im-66-/imls.in ./imls.in
--- ../im-66-/imls.in Sun Aug 24 16:56:19 1997
+++ ./imls.in Sun Sep 14 09:05:11 1997
@@ -437,17 +437,26 @@
($folder, $auth, $user, $host) = imap_spec($folder);
}
- my $pass = &getpass("Password: ");
+ my $pass = '';
+ my $found = 0;
+ if (&usepwagent()) {
+ $pass = &loadpass('imap', $auth, $host, $user);
+ $found = 1 if ($pass ne '');
+ }
+ $pass = &getpass('Password: ') if ($pass eq '');
# im_warn("accessing IMAP/$auth:$user\@$host\n") if (&verbose);
if (&imap_open($auth, $host, $user, $pass) < 0) {
- im_warn("$ErrMsg\n");
+ &savepass('imap', $auth, $host, $user, '')
+ if ($found && &usepwagent());
# im_warn("IMAP connection was not established.\n")
# if (&debug("imap") || &verbose);
$scan_count = -1;
return -1;
}
+ &savepass('imap', $auth, $host, $user, $pass)
+ if (!$found && $pass ne '' && &usepwagent());
my $exists = &imap_select($folder, 1);
if ($exists < 0) {
&imap_close;
diff -ur ../im-66-/imput.in ./imput.in
--- ../im-66-/imput.in Wed Aug 20 19:38:59 1997
+++ ./imput.in Sun Sep 14 08:58:12 1997
@@ -114,6 +114,8 @@
=> 'Default domain name for recipients.',
'MsgIdDomain;s;;Message_id_domain_name'
=> 'Default domain name for Message-Id generation.',
+ 'NoMsgIdForNews;s;;NoMsgIdForNews'
+ => 'Strip Message-Id when posting to news system.',
'User;s;;User_name'
=> "Local part of the sender's address.",
'Address;s;;Mail_Address'
diff -ur ../im-66-/impwagent.in ./impwagent.in
--- ../im-66-/impwagent.in Sun Sep 14 09:08:32 1997
+++ ./impwagent.in Sun Sep 14 08:58:12 1997
@@ -0,0 +1,157 @@
+#! @im_path_perl@
+################################################################
+###
+### impwagent
+###
+### Copyright (C) 1996-1997 Internet Message Group
+###
+### This Perl5 library conforms
+### GNU GENERAL PUBLIC LICENSE Version 2.
+###
+###
+### Author: Internet Message Group <img at example.com>
+### Created: Sep 13, 1997
+### Revised: @im_revised@
+###
+
+my $VERSION = "impwagent @im_version@";
+
+$Prog = 'impwagent';
+
+##
+## Require packages
+##
+
+require 5.003;
+use Socket;
+use IM::GetPass;
+
+##
+## Main
+##
+
+# server termination
+if ($ARGV[0] =~ /quit/i) {
+ my $res = &connect_agent("QUIT\n", 1);
+ if ($res eq '') {
+ print "$Prog: server is not running\n";
+ } else {
+ print "$Prog: exit message: $res";
+ }
+ exit 0;
+}
+
+# clear password cache
+if ($ARGV[0] =~ /clear/i) {
+ my $res = &connect_agent("CLEAR\n", 1);
+ if ($res eq '') {
+ print "$Prog: server is not running\n";
+ } else {
+ print "$Prog: exit message: $res";
+ }
+ exit 0;
+}
+
+# duplicate check
+my $res = &connect_agent("PING\n", 1);
+if ($res eq "PONG\n") {
+ print STDERR "$Prog: already running.\n";
+ exit 1;
+}
+
+# preparing socket directory
+my $realuser = getlogin || (getpwuid($<))[0];
+unless ($realuser) {
+ print STDERR "$Prog: can not get login name.\n";
+ exit 1;
+}
+
+my $dir = "/tmp/im-$realuser";
+my $sockname = "$dir/pw";
+
+unlink ($sockname);
+rmdir ($dir);
+
+if (-e $dir) {
+ print STDERR "$Prog: can not re-create directory: $dir.\n";
+ exit 1;
+}
+
+mkdir ($dir, 0700);
+
+unless (socket(SOCK, &AF_UNIX, &SOCK_STREAM, 0)) {
+ print STDERR "$Prog: socket: $!\n";
+ exit 1;
+}
+my $sun = sockaddr_un($sockname);
+unless (bind(SOCK, $sun)) {
+ print STDERR "$Prog: bind: $!\n";
+ exit 1;
+}
+
+chmod(0600, $sockname);
+
+listen(SOCK, 5);
+select(SOCK); $| = 1; select(STDOUT);
+
+$SIG{'ALRM'} = \&alarm_func;
+
+my $id = fork();
+if ($id < 0) {
+ print STDERR "$Prog: can not fork: $!\n";
+ exit 1;
+}
+
+if ($id) {
+ print STDERR "$Prog: started (pid: $id)\n";
+ exit 0;
+}
+
+for (;;) {
+ unless (accept(REQ, SOCK)) {
+ print STDERR "$Prog: accept: $!\n";
+ exit 1;
+ }
+ select(REQ); $| = 1; select(STDOUT);
+ alarm(3);
+ $_ = <REQ>;
+ alarm(0);
+ chomp;
+ if (/^PING$/) {
+ print REQ "PONG\n";
+ } elsif (/^CLEAR$/) {
+ undef %pwcache;
+ print REQ "CLEARED\n";
+ } elsif (/^SAVE\t(.*)/) {
+ my $param = $1;
+ alarm(3);
+ $_ = <REQ>;
+ alarm(0);
+ chomp;
+ if (/^PASS\t(.*)/) {
+ # encrypt ?
+ $pwcache{$param} = $1;
+ print REQ "OK\n";
+ } else {
+ print REQ "ERROR\n";
+ }
+ } elsif (/^LOAD\t(.*)/) {
+ my $param = $1;
+ my $pass = $pwcache{$param};
+ # decrypt ?
+ print REQ "PASS\t$pass\n";
+ } else {
+ # protocol error (including QUIT)
+ print REQ "BYE\n";
+ shutdown (REQ, 2);
+ close (REQ);
+ close (SOCK);
+ exit 1;
+ }
+ shutdown (REQ, 2);
+ close (REQ);
+}
+
+sub alarm_func {
+# no operation
+}
Mew-dist メーリングリストの案内