This is PGP.m in view mode; [Download] [Up]
/* -*-C-*- ******************************************************************************* * * File: PGP.m * RCS: $Header: /usr/local/lib/cvs/EnhanceMail/PGP.m,v 1.1.1.6 1996/07/01 01:10:24 cedman Exp $ * Description: * Author: Carl Edman * Created: Fri Oct 13 11:48:05 1995 * Modified: Sun Jun 30 13:38:57 1996 (Carl Edman) cedman@capitalist.princeton.edu * Language: C * Package: N/A * Status: Experimental (Do Not Distribute) * * (C) Copyright 1995, but otherwise this file is perfect freeware. * ******************************************************************************* */ #import "EnhanceMail.h" #import "PGP.h" #import "Preferences.h" #import "XImageURL.h" #import "regexp.h" #define PGP_SIGNED "-----BEGIN PGP SIGNED MESSAGE-----" #define PGP_ENCRYPTED "-----BEGIN PGP MESSAGE-----" #define MSG_PGP_RICH NXLocalizedStringFromTableInBundle("Localizable", EnhanceBundle, "Only Plain Text messages are handled by PGP.", NULL, Error for attempt to PGP rich text messages) #define MSG_CANCEL NXLoadLocalizedStringFromTableInBundle("Buttons", nil, "Cancel", NULL) #define MSG_DELIVER NXLoadLocalizedStringFromTableInBundle("Buttons", nil, "Deliver Anyway", NULL) static id mypgp=nil; static regexp *keyrx=0, *addrrx=0; @implementation EnhancePGP + new { if (mypgp==nil) mypgp=[[self alloc] init]; return mypgp; } - init { char path[MAXPATHLEN+1]; if ([EnhanceBundle getPath:path forResource:"EnhancePGPPanel" ofType:"nib"]) [NXApp loadNibFile:path owner:self]; passTime=0; if (keyrx==0) keyrx=regcomp("-----BEGIN PGP PUBLIC KEY BLOCK-----.*-----END PGP PUBLIC KEY BLOCK-----"); if (addrrx==0) addrrx=regcomp("^[^<>]*<([^<> ]*)>[^<>]*$\n^ *([^() \t]*) *\\([^()]*\\) *$"); return self; } - reenter:sender { return [NXApp stopModal:2]; } - ok:sender { return [NXApp stopModal:1]; } - cancel:sender { return [NXApp stopModal:0]; } - clobberPass { const char *pass; char *c; if (!passField) return nil; pass=[passField stringValue]; for(c=(char *)pass;*c;c++) *c='\0'; [passField setStringValue:pass]; return self; } - getUser:(const char **)user pass:(const char **)pass { int ret; time_t curtime=time(0); if (curtime>passTime) [self clobberPass]; if (user && userField!=nil) *user=[userField stringValue]; if (pass && passField!=nil) *pass=[passField stringValue]; if (pass && *pass && **pass) return self; if (passPanel==nil) return nil; if (passField!=nil) [passField selectText:self]; ret=[NXApp runModalFor:passPanel]; [passPanel orderOut:self]; if (ret==0) { user=pass=0; return nil; } if (user && userField) *user=[userField stringValue]; if (pass && passField) *pass=[passField stringValue]; passTime=time(0)+EnhancePGPPassTimeout*60; return self; } - (int)handleError:(const char *)err ok:(BOOL)defok { int ret; const char *c; if ((errPanel==nil) || (errText==nil)) return 0; for(c=err;*c;c++) if (*c=='\a') NXBeep(); while((*err==' ') || (*err=='\n') || (*err=='\a') || (*err==' ')) err++; [errText setText:err]; if (defok && (errDefaultButton!=nil) && (errNonDefaultButton!=nil)) { SEL tmpact; char tmptitle[1024]; tmpact=[errDefaultButton action]; strcpy(tmptitle,[errDefaultButton title]); [errDefaultButton setAction:[errNonDefaultButton action]]; [errDefaultButton setTitle:[errNonDefaultButton title]]; [errNonDefaultButton setAction:tmpact]; [errNonDefaultButton setTitle:tmptitle]; } [errText scrollSelToVisible]; ret=[NXApp runModalFor:errPanel]; [errPanel orderOut:self]; if (defok && (errDefaultButton!=nil) && (errNonDefaultButton!=nil)) { SEL tmpact; char tmptitle[1024]; tmpact=[errDefaultButton action]; strcpy(tmptitle,[errDefaultButton title]); [errDefaultButton setAction:[errNonDefaultButton action]]; [errDefaultButton setTitle:[errNonDefaultButton title]]; [errNonDefaultButton setAction:tmpact]; [errNonDefaultButton setTitle:tmptitle]; } return ret; } - (int)runPGP:(SimpleString *)In to:(SimpleString *)Out error:(SimpleString *)Err args:(const char **)argv { int inpipe[2],outpipe[2],errpipe[2]; int ac,pid; const char **av; union wait status; if (access(EnhancePGPPath,X_OK)) { [NXApp logError:"Missing pgp binary."]; return -1; } for(ac=0;argv[ac];ac++); av=alloca(sizeof(*av)*(ac+6)); ac=0; av[ac++]="pgp"; av[ac++]="+batchmode"; av[ac++]="+force"; av[ac++]="+encrypttoself=on"; av[ac++]="-f"; while (*argv) av[ac++]=*argv++; av[ac]=0; if ((pipe(inpipe)<0) || (pipe(outpipe)<0) || (pipe(errpipe)<0)) { [NXApp logError:"Failure to create pipe pairs."]; return -2; } if (!(pid=fork())) { close(inpipe[1]); close(outpipe[0]); close(errpipe[0]); if (inpipe[0] != 0) { dup2(inpipe[0], 0); close(inpipe[0]); } if (outpipe[1] != 1) { dup2(outpipe[1], 1); close(outpipe[1]); } if (errpipe[1] != 2) { dup2(errpipe[1], 2); close(errpipe[1]); } execv(EnhancePGPPath, av); _exit(1); } if (pid==-1) { [NXApp logError:"Failure to fork."]; return -3; } close(inpipe[0]); close(outpipe[1]); close(errpipe[1]); /* This is not quite proper, but if pgp works the way I think it does, it will work and be a lot shorter and simpler than the proper solution. */ if (In!=nil) [In writeFile:inpipe[1]]; close(inpipe[1]); if (Out!=nil) [[Out empty] appendFile:outpipe[0]]; close(outpipe[0]); if (Err!=nil) [[Err empty] appendFile:errpipe[0]]; close(errpipe[0]); if (wait4(pid,&status,0,0)<0) { [NXApp logError:"PGP process disappeared."]; return -4; } if (status.w_T.w_Termsig!=0) { [NXApp logError:"PGP process killed by signal."]; return -5; } return status.w_T.w_Retcode; } - (BOOL)grabKey:(const char *)keyid { int ac,ret; const char **av=0; char url[MAXPATHLEN+1]; id s; if (!EnhanceRetrievePGPKeys || !EnhanceKeyServerURL) return NO; sprintf(url,"%s%s",EnhanceKeyServerURL,keyid); s=[[SimpleString alloc] init]; if ([NXImage grabURL:url string:s]==NO) { s=[s free]; return NO; } if (regexec(keyrx,[s string])==NO) { s=[s free]; return NO; } av=alloca(sizeof(*av)*2); ac=0; av[ac++]="-ka"; av[ac]=0; ret=[self runPGP:s to:nil error:nil args:av]; s=[s free]; return ret==0; } - (BOOL)decodePGP:(MailMessage *)mes { id In,Out,Err; const char **av; int ret=0,ac; if ([mes isRichBody]) return NO; if ((strncmp([mes body],PGP_ENCRYPTED,sizeof(PGP_ENCRYPTED)-1)!=0) && (strncmp([mes body],PGP_SIGNED,sizeof(PGP_SIGNED)-1)!=0)) return NO; In=[[SimpleString alloc] init]; [In appendString:[mes body] length:[mes bodyLength]]; Out=[[SimpleString alloc] init]; Err=[[SimpleString alloc] init]; av=alloca(sizeof(*av)*5); restart: ac=0; if (strncmp([In string],PGP_ENCRYPTED,sizeof(PGP_ENCRYPTED)-1)==0) { const char *user, *pass; if ([self getUser:&user pass:&pass]==NO) goto end; if (user && *user) { av[ac++]="-u"; av[ac++]=user; } if (pass && *pass) { av[ac++]="-z"; av[ac++]=pass; } } av[ac]=0; ret=[self runPGP:In to:Out error:Err args:av]; if ((ret!=0) || ([Err length]>0)) switch([self handleError:[Err string] ok:(ret==0)]) { case 0: ret=-1; break; case 1: ret=0; break; case 2: [self clobberPass]; goto restart; } if (ret==0) [mes setBody:[Out string] length:[Out length]]; end: if (In!=nil) In=[In free]; if (Out!=nil) Out=[Out free]; if (Err!=nil) Err=[Err free]; return (ret==0); } - (BOOL)encodePGP:(MailMessage *)mes to:(StringList *)rcpt sign:(BOOL)sign encrypt:(BOOL)encrypt { int ret=0, ac; const char **av; id In, Out,Err; if ([rcpt count]==0) encrypt=NO; if (!encrypt && !sign) return YES; if ([mes isRichBody]) { NXBeep(); return !NXRunAlertPanel(0,MSG_PGP_RICH,MSG_CANCEL,MSG_DELIVER,0); } In=[[SimpleString alloc] init]; [In appendString:[mes body] length:[mes bodyLength]]; Out=[[SimpleString alloc] init]; Err=[[SimpleString alloc] init]; av=alloca(sizeof(*av)*([rcpt count]+8)); restart: ac=0; av[ac++]="-a"; if (sign) { const char *user,*pass; if ([self getUser:&user pass:&pass]==NO) goto end; if (user && *user) { av[ac++]="-u"; av[ac++]=user; } if (pass && *pass) { av[ac++]="-z"; av[ac++]=pass; } av[ac++]="-s"; } if (encrypt) { int n; const char *r; char buf[1024]; av[ac++]="-e"; for(n=0;n<[rcpt count];n++) { r=[rcpt stringAt:n]; if (regexec(addrrx,r)) { regsub(addrrx,"\\1\\2",buf); r=strcpy(alloca(strlen(buf)+1),buf); } av[ac++]=r; } } else { av[ac++]="-t"; } av[ac]=0; ret=[self runPGP:In to:Out error:Err args:av]; if ((ret!=0) || ([Err length]>0)) switch([self handleError:[Err string] ok:(ret==0)]) { case 0: ret=-1; break; case 1: ret=0; break; case 2: [self clobberPass]; goto restart; } if (ret==0) [mes setBody:[Out string] length:[Out length]]; end: if (In!=nil) In=[In free]; if (Out!=nil) Out=[Out free]; if (Err!=nil) Err=[Err free]; return (ret==0); } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.