c3810a09e589f57a36ad7d9e63a9f732399028eb
[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, 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 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                 fstrcpy(nt_username, unistr2_to_str(uni_samlogon_user));
677 #if 0
678                 slprintf(nt_username, sizeof(nt_username), "%s\\%s",
679                          unistr2_to_str(uni_domain),
680                          unistr2_to_str(uni_samlogon_user));
681 #endif
682                 DEBUG(3,("User:[%s]\n", nt_username));
683
684                 become_root(True);
685                 sam_pass = getsam21pwntnam(nt_username);
686                 unbecome_root(True);
687
688                 if (sam_pass == NULL)
689                 {
690                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
691                 }
692                 else if (IS_BITS_SET_ALL(sam_pass->acct_ctrl, ACB_DISABLED) &&
693                          IS_BITS_CLR_ALL(sam_pass->acct_ctrl, ACB_PWNOTREQ))
694                 {
695                         status =  0xC0000000 | NT_STATUS_ACCOUNT_DISABLED;
696                 }
697         }
698
699         if (status == 0x0)
700         {
701                 logon_time            = sam_pass->logon_time;
702                 logoff_time           = sam_pass->logoff_time;
703                 kickoff_time          = sam_pass->kickoff_time;
704                 pass_last_set_time    = sam_pass->pass_last_set_time;
705                 pass_can_change_time  = sam_pass->pass_can_change_time;
706                 pass_must_change_time = sam_pass->pass_must_change_time;
707
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_username     , /* 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 }