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