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 static char *get_trust_type_string(TALLOC_CTX
*mem_ctx
,
31 struct winbindd_tdc_domain
*tdc
,
32 struct winbindd_domain
*domain
)
34 enum netr_SchannelType secure_channel_type
= SEC_CHAN_NULL
;
38 secure_channel_type
= domain
->secure_channel_type
;
41 switch (secure_channel_type
) {
44 DBG_ERR("Missing domain [%s]\n",
48 if (domain
->routing_domain
== NULL
) {
49 DBG_ERR("Missing routing for domain [%s]\n",
53 s
= talloc_asprintf(mem_ctx
, "Routed (via %s)",
54 domain
->routing_domain
->name
);
62 s
= talloc_strdup(mem_ctx
, "Local");
69 s
= talloc_strdup(mem_ctx
, "Workstation");
76 int role
= lp_server_role();
78 if (role
== ROLE_DOMAIN_PDC
) {
79 s
= talloc_strdup(mem_ctx
, "PDC");
86 if (role
== ROLE_DOMAIN_BDC
) {
87 s
= talloc_strdup(mem_ctx
, "BDC");
94 s
= talloc_strdup(mem_ctx
, "RWDC");
102 s
= talloc_strdup(mem_ctx
, "RODC");
108 case SEC_CHAN_DNS_DOMAIN
:
109 if (tdc
->trust_attribs
& LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN
) {
110 s
= talloc_strdup(mem_ctx
, "External");
116 if (tdc
->trust_attribs
& LSA_TRUST_ATTRIBUTE_WITHIN_FOREST
) {
117 s
= talloc_strdup(mem_ctx
, "In Forest");
123 if (tdc
->trust_attribs
& LSA_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL
) {
124 s
= talloc_strdup(mem_ctx
, "External");
130 if (tdc
->trust_attribs
& LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
) {
131 s
= talloc_strdup(mem_ctx
, "Forest");
137 s
= talloc_strdup(mem_ctx
, "External");
143 case SEC_CHAN_DOMAIN
:
144 s
= talloc_strdup(mem_ctx
, "External");
151 DBG_ERR("Unhandled secure_channel_type %d for domain[%s]\n",
152 secure_channel_type
, tdc
->domain_name
);
159 static bool trust_is_inbound(struct winbindd_tdc_domain
*domain
)
161 if (domain
->trust_flags
& NETR_TRUST_FLAG_INBOUND
) {
167 static bool trust_is_outbound(struct winbindd_tdc_domain
*domain
)
169 if (domain
->trust_flags
& NETR_TRUST_FLAG_OUTBOUND
) {
175 static bool trust_is_transitive(struct winbindd_tdc_domain
*domain
)
177 bool transitive
= false;
180 * Beware: order matters
183 if (domain
->trust_attribs
& LSA_TRUST_ATTRIBUTE_WITHIN_FOREST
) {
187 if (domain
->trust_attribs
& LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
) {
191 if (domain
->trust_attribs
& LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE
) {
195 if (domain
->trust_attribs
& LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN
) {
199 if (domain
->trust_flags
& NETR_TRUST_FLAG_PRIMARY
) {
206 void winbindd_list_trusted_domains(struct winbindd_cli_state
*state
)
208 struct winbindd_tdc_domain
*dom_list
= NULL
;
209 size_t num_domains
= 0;
210 int extra_data_len
= 0;
211 char *extra_data
= NULL
;
214 DEBUG(3, ("[%5lu]: list trusted domains\n",
215 (unsigned long)state
->pid
));
217 if( !wcache_tdc_fetch_list( &dom_list
, &num_domains
)) {
218 request_error(state
);
222 extra_data
= talloc_strdup(state
->mem_ctx
, "");
223 if (extra_data
== NULL
) {
224 request_error(state
);
228 for ( i
= 0; i
< num_domains
; i
++ ) {
229 struct winbindd_domain
*domain
;
230 bool is_online
= true;
231 struct winbindd_tdc_domain
*d
= NULL
;
232 char *trust_type
= NULL
;
235 domain
= find_domain_from_name_noinit(d
->domain_name
);
237 is_online
= domain
->online
;
240 trust_type
= get_trust_type_string(talloc_tos(), d
, domain
);
241 if (trust_type
== NULL
) {
245 extra_data
= talloc_asprintf_append_buffer(
247 "%s\\%s\\%s\\%s\\%s\\%s\\%s\\%s\n",
249 d
->dns_name
? d
->dns_name
: "",
250 sid_string_talloc(state
->mem_ctx
, &d
->sid
),
252 trust_is_transitive(d
) ? "Yes" : "No",
253 trust_is_inbound(d
) ? "Yes" : "No",
254 trust_is_outbound(d
) ? "Yes" : "No",
255 is_online
? "Online" : "Offline" );
257 TALLOC_FREE(trust_type
);
260 state
->response
->data
.num_entries
= num_domains
;
262 extra_data_len
= strlen(extra_data
);
263 if (extra_data_len
> 0) {
265 /* Strip the last \n */
266 extra_data
[extra_data_len
-1] = '\0';
268 state
->response
->extra_data
.data
= extra_data
;
269 state
->response
->length
+= extra_data_len
;
274 TALLOC_FREE( dom_list
);
277 enum winbindd_result
winbindd_dual_list_trusted_domains(struct winbindd_domain
*domain
,
278 struct winbindd_cli_state
*state
)
281 int extra_data_len
= 0;
284 bool have_own_domain
= False
;
285 struct netr_DomainTrustList trusts
;
287 DEBUG(3, ("[%5lu]: list trusted domains\n",
288 (unsigned long)state
->pid
));
290 result
= wb_cache_trusted_domains(domain
, state
->mem_ctx
, &trusts
);
292 if (!NT_STATUS_IS_OK(result
)) {
293 DEBUG(3, ("winbindd_dual_list_trusted_domains: trusted_domains returned %s\n",
294 nt_errstr(result
) ));
295 return WINBINDD_ERROR
;
298 extra_data
= talloc_strdup(state
->mem_ctx
, "");
300 for (i
=0; i
<trusts
.count
; i
++) {
302 if (trusts
.array
[i
].sid
== NULL
) {
305 if (dom_sid_equal(trusts
.array
[i
].sid
, &global_sid_NULL
)) {
309 extra_data
= talloc_asprintf_append_buffer(
310 extra_data
, "%s\\%s\\%s\\%u\\%u\\%u\n",
311 trusts
.array
[i
].netbios_name
, trusts
.array
[i
].dns_name
,
312 sid_string_talloc(state
->mem_ctx
, trusts
.array
[i
].sid
),
313 trusts
.array
[i
].trust_flags
,
314 (uint32_t)trusts
.array
[i
].trust_type
,
315 trusts
.array
[i
].trust_attributes
);
318 /* add our primary domain */
320 for (i
=0; i
<trusts
.count
; i
++) {
321 if (strequal(trusts
.array
[i
].netbios_name
, domain
->name
)) {
322 have_own_domain
= True
;
327 if (state
->request
->data
.list_all_domains
&& !have_own_domain
) {
328 extra_data
= talloc_asprintf_append_buffer(
329 extra_data
, "%s\\%s\\%s\n", domain
->name
,
330 domain
->alt_name
!= NULL
?
333 sid_string_talloc(state
->mem_ctx
, &domain
->sid
));
336 extra_data_len
= strlen(extra_data
);
337 if (extra_data_len
> 0) {
339 /* Strip the last \n */
340 extra_data
[extra_data_len
-1] = '\0';
342 state
->response
->extra_data
.data
= extra_data
;
343 state
->response
->length
+= extra_data_len
;
349 struct domain_info_state
{
350 struct winbindd_domain
*domain
;
351 struct winbindd_cli_state
*cli
;
352 struct winbindd_request ping_request
;
355 static void domain_info_done(struct tevent_req
*req
);
357 void winbindd_domain_info(struct winbindd_cli_state
*cli
)
359 struct domain_info_state
*state
;
360 struct winbindd_domain
*domain
;
361 struct tevent_req
*req
;
363 DEBUG(3, ("[%5lu]: domain_info [%s]\n", (unsigned long)cli
->pid
,
364 cli
->request
->domain_name
));
366 domain
= find_domain_from_name_noinit(cli
->request
->domain_name
);
368 if (domain
== NULL
) {
369 DEBUG(3, ("Did not find domain [%s]\n",
370 cli
->request
->domain_name
));
375 if (domain
->initialized
) {
376 fstrcpy(cli
->response
->data
.domain_info
.name
,
378 fstrcpy(cli
->response
->data
.domain_info
.alt_name
,
380 sid_to_fstring(cli
->response
->data
.domain_info
.sid
,
382 cli
->response
->data
.domain_info
.native_mode
=
384 cli
->response
->data
.domain_info
.active_directory
=
385 domain
->active_directory
;
386 cli
->response
->data
.domain_info
.primary
=
392 state
= talloc_zero(cli
->mem_ctx
, struct domain_info_state
);
394 DEBUG(0, ("talloc failed\n"));
400 state
->domain
= domain
;
401 state
->ping_request
.cmd
= WINBINDD_PING
;
404 * Send a ping down. This implicitly initializes the domain.
407 req
= wb_domain_request_send(state
, server_event_context(),
408 domain
, &state
->ping_request
);
410 DEBUG(3, ("wb_domain_request_send failed\n"));
414 tevent_req_set_callback(req
, domain_info_done
, state
);
417 static void domain_info_done(struct tevent_req
*req
)
419 struct domain_info_state
*state
= tevent_req_callback_data(
420 req
, struct domain_info_state
);
421 struct winbindd_response
*response
;
424 ret
= wb_domain_request_recv(req
, req
, &response
, &err
);
427 DEBUG(10, ("wb_domain_request failed: %s\n", strerror(errno
)));
428 request_error(state
->cli
);
431 if (!state
->domain
->initialized
) {
432 DEBUG(5, ("wb_domain_request did not initialize domain %s\n",
433 state
->domain
->name
));
434 request_error(state
->cli
);
438 fstrcpy(state
->cli
->response
->data
.domain_info
.name
,
439 state
->domain
->name
);
440 fstrcpy(state
->cli
->response
->data
.domain_info
.alt_name
,
441 state
->domain
->alt_name
);
442 sid_to_fstring(state
->cli
->response
->data
.domain_info
.sid
,
443 &state
->domain
->sid
);
445 state
->cli
->response
->data
.domain_info
.native_mode
=
446 state
->domain
->native_mode
;
447 state
->cli
->response
->data
.domain_info
.active_directory
=
448 state
->domain
->active_directory
;
449 state
->cli
->response
->data
.domain_info
.primary
=
450 state
->domain
->primary
;
452 request_ok(state
->cli
);
455 void winbindd_dc_info(struct winbindd_cli_state
*cli
)
457 struct winbindd_domain
*domain
;
458 char *dc_name
, *dc_ip
;
460 cli
->request
->domain_name
[sizeof(cli
->request
->domain_name
)-1] = '\0';
462 DEBUG(3, ("[%5lu]: domain_info [%s]\n", (unsigned long)cli
->pid
,
463 cli
->request
->domain_name
));
465 if (cli
->request
->domain_name
[0] != '\0') {
466 domain
= find_trust_from_name_noinit(
467 cli
->request
->domain_name
);
468 if (domain
== NULL
) {
469 DEBUG(10, ("Could not find domain %s\n",
470 cli
->request
->domain_name
));
475 domain
= find_our_domain();
478 if (!fetch_current_dc_from_gencache(
479 talloc_tos(), domain
->name
, &dc_name
, &dc_ip
)) {
480 DEBUG(10, ("fetch_current_dc_from_gencache(%s) failed\n",
486 cli
->response
->data
.num_entries
= 1;
487 cli
->response
->extra_data
.data
= talloc_asprintf(
488 cli
->mem_ctx
, "%s\n%s\n", dc_name
, dc_ip
);
490 TALLOC_FREE(dc_name
);
493 if (cli
->response
->extra_data
.data
== NULL
) {
498 /* must add one to length to copy the 0 for string termination */
499 cli
->response
->length
+=
500 strlen((char *)cli
->response
->extra_data
.data
) + 1;
505 /* List various tidbits of information */
507 void winbindd_info(struct winbindd_cli_state
*state
)
510 DEBUG(3, ("[%5lu]: request misc info\n", (unsigned long)state
->pid
));
512 state
->response
->data
.info
.winbind_separator
= *lp_winbind_separator();
513 fstrcpy(state
->response
->data
.info
.samba_version
, samba_version_string());
517 /* Tell the client the current interface version */
519 void winbindd_interface_version(struct winbindd_cli_state
*state
)
521 DEBUG(3, ("[%5lu]: request interface version (version = %d)\n",
522 (unsigned long)state
->pid
, WINBIND_INTERFACE_VERSION
));
524 state
->response
->data
.interface_version
= WINBIND_INTERFACE_VERSION
;
528 /* What domain are we a member of? */
530 void winbindd_domain_name(struct winbindd_cli_state
*state
)
532 DEBUG(3, ("[%5lu]: request domain name\n", (unsigned long)state
->pid
));
534 fstrcpy(state
->response
->data
.domain_name
, lp_workgroup());
538 /* What's my name again? */
540 void winbindd_netbios_name(struct winbindd_cli_state
*state
)
542 DEBUG(3, ("[%5lu]: request netbios name\n",
543 (unsigned long)state
->pid
));
545 fstrcpy(state
->response
->data
.netbios_name
, lp_netbios_name());
549 /* Where can I find the privileged pipe? */
551 void winbindd_priv_pipe_dir(struct winbindd_cli_state
*state
)
554 DEBUG(3, ("[%5lu]: request location of privileged pipe\n",
555 (unsigned long)state
->pid
));
557 priv_dir
= get_winbind_priv_pipe_dir();
558 state
->response
->extra_data
.data
= talloc_move(state
->mem_ctx
,
561 /* must add one to length to copy the 0 for string termination */
562 state
->response
->length
+=
563 strlen((char *)state
->response
->extra_data
.data
) + 1;