PHP  
 PHP: Test and Code Coverage Analysis
downloads | QA | documentation | faq | getting help | mailing lists | reporting bugs | php.net sites | links | my php.net 
 

LCOV - code coverage report
Current view: top level - ext/mcrypt - mcrypt_filter.c (source / functions) Hit Total Coverage
Test: PHP Code Coverage Lines: 82 123 66.7 %
Date: 2014-10-22 Functions: 3 3 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :   +----------------------------------------------------------------------+
       3             :   | PHP Version 7                                                        |
       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             :   | Author: Sara Golemon <pollita@php.net>                               |
      16             :   +----------------------------------------------------------------------+
      17             : 
      18             :   $Id$ 
      19             : */
      20             : 
      21             : #include "php.h"
      22             : 
      23             : #include "php_mcrypt_filter.h"
      24             : #include "php_ini.h"
      25             : #include <mcrypt.h>
      26             : 
      27             : typedef struct _php_mcrypt_filter_data {
      28             :         MCRYPT module;
      29             :         char encrypt;
      30             :         int blocksize;
      31             :         char *block_buffer;
      32             :         int block_used;
      33             :         char persistent;
      34             : } php_mcrypt_filter_data;
      35             : 
      36           4 : static php_stream_filter_status_t php_mcrypt_filter(
      37             :         php_stream *stream,
      38             :         php_stream_filter *thisfilter,
      39             :         php_stream_bucket_brigade *buckets_in,
      40             :         php_stream_bucket_brigade *buckets_out,
      41             :         size_t *bytes_consumed,
      42             :         int flags TSRMLS_DC)
      43             : {
      44             :         php_mcrypt_filter_data *data;
      45             :         php_stream_bucket *bucket;
      46           4 :         size_t consumed = 0;
      47           4 :         php_stream_filter_status_t exit_status = PSFS_FEED_ME;
      48             : 
      49           4 :         if (!thisfilter || !Z_PTR(thisfilter->abstract)) {
      50             :                 /* Should never happen */
      51           0 :                 return PSFS_ERR_FATAL;
      52             :         }
      53             : 
      54           4 :         data = (php_mcrypt_filter_data *)(Z_PTR(thisfilter->abstract));
      55          10 :         while(buckets_in->head) {
      56           2 :                 bucket = buckets_in->head;
      57             : 
      58           2 :                 consumed += bucket->buflen;
      59             : 
      60           2 :                 if (data->blocksize) {
      61             :                         /* Blockmode cipher */
      62             :                         char *outchunk;
      63           2 :                         int chunklen = bucket->buflen + data->block_used, n;
      64             :                         php_stream_bucket *newbucket;
      65             : 
      66           4 :                         outchunk = pemalloc(chunklen, data->persistent);
      67           2 :                         if (data->block_used) {
      68           0 :                                 memcpy(outchunk, data->block_buffer, data->block_used);
      69             :                         }
      70           2 :                         memcpy(outchunk + data->block_used, bucket->buf, bucket->buflen);
      71             : 
      72           9 :                         for(n=0; (n + data->blocksize) <= chunklen; n += data->blocksize) {
      73             : 
      74           7 :                                 if (data->encrypt) {
      75           3 :                                         mcrypt_generic(data->module, outchunk + n, data->blocksize);
      76             :                                 } else {
      77           4 :                                         mdecrypt_generic(data->module, outchunk + n, data->blocksize);
      78             :                                 }
      79             :                         }
      80           2 :                         data->block_used = chunklen - n;
      81           2 :                         memcpy(data->block_buffer, outchunk + n, data->block_used);
      82             : 
      83           2 :                         newbucket = php_stream_bucket_new(stream, outchunk, n, 1, data->persistent TSRMLS_CC);
      84           2 :                         php_stream_bucket_append(buckets_out, newbucket TSRMLS_CC);
      85             : 
      86           2 :                         exit_status = PSFS_PASS_ON;
      87             : 
      88           2 :                         php_stream_bucket_unlink(bucket TSRMLS_CC);
      89           2 :                         php_stream_bucket_delref(bucket TSRMLS_CC);
      90             :                 } else {
      91             :                         /* Stream cipher */
      92           0 :                         php_stream_bucket_make_writeable(bucket TSRMLS_CC);
      93           0 :                         if (data->encrypt) {
      94           0 :                                 mcrypt_generic(data->module, bucket->buf, bucket->buflen);
      95             :                         } else {
      96           0 :                                 mdecrypt_generic(data->module, bucket->buf, bucket->buflen);
      97             :                         }
      98           0 :                         php_stream_bucket_append(buckets_out, bucket TSRMLS_CC);
      99             : 
     100           0 :                         exit_status = PSFS_PASS_ON;
     101             :                 }
     102             :         }
     103             : 
     104           4 :         if ((flags & PSFS_FLAG_FLUSH_CLOSE) && data->blocksize && data->block_used) {
     105             :                 php_stream_bucket *newbucket;
     106             : 
     107           1 :                 memset(data->block_buffer + data->block_used, 0, data->blocksize - data->block_used);
     108           1 :                 if (data->encrypt) {
     109           1 :                         mcrypt_generic(data->module, data->block_buffer, data->blocksize);
     110             :                 } else {
     111           0 :                         mdecrypt_generic(data->module, data->block_buffer, data->blocksize);
     112             :                 }
     113             : 
     114           1 :                 newbucket = php_stream_bucket_new(stream, data->block_buffer, data->blocksize, 0, data->persistent TSRMLS_CC);
     115           1 :                 php_stream_bucket_append(buckets_out, newbucket TSRMLS_CC);
     116             : 
     117           1 :                 exit_status = PSFS_PASS_ON;
     118             :         }
     119             : 
     120           4 :         if (bytes_consumed) {
     121           2 :                 *bytes_consumed = consumed;
     122             :         }
     123             : 
     124           4 :         return exit_status;
     125             : }
     126             : 
     127           2 : static void php_mcrypt_filter_dtor(php_stream_filter *thisfilter TSRMLS_DC)
     128             : {
     129           2 :         if (thisfilter && Z_PTR(thisfilter->abstract)) {
     130           2 :                 php_mcrypt_filter_data *data = (php_mcrypt_filter_data*) Z_PTR(thisfilter->abstract);
     131             : 
     132           2 :                 if (data->block_buffer) {
     133           2 :                         pefree(data->block_buffer, data->persistent);
     134             :                 }
     135             : 
     136           2 :                 mcrypt_generic_deinit(data->module);
     137           2 :                 mcrypt_module_close(data->module);
     138             : 
     139           2 :                 pefree(data, data->persistent);
     140             :         }
     141           2 : }
     142             : 
     143             : static php_stream_filter_ops php_mcrypt_filter_ops = {
     144             :     php_mcrypt_filter,
     145             :     php_mcrypt_filter_dtor,
     146             :     "mcrypt.*"
     147             : };
     148             : 
     149             : /* {{{ php_mcrypt_filter_create
     150             :  * Instantiate mcrypt filter
     151             :  */
     152           2 : static php_stream_filter *php_mcrypt_filter_create(const char *filtername, zval *filterparams, int persistent TSRMLS_DC)
     153             : {
     154           2 :         int encrypt = 1, iv_len, key_len, keyl, result;
     155           2 :         const char *cipher = filtername + sizeof("mcrypt.") - 1;
     156             :         zval *tmpzval;
     157             :         MCRYPT mcrypt_module;
     158           2 :         char *iv = NULL, *key = NULL;
     159           2 :         char *algo_dir = INI_STR("mcrypt.algorithms_dir");
     160           2 :         char *mode_dir = INI_STR("mcrypt.modes_dir");
     161           2 :         char *mode = "cbc";
     162             :         php_mcrypt_filter_data *data;
     163             : 
     164           2 :         if (strncasecmp(filtername, "mdecrypt.", sizeof("mdecrypt.") - 1) == 0) {
     165           1 :                 encrypt = 0;
     166           1 :                 cipher += sizeof("de") - 1;
     167           1 :         } else if (strncasecmp(filtername, "mcrypt.", sizeof("mcrypt.") - 1) != 0) {
     168             :                 /* Should never happen */
     169           0 :                 return NULL;
     170             :         }
     171             : 
     172           4 :         if (!filterparams || Z_TYPE_P(filterparams) != IS_ARRAY) {
     173           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Filter parameters for %s must be an array", filtername);
     174           0 :                 return NULL;
     175             :         }
     176             : 
     177           2 :         if ((tmpzval = zend_hash_str_find(HASH_OF(filterparams), ZEND_STRL("mode")))) {
     178           0 :                 if (Z_TYPE_P(tmpzval) == IS_STRING) {
     179           0 :                         mode = Z_STRVAL_P(tmpzval);
     180             :                 } else {
     181           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "mode is not a string, ignoring");
     182             :                 }
     183             :         }
     184             : 
     185           2 :         if ((tmpzval=zend_hash_str_find(HASH_OF(filterparams), ZEND_STRL("algorithms_dir")))) {
     186           0 :                 if (Z_TYPE_P(tmpzval) == IS_STRING) {
     187           0 :                         algo_dir = Z_STRVAL_P(tmpzval);
     188             :                 } else {
     189           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "algorithms_dir is not a string, ignoring");
     190             :                 }
     191             :         }
     192             : 
     193           2 :         if ((tmpzval=zend_hash_str_find(HASH_OF(filterparams), ZEND_STRL("modes_dir")))) {
     194           0 :                 if (Z_TYPE_P(tmpzval) == IS_STRING) {
     195           0 :                         mode_dir = Z_STRVAL_P(tmpzval);
     196             :                 } else {
     197           0 :                         php_error_docref(NULL TSRMLS_CC, E_WARNING, "modes_dir is not a string, ignoring");
     198             :                 }
     199             :         }
     200             : 
     201           6 :         if ((tmpzval = zend_hash_str_find(HASH_OF(filterparams), ZEND_STRL("key"))) &&
     202             :                 Z_TYPE_P(tmpzval) == IS_STRING) {
     203           2 :                 key = Z_STRVAL_P(tmpzval);
     204           2 :                 key_len = Z_STRLEN_P(tmpzval);
     205             :         } else {
     206           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "key not specified or is not a string");
     207           0 :                 return NULL;
     208             :         }
     209             : 
     210           2 :         mcrypt_module = mcrypt_module_open(cipher, algo_dir, mode, mode_dir);
     211           2 :         if (mcrypt_module == MCRYPT_FAILED) {
     212           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not open encryption module");
     213           0 :                 return NULL;
     214             :         }
     215           2 :         iv_len = mcrypt_enc_get_iv_size(mcrypt_module);
     216           2 :         keyl = mcrypt_enc_get_key_size(mcrypt_module);
     217           2 :         if (keyl < key_len) {
     218           0 :                 key_len = keyl;
     219             :         }
     220             : 
     221           4 :         if (!(tmpzval = zend_hash_str_find(HASH_OF(filterparams), ZEND_STRL("iv"))) ||
     222             :                 Z_TYPE_P(tmpzval) != IS_STRING) {
     223           0 :                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Filter parameter[iv] not provided or not of type: string");
     224           0 :                 mcrypt_module_close(mcrypt_module);
     225           0 :                 return NULL;
     226             :         }
     227             : 
     228           2 :         iv = emalloc(iv_len + 1);
     229           2 :         if (iv_len <= Z_STRLEN_P(tmpzval)) {
     230           2 :                 memcpy(iv, Z_STRVAL_P(tmpzval), iv_len);
     231             :         } else {
     232           0 :                 memcpy(iv, Z_STRVAL_P(tmpzval), Z_STRLEN_P(tmpzval));
     233           0 :                 memset(iv + Z_STRLEN_P(tmpzval), 0, iv_len - Z_STRLEN_P(tmpzval));
     234             :         }
     235             : 
     236           2 :         result = mcrypt_generic_init(mcrypt_module, key, key_len, iv);
     237           2 :         efree(iv);
     238           2 :         if (result < 0) {
     239           0 :                 switch (result) {
     240             :                         case -3:
     241           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Key length incorrect");
     242           0 :                                 break;
     243             :                         case -4:
     244           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Memory allocation error");
     245           0 :                                 break;
     246             :                         case -1:
     247             :                         default:
     248           0 :                                 php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown error");
     249             :                                 break;
     250             :                 }
     251           0 :                 mcrypt_module_close(mcrypt_module);
     252           0 :                 return NULL;
     253             :         }
     254             : 
     255           4 :         data = pemalloc(sizeof(php_mcrypt_filter_data), persistent);
     256           2 :         data->module = mcrypt_module;
     257           2 :         data->encrypt = encrypt;
     258           2 :         if (mcrypt_enc_is_block_mode(mcrypt_module)) {
     259           2 :                 data->blocksize = mcrypt_enc_get_block_size(mcrypt_module);
     260           4 :                 data->block_buffer = pemalloc(data->blocksize, persistent);
     261             :         } else {
     262           0 :                 data->blocksize = 0;
     263           0 :                 data->block_buffer = NULL;
     264             :         }
     265           2 :         data->block_used = 0;
     266           2 :         data->persistent = persistent;
     267             : 
     268           2 :         return php_stream_filter_alloc(&php_mcrypt_filter_ops, data, persistent);
     269             : }
     270             : /* }}} */
     271             : 
     272             : php_stream_filter_factory php_mcrypt_filter_factory = {
     273             :         php_mcrypt_filter_create
     274             : };
     275             : 
     276             : /*
     277             :  * Local variables:
     278             :  * tab-width: 4
     279             :  * c-basic-offset: 4
     280             :  * End:
     281             :  * vim600: noet sw=4 ts=4 fdm=marker
     282             :  * vim<600: noet sw=4 ts=4
     283             :  */

Generated by: LCOV version 1.10

Generated at Wed, 22 Oct 2014 07:24:51 +0000 (2 days ago)

Copyright © 2005-2014 The PHP Group
All rights reserved.