2004-12-06 10:12:38 +03:00
/*
Unix SMB / CIFS implementation .
lsa calls for file sharing connections
Copyright ( C ) Andrew Tridgell 2004
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 2 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 , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
/*
when dealing with ACLs the file sharing client code needs to
sometimes make LSA RPC calls . This code provides an easy interface
for doing those calls .
*/
# include "includes.h"
# include "libcli/raw/libcliraw.h"
2006-01-03 18:40:05 +03:00
# include "libcli/libcli.h"
2006-04-02 16:02:01 +04:00
# include "libcli/security/security.h"
2006-03-16 15:43:28 +03:00
# include "librpc/gen_ndr/ndr_lsa.h"
2006-03-15 02:35:30 +03:00
# include "librpc/gen_ndr/ndr_lsa_c.h"
2004-12-06 10:12:38 +03:00
struct smblsa_state {
struct dcerpc_pipe * pipe ;
struct smbcli_tree * ipc_tree ;
struct policy_handle handle ;
} ;
/*
establish the lsa pipe connection
*/
static NTSTATUS smblsa_connect ( struct smbcli_state * cli )
{
struct smblsa_state * lsa ;
NTSTATUS status ;
struct lsa_OpenPolicy r ;
uint16_t system_name = ' \\ ' ;
union smb_tcon tcon ;
struct lsa_ObjectAttribute attr ;
struct lsa_QosInfo qos ;
if ( cli - > lsa ! = NULL ) {
return NT_STATUS_OK ;
}
2005-01-27 10:08:20 +03:00
lsa = talloc ( cli , struct smblsa_state ) ;
2004-12-06 10:12:38 +03:00
if ( lsa = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2005-01-24 03:57:14 +03:00
lsa - > ipc_tree = smbcli_tree_init ( cli - > session , lsa , False ) ;
2004-12-06 10:12:38 +03:00
if ( lsa - > ipc_tree = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
/* connect to IPC$ */
tcon . generic . level = RAW_TCON_TCONX ;
tcon . tconx . in . flags = 0 ;
tcon . tconx . in . password = data_blob ( NULL , 0 ) ;
tcon . tconx . in . path = " ipc$ " ;
tcon . tconx . in . device = " IPC " ;
2005-08-09 07:09:47 +04:00
status = smb_raw_tcon ( lsa - > ipc_tree , lsa , & tcon ) ;
2004-12-06 10:12:38 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( lsa ) ;
return status ;
}
2005-01-13 21:49:10 +03:00
lsa - > ipc_tree - > tid = tcon . tconx . out . tid ;
2004-12-06 10:12:38 +03:00
2005-06-16 15:36:09 +04:00
lsa - > pipe = dcerpc_pipe_init ( lsa , cli - > transport - > socket - > event . ctx ) ;
2005-01-09 11:34:05 +03:00
if ( lsa - > pipe = = NULL ) {
talloc_free ( lsa ) ;
return NT_STATUS_NO_MEMORY ;
}
2004-12-06 10:12:38 +03:00
/* open the LSA pipe */
2005-01-09 11:34:05 +03:00
status = dcerpc_pipe_open_smb ( lsa - > pipe - > conn , lsa - > ipc_tree , DCERPC_LSARPC_NAME ) ;
2004-12-06 10:12:38 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( lsa ) ;
return status ;
}
/* bind to the LSA pipe */
2005-12-27 17:28:01 +03:00
status = dcerpc_bind_auth_none ( lsa - > pipe , & dcerpc_table_lsarpc ) ;
2004-12-06 10:12:38 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( lsa ) ;
return status ;
}
/* open a lsa policy handle */
qos . len = 0 ;
qos . impersonation_level = 2 ;
qos . context_mode = 1 ;
qos . effective_only = 0 ;
attr . len = 0 ;
attr . root_dir = NULL ;
attr . object_name = NULL ;
attr . attributes = 0 ;
attr . sec_desc = NULL ;
attr . sec_qos = & qos ;
r . in . system_name = & system_name ;
r . in . attr = & attr ;
r . in . access_mask = SEC_FLAG_MAXIMUM_ALLOWED ;
r . out . handle = & lsa - > handle ;
status = dcerpc_lsa_OpenPolicy ( lsa - > pipe , lsa , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( lsa ) ;
return status ;
}
cli - > lsa = lsa ;
return NT_STATUS_OK ;
}
/*
return the set of privileges for the given sid
*/
NTSTATUS smblsa_sid_privileges ( struct smbcli_state * cli , struct dom_sid * sid ,
TALLOC_CTX * mem_ctx ,
struct lsa_RightSet * rights )
{
NTSTATUS status ;
struct lsa_EnumAccountRights r ;
status = smblsa_connect ( cli ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
r . in . handle = & cli - > lsa - > handle ;
r . in . sid = sid ;
r . out . rights = rights ;
return dcerpc_lsa_EnumAccountRights ( cli - > lsa - > pipe , mem_ctx , & r ) ;
}
/*
check if a named sid has a particular named privilege
*/
NTSTATUS smblsa_sid_check_privilege ( struct smbcli_state * cli ,
const char * sid_str ,
const char * privilege )
{
struct lsa_RightSet rights ;
NTSTATUS status ;
2005-01-06 05:32:43 +03:00
TALLOC_CTX * mem_ctx = talloc_new ( cli ) ;
2004-12-06 10:12:38 +03:00
struct dom_sid * sid ;
unsigned i ;
sid = dom_sid_parse_talloc ( mem_ctx , sid_str ) ;
if ( sid = = NULL ) {
talloc_free ( mem_ctx ) ;
return NT_STATUS_INVALID_SID ;
}
status = smblsa_sid_privileges ( cli , sid , mem_ctx , & rights ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( mem_ctx ) ;
return status ;
}
for ( i = 0 ; i < rights . count ; i + + ) {
if ( strcmp ( rights . names [ i ] . string , privilege ) = = 0 ) {
talloc_free ( mem_ctx ) ;
return NT_STATUS_OK ;
}
}
talloc_free ( mem_ctx ) ;
return NT_STATUS_NOT_FOUND ;
}
/*
lookup a SID , returning its name
*/
NTSTATUS smblsa_lookup_sid ( struct smbcli_state * cli ,
const char * sid_str ,
TALLOC_CTX * mem_ctx ,
const char * * name )
{
struct lsa_LookupSids r ;
struct lsa_TransNameArray names ;
struct lsa_SidArray sids ;
uint32_t count = 1 ;
NTSTATUS status ;
struct dom_sid * sid ;
2005-01-06 05:32:43 +03:00
TALLOC_CTX * mem_ctx2 = talloc_new ( mem_ctx ) ;
2004-12-06 10:12:38 +03:00
status = smblsa_connect ( cli ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
sid = dom_sid_parse_talloc ( mem_ctx2 , sid_str ) ;
if ( sid = = NULL ) {
return NT_STATUS_INVALID_SID ;
}
names . count = 0 ;
names . names = NULL ;
sids . num_sids = 1 ;
2005-01-27 10:08:20 +03:00
sids . sids = talloc ( mem_ctx2 , struct lsa_SidPtr ) ;
2004-12-06 10:12:38 +03:00
sids . sids [ 0 ] . sid = sid ;
r . in . handle = & cli - > lsa - > handle ;
r . in . sids = & sids ;
r . in . names = & names ;
r . in . level = 1 ;
r . in . count = & count ;
r . out . count = & count ;
r . out . names = & names ;
status = dcerpc_lsa_LookupSids ( cli - > lsa - > pipe , mem_ctx2 , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( mem_ctx2 ) ;
return status ;
}
if ( names . count ! = 1 ) {
talloc_free ( mem_ctx2 ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
( * name ) = talloc_asprintf ( mem_ctx , " %s \\ %s " ,
r . out . domains - > domains [ 0 ] . name . string ,
names . names [ 0 ] . name . string ) ;
talloc_free ( mem_ctx2 ) ;
return NT_STATUS_OK ;
}
/*
lookup a name , returning its sid
*/
NTSTATUS smblsa_lookup_name ( struct smbcli_state * cli ,
const char * name ,
TALLOC_CTX * mem_ctx ,
const char * * sid_str )
{
struct lsa_LookupNames r ;
struct lsa_TransSidArray sids ;
struct lsa_String names ;
uint32_t count = 1 ;
NTSTATUS status ;
struct dom_sid * sid ;
2005-01-06 05:32:43 +03:00
TALLOC_CTX * mem_ctx2 = talloc_new ( mem_ctx ) ;
2004-12-06 10:12:38 +03:00
uint32_t rid ;
status = smblsa_connect ( cli ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
sids . count = 0 ;
sids . sids = NULL ;
names . string = name ;
r . in . handle = & cli - > lsa - > handle ;
r . in . num_names = 1 ;
r . in . names = & names ;
r . in . sids = & sids ;
r . in . level = 1 ;
r . in . count = & count ;
r . out . count = & count ;
r . out . sids = & sids ;
status = dcerpc_lsa_LookupNames ( cli - > lsa - > pipe , mem_ctx2 , & r ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
talloc_free ( mem_ctx2 ) ;
return status ;
}
if ( sids . count ! = 1 ) {
talloc_free ( mem_ctx2 ) ;
return NT_STATUS_UNSUCCESSFUL ;
}
sid = r . out . domains - > domains [ 0 ] . sid ;
rid = sids . sids [ 0 ] . rid ;
( * sid_str ) = talloc_asprintf ( mem_ctx , " %s-%u " ,
dom_sid_string ( mem_ctx2 , sid ) , rid ) ;
talloc_free ( mem_ctx2 ) ;
return NT_STATUS_OK ;
}
2004-12-14 09:31:20 +03:00
/*
add a set of privileges to the given sid
*/
NTSTATUS smblsa_sid_add_privileges ( struct smbcli_state * cli , struct dom_sid * sid ,
TALLOC_CTX * mem_ctx ,
struct lsa_RightSet * rights )
{
NTSTATUS status ;
struct lsa_AddAccountRights r ;
status = smblsa_connect ( cli ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
r . in . handle = & cli - > lsa - > handle ;
r . in . sid = sid ;
r . in . rights = rights ;
return dcerpc_lsa_AddAccountRights ( cli - > lsa - > pipe , mem_ctx , & r ) ;
}
/*
remove a set of privileges from the given sid
*/
NTSTATUS smblsa_sid_del_privileges ( struct smbcli_state * cli , struct dom_sid * sid ,
TALLOC_CTX * mem_ctx ,
struct lsa_RightSet * rights )
{
NTSTATUS status ;
struct lsa_RemoveAccountRights r ;
status = smblsa_connect ( cli ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
r . in . handle = & cli - > lsa - > handle ;
r . in . sid = sid ;
r . in . unknown = 0 ;
r . in . rights = rights ;
return dcerpc_lsa_RemoveAccountRights ( cli - > lsa - > pipe , mem_ctx , & r ) ;
}