domain aliases added a bit better: does local aliases if you query
[nivanova/samba-autobuild/.git] / source3 / rpc_server / srv_samr.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 extern pstring global_myworkgroup;
34 extern pstring global_myname;
35 extern DOM_SID global_sam_sid;
36
37 extern rid_name domain_group_rids[];
38 extern rid_name domain_alias_rids[];
39 extern rid_name builtin_alias_rids[];
40
41 /*******************************************************************
42   This next function should be replaced with something that
43   dynamically returns the correct user info..... JRA.
44  ********************************************************************/
45
46 static BOOL get_sampwd_entries(SAM_USER_INFO_21 *pw_buf,
47                                 int start_idx,
48                                 int *total_entries, int *num_entries,
49                                 int max_num_entries,
50                                 uint16 acb_mask)
51 {
52         void *vp = NULL;
53         struct sam_passwd *pwd = NULL;
54
55         (*num_entries) = 0;
56         (*total_entries) = 0;
57
58         if (pw_buf == NULL) return False;
59
60         vp = startsmbpwent(False);
61         if (!vp)
62         {
63                 DEBUG(0, ("get_sampwd_entries: Unable to open SMB password database.\n"));
64                 return False;
65         }
66
67         while (((pwd = getsam21pwent(vp)) != NULL) && (*num_entries) < max_num_entries)
68         {
69                 int user_name_len;
70
71                 if (start_idx > 0)
72                 {
73                         /* skip the requested number of entries.
74                            not very efficient, but hey...
75                          */
76                         start_idx--;
77                         continue;
78                 }
79
80                 user_name_len = strlen(pwd->smb_name);
81                 make_unistr2(&(pw_buf[(*num_entries)].uni_user_name), pwd->smb_name, user_name_len-1);
82                 make_uni_hdr(&(pw_buf[(*num_entries)].hdr_user_name), user_name_len-1, 
83                                user_name_len-1, 1);
84                 pw_buf[(*num_entries)].user_rid = pwd->user_rid;
85                 bzero( pw_buf[(*num_entries)].nt_pwd , 16);
86
87                 /* Now check if the NT compatible password is available. */
88                 if (pwd->smb_nt_passwd != NULL)
89                 {
90                         memcpy( pw_buf[(*num_entries)].nt_pwd , pwd->smb_nt_passwd, 16);
91                 }
92
93                 pw_buf[(*num_entries)].acb_info = (uint16)pwd->acct_ctrl;
94
95                 DEBUG(5, ("entry idx: %d user %s, rid 0x%x, acb %x",
96                           (*num_entries), pwd->smb_name,
97                           pwd->user_rid, pwd->acct_ctrl));
98
99                 if (acb_mask == 0 || IS_BITS_SET_SOME(pwd->acct_ctrl, acb_mask))
100                 {
101                         DEBUG(5,(" acb_mask %x accepts\n", acb_mask));
102                         (*num_entries)++;
103                 }
104                 else
105                 {
106                         DEBUG(5,(" acb_mask %x rejects\n", acb_mask));
107                 }
108
109                 (*total_entries)++;
110         }
111
112         endsmbpwent(vp);
113
114         return (*num_entries) > 0;
115 }
116
117 /*******************************************************************
118  samr_reply_unknown_1
119  ********************************************************************/
120 static void samr_reply_close_hnd(SAMR_Q_CLOSE_HND *q_u,
121                                 prs_struct *rdata)
122 {
123         SAMR_R_CLOSE_HND r_u;
124
125         /* set up the SAMR unknown_1 response */
126         bzero(r_u.pol.data, POL_HND_SIZE);
127
128         /* close the policy handle */
129         if (close_lsa_policy_hnd(&(q_u->pol)))
130         {
131                 r_u.status = 0;
132         }
133         else
134         {
135                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_INVALID;
136         }
137
138         DEBUG(5,("samr_reply_close_hnd: %d\n", __LINE__));
139
140         /* store the response in the SMB stream */
141         samr_io_r_close_hnd("", &r_u, rdata, 0);
142
143         DEBUG(5,("samr_reply_close_hnd: %d\n", __LINE__));
144
145 }
146
147 /*******************************************************************
148  api_samr_close_hnd
149  ********************************************************************/
150 static void api_samr_close_hnd( uint16 vuid, prs_struct *data, prs_struct *rdata)
151 {
152         SAMR_Q_CLOSE_HND q_u;
153
154         /* grab the samr unknown 1 */
155         samr_io_q_close_hnd("", &q_u, data, 0);
156
157         /* construct reply.  always indicate success */
158         samr_reply_close_hnd(&q_u, rdata);
159 }
160
161
162 /*******************************************************************
163  samr_reply_open_domain
164  ********************************************************************/
165 static void samr_reply_open_domain(SAMR_Q_OPEN_DOMAIN *q_u,
166                                 prs_struct *rdata)
167 {
168         SAMR_R_OPEN_DOMAIN r_u;
169         BOOL pol_open = False;
170
171         r_u.status = 0x0;
172
173         /* find the connection policy handle. */
174         if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->connect_pol)) == -1))
175         {
176                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
177         }
178
179         /* get a (unique) handle.  open a policy on it. */
180         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.domain_pol))))
181         {
182                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
183         }
184
185         /* associate the domain SID with the (unique) handle. */
186         if (r_u.status == 0x0 && !set_lsa_policy_samr_sid(&(r_u.domain_pol), &(q_u->dom_sid.sid)))
187         {
188                 /* oh, whoops.  don't know what error message to return, here */
189                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
190         }
191
192         if (r_u.status != 0 && pol_open)
193         {
194                 close_lsa_policy_hnd(&(r_u.domain_pol));
195         }
196
197         DEBUG(5,("samr_open_domain: %d\n", __LINE__));
198
199         /* store the response in the SMB stream */
200         samr_io_r_open_domain("", &r_u, rdata, 0);
201
202         DEBUG(5,("samr_open_domain: %d\n", __LINE__));
203
204 }
205
206 /*******************************************************************
207  api_samr_open_domain
208  ********************************************************************/
209 static void api_samr_open_domain( uint16 vuid, prs_struct *data, prs_struct *rdata)
210 {
211         SAMR_Q_OPEN_DOMAIN q_u;
212
213         /* grab the samr open */
214         samr_io_q_open_domain("", &q_u, data, 0);
215
216         /* construct reply.  always indicate success */
217         samr_reply_open_domain(&q_u, rdata);
218 }
219
220
221 /*******************************************************************
222  samr_reply_unknown_2c
223  ********************************************************************/
224 static void samr_reply_unknown_2c(SAMR_Q_UNKNOWN_2C *q_u,
225                                 prs_struct *rdata)
226 {
227         SAMR_R_UNKNOWN_2C r_u;
228         uint32 status = 0x0;
229         uint32 rid;
230
231         /* find the policy handle.  open a policy on it. */
232         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->user_pol)) == -1))
233         {
234                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
235         }
236
237         /* find the user's rid */
238         if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->user_pol))) == 0xffffffff)
239         {
240                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
241         }
242
243         make_samr_r_unknown_2c(&r_u, status);
244
245         DEBUG(5,("samr_unknown_2c: %d\n", __LINE__));
246
247         /* store the response in the SMB stream */
248         samr_io_r_unknown_2c("", &r_u, rdata, 0);
249
250         DEBUG(5,("samr_unknown_2c: %d\n", __LINE__));
251
252 }
253
254 /*******************************************************************
255  api_samr_unknown_2c
256  ********************************************************************/
257 static void api_samr_unknown_2c( uint16 vuid, prs_struct *data, prs_struct *rdata)
258 {
259         SAMR_Q_UNKNOWN_2C q_u;
260
261         /* grab the samr open */
262         samr_io_q_unknown_2c("", &q_u, data, 0);
263
264         /* construct reply.  always indicate success */
265         samr_reply_unknown_2c(&q_u, rdata);
266 }
267
268
269 /*******************************************************************
270  samr_reply_unknown_3
271  ********************************************************************/
272 static void samr_reply_unknown_3(SAMR_Q_UNKNOWN_3 *q_u,
273                                 prs_struct *rdata)
274 {
275         SAMR_R_UNKNOWN_3 r_u;
276         DOM_SID3 sid[MAX_SAM_SIDS];
277         uint32 rid;
278         uint32 status;
279
280         status = 0x0;
281
282         /* find the policy handle.  open a policy on it. */
283         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->user_pol)) == -1))
284         {
285                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
286         }
287
288         /* find the user's rid */
289         if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->user_pol))) == 0xffffffff)
290         {
291                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
292         }
293
294         if (status == 0x0)
295         {
296                 DOM_SID user_sid;
297                 DOM_SID everyone_sid;
298
299                 user_sid = global_sam_sid;
300
301                 SMB_ASSERT_ARRAY(user_sid.sub_auths, user_sid.num_auths+1);
302
303                 /*
304                  * Add the user RID.
305                  */
306                 user_sid.sub_auths[user_sid.num_auths++] = rid;
307                 
308                         string_to_sid(&everyone_sid, "S-1-1");
309
310                         /* maybe need another 1 or 2 (S-1-5-20-0x220 and S-1-5-20-0x224) */
311                         /* these two are DOMAIN_ADMIN and DOMAIN_ACCT_OP group RIDs */
312                         make_dom_sid3(&(sid[0]), 0x035b, 0x0002, &everyone_sid);
313                         make_dom_sid3(&(sid[1]), 0x0044, 0x0002, &user_sid);
314         }
315
316         make_samr_r_unknown_3(&r_u,
317                                 0x0001, 0x8004,
318                                 0x00000014, 0x0002, 0x0070,
319                                 2, sid, status);
320
321         DEBUG(5,("samr_unknown_3: %d\n", __LINE__));
322
323         /* store the response in the SMB stream */
324         samr_io_r_unknown_3("", &r_u, rdata, 0);
325
326         DEBUG(5,("samr_unknown_3: %d\n", __LINE__));
327
328 }
329
330 /*******************************************************************
331  api_samr_unknown_3
332  ********************************************************************/
333 static void api_samr_unknown_3( uint16 vuid, prs_struct *data, prs_struct *rdata)
334 {
335         SAMR_Q_UNKNOWN_3 q_u;
336
337         /* grab the samr open */
338         samr_io_q_unknown_3("", &q_u, data, 0);
339
340         /* construct reply.  always indicate success */
341         samr_reply_unknown_3(&q_u, rdata);
342 }
343
344
345 /*******************************************************************
346  samr_reply_enum_dom_users
347  ********************************************************************/
348 static void samr_reply_enum_dom_users(SAMR_Q_ENUM_DOM_USERS *q_u,
349                                 prs_struct *rdata)
350 {
351         SAMR_R_ENUM_DOM_USERS r_e;
352         SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
353         int num_entries;
354         int total_entries;
355
356         r_e.status = 0x0;
357         r_e.total_num_entries = 0;
358
359         /* find the policy handle.  open a policy on it. */
360         if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
361         {
362                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
363         }
364
365         DEBUG(5,("samr_reply_enum_dom_users: %d\n", __LINE__));
366
367         become_root(True);
368         get_sampwd_entries(pass, 0, &total_entries, &num_entries, MAX_SAM_ENTRIES, q_u->acb_mask);
369         unbecome_root(True);
370
371         make_samr_r_enum_dom_users(&r_e, total_entries,
372                                    q_u->unknown_0, num_entries,
373                                    pass, r_e.status);
374
375         /* store the response in the SMB stream */
376         samr_io_r_enum_dom_users("", &r_e, rdata, 0);
377
378         DEBUG(5,("samr_enum_dom_users: %d\n", __LINE__));
379
380 }
381
382 /*******************************************************************
383  api_samr_enum_dom_users
384  ********************************************************************/
385 static void api_samr_enum_dom_users( uint16 vuid, prs_struct *data, prs_struct *rdata)
386 {
387         SAMR_Q_ENUM_DOM_USERS q_e;
388
389         /* grab the samr open */
390         samr_io_q_enum_dom_users("", &q_e, data, 0);
391
392         /* construct reply. */
393         samr_reply_enum_dom_users(&q_e, rdata);
394 }
395
396
397 /*******************************************************************
398  samr_reply_enum_dom_groups
399  ********************************************************************/
400 static void samr_reply_enum_dom_groups(SAMR_Q_ENUM_DOM_GROUPS *q_u,
401                                 prs_struct *rdata)
402 {
403         SAMR_R_ENUM_DOM_GROUPS r_e;
404         SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
405         int num_entries;
406         BOOL got_grps;
407         char *dummy_group = "Domain Admins";
408
409         r_e.status = 0x0;
410         r_e.num_entries = 0;
411
412         /* find the policy handle.  open a policy on it. */
413         if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
414         {
415                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
416         }
417
418         DEBUG(5,("samr_reply_enum_dom_groups: %d\n", __LINE__));
419
420         got_grps = True;
421         num_entries = 1;
422         make_unistr2(&(pass[0].uni_user_name), dummy_group, strlen(dummy_group));
423         pass[0].user_rid = DOMAIN_GROUP_RID_ADMINS;
424
425         if (r_e.status == 0 && got_grps)
426         {
427                 make_samr_r_enum_dom_groups(&r_e, q_u->start_idx, num_entries, pass, r_e.status);
428         }
429
430         /* store the response in the SMB stream */
431         samr_io_r_enum_dom_groups("", &r_e, rdata, 0);
432
433         DEBUG(5,("samr_enum_dom_groups: %d\n", __LINE__));
434
435 }
436
437 /*******************************************************************
438  api_samr_enum_dom_groups
439  ********************************************************************/
440 static void api_samr_enum_dom_groups( uint16 vuid, prs_struct *data, prs_struct *rdata)
441 {
442         SAMR_Q_ENUM_DOM_GROUPS q_e;
443
444         /* grab the samr open */
445         samr_io_q_enum_dom_groups("", &q_e, data, 0);
446
447         /* construct reply. */
448         samr_reply_enum_dom_groups(&q_e, rdata);
449 }
450
451
452 /*******************************************************************
453  samr_reply_enum_dom_aliases
454  ********************************************************************/
455 static void samr_reply_enum_dom_aliases(SAMR_Q_ENUM_DOM_ALIASES *q_u,
456                                 prs_struct *rdata)
457 {
458         SAMR_R_ENUM_DOM_ALIASES r_e;
459         SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
460         int num_entries;
461         DOM_SID sid;
462         fstring sid_str;
463         fstring sam_sid_str;
464
465         r_e.status = 0x0;
466         r_e.num_entries = 0;
467
468         /* find the policy handle.  open a policy on it. */
469         if (r_e.status == 0x0 && !get_lsa_policy_samr_sid(&q_u->pol, &sid))
470         {
471                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
472         }
473
474         sid_to_string(sid_str, &sid);
475         sid_to_string(sam_sid_str, &global_sam_sid);
476
477         DEBUG(5,("samr_reply_enum_dom_aliases: sid %s\n", sid_str));
478
479         /* well-known aliases */
480         if (strequal(sid_str, "S-1-5-20"))
481         {
482                 char *name;
483                 while (num_entries < MAX_SAM_ENTRIES && ((name = builtin_alias_rids[num_entries].name) != NULL))
484                 {
485                         make_unistr2(&(pass[num_entries].uni_user_name), name, strlen(name));
486                         pass[num_entries].user_rid = builtin_alias_rids[num_entries].rid;
487                         num_entries++;
488                 }
489         }
490         else if (strequal(sid_str, sam_sid_str))
491         {
492                 /* local aliases */
493                 /* oops!  there's no code to deal with this */
494                 DEBUG(3,("samr_reply_enum_dom_aliases: enum of aliases in our domain not supported yet\n"));
495                 num_entries = 0;
496         }
497                 
498         make_samr_r_enum_dom_aliases(&r_e, num_entries, pass, r_e.status);
499
500         /* store the response in the SMB stream */
501         samr_io_r_enum_dom_aliases("", &r_e, rdata, 0);
502
503         DEBUG(5,("samr_enum_dom_aliases: %d\n", __LINE__));
504
505 }
506
507 /*******************************************************************
508  api_samr_enum_dom_aliases
509  ********************************************************************/
510 static void api_samr_enum_dom_aliases( uint16 vuid, prs_struct *data, prs_struct *rdata)
511 {
512         SAMR_Q_ENUM_DOM_ALIASES q_e;
513
514         /* grab the samr open */
515         samr_io_q_enum_dom_aliases("", &q_e, data, 0);
516
517         /* construct reply. */
518         samr_reply_enum_dom_aliases(&q_e, rdata);
519 }
520
521
522 /*******************************************************************
523  samr_reply_query_dispinfo
524  ********************************************************************/
525 static void samr_reply_query_dispinfo(SAMR_Q_QUERY_DISPINFO *q_u,
526                                 prs_struct *rdata)
527 {
528         SAMR_R_QUERY_DISPINFO r_e;
529         SAM_INFO_CTR ctr;
530         SAM_INFO_1 info1;
531         SAM_INFO_2 info2;
532         SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
533         int num_entries = 0;
534         int total_entries = 0;
535         BOOL got_pwds;
536         uint16 switch_level = 0x0;
537
538         ZERO_STRUCT(r_e);
539
540         r_e.status = 0x0;
541
542         DEBUG(5,("samr_reply_query_dispinfo: %d\n", __LINE__));
543
544         /* find the policy handle.  open a policy on it. */
545         if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
546         {
547                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
548                 DEBUG(5,("samr_reply_query_dispinfo: invalid handle\n"));
549         }
550
551         if (r_e.status == 0x0)
552         {
553                 become_root(True);
554                 got_pwds = get_sampwd_entries(pass, q_u->start_idx, &total_entries, &num_entries, MAX_SAM_ENTRIES, 0);
555                 unbecome_root(True);
556
557                 switch (q_u->switch_level)
558                 {
559                         case 0x1:
560                         {
561                         
562                                 /* query disp info is for users */
563                                 switch_level = 0x1;
564                                 make_sam_info_1(&info1, ACB_NORMAL,
565                                         q_u->start_idx, num_entries, pass);
566
567                                 ctr.sam.info1 = &info1;
568
569                                 break;
570                         }
571                         case 0x2:
572                         {
573                                 /* query disp info is for servers */
574                                 switch_level = 0x2;
575                                 make_sam_info_2(&info2, ACB_WSTRUST,
576                                         q_u->start_idx, num_entries, pass);
577
578                                 ctr.sam.info2 = &info2;
579
580                                 break;
581                         }
582                 }
583         }
584
585         if (r_e.status == 0 && got_pwds)
586         {
587                 make_samr_r_query_dispinfo(&r_e, switch_level, &ctr, r_e.status);
588         }
589
590         /* store the response in the SMB stream */
591         samr_io_r_query_dispinfo("", &r_e, rdata, 0);
592
593         DEBUG(5,("samr_query_dispinfo: %d\n", __LINE__));
594
595 }
596
597 /*******************************************************************
598  api_samr_query_dispinfo
599  ********************************************************************/
600 static void api_samr_query_dispinfo( uint16 vuid, prs_struct *data, prs_struct *rdata)
601 {
602         SAMR_Q_QUERY_DISPINFO q_e;
603
604         /* grab the samr open */
605         samr_io_q_query_dispinfo("", &q_e, data, 0);
606
607         /* construct reply. */
608         samr_reply_query_dispinfo(&q_e, rdata);
609 }
610
611
612 /*******************************************************************
613  samr_reply_query_aliasinfo
614  ********************************************************************/
615 static void samr_reply_query_aliasinfo(SAMR_Q_QUERY_ALIASINFO *q_u,
616                                 prs_struct *rdata)
617 {
618         SAMR_R_QUERY_ALIASINFO r_e;
619
620         r_e.status = 0x0;
621         r_e.ptr = 0;
622
623         /* find the policy handle.  open a policy on it. */
624         if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
625         {
626                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
627         }
628
629         DEBUG(5,("samr_reply_query_aliasinfo: %d\n", __LINE__));
630
631         if (r_e.status == 0x0)
632         {
633                 if (q_u->switch_level != 3)
634                 {
635                         r_e.status = NT_STATUS_INVALID_INFO_CLASS;
636                 }
637         }
638
639         make_samr_r_query_aliasinfo(&r_e, q_u->switch_level,
640                             "<account description>",
641                                 r_e.status);
642
643         /* store the response in the SMB stream */
644         samr_io_r_query_aliasinfo("", &r_e, rdata, 0);
645
646         DEBUG(5,("samr_query_aliasinfo: %d\n", __LINE__));
647
648 }
649
650 /*******************************************************************
651  api_samr_query_aliasinfo
652  ********************************************************************/
653 static void api_samr_query_aliasinfo( uint16 vuid, prs_struct *data, prs_struct *rdata)
654 {
655         SAMR_Q_QUERY_ALIASINFO q_e;
656
657         /* grab the samr open */
658         samr_io_q_query_aliasinfo("", &q_e, data, 0);
659
660         /* construct reply. */
661         samr_reply_query_aliasinfo(&q_e, rdata);
662 }
663
664
665 /*******************************************************************
666  samr_reply_lookup_ids
667  ********************************************************************/
668 static void samr_reply_lookup_ids(SAMR_Q_LOOKUP_IDS *q_u,
669                                 prs_struct *rdata)
670 {
671         uint32 rid[MAX_SAM_ENTRIES];
672         uint32 status     = 0;
673         int num_rids = q_u->num_sids1;
674
675         SAMR_R_LOOKUP_IDS r_u;
676
677         DEBUG(5,("samr_lookup_ids: %d\n", __LINE__));
678
679         if (num_rids > MAX_SAM_ENTRIES)
680         {
681                 num_rids = MAX_SAM_ENTRIES;
682                 DEBUG(5,("samr_lookup_ids: truncating entries to %d\n", num_rids));
683         }
684
685 #if 0
686         int i;
687         SMB_ASSERT_ARRAY(q_u->uni_user_name, num_rids);
688
689         for (i = 0; i < num_rids && status == 0; i++)
690         {
691                 struct sam_passwd *sam_pass;
692                 fstring user_name;
693
694
695                 fstrcpy(user_name, unistrn2(q_u->uni_user_name[i].buffer,
696                                             q_u->uni_user_name[i].uni_str_len));
697
698                 /* find the user account */
699                 become_root(True);
700                 sam_pass = get_smb21pwd_entry(user_name, 0);
701                 unbecome_root(True);
702
703                 if (sam_pass == NULL)
704                 {
705                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
706                         rid[i] = 0;
707                 }
708                 else
709                 {
710                         rid[i] = sam_pass->user_rid;
711                 }
712         }
713 #endif
714
715         num_rids = 1;
716         rid[0] = BUILTIN_ALIAS_RID_USERS;
717
718         make_samr_r_lookup_ids(&r_u, num_rids, rid, status);
719
720         /* store the response in the SMB stream */
721         samr_io_r_lookup_ids("", &r_u, rdata, 0);
722
723         DEBUG(5,("samr_lookup_ids: %d\n", __LINE__));
724
725 }
726
727 /*******************************************************************
728  api_samr_lookup_ids
729  ********************************************************************/
730 static void api_samr_lookup_ids( uint16 vuid, prs_struct *data, prs_struct *rdata)
731 {
732         SAMR_Q_LOOKUP_IDS q_u;
733
734         /* grab the samr 0x10 */
735         samr_io_q_lookup_ids("", &q_u, data, 0);
736
737         /* construct reply.  always indicate success */
738         samr_reply_lookup_ids(&q_u, rdata);
739 }
740
741 /*******************************************************************
742  samr_reply_lookup_names
743  ********************************************************************/
744 static void samr_reply_lookup_names(SAMR_Q_LOOKUP_NAMES *q_u,
745                                 prs_struct *rdata)
746 {
747         uint32 rid[MAX_SAM_ENTRIES];
748         uint32 status     = 0;
749         int i;
750         int num_rids = q_u->num_rids1;
751
752         SAMR_R_LOOKUP_NAMES r_u;
753
754         DEBUG(5,("samr_lookup_names: %d\n", __LINE__));
755
756         if (num_rids > MAX_SAM_ENTRIES)
757         {
758                 num_rids = MAX_SAM_ENTRIES;
759                 DEBUG(5,("samr_lookup_names: truncating entries to %d\n", num_rids));
760         }
761
762         SMB_ASSERT_ARRAY(q_u->uni_user_name, num_rids);
763
764         for (i = 0; i < num_rids && status == 0; i++)
765         {
766                 fstring name;
767
768                 status = 0xC0000000 | NT_STATUS_NONE_MAPPED;
769
770                 fstrcpy(name, unistrn2(q_u->uni_user_name[i].buffer, q_u->uni_user_name[i].uni_str_len));
771
772                 status = (status != 0x0) ? lookup_user_rid (name, &(rid[i])) : status;
773                 status = (status != 0x0) ? lookup_group_rid(name, &(rid[i])) : status;
774                 status = (status != 0x0) ? lookup_alias_rid(name, &(rid[i])) : status;
775         }
776
777         make_samr_r_lookup_names(&r_u, num_rids, rid, status);
778
779         /* store the response in the SMB stream */
780         samr_io_r_lookup_names("", &r_u, rdata, 0);
781
782         DEBUG(5,("samr_lookup_names: %d\n", __LINE__));
783
784 }
785
786 /*******************************************************************
787  api_samr_lookup_names
788  ********************************************************************/
789 static void api_samr_lookup_names( uint16 vuid, prs_struct *data, prs_struct *rdata)
790 {
791         SAMR_Q_LOOKUP_NAMES q_u;
792
793         /* grab the samr lookup names */
794         samr_io_q_lookup_names("", &q_u, data, 0);
795
796         /* construct reply.  always indicate success */
797         samr_reply_lookup_names(&q_u, rdata);
798 }
799
800 /*******************************************************************
801  samr_reply_chgpasswd_user
802  ********************************************************************/
803 static void samr_reply_chgpasswd_user(SAMR_Q_CHGPASSWD_USER *q_u,
804                                 prs_struct *rdata)
805 {
806         SAMR_R_CHGPASSWD_USER r_u;
807         uint32 status = 0x0;
808         fstring user_name;
809         fstring wks;
810
811         fstrcpy(user_name, unistrn2(q_u->uni_user_name.buffer, q_u->uni_user_name.uni_str_len));
812         fstrcpy(wks      , unistrn2(q_u->uni_dest_host.buffer, q_u->uni_dest_host.uni_str_len));
813
814         DEBUG(5,("samr_chgpasswd_user: user: %s wks: %s\n", user_name, wks));
815
816         if (!pass_oem_change(user_name,
817                              q_u->lm_newpass.pass, q_u->lm_oldhash.hash,
818                              q_u->nt_newpass.pass, q_u->nt_oldhash.hash))
819         {
820                 status = 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
821         }
822
823         make_samr_r_chgpasswd_user(&r_u, status);
824
825         /* store the response in the SMB stream */
826         samr_io_r_chgpasswd_user("", &r_u, rdata, 0);
827
828         DEBUG(5,("samr_chgpasswd_user: %d\n", __LINE__));
829 }
830
831 /*******************************************************************
832  api_samr_chgpasswd_user
833  ********************************************************************/
834 static void api_samr_chgpasswd_user( uint16 vuid, prs_struct *data, prs_struct *rdata)
835 {
836         SAMR_Q_CHGPASSWD_USER q_u;
837
838         /* unknown 38 command */
839         samr_io_q_chgpasswd_user("", &q_u, data, 0);
840
841         /* construct reply. */
842         samr_reply_chgpasswd_user(&q_u, rdata);
843 }
844
845
846 /*******************************************************************
847  samr_reply_unknown_38
848  ********************************************************************/
849 static void samr_reply_unknown_38(SAMR_Q_UNKNOWN_38 *q_u,
850                                 prs_struct *rdata)
851 {
852         SAMR_R_UNKNOWN_38 r_u;
853
854         DEBUG(5,("samr_unknown_38: %d\n", __LINE__));
855
856         make_samr_r_unknown_38(&r_u);
857
858         /* store the response in the SMB stream */
859         samr_io_r_unknown_38("", &r_u, rdata, 0);
860
861         DEBUG(5,("samr_unknown_38: %d\n", __LINE__));
862 }
863
864 /*******************************************************************
865  api_samr_unknown_38
866  ********************************************************************/
867 static void api_samr_unknown_38( uint16 vuid, prs_struct *data, prs_struct *rdata)
868 {
869         SAMR_Q_UNKNOWN_38 q_u;
870
871         /* unknown 38 command */
872         samr_io_q_unknown_38("", &q_u, data, 0);
873
874         /* construct reply.  always indicate success */
875         samr_reply_unknown_38(&q_u, rdata);
876 }
877
878
879 /*******************************************************************
880  samr_reply_unknown_12
881  ********************************************************************/
882 static void samr_reply_unknown_12(SAMR_Q_UNKNOWN_12 *q_u,
883                                 prs_struct *rdata)
884 {
885         fstring group_names[MAX_SAM_ENTRIES];
886         uint32  group_attrs[MAX_SAM_ENTRIES];
887         uint32 status     = 0;
888         int num_gids = q_u->num_gids1;
889
890         SAMR_R_UNKNOWN_12 r_u;
891
892         DEBUG(5,("samr_unknown_12: %d\n", __LINE__));
893
894         /* find the policy handle.  open a policy on it. */
895         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
896         {
897                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
898         }
899
900         if (status == 0x0)
901         {
902                 int i;
903                 if (num_gids > MAX_SAM_ENTRIES)
904                 {
905                         num_gids = MAX_SAM_ENTRIES;
906                         DEBUG(5,("samr_unknown_12: truncating entries to %d\n", num_gids));
907                 }
908
909                 for (i = 0; i < num_gids && status == 0; i++)
910                 {
911                         fstrcpy(group_names[i], "dummy group");
912                         group_attrs[i] = 0x2;
913                 }
914         }
915
916         make_samr_r_unknown_12(&r_u, num_gids, group_names, group_attrs, status);
917
918         /* store the response in the SMB stream */
919         samr_io_r_unknown_12("", &r_u, rdata, 0);
920
921         DEBUG(5,("samr_unknown_12: %d\n", __LINE__));
922
923 }
924
925 /*******************************************************************
926  api_samr_unknown_12
927  ********************************************************************/
928 static void api_samr_unknown_12( uint16 vuid, prs_struct *data, prs_struct *rdata)
929 {
930         SAMR_Q_UNKNOWN_12 q_u;
931
932         /* grab the samr lookup names */
933         samr_io_q_unknown_12("", &q_u, data, 0);
934
935         /* construct reply.  always indicate success */
936         samr_reply_unknown_12(&q_u, rdata);
937 }
938
939
940 /*******************************************************************
941  samr_reply_open_user
942  ********************************************************************/
943 static void samr_reply_open_user(SAMR_Q_OPEN_USER *q_u,
944                                 prs_struct *rdata,
945                                 int status)
946 {
947         SAMR_R_OPEN_USER r_u;
948         struct sam_passwd *sam_pass;
949         BOOL pol_open = False;
950
951         /* set up the SAMR open_user response */
952         bzero(r_u.user_pol.data, POL_HND_SIZE);
953
954         r_u.status = 0x0;
955
956         /* find the policy handle.  open a policy on it. */
957         if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1))
958         {
959                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
960         }
961
962         /* get a (unique) handle.  open a policy on it. */
963         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.user_pol))))
964         {
965                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
966         }
967
968         become_root(True);
969         sam_pass = getsam21pwrid(q_u->user_rid);
970         unbecome_root(True);
971
972         /* check that the RID exists in our domain. */
973         if (r_u.status == 0x0 && sam_pass == NULL)
974         {
975                 r_u.status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
976         }
977
978         /* associate the RID with the (unique) handle. */
979         if (r_u.status == 0x0 && !set_lsa_policy_samr_rid(&(r_u.user_pol), q_u->user_rid))
980         {
981                 /* oh, whoops.  don't know what error message to return, here */
982                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
983         }
984
985         if (r_u.status != 0 && pol_open)
986         {
987                 close_lsa_policy_hnd(&(r_u.user_pol));
988         }
989
990         DEBUG(5,("samr_open_user: %d\n", __LINE__));
991
992         /* store the response in the SMB stream */
993         samr_io_r_open_user("", &r_u, rdata, 0);
994
995         DEBUG(5,("samr_open_user: %d\n", __LINE__));
996
997 }
998
999 /*******************************************************************
1000  api_samr_open_user
1001  ********************************************************************/
1002 static void api_samr_open_user( uint16 vuid, prs_struct *data, prs_struct *rdata)
1003 {
1004         SAMR_Q_OPEN_USER q_u;
1005
1006         /* grab the samr unknown 22 */
1007         samr_io_q_open_user("", &q_u, data, 0);
1008
1009         /* construct reply.  always indicate success */
1010         samr_reply_open_user(&q_u, rdata, 0x0);
1011 }
1012
1013
1014 /*************************************************************************
1015  get_user_info_10
1016  *************************************************************************/
1017 static BOOL get_user_info_10(SAM_USER_INFO_10 *id10, uint32 user_rid)
1018 {
1019         struct smb_passwd *smb_pass;
1020
1021         if (!pdb_rid_is_user(user_rid))
1022         {
1023                 DEBUG(4,("RID 0x%x is not a user RID\n", user_rid));
1024                 return False;
1025         }
1026
1027         become_root(True);
1028         smb_pass = getsmbpwrid(user_rid);
1029         unbecome_root(True);
1030
1031         if (smb_pass == NULL)
1032         {
1033                 DEBUG(4,("User 0x%x not found\n", user_rid));
1034                 return False;
1035         }
1036
1037         DEBUG(3,("User:[%s]\n", smb_pass->smb_name));
1038
1039         make_sam_user_info10(id10, smb_pass->acct_ctrl); 
1040
1041         return True;
1042 }
1043
1044 /*************************************************************************
1045  get_user_info_21
1046  *************************************************************************/
1047 static BOOL get_user_info_21(SAM_USER_INFO_21 *id21, uint32 user_rid)
1048 {
1049         NTTIME dummy_time;
1050         struct sam_passwd *sam_pass;
1051         LOGON_HRS hrs;
1052         int i;
1053
1054         if (!pdb_rid_is_user(user_rid))
1055         {
1056                 DEBUG(4,("RID 0x%x is not a user RID\n", user_rid));
1057                 return False;
1058         }
1059
1060         become_root(True);
1061         sam_pass = getsam21pwrid(user_rid);
1062         unbecome_root(True);
1063
1064         if (sam_pass == NULL)
1065         {
1066                 DEBUG(4,("User 0x%x not found\n", user_rid));
1067                 return False;
1068         }
1069
1070         DEBUG(3,("User:[%s]\n", sam_pass->smb_name));
1071
1072         dummy_time.low  = 0xffffffff;
1073         dummy_time.high = 0x7fffffff;
1074
1075         DEBUG(0,("get_user_info_21 - TODO: convert unix times to NTTIMEs\n"));
1076
1077         /* create a LOGON_HRS structure */
1078         hrs.len = sam_pass->hours_len;
1079         SMB_ASSERT_ARRAY(hrs.hours, hrs.len);
1080         for (i = 0; i < hrs.len; i++)
1081         {
1082                 hrs.hours[i] = sam_pass->hours[i];
1083         }
1084
1085         make_sam_user_info21(id21,
1086
1087                            &dummy_time, /* logon_time */
1088                            &dummy_time, /* logoff_time */
1089                            &dummy_time, /* kickoff_time */
1090                            &dummy_time, /* pass_last_set_time */
1091                            &dummy_time, /* pass_can_change_time */
1092                            &dummy_time, /* pass_must_change_time */
1093
1094                            sam_pass->smb_name, /* user_name */
1095                            sam_pass->full_name, /* full_name */
1096                            sam_pass->home_dir, /* home_dir */
1097                            sam_pass->dir_drive, /* dir_drive */
1098                            sam_pass->logon_script, /* logon_script */
1099                            sam_pass->profile_path, /* profile_path */
1100                            sam_pass->acct_desc, /* description */
1101                            sam_pass->workstations, /* workstations user can log in from */
1102                            sam_pass->unknown_str, /* don't know, yet */
1103                            sam_pass->munged_dial, /* dialin info.  contains dialin path and tel no */
1104
1105                            sam_pass->user_rid, /* RID user_id */
1106                            sam_pass->group_rid, /* RID group_id */
1107                        sam_pass->acct_ctrl,
1108
1109                    sam_pass->unknown_3, /* unknown_3 */
1110                        sam_pass->logon_divs, /* divisions per week */
1111                            &hrs, /* logon hours */
1112                        sam_pass->unknown_5,
1113                        sam_pass->unknown_6);
1114
1115         return True;
1116 }
1117
1118 /*******************************************************************
1119  samr_reply_query_userinfo
1120  ********************************************************************/
1121 static void samr_reply_query_userinfo(SAMR_Q_QUERY_USERINFO *q_u,
1122                                 prs_struct *rdata)
1123 {
1124         SAMR_R_QUERY_USERINFO r_u;
1125 #if 0
1126         SAM_USER_INFO_11 id11;
1127 #endif
1128         SAM_USER_INFO_10 id10;
1129         SAM_USER_INFO_21 id21;
1130         void *info = NULL;
1131
1132         uint32 status = 0x0;
1133         uint32 rid = 0x0;
1134
1135         DEBUG(5,("samr_reply_query_userinfo: %d\n", __LINE__));
1136
1137         /* search for the handle */
1138         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
1139         {
1140                 status = NT_STATUS_INVALID_HANDLE;
1141         }
1142
1143         /* find the user's rid */
1144         if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff)
1145         {
1146                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
1147         }
1148
1149         DEBUG(5,("samr_reply_query_userinfo: rid:0x%x\n", rid));
1150
1151         /* ok!  user info levels (there are lots: see MSDEV help), off we go... */
1152         if (status == 0x0)
1153         {
1154                 switch (q_u->switch_value)
1155                 {
1156                         case 0x10:
1157                         {
1158                                 info = (void*)&id10;
1159                                 status = get_user_info_10(&id10, rid) ? 0 : NT_STATUS_NO_SUCH_USER;
1160                                 break;
1161                         }
1162 #if 0
1163 /* whoops - got this wrong.  i think.  or don't understand what's happening. */
1164                         case 0x11:
1165                         {
1166                                 NTTIME expire;
1167                                 info = (void*)&id11;
1168                                 
1169                                 expire.low  = 0xffffffff;
1170                                 expire.high = 0x7fffffff;
1171
1172                                 make_sam_user_info11(&id11, &expire, "BROOKFIELDS$", 0x03ef, 0x201, 0x0080);
1173
1174                                 break;
1175                         }
1176 #endif
1177                         case 21:
1178                         {
1179                                 info = (void*)&id21;
1180                                 status = get_user_info_21(&id21, rid) ? 0 : NT_STATUS_NO_SUCH_USER;
1181                                 break;
1182                         }
1183
1184                         default:
1185                         {
1186                                 status = NT_STATUS_INVALID_INFO_CLASS;
1187
1188                                 break;
1189                         }
1190                 }
1191         }
1192
1193         make_samr_r_query_userinfo(&r_u, q_u->switch_value, info, status);
1194
1195         /* store the response in the SMB stream */
1196         samr_io_r_query_userinfo("", &r_u, rdata, 0);
1197
1198         DEBUG(5,("samr_reply_query_userinfo: %d\n", __LINE__));
1199
1200 }
1201
1202 /*******************************************************************
1203  api_samr_query_userinfo
1204  ********************************************************************/
1205 static void api_samr_query_userinfo( uint16 vuid, prs_struct *data, prs_struct *rdata)
1206 {
1207         SAMR_Q_QUERY_USERINFO q_u;
1208
1209         /* grab the samr unknown 24 */
1210         samr_io_q_query_userinfo("", &q_u, data, 0);
1211
1212         /* construct reply.  always indicate success */
1213         samr_reply_query_userinfo(&q_u, rdata);
1214 }
1215
1216
1217 /*******************************************************************
1218  samr_reply_query_usergroups
1219  ********************************************************************/
1220 static void samr_reply_query_usergroups(SAMR_Q_QUERY_USERGROUPS *q_u,
1221                                 prs_struct *rdata)
1222 {
1223         SAMR_R_QUERY_USERGROUPS r_u;
1224         uint32 status = 0x0;
1225
1226         struct sam_passwd *sam_pass;
1227         DOM_GID *gids = NULL;
1228         int num_groups = 0;
1229         uint32 rid;
1230
1231         DEBUG(5,("samr_query_usergroups: %d\n", __LINE__));
1232
1233         /* find the policy handle.  open a policy on it. */
1234         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
1235         {
1236                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1237         }
1238
1239         /* find the user's rid */
1240         if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff)
1241         {
1242                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
1243         }
1244
1245         if (status == 0x0)
1246         {
1247                 become_root(True);
1248                 sam_pass = getsam21pwrid(rid);
1249                 unbecome_root(True);
1250
1251                 if (sam_pass == NULL)
1252                 {
1253                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
1254                 }
1255         }
1256
1257         if (status == 0x0)
1258         {
1259                 pstring groups;
1260                 get_domain_user_groups(groups, sam_pass->smb_name);
1261                 gids = NULL;
1262                 num_groups = make_dom_gids(groups, &gids);
1263         }
1264
1265         /* construct the response.  lkclXXXX: gids are not copied! */
1266         make_samr_r_query_usergroups(&r_u, num_groups, gids, status);
1267
1268         /* store the response in the SMB stream */
1269         samr_io_r_query_usergroups("", &r_u, rdata, 0);
1270
1271         if (gids)
1272         {
1273                 free((char *)gids);
1274         }
1275
1276         DEBUG(5,("samr_query_usergroups: %d\n", __LINE__));
1277
1278 }
1279
1280 /*******************************************************************
1281  api_samr_query_usergroups
1282  ********************************************************************/
1283 static void api_samr_query_usergroups( uint16 vuid, prs_struct *data, prs_struct *rdata)
1284 {
1285         SAMR_Q_QUERY_USERGROUPS q_u;
1286         /* grab the samr unknown 32 */
1287         samr_io_q_query_usergroups("", &q_u, data, 0);
1288
1289         /* construct reply. */
1290         samr_reply_query_usergroups(&q_u, rdata);
1291 }
1292
1293
1294 /*******************************************************************
1295  samr_reply_query_dom_info
1296  ********************************************************************/
1297 static void samr_reply_query_dom_info(SAMR_Q_QUERY_DOMAIN_INFO *q_u,
1298                                 prs_struct *rdata)
1299 {
1300         SAMR_R_QUERY_DOMAIN_INFO r_u;
1301         SAM_UNK_CTR ctr;
1302         uint16 switch_value = 0x0;
1303         uint32 status = 0x0;
1304
1305         ZERO_STRUCT(r_u);
1306         ZERO_STRUCT(ctr);
1307
1308         r_u.ctr = &ctr;
1309
1310         DEBUG(5,("samr_reply_query_dom_info: %d\n", __LINE__));
1311
1312         /* find the policy handle.  open a policy on it. */
1313         if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1))
1314         {
1315                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1316                 DEBUG(5,("samr_reply_query_dom_info: invalid handle\n"));
1317         }
1318
1319         if (status == 0x0)
1320         {
1321                 switch (q_u->switch_value)
1322                 {
1323                         case 0x02:
1324                         {
1325                                 switch_value = 0x2;
1326                                 make_unk_info2(&ctr.info.inf2, global_myworkgroup, global_myname);
1327
1328                                 break;
1329                         }
1330                         default:
1331                         {
1332                                 status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
1333                                 break;
1334                         }
1335                 }
1336         }
1337
1338         make_samr_r_query_dom_info(&r_u, switch_value, &ctr, status);
1339
1340         /* store the response in the SMB stream */
1341         samr_io_r_query_dom_info("", &r_u, rdata, 0);
1342
1343         DEBUG(5,("samr_query_dom_info: %d\n", __LINE__));
1344
1345 }
1346
1347 /*******************************************************************
1348  api_samr_query_dom_info
1349  ********************************************************************/
1350 static void api_samr_query_dom_info( uint16 vuid, prs_struct *data, prs_struct *rdata)
1351 {
1352         SAMR_Q_QUERY_DOMAIN_INFO q_e;
1353
1354         /* grab the samr unknown 8 command */
1355         samr_io_q_query_dom_info("", &q_e, data, 0);
1356
1357         /* construct reply. */
1358         samr_reply_query_dom_info(&q_e, rdata);
1359 }
1360
1361
1362
1363 /*******************************************************************
1364  samr_reply_unknown_32
1365  ********************************************************************/
1366 static void samr_reply_unknown_32(SAMR_Q_UNKNOWN_32 *q_u,
1367                                 prs_struct *rdata,
1368                                 int status)
1369 {
1370         int i;
1371         SAMR_R_UNKNOWN_32 r_u;
1372
1373         /* set up the SAMR unknown_32 response */
1374         bzero(r_u.pol.data, POL_HND_SIZE);
1375         if (status == 0)
1376         {
1377                 for (i = 4; i < POL_HND_SIZE; i++)
1378                 {
1379                         r_u.pol.data[i] = i+1;
1380                 }
1381         }
1382
1383         make_dom_rid4(&(r_u.rid4), 0x0030, 0, 0);
1384         r_u.status    = status;
1385
1386         DEBUG(5,("samr_unknown_32: %d\n", __LINE__));
1387
1388         /* store the response in the SMB stream */
1389         samr_io_r_unknown_32("", &r_u, rdata, 0);
1390
1391         DEBUG(5,("samr_unknown_32: %d\n", __LINE__));
1392
1393 }
1394
1395 /*******************************************************************
1396  api_samr_unknown_32
1397  ********************************************************************/
1398 static void api_samr_unknown_32( uint16 vuid, prs_struct *data, prs_struct *rdata)
1399 {
1400         uint32 status = 0;
1401         struct sam_passwd *sam_pass;
1402         fstring mach_acct;
1403
1404         SAMR_Q_UNKNOWN_32 q_u;
1405
1406         /* grab the samr unknown 32 */
1407         samr_io_q_unknown_32("", &q_u, data, 0);
1408
1409         /* find the machine account: tell the caller if it exists.
1410            lkclXXXX i have *no* idea if this is a problem or not
1411            or even if you are supposed to construct a different
1412            reply if the account already exists...
1413          */
1414
1415         fstrcpy(mach_acct, unistrn2(q_u.uni_mach_acct.buffer,
1416                                     q_u.uni_mach_acct.uni_str_len));
1417
1418         become_root(True);
1419         sam_pass = getsam21pwnam(mach_acct);
1420         unbecome_root(True);
1421
1422         if (sam_pass != NULL)
1423         {
1424                 /* machine account exists: say so */
1425                 status = 0xC0000000 | NT_STATUS_USER_EXISTS;
1426         }
1427         else
1428         {
1429                 /* this could cause trouble... */
1430                 DEBUG(0,("trouble!\n"));
1431                 status = 0;
1432         }
1433
1434         /* construct reply. */
1435         samr_reply_unknown_32(&q_u, rdata, status);
1436 }
1437
1438
1439 /*******************************************************************
1440  samr_reply_connect_anon
1441  ********************************************************************/
1442 static void samr_reply_connect_anon(SAMR_Q_CONNECT_ANON *q_u,
1443                                 prs_struct *rdata)
1444 {
1445         SAMR_R_CONNECT_ANON r_u;
1446         BOOL pol_open = False;
1447
1448         /* set up the SAMR connect_anon response */
1449
1450         r_u.status = 0x0;
1451         /* get a (unique) handle.  open a policy on it. */
1452         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.connect_pol))))
1453         {
1454                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1455         }
1456
1457         /* associate the domain SID with the (unique) handle. */
1458         if (r_u.status == 0x0 && !set_lsa_policy_samr_pol_status(&(r_u.connect_pol), q_u->unknown_0))
1459         {
1460                 /* oh, whoops.  don't know what error message to return, here */
1461                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1462         }
1463
1464         if (r_u.status != 0 && pol_open)
1465         {
1466                 close_lsa_policy_hnd(&(r_u.connect_pol));
1467         }
1468
1469         DEBUG(5,("samr_connect_anon: %d\n", __LINE__));
1470
1471         /* store the response in the SMB stream */
1472         samr_io_r_connect_anon("", &r_u, rdata, 0);
1473
1474         DEBUG(5,("samr_connect_anon: %d\n", __LINE__));
1475
1476 }
1477
1478 /*******************************************************************
1479  api_samr_connect_anon
1480  ********************************************************************/
1481 static void api_samr_connect_anon( uint16 vuid, prs_struct *data, prs_struct *rdata)
1482 {
1483         SAMR_Q_CONNECT_ANON q_u;
1484
1485         /* grab the samr open policy */
1486         samr_io_q_connect_anon("", &q_u, data, 0);
1487
1488         /* construct reply.  always indicate success */
1489         samr_reply_connect_anon(&q_u, rdata);
1490 }
1491
1492 /*******************************************************************
1493  samr_reply_connect
1494  ********************************************************************/
1495 static void samr_reply_connect(SAMR_Q_CONNECT *q_u,
1496                                 prs_struct *rdata)
1497 {
1498         SAMR_R_CONNECT r_u;
1499         BOOL pol_open = False;
1500
1501         /* set up the SAMR connect response */
1502
1503         r_u.status = 0x0;
1504         /* get a (unique) handle.  open a policy on it. */
1505         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.connect_pol))))
1506         {
1507                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1508         }
1509
1510         /* associate the domain SID with the (unique) handle. */
1511         if (r_u.status == 0x0 && !set_lsa_policy_samr_pol_status(&(r_u.connect_pol), q_u->unknown_0))
1512         {
1513                 /* oh, whoops.  don't know what error message to return, here */
1514                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1515         }
1516
1517         if (r_u.status != 0 && pol_open)
1518         {
1519                 close_lsa_policy_hnd(&(r_u.connect_pol));
1520         }
1521
1522         DEBUG(5,("samr_connect: %d\n", __LINE__));
1523
1524         /* store the response in the SMB stream */
1525         samr_io_r_connect("", &r_u, rdata, 0);
1526
1527         DEBUG(5,("samr_connect: %d\n", __LINE__));
1528
1529 }
1530
1531 /*******************************************************************
1532  api_samr_connect
1533  ********************************************************************/
1534 static void api_samr_connect( uint16 vuid, prs_struct *data, prs_struct *rdata)
1535 {
1536         SAMR_Q_CONNECT q_u;
1537
1538         /* grab the samr open policy */
1539         samr_io_q_connect("", &q_u, data, 0);
1540
1541         /* construct reply.  always indicate success */
1542         samr_reply_connect(&q_u, rdata);
1543 }
1544
1545 /*******************************************************************
1546  samr_reply_open_alias
1547  ********************************************************************/
1548 static void samr_reply_open_alias(SAMR_Q_OPEN_ALIAS *q_u,
1549                                 prs_struct *rdata)
1550 {
1551         SAMR_R_OPEN_ALIAS r_u;
1552         BOOL pol_open = False;
1553
1554         /* set up the SAMR open_alias response */
1555
1556         r_u.status = 0x0;
1557         /* get a (unique) handle.  open a policy on it. */
1558         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.pol))))
1559         {
1560                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1561         }
1562
1563         /* associate a RID with the (unique) handle. */
1564         if (r_u.status == 0x0 && !set_lsa_policy_samr_rid(&(r_u.pol), q_u->rid_alias))
1565         {
1566                 /* oh, whoops.  don't know what error message to return, here */
1567                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1568         }
1569
1570         if (r_u.status != 0 && pol_open)
1571         {
1572                 close_lsa_policy_hnd(&(r_u.pol));
1573         }
1574
1575         DEBUG(5,("samr_open_alias: %d\n", __LINE__));
1576
1577         /* store the response in the SMB stream */
1578         samr_io_r_open_alias("", &r_u, rdata, 0);
1579
1580         DEBUG(5,("samr_open_alias: %d\n", __LINE__));
1581
1582 }
1583
1584 /*******************************************************************
1585  api_samr_open_alias
1586  ********************************************************************/
1587 static void api_samr_open_alias( uint16 vuid, prs_struct *data, prs_struct *rdata)
1588                                 
1589 {
1590         SAMR_Q_OPEN_ALIAS q_u;
1591
1592         /* grab the samr open policy */
1593         samr_io_q_open_alias("", &q_u, data, 0);
1594
1595         /* construct reply.  always indicate success */
1596         samr_reply_open_alias(&q_u, rdata);
1597 }
1598
1599 /*******************************************************************
1600  array of \PIPE\samr operations
1601  ********************************************************************/
1602 static struct api_struct api_samr_cmds [] =
1603 {
1604         { "SAMR_CLOSE_HND"        , SAMR_CLOSE_HND        , api_samr_close_hnd        },
1605         { "SAMR_CONNECT"          , SAMR_CONNECT          , api_samr_connect          },
1606         { "SAMR_CONNECT_ANON"     , SAMR_CONNECT_ANON     , api_samr_connect_anon     },
1607         { "SAMR_ENUM_DOM_USERS"   , SAMR_ENUM_DOM_USERS   , api_samr_enum_dom_users   },
1608         { "SAMR_ENUM_DOM_GROUPS"  , SAMR_ENUM_DOM_GROUPS  , api_samr_enum_dom_groups  },
1609         { "SAMR_ENUM_DOM_ALIASES" , SAMR_ENUM_DOM_ALIASES , api_samr_enum_dom_aliases },
1610         { "SAMR_LOOKUP_IDS"       , SAMR_LOOKUP_IDS       , api_samr_lookup_ids       },
1611         { "SAMR_LOOKUP_NAMES"     , SAMR_LOOKUP_NAMES     , api_samr_lookup_names     },
1612         { "SAMR_OPEN_USER"        , SAMR_OPEN_USER        , api_samr_open_user        },
1613         { "SAMR_QUERY_USERINFO"   , SAMR_QUERY_USERINFO   , api_samr_query_userinfo   },
1614         { "SAMR_QUERY_DOMAIN_INFO", SAMR_QUERY_DOMAIN_INFO, api_samr_query_dom_info        },
1615         { "SAMR_QUERY_USERGROUPS" , SAMR_QUERY_USERGROUPS , api_samr_query_usergroups },
1616         { "SAMR_QUERY_DISPINFO"   , SAMR_QUERY_DISPINFO   , api_samr_query_dispinfo   },
1617         { "SAMR_QUERY_ALIASINFO"  , SAMR_QUERY_ALIASINFO  , api_samr_query_aliasinfo  },
1618         { "SAMR_0x32"             , 0x32                  , api_samr_unknown_32       },
1619         { "SAMR_UNKNOWN_12"       , SAMR_UNKNOWN_12       , api_samr_unknown_12       },
1620         { "SAMR_UNKNOWN_38"       , SAMR_UNKNOWN_38       , api_samr_unknown_38       },
1621         { "SAMR_CHGPASSWD_USER"   , SAMR_CHGPASSWD_USER   , api_samr_chgpasswd_user   },
1622         { "SAMR_OPEN_ALIAS"       , SAMR_OPEN_ALIAS       , api_samr_open_alias       },
1623         { "SAMR_OPEN_DOMAIN"      , SAMR_OPEN_DOMAIN      , api_samr_open_domain      },
1624         { "SAMR_UNKNOWN_3"        , SAMR_UNKNOWN_3        , api_samr_unknown_3        },
1625         { "SAMR_UNKNOWN_2C"       , SAMR_UNKNOWN_2C       , api_samr_unknown_2c       },
1626         { NULL                    , 0                     , NULL                      }
1627 };
1628
1629 /*******************************************************************
1630  receives a samr pipe and responds.
1631  ********************************************************************/
1632 BOOL api_samr_rpc(pipes_struct *p, prs_struct *data)
1633 {
1634     return api_rpcTNP(p, "api_samr_rpc", api_samr_cmds, data);
1635 }
1636