~drizzle-trunk/drizzle/development

1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
1
/* Copyright (c) 2008 PrimeBase Technologies GmbH, Germany
2
 *
3
 * PrimeBase S3Daemon
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
 *
19
 *  Created by Barry Leslie on 10/21/08.
20
 *
21
 */
22
 
23
#include "CSConfig.h"
24
#include <ctype.h>
25
26
#include "CSGlobal.h"
27
#include "CSString.h"
28
29
#include "CSEncode.h"
30
31
static const u_char base64Map[64] = {
32
	'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 
33
	'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 
34
	'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 
35
	'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 
36
	'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 
37
	'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 
38
	'w', 'x', 'y', 'z', '0', '1', '2', '3', 
39
	'4', '5', '6', '7', '8', '9', '+', '/'
40
};
41
 
42
static const u_char decodeBase64Map[128] = {
43
	0XBF, 0XFF, 0XF2, 0X2C, 0XBF, 0XFF, 0XF2, 0X24, 
44
	0X0, 0X0, 0X2E, 0X4C, 0X0, 0X0, 0X0, 0X3, 
45
	0X0, 0X0, 0X0, 0X3, 0XBF, 0XFF, 0XF1, 0X40, 
46
	0X0, 0X0, 0X0, 0X50, 0X8F, 0XE1, 0X56, 0XD8, 
47
	0X0, 0X30, 0X6, 0XEC, 0X0, 0X30, 0X6, 0XF0, 
48
	0X0, 0X0, 0X2E, 0X3E, 0X0, 0X0, 0X0, 0X3F, 
49
	0X34, 0X35, 0X36, 0X37, 0X38, 0X39, 0X3A, 0X3B, 
50
	0X3C, 0X3D, 0X2C, 0X68, 0X90, 0X0, 0X17, 0XD8, 
51
	0XBF, 0X0, 0X1, 0X2, 0X3, 0X4, 0X5, 0X6, 
52
	0X7, 0X8, 0X9, 0XA, 0XB, 0XC, 0XD, 0XE, 
53
	0XF, 0X10, 0X11, 0X12, 0X13, 0X14, 0X15, 0X16, 
54
	0X17, 0X18, 0X19, 0X80, 0X0, 0X0, 0X0, 0X0, 
55
	0X0, 0X1A, 0X1B, 0X1C, 0X1D, 0X1E, 0X1F, 0X20, 
56
	0X21, 0X22, 0X23, 0X24, 0X25, 0X26, 0X27, 0X28, 
57
	0X29, 0X2A, 0X2B, 0X2C, 0X2D, 0X2E, 0X2F, 0X30, 
58
	0X31, 0X32, 0X33, 0X0, 0X90, 0X1B, 0XBA, 0X48, 
59
};
60
61
62
static bool base64Encoded(const u_char *data, size_t len)
63
{
64
	if (len % 4)
65
		return false;
66
		
67
	size_t i = len;
68
	
69
	while ( i && data[i-1] == '=') i--;
70
	
71
	if ( (len - i) > 2)
72
		return false;
73
		
74
	for (; i ; i--, data++) {
75
		if (*data > 63)
76
			return false;
77
	}
78
	
79
	return true; // Actually this isn't so much 'true' as 'maybe'
80
}
81
82
char *base64Encode(const void *data, size_t len)
83
{
84
	u_char *wptr, *rptr, *encoding;
85
	size_t size;
86
	enter_();
87
88
	size = ((len + 2) / 3) * 4;
89
	encoding = (u_char *) cs_malloc(size +1);
90
	encoding[size] = 0;
91
	
92
	wptr= encoding;
93
	rptr = (u_char *) data;
94
	
95
	while (len/3) {		
96
		wptr[0] = base64Map[rptr[0] >>2];
97
		wptr[1] = base64Map[((rptr[0] & 0X03) <<4) + (rptr[1] >> 4)];
98
		wptr[2] = base64Map[((rptr[1] & 0X0F) <<2) + (rptr[2] >> 6)];
99
		wptr[3] = base64Map[(rptr[2] & 0X3F)];
100
		rptr += 3;
101
		wptr += 4;
102
		len -=3;
103
	}
104
	
105
	if (len) {
106
		wptr[0] = base64Map[rptr[0] >>2];
107
108
		if (len == 1) {
109
			wptr[1] = base64Map[(rptr[0] & 0x03) << 4]; 
110
			wptr[2] = wptr[3] = '=';
111
		} else {
112
			wptr[1] = base64Map[((rptr[0] & 0X03) <<4) + (rptr[1] >> 4)];
113
			wptr[2] = base64Map[(rptr[1] & 0X0F) <<2];
114
			wptr[3] = '=';
115
		}
116
		
117
	}
118
	
119
	return_((char*)encoding);
120
}
121
122
void *base64Decode(const char *data, size_t len)
123
{
1548.2.2 by Barry.Leslie at PrimeBase
A lot of minor changes to clean up the code and to get it to build with Drizzle.
124
	uint32_t tail;
1548.2.1 by Barry.Leslie at PrimeBase
Added the PBMS daemon plugin.
125
	u_char *wptr, *rptr, *decoding;
126
	enter_();
127
128
	rptr = (u_char *) data;
129
130
	if (!base64Encoded(rptr, len)) 
131
		CSException::throwException(CS_CONTEXT, CS_ERR_GENERIC_ERROR, "String was not Base64 encoded.");
132
	
133
	decoding = (u_char *) cs_malloc((len/ 4) * 3);
134
	
135
	wptr= decoding;
136
	
137
	tail = len; 
138
	while (rptr[tail-1] == '=') 
139
		tail--; 
140
141
	len -= tail;
142
	while (len/4) {		
143
		wptr[0] = ( ((decodeBase64Map[rptr[0]] << 2) & 0xFF) | ((decodeBase64Map[rptr[1]] >> 4) & 0x03) ); 
144
		wptr[1] = ( ((decodeBase64Map[rptr[1]] << 4) & 0xFF) | ((decodeBase64Map[rptr[2]] >> 2) & 0x0F) ); 
145
		wptr[2] = ( ((decodeBase64Map[rptr[2]] << 6) & 0xFF) | (decodeBase64Map[rptr[3]] & 0x3F) ); 
146
147
		rptr += 4;
148
		wptr += 3;
149
		len -=4;
150
	}
151
	
152
	if (len) {
153
		wptr[0] = ( ((decodeBase64Map[rptr[0]] << 2) & 0xFF) |  ((decodeBase64Map[rptr[1]] >> 4) & 0x03) ); 
154
		if (len == 2) 
155
			wptr[1] = ( ((decodeBase64Map[rptr[1]] << 4) & 0xFF) | ((decodeBase64Map[rptr[2]] >> 2) & 0x0F) ); 
156
	}
157
	
158
	return_(decoding);
159
}
160
161
#ifdef NOT_USED
162
//-----------------------------------------------------
163
void  hmac_md5(u_char *text, size_t text_len, u_char *key, size_t key_len, Md5Digest *digest)
164
{
165
	CSMd5 md5;
166
	unsigned char k_ipad[65];    /* inner padding -
167
								  * key XORd with ipad
168
								  */
169
	unsigned char k_opad[65];    /* outer padding -
170
								  * key XORd with opad
171
								  */
172
	unsigned char tk[16];
173
	int i;
174
	
175
	/* if key is longer than 64 bytes reset it to key=MD5(key) */
176
	if (key_len > 64) {
177
		CSMd5 tmd5;
178
179
		md5.md5_init();
180
		md5.md5_append(key, key_len);
181
		md5.md5_digest(digest);
182
183
		key = digest->val;
184
		key_len = 16;
185
	}
186
187
	/* start out by storing key in pads */
188
	memset(k_ipad, 0, sizeof(k_ipad));
189
	memset(k_opad, 0, sizeof(k_opad));
190
191
	memcpy(k_ipad, key, key_len);
192
	memcpy(k_opad, key, key_len);
193
194
	/* XOR key with ipad and opad values */
195
	for (i=0; i<64; i++) {
196
		k_ipad[i] ^= 0x36;
197
		k_opad[i] ^= 0x5c;
198
	}
199
	/*
200
	 * perform inner encoding
201
	 */
202
	md5.md5_init();
203
	md5.md5_append(k_ipad, 64);
204
	md5.md5_append(text, strlen(text));
205
	md5.md5_digest(digest);
206
207
	/*
208
	 * perform outer encoding
209
	 */
210
	md5.md5_init();
211
	md5.md5_append(k_opad, 64);
212
	md5.md5_append((u_char*)digest, 16);
213
	md5.md5_digest(digest);
214
	
215
}
216
217
#endif // NOT_USED
218
219
//-----------------------------------------------------
220
void  hmac_sha1(const char *text, const char *key, Sha1Digest *digest)
221
{
222
	CSSha1 sha1;
223
	size_t key_len = strlen(key);
224
	unsigned char k_ipad[65];    /* inner padding -
225
								  * key XORd with ipad
226
								  */
227
	unsigned char k_opad[65];    /* outer padding -
228
								  * key XORd with opad
229
								  */
230
	int i;
231
	
232
	/* if key is longer than 64 bytes reset it to key=MD5(key) */
233
	if (key_len > 64) {
234
		CSMd5 tmd5;
235
236
		sha1.sha1_reset();
237
		sha1.sha1_input(key, key_len);
238
		sha1.sha1_digest(digest);
239
240
		key = (char *) digest->val;
241
		key_len = 16;
242
	}
243
244
	/* start out by storing key in pads */
245
	memset(k_ipad, 0, sizeof(k_ipad));
246
	memset(k_opad, 0, sizeof(k_opad));
247
248
	memcpy(k_ipad, key, key_len);
249
	memcpy(k_opad, key, key_len);
250
251
	/* XOR key with ipad and opad values */
252
	for (i=0; i<64; i++) {
253
		k_ipad[i] ^= 0x36;
254
		k_opad[i] ^= 0x5c;
255
	}
256
257
	/*
258
	 * perform inner encoding
259
	 */
260
	sha1.sha1_reset();
261
	sha1.sha1_input(k_ipad, 64);
262
	sha1.sha1_input(text, strlen(text));
263
	sha1.sha1_digest(digest);
264
265
266
	/*
267
	 * perform outer encoding
268
	 */
269
	sha1.sha1_reset();
270
	sha1.sha1_input(k_opad, 64);
271
	sha1.sha1_input(digest, 20);
272
	sha1.sha1_digest(digest);
273
}
274
275
276
//-----------------------------------------------------
277
CSString *signature(const char *text, const char *key)
278
{
279
	Sha1Digest digest;
280
	char *encoding;
281
	CSString *signed_str;
282
	
283
	memset(&digest, 0, sizeof(digest));
284
	hmac_sha1(text, key, &digest);
285
286
	encoding = base64Encode(digest.val, SHA1_HASH_SIZE);
287
	signed_str = CSString::newString(encoding);
288
	cs_free(encoding);
289
	return signed_str;
290
}
291
292
293
//-----------------------------------------------------
294
// Encode url unsafe characters
295
CSString *urlEncode(CSString *src)
296
{
297
	const char *hex = "0123456789ABCDEF", *start, *ptr;
298
	char encoded[3];
299
	CSStringBuffer *url;
300
	
301
	enter_();
302
	push_(src);
303
	
304
	new_(url, CSStringBuffer(10));
305
	push_(url);
306
	
307
	start = ptr = src->getCString();
308
	encoded[0] = '%';
309
	
310
	while(*ptr) {
311
		if (!isalnum(*ptr)) {
312
			switch (*ptr) {
313
				case '.':
314
				case '!':
315
				case '*':
316
				case '~':
317
				case '\'':
318
				case '(':
319
				case ')':
320
				case '_':
321
				case '-':
322
				case '/':
323
					break;
324
				default:
325
					url->append(start, ptr-start);
326
					start = ptr +1;
327
					encoded[1] = hex[*ptr/16];
328
					encoded[2] = hex[*ptr%16];				
329
					url->append(encoded, 3);
330
			}
331
		}
332
		ptr++;		
333
	}
334
	url->append(start, ptr-start);	
335
	
336
	CSString *safe_str = CSString::newString(url->getCString());
337
	
338
	release_(url);
339
	release_(src);
340
	return_(safe_str);
341
}