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