"For I have laboured mightily on Luke's code, and hath broken
[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
232         if (!allow_access(lp_domain_hostsdeny(), lp_domain_hostsallow(),
233                           client_name(), client_addr()))
234         {
235                 DEBUG(0,("get_md4pw: Workstation %s denied access to domain\n", mach_acct));
236                 return False;
237         }
238
239         become_root(True);
240         smb_pass = get_smbpwd_entry(mach_acct, 0);
241         unbecome_root(True);
242
243         if (smb_pass != NULL)
244         {
245                 memcpy(md4pw, smb_pass->smb_nt_passwd, 16);
246                 dump_data(5, md4pw, 16);
247
248                 return True;
249         }
250         DEBUG(0,("get_md4pw: Workstation %s: no account in domain\n", mach_acct));
251         return False;
252 }
253
254 /*************************************************************************
255  api_net_req_chal:
256  *************************************************************************/
257 static void api_net_req_chal( int uid,
258                               prs_struct *data,
259                               prs_struct *rdata)
260 {
261         NET_Q_REQ_CHAL q_r;
262         uint32 status = 0x0;
263
264         fstring mach_acct;
265         fstring mach_name;
266
267         user_struct *vuser;
268
269         DEBUG(5,("api_net_req_chal(%d): vuid %d\n", __LINE__, uid));
270
271         if ((vuser = get_valid_user_struct(uid)) == NULL) return;
272
273         /* grab the challenge... */
274         net_io_q_req_chal("", &q_r, data, 0);
275
276         fstrcpy(mach_acct, unistrn2(q_r.uni_logon_clnt.buffer,
277                                     q_r.uni_logon_clnt.uni_str_len));
278
279         fstrcpy(mach_name, mach_acct);
280         strlower(mach_name);
281
282         strcat(mach_acct, "$");
283
284         if (get_md4pw(vuser->dc.md4pw, mach_name, mach_acct))
285         {
286                 /* copy the client credentials */
287                 memcpy(vuser->dc.clnt_chal.data          , q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data));
288                 memcpy(vuser->dc.clnt_cred.challenge.data, q_r.clnt_chal.data, sizeof(q_r.clnt_chal.data));
289
290                 /* create a server challenge for the client */
291                 /* PAXX: set these to random values. */
292                 /* lkcl: paul, you mentioned that it doesn't really matter much */
293                 SIVAL(vuser->dc.srv_chal.data, 0, 0x11111111);
294                 SIVAL(vuser->dc.srv_chal.data, 4, 0x11111111);
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 #ifdef ALLOW_SRV_PWSET
370         pstring mach_acct;
371         struct smb_passwd *smb_pass;
372         BOOL ret;
373 #endif
374         user_struct *vuser;
375
376         if ((vuser = get_valid_user_struct(uid)) == NULL) return;
377
378         /* grab the challenge and encrypted password ... */
379         net_io_q_srv_pwset("", &q_a, data, 0);
380
381         /* checks and updates credentials.  creates reply credentials */
382         if (deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred), 
383                         &(q_a.clnt_id.cred), &srv_cred))
384         {
385                 memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred));
386
387                 DEBUG(5,("api_net_srv_pwset: %d\n", __LINE__));
388
389 #ifdef ALLOW_SRV_PWSET
390
391                 pstrcpy(mach_acct, unistrn2(q_a.clnt_id.login.uni_acct_name.buffer,
392                                                                         q_a.clnt_id.login.uni_acct_name.uni_str_len));
393
394                 DEBUG(3,("Server Password Set Wksta:[%s]\n", mach_acct));
395
396                 become_root(True);
397                 smb_pass = get_smbpwd_entry(mach_acct, 0);
398                 unbecome_root(True);
399
400                 if (smb_pass != NULL)
401                 {
402                         unsigned char pwd[16];
403                         uint8 mode = 2;
404
405                         memcpy(pwd, q_a.pwd, 16);
406
407                         if (obfuscate_pwd(pwd, vuser->dc.sess_key, mode))
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
426                 DEBUG(5,("api_net_srv_pwset: %d\n", __LINE__));
427 #else
428                 DEBUG(5,("api_net_srv_pwset: server password set being denied\n"));
429 #endif
430
431         }
432         else
433         {
434                 /* lkclXXXX take a guess at a sensible error code to return... */
435                 status = 0xC0000000 | NT_STATUS_NETWORK_CREDENTIAL_CONFLICT;
436         }
437
438         /* construct reply.  always indicate failure.  nt keeps going... */
439         net_reply_srv_pwset(&q_a, rdata,
440                                         &srv_cred, status);
441 }
442
443
444 /*************************************************************************
445  api_net_sam_logoff:
446  *************************************************************************/
447 static void api_net_sam_logoff( int uid,
448                                prs_struct *data,
449                                prs_struct *rdata)
450 {
451         NET_Q_SAM_LOGOFF q_l;
452         NET_ID_INFO_CTR ctr;    
453
454         DOM_CRED srv_cred;
455
456         user_struct *vuser;
457
458         if ((vuser = get_valid_user_struct(uid)) == NULL) return;
459
460         /* the DOM_ID_INFO_1 structure is a bit big.  plus we might want to
461            dynamically allocate it inside net_io_q_sam_logon, at some point */
462         q_l.sam_id.ctr = &ctr;
463
464         /* grab the challenge... */
465         net_io_q_sam_logoff("", &q_l, data, 0);
466
467         /* checks and updates credentials.  creates reply credentials */
468         deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred), 
469                         &(q_l.sam_id.client.cred), &srv_cred);
470         memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred));
471
472         /* construct reply.  always indicate success */
473         net_reply_sam_logoff(&q_l, rdata,
474                                         &srv_cred,
475                         0x0);
476 }
477
478 /*************************************************************************
479  net_login_interactive:
480  *************************************************************************/
481 static uint32 net_login_interactive(NET_ID_INFO_1 *id1,
482                                 struct smb_passwd *smb_pass,
483                                 user_struct *vuser)
484 {
485         uint32 status = 0x0;
486
487 #ifdef USE_ARCFOUR
488         extern void arcfour(uint8 key[16], uint8 out[16], uint8 in[16]);
489         char nt_pwd[16];
490         char lm_pwd[16];
491         unsigned char arc4_key[16];
492         memset(arc4_key, 0, 16);
493         memcpy(arc4_key, vuser->dc.sess_key, 8);
494
495         arcfour(arc4_key, lm_pwd, id1->arc4_lm_owf.data);
496         arcfour(arc4_key, nt_pwd, id1->arc4_nt_owf.data);
497
498 #ifdef DEBUG_PASSWORD
499         DEBUG(100,("arcfour decrypt of lm owf password:"));
500         dump_data(100, lm_pwd, 16);
501
502         DEBUG(100,("arcfour decrypt of nt owf password:"));
503         dump_data(100, nt_pwd, 16);
504 #endif
505
506         if (memcmp(smb_pass->smb_passwd   , lm_pwd, 16) != 0 &&
507                 memcmp(smb_pass->smb_nt_passwd, nt_pwd, 16) != 0)
508         {
509                 status = 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
510         }
511 #else
512 /* sorry.  have to assume that the password is always ok.
513    this _is_ ok, because the LSA SAM Logon is nothing to do
514    with SMB connections to shares.
515  */
516 DEBUG(3,("SAM Logon.  Password not being checked\n"));
517 #endif
518
519         return status;
520 }
521
522 /*************************************************************************
523  net_login_network:
524  *************************************************************************/
525 static uint32 net_login_network(NET_ID_INFO_2 *id2,
526                                 struct smb_passwd *smb_pass,
527                                 user_struct *vuser)
528 {
529         if ((id2->lm_chal_resp.str_str_len == 24 ||
530              id2->lm_chal_resp.str_str_len == 0) &&
531             id2->nt_chal_resp.str_str_len == 24 && 
532             (((smb_pass->smb_nt_passwd != NULL) &&
533                smb_password_check(id2->nt_chal_resp.buffer, smb_pass->smb_nt_passwd,
534                                  id2->lm_chal)) ||
535                smb_password_check(id2->lm_chal_resp.buffer, smb_pass->smb_passwd,
536                                  id2->lm_chal)))
537         {
538                 return 0x0;
539         }
540         return 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
541 }
542
543 /*************************************************************************
544  api_net_sam_logon:
545  *************************************************************************/
546 static void api_net_sam_logon( int uid,
547                                prs_struct *data,
548                                prs_struct *rdata)
549 {
550         NET_Q_SAM_LOGON q_l;
551         NET_ID_INFO_CTR ctr;    
552         NET_USER_INFO_3 usr_info;
553         uint32 status = 0x0;
554         DOM_CRED srv_cred;
555         struct smb_passwd *smb_pass = NULL;
556         UNISTR2 *uni_samlogon_user = NULL;
557
558         user_struct *vuser = NULL;
559
560         if ((vuser = get_valid_user_struct(uid)) == NULL) return;
561
562         q_l.sam_id.ctr = &ctr;
563
564         net_io_q_sam_logon("", &q_l, data, 0);
565
566         /* checks and updates credentials.  creates reply credentials */
567         if (!deal_with_creds(vuser->dc.sess_key, &(vuser->dc.clnt_cred), 
568                         &(q_l.sam_id.client.cred), &srv_cred))
569         {
570                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
571         }
572         else
573         {
574                 memcpy(&(vuser->dc.srv_cred), &(vuser->dc.clnt_cred), sizeof(vuser->dc.clnt_cred));
575         }
576
577         /* find the username */
578
579         if (status == 0x0)
580         {
581                 switch (q_l.sam_id.logon_level)
582                 {
583                         case 1:
584                         {
585                                 uni_samlogon_user = &(q_l.sam_id.ctr->auth.id1.uni_user_name);
586                                 pstrcpy(samlogon_user, unistrn2(uni_samlogon_user->buffer,
587                                                 uni_samlogon_user->uni_str_len));
588
589                                 DEBUG(3,("SAM Logon (Interactive). Domain:[%s].  User:[%s]\n",
590                                           lp_workgroup(), samlogon_user));
591                                 break;
592                         }
593                         case 2:
594                         {
595                                 uni_samlogon_user = &(q_l.sam_id.ctr->auth.id2.uni_user_name);
596                                 pstrcpy(samlogon_user, unistrn2(uni_samlogon_user->buffer,
597                                                 uni_samlogon_user->uni_str_len));
598
599                                 DEBUG(3,("SAM Logon (Network). Domain:[%s].  User:[%s]\n",
600                                           lp_workgroup(), samlogon_user));
601                                 break;
602                         }
603                         default:
604                         {
605                                 DEBUG(2,("SAM Logon: unsupported switch value\n"));
606                                 status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
607                                 break;
608                         }
609                 }
610         }
611
612         /* check username exists */
613
614         if (status == 0x0)
615         {
616                 pstrcpy(samlogon_user, unistrn2(uni_samlogon_user->buffer,
617                                                 uni_samlogon_user->uni_str_len));
618
619                 become_root(True);
620                 smb_pass = get_smbpwd_entry(samlogon_user, 0);
621                 unbecome_root(True);
622
623                 if (smb_pass == NULL)
624                 {
625                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
626                 }
627         }
628
629         /* validate password. */
630
631         if (status == 0x0)
632         {
633                 switch (q_l.sam_id.logon_level)
634                 {
635                         case 1:
636                         {
637                                 /* interactive login.  passwords arcfour'd with session key */
638                                 status = net_login_interactive(&q_l.sam_id.ctr->auth.id1,
639                                                                smb_pass, vuser);
640                                 break;
641                         }
642                         case 2:
643                         {
644                                 /* network login.  lm challenge and 24 byte responses */
645                                 status = net_login_network(&q_l.sam_id.ctr->auth.id2,
646                                                            smb_pass, vuser);
647                                 break;
648                         }
649                 }
650         }
651         
652         /* lkclXXXX this is the point at which, if the login was
653            successful, that the SAM Local Security Authority should
654            record that the user is logged in to the domain.
655          */
656
657         /* return the profile plus other bits :-) */
658
659         if (status == 0x0)
660         {
661                 DOM_GID gids[LSA_MAX_GROUPS];
662                 int num_gids = 0;
663                 NTTIME dummy_time;
664                 pstring logon_script;
665                 pstring profile_path;
666                 pstring home_dir;
667                 pstring home_drive;
668                 pstring my_name;
669                 pstring my_workgroup;
670                 pstring domain_groups;
671                 pstring dom_sid;
672                 pstring other_sids;
673                 extern pstring myname;
674                 uint32 r_uid;
675                 uint32 r_gid;
676
677                 /* set up pointer indicating user/password failed to be found */
678                 usr_info.ptr_user_info = 0;
679
680                 dummy_time.low  = 0xffffffff;
681                 dummy_time.high = 0x7fffffff;
682
683                 get_myname(myname, NULL);
684
685                 /* XXXX hack to get standard_sub_basic() to use sam logon username */
686                 /* possibly a better way would be to do a become_user() call */
687                 sam_logon_in_ssb = True;
688
689                 pstrcpy(logon_script, lp_logon_script     ());
690                 pstrcpy(profile_path, lp_logon_path       ());
691                 pstrcpy(dom_sid     , lp_domain_sid       ());
692                 pstrcpy(other_sids  , lp_domain_other_sids());
693                 pstrcpy(my_workgroup, lp_workgroup        ());
694
695                 pstrcpy(home_drive  , lp_logon_drive      ());
696                 pstrcpy(home_dir    , lp_logon_home       ());
697
698                 pstrcpy(my_name     , myname                );
699                 strupper(my_name);
700
701                 get_domain_user_groups(domain_groups, samlogon_user);
702
703                 num_gids = make_dom_gids(domain_groups, gids);
704
705                 sam_logon_in_ssb = False;
706
707                 if (name_to_rid(samlogon_user, &r_uid, &r_gid))
708                 {
709                         make_net_user_info3(&usr_info,
710
711                                    &dummy_time, /* logon_time */
712                                    &dummy_time, /* logoff_time */
713                                    &dummy_time, /* kickoff_time */
714                                    &dummy_time, /* pass_last_set_time */
715                                    &dummy_time, /* pass_can_change_time */
716                                    &dummy_time, /* pass_must_change_time */
717
718                                    samlogon_user   , /* user_name */
719                                    vuser->real_name, /* full_name */
720                                    logon_script    , /* logon_script */
721                                    profile_path    , /* profile_path */
722                                    home_dir        , /* home_dir */
723                                    home_drive      , /* dir_drive */
724
725                                    0, /* logon_count */
726                                    0, /* bad_pw_count */
727
728                                    r_uid   , /* RID user_id */
729                                    r_gid   , /* RID group_id */
730                                    num_gids,    /* uint32 num_groups */
731                                    gids    , /* DOM_GID *gids */
732                                    0x20    , /* uint32 user_flgs (?) */
733
734                                    NULL, /* char sess_key[16] */
735
736                                    my_name     , /* char *logon_srv */
737                                    my_workgroup, /* char *logon_dom */
738
739                                    dom_sid,     /* char *dom_sid */
740                                    other_sids); /* char *other_sids */
741                 }
742                 else
743                 {
744                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
745                 }
746         }
747
748         net_reply_sam_logon(&q_l, rdata, &srv_cred, &usr_info, status);
749 }
750
751
752 /*************************************************************************
753  api_net_trust_dom_list:
754  *************************************************************************/
755 static void api_net_trust_dom_list( int uid,
756                                  prs_struct *data,
757                                  prs_struct *rdata)
758 {
759         NET_Q_TRUST_DOM_LIST q_t;
760
761         char *trusted_domain = "test_domain";
762
763         DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
764
765         /* grab the lsa trusted domain list query... */
766         net_io_q_trust_dom("", &q_t, data, 0);
767
768         /* construct reply. */
769         net_reply_trust_dom_list(&q_t, rdata,
770                                 1, trusted_domain);
771
772         DEBUG(6,("api_net_trust_dom_list: %d\n", __LINE__));
773 }
774
775
776 /*************************************************************************
777  error messages cropping up when using nltest.exe...
778  *************************************************************************/
779 #define ERROR_NO_SUCH_DOMAIN   0x54b
780 #define ERROR_NO_LOGON_SERVERS 0x51f
781
782 /*************************************************************************
783  api_net_logon_ctrl2:
784  *************************************************************************/
785 static void api_net_logon_ctrl2( int uid,
786                                  prs_struct *data,
787                                  prs_struct *rdata)
788 {
789         NET_Q_LOGON_CTRL2 q_l;
790
791         /* lkclXXXX - guess what - absolutely no idea what these are! */
792         uint32 flags = 0x0;
793         uint32 pdc_connection_status = 0x0;
794         uint32 logon_attempts = 0x0;
795         uint32 tc_status = ERROR_NO_LOGON_SERVERS;
796         char *trusted_domain = "test_domain";
797
798         DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
799
800         /* grab the lsa netlogon ctrl2 query... */
801         net_io_q_logon_ctrl2("", &q_l, data, 0);
802
803         /* construct reply. */
804         net_reply_logon_ctrl2(&q_l, rdata,
805                                 flags, pdc_connection_status, logon_attempts,
806                                 tc_status, trusted_domain);
807
808         DEBUG(6,("api_net_logon_ctrl2: %d\n", __LINE__));
809 }
810
811 /*******************************************************************
812  array of \PIPE\NETLOGON operations
813  ********************************************************************/
814 static struct api_struct api_net_cmds [] =
815 {
816         { "NET_REQCHAL"       , NET_REQCHAL       , api_net_req_chal       }, 
817         { "NET_AUTH2"         , NET_AUTH2         , api_net_auth_2         }, 
818         { "NET_SRVPWSET"      , NET_SRVPWSET      , api_net_srv_pwset      }, 
819         { "NET_SAMLOGON"      , NET_SAMLOGON      , api_net_sam_logon      }, 
820         { "NET_SAMLOGOFF"     , NET_SAMLOGOFF     , api_net_sam_logoff     }, 
821         { "NET_LOGON_CTRL2"   , NET_LOGON_CTRL2   , api_net_logon_ctrl2    }, 
822         { "NET_TRUST_DOM_LIST", NET_TRUST_DOM_LIST, api_net_trust_dom_list },
823     {  NULL               , 0                 , NULL                   }
824 };
825
826 /*******************************************************************
827  receives a netlogon pipe and responds.
828  ********************************************************************/
829 BOOL api_netlog_rpc(pipes_struct *p, prs_struct *data)
830 {
831         return api_rpcTNP(p, "api_netlog_rpc", api_net_cmds, data);
832 }