3 * Unix SMB/Netbios implementation.
5 * RPC Pipe client / server routines
6 * Copyright (C) Andrew Tridgell 1992-1997,
7 * Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
8 * Copyright (C) Paul Ashton 1997.
9 * Copyright (C) Jeremy Allison 1998.
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.
30 extern int DEBUGLEVEL;
32 extern BOOL sam_logon_in_ssb;
33 extern pstring samlogon_user;
34 extern pstring global_myname;
35 extern DOM_SID global_sam_sid;
37 /*************************************************************************
39 *************************************************************************/
40 static void make_net_r_req_chal(NET_R_REQ_CHAL *r_c,
41 DOM_CHAL *srv_chal, int status)
43 DEBUG(6,("make_net_r_req_chal: %d\n", __LINE__));
44 memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(srv_chal->data));
48 /*************************************************************************
50 *************************************************************************/
51 static void net_reply_req_chal(NET_Q_REQ_CHAL *q_c, prs_struct *rdata,
52 DOM_CHAL *srv_chal, uint32 srv_time)
56 DEBUG(6,("net_reply_req_chal: %d\n", __LINE__));
58 /* set up the LSA REQUEST CHALLENGE response */
59 make_net_r_req_chal(&r_c, srv_chal, srv_time);
61 /* store the response in the SMB stream */
62 net_io_r_req_chal("", &r_c, rdata, 0);
64 DEBUG(6,("net_reply_req_chal: %d\n", __LINE__));
68 /*************************************************************************
69 net_reply_logon_ctrl2:
70 *************************************************************************/
71 static void net_reply_logon_ctrl2(NET_Q_LOGON_CTRL2 *q_l, prs_struct *rdata,
72 uint32 flags, uint32 pdc_status, uint32 logon_attempts,
73 uint32 tc_status, char *trust_domain_name)
75 NET_R_LOGON_CTRL2 r_l;
77 DEBUG(6,("net_reply_logon_ctrl2: %d\n", __LINE__));
79 /* set up the Logon Control2 response */
80 make_r_logon_ctrl2(&r_l, q_l->query_level,
81 flags, pdc_status, logon_attempts,
82 tc_status, trust_domain_name);
84 /* store the response in the SMB stream */
85 net_io_r_logon_ctrl2("", &r_l, rdata, 0);
87 DEBUG(6,("net_reply_logon_ctrl2: %d\n", __LINE__));
91 /*************************************************************************
92 net_reply_trust_dom_list:
93 *************************************************************************/
94 static void net_reply_trust_dom_list(NET_Q_TRUST_DOM_LIST *q_t, prs_struct *rdata,
95 uint32 num_trust_domains, char *trust_domain_name)
97 NET_R_TRUST_DOM_LIST r_t;
99 DEBUG(6,("net_reply_trust_dom_list: %d\n", __LINE__));
101 /* set up the Trusted Domain List response */
102 make_r_trust_dom(&r_t, num_trust_domains, trust_domain_name);
104 /* store the response in the SMB stream */
105 net_io_r_trust_dom("", &r_t, rdata, 0);
107 DEBUG(6,("net_reply_trust_dom_listlogon_ctrl2: %d\n", __LINE__));
111 /*************************************************************************
113 *************************************************************************/
114 static void make_net_r_auth_2(NET_R_AUTH_2 *r_a,
115 DOM_CHAL *resp_cred, NEG_FLAGS *flgs, int status)
117 memcpy( r_a->srv_chal.data, resp_cred->data, sizeof(resp_cred->data));
118 memcpy(&(r_a->srv_flgs) , flgs , sizeof(r_a->srv_flgs));
119 r_a->status = status;
122 /*************************************************************************
124 *************************************************************************/
125 static void net_reply_auth_2(NET_Q_AUTH_2 *q_a, prs_struct *rdata,
126 DOM_CHAL *resp_cred, int status)
131 srv_flgs.neg_flags = 0x000001ff;
133 /* set up the LSA AUTH 2 response */
135 make_net_r_auth_2(&r_a, resp_cred, &srv_flgs, status);
137 /* store the response in the SMB stream */
138 net_io_r_auth_2("", &r_a, rdata, 0);
142 /***********************************************************************************
143 make_net_r_srv_pwset:
144 ***********************************************************************************/
145 static void make_net_r_srv_pwset(NET_R_SRV_PWSET *r_s,
146 DOM_CRED *srv_cred, int status)
148 DEBUG(5,("make_net_r_srv_pwset: %d\n", __LINE__));
150 memcpy(&(r_s->srv_cred), srv_cred, sizeof(r_s->srv_cred));
151 r_s->status = status;
153 DEBUG(5,("make_net_r_srv_pwset: %d\n", __LINE__));
156 /*************************************************************************
158 *************************************************************************/
159 static void net_reply_srv_pwset(NET_Q_SRV_PWSET *q_s, prs_struct *rdata,
160 DOM_CRED *srv_cred, int status)
164 DEBUG(5,("net_srv_pwset: %d\n", __LINE__));
166 /* set up the LSA Server Password Set response */
167 make_net_r_srv_pwset(&r_s, srv_cred, status);
169 /* store the response in the SMB stream */
170 net_io_r_srv_pwset("", &r_s, rdata, 0);
172 DEBUG(5,("net_srv_pwset: %d\n", __LINE__));
176 /*************************************************************************
178 *************************************************************************/
179 static void net_reply_sam_logon(NET_Q_SAM_LOGON *q_s, prs_struct *rdata,
180 DOM_CRED *srv_cred, NET_USER_INFO_3 *user_info,
185 /* XXXX maybe we want to say 'no', reject the client's credentials */
186 r_s.buffer_creds = 1; /* yes, we have valid server credentials */
187 memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds));
189 /* store the user information, if there is any. */
190 r_s.user = user_info;
191 if (status == 0x0 && user_info != NULL && user_info->ptr_user_info != 0)
193 r_s.switch_value = 3; /* indicates type of validation user info */
197 r_s.switch_value = 0; /* indicates no info */
201 r_s.auth_resp = 1; /* authoritative response */
203 /* store the response in the SMB stream */
204 net_io_r_sam_logon("", &r_s, rdata, 0);
209 /*************************************************************************
210 net_reply_sam_logoff:
211 *************************************************************************/
212 static void net_reply_sam_logoff(NET_Q_SAM_LOGOFF *q_s, prs_struct *rdata,
216 NET_R_SAM_LOGOFF r_s;
218 /* XXXX maybe we want to say 'no', reject the client's credentials */
219 r_s.buffer_creds = 1; /* yes, we have valid server credentials */
220 memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds));
224 /* store the response in the SMB stream */
225 net_io_r_sam_logoff("", &r_s, rdata, 0);
229 /******************************************************************
230 gets a machine password entry. checks access rights of the host.
231 ******************************************************************/
232 static BOOL get_md4pw(char *md4pw, char *mach_name, char *mach_acct)
234 struct smb_passwd *smb_pass;
238 * Currently this code is redundent as we already have a filter
239 * by hostname list. What this code really needs to do is to
240 * get a hosts allowed/hosts denied list from the SAM database
241 * on a per user basis, and make the access decision there.
242 * I will leave this code here for now as a reminder to implement
243 * this at a later date. JRA.
246 if (!allow_access(lp_domain_hostsdeny(), lp_domain_hostsallow(),
247 client_name(Client), client_addr(Client)))
249 DEBUG(0,("get_md4pw: Workstation %s denied access to domain\n", mach_acct));
255 smb_pass = getsmbpwnam(mach_acct);
258 if ((smb_pass) != NULL && !(smb_pass->acct_ctrl & ACB_DISABLED) &&
259 (smb_pass->smb_nt_passwd != NULL))
261 memcpy(md4pw, smb_pass->smb_nt_passwd, 16);
262 dump_data(5, md4pw, 16);
266 DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct));
270 /*************************************************************************
272 *************************************************************************/
273 static void api_net_req_chal( uint16 vuid,
285 DEBUG(5,("api_net_req_chal(%d): vuid %d\n", __LINE__, (int)vuid));
287 if ((vuser = get_valid_user_struct(vuid)) == NULL)
290 /* grab the challenge... */
291 net_io_q_req_chal("", &q_r, data, 0);
293 fstrcpy(mach_acct, unistrn2(q_r.uni_logon_clnt.buffer,
294 q_r.uni_logon_clnt.uni_str_len));
296 fstrcpy(mach_name, mach_acct);
299 fstrcat(mach_acct, "$");
301 if (get_md4pw((char *)vuser->dc.md4pw, mach_name, mach_acct))
303 /* copy the client credentials */
304 memcpy(vuser->dc.clnt_chal.data , q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data));
305 memcpy(vuser->dc.clnt_cred.challenge.data, q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data));
307 /* create a server challenge for the client */
308 /* Set these to random values. */
309 generate_random_buffer(vuser->dc.srv_chal.data, 8, False);
311 memcpy(vuser->dc.srv_cred.challenge.data, vuser->dc.srv_chal.data, 8);
313 bzero(vuser->dc.sess_key, sizeof(vuser->dc.sess_key));
315 /* from client / server challenges and md4 password, generate sess key */
316 cred_session_key(&(vuser->dc.clnt_chal), &(vuser->dc.srv_chal),
317 (char *)vuser->dc.md4pw, vuser->dc.sess_key);
321 /* lkclXXXX take a guess at a good error message to return :-) */
322 status = 0xC0000000 | NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT;
325 /* construct reply. */
326 net_reply_req_chal(&q_r, rdata,
327 &(vuser->dc.srv_chal), status);
331 /*************************************************************************
333 *************************************************************************/
334 static void api_net_auth_2( uint16 vuid,
346 if ((vuser = get_valid_user_struct(vuid)) == NULL)
351 /* grab the challenge... */
352 net_io_q_auth_2("", &q_a, data, 0);
354 /* check that the client credentials are valid */
355 if (cred_assert(&(q_a.clnt_chal), vuser->dc.sess_key,
356 &(vuser->dc.clnt_cred.challenge), srv_time))
359 /* create server challenge for inclusion in the reply */
360 cred_create(vuser->dc.sess_key, &(vuser->dc.srv_cred.challenge), srv_time, &srv_cred);
362 /* copy the received client credentials for use next time */
363 memcpy(vuser->dc.clnt_cred.challenge.data, q_a.clnt_chal.data, sizeof(q_a.clnt_chal.data));
364 memcpy(vuser->dc.srv_cred .challenge.data, q_a.clnt_chal.data, sizeof(q_a.clnt_chal.data));
368 status = NT_STATUS_ACCESS_DENIED | 0xC0000000;
371 /* construct reply. */
372 net_reply_auth_2(&q_a, rdata, &srv_cred, status);
376 /*************************************************************************
378 *************************************************************************/
379 static void api_net_srv_pwset( uint16 vuid,
384 uint32 status = NT_STATUS_WRONG_PASSWORD|0xC0000000;
387 struct smb_passwd *smb_pass;
391 if ((vuser = get_valid_user_struct(vuid)) == NULL)
394 /* grab the challenge and encrypted password ... */
395 net_io_q_srv_pwset("", &q_a, data, 0);
397 /* checks and updates credentials. creates reply credentials */
398 if (deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred),
399 &(q_a.clnt_id.cred), &srv_cred))
401 memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred));
403 DEBUG(5,("api_net_srv_pwset: %d\n", __LINE__));
405 pstrcpy(mach_acct, unistrn2(q_a.clnt_id.login.uni_acct_name.buffer,
406 q_a.clnt_id.login.uni_acct_name.uni_str_len));
408 DEBUG(3,("Server Password Set Wksta:[%s]\n", mach_acct));
411 smb_pass = getsmbpwnam(mach_acct);
414 if (smb_pass != NULL)
416 unsigned char pwd[16];
419 DEBUG(100,("Server password set : new given value was :\n"));
420 for(i = 0; i < 16; i++)
422 DEBUG(100,("%02X ", q_a.pwd[i]));
426 cred_hash3( pwd, q_a.pwd, vuser->dc.sess_key, 0);
428 /* lies! nt and lm passwords are _not_ the same: don't care */
429 smb_pass->smb_passwd = pwd;
430 smb_pass->smb_nt_passwd = pwd;
431 smb_pass->acct_ctrl = ACB_WSTRUST;
434 ret = mod_smbpwd_entry(smb_pass,False);
444 DEBUG(5,("api_net_srv_pwset: %d\n", __LINE__));
449 /* lkclXXXX take a guess at a sensible error code to return... */
450 status = 0xC0000000 | NT_STATUS_NETWORK_CREDENTIAL_CONFLICT;
453 /* Construct reply. */
454 net_reply_srv_pwset(&q_a, rdata, &srv_cred, status);
458 /*************************************************************************
460 *************************************************************************/
461 static void api_net_sam_logoff( uint16 vuid,
465 NET_Q_SAM_LOGOFF q_l;
472 if ((vuser = get_valid_user_struct(vuid)) == NULL)
475 /* the DOM_ID_INFO_1 structure is a bit big. plus we might want to
476 dynamically allocate it inside net_io_q_sam_logon, at some point */
477 q_l.sam_id.ctr = &ctr;
479 /* grab the challenge... */
480 net_io_q_sam_logoff("", &q_l, data, 0);
482 /* checks and updates credentials. creates reply credentials */
483 deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred),
484 &(q_l.sam_id.client.cred), &srv_cred);
485 memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred));
487 /* construct reply. always indicate success */
488 net_reply_sam_logoff(&q_l, rdata,
493 /*************************************************************************
494 net_login_interactive:
495 *************************************************************************/
496 static uint32 net_login_interactive(NET_ID_INFO_1 *id1,
497 struct smb_passwd *smb_pass,
504 unsigned char key[16];
507 memcpy(key, vuser->dc.sess_key, 8);
509 memcpy(lm_pwd, id1->lm_owf.data, 16);
510 memcpy(nt_pwd, id1->nt_owf.data, 16);
512 #ifdef DEBUG_PASSWORD
514 dump_data(100, key, 16);
516 DEBUG(100,("lm owf password:"));
517 dump_data(100, lm_pwd, 16);
519 DEBUG(100,("nt owf password:"));
520 dump_data(100, nt_pwd, 16);
523 SamOEMhash((uchar *)lm_pwd, key, False);
524 SamOEMhash((uchar *)nt_pwd, key, False);
526 #ifdef DEBUG_PASSWORD
527 DEBUG(100,("decrypt of lm owf password:"));
528 dump_data(100, lm_pwd, 16);
530 DEBUG(100,("decrypt of nt owf password:"));
531 dump_data(100, nt_pwd, 16);
534 if (memcmp(smb_pass->smb_passwd , lm_pwd, 16) != 0 &&
535 memcmp(smb_pass->smb_nt_passwd, nt_pwd, 16) != 0)
537 status = 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
543 /*************************************************************************
545 *************************************************************************/
546 static uint32 net_login_network(NET_ID_INFO_2 *id2,
547 struct smb_passwd *smb_pass)
549 DEBUG(5,("net_login_network: lm_len: %d nt_len: %d\n",
550 id2->hdr_lm_chal_resp.str_str_len,
551 id2->hdr_nt_chal_resp.str_str_len));
553 /* JRA. Check the NT password first if it exists - this is a higher quality
554 password, if it exists and it doesn't match - fail. */
556 if (id2->hdr_nt_chal_resp.str_str_len == 24 &&
557 smb_pass->smb_nt_passwd != NULL)
559 if(smb_password_check((char *)id2->nt_chal_resp.buffer,
560 smb_pass->smb_nt_passwd,
564 return 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
567 /* lkclXXXX this is not a good place to put disabling of LM hashes in.
568 if that is to be done, first move this entire function into a
569 library routine that calls the two smb_password_check() functions.
570 if disabling LM hashes (which nt can do for security reasons) then
571 an attempt should be made to disable them everywhere (which nt does
572 not do, for various security-hole reasons).
575 if (id2->hdr_lm_chal_resp.str_str_len == 24 &&
576 smb_password_check((char *)id2->lm_chal_resp.buffer,
577 smb_pass->smb_passwd,
584 /* oops! neither password check succeeded */
586 return 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
589 /*************************************************************************
591 *************************************************************************/
592 static void api_net_sam_logon( uint16 vuid,
598 NET_USER_INFO_3 usr_info;
601 struct smb_passwd *smb_pass = NULL;
602 UNISTR2 *uni_samlogon_user = NULL;
604 user_struct *vuser = NULL;
606 if ((vuser = get_valid_user_struct(vuid)) == NULL)
609 q_l.sam_id.ctr = &ctr;
611 net_io_q_sam_logon("", &q_l, data, 0);
613 /* checks and updates credentials. creates reply credentials */
614 if (!deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred),
615 &(q_l.sam_id.client.cred), &srv_cred))
617 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
621 memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred));
624 /* find the username */
628 switch (q_l.sam_id.logon_level)
630 case INTERACTIVE_LOGON_TYPE:
632 uni_samlogon_user = &(q_l.sam_id.ctr->auth.id1.uni_user_name);
634 DEBUG(3,("SAM Logon (Interactive). Domain:[%s]. ", lp_workgroup()));
639 uni_samlogon_user = &(q_l.sam_id.ctr->auth.id2.uni_user_name);
641 DEBUG(3,("SAM Logon (Network). Domain:[%s]. ", lp_workgroup()));
646 DEBUG(2,("SAM Logon: unsupported switch value\n"));
647 status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
651 } /* end if status == 0 */
653 /* check username exists */
657 pstrcpy(samlogon_user, unistrn2(uni_samlogon_user->buffer,
658 uni_samlogon_user->uni_str_len));
660 DEBUG(3,("User:[%s]\n", samlogon_user));
663 * Convert to a UNIX username.
665 map_username(samlogon_user);
668 * Do any case conversions.
670 (void)Get_Pwnam(samlogon_user, True);
673 smb_pass = getsmbpwnam(samlogon_user);
676 if (smb_pass == NULL)
677 status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
678 else if (smb_pass->acct_ctrl & ACB_PWNOTREQ)
680 else if (smb_pass->acct_ctrl & ACB_DISABLED)
681 status = 0xC0000000 | NT_STATUS_ACCOUNT_DISABLED;
684 /* Validate password - if required. */
686 if ((status == 0) && !(smb_pass->acct_ctrl & ACB_PWNOTREQ))
688 switch (q_l.sam_id.logon_level)
690 case INTERACTIVE_LOGON_TYPE:
692 /* interactive login. */
693 status = net_login_interactive(&q_l.sam_id.ctr->auth.id1, smb_pass, vuser);
698 /* network login. lm challenge and 24 byte responses */
699 status = net_login_network(&q_l.sam_id.ctr->auth.id2, smb_pass);
705 /* lkclXXXX this is the point at which, if the login was
706 successful, that the SAM Local Security Authority should
707 record that the user is logged in to the domain.
710 /* return the profile plus other bits :-) */
714 DOM_GID *gids = NULL;
717 pstring logon_script;
718 pstring profile_path;
722 pstring my_workgroup;
723 pstring domain_groups;
727 /* set up pointer indicating user/password failed to be found */
728 usr_info.ptr_user_info = 0;
730 dummy_time.low = 0xffffffff;
731 dummy_time.high = 0x7fffffff;
733 /* XXXX hack to get standard_sub_basic() to use sam logon username */
734 /* possibly a better way would be to do a become_user() call */
735 sam_logon_in_ssb = True;
737 pstrcpy(logon_script, lp_logon_script());
738 pstrcpy(profile_path, lp_logon_path());
740 pstrcpy(my_workgroup, lp_workgroup());
742 pstrcpy(home_drive, lp_logon_drive());
743 pstrcpy(home_dir, lp_logon_home());
745 pstrcpy(my_name, global_myname);
749 * This is the point at which we get the group
750 * database - we should be getting the gid_t list
751 * from /etc/group and then turning the uids into
752 * rids and then into machine sids for this user.
756 get_domain_user_groups(domain_groups, samlogon_user);
759 * make_dom_gids allocates the gids array. JRA.
762 num_gids = make_dom_gids(domain_groups, &gids);
764 sam_logon_in_ssb = False;
766 if (pdb_name_to_rid(samlogon_user, &r_uid, &r_gid))
768 make_net_user_info3(&usr_info,
769 &dummy_time, /* logon_time */
770 &dummy_time, /* logoff_time */
771 &dummy_time, /* kickoff_time */
772 &dummy_time, /* pass_last_set_time */
773 &dummy_time, /* pass_can_change_time */
774 &dummy_time, /* pass_must_change_time */
776 samlogon_user , /* user_name */
777 vuser->real_name, /* full_name */
778 logon_script , /* logon_script */
779 profile_path , /* profile_path */
780 home_dir , /* home_dir */
781 home_drive , /* dir_drive */
784 0, /* bad_pw_count */
786 r_uid , /* RID user_id */
787 r_gid , /* RID group_id */
788 num_gids, /* uint32 num_groups */
789 gids , /* DOM_GID *gids */
790 0x20 , /* uint32 user_flgs (?) */
792 NULL, /* char sess_key[16] */
794 my_name , /* char *logon_srv */
795 my_workgroup, /* char *logon_dom */
797 &global_sam_sid, /* DOM_SID *dom_sid */
798 NULL); /* char *other_sids */
802 status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
805 /* Free any allocated groups array. */
810 net_reply_sam_logon(&q_l, rdata, &srv_cred, &usr_info, status);
814 /*************************************************************************
815 api_net_trust_dom_list:
816 *************************************************************************/
817 static void api_net_trust_dom_list( uint16 vuid,
821 NET_Q_TRUST_DOM_LIST q_t;
823 char *trusted_domain = "test_domain";
825 DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
827 /* grab the lsa trusted domain list query... */
828 net_io_q_trust_dom("", &q_t, data, 0);
830 /* construct reply. */
831 net_reply_trust_dom_list(&q_t, rdata,
834 DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
838 /*************************************************************************
839 error messages cropping up when using nltest.exe...
840 *************************************************************************/
841 #define ERROR_NO_SUCH_DOMAIN 0x54b
842 #define ERROR_NO_LOGON_SERVERS 0x51f
844 /*************************************************************************
846 *************************************************************************/
847 static void api_net_logon_ctrl2( uint16 vuid,
851 NET_Q_LOGON_CTRL2 q_l;
853 /* lkclXXXX - guess what - absolutely no idea what these are! */
855 uint32 pdc_connection_status = 0x0;
856 uint32 logon_attempts = 0x0;
857 uint32 tc_status = ERROR_NO_LOGON_SERVERS;
858 char *trusted_domain = "test_domain";
860 DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
862 /* grab the lsa netlogon ctrl2 query... */
863 net_io_q_logon_ctrl2("", &q_l, data, 0);
865 /* construct reply. */
866 net_reply_logon_ctrl2(&q_l, rdata,
867 flags, pdc_connection_status, logon_attempts,
868 tc_status, trusted_domain);
870 DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
873 /*******************************************************************
874 array of \PIPE\NETLOGON operations
875 ********************************************************************/
876 static struct api_struct api_net_cmds [] =
878 { "NET_REQCHAL" , NET_REQCHAL , api_net_req_chal },
879 { "NET_AUTH2" , NET_AUTH2 , api_net_auth_2 },
880 { "NET_SRVPWSET" , NET_SRVPWSET , api_net_srv_pwset },
881 { "NET_SAMLOGON" , NET_SAMLOGON , api_net_sam_logon },
882 { "NET_SAMLOGOFF" , NET_SAMLOGOFF , api_net_sam_logoff },
883 { "NET_LOGON_CTRL2" , NET_LOGON_CTRL2 , api_net_logon_ctrl2 },
884 { "NET_TRUST_DOM_LIST", NET_TRUST_DOM_LIST, api_net_trust_dom_list },
888 /*******************************************************************
889 receives a netlogon pipe and responds.
890 ********************************************************************/
891 BOOL api_netlog_rpc(pipes_struct *p, prs_struct *data)
893 return api_rpcTNP(p, "api_netlog_rpc", api_net_cmds, data);