2 Unix SMB/CIFS implementation.
4 Winbind daemon - miscellaneous other functions
6 Copyright (C) Tim Potter 2000
7 Copyright (C) Andrew Bartlett 2002
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 3 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, see <http://www.gnu.org/licenses/>.
25 #include "libcli/security/dom_sid.h"
28 #define DBGC_CLASS DBGC_WINBIND
30 /* Constants and helper functions for determining domain trust types */
39 const char *trust_type_strings
[] = {"External",
44 static enum trust_type
get_trust_type(struct winbindd_tdc_domain
*domain
)
46 if (domain
->trust_attribs
== LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN
)
48 else if (domain
->trust_attribs
== LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
)
50 else if (((domain
->trust_flags
& NETR_TRUST_FLAG_IN_FOREST
) == NETR_TRUST_FLAG_IN_FOREST
) &&
51 ((domain
->trust_flags
& NETR_TRUST_FLAG_PRIMARY
) == 0x0))
56 static const char *get_trust_type_string(struct winbindd_tdc_domain
*domain
)
58 return trust_type_strings
[get_trust_type(domain
)];
61 static bool trust_is_inbound(struct winbindd_tdc_domain
*domain
)
63 return (domain
->trust_flags
== 0x0) ||
64 ((domain
->trust_flags
& NETR_TRUST_FLAG_IN_FOREST
) ==
65 NETR_TRUST_FLAG_IN_FOREST
) ||
66 ((domain
->trust_flags
& NETR_TRUST_FLAG_INBOUND
) ==
67 NETR_TRUST_FLAG_INBOUND
);
70 static bool trust_is_outbound(struct winbindd_tdc_domain
*domain
)
72 return (domain
->trust_flags
== 0x0) ||
73 ((domain
->trust_flags
& NETR_TRUST_FLAG_IN_FOREST
) ==
74 NETR_TRUST_FLAG_IN_FOREST
) ||
75 ((domain
->trust_flags
& NETR_TRUST_FLAG_OUTBOUND
) ==
76 NETR_TRUST_FLAG_OUTBOUND
);
79 static bool trust_is_transitive(struct winbindd_tdc_domain
*domain
)
81 if ((domain
->trust_attribs
== LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE
) ||
82 (domain
->trust_attribs
== LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN
) ||
83 (domain
->trust_attribs
== LSA_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL
))
88 void winbindd_list_trusted_domains(struct winbindd_cli_state
*state
)
90 struct winbindd_tdc_domain
*dom_list
= NULL
;
91 size_t num_domains
= 0;
92 int extra_data_len
= 0;
93 char *extra_data
= NULL
;
96 DEBUG(3, ("[%5lu]: list trusted domains\n",
97 (unsigned long)state
->pid
));
99 if( !wcache_tdc_fetch_list( &dom_list
, &num_domains
)) {
100 request_error(state
);
104 extra_data
= talloc_strdup(state
->mem_ctx
, "");
105 if (extra_data
== NULL
) {
106 request_error(state
);
110 for ( i
= 0; i
< num_domains
; i
++ ) {
111 struct winbindd_domain
*domain
;
112 bool is_online
= true;
113 struct winbindd_tdc_domain
*d
= NULL
;
116 domain
= find_domain_from_name_noinit(d
->domain_name
);
118 is_online
= domain
->online
;
120 extra_data
= talloc_asprintf_append_buffer(
122 "%s\\%s\\%s\\%s\\%s\\%s\\%s\\%s\n",
124 d
->dns_name
? d
->dns_name
: "",
125 sid_string_talloc(state
->mem_ctx
, &d
->sid
),
126 get_trust_type_string(d
),
127 trust_is_transitive(d
) ? "Yes" : "No",
128 trust_is_inbound(d
) ? "Yes" : "No",
129 trust_is_outbound(d
) ? "Yes" : "No",
130 is_online
? "Online" : "Offline" );
133 state
->response
->data
.num_entries
= num_domains
;
135 extra_data_len
= strlen(extra_data
);
136 if (extra_data_len
> 0) {
138 /* Strip the last \n */
139 extra_data
[extra_data_len
-1] = '\0';
141 state
->response
->extra_data
.data
= extra_data
;
142 state
->response
->length
+= extra_data_len
;
147 TALLOC_FREE( dom_list
);
150 enum winbindd_result
winbindd_dual_list_trusted_domains(struct winbindd_domain
*domain
,
151 struct winbindd_cli_state
*state
)
154 int extra_data_len
= 0;
157 bool have_own_domain
= False
;
158 struct netr_DomainTrustList trusts
;
160 DEBUG(3, ("[%5lu]: list trusted domains\n",
161 (unsigned long)state
->pid
));
163 result
= domain
->methods
->trusted_domains(domain
, state
->mem_ctx
,
166 if (!NT_STATUS_IS_OK(result
)) {
167 DEBUG(3, ("winbindd_dual_list_trusted_domains: trusted_domains returned %s\n",
168 nt_errstr(result
) ));
169 return WINBINDD_ERROR
;
172 extra_data
= talloc_strdup(state
->mem_ctx
, "");
174 for (i
=0; i
<trusts
.count
; i
++) {
176 if (trusts
.array
[i
].sid
== NULL
) {
179 if (dom_sid_equal(trusts
.array
[i
].sid
, &global_sid_NULL
)) {
183 extra_data
= talloc_asprintf_append_buffer(
184 extra_data
, "%s\\%s\\%s\\%u\\%u\\%u\n",
185 trusts
.array
[i
].netbios_name
, trusts
.array
[i
].dns_name
,
186 sid_string_talloc(state
->mem_ctx
, trusts
.array
[i
].sid
),
187 trusts
.array
[i
].trust_flags
,
188 (uint32_t)trusts
.array
[i
].trust_type
,
189 trusts
.array
[i
].trust_attributes
);
192 /* add our primary domain */
194 for (i
=0; i
<trusts
.count
; i
++) {
195 if (strequal(trusts
.array
[i
].netbios_name
, domain
->name
)) {
196 have_own_domain
= True
;
201 if (state
->request
->data
.list_all_domains
&& !have_own_domain
) {
202 extra_data
= talloc_asprintf_append_buffer(
203 extra_data
, "%s\\%s\\%s\n", domain
->name
,
204 domain
->alt_name
!= NULL
?
207 sid_string_talloc(state
->mem_ctx
, &domain
->sid
));
210 extra_data_len
= strlen(extra_data
);
211 if (extra_data_len
> 0) {
213 /* Strip the last \n */
214 extra_data
[extra_data_len
-1] = '\0';
216 state
->response
->extra_data
.data
= extra_data
;
217 state
->response
->length
+= extra_data_len
;
223 struct domain_info_state
{
224 struct winbindd_domain
*domain
;
225 struct winbindd_cli_state
*cli
;
226 struct winbindd_request ping_request
;
229 static void domain_info_done(struct tevent_req
*req
);
231 void winbindd_domain_info(struct winbindd_cli_state
*cli
)
233 struct domain_info_state
*state
;
234 struct winbindd_domain
*domain
;
235 struct tevent_req
*req
;
237 DEBUG(3, ("[%5lu]: domain_info [%s]\n", (unsigned long)cli
->pid
,
238 cli
->request
->domain_name
));
240 domain
= find_domain_from_name_noinit(cli
->request
->domain_name
);
242 if (domain
== NULL
) {
243 DEBUG(3, ("Did not find domain [%s]\n",
244 cli
->request
->domain_name
));
249 if (domain
->initialized
) {
250 fstrcpy(cli
->response
->data
.domain_info
.name
,
252 fstrcpy(cli
->response
->data
.domain_info
.alt_name
,
254 sid_to_fstring(cli
->response
->data
.domain_info
.sid
,
256 cli
->response
->data
.domain_info
.native_mode
=
258 cli
->response
->data
.domain_info
.active_directory
=
259 domain
->active_directory
;
260 cli
->response
->data
.domain_info
.primary
=
266 state
= talloc_zero(cli
->mem_ctx
, struct domain_info_state
);
268 DEBUG(0, ("talloc failed\n"));
274 state
->domain
= domain
;
275 state
->ping_request
.cmd
= WINBINDD_PING
;
278 * Send a ping down. This implicitly initializes the domain.
281 req
= wb_domain_request_send(state
, winbind_event_context(),
282 domain
, &state
->ping_request
);
284 DEBUG(3, ("wb_domain_request_send failed\n"));
288 tevent_req_set_callback(req
, domain_info_done
, state
);
291 static void domain_info_done(struct tevent_req
*req
)
293 struct domain_info_state
*state
= tevent_req_callback_data(
294 req
, struct domain_info_state
);
295 struct winbindd_response
*response
;
298 ret
= wb_domain_request_recv(req
, req
, &response
, &err
);
301 DEBUG(10, ("wb_domain_request failed: %s\n", strerror(errno
)));
302 request_error(state
->cli
);
305 if (!state
->domain
->initialized
) {
306 DEBUG(5, ("wb_domain_request did not initialize domain %s\n",
307 state
->domain
->name
));
308 request_error(state
->cli
);
312 fstrcpy(state
->cli
->response
->data
.domain_info
.name
,
313 state
->domain
->name
);
314 fstrcpy(state
->cli
->response
->data
.domain_info
.alt_name
,
315 state
->domain
->alt_name
);
316 sid_to_fstring(state
->cli
->response
->data
.domain_info
.sid
,
317 &state
->domain
->sid
);
319 state
->cli
->response
->data
.domain_info
.native_mode
=
320 state
->domain
->native_mode
;
321 state
->cli
->response
->data
.domain_info
.active_directory
=
322 state
->domain
->active_directory
;
323 state
->cli
->response
->data
.domain_info
.primary
=
324 state
->domain
->primary
;
326 request_ok(state
->cli
);
329 void winbindd_dc_info(struct winbindd_cli_state
*cli
)
331 struct winbindd_domain
*domain
;
332 char *dc_name
, *dc_ip
;
334 cli
->request
->domain_name
[sizeof(cli
->request
->domain_name
)-1] = '\0';
336 DEBUG(3, ("[%5lu]: domain_info [%s]\n", (unsigned long)cli
->pid
,
337 cli
->request
->domain_name
));
339 if (cli
->request
->domain_name
[0] != '\0') {
340 domain
= find_domain_from_name_noinit(
341 cli
->request
->domain_name
);
342 DEBUG(10, ("Could not find domain %s\n",
343 cli
->request
->domain_name
));
344 if (domain
== NULL
) {
349 domain
= find_our_domain();
352 if (!fetch_current_dc_from_gencache(
353 talloc_tos(), domain
->name
, &dc_name
, &dc_ip
)) {
354 DEBUG(10, ("fetch_current_dc_from_gencache(%s) failed\n",
360 cli
->response
->data
.num_entries
= 1;
361 cli
->response
->extra_data
.data
= talloc_asprintf(
362 cli
->mem_ctx
, "%s\n%s\n", dc_name
, dc_ip
);
364 TALLOC_FREE(dc_name
);
367 if (cli
->response
->extra_data
.data
== NULL
) {
372 /* must add one to length to copy the 0 for string termination */
373 cli
->response
->length
+=
374 strlen((char *)cli
->response
->extra_data
.data
) + 1;
379 /* List various tidbits of information */
381 void winbindd_info(struct winbindd_cli_state
*state
)
384 DEBUG(3, ("[%5lu]: request misc info\n", (unsigned long)state
->pid
));
386 state
->response
->data
.info
.winbind_separator
= *lp_winbind_separator();
387 fstrcpy(state
->response
->data
.info
.samba_version
, samba_version_string());
391 /* Tell the client the current interface version */
393 void winbindd_interface_version(struct winbindd_cli_state
*state
)
395 DEBUG(3, ("[%5lu]: request interface version (version = %d)\n",
396 (unsigned long)state
->pid
, WINBIND_INTERFACE_VERSION
));
398 state
->response
->data
.interface_version
= WINBIND_INTERFACE_VERSION
;
402 /* What domain are we a member of? */
404 void winbindd_domain_name(struct winbindd_cli_state
*state
)
406 DEBUG(3, ("[%5lu]: request domain name\n", (unsigned long)state
->pid
));
408 fstrcpy(state
->response
->data
.domain_name
, lp_workgroup());
412 /* What's my name again? */
414 void winbindd_netbios_name(struct winbindd_cli_state
*state
)
416 DEBUG(3, ("[%5lu]: request netbios name\n",
417 (unsigned long)state
->pid
));
419 fstrcpy(state
->response
->data
.netbios_name
, lp_netbios_name());
423 /* Where can I find the privileged pipe? */
425 void winbindd_priv_pipe_dir(struct winbindd_cli_state
*state
)
428 DEBUG(3, ("[%5lu]: request location of privileged pipe\n",
429 (unsigned long)state
->pid
));
431 priv_dir
= get_winbind_priv_pipe_dir();
432 state
->response
->extra_data
.data
= talloc_move(state
->mem_ctx
,
435 /* must add one to length to copy the 0 for string termination */
436 state
->response
->length
+=
437 strlen((char *)state
->response
->extra_data
.data
) + 1;