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"
24 #include "libds/common/flag_mapping.h"
30 enum lsa_SidType rtype;
35 .rtype = SID_NAME_WKN_GRP,
38 .name = "CREATOR OWNER",
39 .sid = SID_CREATOR_OWNER,
40 .rtype = SID_NAME_WKN_GRP,
43 .name = "CREATOR GROUP",
44 .sid = SID_CREATOR_GROUP,
45 .rtype = SID_NAME_WKN_GRP,
48 .name = "Owner Rights",
49 .sid = SID_OWNER_RIGHTS,
50 .rtype = SID_NAME_WKN_GRP,
53 .domain = "NT AUTHORITY",
56 .rtype = SID_NAME_WKN_GRP,
59 .domain = "NT AUTHORITY",
61 .sid = SID_NT_NETWORK,
62 .rtype = SID_NAME_WKN_GRP,
65 .domain = "NT AUTHORITY",
68 .rtype = SID_NAME_WKN_GRP,
71 .domain = "NT AUTHORITY",
72 .name = "Interactive",
73 .sid = SID_NT_INTERACTIVE,
74 .rtype = SID_NAME_WKN_GRP,
77 .domain = "NT AUTHORITY",
79 .sid = SID_NT_SERVICE,
80 .rtype = SID_NAME_WKN_GRP,
83 .domain = "NT AUTHORITY",
84 .name = "ANONYMOUS LOGON",
85 .sid = SID_NT_ANONYMOUS,
86 .rtype = SID_NAME_WKN_GRP,
89 .domain = "NT AUTHORITY",
92 .rtype = SID_NAME_WKN_GRP,
95 .domain = "NT AUTHORITY",
96 .name = "ServerLogon",
97 .sid = SID_NT_ENTERPRISE_DCS,
98 .rtype = SID_NAME_WKN_GRP,
101 .domain = "NT AUTHORITY",
104 .rtype = SID_NAME_WKN_GRP,
107 .domain = "NT AUTHORITY",
108 .name = "Authenticated Users",
109 .sid = SID_NT_AUTHENTICATED_USERS,
110 .rtype = SID_NAME_WKN_GRP,
113 .domain = "NT AUTHORITY",
114 .name = "Restricted",
115 .sid = SID_NT_RESTRICTED,
116 .rtype = SID_NAME_WKN_GRP,
119 .domain = "NT AUTHORITY",
120 .name = "Terminal Server User",
121 .sid = SID_NT_TERMINAL_SERVER_USERS,
122 .rtype = SID_NAME_WKN_GRP,
125 .domain = "NT AUTHORITY",
126 .name = "Remote Interactive Logon",
127 .sid = SID_NT_REMOTE_INTERACTIVE,
128 .rtype = SID_NAME_WKN_GRP,
131 .domain = "NT AUTHORITY",
132 .name = "This Organization",
133 .sid = SID_NT_THIS_ORGANISATION,
134 .rtype = SID_NAME_WKN_GRP,
137 .domain = "NT AUTHORITY",
139 .sid = SID_NT_SYSTEM,
140 .rtype = SID_NAME_WKN_GRP,
143 .domain = "NT AUTHORITY",
144 .name = "Local Service",
145 .sid = SID_NT_LOCAL_SERVICE,
146 .rtype = SID_NAME_WKN_GRP,
149 .domain = "NT AUTHORITY",
150 .name = "Network Service",
151 .sid = SID_NT_NETWORK_SERVICE,
152 .rtype = SID_NAME_WKN_GRP,
155 .domain = "NT AUTHORITY",
156 .name = "Digest Authentication",
157 .sid = SID_NT_DIGEST_AUTHENTICATION,
158 .rtype = SID_NAME_WKN_GRP,
161 .domain = "NT AUTHORITY",
162 .name = "Enterprise Domain Controllers",
163 .sid = SID_NT_ENTERPRISE_DCS,
164 .rtype = SID_NAME_WKN_GRP,
167 .domain = "NT AUTHORITY",
168 .name = "NTLM Authentication",
169 .sid = SID_NT_NTLM_AUTHENTICATION,
170 .rtype = SID_NAME_WKN_GRP,
173 .domain = "NT AUTHORITY",
174 .name = "Other Organization",
175 .sid = SID_NT_OTHER_ORGANISATION,
176 .rtype = SID_NAME_WKN_GRP,
179 .domain = "NT AUTHORITY",
180 .name = "SChannel Authentication",
181 .sid = SID_NT_SCHANNEL_AUTHENTICATION,
182 .rtype = SID_NAME_WKN_GRP,
185 .domain = "NT AUTHORITY",
188 .rtype = SID_NAME_WKN_GRP,
195 static NTSTATUS lookup_well_known_names(TALLOC_CTX *mem_ctx, const char *domain,
196 const char *name, const char **authority_name,
197 struct dom_sid **sid, enum lsa_SidType *rtype)
200 for (i=0; well_known[i].sid; i++) {
202 if (strcasecmp_m(domain, well_known[i].domain) == 0
203 && strcasecmp_m(name, well_known[i].name) == 0) {
204 *authority_name = well_known[i].domain;
205 *sid = dom_sid_parse_talloc(mem_ctx, well_known[i].sid);
206 *rtype = well_known[i].rtype;
210 if (strcasecmp_m(name, well_known[i].name) == 0) {
211 *authority_name = well_known[i].domain;
212 *sid = dom_sid_parse_talloc(mem_ctx, well_known[i].sid);
213 *rtype = well_known[i].rtype;
218 return NT_STATUS_NOT_FOUND;
221 static NTSTATUS lookup_well_known_sids(TALLOC_CTX *mem_ctx,
222 const char *sid_str, const char **authority_name,
223 const char **name, enum lsa_SidType *rtype)
226 for (i=0; well_known[i].sid; i++) {
227 if (strcasecmp_m(sid_str, well_known[i].sid) == 0) {
228 *authority_name = well_known[i].domain;
229 *name = well_known[i].name;
230 *rtype = well_known[i].rtype;
234 return NT_STATUS_NOT_FOUND;
238 lookup a SID for 1 name
240 static NTSTATUS dcesrv_lsa_lookup_name(struct tevent_context *ev_ctx,
241 struct loadparm_context *lp_ctx,
242 struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
243 const char *name, const char **authority_name,
244 struct dom_sid **sid, enum lsa_SidType *rtype,
249 struct ldb_message **res;
250 const char * const attrs[] = { "objectSid", "sAMAccountType", NULL};
253 const char *username;
254 struct ldb_dn *domain_dn;
255 struct dom_sid *domain_sid;
258 p = strchr_m(name, '\\');
260 domain = talloc_strndup(mem_ctx, name, p-name);
262 return NT_STATUS_NO_MEMORY;
265 } else if (strchr_m(name, '@')) {
266 status = crack_name_to_nt4_name(mem_ctx, ev_ctx, lp_ctx, DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL, name, &domain, &username);
267 if (!NT_STATUS_IS_OK(status)) {
268 DEBUG(3, ("Failed to crack name %s into an NT4 name: %s\n", name, nt_errstr(status)));
277 /* Look up table of well known names */
278 status = lookup_well_known_names(mem_ctx, NULL, username, authority_name, sid, rtype);
279 if (NT_STATUS_IS_OK(status)) {
280 dom_sid_split_rid(NULL, *sid, NULL, rid);
284 if (username == NULL) {
285 *authority_name = NAME_BUILTIN;
286 *sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN);
288 return NT_STATUS_NO_MEMORY;
290 *rtype = SID_NAME_DOMAIN;
295 if (strcasecmp_m(username, NAME_NT_AUTHORITY) == 0) {
296 *authority_name = NAME_NT_AUTHORITY;
297 *sid = dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY);
299 return NT_STATUS_NO_MEMORY;
301 *rtype = SID_NAME_DOMAIN;
302 dom_sid_split_rid(NULL, *sid, NULL, rid);
305 if (strcasecmp_m(username, NAME_BUILTIN) == 0) {
306 *authority_name = NAME_BUILTIN;
307 *sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN);
309 return NT_STATUS_NO_MEMORY;
311 *rtype = SID_NAME_DOMAIN;
315 if (strcasecmp_m(username, state->domain_dns) == 0) {
316 *authority_name = talloc_strdup(mem_ctx,
318 if (*authority_name == NULL) {
319 return NT_STATUS_NO_MEMORY;
321 *sid = dom_sid_dup(mem_ctx, state->domain_sid);
323 return NT_STATUS_NO_MEMORY;
325 *rtype = SID_NAME_DOMAIN;
329 if (strcasecmp_m(username, state->domain_name) == 0) {
330 *authority_name = talloc_strdup(mem_ctx,
332 if (*authority_name == NULL) {
333 return NT_STATUS_NO_MEMORY;
335 *sid = dom_sid_dup(mem_ctx, state->domain_sid);
337 return NT_STATUS_NO_MEMORY;
339 *rtype = SID_NAME_DOMAIN;
344 /* Perhaps this is a well known user? */
345 name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_NT_AUTHORITY, username);
347 return NT_STATUS_NO_MEMORY;
349 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
350 if (NT_STATUS_IS_OK(status)) {
354 /* Perhaps this is a BUILTIN user? */
355 name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_BUILTIN, username);
357 return NT_STATUS_NO_MEMORY;
359 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
360 if (NT_STATUS_IS_OK(status)) {
364 /* OK, I give up - perhaps we need to assume the user is in our domain? */
365 name = talloc_asprintf(mem_ctx, "%s\\%s", state->domain_name, username);
367 return NT_STATUS_NO_MEMORY;
369 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
370 if (NT_STATUS_IS_OK(status)) {
374 return STATUS_SOME_UNMAPPED;
375 } else if (strcasecmp_m(domain, NAME_NT_AUTHORITY) == 0) {
377 *authority_name = NAME_NT_AUTHORITY;
378 *sid = dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY);
380 return NT_STATUS_NO_MEMORY;
382 *rtype = SID_NAME_DOMAIN;
383 dom_sid_split_rid(NULL, *sid, NULL, rid);
387 /* Look up table of well known names */
388 status = lookup_well_known_names(mem_ctx, domain, username, authority_name,
390 if (NT_STATUS_IS_OK(status)) {
391 dom_sid_split_rid(NULL, *sid, NULL, rid);
394 } else if (strcasecmp_m(domain, NAME_BUILTIN) == 0) {
395 *authority_name = NAME_BUILTIN;
396 domain_dn = state->builtin_dn;
397 } else if (strcasecmp_m(domain, state->domain_dns) == 0) {
398 *authority_name = talloc_strdup(mem_ctx,
400 if (*authority_name == NULL) {
401 return NT_STATUS_NO_MEMORY;
403 domain_dn = state->domain_dn;
404 } else if (strcasecmp_m(domain, state->domain_name) == 0) {
405 *authority_name = talloc_strdup(mem_ctx,
407 if (*authority_name == NULL) {
408 return NT_STATUS_NO_MEMORY;
410 domain_dn = state->domain_dn;
412 /* Not local, need to ask winbind in future */
413 return STATUS_SOME_UNMAPPED;
416 ret = gendb_search_dn(state->sam_ldb, mem_ctx, domain_dn, &res, attrs);
418 return NT_STATUS_INTERNAL_DB_CORRUPTION;
420 domain_sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
421 if (domain_sid == NULL) {
422 return NT_STATUS_INVALID_SID;
427 *rtype = SID_NAME_DOMAIN;
432 ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs,
433 "(&(sAMAccountName=%s)(objectSid=*))",
434 ldb_binary_encode_string(mem_ctx, username));
436 return NT_STATUS_INTERNAL_DB_CORRUPTION;
439 for (i=0; i < ret; i++) {
440 *sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
442 return NT_STATUS_INVALID_SID;
445 /* Check that this is in the domain */
446 if (!dom_sid_in_domain(domain_sid, *sid)) {
450 atype = ldb_msg_find_attr_as_uint(res[i], "sAMAccountType", 0);
452 *rtype = ds_atype_map(atype);
453 if (*rtype == SID_NAME_UNKNOWN) {
454 return STATUS_SOME_UNMAPPED;
457 dom_sid_split_rid(NULL, *sid, NULL, rid);
461 /* need to check for an allocated sid */
463 return NT_STATUS_INVALID_SID;
468 add to the lsa_RefDomainList for LookupSids and LookupNames
470 static NTSTATUS dcesrv_lsa_authority_list(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
471 enum lsa_SidType rtype,
472 const char *authority_name,
474 struct lsa_RefDomainList *domains,
477 struct dom_sid *authority_sid;
480 if (rtype != SID_NAME_DOMAIN) {
481 authority_sid = dom_sid_dup(mem_ctx, sid);
482 if (authority_sid == NULL) {
483 return NT_STATUS_NO_MEMORY;
485 authority_sid->num_auths--;
490 /* see if we've already done this authority name */
491 for (i=0;i<domains->count;i++) {
492 if (strcasecmp_m(authority_name, domains->domains[i].name.string) == 0) {
498 domains->domains = talloc_realloc(domains,
500 struct lsa_DomainInfo,
502 if (domains->domains == NULL) {
503 return NT_STATUS_NO_MEMORY;
505 domains->domains[i].name.string = authority_name;
506 domains->domains[i].sid = authority_sid;
508 domains->max_size = LSA_REF_DOMAIN_LIST_MULTIPLIER * domains->count;
515 lookup a name for 1 SID
517 static NTSTATUS dcesrv_lsa_lookup_sid(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
518 struct dom_sid *sid, const char *sid_str,
519 const char **authority_name,
520 const char **name, enum lsa_SidType *rtype)
525 struct ldb_message **res;
526 struct ldb_dn *domain_dn;
527 const char * const attrs[] = { "sAMAccountName", "sAMAccountType", "cn", NULL};
529 status = lookup_well_known_sids(mem_ctx, sid_str, authority_name, name, rtype);
530 if (NT_STATUS_IS_OK(status)) {
534 if (dom_sid_equal(state->domain_sid, sid)) {
535 *authority_name = talloc_strdup(mem_ctx, state->domain_name);
536 if (*authority_name == NULL) {
537 return NT_STATUS_NO_MEMORY;
540 *rtype = SID_NAME_DOMAIN;
544 if (dom_sid_in_domain(state->domain_sid, sid)) {
545 *authority_name = talloc_strdup(mem_ctx, state->domain_name);
546 if (*authority_name == NULL) {
547 return NT_STATUS_NO_MEMORY;
549 domain_dn = state->domain_dn;
550 } else if (dom_sid_in_domain(state->builtin_sid, sid)) {
551 *authority_name = NAME_BUILTIN;
552 domain_dn = state->builtin_dn;
554 /* Not well known, our domain or built in */
556 /* In future, we must look at SID histories, and at trusted domains via winbind */
558 return NT_STATUS_NOT_FOUND;
561 /* need to re-add a check for an allocated sid */
563 ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs,
564 "objectSid=%s", ldap_encode_ndr_dom_sid(mem_ctx, sid));
565 if ((ret < 0) || (ret > 1)) {
566 return NT_STATUS_INTERNAL_DB_CORRUPTION;
569 return NT_STATUS_NOT_FOUND;
572 *name = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
574 *name = ldb_msg_find_attr_as_string(res[0], "cn", NULL);
576 *name = talloc_strdup(mem_ctx, sid_str);
577 NT_STATUS_HAVE_NO_MEMORY(*name);
581 atype = ldb_msg_find_attr_as_uint(res[0], "sAMAccountType", 0);
582 *rtype = ds_atype_map(atype);
587 static NTSTATUS dcesrv_lsa_LookupSids_common(struct dcesrv_call_state *dce_call,
589 struct lsa_policy_state *state,
590 struct lsa_LookupSids2 *r)
592 struct lsa_RefDomainList *domains = NULL;
593 NTSTATUS status = NT_STATUS_OK;
596 if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
597 r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
598 return NT_STATUS_INVALID_PARAMETER;
601 *r->out.domains = NULL;
603 /* NOTE: the WSPP test suite tries SIDs with invalid revision numbers,
604 and expects NT_STATUS_INVALID_PARAMETER back - we just treat it as
605 an unknown SID. We could add a SID validator here. (tridge)
609 domains = talloc_zero(r->out.domains, struct lsa_RefDomainList);
610 if (domains == NULL) {
611 return NT_STATUS_NO_MEMORY;
613 *r->out.domains = domains;
615 r->out.names = talloc_zero(mem_ctx, struct lsa_TransNameArray2);
616 if (r->out.names == NULL) {
617 return NT_STATUS_NO_MEMORY;
622 r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName2,
623 r->in.sids->num_sids);
624 if (r->out.names->names == NULL) {
625 return NT_STATUS_NO_MEMORY;
628 for (i=0;i<r->in.sids->num_sids;i++) {
629 struct dom_sid *sid = r->in.sids->sids[i].sid;
630 char *sid_str = dom_sid_string(mem_ctx, sid);
631 const char *name, *authority_name;
632 enum lsa_SidType rtype;
636 r->out.names->count++;
638 r->out.names->names[i].sid_type = SID_NAME_UNKNOWN;
639 r->out.names->names[i].name.string = sid_str;
640 r->out.names->names[i].sid_index = 0xFFFFFFFF;
641 r->out.names->names[i].unknown = 0;
643 if (sid_str == NULL) {
644 r->out.names->names[i].name.string = "(SIDERROR)";
645 status = STATUS_SOME_UNMAPPED;
649 status2 = dcesrv_lsa_lookup_sid(state, mem_ctx, sid, sid_str,
650 &authority_name, &name, &rtype);
651 if (!NT_STATUS_IS_OK(status2)) {
652 status = STATUS_SOME_UNMAPPED;
656 /* set up the authority table */
657 status2 = dcesrv_lsa_authority_list(state, mem_ctx, rtype,
659 domains, &sid_index);
660 if (!NT_STATUS_IS_OK(status2)) {
664 r->out.names->names[i].sid_type = rtype;
665 r->out.names->names[i].name.string = name;
666 r->out.names->names[i].sid_index = sid_index;
667 r->out.names->names[i].unknown = 0;
672 if (*r->out.count == 0) {
673 return NT_STATUS_NONE_MAPPED;
675 if (*r->out.count != r->in.sids->num_sids) {
676 return STATUS_SOME_UNMAPPED;
685 NTSTATUS dcesrv_lsa_LookupSids2(struct dcesrv_call_state *dce_call,
687 struct lsa_LookupSids2 *r)
689 enum dcerpc_transport_t transport =
690 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
691 struct lsa_policy_state *state;
692 struct dcesrv_handle *h;
694 if (transport != NCACN_NP && transport != NCALRPC) {
695 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
698 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
702 return dcesrv_lsa_LookupSids_common(dce_call,
712 Identical to LookupSids2, but doesn't take a policy handle
715 NTSTATUS dcesrv_lsa_LookupSids3(struct dcesrv_call_state *dce_call,
717 struct lsa_LookupSids3 *r)
719 enum dcerpc_transport_t transport =
720 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
721 struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
722 struct lsa_policy_state *policy_state;
723 struct lsa_LookupSids2 q;
726 if (transport != NCACN_IP_TCP) {
727 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
731 * We don't have policy handles on this call. So this must be restricted
732 * to crypto connections only.
734 if (auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL ||
735 auth_info->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
736 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
739 status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx,
740 0, /* we skip access checks */
742 if (!NT_STATUS_IS_OK(status)) {
749 q.in.sids = r->in.sids;
750 q.in.names = r->in.names;
751 q.in.level = r->in.level;
752 q.in.count = r->in.count;
753 q.in.lookup_options = r->in.lookup_options;
754 q.in.client_revision = r->in.client_revision;
755 q.out.count = r->out.count;
756 q.out.names = r->out.names;
757 q.out.domains = r->out.domains;
759 status = dcesrv_lsa_LookupSids_common(dce_call,
764 talloc_free(policy_state);
766 r->out.count = q.out.count;
767 r->out.names = q.out.names;
768 r->out.domains = q.out.domains;
777 NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
778 struct lsa_LookupSids *r)
780 enum dcerpc_transport_t transport =
781 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
782 struct lsa_LookupSids2 r2;
786 if (transport != NCACN_NP && transport != NCALRPC) {
787 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
792 r2.in.handle = r->in.handle;
793 r2.in.sids = r->in.sids;
795 r2.in.level = r->in.level;
796 r2.in.count = r->in.count;
797 r2.in.lookup_options = 0;
798 r2.in.client_revision = 0;
799 r2.out.count = r->out.count;
801 r2.out.domains = r->out.domains;
803 status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
804 /* we deliberately don't check for error from the above,
805 as even on error we are supposed to return the names */
807 r->out.domains = r2.out.domains;
813 r->out.names = talloc(mem_ctx, struct lsa_TransNameArray);
814 if (r->out.names == NULL) {
815 return NT_STATUS_NO_MEMORY;
817 r->out.names->count = r2.out.names->count;
818 r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName,
819 r->out.names->count);
820 if (r->out.names->names == NULL) {
821 return NT_STATUS_NO_MEMORY;
823 for (i=0;i<r->out.names->count;i++) {
824 r->out.names->names[i].sid_type = r2.out.names->names[i].sid_type;
825 r->out.names->names[i].name.string = r2.out.names->names[i].name.string;
826 r->out.names->names[i].sid_index = r2.out.names->names[i].sid_index;
832 static NTSTATUS dcesrv_lsa_LookupNames_common(struct dcesrv_call_state *dce_call,
834 struct lsa_policy_state *policy_state,
835 struct lsa_LookupNames3 *r)
837 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
838 struct lsa_RefDomainList *domains;
841 if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
842 r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
843 return NT_STATUS_INVALID_PARAMETER;
846 *r->out.domains = NULL;
848 domains = talloc_zero(mem_ctx, struct lsa_RefDomainList);
849 if (domains == NULL) {
850 return NT_STATUS_NO_MEMORY;
852 *r->out.domains = domains;
854 r->out.sids = talloc_zero(mem_ctx, struct lsa_TransSidArray3);
855 if (r->out.sids == NULL) {
856 return NT_STATUS_NO_MEMORY;
861 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid3,
863 if (r->out.sids->sids == NULL) {
864 return NT_STATUS_NO_MEMORY;
867 for (i=0;i<r->in.num_names;i++) {
868 const char *name = r->in.names[i].string;
869 const char *authority_name;
871 uint32_t sid_index, rid;
872 enum lsa_SidType rtype;
875 r->out.sids->count++;
877 r->out.sids->sids[i].sid_type = SID_NAME_UNKNOWN;
878 r->out.sids->sids[i].sid = NULL;
879 r->out.sids->sids[i].sid_index = 0xFFFFFFFF;
880 r->out.sids->sids[i].flags = 0;
882 status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, policy_state, mem_ctx, name,
883 &authority_name, &sid, &rtype, &rid);
884 if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) {
888 status2 = dcesrv_lsa_authority_list(policy_state, mem_ctx, rtype, authority_name,
889 sid, domains, &sid_index);
890 if (!NT_STATUS_IS_OK(status2)) {
894 r->out.sids->sids[i].sid_type = rtype;
895 r->out.sids->sids[i].sid = sid;
896 r->out.sids->sids[i].sid_index = sid_index;
897 r->out.sids->sids[i].flags = 0;
902 if (*r->out.count == 0) {
903 return NT_STATUS_NONE_MAPPED;
905 if (*r->out.count != r->in.num_names) {
906 return STATUS_SOME_UNMAPPED;
915 NTSTATUS dcesrv_lsa_LookupNames3(struct dcesrv_call_state *dce_call,
917 struct lsa_LookupNames3 *r)
919 enum dcerpc_transport_t transport =
920 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
921 struct lsa_policy_state *policy_state;
922 struct dcesrv_handle *policy_handle;
924 if (transport != NCACN_NP && transport != NCALRPC) {
925 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
928 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
930 policy_state = policy_handle->data;
932 return dcesrv_lsa_LookupNames_common(dce_call,
941 Identical to LookupNames3, but doesn't take a policy handle
944 NTSTATUS dcesrv_lsa_LookupNames4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
945 struct lsa_LookupNames4 *r)
947 enum dcerpc_transport_t transport =
948 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
949 struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
950 struct lsa_policy_state *policy_state;
951 struct lsa_LookupNames3 q;
954 if (transport != NCACN_IP_TCP) {
955 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
959 * We don't have policy handles on this call. So this must be restricted
960 * to crypto connections only.
962 if (auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL ||
963 auth_info->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
964 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
967 status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx,
968 0, /* we skip access checks */
970 if (!NT_STATUS_IS_OK(status)) {
977 q.in.num_names = r->in.num_names;
978 q.in.names = r->in.names;
979 q.in.level = r->in.level;
980 q.in.sids = r->in.sids;
981 q.in.count = r->in.count;
982 q.in.lookup_options = r->in.lookup_options;
983 q.in.client_revision = r->in.client_revision;
985 q.out.count = r->out.count;
986 q.out.sids = r->out.sids;
987 q.out.domains = r->out.domains;
989 status = dcesrv_lsa_LookupNames_common(dce_call,
994 talloc_free(policy_state);
996 r->out.count = q.out.count;
997 r->out.sids = q.out.sids;
998 r->out.domains = q.out.domains;
1006 NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call,
1007 TALLOC_CTX *mem_ctx,
1008 struct lsa_LookupNames2 *r)
1010 enum dcerpc_transport_t transport =
1011 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
1012 struct lsa_policy_state *state;
1013 struct dcesrv_handle *h;
1015 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
1016 struct lsa_RefDomainList *domains;
1018 if (transport != NCACN_NP && transport != NCALRPC) {
1019 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
1022 *r->out.domains = NULL;
1024 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
1026 if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
1027 r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
1028 return NT_STATUS_INVALID_PARAMETER;
1033 domains = talloc_zero(mem_ctx, struct lsa_RefDomainList);
1034 if (domains == NULL) {
1035 return NT_STATUS_NO_MEMORY;
1037 *r->out.domains = domains;
1039 r->out.sids = talloc_zero(mem_ctx, struct lsa_TransSidArray2);
1040 if (r->out.sids == NULL) {
1041 return NT_STATUS_NO_MEMORY;
1046 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid2,
1048 if (r->out.sids->sids == NULL) {
1049 return NT_STATUS_NO_MEMORY;
1052 for (i=0;i<r->in.num_names;i++) {
1053 const char *name = r->in.names[i].string;
1054 const char *authority_name;
1055 struct dom_sid *sid;
1056 uint32_t sid_index, rid=0;
1057 enum lsa_SidType rtype;
1060 r->out.sids->count++;
1062 r->out.sids->sids[i].sid_type = SID_NAME_UNKNOWN;
1063 /* MS-LSAT 3.1.4.7 - rid zero is considered equivalent
1064 to sid NULL - so we should return 0 rid for
1066 r->out.sids->sids[i].rid = 0;
1067 r->out.sids->sids[i].sid_index = 0xFFFFFFFF;
1068 r->out.sids->sids[i].unknown = 0;
1070 status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, state, mem_ctx, name,
1071 &authority_name, &sid, &rtype, &rid);
1072 if (!NT_STATUS_IS_OK(status2)) {
1076 status2 = dcesrv_lsa_authority_list(state, mem_ctx, rtype, authority_name,
1077 sid, domains, &sid_index);
1078 if (!NT_STATUS_IS_OK(status2)) {
1082 r->out.sids->sids[i].sid_type = rtype;
1083 r->out.sids->sids[i].rid = rid;
1084 r->out.sids->sids[i].sid_index = sid_index;
1085 r->out.sids->sids[i].unknown = 0;
1090 if (*r->out.count == 0) {
1091 return NT_STATUS_NONE_MAPPED;
1093 if (*r->out.count != r->in.num_names) {
1094 return STATUS_SOME_UNMAPPED;
1097 return NT_STATUS_OK;
1103 NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1104 struct lsa_LookupNames *r)
1106 enum dcerpc_transport_t transport =
1107 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
1108 struct lsa_LookupNames2 r2;
1112 if (transport != NCACN_NP && transport != NCALRPC) {
1113 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
1118 r2.in.handle = r->in.handle;
1119 r2.in.num_names = r->in.num_names;
1120 r2.in.names = r->in.names;
1122 r2.in.level = r->in.level;
1123 r2.in.count = r->in.count;
1124 r2.in.lookup_options = 0;
1125 r2.in.client_revision = 0;
1126 r2.out.count = r->out.count;
1127 r2.out.domains = r->out.domains;
1129 status = dcesrv_lsa_LookupNames2(dce_call, mem_ctx, &r2);
1130 if (r2.out.sids == NULL) {
1134 r->out.sids = talloc(mem_ctx, struct lsa_TransSidArray);
1135 if (r->out.sids == NULL) {
1136 return NT_STATUS_NO_MEMORY;
1138 r->out.sids->count = r2.out.sids->count;
1139 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid,
1140 r->out.sids->count);
1141 if (r->out.sids->sids == NULL) {
1142 return NT_STATUS_NO_MEMORY;
1144 for (i=0;i<r->out.sids->count;i++) {
1145 r->out.sids->sids[i].sid_type = r2.out.sids->sids[i].sid_type;
1146 r->out.sids->sids[i].rid = r2.out.sids->sids[i].rid;
1147 r->out.sids->sids[i].sid_index = r2.out.sids->sids[i].sid_index;