2007-09-19 16:45:35 +04:00
/*
2002-01-30 09:08:46 +03:00
Unix SMB / CIFS implementation .
2000-12-13 15:52:21 +03:00
RPC pipe client
2001-05-07 05:55:08 +04:00
Copyright ( C ) Tim Potter 2000 - 2001 ,
2000-12-13 15:52:21 +03:00
Copyright ( C ) Andrew Tridgell 1992 - 1997 , 2000 ,
2002-05-17 17:49:01 +04:00
Copyright ( C ) Rafal Szczesniak 2002
2005-09-30 21:13:37 +04:00
Copyright ( C ) Jeremy Allison 2005.
2007-09-20 13:15:26 +04:00
Copyright ( C ) Michael Adam 2007.
2008-02-27 21:38:48 +03:00
Copyright ( C ) Guenther Deschner 2008.
2007-09-19 16:45:35 +04:00
2000-12-13 15:52:21 +03:00
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
2007-07-09 23:25:36 +04:00
the Free Software Foundation ; either version 3 of the License , or
2000-12-13 15:52:21 +03:00
( at your option ) any later version .
2007-09-19 16:45:35 +04:00
2000-12-13 15:52:21 +03:00
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 .
2007-09-19 16:45:35 +04:00
2000-12-13 15:52:21 +03:00
You should have received a copy of the GNU General Public License
2007-07-10 04:52:41 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2000-12-13 15:52:21 +03:00
*/
# include "includes.h"
2002-01-06 06:48:41 +03:00
/** @defgroup lsa LSA - Local Security Architecture
2001-11-23 08:50:05 +03:00
* @ ingroup rpc_client
2001-11-15 09:03:22 +03:00
*
* @ {
* */
/**
* @ file cli_lsarpc . c
*
* RPC client routines for the LSA RPC pipe . LSA means " local
* security authority " , which is half of a password database.
* */
2001-11-23 08:50:05 +03:00
/** Open a LSA policy handle
*
* @ param cli Handle on an initialised SMB connection */
2000-12-13 15:52:21 +03:00
2005-06-09 02:10:34 +04:00
NTSTATUS rpccli_lsa_open_policy ( struct rpc_pipe_client * cli ,
TALLOC_CTX * mem_ctx ,
2007-10-19 04:40:25 +04:00
bool sec_qos , uint32 des_access ,
2005-06-09 02:10:34 +04:00
POLICY_HND * pol )
2000-12-13 15:52:21 +03:00
{
2008-02-11 19:50:18 +03:00
struct lsa_ObjectAttribute attr ;
struct lsa_QosInfo qos ;
uint16_t system_name = ' \\ ' ;
2000-12-13 15:52:21 +03:00
2008-12-08 20:03:01 +03:00
ZERO_STRUCT ( attr ) ;
attr . len = 0x18 ;
2000-12-13 15:52:21 +03:00
if ( sec_qos ) {
2008-12-08 20:03:01 +03:00
qos . len = 0xc ;
qos . impersonation_level = 2 ;
qos . context_mode = 1 ;
qos . effective_only = 0 ;
attr . sec_qos = & qos ;
2000-12-13 15:52:21 +03:00
}
2008-02-11 19:50:18 +03:00
return rpccli_lsa_OpenPolicy ( cli , mem_ctx ,
& system_name ,
& attr ,
des_access ,
pol ) ;
2000-12-13 15:52:21 +03:00
}
2002-02-21 01:34:35 +03:00
/** Open a LSA policy handle
*
2007-09-19 16:45:35 +04:00
* @ param cli Handle on an initialised SMB connection
2002-02-21 01:34:35 +03:00
*/
2001-08-21 07:05:27 +04:00
2005-06-09 02:10:34 +04:00
NTSTATUS rpccli_lsa_open_policy2 ( struct rpc_pipe_client * cli ,
2007-10-19 04:40:25 +04:00
TALLOC_CTX * mem_ctx , bool sec_qos ,
2005-06-09 02:10:34 +04:00
uint32 des_access , POLICY_HND * pol )
2001-08-21 07:05:27 +04:00
{
2008-02-11 19:50:18 +03:00
struct lsa_ObjectAttribute attr ;
struct lsa_QosInfo qos ;
2001-08-21 07:05:27 +04:00
2008-12-08 20:03:01 +03:00
ZERO_STRUCT ( attr ) ;
attr . len = 0x18 ;
2001-08-21 07:05:27 +04:00
if ( sec_qos ) {
2008-12-08 20:03:01 +03:00
qos . len = 0xc ;
qos . impersonation_level = 2 ;
qos . context_mode = 1 ;
qos . effective_only = 0 ;
attr . sec_qos = & qos ;
2001-08-21 07:05:27 +04:00
}
2008-02-11 19:50:18 +03:00
return rpccli_lsa_OpenPolicy2 ( cli , mem_ctx ,
2008-04-20 01:03:16 +04:00
cli - > srv_name_slash ,
2008-02-11 19:50:18 +03:00
& attr ,
des_access ,
pol ) ;
2001-08-21 07:05:27 +04:00
}
2007-05-22 15:30:35 +04:00
/* Lookup a list of sids
*
2007-05-22 17:40:01 +04:00
* internal version withOUT memory allocation of the target arrays .
* this assumes suffciently sized arrays to store domains , names and types . */
2007-05-22 15:30:35 +04:00
static NTSTATUS rpccli_lsa_lookup_sids_noalloc ( struct rpc_pipe_client * cli ,
TALLOC_CTX * mem_ctx ,
POLICY_HND * pol ,
int num_sids ,
const DOM_SID * sids ,
char * * domains ,
char * * names ,
2007-10-26 05:29:49 +04:00
enum lsa_SidType * types )
2007-05-22 15:30:35 +04:00
{
NTSTATUS result = NT_STATUS_OK ;
2007-05-22 17:40:01 +04:00
TALLOC_CTX * tmp_ctx = NULL ;
2007-05-22 15:30:35 +04:00
int i ;
2008-02-18 12:03:19 +03:00
struct lsa_SidArray sid_array ;
struct lsa_RefDomainList * ref_domains = NULL ;
struct lsa_TransNameArray lsa_names ;
uint32_t count = 0 ;
uint16_t level = 1 ;
ZERO_STRUCT ( lsa_names ) ;
2007-05-22 15:30:35 +04:00
2007-05-22 17:40:01 +04:00
tmp_ctx = talloc_new ( mem_ctx ) ;
if ( ! tmp_ctx ) {
DEBUG ( 0 , ( " rpccli_lsa_lookup_sids_noalloc: out of memory! \n " ) ) ;
result = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
2008-02-18 12:03:19 +03:00
sid_array . num_sids = num_sids ;
sid_array . sids = TALLOC_ARRAY ( mem_ctx , struct lsa_SidPtr , num_sids ) ;
if ( ! sid_array . sids ) {
return NT_STATUS_NO_MEMORY ;
}
2007-05-22 15:30:35 +04:00
2008-02-18 12:03:19 +03:00
for ( i = 0 ; i < num_sids ; i + + ) {
sid_array . sids [ i ] . sid = sid_dup_talloc ( mem_ctx , & sids [ i ] ) ;
if ( ! sid_array . sids [ i ] . sid ) {
return NT_STATUS_NO_MEMORY ;
}
}
2007-05-22 15:30:35 +04:00
2008-02-18 12:03:19 +03:00
result = rpccli_lsa_LookupSids ( cli , mem_ctx ,
pol ,
& sid_array ,
& ref_domains ,
& lsa_names ,
level ,
& count ) ;
2007-05-22 15:30:35 +04:00
2007-09-19 16:05:47 +04:00
DEBUG ( 10 , ( " LSA_LOOKUPSIDS returned '%s', mapped count = %d' \n " ,
2008-02-18 12:03:19 +03:00
nt_errstr ( result ) , count ) ) ;
2007-09-19 16:05:47 +04:00
2008-02-18 12:03:19 +03:00
if ( ! NT_STATUS_IS_OK ( result ) & &
! NT_STATUS_EQUAL ( result , NT_STATUS_NONE_MAPPED ) & &
! NT_STATUS_EQUAL ( result , STATUS_SOME_UNMAPPED ) )
2007-05-22 15:30:35 +04:00
{
/* An actual error occured */
goto done ;
}
/* Return output parameters */
2008-02-18 12:03:19 +03:00
if ( NT_STATUS_EQUAL ( result , NT_STATUS_NONE_MAPPED ) | |
( count = = 0 ) )
2007-09-19 16:03:02 +04:00
{
2007-08-29 18:34:15 +04:00
for ( i = 0 ; i < num_sids ; i + + ) {
( names ) [ i ] = NULL ;
( domains ) [ i ] = NULL ;
( types ) [ i ] = SID_NAME_UNKNOWN ;
}
2007-05-22 15:30:35 +04:00
result = NT_STATUS_NONE_MAPPED ;
goto done ;
}
for ( i = 0 ; i < num_sids ; i + + ) {
2008-02-18 12:03:19 +03:00
const char * name , * dom_name ;
uint32_t dom_idx = lsa_names . names [ i ] . sid_index ;
2007-05-22 15:30:35 +04:00
/* Translate optimised name through domain index array */
if ( dom_idx ! = 0xffffffff ) {
2008-02-18 12:03:19 +03:00
dom_name = ref_domains - > domains [ dom_idx ] . name . string ;
name = lsa_names . names [ i ] . name . string ;
2007-05-22 15:30:35 +04:00
2008-04-03 02:23:50 +04:00
if ( name ) {
( names ) [ i ] = talloc_strdup ( mem_ctx , name ) ;
if ( ( names ) [ i ] = = NULL ) {
DEBUG ( 0 , ( " cli_lsa_lookup_sids_noalloc(): out of memory \n " ) ) ;
result = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
} else {
( names ) [ i ] = NULL ;
}
2007-05-22 15:30:35 +04:00
( domains ) [ i ] = talloc_strdup ( mem_ctx , dom_name ) ;
2008-02-18 12:03:19 +03:00
( types ) [ i ] = lsa_names . names [ i ] . sid_type ;
2008-04-03 02:23:50 +04:00
if ( ( ( domains ) [ i ] = = NULL ) ) {
2007-06-09 04:13:07 +04:00
DEBUG ( 0 , ( " cli_lsa_lookup_sids_noalloc(): out of memory \n " ) ) ;
2007-05-22 15:30:35 +04:00
result = NT_STATUS_UNSUCCESSFUL ;
goto done ;
}
} else {
2007-05-23 01:17:31 +04:00
( names ) [ i ] = NULL ;
( domains ) [ i ] = NULL ;
2007-05-22 15:30:35 +04:00
( types ) [ i ] = SID_NAME_UNKNOWN ;
}
}
2007-05-22 17:40:01 +04:00
done :
TALLOC_FREE ( tmp_ctx ) ;
2007-05-22 15:30:35 +04:00
return result ;
}
2007-09-19 16:45:35 +04:00
/* Lookup a list of sids
2007-05-22 15:30:35 +04:00
*
* do it the right way : there is a limit ( of 20480 for w2k3 ) entries
* returned by this call . when the sids list contains more entries ,
* empty lists are returned . This version of lsa_lookup_sids passes
* the list of sids in hunks of LOOKUP_SIDS_HUNK_SIZE to the lsa call . */
/* This constant defines the limit of how many sids to look up
* in one call ( maximum ) . the limit from the server side is
* at 20480 for win2k3 , but we keep it at a save 1000 for now . */
# define LOOKUP_SIDS_HUNK_SIZE 1000
2007-09-20 02:11:09 +04:00
NTSTATUS rpccli_lsa_lookup_sids ( struct rpc_pipe_client * cli ,
TALLOC_CTX * mem_ctx ,
POLICY_HND * pol ,
int num_sids ,
const DOM_SID * sids ,
2008-03-05 18:20:34 +03:00
char * * * pdomains ,
char * * * pnames ,
enum lsa_SidType * * ptypes )
2007-05-22 15:30:35 +04:00
{
NTSTATUS result = NT_STATUS_OK ;
int sids_left = 0 ;
int sids_processed = 0 ;
const DOM_SID * hunk_sids = sids ;
2008-03-05 18:20:34 +03:00
char * * hunk_domains ;
char * * hunk_names ;
enum lsa_SidType * hunk_types ;
char * * domains = NULL ;
char * * names = NULL ;
enum lsa_SidType * types = NULL ;
2007-05-22 15:30:35 +04:00
if ( num_sids ) {
2008-03-05 18:20:34 +03:00
if ( ! ( domains = TALLOC_ARRAY ( mem_ctx , char * , num_sids ) ) ) {
2007-09-20 02:11:09 +04:00
DEBUG ( 0 , ( " rpccli_lsa_lookup_sids(): out of memory \n " ) ) ;
2007-05-22 15:30:35 +04:00
result = NT_STATUS_NO_MEMORY ;
2007-09-19 15:01:44 +04:00
goto fail ;
2007-05-22 15:30:35 +04:00
}
2008-03-05 18:20:34 +03:00
if ( ! ( names = TALLOC_ARRAY ( mem_ctx , char * , num_sids ) ) ) {
2007-09-20 02:11:09 +04:00
DEBUG ( 0 , ( " rpccli_lsa_lookup_sids(): out of memory \n " ) ) ;
2007-05-22 15:30:35 +04:00
result = NT_STATUS_NO_MEMORY ;
2007-09-19 15:01:44 +04:00
goto fail ;
2007-05-22 15:30:35 +04:00
}
2008-03-05 18:20:34 +03:00
if ( ! ( types = TALLOC_ARRAY ( mem_ctx , enum lsa_SidType , num_sids ) ) ) {
2007-09-20 02:11:09 +04:00
DEBUG ( 0 , ( " rpccli_lsa_lookup_sids(): out of memory \n " ) ) ;
2007-05-22 15:30:35 +04:00
result = NT_STATUS_NO_MEMORY ;
2007-09-19 15:01:44 +04:00
goto fail ;
2007-05-22 15:30:35 +04:00
}
}
2007-09-19 16:45:35 +04:00
2007-05-22 15:30:35 +04:00
sids_left = num_sids ;
2008-03-05 18:20:34 +03:00
hunk_domains = domains ;
hunk_names = names ;
hunk_types = types ;
2007-05-22 15:30:35 +04:00
while ( sids_left > 0 ) {
int hunk_num_sids ;
NTSTATUS hunk_result = NT_STATUS_OK ;
2007-09-19 16:45:35 +04:00
hunk_num_sids = ( ( sids_left > LOOKUP_SIDS_HUNK_SIZE )
? LOOKUP_SIDS_HUNK_SIZE
2007-05-22 15:30:35 +04:00
: sids_left ) ;
2007-09-20 02:11:09 +04:00
DEBUG ( 10 , ( " rpccli_lsa_lookup_sids: processing items "
2007-09-19 16:45:35 +04:00
" %d -- %d of %d. \n " ,
sids_processed ,
2007-05-22 15:30:35 +04:00
sids_processed + hunk_num_sids - 1 ,
num_sids ) ) ;
2007-05-22 17:40:01 +04:00
hunk_result = rpccli_lsa_lookup_sids_noalloc ( cli ,
mem_ctx ,
2007-05-22 15:30:35 +04:00
pol ,
2007-09-19 16:45:35 +04:00
hunk_num_sids ,
2007-05-22 15:30:35 +04:00
hunk_sids ,
hunk_domains ,
hunk_names ,
hunk_types ) ;
if ( ! NT_STATUS_IS_OK ( hunk_result ) & &
! NT_STATUS_EQUAL ( hunk_result , STATUS_SOME_UNMAPPED ) & &
2007-09-19 16:45:35 +04:00
! NT_STATUS_EQUAL ( hunk_result , NT_STATUS_NONE_MAPPED ) )
2007-05-22 15:30:35 +04:00
{
/* An actual error occured */
2007-09-19 15:01:44 +04:00
result = hunk_result ;
goto fail ;
2007-05-22 15:30:35 +04:00
}
/* adapt overall result */
2007-09-19 16:45:35 +04:00
if ( ( NT_STATUS_IS_OK ( result ) & &
! NT_STATUS_IS_OK ( hunk_result ) )
2007-05-22 15:30:35 +04:00
| |
( NT_STATUS_EQUAL ( result , NT_STATUS_NONE_MAPPED ) & &
! NT_STATUS_EQUAL ( hunk_result , NT_STATUS_NONE_MAPPED ) ) )
{
result = STATUS_SOME_UNMAPPED ;
}
sids_left - = hunk_num_sids ;
sids_processed + = hunk_num_sids ; /* only used in DEBUG */
hunk_sids + = hunk_num_sids ;
hunk_domains + = hunk_num_sids ;
hunk_names + = hunk_num_sids ;
hunk_types + = hunk_num_sids ;
}
2008-03-05 18:20:34 +03:00
* pdomains = domains ;
* pnames = names ;
* ptypes = types ;
2007-09-19 15:01:44 +04:00
return result ;
fail :
2008-03-05 18:20:34 +03:00
TALLOC_FREE ( domains ) ;
TALLOC_FREE ( names ) ;
TALLOC_FREE ( types ) ;
2007-05-22 15:30:35 +04:00
return result ;
}
2001-11-15 09:03:22 +03:00
/** Lookup a list of names */
2000-12-13 15:52:21 +03:00
2005-06-09 02:10:34 +04:00
NTSTATUS rpccli_lsa_lookup_names ( struct rpc_pipe_client * cli ,
TALLOC_CTX * mem_ctx ,
2007-09-19 16:45:35 +04:00
POLICY_HND * pol , int num_names ,
2006-02-04 01:19:41 +03:00
const char * * names ,
const char * * * dom_names ,
2007-06-27 15:42:17 +04:00
int level ,
2006-02-04 01:19:41 +03:00
DOM_SID * * sids ,
2007-10-26 05:29:49 +04:00
enum lsa_SidType * * types )
2000-12-13 15:52:21 +03:00
{
2001-08-28 01:32:54 +04:00
NTSTATUS result ;
2000-12-13 15:52:21 +03:00
int i ;
2008-02-18 06:30:57 +03:00
struct lsa_String * lsa_names = NULL ;
struct lsa_RefDomainList * domains = NULL ;
struct lsa_TransSidArray sid_array ;
uint32_t count = 0 ;
2007-09-19 16:45:35 +04:00
2008-02-18 06:30:57 +03:00
ZERO_STRUCT ( sid_array ) ;
2000-12-13 15:52:21 +03:00
2008-02-18 06:30:57 +03:00
lsa_names = TALLOC_ARRAY ( mem_ctx , struct lsa_String , num_names ) ;
if ( ! lsa_names ) {
return NT_STATUS_NO_MEMORY ;
}
2005-09-30 21:13:37 +04:00
2008-02-18 06:30:57 +03:00
for ( i = 0 ; i < num_names ; i + + ) {
init_lsa_String ( & lsa_names [ i ] , names [ i ] ) ;
}
2000-12-13 15:52:21 +03:00
2008-02-18 06:30:57 +03:00
result = rpccli_lsa_LookupNames ( cli , mem_ctx ,
pol ,
num_names ,
lsa_names ,
& domains ,
& sid_array ,
level ,
& count ) ;
2000-12-13 15:52:21 +03:00
2002-04-14 15:21:25 +04:00
if ( ! NT_STATUS_IS_OK ( result ) & & NT_STATUS_V ( result ) ! =
NT_STATUS_V ( STATUS_SOME_UNMAPPED ) ) {
2000-12-13 15:52:21 +03:00
/* An actual error occured */
goto done ;
}
/* Return output parameters */
2008-02-18 06:30:57 +03:00
if ( count = = 0 ) {
2001-11-22 11:31:50 +03:00
result = NT_STATUS_NONE_MAPPED ;
goto done ;
}
2007-04-30 06:39:34 +04:00
if ( num_names ) {
if ( ! ( ( * sids = TALLOC_ARRAY ( mem_ctx , DOM_SID , num_names ) ) ) ) {
DEBUG ( 0 , ( " cli_lsa_lookup_sids(): out of memory \n " ) ) ;
result = NT_STATUS_NO_MEMORY ;
goto done ;
}
2000-12-13 15:52:21 +03:00
2007-10-26 05:29:49 +04:00
if ( ! ( ( * types = TALLOC_ARRAY ( mem_ctx , enum lsa_SidType , num_names ) ) ) ) {
2006-02-04 01:19:41 +03:00
DEBUG ( 0 , ( " cli_lsa_lookup_sids(): out of memory \n " ) ) ;
result = NT_STATUS_NO_MEMORY ;
goto done ;
}
2007-04-30 06:39:34 +04:00
if ( dom_names ! = NULL ) {
* dom_names = TALLOC_ARRAY ( mem_ctx , const char * , num_names ) ;
if ( * dom_names = = NULL ) {
DEBUG ( 0 , ( " cli_lsa_lookup_sids(): out of memory \n " ) ) ;
result = NT_STATUS_NO_MEMORY ;
goto done ;
}
}
} else {
* sids = NULL ;
* types = NULL ;
if ( dom_names ! = NULL ) {
* dom_names = NULL ;
}
2006-02-04 01:19:41 +03:00
}
2002-04-14 15:21:25 +04:00
for ( i = 0 ; i < num_names ; i + + ) {
2008-02-18 06:30:57 +03:00
uint32_t dom_idx = sid_array . sids [ i ] . sid_index ;
uint32_t dom_rid = sid_array . sids [ i ] . rid ;
2000-12-13 15:52:21 +03:00
DOM_SID * sid = & ( * sids ) [ i ] ;
/* Translate optimised sid through domain index array */
2006-02-04 01:19:41 +03:00
if ( dom_idx = = 0xffffffff ) {
/* Nothing to do, this is unknown */
ZERO_STRUCTP ( sid ) ;
( * types ) [ i ] = SID_NAME_UNKNOWN ;
continue ;
}
2000-12-13 15:52:21 +03:00
2008-02-18 06:30:57 +03:00
sid_copy ( sid , domains - > domains [ dom_idx ] . sid ) ;
2000-12-13 15:52:21 +03:00
2006-02-04 01:19:41 +03:00
if ( dom_rid ! = 0xffffffff ) {
sid_append_rid ( sid , dom_rid ) ;
}
2000-12-13 15:52:21 +03:00
2008-02-18 06:30:57 +03:00
( * types ) [ i ] = sid_array . sids [ i ] . sid_type ;
2006-02-04 01:19:41 +03:00
if ( dom_names = = NULL ) {
continue ;
2000-12-13 15:52:21 +03:00
}
2006-02-04 01:19:41 +03:00
2008-02-18 06:30:57 +03:00
( * dom_names ) [ i ] = domains - > domains [ dom_idx ] . name . string ;
2000-12-13 15:52:21 +03:00
}
done :
2000-12-15 04:02:11 +03:00
2000-12-13 15:52:21 +03:00
return result ;
2002-08-12 17:40:59 +04:00
}