2 Unix SMB/CIFS implementation.
4 endpoint server for the lsarpc pipe
6 Copyright (C) Andrew Tridgell 2004
7 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2007
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
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, see <http://www.gnu.org/licenses/>.
23 #include "rpc_server/lsa/lsa.h"
29 enum lsa_SidType rtype;
34 .rtype = SID_NAME_WKN_GRP,
37 .name = "CREATOR OWNER",
38 .sid = SID_CREATOR_OWNER,
39 .rtype = SID_NAME_WKN_GRP,
42 .name = "CREATOR GROUP",
43 .sid = SID_CREATOR_GROUP,
44 .rtype = SID_NAME_WKN_GRP,
47 .name = "Owner Rights",
48 .sid = SID_OWNER_RIGHTS,
49 .rtype = SID_NAME_WKN_GRP,
52 .domain = "NT AUTHORITY",
55 .rtype = SID_NAME_WKN_GRP,
58 .domain = "NT AUTHORITY",
60 .sid = SID_NT_NETWORK,
61 .rtype = SID_NAME_WKN_GRP,
64 .domain = "NT AUTHORITY",
67 .rtype = SID_NAME_WKN_GRP,
70 .domain = "NT AUTHORITY",
71 .name = "Interactive",
72 .sid = SID_NT_INTERACTIVE,
73 .rtype = SID_NAME_WKN_GRP,
76 .domain = "NT AUTHORITY",
78 .sid = SID_NT_SERVICE,
79 .rtype = SID_NAME_WKN_GRP,
82 .domain = "NT AUTHORITY",
83 .name = "ANONYMOUS LOGON",
84 .sid = SID_NT_ANONYMOUS,
85 .rtype = SID_NAME_WKN_GRP,
88 .domain = "NT AUTHORITY",
91 .rtype = SID_NAME_WKN_GRP,
94 .domain = "NT AUTHORITY",
95 .name = "ServerLogon",
96 .sid = SID_NT_ENTERPRISE_DCS,
97 .rtype = SID_NAME_WKN_GRP,
100 .domain = "NT AUTHORITY",
103 .rtype = SID_NAME_WKN_GRP,
106 .domain = "NT AUTHORITY",
107 .name = "Authenticated Users",
108 .sid = SID_NT_AUTHENTICATED_USERS,
109 .rtype = SID_NAME_WKN_GRP,
112 .domain = "NT AUTHORITY",
113 .name = "Restricted",
114 .sid = SID_NT_RESTRICTED,
115 .rtype = SID_NAME_WKN_GRP,
118 .domain = "NT AUTHORITY",
119 .name = "Terminal Server User",
120 .sid = SID_NT_TERMINAL_SERVER_USERS,
121 .rtype = SID_NAME_WKN_GRP,
124 .domain = "NT AUTHORITY",
125 .name = "Remote Interactive Logon",
126 .sid = SID_NT_REMOTE_INTERACTIVE,
127 .rtype = SID_NAME_WKN_GRP,
130 .domain = "NT AUTHORITY",
131 .name = "This Organization",
132 .sid = SID_NT_THIS_ORGANISATION,
133 .rtype = SID_NAME_WKN_GRP,
136 .domain = "NT AUTHORITY",
138 .sid = SID_NT_SYSTEM,
139 .rtype = SID_NAME_WKN_GRP,
142 .domain = "NT AUTHORITY",
143 .name = "Local Service",
144 .sid = SID_NT_LOCAL_SERVICE,
145 .rtype = SID_NAME_WKN_GRP,
148 .domain = "NT AUTHORITY",
149 .name = "Network Service",
150 .sid = SID_NT_NETWORK_SERVICE,
151 .rtype = SID_NAME_WKN_GRP,
154 .domain = "NT AUTHORITY",
155 .name = "Digest Authentication",
156 .sid = SID_NT_DIGEST_AUTHENTICATION,
157 .rtype = SID_NAME_WKN_GRP,
160 .domain = "NT AUTHORITY",
161 .name = "Enterprise Domain Controllers",
162 .sid = SID_NT_ENTERPRISE_DCS,
163 .rtype = SID_NAME_WKN_GRP,
166 .domain = "NT AUTHORITY",
167 .name = "NTLM Authentication",
168 .sid = SID_NT_NTLM_AUTHENTICATION,
169 .rtype = SID_NAME_WKN_GRP,
172 .domain = "NT AUTHORITY",
173 .name = "Other Organization",
174 .sid = SID_NT_OTHER_ORGANISATION,
175 .rtype = SID_NAME_WKN_GRP,
178 .domain = "NT AUTHORITY",
179 .name = "SChannel Authentication",
180 .sid = SID_NT_SCHANNEL_AUTHENTICATION,
181 .rtype = SID_NAME_WKN_GRP,
184 .domain = "NT AUTHORITY",
187 .rtype = SID_NAME_WKN_GRP,
194 static NTSTATUS lookup_well_known_names(TALLOC_CTX *mem_ctx, const char *domain,
195 const char *name, const char **authority_name,
196 struct dom_sid **sid, enum lsa_SidType *rtype)
199 for (i=0; well_known[i].sid; i++) {
201 if (strcasecmp_m(domain, well_known[i].domain) == 0
202 && strcasecmp_m(name, well_known[i].name) == 0) {
203 *authority_name = well_known[i].domain;
204 *sid = dom_sid_parse_talloc(mem_ctx, well_known[i].sid);
205 *rtype = well_known[i].rtype;
209 if (strcasecmp_m(name, well_known[i].name) == 0) {
210 *authority_name = well_known[i].domain;
211 *sid = dom_sid_parse_talloc(mem_ctx, well_known[i].sid);
212 *rtype = well_known[i].rtype;
217 return NT_STATUS_NOT_FOUND;
220 static NTSTATUS lookup_well_known_sids(TALLOC_CTX *mem_ctx,
221 const char *sid_str, const char **authority_name,
222 const char **name, enum lsa_SidType *rtype)
225 for (i=0; well_known[i].sid; i++) {
226 if (strcasecmp_m(sid_str, well_known[i].sid) == 0) {
227 *authority_name = well_known[i].domain;
228 *name = well_known[i].name;
229 *rtype = well_known[i].rtype;
233 return NT_STATUS_NOT_FOUND;
237 lookup a SID for 1 name
239 static NTSTATUS dcesrv_lsa_lookup_name(struct tevent_context *ev_ctx,
240 struct loadparm_context *lp_ctx,
241 struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
242 const char *name, const char **authority_name,
243 struct dom_sid **sid, enum lsa_SidType *rtype,
248 struct ldb_message **res;
249 const char * const attrs[] = { "objectSid", "sAMAccountType", NULL};
252 const char *username;
253 struct ldb_dn *domain_dn;
254 struct dom_sid *domain_sid;
257 p = strchr_m(name, '\\');
259 domain = talloc_strndup(mem_ctx, name, p-name);
261 return NT_STATUS_NO_MEMORY;
264 } else if (strchr_m(name, '@')) {
265 status = crack_name_to_nt4_name(mem_ctx, ev_ctx, lp_ctx, DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL, name, &domain, &username);
266 if (!NT_STATUS_IS_OK(status)) {
267 DEBUG(3, ("Failed to crack name %s into an NT4 name: %s\n", name, nt_errstr(status)));
276 /* Look up table of well known names */
277 status = lookup_well_known_names(mem_ctx, NULL, username, authority_name, sid, rtype);
278 if (NT_STATUS_IS_OK(status)) {
279 dom_sid_split_rid(NULL, *sid, NULL, rid);
283 if (username == NULL) {
284 *authority_name = NAME_BUILTIN;
285 *sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN);
286 *rtype = SID_NAME_DOMAIN;
291 if (strcasecmp_m(username, NAME_NT_AUTHORITY) == 0) {
292 *authority_name = NAME_NT_AUTHORITY;
293 *sid = dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY);
294 *rtype = SID_NAME_DOMAIN;
295 dom_sid_split_rid(NULL, *sid, NULL, rid);
298 if (strcasecmp_m(username, NAME_BUILTIN) == 0) {
299 *authority_name = NAME_BUILTIN;
300 *sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN);
301 *rtype = SID_NAME_DOMAIN;
305 if (strcasecmp_m(username, state->domain_dns) == 0) {
306 *authority_name = state->domain_name;
307 *sid = state->domain_sid;
308 *rtype = SID_NAME_DOMAIN;
312 if (strcasecmp_m(username, state->domain_name) == 0) {
313 *authority_name = state->domain_name;
314 *sid = state->domain_sid;
315 *rtype = SID_NAME_DOMAIN;
320 /* Perhaps this is a well known user? */
321 name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_NT_AUTHORITY, username);
323 return NT_STATUS_NO_MEMORY;
325 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
326 if (NT_STATUS_IS_OK(status)) {
330 /* Perhaps this is a BUILTIN user? */
331 name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_BUILTIN, username);
333 return NT_STATUS_NO_MEMORY;
335 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
336 if (NT_STATUS_IS_OK(status)) {
340 /* OK, I give up - perhaps we need to assume the user is in our domain? */
341 name = talloc_asprintf(mem_ctx, "%s\\%s", state->domain_name, username);
343 return NT_STATUS_NO_MEMORY;
345 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
346 if (NT_STATUS_IS_OK(status)) {
350 return STATUS_SOME_UNMAPPED;
351 } else if (strcasecmp_m(domain, NAME_NT_AUTHORITY) == 0) {
353 *authority_name = NAME_NT_AUTHORITY;
354 *sid = dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY);
355 *rtype = SID_NAME_DOMAIN;
356 dom_sid_split_rid(NULL, *sid, NULL, rid);
360 /* Look up table of well known names */
361 status = lookup_well_known_names(mem_ctx, domain, username, authority_name,
363 if (NT_STATUS_IS_OK(status)) {
364 dom_sid_split_rid(NULL, *sid, NULL, rid);
367 } else if (strcasecmp_m(domain, NAME_BUILTIN) == 0) {
368 *authority_name = NAME_BUILTIN;
369 domain_dn = state->builtin_dn;
370 } else if (strcasecmp_m(domain, state->domain_dns) == 0) {
371 *authority_name = state->domain_name;
372 domain_dn = state->domain_dn;
373 } else if (strcasecmp_m(domain, state->domain_name) == 0) {
374 *authority_name = state->domain_name;
375 domain_dn = state->domain_dn;
377 /* Not local, need to ask winbind in future */
378 return STATUS_SOME_UNMAPPED;
381 ret = gendb_search_dn(state->sam_ldb, mem_ctx, domain_dn, &res, attrs);
383 return NT_STATUS_INTERNAL_DB_CORRUPTION;
385 domain_sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
386 if (domain_sid == NULL) {
387 return NT_STATUS_INVALID_SID;
392 *rtype = SID_NAME_DOMAIN;
397 ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs,
398 "(&(sAMAccountName=%s)(objectSid=*))",
399 ldb_binary_encode_string(mem_ctx, username));
401 return NT_STATUS_INTERNAL_DB_CORRUPTION;
404 for (i=0; i < ret; i++) {
405 *sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
407 return NT_STATUS_INVALID_SID;
410 /* Check that this is in the domain */
411 if (!dom_sid_in_domain(domain_sid, *sid)) {
415 atype = samdb_result_uint(res[i], "sAMAccountType", 0);
417 *rtype = ds_atype_map(atype);
418 if (*rtype == SID_NAME_UNKNOWN) {
419 return STATUS_SOME_UNMAPPED;
422 dom_sid_split_rid(NULL, *sid, NULL, rid);
426 /* need to check for an allocated sid */
428 return NT_STATUS_INVALID_SID;
433 add to the lsa_RefDomainList for LookupSids and LookupNames
435 static NTSTATUS dcesrv_lsa_authority_list(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
436 enum lsa_SidType rtype,
437 const char *authority_name,
439 struct lsa_RefDomainList *domains,
442 struct dom_sid *authority_sid;
445 if (rtype != SID_NAME_DOMAIN) {
446 authority_sid = dom_sid_dup(mem_ctx, sid);
447 if (authority_sid == NULL) {
448 return NT_STATUS_NO_MEMORY;
450 authority_sid->num_auths--;
455 /* see if we've already done this authority name */
456 for (i=0;i<domains->count;i++) {
457 if (strcasecmp_m(authority_name, domains->domains[i].name.string) == 0) {
463 domains->domains = talloc_realloc(domains,
465 struct lsa_DomainInfo,
467 if (domains->domains == NULL) {
468 return NT_STATUS_NO_MEMORY;
470 domains->domains[i].name.string = authority_name;
471 domains->domains[i].sid = authority_sid;
473 domains->max_size = LSA_REF_DOMAIN_LIST_MULTIPLIER * domains->count;
480 lookup a name for 1 SID
482 static NTSTATUS dcesrv_lsa_lookup_sid(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
483 struct dom_sid *sid, const char *sid_str,
484 const char **authority_name,
485 const char **name, enum lsa_SidType *rtype)
490 struct ldb_message **res;
491 struct ldb_dn *domain_dn;
492 const char * const attrs[] = { "sAMAccountName", "sAMAccountType", "cn", NULL};
494 status = lookup_well_known_sids(mem_ctx, sid_str, authority_name, name, rtype);
495 if (NT_STATUS_IS_OK(status)) {
499 if (dom_sid_in_domain(state->domain_sid, sid)) {
500 *authority_name = state->domain_name;
501 domain_dn = state->domain_dn;
502 } else if (dom_sid_in_domain(state->builtin_sid, sid)) {
503 *authority_name = NAME_BUILTIN;
504 domain_dn = state->builtin_dn;
506 /* Not well known, our domain or built in */
508 /* In future, we must look at SID histories, and at trusted domains via winbind */
510 return NT_STATUS_NOT_FOUND;
513 /* need to re-add a check for an allocated sid */
515 ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs,
516 "objectSid=%s", ldap_encode_ndr_dom_sid(mem_ctx, sid));
517 if ((ret < 0) || (ret > 1)) {
518 return NT_STATUS_INTERNAL_DB_CORRUPTION;
521 return NT_STATUS_NOT_FOUND;
524 *name = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
526 *name = ldb_msg_find_attr_as_string(res[0], "cn", NULL);
528 *name = talloc_strdup(mem_ctx, sid_str);
529 NT_STATUS_HAVE_NO_MEMORY(*name);
533 atype = samdb_result_uint(res[0], "sAMAccountType", 0);
534 *rtype = ds_atype_map(atype);
543 NTSTATUS dcesrv_lsa_LookupSids2(struct dcesrv_call_state *dce_call,
545 struct lsa_LookupSids2 *r)
547 struct lsa_policy_state *state;
548 struct lsa_RefDomainList *domains = NULL;
550 NTSTATUS status = NT_STATUS_OK;
552 if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
553 r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
554 return NT_STATUS_INVALID_PARAMETER;
557 *r->out.domains = NULL;
559 /* NOTE: the WSPP test suite tries SIDs with invalid revision numbers,
560 and expects NT_STATUS_INVALID_PARAMETER back - we just treat it as
561 an unknown SID. We could add a SID validator here. (tridge)
565 status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
566 if (!NT_STATUS_IS_OK(status)) {
570 domains = talloc_zero(r->out.domains, struct lsa_RefDomainList);
571 if (domains == NULL) {
572 return NT_STATUS_NO_MEMORY;
574 *r->out.domains = domains;
576 r->out.names = talloc_zero(mem_ctx, struct lsa_TransNameArray2);
577 if (r->out.names == NULL) {
578 return NT_STATUS_NO_MEMORY;
583 r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName2,
584 r->in.sids->num_sids);
585 if (r->out.names->names == NULL) {
586 return NT_STATUS_NO_MEMORY;
589 for (i=0;i<r->in.sids->num_sids;i++) {
590 struct dom_sid *sid = r->in.sids->sids[i].sid;
591 char *sid_str = dom_sid_string(mem_ctx, sid);
592 const char *name, *authority_name;
593 enum lsa_SidType rtype;
597 r->out.names->count++;
599 r->out.names->names[i].sid_type = SID_NAME_UNKNOWN;
600 r->out.names->names[i].name.string = sid_str;
601 r->out.names->names[i].sid_index = 0xFFFFFFFF;
602 r->out.names->names[i].unknown = 0;
604 if (sid_str == NULL) {
605 r->out.names->names[i].name.string = "(SIDERROR)";
606 status = STATUS_SOME_UNMAPPED;
610 status2 = dcesrv_lsa_lookup_sid(state, mem_ctx, sid, sid_str,
611 &authority_name, &name, &rtype);
612 if (!NT_STATUS_IS_OK(status2)) {
613 status = STATUS_SOME_UNMAPPED;
617 /* set up the authority table */
618 status2 = dcesrv_lsa_authority_list(state, mem_ctx, rtype,
620 domains, &sid_index);
621 if (!NT_STATUS_IS_OK(status2)) {
625 r->out.names->names[i].sid_type = rtype;
626 r->out.names->names[i].name.string = name;
627 r->out.names->names[i].sid_index = sid_index;
628 r->out.names->names[i].unknown = 0;
633 if (*r->out.count == 0) {
634 return NT_STATUS_NONE_MAPPED;
636 if (*r->out.count != r->in.sids->num_sids) {
637 return STATUS_SOME_UNMAPPED;
647 Identical to LookupSids2, but doesn't take a policy handle
650 NTSTATUS dcesrv_lsa_LookupSids3(struct dcesrv_call_state *dce_call,
652 struct lsa_LookupSids3 *r)
654 struct lsa_LookupSids2 r2;
655 struct lsa_OpenPolicy2 pol;
657 struct dcesrv_handle *h;
661 /* No policy handle on the wire, so make one up here */
662 r2.in.handle = talloc(mem_ctx, struct policy_handle);
664 return NT_STATUS_NO_MEMORY;
667 pol.out.handle = r2.in.handle;
668 pol.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
670 pol.in.system_name = NULL;
671 status = dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &pol);
672 if (!NT_STATUS_IS_OK(status)) {
676 /* ensure this handle goes away at the end of this call */
677 DCESRV_PULL_HANDLE(h, r2.in.handle, LSA_HANDLE_POLICY);
678 talloc_steal(mem_ctx, h);
680 r2.in.sids = r->in.sids;
681 r2.in.names = r->in.names;
682 r2.in.level = r->in.level;
683 r2.in.count = r->in.count;
684 r2.in.lookup_options = r->in.lookup_options;
685 r2.in.client_revision = r->in.client_revision;
686 r2.out.count = r->out.count;
687 r2.out.names = r->out.names;
688 r2.out.domains = r->out.domains;
690 status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
692 r->out.domains = r2.out.domains;
693 r->out.names = r2.out.names;
694 r->out.count = r2.out.count;
703 NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
704 struct lsa_LookupSids *r)
706 struct lsa_LookupSids2 r2;
712 r2.in.handle = r->in.handle;
713 r2.in.sids = r->in.sids;
715 r2.in.level = r->in.level;
716 r2.in.count = r->in.count;
717 r2.in.lookup_options = 0;
718 r2.in.client_revision = 0;
719 r2.out.count = r->out.count;
721 r2.out.domains = r->out.domains;
723 status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
724 /* we deliberately don't check for error from the above,
725 as even on error we are supposed to return the names */
727 r->out.domains = r2.out.domains;
733 r->out.names = talloc(mem_ctx, struct lsa_TransNameArray);
734 if (r->out.names == NULL) {
735 return NT_STATUS_NO_MEMORY;
737 r->out.names->count = r2.out.names->count;
738 r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName,
739 r->out.names->count);
740 if (r->out.names->names == NULL) {
741 return NT_STATUS_NO_MEMORY;
743 for (i=0;i<r->out.names->count;i++) {
744 r->out.names->names[i].sid_type = r2.out.names->names[i].sid_type;
745 r->out.names->names[i].name.string = r2.out.names->names[i].name.string;
746 r->out.names->names[i].sid_index = r2.out.names->names[i].sid_index;
756 NTSTATUS dcesrv_lsa_LookupNames3(struct dcesrv_call_state *dce_call,
758 struct lsa_LookupNames3 *r)
760 struct lsa_policy_state *policy_state;
761 struct dcesrv_handle *policy_handle;
763 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
764 struct lsa_RefDomainList *domains;
766 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
768 if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
769 r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
770 return NT_STATUS_INVALID_PARAMETER;
773 policy_state = policy_handle->data;
775 *r->out.domains = NULL;
777 domains = talloc_zero(mem_ctx, struct lsa_RefDomainList);
778 if (domains == NULL) {
779 return NT_STATUS_NO_MEMORY;
781 *r->out.domains = domains;
783 r->out.sids = talloc_zero(mem_ctx, struct lsa_TransSidArray3);
784 if (r->out.sids == NULL) {
785 return NT_STATUS_NO_MEMORY;
790 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid3,
792 if (r->out.sids->sids == NULL) {
793 return NT_STATUS_NO_MEMORY;
796 for (i=0;i<r->in.num_names;i++) {
797 const char *name = r->in.names[i].string;
798 const char *authority_name;
800 uint32_t sid_index, rid;
801 enum lsa_SidType rtype;
804 r->out.sids->count++;
806 r->out.sids->sids[i].sid_type = SID_NAME_UNKNOWN;
807 r->out.sids->sids[i].sid = NULL;
808 r->out.sids->sids[i].sid_index = 0xFFFFFFFF;
809 r->out.sids->sids[i].flags = 0;
811 status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, policy_state, mem_ctx, name,
812 &authority_name, &sid, &rtype, &rid);
813 if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) {
817 status2 = dcesrv_lsa_authority_list(policy_state, mem_ctx, rtype, authority_name,
818 sid, domains, &sid_index);
819 if (!NT_STATUS_IS_OK(status2)) {
823 r->out.sids->sids[i].sid_type = rtype;
824 r->out.sids->sids[i].sid = sid;
825 r->out.sids->sids[i].sid_index = sid_index;
826 r->out.sids->sids[i].flags = 0;
831 if (*r->out.count == 0) {
832 return NT_STATUS_NONE_MAPPED;
834 if (*r->out.count != r->in.num_names) {
835 return STATUS_SOME_UNMAPPED;
844 Identical to LookupNames3, but doesn't take a policy handle
847 NTSTATUS dcesrv_lsa_LookupNames4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
848 struct lsa_LookupNames4 *r)
850 struct lsa_LookupNames3 r2;
851 struct lsa_OpenPolicy2 pol;
853 struct dcesrv_handle *h;
857 /* No policy handle on the wire, so make one up here */
858 r2.in.handle = talloc(mem_ctx, struct policy_handle);
860 return NT_STATUS_NO_MEMORY;
863 pol.out.handle = r2.in.handle;
864 pol.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
866 pol.in.system_name = NULL;
867 status = dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &pol);
868 if (!NT_STATUS_IS_OK(status)) {
872 /* ensure this handle goes away at the end of this call */
873 DCESRV_PULL_HANDLE(h, r2.in.handle, LSA_HANDLE_POLICY);
874 talloc_steal(mem_ctx, h);
876 r2.in.num_names = r->in.num_names;
877 r2.in.names = r->in.names;
878 r2.in.level = r->in.level;
879 r2.in.sids = r->in.sids;
880 r2.in.count = r->in.count;
881 r2.in.lookup_options = r->in.lookup_options;
882 r2.in.client_revision = r->in.client_revision;
883 r2.out.domains = r->out.domains;
884 r2.out.sids = r->out.sids;
885 r2.out.count = r->out.count;
887 status = dcesrv_lsa_LookupNames3(dce_call, mem_ctx, &r2);
889 r->out.domains = r2.out.domains;
890 r->out.sids = r2.out.sids;
891 r->out.count = r2.out.count;
898 NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call,
900 struct lsa_LookupNames2 *r)
902 struct lsa_policy_state *state;
903 struct dcesrv_handle *h;
905 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
906 struct lsa_RefDomainList *domains;
908 *r->out.domains = NULL;
910 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
912 if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
913 r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
914 return NT_STATUS_INVALID_PARAMETER;
919 domains = talloc_zero(mem_ctx, struct lsa_RefDomainList);
920 if (domains == NULL) {
921 return NT_STATUS_NO_MEMORY;
923 *r->out.domains = domains;
925 r->out.sids = talloc_zero(mem_ctx, struct lsa_TransSidArray2);
926 if (r->out.sids == NULL) {
927 return NT_STATUS_NO_MEMORY;
932 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid2,
934 if (r->out.sids->sids == NULL) {
935 return NT_STATUS_NO_MEMORY;
938 for (i=0;i<r->in.num_names;i++) {
939 const char *name = r->in.names[i].string;
940 const char *authority_name;
942 uint32_t sid_index, rid=0;
943 enum lsa_SidType rtype;
946 r->out.sids->count++;
948 r->out.sids->sids[i].sid_type = SID_NAME_UNKNOWN;
949 /* MS-LSAT 3.1.4.7 - rid zero is considered equivalent
950 to sid NULL - so we should return 0 rid for
952 r->out.sids->sids[i].rid = 0;
953 r->out.sids->sids[i].sid_index = 0xFFFFFFFF;
954 r->out.sids->sids[i].unknown = 0;
956 status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, state, mem_ctx, name,
957 &authority_name, &sid, &rtype, &rid);
958 if (!NT_STATUS_IS_OK(status2)) {
962 status2 = dcesrv_lsa_authority_list(state, mem_ctx, rtype, authority_name,
963 sid, domains, &sid_index);
964 if (!NT_STATUS_IS_OK(status2)) {
968 r->out.sids->sids[i].sid_type = rtype;
969 r->out.sids->sids[i].rid = rid;
970 r->out.sids->sids[i].sid_index = sid_index;
971 r->out.sids->sids[i].unknown = 0;
976 if (*r->out.count == 0) {
977 return NT_STATUS_NONE_MAPPED;
979 if (*r->out.count != r->in.num_names) {
980 return STATUS_SOME_UNMAPPED;
989 NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
990 struct lsa_LookupNames *r)
992 struct lsa_LookupNames2 r2;
998 r2.in.handle = r->in.handle;
999 r2.in.num_names = r->in.num_names;
1000 r2.in.names = r->in.names;
1002 r2.in.level = r->in.level;
1003 r2.in.count = r->in.count;
1004 r2.in.lookup_options = 0;
1005 r2.in.client_revision = 0;
1006 r2.out.count = r->out.count;
1007 r2.out.domains = r->out.domains;
1009 status = dcesrv_lsa_LookupNames2(dce_call, mem_ctx, &r2);
1010 if (r2.out.sids == NULL) {
1014 r->out.sids = talloc(mem_ctx, struct lsa_TransSidArray);
1015 if (r->out.sids == NULL) {
1016 return NT_STATUS_NO_MEMORY;
1018 r->out.sids->count = r2.out.sids->count;
1019 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid,
1020 r->out.sids->count);
1021 if (r->out.sids->sids == NULL) {
1022 return NT_STATUS_NO_MEMORY;
1024 for (i=0;i<r->out.sids->count;i++) {
1025 r->out.sids->sids[i].sid_type = r2.out.sids->sids[i].sid_type;
1026 r->out.sids->sids[i].rid = r2.out.sids->sids[i].rid;
1027 r->out.sids->sids[i].sid_index = r2.out.sids->sids[i].sid_index;