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 "includes.h" 25#include "librpc/ndr/libndr.h" 26#include "librpc/gen_ndr/ndr_misc.h" 27 28 29/** 30 build a GUID from a NDR data blob 31*/ 32_PUBLIC_ NTSTATUS GUID_from_ndr_blob(const DATA_BLOB *b, struct GUID *guid) 33{ 34 enum ndr_err_code ndr_err; 35 TALLOC_CTX *mem_ctx; 36 37 mem_ctx = talloc_new(NULL); 38 NT_STATUS_HAVE_NO_MEMORY(mem_ctx); 39 40 ndr_err = ndr_pull_struct_blob_all(b, mem_ctx, NULL, guid, 41 (ndr_pull_flags_fn_t)ndr_pull_GUID); 42 talloc_free(mem_ctx); 43 return ndr_map_error2ntstatus(ndr_err); 44} 45 46 47/** 48 build a GUID from a string 49*/ 50_PUBLIC_ NTSTATUS GUID_from_data_blob(const DATA_BLOB *s, struct GUID *guid) 51{ 52 NTSTATUS status = NT_STATUS_INVALID_PARAMETER; 53 uint32_t time_low; 54 uint32_t time_mid, time_hi_and_version; 55 uint32_t clock_seq[2]; 56 uint32_t node[6]; 57 uint8_t buf16[16]; 58 59 DATA_BLOB blob16 = data_blob_const(buf16, sizeof(buf16)); 60 int i; 61 62 if (s->data == NULL) { 63 return NT_STATUS_INVALID_PARAMETER; 64 } 65 66 if (s->length == 36) { 67 TALLOC_CTX *mem_ctx; 68 const char *string; 69 70 mem_ctx = talloc_new(NULL); 71 NT_STATUS_HAVE_NO_MEMORY(mem_ctx); 72 string = talloc_strndup(mem_ctx, (const char *)s->data, s->length); 73 NT_STATUS_HAVE_NO_MEMORY(string); 74 if (11 == sscanf(string, 75 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", 76 &time_low, &time_mid, &time_hi_and_version, 77 &clock_seq[0], &clock_seq[1], 78 &node[0], &node[1], &node[2], &node[3], &node[4], &node[5])) { 79 status = NT_STATUS_OK; 80 } 81 talloc_free(mem_ctx); 82 83 } else if (s->length == 38) { 84 TALLOC_CTX *mem_ctx; 85 const char *string; 86 87 mem_ctx = talloc_new(NULL); 88 NT_STATUS_HAVE_NO_MEMORY(mem_ctx); 89 string = talloc_strndup(mem_ctx, (const char *)s->data, s->length); 90 NT_STATUS_HAVE_NO_MEMORY(string); 91 if (11 == sscanf((const char *)s->data, 92 "{%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", 93 &time_low, &time_mid, &time_hi_and_version, 94 &clock_seq[0], &clock_seq[1], 95 &node[0], &node[1], &node[2], &node[3], &node[4], &node[5])) { 96 status = NT_STATUS_OK; 97 } 98 talloc_free(mem_ctx); 99 100 } else if (s->length == 32) { 101 size_t rlen = strhex_to_str((char *)blob16.data, blob16.length, 102 (const char *)s->data, s->length); 103 if (rlen != blob16.length) { 104 return NT_STATUS_INVALID_PARAMETER; 105 } 106 107 s = &blob16; 108 return GUID_from_ndr_blob(s, guid); 109 } 110 111 if (s->length == 16) { 112 return GUID_from_ndr_blob(s, guid); 113 } 114 115 if (!NT_STATUS_IS_OK(status)) { 116 return status; 117 } 118 119 guid->time_low = time_low; 120 guid->time_mid = time_mid; 121 guid->time_hi_and_version = time_hi_and_version; 122 guid->clock_seq[0] = clock_seq[0]; 123 guid->clock_seq[1] = clock_seq[1]; 124 for (i=0;i<6;i++) { 125 guid->node[i] = node[i]; 126 } 127 128 return NT_STATUS_OK; 129} 130 131/** 132 build a GUID from a string 133*/ 134_PUBLIC_ NTSTATUS GUID_from_string(const char *s, struct GUID *guid) 135{ 136 DATA_BLOB blob = data_blob_string_const(s); 137 return GUID_from_data_blob(&blob, guid); 138 return NT_STATUS_OK; 139} 140 141/** 142 build a GUID from a string 143*/ 144_PUBLIC_ NTSTATUS NS_GUID_from_string(const char *s, struct GUID *guid) 145{ 146 NTSTATUS status = NT_STATUS_INVALID_PARAMETER; 147 uint32_t time_low; 148 uint32_t time_mid, time_hi_and_version; 149 uint32_t clock_seq[2]; 150 uint32_t node[6]; 151 int i; 152 153 if (s == NULL) { 154 return NT_STATUS_INVALID_PARAMETER; 155 } 156 157 if (11 == sscanf(s, "%08x-%04x%04x-%02x%02x%02x%02x-%02x%02x%02x%02x", 158 &time_low, &time_mid, &time_hi_and_version, 159 &clock_seq[0], &clock_seq[1], 160 &node[0], &node[1], &node[2], &node[3], &node[4], &node[5])) { 161 status = NT_STATUS_OK; 162 } 163 164 if (!NT_STATUS_IS_OK(status)) { 165 return status; 166 } 167 168 guid->time_low = time_low; 169 guid->time_mid = time_mid; 170 guid->time_hi_and_version = time_hi_and_version; 171 guid->clock_seq[0] = clock_seq[0]; 172 guid->clock_seq[1] = clock_seq[1]; 173 for (i=0;i<6;i++) { 174 guid->node[i] = node[i]; 175 } 176 177 return NT_STATUS_OK; 178} 179 180/** 181 * generate a random GUID 182 */ 183_PUBLIC_ struct GUID GUID_random(void) 184{ 185 struct GUID guid; 186 187 generate_random_buffer((uint8_t *)&guid, sizeof(guid)); 188 guid.clock_seq[0] = (guid.clock_seq[0] & 0x3F) | 0x80; 189 guid.time_hi_and_version = (guid.time_hi_and_version & 0x0FFF) | 0x4000; 190 191 return guid; 192} 193 194/** 195 * generate an empty GUID 196 */ 197_PUBLIC_ struct GUID GUID_zero(void) 198{ 199 struct GUID guid; 200 201 ZERO_STRUCT(guid); 202 203 return guid; 204} 205 206_PUBLIC_ bool GUID_all_zero(const struct GUID *u) 207{ 208 if (u->time_low != 0 || 209 u->time_mid != 0 || 210 u->time_hi_and_version != 0 || 211 u->clock_seq[0] != 0 || 212 u->clock_seq[1] != 0 || 213 !all_zero(u->node, 6)) { 214 return false; 215 } 216 return true; 217} 218 219_PUBLIC_ bool GUID_equal(const struct GUID *u1, const struct GUID *u2) 220{ 221 if (u1->time_low != u2->time_low || 222 u1->time_mid != u2->time_mid || 223 u1->time_hi_and_version != u2->time_hi_and_version || 224 u1->clock_seq[0] != u2->clock_seq[0] || 225 u1->clock_seq[1] != u2->clock_seq[1] || 226 memcmp(u1->node, u2->node, 6) != 0) { 227 return false; 228 } 229 return true; 230} 231 232_PUBLIC_ int GUID_compare(const struct GUID *u1, const struct GUID *u2) 233{ 234 if (u1->time_low != u2->time_low) { 235 return u1->time_low - u2->time_low; 236 } 237 238 if (u1->time_mid != u2->time_mid) { 239 return u1->time_mid - u2->time_mid; 240 } 241 242 if (u1->time_hi_and_version != u2->time_hi_and_version) { 243 return u1->time_hi_and_version - u2->time_hi_and_version; 244 } 245 246 if (u1->clock_seq[0] != u2->clock_seq[0]) { 247 return u1->clock_seq[0] - u2->clock_seq[0]; 248 } 249 250 if (u1->clock_seq[1] != u2->clock_seq[1]) { 251 return u1->clock_seq[1] - u2->clock_seq[1]; 252 } 253 254 return memcmp(u1->node, u2->node, 6); 255} 256 257/** 258 its useful to be able to display these in debugging messages 259*/ 260_PUBLIC_ char *GUID_string(TALLOC_CTX *mem_ctx, const struct GUID *guid) 261{ 262 return talloc_asprintf(mem_ctx, 263 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", 264 guid->time_low, guid->time_mid, 265 guid->time_hi_and_version, 266 guid->clock_seq[0], 267 guid->clock_seq[1], 268 guid->node[0], guid->node[1], 269 guid->node[2], guid->node[3], 270 guid->node[4], guid->node[5]); 271} 272 273_PUBLIC_ char *GUID_string2(TALLOC_CTX *mem_ctx, const struct GUID *guid) 274{ 275 char *ret, *s = GUID_string(mem_ctx, guid); 276 ret = talloc_asprintf(mem_ctx, "{%s}", s); 277 talloc_free(s); 278 return ret; 279} 280 281_PUBLIC_ char *GUID_hexstring(TALLOC_CTX *mem_ctx, const struct GUID *guid) 282{ 283 char *ret; 284 DATA_BLOB guid_blob; 285 enum ndr_err_code ndr_err; 286 TALLOC_CTX *tmp_mem; 287 288 tmp_mem = talloc_new(mem_ctx); 289 if (!tmp_mem) { 290 return NULL; 291 } 292 ndr_err = ndr_push_struct_blob(&guid_blob, tmp_mem, 293 NULL, 294 guid, 295 (ndr_push_flags_fn_t)ndr_push_GUID); 296 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { 297 talloc_free(tmp_mem); 298 return NULL; 299 } 300 301 ret = data_blob_hex_string(mem_ctx, &guid_blob); 302 talloc_free(tmp_mem); 303 return ret; 304} 305 306_PUBLIC_ char *NS_GUID_string(TALLOC_CTX *mem_ctx, const struct GUID *guid) 307{ 308 return talloc_asprintf(mem_ctx, 309 "%08x-%04x%04x-%02x%02x%02x%02x-%02x%02x%02x%02x", 310 guid->time_low, guid->time_mid, 311 guid->time_hi_and_version, 312 guid->clock_seq[0], 313 guid->clock_seq[1], 314 guid->node[0], guid->node[1], 315 guid->node[2], guid->node[3], 316 guid->node[4], guid->node[5]); 317} 318 319_PUBLIC_ bool policy_handle_empty(struct policy_handle *h) 320{ 321 return (h->handle_type == 0 && GUID_all_zero(&h->uuid)); 322} 323