Remove unused rpc_ds marshalling code that is unused now.
[Samba/gebeck_regimport.git] / source / rpc_server / srv_netlog_nt.c
blob5003af8ce78d6044beb460bdc908602b1128474c
1 /*
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 3 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, see <http://www.gnu.org/licenses/>.
24 /* This is the implementation of the netlogon pipe. */
26 #include "includes.h"
28 extern userdom_struct current_user_info;
30 #undef DBGC_CLASS
31 #define DBGC_CLASS DBGC_RPC_SRV
33 /*************************************************************************
34 init_net_r_req_chal:
35 *************************************************************************/
37 static void init_net_r_req_chal(NET_R_REQ_CHAL *r_c,
38 DOM_CHAL *srv_chal, NTSTATUS status)
40 DEBUG(6,("init_net_r_req_chal: %d\n", __LINE__));
41 memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(srv_chal->data));
42 r_c->status = status;
45 /*************************************************************************
46 error messages cropping up when using nltest.exe...
47 *************************************************************************/
49 #define ERROR_NO_SUCH_DOMAIN 0x54b
50 #define ERROR_NO_LOGON_SERVERS 0x51f
51 #define NO_ERROR 0x0
53 /*************************************************************************
54 net_reply_logon_ctrl:
55 *************************************************************************/
57 NTSTATUS _net_logon_ctrl(pipes_struct *p, NET_Q_LOGON_CTRL *q_u,
58 NET_R_LOGON_CTRL *r_u)
60 uint32 flags = 0x0;
61 uint32 pdc_connection_status = 0x00; /* Maybe a win32 error code? */
63 /* Setup the Logon Control response */
65 init_net_r_logon_ctrl(r_u, q_u->query_level, flags,
66 pdc_connection_status);
68 return r_u->status;
71 /****************************************************************************
72 Send a message to smbd to do a sam synchronisation
73 **************************************************************************/
75 static void send_sync_message(void)
77 DEBUG(3, ("sending sam synchronisation message\n"));
78 message_send_all(smbd_messaging_context(), MSG_SMB_SAM_SYNC, NULL, 0,
79 NULL);
82 /*************************************************************************
83 net_reply_logon_ctrl2:
84 *************************************************************************/
86 NTSTATUS _net_logon_ctrl2(pipes_struct *p, NET_Q_LOGON_CTRL2 *q_u, NET_R_LOGON_CTRL2 *r_u)
88 uint32 flags = 0x0;
89 uint32 pdc_connection_status = 0x0;
90 uint32 logon_attempts = 0x0;
91 uint32 tc_status;
92 fstring servername, domain, dc_name, dc_name2;
93 struct sockaddr_storage dc_ss;
95 /* this should be \\global_myname() */
96 unistr2_to_ascii(servername, &q_u->uni_server_name, sizeof(servername));
98 r_u->status = NT_STATUS_OK;
100 tc_status = ERROR_NO_SUCH_DOMAIN;
101 fstrcpy( dc_name, "" );
103 switch ( q_u->function_code ) {
104 case NETLOGON_CONTROL_TC_QUERY:
105 unistr2_to_ascii(domain, &q_u->info.info6.domain, sizeof(domain));
107 if ( !is_trusted_domain( domain ) )
108 break;
110 if ( !get_dc_name( domain, NULL, dc_name2, &dc_ss ) ) {
111 tc_status = ERROR_NO_LOGON_SERVERS;
112 break;
115 fstr_sprintf( dc_name, "\\\\%s", dc_name2 );
117 tc_status = NO_ERROR;
119 break;
121 case NETLOGON_CONTROL_REDISCOVER:
122 unistr2_to_ascii(domain, &q_u->info.info6.domain, sizeof(domain));
124 if ( !is_trusted_domain( domain ) )
125 break;
127 if ( !get_dc_name( domain, NULL, dc_name2, &dc_ss ) ) {
128 tc_status = ERROR_NO_LOGON_SERVERS;
129 break;
132 fstr_sprintf( dc_name, "\\\\%s", dc_name2 );
134 tc_status = NO_ERROR;
136 break;
138 default:
139 /* no idea what this should be */
140 DEBUG(0,("_net_logon_ctrl2: unimplemented function level [%d]\n",
141 q_u->function_code));
144 /* prepare the response */
146 init_net_r_logon_ctrl2( r_u, q_u->query_level, flags,
147 pdc_connection_status, logon_attempts, tc_status, dc_name );
149 if (lp_server_role() == ROLE_DOMAIN_BDC)
150 send_sync_message();
152 return r_u->status;
155 /*************************************************************************
156 net_reply_trust_dom_list:
157 *************************************************************************/
159 NTSTATUS _net_trust_dom_list(pipes_struct *p, NET_Q_TRUST_DOM_LIST *q_u, NET_R_TRUST_DOM_LIST *r_u)
161 const char *trusted_domain = "test_domain";
162 uint32 num_trust_domains = 1;
164 DEBUG(6,("_net_trust_dom_list: %d\n", __LINE__));
166 /* set up the Trusted Domain List response */
167 init_r_trust_dom(r_u, num_trust_domains, trusted_domain);
169 DEBUG(6,("_net_trust_dom_list: %d\n", __LINE__));
171 return r_u->status;
174 /***********************************************************************************
175 init_net_r_srv_pwset:
176 ***********************************************************************************/
178 static void init_net_r_srv_pwset(NET_R_SRV_PWSET *r_s,
179 DOM_CRED *srv_cred, NTSTATUS status)
181 DEBUG(5,("init_net_r_srv_pwset: %d\n", __LINE__));
183 memcpy(&r_s->srv_cred, srv_cred, sizeof(r_s->srv_cred));
184 r_s->status = status;
186 DEBUG(5,("init_net_r_srv_pwset: %d\n", __LINE__));
189 /******************************************************************
190 gets a machine password entry. checks access rights of the host.
191 ******************************************************************/
193 static NTSTATUS get_md4pw(char *md4pw, char *mach_acct, uint16 sec_chan_type)
195 struct samu *sampass = NULL;
196 const uint8 *pass;
197 bool ret;
198 uint32 acct_ctrl;
200 #if 0
201 char addr[INET6_ADDRSTRLEN];
204 * Currently this code is redundent as we already have a filter
205 * by hostname list. What this code really needs to do is to
206 * get a hosts allowed/hosts denied list from the SAM database
207 * on a per user basis, and make the access decision there.
208 * I will leave this code here for now as a reminder to implement
209 * this at a later date. JRA.
212 if (!allow_access(lp_domain_hostsdeny(), lp_domain_hostsallow(),
213 client_name(get_client_fd()),
214 client_addr(get_client_fd(),addr,sizeof(addr)))) {
215 DEBUG(0,("get_md4pw: Workstation %s denied access to domain\n", mach_acct));
216 return False;
218 #endif /* 0 */
220 if ( !(sampass = samu_new( NULL )) ) {
221 return NT_STATUS_NO_MEMORY;
224 /* JRA. This is ok as it is only used for generating the challenge. */
225 become_root();
226 ret = pdb_getsampwnam(sampass, mach_acct);
227 unbecome_root();
229 if (!ret) {
230 DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct));
231 TALLOC_FREE(sampass);
232 return NT_STATUS_ACCESS_DENIED;
235 acct_ctrl = pdb_get_acct_ctrl(sampass);
236 if (acct_ctrl & ACB_DISABLED) {
237 DEBUG(0,("get_md4pw: Workstation %s: account is disabled\n", mach_acct));
238 TALLOC_FREE(sampass);
239 return NT_STATUS_ACCOUNT_DISABLED;
242 if (!(acct_ctrl & ACB_SVRTRUST) &&
243 !(acct_ctrl & ACB_WSTRUST) &&
244 !(acct_ctrl & ACB_DOMTRUST))
246 DEBUG(0,("get_md4pw: Workstation %s: account is not a trust account\n", mach_acct));
247 TALLOC_FREE(sampass);
248 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
251 switch (sec_chan_type) {
252 case SEC_CHAN_BDC:
253 if (!(acct_ctrl & ACB_SVRTRUST)) {
254 DEBUG(0,("get_md4pw: Workstation %s: BDC secure channel requested "
255 "but not a server trust account\n", mach_acct));
256 TALLOC_FREE(sampass);
257 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
259 break;
260 case SEC_CHAN_WKSTA:
261 if (!(acct_ctrl & ACB_WSTRUST)) {
262 DEBUG(0,("get_md4pw: Workstation %s: WORKSTATION secure channel requested "
263 "but not a workstation trust account\n", mach_acct));
264 TALLOC_FREE(sampass);
265 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
267 break;
268 case SEC_CHAN_DOMAIN:
269 if (!(acct_ctrl & ACB_DOMTRUST)) {
270 DEBUG(0,("get_md4pw: Workstation %s: DOMAIN secure channel requested "
271 "but not a interdomain trust account\n", mach_acct));
272 TALLOC_FREE(sampass);
273 return NT_STATUS_NO_TRUST_SAM_ACCOUNT;
275 break;
276 default:
277 break;
280 if ((pass = pdb_get_nt_passwd(sampass)) == NULL) {
281 DEBUG(0,("get_md4pw: Workstation %s: account does not have a password\n", mach_acct));
282 TALLOC_FREE(sampass);
283 return NT_STATUS_LOGON_FAILURE;
286 memcpy(md4pw, pass, 16);
287 dump_data(5, (uint8 *)md4pw, 16);
289 TALLOC_FREE(sampass);
291 return NT_STATUS_OK;
296 /*************************************************************************
297 _net_req_chal
298 *************************************************************************/
300 NTSTATUS _net_req_chal(pipes_struct *p, NET_Q_REQ_CHAL *q_u, NET_R_REQ_CHAL *r_u)
302 if (!p->dc) {
303 p->dc = TALLOC_ZERO_P(p->pipe_state_mem_ctx, struct dcinfo);
304 if (!p->dc) {
305 return NT_STATUS_NO_MEMORY;
307 } else {
308 DEBUG(10,("_net_req_chal: new challenge requested. Clearing old state.\n"));
309 ZERO_STRUCTP(p->dc);
312 rpcstr_pull(p->dc->remote_machine,
313 q_u->uni_logon_clnt.buffer,
314 sizeof(fstring),q_u->uni_logon_clnt.uni_str_len*2,0);
316 /* Save the client challenge to the server. */
317 memcpy(p->dc->clnt_chal.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
319 /* Create a server challenge for the client */
320 /* Set this to a random value. */
321 generate_random_buffer(p->dc->srv_chal.data, 8);
323 /* set up the LSA REQUEST CHALLENGE response */
324 init_net_r_req_chal(r_u, &p->dc->srv_chal, NT_STATUS_OK);
326 p->dc->challenge_sent = True;
328 return NT_STATUS_OK;
331 /*************************************************************************
332 init_net_r_auth:
333 *************************************************************************/
335 static void init_net_r_auth(NET_R_AUTH *r_a, DOM_CHAL *resp_cred, NTSTATUS status)
337 memcpy(r_a->srv_chal.data, resp_cred->data, sizeof(resp_cred->data));
338 r_a->status = status;
341 /*************************************************************************
342 _net_auth. Create the initial credentials.
343 *************************************************************************/
345 NTSTATUS _net_auth(pipes_struct *p, NET_Q_AUTH *q_u, NET_R_AUTH *r_u)
347 NTSTATUS status;
348 fstring mach_acct;
349 fstring remote_machine;
350 DOM_CHAL srv_chal_out;
352 if (!p->dc || !p->dc->challenge_sent) {
353 return NT_STATUS_ACCESS_DENIED;
356 rpcstr_pull(mach_acct, q_u->clnt_id.uni_acct_name.buffer,sizeof(fstring),
357 q_u->clnt_id.uni_acct_name.uni_str_len*2,0);
358 rpcstr_pull(remote_machine, q_u->clnt_id.uni_comp_name.buffer,sizeof(fstring),
359 q_u->clnt_id.uni_comp_name.uni_str_len*2,0);
361 status = get_md4pw((char *)p->dc->mach_pw, mach_acct, q_u->clnt_id.sec_chan);
362 if (!NT_STATUS_IS_OK(status)) {
363 DEBUG(0,("_net_auth: creds_server_check failed. Failed to "
364 "get password for machine account %s "
365 "from client %s: %s\n",
366 mach_acct, remote_machine, nt_errstr(status) ));
367 /* always return NT_STATUS_ACCESS_DENIED */
368 return NT_STATUS_ACCESS_DENIED;
371 /* From the client / server challenges and md4 password, generate sess key */
372 creds_server_init(0, /* No neg flags. */
373 p->dc,
374 &p->dc->clnt_chal, /* Stored client chal. */
375 &p->dc->srv_chal, /* Stored server chal. */
376 p->dc->mach_pw,
377 &srv_chal_out);
379 /* Check client credentials are valid. */
380 if (!creds_server_check(p->dc, &q_u->clnt_chal)) {
381 DEBUG(0,("_net_auth: creds_server_check failed. Rejecting auth "
382 "request from client %s machine account %s\n",
383 remote_machine, mach_acct ));
384 return NT_STATUS_ACCESS_DENIED;
387 fstrcpy(p->dc->mach_acct, mach_acct);
388 fstrcpy(p->dc->remote_machine, remote_machine);
389 p->dc->authenticated = True;
391 /* set up the LSA AUTH response */
392 /* Return the server credentials. */
393 init_net_r_auth(r_u, &srv_chal_out, NT_STATUS_OK);
395 return r_u->status;
398 /*************************************************************************
399 init_net_r_auth_2:
400 *************************************************************************/
402 static void init_net_r_auth_2(NET_R_AUTH_2 *r_a,
403 DOM_CHAL *resp_cred, NEG_FLAGS *flgs, NTSTATUS status)
405 memcpy(r_a->srv_chal.data, resp_cred->data, sizeof(resp_cred->data));
406 memcpy(&r_a->srv_flgs, flgs, sizeof(r_a->srv_flgs));
407 r_a->status = status;
410 /*************************************************************************
411 _net_auth_2
412 *************************************************************************/
414 NTSTATUS _net_auth_2(pipes_struct *p, NET_Q_AUTH_2 *q_u, NET_R_AUTH_2 *r_u)
416 NTSTATUS status;
417 NEG_FLAGS srv_flgs;
418 fstring mach_acct;
419 fstring remote_machine;
420 DOM_CHAL srv_chal_out;
422 rpcstr_pull(mach_acct, q_u->clnt_id.uni_acct_name.buffer,sizeof(fstring),
423 q_u->clnt_id.uni_acct_name.uni_str_len*2,0);
425 /* We use this as the key to store the creds. */
426 rpcstr_pull(remote_machine, q_u->clnt_id.uni_comp_name.buffer,sizeof(fstring),
427 q_u->clnt_id.uni_comp_name.uni_str_len*2,0);
429 if (!p->dc || !p->dc->challenge_sent) {
430 DEBUG(0,("_net_auth2: no challenge sent to client %s\n",
431 remote_machine ));
432 return NT_STATUS_ACCESS_DENIED;
435 if ( (lp_server_schannel() == True) &&
436 ((q_u->clnt_flgs.neg_flags & NETLOGON_NEG_SCHANNEL) == 0) ) {
438 /* schannel must be used, but client did not offer it. */
439 DEBUG(0,("_net_auth2: schannel required but client failed "
440 "to offer it. Client was %s\n",
441 mach_acct ));
442 return NT_STATUS_ACCESS_DENIED;
445 status = get_md4pw((char *)p->dc->mach_pw, mach_acct, q_u->clnt_id.sec_chan);
446 if (!NT_STATUS_IS_OK(status)) {
447 DEBUG(0,("_net_auth2: failed to get machine password for "
448 "account %s: %s\n",
449 mach_acct, nt_errstr(status) ));
450 /* always return NT_STATUS_ACCESS_DENIED */
451 return NT_STATUS_ACCESS_DENIED;
454 /* From the client / server challenges and md4 password, generate sess key */
455 creds_server_init(q_u->clnt_flgs.neg_flags,
456 p->dc,
457 &p->dc->clnt_chal, /* Stored client chal. */
458 &p->dc->srv_chal, /* Stored server chal. */
459 p->dc->mach_pw,
460 &srv_chal_out);
462 /* Check client credentials are valid. */
463 if (!creds_server_check(p->dc, &q_u->clnt_chal)) {
464 DEBUG(0,("_net_auth2: creds_server_check failed. Rejecting auth "
465 "request from client %s machine account %s\n",
466 remote_machine, mach_acct ));
467 return NT_STATUS_ACCESS_DENIED;
470 srv_flgs.neg_flags = 0x000001ff;
472 if (lp_server_schannel() != False) {
473 srv_flgs.neg_flags |= NETLOGON_NEG_SCHANNEL;
476 /* set up the LSA AUTH 2 response */
477 init_net_r_auth_2(r_u, &srv_chal_out, &srv_flgs, NT_STATUS_OK);
479 fstrcpy(p->dc->mach_acct, mach_acct);
480 fstrcpy(p->dc->remote_machine, remote_machine);
481 fstrcpy(p->dc->domain, lp_workgroup() );
483 p->dc->authenticated = True;
485 /* Store off the state so we can continue after client disconnect. */
486 become_root();
487 secrets_store_schannel_session_info(p->mem_ctx,
488 remote_machine,
489 p->dc);
490 unbecome_root();
492 return r_u->status;
495 /*************************************************************************
496 _net_srv_pwset
497 *************************************************************************/
499 NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *r_u)
501 fstring remote_machine;
502 struct samu *sampass=NULL;
503 bool ret = False;
504 unsigned char pwd[16];
505 int i;
506 uint32 acct_ctrl;
507 DOM_CRED cred_out;
508 const uchar *old_pw;
510 DEBUG(5,("_net_srv_pwset: %d\n", __LINE__));
512 /* We need the remote machine name for the creds lookup. */
513 rpcstr_pull(remote_machine,q_u->clnt_id.login.uni_comp_name.buffer,
514 sizeof(remote_machine),q_u->clnt_id.login.uni_comp_name.uni_str_len*2,0);
516 if ( (lp_server_schannel() == True) && (p->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) ) {
517 /* 'server schannel = yes' should enforce use of
518 schannel, the client did offer it in auth2, but
519 obviously did not use it. */
520 DEBUG(0,("_net_srv_pwset: client %s not using schannel for netlogon\n",
521 remote_machine ));
522 return NT_STATUS_ACCESS_DENIED;
525 if (!p->dc) {
526 /* Restore the saved state of the netlogon creds. */
527 become_root();
528 ret = secrets_restore_schannel_session_info(p->pipe_state_mem_ctx,
529 remote_machine,
530 &p->dc);
531 unbecome_root();
532 if (!ret) {
533 return NT_STATUS_INVALID_HANDLE;
537 if (!p->dc || !p->dc->authenticated) {
538 return NT_STATUS_INVALID_HANDLE;
541 DEBUG(3,("_net_srv_pwset: Server Password Set by remote machine:[%s] on account [%s]\n",
542 remote_machine, p->dc->mach_acct));
544 /* Step the creds chain forward. */
545 if (!creds_server_step(p->dc, &q_u->clnt_id.cred, &cred_out)) {
546 DEBUG(2,("_net_srv_pwset: creds_server_step failed. Rejecting auth "
547 "request from client %s machine account %s\n",
548 remote_machine, p->dc->mach_acct ));
549 return NT_STATUS_INVALID_PARAMETER;
552 /* We must store the creds state after an update. */
553 sampass = samu_new( NULL );
554 if (!sampass) {
555 return NT_STATUS_NO_MEMORY;
558 become_root();
559 secrets_store_schannel_session_info(p->pipe_state_mem_ctx,
560 remote_machine,
561 p->dc);
562 ret = pdb_getsampwnam(sampass, p->dc->mach_acct);
563 unbecome_root();
565 if (!ret) {
566 TALLOC_FREE(sampass);
567 return NT_STATUS_ACCESS_DENIED;
570 /* Ensure the account exists and is a machine account. */
572 acct_ctrl = pdb_get_acct_ctrl(sampass);
574 if (!(acct_ctrl & ACB_WSTRUST ||
575 acct_ctrl & ACB_SVRTRUST ||
576 acct_ctrl & ACB_DOMTRUST)) {
577 TALLOC_FREE(sampass);
578 return NT_STATUS_NO_SUCH_USER;
581 if (pdb_get_acct_ctrl(sampass) & ACB_DISABLED) {
582 TALLOC_FREE(sampass);
583 return NT_STATUS_ACCOUNT_DISABLED;
586 /* Woah - what does this to to the credential chain ? JRA */
587 cred_hash3( pwd, q_u->pwd, p->dc->sess_key, 0);
589 DEBUG(100,("Server password set : new given value was :\n"));
590 for(i = 0; i < sizeof(pwd); i++)
591 DEBUG(100,("%02X ", pwd[i]));
592 DEBUG(100,("\n"));
594 old_pw = pdb_get_nt_passwd(sampass);
596 if (old_pw && memcmp(pwd, old_pw, 16) == 0) {
597 /* Avoid backend modificiations and other fun if the
598 client changed the password to the *same thing* */
600 ret = True;
601 } else {
603 /* LM password should be NULL for machines */
604 if (!pdb_set_lanman_passwd(sampass, NULL, PDB_CHANGED)) {
605 TALLOC_FREE(sampass);
606 return NT_STATUS_NO_MEMORY;
609 if (!pdb_set_nt_passwd(sampass, pwd, PDB_CHANGED)) {
610 TALLOC_FREE(sampass);
611 return NT_STATUS_NO_MEMORY;
614 if (!pdb_set_pass_last_set_time(sampass, time(NULL), PDB_CHANGED)) {
615 TALLOC_FREE(sampass);
616 /* Not quite sure what this one qualifies as, but this will do */
617 return NT_STATUS_UNSUCCESSFUL;
620 become_root();
621 r_u->status = pdb_update_sam_account(sampass);
622 unbecome_root();
625 /* set up the LSA Server Password Set response */
626 init_net_r_srv_pwset(r_u, &cred_out, r_u->status);
628 TALLOC_FREE(sampass);
629 return r_u->status;
632 /*************************************************************************
633 _net_sam_logoff:
634 *************************************************************************/
636 NTSTATUS _net_sam_logoff(pipes_struct *p, NET_Q_SAM_LOGOFF *q_u, NET_R_SAM_LOGOFF *r_u)
638 fstring remote_machine;
640 if ( (lp_server_schannel() == True) && (p->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) ) {
641 /* 'server schannel = yes' should enforce use of
642 schannel, the client did offer it in auth2, but
643 obviously did not use it. */
644 DEBUG(0,("_net_sam_logoff: client %s not using schannel for netlogon\n",
645 get_remote_machine_name() ));
646 return NT_STATUS_ACCESS_DENIED;
650 if (!get_valid_user_struct(p->vuid))
651 return NT_STATUS_NO_SUCH_USER;
653 /* Get the remote machine name for the creds store. */
654 rpcstr_pull(remote_machine,q_u->sam_id.client.login.uni_comp_name.buffer,
655 sizeof(remote_machine),q_u->sam_id.client.login.uni_comp_name.uni_str_len*2,0);
657 if (!p->dc) {
658 /* Restore the saved state of the netlogon creds. */
659 bool ret;
661 become_root();
662 ret = secrets_restore_schannel_session_info(p->pipe_state_mem_ctx,
663 remote_machine,
664 &p->dc);
665 unbecome_root();
666 if (!ret) {
667 return NT_STATUS_INVALID_HANDLE;
671 if (!p->dc || !p->dc->authenticated) {
672 return NT_STATUS_INVALID_HANDLE;
675 r_u->buffer_creds = 1; /* yes, we have valid server credentials */
677 /* checks and updates credentials. creates reply credentials */
678 if (!creds_server_step(p->dc, &q_u->sam_id.client.cred, &r_u->srv_creds)) {
679 DEBUG(2,("_net_sam_logoff: creds_server_step failed. Rejecting auth "
680 "request from client %s machine account %s\n",
681 remote_machine, p->dc->mach_acct ));
682 return NT_STATUS_INVALID_PARAMETER;
685 /* We must store the creds state after an update. */
686 become_root();
687 secrets_store_schannel_session_info(p->pipe_state_mem_ctx,
688 remote_machine,
689 p->dc);
690 unbecome_root();
692 r_u->status = NT_STATUS_OK;
693 return r_u->status;
696 /*******************************************************************
697 gets a domain user's groups from their already-calculated NT_USER_TOKEN
698 ********************************************************************/
700 static NTSTATUS nt_token_to_group_list(TALLOC_CTX *mem_ctx,
701 const DOM_SID *domain_sid,
702 size_t num_sids,
703 const DOM_SID *sids,
704 int *numgroups, DOM_GID **pgids)
706 int i;
708 *numgroups=0;
709 *pgids = NULL;
711 for (i=0; i<num_sids; i++) {
712 DOM_GID gid;
713 if (!sid_peek_check_rid(domain_sid, &sids[i], &gid.g_rid)) {
714 continue;
716 gid.attr = (SE_GROUP_MANDATORY|SE_GROUP_ENABLED_BY_DEFAULT|
717 SE_GROUP_ENABLED);
718 ADD_TO_ARRAY(mem_ctx, DOM_GID, gid, pgids, numgroups);
719 if (*pgids == NULL) {
720 return NT_STATUS_NO_MEMORY;
723 return NT_STATUS_OK;
726 /*************************************************************************
727 _net_sam_logon
728 *************************************************************************/
730 static NTSTATUS _net_sam_logon_internal(pipes_struct *p,
731 NET_Q_SAM_LOGON *q_u,
732 NET_R_SAM_LOGON *r_u,
733 bool process_creds)
735 NTSTATUS status = NT_STATUS_OK;
736 NET_USER_INFO_3 *usr_info = NULL;
737 NET_ID_INFO_CTR *ctr = q_u->sam_id.ctr;
738 UNISTR2 *uni_samlogon_user = NULL;
739 UNISTR2 *uni_samlogon_domain = NULL;
740 UNISTR2 *uni_samlogon_workstation = NULL;
741 fstring nt_username, nt_domain, nt_workstation;
742 auth_usersupplied_info *user_info = NULL;
743 auth_serversupplied_info *server_info = NULL;
744 struct samu *sampw;
745 struct auth_context *auth_context = NULL;
747 if ( (lp_server_schannel() == True) && (p->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) ) {
748 /* 'server schannel = yes' should enforce use of
749 schannel, the client did offer it in auth2, but
750 obviously did not use it. */
751 DEBUG(0,("_net_sam_logon_internal: client %s not using schannel for netlogon\n",
752 get_remote_machine_name() ));
753 return NT_STATUS_ACCESS_DENIED;
756 usr_info = TALLOC_P(p->mem_ctx, NET_USER_INFO_3);
757 if (!usr_info) {
758 return NT_STATUS_NO_MEMORY;
761 ZERO_STRUCTP(usr_info);
763 /* store the user information, if there is any. */
764 r_u->user = usr_info;
765 r_u->auth_resp = 1; /* authoritative response */
766 if (q_u->validation_level != 2 && q_u->validation_level != 3) {
767 DEBUG(0,("_net_sam_logon: bad validation_level value %d.\n", (int)q_u->validation_level ));
768 return NT_STATUS_ACCESS_DENIED;
770 /* We handle the return of USER_INFO_2 instead of 3 in the parse return. Sucks, I know... */
771 r_u->switch_value = q_u->validation_level; /* indicates type of validation user info */
772 r_u->buffer_creds = 1; /* Ensure we always return server creds. */
774 if (!get_valid_user_struct(p->vuid))
775 return NT_STATUS_NO_SUCH_USER;
777 if (process_creds) {
778 fstring remote_machine;
780 /* Get the remote machine name for the creds store. */
781 /* Note this is the remote machine this request is coming from (member server),
782 not neccessarily the workstation name the user is logging onto.
784 rpcstr_pull(remote_machine,q_u->sam_id.client.login.uni_comp_name.buffer,
785 sizeof(remote_machine),q_u->sam_id.client.login.uni_comp_name.uni_str_len*2,0);
787 if (!p->dc) {
788 /* Restore the saved state of the netlogon creds. */
789 bool ret;
791 become_root();
792 ret = secrets_restore_schannel_session_info(p->pipe_state_mem_ctx,
793 remote_machine,
794 &p->dc);
795 unbecome_root();
796 if (!ret) {
797 return NT_STATUS_INVALID_HANDLE;
801 if (!p->dc || !p->dc->authenticated) {
802 return NT_STATUS_INVALID_HANDLE;
805 /* checks and updates credentials. creates reply credentials */
806 if (!creds_server_step(p->dc, &q_u->sam_id.client.cred, &r_u->srv_creds)) {
807 DEBUG(2,("_net_sam_logon: creds_server_step failed. Rejecting auth "
808 "request from client %s machine account %s\n",
809 remote_machine, p->dc->mach_acct ));
810 return NT_STATUS_INVALID_PARAMETER;
813 /* We must store the creds state after an update. */
814 become_root();
815 secrets_store_schannel_session_info(p->pipe_state_mem_ctx,
816 remote_machine,
817 p->dc);
818 unbecome_root();
821 switch (q_u->sam_id.logon_level) {
822 case INTERACTIVE_LOGON_TYPE:
823 uni_samlogon_user = &ctr->auth.id1.uni_user_name;
824 uni_samlogon_domain = &ctr->auth.id1.uni_domain_name;
826 uni_samlogon_workstation = &ctr->auth.id1.uni_wksta_name;
828 DEBUG(3,("SAM Logon (Interactive). Domain:[%s]. ", lp_workgroup()));
829 break;
830 case NET_LOGON_TYPE:
831 uni_samlogon_user = &ctr->auth.id2.uni_user_name;
832 uni_samlogon_domain = &ctr->auth.id2.uni_domain_name;
833 uni_samlogon_workstation = &ctr->auth.id2.uni_wksta_name;
835 DEBUG(3,("SAM Logon (Network). Domain:[%s]. ", lp_workgroup()));
836 break;
837 default:
838 DEBUG(2,("SAM Logon: unsupported switch value\n"));
839 return NT_STATUS_INVALID_INFO_CLASS;
840 } /* end switch */
842 rpcstr_pull(nt_username,uni_samlogon_user->buffer,sizeof(nt_username),uni_samlogon_user->uni_str_len*2,0);
843 rpcstr_pull(nt_domain,uni_samlogon_domain->buffer,sizeof(nt_domain),uni_samlogon_domain->uni_str_len*2,0);
844 rpcstr_pull(nt_workstation,uni_samlogon_workstation->buffer,sizeof(nt_workstation),uni_samlogon_workstation->uni_str_len*2,0);
846 DEBUG(3,("User:[%s@%s] Requested Domain:[%s]\n", nt_username, nt_workstation, nt_domain));
847 fstrcpy(current_user_info.smb_name, nt_username);
848 sub_set_smb_name(nt_username);
850 DEBUG(5,("Attempting validation level %d for unmapped username %s.\n", q_u->sam_id.ctr->switch_value, nt_username));
852 status = NT_STATUS_OK;
854 switch (ctr->switch_value) {
855 case NET_LOGON_TYPE:
857 const char *wksname = nt_workstation;
859 if (!NT_STATUS_IS_OK(status = make_auth_context_fixed(&auth_context, ctr->auth.id2.lm_chal))) {
860 return status;
863 /* For a network logon, the workstation name comes in with two
864 * backslashes in the front. Strip them if they are there. */
866 if (*wksname == '\\') wksname++;
867 if (*wksname == '\\') wksname++;
869 /* Standard challenge/response authenticaion */
870 if (!make_user_info_netlogon_network(&user_info,
871 nt_username, nt_domain,
872 wksname,
873 ctr->auth.id2.param_ctrl,
874 ctr->auth.id2.lm_chal_resp.buffer,
875 ctr->auth.id2.lm_chal_resp.str_str_len,
876 ctr->auth.id2.nt_chal_resp.buffer,
877 ctr->auth.id2.nt_chal_resp.str_str_len)) {
878 status = NT_STATUS_NO_MEMORY;
880 break;
882 case INTERACTIVE_LOGON_TYPE:
883 /* 'Interactive' authentication, supplies the password in its
884 MD4 form, encrypted with the session key. We will convert
885 this to challenge/response for the auth subsystem to chew
886 on */
888 const uint8 *chal;
890 if (!NT_STATUS_IS_OK(status = make_auth_context_subsystem(&auth_context))) {
891 return status;
894 chal = auth_context->get_ntlm_challenge(auth_context);
896 if (!make_user_info_netlogon_interactive(&user_info,
897 nt_username, nt_domain,
898 nt_workstation,
899 ctr->auth.id1.param_ctrl,
900 chal,
901 ctr->auth.id1.lm_owf.data,
902 ctr->auth.id1.nt_owf.data,
903 p->dc->sess_key)) {
904 status = NT_STATUS_NO_MEMORY;
906 break;
908 default:
909 DEBUG(2,("SAM Logon: unsupported switch value\n"));
910 return NT_STATUS_INVALID_INFO_CLASS;
911 } /* end switch */
913 if ( NT_STATUS_IS_OK(status) ) {
914 status = auth_context->check_ntlm_password(auth_context,
915 user_info, &server_info);
918 (auth_context->free)(&auth_context);
919 free_user_info(&user_info);
921 DEBUG(5, ("_net_sam_logon: check_password returned status %s\n",
922 nt_errstr(status)));
924 /* Check account and password */
926 if (!NT_STATUS_IS_OK(status)) {
927 /* If we don't know what this domain is, we need to
928 indicate that we are not authoritative. This
929 allows the client to decide if it needs to try
930 a local user. Fix by jpjanosi@us.ibm.com, #2976 */
931 if ( NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)
932 && !strequal(nt_domain, get_global_sam_name())
933 && !is_trusted_domain(nt_domain) )
934 r_u->auth_resp = 0; /* We are not authoritative */
936 TALLOC_FREE(server_info);
937 return status;
940 if (server_info->guest) {
941 /* We don't like guest domain logons... */
942 DEBUG(5,("_net_sam_logon: Attempted domain logon as GUEST "
943 "denied.\n"));
944 TALLOC_FREE(server_info);
945 return NT_STATUS_LOGON_FAILURE;
948 /* This is the point at which, if the login was successful, that
949 the SAM Local Security Authority should record that the user is
950 logged in to the domain. */
953 DOM_GID *gids = NULL;
954 const DOM_SID *user_sid = NULL;
955 const DOM_SID *group_sid = NULL;
956 DOM_SID domain_sid;
957 uint32 user_rid, group_rid;
959 int num_gids = 0;
960 const char *my_name;
961 unsigned char user_session_key[16];
962 unsigned char lm_session_key[16];
963 unsigned char pipe_session_key[16];
965 sampw = server_info->sam_account;
967 /* set up pointer indicating user/password failed to be
968 * found */
969 usr_info->ptr_user_info = 0;
971 user_sid = pdb_get_user_sid(sampw);
972 group_sid = pdb_get_group_sid(sampw);
974 if ((user_sid == NULL) || (group_sid == NULL)) {
975 DEBUG(1, ("_net_sam_logon: User without group or user SID\n"));
976 return NT_STATUS_UNSUCCESSFUL;
979 sid_copy(&domain_sid, user_sid);
980 sid_split_rid(&domain_sid, &user_rid);
982 if (!sid_peek_check_rid(&domain_sid, group_sid, &group_rid)) {
983 DEBUG(1, ("_net_sam_logon: user %s\\%s has user sid "
984 "%s\n but group sid %s.\n"
985 "The conflicting domain portions are not "
986 "supported for NETLOGON calls\n",
987 pdb_get_domain(sampw),
988 pdb_get_username(sampw),
989 sid_string_dbg(user_sid),
990 sid_string_dbg(group_sid)));
991 return NT_STATUS_UNSUCCESSFUL;
994 if(server_info->login_server) {
995 my_name = server_info->login_server;
996 } else {
997 my_name = global_myname();
1000 status = nt_token_to_group_list(p->mem_ctx, &domain_sid,
1001 server_info->num_sids,
1002 server_info->sids,
1003 &num_gids, &gids);
1005 if (!NT_STATUS_IS_OK(status)) {
1006 return status;
1009 if (server_info->user_session_key.length) {
1010 memcpy(user_session_key,
1011 server_info->user_session_key.data,
1012 MIN(sizeof(user_session_key),
1013 server_info->user_session_key.length));
1014 if (process_creds) {
1015 /* Get the pipe session key from the creds. */
1016 memcpy(pipe_session_key, p->dc->sess_key, 16);
1017 } else {
1018 /* Get the pipe session key from the schannel. */
1019 if (p->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL || p->auth.a_u.schannel_auth == NULL) {
1020 return NT_STATUS_INVALID_HANDLE;
1022 memcpy(pipe_session_key, p->auth.a_u.schannel_auth->sess_key, 16);
1024 SamOEMhash(user_session_key, pipe_session_key, 16);
1025 memset(pipe_session_key, '\0', 16);
1027 if (server_info->lm_session_key.length) {
1028 memcpy(lm_session_key,
1029 server_info->lm_session_key.data,
1030 MIN(sizeof(lm_session_key),
1031 server_info->lm_session_key.length));
1032 if (process_creds) {
1033 /* Get the pipe session key from the creds. */
1034 memcpy(pipe_session_key, p->dc->sess_key, 16);
1035 } else {
1036 /* Get the pipe session key from the schannel. */
1037 if (p->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL || p->auth.a_u.schannel_auth == NULL) {
1038 return NT_STATUS_INVALID_HANDLE;
1040 memcpy(pipe_session_key, p->auth.a_u.schannel_auth->sess_key, 16);
1042 SamOEMhash(lm_session_key, pipe_session_key, 16);
1043 memset(pipe_session_key, '\0', 16);
1046 init_net_user_info3(p->mem_ctx, usr_info,
1047 user_rid,
1048 group_rid,
1049 pdb_get_username(sampw),
1050 pdb_get_fullname(sampw),
1051 pdb_get_homedir(sampw),
1052 pdb_get_dir_drive(sampw),
1053 pdb_get_logon_script(sampw),
1054 pdb_get_profile_path(sampw),
1055 pdb_get_logon_time(sampw),
1056 get_time_t_max(),
1057 get_time_t_max(),
1058 pdb_get_pass_last_set_time(sampw),
1059 pdb_get_pass_can_change_time(sampw),
1060 pdb_get_pass_must_change_time(sampw),
1061 0, /* logon_count */
1062 0, /* bad_pw_count */
1063 num_gids, /* uint32 num_groups */
1064 gids , /* DOM_GID *gids */
1065 NETLOGON_EXTRA_SIDS, /* uint32 user_flgs (?) */
1066 pdb_get_acct_ctrl(sampw),
1067 server_info->user_session_key.length ? user_session_key : NULL,
1068 server_info->lm_session_key.length ? lm_session_key : NULL,
1069 my_name , /* char *logon_srv */
1070 pdb_get_domain(sampw),
1071 &domain_sid); /* DOM_SID *dom_sid */
1072 ZERO_STRUCT(user_session_key);
1073 ZERO_STRUCT(lm_session_key);
1075 TALLOC_FREE(server_info);
1076 return status;
1079 /*************************************************************************
1080 _net_sam_logon
1081 *************************************************************************/
1083 NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *r_u)
1085 return _net_sam_logon_internal(p, q_u, r_u, True);
1088 /*************************************************************************
1089 _net_sam_logon_ex - no credential chaining. Map into net sam logon.
1090 *************************************************************************/
1092 NTSTATUS _net_sam_logon_ex(pipes_struct *p, NET_Q_SAM_LOGON_EX *q_u, NET_R_SAM_LOGON_EX *r_u)
1094 NET_Q_SAM_LOGON q;
1095 NET_R_SAM_LOGON r;
1097 ZERO_STRUCT(q);
1098 ZERO_STRUCT(r);
1100 /* Only allow this if the pipe is protected. */
1101 if (p->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) {
1102 DEBUG(0,("_net_sam_logon_ex: client %s not using schannel for netlogon\n",
1103 get_remote_machine_name() ));
1104 return NT_STATUS_INVALID_PARAMETER;
1107 /* Map a NET_Q_SAM_LOGON_EX to NET_Q_SAM_LOGON. */
1108 q.validation_level = q_u->validation_level;
1110 /* Map a DOM_SAM_INFO_EX into a DOM_SAM_INFO with no creds. */
1111 q.sam_id.client.login = q_u->sam_id.client;
1112 q.sam_id.logon_level = q_u->sam_id.logon_level;
1113 q.sam_id.ctr = q_u->sam_id.ctr;
1115 r_u->status = _net_sam_logon_internal(p, &q, &r, False);
1117 if (!NT_STATUS_IS_OK(r_u->status)) {
1118 return r_u->status;
1121 /* Map the NET_R_SAM_LOGON to NET_R_SAM_LOGON_EX. */
1122 r_u->switch_value = r.switch_value;
1123 r_u->user = r.user;
1124 r_u->auth_resp = r.auth_resp;
1125 r_u->flags = 0; /* FIXME ! */
1126 return r_u->status;
1129 /*************************************************************************
1130 _ds_enum_dom_trusts
1131 *************************************************************************/
1132 #if 0 /* JERRY -- not correct */
1133 NTSTATUS _ds_enum_dom_trusts(pipes_struct *p, DS_Q_ENUM_DOM_TRUSTS *q_u,
1134 DS_R_ENUM_DOM_TRUSTS *r_u)
1136 NTSTATUS status = NT_STATUS_OK;
1138 /* TODO: According to MSDN, the can only be executed against a
1139 DC or domain member running Windows 2000 or later. Need
1140 to test against a standalone 2k server and see what it
1141 does. A windows 2000 DC includes its own domain in the
1142 list. --jerry */
1144 return status;
1146 #endif /* JERRY */