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/>.
27 #define DBGC_CLASS DBGC_WINBIND
29 /* Constants and helper functions for determining domain trust types */
38 const char *trust_type_strings
[] = {"External",
43 static enum trust_type
get_trust_type(struct winbindd_tdc_domain
*domain
)
45 if (domain
->trust_attribs
== NETR_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN
)
47 else if (domain
->trust_attribs
== NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE
)
49 else if (((domain
->trust_flags
& NETR_TRUST_FLAG_IN_FOREST
) == NETR_TRUST_FLAG_IN_FOREST
) &&
50 ((domain
->trust_flags
& NETR_TRUST_FLAG_PRIMARY
) == 0x0))
55 static const char *get_trust_type_string(struct winbindd_tdc_domain
*domain
)
57 return trust_type_strings
[get_trust_type(domain
)];
60 static bool trust_is_inbound(struct winbindd_tdc_domain
*domain
)
62 return (domain
->trust_flags
== 0x0) ||
63 ((domain
->trust_flags
& NETR_TRUST_FLAG_IN_FOREST
) ==
64 NETR_TRUST_FLAG_IN_FOREST
) ||
65 ((domain
->trust_flags
& NETR_TRUST_FLAG_INBOUND
) ==
66 NETR_TRUST_FLAG_INBOUND
);
69 static bool trust_is_outbound(struct winbindd_tdc_domain
*domain
)
71 return (domain
->trust_flags
== 0x0) ||
72 ((domain
->trust_flags
& NETR_TRUST_FLAG_IN_FOREST
) ==
73 NETR_TRUST_FLAG_IN_FOREST
) ||
74 ((domain
->trust_flags
& NETR_TRUST_FLAG_OUTBOUND
) ==
75 NETR_TRUST_FLAG_OUTBOUND
);
78 static bool trust_is_transitive(struct winbindd_tdc_domain
*domain
)
80 if ((domain
->trust_attribs
== NETR_TRUST_ATTRIBUTE_NON_TRANSITIVE
) ||
81 (domain
->trust_attribs
== NETR_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN
) ||
82 (domain
->trust_attribs
== NETR_TRUST_ATTRIBUTE_TREAT_AS_EXTERNAL
))
87 void winbindd_list_trusted_domains(struct winbindd_cli_state
*state
)
89 struct winbindd_tdc_domain
*dom_list
= NULL
;
90 struct winbindd_tdc_domain
*d
= 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 for ( i
= 0; i
< num_domains
; i
++ ) {
105 struct winbindd_domain
*domain
;
106 bool is_online
= true;
109 domain
= find_domain_from_name_noinit(d
->domain_name
);
111 is_online
= domain
->online
;
115 extra_data
= talloc_asprintf(state
->mem_ctx
,
116 "%s\\%s\\%s\\%s\\%s\\%s\\%s\\%s",
118 d
->dns_name
? d
->dns_name
: d
->domain_name
,
119 sid_string_talloc(state
->mem_ctx
, &d
->sid
),
120 get_trust_type_string(d
),
121 trust_is_transitive(d
) ? "Yes" : "No",
122 trust_is_inbound(d
) ? "Yes" : "No",
123 trust_is_outbound(d
) ? "Yes" : "No",
124 is_online
? "Online" : "Offline" );
126 extra_data
= talloc_asprintf(state
->mem_ctx
,
127 "%s\n%s\\%s\\%s\\%s\\%s\\%s\\%s\\%s",
130 d
->dns_name
? d
->dns_name
: d
->domain_name
,
131 sid_string_talloc(state
->mem_ctx
, &d
->sid
),
132 get_trust_type_string(d
),
133 trust_is_transitive(d
) ? "Yes" : "No",
134 trust_is_inbound(d
) ? "Yes" : "No",
135 trust_is_outbound(d
) ? "Yes" : "No",
136 is_online
? "Online" : "Offline" );
141 if (extra_data
!= NULL
) {
142 extra_data_len
= strlen(extra_data
);
145 if (extra_data_len
> 0) {
146 state
->response
->extra_data
.data
= extra_data
;
147 state
->response
->length
+= extra_data_len
+1;
152 TALLOC_FREE( dom_list
);
155 enum winbindd_result
winbindd_dual_list_trusted_domains(struct winbindd_domain
*domain
,
156 struct winbindd_cli_state
*state
)
158 uint32 i
, num_domains
;
159 char **names
, **alt_names
;
161 int extra_data_len
= 0;
164 bool have_own_domain
= False
;
166 DEBUG(3, ("[%5lu]: list trusted domains\n",
167 (unsigned long)state
->pid
));
169 result
= domain
->methods
->trusted_domains(domain
, state
->mem_ctx
,
170 &num_domains
, &names
,
173 if (!NT_STATUS_IS_OK(result
)) {
174 DEBUG(3, ("winbindd_dual_list_trusted_domains: trusted_domains returned %s\n",
175 nt_errstr(result
) ));
176 return WINBINDD_ERROR
;
179 extra_data
= talloc_strdup(state
->mem_ctx
, "");
182 extra_data
= talloc_asprintf(
183 state
->mem_ctx
, "%s\\%s\\%s",
184 names
[0], alt_names
[0] ? alt_names
[0] : names
[0],
185 sid_string_talloc(state
->mem_ctx
, &sids
[0]));
187 for (i
=1; i
<num_domains
; i
++)
188 extra_data
= talloc_asprintf(
189 state
->mem_ctx
, "%s\n%s\\%s\\%s",
190 extra_data
, names
[i
],
191 alt_names
[i
] ? alt_names
[i
] : names
[i
],
192 sid_string_talloc(state
->mem_ctx
, &sids
[i
]));
194 /* add our primary domain */
196 for (i
=0; i
<num_domains
; i
++) {
197 if (strequal(names
[i
], domain
->name
)) {
198 have_own_domain
= True
;
203 if (state
->request
->data
.list_all_domains
&& !have_own_domain
) {
204 extra_data
= talloc_asprintf(
205 state
->mem_ctx
, "%s\n%s\\%s\\%s",
206 extra_data
, domain
->name
,
207 domain
->alt_name
? domain
->alt_name
: domain
->name
,
208 sid_string_talloc(state
->mem_ctx
, &domain
->sid
));
211 /* This is a bit excessive, but the extra data sooner or later will be
215 if (extra_data
!= NULL
) {
216 extra_data_len
= strlen(extra_data
);
219 if (extra_data_len
> 0) {
220 state
->response
->extra_data
.data
= extra_data
;
221 state
->response
->length
+= extra_data_len
+1;
227 enum winbindd_result
winbindd_dual_getdcname(struct winbindd_domain
*domain
,
228 struct winbindd_cli_state
*state
)
230 const char *dcname_slash
= NULL
;
232 struct rpc_pipe_client
*netlogon_pipe
;
235 unsigned int orig_timeout
;
236 struct winbindd_domain
*req_domain
;
238 state
->request
->domain_name
239 [sizeof(state
->request
->domain_name
)-1] = '\0';
241 DEBUG(3, ("[%5lu]: Get DC name for %s\n", (unsigned long)state
->pid
,
242 state
->request
->domain_name
));
244 result
= cm_connect_netlogon(domain
, &netlogon_pipe
);
246 if (!NT_STATUS_IS_OK(result
)) {
247 DEBUG(1, ("Can't contact the NETLOGON pipe\n"));
248 return WINBINDD_ERROR
;
251 /* This call can take a long time - allow the server to time out.
252 35 seconds should do it. */
254 orig_timeout
= rpccli_set_timeout(netlogon_pipe
, 35000);
256 req_domain
= find_domain_from_name_noinit(state
->request
->domain_name
);
257 if (req_domain
== domain
) {
258 result
= rpccli_netr_GetDcName(netlogon_pipe
,
261 state
->request
->domain_name
,
265 result
= rpccli_netr_GetAnyDCName(netlogon_pipe
,
268 state
->request
->domain_name
,
272 /* And restore our original timeout. */
273 rpccli_set_timeout(netlogon_pipe
, orig_timeout
);
275 if (!NT_STATUS_IS_OK(result
)) {
276 DEBUG(5,("Error requesting DCname for domain %s: %s\n",
277 state
->request
->domain_name
, nt_errstr(result
)));
278 return WINBINDD_ERROR
;
281 if (!W_ERROR_IS_OK(werr
)) {
282 DEBUG(5, ("Error requesting DCname for domain %s: %s\n",
283 state
->request
->domain_name
, win_errstr(werr
)));
284 return WINBINDD_ERROR
;
295 fstrcpy(state
->response
->data
.dc_name
, p
);
299 /* This is the child-only version of --sequence. It only allows for a single
300 * domain (ie "our" one) to be displayed. */
302 enum winbindd_result
winbindd_dual_show_sequence(struct winbindd_domain
*domain
,
303 struct winbindd_cli_state
*state
)
305 DEBUG(3, ("[%5lu]: show sequence\n", (unsigned long)state
->pid
));
307 /* Ensure null termination */
308 state
->request
->domain_name
[sizeof(state
->request
->domain_name
)-1]='\0';
310 domain
->methods
->sequence_number(domain
, &domain
->sequence_number
);
312 state
->response
->data
.sequence_number
=
313 domain
->sequence_number
;
318 struct domain_info_state
{
319 struct winbindd_domain
*domain
;
320 struct winbindd_cli_state
*cli
;
321 struct winbindd_request ping_request
;
324 static void domain_info_done(struct tevent_req
*req
);
326 void winbindd_domain_info(struct winbindd_cli_state
*cli
)
328 struct domain_info_state
*state
;
329 struct winbindd_domain
*domain
;
330 struct tevent_req
*req
;
332 DEBUG(3, ("[%5lu]: domain_info [%s]\n", (unsigned long)cli
->pid
,
333 cli
->request
->domain_name
));
335 domain
= find_domain_from_name_noinit(cli
->request
->domain_name
);
337 if (domain
== NULL
) {
338 DEBUG(3, ("Did not find domain [%s]\n",
339 cli
->request
->domain_name
));
344 if (domain
->initialized
) {
345 fstrcpy(cli
->response
->data
.domain_info
.name
,
347 fstrcpy(cli
->response
->data
.domain_info
.alt_name
,
349 sid_to_fstring(cli
->response
->data
.domain_info
.sid
,
351 cli
->response
->data
.domain_info
.native_mode
=
353 cli
->response
->data
.domain_info
.active_directory
=
354 domain
->active_directory
;
355 cli
->response
->data
.domain_info
.primary
=
361 state
= talloc_zero(cli
->mem_ctx
, struct domain_info_state
);
363 DEBUG(0, ("talloc failed\n"));
369 state
->domain
= domain
;
370 state
->ping_request
.cmd
= WINBINDD_PING
;
373 * Send a ping down. This implicitly initializes the domain.
376 req
= wb_domain_request_send(state
, winbind_event_context(),
377 domain
, &state
->ping_request
);
379 DEBUG(3, ("wb_domain_request_send failed\n"));
383 tevent_req_set_callback(req
, domain_info_done
, state
);
386 static void domain_info_done(struct tevent_req
*req
)
388 struct domain_info_state
*state
= tevent_req_callback_data(
389 req
, struct domain_info_state
);
390 struct winbindd_response
*response
;
393 ret
= wb_domain_request_recv(req
, req
, &response
, &err
);
396 DEBUG(10, ("wb_domain_request failed: %s\n", strerror(errno
)));
397 request_error(state
->cli
);
400 if (!state
->domain
->initialized
) {
401 DEBUG(5, ("wb_domain_request did not initialize domain %s\n",
402 state
->domain
->name
));
403 request_error(state
->cli
);
407 fstrcpy(state
->cli
->response
->data
.domain_info
.name
,
408 state
->domain
->name
);
409 fstrcpy(state
->cli
->response
->data
.domain_info
.alt_name
,
410 state
->domain
->alt_name
);
411 sid_to_fstring(state
->cli
->response
->data
.domain_info
.sid
,
412 &state
->domain
->sid
);
414 state
->cli
->response
->data
.domain_info
.native_mode
=
415 state
->domain
->native_mode
;
416 state
->cli
->response
->data
.domain_info
.active_directory
=
417 state
->domain
->active_directory
;
418 state
->cli
->response
->data
.domain_info
.primary
=
419 state
->domain
->primary
;
421 request_ok(state
->cli
);
424 /* List various tidbits of information */
426 void winbindd_info(struct winbindd_cli_state
*state
)
429 DEBUG(3, ("[%5lu]: request misc info\n", (unsigned long)state
->pid
));
431 state
->response
->data
.info
.winbind_separator
= *lp_winbind_separator();
432 fstrcpy(state
->response
->data
.info
.samba_version
, samba_version_string());
436 /* Tell the client the current interface version */
438 void winbindd_interface_version(struct winbindd_cli_state
*state
)
440 DEBUG(3, ("[%5lu]: request interface version\n",
441 (unsigned long)state
->pid
));
443 state
->response
->data
.interface_version
= WINBIND_INTERFACE_VERSION
;
447 /* What domain are we a member of? */
449 void winbindd_domain_name(struct winbindd_cli_state
*state
)
451 DEBUG(3, ("[%5lu]: request domain name\n", (unsigned long)state
->pid
));
453 fstrcpy(state
->response
->data
.domain_name
, lp_workgroup());
457 /* What's my name again? */
459 void winbindd_netbios_name(struct winbindd_cli_state
*state
)
461 DEBUG(3, ("[%5lu]: request netbios name\n",
462 (unsigned long)state
->pid
));
464 fstrcpy(state
->response
->data
.netbios_name
, global_myname());
468 /* Where can I find the privileged pipe? */
470 void winbindd_priv_pipe_dir(struct winbindd_cli_state
*state
)
473 DEBUG(3, ("[%5lu]: request location of privileged pipe\n",
474 (unsigned long)state
->pid
));
476 priv_dir
= get_winbind_priv_pipe_dir();
477 state
->response
->extra_data
.data
= talloc_move(state
->mem_ctx
,
480 /* must add one to length to copy the 0 for string termination */
481 state
->response
->length
+=
482 strlen((char *)state
->response
->extra_data
.data
) + 1;