python: remove string_to_byte_array()
[Samba.git] / source3 / winbindd / winbindd_misc.c
blob3dbbc2f92fb4b3f4bdd3d138a6faf48a392ac9f8
1 /*
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/>.
23 #include "includes.h"
24 #include "winbindd.h"
25 #include "libcli/security/dom_sid.h"
26 #include "lib/util/string_wrappers.h"
28 #undef DBGC_CLASS
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;
36 char *s = NULL;
38 if (domain != NULL) {
39 secure_channel_type = domain->secure_channel_type;
42 switch (secure_channel_type) {
43 case SEC_CHAN_NULL: {
44 if (domain == NULL) {
45 DBG_ERR("Missing domain [%s]\n",
46 tdc->domain_name);
47 return NULL;
49 if (domain->routing_domain == NULL) {
50 DBG_ERR("Missing routing for domain [%s]\n",
51 tdc->domain_name);
52 return NULL;
54 s = talloc_asprintf(mem_ctx, "Routed (via %s)",
55 domain->routing_domain->name);
56 if (s == NULL) {
57 return NULL;
59 break;
62 case SEC_CHAN_LOCAL:
63 s = talloc_strdup(mem_ctx, "Local");
64 if (s == NULL) {
65 return NULL;
67 break;
69 case SEC_CHAN_WKSTA:
70 s = talloc_strdup(mem_ctx, "Workstation");
71 if (s == NULL) {
72 return NULL;
74 break;
76 case SEC_CHAN_BDC: {
77 int role = lp_server_role();
79 if (role == ROLE_DOMAIN_PDC || role == ROLE_IPA_DC) {
80 s = talloc_strdup(mem_ctx, "PDC");
81 if (s == NULL) {
82 return NULL;
84 break;
87 if (role == ROLE_DOMAIN_BDC) {
88 s = talloc_strdup(mem_ctx, "BDC");
89 if (s == NULL) {
90 return NULL;
92 break;
95 s = talloc_strdup(mem_ctx, "RWDC");
96 if (s == NULL) {
97 return NULL;
99 break;
102 case SEC_CHAN_RODC:
103 s = talloc_strdup(mem_ctx, "RODC");
104 if (s == NULL) {
105 return NULL;
107 break;
109 case SEC_CHAN_DNS_DOMAIN:
110 if (tdc->trust_attribs & LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) {
111 s = talloc_strdup(mem_ctx, "External");
112 if (s == NULL) {
113 return NULL;
115 break;
117 if (tdc->trust_attribs & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
118 s = talloc_strdup(mem_ctx, "In Forest");
119 if (s == NULL) {
120 return NULL;
122 break;
124 if (tdc->trust_attribs & LSA_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL) {
125 s = talloc_strdup(mem_ctx, "External");
126 if (s == NULL) {
127 return NULL;
129 break;
131 if (tdc->trust_attribs & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
132 s = talloc_strdup(mem_ctx, "Forest");
133 if (s == NULL) {
134 return NULL;
136 break;
138 s = talloc_strdup(mem_ctx, "External");
139 if (s == NULL) {
140 return NULL;
142 break;
144 case SEC_CHAN_DOMAIN:
145 s = talloc_strdup(mem_ctx, "External");
146 if (s == NULL) {
147 return NULL;
149 break;
151 default:
152 DBG_ERR("Unhandled secure_channel_type %d for domain[%s]\n",
153 secure_channel_type, tdc->domain_name);
154 return NULL;
157 return s;
160 static bool trust_is_inbound(struct winbindd_tdc_domain *domain)
162 if (domain->trust_flags & NETR_TRUST_FLAG_INBOUND) {
163 return true;
165 return false;
168 static bool trust_is_outbound(struct winbindd_tdc_domain *domain)
170 if (domain->trust_flags & NETR_TRUST_FLAG_OUTBOUND) {
171 return true;
173 return false;
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) {
185 transitive = true;
188 if (domain->trust_attribs & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
189 transitive = true;
192 if (domain->trust_attribs & LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE) {
193 transitive = false;
196 if (domain->trust_attribs & LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) {
197 transitive = false;
200 if (domain->trust_flags & NETR_TRUST_FLAG_PRIMARY) {
201 transitive = true;
204 return transitive;
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;
213 size_t i = 0;
214 bool ret = false;
216 DBG_NOTICE("[%s (%u)]: list trusted domains\n",
217 state->client_name,
218 (unsigned int)state->pid);
220 if( !wcache_tdc_fetch_list( &dom_list, &num_domains )) {
221 goto done;
224 extra_data = talloc_strdup(state->mem_ctx, "");
225 if (extra_data == NULL) {
226 goto done;
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;
236 d = &dom_list[i];
237 domain = find_domain_from_name_noinit(d->domain_name);
238 if (domain) {
239 is_online = domain->online;
242 trust_type = get_trust_type_string(talloc_tos(), d, domain);
243 if (trust_type == NULL) {
244 continue;
247 extra_data = talloc_asprintf_append_buffer(
248 extra_data,
249 "%s\\%s\\%s\\%s\\%s\\%s\\%s\\%s\n",
250 d->domain_name,
251 d->dns_name ? d->dns_name : "",
252 dom_sid_str_buf(&d->sid, &buf),
253 trust_type,
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;
274 ret = true;
275 done:
276 TALLOC_FREE( dom_list );
277 return ret;
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",
288 cli->client_name,
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));
298 return false;
300 } else {
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",
307 domain->name));
308 return false;
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);
316 TALLOC_FREE(dc_ip);
318 if (cli->response->extra_data.data == NULL) {
319 return false;
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;
326 return true;
329 bool winbindd_ping(struct winbindd_cli_state *state)
331 DBG_NOTICE("[%s (%u)]: ping\n",
332 state->client_name,
333 (unsigned int)state->pid);
334 return true;
337 /* List various tidbits of information */
339 bool winbindd_info(struct winbindd_cli_state *state)
342 DBG_NOTICE("[%s (%u)]: request misc info\n",
343 state->client_name,
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());
348 return true;
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",
356 state->client_name,
357 (unsigned int)state->pid,
358 WINBIND_INTERFACE_VERSION);
360 state->response->data.interface_version = WINBIND_INTERFACE_VERSION;
361 return true;
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",
369 state->client_name,
370 (unsigned int)state->pid);
372 fstrcpy(state->response->data.domain_name, lp_workgroup());
373 return true;
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",
381 state->client_name,
382 (unsigned int)state->pid);
384 fstrcpy(state->response->data.netbios_name, lp_netbios_name());
385 return true;
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)
397 char *priv_dir;
399 DBG_NOTICE("[%s (%u)]: request location of privileged pipe\n",
400 state->client_name,
401 (unsigned int)state->pid);
403 priv_dir = get_winbind_priv_pipe_dir();
404 state->response->extra_data.data = talloc_move(state->mem_ctx,
405 &priv_dir);
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",
412 state->client_name,
413 (unsigned int)state->pid,
414 priv_dir);
416 return true;
419 static void winbindd_setup_max_fds(void)
421 int num_fds = MAX_OPEN_FUDGEFACTOR;
422 int actual_fds;
424 num_fds += lp_winbind_max_clients();
425 /* Add some more to account for 2 sockets open
426 when the client transitions from unprivileged
427 to privileged socket
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
434 with configuration
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();
452 bool ret;
454 if (lp_loaded()) {
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);
460 TALLOC_FREE(fname);
463 reopen_logs();
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);
472 reopen_logs();
473 load_interfaces();
474 winbindd_setup_max_fds();
476 return(ret);
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,
489 size_t depth,
490 const char *fname)
492 switch (cmd) {
493 case TEVENT_CALL_FLOW_REQ_CREATE:
494 *debug_call_depth = depth;
495 DEBUG(20, ("flow: -> %s\n", fname));
496 break;
497 case TEVENT_CALL_FLOW_REQ_NOTIFY_CB:
498 *debug_call_depth = depth;
499 DEBUG(20, ("flow: <- %s\n", fname));
500 break;
501 case TEVENT_CALL_FLOW_REQ_QUEUE_TRIGGER:
502 *debug_call_depth = depth;
503 break;
504 case TEVENT_CALL_FLOW_REQ_RESET:
505 *debug_call_depth = depth;
506 break;
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:
511 break;