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