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