s3:idmap_ldap: rename idmap_ldap_allocate_id to idmap_ldap_allocate_id_internal
[samba.git] / source3 / winbindd / winbindd_misc.c
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
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_WINBIND
28
29 /* Constants and helper functions for determining domain trust types */
30
31 enum trust_type {
32         EXTERNAL = 0,
33         FOREST,
34         IN_FOREST,
35         NONE,
36 };
37
38 const char *trust_type_strings[] = {"External", 
39                                     "Forest", 
40                                     "In Forest",
41                                     "None"};
42
43 static enum trust_type get_trust_type(struct winbindd_tdc_domain *domain)
44 {
45         if (domain->trust_attribs == NETR_TRUST_ATTRIBUTE_QUARANTINED_DOMAIN)   
46                 return EXTERNAL;
47         else if (domain->trust_attribs == NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)
48                 return FOREST;
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))
51                 return IN_FOREST;
52         return NONE;    
53 }
54
55 static const char *get_trust_type_string(struct winbindd_tdc_domain *domain)
56 {
57         return trust_type_strings[get_trust_type(domain)];
58 }
59
60 static bool trust_is_inbound(struct winbindd_tdc_domain *domain)
61 {
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);           
67 }
68
69 static bool trust_is_outbound(struct winbindd_tdc_domain *domain)
70 {
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);          
76 }
77
78 static bool trust_is_transitive(struct winbindd_tdc_domain *domain)
79 {
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))
83                 return False;
84         return True;
85 }
86
87 void winbindd_list_trusted_domains(struct winbindd_cli_state *state)
88 {
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;
94         int i = 0;
95
96         DEBUG(3, ("[%5lu]: list trusted domains\n",
97                   (unsigned long)state->pid));
98
99         if( !wcache_tdc_fetch_list( &dom_list, &num_domains )) {
100                 request_error(state);   
101                 goto done;
102         }
103
104         extra_data = talloc_strdup(state->mem_ctx, "");
105         if (extra_data == NULL) {
106                 request_error(state);
107                 goto done;
108         }
109
110         for ( i = 0; i < num_domains; i++ ) {
111                 struct winbindd_domain *domain;
112                 bool is_online = true;          
113
114                 d = &dom_list[i];
115                 domain = find_domain_from_name_noinit(d->domain_name);
116                 if (domain) {
117                         is_online = domain->online;
118                 }
119                 extra_data = talloc_asprintf_append_buffer(
120                         extra_data,
121                         "%s\\%s\\%s\\%s\\%s\\%s\\%s\\%s\n",
122                         d->domain_name,
123                         d->dns_name ? d->dns_name : d->domain_name,
124                         sid_string_talloc(state->mem_ctx, &d->sid),
125                         get_trust_type_string(d),
126                         trust_is_transitive(d) ? "Yes" : "No",
127                         trust_is_inbound(d) ? "Yes" : "No",
128                         trust_is_outbound(d) ? "Yes" : "No",
129                         is_online ? "Online" : "Offline" );
130         }
131
132         state->response->data.num_entries = num_domains;
133
134         extra_data_len = strlen(extra_data);
135         if (extra_data_len > 0) {
136
137                 /* Strip the last \n */
138                 extra_data[extra_data_len-1] = '\0';
139
140                 state->response->extra_data.data = extra_data;
141                 state->response->length += extra_data_len;
142         }
143
144         request_ok(state);      
145 done:
146         TALLOC_FREE( dom_list );
147 }
148
149 enum winbindd_result winbindd_dual_list_trusted_domains(struct winbindd_domain *domain,
150                                                         struct winbindd_cli_state *state)
151 {
152         int i;
153         int extra_data_len = 0;
154         char *extra_data;
155         NTSTATUS result;
156         bool have_own_domain = False;
157         struct netr_DomainTrustList trusts;
158
159         DEBUG(3, ("[%5lu]: list trusted domains\n",
160                   (unsigned long)state->pid));
161
162         result = domain->methods->trusted_domains(domain, state->mem_ctx,
163                                                   &trusts);
164
165         if (!NT_STATUS_IS_OK(result)) {
166                 DEBUG(3, ("winbindd_dual_list_trusted_domains: trusted_domains returned %s\n",
167                         nt_errstr(result) ));
168                 return WINBINDD_ERROR;
169         }
170
171         extra_data = talloc_strdup(state->mem_ctx, "");
172
173         for (i=0; i<trusts.count; i++) {
174                 extra_data = talloc_asprintf_append_buffer(
175                         extra_data, "%s\\%s\\%s\n",
176                         trusts.array[i].netbios_name,
177                         trusts.array[i].dns_name,
178                         sid_string_talloc(state->mem_ctx,
179                                           trusts.array[i].sid));
180         }
181
182         /* add our primary domain */
183
184         for (i=0; i<trusts.count; i++) {
185                 if (strequal(trusts.array[i].netbios_name, domain->name)) {
186                         have_own_domain = True;
187                         break;
188                 }
189         }
190
191         if (state->request->data.list_all_domains && !have_own_domain) {
192                 extra_data = talloc_asprintf_append_buffer(
193                         extra_data, "%s\\%s\\%s\n", domain->name,
194                         domain->alt_name ? domain->alt_name : domain->name,
195                         sid_string_talloc(state->mem_ctx, &domain->sid));
196         }
197
198         extra_data_len = strlen(extra_data);
199         if (extra_data_len > 0) {
200
201                 /* Strip the last \n */
202                 extra_data[extra_data_len-1] = '\0';
203
204                 state->response->extra_data.data = extra_data;
205                 state->response->length += extra_data_len+1;
206         }
207
208         return WINBINDD_OK;
209 }
210
211 struct domain_info_state {
212         struct winbindd_domain *domain;
213         struct winbindd_cli_state *cli;
214         struct winbindd_request ping_request;
215 };
216
217 static void domain_info_done(struct tevent_req *req);
218
219 void winbindd_domain_info(struct winbindd_cli_state *cli)
220 {
221         struct domain_info_state *state;
222         struct winbindd_domain *domain;
223         struct tevent_req *req;
224
225         DEBUG(3, ("[%5lu]: domain_info [%s]\n", (unsigned long)cli->pid,
226                   cli->request->domain_name));
227
228         domain = find_domain_from_name_noinit(cli->request->domain_name);
229
230         if (domain == NULL) {
231                 DEBUG(3, ("Did not find domain [%s]\n",
232                           cli->request->domain_name));
233                 request_error(cli);
234                 return;
235         }
236
237         if (domain->initialized) {
238                 fstrcpy(cli->response->data.domain_info.name,
239                         domain->name);
240                 fstrcpy(cli->response->data.domain_info.alt_name,
241                         domain->alt_name);
242                 sid_to_fstring(cli->response->data.domain_info.sid,
243                                &domain->sid);
244                 cli->response->data.domain_info.native_mode =
245                         domain->native_mode;
246                 cli->response->data.domain_info.active_directory =
247                         domain->active_directory;
248                 cli->response->data.domain_info.primary =
249                         domain->primary;
250                 request_ok(cli);
251                 return;
252         }
253
254         state = talloc_zero(cli->mem_ctx, struct domain_info_state);
255         if (state == NULL) {
256                 DEBUG(0, ("talloc failed\n"));
257                 request_error(cli);
258                 return;
259         }
260
261         state->cli = cli;
262         state->domain = domain;
263         state->ping_request.cmd = WINBINDD_PING;
264
265         /*
266          * Send a ping down. This implicitly initializes the domain.
267          */
268
269         req = wb_domain_request_send(state, winbind_event_context(),
270                                      domain, &state->ping_request);
271         if (req == NULL) {
272                 DEBUG(3, ("wb_domain_request_send failed\n"));
273                 request_error(cli);
274                 return;
275         }
276         tevent_req_set_callback(req, domain_info_done, state);
277 }
278
279 static void domain_info_done(struct tevent_req *req)
280 {
281         struct domain_info_state *state = tevent_req_callback_data(
282                 req, struct domain_info_state);
283         struct winbindd_response *response;
284         int ret, err;
285
286         ret = wb_domain_request_recv(req, req, &response, &err);
287         TALLOC_FREE(req);
288         if (ret == -1) {
289                 DEBUG(10, ("wb_domain_request failed: %s\n", strerror(errno)));
290                 request_error(state->cli);
291                 return;
292         }
293         if (!state->domain->initialized) {
294                 DEBUG(5, ("wb_domain_request did not initialize domain %s\n",
295                           state->domain->name));
296                 request_error(state->cli);
297                 return;
298         }
299
300         fstrcpy(state->cli->response->data.domain_info.name,
301                 state->domain->name);
302         fstrcpy(state->cli->response->data.domain_info.alt_name,
303                 state->domain->alt_name);
304         sid_to_fstring(state->cli->response->data.domain_info.sid,
305                        &state->domain->sid);
306
307         state->cli->response->data.domain_info.native_mode =
308                 state->domain->native_mode;
309         state->cli->response->data.domain_info.active_directory =
310                 state->domain->active_directory;
311         state->cli->response->data.domain_info.primary =
312                 state->domain->primary;
313
314         request_ok(state->cli);
315 }
316
317 void winbindd_dc_info(struct winbindd_cli_state *cli)
318 {
319         struct winbindd_domain *domain;
320         char *dc_name, *dc_ip;
321
322         cli->request->domain_name[sizeof(cli->request->domain_name)-1] = '\0';
323
324         DEBUG(3, ("[%5lu]: domain_info [%s]\n", (unsigned long)cli->pid,
325                   cli->request->domain_name));
326
327         if (cli->request->domain_name[0] != '\0') {
328                 domain = find_domain_from_name_noinit(
329                         cli->request->domain_name);
330                 DEBUG(10, ("Could not find domain %s\n",
331                            cli->request->domain_name));
332                 if (domain == NULL) {
333                         request_error(cli);
334                         return;
335                 }
336         } else {
337                 domain = find_our_domain();
338         }
339
340         if (!fetch_current_dc_from_gencache(
341                     talloc_tos(), domain->name, &dc_name, &dc_ip)) {
342                 DEBUG(10, ("fetch_current_dc_from_gencache(%s) failed\n",
343                            domain->name));
344                 request_error(cli);
345                 return;
346         }
347
348         cli->response->data.num_entries = 1;
349         cli->response->extra_data.data = talloc_asprintf(
350                 cli->mem_ctx, "%s\n%s\n", dc_name, dc_ip);
351
352         TALLOC_FREE(dc_name);
353         TALLOC_FREE(dc_ip);
354
355         if (cli->response->extra_data.data == NULL) {
356                 request_error(cli);
357                 return;
358         }
359
360         /* must add one to length to copy the 0 for string termination */
361         cli->response->length +=
362                 strlen((char *)cli->response->extra_data.data) + 1;
363
364         request_ok(cli);
365 }
366
367 /* List various tidbits of information */
368
369 void winbindd_info(struct winbindd_cli_state *state)
370 {
371
372         DEBUG(3, ("[%5lu]: request misc info\n", (unsigned long)state->pid));
373
374         state->response->data.info.winbind_separator = *lp_winbind_separator();
375         fstrcpy(state->response->data.info.samba_version, samba_version_string());
376         request_ok(state);
377 }
378
379 /* Tell the client the current interface version */
380
381 void winbindd_interface_version(struct winbindd_cli_state *state)
382 {
383         DEBUG(3, ("[%5lu]: request interface version\n",
384                   (unsigned long)state->pid));
385
386         state->response->data.interface_version = WINBIND_INTERFACE_VERSION;
387         request_ok(state);
388 }
389
390 /* What domain are we a member of? */
391
392 void winbindd_domain_name(struct winbindd_cli_state *state)
393 {
394         DEBUG(3, ("[%5lu]: request domain name\n", (unsigned long)state->pid));
395
396         fstrcpy(state->response->data.domain_name, lp_workgroup());
397         request_ok(state);
398 }
399
400 /* What's my name again? */
401
402 void winbindd_netbios_name(struct winbindd_cli_state *state)
403 {
404         DEBUG(3, ("[%5lu]: request netbios name\n",
405                   (unsigned long)state->pid));
406
407         fstrcpy(state->response->data.netbios_name, global_myname());
408         request_ok(state);
409 }
410
411 /* Where can I find the privileged pipe? */
412
413 void winbindd_priv_pipe_dir(struct winbindd_cli_state *state)
414 {
415         char *priv_dir;
416         DEBUG(3, ("[%5lu]: request location of privileged pipe\n",
417                   (unsigned long)state->pid));
418
419         priv_dir = get_winbind_priv_pipe_dir();
420         state->response->extra_data.data = talloc_move(state->mem_ctx,
421                                                       &priv_dir);
422
423         /* must add one to length to copy the 0 for string termination */
424         state->response->length +=
425                 strlen((char *)state->response->extra_data.data) + 1;
426
427         request_ok(state);
428 }
429