summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Burschka2014-11-16 14:01:10 +0100
committerChristoph Burschka2014-11-16 14:01:10 +0100
commitb54236dceeedbf33796dcdb8319bc72f923584bb (patch)
tree04a69e3cd48b0b34fa80dee69adca289d9dbd530
parentUpdate README for ejabberd 13.10+ (diff)
downloadejabberd-auth-php-b54236dceeedbf33796dcdb8319bc72f923584bb.tar.gz
Fix #8: Add htpasswd authentication
ejabberd can now authenticate against Apache auth files.
-rw-r--r--plugins/htpasswd/BridgeHtpasswd.php19
-rw-r--r--plugins/htpasswd/README.md28
-rw-r--r--plugins/htpasswd/htpasswd.inc75
-rw-r--r--plugins/htpasswd/htpasswd.module18
4 files changed, 140 insertions, 0 deletions
diff --git a/plugins/htpasswd/BridgeHtpasswd.php b/plugins/htpasswd/BridgeHtpasswd.php
new file mode 100644
index 0000000..51b6a94
--- /dev/null
+++ b/plugins/htpasswd/BridgeHtpasswd.php
@@ -0,0 +1,19 @@
+<?php
+
+/**
+ * Implements EjabberdAuthBridge.
+ */
+class BridgeHtpasswd extends EjabberdAuthBridge {
+ function __construct($data, $config) {
+ $this->data = $data;
+ $this->config = $config;
+ }
+
+ function isuser($username, $server) {
+ return array_key_exists($username, $this->data);
+ }
+
+ function auth($username, $server, $password) {
+ return $this->isuser($username, $server) && htpasswd_check($password, $this->data[$username], $this->config);
+ }
+}
diff --git a/plugins/htpasswd/README.md b/plugins/htpasswd/README.md
new file mode 100644
index 0000000..0b78bd6
--- /dev/null
+++ b/plugins/htpasswd/README.md
@@ -0,0 +1,28 @@
+htpasswd
+========
+
+This plugin can parse an Apache authentication file
+generated by htpasswd.
+
+The following hash types are supported:
+
+- APR-MD5 ("htpasswd [-m]", default method)
+- SHA1 ("htpasswd -s")
+- Blowfish ("htpasswd -B")
+- DES ("htpasswd -d")
+- Plaintext ("htpasswd -s")
+
+Note that DES and Plaintext are mutually exclusive, because
+the format is not readily distinguishable. Any hash that does
+not match the MD5, SHA1 or Blowfish formats will be treated as
+a DES hash or a plaintext password depending on configuration.
+
+Installation
+------------
+
+This configuration must be entered into plugin_conf in config.php:
+
+ 'plugin_conf' => [
+ 'htpasswd_file' => '</path/to/htpasswd/file>',
+ 'plain' => FALSE, // optional
+ ]
diff --git a/plugins/htpasswd/htpasswd.inc b/plugins/htpasswd/htpasswd.inc
new file mode 100644
index 0000000..903940b
--- /dev/null
+++ b/plugins/htpasswd/htpasswd.inc
@@ -0,0 +1,75 @@
+<?php
+
+function htpasswd_check($clear, $hash, $config) {
+ /* htpasswd supports the following hashing methods:
+ * - MD5 (standard)
+ * - blowfish
+ * - crypt (DES)
+ * - sha1
+ * - plain
+ *
+ * All but the Apache-specific MD5 implementation
+ * are available in PHP.
+ */
+
+ if (preg_match('/^\$apr1\$(.*?)\$.*$/', $hash, $match)) {
+ $result = htpasswd_apr_md5($clear, $match[1]);
+ }
+ elseif (preg_match('/^\$2y\$.*$/', $hash, $match)) {
+ $result = crypt($clear, $match[0]);
+ }
+ elseif (preg_match('/^\{SHA\}.*$/', $hash, $match)) {
+ $result = '{SHA}' . base64_encode(sha1($clear, TRUE));
+ }
+
+ // The crypt and clear formats are not distinguishable.
+ elseif (empty($config['plain'])) {
+ $result = crypt($clear, $hash);
+ }
+ else {
+ $result = $clear;
+ }
+
+ return hash_equals($result, $hash);
+}
+
+/**
+ * Parts of this APR-MD5 implementation are derived from
+ * an example at http://php.net/crypt
+ */
+function htpasswd_apr_md5($clear, $salt) {
+ $len = strlen($clear);
+ $text = $clear . '$apr1$' . $salt;
+ $bin = pack('H32', md5($clear . $salt . $clear));
+ for($i = $len; $i > 0; $i -= 16) {
+ $text .= substr($bin, 0, min(16, $i));
+ }
+ for($i = $len; $i > 0; $i >>= 1) {
+ $text .= ($i & 1) ? chr(0) : $clear{0};
+ }
+ $bin = pack("H32", md5($text));
+
+ for($i = 0; $i < 1000; $i++) {
+ $new = ($i & 1) ? $clear : $bin;
+ if ($i % 3) $new .= $salt;
+ if ($i % 7) $new .= $clear;
+ $new .= ($i & 1) ? $bin : $clear;
+ $bin = pack("H32", md5($new));
+ }
+
+ $tmp = '';
+ for ($i = 0; $i < 5; $i++) {
+ $k = $i + 6;
+ $j = $i + 12;
+ if ($j == 16) {
+ $j = 5;
+ }
+ $tmp = $bin[$i] . $bin[$k] . $bin[$j] . $tmp;
+ }
+
+ $tmp = chr(0) . chr(0) . $bin[11] . $tmp;
+ $tmp = strtr(strrev(substr(base64_encode($tmp), 2)),
+ 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
+ './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz');
+ return '$apr1$' . $salt . '$' . $tmp;
+}
diff --git a/plugins/htpasswd/htpasswd.module b/plugins/htpasswd/htpasswd.module
new file mode 100644
index 0000000..b97de52
--- /dev/null
+++ b/plugins/htpasswd/htpasswd.module
@@ -0,0 +1,18 @@
+<?php
+
+function htpasswd_init($config) {
+ $data = array();
+ $file = $config['htpasswd_file'];
+ if (file_exists($file) && is_readable($file)) {
+ $lines = explode("\n", trim(file_get_contents($file)));
+ foreach ($lines as $line) {
+ list($user, $password) = explode(":", trim($line), 2);
+ $data[$user] = $password;
+ }
+ }
+
+ // Load the plugin.
+ require_once __DIR__ . '/BridgeHtpasswd.php';
+ require_once __DIR__ . '/htpasswd.inc';
+ return new BridgeHtpasswd($data, $config);
+}