de3eaf9bd9c591972a370e97f4bd4e4174af4947
[kai/samba.git] / source / 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_sam_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         NEG_FLAGS srv_flgs;
130
131         srv_flgs.neg_flags = 0x000001ff;
132
133         /* set up the LSA AUTH 2 response */
134
135         make_net_r_auth_2(&r_a, resp_cred, &srv_flgs, status);
136
137         /* store the response in the SMB stream */
138         net_io_r_auth_2("", &r_a, rdata, 0);
139
140 }
141
142 /***********************************************************************************
143  make_net_r_srv_pwset:
144  ***********************************************************************************/
145 static void make_net_r_srv_pwset(NET_R_SRV_PWSET *r_s,
146                              DOM_CRED *srv_cred, int status)  
147 {
148         DEBUG(5,("make_net_r_srv_pwset: %d\n", __LINE__));
149
150         memcpy(&(r_s->srv_cred), srv_cred, sizeof(r_s->srv_cred));
151         r_s->status = status;
152
153         DEBUG(5,("make_net_r_srv_pwset: %d\n", __LINE__));
154 }
155
156 /*************************************************************************
157  net_reply_srv_pwset:
158  *************************************************************************/
159 static void net_reply_srv_pwset(NET_Q_SRV_PWSET *q_s, prs_struct *rdata,
160                                 DOM_CRED *srv_cred, int status)
161 {
162         NET_R_SRV_PWSET r_s;
163
164         DEBUG(5,("net_srv_pwset: %d\n", __LINE__));
165
166         /* set up the LSA Server Password Set response */
167         make_net_r_srv_pwset(&r_s, srv_cred, status);
168
169         /* store the response in the SMB stream */
170         net_io_r_srv_pwset("", &r_s, rdata, 0);
171
172         DEBUG(5,("net_srv_pwset: %d\n", __LINE__));
173
174 }
175
176 /*************************************************************************
177  net_reply_sam_logon:
178  *************************************************************************/
179 static void net_reply_sam_logon(NET_Q_SAM_LOGON *q_s, prs_struct *rdata,
180                                 DOM_CRED *srv_cred, NET_USER_INFO_3 *user_info,
181                                 uint32 status)
182 {
183         NET_R_SAM_LOGON r_s;
184
185         /* XXXX maybe we want to say 'no', reject the client's credentials */
186         r_s.buffer_creds = 1; /* yes, we have valid server credentials */
187         memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds));
188
189         /* store the user information, if there is any. */
190         r_s.user = user_info;
191         if (status == 0x0 && user_info != NULL && user_info->ptr_user_info != 0)
192         {
193                 r_s.switch_value = 3; /* indicates type of validation user info */
194         }
195         else
196         {
197                 r_s.switch_value = 0; /* indicates no info */
198         }
199
200         r_s.status = status;
201         r_s.auth_resp = 1; /* authoritative response */
202
203         /* store the response in the SMB stream */
204         net_io_r_sam_logon("", &r_s, rdata, 0);
205
206 }
207
208
209 /*************************************************************************
210  net_reply_sam_logoff:
211  *************************************************************************/
212 static void net_reply_sam_logoff(NET_Q_SAM_LOGOFF *q_s, prs_struct *rdata,
213                                 DOM_CRED *srv_cred, 
214                                 uint32 status)
215 {
216         NET_R_SAM_LOGOFF r_s;
217
218         /* XXXX maybe we want to say 'no', reject the client's credentials */
219         r_s.buffer_creds = 1; /* yes, we have valid server credentials */
220         memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds));
221
222         r_s.status = status;
223
224         /* store the response in the SMB stream */
225         net_io_r_sam_logoff("", &r_s, rdata, 0);
226
227 }
228
229 /******************************************************************
230  gets a machine password entry.  checks access rights of the host.
231  ******************************************************************/
232 static BOOL get_md4pw(char *md4pw, char *mach_name, char *mach_acct)
233 {
234         struct smb_passwd *smb_pass;
235
236 #if 0
237     /*
238      * Currently this code is redundent as we already have a filter
239      * by hostname list. What this code really needs to do is to 
240      * get a hosts allowed/hosts denied list from the SAM database
241      * on a per user basis, and make the access decision there.
242      * I will leave this code here for now as a reminder to implement
243      * this at a later date. JRA.
244      */
245
246         if (!allow_access(lp_domain_hostsdeny(), lp_domain_hostsallow(),
247                           client_name(Client), client_addr(Client)))
248         {
249                 DEBUG(0,("get_md4pw: Workstation %s denied access to domain\n", mach_acct));
250                 return False;
251         }
252 #endif /* 0 */
253
254         become_root(True);
255         smb_pass = getsmbpwnam(mach_acct);
256         unbecome_root(True);
257
258         if ((smb_pass) != NULL && !(smb_pass->acct_ctrl & ACB_DISABLED) &&
259         (smb_pass->smb_nt_passwd != NULL))
260         {
261                 memcpy(md4pw, smb_pass->smb_nt_passwd, 16);
262                 dump_data(5, md4pw, 16);
263
264                 return True;
265         }
266         DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct));
267         return False;
268 }
269
270 /*************************************************************************
271  api_net_req_chal:
272  *************************************************************************/
273 static void api_net_req_chal( uint16 vuid,
274                               prs_struct *data,
275                               prs_struct *rdata)
276 {
277         NET_Q_REQ_CHAL q_r;
278         uint32 status = 0x0;
279
280         fstring mach_acct;
281         fstring mach_name;
282
283         user_struct *vuser;
284
285         DEBUG(5,("api_net_req_chal(%d): vuid %d\n", __LINE__, (int)vuid));
286
287         if ((vuser = get_valid_user_struct(vuid)) == NULL)
288       return;
289
290         /* grab the challenge... */
291         net_io_q_req_chal("", &q_r, data, 0);
292
293         fstrcpy(mach_acct, unistrn2(q_r.uni_logon_clnt.buffer,
294                                     q_r.uni_logon_clnt.uni_str_len));
295
296         fstrcpy(mach_name, mach_acct);
297         strlower(mach_name);
298
299         fstrcat(mach_acct, "$");
300
301         if (get_md4pw((char *)vuser->dc.md4pw, mach_name, mach_acct))
302         {
303                 /* copy the client credentials */
304                 memcpy(vuser->dc.clnt_chal.data          , q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data));
305                 memcpy(vuser->dc.clnt_cred.challenge.data, q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data));
306
307                 /* create a server challenge for the client */
308                 /* Set these to random values. */
309                 generate_random_buffer(vuser->dc.srv_chal.data, 8, False);
310
311                 memcpy(vuser->dc.srv_cred.challenge.data, vuser->dc.srv_chal.data, 8);
312
313                 bzero(vuser->dc.sess_key, sizeof(vuser->dc.sess_key));
314
315                 /* from client / server challenges and md4 password, generate sess key */
316                 cred_session_key(&(vuser->dc.clnt_chal), &(vuser->dc.srv_chal),
317                                  (char *)vuser->dc.md4pw, vuser->dc.sess_key);
318         }
319         else
320         {
321                 /* lkclXXXX take a guess at a good error message to return :-) */
322                 status = 0xC0000000 | NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT;
323         }
324
325         /* construct reply. */
326         net_reply_req_chal(&q_r, rdata,
327                                         &(vuser->dc.srv_chal), status);
328
329 }
330
331 /*************************************************************************
332  api_net_auth_2:
333  *************************************************************************/
334 static void api_net_auth_2( uint16 vuid,
335                             prs_struct *data,
336                             prs_struct *rdata)
337 {
338         NET_Q_AUTH_2 q_a;
339         uint32 status = 0x0;
340
341         DOM_CHAL srv_cred;
342         UTIME srv_time;
343
344         user_struct *vuser;
345
346         if ((vuser = get_valid_user_struct(vuid)) == NULL)
347       return;
348
349         srv_time.time = 0;
350
351         /* grab the challenge... */
352         net_io_q_auth_2("", &q_a, data, 0);
353
354         /* check that the client credentials are valid */
355         if (cred_assert(&(q_a.clnt_chal), vuser->dc.sess_key,
356                     &(vuser->dc.clnt_cred.challenge), srv_time))
357         {
358
359                 /* create server challenge for inclusion in the reply */
360                 cred_create(vuser->dc.sess_key, &(vuser->dc.srv_cred.challenge), srv_time, &srv_cred);
361
362                 /* copy the received client credentials for use next time */
363                 memcpy(vuser->dc.clnt_cred.challenge.data, q_a.clnt_chal.data, sizeof(q_a.clnt_chal.data));
364                 memcpy(vuser->dc.srv_cred .challenge.data, q_a.clnt_chal.data, sizeof(q_a.clnt_chal.data));
365         }
366         else
367         {
368                 status = NT_STATUS_ACCESS_DENIED | 0xC0000000;
369         }
370
371         /* construct reply. */
372         net_reply_auth_2(&q_a, rdata, &srv_cred, status);
373 }
374
375
376 /*************************************************************************
377  api_net_srv_pwset:
378  *************************************************************************/
379 static void api_net_srv_pwset( uint16 vuid,
380                                prs_struct *data,
381                                prs_struct *rdata)
382 {
383         NET_Q_SRV_PWSET q_a;
384         uint32 status = NT_STATUS_WRONG_PASSWORD|0xC0000000;
385         DOM_CRED srv_cred;
386         pstring mach_acct;
387         struct smb_passwd *smb_pass;
388         BOOL ret;
389         user_struct *vuser;
390
391         if ((vuser = get_valid_user_struct(vuid)) == NULL)
392       return;
393
394         /* grab the challenge and encrypted password ... */
395         net_io_q_srv_pwset("", &q_a, data, 0);
396
397         /* checks and updates credentials.  creates reply credentials */
398         if (deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred), 
399                             &(q_a.clnt_id.cred), &srv_cred))
400         {
401                 memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred));
402
403                 DEBUG(5,("api_net_srv_pwset: %d\n", __LINE__));
404
405                 pstrcpy(mach_acct, unistrn2(q_a.clnt_id.login.uni_acct_name.buffer,
406                                             q_a.clnt_id.login.uni_acct_name.uni_str_len));
407
408                 DEBUG(3,("Server Password Set Wksta:[%s]\n", mach_acct));
409
410                 become_root(True);
411                 smb_pass = getsmbpwnam(mach_acct);
412                 unbecome_root(True);
413
414                 if (smb_pass != NULL)
415                 {
416                         unsigned char pwd[16];
417                         int i;
418
419                         DEBUG(100,("Server password set : new given value was :\n"));
420                         for(i = 0; i < 16; i++)
421                         {
422                                 DEBUG(100,("%02X ", q_a.pwd[i]));
423                         }
424                         DEBUG(100,("\n"));
425
426                         cred_hash3( pwd, q_a.pwd, vuser->dc.sess_key, 0);
427
428                         /* lies!  nt and lm passwords are _not_ the same: don't care */
429                         smb_pass->smb_passwd    = pwd;
430                         smb_pass->smb_nt_passwd = pwd;
431                         smb_pass->acct_ctrl     = ACB_WSTRUST;
432
433                         become_root(True);
434                         ret = mod_smbpwd_entry(smb_pass,False);
435                         unbecome_root(True);
436
437                         if (ret)
438                         {
439                                 /* hooray! */
440                                 status = 0x0;
441                         }
442                 }
443
444                 DEBUG(5,("api_net_srv_pwset: %d\n", __LINE__));
445
446         }
447         else
448         {
449                 /* lkclXXXX take a guess at a sensible error code to return... */
450                 status = 0xC0000000 | NT_STATUS_NETWORK_CREDENTIAL_CONFLICT;
451         }
452
453         /* Construct reply. */
454         net_reply_srv_pwset(&q_a, rdata, &srv_cred, status);
455 }
456
457
458 /*************************************************************************
459  api_net_sam_logoff:
460  *************************************************************************/
461 static void api_net_sam_logoff( uint16 vuid,
462                                prs_struct *data,
463                                prs_struct *rdata)
464 {
465         NET_Q_SAM_LOGOFF q_l;
466         NET_ID_INFO_CTR ctr;    
467
468         DOM_CRED srv_cred;
469
470         user_struct *vuser;
471
472         if ((vuser = get_valid_user_struct(vuid)) == NULL)
473       return;
474
475         /* the DOM_ID_INFO_1 structure is a bit big.  plus we might want to
476            dynamically allocate it inside net_io_q_sam_logon, at some point */
477         q_l.sam_id.ctr = &ctr;
478
479         /* grab the challenge... */
480         net_io_q_sam_logoff("", &q_l, data, 0);
481
482         /* checks and updates credentials.  creates reply credentials */
483         deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred), 
484                         &(q_l.sam_id.client.cred), &srv_cred);
485         memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred));
486
487         /* construct reply.  always indicate success */
488         net_reply_sam_logoff(&q_l, rdata,
489                                         &srv_cred,
490                         0x0);
491 }
492
493 /*************************************************************************
494  net_login_interactive:
495  *************************************************************************/
496 static uint32 net_login_interactive(NET_ID_INFO_1 *id1,
497                                 struct smb_passwd *smb_pass,
498                                 user_struct *vuser)
499 {
500         uint32 status = 0x0;
501
502         char nt_pwd[16];
503         char lm_pwd[16];
504         unsigned char key[16];
505
506         memset(key, 0, 16);
507         memcpy(key, vuser->dc.sess_key, 8);
508
509         memcpy(lm_pwd, id1->lm_owf.data, 16);
510         memcpy(nt_pwd, id1->nt_owf.data, 16);
511
512 #ifdef DEBUG_PASSWORD
513         DEBUG(100,("key:"));
514         dump_data(100, key, 16);
515
516         DEBUG(100,("lm owf password:"));
517         dump_data(100, lm_pwd, 16);
518
519         DEBUG(100,("nt owf password:"));
520         dump_data(100, nt_pwd, 16);
521 #endif
522
523         SamOEMhash((uchar *)lm_pwd, key, False);
524         SamOEMhash((uchar *)nt_pwd, key, False);
525
526 #ifdef DEBUG_PASSWORD
527         DEBUG(100,("decrypt of lm owf password:"));
528         dump_data(100, lm_pwd, 16);
529
530         DEBUG(100,("decrypt of nt owf password:"));
531         dump_data(100, nt_pwd, 16);
532 #endif
533
534         if (memcmp(smb_pass->smb_passwd   , lm_pwd, 16) != 0 &&
535             memcmp(smb_pass->smb_nt_passwd, nt_pwd, 16) != 0)
536         {
537                 status = 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
538         }
539
540         return status;
541 }
542
543 /*************************************************************************
544  net_login_network:
545  *************************************************************************/
546 static uint32 net_login_network(NET_ID_INFO_2 *id2,
547                                 struct smb_passwd *smb_pass,
548                                 user_struct *vuser)
549 {
550         DEBUG(5,("net_login_network: lm_len: %d nt_len: %d\n",
551                 id2->hdr_lm_chal_resp.str_str_len, 
552                 id2->hdr_nt_chal_resp.str_str_len));
553
554         /* JRA. Check the NT password first if it exists - this is a higher quality 
555            password, if it exists and it doesn't match - fail. */
556
557         if (id2->hdr_nt_chal_resp.str_str_len == 24 && 
558                 smb_pass->smb_nt_passwd != NULL)
559         {
560                 if(smb_password_check((char *)id2->nt_chal_resp.buffer,
561                                    smb_pass->smb_nt_passwd,
562                            id2->lm_chal)) 
563                   return 0x0;
564                 else
565                   return 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
566         }
567
568         /* lkclXXXX this is not a good place to put disabling of LM hashes in.
569            if that is to be done, first move this entire function into a
570            library routine that calls the two smb_password_check() functions.
571            if disabling LM hashes (which nt can do for security reasons) then
572            an attempt should be made to disable them everywhere (which nt does
573            not do, for various security-hole reasons).
574          */
575
576         if (id2->hdr_lm_chal_resp.str_str_len == 24 &&
577                 smb_password_check((char *)id2->lm_chal_resp.buffer,
578                                    smb_pass->smb_passwd,
579                                    id2->lm_chal))
580         {
581                 return 0x0;
582         }
583
584
585         /* oops! neither password check succeeded */
586
587         return 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
588 }
589
590 /*************************************************************************
591  api_net_sam_logon:
592  *************************************************************************/
593 static void api_net_sam_logon( uint16 vuid,
594                                prs_struct *data,
595                                prs_struct *rdata)
596 {
597   NET_Q_SAM_LOGON q_l;
598   NET_ID_INFO_CTR ctr;  
599   NET_USER_INFO_3 usr_info;
600   uint32 status = 0x0;
601   DOM_CRED srv_cred;
602   struct smb_passwd *smb_pass = NULL;
603   UNISTR2 *uni_samlogon_user = NULL;
604
605   user_struct *vuser = NULL;
606
607   if ((vuser = get_valid_user_struct(vuid)) == NULL)
608     return;
609
610   q_l.sam_id.ctr = &ctr;
611
612   net_io_q_sam_logon("", &q_l, data, 0);
613
614   /* checks and updates credentials.  creates reply credentials */
615   if (!deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred), 
616                        &(q_l.sam_id.client.cred), &srv_cred))
617   {
618     status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
619   }
620   else
621   {
622     memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred));
623   }
624
625   /* find the username */
626
627   if (status == 0)
628   {
629     switch (q_l.sam_id.logon_level)
630     {
631       case INTERACTIVE_LOGON_TYPE:
632       {
633         uni_samlogon_user = &(q_l.sam_id.ctr->auth.id1.uni_user_name);
634
635         DEBUG(3,("SAM Logon (Interactive). Domain:[%s].  ", lp_workgroup()));
636         break;
637       }
638       case NET_LOGON_TYPE:
639       {
640         uni_samlogon_user = &(q_l.sam_id.ctr->auth.id2.uni_user_name);
641
642         DEBUG(3,("SAM Logon (Network). Domain:[%s].  ", lp_workgroup()));
643         break;
644       }
645       default:
646       {
647         DEBUG(2,("SAM Logon: unsupported switch value\n"));
648         status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
649         break;
650       }
651     } /* end switch */
652   } /* end if status == 0 */
653
654   /* check username exists */
655
656   if (status == 0)
657   {
658     pstrcpy(samlogon_user, unistrn2(uni_samlogon_user->buffer,
659             uni_samlogon_user->uni_str_len));
660
661     DEBUG(3,("User:[%s]\n", samlogon_user));
662
663     /*
664      * Convert to a UNIX username.
665      */
666     map_username(samlogon_user);
667
668     /*
669      * Do any case conversions.
670      */
671     (void)Get_Pwnam(samlogon_user, True);
672
673     become_root(True);
674     smb_pass = getsmbpwnam(samlogon_user);
675     unbecome_root(True);
676
677     if (smb_pass == NULL)
678       status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
679     else if (smb_pass->acct_ctrl & ACB_DISABLED)
680       status =  0xC0000000 | NT_STATUS_ACCOUNT_DISABLED;
681   }
682
683   /* validate password. */
684
685   if (status == 0)
686   {
687     switch (q_l.sam_id.logon_level)
688     {
689       case INTERACTIVE_LOGON_TYPE:
690       {
691         /* interactive login. */
692         status = net_login_interactive(&q_l.sam_id.ctr->auth.id1, smb_pass, vuser);
693         break;
694       }
695       case NET_LOGON_TYPE:
696       {
697         /* network login.  lm challenge and 24 byte responses */
698         status = net_login_network(&q_l.sam_id.ctr->auth.id2, smb_pass, vuser);
699         break;
700       }
701     }
702   }
703         
704   /* lkclXXXX this is the point at which, if the login was
705      successful, that the SAM Local Security Authority should
706      record that the user is logged in to the domain.
707    */
708
709   /* return the profile plus other bits :-) */
710
711   if (status == 0)
712   {
713     DOM_GID *gids = NULL;
714     int num_gids = 0;
715     NTTIME dummy_time;
716     pstring logon_script;
717     pstring profile_path;
718     pstring home_dir;
719     pstring home_drive;
720     pstring my_name;
721     pstring my_workgroup;
722     pstring domain_groups;
723     uint32 r_uid;
724     uint32 r_gid;
725
726     /* set up pointer indicating user/password failed to be found */
727     usr_info.ptr_user_info = 0;
728
729     dummy_time.low  = 0xffffffff;
730     dummy_time.high = 0x7fffffff;
731
732     /* XXXX hack to get standard_sub_basic() to use sam logon username */
733     /* possibly a better way would be to do a become_user() call */
734     sam_logon_in_ssb = True;
735
736     pstrcpy(logon_script, lp_logon_script());
737     pstrcpy(profile_path, lp_logon_path());
738
739     pstrcpy(my_workgroup, lp_workgroup());
740
741     pstrcpy(home_drive, lp_logon_drive());
742     pstrcpy(home_dir, lp_logon_home());
743
744     pstrcpy(my_name, global_myname);
745     strupper(my_name);
746
747     /*
748      * This is the point at which we get the group
749      * database - we should be getting the gid_t list
750      * from /etc/group and then turning the uids into
751      * rids and then into machine sids for this user.
752      * JRA.
753      */
754
755     get_domain_user_groups(domain_groups, samlogon_user);
756
757     /*
758      * make_dom_gids allocates the gids array. JRA.
759      */
760     gids = NULL;
761     num_gids = make_dom_gids(domain_groups, &gids);
762
763     sam_logon_in_ssb = False;
764
765     if (pdb_name_to_rid(samlogon_user, &r_uid, &r_gid))
766     {
767       make_net_user_info3(&usr_info,
768                           &dummy_time, /* logon_time */
769                           &dummy_time, /* logoff_time */
770                           &dummy_time, /* kickoff_time */
771                           &dummy_time, /* pass_last_set_time */
772                           &dummy_time, /* pass_can_change_time */
773                           &dummy_time, /* pass_must_change_time */
774
775                           samlogon_user   , /* user_name */
776                           vuser->real_name, /* full_name */
777                           logon_script    , /* logon_script */
778                           profile_path    , /* profile_path */
779                           home_dir        , /* home_dir */
780                           home_drive      , /* dir_drive */
781
782                           0, /* logon_count */
783                           0, /* bad_pw_count */
784
785                           r_uid   , /* RID user_id */
786                           r_gid   , /* RID group_id */
787                           num_gids,    /* uint32 num_groups */
788                           gids    , /* DOM_GID *gids */
789                           0x20    , /* uint32 user_flgs (?) */
790
791                           NULL, /* char sess_key[16] */
792
793                           my_name     , /* char *logon_srv */
794                           my_workgroup, /* char *logon_dom */
795
796                           &global_sam_sid,     /* DOM_SID *dom_sid */
797                           NULL); /* char *other_sids */
798     }
799     else
800     {
801       status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
802     }
803
804     /* Free any allocated groups array. */
805     if(gids)
806       free((char *)gids);
807   }
808
809   net_reply_sam_logon(&q_l, rdata, &srv_cred, &usr_info, status);
810 }
811
812
813 /*************************************************************************
814  api_net_trust_dom_list:
815  *************************************************************************/
816 static void api_net_trust_dom_list( uint16 vuid,
817                                  prs_struct *data,
818                                  prs_struct *rdata)
819 {
820         NET_Q_TRUST_DOM_LIST q_t;
821
822         char *trusted_domain = "test_domain";
823
824         DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
825
826         /* grab the lsa trusted domain list query... */
827         net_io_q_trust_dom("", &q_t, data, 0);
828
829         /* construct reply. */
830         net_reply_trust_dom_list(&q_t, rdata,
831                                 1, trusted_domain);
832
833         DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
834 }
835
836
837 /*************************************************************************
838  error messages cropping up when using nltest.exe...
839  *************************************************************************/
840 #define ERROR_NO_SUCH_DOMAIN   0x54b
841 #define ERROR_NO_LOGON_SERVERS 0x51f
842
843 /*************************************************************************
844  api_net_logon_ctrl2:
845  *************************************************************************/
846 static void api_net_logon_ctrl2( uint16 vuid,
847                                  prs_struct *data,
848                                  prs_struct *rdata)
849 {
850         NET_Q_LOGON_CTRL2 q_l;
851
852         /* lkclXXXX - guess what - absolutely no idea what these are! */
853         uint32 flags = 0x0;
854         uint32 pdc_connection_status = 0x0;
855         uint32 logon_attempts = 0x0;
856         uint32 tc_status = ERROR_NO_LOGON_SERVERS;
857         char *trusted_domain = "test_domain";
858
859         DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
860
861         /* grab the lsa netlogon ctrl2 query... */
862         net_io_q_logon_ctrl2("", &q_l, data, 0);
863
864         /* construct reply. */
865         net_reply_logon_ctrl2(&q_l, rdata,
866                                 flags, pdc_connection_status, logon_attempts,
867                                 tc_status, trusted_domain);
868
869         DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
870 }
871
872 /*******************************************************************
873  array of \PIPE\NETLOGON operations
874  ********************************************************************/
875 static struct api_struct api_net_cmds [] =
876 {
877         { "NET_REQCHAL"       , NET_REQCHAL       , api_net_req_chal       }, 
878         { "NET_AUTH2"         , NET_AUTH2         , api_net_auth_2         }, 
879         { "NET_SRVPWSET"      , NET_SRVPWSET      , api_net_srv_pwset      }, 
880         { "NET_SAMLOGON"      , NET_SAMLOGON      , api_net_sam_logon      }, 
881         { "NET_SAMLOGOFF"     , NET_SAMLOGOFF     , api_net_sam_logoff     }, 
882         { "NET_LOGON_CTRL2"   , NET_LOGON_CTRL2   , api_net_logon_ctrl2    }, 
883         { "NET_TRUST_DOM_LIST", NET_TRUST_DOM_LIST, api_net_trust_dom_list },
884     {  NULL               , 0                 , NULL                   }
885 };
886
887 /*******************************************************************
888  receives a netlogon pipe and responds.
889  ********************************************************************/
890 BOOL api_netlog_rpc(pipes_struct *p, prs_struct *data)
891 {
892         return api_rpcTNP(p, "api_netlog_rpc", api_net_cmds, data);
893 }