Greg Dickie spotted some wierd memory corruption problem with group
[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 (memcmp(smb_pass->smb_passwd   , lm_pwd, 16) != 0 &&
532             memcmp(smb_pass->smb_nt_passwd, nt_pwd, 16) != 0)
533         {
534                 status = 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
535         }
536
537         return status;
538 }
539
540 /*************************************************************************
541  net_login_network:
542  *************************************************************************/
543 static uint32 net_login_network(NET_ID_INFO_2 *id2,
544                                 struct sam_passwd *smb_pass,
545                                 user_struct *vuser)
546 {
547         DEBUG(5,("net_login_network: lm_len: %d nt_len: %d\n",
548                 id2->hdr_lm_chal_resp.str_str_len, 
549                 id2->hdr_nt_chal_resp.str_str_len));
550
551         /* JRA. Check the NT password first if it exists - this is a higher quality 
552            password, if it exists and it doesn't match - fail. */
553
554         if (id2->hdr_nt_chal_resp.str_str_len == 24 && 
555                 smb_pass->smb_nt_passwd != NULL)
556         {
557                 if(smb_password_check((char *)id2->nt_chal_resp.buffer,
558                                    smb_pass->smb_nt_passwd,
559                            id2->lm_chal)) 
560                   return 0x0;
561                 else
562                   return 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
563         }
564
565         /* lkclXXXX this is not a good place to put disabling of LM hashes in.
566            if that is to be done, first move this entire function into a
567            library routine that calls the two smb_password_check() functions.
568            if disabling LM hashes (which nt can do for security reasons) then
569            an attempt should be made to disable them everywhere (which nt does
570            not do, for various security-hole reasons).
571          */
572
573         if (id2->hdr_lm_chal_resp.str_str_len == 24 &&
574                 smb_password_check((char *)id2->lm_chal_resp.buffer,
575                                    smb_pass->smb_passwd,
576                                    id2->lm_chal))
577         {
578                 return 0x0;
579         }
580
581
582         /* oops! neither password check succeeded */
583
584         return 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
585 }
586
587 /*************************************************************************
588  api_net_sam_logon:
589  *************************************************************************/
590 static void api_net_sam_logon( uint16 vuid,
591                                prs_struct *data,
592                                prs_struct *rdata)
593 {
594         NET_Q_SAM_LOGON q_l;
595         NET_ID_INFO_CTR ctr;    
596         NET_USER_INFO_3 usr_info;
597         uint32 status = 0x0;
598         DOM_CRED srv_cred;
599         struct sam_passwd *sam_pass = NULL;
600         UNISTR2 *uni_samlogon_user = NULL;
601         UNISTR2 *uni_domain = NULL;
602         fstring nt_username;
603
604         NTTIME logon_time           ;
605         NTTIME logoff_time          ;
606         NTTIME kickoff_time         ;
607         NTTIME pass_last_set_time   ;
608         NTTIME pass_can_change_time ;
609         NTTIME pass_must_change_time;
610
611         fstring nt_name     ;
612         fstring full_name   ;
613         fstring logon_script;
614         fstring profile_path;
615         fstring home_dir    ;
616         fstring dir_drive   ;
617
618         uint32 user_rid ;
619         uint32 group_rid;
620
621         user_struct *vuser = NULL;
622
623         if ((vuser = get_valid_user_struct(vuid)) == NULL)
624         return;
625
626         q_l.sam_id.ctr = &ctr;
627
628         net_io_q_sam_logon("", &q_l, data, 0);
629
630         /* checks and updates credentials.  creates reply credentials */
631         if (!deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred), 
632                              &(q_l.sam_id.client.cred), &srv_cred))
633         {
634                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
635         }
636         else
637         {
638                 memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred));
639         }
640
641         /* find the username */
642
643         if (status == 0)
644         {
645                 switch (q_l.sam_id.logon_level)
646                 {
647                         case INTERACTIVE_LOGON_TYPE:
648                         {
649                                 uni_samlogon_user = &(q_l.sam_id.ctr->auth.id1.uni_user_name);
650                                 uni_domain        = &(q_l.sam_id.ctr->auth.id1.uni_domain_name);
651
652                                 DEBUG(3,("SAM Logon (Interactive). Domain:[%s].  ", global_sam_name));
653                                 break;
654                         }
655                         case NET_LOGON_TYPE:
656                         {
657                                 uni_samlogon_user = &(q_l.sam_id.ctr->auth.id2.uni_user_name);
658                                 uni_domain        = &(q_l.sam_id.ctr->auth.id2.uni_domain_name);
659
660                                 DEBUG(3,("SAM Logon (Network). Domain:[%s].  ", global_sam_name));
661                                 break;
662                         }
663                         default:
664                         {
665                                 DEBUG(2,("SAM Logon: unsupported switch value\n"));
666                                 status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
667                                 break;
668                         }
669                 } /* end switch */
670         } /* end if status == 0 */
671
672         /* check username exists */
673
674         if (status == 0)
675         {
676                 unistr2_to_ascii(nt_username, uni_samlogon_user,
677                                  sizeof(nt_username)-1);
678
679                 DEBUG(3,("User:[%s]\n", nt_username));
680
681                 become_root(True);
682                 sam_pass = getsam21pwntnam(nt_username);
683                 unbecome_root(True);
684
685                 if (sam_pass == NULL)
686                 {
687                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
688                 }
689                 else if (IS_BITS_SET_ALL(sam_pass->acct_ctrl, ACB_DISABLED) &&
690                          IS_BITS_CLR_ALL(sam_pass->acct_ctrl, ACB_PWNOTREQ))
691                 {
692                         status =  0xC0000000 | NT_STATUS_ACCOUNT_DISABLED;
693                 }
694         }
695
696         if (status == 0x0)
697         {
698                 logon_time            = sam_pass->logon_time;
699                 logoff_time           = sam_pass->logoff_time;
700                 kickoff_time          = sam_pass->kickoff_time;
701                 pass_last_set_time    = sam_pass->pass_last_set_time;
702                 pass_can_change_time  = sam_pass->pass_can_change_time;
703                 pass_must_change_time = sam_pass->pass_must_change_time;
704
705                 fstrcpy(nt_name     , sam_pass->nt_name);
706                 fstrcpy(full_name   , sam_pass->full_name);
707                 fstrcpy(logon_script, sam_pass->logon_script);
708                 fstrcpy(profile_path, sam_pass->profile_path);
709                 fstrcpy(home_dir    , sam_pass->home_dir);
710                 fstrcpy(dir_drive   , sam_pass->dir_drive);
711
712                 user_rid  = sam_pass->user_rid;
713                 group_rid = sam_pass->group_rid;
714         }
715
716         /* validate password - if required */
717
718         if (status == 0 && !(IS_BITS_SET_ALL(sam_pass->acct_ctrl, ACB_PWNOTREQ)))
719         {
720                 switch (q_l.sam_id.logon_level)
721                 {
722                         case INTERACTIVE_LOGON_TYPE:
723                         {
724                                 /* interactive login. */
725                                 status = net_login_interactive(&q_l.sam_id.ctr->auth.id1, sam_pass, vuser);
726                                 break;
727                         }
728                         case NET_LOGON_TYPE:
729                         {
730                                 /* network login.  lm challenge and 24 byte responses */
731                                 status = net_login_network(&q_l.sam_id.ctr->auth.id2, sam_pass, vuser);
732                                 break;
733                         }
734                 }
735         }
736
737         /* lkclXXXX this is the point at which, if the login was
738         successful, that the SAM Local Security Authority should
739         record that the user is logged in to the domain.
740         */
741
742         /* return the profile plus other bits :-) */
743
744         if (status == 0)
745         {
746                 int num_gids = 0;
747                 DOMAIN_GRP *grp_mem = NULL;
748
749                 /* set up pointer indicating user/password failed to be found */
750                 usr_info.ptr_user_info = 0;
751
752                 if (!getusergroupsntnam(nt_username, &grp_mem, &num_gids))
753                 {
754                         status = 0xC0000000 | NT_STATUS_INVALID_PRIMARY_GROUP;
755                 }
756
757                 if (status == 0x0)
758                 {
759                         DOM_GID *gids = NULL;
760                         num_gids = make_dom_gids(grp_mem, num_gids, &gids);
761
762                         make_net_user_info3(&usr_info,
763                                 &logon_time,
764                                 &logoff_time,
765                                 &kickoff_time,
766                                 &pass_last_set_time,
767                                 &pass_can_change_time,
768                                 &pass_must_change_time,
769
770                                 nt_name         , /* user_name */
771                                 full_name       , /* full_name */
772                                 logon_script    , /* logon_script */
773                                 profile_path    , /* profile_path */
774                                 home_dir        , /* home_dir */
775                                 dir_drive       , /* dir_drive */
776
777                                 0, /* logon_count */
778                                 0, /* bad_pw_count */
779
780                                 user_rid   , /* RID user_id */
781                                 group_rid  , /* RID group_id */
782                                 num_gids,    /* uint32 num_groups */
783                                 gids    , /* DOM_GID *gids */
784                                 0x20    , /* uint32 user_flgs (?) */
785
786                                 NULL, /* char sess_key[16] */
787
788                                 global_myname  , /* char *logon_srv */
789                                 global_sam_name, /* char *logon_dom */
790                                 &global_sam_sid, /* DOM_SID *dom_sid */
791                                 NULL); /* char *other_sids */
792
793                         /* Free any allocated groups array. */
794                         if (gids)
795                         {
796                                 free((char *)gids);
797                         }
798                 }
799
800         }
801
802         net_reply_sam_logon(&q_l, rdata, &srv_cred, &usr_info, status);
803 }
804
805
806 /*************************************************************************
807  api_net_trust_dom_list:
808  *************************************************************************/
809 static void api_net_trust_dom_list( uint16 vuid,
810                                  prs_struct *data,
811                                  prs_struct *rdata)
812 {
813         NET_Q_TRUST_DOM_LIST q_t;
814
815         char *trusted_domain = "test_domain";
816
817         DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
818
819         /* grab the lsa trusted domain list query... */
820         net_io_q_trust_dom("", &q_t, data, 0);
821
822         /* construct reply. */
823         net_reply_trust_dom_list(&q_t, rdata,
824                                 1, trusted_domain);
825
826         DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
827 }
828
829
830 /*************************************************************************
831  error messages cropping up when using nltest.exe...
832  *************************************************************************/
833 #define ERROR_NO_SUCH_DOMAIN   0x54b
834 #define ERROR_NO_LOGON_SERVERS 0x51f
835
836 /*************************************************************************
837  api_net_logon_ctrl2:
838  *************************************************************************/
839 static void api_net_logon_ctrl2( uint16 vuid,
840                                  prs_struct *data,
841                                  prs_struct *rdata)
842 {
843         NET_Q_LOGON_CTRL2 q_l;
844
845         /* lkclXXXX - guess what - absolutely no idea what these are! */
846         uint32 flags = 0x0;
847         uint32 pdc_connection_status = 0x0;
848         uint32 logon_attempts = 0x0;
849         uint32 tc_status = ERROR_NO_LOGON_SERVERS;
850         char *trusted_domain = "test_domain";
851
852         DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
853
854         /* grab the lsa netlogon ctrl2 query... */
855         net_io_q_logon_ctrl2("", &q_l, data, 0);
856
857         /* construct reply. */
858         net_reply_logon_ctrl2(&q_l, rdata,
859                                 flags, pdc_connection_status, logon_attempts,
860                                 tc_status, trusted_domain);
861
862         DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
863 }
864
865 /*******************************************************************
866  array of \PIPE\NETLOGON operations
867  ********************************************************************/
868 static struct api_struct api_net_cmds [] =
869 {
870         { "NET_REQCHAL"       , NET_REQCHAL       , api_net_req_chal       }, 
871         { "NET_AUTH2"         , NET_AUTH2         , api_net_auth_2         }, 
872         { "NET_SRVPWSET"      , NET_SRVPWSET      , api_net_srv_pwset      }, 
873         { "NET_SAMLOGON"      , NET_SAMLOGON      , api_net_sam_logon      }, 
874         { "NET_SAMLOGOFF"     , NET_SAMLOGOFF     , api_net_sam_logoff     }, 
875         { "NET_LOGON_CTRL2"   , NET_LOGON_CTRL2   , api_net_logon_ctrl2    }, 
876         { "NET_TRUST_DOM_LIST", NET_TRUST_DOM_LIST, api_net_trust_dom_list },
877     {  NULL               , 0                 , NULL                   }
878 };
879
880 /*******************************************************************
881  receives a netlogon pipe and responds.
882  ********************************************************************/
883 BOOL api_netlog_rpc(pipes_struct *p, prs_struct *data)
884 {
885         return api_rpcTNP(p, "api_netlog_rpc", api_net_cmds, data);
886 }