s4:rpc_server/lsa: prepare dcesrv_lsa_LookupSids* for async processing
[Samba.git] / source4 / rpc_server / lsa / lsa_lookup.c
blob62d29d3173ebfd28487de4fabb27e0bbdad1f43c
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,
267 state->sam_ldb,
268 DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
269 name, &domain, &username);
270 if (!NT_STATUS_IS_OK(status)) {
271 DEBUG(3, ("Failed to crack name %s into an NT4 name: %s\n", name, nt_errstr(status)));
272 return status;
274 } else {
275 domain = NULL;
276 username = name;
279 if (!domain) {
280 /* Look up table of well known names */
281 status = lookup_well_known_names(mem_ctx, NULL, username, authority_name, sid, rtype);
282 if (NT_STATUS_IS_OK(status)) {
283 dom_sid_split_rid(NULL, *sid, NULL, rid);
284 return NT_STATUS_OK;
287 if (username == NULL) {
288 *authority_name = NAME_BUILTIN;
289 *sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN);
290 if (*sid == NULL) {
291 return NT_STATUS_NO_MEMORY;
293 *rtype = SID_NAME_DOMAIN;
294 *rid = 0xFFFFFFFF;
295 return NT_STATUS_OK;
298 if (strcasecmp_m(username, NAME_NT_AUTHORITY) == 0) {
299 *authority_name = NAME_NT_AUTHORITY;
300 *sid = dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY);
301 if (*sid == NULL) {
302 return NT_STATUS_NO_MEMORY;
304 *rtype = SID_NAME_DOMAIN;
305 dom_sid_split_rid(NULL, *sid, NULL, rid);
306 return NT_STATUS_OK;
308 if (strcasecmp_m(username, NAME_BUILTIN) == 0) {
309 *authority_name = NAME_BUILTIN;
310 *sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN);
311 if (*sid == NULL) {
312 return NT_STATUS_NO_MEMORY;
314 *rtype = SID_NAME_DOMAIN;
315 *rid = 0xFFFFFFFF;
316 return NT_STATUS_OK;
318 if (strcasecmp_m(username, state->domain_dns) == 0) {
319 *authority_name = talloc_strdup(mem_ctx,
320 state->domain_name);
321 if (*authority_name == NULL) {
322 return NT_STATUS_NO_MEMORY;
324 *sid = dom_sid_dup(mem_ctx, state->domain_sid);
325 if (*sid == NULL) {
326 return NT_STATUS_NO_MEMORY;
328 *rtype = SID_NAME_DOMAIN;
329 *rid = 0xFFFFFFFF;
330 return NT_STATUS_OK;
332 if (strcasecmp_m(username, state->domain_name) == 0) {
333 *authority_name = talloc_strdup(mem_ctx,
334 state->domain_name);
335 if (*authority_name == NULL) {
336 return NT_STATUS_NO_MEMORY;
338 *sid = dom_sid_dup(mem_ctx, state->domain_sid);
339 if (*sid == NULL) {
340 return NT_STATUS_NO_MEMORY;
342 *rtype = SID_NAME_DOMAIN;
343 *rid = 0xFFFFFFFF;
344 return NT_STATUS_OK;
347 /* Perhaps this is a well known user? */
348 name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_NT_AUTHORITY, username);
349 if (!name) {
350 return NT_STATUS_NO_MEMORY;
352 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
353 if (NT_STATUS_IS_OK(status)) {
354 return status;
357 /* Perhaps this is a BUILTIN user? */
358 name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_BUILTIN, username);
359 if (!name) {
360 return NT_STATUS_NO_MEMORY;
362 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
363 if (NT_STATUS_IS_OK(status)) {
364 return status;
367 /* OK, I give up - perhaps we need to assume the user is in our domain? */
368 name = talloc_asprintf(mem_ctx, "%s\\%s", state->domain_name, username);
369 if (!name) {
370 return NT_STATUS_NO_MEMORY;
372 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
373 if (NT_STATUS_IS_OK(status)) {
374 return status;
377 return STATUS_SOME_UNMAPPED;
378 } else if (strcasecmp_m(domain, NAME_NT_AUTHORITY) == 0) {
379 if (!*username) {
380 *authority_name = NAME_NT_AUTHORITY;
381 *sid = dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY);
382 if (*sid == NULL) {
383 return NT_STATUS_NO_MEMORY;
385 *rtype = SID_NAME_DOMAIN;
386 dom_sid_split_rid(NULL, *sid, NULL, rid);
387 return NT_STATUS_OK;
390 /* Look up table of well known names */
391 status = lookup_well_known_names(mem_ctx, domain, username, authority_name,
392 sid, rtype);
393 if (NT_STATUS_IS_OK(status)) {
394 dom_sid_split_rid(NULL, *sid, NULL, rid);
396 return status;
397 } else if (strcasecmp_m(domain, NAME_BUILTIN) == 0) {
398 *authority_name = NAME_BUILTIN;
399 domain_dn = state->builtin_dn;
400 } else if (strcasecmp_m(domain, state->domain_dns) == 0) {
401 *authority_name = talloc_strdup(mem_ctx,
402 state->domain_name);
403 if (*authority_name == NULL) {
404 return NT_STATUS_NO_MEMORY;
406 domain_dn = state->domain_dn;
407 } else if (strcasecmp_m(domain, state->domain_name) == 0) {
408 *authority_name = talloc_strdup(mem_ctx,
409 state->domain_name);
410 if (*authority_name == NULL) {
411 return NT_STATUS_NO_MEMORY;
413 domain_dn = state->domain_dn;
414 } else {
415 /* Not local, need to ask winbind in future */
416 return STATUS_SOME_UNMAPPED;
419 ret = gendb_search_dn(state->sam_ldb, mem_ctx, domain_dn, &res, attrs);
420 if (ret != 1) {
421 return NT_STATUS_INTERNAL_DB_CORRUPTION;
423 domain_sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
424 if (domain_sid == NULL) {
425 return NT_STATUS_INVALID_SID;
428 if (!*username) {
429 *sid = domain_sid;
430 *rtype = SID_NAME_DOMAIN;
431 *rid = 0xFFFFFFFF;
432 return NT_STATUS_OK;
435 ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs,
436 "(&(sAMAccountName=%s)(objectSid=*))",
437 ldb_binary_encode_string(mem_ctx, username));
438 if (ret < 0) {
439 return NT_STATUS_INTERNAL_DB_CORRUPTION;
442 for (i=0; i < ret; i++) {
443 *sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
444 if (*sid == NULL) {
445 return NT_STATUS_INVALID_SID;
448 /* Check that this is in the domain */
449 if (!dom_sid_in_domain(domain_sid, *sid)) {
450 continue;
453 atype = ldb_msg_find_attr_as_uint(res[i], "sAMAccountType", 0);
455 *rtype = ds_atype_map(atype);
456 if (*rtype == SID_NAME_UNKNOWN) {
457 return STATUS_SOME_UNMAPPED;
460 dom_sid_split_rid(NULL, *sid, NULL, rid);
461 return NT_STATUS_OK;
464 /* need to check for an allocated sid */
466 return NT_STATUS_INVALID_SID;
471 add to the lsa_RefDomainList for LookupSids and LookupNames
473 static NTSTATUS dcesrv_lsa_authority_list(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
474 enum lsa_SidType rtype,
475 const char *authority_name,
476 struct dom_sid *sid,
477 struct lsa_RefDomainList *domains,
478 uint32_t *sid_index)
480 struct dom_sid *authority_sid;
481 uint32_t i;
483 if (rtype != SID_NAME_DOMAIN) {
484 authority_sid = dom_sid_dup(mem_ctx, sid);
485 if (authority_sid == NULL) {
486 return NT_STATUS_NO_MEMORY;
488 authority_sid->num_auths--;
489 } else {
490 authority_sid = sid;
493 /* see if we've already done this authority name */
494 for (i=0;i<domains->count;i++) {
495 if (strcasecmp_m(authority_name, domains->domains[i].name.string) == 0) {
496 *sid_index = i;
497 return NT_STATUS_OK;
501 domains->domains = talloc_realloc(domains,
502 domains->domains,
503 struct lsa_DomainInfo,
504 domains->count+1);
505 if (domains->domains == NULL) {
506 return NT_STATUS_NO_MEMORY;
508 domains->domains[i].name.string = authority_name;
509 domains->domains[i].sid = authority_sid;
510 domains->count++;
511 domains->max_size = LSA_REF_DOMAIN_LIST_MULTIPLIER * domains->count;
512 *sid_index = i;
514 return NT_STATUS_OK;
518 lookup a name for 1 SID
520 static NTSTATUS dcesrv_lsa_lookup_sid(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
521 struct dom_sid *sid, const char *sid_str,
522 const char **authority_name,
523 const char **name, enum lsa_SidType *rtype)
525 NTSTATUS status;
526 int ret;
527 uint32_t atype;
528 struct ldb_message **res;
529 struct ldb_dn *domain_dn;
530 const char * const attrs[] = { "sAMAccountName", "sAMAccountType", "cn", NULL};
532 status = lookup_well_known_sids(mem_ctx, sid_str, authority_name, name, rtype);
533 if (NT_STATUS_IS_OK(status)) {
534 return status;
537 if (dom_sid_equal(state->domain_sid, sid)) {
538 *authority_name = talloc_strdup(mem_ctx, state->domain_name);
539 if (*authority_name == NULL) {
540 return NT_STATUS_NO_MEMORY;
542 *name = NULL;
543 *rtype = SID_NAME_DOMAIN;
544 return NT_STATUS_OK;
547 if (dom_sid_in_domain(state->domain_sid, sid)) {
548 *authority_name = talloc_strdup(mem_ctx, state->domain_name);
549 if (*authority_name == NULL) {
550 return NT_STATUS_NO_MEMORY;
552 domain_dn = state->domain_dn;
553 } else if (dom_sid_in_domain(state->builtin_sid, sid)) {
554 *authority_name = NAME_BUILTIN;
555 domain_dn = state->builtin_dn;
556 } else {
557 /* Not well known, our domain or built in */
559 /* In future, we must look at SID histories, and at trusted domains via winbind */
561 return NT_STATUS_NOT_FOUND;
564 /* need to re-add a check for an allocated sid */
566 ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs,
567 "objectSid=%s", ldap_encode_ndr_dom_sid(mem_ctx, sid));
568 if ((ret < 0) || (ret > 1)) {
569 return NT_STATUS_INTERNAL_DB_CORRUPTION;
571 if (ret == 0) {
572 return NT_STATUS_NOT_FOUND;
575 *name = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
576 if (!*name) {
577 *name = ldb_msg_find_attr_as_string(res[0], "cn", NULL);
578 if (!*name) {
579 *name = talloc_strdup(mem_ctx, sid_str);
580 NT_STATUS_HAVE_NO_MEMORY(*name);
584 atype = ldb_msg_find_attr_as_uint(res[0], "sAMAccountType", 0);
585 *rtype = ds_atype_map(atype);
587 return NT_STATUS_OK;
590 struct dcesrv_lsa_LookupSids_base_state {
591 struct dcesrv_call_state *dce_call;
593 TALLOC_CTX *mem_ctx;
595 struct lsa_policy_state *policy_state;
597 struct lsa_LookupSids3 r;
599 struct {
600 struct lsa_LookupSids *l;
601 struct lsa_LookupSids2 *l2;
602 struct lsa_LookupSids3 *l3;
603 } _r;
606 static NTSTATUS dcesrv_lsa_LookupSids_base_call(struct dcesrv_lsa_LookupSids_base_state *state)
608 struct lsa_policy_state *policy_state = state->policy_state;
609 TALLOC_CTX *mem_ctx = state->mem_ctx;
610 struct lsa_LookupSids3 *r = &state->r;
611 struct lsa_RefDomainList *domains = NULL;
612 uint32_t i;
614 *r->out.domains = NULL;
615 r->out.names->count = 0;
616 r->out.names->names = NULL;
617 *r->out.count = 0;
619 if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
620 r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
621 return NT_STATUS_INVALID_PARAMETER;
624 /* NOTE: the WSPP test suite tries SIDs with invalid revision numbers,
625 and expects NT_STATUS_INVALID_PARAMETER back - we just treat it as
626 an unknown SID. We could add a SID validator here. (tridge)
627 MS-DTYP 2.4.2
630 domains = talloc_zero(r->out.domains, struct lsa_RefDomainList);
631 if (domains == NULL) {
632 return NT_STATUS_NO_MEMORY;
634 *r->out.domains = domains;
636 r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName2,
637 r->in.sids->num_sids);
638 if (r->out.names->names == NULL) {
639 return NT_STATUS_NO_MEMORY;
642 for (i=0;i<r->in.sids->num_sids;i++) {
643 struct dom_sid *sid = r->in.sids->sids[i].sid;
644 char *sid_str = dom_sid_string(mem_ctx, sid);
645 const char *name, *authority_name;
646 enum lsa_SidType rtype;
647 uint32_t sid_index;
648 NTSTATUS status2;
650 r->out.names->count++;
652 r->out.names->names[i].sid_type = SID_NAME_UNKNOWN;
653 r->out.names->names[i].name.string = sid_str;
654 r->out.names->names[i].sid_index = 0xFFFFFFFF;
655 r->out.names->names[i].unknown = 0;
657 if (sid_str == NULL) {
658 r->out.names->names[i].name.string = "(SIDERROR)";
659 continue;
662 status2 = dcesrv_lsa_lookup_sid(policy_state, mem_ctx, sid, sid_str,
663 &authority_name, &name, &rtype);
664 if (!NT_STATUS_IS_OK(status2)) {
665 continue;
668 /* set up the authority table */
669 status2 = dcesrv_lsa_authority_list(policy_state, mem_ctx, rtype,
670 authority_name, sid,
671 domains, &sid_index);
672 if (!NT_STATUS_IS_OK(status2)) {
673 continue;
676 r->out.names->names[i].sid_type = rtype;
677 r->out.names->names[i].name.string = name;
678 r->out.names->names[i].sid_index = sid_index;
679 r->out.names->names[i].unknown = 0;
681 (*r->out.count)++;
684 if (*r->out.count == 0) {
685 return NT_STATUS_NONE_MAPPED;
687 if (*r->out.count != r->in.sids->num_sids) {
688 return STATUS_SOME_UNMAPPED;
691 return NT_STATUS_OK;
694 static void dcesrv_lsa_LookupSids_base_map(
695 struct dcesrv_lsa_LookupSids_base_state *state)
697 if (state->_r.l3 != NULL) {
698 struct lsa_LookupSids3 *r = state->_r.l3;
700 r->out.result = state->r.out.result;
701 return;
704 if (state->_r.l2 != NULL) {
705 struct lsa_LookupSids2 *r = state->_r.l2;
707 r->out.result = state->r.out.result;
708 return;
711 if (state->_r.l != NULL) {
712 struct lsa_LookupSids *r = state->_r.l;
713 uint32_t i;
715 r->out.result = state->r.out.result;
717 SMB_ASSERT(state->r.out.names->count <= r->in.sids->num_sids);
718 for (i = 0; i < state->r.out.names->count; i++) {
719 struct lsa_TranslatedName2 *n2 =
720 &state->r.out.names->names[i];
721 struct lsa_TranslatedName *n =
722 &r->out.names->names[i];
724 n->sid_type = n2->sid_type;
725 n->name = n2->name;
726 n->sid_index = n2->sid_index;
728 r->out.names->count = state->r.out.names->count;
729 return;
734 lsa_LookupSids2
736 NTSTATUS dcesrv_lsa_LookupSids2(struct dcesrv_call_state *dce_call,
737 TALLOC_CTX *mem_ctx,
738 struct lsa_LookupSids2 *r)
740 enum dcerpc_transport_t transport =
741 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
742 struct dcesrv_lsa_LookupSids_base_state *state = NULL;
743 struct dcesrv_handle *policy_handle = NULL;
744 NTSTATUS status;
746 if (transport != NCACN_NP && transport != NCALRPC) {
747 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
750 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
752 *r->out.domains = NULL;
753 r->out.names->count = 0;
754 r->out.names->names = NULL;
755 *r->out.count = 0;
757 state = talloc_zero(mem_ctx, struct dcesrv_lsa_LookupSids_base_state);
758 if (state == NULL) {
759 return NT_STATUS_NO_MEMORY;
762 state->dce_call = dce_call;
763 state->mem_ctx = mem_ctx;
765 state->policy_state = policy_handle->data;
767 state->r.in.sids = r->in.sids;
768 state->r.in.level = r->in.level;
769 state->r.in.lookup_options = r->in.lookup_options;
770 state->r.in.client_revision = r->in.client_revision;
771 state->r.in.names = r->in.names;
772 state->r.in.count = r->in.count;
773 state->r.out.domains = r->out.domains;
774 state->r.out.names = r->out.names;
775 state->r.out.count = r->out.count;
777 state->_r.l2 = r;
779 status = dcesrv_lsa_LookupSids_base_call(state);
781 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
782 return status;
785 state->r.out.result = status;
786 dcesrv_lsa_LookupSids_base_map(state);
787 TALLOC_FREE(state);
788 return status;
793 lsa_LookupSids3
795 Identical to LookupSids2, but doesn't take a policy handle
798 NTSTATUS dcesrv_lsa_LookupSids3(struct dcesrv_call_state *dce_call,
799 TALLOC_CTX *mem_ctx,
800 struct lsa_LookupSids3 *r)
802 enum dcerpc_transport_t transport =
803 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
804 const struct dcesrv_auth *auth = &dce_call->conn->auth_state;
805 struct dcesrv_lsa_LookupSids_base_state *state = NULL;
806 NTSTATUS status;
808 if (transport != NCACN_IP_TCP) {
809 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
813 * We don't have policy handles on this call. So this must be restricted
814 * to crypto connections only.
816 if (auth->auth_type != DCERPC_AUTH_TYPE_SCHANNEL ||
817 auth->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
818 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
821 *r->out.domains = NULL;
822 r->out.names->count = 0;
823 r->out.names->names = NULL;
824 *r->out.count = 0;
826 state = talloc_zero(mem_ctx, struct dcesrv_lsa_LookupSids_base_state);
827 if (state == NULL) {
828 return NT_STATUS_NO_MEMORY;
831 state->dce_call = dce_call;
832 state->mem_ctx = mem_ctx;
834 status = dcesrv_lsa_get_policy_state(state->dce_call, mem_ctx,
835 0, /* we skip access checks */
836 &state->policy_state);
837 if (!NT_STATUS_IS_OK(status)) {
838 return status;
841 state->r.in.sids = r->in.sids;
842 state->r.in.level = r->in.level;
843 state->r.in.lookup_options = r->in.lookup_options;
844 state->r.in.client_revision = r->in.client_revision;
845 state->r.in.names = r->in.names;
846 state->r.in.count = r->in.count;
847 state->r.out.domains = r->out.domains;
848 state->r.out.names = r->out.names;
849 state->r.out.count = r->out.count;
851 state->_r.l3 = r;
853 status = dcesrv_lsa_LookupSids_base_call(state);
855 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
856 return status;
859 state->r.out.result = status;
860 dcesrv_lsa_LookupSids_base_map(state);
861 TALLOC_FREE(state);
862 return status;
867 lsa_LookupSids
869 NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
870 struct lsa_LookupSids *r)
872 enum dcerpc_transport_t transport =
873 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
874 struct dcesrv_lsa_LookupSids_base_state *state = NULL;
875 struct dcesrv_handle *policy_handle = NULL;
876 NTSTATUS status;
878 if (transport != NCACN_NP && transport != NCALRPC) {
879 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
882 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
884 *r->out.domains = NULL;
885 r->out.names->count = 0;
886 r->out.names->names = NULL;
887 *r->out.count = 0;
889 r->out.names->names = talloc_zero_array(r->out.names,
890 struct lsa_TranslatedName,
891 r->in.sids->num_sids);
892 if (r->out.names->names == NULL) {
893 return NT_STATUS_NO_MEMORY;
896 state = talloc_zero(mem_ctx, struct dcesrv_lsa_LookupSids_base_state);
897 if (state == NULL) {
898 return NT_STATUS_NO_MEMORY;
901 state->dce_call = dce_call;
902 state->mem_ctx = mem_ctx;
904 state->policy_state = policy_handle->data;
906 state->r.in.sids = r->in.sids;
907 state->r.in.level = r->in.level;
908 state->r.in.lookup_options = LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES;
909 state->r.in.client_revision = LSA_CLIENT_REVISION_1;
910 state->r.in.names = talloc_zero(state, struct lsa_TransNameArray2);
911 if (state->r.in.names == NULL) {
912 return NT_STATUS_NO_MEMORY;
914 state->r.in.count = r->in.count;
915 state->r.out.domains = r->out.domains;
916 state->r.out.names = talloc_zero(state, struct lsa_TransNameArray2);
917 if (state->r.out.names == NULL) {
918 return NT_STATUS_NO_MEMORY;
920 state->r.out.count = r->out.count;
922 state->_r.l = r;
924 status = dcesrv_lsa_LookupSids_base_call(state);
926 if (dce_call->state_flags & DCESRV_CALL_STATE_FLAG_ASYNC) {
927 return status;
930 state->r.out.result = status;
931 dcesrv_lsa_LookupSids_base_map(state);
932 TALLOC_FREE(state);
933 return status;
936 static NTSTATUS dcesrv_lsa_LookupNames_common(struct dcesrv_call_state *dce_call,
937 TALLOC_CTX *mem_ctx,
938 struct lsa_policy_state *policy_state,
939 struct lsa_LookupNames3 *r)
941 struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
942 struct lsa_RefDomainList *domains;
943 uint32_t i;
945 *r->out.domains = NULL;
946 r->out.sids->count = 0;
947 r->out.sids->sids = NULL;
948 *r->out.count = 0;
950 if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
951 r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
952 return NT_STATUS_INVALID_PARAMETER;
955 domains = talloc_zero(r->out.domains, struct lsa_RefDomainList);
956 if (domains == NULL) {
957 return NT_STATUS_NO_MEMORY;
959 *r->out.domains = domains;
961 r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid3,
962 r->in.num_names);
963 if (r->out.sids->sids == NULL) {
964 return NT_STATUS_NO_MEMORY;
967 for (i=0;i<r->in.num_names;i++) {
968 const char *name = r->in.names[i].string;
969 const char *authority_name;
970 struct dom_sid *sid;
971 uint32_t sid_index, rid;
972 enum lsa_SidType rtype;
973 NTSTATUS status2;
975 r->out.sids->count++;
977 r->out.sids->sids[i].sid_type = SID_NAME_UNKNOWN;
978 r->out.sids->sids[i].sid = NULL;
979 r->out.sids->sids[i].sid_index = 0xFFFFFFFF;
980 r->out.sids->sids[i].flags = 0;
982 status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, policy_state, mem_ctx, name,
983 &authority_name, &sid, &rtype, &rid);
984 if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) {
985 continue;
988 status2 = dcesrv_lsa_authority_list(policy_state, mem_ctx, rtype, authority_name,
989 sid, domains, &sid_index);
990 if (!NT_STATUS_IS_OK(status2)) {
991 continue;
994 r->out.sids->sids[i].sid_type = rtype;
995 r->out.sids->sids[i].sid = sid;
996 r->out.sids->sids[i].sid_index = sid_index;
997 r->out.sids->sids[i].flags = 0;
999 (*r->out.count)++;
1002 if (*r->out.count == 0) {
1003 return NT_STATUS_NONE_MAPPED;
1005 if (*r->out.count != r->in.num_names) {
1006 return STATUS_SOME_UNMAPPED;
1009 return NT_STATUS_OK;
1013 lsa_LookupNames3
1015 NTSTATUS dcesrv_lsa_LookupNames3(struct dcesrv_call_state *dce_call,
1016 TALLOC_CTX *mem_ctx,
1017 struct lsa_LookupNames3 *r)
1019 enum dcerpc_transport_t transport =
1020 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
1021 struct lsa_policy_state *policy_state;
1022 struct dcesrv_handle *policy_handle;
1024 if (transport != NCACN_NP && transport != NCALRPC) {
1025 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
1028 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1030 policy_state = policy_handle->data;
1032 return dcesrv_lsa_LookupNames_common(dce_call,
1033 mem_ctx,
1034 policy_state,
1039 lsa_LookupNames4
1041 Identical to LookupNames3, but doesn't take a policy handle
1044 NTSTATUS dcesrv_lsa_LookupNames4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1045 struct lsa_LookupNames4 *r)
1047 enum dcerpc_transport_t transport =
1048 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
1049 const struct dcesrv_auth *auth = &dce_call->conn->auth_state;
1050 struct lsa_policy_state *policy_state;
1051 struct lsa_LookupNames3 q;
1052 NTSTATUS status;
1054 if (transport != NCACN_IP_TCP) {
1055 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
1059 * We don't have policy handles on this call. So this must be restricted
1060 * to crypto connections only.
1062 if (auth->auth_type != DCERPC_AUTH_TYPE_SCHANNEL ||
1063 auth->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
1064 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
1067 *r->out.domains = NULL;
1068 r->out.sids->count = 0;
1069 r->out.sids->sids = NULL;
1070 *r->out.count = 0;
1072 status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx,
1073 0, /* we skip access checks */
1074 &policy_state);
1075 if (!NT_STATUS_IS_OK(status)) {
1076 return status;
1079 ZERO_STRUCT(q);
1081 q.in.handle = NULL;
1082 q.in.num_names = r->in.num_names;
1083 q.in.names = r->in.names;
1084 q.in.level = r->in.level;
1085 q.in.sids = r->in.sids;
1086 q.in.count = r->in.count;
1087 q.in.lookup_options = r->in.lookup_options;
1088 q.in.client_revision = r->in.client_revision;
1090 q.out.count = r->out.count;
1091 q.out.sids = r->out.sids;
1092 q.out.domains = r->out.domains;
1094 status = dcesrv_lsa_LookupNames_common(dce_call,
1095 mem_ctx,
1096 policy_state,
1097 &q);
1099 talloc_free(policy_state);
1101 r->out.count = q.out.count;
1102 r->out.sids = q.out.sids;
1103 r->out.domains = q.out.domains;
1105 return status;
1109 lsa_LookupNames2
1111 NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call,
1112 TALLOC_CTX *mem_ctx,
1113 struct lsa_LookupNames2 *r)
1115 enum dcerpc_transport_t transport =
1116 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
1117 struct lsa_policy_state *policy_state = NULL;
1118 struct dcesrv_handle *policy_handle = NULL;
1119 struct lsa_LookupNames3 r2;
1120 NTSTATUS status;
1121 uint32_t i;
1123 if (transport != NCACN_NP && transport != NCALRPC) {
1124 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
1127 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1129 policy_state = policy_handle->data;
1131 *r->out.domains = NULL;
1132 r->out.sids->count = 0;
1133 r->out.sids->sids = NULL;
1134 *r->out.count = 0;
1136 r->out.sids->sids = talloc_zero_array(r->out.sids,
1137 struct lsa_TranslatedSid2,
1138 r->in.num_names);
1139 if (r->out.sids->sids == NULL) {
1140 return NT_STATUS_NO_MEMORY;
1143 ZERO_STRUCT(r2);
1145 r2.in.handle = r->in.handle;
1146 r2.in.num_names = r->in.num_names;
1147 r2.in.names = r->in.names;
1148 r2.in.sids = talloc_zero(mem_ctx, struct lsa_TransSidArray3);
1149 if (r2.in.sids == NULL) {
1150 return NT_STATUS_NO_MEMORY;
1152 r2.in.level = r->in.level;
1153 r2.in.count = r->in.count;
1155 * MS-LSAT 3.1.4.7:
1157 * The LookupOptions and ClientRevision parameters MUST be ignored.
1158 * Message processing MUST happen as if LookupOptions is set to
1159 * 0x00000000 and ClientRevision is set to 0x00000002.
1161 r2.in.lookup_options = LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES;
1162 r2.in.client_revision = LSA_CLIENT_REVISION_2;
1163 r2.out.count = r->out.count;
1164 r2.out.sids = talloc_zero(mem_ctx, struct lsa_TransSidArray3);
1165 if (r2.out.sids == NULL) {
1166 return NT_STATUS_NO_MEMORY;
1168 r2.out.domains = r->out.domains;
1170 status = dcesrv_lsa_LookupNames_common(dce_call,
1171 mem_ctx,
1172 policy_state,
1173 &r2);
1175 SMB_ASSERT(r2.out.sids->count <= r->in.num_names);
1176 for (i=0;i<r2.out.sids->count;i++) {
1177 struct lsa_TranslatedSid3 *s3 =
1178 &r2.out.sids->sids[i];
1179 struct lsa_TranslatedSid2 *s2 =
1180 &r->out.sids->sids[i];
1182 s2->sid_type = s3->sid_type;
1183 if (s3->sid_type == SID_NAME_DOMAIN) {
1184 s2->rid = UINT32_MAX;
1185 } else if (s3->flags & 0x00000004) {
1186 s2->rid = UINT32_MAX;
1187 } else if (s3->sid == NULL) {
1189 * MS-LSAT 3.1.4.7 - rid zero is considered
1190 * equivalent to sid NULL - so we should return
1191 * 0 rid for unmapped entries
1193 s2->rid = 0;
1194 } else {
1195 s2->rid = 0;
1196 dom_sid_split_rid(NULL, s3->sid,
1197 NULL, &s2->rid);
1199 s2->sid_index = s3->sid_index;
1201 r->out.sids->count = r2.out.sids->count;
1203 return status;
1207 lsa_LookupNames
1209 NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1210 struct lsa_LookupNames *r)
1212 enum dcerpc_transport_t transport =
1213 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
1214 struct lsa_policy_state *policy_state = NULL;
1215 struct dcesrv_handle *policy_handle = NULL;
1216 struct lsa_LookupNames3 r2;
1217 NTSTATUS status;
1218 uint32_t i;
1220 if (transport != NCACN_NP && transport != NCALRPC) {
1221 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
1224 DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1226 policy_state = policy_handle->data;
1228 *r->out.domains = NULL;
1229 r->out.sids->count = 0;
1230 r->out.sids->sids = NULL;
1231 *r->out.count = 0;
1233 r->out.sids->sids = talloc_zero_array(r->out.sids,
1234 struct lsa_TranslatedSid,
1235 r->in.num_names);
1236 if (r->out.sids->sids == NULL) {
1237 return NT_STATUS_NO_MEMORY;
1240 ZERO_STRUCT(r2);
1242 r2.in.handle = r->in.handle;
1243 r2.in.num_names = r->in.num_names;
1244 r2.in.names = r->in.names;
1245 r2.in.sids = talloc_zero(mem_ctx, struct lsa_TransSidArray3);
1246 if (r2.in.sids == NULL) {
1247 return NT_STATUS_NO_MEMORY;
1249 r2.in.level = r->in.level;
1250 r2.in.count = r->in.count;
1251 r2.in.lookup_options = LSA_LOOKUP_OPTION_SEARCH_ISOLATED_NAMES;
1252 r2.in.client_revision = LSA_CLIENT_REVISION_1;
1253 r2.out.count = r->out.count;
1254 r2.out.sids = talloc_zero(mem_ctx, struct lsa_TransSidArray3);
1255 if (r2.out.sids == NULL) {
1256 return NT_STATUS_NO_MEMORY;
1258 r2.out.domains = r->out.domains;
1260 status = dcesrv_lsa_LookupNames_common(dce_call,
1261 mem_ctx,
1262 policy_state,
1263 &r2);
1265 SMB_ASSERT(r2.out.sids->count <= r->in.num_names);
1266 for (i=0;i<r2.out.sids->count;i++) {
1267 struct lsa_TranslatedSid3 *s3 =
1268 &r2.out.sids->sids[i];
1269 struct lsa_TranslatedSid *s =
1270 &r->out.sids->sids[i];
1272 s->sid_type = s3->sid_type;
1273 if (s3->sid_type == SID_NAME_DOMAIN) {
1274 s->rid = UINT32_MAX;
1275 } else if (s3->flags & 0x00000004) {
1276 s->rid = UINT32_MAX;
1277 } else if (s3->sid == NULL) {
1279 * MS-LSAT 3.1.4.7 - rid zero is considered
1280 * equivalent to sid NULL - so we should return
1281 * 0 rid for unmapped entries
1283 s->rid = 0;
1284 } else {
1285 s->rid = 0;
1286 dom_sid_split_rid(NULL, s3->sid,
1287 NULL, &s->rid);
1289 s->sid_index = s3->sid_index;
1291 r->out.sids->count = r2.out.sids->count;
1293 return status;