Make user defaults more secure on all systems.

git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/base/trunk@14341 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
Richard Frith-Macdonald 2002-08-27 08:52:14 +00:00
parent 2cd3bfa4d6
commit 02fb142696
4 changed files with 67 additions and 43 deletions

View file

@ -1,3 +1,11 @@
2002-08-27 Richard Frith-Macdonald <rfm@gnu.org>
* Source/NSData.m: ([-writeToFile:atomically:]) Removed bogus line
which deleted files when it shouldn't.
* Source/NSUserDefaults.m: Use distributed lock to ensure that there
is no possible window when the defaults file is invalid ... not all
systems guarantee that the rename() system call is atomic.
2002-08-25 Richard Frith-Macdonald <rfm@gnu.org>
* Source/WindowsFileHandle.m: Removed ... no longer used.

View file

@ -35,6 +35,7 @@
@class NSData;
@class NSTimer;
@class NSRecursiveLock;
@class NSDistributedLock;
/* Standard domains */
GS_EXPORT NSString* const NSArgumentDomain;
@ -125,6 +126,7 @@ GS_EXPORT NSString* const NSLocale;
NSDate *_lastSync;
NSTimer *_tickingTimer; // for synchronization
NSRecursiveLock *_lock;
NSDistributedLock *_fileLock;
}
/* Getting the Shared Instance */

View file

@ -857,7 +857,6 @@ failure:
att = [[mgr fileAttributesAtPath: path
traverseLink: YES] mutableCopy];
IF_NO_GC(TEST_AUTORELEASE(att));
[mgr removeFileAtPath: path handler: nil];
}
c = rename(thePath, theRealPath);
@ -868,7 +867,7 @@ failure:
goto failure;
}
if (att)
if (att != nil)
{
/*
* We have created a new file - so we attempt to make it's

View file

@ -33,21 +33,23 @@
#include <errno.h>
#include <Foundation/NSUserDefaults.h>
#include <Foundation/NSFileManager.h>
#include <Foundation/NSPathUtilities.h>
#include <Foundation/NSDictionary.h>
#include <Foundation/NSArray.h>
#include <Foundation/NSDate.h>
#include <Foundation/NSUtilities.h>
#include <Foundation/NSArchiver.h>
#include <Foundation/NSArray.h>
#include <Foundation/NSBundle.h>
#include <Foundation/NSDate.h>
#include <Foundation/NSDictionary.h>
#include <Foundation/NSDistributedLock.h>
#include <Foundation/NSException.h>
#include <Foundation/NSFileManager.h>
#include <Foundation/NSLock.h>
#include <Foundation/NSNotification.h>
#include <Foundation/NSTimer.h>
#include <Foundation/NSPathUtilities.h>
#include <Foundation/NSProcessInfo.h>
#include <Foundation/NSRunLoop.h>
#include <Foundation/NSBundle.h>
#include <Foundation/NSThread.h>
#include <Foundation/NSTimer.h>
#include <Foundation/NSUtilities.h>
#include <Foundation/NSValue.h>
#include <Foundation/NSLock.h>
#include <base/GSLocale.h>
#include "GSPrivate.h"
@ -712,6 +714,9 @@ static NSString *pathForUser(NSString *user)
{
_defaultsDatabase = [pathForUser(NSUserName()) copy];
}
_fileLock = [[NSDistributedLock alloc] initWithPath:
[_defaultsDatabase stringByAppendingPathExtension: @"lck"]];
_lock = [NSRecursiveLock new];
// Create an empty search list
_searchList = [[NSMutableArray alloc] initWithCapacity: 10];
@ -765,20 +770,22 @@ static NSString *pathForUser(NSString *user)
setObject: [NSMutableDictionaryClass dictionaryWithCapacity: 10]
forKey: NSRegistrationDomain];
_lock = [NSRecursiveLock new];
return self;
}
- (void) dealloc
{
if (_tickingTimer)
[_tickingTimer invalidate];
if (_tickingTimer != nil)
{
[_tickingTimer invalidate];
}
RELEASE(_lastSync);
RELEASE(_searchList);
RELEASE(_persDomains);
RELEASE(_tempDomains);
RELEASE(_changedDomains);
RELEASE(_dictionaryRep);
RELEASE(_fileLock);
RELEASE(_lock);
[super dealloc];
}
@ -1173,6 +1180,23 @@ static NSString *pathForUser(NSString *user)
[_lock lock];
while ([_fileLock tryLock] == NO)
{
CREATE_AUTORELEASE_POOL(arp);
NSDate *when;
when = [NSDate dateWithTimeIntervalSinceNow: 0.1];
if ([when timeIntervalSinceDate: [_fileLock lockDate]] > 5.0)
{
[_fileLock breakLock];
}
else
{
[NSThread sleepUntilDate: when];
}
RELEASE(arp);
}
if (_tickingTimer == nil)
{
_tickingTimer = [NSTimer scheduledTimerWithTimeInterval: 30
@ -1188,7 +1212,7 @@ static NSString *pathForUser(NSString *user)
*/
attr = [mgr fileAttributesAtPath: _defaultsDatabase
traverseLink: YES];
if (_changedDomains == NO)
if (_changedDomains == nil)
{
BOOL wantRead = NO;
@ -1215,6 +1239,7 @@ static NSString *pathForUser(NSString *user)
}
if (wantRead == NO)
{
[_fileLock unlock];
[_lock unlock];
return YES;
}
@ -1239,6 +1264,7 @@ static NSString *pathForUser(NSString *user)
if (newDict == nil)
{
NSLog(@"Unable to load defaults from '%@'", _defaultsDatabase);
[_fileLock unlock];
[_lock unlock];
return NO;
}
@ -1269,25 +1295,23 @@ static NSString *pathForUser(NSString *user)
atPath: _defaultsDatabase];
}
if (_changedDomains)
if (_changedDomains != nil)
{ // Synchronize both dictionaries
NSEnumerator *enumerator = [_changedDomains objectEnumerator];
IMP nextImp;
IMP pImp;
id obj, dict;
NSString *domainName;
NSDictionary *domain;
nextImp = [enumerator methodForSelector: nextObjectSel];
pImp = [_persDomains methodForSelector: objectForKeySel];
while ((obj = (*nextImp)(enumerator, nextObjectSel)) != nil)
DESTROY(_changedDomains); // Retained by enumerator.
while ((domainName = [enumerator nextObject]) != nil)
{
dict = (*pImp)(_persDomains, objectForKeySel, obj);
if (dict) // Domain was added or changed
domain = [_persDomains objectForKey: domainName];
if (domain != nil) // Domain was added or changed
{
[newDict setObject: dict forKey: obj];
[newDict setObject: domain forKey: domainName];
}
else // Domain was removed
else // Domain was removed
{
[newDict removeObjectForKey: obj];
[newDict removeObjectForKey: domainName];
}
}
RELEASE(_persDomains);
@ -1295,6 +1319,7 @@ static NSString *pathForUser(NSString *user)
// Save the changes
if (![_persDomains writeToFile: _defaultsDatabase atomically: YES])
{
[_fileLock unlock];
[_lock unlock];
return NO;
}
@ -1318,6 +1343,7 @@ static NSString *pathForUser(NSString *user)
}
}
[_fileLock unlock];
[_lock unlock];
return YES;
}
@ -1575,32 +1601,21 @@ static NSString *pathForUser(NSString *user)
- (void) __changePersistentDomain: (NSString*)domainName
{
NSEnumerator *enumerator = nil;
IMP nImp;
id obj;
[_lock lock];
DESTROY(_dictionaryRep);
if (!_changedDomains)
if (_changedDomains == nil)
{
_changedDomains = [[NSMutableArray alloc] initWithCapacity: 5];
_changedDomains = [[NSMutableArray alloc] initWithObjects: &domainName
count: 1];
updateCache(self);
[[NSNotificationCenter defaultCenter]
postNotificationName: NSUserDefaultsDidChangeNotification
object: self];
}
enumerator = [_changedDomains objectEnumerator];
nImp = [enumerator methodForSelector: nextObjectSel];
while ((obj = (*nImp)(enumerator, nextObjectSel)) != nil)
else if ([_changedDomains containsObject: domainName] == NO)
{
if ([obj isEqualToString: domainName])
{
[_lock unlock];
return;
}
[_changedDomains addObject: domainName];
}
[_changedDomains addObject: domainName];
[_lock unlock];
return;
}