stas                                     Fri, 15 Jan 2010 22:13:55 +0000

Revision: http://svn.php.net/viewvc?view=revision&revision=293599

Log:
add filters to mcrypt

Changed paths:
    U   php/php-src/trunk/ext/mcrypt/config.m4
    U   php/php-src/trunk/ext/mcrypt/config.w32
    U   php/php-src/trunk/ext/mcrypt/mcrypt.c
    A   php/php-src/trunk/ext/mcrypt/mcrypt_filter.c
    A   php/php-src/trunk/ext/mcrypt/php_mcrypt_filter.h
    A   php/php-src/trunk/ext/mcrypt/tests/mcrypt_filters.phpt

Modified: php/php-src/trunk/ext/mcrypt/config.m4
===================================================================
--- php/php-src/trunk/ext/mcrypt/config.m4	2010-01-15 21:35:38 UTC (rev 293598)
+++ php/php-src/trunk/ext/mcrypt/config.m4	2010-01-15 22:13:55 UTC (rev 293599)
@@ -55,5 +55,5 @@
   PHP_ADD_INCLUDE($MCRYPT_DIR/include)

   PHP_SUBST(MCRYPT_SHARED_LIBADD)
-  PHP_NEW_EXTENSION(mcrypt, mcrypt.c, $ext_shared)
+  PHP_NEW_EXTENSION(mcrypt, mcrypt.c mcrypt_filter.c, $ext_shared)
 fi

Modified: php/php-src/trunk/ext/mcrypt/config.w32
===================================================================
--- php/php-src/trunk/ext/mcrypt/config.w32	2010-01-15 21:35:38 UTC (rev 293598)
+++ php/php-src/trunk/ext/mcrypt/config.w32	2010-01-15 22:13:55 UTC (rev 293599)
@@ -8,12 +8,11 @@
 	if (CHECK_HEADER_ADD_INCLUDE('mcrypt.h', 'CFLAGS_MCRYPT') &&
 			CHECK_LIB('libmcrypt_a.lib;libmcrypt.lib', 'mcrypt') &&
 			CHECK_LIB('Advapi32.lib', 'mcrypt')
-		) {
-		EXTENSION('mcrypt', 'mcrypt.c', false);
+			) {
+		EXTENSION('mcrypt', 'mcrypt.c mcrypt_filter.c', false);
 		AC_DEFINE('HAVE_LIBMCRYPT', 1);
 		AC_DEFINE('HAVE_LIBMCRYPT24', 1);
 	} else {
 		WARNING("mcrypt not enabled; libraries and headers not found");
 	}
 }
-

Modified: php/php-src/trunk/ext/mcrypt/mcrypt.c
===================================================================
--- php/php-src/trunk/ext/mcrypt/mcrypt.c	2010-01-15 21:35:38 UTC (rev 293598)
+++ php/php-src/trunk/ext/mcrypt/mcrypt.c	2010-01-15 22:13:55 UTC (rev 293599)
@@ -41,6 +41,7 @@
 #include "php_globals.h"
 #include "ext/standard/info.h"
 #include "ext/standard/php_rand.h"
+#include "php_mcrypt_filter.h"

 static int le_mcrypt;

@@ -414,12 +415,19 @@
 	MCRYPT_ENTRY2_2_4(MODE_OFB, "ofb");
 	MCRYPT_ENTRY2_2_4(MODE_STREAM, "stream");
 	REGISTER_INI_ENTRIES();
+
+	php_stream_filter_register_factory("mcrypt.*", &php_mcrypt_filter_factory TSRMLS_CC);
+	php_stream_filter_register_factory("mdecrypt.*", &php_mcrypt_filter_factory TSRMLS_CC);
+
 	return SUCCESS;
 }
 /* }}} */

 static PHP_MSHUTDOWN_FUNCTION(mcrypt) /* {{{ */
 {
+	php_stream_filter_unregister_factory("mcrypt.*" TSRMLS_CC);
+	php_stream_filter_unregister_factory("mdecrypt.*" TSRMLS_CC);
+
 	UNREGISTER_INI_ENTRIES();
 	return SUCCESS;
 }
@@ -461,6 +469,7 @@

 	php_info_print_table_start();
 	php_info_print_table_header(2, "mcrypt support", "enabled");
+	php_info_print_table_header(2, "mcrypt_filter support", "enabled");
 	php_info_print_table_row(2, "Version", LIBMCRYPT_VERSION);
 	php_info_print_table_row(2, "Api No", mcrypt_api_no);
 	php_info_print_table_row(2, "Supported ciphers", tmp1.c);

Added: php/php-src/trunk/ext/mcrypt/mcrypt_filter.c
===================================================================
--- php/php-src/trunk/ext/mcrypt/mcrypt_filter.c	                        (rev 0)
+++ php/php-src/trunk/ext/mcrypt/mcrypt_filter.c	2010-01-15 22:13:55 UTC (rev 293599)
@@ -0,0 +1,289 @@
+/*
+  +----------------------------------------------------------------------+
+  | PHP Version 6                                                        |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 1997-2010 The PHP Group                                |
+  +----------------------------------------------------------------------+
+  | This source file is subject to version 3.01 of the PHP license,      |
+  | that is bundled with this package in the file LICENSE, and is        |
+  | available through the world-wide-web at the following url:           |
+  | http://www.php.net/license/3_01.txt                                  |
+  | 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          |
+  | lice...@php.net so we can mail you a copy immediately.               |
+  +----------------------------------------------------------------------+
+  | Author: Sara Golemon <poll...@php.net>                               |
+  +----------------------------------------------------------------------+
+
+  $Id$
+*/
+
+#include "php.h"
+
+#include "php_mcrypt_filter.h"
+#include "php_ini.h"
+#include <mcrypt.h>
+
+typedef struct _php_mcrypt_filter_data {
+	MCRYPT module;
+	char encrypt;
+	int blocksize;
+	char *block_buffer;
+	int block_used;
+	char persistent;
+} php_mcrypt_filter_data;
+
+static php_stream_filter_status_t php_mcrypt_filter(
+	php_stream *stream,
+	php_stream_filter *thisfilter,
+	php_stream_bucket_brigade *buckets_in,
+	php_stream_bucket_brigade *buckets_out,
+	size_t *bytes_consumed,
+	int flags TSRMLS_DC)
+{
+	php_mcrypt_filter_data *data;
+	php_stream_bucket *bucket;
+	size_t consumed = 0;
+	php_stream_filter_status_t exit_status = PSFS_FEED_ME;
+
+	if (!thisfilter || !thisfilter->abstract) {
+		/* Should never happen */
+		return PSFS_ERR_FATAL;
+	}
+
+	data = (php_mcrypt_filter_data *)(thisfilter->abstract);
+	while(buckets_in->head) {
+		bucket = buckets_in->head;
+
+		if (bucket->buf_type == IS_UNICODE) {
+			/* inflation not allowed for unicode data */
+			return PSFS_ERR_FATAL;
+		}
+
+		consumed += bucket->buflen;
+
+		if (data->blocksize) {
+			/* Blockmode cipher */
+			char *outchunk;
+			int chunklen = bucket->buflen + data->block_used, n;
+			php_stream_bucket *newbucket;
+
+			outchunk = pemalloc(chunklen, data->persistent);
+			if (data->block_used) {
+				memcpy(outchunk, data->block_buffer, data->block_used);
+			}
+			memcpy(outchunk + data->block_used, bucket->buf.s, bucket->buflen);
+
+			for(n=0; (n + data->blocksize) <= chunklen; n += data->blocksize) {
+
+				if (data->encrypt) {
+					mcrypt_generic(data->module, outchunk + n, data->blocksize);
+				} else {
+					mdecrypt_generic(data->module, outchunk + n, data->blocksize);
+				}
+			}
+			data->block_used = chunklen - n;
+			memcpy(data->block_buffer, outchunk + n, data->block_used);
+
+			newbucket = php_stream_bucket_new(stream, outchunk, n, 1, data->persistent TSRMLS_CC);
+			php_stream_bucket_append(buckets_out, newbucket TSRMLS_CC);
+
+			exit_status = PSFS_PASS_ON;
+
+			php_stream_bucket_unlink(bucket TSRMLS_CC);
+			php_stream_bucket_delref(bucket TSRMLS_CC);
+		} else {
+			/* Stream cipher */
+			php_stream_bucket_make_writeable(bucket TSRMLS_CC);
+			if (data->encrypt) {
+				mcrypt_generic(data->module, bucket->buf.s, bucket->buflen);
+			} else {
+				mdecrypt_generic(data->module, bucket->buf.s, bucket->buflen);
+			}
+			php_stream_bucket_append(buckets_out, bucket TSRMLS_CC);
+
+			exit_status = PSFS_PASS_ON;
+		}
+	}
+
+	if ((flags & PSFS_FLAG_FLUSH_CLOSE) && data->blocksize && data->block_used) {
+		php_stream_bucket *newbucket;
+
+		memset(data->block_buffer + data->block_used, 0, data->blocksize - data->block_used);
+		if (data->encrypt) {
+			mcrypt_generic(data->module, data->block_buffer, data->blocksize);
+		} else {
+			mdecrypt_generic(data->module, data->block_buffer, data->blocksize);
+		}
+
+		newbucket = php_stream_bucket_new(stream, data->block_buffer, data->blocksize, 0, data->persistent TSRMLS_CC);
+		php_stream_bucket_append(buckets_out, newbucket TSRMLS_CC);
+
+		exit_status = PSFS_PASS_ON;
+	}
+
+	if (bytes_consumed) {
+		*bytes_consumed = consumed;
+	}
+
+	return exit_status;
+}
+
+static void php_mcrypt_filter_dtor(php_stream_filter *thisfilter TSRMLS_DC)
+{
+	if (thisfilter && thisfilter->abstract) {
+		php_mcrypt_filter_data *data = (php_mcrypt_filter_data*)thisfilter->abstract;
+
+		if (data->block_buffer) {
+			pefree(data->block_buffer, data->persistent);
+		}
+
+		mcrypt_generic_deinit(data->module);
+		mcrypt_module_close(data->module);
+
+		pefree(data, data->persistent);
+	}
+}
+
+static php_stream_filter_ops php_mcrypt_filter_ops = {
+    php_mcrypt_filter,
+    php_mcrypt_filter_dtor,
+    "mcrypt.*",
+	PSFO_FLAG_ACCEPTS_STRING | PSFO_FLAG_OUTPUTS_STRING
+};
+
+/* {{{ php_mcrypt_filter_create
+ * Instantiate mcrypt filter
+ */
+static php_stream_filter *php_mcrypt_filter_create(const char *filtername, zval *filterparams, int persistent TSRMLS_DC)
+{
+	int encrypt = 1, iv_len, key_len, keyl, result;
+	const char *cipher = filtername + sizeof("mcrypt.") - 1;
+	zval **tmpzval;
+	MCRYPT mcrypt_module;
+	char *iv = NULL, *key = NULL;
+	char *algo_dir = INI_STR("mcrypt.algorithms_dir");
+	char *mode_dir = INI_STR("mcrypt.modes_dir");
+	char *mode = "cbc";
+	php_mcrypt_filter_data *data;
+
+	if (strncasecmp(filtername, "mdecrypt.", sizeof("mdecrypt.") - 1) == 0) {
+		encrypt = 0;
+		cipher += sizeof("de") - 1;
+	} else if (strncasecmp(filtername, "mcrypt.", sizeof("mcrypt.") - 1) != 0) {
+		/* Should never happen */
+		return NULL;
+	}
+
+	if (!filterparams || Z_TYPE_P(filterparams) != IS_ARRAY) {
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Filter parameters for %s must be an array", filtername);
+		return NULL;
+	}
+
+	if (zend_ascii_hash_find(HASH_OF(filterparams), "mode", sizeof("mode"), (void**)&tmpzval) == SUCCESS) {
+		if (Z_TYPE_PP(tmpzval) == IS_STRING) {
+			mode = Z_STRVAL_PP(tmpzval);
+		} else {
+			php_error_docref(NULL TSRMLS_CC, E_WARNING, "mode is not a string, ignoring");
+		}
+	}
+
+	if (zend_ascii_hash_find(HASH_OF(filterparams), "algorithms_dir", sizeof("algorithms_dir"), (void**)&tmpzval) == SUCCESS) {
+		if (Z_TYPE_PP(tmpzval) == IS_STRING) {
+			algo_dir = Z_STRVAL_PP(tmpzval);
+		} else {
+			php_error_docref(NULL TSRMLS_CC, E_WARNING, "algorithms_dir is not a string, ignoring");
+		}
+	}
+
+	if (zend_ascii_hash_find(HASH_OF(filterparams), "modes_dir", sizeof("modes_dir"), (void**)&tmpzval) == SUCCESS) {
+		if (Z_TYPE_PP(tmpzval) == IS_STRING) {
+			mode_dir = Z_STRVAL_PP(tmpzval);
+		} else {
+			php_error_docref(NULL TSRMLS_CC, E_WARNING, "modes_dir is not a string, ignoring");
+		}
+	}
+
+	if (zend_ascii_hash_find(HASH_OF(filterparams), "key", sizeof("key"), (void**)&tmpzval) == SUCCESS &&
+		Z_TYPE_PP(tmpzval) == IS_STRING) {
+		key = Z_STRVAL_PP(tmpzval);
+		key_len = Z_STRLEN_PP(tmpzval);
+	} else {
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "key not specified or is not a string");
+		return NULL;
+	}
+
+	mcrypt_module = mcrypt_module_open(cipher, algo_dir, mode, mode_dir);
+	if (mcrypt_module == MCRYPT_FAILED) {
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not open encryption module");
+		return NULL;
+	}
+	iv_len = mcrypt_enc_get_iv_size(mcrypt_module);
+	keyl = mcrypt_enc_get_key_size(mcrypt_module);
+	if (keyl < key_len) {
+		key_len = keyl;
+	}
+
+	if (zend_ascii_hash_find(HASH_OF(filterparams), "iv", sizeof("iv"), (void**) &tmpzval) == FAILURE ||
+		Z_TYPE_PP(tmpzval) != IS_STRING) {
+		php_error_docref(NULL TSRMLS_CC, E_WARNING, "Filter parameter[iv] not provided or not of type: string");
+		mcrypt_module_close(mcrypt_module);
+		return NULL;
+	}
+
+	iv = emalloc(iv_len + 1);
+	if (iv_len <= Z_STRLEN_PP(tmpzval)) {
+		memcpy(iv, Z_STRVAL_PP(tmpzval), iv_len);
+	} else {
+		memcpy(iv, Z_STRVAL_PP(tmpzval), Z_STRLEN_PP(tmpzval));
+		memset(iv + Z_STRLEN_PP(tmpzval), 0, iv_len - Z_STRLEN_PP(tmpzval));
+	}
+
+	result = mcrypt_generic_init(mcrypt_module, key, key_len, iv);
+	efree(iv);
+	if (result < 0) {
+		switch (result) {
+			case -3:
+				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Key length incorrect");
+				break;
+			case -4:
+				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Memory allocation error");
+				break;
+			case -1:
+			default:
+				php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown error");
+				break;
+		}
+		mcrypt_module_close(mcrypt_module);
+		return NULL;
+	}
+
+	data = pemalloc(sizeof(php_mcrypt_filter_data), persistent);
+	data->module = mcrypt_module;
+	data->encrypt = encrypt;
+	if (mcrypt_enc_is_block_mode(mcrypt_module)) {
+		data->blocksize = mcrypt_enc_get_block_size(mcrypt_module);
+		data->block_buffer = pemalloc(data->blocksize, persistent);
+	} else {
+		data->blocksize = 0;
+		data->block_buffer = NULL;
+	}
+	data->block_used = 0;
+	data->persistent = persistent;
+
+	return php_stream_filter_alloc(&php_mcrypt_filter_ops, data, persistent);
+}
+/* }}} */
+
+php_stream_filter_factory php_mcrypt_filter_factory = {
+	php_mcrypt_filter_create
+};
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */


Property changes on: php/php-src/trunk/ext/mcrypt/mcrypt_filter.c
___________________________________________________________________
Added: svn:keywords
   + Id Rev Revision
Added: svn:eol-style
   + native

Added: php/php-src/trunk/ext/mcrypt/php_mcrypt_filter.h
===================================================================
--- php/php-src/trunk/ext/mcrypt/php_mcrypt_filter.h	                        (rev 0)
+++ php/php-src/trunk/ext/mcrypt/php_mcrypt_filter.h	2010-01-15 22:13:55 UTC (rev 293599)
@@ -0,0 +1,39 @@
+/*
+  +----------------------------------------------------------------------+
+  | PHP Version 6                                                        |
+  +----------------------------------------------------------------------+
+  | Copyright (c) 1997-2010 The PHP Group                                |
+  +----------------------------------------------------------------------+
+  | This source file is subject to version 3.01 of the PHP license,      |
+  | that is bundled with this package in the file LICENSE, and is        |
+  | available through the world-wide-web at the following url:           |
+  | http://www.php.net/license/3_01.txt                                  |
+  | 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          |
+  | lice...@php.net so we can mail you a copy immediately.               |
+  +----------------------------------------------------------------------+
+  | Author: Sara Golemon <poll...@php.net>                               |
+  +----------------------------------------------------------------------+
+
+  $Id$
+*/
+
+#ifndef PHP_MCRYPT_FILTER_H
+#define PHP_MCRYPT_FILTER_H
+
+extern php_stream_filter_factory php_mcrypt_filter_factory;
+
+PHP_MINIT_FUNCTION(mcrypt_filter);
+PHP_MSHUTDOWN_FUNCTION(mcrypt_filter);
+PHP_MINFO_FUNCTION(mcrypt_filter);
+
+#endif	/* PHP_MCRYPT_FILTER_H */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ */


Property changes on: php/php-src/trunk/ext/mcrypt/php_mcrypt_filter.h
___________________________________________________________________
Added: svn:keywords
   + Id Rev Revision
Added: svn:eol-style
   + native

Added: php/php-src/trunk/ext/mcrypt/tests/mcrypt_filters.phpt
===================================================================
--- php/php-src/trunk/ext/mcrypt/tests/mcrypt_filters.phpt	                        (rev 0)
+++ php/php-src/trunk/ext/mcrypt/tests/mcrypt_filters.phpt	2010-01-15 22:13:55 UTC (rev 293599)
@@ -0,0 +1,41 @@
+--TEST--
+mcrypt filters
+--SKIPIF--
+<?php if (!extension_loaded("mcrypt")) print "skip"; ?>
+--FILE--
+<?php
+foreach (stream_get_filters() as $f) {
+	if ($f == "mcrypt.*" || $f == "mdecrypt.*") {
+	   echo "FOUND\n";
+	}
+}
+
+$secretfile = 'secert-file.tmp';
+$passphrase = 'My secret';
+
+$iv = substr(md5('iv'.$passphrase, true), 0, 8);
+$key = substr(md5('pass1'.$passphrase, true) .
+               md5('pass2'.$passphrase, true), 0, 24);
+$opts = array('iv'=>$iv,'key'=>$key);
+
+$fp = fopen($secretfile, 'wb');
+stream_filter_append($fp, 'mcrypt.tripledes', STREAM_FILTER_WRITE, $opts);
+fwrite($fp, b'Secret secret secret data');
+fclose($fp);
+
+echo md5_file($secretfile)."\n";
+
+$fp = fopen($secretfile, 'rb');
+stream_filter_append($fp, 'mdecrypt.tripledes', STREAM_FILTER_READ, $opts);
+$data = stream_get_contents($fp);
+fclose($fp);
+
+echo $data."\n";
+
+...@unlink($secretfile);
+
+--EXPECTF--
+FOUND
+FOUND
+32e14bd3c31f2bd666e4290ebdb166a7
+Secret secret secret data
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to