fixed unitialized struct bug in enum_users (whatever it is called)
[Samba/gbeck.git] / source / rpc_server / srv_samr.c
blob04399a638c36c1ba2051e549346546fa8a4b0958
1 #define OLD_NTDOMAIN 1
2 /*
3 * Unix SMB/Netbios implementation.
4 * Version 1.9.
5 * RPC Pipe client / server routines
6 * Copyright (C) Andrew Tridgell 1992-1997,
7 * Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
8 * Copyright (C) Paul Ashton 1997.
9 * Copyright (C) Hewlett-Packard Company 1999.
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 #include "includes.h"
28 extern int DEBUGLEVEL;
30 extern fstring global_myworkgroup;
31 extern pstring global_myname;
32 extern DOM_SID global_sam_sid;
34 extern rid_name domain_group_rids[];
35 extern rid_name domain_alias_rids[];
36 extern rid_name builtin_alias_rids[];
38 /*******************************************************************
39 This next function should be replaced with something that
40 dynamically returns the correct user info..... JRA.
41 ********************************************************************/
43 static BOOL get_sampwd_entries(SAM_USER_INFO_21 *pw_buf,
44 int start_idx,
45 int *total_entries, int *num_entries,
46 int max_num_entries,
47 uint16 acb_mask)
49 void *vp = NULL;
50 struct sam_passwd *pwd = NULL;
52 (*num_entries) = 0;
53 (*total_entries) = 0;
55 if (pw_buf == NULL) return False;
57 vp = startsmbpwent(False);
58 if (!vp) {
59 DEBUG(0, ("get_sampwd_entries: Unable to open SMB password database.\n"));
60 return False;
63 while (((pwd = getsam21pwent(vp)) != NULL) && (*num_entries) < max_num_entries) {
64 int user_name_len;
66 if (start_idx > 0) {
67 /* skip the requested number of entries.
68 not very efficient, but hey...
70 start_idx--;
71 continue;
74 user_name_len = strlen(pwd->smb_name);
75 init_unistr2(&(pw_buf[(*num_entries)].uni_user_name), pwd->smb_name, user_name_len);
76 init_uni_hdr(&(pw_buf[(*num_entries)].hdr_user_name), user_name_len);
77 pw_buf[(*num_entries)].user_rid = pwd->user_rid;
78 memset((char *)pw_buf[(*num_entries)].nt_pwd, '\0', 16);
80 /* Now check if the NT compatible password is available. */
81 if (pwd->smb_nt_passwd != NULL) {
82 memcpy( pw_buf[(*num_entries)].nt_pwd , pwd->smb_nt_passwd, 16);
85 pw_buf[(*num_entries)].acb_info = (uint16)pwd->acct_ctrl;
87 DEBUG(5, ("entry idx: %d user %s, rid 0x%x, acb %x",
88 (*num_entries), pwd->smb_name,
89 pwd->user_rid, pwd->acct_ctrl));
91 if (acb_mask == 0 || (pwd->acct_ctrl & acb_mask)) {
92 DEBUG(5,(" acb_mask %x accepts\n", acb_mask));
93 (*num_entries)++;
94 } else {
95 DEBUG(5,(" acb_mask %x rejects\n", acb_mask));
98 (*total_entries)++;
101 endsmbpwent(vp);
103 return (*num_entries) > 0;
106 /*******************************************************************
107 This function uses the username map file and tries to map a UNIX
108 user name to an DOS name. (Sort of the reverse of the
109 map_username() function.) Since more than one DOS name can map
110 to the UNIX name, to reverse the mapping you have to specify
111 which corresponding DOS name you want; that's where the name_idx
112 parameter comes in. Returns the string requested or NULL if it
113 fails or can't complete the request for any reason. This doesn't
114 handle group names (starting with '@') or names starting with
115 '+' or '&'. If they are encountered, they are skipped.
116 ********************************************************************/
118 static char *unmap_unixname(char *unix_user_name, int name_idx)
120 char *mapfile = lp_username_map();
121 char **lines;
122 static pstring tok;
123 int i;
125 if (!*unix_user_name) return NULL;
126 if (!*mapfile) return NULL;
128 lines = file_lines_load(mapfile, NULL);
129 if (!lines) {
130 DEBUG(0,("unmap_unixname: can't open username map %s\n", mapfile));
131 return NULL;
134 DEBUG(5,("unmap_unixname: scanning username map %s, index: %d\n", mapfile, name_idx));
136 for (i=0; lines[i]; i++) {
137 char *unixname = lines[i];
138 char *dosname = strchr(unixname,'=');
140 if (!dosname)
141 continue;
143 *dosname++ = 0;
145 while (isspace(*unixname))
146 unixname++;
147 if ('!' == *unixname) {
148 unixname++;
149 while (*unixname && isspace(*unixname))
150 unixname++;
153 if (!*unixname || strchr("#;",*unixname))
154 continue;
156 if (strncmp(unixname, unix_user_name, strlen(unix_user_name)))
157 continue;
159 /* We have matched the UNIX user name */
161 while(next_token(&dosname, tok, LIST_SEP, sizeof(tok))) {
162 if (!strchr("@&+", *tok)) {
163 name_idx--;
164 if (name_idx < 0 ) {
165 break;
170 if (name_idx >= 0) {
171 DEBUG(0,("unmap_unixname: index too high - not that many DOS names\n"));
172 file_lines_free(lines);
173 return NULL;
174 } else {
175 file_lines_free(lines);
176 return tok;
180 DEBUG(0,("unmap_unixname: Couldn't find the UNIX user name\n"));
181 file_lines_free(lines);
182 return NULL;
185 /*******************************************************************
186 This function sets up a list of users taken from the list of
187 users that UNIX knows about, as well as all the user names that
188 Samba maps to a valid UNIX user name. (This should work with
189 /etc/passwd or NIS.)
190 ********************************************************************/
192 static BOOL get_passwd_entries(SAM_USER_INFO_21 *pw_buf,
193 int start_idx,
194 int *total_entries, int *num_entries,
195 int max_num_entries,
196 uint16 acb_mask)
198 static struct passwd *pwd = NULL;
199 static uint32 pw_rid;
200 static BOOL orig_done = False;
201 static int current_idx = 0;
202 static int mapped_idx = 0;
203 char *sep;
205 DEBUG(5, ("get_passwd_entries: retrieving a list of UNIX users\n"));
207 (*num_entries) = 0;
208 (*total_entries) = 0;
210 if (pw_buf == NULL) return False;
212 if (current_idx == 0) {
213 setpwent();
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;
225 if(!orig_done) {
226 if ((pwd = getpwent()) == NULL) break;
227 current_idx++;
228 orig_done = True;
231 while (((unmap_name = unmap_unixname(pwd->pw_name, mapped_idx)) != NULL) &&
232 (current_idx < start_idx)) {
233 current_idx++;
234 mapped_idx++;
237 if (unmap_name == NULL) {
238 orig_done = False;
239 mapped_idx = 0;
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;
252 if(!orig_done) {
253 if ((pwd = getpwent()) == NULL) break;
254 current_idx++;
255 orig_done = True;
258 while (((unmap_name = unmap_unixname(pwd->pw_name, mapped_idx)) != NULL) &&
259 (current_idx < start_idx)) {
260 current_idx++;
261 mapped_idx++;
264 if (unmap_name == NULL) {
265 orig_done = False;
266 mapped_idx = 0;
271 sep = lp_winbind_separator();
273 /* now current_idx == start_idx */
274 while ((*num_entries) < max_num_entries) {
275 int user_name_len;
276 char *unmap_name;
278 /* This does the original UNIX user itself */
279 if(!orig_done) {
280 if ((pwd = getpwent()) == NULL) break;
282 /* Don't enumerate winbind users as they are not local */
284 if (strchr(pwd->pw_name, *sep) != NULL) {
285 continue;
288 user_name_len = strlen(pwd->pw_name);
289 pw_rid = pdb_uid_to_user_rid(pwd->pw_uid);
290 ZERO_STRUCTP(&pw_buf[(*num_entries)]);
291 init_unistr2(&(pw_buf[(*num_entries)].uni_user_name), pwd->pw_name, user_name_len);
292 init_uni_hdr(&(pw_buf[(*num_entries)].hdr_user_name), user_name_len);
293 pw_buf[(*num_entries)].user_rid = pw_rid;
294 memset((char *)pw_buf[(*num_entries)].nt_pwd, '\0', 16);
296 pw_buf[(*num_entries)].acb_info = ACB_NORMAL;
298 DEBUG(5, ("get_passwd_entries: entry idx %d user %s, rid 0x%x\n", (*num_entries), pwd->pw_name, pw_rid));
300 (*num_entries)++;
301 (*total_entries)++;
302 current_idx++;
303 orig_done = True;
306 /* This does all the user names that map to the UNIX user */
307 while (((unmap_name = unmap_unixname(pwd->pw_name, mapped_idx)) != NULL) &&
308 (*num_entries < max_num_entries)) {
309 user_name_len = strlen(unmap_name);
310 ZERO_STRUCTP(&pw_buf[(*num_entries)]);
311 init_unistr2(&(pw_buf[(*num_entries)].uni_user_name), unmap_name, user_name_len);
312 init_uni_hdr(&(pw_buf[(*num_entries)].hdr_user_name), user_name_len);
313 pw_buf[(*num_entries)].user_rid = pw_rid;
314 memset((char *)pw_buf[(*num_entries)].nt_pwd, '\0', 16);
316 pw_buf[(*num_entries)].acb_info = ACB_NORMAL;
318 DEBUG(5, ("get_passwd_entries: entry idx %d user %s, rid 0x%x\n", (*num_entries), pwd->pw_name, pw_rid));
320 (*num_entries)++;
321 (*total_entries)++;
322 current_idx++;
323 mapped_idx++;
326 if (unmap_name == NULL) {
327 /* done with 'aliases', go on to next UNIX user */
328 orig_done = False;
329 mapped_idx = 0;
333 if (pwd == NULL) {
334 /* totally done, reset everything */
335 endpwent();
336 current_idx = 0;
337 mapped_idx = 0;
340 return (*num_entries) > 0;
343 /*******************************************************************
344 samr_reply_unknown_1
345 ********************************************************************/
346 static BOOL samr_reply_close_hnd(SAMR_Q_CLOSE_HND *q_u,
347 prs_struct *rdata)
349 SAMR_R_CLOSE_HND r_u;
351 /* set up the SAMR unknown_1 response */
352 memset((char *)r_u.pol.data, '\0', POL_HND_SIZE);
354 /* close the policy handle */
355 if (close_lsa_policy_hnd(&(q_u->pol)))
357 r_u.status = 0;
359 else
361 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_INVALID;
364 DEBUG(5,("samr_reply_close_hnd: %d\n", __LINE__));
366 /* store the response in the SMB stream */
367 if(!samr_io_r_close_hnd("", &r_u, rdata, 0))
368 return False;
370 DEBUG(5,("samr_reply_close_hnd: %d\n", __LINE__));
372 return True;
375 /*******************************************************************
376 api_samr_close_hnd
377 ********************************************************************/
378 static BOOL api_samr_close_hnd(pipes_struct *p)
380 SAMR_Q_CLOSE_HND q_u;
381 prs_struct *data = &p->in_data.data;
382 prs_struct *rdata = &p->out_data.rdata;
384 /* grab the samr unknown 1 */
385 if(!samr_io_q_close_hnd("", &q_u, data, 0))
386 return False;
388 /* construct reply. always indicate success */
389 if(!samr_reply_close_hnd(&q_u, rdata))
390 return False;
392 return True;
396 /*******************************************************************
397 samr_reply_open_domain
398 ********************************************************************/
399 static BOOL samr_reply_open_domain(SAMR_Q_OPEN_DOMAIN *q_u,
400 prs_struct *rdata)
402 SAMR_R_OPEN_DOMAIN r_u;
403 BOOL pol_open = False;
405 r_u.status = 0x0;
407 /* find the connection policy handle. */
408 if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->connect_pol)) == -1))
410 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
413 /* get a (unique) handle. open a policy on it. */
414 if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.domain_pol))))
416 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
419 /* associate the domain SID with the (unique) handle. */
420 if (r_u.status == 0x0 && !set_lsa_policy_samr_sid(&(r_u.domain_pol), &(q_u->dom_sid.sid)))
422 /* oh, whoops. don't know what error message to return, here */
423 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
426 if (r_u.status != 0 && pol_open)
428 close_lsa_policy_hnd(&(r_u.domain_pol));
431 DEBUG(5,("samr_open_domain: %d\n", __LINE__));
433 /* store the response in the SMB stream */
434 if(!samr_io_r_open_domain("", &r_u, rdata, 0))
435 return False;
437 DEBUG(5,("samr_open_domain: %d\n", __LINE__));
439 return True;
442 /*******************************************************************
443 api_samr_open_domain
444 ********************************************************************/
445 static BOOL api_samr_open_domain(pipes_struct *p)
447 SAMR_Q_OPEN_DOMAIN q_u;
448 prs_struct *data = &p->in_data.data;
449 prs_struct *rdata = &p->out_data.rdata;
451 /* grab the samr open */
452 if(!samr_io_q_open_domain("", &q_u, data, 0))
453 return False;
455 /* construct reply. always indicate success */
456 if(!samr_reply_open_domain(&q_u, rdata))
457 return False;
459 return True;
463 /*******************************************************************
464 samr_reply_unknown_2c
465 ********************************************************************/
466 static BOOL samr_reply_unknown_2c(SAMR_Q_UNKNOWN_2C *q_u,
467 prs_struct *rdata)
469 SAMR_R_UNKNOWN_2C r_u;
470 uint32 status = 0x0;
472 /* find the policy handle. open a policy on it. */
473 if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->user_pol)) == -1))
475 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
478 /* find the user's rid */
479 if ((status == 0x0) && (get_lsa_policy_samr_rid(&(q_u->user_pol)) == 0xffffffff))
481 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
484 init_samr_r_unknown_2c(&r_u, status);
486 DEBUG(5,("samr_unknown_2c: %d\n", __LINE__));
488 /* store the response in the SMB stream */
489 if(!samr_io_r_unknown_2c("", &r_u, rdata, 0))
490 return False;
492 DEBUG(5,("samr_unknown_2c: %d\n", __LINE__));
494 return True;
497 /*******************************************************************
498 api_samr_unknown_2c
499 ********************************************************************/
500 static BOOL api_samr_unknown_2c(pipes_struct *p)
502 SAMR_Q_UNKNOWN_2C q_u;
503 prs_struct *data = &p->in_data.data;
504 prs_struct *rdata = &p->out_data.rdata;
506 /* grab the samr open */
507 if(!samr_io_q_unknown_2c("", &q_u, data, 0))
508 return False;
510 /* construct reply. always indicate success */
511 if(!samr_reply_unknown_2c(&q_u, rdata))
512 return False;
514 return True;
518 /*******************************************************************
519 samr_reply_unknown_3
520 ********************************************************************/
521 static BOOL samr_reply_unknown_3(SAMR_Q_UNKNOWN_3 *q_u,
522 prs_struct *rdata)
524 SAMR_R_UNKNOWN_3 r_u;
525 DOM_SID3 sid[MAX_SAM_SIDS];
526 uint32 rid;
527 uint32 status;
529 status = 0x0;
531 /* find the policy handle. open a policy on it. */
532 if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->user_pol)) == -1))
534 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
537 /* find the user's rid */
538 if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->user_pol))) == 0xffffffff)
540 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
543 if (status == 0x0)
545 DOM_SID user_sid;
546 DOM_SID everyone_sid;
548 user_sid = global_sam_sid;
550 SMB_ASSERT_ARRAY(user_sid.sub_auths, user_sid.num_auths+1);
553 * Add the user RID.
555 user_sid.sub_auths[user_sid.num_auths++] = rid;
557 string_to_sid(&everyone_sid, "S-1-1");
559 /* maybe need another 1 or 2 (S-1-5-0x20-0x220 and S-1-5-20-0x224) */
560 /* these two are DOMAIN_ADMIN and DOMAIN_ACCT_OP group RIDs */
561 init_dom_sid3(&(sid[0]), 0x035b, 0x0002, &everyone_sid);
562 init_dom_sid3(&(sid[1]), 0x0044, 0x0002, &user_sid);
565 init_samr_r_unknown_3(&r_u,
566 0x0001, 0x8004,
567 0x00000014, 0x0002, 0x0070,
568 2, sid, status);
570 DEBUG(5,("samr_unknown_3: %d\n", __LINE__));
572 /* store the response in the SMB stream */
573 if(!samr_io_r_unknown_3("", &r_u, rdata, 0))
574 return False;
576 DEBUG(5,("samr_unknown_3: %d\n", __LINE__));
578 return True;
581 /*******************************************************************
582 api_samr_unknown_3
583 ********************************************************************/
584 static BOOL api_samr_unknown_3(pipes_struct *p)
586 SAMR_Q_UNKNOWN_3 q_u;
587 prs_struct *data = &p->in_data.data;
588 prs_struct *rdata = &p->out_data.rdata;
590 /* grab the samr open */
591 if(!samr_io_q_unknown_3("", &q_u, data, 0))
592 return False;
594 /* construct reply. always indicate success */
595 if(!samr_reply_unknown_3(&q_u, rdata))
596 return False;
598 return True;
602 /*******************************************************************
603 samr_reply_enum_dom_users
604 ********************************************************************/
605 static BOOL samr_reply_enum_dom_users(SAMR_Q_ENUM_DOM_USERS *q_u,
606 prs_struct *rdata)
608 SAMR_R_ENUM_DOM_USERS r_e;
609 SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
610 int num_entries;
611 int total_entries;
613 r_e.status = 0x0;
614 r_e.total_num_entries = 0;
616 /* find the policy handle. open a policy on it. */
617 if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
619 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
622 DEBUG(5,("samr_reply_enum_dom_users: %d\n", __LINE__));
624 become_root();
625 get_sampwd_entries(pass, 0, &total_entries, &num_entries, MAX_SAM_ENTRIES, q_u->acb_mask);
626 unbecome_root();
628 init_samr_r_enum_dom_users(&r_e, total_entries,
629 q_u->unknown_0, num_entries,
630 pass, r_e.status);
632 /* store the response in the SMB stream */
633 if(!samr_io_r_enum_dom_users("", &r_e, rdata, 0))
634 return False;
636 DEBUG(5,("samr_enum_dom_users: %d\n", __LINE__));
638 return True;
641 /*******************************************************************
642 api_samr_enum_dom_users
643 ********************************************************************/
644 static BOOL api_samr_enum_dom_users(pipes_struct *p)
646 SAMR_Q_ENUM_DOM_USERS q_e;
647 prs_struct *data = &p->in_data.data;
648 prs_struct *rdata = &p->out_data.rdata;
650 /* grab the samr open */
651 if(!samr_io_q_enum_dom_users("", &q_e, data, 0))
652 return False;
654 /* construct reply. */
655 if(!samr_reply_enum_dom_users(&q_e, rdata))
656 return False;
658 return True;
661 /*******************************************************************
662 samr_reply_enum_dom_groups
663 ********************************************************************/
664 static BOOL samr_reply_enum_dom_groups(SAMR_Q_ENUM_DOM_GROUPS *q_u,
665 prs_struct *rdata)
667 SAMR_R_ENUM_DOM_GROUPS r_e;
668 SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
669 int num_entries;
670 BOOL got_grps;
671 char *dummy_group = "Domain Admins";
673 r_e.status = 0x0;
674 r_e.num_entries = 0;
676 /* find the policy handle. open a policy on it. */
677 if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
679 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
682 DEBUG(5,("samr_reply_enum_dom_groups: %d\n", __LINE__));
684 got_grps = True;
685 num_entries = 1;
686 ZERO_STRUCTP(&pass[0]);
687 init_unistr2(&(pass[0].uni_user_name), dummy_group, strlen(dummy_group));
688 pass[0].user_rid = DOMAIN_GROUP_RID_ADMINS;
690 if (r_e.status == 0 && got_grps)
692 init_samr_r_enum_dom_groups(&r_e, q_u->start_idx, num_entries, pass, r_e.status);
695 /* store the response in the SMB stream */
696 if(!samr_io_r_enum_dom_groups("", &r_e, rdata, 0))
697 return False;
699 DEBUG(5,("samr_enum_dom_groups: %d\n", __LINE__));
701 return True;
704 /*******************************************************************
705 api_samr_enum_dom_groups
706 ********************************************************************/
707 static BOOL api_samr_enum_dom_groups(pipes_struct *p)
709 SAMR_Q_ENUM_DOM_GROUPS q_e;
710 prs_struct *data = &p->in_data.data;
711 prs_struct *rdata = &p->out_data.rdata;
713 /* grab the samr open */
714 if(!samr_io_q_enum_dom_groups("", &q_e, data, 0))
715 return False;
717 /* construct reply. */
718 if(!samr_reply_enum_dom_groups(&q_e, rdata))
719 return False;
721 return True;
724 /*******************************************************************
725 samr_reply_enum_dom_aliases
726 ********************************************************************/
727 static BOOL samr_reply_enum_dom_aliases(SAMR_Q_ENUM_DOM_ALIASES *q_u,
728 prs_struct *rdata)
730 SAMR_R_ENUM_DOM_ALIASES r_e;
731 SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
732 int num_entries = 0;
733 DOM_SID sid;
734 fstring sid_str;
735 fstring sam_sid_str;
736 struct group *grp;
738 ZERO_STRUCT(r_e);
740 /* find the policy handle. open a policy on it. */
741 if (r_e.status == 0x0 && !get_lsa_policy_samr_sid(&q_u->pol, &sid))
743 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
746 sid_to_string(sid_str, &sid);
747 sid_to_string(sam_sid_str, &global_sam_sid);
749 DEBUG(5,("samr_reply_enum_dom_aliases: sid %s\n", sid_str));
751 /* well-known aliases */
752 if (strequal(sid_str, "S-1-5-32"))
754 char *name;
755 while (num_entries < MAX_SAM_ENTRIES && ((name = builtin_alias_rids[num_entries].name) != NULL))
757 init_unistr2(&(pass[num_entries].uni_user_name), name, strlen(name));
758 pass[num_entries].user_rid = builtin_alias_rids[num_entries].rid;
759 num_entries++;
762 else if (strequal(sid_str, sam_sid_str))
764 char *name;
765 char *sep;
767 sep = lp_winbind_separator();
769 /* local aliases */
770 /* we return the UNIX groups here. This seems to be the right */
771 /* thing to do, since NT member servers return their local */
772 /* groups in the same situation. */
773 setgrent();
775 while (num_entries < MAX_SAM_ENTRIES && ((grp = getgrent()) != NULL))
777 name = grp->gr_name;
779 /* Don't return winbind groups as they are not local! */
781 if (strchr(name, *sep) != NULL) {
782 continue;
785 init_unistr2(&(pass[num_entries].uni_user_name), name, strlen(name));
786 pass[num_entries].user_rid = pdb_gid_to_group_rid(grp->gr_gid);
787 num_entries++;
790 endgrent();
793 init_samr_r_enum_dom_aliases(&r_e, num_entries, pass, r_e.status);
795 /* store the response in the SMB stream */
796 if(!samr_io_r_enum_dom_aliases("", &r_e, rdata, 0))
797 return False;
799 DEBUG(5,("samr_enum_dom_aliases: %d\n", __LINE__));
801 return True;
804 /*******************************************************************
805 api_samr_enum_dom_aliases
806 ********************************************************************/
807 static BOOL api_samr_enum_dom_aliases(pipes_struct *p)
809 SAMR_Q_ENUM_DOM_ALIASES q_e;
810 prs_struct *data = &p->in_data.data;
811 prs_struct *rdata = &p->out_data.rdata;
813 ZERO_STRUCT(q_e);
815 /* grab the samr open */
816 if(!samr_io_q_enum_dom_aliases("", &q_e, data, 0))
817 return False;
819 /* construct reply. */
820 if(!samr_reply_enum_dom_aliases(&q_e, rdata))
821 return False;
823 return True;
827 /*******************************************************************
828 samr_reply_query_dispinfo
829 ********************************************************************/
830 static BOOL samr_reply_query_dispinfo(SAMR_Q_QUERY_DISPINFO *q_u, prs_struct *rdata)
832 SAMR_R_QUERY_DISPINFO r_e;
833 SAM_INFO_CTR ctr;
834 SAM_INFO_1 info1;
835 SAM_INFO_2 info2;
836 SAM_USER_INFO_21 pass[MAX_SAM_ENTRIES];
837 int num_entries = 0;
838 int total_entries = 0;
839 BOOL got_pwds;
840 uint16 switch_level = 0x0;
842 ZERO_STRUCT(r_e);
844 DEBUG(5,("samr_reply_query_dispinfo: %d\n", __LINE__));
846 /* find the policy handle. open a policy on it. */
847 if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
849 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
850 DEBUG(5,("samr_reply_query_dispinfo: invalid handle\n"));
853 if (r_e.status == 0x0)
855 /* decide how many entries to get depending on the max_entries
856 and max_size passed by client */
857 uint32 retsize;
859 if(q_u->max_entries > MAX_SAM_ENTRIES)
860 q_u->max_entries = MAX_SAM_ENTRIES;
862 retsize = (q_u->max_entries * (sizeof(SAM_ENTRY1)+sizeof(SAM_STR1)))
863 + 3*sizeof(uint32);
865 if(retsize > q_u->max_size)
867 /* determine max_entries based on max_size */
868 q_u->max_entries = (q_u->max_size - 3*sizeof(uint32)) /
869 (sizeof(SAM_ENTRY1)+sizeof(SAM_STR1));
870 q_u->max_entries = (q_u->max_entries>0?q_u->max_entries:1);
873 DEBUG(10,("samr_reply_query_dispinfo: Setting q_u->max_entries to %u\n",q_u->max_entries));
875 become_root();
876 got_pwds = get_passwd_entries(pass, q_u->start_idx, &total_entries, &num_entries, q_u->max_entries, 0);
877 unbecome_root();
879 /* more left - set resume handle */
880 if(total_entries > num_entries)
882 r_e.status = 0x105;
885 switch (q_u->switch_level)
887 case 0x1:
890 /* query disp info is for users */
891 ZERO_STRUCT (info1);
892 switch_level = 0x1;
893 init_sam_info_1(&info1, ACB_NORMAL,
894 q_u->start_idx, num_entries, pass);
896 ctr.sam.info1 = &info1;
898 break;
900 case 0x2:
902 /* query disp info is for servers */
903 ZERO_STRUCT (info2);
904 switch_level = 0x2;
905 init_sam_info_2(&info2, ACB_WSTRUST,
906 q_u->start_idx, num_entries, pass);
908 ctr.sam.info2 = &info2;
910 break;
915 /* more left - set resume handle */
916 if(total_entries > num_entries)
918 r_e.status = 0x105;
921 if (r_e.status == 0 || r_e.status == 0x105)
923 init_samr_r_query_dispinfo(&r_e, switch_level, &ctr, r_e.status);
926 /* store the response in the SMB stream */
927 if(!samr_io_r_query_dispinfo("", &r_e, rdata, 0))
928 return False;
930 DEBUG(5,("samr_query_dispinfo: %d\n", __LINE__));
932 return True;
935 /*******************************************************************
936 api_samr_query_dispinfo
937 ********************************************************************/
938 static BOOL api_samr_query_dispinfo(pipes_struct *p)
940 SAMR_Q_QUERY_DISPINFO q_e;
941 prs_struct *data = &p->in_data.data;
942 prs_struct *rdata = &p->out_data.rdata;
944 /* grab the samr open */
945 if(!samr_io_q_query_dispinfo("", &q_e, data, 0))
946 return False;
948 /* construct reply. */
949 if(!samr_reply_query_dispinfo(&q_e, rdata))
950 return False;
952 return True;
956 /*******************************************************************
957 samr_reply_query_aliasinfo
958 ********************************************************************/
959 static BOOL samr_reply_query_aliasinfo(SAMR_Q_QUERY_ALIASINFO *q_u,
960 prs_struct *rdata)
962 SAMR_R_QUERY_ALIASINFO r_e;
963 fstring alias_desc = "Local Unix group";
964 fstring alias="";
965 uint8 type;
966 uint32 alias_rid;
968 ZERO_STRUCT(r_e);
970 DEBUG(5,("samr_reply_query_aliasinfo: %d\n", __LINE__));
972 /* find the policy handle. open a policy on it. */
973 if (r_e.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
975 r_e.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
978 alias_rid = get_lsa_policy_samr_rid(&q_u->pol);
979 if(alias_rid == 0xffffffff)
980 r_e.status = 0xC0000000 | NT_STATUS_NO_SUCH_ALIAS;
982 if(!local_lookup_rid(alias_rid, alias, &type))
984 r_e.status = 0xC0000000 | NT_STATUS_NO_SUCH_ALIAS;
987 init_samr_r_query_aliasinfo(&r_e, q_u->switch_level, alias, alias_desc);
989 /* store the response in the SMB stream */
990 if(!samr_io_r_query_aliasinfo("", &r_e, rdata, 0))
991 return False;
993 DEBUG(5,("samr_query_aliasinfo: %d\n", __LINE__));
995 return True;
998 /*******************************************************************
999 api_samr_query_aliasinfo
1000 ********************************************************************/
1001 static BOOL api_samr_query_aliasinfo(pipes_struct *p)
1003 SAMR_Q_QUERY_ALIASINFO q_e;
1004 prs_struct *data = &p->in_data.data;
1005 prs_struct *rdata = &p->out_data.rdata;
1007 /* grab the samr open */
1008 if(!samr_io_q_query_aliasinfo("", &q_e, data, 0))
1009 return False;
1011 /* construct reply. */
1012 if(!samr_reply_query_aliasinfo(&q_e, rdata))
1013 return False;
1015 return True;
1019 /*******************************************************************
1020 samr_reply_lookup_ids
1021 ********************************************************************/
1022 static BOOL samr_reply_lookup_ids(SAMR_Q_LOOKUP_IDS *q_u,
1023 prs_struct *rdata)
1025 uint32 rid[MAX_SAM_ENTRIES];
1026 uint32 status = 0;
1027 int num_rids = q_u->num_sids1;
1029 SAMR_R_LOOKUP_IDS r_u;
1031 DEBUG(5,("samr_lookup_ids: %d\n", __LINE__));
1033 if (num_rids > MAX_SAM_ENTRIES)
1035 num_rids = MAX_SAM_ENTRIES;
1036 DEBUG(5,("samr_lookup_ids: truncating entries to %d\n", num_rids));
1039 #if 0
1040 int i;
1041 SMB_ASSERT_ARRAY(q_u->uni_user_name, num_rids);
1043 for (i = 0; i < num_rids && status == 0; i++)
1045 struct sam_passwd *sam_pass;
1046 fstring user_name;
1049 fstrcpy(user_name, unistrn2(q_u->uni_user_name[i].buffer,
1050 q_u->uni_user_name[i].uni_str_len));
1052 /* find the user account */
1053 become_root();
1054 sam_pass = get_smb21pwd_entry(user_name, 0);
1055 unbecome_root();
1057 if (sam_pass == NULL)
1059 status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
1060 rid[i] = 0;
1062 else
1064 rid[i] = sam_pass->user_rid;
1067 #endif
1069 num_rids = 1;
1070 rid[0] = BUILTIN_ALIAS_RID_USERS;
1072 init_samr_r_lookup_ids(&r_u, num_rids, rid, status);
1074 /* store the response in the SMB stream */
1075 if(!samr_io_r_lookup_ids("", &r_u, rdata, 0))
1076 return False;
1078 DEBUG(5,("samr_lookup_ids: %d\n", __LINE__));
1080 return True;
1083 /*******************************************************************
1084 api_samr_lookup_ids
1085 ********************************************************************/
1086 static BOOL api_samr_lookup_ids(pipes_struct *p)
1088 SAMR_Q_LOOKUP_IDS q_u;
1089 prs_struct *data = &p->in_data.data;
1090 prs_struct *rdata = &p->out_data.rdata;
1092 /* grab the samr 0x10 */
1093 if(!samr_io_q_lookup_ids("", &q_u, data, 0))
1094 return False;
1096 /* construct reply. always indicate success */
1097 if(!samr_reply_lookup_ids(&q_u, rdata))
1098 return False;
1100 return True;
1103 /*******************************************************************
1104 samr_reply_lookup_names
1105 ********************************************************************/
1107 static BOOL samr_reply_lookup_names(SAMR_Q_LOOKUP_NAMES *q_u,
1108 prs_struct *rdata)
1110 uint32 rid[MAX_SAM_ENTRIES];
1111 uint8 type[MAX_SAM_ENTRIES];
1112 uint32 status = 0;
1113 int i;
1114 int num_rids = q_u->num_names1;
1115 DOM_SID pol_sid;
1117 SAMR_R_LOOKUP_NAMES r_u;
1119 DEBUG(5,("samr_lookup_names: %d\n", __LINE__));
1121 ZERO_ARRAY(rid);
1122 ZERO_ARRAY(type);
1124 if (!get_lsa_policy_samr_sid(&q_u->pol, &pol_sid)) {
1125 status = 0xC0000000 | NT_STATUS_OBJECT_TYPE_MISMATCH;
1126 init_samr_r_lookup_names(&r_u, 0, rid, type, status);
1127 if(!samr_io_r_lookup_names("", &r_u, rdata, 0)) {
1128 DEBUG(0,("samr_reply_lookup_names: failed to marshall SAMR_R_LOOKUP_NAMES.\n"));
1129 return False;
1131 return True;
1134 if (num_rids > MAX_SAM_ENTRIES) {
1135 num_rids = MAX_SAM_ENTRIES;
1136 DEBUG(5,("samr_lookup_names: truncating entries to %d\n", num_rids));
1139 SMB_ASSERT_ARRAY(q_u->uni_name, num_rids);
1141 for (i = 0; i < num_rids; i++) {
1142 fstring name;
1144 status = 0xC0000000 | NT_STATUS_NONE_MAPPED;
1146 rid [i] = 0xffffffff;
1147 type[i] = SID_NAME_UNKNOWN;
1149 fstrcpy(name, dos_unistrn2(q_u->uni_name[i].buffer,
1150 q_u->uni_name[i].uni_str_len));
1152 if(sid_equal(&pol_sid, &global_sam_sid))
1154 DOM_SID sid;
1155 if(local_lookup_name(global_myname, name,
1156 &sid, &type[i]))
1158 sid_split_rid( &sid, &rid[i]);
1159 status = 0;
1164 init_samr_r_lookup_names(&r_u, num_rids, rid, type, status);
1166 /* store the response in the SMB stream */
1167 if(!samr_io_r_lookup_names("", &r_u, rdata, 0)) {
1168 DEBUG(0,("samr_reply_lookup_names: failed to marshall SAMR_R_LOOKUP_NAMES.\n"));
1169 return False;
1172 DEBUG(5,("samr_lookup_names: %d\n", __LINE__));
1174 return True;
1177 /*******************************************************************
1178 api_samr_lookup_names
1179 ********************************************************************/
1181 static BOOL api_samr_lookup_names(pipes_struct *p)
1183 SAMR_Q_LOOKUP_NAMES q_u;
1184 prs_struct *data = &p->in_data.data;
1185 prs_struct *rdata = &p->out_data.rdata;
1187 memset(&q_u, '\0', sizeof(q_u));
1189 /* grab the samr lookup names */
1190 if(!samr_io_q_lookup_names("", &q_u, data, 0)) {
1191 DEBUG(0,("api_samr_lookup_names: failed to unmarshall SAMR_Q_LOOKUP_NAMES.\n"));
1192 return False;
1195 /* construct reply. always indicate success */
1196 if(!samr_reply_lookup_names(&q_u, rdata))
1197 return False;
1199 return True;
1202 /*******************************************************************
1203 samr_reply_chgpasswd_user
1204 ********************************************************************/
1206 static BOOL samr_reply_chgpasswd_user(SAMR_Q_CHGPASSWD_USER *q_u,
1207 prs_struct *rdata)
1209 SAMR_R_CHGPASSWD_USER r_u;
1210 uint32 status = 0x0;
1211 fstring user_name;
1212 fstring wks;
1214 fstrcpy(user_name, dos_unistrn2(q_u->uni_user_name.buffer, q_u->uni_user_name.uni_str_len));
1215 fstrcpy(wks , dos_unistrn2(q_u->uni_dest_host.buffer, q_u->uni_dest_host.uni_str_len));
1217 DEBUG(5,("samr_chgpasswd_user: user: %s wks: %s\n", user_name, wks));
1219 if (!pass_oem_change(user_name,
1220 q_u->lm_newpass.pass, q_u->lm_oldhash.hash,
1221 q_u->nt_newpass.pass, q_u->nt_oldhash.hash))
1223 status = 0xC0000000 | NT_STATUS_WRONG_PASSWORD;
1226 init_samr_r_chgpasswd_user(&r_u, status);
1228 /* store the response in the SMB stream */
1229 if(!samr_io_r_chgpasswd_user("", &r_u, rdata, 0)) {
1230 DEBUG(0,("samr_reply_chgpasswd_user: Failed to marshall SAMR_R_CHGPASSWD_USER struct.\n" ));
1231 return False;
1234 DEBUG(5,("samr_chgpasswd_user: %d\n", __LINE__));
1235 return True;
1238 /*******************************************************************
1239 api_samr_chgpasswd_user
1240 ********************************************************************/
1242 static BOOL api_samr_chgpasswd_user(pipes_struct *p)
1244 SAMR_Q_CHGPASSWD_USER q_u;
1245 prs_struct *data = &p->in_data.data;
1246 prs_struct *rdata = &p->out_data.rdata;
1248 /* unknown 38 command */
1249 if (!samr_io_q_chgpasswd_user("", &q_u, data, 0)) {
1250 DEBUG(0,("api_samr_chgpasswd_user: samr_io_q_chgpasswd_user failed to parse RPC packet.\n"));
1251 return False;
1254 /* construct reply. */
1255 if(!samr_reply_chgpasswd_user(&q_u, rdata)) {
1256 DEBUG(0,("api_samr_chgpasswd_user: samr_reply_chgpasswd_user failed to create reply packet.\n"));
1257 return False;
1260 return True;
1264 /*******************************************************************
1265 samr_reply_unknown_38
1266 ********************************************************************/
1267 static BOOL samr_reply_unknown_38(SAMR_Q_UNKNOWN_38 *q_u, prs_struct *rdata)
1269 SAMR_R_UNKNOWN_38 r_u;
1271 DEBUG(5,("samr_unknown_38: %d\n", __LINE__));
1273 init_samr_r_unknown_38(&r_u);
1275 /* store the response in the SMB stream */
1276 if(!samr_io_r_unknown_38("", &r_u, rdata, 0))
1277 return False;
1279 DEBUG(5,("samr_unknown_38: %d\n", __LINE__));
1280 return True;
1283 /*******************************************************************
1284 api_samr_unknown_38
1285 ********************************************************************/
1286 static BOOL api_samr_unknown_38(pipes_struct *p)
1288 SAMR_Q_UNKNOWN_38 q_u;
1289 prs_struct *data = &p->in_data.data;
1290 prs_struct *rdata = &p->out_data.rdata;
1292 /* unknown 38 command */
1293 if(!samr_io_q_unknown_38("", &q_u, data, 0))
1294 return False;
1296 /* construct reply. always indicate success */
1297 if(!samr_reply_unknown_38(&q_u, rdata))
1298 return False;
1300 return True;
1304 /*******************************************************************
1305 samr_reply_unknown_12
1306 ********************************************************************/
1307 static BOOL samr_reply_unknown_12(SAMR_Q_UNKNOWN_12 *q_u,
1308 prs_struct *rdata)
1310 fstring group_names[MAX_SAM_ENTRIES];
1311 uint32 group_attrs[MAX_SAM_ENTRIES];
1312 uint32 status = 0;
1313 int num_gids = q_u->num_gids1;
1315 SAMR_R_UNKNOWN_12 r_u;
1317 DEBUG(5,("samr_unknown_12: %d\n", __LINE__));
1319 /* find the policy handle. open a policy on it. */
1320 if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
1322 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1325 if (status == 0x0)
1327 int i;
1328 if (num_gids > MAX_SAM_ENTRIES)
1330 num_gids = MAX_SAM_ENTRIES;
1331 DEBUG(5,("samr_unknown_12: truncating entries to %d\n", num_gids));
1334 for (i = 0; i < num_gids && status == 0; i++)
1336 fstrcpy(group_names[i], "dummy group");
1337 group_attrs[i] = 0x2;
1341 init_samr_r_unknown_12(&r_u, num_gids, group_names, group_attrs, status);
1343 /* store the response in the SMB stream */
1344 if(!samr_io_r_unknown_12("", &r_u, rdata, 0))
1345 return False;
1347 DEBUG(5,("samr_unknown_12: %d\n", __LINE__));
1349 return True;
1352 /*******************************************************************
1353 api_samr_unknown_12
1354 ********************************************************************/
1355 static BOOL api_samr_unknown_12(pipes_struct *p)
1357 SAMR_Q_UNKNOWN_12 q_u;
1358 prs_struct *data = &p->in_data.data;
1359 prs_struct *rdata = &p->out_data.rdata;
1361 /* grab the samr lookup names */
1362 if(!samr_io_q_unknown_12("", &q_u, data, 0))
1363 return False;
1365 /* construct reply. always indicate success */
1366 if(!samr_reply_unknown_12(&q_u, rdata))
1367 return False;
1369 return True;
1373 /*******************************************************************
1374 samr_reply_open_user
1375 ********************************************************************/
1376 static BOOL samr_reply_open_user(SAMR_Q_OPEN_USER *q_u, prs_struct *rdata, int status)
1378 SAMR_R_OPEN_USER r_u;
1379 struct sam_passwd *sam_pass;
1380 BOOL pol_open = False;
1382 /* set up the SAMR open_user response */
1383 memset((char *)r_u.user_pol.data, '\0', POL_HND_SIZE);
1385 r_u.status = 0x0;
1387 /* find the policy handle. open a policy on it. */
1388 if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1))
1390 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1393 /* get a (unique) handle. open a policy on it. */
1394 if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.user_pol))))
1396 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1399 become_root();
1400 sam_pass = getsam21pwrid(q_u->user_rid);
1401 unbecome_root();
1403 /* check that the RID exists in our domain. */
1404 if (r_u.status == 0x0 && sam_pass == NULL)
1406 r_u.status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
1409 /* associate the RID with the (unique) handle. */
1410 if (r_u.status == 0x0 && !set_lsa_policy_samr_rid(&(r_u.user_pol), q_u->user_rid))
1412 /* oh, whoops. don't know what error message to return, here */
1413 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1416 if (r_u.status != 0 && pol_open)
1418 close_lsa_policy_hnd(&(r_u.user_pol));
1421 DEBUG(5,("samr_open_user: %d\n", __LINE__));
1423 /* store the response in the SMB stream */
1424 if(!samr_io_r_open_user("", &r_u, rdata, 0))
1425 return False;
1427 DEBUG(5,("samr_open_user: %d\n", __LINE__));
1429 return True;
1432 /*******************************************************************
1433 api_samr_open_user
1434 ********************************************************************/
1435 static BOOL api_samr_open_user(pipes_struct *p)
1437 SAMR_Q_OPEN_USER q_u;
1438 prs_struct *data = &p->in_data.data;
1439 prs_struct *rdata = &p->out_data.rdata;
1441 /* grab the samr unknown 22 */
1442 if(!samr_io_q_open_user("", &q_u, data, 0))
1443 return False;
1445 /* construct reply. always indicate success */
1446 if(!samr_reply_open_user(&q_u, rdata, 0x0))
1447 return False;
1449 return True;
1453 /*************************************************************************
1454 get_user_info_10
1455 *************************************************************************/
1456 static BOOL get_user_info_10(SAM_USER_INFO_10 *id10, uint32 user_rid)
1458 struct smb_passwd *smb_pass;
1460 if (!pdb_rid_is_user(user_rid))
1462 DEBUG(4,("RID 0x%x is not a user RID\n", user_rid));
1463 return False;
1466 become_root();
1467 smb_pass = getsmbpwrid(user_rid);
1468 unbecome_root();
1470 if (smb_pass == NULL)
1472 DEBUG(4,("User 0x%x not found\n", user_rid));
1473 return False;
1476 DEBUG(3,("User:[%s]\n", smb_pass->smb_name));
1478 init_sam_user_info10(id10, smb_pass->acct_ctrl);
1480 return True;
1483 /*************************************************************************
1484 get_user_info_21
1485 *************************************************************************/
1486 static BOOL get_user_info_21(SAM_USER_INFO_21 *id21, uint32 user_rid)
1488 NTTIME dummy_time;
1489 struct sam_passwd *sam_pass;
1490 LOGON_HRS hrs;
1491 int i;
1493 if (!pdb_rid_is_user(user_rid))
1495 DEBUG(4,("RID 0x%x is not a user RID\n", user_rid));
1496 return False;
1499 become_root();
1500 sam_pass = getsam21pwrid(user_rid);
1501 unbecome_root();
1503 if (sam_pass == NULL)
1505 DEBUG(4,("User 0x%x not found\n", user_rid));
1506 return False;
1509 DEBUG(3,("User:[%s]\n", sam_pass->smb_name));
1511 dummy_time.low = 0xffffffff;
1512 dummy_time.high = 0x7fffffff;
1514 DEBUG(5,("get_user_info_21 - TODO: convert unix times to NTTIMEs\n"));
1516 /* create a LOGON_HRS structure */
1517 hrs.len = sam_pass->hours_len;
1518 SMB_ASSERT_ARRAY(hrs.hours, hrs.len);
1519 for (i = 0; i < hrs.len; i++)
1521 hrs.hours[i] = sam_pass->hours[i];
1524 init_sam_user_info21(id21,
1526 &dummy_time, /* logon_time */
1527 &dummy_time, /* logoff_time */
1528 &dummy_time, /* kickoff_time */
1529 &dummy_time, /* pass_last_set_time */
1530 &dummy_time, /* pass_can_change_time */
1531 &dummy_time, /* pass_must_change_time */
1533 sam_pass->smb_name, /* user_name */
1534 sam_pass->full_name, /* full_name */
1535 sam_pass->home_dir, /* home_dir */
1536 sam_pass->dir_drive, /* dir_drive */
1537 sam_pass->logon_script, /* logon_script */
1538 sam_pass->profile_path, /* profile_path */
1539 sam_pass->acct_desc, /* description */
1540 sam_pass->workstations, /* workstations user can log in from */
1541 sam_pass->unknown_str, /* don't know, yet */
1542 sam_pass->munged_dial, /* dialin info. contains dialin path and tel no */
1544 sam_pass->user_rid, /* RID user_id */
1545 sam_pass->group_rid, /* RID group_id */
1546 sam_pass->acct_ctrl,
1548 sam_pass->unknown_3, /* unknown_3 */
1549 sam_pass->logon_divs, /* divisions per week */
1550 &hrs, /* logon hours */
1551 sam_pass->unknown_5,
1552 sam_pass->unknown_6);
1554 return True;
1557 /*******************************************************************
1558 samr_reply_query_userinfo
1559 ********************************************************************/
1560 static BOOL samr_reply_query_userinfo(SAMR_Q_QUERY_USERINFO *q_u,
1561 prs_struct *rdata)
1563 SAMR_R_QUERY_USERINFO r_u;
1564 #if 0
1565 SAM_USER_INFO_11 id11;
1566 #endif
1567 SAM_USER_INFO_10 id10;
1568 SAM_USER_INFO_21 id21;
1569 void *info = NULL;
1571 uint32 status = 0x0;
1572 uint32 rid = 0x0;
1574 DEBUG(5,("samr_reply_query_userinfo: %d\n", __LINE__));
1576 /* search for the handle */
1577 if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
1579 status = NT_STATUS_INVALID_HANDLE;
1582 /* find the user's rid */
1583 if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff)
1585 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
1588 DEBUG(5,("samr_reply_query_userinfo: rid:0x%x\n", rid));
1590 /* ok! user info levels (there are lots: see MSDEV help), off we go... */
1591 if (status == 0x0)
1593 switch (q_u->switch_value)
1595 case 0x10:
1597 info = (void*)&id10;
1598 status = get_user_info_10(&id10, rid) ? 0 : NT_STATUS_NO_SUCH_USER;
1599 break;
1601 #if 0
1602 /* whoops - got this wrong. i think. or don't understand what's happening. */
1603 case 0x11:
1605 NTTIME expire;
1606 info = (void*)&id11;
1608 expire.low = 0xffffffff;
1609 expire.high = 0x7fffffff;
1611 make_sam_user_info11(&id11, &expire, "BROOKFIELDS$", 0x03ef, 0x201, 0x0080);
1613 break;
1615 #endif
1616 case 21:
1618 info = (void*)&id21;
1619 status = get_user_info_21(&id21, rid) ? 0 : NT_STATUS_NO_SUCH_USER;
1620 break;
1623 default:
1625 status = NT_STATUS_INVALID_INFO_CLASS;
1627 break;
1632 init_samr_r_query_userinfo(&r_u, q_u->switch_value, info, status);
1634 /* store the response in the SMB stream */
1635 if(!samr_io_r_query_userinfo("", &r_u, rdata, 0))
1636 return False;
1638 DEBUG(5,("samr_reply_query_userinfo: %d\n", __LINE__));
1640 return True;
1643 /*******************************************************************
1644 api_samr_query_userinfo
1645 ********************************************************************/
1646 static BOOL api_samr_query_userinfo(pipes_struct *p)
1648 SAMR_Q_QUERY_USERINFO q_u;
1649 prs_struct *data = &p->in_data.data;
1650 prs_struct *rdata = &p->out_data.rdata;
1652 /* grab the samr unknown 24 */
1653 if(!samr_io_q_query_userinfo("", &q_u, data, 0))
1654 return False;
1656 /* construct reply. always indicate success */
1657 if(!samr_reply_query_userinfo(&q_u, rdata))
1658 return False;
1660 return True;
1664 /*******************************************************************
1665 samr_reply_query_usergroups
1666 ********************************************************************/
1667 static BOOL samr_reply_query_usergroups(SAMR_Q_QUERY_USERGROUPS *q_u,
1668 prs_struct *rdata)
1670 SAMR_R_QUERY_USERGROUPS r_u;
1671 uint32 status = 0x0;
1673 struct sam_passwd *sam_pass;
1674 DOM_GID *gids = NULL;
1675 int num_groups = 0;
1676 uint32 rid;
1678 DEBUG(5,("samr_query_usergroups: %d\n", __LINE__));
1680 /* find the policy handle. open a policy on it. */
1681 if (status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->pol)) == -1))
1683 status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1686 /* find the user's rid */
1687 if (status == 0x0 && (rid = get_lsa_policy_samr_rid(&(q_u->pol))) == 0xffffffff)
1689 status = NT_STATUS_OBJECT_TYPE_MISMATCH;
1692 if (status == 0x0)
1694 become_root();
1695 sam_pass = getsam21pwrid(rid);
1696 unbecome_root();
1698 if (sam_pass == NULL)
1700 status = 0xC0000000 | NT_STATUS_NO_SUCH_USER;
1704 if (status == 0x0)
1706 pstring groups;
1707 get_domain_user_groups(groups, sam_pass->smb_name);
1708 gids = NULL;
1709 num_groups = make_dom_gids(groups, &gids);
1712 /* construct the response. lkclXXXX: gids are not copied! */
1713 init_samr_r_query_usergroups(&r_u, num_groups, gids, status);
1715 /* store the response in the SMB stream */
1716 if(!samr_io_r_query_usergroups("", &r_u, rdata, 0)) {
1717 if (gids)
1718 free((char *)gids);
1719 return False;
1722 if (gids)
1723 free((char *)gids);
1725 DEBUG(5,("samr_query_usergroups: %d\n", __LINE__));
1727 return True;
1730 /*******************************************************************
1731 api_samr_query_usergroups
1732 ********************************************************************/
1733 static BOOL api_samr_query_usergroups(pipes_struct *p)
1735 SAMR_Q_QUERY_USERGROUPS q_u;
1736 prs_struct *data = &p->in_data.data;
1737 prs_struct *rdata = &p->out_data.rdata;
1739 /* grab the samr unknown 32 */
1740 if(!samr_io_q_query_usergroups("", &q_u, data, 0))
1741 return False;
1743 /* construct reply. */
1744 if(!samr_reply_query_usergroups(&q_u, rdata))
1745 return False;
1747 return True;
1751 /*******************************************************************
1752 samr_reply_query_dom_info
1753 ********************************************************************/
1754 static BOOL samr_reply_query_dom_info(SAMR_Q_QUERY_DOMAIN_INFO *q_u, prs_struct *rdata)
1756 SAMR_R_QUERY_DOMAIN_INFO r_u;
1757 SAM_UNK_CTR ctr;
1758 uint16 switch_value = 0x0;
1759 uint32 status = 0x0;
1761 ZERO_STRUCT(r_u);
1762 ZERO_STRUCT(ctr);
1764 r_u.ctr = &ctr;
1766 DEBUG(5,("samr_reply_query_dom_info: %d\n", __LINE__));
1768 /* find the policy handle. open a policy on it. */
1769 if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->domain_pol)) == -1))
1771 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
1772 DEBUG(5,("samr_reply_query_dom_info: invalid handle\n"));
1775 if (status == 0x0)
1777 switch (q_u->switch_value)
1779 case 0x02:
1781 switch_value = 0x2;
1782 init_unk_info2(&ctr.info.inf2, global_myworkgroup, global_myname);
1784 break;
1786 default:
1788 status = 0xC0000000 | NT_STATUS_INVALID_INFO_CLASS;
1789 break;
1794 init_samr_r_query_dom_info(&r_u, switch_value, &ctr, status);
1796 /* store the response in the SMB stream */
1797 if(!samr_io_r_query_dom_info("", &r_u, rdata, 0))
1798 return False;
1800 DEBUG(5,("samr_query_dom_info: %d\n", __LINE__));
1802 return True;
1805 /*******************************************************************
1806 api_samr_query_dom_info
1807 ********************************************************************/
1808 static BOOL api_samr_query_dom_info(pipes_struct *p)
1810 SAMR_Q_QUERY_DOMAIN_INFO q_e;
1811 prs_struct *data = &p->in_data.data;
1812 prs_struct *rdata = &p->out_data.rdata;
1814 /* grab the samr unknown 8 command */
1815 if(!samr_io_q_query_dom_info("", &q_e, data, 0))
1816 return False;
1818 /* construct reply. */
1819 if(!samr_reply_query_dom_info(&q_e, rdata))
1820 return False;
1822 return True;
1825 /*******************************************************************
1826 samr_reply_unknown_32
1827 ********************************************************************/
1828 static BOOL samr_reply_unknown_32(SAMR_Q_UNKNOWN_32 *q_u,
1829 prs_struct *rdata,
1830 int status)
1832 int i;
1833 SAMR_R_UNKNOWN_32 r_u;
1835 /* set up the SAMR unknown_32 response */
1836 memset((char *)r_u.pol.data, '\0', POL_HND_SIZE);
1837 if (status == 0)
1839 for (i = 4; i < POL_HND_SIZE; i++)
1841 r_u.pol.data[i] = i+1;
1845 init_dom_rid4(&(r_u.rid4), 0x0030, 0, 0);
1846 r_u.status = status;
1848 DEBUG(5,("samr_unknown_32: %d\n", __LINE__));
1850 /* store the response in the SMB stream */
1851 if(!samr_io_r_unknown_32("", &r_u, rdata, 0))
1852 return False;
1854 DEBUG(5,("samr_unknown_32: %d\n", __LINE__));
1856 return True;
1859 /*******************************************************************
1860 api_samr_unknown_32
1861 ********************************************************************/
1862 static BOOL api_samr_unknown_32(pipes_struct *p)
1864 uint32 status = 0;
1865 struct sam_passwd *sam_pass;
1866 fstring mach_acct;
1867 prs_struct *data = &p->in_data.data;
1868 prs_struct *rdata = &p->out_data.rdata;
1870 SAMR_Q_UNKNOWN_32 q_u;
1872 /* grab the samr unknown 32 */
1873 samr_io_q_unknown_32("", &q_u, data, 0);
1875 /* find the machine account: tell the caller if it exists.
1876 lkclXXXX i have *no* idea if this is a problem or not
1877 or even if you are supposed to construct a different
1878 reply if the account already exists...
1881 fstrcpy(mach_acct, dos_unistrn2(q_u.uni_mach_acct.buffer,
1882 q_u.uni_mach_acct.uni_str_len));
1884 become_root();
1885 sam_pass = getsam21pwnam(mach_acct);
1886 unbecome_root();
1888 if (sam_pass != NULL)
1890 /* machine account exists: say so */
1891 status = 0xC0000000 | NT_STATUS_USER_EXISTS;
1893 else
1895 /* this could cause trouble... */
1896 DEBUG(0,("trouble!\n"));
1897 status = 0;
1900 /* construct reply. */
1901 if(!samr_reply_unknown_32(&q_u, rdata, status))
1902 return False;
1904 return True;
1908 /*******************************************************************
1909 samr_reply_connect_anon
1910 ********************************************************************/
1911 static BOOL samr_reply_connect_anon(SAMR_Q_CONNECT_ANON *q_u, prs_struct *rdata)
1913 SAMR_R_CONNECT_ANON r_u;
1914 BOOL pol_open = False;
1916 /* set up the SAMR connect_anon response */
1918 r_u.status = 0x0;
1919 /* get a (unique) handle. open a policy on it. */
1920 if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.connect_pol))))
1922 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1925 /* associate the domain SID with the (unique) handle. */
1926 if (r_u.status == 0x0 && !set_lsa_policy_samr_pol_status(&(r_u.connect_pol), q_u->unknown_0))
1928 /* oh, whoops. don't know what error message to return, here */
1929 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1932 if (r_u.status != 0 && pol_open)
1934 close_lsa_policy_hnd(&(r_u.connect_pol));
1937 DEBUG(5,("samr_connect_anon: %d\n", __LINE__));
1939 /* store the response in the SMB stream */
1940 if(!samr_io_r_connect_anon("", &r_u, rdata, 0))
1941 return False;
1943 DEBUG(5,("samr_connect_anon: %d\n", __LINE__));
1945 return True;
1948 /*******************************************************************
1949 api_samr_connect_anon
1950 ********************************************************************/
1951 static BOOL api_samr_connect_anon(pipes_struct *p)
1953 SAMR_Q_CONNECT_ANON q_u;
1954 prs_struct *data = &p->in_data.data;
1955 prs_struct *rdata = &p->out_data.rdata;
1957 /* grab the samr open policy */
1958 if(!samr_io_q_connect_anon("", &q_u, data, 0))
1959 return False;
1961 /* construct reply. always indicate success */
1962 if(!samr_reply_connect_anon(&q_u, rdata))
1963 return False;
1965 return True;
1968 /*******************************************************************
1969 samr_reply_connect
1970 ********************************************************************/
1971 static BOOL samr_reply_connect(SAMR_Q_CONNECT *q_u, prs_struct *rdata)
1973 SAMR_R_CONNECT r_u;
1974 BOOL pol_open = False;
1976 /* set up the SAMR connect response */
1978 r_u.status = 0x0;
1979 /* get a (unique) handle. open a policy on it. */
1980 if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.connect_pol))))
1982 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1985 /* associate the domain SID with the (unique) handle. */
1986 if (r_u.status == 0x0 && !set_lsa_policy_samr_pol_status(&(r_u.connect_pol), q_u->unknown_0))
1988 /* oh, whoops. don't know what error message to return, here */
1989 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
1992 if (r_u.status != 0 && pol_open)
1994 close_lsa_policy_hnd(&(r_u.connect_pol));
1997 DEBUG(5,("samr_connect: %d\n", __LINE__));
1999 /* store the response in the SMB stream */
2000 if(!samr_io_r_connect("", &r_u, rdata, 0))
2001 return False;
2003 DEBUG(5,("samr_connect: %d\n", __LINE__));
2005 return True;
2008 /*******************************************************************
2009 api_samr_connect
2010 ********************************************************************/
2011 static BOOL api_samr_connect(pipes_struct *p)
2013 SAMR_Q_CONNECT q_u;
2014 prs_struct *data = &p->in_data.data;
2015 prs_struct *rdata = &p->out_data.rdata;
2017 /* grab the samr open policy */
2018 if(!samr_io_q_connect("", &q_u, data, 0))
2019 return False;
2021 /* construct reply. always indicate success */
2022 if(!samr_reply_connect(&q_u, rdata))
2023 return False;
2025 return True;
2028 /**********************************************************************
2029 api_reply_lookup_domain
2030 **********************************************************************/
2031 static BOOL samr_reply_lookup_domain(SAMR_Q_LOOKUP_DOMAIN* q_u, prs_struct* rdata)
2033 SAMR_R_LOOKUP_DOMAIN r_u;
2035 r_u.status = 0x0;
2036 if (r_u.status == 0x0 && (find_lsa_policy_by_hnd(&(q_u->connect_pol)) == -1))
2038 r_u.status = 0xC0000000 | NT_STATUS_INVALID_HANDLE;
2039 DEBUG(5,("samr_reply_lookup_domain: invalid handle\n"));
2042 /* assume the domain name sent is our global_myname and
2043 send global_sam_sid */
2044 init_samr_r_lookup_domain(&r_u, &global_sam_sid, r_u.status);
2046 if(!samr_io_r_lookup_domain("", &r_u, rdata, 0))
2047 return False;
2049 DEBUG(5,("samr_reply_lookup_domain: %d\n", __LINE__));
2051 return True;
2054 /**********************************************************************
2055 api_samr_lookup_domain
2056 **********************************************************************/
2057 static BOOL api_samr_lookup_domain(pipes_struct *p)
2059 SAMR_Q_LOOKUP_DOMAIN q_u;
2060 prs_struct *data = &p->in_data.data;
2061 prs_struct *rdata = &p->out_data.rdata;
2063 if(!samr_io_q_lookup_domain("", &q_u, data, 0))
2064 return False;
2066 if(!samr_reply_lookup_domain(&q_u, rdata))
2067 return False;
2069 return True;
2072 /**********************************************************************
2073 samr_reply_enum_domains
2074 **********************************************************************/
2075 static BOOL samr_reply_enum_domains(SAMR_Q_ENUM_DOMAINS* q_u, prs_struct* rdata)
2077 SAMR_R_ENUM_DOMAINS r_u;
2078 fstring dom[2];
2080 fstrcpy(dom[0],global_myname);
2081 fstrcpy(dom[1],"Builtin");
2082 r_u.status = 0;
2084 init_samr_r_enum_domains(&r_u, q_u->start_idx, dom, 2);
2085 if(!samr_io_r_enum_domains("", &r_u, rdata, 0)) {
2086 free(r_u.sam);
2087 free(r_u.uni_dom_name);
2088 return False;
2091 free(r_u.sam);
2092 free(r_u.uni_dom_name);
2094 return True;
2097 /**********************************************************************
2098 api_samr_enum_domains
2099 **********************************************************************/
2100 static BOOL api_samr_enum_domains(pipes_struct *p)
2102 SAMR_Q_ENUM_DOMAINS q_u;
2103 prs_struct *data = &p->in_data.data;
2104 prs_struct *rdata = &p->out_data.rdata;
2106 if(!samr_io_q_enum_domains("", &q_u, data, 0))
2107 return False;
2109 if(!samr_reply_enum_domains(&q_u, rdata))
2110 return False;
2112 return True;
2115 /*******************************************************************
2116 samr_reply_open_alias
2117 ********************************************************************/
2118 static BOOL samr_reply_open_alias(SAMR_Q_OPEN_ALIAS *q_u, prs_struct *rdata)
2120 SAMR_R_OPEN_ALIAS r_u;
2121 BOOL pol_open = False;
2123 /* set up the SAMR open_alias response */
2125 r_u.status = 0x0;
2126 /* get a (unique) handle. open a policy on it. */
2127 if (r_u.status == 0x0 && !(pol_open = open_lsa_policy_hnd(&(r_u.pol))))
2129 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2132 /* associate a RID with the (unique) handle. */
2133 if (r_u.status == 0x0 && !set_lsa_policy_samr_rid(&(r_u.pol), q_u->rid_alias))
2135 /* oh, whoops. don't know what error message to return, here */
2136 r_u.status = 0xC0000000 | NT_STATUS_OBJECT_NAME_NOT_FOUND;
2139 if (r_u.status != 0 && pol_open)
2141 close_lsa_policy_hnd(&(r_u.pol));
2144 DEBUG(5,("samr_open_alias: %d\n", __LINE__));
2146 /* store the response in the SMB stream */
2147 if(!samr_io_r_open_alias("", &r_u, rdata, 0))
2148 return False;
2150 DEBUG(5,("samr_open_alias: %d\n", __LINE__));
2152 return True;
2155 /*******************************************************************
2156 api_samr_open_alias
2157 ********************************************************************/
2158 static BOOL api_samr_open_alias(pipes_struct *p)
2160 SAMR_Q_OPEN_ALIAS q_u;
2161 prs_struct *data = &p->in_data.data;
2162 prs_struct *rdata = &p->out_data.rdata;
2164 /* grab the samr open policy */
2165 if(!samr_io_q_open_alias("", &q_u, data, 0))
2166 return False;
2168 /* construct reply. always indicate success */
2169 if(!samr_reply_open_alias(&q_u, rdata))
2170 return False;
2172 return True;
2175 /*******************************************************************
2176 array of \PIPE\samr operations
2177 ********************************************************************/
2178 static struct api_struct api_samr_cmds [] =
2180 { "SAMR_CLOSE_HND" , SAMR_CLOSE_HND , api_samr_close_hnd },
2181 { "SAMR_CONNECT" , SAMR_CONNECT , api_samr_connect },
2182 { "SAMR_CONNECT_ANON" , SAMR_CONNECT_ANON , api_samr_connect_anon },
2183 { "SAMR_ENUM_DOM_USERS" , SAMR_ENUM_DOM_USERS , api_samr_enum_dom_users },
2184 { "SAMR_ENUM_DOM_GROUPS" , SAMR_ENUM_DOM_GROUPS , api_samr_enum_dom_groups },
2185 { "SAMR_ENUM_DOM_ALIASES" , SAMR_ENUM_DOM_ALIASES , api_samr_enum_dom_aliases },
2186 { "SAMR_LOOKUP_IDS" , SAMR_LOOKUP_IDS , api_samr_lookup_ids },
2187 { "SAMR_LOOKUP_NAMES" , SAMR_LOOKUP_NAMES , api_samr_lookup_names },
2188 { "SAMR_OPEN_USER" , SAMR_OPEN_USER , api_samr_open_user },
2189 { "SAMR_QUERY_USERINFO" , SAMR_QUERY_USERINFO , api_samr_query_userinfo },
2190 { "SAMR_QUERY_DOMAIN_INFO", SAMR_QUERY_DOMAIN_INFO, api_samr_query_dom_info },
2191 { "SAMR_QUERY_USERGROUPS" , SAMR_QUERY_USERGROUPS , api_samr_query_usergroups },
2192 { "SAMR_QUERY_DISPINFO" , SAMR_QUERY_DISPINFO , api_samr_query_dispinfo },
2193 { "SAMR_QUERY_ALIASINFO" , SAMR_QUERY_ALIASINFO , api_samr_query_aliasinfo },
2194 { "SAMR_0x32" , 0x32 , api_samr_unknown_32 },
2195 { "SAMR_UNKNOWN_12" , SAMR_UNKNOWN_12 , api_samr_unknown_12 },
2196 { "SAMR_UNKNOWN_38" , SAMR_UNKNOWN_38 , api_samr_unknown_38 },
2197 { "SAMR_CHGPASSWD_USER" , SAMR_CHGPASSWD_USER , api_samr_chgpasswd_user },
2198 { "SAMR_OPEN_ALIAS" , SAMR_OPEN_ALIAS , api_samr_open_alias },
2199 { "SAMR_OPEN_DOMAIN" , SAMR_OPEN_DOMAIN , api_samr_open_domain },
2200 { "SAMR_UNKNOWN_3" , SAMR_UNKNOWN_3 , api_samr_unknown_3 },
2201 { "SAMR_UNKNOWN_2C" , SAMR_UNKNOWN_2C , api_samr_unknown_2c },
2202 { "SAMR_LOOKUP_DOMAIN" , SAMR_LOOKUP_DOMAIN , api_samr_lookup_domain },
2203 { "SAMR_ENUM_DOMAINS" , SAMR_ENUM_DOMAINS , api_samr_enum_domains },
2204 { NULL , 0 , NULL }
2207 /*******************************************************************
2208 receives a samr pipe and responds.
2209 ********************************************************************/
2210 BOOL api_samr_rpc(pipes_struct *p)
2212 return api_rpcTNP(p, "api_samr_rpc", api_samr_cmds);
2214 #undef OLD_NTDOMAIN