From 4c78e956c61c76a3e93e289b112c1cd31eab0d18 Mon Sep 17 00:00:00 2001 From: Jay Threeth Date: Sat, 2 Apr 2011 10:18:40 -0700 Subject: checkpoint, non functional --- linden/indra/cmake/00-Common.cmake | 13 + linden/indra/cmake/Variables.cmake | 1 + linden/indra/newview/llappviewer.cpp | 12 + linden/indra/newview/llfirstuse.cpp | 28 +- linden/indra/newview/llfloaterpreference.cpp | 21 + linden/indra/newview/llimpanel.cpp | 972 ++++++++++++++++++++++++++- linden/indra/newview/llviewermessage.cpp | 125 ++++ linden/indra/newview/viewer_manifest.py | 17 + 8 files changed, 1186 insertions(+), 3 deletions(-) (limited to 'linden/indra') diff --git a/linden/indra/cmake/00-Common.cmake b/linden/indra/cmake/00-Common.cmake index 3120534..583e15e 100644 --- a/linden/indra/cmake/00-Common.cmake +++ b/linden/indra/cmake/00-Common.cmake @@ -66,6 +66,10 @@ if (WINDOWS) /MP ) + add_definitions( + /DUSE_OTR=1 + ) + if(MSVC80 OR MSVC90) set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -D_SECURE_STL=0 -D_HAS_ITERATOR_DEBUGGING=0" @@ -146,6 +150,10 @@ if (LINUX) -pthread ) + add_definitions( + -DUSE_OTR=1 + ) + if (SERVER) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -ftemplate-depth-60") if (EXISTS /etc/debian_version) @@ -193,6 +201,11 @@ endif (LINUX) if (DARWIN) add_definitions(-DLL_DARWIN=1) + + add_definitions( + -DUSE_OTR=1 + ) + set(CMAKE_CXX_LINK_FLAGS "-Wl,-headerpad_max_install_names,-search_paths_first") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_CXX_LINK_FLAGS}") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mlong-branch -msse3 -mssse3 -w") diff --git a/linden/indra/cmake/Variables.cmake b/linden/indra/cmake/Variables.cmake index 18f3cdd..65fe841 100644 --- a/linden/indra/cmake/Variables.cmake +++ b/linden/indra/cmake/Variables.cmake @@ -42,6 +42,7 @@ endif (EXISTS ${CMAKE_SOURCE_DIR}/Server.cmake) if (${CMAKE_SYSTEM_NAME} MATCHES "Windows") set(WINDOWS ON BOOL FORCE) + set(USE_OTR 0) set(ARCH i686) set(LL_ARCH ${ARCH}_win32) set(LL_ARCH_DIR ${ARCH}-win32) diff --git a/linden/indra/newview/llappviewer.cpp b/linden/indra/newview/llappviewer.cpp index 18b65cc..16ff418 100644 --- a/linden/indra/newview/llappviewer.cpp +++ b/linden/indra/newview/llappviewer.cpp @@ -206,6 +206,11 @@ //---------------------------------------------------------------------------- // viewer.cpp - these are only used in viewer, should be easily moved. + +#if USE_OTR // [$PLOTR$] +#include "otr_wrapper.h" +#endif // COMPILE_OTR // [/$PLOTR$] + extern void disable_win_error_reporting(); #if LL_DARWIN @@ -3779,6 +3784,10 @@ void LLAppViewer::idle() void LLAppViewer::idleShutdown() { +#if USE_OTR // [$PLOTR$] + OTR_Wrapper::logout(); +#endif // USE_OTR // [/$PLOTR$] + // Wait for all modal alerts to get resolved if (LLModalDialog::activeCount() > 0) { @@ -4354,4 +4363,7 @@ void LLAppViewer::handleLoginComplete() gRlvHandler.processRetainedCommands(); } // [/RLVa:KB] +#if USE_OTR // [$PLOTR$] + OTR_Wrapper::init(); +#endif // USE_OTR // [/$PLOTR$] } diff --git a/linden/indra/newview/llfirstuse.cpp b/linden/indra/newview/llfirstuse.cpp index bae1ff4..a377959 100644 --- a/linden/indra/newview/llfirstuse.cpp +++ b/linden/indra/newview/llfirstuse.cpp @@ -363,6 +363,32 @@ void LLFirstUse::ClientTags() } } +#if USE_OTR // [$PLOTR$] +void LLFirstUse::callbackEmeraldOTR(const LLSD ¬ification, const LLSD &response) +{ + gSavedSettings.setWarning("EmeraldOTR", FALSE); + + S32 option = LLNotification::getSelectedOption(notification, response); + + if ( option == 0 ) + { + gSavedSettings.setU32("EmeraldUseOTR",(U32)1); + } + else if ( option == 1 ) + { + gSavedSettings.setU32("EmeraldUseOTR",(U32)2); + } +} + +void LLFirstUse::EmeraldOTR() +{ + if(gSavedSettings.getWarning("EmeraldOTR")) + { + LLNotifications::instance().add("QueryEmeraldOTR", LLSD(),LLSD(), callbackEmeraldOTR); + } +} +#endif // USE_OTR // [/$PLOTR$] + // static void LLFirstUse::useLoginScreen() { @@ -417,4 +443,4 @@ void LLFirstUse::Privacy() { LLStartUp::setStartupState(STATE_PRIVACY_LECTURED); } -} \ No newline at end of file +} diff --git a/linden/indra/newview/llfloaterpreference.cpp b/linden/indra/newview/llfloaterpreference.cpp index 0f81be6..46e6104 100644 --- a/linden/indra/newview/llfloaterpreference.cpp +++ b/linden/indra/newview/llfloaterpreference.cpp @@ -79,6 +79,10 @@ #include "llscrollcontainer.h" #include "llfloaterhardwaresettings.h" +#if USE_OTR // [$PLOTR$] +#include "otr_wrapper.h" +#endif // USE_OTR // [/$PLOTR$] + const S32 PREF_BORDER = 4; const S32 PREF_PAD = 5; const S32 PREF_BUTTON_WIDTH = 70; @@ -422,6 +426,11 @@ LLFloaterPreference::~LLFloaterPreference() void LLFloaterPreference::apply() { this->mPreferenceCore->apply(); +#if USE_OTR // [$PLOTR$] + U32 otrpref = gSavedSettings.getU32("EmeraldUseOTR"); + // otrpref: 0 == Require OTR, 1 == Request OTR, 2 == Accept OTR, 3 == Decline OTR + if (3 == otrpref) OTR_Wrapper::stopAll(); +#endif // USE_OTR // [/$PLOTR$] } @@ -473,6 +482,13 @@ void LLFloaterPreference::onBtnOK( void* userdata ) if (fp->canClose()) { fp->apply(); + +#if USE_OTR // [$PLOTR$] + U32 otrpref = gSavedSettings.getU32("EmeraldUseOTR"); + // otrpref: 0 == Require OTR, 1 == Request OTR, 2 == Accept OTR, 3 == Decline OTR + if (3 == otrpref) OTR_Wrapper::stopAll(); +#endif // USE_OTR // [/$PLOTR$] + fp->close(false); gSavedSettings.saveToFile( gSavedSettings.getString("ClientSettingsFile"), TRUE ); @@ -504,6 +520,11 @@ void LLFloaterPreference::onBtnApply( void* userdata ) } } fp->apply(); +#if USE_OTR // [$PLOTR$] + U32 otrpref = gSavedSettings.getU32("EmeraldUseOTR"); + // otrpref: 0 == Require OTR, 1 == Request OTR, 2 == Accept OTR, 3 == Decline OTR + if (3 == otrpref) OTR_Wrapper::stopAll(); +#endif // USE_OTR // [/$PLOTR$] LLPanelLogin::refreshLocation( false ); } diff --git a/linden/indra/newview/llimpanel.cpp b/linden/indra/newview/llimpanel.cpp index cfe3996..3f531aa 100644 --- a/linden/indra/newview/llimpanel.cpp +++ b/linden/indra/newview/llimpanel.cpp @@ -83,6 +83,15 @@ #include "rlvhandler.h" // [/RLVa:KB] +#if USE_OTR // [$PLOTR$] +#include "context.h" +#include "llcombobox.h" +#include "otr_wrapper.h" +#include "otr_floater_smp_dialog.h" +#include "otr_floater_smp_progress.h" +#include "mfdKeywordFloater.h" +#endif // USE_OTR // [/$PLOTR$] + // // Constants // @@ -1107,6 +1116,10 @@ LLFloaterIMPanel::LLFloaterIMPanel( mCallBackEnabled(TRUE), mSpeakers(NULL), mSpeakerPanel(NULL), +#if USE_OTR // [$PLOTR$] + mOtrSmpDialog(NULL), + mOtrSmpProgress(NULL), +#endif // USE_OTR // [/$PLOTR$] mFirstKeystrokeTimer(), mLastKeystrokeTimer() { @@ -1140,6 +1153,10 @@ LLFloaterIMPanel::LLFloaterIMPanel( mCallBackEnabled(TRUE), mSpeakers(NULL), mSpeakerPanel(NULL), +#if USE_OTR // [$PLOTR$] + mOtrSmpDialog(NULL), + mOtrSmpProgress(NULL), +#endif // USE_OTR // [/$PLOTR$] mFirstKeystrokeTimer(), mLastKeystrokeTimer(), mIMPanelType(IM_PANEL_PLAIN) @@ -1319,6 +1336,11 @@ LLFloaterIMPanel::~LLFloaterIMPanel() { mInputEditor->setFocusLostCallback( NULL ); } + +#if USE_OTR // [$PLOTR$] + if (mOtrSmpDialog) delete mOtrSmpDialog; + if (mOtrSmpProgress) delete mOtrSmpProgress; +#endif // USE_OTR // [/$PLOTR$] } BOOL LLFloaterIMPanel::postBuild() @@ -1388,6 +1410,26 @@ BOOL LLFloaterIMPanel::postBuild() childSetCommitCallback("speaker_volume", onVolumeChange, this); } +#if USE_OTR // [$PLOTR$] + if (!gOTR) OTR_Wrapper::init(); + if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) + { + LLComboBox *combo = getChild("otr_combo"); + if (!combo) + { + llwarns << "$PLOTR$ Can't find OTR control/status" << llendl; + } + else + { + llinfos << "$PLOTR$ found OTR control/status" << llendl; + combo->setCommitCallback(onClickOtr); + combo->setCallbackUserData(this); + combo->setAllowTextEntry(FALSE, 0, FALSE); + showOtrStatus(); + } + } +#endif // USE_OTR // [/$PLOTR$] + setDefaultBtn("send_btn"); return TRUE; } @@ -2112,6 +2154,786 @@ void deliver_message(const std::string& utf8_text, } } +#if USE_OTR // [$PLOTR$] +static bool g_otr_force_typing_stop = false; // ugly hack... +// sometimes we must send messages, but don't know if they are offline + +void otr_deliver_message(const std::string& utf8_text, + const LLUUID& im_session_id, + const LLUUID& other_participant_id, + EInstantMessage dialog) +{ +// llinfos +// << "$PLOTR$ message length:" << utf8_text.length() +// << " [" << utf8_text.substr(0, 24) +// << "]...[" << utf8_text.substr(utf8_text.length()-10, utf8_text.length()-1) +// << "]" << llendl; + std::string name; + gAgent.buildFullname(name); + + const LLRelationship* info = NULL; + info = LLAvatarTracker::instance().getBuddyInfo(other_participant_id); + + U8 offline = (!info || info->isOnline()) ? IM_ONLINE : IM_OFFLINE; + + // default to IM_SESSION_SEND unless it's nothing special - in + // which case it's probably an IM to everyone. + U8 new_dialog = dialog; + + if ( dialog != IM_NOTHING_SPECIAL ) + { + new_dialog = IM_SESSION_SEND; + } + if ((new_dialog == IM_NOTHING_SPECIAL) && + (g_otr_force_typing_stop || + (gSavedSettings.getBOOL("EmeraldOTRInTypingStop")))) + { + OtrlMessageType mtype = otrl_proto_message_type(utf8_text.c_str()); + switch (mtype) + { + case OTRL_MSGTYPE_UNKNOWN: + llwarns << "Sending unknown type of OTR message" << llendl; + // fall through + case OTRL_MSGTYPE_QUERY: + case OTRL_MSGTYPE_DH_COMMIT: + case OTRL_MSGTYPE_DH_KEY: + case OTRL_MSGTYPE_REVEALSIG: + case OTRL_MSGTYPE_SIGNATURE: + case OTRL_MSGTYPE_V1_KEYEXCH: + case OTRL_MSGTYPE_DATA: + case OTRL_MSGTYPE_TAGGEDPLAINTEXT: + new_dialog = IM_TYPING_STOP; + break; + case OTRL_MSGTYPE_NOTOTR: + case OTRL_MSGTYPE_ERROR: + default: + /* new_dialog = IM_NOTHING_SPECIAL */ ; + } + } + pack_instant_message( + gMessageSystem, + gAgent.getID(), + FALSE, + gAgent.getSessionID(), + other_participant_id, + name.c_str(), + utf8_text.c_str(), + offline, + (EInstantMessage)new_dialog, + im_session_id); + gAgent.sendReliableMessage(); + + // If there is a mute list and this is not a group chat... + if ( LLMuteList::getInstance() ) + { + // ... the target should not be in our mute list for some message types. + // Auto-remove them if present. + switch( dialog ) + { + case IM_NOTHING_SPECIAL: + case IM_GROUP_INVITATION: + case IM_INVENTORY_OFFERED: + case IM_SESSION_INVITE: + case IM_SESSION_P2P_INVITE: + case IM_SESSION_CONFERENCE_START: + case IM_SESSION_SEND: // This one is marginal - erring on the side of hearing. + case IM_LURE_USER: + case IM_GODLIKE_LURE_USER: + case IM_FRIENDSHIP_OFFERED: + LLMuteList::getInstance()->autoRemove(other_participant_id, LLMuteList::AR_IM); + break; + default: ; // do nothing + } + } +} + +// static +void LLFloaterIMPanel::onClickOtr(LLUICtrl* source, void* userdata) +{ + LLFloaterIMPanel* self = (LLFloaterIMPanel*) userdata; + if (self) + { + self->doOtrMenu(); + self->showOtrStatus(); + } + else + { + llwarns << "$PLOTR$ onClickOtr() can't find floater." << llendl; + } +} + +void LLFloaterIMPanel::doOtrStart() +{ + U32 otrpref = gSavedSettings.getU32("EmeraldUseOTR"); + // otrpref: 0 == Require use of OTR in IMs, 1 == Request OTR if available, 2 == Accept OTR requests, 3 == Decline use of OTR + if (3 == otrpref) + { + //otrLogMessageGetstring("otr_err_deacivated"); + showOtrStatus(); + return; + } + if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) + { + llinfos << "$PLOTR$ otr menu start/restart/refresh" << llendl; + gcry_error_t err = 0; + char *newmessage = NULL; + char my_uuid[UUID_STR_SIZE]; + char their_uuid[UUID_STR_SIZE]; + gAgent.getID().toString(&(my_uuid[0])); + mOtherParticipantUUID.toString(&(their_uuid[0])); + + const LLRelationship* info = NULL; + info = LLAvatarTracker::instance().getBuddyInfo(mOtherParticipantUUID); + if (info && (!info->isOnline())) + { + otrLogMessageGetstringName("otr_err_offline_start"); + return; + } + + if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) + { + // only try OTR for 1 on 1 IM's + err = otrl_message_sending( + gOTR->get_userstate(), + gOTR->get_uistate(), + &mSessionUUID, + my_uuid, + gOTR->get_protocolid(), + their_uuid, + "?OTRv2?", NULL, &newmessage, + NULL, NULL); + } + if (err) + { + llwarns << "$PLOTR$ OTR failed to encrypt start message" << llendl; + otrLogMessageGetstring("otr_err_failed_starting"); + return; + } + else if (newmessage) + { + // OTR encrypted the message. Handle fragmentation of the message + int context_added = 0; + ConnContext *context = getOtrContext(1, &context_added); + if (context_added) + { + llwarns << "$PLOTR$ context added *after* send start but before fragmentation." << llendl; + } + if (! context) + { + otrLogMessageGetstring("otr_err_failed_starting"); + llwarns << "$PLOTR$ can't find context, not sending start message." << llendl; + return; + } + else + { + char *extrafragment = NULL; + err = otrl_message_fragment_and_send( + gOTR->get_uistate(), + &mSessionUUID, + context, + newmessage, + OTRL_FRAGMENT_SEND_ALL, + &extrafragment); + } + if (newmessage) otrl_message_free(newmessage); + //otrLogMessageGetstringName("otr_prog_I_start"); + } + else + { + llwarns << "$PLOTR$ can't start OTR for some reason." << llendl; + otrLogMessageGetstring("otr_err_failed_starting"); + return; + } + } +} + +void LLFloaterIMPanel::doOtrStop(bool pretend_they_did) +{ + llinfos << "$PLOTR$ otr menu stop 1" << llendl; + // do not disable this bassed on gSavedSettings.getU32("EmeraldUseOTR"); + // when the user disables OTR we may still need to stop currently encrypted conversations + if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) + { + char my_uuid[UUID_STR_SIZE]; + char their_uuid[UUID_STR_SIZE]; + gAgent.getID().toString(&(my_uuid[0])); + mOtherParticipantUUID.toString(&(their_uuid[0])); + llinfos << "$PLOTR$ otr menu stop 2 their_uuid:" << mOtherParticipantUUID << llendl; + g_otr_force_typing_stop = true; // ugly hack + otrl_message_disconnect( + gOTR->get_userstate(), + gOTR->get_uistate(), + &mSessionUUID, + my_uuid, + gOTR->get_protocolid(), + their_uuid); + g_otr_force_typing_stop = false; + if (pretend_they_did) + { + otrLogMessageGetstringName("otr_prog_they_stop"); + } + else + { + //otrLogMessageGetstringName("otr_prog_I_stop"); + } + showOtrStatus(); + } +} + +void LLFloaterIMPanel::doOtrAuth() +{ + if (mOtrSmpDialog) + { + llinfos << "$PLOTR$ mOtrSmpDialog SMP already in progress, ignoring request to start it" << llendl; + return; + } + if (mOtrSmpDialog || mOtrSmpProgress) + { + llinfos << "$PLOTR$ SMP already in progress, ignoring request to start it" << llendl; + // $TODO$ Tell the user nicely to cancel the one in progress. + // $TODO$ better yet, cancel it/them for the user + return; + } + if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) + { + llinfos << "$PLOTR$ otr menu auth" << llendl; + + ConnContext *context = getOtrContext(); + if (!context) + { + llwarns << "$PLOTR$ doOtrAuth can't find context." << llendl; + return; + } + char my_uuid[UUID_STR_SIZE]; + gAgent.getID().toString(&(my_uuid[0])); + char my_fingerprint[45]; + otrl_privkey_fingerprint(gOTR->get_userstate(), + my_fingerprint, + my_uuid, + gOTR->get_protocolid()); + char other_fingerprint[45]; + otrl_privkey_hash_to_human(other_fingerprint, context->active_fingerprint->fingerprint); + startSmpDialog(mSessionUUID, mOtherParticipantUUID, + &(my_fingerprint[0]), &(other_fingerprint[0])); + } +} + +void LLFloaterIMPanel::doOtrMenu() +{ + if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) + { + LLComboBox *combo = getChild("otr_combo"); + if (!combo) + { + llwarns << "$PLOTR$ Can't find OTR control/status" << llendl; + } + else + { + std::string choice = combo->getSimple(); + if ((getString("otr_start") == choice) || + (getString("otr_restart") == choice) || + (getString("otr_refresh") == choice)) + { + doOtrStart(); + } + else if (getString("otr_stop") == choice) + { + doOtrStop(); + } + else if (getString("otr_auth") == choice) + { + doOtrAuth(); + } + else if (getString("otr_help") == choice) + { + llinfos << "$PLOTR$ otr help" << llendl; + LLWeb::loadURL("http://www.cypherpunks.ca/otr/"); + } + else if (getString("otr_levels") == choice) + { + llinfos << "$PLOTR$ otr levels help" << llendl; + LLWeb::loadURL("http://www.cypherpunks.ca/otr/help/3.2.0/levels.php"); + } + else + { + llwarns << "$PLOTR$ unknown menu item" << llendl; + } + } + } +} + +ConnContext *LLFloaterIMPanel::getOtrContext(int create_if_not_found, int *context_added) +{ + ConnContext *context = NULL; + if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) + { + char my_uuid[UUID_STR_SIZE]; + char their_uuid[UUID_STR_SIZE]; + gAgent.getID().toString(&(my_uuid[0])); + mOtherParticipantUUID.toString(&(their_uuid[0])); + context = otrl_context_find( + gOTR->get_userstate(), + their_uuid, + my_uuid, + gOTR->get_protocolid(), + create_if_not_found, context_added, NULL, NULL); + } + return context; +} + +bool LLFloaterIMPanel::otherIsOtrAuthenticated() +{ + if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) + { + ConnContext *context = getOtrContext(); + if (context && context->active_fingerprint && + context->active_fingerprint->trust && + *(context->active_fingerprint->trust)) + { + llinfos << "$PLOTR$ they are authenticated -- trust level is " + << (context->active_fingerprint->trust) << llendl; + return true; + } + } + llinfos << "$PLOTR$ they are NOT authenticated" << llendl; + return false; +} + +void LLFloaterIMPanel::showOtrStatus() +{ + if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) + { + LLComboBox *combo = getChild("otr_combo"); + if (!combo) + { + llwarns << "$PLOTR$ Can't find OTR control/status" << llendl; + } + else + { + ConnContext *context = getOtrContext(); + U32 otrpref = gSavedSettings.getU32("EmeraldUseOTR"); + // otrpref: 0 == Require OTR, 1 == Request OTR, 2 == Accept OTR, 3 == Decline OTR + if (3 == otrpref) + { + if (context && (OTRL_MSGSTATE_ENCRYPTED == context->msgstate)) + { + doOtrStop(); + } + combo->removeall(); + combo->add(getString("otr_start"), ADD_BOTTOM, TRUE); // to tell them where to turn it back on + combo->add(getString("otr_stop"), ADD_BOTTOM, FALSE); + combo->add(getString("otr_auth"), ADD_BOTTOM, FALSE); + combo->add(getString("otr_help"), ADD_BOTTOM, TRUE); + combo->add(getString("otr_levels"), ADD_BOTTOM, TRUE); + combo->setLabel(getString("otr_not_private")); + } + else if (context && (OTRL_MSGSTATE_ENCRYPTED == context->msgstate)) + { + combo->removeall(); + combo->add(getString("otr_refresh"), ADD_BOTTOM, TRUE); + combo->add(getString("otr_stop"), ADD_BOTTOM, TRUE); + combo->add(getString("otr_auth"), ADD_BOTTOM, TRUE); + combo->add(getString("otr_help"), ADD_BOTTOM, TRUE); + combo->add(getString("otr_levels"), ADD_BOTTOM, TRUE); + if (otherIsOtrAuthenticated()) + combo->setLabel(getString("otr_private")); + else + combo->setLabel(getString("otr_unverified")); + } + else if (context && (OTRL_MSGSTATE_FINISHED == context->msgstate)) + { + if (OTRL_MSGSTATE_ENCRYPTED == mOtrLastStatus) + { + if (otherIsOtrAuthenticated()) + otrLogMessageGetstringName("otr_prog_they_stop_private"); + else + otrLogMessageGetstringName("otr_prog_they_stop_unverified"); + } + combo->removeall(); + combo->add(getString("otr_restart"), ADD_BOTTOM, TRUE); + combo->add(getString("otr_stop"), ADD_BOTTOM, TRUE); + combo->add(getString("otr_auth"), ADD_BOTTOM, FALSE); + combo->add(getString("otr_help"), ADD_BOTTOM, TRUE); + combo->add(getString("otr_levels"), ADD_BOTTOM, TRUE); + combo->setLabel(getString("otr_finished")); + } + else // OTRL_MSGSTATE_PLAINTEXT, or no context yet + { + combo->removeall(); + combo->add(getString("otr_start"), ADD_BOTTOM, TRUE); + combo->add(getString("otr_stop"), ADD_BOTTOM, FALSE); + combo->add(getString("otr_auth"), ADD_BOTTOM, FALSE); + combo->add(getString("otr_help"), ADD_BOTTOM, TRUE); + combo->add(getString("otr_levels"), ADD_BOTTOM, TRUE); + combo->setLabel(getString("otr_not_private")); + } + if (context) + { + mOtrLastStatus = context->msgstate; + } + } + } +} + +void LLFloaterIMPanel::otrLogMessage(std::string message) +{ + addHistoryLine(message, gSavedSettings.getColor("SystemChatColor"), true, mOtherParticipantUUID); +} + +void LLFloaterIMPanel::otrLogMessageGetstring(const char *message_name) +{ + LLUIString msg = getString(message_name); + otrLogMessage(msg); +} + +void LLFloaterIMPanel::otrLogMessageGetstringName(const char *message_name) +{ + LLUIString msg = getString(message_name); + std::string them; + if (!gCacheName->getFullName(mOtherParticipantUUID, them)) them = getString("otr_generic_name"); + msg.setArg("[NAME]", them); + otrLogMessage(msg); +} + +void otr_log_message(LLUUID session_id, const char *message) +{ + LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(session_id); + if (floater) floater->otrLogMessage(message); + else + { + llinfos << "$PLOTR$ otr_log_message(" << message << ") failed to find floater." << llendl; + } +} + +void otr_log_message_getstring(LLUUID session_id, const char *message_name) +{ + LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(session_id); + if (floater) floater->otrLogMessageGetstring(message_name); + else + { + llinfos << "$PLOTR$ otr_log_message_getstring(" << message_name << ") failed to find floater." << llendl; + } +} + +void otr_log_message_getstring_name(LLUUID session_id, const char *message_name) +{ + LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(session_id); + if (floater) floater->otrLogMessageGetstringName(message_name); + else + { + llinfos << "$PLOTR$ otr_log_message_getstring_name(" << message_name << ") failed to find floater." << llendl; + } +} + +void LLFloaterIMPanel::otrAuthenticateKey(const char *trust) +{ + int context_added = 0; + ConnContext *context = getOtrContext(0, &context_added); + if (gOTR && context) + { + otrl_context_set_trust(context->active_fingerprint, trust); + otrLogMessageGetstringName("otr_log_authenticated"); + otrLogMessageGetstringName("otr_log_start_private"); + std::string pubpath = + gDirUtilp->getExpandedFilename( + LL_PATH_PER_SL_ACCOUNT, OTR_PUBLIC_KEYS_FILE); + otrl_privkey_write_fingerprints(gOTR->get_userstate(), pubpath.c_str()); + showOtrStatus(); + } +} + +void otr_authenticate_key(LLUUID session_id, const char *trust) +{ + LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(session_id); + if (floater) floater->otrAuthenticateKey(trust); + else + { + llinfos << "$PLOTR$ otr_authenticate_key(" << session_id << ", " << trust << ") failed to find floater." << llendl; + } +} + +void otr_show_status(LLUUID session_id) +{ + LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(session_id); + if (floater) floater->showOtrStatus(); + else + { + llinfos << "$PLOTR$ can't find floater." << llendl; + } +} + +void LLFloaterIMPanel::pretendTheyOtrStop() +{ + llinfos << "$PLOTR$ pretending they did doOtrStop()" << llendl; + // we really stop our end, but... + doOtrStop(true); // ... pretend that they did it + ConnContext *context = getOtrContext(); + if (context) context->msgstate = OTRL_MSGSTATE_FINISHED; + else + { + llwarns << "$PLOTR$ can't find context." << llendl; + } + showOtrStatus(); +} + +void LLFloaterIMPanel::startSmpDialog( + LLUUID session_id, LLUUID other_id, + std::string my_fingerprint, std::string other_fingerprint) +{ + if (mOtrSmpDialog) + { + mOtrSmpDialog->close(); + delete mOtrSmpDialog; + } + mOtrSmpDialog = new OtrFloaterSmpDialog( + this, mSessionUUID, mOtherParticipantUUID, + my_fingerprint, other_fingerprint); + if (mOtrSmpDialog) mOtrSmpDialog->show(); + else + { + llwarns << "$PLOTR$ couldn't new OtrFloaterSmpDialog" << llendl; + } +} + +void LLFloaterIMPanel::startSmpDialogQA( + LLUUID session_id, LLUUID other_id, std::string question, OtrlTLV *tlv) +{ + if (mOtrSmpDialog) + { + mOtrSmpDialog->close(); + delete mOtrSmpDialog; + } + mOtrSmpDialog = new OtrFloaterSmpDialog( + this, mSessionUUID, mOtherParticipantUUID, question, tlv); + if (mOtrSmpDialog) mOtrSmpDialog->show(); + else + { + llwarns << "$PLOTR$ couldn't new OtrFloaterSmpDialog" << llendl; + } +} + +void LLFloaterIMPanel::startSmpDialogSS( + LLUUID session_id, LLUUID other_id, OtrlTLV *tlv) +{ + if (mOtrSmpDialog) + { + mOtrSmpDialog->close(); + delete mOtrSmpDialog; + } + mOtrSmpDialog = new OtrFloaterSmpDialog( + this, mSessionUUID, mOtherParticipantUUID, tlv); + if (mOtrSmpProgress) mOtrSmpDialog->show(); + else + { + llwarns << "$PLOTR$ couldn't new OtrFloaterSmpDialog" << llendl; + } +} + +void LLFloaterIMPanel::endSmpDialog() +{ + if (!mOtrSmpDialog) + { + llwarns << "$PLOTR$ couldn't find OtrFloaterSmpDialog" << llendl; + } + else + { + delete mOtrSmpDialog; + mOtrSmpDialog = NULL; + } +} + +void LLFloaterIMPanel::startSmpProgress( + LLUUID session_id, LLUUID other_id, + std::string a_question, std::string a_secret_answer, bool is_reply) +{ + if (mOtrSmpProgress) + { + mOtrSmpProgress->close(); + delete mOtrSmpProgress; + } + mOtrSmpProgress = + new OtrFloaterSmpProgress(this, mSessionUUID, mOtherParticipantUUID, + a_question, a_secret_answer, is_reply); + if (mOtrSmpProgress) mOtrSmpProgress->show(); + else + { + llwarns << "$PLOTR$ couldn't new OtrFloaterSmpProgress" << llendl; + } +} + +void LLFloaterIMPanel::startSmpProgress( + LLUUID session_id, LLUUID other_id, + std::string a_secret, bool is_reply) +{ + if (mOtrSmpProgress) + { + mOtrSmpProgress->close(); + delete mOtrSmpProgress; + } + mOtrSmpProgress = + new OtrFloaterSmpProgress(this, mSessionUUID, mOtherParticipantUUID, + a_secret, is_reply); + if (mOtrSmpProgress) mOtrSmpProgress->show(); + else + { + llwarns << "$PLOTR$ couldn't new OtrFloaterSmpProgress" << llendl; + } +} + +void LLFloaterIMPanel::endSmpProgress() +{ + if (!mOtrSmpProgress) + { + llwarns << "$PLOTR$ couldn't find OtrFloaterSmpProgress" << llendl; + } + else + { + delete mOtrSmpProgress; + mOtrSmpProgress = NULL; + } +} + +void LLFloaterIMPanel::handleOtrTlvs(OtrlTLV *tlvs) +{ + ConnContext *context = getOtrContext(); + if (! context) + { + llwarns << "$PLOTR$ Can't find otr context" << llendl; + return; + } + if (! context->smstate) + { + llwarns << "$PLOTR$ OTR context doesn't have smstate" << llendl; + return; + } + if (context->smstate->sm_prog_state == OTRL_SMP_PROG_CHEATED) + { + if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_errored"); + context->smstate->nextExpected = OTRL_SMP_EXPECT1; + context->smstate->sm_prog_state = OTRL_SMP_PROG_OK; + return; + } + NextExpectedSMP nextMsg = context->smstate->nextExpected; + OtrlTLV *tlv = NULL; + tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1Q); + if (tlv) + { + if (nextMsg != OTRL_SMP_EXPECT1) + { + if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_errored"); + return; + } + // Start a challenge SMP dialog + char *question = (char *)tlv->data; + char *eoq = (char *)memchr(question, '\0', tlv->len); + if (!eoq) + { + llwarns << "$PLOTR$ bad format in OTRL_TLV_SMP1Q, no end to question." << llendl; + if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_errored"); + return; + } + startSmpDialogQA(mSessionUUID, mOtherParticipantUUID, question, tlv); + if (mOtrSmpProgress) mOtrSmpProgress->setPercent(25); + return; + } + tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP1); + if (tlv) + { + if (nextMsg != OTRL_SMP_EXPECT1) + { + if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_errored"); + return; + } + // Start a challenge SMP dialog + startSmpDialogSS(mSessionUUID, mOtherParticipantUUID, tlv); + if (mOtrSmpProgress) mOtrSmpProgress->setPercent(25); + return; + } + tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP2); + if (tlv) + { + if (nextMsg != OTRL_SMP_EXPECT2) + { + if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_errored"); + return; + } + else + { + // If we received TLV2, we will send TLV3 and expect TLV4 + context->smstate->nextExpected = OTRL_SMP_EXPECT4; + if (mOtrSmpProgress) mOtrSmpProgress->setPercent(75); + } + } + tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP3); + if (tlv) + { + if (nextMsg != OTRL_SMP_EXPECT3) + { + if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_errored"); + return; + } + else + { + // If we received TLV3, we will send TLV4 + // We will not expect more messages, so prepare for next SMP + context->smstate->nextExpected = OTRL_SMP_EXPECT1; + // Report result to user + if (context->smstate->sm_prog_state == OTRL_SMP_PROG_SUCCEEDED) + { + if (context->active_fingerprint && + context->active_fingerprint->trust && + *(context->active_fingerprint->trust)) + { + // they authed me OK, and I already authed them in the past + if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_ok"); + } + else + { + // they authed me OK, but I haven't authed them yet + if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_ok_name_next"); + } + } + else + { + if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_failed"); + } + } + } + tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP4); + if (tlv) + { + if (nextMsg != OTRL_SMP_EXPECT4) + { + if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_errored"); + return; + } + else { + // We will not expect more messages, so prepare for next SMP + context->smstate->nextExpected = OTRL_SMP_EXPECT1; + // Report result to user + if (context->active_fingerprint && + context->active_fingerprint->trust && + *(context->active_fingerprint->trust)) + { + if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_ok"); + } + else + { + if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_failed"); + } + } + } + tlv = otrl_tlv_find(tlvs, OTRL_TLV_SMP_ABORT); + if (tlv) + { + // The message we are waiting for will not arrive, so reset + // and prepare for the next SMP + context->smstate->nextExpected = OTRL_SMP_EXPECT1; + if (mOtrSmpProgress) mOtrSmpProgress->setFinalStatus("otr_smp_prog_auth_aborted"); + } +} +#endif // USE_OTR // [/$PLOTR$] + void LLFloaterIMPanel::sendMsg() { if (!gAgent.isGodlike() @@ -2204,11 +3026,137 @@ void LLFloaterIMPanel::sendMsg() if ( mSessionInitialized ) { +#if USE_OTR // [$PLOTR$] + const LLRelationship* info = NULL; + info = LLAvatarTracker::instance().getBuddyInfo(mOtherParticipantUUID); + ConnContext *context = getOtrContext(1); + if (info && (!info->isOnline()) && context && + ( (OTRL_MSGSTATE_ENCRYPTED == context->msgstate) + || (OTRL_MSGSTATE_FINISHED == context->msgstate))) + { + // we can't continue this encrypted session but we + // can't let the user accidentally send unencrypted + if (OTRL_MSGSTATE_ENCRYPTED == context->msgstate) + pretendTheyOtrStop(); + otrLogMessageGetstringName("otr_err_offline_send"); + return; // leave the unsent message in the edit box + } + + gcry_error_t err = 0; + char *newmessage = NULL; + char my_uuid[UUID_STR_SIZE]; + char their_uuid[UUID_STR_SIZE]; + gAgent.getID().toString(&(my_uuid[0])); + mOtherParticipantUUID.toString(&(their_uuid[0])); + + bool was_finished = false; + if (gOTR && context && (context->msgstate == OTRL_MSGSTATE_FINISHED)) + { + was_finished = true; + } + else if (gOTR && (IM_NOTHING_SPECIAL == mDialog)) + { + // only try OTR for 1 on 1 IM's + err = otrl_message_sending( + gOTR->get_userstate(), + gOTR->get_uistate(), + &mSessionUUID, + my_uuid, + gOTR->get_protocolid(), + their_uuid, + &(utf8_text[0]), NULL, &newmessage, + NULL, NULL); + } + context = getOtrContext(); + if (err) + { + otrLogMessageGetstring("otr_err_failed_sending"); + return; // leave the unsent message in the edit box + } + if (was_finished) + { + llinfos << "$PLOTR$ OTR tried to send into finished conv, not sending message!" << llendl; + //otrLogMessageGetstringName("otr_err_send_in_finished"); //Don't error and tell the user to restart, just restart instead! + doOtrStart(); + return; // leave the unsent message in the edit box + } + OtrlMessageType msgtype = OTRL_MSGTYPE_NOTOTR; + if (newmessage) msgtype = otrl_proto_message_type(newmessage); + if (newmessage && (OTRL_MSGTYPE_TAGGEDPLAINTEXT == msgtype)) + { + // OTR just added the whitespace tag. + otrl_message_free(newmessage); // don't send the message with whitespace tag + err = otrl_message_sending( + gOTR->get_userstate(), + gOTR->get_uistate(), + &mSessionUUID, + my_uuid, + gOTR->get_protocolid(), + their_uuid, + "typing", NULL, &newmessage, + NULL, NULL); + if (!newmessage) + { + llwarns << "$PLOTR$ shouldn't happen, OTR should keep adding whitespace tags till we get a reply from them." << llendl; + } + else + { + // deliver a whitespace tagged "typing" in a IM_TYPING_STOP packet + std::string my_name; + gAgent.buildFullname(my_name); + const LLRelationship* info = NULL; + info = LLAvatarTracker::instance().getBuddyInfo(mOtherParticipantUUID); + U8 offline = (!info || info->isOnline()) ? IM_ONLINE : IM_OFFLINE; + pack_instant_message( + gMessageSystem, + gAgent.getID(), + FALSE, + gAgent.getSessionID(), + mOtherParticipantUUID, + my_name, + newmessage, + offline, + IM_TYPING_STOP, + mSessionUUID); + gAgent.sendReliableMessage(); + otrl_message_free(newmessage); + newmessage = NULL; + } + } + if (newmessage) + { + // OTR encrypted the message + if (! context) + { + llwarns << "$PLOTR$ can't find context, not sending message." << llendl; + otrLogMessageGetstring("otr_err_failed_sending"); + return; // leave the unsent message in the edit box + } + + { + // Handle fragmentation of the message + char *extrafragment = NULL; + err = otrl_message_fragment_and_send( + gOTR->get_uistate(), + &mSessionUUID, + context, + newmessage, + OTRL_FRAGMENT_SEND_ALL, + &extrafragment); + } + if (newmessage) otrl_message_free(newmessage); + showOtrStatus(); + } + else + { // OTR didn't encrypt, or we didn't try cause it's not 1:1 IM +#endif // USE_OTR // [/$PLOTR$] deliver_message(utf8_text, mSessionUUID, mOtherParticipantUUID, mDialog); - +#if USE_OTR // [$PLOTR$] + } +#endif // USE_OTR // [/$PLOTR$] // local echo if((mDialog == IM_NOTHING_SPECIAL) && (mOtherParticipantUUID.notNull())) @@ -2475,7 +3423,27 @@ void LLFloaterIMPanel::chatFromLogFile(LLLogChat::ELogLineType type, std::string //self->addHistoryLine(line, LLColor4::grey, FALSE); self->mHistoryEditor->appendColoredText(message, false, true, LLColor4::grey); } - +/* +// user is known to be offline when we receive this +void LLFloaterIMPanel::setOffline() +{ + if(!gAgent.isGodlike()) + { + childSetEnabled("profile_tele_btn", false); + } +#if USE_OTR // [$PLOTR$] + llinfos << "$PLOTR$ friend went offline" << llendl; + if (gOTR) + { + ConnContext *context = getOtrContext(); + if (context && (context->msgstate == OTRL_MSGSTATE_ENCRYPTED)) + { + pretendTheyOtrStop(); + } + } +#endif // USE_OTR // [/$PLOTR$] +} +*/ void LLFloaterIMPanel::showSessionStartError( const std::string& error_string) { diff --git a/linden/indra/newview/llviewermessage.cpp b/linden/indra/newview/llviewermessage.cpp index 504c193..84e2b7e 100755 --- a/linden/indra/newview/llviewermessage.cpp +++ b/linden/indra/newview/llviewermessage.cpp @@ -158,6 +158,10 @@ #include "llwindebug.h" // For the invalid message handler #endif +#if USE_OTR // [$PLOTR$] +#include "otr_wrapper.h" +#endif // USE_OTR // [/$PLOTR$] + //silly spam define D: bool dialogSpamOn; static LLFrameTimer d_spam; @@ -1582,14 +1586,135 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) is_owned_by_me = source->permYouOwner(); } +#if USE_OTR // [$PLOTR$] + std::string decrypted_msg; + bool encrypted = false; +// if ((CHAT_SOURCE_SYSTEM == chat.mSourceType) && +// ((std::string::npos != message.find("not online")) || +// (std::string::npos != message.find("stored and delivered later")))) +// { +// llinfos << "$PLOTR$ Looks like " << from_id << " went offline." << llendl; +// } + U32 otrpref = gSavedSettings.getU32("EmeraldUseOTR"); + // otrpref: 0 == Require use of OTR in IMs, 1 == Request OTR if available, 2 == Accept OTR requests, 3 == Decline use of OTR + if ((otrpref != 3) && !is_muted && (chat.mSourceType == CHAT_SOURCE_AGENT)) + { + int ignore_message = 0; + char *newmessage = NULL; + OtrlTLV *tlvs = NULL; + char my_uuid[UUID_STR_SIZE]; + char their_uuid[UUID_STR_SIZE]; + + if (gOTR && + ((IM_NOTHING_SPECIAL == dialog) || + ((IM_TYPING_STOP == dialog) && + (! ((message == "typing") || (message == "cryo::ping")))))) + { + // only try OTR for 1 on 1 IM's or special tagged typing_stop packets + gAgent.getID().toString(&(my_uuid[0])); + from_id.toString(&(their_uuid[0])); + ignore_message = otrl_message_receiving( + gOTR->get_userstate(), + gOTR->get_uistate(), + &session_id, + my_uuid, + gOTR->get_protocolid(), + their_uuid, + &(message[0]), &newmessage, + &tlvs, + NULL, NULL); + } + if (tlvs) + { + llinfos << "$PLOTR$ recieved TLVs" << llendl; + LLUUID session = LLIMMgr::computeSessionID(dialog,from_id); + + if(!otrl_tlv_find(tlvs, OTRL_TLV_DISCONNECTED)) + { + // currently the only TLVs we deal with are SMP, and they require an IM panel + if(!gIMMgr->hasSession(session)) + { + gIMMgr->addSession(name,IM_NOTHING_SPECIAL,from_id); + } + + } + LLFloaterIMPanel* pan = gIMMgr->findFloaterBySession(session); + if (pan) pan->handleOtrTlvs(tlvs); + otrl_tlv_free(tlvs); + } + if (1 == ignore_message) + { + OtrlMessageType msgtype = otrl_proto_message_type(&(message[0])); + if (OTRL_MSGTYPE_NOTOTR == msgtype) + { + llinfos << "$PLOTR$ [not otr, but to be ignored (" << message << ")]" << llendl; + if ((0 == otrpref) && (IM_NOTHING_SPECIAL == dialog) && !is_muted) + { + LLUUID session = LLIMMgr::computeSessionID(dialog,from_id); + if(!gIMMgr->hasSession(session)) + { + gIMMgr->addSession(name,IM_NOTHING_SPECIAL,from_id); + } + // NOT deliver_otr_message since those might go via typing_stop + deliver_message( // $TODO$ move the following message to some .xml file + "/me's settings require OTR encrypted instant messages. Your message was not displayed.", + session, from_id, IM_NOTHING_SPECIAL); + LLFloaterIMPanel* pan = gIMMgr->findFloaterBySession(session); + if(pan)pan->doOtrStart(); + } + } + else + { + // an internal OTR protocol message was recieved, don't show anything to the user + llinfos << "$PLOTR$ [OTR PROTOCOL MESSAGE (" << message << ")]" << llendl; + } + otr_show_status(session_id); + return; + } + if (newmessage) + { + // message was processed by OTR. Maybe decrypted, maybe just stripping off the + // white-space "I have OTR" tag + decrypted_msg = newmessage; // use processed message + message = newmessage; // use processed message + otrl_message_free(newmessage); + ConnContext *context = otrl_context_find( + gOTR->get_userstate(), + their_uuid, + my_uuid, + gOTR->get_protocolid(), + 0, NULL, NULL, NULL); + encrypted = (context && (OTRL_MSGSTATE_ENCRYPTED == context->msgstate)); + if (IM_TYPING_STOP == dialog) + { + if ("typing" == message) return; // don't display whitespace tagged "typing" stop messages + dialog = IM_NOTHING_SPECIAL; // display messages received in typing_stop packets + } + } + } + +#endif // USE_OTR // [/$PLOTR$] + std::string separator_string(": "); int message_offset = 0; +#if USE_OTR // [$PLOTR$] + if(encrypted) + { + separator_string = "\xe2\x80\xa7: "; + message = decrypted_msg; + } +#endif // USE_OTR // [/$PLOTR$] + //Handle IRC styled /me messages. std::string prefix = message.substr(0, 4); if (prefix == "/me " || prefix == "/me'") { +#if USE_OTR // [$PLOTR$] + separator_string = encrypted ? "\xe2\x80\xa7" : ""; +#else separator_string = ""; +#endif // USE_OTR // [/$PLOTR$] message_offset = 3; } diff --git a/linden/indra/newview/viewer_manifest.py b/linden/indra/newview/viewer_manifest.py index 3a7039b..0008e45 100755 --- a/linden/indra/newview/viewer_manifest.py +++ b/linden/indra/newview/viewer_manifest.py @@ -596,6 +596,19 @@ class DarwinManifest(ViewerManifest): self.path("libopenal.1.dylib") self.path("libalut.0.dylib") + # otr lib and deps + self.path("libotr.dylib"); + self.path("libintl.8.dylib"); + self.path("libgcrypt.11.dylib"); + self.path("libgpg-error.0.dylib"); + self.path("libiconv.2.dylib"); + # self.path("../../libraries/universal-darwin/lib_release/libotr.dylib", "MacOS/libotr.dylib"); + # self.path("../../libraries/universal-darwin/lib_release/libintl.8.dylib", "MacOS/libintl.8.dylib"); + # self.path("../../libraries/universal-darwin/lib_release/libgcrypt.11.dylib", "MacOS/libgcrypt.11.dylib"); + # self.path("../../libraries/universal-darwin/lib_release/libgpg-error.0.dylib", "MacOS/libgpg-error.0.dylib"); + # self.path("../../libraries/universal-darwin/lib_release/libiconv.2.dylib", "MacOS/libiconv.2.dylib"); + + # self.path("libglib-2.0.dylib") # self.path("libgmodule-2.0.dylib") # self.path("libgobject-2.0.dylib") @@ -1105,6 +1118,8 @@ class Linux_i686Manifest(LinuxManifest): #self.end_prefix("gstreamer-plugins") + self.path("libotr.so.2.2.0") + self.path("libotr.so.2") self.end_prefix("lib") # Vivox runtimes and libs @@ -1237,6 +1252,8 @@ class Linux_x86_64Manifest(LinuxManifest): #self.path("libgstwavparse.so") #self.end_prefix("gstreamer-plugins") + self.path("libotr.so.2.2.0") + self.path("libotr.so.2") self.end_prefix("lib64") -- cgit v1.1 From 93cdc938be59db040fa2eb26c478d2328c34da7b Mon Sep 17 00:00:00 2001 From: Jay Threeth Date: Sat, 2 Apr 2011 18:56:23 -0700 Subject: checkpoint, non functional --- linden/indra/cmake/gpg.vs.cmake | 6 + linden/indra/cmake/libgcrypt.cmake | 8 + linden/indra/cmake/libgpg-error.cmake | 8 + linden/indra/cmake/libotr.cmake | 8 + linden/indra/cmake/libotrb.cmake | 4 + linden/indra/newview/app_settings/settings.xml | 71 +++ linden/indra/newview/llfirstuse.h | 4 + linden/indra/newview/llimpanel.h | 60 ++- linden/indra/newview/llprefsadvanced.cpp | 19 + linden/indra/newview/llstartup.cpp | 13 +- linden/indra/newview/otr_floater_smp_dialog.cpp | 438 ++++++++++++++++++ linden/indra/newview/otr_floater_smp_dialog.h | 63 +++ linden/indra/newview/otr_floater_smp_progress.cpp | 288 ++++++++++++ linden/indra/newview/otr_floater_smp_progress.h | 61 +++ linden/indra/newview/otr_wrapper.cpp | 487 +++++++++++++++++++++ linden/indra/newview/otr_wrapper.h | 58 +++ .../default/xui/en-us/floater_instant_message.xml | 40 ++ .../skins/default/xui/en-us/notifications.xml | 23 + .../default/xui/en-us/otr_floater_smp_dialog.xml | 131 ++++++ .../default/xui/en-us/otr_floater_smp_progress.xml | 52 +++ .../xui/en-us/panel_preferences_advanced.xml | 43 ++ 21 files changed, 1883 insertions(+), 2 deletions(-) create mode 100644 linden/indra/cmake/gpg.vs.cmake create mode 100644 linden/indra/cmake/libgcrypt.cmake create mode 100644 linden/indra/cmake/libgpg-error.cmake create mode 100644 linden/indra/cmake/libotr.cmake create mode 100644 linden/indra/cmake/libotrb.cmake create mode 100644 linden/indra/newview/otr_floater_smp_dialog.cpp create mode 100644 linden/indra/newview/otr_floater_smp_dialog.h create mode 100644 linden/indra/newview/otr_floater_smp_progress.cpp create mode 100644 linden/indra/newview/otr_floater_smp_progress.h create mode 100644 linden/indra/newview/otr_wrapper.cpp create mode 100644 linden/indra/newview/otr_wrapper.h create mode 100644 linden/indra/newview/skins/default/xui/en-us/otr_floater_smp_dialog.xml create mode 100644 linden/indra/newview/skins/default/xui/en-us/otr_floater_smp_progress.xml (limited to 'linden/indra') diff --git a/linden/indra/cmake/gpg.vs.cmake b/linden/indra/cmake/gpg.vs.cmake new file mode 100644 index 0000000..a5220f4 --- /dev/null +++ b/linden/indra/cmake/gpg.vs.cmake @@ -0,0 +1,6 @@ +# -*- cmake -*- + +# gpg.vs is just a place to put windows specific nastyness needed to +# make the libgcrypt, libgpg-error, and libotr compile. + +set(gpg.vs_INCLUDE_DIRS ) diff --git a/linden/indra/cmake/libgcrypt.cmake b/linden/indra/cmake/libgcrypt.cmake new file mode 100644 index 0000000..0134618 --- /dev/null +++ b/linden/indra/cmake/libgcrypt.cmake @@ -0,0 +1,8 @@ +# -*- cmake -*- + +set(LIBGCRYPT_INCLUDE_DIRS + ) + +set(LIBGCRYPT_LIBRARIES + libgcrypt + ) diff --git a/linden/indra/cmake/libgpg-error.cmake b/linden/indra/cmake/libgpg-error.cmake new file mode 100644 index 0000000..71deeaa --- /dev/null +++ b/linden/indra/cmake/libgpg-error.cmake @@ -0,0 +1,8 @@ +# -*- cmake -*- + +set(LIBGPG-ERROR_INCLUDE_DIRS + ) + +set(LIBGPG-ERROR_LIBRARIES + libgpg-error + ) diff --git a/linden/indra/cmake/libotr.cmake b/linden/indra/cmake/libotr.cmake new file mode 100644 index 0000000..3c07be2 --- /dev/null +++ b/linden/indra/cmake/libotr.cmake @@ -0,0 +1,8 @@ +# -*- cmake -*- + +set(LIBOTR_INCLUDE_DIRS + ) + +set(LIBOTR_LIBRARIES + libotr + ) diff --git a/linden/indra/cmake/libotrb.cmake b/linden/indra/cmake/libotrb.cmake new file mode 100644 index 0000000..eb8522f --- /dev/null +++ b/linden/indra/cmake/libotrb.cmake @@ -0,0 +1,4 @@ +# -*- cmake -*- +include(Prebuilt) + +set(OTR_LIBRARY otr) diff --git a/linden/indra/newview/app_settings/settings.xml b/linden/indra/newview/app_settings/settings.xml index b6858b7..e55684a 100644 --- a/linden/indra/newview/app_settings/settings.xml +++ b/linden/indra/newview/app_settings/settings.xml @@ -198,6 +198,30 @@ Value 0 + + EmeraldUseOTR + + Comment + Setting this to 0 will require the use of OTR in every IM, 1 will try OTR when available, 2 will accept incoming OTR requests, and 3 will deny OTR usage + Persist + 1 + Type + U32 + Value + 2 + + EmeraldOTRInTypingStop + + Comment + Setting this to true will make all encrypted OTR messages be sent in an IM_TYPING_STOP packet. This is non-standard behavior, but prevents OTR encrypted IM from being saved and delivered as offline IM. Though it currently works the grid owners may decide to disable the feature at any time. + Persist + 1 + Type + Boolean + Value + 0 + + AppearanceAnimate Comment @@ -5644,6 +5668,40 @@ 0 + + OtrFloaterSmpDialogRect + + Comment + Rectangle for OTR's Authorize Buddy Dialog + Persist + 1 + Type + Rect + Value + + 0 + 440 + 470 + 0 + + + OtrFloaterSmpProgRect + + Comment + Rectangle for OTR's Authorize Buddy Progress bar Dialog + Persist + 1 + Type + Rect + Value + + 0 + 440 + 470 + 0 + + + FloaterActiveSpeakersRect Comment @@ -13805,6 +13863,19 @@ Value 1 + + WarnEmeraldOTR + + Comment + Enables OTR info dialog + Persist + 1 + Type + Boolean + Value + 1 + + WarnFirstAppearance Comment diff --git a/linden/indra/newview/llfirstuse.h b/linden/indra/newview/llfirstuse.h index 8c2ca35..c7a3634 100644 --- a/linden/indra/newview/llfirstuse.h +++ b/linden/indra/newview/llfirstuse.h @@ -115,6 +115,10 @@ public: static void useLoginScreen(); static void callbackClientTags(const LLSD& notification, const LLSD& response); static void ClientTags(); +#if USE_OTR // [$PLOTR$] + static void callbackEmeraldOTR(const LLSD& notification, const LLSD& response); + static void EmeraldOTR(); +#endif // USE_OTR // [/$PLOTR$] static void voiceLicenseAgreement(); static void callbackPrivacy(const LLSD& notification, const LLSD& response); static void Privacy(); diff --git a/linden/indra/newview/llimpanel.h b/linden/indra/newview/llimpanel.h index b5a0165..5a36648 100644 --- a/linden/indra/newview/llimpanel.h +++ b/linden/indra/newview/llimpanel.h @@ -42,6 +42,12 @@ #include "llvoiceclient.h" #include "llstyle.h" +#if USE_OTR // [$PLOTR$] +# include "otr_wrapper.h" +class OtrFloaterSmpDialog; +class OtrFloaterSmpProgress; +#endif // USE_OTR // [/$PLOTR$] + class LLLineEditor; class LLViewerTextEditor; class LLInventoryItem; @@ -175,6 +181,22 @@ private: BOOL mReceivedCall; }; +#if USE_OTR // [$PLOTR$] +extern void otr_authenticate_key(LLUUID session_id, const char *trust); +extern void otr_log_message_getstring_name(LLUUID session_id, const char *message_name); +extern void otr_log_message_getstring(LLUUID session_id, const char *message_name); +extern void otr_log_message(LLUUID session_id, const char *message); +extern void otr_show_status(LLUUID session_id); +extern void otr_deliver_message(const std::string& utf8_text, + const LLUUID& im_session_id, + const LLUUID& other_participant_id, + EInstantMessage dialog); +extern void deliver_message(const std::string& utf8_text, + const LLUUID& im_session_id, + const LLUUID& other_participant_id, + EInstantMessage dialog); +#endif // USE_OTR // [/$PLOTR$] + class LLFloaterIMPanel : public LLFloater { public: @@ -299,7 +321,43 @@ private: void removeTypingIndicator(const LLIMInfo* im_info); void sendTypingState(BOOL typing); - + +#if USE_OTR // [$PLOTR$] +public: + static void onClickOtr(LLUICtrl* source, void* userdata); + void doOtrMenu(); + void showOtrStatus(); + void otrLogMessage(std::string message); + void otrLogMessageGetstring(const char *message_name); + void otrLogMessageGetstringName(const char *message_name); + bool otherIsOtrAuthenticated(); + void otrAuthenticateKey(const char *trust); + void doOtrStart(); + void doOtrStop(bool pretend_they_did=false); + void pretendTheyOtrStop(); + ConnContext *getOtrContext(int add_if_not = 0, int *context_added = NULL); + void startSmpProgress(LLUUID session_id, LLUUID other_id, + std::string a_question, std::string a_secret_answer, + bool is_reply = false); + void startSmpProgress(LLUUID session_id, LLUUID other_id, + std::string a_secret, + bool is_reply = false); + void endSmpProgress(); + void endSmpDialog(); + void handleOtrTlvs(OtrlTLV *tlvs); +private: + void startSmpDialog(LLUUID session_id, LLUUID other_id, + std::string my_fingerprint, std::string other_fingerprint); + void startSmpDialogQA(LLUUID session_id, LLUUID other_id, + std::string question, OtrlTLV *tlv); + void startSmpDialogSS(LLUUID session_id, LLUUID other_id, + OtrlTLV *tlv); + void doOtrAuth(); + OtrlMessageState mOtrLastStatus; + OtrFloaterSmpDialog *mOtrSmpDialog; + OtrFloaterSmpProgress *mOtrSmpProgress; +#endif // USE_OTR // [/$PLOTR$] + private: LLLineEditor* mInputEditor; LLViewerTextEditor* mHistoryEditor; diff --git a/linden/indra/newview/llprefsadvanced.cpp b/linden/indra/newview/llprefsadvanced.cpp index 99bc4fd..17f7b09 100644 --- a/linden/indra/newview/llprefsadvanced.cpp +++ b/linden/indra/newview/llprefsadvanced.cpp @@ -47,6 +47,10 @@ #include "boost/algorithm/string.hpp" +#if USE_OTR // [$PLOTR$] +#include "llweb.h" +#endif // USE_OTR // [/$PLOTR$] + LLPrefsAdvanced* LLPrefsAdvanced::sInstance; LLPrefsAdvanced::LLPrefsAdvanced() @@ -116,6 +120,11 @@ BOOL LLPrefsAdvanced::postBuild() initHelpBtn("EmeraldHelp_SpellCheck", "EmeraldHelp_SpellCheck"); +#if USE_OTR // [$PLOTR$] + childSetValue("EmeraldUseOTR", LLSD((S32)gSavedSettings.getU32("EmeraldUseOTR"))); + getChild("otr_help_btn")->setClickedCallback(onClickOtrHelp, this); +#endif // USE_OTR // [/$PLOTR$] + refresh(); return TRUE; @@ -202,6 +211,9 @@ void LLPrefsAdvanced::apply() LLComboBox* crash_behavior_combobox = getChild("crash_behavior_combobox"); gCrashSettings.setS32(CRASH_BEHAVIOR_SETTING, crash_behavior_combobox->getCurrentIndex()); +#if USE_OTR // [$PLOTR$] + gSavedSettings.setU32("EmeraldUseOTR", (U32)childGetValue("EmeraldUseOTR").asReal()); +#endif // USE_OTR // [/$PLOTR$] } void LLPrefsAdvanced::cancel() @@ -349,3 +361,10 @@ void LLPrefsAdvanced::onClickCommandLine(void* data) FloaterCommandLine::getInstance()->open(); FloaterCommandLine::getInstance()->center(); } + +#if USE_OTR // [$PLOTR$] +void LLPrefsAdvanced::onClickOtrHelp(void* data) +{ + LLWeb::loadURL("http://www.cypherpunks.ca/otr/"); +} +#endif // USE_OTR // [/$PLOTR$] diff --git a/linden/indra/newview/llstartup.cpp b/linden/indra/newview/llstartup.cpp index d9ab5e7..d13e112 100644 --- a/linden/indra/newview/llstartup.cpp +++ b/linden/indra/newview/llstartup.cpp @@ -215,6 +215,10 @@ #include "hippogridmanager.h" #include "hippolimits.h" +#if USE_OTR // [$PLOTR$] +#include "otr_wrapper.h" +#endif // USE_OTR // [/$PLOTR$] + #include "lggautocorrect.h" // // exported globals @@ -2825,6 +2829,9 @@ bool idle_startup() } LLFirstUse::ClientTags(); +#if USE_OTR // [$PLOTR$] + LLFirstUse::EmeraldOTR(); +#endif // USE_OTR // [/$PLOTR$] // Add login location to teleport history 'teleported-into' LLVector3 agent_pos=gAgent.getPositionAgent(); @@ -2867,7 +2874,11 @@ bool idle_startup() { gAgent.requestEnterGodMode(); } - + +#if USE_OTR // [$PLOTR$] + OTR_Wrapper::init(); +#endif // USE_OTR // [/$PLOTR$] + // Start automatic replay if the flag is set. if (gSavedSettings.getBOOL("StatsAutoRun")) { diff --git a/linden/indra/newview/otr_floater_smp_dialog.cpp b/linden/indra/newview/otr_floater_smp_dialog.cpp new file mode 100644 index 0000000..06acdae --- /dev/null +++ b/linden/indra/newview/otr_floater_smp_dialog.cpp @@ -0,0 +1,438 @@ +/* otr_floater_smp_dialog.cpp - SMP dialog box + $PLOTR$ See http://www.cypherpunks.ca/otr/ + + Copyright (C) 2009 Chris Tuchs + + This is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the viewer; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#include "llviewerprecompiledheaders.h" + +#include "llagent.h" +#include "llcachename.h" +#include "llcombobox.h" +#include "llimpanel.h" +#include "lluictrlfactory.h" +#include "llweb.h" + +#include "otr_floater_smp_progress.h" +#include "otr_floater_smp_dialog.h" + +std::string OtrFloaterSmpDialog::getStringName(const char *message_name) +{ + LLUIString message = getString(message_name); + std::string them; + if (!gCacheName->getFullName(mOtherParticipantUUID, them)) them = getString("otr_generic_name"); + message.setArg("[NAME]", them); + return message.getString(); +} + +void OtrFloaterSmpDialog::init() +{ + LLUICtrlFactory::getInstance()->buildFloater(this, "otr_floater_smp_dialog.xml"); +} + +OtrFloaterSmpDialog::OtrFloaterSmpDialog( + LLFloaterIMPanel *im_panel, LLUUID session_id, LLUUID other_id, + std::string my_fingerprint, std::string other_fingerprint) + : LLFloater(std::string("otr_floater_smp_dialog"), std::string("OtrFloaterSmpDialogRect"), LLStringUtil::null), + mIMPanel(im_panel), mIsReply(false), + mSessionUUID(session_id), mOtherParticipantUUID(other_id), + mQuestion(""), + mMyFingerprint(my_fingerprint), mOtherFingerprint(other_fingerprint) +{ + init(); +} + +OtrFloaterSmpDialog::OtrFloaterSmpDialog( + LLFloaterIMPanel *im_panel, LLUUID session_id, LLUUID other_id, + std::string question, OtrlTLV *tlv) + : LLFloater(std::string("otr_floater_smp_dialog"), std::string("OtrFloaterSmpDialogRect"), LLStringUtil::null), + mIMPanel(im_panel), mIsReply(true), + mSessionUUID(session_id), mOtherParticipantUUID(other_id), + mQuestion(question), + mMyFingerprint(""), mOtherFingerprint("") +{ + init(); + LLComboBox *combo = getChild("otr_smp_how_combo"); + if (!combo) + { + llwarns << "$PLOTR$ Can't find OTR SMP how combo" << llendl; + return; + } + combo->removeall(); + combo->add(getString("otr_smp_how_by_qa_challenge"), ADD_BOTTOM, TRUE); + combo->selectFirstItem(); + doComboMenu(); +} + +OtrFloaterSmpDialog::OtrFloaterSmpDialog( + LLFloaterIMPanel *im_panel, LLUUID session_id, LLUUID other_id, + OtrlTLV *tlv) + : LLFloater(std::string("otr_floater_smp_dialog"), std::string("OtrFloaterSmpDialogRect"), LLStringUtil::null), + mIMPanel(im_panel), mIsReply(true), + mSessionUUID(session_id), mOtherParticipantUUID(other_id), + mQuestion(""), + mMyFingerprint(""), mOtherFingerprint("") +{ + init(); + LLComboBox *combo = getChild("otr_smp_how_combo"); + if (!combo) + { + llwarns << "$PLOTR$ Can't find OTR SMP how combo" << llendl; + return; + } + combo->removeall(); + combo->add(getString("otr_smp_how_by_ss_challenge"), ADD_BOTTOM, TRUE); + combo->selectFirstItem(); + doComboMenu(); +} + +OtrFloaterSmpDialog::~OtrFloaterSmpDialog() +{ +} + +BOOL OtrFloaterSmpDialog::postBuild() +{ + childSetAction("otr_smp_help_btn", onClickHelp, this); + childSetAction("otr_smp_cancel_btn", onClickCancel, this); + childSetAction("otr_smp_auth_btn", onClickAuth, this); + LLComboBox *veri = getChild("otr_smp_veri_combo"); + veri->setCommitCallback(onClickVeri); + veri->setCallbackUserData(this); + LLComboBox *combo = getChild("otr_smp_how_combo"); + combo->setCommitCallback(onClickCombo); + combo->setCallbackUserData(this); + combo->removeall(); + combo->add(getString("otr_smp_how_by_qa"), ADD_BOTTOM, TRUE); + combo->add(getString("otr_smp_how_by_ss"), ADD_BOTTOM, TRUE); + combo->add(getString("otr_smp_how_by_mfv"), ADD_BOTTOM, TRUE); + combo->selectFirstItem(); + doComboMenu(); + LLTextBox *why = getChild("otr_smp_why"); + if (why) why->setWrappedText(getString("otr_smp_why_text")); + LLTextBox *how = getChild("otr_smp_how_text"); + if (mIsReply) + { + if (how) how->setWrappedText(getStringName("otr_smp_how_name_challenge_me")); + setTitle(getStringName("otr_smp_name_auth_me")); + } + else + { + if (how) how->setWrappedText(getStringName("otr_smp_how_I_challenge_name")); + setTitle(getStringName("otr_smp_I_auth_name")); + } + return TRUE; +} + +void OtrFloaterSmpDialog::show() +{ + this->open(); /*Flawfinder: ignore*/ + this->setFocus(TRUE); + this->center(); +} + +void OtrFloaterSmpDialog::doVeriMenu() +{ + LLComboBox *veri = getChild("otr_smp_veri_combo"); + if (!veri) + { + llwarns << "$PLOTR$ Can't find OTR SMP verified combo" << llendl; + return; + } + LLButton* auth_btn = getChild("otr_smp_auth_btn"); + if (!auth_btn) + { + llwarns << "$PLOTR$ Can't find OTR SMP authenticate button" << llendl; + return; + } + if (getString("otr_smp_veri_no") == veri->getSimple()) + { + auth_btn->setEnabled(FALSE); + } + else + { + auth_btn->setEnabled(TRUE); + } +} + +void OtrFloaterSmpDialog::doComboMenu() +{ + LLComboBox *combo = getChild("otr_smp_how_combo"); + if (!combo) + { + llwarns << "$PLOTR$ Can't find OTR SMP how combo" << llendl; + return; + } + LLTextBox *howto = getChild("otr_smp_howto"); + if (!howto) + { + llwarns << "$PLOTR$ Can't find OTR SMP howto control" << llendl; + return; + } + LLTextBox *label1 = getChild("otr_smp_label1"); + if (!label1) + { + llwarns << "$PLOTR$ Can't find OTR SMP label1 control" << llendl; + return; + } + LLLineEditor *edit1 = getChild("otr_smp_edit1"); + if (!edit1) + { + llwarns << "$PLOTR$ Can't find OTR SMP edit1 control" << llendl; + return; + } + LLTextBox *label2 = getChild("otr_smp_label2"); + if (!label2) + { + llwarns << "$PLOTR$ Can't find OTR SMP label2 control" << llendl; + return; + } + LLLineEditor *edit2 = getChild("otr_smp_edit2"); + if (!edit2) + { + llwarns << "$PLOTR$ Can't find OTR SMP edit2 control" << llendl; + return; + } + LLComboBox *veri = getChild("otr_smp_veri_combo"); + if (!veri) + { + llwarns << "$PLOTR$ Can't find OTR SMP verified combo" << llendl; + return; + } + std::string choice = combo->getSimple(); + if (getString("otr_smp_how_by_qa") == choice) + { + howto->setWrappedText(getString("otr_smp_howto_qa")); + label1->setWrappedText(getString("otr_smp_howto_qa_t1")); + edit1->clear(); + edit1->setEnabled(TRUE); + label2->setWrappedText(getString("otr_smp_howto_qa_t2")); + edit2->clear(); + edit2->setEnabled(TRUE); + veri->removeall(); + veri->setLabel(getString("otr_empty_string")); + } + else if (getString("otr_smp_how_by_qa_challenge") == choice) + { + howto->setWrappedText(getString("otr_smp_howto_qa")); + label1->setWrappedText(getString("otr_smp_howto_qa_t1")); + edit1->setText(mQuestion); + edit1->setEnabled(FALSE); + label2->setWrappedText(getString("otr_smp_howto_qa_t2")); + edit2->clear(); + edit2->setEnabled(TRUE); + veri->removeall(); + veri->setLabel(getString("otr_empty_string")); + } + else if (getString("otr_smp_how_by_ss") == choice) + { + howto->setWrappedText(getString("otr_smp_howto_ss")); + label1->setWrappedText(getString("otr_smp_howto_ss_t1")); + edit1->clear(); + edit1->setEnabled(TRUE); + label2->setWrappedText(getString("otr_smp_howto_ss_t2")); + edit2->clear(); + edit2->setEnabled(FALSE); + veri->removeall(); + veri->setLabel(getString("otr_empty_string")); + } + else if (getString("otr_smp_how_by_ss_challenge") == choice) + { + howto->setWrappedText(getString("otr_smp_howto_ss")); + label1->setWrappedText(getString("otr_smp_howto_ss_t1")); + edit1->clear(); + edit1->setEnabled(TRUE); + label2->setWrappedText(getString("otr_smp_howto_ss_t2")); + edit2->clear(); + edit2->setEnabled(FALSE); + veri->removeall(); + veri->setLabel(getString("otr_empty_string")); + } + else if (getString("otr_smp_how_by_mfv") == choice) + { + howto->setWrappedText(getString("otr_smp_howto_mfv")); + label1->setWrappedText(getString("otr_smp_howto_mfv_t1")); + edit1->setText(mMyFingerprint); + edit1->setEnabled(FALSE); + label2->setWrappedText(getString("otr_smp_howto_mfv_t2")); + edit2->setText(mOtherFingerprint); + edit2->setEnabled(FALSE); + veri->add(getString("otr_smp_veri_no"), ADD_BOTTOM, TRUE); + veri->add(getString("otr_smp_veri_yes"), ADD_BOTTOM, TRUE); + veri->selectFirstItem(); + } + else + { + llwarns << "$PLOTR$ unknown smp howto choice" << llendl; + } + doVeriMenu(); +} + +// static +void OtrFloaterSmpDialog::onClickCombo(LLUICtrl* source, void* userdata) +{ + OtrFloaterSmpDialog* self = (OtrFloaterSmpDialog*)userdata; + if (!self) + { + llwarns << "$PLOTR$ can't find OTR SMP dialog." << llendl; + } + else + { + self->doComboMenu(); + } +} + +// static +void OtrFloaterSmpDialog::onClickVeri(LLUICtrl* source, void* userdata) +{ + OtrFloaterSmpDialog* self = (OtrFloaterSmpDialog*)userdata; + if (!self) + { + llwarns << "$PLOTR$ can't find OTR SMP dialog." << llendl; + } + else + { + self->doVeriMenu(); + } +} + +// static +void OtrFloaterSmpDialog::onClickHelp(void*) +{ + LLWeb::loadURL("http://www.cypherpunks.ca/otr/help/3.2.0/authenticate.php"); +} + +// virtual +void OtrFloaterSmpDialog::onClose(bool app_quitting) +{ + destroy(); + if (!mIMPanel) + { + llwarns << "$PLOTR$ Can't find mIMPanel." << llendl; + } + else + { + mIMPanel->endSmpDialog(); + } +} + +// static +void OtrFloaterSmpDialog::onClickCancel(void* userdata) +{ + OtrFloaterSmpDialog *self= (OtrFloaterSmpDialog*)userdata; + if (!self) + { + llwarns << "$PLOTR$ can't find OTR SMP dialog." << llendl; + return; + } + self->close(); +} + +void OtrFloaterSmpDialog::doClickAuth() +{ + LLComboBox *combo = getChild("otr_smp_how_combo"); + if (!combo) + { + llwarns << "$PLOTR$ Can't find OTR SMP how combo" << llendl; + return; + } + LLTextBox *howto = getChild("otr_smp_howto"); + if (!howto) + { + llwarns << "$PLOTR$ Can't find OTR SMP howto control" << llendl; + return; + } + LLTextBox *label1 = getChild("otr_smp_label1"); + if (!label1) + { + llwarns << "$PLOTR$ Can't find OTR SMP label1 control" << llendl; + return; + } + LLLineEditor *edit1 = getChild("otr_smp_edit1"); + if (!edit1) + { + llwarns << "$PLOTR$ Can't find OTR SMP edit1 control" << llendl; + return; + } + LLTextBox *label2 = getChild("otr_smp_label2"); + if (!label2) + { + llwarns << "$PLOTR$ Can't find OTR SMP label2 control" << llendl; + return; + } + LLLineEditor *edit2 = getChild("otr_smp_edit2"); + if (!edit2) + { + llwarns << "$PLOTR$ Can't find OTR SMP edit2 control" << llendl; + return; + } + LLComboBox *veri = getChild("otr_smp_veri_combo"); + if (!veri) + { + llwarns << "$PLOTR$ Can't find OTR SMP verified combo" << llendl; + return; + } + std::string choice = combo->getSimple(); + if (getString("otr_smp_how_by_qa") == choice) + { + llinfos << "$PLOTR$ OTR SMP QA method chosen" << llendl; + std::string question = edit1->getText(); + std::string answer = edit2->getText(); + mIMPanel->startSmpProgress(mSessionUUID, mOtherParticipantUUID, question, answer); + } + else if (getString("otr_smp_how_by_ss") == choice) + { + llinfos << "$PLOTR$ OTR SMP SS method chosen" << llendl; + std::string secret = edit1->getText(); + mIMPanel->startSmpProgress(mSessionUUID, mOtherParticipantUUID, secret); + } + else if (getString("otr_smp_how_by_mfv") == choice) + { + if (getString("otr_smp_veri_yes") == veri->getSimple()) + { + llinfos << "$PLOTR$ OTR SMP MFV authenticating " << mOtherParticipantUUID << llendl; + otr_authenticate_key(mSessionUUID, "mfv"); + } + } + else if (getString("otr_smp_how_by_qa_challenge") == choice) + { + std::string answer = edit2->getText(); + mIMPanel->startSmpProgress(mSessionUUID, mOtherParticipantUUID, mQuestion, answer, true); + } + else if (getString("otr_smp_how_by_ss_challenge") == choice) + { + std::string secret = edit1->getText(); + mIMPanel->startSmpProgress(mSessionUUID, mOtherParticipantUUID, secret, true); + } + else + { + llwarns << "$PLOTR$ unknown smp howto choice" << llendl; + } +} + +// static +void OtrFloaterSmpDialog::onClickAuth(void* userdata) +{ + OtrFloaterSmpDialog *self= (OtrFloaterSmpDialog*)userdata; + if (!self) + { + llwarns << "$PLOTR$ can't find OTR SMP dialog." << llendl; + return; + } + self->doClickAuth(); + self->close(); +} + diff --git a/linden/indra/newview/otr_floater_smp_dialog.h b/linden/indra/newview/otr_floater_smp_dialog.h new file mode 100644 index 0000000..bb01b71 --- /dev/null +++ b/linden/indra/newview/otr_floater_smp_dialog.h @@ -0,0 +1,63 @@ +/* otr_floater_smp_dialog.h - SMP dialog box [$PLOTR$] + See http://www.cypherpunks.ca/otr/ + + Copyright (C) 2009 Chris Tuchs + + This is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the viewer; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#ifndef OTR_FLOATER_SMP_DIALOG_H_INCLUDED +#define OTR_FLOATER_SMP_DIALOG_H_INCLUDED 1 + +#include "llfloater.h" +class LLFloaterIMPanel; + +class OtrFloaterSmpDialog +: public LLFloater +{ +private: + LLUUID mOtherParticipantUUID; + LLUUID mSessionUUID; + std::string mQuestion; + std::string mMyFingerprint; + std::string mOtherFingerprint; + LLFloaterIMPanel *mIMPanel; + bool mIsReply; + + static void onClickHelp(void* userdata); + static void onClickCancel(void* userdata); + void doComboMenu(); + static void onClickCombo(LLUICtrl* source, void* userdata); + void doVeriMenu(); + static void onClickVeri(LLUICtrl* source, void* userdata); + void doClickAuth(); + static void onClickAuth(void* userdata); + std::string getStringName(const char *message_name); + +public: + OtrFloaterSmpDialog(LLFloaterIMPanel *im_panel, LLUUID session_id, LLUUID other_id, + std::string my_fingerprint, std::string other_fingerprint); + OtrFloaterSmpDialog(LLFloaterIMPanel *im_panel, LLUUID session_id, LLUUID other_id, + std::string question, OtrlTLV *tlv); + OtrFloaterSmpDialog(LLFloaterIMPanel *im_panel, LLUUID session_id, LLUUID other_id, + OtrlTLV *tlv); + virtual ~OtrFloaterSmpDialog(); + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onClose(bool app_quitting); + + void show(); + void init(); +}; +#endif // ndef OTR_FLOATER_SMP_DIALOG_H_INCLUDED [/$PLOTR$] diff --git a/linden/indra/newview/otr_floater_smp_progress.cpp b/linden/indra/newview/otr_floater_smp_progress.cpp new file mode 100644 index 0000000..76bfc6e --- /dev/null +++ b/linden/indra/newview/otr_floater_smp_progress.cpp @@ -0,0 +1,288 @@ +/* otr_floater_smp_progress.cpp - SMP progress dialog box [$PLOTR$] + See http://www.cypherpunks.ca/otr/ + + Copyright (C) 2009 Chris Tuchs + + This is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the viewer; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#include "llviewerprecompiledheaders.h" + +#include "llagent.h" +#include "llcachename.h" +#include "llimpanel.h" +#include "llprogressbar.h" +#include "lluictrlfactory.h" +#include "llweb.h" + +#include "otr_wrapper.h" +#include "otr_floater_smp_progress.h" + +void OtrFloaterSmpProgress::init() +{ + LLUICtrlFactory::getInstance()->buildFloater(this, "otr_floater_smp_progress.xml"); + childSetAction("otr_smp_prog_help_btn", onClickHelp, this); + childSetAction("otr_smp_prog_cancel_btn", onClickCancel, this); + childSetAction("otr_smp_prog_ok_btn", onClickOk, this); + setDefaultBtn("otr_smp_prog_cancel_btn"); + LLUIString title = mIsReply + ? getString("otr_smp_prog_name_auth_me") + : getString("otr_smp_prog_I_auth_name"); + std::string them; + if (!gCacheName->getFullName(mOtherParticipantUUID, them)) them = getString("otr_generic_name"); + title.setArg("[NAME]", them); + setTitle(title.getString()); +} + +OtrFloaterSmpProgress::OtrFloaterSmpProgress( + LLFloaterIMPanel *im_panel, LLUUID session_id, LLUUID other_id, + std::string a_question, std::string a_secret_answer, bool is_reply) +: LLFloater(std::string("otr_floater_smp_progress"), std::string("OtrFloaterSmpProgRect"), LLStringUtil::null), + mIMPanel(im_panel), mIsReply(is_reply), + mSessionUUID(session_id), mOtherParticipantUUID(other_id), + mQuestion(a_question), mSecretAnswer(a_secret_answer), + mSecretAnswerOnly(false) +{ + init(); + if (!gOTR) + { + llwarns << "$PLOTR$ Can't find gOTR." << llendl; + setFinalStatus("otr_smp_prog_auth_errored"); + return; + } + if (!mIMPanel) + { + llwarns << "$PLOTR$ Can't find mIMPanel." << llendl; + setFinalStatus("otr_smp_prog_auth_errored"); + return; + } + ConnContext *context = mIMPanel->getOtrContext(); + if (!context) + { + llwarns << "$PLOTR$ Can't find context." << llendl; + setFinalStatus("otr_smp_prog_auth_errored"); + return; + } + if (mIsReply) + { + otrl_message_respond_smp( + gOTR->get_userstate(), + gOTR->get_uistate(), + &mSessionUUID, + context, + (const unsigned char *)mSecretAnswer.c_str(), + mSecretAnswer.length()); + setPercent(50); + setStatusName("otr_smp_prog_name_auth_me"); + } + else + { + otrl_message_initiate_smp_q( + gOTR->get_userstate(), + gOTR->get_uistate(), + &mSessionUUID, + context, + mQuestion.c_str(), + (const unsigned char *)mSecretAnswer.c_str(), + mSecretAnswer.length()); + setStatusName("otr_smp_prog_I_auth_name"); + } +} + +OtrFloaterSmpProgress::OtrFloaterSmpProgress( + LLFloaterIMPanel *im_panel, LLUUID session_id, LLUUID other_id, + std::string a_secret_answer, bool is_reply) +: LLFloater(std::string("otr_floater_smp_progress"), std::string("OtrFloaterSmpProgRect"), LLStringUtil::null), + mIMPanel(im_panel), mIsReply(is_reply), + mSessionUUID(session_id), mOtherParticipantUUID(other_id), + mSecretAnswer(a_secret_answer), + mSecretAnswerOnly(true) +{ + init(); + if (!gOTR) + { + llwarns << "$PLOTR$ Can't find gOTR." << llendl; + setFinalStatus("otr_smp_prog_auth_errored"); + return; + } + if (!mIMPanel) + { + llwarns << "$PLOTR$ Can't find mIMPanel." << llendl; + setFinalStatus("otr_smp_prog_auth_errored"); + return; + } + ConnContext *context = mIMPanel->getOtrContext(); + if (!context) + { + llwarns << "$PLOTR$ Can't find context." << llendl; + setFinalStatus("otr_smp_prog_auth_errored"); + return; + } + if (mIsReply) + { + otrl_message_respond_smp( + gOTR->get_userstate(), + gOTR->get_uistate(), + &mSessionUUID, + context, + (const unsigned char *)mSecretAnswer.c_str(), + mSecretAnswer.length()); + setPercent(50); + setStatusName("otr_smp_prog_name_auth_me"); + } + else + { + otrl_message_initiate_smp( + gOTR->get_userstate(), + gOTR->get_uistate(), + &mSessionUUID, + context, + (const unsigned char *)mSecretAnswer.c_str(), + mSecretAnswer.length()); + setStatusName("otr_smp_prog_I_auth_name"); + } +} + +OtrFloaterSmpProgress::~OtrFloaterSmpProgress() +{ +} + +BOOL OtrFloaterSmpProgress::postBuild() +{ + mProgressBar = getChild("otr_smp_prog_progress_bar"); + LLButton* cancel_btn = getChild("otr_smp_prog_cancel_btn"); + cancel_btn->setEnabled(TRUE); + LLButton* ok_btn = getChild("otr_smp_prog_ok_btn"); + ok_btn->setEnabled(FALSE); + return TRUE; +} + +void OtrFloaterSmpProgress::show() +{ + this->open(); /*Flawfinder: ignore*/ + this->center(); +} + +void OtrFloaterSmpProgress::setPercent(float percent) +{ + mProgressBar->setPercent(percent); + if (100 <= percent) + { + LLButton* cancel_btn = getChild("otr_smp_prog_cancel_btn"); + cancel_btn->setEnabled(FALSE); + LLButton* ok_btn = getChild("otr_smp_prog_ok_btn"); + ok_btn->setEnabled(TRUE); + } + else + { + LLButton* cancel_btn = getChild("otr_smp_prog_cancel_btn"); + cancel_btn->setEnabled(TRUE); + LLButton* ok_btn = getChild("otr_smp_prog_ok_btn"); + ok_btn->setEnabled(FALSE); + } +} + +void OtrFloaterSmpProgress::setStatus(const char *message_string_name) +{ + LLTextBox *status = getChild("otr_smp_prog_status"); + if (!status) + { + llwarns << "$PLOTR$ Can't find OTR progress status textbox" << llendl; + return; + } + status->setWrappedText(getString(message_string_name)); +} + +void OtrFloaterSmpProgress::setStatusName(const char *message_string_name) +{ + LLTextBox *status = getChild("otr_smp_prog_status"); + if (!status) + { + llwarns << "$PLOTR$ Can't find OTR progress status textbox" << llendl; + return; + } + LLUIString msg = getString(message_string_name); + std::string them; + if (!gCacheName->getFullName(mOtherParticipantUUID, them)) them = getString("otr_generic_name"); + msg.setArg("[NAME]", them); + status->setWrappedText(msg.getString()); +} + +void OtrFloaterSmpProgress::setFinalStatus(const char *message_string_name) +{ + setPercent(100); + setStatusName(message_string_name); +} + +// static +void OtrFloaterSmpProgress::onClickHelp(void*) +{ + LLWeb::loadURL("http://www.cypherpunks.ca/otr/help/3.2.0/authenticate.php"); +} + +// static +void OtrFloaterSmpProgress::onClickCancel(void* userdata) +{ + OtrFloaterSmpProgress *self= (OtrFloaterSmpProgress*)userdata; + if (!self) + { + llwarns << "$PLOTR$ can't find OTR SMP PROG dialog." << llendl; + return; + } + if (!self->mIMPanel) + { + llwarns << "$PLOTR$ Can't find mIMPanel." << llendl; + return; + } + ConnContext *context = self->mIMPanel->getOtrContext(); + if (!context) + { + llwarns << "$PLOTR$ Can't find context." << llendl; + return; + } + otrl_message_abort_smp( + gOTR->get_userstate(), + gOTR->get_uistate(), + &(self->mSessionUUID), + context); + self->close(); +} + +// static +void OtrFloaterSmpProgress::onClickOk(void* userdata) +{ + OtrFloaterSmpProgress *self= (OtrFloaterSmpProgress*)userdata; + if (!self) + { + llwarns << "$PLOTR$ can't find OTR SMP PROG dialog." << llendl; + return; + } + self->close(); +} + +// virtual +void OtrFloaterSmpProgress::onClose(bool app_quitting) +{ + destroy(); + if (!mIMPanel) + { + llwarns << "$PLOTR$ Can't find mIMPanel." << llendl; + } + else + { + mIMPanel->endSmpProgress(); + } +} +// [/$PLOTR$] diff --git a/linden/indra/newview/otr_floater_smp_progress.h b/linden/indra/newview/otr_floater_smp_progress.h new file mode 100644 index 0000000..05ff208 --- /dev/null +++ b/linden/indra/newview/otr_floater_smp_progress.h @@ -0,0 +1,61 @@ +/* otr_floater_smp_progress.h - SMP progress dialog box [$PLOTR$] + See http://www.cypherpunks.ca/otr/ + + Copyright (C) 2009 Chris Tuchs + + This is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the viewer; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#ifndef OTR_FLOATER_SMP_PROGRESS_H_INCLUDED +#define OTR_FLOATER_SMP_PROGRESS_H_INCLUDED 1 + +#include "llfloater.h" +class LLFloaterIMPanel; +class LLProgressBar; + +class OtrFloaterSmpProgress +: public LLFloater +{ +private: + LLUUID mOtherParticipantUUID; + LLUUID mSessionUUID; + std::string mQuestion; + std::string mSecretAnswer; + bool mSecretAnswerOnly; + LLFloaterIMPanel *mIMPanel; + LLProgressBar* mProgressBar; + bool mIsReply; + + static void onClickHelp(void* userdata); + static void onClickCancel(void* userdata); + static void onClickOk(void* userdata); + + void init(); +public: + OtrFloaterSmpProgress(LLFloaterIMPanel *im_panel, LLUUID session_id, LLUUID other_id, + std::string a_question, std::string a_secret_answer, bool is_reply = false); + OtrFloaterSmpProgress(LLFloaterIMPanel *im_panel, LLUUID session_id, LLUUID other_id, + std::string a_secret_answer, bool is_reply = false); + void setPercent(float percent); + void setStatus(const char *message_string_name); + void setStatusName(const char *message_string_name); + void setFinalStatus(const char *message_string_name); + virtual ~OtrFloaterSmpProgress(); + /*virtual*/ BOOL postBuild(); + /*virtual*/ void onClose(bool app_quitting); + + void show(); +}; +#endif // ndef OTR_FLOATER_SMP_PROGRESS_H_INCLUDED [/$PLOTR$] diff --git a/linden/indra/newview/otr_wrapper.cpp b/linden/indra/newview/otr_wrapper.cpp new file mode 100644 index 0000000..abd1c91 --- /dev/null +++ b/linden/indra/newview/otr_wrapper.cpp @@ -0,0 +1,487 @@ +/* otr_wrapper.cpp - wrap libotr for use in the second life viewer + $PLOTR$ See http://www.cypherpunks.ca/otr/ + + Copyright (C) 2009 Chris Tuchs + + This is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the viewer; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#include "llviewerprecompiledheaders.h" +#include "llviewercontrol.h" +#include "llimpanel.h" +#include "otr_wrapper.h" +#include "llagent.h" +#include "llimview.h" + + +OTR_Wrapper *gOTR = 0; + +OTR_Wrapper::OTR_Wrapper() +{ +} + +OTR_Wrapper::~OTR_Wrapper() +{ + if (gOTR) + { + otrl_userstate_free(gOTR->userstate); + } +} + +#define otrwui_tracing 1 // $TODO$ use some debug compile flag? +#if otrwui_tracing +extern "C" void otrwui_trace(const char *msg) +{ + llinfos << "$PLOTR$TRACE$" << msg << llendl; +} +#else +#define otrwui_trace(x) /* nothing */ +#endif + +static void otrwui_tbd(const char *msg) +{ + llinfos << "$PLOTR$TBD$" << msg << llendl; +} + +static OtrlPolicy otrwui_policy(void *opdata, ConnContext *context) +{ + OtrlPolicy result = 0; + U32 useotr = gSavedSettings.getU32("EmeraldUseOTR"); + if (3 < useotr) + { + llwarns << "$PLOTR$ Unknown setting for EmeraldUseOTR" << useotr << llendl; + useotr = 2; + } + if (0 == useotr) // Require use of OTR in IMs + { + result = (0 +// | OTRL_POLICY_ALLOW_V1 // don't even expose this? + | OTRL_POLICY_ALLOW_V2 + | OTRL_POLICY_REQUIRE_ENCRYPTION + | OTRL_POLICY_SEND_WHITESPACE_TAG + | OTRL_POLICY_WHITESPACE_START_AKE + | OTRL_POLICY_ERROR_START_AKE + ); + } + else if (1 == useotr) // Request OTR if available + { + result = (0 +// | OTRL_POLICY_ALLOW_V1 // don't even expose this? + | OTRL_POLICY_ALLOW_V2 +// | OTRL_POLICY_REQUIRE_ENCRYPTION + | OTRL_POLICY_SEND_WHITESPACE_TAG + | OTRL_POLICY_WHITESPACE_START_AKE + | OTRL_POLICY_ERROR_START_AKE + ); + } + else if (2 == useotr) // Accept OTR requests + { + result = (0 +// | OTRL_POLICY_ALLOW_V1 // don't even expose this? + | OTRL_POLICY_ALLOW_V2 +// | OTRL_POLICY_REQUIRE_ENCRYPTION +// | OTRL_POLICY_SEND_WHITESPACE_TAG + | OTRL_POLICY_WHITESPACE_START_AKE + | OTRL_POLICY_ERROR_START_AKE + ); + } + else if (3 == useotr) // Decline use of OTR + { + result = (0 +// | OTRL_POLICY_ALLOW_V1 // don't even expose this? +// | OTRL_POLICY_ALLOW_V2 +// | OTRL_POLICY_REQUIRE_ENCRYPTION +// | OTRL_POLICY_SEND_WHITESPACE_TAG +// | OTRL_POLICY_WHITESPACE_START_AKE +// | OTRL_POLICY_ERROR_START_AKE + ); + } + return result; +} + + + +static void otrwui_create_privkey( + void *opdata, const char *accountname, + const char *protocol) +{ + otrwui_trace("otrwui_create_privkey()"); + /* Create a private key for the given accountname/protocol if + * desired. */ + if (gOTR) + { + LLUUID session_id = *((LLUUID*)opdata); + otr_log_message_getstring(session_id, "otr_gen_key_please_wait"); + std::string path = + gDirUtilp->getExpandedFilename( + LL_PATH_PER_SL_ACCOUNT, OTR_PRIVATE_KEYS_FILE); + otrl_privkey_generate( + gOTR->get_userstate(), path.c_str(), accountname, protocol); + } +} + +static int otrwui_is_logged_in( + void *opdata, const char *accountname, + const char *protocol, const char *recipient) +{ + /* 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. */ + LLUUID recipient_uuid(recipient); + const LLRelationship* info = NULL; + info = LLAvatarTracker::instance().getBuddyInfo(recipient_uuid); + int result; + if (!info) result = 1; // hack, should be -1. but we'll pretend non-friends are always online + else if (!info->isOnline()) result = 0; + else result = 1; +#if otrwui_tracing + std::string msg = "otrwui_is_logged_in()"; + switch(result) + { + case -1: msg += " -1 unknown"; break; + case 0: msg += " 0 no, logged out"; break; + case 1: msg += " 1 yes, logged in"; break; + default: msg += " ? imposible result"; break; + } + otrwui_trace(msg.c_str()); +#endif + return result; +} + +static void otrwui_inject_message( + void *opdata, const char *accountname, + const char *protocol, const char *recipient, const char *message) +{ + otrwui_trace("otrwui_inject_message()"); + /* Send the given IM to the given recipient from the given + * accountname/protocol. */ + if (!opdata) + { + // don't know how to deliver this with no opdata. + llwarns << "$PLOTR$ otrwui_inject_message() called with NULL opdata; not delivering message" << llendl; + } + else + { + LLUUID sessionUUID = *((LLUUID*)opdata); + LLUUID otherUUID(recipient); + otr_deliver_message(message, sessionUUID, otherUUID, IM_NOTHING_SPECIAL); + } +} + +static void otrwui_notify( + void *opdata, OtrlNotifyLevel level, + const char *accountname, const char *protocol, + const char *username, const char *title, + const char *primary, const char *secondary) +{ + /* Display a notification message for a particular accountname / + * protocol / username conversation. */ + std::string trace = "otrwui_notify: \n"; + trace += "title("; trace += title; trace += ")\n"; + trace += "primary("; trace += primary; trace += ")\n"; + trace += "secondary("; trace += secondary; trace += ")"; + otrwui_tbd(trace.c_str()); // $TODO$ write me +} + +static int otrwui_display_otr_message( + void *opdata, const char *accountname, + const char *protocol, const char *username, const char *msg) +{ + /* 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. */ + otrwui_trace("otrwui_log_message()"); + LLUUID sessionUUID = *((LLUUID*)opdata); + otr_log_message(sessionUUID, msg); + return 0; +} + +static void otrwui_update_context_list( + void *opdata) +{ + /* When the list of ConnContexts changes (including a change in + * state), this is called so the UI can be updated. */ + otrwui_tbd("otrwui_update_context_list"); // $TODO$ write me +} + +static const char *otrwui_protocol_name( + void *opdata, const char *protocol) +{ + /* Return a newly allocated string containing a human-friendly name + * for the given protocol id */ + otrwui_trace("otrwui_protocol_name()"); + return "SecondLife"; +} + +static void otrwui_protocol_name_free( + void *opdata, const char *protocol_name) +{ + /* Deallocate a string allocated by protocol_name */ + otrwui_trace("otrwui_protocol_name_free()"); + return; // no need to deallocate a const char * +} + +static void otrwui_new_fingerprint( + void *opdata, OtrlUserState us, + const char *accountname, const char *protocol, + const char *username, unsigned char fingerprint[20]) +{ + /* A new fingerprint for the given user has been received. */ + std::string trace= "otrwui_new_fingerprint: "; + trace += username; trace += "@"; trace += protocol; + trace += " has a new fingerprint ("; + char fingerprint_copy[45]; + otrl_privkey_hash_to_human(fingerprint_copy, fingerprint); + trace += fingerprint_copy; trace += ")"; + otrwui_tbd(trace.c_str()); // $TODO$ write me +} + +static void otrwui_write_fingerprints( + void *opdata) +{ + otrwui_trace("otrwui_write_fingerprints()"); + /* The list of known fingerprints has changed. Write them to disk. */ + if (gOTR) + { + std::string path = + gDirUtilp->getExpandedFilename( + LL_PATH_PER_SL_ACCOUNT, OTR_PUBLIC_KEYS_FILE); + otrl_privkey_write_fingerprints(gOTR->get_userstate(), path.c_str()); + } +} + +static void otrwui_gone_secure( + void *opdata, ConnContext *context) +{ + otrwui_trace("otrwui_gone_secure()"); + /* A ConnContext has entered a secure state. */ + if (! opdata) + { + otrwui_tbd("otrwui_gone_secure() called with null opdata"); + return; + } + LLUUID session_id = *((LLUUID*)opdata); + if (context && context->active_fingerprint && + context->active_fingerprint->trust && + *(context->active_fingerprint->trust)) + { + //otr_log_message_getstring_name(session_id, "otr_log_start_private"); + } + else + { + //otr_log_message_getstring_name(session_id, "otr_log_start_unverified"); + } + otr_show_status(session_id); +} + +static void otrwui_gone_insecure( + void *opdata, ConnContext *context) +{ + otrwui_trace("otrwui_gone_insecure()"); + /* A ConnContext has left a secure state. */ + if (! opdata) + { + otrwui_tbd("otrwui_gone_insecure() called with null opdata"); + return; + } + LLUUID session_id = *((LLUUID*)opdata); + otr_log_message_getstring(session_id, "otr_log_gone_insecure"); + otr_show_status(session_id); +} + +static void otrwui_still_secure( + void *opdata, ConnContext *context, int is_reply) +{ + otrwui_trace("otrwui_still_secure()"); + /* We have completed an authentication, using the D-H keys we + * already knew. is_reply indicates whether we initiated the AKE. */ + if (! opdata) + { + otrwui_tbd("otrwui_still_secure() called with null opdata"); + return; + } + LLUUID session_id = *((LLUUID*)opdata); + if (context && context->active_fingerprint && + context->active_fingerprint->trust && + *(context->active_fingerprint->trust)) + { + //otr_log_message_getstring_name(session_id, "otr_log_still_private"); + } + else + { + //otr_log_message_getstring_name(session_id, "otr_log_still_unverified"); + } + otr_show_status(session_id); +} + +static void otrwui_log_message( + void *opdata, const char *message) +{ + /* Log a message. The passed message will end in "\n". */ + otrwui_trace("otrwui_log_message()"); + llinfos << message << llendl; +} + +static int otrwui_max_message_size( + void *opdata, ConnContext *context) +{ + /* Find the maximum message size supported by this protocol. */ + return (MAX_MSG_BUF_SIZE - 24); +} + +static const char *otrwui_account_name( + void *opdata, const char *account, + const char *protocol) +{ + /* Return a newly allocated string containing a human-friendly + * representation for the given account */ + otrwui_trace("otrwui_account_name"); + std::string name; + LLUUID uuid = LLUUID(account); + if (!gCacheName->getFullName(uuid, name)) name = account; + char *result = (char *)malloc(name.length()+1); + strncpy(result, name.c_str(), name.length()+1); + return result; +} + +static void otrwui_account_name_free( + void *opdata, const char *account_name) +{ + /* Deallocate a string returned by account_name */ + otrwui_trace("otrwui_account_name_free"); + free((void *)account_name); +} + +// static +void OTR_Wrapper::stopAll() +{ + otrwui_trace("OTR_Wrapper::stopAll()"); + if (!gOTR) return; + if (gOTR->userstate) + { + for (ConnContext *context = gOTR->userstate->context_root; context; context = context->next) + { + if (context && (OTRL_MSGSTATE_ENCRYPTED == context->msgstate)) + { + LLUUID their_uuid = LLUUID(context->username); + LLUUID session_uuid = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, their_uuid); + LLFloaterIMPanel* pan = gIMMgr->findFloaterBySession(session_uuid); + if (pan) + { + llinfos << "$PLOTR$ found IM pannel, pan->doOtrStop()" << llendl; + pan->doOtrStop(); + } + else + { + char my_uuid[UUID_STR_SIZE]; + gAgent.getID().toString(&(my_uuid[0])); + llinfos << "$PLOTR$ didn't find IM panel, going lower level" + << " c->accountname:" << context->accountname // this avatar, aka me + << " c->protocol:" << context->protocol // secondlife, IRC, yahoo... + << " c->username:" << context->username // other participant + << " session_uuid:" << session_uuid + << llendl; + otrl_message_disconnect( + gOTR->get_userstate(), + gOTR->get_uistate(), + &session_uuid, + context->accountname, + context->protocol, + context->username); + } + } + } + } +} + +// static +void OTR_Wrapper::logout() +{ + otrwui_trace("OTR_Wrapper::logout()"); + if (!gOTR) return; + OTR_Wrapper::stopAll(); + delete gOTR; + gOTR = NULL; +} + +// static +void OTR_Wrapper::init() +{ + otrwui_trace("OTR_Wrapper::init()"); + if (! gOTR) + { + gOTR = new OTR_Wrapper; + if (!gOTR) + { + llwarns << "$PLOTR$ Can't new otr_wrapper." << llendl; + } + else + { + llinfos << "$PLOTR$ newed otr_wrapper." << llendl; + gOTR->uistate.policy = &otrwui_policy; + gOTR->uistate.create_privkey = &otrwui_create_privkey; + gOTR->uistate.is_logged_in = &otrwui_is_logged_in; + gOTR->uistate.inject_message = &otrwui_inject_message; + gOTR->uistate.notify = &otrwui_notify; + gOTR->uistate.display_otr_message = &otrwui_display_otr_message; + gOTR->uistate.update_context_list = &otrwui_update_context_list; + gOTR->uistate.protocol_name = &otrwui_protocol_name; + gOTR->uistate.protocol_name_free = &otrwui_protocol_name_free; + gOTR->uistate.new_fingerprint = &otrwui_new_fingerprint; + gOTR->uistate.write_fingerprints = &otrwui_write_fingerprints; + gOTR->uistate.gone_secure = &otrwui_gone_secure; + gOTR->uistate.gone_insecure = &otrwui_gone_insecure; + gOTR->uistate.still_secure = &otrwui_still_secure; + gOTR->uistate.log_message = &otrwui_log_message; + gOTR->uistate.max_message_size = &otrwui_max_message_size; + gOTR->uistate.account_name = &otrwui_account_name; + gOTR->uistate.account_name_free = &otrwui_account_name_free; + OTRL_INIT; + gOTR->userstate = otrl_userstate_create(); + std::string privpath = + gDirUtilp->getExpandedFilename( + LL_PATH_PER_SL_ACCOUNT, OTR_PRIVATE_KEYS_FILE); + otrl_privkey_read(gOTR->userstate, privpath.c_str()); + std::string pubpath = + gDirUtilp->getExpandedFilename( + LL_PATH_PER_SL_ACCOUNT, OTR_PUBLIC_KEYS_FILE); + otrl_privkey_read_fingerprints(gOTR->userstate, pubpath.c_str(), NULL, NULL); +#if 0 // this will gen a key, if the user doesn't have one, at init() time + if (gOTR && gOTR->userstate) + { + OtrlPrivKey *r = gOTR->userstate->privkey_root; + OtrlPrivKey *k = gOTR->userstate->privkey_root; + while (k && (k != r)) + { + if (0 == strcmp(gOTR->get_protocolid(), k->protocol)) + { + return; + } + } + char my_uuid[UUID_STR_SIZE]; + gAgent.getID().toString(&(my_uuid[0])); + otrl_privkey_generate(gOTR->userstate, privpath.c_str(), + my_uuid, gOTR->get_protocolid()); + } +#endif + } + } +} diff --git a/linden/indra/newview/otr_wrapper.h b/linden/indra/newview/otr_wrapper.h new file mode 100644 index 0000000..dd6d12c --- /dev/null +++ b/linden/indra/newview/otr_wrapper.h @@ -0,0 +1,58 @@ +/* otr_wrapper.h - wrap libotr for use in the second life viewer + $PLOTR$ See http://www.cypherpunks.ca/otr/ + + Copyright (C) 2009 Chris Tuchs + + This is free software; you can redistribute it and/or modify it + under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of + the License, or (at your option) any later version. + + This is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public + License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the viewer; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. */ + +#ifndef OTR_WRAPPER_H_INCLUDED +#define OTR_WRAPPER_H_INCLUDED 1 + +extern "C" { +#if WIN32 +#include // various defines needed for OTR on windows +#endif +#include // gcrypt dependancies +#include // OTR +#include // OTR +#include // OTR +#include <../libotr/libotr-3.2.0/src/message.h> // OTR +#include +} + +class OTR_Wrapper +{ +private: + OtrlUserState userstate; // Global state of OTR: known public keys etc. + OtrlMessageAppOps uistate; // UI functions collected into a structure for libotr + OTR_Wrapper(); + ~OTR_Wrapper(); + +public: + static void init(); + static void stopAll(); + static void logout(); + OtrlUserState get_userstate() { return this->userstate; } + OtrlMessageAppOps *get_uistate() { return &(this->uistate); } + const char * get_protocolid() { return "SecondLife"; } +}; + +extern OTR_Wrapper *gOTR; // the singleton OTR wrapper + +#define OTR_PRIVATE_KEYS_FILE "OTR-my-private-key.dat" +#define OTR_PUBLIC_KEYS_FILE "OTR-public-keys.dat" + +#endif // ndef OTR_WRAPPER_H_INCLUDED diff --git a/linden/indra/newview/skins/default/xui/en-us/floater_instant_message.xml b/linden/indra/newview/skins/default/xui/en-us/floater_instant_message.xml index 4ccfe60..5ad564a 100644 --- a/linden/indra/newview/skins/default/xui/en-us/floater_instant_message.xml +++ b/linden/indra/newview/skins/default/xui/en-us/floater_instant_message.xml @@ -37,6 +37,42 @@ Text chat is not available for this call. + + + OTR is generating keys. This will happen once for each of your avatars and should take less than 45 seconds. + Your buddy + [NAME] has ended the private conversation, so your message was not sent. You should restart the private conversation, or end the private conversation. + OTR has been deactivated by preferences (edit > preferences > Emerald tab > IM tab) + Unable to encrypt your message for some reason; it has not been sent. + Unable to start private conversation. + [NAME] appears offline; OTR will not try to start a private conversation. + [NAME] appears offline; You may "End private conversation" and send your message un-encrypted. + Attempting to start a private conversation with [NAME]. + You have ended the unverified conversation with [NAME]. + You have ended the private conversation with [NAME]. + You have ended the OTR conversation with [NAME]. + [NAME] is attempting to start a private conversation. + [NAME] has ended the unverified conversation. + [NAME] has ended the private conversation. + [NAME] has ended the OTR conversation. + [NAME] is now authenticated. + Private conversation with [NAME] started. + Unverified conversation started. [NAME] has not been authenticated, you should "authenticate buddy," see http://www.cypherpunks.ca/otr/help/3.2.0/authenticate.php + Private conversation ended. + Private conversation with [NAME] resumed. + Unverified conversation resumed. [NAME] has not been authenticated, you should "authenticate buddy," see http://www.cypherpunks.ca/otr/help/3.2.0/authenticate.php + OTR: Not Private + OTR: Unverified + OTR: Private + OTR: Finished + Start private conversation + Refresh private conversation + Restart private conversation + End private conversation + Authenticate buddy + What is OTR? + What is this? + Add Friend @@ -72,6 +108,10 @@ image_unselected="icn_speaker_dark.tga" label="" left_delta="56" name="mute_btn" tool_tip="Mute voice" width="25" /> + + + + + +OTR encrypts your IMs so they can't be read by anyone other than the person you are talking to. + +Do you want to automatically secure your IMs? +
+