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