home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC-Online 1998 February
/
PCOnline_02_1998.iso
/
filesbbs
/
win3x
/
pgpjn.exe
/
JNSOURCE.ZIP
/
PGPJN.CPP
< prev
next >
Wrap
C/C++ Source or Header
|
1995-12-11
|
15KB
|
467 lines
// 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