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"
26 #include "lib/util/string_wrappers.h"
29 #define DBGC_CLASS DBGC_WINBIND
31 static char *get_trust_type_string(TALLOC_CTX
*mem_ctx
,
32 struct winbindd_tdc_domain
*tdc
,
33 struct winbindd_domain
*domain
)
35 enum netr_SchannelType secure_channel_type
= SEC_CHAN_NULL
;
39 secure_channel_type
= domain
->secure_channel_type
;
42 switch (secure_channel_type
) {
45 DBG_ERR("Missing domain [%s]\n",
49 if (domain
->routing_domain
== NULL
) {
50 DBG_ERR("Missing routing for domain [%s]\n",
54 s
= talloc_asprintf(mem_ctx
, "Routed (via %s)",
55 domain
->routing_domain
->name
);
63 s
= talloc_strdup(mem_ctx
, "Local");
70 s
= talloc_strdup(mem_ctx
, "Workstation");
77 int role
= lp_server_role();
79 if (role
== ROLE_DOMAIN_PDC
|| role
== ROLE_IPA_DC
) {
80 s
= talloc_strdup(mem_ctx
, "PDC");
87 if (role
== ROLE_DOMAIN_BDC
) {
88 s
= talloc_strdup(mem_ctx
, "BDC");
95 s
= talloc_strdup(mem_ctx
, "RWDC");
103 s
= talloc_strdup(mem_ctx
, "RODC");
109 case SEC_CHAN_DNS_DOMAIN
:
110 if (tdc
->trust_attribs
& LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN
) {
111 s
= talloc_strdup(mem_ctx
, "External");
117 if (tdc
->trust_attribs
& LSA_TRUST_ATTRIBUTE_WITHIN_FOREST
) {
118 s
= talloc_strdup(mem_ctx
, "In Forest");
124 if (tdc
->trust_attribs
& LSA_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL
) {
125 s
= talloc_strdup(mem_ctx
, "External");
131 if (tdc
->trust_attribs
& LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
) {
132 s
= talloc_strdup(mem_ctx
, "Forest");
138 s
= talloc_strdup(mem_ctx
, "External");
144 case SEC_CHAN_DOMAIN
:
145 s
= talloc_strdup(mem_ctx
, "External");
152 DBG_ERR("Unhandled secure_channel_type %d for domain[%s]\n",
153 secure_channel_type
, tdc
->domain_name
);
160 static bool trust_is_inbound(struct winbindd_tdc_domain
*domain
)
162 if (domain
->trust_flags
& NETR_TRUST_FLAG_INBOUND
) {
168 static bool trust_is_outbound(struct winbindd_tdc_domain
*domain
)
170 if (domain
->trust_flags
& NETR_TRUST_FLAG_OUTBOUND
) {
176 static bool trust_is_transitive(struct winbindd_tdc_domain
*domain
)
178 bool transitive
= false;
181 * Beware: order matters
184 if (domain
->trust_attribs
& LSA_TRUST_ATTRIBUTE_WITHIN_FOREST
) {
188 if (domain
->trust_attribs
& LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
) {
192 if (domain
->trust_attribs
& LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE
) {
196 if (domain
->trust_attribs
& LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN
) {
200 if (domain
->trust_flags
& NETR_TRUST_FLAG_PRIMARY
) {
207 bool winbindd_list_trusted_domains(struct winbindd_cli_state
*state
)
209 struct winbindd_tdc_domain
*dom_list
= NULL
;
210 size_t num_domains
= 0;
211 int extra_data_len
= 0;
212 char *extra_data
= NULL
;
216 DBG_NOTICE("[%s (%u)]: list trusted domains\n",
218 (unsigned int)state
->pid
);
220 if( !wcache_tdc_fetch_list( &dom_list
, &num_domains
)) {
224 extra_data
= talloc_strdup(state
->mem_ctx
, "");
225 if (extra_data
== NULL
) {
229 for ( i
= 0; i
< num_domains
; i
++ ) {
230 struct winbindd_domain
*domain
;
231 bool is_online
= true;
232 struct winbindd_tdc_domain
*d
= NULL
;
233 char *trust_type
= NULL
;
234 struct dom_sid_buf buf
;
237 domain
= find_domain_from_name_noinit(d
->domain_name
);
239 is_online
= domain
->online
;
242 trust_type
= get_trust_type_string(talloc_tos(), d
, domain
);
243 if (trust_type
== NULL
) {
247 extra_data
= talloc_asprintf_append_buffer(
249 "%s\\%s\\%s\\%s\\%s\\%s\\%s\\%s\n",
251 d
->dns_name
? d
->dns_name
: "",
252 dom_sid_str_buf(&d
->sid
, &buf
),
254 trust_is_transitive(d
) ? "Yes" : "No",
255 trust_is_inbound(d
) ? "Yes" : "No",
256 trust_is_outbound(d
) ? "Yes" : "No",
257 is_online
? "Online" : "Offline" );
259 TALLOC_FREE(trust_type
);
262 state
->response
->data
.num_entries
= num_domains
;
264 extra_data_len
= strlen(extra_data
);
265 if (extra_data_len
> 0) {
267 /* Strip the last \n */
268 extra_data
[extra_data_len
-1] = '\0';
270 state
->response
->extra_data
.data
= extra_data
;
271 state
->response
->length
+= extra_data_len
;
276 TALLOC_FREE( dom_list
);
280 bool winbindd_dc_info(struct winbindd_cli_state
*cli
)
282 struct winbindd_domain
*domain
;
283 char *dc_name
, *dc_ip
;
285 cli
->request
->domain_name
[sizeof(cli
->request
->domain_name
)-1] = '\0';
287 DBG_NOTICE("[%s (%u)]: domain_info [%s]\n",
289 (unsigned int)cli
->pid
,
290 cli
->request
->domain_name
);
292 if (cli
->request
->domain_name
[0] != '\0') {
293 domain
= find_trust_from_name_noinit(
294 cli
->request
->domain_name
);
295 if (domain
== NULL
) {
296 DEBUG(10, ("Could not find domain %s\n",
297 cli
->request
->domain_name
));
301 domain
= find_our_domain();
304 if (!fetch_current_dc_from_gencache(
305 talloc_tos(), domain
->name
, &dc_name
, &dc_ip
)) {
306 DEBUG(10, ("fetch_current_dc_from_gencache(%s) failed\n",
311 cli
->response
->data
.num_entries
= 1;
312 cli
->response
->extra_data
.data
= talloc_asprintf(
313 cli
->mem_ctx
, "%s\n%s\n", dc_name
, dc_ip
);
315 TALLOC_FREE(dc_name
);
318 if (cli
->response
->extra_data
.data
== NULL
) {
322 /* must add one to length to copy the 0 for string termination */
323 cli
->response
->length
+=
324 strlen((char *)cli
->response
->extra_data
.data
) + 1;
329 bool winbindd_ping(struct winbindd_cli_state
*state
)
331 DBG_NOTICE("[%s (%u)]: ping\n",
333 (unsigned int)state
->pid
);
337 /* List various tidbits of information */
339 bool winbindd_info(struct winbindd_cli_state
*state
)
342 DBG_NOTICE("[%s (%u)]: request misc info\n",
344 (unsigned int)state
->pid
);
346 state
->response
->data
.info
.winbind_separator
= *lp_winbind_separator();
347 fstrcpy(state
->response
->data
.info
.samba_version
, samba_version_string());
351 /* Tell the client the current interface version */
353 bool winbindd_interface_version(struct winbindd_cli_state
*state
)
355 DBG_NOTICE("[%s (%u)]: request interface version (version = %d)\n",
357 (unsigned int)state
->pid
,
358 WINBIND_INTERFACE_VERSION
);
360 state
->response
->data
.interface_version
= WINBIND_INTERFACE_VERSION
;
364 /* What domain are we a member of? */
366 bool winbindd_domain_name(struct winbindd_cli_state
*state
)
368 DBG_NOTICE("[%s (%u)]: request domain name\n",
370 (unsigned int)state
->pid
);
372 fstrcpy(state
->response
->data
.domain_name
, lp_workgroup());
376 /* What's my name again? */
378 bool winbindd_netbios_name(struct winbindd_cli_state
*state
)
380 DBG_NOTICE("[%s (%u)]: request netbios name\n",
382 (unsigned int)state
->pid
);
384 fstrcpy(state
->response
->data
.netbios_name
, lp_netbios_name());
388 /* Where can I find the privileged pipe? */
390 char *get_winbind_priv_pipe_dir(void)
392 return state_path(talloc_tos(), WINBINDD_PRIV_SOCKET_SUBDIR
);
395 bool winbindd_priv_pipe_dir(struct winbindd_cli_state
*state
)
399 DBG_NOTICE("[%s (%u)]: request location of privileged pipe\n",
401 (unsigned int)state
->pid
);
403 priv_dir
= get_winbind_priv_pipe_dir();
404 state
->response
->extra_data
.data
= talloc_move(state
->mem_ctx
,
407 /* must add one to length to copy the 0 for string termination */
408 state
->response
->length
+=
409 strlen((char *)state
->response
->extra_data
.data
) + 1;
411 DBG_NOTICE("[%s (%u)]: response location of privileged pipe: %s\n",
413 (unsigned int)state
->pid
,
419 static void winbindd_setup_max_fds(void)
421 int num_fds
= MAX_OPEN_FUDGEFACTOR
;
424 num_fds
+= lp_winbind_max_clients();
425 /* Add some more to account for 2 sockets open
426 when the client transitions from unprivileged
429 num_fds
+= lp_winbind_max_clients() / 10;
431 /* Add one socket per child process
432 (yeah there are child processes other than the
433 domain children but only domain children can vary
436 num_fds
+= lp_winbind_max_domain_connections() *
437 (lp_allow_trusted_domains() ? WINBIND_MAX_DOMAINS_HINT
: 1);
439 actual_fds
= set_maxfiles(num_fds
);
441 if (actual_fds
< num_fds
) {
442 DEBUG(1, ("winbindd_setup_max_fds: Information only: "
443 "requested %d open files, %d are available.\n",
444 num_fds
, actual_fds
));
448 bool winbindd_reload_services_file(const char *lfile
)
450 const struct loadparm_substitution
*lp_sub
=
451 loadparm_s3_global_substitution();
455 char *fname
= lp_next_configfile(talloc_tos(), lp_sub
);
457 if (file_exist(fname
) && !strcsequal(fname
,get_dyn_CONFIGFILE())) {
458 set_dyn_CONFIGFILE(fname
);
464 ret
= lp_load_global(get_dyn_CONFIGFILE());
466 /* if this is a child, restore the logfile to the special
467 name - <domain>, idmap, etc. */
468 if (lfile
&& *lfile
) {
469 lp_set_logfile(lfile
);
474 winbindd_setup_max_fds();
479 static size_t *debug_call_depth
= NULL
;
481 void winbind_debug_call_depth_setup(size_t *depth
)
483 debug_call_depth
= depth
;
486 void winbind_call_flow(void *private_data
,
487 enum tevent_thread_call_depth_cmd cmd
,
488 struct tevent_req
*req
,
493 case TEVENT_CALL_FLOW_REQ_CREATE
:
494 *debug_call_depth
= depth
;
495 DEBUG(20, ("flow: -> %s\n", fname
));
497 case TEVENT_CALL_FLOW_REQ_NOTIFY_CB
:
498 *debug_call_depth
= depth
;
499 DEBUG(20, ("flow: <- %s\n", fname
));
501 case TEVENT_CALL_FLOW_REQ_QUEUE_TRIGGER
:
502 *debug_call_depth
= depth
;
504 case TEVENT_CALL_FLOW_REQ_RESET
:
505 *debug_call_depth
= depth
;
507 case TEVENT_CALL_FLOW_REQ_CANCEL
:
508 case TEVENT_CALL_FLOW_REQ_CLEANUP
:
509 case TEVENT_CALL_FLOW_REQ_QUEUE_ENTER
:
510 case TEVENT_CALL_FLOW_REQ_QUEUE_LEAVE
: