33eb889ff2ed6a0da4786550fd0f87e14c442277
[samba.git] / source / 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         fstrcpy(mach_acct, unistr2_to_str(&q_r.uni_logon_clnt));
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                 fstrcpy(mach_acct, unistr2_to_str(&q_a.clnt_id.login.uni_acct_name));
403
404                 DEBUG(3,("Server Password Set Wksta:[%s]\n", mach_acct));
405
406                 become_root(True);
407                 smb_pass = getsmbpwnam(mach_acct);
408                 unbecome_root(True);
409
410                 if (smb_pass != NULL)
411                 {
412                         unsigned char pwd[16];
413                         int i;
414
415                         DEBUG(100,("Server password set : new given value was :\n"));
416                         for(i = 0; i < 16; i++)
417                         {
418                                 DEBUG(100,("%02X ", q_a.pwd[i]));
419                         }
420                         DEBUG(100,("\n"));
421
422                         cred_hash3( pwd, q_a.pwd, vuser->dc.sess_key, 0);
423
424                         /* lies!  nt and lm passwords are _not_ the same: don't care */
425                         smb_pass->smb_passwd    = pwd;
426                         smb_pass->smb_nt_passwd = pwd;
427                         smb_pass->acct_ctrl     = ACB_WSTRUST;
428
429                         become_root(True);
430                         ret = mod_smbpwd_entry(smb_pass,False);
431                         unbecome_root(True);
432
433                         if (ret)
434                         {
435                                 /* hooray! */
436                                 status = 0x0;
437                         }
438                 }
439
440                 DEBUG(5,("api_net_srv_pwset: %d\n", __LINE__));
441
442         }
443         else
444         {
445                 /* lkclXXXX take a guess at a sensible error code to return... */
446                 status = 0xC0000000 | NT_STATUS_NETWORK_CREDENTIAL_CONFLICT;
447         }
448
449         /* Construct reply. */
450         net_reply_srv_pwset(&q_a, rdata, &srv_cred, status);
451 }
452
453
454 /*************************************************************************
455  api_net_sam_logoff:
456  *************************************************************************/
457 static void api_net_sam_logoff( uint16 vuid,
458                                prs_struct *data,
459                                prs_struct *rdata)
460 {
461         NET_Q_SAM_LOGOFF q_l;
462         NET_ID_INFO_CTR ctr;    
463
464         DOM_CRED srv_cred;
465
466         user_struct *vuser;
467
468         if ((vuser = get_valid_user_struct(vuid)) == NULL)
469       return;
470
471         /* the DOM_ID_INFO_1 structure is a bit big.  plus we might want to
472            dynamically allocate it inside net_io_q_sam_logon, at some point */
473         q_l.sam_id.ctr = &ctr;
474
475         /* grab the challenge... */
476         net_io_q_sam_logoff("", &q_l, data, 0);
477
478         /* checks and updates credentials.  creates reply credentials */
479         deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred), 
480                         &(q_l.sam_id.client.cred), &srv_cred);
481         memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred));
482
483         /* construct reply.  always indicate success */
484         net_reply_sam_logoff(&q_l, rdata,
485                                         &srv_cred,
486                         0x0);
487 }
488
489 /*************************************************************************
490  net_login_interactive:
491  *************************************************************************/
492 static uint32 net_login_interactive(NET_ID_INFO_1 *id1,
493                                 struct sam_passwd *smb_pass,
494                                 user_struct *vuser)
495 {
496         uint32 status = 0x0;
497
498         char nt_pwd[16];
499         char lm_pwd[16];
500         unsigned char key[16];
501
502         memset(key, 0, 16);
503         memcpy(key, vuser->dc.sess_key, 8);
504
505         memcpy(lm_pwd, id1->lm_owf.data, 16);
506         memcpy(nt_pwd, id1->nt_owf.data, 16);
507
508 #ifdef DEBUG_PASSWORD
509         DEBUG(100,("key:"));
510         dump_data(100, key, 16);
511
512         DEBUG(100,("lm owf password:"));
513         dump_data(100, lm_pwd, 16);
514
515         DEBUG(100,("nt owf password:"));
516         dump_data(100, nt_pwd, 16);
517 #endif
518
519         SamOEMhash((uchar *)lm_pwd, key, False);
520         SamOEMhash((uchar *)nt_pwd, key, False);
521
522 #ifdef DEBUG_PASSWORD
523         DEBUG(100,("decrypt of lm owf password:"));
524         dump_data(100, lm_pwd, 16);
525
526         DEBUG(100,("decrypt of nt owf password:"));
527         dump_data(100, nt_pwd, 16);
528 #endif
529
530         if (memcmp(smb_pass->smb_passwd   , lm_pwd, 16) != 0 &&
531             memcmp(smb_pass->smb_nt_passwd, nt_pwd, 16) != 0)
532         {
533                 status = 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
534         }
535
536         return status;
537 }
538
539 /*************************************************************************
540  net_login_network:
541  *************************************************************************/
542 static uint32 net_login_network(NET_ID_INFO_2 *id2,
543                                 struct sam_passwd *smb_pass,
544                                 user_struct *vuser)
545 {
546         DEBUG(5,("net_login_network: lm_len: %d nt_len: %d\n",
547                 id2->hdr_lm_chal_resp.str_str_len, 
548                 id2->hdr_nt_chal_resp.str_str_len));
549
550         /* JRA. Check the NT password first if it exists - this is a higher quality 
551            password, if it exists and it doesn't match - fail. */
552
553         if (id2->hdr_nt_chal_resp.str_str_len == 24 && 
554                 smb_pass->smb_nt_passwd != NULL)
555         {
556                 if(smb_password_check((char *)id2->nt_chal_resp.buffer,
557                                    smb_pass->smb_nt_passwd,
558                            id2->lm_chal)) 
559                   return 0x0;
560                 else
561                   return 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
562         }
563
564         /* lkclXXXX this is not a good place to put disabling of LM hashes in.
565            if that is to be done, first move this entire function into a
566            library routine that calls the two smb_password_check() functions.
567            if disabling LM hashes (which nt can do for security reasons) then
568            an attempt should be made to disable them everywhere (which nt does
569            not do, for various security-hole reasons).
570          */
571
572         if (id2->hdr_lm_chal_resp.str_str_len == 24 &&
573                 smb_password_check((char *)id2->lm_chal_resp.buffer,
574                                    smb_pass->smb_passwd,
575                                    id2->lm_chal))
576         {
577                 return 0x0;
578         }
579
580
581         /* oops! neither password check succeeded */
582
583         return 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
584 }
585
586 /*************************************************************************
587  api_net_sam_logon:
588  *************************************************************************/
589 static void api_net_sam_logon( uint16 vuid,
590                                prs_struct *data,
591                                prs_struct *rdata)
592 {
593         NET_Q_SAM_LOGON q_l;
594         NET_ID_INFO_CTR ctr;    
595         NET_USER_INFO_3 usr_info;
596         uint32 status = 0x0;
597         DOM_CRED srv_cred;
598         struct sam_passwd *sam_pass = NULL;
599         UNISTR2 *uni_samlogon_user = NULL;
600         UNISTR2 *uni_domain = NULL;
601         fstring nt_username;
602
603         NTTIME logon_time           ;
604         NTTIME logoff_time          ;
605         NTTIME kickoff_time         ;
606         NTTIME pass_last_set_time   ;
607         NTTIME pass_can_change_time ;
608         NTTIME pass_must_change_time;
609
610         fstring nt_name     ;
611         fstring full_name   ;
612         fstring logon_script;
613         fstring profile_path;
614         fstring home_dir    ;
615         fstring dir_drive   ;
616
617         uint32 user_rid ;
618         uint32 group_rid;
619
620         user_struct *vuser = NULL;
621
622         if ((vuser = get_valid_user_struct(vuid)) == NULL)
623         return;
624
625         q_l.sam_id.ctr = &ctr;
626
627         net_io_q_sam_logon("", &q_l, data, 0);
628
629         /* checks and updates credentials.  creates reply credentials */
630         if (!deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred), 
631                              &(q_l.sam_id.client.cred), &srv_cred))
632         {
633                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
634         }
635         else
636         {
637                 memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred));
638         }
639
640         /* find the username */
641
642         if (status == 0)
643         {
644                 switch (q_l.sam_id.logon_level)
645                 {
646                         case INTERACTIVE_LOGON_TYPE:
647                         {
648                                 uni_samlogon_user = &(q_l.sam_id.ctr->auth.id1.uni_user_name);
649                                 uni_domain        = &(q_l.sam_id.ctr->auth.id1.uni_domain_name);
650
651                                 DEBUG(3,("SAM Logon (Interactive). Domain:[%s].  ", global_sam_name));
652                                 break;
653                         }
654                         case NET_LOGON_TYPE:
655                         {
656                                 uni_samlogon_user = &(q_l.sam_id.ctr->auth.id2.uni_user_name);
657                                 uni_domain        = &(q_l.sam_id.ctr->auth.id2.uni_domain_name);
658
659                                 DEBUG(3,("SAM Logon (Network). Domain:[%s].  ", global_sam_name));
660                                 break;
661                         }
662                         default:
663                         {
664                                 DEBUG(2,("SAM Logon: unsupported switch value\n"));
665                                 status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
666                                 break;
667                         }
668                 } /* end switch */
669         } /* end if status == 0 */
670
671         /* check username exists */
672
673         if (status == 0)
674         {
675                 fstrcpy(nt_username, unistr2_to_str(uni_samlogon_user));
676 #if 0
677                 slprintf(nt_username, sizeof(nt_username), "%s\\%s",
678                          unistr2_to_str(uni_domain),
679                          unistr2_to_str(uni_samlogon_user));
680 #endif
681                 DEBUG(3,("User:[%s]\n", nt_username));
682
683                 become_root(True);
684                 sam_pass = getsam21pwntnam(nt_username);
685                 unbecome_root(True);
686
687                 if (sam_pass == NULL)
688                 {
689                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
690                 }
691                 else if (IS_BITS_SET_ALL(sam_pass->acct_ctrl, ACB_DISABLED) &&
692                          IS_BITS_CLR_ALL(sam_pass->acct_ctrl, ACB_PWNOTREQ))
693                 {
694                         status =  0xC0000000 | NT_STATUS_ACCOUNT_DISABLED;
695                 }
696         }
697
698         if (status == 0x0)
699         {
700                 logon_time            = sam_pass->logon_time;
701                 logoff_time           = sam_pass->logoff_time;
702                 kickoff_time          = sam_pass->kickoff_time;
703                 pass_last_set_time    = sam_pass->pass_last_set_time;
704                 pass_can_change_time  = sam_pass->pass_can_change_time;
705                 pass_must_change_time = sam_pass->pass_must_change_time;
706
707                 fstrcpy(nt_name     , sam_pass->nt_name);
708                 fstrcpy(full_name   , sam_pass->full_name);
709                 fstrcpy(logon_script, sam_pass->logon_script);
710                 fstrcpy(profile_path, sam_pass->profile_path);
711                 fstrcpy(home_dir    , sam_pass->home_dir);
712                 fstrcpy(dir_drive   , sam_pass->dir_drive);
713
714                 user_rid  = sam_pass->user_rid;
715                 group_rid = sam_pass->group_rid;
716         }
717
718         /* validate password - if required */
719
720         if (status == 0 && !(IS_BITS_SET_ALL(sam_pass->acct_ctrl, ACB_PWNOTREQ)))
721         {
722                 switch (q_l.sam_id.logon_level)
723                 {
724                         case INTERACTIVE_LOGON_TYPE:
725                         {
726                                 /* interactive login. */
727                                 status = net_login_interactive(&q_l.sam_id.ctr->auth.id1, sam_pass, vuser);
728                                 break;
729                         }
730                         case NET_LOGON_TYPE:
731                         {
732                                 /* network login.  lm challenge and 24 byte responses */
733                                 status = net_login_network(&q_l.sam_id.ctr->auth.id2, sam_pass, vuser);
734                                 break;
735                         }
736                 }
737         }
738
739         /* lkclXXXX this is the point at which, if the login was
740         successful, that the SAM Local Security Authority should
741         record that the user is logged in to the domain.
742         */
743
744         /* return the profile plus other bits :-) */
745
746         if (status == 0)
747         {
748                 int num_gids = 0;
749                 DOMAIN_GRP *grp_mem = NULL;
750
751                 /* set up pointer indicating user/password failed to be found */
752                 usr_info.ptr_user_info = 0;
753
754                 if (!getusergroupsntnam(nt_username, &grp_mem, &num_gids))
755                 {
756                         status = 0xC0000000 | NT_STATUS_INVALID_PRIMARY_GROUP;
757                 }
758
759                 if (status == 0x0)
760                 {
761                         DOM_GID *gids = NULL;
762                         num_gids = make_dom_gids(grp_mem, num_gids, &gids);
763
764                         make_net_user_info3(&usr_info,
765                                 &logon_time,
766                                 &logoff_time,
767                                 &kickoff_time,
768                                 &pass_last_set_time,
769                                 &pass_can_change_time,
770                                 &pass_must_change_time,
771
772                                 nt_name         , /* user_name */
773                                 full_name       , /* full_name */
774                                 logon_script    , /* logon_script */
775                                 profile_path    , /* profile_path */
776                                 home_dir        , /* home_dir */
777                                 dir_drive       , /* dir_drive */
778
779                                 0, /* logon_count */
780                                 0, /* bad_pw_count */
781
782                                 user_rid   , /* RID user_id */
783                                 group_rid  , /* RID group_id */
784                                 num_gids,    /* uint32 num_groups */
785                                 gids    , /* DOM_GID *gids */
786                                 0x20    , /* uint32 user_flgs (?) */
787
788                                 NULL, /* char sess_key[16] */
789
790                                 global_myname  , /* char *logon_srv */
791                                 global_sam_name, /* char *logon_dom */
792                                 &global_sam_sid, /* DOM_SID *dom_sid */
793                                 NULL); /* char *other_sids */
794
795                         /* Free any allocated groups array. */
796                         if (gids)
797                         {
798                                 free((char *)gids);
799                         }
800                 }
801
802         }
803
804         net_reply_sam_logon(&q_l, rdata, &srv_cred, &usr_info, status);
805 }
806
807
808 /*************************************************************************
809  api_net_trust_dom_list:
810  *************************************************************************/
811 static void api_net_trust_dom_list( uint16 vuid,
812                                  prs_struct *data,
813                                  prs_struct *rdata)
814 {
815         NET_Q_TRUST_DOM_LIST q_t;
816
817         char *trusted_domain = "test_domain";
818
819         DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
820
821         /* grab the lsa trusted domain list query... */
822         net_io_q_trust_dom("", &q_t, data, 0);
823
824         /* construct reply. */
825         net_reply_trust_dom_list(&q_t, rdata,
826                                 1, trusted_domain);
827
828         DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
829 }
830
831
832 /*************************************************************************
833  error messages cropping up when using nltest.exe...
834  *************************************************************************/
835 #define ERROR_NO_SUCH_DOMAIN   0x54b
836 #define ERROR_NO_LOGON_SERVERS 0x51f
837
838 /*************************************************************************
839  api_net_logon_ctrl2:
840  *************************************************************************/
841 static void api_net_logon_ctrl2( uint16 vuid,
842                                  prs_struct *data,
843                                  prs_struct *rdata)
844 {
845         NET_Q_LOGON_CTRL2 q_l;
846
847         /* lkclXXXX - guess what - absolutely no idea what these are! */
848         uint32 flags = 0x0;
849         uint32 pdc_connection_status = 0x0;
850         uint32 logon_attempts = 0x0;
851         uint32 tc_status = ERROR_NO_LOGON_SERVERS;
852         char *trusted_domain = "test_domain";
853
854         DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
855
856         /* grab the lsa netlogon ctrl2 query... */
857         net_io_q_logon_ctrl2("", &q_l, data, 0);
858
859         /* construct reply. */
860         net_reply_logon_ctrl2(&q_l, rdata,
861                                 flags, pdc_connection_status, logon_attempts,
862                                 tc_status, trusted_domain);
863
864         DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
865 }
866
867 /*******************************************************************
868  array of \PIPE\NETLOGON operations
869  ********************************************************************/
870 static struct api_struct api_net_cmds [] =
871 {
872         { "NET_REQCHAL"       , NET_REQCHAL       , api_net_req_chal       }, 
873         { "NET_AUTH2"         , NET_AUTH2         , api_net_auth_2         }, 
874         { "NET_SRVPWSET"      , NET_SRVPWSET      , api_net_srv_pwset      }, 
875         { "NET_SAMLOGON"      , NET_SAMLOGON      , api_net_sam_logon      }, 
876         { "NET_SAMLOGOFF"     , NET_SAMLOGOFF     , api_net_sam_logoff     }, 
877         { "NET_LOGON_CTRL2"   , NET_LOGON_CTRL2   , api_net_logon_ctrl2    }, 
878         { "NET_TRUST_DOM_LIST", NET_TRUST_DOM_LIST, api_net_trust_dom_list },
879     {  NULL               , 0                 , NULL                   }
880 };
881
882 /*******************************************************************
883  receives a netlogon pipe and responds.
884  ********************************************************************/
885 BOOL api_netlog_rpc(pipes_struct *p, prs_struct *data)
886 {
887         return api_rpcTNP(p, "api_netlog_rpc", api_net_cmds, data);
888 }