2017-03-13 12:14:23 +13:00
/*
Unix SMB / CIFS implementation .
Helpers to search for links in the DB
Copyright ( C ) Catalyst . Net Ltd 2017
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/>.
*/
# include "includes.h"
# include "dsdb/samdb/samdb.h"
# include "lib/util/binsearch.h"
# include "librpc/gen_ndr/ndr_misc.h"
/*
* We choose , as the sort order , the same order as is used in DRS replication ,
* which is the memcmp ( ) order of the NDR GUID , not that obtained from
* GUID_compare ( ) .
*
* This means that sorted links will be in the same order as a new DC would
* see them .
*/
int ndr_guid_compare ( const struct GUID * guid1 , const struct GUID * guid2 )
{
Fix gcc11 compiler issue "-Werror=maybe-uninitialized"
BUG: https://bugzilla.samba.org/show_bug.cgi?id=14699
../../source4/dsdb/common/util_links.c: In function ‘ndr_guid_compare’:
../../source4/dsdb/common/util_links.c:38:29: error: ‘v1_data’ may be used uninitialized [-Werror=maybe-uninitialized]
38 | struct ldb_val v1 = data_blob_const(v1_data, sizeof(v1_data));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../source4/../lib/util/samba_util.h:48,
from ../../source4/include/includes.h:62,
from ../../source4/dsdb/common/util_links.c:22:
../../lib/util/data_blob.h:116:20: note: by argument 1 of type ‘const void *’ to ‘data_blob_const’ declared here
116 | _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length);
| ^~~~~~~~~~~~~~~
../../source4/dsdb/common/util_links.c:37:17: note: ‘v1_data’ declared here
37 | uint8_t v1_data[16];
| ^~~~~~~
cc1: all warnings being treated as errors
[1729/3991] Compiling source3/smbd/smbXsrv_open.c
../../libcli/auth/smbencrypt.c: In function ‘decode_wkssvc_join_password_buffer’:
../../libcli/auth/smbencrypt.c:1045:32: error: ‘_confounder’ may be used uninitialized [-Werror=maybe-uninitialized]
1045 | DATA_BLOB confounder = data_blob_const(_confounder, 8);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../source4/../lib/util/samba_util.h:48,
from ../../source4/include/includes.h:62,
from ../../libcli/auth/smbencrypt.c:24:
../../lib/util/data_blob.h:116:20: note: by argument 1 of type ‘const void *’ to ‘data_blob_const’ declared here
116 | _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length);
| ^~~~~~~~~~~~~~~
../../libcli/auth/smbencrypt.c:1044:17: note: ‘_confounder’ declared here
1044 | uint8_t _confounder[8];
| ^~~~~~~~~~~
cc1: all warnings being treated as errors
[2624/3991] Compiling source4/torture/rpc/samr.c
../../source3/rpc_client/cli_samr.c: In function ‘dcerpc_samr_chgpasswd_user2’:
../../source3/rpc_client/cli_samr.c:158:33: error: ‘old_nt_hash’ may be used uninitialized [-Werror=maybe-uninitialized]
158 | DATA_BLOB session_key = data_blob_const(old_nt_hash, 16);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../source3/../lib/util/samba_util.h:48,
from ../../source3/include/includes.h:256,
from ../../source3/rpc_client/cli_samr.c:24:
../../lib/util/data_blob.h:116:20: note: by argument 1 of type ‘const void *’ to ‘data_blob_const’ declared here
116 | _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length);
| ^~~~~~~~~~~~~~~
../../source3/rpc_client/cli_samr.c:152:17: note: ‘old_nt_hash’ declared here
152 | uint8_t old_nt_hash[16];
| ^~~~~~~~~~~
../../source3/rpc_client/cli_samr.c: In function ‘dcerpc_samr_chgpasswd_user3’:
../../source3/rpc_client/cli_samr.c:365:33: error: ‘old_nt_hash’ may be used uninitialized [-Werror=maybe-uninitialized]
365 | DATA_BLOB session_key = data_blob_const(old_nt_hash, 16);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../source3/../lib/util/samba_util.h:48,
from ../../source3/include/includes.h:256,
from ../../source3/rpc_client/cli_samr.c:24:
../../lib/util/data_blob.h:116:20: note: by argument 1 of type ‘const void *’ to ‘data_blob_const’ declared here
116 | _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length);
| ^~~~~~~~~~~~~~~
../../source3/rpc_client/cli_samr.c:358:17: note: ‘old_nt_hash’ declared here
358 | uint8_t old_nt_hash[16];
| ^~~~~~~~~~~
cc1: all warnings being treated as errors
[3399/3991] Compiling source3/rpcclient/cmd_spotlight.c
../../source3/smbd/smbXsrv_open.c: In function ‘smbXsrv_open_set_replay_cache’:
../../source3/smbd/smbXsrv_open.c:936:26: error: ‘data’ may be used uninitialized [-Werror=maybe-uninitialized]
936 | DATA_BLOB blob = data_blob_const(data, ARRAY_SIZE(data));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../source3/../lib/util/samba_util.h:48,
from ../../source3/include/includes.h:256,
from ../../source3/smbd/smbXsrv_open.c:21:
../../lib/util/data_blob.h:116:20: note: by argument 1 of type ‘const void *’ to ‘data_blob_const’ declared here
116 | _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length);
| ^~~~~~~~~~~~~~~
../../source3/smbd/smbXsrv_open.c:935:17: note: ‘data’ declared here
935 | uint8_t data[SMBXSRV_OPEN_REPLAY_CACHE_FIXED_SIZE];
| ^~~~
cc1: all warnings being treated as errors
../../source3/rpcclient/cmd_spotlight.c: In function ‘cmd_mdssvc_fetch_properties’:
../../source3/rpcclient/cmd_spotlight.c:60:18: error: ‘share_path’ may be used uninitialized [-Werror=maybe-uninitialized]
60 | status = dcerpc_mdssvc_open(b, mem_ctx,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
61 | &device_id,
| ~~~~~~~~~~~
62 | &unkn1,
| ~~~~~~~
63 | &unkn2,
| ~~~~~~~
64 | argv[2],
| ~~~~~~~~
65 | argv[1],
| ~~~~~~~~
66 | share_path,
| ~~~~~~~~~~~
67 | &share_handle);
| ~~~~~~~~~~~~~~
In file included from ../../source3/rpcclient/cmd_spotlight.c:24:
source3/../librpc/gen_ndr/ndr_mdssvc_c.h:26:10: note: by argument 8 of type ‘const char *’ to ‘dcerpc_mdssvc_open’ declared here
26 | NTSTATUS dcerpc_mdssvc_open(struct dcerpc_binding_handle *h,
| ^~~~~~~~~~~~~~~~~~
../../source3/rpcclient/cmd_spotlight.c:40:14: note: ‘share_path’ declared here
40 | char share_path[1025];
| ^~~~~~~~~~
cc1: all warnings being treated as errors
../../source4/torture/rpc/samr.c: In function ‘test_ChangePasswordUser2’:
../../source4/torture/rpc/samr.c:2266:19: error: ‘old_nt_hash’ may be used uninitialized [-Werror=maybe-uninitialized]
2266 | = data_blob_const(old_nt_hash, sizeof(old_nt_hash));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../source4/../lib/util/samba_util.h:48,
from ../../source4/include/includes.h:62,
from ../../source4/torture/rpc/samr.c:24:
../../lib/util/data_blob.h:116:20: note: by argument 1 of type ‘const void *’ to ‘data_blob_const’ declared here
116 | _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length);
| ^~~~~~~~~~~~~~~
../../source4/torture/rpc/samr.c:2263:17: note: ‘old_nt_hash’ declared here
2263 | uint8_t old_nt_hash[16], new_nt_hash[16];
| ^~~~~~~~~~~
../../source4/torture/rpc/samr.c: In function ‘test_ChangePasswordUser2_ntstatus’:
../../source4/torture/rpc/samr.c:2371:19: error: ‘old_nt_hash’ may be used uninitialized [-Werror=maybe-uninitialized]
2371 | = data_blob_const(old_nt_hash, sizeof(old_nt_hash));
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../source4/../lib/util/samba_util.h:48,
from ../../source4/include/includes.h:62,
from ../../source4/torture/rpc/samr.c:24:
../../lib/util/data_blob.h:116:20: note: by argument 1 of type ‘const void *’ to ‘data_blob_const’ declared here
116 | _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length);
| ^~~~~~~~~~~~~~~
../../source4/torture/rpc/samr.c:2368:17: note: ‘old_nt_hash’ declared here
2368 | uint8_t old_nt_hash[16], new_nt_hash[16];
| ^~~~~~~~~~~
../../source4/torture/rpc/samr.c: In function ‘test_ChangePasswordUser3’:
../../source4/torture/rpc/samr.c:2478:38: error: ‘old_nt_hash’ may be used uninitialized [-Werror=maybe-uninitialized]
2478 | DATA_BLOB old_nt_hash_blob = data_blob_const(old_nt_hash, 16);
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from ../../source4/../lib/util/samba_util.h:48,
from ../../source4/include/includes.h:62,
from ../../source4/torture/rpc/samr.c:24:
../../lib/util/data_blob.h:116:20: note: by argument 1 of type ‘const void *’ to ‘data_blob_const’ declared here
116 | _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length);
| ^~~~~~~~~~~~~~~
../../source4/torture/rpc/samr.c:2473:17: note: ‘old_nt_hash’ declared here
2473 | uint8_t old_nt_hash[16], new_nt_hash[16];
| ^~~~~~~~~~~
../../source4/torture/rpc/samr.c: In function ‘test_ChangePasswordRandomBytes’:
../../source4/torture/rpc/samr.c:2794:19: error: ‘old_nt_hash’ may be used uninitialized [-Werror=maybe-uninitialized]
2794 | = data_blob_const(old_nt_hash,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
2795 | sizeof(old_nt_hash));
| ~~~~~~~~~~~~~~~~~~~~
In file included from ../../source4/../lib/util/samba_util.h:48,
from ../../source4/include/includes.h:62,
from ../../source4/torture/rpc/samr.c:24:
../../lib/util/data_blob.h:116:20: note: by argument 1 of type ‘const void *’ to ‘data_blob_const’ declared here
116 | _PUBLIC_ DATA_BLOB data_blob_const(const void *p, size_t length);
| ^~~~~~~~~~~~~~~
../../source4/torture/rpc/samr.c:2792:17: note: ‘old_nt_hash’ declared here
2792 | uint8_t old_nt_hash[16], new_nt_hash[16];
| ^~~~~~~~~~~
cc1: all warnings being treated as errors
Guenther
Signed-off-by: Guenther Deschner <gd@samba.org>
Reviewed-by: Andreas Schneider <asn@samba.org>
2021-05-03 21:27:43 +02:00
uint8_t v1_data [ 16 ] = { 0 } ;
2017-03-13 12:14:23 +13:00
struct ldb_val v1 = data_blob_const ( v1_data , sizeof ( v1_data ) ) ;
uint8_t v2_data [ 16 ] ;
struct ldb_val v2 = data_blob_const ( v2_data , sizeof ( v2_data ) ) ;
/* This can't fail */
ndr_push_struct_into_fixed_blob ( & v1 , guid1 ,
( ndr_push_flags_fn_t ) ndr_push_GUID ) ;
/* This can't fail */
ndr_push_struct_into_fixed_blob ( & v2 , guid2 ,
( ndr_push_flags_fn_t ) ndr_push_GUID ) ;
return data_blob_cmp ( & v1 , & v2 ) ;
}
static int la_guid_compare_with_trusted_dn ( struct compare_ctx * ctx ,
struct parsed_dn * p )
{
int cmp = 0 ;
/*
* This works like a standard compare function in its return values ,
* but has an extra trick to deal with errors : zero is returned and
* ctx - > err is set to the ldb error code .
*
* That is , if ( as is expected in most cases ) you get a non - zero
* result , you don ' t need to check for errors .
*
* We assume the second argument refers to a DN is from the database
* and has a GUID - - but this GUID might not have been parsed out yet .
*/
if ( p - > dsdb_dn = = NULL ) {
int ret = really_parse_trusted_dn ( ctx - > mem_ctx , ctx - > ldb , p ,
ctx - > ldap_oid ) ;
if ( ret ! = LDB_SUCCESS ) {
ctx - > err = ret ;
return 0 ;
}
}
cmp = ndr_guid_compare ( ctx - > guid , & p - > guid ) ;
if ( cmp = = 0 & & ctx - > compare_extra_part ) {
2017-03-13 12:16:13 +13:00
if ( ctx - > partial_extra_part_length ! = 0 ) {
/* Allow a prefix match on the blob. */
return memcmp ( ctx - > extra_part . data ,
p - > dsdb_dn - > extra_part . data ,
MIN ( ctx - > partial_extra_part_length ,
p - > dsdb_dn - > extra_part . length ) ) ;
} else {
return data_blob_cmp ( & ctx - > extra_part ,
& p - > dsdb_dn - > extra_part ) ;
}
2017-03-13 12:14:23 +13:00
}
return cmp ;
}
/* When a parsed_dn comes from the database, sometimes it is not really parsed. */
int really_parse_trusted_dn ( TALLOC_CTX * mem_ctx , struct ldb_context * ldb ,
struct parsed_dn * pdn , const char * ldap_oid )
{
NTSTATUS status ;
struct dsdb_dn * dsdb_dn = dsdb_dn_parse_trusted ( mem_ctx , ldb , pdn - > v ,
ldap_oid ) ;
if ( dsdb_dn = = NULL ) {
return LDB_ERR_INVALID_DN_SYNTAX ;
}
status = dsdb_get_extended_dn_guid ( dsdb_dn - > dn , & pdn - > guid , " GUID " ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
pdn - > dsdb_dn = dsdb_dn ;
return LDB_SUCCESS ;
}
2019-01-09 15:12:43 +13:00
int get_parsed_dns_trusted ( TALLOC_CTX * mem_ctx , struct ldb_message_element * el ,
struct parsed_dn * * pdn )
{
/* Here we get a list of 'struct parsed_dns' without the parsing */
2019-02-15 13:09:09 +13:00
unsigned int i ;
2019-01-09 15:12:43 +13:00
* pdn = talloc_zero_array ( mem_ctx , struct parsed_dn ,
el - > num_values ) ;
if ( ! * pdn ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
for ( i = 0 ; i < el - > num_values ; i + + ) {
( * pdn ) [ i ] . v = & el - > values [ i ] ;
}
return LDB_SUCCESS ;
}
2017-03-13 12:14:23 +13:00
int parsed_dn_find ( struct ldb_context * ldb , struct parsed_dn * pdn ,
unsigned int count ,
const struct GUID * guid ,
struct ldb_dn * target_dn ,
DATA_BLOB extra_part ,
2017-03-13 12:16:13 +13:00
size_t partial_extra_part_length ,
2017-03-13 12:14:23 +13:00
struct parsed_dn * * exact ,
struct parsed_dn * * next ,
const char * ldap_oid ,
bool compare_extra_part )
{
unsigned int i ;
struct compare_ctx ctx ;
if ( pdn = = NULL ) {
* exact = NULL ;
* next = NULL ;
return LDB_SUCCESS ;
}
if ( unlikely ( GUID_all_zero ( guid ) ) ) {
/*
* When updating a link using DRS , we sometimes get a NULL
* GUID when a forward link has been deleted and its GUID has
* for some reason been forgotten . The best we can do is try
* and match by DN via a linear search . Note that this
* probably only happens in the ADD case , in which we only
* allow modification of link if it is already deleted , so
* this seems very close to an elaborate NO - OP , but we are not
* quite prepared to declare it so .
*
* If the DN is not in our list , we have to add it to the
* beginning of the list , where it would naturally sort .
*/
struct parsed_dn * p ;
if ( target_dn = = NULL ) {
/* We don't know the target DN, so we can't search for DN */
DEBUG ( 1 , ( " parsed_dn_find has a NULL GUID for a linked "
" attribute but we don't have a DN to compare "
" it with \n " ) ) ;
return LDB_ERR_OPERATIONS_ERROR ;
}
* exact = NULL ;
* next = NULL ;
DEBUG ( 3 , ( " parsed_dn_find has a NULL GUID for a link to DN "
" %s; searching through links for it " ,
ldb_dn_get_linearized ( target_dn ) ) ) ;
for ( i = 0 ; i < count ; i + + ) {
int cmp ;
p = & pdn [ i ] ;
if ( p - > dsdb_dn = = NULL ) {
int ret = really_parse_trusted_dn ( pdn , ldb , p , ldap_oid ) ;
if ( ret ! = LDB_SUCCESS ) {
return LDB_ERR_OPERATIONS_ERROR ;
}
}
cmp = ldb_dn_compare ( p - > dsdb_dn - > dn , target_dn ) ;
if ( cmp = = 0 ) {
* exact = p ;
return LDB_SUCCESS ;
}
}
/*
* Here we have a null guid which doesn ' t match any existing
* link . This is a bit unexpected because null guids occur
* when a forward link has been deleted and we are replicating
* that deletion .
*
* The best thing to do is weep into the logs and add the
* offending link to the beginning of the list which is
* at least the correct sort position .
*/
DEBUG ( 1 , ( " parsed_dn_find has been given a NULL GUID for a "
" link to unknown DN %s \n " ,
ldb_dn_get_linearized ( target_dn ) ) ) ;
* next = pdn ;
return LDB_SUCCESS ;
}
ctx . guid = guid ;
ctx . ldb = ldb ;
ctx . mem_ctx = pdn ;
ctx . ldap_oid = ldap_oid ;
ctx . extra_part = extra_part ;
2017-03-13 12:16:13 +13:00
ctx . partial_extra_part_length = partial_extra_part_length ;
2017-03-13 12:14:23 +13:00
ctx . compare_extra_part = compare_extra_part ;
ctx . err = 0 ;
BINARY_ARRAY_SEARCH_GTE ( pdn , count , & ctx , la_guid_compare_with_trusted_dn ,
* exact , * next ) ;
if ( ctx . err ! = 0 ) {
return ctx . err ;
}
return LDB_SUCCESS ;
}