summaryrefslogtreecommitdiff
path: root/lib/Kolab/FreeBusy/HTTPAuth.php
blob: ad0c39416bd4a7eef3a6a9ca869cbfd24df6b190 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
<?php

namespace Kolab\FreeBusy;

use \Net_LDAP3;
use \Monolog\Logger as Monolog;

/**
 * Static class to process HTTP authentication to this service
 */
class HTTPAuth
{
	private static $logger;

	/**
	 * Validate HTTP basic auth against the configured backend
	 */
	public static function check($config)
	{
		$logger = Logger::get('httpauth');

		// no http auth submitted, abort!
		if (empty($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW'])) {
			$logger->addDebug('No HTTP auth submitted');
			return false;
		}
			
		switch ($config['type']) {
			case 'static':
				return self::checkStatic($config, $_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']);

			case 'ldap':
				return self::checkLDAP($config, $_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW']);

			default:
				$logger->addWarning('Unsupported auth type ' . $config['type']);
				break;
		}

		return false;
	}

	/**
	 * Validate static user credentials from config
	 */
	private static function checkStatic($config, $user, $pass)
	{
		$valid = $user == $config['username'] && $pass == $config['password'];
		Logger::get('httpauth')->addInfo("Static: authenticating user '$user': " . ($valid ? 'SUCCESS' : 'FAILURE'));
		return $valid;
	}

	/**
	 * Validate user credentials against the configured LDAP backend
	 */
	private static function checkLDAP($config, $user, $pass)
	{
		self::$logger = Logger::get('httpauth', intval($config['loglevel']));

		$host = parse_url($config['host']);
		$ldap_config = array(
			'hosts'   => array($host['host']),
			'port'    => $host['port'] ?: 389,
			'use_tls' => $host['scheme'] == 'tls' || $host['scheme'] == 'ldaps',
			'root_dn' => $config['base_dn'],
			'filter'  => $config['filter'],
			'service_bind_dn' => $config['bind_dn'],
			'service_bind_pw' => $config['bind_pw'],
			'sizelimit' => 0,
			'timelimit' => 0,
		);

		// instantiate Net_LDAP3 and connect with logger
		$ldap = new Net_LDAP3($ldap_config);
		$ldap->config_set('log_hook', 'Kolab\FreeBusy\HTTPAuth::ldapLog');

		// connect + bind to LDAP server
		if ($ldap->connect()) {
			self::$logger->addDebug("LDAP: connected to $config[host] with '$config[bind_dn]'");

			// extract domain part from base_dn
			$dn_domain = ldap_explode_dn($config['base_dn'], 1);
			unset($dn_domain['count']);
			$domain = join('.', $dn_domain);

			$valid = (bool)$ldap->login($user, $pass, $domain);
		}
		else {
			self::$logger->addWarning("LDAP: connectiion to $config[host] with '$config[bind_dn]' failed!");
		}

		self::$logger->addInfo("LDAP: authenticating user '$user': " . ($valid ? 'SUCCESS' : 'FAILURE'));
		return $valid;
	}

	/**
	 * Callback for Net_LDAP3 logging
	 */
	public static function ldapLog($level, $msg)
	{
		// map PHP log levels to Monolog levels
		static $loglevels = array(
			LOG_DEBUG   => Monolog::DEBUG,
			LOG_NOTICE  => Monolog::NOTICE,
			LOG_INFO    => Monolog::INFO,
			LOG_WARNING => Monolog::WARNING,
			LOG_ERR     => Monolog::ERROR,
			LOG_CRIT    => Monolog::CRITICAL,
			LOG_ALERT   => Monolog::ALERT,
			LOG_EMERG   => Monolog::EMERGENCY,
		);

		$msg = is_array($msg) ? join('; ', $msg) : strval($msg);
		self::$logger->addRecord($loglevels[$level], $msg);
	}

}