testtools: Import new upstream snapshot.
[Samba/gebeck_regimport.git] / source4 / rpc_server / lsa / lsa_lookup.c
blob522d2db6d6e3d0b541705cdeb367696d2ceac806
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"
24 #include "libds/common/flag_mapping.h"
26 static const struct {
27 const char *domain;
28 const char *name;
29 const char *sid;
30 enum lsa_SidType rtype;
31 } well_known[] = {
33 .name = "EVERYONE",
34 .sid = SID_WORLD,
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",
54 .name = "Dialup",
55 .sid = SID_NT_DIALUP,
56 .rtype = SID_NAME_WKN_GRP,
59 .domain = "NT AUTHORITY",
60 .name = "Network",
61 .sid = SID_NT_NETWORK,
62 .rtype = SID_NAME_WKN_GRP,
65 .domain = "NT AUTHORITY",
66 .name = "Batch",
67 .sid = SID_NT_BATCH,
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",
78 .name = "Service",
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",
90 .name = "Proxy",
91 .sid = SID_NT_PROXY,
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",
102 .name = "Self",
103 .sid = SID_NT_SELF,
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",
138 .name = "SYSTEM",
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",
186 .name = "IUSR",
187 .sid = SID_NT_IUSR,
188 .rtype = SID_NAME_WKN_GRP,
191 .sid = NULL,
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)
199 unsigned int i;
200 for (i=0; well_known[i].sid; i++) {
201 if (domain) {
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;
207 return NT_STATUS_OK;
209 } else {
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;
214 return NT_STATUS_OK;
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)
225 unsigned int i;
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;
231 return NT_STATUS_OK;
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,
245 uint32_t *rid)
247 int ret, i;
248 uint32_t atype;
249 struct ldb_message **res;
250 const char * const attrs[] = { "objectSid", "sAMAccountType", NULL};
251 const char *p;
252 const char *domain;
253 const char *username;
254 struct ldb_dn *domain_dn;
255 struct dom_sid *domain_sid;
256 NTSTATUS status;
258 p = strchr_m(name, '\\');
259 if (p != NULL) {
260 domain = talloc_strndup(mem_ctx, name, p-name);
261 if (!domain) {
262 return NT_STATUS_NO_MEMORY;
264 username = p + 1;
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)));
269 return status;
271 } else {
272 domain = NULL;
273 username = name;
276 if (!domain) {
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);
281 return NT_STATUS_OK;
284 if (username == NULL) {
285 *authority_name = NAME_BUILTIN;
286 *sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN);
287 *rtype = SID_NAME_DOMAIN;
288 *rid = 0xFFFFFFFF;
289 return NT_STATUS_OK;
292 if (strcasecmp_m(username, NAME_NT_AUTHORITY) == 0) {
293 *authority_name = NAME_NT_AUTHORITY;
294 *sid = dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY);
295 *rtype = SID_NAME_DOMAIN;
296 dom_sid_split_rid(NULL, *sid, NULL, rid);
297 return NT_STATUS_OK;
299 if (strcasecmp_m(username, NAME_BUILTIN) == 0) {
300 *authority_name = NAME_BUILTIN;
301 *sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN);
302 *rtype = SID_NAME_DOMAIN;
303 *rid = 0xFFFFFFFF;
304 return NT_STATUS_OK;
306 if (strcasecmp_m(username, state->domain_dns) == 0) {
307 *authority_name = state->domain_name;
308 *sid = state->domain_sid;
309 *rtype = SID_NAME_DOMAIN;
310 *rid = 0xFFFFFFFF;
311 return NT_STATUS_OK;
313 if (strcasecmp_m(username, state->domain_name) == 0) {
314 *authority_name = state->domain_name;
315 *sid = state->domain_sid;
316 *rtype = SID_NAME_DOMAIN;
317 *rid = 0xFFFFFFFF;
318 return NT_STATUS_OK;
321 /* Perhaps this is a well known user? */
322 name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_NT_AUTHORITY, username);
323 if (!name) {
324 return NT_STATUS_NO_MEMORY;
326 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
327 if (NT_STATUS_IS_OK(status)) {
328 return status;
331 /* Perhaps this is a BUILTIN user? */
332 name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_BUILTIN, username);
333 if (!name) {
334 return NT_STATUS_NO_MEMORY;
336 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
337 if (NT_STATUS_IS_OK(status)) {
338 return status;
341 /* OK, I give up - perhaps we need to assume the user is in our domain? */
342 name = talloc_asprintf(mem_ctx, "%s\\%s", state->domain_name, username);
343 if (!name) {
344 return NT_STATUS_NO_MEMORY;
346 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
347 if (NT_STATUS_IS_OK(status)) {
348 return status;
351 return STATUS_SOME_UNMAPPED;
352 } else if (strcasecmp_m(domain, NAME_NT_AUTHORITY) == 0) {
353 if (!*username) {
354 *authority_name = NAME_NT_AUTHORITY;
355 *sid = dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY);
356 *rtype = SID_NAME_DOMAIN;
357 dom_sid_split_rid(NULL, *sid, NULL, rid);
358 return NT_STATUS_OK;
361 /* Look up table of well known names */
362 status = lookup_well_known_names(mem_ctx, domain, username, authority_name,
363 sid, rtype);
364 if (NT_STATUS_IS_OK(status)) {
365 dom_sid_split_rid(NULL, *sid, NULL, rid);
367 return status;
368 } else if (strcasecmp_m(domain, NAME_BUILTIN) == 0) {
369 *authority_name = NAME_BUILTIN;
370 domain_dn = state->builtin_dn;
371 } else if (strcasecmp_m(domain, state->domain_dns) == 0) {
372 *authority_name = state->domain_name;
373 domain_dn = state->domain_dn;
374 } else if (strcasecmp_m(domain, state->domain_name) == 0) {
375 *authority_name = state->domain_name;
376 domain_dn = state->domain_dn;
377 } else {
378 /* Not local, need to ask winbind in future */
379 return STATUS_SOME_UNMAPPED;
382 ret = gendb_search_dn(state->sam_ldb, mem_ctx, domain_dn, &res, attrs);
383 if (ret != 1) {
384 return NT_STATUS_INTERNAL_DB_CORRUPTION;
386 domain_sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
387 if (domain_sid == NULL) {
388 return NT_STATUS_INVALID_SID;
391 if (!*username) {
392 *sid = domain_sid;
393 *rtype = SID_NAME_DOMAIN;
394 *rid = 0xFFFFFFFF;
395 return NT_STATUS_OK;
398 ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs,
399 "(&(sAMAccountName=%s)(objectSid=*))",
400 ldb_binary_encode_string(mem_ctx, username));
401 if (ret < 0) {
402 return NT_STATUS_INTERNAL_DB_CORRUPTION;
405 for (i=0; i < ret; i++) {
406 *sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
407 if (*sid == NULL) {
408 return NT_STATUS_INVALID_SID;
411 /* Check that this is in the domain */
412 if (!dom_sid_in_domain(domain_sid, *sid)) {
413 continue;
416 atype = ldb_msg_find_attr_as_uint(res[i], "sAMAccountType", 0);
418 *rtype = ds_atype_map(atype);
419 if (*rtype == SID_NAME_UNKNOWN) {
420 return STATUS_SOME_UNMAPPED;
423 dom_sid_split_rid(NULL, *sid, NULL, rid);
424 return NT_STATUS_OK;
427 /* need to check for an allocated sid */
429 return NT_STATUS_INVALID_SID;
434 add to the lsa_RefDomainList for LookupSids and LookupNames
436 static NTSTATUS dcesrv_lsa_authority_list(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
437 enum lsa_SidType rtype,
438 const char *authority_name,
439 struct dom_sid *sid,
440 struct lsa_RefDomainList *domains,
441 uint32_t *sid_index)
443 struct dom_sid *authority_sid;
444 uint32_t i;
446 if (rtype != SID_NAME_DOMAIN) {
447 authority_sid = dom_sid_dup(mem_ctx, sid);
448 if (authority_sid == NULL) {
449 return NT_STATUS_NO_MEMORY;
451 authority_sid->num_auths--;
452 } else {
453 authority_sid = sid;
456 /* see if we've already done this authority name */
457 for (i=0;i<domains->count;i++) {
458 if (strcasecmp_m(authority_name, domains->domains[i].name.string) == 0) {
459 *sid_index = i;
460 return NT_STATUS_OK;
464 domains->domains = talloc_realloc(domains,
465 domains->domains,
466 struct lsa_DomainInfo,
467 domains->count+1);
468 if (domains->domains == NULL) {
469 return NT_STATUS_NO_MEMORY;
471 domains->domains[i].name.string = authority_name;
472 domains->domains[i].sid = authority_sid;
473 domains->count++;
474 domains->max_size = LSA_REF_DOMAIN_LIST_MULTIPLIER * domains->count;
475 *sid_index = i;
477 return NT_STATUS_OK;
481 lookup a name for 1 SID
483 static NTSTATUS dcesrv_lsa_lookup_sid(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
484 struct dom_sid *sid, const char *sid_str,
485 const char **authority_name,
486 const char **name, enum lsa_SidType *rtype)
488 NTSTATUS status;
489 int ret;
490 uint32_t atype;
491 struct ldb_message **res;
492 struct ldb_dn *domain_dn;
493 const char * const attrs[] = { "sAMAccountName", "sAMAccountType", "cn", NULL};
495 status = lookup_well_known_sids(mem_ctx, sid_str, authority_name, name, rtype);
496 if (NT_STATUS_IS_OK(status)) {
497 return status;
500 if (dom_sid_in_domain(state->domain_sid, sid)) {
501 *authority_name = state->domain_name;
502 domain_dn = state->domain_dn;
503 } else if (dom_sid_in_domain(state->builtin_sid, sid)) {
504 *authority_name = NAME_BUILTIN;
505 domain_dn = state->builtin_dn;
506 } else {
507 /* Not well known, our domain or built in */
509 /* In future, we must look at SID histories, and at trusted domains via winbind */
511 return NT_STATUS_NOT_FOUND;
514 /* need to re-add a check for an allocated sid */
516 ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs,
517 "objectSid=%s", ldap_encode_ndr_dom_sid(mem_ctx, sid));
518 if ((ret < 0) || (ret > 1)) {
519 return NT_STATUS_INTERNAL_DB_CORRUPTION;
521 if (ret == 0) {
522 return NT_STATUS_NOT_FOUND;
525 *name = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
526 if (!*name) {
527 *name = ldb_msg_find_attr_as_string(res[0], "cn", NULL);
528 if (!*name) {
529 *name = talloc_strdup(mem_ctx, sid_str);
530 NT_STATUS_HAVE_NO_MEMORY(*name);
534 atype = ldb_msg_find_attr_as_uint(res[0], "sAMAccountType", 0);
535 *rtype = ds_atype_map(atype);
537 return NT_STATUS_OK;
542 lsa_LookupSids2
544 NTSTATUS dcesrv_lsa_LookupSids2(struct dcesrv_call_state *dce_call,
545 TALLOC_CTX *mem_ctx,
546 struct lsa_LookupSids2 *r)
548 struct lsa_policy_state *state;
549 struct lsa_RefDomainList *domains = NULL;
550 uint32_t i;
551 NTSTATUS status = NT_STATUS_OK;
552 struct dcesrv_handle *h;
554 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
556 if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
557 r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
558 return NT_STATUS_INVALID_PARAMETER;
561 state = h->data;
563 *r->out.domains = NULL;
565 /* NOTE: the WSPP test suite tries SIDs with invalid revision numbers,
566 and expects NT_STATUS_INVALID_PARAMETER back - we just treat it as
567 an unknown SID. We could add a SID validator here. (tridge)
568 MS-DTYP 2.4.2
571 domains = talloc_zero(r->out.domains, struct lsa_RefDomainList);
572 if (domains == NULL) {
573 return NT_STATUS_NO_MEMORY;
575 *r->out.domains = domains;
577 r->out.names = talloc_zero(mem_ctx, struct lsa_TransNameArray2);
578 if (r->out.names == NULL) {
579 return NT_STATUS_NO_MEMORY;
582 *r->out.count = 0;
584 r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName2,
585 r->in.sids->num_sids);
586 if (r->out.names->names == NULL) {
587 return NT_STATUS_NO_MEMORY;
590 for (i=0;i<r->in.sids->num_sids;i++) {
591 struct dom_sid *sid = r->in.sids->sids[i].sid;
592 char *sid_str = dom_sid_string(mem_ctx, sid);
593 const char *name, *authority_name;
594 enum lsa_SidType rtype;
595 uint32_t sid_index;
596 NTSTATUS status2;
598 r->out.names->count++;
600 r->out.names->names[i].sid_type = SID_NAME_UNKNOWN;
601 r->out.names->names[i].name.string = sid_str;
602 r->out.names->names[i].sid_index = 0xFFFFFFFF;
603 r->out.names->names[i].unknown = 0;
605 if (sid_str == NULL) {
606 r->out.names->names[i].name.string = "(SIDERROR)";
607 status = STATUS_SOME_UNMAPPED;
608 continue;
611 status2 = dcesrv_lsa_lookup_sid(state, mem_ctx, sid, sid_str,
612 &authority_name, &name, &rtype);
613 if (!NT_STATUS_IS_OK(status2)) {
614 status = STATUS_SOME_UNMAPPED;
615 continue;
618 /* set up the authority table */
619 status2 = dcesrv_lsa_authority_list(state, mem_ctx, rtype,
620 authority_name, sid,
621 domains, &sid_index);
622 if (!NT_STATUS_IS_OK(status2)) {
623 continue;
626 r->out.names->names[i].sid_type = rtype;
627 r->out.names->names[i].name.string = name;
628 r->out.names->names[i].sid_index = sid_index;
629 r->out.names->names[i].unknown = 0;
631 (*r->out.count)++;
634 if (*r->out.count == 0) {
635 return NT_STATUS_NONE_MAPPED;
637 if (*r->out.count != r->in.sids->num_sids) {
638 return STATUS_SOME_UNMAPPED;
641 return NT_STATUS_OK;
646 lsa_LookupSids3
648 Identical to LookupSids2, but doesn't take a policy handle
651 NTSTATUS dcesrv_lsa_LookupSids3(struct dcesrv_call_state *dce_call,
652 TALLOC_CTX *mem_ctx,
653 struct lsa_LookupSids3 *r)
655 struct lsa_LookupSids2 r2;
656 struct lsa_OpenPolicy2 pol;
657 NTSTATUS status;
658 struct dcesrv_handle *h;
660 ZERO_STRUCT(r2);
662 /* No policy handle on the wire, so make one up here */
663 r2.in.handle = talloc(mem_ctx, struct policy_handle);
664 if (!r2.in.handle) {
665 return NT_STATUS_NO_MEMORY;
668 pol.out.handle = r2.in.handle;
669 pol.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
670 pol.in.attr = NULL;
671 pol.in.system_name = NULL;
672 status = dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &pol);
673 if (!NT_STATUS_IS_OK(status)) {
674 return status;
677 /* ensure this handle goes away at the end of this call */
678 DCESRV_PULL_HANDLE(h, r2.in.handle, LSA_HANDLE_POLICY);
679 talloc_steal(mem_ctx, h);
681 r2.in.sids = r->in.sids;
682 r2.in.names = r->in.names;
683 r2.in.level = r->in.level;
684 r2.in.count = r->in.count;
685 r2.in.lookup_options = r->in.lookup_options;
686 r2.in.client_revision = r->in.client_revision;
687 r2.out.count = r->out.count;
688 r2.out.names = r->out.names;
689 r2.out.domains = r->out.domains;
691 status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
693 r->out.domains = r2.out.domains;
694 r->out.names = r2.out.names;
695 r->out.count = r2.out.count;
697 return status;
702 lsa_LookupSids
704 NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
705 struct lsa_LookupSids *r)
707 struct lsa_LookupSids2 r2;
708 NTSTATUS status;
709 uint32_t i;
711 ZERO_STRUCT(r2);
713 r2.in.handle = r->in.handle;
714 r2.in.sids = r->in.sids;
715 r2.in.names = NULL;
716 r2.in.level = r->in.level;
717 r2.in.count = r->in.count;
718 r2.in.lookup_options = 0;
719 r2.in.client_revision = 0;
720 r2.out.count = r->out.count;
721 r2.out.names = NULL;
722 r2.out.domains = r->out.domains;
724 status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
725 /* we deliberately don't check for error from the above,
726 as even on error we are supposed to return the names */
728 r->out.domains = r2.out.domains;
729 if (!r2.out.names) {
730 r->out.names = NULL;
731 return status;
734 r->out.names = talloc(mem_ctx, struct lsa_TransNameArray);
735 if (r->out.names == NULL) {
736 return NT_STATUS_NO_MEMORY;
738 r->out.names->count = r2.out.names->count;
739 r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName,
740 r->out.names->count);
741 if (r->out.names->names == NULL) {
742 return NT_STATUS_NO_MEMORY;
744 for (i=0;i<r->out.names->count;i++) {
745 r->out.names->names[i].sid_type = r2.out.names->names[i].sid_type;
746 r->out.names->names[i].name.string = r2.out.names->names[i].name.string;
747 r->out.names->names[i].sid_index = r2.out.names->names[i].sid_index;
750 return status;
755 lsa_LookupNames3
757 NTSTATUS dcesrv_lsa_LookupNames3(struct dcesrv_call_state *dce_call,
758 TALLOC_CTX *mem_ctx,
759 struct lsa_LookupNames3 *r)
761 struct lsa_policy_state *policy_state;
762 struct dcesrv_handle *policy_handle;
763 uint32_t i;
764 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
765 struct lsa_RefDomainList *domains;
767 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
769 if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
770 r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
771 return NT_STATUS_INVALID_PARAMETER;
774 policy_state = policy_handle->data;
776 *r->out.domains = NULL;
778 domains = talloc_zero(mem_ctx, struct lsa_RefDomainList);
779 if (domains == NULL) {
780 return NT_STATUS_NO_MEMORY;
782 *r->out.domains = domains;
784 r->out.sids = talloc_zero(mem_ctx, struct lsa_TransSidArray3);
785 if (r->out.sids == NULL) {
786 return NT_STATUS_NO_MEMORY;
789 *r->out.count = 0;
791 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid3,
792 r->in.num_names);
793 if (r->out.sids->sids == NULL) {
794 return NT_STATUS_NO_MEMORY;
797 for (i=0;i<r->in.num_names;i++) {
798 const char *name = r->in.names[i].string;
799 const char *authority_name;
800 struct dom_sid *sid;
801 uint32_t sid_index, rid;
802 enum lsa_SidType rtype;
803 NTSTATUS status2;
805 r->out.sids->count++;
807 r->out.sids->sids[i].sid_type = SID_NAME_UNKNOWN;
808 r->out.sids->sids[i].sid = NULL;
809 r->out.sids->sids[i].sid_index = 0xFFFFFFFF;
810 r->out.sids->sids[i].flags = 0;
812 status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, policy_state, mem_ctx, name,
813 &authority_name, &sid, &rtype, &rid);
814 if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) {
815 continue;
818 status2 = dcesrv_lsa_authority_list(policy_state, mem_ctx, rtype, authority_name,
819 sid, domains, &sid_index);
820 if (!NT_STATUS_IS_OK(status2)) {
821 continue;
824 r->out.sids->sids[i].sid_type = rtype;
825 r->out.sids->sids[i].sid = sid;
826 r->out.sids->sids[i].sid_index = sid_index;
827 r->out.sids->sids[i].flags = 0;
829 (*r->out.count)++;
832 if (*r->out.count == 0) {
833 return NT_STATUS_NONE_MAPPED;
835 if (*r->out.count != r->in.num_names) {
836 return STATUS_SOME_UNMAPPED;
839 return NT_STATUS_OK;
843 lsa_LookupNames4
845 Identical to LookupNames3, but doesn't take a policy handle
848 NTSTATUS dcesrv_lsa_LookupNames4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
849 struct lsa_LookupNames4 *r)
851 struct lsa_LookupNames3 r2;
852 struct lsa_OpenPolicy2 pol;
853 NTSTATUS status;
854 struct dcesrv_handle *h;
856 ZERO_STRUCT(r2);
858 /* No policy handle on the wire, so make one up here */
859 r2.in.handle = talloc(mem_ctx, struct policy_handle);
860 if (!r2.in.handle) {
861 return NT_STATUS_NO_MEMORY;
864 pol.out.handle = r2.in.handle;
865 pol.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
866 pol.in.attr = NULL;
867 pol.in.system_name = NULL;
868 status = dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &pol);
869 if (!NT_STATUS_IS_OK(status)) {
870 return status;
873 /* ensure this handle goes away at the end of this call */
874 DCESRV_PULL_HANDLE(h, r2.in.handle, LSA_HANDLE_POLICY);
875 talloc_steal(mem_ctx, h);
877 r2.in.num_names = r->in.num_names;
878 r2.in.names = r->in.names;
879 r2.in.level = r->in.level;
880 r2.in.sids = r->in.sids;
881 r2.in.count = r->in.count;
882 r2.in.lookup_options = r->in.lookup_options;
883 r2.in.client_revision = r->in.client_revision;
884 r2.out.domains = r->out.domains;
885 r2.out.sids = r->out.sids;
886 r2.out.count = r->out.count;
888 status = dcesrv_lsa_LookupNames3(dce_call, mem_ctx, &r2);
890 r->out.domains = r2.out.domains;
891 r->out.sids = r2.out.sids;
892 r->out.count = r2.out.count;
893 return status;
897 lsa_LookupNames2
899 NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call,
900 TALLOC_CTX *mem_ctx,
901 struct lsa_LookupNames2 *r)
903 struct lsa_policy_state *state;
904 struct dcesrv_handle *h;
905 uint32_t i;
906 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
907 struct lsa_RefDomainList *domains;
909 *r->out.domains = NULL;
911 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
913 if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
914 r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
915 return NT_STATUS_INVALID_PARAMETER;
918 state = h->data;
920 domains = talloc_zero(mem_ctx, struct lsa_RefDomainList);
921 if (domains == NULL) {
922 return NT_STATUS_NO_MEMORY;
924 *r->out.domains = domains;
926 r->out.sids = talloc_zero(mem_ctx, struct lsa_TransSidArray2);
927 if (r->out.sids == NULL) {
928 return NT_STATUS_NO_MEMORY;
931 *r->out.count = 0;
933 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid2,
934 r->in.num_names);
935 if (r->out.sids->sids == NULL) {
936 return NT_STATUS_NO_MEMORY;
939 for (i=0;i<r->in.num_names;i++) {
940 const char *name = r->in.names[i].string;
941 const char *authority_name;
942 struct dom_sid *sid;
943 uint32_t sid_index, rid=0;
944 enum lsa_SidType rtype;
945 NTSTATUS status2;
947 r->out.sids->count++;
949 r->out.sids->sids[i].sid_type = SID_NAME_UNKNOWN;
950 /* MS-LSAT 3.1.4.7 - rid zero is considered equivalent
951 to sid NULL - so we should return 0 rid for
952 unmapped entries */
953 r->out.sids->sids[i].rid = 0;
954 r->out.sids->sids[i].sid_index = 0xFFFFFFFF;
955 r->out.sids->sids[i].unknown = 0;
957 status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, state, mem_ctx, name,
958 &authority_name, &sid, &rtype, &rid);
959 if (!NT_STATUS_IS_OK(status2)) {
960 continue;
963 status2 = dcesrv_lsa_authority_list(state, mem_ctx, rtype, authority_name,
964 sid, domains, &sid_index);
965 if (!NT_STATUS_IS_OK(status2)) {
966 continue;
969 r->out.sids->sids[i].sid_type = rtype;
970 r->out.sids->sids[i].rid = rid;
971 r->out.sids->sids[i].sid_index = sid_index;
972 r->out.sids->sids[i].unknown = 0;
974 (*r->out.count)++;
977 if (*r->out.count == 0) {
978 return NT_STATUS_NONE_MAPPED;
980 if (*r->out.count != r->in.num_names) {
981 return STATUS_SOME_UNMAPPED;
984 return NT_STATUS_OK;
988 lsa_LookupNames
990 NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
991 struct lsa_LookupNames *r)
993 struct lsa_LookupNames2 r2;
994 NTSTATUS status;
995 uint32_t i;
997 ZERO_STRUCT(r2);
999 r2.in.handle = r->in.handle;
1000 r2.in.num_names = r->in.num_names;
1001 r2.in.names = r->in.names;
1002 r2.in.sids = NULL;
1003 r2.in.level = r->in.level;
1004 r2.in.count = r->in.count;
1005 r2.in.lookup_options = 0;
1006 r2.in.client_revision = 0;
1007 r2.out.count = r->out.count;
1008 r2.out.domains = r->out.domains;
1010 status = dcesrv_lsa_LookupNames2(dce_call, mem_ctx, &r2);
1011 if (r2.out.sids == NULL) {
1012 return status;
1015 r->out.sids = talloc(mem_ctx, struct lsa_TransSidArray);
1016 if (r->out.sids == NULL) {
1017 return NT_STATUS_NO_MEMORY;
1019 r->out.sids->count = r2.out.sids->count;
1020 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid,
1021 r->out.sids->count);
1022 if (r->out.sids->sids == NULL) {
1023 return NT_STATUS_NO_MEMORY;
1025 for (i=0;i<r->out.sids->count;i++) {
1026 r->out.sids->sids[i].sid_type = r2.out.sids->sids[i].sid_type;
1027 r->out.sids->sids[i].rid = r2.out.sids->sids[i].rid;
1028 r->out.sids->sids[i].sid_index = r2.out.sids->sids[i].sid_index;
1031 return status;