Changeset 756
- Timestamp:
- Nov 16, 2021 8:30:58 AM (2 years ago)
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
branches/1.1dev/lib/App.inc.php
r710 r756 413 413 * -false <-- To not carry any queries. If URL already has queries those will be retained. 414 414 */ 415 function printHiddenSession($carry_args=null )415 function printHiddenSession($carry_args=null, $include_csrf_token=false) 416 416 { 417 417 static $_using_trans_sid; … … 474 474 if (!isset($_COOKIE[session_name()]) && !$_using_trans_sid) { 475 475 echo '<input type="hidden" name="' . session_name() . '" value="' . session_id() . '" />'; 476 } 477 478 // Include the csrf_token in the form. 479 // This token can be validated upon form submission with $app->verifyCSRFToken() or $app->requireValidCSRFToken() 480 if ($include_csrf_token) { 481 printf('<input type="hidden" name="csrf_token" value="%s" />', getCSRFToken()); 476 482 } 477 483 } … … 620 626 } 621 627 622 /** 623 * Force the user to connect via https (port 443) by redirecting them to 624 * the same page but with https. 628 /* 629 * Generate a csrf_token if it doesn't exist or is expired, save it to the session and return its value. 630 * Otherwise just return the current token. 631 * Details on the synchronizer token pattern: 632 * https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF)_Prevention_Cheat_Sheet#General_Recommendation:_Synchronizer_Token_Pattern 633 * 634 * @access public 635 * @param bool $force_new_token Generate a new token, replacing any existing token in the session (used by $app->resetCSRFToken()) 636 * @return string The new or current csrf_token 637 * @author Quinn Comendant <quinn@strangecode.com> 638 * @version 1.0 639 * @since 15 Nov 2014 17:57:17 640 */ 641 function getCSRFToken($force_new_token=false) 642 { 643 if ($force_new_token || !isset($_SESSION['csrf_token']) || (removeSignature($_SESSION['csrf_token']) + 86400 < time())) { 644 // No token, or token is expired; generate one and return it. 645 return $_SESSION['csrf_token'] = addSignature(time(), null, 64); 646 } 647 // Current token is not expired; return it. 648 return $_SESSION['csrf_token']; 649 } 650 651 /* 652 * Generate a new token, replacing any existing token in the session. Call this function after $app->requireValidCSRFToken() for a new token to be required for each request. 653 * 654 * @access public 655 * @return void 656 * @author Quinn Comendant <quinn@strangecode.com> 657 * @since 14 Oct 2021 17:35:19 658 */ 659 function resetCSRFToken() 660 { 661 getCSRFToken(true); 662 } 663 664 /* 665 * Compares the given csrf_token with the current or previous one saved in the session. 666 * 667 * @access public 668 * @param string $user_submitted_csrf_token The user-submitted token to compare with the session token. 669 * @return bool True if the tokens match, false otherwise. 670 * @author Quinn Comendant <quinn@strangecode.com> 671 * @version 1.0 672 * @since 15 Nov 2014 18:06:55 673 */ 674 function verifyCSRFToken($user_submitted_csrf_token) 675 { 676 677 if ('' == trim($user_submitted_csrf_token)) { 678 logMsg(sprintf('Empty string failed CSRF verification.', null), LOG_NOTICE, __FILE__, __LINE__); 679 return false; 680 } 681 if (!verifySignature($user_submitted_csrf_token, null, 64)) { 682 logMsg(sprintf('Input failed CSRF verification (invalid signature in %s).', $user_submitted_csrf_token), LOG_WARNING, __FILE__, __LINE__); 683 return false; 684 } 685 $csrf_token = getCSRFToken(); 686 if ($user_submitted_csrf_token != $csrf_token) { 687 logMsg(sprintf('Input failed CSRF verification (%s not in %s).', $user_submitted_csrf_token, $csrf_token), LOG_WARNING, __FILE__, __LINE__); 688 return false; 689 } 690 logMsg(sprintf('Verified CSRF token %s', $user_submitted_csrf_token), LOG_DEBUG, __FILE__, __LINE__); 691 return true; 692 } 693 694 /* 695 * Bounce user if they submit a token that doesn't match the one saved in the session. 696 * Because this function calls dieURL() it must be called before any other HTTP header output. 697 * 698 * @access public 699 * @param string $message Optional message to display to the user (otherwise default message will display). Set to an empty string to display no message. 700 * @param int $type The type of message: MSG_NOTICE, 701 * MSG_SUCCESS, MSG_WARNING, or MSG_ERR. 702 * @param string $file __FILE__. 703 * @param string $line __LINE__. 704 * @return void 705 * @author Quinn Comendant <quinn@strangecode.com> 706 * @version 1.0 707 * @since 15 Nov 2014 18:10:17 708 */ 709 function requireValidCSRFToken($message=null, $type=MSG_NOTICE, $file=null, $line=null) 710 { 711 if (!verifyCSRFToken(getFormData('csrf_token'))) { 712 $message = isset($message) ? $message : _("Sorry, the form token expired. Please try again."); 713 raiseMsg($message, $type, $file, $line); 714 dieBoomerangURL(); 715 } 716 } 717 718 /** 719 * This function has changed to do nothing. SSL redirection should happen at the server layer, doing so here may result in a redirect loop. 625 720 */ 626 721 function sslOn() 627 722 { 628 global $CFG; 629 630 if (function_exists('apache_get_modules')) { 631 $modules = apache_get_modules(); 632 } else { 633 // It's safe to assume we have mod_ssl if we can't determine otherwise. 634 $modules = array('mod_ssl'); 635 } 636 637 if ('on' != getenv('HTTPS') && $CFG->ssl_enabled && in_array('mod_ssl', $modules)) { 638 raiseMsg(sprintf(_("Secure SSL connection made to %s"), $CFG->ssl_domain), MSG_NOTICE, __FILE__, __LINE__); 639 // Always append session because some browsers do not send cookie when crossing to SSL URL. 640 dieURL('https://' . $CFG->ssl_domain . getenv('REQUEST_URI'), null, true); 641 } 642 } 643 644 645 /** 646 * to enforce the user to connect via http (port 80) by redirecting them to 647 * a http version of the current url. 723 logMsg(sprintf('sslOn was called and ignored.', null), LOG_DEBUG, __FILE__, __LINE__); 724 } 725 726 /** 727 * This function has changed to do nothing. There is no reason to prefer a non-SSL connection, and doing so may result in a redirect loop. 648 728 */ 649 729 function sslOff() 650 730 { 651 if ('on' == getenv('HTTPS')) { 652 dieURL('http://' . getenv('HTTP_HOST') . getenv('REQUEST_URI'), null, true); 653 } 731 logMsg(sprintf('sslOff was called and ignored.', null), LOG_DEBUG, __FILE__, __LINE__); 654 732 } 655 733 -
branches/1.1dev/lib/Utilities.inc.php
r754 r756 739 739 function hash64($string, $length=18) 740 740 { 741 $app =& App::getInstance(); 742 743 return mb_substr(preg_replace('/[^\w]/' . $app->getParam('preg_u'), '', base64_encode(hash('sha512', $string, true))), 0, $length); 741 return mb_substr(preg_replace('/[^\w]/', '', base64_encode(hash('sha512', $string, true))), 0, $length); 744 742 } 745 743 746 744 /** 747 745 * Signs a value using md5 and a simple text key. In order for this 748 * function to be useful (i.e. secure) the keymust be kept secret, which746 * function to be useful (i.e. secure) the salt must be kept secret, which 749 747 * means keeping it as safe as database credentials. Putting it into an 750 748 * environment variable set in httpd.conf is a good place. 751 749 * 752 750 * @access public 753 *754 751 * @param string $val The string to sign. 755 * @param string $ key(Optional) A text key to use for computing the signature.756 * 752 * @param string $salt (Optional) A text key to use for computing the signature. 753 * @param string $length (Optional) The length of the added signature. Longer signatures are safer. Must match the length passed to verifySignature() for the signatures to match. 757 754 * @return string The original value with a signature appended. 758 755 */ 759 function addSignature($val, $ key=null)760 { 761 global $CFG;762 763 if ('' == $val) {764 logMsg(sprintf('Adding signature to empty string.', null), LOG_NOTICE, __FILE__, __LINE__);765 } 766 767 if (!isset($key)) {768 $ key= $CFG->signing_key;769 } 770 771 return $val . '-' . substr(md5($val . $key), 0, 18);756 function addSignature($val, $salt=null, $length=18) 757 { 758 if ('' == trim($val)) { 759 logMsg(sprintf('Cannot add signature to an empty string.', null), LOG_INFO, __FILE__, __LINE__); 760 return ''; 761 } 762 763 if (!isset($salt)) { 764 global $CFG; 765 $salt = $CFG->signing_key; 766 } 767 768 return $val . '-' . mb_substr(preg_replace('/[^\w]/', '', base64_encode(hash('sha512', $val . $salt, true))), 0, $length); 772 769 } 773 770 … … 776 773 * 777 774 * @access public 778 *779 775 * @param string $signed_val The string to sign. 780 *781 776 * @return string The original value with a signature removed. 782 777 */ 783 778 function removeSignature($signed_val) 784 779 { 785 return substr($signed_val, 0, strrpos($signed_val, '-')); 786 } 787 788 /** 789 * Verifies a signature appened to a value by addSignature(). 780 if (empty($signed_val) || mb_strpos($signed_val, '-') === false) { 781 return ''; 782 } 783 return mb_substr($signed_val, 0, mb_strrpos($signed_val, '-')); 784 } 785 786 /** 787 * Verifies a signature appended to a value by addSignature(). 790 788 * 791 789 * @access public 792 *793 790 * @param string $signed_val A value with appended signature. 794 * @param string $ key(Optional) A text key to use for computing the signature.795 * 791 * @param string $salt (Optional) A text key to use for computing the signature. 792 * @param string $length (Optional) The length of the added signature. 796 793 * @return bool True if the signature matches the var. 797 794 */ 798 function verifySignature($signed_val, $ key=null)795 function verifySignature($signed_val, $salt=null, $length=18) 799 796 { 800 797 // Strip the value from the signed value. 801 $val = substr($signed_val, 0, strrpos($signed_val, '-'));798 $val = removeSignature($signed_val); 802 799 // If the signed value matches the original signed value we consider the value safe. 803 if ( $signed_val == addSignature($val, $key)) {800 if ('' != $signed_val && $signed_val == addSignature($val, $salt, $length)) { 804 801 // Signature verified. 805 802 return true; 806 803 } else { 804 logMsg(sprintf('Failed signature (%s should be %s)', $signed_val, addSignature($val, $salt, $length)), LOG_DEBUG, __FILE__, __LINE__); 807 805 return false; 808 806 } -
branches/1.1dev/polyfill/mysql.inc.php
r699 r756 176 176 try { 177 177 // Add instance 178 $this->_instances[$usePosition] = new P do($dsn, $username, $password, $flags);178 $this->_instances[$usePosition] = new PDO($dsn, $username, $password, $flags); 179 179 180 180 return $usePosition; … … 211 211 try { 212 212 $this->_params[$link]['databaseName'] = $databaseName; 213 return $this->mysql_query("USE {$databaseName}", $link);213 return $this->mysql_query("USE `{$databaseName}`", $link); 214 214 } catch (PDOException $e) { 215 215 return false; … … 265 265 static $last = null; 266 266 267 if ($result === false ) {267 if ($result === false || $result === null) { 268 268 trigger_error('mysql_fetch_*(): supplied argument is not a valid MySQL result resource', E_USER_WARNING); 269 269 return false; -
trunk/polyfill/mysql.inc.php
r719 r756 265 265 static $last = null; 266 266 267 if ($result === false ) {267 if ($result === false || $result === null) { 268 268 trigger_error('mysql_fetch_*(): supplied argument is not a valid MySQL result resource', E_USER_WARNING); 269 269 return false;
Note: See TracChangeset
for help on using the changeset viewer.