Fix another join problem. Don't use a TALLOC_CTX before it has been
[Samba/gebeck_regimport.git] / source / rpc_server / srv_netlog_nt.c
blob65ebef88090d8406e59cf335a0be98cfcba661d2
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 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. */
27 #include "includes.h"
29 #undef DBGC_CLASS
30 #define DBGC_CLASS DBGC_RPC_SRV
32 /*************************************************************************
33 init_net_r_req_chal:
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));
41 r_c->status = status;
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 /*************************************************************************
52 net_reply_logon_ctrl:
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)
64 uint32 flags = 0x0;
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);
72 return r_u->status;
75 /****************************************************************************
76 Send a message to smbd to do a sam synchronisation
77 **************************************************************************/
78 static void send_sync_message(void)
80 TDB_CONTEXT *tdb;
82 tdb = tdb_open_log(lock_path("connections.tdb"), 0,
83 TDB_DEFAULT, O_RDONLY, 0);
85 if (!tdb) {
86 DEBUG(3, ("send_sync_message(): failed to open connections "
87 "database\n"));
88 return;
91 DEBUG(3, ("sending sam synchronisation message\n"));
93 message_send_all(tdb, MSG_SMB_SAM_SYNC, NULL, 0, False, NULL);
95 tdb_close(tdb);
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)
104 uint32 flags = 0x0;
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)
122 send_sync_message();
124 DEBUG(6,("_net_logon_ctrl2: %d\n", __LINE__));
126 return r_u->status;
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__));
145 return r_u->status;
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;
170 const uint8 *pass;
171 BOOL ret;
172 uint32 acct_ctrl;
174 #if 0
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));
188 return False;
190 #endif /* 0 */
192 if(!NT_STATUS_IS_OK(pdb_init_sam(&sampass)))
193 return False;
195 /* JRA. This is ok as it is only used for generating the challenge. */
196 become_root();
197 ret=pdb_getsampwnam(sampass, mach_acct);
198 unbecome_root();
200 if (ret==False) {
201 DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct));
202 pdb_free_sam(&sampass);
203 return False;
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);
215 return True;
218 DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct));
219 pdb_free_sam(&sampass);
220 return False;
224 /*************************************************************************
225 _net_req_chal
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);
249 return status;
252 /*************************************************************************
253 init_net_r_auth:
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 /*************************************************************************
263 _net_auth
264 *************************************************************************/
266 NTSTATUS _net_auth(pipes_struct *p, NET_Q_AUTH *q_u, NET_R_AUTH *r_u)
268 NTSTATUS status = NT_STATUS_OK;
269 DOM_CHAL srv_cred;
270 UTIME srv_time;
271 fstring mach_acct;
273 srv_time.time = 0;
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;
298 } else {
299 status = NT_STATUS_ACCESS_DENIED;
301 } else {
302 status = NT_STATUS_ACCESS_DENIED;
305 /* set up the LSA AUTH response */
306 init_net_r_auth(r_u, &srv_cred, status);
308 return r_u->status;
311 /*************************************************************************
312 init_net_r_auth_2:
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 /*************************************************************************
324 _net_auth_2
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;
330 DOM_CHAL srv_cred;
331 UTIME srv_time;
332 NEG_FLAGS srv_flgs;
333 fstring mach_acct;
335 srv_time.time = 0;
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;
367 } else {
368 status = NT_STATUS_ACCESS_DENIED;
370 } else {
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;
385 last_dcinfo = p->dc;
388 return r_u->status;
391 /*************************************************************************
392 _net_srv_pwset
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;
398 DOM_CRED srv_cred;
399 pstring workstation;
400 SAM_ACCOUNT *sampass=NULL;
401 BOOL ret = False;
402 unsigned char pwd[16];
403 int i;
404 uint32 acct_ctrl;
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);
421 become_root();
422 ret=pdb_getsampwnam(sampass, p->dc.mach_acct);
423 unbecome_root();
425 /* Ensure the account exists and is a machine account. */
427 acct_ctrl = pdb_get_acct_ctrl(sampass);
429 if (!(ret
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]));
445 DEBUG(100,("\n"));
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;
466 become_root();
467 ret = pdb_update_sam_account (sampass);
468 unbecome_root();
470 if (ret)
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);
477 return r_u->status;
481 /*************************************************************************
482 _net_sam_logoff:
483 *************************************************************************/
485 NTSTATUS _net_sam_logoff(pipes_struct *p, NET_Q_SAM_LOGOFF *q_u, NET_R_SAM_LOGOFF *r_u)
487 DOM_CRED srv_cred;
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;
505 return r_u->status;
509 /*************************************************************************
510 _net_sam_logon
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;
518 DOM_CRED srv_cred;
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;
526 SAM_ACCOUNT *sampw;
527 struct auth_context *auth_context = NULL;
529 usr_info = (NET_USER_INFO_3 *)talloc(p->mem_ctx, sizeof(NET_USER_INFO_3));
530 if (!usr_info)
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()));
571 break;
572 case NET_LOGON_TYPE:
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()));
578 break;
579 default:
580 DEBUG(2,("SAM Logon: unsupported switch value\n"));
581 return NT_STATUS_INVALID_INFO_CLASS;
582 } /* end switch */
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) {
599 case NET_LOGON_TYPE:
601 if (!NT_STATUS_IS_OK(status = make_auth_context_fixed(&auth_context, ctr->auth.id2.lm_chal))) {
602 return status;
605 /* Standard challenge/response authenticaion */
606 if (!make_user_info_netlogon_network(&user_info,
607 nt_username, nt_domain,
608 nt_workstation,
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;
615 break;
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 */
623 const uint8 *chal;
625 if (!NT_STATUS_IS_OK(status = make_auth_context_subsystem(&auth_context))) {
626 return status;
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,
636 p->dc.sess_key)) {
637 status = NT_STATUS_NO_MEMORY;
639 break;
641 default:
642 DEBUG(2,("SAM Logon: unsupported switch value\n"));
643 return NT_STATUS_INVALID_INFO_CLASS;
644 } /* end switch */
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",
655 nt_errstr(status)));
657 /* Check account and password */
659 if (!NT_STATUS_IS_OK(status)) {
660 free_server_info(&server_info);
661 return status;
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;
679 DOM_SID domain_sid;
680 uint32 user_rid, group_rid;
682 int num_gids = 0;
683 pstring my_name;
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,
713 &domain_sid,
714 server_info->ptok,
715 &num_gids,
716 &gids))) {
717 return status;
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,
735 user_rid,
736 group_rid,
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),
744 get_time_t_max(),
745 get_time_t_max(),
746 pdb_get_pass_last_set_time(sampw),
747 pdb_get_pass_can_change_time(sampw),
748 pdb_get_pass_must_change_time(sampw),
750 0, /* logon_count */
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);
767 return status;
770 /*************************************************************************
771 _ds_enum_dom_trusts
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
781 reworked. */
783 return status;