(merge from 3.0)
[kai/samba-autobuild/.git] / source / rpc_server / srv_netlog_nt.c
1 /* 
2  *  Unix SMB/CIFS implementation.
3  *  RPC Pipe client / server routines
4  *  Copyright (C) Andrew Tridgell              1992-1997,
5  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
6  *  Copyright (C) Paul Ashton                       1997.
7  *  Copyright (C) Jeremy Allison               1998-2001.
8  *  Copyright (C) Andrew Bartlett                   2001.
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 /* This is the implementation of the netlogon pipe. */
26
27 #include "includes.h"
28
29 #undef DBGC_CLASS
30 #define DBGC_CLASS DBGC_RPC_SRV
31
32 /*************************************************************************
33  init_net_r_req_chal:
34  *************************************************************************/
35
36 static void init_net_r_req_chal(NET_R_REQ_CHAL *r_c,
37                                 DOM_CHAL *srv_chal, NTSTATUS status)
38 {
39         DEBUG(6,("init_net_r_req_chal: %d\n", __LINE__));
40         memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(srv_chal->data));
41         r_c->status = status;
42 }
43
44 /*************************************************************************
45  error messages cropping up when using nltest.exe...
46  *************************************************************************/
47
48 #define ERROR_NO_SUCH_DOMAIN   0x54b
49 #define ERROR_NO_LOGON_SERVERS 0x51f
50
51 /*************************************************************************
52  net_reply_logon_ctrl:
53  *************************************************************************/
54
55 /* Some flag values reverse engineered from NLTEST.EXE */
56
57 #define LOGON_CTRL_IN_SYNC          0x00
58 #define LOGON_CTRL_REPL_NEEDED      0x01
59 #define LOGON_CTRL_REPL_IN_PROGRESS 0x02
60
61 NTSTATUS _net_logon_ctrl(pipes_struct *p, NET_Q_LOGON_CTRL *q_u, 
62                        NET_R_LOGON_CTRL *r_u)
63 {
64         uint32 flags = 0x0;
65         uint32 pdc_connection_status = 0x00; /* Maybe a win32 error code? */
66         
67         /* Setup the Logon Control response */
68
69         init_net_r_logon_ctrl(r_u, q_u->query_level, flags, 
70                               pdc_connection_status);
71
72         return r_u->status;
73 }
74
75 /****************************************************************************
76 Send a message to smbd to do a sam synchronisation
77 **************************************************************************/
78 static void send_sync_message(void)
79 {
80         TDB_CONTEXT *tdb;
81
82         tdb = tdb_open_log(lock_path("connections.tdb"), 0,
83                            TDB_DEFAULT, O_RDONLY, 0);
84
85         if (!tdb) {
86                 DEBUG(3, ("send_sync_message(): failed to open connections "
87                           "database\n"));
88                 return;
89         }
90
91         DEBUG(3, ("sending sam synchronisation message\n"));
92         
93         message_send_all(tdb, MSG_SMB_SAM_SYNC, NULL, 0, False, NULL);
94
95         tdb_close(tdb);
96 }
97
98 /*************************************************************************
99  net_reply_logon_ctrl2:
100  *************************************************************************/
101
102 NTSTATUS _net_logon_ctrl2(pipes_struct *p, NET_Q_LOGON_CTRL2 *q_u, NET_R_LOGON_CTRL2 *r_u)
103 {
104         uint32 flags = 0x0;
105         uint32 pdc_connection_status = 0x0;
106         uint32 logon_attempts = 0x0;
107         uint32 tc_status = ERROR_NO_LOGON_SERVERS;
108         const char *trusted_domain = "test_domain";
109
110         DEBUG(0, ("*** net long ctrl2 %d, %d, %d\n",
111                   q_u->function_code, q_u->query_level, q_u->switch_value));
112
113         DEBUG(6,("_net_logon_ctrl2: %d\n", __LINE__));
114
115
116         /* set up the Logon Control2 response */
117         init_net_r_logon_ctrl2(r_u, q_u->query_level,
118                                flags, pdc_connection_status, logon_attempts,
119                                tc_status, trusted_domain);
120
121         if (lp_server_role() == ROLE_DOMAIN_BDC)
122                 send_sync_message();
123
124         DEBUG(6,("_net_logon_ctrl2: %d\n", __LINE__));
125
126         return r_u->status;
127 }
128
129 /*************************************************************************
130  net_reply_trust_dom_list:
131  *************************************************************************/
132
133 NTSTATUS _net_trust_dom_list(pipes_struct *p, NET_Q_TRUST_DOM_LIST *q_u, NET_R_TRUST_DOM_LIST *r_u)
134 {
135         const char *trusted_domain = "test_domain";
136         uint32 num_trust_domains = 1;
137
138         DEBUG(6,("_net_trust_dom_list: %d\n", __LINE__));
139
140         /* set up the Trusted Domain List response */
141         init_r_trust_dom(r_u, num_trust_domains, trusted_domain);
142
143         DEBUG(6,("_net_trust_dom_list: %d\n", __LINE__));
144
145         return r_u->status;
146 }
147
148 /***********************************************************************************
149  init_net_r_srv_pwset:
150  ***********************************************************************************/
151
152 static void init_net_r_srv_pwset(NET_R_SRV_PWSET *r_s,
153                                  DOM_CRED *srv_cred, NTSTATUS status)  
154 {
155         DEBUG(5,("init_net_r_srv_pwset: %d\n", __LINE__));
156
157         memcpy(&r_s->srv_cred, srv_cred, sizeof(r_s->srv_cred));
158         r_s->status = status;
159
160         DEBUG(5,("init_net_r_srv_pwset: %d\n", __LINE__));
161 }
162
163 /******************************************************************
164  gets a machine password entry.  checks access rights of the host.
165  ******************************************************************/
166
167 static BOOL get_md4pw(char *md4pw, char *mach_acct)
168 {
169         SAM_ACCOUNT *sampass = NULL;
170         const uint8 *pass;
171         BOOL ret;
172         uint32 acct_ctrl;
173
174 #if 0
175     /*
176      * Currently this code is redundent as we already have a filter
177      * by hostname list. What this code really needs to do is to 
178      * get a hosts allowed/hosts denied list from the SAM database
179      * on a per user basis, and make the access decision there.
180      * I will leave this code here for now as a reminder to implement
181      * this at a later date. JRA.
182      */
183
184         if (!allow_access(lp_domain_hostsdeny(), lp_domain_hostsallow(),
185                           client_name(), client_addr()))
186         {
187                 DEBUG(0,("get_md4pw: Workstation %s denied access to domain\n", mach_acct));
188                 return False;
189         }
190 #endif /* 0 */
191
192         if(!NT_STATUS_IS_OK(pdb_init_sam(&sampass)))
193                 return False;
194
195         /* JRA. This is ok as it is only used for generating the challenge. */
196         become_root();
197         ret=pdb_getsampwnam(sampass, mach_acct);
198         unbecome_root();
199  
200         if (ret==False) {
201                 DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct));
202                 pdb_free_sam(&sampass);
203                 return False;
204         }
205
206         acct_ctrl = pdb_get_acct_ctrl(sampass);
207         if (!(acct_ctrl & ACB_DISABLED) &&
208             ((acct_ctrl & ACB_DOMTRUST) ||
209              (acct_ctrl & ACB_WSTRUST) ||
210              (acct_ctrl & ACB_SVRTRUST)) &&
211             ((pass=pdb_get_nt_passwd(sampass)) != NULL)) {
212                 memcpy(md4pw, pass, 16);
213                 dump_data(5, md4pw, 16);
214                 pdb_free_sam(&sampass);
215                 return True;
216         }
217         
218         DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct));
219         pdb_free_sam(&sampass);
220         return False;
221
222 }
223
224 /*************************************************************************
225  _net_req_chal
226  *************************************************************************/
227
228 NTSTATUS _net_req_chal(pipes_struct *p, NET_Q_REQ_CHAL *q_u, NET_R_REQ_CHAL *r_u)
229 {
230         NTSTATUS status = NT_STATUS_OK;
231
232         rpcstr_pull(p->dc.remote_machine,q_u->uni_logon_clnt.buffer,sizeof(fstring),q_u->uni_logon_clnt.uni_str_len*2,0);
233
234         /* create a server challenge for the client */
235         /* Set these to random values. */
236         generate_random_buffer(p->dc.srv_chal.data, 8, False);
237         
238         memcpy(p->dc.srv_cred.challenge.data, p->dc.srv_chal.data, 8);
239
240         memcpy(p->dc.clnt_chal.data          , q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
241         memcpy(p->dc.clnt_cred.challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
242
243         memset((char *)p->dc.sess_key, '\0', sizeof(p->dc.sess_key));
244
245         p->dc.challenge_sent = True;
246         /* set up the LSA REQUEST CHALLENGE response */
247         init_net_r_req_chal(r_u, &p->dc.srv_chal, status);
248         
249         return status;
250 }
251
252 /*************************************************************************
253  init_net_r_auth:
254  *************************************************************************/
255
256 static void init_net_r_auth(NET_R_AUTH *r_a, DOM_CHAL *resp_cred, NTSTATUS status)
257 {
258         memcpy(r_a->srv_chal.data, resp_cred->data, sizeof(resp_cred->data));
259         r_a->status = status;
260 }
261
262 /*************************************************************************
263  _net_auth
264  *************************************************************************/
265
266 NTSTATUS _net_auth(pipes_struct *p, NET_Q_AUTH *q_u, NET_R_AUTH *r_u)
267 {
268         NTSTATUS status = NT_STATUS_OK;
269         DOM_CHAL srv_cred;
270         UTIME srv_time;
271         fstring mach_acct;
272
273         srv_time.time = 0;
274
275         rpcstr_pull(mach_acct, q_u->clnt_id.uni_acct_name.buffer,sizeof(fstring),q_u->clnt_id.uni_acct_name.uni_str_len*2,0);
276
277         if (p->dc.challenge_sent && get_md4pw((char *)p->dc.md4pw, mach_acct)) {
278
279                 /* from client / server challenges and md4 password, generate sess key */
280                 cred_session_key(&p->dc.clnt_chal, &p->dc.srv_chal,
281                                  p->dc.md4pw, p->dc.sess_key);
282                 
283                 /* check that the client credentials are valid */
284                 if (cred_assert(&q_u->clnt_chal, p->dc.sess_key, &p->dc.clnt_cred.challenge, srv_time)) {
285                         
286                         /* create server challenge for inclusion in the reply */
287                         cred_create(p->dc.sess_key, &p->dc.srv_cred.challenge, srv_time, &srv_cred);
288                 
289                         /* copy the received client credentials for use next time */
290                         memcpy(p->dc.clnt_cred.challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
291                         memcpy(p->dc.srv_cred .challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
292                         
293                         /* Save the machine account name. */
294                         fstrcpy(p->dc.mach_acct, mach_acct);
295                 
296                         p->dc.authenticated = True;
297
298                 } else {
299                         status = NT_STATUS_ACCESS_DENIED;
300                 }
301         } else {
302                 status = NT_STATUS_ACCESS_DENIED;
303         }
304         
305         /* set up the LSA AUTH response */
306         init_net_r_auth(r_u, &srv_cred, status);
307
308         return r_u->status;
309 }
310
311 /*************************************************************************
312  init_net_r_auth_2:
313  *************************************************************************/
314
315 static void init_net_r_auth_2(NET_R_AUTH_2 *r_a,
316                               DOM_CHAL *resp_cred, NEG_FLAGS *flgs, NTSTATUS status)
317 {
318         memcpy(r_a->srv_chal.data, resp_cred->data, sizeof(resp_cred->data));
319         memcpy(&r_a->srv_flgs, flgs, sizeof(r_a->srv_flgs));
320         r_a->status = status;
321 }
322
323 /*************************************************************************
324  _net_auth_2
325  *************************************************************************/
326
327 NTSTATUS _net_auth_2(pipes_struct *p, NET_Q_AUTH_2 *q_u, NET_R_AUTH_2 *r_u)
328 {
329         NTSTATUS status = NT_STATUS_OK;
330         DOM_CHAL srv_cred;
331         UTIME srv_time;
332         NEG_FLAGS srv_flgs;
333         fstring mach_acct;
334
335         srv_time.time = 0;
336
337         if ( (lp_server_schannel() == True) &&
338              ((q_u->clnt_flgs.neg_flags & NETLOGON_NEG_SCHANNEL) == 0) ) {
339
340                 /* schannel must be used, but client did not offer it. */
341                 status = NT_STATUS_ACCESS_DENIED;
342         }
343
344         rpcstr_pull(mach_acct, q_u->clnt_id.uni_acct_name.buffer,sizeof(fstring),q_u->clnt_id.uni_acct_name.uni_str_len*2,0);
345
346         if (p->dc.challenge_sent && get_md4pw((char *)p->dc.md4pw, mach_acct)) {
347                 
348                 /* from client / server challenges and md4 password, generate sess key */
349                 cred_session_key(&p->dc.clnt_chal, &p->dc.srv_chal,
350                                  p->dc.md4pw, p->dc.sess_key);
351                 
352                 /* check that the client credentials are valid */
353                 if (cred_assert(&q_u->clnt_chal, p->dc.sess_key, &p->dc.clnt_cred.challenge, srv_time)) {
354                         
355                         /* create server challenge for inclusion in the reply */
356                         cred_create(p->dc.sess_key, &p->dc.srv_cred.challenge, srv_time, &srv_cred);
357                         
358                         /* copy the received client credentials for use next time */
359                         memcpy(p->dc.clnt_cred.challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
360                         memcpy(p->dc.srv_cred .challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
361                         
362                         /* Save the machine account name. */
363                         fstrcpy(p->dc.mach_acct, mach_acct);
364                         
365                         p->dc.authenticated = True;
366
367                 } else {
368                         status = NT_STATUS_ACCESS_DENIED;
369                 }
370         } else {
371                 status = NT_STATUS_ACCESS_DENIED;
372         }
373         
374         srv_flgs.neg_flags = 0x000001ff;
375
376         if (lp_server_schannel() != False) {
377                 srv_flgs.neg_flags |= NETLOGON_NEG_SCHANNEL;
378         }
379
380         /* set up the LSA AUTH 2 response */
381         init_net_r_auth_2(r_u, &srv_cred, &srv_flgs, status);
382
383         if (NT_STATUS_IS_OK(status)) {
384                 extern struct dcinfo last_dcinfo;
385                 last_dcinfo = p->dc;
386         }
387
388         return r_u->status;
389 }
390
391 /*************************************************************************
392  _net_srv_pwset
393  *************************************************************************/
394
395 NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *r_u)
396 {
397         NTSTATUS status = NT_STATUS_ACCESS_DENIED;
398         DOM_CRED srv_cred;
399         pstring workstation;
400         SAM_ACCOUNT *sampass=NULL;
401         BOOL ret = False;
402         unsigned char pwd[16];
403         int i;
404         uint32 acct_ctrl;
405
406         /* checks and updates credentials.  creates reply credentials */
407         if (!(p->dc.authenticated && deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred, &q_u->clnt_id.cred, &srv_cred)))
408                 return NT_STATUS_INVALID_HANDLE;
409
410         memcpy(&p->dc.srv_cred, &p->dc.clnt_cred, sizeof(p->dc.clnt_cred));
411
412         DEBUG(5,("_net_srv_pwset: %d\n", __LINE__));
413
414         rpcstr_pull(workstation,q_u->clnt_id.login.uni_comp_name.buffer,
415                     sizeof(workstation),q_u->clnt_id.login.uni_comp_name.uni_str_len*2,0);
416
417         DEBUG(3,("Server Password Set by Wksta:[%s] on account [%s]\n", workstation, p->dc.mach_acct));
418         
419         pdb_init_sam(&sampass);
420
421         become_root();
422         ret=pdb_getsampwnam(sampass, p->dc.mach_acct);
423         unbecome_root();
424
425         /* Ensure the account exists and is a machine account. */
426         
427         acct_ctrl = pdb_get_acct_ctrl(sampass);
428
429         if (!(ret 
430               && (acct_ctrl & ACB_WSTRUST ||
431                       acct_ctrl & ACB_SVRTRUST ||
432                       acct_ctrl & ACB_DOMTRUST))) {
433                 pdb_free_sam(&sampass);
434                 return NT_STATUS_NO_SUCH_USER;
435         }
436         
437         if (pdb_get_acct_ctrl(sampass) & ACB_DISABLED) {
438                 pdb_free_sam(&sampass);
439                 return NT_STATUS_ACCOUNT_DISABLED;
440         }
441
442         DEBUG(100,("Server password set : new given value was :\n"));
443         for(i = 0; i < 16; i++)
444                 DEBUG(100,("%02X ", q_u->pwd[i]));
445         DEBUG(100,("\n"));
446
447         cred_hash3( pwd, q_u->pwd, p->dc.sess_key, 0);
448
449         /* lies!  nt and lm passwords are _not_ the same: don't care */
450         if (!pdb_set_lanman_passwd (sampass, pwd, PDB_CHANGED)) {
451                 pdb_free_sam(&sampass);
452                 return NT_STATUS_NO_MEMORY;
453         }
454
455         if (!pdb_set_nt_passwd     (sampass, pwd, PDB_CHANGED)) {
456                 pdb_free_sam(&sampass);
457                 return NT_STATUS_NO_MEMORY;
458         }
459
460         if (!pdb_set_pass_changed_now     (sampass)) {
461                 pdb_free_sam(&sampass);
462                 /* Not quite sure what this one qualifies as, but this will do */
463                 return NT_STATUS_UNSUCCESSFUL; 
464         }
465  
466         become_root();
467         ret = pdb_update_sam_account (sampass);
468         unbecome_root();
469  
470         if (ret)
471                 status = NT_STATUS_OK;
472
473         /* set up the LSA Server Password Set response */
474         init_net_r_srv_pwset(r_u, &srv_cred, status);
475
476         pdb_free_sam(&sampass);
477         return r_u->status;
478 }
479
480
481 /*************************************************************************
482  _net_sam_logoff:
483  *************************************************************************/
484
485 NTSTATUS _net_sam_logoff(pipes_struct *p, NET_Q_SAM_LOGOFF *q_u, NET_R_SAM_LOGOFF *r_u)
486 {
487         DOM_CRED srv_cred;
488
489         if (!get_valid_user_struct(p->vuid))
490                 return NT_STATUS_NO_SUCH_USER;
491
492         /* checks and updates credentials.  creates reply credentials */
493         if (!(p->dc.authenticated && deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred, 
494                                                      &q_u->sam_id.client.cred, &srv_cred)))
495                 return NT_STATUS_INVALID_HANDLE;
496
497         memcpy(&p->dc.srv_cred, &p->dc.clnt_cred, sizeof(p->dc.clnt_cred));
498
499         /* XXXX maybe we want to say 'no', reject the client's credentials */
500         r_u->buffer_creds = 1; /* yes, we have valid server credentials */
501         memcpy(&r_u->srv_creds, &srv_cred, sizeof(r_u->srv_creds));
502
503         r_u->status = NT_STATUS_OK;
504
505         return r_u->status;
506 }
507
508
509 /*************************************************************************
510  _net_sam_logon
511  *************************************************************************/
512
513 NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *r_u)
514 {
515         NTSTATUS status = NT_STATUS_OK;
516         NET_USER_INFO_3 *usr_info = NULL;
517         NET_ID_INFO_CTR *ctr = q_u->sam_id.ctr;
518         DOM_CRED srv_cred;
519         UNISTR2 *uni_samlogon_user = NULL;
520         UNISTR2 *uni_samlogon_domain = NULL;
521         UNISTR2 *uni_samlogon_workstation = NULL;
522         fstring nt_username, nt_domain, nt_workstation;
523         auth_usersupplied_info *user_info = NULL;
524         auth_serversupplied_info *server_info = NULL;
525         extern userdom_struct current_user_info;
526         SAM_ACCOUNT *sampw;
527         struct auth_context *auth_context = NULL;
528                 
529         usr_info = (NET_USER_INFO_3 *)talloc(p->mem_ctx, sizeof(NET_USER_INFO_3));
530         if (!usr_info)
531                 return NT_STATUS_NO_MEMORY;
532
533         ZERO_STRUCTP(usr_info);
534
535         /* store the user information, if there is any. */
536         r_u->user = usr_info;
537         r_u->switch_value = 0; /* indicates no info */
538         r_u->auth_resp = 1; /* authoritative response */
539         r_u->switch_value = 3; /* indicates type of validation user info */
540  
541         if (!get_valid_user_struct(p->vuid))
542                 return NT_STATUS_NO_SUCH_USER;
543
544
545         if ( (lp_server_schannel() == True) && (!p->netsec_auth_validated) ) {
546                 /* 'server schannel = yes' should enforce use of
547                    schannel, the client did offer it in auth2, but
548                    obviously did not use it. */
549                 return NT_STATUS_ACCESS_DENIED;
550         }
551
552         /* checks and updates credentials.  creates reply credentials */
553         if (!(p->dc.authenticated && deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred, &q_u->sam_id.client.cred, &srv_cred)))
554                 return NT_STATUS_INVALID_HANDLE;
555
556         memcpy(&p->dc.srv_cred, &p->dc.clnt_cred, sizeof(p->dc.clnt_cred));
557     
558         r_u->buffer_creds = 1; /* yes, we have valid server credentials */
559         memcpy(&r_u->srv_creds, &srv_cred, sizeof(r_u->srv_creds));
560
561         /* find the username */
562     
563         switch (q_u->sam_id.logon_level) {
564         case INTERACTIVE_LOGON_TYPE:
565                 uni_samlogon_user = &ctr->auth.id1.uni_user_name;
566                 uni_samlogon_domain = &ctr->auth.id1.uni_domain_name;
567
568                 uni_samlogon_workstation = &ctr->auth.id1.uni_wksta_name;
569             
570                 DEBUG(3,("SAM Logon (Interactive). Domain:[%s].  ", lp_workgroup()));
571                 break;
572         case NET_LOGON_TYPE:
573                 uni_samlogon_user = &ctr->auth.id2.uni_user_name;
574                 uni_samlogon_domain = &ctr->auth.id2.uni_domain_name;
575                 uni_samlogon_workstation = &ctr->auth.id2.uni_wksta_name;
576             
577                 DEBUG(3,("SAM Logon (Network). Domain:[%s].  ", lp_workgroup()));
578                 break;
579         default:
580                 DEBUG(2,("SAM Logon: unsupported switch value\n"));
581                 return NT_STATUS_INVALID_INFO_CLASS;
582         } /* end switch */
583
584         rpcstr_pull(nt_username,uni_samlogon_user->buffer,sizeof(nt_username),uni_samlogon_user->uni_str_len*2,0);
585         rpcstr_pull(nt_domain,uni_samlogon_domain->buffer,sizeof(nt_domain),uni_samlogon_domain->uni_str_len*2,0);
586         rpcstr_pull(nt_workstation,uni_samlogon_workstation->buffer,sizeof(nt_workstation),uni_samlogon_workstation->uni_str_len*2,0);
587
588         DEBUG(3,("User:[%s@%s] Requested Domain:[%s]\n", nt_username, 
589                  nt_workstation, nt_domain));
590         
591         fstrcpy(current_user_info.smb_name, nt_username);
592         sub_set_smb_name(nt_username);
593      
594         DEBUG(5,("Attempting validation level %d for unmapped username %s.\n", q_u->sam_id.ctr->switch_value, nt_username));
595
596         status = NT_STATUS_OK;
597         
598         switch (ctr->switch_value) {
599         case NET_LOGON_TYPE:
600         {
601                 if (!NT_STATUS_IS_OK(status = make_auth_context_fixed(&auth_context, ctr->auth.id2.lm_chal))) {
602                         return status;
603                 }
604
605                 /* Standard challenge/response authenticaion */
606                 if (!make_user_info_netlogon_network(&user_info, 
607                                                      nt_username, nt_domain, 
608                                                      nt_workstation, 
609                                                      ctr->auth.id2.lm_chal_resp.buffer,
610                                                      ctr->auth.id2.lm_chal_resp.str_str_len,
611                                                      ctr->auth.id2.nt_chal_resp.buffer,
612                                                      ctr->auth.id2.nt_chal_resp.str_str_len)) {
613                         status = NT_STATUS_NO_MEMORY;
614                 }       
615                 break;
616         }
617         case INTERACTIVE_LOGON_TYPE:
618                 /* 'Interactive' autheticaion, supplies the password in its
619                    MD4 form, encrypted with the session key.  We will
620                    convert this to chellange/responce for the auth
621                    subsystem to chew on */
622         {
623                 const uint8 *chal;
624                 
625                 if (!NT_STATUS_IS_OK(status = make_auth_context_subsystem(&auth_context))) {
626                         return status;
627                 }
628                 
629                 chal = auth_context->get_ntlm_challenge(auth_context);
630
631                 if (!make_user_info_netlogon_interactive(&user_info, 
632                                                          nt_username, nt_domain, 
633                                                          nt_workstation, chal,
634                                                          ctr->auth.id1.lm_owf.data, 
635                                                          ctr->auth.id1.nt_owf.data, 
636                                                          p->dc.sess_key)) {
637                         status = NT_STATUS_NO_MEMORY;
638                 }
639                 break;
640         }
641         default:
642                 DEBUG(2,("SAM Logon: unsupported switch value\n"));
643                 return NT_STATUS_INVALID_INFO_CLASS;
644         } /* end switch */
645         
646         if ( NT_STATUS_IS_OK(status) ) {
647                 status = auth_context->check_ntlm_password(auth_context, 
648                         user_info, &server_info);
649         }
650
651         (auth_context->free)(&auth_context);    
652         free_user_info(&user_info);
653         
654         DEBUG(5, ("_net_sam_logon: check_password returned status %s\n", 
655                   nt_errstr(status)));
656
657         /* Check account and password */
658     
659         if (!NT_STATUS_IS_OK(status)) {
660                 free_server_info(&server_info);
661                 return status;
662         }
663
664         if (server_info->guest) {
665                 /* We don't like guest domain logons... */
666                 DEBUG(5,("_net_sam_logon: Attempted domain logon as GUEST denied.\n"));
667                 free_server_info(&server_info);
668                 return NT_STATUS_LOGON_FAILURE;
669         }
670
671         /* This is the point at which, if the login was successful, that
672            the SAM Local Security Authority should record that the user is
673            logged in to the domain.  */
674     
675         {
676                 DOM_GID *gids = NULL;
677                 const DOM_SID *user_sid = NULL;
678                 const DOM_SID *group_sid = NULL;
679                 DOM_SID domain_sid;
680                 uint32 user_rid, group_rid; 
681
682                 int num_gids = 0;
683                 pstring my_name;
684                 fstring user_sid_string;
685                 fstring group_sid_string;
686                 uchar nt_session_key[16];
687                 uchar lm_session_key[16];
688                 uchar netlogon_sess_key[16];
689
690                 sampw = server_info->sam_account;
691
692                 /* set up pointer indicating user/password failed to be found */
693                 usr_info->ptr_user_info = 0;
694
695                 user_sid = pdb_get_user_sid(sampw);
696                 group_sid = pdb_get_group_sid(sampw);
697
698                 sid_copy(&domain_sid, user_sid);
699                 sid_split_rid(&domain_sid, &user_rid);
700
701                 if (!sid_peek_check_rid(&domain_sid, group_sid, &group_rid)) {
702                         DEBUG(1, ("_net_sam_logon: user %s\\%s has user sid %s\n but group sid %s.\nThe conflicting domain portions are not supported for NETLOGON calls\n",        
703                                   pdb_get_domain(sampw), pdb_get_username(sampw),
704                                   sid_to_string(user_sid_string, user_sid),
705                                   sid_to_string(group_sid_string, group_sid)));
706                         return NT_STATUS_UNSUCCESSFUL;
707                 }
708                 
709                 pstrcpy(my_name, global_myname());
710
711                 if (!NT_STATUS_IS_OK(status 
712                                      = nt_token_to_group_list(p->mem_ctx, 
713                                                               &domain_sid, 
714                                                               server_info->ptok, 
715                                                               &num_gids, 
716                                                               &gids))) {
717                         return status;
718                 }
719
720                 ZERO_STRUCT(netlogon_sess_key);
721                 memcpy(netlogon_sess_key, p->dc.sess_key, 8);
722                 if (server_info->nt_session_key.length) {
723                         memcpy(nt_session_key, server_info->nt_session_key.data, 
724                                MIN(sizeof(nt_session_key), server_info->nt_session_key.length));
725                         SamOEMhash(nt_session_key, netlogon_sess_key, 16);
726                 }
727                 if (server_info->lm_session_key.length) {
728                         memcpy(lm_session_key, server_info->lm_session_key.data, 
729                                MIN(sizeof(lm_session_key), server_info->lm_session_key.length));
730                         SamOEMhash(lm_session_key, netlogon_sess_key, 16);
731                 }
732                 ZERO_STRUCT(netlogon_sess_key);
733                 
734                 init_net_user_info3(p->mem_ctx, usr_info, 
735                                     user_rid,
736                                     group_rid,   
737                                     pdb_get_username(sampw),
738                                     pdb_get_fullname(sampw),
739                                     pdb_get_homedir(sampw),
740                                     pdb_get_dir_drive(sampw),
741                                     pdb_get_logon_script(sampw),
742                                     pdb_get_profile_path(sampw),
743                                     pdb_get_logon_time(sampw),
744                                     get_time_t_max(),
745                                     get_time_t_max(),
746                                     pdb_get_pass_last_set_time(sampw),
747                                     pdb_get_pass_can_change_time(sampw),
748                                     pdb_get_pass_must_change_time(sampw),
749                                     
750                                     0, /* logon_count */
751                                     0, /* bad_pw_count */
752                                     num_gids,    /* uint32 num_groups */
753                                     gids    , /* DOM_GID *gids */
754                                     0x20    , /* uint32 user_flgs (?) */
755                                     server_info->nt_session_key.length ? nt_session_key : NULL,
756                                     server_info->lm_session_key.length ? lm_session_key : NULL,
757                                     my_name     , /* char *logon_srv */
758                                     pdb_get_domain(sampw),
759                                     &domain_sid,     /* DOM_SID *dom_sid */  
760                                     /* Should be users domain sid, not servers - for trusted domains */
761                                   
762                                     NULL); /* char *other_sids */
763                 ZERO_STRUCT(nt_session_key);
764                 ZERO_STRUCT(lm_session_key);
765         }
766         free_server_info(&server_info);
767         return status;
768 }
769
770 /*************************************************************************
771  _ds_enum_dom_trusts
772  *************************************************************************/
773 NTSTATUS _ds_enum_dom_trusts(pipes_struct *p, DS_Q_ENUM_DOM_TRUSTS *q_u,
774                              DS_R_ENUM_DOM_TRUSTS *r_u)
775 {
776         NTSTATUS status = NT_STATUS_OK;
777
778         /* We just return zero trusts for now. At least that way we're
779            consistent with NetTrustedDomainList which is what the fallback
780            for this function is. Both of these functions need to be
781            reworked. */
782
783         return status;
784 }