pEpObjCAdapter/PEPObjCAdapter.m
author Dirk Zimmermann <dz@pep.security>
Fri, 27 Nov 2020 18:20:10 +0100
branchIOSAD-185
changeset 2391 1d8448f5267b
parent 2351 59a3893a88e9
permissions -rw-r--r--
IOSAD-185 Guards for all headers
     1 //
     2 //  pEpObjCAdapter.m
     3 //  pEpObjCAdapter
     4 //
     5 //  Created by Volker Birk on 28.04.15.
     6 //  Copyright (c) 2015 p≡p. All rights reserved.
     7 //
     8 
     9 @import Foundation;
    10 
    11 #import "PEPObjCAdapter.h"
    12 #import "PEPObjCAdapter+Internal.h"
    13 #import "NSError+PEP.h"
    14 #import "NSString+NormalizePassphrase.h"
    15 #import "PEPInternalSession.h"
    16 #import "PEPPassphraseCache.h"
    17 
    18 #import <pEp4iosIntern/pEp4iosIntern.h>
    19 
    20 #import "keymanagement.h"
    21 #import "mime.h"
    22 #import "message.h"
    23 #import "message_api.h"
    24 
    25 const PEP_decrypt_flags PEP_decrypt_flag_none = 0x0;
    26 
    27 /**
    28  The pEp part of the home directory (where pEp is supposed to store data).
    29  */
    30 static NSString * const s_pEpHomeComponent = @"pEp_home";
    31 
    32 #if TARGET_OS_IPHONE
    33 // marked for iOS to think about what we want on macOS
    34 const char* _Nullable perMachineDirectory = NULL;
    35 #endif
    36 
    37 NSURL *s_homeURL;
    38 
    39 static BOOL s_unEncryptedSubjectEnabled = NO;
    40 static BOOL s_passiveModeEnabled = NO;
    41 static NSString *s_passphraseForNewKeys = nil;
    42 static id<PEPPassphraseProviderProtocol> s_passphraseProvider = nil;
    43 
    44 @implementation PEPObjCAdapter
    45 
    46 #pragma mark - SUBJECT PROTECTION
    47 
    48 + (BOOL)unEncryptedSubjectEnabled;
    49 {
    50     return s_unEncryptedSubjectEnabled;
    51 }
    52 
    53 + (void)setUnEncryptedSubjectEnabled:(BOOL)enabled;
    54 {
    55     s_unEncryptedSubjectEnabled = enabled;
    56 }
    57 
    58 #pragma mark - Passive Mode
    59 
    60 + (BOOL)passiveModeEnabled
    61 {
    62     return s_passiveModeEnabled;
    63 }
    64 
    65 + (void)setPassiveModeEnabled:(BOOL)enabled
    66 {
    67     s_passiveModeEnabled = enabled;
    68 }
    69 
    70 #pragma mark - Passphrase for own keys
    71 
    72 + (BOOL)configurePassphraseForNewKeys:(NSString * _Nullable)passphrase
    73                                 error:(NSError * _Nullable * _Nullable)error
    74 {
    75     if (passphrase == nil) {
    76         s_passphraseForNewKeys = nil;
    77         [[PEPPassphraseCache sharedInstance] setStoredPassphrase:passphrase];
    78 
    79         return YES;
    80     } else {
    81         NSString *normalizedPassphrase = [passphrase normalizedPassphraseWithError:error];
    82 
    83         if (normalizedPassphrase == nil) {
    84             return NO;
    85         }
    86 
    87         s_passphraseForNewKeys = normalizedPassphrase;
    88         [[PEPPassphraseCache sharedInstance] setStoredPassphrase:passphrase];
    89 
    90         return YES;
    91     }
    92 }
    93 
    94 + (NSString * _Nullable)passphraseForNewKeys
    95 {
    96     return s_passphraseForNewKeys;
    97 }
    98 
    99 #pragma mark - Passphrase Provider
   100 
   101 + (void)setPassphraseProvider:(id<PEPPassphraseProviderProtocol> _Nullable)passphraseProvider
   102 {
   103     s_passphraseProvider = passphraseProvider;
   104 }
   105 
   106 + (id<PEPPassphraseProviderProtocol> _Nullable)passphraseProvider
   107 {
   108     return s_passphraseProvider;
   109 }
   110 
   111 #pragma mark - DB PATHS
   112 
   113 + (void)initialize
   114 {
   115     s_homeURL = [self createApplicationDirectory];
   116 
   117     // The engine will put its per_user_directory under this directory.
   118     setenv("HOME", [[s_homeURL path] cStringUsingEncoding:NSUTF8StringEncoding], 1);
   119 
   120     // This sets the engine's per_machine_directory under iOS.
   121     [self setPerMachineDirectory:s_homeURL];
   122 }
   123 
   124 + (NSURL *)homeURL
   125 {
   126     return s_homeURL;
   127 }
   128 
   129 /**
   130  Looks up (and creates if necessary) a pEp directory under "Application Support".
   131 
   132  @return A URL pointing a pEp directory under "Application Support".
   133  */
   134 + (NSURL *)createApplicationDirectoryOSX
   135 {
   136     NSFileManager *fm = [NSFileManager defaultManager];
   137     NSURL *dirPath = nil;
   138 
   139     // Find the application support directory in the home directory.
   140     NSArray *appSupportDir = [fm URLsForDirectory:NSApplicationSupportDirectory
   141                                         inDomains:NSUserDomainMask];
   142     if ([appSupportDir count] > 0)
   143     {
   144         // Append the bundle ID to the URL for the
   145         // Application Support directory.
   146         // Mainly needed for OS X, but doesn't do any harm on iOS
   147         dirPath = [[appSupportDir objectAtIndex:0] URLByAppendingPathComponent:s_pEpHomeComponent];
   148 
   149         // If the directory does not exist, this method creates it.
   150         // This method is only available in OS X v10.7 and iOS 5.0 or later.
   151         NSError *theError = nil;
   152         if (![fm createDirectoryAtURL:dirPath withIntermediateDirectories:YES
   153                            attributes:nil error:&theError])
   154         {
   155             // Handle the error.
   156             return nil;
   157         }
   158     }
   159 
   160     return dirPath;
   161 }
   162 
   163 /**
   164  Looks up the shared directory for pEp apps under iOS and makes sure it exists.
   165 
   166  @return A URL pointing a pEp directory in the app container.
   167 */
   168 + (NSURL *)createApplicationDirectoryiOS
   169 {
   170     NSFileManager *fm = [NSFileManager defaultManager];
   171     NSURL *containerUrl = [fm containerURLForSecurityApplicationGroupIdentifier:appGroupIdentifier];
   172     NSLog(@"containerUrl '%@'", containerUrl);
   173 
   174     if (containerUrl == nil) {
   175         // Will happen when running tests, so fall back.
   176         NSArray *appSupportDir = [fm URLsForDirectory:NSApplicationSupportDirectory
   177                                             inDomains:NSUserDomainMask];
   178         containerUrl = [appSupportDir lastObject];
   179     }
   180 
   181     if (containerUrl == nil) {
   182         NSLog(@"ERROR: No app container, no application support directory.");
   183     }
   184 
   185     NSURL *dirPath = [containerUrl URLByAppendingPathComponent:s_pEpHomeComponent];
   186 
   187     // If the directory does not exist, this method creates it.
   188     NSError *theError = nil;
   189     if (![fm createDirectoryAtURL:dirPath withIntermediateDirectories:YES
   190                        attributes:nil error:&theError]) {
   191         NSLog(@"ERROR: Could not create pEp home directory, directly writing to app container instead.");
   192     }
   193 
   194     return dirPath;
   195 }
   196 
   197 /**
   198  Looks up the shared directory for pEp apps under iOS and makes sure it exists.
   199 
   200  Derived settings:
   201 
   202  * $HOME (the engine uses that).
   203  * The engine's per_user_directory (which is placed under $HOME).
   204  * The engine's per_machine_directory (see [PEPObjCAdapter setPerMachineDirectory:]).
   205 
   206  @return A URL pointing to as app-specific directory under the OS defined
   207  application support directory for the current user.
   208  */
   209 + (NSURL *)createApplicationDirectory
   210 {
   211 #if TARGET_OS_IPHONE
   212     return [self createApplicationDirectoryiOS];
   213 #else
   214     return [self createApplicationDirectoryOSX];
   215 #endif
   216 }
   217 
   218 /**
   219  Sets the directory that will be fed into the engine's per_machine_directory.
   220 
   221  Does not handle macOS. For macOS, either PER_MACHINE_DIRECTORY has to be defined
   222  (if constant), or this method has to be extended to handle it.
   223 
   224  @param perMachineDir The url to use as the per_machine_directory directory.
   225  */
   226 + (void)setPerMachineDirectory:(NSURL *)perMachineDir
   227 {
   228 #if TARGET_OS_IPHONE
   229     if (perMachineDirectory) {
   230         free((void *) perMachineDirectory);
   231     }
   232     perMachineDirectory = strdup([perMachineDir path].UTF8String);
   233 #endif
   234 }
   235 
   236 + (NSString *)getBundlePathFor: (NSString *) filename
   237 {
   238     return nil;
   239 }
   240 
   241 + (void)copyAssetsIntoDocumentsDirectory:(NSBundle *)rootBundle
   242                                     bundleName:(NSString *)bundleName
   243                                       fileName:(NSString *)fileName {
   244 
   245     NSString *systemDir = [NSString stringWithUTF8String:perMachineDirectory];
   246     
   247     if(!(systemDir && bundleName && fileName))
   248         return;
   249     
   250     // Check if the database file exists in the documents directory.
   251     NSString *destinationPath = [systemDir stringByAppendingPathComponent:fileName];
   252     if (![[NSFileManager defaultManager] fileExistsAtPath:destinationPath]) {
   253         // The file does not exist in the documents directory, so copy it from bundle now.
   254         NSBundle *bundleObj = [NSBundle bundleWithPath:
   255                                [[rootBundle resourcePath]
   256                                 stringByAppendingPathComponent: bundleName]];
   257         if (!bundleObj)
   258             return;
   259         
   260         NSString *sourcePath =[[bundleObj resourcePath] stringByAppendingPathComponent: fileName];
   261         
   262         NSError *error;
   263         [[NSFileManager defaultManager]
   264          copyItemAtPath:sourcePath toPath:destinationPath error:&error];
   265         
   266         // Check if any error occurred during copying and display it.
   267         if (error != nil) {
   268             NSLog(@"%@", [error localizedDescription]);
   269         }
   270     }
   271 }
   272 
   273 + (void)setupTrustWordsDB:(NSBundle *)rootBundle {
   274 // iOS to force us to think about macOS
   275 #if TARGET_OS_IPHONE
   276     [PEPObjCAdapter copyAssetsIntoDocumentsDirectory:rootBundle
   277                                           bundleName:@"pEpTrustWords.bundle"
   278                                             fileName:@"system.db"];
   279 
   280 #endif
   281 }
   282 
   283 + (void)setupTrustWordsDB
   284 {
   285     [PEPObjCAdapter setupTrustWordsDB:[NSBundle mainBundle]];
   286 }
   287 
   288 
   289 + (NSString * _Nonnull)perUserDirectoryString
   290 {
   291     return [NSString stringWithCString:per_user_directory() encoding:NSUTF8StringEncoding];
   292 }
   293 
   294 + (NSString * _Nonnull)perMachineDirectoryString
   295 {
   296     return [NSString stringWithCString:per_machine_directory() encoding:NSUTF8StringEncoding];
   297 }
   298 
   299 @end