attempting to get nt5 wksta to join domain.
[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_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, False);
670         SamOEMhash((uchar *)nt_pwd, key, False);
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 *smb_pass,
701                                 user_struct *vuser)
702 {
703         fstring user;
704         fstring domain;
705
706         int nt_pw_len = id2->hdr_nt_chal_resp.str_str_len;
707         int lm_pw_len = id2->hdr_lm_chal_resp.str_str_len;
708
709         unistr2_to_ascii(user  , &id2->uni_user_name, sizeof(user)-1);
710         unistr2_to_ascii(domain, &id2->uni_domain_name, sizeof(domain)-1);
711
712         DEBUG(5,("net_login_network: lm_len:%d nt_len:%d user:%s domain:%s\n",
713                 lm_pw_len, nt_pw_len, user, domain));
714
715         if (smb_password_ok(pwdb_sam_to_smb(smb_pass), id2->lm_chal, 
716                             user, domain,
717                             (uchar *)id2->lm_chal_resp.buffer, lm_pw_len, 
718                             (uchar *)id2->nt_chal_resp.buffer, nt_pw_len)) 
719         {
720                   return 0x0;
721         }
722
723         return 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
724 }
725
726 /*************************************************************************
727  api_net_sam_logon:
728  *************************************************************************/
729 static uint32 reply_net_sam_logon( NET_Q_SAM_LOGON *q_l, user_struct *vuser,
730         DOM_CRED *srv_cred, NET_USER_INFO_3 *usr_info)
731 {
732         struct sam_passwd *sam_pass = NULL;
733         UNISTR2 *uni_samusr = NULL;
734         UNISTR2 *uni_domain = NULL;
735         fstring nt_username;
736
737         NTTIME logon_time           ;
738         NTTIME logoff_time          ;
739         NTTIME kickoff_time         ;
740         NTTIME pass_last_set_time   ;
741         NTTIME pass_can_change_time ;
742         NTTIME pass_must_change_time;
743
744         fstring nt_name     ;
745         fstring full_name   ;
746         fstring logon_script;
747         fstring profile_path;
748         fstring home_dir    ;
749         fstring dir_drive   ;
750
751         uint32 user_rid ;
752         uint32 group_rid;
753
754         int num_gids = 0;
755         DOMAIN_GRP *grp_mem = NULL;
756         DOM_GID *gids = NULL;
757
758         /* checks and updates credentials.  creates reply credentials */
759         if (!deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred), 
760                              &(q_l->sam_id.client.cred), srv_cred))
761         {
762                 return 0xC0000000 | NT_STATUS_INVALID_HANDLE;
763         }
764         
765         memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred));
766
767         /* find the username */
768
769         switch (q_l->sam_id.logon_level)
770         {
771                 case INTERACTIVE_LOGON_TYPE:
772                 {
773                         uni_samusr = &(q_l->sam_id.ctr->auth.id1.uni_user_name);
774                         uni_domain        = &(q_l->sam_id.ctr->auth.id1.uni_domain_name);
775
776                         DEBUG(3,("SAM Logon (Interactive). Domain:[%s].  ", global_sam_name));
777                         break;
778                 }
779                 case NET_LOGON_TYPE:
780                 {
781                         uni_samusr = &(q_l->sam_id.ctr->auth.id2.uni_user_name);
782                         uni_domain        = &(q_l->sam_id.ctr->auth.id2.uni_domain_name);
783
784                         DEBUG(3,("SAM Logon (Network). Domain:[%s].  ", global_sam_name));
785                         break;
786                 }
787                 default:
788                 {
789                         DEBUG(2,("SAM Logon: unsupported switch value\n"));
790                         return 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
791                 }
792         } 
793
794         /* check username exists */
795
796         unistr2_to_ascii(nt_username, uni_samusr,
797                          sizeof(nt_username)-1);
798
799         DEBUG(3,("User:[%s]\n", nt_username));
800
801         become_root(True);
802         sam_pass = getsam21pwntnam(nt_username);
803         unbecome_root(True);
804
805         if (sam_pass == NULL)
806         {
807                 return 0xC0000000 | NT_STATUS_NO_SUCH_USER;
808         }
809         else if (IS_BITS_SET_ALL(sam_pass->acct_ctrl, ACB_DISABLED) &&
810                  IS_BITS_CLR_ALL(sam_pass->acct_ctrl, ACB_PWNOTREQ))
811         {
812                 return 0xC0000000 | NT_STATUS_ACCOUNT_DISABLED;
813         }
814
815         logon_time            = sam_pass->logon_time;
816         logoff_time           = sam_pass->logoff_time;
817         kickoff_time          = sam_pass->kickoff_time;
818         pass_last_set_time    = sam_pass->pass_last_set_time;
819         pass_can_change_time  = sam_pass->pass_can_change_time;
820         pass_must_change_time = sam_pass->pass_must_change_time;
821
822         fstrcpy(nt_name     , sam_pass->nt_name);
823         fstrcpy(full_name   , sam_pass->full_name);
824         fstrcpy(logon_script, sam_pass->logon_script);
825         fstrcpy(profile_path, sam_pass->profile_path);
826         fstrcpy(home_dir    , sam_pass->home_dir);
827         fstrcpy(dir_drive   , sam_pass->dir_drive);
828
829         user_rid  = sam_pass->user_rid;
830         group_rid = sam_pass->group_rid;
831
832         /* validate password - if required */
833
834         if (!(IS_BITS_SET_ALL(sam_pass->acct_ctrl, ACB_PWNOTREQ)))
835         {
836                 uint32 status = 0x0;
837                 switch (q_l->sam_id.logon_level)
838                 {
839                         case INTERACTIVE_LOGON_TYPE:
840                         {
841                                 /* interactive login. */
842                                 status = net_login_interactive(&q_l->sam_id.ctr->auth.id1, sam_pass, vuser);
843                                 break;
844                         }
845                         case NET_LOGON_TYPE:
846                         {
847                                 /* network login.  lm challenge and 24 byte responses */
848                                 status = net_login_network(&q_l->sam_id.ctr->auth.id2, sam_pass, vuser);
849                                 break;
850                         }
851                 }
852                 if (status != 0x0)
853                 {
854                         return status;
855                 }
856         }
857
858         /* lkclXXXX this is the point at which, if the login was
859         successful, that the SAM Local Security Authority should
860         record that the user is logged in to the domain.
861         */
862
863         /* return the profile plus other bits :-) */
864
865         /* set up pointer indicating user/password failed to be found */
866         usr_info->ptr_user_info = 0;
867
868         if (!getusergroupsntnam(nt_username, &grp_mem, &num_gids))
869         {
870                 return 0xC0000000 | NT_STATUS_INVALID_PRIMARY_GROUP;
871         }
872
873         num_gids = make_dom_gids(grp_mem, num_gids, &gids);
874
875         make_net_user_info3(usr_info,
876                 &logon_time,
877                 &logoff_time,
878                 &kickoff_time,
879                 &pass_last_set_time,
880                 &pass_can_change_time,
881                 &pass_must_change_time,
882
883                 nt_name         , /* user_name */
884                 full_name       , /* full_name */
885                 logon_script    , /* logon_script */
886                 profile_path    , /* profile_path */
887                 home_dir        , /* home_dir */
888                 dir_drive       , /* dir_drive */
889
890                 0, /* logon_count */
891                 0, /* bad_pw_count */
892
893                 user_rid   , /* RID user_id */
894                 group_rid  , /* RID group_id */
895                 num_gids,    /* uint32 num_groups */
896                 gids    , /* DOM_GID *gids */
897                 0x20    , /* uint32 user_flgs (?) */
898
899                 NULL, /* char sess_key[16] */
900
901                 global_myname  , /* char *logon_srv */
902                 global_sam_name, /* char *logon_dom */
903                 &global_sam_sid, /* DOM_SID *dom_sid */
904                 NULL); /* char *other_sids */
905
906         /* Free any allocated groups array. */
907         if (gids)
908         {
909                 free((char *)gids);
910         }
911
912         return 0x0;
913 }
914
915 /*************************************************************************
916  api_net_sam_logon:
917  *************************************************************************/
918 static void api_net_sam_logon( pipes_struct *p,
919                                prs_struct *data,
920                                prs_struct *rdata)
921 {
922         NET_Q_SAM_LOGON q_l;
923         NET_ID_INFO_CTR ctr;    
924         NET_USER_INFO_3 usr_info;
925         uint32 status = 0x0;
926         DOM_CRED srv_cred;
927
928         user_struct *vuser = get_valid_user_struct(p->vuid);
929
930         if (vuser == NULL)
931         {
932                 return;
933         }
934
935         q_l.sam_id.ctr = &ctr;
936         net_io_q_sam_logon("", &q_l, data, 0);
937
938         status = reply_net_sam_logon(&q_l, vuser, &srv_cred, &usr_info);
939         net_reply_sam_logon(&q_l, rdata, &srv_cred, &usr_info, status);
940 }
941
942
943 /*************************************************************************
944  api_net_trust_dom_list:
945  *************************************************************************/
946 static void api_net_trust_dom_list( pipes_struct *p,
947                                     prs_struct *data,
948                                     prs_struct *rdata)
949 {
950         NET_Q_TRUST_DOM_LIST q_t;
951         char **doms = NULL;
952         uint32 num_doms = 0;
953
954         enumtrustdoms(&doms, &num_doms);
955
956         DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
957
958         /* grab the lsa trusted domain list query... */
959         net_io_q_trust_dom("", &q_t, data, 0);
960
961         /* construct reply. */
962         net_reply_trust_dom_list(&q_t, rdata,
963                                 num_doms, doms);
964
965         free_char_array(num_doms, doms);
966
967         DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
968 }
969
970
971 /*************************************************************************
972  error messages cropping up when using nltest.exe...
973  *************************************************************************/
974 #define ERROR_NO_SUCH_DOMAIN   0x54b
975 #define ERROR_NO_LOGON_SERVERS 0x51f
976
977 /*************************************************************************
978  api_net_logon_ctrl2:
979  *************************************************************************/
980 static void api_net_logon_ctrl2( pipes_struct *p,
981                                  prs_struct *data,
982                                  prs_struct *rdata)
983 {
984         NET_Q_LOGON_CTRL2 q_l;
985
986         /* lkclXXXX - guess what - absolutely no idea what these are! */
987         uint32 flags = 0x0;
988         uint32 pdc_connection_status = 0x0;
989         uint32 logon_attempts = 0x0;
990         uint32 tc_status = ERROR_NO_LOGON_SERVERS;
991         char *trusted_domain = "test_domain";
992
993         DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
994
995         /* grab the lsa netlogon ctrl2 query... */
996         net_io_q_logon_ctrl2("", &q_l, data, 0);
997
998         /* construct reply. */
999         net_reply_logon_ctrl2(&q_l, rdata,
1000                                 flags, pdc_connection_status, logon_attempts,
1001                                 tc_status, trusted_domain);
1002
1003         DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
1004 }
1005
1006 /*******************************************************************
1007  array of \PIPE\NETLOGON operations
1008  ********************************************************************/
1009 static struct api_struct api_net_cmds [] =
1010 {
1011         { "NET_REQCHAL"       , NET_REQCHAL       , api_net_req_chal       }, 
1012         { "NET_AUTH"          , NET_AUTH          , api_net_auth           },
1013         { "NET_AUTH2"         , NET_AUTH2         , api_net_auth_2         }, 
1014         { "NET_SRVPWSET"      , NET_SRVPWSET      , api_net_srv_pwset      }, 
1015         { "NET_SAMLOGON"      , NET_SAMLOGON      , api_net_sam_logon      }, 
1016         { "NET_SAMLOGOFF"     , NET_SAMLOGOFF     , api_net_sam_logoff     }, 
1017         { "NET_LOGON_CTRL2"   , NET_LOGON_CTRL2   , api_net_logon_ctrl2    }, 
1018         { "NET_TRUST_DOM_LIST", NET_TRUST_DOM_LIST, api_net_trust_dom_list },
1019         { "NET_SAM_SYNC"      , NET_SAM_SYNC      , api_net_sam_sync       },
1020         {  NULL               , 0                 , NULL                   }
1021 };
1022
1023 /*******************************************************************
1024  receives a netlogon pipe and responds.
1025  ********************************************************************/
1026 BOOL api_netlog_rpc(pipes_struct *p, prs_struct *data)
1027 {
1028         return api_rpcTNP(p, "api_netlog_rpc", api_net_cmds, data);
1029 }