summaryrefslogtreecommitdiff
path: root/crypt.c
diff options
context:
space:
mode:
authorBen Fuhrmannek2014-11-12 18:06:42 +0100
committerBen Fuhrmannek2014-11-12 18:06:42 +0100
commitd35835eabeda75dffe58b6bad50790e6adfbd156 (patch)
tree632a6c3337eec7293acd1b1104edd9fe30d790f4 /crypt.c
parent17849bcb55f757e6271c7d3e21ab34ccec849e07 (diff)
removed session structs + split crypt funcs
Diffstat (limited to 'crypt.c')
-rw-r--r--crypt.c283
1 files changed, 283 insertions, 0 deletions
diff --git a/crypt.c b/crypt.c
new file mode 100644
index 0000000..6df306d
--- /dev/null
+++ b/crypt.c
@@ -0,0 +1,283 @@
1/*
2 +----------------------------------------------------------------------+
3 | Suhosin Version 1 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2006-2007 The Hardened-PHP Project |
6 | Copyright (c) 2007-2014 SektionEins GmbH |
7 +----------------------------------------------------------------------+
8 | This source file is subject to version 3.01 of the PHP license, |
9 | that is bundled with this package in the file LICENSE, and is |
10 | available through the world-wide-web at the following url: |
11 | http://www.php.net/license/3_01.txt |
12 | If you did not receive a copy of the PHP license and are unable to |
13 | obtain it through the world-wide-web, please send a note to |
14 | license@php.net so we can mail you a copy immediately. |
15 +----------------------------------------------------------------------+
16 | Authors: Stefan Esser <sesser@sektioneins.de> |
17 | Ben Fuhrmannek <ben.fuhrmannek@sektioneins.de> |
18 +----------------------------------------------------------------------+
19*/
20
21#ifdef HAVE_CONFIG_H
22#include "config.h"
23#endif
24
25#include "php.h"
26#include "TSRM.h"
27#include "php_suhosin.h"
28#include "ext/standard/base64.h"
29#include "sha256.h"
30
31static void suhosin_get_ipv4(char *buf TSRMLS_DC)
32{
33 char *raddr = suhosin_getenv("REMOTE_ADDR", sizeof("REMOTE_ADDR")-1 TSRMLS_CC);
34 int i;
35
36
37 if (raddr == NULL) {
38 memset(buf, 0, 4);
39 return;
40 }
41
42 for (i=0; i<4; i++) {
43 if (raddr[0] == 0) {
44 buf[i] = 0;
45 } else {
46 buf[i] = strtol(raddr, &raddr, 10);
47 if (raddr[0] == '.') {
48 raddr++;
49 }
50 }
51 }
52}
53
54char *suhosin_encrypt_string(char *str, int len, char *var, int vlen, char *key TSRMLS_DC)
55{
56 int padded_len, i, slen;
57 unsigned char *crypted, *tmp;
58 unsigned int check = 0x13579BDF;
59
60 if (str == NULL) {
61 return NULL;
62 }
63 if (len == 0) {
64 return estrndup("", 0);
65 }
66
67
68 suhosin_aes_gkey(4,8,key TSRMLS_CC);
69
70 padded_len = ((len+15) & ~0xF);
71 crypted = emalloc(16+padded_len+1);
72 memset(crypted, 0xff, 16+padded_len+1);
73 memcpy(crypted+16, str, len+1);
74
75 /* calculate check value */
76 for (i = 0; i<vlen; i++) {
77 check = (check << 3) | (check >> (32-3));
78 check += check << 1;
79 check ^= (unsigned char)var[i];
80 }
81 for (i = 0; i<len; i++) {
82 check = (check << 3) | (check >> (32-3));
83 check += check << 1;
84 check ^= (unsigned char)str[i];
85 }
86
87 /* store ip value */
88 suhosin_get_ipv4((char *)crypted+4 TSRMLS_CC);
89
90 /* store check value */
91 crypted[8] = check & 0xff;
92 crypted[9] = (check >> 8) & 0xff;
93 crypted[10] = (check >> 16) & 0xff;
94 crypted[11] = (check >> 24) & 0xff;
95
96 /* store original length */
97 crypted[12] = len & 0xff;
98 crypted[13] = (len >> 8) & 0xff;
99 crypted[14] = (len >> 16) & 0xff;
100 crypted[15] = (len >> 24) & 0xff;
101
102 for (i=0, tmp=crypted; i<padded_len+16; i+=16, tmp+=16) {
103 if (i > 0) {
104 int j;
105 for (j=0; j<16; j++) tmp[j] ^= tmp[j-16];
106 }
107 suhosin_aes_encrypt((char *)tmp TSRMLS_CC);
108 }
109
110 tmp = php_base64_encode(crypted, padded_len+16, NULL);
111 efree(crypted);
112 slen=strlen((char *)tmp);
113 for (i=0; i<slen; i++) {
114 switch (tmp[i]) {
115 case '/': tmp[i]='-'; break;
116 case '=': tmp[i]='.'; break;
117 case '+': tmp[i]='_'; break;
118 }
119 }
120 return (char *)tmp;
121}
122
123char *suhosin_decrypt_string(char *str, int padded_len, char *var, int vlen, char *key, int *orig_len, int check_ra TSRMLS_DC)
124{
125 int len, i, o_len, invalid = 0;
126 unsigned char *decrypted, *tmp;
127 unsigned int check = 0x13579BDF;
128 char buf[4];
129
130 if (str == NULL) {
131 return NULL;
132 }
133
134 if (padded_len == 0) {
135 if (orig_len) {
136 *orig_len = 0;
137 }
138 return estrndup("", 0);
139 }
140 suhosin_aes_gkey(4,8,key TSRMLS_CC);
141
142 for (i=0; i<padded_len; i++) {
143 switch (str[i]) {
144 case '-': str[i]='/'; break;
145 case '.': str[i]='='; break;
146 case '_': str[i]='+'; break;
147 }
148 }
149
150 decrypted = php_base64_decode((unsigned char *)str, padded_len, &len);
151 if (decrypted == NULL || len < 2*16 || (len % 16) != 0) {
152error_out:
153 if (decrypted != NULL) {
154 efree(decrypted);
155 }
156 if (orig_len) {
157 *orig_len = 0;
158 }
159 return NULL;
160 }
161
162 for (i=len-16, tmp=decrypted+i; i>=0; i-=16, tmp-=16) {
163 suhosin_aes_decrypt((char *)tmp TSRMLS_CC);
164 if (i > 0) {
165 int j;
166 for (j=0; j<16; j++) tmp[j] ^= tmp[j-16];
167 }
168 }
169
170 /* retrieve orig_len */
171 o_len = decrypted[15];
172 o_len <<= 8;
173 o_len |= decrypted[14];
174 o_len <<= 8;
175 o_len |= decrypted[13];
176 o_len <<= 8;
177 o_len |= decrypted[12];
178
179 if (o_len < 0 || o_len > len-16) {
180 goto error_out;
181 }
182
183 /* calculate check value */
184 for (i = 0; i<vlen; i++) {
185 check = (check << 3) | (check >> (32-3));
186 check += check << 1;
187 check ^= (unsigned char)var[i];
188 }
189 for (i = 0; i<o_len; i++) {
190 check = (check << 3) | (check >> (32-3));
191 check += check << 1;
192 check ^= decrypted[16+i];
193 }
194
195 /* check value */
196 invalid = (decrypted[8] != (check & 0xff)) ||
197 (decrypted[9] != ((check >> 8) & 0xff)) ||
198 (decrypted[10] != ((check >> 16) & 0xff)) ||
199 (decrypted[11] != ((check >> 24) & 0xff));
200
201 /* check IP */
202 if (check_ra > 0) {
203 if (check_ra > 4) {
204 check_ra = 4;
205 }
206 suhosin_get_ipv4(&buf[0] TSRMLS_CC);
207 if (memcmp(buf, decrypted+4, check_ra) != 0) {
208 goto error_out;
209 }
210 }
211
212 if (invalid) {
213 goto error_out;
214 }
215
216 if (orig_len) {
217 *orig_len = o_len;
218 }
219
220 memmove(decrypted, decrypted+16, o_len);
221 decrypted[o_len] = 0;
222 /* we do not realloc() here because 16 byte less
223 is simply not worth the overhead */
224 return (char *)decrypted;
225}
226
227char *suhosin_generate_key(char *key, zend_bool ua, zend_bool dr, long raddr, char *cryptkey TSRMLS_DC)
228{
229 char *_ua = NULL;
230 char *_dr = NULL;
231 char *_ra = NULL;
232 suhosin_SHA256_CTX ctx;
233
234 if (ua) {
235 _ua = suhosin_getenv("HTTP_USER_AGENT", sizeof("HTTP_USER_AGENT")-1 TSRMLS_CC);
236 }
237
238 if (dr) {
239 _dr = suhosin_getenv("DOCUMENT_ROOT", sizeof("DOCUMENT_ROOT")-1 TSRMLS_CC);
240 }
241
242 if (raddr > 0) {
243 _ra = suhosin_getenv("REMOTE_ADDR", sizeof("REMOTE_ADDR")-1 TSRMLS_CC);
244 }
245
246 SDEBUG("(suhosin_generate_key) KEY: %s - UA: %s - DR: %s - RA: %s", key,_ua,_dr,_ra);
247
248 suhosin_SHA256Init(&ctx);
249 if (key == NULL || *key == 0) {
250 suhosin_SHA256Update(&ctx, (unsigned char*)"D3F4UL7", strlen("D3F4UL7"));
251 } else {
252 suhosin_SHA256Update(&ctx, (unsigned char*)key, strlen(key));
253 }
254 if (_ua) {
255 suhosin_SHA256Update(&ctx, (unsigned char*)_ua, strlen(_ua));
256 }
257 if (_dr) {
258 suhosin_SHA256Update(&ctx, (unsigned char*)_dr, strlen(_dr));
259 }
260 if (_ra) {
261 if (raddr >= 4) {
262 suhosin_SHA256Update(&ctx, (unsigned char*)_ra, strlen(_ra));
263 } else {
264 long dots = 0;
265 char *tmp = _ra;
266
267 while (*tmp) {
268 if (*tmp == '.') {
269 dots++;
270 if (dots == raddr) {
271 break;
272 }
273 }
274 tmp++;
275 }
276 suhosin_SHA256Update(&ctx, (unsigned char*)_ra, tmp-_ra);
277 }
278 }
279 suhosin_SHA256Final((unsigned char *)cryptkey, &ctx);
280 cryptkey[32] = 0; /* uhmm... not really a string */
281
282 return cryptkey;
283}