/src/samba/librpc/ndr/uuid.c
Line | Count | Source |
1 | | /* |
2 | | Unix SMB/CIFS implementation. |
3 | | |
4 | | UUID/GUID functions |
5 | | |
6 | | Copyright (C) Theodore Ts'o 1996, 1997, |
7 | | Copyright (C) Jim McDonough 2002. |
8 | | Copyright (C) Andrew Tridgell 2003. |
9 | | |
10 | | This program is free software; you can redistribute it and/or modify |
11 | | it under the terms of the GNU General Public License as published by |
12 | | the Free Software Foundation; either version 3 of the License, or |
13 | | (at your option) any later version. |
14 | | |
15 | | This program is distributed in the hope that it will be useful, |
16 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
18 | | GNU General Public License for more details. |
19 | | |
20 | | You should have received a copy of the GNU General Public License |
21 | | along with this program. If not, see <http://www.gnu.org/licenses/>. |
22 | | */ |
23 | | |
24 | | #include "replace.h" |
25 | | #include "lib/util/debug.h" |
26 | | #include "lib/util/samba_util.h" |
27 | | #include "lib/util/genrand.h" |
28 | | #include "librpc/ndr/libndr.h" |
29 | | #include "librpc/gen_ndr/ndr_misc.h" |
30 | | #include "lib/util/util_str_hex.h" |
31 | | |
32 | | _PUBLIC_ void GUID_to_ndr_buf(const struct GUID *guid, |
33 | | struct GUID_ndr_buf *buf) |
34 | 0 | { |
35 | 0 | DATA_BLOB b = { .data = buf->buf, .length = sizeof(buf->buf), }; |
36 | 0 | enum ndr_err_code ndr_err; |
37 | |
|
38 | 0 | ndr_err = ndr_push_struct_into_fixed_blob( |
39 | 0 | &b, guid, (ndr_push_flags_fn_t)ndr_push_GUID); |
40 | 0 | SMB_ASSERT(NDR_ERR_CODE_IS_SUCCESS(ndr_err)); |
41 | 0 | } |
42 | | |
43 | | /** |
44 | | build a NDR blob from a GUID |
45 | | */ |
46 | | _PUBLIC_ NTSTATUS GUID_to_ndr_blob(const struct GUID *guid, TALLOC_CTX *mem_ctx, DATA_BLOB *b) |
47 | 0 | { |
48 | 0 | struct GUID_ndr_buf buf = { .buf = {0}, }; |
49 | |
|
50 | 0 | GUID_to_ndr_buf(guid, &buf); |
51 | |
|
52 | 0 | *b = data_blob_talloc(mem_ctx, buf.buf, sizeof(buf.buf)); |
53 | 0 | if (b->data == NULL) { |
54 | 0 | return NT_STATUS_NO_MEMORY; |
55 | 0 | } |
56 | 0 | return NT_STATUS_OK; |
57 | 0 | } |
58 | | |
59 | | |
60 | | /** |
61 | | build a GUID from a NDR data blob |
62 | | */ |
63 | | _PUBLIC_ NTSTATUS GUID_from_ndr_blob(const DATA_BLOB *b, struct GUID *guid) |
64 | 0 | { |
65 | 0 | enum ndr_err_code ndr_err = |
66 | 0 | ndr_pull_struct_blob_all_noalloc(b, guid, |
67 | 0 | (ndr_pull_flags_fn_t)ndr_pull_GUID); |
68 | 0 | return ndr_map_error2ntstatus(ndr_err); |
69 | 0 | } |
70 | | |
71 | | |
72 | | /** |
73 | | build a GUID from a string |
74 | | */ |
75 | | _PUBLIC_ NTSTATUS GUID_from_data_blob(const DATA_BLOB *s, struct GUID *guid) |
76 | 98.3k | { |
77 | 98.3k | bool ok; |
78 | | |
79 | 98.3k | if (s->data == NULL) { |
80 | 0 | return NT_STATUS_INVALID_PARAMETER; |
81 | 0 | } |
82 | | |
83 | 98.3k | if (s->length == 36) { |
84 | 3.92k | ok = parse_guid_string((char *)s->data, guid); |
85 | 3.92k | return ok ? NT_STATUS_OK : NT_STATUS_INVALID_PARAMETER; |
86 | 3.92k | } |
87 | | |
88 | 94.4k | if (s->length == 38) { |
89 | 94.4k | if (s->data[0] != '{' || s->data[37] != '}') { |
90 | 0 | return NT_STATUS_INVALID_PARAMETER; |
91 | 0 | } |
92 | 94.4k | ok = parse_guid_string((char *)s->data + 1, guid); |
93 | 94.4k | return ok ? NT_STATUS_OK : NT_STATUS_INVALID_PARAMETER; |
94 | 94.4k | } |
95 | | |
96 | 0 | if (s->length == 32) { |
97 | 0 | uint8_t buf16[16] = {0}; |
98 | 0 | DATA_BLOB blob16 = { .data = buf16, .length = sizeof(buf16) }; |
99 | 0 | size_t rlen = strhex_to_str((char *)blob16.data, blob16.length, |
100 | 0 | (const char *)s->data, s->length); |
101 | 0 | if (rlen != blob16.length) { |
102 | 0 | return NT_STATUS_INVALID_PARAMETER; |
103 | 0 | } |
104 | | |
105 | 0 | return GUID_from_ndr_blob(&blob16, guid); |
106 | 0 | } |
107 | | |
108 | 0 | if (s->length == 16) { |
109 | 0 | return GUID_from_ndr_blob(s, guid); |
110 | 0 | } |
111 | | |
112 | 0 | return NT_STATUS_INVALID_PARAMETER; |
113 | 0 | } |
114 | | |
115 | | /** |
116 | | build a GUID from a string |
117 | | */ |
118 | | _PUBLIC_ NTSTATUS GUID_from_string(const char *s, struct GUID *guid) |
119 | 94.9k | { |
120 | 94.9k | DATA_BLOB blob = data_blob_string_const(s); |
121 | 94.9k | return GUID_from_data_blob(&blob, guid); |
122 | 94.9k | } |
123 | | |
124 | | /** |
125 | | * generate a random GUID |
126 | | */ |
127 | | _PUBLIC_ struct GUID GUID_random(void) |
128 | 0 | { |
129 | 0 | struct GUID guid; |
130 | |
|
131 | 0 | generate_random_buffer((uint8_t *)&guid, sizeof(guid)); |
132 | 0 | guid.clock_seq[0] = (guid.clock_seq[0] & 0x3F) | 0x80; |
133 | 0 | guid.time_hi_and_version = (guid.time_hi_and_version & 0x0FFF) | 0x4000; |
134 | |
|
135 | 0 | return guid; |
136 | 0 | } |
137 | | |
138 | | /** |
139 | | * generate an empty GUID |
140 | | */ |
141 | | _PUBLIC_ struct GUID GUID_zero(void) |
142 | 3.39k | { |
143 | 3.39k | return (struct GUID) { .time_low = 0 }; |
144 | 3.39k | } |
145 | | |
146 | | _PUBLIC_ bool GUID_all_zero(const struct GUID *u) |
147 | 5.19k | { |
148 | 5.19k | if (u->time_low != 0 || |
149 | 4.04k | u->time_mid != 0 || |
150 | 3.70k | u->time_hi_and_version != 0 || |
151 | 3.46k | u->clock_seq[0] != 0 || |
152 | 3.21k | u->clock_seq[1] != 0 || |
153 | 2.99k | !all_zero(u->node, 6)) { |
154 | 2.43k | return false; |
155 | 2.43k | } |
156 | 2.75k | return true; |
157 | 5.19k | } |
158 | | |
159 | | _PUBLIC_ bool GUID_equal(const struct GUID *u1, const struct GUID *u2) |
160 | 96.4k | { |
161 | 96.4k | return (GUID_compare(u1, u2) == 0); |
162 | 96.4k | } |
163 | | |
164 | | _PUBLIC_ int GUID_compare(const struct GUID *u1, const struct GUID *u2) |
165 | 96.4k | { |
166 | 96.4k | if (u1->time_low != u2->time_low) { |
167 | 93.8k | return u1->time_low > u2->time_low ? 1 : -1; |
168 | 93.8k | } |
169 | | |
170 | 2.65k | if (u1->time_mid != u2->time_mid) { |
171 | 301 | return u1->time_mid > u2->time_mid ? 1 : -1; |
172 | 301 | } |
173 | | |
174 | 2.35k | if (u1->time_hi_and_version != u2->time_hi_and_version) { |
175 | 185 | return u1->time_hi_and_version > u2->time_hi_and_version ? 1 : -1; |
176 | 185 | } |
177 | | |
178 | 2.16k | if (u1->clock_seq[0] != u2->clock_seq[0]) { |
179 | 206 | return u1->clock_seq[0] > u2->clock_seq[0] ? 1 : -1; |
180 | 206 | } |
181 | | |
182 | 1.95k | if (u1->clock_seq[1] != u2->clock_seq[1]) { |
183 | 120 | return u1->clock_seq[1] > u2->clock_seq[1] ? 1 : -1; |
184 | 120 | } |
185 | | |
186 | 1.83k | return memcmp(u1->node, u2->node, 6); |
187 | 1.95k | } |
188 | | |
189 | | /** |
190 | | its useful to be able to display these in debugging messages |
191 | | */ |
192 | | _PUBLIC_ char *GUID_string(TALLOC_CTX *mem_ctx, const struct GUID *guid) |
193 | 2.22k | { |
194 | 2.22k | struct GUID_txt_buf buf; |
195 | 2.22k | return talloc_strdup(mem_ctx, GUID_buf_string(guid, &buf)); |
196 | 2.22k | } |
197 | | |
198 | | /** |
199 | | * Does the same without allocating memory, using the structure buffer. |
200 | | * Useful for debug messages, so that you do not have to talloc_free the result |
201 | | */ |
202 | | _PUBLIC_ char* GUID_buf_string(const struct GUID *guid, |
203 | | struct GUID_txt_buf *dst) |
204 | 712k | { |
205 | 712k | if (!guid) { |
206 | 0 | return NULL; |
207 | 0 | } |
208 | | |
209 | 712k | if (sizeof(dst->buf) < 37) { |
210 | 0 | return NULL; |
211 | 0 | } |
212 | | |
213 | 712k | dst->buf[0] = nybble_to_hex_lower(guid->time_low >> 28); |
214 | 712k | dst->buf[1] = nybble_to_hex_lower(guid->time_low >> 24); |
215 | 712k | dst->buf[2] = nybble_to_hex_lower(guid->time_low >> 20); |
216 | 712k | dst->buf[3] = nybble_to_hex_lower(guid->time_low >> 16); |
217 | 712k | dst->buf[4] = nybble_to_hex_lower(guid->time_low >> 12); |
218 | 712k | dst->buf[5] = nybble_to_hex_lower(guid->time_low >> 8); |
219 | 712k | dst->buf[6] = nybble_to_hex_lower(guid->time_low >> 4); |
220 | 712k | dst->buf[7] = nybble_to_hex_lower(guid->time_low); |
221 | | |
222 | 712k | dst->buf[8] = '-'; |
223 | | |
224 | 712k | dst->buf[9] = nybble_to_hex_lower(guid->time_mid >> 12); |
225 | 712k | dst->buf[10] = nybble_to_hex_lower(guid->time_mid >> 8); |
226 | 712k | dst->buf[11] = nybble_to_hex_lower(guid->time_mid >> 4); |
227 | 712k | dst->buf[12] = nybble_to_hex_lower(guid->time_mid); |
228 | | |
229 | 712k | dst->buf[13] = '-'; |
230 | | |
231 | 712k | dst->buf[14] = nybble_to_hex_lower(guid->time_hi_and_version >> 12); |
232 | 712k | dst->buf[15] = nybble_to_hex_lower(guid->time_hi_and_version >> 8); |
233 | 712k | dst->buf[16] = nybble_to_hex_lower(guid->time_hi_and_version >> 4); |
234 | 712k | dst->buf[17] = nybble_to_hex_lower(guid->time_hi_and_version); |
235 | | |
236 | 712k | dst->buf[18] = '-'; |
237 | | |
238 | 712k | dst->buf[19] = nybble_to_hex_lower(guid->clock_seq[0] >> 4); |
239 | 712k | dst->buf[20] = nybble_to_hex_lower(guid->clock_seq[0]); |
240 | 712k | dst->buf[21] = nybble_to_hex_lower(guid->clock_seq[1] >> 4); |
241 | 712k | dst->buf[22] = nybble_to_hex_lower(guid->clock_seq[1]); |
242 | | |
243 | 712k | dst->buf[23] = '-'; |
244 | | |
245 | 712k | dst->buf[24] = nybble_to_hex_lower(guid->node[0] >> 4); |
246 | 712k | dst->buf[25] = nybble_to_hex_lower(guid->node[0]); |
247 | 712k | dst->buf[26] = nybble_to_hex_lower(guid->node[1] >> 4); |
248 | 712k | dst->buf[27] = nybble_to_hex_lower(guid->node[1]); |
249 | 712k | dst->buf[28] = nybble_to_hex_lower(guid->node[2] >> 4); |
250 | 712k | dst->buf[29] = nybble_to_hex_lower(guid->node[2]); |
251 | 712k | dst->buf[30] = nybble_to_hex_lower(guid->node[3] >> 4); |
252 | 712k | dst->buf[31] = nybble_to_hex_lower(guid->node[3]); |
253 | 712k | dst->buf[32] = nybble_to_hex_lower(guid->node[4] >> 4); |
254 | 712k | dst->buf[33] = nybble_to_hex_lower(guid->node[4]); |
255 | 712k | dst->buf[34] = nybble_to_hex_lower(guid->node[5] >> 4); |
256 | 712k | dst->buf[35] = nybble_to_hex_lower(guid->node[5]); |
257 | | |
258 | 712k | dst->buf[36] = '\0'; |
259 | | |
260 | 712k | return dst->buf; |
261 | 712k | } |
262 | | |
263 | | _PUBLIC_ char *GUID_string2(TALLOC_CTX *mem_ctx, const struct GUID *guid) |
264 | 0 | { |
265 | 0 | struct GUID_txt_buf buf; |
266 | 0 | char *ret = talloc_asprintf( |
267 | 0 | mem_ctx, "{%s}", GUID_buf_string(guid, &buf)); |
268 | 0 | return ret; |
269 | 0 | } |
270 | | |
271 | | _PUBLIC_ char *GUID_hexstring(TALLOC_CTX *mem_ctx, const struct GUID *guid) |
272 | 0 | { |
273 | 0 | char *ret = NULL; |
274 | 0 | DATA_BLOB guid_blob = { .data = NULL }; |
275 | 0 | NTSTATUS status; |
276 | |
|
277 | 0 | status = GUID_to_ndr_blob(guid, mem_ctx, &guid_blob); |
278 | 0 | if (NT_STATUS_IS_OK(status)) { |
279 | 0 | ret = data_blob_hex_string_upper(mem_ctx, &guid_blob); |
280 | 0 | } |
281 | 0 | TALLOC_FREE(guid_blob.data); |
282 | 0 | return ret; |
283 | 0 | } |
284 | | |
285 | | _PUBLIC_ bool ndr_policy_handle_empty(const struct policy_handle *h) |
286 | 0 | { |
287 | 0 | return (h->handle_type == 0 && GUID_all_zero(&h->uuid)); |
288 | 0 | } |
289 | | |
290 | | _PUBLIC_ bool ndr_policy_handle_equal(const struct policy_handle *hnd1, |
291 | | const struct policy_handle *hnd2) |
292 | 0 | { |
293 | 0 | if (!hnd1 || !hnd2) { |
294 | 0 | return false; |
295 | 0 | } |
296 | | |
297 | 0 | return (memcmp(hnd1, hnd2, sizeof(*hnd1)) == 0); |
298 | 0 | } |