s3: Lift the server_messaging_context from notify_job_status
[Samba/gbeck.git] / source3 / winbindd / winbindd_dual_srv.c
blobd95000969670c9eb9f65dd9b61bee541e4481d07
1 /*
2 Unix SMB/CIFS implementation.
4 In-Child server implementation of the routines defined in wbint.idl
6 Copyright (C) Volker Lendecke 2009
7 Copyright (C) Guenther Deschner 2009
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/winbindd.h"
25 #include "winbindd/winbindd_proto.h"
26 #include "librpc/gen_ndr/srv_wbint.h"
27 #include "../librpc/gen_ndr/cli_netlogon.h"
29 void _wbint_Ping(struct pipes_struct *p, struct wbint_Ping *r)
31 *r->out.out_data = r->in.in_data;
34 NTSTATUS _wbint_LookupSid(struct pipes_struct *p, struct wbint_LookupSid *r)
36 struct winbindd_domain *domain = wb_child_domain();
37 char *dom_name;
38 char *name;
39 enum lsa_SidType type;
40 NTSTATUS status;
42 if (domain == NULL) {
43 return NT_STATUS_REQUEST_NOT_ACCEPTED;
46 status = domain->methods->sid_to_name(domain, p->mem_ctx, r->in.sid,
47 &dom_name, &name, &type);
48 if (!NT_STATUS_IS_OK(status)) {
49 return status;
52 *r->out.domain = dom_name;
53 *r->out.name = name;
54 *r->out.type = type;
55 return NT_STATUS_OK;
58 NTSTATUS _wbint_LookupName(struct pipes_struct *p, struct wbint_LookupName *r)
60 struct winbindd_domain *domain = wb_child_domain();
62 if (domain == NULL) {
63 return NT_STATUS_REQUEST_NOT_ACCEPTED;
66 return domain->methods->name_to_sid(
67 domain, p->mem_ctx, r->in.domain, r->in.name, r->in.flags,
68 r->out.sid, r->out.type);
71 NTSTATUS _wbint_Sid2Uid(struct pipes_struct *p, struct wbint_Sid2Uid *r)
73 uid_t uid;
74 NTSTATUS status;
76 status = idmap_sid_to_uid(r->in.dom_name ? r->in.dom_name : "",
77 r->in.sid, &uid);
78 if (!NT_STATUS_IS_OK(status)) {
79 return status;
81 *r->out.uid = uid;
82 return NT_STATUS_OK;
85 NTSTATUS _wbint_Sid2Gid(struct pipes_struct *p, struct wbint_Sid2Gid *r)
87 gid_t gid;
88 NTSTATUS status;
90 status = idmap_sid_to_gid(r->in.dom_name ? r->in.dom_name : "",
91 r->in.sid, &gid);
92 if (!NT_STATUS_IS_OK(status)) {
93 return status;
95 *r->out.gid = gid;
96 return NT_STATUS_OK;
99 NTSTATUS _wbint_Uid2Sid(struct pipes_struct *p, struct wbint_Uid2Sid *r)
101 return idmap_uid_to_sid(r->in.dom_name ? r->in.dom_name : "",
102 r->out.sid, r->in.uid);
105 NTSTATUS _wbint_Gid2Sid(struct pipes_struct *p, struct wbint_Gid2Sid *r)
107 return idmap_gid_to_sid(r->in.dom_name ? r->in.dom_name : "",
108 r->out.sid, r->in.gid);
111 NTSTATUS _wbint_AllocateUid(struct pipes_struct *p, struct wbint_AllocateUid *r)
113 struct unixid xid;
114 NTSTATUS status;
116 status = idmap_allocate_uid(&xid);
117 if (!NT_STATUS_IS_OK(status)) {
118 return status;
120 *r->out.uid = xid.id;
121 return NT_STATUS_OK;
124 NTSTATUS _wbint_AllocateGid(struct pipes_struct *p, struct wbint_AllocateGid *r)
126 struct unixid xid;
127 NTSTATUS status;
129 status = idmap_allocate_gid(&xid);
130 if (!NT_STATUS_IS_OK(status)) {
131 return status;
133 *r->out.gid = xid.id;
134 return NT_STATUS_OK;
137 NTSTATUS _wbint_QueryUser(struct pipes_struct *p, struct wbint_QueryUser *r)
139 struct winbindd_domain *domain = wb_child_domain();
141 if (domain == NULL) {
142 return NT_STATUS_REQUEST_NOT_ACCEPTED;
145 return domain->methods->query_user(domain, p->mem_ctx, r->in.sid,
146 r->out.info);
149 NTSTATUS _wbint_LookupUserAliases(struct pipes_struct *p,
150 struct wbint_LookupUserAliases *r)
152 struct winbindd_domain *domain = wb_child_domain();
154 if (domain == NULL) {
155 return NT_STATUS_REQUEST_NOT_ACCEPTED;
158 return domain->methods->lookup_useraliases(
159 domain, p->mem_ctx, r->in.sids->num_sids, r->in.sids->sids,
160 &r->out.rids->num_rids, &r->out.rids->rids);
163 NTSTATUS _wbint_LookupUserGroups(struct pipes_struct *p,
164 struct wbint_LookupUserGroups *r)
166 struct winbindd_domain *domain = wb_child_domain();
168 if (domain == NULL) {
169 return NT_STATUS_REQUEST_NOT_ACCEPTED;
172 return domain->methods->lookup_usergroups(
173 domain, p->mem_ctx, r->in.sid,
174 &r->out.sids->num_sids, &r->out.sids->sids);
177 NTSTATUS _wbint_QuerySequenceNumber(struct pipes_struct *p,
178 struct wbint_QuerySequenceNumber *r)
180 struct winbindd_domain *domain = wb_child_domain();
182 if (domain == NULL) {
183 return NT_STATUS_REQUEST_NOT_ACCEPTED;
186 return domain->methods->sequence_number(domain, r->out.sequence);
189 NTSTATUS _wbint_LookupGroupMembers(struct pipes_struct *p,
190 struct wbint_LookupGroupMembers *r)
192 struct winbindd_domain *domain = wb_child_domain();
193 uint32_t i, num_names;
194 struct dom_sid *sid_mem;
195 char **names;
196 uint32_t *name_types;
197 NTSTATUS status;
199 if (domain == NULL) {
200 return NT_STATUS_REQUEST_NOT_ACCEPTED;
203 status = domain->methods->lookup_groupmem(
204 domain, p->mem_ctx, r->in.sid, r->in.type,
205 &num_names, &sid_mem, &names, &name_types);
206 if (!NT_STATUS_IS_OK(status)) {
207 return status;
210 r->out.members->num_principals = num_names;
211 r->out.members->principals = talloc_array(
212 r->out.members, struct wbint_Principal, num_names);
213 if (r->out.members->principals == NULL) {
214 return NT_STATUS_NO_MEMORY;
217 for (i=0; i<num_names; i++) {
218 struct wbint_Principal *m = &r->out.members->principals[i];
219 sid_copy(&m->sid, &sid_mem[i]);
220 m->name = talloc_move(r->out.members->principals, &names[i]);
221 m->type = (enum lsa_SidType)name_types[i];
224 return NT_STATUS_OK;
227 NTSTATUS _wbint_QueryUserList(struct pipes_struct *p,
228 struct wbint_QueryUserList *r)
230 struct winbindd_domain *domain = wb_child_domain();
232 if (domain == NULL) {
233 return NT_STATUS_REQUEST_NOT_ACCEPTED;
236 return domain->methods->query_user_list(
237 domain, p->mem_ctx, &r->out.users->num_userinfos,
238 &r->out.users->userinfos);
241 NTSTATUS _wbint_QueryGroupList(struct pipes_struct *p,
242 struct wbint_QueryGroupList *r)
244 struct winbindd_domain *domain = wb_child_domain();
245 uint32_t i, num_groups;
246 struct acct_info *groups;
247 struct wbint_Principal *result;
248 NTSTATUS status;
250 if (domain == NULL) {
251 return NT_STATUS_REQUEST_NOT_ACCEPTED;
254 status = domain->methods->enum_dom_groups(domain, talloc_tos(),
255 &num_groups, &groups);
256 if (!NT_STATUS_IS_OK(status)) {
257 return status;
260 result = talloc_array(r->out.groups, struct wbint_Principal,
261 num_groups);
262 if (result == NULL) {
263 return NT_STATUS_NO_MEMORY;
266 for (i=0; i<num_groups; i++) {
267 sid_compose(&result[i].sid, &domain->sid, groups[i].rid);
268 result[i].type = SID_NAME_DOM_GRP;
269 result[i].name = talloc_strdup(result, groups[i].acct_name);
270 if (result[i].name == NULL) {
271 TALLOC_FREE(result);
272 TALLOC_FREE(groups);
273 return NT_STATUS_NO_MEMORY;
277 r->out.groups->num_principals = num_groups;
278 r->out.groups->principals = result;
280 TALLOC_FREE(groups);
281 return NT_STATUS_OK;
284 NTSTATUS _wbint_DsGetDcName(struct pipes_struct *p, struct wbint_DsGetDcName *r)
286 struct winbindd_domain *domain = wb_child_domain();
287 struct rpc_pipe_client *netlogon_pipe;
288 struct netr_DsRGetDCNameInfo *dc_info;
289 NTSTATUS status;
290 WERROR werr;
291 unsigned int orig_timeout;
293 if (domain == NULL) {
294 return dsgetdcname(p->mem_ctx, winbind_messaging_context(),
295 r->in.domain_name, r->in.domain_guid,
296 r->in.site_name ? r->in.site_name : "",
297 r->in.flags,
298 r->out.dc_info);
301 status = cm_connect_netlogon(domain, &netlogon_pipe);
303 if (!NT_STATUS_IS_OK(status)) {
304 DEBUG(10, ("Can't contact the NETLOGON pipe\n"));
305 return status;
308 /* This call can take a long time - allow the server to time out.
309 35 seconds should do it. */
311 orig_timeout = rpccli_set_timeout(netlogon_pipe, 35000);
313 if (domain->active_directory) {
314 status = rpccli_netr_DsRGetDCName(
315 netlogon_pipe, p->mem_ctx, domain->dcname,
316 r->in.domain_name, NULL, r->in.domain_guid,
317 r->in.flags, r->out.dc_info, &werr);
318 if (NT_STATUS_IS_OK(status) && W_ERROR_IS_OK(werr)) {
319 goto done;
324 * Fallback to less capable methods
327 dc_info = talloc_zero(r->out.dc_info, struct netr_DsRGetDCNameInfo);
328 if (dc_info == NULL) {
329 status = NT_STATUS_NO_MEMORY;
330 goto done;
333 if (r->in.flags & DS_PDC_REQUIRED) {
334 status = rpccli_netr_GetDcName(
335 netlogon_pipe, p->mem_ctx, domain->dcname,
336 r->in.domain_name, &dc_info->dc_unc, &werr);
337 } else {
338 status = rpccli_netr_GetAnyDCName(
339 netlogon_pipe, p->mem_ctx, domain->dcname,
340 r->in.domain_name, &dc_info->dc_unc, &werr);
343 if (!NT_STATUS_IS_OK(status)) {
344 DEBUG(10, ("rpccli_netr_Get[Any]DCName failed: %s\n",
345 nt_errstr(status)));
346 goto done;
348 if (!W_ERROR_IS_OK(werr)) {
349 DEBUG(10, ("rpccli_netr_Get[Any]DCName failed: %s\n",
350 win_errstr(werr)));
351 status = werror_to_ntstatus(werr);
352 goto done;
355 *r->out.dc_info = dc_info;
356 status = NT_STATUS_OK;
358 done:
359 /* And restore our original timeout. */
360 rpccli_set_timeout(netlogon_pipe, orig_timeout);
362 return status;
365 NTSTATUS _wbint_LookupRids(struct pipes_struct *p, struct wbint_LookupRids *r)
367 struct winbindd_domain *domain = wb_child_domain();
368 char *domain_name;
369 char **names;
370 enum lsa_SidType *types;
371 struct wbint_Principal *result;
372 NTSTATUS status;
373 int i;
375 if (domain == NULL) {
376 return NT_STATUS_REQUEST_NOT_ACCEPTED;
379 status = domain->methods->rids_to_names(
380 domain, talloc_tos(), &domain->sid, r->in.rids->rids,
381 r->in.rids->num_rids, &domain_name, &names, &types);
382 if (!NT_STATUS_IS_OK(status)) {
383 return status;
386 result = talloc_array(p->mem_ctx, struct wbint_Principal,
387 r->in.rids->num_rids);
388 if (result == NULL) {
389 return NT_STATUS_NO_MEMORY;
392 for (i=0; i<r->in.rids->num_rids; i++) {
393 sid_compose(&result[i].sid, &domain->sid, r->in.rids->rids[i]);
394 result[i].type = types[i];
395 result[i].name = talloc_move(result, &names[i]);
397 TALLOC_FREE(types);
398 TALLOC_FREE(names);
400 r->out.names->num_principals = r->in.rids->num_rids;
401 r->out.names->principals = result;
402 return NT_STATUS_OK;
405 NTSTATUS _wbint_CheckMachineAccount(struct pipes_struct *p,
406 struct wbint_CheckMachineAccount *r)
408 struct winbindd_domain *domain;
409 int num_retries = 0;
410 NTSTATUS status;
412 domain = wb_child_domain();
413 if (domain == NULL) {
414 return NT_STATUS_REQUEST_NOT_ACCEPTED;
417 again:
418 invalidate_cm_connection(&domain->conn);
421 struct rpc_pipe_client *netlogon_pipe;
422 status = cm_connect_netlogon(domain, &netlogon_pipe);
425 /* There is a race condition between fetching the trust account
426 password and the periodic machine password change. So it's
427 possible that the trust account password has been changed on us.
428 We are returned NT_STATUS_ACCESS_DENIED if this happens. */
430 #define MAX_RETRIES 3
432 if ((num_retries < MAX_RETRIES)
433 && NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
434 num_retries++;
435 goto again;
438 if (!NT_STATUS_IS_OK(status)) {
439 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
440 goto done;
443 /* Pass back result code - zero for success, other values for
444 specific failures. */
446 DEBUG(3,("domain %s secret is %s\n", domain->name,
447 NT_STATUS_IS_OK(status) ? "good" : "bad"));
449 done:
450 DEBUG(NT_STATUS_IS_OK(status) ? 5 : 2,
451 ("Checking the trust account password for domain %s returned %s\n",
452 domain->name, nt_errstr(status)));
454 return status;
457 NTSTATUS _wbint_ChangeMachineAccount(struct pipes_struct *p,
458 struct wbint_ChangeMachineAccount *r)
460 struct winbindd_domain *domain;
461 int num_retries = 0;
462 NTSTATUS status;
463 struct rpc_pipe_client *netlogon_pipe;
464 TALLOC_CTX *tmp_ctx;
466 again:
467 domain = wb_child_domain();
468 if (domain == NULL) {
469 return NT_STATUS_REQUEST_NOT_ACCEPTED;
472 invalidate_cm_connection(&domain->conn);
475 status = cm_connect_netlogon(domain, &netlogon_pipe);
478 /* There is a race condition between fetching the trust account
479 password and the periodic machine password change. So it's
480 possible that the trust account password has been changed on us.
481 We are returned NT_STATUS_ACCESS_DENIED if this happens. */
483 #define MAX_RETRIES 3
485 if ((num_retries < MAX_RETRIES)
486 && NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
487 num_retries++;
488 goto again;
491 if (!NT_STATUS_IS_OK(status)) {
492 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
493 goto done;
496 tmp_ctx = talloc_new(p->mem_ctx);
498 status = trust_pw_find_change_and_store_it(netlogon_pipe,
499 tmp_ctx,
500 domain->name);
501 talloc_destroy(tmp_ctx);
503 /* Pass back result code - zero for success, other values for
504 specific failures. */
506 DEBUG(3,("domain %s secret %s\n", domain->name,
507 NT_STATUS_IS_OK(status) ? "changed" : "unchanged"));
509 done:
510 DEBUG(NT_STATUS_IS_OK(status) ? 5 : 2,
511 ("Changing the trust account password for domain %s returned %s\n",
512 domain->name, nt_errstr(status)));
514 return status;
517 NTSTATUS _wbint_PingDc(struct pipes_struct *p, struct wbint_PingDc *r)
519 NTSTATUS status;
520 struct winbindd_domain *domain;
521 struct rpc_pipe_client *netlogon_pipe;
522 union netr_CONTROL_QUERY_INFORMATION info;
523 WERROR werr;
524 fstring logon_server;
526 domain = wb_child_domain();
527 if (domain == NULL) {
528 return NT_STATUS_REQUEST_NOT_ACCEPTED;
531 status = cm_connect_netlogon(domain, &netlogon_pipe);
532 if (!NT_STATUS_IS_OK(status)) {
533 DEBUG(3, ("could not open handle to NETLOGON pipe\n"));
534 return status;
537 fstr_sprintf(logon_server, "\\\\%s", domain->dcname);
540 * This provokes a WERR_NOT_SUPPORTED error message. This is
541 * documented in the wspp docs. I could not get a successful
542 * call to work, but the main point here is testing that the
543 * netlogon pipe works.
545 status = rpccli_netr_LogonControl(netlogon_pipe, p->mem_ctx,
546 logon_server, NETLOGON_CONTROL_QUERY,
547 2, &info, &werr);
549 if (NT_STATUS_EQUAL(status, NT_STATUS_IO_TIMEOUT)) {
550 DEBUG(2, ("rpccli_netr_LogonControl timed out\n"));
551 invalidate_cm_connection(&domain->conn);
552 return status;
555 if (!NT_STATUS_EQUAL(status, NT_STATUS_CTL_FILE_NOT_SUPPORTED)) {
556 DEBUG(2, ("rpccli_netr_LogonControl returned %s, expected "
557 "NT_STATUS_CTL_FILE_NOT_SUPPORTED\n",
558 nt_errstr(status)));
559 return status;
562 DEBUG(5, ("winbindd_dual_ping_dc succeeded\n"));
563 return NT_STATUS_OK;
566 NTSTATUS _wbint_SetMapping(struct pipes_struct *p, struct wbint_SetMapping *r)
568 struct id_map map;
570 map.sid = r->in.sid;
571 map.xid.id = r->in.id;
572 map.status = ID_MAPPED;
574 switch (r->in.type) {
575 case WBINT_ID_TYPE_UID:
576 map.xid.type = ID_TYPE_UID;
577 break;
578 case WBINT_ID_TYPE_GID:
579 map.xid.type = ID_TYPE_GID;
580 break;
581 default:
582 return NT_STATUS_INVALID_PARAMETER;
585 return idmap_set_mapping(&map);
588 NTSTATUS _wbint_RemoveMapping(struct pipes_struct *p,
589 struct wbint_RemoveMapping *r)
591 struct id_map map;
593 map.sid = r->in.sid;
594 map.xid.id = r->in.id;
595 map.status = ID_MAPPED;
597 switch (r->in.type) {
598 case WBINT_ID_TYPE_UID:
599 map.xid.type = ID_TYPE_UID;
600 break;
601 case WBINT_ID_TYPE_GID:
602 map.xid.type = ID_TYPE_GID;
603 break;
604 default:
605 return NT_STATUS_INVALID_PARAMETER;
608 return idmap_remove_mapping(&map);
611 NTSTATUS _wbint_SetHWM(struct pipes_struct *p, struct wbint_SetHWM *r)
613 struct unixid id;
614 NTSTATUS status;
616 id.id = r->in.id;
618 switch (r->in.type) {
619 case WBINT_ID_TYPE_UID:
620 id.type = ID_TYPE_UID;
621 status = idmap_set_uid_hwm(&id);
622 break;
623 case WBINT_ID_TYPE_GID:
624 id.type = ID_TYPE_GID;
625 status = idmap_set_gid_hwm(&id);
626 break;
627 default:
628 status = NT_STATUS_INVALID_PARAMETER;
629 break;
631 return status;