2004-05-15 11:51:38 +04:00
/*
Unix SMB / CIFS implementation .
endpoint server for the netlogon pipe
Copyright ( C ) Andrew Bartlett < abartlet @ samba . org > 2004
2005-01-09 15:55:25 +03:00
Copyright ( C ) Stefan Metzmacher < metze @ samba . org > 2005
2004-05-15 11:51:38 +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
the Free Software Foundation ; either version 2 of the License , or
( at your option ) any later version .
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
*/
# include "includes.h"
2004-11-01 13:30:34 +03:00
# include "librpc/gen_ndr/ndr_netlogon.h"
2004-11-02 10:42:47 +03:00
# include "rpc_server/dcerpc_server.h"
2004-05-15 11:51:38 +04:00
# include "rpc_server/common/common.h"
2004-11-02 05:57:18 +03:00
# include "librpc/gen_ndr/ndr_dcom.h"
# include "auth/auth.h"
2004-11-16 12:00:52 +03:00
# include "lib/ldb/include/ldb.h"
2004-05-15 11:51:38 +04:00
struct server_pipe_state {
struct netr_Credential client_challenge ;
struct netr_Credential server_challenge ;
struct creds_CredentialState * creds ;
} ;
2004-06-14 12:12:50 +04:00
/*
a client has connected to the netlogon server using schannel , so we need
to re - establish the credentials state
*/
static NTSTATUS netlogon_schannel_setup ( struct dcesrv_call_state * dce_call )
{
struct server_pipe_state * state ;
NTSTATUS status ;
2005-03-06 09:37:38 +03:00
/* We want the client and server challenge zero */
state = talloc_zero ( dce_call - > conn , struct server_pipe_state ) ;
2004-06-14 12:12:50 +04:00
if ( state = = NULL ) {
2004-08-23 09:51:38 +04:00
return NT_STATUS_NO_MEMORY ;
2004-06-14 12:12:50 +04:00
}
r1294: A nice, large, commit...
This implements gensec for Samba's server side, and brings gensec up
to the standards of a full subsystem.
This means that use of the subsystem is by gensec_* functions, not
function pointers in structures (this is internal). This causes
changes in all the existing gensec users.
Our RPC server no longer contains it's own generalised security
scheme, and now calls gensec directly.
Gensec has also taken over the role of auth/auth_ntlmssp.c
An important part of gensec, is the output of the 'session_info'
struct. This is now reference counted, so that we can correctly free
it when a pipe is closed, no matter if it was inherited, or created by
per-pipe authentication.
The schannel code is reworked, to be in the same file for client and
server.
ntlm_auth is reworked to use gensec.
The major problem with this code is the way it relies on subsystem
auto-initialisation. The primary reason for this commit now.is to
allow these problems to be looked at, and fixed.
There are problems with the new code:
- I've tested it with smbtorture, but currently don't have VMware and
valgrind working (this I'll fix soon).
- The SPNEGO code is client-only at this point.
- We still do not do kerberos.
Andrew Bartlett
(This used to be commit 07fd885fd488fd1051eacc905a2d4962f8a018ec)
2004-06-29 13:40:10 +04:00
status = dcerpc_schannel_creds ( dce_call - > conn - > auth_state . gensec_security ,
2004-09-25 17:28:38 +04:00
state ,
r1294: A nice, large, commit...
This implements gensec for Samba's server side, and brings gensec up
to the standards of a full subsystem.
This means that use of the subsystem is by gensec_* functions, not
function pointers in structures (this is internal). This causes
changes in all the existing gensec users.
Our RPC server no longer contains it's own generalised security
scheme, and now calls gensec directly.
Gensec has also taken over the role of auth/auth_ntlmssp.c
An important part of gensec, is the output of the 'session_info'
struct. This is now reference counted, so that we can correctly free
it when a pipe is closed, no matter if it was inherited, or created by
per-pipe authentication.
The schannel code is reworked, to be in the same file for client and
server.
ntlm_auth is reworked to use gensec.
The major problem with this code is the way it relies on subsystem
auto-initialisation. The primary reason for this commit now.is to
allow these problems to be looked at, and fixed.
There are problems with the new code:
- I've tested it with smbtorture, but currently don't have VMware and
valgrind working (this I'll fix soon).
- The SPNEGO code is client-only at this point.
- We still do not do kerberos.
Andrew Bartlett
(This used to be commit 07fd885fd488fd1051eacc905a2d4962f8a018ec)
2004-06-29 13:40:10 +04:00
& state - > creds ) ;
2004-06-14 12:12:50 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-08-23 09:51:38 +04:00
DEBUG ( 3 , ( " getting schannel credentials failed with %s \n " , nt_errstr ( status ) ) ) ;
2004-09-25 17:28:38 +04:00
talloc_free ( state ) ;
2004-06-14 12:12:50 +04:00
return status ;
}
2005-01-10 15:15:26 +03:00
dce_call - > context - > private = state ;
2004-06-14 12:12:50 +04:00
return NT_STATUS_OK ;
}
/*
a hook for bind on the netlogon pipe
*/
2004-05-15 11:51:38 +04:00
static NTSTATUS netlogon_bind ( struct dcesrv_call_state * dce_call , const struct dcesrv_interface * di )
{
2005-01-10 15:15:26 +03:00
dce_call - > context - > private = NULL ;
2004-05-15 11:51:38 +04:00
2004-06-14 12:12:50 +04:00
/* if this is a schannel bind then we need to reconstruct the pipe state */
if ( dce_call - > conn - > auth_state . auth_info & &
dce_call - > conn - > auth_state . auth_info - > auth_type = = DCERPC_AUTH_TYPE_SCHANNEL ) {
NTSTATUS status ;
2004-08-23 09:51:38 +04:00
DEBUG ( 5 , ( " schannel bind on netlogon \n " ) ) ;
2004-06-14 12:12:50 +04:00
status = netlogon_schannel_setup ( dce_call ) ;
if ( ! NT_STATUS_IS_OK ( status ) ) {
2004-08-23 09:51:38 +04:00
DEBUG ( 3 , ( " schannel bind on netlogon failed with %s \n " , nt_errstr ( status ) ) ) ;
2004-06-14 12:12:50 +04:00
return status ;
}
}
2004-05-15 11:51:38 +04:00
return NT_STATUS_OK ;
}
# define DCESRV_INTERFACE_NETLOGON_BIND netlogon_bind
static NTSTATUS netr_ServerReqChallenge ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_ServerReqChallenge * r )
{
2005-01-10 15:15:26 +03:00
struct server_pipe_state * pipe_state = dce_call - > context - > private ;
2004-05-15 11:51:38 +04:00
2004-05-30 17:15:15 +04:00
ZERO_STRUCTP ( r - > out . credentials ) ;
2004-05-15 11:51:38 +04:00
/* destroyed on pipe shutdown */
if ( pipe_state ) {
2004-09-25 17:28:38 +04:00
talloc_free ( pipe_state ) ;
2005-01-10 15:15:26 +03:00
dce_call - > context - > private = NULL ;
2004-05-15 11:51:38 +04:00
}
2005-01-27 10:08:20 +03:00
pipe_state = talloc ( dce_call - > context , struct server_pipe_state ) ;
2004-05-15 11:51:38 +04:00
if ( ! pipe_state ) {
return NT_STATUS_NO_MEMORY ;
}
pipe_state - > creds = NULL ;
2004-05-30 17:15:15 +04:00
pipe_state - > client_challenge = * r - > in . credentials ;
2004-05-15 11:51:38 +04:00
generate_random_buffer ( pipe_state - > server_challenge . data ,
2004-07-14 16:14:07 +04:00
sizeof ( pipe_state - > server_challenge . data ) ) ;
2004-05-15 11:51:38 +04:00
2004-05-30 17:15:15 +04:00
* r - > out . credentials = pipe_state - > server_challenge ;
2004-05-15 11:51:38 +04:00
2005-01-10 15:15:26 +03:00
dce_call - > context - > private = pipe_state ;
2004-05-15 11:51:38 +04:00
return NT_STATUS_OK ;
}
2004-05-30 17:15:15 +04:00
static NTSTATUS netr_ServerAuthenticate3 ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_ServerAuthenticate3 * r )
2004-05-15 11:51:38 +04:00
{
2005-01-10 15:15:26 +03:00
struct server_pipe_state * pipe_state = dce_call - > context - > private ;
2004-05-15 11:51:38 +04:00
void * sam_ctx ;
2004-06-05 07:22:10 +04:00
struct samr_Password * mach_pwd ;
2004-05-25 21:24:24 +04:00
uint16_t acct_flags ;
2004-05-15 11:51:38 +04:00
int num_records ;
struct ldb_message * * msgs ;
NTSTATUS nt_status ;
2004-05-30 17:15:15 +04:00
const char * attrs [ ] = { " unicodePwd " , " lmPwdHash " , " ntPwdHash " , " userAccountControl " ,
" objectSid " , NULL } ;
2004-05-15 11:51:38 +04:00
2004-05-30 17:15:15 +04:00
ZERO_STRUCTP ( r - > out . credentials ) ;
* r - > out . rid = 0 ;
2004-06-04 03:15:16 +04:00
* r - > out . negotiate_flags = * r - > in . negotiate_flags ;
2004-05-15 11:51:38 +04:00
if ( ! pipe_state ) {
2004-06-05 07:37:27 +04:00
DEBUG ( 1 , ( " No challenge requested by client, cannot authenticate \n " ) ) ;
2004-05-15 11:51:38 +04:00
return NT_STATUS_ACCESS_DENIED ;
}
2004-08-25 10:44:23 +04:00
sam_ctx = samdb_connect ( mem_ctx ) ;
2004-05-15 11:51:38 +04:00
if ( sam_ctx = = NULL ) {
return NT_STATUS_INVALID_SYSTEM_SERVICE ;
}
/* pull the user attributes */
2005-03-23 04:30:43 +03:00
num_records = gendb_search ( sam_ctx , mem_ctx , NULL , & msgs , attrs ,
2004-05-15 11:51:38 +04:00
" (&(sAMAccountName=%s)(objectclass=user)) " ,
2004-06-05 07:22:10 +04:00
r - > in . account_name ) ;
2004-05-15 11:51:38 +04:00
if ( num_records = = 0 ) {
2004-05-17 01:30:48 +04:00
DEBUG ( 3 , ( " Couldn't find user [%s] in samdb. \n " ,
2004-06-05 07:22:10 +04:00
r - > in . account_name ) ) ;
2004-05-15 11:51:38 +04:00
return NT_STATUS_NO_SUCH_USER ;
}
if ( num_records > 1 ) {
2004-07-05 11:24:14 +04:00
DEBUG ( 0 , ( " Found %d records matching user [%s] \n " , num_records , r - > in . account_name ) ) ;
2004-05-15 11:51:38 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
acct_flags = samdb_result_acct_flags ( msgs [ 0 ] ,
" userAccountControl " ) ;
if ( acct_flags & ACB_DISABLED ) {
2004-06-05 07:22:10 +04:00
DEBUG ( 1 , ( " Account [%s] is disabled \n " , r - > in . account_name ) ) ;
2004-05-15 11:51:38 +04:00
return NT_STATUS_ACCESS_DENIED ;
}
2004-05-30 17:15:15 +04:00
if ( r - > in . secure_channel_type = = SEC_CHAN_WKSTA ) {
2004-05-15 11:51:38 +04:00
if ( ! ( acct_flags & ACB_WSTRUST ) ) {
DEBUG ( 1 , ( " Client asked for a workstation secure channel, but is not a workstation (member server) acb flags: 0x%x \n " , acct_flags ) ) ;
return NT_STATUS_ACCESS_DENIED ;
}
2004-05-30 17:15:15 +04:00
} else if ( r - > in . secure_channel_type = = SEC_CHAN_DOMAIN ) {
2004-05-15 11:51:38 +04:00
if ( ! ( acct_flags & ACB_DOMTRUST ) ) {
DEBUG ( 1 , ( " Client asked for a trusted domain secure channel, but is not a trusted domain: acb flags: 0x%x \n " , acct_flags ) ) ;
return NT_STATUS_ACCESS_DENIED ;
}
2004-05-30 17:15:15 +04:00
} else if ( r - > in . secure_channel_type = = SEC_CHAN_BDC ) {
2004-05-15 11:51:38 +04:00
if ( ! ( acct_flags & ACB_SVRTRUST ) ) {
DEBUG ( 1 , ( " Client asked for a server secure channel, but is not a server (domain controller): acb flags: 0x%x \n " , acct_flags ) ) ;
return NT_STATUS_ACCESS_DENIED ;
}
} else {
2004-05-30 17:15:15 +04:00
DEBUG ( 1 , ( " Client asked for an invalid secure channel type: %d \n " ,
r - > in . secure_channel_type ) ) ;
2004-05-15 11:51:38 +04:00
return NT_STATUS_ACCESS_DENIED ;
}
2004-05-30 17:15:15 +04:00
* r - > out . rid = samdb_result_rid_from_sid ( mem_ctx , msgs [ 0 ] , " objectSid " , 0 ) ;
2004-05-15 11:51:38 +04:00
2004-05-30 17:15:15 +04:00
nt_status = samdb_result_passwords ( mem_ctx , msgs [ 0 ] , NULL , & mach_pwd ) ;
2004-06-05 08:51:24 +04:00
if ( ! NT_STATUS_IS_OK ( nt_status ) | | mach_pwd = = NULL ) {
2004-05-15 11:51:38 +04:00
return NT_STATUS_ACCESS_DENIED ;
}
2005-01-10 15:30:13 +03:00
if ( pipe_state - > creds ) {
talloc_free ( pipe_state - > creds ) ;
}
2005-01-27 10:08:20 +03:00
pipe_state - > creds = talloc ( pipe_state , struct creds_CredentialState ) ;
2004-05-15 11:51:38 +04:00
if ( ! pipe_state - > creds ) {
2005-01-10 15:30:13 +03:00
return NT_STATUS_NO_MEMORY ;
2004-05-15 11:51:38 +04:00
}
creds_server_init ( pipe_state - > creds , & pipe_state - > client_challenge ,
& pipe_state - > server_challenge , mach_pwd ,
2004-06-04 03:15:16 +04:00
r - > out . credentials ,
* r - > in . negotiate_flags ) ;
2004-05-30 17:15:15 +04:00
if ( ! creds_server_check ( pipe_state - > creds , r - > in . credentials ) ) {
2005-01-10 15:30:13 +03:00
talloc_free ( pipe_state - > creds ) ;
pipe_state - > creds = NULL ;
2004-05-15 11:51:38 +04:00
return NT_STATUS_ACCESS_DENIED ;
}
2005-01-10 15:30:13 +03:00
pipe_state - > creds - > account_name = talloc_reference ( pipe_state - > creds , r - > in . account_name ) ;
2004-05-15 11:51:38 +04:00
2005-01-10 15:30:13 +03:00
pipe_state - > creds - > computer_name = talloc_reference ( pipe_state - > creds , r - > in . computer_name ) ;
2004-05-15 11:51:38 +04:00
2005-01-10 15:30:13 +03:00
pipe_state - > creds - > secure_channel_type = r - > in . secure_channel_type ;
2004-05-15 11:51:38 +04:00
2005-03-06 09:37:38 +03:00
pipe_state - > creds - > rid = * r - > out . rid ;
r5902: A rather large change...
I wanted to add a simple 'workstation' argument to the DCERPC
authenticated binding calls, but this patch kind of grew from there.
With SCHANNEL, the 'workstation' name (the netbios name of the client)
matters, as this is what ties the session between the NETLOGON ops and
the SCHANNEL bind. This changes a lot of files, and these will again
be changed when jelmer does the credentials work.
I also correct some schannel IDL to distinguish between workstation
names and account names. The distinction matters for domain trust
accounts.
Issues in handling this (issues with lifetime of talloc pointers)
caused me to change the 'creds_CredentialsState' and 'struct
dcerpc_binding' pointers to always be talloc()ed pointers.
In the schannel DB, we now store both the domain and computername, and
query on both. This should ensure we fault correctly when the domain
is specified incorrectly in the SCHANNEL bind.
In the RPC-SCHANNEL test, I finally fixed a bug that vl pointed out,
where the comment claimed we re-used a connection, but in fact we made
a new connection.
This was achived by breaking apart some of the
dcerpc_secondary_connection() logic.
The addition of workstation handling was also propogated to NTLMSSP
and GENSEC, for completeness.
The RPC-SAMSYNC test has been cleaned up a little, using a loop over
usernames/passwords rather than manually expanded tests. This will be
expanded further (the code in #if 0 in this patch) to use a newly
created user account for testing.
In making this test pass test_rpc.sh, I found a bug in the RPC-ECHO
server, caused by the removal of [ref] and the assoicated pointer from
the IDL. This has been re-added, until the underlying pidl issues are
solved.
(This used to be commit 824289dcc20908ddec957a4a892a103eec2da9b9)
2005-03-19 11:34:43 +03:00
pipe_state - > creds - > domain = talloc_strdup ( pipe_state - > creds , lp_workgroup ( ) ) ;
2004-06-05 05:29:20 +04:00
/* remember this session key state */
2005-01-10 15:30:13 +03:00
nt_status = schannel_store_session_key ( mem_ctx , pipe_state - > creds ) ;
2004-06-05 05:29:20 +04:00
return nt_status ;
2004-05-15 11:51:38 +04:00
}
static NTSTATUS netr_ServerAuthenticate ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_ServerAuthenticate * r )
{
2004-05-30 17:15:15 +04:00
struct netr_ServerAuthenticate3 r3 ;
2004-06-24 04:25:38 +04:00
uint32_t rid = 0 ;
2004-06-24 04:08:15 +04:00
/* TODO:
* negotiate_flags is used as an [ in ] parameter
* so it need to be initialised .
*
* ( I think . . . = 0 ; seems wrong here - - metze )
*/
2005-02-10 08:09:35 +03:00
uint32_t negotiate_flags = 0 ;
2004-05-30 17:15:15 +04:00
r3 . in . server_name = r - > in . server_name ;
2004-06-05 07:22:10 +04:00
r3 . in . account_name = r - > in . account_name ;
2004-05-30 17:15:15 +04:00
r3 . in . secure_channel_type = r - > in . secure_channel_type ;
r3 . in . computer_name = r - > in . computer_name ;
r3 . in . credentials = r - > in . credentials ;
r3 . out . credentials = r - > out . credentials ;
r3 . in . negotiate_flags = & negotiate_flags ;
r3 . out . negotiate_flags = & negotiate_flags ;
r3 . out . rid = & rid ;
2004-05-15 11:51:38 +04:00
2004-05-30 17:15:15 +04:00
return netr_ServerAuthenticate3 ( dce_call , mem_ctx , & r3 ) ;
2004-05-15 11:51:38 +04:00
}
static NTSTATUS netr_ServerAuthenticate2 ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-30 17:15:15 +04:00
struct netr_ServerAuthenticate2 * r )
{
struct netr_ServerAuthenticate3 r3 ;
2005-02-10 08:09:35 +03:00
uint32_t rid = 0 ;
2004-05-30 17:15:15 +04:00
r3 . in . server_name = r - > in . server_name ;
2004-06-05 07:22:10 +04:00
r3 . in . account_name = r - > in . account_name ;
2004-05-30 17:15:15 +04:00
r3 . in . secure_channel_type = r - > in . secure_channel_type ;
r3 . in . computer_name = r - > in . computer_name ;
r3 . in . credentials = r - > in . credentials ;
r3 . out . credentials = r - > out . credentials ;
r3 . in . negotiate_flags = r - > in . negotiate_flags ;
r3 . out . negotiate_flags = r - > out . negotiate_flags ;
r3 . out . rid = & rid ;
2004-05-15 11:51:38 +04:00
2004-05-30 17:15:15 +04:00
return netr_ServerAuthenticate3 ( dce_call , mem_ctx , & r3 ) ;
2004-05-15 11:51:38 +04:00
}
2004-05-30 17:15:15 +04:00
2005-01-03 09:23:02 +03:00
static NTSTATUS netr_creds_server_step_check ( struct server_pipe_state * pipe_state ,
struct netr_Authenticator * received_authenticator ,
struct netr_Authenticator * return_authenticator )
2004-05-17 01:30:48 +04:00
{
2005-01-03 09:23:02 +03:00
if ( ! pipe_state ) {
DEBUG ( 1 , ( " No challenge requested by client, cannot authenticate \n " ) ) ;
return NT_STATUS_ACCESS_DENIED ;
}
2004-05-17 01:30:48 +04:00
return creds_server_step_check ( pipe_state - > creds ,
received_authenticator ,
return_authenticator ) ;
}
2004-05-15 16:04:07 +04:00
static NTSTATUS netr_ServerPasswordSet ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_ServerPasswordSet * r )
{
2005-01-10 15:15:26 +03:00
struct server_pipe_state * pipe_state = dce_call - > context - > private ;
2004-05-17 01:30:48 +04:00
void * sam_ctx ;
int num_records ;
int num_records_domain ;
int ret ;
struct ldb_message * * msgs ;
struct ldb_message * * msgs_domain ;
NTSTATUS nt_status ;
2005-01-10 19:12:41 +03:00
struct ldb_message * mod ;
2005-06-24 04:18:20 +04:00
struct dom_sid * domain_sid ;
2004-05-17 01:30:48 +04:00
2004-05-30 17:15:15 +04:00
const char * attrs [ ] = { " objectSid " , NULL } ;
2004-05-15 16:04:07 +04:00
2004-05-17 01:30:48 +04:00
const char * * domain_attrs = attrs ;
2005-01-03 09:23:02 +03:00
nt_status = netr_creds_server_step_check ( pipe_state , & r - > in . credential , & r - > out . return_authenticator ) ;
2005-01-10 19:12:41 +03:00
NT_STATUS_NOT_OK_RETURN ( nt_status ) ;
2004-05-17 01:30:48 +04:00
2004-08-25 10:44:23 +04:00
sam_ctx = samdb_connect ( mem_ctx ) ;
2004-05-17 01:30:48 +04:00
if ( sam_ctx = = NULL ) {
return NT_STATUS_INVALID_SYSTEM_SERVICE ;
}
/* pull the user attributes */
2005-03-23 04:30:43 +03:00
num_records = gendb_search ( sam_ctx , mem_ctx , NULL , & msgs , attrs ,
2004-05-17 01:30:48 +04:00
" (&(sAMAccountName=%s)(objectclass=user)) " ,
2005-01-10 15:30:13 +03:00
pipe_state - > creds - > account_name ) ;
2005-01-10 19:12:41 +03:00
if ( num_records = = - 1 ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2004-05-17 01:30:48 +04:00
if ( num_records = = 0 ) {
DEBUG ( 3 , ( " Couldn't find user [%s] in samdb. \n " ,
2005-01-10 15:30:13 +03:00
pipe_state - > creds - > account_name ) ) ;
2004-05-17 01:30:48 +04:00
return NT_STATUS_NO_SUCH_USER ;
}
if ( num_records > 1 ) {
2004-07-05 11:24:14 +04:00
DEBUG ( 0 , ( " Found %d records matching user [%s] \n " , num_records ,
2005-01-10 15:30:13 +03:00
pipe_state - > creds - > account_name ) ) ;
2004-05-17 01:30:48 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2004-05-22 11:55:48 +04:00
domain_sid = samdb_result_sid_prefix ( mem_ctx , msgs [ 0 ] , " objectSid " ) ;
2004-05-17 01:30:48 +04:00
if ( ! domain_sid ) {
2004-07-05 11:24:14 +04:00
DEBUG ( 0 , ( " no objectSid in user record \n " ) ) ;
2004-05-17 01:30:48 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
/* find the domain's DN */
2005-03-23 04:30:43 +03:00
num_records_domain = gendb_search ( sam_ctx , mem_ctx , NULL ,
2004-05-17 01:30:48 +04:00
& msgs_domain , domain_attrs ,
" (&(objectSid=%s)(objectclass=domain)) " ,
2005-06-24 04:18:20 +04:00
ldap_encode_ndr_dom_sid ( mem_ctx , domain_sid ) ) ;
2005-01-10 19:12:41 +03:00
if ( num_records_domain = = - 1 ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2004-05-17 01:30:48 +04:00
if ( num_records_domain = = 0 ) {
2005-01-12 10:22:34 +03:00
DEBUG ( 3 , ( " Couldn't find domain [%s] in samdb. \n " ,
2005-06-24 04:18:20 +04:00
dom_sid_string ( mem_ctx , domain_sid ) ) ) ;
2004-05-17 01:30:48 +04:00
return NT_STATUS_NO_SUCH_USER ;
}
if ( num_records_domain > 1 ) {
2004-07-05 11:24:14 +04:00
DEBUG ( 0 , ( " Found %d records matching domain [%s] \n " ,
2005-06-24 04:18:20 +04:00
num_records_domain , dom_sid_string ( mem_ctx , domain_sid ) ) ) ;
2004-05-17 01:30:48 +04:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2005-01-10 19:12:41 +03:00
mod = talloc_zero ( mem_ctx , struct ldb_message ) ;
NT_STATUS_HAVE_NO_MEMORY ( mod ) ;
mod - > dn = talloc_reference ( mod , msgs [ 0 ] - > dn ) ;
2004-05-17 01:30:48 +04:00
creds_des_decrypt ( pipe_state - > creds , & r - > in . new_password ) ;
/* set the password - samdb needs to know both the domain and user DNs,
so the domain password policy can be used */
2005-01-10 19:12:41 +03:00
nt_status = samdb_set_password ( sam_ctx , mod ,
msgs [ 0 ] - > dn ,
msgs_domain [ 0 ] - > dn ,
mod ,
2004-05-17 01:30:48 +04:00
NULL , /* Don't have plaintext */
2004-06-04 15:58:46 +04:00
NULL , & r - > in . new_password ,
2005-01-12 13:49:52 +03:00
False , /* This is not considered a password change */
False , /* don't restrict this password change (match w2k3) */
2004-05-25 17:57:39 +04:00
NULL ) ;
2005-01-10 19:12:41 +03:00
NT_STATUS_NOT_OK_RETURN ( nt_status ) ;
2004-05-15 16:04:07 +04:00
2005-01-10 19:12:41 +03:00
ret = samdb_replace ( sam_ctx , mem_ctx , mod ) ;
2004-05-17 01:30:48 +04:00
if ( ret ! = 0 ) {
/* we really need samdb.c to return NTSTATUS */
return NT_STATUS_UNSUCCESSFUL ;
}
return NT_STATUS_OK ;
2004-05-15 16:04:07 +04:00
}
2004-05-15 11:51:38 +04:00
/*
netr_LogonUasLogon
*/
static WERROR netr_LogonUasLogon ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
2004-05-27 08:13:58 +04:00
struct netr_LogonUasLogon * r )
2004-05-15 11:51:38 +04:00
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_LogonUasLogoff
*/
static WERROR netr_LogonUasLogoff ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_LogonUasLogoff * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
2004-06-14 13:31:47 +04:00
netr_LogonSamLogonWithFlags
2004-05-15 11:51:38 +04:00
2005-01-03 09:23:02 +03:00
This version of the function allows other wrappers to say ' do not check the credentials '
2004-05-15 11:51:38 +04:00
*/
2005-01-03 09:23:02 +03:00
static NTSTATUS netr_LogonSamLogonEx ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_LogonSamLogonEx * r )
2004-06-07 07:46:32 +04:00
{
2005-01-10 15:15:26 +03:00
struct server_pipe_state * pipe_state = dce_call - > context - > private ;
2004-06-07 07:46:32 +04:00
struct auth_context * auth_context ;
struct auth_usersupplied_info * user_info ;
struct auth_serversupplied_info * server_info ;
NTSTATUS nt_status ;
const uint8_t * chal ;
2004-06-07 12:54:49 +04:00
static const char zeros [ 16 ] ;
2004-06-14 16:06:53 +04:00
struct netr_SamBaseInfo * sam ;
2004-06-07 12:54:49 +04:00
struct netr_SamInfo2 * sam2 ;
2004-06-14 16:06:53 +04:00
struct netr_SamInfo3 * sam3 ;
struct netr_SamInfo6 * sam6 ;
2004-06-07 07:46:32 +04:00
switch ( r - > in . logon_level ) {
case 1 :
case 3 :
2004-06-14 17:21:37 +04:00
case 5 :
2005-01-03 09:23:02 +03:00
if ( pipe_state - > creds - > negotiate_flags & NETLOGON_NEG_ARCFOUR ) {
creds_arcfour_crypt ( pipe_state - > creds ,
r - > in . logon . password - > lmpassword . hash ,
sizeof ( r - > in . logon . password - > lmpassword . hash ) ) ;
creds_arcfour_crypt ( pipe_state - > creds ,
r - > in . logon . password - > ntpassword . hash ,
sizeof ( r - > in . logon . password - > ntpassword . hash ) ) ;
} else {
creds_des_decrypt ( pipe_state - > creds , & r - > in . logon . password - > lmpassword ) ;
creds_des_decrypt ( pipe_state - > creds , & r - > in . logon . password - > ntpassword ) ;
}
2004-06-07 07:46:32 +04:00
2005-01-09 15:55:25 +03:00
/* TODO: we need to deny anonymous access here */
2005-06-16 15:36:09 +04:00
nt_status = auth_context_create ( mem_ctx , lp_auth_methods ( ) , & auth_context ,
dce_call - > event_ctx ) ;
2005-01-09 15:55:25 +03:00
NT_STATUS_NOT_OK_RETURN ( nt_status ) ;
nt_status = auth_get_challenge ( auth_context , & chal ) ;
NT_STATUS_NOT_OK_RETURN ( nt_status ) ;
2004-06-07 07:46:32 +04:00
2005-01-09 15:55:25 +03:00
nt_status = make_user_info_netlogon_interactive ( mem_ctx ,
2004-06-07 07:46:32 +04:00
r - > in . logon . password - > identity_info . account_name . string ,
r - > in . logon . password - > identity_info . domain_name . string ,
r - > in . logon . password - > identity_info . workstation . string ,
chal ,
& r - > in . logon . password - > lmpassword ,
2005-01-09 15:55:25 +03:00
& r - > in . logon . password - > ntpassword ,
& user_info ) ;
NT_STATUS_NOT_OK_RETURN ( nt_status ) ;
break ;
2004-06-07 07:46:32 +04:00
case 2 :
case 6 :
2005-01-09 15:55:25 +03:00
/* TODO: we need to deny anonymous access here */
2005-06-16 15:36:09 +04:00
nt_status = auth_context_create ( mem_ctx , lp_auth_methods ( ) , & auth_context ,
dce_call - > event_ctx ) ;
2005-01-09 15:55:25 +03:00
NT_STATUS_NOT_OK_RETURN ( nt_status ) ;
nt_status = auth_context_set_challenge ( auth_context , r - > in . logon . network - > challenge , " netr_LogonSamLogonWithFlags " ) ;
NT_STATUS_NOT_OK_RETURN ( nt_status ) ;
2004-06-07 07:46:32 +04:00
2004-09-27 03:39:18 +04:00
nt_status = make_user_info_netlogon_network ( auth_context ,
2004-06-07 07:46:32 +04:00
r - > in . logon . network - > identity_info . account_name . string ,
r - > in . logon . network - > identity_info . domain_name . string ,
r - > in . logon . network - > identity_info . workstation . string ,
2004-06-07 12:54:49 +04:00
r - > in . logon . network - > lm . data , r - > in . logon . network - > lm . length ,
2005-01-09 15:55:25 +03:00
r - > in . logon . network - > nt . data , r - > in . logon . network - > nt . length ,
& user_info ) ;
NT_STATUS_NOT_OK_RETURN ( nt_status ) ;
2004-06-07 07:46:32 +04:00
break ;
default :
return NT_STATUS_INVALID_PARAMETER ;
}
2005-01-09 15:55:25 +03:00
nt_status = auth_check_password ( auth_context , mem_ctx , user_info , & server_info ) ;
NT_STATUS_NOT_OK_RETURN ( nt_status ) ;
2004-06-07 07:46:32 +04:00
2005-06-29 17:55:09 +04:00
nt_status = auth_convert_server_info_sambaseinfo ( mem_ctx , server_info , & sam ) ;
2005-01-10 15:14:26 +03:00
2005-06-29 17:55:09 +04:00
NT_STATUS_NOT_OK_RETURN ( nt_status ) ;
2005-01-10 15:14:26 +03:00
2004-06-08 02:17:51 +04:00
/* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
2004-09-22 16:17:51 +04:00
/* It appears that level 6 is not individually encrypted */
if ( ( r - > in . validation_level ! = 6 )
& & memcmp ( sam - > key . key , zeros ,
sizeof ( sam - > key . key ) ) ! = 0 ) {
2005-01-03 09:23:02 +03:00
/* This key is sent unencrypted without the ARCFOUR flag set */
if ( pipe_state - > creds - > negotiate_flags & NETLOGON_NEG_ARCFOUR ) {
creds_arcfour_crypt ( pipe_state - > creds ,
sam - > key . key ,
sizeof ( sam - > key . key ) ) ;
}
2004-06-07 12:54:49 +04:00
}
2005-01-10 15:14:26 +03:00
2004-06-08 02:17:51 +04:00
/* Don't crypt an all-zero key, it would give away the NETLOGON pipe session key */
2004-09-22 16:17:51 +04:00
/* It appears that level 6 is not individually encrypted */
if ( ( r - > in . validation_level ! = 6 )
& & memcmp ( sam - > LMSessKey . key , zeros ,
sizeof ( sam - > LMSessKey . key ) ) ! = 0 ) {
2005-01-03 09:23:02 +03:00
if ( pipe_state - > creds - > negotiate_flags & NETLOGON_NEG_ARCFOUR ) {
creds_arcfour_crypt ( pipe_state - > creds ,
sam - > LMSessKey . key ,
sizeof ( sam - > LMSessKey . key ) ) ;
} else {
creds_des_encrypt_LMKey ( pipe_state - > creds ,
& sam - > LMSessKey ) ;
}
2004-06-07 12:54:49 +04:00
}
2004-06-07 07:46:32 +04:00
switch ( r - > in . validation_level ) {
case 2 :
2005-01-10 18:56:37 +03:00
sam2 = talloc_zero ( mem_ctx , struct netr_SamInfo2 ) ;
2005-01-09 15:55:25 +03:00
NT_STATUS_HAVE_NO_MEMORY ( sam2 ) ;
2004-06-14 16:06:53 +04:00
sam2 - > base = * sam ;
2004-06-07 12:54:49 +04:00
r - > out . validation . sam2 = sam2 ;
2004-06-07 07:46:32 +04:00
break ;
2004-06-14 16:06:53 +04:00
2004-06-07 07:46:32 +04:00
case 3 :
2005-01-10 18:56:37 +03:00
sam3 = talloc_zero ( mem_ctx , struct netr_SamInfo3 ) ;
2005-01-09 15:55:25 +03:00
NT_STATUS_HAVE_NO_MEMORY ( sam3 ) ;
2004-06-14 16:06:53 +04:00
sam3 - > base = * sam ;
r - > out . validation . sam3 = sam3 ;
2004-06-07 07:46:32 +04:00
break ;
2004-06-14 16:06:53 +04:00
case 6 :
2005-01-10 18:56:37 +03:00
sam6 = talloc_zero ( mem_ctx , struct netr_SamInfo6 ) ;
2005-01-09 15:55:25 +03:00
NT_STATUS_HAVE_NO_MEMORY ( sam6 ) ;
2004-06-14 16:06:53 +04:00
sam6 - > base = * sam ;
2004-06-15 07:53:21 +04:00
sam6 - > forest . string = lp_realm ( ) ;
2004-06-14 16:06:53 +04:00
sam6 - > principle . string = talloc_asprintf ( mem_ctx , " %s@%s " ,
2004-06-15 07:53:21 +04:00
sam - > account_name . string , sam6 - > forest . string ) ;
2005-01-10 18:56:37 +03:00
NT_STATUS_HAVE_NO_MEMORY ( sam6 - > principle . string ) ;
2004-06-14 16:06:53 +04:00
r - > out . validation . sam6 = sam6 ;
break ;
2004-06-07 07:46:32 +04:00
default :
break ;
}
r - > out . authoritative = 1 ;
2005-01-10 15:30:13 +03:00
/* TODO: Describe and deal with these flags */
r - > out . flags = 0 ;
2004-06-07 07:46:32 +04:00
return NT_STATUS_OK ;
}
2004-05-15 11:51:38 +04:00
2005-01-03 09:23:02 +03:00
/*
netr_LogonSamLogonWithFlags
*/
static NTSTATUS netr_LogonSamLogonWithFlags ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_LogonSamLogonWithFlags * r )
{
2005-01-10 18:56:37 +03:00
struct server_pipe_state * pipe_state = dce_call - > context - > private ;
2005-01-03 09:23:02 +03:00
NTSTATUS nt_status ;
struct netr_LogonSamLogonEx r2 ;
2005-01-10 18:56:37 +03:00
struct netr_Authenticator * return_authenticator ;
2005-01-03 09:23:02 +03:00
2005-01-10 18:56:37 +03:00
return_authenticator = talloc ( mem_ctx , struct netr_Authenticator ) ;
NT_STATUS_HAVE_NO_MEMORY ( return_authenticator ) ;
2005-01-03 09:23:02 +03:00
2005-01-10 18:56:37 +03:00
nt_status = netr_creds_server_step_check ( pipe_state , r - > in . credential , return_authenticator ) ;
NT_STATUS_NOT_OK_RETURN ( nt_status ) ;
2005-01-03 09:23:02 +03:00
ZERO_STRUCT ( r2 ) ;
2005-01-10 18:56:37 +03:00
r2 . in . server_name = r - > in . server_name ;
r2 . in . workstation = r - > in . workstation ;
r2 . in . logon_level = r - > in . logon_level ;
r2 . in . logon = r - > in . logon ;
r2 . in . validation_level = r - > in . validation_level ;
r2 . in . flags = r - > in . flags ;
2005-01-03 09:23:02 +03:00
nt_status = netr_LogonSamLogonEx ( dce_call , mem_ctx , & r2 ) ;
2005-01-10 18:56:37 +03:00
r - > out . return_authenticator = return_authenticator ;
r - > out . validation = r2 . out . validation ;
r - > out . authoritative = r2 . out . authoritative ;
r - > out . flags = r2 . out . flags ;
2005-01-03 09:23:02 +03:00
return nt_status ;
}
2004-06-14 13:31:47 +04:00
/*
netr_LogonSamLogon
*/
static NTSTATUS netr_LogonSamLogon ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_LogonSamLogon * r )
{
struct netr_LogonSamLogonWithFlags r2 ;
NTSTATUS status ;
ZERO_STRUCT ( r2 ) ;
r2 . in . server_name = r - > in . server_name ;
r2 . in . workstation = r - > in . workstation ;
r2 . in . credential = r - > in . credential ;
r2 . in . return_authenticator = r - > in . return_authenticator ;
r2 . in . logon_level = r - > in . logon_level ;
r2 . in . logon = r - > in . logon ;
r2 . in . validation_level = r - > in . validation_level ;
r2 . in . flags = 0 ;
status = netr_LogonSamLogonWithFlags ( dce_call , mem_ctx , & r2 ) ;
r - > out . return_authenticator = r2 . out . return_authenticator ;
r - > out . validation = r2 . out . validation ;
r - > out . authoritative = r2 . out . authoritative ;
return status ;
}
2004-05-15 11:51:38 +04:00
/*
netr_LogonSamLogoff
*/
static NTSTATUS netr_LogonSamLogoff ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_LogonSamLogoff * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_DatabaseDeltas
*/
static NTSTATUS netr_DatabaseDeltas ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_DatabaseDeltas * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_DatabaseSync
*/
static NTSTATUS netr_DatabaseSync ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_DatabaseSync * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_AccountDeltas
*/
static NTSTATUS netr_AccountDeltas ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_AccountDeltas * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_AccountSync
*/
static NTSTATUS netr_AccountSync ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_AccountSync * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_GetDcName
*/
static NTSTATUS netr_GetDcName ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_GetDcName * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_LogonControl
*/
static WERROR netr_LogonControl ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_LogonControl * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_GetAnyDCName
*/
static WERROR netr_GetAnyDCName ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_GetAnyDCName * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_LogonControl2
*/
static WERROR netr_LogonControl2 ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_LogonControl2 * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_DatabaseSync2
*/
static NTSTATUS netr_DatabaseSync2 ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_DatabaseSync2 * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_DatabaseRedo
*/
static NTSTATUS netr_DatabaseRedo ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_DatabaseRedo * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_LogonControl2Ex
*/
static WERROR netr_LogonControl2Ex ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_LogonControl2Ex * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
2004-05-28 17:23:30 +04:00
/*
netr_NETRENUMERATETRUSTEDDOMAINS
*/
static WERROR netr_NETRENUMERATETRUSTEDDOMAINS ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_NETRENUMERATETRUSTEDDOMAINS * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_DSRGETDCNAME
*/
static WERROR netr_DSRGETDCNAME ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_DSRGETDCNAME * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_NETRLOGONDUMMYROUTINE1
*/
static WERROR netr_NETRLOGONDUMMYROUTINE1 ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_NETRLOGONDUMMYROUTINE1 * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_NETRLOGONSETSERVICEBITS
*/
static WERROR netr_NETRLOGONSETSERVICEBITS ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_NETRLOGONSETSERVICEBITS * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_NETRLOGONGETTRUSTRID
*/
static WERROR netr_NETRLOGONGETTRUSTRID ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_NETRLOGONGETTRUSTRID * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_NETRLOGONCOMPUTESERVERDIGEST
*/
static WERROR netr_NETRLOGONCOMPUTESERVERDIGEST ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_NETRLOGONCOMPUTESERVERDIGEST * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_NETRLOGONCOMPUTECLIENTDIGEST
*/
static WERROR netr_NETRLOGONCOMPUTECLIENTDIGEST ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_NETRLOGONCOMPUTECLIENTDIGEST * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_DSRGETDCNAMEX
*/
static WERROR netr_DSRGETDCNAMEX ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_DSRGETDCNAMEX * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_DSRGETSITENAME
*/
static WERROR netr_DSRGETSITENAME ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_DSRGETSITENAME * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
2004-06-14 12:12:50 +04:00
/*
fill in a netr_DomainTrustInfo from a ldb search result
*/
static NTSTATUS fill_domain_trust_info ( TALLOC_CTX * mem_ctx , struct ldb_message * res ,
2004-12-21 14:52:53 +03:00
struct netr_DomainTrustInfo * info , BOOL is_local )
2004-06-14 12:12:50 +04:00
{
ZERO_STRUCTP ( info ) ;
2004-12-21 14:52:53 +03:00
if ( is_local ) {
2004-06-14 12:12:50 +04:00
info - > domainname . string = samdb_result_string ( res , " name " , NULL ) ;
info - > fulldomainname . string = samdb_result_string ( res , " dnsDomain " , NULL ) ;
2004-12-21 14:52:53 +03:00
info - > guid = samdb_result_guid ( res , " objectGUID " ) ;
info - > sid = samdb_result_dom_sid ( mem_ctx , res , " objectSid " ) ;
2004-06-14 12:12:50 +04:00
} else {
2004-12-21 14:52:53 +03:00
info - > domainname . string = samdb_result_string ( res , " flatName " , NULL ) ;
2004-06-14 12:12:50 +04:00
info - > fulldomainname . string = samdb_result_string ( res , " name " , NULL ) ;
2004-12-21 14:52:53 +03:00
info - > guid = samdb_result_guid ( res , " objectGUID " ) ;
info - > sid = samdb_result_dom_sid ( mem_ctx , res , " securityIdentifier " ) ;
2004-06-14 12:12:50 +04:00
}
/* TODO: we need proper forest support */
info - > forest . string = info - > fulldomainname . string ;
return NT_STATUS_OK ;
}
2004-05-28 17:23:30 +04:00
/*
2004-06-14 12:12:50 +04:00
netr_LogonGetDomainInfo
this is called as part of the ADS domain logon procedure .
2004-05-28 17:23:30 +04:00
*/
2004-06-14 12:12:50 +04:00
static NTSTATUS netr_LogonGetDomainInfo ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_LogonGetDomainInfo * r )
2004-05-28 17:23:30 +04:00
{
2005-01-10 15:15:26 +03:00
struct server_pipe_state * pipe_state = dce_call - > context - > private ;
2004-06-14 12:12:50 +04:00
const char * const attrs [ ] = { " name " , " dnsDomain " , " objectSid " ,
2004-12-21 14:52:53 +03:00
" objectGUID " , " flatName " , " securityIdentifier " ,
NULL } ;
2004-06-14 12:12:50 +04:00
void * sam_ctx ;
struct ldb_message * * res1 , * * res2 ;
struct netr_DomainInfo1 * info1 ;
int ret1 , ret2 , i ;
NTSTATUS status ;
2005-01-03 09:23:02 +03:00
status = netr_creds_server_step_check ( pipe_state ,
2005-01-29 07:02:13 +03:00
r - > in . credential , r - > out . return_authenticator ) ;
2005-01-03 09:23:02 +03:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
2004-06-14 12:12:50 +04:00
}
2004-08-25 10:44:23 +04:00
sam_ctx = samdb_connect ( mem_ctx ) ;
2004-06-14 12:12:50 +04:00
if ( sam_ctx = = NULL ) {
return NT_STATUS_INVALID_SYSTEM_SERVICE ;
}
/* we need to do two searches. The first will pull our primary
domain and the second will pull any trusted domains . Our
primary domain is also a " trusted " domain , so we need to
put the primary domain into the lists of returned trusts as
well */
2005-03-23 04:30:43 +03:00
ret1 = gendb_search ( sam_ctx , mem_ctx , NULL , & res1 , attrs , " (objectClass=domainDNS) " ) ;
2004-06-14 12:12:50 +04:00
if ( ret1 ! = 1 ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2005-03-23 04:30:43 +03:00
ret2 = gendb_search ( sam_ctx , mem_ctx , NULL , & res2 , attrs , " (objectClass=trustedDomain) " ) ;
2004-06-14 12:12:50 +04:00
if ( ret2 = = - 1 ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
2005-01-27 10:08:20 +03:00
info1 = talloc ( mem_ctx , struct netr_DomainInfo1 ) ;
2004-06-14 12:12:50 +04:00
if ( info1 = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
ZERO_STRUCTP ( info1 ) ;
info1 - > num_trusts = ret2 + 1 ;
2005-01-27 10:08:20 +03:00
info1 - > trusts = talloc_array ( mem_ctx , struct netr_DomainTrustInfo ,
2004-06-14 12:12:50 +04:00
info1 - > num_trusts ) ;
if ( info1 - > trusts = = NULL ) {
return NT_STATUS_NO_MEMORY ;
}
2004-12-21 14:52:53 +03:00
status = fill_domain_trust_info ( mem_ctx , res1 [ 0 ] , & info1 - > domaininfo , True ) ;
2004-06-14 12:12:50 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
2004-12-21 14:52:53 +03:00
status = fill_domain_trust_info ( mem_ctx , res1 [ 0 ] , & info1 - > trusts [ 0 ] , True ) ;
2004-06-14 12:12:50 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
for ( i = 0 ; i < ret2 ; i + + ) {
2004-12-21 14:52:53 +03:00
status = fill_domain_trust_info ( mem_ctx , res2 [ i ] , & info1 - > trusts [ i + 1 ] , False ) ;
2004-06-14 12:12:50 +04:00
if ( ! NT_STATUS_IS_OK ( status ) ) {
return status ;
}
}
r - > out . info . info1 = info1 ;
return NT_STATUS_OK ;
2004-05-28 17:23:30 +04:00
}
/*
2005-01-12 10:22:34 +03:00
netr_ServerPasswordSet2
2004-05-28 17:23:30 +04:00
*/
2005-01-12 10:22:34 +03:00
static NTSTATUS netr_ServerPasswordSet2 ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_ServerPasswordSet2 * r )
2004-05-28 17:23:30 +04:00
{
2005-01-12 10:22:34 +03:00
struct server_pipe_state * pipe_state = dce_call - > context - > private ;
void * sam_ctx ;
int num_records ;
int num_records_domain ;
int ret ;
struct ldb_message * * msgs ;
struct ldb_message * * msgs_domain ;
NTSTATUS nt_status ;
struct ldb_message * mod ;
2005-06-24 04:18:20 +04:00
struct dom_sid * domain_sid ;
2005-01-12 10:22:34 +03:00
char new_pass [ 512 ] ;
uint32_t new_pass_len ;
2005-03-24 09:30:38 +03:00
struct samr_CryptPassword password_buf ;
2005-01-12 10:22:34 +03:00
const char * attrs [ ] = { " objectSid " , NULL } ;
const char * * domain_attrs = attrs ;
nt_status = netr_creds_server_step_check ( pipe_state , & r - > in . credential , & r - > out . return_authenticator ) ;
NT_STATUS_NOT_OK_RETURN ( nt_status ) ;
sam_ctx = samdb_connect ( mem_ctx ) ;
if ( sam_ctx = = NULL ) {
return NT_STATUS_INVALID_SYSTEM_SERVICE ;
}
/* pull the user attributes */
2005-03-23 04:30:43 +03:00
num_records = gendb_search ( sam_ctx , mem_ctx , NULL , & msgs , attrs ,
2005-01-12 10:22:34 +03:00
" (&(sAMAccountName=%s)(objectclass=user)) " ,
pipe_state - > creds - > account_name ) ;
if ( num_records = = - 1 ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
if ( num_records = = 0 ) {
DEBUG ( 3 , ( " Couldn't find user [%s] in samdb. \n " ,
pipe_state - > creds - > account_name ) ) ;
return NT_STATUS_NO_SUCH_USER ;
}
if ( num_records > 1 ) {
DEBUG ( 0 , ( " Found %d records matching user [%s] \n " , num_records ,
pipe_state - > creds - > account_name ) ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
domain_sid = samdb_result_sid_prefix ( mem_ctx , msgs [ 0 ] , " objectSid " ) ;
if ( ! domain_sid ) {
DEBUG ( 0 , ( " no objectSid in user record \n " ) ) ;
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
/* find the domain's DN */
2005-03-23 04:30:43 +03:00
num_records_domain = gendb_search ( sam_ctx , mem_ctx , NULL ,
2005-01-12 10:22:34 +03:00
& msgs_domain , domain_attrs ,
" (&(objectSid=%s)(objectclass=domain)) " ,
2005-06-24 04:18:20 +04:00
ldap_encode_ndr_dom_sid ( mem_ctx , domain_sid ) ) ;
2005-01-12 10:22:34 +03:00
if ( num_records_domain = = - 1 ) {
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
if ( num_records_domain = = 0 ) {
DEBUG ( 3 , ( " Couldn't find domain [%s] in samdb. \n " ,
2005-06-24 04:18:20 +04:00
ldap_encode_ndr_dom_sid ( mem_ctx , domain_sid ) ) ) ;
2005-01-12 10:22:34 +03:00
return NT_STATUS_NO_SUCH_USER ;
}
if ( num_records_domain > 1 ) {
DEBUG ( 0 , ( " Found %d records matching domain [%s] \n " ,
2005-06-24 04:18:20 +04:00
num_records_domain ,
ldap_encode_ndr_dom_sid ( mem_ctx , domain_sid ) ) ) ;
2005-01-12 10:22:34 +03:00
return NT_STATUS_INTERNAL_DB_CORRUPTION ;
}
mod = talloc_zero ( mem_ctx , struct ldb_message ) ;
NT_STATUS_HAVE_NO_MEMORY ( mod ) ;
mod - > dn = talloc_reference ( mod , msgs [ 0 ] - > dn ) ;
2005-03-24 09:30:38 +03:00
memcpy ( password_buf . data , r - > in . new_password . data , 512 ) ;
SIVAL ( password_buf . data , 512 , r - > in . new_password . length ) ;
creds_arcfour_crypt ( pipe_state - > creds , password_buf . data , 516 ) ;
2005-01-12 10:22:34 +03:00
2005-03-24 09:30:38 +03:00
ret = decode_pw_buffer ( password_buf . data , new_pass , sizeof ( new_pass ) ,
& new_pass_len , STR_UNICODE ) ;
2005-01-12 10:22:34 +03:00
if ( ! ret ) {
DEBUG ( 3 , ( " netr_ServerPasswordSet2: failed to decode password buffer \n " ) ) ;
return NT_STATUS_ACCESS_DENIED ;
}
/* set the password - samdb needs to know both the domain and user DNs,
so the domain password policy can be used */
nt_status = samdb_set_password ( sam_ctx , mod ,
msgs [ 0 ] - > dn ,
msgs_domain [ 0 ] - > dn ,
mod , new_pass , /* we have plaintext */
NULL , NULL ,
2005-01-12 13:49:52 +03:00
False , /* This is not considered a password change */
False , /* don't restrict this password change (match w2k3) */
2005-01-12 10:22:34 +03:00
NULL ) ;
2005-02-10 10:39:14 +03:00
ZERO_STRUCT ( new_pass ) ;
2005-01-12 10:22:34 +03:00
NT_STATUS_NOT_OK_RETURN ( nt_status ) ;
ret = samdb_replace ( sam_ctx , mem_ctx , mod ) ;
if ( ret ! = 0 ) {
/* we really need samdb.c to return NTSTATUS */
return NT_STATUS_UNSUCCESSFUL ;
}
return NT_STATUS_OK ;
2004-05-28 17:23:30 +04:00
}
/*
netr_NETRSERVERPASSWORDGET
*/
static WERROR netr_NETRSERVERPASSWORDGET ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_NETRSERVERPASSWORDGET * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_NETRLOGONSENDTOSAM
*/
static WERROR netr_NETRLOGONSENDTOSAM ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_NETRLOGONSENDTOSAM * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_DSRADDRESSTOSITENAMESW
*/
static WERROR netr_DSRADDRESSTOSITENAMESW ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_DSRADDRESSTOSITENAMESW * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
2004-11-22 20:14:57 +03:00
netr_DrsGetDCNameEx2
2004-05-28 17:23:30 +04:00
*/
2004-11-22 20:14:57 +03:00
static WERROR netr_DrsGetDCNameEx2 ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_DrsGetDCNameEx2 * r )
2004-05-28 17:23:30 +04:00
{
2004-11-22 20:14:57 +03:00
const char * const attrs [ ] = { " dnsDomain " , " objectGUID " , NULL } ;
void * sam_ctx ;
struct ldb_message * * res ;
int ret ;
ZERO_STRUCT ( r - > out ) ;
sam_ctx = samdb_connect ( mem_ctx ) ;
if ( sam_ctx = = NULL ) {
return WERR_DS_SERVICE_UNAVAILABLE ;
}
2005-03-23 04:30:43 +03:00
ret = gendb_search ( sam_ctx , mem_ctx , NULL , & res , attrs ,
2004-11-22 20:14:57 +03:00
" (&(objectClass=domainDNS)(dnsDomain=%s)) " ,
r - > in . domain_name ) ;
if ( ret ! = 1 ) {
return WERR_NO_SUCH_DOMAIN ;
}
2005-01-27 10:08:20 +03:00
r - > out . info = talloc ( mem_ctx , struct netr_DrsGetDCNameEx2Info ) ;
2004-11-22 20:14:57 +03:00
if ( ! r - > out . info ) {
return WERR_NOMEM ;
}
/* TODO: - return real IP address
* - check all r - > in . * parameters ( server_unc is ignored by w2k3 ! )
*/
r - > out . info - > dc_unc = talloc_asprintf ( mem_ctx , " \\ \\ %s.%s " , lp_netbios_name ( ) , lp_realm ( ) ) ;
r - > out . info - > dc_address = talloc_strdup ( mem_ctx , " \\ \\ 0.0.0.0 " ) ;
r - > out . info - > dc_address_type = 1 ;
r - > out . info - > domain_guid = samdb_result_guid ( res [ 0 ] , " objectGUID " ) ;
r - > out . info - > domain_name = samdb_result_string ( res [ 0 ] , " dnsDomain " , NULL ) ;
r - > out . info - > forest_name = samdb_result_string ( res [ 0 ] , " dnsDomain " , NULL ) ;
r - > out . info - > dc_flags = 0xE00001FD ;
r - > out . info - > dc_site_name = talloc_strdup ( mem_ctx , " Default-First-Site-Name " ) ;
r - > out . info - > client_site_name = talloc_strdup ( mem_ctx , " Default-First-Site-Name " ) ;
return WERR_OK ;
2004-05-28 17:23:30 +04:00
}
/*
netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN
*/
static WERROR netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_NETRLOGONGETTIMESERVICEPARENTDOMAIN * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_NETRENUMERATETRUSTEDDOMAINSEX
*/
static WERROR netr_NETRENUMERATETRUSTEDDOMAINSEX ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_NETRENUMERATETRUSTEDDOMAINSEX * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_DSRADDRESSTOSITENAMESEXW
*/
static WERROR netr_DSRADDRESSTOSITENAMESEXW ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_DSRADDRESSTOSITENAMESEXW * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_DSRGETDCSITECOVERAGEW
*/
static WERROR netr_DSRGETDCSITECOVERAGEW ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_DSRGETDCSITECOVERAGEW * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_DsrEnumerateDomainTrusts
*/
static WERROR netr_DsrEnumerateDomainTrusts ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_DsrEnumerateDomainTrusts * r )
{
struct netr_DomainTrust * trusts ;
void * sam_ctx ;
int ret , i ;
struct ldb_message * * res ;
const char * const attrs [ ] = { " name " , " dnsDomain " , " objectSid " , " objectGUID " , NULL } ;
ZERO_STRUCT ( r - > out ) ;
2004-08-25 10:44:23 +04:00
sam_ctx = samdb_connect ( mem_ctx ) ;
2004-05-28 17:23:30 +04:00
if ( sam_ctx = = NULL ) {
return WERR_GENERAL_FAILURE ;
}
2005-03-23 04:30:43 +03:00
ret = gendb_search ( sam_ctx , mem_ctx , NULL , & res , attrs , " (objectClass=domainDNS) " ) ;
2004-05-28 17:23:30 +04:00
if ( ret = = - 1 ) {
return WERR_GENERAL_FAILURE ;
}
if ( ret = = 0 ) {
return WERR_OK ;
}
2005-01-27 10:08:20 +03:00
trusts = talloc_array ( mem_ctx , struct netr_DomainTrust , ret ) ;
2004-05-28 17:23:30 +04:00
if ( trusts = = NULL ) {
return WERR_NOMEM ;
}
r - > out . count = ret ;
r - > out . trusts = trusts ;
2004-05-30 17:15:15 +04:00
/* TODO: add filtering by trust_flags, and correct trust_type
and attributes */
2004-05-28 17:23:30 +04:00
for ( i = 0 ; i < ret ; i + + ) {
trusts [ i ] . netbios_name = samdb_result_string ( res [ i ] , " name " , NULL ) ;
trusts [ i ] . dns_name = samdb_result_string ( res [ i ] , " dnsDomain " , NULL ) ;
trusts [ i ] . trust_flags =
NETR_TRUST_FLAG_TREEROOT |
NETR_TRUST_FLAG_IN_FOREST |
NETR_TRUST_FLAG_PRIMARY ;
trusts [ i ] . parent_index = 0 ;
trusts [ i ] . trust_type = 2 ;
trusts [ i ] . trust_attributes = 0 ;
trusts [ i ] . sid = samdb_result_dom_sid ( mem_ctx , res [ i ] , " objectSid " ) ;
trusts [ i ] . guid = samdb_result_guid ( res [ i ] , " objectGUID " ) ;
}
return WERR_OK ;
}
/*
netr_DSRDEREGISTERDNSHOSTRECORDS
*/
static WERROR netr_DSRDEREGISTERDNSHOSTRECORDS ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_DSRDEREGISTERDNSHOSTRECORDS * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_NETRSERVERTRUSTPASSWORDSGET
*/
static WERROR netr_NETRSERVERTRUSTPASSWORDSGET ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_NETRSERVERTRUSTPASSWORDSGET * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_DSRGETFORESTTRUSTINFORMATION
*/
static WERROR netr_DSRGETFORESTTRUSTINFORMATION ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_DSRGETFORESTTRUSTINFORMATION * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_NETRGETFORESTTRUSTINFORMATION
*/
static WERROR netr_NETRGETFORESTTRUSTINFORMATION ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_NETRGETFORESTTRUSTINFORMATION * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
/*
netr_NETRSERVERGETTRUSTINFO
*/
static WERROR netr_NETRSERVERGETTRUSTINFO ( struct dcesrv_call_state * dce_call , TALLOC_CTX * mem_ctx ,
struct netr_NETRSERVERGETTRUSTINFO * r )
{
DCESRV_FAULT ( DCERPC_FAULT_OP_RNG_ERROR ) ;
}
2004-05-15 11:51:38 +04:00
/* include the generated boilerplate */
# include "librpc/gen_ndr/ndr_netlogon_s.c"