2 Unix SMB/CIFS implementation.
4 Winbind daemon for ntdom nss module
6 Copyright (C) Tim Potter 2000-2001
7 Copyright (C) 2001 by Martin Pool <mbp@samba.org>
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.
28 * @file winbindd_util.c
30 * Winbind daemon for NT domain authentication nss module.
35 * Used to clobber name fields that have an undefined value.
37 * Correct code should never look at a field that has this value.
40 static const fstring name_deadbeef
= "<deadbeef>";
42 /* The list of trusted domains. Note that the list can be deleted and
43 recreated using the init_domain_list() function so pointers to
44 individual winbindd_domain structures cannot be made. Keep a copy of
45 the domain name instead. */
47 static struct winbindd_domain
*_domain_list
;
49 struct winbindd_domain
*domain_list(void)
59 /* Free all entries in the trusted domain list */
61 void free_domain_list(void)
63 struct winbindd_domain
*domain
= _domain_list
;
66 struct winbindd_domain
*next
= domain
->next
;
68 DLIST_REMOVE(_domain_list
, domain
);
74 /* Add a trusted domain to our list of domains */
76 static struct winbindd_domain
*add_trusted_domain(char *domain_name
,
77 struct winbindd_methods
*methods
)
79 struct winbindd_domain
*domain
;
81 /* We can't call domain_list() as this function is called from
82 init_domain_list() and we'll get stuck in a loop. */
84 for (domain
= _domain_list
; domain
; domain
= domain
->next
) {
85 if (strcmp(domain_name
, domain
->name
) == 0) {
86 DEBUG(3, ("domain %s already in domain list\n",
92 /* Create new domain entry */
94 if ((domain
= (struct winbindd_domain
*)
95 malloc(sizeof(*domain
))) == NULL
)
100 ZERO_STRUCTP(domain
);
102 fstrcpy(domain
->name
, domain_name
);
103 domain
->methods
= methods
;
104 domain
->sequence_number
= DOM_SEQUENCE_NONE
;
105 domain
->last_seq_check
= 0;
107 /* Link to domain list */
109 DLIST_ADD(_domain_list
, domain
);
114 /* Look up global info for the winbind daemon */
116 BOOL
init_domain_list(void)
120 extern struct winbindd_methods cache_methods
;
121 struct winbindd_domain
*domain
;
126 if (!(mem_ctx
= talloc_init_named("init_domain_list")))
129 /* Free existing list */
133 /* Add ourselves as the first entry */
135 domain
= add_trusted_domain(lp_workgroup(), &cache_methods
);
137 /* Now we *must* get the domain sid for our primary domain. Go into
138 a holding pattern until that is available */
140 result
= cache_methods
.domain_sid(domain
, &domain
->sid
);
141 while (!NT_STATUS_IS_OK(result
)) {
143 DEBUG(1,("Retrying startup domain sid fetch for %s\n",
145 result
= cache_methods
.domain_sid(domain
, &domain
->sid
);
148 DEBUG(1,("Added domain %s (%s)\n",
150 sid_string_static(&domain
->sid
)));
152 DEBUG(1, ("getting trusted domain list\n"));
154 result
= cache_methods
.trusted_domains(domain
, mem_ctx
, (uint
*)&num_domains
,
157 /* Add each domain to the trusted domain list */
158 if (NT_STATUS_IS_OK(result
)) {
160 for(i
= 0; i
< num_domains
; i
++) {
161 domain
= add_trusted_domain(names
[i
], &cache_methods
);
162 if (!domain
) continue;
163 sid_copy(&domain
->sid
, &dom_sids
[i
]);
164 DEBUG(1,("Added domain %s (%s)\n",
166 sid_string_static(&domain
->sid
)));
170 talloc_destroy(mem_ctx
);
174 /* Given a domain name, return the struct winbindd domain info for it
175 if it is actually working. */
177 struct winbindd_domain
*find_domain_from_name(const char *domain_name
)
179 struct winbindd_domain
*domain
;
181 /* Search through list */
183 for (domain
= domain_list(); domain
!= NULL
; domain
= domain
->next
) {
184 if (strequal(domain_name
, domain
->name
) ||
185 strequal(domain_name
, domain
->full_name
))
194 /* Given a domain sid, return the struct winbindd domain info for it */
196 struct winbindd_domain
*find_domain_from_sid(DOM_SID
*sid
)
198 struct winbindd_domain
*domain
;
200 /* Search through list */
202 for (domain
= domain_list(); domain
!= NULL
; domain
= domain
->next
) {
203 if (sid_compare_domain(sid
, &domain
->sid
) == 0)
212 /* Lookup a sid in a domain from a name */
214 BOOL
winbindd_lookup_sid_by_name(struct winbindd_domain
*domain
,
215 const char *name
, DOM_SID
*sid
,
216 enum SID_NAME_USE
*type
)
220 /* Don't bother with machine accounts */
222 if (name
[strlen(name
) - 1] == '$')
226 result
= domain
->methods
->name_to_sid(domain
, name
, sid
, type
);
228 /* Return rid and type if lookup successful */
229 if (!NT_STATUS_IS_OK(result
)) {
230 *type
= SID_NAME_UNKNOWN
;
233 return NT_STATUS_IS_OK(result
);
237 * @brief Lookup a name in a domain from a sid.
239 * @param sid Security ID you want to look up.
241 * @param name On success, set to the name corresponding to @p sid.
243 * @param dom_name On success, set to the 'domain name' corresponding to @p sid.
245 * @param type On success, contains the type of name: alias, group or
248 * @retval True if the name exists, in which case @p name and @p type
249 * are set, otherwise False.
251 BOOL
winbindd_lookup_name_by_sid(DOM_SID
*sid
,
254 enum SID_NAME_USE
*type
)
260 struct winbindd_domain
*domain
;
262 domain
= find_domain_from_sid(sid
);
265 DEBUG(1,("Can't find domain from sid\n"));
271 if (!(mem_ctx
= talloc_init_named("winbindd_lookup_name_by_sid")))
274 result
= domain
->methods
->sid_to_name(domain
, mem_ctx
, sid
, &names
, type
);
276 /* Return name and type if successful */
278 if ((rv
= NT_STATUS_IS_OK(result
))) {
279 fstrcpy(dom_name
, domain
->name
);
280 fstrcpy(name
, names
);
282 *type
= SID_NAME_UNKNOWN
;
283 fstrcpy(name
, name_deadbeef
);
286 talloc_destroy(mem_ctx
);
292 /* Free state information held for {set,get,end}{pw,gr}ent() functions */
294 void free_getent_state(struct getent_state
*state
)
296 struct getent_state
*temp
;
298 /* Iterate over state list */
302 while(temp
!= NULL
) {
303 struct getent_state
*next
;
305 /* Free sam entries then list entry */
307 SAFE_FREE(state
->sam_entries
);
308 DLIST_REMOVE(state
, state
);
316 /* Initialise trusted domain info */
318 BOOL
winbindd_param_init(void)
320 /* Parse winbind uid and winbind_gid parameters */
322 if (!lp_winbind_uid(&server_state
.uid_low
, &server_state
.uid_high
)) {
323 DEBUG(0, ("winbind uid range missing or invalid\n"));
327 if (!lp_winbind_gid(&server_state
.gid_low
, &server_state
.gid_high
)) {
328 DEBUG(0, ("winbind gid range missing or invalid\n"));
335 /* Check if a domain is present in a comma-separated list of domains */
337 BOOL
check_domain_env(char *domain_env
, char *domain
)
340 char *tmp
= domain_env
;
342 while(next_token(&tmp
, name
, ",", sizeof(fstring
))) {
343 if (strequal(name
, domain
))
350 /* Parse a string of the form DOMAIN/user into a domain and a user */
351 extern fstring global_myworkgroup
;
353 BOOL
parse_domain_user(const char *domuser
, fstring domain
, fstring user
)
355 char *p
= strchr(domuser
,*lp_winbind_separator());
357 if (!(p
|| lp_winbind_use_default_domain()))
360 if(!p
&& lp_winbind_use_default_domain()) {
361 fstrcpy(user
, domuser
);
362 fstrcpy(domain
, global_myworkgroup
);
365 fstrcpy(domain
, domuser
);
366 domain
[PTR_DIFF(p
, domuser
)] = 0;
373 Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
374 'winbind separator' options.
376 - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is
380 void fill_domain_username(fstring name
, const char *domain
, const char *user
)
382 if(lp_winbind_use_default_domain() &&
383 !strcmp(global_myworkgroup
, domain
)) {
384 strlcpy(name
, user
, sizeof(fstring
));
386 slprintf(name
, sizeof(fstring
) - 1, "%s%s%s",
387 domain
, lp_winbind_separator(),