Skip to content

Commit 1e820ec

Browse files
committed
-MFH:
- #45430, windows implementation of crypt is not TS - add Blowfish (using implementation from Solar Designer <solar at openwal dot com>) and extended DES support - Make crypt features portable: - if no crypt_r, php's implemetation is used (all algo and TS), php can't be used with unsafe crypt anymore - if one algo is missing, php's implemetation is used - Windows always use php's implementation - removed old code in windows/
1 parent ba84cd7 commit 1e820ec

16 files changed

+2356
-828
lines changed

NEWS

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,13 @@ PHP NEWS
161161
perform class declaration (early and/or run-time binding) in exactly
162162
the same order as vanilla PHP. (Dmitry)
163163

164+
- Improved crypt() function (Pierre)
165+
. add Blowfish (using implementation from Solar Designer <solar at openwal dot com>) and extended DES support
166+
. Make crypt features portable:
167+
. if no crypt_r, php's implemetation is used (all algo and TS), php can't be used with unsafe crypt anymore
168+
. if one algo is missing, php's implemetation is used
169+
. Windows always use php's implementation
170+
164171
- Added new date/time functionality: (Derick)
165172
. date_parse_from_format(): Parse date/time strings according to a format.
166173
. date_create_from_format()/DateTime::createFromFormat(): Create a date/time
@@ -202,7 +209,7 @@ PHP NEWS
202209
. DatePeriod class which supports iterating over a DateTime object applying
203210
DateInterval on each iteration, up to an end date or limited by maximum
204211
number of occurences.
205-
212+
- Added Extended DES, Blowfish to all
206213
- Added hash_copy() function. (Tony)
207214
- Added sha224 hash algorithm to the hash extension. (Scott)
208215
- Added ReflectionProperty::setAccessible() method that allows non-public
@@ -246,6 +253,8 @@ PHP NEWS
246253
prop of wrapped object). (robin_fernandes at uk dot ibm dot com, Arnaud)
247254
- Fixed bug #45571 (ReflectionClass::export() shows superclasses' private
248255
static methods). (robin_fernandes at uk dot ibm dot com)
256+
- Fixed bug #45430 (windows implementation of crypt is not thread safe).
257+
(Pierre)
249258
- Fixed bug #45345 (SPLFileInfo::getPathInfo() returning dir info instead of
250259
file info). (Etienne)
251260
- Fixed bug #45179 (--with-mysql-sock fails to compile & work). (Andrey)

ext/standard/config.m4

Lines changed: 40 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -84,12 +84,6 @@ main() {
8484
],[
8585
ac_cv_crypt_des=yes
8686
])])
87-
if test "$ac_cv_crypt_des" = "yes"; then
88-
ac_result=1
89-
else
90-
ac_result=0
91-
fi
92-
AC_DEFINE_UNQUOTED(PHP_STD_DES_CRYPT, $ac_result, [Whether the system supports standard DES salt])
9387

9488
AC_CACHE_CHECK(for extended DES crypt, ac_cv_crypt_ext_des,[
9589
AC_TRY_RUN([
@@ -114,12 +108,6 @@ main() {
114108
],[
115109
ac_cv_crypt_ext_des=no
116110
])])
117-
if test "$ac_cv_crypt_ext_des" = "yes"; then
118-
ac_result=1
119-
else
120-
ac_result=0
121-
fi
122-
AC_DEFINE_UNQUOTED(PHP_EXT_DES_CRYPT, $ac_result, [Whether the system supports extended DES salt])
123111

124112
AC_CACHE_CHECK(for MD5 crypt, ac_cv_crypt_md5,[
125113
AC_TRY_RUN([
@@ -153,15 +141,6 @@ main() {
153141
],[
154142
ac_cv_crypt_md5=no
155143
])])
156-
if test "$ac_cv_crypt_md5" = "yes"; then
157-
ac_result=1
158-
else
159-
if test "$ac_cv_crypt_des" != "yes"; then
160-
PHP_DEBUG_MACRO(debug.log)
161-
fi
162-
ac_result=0
163-
fi
164-
AC_DEFINE_UNQUOTED(PHP_MD5_CRYPT, $ac_result, [Whether the system supports MD5 salt])
165144

166145
AC_CACHE_CHECK(for Blowfish crypt, ac_cv_crypt_blowfish,[
167146
AC_TRY_RUN([
@@ -192,12 +171,48 @@ main() {
192171
],[
193172
ac_cv_crypt_blowfish=no
194173
])])
195-
if test "$ac_cv_crypt_blowfish" = "yes"; then
196-
ac_result=1
174+
175+
dnl
176+
dnl If one of them is missing, use our own implementation, portable code is then possible
177+
dnl
178+
if test "$ac_cv_crypt_blowfish" = "no" || test "$ac_cv_crypt_des" = "no" || test "$ac_cv_crypt_ext_des" = "no" || test "x$php_crypt_r" = "x0"; then
179+
AC_DEFINE_UNQUOTED(PHP_USE_PHP_CRYPT_R, 1, [Whether PHP has to use its own crypt_r for blowfish, des, ext des and md5])
180+
AC_DEFINE_UNQUOTED(PHP_STD_DES_CRYPT, 1, [Whether the system supports standard DES salt])
181+
AC_DEFINE_UNQUOTED(PHP_BLOWFISH_CRYPT, 1, [Whether the system supports BlowFish salt])
182+
AC_DEFINE_UNQUOTED(PHP_EXT_DES_CRYPT, 1, [Whether the system supports extended DES salt])
183+
AC_DEFINE_UNQUOTED(PHP_MD5_CRYPT, 1, [Whether the system supports extended DES salt])
184+
185+
PHP_ADD_SOURCES(PHP_EXT_DIR(standard), crypt_freesec.c crypt_blowfish.c php_crypt_r.c)
197186
else
198-
ac_result=0
187+
if test "$ac_cv_crypt_des" = "yes"; then
188+
ac_result=1
189+
ac_crypt_des=1
190+
else
191+
ac_result=0
192+
ac_crypt_des=0
193+
fi
194+
AC_DEFINE_UNQUOTED(PHP_STD_DES_CRYPT, $ac_result, [Whether the system supports standard DES salt])
195+
196+
if test "$ac_cv_crypt_blowfish" = "yes"; then
197+
ac_result=1
198+
ac_crypt_blowfish=1
199+
else
200+
ac_result=0
201+
ac_crypt_blowfish=0
202+
fi
203+
AC_DEFINE_UNQUOTED(PHP_BLOWFISH_CRYPT, $ac_result, [Whether the system supports BlowFish salt])
204+
205+
if test "$ac_cv_crypt_ext_des" = "yes"; then
206+
ac_result=1
207+
ac_crypt_edes=1
208+
else
209+
ac_result=0
210+
ac_crypt_edes=0
211+
fi
212+
AC_DEFINE_UNQUOTED(PHP_EXT_DES_CRYPT, $ac_result, [Whether the system supports extended DES salt])
213+
214+
AC_DEFINE_UNQUOTED(PHP_USE_PHP_CRYPT_R, 0, [Whether PHP has to use its own crypt_r for blowfish, des and ext des])
199215
fi
200-
AC_DEFINE_UNQUOTED(PHP_BLOWFISH_CRYPT, $ac_result, [Whether the system supports BlowFish salt])
201216

202217
dnl
203218
dnl Check for available functions

ext/standard/config.w32

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,14 @@ AC_DEFINE("PHP_CONFIG_FILE_SCAN_DIR", PHP_CONFIG_FILE_SCAN_DIR);
77
AC_DEFINE("HAVE_INET_PTON", 1);
88
AC_DEFINE("HAVE_INET_NTOP", 1);
99

10+
AC_DEFINE("PHP_USE_PHP_CRYPT_R", 1);
11+
1012
CHECK_HEADER_ADD_INCLUDE("timelib_config.h", "CFLAGS_STANDARD", "ext/date/lib");
1113

1214
EXTENSION("standard", "array.c base64.c basic_functions.c browscap.c \
13-
crc32.c crypt.c cyr_convert.c datetime.c dir.c dl.c dns.c exec.c \
15+
crc32.c crypt.c \
16+
crypt_freesec.c crypt_blowfish.c php_crypt_r.c \
17+
cyr_convert.c datetime.c dir.c dl.c dns.c exec.c \
1418
file.c filestat.c formatted_print.c fsock.c head.c html.c image.c \
1519
info.c iptc.c lcg.c link.c mail.c math.c md5.c metaphone.c microtime.c \
1620
pack.c pageinfo.c quot_print.c rand.c soundex.c \
@@ -23,4 +27,4 @@ EXTENSION("standard", "array.c base64.c basic_functions.c browscap.c \
2327

2428
if (PHP_MBREGEX != "no") {
2529
CHECK_HEADER_ADD_INCLUDE("oniguruma.h", "CFLAGS_STANDARD", PHP_MBREGEX + ";ext\\mbstring\\oniguruma")
26-
}
30+
}

ext/standard/crypt.c

Lines changed: 65 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,21 @@
2323
#include <stdlib.h>
2424

2525
#include "php.h"
26-
2726
#if HAVE_CRYPT
2827

2928
#if HAVE_UNISTD_H
3029
#include <unistd.h>
3130
#endif
32-
#if HAVE_CRYPT_H
33-
#if defined(CRYPT_R_GNU_SOURCE) && !defined(_GNU_SOURCE)
34-
#define _GNU_SOURCE
35-
#endif
36-
#include <crypt.h>
31+
#ifdef PHP_USE_PHP_CRYPT_R
32+
# include "php_crypt_r.h"
33+
# include "crypt_freesec.h"
34+
#else
35+
# if HAVE_CRYPT_H
36+
# if defined(CRYPT_R_GNU_SOURCE) && !defined(_GNU_SOURCE)
37+
# define _GNU_SOURCE
38+
# endif
39+
# include <crypt.h>
40+
# endif
3741
#endif
3842
#if TM_IN_SYS_TIME
3943
#include <sys/time.h>
@@ -48,7 +52,6 @@
4852

4953
#ifdef PHP_WIN32
5054
#include <process.h>
51-
extern char *crypt(char *__key, char *__salt);
5255
#endif
5356

5457
#include "php_lcg.h"
@@ -98,8 +101,21 @@ PHP_MINIT_FUNCTION(crypt) /* {{{ */
98101
REGISTER_LONG_CONSTANT("CRYPT_MD5", PHP_MD5_CRYPT, CONST_CS | CONST_PERSISTENT);
99102
REGISTER_LONG_CONSTANT("CRYPT_BLOWFISH", PHP_BLOWFISH_CRYPT, CONST_CS | CONST_PERSISTENT);
100103

104+
#ifdef PHP_USE_PHP_CRYPT_R
105+
php_init_crypt_r();
106+
#endif
107+
108+
return SUCCESS;
109+
}
110+
111+
#ifdef PHP_USE_PHP_CRYPT_R
112+
PHP_MSHUTDOWN_FUNCTION(crypt)
113+
{
114+
php_shutdown_crypt_r();
115+
101116
return SUCCESS;
102117
}
118+
#endif
103119
/* }}} */
104120

105121
static unsigned char itoa64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
@@ -135,7 +151,7 @@ PHP_FUNCTION(crypt)
135151
memcpy(salt, salt_in, MIN(PHP_MAX_SALT_LEN, salt_in_len));
136152
}
137153

138-
/* The automatic salt generation only covers standard DES and md5-crypt */
154+
/* The automatic salt generation covers standard DES, md5-crypt and Blowfish (simple) */
139155
if (!*salt) {
140156
#if PHP_MD5_CRYPT
141157
strcpy(salt, "$1$");
@@ -147,21 +163,54 @@ PHP_FUNCTION(crypt)
147163
salt[2] = '\0';
148164
#endif
149165
}
150-
#if defined(HAVE_CRYPT_R) && (defined(_REENTRANT) || defined(_THREAD_SAFE))
166+
167+
/* Windows (win32/crypt) has a stripped down version of libxcrypt and
168+
a CryptoApi md5_crypt implementation */
169+
#if PHP_USE_PHP_CRYPT_R
151170
{
152-
#if defined(CRYPT_R_STRUCT_CRYPT_DATA)
171+
struct php_crypt_extended_data buffer;
172+
173+
if (salt[0]=='$' && salt[1]=='1' && salt[2]=='$') {
174+
char output[MD5_HASH_MAX_LEN];
175+
176+
RETURN_STRING(php_md5_crypt_r(str, salt, output), 1);
177+
} else if (
178+
salt[0] == '$' &&
179+
salt[1] == '2' &&
180+
salt[2] == 'a' &&
181+
salt[3] == '$' &&
182+
salt[4] >= '0' && salt[4] <= '3' &&
183+
salt[5] >= '0' && salt[5] <= '9' &&
184+
salt[6] == '$') {
185+
char output[PHP_MAX_SALT_LEN + 1];
186+
187+
memset(output, 0, PHP_MAX_SALT_LEN + 1);
188+
php_crypt_blowfish_rn(str, salt, output, sizeof(output));
189+
190+
RETVAL_STRING(output, 1);
191+
memset(output, 0, PHP_MAX_SALT_LEN + 1);
192+
} else {
193+
memset(&buffer, 0, sizeof(buffer));
194+
_crypt_extended_init_r();
195+
RETURN_STRING(_crypt_extended_r(str, salt, &buffer), 1);
196+
}
197+
}
198+
#else
199+
200+
# if defined(HAVE_CRYPT_R) && (defined(_REENTRANT) || defined(_THREAD_SAFE))
201+
{
202+
# if defined(CRYPT_R_STRUCT_CRYPT_DATA)
153203
struct crypt_data buffer;
154204
memset(&buffer, 0, sizeof(buffer));
155-
#elif defined(CRYPT_R_CRYPTD)
205+
# elif defined(CRYPT_R_CRYPTD)
156206
CRYPTD buffer;
157-
#else
158-
#error Data struct used by crypt_r() is unknown. Please report.
159-
#endif
207+
# else
208+
# error Data struct used by crypt_r() is unknown. Please report.
209+
# endif
160210

161211
RETURN_STRING(crypt_r(str, salt, &buffer), 1);
162212
}
163-
#else
164-
RETURN_STRING(crypt(str, salt), 1);
213+
# endif
165214
#endif
166215
}
167216
/* }}} */

0 commit comments

Comments
 (0)