     --------------------------------------------------------------
     Runtime-loadable encryptor/decryptor modules for Pegasus Mail.

                         Pegasus Mail System, 
        Copyright (c) 1990-95, David Harris, All Rights Reserved
     --------------------------------------------------------------

The hot topic on everyone's lips is "privacy". And, as usual, the
computer industry is in the process of confusing and disrupting the issue
beyond recognition... We have factions all over the place each arguing
passionately for its own most beloved encryption scheme, and some of the
rhetoric is getting pretty heated.

Add to the proliferation of interests the USA's ridiculous export laws on
encryptors and the sum is trouble. As far as I can tell, encryption is
going through what seems to be an industry-standard cycle of chaos:
everyone suddenly realises there's a lack/opportunity/need and rushes to
promote the idea they like best; a small war develops during which the
users and peripheral developers are left bemused and bewildered amongst
the welter of extravagant claims and counter-claims, then eventually
(usually after two or three years of total pandemonium) the group with
the most clout (although not necessarily the best product) will win out
and become "the standard".

I've been through this rat race several times and have no desire whatever 
to go through it again; on the other hand, my USERS have very legitimate 
concerns about privacy. So what do I do? Easy - I pass the buck.

WinPMail v2.2 and later supports third-party, runtime loadable modules
to handle encryption and decryption of mail. A special mechanism will be
defined which will allow Pegasus Mail to detect that a third party
encryptor has been used and to determine whether the matching decryptor
is available on the system. The built-in encryptor will remain available
for those sites who only need moderate levels of message security.
WinPMail will define an open interface for third-party encryptors and it
is then up to other people to write the code. What I envisage actually
happening is people writing "shell interfaces" for WinPMail - i.e.,
modules which take the calls I make and translate them into calls to
other programs, such as PGP or whatever, returning the result.

I have gone to considerable lengths to find a balance between simplicity
and functionality in designing this interface: an encryptor module can be
implemented with as few as three exported functions, yet has support for
greater functionality as required. The primary features I wanted to be
able to support were encryption/decryption and both the generation and
validation of digital signatures.

The interface is a variant of WinPMail 2.0's Extension Manager Interface:
each encryptor/decryptor will be implemented as a DLL exporting the 
following functions by name:

   int FAR PASCAL encrypt_file (char *sourcefile, 
      char *destfile, char *recipient, char *key, int textfile);
      //  Encrypt the contents of a file: if "textfile" is non-zero,
      //  then the file may contain 8-bit data, but will have normal
      //  text file CR/LF line endings. If "textfile" is zero, the
      //  encryptor routine should presume that the file has unknown
      //  or explicitly binary contents. "recipient" contains the
      //  address of the person to whom this message is being sent.
      //  "key" contains whatever key the user entered, or may be
      //  NULL if the encryptor's FFF flags indicate that it does
      //  not require a key.
      //
      //  On entry, the source file will exist, the destination file
      //  will not: the encryptor should create the destination file
      //  file and place the ciphertext version of the plaintext file
      //  file in it in a format ready for transmission. The module
      //  should NOT delete the plaintext file.
      //
      //  Returns:  1 if the file was successfully encrypted.
      //            2 if the file was successfully encrypted but
      //              may contain 8-bit data and should be sent
      //              encoded using BASE64.
      //            0 on failure.

   int FAR PASCAL decrypt_file (char *sourcefile, char *destfile,
      char *key);
      //  Decrypt a message into a format suitable to be displayed in
      //  a message reader. "sourcefile" contains an image of the message
      //  (not the actual message itself) complete with all header
      //  information intact. The destination file will not exist and
      //  should be created by the decryptor.
      //
      //  This routine should return 2 if the message data cannot be
      //  displayed as text (ie, is binary).
      //       
      //  Returns:  1 if the file was successfully decrypted
      //            2 if the file was decrypted but is non-textual
      //            0 on password or system failure
      //
      //  IMPORTANT NOTE: For encrypted components of MIME multipart
      //  messages, only the encrypted component from the message will
      //  be passed to the encryptor, along with the headers from the
      //  message proper.


Encryptor modules may also export the following optional functions:

   int FAR PASCAL sign_file (char *sourcefile, char *destfile,
      char *recipient, char *key, int encrypt_as_well);
      //  Compute and attach a digital signature to the message passed
      //  in "sourcefile". The message should be rewritten with the 
      //  signature attached in the proper place in "destfile", which
      //  will not exist on entry. "Sourcefile" will contain the body
      //  of the message to sign, but will NOT contain the message
      //  headers. If "encrypt_as_well" is non-zero, the file should
      //  be both encrypted and signed, using whatever method is
      //  appropriate.
      //
      //  Returns:  1 if the message was successfully processed
      //            2 if the file was successfully processed but
      //              may contain 8-bit data and should be sent
      //              encoded using BASE64.
      //            0 if an error occurred during processing
      //           -1 if the operation is not supported

   int FAR PASCAL verify_signature (char *sourcefile, char *text);
      //  Attempt to verify the digital signature (if any) associated
      //  with the message passed in "sourcefile", which contains a
      //  complete image of the message including headers. This
      //  routine should not assume that the message actually has
      //  a digital signature, and should be ready to deal with the
      //  situation where none is present.
      //
      //  The "text" parameter points to a string at most 160 chars
      //  long into which the verify routine can write any descriptive
      //  text about a valid signature that should be reported to 
      //  the user.
      //
      //  Returns:  1 if the digital signature was valid
      //            0 if the digital signature was invalid
      //           -1 if no digital signature could be found
      //           -2 if the operation is not supported

   int FAR PASCAL destroy_file (char *sourcefile);
      //  If this function is exported, WinPMail will call it when it
      //  has finished with a temporary files created in the process
      //  of encryption or decryption. It is up to the module what it
      //  does with the file, although the expectation is that it will
      //  zero the contents and delete it.
      //
      //  Note that if this function is not exported, WinPMail will
      //  destroy the file by writing 0s into every byte then
      //  deleting it.
      //
      //  Returns:  1 if the file was destroyed
      //            0 if the file was not destroyed (in which
      //              case WinPMail will delete it as described).

   int FAR PASCAL key_management (char *sourcefile);
      //  This is the only function in this API which actually
      //  specifically requires that the encryptor module provide
      //  a user interface. The expectation is that it will open a
      //  modal dialog offering a few simple key management choices
      //  for the user. If "sourcefile" is non-null, it will point
      //  to a filename which contains the image of a message selected
      //  by the user (possibly for extraction of a public key
      //  fingerprint, or something similar).


Important considerations:

* Blocking: If an encryptor module has to call another process to perform
its function, then it is the encryptor's duty to ensure that control does
not return to WinPMail before the process is complete - in other words,
WinPMail regards encryptor actions as atomic.

* Line termination: Internet mail uses CR/LF line endings, and Pegasus
Mail enforces this scheme. While in transit, line endings in a message may
be disturbed, and if a message originally contained a line ending scheme
that is illegal in Internet terms (such as the unix LF-only termination),
then the line endings may be arbitrarily altered to conform with Internet
standards in transit. If the position or nature of line termination is
significant to an encryption module, it should ensure that the encrypted
data is "armoured" for transit as part of the encryption process; some
encryptors, such as PGP, support this idea already, but if this is not
the case with your encryptor, you will have to return the value 2 to
WinPMail to have it armour your data using MIME BASE64 encoding.


Interface:

Runtime loadable encryptors are implemented as a variant of the WinPMail
Extension model. They should be implemented as a standard extension that
exports the extra functions described above. Encryptors have access to
the full Extension Manager API set except for those functions specific to
READER extensions. Just as with regular extensions, Pegasus Mail learns
about encryptors via Form Fact Files (FFF files); it uses the "Form
Triggers" keyword in the .FFF file as a regular expression describing
some identifying characteristic of a message that the encryptor module
can handle. The regular expression is applied to the headers, and to the
message body for the number of lines specified in the "# of lines to
probe for enclosures" setting of the Advanced Settings preferences
dialog.

All Pegasus Mail Extensions support a "tagname" - an identifying mark
that is written into an "X-Tagname:" field in messages generated by
the extension. For encryptor extensions the tagname field is
particularly important, since it will usually be the basis for
detecting that a particular encryptor has been used to perturb the
message. Developers of encryptor extensions are urged in the
strongest possible terms to register their tagnames with the author
following the guidelines in WPMFORMS.TXT, the Extension Manager
reference found in the FORMS\ subdirectory of a standard WinPMail
2.x installation.

