winbindd: force netlogon reauth for certain errors in reset_cm_connection_on_error()
[Samba.git] / source3 / winbindd / winbindd_util.c
blob9973c78d00f2a68bb295d6a1a80c43deb4fd862b
1 /*
2 Unix SMB/CIFS implementation.
4 Winbind daemon for ntdom nss module
6 Copyright (C) Tim Potter 2000-2001
7 Copyright (C) 2001 by Martin Pool <mbp@samba.org>
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.h"
25 #include "lib/util_unixsids.h"
26 #include "secrets.h"
27 #include "../libcli/security/security.h"
28 #include "../libcli/auth/pam_errors.h"
29 #include "passdb/machine_sid.h"
30 #include "passdb.h"
31 #include "source4/lib/messaging/messaging.h"
32 #include "librpc/gen_ndr/ndr_lsa.h"
33 #include "librpc/gen_ndr/ndr_drsblobs.h"
34 #include "auth/credentials/credentials.h"
35 #include "libsmb/samlogon_cache.h"
37 #undef DBGC_CLASS
38 #define DBGC_CLASS DBGC_WINBIND
40 /**
41 * @file winbindd_util.c
43 * Winbind daemon for NT domain authentication nss module.
44 **/
46 static bool add_trusted_domains_dc(void);
48 /* The list of trusted domains. Note that the list can be deleted and
49 recreated using the init_domain_list() function so pointers to
50 individual winbindd_domain structures cannot be made. Keep a copy of
51 the domain name instead. */
53 static struct winbindd_domain *_domain_list = NULL;
55 struct winbindd_domain *domain_list(void)
57 /* Initialise list */
59 if ((!_domain_list) && (!init_domain_list())) {
60 smb_panic("Init_domain_list failed");
63 return _domain_list;
66 /* Free all entries in the trusted domain list */
68 static void free_domain_list(void)
70 struct winbindd_domain *domain = _domain_list;
72 while(domain) {
73 struct winbindd_domain *next = domain->next;
75 DLIST_REMOVE(_domain_list, domain);
76 TALLOC_FREE(domain);
77 domain = next;
81 /**
82 * Iterator for winbindd's domain list.
83 * To be used (e.g.) in tevent based loops.
85 struct winbindd_domain *wb_next_domain(struct winbindd_domain *domain)
87 if (domain == NULL) {
88 domain = domain_list();
89 } else {
90 domain = domain->next;
93 if ((domain != NULL) &&
94 (lp_server_role() != ROLE_ACTIVE_DIRECTORY_DC) &&
95 sid_check_is_our_sam(&domain->sid))
97 domain = domain->next;
100 return domain;
103 static bool is_internal_domain(const struct dom_sid *sid)
105 if (sid == NULL)
106 return False;
108 return (sid_check_is_our_sam(sid) || sid_check_is_builtin(sid));
111 static bool is_in_internal_domain(const struct dom_sid *sid)
113 if (sid == NULL)
114 return False;
116 return (sid_check_is_in_our_sam(sid) || sid_check_is_in_builtin(sid));
120 /* Add a trusted domain to our list of domains.
121 If the domain already exists in the list,
122 return it and don't re-initialize. */
124 static NTSTATUS add_trusted_domain(const char *domain_name,
125 const char *dns_name,
126 const struct dom_sid *sid,
127 uint32_t trust_type,
128 uint32_t trust_flags,
129 uint32_t trust_attribs,
130 enum netr_SchannelType secure_channel_type,
131 struct winbindd_domain *routing_domain,
132 struct winbindd_domain **_d)
134 struct winbindd_domain *domain = NULL;
135 const char **ignored_domains = NULL;
136 const char **dom = NULL;
137 int role = lp_server_role();
139 if (is_null_sid(sid)) {
140 DBG_ERR("Got null SID for domain [%s]\n", domain_name);
141 return NT_STATUS_INVALID_PARAMETER;
144 ignored_domains = lp_parm_string_list(-1, "winbind", "ignore domains", NULL);
145 for (dom=ignored_domains; dom && *dom; dom++) {
146 if (gen_fnmatch(*dom, domain_name) == 0) {
147 DEBUG(2,("Ignoring domain '%s'\n", domain_name));
148 return NT_STATUS_NO_SUCH_DOMAIN;
153 * We can't call domain_list() as this function is called from
154 * init_domain_list() and we'll get stuck in a loop.
156 for (domain = _domain_list; domain; domain = domain->next) {
157 if (strequal(domain_name, domain->name)) {
158 break;
162 if (domain != NULL) {
163 struct winbindd_domain *check_domain = NULL;
165 for (check_domain = _domain_list;
166 check_domain != NULL;
167 check_domain = check_domain->next)
169 if (check_domain == domain) {
170 continue;
173 if (dom_sid_equal(&check_domain->sid, sid)) {
174 break;
178 if (check_domain != NULL) {
179 DBG_ERR("SID [%s] already used by domain [%s], "
180 "expected [%s]\n",
181 sid_string_dbg(sid), check_domain->name,
182 domain->name);
183 return NT_STATUS_INVALID_PARAMETER;
187 if ((domain != NULL) && (dns_name != NULL)) {
188 struct winbindd_domain *check_domain = NULL;
190 for (check_domain = _domain_list;
191 check_domain != NULL;
192 check_domain = check_domain->next)
194 if (check_domain == domain) {
195 continue;
198 if (strequal(check_domain->alt_name, dns_name)) {
199 break;
203 if (check_domain != NULL) {
204 DBG_ERR("DNS name [%s] used by domain [%s], "
205 "expected [%s]\n",
206 dns_name, check_domain->name,
207 domain->name);
208 return NT_STATUS_INVALID_PARAMETER;
212 if (domain != NULL) {
213 *_d = domain;
214 return NT_STATUS_OK;
217 /* Create new domain entry */
218 domain = talloc_zero(NULL, struct winbindd_domain);
219 if (domain == NULL) {
220 return NT_STATUS_NO_MEMORY;
223 domain->children = talloc_zero_array(domain,
224 struct winbindd_child,
225 lp_winbind_max_domain_connections());
226 if (domain->children == NULL) {
227 TALLOC_FREE(domain);
228 return NT_STATUS_NO_MEMORY;
231 domain->queue = tevent_queue_create(domain, "winbind_domain");
232 if (domain->queue == NULL) {
233 TALLOC_FREE(domain);
234 return NT_STATUS_NO_MEMORY;
237 domain->binding_handle = wbint_binding_handle(domain, domain, NULL);
238 if (domain->binding_handle == NULL) {
239 TALLOC_FREE(domain);
240 return NT_STATUS_NO_MEMORY;
243 domain->name = talloc_strdup(domain, domain_name);
244 if (domain->name == NULL) {
245 TALLOC_FREE(domain);
246 return NT_STATUS_NO_MEMORY;
249 if (dns_name != NULL) {
250 domain->alt_name = talloc_strdup(domain, dns_name);
251 if (domain->alt_name == NULL) {
252 TALLOC_FREE(domain);
253 return NT_STATUS_NO_MEMORY;
257 domain->backend = NULL;
258 domain->internal = is_internal_domain(sid);
259 domain->secure_channel_type = secure_channel_type;
260 domain->sequence_number = DOM_SEQUENCE_NONE;
261 domain->last_seq_check = 0;
262 domain->initialized = false;
263 domain->online = is_internal_domain(sid);
264 domain->check_online_timeout = 0;
265 domain->dc_probe_pid = (pid_t)-1;
266 domain->domain_flags = trust_flags;
267 domain->domain_type = trust_type;
268 domain->domain_trust_attribs = trust_attribs;
269 domain->secure_channel_type = secure_channel_type;
270 domain->routing_domain = routing_domain;
271 sid_copy(&domain->sid, sid);
273 /* Is this our primary domain ? */
274 if (role == ROLE_DOMAIN_MEMBER) {
275 domain->primary = strequal(domain_name, lp_workgroup());
276 } else {
277 domain->primary = strequal(domain_name, get_global_sam_name());
280 if (domain->primary) {
281 if (role == ROLE_ACTIVE_DIRECTORY_DC) {
282 domain->active_directory = true;
284 if (lp_security() == SEC_ADS) {
285 domain->active_directory = true;
287 } else if (!domain->internal) {
288 if (domain->domain_type == LSA_TRUST_TYPE_UPLEVEL) {
289 domain->active_directory = true;
293 domain->can_do_ncacn_ip_tcp = domain->active_directory;
295 /* Link to domain list */
296 DLIST_ADD_END(_domain_list, domain);
298 wcache_tdc_add_domain( domain );
300 setup_domain_child(domain);
302 DBG_NOTICE("Added domain [%s] [%s] [%s]\n",
303 domain->name, domain->alt_name,
304 sid_string_dbg(&domain->sid));
306 *_d = domain;
307 return NT_STATUS_OK;
310 bool set_routing_domain(struct winbindd_domain *domain,
311 struct winbindd_domain *routing_domain)
313 if (domain->routing_domain == NULL) {
314 domain->routing_domain = routing_domain;
315 return true;
317 if (domain->routing_domain != routing_domain) {
318 return false;
320 return true;
323 bool add_trusted_domain_from_auth(uint16_t validation_level,
324 struct info3_text *info3,
325 struct info6_text *info6)
327 struct winbindd_domain *domain = NULL;
328 struct dom_sid domain_sid;
329 const char *dns_domainname = NULL;
330 NTSTATUS status;
331 bool ok;
334 * We got a successfull auth from a domain that might not yet be in our
335 * domain list. If we're a member we trust our DC who authenticated the
336 * user from that domain and add the domain to our list on-the-fly. If
337 * we're a DC we rely on configured trusts and don't add on-the-fly.
340 if (IS_DC) {
341 return true;
344 ok = dom_sid_parse(info3->dom_sid, &domain_sid);
345 if (!ok) {
346 DBG_NOTICE("dom_sid_parse [%s] failed\n", info3->dom_sid);
347 return false;
350 if (validation_level == 6) {
351 if (!strequal(info6->dns_domainname, "")) {
352 dns_domainname = info6->dns_domainname;
356 status = add_trusted_domain(info3->logon_dom,
357 dns_domainname,
358 &domain_sid,
360 NETR_TRUST_FLAG_OUTBOUND,
362 SEC_CHAN_NULL,
363 find_default_route_domain(),
364 &domain);
365 if (!NT_STATUS_IS_OK(status) &&
366 !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
368 DBG_DEBUG("Adding domain [%s] with sid [%s] failed\n",
369 info3->logon_dom, info3->dom_sid);
370 return false;
373 return true;
376 bool domain_is_forest_root(const struct winbindd_domain *domain)
378 const uint32_t fr_flags =
379 (NETR_TRUST_FLAG_TREEROOT|NETR_TRUST_FLAG_IN_FOREST);
381 return ((domain->domain_flags & fr_flags) == fr_flags);
384 /********************************************************************
385 rescan our domains looking for new trusted domains
386 ********************************************************************/
388 struct trustdom_state {
389 struct winbindd_domain *domain;
390 struct winbindd_request request;
393 static void trustdom_list_done(struct tevent_req *req);
394 static void rescan_forest_root_trusts( void );
395 static void rescan_forest_trusts( void );
397 static void add_trusted_domains( struct winbindd_domain *domain )
399 struct trustdom_state *state;
400 struct tevent_req *req;
402 state = talloc_zero(NULL, struct trustdom_state);
403 if (state == NULL) {
404 DEBUG(0, ("talloc failed\n"));
405 return;
407 state->domain = domain;
409 state->request.length = sizeof(state->request);
410 state->request.cmd = WINBINDD_LIST_TRUSTDOM;
412 req = wb_domain_request_send(state, server_event_context(),
413 domain, &state->request);
414 if (req == NULL) {
415 DEBUG(1, ("wb_domain_request_send failed\n"));
416 TALLOC_FREE(state);
417 return;
419 tevent_req_set_callback(req, trustdom_list_done, state);
422 static void trustdom_list_done(struct tevent_req *req)
424 struct trustdom_state *state = tevent_req_callback_data(
425 req, struct trustdom_state);
426 struct winbindd_response *response;
427 int res, err;
428 char *p;
429 ptrdiff_t extra_len;
430 bool within_forest = false;
431 NTSTATUS status;
434 * Only when we enumerate our primary domain
435 * or our forest root domain, we should keep
436 * the NETR_TRUST_FLAG_IN_FOREST flag, in
437 * all other cases we need to clear it as the domain
438 * is not part of our forest.
440 if (state->domain->primary) {
441 within_forest = true;
442 } else if (domain_is_forest_root(state->domain)) {
443 within_forest = true;
446 res = wb_domain_request_recv(req, state, &response, &err);
447 if ((res == -1) || (response->result != WINBINDD_OK)) {
448 DBG_WARNING("Could not receive trusts for domain %s\n",
449 state->domain->name);
450 TALLOC_FREE(state);
451 return;
454 if (response->length < sizeof(struct winbindd_response)) {
455 DBG_ERR("ill-formed trustdom response - short length\n");
456 TALLOC_FREE(state);
457 return;
460 extra_len = response->length - sizeof(struct winbindd_response);
462 p = (char *)response->extra_data.data;
464 while ((p - (char *)response->extra_data.data) < extra_len) {
465 struct winbindd_domain *domain = NULL;
466 char *name, *q, *sidstr, *alt_name;
467 struct dom_sid sid;
468 uint32_t trust_type;
469 uint32_t trust_attribs;
470 uint32_t trust_flags;
472 DBG_DEBUG("parsing response line '%s'\n", p);
474 name = p;
476 alt_name = strchr(p, '\\');
477 if (alt_name == NULL) {
478 DBG_ERR("Got invalid trustdom response\n");
479 break;
482 *alt_name = '\0';
483 alt_name += 1;
485 sidstr = strchr(alt_name, '\\');
486 if (sidstr == NULL) {
487 DBG_ERR("Got invalid trustdom response\n");
488 break;
491 *sidstr = '\0';
492 sidstr += 1;
494 /* use the real alt_name if we have one, else pass in NULL */
495 if (strequal(alt_name, "(null)")) {
496 alt_name = NULL;
499 q = strtok(sidstr, "\\");
500 if (q == NULL) {
501 DBG_ERR("Got invalid trustdom response\n");
502 break;
505 if (!string_to_sid(&sid, sidstr)) {
506 DEBUG(0, ("Got invalid trustdom response\n"));
507 break;
510 q = strtok(NULL, "\\");
511 if (q == NULL) {
512 DBG_ERR("Got invalid trustdom response\n");
513 break;
516 trust_flags = (uint32_t)strtoul(q, NULL, 10);
518 q = strtok(NULL, "\\");
519 if (q == NULL) {
520 DBG_ERR("Got invalid trustdom response\n");
521 break;
524 trust_type = (uint32_t)strtoul(q, NULL, 10);
526 q = strtok(NULL, "\n");
527 if (q == NULL) {
528 DBG_ERR("Got invalid trustdom response\n");
529 break;
532 trust_attribs = (uint32_t)strtoul(q, NULL, 10);
534 if (!within_forest) {
535 trust_flags &= ~NETR_TRUST_FLAG_IN_FOREST;
538 if (!state->domain->primary) {
539 trust_flags &= ~NETR_TRUST_FLAG_PRIMARY;
543 * We always call add_trusted_domain() cause on an existing
544 * domain structure, it will update the SID if necessary.
545 * This is important because we need the SID for sibling
546 * domains.
548 status = add_trusted_domain(name,
549 alt_name,
550 &sid,
551 trust_type,
552 trust_flags,
553 trust_attribs,
554 SEC_CHAN_NULL,
555 find_default_route_domain(),
556 &domain);
557 if (!NT_STATUS_IS_OK(status) &&
558 !NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
560 DBG_NOTICE("add_trusted_domain returned %s\n",
561 nt_errstr(status));
562 return;
565 p = q + strlen(q) + 1;
569 Cases to consider when scanning trusts:
570 (a) we are calling from a child domain (primary && !forest_root)
571 (b) we are calling from the root of the forest (primary && forest_root)
572 (c) we are calling from a trusted forest domain (!primary
573 && !forest_root)
576 if (state->domain->primary) {
577 /* If this is our primary domain and we are not in the
578 forest root, we have to scan the root trusts first */
580 if (!domain_is_forest_root(state->domain))
581 rescan_forest_root_trusts();
582 else
583 rescan_forest_trusts();
585 } else if (domain_is_forest_root(state->domain)) {
586 /* Once we have done root forest trust search, we can
587 go on to search the trusted forests */
589 rescan_forest_trusts();
592 TALLOC_FREE(state);
594 return;
597 /********************************************************************
598 Scan the trusts of our forest root
599 ********************************************************************/
601 static void rescan_forest_root_trusts( void )
603 struct winbindd_tdc_domain *dom_list = NULL;
604 size_t num_trusts = 0;
605 int i;
606 NTSTATUS status;
608 /* The only transitive trusts supported by Windows 2003 AD are
609 (a) Parent-Child, (b) Tree-Root, and (c) Forest. The
610 first two are handled in forest and listed by
611 DsEnumerateDomainTrusts(). Forest trusts are not so we
612 have to do that ourselves. */
614 if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
615 return;
617 for ( i=0; i<num_trusts; i++ ) {
618 struct winbindd_domain *d = NULL;
620 /* Find the forest root. Don't necessarily trust
621 the domain_list() as our primary domain may not
622 have been initialized. */
624 if ( !(dom_list[i].trust_flags & NETR_TRUST_FLAG_TREEROOT) ) {
625 continue;
628 /* Here's the forest root */
630 d = find_domain_from_name_noinit( dom_list[i].domain_name );
631 if (d == NULL) {
632 status = add_trusted_domain(dom_list[i].domain_name,
633 dom_list[i].dns_name,
634 &dom_list[i].sid,
635 dom_list[i].trust_type,
636 dom_list[i].trust_flags,
637 dom_list[i].trust_attribs,
638 SEC_CHAN_NULL,
639 find_default_route_domain(),
640 &d);
642 if (!NT_STATUS_IS_OK(status) &&
643 NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_DOMAIN))
645 DBG_ERR("add_trusted_domain returned %s\n",
646 nt_errstr(status));
647 return;
650 if (d == NULL) {
651 continue;
654 DEBUG(10,("rescan_forest_root_trusts: Following trust path "
655 "for domain tree root %s (%s)\n",
656 d->name, d->alt_name ));
658 d->domain_flags = dom_list[i].trust_flags;
659 d->domain_type = dom_list[i].trust_type;
660 d->domain_trust_attribs = dom_list[i].trust_attribs;
662 add_trusted_domains( d );
664 break;
667 TALLOC_FREE( dom_list );
669 return;
672 /********************************************************************
673 scan the transitive forest trusts (not our own)
674 ********************************************************************/
677 static void rescan_forest_trusts( void )
679 struct winbindd_domain *d = NULL;
680 struct winbindd_tdc_domain *dom_list = NULL;
681 size_t num_trusts = 0;
682 int i;
683 NTSTATUS status;
685 /* The only transitive trusts supported by Windows 2003 AD are
686 (a) Parent-Child, (b) Tree-Root, and (c) Forest. The
687 first two are handled in forest and listed by
688 DsEnumerateDomainTrusts(). Forest trusts are not so we
689 have to do that ourselves. */
691 if ( !wcache_tdc_fetch_list( &dom_list, &num_trusts ) )
692 return;
694 for ( i=0; i<num_trusts; i++ ) {
695 uint32_t flags = dom_list[i].trust_flags;
696 uint32_t type = dom_list[i].trust_type;
697 uint32_t attribs = dom_list[i].trust_attribs;
699 d = find_domain_from_name_noinit( dom_list[i].domain_name );
701 /* ignore our primary and internal domains */
703 if ( d && (d->internal || d->primary ) )
704 continue;
706 if ( (flags & NETR_TRUST_FLAG_INBOUND) &&
707 (type == LSA_TRUST_TYPE_UPLEVEL) &&
708 (attribs == LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) )
710 /* add the trusted domain if we don't know
711 about it */
713 if (d == NULL) {
714 status = add_trusted_domain(
715 dom_list[i].domain_name,
716 dom_list[i].dns_name,
717 &dom_list[i].sid,
718 type,
719 flags,
720 attribs,
721 SEC_CHAN_NULL,
722 find_default_route_domain(),
723 &d);
724 if (!NT_STATUS_IS_OK(status) &&
725 NT_STATUS_EQUAL(status,
726 NT_STATUS_NO_SUCH_DOMAIN))
728 DBG_ERR("add_trusted_domain: %s\n",
729 nt_errstr(status));
730 return;
734 if (d == NULL) {
735 continue;
738 DEBUG(10,("Following trust path for domain %s (%s)\n",
739 d->name, d->alt_name ));
740 add_trusted_domains( d );
744 TALLOC_FREE( dom_list );
746 return;
749 /*********************************************************************
750 The process of updating the trusted domain list is a three step
751 async process:
752 (a) ask our domain
753 (b) ask the root domain in our forest
754 (c) ask the a DC in any Win2003 trusted forests
755 *********************************************************************/
757 void rescan_trusted_domains(struct tevent_context *ev, struct tevent_timer *te,
758 struct timeval now, void *private_data)
760 TALLOC_FREE(te);
762 /* I use to clear the cache here and start over but that
763 caused problems in child processes that needed the
764 trust dom list early on. Removing it means we
765 could have some trusted domains listed that have been
766 removed from our primary domain's DC until a full
767 restart. This should be ok since I think this is what
768 Windows does as well. */
770 /* this will only add new domains we didn't already know about
771 in the domain_list()*/
773 add_trusted_domains( find_our_domain() );
775 te = tevent_add_timer(
776 ev, NULL, timeval_current_ofs(WINBINDD_RESCAN_FREQ, 0),
777 rescan_trusted_domains, NULL);
779 * If te == NULL, there's not much we can do here. Don't fail, the
780 * only thing we miss is new trusted domains.
783 return;
786 enum winbindd_result winbindd_dual_init_connection(struct winbindd_domain *domain,
787 struct winbindd_cli_state *state)
789 /* Ensure null termination */
790 state->request->domain_name
791 [sizeof(state->request->domain_name)-1]='\0';
792 state->request->data.init_conn.dcname
793 [sizeof(state->request->data.init_conn.dcname)-1]='\0';
795 if (strlen(state->request->data.init_conn.dcname) > 0) {
796 TALLOC_FREE(domain->dcname);
797 domain->dcname = talloc_strdup(domain,
798 state->request->data.init_conn.dcname);
799 if (domain->dcname == NULL) {
800 return WINBINDD_ERROR;
804 init_dc_connection(domain, false);
806 if (!domain->initialized) {
807 /* If we return error here we can't do any cached authentication,
808 but we may be in disconnected mode and can't initialize correctly.
809 Do what the previous code did and just return without initialization,
810 once we go online we'll re-initialize.
812 DEBUG(5, ("winbindd_dual_init_connection: %s returning without initialization "
813 "online = %d\n", domain->name, (int)domain->online ));
816 fstrcpy(state->response->data.domain_info.name, domain->name);
817 fstrcpy(state->response->data.domain_info.alt_name, domain->alt_name);
818 sid_to_fstring(state->response->data.domain_info.sid, &domain->sid);
820 state->response->data.domain_info.native_mode
821 = domain->native_mode;
822 state->response->data.domain_info.active_directory
823 = domain->active_directory;
824 state->response->data.domain_info.primary
825 = domain->primary;
827 return WINBINDD_OK;
830 static void wb_imsg_new_trusted_domain(struct imessaging_context *msg,
831 void *private_data,
832 uint32_t msg_type,
833 struct server_id server_id,
834 DATA_BLOB *data)
836 bool ok;
838 DBG_NOTICE("Rescanning trusted domains\n");
840 ok = add_trusted_domains_dc();
841 if (!ok) {
842 DBG_ERR("Failed to reload trusted domains\n");
847 * We did not get the secret when we queried secrets.tdb, so read it
848 * from secrets.tdb and re-sync the databases
850 static bool migrate_secrets_tdb_to_ldb(struct winbindd_domain *domain)
852 bool ok;
853 struct cli_credentials *creds;
854 NTSTATUS can_migrate = pdb_get_trust_credentials(domain->name,
855 NULL, domain, &creds);
856 if (!NT_STATUS_IS_OK(can_migrate)) {
857 DEBUG(0, ("Failed to fetch our own, local AD domain join "
858 "password for winbindd's internal use, both from "
859 "secrets.tdb and secrets.ldb: %s\n",
860 nt_errstr(can_migrate)));
861 return false;
865 * NOTE: It is very unlikely we end up here if there is an
866 * oldpass, because a new password is created at
867 * classicupgrade, so this is not a concern.
869 ok = secrets_store_machine_pw_sync(cli_credentials_get_password(creds),
870 NULL /* oldpass */,
871 cli_credentials_get_domain(creds),
872 cli_credentials_get_realm(creds),
873 cli_credentials_get_salt_principal(creds),
874 0, /* Supported enc types, unused */
875 &domain->sid,
876 cli_credentials_get_password_last_changed_time(creds),
877 cli_credentials_get_secure_channel_type(creds),
878 false /* do_delete: Do not delete */);
879 TALLOC_FREE(creds);
880 if (ok == false) {
881 DEBUG(0, ("Failed to write our our own, "
882 "local AD domain join password for "
883 "winbindd's internal use into secrets.tdb\n"));
884 return false;
886 return true;
889 static bool add_trusted_domains_dc(void)
891 struct winbindd_domain *domain = NULL;
892 struct pdb_trusted_domain **domains = NULL;
893 uint32_t num_domains = 0;
894 uint32_t i;
895 NTSTATUS status;
897 if (!(pdb_capabilities() & PDB_CAP_TRUSTED_DOMAINS_EX)) {
898 struct trustdom_info **ti = NULL;
900 status = pdb_enum_trusteddoms(talloc_tos(), &num_domains, &ti);
901 if (!NT_STATUS_IS_OK(status)) {
902 DBG_ERR("pdb_enum_trusteddoms() failed - %s\n",
903 nt_errstr(status));
904 return false;
907 for (i = 0; i < num_domains; i++) {
908 status = add_trusted_domain(ti[i]->name,
909 NULL,
910 &ti[i]->sid,
911 LSA_TRUST_TYPE_DOWNLEVEL,
912 NETR_TRUST_FLAG_OUTBOUND,
914 SEC_CHAN_DOMAIN,
915 NULL,
916 &domain);
917 if (!NT_STATUS_IS_OK(status)) {
918 DBG_NOTICE("add_trusted_domain returned %s\n",
919 nt_errstr(status));
920 return false;
923 /* Even in the parent winbindd we'll need to
924 talk to the DC, so try and see if we can
925 contact it. Theoretically this isn't neccessary
926 as the init_dc_connection() in init_child_recv()
927 will do this, but we can start detecting the DC
928 early here. */
929 set_domain_online_request(domain);
932 return true;
935 status = pdb_enum_trusted_domains(talloc_tos(), &num_domains, &domains);
936 if (!NT_STATUS_IS_OK(status)) {
937 DBG_ERR("pdb_enum_trusted_domains() failed - %s\n",
938 nt_errstr(status));
939 return false;
942 for (i = 0; i < num_domains; i++) {
943 enum netr_SchannelType sec_chan_type = SEC_CHAN_DOMAIN;
944 uint32_t trust_flags = 0;
946 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
947 sec_chan_type = SEC_CHAN_DNS_DOMAIN;
950 if (!(domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
951 sec_chan_type = SEC_CHAN_NULL;
954 if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
955 trust_flags |= NETR_TRUST_FLAG_INBOUND;
957 if (domains[i]->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
958 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
960 if (domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_WITHIN_FOREST) {
961 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
964 if (domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_CROSS_ORGANIZATION) {
966 * We don't support selective authentication yet.
968 DBG_WARNING("Ignoring CROSS_ORGANIZATION trust to "
969 "domain[%s/%s]\n",
970 domains[i]->netbios_name,
971 domains[i]->domain_name);
972 continue;
975 status = add_trusted_domain(domains[i]->netbios_name,
976 domains[i]->domain_name,
977 &domains[i]->security_identifier,
978 domains[i]->trust_type,
979 trust_flags,
980 domains[i]->trust_attributes,
981 sec_chan_type,
982 NULL,
983 &domain);
984 if (!NT_STATUS_IS_OK(status)) {
985 DBG_NOTICE("add_trusted_domain returned %s\n",
986 nt_errstr(status));
987 return false;
990 if (domains[i]->trust_type == LSA_TRUST_TYPE_UPLEVEL) {
991 domain->active_directory = true;
993 domain->domain_type = domains[i]->trust_type;
994 domain->domain_trust_attribs = domains[i]->trust_attributes;
996 if (sec_chan_type != SEC_CHAN_NULL) {
997 /* Even in the parent winbindd we'll need to
998 talk to the DC, so try and see if we can
999 contact it. Theoretically this isn't neccessary
1000 as the init_dc_connection() in init_child_recv()
1001 will do this, but we can start detecting the DC
1002 early here. */
1003 set_domain_online_request(domain);
1007 for (i = 0; i < num_domains; i++) {
1008 struct ForestTrustInfo fti;
1009 uint32_t fi;
1010 enum ndr_err_code ndr_err;
1011 struct winbindd_domain *routing_domain = NULL;
1013 if (domains[i]->trust_type != LSA_TRUST_TYPE_UPLEVEL) {
1014 continue;
1017 if (!(domains[i]->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
1018 continue;
1021 if (domains[i]->trust_forest_trust_info.length == 0) {
1022 continue;
1025 routing_domain = find_domain_from_name_noinit(
1026 domains[i]->netbios_name);
1027 if (routing_domain == NULL) {
1028 DBG_ERR("Can't find winbindd domain [%s]\n",
1029 domains[i]->netbios_name);
1030 return false;
1033 ndr_err = ndr_pull_struct_blob_all(
1034 &domains[i]->trust_forest_trust_info,
1035 talloc_tos(), &fti,
1036 (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
1037 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
1038 DBG_ERR("ndr_pull_ForestTrustInfo(%s) - %s\n",
1039 domains[i]->netbios_name,
1040 ndr_map_error2string(ndr_err));
1041 return false;
1044 for (fi = 0; fi < fti.count; fi++) {
1045 struct ForestTrustInfoRecord *rec =
1046 &fti.records[fi].record;
1047 struct ForestTrustDataDomainInfo *drec = NULL;
1049 if (rec->type != FOREST_TRUST_DOMAIN_INFO) {
1050 continue;
1052 drec = &rec->data.info;
1054 if (rec->flags & LSA_NB_DISABLED_MASK) {
1055 continue;
1058 if (rec->flags & LSA_SID_DISABLED_MASK) {
1059 continue;
1063 * TODO:
1064 * also try to find a matching
1065 * LSA_TLN_DISABLED_MASK ???
1068 domain = find_domain_from_name_noinit(drec->netbios_name.string);
1069 if (domain != NULL) {
1070 continue;
1073 status = add_trusted_domain(drec->netbios_name.string,
1074 drec->dns_name.string,
1075 &drec->sid,
1076 LSA_TRUST_TYPE_UPLEVEL,
1077 NETR_TRUST_FLAG_OUTBOUND,
1079 SEC_CHAN_NULL,
1080 routing_domain,
1081 &domain);
1082 if (!NT_STATUS_IS_OK(status)) {
1083 DBG_NOTICE("add_trusted_domain returned %s\n",
1084 nt_errstr(status));
1085 return false;
1087 if (domain == NULL) {
1088 continue;
1093 return true;
1097 /* Look up global info for the winbind daemon */
1098 bool init_domain_list(void)
1100 int role = lp_server_role();
1101 struct pdb_domain_info *pdb_domain_info = NULL;
1102 struct winbindd_domain *domain = NULL;
1103 NTSTATUS status;
1104 bool ok;
1106 /* Free existing list */
1107 free_domain_list();
1109 /* BUILTIN domain */
1111 status = add_trusted_domain("BUILTIN",
1112 NULL,
1113 &global_sid_Builtin,
1114 LSA_TRUST_TYPE_DOWNLEVEL,
1115 0, /* trust_flags */
1116 0, /* trust_attribs */
1117 SEC_CHAN_LOCAL,
1118 NULL,
1119 &domain);
1120 if (!NT_STATUS_IS_OK(status)) {
1121 DBG_ERR("add_trusted_domain BUILTIN returned %s\n",
1122 nt_errstr(status));
1123 return false;
1126 /* Local SAM */
1129 * In case the passdb backend is passdb_dsdb the domain SID comes from
1130 * dsdb, not from secrets.tdb. As we use the domain SID in various
1131 * places, we must ensure the domain SID is migrated from dsdb to
1132 * secrets.tdb before get_global_sam_sid() is called the first time.
1134 * The migration is done as part of the passdb_dsdb initialisation,
1135 * calling pdb_get_domain_info() triggers it.
1137 pdb_domain_info = pdb_get_domain_info(talloc_tos());
1139 if ( role == ROLE_ACTIVE_DIRECTORY_DC ) {
1140 uint32_t trust_flags;
1141 bool is_root;
1142 enum netr_SchannelType sec_chan_type;
1143 const char *account_name;
1144 struct samr_Password current_nt_hash;
1146 if (pdb_domain_info == NULL) {
1147 DEBUG(0, ("Failed to fetch our own, local AD "
1148 "domain info from sam.ldb\n"));
1149 return false;
1152 trust_flags = NETR_TRUST_FLAG_PRIMARY;
1153 trust_flags |= NETR_TRUST_FLAG_IN_FOREST;
1154 trust_flags |= NETR_TRUST_FLAG_NATIVE;
1155 trust_flags |= NETR_TRUST_FLAG_OUTBOUND;
1157 is_root = strequal(pdb_domain_info->dns_domain,
1158 pdb_domain_info->dns_forest);
1159 if (is_root) {
1160 trust_flags |= NETR_TRUST_FLAG_TREEROOT;
1163 status = add_trusted_domain(pdb_domain_info->name,
1164 pdb_domain_info->dns_domain,
1165 &pdb_domain_info->sid,
1166 LSA_TRUST_TYPE_UPLEVEL,
1167 trust_flags,
1168 LSA_TRUST_ATTRIBUTE_WITHIN_FOREST,
1169 SEC_CHAN_BDC,
1170 NULL,
1171 &domain);
1172 TALLOC_FREE(pdb_domain_info);
1173 if (!NT_STATUS_IS_OK(status)) {
1174 DBG_ERR("Failed to add our own, local AD "
1175 "domain to winbindd's internal list\n");
1176 return false;
1180 * We need to call this to find out if we are an RODC
1182 ok = get_trust_pw_hash(domain->name,
1183 current_nt_hash.hash,
1184 &account_name,
1185 &sec_chan_type);
1186 if (!ok) {
1188 * If get_trust_pw_hash() fails, then try and
1189 * fetch the password from the more recent of
1190 * secrets.{ldb,tdb} using the
1191 * pdb_get_trust_credentials()
1193 ok = migrate_secrets_tdb_to_ldb(domain);
1195 if (!ok) {
1196 DEBUG(0, ("Failed to migrate our own, "
1197 "local AD domain join password for "
1198 "winbindd's internal use into "
1199 "secrets.tdb\n"));
1200 return false;
1202 ok = get_trust_pw_hash(domain->name,
1203 current_nt_hash.hash,
1204 &account_name,
1205 &sec_chan_type);
1206 if (!ok) {
1207 DEBUG(0, ("Failed to find our our own, just "
1208 "written local AD domain join "
1209 "password for winbindd's internal "
1210 "use in secrets.tdb\n"));
1211 return false;
1215 domain->secure_channel_type = sec_chan_type;
1216 if (sec_chan_type == SEC_CHAN_RODC) {
1217 domain->rodc = true;
1220 } else {
1221 uint32_t trust_flags;
1222 enum netr_SchannelType secure_channel_type;
1224 trust_flags = NETR_TRUST_FLAG_OUTBOUND;
1225 if (role != ROLE_DOMAIN_MEMBER) {
1226 trust_flags |= NETR_TRUST_FLAG_PRIMARY;
1229 if (role > ROLE_DOMAIN_MEMBER) {
1230 secure_channel_type = SEC_CHAN_BDC;
1231 } else {
1232 secure_channel_type = SEC_CHAN_LOCAL;
1235 status = add_trusted_domain(get_global_sam_name(),
1236 NULL,
1237 get_global_sam_sid(),
1238 LSA_TRUST_TYPE_DOWNLEVEL,
1239 trust_flags,
1240 0, /* trust_attribs */
1241 secure_channel_type,
1242 NULL,
1243 &domain);
1244 if (!NT_STATUS_IS_OK(status)) {
1245 DBG_ERR("Failed to add local SAM to "
1246 "domain to winbindd's internal list\n");
1247 return false;
1251 if (IS_DC) {
1252 ok = add_trusted_domains_dc();
1253 if (!ok) {
1254 DBG_ERR("init_domain_list_dc failed\n");
1255 return false;
1259 if ( role == ROLE_DOMAIN_MEMBER ) {
1260 struct dom_sid our_sid;
1261 uint32_t trust_type;
1263 if (!secrets_fetch_domain_sid(lp_workgroup(), &our_sid)) {
1264 DEBUG(0, ("Could not fetch our SID - did we join?\n"));
1265 return False;
1268 if (lp_realm() != NULL) {
1269 trust_type = LSA_TRUST_TYPE_UPLEVEL;
1270 } else {
1271 trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1274 status = add_trusted_domain(lp_workgroup(),
1275 lp_realm(),
1276 &our_sid,
1277 trust_type,
1278 NETR_TRUST_FLAG_PRIMARY|
1279 NETR_TRUST_FLAG_OUTBOUND,
1280 0, /* trust_attribs */
1281 SEC_CHAN_WKSTA,
1282 NULL,
1283 &domain);
1284 if (!NT_STATUS_IS_OK(status)) {
1285 DBG_ERR("Failed to add local SAM to "
1286 "domain to winbindd's internal list\n");
1287 return false;
1289 /* Even in the parent winbindd we'll need to
1290 talk to the DC, so try and see if we can
1291 contact it. Theoretically this isn't neccessary
1292 as the init_dc_connection() in init_child_recv()
1293 will do this, but we can start detecting the DC
1294 early here. */
1295 set_domain_online_request(domain);
1299 status = imessaging_register(winbind_imessaging_context(), NULL,
1300 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS,
1301 wb_imsg_new_trusted_domain);
1302 if (!NT_STATUS_IS_OK(status)) {
1303 DBG_ERR("imessaging_register failed %s\n", nt_errstr(status));
1304 return false;
1307 return True;
1311 * Given a domain name, return the struct winbindd domain info for it
1313 * @note Do *not* pass lp_workgroup() to this function. domain_list
1314 * may modify it's value, and free that pointer. Instead, our local
1315 * domain may be found by calling find_our_domain().
1316 * directly.
1319 * @return The domain structure for the named domain, if it is working.
1322 struct winbindd_domain *find_domain_from_name_noinit(const char *domain_name)
1324 struct winbindd_domain *domain;
1326 /* Search through list */
1328 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1329 if (strequal(domain_name, domain->name)) {
1330 return domain;
1332 if (domain->alt_name == NULL) {
1333 continue;
1335 if (strequal(domain_name, domain->alt_name)) {
1336 return domain;
1340 /* Not found */
1342 return NULL;
1346 * Given a domain name, return the struct winbindd domain if it's a direct
1347 * outgoing trust
1349 * @return The domain structure for the named domain, if it is a direct outgoing trust
1351 struct winbindd_domain *find_trust_from_name_noinit(const char *domain_name)
1353 struct winbindd_domain *domain = NULL;
1355 domain = find_domain_from_name_noinit(domain_name);
1356 if (domain == NULL) {
1357 return NULL;
1360 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1361 return domain;
1364 return NULL;
1367 struct winbindd_domain *find_domain_from_name(const char *domain_name)
1369 struct winbindd_domain *domain;
1371 domain = find_domain_from_name_noinit(domain_name);
1373 if (domain == NULL)
1374 return NULL;
1376 if (!domain->initialized)
1377 init_dc_connection(domain, false);
1379 return domain;
1382 /* Given a domain sid, return the struct winbindd domain info for it */
1384 struct winbindd_domain *find_domain_from_sid_noinit(const struct dom_sid *sid)
1386 struct winbindd_domain *domain;
1388 /* Search through list */
1390 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1391 if (dom_sid_compare_domain(sid, &domain->sid) == 0)
1392 return domain;
1395 /* Not found */
1397 return NULL;
1401 * Given a domain sid, return the struct winbindd domain if it's a direct
1402 * outgoing trust
1404 * @return The domain structure for the specified domain, if it is a direct outgoing trust
1406 struct winbindd_domain *find_trust_from_sid_noinit(const struct dom_sid *sid)
1408 struct winbindd_domain *domain = NULL;
1410 domain = find_domain_from_sid_noinit(sid);
1411 if (domain == NULL) {
1412 return NULL;
1415 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1416 return domain;
1419 return NULL;
1422 /* Given a domain sid, return the struct winbindd domain info for it */
1424 struct winbindd_domain *find_domain_from_sid(const struct dom_sid *sid)
1426 struct winbindd_domain *domain;
1428 domain = find_domain_from_sid_noinit(sid);
1430 if (domain == NULL)
1431 return NULL;
1433 if (!domain->initialized)
1434 init_dc_connection(domain, false);
1436 return domain;
1439 struct winbindd_domain *find_our_domain(void)
1441 struct winbindd_domain *domain;
1443 /* Search through list */
1445 for (domain = domain_list(); domain != NULL; domain = domain->next) {
1446 if (domain->primary)
1447 return domain;
1450 smb_panic("Could not find our domain");
1451 return NULL;
1454 struct winbindd_domain *find_default_route_domain(void)
1456 if (!IS_DC) {
1457 return find_our_domain();
1459 DBG_DEBUG("Routing logic not yet implemented on a DC\n");
1460 return NULL;
1463 /* Find the appropriate domain to lookup a name or SID */
1465 struct winbindd_domain *find_lookup_domain_from_sid(const struct dom_sid *sid)
1467 DBG_DEBUG("SID [%s]\n", sid_string_dbg(sid));
1470 * SIDs in the S-1-22-{1,2} domain and well-known SIDs should be handled
1471 * by our passdb.
1474 if ( sid_check_is_in_unix_groups(sid) ||
1475 sid_check_is_unix_groups(sid) ||
1476 sid_check_is_in_unix_users(sid) ||
1477 sid_check_is_unix_users(sid) ||
1478 sid_check_is_wellknown_domain(sid, NULL) ||
1479 sid_check_is_in_wellknown_domain(sid) )
1481 return find_domain_from_sid(get_global_sam_sid());
1485 * On member servers the internal domains are different: These are part
1486 * of the local SAM.
1489 if (is_internal_domain(sid) || is_in_internal_domain(sid)) {
1490 DEBUG(10, ("calling find_domain_from_sid\n"));
1491 return find_domain_from_sid(sid);
1494 if (IS_DC) {
1495 struct winbindd_domain *domain = NULL;
1497 domain = find_domain_from_sid_noinit(sid);
1498 if (domain == NULL) {
1499 return NULL;
1502 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1503 return domain;
1506 return domain->routing_domain;
1509 /* On a member server a query for SID or name can always go to our
1510 * primary DC. */
1512 DEBUG(10, ("calling find_our_domain\n"));
1513 return find_our_domain();
1516 struct winbindd_domain *find_lookup_domain_from_name(const char *domain_name)
1518 if ( strequal(domain_name, unix_users_domain_name() ) ||
1519 strequal(domain_name, unix_groups_domain_name() ) )
1522 * The "Unix User" and "Unix Group" domain our handled by
1523 * passdb
1525 return find_domain_from_name_noinit( get_global_sam_name() );
1528 if (strequal(domain_name, "BUILTIN") ||
1529 strequal(domain_name, get_global_sam_name()))
1530 return find_domain_from_name_noinit(domain_name);
1532 if (IS_DC) {
1533 struct winbindd_domain *domain = NULL;
1535 domain = find_domain_from_name_noinit(domain_name);
1536 if (domain == NULL) {
1537 return NULL;
1540 if (domain->secure_channel_type != SEC_CHAN_NULL) {
1541 return domain;
1544 return domain->routing_domain;
1547 return find_our_domain();
1550 /* Is this a domain which we may assume no DOMAIN\ prefix? */
1552 static bool assume_domain(const char *domain)
1554 /* never assume the domain on a standalone server */
1556 if ( lp_server_role() == ROLE_STANDALONE )
1557 return False;
1559 /* domain member servers may possibly assume for the domain name */
1561 if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
1562 if ( !strequal(lp_workgroup(), domain) )
1563 return False;
1565 if ( lp_winbind_use_default_domain() )
1566 return True;
1569 /* only left with a domain controller */
1571 if ( strequal(get_global_sam_name(), domain) ) {
1572 return True;
1575 return False;
1578 /* Parse a string of the form DOMAIN\user into a domain and a user */
1580 bool parse_domain_user(const char *domuser, fstring domain, fstring user)
1582 char *p = strchr(domuser,*lp_winbind_separator());
1584 if ( !p ) {
1585 fstrcpy(user, domuser);
1586 p = strchr(domuser, '@');
1588 if ( assume_domain(lp_workgroup()) && p == NULL) {
1589 fstrcpy(domain, lp_workgroup());
1590 } else if (p != NULL) {
1591 fstrcpy(domain, p + 1);
1592 user[PTR_DIFF(p, domuser)] = 0;
1593 } else {
1594 return False;
1596 } else {
1597 fstrcpy(user, p+1);
1598 fstrcpy(domain, domuser);
1599 domain[PTR_DIFF(p, domuser)] = 0;
1602 return strupper_m(domain);
1605 bool parse_domain_user_talloc(TALLOC_CTX *mem_ctx, const char *domuser,
1606 char **domain, char **user)
1608 fstring fstr_domain, fstr_user;
1609 if (!parse_domain_user(domuser, fstr_domain, fstr_user)) {
1610 return False;
1612 *domain = talloc_strdup(mem_ctx, fstr_domain);
1613 *user = talloc_strdup(mem_ctx, fstr_user);
1614 return ((*domain != NULL) && (*user != NULL));
1617 /* Ensure an incoming username from NSS is fully qualified. Replace the
1618 incoming fstring with DOMAIN <separator> user. Returns the same
1619 values as parse_domain_user() but also replaces the incoming username.
1620 Used to ensure all names are fully qualified within winbindd.
1621 Used by the NSS protocols of auth, chauthtok, logoff and ccache_ntlm_auth.
1622 The protocol definitions of auth_crap, chng_pswd_auth_crap
1623 really should be changed to use this instead of doing things
1624 by hand. JRA. */
1626 bool canonicalize_username(fstring username_inout, fstring domain, fstring user)
1628 if (!parse_domain_user(username_inout, domain, user)) {
1629 return False;
1631 slprintf(username_inout, sizeof(fstring) - 1, "%s%c%s",
1632 domain, *lp_winbind_separator(),
1633 user);
1634 return True;
1638 Fill DOMAIN\\USERNAME entry accounting 'winbind use default domain' and
1639 'winbind separator' options.
1640 This means:
1641 - omit DOMAIN when 'winbind use default domain = true' and DOMAIN is
1642 lp_workgroup()
1644 If we are a PDC or BDC, and this is for our domain, do likewise.
1646 On an AD DC we always fill DOMAIN\\USERNAME.
1648 We always canonicalize as UPPERCASE DOMAIN, lowercase username.
1650 void fill_domain_username(fstring name, const char *domain, const char *user, bool can_assume)
1652 fstring tmp_user;
1654 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1655 can_assume = false;
1658 fstrcpy(tmp_user, user);
1659 (void)strlower_m(tmp_user);
1661 if (can_assume && assume_domain(domain)) {
1662 strlcpy(name, tmp_user, sizeof(fstring));
1663 } else {
1664 slprintf(name, sizeof(fstring) - 1, "%s%c%s",
1665 domain, *lp_winbind_separator(),
1666 tmp_user);
1671 * talloc version of fill_domain_username()
1672 * return NULL on talloc failure.
1674 char *fill_domain_username_talloc(TALLOC_CTX *mem_ctx,
1675 const char *domain,
1676 const char *user,
1677 bool can_assume)
1679 char *tmp_user, *name;
1681 if (lp_server_role() == ROLE_ACTIVE_DIRECTORY_DC) {
1682 can_assume = false;
1685 tmp_user = talloc_strdup(mem_ctx, user);
1686 if (!strlower_m(tmp_user)) {
1687 TALLOC_FREE(tmp_user);
1688 return NULL;
1691 if (can_assume && assume_domain(domain)) {
1692 name = tmp_user;
1693 } else {
1694 name = talloc_asprintf(mem_ctx, "%s%c%s",
1695 domain,
1696 *lp_winbind_separator(),
1697 tmp_user);
1698 TALLOC_FREE(tmp_user);
1701 return name;
1705 * Client list accessor functions
1708 static struct winbindd_cli_state *_client_list;
1709 static int _num_clients;
1711 /* Return list of all connected clients */
1713 struct winbindd_cli_state *winbindd_client_list(void)
1715 return _client_list;
1718 /* Return list-tail of all connected clients */
1720 struct winbindd_cli_state *winbindd_client_list_tail(void)
1722 return DLIST_TAIL(_client_list);
1725 /* Return previous (read:newer) client in list */
1727 struct winbindd_cli_state *
1728 winbindd_client_list_prev(struct winbindd_cli_state *cli)
1730 return DLIST_PREV(cli);
1733 /* Add a connection to the list */
1735 void winbindd_add_client(struct winbindd_cli_state *cli)
1737 cli->last_access = time(NULL);
1738 DLIST_ADD(_client_list, cli);
1739 _num_clients++;
1742 /* Remove a client from the list */
1744 void winbindd_remove_client(struct winbindd_cli_state *cli)
1746 DLIST_REMOVE(_client_list, cli);
1747 _num_clients--;
1750 /* Move a client to head or list */
1752 void winbindd_promote_client(struct winbindd_cli_state *cli)
1754 cli->last_access = time(NULL);
1755 DLIST_PROMOTE(_client_list, cli);
1758 /* Return number of open clients */
1760 int winbindd_num_clients(void)
1762 return _num_clients;
1765 NTSTATUS lookup_usergroups_cached(TALLOC_CTX *mem_ctx,
1766 const struct dom_sid *user_sid,
1767 uint32_t *p_num_groups, struct dom_sid **user_sids)
1769 struct netr_SamInfo3 *info3 = NULL;
1770 NTSTATUS status = NT_STATUS_NO_MEMORY;
1771 uint32_t num_groups = 0;
1773 DEBUG(3,(": lookup_usergroups_cached\n"));
1775 *user_sids = NULL;
1776 *p_num_groups = 0;
1778 info3 = netsamlogon_cache_get(mem_ctx, user_sid);
1780 if (info3 == NULL) {
1781 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1785 * Before bug #7843 the "Domain Local" groups were added with a
1786 * lookupuseraliases call, but this isn't done anymore for our domain
1787 * so we need to resolve resource groups here.
1789 * When to use Resource Groups:
1790 * http://technet.microsoft.com/en-us/library/cc753670%28v=WS.10%29.aspx
1792 status = sid_array_from_info3(mem_ctx, info3,
1793 user_sids,
1794 &num_groups,
1795 false);
1797 if (!NT_STATUS_IS_OK(status)) {
1798 TALLOC_FREE(info3);
1799 return status;
1802 TALLOC_FREE(info3);
1803 *p_num_groups = num_groups;
1804 status = (user_sids != NULL) ? NT_STATUS_OK : NT_STATUS_NO_MEMORY;
1806 DEBUG(3,(": lookup_usergroups_cached succeeded\n"));
1808 return status;
1811 /*********************************************************************
1812 We use this to remove spaces from user and group names
1813 ********************************************************************/
1815 NTSTATUS normalize_name_map(TALLOC_CTX *mem_ctx,
1816 const char *domain_name,
1817 const char *name,
1818 char **normalized)
1820 struct winbindd_domain *domain = NULL;
1821 NTSTATUS nt_status;
1823 if (!name || !normalized) {
1824 return NT_STATUS_INVALID_PARAMETER;
1827 if (!lp_winbind_normalize_names()) {
1828 return NT_STATUS_PROCEDURE_NOT_FOUND;
1831 domain = find_domain_from_name_noinit(domain_name);
1832 if (domain == NULL) {
1833 DBG_ERR("Failed to find domain '%s'\n", domain_name);
1834 return NT_STATUS_NO_SUCH_DOMAIN;
1837 /* Alias support and whitespace replacement are mutually
1838 exclusive */
1840 nt_status = resolve_username_to_alias(mem_ctx, domain,
1841 name, normalized );
1842 if (NT_STATUS_IS_OK(nt_status)) {
1843 /* special return code to let the caller know we
1844 mapped to an alias */
1845 return NT_STATUS_FILE_RENAMED;
1848 /* check for an unreachable domain */
1850 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1851 DEBUG(5,("normalize_name_map: Setting domain %s offline\n",
1852 domain->name));
1853 set_domain_offline(domain);
1854 return nt_status;
1857 /* deal with whitespace */
1859 *normalized = talloc_strdup(mem_ctx, name);
1860 if (!(*normalized)) {
1861 return NT_STATUS_NO_MEMORY;
1864 all_string_sub( *normalized, " ", "_", 0 );
1866 return NT_STATUS_OK;
1869 /*********************************************************************
1870 We use this to do the inverse of normalize_name_map()
1871 ********************************************************************/
1873 NTSTATUS normalize_name_unmap(TALLOC_CTX *mem_ctx,
1874 char *name,
1875 char **normalized)
1877 NTSTATUS nt_status;
1878 struct winbindd_domain *domain = find_our_domain();
1880 if (!name || !normalized) {
1881 return NT_STATUS_INVALID_PARAMETER;
1884 if (!lp_winbind_normalize_names()) {
1885 return NT_STATUS_PROCEDURE_NOT_FOUND;
1888 /* Alias support and whitespace replacement are mutally
1889 exclusive */
1891 /* When mapping from an alias to a username, we don't know the
1892 domain. But we only need a domain structure to cache
1893 a successful lookup , so just our own domain structure for
1894 the seqnum. */
1896 nt_status = resolve_alias_to_username(mem_ctx, domain,
1897 name, normalized);
1898 if (NT_STATUS_IS_OK(nt_status)) {
1899 /* Special return code to let the caller know we mapped
1900 from an alias */
1901 return NT_STATUS_FILE_RENAMED;
1904 /* check for an unreachable domain */
1906 if (NT_STATUS_EQUAL(nt_status, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND)) {
1907 DEBUG(5,("normalize_name_unmap: Setting domain %s offline\n",
1908 domain->name));
1909 set_domain_offline(domain);
1910 return nt_status;
1913 /* deal with whitespace */
1915 *normalized = talloc_strdup(mem_ctx, name);
1916 if (!(*normalized)) {
1917 return NT_STATUS_NO_MEMORY;
1920 all_string_sub(*normalized, "_", " ", 0);
1922 return NT_STATUS_OK;
1925 /*********************************************************************
1926 ********************************************************************/
1928 bool winbindd_can_contact_domain(struct winbindd_domain *domain)
1930 struct winbindd_tdc_domain *tdc = NULL;
1931 TALLOC_CTX *frame = talloc_stackframe();
1932 bool ret = false;
1934 /* We can contact the domain if it is our primary domain */
1936 if (domain->primary) {
1937 ret = true;
1938 goto done;
1941 /* Trust the TDC cache and not the winbindd_domain flags */
1943 if ((tdc = wcache_tdc_fetch_domain(frame, domain->name)) == NULL) {
1944 DEBUG(10,("winbindd_can_contact_domain: %s not found in cache\n",
1945 domain->name));
1946 ret = false;
1947 goto done;
1950 /* Can always contact a domain that is in out forest */
1952 if (tdc->trust_flags & NETR_TRUST_FLAG_IN_FOREST) {
1953 ret = true;
1954 goto done;
1958 * On a _member_ server, we cannot contact the domain if it
1959 * is running AD and we have no inbound trust.
1962 if (!IS_DC &&
1963 domain->active_directory &&
1964 ((tdc->trust_flags & NETR_TRUST_FLAG_INBOUND) != NETR_TRUST_FLAG_INBOUND))
1966 DEBUG(10, ("winbindd_can_contact_domain: %s is an AD domain "
1967 "and we have no inbound trust.\n", domain->name));
1968 goto done;
1971 /* Assume everything else is ok (probably not true but what
1972 can you do?) */
1974 ret = true;
1976 done:
1977 talloc_destroy(frame);
1979 return ret;
1982 #ifdef HAVE_KRB5_LOCATE_PLUGIN_H
1984 /*********************************************************************
1985 ********************************************************************/
1987 static void winbindd_set_locator_kdc_env(const struct winbindd_domain *domain)
1989 char *var = NULL;
1990 char addr[INET6_ADDRSTRLEN];
1991 const char *kdc = NULL;
1992 int lvl = 11;
1994 if (!domain || !domain->alt_name || !*domain->alt_name) {
1995 return;
1998 if (domain->initialized && !domain->active_directory) {
1999 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s not AD\n",
2000 domain->alt_name));
2001 return;
2004 print_sockaddr(addr, sizeof(addr), &domain->dcaddr);
2005 kdc = addr;
2006 if (!*kdc) {
2007 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC IP\n",
2008 domain->alt_name));
2009 kdc = domain->dcname;
2012 if (!kdc || !*kdc) {
2013 DEBUG(lvl,("winbindd_set_locator_kdc_env: %s no DC at all\n",
2014 domain->alt_name));
2015 return;
2018 if (asprintf_strupper_m(&var, "%s_%s", WINBINDD_LOCATOR_KDC_ADDRESS,
2019 domain->alt_name) == -1) {
2020 return;
2023 DEBUG(lvl,("winbindd_set_locator_kdc_env: setting var: %s to: %s\n",
2024 var, kdc));
2026 setenv(var, kdc, 1);
2027 free(var);
2030 /*********************************************************************
2031 ********************************************************************/
2033 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2035 struct winbindd_domain *our_dom = find_our_domain();
2037 winbindd_set_locator_kdc_env(domain);
2039 if (domain != our_dom) {
2040 winbindd_set_locator_kdc_env(our_dom);
2044 /*********************************************************************
2045 ********************************************************************/
2047 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2049 char *var = NULL;
2051 if (!domain || !domain->alt_name || !*domain->alt_name) {
2052 return;
2055 if (asprintf_strupper_m(&var, "%s_%s", WINBINDD_LOCATOR_KDC_ADDRESS,
2056 domain->alt_name) == -1) {
2057 return;
2060 unsetenv(var);
2061 free(var);
2063 #else
2065 void winbindd_set_locator_kdc_envs(const struct winbindd_domain *domain)
2067 return;
2070 void winbindd_unset_locator_kdc_env(const struct winbindd_domain *domain)
2072 return;
2075 #endif /* HAVE_KRB5_LOCATE_PLUGIN_H */
2077 void set_auth_errors(struct winbindd_response *resp, NTSTATUS result)
2079 resp->data.auth.nt_status = NT_STATUS_V(result);
2080 fstrcpy(resp->data.auth.nt_status_string, nt_errstr(result));
2082 /* we might have given a more useful error above */
2083 if (*resp->data.auth.error_string == '\0')
2084 fstrcpy(resp->data.auth.error_string,
2085 get_friendly_nt_error_msg(result));
2086 resp->data.auth.pam_error = nt_status_to_pam(result);
2089 bool is_domain_offline(const struct winbindd_domain *domain)
2091 if (get_global_winbindd_state_offline()) {
2092 return true;
2094 return !domain->online;
2097 bool is_domain_online(const struct winbindd_domain *domain)
2099 return !is_domain_offline(domain);
2103 * Parse an char array into a list of sids.
2105 * The input sidstr should consist of 0-terminated strings
2106 * representing sids, separated by newline characters '\n'.
2107 * The list is terminated by an empty string, i.e.
2108 * character '\0' directly following a character '\n'
2109 * (or '\0' right at the start of sidstr).
2111 bool parse_sidlist(TALLOC_CTX *mem_ctx, const char *sidstr,
2112 struct dom_sid **sids, uint32_t *num_sids)
2114 const char *p;
2116 p = sidstr;
2117 if (p == NULL)
2118 return False;
2120 while (p[0] != '\0') {
2121 struct dom_sid sid;
2122 const char *q = NULL;
2124 if (!dom_sid_parse_endp(p, &sid, &q)) {
2125 DEBUG(1, ("Could not parse sid %s\n", p));
2126 return false;
2128 if (q[0] != '\n') {
2129 DEBUG(1, ("Got invalid sidstr: %s\n", p));
2130 return false;
2132 if (!NT_STATUS_IS_OK(add_sid_to_array(mem_ctx, &sid, sids,
2133 num_sids)))
2135 return False;
2137 p = q+1;
2139 return True;
2142 bool parse_xidlist(TALLOC_CTX *mem_ctx, const char *xidstr,
2143 struct unixid **pxids, uint32_t *pnum_xids)
2145 const char *p;
2146 struct unixid *xids = NULL;
2147 uint32_t num_xids = 0;
2149 p = xidstr;
2150 if (p == NULL) {
2151 return false;
2154 while (p[0] != '\0') {
2155 struct unixid *tmp;
2156 struct unixid xid;
2157 unsigned long long id;
2158 char *endp;
2160 switch (p[0]) {
2161 case 'U':
2162 xid = (struct unixid) { .type = ID_TYPE_UID };
2163 break;
2164 case 'G':
2165 xid = (struct unixid) { .type = ID_TYPE_GID };
2166 break;
2167 default:
2168 return false;
2171 p += 1;
2173 id = strtoull(p, &endp, 10);
2174 if ((id == ULLONG_MAX) && (errno == ERANGE)) {
2175 goto fail;
2177 if (*endp != '\n') {
2178 goto fail;
2180 p = endp+1;
2182 xid.id = id;
2183 if ((unsigned long long)xid.id != id) {
2184 goto fail;
2187 tmp = talloc_realloc(mem_ctx, xids, struct unixid, num_xids+1);
2188 if (tmp == NULL) {
2189 return 0;
2191 xids = tmp;
2193 xids[num_xids] = xid;
2194 num_xids += 1;
2197 *pxids = xids;
2198 *pnum_xids = num_xids;
2199 return true;
2201 fail:
2202 TALLOC_FREE(xids);
2203 return false;