This commit was generated by cvs2svn to compensate for changes in r30,
[kai/samba-autobuild/.git] / source4 / sam / interface.c
1 /*
2    Unix SMB/CIFS implementation.
3    Password and authentication handling
4    Copyright (C) Andrew Bartlett                        2002
5    Copyright (C) Jelmer Vernooij                        2002
6    Copyright (C) Stefan (metze) Metzmacher              2002
7    Copyright (C) Kai Krüger                             2002
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 2 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, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_SAM
28
29 extern DOM_SID global_sid_Builtin;
30
31 /** List of various built-in sam modules */
32
33 const struct sam_init_function_entry builtin_sam_init_functions[] = {
34         { "plugin", sam_init_plugin },
35 #ifdef HAVE_LDAP
36         { "ads", sam_init_ads },
37 #endif
38         { "skel", sam_init_skel },
39         { NULL, NULL}
40 };
41
42
43 static NTSTATUS sam_get_methods_by_sid(const SAM_CONTEXT *context, SAM_METHODS **sam_method, const DOM_SID *domainsid)
44 {
45         SAM_METHODS     *tmp_methods;
46
47         DEBUG(5,("sam_get_methods_by_sid: %d\n", __LINE__));
48
49         /* invalid sam_context specified */
50         SAM_ASSERT(context && context->methods);
51
52         tmp_methods = context->methods;
53
54         while (tmp_methods) {
55                 if (sid_equal(domainsid, &(tmp_methods->domain_sid)))
56                 {
57                         (*sam_method) = tmp_methods;
58                         return NT_STATUS_OK;
59                 }
60                 tmp_methods = tmp_methods->next;
61         }
62
63         DEBUG(3,("sam_get_methods_by_sid: There is no backend specified for domain %s\n", sid_string_static(domainsid)));
64
65         return NT_STATUS_NO_SUCH_DOMAIN;
66 }
67
68 static NTSTATUS sam_get_methods_by_name(const SAM_CONTEXT *context, SAM_METHODS **sam_method, const char *domainname)
69 {
70         SAM_METHODS     *tmp_methods;
71
72         DEBUG(5,("sam_get_methods_by_name: %d\n", __LINE__));
73
74         /* invalid sam_context specified */
75         SAM_ASSERT(context && context->methods);
76
77         tmp_methods = context->methods;
78
79         while (tmp_methods) {
80                 if (strequal(domainname, tmp_methods->domain_name))
81                 {
82                         (*sam_method) = tmp_methods;
83                         return NT_STATUS_OK;
84                 }
85                 tmp_methods = tmp_methods->next;
86         }
87
88         DEBUG(3,("sam_get_methods_by_sid: There is no backend specified for domain %s\n", domainname));
89
90         return NT_STATUS_NO_SUCH_DOMAIN;
91 }
92
93 static NTSTATUS make_sam_methods(TALLOC_CTX *mem_ctx, SAM_METHODS **methods)
94 {
95         *methods = talloc(mem_ctx, sizeof(SAM_METHODS));
96
97         if (!*methods) {
98                 return NT_STATUS_NO_MEMORY;
99         }
100
101         ZERO_STRUCTP(*methods);
102
103         return NT_STATUS_OK;
104 }
105
106 /******************************************************************
107   Free and cleanup a sam context, any associated data and anything
108   that the attached modules might have associated.
109  *******************************************************************/
110
111 void free_sam_context(SAM_CONTEXT **context)
112 {
113         SAM_METHODS *sam_selected = (*context)->methods;
114
115         while (sam_selected) {
116                 if (sam_selected->free_private_data) {
117                         sam_selected->free_private_data(&(sam_selected->private_data));
118                 }
119                 sam_selected = sam_selected->next;
120         }
121
122         talloc_destroy((*context)->mem_ctx);
123         *context = NULL;
124 }
125
126 /******************************************************************
127   Make a backend_entry from scratch
128  *******************************************************************/
129  
130 static NTSTATUS make_backend_entry(SAM_BACKEND_ENTRY *backend_entry, char *sam_backend_string)
131 {
132         char *tmp = NULL;
133         char *tmp_string = sam_backend_string;
134         
135         DEBUG(5,("make_backend_entry: %d\n", __LINE__));
136         
137         SAM_ASSERT(sam_backend_string && backend_entry);
138         
139         backend_entry->module_name = sam_backend_string;
140         
141         DEBUG(5,("makeing backend_entry for %s\n", backend_entry->module_name));
142         
143         if ((tmp = strrchr(tmp_string, '|')) != NULL) {
144                 DEBUGADD(20,("a domain name has been specified\n"));
145                 *tmp = 0;
146                 backend_entry->domain_name = smb_xstrdup(tmp + 1);
147                 tmp_string = tmp + 1;
148         }
149         
150         if ((tmp = strchr(tmp_string, ':')) != NULL) {
151                 DEBUG(20,("options for the backend have been specified\n"));
152                 *tmp = 0;
153                 backend_entry->module_params = smb_xstrdup(tmp + 1);
154                 tmp_string = tmp + 1;
155         }
156                 
157         if (backend_entry->domain_name == NULL) {
158                 DEBUG(10,("make_backend_entry: no domain was specified for sam module %s. Using default domain %s\n",
159                         backend_entry->module_name, lp_workgroup()));
160                 backend_entry->domain_name = smb_xstrdup(lp_workgroup());
161         }
162         
163         if ((backend_entry->domain_sid = (DOM_SID *)malloc(sizeof(DOM_SID))) == NULL) {
164                 DEBUG(0,("make_backend_entry: failed to malloc domain_sid\n"));
165                 return NT_STATUS_NO_MEMORY;
166         }
167         
168         DEBUG(10,("looking up sid for domain %s\n", backend_entry->domain_name));
169         
170         if (!secrets_fetch_domain_sid(backend_entry->domain_name, backend_entry->domain_sid)) {
171                 DEBUG(2,("make_backend_entry: There is no SID stored for domain %s. Creating a new one.\n",
172                         backend_entry->domain_name));           
173                 DEBUG(0, ("FIXME in %s:%d\n", __FILE__, __LINE__));
174                 ZERO_STRUCTP(backend_entry->domain_sid);
175         }
176         
177         DEBUG(5,("make_backend_entry: module name: %s, module parameters: %s, domain name: %s, domain sid: %s\n",
178                 backend_entry->module_name, backend_entry->module_params, backend_entry->domain_name, sid_string_static(backend_entry->domain_sid)));
179         
180         return NT_STATUS_OK;
181 }
182
183 /******************************************************************
184  create sam_methods struct based on sam_backend_entry
185  *****************************************************************/
186
187 static NTSTATUS make_sam_methods_backend_entry(SAM_CONTEXT *context, SAM_METHODS **methods_ptr, SAM_BACKEND_ENTRY *backend_entry)
188 {
189         NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
190         SAM_METHODS *methods;
191         int i;
192
193         DEBUG(5,("make_sam_methods_backend_entry: %d\n", __LINE__));
194
195         if (!NT_STATUS_IS_OK(nt_status = make_sam_methods(context->mem_ctx, methods_ptr))) {
196                 return nt_status;
197         }
198
199         methods = *methods_ptr;
200         methods->backendname = talloc_strdup(context->mem_ctx, backend_entry->module_name);
201         methods->domain_name = talloc_strdup(context->mem_ctx, backend_entry->domain_name);
202         sid_copy(&methods->domain_sid, backend_entry->domain_sid);
203         methods->parent = context;
204
205         DEBUG(5,("Attempting to find sam backend %s\n", backend_entry->module_name));
206         for (i = 0; builtin_sam_init_functions[i].module_name; i++)
207         {
208                 if (strequal(builtin_sam_init_functions[i].module_name, backend_entry->module_name))
209                 {
210                         DEBUG(5,("Found sam backend %s (at pos %d)\n", backend_entry->module_name, i));
211                         DEBUGADD(5,("initialising it with options=%s for domain %s\n", backend_entry->module_params, sid_string_static(backend_entry->domain_sid)));
212                         nt_status = builtin_sam_init_functions[i].init(methods, backend_entry->module_params);
213                         if (NT_STATUS_IS_OK(nt_status)) {
214                                 DEBUG(5,("sam backend %s has a valid init\n", backend_entry->module_name));
215                         } else {
216                                 DEBUG(2,("sam backend %s did not correctly init (error was %s)\n",
217                                         backend_entry->module_name, nt_errstr(nt_status)));
218                         }
219                         return nt_status;
220                 }
221         }
222         
223         DEBUG(2,("could not find backend %s\n", backend_entry->module_name));
224
225         return NT_STATUS_INVALID_PARAMETER;
226 }
227
228 static NTSTATUS sam_context_check_default_backends(SAM_CONTEXT *context)
229 {
230         SAM_BACKEND_ENTRY entry;
231         DOM_SID *global_sam_sid  = get_global_sam_sid(); /* lp_workgroup doesn't play nicely with multiple domains */
232         SAM_METHODS *methods, *tmpmethods;
233         NTSTATUS ntstatus;
234         
235         DEBUG(5,("sam_context_check_default_backends: %d\n", __LINE__));
236
237         /* Make sure domain lp_workgroup() is available */
238         
239         ntstatus = sam_get_methods_by_sid(context, &methods, &global_sid_Builtin);
240
241         if (NT_STATUS_EQUAL(ntstatus, NT_STATUS_NO_SUCH_DOMAIN)) {
242                 DEBUG(4,("There was no backend specified for domain %s(%s); using %s\n",
243                         lp_workgroup(), sid_string_static(global_sam_sid), SAM_DEFAULT_BACKEND));
244
245                 SAM_ASSERT(global_sam_sid);
246
247                 entry.module_name = SAM_DEFAULT_BACKEND;
248                 entry.module_params = NULL;
249                 entry.domain_name = lp_workgroup();
250                 entry.domain_sid = (DOM_SID *)malloc(sizeof(DOM_SID));
251                 sid_copy(entry.domain_sid, global_sam_sid);
252
253                 if (!NT_STATUS_IS_OK(ntstatus = make_sam_methods_backend_entry(context, &methods, &entry))) {
254                         DEBUG(4,("make_sam_methods_backend_entry failed\n"));
255                         return ntstatus;
256                 }
257
258                 DLIST_ADD_END(context->methods, methods, tmpmethods);
259
260         } else if (!NT_STATUS_IS_OK(ntstatus)) {
261                 DEBUG(2, ("sam_get_methods_by_sid failed for %s\n", lp_workgroup()));
262                 return ntstatus;
263         }
264
265         /* Make sure the BUILTIN domain is available */
266
267         ntstatus = sam_get_methods_by_sid(context, &methods, global_sam_sid);
268         
269         if (NT_STATUS_EQUAL(ntstatus, NT_STATUS_NO_SUCH_DOMAIN)) {
270                 DEBUG(4,("There was no backend specified for domain BUILTIN; using %s\n", 
271                                  SAM_DEFAULT_BACKEND));
272                 entry.module_name = SAM_DEFAULT_BACKEND;
273                 entry.module_params = NULL;
274                 entry.domain_name = "BUILTIN";
275                 entry.domain_sid    = (DOM_SID *)malloc(sizeof(DOM_SID)); 
276                 sid_copy(entry.domain_sid, &global_sid_Builtin);
277
278                 if (!NT_STATUS_IS_OK(ntstatus = make_sam_methods_backend_entry(context, &methods,  &entry))) {
279                         DEBUG(4,("make_sam_methods_backend_entry failed\n"));
280                         return ntstatus;
281                 }
282
283                 DLIST_ADD_END(context->methods, methods, tmpmethods);
284         } else if (!NT_STATUS_IS_OK(ntstatus)) {
285                 DEBUG(2, ("sam_get_methods_by_sid failed for BUILTIN\n"));
286                 return ntstatus;
287         }
288
289         return NT_STATUS_OK;
290 }
291
292 static NTSTATUS check_duplicate_backend_entries(SAM_BACKEND_ENTRY **backend_entries, int *nBackends)
293 {
294         int i, j;
295         
296         DEBUG(5,("check_duplicate_backend_entries: %d\n", __LINE__));
297         
298         for (i = 0; i < *nBackends; i++) {
299                 for (j = i + 1; j < *nBackends; j++) {
300                         if (sid_equal((*backend_entries)[i].domain_sid, (*backend_entries)[j].domain_sid)) {
301                                 DEBUG(0,("two backend modules claim the same domain %s\n",
302                                         sid_string_static((*backend_entries)[j].domain_sid)));
303                                 return NT_STATUS_INVALID_PARAMETER;                     
304                         }
305                 }               
306         }
307
308         return NT_STATUS_OK;
309 }
310
311 NTSTATUS make_sam_context_list(SAM_CONTEXT **context, char **sam_backends_param)
312 {
313         int i = 0, j = 0;
314         SAM_METHODS *curmethods, *tmpmethods;
315         int nBackends               = 0;
316         SAM_BACKEND_ENTRY *backends = NULL;
317         NTSTATUS nt_status          = NT_STATUS_UNSUCCESSFUL;
318
319         DEBUG(5,("make_sam_context_from_conf: %d\n", __LINE__));
320
321         if (!sam_backends_param) {
322                 DEBUG(1, ("no SAM backeds specified!\n"));
323                 return NT_STATUS_INVALID_PARAMETER;
324         }
325
326         if (!NT_STATUS_IS_OK(nt_status = make_sam_context(context))) {
327                 DEBUG(4,("make_sam_context failed\n"));
328                 return nt_status;
329         }
330
331         while (sam_backends_param[nBackends])
332                 nBackends++;
333
334         DEBUG(6,("There are %d domains listed with their backends\n", nBackends));
335
336         if ((backends = (SAM_BACKEND_ENTRY *)malloc(sizeof(*backends)*nBackends)) == NULL) {
337                 DEBUG(0,("make_sam_context_list: failed to allocate backends\n"));
338                 return NT_STATUS_NO_MEMORY;
339         }
340
341         memset(backends, '\0', sizeof(*backends)*nBackends);
342
343         for (i = 0; i < nBackends; i++) {
344                 DEBUG(8,("processing %s\n",sam_backends_param[i]));
345                 if (!NT_STATUS_IS_OK(nt_status = make_backend_entry(&backends[i], sam_backends_param[i]))) {
346                         DEBUG(4,("make_backend_entry failed\n"));
347                         for (j = 0; j < nBackends; j++) SAFE_FREE(backends[j].domain_sid);
348                         SAFE_FREE(backends);
349                         free_sam_context(context);
350                         return nt_status;
351                 }
352         }
353
354         if (!NT_STATUS_IS_OK(nt_status = check_duplicate_backend_entries(&backends, &nBackends))) {
355                 DEBUG(4,("check_duplicate_backend_entries failed\n"));
356                 for (j = 0; j < nBackends; j++) SAFE_FREE(backends[j].domain_sid);
357                 SAFE_FREE(backends);
358                 free_sam_context(context);
359                 return nt_status;
360         }
361
362         for (i = 0; i < nBackends; i++) {
363                 if (!NT_STATUS_IS_OK(nt_status = make_sam_methods_backend_entry(*context, &curmethods,  &backends[i]))) {
364                         DEBUG(4,("make_sam_methods_backend_entry failed\n"));
365                         for (j = 0; j < nBackends; j++) SAFE_FREE(backends[j].domain_sid);
366                         SAFE_FREE(backends);
367                         free_sam_context(context);
368                         return nt_status;
369                 }
370                 DLIST_ADD_END((*context)->methods, curmethods, tmpmethods);
371         }
372         
373         for (i = 0; i < nBackends; i++) SAFE_FREE(backends[i].domain_sid);
374
375         SAFE_FREE(backends);
376         return NT_STATUS_OK;
377 }
378
379 /******************************************************************
380   Make a sam_context from scratch.
381  *******************************************************************/
382
383 NTSTATUS make_sam_context(SAM_CONTEXT **context) 
384 {
385         TALLOC_CTX *mem_ctx;
386
387         mem_ctx = talloc_init("sam_context internal allocation context");
388
389         if (!mem_ctx) {
390                 DEBUG(0, ("make_sam_context: talloc init failed!\n"));
391                 return NT_STATUS_NO_MEMORY;
392         }               
393
394         *context = talloc(mem_ctx, sizeof(**context));
395         if (!*context) {
396                 DEBUG(0, ("make_sam_context: talloc failed!\n"));
397                 return NT_STATUS_NO_MEMORY;
398         }
399
400         ZERO_STRUCTP(*context);
401
402         (*context)->mem_ctx = mem_ctx;
403
404         (*context)->free_fn = free_sam_context;
405
406         return NT_STATUS_OK;
407 }
408
409 /******************************************************************
410   Return an already initialised sam_context, to facilitate backward 
411   compatibility (see functions below).
412  *******************************************************************/
413
414 static struct sam_context *sam_get_static_context(BOOL reload) 
415 {
416         static SAM_CONTEXT *sam_context = NULL;
417
418         if ((sam_context) && (reload)) {
419                 sam_context->free_fn(&sam_context);
420                 sam_context = NULL;
421         }
422
423         if (!sam_context) {
424                 if (!NT_STATUS_IS_OK(make_sam_context_list(&sam_context, lp_sam_backend()))) {
425                         DEBUG(4,("make_sam_context_list failed\n"));
426                         return NULL;
427                 }
428
429                 /* Make sure the required domains (default domain, builtin) are available */
430                 if (!NT_STATUS_IS_OK(sam_context_check_default_backends(sam_context))) {
431                         DEBUG(4,("sam_context_check_default_backends failed\n"));
432                         return NULL;
433                 }
434         }
435
436         return sam_context;
437 }
438
439 /***************************************************************
440   Initialize the static context (at smbd startup etc). 
441
442   If uninitialised, context will auto-init on first use.
443  ***************************************************************/
444
445 BOOL initialize_sam(BOOL reload)
446 {       
447         return (sam_get_static_context(reload) != NULL);
448 }
449
450
451 /**************************************************************
452  External API.  This is what the rest of the world calls...
453 ***************************************************************/
454
455 /******************************************************************
456   sam_* functions are used to link the external SAM interface
457   with the internal backends. These functions lookup the appropriate
458   backends for the domain and pass on to the function in sam_methods
459   in the selected backend
460
461   When the context parmater is NULL, the default is used.
462  *******************************************************************/
463
464 #define SAM_SETUP_CONTEXT if (!context) \
465                 context = sam_get_static_context(False);\
466         if (!context) {\
467                 return NT_STATUS_UNSUCCESSFUL; \
468         }\
469         
470
471
472 NTSTATUS sam_get_sec_desc(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, const DOM_SID *sid, SEC_DESC **sd)
473 {
474         SAM_METHODS     *tmp_methods;
475         NTSTATUS        nt_status;
476
477         DEBUG(5,("sam_get_sec_desc: %d\n", __LINE__));
478
479         SAM_SETUP_CONTEXT;
480
481         if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_sid(context, &tmp_methods, sid))) {
482                 DEBUG(4,("sam_get_methods_by_sid failed\n"));
483                 return nt_status;
484         }
485
486         if (!tmp_methods->sam_get_sec_desc) {
487                 DEBUG(3, ("sam_get_sec_desc: sam_methods of the domain did not specify sam_get_sec_desc\n"));
488                 return NT_STATUS_NOT_IMPLEMENTED;
489         }
490
491         if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_get_sec_desc(tmp_methods, access_token, sid, sd))) {
492                 DEBUG(4,("sam_get_sec_desc for %s in backend %s failed\n", sid_string_static(sid), tmp_methods->backendname));
493                 return nt_status;
494         }
495
496         return NT_STATUS_OK;
497 }
498
499 NTSTATUS sam_set_sec_desc(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, const DOM_SID *sid, const SEC_DESC *sd)
500 {
501         SAM_METHODS     *tmp_methods;
502         NTSTATUS        nt_status;
503
504         DEBUG(5,("sam_set_sec_desc: %d\n", __LINE__));
505         
506         SAM_SETUP_CONTEXT;
507
508         if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_sid(context, &tmp_methods, sid))) {
509                 DEBUG(4,("sam_get_methods_by_sid failed\n"));
510                 return nt_status;
511         }
512
513         if (!tmp_methods->sam_set_sec_desc) {
514                 DEBUG(3, ("sam_set_sec_desc: sam_methods of the domain did not specify sam_set_sec_desc\n"));
515                 return NT_STATUS_NOT_IMPLEMENTED;
516         }
517
518         if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_set_sec_desc(tmp_methods, access_token, sid, sd))) {
519                 DEBUG(4,("sam_set_sec_desc for %s in backend %s failed\n", sid_string_static(sid), tmp_methods->backendname));
520                 return nt_status;
521         }
522
523         return NT_STATUS_OK;
524 }
525
526
527 NTSTATUS sam_lookup_name(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, const char *domain, const char *name, DOM_SID *sid, uint32 *type)
528 {
529         SAM_METHODS     *tmp_methods;
530         NTSTATUS        nt_status;
531
532         DEBUG(5,("sam_lookup_name: %d\n", __LINE__));
533
534         SAM_SETUP_CONTEXT;
535
536         if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_name(context, &tmp_methods, domain))) {
537                 DEBUG(4,("sam_get_methods_by_name failed\n"));
538                 return nt_status;
539         }
540
541         if (!tmp_methods->sam_lookup_name) {
542                 DEBUG(3, ("sam_lookup_name: sam_methods of the domain did not specify sam_lookup_name\n"));
543                 return NT_STATUS_NOT_IMPLEMENTED;
544         }
545
546         if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_lookup_name(tmp_methods, access_token, name, sid, type))) {
547                 DEBUG(4,("sam_lookup_name for %s\\%s in backend %s failed\n",
548                                  tmp_methods->domain_name, name, tmp_methods->backendname));
549                 return nt_status;
550         }
551
552         return NT_STATUS_OK;
553 }
554
555 NTSTATUS sam_lookup_sid(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, TALLOC_CTX *mem_ctx, const DOM_SID *sid, char **name, uint32 *type)
556 {
557         SAM_METHODS     *tmp_methods;
558         uint32          rid;
559         NTSTATUS        nt_status;
560         DOM_SID         domainsid;
561
562         DEBUG(5,("sam_lookup_sid: %d\n", __LINE__));
563
564         SAM_SETUP_CONTEXT;
565
566         sid_copy(&domainsid, sid);
567         if (!sid_split_rid(&domainsid, &rid)) {
568                 DEBUG(3,("sam_lookup_sid: failed to split the sid\n"));
569                 return NT_STATUS_INVALID_SID;
570         }
571
572         if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_sid(context, &tmp_methods, &domainsid))) {
573                 DEBUG(4,("sam_get_methods_by_sid failed\n"));
574                 return nt_status;
575         }
576
577         if (!tmp_methods->sam_lookup_sid) {
578                 DEBUG(3, ("sam_lookup_sid: sam_methods of the domain did not specify sam_lookup_sid\n"));
579                 return NT_STATUS_NOT_IMPLEMENTED;
580         }
581
582         if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_lookup_sid(tmp_methods, access_token, mem_ctx, sid, name, type))) {
583                 DEBUG(4,("sam_lookup_name for %s in backend %s failed\n",
584                                  sid_string_static(sid), tmp_methods->backendname));
585                 return nt_status;
586         }
587
588         return NT_STATUS_OK;
589 }
590
591
592 NTSTATUS sam_update_domain(const SAM_CONTEXT *context, const SAM_DOMAIN_HANDLE *domain)
593 {
594         const SAM_METHODS *tmp_methods;
595         NTSTATUS     nt_status;
596
597         DEBUG(5,("sam_update_domain: %d\n", __LINE__));
598         
599         SAM_SETUP_CONTEXT;
600
601         /* invalid domain specified */
602         SAM_ASSERT(domain && domain->current_sam_methods);
603         
604         tmp_methods = domain->current_sam_methods;
605         
606         if (!tmp_methods->sam_update_domain) {
607                 DEBUG(3, ("sam_update_domain: sam_methods of the domain did not specify sam_update_domain\n"));
608                 return NT_STATUS_NOT_IMPLEMENTED;
609         }
610
611         if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_update_domain(tmp_methods, domain))){
612                 DEBUG(4,("sam_update_domain in backend %s failed\n",
613                                  tmp_methods->backendname));
614                 return nt_status;
615         }
616
617         return NT_STATUS_OK;
618 }
619
620 NTSTATUS sam_enum_domains(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, int32 *domain_count, DOM_SID **domains, char ***domain_names)
621 {
622         SAM_METHODS     *tmp_methods;
623         NTSTATUS         nt_status;
624
625         SEC_DESC        *sd;
626         size_t          sd_size;
627         uint32          acc_granted;
628         int             i = 0;
629
630         DEBUG(5,("sam_enum_domains: %d\n", __LINE__));
631
632         SAM_SETUP_CONTEXT;
633
634         /* invalid parmaters specified */
635         SAM_ASSERT(domain_count && domains && domain_names);
636
637         if (!NT_STATUS_IS_OK(nt_status = samr_make_sam_obj_sd(context->mem_ctx, &sd, &sd_size))) {
638                 DEBUG(4,("samr_make_sam_obj_sd failed\n"));
639                 return nt_status;
640         }
641
642         if (!se_access_check(sd, access_token, SA_RIGHT_SAM_ENUM_DOMAINS, &acc_granted, &nt_status)) {
643                 DEBUG(3,("sam_enum_domains: ACCESS DENIED\n"));
644                         return nt_status;
645         }
646
647         tmp_methods= context->methods;
648         *domain_count = 0;
649
650         while (tmp_methods) {
651                 (*domain_count)++;
652                 tmp_methods= tmp_methods->next;
653         }
654
655         DEBUG(6,("sam_enum_domains: enumerating %d domains\n", (*domain_count)));
656
657         tmp_methods = context->methods;
658
659         if (((*domains) = malloc( sizeof(DOM_SID) * (*domain_count))) == NULL) {
660                 DEBUG(0,("sam_enum_domains: Out of memory allocating domain SID list\n"));
661                 return NT_STATUS_NO_MEMORY;
662         }
663
664         if (((*domain_names) = malloc( sizeof(char*) * (*domain_count))) == NULL) {
665                 DEBUG(0,("sam_enum_domains: Out of memory allocating domain name list\n"));
666                 SAFE_FREE((*domains));
667                 return NT_STATUS_NO_MEMORY;
668         }
669
670         while (tmp_methods) {
671                 DEBUGADD(7,("    [%d] %s: %s\n", i, tmp_methods->domain_name, sid_string_static(&tmp_methods->domain_sid)));
672                 sid_copy(domains[i],&tmp_methods->domain_sid);
673                 *domain_names[i] = smb_xstrdup(tmp_methods->domain_name);
674                 i++;
675                 tmp_methods= tmp_methods->next;
676         }
677
678         return NT_STATUS_OK;
679 }
680
681 NTSTATUS sam_lookup_domain(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, const char *domain, DOM_SID **domainsid)
682 {
683         SAM_METHODS     *tmp_methods;
684         NTSTATUS        nt_status;
685
686         SEC_DESC        *sd;
687         size_t          sd_size;
688         uint32          acc_granted;
689
690         DEBUG(5,("sam_lookup_domain: %d\n", __LINE__));
691
692         SAM_SETUP_CONTEXT;
693
694         /* invalid paramters */
695         SAM_ASSERT(access_token && domain && domainsid);
696
697         if (!NT_STATUS_IS_OK(nt_status = samr_make_sam_obj_sd(context->mem_ctx, &sd, &sd_size))) {
698                 DEBUG(4,("samr_make_sam_obj_sd failed\n"));
699                 return nt_status;
700         }
701
702         if (!se_access_check(sd, access_token, SA_RIGHT_SAM_OPEN_DOMAIN, &acc_granted, &nt_status)) {
703                 DEBUG(3,("sam_lookup_domain: ACCESS DENIED\n"));
704                         return nt_status;
705         }
706
707         tmp_methods= context->methods;
708
709         while (tmp_methods) {
710                 if (strcmp(domain, tmp_methods->domain_name) == 0) {
711                         (*domainsid) = (DOM_SID *)malloc(sizeof(DOM_SID));
712                         sid_copy((*domainsid), &tmp_methods->domain_sid);
713                         return NT_STATUS_OK;
714                 }
715                 tmp_methods= tmp_methods->next;
716         }
717
718         return NT_STATUS_NO_SUCH_DOMAIN;
719 }
720
721
722 NTSTATUS sam_get_domain_by_sid(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID *domainsid, SAM_DOMAIN_HANDLE **domain)
723 {
724         SAM_METHODS     *tmp_methods;
725         NTSTATUS        nt_status;
726
727         DEBUG(5,("sam_get_domain_by_sid: %d\n", __LINE__));
728
729         SAM_SETUP_CONTEXT;
730
731         SAM_ASSERT(access_token && domainsid && domain);
732
733         if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_sid(context, &tmp_methods, domainsid))) {
734                 DEBUG(4,("sam_get_methods_by_sid failed\n"));
735                 return nt_status;
736         }
737
738         if (!tmp_methods->sam_get_domain_handle) {
739                 DEBUG(3, ("sam_get_domain_by_sid: sam_methods of the domain did not specify sam_get_domain_handle\n"));
740                 return NT_STATUS_NOT_IMPLEMENTED;
741         }
742
743         if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_get_domain_handle(tmp_methods, access_token, access_desired, domain))) {
744                 DEBUG(4,("sam_get_domain_handle for %s in backend %s failed\n",
745                                  sid_string_static(domainsid), tmp_methods->backendname));
746                 return nt_status;
747         }
748
749         return NT_STATUS_OK;
750 }
751
752 NTSTATUS sam_create_account(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID *domainsid, const char *account_name, uint16 acct_ctrl, SAM_ACCOUNT_HANDLE **account)
753 {
754         SAM_METHODS     *tmp_methods;
755         NTSTATUS        nt_status;
756
757         DEBUG(5,("sam_create_account: %d\n", __LINE__));
758
759         SAM_SETUP_CONTEXT;
760
761         /* invalid parmaters */
762         SAM_ASSERT(access_token && domainsid && account_name && account);
763
764         if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_sid(context, &tmp_methods, domainsid))) {
765                 DEBUG(4,("sam_get_methods_by_sid failed\n"));
766                 return nt_status;
767         }
768
769         if (!tmp_methods->sam_create_account) {
770                 DEBUG(3, ("sam_create_account: sam_methods of the domain did not specify sam_create_account\n"));
771                 return NT_STATUS_NOT_IMPLEMENTED;
772         }
773
774         if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_create_account(tmp_methods, access_token, access_desired, account_name, acct_ctrl, account))) {
775                 DEBUG(4,("sam_create_account in backend %s failed\n",
776                                  tmp_methods->backendname));
777                 return nt_status;
778         }
779
780         return NT_STATUS_OK;
781 }
782
783 NTSTATUS sam_add_account(const SAM_CONTEXT *context, const SAM_ACCOUNT_HANDLE *account)
784 {
785         DOM_SID         domainsid;
786         const DOM_SID           *accountsid;
787         SAM_METHODS     *tmp_methods;
788         uint32          rid;
789         NTSTATUS        nt_status;
790         
791         DEBUG(5,("sam_add_account: %d\n", __LINE__));
792
793         SAM_SETUP_CONTEXT;
794
795         /* invalid parmaters */
796         SAM_ASSERT(account);
797
798         if (!NT_STATUS_IS_OK(nt_status = sam_get_account_sid(account, &accountsid))) {
799                 DEBUG(0,("Can't get account SID\n"));
800                 return nt_status;
801         }
802
803         sid_copy(&domainsid, accountsid);
804         if (!sid_split_rid(&domainsid, &rid)) {
805                 DEBUG(3,("sam_get_account_by_sid: failed to split the sid\n"));
806                 return NT_STATUS_INVALID_SID;
807         }
808
809         if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_sid(context, &tmp_methods, &domainsid))) {
810                 DEBUG(4,("sam_get_methods_by_sid failed\n"));
811                 return nt_status;
812         }
813
814         if (!tmp_methods->sam_add_account) {
815                 DEBUG(3, ("sam_add_account: sam_methods of the domain did not specify sam_add_account\n"));
816                 return NT_STATUS_NOT_IMPLEMENTED;
817         }
818
819         if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_add_account(tmp_methods, account))){
820                 DEBUG(4,("sam_add_account in backend %s failed\n",
821                                  tmp_methods->backendname));
822                 return nt_status;
823         }
824
825         return NT_STATUS_OK;
826 }
827
828 NTSTATUS sam_update_account(const SAM_CONTEXT *context, const SAM_ACCOUNT_HANDLE *account)
829 {
830         const SAM_METHODS *tmp_methods;
831         NTSTATUS     nt_status;
832         
833         DEBUG(5,("sam_update_account: %d\n", __LINE__));
834
835         SAM_SETUP_CONTEXT;
836
837         /* invalid account specified */
838         SAM_ASSERT(account && account->current_sam_methods);
839         
840         tmp_methods = account->current_sam_methods;
841                 
842         if (!tmp_methods->sam_update_account) {
843                 DEBUG(3, ("sam_update_account: sam_methods of the domain did not specify sam_update_account\n"));
844                 return NT_STATUS_NOT_IMPLEMENTED;
845         }
846
847         if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_update_account(tmp_methods, account))){
848                 DEBUG(4,("sam_update_account in backend %s failed\n",
849                                  tmp_methods->backendname));
850                 return nt_status;
851         }
852
853         return NT_STATUS_OK;
854 }
855
856 NTSTATUS sam_delete_account(const SAM_CONTEXT *context, const SAM_ACCOUNT_HANDLE *account)
857 {
858         const SAM_METHODS *tmp_methods;
859         NTSTATUS     nt_status;
860         
861         DEBUG(5,("sam_delete_account: %d\n", __LINE__));
862         
863         SAM_SETUP_CONTEXT;
864
865         /* invalid account specified */
866         SAM_ASSERT(account && account->current_sam_methods);
867         
868         tmp_methods = account->current_sam_methods;
869
870         if (!tmp_methods->sam_delete_account) {
871                 DEBUG(3, ("sam_delete_account: sam_methods of the domain did not specify sam_delete_account\n"));
872                 return NT_STATUS_NOT_IMPLEMENTED;
873         }
874
875         if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_delete_account(tmp_methods, account))){
876                 DEBUG(4,("sam_delete_account in backend %s failed\n",
877                                  tmp_methods->backendname));
878                 return nt_status;
879         }
880
881         return NT_STATUS_OK;
882 }
883
884 NTSTATUS sam_enum_accounts(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, const DOM_SID *domainsid, uint16 acct_ctrl, int32 *account_count, SAM_ACCOUNT_ENUM **accounts)
885 {
886         SAM_METHODS     *tmp_methods;
887         NTSTATUS        nt_status;
888
889         DEBUG(5,("sam_enum_accounts: %d\n", __LINE__));
890
891         SAM_SETUP_CONTEXT;
892
893         SAM_ASSERT(access_token && domainsid && account_count && accounts);
894
895         if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_sid(context, &tmp_methods, domainsid))) {
896                 DEBUG(4,("sam_get_methods_by_sid failed\n"));
897                 return nt_status;
898         }
899
900         if (!tmp_methods->sam_enum_accounts) {
901                 DEBUG(3, ("sam_enum_accounts: sam_methods of the domain did not specify sam_enum_accounts\n"));
902                 return NT_STATUS_NOT_IMPLEMENTED;
903         }
904
905         if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_enum_accounts(tmp_methods, access_token, acct_ctrl, account_count, accounts))) {
906                 DEBUG(4,("sam_enum_accounts for domain %s in backend %s failed\n",
907                                  tmp_methods->domain_name, tmp_methods->backendname));
908                 return nt_status;
909         }
910
911         return NT_STATUS_OK;
912 }
913
914
915 NTSTATUS sam_get_account_by_sid(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID *accountsid, SAM_ACCOUNT_HANDLE **account)
916 {
917         SAM_METHODS     *tmp_methods;
918         uint32          rid;
919         DOM_SID         domainsid;
920         NTSTATUS        nt_status;
921
922         DEBUG(5,("sam_get_account_by_sid: %d\n", __LINE__));
923
924         SAM_SETUP_CONTEXT;
925
926         SAM_ASSERT(access_token && accountsid && account);
927
928         sid_copy(&domainsid, accountsid);
929         if (!sid_split_rid(&domainsid, &rid)) {
930                 DEBUG(3,("sam_get_account_by_sid: failed to split the sid\n"));
931                 return NT_STATUS_INVALID_SID;
932         }
933
934
935         if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_sid(context, &tmp_methods, &domainsid))) {
936                 DEBUG(4,("sam_get_methods_by_sid failed\n"));
937                 return nt_status;
938         }
939
940         if (!tmp_methods->sam_get_account_by_sid) {
941                 DEBUG(3, ("sam_get_account_by_sid: sam_methods of the domain did not specify sam_get_account_by_sid\n"));
942                 return NT_STATUS_NOT_IMPLEMENTED;
943         }
944
945         if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_get_account_by_sid(tmp_methods, access_token, access_desired, accountsid, account))) {
946                 DEBUG(4,("sam_get_account_by_sid for %s in backend %s failed\n",
947                                  sid_string_static(accountsid), tmp_methods->backendname));
948                 return nt_status;
949         }
950
951         return NT_STATUS_OK;
952 }
953
954 NTSTATUS sam_get_account_by_name(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, uint32 access_desired, const char *domain, const char *name, SAM_ACCOUNT_HANDLE **account)
955 {
956         SAM_METHODS     *tmp_methods;
957         NTSTATUS        nt_status;
958
959         DEBUG(5,("sam_get_account_by_name: %d\n", __LINE__));
960
961         SAM_SETUP_CONTEXT;
962
963         SAM_ASSERT(access_token && domain && name && account);
964
965         if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_name(context, &tmp_methods, domain))) {
966                 DEBUG(4,("sam_get_methods_by_name failed\n"));
967                 return nt_status;
968         }
969
970         if (!tmp_methods->sam_get_account_by_name) {
971                 DEBUG(3, ("sam_get_account_by_name: sam_methods of the domain did not specify sam_get_account_by_name\n"));
972                 return NT_STATUS_NOT_IMPLEMENTED;
973         }
974
975         if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_get_account_by_name(tmp_methods, access_token, access_desired, name, account))) {
976                 DEBUG(4,("sam_get_account_by_name for %s\\%s in backend %s failed\n",
977                                  domain, name, tmp_methods->backendname));
978                 return nt_status;
979         }
980
981         return NT_STATUS_OK;
982 }
983
984 NTSTATUS sam_create_group(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID *domainsid, const char *group_name, uint16 group_ctrl, SAM_GROUP_HANDLE **group)
985 {
986         SAM_METHODS     *tmp_methods;
987         NTSTATUS        nt_status;
988
989         DEBUG(5,("sam_create_group: %d\n", __LINE__));
990
991         SAM_SETUP_CONTEXT;
992
993         SAM_ASSERT(access_token && domainsid && group_name && group);
994
995         if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_sid(context, &tmp_methods, domainsid))) {
996                 DEBUG(4,("sam_get_methods_by_sid failed\n"));
997                 return nt_status;
998         }
999
1000         if (!tmp_methods->sam_create_group) {
1001                 DEBUG(3, ("sam_create_group: sam_methods of the domain did not specify sam_create_group\n"));
1002                 return NT_STATUS_UNSUCCESSFUL; 
1003         }
1004
1005         if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_create_group(tmp_methods, access_token, access_desired, group_name, group_ctrl, group))) {
1006                 DEBUG(4,("sam_create_group in backend %s failed\n",
1007                                  tmp_methods->backendname));
1008                 return nt_status;
1009         }
1010
1011         return NT_STATUS_OK;
1012 }
1013
1014 NTSTATUS sam_add_group(const SAM_CONTEXT *context, const SAM_GROUP_HANDLE *group)
1015 {
1016         DOM_SID         domainsid;
1017         const DOM_SID           *groupsid;
1018         SAM_METHODS     *tmp_methods;
1019         uint32          rid;
1020         NTSTATUS        nt_status;
1021         
1022         DEBUG(5,("sam_add_group: %d\n", __LINE__));
1023
1024         SAM_SETUP_CONTEXT;
1025
1026         SAM_ASSERT(group);
1027
1028         if (!NT_STATUS_IS_OK(nt_status = sam_get_group_sid(group, &groupsid))) {
1029                 DEBUG(0,("Can't get group SID\n"));
1030                 return nt_status;
1031         }
1032
1033         sid_copy(&domainsid, groupsid);
1034         if (!sid_split_rid(&domainsid, &rid)) {
1035                 DEBUG(3,("sam_get_group_by_sid: failed to split the sid\n"));
1036                 return NT_STATUS_INVALID_SID;
1037         }
1038
1039         if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_sid(context, &tmp_methods, &domainsid))) {
1040                 DEBUG(4,("sam_get_methods_by_sid failed\n"));
1041                 return nt_status;
1042         }
1043
1044         if (!tmp_methods->sam_add_group) {
1045                 DEBUG(3, ("sam_add_group: sam_methods of the domain did not specify sam_add_group\n"));
1046                 return NT_STATUS_NOT_IMPLEMENTED;
1047         }
1048
1049         if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_add_group(tmp_methods, group))){
1050                 DEBUG(4,("sam_add_group in backend %s failed\n",
1051                                  tmp_methods->backendname));
1052                 return nt_status;
1053         }
1054
1055         return NT_STATUS_OK;
1056 }
1057
1058 NTSTATUS sam_update_group(const SAM_CONTEXT *context, const SAM_GROUP_HANDLE *group)
1059 {
1060         const SAM_METHODS *tmp_methods;
1061         NTSTATUS     nt_status;
1062         
1063         DEBUG(5,("sam_update_group: %d\n", __LINE__));
1064         
1065         SAM_SETUP_CONTEXT;
1066
1067         /* invalid group specified */
1068         SAM_ASSERT(group && group->current_sam_methods);
1069         
1070         tmp_methods = group->current_sam_methods;
1071         
1072         if (!tmp_methods->sam_update_group) {
1073                 DEBUG(3, ("sam_update_group: sam_methods of the domain did not specify sam_update_group\n"));
1074                 return NT_STATUS_NOT_IMPLEMENTED;
1075         }
1076
1077         if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_update_group(tmp_methods, group))){
1078                 DEBUG(4,("sam_update_group in backend %s failed\n",
1079                                  tmp_methods->backendname));
1080                 return nt_status;
1081         }
1082
1083         return NT_STATUS_OK;
1084 }
1085
1086 NTSTATUS sam_delete_group(const SAM_CONTEXT *context, const SAM_GROUP_HANDLE *group)
1087 {
1088         const SAM_METHODS *tmp_methods;
1089         NTSTATUS     nt_status;
1090         
1091         DEBUG(5,("sam_delete_group: %d\n", __LINE__));
1092         
1093         SAM_SETUP_CONTEXT;
1094
1095         /* invalid group specified */
1096         SAM_ASSERT(group && group->current_sam_methods);
1097         
1098         tmp_methods = group->current_sam_methods;
1099
1100         if (!tmp_methods->sam_delete_group) {
1101                 DEBUG(3, ("sam_delete_group: sam_methods of the domain did not specify sam_delete_group\n"));
1102                 return NT_STATUS_NOT_IMPLEMENTED;
1103         }
1104
1105         if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_delete_group(tmp_methods, group))){
1106                 DEBUG(4,("sam_delete_group in backend %s failed\n",
1107                                  tmp_methods->backendname));
1108                 return nt_status;
1109         }
1110
1111         return NT_STATUS_OK;
1112 }
1113
1114 NTSTATUS sam_enum_groups(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, const DOM_SID *domainsid, uint16 group_ctrl, uint32 *groups_count, SAM_GROUP_ENUM **groups)
1115 {
1116         SAM_METHODS     *tmp_methods;
1117         NTSTATUS        nt_status;
1118
1119         DEBUG(5,("sam_enum_groups: %d\n", __LINE__));
1120
1121         SAM_SETUP_CONTEXT;
1122
1123         SAM_ASSERT(access_token && domainsid && groups_count && groups);
1124
1125         if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_sid(context, &tmp_methods, domainsid))) {
1126                 DEBUG(4,("sam_get_methods_by_sid failed\n"));
1127                 return nt_status;
1128         }
1129
1130         if (!tmp_methods->sam_enum_accounts) {
1131                 DEBUG(3, ("sam_enum_groups: sam_methods of the domain did not specify sam_enum_groups\n"));
1132                 return NT_STATUS_NOT_IMPLEMENTED;
1133         }
1134
1135         if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_enum_groups(tmp_methods, access_token, group_ctrl, groups_count, groups))) {
1136                 DEBUG(4,("sam_enum_groups for domain %s in backend %s failed\n",
1137                                  tmp_methods->domain_name, tmp_methods->backendname));
1138                 return nt_status;
1139         }
1140
1141         return NT_STATUS_OK;
1142 }
1143
1144 NTSTATUS sam_get_group_by_sid(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, uint32 access_desired, const DOM_SID *groupsid, SAM_GROUP_HANDLE **group)
1145 {
1146         SAM_METHODS     *tmp_methods;
1147         uint32          rid;
1148         NTSTATUS        nt_status;
1149         DOM_SID         domainsid;
1150
1151         DEBUG(5,("sam_get_group_by_sid: %d\n", __LINE__));
1152
1153         SAM_SETUP_CONTEXT;
1154
1155         SAM_ASSERT(access_token && groupsid && group);
1156
1157         sid_copy(&domainsid, groupsid);
1158         if (!sid_split_rid(&domainsid, &rid)) {
1159                 DEBUG(3,("sam_get_group_by_sid: failed to split the sid\n"));
1160                 return NT_STATUS_INVALID_SID;
1161         }
1162
1163
1164         if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_sid(context, &tmp_methods, &domainsid))) {
1165                 DEBUG(4,("sam_get_methods_by_sid failed\n"));
1166                 return nt_status;
1167         }
1168
1169         if (!tmp_methods->sam_get_group_by_sid) {
1170                 DEBUG(3, ("sam_get_group_by_sid: sam_methods of the domain did not specify sam_get_group_by_sid\n"));
1171                 return NT_STATUS_NOT_IMPLEMENTED;
1172         }
1173
1174         if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_get_group_by_sid(tmp_methods, access_token, access_desired, groupsid, group))) {
1175                 DEBUG(4,("sam_get_group_by_sid for %s in backend %s failed\n",
1176                                  sid_string_static(groupsid), tmp_methods->backendname));
1177                 return nt_status;
1178         }
1179
1180         return NT_STATUS_OK;
1181 }
1182
1183 NTSTATUS sam_get_group_by_name(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, uint32 access_desired, const char *domain, const char *name, SAM_GROUP_HANDLE **group)
1184 {
1185         SAM_METHODS     *tmp_methods;
1186         NTSTATUS        nt_status;
1187
1188         DEBUG(5,("sam_get_group_by_name: %d\n", __LINE__));
1189
1190         SAM_SETUP_CONTEXT;
1191
1192         SAM_ASSERT(access_token && domain && name && group);
1193
1194         if (!NT_STATUS_IS_OK(nt_status = sam_get_methods_by_name(context, &tmp_methods, domain))) {
1195                 DEBUG(4,("sam_get_methods_by_name failed\n"));
1196                 return nt_status;
1197         }
1198
1199         if (!tmp_methods->sam_get_group_by_name) {
1200                 DEBUG(3, ("sam_get_group_by_name: sam_methods of the domain did not specify sam_get_group_by_name\n"));
1201                 return NT_STATUS_NOT_IMPLEMENTED;
1202         }
1203
1204         if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_get_group_by_name(tmp_methods, access_token, access_desired, name, group))) {
1205                 DEBUG(4,("sam_get_group_by_name for %s\\%s in backend %s failed\n",
1206                                  domain, name, tmp_methods->backendname));
1207                 return nt_status;
1208         }
1209
1210         return NT_STATUS_OK;
1211 }
1212
1213 NTSTATUS sam_add_member_to_group(const SAM_CONTEXT *context, const SAM_GROUP_HANDLE *group, const SAM_GROUP_MEMBER *member)
1214 {
1215         const SAM_METHODS *tmp_methods;
1216         NTSTATUS     nt_status;
1217         
1218         SAM_SETUP_CONTEXT;
1219         
1220         /* invalid group or member specified */
1221         SAM_ASSERT(group && group->current_sam_methods && member);
1222         
1223         tmp_methods = group->current_sam_methods;
1224                         
1225         if (!tmp_methods->sam_add_member_to_group) {
1226                 DEBUG(3, ("sam_add_member_to_group: sam_methods of the domain did not specify sam_add_member_to_group\n"));
1227                 return NT_STATUS_NOT_IMPLEMENTED;
1228         }
1229         
1230         if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_add_member_to_group(tmp_methods, group, member))) {
1231                 DEBUG(4,("sam_add_member_to_group in backend %s failed\n", tmp_methods->backendname));
1232                 return nt_status;
1233         }
1234         
1235         return NT_STATUS_OK;    
1236         
1237 }
1238
1239 NTSTATUS sam_delete_member_from_group(const SAM_CONTEXT *context, const SAM_GROUP_HANDLE *group, const SAM_GROUP_MEMBER *member)
1240 {
1241         const SAM_METHODS *tmp_methods;
1242         NTSTATUS     nt_status;
1243
1244         SAM_SETUP_CONTEXT;
1245         
1246         /* invalid group or member specified */
1247         SAM_ASSERT(group && group->current_sam_methods && member);
1248         
1249         tmp_methods = group->current_sam_methods;
1250         
1251         if (!tmp_methods->sam_delete_member_from_group) {
1252                 DEBUG(3, ("sam_delete_member_from_group: sam_methods of the domain did not specify sam_delete_member_from_group\n"));
1253                 return NT_STATUS_NOT_IMPLEMENTED;
1254         }
1255         
1256         if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_delete_member_from_group(tmp_methods, group, member))) {
1257                 DEBUG(4,("sam_delete_member_from_group in backend %s failed\n", tmp_methods->backendname));
1258                 return nt_status;
1259         }
1260         
1261         return NT_STATUS_OK;    
1262 }
1263
1264 NTSTATUS sam_enum_groupmembers(const SAM_CONTEXT *context, const SAM_GROUP_HANDLE *group, uint32 *members_count, SAM_GROUP_MEMBER **members)
1265 {
1266         const SAM_METHODS *tmp_methods;
1267         NTSTATUS     nt_status;
1268         
1269         SAM_SETUP_CONTEXT;
1270         
1271         /* invalid group specified */
1272         SAM_ASSERT(group && group->current_sam_methods && members_count && members);
1273         
1274         tmp_methods = group->current_sam_methods;
1275
1276         if (!tmp_methods->sam_enum_groupmembers) {
1277                 DEBUG(3, ("sam_enum_groupmembers: sam_methods of the domain did not specify sam_enum_group_members\n"));
1278                 return NT_STATUS_NOT_IMPLEMENTED;
1279         }
1280         
1281         if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_enum_groupmembers(tmp_methods, group, members_count, members))) {
1282                 DEBUG(4,("sam_enum_groupmembers in backend %s failed\n", tmp_methods->backendname));
1283                 return nt_status;
1284         }
1285         
1286         return NT_STATUS_OK;    
1287 }
1288
1289 NTSTATUS sam_get_groups_of_sid(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, const DOM_SID **sids, uint16 group_ctrl, uint32 *group_count, SAM_GROUP_ENUM **groups)
1290 {
1291         SAM_METHODS     *tmp_methods;
1292         NTSTATUS        nt_status;
1293         
1294         uint32          tmp_group_count;
1295         SAM_GROUP_ENUM *tmp_groups;
1296         
1297         DEBUG(5,("sam_get_groups_of_sid: %d\n", __LINE__));
1298
1299         SAM_SETUP_CONTEXT;
1300         
1301         /* invalid sam_context specified */
1302         SAM_ASSERT(access_token && sids && context && context->methods);
1303         
1304         *group_count = 0;
1305         
1306         *groups = NULL;
1307
1308         tmp_methods= context->methods;
1309
1310         while (tmp_methods) {
1311                 DEBUG(5,("getting groups from domain \n"));
1312                 if (!tmp_methods->sam_get_groups_of_sid) {
1313                         DEBUG(3, ("sam_get_groups_of_sid: sam_methods of domain did not specify sam_get_groups_of_sid\n"));
1314                         SAFE_FREE(*groups);
1315                         return NT_STATUS_NOT_IMPLEMENTED;
1316                 }
1317                 
1318                 if (!NT_STATUS_IS_OK(nt_status = tmp_methods->sam_get_groups_of_sid(tmp_methods, access_token, sids, group_ctrl, &tmp_group_count, &tmp_groups))) {
1319                         DEBUG(4,("sam_get_groups_of_sid in backend %s failed\n", tmp_methods->backendname));
1320                         SAFE_FREE(*groups);
1321                         return nt_status;
1322                 }
1323                 
1324                 *groups = Realloc(*groups, ((*group_count)  + tmp_group_count) * sizeof(SAM_GROUP_ENUM));
1325
1326                 memcpy(&(*groups)[*group_count], tmp_groups, tmp_group_count);          
1327                 
1328                 SAFE_FREE(tmp_groups);
1329                 
1330                 *group_count += tmp_group_count;
1331                 
1332                 tmp_methods = tmp_methods->next;
1333         }
1334         
1335         return NT_STATUS_OK;    
1336 }
1337
1338