# zcrypt.pl $Id: zcrypt.pl,v 1.11 2002/10/05 07:42:28 jdaniel Exp $
#
# To use zcrypt.pl I suggest copying this file to someplace in your
# homedir.  Then you must make the following additions to your
# .owlconf file.  If you don't have a .owlconf I suggest starting with
# the one in yourmit/ktools/src/owl/configs/owlconf.testing

# Add these lines to load zcrypt.pl, filling in HOMEDIR and PATH as 
# appropriate:
# BEGIN {
#     use lib '/mit/HOMEDIR/PATH';
#     require 'zcrypt.pl';        # send and recieve zcrypt messages
# }

# Place the following lines at the beginning of the format sub:
# sub owl::format_msg() {
#     my $zcrypt = zcrypt_recieve(\$owl::msg, $owl::opcode,
#                                 $owl::class, $owl::instance);
#     return $zcrypt if $zcrypt;

# Also add this line to the startup sub to load the zcrypt alias 
# (only available in owl 1.2 currently owl-beta):
# sub owl::startup {
#     zcrypt_init();				# load zcrypt functionality

# ADDITIONAL NOTE FOR ATHENA 9.1 USERS: Until kretch stops compiling
# on 9.0 you'll have to tell perl an alternate version of where it's
# normal libraries are.  To do this: 
# attach perl5 
# setenv PERLLIB `/mit/perl5/perl -e 'print join ":",@INC'`

# After that you can use zcrypt like you use zwrite.  
#     :zcrypt -c class -i instance
# C-x z will start a zcrypt command, be aware that when replying you
# still have to call zcrypt manually.

# zcrypt.pl works by sending the (not yet encrypted) message to
# yourself (with the same class, instance pair you specified) and then
# on recieving it, sending out the encrypted version to the class.
# This method exposes the key to a greater risk of being cracked since
# for each message both encrypted and decrypted versions are
# obtainable by sniffing the network.  This version uses features in
# owl 1.2 which is still in beta (add ktools; owl-beta).  Any bugs,
# comments, or suggestions email jdaniel@mit.edu

use IPC::Open2;

# get the decrypted version of a message
sub zcrypt_decode ($$) {
    my ($emsg, $class) = @_;
    my $pid = open2(\*RDRFH, \*WTRFH, "zcrypt -D -c $class");
    print WTRFH $emsg;
    close WTRFH;
    my $dmsg = "";
    my $end = "**END**\n";
    while (<RDRFH>) {
        last if $_ eq $end;
        $dmsg .= $_;
    }
    close RDRFH;
    return $dmsg;
}

# get the encrypted version of the message
sub zcrypt_encode ($$) {
    my ($dmsg, $class) = @_;
    
    my $pid = open2(\*RDRFH, \*WTRFH, "zcrypt -E -c $class");
    print WTRFH $dmsg;
    close WTRFH;
    my $emsg = <RDRFH>;
    return $emsg;
}

# encrypt and send a message
sub zcrypt_send ($$$) {
    my ($dmsg, $class, $inst) = @_;
    my $emsg = zcrypt_encode $dmsg, $class;
    my $command = "zwrite -O crypt -c '$class' -i '$inst'";
    owl::send_zwrite($command, $emsg);
}

# call from owl::format_msg() to encrypt or decrypt a incoming message
# or to do nothing depending on the message.  The first argument is a
# pointer to the message so that it can be replaced with the decrypted
# text when appropriate.  returns 0 for normal messages and ones it
# has decrypted, returns a message otherwise.
sub zcrypt_recieve ($$$$) {
    my ($pmsg, $opcode, $class, $inst) = @_;
    if ($opcode eq "crypt") {
        # encrypted message to decode
        $$pmsg = zcrypt_decode $$pmsg, $class;
        return 0;
    } elsif ($opcode eq "encrypt") {
        # message to decrypt
        zcrypt_send $$pmsg, $class, $inst;
        return "Encrypted message sent";
    } else {
        return 0;
    }
}

# call from owl::startup() to initialize the command alias for zcrypt
# and subscribe to the personal instances of the classes that zcrypt
# is to be used for.  Uses any classes specified in the arguments in
# addition to ones in the user's ~/.crypt_table file
sub zcrypt_init (@) {
    my @classes = @_;
    owl::command('alias zcrypt zwrite '.$ENV{USER}.' -O encrypt');
    owl::command('bindkey recv "C-x z" command start-command zcrypt ');
    open CRYPT_TABLE, "<$ENV{HOME}/.crypt-table";
    while (<CRYPT_TABLE>) {
        my ($class) = m/^crypt-(.*?):/;
        push @classes, $class;
    }
    close CRYPT_TABLE;
    for my $class (@classes) {
	# the -t option was added in 1.2.6 drop it for earlier
        owl::command("subscribe -t $class * %me%");
    }
    return "zcrypt inited";
}

1;
