Пример #1
0
size_t Resource::Reader::readData(char *buffer, size_t size)
{
	if(!mCurrentBlock) return 0;	// EOF
	
	if(!mKey.empty() && !mCurrentBlock->hasDecryption())
	{
		BinaryString subsalt;
		subsalt.writeBinary(uint64_t(mCurrentBlockIndex));
		
		// Generate subkey
		BinaryString subkey;
		Sha256().pbkdf2_hmac(mKey, subsalt, subkey, 32, 100);
		
		// Generate iv
		BinaryString iv;
		Sha256().pbkdf2_hmac(mResource->salt(), subsalt, iv, 16, 100);
		
		// Initialize decryption process
		mCurrentBlock->setDecryption(subkey, iv);
	}
	
	size_t ret;
	if((ret = mCurrentBlock->readData(buffer, size)))
	{
		mReadPosition+= ret;
		return ret;
	}
	
	delete mCurrentBlock;
	++mCurrentBlockIndex;
	mCurrentBlock = mNextBlock;
	mNextBlock = createBlock(mCurrentBlockIndex + 1);
	return readData(buffer, size);
}
Пример #2
0
bool PortMapping::NatPMP::check(String &host)
{
	LogDebug("PortMapping::NatPMP", "Trying NAT-PMP...");
	
	BinaryString query;
	query.writeBinary(uint8_t(0));	// version
	query.writeBinary(uint8_t(0));	// op
	
	int attempts = 3;
	duration timeout = milliseconds(250.);
	for(int i=0; i<attempts; ++i)
	{
		BinaryString dgram = query;
		mSock.write(dgram, mGatewayAddr);
		
		using clock = std::chrono::steady_clock;
		std::chrono::time_point<clock> end = clock::now() + std::chrono::duration_cast<clock::duration>(timeout);
		
		while(clock::now() < end)
		{
			Address sender;
			duration left = end - clock::now();
			if(!mSock.read(dgram, sender, left)) break;
			
			if(!sender.isPrivate()) continue;
			
			LogDebug("PortMapping::NatPMP", String("Got response from ") + sender.toString());
			if(parse(dgram, 0))
			{
				LogDebug("PortMapping", "NAT-PMP is available");
				mGatewayAddr = sender;
				host = mExternalHost;
				return true;
			}
		}
		
		timeout*= 2;
	}
	
	//LogDebug("PortMapping::NatPMP", "NAT-PMP is not available");
	return false;
}
Пример #3
0
bool PortMapping::NatPMP::request(uint8_t op, uint16_t internal, uint16_t suggested, uint32_t lifetime, uint16_t *external)
{
	if(!op) return false;
	
	BinaryString query;
	query.writeBinary(uint8_t(0));	// version
	query.writeBinary(op);		// op
	query.writeBinary(uint16_t(0));	// reserved
	query.writeBinary(internal);
	query.writeBinary(suggested);
	query.writeBinary(lifetime);
	
	const int attempts = 3;
	duration timeout = milliseconds(250.);
	for(int i=0; i<attempts; ++i)
	{
		BinaryString dgram = query;
		mSock.write(dgram, mGatewayAddr);
		
		using clock = std::chrono::steady_clock;
		std::chrono::time_point<clock> end = clock::now() + std::chrono::duration_cast<clock::duration>(timeout);
		
		while(clock::now() < end)
		{
			Address sender;
			duration left = end - clock::now();
			if(!mSock.read(dgram, sender, left)) break;
			
			if(!sender.isPrivate()) continue;
			
			if(parse(dgram, op, internal))
				return true;
		}
			
		timeout*= 2;
	}
	
	return false;
}
Пример #4
0
void Resource::process(const String &filename, const String &name, const String &type, const String &secret)
{
	BinaryString salt;
	
	// If secret is not empty then this is an encrypted resource
	if(!secret.empty())
	{
		// Generate salt from plaintext
		// Because we need to be able to recognize data is identical even when encrypted
		BinaryString digest;
		File file(filename, File::Read);
		Sha256().compute(file, digest);
		Sha256().pbkdf2_hmac(digest, type, salt, 32, 100000);
		Assert(!salt.empty());
	}
	
	// Fill index record
	delete mIndexRecord;
	int64_t size = File::Size(filename);
	mIndexRecord = new Resource::IndexRecord;
	mIndexRecord->name = name;
	mIndexRecord->type = type;
	mIndexRecord->size = size;
	mIndexRecord->salt = salt;
	mIndexRecord->blockDigests.reserve(size/Block::Size);
	
	// Process blocks
	File file(filename, File::Read);
	BinaryString blockDigest;
	
	if(!secret.empty())
	{
		BinaryString key;
		Sha256().pbkdf2_hmac(secret, salt, key, 32, 100000);
		
		uint64_t i = 0;
		while(true)
		{
			BinaryString subsalt;
			subsalt.writeBinary(i);
			
			// Generate subkey
			BinaryString subkey;
			Sha256().pbkdf2_hmac(key, subsalt, subkey, 32, 100);
			
			// Generate iv
			BinaryString iv;
			Sha256().pbkdf2_hmac(salt, subsalt, iv, 16, 100);
			
			if(!Block::EncryptFile(file, subkey, iv, blockDigest))
				break;
			
			mIndexRecord->blockDigests.append(blockDigest);
			++i;
		}
	} 
	else {
		while(Block::ProcessFile(file, blockDigest))
			mIndexRecord->blockDigests.append(blockDigest);
	}
	
	// Create index
	String tempFileName = File::TempName();
	File tempFile(tempFileName, File::Truncate);
	BinarySerializer serializer(&tempFile);
	serializer.write(mIndexRecord);
	tempFile.close();
	String indexFilePath = Cache::Instance->move(tempFileName);
	
	// Create index block
	delete mIndexBlock;
	mIndexBlock = new Block(indexFilePath);
}