/src/MapServer/src/mapcrypto.c
Line | Count | Source |
1 | | /****************************************************************************** |
2 | | * $Id$ |
3 | | * |
4 | | * Project: MapServer |
5 | | * Purpose: Encryption functions (see MS-RFC-18) |
6 | | * Author: Daniel Morissette |
7 | | * |
8 | | ****************************************************************************** |
9 | | * Copyright (c) 1996-2006 Regents of the University of Minnesota. |
10 | | * |
11 | | * Permission is hereby granted, free of charge, to any person obtaining a |
12 | | * copy of this software and associated documentation files (the "Software"), |
13 | | * to deal in the Software without restriction, including without limitation |
14 | | * the rights to use, copy, modify, merge, publish, distribute, sublicense, |
15 | | * and/or sell copies of the Software, and to permit persons to whom the |
16 | | * Software is furnished to do so, subject to the following conditions: |
17 | | * |
18 | | * The above copyright notice and this permission notice shall be included in |
19 | | * all copies of this Software or works derived from this Software. |
20 | | * |
21 | | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
22 | | * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
23 | | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
24 | | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
25 | | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING |
26 | | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
27 | | * DEALINGS IN THE SOFTWARE. |
28 | | ****************************************************************************/ |
29 | | |
30 | | #include <assert.h> |
31 | | #include <ctype.h> /* isxdigit() */ |
32 | | #include <stdlib.h> /* rand() */ |
33 | | #include <time.h> /* time() */ |
34 | | |
35 | | #include "mapserver.h" |
36 | | |
37 | | #include "cpl_conv.h" |
38 | | |
39 | | /********************************************************************** |
40 | | * encipher() and decipher() from the Tiny Encryption Algorithm (TEA) |
41 | | * website at: |
42 | | * http://www.simonshepherd.supanet.com/tea.htm |
43 | | * |
44 | | * TEA was developed and placed in the public domain by David Wheeler |
45 | | * and Roger Needham at the Computer Laboratory of Cambridge University. |
46 | | * |
47 | | * The source below came with the following public domain notice: |
48 | | * |
49 | | * "Please feel free to use any of this code in your applications. |
50 | | * The TEA algorithm (including new-variant TEA) has been placed |
51 | | * in the public domain, as have my assembly language implementations." |
52 | | * |
53 | | * ... and the following usage notes: |
54 | | * |
55 | | * All the routines have the general form |
56 | | * |
57 | | * void encipher(const unsigned long *const v,unsigned long *const w, |
58 | | * const unsigned long * const k); |
59 | | * |
60 | | * void decipher(const unsigned long *const v,unsigned long *const w, |
61 | | * const unsigned long * const k); |
62 | | * |
63 | | * TEA takes 64 bits of data in v[0] and v[1], and 128 bits of key in |
64 | | * k[0] - k[3]. The result is returned in w[0] and w[1]. Returning the |
65 | | * result separately makes implementation of cipher modes other than |
66 | | * Electronic Code Book a little bit easier. |
67 | | * |
68 | | * TEA can be operated in any of the modes of DES. |
69 | | * |
70 | | * n is the number of iterations. 32 is ample, 16 is sufficient, as few |
71 | | * as eight should be OK for most applications, especially ones where |
72 | | * the data age quickly (real-time video, for example). The algorithm |
73 | | * achieves good dispersion after six iterations. The iteration count |
74 | | * can be made variable if required. |
75 | | * |
76 | | * Note this algorithm is optimised for 32-bit CPUs with fast shift |
77 | | * capabilities. It can very easily be ported to assembly language |
78 | | * on most CPUs. |
79 | | * |
80 | | * delta is chosen to be the Golden ratio ((5/4)1/2 - 1/2 ~ 0.618034) |
81 | | * multiplied by 232. On entry to decipher(), sum is set to be delta * n. |
82 | | * Which way round you call the functions is arbitrary: DK(EK(P)) = EK(DK(P)) |
83 | | * where EK and DK are encryption and decryption under key K respectively. |
84 | | * |
85 | | **********************************************************************/ |
86 | | |
87 | | static void encipher(const ms_uint32 *const v, ms_uint32 *const w, |
88 | 0 | const ms_uint32 *const k) { |
89 | 0 | register ms_uint32 y = v[0], z = v[1], sum = 0, delta = 0x9E3779B9, n = 32; |
90 | |
|
91 | 0 | while (n-- > 0) { |
92 | 0 | y += ((z << 4 ^ z >> 5) + z) ^ (sum + k[sum & 3]); |
93 | 0 | sum += delta; |
94 | 0 | z += ((y << 4 ^ y >> 5) + y) ^ (sum + k[sum >> 11 & 3]); |
95 | 0 | } |
96 | |
|
97 | 0 | w[0] = y; |
98 | 0 | w[1] = z; |
99 | 0 | } |
100 | | |
101 | | static void decipher(const ms_uint32 *const v, ms_uint32 *const w, |
102 | 0 | const ms_uint32 *const k) { |
103 | 0 | register ms_uint32 y = v[0], z = v[1], sum = 0xC6EF3720, delta = 0x9E3779B9, |
104 | 0 | n = 32; |
105 | | |
106 | | /* sum = delta<<5, in general sum = delta * n */ |
107 | |
|
108 | 0 | while (n-- > 0) { |
109 | 0 | z -= ((y << 4 ^ y >> 5) + y) ^ (sum + k[sum >> 11 & 3]); |
110 | 0 | sum -= delta; |
111 | 0 | y -= ((z << 4 ^ z >> 5) + z) ^ (sum + k[sum & 3]); |
112 | 0 | } |
113 | |
|
114 | 0 | w[0] = y; |
115 | 0 | w[1] = z; |
116 | 0 | } |
117 | | |
118 | | /********************************************************************** |
119 | | * msHexEncode() |
120 | | * |
121 | | * Hex-encode numbytes from in[] and return the result in out[]. |
122 | | * |
123 | | * out[] should be preallocated by the caller to be at least 2*numbytes+1 |
124 | | * (+1 for the terminating '\0') |
125 | | **********************************************************************/ |
126 | 0 | void msHexEncode(const unsigned char *in, char *out, int numbytes) { |
127 | 0 | char *hex = "0123456789ABCDEF"; |
128 | |
|
129 | 0 | while (numbytes-- > 0) { |
130 | 0 | *out++ = hex[*in / 16]; |
131 | 0 | *out++ = hex[*in % 16]; |
132 | 0 | in++; |
133 | 0 | } |
134 | 0 | *out = '\0'; |
135 | 0 | } |
136 | | |
137 | | /********************************************************************** |
138 | | * msHexDecode() |
139 | | * |
140 | | * Hex-decode numchars from in[] and return the result in out[]. |
141 | | * |
142 | | * If numchars > 0 then only up to this number of chars from in[] are |
143 | | * processed, otherwise the full in[] string up to the '\0' is processed. |
144 | | * |
145 | | * out[] should be preallocated by the caller to be large enough to hold |
146 | | * the resulting bytes. |
147 | | * |
148 | | * Returns the number of bytes written to out[] which may be different from |
149 | | * numchars/2 if an error or a '\0' is encountered. |
150 | | **********************************************************************/ |
151 | 0 | int msHexDecode(const char *in, unsigned char *out, int numchars) { |
152 | 0 | int numbytes_out = 0; |
153 | | |
154 | | /* Make sure numchars is even */ |
155 | 0 | numchars = (numchars / 2) * 2; |
156 | |
|
157 | 0 | if (numchars < 2) |
158 | 0 | numchars = -1; /* Will result in this value being ignored in the loop*/ |
159 | |
|
160 | 0 | while (*in != '\0' && *(in + 1) != '\0' && numchars != 0) { |
161 | 0 | *out = 0x10 * (*in >= 'A' ? ((*in & 0xdf) - 'A') + 10 : (*in - '0')); |
162 | 0 | in++; |
163 | 0 | *out += (*in >= 'A' ? ((*in & 0xdf) - 'A') + 10 : (*in - '0')); |
164 | 0 | in++; |
165 | |
|
166 | 0 | out++; |
167 | 0 | numbytes_out++; |
168 | |
|
169 | 0 | numchars -= 2; |
170 | 0 | } |
171 | |
|
172 | 0 | return numbytes_out; |
173 | 0 | } |
174 | | |
175 | | /********************************************************************** |
176 | | * msGenerateEncryptionKey() |
177 | | * |
178 | | * Create a new encryption key. |
179 | | * |
180 | | * The output buffer should be at least MS_ENCRYPTION_KEY_SIZE bytes. |
181 | | **********************************************************************/ |
182 | | |
183 | 0 | int msGenerateEncryptionKey(unsigned char *k) { |
184 | 0 | int i; |
185 | | |
186 | | /* Use current time as seed for rand() */ |
187 | 0 | srand((unsigned int)time(NULL)); |
188 | |
|
189 | 0 | for (i = 0; i < MS_ENCRYPTION_KEY_SIZE; i++) { |
190 | | /* coverity[dont_call] */ |
191 | 0 | k[i] = (unsigned char)rand(); |
192 | 0 | } |
193 | |
|
194 | 0 | return MS_SUCCESS; |
195 | 0 | } |
196 | | |
197 | | /********************************************************************** |
198 | | * msReadEncryptionKeyFromFile() |
199 | | * |
200 | | * Read and decode hex-encoded encryption key from file and returns the |
201 | | * key in the 'unsigned char k[MS_ENCRYPTION_KEY_SIZE]' buffer that is |
202 | | * provided by the caller. |
203 | | * |
204 | | * Returns MS_SUCCESS/MS_FAILURE. |
205 | | **********************************************************************/ |
206 | | |
207 | | int msReadEncryptionKeyFromFile(const char *keyfile, unsigned char *k, |
208 | 0 | const char *pszRelToPath) { |
209 | 0 | FILE *fp; |
210 | 0 | char extended_path[MS_MAXPATHLEN]; |
211 | 0 | char szBuf[100]; |
212 | 0 | int numchars; |
213 | | |
214 | | /* Try to make the path relative */ |
215 | 0 | if (msBuildPath(extended_path, pszRelToPath, keyfile) == NULL) |
216 | 0 | return MS_FAILURE; |
217 | | |
218 | 0 | keyfile = extended_path; |
219 | |
|
220 | 0 | if ((fp = fopen(keyfile, "rt")) == NULL) { |
221 | 0 | msSetError(MS_MISCERR, "Cannot open key file.", |
222 | 0 | "msReadEncryptionKeyFromFile()"); |
223 | 0 | return MS_FAILURE; |
224 | 0 | } |
225 | | |
226 | 0 | numchars = |
227 | 0 | fread(szBuf, sizeof(unsigned char), MS_ENCRYPTION_KEY_SIZE * 2, fp); |
228 | 0 | fclose(fp); |
229 | 0 | szBuf[MS_ENCRYPTION_KEY_SIZE * 2] = '\0'; |
230 | |
|
231 | 0 | if (numchars != MS_ENCRYPTION_KEY_SIZE * 2) { |
232 | 0 | msSetError(MS_MISCERR, "Invalid key file, got %d chars, expected %d.", |
233 | 0 | "msReadEncryptionKeyFromFile()", numchars, |
234 | 0 | MS_ENCRYPTION_KEY_SIZE * 2); |
235 | 0 | return MS_FAILURE; |
236 | 0 | } |
237 | | |
238 | 0 | msHexDecode(szBuf, k, MS_ENCRYPTION_KEY_SIZE * 2); |
239 | |
|
240 | 0 | return MS_SUCCESS; |
241 | 0 | } |
242 | | |
243 | | /********************************************************************** |
244 | | * msLoadEncryptionKey() |
245 | | * |
246 | | * Load and decode hex-encoded encryption key from file and returns the |
247 | | * key in the 'unsigned char k[MS_ENCRYPTION_KEY_SIZE]' buffer that is |
248 | | * provided by the caller. |
249 | | * |
250 | | * The first time that msLoadEncryptionKey() is called for a given mapObj |
251 | | * it will load the encryption key and cache it in mapObj->encryption_key. |
252 | | * If the key is already set in the mapObj then it does nothing and returns. |
253 | | * |
254 | | * The location of the encryption key can be specified in two ways, |
255 | | * either by setting the environment variable MS_ENCRYPTION_KEY or using |
256 | | * a CONFIG directive: |
257 | | * CONFIG MS_ENCRYPTION_KEY "/path/to/mykey.txt" |
258 | | * Returns MS_SUCCESS/MS_FAILURE. |
259 | | **********************************************************************/ |
260 | | |
261 | 0 | static int msLoadEncryptionKey(mapObj *map) { |
262 | 0 | const char *keyfile; |
263 | |
|
264 | 0 | if (map == NULL) { |
265 | 0 | msSetError(MS_MISCERR, "NULL MapObj.", "msLoadEncryptionKey()"); |
266 | 0 | return MS_FAILURE; |
267 | 0 | } |
268 | | |
269 | 0 | if (map->encryption_key_loaded) |
270 | 0 | return MS_SUCCESS; /* Already loaded */ |
271 | | |
272 | 0 | keyfile = msGetConfigOption(map, "MS_ENCRYPTION_KEY"); |
273 | 0 | if (!keyfile) |
274 | 0 | keyfile = CPLGetConfigOption("MS_ENCRYPTION_KEY", NULL); |
275 | |
|
276 | 0 | if (keyfile && msReadEncryptionKeyFromFile(keyfile, map->encryption_key, |
277 | 0 | map->mappath) == MS_SUCCESS) { |
278 | 0 | map->encryption_key_loaded = MS_TRUE; |
279 | 0 | } else { |
280 | 0 | msSetError(MS_MISCERR, |
281 | 0 | "Failed reading encryption key. Make sure " |
282 | 0 | "MS_ENCRYPTION_KEY is set and points to a valid key file.", |
283 | 0 | "msLoadEncryptionKey()"); |
284 | 0 | return MS_FAILURE; |
285 | 0 | } |
286 | | |
287 | 0 | return MS_SUCCESS; |
288 | 0 | } |
289 | | |
290 | | /********************************************************************** |
291 | | * msEncryptStringWithKey() |
292 | | * |
293 | | * Encrypts and hex-encodes the contents of string in[] and returns the |
294 | | * result in out[] which should have been pre-allocated by the caller |
295 | | * to be at least twice the size of in[] + 16+1 bytes (for padding + '\0'). |
296 | | * |
297 | | **********************************************************************/ |
298 | | |
299 | | void msEncryptStringWithKey(const unsigned char *key, const char *in, |
300 | 0 | char *out) { |
301 | 0 | ms_uint32 v[4], w[4]; |
302 | 0 | const ms_uint32 *k; |
303 | 0 | int last_block = MS_FALSE; |
304 | | |
305 | | /* Casting the key this way is safe only as long as longs are 4 bytes |
306 | | * on this platform */ |
307 | 0 | assert(sizeof(ms_uint32) == 4); |
308 | 0 | k = (const ms_uint32 *)key; |
309 | |
|
310 | 0 | while (!last_block) { |
311 | 0 | int i, j; |
312 | | /* encipher() takes v[2] (64 bits) as input. |
313 | | * Copy bytes from in[] to the v[2] input array (pair of 4 bytes) |
314 | | * v[] is padded with zeros if string doesn't align with 8 bytes |
315 | | */ |
316 | 0 | v[0] = 0; |
317 | 0 | v[1] = 0; |
318 | 0 | for (i = 0; !last_block && i < 2; i++) { |
319 | 0 | for (j = 0; j < 4; j++) { |
320 | 0 | if (*in == '\0') { |
321 | 0 | last_block = MS_TRUE; |
322 | 0 | break; |
323 | 0 | } |
324 | | |
325 | 0 | v[i] |= *in << (j * 8); |
326 | 0 | in++; |
327 | 0 | } |
328 | 0 | } |
329 | |
|
330 | 0 | if (*in == '\0') |
331 | 0 | last_block = MS_TRUE; |
332 | | |
333 | | /* Do the actual encryption */ |
334 | 0 | encipher(v, w, k); |
335 | | |
336 | | /* Append hex-encoded bytes to output, 4 bytes at a time */ |
337 | 0 | msHexEncode((unsigned char *)w, out, 4); |
338 | 0 | out += 8; |
339 | 0 | msHexEncode((unsigned char *)(w + 1), out, 4); |
340 | 0 | out += 8; |
341 | 0 | } |
342 | | |
343 | | /* Make sure output is 0-terminated */ |
344 | 0 | *out = '\0'; |
345 | 0 | } |
346 | | |
347 | | /********************************************************************** |
348 | | * msDecryptStringWithKey() |
349 | | * |
350 | | * Hex-decodes and then decrypts the contents of string in[] and returns the |
351 | | * result in out[] which should have been pre-allocated by the caller |
352 | | * to be at least half the size of in[]. |
353 | | * |
354 | | **********************************************************************/ |
355 | | |
356 | | void msDecryptStringWithKey(const unsigned char *key, const char *in, |
357 | 0 | char *out) { |
358 | 0 | ms_uint32 v[4], w[4]; |
359 | 0 | const ms_uint32 *k; |
360 | 0 | int last_block = MS_FALSE; |
361 | | |
362 | | /* Casting the key this way is safe only as long as longs are 4 bytes |
363 | | * on this platform */ |
364 | 0 | assert(sizeof(ms_uint32) == 4); |
365 | 0 | k = (const ms_uint32 *)key; |
366 | |
|
367 | 0 | while (!last_block) { |
368 | 0 | int i; |
369 | | /* decipher() takes v[2] (64 bits) as input. |
370 | | * Copy bytes from in[] to the v[2] input array (pair of 4 bytes) |
371 | | * v[] is padded with zeros if string doesn't align with 8 bytes |
372 | | */ |
373 | 0 | v[0] = 0; |
374 | 0 | v[1] = 0; |
375 | |
|
376 | 0 | if (msHexDecode(in, (unsigned char *)v, 8) != 4) |
377 | 0 | last_block = MS_TRUE; |
378 | 0 | else { |
379 | 0 | in += 8; |
380 | 0 | if (msHexDecode(in, (unsigned char *)(v + 1), 8) != 4) |
381 | 0 | last_block = MS_TRUE; |
382 | 0 | else |
383 | 0 | in += 8; |
384 | 0 | } |
385 | | |
386 | | /* Do the actual decryption */ |
387 | 0 | decipher(v, w, k); |
388 | | |
389 | | /* Copy the results to out[] */ |
390 | 0 | for (i = 0; i < 2; i++) { |
391 | 0 | *out++ = (w[i] & 0x000000ff); |
392 | 0 | *out++ = (w[i] & 0x0000ff00) >> 8; |
393 | 0 | *out++ = (w[i] & 0x00ff0000) >> 16; |
394 | 0 | *out++ = (w[i] & 0xff000000) >> 24; |
395 | 0 | } |
396 | |
|
397 | 0 | if (*in == '\0') |
398 | 0 | last_block = MS_TRUE; |
399 | 0 | } |
400 | | |
401 | | /* Make sure output is 0-terminated */ |
402 | 0 | *out = '\0'; |
403 | 0 | } |
404 | | |
405 | | /********************************************************************** |
406 | | * msDecryptStringTokens() |
407 | | * |
408 | | * Returns a newly allocated string (to be msFree'd by the caller) in |
409 | | * which all occurrences of encrypted strings delimited by {...} have |
410 | | * been decrypted. |
411 | | * |
412 | | **********************************************************************/ |
413 | | |
414 | 0 | char *msDecryptStringTokens(mapObj *map, const char *in) { |
415 | 0 | char *outbuf, *out; |
416 | |
|
417 | 0 | if (map == NULL) { |
418 | 0 | msSetError(MS_MISCERR, "NULL MapObj.", "msLoadEncryptionKey()"); |
419 | 0 | return NULL; |
420 | 0 | } |
421 | | |
422 | | /* Start with a copy of the string. Decryption can only result in |
423 | | * a string with the same or shorter length */ |
424 | 0 | if ((outbuf = (char *)malloc((strlen(in) + 1) * sizeof(char))) == NULL) { |
425 | 0 | msSetError(MS_MEMERR, NULL, "msDecryptStringTokens()"); |
426 | 0 | return NULL; |
427 | 0 | } |
428 | 0 | out = outbuf; |
429 | |
|
430 | 0 | while (*in != '\0') { |
431 | 0 | if (*in == '{') { |
432 | | /* Possibly beginning of a token, look for closing bracket |
433 | | ** and make sure all chars in between are valid hex encoding chars |
434 | | */ |
435 | 0 | const char *pszStart, *pszEnd; |
436 | 0 | int valid_token = MS_FALSE; |
437 | |
|
438 | 0 | pszStart = in + 1; |
439 | 0 | if ((pszEnd = strchr(pszStart, '}')) != NULL && pszEnd - pszStart > 1) { |
440 | 0 | const char *pszTmp; |
441 | 0 | valid_token = MS_TRUE; |
442 | 0 | for (pszTmp = pszStart; pszTmp < pszEnd; pszTmp++) { |
443 | 0 | if (!isxdigit(*pszTmp)) { |
444 | 0 | valid_token = MS_FALSE; |
445 | 0 | break; |
446 | 0 | } |
447 | 0 | } |
448 | 0 | } |
449 | |
|
450 | 0 | if (valid_token) { |
451 | | /* Go ahead and decrypt the token */ |
452 | 0 | char *pszTmp; |
453 | | |
454 | | /* Make sure encryption key is loaded. We do this here instead |
455 | | * of at the beginning of the function to avoid loading the |
456 | | * key unless ready necessary. This is a very cheap call if |
457 | | * the key is already loaded |
458 | | */ |
459 | 0 | if (msLoadEncryptionKey(map) != MS_SUCCESS) |
460 | 0 | return NULL; |
461 | | |
462 | 0 | pszTmp = (char *)malloc((pszEnd - pszStart + 1) * sizeof(char)); |
463 | 0 | strlcpy(pszTmp, pszStart, (pszEnd - pszStart) + 1); |
464 | |
|
465 | 0 | msDecryptStringWithKey(map->encryption_key, pszTmp, out); |
466 | |
|
467 | 0 | out += strlen(out); |
468 | 0 | in = pszEnd + 1; |
469 | 0 | free(pszTmp); |
470 | 0 | } else { |
471 | | /* Not a valid token, just copy the '{' and keep going */ |
472 | 0 | *out++ = *in++; |
473 | 0 | } |
474 | 0 | } else { |
475 | | /* Just copy any other chars */ |
476 | 0 | *out++ = *in++; |
477 | 0 | } |
478 | 0 | } |
479 | 0 | *out = '\0'; |
480 | |
|
481 | 0 | return outbuf; |
482 | 0 | } |
483 | | |
484 | | #ifdef TEST_MAPCRYPTO |
485 | | |
486 | | /* Test for mapcrypto.c functions. To run these tests, use the following |
487 | | ** Makefile directive: |
488 | | |
489 | | test_mapcrypto: $(LIBMAP_STATIC) mapcrypto.c |
490 | | $(CC) $(CFLAGS) mapcrypto.c -DTEST_MAPCRYPTO $(EXE_LDFLAGS) -o test_mapcrypto |
491 | | |
492 | | ** |
493 | | */ |
494 | | int main(int argc, char *argv[]) { |
495 | | const unsigned char bytes_in[] = {0x12, 0x34, 0xff, 0x00, 0x44, 0x22}; |
496 | | unsigned char bytes_out[8], encryption_key[MS_ENCRYPTION_KEY_SIZE * 2 + 1]; |
497 | | char string_buf[256], string_buf2[256]; |
498 | | int numbytes = 0; |
499 | | |
500 | | /* |
501 | | ** Test msHexEncode() |
502 | | */ |
503 | | msHexEncode(bytes_in, string_buf, 6); |
504 | | printf("msHexEncode returned '%s'\n", string_buf); |
505 | | |
506 | | /* |
507 | | ** Test msHexDecode() |
508 | | */ |
509 | | memset(bytes_out, 0, 8); |
510 | | numbytes = msHexDecode(string_buf, bytes_out, -1); |
511 | | printf( |
512 | | "msHexDecode(%s, -1) = %d, bytes_out = %x, %x, %x, %x, %x, %x, %x, %x\n", |
513 | | string_buf, numbytes, bytes_out[0], bytes_out[1], bytes_out[2], |
514 | | bytes_out[3], bytes_out[4], bytes_out[5], bytes_out[6], bytes_out[7]); |
515 | | |
516 | | memset(bytes_out, 0, 8); |
517 | | numbytes = msHexDecode(string_buf, bytes_out, 4); |
518 | | printf( |
519 | | "msHexDecode(%s, 4) = %d, bytes_out = %x, %x, %x, %x, %x, %x, %x, %x\n", |
520 | | string_buf, numbytes, bytes_out[0], bytes_out[1], bytes_out[2], |
521 | | bytes_out[3], bytes_out[4], bytes_out[5], bytes_out[6], bytes_out[7]); |
522 | | |
523 | | memset(bytes_out, 0, 8); |
524 | | numbytes = msHexDecode(string_buf, bytes_out, 20); |
525 | | printf( |
526 | | "msHexDecode(%s, 20) = %d, bytes_out = %x, %x, %x, %x, %x, %x, %x, %x\n", |
527 | | string_buf, numbytes, bytes_out[0], bytes_out[1], bytes_out[2], |
528 | | bytes_out[3], bytes_out[4], bytes_out[5], bytes_out[6], bytes_out[7]); |
529 | | |
530 | | /* |
531 | | ** Test loading encryption key |
532 | | */ |
533 | | if (msReadEncryptionKeyFromFile("/tmp/test.key", encryption_key, NULL) != |
534 | | MS_SUCCESS) { |
535 | | printf("msReadEncryptionKeyFromFile() = MS_FAILURE\n"); |
536 | | printf("Aborting tests!\n"); |
537 | | msWriteError(stderr); |
538 | | return -1; |
539 | | } else { |
540 | | msHexEncode(encryption_key, string_buf, MS_ENCRYPTION_KEY_SIZE); |
541 | | printf("msReadEncryptionKeyFromFile() returned '%s'\n", string_buf); |
542 | | } |
543 | | |
544 | | /* |
545 | | ** Test Encryption/Decryption |
546 | | */ |
547 | | |
548 | | /* First with an 8 bytes input string (test boundaries) */ |
549 | | msEncryptStringWithKey(encryption_key, "test1234", string_buf); |
550 | | printf("msEncryptStringWithKey('test1234') returned '%s'\n", string_buf); |
551 | | |
552 | | msDecryptStringWithKey(encryption_key, string_buf, string_buf2); |
553 | | printf("msDecryptStringWithKey('%s') returned '%s'\n", string_buf, |
554 | | string_buf2); |
555 | | |
556 | | /* Next with an 1 byte input string */ |
557 | | msEncryptStringWithKey(encryption_key, "t", string_buf); |
558 | | printf("msEncryptStringWithKey('t') returned '%s'\n", string_buf); |
559 | | |
560 | | msDecryptStringWithKey(encryption_key, string_buf, string_buf2); |
561 | | printf("msDecryptStringWithKey('%s') returned '%s'\n", string_buf, |
562 | | string_buf2); |
563 | | |
564 | | /* Next with an 12 bytes input string */ |
565 | | msEncryptStringWithKey(encryption_key, "test123456", string_buf); |
566 | | printf("msEncryptStringWithKey('test123456') returned '%s'\n", string_buf); |
567 | | |
568 | | msDecryptStringWithKey(encryption_key, string_buf, string_buf2); |
569 | | printf("msDecryptStringWithKey('%s') returned '%s'\n", string_buf, |
570 | | string_buf2); |
571 | | |
572 | | /* |
573 | | ** Test decryption with tokens |
574 | | */ |
575 | | { |
576 | | char *pszBuf; |
577 | | mapObj *map; |
578 | | /* map = msNewMapObj(); */ |
579 | | map = msLoadMap("/tmp/test.map", NULL); |
580 | | |
581 | | sprintf(string_buf2, "string with a {%s} encrypted token", string_buf); |
582 | | |
583 | | pszBuf = msDecryptStringTokens(map, string_buf2); |
584 | | if (pszBuf == NULL) { |
585 | | printf("msDecryptStringTokens() failed.\n"); |
586 | | printf("Aborting tests!\n"); |
587 | | msWriteError(stderr); |
588 | | return -1; |
589 | | } else { |
590 | | printf("msDecryptStringTokens('%s') returned '%s'\n", string_buf2, |
591 | | pszBuf); |
592 | | } |
593 | | msFree(pszBuf); |
594 | | msFreeMap(map); |
595 | | } |
596 | | |
597 | | return 0; |
598 | | } |
599 | | |
600 | | #endif /* TEST_MAPCRYPTO */ |