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,
550 DEBUG(5,("net_login_network: lm_len: %d nt_len: %d\n",
551 id2->hdr_lm_chal_resp.str_str_len,
552 id2->hdr_nt_chal_resp.str_str_len));
554 /* JRA. Check the NT password first if it exists - this is a higher quality
555 password, if it exists and it doesn't match - fail. */
557 if (id2->hdr_nt_chal_resp.str_str_len == 24 &&
558 smb_pass->smb_nt_passwd != NULL)
560 if(smb_password_check((char *)id2->nt_chal_resp.buffer,
561 smb_pass->smb_nt_passwd,
565 return 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
568 /* lkclXXXX this is not a good place to put disabling of LM hashes in.
569 if that is to be done, first move this entire function into a
570 library routine that calls the two smb_password_check() functions.
571 if disabling LM hashes (which nt can do for security reasons) then
572 an attempt should be made to disable them everywhere (which nt does
573 not do, for various security-hole reasons).
576 if (id2->hdr_lm_chal_resp.str_str_len == 24 &&
577 smb_password_check((char *)id2->lm_chal_resp.buffer,
578 smb_pass->smb_passwd,
585 /* oops! neither password check succeeded */
587 return 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
590 /*************************************************************************
592 *************************************************************************/
593 static void api_net_sam_logon( uint16 vuid,
599 NET_USER_INFO_3 usr_info;
602 struct smb_passwd *smb_pass = NULL;
603 UNISTR2 *uni_samlogon_user = NULL;
605 user_struct *vuser = NULL;
607 if ((vuser = get_valid_user_struct(vuid)) == NULL)
610 q_l.sam_id.ctr = &ctr;
612 net_io_q_sam_logon("", &q_l, data, 0);
614 /* checks and updates credentials. creates reply credentials */
615 if (!deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred),
616 &(q_l.sam_id.client.cred), &srv_cred))
618 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
622 memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred));
625 /* find the username */
629 switch (q_l.sam_id.logon_level)
631 case INTERACTIVE_LOGON_TYPE:
633 uni_samlogon_user = &(q_l.sam_id.ctr->auth.id1.uni_user_name);
635 DEBUG(3,("SAM Logon (Interactive). Domain:[%s]. ", lp_workgroup()));
640 uni_samlogon_user = &(q_l.sam_id.ctr->auth.id2.uni_user_name);
642 DEBUG(3,("SAM Logon (Network). Domain:[%s]. ", lp_workgroup()));
647 DEBUG(2,("SAM Logon: unsupported switch value\n"));
648 status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
652 } /* end if status == 0 */
654 /* check username exists */
658 pstrcpy(samlogon_user, unistrn2(uni_samlogon_user->buffer,
659 uni_samlogon_user->uni_str_len));
661 DEBUG(3,("User:[%s]\n", samlogon_user));
664 * Convert to a UNIX username.
666 map_username(samlogon_user);
669 * Do any case conversions.
671 (void)Get_Pwnam(samlogon_user, True);
674 smb_pass = getsmbpwnam(samlogon_user);
677 if (smb_pass == NULL)
678 status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
679 else if (smb_pass->acct_ctrl & ACB_DISABLED)
680 status = 0xC0000000 | NT_STATUS_ACCOUNT_DISABLED;
683 /* validate password. */
687 switch (q_l.sam_id.logon_level)
689 case INTERACTIVE_LOGON_TYPE:
691 /* interactive login. */
692 status = net_login_interactive(&q_l.sam_id.ctr->auth.id1, smb_pass, vuser);
697 /* network login. lm challenge and 24 byte responses */
698 status = net_login_network(&q_l.sam_id.ctr->auth.id2, smb_pass, vuser);
704 /* lkclXXXX this is the point at which, if the login was
705 successful, that the SAM Local Security Authority should
706 record that the user is logged in to the domain.
709 /* return the profile plus other bits :-) */
713 DOM_GID *gids = NULL;
716 pstring logon_script;
717 pstring profile_path;
721 pstring my_workgroup;
722 pstring domain_groups;
726 /* set up pointer indicating user/password failed to be found */
727 usr_info.ptr_user_info = 0;
729 dummy_time.low = 0xffffffff;
730 dummy_time.high = 0x7fffffff;
732 /* XXXX hack to get standard_sub_basic() to use sam logon username */
733 /* possibly a better way would be to do a become_user() call */
734 sam_logon_in_ssb = True;
736 pstrcpy(logon_script, lp_logon_script());
737 pstrcpy(profile_path, lp_logon_path());
739 pstrcpy(my_workgroup, lp_workgroup());
741 pstrcpy(home_drive, lp_logon_drive());
742 pstrcpy(home_dir, lp_logon_home());
744 pstrcpy(my_name, global_myname);
748 * This is the point at which we get the group
749 * database - we should be getting the gid_t list
750 * from /etc/group and then turning the uids into
751 * rids and then into machine sids for this user.
755 get_domain_user_groups(domain_groups, samlogon_user);
758 * make_dom_gids allocates the gids array. JRA.
761 num_gids = make_dom_gids(domain_groups, &gids);
763 sam_logon_in_ssb = False;
765 if (pdb_name_to_rid(samlogon_user, &r_uid, &r_gid))
767 make_net_user_info3(&usr_info,
768 &dummy_time, /* logon_time */
769 &dummy_time, /* logoff_time */
770 &dummy_time, /* kickoff_time */
771 &dummy_time, /* pass_last_set_time */
772 &dummy_time, /* pass_can_change_time */
773 &dummy_time, /* pass_must_change_time */
775 samlogon_user , /* user_name */
776 vuser->real_name, /* full_name */
777 logon_script , /* logon_script */
778 profile_path , /* profile_path */
779 home_dir , /* home_dir */
780 home_drive , /* dir_drive */
783 0, /* bad_pw_count */
785 r_uid , /* RID user_id */
786 r_gid , /* RID group_id */
787 num_gids, /* uint32 num_groups */
788 gids , /* DOM_GID *gids */
789 0x20 , /* uint32 user_flgs (?) */
791 NULL, /* char sess_key[16] */
793 my_name , /* char *logon_srv */
794 my_workgroup, /* char *logon_dom */
796 &global_sam_sid, /* DOM_SID *dom_sid */
797 NULL); /* char *other_sids */
801 status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
804 /* Free any allocated groups array. */
809 net_reply_sam_logon(&q_l, rdata, &srv_cred, &usr_info, status);
813 /*************************************************************************
814 api_net_trust_dom_list:
815 *************************************************************************/
816 static void api_net_trust_dom_list( uint16 vuid,
820 NET_Q_TRUST_DOM_LIST q_t;
822 char *trusted_domain = "test_domain";
824 DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
826 /* grab the lsa trusted domain list query... */
827 net_io_q_trust_dom("", &q_t, data, 0);
829 /* construct reply. */
830 net_reply_trust_dom_list(&q_t, rdata,
833 DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
837 /*************************************************************************
838 error messages cropping up when using nltest.exe...
839 *************************************************************************/
840 #define ERROR_NO_SUCH_DOMAIN 0x54b
841 #define ERROR_NO_LOGON_SERVERS 0x51f
843 /*************************************************************************
845 *************************************************************************/
846 static void api_net_logon_ctrl2( uint16 vuid,
850 NET_Q_LOGON_CTRL2 q_l;
852 /* lkclXXXX - guess what - absolutely no idea what these are! */
854 uint32 pdc_connection_status = 0x0;
855 uint32 logon_attempts = 0x0;
856 uint32 tc_status = ERROR_NO_LOGON_SERVERS;
857 char *trusted_domain = "test_domain";
859 DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
861 /* grab the lsa netlogon ctrl2 query... */
862 net_io_q_logon_ctrl2("", &q_l, data, 0);
864 /* construct reply. */
865 net_reply_logon_ctrl2(&q_l, rdata,
866 flags, pdc_connection_status, logon_attempts,
867 tc_status, trusted_domain);
869 DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
872 /*******************************************************************
873 array of \PIPE\NETLOGON operations
874 ********************************************************************/
875 static struct api_struct api_net_cmds [] =
877 { "NET_REQCHAL" , NET_REQCHAL , api_net_req_chal },
878 { "NET_AUTH2" , NET_AUTH2 , api_net_auth_2 },
879 { "NET_SRVPWSET" , NET_SRVPWSET , api_net_srv_pwset },
880 { "NET_SAMLOGON" , NET_SAMLOGON , api_net_sam_logon },
881 { "NET_SAMLOGOFF" , NET_SAMLOGOFF , api_net_sam_logoff },
882 { "NET_LOGON_CTRL2" , NET_LOGON_CTRL2 , api_net_logon_ctrl2 },
883 { "NET_TRUST_DOM_LIST", NET_TRUST_DOM_LIST, api_net_trust_dom_list },
887 /*******************************************************************
888 receives a netlogon pipe and responds.
889 ********************************************************************/
890 BOOL api_netlog_rpc(pipes_struct *p, prs_struct *data)
892 return api_rpcTNP(p, "api_netlog_rpc", api_net_cmds, data);