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