Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : Winbind daemon - miscellaneous other functions
5 :
6 : Copyright (C) Tim Potter 2000
7 : Copyright (C) Andrew Bartlett 2002
8 :
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.
13 :
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.
18 :
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/>.
21 : */
22 :
23 : #include "includes.h"
24 : #include "winbindd.h"
25 : #include "libcli/security/dom_sid.h"
26 : #include "lib/util/string_wrappers.h"
27 :
28 : #undef DBGC_CLASS
29 : #define DBGC_CLASS DBGC_WINBIND
30 :
31 266 : static char *get_trust_type_string(TALLOC_CTX *mem_ctx,
32 : struct winbindd_tdc_domain *tdc,
33 : struct winbindd_domain *domain)
34 : {
35 266 : enum netr_SchannelType secure_channel_type = SEC_CHAN_NULL;
36 266 : char *s = NULL;
37 :
38 266 : if (domain != NULL) {
39 266 : secure_channel_type = domain->secure_channel_type;
40 : }
41 :
42 266 : switch (secure_channel_type) {
43 64 : case SEC_CHAN_NULL: {
44 64 : if (domain == NULL) {
45 0 : DBG_ERR("Missing domain [%s]\n",
46 : tdc->domain_name);
47 0 : return NULL;
48 : }
49 64 : if (domain->routing_domain == NULL) {
50 0 : DBG_ERR("Missing routing for domain [%s]\n",
51 : tdc->domain_name);
52 0 : return NULL;
53 : }
54 64 : s = talloc_asprintf(mem_ctx, "Routed (via %s)",
55 64 : domain->routing_domain->name);
56 64 : if (s == NULL) {
57 0 : return NULL;
58 : }
59 64 : break;
60 : }
61 :
62 130 : case SEC_CHAN_LOCAL:
63 130 : s = talloc_strdup(mem_ctx, "Local");
64 130 : if (s == NULL) {
65 0 : return NULL;
66 : }
67 130 : break;
68 :
69 58 : case SEC_CHAN_WKSTA:
70 58 : s = talloc_strdup(mem_ctx, "Workstation");
71 58 : if (s == NULL) {
72 0 : return NULL;
73 : }
74 58 : break;
75 :
76 14 : case SEC_CHAN_BDC: {
77 14 : int role = lp_server_role();
78 :
79 14 : if (role == ROLE_DOMAIN_PDC || role == ROLE_IPA_DC) {
80 14 : s = talloc_strdup(mem_ctx, "PDC");
81 14 : if (s == NULL) {
82 0 : return NULL;
83 : }
84 14 : break;
85 : }
86 :
87 0 : if (role == ROLE_DOMAIN_BDC) {
88 0 : s = talloc_strdup(mem_ctx, "BDC");
89 0 : if (s == NULL) {
90 0 : return NULL;
91 : }
92 0 : break;
93 : }
94 :
95 0 : s = talloc_strdup(mem_ctx, "RWDC");
96 0 : if (s == NULL) {
97 0 : return NULL;
98 : }
99 0 : break;
100 : }
101 :
102 0 : case SEC_CHAN_RODC:
103 0 : s = talloc_strdup(mem_ctx, "RODC");
104 0 : if (s == NULL) {
105 0 : return NULL;
106 : }
107 0 : break;
108 :
109 0 : case SEC_CHAN_DNS_DOMAIN:
110 0 : if (tdc->trust_attribs & LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) {
111 0 : s = talloc_strdup(mem_ctx, "External");
112 0 : if (s == NULL) {
113 0 : return NULL;
114 : }
115 0 : break;
116 : }
117 0 : if (tdc->trust_attribs & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
118 0 : s = talloc_strdup(mem_ctx, "In Forest");
119 0 : if (s == NULL) {
120 0 : return NULL;
121 : }
122 0 : break;
123 : }
124 0 : if (tdc->trust_attribs & LSA_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL) {
125 0 : s = talloc_strdup(mem_ctx, "External");
126 0 : if (s == NULL) {
127 0 : return NULL;
128 : }
129 0 : break;
130 : }
131 0 : if (tdc->trust_attribs & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
132 0 : s = talloc_strdup(mem_ctx, "Forest");
133 0 : if (s == NULL) {
134 0 : return NULL;
135 : }
136 0 : break;
137 : }
138 0 : s = talloc_strdup(mem_ctx, "External");
139 0 : if (s == NULL) {
140 0 : return NULL;
141 : }
142 0 : break;
143 :
144 0 : case SEC_CHAN_DOMAIN:
145 0 : s = talloc_strdup(mem_ctx, "External");
146 0 : if (s == NULL) {
147 0 : return NULL;
148 : }
149 0 : break;
150 :
151 0 : default:
152 0 : DBG_ERR("Unhandled secure_channel_type %d for domain[%s]\n",
153 : secure_channel_type, tdc->domain_name);
154 0 : return NULL;
155 : }
156 :
157 266 : return s;
158 : }
159 :
160 266 : static bool trust_is_inbound(struct winbindd_tdc_domain *domain)
161 : {
162 266 : if (domain->trust_flags & NETR_TRUST_FLAG_INBOUND) {
163 4 : return true;
164 : }
165 262 : return false;
166 : }
167 :
168 266 : static bool trust_is_outbound(struct winbindd_tdc_domain *domain)
169 : {
170 266 : if (domain->trust_flags & NETR_TRUST_FLAG_OUTBOUND) {
171 192 : return true;
172 : }
173 74 : return false;
174 : }
175 :
176 266 : static bool trust_is_transitive(struct winbindd_tdc_domain *domain)
177 : {
178 266 : bool transitive = false;
179 :
180 : /*
181 : * Beware: order matters
182 : */
183 :
184 266 : if (domain->trust_attribs & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
185 0 : transitive = true;
186 : }
187 :
188 266 : if (domain->trust_attribs & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
189 4 : transitive = true;
190 : }
191 :
192 266 : if (domain->trust_attribs & LSA_TRUST_ATTRIBUTE_NON_TRANSITIVE) {
193 0 : transitive = false;
194 : }
195 :
196 266 : if (domain->trust_attribs & LSA_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN) {
197 0 : transitive = false;
198 : }
199 :
200 266 : if (domain->trust_flags & NETR_TRUST_FLAG_PRIMARY) {
201 72 : transitive = true;
202 : }
203 :
204 266 : return transitive;
205 : }
206 :
207 72 : bool winbindd_list_trusted_domains(struct winbindd_cli_state *state)
208 : {
209 72 : struct winbindd_tdc_domain *dom_list = NULL;
210 72 : size_t num_domains = 0;
211 72 : int extra_data_len = 0;
212 72 : char *extra_data = NULL;
213 72 : size_t i = 0;
214 72 : bool ret = false;
215 :
216 72 : DBG_NOTICE("[%s (%u)]: list trusted domains\n",
217 : state->client_name,
218 : (unsigned int)state->pid);
219 :
220 72 : if( !wcache_tdc_fetch_list( &dom_list, &num_domains )) {
221 0 : goto done;
222 : }
223 :
224 72 : extra_data = talloc_strdup(state->mem_ctx, "");
225 72 : if (extra_data == NULL) {
226 0 : goto done;
227 : }
228 :
229 338 : for ( i = 0; i < num_domains; i++ ) {
230 0 : struct winbindd_domain *domain;
231 266 : bool is_online = true;
232 266 : struct winbindd_tdc_domain *d = NULL;
233 266 : char *trust_type = NULL;
234 0 : struct dom_sid_buf buf;
235 :
236 266 : d = &dom_list[i];
237 266 : domain = find_domain_from_name_noinit(d->domain_name);
238 266 : if (domain) {
239 266 : is_online = domain->online;
240 : }
241 :
242 266 : trust_type = get_trust_type_string(talloc_tos(), d, domain);
243 266 : if (trust_type == NULL) {
244 0 : continue;
245 : }
246 :
247 1330 : extra_data = talloc_asprintf_append_buffer(
248 : extra_data,
249 : "%s\\%s\\%s\\%s\\%s\\%s\\%s\\%s\n",
250 : d->domain_name,
251 266 : d->dns_name ? d->dns_name : "",
252 266 : dom_sid_str_buf(&d->sid, &buf),
253 : trust_type,
254 266 : trust_is_transitive(d) ? "Yes" : "No",
255 266 : trust_is_inbound(d) ? "Yes" : "No",
256 266 : trust_is_outbound(d) ? "Yes" : "No",
257 : is_online ? "Online" : "Offline" );
258 :
259 266 : TALLOC_FREE(trust_type);
260 : }
261 :
262 72 : state->response->data.num_entries = num_domains;
263 :
264 72 : extra_data_len = strlen(extra_data);
265 72 : if (extra_data_len > 0) {
266 :
267 : /* Strip the last \n */
268 72 : extra_data[extra_data_len-1] = '\0';
269 :
270 72 : state->response->extra_data.data = extra_data;
271 72 : state->response->length += extra_data_len;
272 : }
273 :
274 72 : ret = true;
275 72 : done:
276 72 : TALLOC_FREE( dom_list );
277 72 : return ret;
278 : }
279 :
280 4 : bool winbindd_dc_info(struct winbindd_cli_state *cli)
281 : {
282 0 : struct winbindd_domain *domain;
283 0 : char *dc_name, *dc_ip;
284 :
285 4 : cli->request->domain_name[sizeof(cli->request->domain_name)-1] = '\0';
286 :
287 4 : DBG_NOTICE("[%s (%u)]: domain_info [%s]\n",
288 : cli->client_name,
289 : (unsigned int)cli->pid,
290 : cli->request->domain_name);
291 :
292 4 : if (cli->request->domain_name[0] != '\0') {
293 4 : domain = find_trust_from_name_noinit(
294 4 : cli->request->domain_name);
295 4 : if (domain == NULL) {
296 0 : DEBUG(10, ("Could not find domain %s\n",
297 : cli->request->domain_name));
298 0 : return false;
299 : }
300 : } else {
301 0 : domain = find_our_domain();
302 : }
303 :
304 4 : if (!fetch_current_dc_from_gencache(
305 4 : talloc_tos(), domain->name, &dc_name, &dc_ip)) {
306 0 : DEBUG(10, ("fetch_current_dc_from_gencache(%s) failed\n",
307 : domain->name));
308 0 : return false;
309 : }
310 :
311 4 : cli->response->data.num_entries = 1;
312 8 : cli->response->extra_data.data = talloc_asprintf(
313 4 : cli->mem_ctx, "%s\n%s\n", dc_name, dc_ip);
314 :
315 4 : TALLOC_FREE(dc_name);
316 4 : TALLOC_FREE(dc_ip);
317 :
318 4 : if (cli->response->extra_data.data == NULL) {
319 0 : return false;
320 : }
321 :
322 : /* must add one to length to copy the 0 for string termination */
323 4 : cli->response->length +=
324 4 : strlen((char *)cli->response->extra_data.data) + 1;
325 :
326 4 : return true;
327 : }
328 :
329 115575 : bool winbindd_ping(struct winbindd_cli_state *state)
330 : {
331 115575 : DBG_NOTICE("[%s (%u)]: ping\n",
332 : state->client_name,
333 : (unsigned int)state->pid);
334 115575 : return true;
335 : }
336 :
337 : /* List various tidbits of information */
338 :
339 2141 : bool winbindd_info(struct winbindd_cli_state *state)
340 : {
341 :
342 2141 : DBG_NOTICE("[%s (%u)]: request misc info\n",
343 : state->client_name,
344 : (unsigned int)state->pid);
345 :
346 2141 : state->response->data.info.winbind_separator = *lp_winbind_separator();
347 2141 : fstrcpy(state->response->data.info.samba_version, samba_version_string());
348 2141 : return true;
349 : }
350 :
351 : /* Tell the client the current interface version */
352 :
353 7578 : bool winbindd_interface_version(struct winbindd_cli_state *state)
354 : {
355 7578 : DBG_NOTICE("[%s (%u)]: request interface version (version = %d)\n",
356 : state->client_name,
357 : (unsigned int)state->pid,
358 : WINBIND_INTERFACE_VERSION);
359 :
360 7578 : state->response->data.interface_version = WINBIND_INTERFACE_VERSION;
361 7578 : return true;
362 : }
363 :
364 : /* What domain are we a member of? */
365 :
366 729 : bool winbindd_domain_name(struct winbindd_cli_state *state)
367 : {
368 729 : DBG_NOTICE("[%s (%u)]: request domain name\n",
369 : state->client_name,
370 : (unsigned int)state->pid);
371 :
372 729 : fstrcpy(state->response->data.domain_name, lp_workgroup());
373 729 : return true;
374 : }
375 :
376 : /* What's my name again? */
377 :
378 725 : bool winbindd_netbios_name(struct winbindd_cli_state *state)
379 : {
380 725 : DBG_NOTICE("[%s (%u)]: request netbios name\n",
381 : state->client_name,
382 : (unsigned int)state->pid);
383 :
384 725 : fstrcpy(state->response->data.netbios_name, lp_netbios_name());
385 725 : return true;
386 : }
387 :
388 : /* Where can I find the privileged pipe? */
389 :
390 1278 : char *get_winbind_priv_pipe_dir(void)
391 : {
392 1278 : return state_path(talloc_tos(), WINBINDD_PRIV_SOCKET_SUBDIR);
393 : }
394 :
395 1188 : bool winbindd_priv_pipe_dir(struct winbindd_cli_state *state)
396 : {
397 0 : char *priv_dir;
398 :
399 1188 : DBG_NOTICE("[%s (%u)]: request location of privileged pipe\n",
400 : state->client_name,
401 : (unsigned int)state->pid);
402 :
403 1188 : priv_dir = get_winbind_priv_pipe_dir();
404 1188 : state->response->extra_data.data = talloc_move(state->mem_ctx,
405 : &priv_dir);
406 :
407 : /* must add one to length to copy the 0 for string termination */
408 1188 : state->response->length +=
409 1188 : strlen((char *)state->response->extra_data.data) + 1;
410 :
411 1188 : DBG_NOTICE("[%s (%u)]: response location of privileged pipe: %s\n",
412 : state->client_name,
413 : (unsigned int)state->pid,
414 : priv_dir);
415 :
416 1188 : return true;
417 : }
418 :
419 131 : static void winbindd_setup_max_fds(void)
420 : {
421 131 : int num_fds = MAX_OPEN_FUDGEFACTOR;
422 0 : int actual_fds;
423 :
424 131 : 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
428 : */
429 131 : num_fds += lp_winbind_max_clients() / 10;
430 :
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
435 : */
436 131 : num_fds += lp_winbind_max_domain_connections() *
437 131 : (lp_allow_trusted_domains() ? WINBIND_MAX_DOMAINS_HINT : 1);
438 :
439 131 : actual_fds = set_maxfiles(num_fds);
440 :
441 131 : if (actual_fds < num_fds) {
442 0 : DEBUG(1, ("winbindd_setup_max_fds: Information only: "
443 : "requested %d open files, %d are available.\n",
444 : num_fds, actual_fds));
445 : }
446 131 : }
447 :
448 131 : bool winbindd_reload_services_file(const char *lfile)
449 : {
450 0 : const struct loadparm_substitution *lp_sub =
451 131 : loadparm_s3_global_substitution();
452 0 : bool ret;
453 :
454 131 : if (lp_loaded()) {
455 131 : char *fname = lp_next_configfile(talloc_tos(), lp_sub);
456 :
457 131 : if (file_exist(fname) && !strcsequal(fname,get_dyn_CONFIGFILE())) {
458 0 : set_dyn_CONFIGFILE(fname);
459 : }
460 131 : TALLOC_FREE(fname);
461 : }
462 :
463 131 : reopen_logs();
464 131 : ret = lp_load_global(get_dyn_CONFIGFILE());
465 :
466 : /* if this is a child, restore the logfile to the special
467 : name - <domain>, idmap, etc. */
468 131 : if (lfile && *lfile) {
469 0 : lp_set_logfile(lfile);
470 : }
471 :
472 131 : reopen_logs();
473 131 : load_interfaces();
474 131 : winbindd_setup_max_fds();
475 :
476 131 : return(ret);
477 : }
478 :
479 : static size_t *debug_call_depth = NULL;
480 :
481 45 : void winbind_debug_call_depth_setup(size_t *depth)
482 : {
483 45 : debug_call_depth = depth;
484 45 : }
485 :
486 0 : 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)
491 : {
492 0 : switch (cmd) {
493 0 : case TEVENT_CALL_FLOW_REQ_CREATE:
494 0 : *debug_call_depth = depth;
495 0 : DEBUG(20, ("flow: -> %s\n", fname));
496 0 : break;
497 0 : case TEVENT_CALL_FLOW_REQ_NOTIFY_CB:
498 0 : *debug_call_depth = depth;
499 0 : DEBUG(20, ("flow: <- %s\n", fname));
500 0 : break;
501 0 : case TEVENT_CALL_FLOW_REQ_QUEUE_TRIGGER:
502 0 : *debug_call_depth = depth;
503 0 : break;
504 0 : case TEVENT_CALL_FLOW_REQ_RESET:
505 0 : *debug_call_depth = depth;
506 0 : break;
507 0 : 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 0 : break;
512 : }
513 0 : }
|