1999-04-22 00:25:57 +00:00
/*
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2014-09-19 16:33:14 +00:00
| PHP Version 7 |
1999-04-22 00:25:57 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2015-01-15 15:27:30 +00:00
| Copyright ( c ) 1997 - 2015 The PHP Group |
1999-04-22 00:25:57 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2006-01-01 12:51:34 +00:00
| This source file is subject to version 3.01 of the PHP license , |
1999-07-16 13:13:16 +00:00
| that is bundled with this package in the file LICENSE , and is |
2003-06-10 20:04:29 +00:00
| available through the world - wide - web at the following url : |
2006-01-01 12:51:34 +00:00
| http : //www.php.net/license/3_01.txt |
1999-07-16 13:13:16 +00:00
| If you did not receive a copy of the PHP license and are unable to |
| obtain it through the world - wide - web , please send a note to |
| license @ php . net so we can mail you a copy immediately . |
1999-04-22 00:25:57 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2004-02-12 19:05:41 +00:00
| Authors : Stig Bakken < ssb @ php . net > |
1999-07-16 13:13:16 +00:00
| Zeev Suraski < zeev @ zend . com > |
2002-02-28 08:29:35 +00:00
| Rasmus Lerdorf < rasmus @ php . net > |
2010-02-21 18:11:11 +00:00
| Pierre Joye < pierre @ php . net > |
1999-04-22 00:25:57 +00:00
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
2007-11-05 12:44:52 +00:00
*/
1999-04-22 00:25:57 +00:00
/* $Id$ */
2007-11-05 12:44:52 +00:00
1999-04-22 00:25:57 +00:00
# include <stdlib.h>
# include "php.h"
# if HAVE_CRYPT
# if HAVE_UNISTD_H
# include <unistd.h>
# endif
2010-04-22 20:54:35 +00:00
# if PHP_USE_PHP_CRYPT_R
2008-07-28 11:50:35 +00:00
# include "php_crypt_r.h"
# include "crypt_freesec.h"
# else
# if HAVE_CRYPT_H
# if defined(CRYPT_R_GNU_SOURCE) && !defined(_GNU_SOURCE)
# define _GNU_SOURCE
# endif
# include <crypt.h>
# endif
1999-04-22 00:25:57 +00:00
# endif
# if TM_IN_SYS_TIME
# include <sys/time.h>
# else
# include <time.h>
# endif
# if HAVE_STRING_H
# include <string.h>
# else
# include <strings.h>
# endif
2000-02-11 15:59:30 +00:00
# ifdef PHP_WIN32
1999-04-22 00:25:57 +00:00
# include <process.h>
# endif
2000-07-26 16:35:32 +00:00
# include "php_lcg.h"
1999-12-04 19:19:57 +00:00
# include "php_crypt.h"
2001-02-22 03:37:32 +00:00
# include "php_rand.h"
1999-04-22 00:25:57 +00:00
2007-11-05 12:44:52 +00:00
/* The capabilities of the crypt() function is determined by the test programs
* run by configure from aclocal . m4 . They will set PHP_STD_DES_CRYPT ,
* PHP_EXT_DES_CRYPT , PHP_MD5_CRYPT and PHP_BLOWFISH_CRYPT as appropriate
* for the target platform . */
2000-02-26 03:20:55 +00:00
# if PHP_STD_DES_CRYPT
# define PHP_MAX_SALT_LEN 2
1999-04-22 00:25:57 +00:00
# endif
2000-07-26 16:42:04 +00:00
2000-02-26 03:20:55 +00:00
# if PHP_EXT_DES_CRYPT
# undef PHP_MAX_SALT_LEN
# define PHP_MAX_SALT_LEN 9
1999-04-22 00:25:57 +00:00
# endif
2000-07-26 16:42:04 +00:00
2000-02-26 03:20:55 +00:00
# if PHP_MD5_CRYPT
# undef PHP_MAX_SALT_LEN
# define PHP_MAX_SALT_LEN 12
1999-04-22 00:25:57 +00:00
# endif
2000-07-26 16:42:04 +00:00
2000-02-26 03:20:55 +00:00
# if PHP_BLOWFISH_CRYPT
# undef PHP_MAX_SALT_LEN
2001-01-07 17:22:17 +00:00
# define PHP_MAX_SALT_LEN 60
2000-05-05 10:36:00 +00:00
# endif
2009-12-09 00:20:14 +00:00
# if PHP_SHA512_CRYPT
# undef PHP_MAX_SALT_LEN
# define PHP_MAX_SALT_LEN 123
# endif
2007-11-05 12:44:52 +00:00
/* If the configure-time checks fail, we provide DES.
* XXX : This is a hack . Fix the real problem ! */
2000-05-05 10:36:00 +00:00
# ifndef PHP_MAX_SALT_LEN
# define PHP_MAX_SALT_LEN 2
# undef PHP_STD_DES_CRYPT
# define PHP_STD_DES_CRYPT 1
1999-04-22 00:25:57 +00:00
# endif
2014-12-13 22:06:14 +00:00
# define PHP_CRYPT_RAND php_rand()
2001-02-22 00:24:19 +00:00
2015-01-09 16:18:33 +00:00
/* Used to check DES salts to ensure that they contain only valid characters */
# define IS_VALID_SALT_CHARACTER(c) (((c) >= '.' && (c) <= '9') || ((c) >= 'A' && (c) <= 'Z') || ((c) >= 'a' && (c) <= 'z'))
# define DES_INVALID_SALT_ERROR "Supplied salt is not valid for DES. Possible bug in provided salt format."
2007-11-05 12:44:52 +00:00
PHP_MINIT_FUNCTION ( crypt ) /* {{{ */
1999-04-22 00:25:57 +00:00
{
2014-08-25 17:24:55 +00:00
REGISTER_LONG_CONSTANT ( " CRYPT_SALT_LENGTH " , PHP_MAX_SALT_LEN , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " CRYPT_STD_DES " , PHP_STD_DES_CRYPT , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " CRYPT_EXT_DES " , PHP_EXT_DES_CRYPT , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " CRYPT_MD5 " , PHP_MD5_CRYPT , CONST_CS | CONST_PERSISTENT ) ;
REGISTER_LONG_CONSTANT ( " CRYPT_BLOWFISH " , PHP_BLOWFISH_CRYPT , CONST_CS | CONST_PERSISTENT ) ;
2009-12-09 01:43:23 +00:00
2010-03-30 10:10:20 +00:00
# ifdef PHP_SHA256_CRYPT
2014-08-25 17:24:55 +00:00
REGISTER_LONG_CONSTANT ( " CRYPT_SHA256 " , PHP_SHA256_CRYPT , CONST_CS | CONST_PERSISTENT ) ;
2010-03-30 10:10:20 +00:00
# endif
# ifdef PHP_SHA512_CRYPT
2014-08-25 17:24:55 +00:00
REGISTER_LONG_CONSTANT ( " CRYPT_SHA512 " , PHP_SHA512_CRYPT , CONST_CS | CONST_PERSISTENT ) ;
2010-03-30 10:10:20 +00:00
# endif
2000-11-03 00:45:24 +00:00
2010-04-22 20:54:35 +00:00
# if PHP_USE_PHP_CRYPT_R
2008-07-28 11:50:35 +00:00
php_init_crypt_r ( ) ;
# endif
return SUCCESS ;
}
2008-08-19 15:14:46 +00:00
/* }}} */
2008-07-28 11:50:35 +00:00
2008-08-19 15:14:46 +00:00
PHP_MSHUTDOWN_FUNCTION ( crypt ) /* {{{ */
2008-07-28 11:50:35 +00:00
{
2010-04-22 20:54:35 +00:00
# if PHP_USE_PHP_CRYPT_R
2008-07-28 11:50:35 +00:00
php_shutdown_crypt_r ( ) ;
2008-08-19 15:14:46 +00:00
# endif
2008-07-28 11:50:35 +00:00
2001-05-06 16:54:27 +00:00
return SUCCESS ;
}
2007-11-05 12:44:52 +00:00
/* }}} */
2000-11-03 00:45:24 +00:00
1999-04-22 00:25:57 +00:00
static unsigned char itoa64 [ ] = " ./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz " ;
2014-08-25 17:24:55 +00:00
static void php_to64 ( char * s , zend_long v , int n ) /* { { { */
2001-09-16 20:49:57 +00:00
{
1999-04-22 00:25:57 +00:00
while ( - - n > = 0 ) {
2007-11-05 12:44:52 +00:00
* s + + = itoa64 [ v & 0x3f ] ;
1999-04-22 00:25:57 +00:00
v > > = 6 ;
2007-11-05 12:44:52 +00:00
}
}
/* }}} */
1999-04-22 00:25:57 +00:00
2014-02-25 04:46:51 +00:00
PHPAPI zend_string * php_crypt ( const char * password , const int pass_len , const char * salt , int salt_len )
1999-04-22 00:25:57 +00:00
{
2010-02-21 18:11:11 +00:00
char * crypt_res ;
2014-02-25 04:46:51 +00:00
zend_string * result ;
2015-01-03 09:22:58 +00:00
/* Windows (win32/crypt) has a stripped down version of libxcrypt and
2008-07-28 11:50:35 +00:00
a CryptoApi md5_crypt implementation */
# if PHP_USE_PHP_CRYPT_R
2006-11-30 15:59:53 +00:00
{
2008-07-28 11:50:35 +00:00
struct php_crypt_extended_data buffer ;
if ( salt [ 0 ] = = ' $ ' & & salt [ 1 ] = = ' 1 ' & & salt [ 2 ] = = ' $ ' ) {
2012-06-28 18:44:04 +00:00
char output [ MD5_HASH_MAX_LEN ] , * out ;
out = php_md5_crypt_r ( password , salt , output ) ;
if ( out ) {
2014-08-25 17:24:55 +00:00
return zend_string_init ( out , strlen ( out ) , 0 ) ;
2012-06-28 18:44:04 +00:00
}
2014-02-25 04:46:51 +00:00
return NULL ;
2009-12-09 00:20:14 +00:00
} else if ( salt [ 0 ] = = ' $ ' & & salt [ 1 ] = = ' 6 ' & & salt [ 2 ] = = ' $ ' ) {
char * output ;
2012-06-29 15:32:25 +00:00
output = emalloc ( PHP_MAX_SALT_LEN ) ;
2009-12-09 00:20:14 +00:00
2012-06-29 15:32:25 +00:00
crypt_res = php_sha512_crypt_r ( password , salt , output , PHP_MAX_SALT_LEN ) ;
2010-02-21 18:11:11 +00:00
if ( ! crypt_res ) {
2012-06-29 15:32:25 +00:00
memset ( output , 0 , PHP_MAX_SALT_LEN ) ;
2012-06-28 18:44:04 +00:00
efree ( output ) ;
2014-02-25 04:46:51 +00:00
return NULL ;
2010-02-21 18:11:11 +00:00
} else {
2014-08-25 17:24:55 +00:00
result = zend_string_init ( output , strlen ( output ) , 0 ) ;
2012-06-29 15:32:25 +00:00
memset ( output , 0 , PHP_MAX_SALT_LEN ) ;
efree ( output ) ;
2014-02-25 04:46:51 +00:00
return result ;
2010-02-21 18:11:11 +00:00
}
2009-12-09 00:20:14 +00:00
} else if ( salt [ 0 ] = = ' $ ' & & salt [ 1 ] = = ' 5 ' & & salt [ 2 ] = = ' $ ' ) {
char * output ;
2012-06-29 15:32:25 +00:00
output = emalloc ( PHP_MAX_SALT_LEN ) ;
2009-12-09 00:20:14 +00:00
2012-06-29 15:32:25 +00:00
crypt_res = php_sha256_crypt_r ( password , salt , output , PHP_MAX_SALT_LEN ) ;
2010-02-21 18:11:11 +00:00
if ( ! crypt_res ) {
2012-06-29 15:32:25 +00:00
memset ( output , 0 , PHP_MAX_SALT_LEN ) ;
2012-06-28 18:44:04 +00:00
efree ( output ) ;
2014-02-25 04:46:51 +00:00
return NULL ;
2010-02-21 18:11:11 +00:00
} else {
2014-08-25 17:24:55 +00:00
result = zend_string_init ( output , strlen ( output ) , 0 ) ;
2012-06-29 15:32:25 +00:00
memset ( output , 0 , PHP_MAX_SALT_LEN ) ;
efree ( output ) ;
2014-02-25 04:46:51 +00:00
return result ;
2010-02-21 18:11:11 +00:00
}
2009-12-09 00:20:14 +00:00
} else if (
2008-07-28 11:50:35 +00:00
salt [ 0 ] = = ' $ ' & &
salt [ 1 ] = = ' 2 ' & &
2015-01-09 16:18:33 +00:00
salt [ 3 ] = = ' $ ' ) {
2008-07-28 11:50:35 +00:00
char output [ PHP_MAX_SALT_LEN + 1 ] ;
memset ( output , 0 , PHP_MAX_SALT_LEN + 1 ) ;
2012-06-28 18:44:04 +00:00
crypt_res = php_crypt_blowfish_rn ( password , salt , output , sizeof ( output ) ) ;
2010-02-21 18:11:11 +00:00
if ( ! crypt_res ) {
2014-09-18 23:46:14 +00:00
ZEND_SECURE_ZERO ( output , PHP_MAX_SALT_LEN + 1 ) ;
2014-02-25 04:46:51 +00:00
return NULL ;
2010-02-21 18:11:11 +00:00
} else {
2014-08-25 17:24:55 +00:00
result = zend_string_init ( output , strlen ( output ) , 0 ) ;
2014-09-18 23:46:14 +00:00
ZEND_SECURE_ZERO ( output , PHP_MAX_SALT_LEN + 1 ) ;
2014-02-25 04:46:51 +00:00
return result ;
2010-02-21 18:11:11 +00:00
}
2015-01-13 16:49:09 +00:00
} else if ( salt [ 0 ] = = ' * ' & & ( salt [ 1 ] = = ' 0 ' | | salt [ 1 ] = = ' 1 ' ) ) {
return NULL ;
2008-07-28 11:50:35 +00:00
} else {
2015-01-09 16:23:06 +00:00
/* DES Fallback */
/* Only check the salt if it's not EXT_DES */
if ( salt [ 0 ] ! = ' _ ' ) {
/* DES style hashes */
if ( ! IS_VALID_SALT_CHARACTER ( salt [ 0 ] ) | | ! IS_VALID_SALT_CHARACTER ( salt [ 1 ] ) ) {
php_error_docref ( NULL , E_DEPRECATED , DES_INVALID_SALT_ERROR ) ;
}
}
2015-01-09 16:18:33 +00:00
2008-07-28 11:50:35 +00:00
memset ( & buffer , 0 , sizeof ( buffer ) ) ;
_crypt_extended_init_r ( ) ;
2010-02-21 18:11:11 +00:00
2012-06-28 18:44:04 +00:00
crypt_res = _crypt_extended_r ( password , salt , & buffer ) ;
2014-10-07 11:27:57 +00:00
if ( ! crypt_res | | ( salt [ 0 ] = = ' * ' & & salt [ 1 ] = = ' 0 ' ) ) {
2014-02-25 04:46:51 +00:00
return NULL ;
2010-02-21 18:11:11 +00:00
} else {
2014-08-25 17:24:55 +00:00
result = zend_string_init ( crypt_res , strlen ( crypt_res ) , 0 ) ;
2014-02-25 04:46:51 +00:00
return result ;
2010-02-21 18:11:11 +00:00
}
2008-07-28 11:50:35 +00:00
}
}
# else
# if defined(HAVE_CRYPT_R) && (defined(_REENTRANT) || defined(_THREAD_SAFE))
{
# if defined(CRYPT_R_STRUCT_CRYPT_DATA)
2006-11-30 15:59:53 +00:00
struct crypt_data buffer ;
memset ( & buffer , 0 , sizeof ( buffer ) ) ;
2008-07-28 11:50:35 +00:00
# elif defined(CRYPT_R_CRYPTD)
2006-12-12 07:38:04 +00:00
CRYPTD buffer ;
2008-07-28 11:50:35 +00:00
# else
# error Data struct used by crypt_r() is unknown. Please report.
# endif
2015-01-09 16:23:06 +00:00
if ( salt [ 0 ] ! = ' $ ' & & salt [ 0 ] ! = ' _ ' & & ( ! IS_VALID_SALT_CHARACTER ( salt [ 0 ] ) | | ! IS_VALID_SALT_CHARACTER ( salt [ 1 ] ) ) ) {
/* error consistently about invalid DES fallbacks */
php_error_docref ( NULL , E_DEPRECATED , DES_INVALID_SALT_ERROR ) ;
}
2012-06-28 18:44:04 +00:00
crypt_res = crypt_r ( password , salt , & buffer ) ;
2014-10-07 12:12:38 +00:00
if ( ! crypt_res | | ( salt [ 0 ] = = ' * ' & & salt [ 1 ] = = ' 0 ' ) ) {
2014-12-01 05:41:04 +00:00
return NULL ;
2010-02-21 18:11:11 +00:00
} else {
2014-08-25 17:24:55 +00:00
result = zend_string_init ( crypt_res , strlen ( crypt_res ) , 0 ) ;
2014-02-25 04:46:51 +00:00
return result ;
2010-02-21 18:11:11 +00:00
}
2006-11-30 15:59:53 +00:00
}
2008-07-28 11:50:35 +00:00
# endif
2006-11-30 15:59:53 +00:00
# endif
1999-04-22 00:25:57 +00:00
}
2000-05-17 19:40:10 +00:00
/* }}} */
2012-06-28 18:44:04 +00:00
/* {{{ proto string crypt(string str [, string salt])
Hash a string */
PHP_FUNCTION ( crypt )
{
char salt [ PHP_MAX_SALT_LEN + 1 ] ;
2014-02-25 04:46:51 +00:00
char * str , * salt_in = NULL ;
2014-08-27 13:31:48 +00:00
size_t str_len , salt_in_len = 0 ;
2014-02-25 04:46:51 +00:00
zend_string * result ;
2012-06-28 18:44:04 +00:00
2014-07-15 11:50:42 +00:00
salt [ 0 ] = salt [ PHP_MAX_SALT_LEN ] = ' \0 ' ;
2012-06-28 18:44:04 +00:00
/* This will produce suitable results if people depend on DES-encryption
* available ( passing always 2 - character salt ) . At least for glibc6 .1 */
memset ( & salt [ 1 ] , ' $ ' , PHP_MAX_SALT_LEN - 1 ) ;
2014-12-13 22:06:14 +00:00
if ( zend_parse_parameters ( ZEND_NUM_ARGS ( ) , " s|s " , & str , & str_len , & salt_in , & salt_in_len ) = = FAILURE ) {
2012-06-28 18:44:04 +00:00
return ;
}
if ( salt_in ) {
memcpy ( salt , salt_in , MIN ( PHP_MAX_SALT_LEN , salt_in_len ) ) ;
2013-10-29 09:53:45 +00:00
} else {
2014-12-13 22:06:14 +00:00
php_error_docref ( NULL , E_NOTICE , " No salt parameter was specified. You must use a randomly generated salt and a strong hash function to produce a secure hash. " ) ;
2012-06-28 18:44:04 +00:00
}
/* The automatic salt generation covers standard DES, md5-crypt and Blowfish (simple) */
if ( ! * salt ) {
# if PHP_MD5_CRYPT
strncpy ( salt , " $1$ " , PHP_MAX_SALT_LEN ) ;
php_to64 ( & salt [ 3 ] , PHP_CRYPT_RAND , 4 ) ;
php_to64 ( & salt [ 7 ] , PHP_CRYPT_RAND , 4 ) ;
strncpy ( & salt [ 11 ] , " $ " , PHP_MAX_SALT_LEN - 11 ) ;
# elif PHP_STD_DES_CRYPT
php_to64 ( & salt [ 0 ] , PHP_CRYPT_RAND , 2 ) ;
salt [ 2 ] = ' \0 ' ;
# endif
salt_in_len = strlen ( salt ) ;
} else {
salt_in_len = MIN ( PHP_MAX_SALT_LEN , salt_in_len ) ;
}
salt [ salt_in_len ] = ' \0 ' ;
2014-10-22 14:15:55 +00:00
if ( ( result = php_crypt ( str , ( int ) str_len , salt , ( int ) salt_in_len ) ) = = NULL ) {
2012-06-28 18:44:04 +00:00
if ( salt [ 0 ] = = ' * ' & & salt [ 1 ] = = ' 0 ' ) {
2014-02-13 13:54:23 +00:00
RETURN_STRING ( " *1 " ) ;
2012-06-28 18:44:04 +00:00
} else {
2014-02-13 13:54:23 +00:00
RETURN_STRING ( " *0 " ) ;
2012-06-28 18:44:04 +00:00
}
}
2014-02-25 04:46:51 +00:00
RETURN_STR ( result ) ;
2012-06-28 18:44:04 +00:00
}
/* }}} */
2000-05-27 19:27:20 +00:00
# endif
1999-04-22 00:25:57 +00:00
/*
* Local variables :
* tab - width : 4
* c - basic - offset : 4
* End :
2001-09-09 13:29:31 +00:00
* vim600 : sw = 4 ts = 4 fdm = marker
* vim < 600 : sw = 4 ts = 4
1999-04-22 00:25:57 +00:00
*/