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