- got fed up of vuser_db spewing 150 lines of trash, made it possible
[Samba.git] / source / netlogond / srv_netlogon_nt.c
blob800e8d573606c30f0ef5e4772da64fbef326c13c
1 /*
2 * Unix SMB/Netbios implementation.
3 * Version 1.9.
4 * RPC Pipe client / server routines
5 * Copyright (C) Andrew Tridgell 1992-2000,
6 * Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
7 * Copyright (C) Paul Ashton 1997-2000,
8 * Copyright (C) Jeremy Allison 1998-2000,
9 * Copyright (C) Sander Striker 2000
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "includes.h"
27 #include "nterr.h"
28 #include "sids.h"
29 #include "rpc_parse.h"
30 #include "rpc_client.h"
32 extern int DEBUGLEVEL;
34 extern pstring global_myname;
36 /******************************************************************
37 gets a machine password entry. checks access rights of the host.
38 ******************************************************************/
39 static uint32 direct_samr_userinfo(const UNISTR2 *uni_user,
40 uint16 level,
41 SAM_USERINFO_CTR * ctr,
42 DOM_GID ** gids,
43 uint32 *num_grps, BOOL set)
45 POLICY_HND sam_pol;
46 POLICY_HND dom_pol;
47 POLICY_HND usr_pol;
48 uint32 user_rid = 0xffffffff;
50 uint32 status_sam = NT_STATUS_NOPROBLEMO;
51 uint32 status_dom = NT_STATUS_NOPROBLEMO;
52 uint32 status_usr = NT_STATUS_NOPROBLEMO;
53 uint32 status_pwd = NT_STATUS_NOPROBLEMO;
54 uint32 status_grp = NT_STATUS_NOPROBLEMO;
56 if (ctr == NULL)
58 return NT_STATUS_INVALID_PARAMETER;
61 if (!set)
63 ZERO_STRUCTP(ctr);
66 status_sam =
67 _samr_connect(NULL, SEC_RIGHTS_MAXIMUM_ALLOWED, &sam_pol);
68 if (status_sam == NT_STATUS_NOPROBLEMO)
70 status_dom = _samr_open_domain(&sam_pol,
71 SEC_RIGHTS_MAXIMUM_ALLOWED,
72 &global_sam_sid, &dom_pol);
74 if (status_dom == NT_STATUS_NOPROBLEMO)
76 uint32 type;
77 uint32 num_rids;
78 uint32 num_types;
80 status_usr = _samr_lookup_names(&dom_pol, 1, 0x3e8,
81 1, uni_user,
82 &num_rids, &user_rid,
83 &num_types, &type);
84 if (type != SID_NAME_USER)
86 status_usr = NT_STATUS_ACCESS_DENIED;
89 if (status_usr == NT_STATUS_NOPROBLEMO)
91 status_usr = _samr_open_user(&dom_pol,
92 SEC_RIGHTS_MAXIMUM_ALLOWED,
93 user_rid, &usr_pol);
95 DEBUG(10, ("_samr_open_user: status %x\n", status_usr));
96 if (status_usr == NT_STATUS_NOPROBLEMO)
98 if (!set && gids != NULL && num_grps != NULL)
100 status_grp = _samr_query_usergroups(&usr_pol,
101 num_grps, gids);
103 DEBUG(10,
104 ("_samr_query_usergroups: status %x\n", status_grp));
105 if (set)
107 status_pwd = _samr_set_userinfo(&usr_pol, level, ctr);
109 else
111 status_pwd =
112 _samr_query_userinfo(&usr_pol, level, ctr);
115 if (status_usr == NT_STATUS_NOPROBLEMO)
116 _samr_close(&usr_pol);
117 if (status_dom == NT_STATUS_NOPROBLEMO)
118 _samr_close(&dom_pol);
119 if (status_sam == NT_STATUS_NOPROBLEMO)
120 _samr_close(&sam_pol);
122 if (status_pwd != NT_STATUS_NOPROBLEMO)
124 return status_pwd;
127 if (status_usr != NT_STATUS_NOPROBLEMO)
129 return status_usr;
132 if (status_grp != NT_STATUS_NOPROBLEMO)
134 return status_grp;
137 if (ctr->info.id == NULL)
139 return NT_STATUS_NO_MEMORY;
142 return NT_STATUS_NOPROBLEMO;
145 /******************************************************************
146 gets a machine password entry. checks access rights of the host.
147 ******************************************************************/
148 static BOOL get_md4pw(char *md4pw, char *trust_name, char *trust_acct)
150 SAM_USERINFO_CTR ctr;
151 uint32 status_pwd = NT_STATUS_NOPROBLEMO;
152 UNISTR2 uni_trust_acct;
154 ZERO_STRUCT(ctr);
156 make_unistr2(&uni_trust_acct, trust_acct, strlen(trust_acct));
158 #if 0
160 * Currently this code is redundent as we already have a filter
161 * by hostname list. What this code really needs to do is to
162 * get a hosts allowed/hosts denied list from the SAM database
163 * on a per user basis, and make the access decision there.
164 * I will leave this code here for now as a reminder to implement
165 * this at a later date. JRA.
168 if (!allow_access(lp_domain_hostsdeny(), lp_domain_hostsallow(),
169 client_connection_name(), client_connection_addr()))
171 DEBUG(0,
172 ("get_md4pw: Workstation %s denied access to domain\n",
173 trust_acct));
174 return False;
176 #endif /* 0 */
178 if (strequal(trust_name, global_myname)
179 || strequal(trust_name, "\\\\."))
181 BOOL ret;
182 DEBUG(10, ("get_md4pw: loop-back, use $MACHINE.ACC\n"));
183 ret = msrpc_lsa_query_trust_passwd("\\\\.",
184 "$MACHINE.ACC", md4pw,
185 NULL);
186 return ret ? NT_STATUS_ACCESS_DENIED : NT_STATUS_NOPROBLEMO;
190 * must do all this as root
192 become_root(True);
193 status_pwd = direct_samr_userinfo(&uni_trust_acct, 0x12, &ctr,
194 NULL, NULL, False);
195 unbecome_root(True);
197 if (status_pwd == NT_STATUS_NOPROBLEMO)
199 memcpy(md4pw, ctr.info.id12->nt_pwd, 16);
200 dump_data_pw("md4pw", md4pw, 16);
203 free_samr_userinfo_ctr(&ctr);
205 return status_pwd == NT_STATUS_NOPROBLEMO;
208 /*************************************************************************
209 net_login_interactive:
210 *************************************************************************/
211 static uint32 remote_interactive(const NET_ID_INFO_1 * id1,
212 struct dcinfo *dc, NET_USER_INFO_3 * usr)
214 const UNISTR2 *uni_samusr = &id1->uni_user_name;
215 const UNISTR2 *uni_samnam = &id1->uni_domain_name;
216 fstring user;
217 fstring domain;
218 uint32 status;
219 char nt_pwd[16];
220 char lm_pwd[16];
221 unsigned char key[16];
223 memset(key, 0, 16);
224 memcpy(key, dc->sess_key, 8);
226 memcpy(lm_pwd, id1->lm_owf.data, 16);
227 memcpy(nt_pwd, id1->nt_owf.data, 16);
229 dump_data_pw("key:", key, 16);
231 dump_data_pw("lm owf password:", lm_pwd, 16);
232 dump_data_pw("nt owf password:", nt_pwd, 16);
234 SamOEMhash((uchar *) lm_pwd, key, 0);
235 SamOEMhash((uchar *) nt_pwd, key, 0);
237 dump_data_pw("decrypt of lm owf password:", lm_pwd, 16);
238 dump_data_pw("decrypt of nt owf password:", nt_pwd, 16);
240 unistr2_to_ascii(user, uni_samusr, sizeof(user) - 1);
241 unistr2_to_ascii(domain, uni_samnam, sizeof(domain) - 1);
243 DEBUG(5, ("BEGIN remote_interactive: %s\\%s\n", domain, user));
245 status = check_domain_security(user, domain,
246 NULL, lm_pwd, 16, nt_pwd, 16, usr);
248 DEBUG(5, ("END remote_interactive: %x\n", status));
250 if (status != 0x0)
252 return status;
255 memset(key, 0, 16);
256 memcpy(key, dc->sess_key, 8);
257 dump_data_pw("key:", key, 16);
258 dump_data_pw("user sess key:", usr->user_sess_key, 16);
259 SamOEMhash((uchar *) usr->user_sess_key, key, 0);
260 dump_data_pw("encrypt of user session key:", usr->user_sess_key, 16);
262 return status;
265 /*************************************************************************
266 net_login_interactive:
267 *************************************************************************/
268 static uint32 net_login_interactive(const NET_ID_INFO_1 * id1,
269 struct dcinfo *dc)
271 const UNISTR2 *uni_samusr = &id1->uni_user_name;
272 uint32 status = NT_STATUS_NOPROBLEMO;
273 SAM_USERINFO_CTR ctr;
275 char nt_pwd[16];
276 char lm_pwd[16];
277 unsigned char key[16];
279 memset(key, 0, 16);
280 memcpy(key, dc->sess_key, 8);
282 memcpy(lm_pwd, id1->lm_owf.data, 16);
283 memcpy(nt_pwd, id1->nt_owf.data, 16);
285 dump_data_pw("key:", key, 16);
287 dump_data_pw("lm owf password:", lm_pwd, 16);
288 dump_data_pw("nt owf password:", nt_pwd, 16);
290 SamOEMhash((uchar *) lm_pwd, key, 0);
291 SamOEMhash((uchar *) nt_pwd, key, 0);
293 dump_data_pw("decrypt of lm owf password:", lm_pwd, 16);
294 dump_data_pw("decrypt of nt owf password:", nt_pwd, 16);
296 become_root(True);
297 status = direct_samr_userinfo(uni_samusr, 0x12, &ctr,
298 NULL, NULL, False);
299 unbecome_root(True);
300 if (status != NT_STATUS_NOPROBLEMO)
302 free_samr_userinfo_ctr(&ctr);
303 return status;
306 if (memcmp(ctr.info.id12->lm_pwd, lm_pwd, 16) != 0 ||
307 memcmp(ctr.info.id12->nt_pwd, nt_pwd, 16) != 0)
309 status = NT_STATUS_WRONG_PASSWORD;
312 free_samr_userinfo_ctr(&ctr);
313 return status;
316 /*************************************************************************
317 net_login_network:
318 *************************************************************************/
319 static uint32 net_login_general(const NET_ID_INFO_4 * id4,
320 struct dcinfo *dc, char usr_sess_key[16])
322 fstring user;
323 fstring domain;
324 const char *general = id4->str_general.buffer;
325 int pw_len = id4->str_general.str_str_len;
327 unistr2_to_ascii(user, &id4->uni_user_name, sizeof(user) - 1);
328 unistr2_to_ascii(domain, &id4->uni_domain_name, sizeof(domain) - 1);
330 if (pw_len >= sizeof(fstring))
332 return NT_STATUS_ACCESS_DENIED;
335 DEBUG(5, ("net_login_general: user:%s domain:%s", user, domain));
336 dump_data_pw("password:\n", general, pw_len);
338 DEBUG(0,
339 ("net_login_general: TODO - \"update encrypted\" disabled\n"));
340 if (pass_check(user, general, pw_len, NULL,
341 #if 0
342 lp_update_encrypted()? update_smbpassword_file :
343 #endif
344 NULL))
346 unsigned char key[16];
347 memset(key, 0, 16);
348 memcpy(key, dc->sess_key, 8);
349 #ifdef DEBUG_PASSWORD
350 DEBUG(100, ("key:"));
351 dump_data(100, key, 16);
352 DEBUG(100, ("user sess key:"));
353 dump_data(100, usr_sess_key, 16);
354 #endif
355 SamOEMhash((uchar *) usr_sess_key, key, 0);
356 #ifdef DEBUG_PASSWORD
357 DEBUG(100, ("encrypt of user session key:"));
358 dump_data(100, usr_sess_key, 16);
359 #endif
360 return NT_STATUS_NOPROBLEMO;
363 return NT_STATUS_WRONG_PASSWORD;
366 /*************************************************************************
367 net_login_network:
368 *************************************************************************/
369 static uint32 remote_network(const NET_ID_INFO_2 * id2,
370 struct dcinfo *dc, NET_USER_INFO_3 * usr)
372 const UNISTR2 *uni_samusr = &id2->uni_user_name;
373 const UNISTR2 *uni_samnam = &id2->uni_domain_name;
374 fstring user;
375 fstring domain;
376 unsigned char key[16];
377 uint32 status;
378 int nt_pw_len = id2->hdr_nt_chal_resp.str_str_len;
379 int lm_pw_len = id2->hdr_lm_chal_resp.str_str_len;
381 unistr2_to_ascii(user, uni_samusr, sizeof(user) - 1);
382 unistr2_to_ascii(domain, uni_samnam, sizeof(domain) - 1);
384 DEBUG(5, ("BEGIN remote_network: %s\\%s\n", domain, user));
386 status = check_domain_security(user, domain,
387 id2->lm_chal,
388 (const uchar *)id2->
389 lm_chal_resp.buffer, lm_pw_len,
390 (const uchar *)id2->
391 nt_chal_resp.buffer, nt_pw_len, usr);
393 DEBUG(5, ("END remote_network: %x\n", status));
395 if (status != 0x0)
397 return status;
400 memset(key, 0, 16);
401 memcpy(key, dc->sess_key, 8);
402 dump_data_pw("key:", key, 16);
403 dump_data_pw("user sess key:", usr->user_sess_key, 16);
404 dump_data_pw("lm_pw8:", usr->padding, 16);
405 SamOEMhash((uchar *) usr->padding, key, 3);
406 SamOEMhash((uchar *) usr->user_sess_key, key, 0);
407 dump_data_pw("encrypt of user session key:", usr->user_sess_key, 16);
408 dump_data_pw("encrypt of lm_pw8:", usr->padding, 16);
410 return status;
413 /*************************************************************************
414 net_login_network:
415 *************************************************************************/
416 static uint32 net_login_network(const NET_ID_INFO_2 * id2,
417 uint16 acb_info,
418 struct dcinfo *dc,
419 char usr_sess_key[16], char lm_pw8[8])
421 const UNISTR2 *uni_samusr = &id2->uni_user_name;
422 fstring user;
423 fstring domain;
424 SAM_USERINFO_CTR ctr;
425 unsigned char key[16];
426 uint32 status;
427 int nt_pw_len = id2->hdr_nt_chal_resp.str_str_len;
428 int lm_pw_len = id2->hdr_lm_chal_resp.str_str_len;
430 unistr2_to_ascii(user, uni_samusr, sizeof(user) - 1);
431 unistr2_to_ascii(domain, &id2->uni_domain_name, sizeof(domain) - 1);
433 become_root(True);
434 status = direct_samr_userinfo(uni_samusr, 0x12, &ctr, NULL, NULL,
435 False);
436 unbecome_root(True);
438 if (status != NT_STATUS_NOPROBLEMO)
440 free_samr_userinfo_ctr(&ctr);
441 return status;
444 DEBUG(5,
445 ("net_login_network: lm_len:%d nt_len:%d user:%s domain:%s\n",
446 lm_pw_len, nt_pw_len, user, domain));
448 if (!smb_password_ok(acb_info, ctr.info.id12->lm_pwd,
449 ctr.info.id12->nt_pwd,
450 id2->lm_chal,
451 user, domain,
452 (const uchar *)id2->lm_chal_resp.buffer,
453 lm_pw_len,
454 (const uchar *)id2->nt_chal_resp.buffer,
455 nt_pw_len, usr_sess_key))
457 free_samr_userinfo_ctr(&ctr);
458 return NT_STATUS_WRONG_PASSWORD;
461 memcpy(lm_pw8, ctr.info.id12->lm_pwd, 8);
462 memset(key, 0, 16);
463 memcpy(key, dc->sess_key, 8);
464 dump_data_pw("key:", key, 16);
465 dump_data_pw("user sess key:", usr_sess_key, 16);
466 dump_data_pw("lm_pw8:", lm_pw8, 16);
467 SamOEMhash((uchar *) lm_pw8, key, 3);
468 SamOEMhash((uchar *) usr_sess_key, key, 0);
469 dump_data_pw("encrypt of user session key:", usr_sess_key, 16);
470 dump_data_pw("encrypt of lm_pw8:", lm_pw8, 16);
472 free_samr_userinfo_ctr(&ctr);
473 return NT_STATUS_NOPROBLEMO;
476 /*************************************************************************
477 _net_req_chal
478 *************************************************************************/
479 uint32 _net_req_chal(const UNISTR2 *uni_logon_server,
480 const UNISTR2 *uni_logon_client,
481 const DOM_CHAL * clnt_chal, DOM_CHAL * srv_chal)
483 fstring trust_acct;
484 fstring trust_name;
485 struct dcinfo dc;
486 ZERO_STRUCT(dc);
487 unistr2_to_ascii(trust_acct, uni_logon_client,
488 sizeof(trust_acct) - 1);
489 fstrcpy(trust_name, trust_acct);
490 strlower(trust_name);
491 fstrcat(trust_acct, "$");
492 if (!get_md4pw((char *)dc.md4pw, trust_name, trust_acct))
494 /* lkclXXXX take a guess at a good error message to return :-) */
495 return NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT;
498 /* copy the client credentials */
499 memcpy(dc.clnt_chal.data, clnt_chal->data, sizeof(clnt_chal->data));
500 memcpy(dc.clnt_cred.challenge.data, clnt_chal->data,
501 sizeof(clnt_chal->data));
503 /* create a server challenge for the client */
504 /* Set these to random values. */
506 generate_random_buffer(srv_chal->data, sizeof(srv_chal->data), False);
508 /* copy the server credentials */
509 memcpy(dc.srv_chal.data, srv_chal->data, sizeof(srv_chal->data));
510 memcpy(dc.srv_cred.challenge.data, srv_chal->data,
511 sizeof(srv_chal->data));
513 ZERO_STRUCT(dc.sess_key);
515 /* from client / server challenges and md4 password, generate sess key */
516 cred_session_key(&(dc.clnt_chal), &(dc.srv_chal),
517 (char *)dc.md4pw, dc.sess_key);
518 if (!cred_store(global_sam_name, trust_name, &dc))
520 return NT_STATUS_ACCESS_DENIED;
523 return NT_STATUS_NOPROBLEMO;
527 /*************************************************************************
528 error messages cropping up when using nltest.exe...
529 *************************************************************************/
530 #define ERROR_NO_SUCH_DOMAIN 0x54b
531 #define ERROR_NO_LOGON_SERVERS 0x51f
533 /*******************************************************************
534 creates a NETLOGON_INFO_3 structure.
535 ********************************************************************/
536 static BOOL make_netinfo_3(NETLOGON_INFO_3 * info, uint32 flags,
537 uint32 logon_attempts)
539 info->flags = flags;
540 info->logon_attempts = logon_attempts;
541 info->reserved_1 = 0x0;
542 info->reserved_2 = 0x0;
543 info->reserved_3 = 0x0;
544 info->reserved_4 = 0x0;
545 info->reserved_5 = 0x0;
546 return True;
550 /*******************************************************************
551 creates a NETLOGON_INFO_1 structure.
552 ********************************************************************/
553 static BOOL make_netinfo_1(NETLOGON_INFO_1 * info, uint32 flags,
554 uint32 pdc_status)
556 info->flags = flags;
557 info->pdc_status = pdc_status;
558 return True;
561 /*******************************************************************
562 creates a NETLOGON_INFO_2 structure.
563 ********************************************************************/
564 static BOOL make_netinfo_2(NETLOGON_INFO_2 * info, uint32 flags,
565 uint32 pdc_status, uint32 tc_status,
566 char *trusted_dc_name)
568 int len_dc_name = strlen(trusted_dc_name);
569 info->flags = flags;
570 info->pdc_status = pdc_status;
571 info->ptr_trusted_dc_name = 1;
572 info->tc_status = tc_status;
573 if (trusted_dc_name != NULL)
575 make_unistr2(&(info->uni_trusted_dc_name), trusted_dc_name,
576 len_dc_name + 1);
578 else
580 make_unistr2(&(info->uni_trusted_dc_name), "", 1);
583 return True;
586 /*************************************************************************
587 _net_logon_ctrl2
588 *************************************************************************/
589 uint32 _net_logon_ctrl2(const UNISTR2 *uni_server_name,
590 uint32 function_code,
591 uint32 query_level,
592 uint32 switch_value,
593 uint32 *reply_switch_value,
594 NETLOGON_INFO * logon_info)
596 /* lkclXXXX - guess what - absolutely no idea what these are! */
597 uint32 flags = 0x0;
598 uint32 pdc_status = 0x0;
599 uint32 logon_attempts = 0x0;
600 uint32 tc_status = ERROR_NO_LOGON_SERVERS;
601 char *trusted_domain = "test_domain";
602 *reply_switch_value = query_level;
603 switch (query_level)
605 case 1:
607 make_netinfo_1(&logon_info->info1, flags, pdc_status);
608 break;
610 case 2:
612 make_netinfo_2(&logon_info->info2, flags, pdc_status,
613 tc_status, trusted_domain);
614 break;
616 case 3:
618 make_netinfo_3(&logon_info->info3, flags,
619 logon_attempts); break;
621 default:
623 /* take a guess at an error code... */
624 return NT_STATUS_INVALID_INFO_CLASS;
625 break;
629 return NT_STATUS_NOPROBLEMO;
632 /*************************************************************************
633 _net_trust_dom_list
634 *************************************************************************/
635 uint32 _net_trust_dom_list(const UNISTR2 *uni_server_name,
636 uint32 function_code, BUFFER2 * uni_trust_dom_name)
638 char **doms = NULL;
639 uint32 num_doms = 0;
640 enumtrustdoms(&doms, &num_doms);
641 make_buffer2_multi(uni_trust_dom_name, doms, num_doms);
642 if (num_doms == 0)
644 uni_trust_dom_name->buf_max_len = 0x2;
645 uni_trust_dom_name->buf_len = 0x2;
647 uni_trust_dom_name->undoc = 0x1;
648 free_char_array(num_doms, doms);
649 return NT_STATUS_NOPROBLEMO;
652 /*************************************************************************
653 _net_auth
654 *************************************************************************/
655 uint32 _net_auth(const UNISTR2 *uni_logon_srv,
656 const UNISTR2 *uni_acct_name,
657 uint16 sec_chan,
658 const UNISTR2 *uni_comp_name,
659 const DOM_CHAL * clnt_chal, DOM_CHAL * srv_chal)
661 UTIME srv_time;
662 fstring trust_name;
663 struct dcinfo dc;
665 ZERO_STRUCT(dc);
666 srv_time.time = 0;
668 unistr2_to_ascii(trust_name, uni_comp_name, sizeof(trust_name) - 1);
669 if (!cred_get(global_sam_name, trust_name, &dc))
671 return NT_STATUS_ACCESS_DENIED;
674 /* check that the client credentials are valid */
675 if (!cred_assert
676 (clnt_chal, dc.sess_key, &(dc.clnt_cred.challenge), srv_time))
678 return NT_STATUS_ACCESS_DENIED;
681 /* create server challenge for inclusion in the reply */
682 cred_create(dc.sess_key, &(dc.srv_cred.challenge), srv_time,
683 srv_chal);
685 /* copy the received client credentials for use next time */
686 memcpy(dc.clnt_cred.challenge.data, clnt_chal->data,
687 sizeof(clnt_chal->data));
688 memcpy(dc.srv_cred.challenge.data, clnt_chal->data,
689 sizeof(clnt_chal->data));
691 if (!cred_store(global_sam_name, trust_name, &dc))
693 return NT_STATUS_ACCESS_DENIED;
696 return NT_STATUS_NOPROBLEMO;
699 /*************************************************************************
700 _net_auth_2
701 *************************************************************************/
702 uint32 _net_auth_2(const UNISTR2 *uni_logon_srv,
703 const UNISTR2 *uni_acct_name,
704 uint16 sec_chan,
705 const UNISTR2 *uni_comp_name,
706 const DOM_CHAL * clnt_chal,
707 const NEG_FLAGS * clnt_flgs,
708 DOM_CHAL * srv_chal, NEG_FLAGS * srv_flgs)
710 UTIME srv_time;
711 fstring trust_name;
712 struct dcinfo dc;
714 ZERO_STRUCT(dc);
715 srv_time.time = 0;
717 unistr2_to_ascii(trust_name, uni_comp_name, sizeof(trust_name) - 1);
718 if (!cred_get(global_sam_name, trust_name, &dc))
720 return NT_STATUS_ACCESS_DENIED;
723 /* check that the client credentials are valid */
724 if (!cred_assert(clnt_chal, dc.sess_key,
725 &(dc.clnt_cred.challenge), srv_time))
727 return NT_STATUS_ACCESS_DENIED;
730 /* create server challenge for inclusion in the reply */
731 cred_create(dc.sess_key, &(dc.srv_cred.challenge), srv_time,
732 srv_chal);
734 /* copy the received client credentials for use next time */
735 memcpy(dc.clnt_cred.challenge.data, clnt_chal->data,
736 sizeof(clnt_chal->data));
737 memcpy(dc.srv_cred.challenge.data, clnt_chal->data,
738 sizeof(clnt_chal->data));
739 if (!cred_store(global_sam_name, trust_name, &dc))
741 return NT_STATUS_ACCESS_DENIED;
744 /* mask out unsupported bits */
745 srv_flgs->neg_flags = clnt_flgs->neg_flags & 0x400001ff;
747 /* minimum bits required */
748 if (!IS_BITS_SET_ALL(srv_flgs->neg_flags, 0x000000ff))
750 return NT_STATUS_ACCESS_DENIED;
753 /* secure channel NOT to be used */
754 if (!lp_server_schannel())
756 srv_flgs->neg_flags &= ~0x40000000;
758 else if (lp_server_schannel() == True)
760 /* secure channel MUST be used */
761 if (IS_BITS_CLR_ALL(srv_flgs->neg_flags, 0x40000000))
763 return NT_STATUS_ACCESS_DENIED;
767 return NT_STATUS_NOPROBLEMO;
770 /*************************************************************************
771 _net_srv_pwset
772 *************************************************************************/
773 uint32 _net_srv_pwset(const UNISTR2 *uni_logon_srv,
774 const UNISTR2 *uni_acct_name,
775 uint16 sec_chan,
776 const UNISTR2 *uni_comp_name,
777 const DOM_CRED * clnt_cred,
778 const uint8 pwd[16], DOM_CRED * srv_cred)
780 pstring trust_acct;
781 unsigned char hash3_pwd[16];
782 uint32 status_pwd;
783 fstring trust_name;
784 struct dcinfo dc;
785 SAM_USERINFO_CTR ctr;
787 ZERO_STRUCT(dc);
789 unistr2_to_ascii(trust_name, uni_comp_name, sizeof(trust_name) - 1);
790 if (!cred_get(global_sam_name, trust_name, &dc))
792 return NT_STATUS_ACCESS_DENIED;
795 /* checks and updates credentials. creates reply credentials */
796 if (!deal_with_creds
797 (dc.sess_key, &(dc.clnt_cred), clnt_cred, srv_cred))
799 /* lkclXXXX take a guess at a sensible error code to return... */
800 return NT_STATUS_ACCESS_DENIED;
803 memcpy(&(dc.srv_cred), &(dc.clnt_cred), sizeof(dc.clnt_cred));
804 if (!cred_store(global_sam_name, trust_name, &dc))
806 return NT_STATUS_ACCESS_DENIED;
809 unistr2_to_ascii(trust_acct, uni_acct_name, sizeof(trust_acct) - 1);
810 DEBUG(3, ("Server Password Set Wksta:[%s]\n", trust_acct));
812 /* get info for trust account */
813 ZERO_STRUCT(ctr);
815 become_root(True);
816 status_pwd = direct_samr_userinfo(uni_acct_name, 0x12, &ctr,
817 NULL, NULL, False);
818 unbecome_root(True);
819 if (status_pwd != NT_STATUS_NOPROBLEMO)
821 free_samr_userinfo_ctr(&ctr);
822 return status_pwd;
825 /* Some debug output, needed an iterater variable */
827 int i;
828 DEBUG(100, ("Server password set : new given value was :\n"));
829 for (i = 0; i < 16; i++)
831 DEBUG(100, ("%02X ", pwd[i]));
833 DEBUG(100, ("\n"));
836 cred_hash3(hash3_pwd, pwd, dc.sess_key, 0);
838 /* lies! nt and lm passwords are _not_ the same: don't care */
839 memcpy(ctr.info.id12->lm_pwd, hash3_pwd, sizeof(hash3_pwd));
840 memcpy(ctr.info.id12->nt_pwd, hash3_pwd, sizeof(hash3_pwd));
842 become_root(True);
843 status_pwd = direct_samr_userinfo(uni_acct_name, 0x12, &ctr,
844 NULL, NULL, True);
845 unbecome_root(True);
847 if (status_pwd != NT_STATUS_NOPROBLEMO)
849 return status_pwd;
852 return NT_STATUS_NOPROBLEMO;
855 static uint32 TooMuchInformation(uint32 status)
857 #ifdef SANITISE_FOR_SECURITY_REASONS
858 switch (status)
860 case NT_STATUS_INVALID_INFO_CLASS:
861 case NT_STATUS_INVALID_PARAMETER:
862 case NT_STATUS_ACCESS_DENIED:
863 case NT_STATUS_NOPROBLEMO:
865 return status;
868 DEBUG(10,("TooMuchInformation: sanitising status %x\n", status));
869 return NT_STATUS_ACCESS_DENIED;
871 #else /* oh well, who cares, anyway */
872 return status;
873 #endif
876 /*************************************************************************
877 _net_sam_logon
878 *************************************************************************/
879 uint32 _net_sam_logon(const UNISTR2 *uni_logon_srv,
880 const UNISTR2 *uni_comp_name,
881 const DOM_CRED * clnt_cred,
882 uint16 logon_level,
883 const NET_ID_INFO_CTR * id_ctr,
884 uint16 validation_level,
885 DOM_CRED * srv_creds,
886 NET_USER_INFO_CTR * uctr, uint32 *auth_resp)
888 const UNISTR2 *uni_samusr = NULL;
889 const UNISTR2 *uni_domain = NULL;
890 fstring nt_username;
891 fstring nt_samname;
892 char *enc_user_sess_key = NULL;
893 char usr_sess_key[16];
894 char lm_pw8[16];
895 char *padding = NULL;
896 uint32 status_pwd = 0x0;
897 SAM_USERINFO_CTR ctr;
898 NTTIME logon_time;
899 NTTIME logoff_time;
900 NTTIME kickoff_time;
901 NTTIME pass_last_set_time;
902 NTTIME pass_can_change_time;
903 NTTIME pass_must_change_time;
904 UNISTR2 *uni_nt_name;
905 UNISTR2 *uni_full_name;
906 UNISTR2 *uni_logon_script;
907 UNISTR2 *uni_profile_path;
908 UNISTR2 *uni_home_dir;
909 UNISTR2 *uni_dir_drive;
910 uint32 user_rid;
911 uint32 group_rid;
912 int num_gids = 0;
913 DOM_GID *gids = NULL;
914 fstring trust_name;
915 struct dcinfo dc;
916 uint16 acb_info;
917 UNISTR2 uni_myname;
918 UNISTR2 uni_sam_name;
919 uint32 status = NT_STATUS_NOPROBLEMO;
922 * checks and updates credentials. creates reply credentials
925 unistr2_to_ascii(trust_name, uni_comp_name, sizeof(trust_name) - 1);
926 if (!cred_get(global_sam_name, trust_name, &dc))
928 return NT_STATUS_ACCESS_DENIED;
931 if (!deal_with_creds(dc.sess_key, &dc.clnt_cred,
932 clnt_cred, srv_creds))
934 return NT_STATUS_ACCESS_DENIED;
937 memcpy(&dc.srv_cred, &dc.clnt_cred, sizeof(dc.clnt_cred));
938 if (!cred_store(global_sam_name, trust_name, &dc))
940 return NT_STATUS_ACCESS_DENIED;
944 * find the username and domain name
947 switch (logon_level)
949 case INTERACTIVE_LOGON_TYPE:
951 uni_samusr = &id_ctr->auth.id1.uni_user_name;
952 uni_domain = &id_ctr->auth.id1.uni_domain_name;
953 DEBUG(3, ("SAM Logon (Interactive)."));
954 break;
956 case NETWORK_LOGON_TYPE:
958 uni_samusr = &id_ctr->auth.id2.uni_user_name;
959 uni_domain = &id_ctr->auth.id2.uni_domain_name;
960 DEBUG(3, ("SAM Logon (Network). "));
961 break;
963 case GENERAL_LOGON_TYPE:
965 uni_samusr = &id_ctr->auth.id4.uni_user_name;
966 uni_domain = &id_ctr->auth.id4.uni_domain_name;
967 DEBUG(3, ("SAM Logon (General). "));
968 break;
970 default:
972 DEBUG(2, ("SAM Logon: unsupported switch value\n"));
973 return NT_STATUS_INVALID_INFO_CLASS;
977 unistr2_to_ascii(nt_username, uni_samusr, sizeof(nt_username) - 1);
978 unistr2_to_ascii(nt_samname, uni_domain, sizeof(nt_samname) - 1);
980 DEBUG(3, ("Domain:[%s] User:[%s]\n", nt_samname, nt_username));
983 * check if we should remote-auth to a PDC.
986 if (lp_server_role() == ROLE_STANDALONE &&
987 !strequal(nt_samname, global_myname))
989 DEBUG(1,("_net_sam_logon: stand-alone server cannot remote-auth domain users!\n"));
990 return NT_STATUS_ACCESS_DENIED;
994 * call up to a PDC if it's not our own SAM database.
997 if (!strequal(nt_samname, global_sam_name) &&
998 !strequal(nt_samname, global_myname))
1000 DEBUG(5,("remote-auth: SAM name: %s my name: %s\n",
1001 global_sam_name, global_myname));
1003 if (validation_level != 3)
1006 * see the g_new of the container, below? well,
1007 * that need to be id2 for AS/U, right.
1008 * and i haven't the inclination to do it, right
1009 * now. needs to make a copy-level-two-to-three
1010 * function. lkclXXXX
1013 DEBUG(0, ("remote-auth, level %d not supported yet\n",
1014 validation_level));
1015 return NT_STATUS_ACCESS_DENIED;
1017 uctr->usr.id3 = g_new(NET_USER_INFO_3, 1);
1018 if (uctr->usr.id3 == NULL)
1020 return NT_STATUS_INVALID_PARAMETER;
1023 (*auth_resp) = 1;
1024 switch (logon_level)
1026 case NETWORK_LOGON_TYPE:
1028 status = remote_network(&id_ctr->auth.id2, &dc,
1029 uctr->usr.id3);
1030 return TooMuchInformation(status);
1032 case INTERACTIVE_LOGON_TYPE:
1034 status = remote_interactive(&id_ctr->auth.id1,
1035 &dc, uctr->usr.id3);
1036 return TooMuchInformation(status);
1038 case GENERAL_LOGON_TYPE:
1039 default:
1041 return NT_STATUS_ACCESS_DENIED;
1044 return NT_STATUS_ACCESS_DENIED;
1048 * IMPORTANT: do a General Login BEFORE the others,
1049 * because "update encrypted" may be enabled, which
1050 * will result in the smb password entry being added.
1052 * calling general login AFTER the getsampwntname() is
1053 * not guaranteed to deliver.
1056 if (logon_level == GENERAL_LOGON_TYPE)
1058 /* general login. cleartext password */
1059 status = net_login_general(&id_ctr->auth.id4, &dc,
1060 usr_sess_key);
1061 enc_user_sess_key = usr_sess_key;
1062 if (status != NT_STATUS_NOPROBLEMO)
1064 return TooMuchInformation(status);
1066 (*auth_resp) = 1;
1070 * now obtain smb passwd entry, which MAY have just been
1071 * added by "update encrypted" in general login.
1073 * this also obtains the user's groups. all this is
1074 * needed for the user profile.
1077 become_root(True);
1078 status_pwd = direct_samr_userinfo(uni_samusr, 21, &ctr,
1079 &gids, &num_gids, False);
1080 unbecome_root(True);
1082 if (status_pwd != NT_STATUS_NOPROBLEMO)
1084 free_samr_userinfo_ctr(&ctr);
1086 return TooMuchInformation(status_pwd);
1090 * check the Account Control Bits
1093 acb_info = ctr.info.id21->acb_info;
1095 if (IS_BITS_SET_ALL(acb_info, ACB_DISABLED))
1097 return TooMuchInformation(NT_STATUS_ACCOUNT_DISABLED);
1100 if (IS_BITS_SET_ALL(acb_info, ACB_DOMTRUST))
1102 return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT;
1105 if (IS_BITS_SET_ALL(acb_info, ACB_SVRTRUST))
1107 return NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT;
1110 if (IS_BITS_SET_ALL(acb_info, ACB_WSTRUST))
1112 return NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT;
1116 * get some user profile info
1119 logon_time = ctr.info.id21->logon_time;
1120 logoff_time = ctr.info.id21->logoff_time;
1121 kickoff_time = ctr.info.id21->kickoff_time;
1122 pass_last_set_time = ctr.info.id21->pass_last_set_time;
1123 pass_can_change_time = ctr.info.id21->pass_can_change_time;
1124 pass_must_change_time = ctr.info.id21->pass_must_change_time;
1125 uni_nt_name = &ctr.info.id21->uni_user_name;
1126 uni_full_name = &ctr.info.id21->uni_full_name;
1127 uni_home_dir = &ctr.info.id21->uni_home_dir;
1128 uni_dir_drive = &ctr.info.id21->uni_dir_drive;
1129 uni_logon_script = &ctr.info.id21->uni_logon_script;
1130 uni_profile_path = &ctr.info.id21->uni_profile_path;
1131 user_rid = ctr.info.id21->user_rid;
1132 group_rid = ctr.info.id21->group_rid;
1135 * validate password - if required
1138 if (!(IS_BITS_SET_ALL(acb_info, ACB_PWNOTREQ)))
1140 switch (logon_level)
1142 case INTERACTIVE_LOGON_TYPE:
1144 /* interactive login. */
1145 status = net_login_interactive(&id_ctr->auth.
1146 id1, &dc);
1147 (*auth_resp) = 1;
1148 break;
1150 case NETWORK_LOGON_TYPE:
1152 /* network login. lm challenge and 24 byte responses */
1153 status = net_login_network(&id_ctr->auth.id2,
1154 acb_info, &dc,
1155 usr_sess_key,
1156 lm_pw8);
1157 padding = lm_pw8;
1158 enc_user_sess_key = usr_sess_key;
1159 (*auth_resp) = 1;
1160 break;
1162 case GENERAL_LOGON_TYPE:
1164 /* general login type ALREADY been checked */
1165 break;
1168 if (status != NT_STATUS_NOPROBLEMO)
1170 safe_free(gids);
1171 free_samr_userinfo_ctr(&ctr);
1172 return TooMuchInformation(status);
1176 /* lkclXXXX this is the point at which, if the login was
1177 successful, that the SAM Local Security Authority should
1178 record that the user is logged in to the domain.
1181 /* return the profile plus other bits :-) */
1183 make_unistr2(&uni_myname, global_myname, strlen(global_myname));
1184 make_unistr2(&uni_sam_name, global_sam_name, strlen(global_sam_name));
1185 switch (validation_level)
1187 case 2:
1189 uctr->usr.id2 = g_new(NET_USER_INFO_2, 1);
1190 if (uctr->usr.id2 == NULL)
1192 status = NT_STATUS_INVALID_PARAMETER;
1193 break;
1195 make_net_user_info2W(uctr->usr.id2, &logon_time,
1196 &logoff_time, &kickoff_time,
1197 &pass_last_set_time,
1198 &pass_can_change_time,
1199 &pass_must_change_time,
1200 uni_nt_name, uni_full_name,
1201 uni_logon_script,
1202 uni_profile_path, uni_home_dir,
1203 uni_dir_drive, 0, 0, user_rid,
1204 group_rid, num_gids, gids, 0x20,
1205 enc_user_sess_key, &uni_myname,
1206 &uni_sam_name, padding,
1207 &global_sam_sid);
1208 break;
1210 case 3:
1212 uctr->usr.id3 = g_new(NET_USER_INFO_3, 1);
1213 if (uctr->usr.id3 == NULL)
1215 status = NT_STATUS_INVALID_PARAMETER;
1216 break;
1218 make_net_user_info3W(uctr->usr.id3, &logon_time,
1219 &logoff_time, &kickoff_time,
1220 &pass_last_set_time,
1221 &pass_can_change_time,
1222 &pass_must_change_time,
1223 uni_nt_name, uni_full_name,
1224 uni_logon_script,
1225 uni_profile_path, uni_home_dir,
1226 uni_dir_drive, 0,
1228 user_rid, group_rid, num_gids,
1229 gids, 0x20,
1230 enc_user_sess_key, &uni_myname,
1231 &uni_sam_name, padding,
1232 &global_sam_sid, NULL);
1233 break;
1235 default:
1237 status = NT_STATUS_INVALID_INFO_CLASS;
1238 break;
1242 /* Free any allocated groups array. */
1243 safe_free(gids);
1244 free_samr_userinfo_ctr(&ctr);
1245 if (status != NT_STATUS_NOPROBLEMO)
1247 return TooMuchInformation(status);
1250 return NT_STATUS_NOPROBLEMO;
1253 /*************************************************************************
1254 _net_sam_logoff
1255 *************************************************************************/
1256 uint32 _net_sam_logoff(const DOM_SAM_INFO * sam_id, DOM_CRED * srv_creds)
1258 fstring trust_name;
1259 struct dcinfo dc;
1261 ZERO_STRUCT(dc);
1262 unistr2_to_ascii(trust_name,
1263 &(sam_id->client.login.uni_comp_name),
1264 sizeof(trust_name) - 1);
1265 if (!cred_get(global_sam_name, trust_name, &dc))
1267 return NT_STATUS_ACCESS_DENIED;
1270 /* checks and updates credentials. creates reply credentials */
1271 if (!deal_with_creds(dc.sess_key, &(dc.clnt_cred),
1272 &(sam_id->client.cred), srv_creds))
1274 return NT_STATUS_ACCESS_DENIED;
1277 memcpy(&(dc.srv_cred), &(dc.clnt_cred), sizeof(dc.clnt_cred));
1278 if (!cred_store(global_sam_name, trust_name, &dc))
1280 return NT_STATUS_ACCESS_DENIED;
1283 return NT_STATUS_NOPROBLEMO;
1286 /*************************************************************************
1287 _net_sam_sync
1288 *************************************************************************/
1289 uint32 _net_sam_sync(const UNISTR2 *uni_srv_name,
1290 const UNISTR2 *uni_cli_name,
1291 DOM_CRED * cli_creds,
1292 DOM_CRED * srv_creds,
1293 uint32 database_id,
1294 uint32 restart_state,
1295 uint32 *sync_context,
1296 uint32 max_size,
1297 uint32 *num_deltas,
1298 uint32 *num_deltas2,
1299 SAM_DELTA_HDR * hdr_deltas, SAM_DELTA_CTR * deltas)
1301 fstring trust_name;
1302 int i = 0;
1303 POLICY_HND sam_pol;
1304 POLICY_HND dom_pol;
1305 uint32 enum_status;
1306 SAM_ENTRY *sam = NULL;
1307 UNISTR2 *uni_acct_name = NULL;
1308 uint32 start_idx = 0x0;
1309 uint32 num_sam_users = 0;
1310 uint32 idx;
1311 struct dcinfo dc;
1313 unistr2_to_ascii(trust_name, uni_cli_name, sizeof(trust_name) - 1);
1314 if (!cred_get(global_sam_name, trust_name, &dc))
1316 return NT_STATUS_ACCESS_DENIED;
1319 /* checks and updates credentials. creates reply credentials */
1320 if (!deal_with_creds(dc.sess_key, &dc.clnt_cred,
1321 cli_creds, srv_creds))
1323 return NT_STATUS_ACCESS_DENIED;
1326 memcpy(&dc.srv_cred, &dc.clnt_cred, sizeof(dc.clnt_cred));
1327 if (!cred_store(global_sam_name, trust_name, &dc))
1329 return NT_STATUS_ACCESS_DENIED;
1332 (*sync_context) = 1;
1333 if (_samr_connect(NULL, SEC_RIGHTS_MAXIMUM_ALLOWED, &sam_pol) !=
1334 NT_STATUS_NOPROBLEMO)
1336 return NT_STATUS_ACCESS_DENIED;
1338 if (_samr_open_domain(&sam_pol, SEC_RIGHTS_MAXIMUM_ALLOWED,
1339 &global_sam_sid,
1340 &dom_pol) != NT_STATUS_NOPROBLEMO)
1342 _samr_close(&sam_pol);
1343 return NT_STATUS_ACCESS_DENIED;
1347 * enumerate users, first
1352 enum_status = _samr_enum_dom_users(&dom_pol,
1353 &start_idx,
1354 0x0, 0x0, 0x10000,
1355 &sam,
1356 &uni_acct_name,
1357 &num_sam_users);
1359 while (enum_status == STATUS_MORE_ENTRIES);
1361 for (idx = 0; idx < num_sam_users; idx++)
1363 SAM_USERINFO_CTR ctr;
1364 POLICY_HND usr_pol;
1365 uint32 status_usr = NT_STATUS_NOPROBLEMO;
1366 ZERO_STRUCT(ctr);
1367 status_usr =
1368 _samr_open_user(&dom_pol, SEC_RIGHTS_MAXIMUM_ALLOWED,
1369 sam[idx].rid, &usr_pol);
1370 if (status_usr == NT_STATUS_NOPROBLEMO
1371 && _samr_query_userinfo(&usr_pol, 0x21,
1372 &ctr) == NT_STATUS_NOPROBLEMO)
1374 SAM_USER_INFO_21 *usr = ctr.info.id21;
1375 make_sam_delta_hdr(&hdr_deltas[i], 5, usr->user_rid);
1376 make_sam_account_info(&deltas[i].account_info,
1377 &usr->uni_user_name,
1378 &usr->uni_full_name,
1379 usr->user_rid, usr->group_rid,
1380 &usr->uni_home_dir,
1381 &usr->uni_dir_drive,
1382 &usr->uni_logon_script,
1383 &usr->uni_acct_desc,
1384 usr->acb_info,
1385 &usr->uni_profile_path,
1386 &usr->uni_workstations,
1387 &usr->uni_unknown_str,
1388 &usr->uni_munged_dial);
1389 i++;
1390 free_samr_userinfo_ctr(&ctr);
1393 if (status_usr == NT_STATUS_NOPROBLEMO)
1395 _samr_close(&usr_pol);
1399 safe_free(sam);
1400 safe_free(uni_acct_name);
1402 sam = NULL;
1403 uni_acct_name = NULL;
1404 num_sam_users = 0;
1406 _samr_close(&dom_pol);
1407 _samr_close(&sam_pol);
1409 (*num_deltas2) = i;
1410 (*num_deltas) = i;
1412 return NT_STATUS_NOPROBLEMO;