2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-1997,
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
6 * Copyright (C) Paul Ashton 1997.
7 * Copyright (C) Jeremy Allison 1998-2001.
8 * Copyright (C) Andrew Bartlett 2001.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 /* This is the implementation of the netlogon pipe. */
30 #define DBGC_CLASS DBGC_RPC_SRV
32 /*************************************************************************
34 *************************************************************************/
36 static void init_net_r_req_chal(NET_R_REQ_CHAL
*r_c
,
37 DOM_CHAL
*srv_chal
, NTSTATUS status
)
39 DEBUG(6,("init_net_r_req_chal: %d\n", __LINE__
));
40 memcpy(r_c
->srv_chal
.data
, srv_chal
->data
, sizeof(srv_chal
->data
));
44 /*************************************************************************
45 error messages cropping up when using nltest.exe...
46 *************************************************************************/
48 #define ERROR_NO_SUCH_DOMAIN 0x54b
49 #define ERROR_NO_LOGON_SERVERS 0x51f
51 /*************************************************************************
53 *************************************************************************/
55 /* Some flag values reverse engineered from NLTEST.EXE */
57 #define LOGON_CTRL_IN_SYNC 0x00
58 #define LOGON_CTRL_REPL_NEEDED 0x01
59 #define LOGON_CTRL_REPL_IN_PROGRESS 0x02
61 NTSTATUS
_net_logon_ctrl(pipes_struct
*p
, NET_Q_LOGON_CTRL
*q_u
,
62 NET_R_LOGON_CTRL
*r_u
)
65 uint32 pdc_connection_status
= 0x00; /* Maybe a win32 error code? */
67 /* Setup the Logon Control response */
69 init_net_r_logon_ctrl(r_u
, q_u
->query_level
, flags
,
70 pdc_connection_status
);
75 /****************************************************************************
76 Send a message to smbd to do a sam synchronisation
77 **************************************************************************/
78 static void send_sync_message(void)
82 tdb
= tdb_open_log(lock_path("connections.tdb"), 0,
83 TDB_DEFAULT
, O_RDONLY
, 0);
86 DEBUG(3, ("send_sync_message(): failed to open connections "
91 DEBUG(3, ("sending sam synchronisation message\n"));
93 message_send_all(tdb
, MSG_SMB_SAM_SYNC
, NULL
, 0, False
, NULL
);
98 /*************************************************************************
99 net_reply_logon_ctrl2:
100 *************************************************************************/
102 NTSTATUS
_net_logon_ctrl2(pipes_struct
*p
, NET_Q_LOGON_CTRL2
*q_u
, NET_R_LOGON_CTRL2
*r_u
)
105 uint32 pdc_connection_status
= 0x0;
106 uint32 logon_attempts
= 0x0;
107 uint32 tc_status
= ERROR_NO_LOGON_SERVERS
;
108 const char *trusted_domain
= "test_domain";
110 DEBUG(0, ("*** net long ctrl2 %d, %d, %d\n",
111 q_u
->function_code
, q_u
->query_level
, q_u
->switch_value
));
113 DEBUG(6,("_net_logon_ctrl2: %d\n", __LINE__
));
116 /* set up the Logon Control2 response */
117 init_net_r_logon_ctrl2(r_u
, q_u
->query_level
,
118 flags
, pdc_connection_status
, logon_attempts
,
119 tc_status
, trusted_domain
);
121 if (lp_server_role() == ROLE_DOMAIN_BDC
)
124 DEBUG(6,("_net_logon_ctrl2: %d\n", __LINE__
));
129 /*************************************************************************
130 net_reply_trust_dom_list:
131 *************************************************************************/
133 NTSTATUS
_net_trust_dom_list(pipes_struct
*p
, NET_Q_TRUST_DOM_LIST
*q_u
, NET_R_TRUST_DOM_LIST
*r_u
)
135 const char *trusted_domain
= "test_domain";
136 uint32 num_trust_domains
= 1;
138 DEBUG(6,("_net_trust_dom_list: %d\n", __LINE__
));
140 /* set up the Trusted Domain List response */
141 init_r_trust_dom(r_u
, num_trust_domains
, trusted_domain
);
143 DEBUG(6,("_net_trust_dom_list: %d\n", __LINE__
));
148 /***********************************************************************************
149 init_net_r_srv_pwset:
150 ***********************************************************************************/
152 static void init_net_r_srv_pwset(NET_R_SRV_PWSET
*r_s
,
153 DOM_CRED
*srv_cred
, NTSTATUS status
)
155 DEBUG(5,("init_net_r_srv_pwset: %d\n", __LINE__
));
157 memcpy(&r_s
->srv_cred
, srv_cred
, sizeof(r_s
->srv_cred
));
158 r_s
->status
= status
;
160 DEBUG(5,("init_net_r_srv_pwset: %d\n", __LINE__
));
163 /******************************************************************
164 gets a machine password entry. checks access rights of the host.
165 ******************************************************************/
167 static BOOL
get_md4pw(char *md4pw
, char *mach_acct
)
169 SAM_ACCOUNT
*sampass
= NULL
;
176 * Currently this code is redundent as we already have a filter
177 * by hostname list. What this code really needs to do is to
178 * get a hosts allowed/hosts denied list from the SAM database
179 * on a per user basis, and make the access decision there.
180 * I will leave this code here for now as a reminder to implement
181 * this at a later date. JRA.
184 if (!allow_access(lp_domain_hostsdeny(), lp_domain_hostsallow(),
185 client_name(), client_addr()))
187 DEBUG(0,("get_md4pw: Workstation %s denied access to domain\n", mach_acct
));
192 if(!NT_STATUS_IS_OK(pdb_init_sam(&sampass
)))
195 /* JRA. This is ok as it is only used for generating the challenge. */
197 ret
=pdb_getsampwnam(sampass
, mach_acct
);
201 DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct
));
202 pdb_free_sam(&sampass
);
206 acct_ctrl
= pdb_get_acct_ctrl(sampass
);
207 if (!(acct_ctrl
& ACB_DISABLED
) &&
208 ((acct_ctrl
& ACB_DOMTRUST
) ||
209 (acct_ctrl
& ACB_WSTRUST
) ||
210 (acct_ctrl
& ACB_SVRTRUST
)) &&
211 ((pass
=pdb_get_nt_passwd(sampass
)) != NULL
)) {
212 memcpy(md4pw
, pass
, 16);
213 dump_data(5, md4pw
, 16);
214 pdb_free_sam(&sampass
);
218 DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct
));
219 pdb_free_sam(&sampass
);
224 /*************************************************************************
226 *************************************************************************/
228 NTSTATUS
_net_req_chal(pipes_struct
*p
, NET_Q_REQ_CHAL
*q_u
, NET_R_REQ_CHAL
*r_u
)
230 NTSTATUS status
= NT_STATUS_OK
;
232 rpcstr_pull(p
->dc
.remote_machine
,q_u
->uni_logon_clnt
.buffer
,sizeof(fstring
),q_u
->uni_logon_clnt
.uni_str_len
*2,0);
234 /* create a server challenge for the client */
235 /* Set these to random values. */
236 generate_random_buffer(p
->dc
.srv_chal
.data
, 8, False
);
238 memcpy(p
->dc
.srv_cred
.challenge
.data
, p
->dc
.srv_chal
.data
, 8);
240 memcpy(p
->dc
.clnt_chal
.data
, q_u
->clnt_chal
.data
, sizeof(q_u
->clnt_chal
.data
));
241 memcpy(p
->dc
.clnt_cred
.challenge
.data
, q_u
->clnt_chal
.data
, sizeof(q_u
->clnt_chal
.data
));
243 memset((char *)p
->dc
.sess_key
, '\0', sizeof(p
->dc
.sess_key
));
245 p
->dc
.challenge_sent
= True
;
246 /* set up the LSA REQUEST CHALLENGE response */
247 init_net_r_req_chal(r_u
, &p
->dc
.srv_chal
, status
);
252 /*************************************************************************
254 *************************************************************************/
256 static void init_net_r_auth(NET_R_AUTH
*r_a
, DOM_CHAL
*resp_cred
, NTSTATUS status
)
258 memcpy(r_a
->srv_chal
.data
, resp_cred
->data
, sizeof(resp_cred
->data
));
259 r_a
->status
= status
;
262 /*************************************************************************
264 *************************************************************************/
266 NTSTATUS
_net_auth(pipes_struct
*p
, NET_Q_AUTH
*q_u
, NET_R_AUTH
*r_u
)
268 NTSTATUS status
= NT_STATUS_OK
;
275 rpcstr_pull(mach_acct
, q_u
->clnt_id
.uni_acct_name
.buffer
,sizeof(fstring
),q_u
->clnt_id
.uni_acct_name
.uni_str_len
*2,0);
277 if (p
->dc
.challenge_sent
&& get_md4pw((char *)p
->dc
.md4pw
, mach_acct
)) {
279 /* from client / server challenges and md4 password, generate sess key */
280 cred_session_key(&p
->dc
.clnt_chal
, &p
->dc
.srv_chal
,
281 p
->dc
.md4pw
, p
->dc
.sess_key
);
283 /* check that the client credentials are valid */
284 if (cred_assert(&q_u
->clnt_chal
, p
->dc
.sess_key
, &p
->dc
.clnt_cred
.challenge
, srv_time
)) {
286 /* create server challenge for inclusion in the reply */
287 cred_create(p
->dc
.sess_key
, &p
->dc
.srv_cred
.challenge
, srv_time
, &srv_cred
);
289 /* copy the received client credentials for use next time */
290 memcpy(p
->dc
.clnt_cred
.challenge
.data
, q_u
->clnt_chal
.data
, sizeof(q_u
->clnt_chal
.data
));
291 memcpy(p
->dc
.srv_cred
.challenge
.data
, q_u
->clnt_chal
.data
, sizeof(q_u
->clnt_chal
.data
));
293 /* Save the machine account name. */
294 fstrcpy(p
->dc
.mach_acct
, mach_acct
);
296 p
->dc
.authenticated
= True
;
299 status
= NT_STATUS_ACCESS_DENIED
;
302 status
= NT_STATUS_ACCESS_DENIED
;
305 /* set up the LSA AUTH response */
306 init_net_r_auth(r_u
, &srv_cred
, status
);
311 /*************************************************************************
313 *************************************************************************/
315 static void init_net_r_auth_2(NET_R_AUTH_2
*r_a
,
316 DOM_CHAL
*resp_cred
, NEG_FLAGS
*flgs
, NTSTATUS status
)
318 memcpy(r_a
->srv_chal
.data
, resp_cred
->data
, sizeof(resp_cred
->data
));
319 memcpy(&r_a
->srv_flgs
, flgs
, sizeof(r_a
->srv_flgs
));
320 r_a
->status
= status
;
323 /*************************************************************************
325 *************************************************************************/
327 NTSTATUS
_net_auth_2(pipes_struct
*p
, NET_Q_AUTH_2
*q_u
, NET_R_AUTH_2
*r_u
)
329 NTSTATUS status
= NT_STATUS_OK
;
337 if ( (lp_server_schannel() == True
) &&
338 ((q_u
->clnt_flgs
.neg_flags
& NETLOGON_NEG_SCHANNEL
) == 0) ) {
340 /* schannel must be used, but client did not offer it. */
341 status
= NT_STATUS_ACCESS_DENIED
;
344 rpcstr_pull(mach_acct
, q_u
->clnt_id
.uni_acct_name
.buffer
,sizeof(fstring
),q_u
->clnt_id
.uni_acct_name
.uni_str_len
*2,0);
346 if (p
->dc
.challenge_sent
&& get_md4pw((char *)p
->dc
.md4pw
, mach_acct
)) {
348 /* from client / server challenges and md4 password, generate sess key */
349 cred_session_key(&p
->dc
.clnt_chal
, &p
->dc
.srv_chal
,
350 p
->dc
.md4pw
, p
->dc
.sess_key
);
352 /* check that the client credentials are valid */
353 if (cred_assert(&q_u
->clnt_chal
, p
->dc
.sess_key
, &p
->dc
.clnt_cred
.challenge
, srv_time
)) {
355 /* create server challenge for inclusion in the reply */
356 cred_create(p
->dc
.sess_key
, &p
->dc
.srv_cred
.challenge
, srv_time
, &srv_cred
);
358 /* copy the received client credentials for use next time */
359 memcpy(p
->dc
.clnt_cred
.challenge
.data
, q_u
->clnt_chal
.data
, sizeof(q_u
->clnt_chal
.data
));
360 memcpy(p
->dc
.srv_cred
.challenge
.data
, q_u
->clnt_chal
.data
, sizeof(q_u
->clnt_chal
.data
));
362 /* Save the machine account name. */
363 fstrcpy(p
->dc
.mach_acct
, mach_acct
);
365 p
->dc
.authenticated
= True
;
368 status
= NT_STATUS_ACCESS_DENIED
;
371 status
= NT_STATUS_ACCESS_DENIED
;
374 srv_flgs
.neg_flags
= 0x000001ff;
376 if (lp_server_schannel() != False
) {
377 srv_flgs
.neg_flags
|= NETLOGON_NEG_SCHANNEL
;
380 /* set up the LSA AUTH 2 response */
381 init_net_r_auth_2(r_u
, &srv_cred
, &srv_flgs
, status
);
383 if (NT_STATUS_IS_OK(status
)) {
384 extern struct dcinfo last_dcinfo
;
391 /*************************************************************************
393 *************************************************************************/
395 NTSTATUS
_net_srv_pwset(pipes_struct
*p
, NET_Q_SRV_PWSET
*q_u
, NET_R_SRV_PWSET
*r_u
)
397 NTSTATUS status
= NT_STATUS_ACCESS_DENIED
;
400 SAM_ACCOUNT
*sampass
=NULL
;
402 unsigned char pwd
[16];
406 /* checks and updates credentials. creates reply credentials */
407 if (!(p
->dc
.authenticated
&& deal_with_creds(p
->dc
.sess_key
, &p
->dc
.clnt_cred
, &q_u
->clnt_id
.cred
, &srv_cred
)))
408 return NT_STATUS_INVALID_HANDLE
;
410 memcpy(&p
->dc
.srv_cred
, &p
->dc
.clnt_cred
, sizeof(p
->dc
.clnt_cred
));
412 DEBUG(5,("_net_srv_pwset: %d\n", __LINE__
));
414 rpcstr_pull(workstation
,q_u
->clnt_id
.login
.uni_comp_name
.buffer
,
415 sizeof(workstation
),q_u
->clnt_id
.login
.uni_comp_name
.uni_str_len
*2,0);
417 DEBUG(3,("Server Password Set by Wksta:[%s] on account [%s]\n", workstation
, p
->dc
.mach_acct
));
419 pdb_init_sam(&sampass
);
422 ret
=pdb_getsampwnam(sampass
, p
->dc
.mach_acct
);
425 /* Ensure the account exists and is a machine account. */
427 acct_ctrl
= pdb_get_acct_ctrl(sampass
);
430 && (acct_ctrl
& ACB_WSTRUST
||
431 acct_ctrl
& ACB_SVRTRUST
||
432 acct_ctrl
& ACB_DOMTRUST
))) {
433 pdb_free_sam(&sampass
);
434 return NT_STATUS_NO_SUCH_USER
;
437 if (pdb_get_acct_ctrl(sampass
) & ACB_DISABLED
) {
438 pdb_free_sam(&sampass
);
439 return NT_STATUS_ACCOUNT_DISABLED
;
442 DEBUG(100,("Server password set : new given value was :\n"));
443 for(i
= 0; i
< 16; i
++)
444 DEBUG(100,("%02X ", q_u
->pwd
[i
]));
447 cred_hash3( pwd
, q_u
->pwd
, p
->dc
.sess_key
, 0);
449 /* lies! nt and lm passwords are _not_ the same: don't care */
450 if (!pdb_set_lanman_passwd (sampass
, pwd
, PDB_CHANGED
)) {
451 pdb_free_sam(&sampass
);
452 return NT_STATUS_NO_MEMORY
;
455 if (!pdb_set_nt_passwd (sampass
, pwd
, PDB_CHANGED
)) {
456 pdb_free_sam(&sampass
);
457 return NT_STATUS_NO_MEMORY
;
460 if (!pdb_set_pass_changed_now (sampass
)) {
461 pdb_free_sam(&sampass
);
462 /* Not quite sure what this one qualifies as, but this will do */
463 return NT_STATUS_UNSUCCESSFUL
;
467 ret
= pdb_update_sam_account (sampass
);
471 status
= NT_STATUS_OK
;
473 /* set up the LSA Server Password Set response */
474 init_net_r_srv_pwset(r_u
, &srv_cred
, status
);
476 pdb_free_sam(&sampass
);
481 /*************************************************************************
483 *************************************************************************/
485 NTSTATUS
_net_sam_logoff(pipes_struct
*p
, NET_Q_SAM_LOGOFF
*q_u
, NET_R_SAM_LOGOFF
*r_u
)
489 if (!get_valid_user_struct(p
->vuid
))
490 return NT_STATUS_NO_SUCH_USER
;
492 /* checks and updates credentials. creates reply credentials */
493 if (!(p
->dc
.authenticated
&& deal_with_creds(p
->dc
.sess_key
, &p
->dc
.clnt_cred
,
494 &q_u
->sam_id
.client
.cred
, &srv_cred
)))
495 return NT_STATUS_INVALID_HANDLE
;
497 memcpy(&p
->dc
.srv_cred
, &p
->dc
.clnt_cred
, sizeof(p
->dc
.clnt_cred
));
499 /* XXXX maybe we want to say 'no', reject the client's credentials */
500 r_u
->buffer_creds
= 1; /* yes, we have valid server credentials */
501 memcpy(&r_u
->srv_creds
, &srv_cred
, sizeof(r_u
->srv_creds
));
503 r_u
->status
= NT_STATUS_OK
;
509 /*************************************************************************
511 *************************************************************************/
513 NTSTATUS
_net_sam_logon(pipes_struct
*p
, NET_Q_SAM_LOGON
*q_u
, NET_R_SAM_LOGON
*r_u
)
515 NTSTATUS status
= NT_STATUS_OK
;
516 NET_USER_INFO_3
*usr_info
= NULL
;
517 NET_ID_INFO_CTR
*ctr
= q_u
->sam_id
.ctr
;
519 UNISTR2
*uni_samlogon_user
= NULL
;
520 UNISTR2
*uni_samlogon_domain
= NULL
;
521 UNISTR2
*uni_samlogon_workstation
= NULL
;
522 fstring nt_username
, nt_domain
, nt_workstation
;
523 auth_usersupplied_info
*user_info
= NULL
;
524 auth_serversupplied_info
*server_info
= NULL
;
525 extern userdom_struct current_user_info
;
527 struct auth_context
*auth_context
= NULL
;
529 usr_info
= (NET_USER_INFO_3
*)talloc(p
->mem_ctx
, sizeof(NET_USER_INFO_3
));
531 return NT_STATUS_NO_MEMORY
;
533 ZERO_STRUCTP(usr_info
);
535 /* store the user information, if there is any. */
536 r_u
->user
= usr_info
;
537 r_u
->switch_value
= 0; /* indicates no info */
538 r_u
->auth_resp
= 1; /* authoritative response */
539 r_u
->switch_value
= 3; /* indicates type of validation user info */
541 if (!get_valid_user_struct(p
->vuid
))
542 return NT_STATUS_NO_SUCH_USER
;
545 if ( (lp_server_schannel() == True
) && (!p
->netsec_auth_validated
) ) {
546 /* 'server schannel = yes' should enforce use of
547 schannel, the client did offer it in auth2, but
548 obviously did not use it. */
549 return NT_STATUS_ACCESS_DENIED
;
552 /* checks and updates credentials. creates reply credentials */
553 if (!(p
->dc
.authenticated
&& deal_with_creds(p
->dc
.sess_key
, &p
->dc
.clnt_cred
, &q_u
->sam_id
.client
.cred
, &srv_cred
)))
554 return NT_STATUS_INVALID_HANDLE
;
556 memcpy(&p
->dc
.srv_cred
, &p
->dc
.clnt_cred
, sizeof(p
->dc
.clnt_cred
));
558 r_u
->buffer_creds
= 1; /* yes, we have valid server credentials */
559 memcpy(&r_u
->srv_creds
, &srv_cred
, sizeof(r_u
->srv_creds
));
561 /* find the username */
563 switch (q_u
->sam_id
.logon_level
) {
564 case INTERACTIVE_LOGON_TYPE
:
565 uni_samlogon_user
= &ctr
->auth
.id1
.uni_user_name
;
566 uni_samlogon_domain
= &ctr
->auth
.id1
.uni_domain_name
;
568 uni_samlogon_workstation
= &ctr
->auth
.id1
.uni_wksta_name
;
570 DEBUG(3,("SAM Logon (Interactive). Domain:[%s]. ", lp_workgroup()));
573 uni_samlogon_user
= &ctr
->auth
.id2
.uni_user_name
;
574 uni_samlogon_domain
= &ctr
->auth
.id2
.uni_domain_name
;
575 uni_samlogon_workstation
= &ctr
->auth
.id2
.uni_wksta_name
;
577 DEBUG(3,("SAM Logon (Network). Domain:[%s]. ", lp_workgroup()));
580 DEBUG(2,("SAM Logon: unsupported switch value\n"));
581 return NT_STATUS_INVALID_INFO_CLASS
;
584 rpcstr_pull(nt_username
,uni_samlogon_user
->buffer
,sizeof(nt_username
),uni_samlogon_user
->uni_str_len
*2,0);
585 rpcstr_pull(nt_domain
,uni_samlogon_domain
->buffer
,sizeof(nt_domain
),uni_samlogon_domain
->uni_str_len
*2,0);
586 rpcstr_pull(nt_workstation
,uni_samlogon_workstation
->buffer
,sizeof(nt_workstation
),uni_samlogon_workstation
->uni_str_len
*2,0);
588 DEBUG(3,("User:[%s@%s] Requested Domain:[%s]\n", nt_username
,
589 nt_workstation
, nt_domain
));
591 fstrcpy(current_user_info
.smb_name
, nt_username
);
592 sub_set_smb_name(nt_username
);
594 DEBUG(5,("Attempting validation level %d for unmapped username %s.\n", q_u
->sam_id
.ctr
->switch_value
, nt_username
));
596 status
= NT_STATUS_OK
;
598 switch (ctr
->switch_value
) {
601 if (!NT_STATUS_IS_OK(status
= make_auth_context_fixed(&auth_context
, ctr
->auth
.id2
.lm_chal
))) {
605 /* Standard challenge/response authenticaion */
606 if (!make_user_info_netlogon_network(&user_info
,
607 nt_username
, nt_domain
,
609 ctr
->auth
.id2
.lm_chal_resp
.buffer
,
610 ctr
->auth
.id2
.lm_chal_resp
.str_str_len
,
611 ctr
->auth
.id2
.nt_chal_resp
.buffer
,
612 ctr
->auth
.id2
.nt_chal_resp
.str_str_len
)) {
613 status
= NT_STATUS_NO_MEMORY
;
617 case INTERACTIVE_LOGON_TYPE
:
618 /* 'Interactive' autheticaion, supplies the password in its
619 MD4 form, encrypted with the session key. We will
620 convert this to chellange/responce for the auth
621 subsystem to chew on */
625 if (!NT_STATUS_IS_OK(status
= make_auth_context_subsystem(&auth_context
))) {
629 chal
= auth_context
->get_ntlm_challenge(auth_context
);
631 if (!make_user_info_netlogon_interactive(&user_info
,
632 nt_username
, nt_domain
,
633 nt_workstation
, chal
,
634 ctr
->auth
.id1
.lm_owf
.data
,
635 ctr
->auth
.id1
.nt_owf
.data
,
637 status
= NT_STATUS_NO_MEMORY
;
642 DEBUG(2,("SAM Logon: unsupported switch value\n"));
643 return NT_STATUS_INVALID_INFO_CLASS
;
646 if ( NT_STATUS_IS_OK(status
) ) {
647 status
= auth_context
->check_ntlm_password(auth_context
,
648 user_info
, &server_info
);
651 (auth_context
->free
)(&auth_context
);
652 free_user_info(&user_info
);
654 DEBUG(5, ("_net_sam_logon: check_password returned status %s\n",
657 /* Check account and password */
659 if (!NT_STATUS_IS_OK(status
)) {
660 free_server_info(&server_info
);
664 if (server_info
->guest
) {
665 /* We don't like guest domain logons... */
666 DEBUG(5,("_net_sam_logon: Attempted domain logon as GUEST denied.\n"));
667 free_server_info(&server_info
);
668 return NT_STATUS_LOGON_FAILURE
;
671 /* This is the point at which, if the login was successful, that
672 the SAM Local Security Authority should record that the user is
673 logged in to the domain. */
676 DOM_GID
*gids
= NULL
;
677 const DOM_SID
*user_sid
= NULL
;
678 const DOM_SID
*group_sid
= NULL
;
680 uint32 user_rid
, group_rid
;
684 fstring user_sid_string
;
685 fstring group_sid_string
;
686 uchar nt_session_key
[16];
687 uchar lm_session_key
[16];
688 uchar netlogon_sess_key
[16];
690 sampw
= server_info
->sam_account
;
692 /* set up pointer indicating user/password failed to be found */
693 usr_info
->ptr_user_info
= 0;
695 user_sid
= pdb_get_user_sid(sampw
);
696 group_sid
= pdb_get_group_sid(sampw
);
698 sid_copy(&domain_sid
, user_sid
);
699 sid_split_rid(&domain_sid
, &user_rid
);
701 if (!sid_peek_check_rid(&domain_sid
, group_sid
, &group_rid
)) {
702 DEBUG(1, ("_net_sam_logon: user %s\\%s has user sid %s\n but group sid %s.\nThe conflicting domain portions are not supported for NETLOGON calls\n",
703 pdb_get_domain(sampw
), pdb_get_username(sampw
),
704 sid_to_string(user_sid_string
, user_sid
),
705 sid_to_string(group_sid_string
, group_sid
)));
706 return NT_STATUS_UNSUCCESSFUL
;
709 pstrcpy(my_name
, global_myname());
711 if (!NT_STATUS_IS_OK(status
712 = nt_token_to_group_list(p
->mem_ctx
,
720 ZERO_STRUCT(netlogon_sess_key
);
721 memcpy(netlogon_sess_key
, p
->dc
.sess_key
, 8);
722 if (server_info
->nt_session_key
.length
) {
723 memcpy(nt_session_key
, server_info
->nt_session_key
.data
,
724 MIN(sizeof(nt_session_key
), server_info
->nt_session_key
.length
));
725 SamOEMhash(nt_session_key
, netlogon_sess_key
, 16);
727 if (server_info
->lm_session_key
.length
) {
728 memcpy(lm_session_key
, server_info
->lm_session_key
.data
,
729 MIN(sizeof(lm_session_key
), server_info
->lm_session_key
.length
));
730 SamOEMhash(lm_session_key
, netlogon_sess_key
, 16);
732 ZERO_STRUCT(netlogon_sess_key
);
734 init_net_user_info3(p
->mem_ctx
, usr_info
,
737 pdb_get_username(sampw
),
738 pdb_get_fullname(sampw
),
739 pdb_get_homedir(sampw
),
740 pdb_get_dir_drive(sampw
),
741 pdb_get_logon_script(sampw
),
742 pdb_get_profile_path(sampw
),
743 pdb_get_logon_time(sampw
),
746 pdb_get_pass_last_set_time(sampw
),
747 pdb_get_pass_can_change_time(sampw
),
748 pdb_get_pass_must_change_time(sampw
),
751 0, /* bad_pw_count */
752 num_gids
, /* uint32 num_groups */
753 gids
, /* DOM_GID *gids */
754 0x20 , /* uint32 user_flgs (?) */
755 server_info
->nt_session_key
.length
? nt_session_key
: NULL
,
756 server_info
->lm_session_key
.length
? lm_session_key
: NULL
,
757 my_name
, /* char *logon_srv */
758 pdb_get_domain(sampw
),
759 &domain_sid
, /* DOM_SID *dom_sid */
760 /* Should be users domain sid, not servers - for trusted domains */
762 NULL
); /* char *other_sids */
763 ZERO_STRUCT(nt_session_key
);
764 ZERO_STRUCT(lm_session_key
);
766 free_server_info(&server_info
);
770 /*************************************************************************
772 *************************************************************************/
773 NTSTATUS
_ds_enum_dom_trusts(pipes_struct
*p
, DS_Q_ENUM_DOM_TRUSTS
*q_u
,
774 DS_R_ENUM_DOM_TRUSTS
*r_u
)
776 NTSTATUS status
= NT_STATUS_OK
;
778 /* We just return zero trusts for now. At least that way we're
779 consistent with NetTrustedDomainList which is what the fallback
780 for this function is. Both of these functions need to be