From 73fa051ef8988b4cbdbe76e2fe2aafcf23097182 Mon Sep 17 00:00:00 2001 From: Pliable Pixels Date: Sat, 29 Aug 2015 13:29:52 -0400 Subject: [PATCH 1/9] Google recaptcha --- .../lib/ZoneMinder/ConfigData.pm.in | 54 ++++++++ web/includes/actions.php | 16 +++ web/includes/recaptcha/.gitignore | 3 + web/includes/recaptcha/.travis.yml | 18 +++ web/includes/recaptcha/CONTRIBUTING.md | 24 ++++ web/includes/recaptcha/LICENSE | 29 +++++ web/includes/recaptcha/README.md | 113 ++++++++++++++++ .../recaptcha/src/ReCaptcha/ReCaptcha.php | 97 ++++++++++++++ .../recaptcha/src/ReCaptcha/RequestMethod.php | 42 ++++++ .../src/ReCaptcha/RequestMethod/Curl.php | 47 +++++++ .../src/ReCaptcha/RequestMethod/Post.php | 70 ++++++++++ .../src/ReCaptcha/RequestMethod/Socket.php | 104 +++++++++++++++ .../ReCaptcha/RequestMethod/SocketPost.php | 121 ++++++++++++++++++ .../src/ReCaptcha/RequestParameters.php | 103 +++++++++++++++ .../recaptcha/src/ReCaptcha/Response.php | 102 +++++++++++++++ web/includes/recaptcha/src/autoload.php | 38 ++++++ web/skins/classic/views/login.php | 14 ++ 17 files changed, 995 insertions(+) create mode 100644 web/includes/recaptcha/.gitignore create mode 100644 web/includes/recaptcha/.travis.yml create mode 100644 web/includes/recaptcha/CONTRIBUTING.md create mode 100644 web/includes/recaptcha/LICENSE create mode 100644 web/includes/recaptcha/README.md create mode 100644 web/includes/recaptcha/src/ReCaptcha/ReCaptcha.php create mode 100644 web/includes/recaptcha/src/ReCaptcha/RequestMethod.php create mode 100644 web/includes/recaptcha/src/ReCaptcha/RequestMethod/Curl.php create mode 100644 web/includes/recaptcha/src/ReCaptcha/RequestMethod/Post.php create mode 100644 web/includes/recaptcha/src/ReCaptcha/RequestMethod/Socket.php create mode 100644 web/includes/recaptcha/src/ReCaptcha/RequestMethod/SocketPost.php create mode 100644 web/includes/recaptcha/src/ReCaptcha/RequestParameters.php create mode 100644 web/includes/recaptcha/src/ReCaptcha/Response.php create mode 100644 web/includes/recaptcha/src/autoload.php diff --git a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in index e55e856e4..7fff3d62e 100644 --- a/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in +++ b/scripts/ZoneMinder/lib/ZoneMinder/ConfigData.pm.in @@ -357,6 +357,60 @@ our @options = type => $types{boolean}, category => "system", }, + # PP - Google reCaptcha settings + { + name => "ZM_OPT_USE_GOOG_RECAPTCHA", + default => "no", + description => "Add Google reCaptcha to login page", + help => qqq(" + This option allows you to include a google + reCaptcha validation at login. This means in addition to providing + a valid usernane and password, you will also have to + pass the reCaptcha test. Please note that enabling this + option results in the zoneminder login page reach out + to google servers for captcha validation. Also please note + that enabling this option will break 3rd party clients + like zmNinja and zmView as they also need to login to ZoneMinder + and they will fail the reCaptcha test. + "), + requires => [ + {name=>"ZM_OPT_USE_AUTH", value=>"yes"} + ], + type => $types {boolean}, + category => "system", + }, + + { + name => "ZM_OPT_GOOG_RECAPTCHA_SITEKEY", + default => "...Insert your recaptcha site-key here...", + description => "Your recaptcha site-key", + help => qqq("You need to generate your keys from + the Google reCaptcha website. + Please refer to https://www.google.com/recaptcha/ + for more details. + "), + requires => [ + {name=>"ZM_OPT_USE_GOOG_RECAPTCHA", value=>"yes"} + ], + type => $types {string}, + category => "system", + }, + { + name => "ZM_OPT_GOOG_RECAPTCHA_SECRETKEY", + default => "...Insert your recaptcha secret-key here...", + description => "Your recaptcha secret-key", + help => qqq("You need to generate your keys from + the Google reCaptcha website. + Please refer to https://www.google.com/recaptcha/ + for more details. + "), + requires => [ + {name=>"ZM_OPT_USE_GOOG_RECAPTCHA", value=>"yes"} + ], + type => $types {string}, + category => "system", + }, + { name => "ZM_DIR_EVENTS", default => "events", diff --git a/web/includes/actions.php b/web/includes/actions.php index 3ddf1bb40..d3a4c4121 100644 --- a/web/includes/actions.php +++ b/web/includes/actions.php @@ -42,6 +42,22 @@ if ( ZM_OPT_USE_AUTH && ZM_AUTH_HASH_LOGINS && empty($user) && !empty($_REQUEST[ if ( !empty($action) ) { + // PP - lets validate reCaptcha if it exists + if (ZM_OPT_USE_GOOG_RECAPTCHA) + { + require_once( 'recaptcha/src/autoload.php' ); + $secret = ZM_OPT_GOOG_RECAPTCHA_SECRETKEY; + $gRecaptchaResponse = $_REQUEST['g-recaptcha-response']; + $remoteIp = $_SERVER['REMOTE_ADDR']; + $recaptcha = new \ReCaptcha\ReCaptcha($secret); + $resp = $recaptcha->verify($gRecaptchaResponse, $remoteIp); + if (!$resp->isSuccess()) { + userLogout(); + $view='login'; + $refreshParent = true; + } + } + // General scope actions if ( $action == "login" && isset($_REQUEST['username']) && ( ZM_AUTH_TYPE == "remote" || isset($_REQUEST['password']) ) ) { diff --git a/web/includes/recaptcha/.gitignore b/web/includes/recaptcha/.gitignore new file mode 100644 index 000000000..436384ab7 --- /dev/null +++ b/web/includes/recaptcha/.gitignore @@ -0,0 +1,3 @@ +/composer.lock +/nbproject/private/ +/vendor/ diff --git a/web/includes/recaptcha/.travis.yml b/web/includes/recaptcha/.travis.yml new file mode 100644 index 000000000..fb25bad2d --- /dev/null +++ b/web/includes/recaptcha/.travis.yml @@ -0,0 +1,18 @@ +language: php + +sudo: false + +php: + - 5.3 + - 5.4 + - 5.5 + - 5.6 + - hhvm + +before_script: + - composer install + - phpenv version-name | grep ^5.[34] && echo "extension=apc.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini ; true + - phpenv version-name | grep ^5.[34] && echo "apc.enable_cli=1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini ; true + +script: + - vendor/bin/phpunit diff --git a/web/includes/recaptcha/CONTRIBUTING.md b/web/includes/recaptcha/CONTRIBUTING.md new file mode 100644 index 000000000..1ba853922 --- /dev/null +++ b/web/includes/recaptcha/CONTRIBUTING.md @@ -0,0 +1,24 @@ +Want to contribute? Great! First, read this page (including the small print at the end). + +### Before you contribute +Before we can use your code, you must sign the +[Google Individual Contributor License Agreement](https://developers.google.com/open-source/cla/individual?csw=1) +(CLA), which you can do online. The CLA is necessary mainly because you own the +copyright to your changes, even after your contribution becomes part of our +codebase, so we need your permission to use and distribute your code. We also +need to be sure of various other things—for instance that you'll tell us if you +know that your code infringes on other people's patents. You don't have to sign +the CLA until after you've submitted your code for review and a member has +approved it, but you must do it before we can put your code into our codebase. +Before you start working on a larger contribution, you should get in touch with +us first through the issue tracker with your idea so that we can help out and +possibly guide you. Coordinating up front makes it much easier to avoid +frustration later on. + +### Code reviews +All submissions, including submissions by project members, require review. We +use Github pull requests for this purpose. + +### The small print +Contributions made by corporations are covered by a different agreement than +the one above, the Software Grant and Corporate Contributor License Agreement. diff --git a/web/includes/recaptcha/LICENSE b/web/includes/recaptcha/LICENSE new file mode 100644 index 000000000..f6412328f --- /dev/null +++ b/web/includes/recaptcha/LICENSE @@ -0,0 +1,29 @@ +Copyright 2014, Google Inc. +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above +copyright notice, this list of conditions and the following disclaimer +in the documentation and/or other materials provided with the +distribution. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + diff --git a/web/includes/recaptcha/README.md b/web/includes/recaptcha/README.md new file mode 100644 index 000000000..c3364caab --- /dev/null +++ b/web/includes/recaptcha/README.md @@ -0,0 +1,113 @@ +# reCAPTCHA PHP client library + +[![Build Status](https://travis-ci.org/google/recaptcha.svg)](https://travis-ci.org/google/recaptcha) +[![Latest Stable Version](https://poser.pugx.org/google/recaptcha/v/stable.svg)](https://packagist.org/packages/google/recaptcha) +[![Total Downloads](https://poser.pugx.org/google/recaptcha/downloads.svg)](https://packagist.org/packages/google/recaptcha) + +* Project page: http://www.google.com/recaptcha/ +* Repository: https://github.com/google/recaptcha +* Version: 1.1.1 +* License: BSD, see [LICENSE](LICENSE) + +## Description + +reCAPTCHA is a free CAPTCHA service that protect websites from spam and abuse. +This is Google authored code that provides plugins for third-party integration +with reCAPTCHA. + +## Installation + +### Composer (Recommended) + +[Composer](https://getcomposer.org/) is a widely used dependency manager for PHP +packages. This reCAPTCHA client is available on Packagist as +[`google/recaptcha`](https://packagist.org/packages/google/recaptcha) and can be +installed either by running the `composer require` command or adding the library +to your `composer.json`. To enable Composer for you project, refer to the +project's [Getting Started](https://getcomposer.org/doc/00-intro.md) +documentation. + +To add this dependency using the command, run the following from within your +project directory: +``` +composer require google/recaptcha "~1.1" +``` + +Alternatively, add the dependency directly to your `composer.json` file: +```json +"require": { + "google/recaptcha": "~1.1" +} +``` + +### Direct download (no Composer) + +If you wish to install the library manually (i.e. without Composer), then you +can use the links on the main project page to either clone the repo or download +the [ZIP file](https://github.com/google/recaptcha/archive/master.zip). For +convenience, an autoloader script is provided in `src/autoload.php` which you +can require into your script instead of Composer's `vendor/autoload.php`. For +example: + +```php +require('/path/to/recaptcha/src/autoload.php'); +$recaptcha = new \ReCaptcha\ReCaptcha($secret); +``` + +The classes in the project are structured according to the +[PSR-4](http://www.php-fig.org/psr/psr-4/) standard, so you may of course also +use your own autoloader or require the needed files directly in your code. + +### Development install + +If you would like to contribute to this project or run the unit tests on within +your own environment you will need to install the development dependencies, in +this case that means [PHPUnit](https://phpunit.de/). If you clone the repo and +run `composer install` from within the repo, this will also grab PHPUnit and all +its dependencies for you. If you only need the autoloader installed, then you +can always specify to Composer not to run in development mode, e.g. `composer +install --no-dev`. + +*Note:* These dependencies are only required for development, there's no +requirement for them to be included in your production code. + +## Usage + +First, register keys for your site at https://www.google.com/recaptcha/admin + +When your app receives a form submission containing the `g-recaptcha-response` +field, you can verify it using: +```php +verify($gRecaptchaResponse, $remoteIp); +if ($resp->isSuccess()) { + // verified! +} else { + $errors = $resp->getErrorCodes(); +} +``` + +You can see an end-to-end working example in +[examples/example-captcha.php](examples/example-captcha.php) + +## Upgrading + +### From 1.0.0 + +The previous version of this client is still available on the `1.0.0` tag [in +this repo](https://github.com/google/recaptcha/tree/1.0.0) but it is purely for +reference and will not receive any updates. + +The major changes in 1.1.0 are: +* installation now via Composer; +* class loading also via Composer; +* classes now namespaced; +* old method call was `$rc->verifyResponse($remoteIp, $response)`, new call is + `$rc->verify($response, $remoteIp)` + +## Contributing + +We accept contributions via GitHub Pull Requests, but all contributors need to +be covered by the standard Google Contributor License Agreement. You can find +instructions for this in [CONTRIBUTING](CONTRIBUTING.md) diff --git a/web/includes/recaptcha/src/ReCaptcha/ReCaptcha.php b/web/includes/recaptcha/src/ReCaptcha/ReCaptcha.php new file mode 100644 index 000000000..523c4aae4 --- /dev/null +++ b/web/includes/recaptcha/src/ReCaptcha/ReCaptcha.php @@ -0,0 +1,97 @@ +secret = $secret; + + if (!is_null($requestMethod)) { + $this->requestMethod = $requestMethod; + } else { + $this->requestMethod = new RequestMethod\Post(); + } + } + + /** + * Calls the reCAPTCHA siteverify API to verify whether the user passes + * CAPTCHA test. + * + * @param string $response The value of 'g-recaptcha-response' in the submitted form. + * @param string $remoteIp The end user's IP address. + * @return Response Response from the service. + */ + public function verify($response, $remoteIp = null) + { + // Discard empty solution submissions + if (empty($response)) { + $recaptchaResponse = new Response(false, array('missing-input-response')); + return $recaptchaResponse; + } + + $params = new RequestParameters($this->secret, $response, $remoteIp, self::VERSION); + $rawResponse = $this->requestMethod->submit($params); + return Response::fromJson($rawResponse); + } +} diff --git a/web/includes/recaptcha/src/ReCaptcha/RequestMethod.php b/web/includes/recaptcha/src/ReCaptcha/RequestMethod.php new file mode 100644 index 000000000..fc4dde59c --- /dev/null +++ b/web/includes/recaptcha/src/ReCaptcha/RequestMethod.php @@ -0,0 +1,42 @@ + true, + CURLOPT_POSTFIELDS => $params->toQueryString(), + CURLOPT_HTTPHEADER => array( + 'Content-Type: application/x-www-form-urlencoded' + ), + CURLINFO_HEADER_OUT => false, + CURLOPT_HEADER => false, + CURLOPT_RETURNTRANSFER => true, + CURLOPT_SSL_VERIFYPEER => true + ); + curl_setopt_array($handle, $options); + + $response = curl_exec($handle); + curl_close($handle); + + return $response; + } +} diff --git a/web/includes/recaptcha/src/ReCaptcha/RequestMethod/Post.php b/web/includes/recaptcha/src/ReCaptcha/RequestMethod/Post.php new file mode 100644 index 000000000..7770d9081 --- /dev/null +++ b/web/includes/recaptcha/src/ReCaptcha/RequestMethod/Post.php @@ -0,0 +1,70 @@ + array( + 'header' => "Content-type: application/x-www-form-urlencoded\r\n", + 'method' => 'POST', + 'content' => $params->toQueryString(), + // Force the peer to validate (not needed in 5.6.0+, but still works + 'verify_peer' => true, + // Force the peer validation to use www.google.com + $peer_key => 'www.google.com', + ), + ); + $context = stream_context_create($options); + return file_get_contents(self::SITE_VERIFY_URL, false, $context); + } +} diff --git a/web/includes/recaptcha/src/ReCaptcha/RequestMethod/Socket.php b/web/includes/recaptcha/src/ReCaptcha/RequestMethod/Socket.php new file mode 100644 index 000000000..e74fc49d6 --- /dev/null +++ b/web/includes/recaptcha/src/ReCaptcha/RequestMethod/Socket.php @@ -0,0 +1,104 @@ +handle = fsockopen($hostname, $port, $errno, $errstr, (is_null($timeout) ? ini_get("default_socket_timeout") : $timeout)); + + if ($this->handle != false && $errno === 0 && $errstr === '') { + return $this->handle; + } else { + return false; + } + } + + /** + * fwrite + * + * @see http://php.net/fwrite + * @param string $string + * @param int $length + * @return int | bool + */ + public function fwrite($string, $length = null) + { + return fwrite($this->handle, $string, (is_null($length) ? strlen($string) : $length)); + } + + /** + * fgets + * + * @see http://php.net/fgets + * @param int $length + */ + public function fgets($length = null) + { + return fgets($this->handle, $length); + } + + /** + * feof + * + * @see http://php.net/feof + * @return bool + */ + public function feof() + { + return feof($this->handle); + } + + /** + * fclose + * + * @see http://php.net/fclose + * @return bool + */ + public function fclose() + { + return fclose($this->handle); + } +} diff --git a/web/includes/recaptcha/src/ReCaptcha/RequestMethod/SocketPost.php b/web/includes/recaptcha/src/ReCaptcha/RequestMethod/SocketPost.php new file mode 100644 index 000000000..47541215f --- /dev/null +++ b/web/includes/recaptcha/src/ReCaptcha/RequestMethod/SocketPost.php @@ -0,0 +1,121 @@ +socket = $socket; + } else { + $this->socket = new Socket(); + } + } + + /** + * Submit the POST request with the specified parameters. + * + * @param RequestParameters $params Request parameters + * @return string Body of the reCAPTCHA response + */ + public function submit(RequestParameters $params) + { + $errno = 0; + $errstr = ''; + + if (false === $this->socket->fsockopen('ssl://' . self::RECAPTCHA_HOST, 443, $errno, $errstr, 30)) { + return self::BAD_REQUEST; + } + + $content = $params->toQueryString(); + + $request = "POST " . self::SITE_VERIFY_PATH . " HTTP/1.1\r\n"; + $request .= "Host: " . self::RECAPTCHA_HOST . "\r\n"; + $request .= "Content-Type: application/x-www-form-urlencoded\r\n"; + $request .= "Content-length: " . strlen($content) . "\r\n"; + $request .= "Connection: close\r\n\r\n"; + $request .= $content . "\r\n\r\n"; + + $this->socket->fwrite($request); + $response = ''; + + while (!$this->socket->feof()) { + $response .= $this->socket->fgets(4096); + } + + $this->socket->fclose(); + + if (0 !== strpos($response, 'HTTP/1.1 200 OK')) { + return self::BAD_RESPONSE; + } + + $parts = preg_split("#\n\s*\n#Uis", $response); + + return $parts[1]; + } +} diff --git a/web/includes/recaptcha/src/ReCaptcha/RequestParameters.php b/web/includes/recaptcha/src/ReCaptcha/RequestParameters.php new file mode 100644 index 000000000..cb66f26cf --- /dev/null +++ b/web/includes/recaptcha/src/ReCaptcha/RequestParameters.php @@ -0,0 +1,103 @@ +secret = $secret; + $this->response = $response; + $this->remoteIp = $remoteIp; + $this->version = $version; + } + + /** + * Array representation. + * + * @return array Array formatted parameters. + */ + public function toArray() + { + $params = array('secret' => $this->secret, 'response' => $this->response); + + if (!is_null($this->remoteIp)) { + $params['remoteip'] = $this->remoteIp; + } + + if (!is_null($this->version)) { + $params['version'] = $this->version; + } + + return $params; + } + + /** + * Query string representation for HTTP request. + * + * @return string Query string formatted parameters. + */ + public function toQueryString() + { + return http_build_query($this->toArray(), '', '&'); + } +} diff --git a/web/includes/recaptcha/src/ReCaptcha/Response.php b/web/includes/recaptcha/src/ReCaptcha/Response.php new file mode 100644 index 000000000..d2d8a8bf7 --- /dev/null +++ b/web/includes/recaptcha/src/ReCaptcha/Response.php @@ -0,0 +1,102 @@ +success = $success; + $this->errorCodes = $errorCodes; + } + + /** + * Is success? + * + * @return boolean + */ + public function isSuccess() + { + return $this->success; + } + + /** + * Get error codes. + * + * @return array + */ + public function getErrorCodes() + { + return $this->errorCodes; + } +} diff --git a/web/includes/recaptcha/src/autoload.php b/web/includes/recaptcha/src/autoload.php new file mode 100644 index 000000000..a53cbd78b --- /dev/null +++ b/web/includes/recaptcha/src/autoload.php @@ -0,0 +1,38 @@ + + + "; + } +?>
From f7fea2fe48381471d07062d4e098ccf975673122 Mon Sep 17 00:00:00 2001 From: Pliable Pixels Date: Sat, 29 Aug 2015 15:13:15 -0400 Subject: [PATCH 2/9] Removed dependency on recaptcha client library --- web/includes/actions.php | 47 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/web/includes/actions.php b/web/includes/actions.php index d3a4c4121..b0d3f1a76 100644 --- a/web/includes/actions.php +++ b/web/includes/actions.php @@ -18,6 +18,31 @@ // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // + +// PP - POST request handler for PHP which does not need extensions +// credit: http://wezfurlong.org/blog/2006/nov/http-post-from-php-without-curl/ + +function do_post_request($url, $data, $optional_headers = null) +{ + $params = array('http' => array( + 'method' => 'POST', + 'content' => $data + )); + if ($optional_headers !== null) { + $params['http']['header'] = $optional_headers; + } + $ctx = stream_context_create($params); + $fp = @fopen($url, 'rb', false, $ctx); + if (!$fp) { + throw new Exception("Problem with $url, $php_errormsg"); + } + $response = @stream_get_contents($fp); + if ($response === false) { + throw new Exception("Problem reading data from $url, $php_errormsg"); + } + return $response; +} + function getAffectedIds( $name ) { $names = $name."s"; @@ -45,6 +70,26 @@ if ( !empty($action) ) // PP - lets validate reCaptcha if it exists if (ZM_OPT_USE_GOOG_RECAPTCHA) { + $url = 'https://www.google.com/recaptcha/api/siteverify'; + $fields = array ( + 'secret'=> ZM_OPT_GOOG_RECAPTCHA_SECRETKEY, + 'response' => $_REQUEST['g-recaptcha-response'], + 'remoteip'=> $_SERVER['REMOTE_ADDR'] + + ); + $result = json_decode(do_post_request($url, http_build_query($fields))); + if ($result->success != 'true') + { + userLogout(); + $view='login'; + $refreshParent = true; + + } + + /* + //PP - this is using google's recaptcha library + // keeping this code here incase anyone reports a problem + // with the above approach require_once( 'recaptcha/src/autoload.php' ); $secret = ZM_OPT_GOOG_RECAPTCHA_SECRETKEY; $gRecaptchaResponse = $_REQUEST['g-recaptcha-response']; @@ -55,7 +100,7 @@ if ( !empty($action) ) userLogout(); $view='login'; $refreshParent = true; - } + }*/ } // General scope actions From feeb890be2ddd2cb369b8e59fed6f8bf87cd7b57 Mon Sep 17 00:00:00 2001 From: Pliable Pixels Date: Sat, 29 Aug 2015 15:14:20 -0400 Subject: [PATCH 3/9] removed recaptcha client dependency --- web/includes/recaptcha/.gitignore | 3 - web/includes/recaptcha/.travis.yml | 18 --- web/includes/recaptcha/CONTRIBUTING.md | 24 ---- web/includes/recaptcha/LICENSE | 29 ----- web/includes/recaptcha/README.md | 113 ---------------- .../recaptcha/src/ReCaptcha/ReCaptcha.php | 97 -------------- .../recaptcha/src/ReCaptcha/RequestMethod.php | 42 ------ .../src/ReCaptcha/RequestMethod/Curl.php | 47 ------- .../src/ReCaptcha/RequestMethod/Post.php | 70 ---------- .../src/ReCaptcha/RequestMethod/Socket.php | 104 --------------- .../ReCaptcha/RequestMethod/SocketPost.php | 121 ------------------ .../src/ReCaptcha/RequestParameters.php | 103 --------------- .../recaptcha/src/ReCaptcha/Response.php | 102 --------------- web/includes/recaptcha/src/autoload.php | 38 ------ 14 files changed, 911 deletions(-) delete mode 100644 web/includes/recaptcha/.gitignore delete mode 100644 web/includes/recaptcha/.travis.yml delete mode 100644 web/includes/recaptcha/CONTRIBUTING.md delete mode 100644 web/includes/recaptcha/LICENSE delete mode 100644 web/includes/recaptcha/README.md delete mode 100644 web/includes/recaptcha/src/ReCaptcha/ReCaptcha.php delete mode 100644 web/includes/recaptcha/src/ReCaptcha/RequestMethod.php delete mode 100644 web/includes/recaptcha/src/ReCaptcha/RequestMethod/Curl.php delete mode 100644 web/includes/recaptcha/src/ReCaptcha/RequestMethod/Post.php delete mode 100644 web/includes/recaptcha/src/ReCaptcha/RequestMethod/Socket.php delete mode 100644 web/includes/recaptcha/src/ReCaptcha/RequestMethod/SocketPost.php delete mode 100644 web/includes/recaptcha/src/ReCaptcha/RequestParameters.php delete mode 100644 web/includes/recaptcha/src/ReCaptcha/Response.php delete mode 100644 web/includes/recaptcha/src/autoload.php diff --git a/web/includes/recaptcha/.gitignore b/web/includes/recaptcha/.gitignore deleted file mode 100644 index 436384ab7..000000000 --- a/web/includes/recaptcha/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -/composer.lock -/nbproject/private/ -/vendor/ diff --git a/web/includes/recaptcha/.travis.yml b/web/includes/recaptcha/.travis.yml deleted file mode 100644 index fb25bad2d..000000000 --- a/web/includes/recaptcha/.travis.yml +++ /dev/null @@ -1,18 +0,0 @@ -language: php - -sudo: false - -php: - - 5.3 - - 5.4 - - 5.5 - - 5.6 - - hhvm - -before_script: - - composer install - - phpenv version-name | grep ^5.[34] && echo "extension=apc.so" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini ; true - - phpenv version-name | grep ^5.[34] && echo "apc.enable_cli=1" >> ~/.phpenv/versions/$(phpenv version-name)/etc/php.ini ; true - -script: - - vendor/bin/phpunit diff --git a/web/includes/recaptcha/CONTRIBUTING.md b/web/includes/recaptcha/CONTRIBUTING.md deleted file mode 100644 index 1ba853922..000000000 --- a/web/includes/recaptcha/CONTRIBUTING.md +++ /dev/null @@ -1,24 +0,0 @@ -Want to contribute? Great! First, read this page (including the small print at the end). - -### Before you contribute -Before we can use your code, you must sign the -[Google Individual Contributor License Agreement](https://developers.google.com/open-source/cla/individual?csw=1) -(CLA), which you can do online. The CLA is necessary mainly because you own the -copyright to your changes, even after your contribution becomes part of our -codebase, so we need your permission to use and distribute your code. We also -need to be sure of various other things—for instance that you'll tell us if you -know that your code infringes on other people's patents. You don't have to sign -the CLA until after you've submitted your code for review and a member has -approved it, but you must do it before we can put your code into our codebase. -Before you start working on a larger contribution, you should get in touch with -us first through the issue tracker with your idea so that we can help out and -possibly guide you. Coordinating up front makes it much easier to avoid -frustration later on. - -### Code reviews -All submissions, including submissions by project members, require review. We -use Github pull requests for this purpose. - -### The small print -Contributions made by corporations are covered by a different agreement than -the one above, the Software Grant and Corporate Contributor License Agreement. diff --git a/web/includes/recaptcha/LICENSE b/web/includes/recaptcha/LICENSE deleted file mode 100644 index f6412328f..000000000 --- a/web/includes/recaptcha/LICENSE +++ /dev/null @@ -1,29 +0,0 @@ -Copyright 2014, Google Inc. -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above -copyright notice, this list of conditions and the following disclaimer -in the documentation and/or other materials provided with the -distribution. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - diff --git a/web/includes/recaptcha/README.md b/web/includes/recaptcha/README.md deleted file mode 100644 index c3364caab..000000000 --- a/web/includes/recaptcha/README.md +++ /dev/null @@ -1,113 +0,0 @@ -# reCAPTCHA PHP client library - -[![Build Status](https://travis-ci.org/google/recaptcha.svg)](https://travis-ci.org/google/recaptcha) -[![Latest Stable Version](https://poser.pugx.org/google/recaptcha/v/stable.svg)](https://packagist.org/packages/google/recaptcha) -[![Total Downloads](https://poser.pugx.org/google/recaptcha/downloads.svg)](https://packagist.org/packages/google/recaptcha) - -* Project page: http://www.google.com/recaptcha/ -* Repository: https://github.com/google/recaptcha -* Version: 1.1.1 -* License: BSD, see [LICENSE](LICENSE) - -## Description - -reCAPTCHA is a free CAPTCHA service that protect websites from spam and abuse. -This is Google authored code that provides plugins for third-party integration -with reCAPTCHA. - -## Installation - -### Composer (Recommended) - -[Composer](https://getcomposer.org/) is a widely used dependency manager for PHP -packages. This reCAPTCHA client is available on Packagist as -[`google/recaptcha`](https://packagist.org/packages/google/recaptcha) and can be -installed either by running the `composer require` command or adding the library -to your `composer.json`. To enable Composer for you project, refer to the -project's [Getting Started](https://getcomposer.org/doc/00-intro.md) -documentation. - -To add this dependency using the command, run the following from within your -project directory: -``` -composer require google/recaptcha "~1.1" -``` - -Alternatively, add the dependency directly to your `composer.json` file: -```json -"require": { - "google/recaptcha": "~1.1" -} -``` - -### Direct download (no Composer) - -If you wish to install the library manually (i.e. without Composer), then you -can use the links on the main project page to either clone the repo or download -the [ZIP file](https://github.com/google/recaptcha/archive/master.zip). For -convenience, an autoloader script is provided in `src/autoload.php` which you -can require into your script instead of Composer's `vendor/autoload.php`. For -example: - -```php -require('/path/to/recaptcha/src/autoload.php'); -$recaptcha = new \ReCaptcha\ReCaptcha($secret); -``` - -The classes in the project are structured according to the -[PSR-4](http://www.php-fig.org/psr/psr-4/) standard, so you may of course also -use your own autoloader or require the needed files directly in your code. - -### Development install - -If you would like to contribute to this project or run the unit tests on within -your own environment you will need to install the development dependencies, in -this case that means [PHPUnit](https://phpunit.de/). If you clone the repo and -run `composer install` from within the repo, this will also grab PHPUnit and all -its dependencies for you. If you only need the autoloader installed, then you -can always specify to Composer not to run in development mode, e.g. `composer -install --no-dev`. - -*Note:* These dependencies are only required for development, there's no -requirement for them to be included in your production code. - -## Usage - -First, register keys for your site at https://www.google.com/recaptcha/admin - -When your app receives a form submission containing the `g-recaptcha-response` -field, you can verify it using: -```php -verify($gRecaptchaResponse, $remoteIp); -if ($resp->isSuccess()) { - // verified! -} else { - $errors = $resp->getErrorCodes(); -} -``` - -You can see an end-to-end working example in -[examples/example-captcha.php](examples/example-captcha.php) - -## Upgrading - -### From 1.0.0 - -The previous version of this client is still available on the `1.0.0` tag [in -this repo](https://github.com/google/recaptcha/tree/1.0.0) but it is purely for -reference and will not receive any updates. - -The major changes in 1.1.0 are: -* installation now via Composer; -* class loading also via Composer; -* classes now namespaced; -* old method call was `$rc->verifyResponse($remoteIp, $response)`, new call is - `$rc->verify($response, $remoteIp)` - -## Contributing - -We accept contributions via GitHub Pull Requests, but all contributors need to -be covered by the standard Google Contributor License Agreement. You can find -instructions for this in [CONTRIBUTING](CONTRIBUTING.md) diff --git a/web/includes/recaptcha/src/ReCaptcha/ReCaptcha.php b/web/includes/recaptcha/src/ReCaptcha/ReCaptcha.php deleted file mode 100644 index 523c4aae4..000000000 --- a/web/includes/recaptcha/src/ReCaptcha/ReCaptcha.php +++ /dev/null @@ -1,97 +0,0 @@ -secret = $secret; - - if (!is_null($requestMethod)) { - $this->requestMethod = $requestMethod; - } else { - $this->requestMethod = new RequestMethod\Post(); - } - } - - /** - * Calls the reCAPTCHA siteverify API to verify whether the user passes - * CAPTCHA test. - * - * @param string $response The value of 'g-recaptcha-response' in the submitted form. - * @param string $remoteIp The end user's IP address. - * @return Response Response from the service. - */ - public function verify($response, $remoteIp = null) - { - // Discard empty solution submissions - if (empty($response)) { - $recaptchaResponse = new Response(false, array('missing-input-response')); - return $recaptchaResponse; - } - - $params = new RequestParameters($this->secret, $response, $remoteIp, self::VERSION); - $rawResponse = $this->requestMethod->submit($params); - return Response::fromJson($rawResponse); - } -} diff --git a/web/includes/recaptcha/src/ReCaptcha/RequestMethod.php b/web/includes/recaptcha/src/ReCaptcha/RequestMethod.php deleted file mode 100644 index fc4dde59c..000000000 --- a/web/includes/recaptcha/src/ReCaptcha/RequestMethod.php +++ /dev/null @@ -1,42 +0,0 @@ - true, - CURLOPT_POSTFIELDS => $params->toQueryString(), - CURLOPT_HTTPHEADER => array( - 'Content-Type: application/x-www-form-urlencoded' - ), - CURLINFO_HEADER_OUT => false, - CURLOPT_HEADER => false, - CURLOPT_RETURNTRANSFER => true, - CURLOPT_SSL_VERIFYPEER => true - ); - curl_setopt_array($handle, $options); - - $response = curl_exec($handle); - curl_close($handle); - - return $response; - } -} diff --git a/web/includes/recaptcha/src/ReCaptcha/RequestMethod/Post.php b/web/includes/recaptcha/src/ReCaptcha/RequestMethod/Post.php deleted file mode 100644 index 7770d9081..000000000 --- a/web/includes/recaptcha/src/ReCaptcha/RequestMethod/Post.php +++ /dev/null @@ -1,70 +0,0 @@ - array( - 'header' => "Content-type: application/x-www-form-urlencoded\r\n", - 'method' => 'POST', - 'content' => $params->toQueryString(), - // Force the peer to validate (not needed in 5.6.0+, but still works - 'verify_peer' => true, - // Force the peer validation to use www.google.com - $peer_key => 'www.google.com', - ), - ); - $context = stream_context_create($options); - return file_get_contents(self::SITE_VERIFY_URL, false, $context); - } -} diff --git a/web/includes/recaptcha/src/ReCaptcha/RequestMethod/Socket.php b/web/includes/recaptcha/src/ReCaptcha/RequestMethod/Socket.php deleted file mode 100644 index e74fc49d6..000000000 --- a/web/includes/recaptcha/src/ReCaptcha/RequestMethod/Socket.php +++ /dev/null @@ -1,104 +0,0 @@ -handle = fsockopen($hostname, $port, $errno, $errstr, (is_null($timeout) ? ini_get("default_socket_timeout") : $timeout)); - - if ($this->handle != false && $errno === 0 && $errstr === '') { - return $this->handle; - } else { - return false; - } - } - - /** - * fwrite - * - * @see http://php.net/fwrite - * @param string $string - * @param int $length - * @return int | bool - */ - public function fwrite($string, $length = null) - { - return fwrite($this->handle, $string, (is_null($length) ? strlen($string) : $length)); - } - - /** - * fgets - * - * @see http://php.net/fgets - * @param int $length - */ - public function fgets($length = null) - { - return fgets($this->handle, $length); - } - - /** - * feof - * - * @see http://php.net/feof - * @return bool - */ - public function feof() - { - return feof($this->handle); - } - - /** - * fclose - * - * @see http://php.net/fclose - * @return bool - */ - public function fclose() - { - return fclose($this->handle); - } -} diff --git a/web/includes/recaptcha/src/ReCaptcha/RequestMethod/SocketPost.php b/web/includes/recaptcha/src/ReCaptcha/RequestMethod/SocketPost.php deleted file mode 100644 index 47541215f..000000000 --- a/web/includes/recaptcha/src/ReCaptcha/RequestMethod/SocketPost.php +++ /dev/null @@ -1,121 +0,0 @@ -socket = $socket; - } else { - $this->socket = new Socket(); - } - } - - /** - * Submit the POST request with the specified parameters. - * - * @param RequestParameters $params Request parameters - * @return string Body of the reCAPTCHA response - */ - public function submit(RequestParameters $params) - { - $errno = 0; - $errstr = ''; - - if (false === $this->socket->fsockopen('ssl://' . self::RECAPTCHA_HOST, 443, $errno, $errstr, 30)) { - return self::BAD_REQUEST; - } - - $content = $params->toQueryString(); - - $request = "POST " . self::SITE_VERIFY_PATH . " HTTP/1.1\r\n"; - $request .= "Host: " . self::RECAPTCHA_HOST . "\r\n"; - $request .= "Content-Type: application/x-www-form-urlencoded\r\n"; - $request .= "Content-length: " . strlen($content) . "\r\n"; - $request .= "Connection: close\r\n\r\n"; - $request .= $content . "\r\n\r\n"; - - $this->socket->fwrite($request); - $response = ''; - - while (!$this->socket->feof()) { - $response .= $this->socket->fgets(4096); - } - - $this->socket->fclose(); - - if (0 !== strpos($response, 'HTTP/1.1 200 OK')) { - return self::BAD_RESPONSE; - } - - $parts = preg_split("#\n\s*\n#Uis", $response); - - return $parts[1]; - } -} diff --git a/web/includes/recaptcha/src/ReCaptcha/RequestParameters.php b/web/includes/recaptcha/src/ReCaptcha/RequestParameters.php deleted file mode 100644 index cb66f26cf..000000000 --- a/web/includes/recaptcha/src/ReCaptcha/RequestParameters.php +++ /dev/null @@ -1,103 +0,0 @@ -secret = $secret; - $this->response = $response; - $this->remoteIp = $remoteIp; - $this->version = $version; - } - - /** - * Array representation. - * - * @return array Array formatted parameters. - */ - public function toArray() - { - $params = array('secret' => $this->secret, 'response' => $this->response); - - if (!is_null($this->remoteIp)) { - $params['remoteip'] = $this->remoteIp; - } - - if (!is_null($this->version)) { - $params['version'] = $this->version; - } - - return $params; - } - - /** - * Query string representation for HTTP request. - * - * @return string Query string formatted parameters. - */ - public function toQueryString() - { - return http_build_query($this->toArray(), '', '&'); - } -} diff --git a/web/includes/recaptcha/src/ReCaptcha/Response.php b/web/includes/recaptcha/src/ReCaptcha/Response.php deleted file mode 100644 index d2d8a8bf7..000000000 --- a/web/includes/recaptcha/src/ReCaptcha/Response.php +++ /dev/null @@ -1,102 +0,0 @@ -success = $success; - $this->errorCodes = $errorCodes; - } - - /** - * Is success? - * - * @return boolean - */ - public function isSuccess() - { - return $this->success; - } - - /** - * Get error codes. - * - * @return array - */ - public function getErrorCodes() - { - return $this->errorCodes; - } -} diff --git a/web/includes/recaptcha/src/autoload.php b/web/includes/recaptcha/src/autoload.php deleted file mode 100644 index a53cbd78b..000000000 --- a/web/includes/recaptcha/src/autoload.php +++ /dev/null @@ -1,38 +0,0 @@ - Date: Mon, 31 Aug 2015 20:39:28 -0400 Subject: [PATCH 4/9] Handled situation where user enables captcha but forgets to supply keys --- web/includes/actions.php | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/web/includes/actions.php b/web/includes/actions.php index b0d3f1a76..ef0b21135 100644 --- a/web/includes/actions.php +++ b/web/includes/actions.php @@ -68,7 +68,7 @@ if ( ZM_OPT_USE_AUTH && ZM_AUTH_HASH_LOGINS && empty($user) && !empty($_REQUEST[ if ( !empty($action) ) { // PP - lets validate reCaptcha if it exists - if (ZM_OPT_USE_GOOG_RECAPTCHA) + if (ZM_OPT_USE_GOOG_RECAPTCHA && ZM_OPT_GOOG_RECAPTCHA_SECRETKEY && ZM_OPT_GOOG_RECAPTCHA_SITEKEY) { $url = 'https://www.google.com/recaptcha/api/siteverify'; $fields = array ( @@ -77,30 +77,16 @@ if ( !empty($action) ) 'remoteip'=> $_SERVER['REMOTE_ADDR'] ); - $result = json_decode(do_post_request($url, http_build_query($fields))); + $res= do_post_request($url, http_build_query($fields)); + $result = json_decode($res); if ($result->success != 'true') - { + { userLogout(); $view='login'; $refreshParent = true; } - /* - //PP - this is using google's recaptcha library - // keeping this code here incase anyone reports a problem - // with the above approach - require_once( 'recaptcha/src/autoload.php' ); - $secret = ZM_OPT_GOOG_RECAPTCHA_SECRETKEY; - $gRecaptchaResponse = $_REQUEST['g-recaptcha-response']; - $remoteIp = $_SERVER['REMOTE_ADDR']; - $recaptcha = new \ReCaptcha\ReCaptcha($secret); - $resp = $recaptcha->verify($gRecaptchaResponse, $remoteIp); - if (!$resp->isSuccess()) { - userLogout(); - $view='login'; - $refreshParent = true; - }*/ } // General scope actions From 2481c7a22ed7a23a4563d2d7781b64654060be5d Mon Sep 17 00:00:00 2001 From: Pliable Pixels Date: Mon, 31 Aug 2015 20:39:43 -0400 Subject: [PATCH 5/9] Handled situation where user enables captcha but forgets to supply keys --- web/skins/classic/views/login.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/skins/classic/views/login.php b/web/skins/classic/views/login.php index 9e9c58b89..b91293965 100644 --- a/web/skins/classic/views/login.php +++ b/web/skins/classic/views/login.php @@ -52,7 +52,7 @@ xhtmlHeaders(__FILE__, translate('Login') );
"; } From dc9a5b13fe93dfd80bcfeb7e267e6dfa431da036 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Mon, 7 Sep 2015 15:50:42 -0500 Subject: [PATCH 6/9] redhat rpm packaging modifications --- distros/redhat/README.Centos7 | 71 ++++++++++++++------------- distros/redhat/README.https | 25 ++++++++++ distros/redhat/zoneminder.el7.conf.in | 23 ++++----- distros/redhat/zoneminder.el7.spec | 28 +++++++---- 4 files changed, 93 insertions(+), 54 deletions(-) create mode 100644 distros/redhat/README.https diff --git a/distros/redhat/README.Centos7 b/distros/redhat/README.Centos7 index 54f355397..89fe9736c 100644 --- a/distros/redhat/README.Centos7 +++ b/distros/redhat/README.Centos7 @@ -1,23 +1,19 @@ - What's New ========== -1. The Apache ScriptAlias has been changed from "/cgi-bin/zm/zms" to - "/cgi-bin-zm/zms". This has been to done to avoid this bug: - https://bugzilla.redhat.com/show_bug.cgi?id=973067 +1. The ZoneMinder mysql account now requires "Create" permission. This change + must be done manually before ZoneMinder will run. See the installation steps + below. - IMPORTANT: ZoneMinder will not update this value during an upgrade. You must - manually update ZM_PATH_ZMS yourself under Options. This does not affect - new installs. +2. A new permission group called "Groups" has been added. This allows the + system administrator to assign "view", "edit", or "none" permission to + normal users, without giving them access to the rest of the ZoneMinder + system. During an upgrade, existing accounts will default to a Groups + permission of "none". -2. During an rpm package upgrade, zmupdate.pl will now auto-update the database - and the zonemidner service will restart automatically. - -3. The ZoneMinder config file, zm.conf, has been moved under /etc/zm. - -4. Systemd. CentOS 7 uses Systemd instead of the legacy Sys V Init. Under the - hood, Systemd does things quite a bit differently. Prepare to go through a - learning curve if you have not done so already. +3. This package now requires the HTTPS protocol to access the web portal. + Requests using HTTP will auto-redirect to HTTPS. See README.https for + more information. New installs ============ @@ -36,7 +32,7 @@ New installs mysql -u root -p < /usr/share/zoneminder/db/zm_create.sql mysql -u root -p - mysql> grant select,insert,update,delete,lock tables,alter, create + mysql> grant select,insert,update,delete,lock tables,alter,create on zm.* to 'zmuser'@localhost identified by 'zmpass'; mysql> exit; mysqladmin -u root -p reload @@ -50,21 +46,22 @@ New installs step. 4. Edit /etc/php.ini, uncomment the date.timezone line, and add your local - timezone. For whatever reason, PHP will complain loudly if this is not set, - or if it is set incorrectly, and these complaints will show up in the - zoneminder logging system as errors. + timezone. PHP will complain loudly if this is not set, or if it is set + incorrectly, and these complaints will show up in the zoneminder logging + system as errors. If you are not sure of the proper timezone specification to use, look at http://php.net/date.timezone -5. This package will automatically configure and install an SELinux policy - called local_zoneminder. A copy of this policy is in the documentation - folder. +5. Disable SELinux + + We currently do not have the resources to create and maintain an accurate + SELinux policy for ZoneMinder on CentOS 7. We will gladly accept pull + reqeusts from anyone who wishes to do the work. In the meantime, SELinux + will need to be disabled or put into permissive mode. - Maintaining an accurate SELinux policy file that does not create issues has - been a struggle. If SELinux blocks nortmal ZoneMinder acitivity, or you - feel you just don't need it, SELinux can be disabled for the current running - session with the following command: + To immediately disbale SELinux for the current seesion, issue the following + from the command line: sudo setenforce 0 @@ -99,7 +96,7 @@ Upgrades 2. Verify permissions of the zmuser account. - Overtime, the database account permissions required for normal operation + Over time, the database account permissions required for normal operation have changed. Verify the zmuser database account has been granted select, insert, update, delete, lock tables, alter, and create permission to the ZoneMinder database: @@ -108,20 +105,26 @@ Upgrades mysql> show grants for zmuser@localhost; mysql> exit; -3. Verify the database was upgraded automatically. + See step 2 of the Installation section to add missing permissions. - From the web console, ZoneMinder should show a status of "Running", and the - version number should have incremented. +3. Verify the ZoneMinder Apache configuration file in the folder + /etc/httpd/conf.d. You will have a file called "zoneminder.conf" and there + may also be a file called "zoneminder.conf.rpmnew". If the rpmnew file + exists, inspect it and merge anything new in that file with zoneminder.conf. - If it is not running, then try to start it. The web console will indicate - if there is a database version conflict. If this is the case, then you may - need to manually update the database from the command line: +4. Upgrade the database before starting ZoneMinder. + + Most upgrades can be performed by executing the following command: sudo zmupdate.pl - Modern versions of ZoneMinder don't require any parameters added to the + Recent versions of ZoneMinder don't require any parameters added to the zmupdate command. However, if ZoneMinder complains, you may need to call zmupdate in the following manner: sudo zmupdate.pl --user=root --pass= --version= +5. Now start zoneminder: + + sudo systemctl start zoneminder + diff --git a/distros/redhat/README.https b/distros/redhat/README.https new file mode 100644 index 000000000..23affeb96 --- /dev/null +++ b/distros/redhat/README.https @@ -0,0 +1,25 @@ +HTTPS is now a requirement +========================== + +This package now depends on Apache's mod_ssl pacakge. This will automatically +be installed along with ZoneMinder. Upon installation, the mod_ssl package +will create a default, self-signed certificate. This is the certificate that +ZoneMinder will use out of the box. + +Since the certificate is self-signed, you will get a warning from your browser +the first time you access the web portal. This is normal. + +This is not intended to be an all encompasing solution for everyone. ZoneMinder +will work just fine over HTTPS the way it is currently configured. However, +here are a couple of considerations you may want to take. + +1. Create your own certificate. The CentOS wiki has a guide that describes how + to do this: https://wiki.centos.org/HowTos/Https . Additionally, Googling + "centos certificate" reveals many articles on the subject. Note that some + third party applications, such as zmNinja, will require you to create a + certificate different than the default certificate on your machine. + +2. You can turn off HTTPS entirely by simply commenting out the SSLRequireSSL + directives found in /etc/httpd/conf.d/zoneminder.conf. You should also + comment out the HTTP -> HTTPS Rewrite rule. + diff --git a/distros/redhat/zoneminder.el7.conf.in b/distros/redhat/zoneminder.el7.conf.in index 28bada18e..564e4ccbd 100644 --- a/distros/redhat/zoneminder.el7.conf.in +++ b/distros/redhat/zoneminder.el7.conf.in @@ -1,16 +1,17 @@ -# When using Zoneminder's own authentication, recorded CCTV images are -# accessible from the web directly without passing the authentication. This -# means any attacker could see your CCTV images without a password. In order -# to avoid this you can disable Zoneminder's authentication and configure -# standard Apache authentication (see the Apache documentation for details on -# this). # -# If you still wish to use Zoneminder's own authentication, or have an -# internal site which needs no authentication, you need to delete the line -# marked below and restart Apache. +# ZoneMinder Apache configuration file +# With SSLRequire and HTTPS auto redirect +# Modify this configuration to suit your requirements +# + +# Auto Redirect HTTP requests to HTTPS +RewriteEngine On +RewriteCond %{HTTPS} !=on +RewriteRule ^/?(zm)(.*) https://%{SERVER_NAME}/$1$2 [R,L] Alias /zm "@ZM_WEBDIR@" + SSLRequireSSL Options -Indexes +MultiViews +FollowSymLinks AllowOverride All @@ -22,12 +23,11 @@ Alias /zm "@ZM_WEBDIR@" Order deny,allow Allow from all - # ZoneMinder no longer uses short tags so this is safe to leave disabled - # php_value short_open_tag 1 ScriptAlias /cgi-bin-zm "@ZM_CGIDIR@" + SSLRequireSSL AllowOverride All Options +ExecCGI +FollowSymLinks @@ -40,3 +40,4 @@ ScriptAlias /cgi-bin-zm "@ZM_CGIDIR@" Allow from all + diff --git a/distros/redhat/zoneminder.el7.spec b/distros/redhat/zoneminder.el7.spec index 1d53cbdd5..9793a8934 100644 --- a/distros/redhat/zoneminder.el7.spec +++ b/distros/redhat/zoneminder.el7.spec @@ -32,8 +32,8 @@ BuildRequires: ffmpeg ffmpeg-devel perl(X10::ActiveHome) perl(Astro::SunTime) # cmake needs the following installed at build time due to the way it auto-detects certain parameters BuildRequires: httpd polkit-devel -Requires: httpd php php-gd php-mysql mariadb-server polkit net-tools psmisc -Requires: libjpeg-turbo vlc-core libcurl +Requires: httpd php php-gd php-mysql mariadb-server polkit net-tools mod_ssl +Requires: psmisc libjpeg-turbo vlc-core libcurl Requires: perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version)) Requires: perl(DBD::mysql) perl(Archive::Tar) perl(Archive::Zip) Requires: perl(MIME::Entity) perl(MIME::Lite) perl(Net::SMTP) perl(Net::FTP) @@ -87,20 +87,27 @@ fi /usr/bin/gpasswd -a %{zmuid_final} video /usr/bin/gpasswd -a %{zmuid_final} dialout +# Disabled. SELinux policy does not work for RHEL 7. # Create and load zoneminder selinux policy module -echo -e "\nCreating and installing a ZoneMinder SELinux policy module. Please wait.\n" -/usr/bin/checkmodule -M -m -o %{_docdir}/%{name}-%{version}/local_zoneminder.mod %{_docdir}/%{name}-%{version}/local_zoneminder.te > /dev/null -/usr/bin/semodule_package -o %{_docdir}/%{name}-%{version}/local_zoneminder.pp -m %{_docdir}/%{name}-%{version}/local_zoneminder.mod > /dev/null -/usr/sbin/semodule -i %{_docdir}/%{name}-%{version}/local_zoneminder.pp > /dev/null +#echo -e "\nCreating and installing a ZoneMinder SELinux policy module. Please wait.\n" +#/usr/bin/checkmodule -M -m -o %{_docdir}/%{name}-%{version}/local_zoneminder.mod %{_docdir}/%{name}-%{version}/local_zoneminder.te > /dev/null +#/usr/bin/semodule_package -o %{_docdir}/%{name}-%{version}/local_zoneminder.pp -m %{_docdir}/%{name}-%{version}/local_zoneminder.mod > /dev/null +#/usr/sbin/semodule -i %{_docdir}/%{name}-%{version}/local_zoneminder.pp > /dev/null # Upgrade from a previous version of zoneminder if [ $1 -eq 2 ] ; then + # Freshen the database + /usr/bin/zmupdate.pl -f + + # We can't run this automatically when new sql account permissions need to + # be manually added first # Run zmupdate non-interactively - /usr/bin/zmupdate.pl --nointeractive + #/usr/bin/zmupdate.pl --nointeractive fi -# Display the README for post installation instructions -/usr/bin/less %{_docdir}/%{name}-%{version}/README.Centos7 +# Warn the end user to read the README file +echo -e "/nVERY IMPORTANT: Before starting ZoneMinder, read README.Centos7 to finish the\ninstallation or upgrade!\n" +echo -e "/nThe README file is located here: %{_docdir}/%{name}-%{version}." %preun if [ $1 -eq 0 ] ; then @@ -184,6 +191,9 @@ fi %changelog +* Mon Sep 7 2015 Andrew Bauer - 1.28.1 +- Require https, disable selinux module, freshen dB on updates. + * Sun Feb 8 2015 Andrew Bauer - 1.28.1 - Initial release for CentOS 7. From 41cfadbcb16d7f74cf7e0b62dd4eda042c65f8f4 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Mon, 7 Sep 2015 16:14:58 -0500 Subject: [PATCH 7/9] Update zoneminder.el7.spec typo --- distros/redhat/zoneminder.el7.spec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/distros/redhat/zoneminder.el7.spec b/distros/redhat/zoneminder.el7.spec index 9793a8934..d4ab8c3af 100644 --- a/distros/redhat/zoneminder.el7.spec +++ b/distros/redhat/zoneminder.el7.spec @@ -106,8 +106,8 @@ if [ $1 -eq 2 ] ; then fi # Warn the end user to read the README file -echo -e "/nVERY IMPORTANT: Before starting ZoneMinder, read README.Centos7 to finish the\ninstallation or upgrade!\n" -echo -e "/nThe README file is located here: %{_docdir}/%{name}-%{version}." +echo -e "\nVERY IMPORTANT: Before starting ZoneMinder, read README.Centos7 to finish the\ninstallation or upgrade!\n" +echo -e "\nThe README file is located here: %{_docdir}/%{name}-%{version}.\n" %preun if [ $1 -eq 0 ] ; then From 427c71f5e87d9263b31d32f621c173e1d2bbdaea Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Mon, 7 Sep 2015 16:54:13 -0500 Subject: [PATCH 8/9] Update README.Centos7 --- distros/redhat/README.Centos7 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/distros/redhat/README.Centos7 b/distros/redhat/README.Centos7 index 89fe9736c..70e98b006 100644 --- a/distros/redhat/README.Centos7 +++ b/distros/redhat/README.Centos7 @@ -14,6 +14,8 @@ What's New 3. This package now requires the HTTPS protocol to access the web portal. Requests using HTTP will auto-redirect to HTTPS. See README.https for more information. + +4. This package ships with the new ZoneMinder API enabled. New installs ============ From ebb6e7158ac497813e1f09de2d45adcbfb2b5522 Mon Sep 17 00:00:00 2001 From: Andrew Bauer Date: Tue, 8 Sep 2015 18:16:19 -0500 Subject: [PATCH 9/9] rpm packaging changes for centos 6 --- distros/redhat/README.CentOS | 101 +++++++++++++++++++------- distros/redhat/zoneminder.el6.conf.in | 22 +++--- distros/redhat/zoneminder.el6.spec | 23 +++++- 3 files changed, 103 insertions(+), 43 deletions(-) diff --git a/distros/redhat/README.CentOS b/distros/redhat/README.CentOS index 640d11ad1..05e2cb0ab 100644 --- a/distros/redhat/README.CentOS +++ b/distros/redhat/README.CentOS @@ -1,6 +1,22 @@ -================================================================================ - NEW INSTALLS -================================================================================ +What's New +========== + +1. The ZoneMinder mysql account now requires "Create" permission. This change + must be done manually before ZoneMinder will run. See the installation steps + below. + +2. A new permission group called "Groups" has been added. This allows the + system administrator to assign "view", "edit", or "none" permission to + normal users, without giving them access to the rest of the ZoneMinder + system. During an upgrade, existing accounts will default to a Groups + permission of "none". + +3. This package now requires the HTTPS protocol to access the web portal. + Requests using HTTP will auto-redirect to HTTPS. See README.https for + more information. + +New installs +============ 1. Unless you are already using MySQL server, you need to ensure that the server is confired to start during boot and properly secured @@ -11,7 +27,8 @@ sudo chkconfig mysqld on 2. Using the password for the root account set during the previous step, you - will need to create the ZoneMinder database: + will need to create the ZoneMinder database and configure a database + account for ZoneMinder to use: mysql -uroot -p mysql> create database zm; @@ -21,20 +38,26 @@ mysql -uroot -p < /usr/share/zoneminder/db/zm_create.sql mysqladmin -uroot -p reload + The database account credentials, zmuser/zmpass, are arbitrary. Set them to + anything that suits your envinroment. + 3. If you have chosen to change the zoneminder mysql credentials to something other than zmuser/zmpass then you must now edit /etc/zm.conf. Change ZM_DB_USER and ZM_DB_PASS to the values you created in step 2. -4. IMPORTANT: Edit /etc/php.ini and put in the appropriate timezone for - date.timezone! +4. Edit /etc/php.ini, uncomment the date.timezone line, and add your local + timezone. PHP will complain loudly if this is not set, or if it is set + incorrectly, and these complaints will show up in the zoneminder logging + system as errors -5. The ZoneMinder web interface is disabled by default, you will need - to edit this file to enable it: + If you are not sure of the proper timezone specification to use, look at + http://php.net/date.timezone + +5. Verify the default ZoneMinder Apache configuration meets your needs: /etc/httpd/conf.d/zoneminder.conf - HINT: Most users will want to simply delete the line that says - "Deny from all". + When in doubt, leave this configuration as it is. 6. Configure the web server to start automatically: @@ -45,8 +68,8 @@ called local_zoneminder. A copy of this policy is in the documentation folder. - Unfortunately, this has not resolved all the SELinux issues so - most will want to disable SELinux permanently by editing the following: + It is still possible to run into SELinux issues, however. If this is case, + you can disable SELinux permanently by editing the following: /etc/selinux/conf @@ -66,27 +89,49 @@ UPGRADES ================================================================================ -1. Add additional permissions to the zmuser account: +1. Verify /etc/zm.conf. + + If zm.conf was manually edited before running the upgrade, the installation + may not overwrite it. In this case, it will create the file + /etc/zm.conf.rpmnew. + + For example, this will happen if you are using database account credentials + other than zmuser/zmpass. + + Compare /etc/zm.conf to /etc/zm.conf.rpmnew. Verify that zm.conf + contains any new config settings that may be in zm.conf.rpmnew. + +2. Verify permissions of the zmuser account. + + Over time, the database account permissions required for normal operation + have changed. Verify the zmuser database account has been granted select, + insert, update, delete, lock tables, alter, and create permission to the + ZoneMinder database: mysql -u root -p - grant lock tables,alter,create on zm.* to - 'zmuser'@localhost identified by 'zmpass'; + mysql> show grants for zmuser@localhost; + mysql> exit; - Since this is an upgrade, the assumption is that the zmuser account exists - and already has select, insert, update, and delete permission. + See step 2 of the Installation section to add missing permissions. + +3. Verify the ZoneMinder Apache configuration file in the folder + /etc/httpd/conf.d. You will have a file called "zoneminder.conf" and there + may also be a file called "zoneminder.conf.rpmnew". If the rpmnew file + exists, inspect it and merge anything new in that file with zoneminder.conf. + +4. Upgrade the database before starting ZoneMinder. + + Most upgrades can be performed by executing the following command: -2. If you have previsouly changed the zoneminder mysql credentials to something - other than zmuser/zmpass then you must now edit /etc/zm.conf. Change - ZM_DB_USER and ZM_DB_PASS to their appropriate values. - -3. You will need to upgrade the ZoneMinder database as described in the manual. - Only if step 1 was succesfully applied, may you run zmupdate like so: - - sudo zmupdate.pl --version= - - - If unsure then run it this way: + sudo zmupdate.pl + + Recent versions of ZoneMinder don't require any parameters added to the + zmupdate command. However, if ZoneMinder complains, you may need to call + zmupdate in the following manner: sudo zmupdate.pl --user=root --pass= --version= +5. Now start zoneminder: + + sudo service zoneminder start diff --git a/distros/redhat/zoneminder.el6.conf.in b/distros/redhat/zoneminder.el6.conf.in index 61e0530f8..e0808e08b 100644 --- a/distros/redhat/zoneminder.el6.conf.in +++ b/distros/redhat/zoneminder.el6.conf.in @@ -1,26 +1,26 @@ -# When using Zoneminder's own authentication, recorded CCTV images are -# accessible from the web directly without passing the authentication. This -# means any attacker could see your CCTV images without a password. In order -# to avoid this you can disable Zoneminder's authentication and configure -# standard Apache authentication (see the Apache documentation for details on -# this). # -# If you still wish to use Zoneminder's own authentication, or have an -# internal site which needs no authentication, you need to delete the line -# marked below and restart Apache. +# ZoneMinder Apache configuration file +# With SSLRequire and HTTPS auto redirect +# Modify this configuration to suit your requirements +# + +# Auto Redirect HTTP requests to HTTPS +RewriteEngine On +RewriteCond %{HTTPS} !=on +RewriteRule ^/?(zm)(.*) https://%{SERVER_NAME}/$1$2 [R,L] Alias /zm "@ZM_WEBDIR@" + SSLRequireSSL Options -Indexes MultiViews FollowSymLinks AllowOverride All Order allow,deny Allow from all - # ZoneMinder no longer uses short tags so this is safe to leave disabled - # php_value short_open_tag 1 ScriptAlias /cgi-bin/zm "@ZM_WEBDIR@" + SSLRequireSSL AllowOverride All Options ExecCGI FollowSymLinks Order allow,deny diff --git a/distros/redhat/zoneminder.el6.spec b/distros/redhat/zoneminder.el6.spec index 1d6d5ead1..d9487e480 100644 --- a/distros/redhat/zoneminder.el6.spec +++ b/distros/redhat/zoneminder.el6.spec @@ -30,8 +30,8 @@ BuildRequires: libcurl-devel vlc-devel ffmpeg-devel polkit-devel # cmake needs the following installed at build time due to the way it auto-detects certain parameters BuildRequires: httpd ffmpeg -Requires: httpd php php-gd php-mysql mysql-server libjpeg-turbo polkit net-tools psmisc -Requires: perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version)) +Requires: httpd php php-gd php-mysql mysql-server libjpeg-turbo polkit net-tools mod_ssl +Requires: psmisc perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version)) Requires: perl(DBD::mysql) perl(Archive::Tar) perl(Archive::Zip) Requires: perl(MIME::Entity) perl(MIME::Lite) perl(Net::SMTP) perl(Net::FTP) Requires: libcurl vlc-core ffmpeg @@ -96,8 +96,20 @@ echo -e "\nCreating and installing a ZoneMinder SELinux policy module. Please wa /usr/bin/semodule_package -o %{_docdir}/%{name}-%{version}/local_zoneminder.pp -m %{_docdir}/%{name}-%{version}/local_zoneminder.mod > /dev/null /usr/sbin/semodule -i %{_docdir}/%{name}-%{version}/local_zoneminder.pp > /dev/null -# Display the README for post installation instructions -/usr/bin/less %{_docdir}/%{name}-%{version}/README.CentOS +# Upgrade from a previous version of zoneminder +if [ $1 -eq 2 ] ; then + # Freshen the database + /usr/bin/zmupdate.pl -f + + # We can't run this automatically when new sql account permissions need to + # be manually added first + # Run zmupdate non-interactively + #/usr/bin/zmupdate.pl --nointeractive +fi + +# Warn the end user to read the README file +echo -e "\nVERY IMPORTANT: Before starting ZoneMinder, read README.Centos to finish the\ninstallation or upgrade!\n" +echo -e "\nThe README file is located here: %{_docdir}/%{name}-%{version}.\n" %preun if [ $1 -eq 0 ]; then @@ -170,6 +182,9 @@ rm -rf %{_docdir}/%{name}-%{version} %dir %attr(755,%{zmuid_final},%{zmgid_final}) %{_localstatedir}/spool/zoneminder-upload %changelog +* Tue Sep 8 2015 Andrew Bauer - 1.28.1 +- Require https, freshen dB on updates. + * Wed Feb 18 2015 Andrew Bauer - 1.28.1 - Include ONVIF support files