2004-05-03 18:58:08 +04:00
/*
Unix SMB / CIFS implementation .
endpoint server for the samr pipe
Copyright ( C ) Andrew Tridgell 2004
2004-12-29 02:05:48 +03:00
Copyright ( C ) Volker Lendecke 2004
2005-01-12 10:57:33 +03:00
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2004 - 2005
2004-05-03 18:58:08 +04: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-10 06:07:03 +04:00
the Free Software Foundation ; either version 3 of the License , or
2004-05-03 18:58:08 +04:00
( 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
2007-07-10 06:07:03 +04:00
along with this program . If not , see < http : //www.gnu.org/licenses/>.
2004-05-03 18:58:08 +04:00
*/
# include "includes.h"
2004-11-01 13:30:34 +03:00
# include "librpc/gen_ndr/ndr_samr.h"
2004-11-02 10:42:47 +03:00
# include "rpc_server/dcerpc_server.h"
2004-05-04 10:11:47 +04:00
# include "rpc_server/common/common.h"
2004-05-24 09:35:59 +04:00
# include "rpc_server/samr/dcesrv_samr.h"
2004-11-02 03:24:21 +03:00
# include "system/time.h"
2004-11-16 12:00:52 +03:00
# include "lib/ldb/include/ldb.h"
2006-06-15 03:47:45 +04:00
# include "lib/ldb/include/ldb_errors.h"
2006-08-30 15:29:34 +04:00
# include "dsdb/common/flags.h"
2005-12-28 18:38:36 +03:00
# include "dsdb/samdb/samdb.h"
# include "libcli/ldap/ldap.h"
2006-04-02 16:02:01 +04:00
# include "libcli/security/security.h"
2006-03-07 02:28:18 +03:00
# include "rpc_server/samr/proto.h"
2006-03-07 14:07:23 +03:00
# include "db_wrap.h"
2004-05-06 11:32:51 +04:00
2006-07-04 06:46:24 +04:00
/* these query macros make samr_Query[User|Group]Info a bit easier to read */
# define QUERY_STRING(msg, field, attr) \
2007-07-27 06:07:17 +04:00
r - > out . info - > field . string = samdb_result_string ( msg , attr , " " ) ;
2006-07-04 06:46:24 +04:00
# define QUERY_UINT(msg, field, attr) \
r - > out . info - > field = samdb_result_uint ( msg , attr , 0 ) ;
# define QUERY_RID(msg, field, attr) \
r - > out . info - > field = samdb_result_rid_from_sid ( mem_ctx , msg , attr , 0 ) ;
2007-09-06 08:01:52 +04:00
# define QUERY_UINT64(msg, field, attr) \
r - > out . info - > field = samdb_result_uint64 ( msg , attr , 0 ) ;
2006-07-04 06:46:24 +04:00
# define QUERY_APASSC(msg, field, attr) \
r - > out . info - > field = samdb_result_allow_password_change ( sam_ctx , mem_ctx , \
a_state - > domain_state - > domain_dn , msg , attr ) ;
# define QUERY_FPASSC(msg, field, attr) \
r - > out . info - > field = samdb_result_force_password_change ( sam_ctx , mem_ctx , \
a_state - > domain_state - > domain_dn , msg ) ;
# define QUERY_LHOURS(msg, field, attr) \
r - > out . info - > field = samdb_result_logon_hours ( mem_ctx , msg , attr ) ;
# define QUERY_AFLAGS(msg, field, attr) \
r - > out . info - > field = samdb_result_acct_flags ( msg , attr ) ;
/* these are used to make the Set[User|Group]Info code easier to follow */
2007-07-27 06:07:17 +04:00
# define SET_STRING(msg, field, attr) do { \
struct ldb_message_element * set_el ; \
if ( r - > in . info - > field . string = = NULL ) return NT_STATUS_INVALID_PARAMETER ; \
if ( r - > in . info - > field . string [ 0 ] = = ' \0 ' ) { \
if ( ldb_msg_add_empty ( msg , attr , LDB_FLAG_MOD_DELETE , NULL ) ) { \
return NT_STATUS_NO_MEMORY ; \
} \
} \
if ( ldb_msg_add_string ( msg , attr , r - > in . info - > field . string ) ! = 0 ) { \
return NT_STATUS_NO_MEMORY ; \
} \
set_el = ldb_msg_find_element ( msg , attr ) ; \
set_el - > flags = LDB_FLAG_MOD_REPLACE ; \
2006-07-04 06:46:24 +04:00
} while ( 0 )
2007-07-27 06:07:17 +04:00
# define SET_UINT(msg, field, attr) do { \
struct ldb_message_element * set_el ; \
if ( samdb_msg_add_uint ( sam_ctx , mem_ctx , msg , attr , r - > in . info - > field ) ! = 0 ) { \
return NT_STATUS_NO_MEMORY ; \
} \
set_el = ldb_msg_find_element ( msg , attr ) ; \
set_el - > flags = LDB_FLAG_MOD_REPLACE ; \
} while ( 0 )
# define SET_INT64(msg, field, attr) do { \
struct ldb_message_element * set_el ; \
if ( samdb_msg_add_int64 ( sam_ctx , mem_ctx , msg , attr , r - > in . info - > field ) ! = 0 ) { \
return NT_STATUS_NO_MEMORY ; \
} \
set_el = ldb_msg_find_element ( msg , attr ) ; \
set_el - > flags = LDB_FLAG_MOD_REPLACE ; \
} while ( 0 )
# define SET_UINT64(msg, field, attr) do { \
struct ldb_message_element * set_el ; \
if ( samdb_msg_add_uint64 ( sam_ctx , mem_ctx , msg , attr , r - > in . info - > field ) ! = 0 ) { \
return NT_STATUS_NO_MEMORY ; \
} \
set_el = ldb_msg_find_element ( msg , attr ) ; \
set_el - > flags = LDB_FLAG_MOD_REPLACE ; \
} while ( 0 )
# define SET_AFLAGS(msg, field, attr) do { \
struct ldb_message_element * set_el ; \
2006-07-04 06:46:24 +04:00
if ( samdb_msg_add_acct_flags ( sam_ctx , mem_ctx , msg , attr , r - > in . info - > field ) ! = 0 ) { \
2007-07-27 06:07:17 +04:00
return NT_STATUS_NO_MEMORY ; \
} \
set_el = ldb_msg_find_element ( msg , attr ) ; \
set_el - > flags = LDB_FLAG_MOD_REPLACE ; \
} while ( 0 )
# define SET_LHOURS(msg, field, attr) do { \
struct ldb_message_element * set_el ; \
2006-07-04 06:46:24 +04:00
if ( samdb_msg_add_logon_hours ( sam_ctx , mem_ctx , msg , attr , & r - > in . info - > field ) ! = 0 ) { \
2007-07-27 06:07:17 +04:00
return NT_STATUS_NO_MEMORY ; \
} \
set_el = ldb_msg_find_element ( msg , attr ) ; \
set_el - > flags = LDB_FLAG_MOD_REPLACE ; \
2006-07-04 06:46:24 +04:00
} while ( 0 )
2004-05-03 18:58:08 +04:00
/*
samr_Connect
create a connection to the SAM database
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_Connect ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_Connect * r )
{
2004-05-10 16:37:06 +04:00
struct samr_connect_state * c_state ;
2004-05-03 18:58:08 +04:00
struct dcesrv_handle * handle ;
2004-09-21 07:51:38 +04:00
ZERO_STRUCTP ( r - > out . connect_handle ) ;
2004-05-03 18:58:08 +04:00
2005-01-27 10:08:20 +03:00
c_state = talloc ( dce_call - > conn , struct samr_connect_state ) ;
2004-05-10 16:37:06 +04:00
if ( ! c_state ) {
2004-05-03 18:58:08 +04:00
return NT_STATUS_NO_MEMORY ;
}
/* make sure the sam database is accessible */
2005-10-07 15:31:45 +04:00
c_state - > sam_ctx = samdb_connect ( c_state , dce_call - > conn - > auth_state . session_info ) ;
2004-05-10 16:37:06 +04:00
if ( c_state - > sam_ctx = = NULL ) {
2004-09-08 04:00:56 +04:00
talloc_free ( c_state ) ;
2004-05-04 10:07:52 +04:00
return NT_STATUS_INVALID_SYSTEM_SERVICE ;
2004-05-03 18:58:08 +04:00
}
2005-10-07 15:31:45 +04:00
2005-01-10 15:15:26 +03:00
handle = dcesrv_handle_new ( dce_call - > context , SAMR_HANDLE_CONNECT ) ;
2004-05-03 18:58:08 +04:00
if ( ! handle ) {
2004-08-25 10:44:23 +04:00
talloc_free ( c_state ) ;
2004-05-03 18:58:08 +04:00
return NT_STATUS_NO_MEMORY ;
}
2005-01-10 15:15:26 +03:00
handle - > data = talloc_steal ( handle , c_state ) ;
2004-05-03 18:58:08 +04:00
2004-05-10 16:37:06 +04:00
c_state - > access_mask = r - > in . access_mask ;
2004-09-21 07:51:38 +04:00
* r - > out . connect_handle = handle - > wire_handle ;
2004-05-03 18:58:08 +04:00
return NT_STATUS_OK ;
}
/*
samr_Close
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_Close ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_Close * r )
{
2004-05-08 04:02:31 +04:00
struct dcesrv_handle * h ;
* r - > out . handle = * r - > in . handle ;
DCESRV_PULL_HANDLE ( h , r - > in . handle , DCESRV_HANDLE_ANY ) ;
2004-05-03 18:58:08 +04:00
2005-01-10 15:15:26 +03:00
talloc_free ( h ) ;
2004-05-03 18:58:08 +04:00
ZERO_STRUCTP ( r - > out . handle ) ;
return NT_STATUS_OK ;
}
/*
samr_SetSecurity
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_SetSecurity ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_SetSecurity * r )
{
2004-05-04 10:07:52 +04:00
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
2004-05-03 18:58:08 +04:00
}
/*
samr_QuerySecurity
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_QuerySecurity ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_QuerySecurity * r )
{
2004-05-28 17:23:30 +04:00
struct dcesrv_handle * h ;
2004-11-20 03:29:04 +03:00
struct sec_desc_buf * sd ;
2004-05-28 17:23:30 +04:00
r - > out . sdbuf = NULL ;
DCESRV_PULL_HANDLE ( h , r - > in . handle , DCESRV_HANDLE_ANY ) ;
2005-01-27 10:08:20 +03:00
sd = talloc ( mem_ctx , struct sec_desc_buf ) ;
2004-05-28 17:23:30 +04:00
if ( sd = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
sd - > sd = samdb_default_security_descriptor ( mem_ctx ) ;
r - > out . sdbuf = sd ;
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
/*
samr_Shutdown
we refuse this operation completely . If a admin wants to shutdown samr
in Samba then they should use the samba admin tools to disable the samr pipe
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_Shutdown ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_Shutdown * r )
{
return NT_STATUS_ACCESS_DENIED ;
}
/*
samr_LookupDomain
this maps from a domain name to a SID
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_LookupDomain ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_LookupDomain * r )
{
2004-05-10 16:37:06 +04:00
struct samr_connect_state * c_state ;
2004-05-03 18:58:08 +04:00
struct dcesrv_handle * h ;
2005-06-24 04:18:20 +04:00
struct dom_sid * sid ;
2005-08-03 22:30:21 +04:00
const char * const dom_attrs [ ] = { " objectSid " , NULL } ;
const char * const ref_attrs [ ] = { " ncName " , NULL } ;
struct ldb_message * * dom_msgs ;
struct ldb_message * * ref_msgs ;
int ret ;
2006-11-22 03:59:34 +03:00
struct ldb_dn * partitions_basedn ;
2005-08-03 22:30:21 +04:00
2004-05-08 04:02:31 +04:00
r - > out . sid = NULL ;
2004-05-04 10:07:52 +04:00
2004-09-21 07:51:38 +04:00
DCESRV_PULL_HANDLE ( h , r - > in . connect_handle , SAMR_HANDLE_CONNECT ) ;
2004-05-03 18:58:08 +04:00
2004-05-10 16:37:06 +04:00
c_state = h - > data ;
2004-05-06 16:42:42 +04:00
2005-02-13 03:26:43 +03:00
if ( r - > in . domain_name - > string = = NULL ) {
2004-05-04 10:07:52 +04:00
return NT_STATUS_INVALID_PARAMETER ;
2004-05-03 18:58:08 +04:00
}
2006-08-25 11:32:18 +04:00
partitions_basedn = samdb_partitions_dn ( c_state - > sam_ctx , mem_ctx ) ;
2005-08-03 22:30:21 +04:00
if ( strcasecmp ( r - > in . domain_name - > string , " BUILTIN " ) = = 0 ) {
ret = gendb_search ( c_state - > sam_ctx ,
2006-08-25 11:08:06 +04:00
mem_ctx , NULL , & dom_msgs , dom_attrs ,
2005-08-03 22:30:21 +04:00
" (objectClass=builtinDomain) " ) ;
} else {
ret = gendb_search ( c_state - > sam_ctx ,
2006-06-15 03:47:45 +04:00
mem_ctx , partitions_basedn , & ref_msgs , ref_attrs ,
2005-08-03 22:30:21 +04:00
" (&(&(nETBIOSName=%s)(objectclass=crossRef))(ncName=*)) " ,
2005-12-19 10:07:11 +03:00
ldb_binary_encode_string ( mem_ctx , r - > in . domain_name - > string ) ) ;
2005-08-03 22:30:21 +04:00
if ( ret ! = 1 ) {
return NT_STATUS_NO_SUCH_DOMAIN ;
}
ret = gendb_search_dn ( c_state - > sam_ctx , mem_ctx ,
2006-11-22 03:59:34 +03:00
samdb_result_dn ( c_state - > sam_ctx , mem_ctx ,
2005-09-02 03:26:50 +04:00
ref_msgs [ 0 ] , " ncName " , NULL ) ,
2005-08-03 22:30:21 +04:00
& dom_msgs , dom_attrs ) ;
}
if ( ret ! = 1 ) {
return NT_STATUS_NO_SUCH_DOMAIN ;
}
sid = samdb_result_dom_sid ( mem_ctx , dom_msgs [ 0 ] ,
" objectSid " ) ;
2004-05-03 18:58:08 +04:00
if ( sid = = NULL ) {
2005-06-24 04:18:20 +04:00
return NT_STATUS_NO_SUCH_DOMAIN ;
2004-05-03 18:58:08 +04:00
}
r - > out . sid = sid ;
return NT_STATUS_OK ;
}
/*
samr_EnumDomains
list the domains in the SAM
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_EnumDomains ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_EnumDomains * r )
{
2004-05-10 16:37:06 +04:00
struct samr_connect_state * c_state ;
2004-05-03 18:58:08 +04:00
struct dcesrv_handle * h ;
struct samr_SamArray * array ;
int count , i , start_i ;
2005-08-03 22:30:21 +04:00
const char * const dom_attrs [ ] = { " cn " , NULL } ;
const char * const ref_attrs [ ] = { " nETBIOSName " , NULL } ;
struct ldb_message * * dom_msgs ;
struct ldb_message * * ref_msgs ;
2006-11-22 03:59:34 +03:00
struct ldb_dn * partitions_basedn ;
2004-05-03 18:58:08 +04:00
* r - > out . resume_handle = 0 ;
r - > out . sam = NULL ;
r - > out . num_entries = 0 ;
2004-09-21 07:51:38 +04:00
DCESRV_PULL_HANDLE ( h , r - > in . connect_handle , SAMR_HANDLE_CONNECT ) ;
2004-05-08 04:02:31 +04:00
2004-05-10 16:37:06 +04:00
c_state = h - > data ;
2004-05-08 04:02:31 +04:00
2006-08-25 11:32:18 +04:00
partitions_basedn = samdb_partitions_dn ( c_state - > sam_ctx , mem_ctx ) ;
2005-08-03 22:30:21 +04:00
count = gendb_search ( c_state - > sam_ctx ,
2006-08-25 11:08:06 +04:00
mem_ctx , NULL , & dom_msgs , dom_attrs ,
2006-06-15 03:47:45 +04:00
" (objectClass=domain) " ) ;
2004-05-03 18:58:08 +04:00
if ( count = = - 1 ) {
2004-07-05 11:24:14 +04:00
DEBUG ( 0 , ( " samdb: no domains found in EnumDomains \n " ) ) ;
2004-05-04 10:07:52 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
2004-05-03 18:58:08 +04:00
}
* r - > out . resume_handle = count ;
start_i = * r - > in . resume_handle ;
if ( start_i > = count ) {
/* search past end of list is not an error for this call */
return NT_STATUS_OK ;
}
2005-01-27 10:08:20 +03:00
array = talloc ( mem_ctx , struct samr_SamArray ) ;
2004-05-03 18:58:08 +04:00
if ( array = = NULL ) {
2004-05-04 10:07:52 +04:00
return NT_STATUS_NO_MEMORY ;
2004-05-03 18:58:08 +04:00
}
array - > count = 0 ;
array - > entries = NULL ;
2005-01-27 10:08:20 +03:00
array - > entries = talloc_array ( mem_ctx , struct samr_SamEntry , count - start_i ) ;
2004-05-03 18:58:08 +04:00
if ( array - > entries = = NULL ) {
2004-05-04 10:07:52 +04:00
return NT_STATUS_NO_MEMORY ;
2004-05-03 18:58:08 +04:00
}
for ( i = 0 ; i < count - start_i ; i + + ) {
2005-08-03 22:30:21 +04:00
int ret ;
2004-05-03 18:58:08 +04:00
array - > entries [ i ] . idx = start_i + i ;
2005-08-03 22:30:21 +04:00
/* try and find the domain */
2006-06-15 03:47:45 +04:00
ret = gendb_search ( c_state - > sam_ctx , mem_ctx , partitions_basedn ,
2005-08-03 23:58:58 +04:00
& ref_msgs , ref_attrs ,
2005-08-03 22:30:21 +04:00
" (&(objectClass=crossRef)(ncName=%s)) " ,
2006-11-22 05:05:19 +03:00
ldb_dn_get_linearized ( dom_msgs [ i ] - > dn ) ) ;
2005-08-03 22:30:21 +04:00
if ( ret = = 1 ) {
array - > entries [ i ] . name . string = samdb_result_string ( ref_msgs [ 0 ] , " nETBIOSName " , NULL ) ;
} else {
2005-08-03 23:58:58 +04:00
array - > entries [ i ] . name . string = samdb_result_string ( dom_msgs [ i ] , " cn " , NULL ) ;
2005-08-03 22:30:21 +04:00
}
2004-05-03 18:58:08 +04:00
}
r - > out . sam = array ;
2004-05-20 11:49:34 +04:00
r - > out . num_entries = i ;
2004-05-03 18:58:08 +04:00
array - > count = r - > out . num_entries ;
return NT_STATUS_OK ;
}
/*
samr_OpenDomain
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_OpenDomain ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-04 11:53:06 +04:00
struct samr_OpenDomain * r )
2004-05-03 18:58:08 +04:00
{
2004-05-04 11:53:06 +04:00
struct dcesrv_handle * h_conn , * h_domain ;
2005-06-24 04:18:20 +04:00
const char * domain_name ;
2004-05-06 16:42:42 +04:00
struct samr_connect_state * c_state ;
2004-05-10 16:37:06 +04:00
struct samr_domain_state * d_state ;
2005-08-03 23:58:58 +04:00
const char * const dom_attrs [ ] = { " cn " , NULL } ;
2005-08-03 22:30:21 +04:00
const char * const ref_attrs [ ] = { " nETBIOSName " , NULL } ;
struct ldb_message * * dom_msgs ;
struct ldb_message * * ref_msgs ;
2004-05-08 04:02:31 +04:00
int ret ;
2006-11-22 03:59:34 +03:00
struct ldb_dn * partitions_basedn ;
2004-05-08 04:02:31 +04:00
ZERO_STRUCTP ( r - > out . domain_handle ) ;
2004-05-04 11:53:06 +04:00
2004-09-21 07:51:38 +04:00
DCESRV_PULL_HANDLE ( h_conn , r - > in . connect_handle , SAMR_HANDLE_CONNECT ) ;
2004-05-04 11:53:06 +04:00
2004-05-06 16:42:42 +04:00
c_state = h_conn - > data ;
2004-05-08 04:02:31 +04:00
if ( r - > in . sid = = NULL ) {
return NT_STATUS_INVALID_PARAMETER ;
}
2006-08-25 11:32:18 +04:00
partitions_basedn = samdb_partitions_dn ( c_state - > sam_ctx , mem_ctx ) ;
2005-03-23 04:30:43 +03:00
ret = gendb_search ( c_state - > sam_ctx ,
2006-08-25 11:08:06 +04:00
mem_ctx , NULL , & dom_msgs , dom_attrs ,
2006-09-12 08:03:43 +04:00
" (&(objectSid=%s)(&(|(objectclass=domain)(objectClass=builtinDomain)))) " ,
2005-06-24 04:18:20 +04:00
ldap_encode_ndr_dom_sid ( mem_ctx , r - > in . sid ) ) ;
2006-09-12 04:41:12 +04:00
if ( ret = = 0 ) {
return NT_STATUS_NO_SUCH_DOMAIN ;
} else if ( ret > 1 ) {
2005-08-03 23:58:58 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
2006-09-12 04:41:12 +04:00
} else if ( ret = = - 1 ) {
DEBUG ( 1 , ( " Failed to open domain %s: %s \n " , dom_sid_string ( mem_ctx , r - > in . sid ) , ldb_errstring ( c_state - > sam_ctx ) ) ) ;
2006-12-13 14:19:51 +03:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
2005-08-03 23:58:58 +04:00
} else {
ret = gendb_search ( c_state - > sam_ctx ,
2006-06-15 03:47:45 +04:00
mem_ctx , partitions_basedn , & ref_msgs , ref_attrs ,
2005-08-03 23:58:58 +04:00
" (&(&(nETBIOSName=*)(objectclass=crossRef))(ncName=%s)) " ,
2006-11-22 05:05:19 +03:00
ldb_dn_get_linearized ( dom_msgs [ 0 ] - > dn ) ) ;
2005-09-02 03:26:50 +04:00
if ( ret = = 0 ) {
2006-08-13 12:00:36 +04:00
domain_name = ldb_msg_find_attr_as_string ( dom_msgs [ 0 ] , " cn " , NULL ) ;
2005-09-02 03:26:50 +04:00
if ( domain_name = = NULL ) {
return NT_STATUS_NO_SUCH_DOMAIN ;
}
} else if ( ret = = 1 ) {
2005-08-03 23:58:58 +04:00
2006-08-13 12:00:36 +04:00
domain_name = ldb_msg_find_attr_as_string ( ref_msgs [ 0 ] , " nETBIOSName " , NULL ) ;
2005-09-02 03:26:50 +04:00
if ( domain_name = = NULL ) {
return NT_STATUS_NO_SUCH_DOMAIN ;
}
} else {
2005-08-03 23:58:58 +04:00
return NT_STATUS_NO_SUCH_DOMAIN ;
}
2004-05-04 11:53:06 +04:00
}
2005-01-27 10:08:20 +03:00
d_state = talloc ( c_state , struct samr_domain_state ) ;
2004-05-10 16:37:06 +04:00
if ( ! d_state ) {
2004-05-04 11:53:06 +04:00
return NT_STATUS_NO_MEMORY ;
}
2004-09-27 09:13:00 +04:00
d_state - > connect_state = talloc_reference ( d_state , c_state ) ;
2004-05-10 16:37:06 +04:00
d_state - > sam_ctx = c_state - > sam_ctx ;
2005-06-24 04:18:20 +04:00
d_state - > domain_sid = dom_sid_dup ( d_state , r - > in . sid ) ;
2004-08-25 10:44:23 +04:00
d_state - > domain_name = talloc_strdup ( d_state , domain_name ) ;
2005-08-18 19:02:01 +04:00
d_state - > domain_dn = ldb_dn_copy ( d_state , dom_msgs [ 0 ] - > dn ) ;
2004-05-10 16:37:06 +04:00
if ( ! d_state - > domain_sid | | ! d_state - > domain_name | | ! d_state - > domain_dn ) {
2004-08-25 10:44:23 +04:00
talloc_free ( d_state ) ;
2004-05-08 04:02:31 +04:00
return NT_STATUS_NO_MEMORY ;
}
2004-05-10 16:37:06 +04:00
d_state - > access_mask = r - > in . access_mask ;
2004-05-04 11:53:06 +04:00
2005-01-10 15:15:26 +03:00
h_domain = dcesrv_handle_new ( dce_call - > context , SAMR_HANDLE_DOMAIN ) ;
2004-05-04 11:53:06 +04:00
if ( ! h_domain ) {
2004-08-25 10:44:23 +04:00
talloc_free ( d_state ) ;
2004-05-04 11:53:06 +04:00
return NT_STATUS_NO_MEMORY ;
}
2004-09-27 09:13:00 +04:00
2005-01-10 15:15:26 +03:00
h_domain - > data = talloc_steal ( h_domain , d_state ) ;
2004-05-04 11:53:06 +04:00
* r - > out . domain_handle = h_domain - > wire_handle ;
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
2004-12-30 20:01:49 +03:00
/*
return DomInfo1
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_info_DomInfo1 ( struct samr_domain_state * state ,
2004-12-30 20:01:49 +03:00
TALLOC_CTX * mem_ctx ,
2006-07-04 06:46:24 +04:00
struct ldb_message * * dom_msgs ,
2004-12-30 20:01:49 +03:00
struct samr_DomInfo1 * info )
{
info - > min_password_length =
2006-07-04 06:46:24 +04:00
samdb_result_uint ( dom_msgs [ 0 ] , " minPwdLength " , 0 ) ;
2004-12-30 20:01:49 +03:00
info - > password_history_length =
2006-07-04 06:46:24 +04:00
samdb_result_uint ( dom_msgs [ 0 ] , " pwdHistoryLength " , 0 ) ;
2004-12-30 20:01:49 +03:00
info - > password_properties =
2006-07-04 06:46:24 +04:00
samdb_result_uint ( dom_msgs [ 0 ] , " pwdProperties " , 0 ) ;
2004-12-30 20:01:49 +03:00
info - > max_password_age =
2006-07-04 06:46:24 +04:00
samdb_result_int64 ( dom_msgs [ 0 ] , " maxPwdAge " , 0 ) ;
2004-12-30 20:01:49 +03:00
info - > min_password_age =
2006-07-04 06:46:24 +04:00
samdb_result_int64 ( dom_msgs [ 0 ] , " minPwdAge " , 0 ) ;
2004-12-30 20:01:49 +03:00
return NT_STATUS_OK ;
}
2004-05-27 08:13:58 +04:00
/*
return DomInfo2
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_info_DomInfo2 ( struct samr_domain_state * state , TALLOC_CTX * mem_ctx ,
2006-07-04 06:46:24 +04:00
struct ldb_message * * dom_msgs ,
2004-05-27 08:13:58 +04:00
struct samr_DomInfo2 * info )
{
2006-12-13 14:19:51 +03:00
enum server_role role = lp_server_role ( ) ;
/* This pulls the NetBIOS name from the
cn = NTDS Settings , cn = < NETBIOS name of PDC > , . . . .
string */
info - > primary . string = samdb_result_fsmo_name ( state - > sam_ctx , mem_ctx , dom_msgs [ 0 ] , " fSMORoleOwner " ) ;
2006-08-13 12:00:36 +04:00
info - > force_logoff_time = ldb_msg_find_attr_as_uint64 ( dom_msgs [ 0 ] , " forceLogoff " ,
2006-07-04 06:46:24 +04:00
0x8000000000000000LL ) ;
2004-05-27 08:13:58 +04:00
2005-08-03 22:30:21 +04:00
info - > comment . string = samdb_result_string ( dom_msgs [ 0 ] , " comment " , NULL ) ;
2006-07-04 06:46:24 +04:00
info - > domain_name . string = state - > domain_name ;
2004-05-27 08:13:58 +04:00
2006-08-13 12:00:36 +04:00
info - > sequence_num = ldb_msg_find_attr_as_uint64 ( dom_msgs [ 0 ] , " modifiedCount " ,
2006-07-04 06:46:24 +04:00
0 ) ;
2006-12-13 14:19:51 +03:00
switch ( role ) {
case ROLE_DOMAIN_CONTROLLER :
/* This pulls the NetBIOS name from the
cn = NTDS Settings , cn = < NETBIOS name of PDC > , . . . .
string */
if ( samdb_is_pdc ( state - > sam_ctx ) ) {
info - > role = SAMR_ROLE_DOMAIN_PDC ;
} else {
info - > role = SAMR_ROLE_DOMAIN_BDC ;
}
break ;
case ROLE_DOMAIN_MEMBER :
info - > role = SAMR_ROLE_DOMAIN_MEMBER ;
break ;
case ROLE_STANDALONE :
info - > role = SAMR_ROLE_STANDALONE ;
break ;
}
2006-06-15 03:47:45 +04:00
2007-07-26 07:50:24 +04:00
/* No users in BUILTIN, and the LOCAL group types are only in builtin, and the global group type is never in BUILTIN */
2006-07-04 06:46:24 +04:00
info - > num_users = samdb_search_count ( state - > sam_ctx , mem_ctx , state - > domain_dn ,
" (objectClass=user) " ) ;
2006-06-15 03:47:45 +04:00
info - > num_groups = samdb_search_count ( state - > sam_ctx , mem_ctx , state - > domain_dn ,
2004-05-27 08:13:58 +04:00
" (&(objectClass=group)(sAMAccountType=%u)) " ,
ATYPE_GLOBAL_GROUP ) ;
2006-06-15 03:47:45 +04:00
info - > num_aliases = samdb_search_count ( state - > sam_ctx , mem_ctx , state - > domain_dn ,
2004-05-27 08:13:58 +04:00
" (&(objectClass=group)(sAMAccountType=%u)) " ,
ATYPE_LOCAL_GROUP ) ;
return NT_STATUS_OK ;
}
2004-05-03 18:58:08 +04:00
2004-12-30 22:11:25 +03:00
/*
return DomInfo3
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_info_DomInfo3 ( struct samr_domain_state * state ,
2004-12-30 22:11:25 +03:00
TALLOC_CTX * mem_ctx ,
2006-07-04 06:46:24 +04:00
struct ldb_message * * dom_msgs ,
2004-12-30 22:11:25 +03:00
struct samr_DomInfo3 * info )
{
2006-08-13 12:00:36 +04:00
info - > force_logoff_time = ldb_msg_find_attr_as_uint64 ( dom_msgs [ 0 ] , " forceLogoff " ,
2006-06-13 00:00:18 +04:00
0x8000000000000000LL ) ;
2004-12-30 22:11:25 +03:00
return NT_STATUS_OK ;
}
2006-07-04 06:46:24 +04:00
/*
return DomInfo4
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_info_DomInfo4 ( struct samr_domain_state * state ,
2006-07-04 06:46:24 +04:00
TALLOC_CTX * mem_ctx ,
struct ldb_message * * dom_msgs ,
struct samr_DomInfo4 * info )
{
info - > comment . string = samdb_result_string ( dom_msgs [ 0 ] , " comment " , NULL ) ;
return NT_STATUS_OK ;
}
/*
return DomInfo5
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_info_DomInfo5 ( struct samr_domain_state * state ,
2006-07-04 06:46:24 +04:00
TALLOC_CTX * mem_ctx ,
struct ldb_message * * dom_msgs ,
struct samr_DomInfo5 * info )
{
info - > domain_name . string = state - > domain_name ;
return NT_STATUS_OK ;
}
/*
return DomInfo6
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_info_DomInfo6 ( struct samr_domain_state * state ,
2006-07-04 06:46:24 +04:00
TALLOC_CTX * mem_ctx ,
2006-12-13 14:19:51 +03:00
struct ldb_message * * dom_msgs ,
2006-07-04 06:46:24 +04:00
struct samr_DomInfo6 * info )
{
2006-12-13 14:19:51 +03:00
/* This pulls the NetBIOS name from the
cn = NTDS Settings , cn = < NETBIOS name of PDC > , . . . .
string */
info - > primary . string = samdb_result_fsmo_name ( state - > sam_ctx , mem_ctx ,
dom_msgs [ 0 ] , " fSMORoleOwner " ) ;
2006-07-04 06:46:24 +04:00
return NT_STATUS_OK ;
}
/*
return DomInfo7
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_info_DomInfo7 ( struct samr_domain_state * state ,
2006-07-04 06:46:24 +04:00
TALLOC_CTX * mem_ctx ,
struct ldb_message * * dom_msgs ,
struct samr_DomInfo7 * info )
{
2006-12-13 14:19:51 +03:00
enum server_role role = lp_server_role ( ) ;
switch ( role ) {
case ROLE_DOMAIN_CONTROLLER :
/* This pulls the NetBIOS name from the
cn = NTDS Settings , cn = < NETBIOS name of PDC > , . . . .
string */
if ( samdb_is_pdc ( state - > sam_ctx ) ) {
info - > role = SAMR_ROLE_DOMAIN_PDC ;
} else {
info - > role = SAMR_ROLE_DOMAIN_BDC ;
}
break ;
case ROLE_DOMAIN_MEMBER :
info - > role = SAMR_ROLE_DOMAIN_MEMBER ;
break ;
case ROLE_STANDALONE :
info - > role = SAMR_ROLE_STANDALONE ;
break ;
}
2006-07-04 06:46:24 +04:00
return NT_STATUS_OK ;
}
/*
return DomInfo8
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_info_DomInfo8 ( struct samr_domain_state * state ,
2006-07-04 06:46:24 +04:00
TALLOC_CTX * mem_ctx ,
struct ldb_message * * dom_msgs ,
struct samr_DomInfo8 * info )
{
2006-08-13 12:00:36 +04:00
info - > sequence_num = ldb_msg_find_attr_as_uint64 ( dom_msgs [ 0 ] , " modifiedCount " ,
2006-07-04 06:46:24 +04:00
time ( NULL ) ) ;
2006-08-13 12:00:36 +04:00
info - > domain_create_time = ldb_msg_find_attr_as_uint ( dom_msgs [ 0 ] , " creationTime " ,
2006-07-04 06:46:24 +04:00
0x0LL ) ;
return NT_STATUS_OK ;
}
/*
return DomInfo9
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_info_DomInfo9 ( struct samr_domain_state * state ,
2006-07-04 06:46:24 +04:00
TALLOC_CTX * mem_ctx ,
struct ldb_message * * dom_msgs ,
struct samr_DomInfo9 * info )
{
info - > unknown = 1 ;
return NT_STATUS_OK ;
}
/*
return DomInfo11
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_info_DomInfo11 ( struct samr_domain_state * state ,
2006-07-04 06:46:24 +04:00
TALLOC_CTX * mem_ctx ,
struct ldb_message * * dom_msgs ,
struct samr_DomInfo11 * info )
{
NTSTATUS status ;
2007-01-17 17:49:36 +03:00
status = dcesrv_samr_info_DomInfo2 ( state , mem_ctx , dom_msgs , & info - > info2 ) ;
2006-07-04 06:46:24 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2006-08-13 12:00:36 +04:00
info - > lockout_duration = ldb_msg_find_attr_as_int64 ( dom_msgs [ 0 ] , " lockoutDuration " ,
2006-07-04 06:46:24 +04:00
- 18000000000LL ) ;
2006-08-13 12:00:36 +04:00
info - > lockout_window = ldb_msg_find_attr_as_int64 ( dom_msgs [ 0 ] , " lockOutObservationWindow " ,
2006-07-04 06:46:24 +04:00
- 18000000000LL ) ;
2006-08-13 12:00:36 +04:00
info - > lockout_threshold = ldb_msg_find_attr_as_int64 ( dom_msgs [ 0 ] , " lockoutThreshold " , 0 ) ;
2006-07-04 06:46:24 +04:00
return NT_STATUS_OK ;
}
/*
return DomInfo12
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_info_DomInfo12 ( struct samr_domain_state * state ,
2006-07-04 06:46:24 +04:00
TALLOC_CTX * mem_ctx ,
struct ldb_message * * dom_msgs ,
struct samr_DomInfo12 * info )
{
2006-08-13 12:00:36 +04:00
info - > lockout_duration = ldb_msg_find_attr_as_int64 ( dom_msgs [ 0 ] , " lockoutDuration " ,
2006-07-04 06:46:24 +04:00
- 18000000000LL ) ;
2006-08-13 12:00:36 +04:00
info - > lockout_window = ldb_msg_find_attr_as_int64 ( dom_msgs [ 0 ] , " lockOutObservationWindow " ,
2006-07-04 06:46:24 +04:00
- 18000000000LL ) ;
2006-08-13 12:00:36 +04:00
info - > lockout_threshold = ldb_msg_find_attr_as_int64 ( dom_msgs [ 0 ] , " lockoutThreshold " , 0 ) ;
2006-07-04 06:46:24 +04:00
return NT_STATUS_OK ;
}
/*
return DomInfo13
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_info_DomInfo13 ( struct samr_domain_state * state ,
2006-07-04 06:46:24 +04:00
TALLOC_CTX * mem_ctx ,
struct ldb_message * * dom_msgs ,
struct samr_DomInfo13 * info )
{
2006-08-13 12:00:36 +04:00
info - > sequence_num = ldb_msg_find_attr_as_uint64 ( dom_msgs [ 0 ] , " modifiedCount " ,
2006-07-04 06:46:24 +04:00
time ( NULL ) ) ;
2006-08-13 12:00:36 +04:00
info - > domain_create_time = ldb_msg_find_attr_as_uint ( dom_msgs [ 0 ] , " creationTime " ,
2006-07-04 06:46:24 +04:00
0x0LL ) ;
info - > unknown1 = 0 ;
info - > unknown2 = 0 ;
return NT_STATUS_OK ;
}
2004-05-03 18:58:08 +04:00
/*
samr_QueryDomainInfo
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_QueryDomainInfo ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-27 08:13:58 +04:00
struct samr_QueryDomainInfo * r )
2004-05-03 18:58:08 +04:00
{
2004-05-27 08:13:58 +04:00
struct dcesrv_handle * h ;
struct samr_domain_state * d_state ;
2006-07-04 06:46:24 +04:00
struct ldb_message * * dom_msgs ;
const char * const * attrs = NULL ;
2004-05-27 08:13:58 +04:00
r - > out . info = NULL ;
2004-09-21 07:51:38 +04:00
DCESRV_PULL_HANDLE ( h , r - > in . domain_handle , SAMR_HANDLE_DOMAIN ) ;
2004-05-27 08:13:58 +04:00
d_state = h - > data ;
2005-01-27 10:08:20 +03:00
r - > out . info = talloc ( mem_ctx , union samr_DomainInfo ) ;
2004-05-27 08:13:58 +04:00
if ( ! r - > out . info ) {
return NT_STATUS_NO_MEMORY ;
}
2006-07-04 06:46:24 +04:00
switch ( r - > in . level ) {
case 1 :
{
static const char * const attrs2 [ ] = { " minPwdLength " , " pwdHistoryLength " ,
" pwdProperties " , " maxPwdAge " ,
" minPwdAge " , NULL } ;
attrs = attrs2 ;
break ;
}
case 2 :
{
static const char * const attrs2 [ ] = { " forceLogoff " ,
" comment " ,
2006-09-08 09:10:10 +04:00
" modifiedCount " ,
2006-12-13 14:19:51 +03:00
" fSMORoleOwner " ,
2006-09-08 09:10:10 +04:00
NULL } ;
2006-07-04 06:46:24 +04:00
attrs = attrs2 ;
break ;
}
case 3 :
{
2006-09-08 09:10:10 +04:00
static const char * const attrs2 [ ] = { " forceLogoff " ,
NULL } ;
2006-07-04 06:46:24 +04:00
attrs = attrs2 ;
break ;
}
case 4 :
{
2006-09-08 09:10:10 +04:00
static const char * const attrs2 [ ] = { " comment " ,
NULL } ;
2006-07-04 06:46:24 +04:00
attrs = attrs2 ;
break ;
}
case 5 :
2006-12-13 14:19:51 +03:00
{
attrs = NULL ;
break ;
}
2006-07-04 06:46:24 +04:00
case 6 :
2006-12-13 14:19:51 +03:00
{
static const char * const attrs2 [ ] = { " fSMORoleOwner " ,
NULL } ;
attrs = attrs2 ;
break ;
}
2006-07-04 06:46:24 +04:00
case 7 :
{
attrs = NULL ;
break ;
}
case 8 :
{
2006-09-08 09:10:10 +04:00
static const char * const attrs2 [ ] = { " modifiedCount " ,
" creationTime " ,
NULL } ;
2006-07-04 06:46:24 +04:00
attrs = attrs2 ;
break ;
}
case 9 :
attrs = NULL ;
break ;
case 11 :
{
static const char * const attrs2 [ ] = { " comment " , " forceLogoff " ,
" modifiedCount " ,
" lockoutDuration " ,
" lockOutObservationWindow " ,
2006-09-08 09:10:10 +04:00
" lockoutThreshold " ,
NULL } ;
2006-07-04 06:46:24 +04:00
attrs = attrs2 ;
break ;
}
case 12 :
{
static const char * const attrs2 [ ] = { " lockoutDuration " ,
" lockOutObservationWindow " ,
2006-09-08 09:10:10 +04:00
" lockoutThreshold " ,
NULL } ;
2006-07-04 06:46:24 +04:00
attrs = attrs2 ;
break ;
}
case 13 :
{
2006-09-08 09:10:10 +04:00
static const char * const attrs2 [ ] = { " modifiedCount " ,
" creationTime " ,
NULL } ;
2006-07-04 06:46:24 +04:00
attrs = attrs2 ;
break ;
}
}
/* some levels don't need a search */
if ( attrs ) {
int ret ;
ret = gendb_search_dn ( d_state - > sam_ctx , mem_ctx ,
d_state - > domain_dn , & dom_msgs , attrs ) ;
if ( ret ! = 1 ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
}
2004-05-27 08:13:58 +04:00
ZERO_STRUCTP ( r - > out . info ) ;
switch ( r - > in . level ) {
2004-12-30 20:01:49 +03:00
case 1 :
2007-01-17 17:49:36 +03:00
return dcesrv_samr_info_DomInfo1 ( d_state , mem_ctx , dom_msgs ,
2004-12-30 20:01:49 +03:00
& r - > out . info - > info1 ) ;
2004-05-27 08:13:58 +04:00
case 2 :
2007-01-17 17:49:36 +03:00
return dcesrv_samr_info_DomInfo2 ( d_state , mem_ctx , dom_msgs ,
2006-07-04 06:46:24 +04:00
& r - > out . info - > info2 ) ;
2004-12-30 22:11:25 +03:00
case 3 :
2007-01-17 17:49:36 +03:00
return dcesrv_samr_info_DomInfo3 ( d_state , mem_ctx , dom_msgs ,
2004-12-30 22:11:25 +03:00
& r - > out . info - > info3 ) ;
2006-07-04 06:46:24 +04:00
case 4 :
2007-01-17 17:49:36 +03:00
return dcesrv_samr_info_DomInfo4 ( d_state , mem_ctx , dom_msgs ,
2006-07-04 06:46:24 +04:00
& r - > out . info - > info4 ) ;
case 5 :
2007-01-17 17:49:36 +03:00
return dcesrv_samr_info_DomInfo5 ( d_state , mem_ctx , dom_msgs ,
2006-07-04 06:46:24 +04:00
& r - > out . info - > info5 ) ;
case 6 :
2007-01-17 17:49:36 +03:00
return dcesrv_samr_info_DomInfo6 ( d_state , mem_ctx , dom_msgs ,
2006-07-04 06:46:24 +04:00
& r - > out . info - > info6 ) ;
case 7 :
2007-01-17 17:49:36 +03:00
return dcesrv_samr_info_DomInfo7 ( d_state , mem_ctx , dom_msgs ,
2006-07-04 06:46:24 +04:00
& r - > out . info - > info7 ) ;
case 8 :
2007-01-17 17:49:36 +03:00
return dcesrv_samr_info_DomInfo8 ( d_state , mem_ctx , dom_msgs ,
2006-07-04 06:46:24 +04:00
& r - > out . info - > info8 ) ;
case 9 :
2007-01-17 17:49:36 +03:00
return dcesrv_samr_info_DomInfo9 ( d_state , mem_ctx , dom_msgs ,
2006-07-04 06:46:24 +04:00
& r - > out . info - > info9 ) ;
case 11 :
2007-01-17 17:49:36 +03:00
return dcesrv_samr_info_DomInfo11 ( d_state , mem_ctx , dom_msgs ,
2006-07-04 06:46:24 +04:00
& r - > out . info - > info11 ) ;
case 12 :
2007-01-17 17:49:36 +03:00
return dcesrv_samr_info_DomInfo12 ( d_state , mem_ctx , dom_msgs ,
2006-07-04 06:46:24 +04:00
& r - > out . info - > info12 ) ;
case 13 :
2007-01-17 17:49:36 +03:00
return dcesrv_samr_info_DomInfo13 ( d_state , mem_ctx , dom_msgs ,
2006-07-04 06:46:24 +04:00
& r - > out . info - > info13 ) ;
2004-05-27 08:13:58 +04:00
}
return NT_STATUS_INVALID_INFO_CLASS ;
2004-05-03 18:58:08 +04:00
}
/*
samr_SetDomainInfo
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_SetDomainInfo ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_SetDomainInfo * r )
{
2006-07-04 06:46:24 +04:00
struct dcesrv_handle * h ;
struct samr_domain_state * d_state ;
struct ldb_message * msg ;
int ret ;
struct ldb_context * sam_ctx ;
DCESRV_PULL_HANDLE ( h , r - > in . domain_handle , SAMR_HANDLE_DOMAIN ) ;
d_state = h - > data ;
sam_ctx = d_state - > sam_ctx ;
msg = ldb_msg_new ( mem_ctx ) ;
if ( msg = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
msg - > dn = talloc_reference ( mem_ctx , d_state - > domain_dn ) ;
if ( ! msg - > dn ) {
return NT_STATUS_NO_MEMORY ;
}
switch ( r - > in . level ) {
case 1 :
SET_UINT ( msg , info1 . min_password_length , " minPwdLength " ) ;
SET_UINT ( msg , info1 . password_history_length , " pwdHistoryLength " ) ;
SET_UINT ( msg , info1 . password_properties , " pwdProperties " ) ;
SET_INT64 ( msg , info1 . max_password_age , " maxPwdAge " ) ;
SET_INT64 ( msg , info1 . min_password_age , " minPwdAge " ) ;
break ;
case 3 :
SET_UINT64 ( msg , info3 . force_logoff_time , " forceLogoff " ) ;
break ;
case 4 :
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info4 . comment , " comment " ) ;
2006-07-04 06:46:24 +04:00
break ;
case 6 :
case 7 :
case 9 :
/* No op, we don't know where to set these */
return NT_STATUS_OK ;
case 12 :
SET_INT64 ( msg , info12 . lockout_duration , " lockoutDuration " ) ;
SET_INT64 ( msg , info12 . lockout_window , " lockOutObservationWindow " ) ;
SET_INT64 ( msg , info12 . lockout_threshold , " lockoutThreshold " ) ;
break ;
default :
/* many info classes are not valid for SetDomainInfo */
return NT_STATUS_INVALID_INFO_CLASS ;
}
/* modify the samdb record */
2007-07-27 06:07:17 +04:00
ret = ldb_modify ( sam_ctx , msg ) ;
2006-07-04 06:46:24 +04:00
if ( ret ! = 0 ) {
DEBUG ( 1 , ( " Failed to modify record %s: %s \n " ,
2006-11-22 05:05:19 +03:00
ldb_dn_get_linearized ( d_state - > domain_dn ) ,
2006-07-04 06:46:24 +04:00
ldb_errstring ( sam_ctx ) ) ) ;
/* we really need samdb.c to return NTSTATUS */
return NT_STATUS_UNSUCCESSFUL ;
}
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
/*
samr_CreateDomainGroup
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_CreateDomainGroup ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-09 16:32:25 +04:00
struct samr_CreateDomainGroup * r )
2004-05-03 18:58:08 +04:00
{
2004-05-09 15:21:46 +04:00
struct samr_domain_state * d_state ;
2004-05-10 16:37:06 +04:00
struct samr_account_state * a_state ;
2004-05-09 15:21:46 +04:00
struct dcesrv_handle * h ;
const char * name ;
2005-01-02 10:51:13 +03:00
struct ldb_message * msg ;
2005-03-28 03:31:43 +04:00
struct dom_sid * sid ;
2005-06-24 04:18:20 +04:00
const char * groupname ;
2004-05-09 15:21:46 +04:00
struct dcesrv_handle * g_handle ;
int ret ;
ZERO_STRUCTP ( r - > out . group_handle ) ;
* r - > out . rid = 0 ;
2004-09-21 07:51:38 +04:00
DCESRV_PULL_HANDLE ( h , r - > in . domain_handle , SAMR_HANDLE_DOMAIN ) ;
2004-05-09 15:21:46 +04:00
d_state = h - > data ;
2004-11-13 16:45:41 +03:00
groupname = r - > in . name - > string ;
2004-05-09 15:21:46 +04:00
if ( groupname = = NULL ) {
return NT_STATUS_INVALID_PARAMETER ;
}
/* check if the group already exists */
2004-05-26 08:20:17 +04:00
name = samdb_search_string ( d_state - > sam_ctx , mem_ctx , NULL ,
2004-05-09 16:32:25 +04:00
" sAMAccountName " ,
2004-05-09 15:21:46 +04:00
" (&(sAMAccountName=%s)(objectclass=group)) " ,
2005-12-19 10:07:11 +03:00
ldb_binary_encode_string ( mem_ctx , groupname ) ) ;
2004-05-09 15:21:46 +04:00
if ( name ! = NULL ) {
return NT_STATUS_GROUP_EXISTS ;
}
2005-01-02 10:51:13 +03:00
msg = ldb_msg_new ( mem_ctx ) ;
if ( msg = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2004-05-09 15:21:46 +04:00
/* add core elements to the ldb_message for the user */
2006-11-22 03:59:34 +03:00
msg - > dn = ldb_dn_copy ( mem_ctx , d_state - > domain_dn ) ;
ldb_dn_add_child_fmt ( msg - > dn , " CN=%s,CN=Users " , groupname ) ;
2005-01-02 10:51:13 +03:00
if ( ! msg - > dn ) {
2004-05-09 15:21:46 +04:00
return NT_STATUS_NO_MEMORY ;
}
2005-01-02 10:51:13 +03:00
samdb_msg_add_string ( d_state - > sam_ctx , mem_ctx , msg , " sAMAccountName " , groupname ) ;
samdb_msg_add_string ( d_state - > sam_ctx , mem_ctx , msg , " objectClass " , " group " ) ;
2004-05-09 15:21:46 +04:00
/* create the group */
2005-01-02 10:51:13 +03:00
ret = samdb_add ( d_state - > sam_ctx , mem_ctx , msg ) ;
2006-11-25 21:57:47 +03:00
switch ( ret ) {
case LDB_SUCCESS :
break ;
case LDB_ERR_ENTRY_ALREADY_EXISTS :
DEBUG ( 0 , ( " Failed to create group record %s: %s \n " ,
ldb_dn_get_linearized ( msg - > dn ) ,
ldb_errstring ( d_state - > sam_ctx ) ) ) ;
return NT_STATUS_GROUP_EXISTS ;
case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS :
DEBUG ( 0 , ( " Failed to create group record %s: %s \n " ,
ldb_dn_get_linearized ( msg - > dn ) ,
ldb_errstring ( d_state - > sam_ctx ) ) ) ;
return NT_STATUS_ACCESS_DENIED ;
default :
DEBUG ( 0 , ( " Failed to create group record %s: %s \n " ,
ldb_dn_get_linearized ( msg - > dn ) ,
ldb_errstring ( d_state - > sam_ctx ) ) ) ;
2004-05-09 15:21:46 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2005-01-27 10:08:20 +03:00
a_state = talloc ( d_state , struct samr_account_state ) ;
2004-05-10 16:37:06 +04:00
if ( ! a_state ) {
2004-05-09 15:21:46 +04:00
return NT_STATUS_NO_MEMORY ;
}
2004-05-10 16:37:06 +04:00
a_state - > sam_ctx = d_state - > sam_ctx ;
a_state - > access_mask = r - > in . access_mask ;
2004-09-27 09:13:00 +04:00
a_state - > domain_state = talloc_reference ( a_state , d_state ) ;
2005-01-02 10:51:13 +03:00
a_state - > account_dn = talloc_steal ( a_state , msg - > dn ) ;
2005-03-28 03:31:43 +04:00
2005-06-24 04:18:20 +04:00
/* retrieve the sid for the group just created */
sid = samdb_search_dom_sid ( d_state - > sam_ctx , a_state ,
2005-10-11 15:00:16 +04:00
msg - > dn , " objectSid " , NULL ) ;
2005-06-24 04:18:20 +04:00
if ( sid = = NULL ) {
2005-03-28 03:31:43 +04:00
return NT_STATUS_UNSUCCESSFUL ;
}
2004-12-23 00:20:12 +03:00
a_state - > account_name = talloc_strdup ( a_state , groupname ) ;
2004-12-23 01:19:54 +03:00
if ( ! a_state - > account_name ) {
2004-05-09 15:21:46 +04:00
return NT_STATUS_NO_MEMORY ;
}
/* create the policy handle */
2005-01-10 15:15:26 +03:00
g_handle = dcesrv_handle_new ( dce_call - > context , SAMR_HANDLE_GROUP ) ;
2004-05-09 15:21:46 +04:00
if ( ! g_handle ) {
return NT_STATUS_NO_MEMORY ;
}
2005-01-10 15:15:26 +03:00
g_handle - > data = talloc_steal ( g_handle , a_state ) ;
2004-05-09 15:21:46 +04:00
* r - > out . group_handle = g_handle - > wire_handle ;
2005-03-28 03:31:43 +04:00
* r - > out . rid = sid - > sub_auths [ sid - > num_auths - 1 ] ;
2004-05-09 15:21:46 +04:00
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
2004-12-28 10:57:31 +03:00
/*
comparison function for sorting SamEntry array
*/
static int compare_SamEntry ( struct samr_SamEntry * e1 , struct samr_SamEntry * e2 )
{
return e1 - > idx - e2 - > idx ;
}
2004-05-03 18:58:08 +04:00
/*
samr_EnumDomainGroups
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_EnumDomainGroups ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-06 11:32:51 +04:00
struct samr_EnumDomainGroups * r )
2004-05-03 18:58:08 +04:00
{
2004-12-28 10:57:31 +03:00
struct dcesrv_handle * h ;
struct samr_domain_state * d_state ;
struct ldb_message * * res ;
int ldb_cnt , count , i , first ;
struct samr_SamEntry * entries ;
const char * const attrs [ 3 ] = { " objectSid " , " sAMAccountName " , NULL } ;
* r - > out . resume_handle = 0 ;
r - > out . sam = NULL ;
r - > out . num_entries = 0 ;
DCESRV_PULL_HANDLE ( h , r - > in . domain_handle , SAMR_HANDLE_DOMAIN ) ;
d_state = h - > data ;
2004-12-30 20:01:49 +03:00
2004-12-28 10:57:31 +03:00
/* search for all domain groups in this domain. This could possibly be
cached and resumed based on resume_key */
2004-12-30 20:01:49 +03:00
ldb_cnt = samdb_search_domain ( d_state - > sam_ctx , mem_ctx ,
d_state - > domain_dn , & res , attrs ,
2005-06-24 04:18:20 +04:00
d_state - > domain_sid ,
2006-06-13 00:00:18 +04:00
" (&(grouptype=%d)(objectclass=group)) " ,
GTYPE_SECURITY_GLOBAL_GROUP ) ;
2004-12-28 10:57:31 +03:00
if ( ldb_cnt = = - 1 ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
if ( ldb_cnt = = 0 | | r - > in . max_size = = 0 ) {
return NT_STATUS_OK ;
}
/* convert to SamEntry format */
2005-01-27 10:08:20 +03:00
entries = talloc_array ( mem_ctx , struct samr_SamEntry , ldb_cnt ) ;
2004-12-28 10:57:31 +03:00
if ( ! entries ) {
return NT_STATUS_NO_MEMORY ;
}
count = 0 ;
for ( i = 0 ; i < ldb_cnt ; i + + ) {
2004-12-30 20:01:49 +03:00
struct dom_sid * group_sid ;
2004-12-28 10:57:31 +03:00
2004-12-30 20:01:49 +03:00
group_sid = samdb_result_dom_sid ( mem_ctx , res [ i ] ,
2004-12-28 10:57:31 +03:00
" objectSid " ) ;
2004-12-30 20:01:49 +03:00
if ( group_sid = = NULL )
2004-12-28 10:57:31 +03:00
continue ;
entries [ count ] . idx =
2004-12-30 20:01:49 +03:00
group_sid - > sub_auths [ group_sid - > num_auths - 1 ] ;
2004-12-28 10:57:31 +03:00
entries [ count ] . name . string =
samdb_result_string ( res [ i ] , " sAMAccountName " , " " ) ;
count + = 1 ;
}
/* sort the results by rid */
qsort ( entries , count , sizeof ( struct samr_SamEntry ) ,
( comparison_fn_t ) compare_SamEntry ) ;
/* find the first entry to return */
for ( first = 0 ;
first < count & & entries [ first ] . idx < = * r - > in . resume_handle ;
first + + ) ;
if ( first = = count ) {
return NT_STATUS_OK ;
}
/* return the rest, limit by max_size. Note that we
use the w2k3 element size value of 54 */
r - > out . num_entries = count - first ;
r - > out . num_entries = MIN ( r - > out . num_entries ,
1 + ( r - > in . max_size / SAMR_ENUM_USERS_MULTIPLIER ) ) ;
2005-01-27 10:08:20 +03:00
r - > out . sam = talloc ( mem_ctx , struct samr_SamArray ) ;
2004-12-28 10:57:31 +03:00
if ( ! r - > out . sam ) {
return NT_STATUS_NO_MEMORY ;
}
r - > out . sam - > entries = entries + first ;
r - > out . sam - > count = r - > out . num_entries ;
if ( r - > out . num_entries < count - first ) {
* r - > out . resume_handle = entries [ first + r - > out . num_entries - 1 ] . idx ;
return STATUS_MORE_ENTRIES ;
}
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
2004-05-06 11:32:51 +04:00
/*
samr_CreateUser2
2004-05-08 04:02:31 +04:00
2005-12-27 02:47:19 +03:00
This call uses transactions to ensure we don ' t get a new conflicting
user while we are processing this , and to ensure the user either
completly exists , or does not .
2004-05-06 11:32:51 +04:00
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_CreateUser2 ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-06 11:32:51 +04:00
struct samr_CreateUser2 * r )
{
2004-05-06 16:42:42 +04:00
struct samr_domain_state * d_state ;
2004-05-10 16:37:06 +04:00
struct samr_account_state * a_state ;
2004-05-08 04:02:31 +04:00
struct dcesrv_handle * h ;
2004-05-06 16:42:42 +04:00
const char * name ;
2005-01-02 10:51:13 +03:00
struct ldb_message * msg ;
2005-03-28 03:31:43 +04:00
struct dom_sid * sid ;
2005-06-24 04:18:20 +04:00
const char * account_name ;
2004-05-08 04:02:31 +04:00
struct dcesrv_handle * u_handle ;
int ret ;
2005-07-12 14:59:12 +04:00
const char * container , * obj_class = NULL ;
char * cn_name ;
int cn_name_len ;
2004-05-08 04:02:31 +04:00
2005-12-22 12:32:26 +03:00
const char * attrs [ ] = {
" objectSid " ,
" userAccountControl " ,
NULL
} ;
uint32_t user_account_control ;
struct ldb_message * * msgs ;
2004-09-21 07:51:38 +04:00
ZERO_STRUCTP ( r - > out . user_handle ) ;
2004-05-08 04:02:31 +04:00
* r - > out . access_granted = 0 ;
* r - > out . rid = 0 ;
2004-05-06 16:42:42 +04:00
2004-09-21 07:51:38 +04:00
DCESRV_PULL_HANDLE ( h , r - > in . domain_handle , SAMR_HANDLE_DOMAIN ) ;
2004-05-06 11:32:51 +04:00
2004-05-06 16:42:42 +04:00
d_state = h - > data ;
2004-11-13 16:45:41 +03:00
account_name = r - > in . account_name - > string ;
2004-05-08 04:02:31 +04:00
2004-06-05 07:22:10 +04:00
if ( account_name = = NULL ) {
2004-05-06 16:42:42 +04:00
return NT_STATUS_INVALID_PARAMETER ;
}
2005-12-22 12:32:26 +03:00
ret = ldb_transaction_start ( d_state - > sam_ctx ) ;
if ( ret ! = 0 ) {
2005-12-27 10:49:34 +03:00
DEBUG ( 0 , ( " Failed to start a transaction for user creation: %s \n " ,
ldb_errstring ( d_state - > sam_ctx ) ) ) ;
2005-12-22 12:32:26 +03:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2004-05-06 11:32:51 +04:00
/* check if the user already exists */
2006-08-25 11:08:06 +04:00
name = samdb_search_string ( d_state - > sam_ctx , mem_ctx , NULL ,
2004-05-09 16:32:25 +04:00
" sAMAccountName " ,
2005-12-19 10:07:11 +03:00
" (&(sAMAccountName=%s)(objectclass=user)) " ,
ldb_binary_encode_string ( mem_ctx , account_name ) ) ;
2004-05-06 16:42:42 +04:00
if ( name ! = NULL ) {
2005-12-22 12:32:26 +03:00
ldb_transaction_cancel ( d_state - > sam_ctx ) ;
2004-05-06 16:42:42 +04:00
return NT_STATUS_USER_EXISTS ;
}
2005-01-02 10:51:13 +03:00
msg = ldb_msg_new ( mem_ctx ) ;
if ( msg = = NULL ) {
2005-12-22 12:32:26 +03:00
ldb_transaction_cancel ( d_state - > sam_ctx ) ;
2005-01-02 10:51:13 +03:00
return NT_STATUS_NO_MEMORY ;
}
2004-05-08 04:02:31 +04:00
2005-07-12 14:59:12 +04:00
cn_name = talloc_strdup ( mem_ctx , account_name ) ;
2005-12-27 02:47:19 +03:00
if ( ! cn_name ) {
ldb_transaction_cancel ( d_state - > sam_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
2005-07-12 14:59:12 +04:00
cn_name_len = strlen ( cn_name ) ;
2004-05-15 11:51:38 +04:00
/* This must be one of these values *only* */
if ( r - > in . acct_flags = = ACB_NORMAL ) {
2007-07-10 17:26:10 +04:00
container = " CN=Users " ;
2005-07-12 14:59:12 +04:00
obj_class = " user " ;
2004-05-15 11:51:38 +04:00
} else if ( r - > in . acct_flags = = ACB_WSTRUST ) {
2005-07-12 14:59:12 +04:00
if ( cn_name [ cn_name_len - 1 ] ! = ' $ ' ) {
return NT_STATUS_FOOBAR ;
}
cn_name [ cn_name_len - 1 ] = ' \0 ' ;
2007-07-10 17:26:10 +04:00
container = " CN=Computers " ;
2005-07-12 14:59:12 +04:00
obj_class = " computer " ;
2007-07-30 14:30:34 +04:00
samdb_msg_add_int ( d_state - > sam_ctx , mem_ctx , msg , " primaryGroupID " , DOMAIN_RID_DOMAIN_MEMBERS ) ;
2004-05-15 11:51:38 +04:00
} else if ( r - > in . acct_flags = = ACB_SVRTRUST ) {
2005-07-12 14:59:12 +04:00
if ( cn_name [ cn_name_len - 1 ] ! = ' $ ' ) {
return NT_STATUS_FOOBAR ;
}
cn_name [ cn_name_len - 1 ] = ' \0 ' ;
2007-07-10 17:26:10 +04:00
container = " OU=Domain Controllers " ;
2005-07-12 14:59:12 +04:00
obj_class = " computer " ;
2007-07-30 14:30:34 +04:00
samdb_msg_add_int ( d_state - > sam_ctx , mem_ctx , msg , " primaryGroupID " , DOMAIN_RID_DCS ) ;
2004-05-15 11:51:38 +04:00
} else if ( r - > in . acct_flags = = ACB_DOMTRUST ) {
2007-07-10 17:26:10 +04:00
container = " CN=Users " ;
2005-07-12 14:59:12 +04:00
obj_class = " user " ;
2004-05-15 11:51:38 +04:00
} else {
2005-12-22 12:32:26 +03:00
ldb_transaction_cancel ( d_state - > sam_ctx ) ;
2004-05-15 11:51:38 +04:00
return NT_STATUS_INVALID_PARAMETER ;
2004-05-08 04:02:31 +04:00
}
2004-05-15 11:51:38 +04:00
2004-05-08 04:02:31 +04:00
/* add core elements to the ldb_message for the user */
2006-11-22 03:59:34 +03:00
msg - > dn = ldb_dn_copy ( mem_ctx , d_state - > domain_dn ) ;
2007-07-10 17:26:10 +04:00
if ( ! ldb_dn_add_child_fmt ( msg - > dn , " CN=%s,%s " , cn_name , container ) ) {
2005-12-22 12:32:26 +03:00
ldb_transaction_cancel ( d_state - > sam_ctx ) ;
2006-11-22 03:59:34 +03:00
return NT_STATUS_FOOBAR ;
2004-05-08 04:02:31 +04:00
}
2006-11-22 03:59:34 +03:00
2005-01-02 10:51:13 +03:00
samdb_msg_add_string ( d_state - > sam_ctx , mem_ctx , msg , " sAMAccountName " , account_name ) ;
2005-07-12 14:59:12 +04:00
samdb_msg_add_string ( d_state - > sam_ctx , mem_ctx , msg , " objectClass " , obj_class ) ;
2005-12-22 12:32:26 +03:00
/* Start a transaction, so we can query and do a subsequent atomic modify */
2004-05-06 11:32:51 +04:00
/* create the user */
2005-01-02 10:51:13 +03:00
ret = samdb_add ( d_state - > sam_ctx , mem_ctx , msg ) ;
2006-06-15 03:47:45 +04:00
switch ( ret ) {
case LDB_SUCCESS :
break ;
case LDB_ERR_ENTRY_ALREADY_EXISTS :
ldb_transaction_cancel ( d_state - > sam_ctx ) ;
DEBUG ( 0 , ( " Failed to create user record %s: %s \n " ,
2006-11-22 03:59:34 +03:00
ldb_dn_get_linearized ( msg - > dn ) ,
2006-06-15 03:47:45 +04:00
ldb_errstring ( d_state - > sam_ctx ) ) ) ;
return NT_STATUS_USER_EXISTS ;
2006-11-25 21:57:47 +03:00
case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS :
ldb_transaction_cancel ( d_state - > sam_ctx ) ;
DEBUG ( 0 , ( " Failed to create user record %s: %s \n " ,
ldb_dn_get_linearized ( msg - > dn ) ,
ldb_errstring ( d_state - > sam_ctx ) ) ) ;
return NT_STATUS_ACCESS_DENIED ;
2006-06-15 03:47:45 +04:00
default :
2005-12-22 12:32:26 +03:00
ldb_transaction_cancel ( d_state - > sam_ctx ) ;
2005-12-27 10:49:34 +03:00
DEBUG ( 0 , ( " Failed to create user record %s: %s \n " ,
2006-11-22 03:59:34 +03:00
ldb_dn_get_linearized ( msg - > dn ) ,
2005-12-27 10:49:34 +03:00
ldb_errstring ( d_state - > sam_ctx ) ) ) ;
2004-05-08 04:02:31 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2005-01-27 10:08:20 +03:00
a_state = talloc ( d_state , struct samr_account_state ) ;
2004-05-10 16:37:06 +04:00
if ( ! a_state ) {
2005-12-22 12:32:26 +03:00
ldb_transaction_cancel ( d_state - > sam_ctx ) ;
2004-05-08 04:02:31 +04:00
return NT_STATUS_NO_MEMORY ;
}
2004-05-10 16:37:06 +04:00
a_state - > sam_ctx = d_state - > sam_ctx ;
a_state - > access_mask = r - > in . access_mask ;
2004-09-27 09:13:00 +04:00
a_state - > domain_state = talloc_reference ( a_state , d_state ) ;
2005-01-02 10:51:13 +03:00
a_state - > account_dn = talloc_steal ( a_state , msg - > dn ) ;
2005-03-28 03:31:43 +04:00
2005-12-22 12:32:26 +03:00
/* retrieve the sid and account control bits for the user just created */
ret = gendb_search_dn ( d_state - > sam_ctx , a_state ,
msg - > dn , & msgs , attrs ) ;
if ( ret ! = 1 ) {
ldb_transaction_cancel ( d_state - > sam_ctx ) ;
DEBUG ( 0 , ( " Apparently we failed to create an account record, as %s now doesn't exist \n " ,
2006-11-22 05:05:19 +03:00
ldb_dn_get_linearized ( msg - > dn ) ) ) ;
2005-12-22 12:32:26 +03:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
sid = samdb_result_dom_sid ( mem_ctx , msgs [ 0 ] , " objectSid " ) ;
2005-06-24 04:18:20 +04:00
if ( sid = = NULL ) {
2005-12-22 14:26:12 +03:00
ldb_transaction_cancel ( d_state - > sam_ctx ) ;
2006-11-25 21:57:47 +03:00
DEBUG ( 0 , ( " Apparently we failed to get the objectSid of the just created account record %s \n " ,
ldb_dn_get_linearized ( msg - > dn ) ) ) ;
2005-12-22 12:32:26 +03:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2005-12-22 14:26:12 +03:00
/* Change the account control to be the correct account type.
* The default is for a workstation account */
2005-12-22 12:32:26 +03:00
user_account_control = samdb_result_uint ( msgs [ 0 ] , " userAccountControl " , 0 ) ;
2005-12-22 14:26:12 +03:00
user_account_control = ( user_account_control &
~ ( UF_NORMAL_ACCOUNT |
UF_INTERDOMAIN_TRUST_ACCOUNT |
UF_WORKSTATION_TRUST_ACCOUNT |
UF_SERVER_TRUST_ACCOUNT ) ) ;
2005-12-22 12:32:26 +03:00
user_account_control | = samdb_acb2uf ( r - > in . acct_flags ) ;
talloc_free ( msg ) ;
msg = ldb_msg_new ( mem_ctx ) ;
if ( msg = = NULL ) {
ldb_transaction_cancel ( d_state - > sam_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
2005-12-30 11:40:16 +03:00
msg - > dn = ldb_dn_copy ( msg , a_state - > account_dn ) ;
2005-12-22 12:32:26 +03:00
if ( samdb_msg_add_uint ( a_state - > sam_ctx , mem_ctx , msg ,
" userAccountControl " ,
user_account_control ) ! = 0 ) {
ldb_transaction_cancel ( d_state - > sam_ctx ) ;
return NT_STATUS_NO_MEMORY ;
}
/* modify the samdb record */
ret = samdb_replace ( a_state - > sam_ctx , mem_ctx , msg ) ;
if ( ret ! = 0 ) {
2005-12-27 10:49:34 +03:00
DEBUG ( 0 , ( " Failed to modify account record %s to set userAccountControl: %s \n " ,
2006-11-22 05:05:19 +03:00
ldb_dn_get_linearized ( msg - > dn ) ,
2005-12-27 10:49:34 +03:00
ldb_errstring ( d_state - > sam_ctx ) ) ) ;
2005-12-22 12:32:26 +03:00
ldb_transaction_cancel ( d_state - > sam_ctx ) ;
/* we really need samdb.c to return NTSTATUS */
2005-03-28 03:31:43 +04:00
return NT_STATUS_UNSUCCESSFUL ;
}
2005-12-27 10:49:34 +03:00
ret = ldb_transaction_commit ( d_state - > sam_ctx ) ;
2005-12-22 12:32:26 +03:00
if ( ret ! = 0 ) {
2005-12-27 10:49:34 +03:00
DEBUG ( 0 , ( " Failed to commit transaction to add and modify account record %s: %s \n " ,
2006-11-22 05:05:19 +03:00
ldb_dn_get_linearized ( msg - > dn ) ,
2005-12-27 10:49:34 +03:00
ldb_errstring ( d_state - > sam_ctx ) ) ) ;
2005-12-22 12:32:26 +03:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
a_state - > account_name = talloc_steal ( a_state , account_name ) ;
2004-12-23 01:19:54 +03:00
if ( ! a_state - > account_name ) {
2004-05-08 04:02:31 +04:00
return NT_STATUS_NO_MEMORY ;
}
/* create the policy handle */
2005-01-10 15:15:26 +03:00
u_handle = dcesrv_handle_new ( dce_call - > context , SAMR_HANDLE_USER ) ;
2004-05-08 04:02:31 +04:00
if ( ! u_handle ) {
return NT_STATUS_NO_MEMORY ;
}
2005-01-10 15:15:26 +03:00
u_handle - > data = talloc_steal ( u_handle , a_state ) ;
2004-05-08 04:02:31 +04:00
2004-09-21 07:51:38 +04:00
* r - > out . user_handle = u_handle - > wire_handle ;
2004-05-08 04:02:31 +04:00
* r - > out . access_granted = 0xf07ff ; /* TODO: fix access mask calculations */
2005-03-28 03:31:43 +04:00
* r - > out . rid = sid - > sub_auths [ sid - > num_auths - 1 ] ;
2004-05-08 04:02:31 +04:00
return NT_STATUS_OK ;
2004-05-06 11:32:51 +04:00
}
2004-05-03 18:58:08 +04:00
/*
samr_CreateUser
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_CreateUser ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-06 11:32:51 +04:00
struct samr_CreateUser * r )
2004-05-03 18:58:08 +04:00
{
2004-05-06 11:32:51 +04:00
struct samr_CreateUser2 r2 ;
2004-06-24 04:25:38 +04:00
uint32_t access_granted = 0 ;
2004-05-06 11:32:51 +04:00
/* a simple wrapper around samr_CreateUser2 works nicely */
2004-09-21 07:51:38 +04:00
r2 . in . domain_handle = r - > in . domain_handle ;
2004-06-05 07:22:10 +04:00
r2 . in . account_name = r - > in . account_name ;
2004-05-15 11:51:38 +04:00
r2 . in . acct_flags = ACB_NORMAL ;
2004-05-06 11:32:51 +04:00
r2 . in . access_mask = r - > in . access_mask ;
2004-09-21 07:51:38 +04:00
r2 . out . user_handle = r - > out . user_handle ;
2004-05-06 11:32:51 +04:00
r2 . out . access_granted = & access_granted ;
2004-05-08 04:02:31 +04:00
r2 . out . rid = r - > out . rid ;
2004-05-06 11:32:51 +04:00
2007-01-17 17:49:36 +03:00
return dcesrv_samr_CreateUser2 ( dce_call , mem_ctx , & r2 ) ;
2004-05-03 18:58:08 +04:00
}
/*
samr_EnumDomainUsers
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_EnumDomainUsers ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-08 18:42:45 +04:00
struct samr_EnumDomainUsers * r )
2004-05-03 18:58:08 +04:00
{
2004-05-08 18:42:45 +04:00
struct dcesrv_handle * h ;
2004-05-10 16:37:06 +04:00
struct samr_domain_state * d_state ;
2004-05-08 18:42:45 +04:00
struct ldb_message * * res ;
2007-07-26 11:27:46 +04:00
int count , num_filtered_entries , i , first ;
2004-05-08 18:42:45 +04:00
struct samr_SamEntry * entries ;
2007-07-26 11:27:46 +04:00
const char * const attrs [ ] = { " objectSid " , " sAMAccountName " , " userAccountControl " , NULL } ;
2004-05-08 18:42:45 +04:00
* r - > out . resume_handle = 0 ;
r - > out . sam = NULL ;
r - > out . num_entries = 0 ;
2004-09-21 07:51:38 +04:00
DCESRV_PULL_HANDLE ( h , r - > in . domain_handle , SAMR_HANDLE_DOMAIN ) ;
2004-05-08 18:42:45 +04:00
2004-05-10 16:37:06 +04:00
d_state = h - > data ;
2004-05-08 18:42:45 +04:00
/* search for all users in this domain. This could possibly be cached and
resumed based on resume_key */
2005-03-23 04:30:43 +03:00
count = gendb_search ( d_state - > sam_ctx , mem_ctx , d_state - > domain_dn , & res , attrs ,
2004-05-08 18:42:45 +04:00
" objectclass=user " ) ;
if ( count = = - 1 ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2004-05-09 04:42:09 +04:00
if ( count = = 0 | | r - > in . max_size = = 0 ) {
2004-05-08 18:42:45 +04:00
return NT_STATUS_OK ;
}
/* convert to SamEntry format */
2005-01-27 10:08:20 +03:00
entries = talloc_array ( mem_ctx , struct samr_SamEntry , count ) ;
2004-05-08 18:42:45 +04:00
if ( ! entries ) {
return NT_STATUS_NO_MEMORY ;
}
2007-07-26 11:27:46 +04:00
num_filtered_entries = 0 ;
2004-05-08 18:42:45 +04:00
for ( i = 0 ; i < count ; i + + ) {
2007-07-26 11:27:46 +04:00
/* Check if a mask has been requested */
if ( r - > in . acct_flags
& & ( ( samdb_result_acct_flags ( res [ i ] ,
" userAccountControl " ) & r - > in . acct_flags ) = = 0 ) ) {
continue ;
}
entries [ num_filtered_entries ] . idx = samdb_result_rid_from_sid ( mem_ctx , res [ i ] , " objectSid " , 0 ) ;
entries [ num_filtered_entries ] . name . string = samdb_result_string ( res [ i ] , " sAMAccountName " , " " ) ;
num_filtered_entries + + ;
2004-05-08 18:42:45 +04:00
}
/* sort the results by rid */
2007-07-26 11:27:46 +04:00
qsort ( entries , num_filtered_entries , sizeof ( struct samr_SamEntry ) ,
2004-05-08 18:42:45 +04:00
( comparison_fn_t ) compare_SamEntry ) ;
/* find the first entry to return */
for ( first = 0 ;
2007-07-26 11:27:46 +04:00
first < num_filtered_entries & & entries [ first ] . idx < = * r - > in . resume_handle ;
2004-05-08 18:42:45 +04:00
first + + ) ;
/* return the rest, limit by max_size. Note that we
use the w2k3 element size value of 54 */
2007-07-26 11:27:46 +04:00
r - > out . num_entries = num_filtered_entries - first ;
2004-05-09 04:42:09 +04:00
r - > out . num_entries = MIN ( r - > out . num_entries ,
1 + ( r - > in . max_size / SAMR_ENUM_USERS_MULTIPLIER ) ) ;
2004-05-08 18:42:45 +04:00
2005-01-27 10:08:20 +03:00
r - > out . sam = talloc ( mem_ctx , struct samr_SamArray ) ;
2004-05-08 18:42:45 +04:00
if ( ! r - > out . sam ) {
return NT_STATUS_NO_MEMORY ;
}
r - > out . sam - > entries = entries + first ;
r - > out . sam - > count = r - > out . num_entries ;
2007-07-26 11:27:46 +04:00
if ( first = = num_filtered_entries ) {
return NT_STATUS_OK ;
}
if ( r - > out . num_entries < num_filtered_entries - first ) {
2004-05-08 18:42:45 +04:00
* r - > out . resume_handle = entries [ first + r - > out . num_entries - 1 ] . idx ;
return STATUS_MORE_ENTRIES ;
}
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
/*
samr_CreateDomAlias
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_CreateDomAlias ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_CreateDomAlias * r )
{
2004-12-23 01:19:54 +03:00
struct samr_domain_state * d_state ;
struct samr_account_state * a_state ;
struct dcesrv_handle * h ;
2005-06-24 04:18:20 +04:00
const char * alias_name , * name ;
2005-01-02 10:51:13 +03:00
struct ldb_message * msg ;
2005-03-28 03:31:43 +04:00
struct dom_sid * sid ;
2004-12-23 01:19:54 +03:00
struct dcesrv_handle * a_handle ;
int ret ;
ZERO_STRUCTP ( r - > out . alias_handle ) ;
* r - > out . rid = 0 ;
DCESRV_PULL_HANDLE ( h , r - > in . domain_handle , SAMR_HANDLE_DOMAIN ) ;
d_state = h - > data ;
2005-04-13 10:26:43 +04:00
alias_name = r - > in . alias_name - > string ;
2004-12-23 01:19:54 +03:00
2005-04-13 10:26:43 +04:00
if ( alias_name = = NULL ) {
2004-12-23 01:19:54 +03:00
return NT_STATUS_INVALID_PARAMETER ;
}
/* Check if alias already exists */
name = samdb_search_string ( d_state - > sam_ctx , mem_ctx , NULL ,
" sAMAccountName " ,
2005-07-27 04:23:09 +04:00
" (sAMAccountName=%s)(objectclass=group)) " ,
2005-12-19 10:07:11 +03:00
ldb_binary_encode_string ( mem_ctx , alias_name ) ) ;
2004-12-23 01:19:54 +03:00
if ( name ! = NULL ) {
return NT_STATUS_ALIAS_EXISTS ;
}
2005-01-02 10:51:13 +03:00
msg = ldb_msg_new ( mem_ctx ) ;
if ( msg = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2004-12-23 01:19:54 +03:00
2004-12-28 01:20:17 +03:00
/* add core elements to the ldb_message for the alias */
2006-11-22 03:59:34 +03:00
msg - > dn = ldb_dn_copy ( mem_ctx , d_state - > domain_dn ) ;
ldb_dn_add_child_fmt ( msg - > dn , " CN=%s,CN=Users " , alias_name ) ;
2005-01-02 10:51:13 +03:00
if ( ! msg - > dn ) {
2004-12-23 01:19:54 +03:00
return NT_STATUS_NO_MEMORY ;
}
2005-04-13 10:26:43 +04:00
samdb_msg_add_string ( d_state - > sam_ctx , mem_ctx , msg , " sAMAccountName " , alias_name ) ;
2005-01-02 10:51:13 +03:00
samdb_msg_add_string ( d_state - > sam_ctx , mem_ctx , msg , " objectClass " , " group " ) ;
2006-07-04 06:46:24 +04:00
samdb_msg_add_int ( d_state - > sam_ctx , mem_ctx , msg , " groupType " , GTYPE_SECURITY_DOMAIN_LOCAL_GROUP ) ;
2004-12-23 01:19:54 +03:00
/* create the alias */
2005-01-02 10:51:13 +03:00
ret = samdb_add ( d_state - > sam_ctx , mem_ctx , msg ) ;
2006-07-04 06:46:24 +04:00
switch ( ret ) {
case LDB_SUCCESS :
break ;
case LDB_ERR_ENTRY_ALREADY_EXISTS :
return NT_STATUS_ALIAS_EXISTS ;
2006-11-25 21:57:47 +03:00
case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS :
return NT_STATUS_ACCESS_DENIED ;
2006-07-04 06:46:24 +04:00
default :
DEBUG ( 0 , ( " Failed to create alias record %s: %s \n " ,
2006-11-22 05:05:19 +03:00
ldb_dn_get_linearized ( msg - > dn ) ,
2006-07-04 06:46:24 +04:00
ldb_errstring ( d_state - > sam_ctx ) ) ) ;
2004-12-23 01:19:54 +03:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2005-01-27 10:08:20 +03:00
a_state = talloc ( d_state , struct samr_account_state ) ;
2004-12-23 01:19:54 +03:00
if ( ! a_state ) {
return NT_STATUS_NO_MEMORY ;
}
a_state - > sam_ctx = d_state - > sam_ctx ;
a_state - > access_mask = r - > in . access_mask ;
a_state - > domain_state = talloc_reference ( a_state , d_state ) ;
2005-01-02 10:51:13 +03:00
a_state - > account_dn = talloc_steal ( a_state , msg - > dn ) ;
2005-03-28 03:31:43 +04:00
2005-06-24 04:18:20 +04:00
/* retrieve the sid for the alias just created */
sid = samdb_search_dom_sid ( d_state - > sam_ctx , a_state ,
2005-10-11 15:00:16 +04:00
msg - > dn , " objectSid " , NULL ) ;
2005-03-28 03:31:43 +04:00
2005-04-13 10:26:43 +04:00
a_state - > account_name = talloc_strdup ( a_state , alias_name ) ;
2004-12-23 15:02:55 +03:00
if ( ! a_state - > account_name ) {
2004-12-23 01:19:54 +03:00
return NT_STATUS_NO_MEMORY ;
}
/* create the policy handle */
2005-01-10 15:15:26 +03:00
a_handle = dcesrv_handle_new ( dce_call - > context , SAMR_HANDLE_ALIAS ) ;
2004-12-23 01:19:54 +03:00
if ( a_handle = = NULL )
return NT_STATUS_NO_MEMORY ;
2005-01-10 15:15:26 +03:00
a_handle - > data = talloc_steal ( a_handle , a_state ) ;
2004-12-23 01:19:54 +03:00
* r - > out . alias_handle = a_handle - > wire_handle ;
2005-03-28 03:31:43 +04:00
* r - > out . rid = sid - > sub_auths [ sid - > num_auths - 1 ] ;
2004-12-23 01:19:54 +03:00
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
/*
samr_EnumDomainAliases
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_EnumDomainAliases ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_EnumDomainAliases * r )
{
2004-12-28 10:57:31 +03:00
struct dcesrv_handle * h ;
struct samr_domain_state * d_state ;
struct ldb_message * * res ;
int ldb_cnt , count , i , first ;
struct samr_SamEntry * entries ;
const char * const attrs [ 3 ] = { " objectSid " , " sAMAccountName " , NULL } ;
* r - > out . resume_handle = 0 ;
r - > out . sam = NULL ;
r - > out . num_entries = 0 ;
DCESRV_PULL_HANDLE ( h , r - > in . domain_handle , SAMR_HANDLE_DOMAIN ) ;
d_state = h - > data ;
2004-12-30 20:01:49 +03:00
2004-12-28 10:57:31 +03:00
/* search for all domain groups in this domain. This could possibly be
cached and resumed based on resume_key */
2004-12-30 20:01:49 +03:00
ldb_cnt = samdb_search_domain ( d_state - > sam_ctx , mem_ctx ,
d_state - > domain_dn ,
2005-06-24 04:18:20 +04:00
& res , attrs ,
d_state - > domain_sid ,
2006-06-13 00:00:18 +04:00
" (&(|(grouptype=%d)(grouptype=%d))) "
2004-12-30 20:01:49 +03:00
" (objectclass=group)) " ,
2006-06-13 00:00:18 +04:00
GTYPE_SECURITY_BUILTIN_LOCAL_GROUP ,
GTYPE_SECURITY_DOMAIN_LOCAL_GROUP ) ;
2004-12-28 10:57:31 +03:00
if ( ldb_cnt = = - 1 ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
if ( ldb_cnt = = 0 ) {
return NT_STATUS_OK ;
}
/* convert to SamEntry format */
2005-01-27 10:08:20 +03:00
entries = talloc_array ( mem_ctx , struct samr_SamEntry , ldb_cnt ) ;
2004-12-28 10:57:31 +03:00
if ( ! entries ) {
return NT_STATUS_NO_MEMORY ;
}
count = 0 ;
for ( i = 0 ; i < ldb_cnt ; i + + ) {
struct dom_sid * alias_sid ;
alias_sid = samdb_result_dom_sid ( mem_ctx , res [ i ] ,
" objectSid " ) ;
if ( alias_sid = = NULL )
continue ;
entries [ count ] . idx =
alias_sid - > sub_auths [ alias_sid - > num_auths - 1 ] ;
entries [ count ] . name . string =
samdb_result_string ( res [ i ] , " sAMAccountName " , " " ) ;
count + = 1 ;
}
/* sort the results by rid */
qsort ( entries , count , sizeof ( struct samr_SamEntry ) ,
( comparison_fn_t ) compare_SamEntry ) ;
/* find the first entry to return */
for ( first = 0 ;
first < count & & entries [ first ] . idx < = * r - > in . resume_handle ;
first + + ) ;
if ( first = = count ) {
return NT_STATUS_OK ;
}
r - > out . num_entries = count - first ;
r - > out . num_entries = MIN ( r - > out . num_entries , 1000 ) ;
2005-01-27 10:08:20 +03:00
r - > out . sam = talloc ( mem_ctx , struct samr_SamArray ) ;
2004-12-28 10:57:31 +03:00
if ( ! r - > out . sam ) {
return NT_STATUS_NO_MEMORY ;
}
r - > out . sam - > entries = entries + first ;
r - > out . sam - > count = r - > out . num_entries ;
if ( r - > out . num_entries < count - first ) {
* r - > out . resume_handle =
entries [ first + r - > out . num_entries - 1 ] . idx ;
return STATUS_MORE_ENTRIES ;
}
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
/*
samr_GetAliasMembership
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_GetAliasMembership ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_GetAliasMembership * r )
{
2004-12-30 01:57:20 +03:00
struct dcesrv_handle * h ;
struct samr_domain_state * d_state ;
struct ldb_message * * res ;
int i , count = 0 ;
DCESRV_PULL_HANDLE ( h , r - > in . domain_handle , SAMR_HANDLE_DOMAIN ) ;
d_state = h - > data ;
if ( r - > in . sids - > num_sids > 0 ) {
const char * filter ;
const char * const attrs [ 2 ] = { " objectSid " , NULL } ;
filter = talloc_asprintf ( mem_ctx ,
2006-06-13 00:00:18 +04:00
" (&(|(grouptype=%d)(grouptype=%d)) "
2004-12-30 01:57:20 +03:00
" (objectclass=group)(| " ,
2006-06-13 00:00:18 +04:00
GTYPE_SECURITY_BUILTIN_LOCAL_GROUP ,
GTYPE_SECURITY_DOMAIN_LOCAL_GROUP ) ;
2004-12-30 01:57:20 +03:00
if ( filter = = NULL )
return NT_STATUS_NO_MEMORY ;
for ( i = 0 ; i < r - > in . sids - > num_sids ; i + + ) {
2005-06-24 04:18:20 +04:00
const char * memberdn ;
2004-12-30 01:57:20 +03:00
2005-06-24 04:18:20 +04:00
memberdn =
samdb_search_string ( d_state - > sam_ctx ,
2006-08-25 11:08:06 +04:00
mem_ctx , NULL , " distinguishedName " ,
2005-06-24 04:18:20 +04:00
" (objectSid=%s) " ,
ldap_encode_ndr_dom_sid ( mem_ctx ,
r - > in . sids - > sids [ i ] . sid ) ) ;
2004-12-30 01:57:20 +03:00
if ( memberdn = = NULL )
continue ;
filter = talloc_asprintf ( mem_ctx , " %s(member=%s) " ,
filter , memberdn ) ;
if ( filter = = NULL )
return NT_STATUS_NO_MEMORY ;
}
2004-12-30 20:01:49 +03:00
count = samdb_search_domain ( d_state - > sam_ctx , mem_ctx ,
d_state - > domain_dn , & res , attrs ,
2005-06-24 04:18:20 +04:00
d_state - > domain_sid , " %s)) " , filter ) ;
2004-12-30 01:57:20 +03:00
if ( count < 0 )
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
r - > out . rids - > count = 0 ;
2005-01-27 10:08:20 +03:00
r - > out . rids - > ids = talloc_array ( mem_ctx , uint32_t , count ) ;
2004-12-30 01:57:20 +03:00
if ( r - > out . rids - > ids = = NULL )
return NT_STATUS_NO_MEMORY ;
for ( i = 0 ; i < count ; i + + ) {
struct dom_sid * alias_sid ;
alias_sid = samdb_result_dom_sid ( mem_ctx , res [ i ] , " objectSid " ) ;
if ( alias_sid = = NULL ) {
DEBUG ( 0 , ( " Could not find objectSid \n " ) ) ;
continue ;
}
r - > out . rids - > ids [ r - > out . rids - > count ] =
alias_sid - > sub_auths [ alias_sid - > num_auths - 1 ] ;
r - > out . rids - > count + = 1 ;
}
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
/*
samr_LookupNames
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_LookupNames ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-08 04:02:31 +04:00
struct samr_LookupNames * r )
2004-05-03 18:58:08 +04:00
{
2004-05-08 04:02:31 +04:00
struct dcesrv_handle * h ;
2004-05-10 16:37:06 +04:00
struct samr_domain_state * d_state ;
2007-06-06 16:51:45 +04:00
int i , num_mapped ;
2004-05-08 04:02:31 +04:00
NTSTATUS status = NT_STATUS_OK ;
const char * const attrs [ ] = { " sAMAccountType " , " objectSid " , NULL } ;
int count ;
ZERO_STRUCT ( r - > out . rids ) ;
ZERO_STRUCT ( r - > out . types ) ;
2004-09-21 07:51:38 +04:00
DCESRV_PULL_HANDLE ( h , r - > in . domain_handle , SAMR_HANDLE_DOMAIN ) ;
2004-05-08 04:02:31 +04:00
2004-05-10 16:37:06 +04:00
d_state = h - > data ;
2004-05-08 04:02:31 +04:00
if ( r - > in . num_names = = 0 ) {
return NT_STATUS_OK ;
}
2005-01-27 10:08:20 +03:00
r - > out . rids . ids = talloc_array ( mem_ctx , uint32_t , r - > in . num_names ) ;
r - > out . types . ids = talloc_array ( mem_ctx , uint32_t , r - > in . num_names ) ;
2004-05-08 04:02:31 +04:00
if ( ! r - > out . rids . ids | | ! r - > out . types . ids ) {
return NT_STATUS_NO_MEMORY ;
}
r - > out . rids . count = r - > in . num_names ;
r - > out . types . count = r - > in . num_names ;
2007-06-06 16:51:45 +04:00
num_mapped = 0 ;
2004-05-08 04:02:31 +04:00
for ( i = 0 ; i < r - > in . num_names ; i + + ) {
struct ldb_message * * res ;
2005-06-24 04:18:20 +04:00
struct dom_sid * sid ;
2004-05-25 20:24:13 +04:00
uint32_t atype , rtype ;
2004-05-08 04:02:31 +04:00
r - > out . rids . ids [ i ] = 0 ;
r - > out . types . ids [ i ] = SID_NAME_UNKNOWN ;
2005-03-23 04:30:43 +03:00
count = gendb_search ( d_state - > sam_ctx , mem_ctx , d_state - > domain_dn , & res , attrs ,
2005-12-19 10:07:11 +03:00
" sAMAccountName=%s " ,
ldb_binary_encode_string ( mem_ctx , r - > in . names [ i ] . string ) ) ;
2004-05-08 04:02:31 +04:00
if ( count ! = 1 ) {
status = STATUS_SOME_UNMAPPED ;
continue ;
}
2005-06-24 04:18:20 +04:00
sid = samdb_result_dom_sid ( mem_ctx , res [ 0 ] , " objectSid " ) ;
2004-05-08 04:02:31 +04:00
if ( sid = = NULL ) {
status = STATUS_SOME_UNMAPPED ;
continue ;
}
2005-06-24 04:18:20 +04:00
2004-05-08 04:02:31 +04:00
atype = samdb_result_uint ( res [ 0 ] , " sAMAccountType " , 0 ) ;
if ( atype = = 0 ) {
status = STATUS_SOME_UNMAPPED ;
continue ;
}
2004-05-15 11:51:38 +04:00
rtype = samdb_atype_map ( atype ) ;
if ( rtype = = SID_NAME_UNKNOWN ) {
2004-05-08 04:02:31 +04:00
status = STATUS_SOME_UNMAPPED ;
continue ;
}
r - > out . rids . ids [ i ] = sid - > sub_auths [ sid - > num_auths - 1 ] ;
r - > out . types . ids [ i ] = rtype ;
2007-06-06 16:51:45 +04:00
num_mapped + + ;
2004-05-08 04:02:31 +04:00
}
2007-06-06 16:51:45 +04:00
if ( num_mapped = = 0 ) {
return NT_STATUS_NONE_MAPPED ;
}
2004-05-08 04:02:31 +04:00
return status ;
2004-05-03 18:58:08 +04:00
}
/*
samr_LookupRids
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_LookupRids ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_LookupRids * r )
{
2004-12-27 02:31:19 +03:00
struct dcesrv_handle * h ;
struct samr_domain_state * d_state ;
2005-03-28 03:31:43 +04:00
int i , total ;
2004-12-27 02:31:19 +03:00
NTSTATUS status = NT_STATUS_OK ;
2005-07-08 12:09:02 +04:00
struct lsa_String * names ;
2004-12-27 12:48:49 +03:00
uint32_t * ids ;
2004-12-27 02:31:19 +03:00
ZERO_STRUCT ( r - > out . names ) ;
ZERO_STRUCT ( r - > out . types ) ;
DCESRV_PULL_HANDLE ( h , r - > in . domain_handle , SAMR_HANDLE_DOMAIN ) ;
d_state = h - > data ;
if ( r - > in . num_rids = = 0 )
return NT_STATUS_OK ;
2005-07-08 12:09:02 +04:00
names = talloc_array ( mem_ctx , struct lsa_String , r - > in . num_rids ) ;
2005-01-27 10:08:20 +03:00
ids = talloc_array ( mem_ctx , uint32_t , r - > in . num_rids ) ;
2004-12-27 02:31:19 +03:00
2004-12-27 12:48:49 +03:00
if ( ( names = = NULL ) | | ( ids = = NULL ) )
2004-12-27 02:31:19 +03:00
return NT_STATUS_NO_MEMORY ;
2005-03-28 03:31:43 +04:00
total = 0 ;
2004-12-27 02:31:19 +03:00
for ( i = 0 ; i < r - > in . num_rids ; i + + ) {
struct ldb_message * * res ;
int count ;
const char * const attrs [ ] = { " sAMAccountType " ,
" sAMAccountName " , NULL } ;
uint32_t atype ;
2005-06-24 04:18:20 +04:00
struct dom_sid * sid ;
2004-12-27 02:31:19 +03:00
2004-12-27 12:48:49 +03:00
ids [ i ] = SID_NAME_UNKNOWN ;
2004-12-27 02:31:19 +03:00
2005-06-24 04:18:20 +04:00
sid = dom_sid_add_rid ( mem_ctx , d_state - > domain_sid , r - > in . rids [ i ] ) ;
if ( sid = = NULL ) {
names [ i ] . string = NULL ;
status = STATUS_SOME_UNMAPPED ;
continue ;
}
2005-03-23 04:30:43 +03:00
count = gendb_search ( d_state - > sam_ctx , mem_ctx ,
2004-12-27 02:31:19 +03:00
d_state - > domain_dn , & res , attrs ,
2005-06-24 04:18:20 +04:00
" (objectSid=%s) " ,
ldap_encode_ndr_dom_sid ( mem_ctx , sid ) ) ;
2004-12-27 02:31:19 +03:00
if ( count ! = 1 ) {
2005-03-28 03:31:43 +04:00
names [ i ] . string = NULL ;
2004-12-27 02:31:19 +03:00
status = STATUS_SOME_UNMAPPED ;
continue ;
}
2004-12-27 12:48:49 +03:00
names [ i ] . string = samdb_result_string ( res [ 0 ] , " sAMAccountName " ,
NULL ) ;
2005-03-28 03:31:43 +04:00
2004-12-27 02:31:19 +03:00
atype = samdb_result_uint ( res [ 0 ] , " sAMAccountType " , 0 ) ;
if ( atype = = 0 ) {
status = STATUS_SOME_UNMAPPED ;
continue ;
}
2004-12-27 12:48:49 +03:00
ids [ i ] = samdb_atype_map ( atype ) ;
2004-12-27 02:31:19 +03:00
2004-12-27 12:48:49 +03:00
if ( ids [ i ] = = SID_NAME_UNKNOWN ) {
2004-12-27 02:31:19 +03:00
status = STATUS_SOME_UNMAPPED ;
continue ;
}
}
2004-12-27 12:48:49 +03:00
r - > out . names . names = names ;
r - > out . names . count = r - > in . num_rids ;
r - > out . types . ids = ids ;
r - > out . types . count = r - > in . num_rids ;
2004-12-27 02:31:19 +03:00
return status ;
2004-05-03 18:58:08 +04:00
}
/*
samr_OpenGroup
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_OpenGroup ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_OpenGroup * r )
{
2004-05-09 19:39:12 +04:00
struct samr_domain_state * d_state ;
2004-05-10 16:37:06 +04:00
struct samr_account_state * a_state ;
2004-05-09 19:39:12 +04:00
struct dcesrv_handle * h ;
2005-06-24 04:18:20 +04:00
const char * groupname ;
struct dom_sid * sid ;
2004-05-09 19:39:12 +04:00
struct ldb_message * * msgs ;
struct dcesrv_handle * g_handle ;
const char * const attrs [ 2 ] = { " sAMAccountName " , NULL } ;
int ret ;
2004-09-21 07:51:38 +04:00
ZERO_STRUCTP ( r - > out . group_handle ) ;
2004-05-09 19:39:12 +04:00
2004-09-21 07:51:38 +04:00
DCESRV_PULL_HANDLE ( h , r - > in . domain_handle , SAMR_HANDLE_DOMAIN ) ;
2004-05-09 19:39:12 +04:00
d_state = h - > data ;
/* form the group SID */
2005-06-24 04:18:20 +04:00
sid = dom_sid_add_rid ( mem_ctx , d_state - > domain_sid , r - > in . rid ) ;
if ( ! sid ) {
2004-05-09 19:39:12 +04:00
return NT_STATUS_NO_MEMORY ;
}
/* search for the group record */
2005-03-23 04:30:43 +03:00
ret = gendb_search ( d_state - > sam_ctx ,
2004-05-10 16:37:06 +04:00
mem_ctx , d_state - > domain_dn , & msgs , attrs ,
2004-12-26 21:02:18 +03:00
" (&(objectSid=%s)(objectclass=group) "
2006-06-13 00:00:18 +04:00
" (grouptype=%d)) " ,
2005-06-24 04:18:20 +04:00
ldap_encode_ndr_dom_sid ( mem_ctx , sid ) ,
2006-06-13 00:00:18 +04:00
GTYPE_SECURITY_GLOBAL_GROUP ) ;
2004-05-09 19:39:12 +04:00
if ( ret = = 0 ) {
return NT_STATUS_NO_SUCH_GROUP ;
}
if ( ret ! = 1 ) {
2005-06-24 04:18:20 +04:00
DEBUG ( 0 , ( " Found %d records matching sid %s \n " ,
ret , dom_sid_string ( mem_ctx , sid ) ) ) ;
2004-05-09 19:39:12 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
groupname = samdb_result_string ( msgs [ 0 ] , " sAMAccountName " , NULL ) ;
if ( groupname = = NULL ) {
2005-06-24 04:18:20 +04:00
DEBUG ( 0 , ( " sAMAccountName field missing for sid %s \n " ,
dom_sid_string ( mem_ctx , sid ) ) ) ;
2004-05-09 19:39:12 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2005-01-27 10:08:20 +03:00
a_state = talloc ( d_state , struct samr_account_state ) ;
2004-05-10 16:37:06 +04:00
if ( ! a_state ) {
2004-05-09 19:39:12 +04:00
return NT_STATUS_NO_MEMORY ;
}
2004-05-10 16:37:06 +04:00
a_state - > sam_ctx = d_state - > sam_ctx ;
a_state - > access_mask = r - > in . access_mask ;
2004-09-27 09:13:00 +04:00
a_state - > domain_state = talloc_reference ( a_state , d_state ) ;
2004-08-25 10:44:23 +04:00
a_state - > account_dn = talloc_steal ( a_state , msgs [ 0 ] - > dn ) ;
2005-06-24 04:18:20 +04:00
a_state - > account_sid = talloc_steal ( a_state , sid ) ;
2004-08-25 10:44:23 +04:00
a_state - > account_name = talloc_strdup ( a_state , groupname ) ;
2004-12-23 15:02:55 +03:00
if ( ! a_state - > account_name ) {
2004-05-09 19:39:12 +04:00
return NT_STATUS_NO_MEMORY ;
}
/* create the policy handle */
2005-01-10 15:15:26 +03:00
g_handle = dcesrv_handle_new ( dce_call - > context , SAMR_HANDLE_GROUP ) ;
2004-05-09 19:39:12 +04:00
if ( ! g_handle ) {
return NT_STATUS_NO_MEMORY ;
}
2005-01-10 15:15:26 +03:00
g_handle - > data = talloc_steal ( g_handle , a_state ) ;
2004-05-09 19:39:12 +04:00
2004-09-21 07:51:38 +04:00
* r - > out . group_handle = g_handle - > wire_handle ;
2004-05-09 19:39:12 +04:00
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
/*
samr_QueryGroupInfo
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_QueryGroupInfo ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_QueryGroupInfo * r )
{
2004-05-09 19:39:12 +04:00
struct dcesrv_handle * h ;
2004-05-10 16:37:06 +04:00
struct samr_account_state * a_state ;
2004-05-09 19:39:12 +04:00
struct ldb_message * msg , * * res ;
const char * const attrs [ 4 ] = { " sAMAccountName " , " description " ,
" numMembers " , NULL } ;
int ret ;
r - > out . info = NULL ;
2004-09-21 07:51:38 +04:00
DCESRV_PULL_HANDLE ( h , r - > in . group_handle , SAMR_HANDLE_GROUP ) ;
2004-05-09 19:39:12 +04:00
2004-05-10 16:37:06 +04:00
a_state = h - > data ;
2004-05-09 19:39:12 +04:00
/* pull all the group attributes */
2005-06-14 23:15:17 +04:00
ret = gendb_search_dn ( a_state - > sam_ctx , mem_ctx ,
a_state - > account_dn , & res , attrs ) ;
2004-05-09 19:39:12 +04:00
if ( ret ! = 1 ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
msg = res [ 0 ] ;
/* allocate the info structure */
2005-01-27 10:08:20 +03:00
r - > out . info = talloc ( mem_ctx , union samr_GroupInfo ) ;
2004-05-09 19:39:12 +04:00
if ( r - > out . info = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
ZERO_STRUCTP ( r - > out . info ) ;
/* Fill in the level */
switch ( r - > in . level ) {
2005-01-29 05:46:37 +03:00
case GROUPINFOALL :
2007-07-27 06:07:17 +04:00
QUERY_STRING ( msg , all . name , " sAMAccountName " ) ;
2006-07-03 08:00:10 +04:00
r - > out . info - > all . attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED ; /* Do like w2k3 */
2004-05-09 19:39:12 +04:00
QUERY_UINT ( msg , all . num_members , " numMembers " )
2007-07-27 06:07:17 +04:00
QUERY_STRING ( msg , all . description , " description " ) ;
2004-05-09 19:39:12 +04:00
break ;
2005-01-29 05:46:37 +03:00
case GROUPINFONAME :
2007-07-27 06:07:17 +04:00
QUERY_STRING ( msg , name , " sAMAccountName " ) ;
2004-05-09 19:39:12 +04:00
break ;
2006-07-03 08:00:10 +04:00
case GROUPINFOATTRIBUTES :
r - > out . info - > attributes . attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED ; /* Do like w2k3 */
2004-05-09 19:39:12 +04:00
break ;
2005-01-29 05:46:37 +03:00
case GROUPINFODESCRIPTION :
2007-07-27 06:07:17 +04:00
QUERY_STRING ( msg , description , " description " ) ;
2004-05-09 19:39:12 +04:00
break ;
2006-07-03 08:00:10 +04:00
case GROUPINFOALL2 :
2007-07-27 06:07:17 +04:00
QUERY_STRING ( msg , all2 . name , " sAMAccountName " ) ;
2006-07-03 08:00:10 +04:00
r - > out . info - > all . attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED ; /* Do like w2k3 */
QUERY_UINT ( msg , all2 . num_members , " numMembers " )
2007-07-27 06:07:17 +04:00
QUERY_STRING ( msg , all2 . description , " description " ) ;
2006-07-03 08:00:10 +04:00
break ;
2004-05-09 19:39:12 +04:00
default :
r - > out . info = NULL ;
return NT_STATUS_INVALID_INFO_CLASS ;
}
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
/*
samr_SetGroupInfo
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_SetGroupInfo ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2005-01-02 10:51:13 +03:00
struct samr_SetGroupInfo * r )
2004-05-03 18:58:08 +04:00
{
2004-05-09 19:39:12 +04:00
struct dcesrv_handle * h ;
2006-07-04 06:46:24 +04:00
struct samr_account_state * g_state ;
2005-01-02 10:51:13 +03:00
struct ldb_message * msg ;
2006-07-04 06:46:24 +04:00
struct ldb_context * sam_ctx ;
2004-05-22 04:53:57 +04:00
int ret ;
2004-05-09 19:39:12 +04:00
2004-09-21 07:51:38 +04:00
DCESRV_PULL_HANDLE ( h , r - > in . group_handle , SAMR_HANDLE_GROUP ) ;
2004-05-09 19:39:12 +04:00
2006-07-04 06:46:24 +04:00
g_state = h - > data ;
sam_ctx = g_state - > sam_ctx ;
2004-05-09 19:39:12 +04:00
2005-01-02 10:51:13 +03:00
msg = ldb_msg_new ( mem_ctx ) ;
if ( msg = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2006-07-04 06:46:24 +04:00
msg - > dn = ldb_dn_copy ( mem_ctx , g_state - > account_dn ) ;
2005-01-02 10:51:13 +03:00
if ( ! msg - > dn ) {
2004-05-09 19:39:12 +04:00
return NT_STATUS_NO_MEMORY ;
}
switch ( r - > in . level ) {
2005-01-29 05:46:37 +03:00
case GROUPINFODESCRIPTION :
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , description , " description " ) ;
2004-05-09 19:39:12 +04:00
break ;
2005-01-29 05:46:37 +03:00
case GROUPINFONAME :
2004-05-09 19:39:12 +04:00
/* On W2k3 this does not change the name, it changes the
* sAMAccountName attribute */
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , name , " sAMAccountName " ) ;
2004-05-09 19:39:12 +04:00
break ;
2006-07-03 08:00:10 +04:00
case GROUPINFOATTRIBUTES :
2004-05-09 19:39:12 +04:00
/* This does not do anything obviously visible in W2k3 LDAP */
2006-09-21 09:44:39 +04:00
return NT_STATUS_OK ;
2004-05-09 19:39:12 +04:00
default :
return NT_STATUS_INVALID_INFO_CLASS ;
}
/* modify the samdb record */
2007-07-27 06:07:17 +04:00
ret = ldb_modify ( g_state - > sam_ctx , msg ) ;
2004-05-09 19:39:12 +04:00
if ( ret ! = 0 ) {
/* we really need samdb.c to return NTSTATUS */
return NT_STATUS_UNSUCCESSFUL ;
}
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
/*
samr_AddGroupMember
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_AddGroupMember ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_AddGroupMember * r )
{
2004-12-26 21:02:18 +03:00
struct dcesrv_handle * h ;
struct samr_account_state * a_state ;
struct samr_domain_state * d_state ;
2005-01-02 10:51:13 +03:00
struct ldb_message * mod ;
2005-06-24 04:18:20 +04:00
struct dom_sid * membersid ;
2004-12-26 21:02:18 +03:00
const char * memberdn ;
2006-07-04 06:46:24 +04:00
struct ldb_result * res ;
const char * const attrs [ ] = { NULL } ;
2004-12-26 21:02:18 +03:00
int ret ;
DCESRV_PULL_HANDLE ( h , r - > in . group_handle , SAMR_HANDLE_GROUP ) ;
a_state = h - > data ;
d_state = a_state - > domain_state ;
2005-06-24 04:18:20 +04:00
membersid = dom_sid_add_rid ( mem_ctx , d_state - > domain_sid , r - > in . rid ) ;
if ( membersid = = NULL )
2004-12-26 21:02:18 +03:00
return NT_STATUS_NO_MEMORY ;
/* In native mode, AD can also nest domain groups. Not sure yet
* whether this is also available via RPC . */
2006-12-05 07:25:27 +03:00
ret = ldb_search_exp_fmt ( d_state - > sam_ctx , mem_ctx , & res ,
d_state - > domain_dn , LDB_SCOPE_SUBTREE , attrs ,
" (&(objectSid=%s)(objectclass=user)) " ,
ldap_encode_ndr_dom_sid ( mem_ctx , membersid ) ) ;
2004-12-26 21:02:18 +03:00
2006-07-04 06:46:24 +04:00
if ( ret ! = 0 ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2004-12-26 21:02:18 +03:00
2006-07-04 06:46:24 +04:00
if ( res - > count = = 0 ) {
return NT_STATUS_NO_SUCH_USER ;
}
if ( res - > count > 1 ) {
2004-12-26 21:02:18 +03:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
2006-07-04 06:46:24 +04:00
}
2004-12-26 21:02:18 +03:00
2006-11-22 05:05:19 +03:00
memberdn = ldb_dn_alloc_linearized ( mem_ctx , res - > msgs [ 0 ] - > dn ) ;
2004-12-26 21:02:18 +03:00
if ( memberdn = = NULL )
2006-07-04 06:46:24 +04:00
return NT_STATUS_NO_MEMORY ;
2004-12-26 21:02:18 +03:00
2005-01-02 10:51:13 +03:00
mod = ldb_msg_new ( mem_ctx ) ;
if ( mod = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2004-12-26 21:02:18 +03:00
2005-01-02 10:51:13 +03:00
mod - > dn = talloc_reference ( mem_ctx , a_state - > account_dn ) ;
if ( samdb_msg_add_addval ( d_state - > sam_ctx , mem_ctx , mod , " member " ,
2004-12-26 21:02:18 +03:00
memberdn ) ! = 0 )
return NT_STATUS_UNSUCCESSFUL ;
2007-07-27 06:07:17 +04:00
ret = ldb_modify ( a_state - > sam_ctx , mod ) ;
2006-07-04 06:46:24 +04:00
switch ( ret ) {
case LDB_SUCCESS :
return NT_STATUS_OK ;
case LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS :
return NT_STATUS_MEMBER_IN_GROUP ;
2006-11-25 21:57:47 +03:00
case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS :
return NT_STATUS_ACCESS_DENIED ;
2006-07-04 06:46:24 +04:00
default :
2004-12-26 21:02:18 +03:00
return NT_STATUS_UNSUCCESSFUL ;
2006-07-04 06:46:24 +04:00
}
2004-12-26 21:02:18 +03:00
2004-05-03 18:58:08 +04:00
}
/*
samr_DeleteDomainGroup
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_DeleteDomainGroup ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_DeleteDomainGroup * r )
{
2004-05-09 19:39:12 +04:00
struct dcesrv_handle * h ;
2004-05-10 16:37:06 +04:00
struct samr_account_state * a_state ;
2004-05-09 19:39:12 +04:00
int ret ;
2004-09-21 07:51:38 +04:00
* r - > out . group_handle = * r - > in . group_handle ;
2004-05-09 19:39:12 +04:00
2004-09-21 07:51:38 +04:00
DCESRV_PULL_HANDLE ( h , r - > in . group_handle , SAMR_HANDLE_GROUP ) ;
2004-05-09 19:39:12 +04:00
2004-05-10 16:37:06 +04:00
a_state = h - > data ;
2004-05-09 19:39:12 +04:00
2004-05-10 16:37:06 +04:00
ret = samdb_delete ( a_state - > sam_ctx , mem_ctx , a_state - > account_dn ) ;
2004-05-09 19:39:12 +04:00
if ( ret ! = 0 ) {
return NT_STATUS_UNSUCCESSFUL ;
}
2004-09-21 07:51:38 +04:00
ZERO_STRUCTP ( r - > out . group_handle ) ;
2004-05-09 19:39:12 +04:00
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
/*
samr_DeleteGroupMember
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_DeleteGroupMember ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_DeleteGroupMember * r )
{
2004-12-26 21:02:18 +03:00
struct dcesrv_handle * h ;
struct samr_account_state * a_state ;
struct samr_domain_state * d_state ;
2005-01-02 10:51:13 +03:00
struct ldb_message * mod ;
2005-06-24 04:18:20 +04:00
struct dom_sid * membersid ;
2004-12-26 21:02:18 +03:00
const char * memberdn ;
2006-07-04 06:46:24 +04:00
struct ldb_result * res ;
const char * const attrs [ ] = { NULL } ;
2004-12-26 21:02:18 +03:00
int ret ;
DCESRV_PULL_HANDLE ( h , r - > in . group_handle , SAMR_HANDLE_GROUP ) ;
a_state = h - > data ;
d_state = a_state - > domain_state ;
2005-06-24 04:18:20 +04:00
membersid = dom_sid_add_rid ( mem_ctx , d_state - > domain_sid , r - > in . rid ) ;
if ( membersid = = NULL )
2004-12-26 21:02:18 +03:00
return NT_STATUS_NO_MEMORY ;
/* In native mode, AD can also nest domain groups. Not sure yet
* whether this is also available via RPC . */
2006-12-05 07:25:27 +03:00
ret = ldb_search_exp_fmt ( d_state - > sam_ctx , mem_ctx , & res ,
d_state - > domain_dn , LDB_SCOPE_SUBTREE , attrs ,
" (&(objectSid=%s)(objectclass=user)) " ,
ldap_encode_ndr_dom_sid ( mem_ctx , membersid ) ) ;
2004-12-26 21:02:18 +03:00
2006-07-04 06:46:24 +04:00
if ( ret ! = 0 ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2004-12-26 21:02:18 +03:00
2006-07-04 06:46:24 +04:00
if ( res - > count = = 0 ) {
return NT_STATUS_NO_SUCH_USER ;
}
if ( res - > count > 1 ) {
2004-12-26 21:02:18 +03:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
2006-07-04 06:46:24 +04:00
}
2004-12-26 21:02:18 +03:00
2006-11-22 05:05:19 +03:00
memberdn = ldb_dn_alloc_linearized ( mem_ctx , res - > msgs [ 0 ] - > dn ) ;
2004-12-26 21:02:18 +03:00
if ( memberdn = = NULL )
2006-07-04 06:46:24 +04:00
return NT_STATUS_NO_MEMORY ;
2004-12-26 21:02:18 +03:00
2005-01-02 10:51:13 +03:00
mod = ldb_msg_new ( mem_ctx ) ;
if ( mod = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
mod - > dn = talloc_reference ( mem_ctx , a_state - > account_dn ) ;
2004-12-26 21:02:18 +03:00
2005-01-02 10:51:13 +03:00
if ( samdb_msg_add_delval ( d_state - > sam_ctx , mem_ctx , mod , " member " ,
2006-07-04 06:46:24 +04:00
memberdn ) ! = 0 ) {
return NT_STATUS_NO_MEMORY ;
}
2004-12-26 21:02:18 +03:00
2007-07-27 06:07:17 +04:00
ret = ldb_modify ( a_state - > sam_ctx , mod ) ;
2006-07-04 06:46:24 +04:00
switch ( ret ) {
case LDB_SUCCESS :
return NT_STATUS_OK ;
case LDB_ERR_NO_SUCH_ATTRIBUTE :
return NT_STATUS_MEMBER_NOT_IN_GROUP ;
2006-11-25 21:57:47 +03:00
case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS :
return NT_STATUS_ACCESS_DENIED ;
2006-07-04 06:46:24 +04:00
default :
2004-12-26 21:02:18 +03:00
return NT_STATUS_UNSUCCESSFUL ;
2006-07-04 06:46:24 +04:00
}
2004-12-26 21:02:18 +03:00
2004-05-03 18:58:08 +04:00
}
/*
samr_QueryGroupMember
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_QueryGroupMember ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2005-09-02 03:26:50 +04:00
struct samr_QueryGroupMember * r )
2004-05-03 18:58:08 +04:00
{
2004-12-26 21:02:18 +03:00
struct dcesrv_handle * h ;
struct samr_account_state * a_state ;
struct ldb_message * * res ;
struct ldb_message_element * el ;
2005-05-01 12:05:17 +04:00
struct samr_RidTypeArray * array ;
2004-12-26 21:02:18 +03:00
const char * const attrs [ 2 ] = { " member " , NULL } ;
int ret ;
DCESRV_PULL_HANDLE ( h , r - > in . group_handle , SAMR_HANDLE_GROUP ) ;
a_state = h - > data ;
/* pull the member attribute */
2005-06-14 23:15:17 +04:00
ret = gendb_search_dn ( a_state - > sam_ctx , mem_ctx ,
a_state - > account_dn , & res , attrs ) ;
2004-12-26 21:02:18 +03:00
if ( ret ! = 1 ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2005-05-01 12:05:17 +04:00
array = talloc ( mem_ctx , struct samr_RidTypeArray ) ;
2004-12-26 21:02:18 +03:00
if ( array = = NULL )
return NT_STATUS_NO_MEMORY ;
ZERO_STRUCTP ( array ) ;
el = ldb_msg_find_element ( res [ 0 ] , " member " ) ;
if ( el ! = NULL ) {
int i ;
array - > count = el - > num_values ;
2005-02-10 08:09:35 +03:00
array - > rids = talloc_array ( mem_ctx , uint32_t ,
2004-12-26 21:02:18 +03:00
el - > num_values ) ;
if ( array - > rids = = NULL )
return NT_STATUS_NO_MEMORY ;
2005-05-01 12:05:17 +04:00
array - > types = talloc_array ( mem_ctx , uint32_t ,
el - > num_values ) ;
if ( array - > types = = NULL )
2004-12-26 21:02:18 +03:00
return NT_STATUS_NO_MEMORY ;
for ( i = 0 ; i < el - > num_values ; i + + ) {
struct ldb_message * * res2 ;
const char * const attrs2 [ 2 ] = { " objectSid " , NULL } ;
2005-06-14 23:15:17 +04:00
ret = gendb_search_dn ( a_state - > sam_ctx , mem_ctx ,
2006-11-22 03:59:34 +03:00
ldb_dn_new ( mem_ctx , a_state - > sam_ctx , ( const char * ) el - > values [ i ] . data ) ,
2005-06-14 23:15:17 +04:00
& res2 , attrs2 ) ;
2004-12-26 21:02:18 +03:00
if ( ret ! = 1 )
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
array - > rids [ i ] =
samdb_result_rid_from_sid ( mem_ctx , res2 [ 0 ] ,
" objectSid " , 0 ) ;
if ( array - > rids [ i ] = = 0 )
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
2005-05-01 12:05:17 +04:00
array - > types [ i ] = 7 ; /* RID type of some kind, not sure what the value means. */
2004-12-26 21:02:18 +03:00
}
}
r - > out . rids = array ;
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
/*
samr_SetMemberAttributesOfGroup
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_SetMemberAttributesOfGroup ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_SetMemberAttributesOfGroup * r )
{
2004-05-04 10:07:52 +04:00
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
2004-05-03 18:58:08 +04:00
}
/*
samr_OpenAlias
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_OpenAlias ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_OpenAlias * r )
{
2004-12-27 14:27:30 +03:00
struct samr_domain_state * d_state ;
struct samr_account_state * a_state ;
struct dcesrv_handle * h ;
2005-06-24 04:18:20 +04:00
const char * alias_name ;
struct dom_sid * sid ;
2004-12-27 14:27:30 +03:00
struct ldb_message * * msgs ;
struct dcesrv_handle * g_handle ;
const char * const attrs [ 2 ] = { " sAMAccountName " , NULL } ;
int ret ;
ZERO_STRUCTP ( r - > out . alias_handle ) ;
DCESRV_PULL_HANDLE ( h , r - > in . domain_handle , SAMR_HANDLE_DOMAIN ) ;
d_state = h - > data ;
/* form the alias SID */
2005-06-24 04:18:20 +04:00
sid = dom_sid_add_rid ( mem_ctx , d_state - > domain_sid , r - > in . rid ) ;
if ( sid = = NULL )
2004-12-27 14:27:30 +03:00
return NT_STATUS_NO_MEMORY ;
/* search for the group record */
2005-03-23 04:30:43 +03:00
ret = gendb_search ( d_state - > sam_ctx ,
2004-12-27 14:27:30 +03:00
mem_ctx , d_state - > domain_dn , & msgs , attrs ,
" (&(objectSid=%s)(objectclass=group) "
2006-06-13 00:00:18 +04:00
" (|(grouptype=%d)(grouptype=%d))) " ,
2005-06-24 04:18:20 +04:00
ldap_encode_ndr_dom_sid ( mem_ctx , sid ) ,
2006-06-13 00:00:18 +04:00
GTYPE_SECURITY_BUILTIN_LOCAL_GROUP ,
GTYPE_SECURITY_DOMAIN_LOCAL_GROUP ) ;
2004-12-27 14:27:30 +03:00
if ( ret = = 0 ) {
return NT_STATUS_NO_SUCH_ALIAS ;
}
if ( ret ! = 1 ) {
2005-06-24 04:18:20 +04:00
DEBUG ( 0 , ( " Found %d records matching sid %s \n " ,
ret , dom_sid_string ( mem_ctx , sid ) ) ) ;
2004-12-27 14:27:30 +03:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2005-04-13 10:26:43 +04:00
alias_name = samdb_result_string ( msgs [ 0 ] , " sAMAccountName " , NULL ) ;
if ( alias_name = = NULL ) {
2005-06-24 04:18:20 +04:00
DEBUG ( 0 , ( " sAMAccountName field missing for sid %s \n " ,
dom_sid_string ( mem_ctx , sid ) ) ) ;
2004-12-27 14:27:30 +03:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2005-01-27 10:08:20 +03:00
a_state = talloc ( d_state , struct samr_account_state ) ;
2004-12-27 14:27:30 +03:00
if ( ! a_state ) {
return NT_STATUS_NO_MEMORY ;
}
a_state - > sam_ctx = d_state - > sam_ctx ;
a_state - > access_mask = r - > in . access_mask ;
a_state - > domain_state = talloc_reference ( a_state , d_state ) ;
a_state - > account_dn = talloc_steal ( a_state , msgs [ 0 ] - > dn ) ;
2005-06-24 04:18:20 +04:00
a_state - > account_sid = talloc_steal ( a_state , sid ) ;
2005-04-13 10:26:43 +04:00
a_state - > account_name = talloc_strdup ( a_state , alias_name ) ;
2004-12-27 14:27:30 +03:00
if ( ! a_state - > account_name ) {
return NT_STATUS_NO_MEMORY ;
}
/* create the policy handle */
2005-01-10 15:15:26 +03:00
g_handle = dcesrv_handle_new ( dce_call - > context , SAMR_HANDLE_ALIAS ) ;
2004-12-27 14:27:30 +03:00
if ( ! g_handle ) {
return NT_STATUS_NO_MEMORY ;
}
2005-01-10 15:15:26 +03:00
g_handle - > data = talloc_steal ( g_handle , a_state ) ;
2004-12-27 14:27:30 +03:00
* r - > out . alias_handle = g_handle - > wire_handle ;
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
/*
samr_QueryAliasInfo
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_QueryAliasInfo ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_QueryAliasInfo * r )
{
2004-12-27 14:27:30 +03:00
struct dcesrv_handle * h ;
struct samr_account_state * a_state ;
struct ldb_message * msg , * * res ;
const char * const attrs [ 4 ] = { " sAMAccountName " , " description " ,
" numMembers " , NULL } ;
int ret ;
r - > out . info = NULL ;
DCESRV_PULL_HANDLE ( h , r - > in . alias_handle , SAMR_HANDLE_ALIAS ) ;
a_state = h - > data ;
/* pull all the alias attributes */
2005-06-14 23:15:17 +04:00
ret = gendb_search_dn ( a_state - > sam_ctx , mem_ctx ,
a_state - > account_dn , & res , attrs ) ;
2004-12-27 14:27:30 +03:00
if ( ret ! = 1 ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
msg = res [ 0 ] ;
/* allocate the info structure */
2005-01-27 10:08:20 +03:00
r - > out . info = talloc ( mem_ctx , union samr_AliasInfo ) ;
2004-12-27 14:27:30 +03:00
if ( r - > out . info = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
ZERO_STRUCTP ( r - > out . info ) ;
switch ( r - > in . level ) {
2005-01-29 05:46:37 +03:00
case ALIASINFOALL :
2007-07-27 06:07:17 +04:00
QUERY_STRING ( msg , all . name , " sAMAccountName " ) ;
2004-12-27 14:27:30 +03:00
QUERY_UINT ( msg , all . num_members , " numMembers " ) ;
2007-07-27 06:07:17 +04:00
QUERY_STRING ( msg , all . description , " description " ) ;
2004-12-27 14:27:30 +03:00
break ;
2005-01-29 05:46:37 +03:00
case ALIASINFONAME :
2007-07-27 06:07:17 +04:00
QUERY_STRING ( msg , name , " sAMAccountName " ) ;
2004-12-27 14:27:30 +03:00
break ;
2005-01-29 05:46:37 +03:00
case ALIASINFODESCRIPTION :
2007-07-27 06:07:17 +04:00
QUERY_STRING ( msg , description , " description " ) ;
2004-12-27 14:27:30 +03:00
break ;
default :
r - > out . info = NULL ;
return NT_STATUS_INVALID_INFO_CLASS ;
}
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
/*
samr_SetAliasInfo
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_SetAliasInfo ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_SetAliasInfo * r )
{
2004-12-27 14:27:30 +03:00
struct dcesrv_handle * h ;
struct samr_account_state * a_state ;
2005-01-02 10:51:13 +03:00
struct ldb_message * msg ;
2006-07-04 06:46:24 +04:00
struct ldb_context * sam_ctx ;
2004-12-27 14:27:30 +03:00
int ret ;
DCESRV_PULL_HANDLE ( h , r - > in . alias_handle , SAMR_HANDLE_ALIAS ) ;
a_state = h - > data ;
2006-07-04 06:46:24 +04:00
sam_ctx = a_state - > sam_ctx ;
2004-12-27 14:27:30 +03:00
2005-01-02 10:51:13 +03:00
msg = ldb_msg_new ( mem_ctx ) ;
if ( msg = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2005-08-18 19:02:01 +04:00
msg - > dn = ldb_dn_copy ( mem_ctx , a_state - > account_dn ) ;
2005-01-02 10:51:13 +03:00
if ( ! msg - > dn ) {
2004-12-27 14:27:30 +03:00
return NT_STATUS_NO_MEMORY ;
}
switch ( r - > in . level ) {
2005-01-29 05:46:37 +03:00
case ALIASINFODESCRIPTION :
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , description , " description " ) ;
2004-12-27 14:27:30 +03:00
break ;
2005-01-29 05:46:37 +03:00
case ALIASINFONAME :
2004-12-27 14:27:30 +03:00
/* On W2k3 this does not change the name, it changes the
* sAMAccountName attribute */
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , name , " sAMAccountName " ) ;
2004-12-27 14:27:30 +03:00
break ;
default :
return NT_STATUS_INVALID_INFO_CLASS ;
}
/* modify the samdb record */
2007-07-27 06:07:17 +04:00
ret = ldb_modify ( a_state - > sam_ctx , msg ) ;
2004-12-27 14:27:30 +03:00
if ( ret ! = 0 ) {
/* we really need samdb.c to return NTSTATUS */
return NT_STATUS_UNSUCCESSFUL ;
}
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
/*
samr_DeleteDomAlias
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_DeleteDomAlias ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_DeleteDomAlias * r )
{
2005-03-28 03:31:43 +04:00
struct dcesrv_handle * h ;
struct samr_account_state * a_state ;
int ret ;
* r - > out . alias_handle = * r - > in . alias_handle ;
DCESRV_PULL_HANDLE ( h , r - > in . alias_handle , SAMR_HANDLE_ALIAS ) ;
a_state = h - > data ;
ret = samdb_delete ( a_state - > sam_ctx , mem_ctx , a_state - > account_dn ) ;
if ( ret ! = 0 ) {
return NT_STATUS_UNSUCCESSFUL ;
}
ZERO_STRUCTP ( r - > out . alias_handle ) ;
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
/*
samr_AddAliasMember
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_AddAliasMember ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_AddAliasMember * r )
{
2004-12-28 01:20:17 +03:00
struct dcesrv_handle * h ;
struct samr_account_state * a_state ;
struct samr_domain_state * d_state ;
2005-01-02 10:51:13 +03:00
struct ldb_message * mod ;
2004-12-28 01:20:17 +03:00
struct ldb_message * * msgs ;
2006-07-04 06:46:24 +04:00
const char * const attrs [ ] = { NULL } ;
2005-08-18 19:02:01 +04:00
struct ldb_dn * memberdn = NULL ;
2004-12-28 01:20:17 +03:00
int ret ;
2006-07-06 09:23:29 +04:00
NTSTATUS status ;
2004-12-28 01:20:17 +03:00
DCESRV_PULL_HANDLE ( h , r - > in . alias_handle , SAMR_HANDLE_ALIAS ) ;
a_state = h - > data ;
d_state = a_state - > domain_state ;
2006-08-25 11:08:06 +04:00
ret = gendb_search ( d_state - > sam_ctx , mem_ctx , NULL ,
2005-06-24 04:18:20 +04:00
& msgs , attrs , " (objectsid=%s) " ,
ldap_encode_ndr_dom_sid ( mem_ctx , r - > in . sid ) ) ;
2004-12-28 01:20:17 +03:00
if ( ret = = 1 ) {
2006-07-04 06:46:24 +04:00
memberdn = msgs [ 0 ] - > dn ;
2004-12-28 01:20:17 +03:00
} else if ( ret > 1 ) {
2005-06-24 04:18:20 +04:00
DEBUG ( 0 , ( " Found %d records matching sid %s \n " ,
ret , dom_sid_string ( mem_ctx , r - > in . sid ) ) ) ;
2004-12-28 01:20:17 +03:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
} else if ( ret = = 0 ) {
2006-07-06 09:23:29 +04:00
status = samdb_create_foreign_security_principal ( d_state - > sam_ctx , mem_ctx ,
r - > in . sid , & memberdn ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2004-12-28 01:20:17 +03:00
}
} else {
2006-07-06 09:23:29 +04:00
DEBUG ( 0 , ( " samdb_search returned %d: %s \n " , ret , ldb_errstring ( d_state - > sam_ctx ) ) ) ;
2004-12-28 01:20:17 +03:00
}
if ( memberdn = = NULL ) {
DEBUG ( 0 , ( " Could not find memberdn \n " ) ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2005-01-02 10:51:13 +03:00
mod = ldb_msg_new ( mem_ctx ) ;
if ( mod = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
mod - > dn = talloc_reference ( mem_ctx , a_state - > account_dn ) ;
2004-12-28 01:20:17 +03:00
2005-01-02 10:51:13 +03:00
if ( samdb_msg_add_addval ( d_state - > sam_ctx , mem_ctx , mod , " member " ,
2006-11-22 05:05:19 +03:00
ldb_dn_alloc_linearized ( mem_ctx , memberdn ) ) ! = 0 )
2004-12-28 01:20:17 +03:00
return NT_STATUS_UNSUCCESSFUL ;
2007-07-27 06:07:17 +04:00
if ( ldb_modify ( a_state - > sam_ctx , mod ) ! = 0 )
2004-12-28 01:20:17 +03:00
return NT_STATUS_UNSUCCESSFUL ;
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
/*
samr_DeleteAliasMember
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_DeleteAliasMember ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_DeleteAliasMember * r )
{
2004-12-28 01:20:17 +03:00
struct dcesrv_handle * h ;
struct samr_account_state * a_state ;
struct samr_domain_state * d_state ;
2005-01-02 10:51:13 +03:00
struct ldb_message * mod ;
2004-12-28 01:20:17 +03:00
const char * memberdn ;
DCESRV_PULL_HANDLE ( h , r - > in . alias_handle , SAMR_HANDLE_ALIAS ) ;
a_state = h - > data ;
d_state = a_state - > domain_state ;
2006-08-25 11:08:06 +04:00
memberdn = samdb_search_string ( d_state - > sam_ctx , mem_ctx , NULL ,
2005-10-11 15:00:16 +04:00
" distinguishedName " , " (objectSid=%s) " ,
2005-06-24 04:18:20 +04:00
ldap_encode_ndr_dom_sid ( mem_ctx , r - > in . sid ) ) ;
2004-12-28 01:20:17 +03:00
if ( memberdn = = NULL )
return NT_STATUS_OBJECT_NAME_NOT_FOUND ;
2005-01-02 10:51:13 +03:00
mod = ldb_msg_new ( mem_ctx ) ;
if ( mod = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
mod - > dn = talloc_reference ( mem_ctx , a_state - > account_dn ) ;
2004-12-28 01:20:17 +03:00
2005-01-02 10:51:13 +03:00
if ( samdb_msg_add_delval ( d_state - > sam_ctx , mem_ctx , mod , " member " ,
2004-12-28 01:20:17 +03:00
memberdn ) ! = 0 )
return NT_STATUS_UNSUCCESSFUL ;
2007-07-27 06:07:17 +04:00
if ( ldb_modify ( a_state - > sam_ctx , mod ) ! = 0 )
2004-12-28 01:20:17 +03:00
return NT_STATUS_UNSUCCESSFUL ;
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
/*
samr_GetMembersInAlias
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_GetMembersInAlias ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_GetMembersInAlias * r )
{
2004-12-28 01:20:17 +03:00
struct dcesrv_handle * h ;
struct samr_account_state * a_state ;
struct samr_domain_state * d_state ;
struct ldb_message * * msgs ;
struct lsa_SidPtr * sids ;
struct ldb_message_element * el ;
const char * const attrs [ 2 ] = { " member " , NULL } ;
int ret ;
DCESRV_PULL_HANDLE ( h , r - > in . alias_handle , SAMR_HANDLE_ALIAS ) ;
a_state = h - > data ;
d_state = a_state - > domain_state ;
2005-06-14 23:15:17 +04:00
ret = gendb_search_dn ( d_state - > sam_ctx , mem_ctx ,
a_state - > account_dn , & msgs , attrs ) ;
2004-05-03 18:58:08 +04:00
2004-12-28 01:20:17 +03:00
if ( ret ! = 1 )
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
2004-12-29 16:22:00 +03:00
r - > out . sids - > num_sids = 0 ;
r - > out . sids - > sids = NULL ;
2004-12-28 01:20:17 +03:00
el = ldb_msg_find_element ( msgs [ 0 ] , " member " ) ;
if ( el ! = NULL ) {
int i ;
2005-01-27 10:08:20 +03:00
sids = talloc_array ( mem_ctx , struct lsa_SidPtr ,
2004-12-28 01:20:17 +03:00
el - > num_values ) ;
if ( sids = = NULL )
return NT_STATUS_NO_MEMORY ;
for ( i = 0 ; i < el - > num_values ; i + + ) {
struct ldb_message * * msgs2 ;
const char * const attrs2 [ 2 ] = { " objectSid " , NULL } ;
2005-06-14 23:15:17 +04:00
ret = gendb_search_dn ( a_state - > sam_ctx , mem_ctx ,
2006-11-22 03:59:34 +03:00
ldb_dn_new ( mem_ctx , a_state - > sam_ctx , ( const char * ) el - > values [ i ] . data ) ,
2005-06-14 23:15:17 +04:00
& msgs2 , attrs2 ) ;
2004-12-28 01:20:17 +03:00
if ( ret ! = 1 )
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
sids [ i ] . sid = samdb_result_dom_sid ( mem_ctx , msgs2 [ 0 ] ,
" objectSid " ) ;
if ( sids [ i ] . sid = = NULL )
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2004-12-29 16:22:00 +03:00
r - > out . sids - > num_sids = el - > num_values ;
r - > out . sids - > sids = sids ;
2004-12-28 01:20:17 +03:00
}
return NT_STATUS_OK ;
}
2004-05-03 18:58:08 +04:00
/*
samr_OpenUser
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_OpenUser ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-08 04:02:31 +04:00
struct samr_OpenUser * r )
2004-05-03 18:58:08 +04:00
{
2004-05-08 04:02:31 +04:00
struct samr_domain_state * d_state ;
2004-05-10 16:37:06 +04:00
struct samr_account_state * a_state ;
2004-05-08 04:02:31 +04:00
struct dcesrv_handle * h ;
2005-06-24 04:18:20 +04:00
const char * account_name ;
struct dom_sid * sid ;
2004-05-08 04:02:31 +04:00
struct ldb_message * * msgs ;
struct dcesrv_handle * u_handle ;
const char * const attrs [ 2 ] = { " sAMAccountName " , NULL } ;
int ret ;
2004-09-21 07:51:38 +04:00
ZERO_STRUCTP ( r - > out . user_handle ) ;
2004-05-08 04:02:31 +04:00
2004-09-21 07:51:38 +04:00
DCESRV_PULL_HANDLE ( h , r - > in . domain_handle , SAMR_HANDLE_DOMAIN ) ;
2004-05-08 04:02:31 +04:00
d_state = h - > data ;
/* form the users SID */
2005-06-24 04:18:20 +04:00
sid = dom_sid_add_rid ( mem_ctx , d_state - > domain_sid , r - > in . rid ) ;
if ( ! sid ) {
2004-05-08 04:02:31 +04:00
return NT_STATUS_NO_MEMORY ;
}
/* search for the user record */
2005-03-23 04:30:43 +03:00
ret = gendb_search ( d_state - > sam_ctx ,
2004-05-10 16:37:06 +04:00
mem_ctx , d_state - > domain_dn , & msgs , attrs ,
2004-05-08 04:02:31 +04:00
" (&(objectSid=%s)(objectclass=user)) " ,
2005-06-24 04:18:20 +04:00
ldap_encode_ndr_dom_sid ( mem_ctx , sid ) ) ;
2004-05-08 04:02:31 +04:00
if ( ret = = 0 ) {
return NT_STATUS_NO_SUCH_USER ;
}
if ( ret ! = 1 ) {
2005-06-24 04:18:20 +04:00
DEBUG ( 0 , ( " Found %d records matching sid %s \n " , ret ,
dom_sid_string ( mem_ctx , sid ) ) ) ;
2004-05-08 04:02:31 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2004-06-05 07:22:10 +04:00
account_name = samdb_result_string ( msgs [ 0 ] , " sAMAccountName " , NULL ) ;
if ( account_name = = NULL ) {
2005-06-24 04:18:20 +04:00
DEBUG ( 0 , ( " sAMAccountName field missing for sid %s \n " ,
dom_sid_string ( mem_ctx , sid ) ) ) ;
2004-05-08 04:02:31 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2005-01-27 10:08:20 +03:00
a_state = talloc ( mem_ctx , struct samr_account_state ) ;
2004-05-10 16:37:06 +04:00
if ( ! a_state ) {
2004-05-08 04:02:31 +04:00
return NT_STATUS_NO_MEMORY ;
}
2004-05-10 16:37:06 +04:00
a_state - > sam_ctx = d_state - > sam_ctx ;
a_state - > access_mask = r - > in . access_mask ;
2004-09-27 09:13:00 +04:00
a_state - > domain_state = talloc_reference ( a_state , d_state ) ;
2004-12-23 15:02:55 +03:00
a_state - > account_dn = talloc_steal ( a_state , msgs [ 0 ] - > dn ) ;
2005-06-24 04:18:20 +04:00
a_state - > account_sid = talloc_steal ( a_state , sid ) ;
2004-12-23 15:02:55 +03:00
a_state - > account_name = talloc_strdup ( a_state , account_name ) ;
if ( ! a_state - > account_name ) {
2004-05-08 04:02:31 +04:00
return NT_STATUS_NO_MEMORY ;
}
/* create the policy handle */
2005-01-10 15:15:26 +03:00
u_handle = dcesrv_handle_new ( dce_call - > context , SAMR_HANDLE_USER ) ;
2004-05-08 04:02:31 +04:00
if ( ! u_handle ) {
return NT_STATUS_NO_MEMORY ;
}
2005-01-10 15:15:26 +03:00
u_handle - > data = talloc_steal ( u_handle , a_state ) ;
2004-05-08 04:02:31 +04:00
2004-09-21 07:51:38 +04:00
* r - > out . user_handle = u_handle - > wire_handle ;
2004-05-08 04:02:31 +04:00
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
/*
samr_DeleteUser
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_DeleteUser ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-08 04:02:31 +04:00
struct samr_DeleteUser * r )
2004-05-03 18:58:08 +04:00
{
2004-05-08 04:02:31 +04:00
struct dcesrv_handle * h ;
2004-05-10 16:37:06 +04:00
struct samr_account_state * a_state ;
2004-05-08 04:02:31 +04:00
int ret ;
2004-09-21 07:51:38 +04:00
* r - > out . user_handle = * r - > in . user_handle ;
2004-05-08 04:02:31 +04:00
2004-09-21 07:51:38 +04:00
DCESRV_PULL_HANDLE ( h , r - > in . user_handle , SAMR_HANDLE_USER ) ;
2004-05-08 04:02:31 +04:00
2004-05-10 16:37:06 +04:00
a_state = h - > data ;
2004-05-08 04:02:31 +04:00
2004-05-10 16:37:06 +04:00
ret = samdb_delete ( a_state - > sam_ctx , mem_ctx , a_state - > account_dn ) ;
2004-05-08 04:02:31 +04:00
if ( ret ! = 0 ) {
return NT_STATUS_UNSUCCESSFUL ;
}
2004-09-21 07:51:38 +04:00
ZERO_STRUCTP ( r - > out . user_handle ) ;
2004-05-08 04:02:31 +04:00
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
/*
samr_QueryUserInfo
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_QueryUserInfo ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-08 18:42:45 +04:00
struct samr_QueryUserInfo * r )
2004-05-03 18:58:08 +04:00
{
2004-05-08 18:42:45 +04:00
struct dcesrv_handle * h ;
2004-05-10 16:37:06 +04:00
struct samr_account_state * a_state ;
2004-05-08 18:42:45 +04:00
struct ldb_message * msg , * * res ;
int ret ;
2006-07-04 06:46:24 +04:00
struct ldb_context * sam_ctx ;
const char * const * attrs = NULL ;
2004-05-08 18:42:45 +04:00
r - > out . info = NULL ;
2004-09-21 07:51:38 +04:00
DCESRV_PULL_HANDLE ( h , r - > in . user_handle , SAMR_HANDLE_USER ) ;
2004-05-08 18:42:45 +04:00
2004-05-10 16:37:06 +04:00
a_state = h - > data ;
2006-07-04 06:46:24 +04:00
sam_ctx = a_state - > sam_ctx ;
/* fill in the reply */
switch ( r - > in . level ) {
case 1 :
{
static const char * const attrs2 [ ] = { " sAMAccountName " , " displayName " ,
" primaryGroupID " , " description " ,
" comment " , NULL } ;
attrs = attrs2 ;
break ;
}
case 2 :
{
static const char * const attrs2 [ ] = { " comment " , " countryCode " , " codePage " , NULL } ;
attrs = attrs2 ;
break ;
}
case 3 :
{
static const char * const attrs2 [ ] = { " sAMAccountName " ,
" displayName " ,
" objectSid " ,
" primaryGroupID " ,
" homeDirectory " ,
" homeDrive " ,
" scriptPath " ,
" profilePath " ,
" userWorkstations " ,
" lastLogon " ,
" lastLogoff " ,
" pwdLastSet " ,
" logonHours " ,
" badPwdCount " ,
" logonCount " ,
" userAccountControl " , NULL } ;
attrs = attrs2 ;
break ;
}
case 4 :
{
static const char * const attrs2 [ ] = { " logonHours " , NULL } ;
attrs = attrs2 ;
break ;
}
case 5 :
{
static const char * const attrs2 [ ] = { " sAMAccountName " ,
" displayName " ,
" objectSid " ,
" primaryGroupID " ,
" homeDirectory " ,
" homeDrive " ,
" scriptPath " ,
" profilePath " ,
" description " ,
" userWorkstations " ,
" lastLogon " ,
" lastLogoff " ,
" logonHours " ,
" badPwdCount " ,
" logonCount " ,
" pwdLastSet " ,
" accountExpires " ,
" userAccountControl " ,
NULL } ;
attrs = attrs2 ;
break ;
}
case 6 :
{
static const char * const attrs2 [ ] = { " sAMAccountName " , " displayName " , NULL } ;
attrs = attrs2 ;
break ;
}
case 7 :
{
static const char * const attrs2 [ ] = { " sAMAccountName " , NULL } ;
attrs = attrs2 ;
break ;
}
case 8 :
{
static const char * const attrs2 [ ] = { " displayName " , NULL } ;
attrs = attrs2 ;
break ;
}
case 9 :
{
static const char * const attrs2 [ ] = { " primaryGroupID " , NULL } ;
attrs = attrs2 ;
break ;
}
case 10 :
{
static const char * const attrs2 [ ] = { " homeDirectory " , " homeDrive " , NULL } ;
attrs = attrs2 ;
break ;
}
case 11 :
{
static const char * const attrs2 [ ] = { " scriptPath " , NULL } ;
attrs = attrs2 ;
break ;
}
case 12 :
{
static const char * const attrs2 [ ] = { " profilePath " , NULL } ;
attrs = attrs2 ;
break ;
}
case 13 :
{
static const char * const attrs2 [ ] = { " description " , NULL } ;
attrs = attrs2 ;
break ;
}
case 14 :
{
static const char * const attrs2 [ ] = { " userWorkstations " , NULL } ;
attrs = attrs2 ;
break ;
}
case 16 :
{
static const char * const attrs2 [ ] = { " userAccountControl " , NULL } ;
attrs = attrs2 ;
break ;
}
case 17 :
{
static const char * const attrs2 [ ] = { " accountExpires " , NULL } ;
attrs = attrs2 ;
break ;
}
case 20 :
{
static const char * const attrs2 [ ] = { " userParameters " , NULL } ;
attrs = attrs2 ;
break ;
}
case 21 :
{
static const char * const attrs2 [ ] = { " lastLogon " ,
" lastLogoff " ,
" pwdLastSet " ,
" accountExpires " ,
" sAMAccountName " ,
" displayName " ,
" homeDirectory " ,
" homeDrive " ,
" scriptPath " ,
" profilePath " ,
" description " ,
" userWorkstations " ,
" comment " ,
" userParameters " ,
" objectSid " ,
" primaryGroupID " ,
" userAccountControl " ,
" logonHours " ,
" badPwdCount " ,
" logonCount " ,
" countryCode " ,
" codePage " ,
NULL } ;
attrs = attrs2 ;
break ;
}
}
2004-05-08 18:42:45 +04:00
/* pull all the user attributes */
2005-06-14 23:15:17 +04:00
ret = gendb_search_dn ( a_state - > sam_ctx , mem_ctx ,
2006-07-04 06:46:24 +04:00
a_state - > account_dn , & res , attrs ) ;
2004-05-08 18:42:45 +04:00
if ( ret ! = 1 ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
msg = res [ 0 ] ;
/* allocate the info structure */
2005-01-27 10:08:20 +03:00
r - > out . info = talloc ( mem_ctx , union samr_UserInfo ) ;
2004-05-08 18:42:45 +04:00
if ( r - > out . info = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
ZERO_STRUCTP ( r - > out . info ) ;
/* fill in the reply */
switch ( r - > in . level ) {
case 1 :
2007-07-27 06:07:17 +04:00
QUERY_STRING ( msg , info1 . account_name , " sAMAccountName " ) ;
QUERY_STRING ( msg , info1 . full_name , " displayName " ) ;
2004-11-13 16:45:41 +03:00
QUERY_UINT ( msg , info1 . primary_gid , " primaryGroupID " ) ;
2007-07-27 06:07:17 +04:00
QUERY_STRING ( msg , info1 . description , " description " ) ;
QUERY_STRING ( msg , info1 . comment , " comment " ) ;
2004-05-08 18:42:45 +04:00
break ;
case 2 :
2007-07-27 06:07:17 +04:00
QUERY_STRING ( msg , info2 . comment , " comment " ) ;
2004-11-13 16:45:41 +03:00
QUERY_UINT ( msg , info2 . country_code , " countryCode " ) ;
QUERY_UINT ( msg , info2 . code_page , " codePage " ) ;
2004-05-08 18:42:45 +04:00
break ;
case 3 :
2007-07-27 06:07:17 +04:00
QUERY_STRING ( msg , info3 . account_name , " sAMAccountName " ) ;
QUERY_STRING ( msg , info3 . full_name , " displayName " ) ;
2004-11-13 16:45:41 +03:00
QUERY_RID ( msg , info3 . rid , " objectSid " ) ;
QUERY_UINT ( msg , info3 . primary_gid , " primaryGroupID " ) ;
2007-07-27 06:07:17 +04:00
QUERY_STRING ( msg , info3 . home_directory , " homeDirectory " ) ;
QUERY_STRING ( msg , info3 . home_drive , " homeDrive " ) ;
QUERY_STRING ( msg , info3 . logon_script , " scriptPath " ) ;
QUERY_STRING ( msg , info3 . profile_path , " profilePath " ) ;
QUERY_STRING ( msg , info3 . workstations , " userWorkstations " ) ;
2007-09-06 08:01:52 +04:00
QUERY_UINT64 ( msg , info3 . last_logon , " lastLogon " ) ;
QUERY_UINT64 ( msg , info3 . last_logoff , " lastLogoff " ) ;
QUERY_UINT64 ( msg , info3 . last_password_change , " pwdLastSet " ) ;
2004-11-13 16:45:41 +03:00
QUERY_APASSC ( msg , info3 . allow_password_change , " pwdLastSet " ) ;
QUERY_FPASSC ( msg , info3 . force_password_change , " pwdLastSet " ) ;
QUERY_LHOURS ( msg , info3 . logon_hours , " logonHours " ) ;
QUERY_UINT ( msg , info3 . bad_password_count , " badPwdCount " ) ;
QUERY_UINT ( msg , info3 . logon_count , " logonCount " ) ;
QUERY_AFLAGS ( msg , info3 . acct_flags , " userAccountControl " ) ;
2004-05-09 13:39:47 +04:00
break ;
case 4 :
2004-11-13 16:45:41 +03:00
QUERY_LHOURS ( msg , info4 . logon_hours , " logonHours " ) ;
2004-05-09 13:39:47 +04:00
break ;
case 5 :
2007-07-27 06:07:17 +04:00
QUERY_STRING ( msg , info5 . account_name , " sAMAccountName " ) ;
QUERY_STRING ( msg , info5 . full_name , " displayName " ) ;
2004-11-13 16:45:41 +03:00
QUERY_RID ( msg , info5 . rid , " objectSid " ) ;
QUERY_UINT ( msg , info5 . primary_gid , " primaryGroupID " ) ;
2007-07-27 06:07:17 +04:00
QUERY_STRING ( msg , info5 . home_directory , " homeDirectory " ) ;
QUERY_STRING ( msg , info5 . home_drive , " homeDrive " ) ;
QUERY_STRING ( msg , info5 . logon_script , " scriptPath " ) ;
QUERY_STRING ( msg , info5 . profile_path , " profilePath " ) ;
QUERY_STRING ( msg , info5 . description , " description " ) ;
QUERY_STRING ( msg , info5 . workstations , " userWorkstations " ) ;
2007-09-06 08:01:52 +04:00
QUERY_UINT64 ( msg , info5 . last_logon , " lastLogon " ) ;
QUERY_UINT64 ( msg , info5 . last_logoff , " lastLogoff " ) ;
2004-11-13 16:45:41 +03:00
QUERY_LHOURS ( msg , info5 . logon_hours , " logonHours " ) ;
QUERY_UINT ( msg , info5 . bad_password_count , " badPwdCount " ) ;
QUERY_UINT ( msg , info5 . logon_count , " logonCount " ) ;
2007-09-06 08:01:52 +04:00
QUERY_UINT64 ( msg , info5 . last_password_change , " pwdLastSet " ) ;
QUERY_UINT64 ( msg , info5 . acct_expiry , " accountExpires " ) ;
2004-11-13 16:45:41 +03:00
QUERY_AFLAGS ( msg , info5 . acct_flags , " userAccountControl " ) ;
2004-05-09 13:39:47 +04:00
break ;
case 6 :
2007-07-27 06:07:17 +04:00
QUERY_STRING ( msg , info6 . account_name , " sAMAccountName " ) ;
QUERY_STRING ( msg , info6 . full_name , " displayName " ) ;
2004-05-09 13:39:47 +04:00
break ;
case 7 :
2007-07-27 06:07:17 +04:00
QUERY_STRING ( msg , info7 . account_name , " sAMAccountName " ) ;
2004-05-09 13:39:47 +04:00
break ;
case 8 :
2007-07-27 06:07:17 +04:00
QUERY_STRING ( msg , info8 . full_name , " displayName " ) ;
2004-05-09 13:39:47 +04:00
break ;
case 9 :
2007-07-27 06:07:17 +04:00
QUERY_UINT ( msg , info9 . primary_gid , " primaryGroupID " ) ;
2004-05-09 13:39:47 +04:00
break ;
case 10 :
2007-07-27 06:07:17 +04:00
QUERY_STRING ( msg , info10 . home_directory , " homeDirectory " ) ;
QUERY_STRING ( msg , info10 . home_drive , " homeDrive " ) ;
2004-05-09 13:39:47 +04:00
break ;
case 11 :
2007-07-27 06:07:17 +04:00
QUERY_STRING ( msg , info11 . logon_script , " scriptPath " ) ;
2004-05-08 18:42:45 +04:00
break ;
2004-05-09 13:39:47 +04:00
case 12 :
2007-07-27 06:07:17 +04:00
QUERY_STRING ( msg , info12 . profile_path , " profilePath " ) ;
2004-05-09 13:39:47 +04:00
break ;
case 13 :
2007-07-27 06:07:17 +04:00
QUERY_STRING ( msg , info13 . description , " description " ) ;
2004-05-09 13:39:47 +04:00
break ;
case 14 :
2007-07-27 06:07:17 +04:00
QUERY_STRING ( msg , info14 . workstations , " userWorkstations " ) ;
2004-05-09 13:39:47 +04:00
break ;
case 16 :
2007-07-27 06:07:17 +04:00
QUERY_AFLAGS ( msg , info16 . acct_flags , " userAccountControl " ) ;
2004-05-09 13:39:47 +04:00
break ;
case 17 :
2007-09-06 08:01:52 +04:00
QUERY_UINT64 ( msg , info17 . acct_expiry , " accountExpires " ) ;
2004-05-09 13:39:47 +04:00
case 20 :
2007-07-27 06:07:17 +04:00
QUERY_STRING ( msg , info20 . parameters , " userParameters " ) ;
2004-05-09 13:39:47 +04:00
break ;
case 21 :
2007-09-06 08:01:52 +04:00
QUERY_UINT64 ( msg , info21 . last_logon , " lastLogon " ) ;
QUERY_UINT64 ( msg , info21 . last_logoff , " lastLogoff " ) ;
QUERY_UINT64 ( msg , info21 . last_password_change , " pwdLastSet " ) ;
QUERY_UINT64 ( msg , info21 . acct_expiry , " accountExpires " ) ;
2004-06-05 08:32:50 +04:00
QUERY_APASSC ( msg , info21 . allow_password_change , " pwdLastSet " ) ;
QUERY_FPASSC ( msg , info21 . force_password_change , " pwdLastSet " ) ;
2007-07-27 06:07:17 +04:00
QUERY_STRING ( msg , info21 . account_name , " sAMAccountName " ) ;
QUERY_STRING ( msg , info21 . full_name , " displayName " ) ;
QUERY_STRING ( msg , info21 . home_directory , " homeDirectory " ) ;
QUERY_STRING ( msg , info21 . home_drive , " homeDrive " ) ;
QUERY_STRING ( msg , info21 . logon_script , " scriptPath " ) ;
QUERY_STRING ( msg , info21 . profile_path , " profilePath " ) ;
QUERY_STRING ( msg , info21 . description , " description " ) ;
QUERY_STRING ( msg , info21 . workstations , " userWorkstations " ) ;
QUERY_STRING ( msg , info21 . comment , " comment " ) ;
QUERY_STRING ( msg , info21 . parameters , " userParameters " ) ;
2004-11-13 16:45:41 +03:00
QUERY_RID ( msg , info21 . rid , " objectSid " ) ;
QUERY_UINT ( msg , info21 . primary_gid , " primaryGroupID " ) ;
QUERY_AFLAGS ( msg , info21 . acct_flags , " userAccountControl " ) ;
2004-05-09 13:39:47 +04:00
r - > out . info - > info21 . fields_present = 0x00FFFFFF ;
2004-11-13 16:45:41 +03:00
QUERY_LHOURS ( msg , info21 . logon_hours , " logonHours " ) ;
QUERY_UINT ( msg , info21 . bad_password_count , " badPwdCount " ) ;
QUERY_UINT ( msg , info21 . logon_count , " logonCount " ) ;
QUERY_UINT ( msg , info21 . country_code , " countryCode " ) ;
QUERY_UINT ( msg , info21 . code_page , " codePage " ) ;
2004-05-09 13:39:47 +04:00
break ;
2004-05-08 18:42:45 +04:00
default :
r - > out . info = NULL ;
return NT_STATUS_INVALID_INFO_CLASS ;
}
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
2004-05-09 13:39:47 +04:00
2004-05-03 18:58:08 +04:00
/*
samr_SetUserInfo
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_SetUserInfo ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-08 18:42:45 +04:00
struct samr_SetUserInfo * r )
2004-05-03 18:58:08 +04:00
{
2004-05-08 18:42:45 +04:00
struct dcesrv_handle * h ;
2004-05-10 16:37:06 +04:00
struct samr_account_state * a_state ;
2005-01-02 10:51:13 +03:00
struct ldb_message * msg ;
2004-05-22 04:53:57 +04:00
int ret ;
2004-05-10 15:23:50 +04:00
NTSTATUS status = NT_STATUS_OK ;
2006-07-04 06:46:24 +04:00
struct ldb_context * sam_ctx ;
2004-05-08 18:42:45 +04:00
2004-09-21 07:51:38 +04:00
DCESRV_PULL_HANDLE ( h , r - > in . user_handle , SAMR_HANDLE_USER ) ;
2004-05-08 18:42:45 +04:00
2004-05-10 16:37:06 +04:00
a_state = h - > data ;
2006-07-04 06:46:24 +04:00
sam_ctx = a_state - > sam_ctx ;
2004-05-08 18:42:45 +04:00
2005-01-02 10:51:13 +03:00
msg = ldb_msg_new ( mem_ctx ) ;
if ( msg = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2005-01-11 16:59:18 +03:00
msg - > dn = talloc_reference ( mem_ctx , a_state - > account_dn ) ;
2005-01-02 10:51:13 +03:00
if ( ! msg - > dn ) {
2004-05-08 18:42:45 +04:00
return NT_STATUS_NO_MEMORY ;
}
switch ( r - > in . level ) {
case 2 :
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info2 . comment , " comment " ) ;
SET_UINT ( msg , info2 . country_code , " countryCode " ) ;
SET_UINT ( msg , info2 . code_page , " codePage " ) ;
2004-05-09 13:39:47 +04:00
break ;
case 4 :
2007-07-27 06:07:17 +04:00
SET_LHOURS ( msg , info4 . logon_hours , " logonHours " ) ;
2004-05-09 13:39:47 +04:00
break ;
case 6 :
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info6 . full_name , " displayName " ) ;
2004-05-09 13:39:47 +04:00
break ;
2005-03-13 09:43:34 +03:00
case 7 :
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info7 . account_name , " samAccountName " ) ;
2005-03-13 09:43:34 +03:00
break ;
2004-05-09 13:39:47 +04:00
case 8 :
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info8 . full_name , " displayName " ) ;
2004-05-09 13:39:47 +04:00
break ;
case 9 :
2007-07-27 06:07:17 +04:00
SET_UINT ( msg , info9 . primary_gid , " primaryGroupID " ) ;
2004-05-09 13:39:47 +04:00
break ;
case 10 :
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info10 . home_directory , " homeDirectory " ) ;
SET_STRING ( msg , info10 . home_drive , " homeDrive " ) ;
2004-05-09 13:39:47 +04:00
break ;
case 11 :
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info11 . logon_script , " scriptPath " ) ;
2004-05-09 13:39:47 +04:00
break ;
case 12 :
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info12 . profile_path , " profilePath " ) ;
2004-05-09 13:39:47 +04:00
break ;
case 13 :
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info13 . description , " description " ) ;
2004-05-09 13:39:47 +04:00
break ;
case 14 :
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info14 . workstations , " userWorkstations " ) ;
2004-05-09 13:39:47 +04:00
break ;
case 16 :
2007-07-27 06:07:17 +04:00
SET_AFLAGS ( msg , info16 . acct_flags , " userAccountControl " ) ;
2004-05-09 13:39:47 +04:00
break ;
2006-10-13 00:21:46 +04:00
case 17 :
2007-07-27 06:07:17 +04:00
SET_UINT64 ( msg , info17 . acct_expiry , " accountExpires " ) ;
2006-10-13 00:21:46 +04:00
break ;
2004-05-09 13:39:47 +04:00
case 20 :
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info20 . parameters , " userParameters " ) ;
2004-05-09 13:39:47 +04:00
break ;
case 21 :
2007-09-04 06:22:04 +04:00
# define IFSET(bit) if (bit & r->in.info->info21.fields_present)
IFSET ( SAMR_FIELD_ACCT_EXPIRY )
SET_UINT64 ( msg , info21 . acct_expiry , " accountExpires " ) ;
2005-03-13 09:43:34 +03:00
IFSET ( SAMR_FIELD_ACCOUNT_NAME )
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info21 . account_name , " samAccountName " ) ;
2006-10-13 00:21:46 +04:00
IFSET ( SAMR_FIELD_FULL_NAME )
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info21 . full_name , " displayName " ) ;
2006-10-13 00:21:46 +04:00
IFSET ( SAMR_FIELD_DESCRIPTION )
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info21 . description , " description " ) ;
2006-10-13 00:21:46 +04:00
IFSET ( SAMR_FIELD_COMMENT )
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info21 . comment , " comment " ) ;
2006-10-13 00:21:46 +04:00
IFSET ( SAMR_FIELD_LOGON_SCRIPT )
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info21 . logon_script , " scriptPath " ) ;
2006-10-13 00:21:46 +04:00
IFSET ( SAMR_FIELD_PROFILE_PATH )
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info21 . profile_path , " profilePath " ) ;
2006-10-13 00:21:46 +04:00
IFSET ( SAMR_FIELD_HOME_DIRECTORY )
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info21 . home_directory , " homeDirectory " ) ;
2006-10-13 00:21:46 +04:00
IFSET ( SAMR_FIELD_HOME_DRIVE )
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info21 . home_drive , " homeDrive " ) ;
2006-10-13 00:21:46 +04:00
IFSET ( SAMR_FIELD_WORKSTATIONS )
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info21 . workstations , " userWorkstations " ) ;
2006-10-13 00:21:46 +04:00
IFSET ( SAMR_FIELD_LOGON_HOURS )
2007-07-27 06:07:17 +04:00
SET_LHOURS ( msg , info21 . logon_hours , " logonHours " ) ;
2006-10-13 00:21:46 +04:00
IFSET ( SAMR_FIELD_ACCT_FLAGS )
2007-07-27 06:07:17 +04:00
SET_AFLAGS ( msg , info21 . acct_flags , " userAccountControl " ) ;
2006-10-13 00:21:46 +04:00
IFSET ( SAMR_FIELD_PARAMETERS )
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info21 . parameters , " userParameters " ) ;
2006-10-13 00:21:46 +04:00
IFSET ( SAMR_FIELD_COUNTRY_CODE )
2007-07-27 06:07:17 +04:00
SET_UINT ( msg , info21 . country_code , " countryCode " ) ;
2006-10-13 00:21:46 +04:00
IFSET ( SAMR_FIELD_CODE_PAGE )
2007-09-04 06:22:04 +04:00
SET_UINT ( msg , info21 . code_page , " codePage " ) ;
2004-05-26 08:20:17 +04:00
# undef IFSET
break ;
case 23 :
# define IFSET(bit) if (bit & r->in.info->info23.info.fields_present)
2007-09-04 06:22:04 +04:00
IFSET ( SAMR_FIELD_ACCT_EXPIRY )
SET_UINT64 ( msg , info23 . info . acct_expiry , " accountExpires " ) ;
2005-03-13 09:43:34 +03:00
IFSET ( SAMR_FIELD_ACCOUNT_NAME )
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info23 . info . account_name , " samAccountName " ) ;
2005-03-13 09:43:34 +03:00
IFSET ( SAMR_FIELD_FULL_NAME )
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info23 . info . full_name , " displayName " ) ;
2004-05-26 08:20:17 +04:00
IFSET ( SAMR_FIELD_DESCRIPTION )
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info23 . info . description , " description " ) ;
2004-05-26 08:20:17 +04:00
IFSET ( SAMR_FIELD_COMMENT )
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info23 . info . comment , " comment " ) ;
2004-05-26 08:20:17 +04:00
IFSET ( SAMR_FIELD_LOGON_SCRIPT )
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info23 . info . logon_script , " scriptPath " ) ;
2004-06-05 08:32:50 +04:00
IFSET ( SAMR_FIELD_PROFILE_PATH )
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info23 . info . profile_path , " profilePath " ) ;
2005-03-18 07:25:10 +03:00
IFSET ( SAMR_FIELD_WORKSTATIONS )
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info23 . info . workstations , " userWorkstations " ) ;
2004-05-26 08:20:17 +04:00
IFSET ( SAMR_FIELD_LOGON_HOURS )
2007-07-27 06:07:17 +04:00
SET_LHOURS ( msg , info23 . info . logon_hours , " logonHours " ) ;
2004-10-20 06:12:52 +04:00
IFSET ( SAMR_FIELD_ACCT_FLAGS )
2007-07-27 06:07:17 +04:00
SET_AFLAGS ( msg , info23 . info . acct_flags , " userAccountControl " ) ;
2004-11-13 16:45:41 +03:00
IFSET ( SAMR_FIELD_PARAMETERS )
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info23 . info . parameters , " userParameters " ) ;
2004-05-26 08:20:17 +04:00
IFSET ( SAMR_FIELD_COUNTRY_CODE )
2007-07-27 06:07:17 +04:00
SET_UINT ( msg , info23 . info . country_code , " countryCode " ) ;
2004-05-26 08:20:17 +04:00
IFSET ( SAMR_FIELD_CODE_PAGE )
2007-07-27 06:07:17 +04:00
SET_UINT ( msg , info23 . info . code_page , " codePage " ) ;
2004-05-26 08:20:17 +04:00
IFSET ( SAMR_FIELD_PASSWORD ) {
status = samr_set_password ( dce_call ,
a_state - > sam_ctx ,
a_state - > account_dn ,
a_state - > domain_state - > domain_dn ,
mem_ctx , msg ,
& r - > in . info - > info23 . password ) ;
2004-10-20 06:26:59 +04:00
} else IFSET ( SAMR_FIELD_PASSWORD2 ) {
status = samr_set_password ( dce_call ,
a_state - > sam_ctx ,
a_state - > account_dn ,
a_state - > domain_state - > domain_dn ,
mem_ctx , msg ,
& r - > in . info - > info23 . password ) ;
2004-05-26 08:20:17 +04:00
}
# undef IFSET
2004-05-08 18:42:45 +04:00
break ;
2004-05-10 15:23:50 +04:00
/* the set password levels are handled separately */
case 24 :
2004-05-25 17:57:39 +04:00
status = samr_set_password ( dce_call ,
a_state - > sam_ctx ,
2004-05-24 09:35:59 +04:00
a_state - > account_dn ,
a_state - > domain_state - > domain_dn ,
mem_ctx , msg ,
2004-05-10 15:23:50 +04:00
& r - > in . info - > info24 . password ) ;
break ;
2004-05-26 08:20:17 +04:00
case 25 :
# define IFSET(bit) if (bit & r->in.info->info25.info.fields_present)
2007-09-04 06:22:04 +04:00
IFSET ( SAMR_FIELD_ACCT_EXPIRY )
SET_UINT64 ( msg , info25 . info . acct_expiry , " accountExpires " ) ;
2005-03-13 09:43:34 +03:00
IFSET ( SAMR_FIELD_ACCOUNT_NAME )
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info25 . info . account_name , " samAccountName " ) ;
2005-03-13 09:43:34 +03:00
IFSET ( SAMR_FIELD_FULL_NAME )
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info25 . info . full_name , " displayName " ) ;
2004-05-26 08:20:17 +04:00
IFSET ( SAMR_FIELD_DESCRIPTION )
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info25 . info . description , " description " ) ;
2004-05-26 08:20:17 +04:00
IFSET ( SAMR_FIELD_COMMENT )
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info25 . info . comment , " comment " ) ;
2004-05-26 08:20:17 +04:00
IFSET ( SAMR_FIELD_LOGON_SCRIPT )
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info25 . info . logon_script , " scriptPath " ) ;
2004-06-05 08:32:50 +04:00
IFSET ( SAMR_FIELD_PROFILE_PATH )
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info25 . info . profile_path , " profilePath " ) ;
2005-03-18 07:25:10 +03:00
IFSET ( SAMR_FIELD_WORKSTATIONS )
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info25 . info . workstations , " userWorkstations " ) ;
2004-05-26 08:20:17 +04:00
IFSET ( SAMR_FIELD_LOGON_HOURS )
2007-07-27 06:07:17 +04:00
SET_LHOURS ( msg , info25 . info . logon_hours , " logonHours " ) ;
2004-10-20 06:12:52 +04:00
IFSET ( SAMR_FIELD_ACCT_FLAGS )
2007-07-27 06:07:17 +04:00
SET_AFLAGS ( msg , info25 . info . acct_flags , " userAccountControl " ) ;
2004-11-13 16:45:41 +03:00
IFSET ( SAMR_FIELD_PARAMETERS )
2007-07-27 06:07:17 +04:00
SET_STRING ( msg , info25 . info . parameters , " userParameters " ) ;
2004-05-26 08:20:17 +04:00
IFSET ( SAMR_FIELD_COUNTRY_CODE )
2007-07-27 06:07:17 +04:00
SET_UINT ( msg , info25 . info . country_code , " countryCode " ) ;
2004-05-26 08:20:17 +04:00
IFSET ( SAMR_FIELD_CODE_PAGE )
2007-07-27 06:07:17 +04:00
SET_UINT ( msg , info25 . info . code_page , " codePage " ) ;
2004-05-26 08:20:17 +04:00
IFSET ( SAMR_FIELD_PASSWORD ) {
status = samr_set_password_ex ( dce_call ,
a_state - > sam_ctx ,
a_state - > account_dn ,
a_state - > domain_state - > domain_dn ,
mem_ctx , msg ,
& r - > in . info - > info25 . password ) ;
2004-10-20 06:26:59 +04:00
} else IFSET ( SAMR_FIELD_PASSWORD2 ) {
status = samr_set_password_ex ( dce_call ,
a_state - > sam_ctx ,
a_state - > account_dn ,
a_state - > domain_state - > domain_dn ,
mem_ctx , msg ,
& r - > in . info - > info25 . password ) ;
2004-05-26 08:20:17 +04:00
}
# undef IFSET
break ;
/* the set password levels are handled separately */
case 26 :
status = samr_set_password_ex ( dce_call ,
a_state - > sam_ctx ,
a_state - > account_dn ,
a_state - > domain_state - > domain_dn ,
mem_ctx , msg ,
& r - > in . info - > info26 . password ) ;
break ;
2004-05-10 15:23:50 +04:00
2004-05-08 18:42:45 +04:00
default :
/* many info classes are not valid for SetUserInfo */
return NT_STATUS_INVALID_INFO_CLASS ;
}
2004-05-10 15:23:50 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2004-05-08 18:42:45 +04:00
/* modify the samdb record */
2007-07-27 06:07:17 +04:00
ret = ldb_modify ( a_state - > sam_ctx , msg ) ;
2004-05-08 18:42:45 +04:00
if ( ret ! = 0 ) {
2005-12-30 11:40:16 +03:00
DEBUG ( 1 , ( " Failed to modify record %s: %s \n " ,
2006-11-22 05:05:19 +03:00
ldb_dn_get_linearized ( a_state - > account_dn ) ,
2005-12-30 11:40:16 +03:00
ldb_errstring ( a_state - > sam_ctx ) ) ) ;
2004-05-08 18:42:45 +04:00
/* we really need samdb.c to return NTSTATUS */
return NT_STATUS_UNSUCCESSFUL ;
}
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
/*
samr_GetGroupsForUser
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_GetGroupsForUser ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_GetGroupsForUser * r )
{
2004-12-30 01:57:20 +03:00
struct dcesrv_handle * h ;
struct samr_account_state * a_state ;
struct samr_domain_state * d_state ;
struct ldb_message * * res ;
const char * const attrs [ 2 ] = { " objectSid " , NULL } ;
2005-06-29 17:55:09 +04:00
struct samr_RidWithAttributeArray * array ;
2004-12-30 01:57:20 +03:00
int count ;
DCESRV_PULL_HANDLE ( h , r - > in . user_handle , SAMR_HANDLE_USER ) ;
a_state = h - > data ;
d_state = a_state - > domain_state ;
2006-06-15 03:47:45 +04:00
count = samdb_search_domain ( a_state - > sam_ctx , mem_ctx , d_state - > domain_dn , & res ,
2005-06-24 04:18:20 +04:00
attrs , d_state - > domain_sid ,
2006-06-13 00:00:18 +04:00
" (&(member=%s)(grouptype=%d)(objectclass=group)) " ,
2006-11-22 05:05:19 +03:00
ldb_dn_get_linearized ( a_state - > account_dn ) ,
2006-06-13 00:00:18 +04:00
GTYPE_SECURITY_GLOBAL_GROUP ) ;
2004-12-30 01:57:20 +03:00
if ( count < 0 )
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
2005-06-29 17:55:09 +04:00
array = talloc ( mem_ctx , struct samr_RidWithAttributeArray ) ;
2004-12-30 01:57:20 +03:00
if ( array = = NULL )
return NT_STATUS_NO_MEMORY ;
array - > count = 0 ;
2005-05-01 12:05:17 +04:00
array - > rids = NULL ;
2004-12-30 01:57:20 +03:00
if ( count > 0 ) {
int i ;
2005-06-29 17:55:09 +04:00
array - > rids = talloc_array ( mem_ctx , struct samr_RidWithAttribute ,
2004-12-30 01:57:20 +03:00
count ) ;
2005-05-01 12:05:17 +04:00
if ( array - > rids = = NULL )
2004-12-30 01:57:20 +03:00
return NT_STATUS_NO_MEMORY ;
for ( i = 0 ; i < count ; i + + ) {
struct dom_sid * group_sid ;
group_sid = samdb_result_dom_sid ( mem_ctx , res [ i ] ,
" objectSid " ) ;
if ( group_sid = = NULL ) {
DEBUG ( 0 , ( " Couldn't find objectSid attrib \n " ) ) ;
continue ;
}
2005-05-01 12:05:17 +04:00
array - > rids [ array - > count ] . rid =
2004-12-30 01:57:20 +03:00
group_sid - > sub_auths [ group_sid - > num_auths - 1 ] ;
2005-06-29 17:55:09 +04:00
array - > rids [ array - > count ] . attributes = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED ;
2004-12-30 01:57:20 +03:00
array - > count + = 1 ;
}
}
r - > out . rids = array ;
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
/*
samr_QueryDisplayInfo
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_QueryDisplayInfo ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_QueryDisplayInfo * r )
{
2004-12-29 02:01:34 +03:00
struct dcesrv_handle * h ;
struct samr_domain_state * d_state ;
struct ldb_message * * res ;
int ldb_cnt , count , i ;
2007-07-26 07:50:24 +04:00
const char * const attrs [ ] = { " objectSid " , " sAMAccountName " , " displayName " ,
" description " , " userAccountControl " , NULL } ;
2004-12-29 02:01:34 +03:00
struct samr_DispEntryFull * entriesFull = NULL ;
2006-12-13 14:19:51 +03:00
struct samr_DispEntryFullGroup * entriesFullGroup = NULL ;
2004-12-29 02:01:34 +03:00
struct samr_DispEntryAscii * entriesAscii = NULL ;
struct samr_DispEntryGeneral * entriesGeneral = NULL ;
const char * filter ;
DCESRV_PULL_HANDLE ( h , r - > in . domain_handle , SAMR_HANDLE_DOMAIN ) ;
d_state = h - > data ;
switch ( r - > in . level ) {
case 1 :
case 4 :
filter = talloc_asprintf ( mem_ctx , " (&(objectclass=user) "
2006-06-13 00:00:18 +04:00
" (sAMAccountType=%u)) " ,
ATYPE_NORMAL_ACCOUNT ) ;
2004-12-29 02:01:34 +03:00
break ;
case 2 :
filter = talloc_asprintf ( mem_ctx , " (&(objectclass=user) "
2006-06-13 00:00:18 +04:00
" (sAMAccountType=%u)) " ,
ATYPE_WORKSTATION_TRUST ) ;
2004-12-29 02:01:34 +03:00
break ;
case 3 :
case 5 :
2006-06-13 00:00:18 +04:00
filter = talloc_asprintf ( mem_ctx , " (&(grouptype=%d) "
2004-12-29 02:01:34 +03:00
" (objectclass=group)) " ,
2006-06-13 00:00:18 +04:00
GTYPE_SECURITY_GLOBAL_GROUP ) ;
2004-12-29 02:01:34 +03:00
break ;
default :
return NT_STATUS_INVALID_INFO_CLASS ;
}
2004-12-30 20:01:49 +03:00
/* search for all requested objects in this domain. This could
possibly be cached and resumed based on resume_key */
ldb_cnt = samdb_search_domain ( d_state - > sam_ctx , mem_ctx ,
d_state - > domain_dn , & res , attrs ,
2005-06-24 04:18:20 +04:00
d_state - > domain_sid , " %s " , filter ) ;
2004-12-29 02:01:34 +03:00
if ( ldb_cnt = = - 1 ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
if ( ldb_cnt = = 0 | | r - > in . max_entries = = 0 ) {
return NT_STATUS_OK ;
}
switch ( r - > in . level ) {
case 1 :
2005-01-27 10:08:20 +03:00
entriesGeneral = talloc_array ( mem_ctx ,
2004-12-29 02:01:34 +03:00
struct samr_DispEntryGeneral ,
ldb_cnt ) ;
break ;
case 2 :
2005-01-27 10:08:20 +03:00
entriesFull = talloc_array ( mem_ctx ,
2004-12-29 02:01:34 +03:00
struct samr_DispEntryFull ,
ldb_cnt ) ;
break ;
2006-12-13 14:19:51 +03:00
case 3 :
entriesFullGroup = talloc_array ( mem_ctx ,
struct samr_DispEntryFullGroup ,
ldb_cnt ) ;
break ;
2004-12-29 02:01:34 +03:00
case 4 :
case 5 :
2005-01-27 10:08:20 +03:00
entriesAscii = talloc_array ( mem_ctx ,
2004-12-29 02:01:34 +03:00
struct samr_DispEntryAscii ,
ldb_cnt ) ;
break ;
}
if ( ( entriesGeneral = = NULL ) & & ( entriesFull = = NULL ) & &
2006-12-13 14:19:51 +03:00
( entriesAscii = = NULL ) & & ( entriesFullGroup = = NULL ) )
2004-12-29 02:01:34 +03:00
return NT_STATUS_NO_MEMORY ;
count = 0 ;
for ( i = 0 ; i < ldb_cnt ; i + + ) {
struct dom_sid * objectsid ;
objectsid = samdb_result_dom_sid ( mem_ctx , res [ i ] ,
" objectSid " ) ;
if ( objectsid = = NULL )
continue ;
switch ( r - > in . level ) {
case 1 :
2005-06-12 15:03:15 +04:00
entriesGeneral [ count ] . idx = count + 1 ;
2004-12-29 02:01:34 +03:00
entriesGeneral [ count ] . rid =
objectsid - > sub_auths [ objectsid - > num_auths - 1 ] ;
entriesGeneral [ count ] . acct_flags =
samdb_result_acct_flags ( res [ i ] ,
" userAccountControl " ) ;
entriesGeneral [ count ] . account_name . string =
samdb_result_string ( res [ i ] ,
" sAMAccountName " , " " ) ;
entriesGeneral [ count ] . full_name . string =
samdb_result_string ( res [ i ] , " displayName " , " " ) ;
entriesGeneral [ count ] . description . string =
samdb_result_string ( res [ i ] , " description " , " " ) ;
break ;
case 2 :
2005-06-12 15:03:15 +04:00
entriesFull [ count ] . idx = count + 1 ;
2004-12-29 02:01:34 +03:00
entriesFull [ count ] . rid =
objectsid - > sub_auths [ objectsid - > num_auths - 1 ] ;
2007-07-26 07:50:24 +04:00
/* No idea why we need to or in ACB_NORMAL here, but this is what Win2k3 seems to do... */
2004-12-29 02:01:34 +03:00
entriesFull [ count ] . acct_flags =
samdb_result_acct_flags ( res [ i ] ,
2007-07-26 07:50:24 +04:00
" userAccountControl " ) | ACB_NORMAL ;
2004-12-29 02:01:34 +03:00
entriesFull [ count ] . account_name . string =
samdb_result_string ( res [ i ] , " sAMAccountName " ,
" " ) ;
entriesFull [ count ] . description . string =
samdb_result_string ( res [ i ] , " description " , " " ) ;
break ;
2006-12-13 14:19:51 +03:00
case 3 :
entriesFullGroup [ count ] . idx = count + 1 ;
entriesFullGroup [ count ] . rid =
objectsid - > sub_auths [ objectsid - > num_auths - 1 ] ;
entriesFullGroup [ count ] . acct_flags =
samdb_result_acct_flags ( res [ i ] ,
" userAccountControl " ) ;
/* We get a "7" here for groups */
entriesFullGroup [ count ] . acct_flags
= SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | SE_GROUP_ENABLED ;
entriesFullGroup [ count ] . account_name . string =
samdb_result_string ( res [ i ] , " sAMAccountName " ,
" " ) ;
entriesFullGroup [ count ] . description . string =
samdb_result_string ( res [ i ] , " description " , " " ) ;
break ;
2004-12-29 02:01:34 +03:00
case 4 :
case 5 :
2005-06-12 15:03:15 +04:00
entriesAscii [ count ] . idx = count + 1 ;
2004-12-29 02:01:34 +03:00
entriesAscii [ count ] . account_name . string =
samdb_result_string ( res [ i ] , " sAMAccountName " ,
" " ) ;
break ;
}
count + = 1 ;
}
r - > out . total_size = count ;
if ( r - > in . start_idx > = count ) {
r - > out . returned_size = 0 ;
switch ( r - > in . level ) {
case 1 :
r - > out . info . info1 . count = r - > out . returned_size ;
r - > out . info . info1 . entries = NULL ;
break ;
case 2 :
r - > out . info . info2 . count = r - > out . returned_size ;
r - > out . info . info2 . entries = NULL ;
break ;
case 3 :
r - > out . info . info3 . count = r - > out . returned_size ;
r - > out . info . info3 . entries = NULL ;
break ;
case 4 :
r - > out . info . info4 . count = r - > out . returned_size ;
r - > out . info . info4 . entries = NULL ;
break ;
case 5 :
r - > out . info . info5 . count = r - > out . returned_size ;
r - > out . info . info5 . entries = NULL ;
break ;
}
} else {
r - > out . returned_size = MIN ( count - r - > in . start_idx ,
r - > in . max_entries ) ;
switch ( r - > in . level ) {
case 1 :
r - > out . info . info1 . count = r - > out . returned_size ;
r - > out . info . info1 . entries =
& ( entriesGeneral [ r - > in . start_idx ] ) ;
break ;
case 2 :
r - > out . info . info2 . count = r - > out . returned_size ;
r - > out . info . info2 . entries =
& ( entriesFull [ r - > in . start_idx ] ) ;
break ;
case 3 :
r - > out . info . info3 . count = r - > out . returned_size ;
r - > out . info . info3 . entries =
2006-12-13 14:19:51 +03:00
& ( entriesFullGroup [ r - > in . start_idx ] ) ;
2004-12-29 02:01:34 +03:00
break ;
case 4 :
r - > out . info . info4 . count = r - > out . returned_size ;
r - > out . info . info4 . entries =
& ( entriesAscii [ r - > in . start_idx ] ) ;
break ;
case 5 :
r - > out . info . info5 . count = r - > out . returned_size ;
r - > out . info . info5 . entries =
& ( entriesAscii [ r - > in . start_idx ] ) ;
break ;
}
}
return ( r - > out . returned_size < ( count - r - > in . start_idx ) ) ?
STATUS_MORE_ENTRIES : NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
/*
samr_GetDisplayEnumerationIndex
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_GetDisplayEnumerationIndex ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_GetDisplayEnumerationIndex * r )
{
2004-05-04 10:07:52 +04:00
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
2004-05-03 18:58:08 +04:00
}
/*
samr_TestPrivateFunctionsDomain
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_TestPrivateFunctionsDomain ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_TestPrivateFunctionsDomain * r )
{
2006-07-04 06:46:24 +04:00
return NT_STATUS_NOT_IMPLEMENTED ;
2004-05-03 18:58:08 +04:00
}
/*
samr_TestPrivateFunctionsUser
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_TestPrivateFunctionsUser ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_TestPrivateFunctionsUser * r )
{
2006-07-03 08:00:10 +04:00
return NT_STATUS_NOT_IMPLEMENTED ;
2004-05-03 18:58:08 +04:00
}
/*
samr_GetUserPwInfo
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_GetUserPwInfo ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-09 16:32:25 +04:00
struct samr_GetUserPwInfo * r )
2004-05-03 18:58:08 +04:00
{
2004-05-09 16:32:25 +04:00
struct dcesrv_handle * h ;
2004-05-10 16:37:06 +04:00
struct samr_account_state * a_state ;
2004-05-09 16:32:25 +04:00
ZERO_STRUCT ( r - > out . info ) ;
2004-09-21 07:51:38 +04:00
DCESRV_PULL_HANDLE ( h , r - > in . user_handle , SAMR_HANDLE_USER ) ;
2004-05-09 16:32:25 +04:00
2004-05-10 16:37:06 +04:00
a_state = h - > data ;
2004-05-09 16:32:25 +04:00
2005-06-14 23:15:17 +04:00
r - > out . info . min_password_length = samdb_search_uint ( a_state - > sam_ctx , mem_ctx , 0 ,
2005-07-17 13:20:52 +04:00
a_state - > domain_state - > domain_dn , " minPwdLength " ,
2005-10-11 15:00:16 +04:00
NULL ) ;
2005-06-14 23:15:17 +04:00
r - > out . info . password_properties = samdb_search_uint ( a_state - > sam_ctx , mem_ctx , 0 ,
2005-07-17 13:20:52 +04:00
a_state - > account_dn ,
2005-10-11 15:00:16 +04:00
" pwdProperties " , NULL ) ;
2004-05-09 16:32:25 +04:00
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
/*
samr_RemoveMemberFromForeignDomain
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_RemoveMemberFromForeignDomain ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_RemoveMemberFromForeignDomain * r )
{
2004-12-30 21:50:15 +03:00
struct dcesrv_handle * h ;
struct samr_domain_state * d_state ;
2005-06-24 04:18:20 +04:00
const char * memberdn ;
2004-12-30 21:50:15 +03:00
struct ldb_message * * res ;
2005-10-11 15:00:16 +04:00
const char * const attrs [ 3 ] = { " distinguishedName " , " objectSid " , NULL } ;
2004-12-30 21:50:15 +03:00
int i , count ;
DCESRV_PULL_HANDLE ( h , r - > in . domain_handle , SAMR_HANDLE_DOMAIN ) ;
d_state = h - > data ;
memberdn = samdb_search_string ( d_state - > sam_ctx , mem_ctx , NULL ,
2005-10-11 15:00:16 +04:00
" distinguishedName " , " (objectSid=%s) " ,
2005-06-24 04:18:20 +04:00
ldap_encode_ndr_dom_sid ( mem_ctx , r - > in . sid ) ) ;
2006-07-04 06:46:24 +04:00
/* Nothing to do */
if ( memberdn = = NULL ) {
return NT_STATUS_OK ;
}
2004-12-30 21:50:15 +03:00
/* TODO: Does this call only remove alias members, or does it do this
* for domain groups as well ? */
count = samdb_search_domain ( d_state - > sam_ctx , mem_ctx ,
d_state - > domain_dn , & res , attrs ,
2005-06-24 04:18:20 +04:00
d_state - > domain_sid ,
2004-12-30 21:50:15 +03:00
" (&(member=%s)(objectClass=group) "
2006-06-13 00:00:18 +04:00
" (|(groupType=%d)(groupType=%d))) " ,
2004-12-30 21:50:15 +03:00
memberdn ,
2006-06-13 00:00:18 +04:00
GTYPE_SECURITY_BUILTIN_LOCAL_GROUP ,
GTYPE_SECURITY_DOMAIN_LOCAL_GROUP ) ;
2004-12-30 21:50:15 +03:00
if ( count < 0 )
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
for ( i = 0 ; i < count ; i + + ) {
2005-01-02 10:51:13 +03:00
struct ldb_message * mod ;
2004-12-30 21:50:15 +03:00
2005-01-02 10:51:13 +03:00
mod = ldb_msg_new ( mem_ctx ) ;
if ( mod = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2006-11-22 03:59:34 +03:00
mod - > dn = samdb_result_dn ( d_state - > sam_ctx , mod , res [ i ] , " distinguishedName " , NULL ) ;
2005-01-02 10:51:13 +03:00
if ( mod - > dn = = NULL ) {
talloc_free ( mod ) ;
2004-12-30 21:50:15 +03:00
continue ;
2005-01-02 10:51:13 +03:00
}
2004-12-30 21:50:15 +03:00
2005-01-02 10:51:13 +03:00
if ( samdb_msg_add_delval ( d_state - > sam_ctx , mem_ctx , mod ,
2004-12-30 21:50:15 +03:00
" member " , memberdn ) ! = 0 )
return NT_STATUS_NO_MEMORY ;
2007-07-27 06:07:17 +04:00
if ( ldb_modify ( d_state - > sam_ctx , mod ) ! = 0 )
2004-12-30 21:50:15 +03:00
return NT_STATUS_UNSUCCESSFUL ;
2005-01-02 10:51:13 +03:00
talloc_free ( mod ) ;
2004-12-30 21:50:15 +03:00
}
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
/*
samr_QueryDomainInfo2
2006-07-04 06:46:24 +04:00
just an alias for samr_QueryDomainInfo
2004-05-03 18:58:08 +04:00
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_QueryDomainInfo2 ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_QueryDomainInfo2 * r )
{
2006-07-04 06:46:24 +04:00
struct samr_QueryDomainInfo r1 ;
NTSTATUS status ;
ZERO_STRUCT ( r1 . out ) ;
r1 . in . domain_handle = r - > in . domain_handle ;
r1 . in . level = r - > in . level ;
2007-01-17 17:49:36 +03:00
status = dcesrv_samr_QueryDomainInfo ( dce_call , mem_ctx , & r1 ) ;
2006-07-04 06:46:24 +04:00
r - > out . info = r1 . out . info ;
return status ;
2004-05-03 18:58:08 +04:00
}
/*
samr_QueryUserInfo2
2004-05-09 13:39:47 +04:00
just an alias for samr_QueryUserInfo
2004-05-03 18:58:08 +04:00
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_QueryUserInfo2 ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-09 13:39:47 +04:00
struct samr_QueryUserInfo2 * r )
2004-05-03 18:58:08 +04:00
{
2004-05-09 13:39:47 +04:00
struct samr_QueryUserInfo r1 ;
NTSTATUS status ;
2005-01-03 02:31:12 +03:00
ZERO_STRUCT ( r1 . out ) ;
2004-09-21 07:51:38 +04:00
r1 . in . user_handle = r - > in . user_handle ;
2004-05-09 13:39:47 +04:00
r1 . in . level = r - > in . level ;
2007-01-17 17:49:36 +03:00
status = dcesrv_samr_QueryUserInfo ( dce_call , mem_ctx , & r1 ) ;
2004-05-09 13:39:47 +04:00
r - > out . info = r1 . out . info ;
return status ;
2004-05-03 18:58:08 +04:00
}
/*
samr_QueryDisplayInfo2
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_QueryDisplayInfo2 ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2005-01-03 02:31:12 +03:00
struct samr_QueryDisplayInfo2 * r )
2004-05-03 18:58:08 +04:00
{
2004-12-30 20:01:49 +03:00
struct samr_QueryDisplayInfo q ;
NTSTATUS result ;
q . in . domain_handle = r - > in . domain_handle ;
q . in . level = r - > in . level ;
q . in . start_idx = r - > in . start_idx ;
q . in . max_entries = r - > in . max_entries ;
q . in . buf_size = r - > in . buf_size ;
2005-01-03 02:31:12 +03:00
ZERO_STRUCT ( q . out ) ;
2004-12-30 20:01:49 +03:00
2007-01-17 17:49:36 +03:00
result = dcesrv_samr_QueryDisplayInfo ( dce_call , mem_ctx , & q ) ;
2004-12-30 20:01:49 +03:00
r - > out . total_size = q . out . total_size ;
r - > out . returned_size = q . out . returned_size ;
r - > out . info = q . out . info ;
return result ;
2004-05-03 18:58:08 +04:00
}
/*
samr_GetDisplayEnumerationIndex2
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_GetDisplayEnumerationIndex2 ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_GetDisplayEnumerationIndex2 * r )
{
2004-05-04 10:07:52 +04:00
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
2004-05-03 18:58:08 +04:00
}
/*
samr_QueryDisplayInfo3
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_QueryDisplayInfo3 ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_QueryDisplayInfo3 * r )
{
2006-07-04 06:46:24 +04:00
struct samr_QueryDisplayInfo q ;
NTSTATUS result ;
q . in . domain_handle = r - > in . domain_handle ;
q . in . level = r - > in . level ;
q . in . start_idx = r - > in . start_idx ;
q . in . max_entries = r - > in . max_entries ;
q . in . buf_size = r - > in . buf_size ;
ZERO_STRUCT ( q . out ) ;
2007-01-17 17:49:36 +03:00
result = dcesrv_samr_QueryDisplayInfo ( dce_call , mem_ctx , & q ) ;
2006-07-04 06:46:24 +04:00
r - > out . total_size = q . out . total_size ;
r - > out . returned_size = q . out . returned_size ;
r - > out . info = q . out . info ;
return result ;
2004-05-03 18:58:08 +04:00
}
/*
samr_AddMultipleMembersToAlias
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_AddMultipleMembersToAlias ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_AddMultipleMembersToAlias * r )
{
2004-05-04 10:07:52 +04:00
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
2004-05-03 18:58:08 +04:00
}
/*
samr_RemoveMultipleMembersFromAlias
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_RemoveMultipleMembersFromAlias ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_RemoveMultipleMembersFromAlias * r )
{
2004-05-04 10:07:52 +04:00
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
2004-05-03 18:58:08 +04:00
}
/*
samr_GetDomPwInfo
2004-05-04 11:53:06 +04:00
this fetches the default password properties for a domain
2004-05-26 11:32:30 +04:00
note that w2k3 completely ignores the domain name in this call , and
always returns the information for the servers primary domain
2004-05-03 18:58:08 +04:00
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_GetDomPwInfo ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-04 11:53:06 +04:00
struct samr_GetDomPwInfo * r )
2004-05-03 18:58:08 +04:00
{
2004-05-04 11:53:06 +04:00
struct ldb_message * * msgs ;
int ret ;
2004-05-08 04:02:31 +04:00
const char * const attrs [ ] = { " minPwdLength " , " pwdProperties " , NULL } ;
2005-07-27 04:23:09 +04:00
struct ldb_context * sam_ctx ;
2004-05-04 11:53:06 +04:00
2004-06-05 00:36:44 +04:00
ZERO_STRUCT ( r - > out . info ) ;
2005-10-07 15:31:45 +04:00
sam_ctx = samdb_connect ( mem_ctx , dce_call - > conn - > auth_state . session_info ) ;
2004-05-06 16:42:42 +04:00
if ( sam_ctx = = NULL ) {
return NT_STATUS_INVALID_SYSTEM_SERVICE ;
}
2005-09-02 03:26:50 +04:00
/* The domain name in this call is ignored */
ret = gendb_search_dn ( sam_ctx ,
2006-08-25 11:08:06 +04:00
mem_ctx , NULL , & msgs , attrs ) ;
2004-05-04 11:53:06 +04:00
if ( ret < = 0 ) {
return NT_STATUS_NO_SUCH_DOMAIN ;
}
if ( ret > 1 ) {
2005-04-25 16:46:18 +04:00
talloc_free ( msgs ) ;
2004-05-04 11:53:06 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2004-11-17 14:56:13 +03:00
r - > out . info . min_password_length = samdb_result_uint ( msgs [ 0 ] , " minPwdLength " , 0 ) ;
2004-05-04 11:53:06 +04:00
r - > out . info . password_properties = samdb_result_uint ( msgs [ 0 ] , " pwdProperties " , 1 ) ;
2005-04-25 16:46:18 +04:00
talloc_free ( msgs ) ;
2004-05-04 11:53:06 +04:00
2004-08-25 10:44:23 +04:00
talloc_free ( sam_ctx ) ;
2004-05-04 11:53:06 +04:00
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
/*
samr_Connect2
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_Connect2 ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_Connect2 * r )
{
struct samr_Connect c ;
c . in . system_name = NULL ;
c . in . access_mask = r - > in . access_mask ;
2004-09-21 07:51:38 +04:00
c . out . connect_handle = r - > out . connect_handle ;
2004-05-03 18:58:08 +04:00
2007-01-17 17:49:36 +03:00
return dcesrv_samr_Connect ( dce_call , mem_ctx , & c ) ;
2004-05-03 18:58:08 +04:00
}
/*
samr_SetUserInfo2
2004-05-08 18:42:45 +04:00
just an alias for samr_SetUserInfo
2004-05-03 18:58:08 +04:00
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_SetUserInfo2 ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-08 18:42:45 +04:00
struct samr_SetUserInfo2 * r )
2004-05-03 18:58:08 +04:00
{
2004-05-08 18:42:45 +04:00
struct samr_SetUserInfo r2 ;
2004-09-21 07:51:38 +04:00
r2 . in . user_handle = r - > in . user_handle ;
2004-05-08 18:42:45 +04:00
r2 . in . level = r - > in . level ;
r2 . in . info = r - > in . info ;
2007-01-17 17:49:36 +03:00
return dcesrv_samr_SetUserInfo ( dce_call , mem_ctx , & r2 ) ;
2004-05-03 18:58:08 +04:00
}
/*
samr_SetBootKeyInformation
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_SetBootKeyInformation ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_SetBootKeyInformation * r )
{
2004-05-04 10:07:52 +04:00
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
2004-05-03 18:58:08 +04:00
}
/*
samr_GetBootKeyInformation
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_GetBootKeyInformation ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_GetBootKeyInformation * r )
{
2004-05-04 10:07:52 +04:00
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
2004-05-03 18:58:08 +04:00
}
/*
samr_Connect3
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_Connect3 ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_Connect3 * r )
{
struct samr_Connect c ;
c . in . system_name = NULL ;
c . in . access_mask = r - > in . access_mask ;
2004-09-21 07:51:38 +04:00
c . out . connect_handle = r - > out . connect_handle ;
2004-05-03 18:58:08 +04:00
2007-01-17 17:49:36 +03:00
return dcesrv_samr_Connect ( dce_call , mem_ctx , & c ) ;
2004-05-03 18:58:08 +04:00
}
/*
samr_Connect4
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_Connect4 ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_Connect4 * r )
{
struct samr_Connect c ;
c . in . system_name = NULL ;
c . in . access_mask = r - > in . access_mask ;
2004-09-21 07:51:38 +04:00
c . out . connect_handle = r - > out . connect_handle ;
2004-05-03 18:58:08 +04:00
2007-01-17 17:49:36 +03:00
return dcesrv_samr_Connect ( dce_call , mem_ctx , & c ) ;
2004-05-03 18:58:08 +04:00
}
/*
samr_Connect5
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_Connect5 ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_Connect5 * r )
{
struct samr_Connect c ;
NTSTATUS status ;
c . in . system_name = NULL ;
c . in . access_mask = r - > in . access_mask ;
2004-09-21 07:51:38 +04:00
c . out . connect_handle = r - > out . connect_handle ;
2004-05-03 18:58:08 +04:00
2007-01-17 17:49:36 +03:00
status = dcesrv_samr_Connect ( dce_call , mem_ctx , & c ) ;
2004-05-03 18:58:08 +04:00
r - > out . info - > info1 . unknown1 = 3 ;
r - > out . info - > info1 . unknown2 = 0 ;
r - > out . level = r - > in . level ;
return status ;
}
/*
samr_RidToSid
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_RidToSid ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2005-12-27 02:14:56 +03:00
struct samr_RidToSid * r )
2004-05-03 18:58:08 +04:00
{
2005-12-27 02:14:56 +03:00
struct samr_domain_state * d_state ;
struct dcesrv_handle * h ;
DCESRV_PULL_HANDLE ( h , r - > in . domain_handle , SAMR_HANDLE_DOMAIN ) ;
d_state = h - > data ;
/* form the users SID */
r - > out . sid = dom_sid_add_rid ( mem_ctx , d_state - > domain_sid , r - > in . rid ) ;
if ( ! r - > out . sid ) {
return NT_STATUS_NO_MEMORY ;
}
return NT_STATUS_OK ;
2004-05-03 18:58:08 +04:00
}
/*
samr_SetDsrmPassword
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_SetDsrmPassword ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-03 18:58:08 +04:00
struct samr_SetDsrmPassword * r )
{
2004-05-04 10:07:52 +04:00
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
2004-05-03 18:58:08 +04:00
}
/*
samr_ValidatePassword
*/
2007-01-17 17:49:36 +03:00
static NTSTATUS dcesrv_samr_ValidatePassword ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-24 09:35:59 +04:00
struct samr_ValidatePassword * r )
2004-05-03 18:58:08 +04:00
{
2004-05-04 10:07:52 +04:00
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
2004-05-03 18:58:08 +04:00
}
/* include the generated boilerplate */
# include "librpc/gen_ndr/ndr_samr_s.c"