pEpObjCAdapter/PEPInternalSession.m
author Dirk Zimmermann <dz@pep.security>
Tue, 03 Dec 2019 14:07:27 +0100
branchIOSAD-160
changeset 1372 ac119be204d2
parent 1369 c22f0fbc9597
child 1373 86bc00f43015
permissions -rw-r--r--
IOSAD-160 Add 2nd myself instead of changing the original one
     1 //
     2 //  PEPSession.m
     3 //  pEpiOSAdapter
     4 //
     5 //  Created by Volker Birk on 08.07.15.
     6 //  Copyright (c) 2015 p≡p. All rights reserved.
     7 //
     8 
     9 #import "PEPInternalSession.h"
    10 
    11 #import "PEPConstants.h"
    12 
    13 #import "PEPObjCAdapter.h"
    14 #import "PEPObjCAdapter+Internal.h"
    15 #import "PEPMessageUtil.h"
    16 #import "PEPLanguage.h"
    17 #import "PEPCSVScanner.h"
    18 #import "NSArray+Extension.h"
    19 #import "NSDictionary+CommType.h"
    20 #import "NSDictionary+Debug.h"
    21 #import "PEPIdentity.h"
    22 #import "PEPMessage.h"
    23 #import "NSError+PEP+Internal.h"
    24 #import "PEPAutoPointer.h"
    25 #import "NSNumber+PEPRating.h"
    26 #import "NSMutableDictionary+PEP.h"
    27 #import "PEPSync.h"
    28 #import "PEPSync_Internal.h" // for [PEPSync createSession:]
    29 #import "PEPInternalConstants.h"
    30 
    31 #import "key_reset.h"
    32 
    33 @implementation PEPInternalSession
    34 
    35 - (_Nullable instancetype)init
    36 {
    37     self = [super init];
    38     if (self) {
    39         [PEPInternalSession setupTrustWordsDB];
    40 
    41         // Get an engine session from PEPSync, because its creation requires callbacks
    42         // that PEPSync is responsible for.
    43         _session = [PEPSync createSession:nil];
    44 
    45         // [PEPSync createSession:] has already logged any errors.
    46         if (!_session) {
    47             return nil;
    48         }
    49     }
    50     return self;
    51 }
    52 
    53 - (void)dealloc
    54 {
    55     if (_session != nil) {
    56         release(_session);
    57     }
    58 }
    59 
    60 #pragma mark - CONFIG
    61 
    62 - (void)configUnEncryptedSubjectEnabled:(BOOL)enabled;
    63 {
    64     config_unencrypted_subject(self.session, enabled);
    65 }
    66 
    67 #pragma mark - INTERNAL
    68 
    69 + (void)setupTrustWordsDB
    70 {
    71     static dispatch_once_t once;
    72     dispatch_once(&once, ^{
    73         [PEPObjCAdapter setupTrustWordsDB:[NSBundle bundleForClass:[self class]]];
    74     });
    75 }
    76 
    77 #pragma mark - DEBUG UTILS
    78 
    79 #pragma mark - PEPSessionProtocol
    80 
    81 void decryptMessageDictFree(message *src, message *dst, stringlist_t *extraKeys)
    82 {
    83     free_message(src);
    84     free_message(dst);
    85     free_stringlist(extraKeys);
    86 }
    87 
    88 - (PEPDict * _Nullable)decryptMessageDict:(PEPMutableDict * _Nonnull)messageDict
    89                                     flags:(PEPDecryptFlags * _Nullable)flags
    90                                    rating:(PEPRating * _Nullable)rating
    91                                 extraKeys:(PEPStringList * _Nullable * _Nullable)extraKeys
    92                                    status:(PEPStatus * _Nullable)status
    93                                     error:(NSError * _Nullable * _Nullable)error
    94 {
    95     if (rating) {
    96         *rating = PEPRatingUndefined;
    97     }
    98 
    99     message *_src = PEP_messageDictToStruct(messageDict);
   100     message *_dst = NULL;
   101     stringlist_t *theKeys = NULL;
   102     PEPDecryptFlags theFlags = 0;
   103 
   104     if (flags) {
   105         theFlags = *flags;
   106     }
   107 
   108     if (extraKeys && [*extraKeys count]) {
   109         theKeys = PEP_arrayToStringlist(*extraKeys);
   110     }
   111 
   112     PEPRating internalRating = PEPRatingUndefined;
   113 
   114     PEPStatus theStatus = (PEPStatus) decrypt_message(_session,
   115                                                       _src,
   116                                                       &_dst,
   117                                                       &theKeys,
   118                                                       (PEP_rating *) &internalRating,
   119                                                       (PEP_decrypt_flags *) &theFlags);
   120 
   121     if (status) {
   122         *status = theStatus;
   123     }
   124 
   125     if ([NSError setError:error fromPEPStatus:theStatus]) {
   126         decryptMessageDictFree(_src, _dst, theKeys);
   127         return nil;
   128     }
   129 
   130     if (flags) {
   131         *flags = theFlags;
   132     }
   133 
   134     NSDictionary *dst_;
   135 
   136     if (_dst) {
   137         dst_ = PEP_messageDictFromStruct(_dst);
   138     } else {
   139         dst_ = PEP_messageDictFromStruct(_src);
   140     }
   141 
   142     if (theFlags & PEP_decrypt_flag_untrusted_server) {
   143         [messageDict replaceWithMessage:_src];
   144     }
   145 
   146     if (extraKeys) {
   147         *extraKeys = PEP_arrayFromStringlist(theKeys);
   148     }
   149 
   150     decryptMessageDictFree(_src, _dst, theKeys);
   151 
   152     if (rating) {
   153         *rating = internalRating;
   154     }
   155 
   156     return dst_;
   157 }
   158 
   159 - (PEPMessage * _Nullable)decryptMessage:(PEPMessage * _Nonnull)message
   160                                    flags:(PEPDecryptFlags * _Nullable)flags
   161                                   rating:(PEPRating * _Nullable)rating
   162                                extraKeys:(PEPStringList * _Nullable * _Nullable)extraKeys
   163                                   status:(PEPStatus * _Nullable)status
   164                                    error:(NSError * _Nullable * _Nullable)error
   165 {
   166     PEPDict *destDict = [self
   167                          decryptMessageDict:message.mutableDictionary
   168                          flags:flags
   169                          rating:rating
   170                          extraKeys:extraKeys
   171                          status:status
   172                          error:error];
   173 
   174     if (destDict) {
   175         PEPMessage *msg = [PEPMessage new];
   176         [msg setValuesForKeysWithDictionary:destDict];
   177         return msg;
   178     } else {
   179         return nil;
   180     }
   181 }
   182 
   183 - (BOOL)reEvaluateMessageDict:(PEPDict * _Nonnull)messageDict
   184                      xKeyList:(PEPStringList * _Nullable)xKeyList
   185                        rating:(PEPRating * _Nonnull)rating
   186                        status:(PEPStatus * _Nullable)status
   187                         error:(NSError * _Nullable * _Nullable)error
   188 {
   189     message *_src = PEP_messageDictToStruct(messageDict);
   190 
   191     stringlist_t *theKeys = NULL;
   192     if ([xKeyList count]) {
   193         theKeys = PEP_arrayToStringlist(xKeyList);
   194     }
   195 
   196     PEPStatus theStatus = (PEPStatus) re_evaluate_message_rating(_session,
   197                                                                  _src,
   198                                                                  theKeys,
   199                                                                  (PEP_rating) *rating,
   200                                                                  (PEP_rating *) rating);
   201 
   202     free_message(_src);
   203     free_stringlist(theKeys);
   204 
   205     if (status) {
   206         *status = theStatus;
   207     }
   208 
   209     if ([NSError setError:error fromPEPStatus:theStatus]) {
   210         return NO;
   211     } else {
   212         return YES;
   213     }
   214 }
   215 
   216 - (BOOL)reEvaluateMessage:(PEPMessage * _Nonnull)message
   217                  xKeyList:(PEPStringList * _Nullable)xKeyList
   218                    rating:(PEPRating * _Nonnull)rating
   219                    status:(PEPStatus * _Nullable)status
   220                     error:(NSError * _Nullable * _Nullable)error
   221 {
   222     return [self reEvaluateMessageDict:(PEPDict *) message
   223                               xKeyList:xKeyList
   224                                 rating:rating
   225                                 status:status
   226                                  error:error];
   227 }
   228 
   229 - (void)removeEmptyArrayKey:(NSString *)key inDict:(PEPMutableDict *)dict
   230 {
   231     if ([[dict objectForKey:key] count] == 0) {
   232         [dict removeObjectForKey:key];
   233     }
   234 }
   235 
   236 - (NSDictionary *)removeEmptyRecipients:(PEPDict *)src
   237 {
   238     NSMutableDictionary *dest = src.mutableCopy;
   239 
   240     [self removeEmptyArrayKey:kPepTo inDict:dest];
   241     [self removeEmptyArrayKey:kPepCC inDict:dest];
   242     [self removeEmptyArrayKey:kPepBCC inDict:dest];
   243 
   244     return dest;
   245 }
   246 
   247 - (PEPDict * _Nullable)encryptMessageDict:(PEPDict * _Nonnull)messageDict
   248                                 extraKeys:(PEPStringList * _Nullable)extraKeys
   249                                 encFormat:(PEPEncFormat)encFormat
   250                                    status:(PEPStatus * _Nullable)status
   251                                     error:(NSError * _Nullable * _Nullable)error
   252 {
   253     PEP_encrypt_flags_t flags = 0;
   254 
   255     message *_src = PEP_messageDictToStruct([self removeEmptyRecipients:messageDict]);
   256     message *_dst = NULL;
   257     stringlist_t *_keys = PEP_arrayToStringlist(extraKeys);
   258 
   259     PEPStatus theStatus = (PEPStatus) encrypt_message(_session,
   260                                                       _src,
   261                                                       _keys,
   262                                                       &_dst,
   263                                                       (PEP_enc_format) encFormat,
   264                                                       flags);
   265 
   266     if (status) {
   267         *status = theStatus;
   268     }
   269 
   270     if ([NSError setError:error fromPEPStatus:theStatus]) {
   271         return nil;
   272     }
   273 
   274     NSDictionary *dst_;
   275 
   276     if (_dst) {
   277         dst_ = PEP_messageDictFromStruct(_dst);
   278     }
   279     else {
   280         dst_ = PEP_messageDictFromStruct(_src);
   281     }
   282 
   283     free_message(_src);
   284     free_message(_dst);
   285     free_stringlist(_keys);
   286 
   287     return dst_;
   288 }
   289 
   290 - (PEPMessage * _Nullable)encryptMessage:(PEPMessage * _Nonnull)message
   291                                extraKeys:(PEPStringList * _Nullable)extraKeys
   292                                encFormat:(PEPEncFormat)encFormat
   293                                   status:(PEPStatus * _Nullable)status
   294                                    error:(NSError * _Nullable * _Nullable)error
   295 {
   296     PEPDict *encryptedDict = [self encryptMessageDict:(NSDictionary *) message
   297                                             extraKeys:extraKeys
   298                                             encFormat:encFormat
   299                                                status:status
   300                                                 error:error];
   301     if (encryptedDict) {
   302         PEPMessage *encrypted = [PEPMessage new];
   303         [encrypted setValuesForKeysWithDictionary:encryptedDict];
   304         return encrypted;
   305     } else {
   306         return nil;
   307     }
   308 }
   309 
   310 - (PEPMessage * _Nullable)encryptMessage:(PEPMessage * _Nonnull)message
   311                                extraKeys:(PEPStringList * _Nullable)extraKeys
   312                                   status:(PEPStatus * _Nullable)status
   313                                    error:(NSError * _Nullable * _Nullable)error
   314 {
   315     return [self
   316             encryptMessage:message
   317             extraKeys:extraKeys
   318             encFormat:PEPEncFormatPEP
   319             status:status
   320             error:error];
   321 }
   322 
   323 - (PEPDict * _Nullable)encryptMessageDict:(PEPDict * _Nonnull)messageDict
   324                                   forSelf:(PEPIdentity * _Nonnull)ownIdentity
   325                                 extraKeys:(PEPStringList * _Nullable)extraKeys
   326                                    status:(PEPStatus * _Nullable)status
   327                                     error:(NSError * _Nullable * _Nullable)error
   328 {
   329     PEP_encrypt_flags_t flags = 0;
   330 
   331     message *_src = PEP_messageDictToStruct([self removeEmptyRecipients:messageDict]);
   332     pEp_identity *ident = PEP_identityToStruct(ownIdentity);
   333     message *_dst = NULL;
   334 
   335     stringlist_t *keysStringList = PEP_arrayToStringlist(extraKeys);
   336 
   337     PEPStatus theStatus = (PEPStatus) encrypt_message_for_self(_session,
   338                                                                ident,
   339                                                                _src,
   340                                                                keysStringList,
   341                                                                &_dst,
   342                                                                PEP_enc_PGP_MIME,
   343                                                                flags);
   344 
   345     free_stringlist(keysStringList);
   346 
   347     if (status) {
   348         *status = theStatus;
   349     }
   350 
   351     if ([NSError setError:error fromPEPStatus:theStatus]) {
   352         return nil;
   353     }
   354 
   355     NSDictionary *dst_;
   356 
   357     if (_dst) {
   358         dst_ = PEP_messageDictFromStruct(_dst);
   359     }
   360     else {
   361         dst_ = PEP_messageDictFromStruct(_src);
   362     }
   363 
   364     free_message(_src);
   365     free_message(_dst);
   366     free_identity(ident);
   367 
   368     return dst_;
   369 }
   370 
   371 - (PEPMessage * _Nullable)encryptMessage:(PEPMessage * _Nonnull)message
   372                                  forSelf:(PEPIdentity * _Nonnull)ownIdentity
   373                                extraKeys:(PEPStringList * _Nullable)extraKeys
   374                                   status:(PEPStatus * _Nullable)status
   375                                    error:(NSError * _Nullable * _Nullable)error
   376 {
   377     PEPDict *target = [self
   378                        encryptMessageDict:message.dictionary
   379                        forSelf:ownIdentity
   380                        extraKeys:extraKeys
   381                        status:status
   382                        error:error];
   383     if (target) {
   384         PEPMessage *encrypted = [PEPMessage new];
   385         [encrypted setValuesForKeysWithDictionary:target];
   386         return encrypted;
   387     } else {
   388         return nil;
   389     }
   390 }
   391 
   392 
   393 - (PEPDict * _Nullable)encryptMessageDict:(PEPDict * _Nonnull)messageDict
   394                                     toFpr:(NSString * _Nonnull)toFpr
   395                                 encFormat:(PEPEncFormat)encFormat
   396                                     flags:(PEPDecryptFlags)flags
   397                                    status:(PEPStatus * _Nullable)status
   398                                     error:(NSError * _Nullable * _Nullable)error __deprecated
   399 {
   400     message *src = PEP_messageDictToStruct([self removeEmptyRecipients:messageDict]);
   401     message *dst = NULL;
   402 
   403     PEPStatus theStatus = (PEPStatus)
   404     encrypt_message_and_add_priv_key(_session, src, &dst,
   405                                      [[toFpr precomposedStringWithCanonicalMapping] UTF8String],
   406                                      (PEP_enc_format) encFormat, flags);
   407 
   408     if (status) {
   409         *status = theStatus;
   410     }
   411 
   412     if ([NSError setError:error fromPEPStatus:theStatus]) {
   413         return nil;
   414     }
   415 
   416     if (dst) {
   417         return PEP_messageDictFromStruct(dst);
   418     }
   419 
   420     return nil;
   421 }
   422 
   423 - (PEPMessage * _Nullable)encryptMessage:(PEPMessage * _Nonnull)message
   424                                    toFpr:(NSString * _Nonnull)toFpr
   425                                encFormat:(PEPEncFormat)encFormat
   426                                    flags:(PEPDecryptFlags)flags
   427                                   status:(PEPStatus * _Nullable)status
   428                                    error:(NSError * _Nullable * _Nullable)error
   429 {
   430     PEPDict *target = [self
   431                        encryptMessageDict:message.dictionary
   432                        toFpr:toFpr
   433                        encFormat:encFormat
   434                        flags:flags
   435                        status:status
   436                        error:error];
   437 
   438     if (target) {
   439         PEPMessage *encrypted = [PEPMessage new];
   440         [encrypted setValuesForKeysWithDictionary:target];
   441         return encrypted;
   442     } else {
   443         return nil;
   444     }
   445 }
   446 
   447 typedef PEP_STATUS (* rating_function_type)(PEP_SESSION session, message *msg, PEP_rating *rating);
   448 
   449 - (NSNumber * _Nullable)helperOutgoingRatingForMessage:(PEPMessage * _Nonnull)theMessage
   450                                         ratingFunction:(rating_function_type)ratingFunction
   451                                                  error:(NSError * _Nullable * _Nullable)error
   452 {
   453     message *_msg = PEP_messageToStruct(theMessage);
   454     PEPRating rating = PEPRatingUndefined;
   455 
   456     PEPStatus status = (PEPStatus) ratingFunction(_session, _msg, (PEP_rating *) &rating);
   457 
   458     free_message(_msg);
   459 
   460     if ([NSError setError:error fromPEPStatus:status]) {
   461         return nil;
   462     }
   463 
   464     return [NSNumber numberWithPEPRating:rating];
   465 }
   466 
   467 - (NSNumber * _Nullable)outgoingRatingForMessage:(PEPMessage * _Nonnull)theMessage
   468                                            error:(NSError * _Nullable * _Nullable)error
   469 {
   470     return [self
   471             helperOutgoingRatingForMessage:theMessage
   472             ratingFunction:&outgoing_message_rating
   473             error:error];
   474 }
   475 
   476 - (NSNumber * _Nullable)outgoingRatingPreviewForMessage:(PEPMessage * _Nonnull)theMessage
   477                                                   error:(NSError * _Nullable * _Nullable)error
   478 {
   479     return [self
   480             helperOutgoingRatingForMessage:theMessage
   481             ratingFunction:&outgoing_message_rating_preview
   482             error:error];
   483 }
   484 
   485 - (NSNumber * _Nullable)ratingForIdentity:(PEPIdentity * _Nonnull)identity
   486                                     error:(NSError * _Nullable * _Nullable)error
   487 {
   488     pEp_identity *ident = PEP_identityToStruct(identity);
   489     PEPRating rating = PEPRatingUndefined;
   490 
   491     PEPStatus status = (PEPStatus) identity_rating(_session, ident, (PEP_rating *) &rating);
   492 
   493     free_identity(ident);
   494 
   495     if ([NSError setError:error fromPEPStatus:status]) {
   496         return nil;
   497     }
   498 
   499     return [NSNumber numberWithPEPRating:rating];
   500 }
   501 
   502 - (NSArray * _Nullable)trustwordsForFingerprint:(NSString * _Nonnull)fingerprint
   503                                      languageID:(NSString * _Nonnull)languageID
   504                                       shortened:(BOOL)shortened
   505                                           error:(NSError * _Nullable * _Nullable)error
   506 {
   507     NSMutableArray *array = [NSMutableArray array];
   508 
   509     for (int i = 0; i < [fingerprint length]; i += 4) {
   510         if (shortened && i >= 20)
   511             break;
   512 
   513         NSString *str = [fingerprint substringWithRange:NSMakeRange(i, 4)];
   514 
   515         unsigned int value;
   516         [[NSScanner scannerWithString:str] scanHexInt:&value];
   517 
   518         PEPAutoPointer *word = [PEPAutoPointer new];
   519         size_t size;
   520 
   521         PEPStatus status = (PEPStatus) trustword(_session,
   522                                                  value,
   523                                                  [[languageID precomposedStringWithCanonicalMapping]
   524                                                   UTF8String],
   525                                                  word.charPointerPointer,
   526                                                  &size);
   527 
   528         if ([NSError setError:error fromPEPStatus:status]) {
   529             return nil;
   530         }
   531 
   532         [array addObject:[NSString stringWithUTF8String:word.charPointer]];
   533     }
   534 
   535     return array;
   536 }
   537 
   538 - (BOOL)mySelf:(PEPIdentity * _Nonnull)identity
   539          error:(NSError * _Nullable * _Nullable)error
   540 {
   541     // The default for pEpSyncEnabled is YES, that means the adapter
   542     // will not change the engine identity in that regard after new_identity
   543     // (called by PEP_identityToStruct).
   544     return [self mySelf:identity pEpSyncEnabled:YES error:error];
   545 }
   546 
   547 - (BOOL)mySelf:(PEPIdentity * _Nonnull)identity
   548 pEpSyncEnabled:(BOOL)pEpSyncEnabled
   549          error:(NSError * _Nullable * _Nullable)error {
   550     pEp_identity *ident = PEP_identityToStruct(identity);
   551 
   552     PEPStatus status = (PEPStatus) myself(_session, ident);
   553 
   554     if ([NSError setError:error fromPEPStatus:status]) {
   555         free_identity(ident);
   556         return NO;
   557     }
   558 
   559     [identity reset];
   560     [identity setValuesForKeysWithDictionary:PEP_identityDictFromStruct(ident)];
   561     free_identity(ident);
   562 
   563     return YES;
   564 }
   565 
   566 - (BOOL)updateIdentity:(PEPIdentity * _Nonnull)identity error:(NSError * _Nullable * _Nullable)error
   567 {
   568     pEp_identity *ident = PEP_identityToStruct(identity);
   569 
   570     PEPStatus status = (PEPStatus) update_identity(_session, ident);
   571 
   572     if ([NSError setError:error fromPEPStatus:status]) {
   573         free_identity(ident);
   574         return NO;
   575     }
   576 
   577     [identity reset];
   578     [identity setValuesForKeysWithDictionary:PEP_identityDictFromStruct(ident)];
   579     free_identity(ident);
   580 
   581     return YES;
   582 }
   583 
   584 - (BOOL)trustPersonalKey:(PEPIdentity * _Nonnull)identity
   585                    error:(NSError * _Nullable * _Nullable)error
   586 {
   587     pEp_identity *ident = PEP_identityToStruct(identity);
   588 
   589     PEPStatus status = (PEPStatus) trust_personal_key(_session, ident);
   590 
   591     if ([NSError setError:error fromPEPStatus:status]) {
   592         free_identity(ident);
   593         return NO;
   594     }
   595 
   596     [identity reset];
   597     [identity setValuesForKeysWithDictionary:PEP_identityDictFromStruct(ident)];
   598     free_identity(ident);
   599     return YES;
   600 }
   601 
   602 - (BOOL)keyMistrusted:(PEPIdentity *)identity error:(NSError * _Nullable * _Nullable)error
   603 {
   604     pEp_identity *ident = PEP_identityToStruct(identity);
   605 
   606     PEPStatus status = (PEPStatus) key_mistrusted(_session, ident);
   607 
   608     if ([NSError setError:error fromPEPStatus:status]) {
   609         free_identity(ident);
   610         return NO;
   611     }
   612 
   613     [identity reset];
   614     [identity setValuesForKeysWithDictionary:PEP_identityDictFromStruct(ident)];
   615     free_identity(ident);
   616 
   617     return YES;
   618 }
   619 
   620 - (BOOL)keyResetTrust:(PEPIdentity * _Nonnull)identity
   621                 error:(NSError * _Nullable * _Nullable)error
   622 {
   623     pEp_identity *ident = PEP_identityToStruct(identity);
   624 
   625     PEPStatus status = (PEPStatus) key_reset_trust(_session, ident);
   626 
   627     if ([NSError setError:error fromPEPStatus:status]) {
   628         free_identity(ident);
   629         return NO;
   630     }
   631 
   632     [identity reset];
   633     [identity setValuesForKeysWithDictionary:PEP_identityDictFromStruct(ident)];
   634     free_identity(ident);
   635 
   636     return YES;
   637 }
   638 
   639 - (BOOL)enableSyncForIdentity:(PEPIdentity * _Nonnull)identity
   640                         error:(NSError * _Nullable * _Nullable)error
   641 {
   642     if (!identity.isOwn) {
   643         [NSError setError:error fromPEPStatus:PEPStatusIllegalValue];
   644         return NO;
   645     }
   646 
   647     pEp_identity *ident = PEP_identityToStruct(identity);
   648 
   649     PEPStatus status = (PEPStatus) enable_identity_for_sync(_session, ident);
   650 
   651     if ([NSError setError:error fromPEPStatus:status]) {
   652         free_identity(ident);
   653         return NO;
   654     }
   655 
   656     free_identity(ident);
   657 
   658     return YES;
   659 }
   660 
   661 - (BOOL)disableSyncForIdentity:(PEPIdentity * _Nonnull)identity
   662                          error:(NSError * _Nullable * _Nullable)error
   663 {
   664     if (!identity.isOwn) {
   665         [NSError setError:error fromPEPStatus:PEPStatusIllegalValue];
   666         return NO;
   667     }
   668 
   669     pEp_identity *ident = PEP_identityToStruct(identity);
   670 
   671     PEPStatus status = (PEPStatus) disable_identity_for_sync(_session, ident);
   672 
   673     if ([NSError setError:error fromPEPStatus:status]) {
   674         free_identity(ident);
   675         return NO;
   676     }
   677 
   678     free_identity(ident);
   679 
   680     return YES;
   681 }
   682 
   683 - (NSNumber * _Nullable)queryKeySyncEnabledForIdentity:(PEPIdentity * _Nonnull)identity
   684                                                  error:(NSError * _Nullable * _Nullable)error
   685 {
   686     pEp_identity *ident = PEP_identityToStruct(identity);
   687 
   688     if (!identity.isOwn) {
   689         [NSError setError:error fromPEPStatus:PEPStatusIllegalValue];
   690         return nil;
   691     }
   692 
   693     PEPStatus status = (PEPStatus) myself(_session, ident);
   694 
   695     if ([NSError setError:error fromPEPStatus:status]) {
   696         free_identity(ident);
   697         return nil;
   698     }
   699 
   700     identity_flags_t flags = ident->flags;
   701 
   702     free_identity(ident);
   703 
   704     if (flags & PEP_idf_not_for_sync) {
   705         return [NSNumber numberWithBool:NO];
   706     } else {
   707         return [NSNumber numberWithBool:YES];
   708     }
   709 }
   710 
   711 - (NSArray<PEPIdentity *> * _Nullable)importKey:(NSString * _Nonnull)keydata
   712                                           error:(NSError * _Nullable * _Nullable)error
   713 {
   714     identity_list *identList = NULL;
   715 
   716     PEPStatus status = (PEPStatus) import_key(_session,
   717                                               [[keydata precomposedStringWithCanonicalMapping] UTF8String],
   718                                               [keydata length], &identList);
   719 
   720     if ([NSError setError:error fromPEPStatus:status]) {
   721         free(identList);
   722         return nil;
   723     }
   724 
   725     NSArray *idents = PEP_arrayFromIdentityList(identList);
   726     free(identList);
   727 
   728     return idents;
   729 }
   730 
   731 - (BOOL)logTitle:(NSString * _Nonnull)title
   732           entity:(NSString * _Nonnull)entity
   733      description:(NSString * _Nullable)description
   734          comment:(NSString * _Nullable)comment
   735            error:(NSError * _Nullable * _Nullable)error
   736 {
   737     PEPStatus status = (PEPStatus) log_event(_session,
   738                                              [[title precomposedStringWithCanonicalMapping]
   739                                               UTF8String],
   740                                              [[entity precomposedStringWithCanonicalMapping]
   741                                               UTF8String],
   742                                              [[description precomposedStringWithCanonicalMapping]
   743                                               UTF8String],
   744                                              [[comment precomposedStringWithCanonicalMapping]
   745                                               UTF8String]);
   746 
   747     if ([NSError setError:error fromPEPStatus:status]) {
   748         return NO;
   749     } else {
   750         return YES;
   751     }
   752 }
   753 
   754 - (NSString * _Nullable)getLogWithError:(NSError * _Nullable * _Nullable)error
   755 {
   756     char *theChars = NULL;
   757     PEPStatus status = (PEPStatus) get_crashdump_log(_session, 0, &theChars);
   758 
   759     if ([NSError setError:error fromPEPStatus:status]) {
   760         return nil;
   761     }
   762 
   763     if (theChars) {
   764         return [NSString stringWithUTF8String:theChars];
   765     } else {
   766         [NSError setError:error fromPEPStatusInternal:PEP_UNKNOWN_ERROR];
   767         return nil;
   768     }
   769 }
   770 
   771 - (NSString * _Nullable)getTrustwordsIdentity1:(PEPIdentity * _Nonnull)identity1
   772                                      identity2:(PEPIdentity * _Nonnull)identity2
   773                                       language:(NSString * _Nullable)language
   774                                           full:(BOOL)full
   775                                          error:(NSError * _Nullable * _Nullable)error
   776 {
   777     pEp_identity *ident1 = PEP_identityToStruct(identity1);
   778     pEp_identity *ident2 = PEP_identityToStruct(identity2);
   779     PEPStatus status;
   780 
   781     PEPAutoPointer *trustwords = [PEPAutoPointer new];
   782     size_t sizeWritten = 0;
   783 
   784     status = (PEPStatus) get_trustwords(_session, ident1, ident2,
   785                                         [[language precomposedStringWithCanonicalMapping]
   786                                          UTF8String],
   787                                         trustwords.charPointerPointer, &sizeWritten, full);
   788 
   789     free_identity(ident1);
   790     free_identity(ident2);
   791 
   792     NSString *result = nil;
   793 
   794     if (![NSError setError:error fromPEPStatus:status]) {
   795         result = [NSString stringWithUTF8String:trustwords.charPointer];
   796     }
   797 
   798     return result;
   799 }
   800 
   801 - (NSString * _Nullable)getTrustwordsFpr1:(NSString * _Nonnull)fpr1
   802                                      fpr2:(NSString * _Nonnull)fpr2
   803                                  language:(NSString * _Nullable)language
   804                                      full:(BOOL)full
   805                                     error:(NSError * _Nullable * _Nullable)error
   806 {
   807     const char *_fpr1 = [fpr1 UTF8String]; // fprs are NFC normalized anyway
   808     const char *_fpr2 = [fpr2 UTF8String];
   809     
   810     PEPStatus status;
   811     
   812     PEPAutoPointer *trustwords = [PEPAutoPointer new];
   813     size_t sizeWritten = 0;
   814 
   815     status = (PEPStatus) get_trustwords_for_fprs(_session, _fpr1, _fpr2,
   816                                                  [[language precomposedStringWithCanonicalMapping]
   817                                                   UTF8String],
   818                                                  trustwords.charPointerPointer, &sizeWritten, full);
   819     
   820     NSString *result = nil;
   821     
   822     if (![NSError setError:error fromPEPStatus:status]) {
   823         result = [NSString stringWithUTF8String:trustwords.charPointer];
   824     }
   825     
   826     return result;
   827 }
   828 
   829 - (NSArray<PEPLanguage *> * _Nullable)languageListWithError:(NSError * _Nullable * _Nullable)error
   830 {
   831     PEPAutoPointer *chLangs = [PEPAutoPointer new];
   832     PEPStatus status = (PEPStatus) get_languagelist(_session, chLangs.charPointerPointer);
   833 
   834     if ([NSError setError:error fromPEPStatus:status]) {
   835         return nil;
   836     }
   837 
   838     NSString *parserInput = [NSString stringWithUTF8String:chLangs.charPointer];
   839 
   840     NSMutableArray<NSString *> *tokens = [NSMutableArray array];
   841     PEPCSVScanner *scanner = [[PEPCSVScanner alloc] initWithString:parserInput];
   842     while (YES) {
   843         NSString *token = [scanner nextString];
   844         if (!token) {
   845             break;
   846         }
   847         [tokens addObject:token];
   848     }
   849     
   850     NSArray *theTokens = [NSArray arrayWithArray:tokens];
   851     NSMutableArray<PEPLanguage *> *langs = [NSMutableArray new];
   852     while (YES) {
   853         ArrayTake *take = [theTokens takeOrNil:3];
   854         if (!take) {
   855             break;
   856         }
   857         NSArray *elements = take.elements;
   858         PEPLanguage *lang = [[PEPLanguage alloc]
   859                              initWithCode:[elements objectAtIndex:0]
   860                              name:[elements objectAtIndex:1]
   861                              sentence:[elements objectAtIndex:2]];
   862         [langs addObject:lang];
   863         theTokens = take.rest;
   864     }
   865     
   866     return [NSArray arrayWithArray:langs];
   867 }
   868 
   869 static NSDictionary *ratingToString;
   870 static NSDictionary *stringToRating;
   871 
   872 + (void)initialize
   873 {
   874     NSDictionary *ratingToStringIntern =
   875     @{
   876       [NSNumber numberWithInteger:PEPRatingCannotDecrypt]: @"cannot_decrypt",
   877       [NSNumber numberWithInteger:PEPRatingHaveNoKey]: @"have_no_key",
   878       [NSNumber numberWithInteger:PEPRatingUnencrypted]: @"unencrypted",
   879       [NSNumber numberWithInteger:PEPRatingUnencryptedForSome]: @"unencrypted_for_some",
   880       [NSNumber numberWithInteger:PEPRatingUnreliable]: @"unreliable",
   881       [NSNumber numberWithInteger:PEPRatingReliable]: @"reliable",
   882       [NSNumber numberWithInteger:PEPRatingTrusted]: @"trusted",
   883       [NSNumber numberWithInteger:PEPRatingTrustedAndAnonymized]: @"trusted_and_anonymized",
   884       [NSNumber numberWithInteger:PEPRatingFullyAnonymous]: @"fully_anonymous",
   885       [NSNumber numberWithInteger:PEPRatingMistrust]: @"mistrust",
   886       [NSNumber numberWithInteger:PEPRatingB0rken]: @"b0rken",
   887       [NSNumber numberWithInteger:PEPRatingUnderAttack]: @"under_attack",
   888       [NSNumber numberWithInteger:PEPRatingUndefined]: kUndefined,
   889       };
   890     NSMutableDictionary *stringToRatingMutable = [NSMutableDictionary
   891                                                   dictionaryWithCapacity:
   892                                                   ratingToStringIntern.count];
   893     for (NSNumber *ratingNumber in ratingToStringIntern.allKeys) {
   894         NSString *ratingName = [ratingToStringIntern objectForKey:ratingNumber];
   895         [stringToRatingMutable setObject:ratingNumber forKey:ratingName];
   896     }
   897     ratingToString = ratingToStringIntern;
   898     stringToRating = [NSDictionary dictionaryWithDictionary:stringToRatingMutable];
   899 }
   900 
   901 - (PEPRating)ratingFromString:(NSString * _Nonnull)string
   902 {
   903     NSNumber *num = [stringToRating objectForKey:string];
   904     if (num) {
   905         return (PEPRating) [num integerValue];
   906     } else {
   907         return PEPRatingUndefined;
   908     }
   909 }
   910 
   911 - (NSString * _Nonnull)stringFromRating:(PEPRating)rating
   912 {
   913     NSString *stringRating = [ratingToString objectForKey:[NSNumber numberWithInteger:rating]];
   914     if (stringRating) {
   915         return stringRating;
   916     } else {
   917         return kUndefined;
   918     }
   919 }
   920 
   921 - (NSNumber * _Nullable)isPEPUser:(PEPIdentity * _Nonnull)identity
   922                             error:(NSError * _Nullable * _Nullable)error
   923 {
   924     pEp_identity *ident = PEP_identityToStruct(identity);
   925     bool isPEP;
   926     PEPStatus status = (PEPStatus) is_pEp_user(self.session, ident, &isPEP);
   927 
   928     free_identity(ident);
   929 
   930     if ([NSError setError:error fromPEPStatus:status]) {
   931         return nil;
   932     } else {
   933         return [NSNumber numberWithBool:isPEP];
   934     }
   935 }
   936 
   937 - (BOOL)setOwnKey:(PEPIdentity * _Nonnull)identity fingerprint:(NSString * _Nonnull)fingerprint
   938             error:(NSError * _Nullable * _Nullable)error
   939 {
   940     pEp_identity *ident = PEP_identityToStruct(identity);
   941     PEPStatus status = (PEPStatus) set_own_key(self.session, ident,
   942                                                [[fingerprint precomposedStringWithCanonicalMapping]
   943                                                 UTF8String]);
   944     free_identity(ident);
   945 
   946     if ([NSError setError:error fromPEPStatus:status]) {
   947         return NO;
   948     } else {
   949         return YES;
   950     }
   951 }
   952 
   953 - (void)configurePassiveModeEnabled:(BOOL)enabled
   954 {
   955     config_passive_mode(_session, enabled);
   956 }
   957 
   958 - (BOOL)setFlags:(PEPIdentityFlags)flags
   959      forIdentity:(PEPIdentity *)identity
   960            error:(NSError * _Nullable * _Nullable)error
   961 {
   962     pEp_identity *ident = PEP_identityToStruct(identity);
   963     PEPStatus status = (PEPStatus) set_identity_flags(self.session, ident, flags);
   964     free_identity(ident);
   965 
   966     if ([NSError setError:error fromPEPStatus:status]) {
   967         return NO;
   968     } else {
   969         return YES;
   970     }
   971 }
   972 
   973 - (BOOL)deliverHandshakeResult:(PEPSyncHandshakeResult)result
   974              identitiesSharing:(NSArray<PEPIdentity *> * _Nullable)identitiesSharing
   975                          error:(NSError * _Nullable * _Nullable)error;
   976 {
   977     identity_list *identitiesSharingData = NULL;
   978 
   979     if (identitiesSharing) {
   980         identitiesSharingData = PEP_identityArrayToList(identitiesSharing);
   981     }
   982 
   983     PEPStatus status = (PEPStatus) deliverHandshakeResult(self.session,
   984                                                           (sync_handshake_result) result,
   985                                                           identitiesSharingData);
   986 
   987     free(identitiesSharingData);
   988 
   989     if ([NSError setError:error fromPEPStatus:status]) {
   990         return NO;
   991     } else {
   992         return YES;
   993     }
   994 }
   995 
   996 - (BOOL)trustOwnKeyIdentity:(PEPIdentity * _Nonnull)identity
   997                       error:(NSError * _Nullable * _Nullable)error
   998 {
   999     pEp_identity *ident = PEP_identityToStruct(identity);
  1000     PEPStatus status = (PEPStatus) trust_own_key(self.session, ident);
  1001     free_identity(ident);
  1002 
  1003     if ([NSError setError:error fromPEPStatus:status]) {
  1004         return NO;
  1005     } else {
  1006         return YES;
  1007     }
  1008 }
  1009 
  1010 - (PEPColor)colorFromRating:(PEPRating)rating
  1011 {
  1012     return (PEPColor) color_from_rating((PEP_rating) rating);
  1013 }
  1014 
  1015 
  1016 - (BOOL)keyReset:(PEPIdentity * _Nonnull)identity
  1017      fingerprint:(NSString * _Nullable)fingerprint
  1018            error:(NSError * _Nullable * _Nullable)error
  1019 {
  1020     pEp_identity *ident = PEP_identityToStruct(identity);
  1021     const char *fpr = [[fingerprint precomposedStringWithCanonicalMapping] UTF8String];
  1022 
  1023     PEPStatus status = (PEPStatus) key_reset_identity(self.session, ident, fpr);
  1024 
  1025     free_identity(ident);
  1026 
  1027     if ([NSError setError:error fromPEPStatus:status]) {
  1028         return NO;
  1029     } else {
  1030         return YES;
  1031     }
  1032 }
  1033 
  1034 - (BOOL)leaveDeviceGroup:(NSError * _Nullable * _Nullable)error
  1035 {
  1036     PEPStatus status = (PEPStatus) leave_device_group(self.session);
  1037 
  1038     if ([NSError setError:error fromPEPStatus:status]) {
  1039         return NO;
  1040     } else {
  1041         return YES;
  1042     }
  1043 }
  1044 
  1045 - (BOOL)keyResetAllOwnKeysError:(NSError * _Nullable * _Nullable)error
  1046 {
  1047     PEPStatus status = (PEPStatus) key_reset_all_own_keys(self.session);
  1048 
  1049     if ([NSError setError:error fromPEPStatus:status]) {
  1050         return NO;
  1051     } else {
  1052         return YES;
  1053     }
  1054 }
  1055 
  1056 @end