Merge of uninitialised variable fix from APPLIANCE_HEAD.
[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 || (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         ZERO_STRUCT(r_e);
739
740         /* find the policy handle.  open a policy on it. */
741         if (r_e.status == 0x0 && !get_lsa_policy_samr_sid(&q_u->pol, &sid))
742         {
743                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
744         }
745
746         sid_to_string(sid_str, &sid);
747         sid_to_string(sam_sid_str, &global_sam_sid);
748
749         DEBUG(5,("samr_reply_enum_dom_aliases: sid %s\n", sid_str));
750
751         /* well-known aliases */
752         if (strequal(sid_str, "S-1-5-32"))
753         {
754                 char *name;
755                 while (num_entries < MAX_SAM_ENTRIES && ((name = builtin_alias_rids[num_entries].name) != NULL))
756                 {
757                         init_unistr2(&(pass[num_entries].uni_user_name), name, strlen(name));
758                         pass[num_entries].user_rid = builtin_alias_rids[num_entries].rid;
759                         num_entries++;
760                 }
761         }
762         else if (strequal(sid_str, sam_sid_str))
763         {
764                 char *name;
765                 char *sep;
766
767                 sep = lp_winbind_separator();
768
769                 /* local aliases */
770                 /* we return the UNIX groups here.  This seems to be the right */
771                 /* thing to do, since NT member servers return their local     */
772                 /* groups in the same situation.                               */
773                 setgrent();
774
775                 while (num_entries < MAX_SAM_ENTRIES && ((grp = getgrent()) != NULL))
776                 {
777                         name = grp->gr_name;
778
779                         /* Don't return winbind groups as they are not local! */
780
781                         if (strchr(name, *sep) != NULL) {
782                                 continue;
783                         }
784
785                         init_unistr2(&(pass[num_entries].uni_user_name), name, strlen(name));
786                         pass[num_entries].user_rid = pdb_gid_to_group_rid(grp->gr_gid);
787                         num_entries++;
788                 }
789
790                 endgrent();
791         }
792                 
793         init_samr_r_enum_dom_aliases(&r_e, num_entries, pass, r_e.status);
794
795         /* store the response in the SMB stream */
796         if(!samr_io_r_enum_dom_aliases("", &r_e, rdata, 0))
797                 return False;
798
799         DEBUG(5,("samr_enum_dom_aliases: %d\n", __LINE__));
800
801         return True;
802 }
803
804 /*******************************************************************
805  api_samr_enum_dom_aliases
806  ********************************************************************/
807 static BOOL api_samr_enum_dom_aliases(pipes_struct *p)
808 {
809         SAMR_Q_ENUM_DOM_ALIASES q_e;
810         prs_struct *data = &p->in_data.data;
811         prs_struct *rdata = &p->out_data.rdata;
812
813         /* grab the samr open */
814         if(!samr_io_q_enum_dom_aliases("", &q_e, data, 0))
815                 return False;
816
817         /* construct reply. */
818         if(!samr_reply_enum_dom_aliases(&q_e, rdata))
819                 return False;
820
821         return True;
822 }
823
824
825 /*******************************************************************
826  samr_reply_query_dispinfo
827  ********************************************************************/
828 static BOOL samr_reply_query_dispinfo(SAMR_Q_QUERY_DISPINFO *q_u, prs_struct *rdata)
829 {
830         SAMR_R_QUERY_DISPINFO r_e;
831         SAM_INFO_CTR ctr;
832         SAM_INFO_1 info1;
833         SAM_INFO_2 info2;
834         SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
835         int num_entries = 0;
836         int total_entries = 0;
837         BOOL got_pwds;
838         uint16 switch_level = 0x0;
839
840         ZERO_STRUCT(r_e);
841
842         DEBUG(5,("samr_reply_query_dispinfo: %d\n", __LINE__));
843
844         /* find the policy handle.  open a policy on it. */
845         if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
846         {
847                 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
848                 DEBUG(5,("samr_reply_query_dispinfo: invalid handle\n"));
849         }
850
851         if (r_e.status == 0x0)
852         {
853           /* decide how many entries to get depending on the max_entries 
854              and max_size passed by client */
855           uint32 retsize;
856
857           if(q_u->max_entries > MAX_SAM_ENTRIES)
858             q_u->max_entries = MAX_SAM_ENTRIES;
859           
860           retsize = (q_u->max_entries * (sizeof(SAM_ENTRY1)+sizeof(SAM_STR1)))
861             + 3*sizeof(uint32);
862
863           if(retsize > q_u->max_size)
864             {
865               /* determine max_entries based on max_size */
866               q_u->max_entries = (q_u->max_size - 3*sizeof(uint32)) /
867                 (sizeof(SAM_ENTRY1)+sizeof(SAM_STR1));
868               q_u->max_entries = (q_u->max_entries>0?q_u->max_entries:1);
869             }
870
871           DEBUG(10,("samr_reply_query_dispinfo: Setting q_u->max_entries to %u\n",q_u->max_entries));
872
873                 become_root();
874                 got_pwds = get_passwd_entries(pass, q_u->start_idx, &total_entries, &num_entries, q_u->max_entries, 0);
875                 unbecome_root();
876
877                 /* more left - set resume handle */
878                 if(total_entries > num_entries)
879                   {
880                     r_e.status = 0x105;
881                   }
882
883                 switch (q_u->switch_level)
884                 {
885                         case 0x1:
886                         {
887                         
888                                 /* query disp info is for users */
889                                 switch_level = 0x1;
890                                 init_sam_info_1(&info1, ACB_NORMAL,
891                                         q_u->start_idx, num_entries, pass);
892
893                                 ctr.sam.info1 = &info1;
894
895                                 break;
896                         }
897                         case 0x2:
898                         {
899                                 /* query disp info is for servers */
900                                 switch_level = 0x2;
901                                 init_sam_info_2(&info2, ACB_WSTRUST,
902                                         q_u->start_idx, num_entries, pass);
903
904                                 ctr.sam.info2 = &info2;
905
906                                 break;
907                         }
908                 }
909         }
910
911         /* more left - set resume handle */
912         if(total_entries > num_entries)
913           {
914             r_e.status = 0x105;
915           }
916
917         if (r_e.status == 0 || r_e.status == 0x105)
918         {
919           init_samr_r_query_dispinfo(&r_e, switch_level, &ctr, r_e.status);
920         }
921
922         /* store the response in the SMB stream */
923         if(!samr_io_r_query_dispinfo("", &r_e, rdata, 0))
924                 return False;
925
926         DEBUG(5,("samr_query_dispinfo: %d\n", __LINE__));
927
928         return True;
929 }
930
931 /*******************************************************************
932  api_samr_query_dispinfo
933  ********************************************************************/
934 static BOOL api_samr_query_dispinfo(pipes_struct *p)
935 {
936         SAMR_Q_QUERY_DISPINFO q_e;
937         prs_struct *data = &p->in_data.data;
938         prs_struct *rdata = &p->out_data.rdata;
939
940         /* grab the samr open */
941         if(!samr_io_q_query_dispinfo("", &q_e, data, 0))
942                 return False;
943
944         /* construct reply. */
945         if(!samr_reply_query_dispinfo(&q_e, rdata))
946                 return False;
947
948         return True;
949 }
950
951
952 /*******************************************************************
953  samr_reply_query_aliasinfo
954  ********************************************************************/
955 static BOOL samr_reply_query_aliasinfo(SAMR_Q_QUERY_ALIASINFO *q_u,
956                                 prs_struct *rdata)
957 {
958   SAMR_R_QUERY_ALIASINFO r_e;
959   fstring alias_desc = "Local Unix group";
960   fstring alias="";
961   uint8 type;
962   uint32 alias_rid;
963
964   ZERO_STRUCT(r_e);
965
966   DEBUG(5,("samr_reply_query_aliasinfo: %d\n", __LINE__));
967
968   /* find the policy handle.  open a policy on it. */
969   if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
970     {
971       r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
972     }
973
974   alias_rid = get_lsa_policy_samr_rid(&q_u->pol);
975   if(alias_rid == 0xffffffff)
976       r_e.status = 0xC0000000 | NT_STATUS_NO_SUCH_ALIAS;
977
978   if(!local_lookup_rid(alias_rid, alias, &type))
979     {
980       r_e.status = 0xC0000000 | NT_STATUS_NO_SUCH_ALIAS;
981     }
982   
983   init_samr_r_query_aliasinfo(&r_e, q_u->switch_level, alias, alias_desc);
984   
985   /* store the response in the SMB stream */
986   if(!samr_io_r_query_aliasinfo("", &r_e, rdata, 0))
987                 return False;
988   
989   DEBUG(5,("samr_query_aliasinfo: %d\n", __LINE__));
990
991         return True;
992 }
993
994 /*******************************************************************
995  api_samr_query_aliasinfo
996  ********************************************************************/
997 static BOOL api_samr_query_aliasinfo(pipes_struct *p)
998 {
999         SAMR_Q_QUERY_ALIASINFO q_e;
1000         prs_struct *data = &p->in_data.data;
1001         prs_struct *rdata = &p->out_data.rdata;
1002
1003         /* grab the samr open */
1004         if(!samr_io_q_query_aliasinfo("", &q_e, data, 0))
1005                 return False;
1006
1007         /* construct reply. */
1008         if(!samr_reply_query_aliasinfo(&q_e, rdata))
1009                 return False;
1010
1011         return True;
1012 }
1013
1014
1015 /*******************************************************************
1016  samr_reply_lookup_ids
1017  ********************************************************************/
1018 static BOOL samr_reply_lookup_ids(SAMR_Q_LOOKUP_IDS *q_u,
1019                                 prs_struct *rdata)
1020 {
1021         uint32 rid[MAX_SAM_ENTRIES];
1022         uint32 status     = 0;
1023         int num_rids = q_u->num_sids1;
1024
1025         SAMR_R_LOOKUP_IDS r_u;
1026
1027         DEBUG(5,("samr_lookup_ids: %d\n", __LINE__));
1028
1029         if (num_rids > MAX_SAM_ENTRIES)
1030         {
1031                 num_rids = MAX_SAM_ENTRIES;
1032                 DEBUG(5,("samr_lookup_ids: truncating entries to %d\n", num_rids));
1033         }
1034
1035 #if 0
1036         int i;
1037         SMB_ASSERT_ARRAY(q_u->uni_user_name, num_rids);
1038
1039         for (i = 0; i < num_rids && status == 0; i++)
1040         {
1041                 struct sam_passwd *sam_pass;
1042                 fstring user_name;
1043
1044
1045                 fstrcpy(user_name, unistrn2(q_u->uni_user_name[i].buffer,
1046                                             q_u->uni_user_name[i].uni_str_len));
1047
1048                 /* find the user account */
1049                 become_root();
1050                 sam_pass = get_smb21pwd_entry(user_name, 0);
1051                 unbecome_root();
1052
1053                 if (sam_pass == NULL)
1054                 {
1055                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
1056                         rid[i] = 0;
1057                 }
1058                 else
1059                 {
1060                         rid[i] = sam_pass->user_rid;
1061                 }
1062         }
1063 #endif
1064
1065         num_rids = 1;
1066         rid[0] = BUILTIN_ALIAS_RID_USERS;
1067
1068         init_samr_r_lookup_ids(&r_u, num_rids, rid, status);
1069
1070         /* store the response in the SMB stream */
1071         if(!samr_io_r_lookup_ids("", &r_u, rdata, 0))
1072                 return False;
1073
1074         DEBUG(5,("samr_lookup_ids: %d\n", __LINE__));
1075
1076         return True;
1077 }
1078
1079 /*******************************************************************
1080  api_samr_lookup_ids
1081  ********************************************************************/
1082 static BOOL api_samr_lookup_ids(pipes_struct *p)
1083 {
1084         SAMR_Q_LOOKUP_IDS q_u;
1085         prs_struct *data = &p->in_data.data;
1086         prs_struct *rdata = &p->out_data.rdata;
1087
1088         /* grab the samr 0x10 */
1089         if(!samr_io_q_lookup_ids("", &q_u, data, 0))
1090                 return False;
1091
1092         /* construct reply.  always indicate success */
1093         if(!samr_reply_lookup_ids(&q_u, rdata))
1094                 return False;
1095
1096         return True;
1097 }
1098
1099 /*******************************************************************
1100  samr_reply_lookup_names
1101  ********************************************************************/
1102
1103 static BOOL samr_reply_lookup_names(SAMR_Q_LOOKUP_NAMES *q_u,
1104                                     prs_struct *rdata)
1105 {
1106   uint32 rid[MAX_SAM_ENTRIES];
1107   uint8  type[MAX_SAM_ENTRIES];
1108   uint32 status = 0;
1109   int i;
1110   int num_rids = q_u->num_names1;
1111   DOM_SID pol_sid;
1112
1113   SAMR_R_LOOKUP_NAMES r_u;
1114
1115   DEBUG(5,("samr_lookup_names: %d\n", __LINE__));
1116
1117   ZERO_ARRAY(rid);
1118   ZERO_ARRAY(type);
1119
1120   if (!get_lsa_policy_samr_sid(&q_u->pol, &pol_sid)) {
1121     status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH;
1122     init_samr_r_lookup_names(&r_u, 0, rid, type, status);
1123     if(!samr_io_r_lookup_names("", &r_u, rdata, 0)) {
1124       DEBUG(0,("samr_reply_lookup_names: failed to marshall SAMR_R_LOOKUP_NAMES.\n"));
1125       return False;
1126     }
1127     return True;
1128   }
1129
1130   if (num_rids > MAX_SAM_ENTRIES) {
1131     num_rids = MAX_SAM_ENTRIES;
1132     DEBUG(5,("samr_lookup_names: truncating entries to %d\n", num_rids));
1133   }
1134
1135   SMB_ASSERT_ARRAY(q_u->uni_name, num_rids);
1136
1137   for (i = 0; i < num_rids; i++) {
1138     fstring name;
1139
1140     status = 0xC0000000 | NT_STATUS_NONE_MAPPED;
1141
1142     rid [i] = 0xffffffff;
1143     type[i] = SID_NAME_UNKNOWN;
1144
1145     fstrcpy(name, dos_unistrn2(q_u->uni_name[i].buffer,
1146                                q_u->uni_name[i].uni_str_len));
1147
1148     if(sid_equal(&pol_sid, &global_sam_sid)) 
1149     {
1150       DOM_SID sid;
1151       if(local_lookup_name(global_myname, name, 
1152                            &sid, &type[i]))
1153         {
1154           sid_split_rid( &sid, &rid[i]);
1155           status = 0;
1156         }
1157     }
1158   }
1159
1160   init_samr_r_lookup_names(&r_u, num_rids, rid, type, status);
1161
1162   /* store the response in the SMB stream */
1163   if(!samr_io_r_lookup_names("", &r_u, rdata, 0)) {
1164     DEBUG(0,("samr_reply_lookup_names: failed to marshall SAMR_R_LOOKUP_NAMES.\n"));
1165     return False;
1166   }
1167
1168   DEBUG(5,("samr_lookup_names: %d\n", __LINE__));
1169
1170   return True;
1171 }
1172
1173 /*******************************************************************
1174  api_samr_lookup_names
1175  ********************************************************************/
1176
1177 static BOOL api_samr_lookup_names(pipes_struct *p)
1178 {
1179         SAMR_Q_LOOKUP_NAMES q_u;
1180         prs_struct *data = &p->in_data.data;
1181         prs_struct *rdata = &p->out_data.rdata;
1182
1183         memset(&q_u, '\0', sizeof(q_u));
1184
1185         /* grab the samr lookup names */
1186         if(!samr_io_q_lookup_names("", &q_u, data, 0)) {
1187                 DEBUG(0,("api_samr_lookup_names: failed to unmarshall SAMR_Q_LOOKUP_NAMES.\n"));
1188                 return False;
1189         }
1190
1191         /* construct reply.  always indicate success */
1192         if(!samr_reply_lookup_names(&q_u, rdata))
1193                 return False;
1194
1195         return True;
1196 }
1197
1198 /*******************************************************************
1199  samr_reply_chgpasswd_user
1200  ********************************************************************/
1201
1202 static BOOL samr_reply_chgpasswd_user(SAMR_Q_CHGPASSWD_USER *q_u,
1203                                 prs_struct *rdata)
1204 {
1205         SAMR_R_CHGPASSWD_USER r_u;
1206         uint32 status = 0x0;
1207         fstring user_name;
1208         fstring wks;
1209
1210         fstrcpy(user_name, dos_unistrn2(q_u->uni_user_name.buffer, q_u->uni_user_name.uni_str_len));
1211         fstrcpy(wks      , dos_unistrn2(q_u->uni_dest_host.buffer, q_u->uni_dest_host.uni_str_len));
1212
1213         DEBUG(5,("samr_chgpasswd_user: user: %s wks: %s\n", user_name, wks));
1214
1215         if (!pass_oem_change(user_name,
1216                              q_u->lm_newpass.pass, q_u->lm_oldhash.hash,
1217                              q_u->nt_newpass.pass, q_u->nt_oldhash.hash))
1218         {
1219                 status = 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
1220         }
1221
1222         init_samr_r_chgpasswd_user(&r_u, status);
1223
1224         /* store the response in the SMB stream */
1225         if(!samr_io_r_chgpasswd_user("", &r_u, rdata, 0)) {
1226                 DEBUG(0,("samr_reply_chgpasswd_user: Failed to marshall SAMR_R_CHGPASSWD_USER struct.\n" ));
1227                 return False;
1228         }
1229
1230         DEBUG(5,("samr_chgpasswd_user: %d\n", __LINE__));
1231         return True;
1232 }
1233
1234 /*******************************************************************
1235  api_samr_chgpasswd_user
1236  ********************************************************************/
1237
1238 static BOOL api_samr_chgpasswd_user(pipes_struct *p)
1239 {
1240         SAMR_Q_CHGPASSWD_USER q_u;
1241         prs_struct *data = &p->in_data.data;
1242         prs_struct *rdata = &p->out_data.rdata;
1243
1244         /* unknown 38 command */
1245         if (!samr_io_q_chgpasswd_user("", &q_u, data, 0)) {
1246                 DEBUG(0,("api_samr_chgpasswd_user: samr_io_q_chgpasswd_user failed to parse RPC packet.\n"));
1247                 return False;
1248         }
1249
1250         /* construct reply. */
1251         if(!samr_reply_chgpasswd_user(&q_u, rdata)) {
1252                 DEBUG(0,("api_samr_chgpasswd_user: samr_reply_chgpasswd_user failed to create reply packet.\n"));
1253                 return False;
1254         }
1255
1256         return True;
1257 }
1258
1259
1260 /*******************************************************************
1261  samr_reply_unknown_38
1262  ********************************************************************/
1263 static BOOL samr_reply_unknown_38(SAMR_Q_UNKNOWN_38 *q_u, prs_struct *rdata)
1264 {
1265         SAMR_R_UNKNOWN_38 r_u;
1266
1267         DEBUG(5,("samr_unknown_38: %d\n", __LINE__));
1268
1269         init_samr_r_unknown_38(&r_u);
1270
1271         /* store the response in the SMB stream */
1272         if(!samr_io_r_unknown_38("", &r_u, rdata, 0))
1273                 return False;
1274
1275         DEBUG(5,("samr_unknown_38: %d\n", __LINE__));
1276         return True;
1277 }
1278
1279 /*******************************************************************
1280  api_samr_unknown_38
1281  ********************************************************************/
1282 static BOOL api_samr_unknown_38(pipes_struct *p)
1283 {
1284         SAMR_Q_UNKNOWN_38 q_u;
1285         prs_struct *data = &p->in_data.data;
1286         prs_struct *rdata = &p->out_data.rdata;
1287
1288         /* unknown 38 command */
1289         if(!samr_io_q_unknown_38("", &q_u, data, 0))
1290                 return False;
1291
1292         /* construct reply.  always indicate success */
1293         if(!samr_reply_unknown_38(&q_u, rdata))
1294                 return False;
1295
1296         return True;
1297 }
1298
1299
1300 /*******************************************************************
1301  samr_reply_unknown_12
1302  ********************************************************************/
1303 static BOOL samr_reply_unknown_12(SAMR_Q_UNKNOWN_12 *q_u,
1304                                 prs_struct *rdata)
1305 {
1306         fstring group_names[MAX_SAM_ENTRIES];
1307         uint32  group_attrs[MAX_SAM_ENTRIES];
1308         uint32 status     = 0;
1309         int num_gids = q_u->num_gids1;
1310
1311         SAMR_R_UNKNOWN_12 r_u;
1312
1313         DEBUG(5,("samr_unknown_12: %d\n", __LINE__));
1314
1315         /* find the policy handle.  open a policy on it. */
1316         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
1317         {
1318                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1319         }
1320
1321         if (status == 0x0)
1322         {
1323                 int i;
1324                 if (num_gids > MAX_SAM_ENTRIES)
1325                 {
1326                         num_gids = MAX_SAM_ENTRIES;
1327                         DEBUG(5,("samr_unknown_12: truncating entries to %d\n", num_gids));
1328                 }
1329
1330                 for (i = 0; i < num_gids && status == 0; i++)
1331                 {
1332                         fstrcpy(group_names[i], "dummy group");
1333                         group_attrs[i] = 0x2;
1334                 }
1335         }
1336
1337         init_samr_r_unknown_12(&r_u, num_gids, group_names, group_attrs, status);
1338
1339         /* store the response in the SMB stream */
1340         if(!samr_io_r_unknown_12("", &r_u, rdata, 0))
1341                 return False;
1342
1343         DEBUG(5,("samr_unknown_12: %d\n", __LINE__));
1344
1345         return True;
1346 }
1347
1348 /*******************************************************************
1349  api_samr_unknown_12
1350  ********************************************************************/
1351 static BOOL api_samr_unknown_12(pipes_struct *p)
1352 {
1353         SAMR_Q_UNKNOWN_12 q_u;
1354         prs_struct *data = &p->in_data.data;
1355         prs_struct *rdata = &p->out_data.rdata;
1356
1357         /* grab the samr lookup names */
1358         if(!samr_io_q_unknown_12("", &q_u, data, 0))
1359                 return False;
1360
1361         /* construct reply.  always indicate success */
1362         if(!samr_reply_unknown_12(&q_u, rdata))
1363                 return False;
1364
1365         return True;
1366 }
1367
1368
1369 /*******************************************************************
1370  samr_reply_open_user
1371  ********************************************************************/
1372 static BOOL samr_reply_open_user(SAMR_Q_OPEN_USER *q_u, prs_struct *rdata, int status)
1373 {
1374         SAMR_R_OPEN_USER r_u;
1375         struct sam_passwd *sam_pass;
1376         BOOL pol_open = False;
1377
1378         /* set up the SAMR open_user response */
1379         memset((char *)r_u.user_pol.data, '\0', POL_HND_SIZE);
1380
1381         r_u.status = 0x0;
1382
1383         /* find the policy handle.  open a policy on it. */
1384         if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1))
1385         {
1386                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1387         }
1388
1389         /* get a (unique) handle.  open a policy on it. */
1390         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.user_pol))))
1391         {
1392                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1393         }
1394
1395         become_root();
1396         sam_pass = getsam21pwrid(q_u->user_rid);
1397         unbecome_root();
1398
1399         /* check that the RID exists in our domain. */
1400         if (r_u.status == 0x0 && sam_pass == NULL)
1401         {
1402                 r_u.status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
1403         }
1404
1405         /* associate the RID with the (unique) handle. */
1406         if (r_u.status == 0x0 && !set_lsa_policy_samr_rid(&(r_u.user_pol), q_u->user_rid))
1407         {
1408                 /* oh, whoops.  don't know what error message to return, here */
1409                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1410         }
1411
1412         if (r_u.status != 0 && pol_open)
1413         {
1414                 close_lsa_policy_hnd(&(r_u.user_pol));
1415         }
1416
1417         DEBUG(5,("samr_open_user: %d\n", __LINE__));
1418
1419         /* store the response in the SMB stream */
1420         if(!samr_io_r_open_user("", &r_u, rdata, 0))
1421                 return False;
1422
1423         DEBUG(5,("samr_open_user: %d\n", __LINE__));
1424
1425         return True;
1426 }
1427
1428 /*******************************************************************
1429  api_samr_open_user
1430  ********************************************************************/
1431 static BOOL api_samr_open_user(pipes_struct *p)
1432 {
1433         SAMR_Q_OPEN_USER q_u;
1434         prs_struct *data = &p->in_data.data;
1435         prs_struct *rdata = &p->out_data.rdata;
1436
1437         /* grab the samr unknown 22 */
1438         if(!samr_io_q_open_user("", &q_u, data, 0))
1439                 return False;
1440
1441         /* construct reply.  always indicate success */
1442         if(!samr_reply_open_user(&q_u, rdata, 0x0))
1443                 return False;
1444
1445         return True;
1446 }
1447
1448
1449 /*************************************************************************
1450  get_user_info_10
1451  *************************************************************************/
1452 static BOOL get_user_info_10(SAM_USER_INFO_10 *id10, uint32 user_rid)
1453 {
1454         struct smb_passwd *smb_pass;
1455
1456         if (!pdb_rid_is_user(user_rid))
1457         {
1458                 DEBUG(4,("RID 0x%x is not a user RID\n", user_rid));
1459                 return False;
1460         }
1461
1462         become_root();
1463         smb_pass = getsmbpwrid(user_rid);
1464         unbecome_root();
1465
1466         if (smb_pass == NULL)
1467         {
1468                 DEBUG(4,("User 0x%x not found\n", user_rid));
1469                 return False;
1470         }
1471
1472         DEBUG(3,("User:[%s]\n", smb_pass->smb_name));
1473
1474         init_sam_user_info10(id10, smb_pass->acct_ctrl); 
1475
1476         return True;
1477 }
1478
1479 /*************************************************************************
1480  get_user_info_21
1481  *************************************************************************/
1482 static BOOL get_user_info_21(SAM_USER_INFO_21 *id21, uint32 user_rid)
1483 {
1484         NTTIME dummy_time;
1485         struct sam_passwd *sam_pass;
1486         LOGON_HRS hrs;
1487         int i;
1488
1489         if (!pdb_rid_is_user(user_rid))
1490         {
1491                 DEBUG(4,("RID 0x%x is not a user RID\n", user_rid));
1492                 return False;
1493         }
1494
1495         become_root();
1496         sam_pass = getsam21pwrid(user_rid);
1497         unbecome_root();
1498
1499         if (sam_pass == NULL)
1500         {
1501                 DEBUG(4,("User 0x%x not found\n", user_rid));
1502                 return False;
1503         }
1504
1505         DEBUG(3,("User:[%s]\n", sam_pass->smb_name));
1506
1507         dummy_time.low  = 0xffffffff;
1508         dummy_time.high = 0x7fffffff;
1509
1510         DEBUG(5,("get_user_info_21 - TODO: convert unix times to NTTIMEs\n"));
1511
1512         /* create a LOGON_HRS structure */
1513         hrs.len = sam_pass->hours_len;
1514         SMB_ASSERT_ARRAY(hrs.hours, hrs.len);
1515         for (i = 0; i < hrs.len; i++)
1516         {
1517                 hrs.hours[i] = sam_pass->hours[i];
1518         }
1519
1520         init_sam_user_info21(id21,
1521
1522                            &dummy_time, /* logon_time */
1523                            &dummy_time, /* logoff_time */
1524                            &dummy_time, /* kickoff_time */
1525                            &dummy_time, /* pass_last_set_time */
1526                            &dummy_time, /* pass_can_change_time */
1527                            &dummy_time, /* pass_must_change_time */
1528
1529                            sam_pass->smb_name, /* user_name */
1530                            sam_pass->full_name, /* full_name */
1531                            sam_pass->home_dir, /* home_dir */
1532                            sam_pass->dir_drive, /* dir_drive */
1533                            sam_pass->logon_script, /* logon_script */
1534                            sam_pass->profile_path, /* profile_path */
1535                            sam_pass->acct_desc, /* description */
1536                            sam_pass->workstations, /* workstations user can log in from */
1537                            sam_pass->unknown_str, /* don't know, yet */
1538                            sam_pass->munged_dial, /* dialin info.  contains dialin path and tel no */
1539
1540                            sam_pass->user_rid, /* RID user_id */
1541                            sam_pass->group_rid, /* RID group_id */
1542                        sam_pass->acct_ctrl,
1543
1544                    sam_pass->unknown_3, /* unknown_3 */
1545                        sam_pass->logon_divs, /* divisions per week */
1546                            &hrs, /* logon hours */
1547                        sam_pass->unknown_5,
1548                        sam_pass->unknown_6);
1549
1550         return True;
1551 }
1552
1553 /*******************************************************************
1554  samr_reply_query_userinfo
1555  ********************************************************************/
1556 static BOOL samr_reply_query_userinfo(SAMR_Q_QUERY_USERINFO *q_u,
1557                                 prs_struct *rdata)
1558 {
1559         SAMR_R_QUERY_USERINFO r_u;
1560 #if 0
1561         SAM_USER_INFO_11 id11;
1562 #endif
1563         SAM_USER_INFO_10 id10;
1564         SAM_USER_INFO_21 id21;
1565         void *info = NULL;
1566
1567         uint32 status = 0x0;
1568         uint32 rid = 0x0;
1569
1570         DEBUG(5,("samr_reply_query_userinfo: %d\n", __LINE__));
1571
1572         /* search for the handle */
1573         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
1574         {
1575                 status = NT_STATUS_INVALID_HANDLE;
1576         }
1577
1578         /* find the user's rid */
1579         if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff)
1580         {
1581                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
1582         }
1583
1584         DEBUG(5,("samr_reply_query_userinfo: rid:0x%x\n", rid));
1585
1586         /* ok!  user info levels (there are lots: see MSDEV help), off we go... */
1587         if (status == 0x0)
1588         {
1589                 switch (q_u->switch_value)
1590                 {
1591                         case 0x10:
1592                         {
1593                                 info = (void*)&id10;
1594                                 status = get_user_info_10(&id10, rid) ? 0 : NT_STATUS_NO_SUCH_USER;
1595                                 break;
1596                         }
1597 #if 0
1598 /* whoops - got this wrong.  i think.  or don't understand what's happening. */
1599                         case 0x11:
1600                         {
1601                                 NTTIME expire;
1602                                 info = (void*)&id11;
1603                                 
1604                                 expire.low  = 0xffffffff;
1605                                 expire.high = 0x7fffffff;
1606
1607                                 make_sam_user_info11(&id11, &expire, "BROOKFIELDS$", 0x03ef, 0x201, 0x0080);
1608
1609                                 break;
1610                         }
1611 #endif
1612                         case 21:
1613                         {
1614                                 info = (void*)&id21;
1615                                 status = get_user_info_21(&id21, rid) ? 0 : NT_STATUS_NO_SUCH_USER;
1616                                 break;
1617                         }
1618
1619                         default:
1620                         {
1621                                 status = NT_STATUS_INVALID_INFO_CLASS;
1622
1623                                 break;
1624                         }
1625                 }
1626         }
1627
1628         init_samr_r_query_userinfo(&r_u, q_u->switch_value, info, status);
1629
1630         /* store the response in the SMB stream */
1631         if(!samr_io_r_query_userinfo("", &r_u, rdata, 0))
1632                 return False;
1633
1634         DEBUG(5,("samr_reply_query_userinfo: %d\n", __LINE__));
1635
1636         return True;
1637 }
1638
1639 /*******************************************************************
1640  api_samr_query_userinfo
1641  ********************************************************************/
1642 static BOOL api_samr_query_userinfo(pipes_struct *p)
1643 {
1644         SAMR_Q_QUERY_USERINFO q_u;
1645         prs_struct *data = &p->in_data.data;
1646         prs_struct *rdata = &p->out_data.rdata;
1647
1648         /* grab the samr unknown 24 */
1649         if(!samr_io_q_query_userinfo("", &q_u, data, 0))
1650                 return False;
1651
1652         /* construct reply.  always indicate success */
1653         if(!samr_reply_query_userinfo(&q_u, rdata))
1654                 return False;
1655
1656         return True;
1657 }
1658
1659
1660 /*******************************************************************
1661  samr_reply_query_usergroups
1662  ********************************************************************/
1663 static BOOL samr_reply_query_usergroups(SAMR_Q_QUERY_USERGROUPS *q_u,
1664                                 prs_struct *rdata)
1665 {
1666         SAMR_R_QUERY_USERGROUPS r_u;
1667         uint32 status = 0x0;
1668
1669         struct sam_passwd *sam_pass;
1670         DOM_GID *gids = NULL;
1671         int num_groups = 0;
1672         uint32 rid;
1673
1674         DEBUG(5,("samr_query_usergroups: %d\n", __LINE__));
1675
1676         /* find the policy handle.  open a policy on it. */
1677         if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
1678         {
1679                 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1680         }
1681
1682         /* find the user's rid */
1683         if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff)
1684         {
1685                 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
1686         }
1687
1688         if (status == 0x0)
1689         {
1690                 become_root();
1691                 sam_pass = getsam21pwrid(rid);
1692                 unbecome_root();
1693
1694                 if (sam_pass == NULL)
1695                 {
1696                         status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
1697                 }
1698         }
1699
1700         if (status == 0x0)
1701         {
1702                 pstring groups;
1703                 get_domain_user_groups(groups, sam_pass->smb_name);
1704                 gids = NULL;
1705                 num_groups = make_dom_gids(groups, &gids);
1706         }
1707
1708         /* construct the response.  lkclXXXX: gids are not copied! */
1709         init_samr_r_query_usergroups(&r_u, num_groups, gids, status);
1710
1711         /* store the response in the SMB stream */
1712         if(!samr_io_r_query_usergroups("", &r_u, rdata, 0)) {
1713                 if (gids)
1714                         free((char *)gids);
1715                 return False;
1716         }
1717
1718         if (gids)
1719                 free((char *)gids);
1720
1721         DEBUG(5,("samr_query_usergroups: %d\n", __LINE__));
1722         
1723         return True;
1724 }
1725
1726 /*******************************************************************
1727  api_samr_query_usergroups
1728  ********************************************************************/
1729 static BOOL api_samr_query_usergroups(pipes_struct *p)
1730 {
1731         SAMR_Q_QUERY_USERGROUPS q_u;
1732         prs_struct *data = &p->in_data.data;
1733         prs_struct *rdata = &p->out_data.rdata;
1734
1735         /* grab the samr unknown 32 */
1736         if(!samr_io_q_query_usergroups("", &q_u, data, 0))
1737                 return False;
1738
1739         /* construct reply. */
1740         if(!samr_reply_query_usergroups(&q_u, rdata))
1741                 return False;
1742
1743         return True;
1744 }
1745
1746
1747 /*******************************************************************
1748  samr_reply_query_dom_info
1749  ********************************************************************/
1750 static BOOL samr_reply_query_dom_info(SAMR_Q_QUERY_DOMAIN_INFO *q_u, prs_struct *rdata)
1751 {
1752         SAMR_R_QUERY_DOMAIN_INFO r_u;
1753         SAM_UNK_CTR ctr;
1754         uint16 switch_value = 0x0;
1755         uint32 status = 0x0;
1756
1757         ZERO_STRUCT(r_u);
1758         ZERO_STRUCT(ctr);
1759
1760         r_u.ctr = &ctr;
1761
1762         DEBUG(5,("samr_reply_query_dom_info: %d\n", __LINE__));
1763
1764         /* find the policy handle.  open a policy on it. */
1765         if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1))
1766         {
1767                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1768                 DEBUG(5,("samr_reply_query_dom_info: invalid handle\n"));
1769         }
1770
1771         if (status == 0x0)
1772         {
1773                 switch (q_u->switch_value)
1774                 {
1775                         case 0x02:
1776                         {
1777                                 switch_value = 0x2;
1778                                 init_unk_info2(&ctr.info.inf2, global_myworkgroup, global_myname);
1779
1780                                 break;
1781                         }
1782                         default:
1783                         {
1784                                 status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
1785                                 break;
1786                         }
1787                 }
1788         }
1789
1790         init_samr_r_query_dom_info(&r_u, switch_value, &ctr, status);
1791
1792         /* store the response in the SMB stream */
1793         if(!samr_io_r_query_dom_info("", &r_u, rdata, 0))
1794                 return False;
1795
1796         DEBUG(5,("samr_query_dom_info: %d\n", __LINE__));
1797
1798         return True;
1799 }
1800
1801 /*******************************************************************
1802  api_samr_query_dom_info
1803  ********************************************************************/
1804 static BOOL api_samr_query_dom_info(pipes_struct *p)
1805 {
1806         SAMR_Q_QUERY_DOMAIN_INFO q_e;
1807         prs_struct *data = &p->in_data.data;
1808         prs_struct *rdata = &p->out_data.rdata;
1809
1810         /* grab the samr unknown 8 command */
1811         if(!samr_io_q_query_dom_info("", &q_e, data, 0))
1812                 return False;
1813
1814         /* construct reply. */
1815         if(!samr_reply_query_dom_info(&q_e, rdata))
1816                 return False;
1817
1818         return True;
1819 }
1820
1821 /*******************************************************************
1822  samr_reply_unknown_32
1823  ********************************************************************/
1824 static BOOL samr_reply_unknown_32(SAMR_Q_UNKNOWN_32 *q_u,
1825                                 prs_struct *rdata,
1826                                 int status)
1827 {
1828         int i;
1829         SAMR_R_UNKNOWN_32 r_u;
1830
1831         /* set up the SAMR unknown_32 response */
1832         memset((char *)r_u.pol.data, '\0', POL_HND_SIZE);
1833         if (status == 0)
1834         {
1835                 for (i = 4; i < POL_HND_SIZE; i++)
1836                 {
1837                         r_u.pol.data[i] = i+1;
1838                 }
1839         }
1840
1841         init_dom_rid4(&(r_u.rid4), 0x0030, 0, 0);
1842         r_u.status    = status;
1843
1844         DEBUG(5,("samr_unknown_32: %d\n", __LINE__));
1845
1846         /* store the response in the SMB stream */
1847         if(!samr_io_r_unknown_32("", &r_u, rdata, 0))
1848                 return False;
1849
1850         DEBUG(5,("samr_unknown_32: %d\n", __LINE__));
1851
1852         return True;
1853 }
1854
1855 /*******************************************************************
1856  api_samr_unknown_32
1857  ********************************************************************/
1858 static BOOL api_samr_unknown_32(pipes_struct *p)
1859 {
1860         uint32 status = 0;
1861         struct sam_passwd *sam_pass;
1862         fstring mach_acct;
1863         prs_struct *data = &p->in_data.data;
1864         prs_struct *rdata = &p->out_data.rdata;
1865
1866         SAMR_Q_UNKNOWN_32 q_u;
1867
1868         /* grab the samr unknown 32 */
1869         samr_io_q_unknown_32("", &q_u, data, 0);
1870
1871         /* find the machine account: tell the caller if it exists.
1872            lkclXXXX i have *no* idea if this is a problem or not
1873            or even if you are supposed to construct a different
1874            reply if the account already exists...
1875          */
1876
1877         fstrcpy(mach_acct, dos_unistrn2(q_u.uni_mach_acct.buffer,
1878                                     q_u.uni_mach_acct.uni_str_len));
1879
1880         become_root();
1881         sam_pass = getsam21pwnam(mach_acct);
1882         unbecome_root();
1883
1884         if (sam_pass != NULL)
1885         {
1886                 /* machine account exists: say so */
1887                 status = 0xC0000000 | NT_STATUS_USER_EXISTS;
1888         }
1889         else
1890         {
1891                 /* this could cause trouble... */
1892                 DEBUG(0,("trouble!\n"));
1893                 status = 0;
1894         }
1895
1896         /* construct reply. */
1897         if(!samr_reply_unknown_32(&q_u, rdata, status))
1898                 return False;
1899
1900         return True;
1901 }
1902
1903
1904 /*******************************************************************
1905  samr_reply_connect_anon
1906  ********************************************************************/
1907 static BOOL samr_reply_connect_anon(SAMR_Q_CONNECT_ANON *q_u, prs_struct *rdata)
1908 {
1909         SAMR_R_CONNECT_ANON r_u;
1910         BOOL pol_open = False;
1911
1912         /* set up the SAMR connect_anon response */
1913
1914         r_u.status = 0x0;
1915         /* get a (unique) handle.  open a policy on it. */
1916         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.connect_pol))))
1917         {
1918                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1919         }
1920
1921         /* associate the domain SID with the (unique) handle. */
1922         if (r_u.status == 0x0 && !set_lsa_policy_samr_pol_status(&(r_u.connect_pol), q_u->unknown_0))
1923         {
1924                 /* oh, whoops.  don't know what error message to return, here */
1925                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1926         }
1927
1928         if (r_u.status != 0 && pol_open)
1929         {
1930                 close_lsa_policy_hnd(&(r_u.connect_pol));
1931         }
1932
1933         DEBUG(5,("samr_connect_anon: %d\n", __LINE__));
1934
1935         /* store the response in the SMB stream */
1936         if(!samr_io_r_connect_anon("", &r_u, rdata, 0))
1937                 return False;
1938
1939         DEBUG(5,("samr_connect_anon: %d\n", __LINE__));
1940
1941         return True;
1942 }
1943
1944 /*******************************************************************
1945  api_samr_connect_anon
1946  ********************************************************************/
1947 static BOOL api_samr_connect_anon(pipes_struct *p)
1948 {
1949         SAMR_Q_CONNECT_ANON q_u;
1950         prs_struct *data = &p->in_data.data;
1951         prs_struct *rdata = &p->out_data.rdata;
1952
1953         /* grab the samr open policy */
1954         if(!samr_io_q_connect_anon("", &q_u, data, 0))
1955                 return False;
1956
1957         /* construct reply.  always indicate success */
1958         if(!samr_reply_connect_anon(&q_u, rdata))
1959                 return False;
1960
1961         return True;
1962 }
1963
1964 /*******************************************************************
1965  samr_reply_connect
1966  ********************************************************************/
1967 static BOOL samr_reply_connect(SAMR_Q_CONNECT *q_u, prs_struct *rdata)
1968 {
1969         SAMR_R_CONNECT r_u;
1970         BOOL pol_open = False;
1971
1972         /* set up the SAMR connect response */
1973
1974         r_u.status = 0x0;
1975         /* get a (unique) handle.  open a policy on it. */
1976         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.connect_pol))))
1977         {
1978                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1979         }
1980
1981         /* associate the domain SID with the (unique) handle. */
1982         if (r_u.status == 0x0 && !set_lsa_policy_samr_pol_status(&(r_u.connect_pol), q_u->unknown_0))
1983         {
1984                 /* oh, whoops.  don't know what error message to return, here */
1985                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1986         }
1987
1988         if (r_u.status != 0 && pol_open)
1989         {
1990                 close_lsa_policy_hnd(&(r_u.connect_pol));
1991         }
1992
1993         DEBUG(5,("samr_connect: %d\n", __LINE__));
1994
1995         /* store the response in the SMB stream */
1996         if(!samr_io_r_connect("", &r_u, rdata, 0))
1997                 return False;
1998
1999         DEBUG(5,("samr_connect: %d\n", __LINE__));
2000
2001         return True;
2002 }
2003
2004 /*******************************************************************
2005  api_samr_connect
2006  ********************************************************************/
2007 static BOOL api_samr_connect(pipes_struct *p)
2008 {
2009         SAMR_Q_CONNECT q_u;
2010         prs_struct *data = &p->in_data.data;
2011         prs_struct *rdata = &p->out_data.rdata;
2012
2013         /* grab the samr open policy */
2014         if(!samr_io_q_connect("", &q_u, data, 0))
2015                 return False;
2016
2017         /* construct reply.  always indicate success */
2018         if(!samr_reply_connect(&q_u, rdata))
2019                 return False;
2020
2021         return True;
2022 }
2023
2024 /**********************************************************************
2025  api_reply_lookup_domain
2026  **********************************************************************/
2027 static BOOL samr_reply_lookup_domain(SAMR_Q_LOOKUP_DOMAIN* q_u, prs_struct* rdata)
2028 {
2029   SAMR_R_LOOKUP_DOMAIN r_u;
2030   
2031   r_u.status = 0x0;
2032   if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->connect_pol)) == -1))
2033         {
2034                 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
2035                 DEBUG(5,("samr_reply_lookup_domain: invalid handle\n"));
2036         }
2037   
2038   /* assume the domain name sent is our global_myname and 
2039      send global_sam_sid */
2040   init_samr_r_lookup_domain(&r_u, &global_sam_sid, r_u.status);
2041   
2042         if(!samr_io_r_lookup_domain("", &r_u, rdata, 0))
2043                 return False;
2044
2045   DEBUG(5,("samr_reply_lookup_domain: %d\n", __LINE__));
2046  
2047         return True; 
2048 }
2049   
2050 /**********************************************************************
2051  api_samr_lookup_domain
2052  **********************************************************************/
2053 static BOOL api_samr_lookup_domain(pipes_struct *p)
2054 {
2055         SAMR_Q_LOOKUP_DOMAIN q_u;
2056         prs_struct *data = &p->in_data.data;
2057         prs_struct *rdata = &p->out_data.rdata;
2058   
2059         if(!samr_io_q_lookup_domain("", &q_u, data, 0))
2060                 return False;
2061         
2062         if(!samr_reply_lookup_domain(&q_u, rdata))
2063                 return False;
2064         
2065         return True;
2066 }
2067
2068 /**********************************************************************
2069  samr_reply_enum_domains
2070  **********************************************************************/
2071 static BOOL samr_reply_enum_domains(SAMR_Q_ENUM_DOMAINS* q_u, prs_struct* rdata)
2072 {
2073   SAMR_R_ENUM_DOMAINS r_u;
2074   fstring dom[2];
2075
2076   fstrcpy(dom[0],global_myname);
2077   fstrcpy(dom[1],"Builtin");
2078   r_u.status = 0;
2079    
2080   init_samr_r_enum_domains(&r_u, q_u->start_idx, dom, 2); 
2081   if(!samr_io_r_enum_domains("", &r_u, rdata, 0)) {
2082                 free(r_u.sam);
2083                 free(r_u.uni_dom_name);
2084                 return False;
2085         }
2086
2087   free(r_u.sam);
2088   free(r_u.uni_dom_name);
2089
2090         return True;
2091 }
2092
2093 /**********************************************************************
2094  api_samr_enum_domains
2095  **********************************************************************/
2096 static BOOL api_samr_enum_domains(pipes_struct *p)
2097 {
2098         SAMR_Q_ENUM_DOMAINS q_u;
2099         prs_struct *data = &p->in_data.data;
2100         prs_struct *rdata = &p->out_data.rdata;
2101
2102         if(!samr_io_q_enum_domains("", &q_u, data, 0))
2103                 return False;
2104         
2105         if(!samr_reply_enum_domains(&q_u, rdata))
2106                 return False;
2107         
2108         return True;
2109 }
2110
2111 /*******************************************************************
2112  samr_reply_open_alias
2113  ********************************************************************/
2114 static BOOL samr_reply_open_alias(SAMR_Q_OPEN_ALIAS *q_u, prs_struct *rdata)
2115 {
2116         SAMR_R_OPEN_ALIAS r_u;
2117         BOOL pol_open = False;
2118
2119         /* set up the SAMR open_alias response */
2120
2121         r_u.status = 0x0;
2122         /* get a (unique) handle.  open a policy on it. */
2123         if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.pol))))
2124         {
2125                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2126         }
2127
2128         /* associate a RID with the (unique) handle. */
2129         if (r_u.status == 0x0 && !set_lsa_policy_samr_rid(&(r_u.pol), q_u->rid_alias))
2130         {
2131                 /* oh, whoops.  don't know what error message to return, here */
2132                 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2133         }
2134
2135         if (r_u.status != 0 && pol_open)
2136         {
2137                 close_lsa_policy_hnd(&(r_u.pol));
2138         }
2139
2140         DEBUG(5,("samr_open_alias: %d\n", __LINE__));
2141
2142         /* store the response in the SMB stream */
2143         if(!samr_io_r_open_alias("", &r_u, rdata, 0))
2144                 return False;
2145
2146         DEBUG(5,("samr_open_alias: %d\n", __LINE__));
2147         
2148         return True;
2149 }
2150
2151 /*******************************************************************
2152  api_samr_open_alias
2153  ********************************************************************/
2154 static BOOL api_samr_open_alias(pipes_struct *p)
2155 {
2156         SAMR_Q_OPEN_ALIAS q_u;
2157         prs_struct *data = &p->in_data.data;
2158         prs_struct *rdata = &p->out_data.rdata;
2159
2160         /* grab the samr open policy */
2161         if(!samr_io_q_open_alias("", &q_u, data, 0))
2162                 return False;
2163
2164         /* construct reply.  always indicate success */
2165         if(!samr_reply_open_alias(&q_u, rdata))
2166                 return False;
2167
2168         return True;
2169 }
2170
2171 /*******************************************************************
2172  array of \PIPE\samr operations
2173  ********************************************************************/
2174 static struct api_struct api_samr_cmds [] =
2175 {
2176         { "SAMR_CLOSE_HND"        , SAMR_CLOSE_HND        , api_samr_close_hnd        },
2177         { "SAMR_CONNECT"          , SAMR_CONNECT          , api_samr_connect          },
2178         { "SAMR_CONNECT_ANON"     , SAMR_CONNECT_ANON     , api_samr_connect_anon     },
2179         { "SAMR_ENUM_DOM_USERS"   , SAMR_ENUM_DOM_USERS   , api_samr_enum_dom_users   },
2180         { "SAMR_ENUM_DOM_GROUPS"  , SAMR_ENUM_DOM_GROUPS  , api_samr_enum_dom_groups  },
2181         { "SAMR_ENUM_DOM_ALIASES" , SAMR_ENUM_DOM_ALIASES , api_samr_enum_dom_aliases },
2182         { "SAMR_LOOKUP_IDS"       , SAMR_LOOKUP_IDS       , api_samr_lookup_ids       },
2183         { "SAMR_LOOKUP_NAMES"     , SAMR_LOOKUP_NAMES     , api_samr_lookup_names     },
2184         { "SAMR_OPEN_USER"        , SAMR_OPEN_USER        , api_samr_open_user        },
2185         { "SAMR_QUERY_USERINFO"   , SAMR_QUERY_USERINFO   , api_samr_query_userinfo   },
2186         { "SAMR_QUERY_DOMAIN_INFO", SAMR_QUERY_DOMAIN_INFO, api_samr_query_dom_info        },
2187         { "SAMR_QUERY_USERGROUPS" , SAMR_QUERY_USERGROUPS , api_samr_query_usergroups },
2188         { "SAMR_QUERY_DISPINFO"   , SAMR_QUERY_DISPINFO   , api_samr_query_dispinfo   },
2189         { "SAMR_QUERY_ALIASINFO"  , SAMR_QUERY_ALIASINFO  , api_samr_query_aliasinfo  },
2190         { "SAMR_0x32"             , 0x32                  , api_samr_unknown_32       },
2191         { "SAMR_UNKNOWN_12"       , SAMR_UNKNOWN_12       , api_samr_unknown_12       },
2192         { "SAMR_UNKNOWN_38"       , SAMR_UNKNOWN_38       , api_samr_unknown_38       },
2193         { "SAMR_CHGPASSWD_USER"   , SAMR_CHGPASSWD_USER   , api_samr_chgpasswd_user   },
2194         { "SAMR_OPEN_ALIAS"       , SAMR_OPEN_ALIAS       , api_samr_open_alias       },
2195         { "SAMR_OPEN_DOMAIN"      , SAMR_OPEN_DOMAIN      , api_samr_open_domain      },
2196         { "SAMR_UNKNOWN_3"        , SAMR_UNKNOWN_3        , api_samr_unknown_3        },
2197         { "SAMR_UNKNOWN_2C"       , SAMR_UNKNOWN_2C       , api_samr_unknown_2c       },
2198         { "SAMR_LOOKUP_DOMAIN"    , SAMR_LOOKUP_DOMAIN    , api_samr_lookup_domain    },
2199         { "SAMR_ENUM_DOMAINS"     , SAMR_ENUM_DOMAINS     , api_samr_enum_domains     },
2200         { NULL                    , 0                     , NULL                      }
2201 };
2202
2203 /*******************************************************************
2204  receives a samr pipe and responds.
2205  ********************************************************************/
2206 BOOL api_samr_rpc(pipes_struct *p)
2207 {
2208         return api_rpcTNP(p, "api_samr_rpc", api_samr_cmds);
2209 }
2210 #undef OLD_NTDOMAIN