includes.h: Added John's redhat fix for QSORT_CAST.
[samba.git] / source / 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                 /* PAXX: set these to random values. */
293                 /* lkcl: paul, you mentioned that it doesn't really matter much */
294                 SIVAL(vuser->dc.srv_chal.data, 0, 0x11111111);
295                 SIVAL(vuser->dc.srv_chal.data, 4, 0x11111111);
296                 memcpy(vuser->dc.srv_cred.challenge.data, vuser->dc.srv_chal.data, 8);
297
298                 bzero(vuser->dc.sess_key, sizeof(vuser->dc.sess_key));
299
300                 /* from client / server challenges and md4 password, generate sess key */
301                 cred_session_key(&(vuser->dc.clnt_chal), &(vuser->dc.srv_chal),
302                                                    vuser->dc.md4pw, vuser->dc.sess_key);
303         }
304         else
305         {
306                 /* lkclXXXX take a guess at a good error message to return :-) */
307                 status = 0xC0000000 | NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT;
308         }
309
310         /* construct reply. */
311         net_reply_req_chal(&q_r, rdata,
312                                         &(vuser->dc.srv_chal), status);
313
314 }
315
316 /*************************************************************************
317  api_net_auth_2:
318  *************************************************************************/
319 static void api_net_auth_2( int uid,
320                             prs_struct *data,
321                             prs_struct *rdata)
322 {
323         NET_Q_AUTH_2 q_a;
324         uint32 status = 0x0;
325
326         DOM_CHAL srv_cred;
327         UTIME srv_time;
328
329         user_struct *vuser;
330
331         if ((vuser = get_valid_user_struct(uid)) == NULL) return;
332
333         srv_time.time = 0;
334
335         /* grab the challenge... */
336         net_io_q_auth_2("", &q_a, data, 0);
337
338         /* check that the client credentials are valid */
339         if (cred_assert(&(q_a.clnt_chal), vuser->dc.sess_key,
340                     &(vuser->dc.clnt_cred.challenge), srv_time))
341         {
342
343                 /* create server challenge for inclusion in the reply */
344                 cred_create(vuser->dc.sess_key, &(vuser->dc.srv_cred.challenge), srv_time, &srv_cred);
345
346                 /* copy the received client credentials for use next time */
347                 memcpy(vuser->dc.clnt_cred.challenge.data, &(q_a.clnt_chal.data), sizeof(q_a.clnt_chal.data));
348                 memcpy(vuser->dc.srv_cred.challenge.data, &(q_a.clnt_chal.data), sizeof(q_a.clnt_chal.data));
349         }
350         else
351         {
352                 status = NT_STATUS_ACCESS_DENIED | 0xC0000000;
353         }
354
355         /* construct reply. */
356         net_reply_auth_2(&q_a, rdata, &srv_cred, status);
357 }
358
359
360 /*************************************************************************
361  api_net_srv_pwset:
362  *************************************************************************/
363 static void api_net_srv_pwset( int uid,
364                                prs_struct *data,
365                                prs_struct *rdata)
366 {
367         NET_Q_SRV_PWSET q_a;
368         uint32 status = NT_STATUS_WRONG_PASSWORD|0xC0000000;
369         DOM_CRED srv_cred;
370         pstring mach_acct;
371         struct smb_passwd *smb_pass;
372         BOOL ret;
373         user_struct *vuser;
374
375         if ((vuser = get_valid_user_struct(uid)) == NULL) return;
376
377         /* grab the challenge and encrypted password ... */
378         net_io_q_srv_pwset("", &q_a, data, 0);
379
380         /* checks and updates credentials.  creates reply credentials */
381         if (deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred), 
382                         &(q_a.clnt_id.cred), &srv_cred))
383         {
384                 memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred));
385
386                 DEBUG(5,("api_net_srv_pwset: %d\n", __LINE__));
387
388                 pstrcpy(mach_acct, unistrn2(q_a.clnt_id.login.uni_acct_name.buffer,
389                                                                         q_a.clnt_id.login.uni_acct_name.uni_str_len));
390
391                 DEBUG(3,("Server Password Set Wksta:[%s]\n", mach_acct));
392
393                 become_root(True);
394                 smb_pass = getsmbpwnam(mach_acct);
395                 unbecome_root(True);
396
397                 if (smb_pass != NULL)
398                 {
399                   unsigned char pwd[16];
400                   int i;
401
402                   DEBUG(100,("Server password set : new given value was :\n"));
403                   for(i = 0; i < 16; i++)
404                     DEBUG(100,("%02X ", q_a.pwd[i]));
405                   DEBUG(100,("\n"));
406
407                   cred_hash3( pwd, q_a.pwd, vuser->dc.sess_key);
408
409                   /* lies!  nt and lm passwords are _not_ the same: don't care */
410                   smb_pass->smb_passwd    = pwd;
411                   smb_pass->smb_nt_passwd = pwd;
412                   smb_pass->acct_ctrl     = ACB_WSTRUST;
413
414                   become_root(True);
415                   ret = mod_smbpwd_entry(smb_pass);
416                   unbecome_root(True);
417
418                   if (ret)
419                   {
420                     /* hooray! */
421                     status = 0x0;
422                   }
423                 }
424
425                 DEBUG(5,("api_net_srv_pwset: %d\n", __LINE__));
426
427         }
428         else
429         {
430                 /* lkclXXXX take a guess at a sensible error code to return... */
431                 status = 0xC0000000 | NT_STATUS_NETWORK_CREDENTIAL_CONFLICT;
432         }
433
434         /* Construct reply. */
435         net_reply_srv_pwset(&q_a, rdata, &srv_cred, status);
436 }
437
438
439 /*************************************************************************
440  api_net_sam_logoff:
441  *************************************************************************/
442 static void api_net_sam_logoff( int uid,
443                                prs_struct *data,
444                                prs_struct *rdata)
445 {
446         NET_Q_SAM_LOGOFF q_l;
447         NET_ID_INFO_CTR ctr;    
448
449         DOM_CRED srv_cred;
450
451         user_struct *vuser;
452
453         if ((vuser = get_valid_user_struct(uid)) == NULL) return;
454
455         /* the DOM_ID_INFO_1 structure is a bit big.  plus we might want to
456            dynamically allocate it inside net_io_q_sam_logon, at some point */
457         q_l.sam_id.ctr = &ctr;
458
459         /* grab the challenge... */
460         net_io_q_sam_logoff("", &q_l, data, 0);
461
462         /* checks and updates credentials.  creates reply credentials */
463         deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred), 
464                         &(q_l.sam_id.client.cred), &srv_cred);
465         memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred));
466
467         /* construct reply.  always indicate success */
468         net_reply_sam_logoff(&q_l, rdata,
469                                         &srv_cred,
470                         0x0);
471 }
472
473 /*************************************************************************
474  net_login_interactive:
475  *************************************************************************/
476 static uint32 net_login_interactive(NET_ID_INFO_1 *id1,
477                                 struct smb_passwd *smb_pass,
478                                 user_struct *vuser)
479 {
480         uint32 status = 0x0;
481
482         char nt_pwd[16];
483         char lm_pwd[16];
484         unsigned char key[16];
485
486         memset(key, 0, 16);
487         memcpy(key, vuser->dc.sess_key, 8);
488
489         memcpy(lm_pwd, id1->lm_owf.data, 16);
490         memcpy(nt_pwd, id1->nt_owf.data, 16);
491
492         SamOEMhash(lm_pwd, key, False);
493         SamOEMhash(nt_pwd, key, False);
494
495 #ifdef DEBUG_PASSWORD
496         DEBUG(100,("decrypt of lm owf password:"));
497         dump_data(100, lm_pwd, 16);
498
499         DEBUG(100,("decrypt of nt owf password:"));
500         dump_data(100, nt_pwd, 16);
501 #endif
502
503         if (memcmp(smb_pass->smb_passwd   , lm_pwd, 16) != 0 &&
504                 memcmp(smb_pass->smb_nt_passwd, nt_pwd, 16) != 0)
505         {
506                 status = 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
507         }
508
509         return status;
510 }
511
512 /*************************************************************************
513  net_login_network:
514  *************************************************************************/
515 static uint32 net_login_network(NET_ID_INFO_2 *id2,
516                                 struct smb_passwd *smb_pass,
517                                 user_struct *vuser)
518 {
519         DEBUG(5,("net_login_network: lm_len: %d nt_len: %d\n",
520                 id2->lm_chal_resp.str_str_len, 
521                 id2->nt_chal_resp.str_str_len));
522
523         /* JRA. Check the NT password first if it exists - this is a higher quality 
524            password, if it exists and it doesn't match - fail. */
525
526         if (id2->nt_chal_resp.str_str_len == 24 && 
527                 smb_pass->smb_nt_passwd != NULL)
528         {
529                 if(smb_password_check(id2->nt_chal_resp.buffer,
530                                    smb_pass->smb_nt_passwd,
531                            id2->lm_chal)) 
532                   return 0x0;
533                 else
534                   return 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
535         }
536
537         /* lkclXXXX this is not a good place to put disabling of LM hashes in.
538            if that is to be done, first move this entire function into a
539            library routine that calls the two smb_password_check() functions.
540            if disabling LM hashes (which nt can do for security reasons) then
541            an attempt should be made to disable them everywhere (which nt does
542            not do, for various security-hole reasons).
543          */
544
545         if (id2->lm_chal_resp.str_str_len == 24 &&
546                 smb_password_check(id2->lm_chal_resp.buffer,
547                                    smb_pass->smb_passwd,
548                                    id2->lm_chal))
549         {
550                 return 0x0;
551         }
552
553
554         /* oops! neither password check succeeded */
555
556         return 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
557 }
558
559 /*************************************************************************
560  api_net_sam_logon:
561  *************************************************************************/
562 static void api_net_sam_logon( int uid,
563                                prs_struct *data,
564                                prs_struct *rdata)
565 {
566         NET_Q_SAM_LOGON q_l;
567         NET_ID_INFO_CTR ctr;    
568         NET_USER_INFO_3 usr_info;
569         uint32 status = 0x0;
570         DOM_CRED srv_cred;
571         struct smb_passwd *smb_pass = NULL;
572         UNISTR2 *uni_samlogon_user = NULL;
573
574         user_struct *vuser = NULL;
575
576         if ((vuser = get_valid_user_struct(uid)) == NULL) return;
577
578         q_l.sam_id.ctr = &ctr;
579
580         net_io_q_sam_logon("", &q_l, data, 0);
581
582         /* checks and updates credentials.  creates reply credentials */
583         if (!deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred), 
584                         &(q_l.sam_id.client.cred), &srv_cred))
585         {
586                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
587         }
588         else
589         {
590                 memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred));
591         }
592
593         /* find the username */
594
595         if (status == 0x0)
596         {
597                 switch (q_l.sam_id.logon_level)
598                 {
599                         case 1:
600                         {
601                                 uni_samlogon_user = &(q_l.sam_id.ctr->auth.id1.uni_user_name);
602
603                                 DEBUG(3,("SAM Logon (Interactive). Domain:[%s].  ",
604                                           lp_workgroup()));
605                                 break;
606                         }
607                         case 2:
608                         {
609                                 uni_samlogon_user = &(q_l.sam_id.ctr->auth.id2.uni_user_name);
610
611                                 DEBUG(3,("SAM Logon (Network). Domain:[%s].  ",
612                                           lp_workgroup()));
613                                 break;
614                         }
615                         default:
616                         {
617                                 DEBUG(2,("SAM Logon: unsupported switch value\n"));
618                                 status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
619                                 break;
620                         }
621                 }
622         }
623
624         /* check username exists */
625
626         if (status == 0x0)
627         {
628                 pstrcpy(samlogon_user, unistrn2(uni_samlogon_user->buffer,
629                                                 uni_samlogon_user->uni_str_len));
630
631                 DEBUG(3,("User:[%s]\n", samlogon_user));
632
633                 become_root(True);
634                 smb_pass = getsmbpwnam(samlogon_user);
635                 unbecome_root(True);
636
637                 if (smb_pass == NULL)
638                 {
639                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
640                 }
641         }
642
643         /* validate password. */
644
645         if (status == 0x0)
646         {
647                 switch (q_l.sam_id.logon_level)
648                 {
649                         case 1:
650                         {
651                                 /* interactive login.  passwords arcfour'd with session key */
652                                 status = net_login_interactive(&q_l.sam_id.ctr->auth.id1,
653                                                                smb_pass, vuser);
654                                 break;
655                         }
656                         case 2:
657                         {
658                                 /* network login.  lm challenge and 24 byte responses */
659                                 status = net_login_network(&q_l.sam_id.ctr->auth.id2,
660                                                            smb_pass, vuser);
661                                 break;
662                         }
663                 }
664         }
665         
666         /* lkclXXXX this is the point at which, if the login was
667            successful, that the SAM Local Security Authority should
668            record that the user is logged in to the domain.
669          */
670
671         /* return the profile plus other bits :-) */
672
673         if (status == 0x0)
674         {
675                 DOM_GID gids[LSA_MAX_GROUPS];
676                 int num_gids = 0;
677                 NTTIME dummy_time;
678                 pstring logon_script;
679                 pstring profile_path;
680                 pstring home_dir;
681                 pstring home_drive;
682                 pstring my_name;
683                 pstring my_workgroup;
684                 pstring domain_groups;
685                 pstring dom_sid;
686                 pstring other_sids;
687                 extern pstring myname;
688                 uint32 r_uid;
689                 uint32 r_gid;
690
691                 /* set up pointer indicating user/password failed to be found */
692                 usr_info.ptr_user_info = 0;
693
694                 dummy_time.low  = 0xffffffff;
695                 dummy_time.high = 0x7fffffff;
696
697                 get_myname(myname, NULL);
698
699                 /* XXXX hack to get standard_sub_basic() to use sam logon username */
700                 /* possibly a better way would be to do a become_user() call */
701                 sam_logon_in_ssb = True;
702
703                 pstrcpy(logon_script, lp_logon_script     ());
704                 pstrcpy(profile_path, lp_logon_path       ());
705                 pstrcpy(dom_sid     , lp_domain_sid       ());
706                 pstrcpy(other_sids  , lp_domain_other_sids());
707                 pstrcpy(my_workgroup, lp_workgroup        ());
708
709                 pstrcpy(home_drive  , lp_logon_drive      ());
710                 pstrcpy(home_dir    , lp_logon_home       ());
711
712                 pstrcpy(my_name     , myname                );
713                 strupper(my_name);
714
715                 get_domain_user_groups(domain_groups, samlogon_user);
716
717                 num_gids = make_dom_gids(domain_groups, gids);
718
719                 sam_logon_in_ssb = False;
720
721                 if (name_to_rid(samlogon_user, &r_uid, &r_gid))
722                 {
723                         make_net_user_info3(&usr_info,
724
725                                    &dummy_time, /* logon_time */
726                                    &dummy_time, /* logoff_time */
727                                    &dummy_time, /* kickoff_time */
728                                    &dummy_time, /* pass_last_set_time */
729                                    &dummy_time, /* pass_can_change_time */
730                                    &dummy_time, /* pass_must_change_time */
731
732                                    samlogon_user   , /* user_name */
733                                    vuser->real_name, /* full_name */
734                                    logon_script    , /* logon_script */
735                                    profile_path    , /* profile_path */
736                                    home_dir        , /* home_dir */
737                                    home_drive      , /* dir_drive */
738
739                                    0, /* logon_count */
740                                    0, /* bad_pw_count */
741
742                                    r_uid   , /* RID user_id */
743                                    r_gid   , /* RID group_id */
744                                    num_gids,    /* uint32 num_groups */
745                                    gids    , /* DOM_GID *gids */
746                                    0x20    , /* uint32 user_flgs (?) */
747
748                                    NULL, /* char sess_key[16] */
749
750                                    my_name     , /* char *logon_srv */
751                                    my_workgroup, /* char *logon_dom */
752
753                                    dom_sid,     /* char *dom_sid */
754                                    other_sids); /* char *other_sids */
755                 }
756                 else
757                 {
758                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
759                 }
760         }
761
762         net_reply_sam_logon(&q_l, rdata, &srv_cred, &usr_info, status);
763 }
764
765
766 /*************************************************************************
767  api_net_trust_dom_list:
768  *************************************************************************/
769 static void api_net_trust_dom_list( int uid,
770                                  prs_struct *data,
771                                  prs_struct *rdata)
772 {
773         NET_Q_TRUST_DOM_LIST q_t;
774
775         char *trusted_domain = "test_domain";
776
777         DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
778
779         /* grab the lsa trusted domain list query... */
780         net_io_q_trust_dom("", &q_t, data, 0);
781
782         /* construct reply. */
783         net_reply_trust_dom_list(&q_t, rdata,
784                                 1, trusted_domain);
785
786         DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
787 }
788
789
790 /*************************************************************************
791  error messages cropping up when using nltest.exe...
792  *************************************************************************/
793 #define ERROR_NO_SUCH_DOMAIN   0x54b
794 #define ERROR_NO_LOGON_SERVERS 0x51f
795
796 /*************************************************************************
797  api_net_logon_ctrl2:
798  *************************************************************************/
799 static void api_net_logon_ctrl2( int uid,
800                                  prs_struct *data,
801                                  prs_struct *rdata)
802 {
803         NET_Q_LOGON_CTRL2 q_l;
804
805         /* lkclXXXX - guess what - absolutely no idea what these are! */
806         uint32 flags = 0x0;
807         uint32 pdc_connection_status = 0x0;
808         uint32 logon_attempts = 0x0;
809         uint32 tc_status = ERROR_NO_LOGON_SERVERS;
810         char *trusted_domain = "test_domain";
811
812         DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
813
814         /* grab the lsa netlogon ctrl2 query... */
815         net_io_q_logon_ctrl2("", &q_l, data, 0);
816
817         /* construct reply. */
818         net_reply_logon_ctrl2(&q_l, rdata,
819                                 flags, pdc_connection_status, logon_attempts,
820                                 tc_status, trusted_domain);
821
822         DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
823 }
824
825 /*******************************************************************
826  array of \PIPE\NETLOGON operations
827  ********************************************************************/
828 static struct api_struct api_net_cmds [] =
829 {
830         { "NET_REQCHAL"       , NET_REQCHAL       , api_net_req_chal       }, 
831         { "NET_AUTH2"         , NET_AUTH2         , api_net_auth_2         }, 
832         { "NET_SRVPWSET"      , NET_SRVPWSET      , api_net_srv_pwset      }, 
833         { "NET_SAMLOGON"      , NET_SAMLOGON      , api_net_sam_logon      }, 
834         { "NET_SAMLOGOFF"     , NET_SAMLOGOFF     , api_net_sam_logoff     }, 
835         { "NET_LOGON_CTRL2"   , NET_LOGON_CTRL2   , api_net_logon_ctrl2    }, 
836         { "NET_TRUST_DOM_LIST", NET_TRUST_DOM_LIST, api_net_trust_dom_list },
837     {  NULL               , 0                 , NULL                   }
838 };
839
840 /*******************************************************************
841  receives a netlogon pipe and responds.
842  ********************************************************************/
843 BOOL api_netlog_rpc(pipes_struct *p, prs_struct *data)
844 {
845         return api_rpcTNP(p, "api_netlog_rpc", api_net_cmds, data);
846 }