Line data Source code
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 109542998 : _PUBLIC_ void GUID_to_ndr_buf(const struct GUID *guid,
33 : struct GUID_ndr_buf *buf)
34 : {
35 109542998 : DATA_BLOB b = { .data = buf->buf, .length = sizeof(buf->buf), };
36 1427036 : enum ndr_err_code ndr_err;
37 :
38 109542998 : ndr_err = ndr_push_struct_into_fixed_blob(
39 : &b, guid, (ndr_push_flags_fn_t)ndr_push_GUID);
40 109542998 : SMB_ASSERT(NDR_ERR_CODE_IS_SUCCESS(ndr_err));
41 109542998 : }
42 :
43 : /**
44 : build a NDR blob from a GUID
45 : */
46 109459094 : _PUBLIC_ NTSTATUS GUID_to_ndr_blob(const struct GUID *guid, TALLOC_CTX *mem_ctx, DATA_BLOB *b)
47 : {
48 109459094 : struct GUID_ndr_buf buf = { .buf = {0}, };
49 :
50 109459094 : GUID_to_ndr_buf(guid, &buf);
51 :
52 109459094 : *b = data_blob_talloc(mem_ctx, buf.buf, sizeof(buf.buf));
53 109459094 : if (b->data == NULL) {
54 0 : return NT_STATUS_NO_MEMORY;
55 : }
56 109459094 : return NT_STATUS_OK;
57 : }
58 :
59 :
60 : /**
61 : build a GUID from a NDR data blob
62 : */
63 239169694 : _PUBLIC_ NTSTATUS GUID_from_ndr_blob(const DATA_BLOB *b, struct GUID *guid)
64 : {
65 5443658 : enum ndr_err_code ndr_err =
66 239169694 : ndr_pull_struct_blob_all_noalloc(b, guid,
67 : (ndr_pull_flags_fn_t)ndr_pull_GUID);
68 239169694 : return ndr_map_error2ntstatus(ndr_err);
69 : }
70 :
71 :
72 : /**
73 : build a GUID from a string
74 : */
75 120483376 : _PUBLIC_ NTSTATUS GUID_from_data_blob(const DATA_BLOB *s, struct GUID *guid)
76 : {
77 2654051 : bool ok;
78 :
79 120483376 : if (s->data == NULL) {
80 2 : return NT_STATUS_INVALID_PARAMETER;
81 : }
82 :
83 120483374 : if (s->length == 36) {
84 118623192 : ok = parse_guid_string((char *)s->data, guid);
85 118623192 : return ok ? NT_STATUS_OK : NT_STATUS_INVALID_PARAMETER;
86 : }
87 :
88 1860182 : if (s->length == 38) {
89 6526 : if (s->data[0] != '{' || s->data[37] != '}') {
90 0 : return NT_STATUS_INVALID_PARAMETER;
91 : }
92 6526 : ok = parse_guid_string((char *)s->data + 1, guid);
93 6526 : return ok ? NT_STATUS_OK : NT_STATUS_INVALID_PARAMETER;
94 : }
95 :
96 1853656 : if (s->length == 32) {
97 6 : uint8_t buf16[16] = {0};
98 6 : DATA_BLOB blob16 = { .data = buf16, .length = sizeof(buf16) };
99 6 : size_t rlen = strhex_to_str((char *)blob16.data, blob16.length,
100 0 : (const char *)s->data, s->length);
101 6 : if (rlen != blob16.length) {
102 0 : return NT_STATUS_INVALID_PARAMETER;
103 : }
104 :
105 6 : return GUID_from_ndr_blob(&blob16, guid);
106 : }
107 :
108 1853650 : if (s->length == 16) {
109 1853625 : return GUID_from_ndr_blob(s, guid);
110 : }
111 :
112 25 : return NT_STATUS_INVALID_PARAMETER;
113 : }
114 :
115 : /**
116 : build a GUID from a string
117 : */
118 310434 : _PUBLIC_ NTSTATUS GUID_from_string(const char *s, struct GUID *guid)
119 : {
120 310434 : DATA_BLOB blob = data_blob_string_const(s);
121 310434 : return GUID_from_data_blob(&blob, guid);
122 : }
123 :
124 : /**
125 : * generate a random GUID
126 : */
127 1729320 : _PUBLIC_ struct GUID GUID_random(void)
128 : {
129 54001 : struct GUID guid;
130 :
131 1729320 : generate_random_buffer((uint8_t *)&guid, sizeof(guid));
132 1729320 : guid.clock_seq[0] = (guid.clock_seq[0] & 0x3F) | 0x80;
133 1729320 : guid.time_hi_and_version = (guid.time_hi_and_version & 0x0FFF) | 0x4000;
134 :
135 1729320 : return guid;
136 : }
137 :
138 : /**
139 : * generate an empty GUID
140 : */
141 66537133 : _PUBLIC_ struct GUID GUID_zero(void)
142 : {
143 66537133 : return (struct GUID) { .time_low = 0 };
144 : }
145 :
146 86979024 : _PUBLIC_ bool GUID_all_zero(const struct GUID *u)
147 : {
148 86979024 : if (u->time_low != 0 ||
149 18253088 : u->time_mid != 0 ||
150 17362475 : u->time_hi_and_version != 0 ||
151 18253088 : u->clock_seq[0] != 0 ||
152 18253088 : u->clock_seq[1] != 0 ||
153 18253088 : !all_zero(u->node, 6)) {
154 68725936 : return false;
155 : }
156 17362475 : return true;
157 : }
158 :
159 42647626 : _PUBLIC_ bool GUID_equal(const struct GUID *u1, const struct GUID *u2)
160 : {
161 42647626 : return (GUID_compare(u1, u2) == 0);
162 : }
163 :
164 59919457 : _PUBLIC_ int GUID_compare(const struct GUID *u1, const struct GUID *u2)
165 : {
166 59919457 : if (u1->time_low != u2->time_low) {
167 52581077 : return u1->time_low > u2->time_low ? 1 : -1;
168 : }
169 :
170 7338380 : if (u1->time_mid != u2->time_mid) {
171 6406 : return u1->time_mid > u2->time_mid ? 1 : -1;
172 : }
173 :
174 7331974 : if (u1->time_hi_and_version != u2->time_hi_and_version) {
175 0 : return u1->time_hi_and_version > u2->time_hi_and_version ? 1 : -1;
176 : }
177 :
178 7331974 : if (u1->clock_seq[0] != u2->clock_seq[0]) {
179 19335 : return u1->clock_seq[0] > u2->clock_seq[0] ? 1 : -1;
180 : }
181 :
182 7312639 : if (u1->clock_seq[1] != u2->clock_seq[1]) {
183 6382 : return u1->clock_seq[1] > u2->clock_seq[1] ? 1 : -1;
184 : }
185 :
186 7306257 : return memcmp(u1->node, u2->node, 6);
187 : }
188 :
189 : /**
190 : its useful to be able to display these in debugging messages
191 : */
192 31561640 : _PUBLIC_ char *GUID_string(TALLOC_CTX *mem_ctx, const struct GUID *guid)
193 : {
194 298648 : struct GUID_txt_buf buf;
195 31561640 : return talloc_strdup(mem_ctx, GUID_buf_string(guid, &buf));
196 : }
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 39962709 : _PUBLIC_ char* GUID_buf_string(const struct GUID *guid,
203 : struct GUID_txt_buf *dst)
204 : {
205 39962709 : if (!guid) {
206 0 : return NULL;
207 : }
208 39962709 : snprintf(dst->buf, sizeof(dst->buf),
209 : "%08"PRIx32"-%04"PRIx16"-%04"PRIx16"-%02"PRIx8"%02"PRIx8"-%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8"%02"PRIx8,
210 39962709 : guid->time_low, guid->time_mid,
211 39962709 : guid->time_hi_and_version,
212 39962709 : guid->clock_seq[0],
213 39962709 : guid->clock_seq[1],
214 39962709 : guid->node[0], guid->node[1],
215 39962709 : guid->node[2], guid->node[3],
216 39962709 : guid->node[4], guid->node[5]);
217 39962709 : return dst->buf;
218 : }
219 :
220 61 : _PUBLIC_ char *GUID_string2(TALLOC_CTX *mem_ctx, const struct GUID *guid)
221 : {
222 2 : struct GUID_txt_buf buf;
223 61 : char *ret = talloc_asprintf(
224 : mem_ctx, "{%s}", GUID_buf_string(guid, &buf));
225 61 : return ret;
226 : }
227 :
228 0 : _PUBLIC_ char *GUID_hexstring(TALLOC_CTX *mem_ctx, const struct GUID *guid)
229 : {
230 0 : char *ret = NULL;
231 0 : DATA_BLOB guid_blob = { .data = NULL };
232 0 : NTSTATUS status;
233 :
234 0 : status = GUID_to_ndr_blob(guid, mem_ctx, &guid_blob);
235 0 : if (NT_STATUS_IS_OK(status)) {
236 0 : ret = data_blob_hex_string_upper(mem_ctx, &guid_blob);
237 : }
238 0 : TALLOC_FREE(guid_blob.data);
239 0 : return ret;
240 : }
241 :
242 2040330 : _PUBLIC_ bool ndr_policy_handle_empty(const struct policy_handle *h)
243 : {
244 2040330 : return (h->handle_type == 0 && GUID_all_zero(&h->uuid));
245 : }
246 :
247 175 : _PUBLIC_ bool ndr_policy_handle_equal(const struct policy_handle *hnd1,
248 : const struct policy_handle *hnd2)
249 : {
250 175 : if (!hnd1 || !hnd2) {
251 0 : return false;
252 : }
253 :
254 175 : return (memcmp(hnd1, hnd2, sizeof(*hnd1)) == 0);
255 : }
|