From f881fbf88247a2704c22e803cfb2f477afdcc2b4 Mon Sep 17 00:00:00 2001 From: Evan Schoenberg Date: Fri, 18 Nov 2005 23:01:24 +0000 Subject: [PATCH] Merged [14052]: Added the concept of unverified/verified encryption to match OTR. Set the verified status of the contact in adiumGaimOTR; properly update it if the user verifies the contact's fingerprint (identity) in the unknown fingerprint controller; inform the user when starting an encrypted session with an unverified contact. git-svn-id: svn://svn.adiumx.com/adium/branches/adium-0.8@14053 1c916fce-81e2-0310-a464-8ca513f45935 --- Frameworks/Adium Framework/AIChat.h | 8 +++ Frameworks/Adium Framework/AIChat.m | 25 +++++++- .../ESGaimOTRUnknownFingerprintController.m | 15 +++-- Plugins/Gaim Service/adiumGaimOTR.m | 24 ++++++-- Plugins/Secure Messaging/ESSecureMessagingPlugin.h | 3 +- Plugins/Secure Messaging/ESSecureMessagingPlugin.m | 68 ++++++++++++++++++---- 6 files changed, 121 insertions(+), 22 deletions(-) diff --git a/Frameworks/Adium Framework/AIChat.h b/Frameworks/Adium Framework/AIChat.h index d4dc16424..c83ade0a8 100644 --- a/Frameworks/Adium Framework/AIChat.h +++ b/Frameworks/Adium Framework/AIChat.h @@ -53,6 +53,13 @@ typedef enum { EncryptedChat_RejectUnencryptedMessages = 2 } AIEncryptedChatPreference; +typedef enum { + EncryptionStatus_None = 0, + EncryptionStatus_Unverified, + EncryptionStatus_Verified, + EncryptionStatus_Finished +} AIEncryptionStatus; + //Chat errors should be indicated by setting a status object on this key //with an NSNumber of the appropriate error type as its object #define KEY_CHAT_ERROR @"Chat Error" @@ -139,6 +146,7 @@ typedef enum { - (void)setSecurityDetails:(NSDictionary *)securityDetails; - (NSDictionary *)securityDetails; - (BOOL)isSecure; +- (AIEncryptionStatus)encryptionStatus; - (BOOL)supportsSecureMessagingToggling; - (BOOL)canSendImages; diff --git a/Frameworks/Adium Framework/AIChat.m b/Frameworks/Adium Framework/AIChat.m index 5a37d057e..b3c05f13d 100644 --- a/Frameworks/Adium Framework/AIChat.m +++ b/Frameworks/Adium Framework/AIChat.m @@ -221,7 +221,30 @@ static int nextChatNumber = 0; - (BOOL)isSecure { - return([self securityDetails] != nil); + AIEncryptionStatus encryptionStatus = [self encryptionStatus]; + + return (encryptionStatus != EncryptionStatus_None); +} + +- (AIEncryptionStatus)encryptionStatus +{ + AIEncryptionStatus encryptionStatus = EncryptionStatus_None; + + NSDictionary *securityDetails = [self securityDetails]; + if (securityDetails) { + NSNumber *detailsStatus; + if ((detailsStatus = [securityDetails objectForKey:@"EncryptionStatus"])) { + encryptionStatus = [detailsStatus intValue]; + + } else { + /* If we don't have a specific encryption status, but do have security details, assume + * encrypted and verified. + */ + encryptionStatus = EncryptionStatus_Verified; + } + } + + return encryptionStatus; } - (BOOL)supportsSecureMessagingToggling diff --git a/Plugins/Gaim Service/ESGaimOTRUnknownFingerprintController.m b/Plugins/Gaim Service/ESGaimOTRUnknownFingerprintController.m index 87e5afd77..47b776230 100644 --- a/Plugins/Gaim Service/ESGaimOTRUnknownFingerprintController.m +++ b/Plugins/Gaim Service/ESGaimOTRUnknownFingerprintController.m @@ -132,12 +132,17 @@ Fingerprint *fprint; BOOL oldtrust, trust; - if (context == NULL) return; - - fprint = otrl_context_find_fingerprint(context, (unsigned char *)[fingerprint UTF8String], - 0, NULL); + if (context == NULL) { + AILog(@"Warning: ESGaimOTRUnknownFingerprintController: NULL context for %@",responseInfo); + return; + } - if (fprint == NULL) return; + fprint = context->active_fingerprint; + + if (fprint == NULL) { + AILog(@"Warning: ESGaimOTRUnknownFingerprintController: NULL fprint for %@",responseInfo); + return; + } oldtrust = (fprint->trust && fprint->trust[0]); trust = [fingerprintAcceptedNumber boolValue]; diff --git a/Plugins/Gaim Service/adiumGaimOTR.m b/Plugins/Gaim Service/adiumGaimOTR.m index 8a9059981..3cd6026fa 100644 --- a/Plugins/Gaim Service/adiumGaimOTR.m +++ b/Plugins/Gaim Service/adiumGaimOTR.m @@ -83,7 +83,7 @@ static ConnContext* context_for_conv(GaimConversation *conv) static NSDictionary* details_for_context(ConnContext *context) { NSDictionary *securityDetailsDict; - if (context == NULL /*|| context->msgstate != OTRL_MSGSTATE_ENCRYPTED*/) { + if (context == NULL) { NSLog(@"Ack! (%x)",context); return nil; } @@ -100,7 +100,24 @@ static NSDictionary* details_for_context(ConnContext *context) if (context == NULL) return nil; fingerprint = fprint->fingerprint; - trust = fprint->trust; + + TrustLevel level = otrg_plugin_context_to_trust(context); + AIEncryptionStatus encryptionStatus; + + switch (level) { + case TRUST_NOT_PRIVATE: + encryptionStatus = EncryptionStatus_None; + break; + case TRUST_UNVERIFIED: + encryptionStatus = EncryptionStatus_Unverified; + break; + case TRUST_PRIVATE: + encryptionStatus = EncryptionStatus_Verified; + break; + case TRUST_FINISHED: + encryptionStatus = EncryptionStatus_Finished; + break; + } otrl_privkey_fingerprint(otrg_plugin_userstate, our_hash, context->accountname, context->protocol); @@ -112,7 +129,7 @@ static NSDictionary* details_for_context(ConnContext *context) securityDetailsDict = [NSDictionary dictionaryWithObjectsAndKeys: [NSString stringWithUTF8String:hash], @"Fingerprint", - [NSString stringWithUTF8String:(trust ? trust : "")], @"Trust", + [NSNumber numberWithInt:encryptionStatus], @"EncryptionStatus", [NSString stringWithUTF8String:context->accountname], @"accountname", [NSString stringWithUTF8String:context->username], @"who", ((context->protocol) ? [NSString stringWithUTF8String:context->protocol] : @""), @"protocol", @@ -316,7 +333,6 @@ static void otrg_adium_dialog_new_conv(GaimConversation *conv) context = context_for_conv(conv); trustLevel = otrg_plugin_context_to_trust(context); -#warning Need to set actual state if (trustLevel != TRUST_NOT_PRIVATE) { NSDictionary *securityDetailsDict; diff --git a/Plugins/Secure Messaging/ESSecureMessagingPlugin.h b/Plugins/Secure Messaging/ESSecureMessagingPlugin.h index 2e7ce5fb9..4e167f91c 100644 --- a/Plugins/Secure Messaging/ESSecureMessagingPlugin.h +++ b/Plugins/Secure Messaging/ESSecureMessagingPlugin.h @@ -21,7 +21,8 @@ @protocol AIChatObserver; typedef enum { - AISecureMessagingMenu_Toggle = 1, + AISecureMessagingMenu_Root = 1, + AISecureMessagingMenu_Toggle, AISecureMessagingMenu_ShowDetails, AISecureMessagingMenu_Options, AISecureMessagingMenu_ShowAbout diff --git a/Plugins/Secure Messaging/ESSecureMessagingPlugin.m b/Plugins/Secure Messaging/ESSecureMessagingPlugin.m index 73c1bd99e..2ddf9d13d 100644 --- a/Plugins/Secure Messaging/ESSecureMessagingPlugin.m +++ b/Plugins/Secure Messaging/ESSecureMessagingPlugin.m @@ -16,6 +16,7 @@ #import "AIContentController.h" #import "AIInterfaceController.h" +#import "AIMenuController.h" #import "AIToolbarController.h" #import "ESSecureMessagingPlugin.h" #import @@ -35,10 +36,12 @@ #define TITLE_ENCRYPTION AILocalizedString(@"Encryption",nil) -#define CHAT_NOW_SECURE AILocalizedString(@"Encrypted OTR chat initiated.", nil) -#define CHAT_NO_LONGER_SECURE AILocalizedString(@"Ended encrypted OTR chat.", nil) +#define CHAT_NOW_SECURE AILocalizedString(@"Encrypted OTR chat initiated.", nil) +#define CHAT_NOW_SECURE_UNVERIFIED AILocalizedString(@"Encrypted OTR chat initiated. %@'s identity not verified.", nil) +#define CHAT_NO_LONGER_SECURE AILocalizedString(@"Ended encrypted OTR chat.", nil) @interface ESSecureMessagingPlugin (PRIVATE) +- (void)configureMenuItems; - (void)registerToolbarItem; - (NSMenu *)_secureMessagingMenu; - (void)_updateToolbarIconOfChat:(AIChat *)inChat inWindow:(NSWindow *)window; @@ -58,7 +61,8 @@ */ [self registerToolbarItem]; - + [self configureMenuItems]; + [[adium contentController] registerChatObserver:self]; } @@ -68,6 +72,26 @@ [[NSNotificationCenter defaultCenter] removeObserver:self]; } +- (void)configureMenuItems +{ + NSMenu *menu = [self _secureMessagingMenu]; + + //Add menu to toolbar item (for text mode) + NSMenuItem *menuItem = [[[NSMenuItem allocWithZone:[NSMenu menuZone]] initWithTitle:AILocalizedString(@"Encryption", nil) + target:self + action:@selector(dummyAction:) + keyEquivalent:@""] autorelease]; + [menuItem setSubmenu:menu]; + [menuItem setTag:AISecureMessagingMenu_Root]; + + [[adium menuController] addMenuItem:menuItem + toLocation:LOC_Contact_Additions]; + + menuItem = [[menuItem copy] autorelease]; + [[adium menuController] addContextualMenuItem:menuItem + toLocation:Context_Contact_ChatAction]; +} + - (void)registerToolbarItem { toolbarItems = [[NSMutableSet alloc] init]; @@ -169,19 +193,34 @@ BOOL chatIsSecure = [inChat isSecure]; if(!lastEncryptedNumber || (chatIsSecure != [lastEncryptedNumber boolValue])){ NSString *message; - + [inChat setStatusObject:[NSNumber numberWithBool:chatIsSecure] forKey:@"secureMessagingLastEncryptedState" notify:NotifyNever]; - - message = (chatIsSecure ? CHAT_NOW_SECURE : CHAT_NO_LONGER_SECURE); - + + if (chatIsSecure) { + if ([inChat encryptionStatus] == EncryptionStatus_Unverified) { + AIListObject *listObject = [inChat listObject]; + NSString *displayName = (listObject ? + [listObject formattedUID] : + [inChat displayName]); + + message = [NSString stringWithFormat:CHAT_NOW_SECURE_UNVERIFIED, displayName]; + + } else { + message = CHAT_NOW_SECURE; + } + + } else { + message = CHAT_NO_LONGER_SECURE; + } + [[adium contentController] displayStatusMessage:message ofType:@"encryption" inChat:inChat]; } } - + return nil; } @@ -254,7 +293,9 @@ { AIChat *chat = [[adium interfaceController] activeChat]; - if([[[menuItem menu] title] isEqualToString:ENCRYPTION_MENU_TITLE]){ + if (!chat) return NO; + + if ([[[menuItem menu] title] isEqualToString:ENCRYPTION_MENU_TITLE]) { /* Options submenu */ AIEncryptedChatPreference tag = [menuItem tag]; switch(tag){ @@ -292,6 +333,10 @@ AISecureMessagingMenuTag tag = [menuItem tag]; switch(tag){ + case AISecureMessagingMenu_Root: + return [chat supportsSecureMessagingToggling]; + break; + case AISecureMessagingMenu_Toggle: //The menu item should indicate what will happen if it is selected.. the opposite of our secure state [menuItem setTitle:([chat isSecure] ? TITLE_MAKE_INSECURE : TITLE_MAKE_SECURE)]; @@ -311,10 +356,9 @@ case AISecureMessagingMenu_ShowAbout: return [chat supportsSecureMessagingToggling]; break; - - } } + return YES; } @@ -362,4 +406,6 @@ return([[_secureMessagingMenu copy] autorelease]); } +- (void)dummyAction:(id)sender {}; + @end -- 2.11.4.GIT