summaryrefslogtreecommitdiff
path: root/crypt.c
diff options
context:
space:
mode:
authorStefan Esser2010-02-21 11:44:54 +0100
committerStefan Esser2010-02-21 11:44:54 +0100
commit36dbfacbe64697d959f524e537b15b73c090d898 (patch)
treef1c7ce1409b0e7765fc72d550546967fcf0f9717 /crypt.c
Inital commit
Diffstat (limited to 'crypt.c')
-rw-r--r--crypt.c214
1 files changed, 214 insertions, 0 deletions
diff --git a/crypt.c b/crypt.c
new file mode 100644
index 0000000..72a34c8
--- /dev/null
+++ b/crypt.c
@@ -0,0 +1,214 @@
1/*
2 +----------------------------------------------------------------------+
3 | Suhosin Version 1 |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2006-2007 The Hardened-PHP Project |
6 | Copyright (c) 2007 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 | Author: Stefan Esser <sesser@sektioneins.de> |
17 +----------------------------------------------------------------------+
18*/
19/*
20 $Id: crypt.c,v 1.2 2008-01-04 11:23:47 sesser Exp $
21*/
22
23#ifdef HAVE_CONFIG_H
24#include "config.h"
25#endif
26
27#include "php.h"
28#include "php_ini.h"
29#include "php_suhosin.h"
30
31
32#if HAVE_UNISTD_H
33#include <unistd.h>
34#endif
35#if HAVE_CRYPT_H
36#include <crypt.h>
37#endif
38#if TM_IN_SYS_TIME
39#include <sys/time.h>
40#else
41#include <time.h>
42#endif
43#if HAVE_STRING_H
44#include <string.h>
45#else
46#include <strings.h>
47#endif
48
49#ifdef PHP_WIN32
50#include <process.h>
51extern char *crypt(char *__key, char *__salt);
52#endif
53
54#include "ext/standard/php_lcg.h"
55#include "ext/standard/php_crypt.h"
56#include "ext/standard/php_rand.h"
57
58
59#define PHP_CRYPT_RAND php_rand(TSRMLS_C)
60
61#define BLOWFISH_SALT_LEN 60
62
63#ifdef ZTS
64static MUTEX_T suhosin_crypt_mutex;
65#endif
66
67static int CRYPT_MD5 = 0;
68
69char *suhosin_crypt_blowfish_rn(char *key, char *setting, char *output, int size);
70char *suhosin_crypt_gensalt_blowfish_rn(unsigned long count, char *input, int size, char *output, int output_size);
71
72static unsigned char itoa64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
73
74static void php_to64(char *s, long v, int n)
75{
76 while (--n >= 0) {
77 *s++ = itoa64[v&0x3f];
78 v >>= 6;
79 }
80}
81
82/* {{{ proto string crypt(string str [, string salt])
83 Encrypt a string */
84static PHP_FUNCTION(suhosin_crypt)
85{
86 char salt[BLOWFISH_SALT_LEN+1];
87 char *str, *salt_in = NULL;
88 int str_len, salt_in_len;
89
90 salt[0]=salt[BLOWFISH_SALT_LEN]='\0';
91 /* This will produce suitable results if people depend on DES-encryption
92 available (passing always 2-character salt). At least for glibc6.1 */
93 memset(&salt[1], '$', BLOWFISH_SALT_LEN-1);
94
95 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &str, &str_len,
96 &salt_in, &salt_in_len) == FAILURE) {
97 return;
98 }
99
100 if (salt_in) {
101 memcpy(salt, salt_in, MIN(BLOWFISH_SALT_LEN, salt_in_len));
102 }
103
104 /* The automatic salt generation only covers standard DES and md5-crypt */
105 if(!*salt) {
106 if (CRYPT_MD5) {
107 strcpy(salt, "$1$");
108 php_to64(&salt[3], PHP_CRYPT_RAND, 4);
109 php_to64(&salt[7], PHP_CRYPT_RAND, 4);
110 strcpy(&salt[11], "$");
111 } else {
112 php_to64(&salt[0], PHP_CRYPT_RAND, 2);
113 salt[2] = '\0';
114 }
115 }
116
117 if (salt[0] == '$' &&
118 salt[1] == '2' &&
119 salt[2] == 'a' &&
120 salt[3] == '$' &&
121 salt[4] >= '0' && salt[4] <= '3' &&
122 salt[5] >= '0' && salt[5] <= '9' &&
123 salt[6] == '$') {
124
125 char output[BLOWFISH_SALT_LEN+1];
126
127 output[0] = 0;
128 suhosin_crypt_blowfish_rn(str, salt, output, sizeof(output));
129 RETVAL_STRING(output, 1);
130
131 } else {
132#ifdef ZTS
133 tsrm_mutex_lock(suhosin_crypt_mutex);
134#endif
135 RETVAL_STRING(crypt(str, salt), 1);
136#ifdef ZTS
137 tsrm_mutex_unlock(suhosin_crypt_mutex);
138#endif
139 }
140}
141/* }}} */
142
143
144/* {{{ suhosin_crypt_functions[]
145 */
146static function_entry suhosin_crypt_functions[] = {
147 PHP_NAMED_FE(crypt, PHP_FN(suhosin_crypt), NULL)
148 {NULL, NULL, NULL}
149};
150/* }}} */
151
152
153void suhosin_hook_crypt()
154{
155 zend_constant *c;
156 TSRMLS_FETCH();
157
158 /* check if we have MD5 support */
159 if (zend_hash_find(EG(zend_constants), "CRYPT_MD5", sizeof("CRYPT_MD5"), (void **) &c) == SUCCESS) {
160 if (c->value.type == IS_LONG && c->value.value.lval > 0) {
161 CRYPT_MD5 = 1;
162 }
163 }
164
165 /* check if we already have blowfish support */
166 if (zend_hash_find(EG(zend_constants), "CRYPT_BLOWFISH", sizeof("CRYPT_BLOWFISH"), (void **) &c) == FAILURE) {
167
168 /* should we just bailout when this constant is not known at all? */
169 return;
170 }
171
172 if (c->value.type == IS_LONG && c->value.value.lval > 0) {
173
174 /* blowfish support already installed */
175 return;
176 }
177
178 /* mark blowfish as supported */
179 c->value.type = IS_LONG;
180 c->value.value.lval = 1;
181
182 /* now fix the CRYPT_SALT_LENGTH constant */
183 if (zend_hash_find(EG(zend_constants), "CRYPT_SALT_LENGTH", sizeof("CRYPT_SALT_LENGTH"), (void **) &c) == SUCCESS) {
184 c->value.type = IS_LONG;
185 c->value.value.lval = BLOWFISH_SALT_LEN;
186 }
187#ifdef ZTS
188 suhosin_crypt_mutex = tsrm_mutex_alloc();
189#endif
190
191 /* replace the crypt() function */
192 zend_hash_del(CG(function_table), "crypt", sizeof("crypt"));
193#ifndef ZEND_ENGINE_2
194 zend_register_functions(suhosin_crypt_functions, NULL, MODULE_PERSISTENT TSRMLS_CC);
195#else
196 zend_register_functions(NULL, suhosin_crypt_functions, NULL, MODULE_PERSISTENT TSRMLS_CC);
197#endif
198
199
200
201
202}
203
204
205/*
206 * Local variables:
207 * tab-width: 4
208 * c-basic-offset: 4
209 * End:
210 * vim600: noet sw=4 ts=4 fdm=marker
211 * vim<600: noet sw=4 ts=4
212 */
213
214