| 1 | /*
 | 
|---|
| 2 |    Unix SMB/CIFS implementation.
 | 
|---|
| 3 |    ID Mapping
 | 
|---|
| 4 |    Copyright (C) Tim Potter 2000
 | 
|---|
| 5 |    Copyright (C) Jim McDonough <jmcd@us.ibm.com>        2003
 | 
|---|
| 6 |    Copyright (C) Simo Sorce 2003-2007
 | 
|---|
| 7 |    Copyright (C) Jeremy Allison 2006
 | 
|---|
| 8 | 
 | 
|---|
| 9 |    This program is free software; you can redistribute it and/or modify
 | 
|---|
| 10 |    it under the terms of the GNU General Public License as published by
 | 
|---|
| 11 |    the Free Software Foundation; either version 3 of the License, or
 | 
|---|
| 12 |    (at your option) any later version.
 | 
|---|
| 13 | 
 | 
|---|
| 14 |    This program is distributed in the hope that it will be useful,
 | 
|---|
| 15 |    but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
|---|
| 16 |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
|---|
| 17 |    GNU General Public License for more details.
 | 
|---|
| 18 | 
 | 
|---|
| 19 |    You should have received a copy of the GNU General Public License
 | 
|---|
| 20 |    along with this program.  If not, see <http://www.gnu.org/licenses/>.
 | 
|---|
| 21 | */
 | 
|---|
| 22 | 
 | 
|---|
| 23 | #include "includes.h"
 | 
|---|
| 24 | #include "winbindd.h"
 | 
|---|
| 25 | 
 | 
|---|
| 26 | #undef DBGC_CLASS
 | 
|---|
| 27 | #define DBGC_CLASS DBGC_IDMAP
 | 
|---|
| 28 | 
 | 
|---|
| 29 | static_decl_idmap;
 | 
|---|
| 30 | 
 | 
|---|
| 31 | /**
 | 
|---|
| 32 |  * Pointer to the backend methods. Modules register themselves here via
 | 
|---|
| 33 |  * smb_register_idmap.
 | 
|---|
| 34 |  */
 | 
|---|
| 35 | 
 | 
|---|
| 36 | struct idmap_backend {
 | 
|---|
| 37 |         const char *name;
 | 
|---|
| 38 |         struct idmap_methods *methods;
 | 
|---|
| 39 |         struct idmap_backend *prev, *next;
 | 
|---|
| 40 | };
 | 
|---|
| 41 | static struct idmap_backend *backends = NULL;
 | 
|---|
| 42 | 
 | 
|---|
| 43 | /**
 | 
|---|
| 44 |  * Pointer to the alloc backend methods. Modules register themselves here via
 | 
|---|
| 45 |  * smb_register_idmap_alloc.
 | 
|---|
| 46 |  */
 | 
|---|
| 47 | struct idmap_alloc_backend {
 | 
|---|
| 48 |         const char *name;
 | 
|---|
| 49 |         struct idmap_alloc_methods *methods;
 | 
|---|
| 50 |         struct idmap_alloc_backend *prev, *next;
 | 
|---|
| 51 | };
 | 
|---|
| 52 | static struct idmap_alloc_backend *alloc_backends = NULL;
 | 
|---|
| 53 | 
 | 
|---|
| 54 | /**
 | 
|---|
| 55 |  * The idmap alloc context that is configured via "idmap alloc
 | 
|---|
| 56 |  * backend". Defaults to "idmap backend" in case the module (tdb, ldap) also
 | 
|---|
| 57 |  * provides alloc methods.
 | 
|---|
| 58 |  */
 | 
|---|
| 59 | struct idmap_alloc_context {
 | 
|---|
| 60 |         struct idmap_alloc_methods *methods;
 | 
|---|
| 61 | };
 | 
|---|
| 62 | static struct idmap_alloc_context *idmap_alloc_ctx = NULL;
 | 
|---|
| 63 | 
 | 
|---|
| 64 | /**
 | 
|---|
| 65 |  * Default idmap domain configured via "idmap backend".
 | 
|---|
| 66 |  */
 | 
|---|
| 67 | static struct idmap_domain *default_idmap_domain;
 | 
|---|
| 68 | 
 | 
|---|
| 69 | /**
 | 
|---|
| 70 |  * Passdb idmap domain, not configurable. winbind must always give passdb a
 | 
|---|
| 71 |  * chance to map ids.
 | 
|---|
| 72 |  */
 | 
|---|
| 73 | static struct idmap_domain *passdb_idmap_domain;
 | 
|---|
| 74 | 
 | 
|---|
| 75 | /**
 | 
|---|
| 76 |  * List of specially configured idmap domains. This list is filled on demand
 | 
|---|
| 77 |  * in the winbind idmap child when the parent winbind figures out via the
 | 
|---|
| 78 |  * special range parameter or via the domain SID that a special "idmap config
 | 
|---|
| 79 |  * domain" configuration is present.
 | 
|---|
| 80 |  */
 | 
|---|
| 81 | static struct idmap_domain **idmap_domains = NULL;
 | 
|---|
| 82 | static int num_domains = 0;
 | 
|---|
| 83 | 
 | 
|---|
| 84 | static struct idmap_methods *get_methods(const char *name)
 | 
|---|
| 85 | {
 | 
|---|
| 86 |         struct idmap_backend *b;
 | 
|---|
| 87 | 
 | 
|---|
| 88 |         for (b = backends; b; b = b->next) {
 | 
|---|
| 89 |                 if (strequal(b->name, name)) {
 | 
|---|
| 90 |                         return b->methods;
 | 
|---|
| 91 |                 }
 | 
|---|
| 92 |         }
 | 
|---|
| 93 | 
 | 
|---|
| 94 |         return NULL;
 | 
|---|
| 95 | }
 | 
|---|
| 96 | 
 | 
|---|
| 97 | static struct idmap_alloc_methods *get_alloc_methods(const char *name)
 | 
|---|
| 98 | {
 | 
|---|
| 99 |         struct idmap_alloc_backend *b;
 | 
|---|
| 100 | 
 | 
|---|
| 101 |         for (b = alloc_backends; b; b = b->next) {
 | 
|---|
| 102 |                 if (strequal(b->name, name)) {
 | 
|---|
| 103 |                         return b->methods;
 | 
|---|
| 104 |                 }
 | 
|---|
| 105 |         }
 | 
|---|
| 106 | 
 | 
|---|
| 107 |         return NULL;
 | 
|---|
| 108 | }
 | 
|---|
| 109 | 
 | 
|---|
| 110 | bool idmap_is_offline(void)
 | 
|---|
| 111 | {
 | 
|---|
| 112 |         return ( lp_winbind_offline_logon() &&
 | 
|---|
| 113 |              get_global_winbindd_state_offline() );
 | 
|---|
| 114 | }
 | 
|---|
| 115 | 
 | 
|---|
| 116 | bool idmap_is_online(void)
 | 
|---|
| 117 | {
 | 
|---|
| 118 |         return !idmap_is_offline();
 | 
|---|
| 119 | }
 | 
|---|
| 120 | 
 | 
|---|
| 121 | /**********************************************************************
 | 
|---|
| 122 |  Allow a module to register itself as a method.
 | 
|---|
| 123 | **********************************************************************/
 | 
|---|
| 124 | 
 | 
|---|
| 125 | NTSTATUS smb_register_idmap(int version, const char *name,
 | 
|---|
| 126 |                             struct idmap_methods *methods)
 | 
|---|
| 127 | {
 | 
|---|
| 128 |         struct idmap_backend *entry;
 | 
|---|
| 129 | 
 | 
|---|
| 130 |         if ((version != SMB_IDMAP_INTERFACE_VERSION)) {
 | 
|---|
| 131 |                 DEBUG(0, ("Failed to register idmap module.\n"
 | 
|---|
| 132 |                           "The module was compiled against "
 | 
|---|
| 133 |                           "SMB_IDMAP_INTERFACE_VERSION %d,\n"
 | 
|---|
| 134 |                           "current SMB_IDMAP_INTERFACE_VERSION is %d.\n"
 | 
|---|
| 135 |                           "Please recompile against the current version "
 | 
|---|
| 136 |                           "of samba!\n",
 | 
|---|
| 137 |                           version, SMB_IDMAP_INTERFACE_VERSION));
 | 
|---|
| 138 |                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
 | 
|---|
| 139 |         }
 | 
|---|
| 140 | 
 | 
|---|
| 141 |         if (!name || !name[0] || !methods) {
 | 
|---|
| 142 |                 DEBUG(0,("Called with NULL pointer or empty name!\n"));
 | 
|---|
| 143 |                 return NT_STATUS_INVALID_PARAMETER;
 | 
|---|
| 144 |         }
 | 
|---|
| 145 | 
 | 
|---|
| 146 |         for (entry = backends; entry != NULL; entry = entry->next) {
 | 
|---|
| 147 |                 if (strequal(entry->name, name)) {
 | 
|---|
| 148 |                         DEBUG(0,("Idmap module %s already registered!\n",
 | 
|---|
| 149 |                                  name));
 | 
|---|
| 150 |                         return NT_STATUS_OBJECT_NAME_COLLISION;
 | 
|---|
| 151 |                 }
 | 
|---|
| 152 |         }
 | 
|---|
| 153 | 
 | 
|---|
| 154 |         entry = talloc(NULL, struct idmap_backend);
 | 
|---|
| 155 |         if ( ! entry) {
 | 
|---|
| 156 |                 DEBUG(0,("Out of memory!\n"));
 | 
|---|
| 157 |                 TALLOC_FREE(entry);
 | 
|---|
| 158 |                 return NT_STATUS_NO_MEMORY;
 | 
|---|
| 159 |         }
 | 
|---|
| 160 |         entry->name = talloc_strdup(entry, name);
 | 
|---|
| 161 |         if ( ! entry->name) {
 | 
|---|
| 162 |                 DEBUG(0,("Out of memory!\n"));
 | 
|---|
| 163 |                 TALLOC_FREE(entry);
 | 
|---|
| 164 |                 return NT_STATUS_NO_MEMORY;
 | 
|---|
| 165 |         }
 | 
|---|
| 166 |         entry->methods = methods;
 | 
|---|
| 167 | 
 | 
|---|
| 168 |         DLIST_ADD(backends, entry);
 | 
|---|
| 169 |         DEBUG(5, ("Successfully added idmap backend '%s'\n", name));
 | 
|---|
| 170 |         return NT_STATUS_OK;
 | 
|---|
| 171 | }
 | 
|---|
| 172 | 
 | 
|---|
| 173 | /**********************************************************************
 | 
|---|
| 174 |  Allow a module to register itself as an alloc method.
 | 
|---|
| 175 | **********************************************************************/
 | 
|---|
| 176 | 
 | 
|---|
| 177 | NTSTATUS smb_register_idmap_alloc(int version, const char *name,
 | 
|---|
| 178 |                                   struct idmap_alloc_methods *methods)
 | 
|---|
| 179 | {
 | 
|---|
| 180 |         struct idmap_alloc_methods *test;
 | 
|---|
| 181 |         struct idmap_alloc_backend *entry;
 | 
|---|
| 182 | 
 | 
|---|
| 183 |         if ((version != SMB_IDMAP_INTERFACE_VERSION)) {
 | 
|---|
| 184 |                 DEBUG(0, ("Failed to register idmap alloc module.\n"
 | 
|---|
| 185 |                           "The module was compiled against "
 | 
|---|
| 186 |                           "SMB_IDMAP_INTERFACE_VERSION %d,\n"
 | 
|---|
| 187 |                           "current SMB_IDMAP_INTERFACE_VERSION is %d.\n"
 | 
|---|
| 188 |                           "Please recompile against the current version "
 | 
|---|
| 189 |                           "of samba!\n",
 | 
|---|
| 190 |                           version, SMB_IDMAP_INTERFACE_VERSION));
 | 
|---|
| 191 |                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
 | 
|---|
| 192 |         }
 | 
|---|
| 193 | 
 | 
|---|
| 194 |         if (!name || !name[0] || !methods) {
 | 
|---|
| 195 |                 DEBUG(0,("Called with NULL pointer or empty name!\n"));
 | 
|---|
| 196 |                 return NT_STATUS_INVALID_PARAMETER;
 | 
|---|
| 197 |         }
 | 
|---|
| 198 | 
 | 
|---|
| 199 |         test = get_alloc_methods(name);
 | 
|---|
| 200 |         if (test) {
 | 
|---|
| 201 |                 DEBUG(0,("idmap_alloc module %s already registered!\n", name));
 | 
|---|
| 202 |                 return NT_STATUS_OBJECT_NAME_COLLISION;
 | 
|---|
| 203 |         }
 | 
|---|
| 204 | 
 | 
|---|
| 205 |         entry = talloc(NULL, struct idmap_alloc_backend);
 | 
|---|
| 206 |         if ( ! entry) {
 | 
|---|
| 207 |                 DEBUG(0,("Out of memory!\n"));
 | 
|---|
| 208 |                 return NT_STATUS_NO_MEMORY;
 | 
|---|
| 209 |         }
 | 
|---|
| 210 |         entry->name = talloc_strdup(entry, name);
 | 
|---|
| 211 |         if ( ! entry->name) {
 | 
|---|
| 212 |                 DEBUG(0,("Out of memory!\n"));
 | 
|---|
| 213 |                 return NT_STATUS_NO_MEMORY;
 | 
|---|
| 214 |         }
 | 
|---|
| 215 |         entry->methods = methods;
 | 
|---|
| 216 | 
 | 
|---|
| 217 |         DLIST_ADD(alloc_backends, entry);
 | 
|---|
| 218 |         DEBUG(5, ("Successfully added idmap alloc backend '%s'\n", name));
 | 
|---|
| 219 |         return NT_STATUS_OK;
 | 
|---|
| 220 | }
 | 
|---|
| 221 | 
 | 
|---|
| 222 | static int close_domain_destructor(struct idmap_domain *dom)
 | 
|---|
| 223 | {
 | 
|---|
| 224 |         NTSTATUS ret;
 | 
|---|
| 225 | 
 | 
|---|
| 226 |         ret = dom->methods->close_fn(dom);
 | 
|---|
| 227 |         if (!NT_STATUS_IS_OK(ret)) {
 | 
|---|
| 228 |                 DEBUG(3, ("Failed to close idmap domain [%s]!\n", dom->name));
 | 
|---|
| 229 |         }
 | 
|---|
| 230 | 
 | 
|---|
| 231 |         return 0;
 | 
|---|
| 232 | }
 | 
|---|
| 233 | 
 | 
|---|
| 234 | static bool parse_idmap_module(TALLOC_CTX *mem_ctx, const char *param,
 | 
|---|
| 235 |                                char **pmodulename, char **pargs)
 | 
|---|
| 236 | {
 | 
|---|
| 237 |         char *modulename;
 | 
|---|
| 238 |         char *args;
 | 
|---|
| 239 | 
 | 
|---|
| 240 |         if (strncmp(param, "idmap_", 6) == 0) {
 | 
|---|
| 241 |                 param += 6;
 | 
|---|
| 242 |                 DEBUG(1, ("idmap_init: idmap backend uses deprecated "
 | 
|---|
| 243 |                           "'idmap_' prefix.  Please replace 'idmap_%s' by "
 | 
|---|
| 244 |                           "'%s'\n", param, param));
 | 
|---|
| 245 |         }
 | 
|---|
| 246 | 
 | 
|---|
| 247 |         modulename = talloc_strdup(mem_ctx, param);
 | 
|---|
| 248 |         if (modulename == NULL) {
 | 
|---|
| 249 |                 return false;
 | 
|---|
| 250 |         }
 | 
|---|
| 251 | 
 | 
|---|
| 252 |         args = strchr(modulename, ':');
 | 
|---|
| 253 |         if (args == NULL) {
 | 
|---|
| 254 |                 *pmodulename = modulename;
 | 
|---|
| 255 |                 *pargs = NULL;
 | 
|---|
| 256 |                 return true;
 | 
|---|
| 257 |         }
 | 
|---|
| 258 | 
 | 
|---|
| 259 |         *args = '\0';
 | 
|---|
| 260 | 
 | 
|---|
| 261 |         args = talloc_strdup(mem_ctx, args+1);
 | 
|---|
| 262 |         if (args == NULL) {
 | 
|---|
| 263 |                 TALLOC_FREE(modulename);
 | 
|---|
| 264 |                 return false;
 | 
|---|
| 265 |         }
 | 
|---|
| 266 | 
 | 
|---|
| 267 |         *pmodulename = modulename;
 | 
|---|
| 268 |         *pargs = args;
 | 
|---|
| 269 |         return true;
 | 
|---|
| 270 | }
 | 
|---|
| 271 | 
 | 
|---|
| 272 | /**
 | 
|---|
| 273 |  * Initialize a domain structure
 | 
|---|
| 274 |  * @param[in] mem_ctx           memory context for the result
 | 
|---|
| 275 |  * @param[in] domainname        which domain is this for
 | 
|---|
| 276 |  * @param[in] modulename        which backend module
 | 
|---|
| 277 |  * @param[in] params            parameter to pass to the init function
 | 
|---|
| 278 |  * @result The initialized structure
 | 
|---|
| 279 |  */
 | 
|---|
| 280 | static struct idmap_domain *idmap_init_domain(TALLOC_CTX *mem_ctx,
 | 
|---|
| 281 |                                               const char *domainname,
 | 
|---|
| 282 |                                               const char *modulename,
 | 
|---|
| 283 |                                               const char *params)
 | 
|---|
| 284 | {
 | 
|---|
| 285 |         struct idmap_domain *result;
 | 
|---|
| 286 |         NTSTATUS status;
 | 
|---|
| 287 | 
 | 
|---|
| 288 |         result = talloc_zero(mem_ctx, struct idmap_domain);
 | 
|---|
| 289 |         if (result == NULL) {
 | 
|---|
| 290 |                 DEBUG(0, ("talloc failed\n"));
 | 
|---|
| 291 |                 return NULL;
 | 
|---|
| 292 |         }
 | 
|---|
| 293 | 
 | 
|---|
| 294 |         result->name = talloc_strdup(result, domainname);
 | 
|---|
| 295 |         if (result->name == NULL) {
 | 
|---|
| 296 |                 DEBUG(0, ("talloc failed\n"));
 | 
|---|
| 297 |                 goto fail;
 | 
|---|
| 298 |         }
 | 
|---|
| 299 | 
 | 
|---|
| 300 |         result->methods = get_methods(modulename);
 | 
|---|
| 301 |         if (result->methods == NULL) {
 | 
|---|
| 302 |                 DEBUG(3, ("idmap backend %s not found\n", modulename));
 | 
|---|
| 303 | 
 | 
|---|
| 304 |                 status = smb_probe_module("idmap", modulename);
 | 
|---|
| 305 |                 if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 306 |                         DEBUG(3, ("Could not probe idmap module %s\n",
 | 
|---|
| 307 |                                   modulename));
 | 
|---|
| 308 |                         goto fail;
 | 
|---|
| 309 |                 }
 | 
|---|
| 310 | 
 | 
|---|
| 311 |                 result->methods = get_methods(modulename);
 | 
|---|
| 312 |         }
 | 
|---|
| 313 |         if (result->methods == NULL) {
 | 
|---|
| 314 |                 DEBUG(1, ("idmap backend %s not found\n", modulename));
 | 
|---|
| 315 |                 goto fail;
 | 
|---|
| 316 |         }
 | 
|---|
| 317 | 
 | 
|---|
| 318 |         status = result->methods->init(result, params);
 | 
|---|
| 319 |         if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 320 |                 DEBUG(1, ("idmap initialization returned %s\n",
 | 
|---|
| 321 |                           nt_errstr(status)));
 | 
|---|
| 322 |                 goto fail;
 | 
|---|
| 323 |         }
 | 
|---|
| 324 | 
 | 
|---|
| 325 |         talloc_set_destructor(result, close_domain_destructor);
 | 
|---|
| 326 | 
 | 
|---|
| 327 |         return result;
 | 
|---|
| 328 | 
 | 
|---|
| 329 | fail:
 | 
|---|
| 330 |         TALLOC_FREE(result);
 | 
|---|
| 331 |         return NULL;
 | 
|---|
| 332 | }
 | 
|---|
| 333 | 
 | 
|---|
| 334 | /**
 | 
|---|
| 335 |  * Initialize the default domain structure
 | 
|---|
| 336 |  * @param[in] mem_ctx           memory context for the result
 | 
|---|
| 337 |  * @result The default domain structure
 | 
|---|
| 338 |  *
 | 
|---|
| 339 |  * This routine takes the module name from the "idmap backend" parameter,
 | 
|---|
| 340 |  * passing a possible parameter like ldap:ldap://ldap-url/ to the module.
 | 
|---|
| 341 |  */
 | 
|---|
| 342 | 
 | 
|---|
| 343 | static struct idmap_domain *idmap_init_default_domain(TALLOC_CTX *mem_ctx)
 | 
|---|
| 344 | {
 | 
|---|
| 345 |         struct idmap_domain *result;
 | 
|---|
| 346 |         char *modulename;
 | 
|---|
| 347 |         char *params;
 | 
|---|
| 348 | 
 | 
|---|
| 349 |         DEBUG(10, ("idmap_init_default_domain: calling static_init_idmap\n"));
 | 
|---|
| 350 | 
 | 
|---|
| 351 |         static_init_idmap;
 | 
|---|
| 352 | 
 | 
|---|
| 353 |         if (!parse_idmap_module(talloc_tos(), lp_idmap_backend(), &modulename,
 | 
|---|
| 354 |                                 ¶ms)) {
 | 
|---|
| 355 |                 DEBUG(1, ("parse_idmap_module failed\n"));
 | 
|---|
| 356 |                 return NULL;
 | 
|---|
| 357 |         }
 | 
|---|
| 358 | 
 | 
|---|
| 359 |         DEBUG(3, ("idmap_init: using '%s' as remote backend\n", modulename));
 | 
|---|
| 360 | 
 | 
|---|
| 361 |         result = idmap_init_domain(mem_ctx, "*", modulename, params);
 | 
|---|
| 362 |         if (result == NULL) {
 | 
|---|
| 363 |                 goto fail;
 | 
|---|
| 364 |         }
 | 
|---|
| 365 | 
 | 
|---|
| 366 |         TALLOC_FREE(modulename);
 | 
|---|
| 367 |         TALLOC_FREE(params);
 | 
|---|
| 368 |         return result;
 | 
|---|
| 369 | 
 | 
|---|
| 370 | fail:
 | 
|---|
| 371 |         TALLOC_FREE(modulename);
 | 
|---|
| 372 |         TALLOC_FREE(params);
 | 
|---|
| 373 |         TALLOC_FREE(result);
 | 
|---|
| 374 |         return NULL;
 | 
|---|
| 375 | }
 | 
|---|
| 376 | 
 | 
|---|
| 377 | /**
 | 
|---|
| 378 |  * Initialize a named domain structure
 | 
|---|
| 379 |  * @param[in] mem_ctx           memory context for the result
 | 
|---|
| 380 |  * @param[in] domname           the domain name
 | 
|---|
| 381 |  * @result The default domain structure
 | 
|---|
| 382 |  *
 | 
|---|
| 383 |  * This routine looks at the "idmap config <domname>" parameters to figure out
 | 
|---|
| 384 |  * the configuration.
 | 
|---|
| 385 |  */
 | 
|---|
| 386 | 
 | 
|---|
| 387 | static struct idmap_domain *idmap_init_named_domain(TALLOC_CTX *mem_ctx,
 | 
|---|
| 388 |                                                     const char *domname)
 | 
|---|
| 389 | {
 | 
|---|
| 390 |         struct idmap_domain *result = NULL;
 | 
|---|
| 391 |         char *config_option;
 | 
|---|
| 392 |         const char *backend;
 | 
|---|
| 393 | 
 | 
|---|
| 394 |         config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
 | 
|---|
| 395 |                                         domname);
 | 
|---|
| 396 |         if (config_option == NULL) {
 | 
|---|
| 397 |                 DEBUG(0, ("talloc failed\n"));
 | 
|---|
| 398 |                 goto fail;
 | 
|---|
| 399 |         }
 | 
|---|
| 400 | 
 | 
|---|
| 401 |         backend = lp_parm_const_string(-1, config_option, "backend", NULL);
 | 
|---|
| 402 |         if (backend == NULL) {
 | 
|---|
| 403 |                 DEBUG(1, ("no backend defined for %s\n", config_option));
 | 
|---|
| 404 |                 goto fail;
 | 
|---|
| 405 |         }
 | 
|---|
| 406 | 
 | 
|---|
| 407 |         result = idmap_init_domain(mem_ctx, domname, backend, NULL);
 | 
|---|
| 408 |         if (result == NULL) {
 | 
|---|
| 409 |                 goto fail;
 | 
|---|
| 410 |         }
 | 
|---|
| 411 | 
 | 
|---|
| 412 |         TALLOC_FREE(config_option);
 | 
|---|
| 413 |         return result;
 | 
|---|
| 414 | 
 | 
|---|
| 415 | fail:
 | 
|---|
| 416 |         TALLOC_FREE(config_option);
 | 
|---|
| 417 |         TALLOC_FREE(result);
 | 
|---|
| 418 |         return NULL;
 | 
|---|
| 419 | }
 | 
|---|
| 420 | 
 | 
|---|
| 421 | /**
 | 
|---|
| 422 |  * Initialize the passdb domain structure
 | 
|---|
| 423 |  * @param[in] mem_ctx           memory context for the result
 | 
|---|
| 424 |  * @result The default domain structure
 | 
|---|
| 425 |  *
 | 
|---|
| 426 |  * No config, passdb has its own configuration.
 | 
|---|
| 427 |  */
 | 
|---|
| 428 | 
 | 
|---|
| 429 | static struct idmap_domain *idmap_init_passdb_domain(TALLOC_CTX *mem_ctx)
 | 
|---|
| 430 | {
 | 
|---|
| 431 |         if (passdb_idmap_domain != NULL) {
 | 
|---|
| 432 |                 return passdb_idmap_domain;
 | 
|---|
| 433 |         }
 | 
|---|
| 434 | 
 | 
|---|
| 435 |         passdb_idmap_domain = idmap_init_domain(NULL, get_global_sam_name(),
 | 
|---|
| 436 |                                                 "passdb", NULL);
 | 
|---|
| 437 |         if (passdb_idmap_domain == NULL) {
 | 
|---|
| 438 |                 DEBUG(1, ("Could not init passdb idmap domain\n"));
 | 
|---|
| 439 |         }
 | 
|---|
| 440 | 
 | 
|---|
| 441 |         return passdb_idmap_domain;
 | 
|---|
| 442 | }
 | 
|---|
| 443 | 
 | 
|---|
| 444 | /**
 | 
|---|
| 445 |  * Find a domain struct according to a domain name
 | 
|---|
| 446 |  * @param[in] domname           Domain name to get the config for
 | 
|---|
| 447 |  * @result The default domain structure that fits
 | 
|---|
| 448 |  *
 | 
|---|
| 449 |  * This is the central routine in the winbindd-idmap child to pick the correct
 | 
|---|
| 450 |  * domain for looking up IDs. If domname is NULL or empty, we use the default
 | 
|---|
| 451 |  * domain. If it contains something, we try to use idmap_init_named_domain()
 | 
|---|
| 452 |  * to fetch the correct backend.
 | 
|---|
| 453 |  *
 | 
|---|
| 454 |  * The choice about "domname" is being made by the winbind parent, look at the
 | 
|---|
| 455 |  * "have_idmap_config" of "struct winbindd_domain" which is set in
 | 
|---|
| 456 |  * add_trusted_domain.
 | 
|---|
| 457 |  */
 | 
|---|
| 458 | 
 | 
|---|
| 459 | static struct idmap_domain *idmap_find_domain(const char *domname)
 | 
|---|
| 460 | {
 | 
|---|
| 461 |         struct idmap_domain *result;
 | 
|---|
| 462 |         int i;
 | 
|---|
| 463 | 
 | 
|---|
| 464 |         DEBUG(10, ("idmap_find_domain called for domain '%s'\n",
 | 
|---|
| 465 |                    domname?domname:"NULL"));
 | 
|---|
| 466 | 
 | 
|---|
| 467 |         /*
 | 
|---|
| 468 |          * Always init the default domain, we can't go without one
 | 
|---|
| 469 |          */
 | 
|---|
| 470 |         if (default_idmap_domain == NULL) {
 | 
|---|
| 471 |                 default_idmap_domain = idmap_init_default_domain(NULL);
 | 
|---|
| 472 |         }
 | 
|---|
| 473 |         if (default_idmap_domain == NULL) {
 | 
|---|
| 474 |                 return NULL;
 | 
|---|
| 475 |         }
 | 
|---|
| 476 | 
 | 
|---|
| 477 |         if ((domname == NULL) || (domname[0] == '\0')) {
 | 
|---|
| 478 |                 return default_idmap_domain;
 | 
|---|
| 479 |         }
 | 
|---|
| 480 | 
 | 
|---|
| 481 |         for (i=0; i<num_domains; i++) {
 | 
|---|
| 482 |                 if (strequal(idmap_domains[i]->name, domname)) {
 | 
|---|
| 483 |                         return idmap_domains[i];
 | 
|---|
| 484 |                 }
 | 
|---|
| 485 |         }
 | 
|---|
| 486 | 
 | 
|---|
| 487 |         if (idmap_domains == NULL) {
 | 
|---|
| 488 |                 /*
 | 
|---|
| 489 |                  * talloc context for all idmap domains
 | 
|---|
| 490 |                  */
 | 
|---|
| 491 |                 idmap_domains = TALLOC_ARRAY(NULL, struct idmap_domain *, 1);
 | 
|---|
| 492 |         }
 | 
|---|
| 493 | 
 | 
|---|
| 494 |         if (idmap_domains == NULL) {
 | 
|---|
| 495 |                 DEBUG(0, ("talloc failed\n"));
 | 
|---|
| 496 |                 return NULL;
 | 
|---|
| 497 |         }
 | 
|---|
| 498 | 
 | 
|---|
| 499 |         result = idmap_init_named_domain(idmap_domains, domname);
 | 
|---|
| 500 |         if (result == NULL) {
 | 
|---|
| 501 |                 /*
 | 
|---|
| 502 |                  * Could not init that domain -- try the default one
 | 
|---|
| 503 |                  */
 | 
|---|
| 504 |                 return default_idmap_domain;
 | 
|---|
| 505 |         }
 | 
|---|
| 506 | 
 | 
|---|
| 507 |         ADD_TO_ARRAY(idmap_domains, struct idmap_domain *, result,
 | 
|---|
| 508 |                      &idmap_domains, &num_domains);
 | 
|---|
| 509 |         return result;
 | 
|---|
| 510 | }
 | 
|---|
| 511 | 
 | 
|---|
| 512 | void idmap_close(void)
 | 
|---|
| 513 | {
 | 
|---|
| 514 |         if (idmap_alloc_ctx) {
 | 
|---|
| 515 |                 idmap_alloc_ctx->methods->close_fn();
 | 
|---|
| 516 |                 idmap_alloc_ctx->methods = NULL;
 | 
|---|
| 517 |         }
 | 
|---|
| 518 |         alloc_backends = NULL;
 | 
|---|
| 519 |         TALLOC_FREE(default_idmap_domain);
 | 
|---|
| 520 |         TALLOC_FREE(passdb_idmap_domain);
 | 
|---|
| 521 |         TALLOC_FREE(idmap_domains);
 | 
|---|
| 522 |         num_domains = 0;
 | 
|---|
| 523 | }
 | 
|---|
| 524 | 
 | 
|---|
| 525 | /**
 | 
|---|
| 526 |  * Initialize the idmap alloc backend
 | 
|---|
| 527 |  * @param[out] ctx              Where to put the alloc_ctx?
 | 
|---|
| 528 |  * @result Did it work fine?
 | 
|---|
| 529 |  *
 | 
|---|
| 530 |  * This routine first looks at "idmap alloc backend" and if that is not
 | 
|---|
| 531 |  * defined, it uses "idmap backend" for the module name.
 | 
|---|
| 532 |  */
 | 
|---|
| 533 | static NTSTATUS idmap_alloc_init(struct idmap_alloc_context **ctx)
 | 
|---|
| 534 | {
 | 
|---|
| 535 |         const char *backend;
 | 
|---|
| 536 |         char *modulename, *params;
 | 
|---|
| 537 |         NTSTATUS ret = NT_STATUS_NO_MEMORY;;
 | 
|---|
| 538 | 
 | 
|---|
| 539 |         static_init_idmap;
 | 
|---|
| 540 | 
 | 
|---|
| 541 |         if (idmap_alloc_ctx != NULL) {
 | 
|---|
| 542 |                 *ctx = idmap_alloc_ctx;
 | 
|---|
| 543 |                 return NT_STATUS_OK;
 | 
|---|
| 544 |         }
 | 
|---|
| 545 | 
 | 
|---|
| 546 |         idmap_alloc_ctx = talloc(NULL, struct idmap_alloc_context);
 | 
|---|
| 547 |         if (idmap_alloc_ctx == NULL) {
 | 
|---|
| 548 |                 DEBUG(0, ("talloc failed\n"));
 | 
|---|
| 549 |                 goto fail;
 | 
|---|
| 550 |         }
 | 
|---|
| 551 | 
 | 
|---|
| 552 |         backend = lp_idmap_alloc_backend();
 | 
|---|
| 553 |         if ((backend == NULL) || (backend[0] == '\0')) {
 | 
|---|
| 554 |                 backend = lp_idmap_backend();
 | 
|---|
| 555 |         }
 | 
|---|
| 556 | 
 | 
|---|
| 557 |         if (backend == NULL) {
 | 
|---|
| 558 |                 DEBUG(3, ("no idmap alloc backend defined\n"));
 | 
|---|
| 559 |                 ret = NT_STATUS_INVALID_PARAMETER;
 | 
|---|
| 560 |                 goto fail;
 | 
|---|
| 561 |         }
 | 
|---|
| 562 | 
 | 
|---|
| 563 |         if (!parse_idmap_module(idmap_alloc_ctx, backend, &modulename,
 | 
|---|
| 564 |                                 ¶ms)) {
 | 
|---|
| 565 |                 DEBUG(1, ("parse_idmap_module %s failed\n", backend));
 | 
|---|
| 566 |                 goto fail;
 | 
|---|
| 567 |         }
 | 
|---|
| 568 | 
 | 
|---|
| 569 |         idmap_alloc_ctx->methods = get_alloc_methods(modulename);
 | 
|---|
| 570 | 
 | 
|---|
| 571 |         if (idmap_alloc_ctx->methods == NULL) {
 | 
|---|
| 572 |                 ret = smb_probe_module("idmap", modulename);
 | 
|---|
| 573 |                 if (NT_STATUS_IS_OK(ret)) {
 | 
|---|
| 574 |                         idmap_alloc_ctx->methods =
 | 
|---|
| 575 |                                 get_alloc_methods(modulename);
 | 
|---|
| 576 |                 }
 | 
|---|
| 577 |         }
 | 
|---|
| 578 | 
 | 
|---|
| 579 |         if (idmap_alloc_ctx->methods == NULL) {
 | 
|---|
| 580 |                 DEBUG(1, ("could not find idmap alloc module %s\n", backend));
 | 
|---|
| 581 |                 ret = NT_STATUS_INVALID_PARAMETER;
 | 
|---|
| 582 |                 goto fail;
 | 
|---|
| 583 |         }
 | 
|---|
| 584 | 
 | 
|---|
| 585 |         ret = idmap_alloc_ctx->methods->init(params);
 | 
|---|
| 586 | 
 | 
|---|
| 587 |         if (!NT_STATUS_IS_OK(ret)) {
 | 
|---|
| 588 |                 DEBUG(0, ("ERROR: Initialization failed for alloc "
 | 
|---|
| 589 |                           "backend, deferred!\n"));
 | 
|---|
| 590 |                 goto fail;
 | 
|---|
| 591 |         }
 | 
|---|
| 592 | 
 | 
|---|
| 593 |         TALLOC_FREE(modulename);
 | 
|---|
| 594 |         TALLOC_FREE(params);
 | 
|---|
| 595 | 
 | 
|---|
| 596 |         *ctx = idmap_alloc_ctx;
 | 
|---|
| 597 |         return NT_STATUS_OK;
 | 
|---|
| 598 | 
 | 
|---|
| 599 | fail:
 | 
|---|
| 600 |         TALLOC_FREE(idmap_alloc_ctx);
 | 
|---|
| 601 |         return ret;
 | 
|---|
| 602 | }
 | 
|---|
| 603 | 
 | 
|---|
| 604 | /**************************************************************************
 | 
|---|
| 605 |  idmap allocator interface functions
 | 
|---|
| 606 | **************************************************************************/
 | 
|---|
| 607 | 
 | 
|---|
| 608 | NTSTATUS idmap_allocate_uid(struct unixid *id)
 | 
|---|
| 609 | {
 | 
|---|
| 610 |         struct idmap_alloc_context *ctx;
 | 
|---|
| 611 |         NTSTATUS ret;
 | 
|---|
| 612 | 
 | 
|---|
| 613 |         if (!NT_STATUS_IS_OK(ret = idmap_alloc_init(&ctx))) {
 | 
|---|
| 614 |                 return ret;
 | 
|---|
| 615 |         }
 | 
|---|
| 616 | 
 | 
|---|
| 617 |         id->type = ID_TYPE_UID;
 | 
|---|
| 618 |         return ctx->methods->allocate_id(id);
 | 
|---|
| 619 | }
 | 
|---|
| 620 | 
 | 
|---|
| 621 | NTSTATUS idmap_allocate_gid(struct unixid *id)
 | 
|---|
| 622 | {
 | 
|---|
| 623 |         struct idmap_alloc_context *ctx;
 | 
|---|
| 624 |         NTSTATUS ret;
 | 
|---|
| 625 | 
 | 
|---|
| 626 |         if (!NT_STATUS_IS_OK(ret = idmap_alloc_init(&ctx))) {
 | 
|---|
| 627 |                 return ret;
 | 
|---|
| 628 |         }
 | 
|---|
| 629 | 
 | 
|---|
| 630 |         id->type = ID_TYPE_GID;
 | 
|---|
| 631 |         return ctx->methods->allocate_id(id);
 | 
|---|
| 632 | }
 | 
|---|
| 633 | 
 | 
|---|
| 634 | NTSTATUS idmap_set_uid_hwm(struct unixid *id)
 | 
|---|
| 635 | {
 | 
|---|
| 636 |         struct idmap_alloc_context *ctx;
 | 
|---|
| 637 |         NTSTATUS ret;
 | 
|---|
| 638 | 
 | 
|---|
| 639 |         if (!NT_STATUS_IS_OK(ret = idmap_alloc_init(&ctx))) {
 | 
|---|
| 640 |                 return ret;
 | 
|---|
| 641 |         }
 | 
|---|
| 642 | 
 | 
|---|
| 643 |         id->type = ID_TYPE_UID;
 | 
|---|
| 644 |         return ctx->methods->set_id_hwm(id);
 | 
|---|
| 645 | }
 | 
|---|
| 646 | 
 | 
|---|
| 647 | NTSTATUS idmap_set_gid_hwm(struct unixid *id)
 | 
|---|
| 648 | {
 | 
|---|
| 649 |         struct idmap_alloc_context *ctx;
 | 
|---|
| 650 |         NTSTATUS ret;
 | 
|---|
| 651 | 
 | 
|---|
| 652 |         if (!NT_STATUS_IS_OK(ret = idmap_alloc_init(&ctx))) {
 | 
|---|
| 653 |                 return ret;
 | 
|---|
| 654 |         }
 | 
|---|
| 655 | 
 | 
|---|
| 656 |         id->type = ID_TYPE_GID;
 | 
|---|
| 657 |         return ctx->methods->set_id_hwm(id);
 | 
|---|
| 658 | }
 | 
|---|
| 659 | 
 | 
|---|
| 660 | NTSTATUS idmap_new_mapping(const struct dom_sid *psid, enum id_type type,
 | 
|---|
| 661 |                            struct unixid *pxid)
 | 
|---|
| 662 | {
 | 
|---|
| 663 |         struct dom_sid sid;
 | 
|---|
| 664 |         struct idmap_domain *dom;
 | 
|---|
| 665 |         struct id_map map;
 | 
|---|
| 666 |         NTSTATUS status;
 | 
|---|
| 667 | 
 | 
|---|
| 668 |         dom = idmap_find_domain(NULL);
 | 
|---|
| 669 |         if (dom == NULL) {
 | 
|---|
| 670 |                 DEBUG(3, ("no default domain, no place to write\n"));
 | 
|---|
| 671 |                 return NT_STATUS_ACCESS_DENIED;
 | 
|---|
| 672 |         }
 | 
|---|
| 673 |         if (dom->methods->set_mapping == NULL) {
 | 
|---|
| 674 |                 DEBUG(3, ("default domain not writable\n"));
 | 
|---|
| 675 |                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
 | 
|---|
| 676 |         }
 | 
|---|
| 677 | 
 | 
|---|
| 678 |         sid_copy(&sid, psid);
 | 
|---|
| 679 |         map.sid = &sid;
 | 
|---|
| 680 |         map.xid.type = type;
 | 
|---|
| 681 | 
 | 
|---|
| 682 |         switch (type) {
 | 
|---|
| 683 |         case ID_TYPE_UID:
 | 
|---|
| 684 |                 status = idmap_allocate_uid(&map.xid);
 | 
|---|
| 685 |                 break;
 | 
|---|
| 686 |         case ID_TYPE_GID:
 | 
|---|
| 687 |                 status = idmap_allocate_gid(&map.xid);
 | 
|---|
| 688 |                 break;
 | 
|---|
| 689 |         default:
 | 
|---|
| 690 |                 status = NT_STATUS_INVALID_PARAMETER;
 | 
|---|
| 691 |                 break;
 | 
|---|
| 692 |         }
 | 
|---|
| 693 | 
 | 
|---|
| 694 |         if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 695 |                 DEBUG(3, ("Could not allocate id: %s\n", nt_errstr(status)));
 | 
|---|
| 696 |                 return status;
 | 
|---|
| 697 |         }
 | 
|---|
| 698 | 
 | 
|---|
| 699 |         map.status = ID_MAPPED;
 | 
|---|
| 700 | 
 | 
|---|
| 701 |         DEBUG(10, ("Setting mapping: %s <-> %s %lu\n",
 | 
|---|
| 702 |                    sid_string_dbg(map.sid),
 | 
|---|
| 703 |                    (map.xid.type == ID_TYPE_UID) ? "UID" : "GID",
 | 
|---|
| 704 |                    (unsigned long)map.xid.id));
 | 
|---|
| 705 | 
 | 
|---|
| 706 |         status = dom->methods->set_mapping(dom, &map);
 | 
|---|
| 707 | 
 | 
|---|
| 708 |         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_COLLISION)) {
 | 
|---|
| 709 |                 struct id_map *ids[2];
 | 
|---|
| 710 |                 DEBUG(5, ("Mapping for %s exists - retrying to map sid\n",
 | 
|---|
| 711 |                           sid_string_dbg(map.sid)));
 | 
|---|
| 712 |                 ids[0] = ↦
 | 
|---|
| 713 |                 ids[1] = NULL;
 | 
|---|
| 714 |                 status = dom->methods->sids_to_unixids(dom, ids);
 | 
|---|
| 715 |         }
 | 
|---|
| 716 | 
 | 
|---|
| 717 |         if (!NT_STATUS_IS_OK(status)) {
 | 
|---|
| 718 |                 DEBUG(3, ("Could not store the new mapping: %s\n",
 | 
|---|
| 719 |                           nt_errstr(status)));
 | 
|---|
| 720 |                 return status;
 | 
|---|
| 721 |         }
 | 
|---|
| 722 | 
 | 
|---|
| 723 |         *pxid = map.xid;
 | 
|---|
| 724 | 
 | 
|---|
| 725 |         return NT_STATUS_OK;
 | 
|---|
| 726 | }
 | 
|---|
| 727 | 
 | 
|---|
| 728 | NTSTATUS idmap_backends_unixid_to_sid(const char *domname, struct id_map *id)
 | 
|---|
| 729 | {
 | 
|---|
| 730 |         struct idmap_domain *dom;
 | 
|---|
| 731 |         struct id_map *maps[2];
 | 
|---|
| 732 | 
 | 
|---|
| 733 |          DEBUG(10, ("idmap_backend_unixid_to_sid: domain = '%s', xid = %d "
 | 
|---|
| 734 |                     "(type %d)\n",
 | 
|---|
| 735 |                     domname?domname:"NULL", id->xid.id, id->xid.type));
 | 
|---|
| 736 | 
 | 
|---|
| 737 |         maps[0] = id;
 | 
|---|
| 738 |         maps[1] = NULL;
 | 
|---|
| 739 | 
 | 
|---|
| 740 |         /*
 | 
|---|
| 741 |          * Always give passdb a chance first
 | 
|---|
| 742 |          */
 | 
|---|
| 743 | 
 | 
|---|
| 744 |         dom = idmap_init_passdb_domain(NULL);
 | 
|---|
| 745 |         if ((dom != NULL)
 | 
|---|
| 746 |             && NT_STATUS_IS_OK(dom->methods->unixids_to_sids(dom, maps))
 | 
|---|
| 747 |             && id->status == ID_MAPPED) {
 | 
|---|
| 748 |                 return NT_STATUS_OK;
 | 
|---|
| 749 |         }
 | 
|---|
| 750 | 
 | 
|---|
| 751 |         dom = idmap_find_domain(domname);
 | 
|---|
| 752 |         if (dom == NULL) {
 | 
|---|
| 753 |                 return NT_STATUS_NONE_MAPPED;
 | 
|---|
| 754 |         }
 | 
|---|
| 755 | 
 | 
|---|
| 756 |         return dom->methods->unixids_to_sids(dom, maps);
 | 
|---|
| 757 | }
 | 
|---|
| 758 | 
 | 
|---|
| 759 | NTSTATUS idmap_backends_sid_to_unixid(const char *domain, struct id_map *id)
 | 
|---|
| 760 | {
 | 
|---|
| 761 |         struct idmap_domain *dom;
 | 
|---|
| 762 |         struct id_map *maps[2];
 | 
|---|
| 763 | 
 | 
|---|
| 764 |          DEBUG(10, ("idmap_backends_sid_to_unixid: domain = '%s', sid = [%s]\n",
 | 
|---|
| 765 |                     domain?domain:"NULL", sid_string_dbg(id->sid)));
 | 
|---|
| 766 | 
 | 
|---|
| 767 |         maps[0] = id;
 | 
|---|
| 768 |         maps[1] = NULL;
 | 
|---|
| 769 | 
 | 
|---|
| 770 |         if (sid_check_is_in_builtin(id->sid)
 | 
|---|
| 771 |             || (sid_check_is_in_our_domain(id->sid))) {
 | 
|---|
| 772 | 
 | 
|---|
| 773 |                 dom = idmap_init_passdb_domain(NULL);
 | 
|---|
| 774 |                 if (dom == NULL) {
 | 
|---|
| 775 |                         return NT_STATUS_NONE_MAPPED;
 | 
|---|
| 776 |                 }
 | 
|---|
| 777 |                 return dom->methods->sids_to_unixids(dom, maps);
 | 
|---|
| 778 |         }
 | 
|---|
| 779 | 
 | 
|---|
| 780 |         dom = idmap_find_domain(domain);
 | 
|---|
| 781 |         if (dom == NULL) {
 | 
|---|
| 782 |                 return NT_STATUS_NONE_MAPPED;
 | 
|---|
| 783 |         }
 | 
|---|
| 784 | 
 | 
|---|
| 785 |         return dom->methods->sids_to_unixids(dom, maps);
 | 
|---|
| 786 | }
 | 
|---|
| 787 | 
 | 
|---|
| 788 | NTSTATUS idmap_set_mapping(const struct id_map *map)
 | 
|---|
| 789 | {
 | 
|---|
| 790 |         struct idmap_domain *dom;
 | 
|---|
| 791 | 
 | 
|---|
| 792 |         dom = idmap_find_domain(NULL);
 | 
|---|
| 793 |         if (dom == NULL) {
 | 
|---|
| 794 |                 DEBUG(3, ("no default domain, no place to write\n"));
 | 
|---|
| 795 |                 return NT_STATUS_ACCESS_DENIED;
 | 
|---|
| 796 |         }
 | 
|---|
| 797 |         if (dom->methods->set_mapping == NULL) {
 | 
|---|
| 798 |                 DEBUG(3, ("default domain not writable\n"));
 | 
|---|
| 799 |                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
 | 
|---|
| 800 |         }
 | 
|---|
| 801 | 
 | 
|---|
| 802 |         return dom->methods->set_mapping(dom, map);
 | 
|---|
| 803 | }
 | 
|---|
| 804 | 
 | 
|---|
| 805 | NTSTATUS idmap_remove_mapping(const struct id_map *map)
 | 
|---|
| 806 | {
 | 
|---|
| 807 |         struct idmap_domain *dom;
 | 
|---|
| 808 | 
 | 
|---|
| 809 |         dom = idmap_find_domain(NULL);
 | 
|---|
| 810 |         if (dom == NULL) {
 | 
|---|
| 811 |                 DEBUG(3, ("no default domain, no place to write\n"));
 | 
|---|
| 812 |                 return NT_STATUS_ACCESS_DENIED;
 | 
|---|
| 813 |         }
 | 
|---|
| 814 |         if (dom->methods->remove_mapping == NULL) {
 | 
|---|
| 815 |                 DEBUG(3, ("default domain not writable\n"));
 | 
|---|
| 816 |                 return NT_STATUS_MEDIA_WRITE_PROTECTED;
 | 
|---|
| 817 |         }
 | 
|---|
| 818 | 
 | 
|---|
| 819 |         return dom->methods->remove_mapping(dom, map);
 | 
|---|
| 820 | }
 | 
|---|