The code is a bit of a mess right now.
[Samba/gbeck.git] / source3 / sam / interface.c
blob51ae561999c40de946c4d239c3276827c4285a5b
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
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.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "includes.h"
26 #undef DBGC_CLASS
27 #define DBGC_CLASS DBGC_SAM
29 extern DOM_SID global_sid_Builtin;
31 /** List of various built-in sam modules */
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}
43 static NTSTATUS sam_get_methods_by_sid(const SAM_CONTEXT *context, SAM_METHODS **sam_method, const DOM_SID *domainsid)
45 SAM_METHODS *tmp_methods;
47 DEBUG(5,("sam_get_methods_by_sid: %d\n", __LINE__));
49 /* invalid sam_context specified */
50 SAM_ASSERT(context && context->methods);
52 tmp_methods = context->methods;
54 while (tmp_methods) {
55 if (sid_equal(domainsid, &(tmp_methods->domain_sid)))
57 (*sam_method) = tmp_methods;
58 return NT_STATUS_OK;
60 tmp_methods = tmp_methods->next;
63 DEBUG(3,("sam_get_methods_by_sid: There is no backend specified for domain %s\n", sid_string_static(domainsid)));
65 return NT_STATUS_NO_SUCH_DOMAIN;
68 static NTSTATUS sam_get_methods_by_name(const SAM_CONTEXT *context, SAM_METHODS **sam_method, const char *domainname)
70 SAM_METHODS *tmp_methods;
72 DEBUG(5,("sam_get_methods_by_name: %d\n", __LINE__));
74 /* invalid sam_context specified */
75 SAM_ASSERT(context && context->methods);
77 tmp_methods = context->methods;
79 while (tmp_methods) {
80 if (strequal(domainname, tmp_methods->domain_name))
82 (*sam_method) = tmp_methods;
83 return NT_STATUS_OK;
85 tmp_methods = tmp_methods->next;
88 DEBUG(3,("sam_get_methods_by_sid: There is no backend specified for domain %s\n", domainname));
90 return NT_STATUS_NO_SUCH_DOMAIN;
93 static NTSTATUS make_sam_methods(TALLOC_CTX *mem_ctx, SAM_METHODS **methods)
95 *methods = talloc(mem_ctx, sizeof(SAM_METHODS));
97 if (!*methods) {
98 return NT_STATUS_NO_MEMORY;
101 ZERO_STRUCTP(*methods);
103 return NT_STATUS_OK;
106 /******************************************************************
107 Free and cleanup a sam context, any associated data and anything
108 that the attached modules might have associated.
109 *******************************************************************/
111 void free_sam_context(SAM_CONTEXT **context)
113 SAM_METHODS *sam_selected = (*context)->methods;
115 while (sam_selected) {
116 if (sam_selected->free_private_data) {
117 sam_selected->free_private_data(&(sam_selected->private_data));
119 sam_selected = sam_selected->next;
122 talloc_destroy((*context)->mem_ctx);
123 *context = NULL;
126 /******************************************************************
127 Make a backend_entry from scratch
128 *******************************************************************/
130 static NTSTATUS make_backend_entry(SAM_BACKEND_ENTRY *backend_entry, char *sam_backend_string)
132 char *tmp = NULL;
133 char *tmp_string = sam_backend_string;
135 DEBUG(5,("make_backend_entry: %d\n", __LINE__));
137 SAM_ASSERT(sam_backend_string && backend_entry);
139 backend_entry->module_name = sam_backend_string;
141 DEBUG(5,("makeing backend_entry for %s\n", backend_entry->module_name));
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;
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;
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());
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;
168 DEBUG(10,("looking up sid for domain %s\n", backend_entry->domain_name));
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);
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)));
180 return NT_STATUS_OK;
183 /******************************************************************
184 create sam_methods struct based on sam_backend_entry
185 *****************************************************************/
187 static NTSTATUS make_sam_methods_backend_entry(SAM_CONTEXT *context, SAM_METHODS **methods_ptr, SAM_BACKEND_ENTRY *backend_entry)
189 NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL;
190 SAM_METHODS *methods;
191 int i;
193 DEBUG(5,("make_sam_methods_backend_entry: %d\n", __LINE__));
195 if (!NT_STATUS_IS_OK(nt_status = make_sam_methods(context->mem_ctx, methods_ptr))) {
196 return nt_status;
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;
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++)
208 if (strequal(builtin_sam_init_functions[i].module_name, backend_entry->module_name))
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)));
219 return nt_status;
223 DEBUG(2,("could not find backend %s\n", backend_entry->module_name));
225 return NT_STATUS_INVALID_PARAMETER;
228 static NTSTATUS sam_context_check_default_backends(SAM_CONTEXT *context)
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;
235 DEBUG(5,("sam_context_check_default_backends: %d\n", __LINE__));
237 /* Make sure domain lp_workgroup() is available */
239 ntstatus = sam_get_methods_by_sid(context, &methods, &global_sid_Builtin);
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));
245 SAM_ASSERT(global_sam_sid);
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);
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;
258 DLIST_ADD_END(context->methods, methods, tmpmethods);
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;
265 /* Make sure the BUILTIN domain is available */
267 ntstatus = sam_get_methods_by_sid(context, &methods, global_sam_sid);
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);
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;
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;
289 return NT_STATUS_OK;
292 static NTSTATUS check_duplicate_backend_entries(SAM_BACKEND_ENTRY **backend_entries, int *nBackends)
294 int i, j;
296 DEBUG(5,("check_duplicate_backend_entries: %d\n", __LINE__));
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;
308 return NT_STATUS_OK;
311 NTSTATUS make_sam_context_list(SAM_CONTEXT **context, char **sam_backends_param)
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;
319 DEBUG(5,("make_sam_context_from_conf: %d\n", __LINE__));
321 if (!sam_backends_param) {
322 DEBUG(1, ("no SAM backeds specified!\n"));
323 return NT_STATUS_INVALID_PARAMETER;
326 if (!NT_STATUS_IS_OK(nt_status = make_sam_context(context))) {
327 DEBUG(4,("make_sam_context failed\n"));
328 return nt_status;
331 while (sam_backends_param[nBackends])
332 nBackends++;
334 DEBUG(6,("There are %d domains listed with their backends\n", nBackends));
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;
341 memset(backends, '\0', sizeof(*backends)*nBackends);
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;
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;
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;
370 DLIST_ADD_END((*context)->methods, curmethods, tmpmethods);
373 for (i = 0; i < nBackends; i++) SAFE_FREE(backends[i].domain_sid);
375 SAFE_FREE(backends);
376 return NT_STATUS_OK;
379 /******************************************************************
380 Make a sam_context from scratch.
381 *******************************************************************/
383 NTSTATUS make_sam_context(SAM_CONTEXT **context)
385 TALLOC_CTX *mem_ctx;
387 mem_ctx = talloc_init("sam_context internal allocation context");
389 if (!mem_ctx) {
390 DEBUG(0, ("make_sam_context: talloc init failed!\n"));
391 return NT_STATUS_NO_MEMORY;
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;
400 ZERO_STRUCTP(*context);
402 (*context)->mem_ctx = mem_ctx;
404 (*context)->free_fn = free_sam_context;
406 return NT_STATUS_OK;
409 /******************************************************************
410 Return an already initialised sam_context, to facilitate backward
411 compatibility (see functions below).
412 *******************************************************************/
414 static struct sam_context *sam_get_static_context(BOOL reload)
416 static SAM_CONTEXT *sam_context = NULL;
418 if ((sam_context) && (reload)) {
419 sam_context->free_fn(&sam_context);
420 sam_context = NULL;
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;
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;
436 return sam_context;
439 /***************************************************************
440 Initialize the static context (at smbd startup etc).
442 If uninitialised, context will auto-init on first use.
443 ***************************************************************/
445 BOOL initialize_sam(BOOL reload)
447 return (sam_get_static_context(reload) != NULL);
451 /**************************************************************
452 External API. This is what the rest of the world calls...
453 ***************************************************************/
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
461 When the context parmater is NULL, the default is used.
462 *******************************************************************/
464 #define SAM_SETUP_CONTEXT if (!context) \
465 context = sam_get_static_context(False);\
466 if (!context) {\
467 return NT_STATUS_UNSUCCESSFUL; \
472 NTSTATUS sam_get_sec_desc(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, const DOM_SID *sid, SEC_DESC **sd)
474 SAM_METHODS *tmp_methods;
475 NTSTATUS nt_status;
477 DEBUG(5,("sam_get_sec_desc: %d\n", __LINE__));
479 SAM_SETUP_CONTEXT;
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;
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;
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;
496 return NT_STATUS_OK;
499 NTSTATUS sam_set_sec_desc(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, const DOM_SID *sid, const SEC_DESC *sd)
501 SAM_METHODS *tmp_methods;
502 NTSTATUS nt_status;
504 DEBUG(5,("sam_set_sec_desc: %d\n", __LINE__));
506 SAM_SETUP_CONTEXT;
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;
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;
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;
523 return NT_STATUS_OK;
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)
529 SAM_METHODS *tmp_methods;
530 NTSTATUS nt_status;
532 DEBUG(5,("sam_lookup_name: %d\n", __LINE__));
534 SAM_SETUP_CONTEXT;
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;
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;
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;
552 return NT_STATUS_OK;
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)
557 SAM_METHODS *tmp_methods;
558 uint32 rid;
559 NTSTATUS nt_status;
560 DOM_SID domainsid;
562 DEBUG(5,("sam_lookup_sid: %d\n", __LINE__));
564 SAM_SETUP_CONTEXT;
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;
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;
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;
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;
588 return NT_STATUS_OK;
592 NTSTATUS sam_update_domain(const SAM_CONTEXT *context, const SAM_DOMAIN_HANDLE *domain)
594 const SAM_METHODS *tmp_methods;
595 NTSTATUS nt_status;
597 DEBUG(5,("sam_update_domain: %d\n", __LINE__));
599 SAM_SETUP_CONTEXT;
601 /* invalid domain specified */
602 SAM_ASSERT(domain && domain->current_sam_methods);
604 tmp_methods = domain->current_sam_methods;
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;
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;
617 return NT_STATUS_OK;
620 NTSTATUS sam_enum_domains(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, int32 *domain_count, DOM_SID **domains, char ***domain_names)
622 SAM_METHODS *tmp_methods;
623 NTSTATUS nt_status;
625 SEC_DESC *sd;
626 size_t sd_size;
627 uint32 acc_granted;
628 int i = 0;
630 DEBUG(5,("sam_enum_domains: %d\n", __LINE__));
632 SAM_SETUP_CONTEXT;
634 /* invalid parmaters specified */
635 SAM_ASSERT(domain_count && domains && domain_names);
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;
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;
647 tmp_methods= context->methods;
648 *domain_count = 0;
650 while (tmp_methods) {
651 (*domain_count)++;
652 tmp_methods= tmp_methods->next;
655 DEBUG(6,("sam_enum_domains: enumerating %d domains\n", (*domain_count)));
657 tmp_methods = context->methods;
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;
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;
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;
678 return NT_STATUS_OK;
681 NTSTATUS sam_lookup_domain(const SAM_CONTEXT *context, const NT_USER_TOKEN *access_token, const char *domain, DOM_SID **domainsid)
683 SAM_METHODS *tmp_methods;
684 NTSTATUS nt_status;
686 SEC_DESC *sd;
687 size_t sd_size;
688 uint32 acc_granted;
690 DEBUG(5,("sam_lookup_domain: %d\n", __LINE__));
692 SAM_SETUP_CONTEXT;
694 /* invalid paramters */
695 SAM_ASSERT(access_token && domain && domainsid);
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;
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;
707 tmp_methods= context->methods;
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;
715 tmp_methods= tmp_methods->next;
718 return NT_STATUS_NO_SUCH_DOMAIN;
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)
724 SAM_METHODS *tmp_methods;
725 NTSTATUS nt_status;
727 DEBUG(5,("sam_get_domain_by_sid: %d\n", __LINE__));
729 SAM_SETUP_CONTEXT;
731 SAM_ASSERT(access_token && domainsid && domain);
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;
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;
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;
749 return NT_STATUS_OK;
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)
754 SAM_METHODS *tmp_methods;
755 NTSTATUS nt_status;
757 DEBUG(5,("sam_create_account: %d\n", __LINE__));
759 SAM_SETUP_CONTEXT;
761 /* invalid parmaters */
762 SAM_ASSERT(access_token && domainsid && account_name && account);
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;
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;
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;
780 return NT_STATUS_OK;
783 NTSTATUS sam_add_account(const SAM_CONTEXT *context, const SAM_ACCOUNT_HANDLE *account)
785 DOM_SID domainsid;
786 const DOM_SID *accountsid;
787 SAM_METHODS *tmp_methods;
788 uint32 rid;
789 NTSTATUS nt_status;
791 DEBUG(5,("sam_add_account: %d\n", __LINE__));
793 SAM_SETUP_CONTEXT;
795 /* invalid parmaters */
796 SAM_ASSERT(account);
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;
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;
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;
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;
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;
825 return NT_STATUS_OK;
828 NTSTATUS sam_update_account(const SAM_CONTEXT *context, const SAM_ACCOUNT_HANDLE *account)
830 const SAM_METHODS *tmp_methods;
831 NTSTATUS nt_status;
833 DEBUG(5,("sam_update_account: %d\n", __LINE__));
835 SAM_SETUP_CONTEXT;
837 /* invalid account specified */
838 SAM_ASSERT(account && account->current_sam_methods);
840 tmp_methods = account->current_sam_methods;
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;
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;
853 return NT_STATUS_OK;
856 NTSTATUS sam_delete_account(const SAM_CONTEXT *context, const SAM_ACCOUNT_HANDLE *account)
858 const SAM_METHODS *tmp_methods;
859 NTSTATUS nt_status;
861 DEBUG(5,("sam_delete_account: %d\n", __LINE__));
863 SAM_SETUP_CONTEXT;
865 /* invalid account specified */
866 SAM_ASSERT(account && account->current_sam_methods);
868 tmp_methods = account->current_sam_methods;
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;
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;
881 return NT_STATUS_OK;
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)
886 SAM_METHODS *tmp_methods;
887 NTSTATUS nt_status;
889 DEBUG(5,("sam_enum_accounts: %d\n", __LINE__));
891 SAM_SETUP_CONTEXT;
893 SAM_ASSERT(access_token && domainsid && account_count && accounts);
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;
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;
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;
911 return NT_STATUS_OK;
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)
917 SAM_METHODS *tmp_methods;
918 uint32 rid;
919 DOM_SID domainsid;
920 NTSTATUS nt_status;
922 DEBUG(5,("sam_get_account_by_sid: %d\n", __LINE__));
924 SAM_SETUP_CONTEXT;
926 SAM_ASSERT(access_token && accountsid && account);
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;
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;
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;
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;
951 return NT_STATUS_OK;
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)
956 SAM_METHODS *tmp_methods;
957 NTSTATUS nt_status;
959 DEBUG(5,("sam_get_account_by_name: %d\n", __LINE__));
961 SAM_SETUP_CONTEXT;
963 SAM_ASSERT(access_token && domain && name && account);
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;
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;
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;
981 return NT_STATUS_OK;
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)
986 SAM_METHODS *tmp_methods;
987 NTSTATUS nt_status;
989 DEBUG(5,("sam_create_group: %d\n", __LINE__));
991 SAM_SETUP_CONTEXT;
993 SAM_ASSERT(access_token && domainsid && group_name && group);
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;
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;
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;
1011 return NT_STATUS_OK;
1014 NTSTATUS sam_add_group(const SAM_CONTEXT *context, const SAM_GROUP_HANDLE *group)
1016 DOM_SID domainsid;
1017 const DOM_SID *groupsid;
1018 SAM_METHODS *tmp_methods;
1019 uint32 rid;
1020 NTSTATUS nt_status;
1022 DEBUG(5,("sam_add_group: %d\n", __LINE__));
1024 SAM_SETUP_CONTEXT;
1026 SAM_ASSERT(group);
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;
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;
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;
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;
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;
1055 return NT_STATUS_OK;
1058 NTSTATUS sam_update_group(const SAM_CONTEXT *context, const SAM_GROUP_HANDLE *group)
1060 const SAM_METHODS *tmp_methods;
1061 NTSTATUS nt_status;
1063 DEBUG(5,("sam_update_group: %d\n", __LINE__));
1065 SAM_SETUP_CONTEXT;
1067 /* invalid group specified */
1068 SAM_ASSERT(group && group->current_sam_methods);
1070 tmp_methods = group->current_sam_methods;
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;
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;
1083 return NT_STATUS_OK;
1086 NTSTATUS sam_delete_group(const SAM_CONTEXT *context, const SAM_GROUP_HANDLE *group)
1088 const SAM_METHODS *tmp_methods;
1089 NTSTATUS nt_status;
1091 DEBUG(5,("sam_delete_group: %d\n", __LINE__));
1093 SAM_SETUP_CONTEXT;
1095 /* invalid group specified */
1096 SAM_ASSERT(group && group->current_sam_methods);
1098 tmp_methods = group->current_sam_methods;
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;
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;
1111 return NT_STATUS_OK;
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)
1116 SAM_METHODS *tmp_methods;
1117 NTSTATUS nt_status;
1119 DEBUG(5,("sam_enum_groups: %d\n", __LINE__));
1121 SAM_SETUP_CONTEXT;
1123 SAM_ASSERT(access_token && domainsid && groups_count && groups);
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;
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;
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;
1141 return NT_STATUS_OK;
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)
1146 SAM_METHODS *tmp_methods;
1147 uint32 rid;
1148 NTSTATUS nt_status;
1149 DOM_SID domainsid;
1151 DEBUG(5,("sam_get_group_by_sid: %d\n", __LINE__));
1153 SAM_SETUP_CONTEXT;
1155 SAM_ASSERT(access_token && groupsid && group);
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;
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;
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;
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;
1180 return NT_STATUS_OK;
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)
1185 SAM_METHODS *tmp_methods;
1186 NTSTATUS nt_status;
1188 DEBUG(5,("sam_get_group_by_name: %d\n", __LINE__));
1190 SAM_SETUP_CONTEXT;
1192 SAM_ASSERT(access_token && domain && name && group);
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;
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;
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;
1210 return NT_STATUS_OK;
1213 NTSTATUS sam_add_member_to_group(const SAM_CONTEXT *context, const SAM_GROUP_HANDLE *group, const SAM_GROUP_MEMBER *member)
1215 const SAM_METHODS *tmp_methods;
1216 NTSTATUS nt_status;
1218 SAM_SETUP_CONTEXT;
1220 /* invalid group or member specified */
1221 SAM_ASSERT(group && group->current_sam_methods && member);
1223 tmp_methods = group->current_sam_methods;
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;
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;
1235 return NT_STATUS_OK;
1239 NTSTATUS sam_delete_member_from_group(const SAM_CONTEXT *context, const SAM_GROUP_HANDLE *group, const SAM_GROUP_MEMBER *member)
1241 const SAM_METHODS *tmp_methods;
1242 NTSTATUS nt_status;
1244 SAM_SETUP_CONTEXT;
1246 /* invalid group or member specified */
1247 SAM_ASSERT(group && group->current_sam_methods && member);
1249 tmp_methods = group->current_sam_methods;
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;
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;
1261 return NT_STATUS_OK;
1264 NTSTATUS sam_enum_groupmembers(const SAM_CONTEXT *context, const SAM_GROUP_HANDLE *group, uint32 *members_count, SAM_GROUP_MEMBER **members)
1266 const SAM_METHODS *tmp_methods;
1267 NTSTATUS nt_status;
1269 SAM_SETUP_CONTEXT;
1271 /* invalid group specified */
1272 SAM_ASSERT(group && group->current_sam_methods && members_count && members);
1274 tmp_methods = group->current_sam_methods;
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;
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;
1286 return NT_STATUS_OK;
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)
1291 SAM_METHODS *tmp_methods;
1292 NTSTATUS nt_status;
1294 uint32 tmp_group_count;
1295 SAM_GROUP_ENUM *tmp_groups;
1297 DEBUG(5,("sam_get_groups_of_sid: %d\n", __LINE__));
1299 SAM_SETUP_CONTEXT;
1301 /* invalid sam_context specified */
1302 SAM_ASSERT(access_token && sids && context && context->methods);
1304 *group_count = 0;
1306 *groups = NULL;
1308 tmp_methods= context->methods;
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;
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;
1324 *groups = Realloc(*groups, ((*group_count) + tmp_group_count) * sizeof(SAM_GROUP_ENUM));
1326 memcpy(&(*groups)[*group_count], tmp_groups, tmp_group_count);
1328 SAFE_FREE(tmp_groups);
1330 *group_count += tmp_group_count;
1332 tmp_methods = tmp_methods->next;
1335 return NT_STATUS_OK;