Use ntvfs session close to close downstream session
[Samba/vfs_proxy.git] / source4 / rpc_server / lsa / lsa_lookup.c
bloba56e7764a985c12e24f2e561b87f9fce2c1264b5
1 /*
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"
25 static const struct {
26 const char *domain;
27 const char *name;
28 const char *sid;
29 int rtype;
30 } well_known[] = {
32 .name = "EVERYONE",
33 .sid = SID_WORLD,
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",
53 .name = "Dialup",
54 .sid = SID_NT_DIALUP,
55 .rtype = SID_NAME_WKN_GRP,
58 .domain = "NT AUTHORITY",
59 .name = "Network",
60 .sid = SID_NT_NETWORK,
61 .rtype = SID_NAME_WKN_GRP,
64 .domain = "NT AUTHORITY",
65 .name = "Batch",
66 .sid = SID_NT_BATCH,
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",
77 .name = "Service",
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",
89 .name = "Proxy",
90 .sid = SID_NT_PROXY,
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",
101 .name = "Self",
102 .sid = SID_NT_SELF,
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",
137 .name = "SYSTEM",
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",
185 .name = "IUSR",
186 .sid = SID_NT_IUSR,
187 .rtype = SID_NAME_WKN_GRP,
190 .sid = NULL,
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, uint32_t *rtype)
198 int i;
199 for (i=0; well_known[i].sid; i++) {
200 if (domain) {
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;
206 return NT_STATUS_OK;
208 } else {
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;
213 return NT_STATUS_OK;
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, uint32_t *rtype)
224 int i;
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;
230 return NT_STATUS_OK;
233 return NT_STATUS_NOT_FOUND;
237 lookup a SID for 1 name
239 static NTSTATUS dcesrv_lsa_lookup_name(struct event_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)
245 int ret, atype, i;
246 struct ldb_message **res;
247 const char * const attrs[] = { "objectSid", "sAMAccountType", NULL};
248 const char *p;
249 const char *domain;
250 const char *username;
251 struct ldb_dn *domain_dn;
252 struct dom_sid *domain_sid;
253 NTSTATUS status;
255 p = strchr_m(name, '\\');
256 if (p != NULL) {
257 domain = talloc_strndup(mem_ctx, name, p-name);
258 if (!domain) {
259 return NT_STATUS_NO_MEMORY;
261 username = p + 1;
262 } else if (strchr_m(name, '@')) {
263 status = crack_name_to_nt4_name(mem_ctx, ev_ctx, lp_ctx, DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL, name, &domain, &username);
264 if (!NT_STATUS_IS_OK(status)) {
265 DEBUG(3, ("Failed to crack name %s into an NT4 name: %s\n", name, nt_errstr(status)));
266 return status;
268 } else {
269 domain = NULL;
270 username = name;
273 if (!domain) {
274 /* Look up table of well known names */
275 status = lookup_well_known_names(mem_ctx, NULL, username, authority_name, sid, rtype);
276 if (NT_STATUS_IS_OK(status)) {
277 return NT_STATUS_OK;
280 if (strcasecmp_m(username, NAME_NT_AUTHORITY) == 0) {
281 *authority_name = NAME_NT_AUTHORITY;
282 *sid = dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY);
283 *rtype = SID_NAME_DOMAIN;
284 return NT_STATUS_OK;
286 if (strcasecmp_m(username, NAME_BUILTIN) == 0) {
287 *authority_name = NAME_BUILTIN;
288 *sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN);
289 *rtype = SID_NAME_DOMAIN;
290 return NT_STATUS_OK;
292 if (strcasecmp_m(username, state->domain_dns) == 0) {
293 *authority_name = state->domain_name;
294 *sid = state->domain_sid;
295 *rtype = SID_NAME_DOMAIN;
296 return NT_STATUS_OK;
298 if (strcasecmp_m(username, state->domain_name) == 0) {
299 *authority_name = state->domain_name;
300 *sid = state->domain_sid;
301 *rtype = SID_NAME_DOMAIN;
302 return NT_STATUS_OK;
305 /* Perhaps this is a well known user? */
306 name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_NT_AUTHORITY, username);
307 if (!name) {
308 return NT_STATUS_NO_MEMORY;
310 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype);
311 if (NT_STATUS_IS_OK(status)) {
312 return status;
315 /* Perhaps this is a BUILTIN user? */
316 name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_BUILTIN, username);
317 if (!name) {
318 return NT_STATUS_NO_MEMORY;
320 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype);
321 if (NT_STATUS_IS_OK(status)) {
322 return status;
325 /* OK, I give up - perhaps we need to assume the user is in our domain? */
326 name = talloc_asprintf(mem_ctx, "%s\\%s", state->domain_name, username);
327 if (!name) {
328 return NT_STATUS_NO_MEMORY;
330 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype);
331 if (NT_STATUS_IS_OK(status)) {
332 return status;
335 return STATUS_SOME_UNMAPPED;
336 } else if (strcasecmp_m(domain, NAME_NT_AUTHORITY) == 0) {
337 if (!*username) {
338 *authority_name = NAME_NT_AUTHORITY;
339 *sid = dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY);
340 *rtype = SID_NAME_DOMAIN;
341 return NT_STATUS_OK;
344 /* Look up table of well known names */
345 return lookup_well_known_names(mem_ctx, domain, username, authority_name,
346 sid, rtype);
347 } else if (strcasecmp_m(domain, NAME_BUILTIN) == 0) {
348 *authority_name = NAME_BUILTIN;
349 domain_dn = state->builtin_dn;
350 } else if (strcasecmp_m(domain, state->domain_dns) == 0) {
351 *authority_name = state->domain_name;
352 domain_dn = state->domain_dn;
353 } else if (strcasecmp_m(domain, state->domain_name) == 0) {
354 *authority_name = state->domain_name;
355 domain_dn = state->domain_dn;
356 } else {
357 /* Not local, need to ask winbind in future */
358 return STATUS_SOME_UNMAPPED;
361 ret = gendb_search_dn(state->sam_ldb, mem_ctx, domain_dn, &res, attrs);
362 if (ret == 1) {
363 domain_sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
364 if (domain_sid == NULL) {
365 return NT_STATUS_INVALID_SID;
367 } else {
368 return NT_STATUS_INVALID_SID;
371 if (!*username) {
372 *sid = domain_sid;
373 *rtype = SID_NAME_DOMAIN;
374 return NT_STATUS_OK;
377 ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs,
378 "(&(sAMAccountName=%s)(objectSid=*))",
379 ldb_binary_encode_string(mem_ctx, username));
380 if (ret == -1) {
381 return NT_STATUS_INVALID_SID;
384 for (i=0; i < ret; i++) {
385 *sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
386 if (*sid == NULL) {
387 return NT_STATUS_INVALID_SID;
390 /* Check that this is in the domain */
391 if (!dom_sid_in_domain(domain_sid, *sid)) {
392 continue;
395 atype = samdb_result_uint(res[i], "sAMAccountType", 0);
397 *rtype = samdb_atype_map(atype);
398 if (*rtype == SID_NAME_UNKNOWN) {
399 return STATUS_SOME_UNMAPPED;
402 return NT_STATUS_OK;
405 /* need to check for an allocated sid */
407 return NT_STATUS_INVALID_SID;
412 add to the lsa_RefDomainList for LookupSids and LookupNames
414 static NTSTATUS dcesrv_lsa_authority_list(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
415 enum lsa_SidType rtype,
416 const char *authority_name,
417 struct dom_sid *sid,
418 struct lsa_RefDomainList *domains,
419 uint32_t *sid_index)
421 struct dom_sid *authority_sid;
422 int i;
424 if (rtype != SID_NAME_DOMAIN) {
425 authority_sid = dom_sid_dup(mem_ctx, sid);
426 if (authority_sid == NULL) {
427 return NT_STATUS_NO_MEMORY;
429 authority_sid->num_auths--;
430 } else {
431 authority_sid = sid;
434 /* see if we've already done this authority name */
435 for (i=0;i<domains->count;i++) {
436 if (strcasecmp_m(authority_name, domains->domains[i].name.string) == 0) {
437 *sid_index = i;
438 return NT_STATUS_OK;
442 domains->domains = talloc_realloc(domains,
443 domains->domains,
444 struct lsa_DomainInfo,
445 domains->count+1);
446 if (domains->domains == NULL) {
447 return NT_STATUS_NO_MEMORY;
449 domains->domains[i].name.string = authority_name;
450 domains->domains[i].sid = authority_sid;
451 domains->count++;
452 domains->max_size = LSA_REF_DOMAIN_LIST_MULTIPLIER * domains->count;
453 *sid_index = i;
455 return NT_STATUS_OK;
459 lookup a name for 1 SID
461 static NTSTATUS dcesrv_lsa_lookup_sid(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
462 struct dom_sid *sid, const char *sid_str,
463 const char **authority_name,
464 const char **name, enum lsa_SidType *rtype)
466 NTSTATUS status;
467 int ret;
468 uint32_t atype;
469 struct ldb_message **res;
470 struct ldb_dn *domain_dn;
471 const char * const attrs[] = { "sAMAccountName", "sAMAccountType", "cn", NULL};
473 status = lookup_well_known_sids(mem_ctx, sid_str, authority_name, name, rtype);
474 if (NT_STATUS_IS_OK(status)) {
475 return status;
478 if (dom_sid_in_domain(state->domain_sid, sid)) {
479 *authority_name = state->domain_name;
480 domain_dn = state->domain_dn;
481 } else if (dom_sid_in_domain(state->builtin_sid, sid)) {
482 *authority_name = NAME_BUILTIN;
483 domain_dn = state->builtin_dn;
484 } else {
485 /* Not well known, our domain or built in */
487 /* In future, we must look at SID histories, and at trusted domains via winbind */
489 return NT_STATUS_NOT_FOUND;
492 ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs,
493 "objectSid=%s", ldap_encode_ndr_dom_sid(mem_ctx, sid));
494 if (ret == 1) {
495 *name = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
496 if (!*name) {
497 *name = ldb_msg_find_attr_as_string(res[0], "cn", NULL);
498 if (!*name) {
499 *name = talloc_strdup(mem_ctx, sid_str);
500 NT_STATUS_HAVE_NO_MEMORY(*name);
504 atype = samdb_result_uint(res[0], "sAMAccountType", 0);
506 *rtype = samdb_atype_map(atype);
508 return NT_STATUS_OK;
511 /* need to re-add a check for an allocated sid */
513 return NT_STATUS_NOT_FOUND;
518 lsa_LookupSids2
520 NTSTATUS dcesrv_lsa_LookupSids2(struct dcesrv_call_state *dce_call,
521 TALLOC_CTX *mem_ctx,
522 struct lsa_LookupSids2 *r)
524 struct lsa_policy_state *state;
525 struct lsa_RefDomainList *domains = NULL;
526 int i;
527 NTSTATUS status = NT_STATUS_OK;
529 if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
530 r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
531 return NT_STATUS_INVALID_PARAMETER;
534 *r->out.domains = NULL;
536 /* NOTE: the WSPP test suite tries SIDs with invalid revision numbers,
537 and expects NT_STATUS_INVALID_PARAMETER back - we just treat it as
538 an unknown SID. We could add a SID validator here. (tridge)
539 MS-DTYP 2.4.2
542 status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
543 if (!NT_STATUS_IS_OK(status)) {
544 return status;
547 domains = talloc_zero(r->out.domains, struct lsa_RefDomainList);
548 if (domains == NULL) {
549 return NT_STATUS_NO_MEMORY;
551 *r->out.domains = domains;
553 r->out.names = talloc_zero(mem_ctx, struct lsa_TransNameArray2);
554 if (r->out.names == NULL) {
555 return NT_STATUS_NO_MEMORY;
558 *r->out.count = 0;
560 r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName2,
561 r->in.sids->num_sids);
562 if (r->out.names->names == NULL) {
563 return NT_STATUS_NO_MEMORY;
566 for (i=0;i<r->in.sids->num_sids;i++) {
567 struct dom_sid *sid = r->in.sids->sids[i].sid;
568 char *sid_str = dom_sid_string(mem_ctx, sid);
569 const char *name, *authority_name;
570 enum lsa_SidType rtype;
571 uint32_t sid_index;
572 NTSTATUS status2;
574 r->out.names->count++;
576 r->out.names->names[i].sid_type = SID_NAME_UNKNOWN;
577 r->out.names->names[i].name.string = sid_str;
578 r->out.names->names[i].sid_index = 0xFFFFFFFF;
579 r->out.names->names[i].unknown = 0;
581 if (sid_str == NULL) {
582 r->out.names->names[i].name.string = "(SIDERROR)";
583 status = STATUS_SOME_UNMAPPED;
584 continue;
587 status2 = dcesrv_lsa_lookup_sid(state, mem_ctx, sid, sid_str,
588 &authority_name, &name, &rtype);
589 if (!NT_STATUS_IS_OK(status2)) {
590 status = STATUS_SOME_UNMAPPED;
591 continue;
594 /* set up the authority table */
595 status2 = dcesrv_lsa_authority_list(state, mem_ctx, rtype,
596 authority_name, sid,
597 domains, &sid_index);
598 if (!NT_STATUS_IS_OK(status2)) {
599 continue;
602 r->out.names->names[i].sid_type = rtype;
603 r->out.names->names[i].name.string = name;
604 r->out.names->names[i].sid_index = sid_index;
605 r->out.names->names[i].unknown = 0;
607 (*r->out.count)++;
610 if (*r->out.count == 0) {
611 return NT_STATUS_NONE_MAPPED;
613 if (*r->out.count != r->in.sids->num_sids) {
614 return STATUS_SOME_UNMAPPED;
617 return NT_STATUS_OK;
622 lsa_LookupSids3
624 Identical to LookupSids2, but doesn't take a policy handle
627 NTSTATUS dcesrv_lsa_LookupSids3(struct dcesrv_call_state *dce_call,
628 TALLOC_CTX *mem_ctx,
629 struct lsa_LookupSids3 *r)
631 struct lsa_LookupSids2 r2;
632 struct lsa_OpenPolicy2 pol;
633 NTSTATUS status;
634 struct dcesrv_handle *h;
636 ZERO_STRUCT(r2);
638 /* No policy handle on the wire, so make one up here */
639 r2.in.handle = talloc(mem_ctx, struct policy_handle);
640 if (!r2.in.handle) {
641 return NT_STATUS_NO_MEMORY;
644 pol.out.handle = r2.in.handle;
645 pol.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
646 pol.in.attr = NULL;
647 pol.in.system_name = NULL;
648 status = dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &pol);
649 if (!NT_STATUS_IS_OK(status)) {
650 return status;
653 /* ensure this handle goes away at the end of this call */
654 DCESRV_PULL_HANDLE(h, r2.in.handle, LSA_HANDLE_POLICY);
655 talloc_steal(mem_ctx, h);
657 r2.in.sids = r->in.sids;
658 r2.in.names = r->in.names;
659 r2.in.level = r->in.level;
660 r2.in.count = r->in.count;
661 r2.in.unknown1 = r->in.unknown1;
662 r2.in.unknown2 = r->in.unknown2;
663 r2.out.count = r->out.count;
664 r2.out.names = r->out.names;
665 r2.out.domains = r->out.domains;
667 status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
669 r->out.domains = r2.out.domains;
670 r->out.names = r2.out.names;
671 r->out.count = r2.out.count;
673 return status;
678 lsa_LookupSids
680 NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
681 struct lsa_LookupSids *r)
683 struct lsa_LookupSids2 r2;
684 NTSTATUS status;
685 int i;
687 ZERO_STRUCT(r2);
689 r2.in.handle = r->in.handle;
690 r2.in.sids = r->in.sids;
691 r2.in.names = NULL;
692 r2.in.level = r->in.level;
693 r2.in.count = r->in.count;
694 r2.in.unknown1 = 0;
695 r2.in.unknown2 = 0;
696 r2.out.count = r->out.count;
697 r2.out.names = NULL;
698 r2.out.domains = r->out.domains;
700 status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
701 /* we deliberately don't check for error from the above,
702 as even on error we are supposed to return the names */
704 r->out.domains = r2.out.domains;
705 if (!r2.out.names) {
706 r->out.names = NULL;
707 return status;
710 r->out.names = talloc(mem_ctx, struct lsa_TransNameArray);
711 if (r->out.names == NULL) {
712 return NT_STATUS_NO_MEMORY;
714 r->out.names->count = r2.out.names->count;
715 r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName,
716 r->out.names->count);
717 if (r->out.names->names == NULL) {
718 return NT_STATUS_NO_MEMORY;
720 for (i=0;i<r->out.names->count;i++) {
721 r->out.names->names[i].sid_type = r2.out.names->names[i].sid_type;
722 r->out.names->names[i].name.string = r2.out.names->names[i].name.string;
723 r->out.names->names[i].sid_index = r2.out.names->names[i].sid_index;
726 return status;
731 lsa_LookupNames3
733 NTSTATUS dcesrv_lsa_LookupNames3(struct dcesrv_call_state *dce_call,
734 TALLOC_CTX *mem_ctx,
735 struct lsa_LookupNames3 *r)
737 struct lsa_policy_state *policy_state;
738 struct dcesrv_handle *policy_handle;
739 int i;
740 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
741 struct lsa_RefDomainList *domains;
743 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
745 if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
746 r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
747 return NT_STATUS_INVALID_PARAMETER;
750 policy_state = policy_handle->data;
752 *r->out.domains = NULL;
754 domains = talloc_zero(mem_ctx, struct lsa_RefDomainList);
755 if (domains == NULL) {
756 return NT_STATUS_NO_MEMORY;
758 *r->out.domains = domains;
760 r->out.sids = talloc_zero(mem_ctx, struct lsa_TransSidArray3);
761 if (r->out.sids == NULL) {
762 return NT_STATUS_NO_MEMORY;
765 *r->out.count = 0;
767 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid3,
768 r->in.num_names);
769 if (r->out.sids->sids == NULL) {
770 return NT_STATUS_NO_MEMORY;
773 for (i=0;i<r->in.num_names;i++) {
774 const char *name = r->in.names[i].string;
775 const char *authority_name;
776 struct dom_sid *sid;
777 uint32_t sid_index;
778 enum lsa_SidType rtype;
779 NTSTATUS status2;
781 r->out.sids->count++;
783 r->out.sids->sids[i].sid_type = SID_NAME_UNKNOWN;
784 r->out.sids->sids[i].sid = NULL;
785 r->out.sids->sids[i].sid_index = 0xFFFFFFFF;
786 r->out.sids->sids[i].flags = 0;
788 status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, policy_state, mem_ctx, name, &authority_name, &sid, &rtype);
789 if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) {
790 continue;
793 status2 = dcesrv_lsa_authority_list(policy_state, mem_ctx, rtype, authority_name,
794 sid, domains, &sid_index);
795 if (!NT_STATUS_IS_OK(status2)) {
796 continue;
799 r->out.sids->sids[i].sid_type = rtype;
800 r->out.sids->sids[i].sid = sid;
801 r->out.sids->sids[i].sid_index = sid_index;
802 r->out.sids->sids[i].flags = 0;
804 (*r->out.count)++;
807 if (*r->out.count == 0) {
808 return NT_STATUS_NONE_MAPPED;
810 if (*r->out.count != r->in.num_names) {
811 return STATUS_SOME_UNMAPPED;
814 return NT_STATUS_OK;
818 lsa_LookupNames4
820 Identical to LookupNames3, but doesn't take a policy handle
823 NTSTATUS dcesrv_lsa_LookupNames4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
824 struct lsa_LookupNames4 *r)
826 struct lsa_LookupNames3 r2;
827 struct lsa_OpenPolicy2 pol;
828 NTSTATUS status;
829 struct dcesrv_handle *h;
831 ZERO_STRUCT(r2);
833 /* No policy handle on the wire, so make one up here */
834 r2.in.handle = talloc(mem_ctx, struct policy_handle);
835 if (!r2.in.handle) {
836 return NT_STATUS_NO_MEMORY;
839 pol.out.handle = r2.in.handle;
840 pol.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
841 pol.in.attr = NULL;
842 pol.in.system_name = NULL;
843 status = dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &pol);
844 if (!NT_STATUS_IS_OK(status)) {
845 return status;
848 /* ensure this handle goes away at the end of this call */
849 DCESRV_PULL_HANDLE(h, r2.in.handle, LSA_HANDLE_POLICY);
850 talloc_steal(mem_ctx, h);
852 r2.in.num_names = r->in.num_names;
853 r2.in.names = r->in.names;
854 r2.in.level = r->in.level;
855 r2.in.sids = r->in.sids;
856 r2.in.count = r->in.count;
857 r2.in.lookup_options = r->in.lookup_options;
858 r2.in.client_revision = r->in.client_revision;
859 r2.out.domains = r->out.domains;
860 r2.out.sids = r->out.sids;
861 r2.out.count = r->out.count;
863 status = dcesrv_lsa_LookupNames3(dce_call, mem_ctx, &r2);
865 r->out.domains = r2.out.domains;
866 r->out.sids = r2.out.sids;
867 r->out.count = r2.out.count;
868 return status;
872 lsa_LookupNames2
874 NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call,
875 TALLOC_CTX *mem_ctx,
876 struct lsa_LookupNames2 *r)
878 struct lsa_policy_state *state;
879 struct dcesrv_handle *h;
880 int i;
881 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
882 struct lsa_RefDomainList *domains;
884 *r->out.domains = NULL;
886 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
888 if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
889 r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
890 return NT_STATUS_INVALID_PARAMETER;
893 state = h->data;
895 domains = talloc_zero(mem_ctx, struct lsa_RefDomainList);
896 if (domains == NULL) {
897 return NT_STATUS_NO_MEMORY;
899 *r->out.domains = domains;
901 r->out.sids = talloc_zero(mem_ctx, struct lsa_TransSidArray2);
902 if (r->out.sids == NULL) {
903 return NT_STATUS_NO_MEMORY;
906 *r->out.count = 0;
908 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid2,
909 r->in.num_names);
910 if (r->out.sids->sids == NULL) {
911 return NT_STATUS_NO_MEMORY;
914 for (i=0;i<r->in.num_names;i++) {
915 const char *name = r->in.names[i].string;
916 const char *authority_name;
917 struct dom_sid *sid;
918 uint32_t rtype, sid_index;
919 NTSTATUS status2;
921 r->out.sids->count++;
923 r->out.sids->sids[i].sid_type = SID_NAME_UNKNOWN;
924 /* MS-LSAT 3.1.4.7 - rid zero is considered equivalent
925 to sid NULL - so we should return 0 rid for
926 unmapped entries */
927 r->out.sids->sids[i].rid = 0;
928 r->out.sids->sids[i].sid_index = 0xFFFFFFFF;
929 r->out.sids->sids[i].unknown = 0;
931 status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, state, mem_ctx, name,
932 &authority_name, &sid, &rtype);
933 if (!NT_STATUS_IS_OK(status2)) {
934 continue;
937 status2 = dcesrv_lsa_authority_list(state, mem_ctx, rtype, authority_name,
938 sid, domains, &sid_index);
939 if (!NT_STATUS_IS_OK(status2)) {
940 continue;
943 r->out.sids->sids[i].sid_type = rtype;
944 r->out.sids->sids[i].rid = sid->sub_auths[sid->num_auths-1];
945 r->out.sids->sids[i].sid_index = sid_index;
946 r->out.sids->sids[i].unknown = 0;
948 (*r->out.count)++;
951 if (*r->out.count == 0) {
952 return NT_STATUS_NONE_MAPPED;
954 if (*r->out.count != r->in.num_names) {
955 return STATUS_SOME_UNMAPPED;
958 return NT_STATUS_OK;
962 lsa_LookupNames
964 NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
965 struct lsa_LookupNames *r)
967 struct lsa_LookupNames2 r2;
968 NTSTATUS status;
969 int i;
971 ZERO_STRUCT(r2);
973 r2.in.handle = r->in.handle;
974 r2.in.num_names = r->in.num_names;
975 r2.in.names = r->in.names;
976 r2.in.sids = NULL;
977 r2.in.level = r->in.level;
978 r2.in.count = r->in.count;
979 r2.in.lookup_options = 0;
980 r2.in.client_revision = 0;
981 r2.out.count = r->out.count;
982 r2.out.domains = r->out.domains;
984 status = dcesrv_lsa_LookupNames2(dce_call, mem_ctx, &r2);
985 if (r2.out.sids == NULL) {
986 return status;
989 r->out.sids = talloc(mem_ctx, struct lsa_TransSidArray);
990 if (r->out.sids == NULL) {
991 return NT_STATUS_NO_MEMORY;
993 r->out.sids->count = r2.out.sids->count;
994 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid,
995 r->out.sids->count);
996 if (r->out.sids->sids == NULL) {
997 return NT_STATUS_NO_MEMORY;
999 for (i=0;i<r->out.sids->count;i++) {
1000 r->out.sids->sids[i].sid_type = r2.out.sids->sids[i].sid_type;
1001 r->out.sids->sids[i].rid = r2.out.sids->sids[i].rid;
1002 r->out.sids->sids[i].sid_index = r2.out.sids->sids[i].sid_index;
1005 return status;