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