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