File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / standard / crypt.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Sun Jun 15 20:03:57 2014 UTC (10 years, 1 month ago) by misho
Branches: php, MAIN
CVS tags: v5_4_29, HEAD
php 5.4.29

    1: /*
    2:    +----------------------------------------------------------------------+
    3:    | PHP Version 5                                                        |
    4:    +----------------------------------------------------------------------+
    5:    | Copyright (c) 1997-2014 The PHP Group                                |
    6:    +----------------------------------------------------------------------+
    7:    | This source file is subject to version 3.01 of the PHP license,      |
    8:    | that is bundled with this package in the file LICENSE, and is        |
    9:    | available through the world-wide-web at the following url:           |
   10:    | http://www.php.net/license/3_01.txt                                  |
   11:    | If you did not receive a copy of the PHP license and are unable to   |
   12:    | obtain it through the world-wide-web, please send a note to          |
   13:    | license@php.net so we can mail you a copy immediately.               |
   14:    +----------------------------------------------------------------------+
   15:    | Authors: Stig Bakken <ssb@php.net>                                   |
   16:    |          Zeev Suraski <zeev@zend.com>                                |
   17:    |          Rasmus Lerdorf <rasmus@php.net>                             |
   18:    |          Pierre Joye <pierre@php.net>                                |
   19:    +----------------------------------------------------------------------+
   20: */
   21: 
   22: /* $Id: crypt.c,v 1.1.1.4 2014/06/15 20:03:57 misho Exp $ */
   23: 
   24: #include <stdlib.h>
   25: 
   26: #include "php.h"
   27: #if HAVE_CRYPT
   28: 
   29: #if HAVE_UNISTD_H
   30: #include <unistd.h>
   31: #endif
   32: #if PHP_USE_PHP_CRYPT_R
   33: # include "php_crypt_r.h"
   34: # include "crypt_freesec.h"
   35: #else
   36: # if HAVE_CRYPT_H
   37: #  if defined(CRYPT_R_GNU_SOURCE) && !defined(_GNU_SOURCE)
   38: #   define _GNU_SOURCE
   39: #  endif
   40: #  include <crypt.h>
   41: # endif
   42: #endif
   43: #if TM_IN_SYS_TIME
   44: #include <sys/time.h>
   45: #else
   46: #include <time.h>
   47: #endif
   48: #if HAVE_STRING_H
   49: #include <string.h>
   50: #else
   51: #include <strings.h>
   52: #endif
   53: 
   54: #ifdef PHP_WIN32
   55: #include <process.h>
   56: #endif
   57: 
   58: #include "php_lcg.h"
   59: #include "php_crypt.h"
   60: #include "php_rand.h"
   61: 
   62: /* The capabilities of the crypt() function is determined by the test programs
   63:  * run by configure from aclocal.m4.  They will set PHP_STD_DES_CRYPT,
   64:  * PHP_EXT_DES_CRYPT, PHP_MD5_CRYPT and PHP_BLOWFISH_CRYPT as appropriate
   65:  * for the target platform. */
   66: 
   67: #if PHP_STD_DES_CRYPT
   68: #define PHP_MAX_SALT_LEN 2
   69: #endif
   70: 
   71: #if PHP_EXT_DES_CRYPT
   72: #undef PHP_MAX_SALT_LEN
   73: #define PHP_MAX_SALT_LEN 9
   74: #endif
   75: 
   76: #if PHP_MD5_CRYPT
   77: #undef PHP_MAX_SALT_LEN
   78: #define PHP_MAX_SALT_LEN 12
   79: #endif
   80: 
   81: #if PHP_BLOWFISH_CRYPT
   82: #undef PHP_MAX_SALT_LEN
   83: #define PHP_MAX_SALT_LEN 60
   84: #endif
   85: 
   86: #if PHP_SHA512_CRYPT
   87: #undef PHP_MAX_SALT_LEN
   88: #define PHP_MAX_SALT_LEN 123
   89: #endif
   90: 
   91: 
   92: /* If the configure-time checks fail, we provide DES.
   93:  * XXX: This is a hack. Fix the real problem! */
   94: 
   95: #ifndef PHP_MAX_SALT_LEN
   96: #define PHP_MAX_SALT_LEN 2
   97: #undef PHP_STD_DES_CRYPT
   98: #define PHP_STD_DES_CRYPT 1
   99: #endif
  100: 
  101: #define PHP_CRYPT_RAND php_rand(TSRMLS_C)
  102: 
  103: PHP_MINIT_FUNCTION(crypt) /* {{{ */
  104: {
  105: 	REGISTER_LONG_CONSTANT("CRYPT_SALT_LENGTH", PHP_MAX_SALT_LEN, CONST_CS | CONST_PERSISTENT);
  106: 	REGISTER_LONG_CONSTANT("CRYPT_STD_DES", PHP_STD_DES_CRYPT, CONST_CS | CONST_PERSISTENT);
  107: 	REGISTER_LONG_CONSTANT("CRYPT_EXT_DES", PHP_EXT_DES_CRYPT, CONST_CS | CONST_PERSISTENT);
  108: 	REGISTER_LONG_CONSTANT("CRYPT_MD5", PHP_MD5_CRYPT, CONST_CS | CONST_PERSISTENT);
  109: 	REGISTER_LONG_CONSTANT("CRYPT_BLOWFISH", PHP_BLOWFISH_CRYPT, CONST_CS | CONST_PERSISTENT);
  110: 
  111: #ifdef PHP_SHA256_CRYPT
  112:    REGISTER_LONG_CONSTANT("CRYPT_SHA256", PHP_SHA256_CRYPT, CONST_CS | CONST_PERSISTENT);
  113: #endif
  114: 
  115: #ifdef PHP_SHA512_CRYPT
  116:    REGISTER_LONG_CONSTANT("CRYPT_SHA512", PHP_SHA512_CRYPT, CONST_CS | CONST_PERSISTENT);
  117: #endif
  118: 
  119: #if PHP_USE_PHP_CRYPT_R
  120: 	php_init_crypt_r();
  121: #endif
  122: 
  123: 	return SUCCESS;
  124: }
  125: /* }}} */
  126: 
  127: PHP_MSHUTDOWN_FUNCTION(crypt) /* {{{ */
  128: {
  129: #if PHP_USE_PHP_CRYPT_R
  130: 	php_shutdown_crypt_r();
  131: #endif
  132: 
  133: 	return SUCCESS;
  134: }
  135: /* }}} */
  136: 
  137: static unsigned char itoa64[] = "./0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
  138: 
  139: static void php_to64(char *s, long v, int n) /* {{{ */
  140: {
  141: 	while (--n >= 0) {
  142: 		*s++ = itoa64[v&0x3f];
  143: 		v >>= 6;
  144: 	}
  145: }
  146: /* }}} */
  147: 
  148: /* {{{ proto string crypt(string str [, string salt])
  149:    Hash a string */
  150: PHP_FUNCTION(crypt)
  151: {
  152: 	char salt[PHP_MAX_SALT_LEN + 1];
  153: 	char *str, *salt_in = NULL;
  154: 	int str_len, salt_in_len = 0;
  155: 	char *crypt_res;
  156: 	salt[0] = salt[PHP_MAX_SALT_LEN] = '\0';
  157: 
  158: 	/* This will produce suitable results if people depend on DES-encryption
  159: 	 * available (passing always 2-character salt). At least for glibc6.1 */
  160: 	memset(&salt[1], '$', PHP_MAX_SALT_LEN - 1);
  161: 
  162: 	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|s", &str, &str_len, &salt_in, &salt_in_len) == FAILURE) {
  163: 		return;
  164: 	}
  165: 
  166: 	if (salt_in) {
  167: 		memcpy(salt, salt_in, MIN(PHP_MAX_SALT_LEN, salt_in_len));
  168: 	}
  169: 
  170: 	/* The automatic salt generation covers standard DES, md5-crypt and Blowfish (simple) */
  171: 	if (!*salt) {
  172: #if PHP_MD5_CRYPT
  173: 		strncpy(salt, "$1$", PHP_MAX_SALT_LEN);
  174: 		php_to64(&salt[3], PHP_CRYPT_RAND, 4);
  175: 		php_to64(&salt[7], PHP_CRYPT_RAND, 4);
  176: 		strncpy(&salt[11], "$", PHP_MAX_SALT_LEN - 11);
  177: #elif PHP_STD_DES_CRYPT
  178: 		php_to64(&salt[0], PHP_CRYPT_RAND, 2);
  179: 		salt[2] = '\0';
  180: #endif
  181: 		salt_in_len = strlen(salt);
  182: 	} else {
  183: 		salt_in_len = MIN(PHP_MAX_SALT_LEN, salt_in_len);
  184: 	}
  185: 
  186: /* Windows (win32/crypt) has a stripped down version of libxcrypt and 
  187: 	a CryptoApi md5_crypt implementation */
  188: #if PHP_USE_PHP_CRYPT_R
  189: 	{
  190: 		struct php_crypt_extended_data buffer;
  191: 
  192: 		if (salt[0]=='$' && salt[1]=='1' && salt[2]=='$') {
  193: 			char output[MD5_HASH_MAX_LEN];
  194: 
  195: 			RETURN_STRING(php_md5_crypt_r(str, salt, output), 1);
  196: 		} else if (salt[0]=='$' && salt[1]=='6' && salt[2]=='$') {
  197: 			const char sha512_salt_prefix[] = "$6$";
  198: 			const char sha512_rounds_prefix[] = "rounds=";
  199: 			char *output;
  200: 			int needed = (sizeof(sha512_salt_prefix) - 1
  201: 						+ sizeof(sha512_rounds_prefix) + 9 + 1
  202: 						+ salt_in_len + 1 + 86 + 1);
  203: 			output = emalloc(needed);
  204: 			salt[salt_in_len] = '\0';
  205: 
  206: 			crypt_res = php_sha512_crypt_r(str, salt, output, needed);
  207: 			if (!crypt_res) {
  208: 				if (salt[0]=='*' && salt[1]=='0') {
  209: 					RETVAL_STRING("*1", 1);
  210: 				} else {
  211: 					RETVAL_STRING("*0", 1);
  212: 				}
  213: 			} else {
  214: 				RETVAL_STRING(output, 1);
  215: 			}
  216: 
  217: 			memset(output, 0, needed);
  218: 			efree(output);
  219: 		} else if (salt[0]=='$' && salt[1]=='5' && salt[2]=='$') {
  220: 			const char sha256_salt_prefix[] = "$5$";
  221: 			const char sha256_rounds_prefix[] = "rounds=";
  222: 			char *output;
  223: 			int needed = (sizeof(sha256_salt_prefix) - 1
  224: 						+ sizeof(sha256_rounds_prefix) + 9 + 1
  225: 						+ salt_in_len + 1 + 43 + 1);
  226: 			output = emalloc(needed);
  227: 			salt[salt_in_len] = '\0';
  228: 
  229: 			crypt_res = php_sha256_crypt_r(str, salt, output, needed);
  230: 			if (!crypt_res) {
  231: 				if (salt[0]=='*' && salt[1]=='0') {
  232: 					RETVAL_STRING("*1", 1);
  233: 				} else {
  234: 					RETVAL_STRING("*0", 1);
  235: 				}
  236: 			} else {
  237: 				RETVAL_STRING(output, 1);
  238: 			}
  239: 
  240: 			memset(output, 0, needed);
  241: 			efree(output);
  242: 		} else if (
  243: 				salt[0] == '$' &&
  244: 				salt[1] == '2' &&
  245: 				salt[2] >= 'a' && salt[2] <= 'z' &&
  246: 				salt[3] == '$' &&
  247: 				salt[4] >= '0' && salt[4] <= '3' &&
  248: 				salt[5] >= '0' && salt[5] <= '9' &&
  249: 				salt[6] == '$') {
  250: 			char output[PHP_MAX_SALT_LEN + 1];
  251: 
  252: 			memset(output, 0, PHP_MAX_SALT_LEN + 1);
  253: 
  254: 			crypt_res = php_crypt_blowfish_rn(str, salt, output, sizeof(output));
  255: 			if (!crypt_res) {
  256: 				if (salt[0]=='*' && salt[1]=='0') {
  257: 					RETVAL_STRING("*1", 1);
  258: 				} else {
  259: 					RETVAL_STRING("*0", 1);
  260: 				}
  261: 			} else {
  262: 				RETVAL_STRING(output, 1);
  263: 			}
  264: 
  265: 			memset(output, 0, PHP_MAX_SALT_LEN + 1);
  266: 		} else {
  267: 			memset(&buffer, 0, sizeof(buffer));
  268: 			_crypt_extended_init_r();
  269: 
  270: 			crypt_res = _crypt_extended_r(str, salt, &buffer);
  271: 			if (!crypt_res) {
  272: 				if (salt[0]=='*' && salt[1]=='0') {
  273: 					RETURN_STRING("*1", 1);
  274: 				} else {
  275: 					RETURN_STRING("*0", 1);
  276: 				}
  277: 			} else {
  278: 				RETURN_STRING(crypt_res, 1);
  279: 			}
  280: 		}
  281: 	}
  282: #else
  283: 
  284: # if defined(HAVE_CRYPT_R) && (defined(_REENTRANT) || defined(_THREAD_SAFE))
  285: 	{
  286: #  if defined(CRYPT_R_STRUCT_CRYPT_DATA)
  287: 		struct crypt_data buffer;
  288: 		memset(&buffer, 0, sizeof(buffer));
  289: #  elif defined(CRYPT_R_CRYPTD)
  290: 		CRYPTD buffer;
  291: #  else
  292: #    error Data struct used by crypt_r() is unknown. Please report.
  293: #  endif
  294: 		crypt_res = crypt_r(str, salt, &buffer);
  295: 		if (!crypt_res) {
  296: 				if (salt[0]=='*' && salt[1]=='0') {
  297: 					RETURN_STRING("*1", 1);
  298: 				} else {
  299: 					RETURN_STRING("*0", 1);
  300: 				}
  301: 		} else {
  302: 			RETURN_STRING(crypt_res, 1);
  303: 		}
  304: 	}
  305: # endif
  306: #endif
  307: }
  308: /* }}} */
  309: #endif
  310: 
  311: /*
  312:  * Local variables:
  313:  * tab-width: 4
  314:  * c-basic-offset: 4
  315:  * End:
  316:  * vim600: sw=4 ts=4 fdm=marker
  317:  * vim<600: sw=4 ts=4
  318:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>