lib: Align an integer type
[vlendec/samba-autobuild/.git] / librpc / ndr / uuid.c
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 {
35         DATA_BLOB b = { .data = buf->buf, .length = sizeof(buf->buf), };
36         enum ndr_err_code ndr_err;
37
38         ndr_err = ndr_push_struct_into_fixed_blob(
39                 &b, guid, (ndr_push_flags_fn_t)ndr_push_GUID);
40         SMB_ASSERT(NDR_ERR_CODE_IS_SUCCESS(ndr_err));
41 }
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 {
48         struct GUID_ndr_buf buf = { .buf = {0}, };
49
50         GUID_to_ndr_buf(guid, &buf);
51
52         *b = data_blob_talloc(mem_ctx, buf.buf, sizeof(buf.buf));
53         if (b->data == NULL) {
54                 return NT_STATUS_NO_MEMORY;
55         }
56         return NT_STATUS_OK;
57 }
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 {
65         enum ndr_err_code ndr_err =
66                 ndr_pull_struct_blob_all_noalloc(b, guid,
67                                                  (ndr_pull_flags_fn_t)ndr_pull_GUID);
68         return ndr_map_error2ntstatus(ndr_err);
69 }
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 {
77         bool ok;
78
79         if (s->data == NULL) {
80                 return NT_STATUS_INVALID_PARAMETER;
81         }
82
83         if (s->length == 36) {
84                 ok = parse_guid_string((char *)s->data, guid);
85                 return ok ? NT_STATUS_OK : NT_STATUS_INVALID_PARAMETER;
86         }
87
88         if (s->length == 38) {
89                 if (s->data[0] != '{' || s->data[37] != '}') {
90                         return NT_STATUS_INVALID_PARAMETER;
91                 }
92                 ok = parse_guid_string((char *)s->data + 1, guid);
93                 return ok ? NT_STATUS_OK : NT_STATUS_INVALID_PARAMETER;
94         }
95
96         if (s->length == 32) {
97                 uint8_t buf16[16] = {0};
98                 DATA_BLOB blob16 = { .data = buf16, .length = sizeof(buf16) };
99                 size_t rlen = strhex_to_str((char *)blob16.data, blob16.length,
100                                             (const char *)s->data, s->length);
101                 if (rlen != blob16.length) {
102                         return NT_STATUS_INVALID_PARAMETER;
103                 }
104
105                 return GUID_from_ndr_blob(&blob16, guid);
106         }
107
108         if (s->length == 16) {
109                 return GUID_from_ndr_blob(s, guid);
110         }
111
112         return NT_STATUS_INVALID_PARAMETER;
113 }
114
115 /**
116   build a GUID from a string
117 */
118 _PUBLIC_ NTSTATUS GUID_from_string(const char *s, struct GUID *guid)
119 {
120         DATA_BLOB blob = data_blob_string_const(s);
121         return GUID_from_data_blob(&blob, guid);
122 }
123
124 /**
125  * generate a random GUID
126  */
127 _PUBLIC_ struct GUID GUID_random(void)
128 {
129         struct GUID guid;
130
131         generate_random_buffer((uint8_t *)&guid, sizeof(guid));
132         guid.clock_seq[0] = (guid.clock_seq[0] & 0x3F) | 0x80;
133         guid.time_hi_and_version = (guid.time_hi_and_version & 0x0FFF) | 0x4000;
134
135         return guid;
136 }
137
138 /**
139  * generate an empty GUID 
140  */
141 _PUBLIC_ struct GUID GUID_zero(void)
142 {
143         return (struct GUID) { .time_low = 0 };
144 }
145
146 _PUBLIC_ bool GUID_all_zero(const struct GUID *u)
147 {
148         if (u->time_low != 0 ||
149             u->time_mid != 0 ||
150             u->time_hi_and_version != 0 ||
151             u->clock_seq[0] != 0 ||
152             u->clock_seq[1] != 0 ||
153             !all_zero(u->node, 6)) {
154                 return false;
155         }
156         return true;
157 }
158
159 _PUBLIC_ bool GUID_equal(const struct GUID *u1, const struct GUID *u2)
160 {
161         return (GUID_compare(u1, u2) == 0);
162 }
163
164 _PUBLIC_ int GUID_compare(const struct GUID *u1, const struct GUID *u2)
165 {
166         if (u1->time_low != u2->time_low) {
167                 return u1->time_low > u2->time_low ? 1 : -1;
168         }
169
170         if (u1->time_mid != u2->time_mid) {
171                 return u1->time_mid > u2->time_mid ? 1 : -1;
172         }
173
174         if (u1->time_hi_and_version != u2->time_hi_and_version) {
175                 return u1->time_hi_and_version > u2->time_hi_and_version ? 1 : -1;
176         }
177
178         if (u1->clock_seq[0] != u2->clock_seq[0]) {
179                 return u1->clock_seq[0] > u2->clock_seq[0] ? 1 : -1;
180         }
181
182         if (u1->clock_seq[1] != u2->clock_seq[1]) {
183                 return u1->clock_seq[1] > u2->clock_seq[1] ? 1 : -1;
184         }
185
186         return memcmp(u1->node, u2->node, 6);
187 }
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 {
194         struct GUID_txt_buf buf;
195         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 _PUBLIC_ char* GUID_buf_string(const struct GUID *guid,
203                                struct GUID_txt_buf *dst)
204 {
205         if (!guid) {
206                 return NULL;
207         }
208         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                  guid->time_low, guid->time_mid,
211                  guid->time_hi_and_version,
212                  guid->clock_seq[0],
213                  guid->clock_seq[1],
214                  guid->node[0], guid->node[1],
215                  guid->node[2], guid->node[3],
216                  guid->node[4], guid->node[5]);
217         return dst->buf;
218 }
219
220 _PUBLIC_ char *GUID_string2(TALLOC_CTX *mem_ctx, const struct GUID *guid)
221 {
222         struct GUID_txt_buf buf;
223         char *ret = talloc_asprintf(
224                 mem_ctx, "{%s}", GUID_buf_string(guid, &buf));
225         return ret;
226 }
227
228 _PUBLIC_ char *GUID_hexstring(TALLOC_CTX *mem_ctx, const struct GUID *guid)
229 {
230         char *ret = NULL;
231         DATA_BLOB guid_blob = { .data = NULL };
232         NTSTATUS status;
233
234         status = GUID_to_ndr_blob(guid, mem_ctx, &guid_blob);
235         if (NT_STATUS_IS_OK(status)) {
236                 ret = data_blob_hex_string_upper(mem_ctx, &guid_blob);
237         }
238         TALLOC_FREE(guid_blob.data);
239         return ret;
240 }
241
242 _PUBLIC_ bool ndr_policy_handle_empty(const struct policy_handle *h)
243 {
244         return (h->handle_type == 0 && GUID_all_zero(&h->uuid));
245 }
246
247 _PUBLIC_ bool ndr_policy_handle_equal(const struct policy_handle *hnd1,
248                                   const struct policy_handle *hnd2)
249 {
250         if (!hnd1 || !hnd2) {
251                 return false;
252         }
253
254         return (memcmp(hnd1, hnd2, sizeof(*hnd1)) == 0);
255 }