home *** CD-ROM | disk | FTP | other *** search
- // PGPJN.CPP
- // Runtime Loadable Encryptor Extension for Pegasus Mail for Windows.
- // Copyright (c) 1995, David Harris, All Rights Reserved.
- //
- // Pretty Good Privacy modifications by John Navas
- // Copyright (c) 1995, John Navas, All Rights Reserved.
- //
- // The author grants explicit permission for this source code to be
- // used or modified as required, subject only to the conditions that
- // the copyright notices above are preserved; that this source code
- // not be used in any product distributed in competition with this
- // product; that by using this code you agree that the code is
- // provided without warranty of any kind, either explicit or implied,
- // and you use it at your own risk.
- //
- // This module implements an interface to Pretty Good Privacy (tm)
- // and (c) Copyright 1990-1994 Philip Zimmermann. All rights reserved.
- //
- // The Massachusetts Institute of Technology is the distributor of PGP
- // version 2.6, for distribution in the USA only. It is available from
- // "net-dist.mit.edu," a controlled FTP site that has restrictions and
- // limitations, similar to those used by RSA Data Security, Inc., to comply
- // with export control requirements. The software resides in the directory
- // /pub/PGP.
-
- #include "pgpjn.h"
- #include "resource.h"
-
- #define VERSION (0x100) // version of WinPMail Forms I work with
-
- ///////////////////////////////////////////////////////////////////////////////
- // set in LibMain, used throughout the DLL
-
- HINSTANCE hLibInstance; // my instance
- HWND hwndParent = NULL; // handle of WinPMail parent window
- MODE MyMode = PUB; // my Form mode
- char MyDir[_MAX_DRIVE+_MAX_DIR]; // my directory
- char PGPpath[_MAX_PATH]; // PGP executable
- char* TEMP; // TEMP directory for PGPJNDOS
-
- char PGPEXE[_MAX_FNAME+_MAX_EXT]; // PGP executable
- char PGPJNDOS[_MAX_FNAME+_MAX_EXT]; // my special EXE
-
- char PGPBegin[MAXTAG]; // start of PGP encrypted section
- char PGPEnd[MAXTAG]; // end of PGP encrypted section
- char PGPBeginKey[MAXTAG]; // start of PGP public key
- char PGPEndKey[MAXTAG]; // end of PGP public key
-
- char SigGood[MAXTAG]; // PGP good sig message
- char SigBad[MAXTAG]; // PGP bad sig message
- char SigNoKey[MAXTAG]; // PGP missing key to verify sig
-
- char PGPBeginAdvise[MAXTAG]; // start of PGP public key
- char PGPEndAdvise[MAXTAG]; // end of PGP public key
-
- char PGPJNKey[128] = { '\0' }; // Master Key option
-
- ///////////////////////////////////////////////////////////////////////////////
-
- static BOOL Ctl3D = FALSE; // whether or not CTL3D registered
-
- ///////////////////////////////////////////////////////////////////////////////
-
- #ifdef _DEBUG
- void
- _cdecl
- MyDebugOutput(
- LPCSTR lpszFmt,
- ...
- )
- {
- char buf[256];
- va_list arg;
-
- va_start(arg, lpszFmt);
- wvsprintf(buf, lpszFmt, &va_arg(arg, int));
- OutputDebugString(buf);
- va_end(arg);
- }
- #endif // _DEBUG
-
- ///////////////////////////////////////////////////////////////////////////////
- // CHECK (SYSTEM) RESOURCES
-
- BOOL // FALSE if OK; TRUE if too low
- CheckResources()
- {
- // check system resources
- typedef struct {
- UINT type; UINT min;
- } RESOURCE;
- RESOURCE res[] = {
- { GFSR_SYSTEMRESOURCES, MINRES },
- { GFSR_GDIRESOURCES, MINRES },
- { GFSR_USERRESOURCES, MINRES }
- };
- for (int n = 0; n < sizeof(res)/sizeof(res[0]); ++n)
- if (GetFreeSystemResources(res[n].type) < res[n].min)
- return TRUE;
-
- // check heap space
- {
- void* ptr = malloc(16000);
-
- if (! ptr)
- return TRUE;
- free(ptr);
- }
-
- // check DOS memory
- {
- DWORD mem = GlobalDosAlloc(1024);
-
- if (! mem)
- return TRUE;
- GlobalDosFree((UINT) mem);
- }
-
- // made it!
- return FALSE;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // ADD FILENAME TO AN EXISTING PATH
-
- char* // complete pathname
- AddFileName(
- char* path, // directory path
- const char* file // filename to add
- )
- {
- char drive[_MAX_DRIVE];
- char dir[_MAX_DIR];
- char fname[_MAX_FNAME];
- char ext[_MAX_EXT];
-
- _splitpath(path, drive, dir, fname, ext); // check dir
-
- if (*fname) { // logic was fooled, thinks dir is file
- lstrcat(dir, fname); // fixup path
- lstrcat(dir, ext);
- }
-
- _splitpath(file, NULL, NULL, fname, ext); // get real file
-
- _makepath(path, drive, dir, fname, ext); // make pathname
-
- return path;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // FIND OUT IF PATH IS EXECUTABLE OR DIRECTORY
-
- static
- enum {OTHER, DIR, EXE}
- GetMode(const char* path)
- {
- struct _stat fil;
-
- if (_stat(path, &fil))
- return OTHER;
-
- if (fil.st_mode & _S_IFCHR)
- return OTHER;
-
- if (fil.st_mode & _S_IFREG)
- if (fil.st_mode & _S_IEXEC)
- return EXE;
-
- if (fil.st_mode & _S_IFDIR)
- return DIR;
-
- return OTHER;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
- // FIND PGP EXECUTABLE
-
- static
- char* // path of PGP exe or NULL if not found
- FindPGP(char* PGPpath) // store PGP path here
- {
- // first check PGPPATH environment variable
- char* path = getenv("PGPPATH"); // it's supposed to be here
-
- if (path) { // if PGPPATH set
- lstrcpy(PGPpath, path); // get it
-
- switch (GetMode(PGPpath)) { // and check it
- case EXE:
- return PGPpath; // EXE found
- case DIR:
- AddFileName(PGPpath, PGPEXE); // DIR found, so add filename
- if (GetMode(PGPpath) == EXE) // and check it again
- return PGPpath; // yes it was there
- }
- }
-
- // next see if saved in WIN.INI [programs]
- if (GetProfileString("[programs]", PGPEXE, "", PGPpath, _MAX_PATH)) {
- if (GetMode(PGPpath) == EXE)
- return PGPpath;
- }
-
- { // next, check to see if PGP extension registered
- char buf[_MAX_PATH + 4];
- LONG lbuf = sizeof(buf);
-
- if (RegQueryValue(HKEY_CLASSES_ROOT, ".PGP\\shell\\open\\command", buf, &lbuf)
- == ERROR_SUCCESS) {
- char* ptr = strchr(buf, ' '); // check for arguments
-
- if (ptr)
- *ptr = '\0'; // separate arguments
-
- lstrcpy(PGPpath, buf); // get execution command
-
- if (GetMode(PGPpath) == EXE) // and check it
- return PGPpath;
- }
- }
-
- // finally, search the path
- _searchenv(PGPEXE, "PATH", PGPpath);
- return *PGPpath ? PGPpath : NULL ;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
-
- // FORMINIT: Runtime Loadable Encryptors are simply a specialised form of
- // WinPMail Extension. As such, they must follow the standard rules for
- // such Extensions, including having an .FFF file to describe their char-
- // acteristics to the Extensions Manager, and a routine called FORMINIT
- // that is called when the module is loaded. For more information on
- // Extensions, examine the files WPMFORMS.TXT and WPMFORMS.TXT supplied in
- // the "FORMS" subdirectory of the WinPMail install directory. Note that
- // an encryptor module can use the entire family of Extension Manager
- // interface calls except those specific to READER Extensions.
- //
- // In short, FORMINIT must take the following form:
- //
- // WORD FAR PASCAL _export FORMINIT (WORD version, int variant, HWND hParent,
- // char *data, HWND *hDialog, char *callback_name);
- //
- // "version" is passed in with the version of the WinPMail forms
- // manager which is running.
- // "variant" indicates what type of form is required - the following
- // values are currently defined:
- // 0: Create a form for composing a message
- // 1: Create a form for reading a message
- // "hParent" contains the handle of the WinPMail MDI child window
- // which is to contain the form. For encryptor modules this window
- // will almost always be hidden.
- // "data" contains any string defined as being required for the
- // form in the menu interface.
- // "hDialog" should be filled in with the window handle of the
- // modeless dialog created within the MDI child window.
- // "callback_name" (optional) should be filled in with the name of the
- // function in the DLL of the exported function to which messages
- // should be sent or NULL if there is none. If NULL, messages are
- // sent to the dialog returned in "hDialog". You will use an
- // indirect callback of this kind when your extension does not
- // create a dialog within the enclosing parent window.
- //
- // When forminit is called, the DLL should register any window
- // classes it needs then create the dialog within the MDI parent
- // window and size it to the correct size. On return WinPMail will
- // resize the parent window to enclose the dialog correctly. The
- // DLL should NOT make the dialog visible - WinPMail will do that
- // as required.
-
- extern "C"
- WORD
- FAR PASCAL _export
- FORMINIT(
- WORD version,
- int variant,
- HWND hParent,
- char *data,
- HWND *hDialog,
- FORM_CALLBACK *callback
- )
- {
- char buf[128], *p; // used for parsing
- const char delim[] = " \t,;";
-
- #ifdef _DEBUG
- MyDebugOutput("FORMINIT called with data '%s'\n", data);
- #endif // _DEBUG
-
- // First, check to see if the version of the form manager is
- // one we can work with. This check is pretty arbitrary - you
- // should probably assume that you may not work with any version
- // where the major version number is higher than the original
- // version you targeted.
-
- if ((version & 0xFF00) > VERSION) {
- MessageBox(
- NULL, /* handle of parent window */
- "You need an updated version of the PGP interface"
- "to work with this version of WinPMail!", /* address of text in message box */
- "PGP Interface", /* address of title of message box */
- MB_ICONSTOP | MB_OK); /* style of message box */
- return 0;
- }
-
- hwndParent = hParent; // save parent window handle
- *hDialog = NULL; // i'm not going to use this
-
- // parse the data string
- lstrcpy(buf, data);
- for (p = strtok(buf, delim); p; p = strtok(NULL, delim)) {
- // set the mode switch; PUB is the default
- if (! lstrcmpi(p, "SIG"))
- MyMode = SIG;
- }
-
- return 1;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
-
- static
- BOOL // FALSE = failure; TRUE = OK
- InitInstance(
- HINSTANCE hInst
- )
- {
- char path[_MAX_PATH];
- char drive[_MAX_DRIVE];
- char dir[_MAX_DIR];
-
- // check system for adequate resources
- if (CheckResources()) {
- MessageBox(
- NULL, /* handle of parent window */
- "Insufficient memory or system resources!\r\n" /* address of text in message box */
- "(Close an application and try again.)",
- "PGP Interface", /* address of title of message box */
- MB_ICONSTOP | MB_OK); /* style of message box */
- return FALSE;
- }
-
- // register CTL3D if Windows 3.1x
- {
- WORD winver = LOWORD(GetVersion());
-
- if (3 == LOBYTE(winver) && HIBYTE(winver) >= 10 && HIBYTE(winver) < 95)
- if ((Ctl3D = Ctl3dRegister(hInst)))
- Ctl3dAutoSubclass(hInst);
- }
-
- // get my directory ('cause I have stuff stored there)
- GetModuleFileName(hInst, path, sizeof(path));
- _splitpath(path, drive, dir, NULL, NULL);
- _makepath(path, drive, dir, NULL, NULL);
- _fullpath(MyDir, path, sizeof(MyDir)); // get rid of trailing backslash
- // load my strings
- _makepath(path, drive, dir, "PGPJN", ".INI"); // for my strings
- typedef struct {
- char* tag; char* def; char* str; int len;
- } VINI;
- static const VINI vINI[] = {
- { "PGPEXE", "PGP.EXE", PGPEXE, sizeof(PGPEXE) },
- { "PGPJNDOS", "PGPJNDOS.EXE", PGPJNDOS, sizeof(PGPJNDOS) },
- { "BeginPGP", "-----BEGIN PGP MESSAGE", PGPBegin, sizeof(PGPBegin) },
- { "EndPGP", "-----END PGP MESSAGE", PGPEnd, sizeof(PGPEnd) },
- { "BeginPGPKey", "-----BEGIN PGP PUBLIC KEY BLOCK-----", PGPBeginKey, sizeof(PGPBeginKey) },
- { "EndPGPKey", "-----END PGP PUBLIC KEY BLOCK-----", PGPEndKey, sizeof(PGPEndKey) },
- { "GoodSig", "Good signature from", SigGood, sizeof(SigGood) },
- { "BadSig", "WARNING: Bad signature", SigBad, sizeof(SigBad) },
- { "NoKeySig", "WARNING: Can't find the right public key", SigNoKey, sizeof(SigNoKey) },
- { "BeginPGPAdvise", "-----BEGIN PGPJN SIGNATURE ADVISORY-----", PGPBeginAdvise, sizeof(PGPBeginAdvise) },
- { "EndPGPAdvise", "-----END PGPJN SIGNATURE ADVISORY-----", PGPEndAdvise, sizeof(PGPEndAdvise) }
- };
- for (int n = 0; n < sizeof(vINI)/sizeof(vINI[0]); ++n)
- GetPrivateProfileString("General",
- vINI[n].tag, vINI[n].def, vINI[n].str, vINI[n].len, path);
-
- // find the PGP executable
- if (! FindPGP(PGPpath)) {
- MessageBox(
- NULL, /* handle of parent window */
- "PGP executable not found!", /* address of text in message box */
- "PGP Interface", /* address of title of message box */
- MB_ICONSTOP | MB_OK); /* style of message box */
- return FALSE; // failure!
- }
-
- // save TEMP environment variable
- TEMP = getenv("TEMP");
- if (! TEMP || GetMode(TEMP) != DIR) {
- TEMP = getenv("TMP");
- if (! TEMP || GetMode(TEMP) != DIR) {
- MessageBox(
- NULL, /* handle of parent window */
- "TEMP environment variable not set properly!", /* address of text in message box */
- "PGP Interface", /* address of title of message box */
- MB_ICONSTOP | MB_OK); /* style of message box */
- return FALSE; // failure!
- }
- }
-
- // get PGPJNKEY option if set
- {
- char* key = getenv("PGPJNKEY");
-
- if (key) {
- lstrcpyn(PGPJNKey, key, sizeof(PGPJNKey) - 3);
- FrameIt(PGPJNKey);
- }
- }
-
- return TRUE; // success
- }
-
- ///////////////////////////////////////////////////////////////////////////////
-
- extern "C"
- BOOL
- FAR PASCAL
- LibMain(
- HINSTANCE hInst,
- WORD wDataSeg,
- WORD cbHeapSize,
- LPSTR lpszCmdLine
- )
- {
- #ifdef _DEBUG
- MyDebugOutput("LIBMAIN called with args '%s'\n", lpszCmdLine);
- #endif // _DEBUG
-
- // This particular encryptor has no user interface as such
- // so we don't have to register any window classes or anything.
-
- // unlock my data segment
- if (cbHeapSize > 0)
- UnlockData(0);
-
- // initialize my instance
- if (! hLibInstance)
- if (InitInstance(hInst))
- hLibInstance = hInst;
- else
- return FALSE; // initialization failed
-
- return TRUE; // Initialization went OK
- }
-
- ///////////////////////////////////////////////////////////////////////////////
-
- extern "C"
- int
- FAR PASCAL
- _WEP(int val)
- {
- /* Your WEP functionality goes here */
- if (Ctl3D)
- Ctl3dUnregister(hLibInstance);
-
- return 1;
- }
-
- ///////////////////////////////////////////////////////////////////////////////
-
- // PGPJN.CPP
-