9fa3ed79cc106303fe84cd72907718f4d764121a
[samba.git] / source / rpc_server / srv_netlog.c
1 /* 
2  *  Unix SMB/Netbios implementation.
3  *  Version 1.9.
4  *  RPC Pipe client / server routines
5  *  Copyright (C) Andrew Tridgell              1992-1997,
6  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
7  *  Copyright (C) Paul Ashton                       1997.
8  *  Copyright (C) Jeremy Allison                    1998.
9  *
10  *  This program is free software; you can redistribute it and/or modify
11  *  it under the terms of the GNU General Public License as published by
12  *  the Free Software Foundation; either version 2 of the License, or
13  *  (at your option) any later version.
14  *  
15  *  This program is distributed in the hope that it will be useful,
16  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  *  GNU General Public License for more details.
19  *  
20  *  You should have received a copy of the GNU General Public License
21  *  along with this program; if not, write to the Free Software
22  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23  */
24
25
26 #include "includes.h"
27 #include "nterr.h"
28
29 extern int DEBUGLEVEL;
30
31 extern BOOL sam_logon_in_ssb;
32 extern pstring samlogon_user;
33 extern pstring global_myname;
34 extern DOM_SID global_sam_sid;
35
36 /*************************************************************************
37  make_net_r_req_chal:
38  *************************************************************************/
39 static void make_net_r_req_chal(NET_R_REQ_CHAL *r_c,
40                                 DOM_CHAL *srv_chal, int status)
41 {
42         DEBUG(6,("make_net_r_req_chal: %d\n", __LINE__));
43         memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(srv_chal->data));
44         r_c->status = status;
45 }
46
47 /*************************************************************************
48  net_reply_req_chal:
49  *************************************************************************/
50 static void net_reply_req_chal(NET_Q_REQ_CHAL *q_c, prs_struct *rdata,
51                                         DOM_CHAL *srv_chal, uint32 srv_time)
52 {
53         NET_R_REQ_CHAL r_c;
54
55         DEBUG(6,("net_reply_req_chal: %d\n", __LINE__));
56
57         /* set up the LSA REQUEST CHALLENGE response */
58         make_net_r_req_chal(&r_c, srv_chal, srv_time);
59
60         /* store the response in the SMB stream */
61         net_io_r_req_chal("", &r_c, rdata, 0);
62
63         DEBUG(6,("net_reply_req_chal: %d\n", __LINE__));
64
65 }
66
67 /*************************************************************************
68  net_reply_logon_ctrl2:
69  *************************************************************************/
70 static void net_reply_logon_ctrl2(NET_Q_LOGON_CTRL2 *q_l, prs_struct *rdata,
71                         uint32 flags, uint32 pdc_status, uint32 logon_attempts,
72                         uint32 tc_status, char *trust_domain_name)
73 {
74         NET_R_LOGON_CTRL2 r_l;
75
76         DEBUG(6,("net_reply_logon_ctrl2: %d\n", __LINE__));
77
78         /* set up the Logon Control2 response */
79         make_r_logon_ctrl2(&r_l, q_l->query_level,
80                            flags, pdc_status, logon_attempts,
81                            tc_status, trust_domain_name);
82
83         /* store the response in the SMB stream */
84         net_io_r_logon_ctrl2("", &r_l, rdata, 0);
85
86         DEBUG(6,("net_reply_logon_ctrl2: %d\n", __LINE__));
87
88 }
89
90 /*************************************************************************
91  net_reply_trust_dom_list:
92  *************************************************************************/
93 static void net_reply_trust_dom_list(NET_Q_TRUST_DOM_LIST *q_t, prs_struct *rdata,
94                         uint32 num_trust_domains, char *trust_domain_name)
95 {
96         NET_R_TRUST_DOM_LIST r_t;
97
98         DEBUG(6,("net_reply_trust_dom_list: %d\n", __LINE__));
99
100         /* set up the Trusted Domain List response */
101         make_r_trust_dom(&r_t, num_trust_domains, trust_domain_name);
102
103         /* store the response in the SMB stream */
104         net_io_r_trust_dom("", &r_t, rdata, 0);
105
106         DEBUG(6,("net_reply_trust_dom_listlogon_ctrl2: %d\n", __LINE__));
107
108 }
109
110 /*************************************************************************
111  make_net_r_auth_2:
112  *************************************************************************/
113 static void make_net_r_auth_2(NET_R_AUTH_2 *r_a,
114                               DOM_CHAL *resp_cred, NEG_FLAGS *flgs, int status)
115 {
116         memcpy(  r_a->srv_chal.data, resp_cred->data, sizeof(resp_cred->data));
117         memcpy(&(r_a->srv_flgs)    , flgs           , sizeof(r_a->srv_flgs));
118         r_a->status = status;
119 }
120
121 /*************************************************************************
122  net_reply_auth_2:
123  *************************************************************************/
124 static void net_reply_auth_2(NET_Q_AUTH_2 *q_a, prs_struct *rdata,
125                                 DOM_CHAL *resp_cred, int status)
126 {
127         NET_R_AUTH_2 r_a;
128         NEG_FLAGS srv_flgs;
129
130         srv_flgs.neg_flags = 0x000001ff;
131
132         /* set up the LSA AUTH 2 response */
133
134         make_net_r_auth_2(&r_a, resp_cred, &srv_flgs, status);
135
136         /* store the response in the SMB stream */
137         net_io_r_auth_2("", &r_a, rdata, 0);
138
139 }
140
141 /***********************************************************************************
142  make_net_r_srv_pwset:
143  ***********************************************************************************/
144 static void make_net_r_srv_pwset(NET_R_SRV_PWSET *r_s,
145                              DOM_CRED *srv_cred, int status)  
146 {
147         DEBUG(5,("make_net_r_srv_pwset: %d\n", __LINE__));
148
149         memcpy(&(r_s->srv_cred), srv_cred, sizeof(r_s->srv_cred));
150         r_s->status = status;
151
152         DEBUG(5,("make_net_r_srv_pwset: %d\n", __LINE__));
153 }
154
155 /*************************************************************************
156  net_reply_srv_pwset:
157  *************************************************************************/
158 static void net_reply_srv_pwset(NET_Q_SRV_PWSET *q_s, prs_struct *rdata,
159                                 DOM_CRED *srv_cred, int status)
160 {
161         NET_R_SRV_PWSET r_s;
162
163         DEBUG(5,("net_srv_pwset: %d\n", __LINE__));
164
165         /* set up the LSA Server Password Set response */
166         make_net_r_srv_pwset(&r_s, srv_cred, status);
167
168         /* store the response in the SMB stream */
169         net_io_r_srv_pwset("", &r_s, rdata, 0);
170
171         DEBUG(5,("net_srv_pwset: %d\n", __LINE__));
172
173 }
174
175 /*************************************************************************
176  net_reply_sam_logon:
177  *************************************************************************/
178 static void net_reply_sam_logon(NET_Q_SAM_LOGON *q_s, prs_struct *rdata,
179                                 DOM_CRED *srv_cred, NET_USER_INFO_3 *user_info,
180                                 uint32 status)
181 {
182         NET_R_SAM_LOGON r_s;
183
184         /* XXXX maybe we want to say 'no', reject the client's credentials */
185         r_s.buffer_creds = 1; /* yes, we have valid server credentials */
186         memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds));
187
188         /* store the user information, if there is any. */
189         r_s.user = user_info;
190         if (status == 0x0 && user_info != NULL && user_info->ptr_user_info != 0)
191         {
192                 r_s.switch_value = 3; /* indicates type of validation user info */
193         }
194         else
195         {
196                 r_s.switch_value = 0; /* indicates no info */
197         }
198
199         r_s.status = status;
200         r_s.auth_resp = 1; /* authoritative response */
201
202         /* store the response in the SMB stream */
203         net_io_r_sam_logon("", &r_s, rdata, 0);
204
205 }
206
207
208 /*************************************************************************
209  net_reply_sam_logoff:
210  *************************************************************************/
211 static void net_reply_sam_logoff(NET_Q_SAM_LOGOFF *q_s, prs_struct *rdata,
212                                 DOM_CRED *srv_cred, 
213                                 uint32 status)
214 {
215         NET_R_SAM_LOGOFF r_s;
216
217         /* XXXX maybe we want to say 'no', reject the client's credentials */
218         r_s.buffer_creds = 1; /* yes, we have valid server credentials */
219         memcpy(&(r_s.srv_creds), srv_cred, sizeof(r_s.srv_creds));
220
221         r_s.status = status;
222
223         /* store the response in the SMB stream */
224         net_io_r_sam_logoff("", &r_s, rdata, 0);
225
226 }
227
228 /******************************************************************
229  gets a machine password entry.  checks access rights of the host.
230  ******************************************************************/
231 static BOOL get_md4pw(char *md4pw, char *mach_name, char *mach_acct)
232 {
233         struct smb_passwd *smb_pass;
234
235 #if 0
236     /*
237      * Currently this code is redundent as we already have a filter
238      * by hostname list. What this code really needs to do is to 
239      * get a hosts allowed/hosts denied list from the SAM database
240      * on a per user basis, and make the access decision there.
241      * I will leave this code here for now as a reminder to implement
242      * this at a later date. JRA.
243      */
244
245         if (!allow_access(lp_domain_hostsdeny(), lp_domain_hostsallow(),
246                           client_name(Client), client_addr(Client)))
247         {
248                 DEBUG(0,("get_md4pw: Workstation %s denied access to domain\n", mach_acct));
249                 return False;
250         }
251 #endif /* 0 */
252
253         become_root(True);
254         smb_pass = getsmbpwnam(mach_acct);
255         unbecome_root(True);
256
257         if ((smb_pass) != NULL && !(smb_pass->acct_ctrl & ACB_DISABLED) &&
258         (smb_pass->smb_nt_passwd != NULL))
259         {
260                 memcpy(md4pw, smb_pass->smb_nt_passwd, 16);
261                 dump_data(5, md4pw, 16);
262
263                 return True;
264         }
265         DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct));
266         return False;
267 }
268
269 /*************************************************************************
270  api_net_req_chal:
271  *************************************************************************/
272 static void api_net_req_chal( uint16 vuid,
273                               prs_struct *data,
274                               prs_struct *rdata)
275 {
276         NET_Q_REQ_CHAL q_r;
277         uint32 status = 0x0;
278
279         fstring mach_acct;
280         fstring mach_name;
281
282         user_struct *vuser;
283
284         DEBUG(5,("api_net_req_chal(%d): vuid %d\n", __LINE__, (int)vuid));
285
286         if ((vuser = get_valid_user_struct(vuid)) == NULL)
287       return;
288
289         /* grab the challenge... */
290         net_io_q_req_chal("", &q_r, data, 0);
291
292         fstrcpy(mach_acct, unistrn2(q_r.uni_logon_clnt.buffer,
293                                     q_r.uni_logon_clnt.uni_str_len));
294
295         fstrcpy(mach_name, mach_acct);
296         strlower(mach_name);
297
298         fstrcat(mach_acct, "$");
299
300         if (get_md4pw((char *)vuser->dc.md4pw, mach_name, mach_acct))
301         {
302                 /* copy the client credentials */
303                 memcpy(vuser->dc.clnt_chal.data          , q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data));
304                 memcpy(vuser->dc.clnt_cred.challenge.data, q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data));
305
306                 /* create a server challenge for the client */
307                 /* Set these to random values. */
308                 generate_random_buffer(vuser->dc.srv_chal.data, 8, False);
309
310                 memcpy(vuser->dc.srv_cred.challenge.data, vuser->dc.srv_chal.data, 8);
311
312                 bzero(vuser->dc.sess_key, sizeof(vuser->dc.sess_key));
313
314                 /* from client / server challenges and md4 password, generate sess key */
315                 cred_session_key(&(vuser->dc.clnt_chal), &(vuser->dc.srv_chal),
316                                  (char *)vuser->dc.md4pw, vuser->dc.sess_key);
317         }
318         else
319         {
320                 /* lkclXXXX take a guess at a good error message to return :-) */
321                 status = 0xC0000000 | NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT;
322         }
323
324         /* construct reply. */
325         net_reply_req_chal(&q_r, rdata,
326                                         &(vuser->dc.srv_chal), status);
327
328 }
329
330 /*************************************************************************
331  api_net_auth_2:
332  *************************************************************************/
333 static void api_net_auth_2( uint16 vuid,
334                             prs_struct *data,
335                             prs_struct *rdata)
336 {
337         NET_Q_AUTH_2 q_a;
338         uint32 status = 0x0;
339
340         DOM_CHAL srv_cred;
341         UTIME srv_time;
342
343         user_struct *vuser;
344
345         if ((vuser = get_valid_user_struct(vuid)) == NULL)
346       return;
347
348         srv_time.time = 0;
349
350         /* grab the challenge... */
351         net_io_q_auth_2("", &q_a, data, 0);
352
353         /* check that the client credentials are valid */
354         if (cred_assert(&(q_a.clnt_chal), vuser->dc.sess_key,
355                     &(vuser->dc.clnt_cred.challenge), srv_time))
356         {
357
358                 /* create server challenge for inclusion in the reply */
359                 cred_create(vuser->dc.sess_key, &(vuser->dc.srv_cred.challenge), srv_time, &srv_cred);
360
361                 /* copy the received client credentials for use next time */
362                 memcpy(vuser->dc.clnt_cred.challenge.data, q_a.clnt_chal.data, sizeof(q_a.clnt_chal.data));
363                 memcpy(vuser->dc.srv_cred .challenge.data, q_a.clnt_chal.data, sizeof(q_a.clnt_chal.data));
364         }
365         else
366         {
367                 status = NT_STATUS_ACCESS_DENIED | 0xC0000000;
368         }
369
370         /* construct reply. */
371         net_reply_auth_2(&q_a, rdata, &srv_cred, status);
372 }
373
374
375 /*************************************************************************
376  api_net_srv_pwset:
377  *************************************************************************/
378 static void api_net_srv_pwset( uint16 vuid,
379                                prs_struct *data,
380                                prs_struct *rdata)
381 {
382         NET_Q_SRV_PWSET q_a;
383         uint32 status = NT_STATUS_WRONG_PASSWORD|0xC0000000;
384         DOM_CRED srv_cred;
385         pstring mach_acct;
386         struct smb_passwd *smb_pass;
387         BOOL ret;
388         user_struct *vuser;
389
390         if ((vuser = get_valid_user_struct(vuid)) == NULL)
391       return;
392
393         /* grab the challenge and encrypted password ... */
394         net_io_q_srv_pwset("", &q_a, data, 0);
395
396         /* checks and updates credentials.  creates reply credentials */
397         if (deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred), 
398                             &(q_a.clnt_id.cred), &srv_cred))
399         {
400                 memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred));
401
402                 DEBUG(5,("api_net_srv_pwset: %d\n", __LINE__));
403
404                 pstrcpy(mach_acct, unistrn2(q_a.clnt_id.login.uni_acct_name.buffer,
405                                             q_a.clnt_id.login.uni_acct_name.uni_str_len));
406
407                 DEBUG(3,("Server Password Set Wksta:[%s]\n", mach_acct));
408
409                 become_root(True);
410                 smb_pass = getsmbpwnam(mach_acct);
411                 unbecome_root(True);
412
413                 if (smb_pass != NULL)
414                 {
415                         unsigned char pwd[16];
416                         int i;
417
418                         DEBUG(100,("Server password set : new given value was :\n"));
419                         for(i = 0; i < 16; i++)
420                         {
421                                 DEBUG(100,("%02X ", q_a.pwd[i]));
422                         }
423                         DEBUG(100,("\n"));
424
425                         cred_hash3( pwd, q_a.pwd, vuser->dc.sess_key, 0);
426
427                         /* lies!  nt and lm passwords are _not_ the same: don't care */
428                         smb_pass->smb_passwd    = pwd;
429                         smb_pass->smb_nt_passwd = pwd;
430                         smb_pass->acct_ctrl     = ACB_WSTRUST;
431
432                         become_root(True);
433                         ret = mod_smbpwd_entry(smb_pass,False);
434                         unbecome_root(True);
435
436                         if (ret)
437                         {
438                                 /* hooray! */
439                                 status = 0x0;
440                         }
441                 }
442
443                 DEBUG(5,("api_net_srv_pwset: %d\n", __LINE__));
444
445         }
446         else
447         {
448                 /* lkclXXXX take a guess at a sensible error code to return... */
449                 status = 0xC0000000 | NT_STATUS_NETWORK_CREDENTIAL_CONFLICT;
450         }
451
452         /* Construct reply. */
453         net_reply_srv_pwset(&q_a, rdata, &srv_cred, status);
454 }
455
456
457 /*************************************************************************
458  api_net_sam_logoff:
459  *************************************************************************/
460 static void api_net_sam_logoff( uint16 vuid,
461                                prs_struct *data,
462                                prs_struct *rdata)
463 {
464         NET_Q_SAM_LOGOFF q_l;
465         NET_ID_INFO_CTR ctr;    
466
467         DOM_CRED srv_cred;
468
469         user_struct *vuser;
470
471         if ((vuser = get_valid_user_struct(vuid)) == NULL)
472       return;
473
474         /* the DOM_ID_INFO_1 structure is a bit big.  plus we might want to
475            dynamically allocate it inside net_io_q_sam_logon, at some point */
476         q_l.sam_id.ctr = &ctr;
477
478         /* grab the challenge... */
479         net_io_q_sam_logoff("", &q_l, data, 0);
480
481         /* checks and updates credentials.  creates reply credentials */
482         deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred), 
483                         &(q_l.sam_id.client.cred), &srv_cred);
484         memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred));
485
486         /* construct reply.  always indicate success */
487         net_reply_sam_logoff(&q_l, rdata,
488                                         &srv_cred,
489                         0x0);
490 }
491
492 /*************************************************************************
493  net_login_interactive:
494  *************************************************************************/
495 static uint32 net_login_interactive(NET_ID_INFO_1 *id1,
496                                 struct smb_passwd *smb_pass,
497                                 user_struct *vuser)
498 {
499         uint32 status = 0x0;
500
501         char nt_pwd[16];
502         char lm_pwd[16];
503         unsigned char key[16];
504
505         memset(key, 0, 16);
506         memcpy(key, vuser->dc.sess_key, 8);
507
508         memcpy(lm_pwd, id1->lm_owf.data, 16);
509         memcpy(nt_pwd, id1->nt_owf.data, 16);
510
511 #ifdef DEBUG_PASSWORD
512         DEBUG(100,("key:"));
513         dump_data(100, key, 16);
514
515         DEBUG(100,("lm owf password:"));
516         dump_data(100, lm_pwd, 16);
517
518         DEBUG(100,("nt owf password:"));
519         dump_data(100, nt_pwd, 16);
520 #endif
521
522         SamOEMhash((uchar *)lm_pwd, key, False);
523         SamOEMhash((uchar *)nt_pwd, key, False);
524
525 #ifdef DEBUG_PASSWORD
526         DEBUG(100,("decrypt of lm owf password:"));
527         dump_data(100, lm_pwd, 16);
528
529         DEBUG(100,("decrypt of nt owf password:"));
530         dump_data(100, nt_pwd, 16);
531 #endif
532
533         if (memcmp(smb_pass->smb_passwd   , lm_pwd, 16) != 0 &&
534             memcmp(smb_pass->smb_nt_passwd, nt_pwd, 16) != 0)
535         {
536                 status = 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
537         }
538
539         return status;
540 }
541
542 /*************************************************************************
543  net_login_network:
544  *************************************************************************/
545 static uint32 net_login_network(NET_ID_INFO_2 *id2,
546                                 struct smb_passwd *smb_pass,
547                                 user_struct *vuser)
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 == NULL)
677                 {
678                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
679                 }
680                 else if (IS_BITS_SET_ALL(smb_pass->acct_ctrl, ACB_DISABLED) &&
681                          IS_BITS_CLR_ALL(smb_pass->acct_ctrl, ACB_PWNOTREQ))
682                 {
683                         status =  0xC0000000 | NT_STATUS_ACCOUNT_DISABLED;
684                 }
685         }
686
687         /* validate password - if required */
688
689         if (status == 0 && !(IS_BITS_SET_ALL(smb_pass->acct_ctrl, ACB_PWNOTREQ)))
690         {
691                 switch (q_l.sam_id.logon_level)
692                 {
693                         case INTERACTIVE_LOGON_TYPE:
694                         {
695                                 /* interactive login. */
696                                 status = net_login_interactive(&q_l.sam_id.ctr->auth.id1, smb_pass, vuser);
697                                 break;
698                         }
699                         case NET_LOGON_TYPE:
700                         {
701                                 /* network login.  lm challenge and 24 byte responses */
702                                 status = net_login_network(&q_l.sam_id.ctr->auth.id2, smb_pass, vuser);
703                                 break;
704                         }
705                 }
706         }
707
708         /* lkclXXXX this is the point at which, if the login was
709         successful, that the SAM Local Security Authority should
710         record that the user is logged in to the domain.
711         */
712
713         /* return the profile plus other bits :-) */
714
715         if (status == 0)
716         {
717                 DOM_GID *gids = NULL;
718                 int num_gids = 0;
719                 NTTIME dummy_time;
720                 pstring logon_script;
721                 pstring profile_path;
722                 pstring home_dir;
723                 pstring home_drive;
724                 pstring my_name;
725                 pstring my_workgroup;
726                 DOMAIN_GRP *grp_mem;
727                 uint32 r_uid;
728                 uint32 r_gid;
729
730                 /* set up pointer indicating user/password failed to be found */
731                 usr_info.ptr_user_info = 0;
732
733                 dummy_time.low  = 0xffffffff;
734                 dummy_time.high = 0x7fffffff;
735
736                 /* XXXX hack to get standard_sub_basic() to use sam logon username */
737                 /* possibly a better way would be to do a become_user() call */
738                 sam_logon_in_ssb = True;
739
740                 pstrcpy(logon_script, lp_logon_script());
741                 pstrcpy(profile_path, lp_logon_path());
742
743                 pstrcpy(my_workgroup, lp_workgroup());
744
745                 pstrcpy(home_drive, lp_logon_drive());
746                 pstrcpy(home_dir, lp_logon_home());
747                 pstrcpy(my_name, global_myname);
748                 strupper(my_name);
749
750                 status = lookup_user_rids(samlogon_user, &r_uid, &r_gid);
751                 status = getusergroupsnam(samlogon_user, &grp_mem, &num_gids) ? 0 : 0xC0000000 | NT_STATUS_INVALID_PRIMARY_GROUP;
752
753                 if (status == 0x0)
754                 {
755                         gids = NULL;
756                         num_gids = make_dom_gids(grp_mem, num_gids, &gids);
757
758                         make_net_user_info3(&usr_info,
759                                 &dummy_time, /* logon_time */
760                                 &dummy_time, /* logoff_time */
761                                 &dummy_time, /* kickoff_time */
762                                 &dummy_time, /* pass_last_set_time */
763                                 &dummy_time, /* pass_can_change_time */
764                                 &dummy_time, /* pass_must_change_time */
765
766                                 samlogon_user   , /* user_name */
767                                 vuser->real_name, /* full_name */
768                                 logon_script    , /* logon_script */
769                                 profile_path    , /* profile_path */
770                                 home_dir        , /* home_dir */
771                                 home_drive      , /* dir_drive */
772
773                                 0, /* logon_count */
774                                 0, /* bad_pw_count */
775
776                                 r_uid   , /* RID user_id */
777                                 r_gid   , /* RID group_id */
778                                 num_gids,    /* uint32 num_groups */
779                                 gids    , /* DOM_GID *gids */
780                                 0x20    , /* uint32 user_flgs (?) */
781
782                                 NULL, /* char sess_key[16] */
783
784                                 my_name     , /* char *logon_srv */
785                                 my_workgroup, /* char *logon_dom */
786
787                                 &global_sam_sid,     /* DOM_SID *dom_sid */
788                                 NULL); /* char *other_sids */
789                 }
790
791                 /* Free any allocated groups array. */
792                 if (gids)
793                 {
794                         free((char *)gids);
795                 }
796         }
797
798         net_reply_sam_logon(&q_l, rdata, &srv_cred, &usr_info, status);
799 }
800
801
802 /*************************************************************************
803  api_net_trust_dom_list:
804  *************************************************************************/
805 static void api_net_trust_dom_list( uint16 vuid,
806                                  prs_struct *data,
807                                  prs_struct *rdata)
808 {
809         NET_Q_TRUST_DOM_LIST q_t;
810
811         char *trusted_domain = "test_domain";
812
813         DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
814
815         /* grab the lsa trusted domain list query... */
816         net_io_q_trust_dom("", &q_t, data, 0);
817
818         /* construct reply. */
819         net_reply_trust_dom_list(&q_t, rdata,
820                                 1, trusted_domain);
821
822         DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
823 }
824
825
826 /*************************************************************************
827  error messages cropping up when using nltest.exe...
828  *************************************************************************/
829 #define ERROR_NO_SUCH_DOMAIN   0x54b
830 #define ERROR_NO_LOGON_SERVERS 0x51f
831
832 /*************************************************************************
833  api_net_logon_ctrl2:
834  *************************************************************************/
835 static void api_net_logon_ctrl2( uint16 vuid,
836                                  prs_struct *data,
837                                  prs_struct *rdata)
838 {
839         NET_Q_LOGON_CTRL2 q_l;
840
841         /* lkclXXXX - guess what - absolutely no idea what these are! */
842         uint32 flags = 0x0;
843         uint32 pdc_connection_status = 0x0;
844         uint32 logon_attempts = 0x0;
845         uint32 tc_status = ERROR_NO_LOGON_SERVERS;
846         char *trusted_domain = "test_domain";
847
848         DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
849
850         /* grab the lsa netlogon ctrl2 query... */
851         net_io_q_logon_ctrl2("", &q_l, data, 0);
852
853         /* construct reply. */
854         net_reply_logon_ctrl2(&q_l, rdata,
855                                 flags, pdc_connection_status, logon_attempts,
856                                 tc_status, trusted_domain);
857
858         DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
859 }
860
861 /*******************************************************************
862  array of \PIPE\NETLOGON operations
863  ********************************************************************/
864 static struct api_struct api_net_cmds [] =
865 {
866         { "NET_REQCHAL"       , NET_REQCHAL       , api_net_req_chal       }, 
867         { "NET_AUTH2"         , NET_AUTH2         , api_net_auth_2         }, 
868         { "NET_SRVPWSET"      , NET_SRVPWSET      , api_net_srv_pwset      }, 
869         { "NET_SAMLOGON"      , NET_SAMLOGON      , api_net_sam_logon      }, 
870         { "NET_SAMLOGOFF"     , NET_SAMLOGOFF     , api_net_sam_logoff     }, 
871         { "NET_LOGON_CTRL2"   , NET_LOGON_CTRL2   , api_net_logon_ctrl2    }, 
872         { "NET_TRUST_DOM_LIST", NET_TRUST_DOM_LIST, api_net_trust_dom_list },
873     {  NULL               , 0                 , NULL                   }
874 };
875
876 /*******************************************************************
877  receives a netlogon pipe and responds.
878  ********************************************************************/
879 BOOL api_netlog_rpc(pipes_struct *p, prs_struct *data)
880 {
881         return api_rpcTNP(p, "api_netlog_rpc", api_net_cmds, data);
882 }