PageRenderTime 42ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/core/form_api.php

https://github.com/fusenigk/mantisbt-1
PHP | 207 lines | 89 code | 37 blank | 81 comment | 33 complexity | 53af06d46da796742942c821dc4c55a6 MD5 | raw file
  1. <?php
  2. # MantisBT - A PHP based bugtracking system
  3. # MantisBT is free software: you can redistribute it and/or modify
  4. # it under the terms of the GNU General Public License as published by
  5. # the Free Software Foundation, either version 2 of the License, or
  6. # (at your option) any later version.
  7. #
  8. # MantisBT is distributed in the hope that it will be useful,
  9. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. # GNU General Public License for more details.
  12. #
  13. # You should have received a copy of the GNU General Public License
  14. # along with MantisBT. If not, see <http://www.gnu.org/licenses/>.
  15. /**
  16. * Form API
  17. *
  18. * Handles form security and validation. Security methods are targeted to
  19. * work with both GET and POST form types and should allow multiple
  20. * simultaneous edits of the form to be submitted out-of-order.
  21. *
  22. * @package CoreAPI
  23. * @subpackage FormAPI
  24. * @copyright Copyright (C) 2000 - 2002 Kenzaburo Ito - kenito@300baud.org
  25. * @copyright Copyright (C) 2002 - 2011 MantisBT Team - mantisbt-dev@lists.sourceforge.net
  26. * @link http://www.mantisbt.org
  27. *
  28. * @uses config_api.php
  29. * @uses constant_inc.php
  30. * @uses crypto_api.php
  31. * @uses gpc_api.php
  32. * @uses php_api.php
  33. * @uses session_api.php
  34. */
  35. require_api( 'config_api.php' );
  36. require_api( 'constant_inc.php' );
  37. require_api( 'crypto_api.php' );
  38. require_api( 'gpc_api.php' );
  39. require_api( 'php_api.php' );
  40. require_api( 'session_api.php' );
  41. /**
  42. * Generate a random security token, prefixed by date, store it in the
  43. * user's session, and then return the string to be used as a form element
  44. * element with the security token as the value.
  45. * @param string Form name
  46. * @return string Security token string
  47. */
  48. function form_security_token( $p_form_name ) {
  49. if ( PHP_CLI == php_mode() || OFF == config_get_global( 'form_security_validation' ) ) {
  50. return '';
  51. }
  52. $t_tokens = session_get( 'form_security_tokens', array() );
  53. # Create a new array for the form name if necessary
  54. if( !isset( $t_tokens[$p_form_name] ) || !is_array( $t_tokens[$p_form_name] ) ) {
  55. $t_tokens[$p_form_name] = array();
  56. }
  57. # Generate a nonce prefixed by date.
  58. # With a base64 output encoded nonce length of 32 characters, we are
  59. # generating a 192bit nonce.
  60. $t_date = date( 'Ymd' );
  61. $t_string = $t_date . crypto_generate_uri_safe_nonce( 32 );
  62. # Add the token to the user's session
  63. if ( !isset( $t_tokens[$p_form_name][$t_date] ) ) {
  64. $t_tokens[$p_form_name][$t_date] = array();
  65. }
  66. $t_tokens[$p_form_name][$t_date][$t_string] = true;
  67. session_set( 'form_security_tokens', $t_tokens );
  68. # The token string
  69. return $t_string;
  70. }
  71. /**
  72. * Get a hidden form element containing a generated form security token.
  73. * @param string Form name
  74. * @return string Hidden form element to output
  75. */
  76. function form_security_field( $p_form_name ) {
  77. if ( PHP_CLI == php_mode() || OFF == config_get_global( 'form_security_validation' ) ) {
  78. return '';
  79. }
  80. $t_string = form_security_token( $p_form_name );
  81. # Create the form element HTML string for the security token
  82. $t_form_token = $p_form_name . '_token';
  83. $t_element = '<input type="hidden" name="%s" value="%s"/>';
  84. $t_element = sprintf( $t_element, $t_form_token, $t_string );
  85. return $t_element;
  86. }
  87. /**
  88. * Get a URL parameter containing a generated form security token.
  89. * @param string Form name
  90. * @return string Hidden form element to output
  91. */
  92. function form_security_param( $p_form_name ) {
  93. if ( PHP_CLI == php_mode() || OFF == config_get_global( 'form_security_validation' ) ) {
  94. return '';
  95. }
  96. $t_string = form_security_token( $p_form_name );
  97. # Create the GET parameter to be used in a URL for a secure link
  98. $t_form_token = $p_form_name . '_token';
  99. $t_param = '&%s=%s';
  100. $t_param = sprintf( $t_param, $t_form_token, $t_string );
  101. return $t_param;
  102. }
  103. /**
  104. * Validate the security token for the given form name based on tokens
  105. * stored in the user's session. While checking stored tokens, any that
  106. * are more than 3 days old will be purged.
  107. * @param string Form name
  108. * @return boolean Form is valid
  109. */
  110. function form_security_validate( $p_form_name ) {
  111. if ( PHP_CLI == php_mode() || OFF == config_get_global( 'form_security_validation' ) ) {
  112. return true;
  113. }
  114. $t_tokens = session_get( 'form_security_tokens', array() );
  115. # Short-circuit if we don't have any tokens for the given form name
  116. if( !isset( $t_tokens[$p_form_name] ) || !is_array( $t_tokens[$p_form_name] ) || count( $t_tokens[$p_form_name] ) < 1 ) {
  117. trigger_error( ERROR_FORM_TOKEN_INVALID, ERROR );
  118. return false;
  119. }
  120. # Get the form input
  121. $t_form_token = $p_form_name . '_token';
  122. $t_input = gpc_get_string( $t_form_token, '' );
  123. # No form input
  124. if( '' == $t_input ) {
  125. trigger_error( ERROR_FORM_TOKEN_INVALID, ERROR );
  126. return false;
  127. }
  128. # Get the date claimed by the token
  129. $t_date = utf8_substr( $t_input, 0, 8 );
  130. # Check if the token exists
  131. if ( isset( $t_tokens[$p_form_name][$t_date][$t_input] ) ) {
  132. return true;
  133. }
  134. # Token does not exist
  135. trigger_error( ERROR_FORM_TOKEN_INVALID, ERROR );
  136. return false;
  137. }
  138. /**
  139. * Purge form security tokens that are older than 3 days, or used
  140. * for form validation.
  141. * @param string Form name
  142. */
  143. function form_security_purge( $p_form_name ) {
  144. if ( PHP_CLI == php_mode() || OFF == config_get_global( 'form_security_validation' ) ) {
  145. return;
  146. }
  147. $t_tokens = session_get( 'form_security_tokens', array() );
  148. # Short-circuit if we don't have any tokens for the given form name
  149. if( !isset( $t_tokens[$p_form_name] ) || !is_array( $t_tokens[$p_form_name] ) || count( $t_tokens[$p_form_name] ) < 1 ) {
  150. return;
  151. }
  152. # Get the form input
  153. $t_form_token = $p_form_name . '_token';
  154. $t_input = gpc_get_string( $t_form_token, '' );
  155. # Get the date claimed by the token
  156. $t_date = utf8_substr( $t_input, 0, 8 );
  157. # Generate a date string of three days ago
  158. $t_purge_date = date( 'Ymd', time() - ( 3 * 24 * 60 * 60 ) );
  159. # Purge old token data, and the currently-used token
  160. unset( $t_tokens[$p_form_name][$t_date][$t_input] );
  161. foreach( $t_tokens as $t_form_name => $t_dates ) {
  162. foreach( $t_dates as $t_date => $t_date_tokens ) {
  163. if ( $t_date < $t_purge_date ) {
  164. unset( $t_tokens[$t_form_name][$t_date] );
  165. }
  166. }
  167. }
  168. session_set( 'form_security_tokens', $t_tokens );
  169. return;
  170. }