diff options
author | mataes2007 <mataes2007@e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb> | 2011-11-22 18:30:08 +0000 |
---|---|---|
committer | mataes2007 <mataes2007@e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb> | 2011-11-22 18:30:08 +0000 |
commit | 4101ee8ff9bc818f40dc0173b1434761f187597f (patch) | |
tree | 15ace4a23c2d13b1c4b506a54887b1ec196ee007 /GnuPG/sendrecv.cpp | |
parent | da1c34bde32e040a0a431ffb809c3b1e425dc558 (diff) |
added GnuPG
git-svn-id: http://miranda-plugins.googlecode.com/svn/trunk@197 e753b5eb-9565-29b2-b5c5-2cc6f99dfbcb
Diffstat (limited to 'GnuPG/sendrecv.cpp')
-rw-r--r-- | GnuPG/sendrecv.cpp | 406 |
1 files changed, 406 insertions, 0 deletions
diff --git a/GnuPG/sendrecv.cpp b/GnuPG/sendrecv.cpp new file mode 100644 index 0000000..f59f35b --- /dev/null +++ b/GnuPG/sendrecv.cpp @@ -0,0 +1,406 @@ +#include "gnupgplugin.h"
+
+char PGP_PUBKEY_PROLOG[]="-----BEGIN PGP PUBLIC KEY BLOCK-----";
+char PGP_PUBKEY_EPILOG[]="-----END PGP PUBLIC KEY BLOCK-----";
+char PGP_MSG_PROLOG[]="-----BEGIN PGP MESSAGE-----";
+char PGP_MSG_EPILOG[]="-----END PGP MESSAGE-----";
+
+int SendMsgSvc(WPARAM wParam, LPARAM lParam)
+ // ANSI mode:
+ // ANSI source message is encrypted to ANSI cyphertext, then sent.
+ // UNICODE mode:
+ // ANSI part of source ANSI+UCS2 message is encrypted to ANSI cyphertext,
+ // then the cyphertext is appended by UCS2 version of the ANSI
+ // cyphertext, then the resulting ANSI+UCS2 cyphertext is sent.
+ // Note: the UCS2 part of the source message is lost! This is a feature.
+{
+ CCSDATA *ccs=(CCSDATA*)lParam;
+ if (!ccs)
+ {
+ LogMessage("--- GnuPG.SendMsgSvc: ","ccs==NULL, not our case.","\n");
+ return CallService(MS_PROTO_CHAINSEND,wParam,lParam);
+ }
+ char *msg=(char*)(ccs->lParam);
+ if (!msg)
+ {
+ LogMessage("--- GnuPG.SendMsgSvc: ","msg==NULL, not our case.","\n");
+ return CallService(MS_PROTO_CHAINSEND,wParam,lParam);
+ }
+
+ bool isUnicode=(bool)(ccs->wParam&PREF_UNICODE);
+ LogMessage("--- GnuPG.SendMsgSvc: mode: ",(isUnicode?"UNICODE":"ANSI"),"\n");
+ LogMessage("--- GnuPG.SendMsgSvc: msg (ANSI part):\n",msg,"\n--- EOM ---\n");
+
+ #if defined(__GPG_DEBUG__)
+ int binsiz=strlen(msg)+1;
+ if (isUnicode) binsiz*=(sizeof(wchar_t)+1);
+ FILE *fp=fopen("C:\\mir_SendMsgSvc_preenc.asc","wb");
+ if (fp)
+ {
+ fwrite(msg,1,binsiz,fp);
+ fclose(fp);
+ }
+ #endif
+
+ char keyuserid[keyuseridsize];
+
+ // get keyuserid
+ {
+ DBVARIANT dbv;
+ strcpy(keyuserid,(
+ DBGetContactSetting(ccs->hContact,pluginid,dbkeyuserid,&dbv)==0
+ ?dbv.pszVal
+ :""));
+ DBFreeVariant(&dbv);
+ }
+
+ UINT useencryptionchecked
+ =DBGetContactSettingByte(ccs->hContact,pluginid,dbuseencryption,FALSE);
+
+ char *buf=NULL;
+
+ if (useencryptionchecked && strlen(keyuserid))
+ {
+ char keyid[keyidsize];
+ ZeroMemory(keyid,sizeof(keyid));
+ getNextPart(keyid,keyuserid,txtidseparator);
+
+ if (gpgEncrypt(&buf,keyid,msg)!=gpgSuccess)
+ {
+ ErrorMessage(txterror,txtencryptfailed,txtverifyoptions);
+ return 0;
+ }
+ // *** ENCRYPT
+
+ if (buf) // now buf allocated and filled by encrypted message.
+ {
+ int binsiz=strlen(buf)+1;
+ if (isUnicode)
+ {
+ char *mix=makemix_dup(buf);
+ if (mix)
+ {
+ fnFALSE(&buf);
+ buf=mix;
+ binsiz*=(sizeof(wchar_t)+1);
+ }
+ else
+ LogMessage("--- GnuPG.SendMsgSvc: MIX: ","FAILED.","\n");
+ }
+
+ LogMessage("--- GnuPG.SendMsgSvc: Encrypted: \n",buf,"\n--- EOM ---\n");
+
+ #if defined(__GPG_DEBUG__)
+ FILE *fp=fopen("C:\\mir_SendMsgSvc_encbuf.asc","wb");
+ if (fp)
+ {
+ fwrite(buf,1,binsiz,fp);
+ fclose(fp);
+ }
+ #endif
+
+ ccs->lParam=(LPARAM)buf;
+
+// *** THIS IS A FEATURE HACK FOR JABBERG CODE... ***
+ ccs->wParam&=~PREF_UNICODE; // *** GO ANSI WAY!
+ LogMessage("--- GnuPG.SendMsgSvc: ANSI MODE FORCED: ","JabberG feature hack.","\n");
+// *** THIS IS A FEATURE HACK FOR JABBERG CODE... ***
+
+ int rc=CallService(MS_PROTO_CHAINSEND,wParam,(LPARAM)ccs);
+ // *** SEND ENCRYPTED!
+ fnFALSE(&buf);
+ ccs->lParam=(LPARAM)msg;
+ return rc;
+ }
+ // buf not allocated, so... send unencrypted.
+ }
+
+ LogMessage("--- GnuPG.SendMsgSvc: sending: ","UNENCRYPTED.","\n");
+
+ return CallService(MS_PROTO_CHAINSEND,wParam,lParam);
+
+} // int SendMsgSvc(WPARAM wParam, LPARAM lParam)
+
+enum recv_event_type { re_undefined, re_pgpmessage, re_pgppublickey, re_unknown };
+
+enum recv_event_type get_recv_event_type(const char *msg)
+{
+ char *prolog,*epilog;
+ prolog=(char*)strstr(msg,PGP_MSG_PROLOG);
+ epilog=(char*)strstr(msg,PGP_MSG_EPILOG);
+ if (prolog && epilog)
+ {
+ LogMessage("--- GnuPG.get_recv_event_type: ","re_pgpmessage","\n");
+ return re_pgpmessage;
+ }
+ prolog=(char*)strstr(msg,PGP_PUBKEY_PROLOG);
+ epilog=(char*)strstr(msg,PGP_PUBKEY_EPILOG);
+ if (prolog && epilog)
+ {
+ LogMessage("--- GnuPG.get_recv_event_type: ","re_pgppublickey","\n");
+ return re_pgppublickey;
+ }
+ LogMessage("--- GnuPG.get_recv_event_type: ","re_unknown","\n");
+ return re_unknown;
+}
+
+int parse_pgp_message(WPARAM wParam, CCSDATA *ccs)
+{
+ PROTORECVEVENT *pre=(PROTORECVEVENT*)(ccs->lParam);
+ char *msg=pre->szMessage;
+ if (!msg)
+ return CallService(MS_PROTO_CHAINRECV,wParam,(LPARAM)ccs);
+
+ bool isUnicode=(bool)(pre->flags&PREF_UNICODE);
+ bool isUtf=(bool)(pre->flags&PREF_UTF);
+
+ LogMessage("--- GnuPG.parse_pgp_message: pre->flags: ",
+ (isUnicode?"UNICODE":"ANSI"),
+ (isUtf?"+UTF\n":"\n"));
+
+ char *OrigMessage=msg;
+ char *tmp=fixcrlf_dup(msg);
+ if (tmp)
+ msg=tmp;
+ else
+ LogMessage("--- GnuPG.parse_pgp_message: CR/LF: ","FAILED.","\n");
+
+ char keyuserid[keyuseridsize]; ZeroMemory(keyuserid,sizeof(keyuserid));
+ bool useridvalid=(gpgDetectUserID(keyuserid,msg)==gpgSuccess);
+
+ char *storedpassphrase=NULL;
+ char passphrase[passphrasesize];
+
+ if (useridvalid)
+ {
+ if (storepassphraseschecked==BST_CHECKED)
+ storedpassphrase=getPassphrase(keyuserid);
+ }
+ else
+ {
+ ErrorMessage(txtwarning,txtdetectuseridfailed,txtverifyoptions);
+ strcpy(keyuserid,txtunknownuserid);
+ }
+
+ gpgResult gpgresult=gpgUnknownError;
+ char *decrypteddata=NULL;
+
+ LogMessage("--- GnuPG.parse_pgp_message: keyuserid: ",keyuserid,"\n");
+
+ if (storedpassphrase)
+ {
+ strcpy(passphrase,storedpassphrase);
+ gpgresult=gpgDecrypt(&decrypteddata,msg,passphrase);
+ // *** DECRYPT
+ }
+
+ int dlgresult=IDOK;
+ while (gpgresult!=gpgSuccess && dlgresult!=IDCANCEL)
+ // if there were no stored passphrase or we just failed to decrypt...
+ {
+ dlgresult=DialogBoxParam(dllinstance,MAKEINTRESOURCE(IDD_PASSPHRASE_DLG),
+ NULL,PassphraseDialogProcedure,(LPARAM)keyuserid);
+
+ if (dlgresult==IDOK) // if some passphrase given...
+ {
+ strcpy(passphrase,dlgpassphrase); ZeroMemory(dlgpassphrase,passphrasesize);
+ strcat(passphrase,txtcrlf); // wtf
+ gpgresult=gpgDecrypt(&decrypteddata,msg,passphrase);
+ // *** DECRYPT
+ }
+ }
+ // here on cancel or successful decryption
+
+ if (gpgresult==gpgSuccess) // if successfully decrypted
+ {
+ if (useridvalid && storepassphraseschecked==BST_CHECKED)
+ addPassphrase(keyuserid,passphrase); // cache passphrase
+ }
+
+ if (decrypteddata)
+ {
+ // 0. not utf? => decode from utf to ANSI
+ if (!isUtf) // !!! QUICK'N'DIRTY HACK for 0.7 <-> 0.7 only
+ mir_utf8decode(decrypteddata,NULL);
+
+ // We have some decrypted data, so let's:
+ // 1. embrace 'em with tags.
+ // 2. replace original message with the embraced decrypted data.
+ char *tmp=(char*)mir_alloc(strlen(starttag)+strlen(decrypteddata)+strlen(endtag)+1);
+ if (tmp)
+ {
+ strcpy(tmp,starttag);
+ strcat(tmp,decrypteddata);
+ strcat(tmp,endtag);
+ mir_free(decrypteddata);
+ decrypteddata=tmp;
+ } // *** start and end tags added if possible
+
+ LogMessage("--- GnuPG.parse_pgp_message: decrypteddata:\n",
+ decrypteddata,"\n--- EOM ---\n");
+
+ pre->szMessage=decrypteddata; // swap for decrypted
+ if (msg!=OrigMessage) fnFALSE(&msg); // throw away msg if not OrigMessage
+ }
+ else
+ pre->szMessage=msg; // no decrypted, so show the cyphertext
+
+ if (isUnicode && pre->szMessage!=OrigMessage)
+ // in Unicode mode, only for mir_allocated message
+ {
+ char *mix=makemix_dup(pre->szMessage);
+ if (mix)
+ {
+ mir_free(pre->szMessage);
+ pre->szMessage=mix; // mix done
+ }
+ else
+ {
+ LogMessage("--- GnuPG.parse_pgp_message: MIX: ","FAILED.","\n");
+ mir_free(pre->szMessage); // *** whatever there were...
+ pre->szMessage=OrigMessage;
+ // failed to mix => original cyphertext!
+ }
+ } // Unicode mode? => we should use mix! ...or original message.
+
+ ZeroMemory(passphrase,sizeof(passphrase)); // security kid
+
+ int rc=CallService(MS_PROTO_CHAINRECV,wParam,(LPARAM)ccs);
+ // RECEIVE IT FINALLY
+
+ if (pre->szMessage!=OrigMessage)
+ {
+ mir_free(pre->szMessage);
+ pre->szMessage=OrigMessage; // swap back to original encrypted
+ }
+ return rc;
+}
+
+int parse_pgp_public_key(WPARAM wParam, CCSDATA *ccs)
+{
+ PROTORECVEVENT *pre=(PROTORECVEVENT*)(ccs->lParam);
+ char *key=pre->szMessage;
+ if (!key)
+ return CallService(MS_PROTO_CHAINRECV,wParam,(LPARAM)ccs);
+
+ bool isUnicode=(pre->flags&PREF_UNICODE)?true:false;
+
+ char *OrigMessage=key;
+ char *tmp=fixcrlf_dup(key);
+ if (tmp)
+ key=tmp;
+ else
+ LogMessage("--- GnuPG.parse_pgp_public_key: CR/LF: ","FAILED.","\n");
+
+ time_t now; time(&now); struct tm tms=*localtime(&now);
+ const int ASCTIMESIZ=26; // *** as defined in asctime description. Dangerous?
+ char atstr[ASCTIMESIZ];
+ strcpy(atstr,asctime(&tms)); replace(atstr,"\n",""); replace(atstr,"\r","");
+ DBWriteContactSettingString(ccs->hContact,pluginid,dbkeymodified,atstr);
+
+ gpgResult gpgresult=gpgUnknownError;
+ char *atprolog=strstr(key,PGP_PUBKEY_PROLOG);
+ if (atprolog)
+ {
+ DBWriteContactSettingString(ccs->hContact,pluginid,dbkey,atprolog);
+ if (autoimportpublickeyschecked==BST_CHECKED)
+ gpgresult=gpgImportPublicKey(atprolog);
+ // *** PUBKEY MAYBE IMPORTED
+ }
+
+ if (key && key!=OrigMessage)
+ mir_free(key);
+
+ // let's try to save some human-readable words for history!
+
+ char *buf=(char*)mir_alloc(
+ strlen(starttag)
+ +strlen(Translate(txtpublickeyreceivedstored))
+ +strlen(Translate(txtpublickeyreceived))
+ +strlen(Translate(txtimportpublickeyfailed))
+ +strlen(Translate(txtverifyoptions))
+ +strlen(endtag)
+ +3 // two ' ' and one '\0'
+ );
+
+ if (buf)
+ {
+ strcpy(buf,starttag);
+
+ if (gpgresult==gpgSuccess)
+ strcat(buf,Translate(txtpublickeyreceivedstored));
+ else
+ {
+ strcat(buf,Translate(txtpublickeyreceived));
+ if (autoimportpublickeyschecked==BST_CHECKED)
+ {
+ strcat(buf," ");
+ strcat(buf,Translate(txtimportpublickeyfailed));
+ strcat(buf," ");
+ strcat(buf,Translate(txtverifyoptions));
+ }
+ }
+
+ strcat(buf,endtag);
+
+ pre->flags&=~PREF_UNICODE; // no reason for Unicode here!
+ pre->szMessage=buf; // for history
+
+ int rc=CallService(MS_PROTO_CHAINRECV,wParam,(LPARAM)ccs);
+ // *** some words for history should be written to db now.
+ if (pre->szMessage!=OrigMessage)
+ {
+ mir_free(pre->szMessage);
+ pre->szMessage=OrigMessage; // swap back...
+ }
+ return rc;
+ }
+
+ return CallService(MS_PROTO_CHAINRECV,wParam,(LPARAM)ccs);
+ // as far as we have no chance to save our words for history,
+ // let it be the original data.
+}
+
+int RecvMsgSvc(WPARAM wParam, LPARAM lParam)
+ // wParam - used to call proto recv chain, not used internally.
+ // lParam - points to CCSDATA structure
+ // returns result of CallService(MS_PROTO_CHAINRECV,wParam,lParam)
+{
+ CCSDATA *ccs=(CCSDATA*)lParam;
+ if (!ccs) // ccs==NULL => not our case!
+ return CallService(MS_PROTO_CHAINRECV,wParam,lParam);
+
+ PROTORECVEVENT *pre=(PROTORECVEVENT*)(ccs->lParam);
+ if (!pre) // pre==NULL => not our case!
+ return CallService(MS_PROTO_CHAINRECV,wParam,lParam);
+
+ char *msg=pre->szMessage;
+ if (!msg) // No message => not our case!
+ return CallService(MS_PROTO_CHAINRECV,wParam,lParam);
+
+ bool isUnicode=(bool)(pre->flags&PREF_UNICODE);
+ LogMessage("--- GnuPG.RecvMsgSvc: mode: ",(isUnicode?"UNICODE":"ANSI"),"\n");
+ LogMessage("--- GnuPG.RecvMsgSvc: msg (ANSI part):\n",msg,"\n--- EOM ---\n");
+
+ #if defined(__GPG_DEBUG__)
+ FILE *fp=fopen("C:\\mir_RecvMsgSvc.bin","wb");
+ if (fp)
+ {
+ int binlen=strlen(msg)+1;
+ if (isUnicode)
+ binlen*=(sizeof(wchar_t)+1);
+ fwrite(msg,1,binlen,fp);
+ fclose(fp);
+ }
+ #endif
+
+ switch (get_recv_event_type(msg))
+ {
+ case re_pgpmessage: return parse_pgp_message(wParam,ccs);
+ case re_pgppublickey: return parse_pgp_public_key(wParam,ccs);
+ default: break; // unknown event type, so not our case!
+ }
+
+ return CallService(MS_PROTO_CHAINRECV,wParam,lParam);
+ // not our case...
+} // int RecvMsgSvc(WPARAM wParam, LPARAM lParam)
|