summaryrefslogtreecommitdiff
path: root/src/web/helpers/ldap.php
blob: 46bbe691f924453f7eb5bb8798fe399f409150e4 (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
118
119
120
<?php /* Copyright (c) 2024 Freya Murphy */

class LDAPHelper {

	private ?\LDAP\Connection $conn;
	private array $env;
	private array $matchers;

	private ?string $bound;

	function __construct() {
		$this->env = array(
			# ldap host
			'url' =>  getenv("LDAP_URL"),
			# ldap credentials
			'bind' => getenv("LDAP_BIND_DN"),
			'password' => getenv("LDAP_BIND_PASSWORD"),
			# ldap search
			'base' => getenv("LDAP_BASE_DN"),
			'filter' => getenv("LDAP_FILTER"),
			'uid' => getenv("LDAP_UID"),
		);

		$this->matchers = array(
			'username' => getenv("LDAP_USERNAME_MATCHER"),
			'email' => getenv("LDAP_EMAIL_MATCHER"),
			'first_name' => getenv("LDAP_FIRST_NAME_MATCHER"),
			'last_name' => getenv("LDAP_LAST_NAME_MATCHER"),
		);

		$this->bound = NULL;
		$this->conn = NULL;
	}

	private function connect(): int {
		if (($this->conn = @ldap_connect($this->env['url'])) == FALSE) {
			$this->conn = NULL;
			return 1;
		}
		@ldap_set_option($this->conn, LDAP_OPT_PROTOCOL_VERSION, 3);
		return 0;
	}

	private function rebind(): int {
		if ($this->bound != $this->env['bind']) {
			return $this->bind(
				$this->env['bind'],
				$this->env['password']);
		}
		return 0;
	}

	public function bind(
		string $dn,
		#[\SensitiveParameter] string $password
	): int {
		if ($this->conn == NULL && $this->connect()) {
			return 1;
		}
		if (@ldap_bind($this->conn, $dn, $password) == FALSE) {
			return 1;
		}
		$this->bound = $dn;
		return 0;
	}

    /**
     * @param array<int,mixed> $user
     */
	private function find_entry(array $user, string $field): mixed {
		if (!isset($user[$field]))
			return NULL;
		$data = $user[$field];
		if (is_array($data))
			$data = $data[0];
		return $data;
	}

	public function search(
		string ...$usernames
	): ?array {
		if ($this->rebind())
			return NULL;

		$search = @ldap_search(
			$this->conn,
			$this->env['base'],
			$this->env['filter']
		);
		if ($search == FALSE)
			return NULL;

		$info = @ldap_get_entries($this->conn, $search);

		$users = array();

		for ($i=0; $i<$info['count']; $i++) {
			$user_arr = $info[$i];
			$user_data = array (
				'dn' => $user_arr['dn'],
				'username' => $this->find_entry($user_arr, $this->matchers['username']),
				'email' => $this->find_entry($user_arr, $this->matchers['email']),
				'first_name' => $this->find_entry($user_arr, $this->matchers['first_name']),
				'last_name' => $this->find_entry($user_arr, $this->matchers['last_name'])
			);
			$user = new User();
			if ($user->from_array($user_data)) {
				continue;
			}
			if (count($usernames) && !in_array($user->username, $usernames)) {
				continue;
			}
			$users[] = $user;
		}

		return $users;
	}

}