/*
* ratPGPprog.c --
*
* This file contains compatibility functions.
*
* TkRat software and its included text is Copyright 1996-2002 by
* Martin Forssén
*
* The full text of the legal notice is contained in the file called
* COPYRIGHT, included with this distribution.
*/
#include "ratFolder.h"
#include "ratPGP.h"
/*
* Maximaum length of pass phrase (plus two)
*/
#define MAXPASSLENGTH 1024
/*
* Cached pass phrase
*/
static char pgpPass[MAXPASSLENGTH];
static int pgpPassValid = 0;
static Tcl_TimerToken pgpPassToken;
/*
*----------------------------------------------------------------------
*
* ClearPGPPass --
*
* Clear the pgp pass phrase
*
* Results:
* None.
*
* Side effects:
* The pass phrase is cleared.
*
*
*----------------------------------------------------------------------
*/
void
ClearPGPPass(ClientData unused)
{
memset(pgpPass, '\0', sizeof(pgpPass));
pgpPassValid = 0;
}
/*
*----------------------------------------------------------------------
*
* RatPGPPhrase --
*
* Get the pass phrase.
*
* Results:
* A pointer to a buffer containing the pass phrase or NULL if the
* user aborted the operation.
*
* Side effects:
* It is the callers responsibility to free this buffer.
*
*----------------------------------------------------------------------
*/
char*
RatPGPPhrase(Tcl_Interp *interp)
{
char buf[32], *result;
int doCache, timeout, objc;
Tcl_Obj *oPtr, **objv;
oPtr = Tcl_GetVar2Ex(interp, "option","cache_pgp_timeout",TCL_GLOBAL_ONLY);
Tcl_GetIntFromObj(interp, oPtr, &timeout);
if (pgpPassValid) {
Tcl_DeleteTimerHandler(pgpPassToken);
if (timeout) {
pgpPassToken = Tcl_CreateTimerHandler(timeout*1000, ClearPGPPass,
NULL);
}
return cpystr(pgpPass);
}
strlcpy(buf, "RatGetPGPPassPhrase", sizeof(buf));
Tcl_Eval(interp, buf);
oPtr = Tcl_GetObjResult(interp);
Tcl_ListObjGetElements(interp, oPtr, &objc, &objv);
if (!strcmp("ok", Tcl_GetString(objv[0]))) {
oPtr = Tcl_GetVar2Ex(interp, "option", "cache_pgp", TCL_GLOBAL_ONLY);
Tcl_GetBooleanFromObj(interp, oPtr, &doCache);
if (doCache) {
strlcpy(pgpPass, Tcl_GetString(objv[1]), sizeof(pgpPass));
pgpPassValid = 1;
if (timeout) {
pgpPassToken = Tcl_CreateTimerHandler(timeout*1000,
ClearPGPPass, NULL);
} else {
pgpPassToken = NULL;
}
}
result = cpystr(Tcl_GetString(objv[1]));
return result;
} else {
return NULL;
}
}
/*
*----------------------------------------------------------------------
*
* RatSenderPGPPhrase --
*
* Get the pass phrase. This function may only be called from the
* sender process.
*
* Results:
* A pointer to a static buffer containing the pass phrase. It is up to
* the caller to overwrite this buffer with nulls.
*
* Side effects:
* None.
*
*
*----------------------------------------------------------------------
*/
char*
RatSenderPGPPhrase(Tcl_Interp *interp)
{
static CONST84 char **argv = NULL;
int argc;
char *result = RatSendPGPCommand("PGP getpass");
if (!strncmp("PHRASE ", result, 7)) {
ckfree(argv);
Tcl_SplitList(interp, result, &argc, &argv);
memset(result, '\0', strlen(result));
return (char*)argv[1];
} else {
return NULL;
}
}
/*
*----------------------------------------------------------------------
*
* RatPGPBodyCheck --
*
* Checks if the given bodypart is either signed or encoded with
* pgp. Parts of the bodypart signature are then initialized.
*
* Results:
* None.
*
* Side effects:
* The passed BodyInfo structure is modified.
*
*
*----------------------------------------------------------------------
*/
void
RatPGPBodyCheck(Tcl_Interp *interp, MessageProcInfo *procInfo,
BodyInfo **bodyInfoPtrPtr)
{
PARAMETER *parPtr;
int prot, enc;
unsigned long length;
char *text, *start, *end, *middle;
const char *version;
version = Tcl_GetVar2(interp, "option", "pgp_version", TCL_GLOBAL_ONLY);
if (!version || !strcmp("0", version)) {
return;
}
/*
* Check for PGP/MIME messages
*/
(*bodyInfoPtrPtr)->sigStatus = RAT_UNSIGNED;
if ((*bodyInfoPtrPtr)->bodyPtr->type == TYPEMULTIPART
&& !strcasecmp("encrypted", (*bodyInfoPtrPtr)->bodyPtr->subtype)) {
enc = 0;
for (parPtr = (*bodyInfoPtrPtr)->bodyPtr->parameter; parPtr;
parPtr = parPtr->next) {
if (!strcasecmp(parPtr->attribute, "protocol")
&& !strcasecmp(parPtr->value,"application/pgp-encrypted")){
enc = 1;
break;
}
}
if (enc) {
RatPGPDecrypt(interp, procInfo, bodyInfoPtrPtr);
(*bodyInfoPtrPtr)->encoded = 1;
}
} else if ((*bodyInfoPtrPtr)->bodyPtr->type == TYPEMULTIPART
&& !strcasecmp("signed", (*bodyInfoPtrPtr)->bodyPtr->subtype)) {
prot = 0;
for (parPtr = (*bodyInfoPtrPtr)->bodyPtr->parameter; parPtr;
parPtr = parPtr->next) {
if (!strcasecmp(parPtr->attribute, "protocol")
&& !strcasecmp(parPtr->value,"application/pgp-signature")){
prot = 1;
}
}
if (prot) {
BodyInfo *bodyInfoPtr;
(*procInfo[(*bodyInfoPtrPtr)->type].makeChildrenProc)(interp,
*bodyInfoPtrPtr);
bodyInfoPtr = *bodyInfoPtrPtr;
*bodyInfoPtrPtr = (*bodyInfoPtrPtr)->firstbornPtr;
(*bodyInfoPtrPtr)->sigStatus = RAT_UNCHECKED;
(*bodyInfoPtrPtr)->secPtr = bodyInfoPtr;
}
} else if ((*bodyInfoPtrPtr)->bodyPtr->type == TYPETEXT
|| ((*bodyInfoPtrPtr)->bodyPtr->type == TYPEAPPLICATION
&& !strcasecmp("pgp", (*bodyInfoPtrPtr)->bodyPtr->subtype))) {
text = (*procInfo[(*bodyInfoPtrPtr)->type].fetchBodyProc)
(*bodyInfoPtrPtr, &length);
if (text && (((start = RatPGPStrFind(text,length,"BEGIN PGP SIGNED",1))
&& (middle = RatPGPStrFind(start, length - (start-text),
"BEGIN PGP SIGNATURE",1))
&& (end = RatPGPStrFind(middle, length - (middle-text),
"END PGP",1)))
|| ((start = RatPGPStrFind(text, length,"BEGIN PGP MESSAGE",1))
&& (end = RatPGPStrFind(start, length - (start-text),
"END PGP",1))))) {
RatPGPHandleOld(interp, *bodyInfoPtrPtr, text, start, end+1);
}
}
}
/*
*----------------------------------------------------------------------
*
* RatPGPCmd --
*
* Handle ratPGP command.
*
* Results:
* A standard tcl result.
*
* Side effects:
* Depends on the arguments
*
*----------------------------------------------------------------------
*/
int
RatPGPCmd(ClientData clientData, Tcl_Interp *interp, int objc,
Tcl_Obj *const objv[])
{
if (objc < 2) goto usage;
if (!strcmp(Tcl_GetString(objv[1]), "listkeys")) {
if (objc != 3 && objc != 2) goto usage;
if (objc == 3) {
return RatPGPListKeys(interp, Tcl_GetString(objv[2]));
} else {
return RatPGPListKeys(interp, NULL);
}
} else if (!strcmp(Tcl_GetString(objv[1]), "extract")) {
if (objc != 3 && objc != 4) goto usage;
if (objc == 4) {
return RatPGPExtractKey(interp, Tcl_GetString(objv[2]),
Tcl_GetString(objv[3]));
} else {
return RatPGPExtractKey(interp, Tcl_GetString(objv[2]), NULL);
}
} else if (!strcmp(Tcl_GetString(objv[1]), "add")) {
if (objc != 3 && objc != 4) goto usage;
if (objc == 4) {
return RatPGPAddKeys(interp, Tcl_GetString(objv[2]),
Tcl_GetString(objv[3]));
} else {
return RatPGPAddKeys(interp, Tcl_GetString(objv[2]), NULL);
}
}
usage:
Tcl_AppendResult(interp, "Illegal usage of \"", Tcl_GetString(objv[0]),
"\"", (char *) NULL);
return TCL_ERROR;
}
/*
*----------------------------------------------------------------------
*
* RatPGPStrFind --
*
* Find a PGP string in a message
*
* Results:
* A pointer to the start of the string.
*
* Side effects:
* None.
*
*
*----------------------------------------------------------------------
*/
char*
RatPGPStrFind(char *haystack, long straws, char *needle, int linestart)
{
long i, j, end;
int needleSize = strlen(needle);
end = straws-strlen(needle);
for (i=0; i<=end; i+= 5) {
if ('-' == haystack[i]) {
for (j=i; j>0 && j>i-5 && '-' == haystack[j]; j--);
if ((j >= end-5) || (linestart && j>0 && '\n' != haystack[j])) {
continue;
}
if (j > 0) {
j++;
}
if (!strncmp("-----", haystack+i, 5-(i-j))
&& !strncmp(needle, haystack+j+5, needleSize)) {
return haystack+j;
}
}
}
return NULL;
}
syntax highlighted by Code2HTML, v. 0.9.1