November 2019

S M T W T F S
      12
34 5 678 9
10111213141516
17181920212223
24252627282930

Page Summary

Style Credit

Expand Cut Tags

No cut tags
Saturday, March 3rd, 2012 03:29 pm

Возникла у меня тут необходимость запускать 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 в любой форме и любом объёме.

Saturday, March 3rd, 2012 08:35 pm (UTC)
Разминание иногда размягчает.