2 * Unix SMB/Netbios implementation.
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.
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
,
41 SAM_USERINFO_CTR
* ctr
,
43 uint32
*num_grps
, BOOL set
)
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
;
58 return NT_STATUS_INVALID_PARAMETER
;
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
)
80 status_usr
= _samr_lookup_names(&dom_pol
, 1, 0x3e8,
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
,
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
,
104 ("_samr_query_usergroups: status %x\n", status_grp
));
107 status_pwd
= _samr_set_userinfo(&usr_pol
, level
, ctr
);
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
)
127 if (status_usr
!= NT_STATUS_NOPROBLEMO
)
132 if (status_grp
!= NT_STATUS_NOPROBLEMO
)
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
;
156 make_unistr2(&uni_trust_acct
, trust_acct
, strlen(trust_acct
));
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()))
172 ("get_md4pw: Workstation %s denied access to domain\n",
178 if (strequal(trust_name
, global_myname
)
179 || strequal(trust_name
, "\\\\."))
182 DEBUG(10, ("get_md4pw: loop-back, use $MACHINE.ACC\n"));
183 ret
= msrpc_lsa_query_trust_passwd("\\\\.",
184 "$MACHINE.ACC", md4pw
,
186 return ret
? NT_STATUS_ACCESS_DENIED
: NT_STATUS_NOPROBLEMO
;
190 * must do all this as root
193 status_pwd
= direct_samr_userinfo(&uni_trust_acct
, 0x12, &ctr
,
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
;
221 unsigned char key
[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
));
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);
265 /*************************************************************************
266 net_login_interactive:
267 *************************************************************************/
268 static uint32
net_login_interactive(const NET_ID_INFO_1
* id1
,
271 const UNISTR2
*uni_samusr
= &id1
->uni_user_name
;
272 uint32 status
= NT_STATUS_NOPROBLEMO
;
273 SAM_USERINFO_CTR ctr
;
277 unsigned char key
[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);
297 status
= direct_samr_userinfo(uni_samusr
, 0x12, &ctr
,
300 if (status
!= NT_STATUS_NOPROBLEMO
)
302 free_samr_userinfo_ctr(&ctr
);
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
);
316 /*************************************************************************
318 *************************************************************************/
319 static uint32
net_login_general(const NET_ID_INFO_4
* id4
,
320 struct dcinfo
*dc
, char usr_sess_key
[16])
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
);
339 ("net_login_general: TODO - \"update encrypted\" disabled\n"));
340 if (pass_check(user
, general
, pw_len
, NULL
,
342 lp_update_encrypted()? update_smbpassword_file
:
346 unsigned char key
[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);
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);
360 return NT_STATUS_NOPROBLEMO
;
363 return NT_STATUS_WRONG_PASSWORD
;
366 /*************************************************************************
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
;
376 unsigned char key
[16];
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
,
389 lm_chal_resp
.buffer
, lm_pw_len
,
391 nt_chal_resp
.buffer
, nt_pw_len
, usr
);
393 DEBUG(5, ("END remote_network: %x\n", status
));
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);
413 /*************************************************************************
415 *************************************************************************/
416 static uint32
net_login_network(const NET_ID_INFO_2
* id2
,
419 char usr_sess_key
[16], char lm_pw8
[8])
421 const UNISTR2
*uni_samusr
= &id2
->uni_user_name
;
424 SAM_USERINFO_CTR ctr
;
425 unsigned char key
[16];
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);
434 status
= direct_samr_userinfo(uni_samusr
, 0x12, &ctr
, NULL
, NULL
,
438 if (status
!= NT_STATUS_NOPROBLEMO
)
440 free_samr_userinfo_ctr(&ctr
);
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
,
452 (const uchar
*)id2
->lm_chal_resp
.buffer
,
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);
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 /*************************************************************************
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
)
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
)
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;
550 /*******************************************************************
551 creates a NETLOGON_INFO_1 structure.
552 ********************************************************************/
553 static BOOL
make_netinfo_1(NETLOGON_INFO_1
* info
, uint32 flags
,
557 info
->pdc_status
= pdc_status
;
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
);
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
,
580 make_unistr2(&(info
->uni_trusted_dc_name
), "", 1);
586 /*************************************************************************
588 *************************************************************************/
589 uint32
_net_logon_ctrl2(const UNISTR2
*uni_server_name
,
590 uint32 function_code
,
593 uint32
*reply_switch_value
,
594 NETLOGON_INFO
* logon_info
)
596 /* lkclXXXX - guess what - absolutely no idea what these are! */
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
;
607 make_netinfo_1(&logon_info
->info1
, flags
, pdc_status
);
612 make_netinfo_2(&logon_info
->info2
, flags
, pdc_status
,
613 tc_status
, trusted_domain
);
618 make_netinfo_3(&logon_info
->info3
, flags
,
619 logon_attempts
); break;
623 /* take a guess at an error code... */
624 return NT_STATUS_INVALID_INFO_CLASS
;
629 return NT_STATUS_NOPROBLEMO
;
632 /*************************************************************************
634 *************************************************************************/
635 uint32
_net_trust_dom_list(const UNISTR2
*uni_server_name
,
636 uint32 function_code
, BUFFER2
* uni_trust_dom_name
)
640 enumtrustdoms(&doms
, &num_doms
);
641 make_buffer2_multi(uni_trust_dom_name
, doms
, num_doms
);
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 /*************************************************************************
654 *************************************************************************/
655 uint32
_net_auth(const UNISTR2
*uni_logon_srv
,
656 const UNISTR2
*uni_acct_name
,
658 const UNISTR2
*uni_comp_name
,
659 const DOM_CHAL
* clnt_chal
, DOM_CHAL
* srv_chal
)
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 */
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
,
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 /*************************************************************************
701 *************************************************************************/
702 uint32
_net_auth_2(const UNISTR2
*uni_logon_srv
,
703 const UNISTR2
*uni_acct_name
,
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
)
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
,
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 /*************************************************************************
772 *************************************************************************/
773 uint32
_net_srv_pwset(const UNISTR2
*uni_logon_srv
,
774 const UNISTR2
*uni_acct_name
,
776 const UNISTR2
*uni_comp_name
,
777 const DOM_CRED
* clnt_cred
,
778 const uint8 pwd
[16], DOM_CRED
* srv_cred
)
781 unsigned char hash3_pwd
[16];
785 SAM_USERINFO_CTR ctr
;
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 */
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 */
816 status_pwd
= direct_samr_userinfo(uni_acct_name
, 0x12, &ctr
,
819 if (status_pwd
!= NT_STATUS_NOPROBLEMO
)
821 free_samr_userinfo_ctr(&ctr
);
825 /* Some debug output, needed an iterater variable */
828 DEBUG(100, ("Server password set : new given value was :\n"));
829 for (i
= 0; i
< 16; i
++)
831 DEBUG(100, ("%02X ", pwd
[i
]));
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
));
843 status_pwd
= direct_samr_userinfo(uni_acct_name
, 0x12, &ctr
,
847 if (status_pwd
!= NT_STATUS_NOPROBLEMO
)
852 return NT_STATUS_NOPROBLEMO
;
855 static uint32
TooMuchInformation(uint32 status
)
857 #ifdef SANITISE_FOR_SECURITY_REASONS
860 case NT_STATUS_INVALID_INFO_CLASS
:
861 case NT_STATUS_INVALID_PARAMETER
:
862 case NT_STATUS_ACCESS_DENIED
:
863 case NT_STATUS_NOPROBLEMO
:
868 DEBUG(10,("TooMuchInformation: sanitising status %x\n", status
));
869 return NT_STATUS_ACCESS_DENIED
;
871 #else /* oh well, who cares, anyway */
876 /*************************************************************************
878 *************************************************************************/
879 uint32
_net_sam_logon(const UNISTR2
*uni_logon_srv
,
880 const UNISTR2
*uni_comp_name
,
881 const DOM_CRED
* clnt_cred
,
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
;
892 char *enc_user_sess_key
= NULL
;
893 char usr_sess_key
[16];
895 char *padding
= NULL
;
896 uint32 status_pwd
= 0x0;
897 SAM_USERINFO_CTR ctr
;
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
;
913 DOM_GID
*gids
= NULL
;
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
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)."));
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). "));
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). "));
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",
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
;
1024 switch (logon_level
)
1026 case NETWORK_LOGON_TYPE
:
1028 status
= remote_network(&id_ctr
->auth
.id2
, &dc
,
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
:
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
,
1061 enc_user_sess_key
= usr_sess_key
;
1062 if (status
!= NT_STATUS_NOPROBLEMO
)
1064 return TooMuchInformation(status
);
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.
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
.
1150 case NETWORK_LOGON_TYPE
:
1152 /* network login. lm challenge and 24 byte responses */
1153 status
= net_login_network(&id_ctr
->auth
.id2
,
1158 enc_user_sess_key
= usr_sess_key
;
1162 case GENERAL_LOGON_TYPE
:
1164 /* general login type ALREADY been checked */
1168 if (status
!= NT_STATUS_NOPROBLEMO
)
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
)
1189 uctr
->usr
.id2
= g_new(NET_USER_INFO_2
, 1);
1190 if (uctr
->usr
.id2
== NULL
)
1192 status
= NT_STATUS_INVALID_PARAMETER
;
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
,
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
,
1212 uctr
->usr
.id3
= g_new(NET_USER_INFO_3
, 1);
1213 if (uctr
->usr
.id3
== NULL
)
1215 status
= NT_STATUS_INVALID_PARAMETER
;
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
,
1225 uni_profile_path
, uni_home_dir
,
1228 user_rid
, group_rid
, num_gids
,
1230 enc_user_sess_key
, &uni_myname
,
1231 &uni_sam_name
, padding
,
1232 &global_sam_sid
, NULL
);
1237 status
= NT_STATUS_INVALID_INFO_CLASS
;
1242 /* Free any allocated groups array. */
1244 free_samr_userinfo_ctr(&ctr
);
1245 if (status
!= NT_STATUS_NOPROBLEMO
)
1247 return TooMuchInformation(status
);
1250 return NT_STATUS_NOPROBLEMO
;
1253 /*************************************************************************
1255 *************************************************************************/
1256 uint32
_net_sam_logoff(const DOM_SAM_INFO
* sam_id
, DOM_CRED
* srv_creds
)
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 /*************************************************************************
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
,
1294 uint32 restart_state
,
1295 uint32
*sync_context
,
1298 uint32
*num_deltas2
,
1299 SAM_DELTA_HDR
* hdr_deltas
, SAM_DELTA_CTR
* deltas
)
1306 SAM_ENTRY
*sam
= NULL
;
1307 UNISTR2
*uni_acct_name
= NULL
;
1308 uint32 start_idx
= 0x0;
1309 uint32 num_sam_users
= 0;
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
,
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
,
1359 while (enum_status
== STATUS_MORE_ENTRIES
);
1361 for (idx
= 0; idx
< num_sam_users
; idx
++)
1363 SAM_USERINFO_CTR ctr
;
1365 uint32 status_usr
= NT_STATUS_NOPROBLEMO
;
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
,
1381 &usr
->uni_dir_drive
,
1382 &usr
->uni_logon_script
,
1383 &usr
->uni_acct_desc
,
1385 &usr
->uni_profile_path
,
1386 &usr
->uni_workstations
,
1387 &usr
->uni_unknown_str
,
1388 &usr
->uni_munged_dial
);
1390 free_samr_userinfo_ctr(&ctr
);
1393 if (status_usr
== NT_STATUS_NOPROBLEMO
)
1395 _samr_close(&usr_pol
);
1400 safe_free(uni_acct_name
);
1403 uni_acct_name
= NULL
;
1406 _samr_close(&dom_pol
);
1407 _samr_close(&sam_pol
);
1412 return NT_STATUS_NOPROBLEMO
;