summaryrefslogtreecommitdiff
path: root/MirOTR/otr.cpp
diff options
context:
space:
mode:
authoradmin@progandy.co.cc <admin@progandy.co.cc@eced67a3-f377-a0ae-92ae-d6de1850b05a>2010-08-19 20:12:06 +0000
committeradmin@progandy.co.cc <admin@progandy.co.cc@eced67a3-f377-a0ae-92ae-d6de1850b05a>2010-08-19 20:12:06 +0000
commit11e5e8749eb7d4d3cfebfa49bbb7ea4624608647 (patch)
treec773fee94a63a078e5cb59bdbfd3165f1830b7ea /MirOTR/otr.cpp
parentc7e64af067562167b6941f3ad8383e3ceb817633 (diff)
initial commit with v0.8.6.1
git-svn-id: http://mirotr.googlecode.com/svn/trunk@2 eced67a3-f377-a0ae-92ae-d6de1850b05a
Diffstat (limited to 'MirOTR/otr.cpp')
-rw-r--r--MirOTR/otr.cpp383
1 files changed, 383 insertions, 0 deletions
diff --git a/MirOTR/otr.cpp b/MirOTR/otr.cpp
new file mode 100644
index 0000000..9779800
--- /dev/null
+++ b/MirOTR/otr.cpp
@@ -0,0 +1,383 @@
+#include <stdafx.h>
+#include "otr.h"
+#include <process.h>
+
+OtrlUserState otr_user_state;
+#define WMU_ENDDIALOG (WM_USER+244)
+
+OtrlMessageAppOps ops = {
+ otr_gui_policy,
+ otr_gui_create_privkey,
+ otr_gui_is_logged_in,
+ otr_gui_inject_message,
+ otr_gui_notify,
+ otr_gui_display_otr_message,
+ otr_gui_update_context_list,
+ otr_gui_protocol_name,
+ otr_gui_protocol_name_free,
+ otr_gui_new_fingerprint,
+ otr_gui_write_fingerprints,
+ otr_gui_gone_secure,
+ otr_gui_gone_insecure,
+ otr_gui_still_secure,
+ otr_gui_log_message,
+ max_message_size,
+ account_name,
+ account_name_free
+};
+
+struct GenKeyData{
+ HWND dialog;
+ char *proto;
+};
+
+static unsigned int CALLBACK generate_key_thread(void* param) {
+ CallService(MS_SYSTEM_THREAD_PUSH, 0, 0);
+ GenKeyData *data = (GenKeyData *)param;
+ lib_cs_lock();
+ otrl_privkey_generate(otr_user_state, g_private_key_filename, data->proto, data->proto);
+ lib_cs_unlock();
+ PostMessage(data->dialog, WMU_ENDDIALOG, 0, 0);
+ CallService(MS_SYSTEM_THREAD_POP, 0, 0);
+ return 0;
+}
+
+INT_PTR CALLBACK GenKeyDlgFunc(HWND hWndDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
+ switch(msg) {
+ case WM_INITDIALOG:
+ {
+ if (!lParam) {
+ EndDialog(hWndDlg, 0);
+ return 0;
+ }
+ TranslateDialogDefault(hWndDlg);
+ SetClassLongPtr(hWndDlg, GCL_HICON, (LONG_PTR)LoadIcon(ICON_OTR,1) );
+ TCHAR buff[256];
+ TCHAR *proto = mir_a2t((char*)lParam);
+ mir_sntprintf(buff, 256, TranslateT(LANG_GENERATE_KEY), proto);
+ mir_free(proto);
+ SetDlgItemText(hWndDlg, IDC_GENERATE, buff);
+ GenKeyData *data = new GenKeyData();
+ data->dialog = hWndDlg;
+ data->proto = (char*)lParam;
+ CloseHandle((HANDLE)_beginthreadex(0, 0, generate_key_thread, (void*)data, 0, 0));
+ }break;
+ case WMU_ENDDIALOG:
+ EndDialog(hWndDlg, 0);
+ return TRUE;
+ case WM_DESTROY:
+ SetClassLongPtr(hWndDlg, GCL_HICON, 0);
+ ReleaseIcon(ICON_OTR,1);
+ }
+ return FALSE;
+}
+
+extern "C" {
+ /* Return the OTR policy for the given context. */
+ OtrlPolicy otr_gui_policy(void *opdata, ConnContext *context) {
+ DEBUGOUT_T("OTR_GUI_POLICY")
+ HANDLE hContact = (HANDLE)opdata;
+ DWORD pol;
+ if(hContact) {
+ pol = DBGetContactSettingDword(hContact, MODULENAME, "Policy", CONTACT_DEFAULT_POLICY);
+ if(pol != CONTACT_DEFAULT_POLICY) return pol ;
+ }
+ if(context->protocol) {
+ pol = db_dword_get(0,MODULENAME"_ProtoPol", context->protocol, CONTACT_DEFAULT_POLICY);
+ if(pol != CONTACT_DEFAULT_POLICY) return pol ;
+ }
+
+ return options.default_policy ;
+ }
+
+ /* Create a private key for the given accountname/protocol if
+ * desired. */
+ void otr_gui_create_privkey(void *opdata, const char *account_name, const char *protocol) {
+ DEBUGOUT_T("OTR_GUI_CREATE_PRIVKEY")
+ //if(MessageBox(0, Translate("Would you like to generate a new private key for this protocol?"), Translate("OTR"), MB_YESNO) == IDYES)
+ //if(options.err_method == ED_POP)
+ //ShowPopup(Translate("Generating new private key."), 0 /*Translate("Please wait.")*/, 5);
+
+ //NewKeyData *nkd = (NewKeyData *)malloc(sizeof(NewKeyData));
+ //nkd->account_name = strdup(account_name);
+ //nkd->protocol = strdup(protocol);
+
+ //DWORD tid;
+ //CloseHandle(CreateThread(0, 0, newKeyThread, (VOID *)nkd, 0, &tid));
+ //QueueUserAPC(newKeyAPC, Global::mainThread, (DWORD)nkd);
+ DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_GENKEYNOTIFY), GetDesktopWindow(), GenKeyDlgFunc, (LPARAM)protocol );
+
+ }
+
+ /* Report whether you think the given user is online. Return 1 if
+ * you think he is, 0 if you think he isn't, -1 if you're not sure.
+ *
+ * If you return 1, messages such as heartbeats or other
+ * notifications may be sent to the user, which could result in "not
+ * logged in" errors if you're wrong. */
+ int otr_gui_is_logged_in(void *opdata, const char *accountname, const char *protocol, const char *recipient) {
+ DEBUGOUT_T("OTR_GUI_IS_LOGGED_IN")
+ HANDLE hContact = (HANDLE)opdata;
+ if(hContact) {
+ WORD status = DBGetContactSettingWord(hContact, contact_get_proto(hContact), "Status", ID_STATUS_OFFLINE);
+ if(status == ID_STATUS_OFFLINE) return 0;
+ else return 1;
+ }
+
+ return -1;
+ }
+
+ /* Send the given IM to the given recipient from the given
+ * accountname/protocol. */
+ void otr_gui_inject_message(void *opdata, const char *accountname, const char *protocol, const char *recipient, const char *message) {
+ DEBUGOUT_T("OTR_GUI_INJECT_MESSAGE")
+ //MessageBox(0, message, "OTR Inject", MB_OK);
+ HANDLE hContact = (HANDLE)opdata;
+
+ if(protocol && DBGetContactSettingWord(hContact, protocol, "Status", ID_STATUS_OFFLINE) != ID_STATUS_OFFLINE) {
+ /* this would be with translation
+ TCHAR *decode = mir_utf8decodeT(message);
+ TCHAR *encode = mir_utf8encodeT(TranslateT(decide));
+ mir_free(decode);
+ CallContactService(hContact, PSS_MESSAGE, PREF_UTF|PREF_BYPASS_OTR, (LPARAM)encode);
+ mir_free(encode);
+ */
+ CallContactService(hContact, PSS_MESSAGE, PREF_UTF|PREF_BYPASS_OTR, (LPARAM)message);
+ //DEBUGOUT_T("INJECT")
+ }
+ }
+
+ /* Display a notification message for a particular accountname /
+ * protocol / username conversation. */
+ void otr_gui_notify(void *opdata, OtrlNotifyLevel level, const char *accountname, const char *protocol, const char *username, const char *title, const char *primary, const char *secondary) {
+ DEBUGOUT_T("OTR_GUI_NOTIFY")
+ const TCHAR* uname = contact_get_nameT((HANDLE)opdata);
+ TCHAR* title_t = mir_utf8decodeT(title);
+ TCHAR *notify = TranslateT(LANG_OTR_NOTIFY);
+
+ int len = _tcslen(uname) + _tcslen(title_t) + _tcslen(notify);
+ TCHAR *buff1 = new TCHAR[len];
+ mir_sntprintf(buff1, len, notify, TranslateTS(title_t), uname);
+ mir_free(title_t);
+
+ len = strlen(primary) + strlen(secondary) + 5;
+ char *buff2 = new char[len];
+ mir_snprintf(buff2, len, "%s\n%s", Translate(primary), Translate(secondary));
+ TCHAR* buff2_t = mir_utf8decodeT(buff2);
+ delete buff2;
+
+ DEBUGOUT_T("OTR_GUI_NOTIFY")
+
+ ShowPopup(buff1, buff2_t, 0);
+ mir_free(buff2_t);
+ delete buff1;
+ }
+
+ /* Display an OTR control message for a particular accountname /
+ * protocol / username conversation. Return 0 if you are able to
+ * successfully display it. If you return non-0 (or if this
+ * function is NULL), the control message will be displayed inline,
+ * as a received message, or else by using the above notify()
+ * callback. */
+ int otr_gui_display_otr_message(void *opdata, const char *accountname, const char *protocol, const char *username, const char *msg) {
+ DEBUGOUT_T("OTR_GUI_DISPLAY_OTR_MESSAGE")
+ if(options.msg_inline)
+ ShowMessageInlineUtf((HANDLE)opdata, Translate(msg));
+ if(options.msg_popup) {
+ TCHAR buff[512];
+ TCHAR* proto = mir_a2t(protocol);
+ mir_sntprintf(buff, 512, TranslateT(LANG_OTR_USERMESSAGE), contact_get_nameT((HANDLE)opdata), proto);
+ mir_free(proto);
+ TCHAR *msg_t = mir_utf8decodeT(msg);
+ ShowPopup(buff, TranslateTS(msg_t), 0);
+ mir_free(msg_t);
+ }
+ return 0;
+ }
+
+ /* When the list of ConnContexts changes (including a change in
+ * state), this is called so the UI can be updated. */
+ void otr_gui_update_context_list(void *opdata) {
+ //MessageBox(0, "Update Context List", "OTR Callback", MB_OK);
+ DEBUGOUT_T("OTR: Update Context List");
+ }
+
+ /* Return a newly-allocated string containing a human-friendly name
+ * for the given protocol id */
+ const char *otr_gui_protocol_name(void *opdata, const char *protocol) {
+ //return strdup(protocol);
+ DEBUGOUT_T("OTR_GUI_PROTOCOL_NAME")
+ return protocol;
+ }
+
+ /* Deallocate a string allocated by protocol_name */
+ void otr_gui_protocol_name_free(void *opdata, const char *protocol_name) {
+ //free((void *)protocol_name);
+ }
+
+ /* A new fingerprint for the given user has been received. */
+ void otr_gui_new_fingerprint(void *opdata, OtrlUserState us, const char *accountname, const char *protocol, const char *username, unsigned char fingerprint[20]) {
+ DEBUGOUT_T("OTR_GUI_NEW_FUNGERPRINT")
+ //MessageBox(0, username, Translate("OTR New Fingerprint"), MB_OK);
+ ConnContext *context = otrl_context_find(us, username, accountname, protocol, TRUE, 0, add_appdata, opdata);
+ Fingerprint *fp = otrl_context_find_fingerprint(context, fingerprint, TRUE, 0);
+
+ //CloseHandle((HANDLE)_beginthreadex(0, 0, trust_fp_thread, (void *)fp, 0, 0));
+
+ otrl_context_set_trust(fp, NULL);
+ otrl_privkey_write_fingerprints(otr_user_state, g_fingerprint_store_filename);
+ }
+
+ /* The list of known fingerprints has changed. Write them to disk. */
+ void otr_gui_write_fingerprints(void *opdata) {
+ DEBUGOUT_T("OTR_GUI_WRITE_FINGERPRINTS")
+ //if(MessageBox(0, Translate("Would you like to save the current fingerprint list?"), Translate(MODULE), MB_YESNO) == IDYES)
+ otrl_privkey_write_fingerprints(otr_user_state, g_fingerprint_store_filename);
+ }
+
+ /* A ConnContext has entered a secure state. */
+ void otr_gui_gone_secure(void *opdata, ConnContext *context) {
+ DEBUGOUT_T("OTR_GUI_GONE_SECURE")
+ TrustLevel trusted = otr_context_get_trust(context);
+ // opdata is hContact
+ SetEncryptionStatus((HANDLE)opdata, trusted);
+ TCHAR buff[1024];
+ if(trusted == TRUST_PRIVATE) {
+ mir_sntprintf(buff, 1024, TranslateT(LANG_SESSION_START_OTR), contact_get_nameT((HANDLE)opdata));
+ } else if (trusted == TRUST_UNVERIFIED) {
+ if (options.autoshow_verify) VerifyContextDialog(context);
+ mir_sntprintf(buff, 1024, TranslateT(LANG_SESSION_START_OTR_VERIFY), contact_get_nameT((HANDLE)opdata));
+ } else { // should never happen
+ mir_sntprintf(buff, 1024, TranslateT(LANG_SESSION_NOT_STARTED_OTR), contact_get_nameT((HANDLE)opdata));
+ }
+ // opdata is hContact
+ ShowMessage((HANDLE)opdata, buff);
+
+ }
+
+ /* A ConnContext has left a secure state. */
+ void otr_gui_gone_insecure(void *opdata, ConnContext *context) {
+ DEBUGOUT_T("OTR_GUI_GONE_INSECURE")
+ TCHAR buff[512];
+ mir_sntprintf(buff, 512, TranslateT(LANG_SESSION_TERMINATED_BY_OTR), contact_get_nameT((HANDLE)opdata));
+ //MessageBox(0, buff, Translate("OTR Information"), MB_OK);
+ ShowMessage((HANDLE)opdata, buff);
+
+ // opdata is hContact
+ SetEncryptionStatus((HANDLE)opdata, otr_context_get_trust(context));
+ }
+
+ /* We have completed an authentication, using the D-H keys we
+ * already knew. is_reply indicates whether we initiated the AKE. */
+ void otr_gui_still_secure(void *opdata, ConnContext *context, int is_reply) {
+ DEBUGOUT_T("OTR_GUI_STILL_SECURE")
+ TrustLevel trusted = otr_context_get_trust(context);
+ SetEncryptionStatus((HANDLE)opdata, trusted);
+ TCHAR buff[1024];
+ if(!is_reply) {
+ if(trusted == TRUST_PRIVATE) {
+ mir_sntprintf(buff, 1024, TranslateT(LANG_SESSION_CONTINUE_OTR), contact_get_nameT((HANDLE)opdata));
+ } else if (trusted == TRUST_UNVERIFIED) {
+ if (options.autoshow_verify) VerifyContextDialog(context);
+ mir_sntprintf(buff, 1024, TranslateT(LANG_SESSION_CONTINUE_OTR_VERIFY), contact_get_nameT((HANDLE)opdata));
+ } else { // should never happen
+ mir_sntprintf(buff, 1024, TranslateT(LANG_SESSION_NOT_STARTED_OTR), contact_get_nameT((HANDLE)opdata));
+ }
+ // opdata is hContact
+ ShowMessage((HANDLE)opdata, buff);
+ } else {
+ if(trusted == TRUST_PRIVATE) {
+ mir_sntprintf(buff, 1024, TranslateT(LANG_SESSION_HAS_CONTINUE_OTR), contact_get_nameT((HANDLE)opdata));
+ } else if (trusted == TRUST_UNVERIFIED) {
+ mir_sntprintf(buff, 1024, TranslateT(LANG_SESSION_HAS_CONTINUE_OTR_VERIFY), contact_get_nameT((HANDLE)opdata));
+ } else { // should never happen
+ mir_sntprintf(buff, 1024, TranslateT(LANG_SESSION_NOT_STARTED_OTR), contact_get_nameT((HANDLE)opdata));
+ }
+
+ }
+ SetEncryptionStatus((HANDLE)opdata, trusted);
+ }
+
+ /* Log a message. The passed message will end in "\n". */
+ void otr_gui_log_message(void *opdata, const char *message) {
+ //MessageBox(0, message, Translate("OTR Log Message"), MB_OK);
+ //ShowMessageInline((HANDLE)opdata, message);
+#ifdef _DEBUG
+ char* msg = strcpy((char*)mir_alloc(strlen(message)+15), "OTR message: ");
+ strcat(msg, message);
+ DEBUGOUTA(msg)
+ mir_free(msg);
+#endif
+ }
+
+ int max_message_size(void *opdata, ConnContext *context) {
+ int s = CallProtoService(context->protocol, PS_GETCAPS, PFLAG_MAXLENOFMESSAGE, 0);
+ return s;
+ }
+
+ const char *account_name(void *opdata, const char *account, const char *protocol) {
+ return account;
+ }
+
+ void account_name_free(void *opdata, const char *account_name) {
+ }
+
+ void add_appdata(void *data, ConnContext *context) {
+ if(context) context->app_data = data;
+ }
+}
+
+// Forward decl
+gcry_error_t otrl_privkey_write_FILEp(OtrlUserState us, FILE *privf);
+/* Generate a private DSA key for a given account, storing it into a
+ * file on disk, and loading it into the given OtrlUserState. Overwrite any
+ * previously generated keys for that account in that OtrlUserState. */
+gcry_error_t otrl_privkey_write(OtrlUserState us, const char *filename)
+{
+ gcry_error_t err;
+ FILE *privf;
+#ifndef WIN32
+ mode_t oldmask;
+#endif
+
+#ifndef WIN32
+ oldmask = umask(077);
+#endif
+ privf = fopen(filename, "w+b");
+ if (!privf) {
+#ifndef WIN32
+ umask(oldmask);
+#endif
+ err = gcry_error_from_errno(errno);
+ return err;
+ }
+
+ err = otrl_privkey_write_FILEp(us, privf);
+
+ fclose(privf);
+#ifndef WIN32
+ umask(oldmask);
+#endif
+ return err;
+}
+
+/* Just store the private keys of an OtrlUserState.
+ * The FILE* must be open for reading and writing. */
+gcry_error_t otrl_privkey_write_FILEp(OtrlUserState us, FILE *privf)
+{
+ OtrlPrivKey *p;
+
+ if (!privf) return gcry_error(GPG_ERR_NO_ERROR);
+
+
+
+ /* Output the other keys we know */
+ fprintf(privf, "(privkeys\n");
+ for (p=us->privkey_root; p; p=p->next) {
+ otrl_account_write(privf, p->accountname, p->protocol, p->privkey);
+ }
+ if ( fprintf(privf, ")\n") < 0 )
+ return gcry_error_from_errno(errno);
+ return gcry_error(GPG_ERR_NO_ERROR);
+
+} \ No newline at end of file