delineation between smb and msrpc more marked. smbd now constructs
[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( rpcsrv_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         DEBUG(5,("api_net_req_chal(%d)\n", __LINE__));
355
356         /* grab the challenge... */
357         net_io_q_req_chal("", &q_r, data, 0);
358
359         unistr2_to_ascii(mach_acct, &q_r.uni_logon_clnt, sizeof(mach_acct)-1);
360
361         fstrcpy(mach_name, mach_acct);
362         strlower(mach_name);
363
364         fstrcat(mach_acct, "$");
365
366         if (get_md4pw((char *)p->dc.md4pw, mach_name, mach_acct))
367         {
368                 /* copy the client credentials */
369                 memcpy(p->dc.clnt_chal.data          , q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data));
370                 memcpy(p->dc.clnt_cred.challenge.data, q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data));
371
372                 /* create a server challenge for the client */
373                 /* Set these to random values. */
374                 generate_random_buffer(p->dc.srv_chal.data, 8, False);
375
376                 memcpy(p->dc.srv_cred.challenge.data, p->dc.srv_chal.data, 8);
377
378                 bzero(p->dc.sess_key, sizeof(p->dc.sess_key));
379
380                 /* from client / server challenges and md4 password, generate sess key */
381                 cred_session_key(&(p->dc.clnt_chal), &(p->dc.srv_chal),
382                                  (char *)p->dc.md4pw, p->dc.sess_key);
383         }
384         else
385         {
386                 /* lkclXXXX take a guess at a good error message to return :-) */
387                 status = 0xC0000000 | NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT;
388         }
389
390         /* construct reply. */
391         net_reply_req_chal(&q_r, rdata,
392                                         &(p->dc.srv_chal), status);
393
394 }
395
396 /*************************************************************************
397  api_net_auth:
398  *************************************************************************/
399 static void api_net_auth( rpcsrv_struct *p,
400                             prs_struct *data,
401                             prs_struct *rdata)
402 {
403         NET_Q_AUTH q_a;
404         uint32 status = 0x0;
405
406         DOM_CHAL srv_cred;
407         UTIME srv_time;
408
409         srv_time.time = 0;
410
411         /* grab the challenge... */
412         net_io_q_auth("", &q_a, data, 0);
413
414         /* check that the client credentials are valid */
415         if (cred_assert(&(q_a.clnt_chal), p->dc.sess_key,
416                     &(p->dc.clnt_cred.challenge), srv_time))
417         {
418
419                 /* create server challenge for inclusion in the reply */
420                 cred_create(p->dc.sess_key, &(p->dc.srv_cred.challenge), srv_time, &srv_cred);
421
422                 /* copy the received client credentials for use next time */
423                 memcpy(p->dc.clnt_cred.challenge.data, q_a.clnt_chal.data, sizeof(q_a.clnt_chal.data));
424                 memcpy(p->dc.srv_cred .challenge.data, q_a.clnt_chal.data, sizeof(q_a.clnt_chal.data));
425         }
426         else
427         {
428                 status = NT_STATUS_ACCESS_DENIED | 0xC0000000;
429         }
430
431         /* construct reply. */
432         net_reply_auth(&q_a, rdata, &srv_cred, status);
433 }
434
435 /*************************************************************************
436  api_net_auth_2:
437  *************************************************************************/
438 static void api_net_auth_2( rpcsrv_struct *p,
439                             prs_struct *data,
440                             prs_struct *rdata)
441 {
442         NET_Q_AUTH_2 q_a;
443         uint32 status = 0x0;
444
445         DOM_CHAL srv_cred;
446         UTIME srv_time;
447
448         srv_time.time = 0;
449
450         /* grab the challenge... */
451         net_io_q_auth_2("", &q_a, data, 0);
452
453         /* check that the client credentials are valid */
454         if (cred_assert(&(q_a.clnt_chal), p->dc.sess_key,
455                     &(p->dc.clnt_cred.challenge), srv_time))
456         {
457
458                 /* create server challenge for inclusion in the reply */
459                 cred_create(p->dc.sess_key, &(p->dc.srv_cred.challenge), srv_time, &srv_cred);
460
461                 /* copy the received client credentials for use next time */
462                 memcpy(p->dc.clnt_cred.challenge.data, q_a.clnt_chal.data, sizeof(q_a.clnt_chal.data));
463                 memcpy(p->dc.srv_cred .challenge.data, q_a.clnt_chal.data, sizeof(q_a.clnt_chal.data));
464         }
465         else
466         {
467                 status = NT_STATUS_ACCESS_DENIED | 0xC0000000;
468         }
469
470         /* construct reply. */
471         net_reply_auth_2(&q_a, rdata, &srv_cred, status);
472 }
473
474 /*************************************************************************
475  api_net_srv_pwset:
476  *************************************************************************/
477 static void api_net_srv_pwset( rpcsrv_struct *p,
478                                prs_struct *data,
479                                prs_struct *rdata)
480 {
481         NET_Q_SRV_PWSET q_a;
482         uint32 status = NT_STATUS_WRONG_PASSWORD|0xC0000000;
483         DOM_CRED srv_cred;
484         pstring mach_acct;
485         struct smb_passwd *smb_pass;
486         BOOL ret;
487
488         /* grab the challenge and encrypted password ... */
489         net_io_q_srv_pwset("", &q_a, data, 0);
490
491         /* checks and updates credentials.  creates reply credentials */
492         if (deal_with_creds(p->dc.sess_key, &(p->dc.clnt_cred), 
493                             &(q_a.clnt_id.cred), &srv_cred))
494         {
495                 memcpy(&(p->dc.srv_cred), &(p->dc.clnt_cred), sizeof(p->dc.clnt_cred));
496
497                 DEBUG(5,("api_net_srv_pwset: %d\n", __LINE__));
498
499                 unistr2_to_ascii(mach_acct, &q_a.clnt_id.login.uni_acct_name,
500                                  sizeof(mach_acct)-1);
501
502                 DEBUG(3,("Server Password Set Wksta:[%s]\n", mach_acct));
503
504                 become_root(True);
505                 smb_pass = getsmbpwnam(mach_acct);
506                 unbecome_root(True);
507
508                 if (smb_pass != NULL)
509                 {
510                         unsigned char pwd[16];
511                         int i;
512
513                         DEBUG(100,("Server password set : new given value was :\n"));
514                         for(i = 0; i < 16; i++)
515                         {
516                                 DEBUG(100,("%02X ", q_a.pwd[i]));
517                         }
518                         DEBUG(100,("\n"));
519
520                         cred_hash3( pwd, q_a.pwd, p->dc.sess_key, 0);
521
522                         /* lies!  nt and lm passwords are _not_ the same: don't care */
523                         smb_pass->smb_passwd    = pwd;
524                         smb_pass->smb_nt_passwd = pwd;
525                         smb_pass->acct_ctrl     = ACB_WSTRUST;
526
527                         become_root(True);
528                         ret = mod_smbpwd_entry(smb_pass,False);
529                         unbecome_root(True);
530
531                         if (ret)
532                         {
533                                 /* hooray! */
534                                 status = 0x0;
535                         }
536                 }
537
538                 DEBUG(5,("api_net_srv_pwset: %d\n", __LINE__));
539
540         }
541         else
542         {
543                 /* lkclXXXX take a guess at a sensible error code to return... */
544                 status = 0xC0000000 | NT_STATUS_NETWORK_CREDENTIAL_CONFLICT;
545         }
546
547         /* Construct reply. */
548         net_reply_srv_pwset(&q_a, rdata, &srv_cred, status);
549 }
550
551
552 /*************************************************************************
553  api_net_sam_logoff:
554  *************************************************************************/
555 static void api_net_sam_logoff( rpcsrv_struct *p,
556                                 prs_struct *data,
557                                 prs_struct *rdata)
558 {
559         NET_Q_SAM_LOGOFF q_l;
560         NET_ID_INFO_CTR ctr;    
561
562         DOM_CRED srv_cred;
563
564         /* the DOM_ID_INFO_1 structure is a bit big.  plus we might want to
565            dynamically allocate it inside net_io_q_sam_logon, at some point */
566         q_l.sam_id.ctr = &ctr;
567
568         /* grab the challenge... */
569         net_io_q_sam_logoff("", &q_l, data, 0);
570
571         /* checks and updates credentials.  creates reply credentials */
572         deal_with_creds(p->dc.sess_key, &(p->dc.clnt_cred), 
573                         &(q_l.sam_id.client.cred), &srv_cred);
574         memcpy(&(p->dc.srv_cred), &(p->dc.clnt_cred), sizeof(p->dc.clnt_cred));
575
576         /* construct reply.  always indicate success */
577         net_reply_sam_logoff(&q_l, rdata, &srv_cred, 0x0);
578 }
579
580 /*************************************************************************
581  api_net_sam_sync:
582  *************************************************************************/
583 static void api_net_sam_sync( rpcsrv_struct *p,
584                               prs_struct *data,
585                               prs_struct *rdata)
586 {
587         NET_Q_SAM_SYNC q_s;
588         DOM_CRED srv_creds;
589         uint32 status = 0x0;
590
591         /* grab the challenge... */
592         net_io_q_sam_sync("", &q_s, data, 0);
593
594         /* checks and updates credentials.  creates reply credentials */
595         if (deal_with_creds(p->dc.sess_key, &(p->dc.clnt_cred), 
596                         &(q_s.cli_creds), &srv_creds))
597         {
598                 memcpy(&(p->dc.srv_cred), &(p->dc.clnt_cred),
599                        sizeof(p->dc.clnt_cred));
600         }
601         else
602         {
603                 status = 0xC0000000 | NT_STATUS_NETWORK_CREDENTIAL_CONFLICT;
604         }
605
606         /* construct reply. */
607         net_reply_sam_sync(&q_s, rdata, p->dc.sess_key, &srv_creds, status);
608 }
609
610
611 /*************************************************************************
612  net_login_interactive:
613  *************************************************************************/
614 static uint32 net_login_interactive(NET_ID_INFO_1 *id1,
615                                 struct sam_passwd *smb_pass,
616                                 struct dcinfo *dc)
617 {
618         uint32 status = 0x0;
619
620         char nt_pwd[16];
621         char lm_pwd[16];
622         unsigned char key[16];
623
624         memset(key, 0, 16);
625         memcpy(key, dc->sess_key, 8);
626
627         memcpy(lm_pwd, id1->lm_owf.data, 16);
628         memcpy(nt_pwd, id1->nt_owf.data, 16);
629
630 #ifdef DEBUG_PASSWORD
631         DEBUG(100,("key:"));
632         dump_data(100, key, 16);
633
634         DEBUG(100,("lm owf password:"));
635         dump_data(100, lm_pwd, 16);
636
637         DEBUG(100,("nt owf password:"));
638         dump_data(100, nt_pwd, 16);
639 #endif
640
641         SamOEMhash((uchar *)lm_pwd, key, 0);
642         SamOEMhash((uchar *)nt_pwd, key, 0);
643
644 #ifdef DEBUG_PASSWORD
645         DEBUG(100,("decrypt of lm owf password:"));
646         dump_data(100, lm_pwd, 16);
647
648         DEBUG(100,("decrypt of nt owf password:"));
649         dump_data(100, nt_pwd, 16);
650 #endif
651
652         if (smb_pass->smb_nt_passwd == NULL)
653         {
654                 DEBUG(5,("warning: NETLOGON user %s only has an LM password\n",
655                           smb_pass->unix_name));
656         }
657
658         if (memcmp(smb_pass->smb_passwd   , lm_pwd, 16) != 0 ||
659             smb_pass->smb_nt_passwd == NULL ||
660             memcmp(smb_pass->smb_nt_passwd, nt_pwd, 16) != 0)
661         {
662                 status = 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
663         }
664
665         return status;
666 }
667
668 /*************************************************************************
669  net_login_network:
670  *************************************************************************/
671 static uint32 net_login_network(NET_ID_INFO_2 *id2,
672                                 struct sam_passwd *sam_pass,
673                                 struct dcinfo *dc,
674                                 char sess_key[16])
675 {
676         fstring user;
677         fstring domain;
678
679         int nt_pw_len = id2->hdr_nt_chal_resp.str_str_len;
680         int lm_pw_len = id2->hdr_lm_chal_resp.str_str_len;
681
682         unistr2_to_ascii(user  , &id2->uni_user_name, sizeof(user)-1);
683         unistr2_to_ascii(domain, &id2->uni_domain_name, sizeof(domain)-1);
684
685         DEBUG(5,("net_login_network: lm_len:%d nt_len:%d user:%s domain:%s\n",
686                 lm_pw_len, nt_pw_len, user, domain));
687
688         if (pass_check_smb(pwdb_sam_to_smb(sam_pass),
689                             domain,
690                             id2->lm_chal, 
691                             (uchar *)id2->lm_chal_resp.buffer, lm_pw_len, 
692                             (uchar *)id2->nt_chal_resp.buffer, nt_pw_len,
693                             NULL, sess_key)) 
694         {
695                 unsigned char key[16];
696
697                 memset(key, 0, 16);
698                 memcpy(key, dc->sess_key, 8);
699
700 #ifdef DEBUG_PASSWORD
701                 DEBUG(100,("key:"));
702                 dump_data(100, key, 16);
703
704                 DEBUG(100,("user sess key:"));
705                 dump_data(100, sess_key, 16);
706 #endif
707
708                 SamOEMhash((uchar *)sess_key, key, 0);
709
710 #ifdef DEBUG_PASSWORD
711                 DEBUG(100,("encrypt of user session key:"));
712                 dump_data(100, sess_key, 16);
713 #endif
714
715                   return 0x0;
716         }
717
718         return 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
719 }
720
721 /*************************************************************************
722  api_net_sam_logon:
723  *************************************************************************/
724 static uint32 reply_net_sam_logon(NET_Q_SAM_LOGON *q_l,
725                                 struct dcinfo *dc,
726                                 DOM_CRED *srv_cred, NET_USER_INFO_3 *usr_info)
727 {
728         struct sam_passwd *sam_pass = NULL;
729         UNISTR2 *uni_samusr = NULL;
730         UNISTR2 *uni_domain = NULL;
731         fstring nt_username;
732         char *enc_user_sess_key = NULL;
733         char sess_key[16];
734
735         NTTIME logon_time           ;
736         NTTIME logoff_time          ;
737         NTTIME kickoff_time         ;
738         NTTIME pass_last_set_time   ;
739         NTTIME pass_can_change_time ;
740         NTTIME pass_must_change_time;
741
742         fstring nt_name     ;
743         fstring full_name   ;
744         fstring logon_script;
745         fstring profile_path;
746         fstring home_dir    ;
747         fstring dir_drive   ;
748
749         uint32 user_rid ;
750         uint32 group_rid;
751
752         int num_gids = 0;
753         DOMAIN_GRP *grp_mem = NULL;
754         DOM_GID *gids = NULL;
755
756         /* checks and updates credentials.  creates reply credentials */
757         if (!deal_with_creds(dc->sess_key, &(dc->clnt_cred), 
758                              &(q_l->sam_id.client.cred), srv_cred))
759         {
760                 return 0xC0000000 | NT_STATUS_INVALID_HANDLE;
761         }
762         
763         memcpy(&(dc->srv_cred), &(dc->clnt_cred), sizeof(dc->clnt_cred));
764
765         /* find the username */
766
767         switch (q_l->sam_id.logon_level)
768         {
769                 case INTERACTIVE_LOGON_TYPE:
770                 {
771                         uni_samusr = &(q_l->sam_id.ctr->auth.id1.uni_user_name);
772                         uni_domain        = &(q_l->sam_id.ctr->auth.id1.uni_domain_name);
773
774                         DEBUG(3,("SAM Logon (Interactive). Domain:[%s].  ", global_sam_name));
775                         break;
776                 }
777                 case NET_LOGON_TYPE:
778                 {
779                         uni_samusr = &(q_l->sam_id.ctr->auth.id2.uni_user_name);
780                         uni_domain        = &(q_l->sam_id.ctr->auth.id2.uni_domain_name);
781
782                         DEBUG(3,("SAM Logon (Network). Domain:[%s].  ", global_sam_name));
783                         break;
784                 }
785                 default:
786                 {
787                         DEBUG(2,("SAM Logon: unsupported switch value\n"));
788                         return 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
789                 }
790         } 
791
792         /* check username exists */
793
794         unistr2_to_ascii(nt_username, uni_samusr,
795                          sizeof(nt_username)-1);
796
797         DEBUG(3,("User:[%s]\n", nt_username));
798
799         become_root(True);
800         sam_pass = getsam21pwntnam(nt_username);
801         unbecome_root(True);
802
803         if (sam_pass == NULL)
804         {
805                 return 0xC0000000 | NT_STATUS_NO_SUCH_USER;
806         }
807         else if (IS_BITS_SET_ALL(sam_pass->acct_ctrl, ACB_DISABLED) &&
808                  IS_BITS_CLR_ALL(sam_pass->acct_ctrl, ACB_PWNOTREQ))
809         {
810                 return 0xC0000000 | NT_STATUS_ACCOUNT_DISABLED;
811         }
812
813         logon_time            = sam_pass->logon_time;
814         logoff_time           = sam_pass->logoff_time;
815         kickoff_time          = sam_pass->kickoff_time;
816         pass_last_set_time    = sam_pass->pass_last_set_time;
817         pass_can_change_time  = sam_pass->pass_can_change_time;
818         pass_must_change_time = sam_pass->pass_must_change_time;
819
820         fstrcpy(nt_name     , sam_pass->nt_name);
821         fstrcpy(full_name   , sam_pass->full_name);
822         fstrcpy(logon_script, sam_pass->logon_script);
823         fstrcpy(profile_path, sam_pass->profile_path);
824         fstrcpy(home_dir    , sam_pass->home_dir);
825         fstrcpy(dir_drive   , sam_pass->dir_drive);
826
827         user_rid  = sam_pass->user_rid;
828         group_rid = sam_pass->group_rid;
829
830         /* validate password - if required */
831
832         if (!(IS_BITS_SET_ALL(sam_pass->acct_ctrl, ACB_PWNOTREQ)))
833         {
834                 uint32 status = 0x0;
835                 switch (q_l->sam_id.logon_level)
836                 {
837                         case INTERACTIVE_LOGON_TYPE:
838                         {
839                                 /* interactive login. */
840                                 status = net_login_interactive(&q_l->sam_id.ctr->auth.id1, sam_pass, dc);
841                                 break;
842                         }
843                         case NET_LOGON_TYPE:
844                         {
845                                 /* network login.  lm challenge and 24 byte responses */
846                                 status = net_login_network(&q_l->sam_id.ctr->auth.id2, sam_pass, dc, sess_key);
847                                 enc_user_sess_key = sess_key;
848                                 break;
849                         }
850                 }
851                 if (status != 0x0)
852                 {
853                         return status;
854                 }
855         }
856
857         /* lkclXXXX this is the point at which, if the login was
858         successful, that the SAM Local Security Authority should
859         record that the user is logged in to the domain.
860         */
861
862         /* return the profile plus other bits :-) */
863
864         /* set up pointer indicating user/password failed to be found */
865         usr_info->ptr_user_info = 0;
866
867         if (!getusergroupsntnam(nt_username, &grp_mem, &num_gids))
868         {
869                 return 0xC0000000 | NT_STATUS_INVALID_PRIMARY_GROUP;
870         }
871
872         num_gids = make_dom_gids(grp_mem, num_gids, &gids);
873
874         make_net_user_info3(usr_info,
875                 &logon_time,
876                 &logoff_time,
877                 &kickoff_time,
878                 &pass_last_set_time,
879                 &pass_can_change_time,
880                 &pass_must_change_time,
881
882                 nt_name         , /* user_name */
883                 full_name       , /* full_name */
884                 logon_script    , /* logon_script */
885                 profile_path    , /* profile_path */
886                 home_dir        , /* home_dir */
887                 dir_drive       , /* dir_drive */
888
889                 0, /* logon_count */
890                 0, /* bad_pw_count */
891
892                 user_rid   , /* RID user_id */
893                 group_rid  , /* RID group_id */
894                 num_gids,    /* uint32 num_groups */
895                 gids    , /* DOM_GID *gids */
896                 0x20    , /* uint32 user_flgs (?) */
897
898                 enc_user_sess_key, /* char sess_key[16] */
899
900                 global_myname  , /* char *logon_srv */
901                 global_sam_name, /* char *logon_dom */
902                 &global_sam_sid, /* DOM_SID *dom_sid */
903                 NULL); /* char *other_sids */
904
905         /* Free any allocated groups array. */
906         if (gids)
907         {
908                 free((char *)gids);
909         }
910
911         return 0x0;
912 }
913
914 /*************************************************************************
915  api_net_sam_logon:
916  *************************************************************************/
917 static void api_net_sam_logon( rpcsrv_struct *p,
918                                prs_struct *data,
919                                prs_struct *rdata)
920 {
921         NET_Q_SAM_LOGON q_l;
922         NET_ID_INFO_CTR ctr;    
923         NET_USER_INFO_3 usr_info;
924         uint32 status = 0x0;
925         DOM_CRED srv_cred;
926
927         q_l.sam_id.ctr = &ctr;
928         net_io_q_sam_logon("", &q_l, data, 0);
929
930         status = reply_net_sam_logon(&q_l, &p->dc, &srv_cred, &usr_info);
931         net_reply_sam_logon(&q_l, rdata, &srv_cred, &usr_info, status);
932 }
933
934
935 /*************************************************************************
936  api_net_trust_dom_list:
937  *************************************************************************/
938 static void api_net_trust_dom_list( rpcsrv_struct *p,
939                                     prs_struct *data,
940                                     prs_struct *rdata)
941 {
942         NET_Q_TRUST_DOM_LIST q_t;
943         char **doms = NULL;
944         uint32 num_doms = 0;
945
946         enumtrustdoms(&doms, &num_doms);
947
948         DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
949
950         /* grab the lsa trusted domain list query... */
951         net_io_q_trust_dom("", &q_t, data, 0);
952
953         /* construct reply. */
954         net_reply_trust_dom_list(&q_t, rdata,
955                                 num_doms, doms);
956
957         free_char_array(num_doms, doms);
958
959         DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
960 }
961
962
963 /*************************************************************************
964  error messages cropping up when using nltest.exe...
965  *************************************************************************/
966 #define ERROR_NO_SUCH_DOMAIN   0x54b
967 #define ERROR_NO_LOGON_SERVERS 0x51f
968
969 /*************************************************************************
970  api_net_logon_ctrl2:
971  *************************************************************************/
972 static void api_net_logon_ctrl2( rpcsrv_struct *p,
973                                  prs_struct *data,
974                                  prs_struct *rdata)
975 {
976         NET_Q_LOGON_CTRL2 q_l;
977
978         /* lkclXXXX - guess what - absolutely no idea what these are! */
979         uint32 flags = 0x0;
980         uint32 pdc_connection_status = 0x0;
981         uint32 logon_attempts = 0x0;
982         uint32 tc_status = ERROR_NO_LOGON_SERVERS;
983         char *trusted_domain = "test_domain";
984
985         DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
986
987         /* grab the lsa netlogon ctrl2 query... */
988         net_io_q_logon_ctrl2("", &q_l, data, 0);
989
990         /* construct reply. */
991         net_reply_logon_ctrl2(&q_l, rdata,
992                                 flags, pdc_connection_status, logon_attempts,
993                                 tc_status, trusted_domain);
994
995         DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
996 }
997
998 /*******************************************************************
999  array of \PIPE\NETLOGON operations
1000  ********************************************************************/
1001 static struct api_struct api_net_cmds [] =
1002 {
1003         { "NET_REQCHAL"       , NET_REQCHAL       , api_net_req_chal       }, 
1004         { "NET_AUTH"          , NET_AUTH          , api_net_auth           },
1005         { "NET_AUTH2"         , NET_AUTH2         , api_net_auth_2         }, 
1006         { "NET_SRVPWSET"      , NET_SRVPWSET      , api_net_srv_pwset      }, 
1007         { "NET_SAMLOGON"      , NET_SAMLOGON      , api_net_sam_logon      }, 
1008         { "NET_SAMLOGOFF"     , NET_SAMLOGOFF     , api_net_sam_logoff     }, 
1009         { "NET_LOGON_CTRL2"   , NET_LOGON_CTRL2   , api_net_logon_ctrl2    }, 
1010         { "NET_TRUST_DOM_LIST", NET_TRUST_DOM_LIST, api_net_trust_dom_list },
1011         { "NET_SAM_SYNC"      , NET_SAM_SYNC      , api_net_sam_sync       },
1012         {  NULL               , 0                 , NULL                   }
1013 };
1014
1015 /*******************************************************************
1016  receives a netlogon pipe and responds.
1017  ********************************************************************/
1018 BOOL api_netlog_rpc(rpcsrv_struct *p, prs_struct *data)
1019 {
1020         return api_rpcTNP(p, "api_netlog_rpc", api_net_cmds, data);
1021 }