blob: 0f0ca3c7c579a3fb7aba078fdfa3696fc9c2a5c7 [file] [log] [blame]
Matthias Andreas Benkard7b2a3a12021-08-16 10:57:25 +02001<?php
2
3namespace LdapRecord;
4
5class Utilities
6{
7 /**
8 * Converts a DN string into an array of RDNs.
9 *
10 * This will also decode hex characters into their true
11 * UTF-8 representation embedded inside the DN as well.
12 *
13 * @param string $dn
14 * @param bool $removeAttributePrefixes
15 *
16 * @return array|false
17 */
18 public static function explodeDn($dn, $removeAttributePrefixes = true)
19 {
20 $dn = ldap_explode_dn($dn, ($removeAttributePrefixes ? 1 : 0));
21
22 if (! is_array($dn)) {
23 return false;
24 }
25
26 if (! array_key_exists('count', $dn)) {
27 return false;
28 }
29
30 unset($dn['count']);
31
32 foreach ($dn as $rdn => $value) {
33 $dn[$rdn] = static::unescape($value);
34 }
35
36 return $dn;
37 }
38
39 /**
40 * Un-escapes a hexadecimal string into its original string representation.
41 *
42 * @param string $value
43 *
44 * @return string
45 */
46 public static function unescape($value)
47 {
48 return preg_replace_callback('/\\\([0-9A-Fa-f]{2})/', function ($matches) {
49 return chr(hexdec($matches[1]));
50 }, $value);
51 }
52
53 /**
54 * Convert a binary SID to a string SID.
55 *
56 * @author Chad Sikorra
57 *
58 * @see https://github.com/ChadSikorra
59 * @see https://stackoverflow.com/questions/39533560/php-ldap-get-user-sid
60 *
61 * @param string $value The Binary SID
62 *
63 * @return string|null
64 */
65 public static function binarySidToString($value)
66 {
67 // Revision - 8bit unsigned int (C1)
68 // Count - 8bit unsigned int (C1)
69 // 2 null bytes
70 // ID - 32bit unsigned long, big-endian order
71 $sid = @unpack('C1rev/C1count/x2/N1id', $value);
72
73 if (! isset($sid['id']) || ! isset($sid['rev'])) {
74 return;
75 }
76
77 $revisionLevel = $sid['rev'];
78
79 $identifierAuthority = $sid['id'];
80
81 $subs = isset($sid['count']) ? $sid['count'] : 0;
82
83 $sidHex = $subs ? bin2hex($value) : '';
84
85 $subAuthorities = [];
86
87 // The sub-authorities depend on the count, so only get as
88 // many as the count, regardless of data beyond it.
89 for ($i = 0; $i < $subs; $i++) {
90 $data = implode(array_reverse(
91 str_split(
92 substr($sidHex, 16 + ($i * 8), 8),
93 2
94 )
95 ));
96
97 $subAuthorities[] = hexdec($data);
98 }
99
100 // Tack on the 'S-' and glue it all together...
101 return 'S-'.$revisionLevel.'-'.$identifierAuthority.implode(
102 preg_filter('/^/', '-', $subAuthorities)
103 );
104 }
105
106 /**
107 * Convert a binary GUID to a string GUID.
108 *
109 * @param string $binGuid
110 *
111 * @return string|null
112 */
113 public static function binaryGuidToString($binGuid)
114 {
115 if (trim($binGuid) == '' || is_null($binGuid)) {
116 return;
117 }
118
119 $hex = unpack('H*hex', $binGuid)['hex'];
120
121 $hex1 = substr($hex, -26, 2).substr($hex, -28, 2).substr($hex, -30, 2).substr($hex, -32, 2);
122 $hex2 = substr($hex, -22, 2).substr($hex, -24, 2);
123 $hex3 = substr($hex, -18, 2).substr($hex, -20, 2);
124 $hex4 = substr($hex, -16, 4);
125 $hex5 = substr($hex, -12, 12);
126
127 return sprintf('%s-%s-%s-%s-%s', $hex1, $hex2, $hex3, $hex4, $hex5);
128 }
129
130 /**
131 * Converts a string GUID to it's hex variant.
132 *
133 * @param string $string
134 *
135 * @return string
136 */
137 public static function stringGuidToHex($string)
138 {
139 $hex = '\\'.substr($string, 6, 2).'\\'.substr($string, 4, 2).'\\'.substr($string, 2, 2).'\\'.substr($string, 0, 2);
140 $hex = $hex.'\\'.substr($string, 11, 2).'\\'.substr($string, 9, 2);
141 $hex = $hex.'\\'.substr($string, 16, 2).'\\'.substr($string, 14, 2);
142 $hex = $hex.'\\'.substr($string, 19, 2).'\\'.substr($string, 21, 2);
143 $hex = $hex.'\\'.substr($string, 24, 2).'\\'.substr($string, 26, 2).'\\'.substr($string, 28, 2).'\\'.substr($string, 30, 2).'\\'.substr($string, 32, 2).'\\'.substr($string, 34, 2);
144
145 return $hex;
146 }
147
148 /**
149 * Round a Windows timestamp down to seconds and remove
150 * the seconds between 1601-01-01 and 1970-01-01.
151 *
152 * @param float $windowsTime
153 *
154 * @return float
155 */
156 public static function convertWindowsTimeToUnixTime($windowsTime)
157 {
158 return round($windowsTime / 10000000) - 11644473600;
159 }
160
161 /**
162 * Convert a Unix timestamp to Windows timestamp.
163 *
164 * @param float $unixTime
165 *
166 * @return float
167 */
168 public static function convertUnixTimeToWindowsTime($unixTime)
169 {
170 return ($unixTime + 11644473600) * 10000000;
171 }
172
173 /**
174 * Validates that the inserted string is an object SID.
175 *
176 * @param string $sid
177 *
178 * @return bool
179 */
180 public static function isValidSid($sid)
181 {
182 return (bool) preg_match("/^S-\d(-\d{1,10}){1,16}$/i", $sid);
183 }
184
185 /**
186 * Validates that the inserted string is an object GUID.
187 *
188 * @param string $guid
189 *
190 * @return bool
191 */
192 public static function isValidGuid($guid)
193 {
194 return (bool) preg_match('/^([0-9a-fA-F]){8}(-([0-9a-fA-F]){4}){3}-([0-9a-fA-F]){12}$/', $guid);
195 }
196}