Возникла у меня тут необходимость запускать gpg в пакетном режиме, без взаимодействия с пользователем. Точнее, пользователь должен один раз ввести пароль от ключа, и больше не вмешиваться.
Нашел модуль GnuPG, но оказалось, что он полагается на shared memory, а в нынешнем gpg2 эта фича не поддерживается. Теперь надо а gpg все дополнительные данные скармливать через файловые дескрипторы. Пробую запустить из комнадной строки:
/usr/bin/gpg --decrypt --batch --passphrase-fd 3 encrypted.file 3<password.file
Работает. Ну ладно, будем запускать то же самое из перла, только без файла, а напрямую скармливая пароль через пайп.
В целом вроде бы тоже работает, gpg запускается, зашифрованный файл находит, даже показывает, каким ключом он зашифрован, но… расшифровать не может, поскольку не видит пароля:
can't connect to `/home/dil/.gnupg/S.gpg-agent': No such file or directory
gpg: encrypted with 2048-bit RSA key, ID 673056FF, created 2012-02-17
"юзер <почтовый адрес>"
gpg: public key decryption failed: Bad passphrase
gpg: decryption failed: No secret key
Пробую напечатать пароль непосредственно в перле из дочернего процесса, прочитав его из пайпа. Нормально читается и печатается. А gpg из того же пайпа этот пароль в упор не видит.
Вопрос для продвинутых программистов и сисадминов: где засада?
Подсказка: проблема решилась после добавления в скрипт пары строчек. Угадайте, каких.
Исходник на перле под катом.
#!/usr/bin/perl -w
my ($pwread, $pwwrite);
pipe($pwread, $pwwrite);
my $dataread;
my $pid = open $dataread, "-|";
die "Cannot fork: $!\n" unless defined($pid); # fork error
if($pid) { # parent process
close($pwread);
print $pwwrite 'password';
close($pwwrite);
$DATA = <$dataread>;
unless(defined($DATA) && length($DATA) > 0) {
die "Failed to read data\n";
}
chomp $DATA;
print "data='$DATA'\n";
close($dataread);
waitpid($pid, 0);
exit 0;
}
# child
close($pwwrite);
my $pwfd = fileno($pwread); # узнаём номер файлового дескриптора
print STDERR "pwfd=$pwfd\n";
# my $d = <$pwread>; # вот если читать пароль тут, то он нормально читается
# print STDERR "d='$d'\n"; # и пишется
# print STDOUT "some fake data here\n"; # потом можно подсунуть родительскому процессу данные, якобы от расшифрованного файла, и он их тоже нормально получает
# exit 0;
# а вот если запустить gpg, то пароль из указанного дексриптора почему-то не виден
exec('/usr/bin/gpg',
'--decrypt',
'--batch',
'--passphrase-fd', $pwfd,
'encrypted.file',
) or die "Cannot exec gpg: $!\n";
exit 0; # child exits anyhow;
Оригинал этой записи в личном блоге.
Любые материалы из этого блога запрещается использовать на сайте livejournal.ru в любой форме и любом объёме.
no subject