Got very strict about the differences and uses of
[mimir/samba.git] / source3 / rpc_server / srv_netlog.c
1
2 /* 
3  *  Unix SMB/Netbios implementation.
4  *  Version 1.9.
5  *  RPC Pipe client / server routines
6  *  Copyright (C) Andrew Tridgell              1992-1997,
7  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
8  *  Copyright (C) Paul Ashton                       1997.
9  *  Copyright (C) Jeremy Allison                    1998.
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *  
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *  
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25
26
27 #include "includes.h"
28 #include "nterr.h"
29
30 extern int DEBUGLEVEL;
31
32 extern BOOL sam_logon_in_ssb;
33 extern pstring samlogon_user;
34 extern pstring global_myname;
35 extern DOM_SID global_machine_sid;
36
37 /*************************************************************************
38  make_net_r_req_chal:
39  *************************************************************************/
40 static void make_net_r_req_chal(NET_R_REQ_CHAL *r_c,
41                                 DOM_CHAL *srv_chal, int status)
42 {
43         DEBUG(6,("make_net_r_req_chal: %d\n", __LINE__));
44         memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(srv_chal->data));
45         r_c->status = status;
46 }
47
48 /*************************************************************************
49  net_reply_req_chal:
50  *************************************************************************/
51 static void net_reply_req_chal(NET_Q_REQ_CHAL *q_c, prs_struct *rdata,
52                                         DOM_CHAL *srv_chal, uint32 srv_time)
53 {
54         NET_R_REQ_CHAL r_c;
55
56         DEBUG(6,("net_reply_req_chal: %d\n", __LINE__));
57
58         /* set up the LSA REQUEST CHALLENGE response */
59         make_net_r_req_chal(&r_c, srv_chal, srv_time);
60
61         /* store the response in the SMB stream */
62         net_io_r_req_chal("", &r_c, rdata, 0);
63
64         DEBUG(6,("net_reply_req_chal: %d\n", __LINE__));
65
66 }
67
68 /*************************************************************************
69  net_reply_logon_ctrl2:
70  *************************************************************************/
71 static void net_reply_logon_ctrl2(NET_Q_LOGON_CTRL2 *q_l, prs_struct *rdata,
72                         uint32 flags, uint32 pdc_status, uint32 logon_attempts,
73                         uint32 tc_status, char *trust_domain_name)
74 {
75         NET_R_LOGON_CTRL2 r_l;
76
77         DEBUG(6,("net_reply_logon_ctrl2: %d\n", __LINE__));
78
79         /* set up the Logon Control2 response */
80         make_r_logon_ctrl2(&r_l, q_l->query_level,
81                            flags, pdc_status, logon_attempts,
82                            tc_status, trust_domain_name);
83
84         /* store the response in the SMB stream */
85         net_io_r_logon_ctrl2("", &r_l, rdata, 0);
86
87         DEBUG(6,("net_reply_logon_ctrl2: %d\n", __LINE__));
88
89 }
90
91 /*************************************************************************
92  net_reply_trust_dom_list:
93  *************************************************************************/
94 static void net_reply_trust_dom_list(NET_Q_TRUST_DOM_LIST *q_t, prs_struct *rdata,
95                         uint32 num_trust_domains, char *trust_domain_name)
96 {
97         NET_R_TRUST_DOM_LIST r_t;
98
99         DEBUG(6,("net_reply_trust_dom_list: %d\n", __LINE__));
100
101         /* set up the Trusted Domain List response */
102         make_r_trust_dom(&r_t, num_trust_domains, trust_domain_name);
103
104         /* store the response in the SMB stream */
105         net_io_r_trust_dom("", &r_t, rdata, 0);
106
107         DEBUG(6,("net_reply_trust_dom_listlogon_ctrl2: %d\n", __LINE__));
108
109 }
110
111 /*************************************************************************
112  make_net_r_auth_2:
113  *************************************************************************/
114 static void make_net_r_auth_2(NET_R_AUTH_2 *r_a,
115                               DOM_CHAL *resp_cred, NEG_FLAGS *flgs, int status)
116 {
117         memcpy(  r_a->srv_chal.data, resp_cred->data, sizeof(resp_cred->data));
118         memcpy(&(r_a->srv_flgs)    , flgs           , sizeof(r_a->srv_flgs));
119         r_a->status = status;
120 }
121
122 /*************************************************************************
123  net_reply_auth_2:
124  *************************************************************************/
125 static void net_reply_auth_2(NET_Q_AUTH_2 *q_a, prs_struct *rdata,
126                                 DOM_CHAL *resp_cred, int status)
127 {
128         NET_R_AUTH_2 r_a;
129
130         /* set up the LSA AUTH 2 response */
131
132         make_net_r_auth_2(&r_a, resp_cred, &(q_a->clnt_flgs), status);
133
134         /* store the response in the SMB stream */
135         net_io_r_auth_2("", &r_a, rdata, 0);
136
137 }
138
139 /***********************************************************************************
140  make_net_r_srv_pwset:
141  ***********************************************************************************/
142 static void make_net_r_srv_pwset(NET_R_SRV_PWSET *r_s,
143                              DOM_CRED *srv_cred, int status)  
144 {
145         DEBUG(5,("make_net_r_srv_pwset: %d\n", __LINE__));
146
147         memcpy(&(r_s->srv_cred), srv_cred, sizeof(r_s->srv_cred));
148         r_s->status = status;
149
150         DEBUG(5,("make_net_r_srv_pwset: %d\n", __LINE__));
151 }
152
153 /*************************************************************************
154  net_reply_srv_pwset:
155  *************************************************************************/
156 static void net_reply_srv_pwset(NET_Q_SRV_PWSET *q_s, prs_struct *rdata,
157                                 DOM_CRED *srv_cred, int status)
158 {
159         NET_R_SRV_PWSET r_s;
160
161         DEBUG(5,("net_srv_pwset: %d\n", __LINE__));
162
163         /* set up the LSA Server Password Set response */
164         make_net_r_srv_pwset(&r_s, srv_cred, status);
165
166         /* store the response in the SMB stream */
167         net_io_r_srv_pwset("", &r_s, rdata, 0);
168
169         DEBUG(5,("net_srv_pwset: %d\n", __LINE__));
170
171 }
172
173 /*************************************************************************
174  net_reply_sam_logon:
175  *************************************************************************/
176 static void net_reply_sam_logon(NET_Q_SAM_LOGON *q_s, prs_struct *rdata,
177                                 DOM_CRED *srv_cred, NET_USER_INFO_3 *user_info,
178                                 uint32 status)
179 {
180         NET_R_SAM_LOGON r_s;
181
182         /* XXXX maybe we want to say 'no', reject the client's credentials */
183         r_s.buffer_creds = 1; /* yes, we have valid server credentials */
184         memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds));
185
186         /* store the user information, if there is any. */
187         r_s.user = user_info;
188         if (status == 0x0 && user_info != NULL && user_info->ptr_user_info != 0)
189         {
190                 r_s.switch_value = 3; /* indicates type of validation user info */
191         }
192         else
193         {
194                 r_s.switch_value = 0; /* indicates no info */
195         }
196
197         r_s.status = status;
198         r_s.auth_resp = 1; /* authoritative response */
199
200         /* store the response in the SMB stream */
201         net_io_r_sam_logon("", &r_s, rdata, 0);
202
203 }
204
205
206 /*************************************************************************
207  net_reply_sam_logoff:
208  *************************************************************************/
209 static void net_reply_sam_logoff(NET_Q_SAM_LOGOFF *q_s, prs_struct *rdata,
210                                 DOM_CRED *srv_cred, 
211                                 uint32 status)
212 {
213         NET_R_SAM_LOGOFF r_s;
214
215         /* XXXX maybe we want to say 'no', reject the client's credentials */
216         r_s.buffer_creds = 1; /* yes, we have valid server credentials */
217         memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds));
218
219         r_s.status = status;
220
221         /* store the response in the SMB stream */
222         net_io_r_sam_logoff("", &r_s, rdata, 0);
223
224 }
225
226 /******************************************************************
227  gets a machine password entry.  checks access rights of the host.
228  ******************************************************************/
229 static BOOL get_md4pw(char *md4pw, char *mach_name, char *mach_acct)
230 {
231         struct smb_passwd *smb_pass;
232
233 #if 0
234     /*
235      * Currently this code is redundent as we already have a filter
236      * by hostname list. What this code really needs to do is to 
237      * get a hosts allowed/hosts denied list from the SAM database
238      * on a per user basis, and make the access decision there.
239      * I will leave this code here for now as a reminder to implement
240      * this at a later date. JRA.
241      */
242
243         if (!allow_access(lp_domain_hostsdeny(), lp_domain_hostsallow(),
244                           client_name(Client), client_addr(Client)))
245         {
246                 DEBUG(0,("get_md4pw: Workstation %s denied access to domain\n", mach_acct));
247                 return False;
248         }
249 #endif /* 0 */
250
251         become_root(True);
252         smb_pass = getsmbpwnam(mach_acct);
253         unbecome_root(True);
254
255         if ((smb_pass) != NULL && !(smb_pass->acct_ctrl & ACB_DISABLED) &&
256         (smb_pass->smb_nt_passwd != NULL))
257         {
258                 memcpy(md4pw, smb_pass->smb_nt_passwd, 16);
259                 dump_data(5, md4pw, 16);
260
261                 return True;
262         }
263         DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct));
264         return False;
265 }
266
267 /*************************************************************************
268  api_net_req_chal:
269  *************************************************************************/
270 static void api_net_req_chal( uint16 vuid,
271                               prs_struct *data,
272                               prs_struct *rdata)
273 {
274         NET_Q_REQ_CHAL q_r;
275         uint32 status = 0x0;
276
277         fstring mach_acct;
278         fstring mach_name;
279
280         user_struct *vuser;
281
282         DEBUG(5,("api_net_req_chal(%d): vuid %d\n", __LINE__, (int)vuid));
283
284         if ((vuser = get_valid_user_struct(vuid)) == NULL)
285       return;
286
287         /* grab the challenge... */
288         net_io_q_req_chal("", &q_r, data, 0);
289
290         fstrcpy(mach_acct, unistrn2(q_r.uni_logon_clnt.buffer,
291                                     q_r.uni_logon_clnt.uni_str_len));
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                 pstrcpy(mach_acct, unistrn2(q_a.clnt_id.login.uni_acct_name.buffer,
403                                             q_a.clnt_id.login.uni_acct_name.uni_str_len));
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 smb_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         SamOEMhash((uchar *)lm_pwd, key, False);
510         SamOEMhash((uchar *)nt_pwd, key, False);
511
512 #ifdef DEBUG_PASSWORD
513         DEBUG(100,("decrypt of lm owf password:"));
514         dump_data(100, lm_pwd, 16);
515
516         DEBUG(100,("decrypt of nt owf password:"));
517         dump_data(100, nt_pwd, 16);
518 #endif
519
520         if (memcmp(smb_pass->smb_passwd   , lm_pwd, 16) != 0 &&
521                 memcmp(smb_pass->smb_nt_passwd, nt_pwd, 16) != 0)
522         {
523                 status = 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
524         }
525
526         return status;
527 }
528
529 /*************************************************************************
530  net_login_network:
531  *************************************************************************/
532 static uint32 net_login_network(NET_ID_INFO_2 *id2,
533                                 struct smb_passwd *smb_pass,
534                                 user_struct *vuser)
535 {
536         DEBUG(5,("net_login_network: lm_len: %d nt_len: %d\n",
537                 id2->hdr_lm_chal_resp.str_str_len, 
538                 id2->hdr_nt_chal_resp.str_str_len));
539
540         /* JRA. Check the NT password first if it exists - this is a higher quality 
541            password, if it exists and it doesn't match - fail. */
542
543         if (id2->hdr_nt_chal_resp.str_str_len == 24 && 
544                 smb_pass->smb_nt_passwd != NULL)
545         {
546                 if(smb_password_check((char *)id2->nt_chal_resp.buffer,
547                                    smb_pass->smb_nt_passwd,
548                            id2->lm_chal)) 
549                   return 0x0;
550                 else
551                   return 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
552         }
553
554         /* lkclXXXX this is not a good place to put disabling of LM hashes in.
555            if that is to be done, first move this entire function into a
556            library routine that calls the two smb_password_check() functions.
557            if disabling LM hashes (which nt can do for security reasons) then
558            an attempt should be made to disable them everywhere (which nt does
559            not do, for various security-hole reasons).
560          */
561
562         if (id2->hdr_lm_chal_resp.str_str_len == 24 &&
563                 smb_password_check((char *)id2->lm_chal_resp.buffer,
564                                    smb_pass->smb_passwd,
565                                    id2->lm_chal))
566         {
567                 return 0x0;
568         }
569
570
571         /* oops! neither password check succeeded */
572
573         return 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
574 }
575
576 /*************************************************************************
577  api_net_sam_logon:
578  *************************************************************************/
579 static void api_net_sam_logon( uint16 vuid,
580                                prs_struct *data,
581                                prs_struct *rdata)
582 {
583   NET_Q_SAM_LOGON q_l;
584   NET_ID_INFO_CTR ctr;  
585   NET_USER_INFO_3 usr_info;
586   uint32 status = 0x0;
587   DOM_CRED srv_cred;
588   struct smb_passwd *smb_pass = NULL;
589   UNISTR2 *uni_samlogon_user = NULL;
590
591   user_struct *vuser = NULL;
592
593   if ((vuser = get_valid_user_struct(vuid)) == NULL)
594     return;
595
596   q_l.sam_id.ctr = &ctr;
597
598   net_io_q_sam_logon("", &q_l, data, 0);
599
600   /* checks and updates credentials.  creates reply credentials */
601   if (!deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred), 
602                        &(q_l.sam_id.client.cred), &srv_cred))
603   {
604     status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
605   }
606   else
607   {
608     memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred));
609   }
610
611   /* find the username */
612
613   if (status == 0)
614   {
615     switch (q_l.sam_id.logon_level)
616     {
617       case INTERACTIVE_LOGON_TYPE:
618       {
619         uni_samlogon_user = &(q_l.sam_id.ctr->auth.id1.uni_user_name);
620
621         DEBUG(3,("SAM Logon (Interactive). Domain:[%s].  ", lp_workgroup()));
622         break;
623       }
624       case NET_LOGON_TYPE:
625       {
626         uni_samlogon_user = &(q_l.sam_id.ctr->auth.id2.uni_user_name);
627
628         DEBUG(3,("SAM Logon (Network). Domain:[%s].  ", lp_workgroup()));
629         break;
630       }
631       default:
632       {
633         DEBUG(2,("SAM Logon: unsupported switch value\n"));
634         status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
635         break;
636       }
637     } /* end switch */
638   } /* end if status == 0 */
639
640   /* check username exists */
641
642   if (status == 0)
643   {
644     pstrcpy(samlogon_user, unistrn2(uni_samlogon_user->buffer,
645             uni_samlogon_user->uni_str_len));
646
647     DEBUG(3,("User:[%s]\n", samlogon_user));
648
649     /*
650      * Convert to a UNIX username.
651      */
652     map_username(samlogon_user);
653
654     /*
655      * Do any case conversions.
656      */
657     (void)Get_Pwnam(samlogon_user, True);
658
659     become_root(True);
660     smb_pass = getsmbpwnam(samlogon_user);
661     unbecome_root(True);
662
663     if (smb_pass == NULL)
664       status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
665     else if (smb_pass->acct_ctrl & ACB_DISABLED)
666       status =  0xC0000000 | NT_STATUS_ACCOUNT_DISABLED;
667   }
668
669   /* validate password. */
670
671   if (status == 0)
672   {
673     switch (q_l.sam_id.logon_level)
674     {
675       case INTERACTIVE_LOGON_TYPE:
676       {
677         /* interactive login. */
678         status = net_login_interactive(&q_l.sam_id.ctr->auth.id1, smb_pass, vuser);
679         break;
680       }
681       case NET_LOGON_TYPE:
682       {
683         /* network login.  lm challenge and 24 byte responses */
684         status = net_login_network(&q_l.sam_id.ctr->auth.id2, smb_pass, vuser);
685         break;
686       }
687     }
688   }
689         
690   /* lkclXXXX this is the point at which, if the login was
691      successful, that the SAM Local Security Authority should
692      record that the user is logged in to the domain.
693    */
694
695   /* return the profile plus other bits :-) */
696
697   if (status == 0)
698   {
699     DOM_GID *gids = NULL;
700     int num_gids = 0;
701     NTTIME dummy_time;
702     pstring logon_script;
703     pstring profile_path;
704     pstring home_dir;
705     pstring home_drive;
706     pstring my_name;
707     pstring my_workgroup;
708     pstring domain_groups;
709     uint32 r_uid;
710     uint32 r_gid;
711
712     /* set up pointer indicating user/password failed to be found */
713     usr_info.ptr_user_info = 0;
714
715     dummy_time.low  = 0xffffffff;
716     dummy_time.high = 0x7fffffff;
717
718     /* XXXX hack to get standard_sub_basic() to use sam logon username */
719     /* possibly a better way would be to do a become_user() call */
720     sam_logon_in_ssb = True;
721
722     pstrcpy(logon_script, lp_logon_script());
723     pstrcpy(profile_path, lp_logon_path());
724
725     pstrcpy(my_workgroup, lp_workgroup());
726
727     pstrcpy(home_drive, lp_logon_drive());
728     pstrcpy(home_dir, lp_logon_home());
729
730     pstrcpy(my_name, global_myname);
731     strupper(my_name);
732
733     /*
734      * This is the point at which we get the group
735      * database - we should be getting the gid_t list
736      * from /etc/group and then turning the uids into
737      * rids and then into machine sids for this user.
738      * JRA.
739      */
740
741     get_domain_user_groups(domain_groups, samlogon_user);
742
743     /*
744      * make_dom_gids allocates the gids array. JRA.
745      */
746     gids = NULL;
747     num_gids = make_dom_gids(domain_groups, &gids);
748
749     sam_logon_in_ssb = False;
750
751     if (pdb_name_to_rid(samlogon_user, &r_uid, &r_gid))
752     {
753       make_net_user_info3(&usr_info,
754                           &dummy_time, /* logon_time */
755                           &dummy_time, /* logoff_time */
756                           &dummy_time, /* kickoff_time */
757                           &dummy_time, /* pass_last_set_time */
758                           &dummy_time, /* pass_can_change_time */
759                           &dummy_time, /* pass_must_change_time */
760
761                           samlogon_user   , /* user_name */
762                           vuser->real_name, /* full_name */
763                           logon_script    , /* logon_script */
764                           profile_path    , /* profile_path */
765                           home_dir        , /* home_dir */
766                           home_drive      , /* dir_drive */
767
768                           0, /* logon_count */
769                           0, /* bad_pw_count */
770
771                           r_uid   , /* RID user_id */
772                           r_gid   , /* RID group_id */
773                           num_gids,    /* uint32 num_groups */
774                           gids    , /* DOM_GID *gids */
775                           0x20    , /* uint32 user_flgs (?) */
776
777                           NULL, /* char sess_key[16] */
778
779                           my_name     , /* char *logon_srv */
780                           my_workgroup, /* char *logon_dom */
781
782                           &global_machine_sid,     /* DOM_SID *dom_sid */
783                           NULL); /* char *other_sids */
784     }
785     else
786     {
787       status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
788     }
789
790     /* Free any allocated groups array. */
791     if(gids)
792       free((char *)gids);
793   }
794
795   net_reply_sam_logon(&q_l, rdata, &srv_cred, &usr_info, status);
796 }
797
798
799 /*************************************************************************
800  api_net_trust_dom_list:
801  *************************************************************************/
802 static void api_net_trust_dom_list( uint16 vuid,
803                                  prs_struct *data,
804                                  prs_struct *rdata)
805 {
806         NET_Q_TRUST_DOM_LIST q_t;
807
808         char *trusted_domain = "test_domain";
809
810         DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
811
812         /* grab the lsa trusted domain list query... */
813         net_io_q_trust_dom("", &q_t, data, 0);
814
815         /* construct reply. */
816         net_reply_trust_dom_list(&q_t, rdata,
817                                 1, trusted_domain);
818
819         DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
820 }
821
822
823 /*************************************************************************
824  error messages cropping up when using nltest.exe...
825  *************************************************************************/
826 #define ERROR_NO_SUCH_DOMAIN   0x54b
827 #define ERROR_NO_LOGON_SERVERS 0x51f
828
829 /*************************************************************************
830  api_net_logon_ctrl2:
831  *************************************************************************/
832 static void api_net_logon_ctrl2( uint16 vuid,
833                                  prs_struct *data,
834                                  prs_struct *rdata)
835 {
836         NET_Q_LOGON_CTRL2 q_l;
837
838         /* lkclXXXX - guess what - absolutely no idea what these are! */
839         uint32 flags = 0x0;
840         uint32 pdc_connection_status = 0x0;
841         uint32 logon_attempts = 0x0;
842         uint32 tc_status = ERROR_NO_LOGON_SERVERS;
843         char *trusted_domain = "test_domain";
844
845         DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
846
847         /* grab the lsa netlogon ctrl2 query... */
848         net_io_q_logon_ctrl2("", &q_l, data, 0);
849
850         /* construct reply. */
851         net_reply_logon_ctrl2(&q_l, rdata,
852                                 flags, pdc_connection_status, logon_attempts,
853                                 tc_status, trusted_domain);
854
855         DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
856 }
857
858 /*******************************************************************
859  array of \PIPE\NETLOGON operations
860  ********************************************************************/
861 static struct api_struct api_net_cmds [] =
862 {
863         { "NET_REQCHAL"       , NET_REQCHAL       , api_net_req_chal       }, 
864         { "NET_AUTH2"         , NET_AUTH2         , api_net_auth_2         }, 
865         { "NET_SRVPWSET"      , NET_SRVPWSET      , api_net_srv_pwset      }, 
866         { "NET_SAMLOGON"      , NET_SAMLOGON      , api_net_sam_logon      }, 
867         { "NET_SAMLOGOFF"     , NET_SAMLOGOFF     , api_net_sam_logoff     }, 
868         { "NET_LOGON_CTRL2"   , NET_LOGON_CTRL2   , api_net_logon_ctrl2    }, 
869         { "NET_TRUST_DOM_LIST", NET_TRUST_DOM_LIST, api_net_trust_dom_list },
870     {  NULL               , 0                 , NULL                   }
871 };
872
873 /*******************************************************************
874  receives a netlogon pipe and responds.
875  ********************************************************************/
876 BOOL api_netlog_rpc(pipes_struct *p, prs_struct *data)
877 {
878         return api_rpcTNP(p, "api_netlog_rpc", api_net_cmds, data);
879 }