1bb86e183f71ea1a4355bb30abe9adc67b61ff7d
[samba.git] / source3 / rpc_server / srv_netlog.c
1 /* 
2  *  Unix SMB/Netbios implementation.
3  *  Version 1.9.
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.
9  *
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.
14  *  
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.
19  *  
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.
23  */
24
25
26 #include "includes.h"
27 #include "nterr.h"
28
29 extern int DEBUGLEVEL;
30
31 extern pstring global_myname;
32 extern DOM_SID global_sam_sid;
33 extern fstring global_sam_name;
34
35 /*************************************************************************
36  make_net_r_req_chal:
37  *************************************************************************/
38 static void make_net_r_req_chal(NET_R_REQ_CHAL *r_c,
39                                 DOM_CHAL *srv_chal, int status)
40 {
41         DEBUG(6,("make_net_r_req_chal: %d\n", __LINE__));
42         memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(srv_chal->data));
43         r_c->status = status;
44 }
45
46 /*************************************************************************
47  net_reply_req_chal:
48  *************************************************************************/
49 static void net_reply_req_chal(NET_Q_REQ_CHAL *q_c, prs_struct *rdata,
50                                         DOM_CHAL *srv_chal, uint32 srv_time)
51 {
52         NET_R_REQ_CHAL r_c;
53
54         DEBUG(6,("net_reply_req_chal: %d\n", __LINE__));
55
56         /* set up the LSA REQUEST CHALLENGE response */
57         make_net_r_req_chal(&r_c, srv_chal, srv_time);
58
59         /* store the response in the SMB stream */
60         net_io_r_req_chal("", &r_c, rdata, 0);
61
62         DEBUG(6,("net_reply_req_chal: %d\n", __LINE__));
63
64 }
65
66 /*************************************************************************
67  net_reply_logon_ctrl2:
68  *************************************************************************/
69 static void net_reply_logon_ctrl2(NET_Q_LOGON_CTRL2 *q_l, prs_struct *rdata,
70                         uint32 flags, uint32 pdc_status, uint32 logon_attempts,
71                         uint32 tc_status, char *trust_domain_name)
72 {
73         NET_R_LOGON_CTRL2 r_l;
74
75         DEBUG(6,("net_reply_logon_ctrl2: %d\n", __LINE__));
76
77         /* set up the Logon Control2 response */
78         make_r_logon_ctrl2(&r_l, q_l->query_level,
79                            flags, pdc_status, logon_attempts,
80                            tc_status, trust_domain_name);
81
82         /* store the response in the SMB stream */
83         net_io_r_logon_ctrl2("", &r_l, rdata, 0);
84
85         DEBUG(6,("net_reply_logon_ctrl2: %d\n", __LINE__));
86
87 }
88
89 /*************************************************************************
90  net_reply_trust_dom_list:
91  *************************************************************************/
92 static void net_reply_trust_dom_list(NET_Q_TRUST_DOM_LIST *q_t, prs_struct *rdata,
93                         uint32 num_trust_domains, char *trust_domain_name)
94 {
95         NET_R_TRUST_DOM_LIST r_t;
96
97         DEBUG(6,("net_reply_trust_dom_list: %d\n", __LINE__));
98
99         /* set up the Trusted Domain List response */
100         make_r_trust_dom(&r_t, num_trust_domains, trust_domain_name);
101
102         /* store the response in the SMB stream */
103         net_io_r_trust_dom("", &r_t, rdata, 0);
104
105         DEBUG(6,("net_reply_trust_dom_listlogon_ctrl2: %d\n", __LINE__));
106
107 }
108
109 /*************************************************************************
110  make_net_r_auth_2:
111  *************************************************************************/
112 static void make_net_r_auth_2(NET_R_AUTH_2 *r_a,
113                               DOM_CHAL *resp_cred, NEG_FLAGS *flgs, int status)
114 {
115         memcpy(  r_a->srv_chal.data, resp_cred->data, sizeof(resp_cred->data));
116         memcpy(&(r_a->srv_flgs)    , flgs           , sizeof(r_a->srv_flgs));
117         r_a->status = status;
118 }
119
120 /*************************************************************************
121  net_reply_auth_2:
122  *************************************************************************/
123 static void net_reply_auth_2(NET_Q_AUTH_2 *q_a, prs_struct *rdata,
124                                 DOM_CHAL *resp_cred, int status)
125 {
126         NET_R_AUTH_2 r_a;
127         NEG_FLAGS srv_flgs;
128
129         srv_flgs.neg_flags = 0x000001ff;
130
131         /* set up the LSA AUTH 2 response */
132
133         make_net_r_auth_2(&r_a, resp_cred, &srv_flgs, status);
134
135         /* store the response in the SMB stream */
136         net_io_r_auth_2("", &r_a, rdata, 0);
137
138 }
139
140 /***********************************************************************************
141  make_net_r_srv_pwset:
142  ***********************************************************************************/
143 static void make_net_r_srv_pwset(NET_R_SRV_PWSET *r_s,
144                              DOM_CRED *srv_cred, int status)  
145 {
146         DEBUG(5,("make_net_r_srv_pwset: %d\n", __LINE__));
147
148         memcpy(&(r_s->srv_cred), srv_cred, sizeof(r_s->srv_cred));
149         r_s->status = status;
150
151         DEBUG(5,("make_net_r_srv_pwset: %d\n", __LINE__));
152 }
153
154 /*************************************************************************
155  net_reply_srv_pwset:
156  *************************************************************************/
157 static void net_reply_srv_pwset(NET_Q_SRV_PWSET *q_s, prs_struct *rdata,
158                                 DOM_CRED *srv_cred, int status)
159 {
160         NET_R_SRV_PWSET r_s;
161
162         DEBUG(5,("net_srv_pwset: %d\n", __LINE__));
163
164         /* set up the LSA Server Password Set response */
165         make_net_r_srv_pwset(&r_s, srv_cred, status);
166
167         /* store the response in the SMB stream */
168         net_io_r_srv_pwset("", &r_s, rdata, 0);
169
170         DEBUG(5,("net_srv_pwset: %d\n", __LINE__));
171
172 }
173
174 /*************************************************************************
175  net_reply_sam_logon:
176  *************************************************************************/
177 static void net_reply_sam_logon(NET_Q_SAM_LOGON *q_s, prs_struct *rdata,
178                                 DOM_CRED *srv_cred, NET_USER_INFO_3 *user_info,
179                                 uint32 status)
180 {
181         NET_R_SAM_LOGON r_s;
182
183         /* XXXX maybe we want to say 'no', reject the client's credentials */
184         r_s.buffer_creds = 1; /* yes, we have valid server credentials */
185         memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds));
186
187         /* store the user information, if there is any. */
188         r_s.user = user_info;
189         if (status == 0x0 && user_info != NULL && user_info->ptr_user_info != 0)
190         {
191                 r_s.switch_value = 3; /* indicates type of validation user info */
192         }
193         else
194         {
195                 r_s.switch_value = 0; /* indicates no info */
196         }
197
198         r_s.status = status;
199         r_s.auth_resp = 1; /* authoritative response */
200
201         /* store the response in the SMB stream */
202         net_io_r_sam_logon("", &r_s, rdata, 0);
203
204 }
205
206
207 /*************************************************************************
208  net_reply_sam_logoff:
209  *************************************************************************/
210 static void net_reply_sam_logoff(NET_Q_SAM_LOGOFF *q_s, prs_struct *rdata,
211                                 DOM_CRED *srv_cred, 
212                                 uint32 status)
213 {
214         NET_R_SAM_LOGOFF r_s;
215
216         /* XXXX maybe we want to say 'no', reject the client's credentials */
217         r_s.buffer_creds = 1; /* yes, we have valid server credentials */
218         memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds));
219
220         r_s.status = status;
221
222         /* store the response in the SMB stream */
223         net_io_r_sam_logoff("", &r_s, rdata, 0);
224
225 }
226
227 /******************************************************************
228  gets a machine password entry.  checks access rights of the host.
229  ******************************************************************/
230 static BOOL get_md4pw(char *md4pw, char *mach_name, char *mach_acct)
231 {
232         struct smb_passwd *smb_pass;
233
234 #if 0
235     /*
236      * Currently this code is redundent as we already have a filter
237      * by hostname list. What this code really needs to do is to 
238      * get a hosts allowed/hosts denied list from the SAM database
239      * on a per user basis, and make the access decision there.
240      * I will leave this code here for now as a reminder to implement
241      * this at a later date. JRA.
242      */
243
244         if (!allow_access(lp_domain_hostsdeny(), lp_domain_hostsallow(),
245                           client_name(Client), client_addr(Client)))
246         {
247                 DEBUG(0,("get_md4pw: Workstation %s denied access to domain\n", mach_acct));
248                 return False;
249         }
250 #endif /* 0 */
251
252         become_root(True);
253         smb_pass = getsmbpwnam(mach_acct);
254         unbecome_root(True);
255
256         if ((smb_pass) != NULL && !(smb_pass->acct_ctrl & ACB_DISABLED) &&
257         (smb_pass->smb_nt_passwd != NULL))
258         {
259                 memcpy(md4pw, smb_pass->smb_nt_passwd, 16);
260                 dump_data(5, md4pw, 16);
261
262                 return True;
263         }
264         DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct));
265         return False;
266 }
267
268 /*************************************************************************
269  api_net_req_chal:
270  *************************************************************************/
271 static void api_net_req_chal( uint16 vuid,
272                               prs_struct *data,
273                               prs_struct *rdata)
274 {
275         NET_Q_REQ_CHAL q_r;
276         uint32 status = 0x0;
277
278         fstring mach_acct;
279         fstring mach_name;
280
281         user_struct *vuser;
282
283         DEBUG(5,("api_net_req_chal(%d): vuid %d\n", __LINE__, (int)vuid));
284
285         if ((vuser = get_valid_user_struct(vuid)) == NULL)
286       return;
287
288         /* grab the challenge... */
289         net_io_q_req_chal("", &q_r, data, 0);
290
291         unistr2_to_ascii(mach_acct, &q_r.uni_logon_clnt, sizeof(mach_acct)-1);
292
293         fstrcpy(mach_name, mach_acct);
294         strlower(mach_name);
295
296         fstrcat(mach_acct, "$");
297
298         if (get_md4pw((char *)vuser->dc.md4pw, mach_name, mach_acct))
299         {
300                 /* copy the client credentials */
301                 memcpy(vuser->dc.clnt_chal.data          , q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data));
302                 memcpy(vuser->dc.clnt_cred.challenge.data, q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data));
303
304                 /* create a server challenge for the client */
305                 /* Set these to random values. */
306                 generate_random_buffer(vuser->dc.srv_chal.data, 8, False);
307
308                 memcpy(vuser->dc.srv_cred.challenge.data, vuser->dc.srv_chal.data, 8);
309
310                 bzero(vuser->dc.sess_key, sizeof(vuser->dc.sess_key));
311
312                 /* from client / server challenges and md4 password, generate sess key */
313                 cred_session_key(&(vuser->dc.clnt_chal), &(vuser->dc.srv_chal),
314                                  (char *)vuser->dc.md4pw, vuser->dc.sess_key);
315         }
316         else
317         {
318                 /* lkclXXXX take a guess at a good error message to return :-) */
319                 status = 0xC0000000 | NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT;
320         }
321
322         /* construct reply. */
323         net_reply_req_chal(&q_r, rdata,
324                                         &(vuser->dc.srv_chal), status);
325
326 }
327
328 /*************************************************************************
329  api_net_auth_2:
330  *************************************************************************/
331 static void api_net_auth_2( uint16 vuid,
332                             prs_struct *data,
333                             prs_struct *rdata)
334 {
335         NET_Q_AUTH_2 q_a;
336         uint32 status = 0x0;
337
338         DOM_CHAL srv_cred;
339         UTIME srv_time;
340
341         user_struct *vuser;
342
343         if ((vuser = get_valid_user_struct(vuid)) == NULL)
344       return;
345
346         srv_time.time = 0;
347
348         /* grab the challenge... */
349         net_io_q_auth_2("", &q_a, data, 0);
350
351         /* check that the client credentials are valid */
352         if (cred_assert(&(q_a.clnt_chal), vuser->dc.sess_key,
353                     &(vuser->dc.clnt_cred.challenge), srv_time))
354         {
355
356                 /* create server challenge for inclusion in the reply */
357                 cred_create(vuser->dc.sess_key, &(vuser->dc.srv_cred.challenge), srv_time, &srv_cred);
358
359                 /* copy the received client credentials for use next time */
360                 memcpy(vuser->dc.clnt_cred.challenge.data, q_a.clnt_chal.data, sizeof(q_a.clnt_chal.data));
361                 memcpy(vuser->dc.srv_cred .challenge.data, q_a.clnt_chal.data, sizeof(q_a.clnt_chal.data));
362         }
363         else
364         {
365                 status = NT_STATUS_ACCESS_DENIED | 0xC0000000;
366         }
367
368         /* construct reply. */
369         net_reply_auth_2(&q_a, rdata, &srv_cred, status);
370 }
371
372
373 /*************************************************************************
374  api_net_srv_pwset:
375  *************************************************************************/
376 static void api_net_srv_pwset( uint16 vuid,
377                                prs_struct *data,
378                                prs_struct *rdata)
379 {
380         NET_Q_SRV_PWSET q_a;
381         uint32 status = NT_STATUS_WRONG_PASSWORD|0xC0000000;
382         DOM_CRED srv_cred;
383         pstring mach_acct;
384         struct smb_passwd *smb_pass;
385         BOOL ret;
386         user_struct *vuser;
387
388         if ((vuser = get_valid_user_struct(vuid)) == NULL)
389       return;
390
391         /* grab the challenge and encrypted password ... */
392         net_io_q_srv_pwset("", &q_a, data, 0);
393
394         /* checks and updates credentials.  creates reply credentials */
395         if (deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred), 
396                             &(q_a.clnt_id.cred), &srv_cred))
397         {
398                 memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred));
399
400                 DEBUG(5,("api_net_srv_pwset: %d\n", __LINE__));
401
402                 unistr2_to_ascii(mach_acct, &q_a.clnt_id.login.uni_acct_name,
403                                  sizeof(mach_acct)-1);
404
405                 DEBUG(3,("Server Password Set Wksta:[%s]\n", mach_acct));
406
407                 become_root(True);
408                 smb_pass = getsmbpwnam(mach_acct);
409                 unbecome_root(True);
410
411                 if (smb_pass != NULL)
412                 {
413                         unsigned char pwd[16];
414                         int i;
415
416                         DEBUG(100,("Server password set : new given value was :\n"));
417                         for(i = 0; i < 16; i++)
418                         {
419                                 DEBUG(100,("%02X ", q_a.pwd[i]));
420                         }
421                         DEBUG(100,("\n"));
422
423                         cred_hash3( pwd, q_a.pwd, vuser->dc.sess_key, 0);
424
425                         /* lies!  nt and lm passwords are _not_ the same: don't care */
426                         smb_pass->smb_passwd    = pwd;
427                         smb_pass->smb_nt_passwd = pwd;
428                         smb_pass->acct_ctrl     = ACB_WSTRUST;
429
430                         become_root(True);
431                         ret = mod_smbpwd_entry(smb_pass,False);
432                         unbecome_root(True);
433
434                         if (ret)
435                         {
436                                 /* hooray! */
437                                 status = 0x0;
438                         }
439                 }
440
441                 DEBUG(5,("api_net_srv_pwset: %d\n", __LINE__));
442
443         }
444         else
445         {
446                 /* lkclXXXX take a guess at a sensible error code to return... */
447                 status = 0xC0000000 | NT_STATUS_NETWORK_CREDENTIAL_CONFLICT;
448         }
449
450         /* Construct reply. */
451         net_reply_srv_pwset(&q_a, rdata, &srv_cred, status);
452 }
453
454
455 /*************************************************************************
456  api_net_sam_logoff:
457  *************************************************************************/
458 static void api_net_sam_logoff( uint16 vuid,
459                                prs_struct *data,
460                                prs_struct *rdata)
461 {
462         NET_Q_SAM_LOGOFF q_l;
463         NET_ID_INFO_CTR ctr;    
464
465         DOM_CRED srv_cred;
466
467         user_struct *vuser;
468
469         if ((vuser = get_valid_user_struct(vuid)) == NULL)
470       return;
471
472         /* the DOM_ID_INFO_1 structure is a bit big.  plus we might want to
473            dynamically allocate it inside net_io_q_sam_logon, at some point */
474         q_l.sam_id.ctr = &ctr;
475
476         /* grab the challenge... */
477         net_io_q_sam_logoff("", &q_l, data, 0);
478
479         /* checks and updates credentials.  creates reply credentials */
480         deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred), 
481                         &(q_l.sam_id.client.cred), &srv_cred);
482         memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred));
483
484         /* construct reply.  always indicate success */
485         net_reply_sam_logoff(&q_l, rdata,
486                                         &srv_cred,
487                         0x0);
488 }
489
490 /*************************************************************************
491  net_login_interactive:
492  *************************************************************************/
493 static uint32 net_login_interactive(NET_ID_INFO_1 *id1,
494                                 struct sam_passwd *smb_pass,
495                                 user_struct *vuser)
496 {
497         uint32 status = 0x0;
498
499         char nt_pwd[16];
500         char lm_pwd[16];
501         unsigned char key[16];
502
503         memset(key, 0, 16);
504         memcpy(key, vuser->dc.sess_key, 8);
505
506         memcpy(lm_pwd, id1->lm_owf.data, 16);
507         memcpy(nt_pwd, id1->nt_owf.data, 16);
508
509 #ifdef DEBUG_PASSWORD
510         DEBUG(100,("key:"));
511         dump_data(100, key, 16);
512
513         DEBUG(100,("lm owf password:"));
514         dump_data(100, lm_pwd, 16);
515
516         DEBUG(100,("nt owf password:"));
517         dump_data(100, nt_pwd, 16);
518 #endif
519
520         SamOEMhash((uchar *)lm_pwd, key, False);
521         SamOEMhash((uchar *)nt_pwd, key, False);
522
523 #ifdef DEBUG_PASSWORD
524         DEBUG(100,("decrypt of lm owf password:"));
525         dump_data(100, lm_pwd, 16);
526
527         DEBUG(100,("decrypt of nt owf password:"));
528         dump_data(100, nt_pwd, 16);
529 #endif
530
531         if (smb_pass->smb_nt_passwd == NULL)
532         {
533                 DEBUG(5,("warning: NETLOGON user %s only has an LM password\n",
534                           smb_pass->unix_name));
535         }
536
537         if (memcmp(smb_pass->smb_passwd   , lm_pwd, 16) != 0 &&
538             (smb_pass->smb_nt_passwd == NULL ||
539             memcmp(smb_pass->smb_nt_passwd, nt_pwd, 16) != 0))
540         {
541                 status = 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
542         }
543
544         return status;
545 }
546
547 /*************************************************************************
548  net_login_network:
549  *************************************************************************/
550 static uint32 net_login_network(NET_ID_INFO_2 *id2,
551                                 struct sam_passwd *smb_pass,
552                                 user_struct *vuser)
553 {
554         DEBUG(5,("net_login_network: lm_len: %d nt_len: %d\n",
555                 id2->hdr_lm_chal_resp.str_str_len, 
556                 id2->hdr_nt_chal_resp.str_str_len));
557
558         /* JRA. Check the NT password first if it exists - this is a higher quality 
559            password, if it exists and it doesn't match - fail. */
560
561         if (id2->hdr_nt_chal_resp.str_str_len == 24 && 
562                 smb_pass->smb_nt_passwd != NULL)
563         {
564                 if(smb_password_check((char *)id2->nt_chal_resp.buffer,
565                                    smb_pass->smb_nt_passwd,
566                            id2->lm_chal)) 
567                   return 0x0;
568                 else
569                   return 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
570         }
571
572         /* lkclXXXX this is not a good place to put disabling of LM hashes in.
573            if that is to be done, first move this entire function into a
574            library routine that calls the two smb_password_check() functions.
575            if disabling LM hashes (which nt can do for security reasons) then
576            an attempt should be made to disable them everywhere (which nt does
577            not do, for various security-hole reasons).
578          */
579
580         if (id2->hdr_lm_chal_resp.str_str_len == 24 &&
581                 smb_password_check((char *)id2->lm_chal_resp.buffer,
582                                    smb_pass->smb_passwd,
583                                    id2->lm_chal))
584         {
585                 return 0x0;
586         }
587
588
589         /* oops! neither password check succeeded */
590
591         return 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
592 }
593
594 /*************************************************************************
595  api_net_sam_logon:
596  *************************************************************************/
597 static void api_net_sam_logon( uint16 vuid,
598                                prs_struct *data,
599                                prs_struct *rdata)
600 {
601         NET_Q_SAM_LOGON q_l;
602         NET_ID_INFO_CTR ctr;    
603         NET_USER_INFO_3 usr_info;
604         uint32 status = 0x0;
605         DOM_CRED srv_cred;
606         struct sam_passwd *sam_pass = NULL;
607         UNISTR2 *uni_samlogon_user = NULL;
608         UNISTR2 *uni_domain = NULL;
609         fstring nt_username;
610
611         NTTIME logon_time           ;
612         NTTIME logoff_time          ;
613         NTTIME kickoff_time         ;
614         NTTIME pass_last_set_time   ;
615         NTTIME pass_can_change_time ;
616         NTTIME pass_must_change_time;
617
618         fstring nt_name     ;
619         fstring full_name   ;
620         fstring logon_script;
621         fstring profile_path;
622         fstring home_dir    ;
623         fstring dir_drive   ;
624
625         uint32 user_rid ;
626         uint32 group_rid;
627
628         user_struct *vuser = NULL;
629
630         if ((vuser = get_valid_user_struct(vuid)) == NULL)
631         return;
632
633         q_l.sam_id.ctr = &ctr;
634
635         net_io_q_sam_logon("", &q_l, data, 0);
636
637         /* checks and updates credentials.  creates reply credentials */
638         if (!deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred), 
639                              &(q_l.sam_id.client.cred), &srv_cred))
640         {
641                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
642         }
643         else
644         {
645                 memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred));
646         }
647
648         /* find the username */
649
650         if (status == 0)
651         {
652                 switch (q_l.sam_id.logon_level)
653                 {
654                         case INTERACTIVE_LOGON_TYPE:
655                         {
656                                 uni_samlogon_user = &(q_l.sam_id.ctr->auth.id1.uni_user_name);
657                                 uni_domain        = &(q_l.sam_id.ctr->auth.id1.uni_domain_name);
658
659                                 DEBUG(3,("SAM Logon (Interactive). Domain:[%s].  ", global_sam_name));
660                                 break;
661                         }
662                         case NET_LOGON_TYPE:
663                         {
664                                 uni_samlogon_user = &(q_l.sam_id.ctr->auth.id2.uni_user_name);
665                                 uni_domain        = &(q_l.sam_id.ctr->auth.id2.uni_domain_name);
666
667                                 DEBUG(3,("SAM Logon (Network). Domain:[%s].  ", global_sam_name));
668                                 break;
669                         }
670                         default:
671                         {
672                                 DEBUG(2,("SAM Logon: unsupported switch value\n"));
673                                 status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
674                                 break;
675                         }
676                 } /* end switch */
677         } /* end if status == 0 */
678
679         /* check username exists */
680
681         if (status == 0)
682         {
683                 unistr2_to_ascii(nt_username, uni_samlogon_user,
684                                  sizeof(nt_username)-1);
685
686                 DEBUG(3,("User:[%s]\n", nt_username));
687
688                 become_root(True);
689                 sam_pass = getsam21pwntnam(nt_username);
690                 unbecome_root(True);
691
692                 if (sam_pass == NULL)
693                 {
694                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
695                 }
696                 else if (IS_BITS_SET_ALL(sam_pass->acct_ctrl, ACB_DISABLED) &&
697                          IS_BITS_CLR_ALL(sam_pass->acct_ctrl, ACB_PWNOTREQ))
698                 {
699                         status =  0xC0000000 | NT_STATUS_ACCOUNT_DISABLED;
700                 }
701         }
702
703         if (status == 0x0)
704         {
705                 logon_time            = sam_pass->logon_time;
706                 logoff_time           = sam_pass->logoff_time;
707                 kickoff_time          = sam_pass->kickoff_time;
708                 pass_last_set_time    = sam_pass->pass_last_set_time;
709                 pass_can_change_time  = sam_pass->pass_can_change_time;
710                 pass_must_change_time = sam_pass->pass_must_change_time;
711
712                 fstrcpy(nt_name     , sam_pass->nt_name);
713                 fstrcpy(full_name   , sam_pass->full_name);
714                 fstrcpy(logon_script, sam_pass->logon_script);
715                 fstrcpy(profile_path, sam_pass->profile_path);
716                 fstrcpy(home_dir    , sam_pass->home_dir);
717                 fstrcpy(dir_drive   , sam_pass->dir_drive);
718
719                 user_rid  = sam_pass->user_rid;
720                 group_rid = sam_pass->group_rid;
721         }
722
723         /* validate password - if required */
724
725         if (status == 0 && !(IS_BITS_SET_ALL(sam_pass->acct_ctrl, ACB_PWNOTREQ)))
726         {
727                 switch (q_l.sam_id.logon_level)
728                 {
729                         case INTERACTIVE_LOGON_TYPE:
730                         {
731                                 /* interactive login. */
732                                 status = net_login_interactive(&q_l.sam_id.ctr->auth.id1, sam_pass, vuser);
733                                 break;
734                         }
735                         case NET_LOGON_TYPE:
736                         {
737                                 /* network login.  lm challenge and 24 byte responses */
738                                 status = net_login_network(&q_l.sam_id.ctr->auth.id2, sam_pass, vuser);
739                                 break;
740                         }
741                 }
742         }
743
744         /* lkclXXXX this is the point at which, if the login was
745         successful, that the SAM Local Security Authority should
746         record that the user is logged in to the domain.
747         */
748
749         /* return the profile plus other bits :-) */
750
751         if (status == 0)
752         {
753                 int num_gids = 0;
754                 DOMAIN_GRP *grp_mem = NULL;
755
756                 /* set up pointer indicating user/password failed to be found */
757                 usr_info.ptr_user_info = 0;
758
759                 if (!getusergroupsntnam(nt_username, &grp_mem, &num_gids))
760                 {
761                         status = 0xC0000000 | NT_STATUS_INVALID_PRIMARY_GROUP;
762                 }
763
764                 if (status == 0x0)
765                 {
766                         DOM_GID *gids = NULL;
767                         num_gids = make_dom_gids(grp_mem, num_gids, &gids);
768
769                         make_net_user_info3(&usr_info,
770                                 &logon_time,
771                                 &logoff_time,
772                                 &kickoff_time,
773                                 &pass_last_set_time,
774                                 &pass_can_change_time,
775                                 &pass_must_change_time,
776
777                                 nt_name         , /* user_name */
778                                 full_name       , /* full_name */
779                                 logon_script    , /* logon_script */
780                                 profile_path    , /* profile_path */
781                                 home_dir        , /* home_dir */
782                                 dir_drive       , /* dir_drive */
783
784                                 0, /* logon_count */
785                                 0, /* bad_pw_count */
786
787                                 user_rid   , /* RID user_id */
788                                 group_rid  , /* RID group_id */
789                                 num_gids,    /* uint32 num_groups */
790                                 gids    , /* DOM_GID *gids */
791                                 0x20    , /* uint32 user_flgs (?) */
792
793                                 NULL, /* char sess_key[16] */
794
795                                 global_myname  , /* char *logon_srv */
796                                 global_sam_name, /* char *logon_dom */
797                                 &global_sam_sid, /* DOM_SID *dom_sid */
798                                 NULL); /* char *other_sids */
799
800                         /* Free any allocated groups array. */
801                         if (gids)
802                         {
803                                 free((char *)gids);
804                         }
805                 }
806
807         }
808
809         net_reply_sam_logon(&q_l, rdata, &srv_cred, &usr_info, status);
810 }
811
812
813 /*************************************************************************
814  api_net_trust_dom_list:
815  *************************************************************************/
816 static void api_net_trust_dom_list( uint16 vuid,
817                                  prs_struct *data,
818                                  prs_struct *rdata)
819 {
820         NET_Q_TRUST_DOM_LIST q_t;
821
822         char *trusted_domain = "test_domain";
823
824         DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
825
826         /* grab the lsa trusted domain list query... */
827         net_io_q_trust_dom("", &q_t, data, 0);
828
829         /* construct reply. */
830         net_reply_trust_dom_list(&q_t, rdata,
831                                 1, trusted_domain);
832
833         DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
834 }
835
836
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
842
843 /*************************************************************************
844  api_net_logon_ctrl2:
845  *************************************************************************/
846 static void api_net_logon_ctrl2( uint16 vuid,
847                                  prs_struct *data,
848                                  prs_struct *rdata)
849 {
850         NET_Q_LOGON_CTRL2 q_l;
851
852         /* lkclXXXX - guess what - absolutely no idea what these are! */
853         uint32 flags = 0x0;
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";
858
859         DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
860
861         /* grab the lsa netlogon ctrl2 query... */
862         net_io_q_logon_ctrl2("", &q_l, data, 0);
863
864         /* construct reply. */
865         net_reply_logon_ctrl2(&q_l, rdata,
866                                 flags, pdc_connection_status, logon_attempts,
867                                 tc_status, trusted_domain);
868
869         DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
870 }
871
872 /*******************************************************************
873  array of \PIPE\NETLOGON operations
874  ********************************************************************/
875 static struct api_struct api_net_cmds [] =
876 {
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 },
884     {  NULL               , 0                 , NULL                   }
885 };
886
887 /*******************************************************************
888  receives a netlogon pipe and responds.
889  ********************************************************************/
890 BOOL api_netlog_rpc(pipes_struct *p, prs_struct *data)
891 {
892         return api_rpcTNP(p, "api_netlog_rpc", api_net_cmds, data);
893 }