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