2007-11-09 13:50:14 +03:00
/*
Unix SMB / CIFS implementation .
UUID / GUID functions
Copyright ( C ) Theodore Ts ' o 1996 , 1997 ,
Copyright ( C ) Jim McDonough 2002.
Copyright ( C ) Andrew Tridgell 2003.
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 3 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
2020-09-29 10:51:48 +03:00
# include "replace.h"
2024-02-09 21:09:35 +03:00
# include "lib/util/debug.h"
2020-09-29 10:51:48 +03:00
# include "lib/util/samba_util.h"
# include "lib/util/genrand.h"
2007-11-09 13:50:14 +03:00
# include "librpc/ndr/libndr.h"
2008-11-13 23:27:10 +03:00
# include "librpc/gen_ndr/ndr_misc.h"
2018-02-16 07:53:15 +03:00
# include "lib/util/util_str_hex.h"
2020-09-29 10:59:29 +03:00
2024-02-09 21:09:35 +03:00
_PUBLIC_ void GUID_to_ndr_buf ( const struct GUID * guid ,
struct GUID_ndr_buf * buf )
2020-09-29 10:59:29 +03:00
{
DATA_BLOB b = { . data = buf - > buf , . length = sizeof ( buf - > buf ) , } ;
enum ndr_err_code ndr_err ;
ndr_err = ndr_push_struct_into_fixed_blob (
& b , guid , ( ndr_push_flags_fn_t ) ndr_push_GUID ) ;
2024-02-09 21:09:35 +03:00
SMB_ASSERT ( NDR_ERR_CODE_IS_SUCCESS ( ndr_err ) ) ;
2020-09-29 10:59:29 +03:00
}
2009-12-10 06:29:19 +03:00
/**
build a NDR blob from a GUID
*/
_PUBLIC_ NTSTATUS GUID_to_ndr_blob ( const struct GUID * guid , TALLOC_CTX * mem_ctx , DATA_BLOB * b )
{
2020-09-29 11:09:48 +03:00
struct GUID_ndr_buf buf = { . buf = { 0 } , } ;
2024-02-09 21:09:35 +03:00
GUID_to_ndr_buf ( guid , & buf ) ;
2020-09-29 11:09:48 +03:00
* b = data_blob_talloc ( mem_ctx , buf . buf , sizeof ( buf . buf ) ) ;
2016-06-17 04:29:51 +03:00
if ( b - > data = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2020-09-29 11:09:48 +03:00
return NT_STATUS_OK ;
2009-12-10 06:29:19 +03:00
}
2009-12-10 03:22:20 +03:00
/**
build a GUID from a NDR data blob
*/
_PUBLIC_ NTSTATUS GUID_from_ndr_blob ( const DATA_BLOB * b , struct GUID * guid )
{
2016-04-22 03:02:57 +03:00
enum ndr_err_code ndr_err =
ndr_pull_struct_blob_all_noalloc ( b , guid ,
( ndr_pull_flags_fn_t ) ndr_pull_GUID ) ;
2009-12-10 03:22:20 +03:00
return ndr_map_error2ntstatus ( ndr_err ) ;
}
2007-11-09 13:50:14 +03:00
/**
build a GUID from a string
*/
2008-11-10 03:40:31 +03:00
_PUBLIC_ NTSTATUS GUID_from_data_blob ( const DATA_BLOB * s , struct GUID * guid )
2007-11-09 13:50:14 +03:00
{
2021-01-24 11:15:29 +03:00
bool ok ;
2007-11-09 13:50:14 +03:00
2008-11-10 03:40:31 +03:00
if ( s - > data = = NULL ) {
2007-11-09 13:50:14 +03:00
return NT_STATUS_INVALID_PARAMETER ;
}
2021-01-24 11:15:29 +03:00
if ( s - > length = = 36 ) {
ok = parse_guid_string ( ( char * ) s - > data , guid ) ;
return ok ? NT_STATUS_OK : NT_STATUS_INVALID_PARAMETER ;
2010-06-07 12:00:39 +04:00
}
2021-01-24 11:15:29 +03:00
if ( s - > length = = 38 ) {
2016-12-07 01:54:41 +03:00
if ( s - > data [ 0 ] ! = ' { ' | | s - > data [ 37 ] ! = ' } ' ) {
2021-01-24 11:15:29 +03:00
return NT_STATUS_INVALID_PARAMETER ;
2008-12-20 04:05:48 +03:00
}
2021-01-24 11:15:29 +03:00
ok = parse_guid_string ( ( char * ) s - > data + 1 , guid ) ;
return ok ? NT_STATUS_OK : NT_STATUS_INVALID_PARAMETER ;
2010-06-07 12:00:39 +04:00
}
2021-01-24 11:15:29 +03:00
if ( s - > length = = 32 ) {
uint8_t buf16 [ 16 ] = { 0 } ;
DATA_BLOB blob16 = { . data = buf16 , . length = sizeof ( buf16 ) } ;
2008-11-13 23:27:10 +03:00
size_t rlen = strhex_to_str ( ( char * ) blob16 . data , blob16 . length ,
( const char * ) s - > data , s - > length ) ;
2010-06-28 23:00:30 +04:00
if ( rlen ! = blob16 . length ) {
return NT_STATUS_INVALID_PARAMETER ;
2008-11-13 23:27:10 +03:00
}
2010-06-28 23:00:30 +04:00
2021-01-24 11:15:29 +03:00
return GUID_from_ndr_blob ( & blob16 , guid ) ;
2007-11-09 13:50:14 +03:00
}
2021-01-24 11:15:29 +03:00
if ( s - > length = = 16 ) {
return GUID_from_ndr_blob ( s , guid ) ;
2007-11-09 13:50:14 +03:00
}
2021-01-24 11:15:29 +03:00
return NT_STATUS_INVALID_PARAMETER ;
2007-11-09 13:50:14 +03:00
}
2008-11-10 03:40:31 +03:00
/**
build a GUID from a string
*/
_PUBLIC_ NTSTATUS GUID_from_string ( const char * s , struct GUID * guid )
{
DATA_BLOB blob = data_blob_string_const ( s ) ;
return GUID_from_data_blob ( & blob , guid ) ;
}
2007-11-09 13:50:14 +03:00
/**
* generate a random GUID
*/
2008-10-13 17:01:28 +04:00
_PUBLIC_ struct GUID GUID_random ( void )
2007-11-09 13:50:14 +03:00
{
struct GUID guid ;
generate_random_buffer ( ( uint8_t * ) & guid , sizeof ( guid ) ) ;
guid . clock_seq [ 0 ] = ( guid . clock_seq [ 0 ] & 0x3F ) | 0x80 ;
guid . time_hi_and_version = ( guid . time_hi_and_version & 0x0FFF ) | 0x4000 ;
return guid ;
}
/**
* generate an empty GUID
*/
_PUBLIC_ struct GUID GUID_zero ( void )
{
2021-08-18 07:27:52 +03:00
return ( struct GUID ) { . time_low = 0 } ;
2007-11-09 13:50:14 +03:00
}
_PUBLIC_ bool GUID_all_zero ( const struct GUID * u )
{
if ( u - > time_low ! = 0 | |
u - > time_mid ! = 0 | |
u - > time_hi_and_version ! = 0 | |
u - > clock_seq [ 0 ] ! = 0 | |
u - > clock_seq [ 1 ] ! = 0 | |
! all_zero ( u - > node , 6 ) ) {
return false ;
}
return true ;
}
_PUBLIC_ bool GUID_equal ( const struct GUID * u1 , const struct GUID * u2 )
{
2014-06-05 13:56:55 +04:00
return ( GUID_compare ( u1 , u2 ) = = 0 ) ;
2007-11-09 13:50:14 +03:00
}
_PUBLIC_ int GUID_compare ( const struct GUID * u1 , const struct GUID * u2 )
{
if ( u1 - > time_low ! = u2 - > time_low ) {
2009-12-20 02:25:46 +03:00
return u1 - > time_low > u2 - > time_low ? 1 : - 1 ;
2007-11-09 13:50:14 +03:00
}
if ( u1 - > time_mid ! = u2 - > time_mid ) {
2009-12-20 02:25:46 +03:00
return u1 - > time_mid > u2 - > time_mid ? 1 : - 1 ;
2007-11-09 13:50:14 +03:00
}
if ( u1 - > time_hi_and_version ! = u2 - > time_hi_and_version ) {
2009-12-20 02:25:46 +03:00
return u1 - > time_hi_and_version > u2 - > time_hi_and_version ? 1 : - 1 ;
2007-11-09 13:50:14 +03:00
}
if ( u1 - > clock_seq [ 0 ] ! = u2 - > clock_seq [ 0 ] ) {
2009-12-20 02:25:46 +03:00
return u1 - > clock_seq [ 0 ] > u2 - > clock_seq [ 0 ] ? 1 : - 1 ;
2007-11-09 13:50:14 +03:00
}
if ( u1 - > clock_seq [ 1 ] ! = u2 - > clock_seq [ 1 ] ) {
2009-12-20 02:25:46 +03:00
return u1 - > clock_seq [ 1 ] > u2 - > clock_seq [ 1 ] ? 1 : - 1 ;
2007-11-09 13:50:14 +03:00
}
return memcmp ( u1 - > node , u2 - > node , 6 ) ;
}
/**
its useful to be able to display these in debugging messages
*/
_PUBLIC_ char * GUID_string ( TALLOC_CTX * mem_ctx , const struct GUID * guid )
{
2014-09-30 10:32:36 +04:00
struct GUID_txt_buf buf ;
return talloc_strdup ( mem_ctx , GUID_buf_string ( guid , & buf ) ) ;
2007-11-09 13:50:14 +03:00
}
2014-09-25 12:14:27 +04:00
/**
* Does the same without allocating memory , using the structure buffer .
* Useful for debug messages , so that you do not have to talloc_free the result
*/
_PUBLIC_ char * GUID_buf_string ( const struct GUID * guid ,
struct GUID_txt_buf * dst )
{
if ( ! guid ) {
return NULL ;
}
2023-03-01 04:54:14 +03:00
if ( sizeof ( dst - > buf ) < 37 ) {
return NULL ;
}
dst - > buf [ 0 ] = nybble_to_hex_lower ( guid - > time_low > > 28 ) ;
dst - > buf [ 1 ] = nybble_to_hex_lower ( guid - > time_low > > 24 ) ;
dst - > buf [ 2 ] = nybble_to_hex_lower ( guid - > time_low > > 20 ) ;
dst - > buf [ 3 ] = nybble_to_hex_lower ( guid - > time_low > > 16 ) ;
dst - > buf [ 4 ] = nybble_to_hex_lower ( guid - > time_low > > 12 ) ;
dst - > buf [ 5 ] = nybble_to_hex_lower ( guid - > time_low > > 8 ) ;
dst - > buf [ 6 ] = nybble_to_hex_lower ( guid - > time_low > > 4 ) ;
dst - > buf [ 7 ] = nybble_to_hex_lower ( guid - > time_low ) ;
dst - > buf [ 8 ] = ' - ' ;
dst - > buf [ 9 ] = nybble_to_hex_lower ( guid - > time_mid > > 12 ) ;
dst - > buf [ 10 ] = nybble_to_hex_lower ( guid - > time_mid > > 8 ) ;
dst - > buf [ 11 ] = nybble_to_hex_lower ( guid - > time_mid > > 4 ) ;
dst - > buf [ 12 ] = nybble_to_hex_lower ( guid - > time_mid ) ;
dst - > buf [ 13 ] = ' - ' ;
dst - > buf [ 14 ] = nybble_to_hex_lower ( guid - > time_hi_and_version > > 12 ) ;
dst - > buf [ 15 ] = nybble_to_hex_lower ( guid - > time_hi_and_version > > 8 ) ;
dst - > buf [ 16 ] = nybble_to_hex_lower ( guid - > time_hi_and_version > > 4 ) ;
dst - > buf [ 17 ] = nybble_to_hex_lower ( guid - > time_hi_and_version ) ;
dst - > buf [ 18 ] = ' - ' ;
dst - > buf [ 19 ] = nybble_to_hex_lower ( guid - > clock_seq [ 0 ] > > 4 ) ;
dst - > buf [ 20 ] = nybble_to_hex_lower ( guid - > clock_seq [ 0 ] ) ;
dst - > buf [ 21 ] = nybble_to_hex_lower ( guid - > clock_seq [ 1 ] > > 4 ) ;
dst - > buf [ 22 ] = nybble_to_hex_lower ( guid - > clock_seq [ 1 ] ) ;
dst - > buf [ 23 ] = ' - ' ;
dst - > buf [ 24 ] = nybble_to_hex_lower ( guid - > node [ 0 ] > > 4 ) ;
dst - > buf [ 25 ] = nybble_to_hex_lower ( guid - > node [ 0 ] ) ;
dst - > buf [ 26 ] = nybble_to_hex_lower ( guid - > node [ 1 ] > > 4 ) ;
dst - > buf [ 27 ] = nybble_to_hex_lower ( guid - > node [ 1 ] ) ;
dst - > buf [ 28 ] = nybble_to_hex_lower ( guid - > node [ 2 ] > > 4 ) ;
dst - > buf [ 29 ] = nybble_to_hex_lower ( guid - > node [ 2 ] ) ;
dst - > buf [ 30 ] = nybble_to_hex_lower ( guid - > node [ 3 ] > > 4 ) ;
dst - > buf [ 31 ] = nybble_to_hex_lower ( guid - > node [ 3 ] ) ;
dst - > buf [ 32 ] = nybble_to_hex_lower ( guid - > node [ 4 ] > > 4 ) ;
dst - > buf [ 33 ] = nybble_to_hex_lower ( guid - > node [ 4 ] ) ;
dst - > buf [ 34 ] = nybble_to_hex_lower ( guid - > node [ 5 ] > > 4 ) ;
dst - > buf [ 35 ] = nybble_to_hex_lower ( guid - > node [ 5 ] ) ;
dst - > buf [ 36 ] = ' \0 ' ;
2014-09-25 12:14:27 +04:00
return dst - > buf ;
}
2007-11-09 13:50:14 +03:00
_PUBLIC_ char * GUID_string2 ( TALLOC_CTX * mem_ctx , const struct GUID * guid )
{
2021-08-18 07:25:00 +03:00
struct GUID_txt_buf buf ;
char * ret = talloc_asprintf (
mem_ctx , " {%s} " , GUID_buf_string ( guid , & buf ) ) ;
2007-11-09 13:50:14 +03:00
return ret ;
}
2008-11-13 23:28:02 +03:00
_PUBLIC_ char * GUID_hexstring ( TALLOC_CTX * mem_ctx , const struct GUID * guid )
{
2021-08-18 07:21:52 +03:00
char * ret = NULL ;
DATA_BLOB guid_blob = { . data = NULL } ;
2009-12-10 06:29:19 +03:00
NTSTATUS status ;
2008-11-13 23:28:02 +03:00
2021-08-18 07:21:52 +03:00
status = GUID_to_ndr_blob ( guid , mem_ctx , & guid_blob ) ;
if ( NT_STATUS_IS_OK ( status ) ) {
ret = data_blob_hex_string_upper ( mem_ctx , & guid_blob ) ;
2008-11-13 23:28:02 +03:00
}
2021-08-18 07:21:52 +03:00
TALLOC_FREE ( guid_blob . data ) ;
2008-11-13 23:28:02 +03:00
return ret ;
}
2012-03-18 20:44:24 +04:00
_PUBLIC_ bool ndr_policy_handle_empty ( const struct policy_handle * h )
2007-11-09 13:50:14 +03:00
{
return ( h - > handle_type = = 0 & & GUID_all_zero ( & h - > uuid ) ) ;
}
2011-02-08 02:04:20 +03:00
2012-03-18 19:54:21 +04:00
_PUBLIC_ bool ndr_policy_handle_equal ( const struct policy_handle * hnd1 ,
2011-02-08 02:04:20 +03:00
const struct policy_handle * hnd2 )
{
if ( ! hnd1 | | ! hnd2 ) {
return false ;
}
return ( memcmp ( hnd1 , hnd2 , sizeof ( * hnd1 ) ) = = 0 ) ;
}