Deprecated but still supported "idmap
backend" actually is broken
Dmitry Butskoy
buc at odusz.so-cdu.ru
Fri Oct 12 15:04:25 GMT 2007
simo wrote:
> I am still building packages to test but if you want to give it a try
> you'll find attached my first take
>
The patch should be fixed a little.
When we change the idmap dom name from the "default domain" to the name
of the actual primary domain (lp_workgroup()), it leads the "trusted
domains only" feature no more work. (IOW the case of idmap_nss "hidden"
backend).
Consider a case, when we:
- do not specify any idmap backends or idmap domains at all;
- and specify "winbind trusted domains only = yes" (for UNIX accounts
comes from UNIX NSS).
Consider (new, patched) "nsswitch/idmap.c:idmap_init()" again:
> NTSTATUS idmap_init(void)
> {
> NTSTATUS ret;
> static NTSTATUS idmap_init_status = NT_STATUS_UNSUCCESSFUL;
> struct idmap_domain *dom;
> char *compat_backend = NULL;
> char *compat_params = NULL;
> const char **dom_list = NULL;
> const char *default_domain = NULL;
> char *alloc_backend = NULL;
> BOOL default_already_defined = False;
> BOOL pri_dom_is_in_list = False;
> int compat = 0;
> int i;
>
> ret = idmap_init_cache();
> if (!NT_STATUS_IS_OK(ret))
> return ret;
>
> if (NT_STATUS_IS_OK(idmap_init_status))
> return NT_STATUS_OK;
>
> static_init_idmap;
>
> dom_list = lp_idmap_domains();
NULL
>
> if ( lp_idmap_backend() ) {
false
> const char **compat_list = lp_idmap_backend();
> char *p = NULL;
> const char *q = NULL;
>
> if (dom_list) {
> DEBUG(0, ("WARNING: idmap backend and idmap domains "
> "are mutually excusive!\n"));
> DEBUGADD(0,("idmap backend option will be IGNORED!\n"));
> } else {
> compat = 1;
>
> compat_backend = talloc_strdup(idmap_ctx, *compat_list);
> if (compat_backend == NULL) {
> ret = NT_STATUS_NO_MEMORY;
> goto done;
> }
>
> /* strip any leading idmap_ prefix of */
> if (strncmp(*compat_list, "idmap_", 6) == 0 ) {
> q = *compat_list += 6;
> DEBUG(0, ("WARNING: idmap backend uses obsolete"
> " and deprecated 'idmap_' prefix.\n"o
> "Please replace 'idmap_%s' by '%s' in"
> " %s\n", q, q, dyn_CONFIGFILE));
> compat_backend = talloc_strdup(idmap_ctx, q);
> } else {
> compat_backend = talloc_strdup(idmap_ctx,
> *compat_list);
> }
>
> /* separate the backend and module arguements */
> if ((p = strchr(compat_backend, ':')) != NULL) {
> *p = '\0';
> compat_params = p + 1;
> }
> }
> } else if ( !dom_list ) {
yes
> /* Back compatible: without idmap domains and explicit
> idmap backend. Taking default idmap backend: tdb */
>
> compat = 1;
> compat_backend = talloc_strdup( idmap_ctx, "tdb");
> compat_params = compat_backend;
> }
>
> if ( ! dom_list) {
yes, again...
> /* generate a list with our main domain */
> char ** dl;
>
> dl = talloc_array(idmap_ctx, char *, 2);
> if (dl == NULL) {
> ret = NT_STATUS_NO_MEMORY;
> goto done;
> }
> dl[0] = talloc_strdup(dl, lp_workgroup());
> if (dl[0] == NULL) {Consider (new, patched)
> ret = NT_STATUS_NO_MEMORY;
> goto done;
> }
>
> /* terminate */
> dl[1] = NULL;
>
> dom_list = dl;
> default_domain = dl[0];
...and now default_domain == lp_workgroup()
> }
>
> /***************************
> * initialize idmap domains
> */
> DEBUG(1, ("Initializing idmap domains\n"));
>
> for (i = 0; dom_list[i]; i++) {
> const char *parm_backend;
> char *config_option;
>
> /* ignore BUILTIN and local MACHINE domains */
> if (strequal(dom_list[i], "BUILTIN")
> || strequal(dom_list[i], get_global_sam_name()))
> {
> DEBUG(0,("idmap_init: Ignoring invalid domain %s\n",
> dom_list[i]));
> continue;
> }
>
> if (strequal(dom_list[i], lp_workgroup())) {
> pri_dom_is_in_list = True;
yes, it is True now, but was False before the patch applied (when
dom_list[i] was "default domain")
> }
> /* init domain */
>
> dom = TALLOC_ZERO_P(idmap_ctx, struct idmap_domain);
> IDMAP_CHECK_ALLOC(dom);
>
> dom->name = talloc_strdup(dom, dom_list[i]);
> IDMAP_CHECK_ALLOC(dom->name);
>
> config_option = talloc_asprintf(dom, "idmap config %s",
> dom->name);
> IDMAP_CHECK_ALLOC(config_option);
>
> /* default or specific ? */
>
> dom->default_domain = lp_parm_bool(-1, config_option,
> "default", False);
>
> if (dom->default_domain ||
> (default_domain && strequal(dom_list[i], default_domain))) {
>
> /* make sure this is set even when we match
> * default_domain */
> dom->default_domain = True;
>
> if (default_already_defined) {
> DEBUG(1, ("ERROR: Multiple domains defined as"
> " default!\n"));
> ret = NT_STATUS_INVALID_PARAMETER;
> goto done;
> }
>
> default_already_defined = True;
>
> }
>
> dom->readonly = lp_parm_bool(-1, config_option,
> "readonly", False);
>
> /* find associated backend (default: tdb) */
> if (compat) {
> parm_backend = talloc_strdup(idmap_ctx, compat_backend);
> } else {
> char *backend = lp_parm_const_string(-1, config_option,
> "backend", "tdb");
> parm_backend = talloc_strdup(idmap_ctx, backend);
> }
> IDMAP_CHECK_ALLOC(parm_backend);
>
> /* get the backend methods for this domain */
> dom->methods = get_methods(backends, parm_backend);
>
> if ( ! dom->methods) {
> ret = smb_probe_module("idmap", parm_backend);
> if (NT_STATUS_IS_OK(ret)) {
> dom->methods = get_methods(backends,
> parm_backend);
> }
> }
> if ( ! dom->methods) {
> DEBUG(0, ("ERROR: Could not get methods for "
> "backend %s\n", parm_backend));
> ret = NT_STATUS_UNSUCCESSFUL;
> goto done;
> }
>
> /* check the set_mapping function exists otherwise mark the
> * module as readonly */
> if ( ! dom->methods->set_mapping) {
> DEBUG(5, ("Forcing to readonly, as this module can't"
> " store arbitrary mappings.\n"));
> dom->readonly = True;
> }
>
> /* now that we have methods,
> * set the destructor for this domain */
> talloc_set_destructor(dom, close_domain_destructor);
>
> if (compat_params) {
> dom->params = talloc_strdup(dom, compat_params);
> IDMAP_CHECK_ALLOC(dom->params);
> } else {
> dom->params = NULL;
> }
>
> /* Finally instance a backend copy for this domain */
> ret = dom->methods->init(dom);
> if ( ! NT_STATUS_IS_OK(ret)) {
> DEBUG(0, ("ERROR: Initialization failed for backend "
> "%s (domain %s), deferred!\n",
> parm_backend, dom->name));
> }
> idmap_domains = talloc_realloc(idmap_ctx, idmap_domains,
> struct idmap_domain *, i+1);
> if ( ! idmap_domains) {
> DEBUG(0, ("Out of memory!\n"));
> ret = NT_STATUS_NO_MEMORY;
> goto done;
> }
> idmap_domains[i] = dom;
>
> /* save default domain position for future uses */
> if (dom->default_domain) {
> def_dom_num = i;
> }
>
> DEBUG(10, ("Domain %s - Backend %s - %sdefault - %sreadonly\n",
> dom->name, parm_backend,
> dom->default_domain?"":"not ",
> dom->readonly?"":"not "));
>
> talloc_free(config_option);
> }
>
> /* save the number of domains we have */
> num_domains = i;
>
> /* automatically add idmap_nss backend if needed */
> if ((lp_server_role() == ROLE_DOMAIN_MEMBER) &&
> ( ! pri_dom_is_in_list) &&
Oops! Before the patch "( ! pri_dom_is_in_list)" was True (then
idmap_nss inited etc.), now it is False!
> lp_winbind_trusted_domains_only()) {
>
> dom = TALLOC_ZERO_P(idmap_ctx, struct idmap_domain);
> IDMAP_CHECK_ALLOC(dom);
>
> dom->name = talloc_strdup(dom, lp_workgroup());
> IDMAP_CHECK_ALLOC(dom->name);
>
> dom->default_domain = False;
> dom->readonly = True;
>
> /* get the backend methods for passdb */
> dom->methods = get_methods(backends, "nss");
[snip]
IOW, now by default (when both "idmap backend" and "idmap domains" are
empty), the "pri_dom_is_in_list" is always True, which prevents the
using of "winbind trusted domains only = yes" feature...
~buc
More information about the samba-technical
mailing list