Unless the error is exactly NT_STATUS_OK, we might not have a server info, so
[kai/samba-autobuild/.git] / source / rpc_server / srv_netlog_nt.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-2001.
9  *  Copyirht  (C) Andrew Bartlett                   2001.
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *  
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *  
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25
26 /* This is the implementation of the netlogon pipe. */
27
28 #include "includes.h"
29
30 extern BOOL sam_logon_in_ssb;
31 extern pstring samlogon_user;
32 extern pstring global_myname;
33 extern DOM_SID global_sam_sid;
34
35 /*************************************************************************
36  init_net_r_req_chal:
37  *************************************************************************/
38
39 static void init_net_r_req_chal(NET_R_REQ_CHAL *r_c,
40                                 DOM_CHAL *srv_chal, NTSTATUS status)
41 {
42         DEBUG(6,("init_net_r_req_chal: %d\n", __LINE__));
43         memcpy(r_c->srv_chal.data, srv_chal->data, sizeof(srv_chal->data));
44         r_c->status = status;
45 }
46
47 /*************************************************************************
48  error messages cropping up when using nltest.exe...
49  *************************************************************************/
50
51 #define ERROR_NO_SUCH_DOMAIN   0x54b
52 #define ERROR_NO_LOGON_SERVERS 0x51f
53
54 /*************************************************************************
55  net_reply_logon_ctrl:
56  *************************************************************************/
57
58 /* Some flag values reverse engineered from NLTEST.EXE */
59
60 #define LOGON_CTRL_IN_SYNC          0x00
61 #define LOGON_CTRL_REPL_NEEDED      0x01
62 #define LOGON_CTRL_REPL_IN_PROGRESS 0x02
63
64 NTSTATUS _net_logon_ctrl(pipes_struct *p, NET_Q_LOGON_CTRL *q_u, 
65                        NET_R_LOGON_CTRL *r_u)
66 {
67         uint32 flags = 0x0;
68         uint32 pdc_connection_status = 0x00; /* Maybe a win32 error code? */
69         
70         /* Setup the Logon Control response */
71
72         init_net_r_logon_ctrl(r_u, q_u->query_level, flags, 
73                               pdc_connection_status);
74
75         return r_u->status;
76 }
77
78 /****************************************************************************
79 Send a message to smbd to do a sam synchronisation
80 **************************************************************************/
81 static void send_sync_message(void)
82 {
83         TDB_CONTEXT *tdb;
84
85         tdb = tdb_open_log(lock_path("connections.tdb"), 0,
86                            TDB_DEFAULT, O_RDONLY, 0);
87
88         if (!tdb) {
89                 DEBUG(3, ("send_sync_message(): failed to open connections "
90                           "database\n"));
91                 return;
92         }
93
94         DEBUG(3, ("sending sam synchronisation message\n"));
95         
96         message_send_all(tdb, MSG_SMB_SAM_SYNC, NULL, 0, False);
97
98         tdb_close(tdb);
99 }
100
101 /*************************************************************************
102  net_reply_logon_ctrl2:
103  *************************************************************************/
104
105 NTSTATUS _net_logon_ctrl2(pipes_struct *p, NET_Q_LOGON_CTRL2 *q_u, NET_R_LOGON_CTRL2 *r_u)
106 {
107         uint32 flags = 0x0;
108         uint32 pdc_connection_status = 0x0;
109         uint32 logon_attempts = 0x0;
110         uint32 tc_status = ERROR_NO_LOGON_SERVERS;
111         char *trusted_domain = "test_domain";
112
113         DEBUG(0, ("*** net long ctrl2 %d, %d, %d\n",
114                   q_u->function_code, q_u->query_level, q_u->switch_value));
115
116         DEBUG(6,("_net_logon_ctrl2: %d\n", __LINE__));
117
118
119         /* set up the Logon Control2 response */
120         init_net_r_logon_ctrl2(r_u, q_u->query_level,
121                                flags, pdc_connection_status, logon_attempts,
122                                tc_status, trusted_domain);
123
124         if (lp_server_role() == ROLE_DOMAIN_BDC)
125                 send_sync_message();
126
127         DEBUG(6,("_net_logon_ctrl2: %d\n", __LINE__));
128
129         return r_u->status;
130 }
131
132 /*************************************************************************
133  net_reply_trust_dom_list:
134  *************************************************************************/
135
136 NTSTATUS _net_trust_dom_list(pipes_struct *p, NET_Q_TRUST_DOM_LIST *q_u, NET_R_TRUST_DOM_LIST *r_u)
137 {
138         char *trusted_domain = "test_domain";
139         uint32 num_trust_domains = 1;
140
141         DEBUG(6,("_net_trust_dom_list: %d\n", __LINE__));
142
143         /* set up the Trusted Domain List response */
144         init_r_trust_dom(r_u, num_trust_domains, trusted_domain);
145
146         DEBUG(6,("_net_trust_dom_list: %d\n", __LINE__));
147
148         return r_u->status;
149 }
150
151 /***********************************************************************************
152  init_net_r_srv_pwset:
153  ***********************************************************************************/
154
155 static void init_net_r_srv_pwset(NET_R_SRV_PWSET *r_s,
156                              DOM_CRED *srv_cred, NTSTATUS status)  
157 {
158         DEBUG(5,("init_net_r_srv_pwset: %d\n", __LINE__));
159
160         memcpy(&r_s->srv_cred, srv_cred, sizeof(r_s->srv_cred));
161         r_s->status = status;
162
163         DEBUG(5,("init_net_r_srv_pwset: %d\n", __LINE__));
164 }
165
166 /******************************************************************
167  gets a machine password entry.  checks access rights of the host.
168  ******************************************************************/
169
170 static BOOL get_md4pw(char *md4pw, char *mach_acct)
171 {
172         SAM_ACCOUNT *sampass = NULL;
173         const uint8 *pass;
174         BOOL ret;
175
176 #if 0
177     /*
178      * Currently this code is redundent as we already have a filter
179      * by hostname list. What this code really needs to do is to 
180      * get a hosts allowed/hosts denied list from the SAM database
181      * on a per user basis, and make the access decision there.
182      * I will leave this code here for now as a reminder to implement
183      * this at a later date. JRA.
184      */
185
186         if (!allow_access(lp_domain_hostsdeny(), lp_domain_hostsallow(),
187                           client_name(), client_addr()))
188         {
189                 DEBUG(0,("get_md4pw: Workstation %s denied access to domain\n", mach_acct));
190                 return False;
191         }
192 #endif /* 0 */
193
194         if(!pdb_init_sam(&sampass))
195                 return False;
196
197         /* JRA. This is ok as it is only used for generating the challenge. */
198         become_root();
199         ret=pdb_getsampwnam(sampass, mach_acct);
200         unbecome_root();
201  
202         if (ret==False) {
203                 DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct));
204                 pdb_free_sam(&sampass);
205                 return False;
206         }
207
208         if (!(pdb_get_acct_ctrl(sampass) & ACB_DISABLED) && ((pass=pdb_get_nt_passwd(sampass)) != NULL)) {
209                 memcpy(md4pw, pass, 16);
210                 dump_data(5, md4pw, 16);
211                 pdb_free_sam(&sampass);
212                 return True;
213         }
214         
215         DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct));
216         pdb_free_sam(&sampass);
217         return False;
218
219 }
220
221 /*************************************************************************
222  _net_req_chal
223  *************************************************************************/
224
225 NTSTATUS _net_req_chal(pipes_struct *p, NET_Q_REQ_CHAL *q_u, NET_R_REQ_CHAL *r_u)
226 {
227         NTSTATUS status = NT_STATUS_OK;
228         fstring mach_acct;
229
230         if (!get_valid_user_struct(p->vuid))
231                 return NT_STATUS_NO_SUCH_USER;
232
233         rpcstr_pull(mach_acct,q_u->uni_logon_clnt.buffer,sizeof(fstring),q_u->uni_logon_clnt.uni_str_len*2,0);
234
235         strlower(mach_acct);
236         fstrcat(mach_acct, "$");
237
238         if (get_md4pw((char *)p->dc.md4pw, mach_acct)) {
239                 /* copy the client credentials */
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                 /* create a server challenge for the client */
244                 /* Set these to random values. */
245                 generate_random_buffer(p->dc.srv_chal.data, 8, False);
246
247                 memcpy(p->dc.srv_cred.challenge.data, p->dc.srv_chal.data, 8);
248
249                 memset((char *)p->dc.sess_key, '\0', sizeof(p->dc.sess_key));
250
251                 /* from client / server challenges and md4 password, generate sess key */
252                 cred_session_key(&p->dc.clnt_chal, &p->dc.srv_chal,
253                                  (char *)p->dc.md4pw, p->dc.sess_key);
254
255                 /* Save the machine account name. */
256                 fstrcpy(p->dc.mach_acct, mach_acct);
257
258         } else {
259                 /* lkclXXXX take a guess at a good error message to return :-) */
260                 status = NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT;
261         }
262
263         /* set up the LSA REQUEST CHALLENGE response */
264         init_net_r_req_chal(r_u, &p->dc.srv_chal, status);
265
266         return r_u->status;
267 }
268
269 /*************************************************************************
270  init_net_r_auth:
271  *************************************************************************/
272
273 static void init_net_r_auth(NET_R_AUTH *r_a, DOM_CHAL *resp_cred, NTSTATUS status)
274 {
275         memcpy(r_a->srv_chal.data, resp_cred->data, sizeof(resp_cred->data));
276         r_a->status = status;
277 }
278
279 /*************************************************************************
280  _net_auth
281  *************************************************************************/
282
283 NTSTATUS _net_auth(pipes_struct *p, NET_Q_AUTH *q_u, NET_R_AUTH *r_u)
284 {
285         NTSTATUS status = NT_STATUS_OK;
286         DOM_CHAL srv_cred;
287         UTIME srv_time;
288
289         if (!get_valid_user_struct(p->vuid))
290                 return NT_STATUS_NO_SUCH_USER;
291
292         srv_time.time = 0;
293
294         /* check that the client credentials are valid */
295         if (cred_assert(&q_u->clnt_chal, p->dc.sess_key, &p->dc.clnt_cred.challenge, srv_time)) {
296
297                 /* create server challenge for inclusion in the reply */
298                 cred_create(p->dc.sess_key, &p->dc.srv_cred.challenge, srv_time, &srv_cred);
299
300                 /* copy the received client credentials for use next time */
301                 memcpy(p->dc.clnt_cred.challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
302                 memcpy(p->dc.srv_cred .challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
303         } else {
304                 status = NT_STATUS_ACCESS_DENIED;
305         }
306
307         /* set up the LSA AUTH 2 response */
308         init_net_r_auth(r_u, &srv_cred, status);
309
310         return r_u->status;
311 }
312
313 /*************************************************************************
314  init_net_r_auth_2:
315  *************************************************************************/
316
317 static void init_net_r_auth_2(NET_R_AUTH_2 *r_a,
318                               DOM_CHAL *resp_cred, NEG_FLAGS *flgs, NTSTATUS status)
319 {
320         memcpy(r_a->srv_chal.data, resp_cred->data, sizeof(resp_cred->data));
321         memcpy(&r_a->srv_flgs, flgs, sizeof(r_a->srv_flgs));
322         r_a->status = status;
323 }
324
325 /*************************************************************************
326  _net_auth_2
327  *************************************************************************/
328
329 NTSTATUS _net_auth_2(pipes_struct *p, NET_Q_AUTH_2 *q_u, NET_R_AUTH_2 *r_u)
330 {
331         NTSTATUS status = NT_STATUS_OK;
332         DOM_CHAL srv_cred;
333         UTIME srv_time;
334         NEG_FLAGS srv_flgs;
335
336         if (!get_valid_user_struct(p->vuid))
337                 return NT_STATUS_NO_SUCH_USER;
338
339         srv_time.time = 0;
340
341         /* check that the client credentials are valid */
342         if (cred_assert(&q_u->clnt_chal, p->dc.sess_key, &p->dc.clnt_cred.challenge, srv_time)) {
343
344                 /* create server challenge for inclusion in the reply */
345                 cred_create(p->dc.sess_key, &p->dc.srv_cred.challenge, srv_time, &srv_cred);
346
347                 /* copy the received client credentials for use next time */
348                 memcpy(p->dc.clnt_cred.challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
349                 memcpy(p->dc.srv_cred .challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data));
350         } else {
351                 status = NT_STATUS_ACCESS_DENIED;
352         }
353
354         srv_flgs.neg_flags = 0x000001ff;
355
356         /* set up the LSA AUTH 2 response */
357         init_net_r_auth_2(r_u, &srv_cred, &srv_flgs, status);
358
359         return r_u->status;
360 }
361
362 /*************************************************************************
363  _net_srv_pwset
364  *************************************************************************/
365
366 NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *r_u)
367 {
368         NTSTATUS status = NT_STATUS_WRONG_PASSWORD;
369         DOM_CRED srv_cred;
370         pstring mach_acct;
371         SAM_ACCOUNT *sampass=NULL;
372         BOOL ret = False;
373         unsigned char pwd[16];
374         int i;
375
376         if (!get_valid_user_struct(p->vuid))
377                 return NT_STATUS_NO_SUCH_USER;
378
379         /* checks and updates credentials.  creates reply credentials */
380         if (!deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred, &q_u->clnt_id.cred, &srv_cred))
381                 return NT_STATUS_INVALID_HANDLE;
382
383         memcpy(&p->dc.srv_cred, &p->dc.clnt_cred, sizeof(p->dc.clnt_cred));
384
385         DEBUG(5,("_net_srv_pwset: %d\n", __LINE__));
386
387         rpcstr_pull(mach_acct,q_u->clnt_id.login.uni_acct_name.buffer,
388                         sizeof(mach_acct),q_u->clnt_id.login.uni_acct_name.uni_str_len*2,0);
389
390         DEBUG(3,("Server Password Set Wksta:[%s]\n", mach_acct));
391         
392         /*
393          * Check the machine account name we're changing is the same
394          * as the one we've authenticated from. This prevents arbitrary
395          * machines changing other machine account passwords.
396          */
397
398         if (!strequal(mach_acct, p->dc.mach_acct)) {
399                 return NT_STATUS_ACCESS_DENIED;
400         }
401
402         pdb_init_sam(&sampass);
403
404         become_root();
405         ret=pdb_getsampwnam(sampass, mach_acct);
406         unbecome_root();
407
408         /* Ensure the account exists and is a machine account. */
409
410         if (ret==False || !(pdb_get_acct_ctrl(sampass) & ACB_WSTRUST)) {
411                 pdb_free_sam(&sampass);
412                 return NT_STATUS_NO_SUCH_USER;
413         }
414         
415         DEBUG(100,("Server password set : new given value was :\n"));
416         for(i = 0; i < 16; i++)
417                 DEBUG(100,("%02X ", q_u->pwd[i]));
418         DEBUG(100,("\n"));
419
420         cred_hash3( pwd, q_u->pwd, p->dc.sess_key, 0);
421
422         /* lies!  nt and lm passwords are _not_ the same: don't care */
423         if (!pdb_set_lanman_passwd (sampass, pwd)) {
424                 pdb_free_sam(&sampass);
425                 return NT_STATUS_NO_MEMORY;
426         }
427
428         if (!pdb_set_nt_passwd     (sampass, pwd)) {
429                 pdb_free_sam(&sampass);
430                 return NT_STATUS_NO_MEMORY;
431         }
432
433         if (!pdb_set_acct_ctrl     (sampass, ACB_WSTRUST)) {
434                 pdb_free_sam(&sampass);
435                 /* Not quite sure what this one qualifies as, but this will do */
436                 return NT_STATUS_NO_MEMORY; 
437         }
438  
439         if (!pdb_set_pass_changed_now     (sampass)) {
440                 pdb_free_sam(&sampass);
441                 /* Not quite sure what this one qualifies as, but this will do */
442                 return NT_STATUS_NO_MEMORY; 
443         }
444  
445         become_root();
446         ret = pdb_update_sam_account (sampass,False);
447         unbecome_root();
448  
449         if (ret)
450                 status = NT_STATUS_OK;
451
452         /* set up the LSA Server Password Set response */
453         init_net_r_srv_pwset(r_u, &srv_cred, status);
454
455         pdb_free_sam(&sampass);
456         return r_u->status;
457 }
458
459
460 /*************************************************************************
461  _net_sam_logoff:
462  *************************************************************************/
463
464 NTSTATUS _net_sam_logoff(pipes_struct *p, NET_Q_SAM_LOGOFF *q_u, NET_R_SAM_LOGOFF *r_u)
465 {
466         DOM_CRED srv_cred;
467
468         if (!get_valid_user_struct(p->vuid))
469                 return NT_STATUS_NO_SUCH_USER;
470
471         /* checks and updates credentials.  creates reply credentials */
472         if (!deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred, 
473                         &q_u->sam_id.client.cred, &srv_cred))
474                 return NT_STATUS_INVALID_HANDLE;
475
476         memcpy(&p->dc.srv_cred, &p->dc.clnt_cred, sizeof(p->dc.clnt_cred));
477
478         /* XXXX maybe we want to say 'no', reject the client's credentials */
479         r_u->buffer_creds = 1; /* yes, we have valid server credentials */
480         memcpy(&r_u->srv_creds, &srv_cred, sizeof(r_u->srv_creds));
481
482         r_u->status = NT_STATUS_OK;
483
484         return r_u->status;
485 }
486
487
488 /*************************************************************************
489  _net_sam_logon
490  *************************************************************************/
491
492 NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *r_u)
493 {
494         NTSTATUS status = NT_STATUS_OK;
495         NET_USER_INFO_3 *usr_info = NULL;
496         NET_ID_INFO_CTR *ctr = q_u->sam_id.ctr;
497         DOM_CRED srv_cred;
498         UNISTR2 *uni_samlogon_user = NULL;
499         UNISTR2 *uni_samlogon_domain = NULL;
500         UNISTR2 *uni_samlogon_workstation = NULL;
501         fstring nt_username, nt_domain, nt_workstation;
502         auth_usersupplied_info *user_info = NULL;
503         auth_serversupplied_info *server_info = NULL;
504                 
505         usr_info = (NET_USER_INFO_3 *)talloc(p->mem_ctx, sizeof(NET_USER_INFO_3));
506         if (!usr_info)
507                 return NT_STATUS_NO_MEMORY;
508
509         ZERO_STRUCTP(usr_info);
510  
511         if (!get_valid_user_struct(p->vuid))
512                 return NT_STATUS_NO_SUCH_USER;
513     
514         /* checks and updates credentials.  creates reply credentials */
515         if (!deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred, &q_u->sam_id.client.cred, &srv_cred))
516                 return NT_STATUS_INVALID_HANDLE;
517         else
518                 memcpy(&p->dc.srv_cred, &p->dc.clnt_cred, sizeof(p->dc.clnt_cred));
519     
520         r_u->buffer_creds = 1; /* yes, we have valid server credentials */
521         memcpy(&r_u->srv_creds, &srv_cred, sizeof(r_u->srv_creds));
522
523         /* store the user information, if there is any. */
524         r_u->user = usr_info;
525         r_u->switch_value = 0; /* indicates no info */
526         r_u->auth_resp = 1; /* authoritative response */
527         r_u->switch_value = 3; /* indicates type of validation user info */
528
529         /* find the username */
530     
531         switch (q_u->sam_id.logon_level) {
532         case INTERACTIVE_LOGON_TYPE:
533                 uni_samlogon_user = &ctr->auth.id1.uni_user_name;
534                 uni_samlogon_domain = &ctr->auth.id1.uni_domain_name;
535
536                 uni_samlogon_workstation = &ctr->auth.id1.uni_wksta_name;
537             
538                 DEBUG(3,("SAM Logon (Interactive). Domain:[%s].  ", lp_workgroup()));
539                 break;
540         case NET_LOGON_TYPE:
541                 uni_samlogon_user = &ctr->auth.id2.uni_user_name;
542                 uni_samlogon_domain = &ctr->auth.id2.uni_domain_name;
543                 uni_samlogon_workstation = &ctr->auth.id2.uni_wksta_name;
544             
545                 DEBUG(3,("SAM Logon (Network). Domain:[%s].  ", lp_workgroup()));
546                 break;
547         default:
548                 DEBUG(2,("SAM Logon: unsupported switch value\n"));
549                 return NT_STATUS_INVALID_INFO_CLASS;
550         } /* end switch */
551
552         /* check username exists */
553
554         rpcstr_pull(nt_username,uni_samlogon_user->buffer,sizeof(nt_username),uni_samlogon_user->uni_str_len*2,0);
555         rpcstr_pull(nt_domain,uni_samlogon_domain->buffer,sizeof(nt_domain),uni_samlogon_domain->uni_str_len*2,0);
556         rpcstr_pull(nt_workstation,uni_samlogon_workstation->buffer,sizeof(nt_workstation),uni_samlogon_workstation->uni_str_len*2,0);
557
558         DEBUG(3,("User:[%s@%s] Requested Domain:[%s]\n", nt_username, 
559                  nt_workstation, nt_domain));
560         
561         /*
562          * Convert to a UNIX username.
563          */
564
565         DEBUG(5,("Attempting validation level %d for unmapped username %s.\n", q_u->sam_id.ctr->switch_value, nt_username));
566
567         switch (ctr->switch_value) {
568         case NET_LOGON_TYPE:
569         {
570                 auth_authsupplied_info *auth_info = NULL;
571                 make_auth_info_fixed(&auth_info, ctr->auth.id2.lm_chal);
572                 /* Standard challange/response authenticaion */
573                 make_user_info_netlogon_network(&user_info, 
574                                                 nt_username, nt_domain, 
575                                                 nt_workstation, 
576                                                 ctr->auth.id2.lm_chal_resp.buffer,
577                                                 ctr->auth.id2.lm_chal_resp.str_str_len,
578                                                 ctr->auth.id2.nt_chal_resp.buffer,
579                                                 ctr->auth.id2.nt_chal_resp.str_str_len);
580
581                 status = check_password(user_info, auth_info, &server_info);
582                 free_auth_info(&auth_info);
583                         
584                 break;
585         }
586         case INTERACTIVE_LOGON_TYPE:
587                 /* 'Interactive' autheticaion, supplies the password in its MD4 form, encrypted
588                    with the session key.  We will convert this to challange/responce for the 
589                    auth subsystem to chew on */
590         {
591                 auth_authsupplied_info *auth_info = NULL;
592                 DATA_BLOB chal;
593                 if (!make_auth_info_subsystem(&auth_info)) {
594                         return NT_STATUS_NO_MEMORY;
595                 }
596                 
597                 chal = auth_get_challange(auth_info);
598
599                 make_user_info_netlogon_interactive(&user_info, 
600                                                     nt_username, nt_domain, 
601                                                     nt_workstation, chal.data,
602                                                     ctr->auth.id1.lm_owf.data, 
603                                                     ctr->auth.id1.nt_owf.data, 
604                                                     p->dc.sess_key);
605                 status = check_password(user_info, auth_info, &server_info);
606                 data_blob_free(&chal);
607                 free_auth_info(&auth_info);
608
609                 break;
610         }
611         default:
612                 DEBUG(2,("SAM Logon: unsupported switch value\n"));
613                 return NT_STATUS_INVALID_INFO_CLASS;
614         } /* end switch */
615         
616         free_user_info(&user_info);
617         
618         DEBUG(5, ("_net_sam_logon: check_password returned status %s\n", 
619                   get_nt_error_msg(status)));
620
621         /* Check account and password */
622     
623         if (!NT_STATUS_IS_OK(status)) {
624                 free_server_info(&server_info);
625                 return status;
626         }
627
628         if (server_info->guest) {
629                 /* We don't like guest domain logons... */
630                 DEBUG(5,("_net_sam_logon: Attempted domain logon as GUEST denied.\n"));
631                 free_server_info(&server_info);
632                 return NT_STATUS_LOGON_FAILURE;
633         }
634
635         /* This is the point at which, if the login was successful, that
636            the SAM Local Security Authority should record that the user is
637            logged in to the domain.  */
638     
639         {
640                 DOM_GID *gids = NULL;
641                 int num_gids = 0;
642                 pstring my_name;
643                 pstring my_workgroup;
644                 pstring domain_groups;
645         
646                 /* set up pointer indicating user/password failed to be found */
647                 usr_info->ptr_user_info = 0;
648         
649                 /* XXXX hack to get standard_sub_basic() to use sam logon username */
650                 /* possibly a better way would be to do a change_to_user() call */
651                 sam_logon_in_ssb = True;
652                 pstrcpy(samlogon_user, nt_username);
653
654                 pstrcpy(my_workgroup, lp_workgroup());
655                 pstrcpy(my_name, global_myname);
656                 strupper(my_name);
657
658                 /*
659                  * This is the point at which we get the group
660                  * database - we should be getting the gid_t list
661                  * from /etc/group and then turning the uids into
662                  * rids and then into machine sids for this user.
663                  * JRA.
664                  */
665
666                 *domain_groups = 0;
667   
668                 get_domain_user_groups(domain_groups, nt_username);
669         
670                 /*
671                  * make_dom_gids allocates the gids array. JRA.
672                  */
673                 gids = NULL;
674                 num_gids = make_dom_gids(p->mem_ctx, domain_groups, &gids);
675         
676                 sam_logon_in_ssb = False;
677         
678                 init_net_user_info3(p->mem_ctx, usr_info, server_info->sam_account,
679                             0, /* logon_count */
680                             0, /* bad_pw_count */
681                             num_gids,    /* uint32 num_groups */
682                             gids    , /* DOM_GID *gids */
683                             0x20    , /* uint32 user_flgs (?) */
684                             NULL, /* uchar sess_key[16] */
685                             my_name     , /* char *logon_srv */
686                             my_workgroup, /* char *logon_dom */
687                             &global_sam_sid,     /* DOM_SID *dom_sid */
688                             NULL); /* char *other_sids */
689         }
690         free_server_info(&server_info);
691         return status;
692 }
693
694