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