summaryrefslogtreecommitdiff
path: root/lib/backupclient/BackupStoreFilenameClear.cpp
blob: c415b9bb3a9deec6bb741f785b73f3b13a0e092d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
// --------------------------------------------------------------------------
//
// File
//		Name:    BackupStoreFilenameClear.cpp
//		Purpose: BackupStoreFilenames in the clear
//		Created: 2003/08/26
//
// --------------------------------------------------------------------------

#include "Box.h"
#include "BackupStoreFilenameClear.h"
#include "BackupStoreException.h"
#include "CipherContext.h"
#include "CipherBlowfish.h"
#include "Guards.h"

#include "MemLeakFindOn.h"

// Hide private variables from the rest of the world
namespace
{
	int sEncodeMethod = BackupStoreFilename::Encoding_Clear;
	CipherContext sBlowfishEncrypt;
	CipherContext sBlowfishDecrypt;
}

// --------------------------------------------------------------------------
//
// Function
//		Name:    BackupStoreFilenameClear::BackupStoreFilenameClear()
//		Purpose: Default constructor, creates an invalid filename
//		Created: 2003/08/26
//
// --------------------------------------------------------------------------
BackupStoreFilenameClear::BackupStoreFilenameClear()
{
}

// --------------------------------------------------------------------------
//
// Function
//		Name:    BackupStoreFilenameClear::BackupStoreFilenameClear(const std::string &)
//		Purpose: Creates a filename, encoding from the given string
//		Created: 2003/08/26
//
// --------------------------------------------------------------------------
BackupStoreFilenameClear::BackupStoreFilenameClear(const std::string &rToEncode)
{
	SetClearFilename(rToEncode);
}

// --------------------------------------------------------------------------
//
// Function
//		Name:    BackupStoreFilenameClear::BackupStoreFilenameClear(const BackupStoreFilenameClear &)
//		Purpose: Copy constructor
//		Created: 2003/08/26
//
// --------------------------------------------------------------------------
BackupStoreFilenameClear::BackupStoreFilenameClear(const BackupStoreFilenameClear &rToCopy)
	: BackupStoreFilename(rToCopy),
	  mClearFilename(rToCopy.mClearFilename)
{
}

// --------------------------------------------------------------------------
//
// Function
//		Name:    BackupStoreFilenameClear::BackupStoreFilenameClear(const BackupStoreFilename &rToCopy)
//		Purpose: Copy from base class
//		Created: 2003/08/26
//
// --------------------------------------------------------------------------
BackupStoreFilenameClear::BackupStoreFilenameClear(const BackupStoreFilename &rToCopy)
	: BackupStoreFilename(rToCopy)
{
	// Will get a clear filename when it's required
}

// --------------------------------------------------------------------------
//
// Function
//		Name:    BackupStoreFilenameClear::~BackupStoreFilenameClear()
//		Purpose: Destructor
//		Created: 2003/08/26
//
// --------------------------------------------------------------------------
BackupStoreFilenameClear::~BackupStoreFilenameClear()
{
}

// --------------------------------------------------------------------------
//
// Function
//		Name:    BackupStoreFilenameClear::GetClearFilename()
//		Purpose: Get the unencoded filename
//		Created: 2003/08/26
//
// --------------------------------------------------------------------------
#ifdef BACKUPSTOREFILEAME_MALLOC_ALLOC_BASE_TYPE
const std::string BackupStoreFilenameClear::GetClearFilename() const
{
	MakeClearAvailable();
	// When modifying, remember to change back to reference return if at all possible
	// -- returns an object rather than a reference to allow easy use with other code.
	return std::string(mClearFilename.c_str(), mClearFilename.size());
}
#else
const std::string &BackupStoreFilenameClear::GetClearFilename() const
{
	MakeClearAvailable();
	return mClearFilename;
}
#endif

// --------------------------------------------------------------------------
//
// Function
//		Name:    BackupStoreFilenameClear::SetClearFilename(const std::string &)
//		Purpose: Encode and make available the clear filename
//		Created: 2003/08/26
//
// --------------------------------------------------------------------------
void BackupStoreFilenameClear::SetClearFilename(const std::string &rToEncode)
{
	// Only allow Blowfish encodings
	if(sEncodeMethod != Encoding_Blowfish)
	{
		THROW_EXCEPTION(BackupStoreException, FilenameEncryptionNotSetup)
	}

	// Make an encoded string with blowfish encryption
	EncryptClear(rToEncode, sBlowfishEncrypt, Encoding_Blowfish);
		
	// Store the clear filename
	mClearFilename.assign(rToEncode.c_str(), rToEncode.size());

	// Make sure we did the right thing
	if(!CheckValid(false))
	{
		THROW_EXCEPTION(BackupStoreException, Internal)
	}
}

// --------------------------------------------------------------------------
//
// Function
//		Name:    BackupStoreFilenameClear::MakeClearAvailable()
//		Purpose: Private. Make sure the clear filename is available
//		Created: 2003/08/26
//
// --------------------------------------------------------------------------
void BackupStoreFilenameClear::MakeClearAvailable() const
{
	if(!mClearFilename.empty())
		return;		// nothing to do

	// Check valid
	CheckValid();
		
	// Decode the header
	int size = BACKUPSTOREFILENAME_GET_SIZE(*this);
	int encoding = BACKUPSTOREFILENAME_GET_ENCODING(*this);
	
	// Decode based on encoding given in the header
	switch(encoding)
	{
	case Encoding_Clear:
		TRACE0("**** BackupStoreFilename encoded with Clear encoding ****\n");
		mClearFilename.assign(c_str() + 2, size - 2);
		break;
		
	case Encoding_Blowfish:
		DecryptEncoded(sBlowfishDecrypt);
		break;
	
	default:
		THROW_EXCEPTION(BackupStoreException, UnknownFilenameEncoding)
		break;	
	}
}


// Buffer for encoding and decoding -- do this all in one single buffer to
// avoid lots of string allocation, which stuffs up memory usage.
// These static memory vars are, of course, not thread safe, but we don't use threads.
static int sEncDecBufferSize = 0;
static MemoryBlockGuard<uint8_t *> *spEncDecBuffer = 0;

static void EnsureEncDecBufferSize(int BufSize)
{
	if(spEncDecBuffer == 0)
	{
#ifndef WIN32
		TRACE1("Allocating filename encoding/decoding buffer with size %d\n", BufSize);
#endif
		spEncDecBuffer = new MemoryBlockGuard<uint8_t *>(BufSize);
		MEMLEAKFINDER_NOT_A_LEAK(spEncDecBuffer);
		MEMLEAKFINDER_NOT_A_LEAK(*spEncDecBuffer);
		sEncDecBufferSize = BufSize;
	}
	else
	{
		if(sEncDecBufferSize < BufSize)
		{
#ifndef WIN32
			TRACE2("Reallocating filename encoding/decoding buffer from %d to %d\n", sEncDecBufferSize, BufSize);
#endif
			spEncDecBuffer->Resize(BufSize);
			sEncDecBufferSize = BufSize;
			MEMLEAKFINDER_NOT_A_LEAK(*spEncDecBuffer);
		}
	}
}

// --------------------------------------------------------------------------
//
// Function
//		Name:    BackupStoreFilenameClear::EncryptClear(const std::string &, CipherContext &, int)
//		Purpose: Private. Assigns the encoded filename string, encrypting.
//		Created: 1/12/03
//
// --------------------------------------------------------------------------
void BackupStoreFilenameClear::EncryptClear(const std::string &rToEncode, CipherContext &rCipherContext, int StoreAsEncoding)
{
	// Work out max size
	int maxOutSize = rCipherContext.MaxOutSizeForInBufferSize(rToEncode.size()) + 4;
	
	// Make sure encode/decode buffer has enough space
	EnsureEncDecBufferSize(maxOutSize);
	
	// Pointer to buffer
	uint8_t *buffer = *spEncDecBuffer;
	
	// Encode -- do entire block in one go
	int encSize = rCipherContext.TransformBlock(buffer + 2, sEncDecBufferSize - 2, rToEncode.c_str(), rToEncode.size());
	// and add in header size
	encSize += 2;
	
	// Adjust header
	BACKUPSTOREFILENAME_MAKE_HDR(buffer, encSize, StoreAsEncoding);
	
	// Store the encoded string
	assign((char*)buffer, encSize);
}


// --------------------------------------------------------------------------
//
// Function
//		Name:    BackupStoreFilenameClear::DecryptEncoded(CipherContext &)
//		Purpose: Decrypt the encoded filename using the cipher context
//		Created: 1/12/03
//
// --------------------------------------------------------------------------
void BackupStoreFilenameClear::DecryptEncoded(CipherContext &rCipherContext) const
{
	// Work out max size
	int maxOutSize = rCipherContext.MaxOutSizeForInBufferSize(size()) + 4;
	
	// Make sure encode/decode buffer has enough space
	EnsureEncDecBufferSize(maxOutSize);
	
	// Pointer to buffer
	uint8_t *buffer = *spEncDecBuffer;
	
	// Decrypt
	const char *str = c_str() + 2;
	int sizeOut = rCipherContext.TransformBlock(buffer, sEncDecBufferSize, str, size() - 2);
	
	// Assign to this
	mClearFilename.assign((char*)buffer, sizeOut);
}


// --------------------------------------------------------------------------
//
// Function
//		Name:    BackupStoreFilenameClear::EncodedFilenameChanged()
//		Purpose: The encoded filename stored has changed
//		Created: 2003/08/26
//
// --------------------------------------------------------------------------
void BackupStoreFilenameClear::EncodedFilenameChanged()
{
	BackupStoreFilename::EncodedFilenameChanged();

	// Delete stored filename in clear
	mClearFilename.erase();
}


// --------------------------------------------------------------------------
//
// Function
//		Name:    BackupStoreFilenameClear::SetBlowfishKey(const void *, int)
//		Purpose: Set the key used for Blowfish encryption of filenames
//		Created: 1/12/03
//
// --------------------------------------------------------------------------
void BackupStoreFilenameClear::SetBlowfishKey(const void *pKey, int KeyLength, const void *pIV, int IVLength)
{
	// Initialisation vector not used. Can't use a different vector for each filename as
	// that would stop comparisions on the server working.
	sBlowfishEncrypt.Reset();
	sBlowfishEncrypt.Init(CipherContext::Encrypt, CipherBlowfish(CipherDescription::Mode_CBC, pKey, KeyLength));
	ASSERT(sBlowfishEncrypt.GetIVLength() == IVLength);
	sBlowfishEncrypt.SetIV(pIV);
	sBlowfishDecrypt.Reset();
	sBlowfishDecrypt.Init(CipherContext::Decrypt, CipherBlowfish(CipherDescription::Mode_CBC, pKey, KeyLength));
	ASSERT(sBlowfishDecrypt.GetIVLength() == IVLength);
	sBlowfishDecrypt.SetIV(pIV);
}

// --------------------------------------------------------------------------
//
// Function
//		Name:    BackupStoreFilenameClear::SetEncodingMethod(int)
//		Purpose: Set the encoding method used for filenames
//		Created: 1/12/03
//
// --------------------------------------------------------------------------
void BackupStoreFilenameClear::SetEncodingMethod(int Method)
{
	sEncodeMethod = Method;
}