s3: Remove close_fn from idmap_methods
[mat/samba.git] / source3 / winbindd / idmap.c
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    Copyright (C) Michael Adam 2010
9
10    This program is free software; you can redistribute it and/or modify
11    it under the terms of the GNU General Public License as published by
12    the Free Software Foundation; either version 3 of the License, or
13    (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18    GNU General Public License for more details.
19
20    You should have received a copy of the GNU General Public License
21    along with this program.  If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 #include "includes.h"
25 #include "winbindd.h"
26 #include "idmap.h"
27
28 #undef DBGC_CLASS
29 #define DBGC_CLASS DBGC_IDMAP
30
31 static_decl_idmap;
32
33 static void idmap_init(void)
34 {
35         static bool initialized;
36
37         if (initialized) {
38                 return;
39         }
40
41         DEBUG(10, ("idmap_init(): calling static_init_idmap\n"));
42
43         static_init_idmap;
44
45         initialized = true;
46 }
47
48 /**
49  * Pointer to the backend methods. Modules register themselves here via
50  * smb_register_idmap.
51  */
52
53 struct idmap_backend {
54         const char *name;
55         struct idmap_methods *methods;
56         struct idmap_backend *prev, *next;
57 };
58 static struct idmap_backend *backends = NULL;
59
60 /**
61  * Default idmap domain configured via "idmap backend".
62  */
63 static struct idmap_domain *default_idmap_domain;
64
65 /**
66  * Passdb idmap domain, not configurable. winbind must always give passdb a
67  * chance to map ids.
68  */
69 static struct idmap_domain *passdb_idmap_domain;
70
71 /**
72  * List of specially configured idmap domains. This list is filled on demand
73  * in the winbind idmap child when the parent winbind figures out via the
74  * special range parameter or via the domain SID that a special "idmap config
75  * domain" configuration is present.
76  */
77 static struct idmap_domain **idmap_domains = NULL;
78 static int num_domains = 0;
79
80 static struct idmap_methods *get_methods(const char *name)
81 {
82         struct idmap_backend *b;
83
84         for (b = backends; b; b = b->next) {
85                 if (strequal(b->name, name)) {
86                         return b->methods;
87                 }
88         }
89
90         return NULL;
91 }
92
93 bool idmap_is_offline(void)
94 {
95         return ( lp_winbind_offline_logon() &&
96              get_global_winbindd_state_offline() );
97 }
98
99 bool idmap_is_online(void)
100 {
101         return !idmap_is_offline();
102 }
103
104 /**********************************************************************
105  Allow a module to register itself as a method.
106 **********************************************************************/
107
108 NTSTATUS smb_register_idmap(int version, const char *name,
109                             struct idmap_methods *methods)
110 {
111         struct idmap_backend *entry;
112
113         if ((version != SMB_IDMAP_INTERFACE_VERSION)) {
114                 DEBUG(0, ("Failed to register idmap module.\n"
115                           "The module was compiled against "
116                           "SMB_IDMAP_INTERFACE_VERSION %d,\n"
117                           "current SMB_IDMAP_INTERFACE_VERSION is %d.\n"
118                           "Please recompile against the current version "
119                           "of samba!\n",
120                           version, SMB_IDMAP_INTERFACE_VERSION));
121                 return NT_STATUS_OBJECT_TYPE_MISMATCH;
122         }
123
124         if (!name || !name[0] || !methods) {
125                 DEBUG(0,("Called with NULL pointer or empty name!\n"));
126                 return NT_STATUS_INVALID_PARAMETER;
127         }
128
129         for (entry = backends; entry != NULL; entry = entry->next) {
130                 if (strequal(entry->name, name)) {
131                         DEBUG(0,("Idmap module %s already registered!\n",
132                                  name));
133                         return NT_STATUS_OBJECT_NAME_COLLISION;
134                 }
135         }
136
137         entry = talloc(NULL, struct idmap_backend);
138         if ( ! entry) {
139                 DEBUG(0,("Out of memory!\n"));
140                 TALLOC_FREE(entry);
141                 return NT_STATUS_NO_MEMORY;
142         }
143         entry->name = talloc_strdup(entry, name);
144         if ( ! entry->name) {
145                 DEBUG(0,("Out of memory!\n"));
146                 TALLOC_FREE(entry);
147                 return NT_STATUS_NO_MEMORY;
148         }
149         entry->methods = methods;
150
151         DLIST_ADD(backends, entry);
152         DEBUG(5, ("Successfully added idmap backend '%s'\n", name));
153         return NT_STATUS_OK;
154 }
155
156 static bool parse_idmap_module(TALLOC_CTX *mem_ctx, const char *param,
157                                char **pmodulename, char **pargs)
158 {
159         char *modulename;
160         char *args;
161
162         if (strncmp(param, "idmap_", 6) == 0) {
163                 param += 6;
164                 DEBUG(1, ("idmap_init: idmap backend uses deprecated "
165                           "'idmap_' prefix.  Please replace 'idmap_%s' by "
166                           "'%s'\n", param, param));
167         }
168
169         modulename = talloc_strdup(mem_ctx, param);
170         if (modulename == NULL) {
171                 return false;
172         }
173
174         args = strchr(modulename, ':');
175         if (args == NULL) {
176                 *pmodulename = modulename;
177                 *pargs = NULL;
178                 return true;
179         }
180
181         *args = '\0';
182
183         args = talloc_strdup(mem_ctx, args+1);
184         if (args == NULL) {
185                 TALLOC_FREE(modulename);
186                 return false;
187         }
188
189         *pmodulename = modulename;
190         *pargs = args;
191         return true;
192 }
193
194 /**
195  * Initialize a domain structure
196  * @param[in] mem_ctx           memory context for the result
197  * @param[in] domainname        which domain is this for
198  * @param[in] modulename        which backend module
199  * @param[in] params            parameter to pass to the init function
200  * @param[in] check_range       whether range checking should be done
201  * @result The initialized structure
202  */
203 static struct idmap_domain *idmap_init_domain(TALLOC_CTX *mem_ctx,
204                                               const char *domainname,
205                                               const char *modulename,
206                                               const char *params,
207                                               bool check_range)
208 {
209         struct idmap_domain *result;
210         NTSTATUS status;
211
212         result = talloc_zero(mem_ctx, struct idmap_domain);
213         if (result == NULL) {
214                 DEBUG(0, ("talloc failed\n"));
215                 return NULL;
216         }
217
218         result->name = talloc_strdup(result, domainname);
219         if (result->name == NULL) {
220                 DEBUG(0, ("talloc failed\n"));
221                 goto fail;
222         }
223
224         /*
225          * load ranges and read only information from the config
226          */
227         if (strequal(result->name, "*")) {
228                 /*
229                  * The default domain "*" is configured differently
230                  * from named domains.
231                  */
232                 uid_t low_uid = 0;
233                 uid_t high_uid = 0;
234                 gid_t low_gid = 0;
235                 gid_t high_gid = 0;
236
237                 result->low_id = 0;
238                 result->high_id = 0;
239
240                 if (!lp_idmap_uid(&low_uid, &high_uid)) {
241                         DEBUG(1, ("'idmap uid' not set!\n"));
242                         if (check_range) {
243                                 goto fail;
244                         }
245                 }
246
247                 result->low_id = low_uid;
248                 result->high_id = high_uid;
249
250                 if (!lp_idmap_gid(&low_gid, &high_gid)) {
251                         DEBUG(1, ("'idmap gid' not set!\n"));
252                         if (check_range) {
253                                 goto fail;
254                         }
255                 }
256
257                 if ((low_gid != low_uid) || (high_gid != high_uid)) {
258                         DEBUG(1, ("Warning: 'idmap uid' and 'idmap gid'"
259                               " ranges do not agree -- building "
260                               "intersection\n"));
261                         result->low_id = MAX(result->low_id, low_gid);
262                         result->high_id = MIN(result->high_id, high_gid);
263                 }
264
265                 result->read_only = lp_idmap_read_only();
266         } else {
267                 char *config_option = NULL;
268                 const char *range;
269
270                 config_option = talloc_asprintf(result, "idmap config %s",
271                                                 result->name);
272                 if (config_option == NULL) {
273                         DEBUG(0, ("Out of memory!\n"));
274                         goto fail;
275                 }
276
277                 range = lp_parm_const_string(-1, config_option, "range", NULL);
278                 if (range == NULL) {
279                         DEBUG(1, ("idmap range not specified for domain %s\n",
280                                   result ->name));
281                         if (check_range) {
282                                 goto fail;
283                         }
284                 } else if (sscanf(range, "%u - %u", &result->low_id,
285                                   &result->high_id) != 2)
286                 {
287                         DEBUG(1, ("invalid range '%s' specified for domain "
288                                   "'%s'\n", range, result->name));
289                         if (check_range) {
290                                 goto fail;
291                         }
292                 }
293
294                 result->read_only = lp_parm_bool(-1, config_option, "read only",
295                                                  false);
296
297                 talloc_free(config_option);
298         }
299
300         if (result->low_id > result->high_id) {
301                 DEBUG(1, ("Error: invalid idmap range detected: %lu - %lu\n",
302                           (unsigned long)result->low_id,
303                           (unsigned long)result->high_id));
304                 if (check_range) {
305                         goto fail;
306                 }
307         }
308
309         result->methods = get_methods(modulename);
310         if (result->methods == NULL) {
311                 DEBUG(3, ("idmap backend %s not found\n", modulename));
312
313                 status = smb_probe_module("idmap", modulename);
314                 if (!NT_STATUS_IS_OK(status)) {
315                         DEBUG(3, ("Could not probe idmap module %s\n",
316                                   modulename));
317                         goto fail;
318                 }
319
320                 result->methods = get_methods(modulename);
321         }
322         if (result->methods == NULL) {
323                 DEBUG(1, ("idmap backend %s not found\n", modulename));
324                 goto fail;
325         }
326
327         status = result->methods->init(result, params);
328         if (!NT_STATUS_IS_OK(status)) {
329                 DEBUG(1, ("idmap initialization returned %s\n",
330                           nt_errstr(status)));
331                 goto fail;
332         }
333
334         return result;
335
336 fail:
337         TALLOC_FREE(result);
338         return NULL;
339 }
340
341 /**
342  * Initialize the default domain structure
343  * @param[in] mem_ctx           memory context for the result
344  * @result The default domain structure
345  *
346  * This routine takes the module name from the "idmap backend" parameter,
347  * passing a possible parameter like ldap:ldap://ldap-url/ to the module.
348  */
349
350 static struct idmap_domain *idmap_init_default_domain(TALLOC_CTX *mem_ctx)
351 {
352         struct idmap_domain *result;
353         char *modulename;
354         char *params;
355
356         idmap_init();
357
358         if (!parse_idmap_module(talloc_tos(), lp_idmap_backend(), &modulename,
359                                 &params)) {
360                 DEBUG(1, ("parse_idmap_module failed\n"));
361                 return NULL;
362         }
363
364         DEBUG(3, ("idmap_init: using '%s' as remote backend\n", modulename));
365
366         result = idmap_init_domain(mem_ctx, "*", modulename, params, true);
367         if (result == NULL) {
368                 goto fail;
369         }
370
371         TALLOC_FREE(modulename);
372         TALLOC_FREE(params);
373         return result;
374
375 fail:
376         TALLOC_FREE(modulename);
377         TALLOC_FREE(params);
378         TALLOC_FREE(result);
379         return NULL;
380 }
381
382 /**
383  * Initialize a named domain structure
384  * @param[in] mem_ctx           memory context for the result
385  * @param[in] domname           the domain name
386  * @result The default domain structure
387  *
388  * This routine looks at the "idmap config <domname>" parameters to figure out
389  * the configuration.
390  */
391
392 static struct idmap_domain *idmap_init_named_domain(TALLOC_CTX *mem_ctx,
393                                                     const char *domname)
394 {
395         struct idmap_domain *result = NULL;
396         char *config_option;
397         const char *backend;
398
399         config_option = talloc_asprintf(talloc_tos(), "idmap config %s",
400                                         domname);
401         if (config_option == NULL) {
402                 DEBUG(0, ("talloc failed\n"));
403                 goto fail;
404         }
405
406         backend = lp_parm_const_string(-1, config_option, "backend", NULL);
407         if (backend == NULL) {
408                 DEBUG(1, ("no backend defined for %s\n", config_option));
409                 goto fail;
410         }
411
412         result = idmap_init_domain(mem_ctx, domname, backend, NULL, true);
413         if (result == NULL) {
414                 goto fail;
415         }
416
417         TALLOC_FREE(config_option);
418         return result;
419
420 fail:
421         TALLOC_FREE(config_option);
422         TALLOC_FREE(result);
423         return NULL;
424 }
425
426 /**
427  * Initialize the passdb domain structure
428  * @param[in] mem_ctx           memory context for the result
429  * @result The default domain structure
430  *
431  * No config, passdb has its own configuration.
432  */
433
434 static struct idmap_domain *idmap_init_passdb_domain(TALLOC_CTX *mem_ctx)
435 {
436         idmap_init();
437
438         /*
439          * Always init the default domain, we can't go without one
440          */
441         if (default_idmap_domain == NULL) {
442                 default_idmap_domain = idmap_init_default_domain(NULL);
443         }
444         if (default_idmap_domain == NULL) {
445                 return NULL;
446         }
447
448         if (passdb_idmap_domain != NULL) {
449                 return passdb_idmap_domain;
450         }
451
452         passdb_idmap_domain = idmap_init_domain(NULL, get_global_sam_name(),
453                                                 "passdb", NULL, false);
454         if (passdb_idmap_domain == NULL) {
455                 DEBUG(1, ("Could not init passdb idmap domain\n"));
456         }
457
458         return passdb_idmap_domain;
459 }
460
461 /**
462  * Find a domain struct according to a domain name
463  * @param[in] domname           Domain name to get the config for
464  * @result The default domain structure that fits
465  *
466  * This is the central routine in the winbindd-idmap child to pick the correct
467  * domain for looking up IDs. If domname is NULL or empty, we use the default
468  * domain. If it contains something, we try to use idmap_init_named_domain()
469  * to fetch the correct backend.
470  *
471  * The choice about "domname" is being made by the winbind parent, look at the
472  * "have_idmap_config" of "struct winbindd_domain" which is set in
473  * add_trusted_domain.
474  */
475
476 static struct idmap_domain *idmap_find_domain(const char *domname)
477 {
478         struct idmap_domain *result;
479         int i;
480
481         DEBUG(10, ("idmap_find_domain called for domain '%s'\n",
482                    domname?domname:"NULL"));
483
484         /*
485          * Always init the default domain, we can't go without one
486          */
487         if (default_idmap_domain == NULL) {
488                 default_idmap_domain = idmap_init_default_domain(NULL);
489         }
490         if (default_idmap_domain == NULL) {
491                 return NULL;
492         }
493
494         if ((domname == NULL) || (domname[0] == '\0')) {
495                 return default_idmap_domain;
496         }
497
498         for (i=0; i<num_domains; i++) {
499                 if (strequal(idmap_domains[i]->name, domname)) {
500                         return idmap_domains[i];
501                 }
502         }
503
504         if (idmap_domains == NULL) {
505                 /*
506                  * talloc context for all idmap domains
507                  */
508                 idmap_domains = TALLOC_ARRAY(NULL, struct idmap_domain *, 1);
509         }
510
511         if (idmap_domains == NULL) {
512                 DEBUG(0, ("talloc failed\n"));
513                 return NULL;
514         }
515
516         result = idmap_init_named_domain(idmap_domains, domname);
517         if (result == NULL) {
518                 /*
519                  * Could not init that domain -- try the default one
520                  */
521                 return default_idmap_domain;
522         }
523
524         ADD_TO_ARRAY(idmap_domains, struct idmap_domain *, result,
525                      &idmap_domains, &num_domains);
526         return result;
527 }
528
529 void idmap_close(void)
530 {
531         TALLOC_FREE(default_idmap_domain);
532         TALLOC_FREE(passdb_idmap_domain);
533         TALLOC_FREE(idmap_domains);
534         num_domains = 0;
535 }
536
537 /**************************************************************************
538  idmap allocator interface functions
539 **************************************************************************/
540
541 static NTSTATUS idmap_allocate_unixid(struct unixid *id)
542 {
543         struct idmap_domain *dom;
544         NTSTATUS ret;
545
546         dom = idmap_find_domain(NULL);
547
548         if (dom == NULL) {
549                 return NT_STATUS_UNSUCCESSFUL;
550         }
551
552         if (dom->methods->allocate_id == NULL) {
553                 return NT_STATUS_NOT_IMPLEMENTED;
554         }
555
556         ret = dom->methods->allocate_id(dom, id);
557
558         return ret;
559 }
560
561
562 NTSTATUS idmap_allocate_uid(struct unixid *id)
563 {
564         id->type = ID_TYPE_UID;
565         return idmap_allocate_unixid(id);
566 }
567
568 NTSTATUS idmap_allocate_gid(struct unixid *id)
569 {
570         id->type = ID_TYPE_GID;
571         return idmap_allocate_unixid(id);
572 }
573
574 NTSTATUS idmap_backends_unixid_to_sid(const char *domname, struct id_map *id)
575 {
576         struct idmap_domain *dom;
577         struct id_map *maps[2];
578
579          DEBUG(10, ("idmap_backend_unixid_to_sid: domain = '%s', xid = %d "
580                     "(type %d)\n",
581                     domname?domname:"NULL", id->xid.id, id->xid.type));
582
583         maps[0] = id;
584         maps[1] = NULL;
585
586         /*
587          * Always give passdb a chance first
588          */
589
590         dom = idmap_init_passdb_domain(NULL);
591         if ((dom != NULL)
592             && NT_STATUS_IS_OK(dom->methods->unixids_to_sids(dom, maps))
593             && id->status == ID_MAPPED) {
594                 return NT_STATUS_OK;
595         }
596
597         dom = idmap_find_domain(domname);
598         if (dom == NULL) {
599                 return NT_STATUS_NONE_MAPPED;
600         }
601
602         return dom->methods->unixids_to_sids(dom, maps);
603 }
604
605 NTSTATUS idmap_backends_sid_to_unixid(const char *domain, struct id_map *id)
606 {
607         struct idmap_domain *dom;
608         struct id_map *maps[2];
609
610         DEBUG(10, ("idmap_backends_sid_to_unixid: domain = '%s', sid = [%s]\n",
611                    domain?domain:"NULL", sid_string_dbg(id->sid)));
612
613         maps[0] = id;
614         maps[1] = NULL;
615
616         if (sid_check_is_in_builtin(id->sid)
617             || (sid_check_is_in_our_domain(id->sid)))
618         {
619                 NTSTATUS status;
620
621                 DEBUG(10, ("asking passdb...\n"));
622
623                 dom = idmap_init_passdb_domain(NULL);
624                 if (dom == NULL) {
625                         return NT_STATUS_NONE_MAPPED;
626                 }
627                 status = dom->methods->sids_to_unixids(dom, maps);
628
629                 if (NT_STATUS_IS_OK(status) && id->status == ID_MAPPED) {
630                         return status;
631                 }
632
633                 DEBUG(10, ("passdb could not map.\n"));
634
635                 return NT_STATUS_NONE_MAPPED;
636         }
637
638         dom = idmap_find_domain(domain);
639         if (dom == NULL) {
640                 return NT_STATUS_NONE_MAPPED;
641         }
642
643         return dom->methods->sids_to_unixids(dom, maps);
644 }