2 * Unix SMB/CIFS implementation.
3 * RPC Pipe client / server routines
4 * Copyright (C) Andrew Tridgell 1992-1998
5 * Copyright (C) Luke Kenneth Casson Leighton 1996-1998,
6 * Copyright (C) Paul Ashton 1997-1998,
7 * Copyright (C) Andrew Bartlett 2004.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 /* this module apparently provides an implementation of DCE/RPC over a
25 * named pipe (IPC$ connection using SMBtrans). details of DCE/RPC
26 * documentation are available (in on-line form) from the X-Open group.
28 * this module should provide a level of abstraction between SMB
29 * and DCE/RPC, while minimising the amount of mallocs, unnecessary
30 * data copies, and network traffic.
32 * in this version, which takes a "let's learn what's going on and
33 * get something running" approach, there is additional network
34 * traffic generated, but the code should be easier to understand...
36 * ... if you read the docs. or stare at packets for weeks on end.
43 #define DBGC_CLASS DBGC_RPC_SRV
46 * A list of the rids of well known BUILTIN and Domain users
50 static const rid_name builtin_alias_rids
[] =
52 { BUILTIN_ALIAS_RID_ADMINS
, "Administrators" },
53 { BUILTIN_ALIAS_RID_USERS
, "Users" },
54 { BUILTIN_ALIAS_RID_GUESTS
, "Guests" },
55 { BUILTIN_ALIAS_RID_POWER_USERS
, "Power Users" },
57 { BUILTIN_ALIAS_RID_ACCOUNT_OPS
, "Account Operators" },
58 { BUILTIN_ALIAS_RID_SYSTEM_OPS
, "System Operators" },
59 { BUILTIN_ALIAS_RID_PRINT_OPS
, "Print Operators" },
60 { BUILTIN_ALIAS_RID_BACKUP_OPS
, "Backup Operators" },
61 { BUILTIN_ALIAS_RID_REPLICATOR
, "Replicator" },
65 /* array lookup of well-known Domain RID users. */
66 static const rid_name domain_user_rids
[] =
68 { DOMAIN_USER_RID_ADMIN
, "Administrator" },
69 { DOMAIN_USER_RID_GUEST
, "Guest" },
73 /* array lookup of well-known Domain RID groups. */
74 static const rid_name domain_group_rids
[] =
76 { DOMAIN_GROUP_RID_ADMINS
, "Domain Admins" },
77 { DOMAIN_GROUP_RID_USERS
, "Domain Users" },
78 { DOMAIN_GROUP_RID_GUESTS
, "Domain Guests" },
82 /*******************************************************************
83 gets a domain user's groups
84 ********************************************************************/
85 NTSTATUS
get_alias_user_groups(TALLOC_CTX
*ctx
, DOM_SID
*sid
, int *numgroups
, uint32
**prids
, DOM_SID
*q_sid
)
87 SAM_ACCOUNT
*sam_pass
=NULL
;
95 fstring str_domsid
, str_qsid
;
97 uint32
*rids
=NULL
, *new_rids
=NULL
;
98 gid_t winbind_gid_low
, winbind_gid_high
;
100 BOOL winbind_groups_exist
;
105 winbind_groups_exist
= lp_idmap_gid(&winbind_gid_low
, &winbind_gid_high
);
108 DEBUG(10,("get_alias_user_groups: looking if SID %s is a member of groups in the SID domain %s\n",
109 sid_to_string(str_qsid
, q_sid
), sid_to_string(str_domsid
, sid
)));
111 pdb_init_sam(&sam_pass
);
113 ret
= pdb_getsampwsid(sam_pass
, q_sid
);
116 pdb_free_sam(&sam_pass
);
117 return NT_STATUS_NO_SUCH_USER
;
120 fstrcpy(user_name
, pdb_get_username(sam_pass
));
121 grid
=pdb_get_group_rid(sam_pass
);
122 if (!NT_STATUS_IS_OK(sid_to_gid(pdb_get_group_sid(sam_pass
), &gid
))) {
123 /* this should never happen */
124 DEBUG(2,("get_alias_user_groups: sid_to_gid failed!\n"));
125 pdb_free_sam(&sam_pass
);
126 return NT_STATUS_UNSUCCESSFUL
;
129 ret
= getgroups_user(user_name
, &groups
, &num_groups
);
131 /* this should never happen */
132 DEBUG(2,("get_alias_user_groups: getgroups_user failed\n"));
133 pdb_free_sam(&sam_pass
);
134 return NT_STATUS_UNSUCCESSFUL
;
137 for (i
=0;i
<num_groups
;i
++) {
140 ret
= get_group_from_gid(groups
[i
], &map
);
144 DEBUG(10,("get_alias_user_groups: gid %d. not found\n", (int)groups
[i
]));
148 /* if it's not an alias, continue */
149 if (map
.sid_name_use
!= SID_NAME_ALIAS
) {
150 DEBUG(10,("get_alias_user_groups: not returing %s, not an ALIAS group.\n", map
.nt_name
));
154 sid_copy(&tmp_sid
, &map
.sid
);
155 sid_split_rid(&tmp_sid
, &rid
);
157 /* if the sid is not in the correct domain, continue */
158 if (!sid_equal(&tmp_sid
, sid
)) {
159 DEBUG(10,("get_alias_user_groups: not returing %s, not in the domain SID.\n", map
.nt_name
));
163 /* Don't return winbind groups as they are not local! */
164 if (winbind_groups_exist
&& (groups
[i
] >= winbind_gid_low
) && (groups
[i
] <= winbind_gid_high
)) {
165 DEBUG(10,("get_alias_user_groups: not returing %s, not local.\n", map
.nt_name
));
169 /* Don't return user private groups... */
170 if (Get_Pwnam(map
.nt_name
) != 0) {
171 DEBUG(10,("get_alias_user_groups: not returing %s, clashes with user.\n", map
.nt_name
));
175 new_rids
=(uint32
*)Realloc(rids
, sizeof(uint32
)*(cur_rid
+1));
176 if (new_rids
==NULL
) {
177 DEBUG(10,("get_alias_user_groups: could not realloc memory\n"));
178 pdb_free_sam(&sam_pass
);
180 return NT_STATUS_NO_MEMORY
;
184 sid_peek_rid(&map
.sid
, &(rids
[cur_rid
]));
192 /* now check for the user's gid (the primary group rid) */
193 for (i
=0; i
<cur_rid
&& grid
!=rids
[i
]; i
++)
196 /* the user's gid is already there */
198 DEBUG(10,("get_alias_user_groups: user is already in the list. good.\n"));
202 DEBUG(10,("get_alias_user_groups: looking for gid %d of user %s\n", (int)gid
, user_name
));
204 if(!get_group_from_gid(gid
, &map
)) {
205 DEBUG(0,("get_alias_user_groups: gid of user %s doesn't exist. Check your "
206 "/etc/passwd and /etc/group files\n", user_name
));
210 /* the primary group isn't an alias */
211 if (map
.sid_name_use
!=SID_NAME_ALIAS
) {
212 DEBUG(10,("get_alias_user_groups: not returing %s, not an ALIAS group.\n", map
.nt_name
));
216 sid_copy(&tmp_sid
, &map
.sid
);
217 sid_split_rid(&tmp_sid
, &rid
);
219 /* if the sid is not in the correct domain, continue */
220 if (!sid_equal(&tmp_sid
, sid
)) {
221 DEBUG(10,("get_alias_user_groups: not returing %s, not in the domain SID.\n", map
.nt_name
));
225 /* Don't return winbind groups as they are not local! */
226 if (winbind_groups_exist
&& (gid
>= winbind_gid_low
) && (gid
<= winbind_gid_high
)) {
227 DEBUG(10,("get_alias_user_groups: not returing %s, not local.\n", map
.nt_name
));
231 /* Don't return user private groups... */
232 if (Get_Pwnam(map
.nt_name
) != 0) {
233 DEBUG(10,("get_alias_user_groups: not returing %s, clashes with user.\n", map
.nt_name
));
237 new_rids
=(uint32
*)Realloc(rids
, sizeof(uint32
)*(cur_rid
+1));
238 if (new_rids
==NULL
) {
239 DEBUG(10,("get_alias_user_groups: could not realloc memory\n"));
240 pdb_free_sam(&sam_pass
);
241 return NT_STATUS_NO_MEMORY
;
245 sid_peek_rid(&map
.sid
, &(rids
[cur_rid
]));
251 pdb_free_sam(&sam_pass
);
257 /*******************************************************************
258 gets a domain user's groups
259 ********************************************************************/
260 BOOL
get_domain_user_groups(TALLOC_CTX
*ctx
, int *numgroups
, DOM_GID
**pgids
, SAM_ACCOUNT
*sam_pass
)
263 const char *username
= pdb_get_username(sam_pass
);
271 if (!getgroups_user(username
, &unix_groups
, &n_unix_groups
)) {
275 /* now setup the space for storing the SIDS */
277 if (n_unix_groups
> 0) {
279 *pgids
= talloc(ctx
, sizeof(DOM_GID
) * n_unix_groups
);
282 DEBUG(0, ("get_user_group: malloc() failed for DOM_GID list!\n"));
283 SAFE_FREE(unix_groups
);
290 for (i
= 0; i
< n_unix_groups
; i
++) {
294 if (!pdb_getgrgid(&map
, unix_groups
[i
])) {
295 DEBUG(3, ("get_user_groups: failed to convert gid %ld to a domain group!\n",
296 (long int)unix_groups
[i
+1]));
298 DEBUG(1,("get_domain_user_groups: primary gid of user [%s] is not a Domain group !\n", username
));
299 DEBUGADD(1,("get_domain_user_groups: You should fix it, NT doesn't like that\n"));
301 } else if ((map
.sid_name_use
== SID_NAME_DOM_GRP
)
302 && sid_peek_check_rid(get_global_sam_sid(), &map
.sid
, &rid
)) {
304 (*pgids
)[j
].g_rid
=rid
;
312 SAFE_FREE(unix_groups
);
317 /*******************************************************************
318 gets a domain user's groups from their already-calculated NT_USER_TOKEN
319 ********************************************************************/
320 NTSTATUS
nt_token_to_group_list(TALLOC_CTX
*mem_ctx
, const DOM_SID
*domain_sid
,
321 const NT_USER_TOKEN
*nt_token
,
322 int *numgroups
, DOM_GID
**pgids
)
327 gids
= (DOM_GID
*)talloc(mem_ctx
, sizeof(*gids
) * nt_token
->num_sids
);
330 return NT_STATUS_NO_MEMORY
;
335 for (i
=PRIMARY_GROUP_SID_INDEX
; i
< nt_token
->num_sids
; i
++) {
336 if (sid_compare_domain(domain_sid
, &nt_token
->user_sids
[i
])==0) {
337 sid_peek_rid(&nt_token
->user_sids
[i
], &(gids
[*numgroups
].g_rid
));
338 gids
[*numgroups
].attr
=7;