############################################################################## # # Jarl - GPG Access Functions # Perl code to handle GPG calls that Jarl needs to message encrypted style. # ############################################################################## ############################################################################## # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # Jabber # Copyright (C) 1998-1999 The Jabber Team http://jabber.org/ # ############################################################################## use IO::Handle; use GnuPG::Interface; use IPC::Open3; $SIG{CHLD} = 'IGNORE'; ############################################################################## # # jarlGPG_SignStatus - generate the CDATA for the jabber:x:signed presence # ############################################################################## sub jarlGPG_SignStatus { my $passphrase = shift; my $status = shift; $Debug->Log1("jarlGPG_SignStatus: status($status)\n"); my $gnupg = GnuPG::Interface->new(); my $stdin = IO::Handle->new(); my $stdout = IO::Handle->new(); my $stderr = IO::Handle->new(); my $handles = GnuPG::Handles->new(stdin=>$stdin, stdout=>$stdout, stderr=>$stderr, ); $gnupg->options->meta_interactive(0); $gnupg->options->hash_init(armor=>1); $gnupg->passphrase($passphrase); $gnupg->clearsign(handles=>$handles); print $stdin "$status\n"; close($stdin); my $body; while(($_ = <$stdout>) && !(/^-----BEGIN PGP SIGNATURE/)) { } while(($_ = <$stdout>) && ($_ ne "\n")) { } while(($_ = <$stdout>) && !(/^-----\S+ PGP/)) { $body .= $_; } close($stdout); close($stderr); chomp($body); $Debug->Log1("jarlGPG_SignStatus: body($body)\n"); return $body; } ############################################################################## # # jarlGPG_GetKeyID - extract the key id from CDATA of a signed presence # ############################################################################## sub jarlGPG_GetKeyID { my $status = shift; my $sig = shift; $Debug->Log1("jarlGPG_GetKeyID: status($status) sig($sig)\n"); my $sigHeader1 = "-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 "; my $sigHeader2 = " -----BEGIN PGP SIGNATURE----- Version: Jarl "; my $sigFooter = " -----END PGP SIGNATURE----- "; my $gnupg = GnuPG::Interface->new(); my $stdin = IO::Handle->new(); my $stdout = IO::Handle->new(); my $stderr = IO::Handle->new(); my $handles = GnuPG::Handles->new( stdin => $stdin, stdout => $stdout, stderr => $stderr ); $gnupg->options->meta_interactive(0); $gnupg->verify(handles=>$handles); print $stdin $sigHeader1,$status,$sigHeader2,$sig,$sigFooter,"\n"; close($stdin); my $key = ""; foreach my $line (<$stderr>) { ($key) = ($line =~ /.*Signature made.*using.*key ID (\S+)/); last if ($key ne ""); } close($stderr); close($stdout); $Debug->Log1("jarlGPG_GetKeyID: key($key)\n"); return $key; } ############################################################################## # # jarlGPG_DecryptMessage - get the body data from the encrypted message # ############################################################################## sub jarlGPG_DecryptMessage { my $passphrase = shift; my $message = shift; $Debug->Log1("jarlGPG_DecryptMessage: message($message)\n"); my $messageHeader = "-----BEGIN PGP MESSAGE----- "; my $messageFooter = "-----END PGP MESSAGE----- "; my $gnupg = GnuPG::Interface->new(); my $stdin = IO::Handle->new(); my $stdout = IO::Handle->new(); my $stderr = IO::Handle->new(); my $handles = GnuPG::Handles->new(stdin=>$stdin, stdout=>$stdout, stderr=>$stderr, ); $gnupg->options->meta_interactive(0); $gnupg->passphrase($passphrase); $gnupg->decrypt(handles=>$handles); print $stdin $messageHeader,$message,$messageFooter,"\n"; close($stdin); my @decrypted = <$stdout>; my $signed = 0; foreach my $line (@decrypted) { $signed = 1 if ($line =~ /^-----BEGIN PGP/); } my $body; if ($signed == 1) { my $seenStart = 0; my $seenBody = 0; foreach my $line (@decrypted) { next if (($seenStart == 0) && !($line =~ /^-----BEGIN PGP/)); if ($seenStart == 0) { $seenStart = 1; next; } next if (($seenBody == 0) && ($line ne "\n")); if ($seenBody == 0) { $seenBody = 1; next; } last if ($line =~ /^-----\S+ PGP/); $body .= $line; } } else { foreach my $line (@decrypted) { $body .= $line; } } close($stdout); close($stderr); chomp($body); $Debug->Log1("jarlGPG_DecryptMessage: body($body)\n"); return $body; } ############################################################################## # # jarlGPG_EncryptMessage - generate the GPG version of the data # ############################################################################## sub jarlGPG_EncryptMessage { my $passphrase = shift; my $recipient = shift; my $body = shift; $Debug->Log1("jarlGPG_EncryptMessage: recipient($recipient) body($body)\n"); my $gnupg = GnuPG::Interface->new(); my $stdin = IO::Handle->new(); my $stdout = IO::Handle->new(); my $stderr = IO::Handle->new(); my $handles = GnuPG::Handles->new(stdin=>$stdin, stdout=>$stdout, stderr=>$stderr, ); $gnupg->options->meta_interactive(0); $gnupg->options->hash_init(armor=>1, recipients=>[ $recipient ] ); $gnupg->passphrase($passphrase); $gnupg->clearsign(handles=>$handles); print $stdin "$body"; close($stdin); my @signed = <$stdout>; close($stdout); close($stderr); $gnupg = GnuPG::Interface->new(); $stdin = IO::Handle->new(); $stdout = IO::Handle->new(); $stderr = IO::Handle->new(); $handles = GnuPG::Handles->new(stdin=>$stdin, stdout=>$stdout, stderr=>$stderr, ); $gnupg->options->meta_interactive(0); $gnupg->options->hash_init(armor=>1, recipients=>[ $recipient ] ); $gnupg->encrypt(handles=>$handles); print $stdin @signed; close($stdin); my $newBody; while(($_ = <$stdout>) && !(/^-----BEGIN PGP/)) { } while(($_ = <$stdout>) && ($_ ne "\n")) { } while(($_ = <$stdout>) && !(/^-----\S+ PGP/)) { $newBody .= $_; } close($stdout); close($stderr); $Debug->Log1("jarlGPG_EncryptMessage: output($newBody)\n"); return $newBody; } ############################################################################## # # jarlGPG_CheckKeyRing - check if the specified user is in your pub key ring. # ############################################################################## sub jarlGPG_CheckKeyRing { my $keyid = shift; $Debug->Log1("jarlGPG_CheckKeyRing: keyid($keyid)\n"); my $gnupg = GnuPG::Interface->new(); my $stdin = IO::Handle->new(); my $stdout = IO::Handle->new(); my $stderr = IO::Handle->new(); my $handles = GnuPG::Handles->new(stdin=>$stdin, stdout=>$stdout, stderr=>$stderr, ); $gnupg->options->meta_interactive(0); $gnupg->list_public_keys(handles=>$handles); my @keys = <$stdout>; $Debug->Log1("jarlGPG_CheckKeyRing: keys(@keys)\n"); close($stdin); close($stdout); close($stderr); my $haveKey = 0; foreach my $key (@keys) { $haveKey = 1 if ($key =~ /$keyid/); } $Debug->Log1("jarlGPG_CheckKeyRing: in public ring($haveKey)\n"); $haveKey = &jarlGPG_KeyTrusted($keyid) if ($haveKey == 1); $Debug->Log1("jarlGPG_CheckKeyRing: trusted($haveKey)\n"); return $haveKey; } ############################################################################## # # jarlGPG_TestPassphrase - test that the specified passphrase works # ############################################################################## sub jarlGPG_TestPassphrase { my $passphrase = shift; my $gnupg = GnuPG::Interface->new(); $gnupg->options->meta_interactive(0); $gnupg->passphrase($passphrase); my $test = $gnupg->test_default_key_passphrase(); $Debug->Log1("jarlGPG_TestPassphrase: pass($test)\n"); return $test; } ############################################################################## # # jarlGPG_KeyTrusted - is the key trusted? # ############################################################################## sub jarlGPG_KeyTrusted { my $key = shift; $Debug->Log1("jarlGPG_KeyTrusted: key($key)\n"); my $gnupg = GnuPG::Interface->new(); $gnupg->options->meta_interactive(0); my @keys = $gnupg->get_public_keys($key); if ($#keys == -1) { $Debug->Log1("jarlGPG_KeyTrusted: no key\n"); return 0; } my $trust = $keys[0]->owner_trust(); if (($trust eq "m") || ($trust eq "f") || ($trust eq "u")) { $Debug->Log1("jarlGPG_KeyTrusted: we trust them\n"); return 1; } $Debug->Log1("jarlGPG_KeyTrusted: they can't even hold the door open for me....\n"); return 0; } ############################################################################## # # jarlGPG_FetchAndTrustKey - fetch and trust the key # ############################################################################## sub jarlGPG_FetchAndTrustKey { my $key = shift; $Debug->Log1("jarlGPG_FetchAndTrustKey: key($key)\n"); $Debug->Log1("jarlGPG_FetchAndTrustKey: fetch\n"); open3(STDIN,STDOUT,"","gpg --keyserver $config{gpg}->{keyserver} --recv-key $key"); close(STDIN); close(STDOUT); $Debug->Log1("jarlGPG_FetchAndTrustKey: trust\n"); open3(STDIN,STDOUT,"","gpg --command-fd 0 --edit-key $key"); print STDIN "trust\n"; print STDIN "$config{gpg}->{trust}\n"; print STDIN "quit\n"; close(STDIN); close(STDOUT); $Debug->Log1("jarlGPG_FetchAndTrustKey: done\n"); } 1;