Don't return winbind groups or users when responding to samr_enum_dom_users
[samba.git] / source / rpc_server / srv_samr.c
1 #define OLD_NTDOMAIN 1
2 /* 
3  *  Unix SMB/Netbios implementation.
4  *  Version 1.9.
5  *  RPC Pipe client / server routines
6  *  Copyright (C) Andrew Tridgell              1992-1997,
7  *  Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
8  *  Copyright (C) Paul Ashton                       1997.
9  *  Copyright (C) Hewlett-Packard Company           1999.
10  *  
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *  
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *  
21  *  You should have received a copy of the GNU General Public License
22  *  along with this program; if not, write to the Free Software
23  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24  */
25
26 #include "includes.h"
27
28 extern int DEBUGLEVEL;
29
30 extern fstring global_myworkgroup;
31 extern pstring global_myname;
32 extern DOM_SID global_sam_sid;
33
34 extern rid_name domain_group_rids[];
35 extern rid_name domain_alias_rids[];
36 extern rid_name builtin_alias_rids[];
37
38 /*******************************************************************
39   This next function should be replaced with something that
40   dynamically returns the correct user info..... JRA.
41  ********************************************************************/
42
43 static BOOL get_sampwd_entries(SAM_USER_INFO_21 *pw_buf,
44                                 int start_idx,
45                                 int *total_entries, int *num_entries,
46                                 int max_num_entries,
47                                 uint16 acb_mask)
48 {
49         void *vp = NULL;
50         struct sam_passwd *pwd = NULL;
51
52         (*num_entries) = 0;
53         (*total_entries) = 0;
54
55         if (pw_buf == NULL) return False;
56
57         vp = startsmbpwent(False);
58         if (!vp) {
59                 DEBUG(0, ("get_sampwd_entries: Unable to open SMB password database.\n"));
60                 return False;
61         }
62
63         while (((pwd = getsam21pwent(vp)) != NULL) && (*num_entries) < max_num_entries) {
64                 int user_name_len;
65
66                 if (start_idx > 0) {
67                         /* skip the requested number of entries.
68                            not very efficient, but hey...
69                          */
70                         start_idx--;
71                         continue;
72                 }
73
74                 user_name_len = strlen(pwd->smb_name);
75                 init_unistr2(&(pw_buf[(*num_entries)].uni_user_name), pwd->smb_name, user_name_len);
76                 init_uni_hdr(&(pw_buf[(*num_entries)].hdr_user_name), user_name_len);
77                 pw_buf[(*num_entries)].user_rid = pwd->user_rid;
78                 memset((char *)pw_buf[(*num_entries)].nt_pwd, '\0', 16);
79
80                 /* Now check if the NT compatible password is available. */
81                 if (pwd->smb_nt_passwd != NULL) {
82                         memcpy( pw_buf[(*num_entries)].nt_pwd , pwd->smb_nt_passwd, 16);
83                 }
84
85                 pw_buf[(*num_entries)].acb_info = (uint16)pwd->acct_ctrl;
86
87                 DEBUG(5, ("entry idx: %d user %s, rid 0x%x, acb %x",
88                           (*num_entries), pwd->smb_name,
89                           pwd->user_rid, pwd->acct_ctrl));
90
91                 if (acb_mask == 0 || IS_BITS_SET_SOME(pwd->acct_ctrl, acb_mask)) {
92                         DEBUG(5,(" acb_mask %x accepts\n", acb_mask));
93                         (*num_entries)++;
94                 } else {
95                         DEBUG(5,(" acb_mask %x rejects\n", acb_mask));
96                 }
97
98                 (*total_entries)++;
99         }
100
101         endsmbpwent(vp);
102
103         return (*num_entries) > 0;
104 }
105
106 /*******************************************************************
107  This function uses the username map file and tries to map a UNIX
108  user name to an DOS name.  (Sort of the reverse of the
109  map_username() function.)  Since more than one DOS name can map
110  to the UNIX name, to reverse the mapping you have to specify
111  which corresponding DOS name you want; that's where the name_idx
112  parameter comes in.  Returns the string requested or NULL if it
113  fails or can't complete the request for any reason.  This doesn't
114  handle group names (starting with '@') or names starting with
115  '+' or '&'.  If they are encountered, they are skipped.
116 ********************************************************************/
117
118 static char *unmap_unixname(char *unix_user_name, int name_idx)
119 {
120         char *mapfile = lp_username_map();
121         char **lines;
122         static pstring tok;
123         int i;
124
125         if (!*unix_user_name) return NULL;
126         if (!*mapfile) return NULL;
127
128         lines = file_lines_load(mapfile, NULL);
129         if (!lines) {
130                 DEBUG(0,("unmap_unixname: can't open username map %s\n", mapfile));
131                 return NULL;
132         }
133
134         DEBUG(5,("unmap_unixname: scanning username map %s, index: %d\n", mapfile, name_idx));
135
136         for (i=0; lines[i]; i++) {
137                 char *unixname = lines[i];
138                 char *dosname = strchr(unixname,'=');
139
140                 if (!dosname)
141                         continue;
142
143                 *dosname++ = 0;
144
145                 while (isspace(*unixname))
146                         unixname++;
147                 if ('!' == *unixname) {
148                         unixname++;
149                         while (*unixname && isspace(*unixname))
150                                 unixname++;
151                 }
152     
153                 if (!*unixname || strchr("#;",*unixname))
154                         continue;
155
156                 if (strncmp(unixname, unix_user_name, strlen(unix_user_name)))
157                         continue;
158
159                 /* We have matched the UNIX user name */
160
161                 while(next_token(&dosname, tok, LIST_SEP, sizeof(tok))) {
162                         if (!strchr("@&+", *tok)) {
163                                 name_idx--;
164                                 if (name_idx < 0 ) {
165                                         break;
166                                 }
167                         }
168                 }
169
170                 if (name_idx >= 0) {
171                         DEBUG(0,("unmap_unixname: index too high - not that many DOS names\n"));
172                         file_lines_free(lines);
173                         return NULL;
174                 } else {
175                         file_lines_free(lines);
176                         return tok;
177                 }
178         }
179
180         DEBUG(0,("unmap_unixname: Couldn't find the UNIX user name\n"));
181         file_lines_free(lines);
182         return NULL;
183 }
184
185 /*******************************************************************
186  This function sets up a list of users taken from the list of
187  users that UNIX knows about, as well as all the user names that
188  Samba maps to a valid UNIX user name.  (This should work with
189  /etc/passwd or NIS.)
190 ********************************************************************/
191
192 static BOOL get_passwd_entries(SAM_USER_INFO_21 *pw_buf,
193                                 int start_idx,
194                                 int *total_entries, int *num_entries,
195                                 int max_num_entries,
196                                 uint16 acb_mask)
197 {
198         static struct passwd *pwd = NULL;
199         static uint32 pw_rid;
200         static BOOL orig_done = False;
201         static int current_idx = 0;
202         static int mapped_idx = 0;
203         char *sep;
204
205         DEBUG(5, ("get_passwd_entries: retrieving a list of UNIX users\n"));
206
207         (*num_entries) = 0;
208         (*total_entries) = 0;
209
210         if (pw_buf == NULL) return False;
211
212         if (current_idx == 0) {
213                 setpwent();
214         }
215
216         /* These two cases are inefficient, but should be called very rarely */
217         /* they are the cases where the starting index isn't picking up      */
218         /* where we left off last time.  It is efficient when it starts over */
219         /* at zero though.                                                   */
220         if (start_idx > current_idx) {
221                 /* We aren't far enough; advance to start_idx */
222                 while (current_idx < start_idx) {
223                         char *unmap_name;
224
225                         if(!orig_done) {
226                                 if ((pwd = getpwent()) == NULL) break;
227                                 current_idx++;
228                                 orig_done = True;
229                         }
230
231                         while (((unmap_name = unmap_unixname(pwd->pw_name, mapped_idx)) != NULL) && 
232                                 (current_idx < start_idx)) {
233                                 current_idx++;
234                                 mapped_idx++;
235                         }
236
237                         if (unmap_name == NULL) {
238                                 orig_done = False;
239                                 mapped_idx = 0;
240                         }
241                 }
242         } else if (start_idx < current_idx) {
243                 /* We are already too far; start over and advance to start_idx */
244                 endpwent();
245                 setpwent();
246                 current_idx = 0;
247                 mapped_idx = 0;
248                 orig_done = False;
249                 while (current_idx < start_idx) {
250                         char *unmap_name;
251
252                         if(!orig_done) {
253                                 if ((pwd = getpwent()) == NULL) break;
254                                 current_idx++;
255                                 orig_done = True;
256                         }
257
258                         while (((unmap_name = unmap_unixname(pwd->pw_name, mapped_idx)) != NULL) && 
259                                 (current_idx < start_idx)) {
260                                 current_idx++;
261                                 mapped_idx++;
262                         }
263
264                         if (unmap_name == NULL) {
265                                 orig_done = False;
266                                 mapped_idx = 0;
267                         }
268                 }
269         }
270
271         sep = lp_winbind_separator();
272
273         /* now current_idx == start_idx */
274         while ((*num_entries) < max_num_entries) {
275                 int user_name_len;
276                 char *unmap_name;
277
278                 /* This does the original UNIX user itself */
279                 if(!orig_done) {
280                         if ((pwd = getpwent()) == NULL) break;
281
282                         /* Don't enumerate winbind users as they are not local */
283
284                         if (strchr(pwd->pw_name, *sep) != NULL) {
285                                 continue;
286                         }
287
288                         user_name_len = strlen(pwd->pw_name);
289                         pw_rid = pdb_uid_to_user_rid(pwd->pw_uid);
290                         ZERO_STRUCTP(&pw_buf[(*num_entries)]);
291                         init_unistr2(&(pw_buf[(*num_entries)].uni_user_name), pwd->pw_name, user_name_len);
292                         init_uni_hdr(&(pw_buf[(*num_entries)].hdr_user_name), user_name_len);
293                         pw_buf[(*num_entries)].user_rid = pw_rid;
294                         memset((char *)pw_buf[(*num_entries)].nt_pwd, '\0', 16);
295
296                         pw_buf[(*num_entries)].acb_info = ACB_NORMAL;
297
298                         DEBUG(5, ("get_passwd_entries: entry idx %d user %s, rid 0x%x\n", (*num_entries), pwd->pw_name, pw_rid));
299
300                         (*num_entries)++;
301                         (*total_entries)++;
302                         current_idx++;
303                         orig_done = True;
304                 }
305
306                 /* This does all the user names that map to the UNIX user */
307                 while (((unmap_name = unmap_unixname(pwd->pw_name, mapped_idx)) != NULL) && 
308                         (*num_entries < max_num_entries)) {
309                         user_name_len = strlen(unmap_name);
310                         ZERO_STRUCTP(&pw_buf[(*num_entries)]);
311                         init_unistr2(&(pw_buf[(*num_entries)].uni_user_name), unmap_name, user_name_len);
312                         init_uni_hdr(&(pw_buf[(*num_entries)].hdr_user_name), user_name_len);
313                         pw_buf[(*num_entries)].user_rid = pw_rid;
314                         memset((char *)pw_buf[(*num_entries)].nt_pwd, '\0', 16);
315
316                         pw_buf[(*num_entries)].acb_info = ACB_NORMAL;
317
318                         DEBUG(5, ("get_passwd_entries: entry idx %d user %s, rid 0x%x\n", (*num_entries), pwd->pw_name, pw_rid));
319
320                         (*num_entries)++;
321                         (*total_entries)++;
322                         current_idx++;
323                         mapped_idx++;
324                 }
325
326                 if (unmap_name == NULL) {
327                         /* done with 'aliases', go on to next UNIX user */
328                         orig_done = False;
329                         mapped_idx = 0;
330                 }
331         }
332
333         if (pwd == NULL) {
334                 /* totally done, reset everything */
335                 endpwent();
336                 current_idx = 0;
337                 mapped_idx = 0;
338         }
339
340         return (*num_entries) > 0;
341 }
342
343 /*******************************************************************
344  samr_reply_unknown_1
345  ********************************************************************/
346 static BOOL samr_reply_close_hnd(SAMR_Q_CLOSE_HND *q_u,
347                                 prs_struct *rdata)
348 {
349         SAMR_R_CLOSE_HND r_u;
350
351         /* set up the SAMR unknown_1 response */
352         memset((char *)r_u.pol.data, '\0', POL_HND_SIZE);
353
354         /* close the policy handle */
355         if (close_lsa_policy_hnd(&(q_u->pol)))
356         {
357                 r_u.status = 0;
358         }
359         else
360         {
361                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_INVALID;
362         }
363
364         DEBUG(5,("samr_reply_close_hnd: %d\n", __LINE__));
365
366         /* store the response in the SMB stream */
367         if(!samr_io_r_close_hnd("", &r_u, rdata, 0))
368                 return False;
369
370         DEBUG(5,("samr_reply_close_hnd: %d\n", __LINE__));
371
372         return True;
373 }
374
375 /*******************************************************************
376  api_samr_close_hnd
377  ********************************************************************/
378 static BOOL api_samr_close_hnd(pipes_struct *p)
379 {
380         SAMR_Q_CLOSE_HND q_u;
381         prs_struct *data = &p->in_data.data;
382         prs_struct *rdata = &p->out_data.rdata;
383
384         /* grab the samr unknown 1 */
385         if(!samr_io_q_close_hnd("", &q_u, data, 0))
386                 return False;
387
388         /* construct reply.  always indicate success */
389         if(!samr_reply_close_hnd(&q_u, rdata))
390                 return False;
391
392         return True;
393 }
394
395
396 /*******************************************************************
397  samr_reply_open_domain
398  ********************************************************************/
399 static BOOL samr_reply_open_domain(SAMR_Q_OPEN_DOMAIN *q_u,
400                                 prs_struct *rdata)
401 {
402         SAMR_R_OPEN_DOMAIN r_u;
403         BOOL pol_open = False;
404
405         r_u.status = 0x0;
406
407         /* find the connection policy handle. */
408         if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->connect_pol)) == -1))
409         {
410                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
411         }
412
413         /* get a (unique) handle.  open a policy on it. */
414         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.domain_pol))))
415         {
416                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
417         }
418
419         /* associate the domain SID with the (unique) handle. */
420         if (r_u.status == 0x0 && !set_lsa_policy_samr_sid(&(r_u.domain_pol), &(q_u->dom_sid.sid)))
421         {
422                 /* oh, whoops.  don't know what error message to return, here */
423                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
424         }
425
426         if (r_u.status != 0 && pol_open)
427         {
428                 close_lsa_policy_hnd(&(r_u.domain_pol));
429         }
430
431         DEBUG(5,("samr_open_domain: %d\n", __LINE__));
432
433         /* store the response in the SMB stream */
434         if(!samr_io_r_open_domain("", &r_u, rdata, 0))
435                 return False;
436
437         DEBUG(5,("samr_open_domain: %d\n", __LINE__));
438
439         return True;
440 }
441
442 /*******************************************************************
443  api_samr_open_domain
444  ********************************************************************/
445 static BOOL api_samr_open_domain(pipes_struct *p)
446 {
447         SAMR_Q_OPEN_DOMAIN q_u;
448         prs_struct *data = &p->in_data.data;
449         prs_struct *rdata = &p->out_data.rdata;
450
451         /* grab the samr open */
452         if(!samr_io_q_open_domain("", &q_u, data, 0))
453                 return False;
454
455         /* construct reply.  always indicate success */
456         if(!samr_reply_open_domain(&q_u, rdata))
457                 return False;
458
459         return True;
460 }
461
462
463 /*******************************************************************
464  samr_reply_unknown_2c
465  ********************************************************************/
466 static BOOL samr_reply_unknown_2c(SAMR_Q_UNKNOWN_2C *q_u,
467                                 prs_struct *rdata)
468 {
469         SAMR_R_UNKNOWN_2C r_u;
470         uint32 status = 0x0;
471
472         /* find the policy handle.  open a policy on it. */
473         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->user_pol)) == -1))
474         {
475                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
476         }
477
478         /* find the user's rid */
479         if ((status == 0x0) && (get_lsa_policy_samr_rid(&(q_u->user_pol)) == 0xffffffff))
480         {
481                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
482         }
483
484         init_samr_r_unknown_2c(&r_u, status);
485
486         DEBUG(5,("samr_unknown_2c: %d\n", __LINE__));
487
488         /* store the response in the SMB stream */
489         if(!samr_io_r_unknown_2c("", &r_u, rdata, 0))
490                 return False;
491
492         DEBUG(5,("samr_unknown_2c: %d\n", __LINE__));
493
494         return True;
495 }
496
497 /*******************************************************************
498  api_samr_unknown_2c
499  ********************************************************************/
500 static BOOL api_samr_unknown_2c(pipes_struct *p)
501 {
502         SAMR_Q_UNKNOWN_2C q_u;
503         prs_struct *data = &p->in_data.data;
504         prs_struct *rdata = &p->out_data.rdata;
505
506         /* grab the samr open */
507         if(!samr_io_q_unknown_2c("", &q_u, data, 0))
508                 return False;
509
510         /* construct reply.  always indicate success */
511         if(!samr_reply_unknown_2c(&q_u, rdata))
512                 return False;
513
514         return True;
515 }
516
517
518 /*******************************************************************
519  samr_reply_unknown_3
520  ********************************************************************/
521 static BOOL samr_reply_unknown_3(SAMR_Q_UNKNOWN_3 *q_u,
522                                 prs_struct *rdata)
523 {
524         SAMR_R_UNKNOWN_3 r_u;
525         DOM_SID3 sid[MAX_SAM_SIDS];
526         uint32 rid;
527         uint32 status;
528
529         status = 0x0;
530
531         /* find the policy handle.  open a policy on it. */
532         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->user_pol)) == -1))
533         {
534                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
535         }
536
537         /* find the user's rid */
538         if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->user_pol))) == 0xffffffff)
539         {
540                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
541         }
542
543         if (status == 0x0)
544         {
545                 DOM_SID user_sid;
546                 DOM_SID everyone_sid;
547
548                 user_sid = global_sam_sid;
549
550                 SMB_ASSERT_ARRAY(user_sid.sub_auths, user_sid.num_auths+1);
551
552                 /*
553                  * Add the user RID.
554                  */
555                 user_sid.sub_auths[user_sid.num_auths++] = rid;
556                 
557                         string_to_sid(&everyone_sid, "S-1-1");
558
559                         /* maybe need another 1 or 2 (S-1-5-0x20-0x220 and S-1-5-20-0x224) */
560                         /* these two are DOMAIN_ADMIN and DOMAIN_ACCT_OP group RIDs */
561                         init_dom_sid3(&(sid[0]), 0x035b, 0x0002, &everyone_sid);
562                         init_dom_sid3(&(sid[1]), 0x0044, 0x0002, &user_sid);
563         }
564
565         init_samr_r_unknown_3(&r_u,
566                                 0x0001, 0x8004,
567                                 0x00000014, 0x0002, 0x0070,
568                                 2, sid, status);
569
570         DEBUG(5,("samr_unknown_3: %d\n", __LINE__));
571
572         /* store the response in the SMB stream */
573         if(!samr_io_r_unknown_3("", &r_u, rdata, 0))
574                 return False;
575
576         DEBUG(5,("samr_unknown_3: %d\n", __LINE__));
577
578         return True;
579 }
580
581 /*******************************************************************
582  api_samr_unknown_3
583  ********************************************************************/
584 static BOOL api_samr_unknown_3(pipes_struct *p)
585 {
586         SAMR_Q_UNKNOWN_3 q_u;
587         prs_struct *data = &p->in_data.data;
588         prs_struct *rdata = &p->out_data.rdata;
589
590         /* grab the samr open */
591         if(!samr_io_q_unknown_3("", &q_u, data, 0))
592                 return False;
593
594         /* construct reply.  always indicate success */
595         if(!samr_reply_unknown_3(&q_u, rdata))
596                 return False;
597
598         return True;
599 }
600
601
602 /*******************************************************************
603  samr_reply_enum_dom_users
604  ********************************************************************/
605 static BOOL samr_reply_enum_dom_users(SAMR_Q_ENUM_DOM_USERS *q_u,
606                                 prs_struct *rdata)
607 {
608         SAMR_R_ENUM_DOM_USERS r_e;
609         SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
610         int num_entries;
611         int total_entries;
612
613         r_e.status = 0x0;
614         r_e.total_num_entries = 0;
615
616         /* find the policy handle.  open a policy on it. */
617         if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
618         {
619                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
620         }
621
622         DEBUG(5,("samr_reply_enum_dom_users: %d\n", __LINE__));
623
624         become_root();
625         get_sampwd_entries(pass, 0, &total_entries, &num_entries, MAX_SAM_ENTRIES, q_u->acb_mask);
626         unbecome_root();
627
628         init_samr_r_enum_dom_users(&r_e, total_entries,
629                                    q_u->unknown_0, num_entries,
630                                    pass, r_e.status);
631
632         /* store the response in the SMB stream */
633         if(!samr_io_r_enum_dom_users("", &r_e, rdata, 0))
634                 return False;
635
636         DEBUG(5,("samr_enum_dom_users: %d\n", __LINE__));
637
638         return True;
639 }
640
641 /*******************************************************************
642  api_samr_enum_dom_users
643  ********************************************************************/
644 static BOOL api_samr_enum_dom_users(pipes_struct *p)
645 {
646         SAMR_Q_ENUM_DOM_USERS q_e;
647         prs_struct *data = &p->in_data.data;
648         prs_struct *rdata = &p->out_data.rdata;
649
650         /* grab the samr open */
651         if(!samr_io_q_enum_dom_users("", &q_e, data, 0))
652                 return False;
653
654         /* construct reply. */
655         if(!samr_reply_enum_dom_users(&q_e, rdata))
656                 return False;
657
658         return True;
659 }
660
661 /*******************************************************************
662  samr_reply_enum_dom_groups
663  ********************************************************************/
664 static BOOL samr_reply_enum_dom_groups(SAMR_Q_ENUM_DOM_GROUPS *q_u,
665                                 prs_struct *rdata)
666 {
667         SAMR_R_ENUM_DOM_GROUPS r_e;
668         SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
669         int num_entries;
670         BOOL got_grps;
671         char *dummy_group = "Domain Admins";
672
673         r_e.status = 0x0;
674         r_e.num_entries = 0;
675
676         /* find the policy handle.  open a policy on it. */
677         if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
678         {
679                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
680         }
681
682         DEBUG(5,("samr_reply_enum_dom_groups: %d\n", __LINE__));
683
684         got_grps = True;
685         num_entries = 1;
686         ZERO_STRUCTP(&pass[0]);
687         init_unistr2(&(pass[0].uni_user_name), dummy_group, strlen(dummy_group));
688         pass[0].user_rid = DOMAIN_GROUP_RID_ADMINS;
689
690         if (r_e.status == 0 && got_grps)
691         {
692                 init_samr_r_enum_dom_groups(&r_e, q_u->start_idx, num_entries, pass, r_e.status);
693         }
694
695         /* store the response in the SMB stream */
696         if(!samr_io_r_enum_dom_groups("", &r_e, rdata, 0))
697                 return False;
698
699         DEBUG(5,("samr_enum_dom_groups: %d\n", __LINE__));
700
701         return True;
702 }
703
704 /*******************************************************************
705  api_samr_enum_dom_groups
706  ********************************************************************/
707 static BOOL api_samr_enum_dom_groups(pipes_struct *p)
708 {
709         SAMR_Q_ENUM_DOM_GROUPS q_e;
710         prs_struct *data = &p->in_data.data;
711         prs_struct *rdata = &p->out_data.rdata;
712
713         /* grab the samr open */
714         if(!samr_io_q_enum_dom_groups("", &q_e, data, 0))
715                 return False;
716
717         /* construct reply. */
718         if(!samr_reply_enum_dom_groups(&q_e, rdata))
719                 return False;
720
721         return True;
722 }
723
724 /*******************************************************************
725  samr_reply_enum_dom_aliases
726  ********************************************************************/
727 static BOOL samr_reply_enum_dom_aliases(SAMR_Q_ENUM_DOM_ALIASES *q_u,
728                                 prs_struct *rdata)
729 {
730         SAMR_R_ENUM_DOM_ALIASES r_e;
731         SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
732         int num_entries = 0;
733         DOM_SID sid;
734         fstring sid_str;
735         fstring sam_sid_str;
736         struct group *grp;
737
738         r_e.status = 0x0;
739         r_e.num_entries = 0;
740
741         /* find the policy handle.  open a policy on it. */
742         if (r_e.status == 0x0 && !get_lsa_policy_samr_sid(&q_u->pol, &sid))
743         {
744                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
745         }
746
747         sid_to_string(sid_str, &sid);
748         sid_to_string(sam_sid_str, &global_sam_sid);
749
750         DEBUG(5,("samr_reply_enum_dom_aliases: sid %s\n", sid_str));
751
752         /* well-known aliases */
753         if (strequal(sid_str, "S-1-5-32"))
754         {
755                 char *name;
756                 while (num_entries < MAX_SAM_ENTRIES && ((name = builtin_alias_rids[num_entries].name) != NULL))
757                 {
758                         init_unistr2(&(pass[num_entries].uni_user_name), name, strlen(name));
759                         pass[num_entries].user_rid = builtin_alias_rids[num_entries].rid;
760                         num_entries++;
761                 }
762         }
763         else if (strequal(sid_str, sam_sid_str))
764         {
765                 char *name;
766                 char *sep;
767
768                 sep = lp_winbind_separator();
769
770                 /* local aliases */
771                 /* we return the UNIX groups here.  This seems to be the right */
772                 /* thing to do, since NT member servers return their local     */
773                 /* groups in the same situation.                               */
774                 setgrent();
775
776                 while (num_entries < MAX_SAM_ENTRIES && ((grp = getgrent()) != NULL))
777                 {
778                         name = grp->gr_name;
779
780                         /* Don't return winbind groups as they are not local! */
781
782                         if (strchr(name, *sep) != NULL) {
783                                 continue;
784                         }
785
786                         init_unistr2(&(pass[num_entries].uni_user_name), name, strlen(name));
787                         pass[num_entries].user_rid = pdb_gid_to_group_rid(grp->gr_gid);
788                         num_entries++;
789                 }
790
791                 endgrent();
792         }
793                 
794         init_samr_r_enum_dom_aliases(&r_e, num_entries, pass, r_e.status);
795
796         /* store the response in the SMB stream */
797         if(!samr_io_r_enum_dom_aliases("", &r_e, rdata, 0))
798                 return False;
799
800         DEBUG(5,("samr_enum_dom_aliases: %d\n", __LINE__));
801
802         return True;
803 }
804
805 /*******************************************************************
806  api_samr_enum_dom_aliases
807  ********************************************************************/
808 static BOOL api_samr_enum_dom_aliases(pipes_struct *p)
809 {
810         SAMR_Q_ENUM_DOM_ALIASES q_e;
811         prs_struct *data = &p->in_data.data;
812         prs_struct *rdata = &p->out_data.rdata;
813
814         /* grab the samr open */
815         if(!samr_io_q_enum_dom_aliases("", &q_e, data, 0))
816                 return False;
817
818         /* construct reply. */
819         if(!samr_reply_enum_dom_aliases(&q_e, rdata))
820                 return False;
821
822         return True;
823 }
824
825
826 /*******************************************************************
827  samr_reply_query_dispinfo
828  ********************************************************************/
829 static BOOL samr_reply_query_dispinfo(SAMR_Q_QUERY_DISPINFO *q_u, prs_struct *rdata)
830 {
831         SAMR_R_QUERY_DISPINFO r_e;
832         SAM_INFO_CTR ctr;
833         SAM_INFO_1 info1;
834         SAM_INFO_2 info2;
835         SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
836         int num_entries = 0;
837         int total_entries = 0;
838         BOOL got_pwds;
839         uint16 switch_level = 0x0;
840
841         ZERO_STRUCT(r_e);
842
843         r_e.status = 0x0;
844
845         DEBUG(5,("samr_reply_query_dispinfo: %d\n", __LINE__));
846
847         /* find the policy handle.  open a policy on it. */
848         if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
849         {
850                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
851                 DEBUG(5,("samr_reply_query_dispinfo: invalid handle\n"));
852         }
853
854         if (r_e.status == 0x0)
855         {
856           /* decide how many entries to get depending on the max_entries 
857              and max_size passed by client */
858           uint32 retsize;
859
860           if(q_u->max_entries > MAX_SAM_ENTRIES)
861             q_u->max_entries = MAX_SAM_ENTRIES;
862           
863           retsize = (q_u->max_entries * (sizeof(SAM_ENTRY1)+sizeof(SAM_STR1)))
864             + 3*sizeof(uint32);
865
866           if(retsize > q_u->max_size)
867             {
868               /* determine max_entries based on max_size */
869               q_u->max_entries = (q_u->max_size - 3*sizeof(uint32)) /
870                 (sizeof(SAM_ENTRY1)+sizeof(SAM_STR1));
871               q_u->max_entries = (q_u->max_entries>0?q_u->max_entries:1);
872             }
873
874           DEBUG(10,("samr_reply_query_dispinfo: Setting q_u->max_entries to %u\n",q_u->max_entries));
875
876                 become_root();
877                 got_pwds = get_passwd_entries(pass, q_u->start_idx, &total_entries, &num_entries, q_u->max_entries, 0);
878                 unbecome_root();
879
880                 /* more left - set resume handle */
881                 if(total_entries > num_entries)
882                   {
883                     r_e.status = 0x105;
884                   }
885
886                 switch (q_u->switch_level)
887                 {
888                         case 0x1:
889                         {
890                         
891                                 /* query disp info is for users */
892                                 switch_level = 0x1;
893                                 init_sam_info_1(&info1, ACB_NORMAL,
894                                         q_u->start_idx, num_entries, pass);
895
896                                 ctr.sam.info1 = &info1;
897
898                                 break;
899                         }
900                         case 0x2:
901                         {
902                                 /* query disp info is for servers */
903                                 switch_level = 0x2;
904                                 init_sam_info_2(&info2, ACB_WSTRUST,
905                                         q_u->start_idx, num_entries, pass);
906
907                                 ctr.sam.info2 = &info2;
908
909                                 break;
910                         }
911                 }
912         }
913
914         /* more left - set resume handle */
915         if(total_entries > num_entries)
916           {
917             r_e.status = 0x105;
918           }
919
920         if (r_e.status == 0 || r_e.status == 0x105)
921         {
922           init_samr_r_query_dispinfo(&r_e, switch_level, &ctr, r_e.status);
923         }
924
925         /* store the response in the SMB stream */
926         if(!samr_io_r_query_dispinfo("", &r_e, rdata, 0))
927                 return False;
928
929         DEBUG(5,("samr_query_dispinfo: %d\n", __LINE__));
930
931         return True;
932 }
933
934 /*******************************************************************
935  api_samr_query_dispinfo
936  ********************************************************************/
937 static BOOL api_samr_query_dispinfo(pipes_struct *p)
938 {
939         SAMR_Q_QUERY_DISPINFO q_e;
940         prs_struct *data = &p->in_data.data;
941         prs_struct *rdata = &p->out_data.rdata;
942
943         /* grab the samr open */
944         if(!samr_io_q_query_dispinfo("", &q_e, data, 0))
945                 return False;
946
947         /* construct reply. */
948         if(!samr_reply_query_dispinfo(&q_e, rdata))
949                 return False;
950
951         return True;
952 }
953
954
955 /*******************************************************************
956  samr_reply_query_aliasinfo
957  ********************************************************************/
958 static BOOL samr_reply_query_aliasinfo(SAMR_Q_QUERY_ALIASINFO *q_u,
959                                 prs_struct *rdata)
960 {
961   SAMR_R_QUERY_ALIASINFO r_e;
962   fstring alias_desc = "Local Unix group";
963   fstring alias="";
964   uint8 type;
965   uint32 alias_rid;
966
967   ZERO_STRUCT(r_e);
968
969   DEBUG(5,("samr_reply_query_aliasinfo: %d\n", __LINE__));
970
971   /* find the policy handle.  open a policy on it. */
972   if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
973     {
974       r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
975     }
976
977   alias_rid = get_lsa_policy_samr_rid(&q_u->pol);
978   if(alias_rid == 0xffffffff)
979       r_e.status = 0xC0000000 | NT_STATUS_NO_SUCH_ALIAS;
980
981   if(!lookup_local_rid(alias_rid, alias, &type))
982     {
983       r_e.status = 0xC0000000 | NT_STATUS_NO_SUCH_ALIAS;
984     }
985   
986   init_samr_r_query_aliasinfo(&r_e, q_u->switch_level, alias, alias_desc);
987   
988   /* store the response in the SMB stream */
989   if(!samr_io_r_query_aliasinfo("", &r_e, rdata, 0))
990                 return False;
991   
992   DEBUG(5,("samr_query_aliasinfo: %d\n", __LINE__));
993
994         return True;
995 }
996
997 /*******************************************************************
998  api_samr_query_aliasinfo
999  ********************************************************************/
1000 static BOOL api_samr_query_aliasinfo(pipes_struct *p)
1001 {
1002         SAMR_Q_QUERY_ALIASINFO q_e;
1003         prs_struct *data = &p->in_data.data;
1004         prs_struct *rdata = &p->out_data.rdata;
1005
1006         /* grab the samr open */
1007         if(!samr_io_q_query_aliasinfo("", &q_e, data, 0))
1008                 return False;
1009
1010         /* construct reply. */
1011         if(!samr_reply_query_aliasinfo(&q_e, rdata))
1012                 return False;
1013
1014         return True;
1015 }
1016
1017
1018 /*******************************************************************
1019  samr_reply_lookup_ids
1020  ********************************************************************/
1021 static BOOL samr_reply_lookup_ids(SAMR_Q_LOOKUP_IDS *q_u,
1022                                 prs_struct *rdata)
1023 {
1024         uint32 rid[MAX_SAM_ENTRIES];
1025         uint32 status     = 0;
1026         int num_rids = q_u->num_sids1;
1027
1028         SAMR_R_LOOKUP_IDS r_u;
1029
1030         DEBUG(5,("samr_lookup_ids: %d\n", __LINE__));
1031
1032         if (num_rids > MAX_SAM_ENTRIES)
1033         {
1034                 num_rids = MAX_SAM_ENTRIES;
1035                 DEBUG(5,("samr_lookup_ids: truncating entries to %d\n", num_rids));
1036         }
1037
1038 #if 0
1039         int i;
1040         SMB_ASSERT_ARRAY(q_u->uni_user_name, num_rids);
1041
1042         for (i = 0; i < num_rids && status == 0; i++)
1043         {
1044                 struct sam_passwd *sam_pass;
1045                 fstring user_name;
1046
1047
1048                 fstrcpy(user_name, unistrn2(q_u->uni_user_name[i].buffer,
1049                                             q_u->uni_user_name[i].uni_str_len));
1050
1051                 /* find the user account */
1052                 become_root();
1053                 sam_pass = get_smb21pwd_entry(user_name, 0);
1054                 unbecome_root();
1055
1056                 if (sam_pass == NULL)
1057                 {
1058                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
1059                         rid[i] = 0;
1060                 }
1061                 else
1062                 {
1063                         rid[i] = sam_pass->user_rid;
1064                 }
1065         }
1066 #endif
1067
1068         num_rids = 1;
1069         rid[0] = BUILTIN_ALIAS_RID_USERS;
1070
1071         init_samr_r_lookup_ids(&r_u, num_rids, rid, status);
1072
1073         /* store the response in the SMB stream */
1074         if(!samr_io_r_lookup_ids("", &r_u, rdata, 0))
1075                 return False;
1076
1077         DEBUG(5,("samr_lookup_ids: %d\n", __LINE__));
1078
1079         return True;
1080 }
1081
1082 /*******************************************************************
1083  api_samr_lookup_ids
1084  ********************************************************************/
1085 static BOOL api_samr_lookup_ids(pipes_struct *p)
1086 {
1087         SAMR_Q_LOOKUP_IDS q_u;
1088         prs_struct *data = &p->in_data.data;
1089         prs_struct *rdata = &p->out_data.rdata;
1090
1091         /* grab the samr 0x10 */
1092         if(!samr_io_q_lookup_ids("", &q_u, data, 0))
1093                 return False;
1094
1095         /* construct reply.  always indicate success */
1096         if(!samr_reply_lookup_ids(&q_u, rdata))
1097                 return False;
1098
1099         return True;
1100 }
1101
1102 /*******************************************************************
1103  samr_reply_lookup_names
1104  ********************************************************************/
1105
1106 static BOOL samr_reply_lookup_names(SAMR_Q_LOOKUP_NAMES *q_u,
1107                                     prs_struct *rdata)
1108 {
1109   uint32 rid[MAX_SAM_ENTRIES];
1110   uint8  type[MAX_SAM_ENTRIES];
1111   uint32 status = 0;
1112   int i;
1113   int num_rids = q_u->num_names1;
1114   DOM_SID pol_sid;
1115
1116   SAMR_R_LOOKUP_NAMES r_u;
1117
1118   DEBUG(5,("samr_lookup_names: %d\n", __LINE__));
1119
1120   ZERO_ARRAY(rid);
1121   ZERO_ARRAY(type);
1122
1123   if (!get_lsa_policy_samr_sid(&q_u->pol, &pol_sid)) {
1124     status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH;
1125     init_samr_r_lookup_names(&r_u, 0, rid, type, status);
1126     if(!samr_io_r_lookup_names("", &r_u, rdata, 0)) {
1127       DEBUG(0,("samr_reply_lookup_names: failed to marshall SAMR_R_LOOKUP_NAMES.\n"));
1128       return False;
1129     }
1130     return True;
1131   }
1132
1133   if (num_rids > MAX_SAM_ENTRIES) {
1134     num_rids = MAX_SAM_ENTRIES;
1135     DEBUG(5,("samr_lookup_names: truncating entries to %d\n", num_rids));
1136   }
1137
1138   SMB_ASSERT_ARRAY(q_u->uni_name, num_rids);
1139
1140   for (i = 0; i < num_rids; i++) {
1141     fstring name;
1142
1143     status = 0xC0000000 | NT_STATUS_NONE_MAPPED;
1144
1145     rid [i] = 0xffffffff;
1146     type[i] = SID_NAME_UNKNOWN;
1147
1148     fstrcpy(name, dos_unistrn2(q_u->uni_name[i].buffer,
1149                                q_u->uni_name[i].uni_str_len));
1150
1151     if(sid_equal(&pol_sid, &global_sam_sid)) 
1152     {
1153       DOM_SID sid;
1154       if(lookup_local_name(global_myname, name, 
1155                            &sid, &type[i]))
1156         {
1157           sid_split_rid( &sid, &rid[i]);
1158           status = 0;
1159         }
1160     }
1161   }
1162
1163   init_samr_r_lookup_names(&r_u, num_rids, rid, type, status);
1164
1165   /* store the response in the SMB stream */
1166   if(!samr_io_r_lookup_names("", &r_u, rdata, 0)) {
1167     DEBUG(0,("samr_reply_lookup_names: failed to marshall SAMR_R_LOOKUP_NAMES.\n"));
1168     return False;
1169   }
1170
1171   DEBUG(5,("samr_lookup_names: %d\n", __LINE__));
1172
1173   return True;
1174 }
1175
1176 /*******************************************************************
1177  api_samr_lookup_names
1178  ********************************************************************/
1179
1180 static BOOL api_samr_lookup_names(pipes_struct *p)
1181 {
1182         SAMR_Q_LOOKUP_NAMES q_u;
1183         prs_struct *data = &p->in_data.data;
1184         prs_struct *rdata = &p->out_data.rdata;
1185
1186         memset(&q_u, '\0', sizeof(q_u));
1187
1188         /* grab the samr lookup names */
1189         if(!samr_io_q_lookup_names("", &q_u, data, 0)) {
1190                 DEBUG(0,("api_samr_lookup_names: failed to unmarshall SAMR_Q_LOOKUP_NAMES.\n"));
1191                 return False;
1192         }
1193
1194         /* construct reply.  always indicate success */
1195         if(!samr_reply_lookup_names(&q_u, rdata))
1196                 return False;
1197
1198         return True;
1199 }
1200
1201 /*******************************************************************
1202  samr_reply_chgpasswd_user
1203  ********************************************************************/
1204
1205 static BOOL samr_reply_chgpasswd_user(SAMR_Q_CHGPASSWD_USER *q_u,
1206                                 prs_struct *rdata)
1207 {
1208         SAMR_R_CHGPASSWD_USER r_u;
1209         uint32 status = 0x0;
1210         fstring user_name;
1211         fstring wks;
1212
1213         fstrcpy(user_name, dos_unistrn2(q_u->uni_user_name.buffer, q_u->uni_user_name.uni_str_len));
1214         fstrcpy(wks      , dos_unistrn2(q_u->uni_dest_host.buffer, q_u->uni_dest_host.uni_str_len));
1215
1216         DEBUG(5,("samr_chgpasswd_user: user: %s wks: %s\n", user_name, wks));
1217
1218         if (!pass_oem_change(user_name,
1219                              q_u->lm_newpass.pass, q_u->lm_oldhash.hash,
1220                              q_u->nt_newpass.pass, q_u->nt_oldhash.hash))
1221         {
1222                 status = 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
1223         }
1224
1225         init_samr_r_chgpasswd_user(&r_u, status);
1226
1227         /* store the response in the SMB stream */
1228         if(!samr_io_r_chgpasswd_user("", &r_u, rdata, 0)) {
1229                 DEBUG(0,("samr_reply_chgpasswd_user: Failed to marshall SAMR_R_CHGPASSWD_USER struct.\n" ));
1230                 return False;
1231         }
1232
1233         DEBUG(5,("samr_chgpasswd_user: %d\n", __LINE__));
1234         return True;
1235 }
1236
1237 /*******************************************************************
1238  api_samr_chgpasswd_user
1239  ********************************************************************/
1240
1241 static BOOL api_samr_chgpasswd_user(pipes_struct *p)
1242 {
1243         SAMR_Q_CHGPASSWD_USER q_u;
1244         prs_struct *data = &p->in_data.data;
1245         prs_struct *rdata = &p->out_data.rdata;
1246
1247         /* unknown 38 command */
1248         if (!samr_io_q_chgpasswd_user("", &q_u, data, 0)) {
1249                 DEBUG(0,("api_samr_chgpasswd_user: samr_io_q_chgpasswd_user failed to parse RPC packet.\n"));
1250                 return False;
1251         }
1252
1253         /* construct reply. */
1254         if(!samr_reply_chgpasswd_user(&q_u, rdata)) {
1255                 DEBUG(0,("api_samr_chgpasswd_user: samr_reply_chgpasswd_user failed to create reply packet.\n"));
1256                 return False;
1257         }
1258
1259         return True;
1260 }
1261
1262
1263 /*******************************************************************
1264  samr_reply_unknown_38
1265  ********************************************************************/
1266 static BOOL samr_reply_unknown_38(SAMR_Q_UNKNOWN_38 *q_u, prs_struct *rdata)
1267 {
1268         SAMR_R_UNKNOWN_38 r_u;
1269
1270         DEBUG(5,("samr_unknown_38: %d\n", __LINE__));
1271
1272         init_samr_r_unknown_38(&r_u);
1273
1274         /* store the response in the SMB stream */
1275         if(!samr_io_r_unknown_38("", &r_u, rdata, 0))
1276                 return False;
1277
1278         DEBUG(5,("samr_unknown_38: %d\n", __LINE__));
1279         return True;
1280 }
1281
1282 /*******************************************************************
1283  api_samr_unknown_38
1284  ********************************************************************/
1285 static BOOL api_samr_unknown_38(pipes_struct *p)
1286 {
1287         SAMR_Q_UNKNOWN_38 q_u;
1288         prs_struct *data = &p->in_data.data;
1289         prs_struct *rdata = &p->out_data.rdata;
1290
1291         /* unknown 38 command */
1292         if(!samr_io_q_unknown_38("", &q_u, data, 0))
1293                 return False;
1294
1295         /* construct reply.  always indicate success */
1296         if(!samr_reply_unknown_38(&q_u, rdata))
1297                 return False;
1298
1299         return True;
1300 }
1301
1302
1303 /*******************************************************************
1304  samr_reply_unknown_12
1305  ********************************************************************/
1306 static BOOL samr_reply_unknown_12(SAMR_Q_UNKNOWN_12 *q_u,
1307                                 prs_struct *rdata)
1308 {
1309         fstring group_names[MAX_SAM_ENTRIES];
1310         uint32  group_attrs[MAX_SAM_ENTRIES];
1311         uint32 status     = 0;
1312         int num_gids = q_u->num_gids1;
1313
1314         SAMR_R_UNKNOWN_12 r_u;
1315
1316         DEBUG(5,("samr_unknown_12: %d\n", __LINE__));
1317
1318         /* find the policy handle.  open a policy on it. */
1319         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
1320         {
1321                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1322         }
1323
1324         if (status == 0x0)
1325         {
1326                 int i;
1327                 if (num_gids > MAX_SAM_ENTRIES)
1328                 {
1329                         num_gids = MAX_SAM_ENTRIES;
1330                         DEBUG(5,("samr_unknown_12: truncating entries to %d\n", num_gids));
1331                 }
1332
1333                 for (i = 0; i < num_gids && status == 0; i++)
1334                 {
1335                         fstrcpy(group_names[i], "dummy group");
1336                         group_attrs[i] = 0x2;
1337                 }
1338         }
1339
1340         init_samr_r_unknown_12(&r_u, num_gids, group_names, group_attrs, status);
1341
1342         /* store the response in the SMB stream */
1343         if(!samr_io_r_unknown_12("", &r_u, rdata, 0))
1344                 return False;
1345
1346         DEBUG(5,("samr_unknown_12: %d\n", __LINE__));
1347
1348         return True;
1349 }
1350
1351 /*******************************************************************
1352  api_samr_unknown_12
1353  ********************************************************************/
1354 static BOOL api_samr_unknown_12(pipes_struct *p)
1355 {
1356         SAMR_Q_UNKNOWN_12 q_u;
1357         prs_struct *data = &p->in_data.data;
1358         prs_struct *rdata = &p->out_data.rdata;
1359
1360         /* grab the samr lookup names */
1361         if(!samr_io_q_unknown_12("", &q_u, data, 0))
1362                 return False;
1363
1364         /* construct reply.  always indicate success */
1365         if(!samr_reply_unknown_12(&q_u, rdata))
1366                 return False;
1367
1368         return True;
1369 }
1370
1371
1372 /*******************************************************************
1373  samr_reply_open_user
1374  ********************************************************************/
1375 static BOOL samr_reply_open_user(SAMR_Q_OPEN_USER *q_u, prs_struct *rdata, int status)
1376 {
1377         SAMR_R_OPEN_USER r_u;
1378         struct sam_passwd *sam_pass;
1379         BOOL pol_open = False;
1380
1381         /* set up the SAMR open_user response */
1382         memset((char *)r_u.user_pol.data, '\0', POL_HND_SIZE);
1383
1384         r_u.status = 0x0;
1385
1386         /* find the policy handle.  open a policy on it. */
1387         if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1))
1388         {
1389                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1390         }
1391
1392         /* get a (unique) handle.  open a policy on it. */
1393         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.user_pol))))
1394         {
1395                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1396         }
1397
1398         become_root();
1399         sam_pass = getsam21pwrid(q_u->user_rid);
1400         unbecome_root();
1401
1402         /* check that the RID exists in our domain. */
1403         if (r_u.status == 0x0 && sam_pass == NULL)
1404         {
1405                 r_u.status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
1406         }
1407
1408         /* associate the RID with the (unique) handle. */
1409         if (r_u.status == 0x0 && !set_lsa_policy_samr_rid(&(r_u.user_pol), q_u->user_rid))
1410         {
1411                 /* oh, whoops.  don't know what error message to return, here */
1412                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1413         }
1414
1415         if (r_u.status != 0 && pol_open)
1416         {
1417                 close_lsa_policy_hnd(&(r_u.user_pol));
1418         }
1419
1420         DEBUG(5,("samr_open_user: %d\n", __LINE__));
1421
1422         /* store the response in the SMB stream */
1423         if(!samr_io_r_open_user("", &r_u, rdata, 0))
1424                 return False;
1425
1426         DEBUG(5,("samr_open_user: %d\n", __LINE__));
1427
1428         return True;
1429 }
1430
1431 /*******************************************************************
1432  api_samr_open_user
1433  ********************************************************************/
1434 static BOOL api_samr_open_user(pipes_struct *p)
1435 {
1436         SAMR_Q_OPEN_USER q_u;
1437         prs_struct *data = &p->in_data.data;
1438         prs_struct *rdata = &p->out_data.rdata;
1439
1440         /* grab the samr unknown 22 */
1441         if(!samr_io_q_open_user("", &q_u, data, 0))
1442                 return False;
1443
1444         /* construct reply.  always indicate success */
1445         if(!samr_reply_open_user(&q_u, rdata, 0x0))
1446                 return False;
1447
1448         return True;
1449 }
1450
1451
1452 /*************************************************************************
1453  get_user_info_10
1454  *************************************************************************/
1455 static BOOL get_user_info_10(SAM_USER_INFO_10 *id10, uint32 user_rid)
1456 {
1457         struct smb_passwd *smb_pass;
1458
1459         if (!pdb_rid_is_user(user_rid))
1460         {
1461                 DEBUG(4,("RID 0x%x is not a user RID\n", user_rid));
1462                 return False;
1463         }
1464
1465         become_root();
1466         smb_pass = getsmbpwrid(user_rid);
1467         unbecome_root();
1468
1469         if (smb_pass == NULL)
1470         {
1471                 DEBUG(4,("User 0x%x not found\n", user_rid));
1472                 return False;
1473         }
1474
1475         DEBUG(3,("User:[%s]\n", smb_pass->smb_name));
1476
1477         init_sam_user_info10(id10, smb_pass->acct_ctrl); 
1478
1479         return True;
1480 }
1481
1482 /*************************************************************************
1483  get_user_info_21
1484  *************************************************************************/
1485 static BOOL get_user_info_21(SAM_USER_INFO_21 *id21, uint32 user_rid)
1486 {
1487         NTTIME dummy_time;
1488         struct sam_passwd *sam_pass;
1489         LOGON_HRS hrs;
1490         int i;
1491
1492         if (!pdb_rid_is_user(user_rid))
1493         {
1494                 DEBUG(4,("RID 0x%x is not a user RID\n", user_rid));
1495                 return False;
1496         }
1497
1498         become_root();
1499         sam_pass = getsam21pwrid(user_rid);
1500         unbecome_root();
1501
1502         if (sam_pass == NULL)
1503         {
1504                 DEBUG(4,("User 0x%x not found\n", user_rid));
1505                 return False;
1506         }
1507
1508         DEBUG(3,("User:[%s]\n", sam_pass->smb_name));
1509
1510         dummy_time.low  = 0xffffffff;
1511         dummy_time.high = 0x7fffffff;
1512
1513         DEBUG(5,("get_user_info_21 - TODO: convert unix times to NTTIMEs\n"));
1514
1515         /* create a LOGON_HRS structure */
1516         hrs.len = sam_pass->hours_len;
1517         SMB_ASSERT_ARRAY(hrs.hours, hrs.len);
1518         for (i = 0; i < hrs.len; i++)
1519         {
1520                 hrs.hours[i] = sam_pass->hours[i];
1521         }
1522
1523         init_sam_user_info21(id21,
1524
1525                            &dummy_time, /* logon_time */
1526                            &dummy_time, /* logoff_time */
1527                            &dummy_time, /* kickoff_time */
1528                            &dummy_time, /* pass_last_set_time */
1529                            &dummy_time, /* pass_can_change_time */
1530                            &dummy_time, /* pass_must_change_time */
1531
1532                            sam_pass->smb_name, /* user_name */
1533                            sam_pass->full_name, /* full_name */
1534                            sam_pass->home_dir, /* home_dir */
1535                            sam_pass->dir_drive, /* dir_drive */
1536                            sam_pass->logon_script, /* logon_script */
1537                            sam_pass->profile_path, /* profile_path */
1538                            sam_pass->acct_desc, /* description */
1539                            sam_pass->workstations, /* workstations user can log in from */
1540                            sam_pass->unknown_str, /* don't know, yet */
1541                            sam_pass->munged_dial, /* dialin info.  contains dialin path and tel no */
1542
1543                            sam_pass->user_rid, /* RID user_id */
1544                            sam_pass->group_rid, /* RID group_id */
1545                        sam_pass->acct_ctrl,
1546
1547                    sam_pass->unknown_3, /* unknown_3 */
1548                        sam_pass->logon_divs, /* divisions per week */
1549                            &hrs, /* logon hours */
1550                        sam_pass->unknown_5,
1551                        sam_pass->unknown_6);
1552
1553         return True;
1554 }
1555
1556 /*******************************************************************
1557  samr_reply_query_userinfo
1558  ********************************************************************/
1559 static BOOL samr_reply_query_userinfo(SAMR_Q_QUERY_USERINFO *q_u,
1560                                 prs_struct *rdata)
1561 {
1562         SAMR_R_QUERY_USERINFO r_u;
1563 #if 0
1564         SAM_USER_INFO_11 id11;
1565 #endif
1566         SAM_USER_INFO_10 id10;
1567         SAM_USER_INFO_21 id21;
1568         void *info = NULL;
1569
1570         uint32 status = 0x0;
1571         uint32 rid = 0x0;
1572
1573         DEBUG(5,("samr_reply_query_userinfo: %d\n", __LINE__));
1574
1575         /* search for the handle */
1576         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
1577         {
1578                 status = NT_STATUS_INVALID_HANDLE;
1579         }
1580
1581         /* find the user's rid */
1582         if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff)
1583         {
1584                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
1585         }
1586
1587         DEBUG(5,("samr_reply_query_userinfo: rid:0x%x\n", rid));
1588
1589         /* ok!  user info levels (there are lots: see MSDEV help), off we go... */
1590         if (status == 0x0)
1591         {
1592                 switch (q_u->switch_value)
1593                 {
1594                         case 0x10:
1595                         {
1596                                 info = (void*)&id10;
1597                                 status = get_user_info_10(&id10, rid) ? 0 : NT_STATUS_NO_SUCH_USER;
1598                                 break;
1599                         }
1600 #if 0
1601 /* whoops - got this wrong.  i think.  or don't understand what's happening. */
1602                         case 0x11:
1603                         {
1604                                 NTTIME expire;
1605                                 info = (void*)&id11;
1606                                 
1607                                 expire.low  = 0xffffffff;
1608                                 expire.high = 0x7fffffff;
1609
1610                                 make_sam_user_info11(&id11, &expire, "BROOKFIELDS$", 0x03ef, 0x201, 0x0080);
1611
1612                                 break;
1613                         }
1614 #endif
1615                         case 21:
1616                         {
1617                                 info = (void*)&id21;
1618                                 status = get_user_info_21(&id21, rid) ? 0 : NT_STATUS_NO_SUCH_USER;
1619                                 break;
1620                         }
1621
1622                         default:
1623                         {
1624                                 status = NT_STATUS_INVALID_INFO_CLASS;
1625
1626                                 break;
1627                         }
1628                 }
1629         }
1630
1631         init_samr_r_query_userinfo(&r_u, q_u->switch_value, info, status);
1632
1633         /* store the response in the SMB stream */
1634         if(!samr_io_r_query_userinfo("", &r_u, rdata, 0))
1635                 return False;
1636
1637         DEBUG(5,("samr_reply_query_userinfo: %d\n", __LINE__));
1638
1639         return True;
1640 }
1641
1642 /*******************************************************************
1643  api_samr_query_userinfo
1644  ********************************************************************/
1645 static BOOL api_samr_query_userinfo(pipes_struct *p)
1646 {
1647         SAMR_Q_QUERY_USERINFO q_u;
1648         prs_struct *data = &p->in_data.data;
1649         prs_struct *rdata = &p->out_data.rdata;
1650
1651         /* grab the samr unknown 24 */
1652         if(!samr_io_q_query_userinfo("", &q_u, data, 0))
1653                 return False;
1654
1655         /* construct reply.  always indicate success */
1656         if(!samr_reply_query_userinfo(&q_u, rdata))
1657                 return False;
1658
1659         return True;
1660 }
1661
1662
1663 /*******************************************************************
1664  samr_reply_query_usergroups
1665  ********************************************************************/
1666 static BOOL samr_reply_query_usergroups(SAMR_Q_QUERY_USERGROUPS *q_u,
1667                                 prs_struct *rdata)
1668 {
1669         SAMR_R_QUERY_USERGROUPS r_u;
1670         uint32 status = 0x0;
1671
1672         struct sam_passwd *sam_pass;
1673         DOM_GID *gids = NULL;
1674         int num_groups = 0;
1675         uint32 rid;
1676
1677         DEBUG(5,("samr_query_usergroups: %d\n", __LINE__));
1678
1679         /* find the policy handle.  open a policy on it. */
1680         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
1681         {
1682                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1683         }
1684
1685         /* find the user's rid */
1686         if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff)
1687         {
1688                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
1689         }
1690
1691         if (status == 0x0)
1692         {
1693                 become_root();
1694                 sam_pass = getsam21pwrid(rid);
1695                 unbecome_root();
1696
1697                 if (sam_pass == NULL)
1698                 {
1699                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
1700                 }
1701         }
1702
1703         if (status == 0x0)
1704         {
1705                 pstring groups;
1706                 get_domain_user_groups(groups, sam_pass->smb_name);
1707                 gids = NULL;
1708                 num_groups = make_dom_gids(groups, &gids);
1709         }
1710
1711         /* construct the response.  lkclXXXX: gids are not copied! */
1712         init_samr_r_query_usergroups(&r_u, num_groups, gids, status);
1713
1714         /* store the response in the SMB stream */
1715         if(!samr_io_r_query_usergroups("", &r_u, rdata, 0)) {
1716                 if (gids)
1717                         free((char *)gids);
1718                 return False;
1719         }
1720
1721         if (gids)
1722                 free((char *)gids);
1723
1724         DEBUG(5,("samr_query_usergroups: %d\n", __LINE__));
1725         
1726         return True;
1727 }
1728
1729 /*******************************************************************
1730  api_samr_query_usergroups
1731  ********************************************************************/
1732 static BOOL api_samr_query_usergroups(pipes_struct *p)
1733 {
1734         SAMR_Q_QUERY_USERGROUPS q_u;
1735         prs_struct *data = &p->in_data.data;
1736         prs_struct *rdata = &p->out_data.rdata;
1737
1738         /* grab the samr unknown 32 */
1739         if(!samr_io_q_query_usergroups("", &q_u, data, 0))
1740                 return False;
1741
1742         /* construct reply. */
1743         if(!samr_reply_query_usergroups(&q_u, rdata))
1744                 return False;
1745
1746         return True;
1747 }
1748
1749
1750 /*******************************************************************
1751  samr_reply_query_dom_info
1752  ********************************************************************/
1753 static BOOL samr_reply_query_dom_info(SAMR_Q_QUERY_DOMAIN_INFO *q_u, prs_struct *rdata)
1754 {
1755         SAMR_R_QUERY_DOMAIN_INFO r_u;
1756         SAM_UNK_CTR ctr;
1757         uint16 switch_value = 0x0;
1758         uint32 status = 0x0;
1759
1760         ZERO_STRUCT(r_u);
1761         ZERO_STRUCT(ctr);
1762
1763         r_u.ctr = &ctr;
1764
1765         DEBUG(5,("samr_reply_query_dom_info: %d\n", __LINE__));
1766
1767         /* find the policy handle.  open a policy on it. */
1768         if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1))
1769         {
1770                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1771                 DEBUG(5,("samr_reply_query_dom_info: invalid handle\n"));
1772         }
1773
1774         if (status == 0x0)
1775         {
1776                 switch (q_u->switch_value)
1777                 {
1778                         case 0x02:
1779                         {
1780                                 switch_value = 0x2;
1781                                 init_unk_info2(&ctr.info.inf2, global_myworkgroup, global_myname);
1782
1783                                 break;
1784                         }
1785                         default:
1786                         {
1787                                 status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
1788                                 break;
1789                         }
1790                 }
1791         }
1792
1793         init_samr_r_query_dom_info(&r_u, switch_value, &ctr, status);
1794
1795         /* store the response in the SMB stream */
1796         if(!samr_io_r_query_dom_info("", &r_u, rdata, 0))
1797                 return False;
1798
1799         DEBUG(5,("samr_query_dom_info: %d\n", __LINE__));
1800
1801         return True;
1802 }
1803
1804 /*******************************************************************
1805  api_samr_query_dom_info
1806  ********************************************************************/
1807 static BOOL api_samr_query_dom_info(pipes_struct *p)
1808 {
1809         SAMR_Q_QUERY_DOMAIN_INFO q_e;
1810         prs_struct *data = &p->in_data.data;
1811         prs_struct *rdata = &p->out_data.rdata;
1812
1813         /* grab the samr unknown 8 command */
1814         if(!samr_io_q_query_dom_info("", &q_e, data, 0))
1815                 return False;
1816
1817         /* construct reply. */
1818         if(!samr_reply_query_dom_info(&q_e, rdata))
1819                 return False;
1820
1821         return True;
1822 }
1823
1824 /*******************************************************************
1825  samr_reply_unknown_32
1826  ********************************************************************/
1827 static BOOL samr_reply_unknown_32(SAMR_Q_UNKNOWN_32 *q_u,
1828                                 prs_struct *rdata,
1829                                 int status)
1830 {
1831         int i;
1832         SAMR_R_UNKNOWN_32 r_u;
1833
1834         /* set up the SAMR unknown_32 response */
1835         memset((char *)r_u.pol.data, '\0', POL_HND_SIZE);
1836         if (status == 0)
1837         {
1838                 for (i = 4; i < POL_HND_SIZE; i++)
1839                 {
1840                         r_u.pol.data[i] = i+1;
1841                 }
1842         }
1843
1844         init_dom_rid4(&(r_u.rid4), 0x0030, 0, 0);
1845         r_u.status    = status;
1846
1847         DEBUG(5,("samr_unknown_32: %d\n", __LINE__));
1848
1849         /* store the response in the SMB stream */
1850         if(!samr_io_r_unknown_32("", &r_u, rdata, 0))
1851                 return False;
1852
1853         DEBUG(5,("samr_unknown_32: %d\n", __LINE__));
1854
1855         return True;
1856 }
1857
1858 /*******************************************************************
1859  api_samr_unknown_32
1860  ********************************************************************/
1861 static BOOL api_samr_unknown_32(pipes_struct *p)
1862 {
1863         uint32 status = 0;
1864         struct sam_passwd *sam_pass;
1865         fstring mach_acct;
1866         prs_struct *data = &p->in_data.data;
1867         prs_struct *rdata = &p->out_data.rdata;
1868
1869         SAMR_Q_UNKNOWN_32 q_u;
1870
1871         /* grab the samr unknown 32 */
1872         samr_io_q_unknown_32("", &q_u, data, 0);
1873
1874         /* find the machine account: tell the caller if it exists.
1875            lkclXXXX i have *no* idea if this is a problem or not
1876            or even if you are supposed to construct a different
1877            reply if the account already exists...
1878          */
1879
1880         fstrcpy(mach_acct, dos_unistrn2(q_u.uni_mach_acct.buffer,
1881                                     q_u.uni_mach_acct.uni_str_len));
1882
1883         become_root();
1884         sam_pass = getsam21pwnam(mach_acct);
1885         unbecome_root();
1886
1887         if (sam_pass != NULL)
1888         {
1889                 /* machine account exists: say so */
1890                 status = 0xC0000000 | NT_STATUS_USER_EXISTS;
1891         }
1892         else
1893         {
1894                 /* this could cause trouble... */
1895                 DEBUG(0,("trouble!\n"));
1896                 status = 0;
1897         }
1898
1899         /* construct reply. */
1900         if(!samr_reply_unknown_32(&q_u, rdata, status))
1901                 return False;
1902
1903         return True;
1904 }
1905
1906
1907 /*******************************************************************
1908  samr_reply_connect_anon
1909  ********************************************************************/
1910 static BOOL samr_reply_connect_anon(SAMR_Q_CONNECT_ANON *q_u, prs_struct *rdata)
1911 {
1912         SAMR_R_CONNECT_ANON r_u;
1913         BOOL pol_open = False;
1914
1915         /* set up the SAMR connect_anon response */
1916
1917         r_u.status = 0x0;
1918         /* get a (unique) handle.  open a policy on it. */
1919         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.connect_pol))))
1920         {
1921                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1922         }
1923
1924         /* associate the domain SID with the (unique) handle. */
1925         if (r_u.status == 0x0 && !set_lsa_policy_samr_pol_status(&(r_u.connect_pol), q_u->unknown_0))
1926         {
1927                 /* oh, whoops.  don't know what error message to return, here */
1928                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1929         }
1930
1931         if (r_u.status != 0 && pol_open)
1932         {
1933                 close_lsa_policy_hnd(&(r_u.connect_pol));
1934         }
1935
1936         DEBUG(5,("samr_connect_anon: %d\n", __LINE__));
1937
1938         /* store the response in the SMB stream */
1939         if(!samr_io_r_connect_anon("", &r_u, rdata, 0))
1940                 return False;
1941
1942         DEBUG(5,("samr_connect_anon: %d\n", __LINE__));
1943
1944         return True;
1945 }
1946
1947 /*******************************************************************
1948  api_samr_connect_anon
1949  ********************************************************************/
1950 static BOOL api_samr_connect_anon(pipes_struct *p)
1951 {
1952         SAMR_Q_CONNECT_ANON q_u;
1953         prs_struct *data = &p->in_data.data;
1954         prs_struct *rdata = &p->out_data.rdata;
1955
1956         /* grab the samr open policy */
1957         if(!samr_io_q_connect_anon("", &q_u, data, 0))
1958                 return False;
1959
1960         /* construct reply.  always indicate success */
1961         if(!samr_reply_connect_anon(&q_u, rdata))
1962                 return False;
1963
1964         return True;
1965 }
1966
1967 /*******************************************************************
1968  samr_reply_connect
1969  ********************************************************************/
1970 static BOOL samr_reply_connect(SAMR_Q_CONNECT *q_u, prs_struct *rdata)
1971 {
1972         SAMR_R_CONNECT r_u;
1973         BOOL pol_open = False;
1974
1975         /* set up the SAMR connect response */
1976
1977         r_u.status = 0x0;
1978         /* get a (unique) handle.  open a policy on it. */
1979         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.connect_pol))))
1980         {
1981                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1982         }
1983
1984         /* associate the domain SID with the (unique) handle. */
1985         if (r_u.status == 0x0 && !set_lsa_policy_samr_pol_status(&(r_u.connect_pol), q_u->unknown_0))
1986         {
1987                 /* oh, whoops.  don't know what error message to return, here */
1988                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1989         }
1990
1991         if (r_u.status != 0 && pol_open)
1992         {
1993                 close_lsa_policy_hnd(&(r_u.connect_pol));
1994         }
1995
1996         DEBUG(5,("samr_connect: %d\n", __LINE__));
1997
1998         /* store the response in the SMB stream */
1999         if(!samr_io_r_connect("", &r_u, rdata, 0))
2000                 return False;
2001
2002         DEBUG(5,("samr_connect: %d\n", __LINE__));
2003
2004         return True;
2005 }
2006
2007 /*******************************************************************
2008  api_samr_connect
2009  ********************************************************************/
2010 static BOOL api_samr_connect(pipes_struct *p)
2011 {
2012         SAMR_Q_CONNECT q_u;
2013         prs_struct *data = &p->in_data.data;
2014         prs_struct *rdata = &p->out_data.rdata;
2015
2016         /* grab the samr open policy */
2017         if(!samr_io_q_connect("", &q_u, data, 0))
2018                 return False;
2019
2020         /* construct reply.  always indicate success */
2021         if(!samr_reply_connect(&q_u, rdata))
2022                 return False;
2023
2024         return True;
2025 }
2026
2027 /**********************************************************************
2028  api_reply_lookup_domain
2029  **********************************************************************/
2030 static BOOL samr_reply_lookup_domain(SAMR_Q_LOOKUP_DOMAIN* q_u, prs_struct* rdata)
2031 {
2032   SAMR_R_LOOKUP_DOMAIN r_u;
2033   
2034   r_u.status = 0x0;
2035   if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->connect_pol)) == -1))
2036         {
2037                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
2038                 DEBUG(5,("samr_reply_lookup_domain: invalid handle\n"));
2039         }
2040   
2041   /* assume the domain name sent is our global_myname and 
2042      send global_sam_sid */
2043   init_samr_r_lookup_domain(&r_u, &global_sam_sid, r_u.status);
2044   
2045         if(!samr_io_r_lookup_domain("", &r_u, rdata, 0))
2046                 return False;
2047
2048   DEBUG(5,("samr_reply_lookup_domain: %d\n", __LINE__));
2049  
2050         return True; 
2051 }
2052   
2053 /**********************************************************************
2054  api_samr_lookup_domain
2055  **********************************************************************/
2056 static BOOL api_samr_lookup_domain(pipes_struct *p)
2057 {
2058         SAMR_Q_LOOKUP_DOMAIN q_u;
2059         prs_struct *data = &p->in_data.data;
2060         prs_struct *rdata = &p->out_data.rdata;
2061   
2062         if(!samr_io_q_lookup_domain("", &q_u, data, 0))
2063                 return False;
2064         
2065         if(!samr_reply_lookup_domain(&q_u, rdata))
2066                 return False;
2067         
2068         return True;
2069 }
2070
2071 /**********************************************************************
2072  samr_reply_enum_domains
2073  **********************************************************************/
2074 static BOOL samr_reply_enum_domains(SAMR_Q_ENUM_DOMAINS* q_u, prs_struct* rdata)
2075 {
2076   SAMR_R_ENUM_DOMAINS r_u;
2077   fstring dom[2];
2078
2079   fstrcpy(dom[0],global_myname);
2080   fstrcpy(dom[1],"Builtin");
2081   r_u.status = 0;
2082    
2083   init_samr_r_enum_domains(&r_u, q_u->start_idx, dom, 2); 
2084   if(!samr_io_r_enum_domains("", &r_u, rdata, 0)) {
2085                 free(r_u.sam);
2086                 free(r_u.uni_dom_name);
2087                 return False;
2088         }
2089
2090   free(r_u.sam);
2091   free(r_u.uni_dom_name);
2092
2093         return True;
2094 }
2095
2096 /**********************************************************************
2097  api_samr_enum_domains
2098  **********************************************************************/
2099 static BOOL api_samr_enum_domains(pipes_struct *p)
2100 {
2101         SAMR_Q_ENUM_DOMAINS q_u;
2102         prs_struct *data = &p->in_data.data;
2103         prs_struct *rdata = &p->out_data.rdata;
2104
2105         if(!samr_io_q_enum_domains("", &q_u, data, 0))
2106                 return False;
2107         
2108         if(!samr_reply_enum_domains(&q_u, rdata))
2109                 return False;
2110         
2111         return True;
2112 }
2113
2114 /*******************************************************************
2115  samr_reply_open_alias
2116  ********************************************************************/
2117 static BOOL samr_reply_open_alias(SAMR_Q_OPEN_ALIAS *q_u, prs_struct *rdata)
2118 {
2119         SAMR_R_OPEN_ALIAS r_u;
2120         BOOL pol_open = False;
2121
2122         /* set up the SAMR open_alias response */
2123
2124         r_u.status = 0x0;
2125         /* get a (unique) handle.  open a policy on it. */
2126         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.pol))))
2127         {
2128                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2129         }
2130
2131         /* associate a RID with the (unique) handle. */
2132         if (r_u.status == 0x0 && !set_lsa_policy_samr_rid(&(r_u.pol), q_u->rid_alias))
2133         {
2134                 /* oh, whoops.  don't know what error message to return, here */
2135                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2136         }
2137
2138         if (r_u.status != 0 && pol_open)
2139         {
2140                 close_lsa_policy_hnd(&(r_u.pol));
2141         }
2142
2143         DEBUG(5,("samr_open_alias: %d\n", __LINE__));
2144
2145         /* store the response in the SMB stream */
2146         if(!samr_io_r_open_alias("", &r_u, rdata, 0))
2147                 return False;
2148
2149         DEBUG(5,("samr_open_alias: %d\n", __LINE__));
2150         
2151         return True;
2152 }
2153
2154 /*******************************************************************
2155  api_samr_open_alias
2156  ********************************************************************/
2157 static BOOL api_samr_open_alias(pipes_struct *p)
2158 {
2159         SAMR_Q_OPEN_ALIAS q_u;
2160         prs_struct *data = &p->in_data.data;
2161         prs_struct *rdata = &p->out_data.rdata;
2162
2163         /* grab the samr open policy */
2164         if(!samr_io_q_open_alias("", &q_u, data, 0))
2165                 return False;
2166
2167         /* construct reply.  always indicate success */
2168         if(!samr_reply_open_alias(&q_u, rdata))
2169                 return False;
2170
2171         return True;
2172 }
2173
2174 /*******************************************************************
2175  array of \PIPE\samr operations
2176  ********************************************************************/
2177 static struct api_struct api_samr_cmds [] =
2178 {
2179         { "SAMR_CLOSE_HND"        , SAMR_CLOSE_HND        , api_samr_close_hnd        },
2180         { "SAMR_CONNECT"          , SAMR_CONNECT          , api_samr_connect          },
2181         { "SAMR_CONNECT_ANON"     , SAMR_CONNECT_ANON     , api_samr_connect_anon     },
2182         { "SAMR_ENUM_DOM_USERS"   , SAMR_ENUM_DOM_USERS   , api_samr_enum_dom_users   },
2183         { "SAMR_ENUM_DOM_GROUPS"  , SAMR_ENUM_DOM_GROUPS  , api_samr_enum_dom_groups  },
2184         { "SAMR_ENUM_DOM_ALIASES" , SAMR_ENUM_DOM_ALIASES , api_samr_enum_dom_aliases },
2185         { "SAMR_LOOKUP_IDS"       , SAMR_LOOKUP_IDS       , api_samr_lookup_ids       },
2186         { "SAMR_LOOKUP_NAMES"     , SAMR_LOOKUP_NAMES     , api_samr_lookup_names     },
2187         { "SAMR_OPEN_USER"        , SAMR_OPEN_USER        , api_samr_open_user        },
2188         { "SAMR_QUERY_USERINFO"   , SAMR_QUERY_USERINFO   , api_samr_query_userinfo   },
2189         { "SAMR_QUERY_DOMAIN_INFO", SAMR_QUERY_DOMAIN_INFO, api_samr_query_dom_info        },
2190         { "SAMR_QUERY_USERGROUPS" , SAMR_QUERY_USERGROUPS , api_samr_query_usergroups },
2191         { "SAMR_QUERY_DISPINFO"   , SAMR_QUERY_DISPINFO   , api_samr_query_dispinfo   },
2192         { "SAMR_QUERY_ALIASINFO"  , SAMR_QUERY_ALIASINFO  , api_samr_query_aliasinfo  },
2193         { "SAMR_0x32"             , 0x32                  , api_samr_unknown_32       },
2194         { "SAMR_UNKNOWN_12"       , SAMR_UNKNOWN_12       , api_samr_unknown_12       },
2195         { "SAMR_UNKNOWN_38"       , SAMR_UNKNOWN_38       , api_samr_unknown_38       },
2196         { "SAMR_CHGPASSWD_USER"   , SAMR_CHGPASSWD_USER   , api_samr_chgpasswd_user   },
2197         { "SAMR_OPEN_ALIAS"       , SAMR_OPEN_ALIAS       , api_samr_open_alias       },
2198         { "SAMR_OPEN_DOMAIN"      , SAMR_OPEN_DOMAIN      , api_samr_open_domain      },
2199         { "SAMR_UNKNOWN_3"        , SAMR_UNKNOWN_3        , api_samr_unknown_3        },
2200         { "SAMR_UNKNOWN_2C"       , SAMR_UNKNOWN_2C       , api_samr_unknown_2c       },
2201         { "SAMR_LOOKUP_DOMAIN"    , SAMR_LOOKUP_DOMAIN    , api_samr_lookup_domain    },
2202         { "SAMR_ENUM_DOMAINS"     , SAMR_ENUM_DOMAINS     , api_samr_enum_domains     },
2203         { NULL                    , 0                     , NULL                      }
2204 };
2205
2206 /*******************************************************************
2207  receives a samr pipe and responds.
2208  ********************************************************************/
2209 BOOL api_samr_rpc(pipes_struct *p)
2210 {
2211         return api_rpcTNP(p, "api_samr_rpc", api_samr_cmds);
2212 }
2213 #undef OLD_NTDOMAIN