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