pEpObjCAdapter/PEPPassphraseCache.m
author Dirk Zimmermann <dz@pep.security>
Fri, 26 Jun 2020 16:54:34 +0200
branchIOSAD-172
changeset 1479 5f44fbef4658
parent 1478 17e48ad64829
child 1481 1418627a6351
permissions -rw-r--r--
IOSAD-172 Use configured timeout, not the default
     1 //
     2 //  PEPPassphraseCache.m
     3 //  pEpObjCAdapter
     4 //
     5 //  Created by Dirk Zimmermann on 25.06.20.
     6 //  Copyright © 2020 p≡p. All rights reserved.
     7 //
     8 
     9 #import "PEPPassphraseCache.h"
    10 
    11 #import "PEPPassphraseCacheInternal.h"
    12 
    13 #import "PEPPassphraseCacheEntry.h"
    14 
    15 static NSUInteger s_maxNumberOfPassphrases = 20;
    16 static NSTimeInterval s_defaultTimeoutInSeconds = 10 * 60;
    17 static NSTimeInterval s_defaultCheckExpiryInterval = 60;
    18 
    19 @interface PEPPassphraseCache ()
    20 
    21 /// Timeout of passwords in seconds.
    22 @property (nonatomic) NSTimeInterval timeout;
    23 
    24 @property (nonatomic) dispatch_queue_t queue;
    25 @property (nonatomic) NSMutableArray<PEPPassphraseCacheEntry *> *mutablePassphrases;
    26 @property (nonatomic) dispatch_source_t timer;
    27 
    28 @end
    29 
    30 @implementation PEPPassphraseCache
    31 
    32 /// Internal constructor (for now).
    33 - (instancetype)initWithPassphraseTimeout:(NSTimeInterval)timeout
    34                       checkExpiryInterval:(NSTimeInterval)checkExpiryInterval
    35 {
    36     self = [super init];
    37     if (self) {
    38         _timeout = timeout;
    39         _queue = dispatch_queue_create("PEPPassphraseCache Queue", DISPATCH_QUEUE_SERIAL);
    40         _mutablePassphrases = [NSMutableArray arrayWithCapacity:s_maxNumberOfPassphrases];
    41 
    42         // we have a strong reference to the timer, but the timer doesn't have one to us
    43         typeof(self) __weak weakSelf = self;
    44 
    45         _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, _queue);
    46         dispatch_source_set_timer(_timer,
    47                                   DISPATCH_TIME_NOW,
    48                                   checkExpiryInterval * NSEC_PER_SEC,
    49                                   checkExpiryInterval / 10 * NSEC_PER_SEC);
    50         dispatch_source_set_event_handler(_timer, ^{
    51             [weakSelf removeStaleEntries];
    52         });
    53         dispatch_resume(_timer);
    54     }
    55     return self;
    56 }
    57 
    58 /// Public constructor with default values.
    59 - (instancetype)init
    60 {
    61     return [self initWithPassphraseTimeout:s_defaultTimeoutInSeconds
    62                        checkExpiryInterval:s_defaultCheckExpiryInterval];
    63 }
    64 
    65 - (void)addPassphrase:(NSString *)passphrase
    66 {
    67     PEPPassphraseCacheEntry *entry = [[PEPPassphraseCacheEntry alloc]
    68                                       initWithPassphrase:passphrase];
    69     dispatch_sync(self.queue, ^{
    70         [self.mutablePassphrases addObject:entry];
    71         if (self.mutablePassphrases.count > s_maxNumberOfPassphrases) {
    72             [self.mutablePassphrases removeObjectAtIndex:0];
    73         }
    74     });
    75 }
    76 
    77 - (NSArray *)passphrases
    78 {
    79     NSMutableArray *resultingPassphrases = [NSMutableArray
    80                                             arrayWithCapacity:s_maxNumberOfPassphrases + 1];
    81     [resultingPassphrases addObject:@""];
    82     dispatch_sync(self.queue, ^{
    83         for (PEPPassphraseCacheEntry *entry in self.mutablePassphrases) {
    84             [resultingPassphrases addObject:entry.passphrase];
    85         }
    86     });
    87     return [NSArray arrayWithArray:resultingPassphrases];
    88 }
    89 
    90 /// Remove password entries that have timed out.
    91 /// - Note: Assumes it gets called on `queue`.
    92 - (void)removeStaleEntries
    93 {
    94     NSDate *now = [NSDate date];
    95     NSDate *minimum = [now dateByAddingTimeInterval:-self.timeout];
    96     NSTimeInterval minimumTimeInterval = [minimum timeIntervalSinceReferenceDate];
    97     NSMutableArray *resultingPassphrases = [NSMutableArray
    98                                             arrayWithCapacity:s_maxNumberOfPassphrases];
    99 
   100     for (PEPPassphraseCacheEntry *entry in self.mutablePassphrases) {
   101         if ([entry.dateAdded timeIntervalSinceReferenceDate] >= minimumTimeInterval) {
   102             [resultingPassphrases addObject:entry];
   103         }
   104     }
   105 
   106     [self.mutablePassphrases removeAllObjects];
   107     [self.mutablePassphrases addObjectsFromArray:resultingPassphrases];
   108 }
   109 
   110 @end