s4-lsa: fixed the lsa server to cope with the new tests from gd
[Samba.git] / source4 / rpc_server / lsa / lsa_lookup.c
blob27371ea8d1d339673dca39be023c0590ecf67234
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 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,
244 uint32_t *rid)
246 int ret, atype, i;
247 struct ldb_message **res;
248 const char * const attrs[] = { "objectSid", "sAMAccountType", NULL};
249 const char *p;
250 const char *domain;
251 const char *username;
252 struct ldb_dn *domain_dn;
253 struct dom_sid *domain_sid;
254 NTSTATUS status;
256 p = strchr_m(name, '\\');
257 if (p != NULL) {
258 domain = talloc_strndup(mem_ctx, name, p-name);
259 if (!domain) {
260 return NT_STATUS_NO_MEMORY;
262 username = p + 1;
263 } else if (strchr_m(name, '@')) {
264 status = crack_name_to_nt4_name(mem_ctx, ev_ctx, lp_ctx, DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL, name, &domain, &username);
265 if (!NT_STATUS_IS_OK(status)) {
266 DEBUG(3, ("Failed to crack name %s into an NT4 name: %s\n", name, nt_errstr(status)));
267 return status;
269 } else {
270 domain = NULL;
271 username = name;
274 if (!domain) {
275 /* Look up table of well known names */
276 status = lookup_well_known_names(mem_ctx, NULL, username, authority_name, sid, rtype);
277 if (NT_STATUS_IS_OK(status)) {
278 dom_sid_split_rid(NULL, *sid, NULL, rid);
279 return NT_STATUS_OK;
282 if (username == NULL) {
283 *authority_name = NAME_BUILTIN;
284 *sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN);
285 *rtype = SID_NAME_DOMAIN;
286 *rid = 0xFFFFFFFF;
287 return NT_STATUS_OK;
290 if (strcasecmp_m(username, NAME_NT_AUTHORITY) == 0) {
291 *authority_name = NAME_NT_AUTHORITY;
292 *sid = dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY);
293 *rtype = SID_NAME_DOMAIN;
294 dom_sid_split_rid(NULL, *sid, NULL, rid);
295 return NT_STATUS_OK;
297 if (strcasecmp_m(username, NAME_BUILTIN) == 0) {
298 *authority_name = NAME_BUILTIN;
299 *sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN);
300 *rtype = SID_NAME_DOMAIN;
301 *rid = 0xFFFFFFFF;
302 return NT_STATUS_OK;
304 if (strcasecmp_m(username, state->domain_dns) == 0) {
305 *authority_name = state->domain_name;
306 *sid = state->domain_sid;
307 *rtype = SID_NAME_DOMAIN;
308 *rid = 0xFFFFFFFF;
309 return NT_STATUS_OK;
311 if (strcasecmp_m(username, state->domain_name) == 0) {
312 *authority_name = state->domain_name;
313 *sid = state->domain_sid;
314 *rtype = SID_NAME_DOMAIN;
315 *rid = 0xFFFFFFFF;
316 return NT_STATUS_OK;
319 /* Perhaps this is a well known user? */
320 name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_NT_AUTHORITY, username);
321 if (!name) {
322 return NT_STATUS_NO_MEMORY;
324 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
325 if (NT_STATUS_IS_OK(status)) {
326 return status;
329 /* Perhaps this is a BUILTIN user? */
330 name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_BUILTIN, username);
331 if (!name) {
332 return NT_STATUS_NO_MEMORY;
334 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
335 if (NT_STATUS_IS_OK(status)) {
336 return status;
339 /* OK, I give up - perhaps we need to assume the user is in our domain? */
340 name = talloc_asprintf(mem_ctx, "%s\\%s", state->domain_name, username);
341 if (!name) {
342 return NT_STATUS_NO_MEMORY;
344 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
345 if (NT_STATUS_IS_OK(status)) {
346 return status;
349 return STATUS_SOME_UNMAPPED;
350 } else if (strcasecmp_m(domain, NAME_NT_AUTHORITY) == 0) {
351 if (!*username) {
352 *authority_name = NAME_NT_AUTHORITY;
353 *sid = dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY);
354 *rtype = SID_NAME_DOMAIN;
355 dom_sid_split_rid(NULL, *sid, NULL, rid);
356 return NT_STATUS_OK;
359 /* Look up table of well known names */
360 status = lookup_well_known_names(mem_ctx, domain, username, authority_name,
361 sid, rtype);
362 if (NT_STATUS_IS_OK(status)) {
363 dom_sid_split_rid(NULL, *sid, NULL, rid);
365 return status;
366 } else if (strcasecmp_m(domain, NAME_BUILTIN) == 0) {
367 *authority_name = NAME_BUILTIN;
368 domain_dn = state->builtin_dn;
369 } else if (strcasecmp_m(domain, state->domain_dns) == 0) {
370 *authority_name = state->domain_name;
371 domain_dn = state->domain_dn;
372 } else if (strcasecmp_m(domain, state->domain_name) == 0) {
373 *authority_name = state->domain_name;
374 domain_dn = state->domain_dn;
375 } else {
376 /* Not local, need to ask winbind in future */
377 return STATUS_SOME_UNMAPPED;
380 ret = gendb_search_dn(state->sam_ldb, mem_ctx, domain_dn, &res, attrs);
381 if (ret == 1) {
382 domain_sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
383 if (domain_sid == NULL) {
384 return NT_STATUS_INVALID_SID;
386 } else {
387 return NT_STATUS_INVALID_SID;
390 if (!*username) {
391 *sid = domain_sid;
392 *rtype = SID_NAME_DOMAIN;
393 *rid = 0xFFFFFFFF;
394 return NT_STATUS_OK;
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));
400 if (ret == -1) {
401 return NT_STATUS_INVALID_SID;
404 for (i=0; i < ret; i++) {
405 *sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
406 if (*sid == NULL) {
407 return NT_STATUS_INVALID_SID;
410 /* Check that this is in the domain */
411 if (!dom_sid_in_domain(domain_sid, *sid)) {
412 continue;
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 return NT_STATUS_OK;
425 /* need to check for an allocated sid */
427 return NT_STATUS_INVALID_SID;
432 add to the lsa_RefDomainList for LookupSids and LookupNames
434 static NTSTATUS dcesrv_lsa_authority_list(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
435 enum lsa_SidType rtype,
436 const char *authority_name,
437 struct dom_sid *sid,
438 struct lsa_RefDomainList *domains,
439 uint32_t *sid_index)
441 struct dom_sid *authority_sid;
442 int i;
444 if (rtype != SID_NAME_DOMAIN) {
445 authority_sid = dom_sid_dup(mem_ctx, sid);
446 if (authority_sid == NULL) {
447 return NT_STATUS_NO_MEMORY;
449 authority_sid->num_auths--;
450 } else {
451 authority_sid = sid;
454 /* see if we've already done this authority name */
455 for (i=0;i<domains->count;i++) {
456 if (strcasecmp_m(authority_name, domains->domains[i].name.string) == 0) {
457 *sid_index = i;
458 return NT_STATUS_OK;
462 domains->domains = talloc_realloc(domains,
463 domains->domains,
464 struct lsa_DomainInfo,
465 domains->count+1);
466 if (domains->domains == NULL) {
467 return NT_STATUS_NO_MEMORY;
469 domains->domains[i].name.string = authority_name;
470 domains->domains[i].sid = authority_sid;
471 domains->count++;
472 domains->max_size = LSA_REF_DOMAIN_LIST_MULTIPLIER * domains->count;
473 *sid_index = i;
475 return NT_STATUS_OK;
479 lookup a name for 1 SID
481 static NTSTATUS dcesrv_lsa_lookup_sid(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
482 struct dom_sid *sid, const char *sid_str,
483 const char **authority_name,
484 const char **name, enum lsa_SidType *rtype)
486 NTSTATUS status;
487 int ret;
488 uint32_t atype;
489 struct ldb_message **res;
490 struct ldb_dn *domain_dn;
491 const char * const attrs[] = { "sAMAccountName", "sAMAccountType", "cn", NULL};
493 status = lookup_well_known_sids(mem_ctx, sid_str, authority_name, name, rtype);
494 if (NT_STATUS_IS_OK(status)) {
495 return status;
498 if (dom_sid_in_domain(state->domain_sid, sid)) {
499 *authority_name = state->domain_name;
500 domain_dn = state->domain_dn;
501 } else if (dom_sid_in_domain(state->builtin_sid, sid)) {
502 *authority_name = NAME_BUILTIN;
503 domain_dn = state->builtin_dn;
504 } else {
505 /* Not well known, our domain or built in */
507 /* In future, we must look at SID histories, and at trusted domains via winbind */
509 return NT_STATUS_NOT_FOUND;
512 ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs,
513 "objectSid=%s", ldap_encode_ndr_dom_sid(mem_ctx, sid));
514 if (ret == 1) {
515 *name = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
516 if (!*name) {
517 *name = ldb_msg_find_attr_as_string(res[0], "cn", NULL);
518 if (!*name) {
519 *name = talloc_strdup(mem_ctx, sid_str);
520 NT_STATUS_HAVE_NO_MEMORY(*name);
524 atype = samdb_result_uint(res[0], "sAMAccountType", 0);
526 *rtype = ds_atype_map(atype);
528 return NT_STATUS_OK;
531 /* need to re-add a check for an allocated sid */
533 return NT_STATUS_NOT_FOUND;
538 lsa_LookupSids2
540 NTSTATUS dcesrv_lsa_LookupSids2(struct dcesrv_call_state *dce_call,
541 TALLOC_CTX *mem_ctx,
542 struct lsa_LookupSids2 *r)
544 struct lsa_policy_state *state;
545 struct lsa_RefDomainList *domains = NULL;
546 int i;
547 NTSTATUS status = NT_STATUS_OK;
549 if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
550 r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
551 return NT_STATUS_INVALID_PARAMETER;
554 *r->out.domains = NULL;
556 /* NOTE: the WSPP test suite tries SIDs with invalid revision numbers,
557 and expects NT_STATUS_INVALID_PARAMETER back - we just treat it as
558 an unknown SID. We could add a SID validator here. (tridge)
559 MS-DTYP 2.4.2
562 status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
563 if (!NT_STATUS_IS_OK(status)) {
564 return status;
567 domains = talloc_zero(r->out.domains, struct lsa_RefDomainList);
568 if (domains == NULL) {
569 return NT_STATUS_NO_MEMORY;
571 *r->out.domains = domains;
573 r->out.names = talloc_zero(mem_ctx, struct lsa_TransNameArray2);
574 if (r->out.names == NULL) {
575 return NT_STATUS_NO_MEMORY;
578 *r->out.count = 0;
580 r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName2,
581 r->in.sids->num_sids);
582 if (r->out.names->names == NULL) {
583 return NT_STATUS_NO_MEMORY;
586 for (i=0;i<r->in.sids->num_sids;i++) {
587 struct dom_sid *sid = r->in.sids->sids[i].sid;
588 char *sid_str = dom_sid_string(mem_ctx, sid);
589 const char *name, *authority_name;
590 enum lsa_SidType rtype;
591 uint32_t sid_index;
592 NTSTATUS status2;
594 r->out.names->count++;
596 r->out.names->names[i].sid_type = SID_NAME_UNKNOWN;
597 r->out.names->names[i].name.string = sid_str;
598 r->out.names->names[i].sid_index = 0xFFFFFFFF;
599 r->out.names->names[i].unknown = 0;
601 if (sid_str == NULL) {
602 r->out.names->names[i].name.string = "(SIDERROR)";
603 status = STATUS_SOME_UNMAPPED;
604 continue;
607 status2 = dcesrv_lsa_lookup_sid(state, mem_ctx, sid, sid_str,
608 &authority_name, &name, &rtype);
609 if (!NT_STATUS_IS_OK(status2)) {
610 status = STATUS_SOME_UNMAPPED;
611 continue;
614 /* set up the authority table */
615 status2 = dcesrv_lsa_authority_list(state, mem_ctx, rtype,
616 authority_name, sid,
617 domains, &sid_index);
618 if (!NT_STATUS_IS_OK(status2)) {
619 continue;
622 r->out.names->names[i].sid_type = rtype;
623 r->out.names->names[i].name.string = name;
624 r->out.names->names[i].sid_index = sid_index;
625 r->out.names->names[i].unknown = 0;
627 (*r->out.count)++;
630 if (*r->out.count == 0) {
631 return NT_STATUS_NONE_MAPPED;
633 if (*r->out.count != r->in.sids->num_sids) {
634 return STATUS_SOME_UNMAPPED;
637 return NT_STATUS_OK;
642 lsa_LookupSids3
644 Identical to LookupSids2, but doesn't take a policy handle
647 NTSTATUS dcesrv_lsa_LookupSids3(struct dcesrv_call_state *dce_call,
648 TALLOC_CTX *mem_ctx,
649 struct lsa_LookupSids3 *r)
651 struct lsa_LookupSids2 r2;
652 struct lsa_OpenPolicy2 pol;
653 NTSTATUS status;
654 struct dcesrv_handle *h;
656 ZERO_STRUCT(r2);
658 /* No policy handle on the wire, so make one up here */
659 r2.in.handle = talloc(mem_ctx, struct policy_handle);
660 if (!r2.in.handle) {
661 return NT_STATUS_NO_MEMORY;
664 pol.out.handle = r2.in.handle;
665 pol.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
666 pol.in.attr = NULL;
667 pol.in.system_name = NULL;
668 status = dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &pol);
669 if (!NT_STATUS_IS_OK(status)) {
670 return status;
673 /* ensure this handle goes away at the end of this call */
674 DCESRV_PULL_HANDLE(h, r2.in.handle, LSA_HANDLE_POLICY);
675 talloc_steal(mem_ctx, h);
677 r2.in.sids = r->in.sids;
678 r2.in.names = r->in.names;
679 r2.in.level = r->in.level;
680 r2.in.count = r->in.count;
681 r2.in.lookup_options = r->in.lookup_options;
682 r2.in.client_revision = r->in.client_revision;
683 r2.out.count = r->out.count;
684 r2.out.names = r->out.names;
685 r2.out.domains = r->out.domains;
687 status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
689 r->out.domains = r2.out.domains;
690 r->out.names = r2.out.names;
691 r->out.count = r2.out.count;
693 return status;
698 lsa_LookupSids
700 NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
701 struct lsa_LookupSids *r)
703 struct lsa_LookupSids2 r2;
704 NTSTATUS status;
705 int i;
707 ZERO_STRUCT(r2);
709 r2.in.handle = r->in.handle;
710 r2.in.sids = r->in.sids;
711 r2.in.names = NULL;
712 r2.in.level = r->in.level;
713 r2.in.count = r->in.count;
714 r2.in.lookup_options = 0;
715 r2.in.client_revision = 0;
716 r2.out.count = r->out.count;
717 r2.out.names = NULL;
718 r2.out.domains = r->out.domains;
720 status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
721 /* we deliberately don't check for error from the above,
722 as even on error we are supposed to return the names */
724 r->out.domains = r2.out.domains;
725 if (!r2.out.names) {
726 r->out.names = NULL;
727 return status;
730 r->out.names = talloc(mem_ctx, struct lsa_TransNameArray);
731 if (r->out.names == NULL) {
732 return NT_STATUS_NO_MEMORY;
734 r->out.names->count = r2.out.names->count;
735 r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName,
736 r->out.names->count);
737 if (r->out.names->names == NULL) {
738 return NT_STATUS_NO_MEMORY;
740 for (i=0;i<r->out.names->count;i++) {
741 r->out.names->names[i].sid_type = r2.out.names->names[i].sid_type;
742 r->out.names->names[i].name.string = r2.out.names->names[i].name.string;
743 r->out.names->names[i].sid_index = r2.out.names->names[i].sid_index;
746 return status;
751 lsa_LookupNames3
753 NTSTATUS dcesrv_lsa_LookupNames3(struct dcesrv_call_state *dce_call,
754 TALLOC_CTX *mem_ctx,
755 struct lsa_LookupNames3 *r)
757 struct lsa_policy_state *policy_state;
758 struct dcesrv_handle *policy_handle;
759 int i;
760 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
761 struct lsa_RefDomainList *domains;
763 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
765 if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
766 r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
767 return NT_STATUS_INVALID_PARAMETER;
770 policy_state = policy_handle->data;
772 *r->out.domains = NULL;
774 domains = talloc_zero(mem_ctx, struct lsa_RefDomainList);
775 if (domains == NULL) {
776 return NT_STATUS_NO_MEMORY;
778 *r->out.domains = domains;
780 r->out.sids = talloc_zero(mem_ctx, struct lsa_TransSidArray3);
781 if (r->out.sids == NULL) {
782 return NT_STATUS_NO_MEMORY;
785 *r->out.count = 0;
787 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid3,
788 r->in.num_names);
789 if (r->out.sids->sids == NULL) {
790 return NT_STATUS_NO_MEMORY;
793 for (i=0;i<r->in.num_names;i++) {
794 const char *name = r->in.names[i].string;
795 const char *authority_name;
796 struct dom_sid *sid;
797 uint32_t sid_index, rid;
798 enum lsa_SidType rtype;
799 NTSTATUS status2;
801 r->out.sids->count++;
803 r->out.sids->sids[i].sid_type = SID_NAME_UNKNOWN;
804 r->out.sids->sids[i].sid = NULL;
805 r->out.sids->sids[i].sid_index = 0xFFFFFFFF;
806 r->out.sids->sids[i].flags = 0;
808 status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, policy_state, mem_ctx, name,
809 &authority_name, &sid, &rtype, &rid);
810 if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) {
811 continue;
814 status2 = dcesrv_lsa_authority_list(policy_state, mem_ctx, rtype, authority_name,
815 sid, domains, &sid_index);
816 if (!NT_STATUS_IS_OK(status2)) {
817 continue;
820 r->out.sids->sids[i].sid_type = rtype;
821 r->out.sids->sids[i].sid = sid;
822 r->out.sids->sids[i].sid_index = sid_index;
823 r->out.sids->sids[i].flags = 0;
825 (*r->out.count)++;
828 if (*r->out.count == 0) {
829 return NT_STATUS_NONE_MAPPED;
831 if (*r->out.count != r->in.num_names) {
832 return STATUS_SOME_UNMAPPED;
835 return NT_STATUS_OK;
839 lsa_LookupNames4
841 Identical to LookupNames3, but doesn't take a policy handle
844 NTSTATUS dcesrv_lsa_LookupNames4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
845 struct lsa_LookupNames4 *r)
847 struct lsa_LookupNames3 r2;
848 struct lsa_OpenPolicy2 pol;
849 NTSTATUS status;
850 struct dcesrv_handle *h;
852 ZERO_STRUCT(r2);
854 /* No policy handle on the wire, so make one up here */
855 r2.in.handle = talloc(mem_ctx, struct policy_handle);
856 if (!r2.in.handle) {
857 return NT_STATUS_NO_MEMORY;
860 pol.out.handle = r2.in.handle;
861 pol.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
862 pol.in.attr = NULL;
863 pol.in.system_name = NULL;
864 status = dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &pol);
865 if (!NT_STATUS_IS_OK(status)) {
866 return status;
869 /* ensure this handle goes away at the end of this call */
870 DCESRV_PULL_HANDLE(h, r2.in.handle, LSA_HANDLE_POLICY);
871 talloc_steal(mem_ctx, h);
873 r2.in.num_names = r->in.num_names;
874 r2.in.names = r->in.names;
875 r2.in.level = r->in.level;
876 r2.in.sids = r->in.sids;
877 r2.in.count = r->in.count;
878 r2.in.lookup_options = r->in.lookup_options;
879 r2.in.client_revision = r->in.client_revision;
880 r2.out.domains = r->out.domains;
881 r2.out.sids = r->out.sids;
882 r2.out.count = r->out.count;
884 status = dcesrv_lsa_LookupNames3(dce_call, mem_ctx, &r2);
886 r->out.domains = r2.out.domains;
887 r->out.sids = r2.out.sids;
888 r->out.count = r2.out.count;
889 return status;
893 lsa_LookupNames2
895 NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call,
896 TALLOC_CTX *mem_ctx,
897 struct lsa_LookupNames2 *r)
899 struct lsa_policy_state *state;
900 struct dcesrv_handle *h;
901 int i;
902 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
903 struct lsa_RefDomainList *domains;
905 *r->out.domains = NULL;
907 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
909 if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
910 r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
911 return NT_STATUS_INVALID_PARAMETER;
914 state = h->data;
916 domains = talloc_zero(mem_ctx, struct lsa_RefDomainList);
917 if (domains == NULL) {
918 return NT_STATUS_NO_MEMORY;
920 *r->out.domains = domains;
922 r->out.sids = talloc_zero(mem_ctx, struct lsa_TransSidArray2);
923 if (r->out.sids == NULL) {
924 return NT_STATUS_NO_MEMORY;
927 *r->out.count = 0;
929 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid2,
930 r->in.num_names);
931 if (r->out.sids->sids == NULL) {
932 return NT_STATUS_NO_MEMORY;
935 for (i=0;i<r->in.num_names;i++) {
936 const char *name = r->in.names[i].string;
937 const char *authority_name;
938 struct dom_sid *sid;
939 uint32_t rtype, sid_index, rid=0;
940 NTSTATUS status2;
942 r->out.sids->count++;
944 r->out.sids->sids[i].sid_type = SID_NAME_UNKNOWN;
945 /* MS-LSAT 3.1.4.7 - rid zero is considered equivalent
946 to sid NULL - so we should return 0 rid for
947 unmapped entries */
948 r->out.sids->sids[i].rid = 0;
949 r->out.sids->sids[i].sid_index = 0xFFFFFFFF;
950 r->out.sids->sids[i].unknown = 0;
952 status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, state, mem_ctx, name,
953 &authority_name, &sid, &rtype, &rid);
954 if (!NT_STATUS_IS_OK(status2)) {
955 continue;
958 status2 = dcesrv_lsa_authority_list(state, mem_ctx, rtype, authority_name,
959 sid, domains, &sid_index);
960 if (!NT_STATUS_IS_OK(status2)) {
961 continue;
964 r->out.sids->sids[i].sid_type = rtype;
965 r->out.sids->sids[i].rid = rid;
966 r->out.sids->sids[i].sid_index = sid_index;
967 r->out.sids->sids[i].unknown = 0;
969 (*r->out.count)++;
972 if (*r->out.count == 0) {
973 return NT_STATUS_NONE_MAPPED;
975 if (*r->out.count != r->in.num_names) {
976 return STATUS_SOME_UNMAPPED;
979 return NT_STATUS_OK;
983 lsa_LookupNames
985 NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
986 struct lsa_LookupNames *r)
988 struct lsa_LookupNames2 r2;
989 NTSTATUS status;
990 int i;
992 ZERO_STRUCT(r2);
994 r2.in.handle = r->in.handle;
995 r2.in.num_names = r->in.num_names;
996 r2.in.names = r->in.names;
997 r2.in.sids = NULL;
998 r2.in.level = r->in.level;
999 r2.in.count = r->in.count;
1000 r2.in.lookup_options = 0;
1001 r2.in.client_revision = 0;
1002 r2.out.count = r->out.count;
1003 r2.out.domains = r->out.domains;
1005 status = dcesrv_lsa_LookupNames2(dce_call, mem_ctx, &r2);
1006 if (r2.out.sids == NULL) {
1007 return status;
1010 r->out.sids = talloc(mem_ctx, struct lsa_TransSidArray);
1011 if (r->out.sids == NULL) {
1012 return NT_STATUS_NO_MEMORY;
1014 r->out.sids->count = r2.out.sids->count;
1015 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid,
1016 r->out.sids->count);
1017 if (r->out.sids->sids == NULL) {
1018 return NT_STATUS_NO_MEMORY;
1020 for (i=0;i<r->out.sids->count;i++) {
1021 r->out.sids->sids[i].sid_type = r2.out.sids->sids[i].sid_type;
1022 r->out.sids->sids[i].rid = r2.out.sids->sids[i].rid;
1023 r->out.sids->sids[i].sid_index = r2.out.sids->sids[i].sid_index;
1026 return status;