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