2 * Unix SMB/Netbios implementation.
4 * RPC Pipe client / server routines
5 * Copyright (C) Andrew Tridgell 1992-1997,
6 * Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
7 * Copyright (C) Paul Ashton 1997.
8 * Copyright (C) Jeremy Allison 1998.
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 extern int DEBUGLEVEL;
31 extern BOOL sam_logon_in_ssb;
32 extern pstring samlogon_user;
33 extern pstring global_myname;
34 extern DOM_SID global_sam_sid;
36 /*************************************************************************
38 *************************************************************************/
39 static void make_net_r_req_chal(NET_R_REQ_CHAL *r_c,
40 DOM_CHAL *srv_chal, int status)
42 DEBUG(6,("make_net_r_req_chal: %d\n", __LINE__));
43 memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(srv_chal->data));
47 /*************************************************************************
49 *************************************************************************/
50 static void net_reply_req_chal(NET_Q_REQ_CHAL *q_c, prs_struct *rdata,
51 DOM_CHAL *srv_chal, uint32 srv_time)
55 DEBUG(6,("net_reply_req_chal: %d\n", __LINE__));
57 /* set up the LSA REQUEST CHALLENGE response */
58 make_net_r_req_chal(&r_c, srv_chal, srv_time);
60 /* store the response in the SMB stream */
61 net_io_r_req_chal("", &r_c, rdata, 0);
63 DEBUG(6,("net_reply_req_chal: %d\n", __LINE__));
67 /*************************************************************************
68 net_reply_logon_ctrl2:
69 *************************************************************************/
70 static void net_reply_logon_ctrl2(NET_Q_LOGON_CTRL2 *q_l, prs_struct *rdata,
71 uint32 flags, uint32 pdc_status, uint32 logon_attempts,
72 uint32 tc_status, char *trust_domain_name)
74 NET_R_LOGON_CTRL2 r_l;
76 DEBUG(6,("net_reply_logon_ctrl2: %d\n", __LINE__));
78 /* set up the Logon Control2 response */
79 make_r_logon_ctrl2(&r_l, q_l->query_level,
80 flags, pdc_status, logon_attempts,
81 tc_status, trust_domain_name);
83 /* store the response in the SMB stream */
84 net_io_r_logon_ctrl2("", &r_l, rdata, 0);
86 DEBUG(6,("net_reply_logon_ctrl2: %d\n", __LINE__));
90 /*************************************************************************
91 net_reply_trust_dom_list:
92 *************************************************************************/
93 static void net_reply_trust_dom_list(NET_Q_TRUST_DOM_LIST *q_t, prs_struct *rdata,
94 uint32 num_trust_domains, char *trust_domain_name)
96 NET_R_TRUST_DOM_LIST r_t;
98 DEBUG(6,("net_reply_trust_dom_list: %d\n", __LINE__));
100 /* set up the Trusted Domain List response */
101 make_r_trust_dom(&r_t, num_trust_domains, trust_domain_name);
103 /* store the response in the SMB stream */
104 net_io_r_trust_dom("", &r_t, rdata, 0);
106 DEBUG(6,("net_reply_trust_dom_listlogon_ctrl2: %d\n", __LINE__));
110 /*************************************************************************
112 *************************************************************************/
113 static void make_net_r_auth_2(NET_R_AUTH_2 *r_a,
114 DOM_CHAL *resp_cred, NEG_FLAGS *flgs, int status)
116 memcpy( r_a->srv_chal.data, resp_cred->data, sizeof(resp_cred->data));
117 memcpy(&(r_a->srv_flgs) , flgs , sizeof(r_a->srv_flgs));
118 r_a->status = status;
121 /*************************************************************************
123 *************************************************************************/
124 static void net_reply_auth_2(NET_Q_AUTH_2 *q_a, prs_struct *rdata,
125 DOM_CHAL *resp_cred, int status)
130 srv_flgs.neg_flags = 0x000001ff;
132 /* set up the LSA AUTH 2 response */
134 make_net_r_auth_2(&r_a, resp_cred, &srv_flgs, status);
136 /* store the response in the SMB stream */
137 net_io_r_auth_2("", &r_a, rdata, 0);
141 /***********************************************************************************
142 make_net_r_srv_pwset:
143 ***********************************************************************************/
144 static void make_net_r_srv_pwset(NET_R_SRV_PWSET *r_s,
145 DOM_CRED *srv_cred, int status)
147 DEBUG(5,("make_net_r_srv_pwset: %d\n", __LINE__));
149 memcpy(&(r_s->srv_cred), srv_cred, sizeof(r_s->srv_cred));
150 r_s->status = status;
152 DEBUG(5,("make_net_r_srv_pwset: %d\n", __LINE__));
155 /*************************************************************************
157 *************************************************************************/
158 static void net_reply_srv_pwset(NET_Q_SRV_PWSET *q_s, prs_struct *rdata,
159 DOM_CRED *srv_cred, int status)
163 DEBUG(5,("net_srv_pwset: %d\n", __LINE__));
165 /* set up the LSA Server Password Set response */
166 make_net_r_srv_pwset(&r_s, srv_cred, status);
168 /* store the response in the SMB stream */
169 net_io_r_srv_pwset("", &r_s, rdata, 0);
171 DEBUG(5,("net_srv_pwset: %d\n", __LINE__));
175 /*************************************************************************
177 *************************************************************************/
178 static void net_reply_sam_logon(NET_Q_SAM_LOGON *q_s, prs_struct *rdata,
179 DOM_CRED *srv_cred, NET_USER_INFO_3 *user_info,
184 /* XXXX maybe we want to say 'no', reject the client's credentials */
185 r_s.buffer_creds = 1; /* yes, we have valid server credentials */
186 memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds));
188 /* store the user information, if there is any. */
189 r_s.user = user_info;
190 if (status == 0x0 && user_info != NULL && user_info->ptr_user_info != 0)
192 r_s.switch_value = 3; /* indicates type of validation user info */
196 r_s.switch_value = 0; /* indicates no info */
200 r_s.auth_resp = 1; /* authoritative response */
202 /* store the response in the SMB stream */
203 net_io_r_sam_logon("", &r_s, rdata, 0);
208 /*************************************************************************
209 net_reply_sam_logoff:
210 *************************************************************************/
211 static void net_reply_sam_logoff(NET_Q_SAM_LOGOFF *q_s, prs_struct *rdata,
215 NET_R_SAM_LOGOFF r_s;
217 /* XXXX maybe we want to say 'no', reject the client's credentials */
218 r_s.buffer_creds = 1; /* yes, we have valid server credentials */
219 memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds));
223 /* store the response in the SMB stream */
224 net_io_r_sam_logoff("", &r_s, rdata, 0);
228 /******************************************************************
229 gets a machine password entry. checks access rights of the host.
230 ******************************************************************/
231 static BOOL get_md4pw(char *md4pw, char *mach_name, char *mach_acct)
233 struct smb_passwd *smb_pass;
237 * Currently this code is redundent as we already have a filter
238 * by hostname list. What this code really needs to do is to
239 * get a hosts allowed/hosts denied list from the SAM database
240 * on a per user basis, and make the access decision there.
241 * I will leave this code here for now as a reminder to implement
242 * this at a later date. JRA.
245 if (!allow_access(lp_domain_hostsdeny(), lp_domain_hostsallow(),
246 client_name(Client), client_addr(Client)))
248 DEBUG(0,("get_md4pw: Workstation %s denied access to domain\n", mach_acct));
254 smb_pass = getsmbpwnam(mach_acct);
257 if ((smb_pass) != NULL && !(smb_pass->acct_ctrl & ACB_DISABLED) &&
258 (smb_pass->smb_nt_passwd != NULL))
260 memcpy(md4pw, smb_pass->smb_nt_passwd, 16);
261 dump_data(5, md4pw, 16);
265 DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct));
269 /*************************************************************************
271 *************************************************************************/
272 static void api_net_req_chal( uint16 vuid,
284 DEBUG(5,("api_net_req_chal(%d): vuid %d\n", __LINE__, (int)vuid));
286 if ((vuser = get_valid_user_struct(vuid)) == NULL)
289 /* grab the challenge... */
290 net_io_q_req_chal("", &q_r, data, 0);
292 fstrcpy(mach_acct, unistrn2(q_r.uni_logon_clnt.buffer,
293 q_r.uni_logon_clnt.uni_str_len));
295 fstrcpy(mach_name, mach_acct);
298 fstrcat(mach_acct, "$");
300 if (get_md4pw((char *)vuser->dc.md4pw, mach_name, mach_acct))
302 /* copy the client credentials */
303 memcpy(vuser->dc.clnt_chal.data , q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data));
304 memcpy(vuser->dc.clnt_cred.challenge.data, q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data));
306 /* create a server challenge for the client */
307 /* Set these to random values. */
308 generate_random_buffer(vuser->dc.srv_chal.data, 8, False);
310 memcpy(vuser->dc.srv_cred.challenge.data, vuser->dc.srv_chal.data, 8);
312 bzero(vuser->dc.sess_key, sizeof(vuser->dc.sess_key));
314 /* from client / server challenges and md4 password, generate sess key */
315 cred_session_key(&(vuser->dc.clnt_chal), &(vuser->dc.srv_chal),
316 (char *)vuser->dc.md4pw, vuser->dc.sess_key);
320 /* lkclXXXX take a guess at a good error message to return :-) */
321 status = 0xC0000000 | NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT;
324 /* construct reply. */
325 net_reply_req_chal(&q_r, rdata,
326 &(vuser->dc.srv_chal), status);
330 /*************************************************************************
332 *************************************************************************/
333 static void api_net_auth_2( uint16 vuid,
345 if ((vuser = get_valid_user_struct(vuid)) == NULL)
350 /* grab the challenge... */
351 net_io_q_auth_2("", &q_a, data, 0);
353 /* check that the client credentials are valid */
354 if (cred_assert(&(q_a.clnt_chal), vuser->dc.sess_key,
355 &(vuser->dc.clnt_cred.challenge), srv_time))
358 /* create server challenge for inclusion in the reply */
359 cred_create(vuser->dc.sess_key, &(vuser->dc.srv_cred.challenge), srv_time, &srv_cred);
361 /* copy the received client credentials for use next time */
362 memcpy(vuser->dc.clnt_cred.challenge.data, q_a.clnt_chal.data, sizeof(q_a.clnt_chal.data));
363 memcpy(vuser->dc.srv_cred .challenge.data, q_a.clnt_chal.data, sizeof(q_a.clnt_chal.data));
367 status = NT_STATUS_ACCESS_DENIED | 0xC0000000;
370 /* construct reply. */
371 net_reply_auth_2(&q_a, rdata, &srv_cred, status);
375 /*************************************************************************
377 *************************************************************************/
378 static void api_net_srv_pwset( uint16 vuid,
383 uint32 status = NT_STATUS_WRONG_PASSWORD|0xC0000000;
386 struct smb_passwd *smb_pass;
390 if ((vuser = get_valid_user_struct(vuid)) == NULL)
393 /* grab the challenge and encrypted password ... */
394 net_io_q_srv_pwset("", &q_a, data, 0);
396 /* checks and updates credentials. creates reply credentials */
397 if (deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred),
398 &(q_a.clnt_id.cred), &srv_cred))
400 memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred));
402 DEBUG(5,("api_net_srv_pwset: %d\n", __LINE__));
404 pstrcpy(mach_acct, unistrn2(q_a.clnt_id.login.uni_acct_name.buffer,
405 q_a.clnt_id.login.uni_acct_name.uni_str_len));
407 DEBUG(3,("Server Password Set Wksta:[%s]\n", mach_acct));
410 smb_pass = getsmbpwnam(mach_acct);
413 if (smb_pass != NULL)
415 unsigned char pwd[16];
418 DEBUG(100,("Server password set : new given value was :\n"));
419 for(i = 0; i < 16; i++)
421 DEBUG(100,("%02X ", q_a.pwd[i]));
425 cred_hash3( pwd, q_a.pwd, vuser->dc.sess_key, 0);
427 /* lies! nt and lm passwords are _not_ the same: don't care */
428 smb_pass->smb_passwd = pwd;
429 smb_pass->smb_nt_passwd = pwd;
430 smb_pass->acct_ctrl = ACB_WSTRUST;
433 ret = mod_smbpwd_entry(smb_pass,False);
443 DEBUG(5,("api_net_srv_pwset: %d\n", __LINE__));
448 /* lkclXXXX take a guess at a sensible error code to return... */
449 status = 0xC0000000 | NT_STATUS_NETWORK_CREDENTIAL_CONFLICT;
452 /* Construct reply. */
453 net_reply_srv_pwset(&q_a, rdata, &srv_cred, status);
457 /*************************************************************************
459 *************************************************************************/
460 static void api_net_sam_logoff( uint16 vuid,
464 NET_Q_SAM_LOGOFF q_l;
471 if ((vuser = get_valid_user_struct(vuid)) == NULL)
474 /* the DOM_ID_INFO_1 structure is a bit big. plus we might want to
475 dynamically allocate it inside net_io_q_sam_logon, at some point */
476 q_l.sam_id.ctr = &ctr;
478 /* grab the challenge... */
479 net_io_q_sam_logoff("", &q_l, data, 0);
481 /* checks and updates credentials. creates reply credentials */
482 deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred),
483 &(q_l.sam_id.client.cred), &srv_cred);
484 memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred));
486 /* construct reply. always indicate success */
487 net_reply_sam_logoff(&q_l, rdata,
492 /*************************************************************************
493 net_login_interactive:
494 *************************************************************************/
495 static uint32 net_login_interactive(NET_ID_INFO_1 *id1,
496 struct smb_passwd *smb_pass,
503 unsigned char key[16];
506 memcpy(key, vuser->dc.sess_key, 8);
508 memcpy(lm_pwd, id1->lm_owf.data, 16);
509 memcpy(nt_pwd, id1->nt_owf.data, 16);
511 #ifdef DEBUG_PASSWORD
513 dump_data(100, key, 16);
515 DEBUG(100,("lm owf password:"));
516 dump_data(100, lm_pwd, 16);
518 DEBUG(100,("nt owf password:"));
519 dump_data(100, nt_pwd, 16);
522 SamOEMhash((uchar *)lm_pwd, key, False);
523 SamOEMhash((uchar *)nt_pwd, key, False);
525 #ifdef DEBUG_PASSWORD
526 DEBUG(100,("decrypt of lm owf password:"));
527 dump_data(100, lm_pwd, 16);
529 DEBUG(100,("decrypt of nt owf password:"));
530 dump_data(100, nt_pwd, 16);
533 if (memcmp(smb_pass->smb_passwd , lm_pwd, 16) != 0 &&
534 memcmp(smb_pass->smb_nt_passwd, nt_pwd, 16) != 0)
536 status = 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
542 /*************************************************************************
544 *************************************************************************/
545 static uint32 net_login_network(NET_ID_INFO_2 *id2,
546 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)
678 status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
680 else if (IS_BITS_SET_ALL(smb_pass->acct_ctrl, ACB_DISABLED) &&
681 IS_BITS_CLR_ALL(smb_pass->acct_ctrl, ACB_PWNOTREQ))
683 status = 0xC0000000 | NT_STATUS_ACCOUNT_DISABLED;
687 /* validate password - if required */
689 if (status == 0 && !(IS_BITS_SET_ALL(smb_pass->acct_ctrl, ACB_PWNOTREQ)))
691 switch (q_l.sam_id.logon_level)
693 case INTERACTIVE_LOGON_TYPE:
695 /* interactive login. */
696 status = net_login_interactive(&q_l.sam_id.ctr->auth.id1, smb_pass, vuser);
701 /* network login. lm challenge and 24 byte responses */
702 status = net_login_network(&q_l.sam_id.ctr->auth.id2, smb_pass, vuser);
708 /* lkclXXXX this is the point at which, if the login was
709 successful, that the SAM Local Security Authority should
710 record that the user is logged in to the domain.
713 /* return the profile plus other bits :-) */
717 DOM_GID *gids = NULL;
720 pstring logon_script;
721 pstring profile_path;
725 pstring my_workgroup;
730 /* set up pointer indicating user/password failed to be found */
731 usr_info.ptr_user_info = 0;
733 dummy_time.low = 0xffffffff;
734 dummy_time.high = 0x7fffffff;
736 /* XXXX hack to get standard_sub_basic() to use sam logon username */
737 /* possibly a better way would be to do a become_user() call */
738 sam_logon_in_ssb = True;
740 pstrcpy(logon_script, lp_logon_script());
741 pstrcpy(profile_path, lp_logon_path());
743 pstrcpy(my_workgroup, lp_workgroup());
745 pstrcpy(home_drive, lp_logon_drive());
746 pstrcpy(home_dir, lp_logon_home());
747 pstrcpy(my_name, global_myname);
750 status = lookup_user_rids(samlogon_user, &r_uid, &r_gid);
751 status = status == 0 ? getusergroupsnam(samlogon_user, &grp_mem, &num_gids) : 0xC0000000 | NT_STATUS_INVALID_PRIMARY_GROUP;
756 num_gids = make_dom_gids(grp_mem, num_gids, &gids);
758 make_net_user_info3(&usr_info,
759 &dummy_time, /* logon_time */
760 &dummy_time, /* logoff_time */
761 &dummy_time, /* kickoff_time */
762 &dummy_time, /* pass_last_set_time */
763 &dummy_time, /* pass_can_change_time */
764 &dummy_time, /* pass_must_change_time */
766 samlogon_user , /* user_name */
767 vuser->real_name, /* full_name */
768 logon_script , /* logon_script */
769 profile_path , /* profile_path */
770 home_dir , /* home_dir */
771 home_drive , /* dir_drive */
774 0, /* bad_pw_count */
776 r_uid , /* RID user_id */
777 r_gid , /* RID group_id */
778 num_gids, /* uint32 num_groups */
779 gids , /* DOM_GID *gids */
780 0x20 , /* uint32 user_flgs (?) */
782 NULL, /* char sess_key[16] */
784 my_name , /* char *logon_srv */
785 my_workgroup, /* char *logon_dom */
787 &global_sam_sid, /* DOM_SID *dom_sid */
788 NULL); /* char *other_sids */
792 status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
795 /* Free any allocated groups array. */
802 net_reply_sam_logon(&q_l, rdata, &srv_cred, &usr_info, status);
806 /*************************************************************************
807 api_net_trust_dom_list:
808 *************************************************************************/
809 static void api_net_trust_dom_list( uint16 vuid,
813 NET_Q_TRUST_DOM_LIST q_t;
815 char *trusted_domain = "test_domain";
817 DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
819 /* grab the lsa trusted domain list query... */
820 net_io_q_trust_dom("", &q_t, data, 0);
822 /* construct reply. */
823 net_reply_trust_dom_list(&q_t, rdata,
826 DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
830 /*************************************************************************
831 error messages cropping up when using nltest.exe...
832 *************************************************************************/
833 #define ERROR_NO_SUCH_DOMAIN 0x54b
834 #define ERROR_NO_LOGON_SERVERS 0x51f
836 /*************************************************************************
838 *************************************************************************/
839 static void api_net_logon_ctrl2( uint16 vuid,
843 NET_Q_LOGON_CTRL2 q_l;
845 /* lkclXXXX - guess what - absolutely no idea what these are! */
847 uint32 pdc_connection_status = 0x0;
848 uint32 logon_attempts = 0x0;
849 uint32 tc_status = ERROR_NO_LOGON_SERVERS;
850 char *trusted_domain = "test_domain";
852 DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
854 /* grab the lsa netlogon ctrl2 query... */
855 net_io_q_logon_ctrl2("", &q_l, data, 0);
857 /* construct reply. */
858 net_reply_logon_ctrl2(&q_l, rdata,
859 flags, pdc_connection_status, logon_attempts,
860 tc_status, trusted_domain);
862 DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
865 /*******************************************************************
866 array of \PIPE\NETLOGON operations
867 ********************************************************************/
868 static struct api_struct api_net_cmds [] =
870 { "NET_REQCHAL" , NET_REQCHAL , api_net_req_chal },
871 { "NET_AUTH2" , NET_AUTH2 , api_net_auth_2 },
872 { "NET_SRVPWSET" , NET_SRVPWSET , api_net_srv_pwset },
873 { "NET_SAMLOGON" , NET_SAMLOGON , api_net_sam_logon },
874 { "NET_SAMLOGOFF" , NET_SAMLOGOFF , api_net_sam_logoff },
875 { "NET_LOGON_CTRL2" , NET_LOGON_CTRL2 , api_net_logon_ctrl2 },
876 { "NET_TRUST_DOM_LIST", NET_TRUST_DOM_LIST, api_net_trust_dom_list },
880 /*******************************************************************
881 receives a netlogon pipe and responds.
882 ********************************************************************/
883 BOOL api_netlog_rpc(pipes_struct *p, prs_struct *data)
885 return api_rpcTNP(p, "api_netlog_rpc", api_net_cmds, data);