Merge branch 'master' of /home/tridge/samba/git/combined
[Samba/aatanasov.git] / source3 / winbindd / winbindd_dual_srv.c
blob179a77106660c894fa929d33f344eaa636e2f6b7
1 /*
2 Unix SMB/CIFS implementation.
4 In-Child server implementation of the routines defined in wbint.idl
6 Copyright (C) Volker Lendecke 2009
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "winbindd/winbindd.h"
24 #include "winbindd/winbindd_proto.h"
25 #include "librpc/gen_ndr/srv_wbint.h"
27 void _wbint_Ping(pipes_struct *p, struct wbint_Ping *r)
29 *r->out.out_data = r->in.in_data;
32 NTSTATUS _wbint_LookupSid(pipes_struct *p, struct wbint_LookupSid *r)
34 struct winbindd_domain *domain = wb_child_domain();
35 char *dom_name;
36 char *name;
37 enum lsa_SidType type;
38 NTSTATUS status;
40 if (domain == NULL) {
41 return NT_STATUS_REQUEST_NOT_ACCEPTED;
44 status = domain->methods->sid_to_name(domain, p->mem_ctx, r->in.sid,
45 &dom_name, &name, &type);
46 if (!NT_STATUS_IS_OK(status)) {
47 return status;
50 *r->out.domain = dom_name;
51 *r->out.name = name;
52 *r->out.type = type;
53 return NT_STATUS_OK;
56 NTSTATUS _wbint_LookupName(pipes_struct *p, struct wbint_LookupName *r)
58 struct winbindd_domain *domain = wb_child_domain();
60 if (domain == NULL) {
61 return NT_STATUS_REQUEST_NOT_ACCEPTED;
64 return domain->methods->name_to_sid(
65 domain, p->mem_ctx, r->in.domain, r->in.name, r->in.flags,
66 r->out.sid, r->out.type);
69 NTSTATUS _wbint_Sid2Uid(pipes_struct *p, struct wbint_Sid2Uid *r)
71 uid_t uid;
72 NTSTATUS status;
74 status = idmap_sid_to_uid(r->in.dom_name ? r->in.dom_name : "",
75 r->in.sid, &uid);
76 if (!NT_STATUS_IS_OK(status)) {
77 return status;
79 *r->out.uid = uid;
80 return NT_STATUS_OK;
83 NTSTATUS _wbint_Sid2Gid(pipes_struct *p, struct wbint_Sid2Gid *r)
85 gid_t gid;
86 NTSTATUS status;
88 status = idmap_sid_to_gid(r->in.dom_name ? r->in.dom_name : "",
89 r->in.sid, &gid);
90 if (!NT_STATUS_IS_OK(status)) {
91 return status;
93 *r->out.gid = gid;
94 return NT_STATUS_OK;
97 NTSTATUS _wbint_Uid2Sid(pipes_struct *p, struct wbint_Uid2Sid *r)
99 return idmap_uid_to_sid(r->in.dom_name ? r->in.dom_name : "",
100 r->out.sid, r->in.uid);
103 NTSTATUS _wbint_Gid2Sid(pipes_struct *p, struct wbint_Gid2Sid *r)
105 return idmap_gid_to_sid(r->in.dom_name ? r->in.dom_name : "",
106 r->out.sid, r->in.gid);
109 NTSTATUS _wbint_AllocateUid(pipes_struct *p, struct wbint_AllocateUid *r)
111 struct unixid xid;
112 NTSTATUS status;
114 status = idmap_allocate_uid(&xid);
115 if (!NT_STATUS_IS_OK(status)) {
116 return status;
118 *r->out.uid = xid.id;
119 return NT_STATUS_OK;
122 NTSTATUS _wbint_AllocateGid(pipes_struct *p, struct wbint_AllocateGid *r)
124 struct unixid xid;
125 NTSTATUS status;
127 status = idmap_allocate_gid(&xid);
128 if (!NT_STATUS_IS_OK(status)) {
129 return status;
131 *r->out.gid = xid.id;
132 return NT_STATUS_OK;
135 NTSTATUS _wbint_QueryUser(pipes_struct *p, struct wbint_QueryUser *r)
137 struct winbindd_domain *domain = wb_child_domain();
139 if (domain == NULL) {
140 return NT_STATUS_REQUEST_NOT_ACCEPTED;
143 return domain->methods->query_user(domain, p->mem_ctx, r->in.sid,
144 r->out.info);
147 NTSTATUS _wbint_LookupUserAliases(pipes_struct *p,
148 struct wbint_LookupUserAliases *r)
150 struct winbindd_domain *domain = wb_child_domain();
152 if (domain == NULL) {
153 return NT_STATUS_REQUEST_NOT_ACCEPTED;
156 return domain->methods->lookup_useraliases(
157 domain, p->mem_ctx, r->in.sids->num_sids, r->in.sids->sids,
158 &r->out.rids->num_rids, &r->out.rids->rids);
161 NTSTATUS _wbint_LookupUserGroups(pipes_struct *p,
162 struct wbint_LookupUserGroups *r)
164 struct winbindd_domain *domain = wb_child_domain();
166 if (domain == NULL) {
167 return NT_STATUS_REQUEST_NOT_ACCEPTED;
170 return domain->methods->lookup_usergroups(
171 domain, p->mem_ctx, r->in.sid,
172 &r->out.sids->num_sids, &r->out.sids->sids);
175 NTSTATUS _wbint_QuerySequenceNumber(pipes_struct *p,
176 struct wbint_QuerySequenceNumber *r)
178 struct winbindd_domain *domain = wb_child_domain();
180 if (domain == NULL) {
181 return NT_STATUS_REQUEST_NOT_ACCEPTED;
184 return domain->methods->sequence_number(domain, r->out.sequence);
187 NTSTATUS _wbint_LookupGroupMembers(pipes_struct *p,
188 struct wbint_LookupGroupMembers *r)
190 struct winbindd_domain *domain = wb_child_domain();
191 uint32_t i, num_names;
192 struct dom_sid *sid_mem;
193 char **names;
194 uint32_t *name_types;
195 NTSTATUS status;
197 if (domain == NULL) {
198 return NT_STATUS_REQUEST_NOT_ACCEPTED;
201 status = domain->methods->lookup_groupmem(
202 domain, p->mem_ctx, r->in.sid, r->in.type,
203 &num_names, &sid_mem, &names, &name_types);
204 if (!NT_STATUS_IS_OK(status)) {
205 return status;
208 r->out.members->num_principals = num_names;
209 r->out.members->principals = talloc_array(
210 r->out.members, struct wbint_Principal, num_names);
211 if (r->out.members->principals == NULL) {
212 return NT_STATUS_NO_MEMORY;
215 for (i=0; i<num_names; i++) {
216 struct wbint_Principal *m = &r->out.members->principals[i];
217 sid_copy(&m->sid, &sid_mem[i]);
218 m->name = talloc_move(r->out.members->principals, &names[i]);
219 m->type = (enum lsa_SidType)name_types[i];
222 return NT_STATUS_OK;
225 NTSTATUS _wbint_QueryUserList(pipes_struct *p, struct wbint_QueryUserList *r)
227 struct winbindd_domain *domain = wb_child_domain();
229 if (domain == NULL) {
230 return NT_STATUS_REQUEST_NOT_ACCEPTED;
233 return domain->methods->query_user_list(
234 domain, p->mem_ctx, &r->out.users->num_userinfos,
235 &r->out.users->userinfos);
238 NTSTATUS _wbint_QueryGroupList(pipes_struct *p, struct wbint_QueryGroupList *r)
240 struct winbindd_domain *domain = wb_child_domain();
241 uint32_t i, num_groups;
242 struct acct_info *groups;
243 struct wbint_Principal *result;
244 NTSTATUS status;
246 if (domain == NULL) {
247 return NT_STATUS_REQUEST_NOT_ACCEPTED;
250 status = domain->methods->enum_dom_groups(domain, talloc_tos(),
251 &num_groups, &groups);
252 if (!NT_STATUS_IS_OK(status)) {
253 return status;
256 result = talloc_array(r->out.groups, struct wbint_Principal,
257 num_groups);
258 if (result == NULL) {
259 return NT_STATUS_NO_MEMORY;
262 for (i=0; i<num_groups; i++) {
263 sid_compose(&result[i].sid, &domain->sid, groups[i].rid);
264 result[i].type = SID_NAME_DOM_GRP;
265 result[i].name = talloc_strdup(result, groups[i].acct_name);
266 if (result[i].name == NULL) {
267 TALLOC_FREE(result);
268 TALLOC_FREE(groups);
269 return NT_STATUS_NO_MEMORY;
273 r->out.groups->num_principals = num_groups;
274 r->out.groups->principals = result;
275 return NT_STATUS_OK;
278 NTSTATUS _wbint_DsGetDcName(pipes_struct *p, struct wbint_DsGetDcName *r)
280 struct winbindd_domain *domain = wb_child_domain();
281 struct rpc_pipe_client *netlogon_pipe;
282 struct netr_DsRGetDCNameInfo *dc_info;
283 NTSTATUS status;
284 WERROR werr;
285 unsigned int orig_timeout;
287 if (domain == NULL) {
288 return dsgetdcname(p->mem_ctx, winbind_messaging_context(),
289 r->in.domain_name, r->in.domain_guid,
290 r->in.site_name ? r->in.site_name : "",
291 r->in.flags,
292 r->out.dc_info);
295 status = cm_connect_netlogon(domain, &netlogon_pipe);
297 if (!NT_STATUS_IS_OK(status)) {
298 DEBUG(10, ("Can't contact the NETLOGON pipe\n"));
299 return status;
302 /* This call can take a long time - allow the server to time out.
303 35 seconds should do it. */
305 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
307 if (domain->active_directory) {
308 status = rpccli_netr_DsRGetDCName(
309 netlogon_pipe, p->mem_ctx, domain->dcname,
310 r->in.domain_name, NULL, r->in.domain_guid,
311 r->in.flags, r->out.dc_info, &werr);
312 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(werr)) {
313 goto done;
318 * Fallback to less capable methods
321 dc_info = talloc_zero(r->out.dc_info, struct netr_DsRGetDCNameInfo);
322 if (dc_info == NULL) {
323 status = NT_STATUS_NO_MEMORY;
324 goto done;
327 if (r->in.flags & DS_PDC_REQUIRED) {
328 status = rpccli_netr_GetDcName(
329 netlogon_pipe, p->mem_ctx, domain->dcname,
330 r->in.domain_name, &dc_info->dc_unc, &werr);
331 } else {
332 status = rpccli_netr_GetAnyDCName(
333 netlogon_pipe, p->mem_ctx, domain->dcname,
334 r->in.domain_name, &dc_info->dc_unc, &werr);
337 if (!NT_STATUS_IS_OK(status)) {
338 DEBUG(10, ("rpccli_netr_Get[Any]DCName failed: %s\n",
339 nt_errstr(status)));
340 goto done;
342 if (!W_ERROR_IS_OK(werr)) {
343 DEBUG(10, ("rpccli_netr_Get[Any]DCName failed: %s\n",
344 win_errstr(werr)));
345 status = werror_to_ntstatus(werr);
346 goto done;
349 *r->out.dc_info = dc_info;
350 status = NT_STATUS_OK;
352 done:
353 /* And restore our original timeout. */
354 rpccli_set_timeout(netlogon_pipe, orig_timeout);
356 return status;
359 NTSTATUS _wbint_LookupRids(pipes_struct *p, struct wbint_LookupRids *r)
361 struct winbindd_domain *domain = wb_child_domain();
362 char *domain_name;
363 char **names;
364 enum lsa_SidType *types;
365 struct wbint_Principal *result;
366 NTSTATUS status;
367 int i;
369 if (domain == NULL) {
370 return NT_STATUS_REQUEST_NOT_ACCEPTED;
373 status = domain->methods->rids_to_names(
374 domain, talloc_tos(), &domain->sid, r->in.rids->rids,
375 r->in.rids->num_rids, &domain_name, &names, &types);
376 if (!NT_STATUS_IS_OK(status)) {
377 return status;
380 result = talloc_array(p->mem_ctx, struct wbint_Principal,
381 r->in.rids->num_rids);
382 if (result == NULL) {
383 return NT_STATUS_NO_MEMORY;
386 for (i=0; i<r->in.rids->num_rids; i++) {
387 sid_compose(&result[i].sid, &domain->sid, r->in.rids->rids[i]);
388 result[i].type = types[i];
389 result[i].name = talloc_move(result, &names[i]);
391 TALLOC_FREE(types);
392 TALLOC_FREE(names);
394 r->out.names->num_principals = r->in.rids->num_rids;
395 r->out.names->principals = result;
396 return NT_STATUS_OK;
399 NTSTATUS _wbint_CheckMachineAccount(pipes_struct *p,
400 struct wbint_CheckMachineAccount *r)
402 struct winbindd_domain *domain;
403 int num_retries = 0;
404 NTSTATUS status;
406 again:
407 domain = wb_child_domain();
408 if (domain == NULL) {
409 return NT_STATUS_REQUEST_NOT_ACCEPTED;
412 invalidate_cm_connection(&domain->conn);
415 struct rpc_pipe_client *netlogon_pipe;
416 status = cm_connect_netlogon(domain, &netlogon_pipe);
419 /* There is a race condition between fetching the trust account
420 password and the periodic machine password change. So it's
421 possible that the trust account password has been changed on us.
422 We are returned NT_STATUS_ACCESS_DENIED if this happens. */
424 #define MAX_RETRIES 3
426 if ((num_retries < MAX_RETRIES)
427 && NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
428 num_retries++;
429 goto again;
432 if (!NT_STATUS_IS_OK(status)) {
433 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
434 goto done;
437 /* Pass back result code - zero for success, other values for
438 specific failures. */
440 DEBUG(3, ("secret is %s\n", NT_STATUS_IS_OK(status) ?
441 "good" : "bad"));
443 done:
444 DEBUG(NT_STATUS_IS_OK(status) ? 5 : 2,
445 ("Checking the trust account password returned %s\n",
446 nt_errstr(status)));
448 return status;
451 NTSTATUS _wbint_SetMapping(pipes_struct *p, struct wbint_SetMapping *r)
453 struct id_map map;
455 map.sid = r->in.sid;
456 map.xid.id = r->in.id;
457 map.status = ID_MAPPED;
459 switch (r->in.type) {
460 case WBINT_ID_TYPE_UID:
461 map.xid.type = ID_TYPE_UID;
462 break;
463 case WBINT_ID_TYPE_GID:
464 map.xid.type = ID_TYPE_GID;
465 break;
466 default:
467 return NT_STATUS_INVALID_PARAMETER;
470 return idmap_set_mapping(&map);
473 NTSTATUS _wbint_RemoveMapping(pipes_struct *p, struct wbint_RemoveMapping *r)
475 struct id_map map;
477 map.sid = r->in.sid;
478 map.xid.id = r->in.id;
479 map.status = ID_MAPPED;
481 switch (r->in.type) {
482 case WBINT_ID_TYPE_UID:
483 map.xid.type = ID_TYPE_UID;
484 break;
485 case WBINT_ID_TYPE_GID:
486 map.xid.type = ID_TYPE_GID;
487 break;
488 default:
489 return NT_STATUS_INVALID_PARAMETER;
492 return idmap_remove_mapping(&map);
495 NTSTATUS _wbint_SetHWM(pipes_struct *p, struct wbint_SetHWM *r)
497 struct unixid id;
498 NTSTATUS status;
500 id.id = r->in.id;
502 switch (id.type) {
503 case WBINT_ID_TYPE_UID:
504 id.type = ID_TYPE_UID;
505 status = idmap_set_uid_hwm(&id);
506 break;
507 case ID_TYPE_GID:
508 id.type = ID_TYPE_GID;
509 status = idmap_set_gid_hwm(&id);
510 break;
511 default:
512 status = NT_STATUS_INVALID_PARAMETER;
513 break;
515 return status;