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"
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",
55 .rtype
= SID_NAME_WKN_GRP
,
58 .domain
= "NT AUTHORITY",
60 .sid
= SID_NT_NETWORK
,
61 .rtype
= SID_NAME_WKN_GRP
,
64 .domain
= "NT AUTHORITY",
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",
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",
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",
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",
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",
187 .rtype
= SID_NAME_WKN_GRP
,
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
)
199 for (i
=0; well_known
[i
].sid
; i
++) {
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
;
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
;
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
)
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
;
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
,
248 struct ldb_message
**res
;
249 const char * const attrs
[] = { "objectSid", "sAMAccountType", NULL
};
252 const char *username
;
253 struct ldb_dn
*domain_dn
;
254 struct dom_sid
*domain_sid
;
257 p
= strchr_m(name
, '\\');
259 domain
= talloc_strndup(mem_ctx
, name
, p
-name
);
261 return NT_STATUS_NO_MEMORY
;
264 } else if (strchr_m(name
, '@')) {
265 status
= crack_name_to_nt4_name(mem_ctx
, ev_ctx
, lp_ctx
, DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL
, name
, &domain
, &username
);
266 if (!NT_STATUS_IS_OK(status
)) {
267 DEBUG(3, ("Failed to crack name %s into an NT4 name: %s\n", name
, nt_errstr(status
)));
276 /* Look up table of well known names */
277 status
= lookup_well_known_names(mem_ctx
, NULL
, username
, authority_name
, sid
, rtype
);
278 if (NT_STATUS_IS_OK(status
)) {
279 dom_sid_split_rid(NULL
, *sid
, NULL
, rid
);
283 if (username
== NULL
) {
284 *authority_name
= NAME_BUILTIN
;
285 *sid
= dom_sid_parse_talloc(mem_ctx
, SID_BUILTIN
);
286 *rtype
= SID_NAME_DOMAIN
;
291 if (strcasecmp_m(username
, NAME_NT_AUTHORITY
) == 0) {
292 *authority_name
= NAME_NT_AUTHORITY
;
293 *sid
= dom_sid_parse_talloc(mem_ctx
, SID_NT_AUTHORITY
);
294 *rtype
= SID_NAME_DOMAIN
;
295 dom_sid_split_rid(NULL
, *sid
, NULL
, rid
);
298 if (strcasecmp_m(username
, NAME_BUILTIN
) == 0) {
299 *authority_name
= NAME_BUILTIN
;
300 *sid
= dom_sid_parse_talloc(mem_ctx
, SID_BUILTIN
);
301 *rtype
= SID_NAME_DOMAIN
;
305 if (strcasecmp_m(username
, state
->domain_dns
) == 0) {
306 *authority_name
= state
->domain_name
;
307 *sid
= state
->domain_sid
;
308 *rtype
= SID_NAME_DOMAIN
;
312 if (strcasecmp_m(username
, state
->domain_name
) == 0) {
313 *authority_name
= state
->domain_name
;
314 *sid
= state
->domain_sid
;
315 *rtype
= SID_NAME_DOMAIN
;
320 /* Perhaps this is a well known user? */
321 name
= talloc_asprintf(mem_ctx
, "%s\\%s", NAME_NT_AUTHORITY
, username
);
323 return NT_STATUS_NO_MEMORY
;
325 status
= dcesrv_lsa_lookup_name(ev_ctx
, lp_ctx
, state
, mem_ctx
, name
, authority_name
, sid
, rtype
, rid
);
326 if (NT_STATUS_IS_OK(status
)) {
330 /* Perhaps this is a BUILTIN user? */
331 name
= talloc_asprintf(mem_ctx
, "%s\\%s", NAME_BUILTIN
, username
);
333 return NT_STATUS_NO_MEMORY
;
335 status
= dcesrv_lsa_lookup_name(ev_ctx
, lp_ctx
, state
, mem_ctx
, name
, authority_name
, sid
, rtype
, rid
);
336 if (NT_STATUS_IS_OK(status
)) {
340 /* OK, I give up - perhaps we need to assume the user is in our domain? */
341 name
= talloc_asprintf(mem_ctx
, "%s\\%s", state
->domain_name
, username
);
343 return NT_STATUS_NO_MEMORY
;
345 status
= dcesrv_lsa_lookup_name(ev_ctx
, lp_ctx
, state
, mem_ctx
, name
, authority_name
, sid
, rtype
, rid
);
346 if (NT_STATUS_IS_OK(status
)) {
350 return STATUS_SOME_UNMAPPED
;
351 } else if (strcasecmp_m(domain
, NAME_NT_AUTHORITY
) == 0) {
353 *authority_name
= NAME_NT_AUTHORITY
;
354 *sid
= dom_sid_parse_talloc(mem_ctx
, SID_NT_AUTHORITY
);
355 *rtype
= SID_NAME_DOMAIN
;
356 dom_sid_split_rid(NULL
, *sid
, NULL
, rid
);
360 /* Look up table of well known names */
361 status
= lookup_well_known_names(mem_ctx
, domain
, username
, authority_name
,
363 if (NT_STATUS_IS_OK(status
)) {
364 dom_sid_split_rid(NULL
, *sid
, NULL
, rid
);
367 } else if (strcasecmp_m(domain
, NAME_BUILTIN
) == 0) {
368 *authority_name
= NAME_BUILTIN
;
369 domain_dn
= state
->builtin_dn
;
370 } else if (strcasecmp_m(domain
, state
->domain_dns
) == 0) {
371 *authority_name
= state
->domain_name
;
372 domain_dn
= state
->domain_dn
;
373 } else if (strcasecmp_m(domain
, state
->domain_name
) == 0) {
374 *authority_name
= state
->domain_name
;
375 domain_dn
= state
->domain_dn
;
377 /* Not local, need to ask winbind in future */
378 return STATUS_SOME_UNMAPPED
;
381 ret
= gendb_search_dn(state
->sam_ldb
, mem_ctx
, domain_dn
, &res
, attrs
);
383 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
385 domain_sid
= samdb_result_dom_sid(mem_ctx
, res
[0], "objectSid");
386 if (domain_sid
== NULL
) {
387 return NT_STATUS_INVALID_SID
;
392 *rtype
= SID_NAME_DOMAIN
;
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
));
401 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
404 for (i
=0; i
< ret
; i
++) {
405 *sid
= samdb_result_dom_sid(mem_ctx
, res
[i
], "objectSid");
407 return NT_STATUS_INVALID_SID
;
410 /* Check that this is in the domain */
411 if (!dom_sid_in_domain(domain_sid
, *sid
)) {
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 dom_sid_split_rid(NULL
, *sid
, NULL
, rid
);
426 /* need to check for an allocated sid */
428 return NT_STATUS_INVALID_SID
;
433 add to the lsa_RefDomainList for LookupSids and LookupNames
435 static NTSTATUS
dcesrv_lsa_authority_list(struct lsa_policy_state
*state
, TALLOC_CTX
*mem_ctx
,
436 enum lsa_SidType rtype
,
437 const char *authority_name
,
439 struct lsa_RefDomainList
*domains
,
442 struct dom_sid
*authority_sid
;
445 if (rtype
!= SID_NAME_DOMAIN
) {
446 authority_sid
= dom_sid_dup(mem_ctx
, sid
);
447 if (authority_sid
== NULL
) {
448 return NT_STATUS_NO_MEMORY
;
450 authority_sid
->num_auths
--;
455 /* see if we've already done this authority name */
456 for (i
=0;i
<domains
->count
;i
++) {
457 if (strcasecmp_m(authority_name
, domains
->domains
[i
].name
.string
) == 0) {
463 domains
->domains
= talloc_realloc(domains
,
465 struct lsa_DomainInfo
,
467 if (domains
->domains
== NULL
) {
468 return NT_STATUS_NO_MEMORY
;
470 domains
->domains
[i
].name
.string
= authority_name
;
471 domains
->domains
[i
].sid
= authority_sid
;
473 domains
->max_size
= LSA_REF_DOMAIN_LIST_MULTIPLIER
* domains
->count
;
480 lookup a name for 1 SID
482 static NTSTATUS
dcesrv_lsa_lookup_sid(struct lsa_policy_state
*state
, TALLOC_CTX
*mem_ctx
,
483 struct dom_sid
*sid
, const char *sid_str
,
484 const char **authority_name
,
485 const char **name
, enum lsa_SidType
*rtype
)
490 struct ldb_message
**res
;
491 struct ldb_dn
*domain_dn
;
492 const char * const attrs
[] = { "sAMAccountName", "sAMAccountType", "cn", NULL
};
494 status
= lookup_well_known_sids(mem_ctx
, sid_str
, authority_name
, name
, rtype
);
495 if (NT_STATUS_IS_OK(status
)) {
499 if (dom_sid_in_domain(state
->domain_sid
, sid
)) {
500 *authority_name
= state
->domain_name
;
501 domain_dn
= state
->domain_dn
;
502 } else if (dom_sid_in_domain(state
->builtin_sid
, sid
)) {
503 *authority_name
= NAME_BUILTIN
;
504 domain_dn
= state
->builtin_dn
;
506 /* Not well known, our domain or built in */
508 /* In future, we must look at SID histories, and at trusted domains via winbind */
510 return NT_STATUS_NOT_FOUND
;
513 /* need to re-add a check for an allocated sid */
515 ret
= gendb_search(state
->sam_ldb
, mem_ctx
, domain_dn
, &res
, attrs
,
516 "objectSid=%s", ldap_encode_ndr_dom_sid(mem_ctx
, sid
));
517 if ((ret
< 0) || (ret
> 1)) {
518 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
521 return NT_STATUS_NOT_FOUND
;
524 *name
= ldb_msg_find_attr_as_string(res
[0], "sAMAccountName", NULL
);
526 *name
= ldb_msg_find_attr_as_string(res
[0], "cn", NULL
);
528 *name
= talloc_strdup(mem_ctx
, sid_str
);
529 NT_STATUS_HAVE_NO_MEMORY(*name
);
533 atype
= samdb_result_uint(res
[0], "sAMAccountType", 0);
534 *rtype
= ds_atype_map(atype
);
543 NTSTATUS
dcesrv_lsa_LookupSids2(struct dcesrv_call_state
*dce_call
,
545 struct lsa_LookupSids2
*r
)
547 struct lsa_policy_state
*state
;
548 struct lsa_RefDomainList
*domains
= NULL
;
550 NTSTATUS status
= NT_STATUS_OK
;
552 if (r
->in
.level
< LSA_LOOKUP_NAMES_ALL
||
553 r
->in
.level
> LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC
) {
554 return NT_STATUS_INVALID_PARAMETER
;
557 *r
->out
.domains
= NULL
;
559 /* NOTE: the WSPP test suite tries SIDs with invalid revision numbers,
560 and expects NT_STATUS_INVALID_PARAMETER back - we just treat it as
561 an unknown SID. We could add a SID validator here. (tridge)
565 status
= dcesrv_lsa_get_policy_state(dce_call
, mem_ctx
, &state
);
566 if (!NT_STATUS_IS_OK(status
)) {
570 domains
= talloc_zero(r
->out
.domains
, struct lsa_RefDomainList
);
571 if (domains
== NULL
) {
572 return NT_STATUS_NO_MEMORY
;
574 *r
->out
.domains
= domains
;
576 r
->out
.names
= talloc_zero(mem_ctx
, struct lsa_TransNameArray2
);
577 if (r
->out
.names
== NULL
) {
578 return NT_STATUS_NO_MEMORY
;
583 r
->out
.names
->names
= talloc_array(r
->out
.names
, struct lsa_TranslatedName2
,
584 r
->in
.sids
->num_sids
);
585 if (r
->out
.names
->names
== NULL
) {
586 return NT_STATUS_NO_MEMORY
;
589 for (i
=0;i
<r
->in
.sids
->num_sids
;i
++) {
590 struct dom_sid
*sid
= r
->in
.sids
->sids
[i
].sid
;
591 char *sid_str
= dom_sid_string(mem_ctx
, sid
);
592 const char *name
, *authority_name
;
593 enum lsa_SidType rtype
;
597 r
->out
.names
->count
++;
599 r
->out
.names
->names
[i
].sid_type
= SID_NAME_UNKNOWN
;
600 r
->out
.names
->names
[i
].name
.string
= sid_str
;
601 r
->out
.names
->names
[i
].sid_index
= 0xFFFFFFFF;
602 r
->out
.names
->names
[i
].unknown
= 0;
604 if (sid_str
== NULL
) {
605 r
->out
.names
->names
[i
].name
.string
= "(SIDERROR)";
606 status
= STATUS_SOME_UNMAPPED
;
610 status2
= dcesrv_lsa_lookup_sid(state
, mem_ctx
, sid
, sid_str
,
611 &authority_name
, &name
, &rtype
);
612 if (!NT_STATUS_IS_OK(status2
)) {
613 status
= STATUS_SOME_UNMAPPED
;
617 /* set up the authority table */
618 status2
= dcesrv_lsa_authority_list(state
, mem_ctx
, rtype
,
620 domains
, &sid_index
);
621 if (!NT_STATUS_IS_OK(status2
)) {
625 r
->out
.names
->names
[i
].sid_type
= rtype
;
626 r
->out
.names
->names
[i
].name
.string
= name
;
627 r
->out
.names
->names
[i
].sid_index
= sid_index
;
628 r
->out
.names
->names
[i
].unknown
= 0;
633 if (*r
->out
.count
== 0) {
634 return NT_STATUS_NONE_MAPPED
;
636 if (*r
->out
.count
!= r
->in
.sids
->num_sids
) {
637 return STATUS_SOME_UNMAPPED
;
647 Identical to LookupSids2, but doesn't take a policy handle
650 NTSTATUS
dcesrv_lsa_LookupSids3(struct dcesrv_call_state
*dce_call
,
652 struct lsa_LookupSids3
*r
)
654 struct lsa_LookupSids2 r2
;
655 struct lsa_OpenPolicy2 pol
;
657 struct dcesrv_handle
*h
;
661 /* No policy handle on the wire, so make one up here */
662 r2
.in
.handle
= talloc(mem_ctx
, struct policy_handle
);
664 return NT_STATUS_NO_MEMORY
;
667 pol
.out
.handle
= r2
.in
.handle
;
668 pol
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
670 pol
.in
.system_name
= NULL
;
671 status
= dcesrv_lsa_OpenPolicy2(dce_call
, mem_ctx
, &pol
);
672 if (!NT_STATUS_IS_OK(status
)) {
676 /* ensure this handle goes away at the end of this call */
677 DCESRV_PULL_HANDLE(h
, r2
.in
.handle
, LSA_HANDLE_POLICY
);
678 talloc_steal(mem_ctx
, h
);
680 r2
.in
.sids
= r
->in
.sids
;
681 r2
.in
.names
= r
->in
.names
;
682 r2
.in
.level
= r
->in
.level
;
683 r2
.in
.count
= r
->in
.count
;
684 r2
.in
.lookup_options
= r
->in
.lookup_options
;
685 r2
.in
.client_revision
= r
->in
.client_revision
;
686 r2
.out
.count
= r
->out
.count
;
687 r2
.out
.names
= r
->out
.names
;
688 r2
.out
.domains
= r
->out
.domains
;
690 status
= dcesrv_lsa_LookupSids2(dce_call
, mem_ctx
, &r2
);
692 r
->out
.domains
= r2
.out
.domains
;
693 r
->out
.names
= r2
.out
.names
;
694 r
->out
.count
= r2
.out
.count
;
703 NTSTATUS
dcesrv_lsa_LookupSids(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
704 struct lsa_LookupSids
*r
)
706 struct lsa_LookupSids2 r2
;
712 r2
.in
.handle
= r
->in
.handle
;
713 r2
.in
.sids
= r
->in
.sids
;
715 r2
.in
.level
= r
->in
.level
;
716 r2
.in
.count
= r
->in
.count
;
717 r2
.in
.lookup_options
= 0;
718 r2
.in
.client_revision
= 0;
719 r2
.out
.count
= r
->out
.count
;
721 r2
.out
.domains
= r
->out
.domains
;
723 status
= dcesrv_lsa_LookupSids2(dce_call
, mem_ctx
, &r2
);
724 /* we deliberately don't check for error from the above,
725 as even on error we are supposed to return the names */
727 r
->out
.domains
= r2
.out
.domains
;
733 r
->out
.names
= talloc(mem_ctx
, struct lsa_TransNameArray
);
734 if (r
->out
.names
== NULL
) {
735 return NT_STATUS_NO_MEMORY
;
737 r
->out
.names
->count
= r2
.out
.names
->count
;
738 r
->out
.names
->names
= talloc_array(r
->out
.names
, struct lsa_TranslatedName
,
739 r
->out
.names
->count
);
740 if (r
->out
.names
->names
== NULL
) {
741 return NT_STATUS_NO_MEMORY
;
743 for (i
=0;i
<r
->out
.names
->count
;i
++) {
744 r
->out
.names
->names
[i
].sid_type
= r2
.out
.names
->names
[i
].sid_type
;
745 r
->out
.names
->names
[i
].name
.string
= r2
.out
.names
->names
[i
].name
.string
;
746 r
->out
.names
->names
[i
].sid_index
= r2
.out
.names
->names
[i
].sid_index
;
756 NTSTATUS
dcesrv_lsa_LookupNames3(struct dcesrv_call_state
*dce_call
,
758 struct lsa_LookupNames3
*r
)
760 struct lsa_policy_state
*policy_state
;
761 struct dcesrv_handle
*policy_handle
;
763 struct loadparm_context
*lp_ctx
= dce_call
->conn
->dce_ctx
->lp_ctx
;
764 struct lsa_RefDomainList
*domains
;
766 DCESRV_PULL_HANDLE(policy_handle
, r
->in
.handle
, LSA_HANDLE_POLICY
);
768 if (r
->in
.level
< LSA_LOOKUP_NAMES_ALL
||
769 r
->in
.level
> LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC
) {
770 return NT_STATUS_INVALID_PARAMETER
;
773 policy_state
= policy_handle
->data
;
775 *r
->out
.domains
= NULL
;
777 domains
= talloc_zero(mem_ctx
, struct lsa_RefDomainList
);
778 if (domains
== NULL
) {
779 return NT_STATUS_NO_MEMORY
;
781 *r
->out
.domains
= domains
;
783 r
->out
.sids
= talloc_zero(mem_ctx
, struct lsa_TransSidArray3
);
784 if (r
->out
.sids
== NULL
) {
785 return NT_STATUS_NO_MEMORY
;
790 r
->out
.sids
->sids
= talloc_array(r
->out
.sids
, struct lsa_TranslatedSid3
,
792 if (r
->out
.sids
->sids
== NULL
) {
793 return NT_STATUS_NO_MEMORY
;
796 for (i
=0;i
<r
->in
.num_names
;i
++) {
797 const char *name
= r
->in
.names
[i
].string
;
798 const char *authority_name
;
800 uint32_t sid_index
, rid
;
801 enum lsa_SidType rtype
;
804 r
->out
.sids
->count
++;
806 r
->out
.sids
->sids
[i
].sid_type
= SID_NAME_UNKNOWN
;
807 r
->out
.sids
->sids
[i
].sid
= NULL
;
808 r
->out
.sids
->sids
[i
].sid_index
= 0xFFFFFFFF;
809 r
->out
.sids
->sids
[i
].flags
= 0;
811 status2
= dcesrv_lsa_lookup_name(dce_call
->event_ctx
, lp_ctx
, policy_state
, mem_ctx
, name
,
812 &authority_name
, &sid
, &rtype
, &rid
);
813 if (!NT_STATUS_IS_OK(status2
) || sid
->num_auths
== 0) {
817 status2
= dcesrv_lsa_authority_list(policy_state
, mem_ctx
, rtype
, authority_name
,
818 sid
, domains
, &sid_index
);
819 if (!NT_STATUS_IS_OK(status2
)) {
823 r
->out
.sids
->sids
[i
].sid_type
= rtype
;
824 r
->out
.sids
->sids
[i
].sid
= sid
;
825 r
->out
.sids
->sids
[i
].sid_index
= sid_index
;
826 r
->out
.sids
->sids
[i
].flags
= 0;
831 if (*r
->out
.count
== 0) {
832 return NT_STATUS_NONE_MAPPED
;
834 if (*r
->out
.count
!= r
->in
.num_names
) {
835 return STATUS_SOME_UNMAPPED
;
844 Identical to LookupNames3, but doesn't take a policy handle
847 NTSTATUS
dcesrv_lsa_LookupNames4(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
848 struct lsa_LookupNames4
*r
)
850 struct lsa_LookupNames3 r2
;
851 struct lsa_OpenPolicy2 pol
;
853 struct dcesrv_handle
*h
;
857 /* No policy handle on the wire, so make one up here */
858 r2
.in
.handle
= talloc(mem_ctx
, struct policy_handle
);
860 return NT_STATUS_NO_MEMORY
;
863 pol
.out
.handle
= r2
.in
.handle
;
864 pol
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
866 pol
.in
.system_name
= NULL
;
867 status
= dcesrv_lsa_OpenPolicy2(dce_call
, mem_ctx
, &pol
);
868 if (!NT_STATUS_IS_OK(status
)) {
872 /* ensure this handle goes away at the end of this call */
873 DCESRV_PULL_HANDLE(h
, r2
.in
.handle
, LSA_HANDLE_POLICY
);
874 talloc_steal(mem_ctx
, h
);
876 r2
.in
.num_names
= r
->in
.num_names
;
877 r2
.in
.names
= r
->in
.names
;
878 r2
.in
.level
= r
->in
.level
;
879 r2
.in
.sids
= r
->in
.sids
;
880 r2
.in
.count
= r
->in
.count
;
881 r2
.in
.lookup_options
= r
->in
.lookup_options
;
882 r2
.in
.client_revision
= r
->in
.client_revision
;
883 r2
.out
.domains
= r
->out
.domains
;
884 r2
.out
.sids
= r
->out
.sids
;
885 r2
.out
.count
= r
->out
.count
;
887 status
= dcesrv_lsa_LookupNames3(dce_call
, mem_ctx
, &r2
);
889 r
->out
.domains
= r2
.out
.domains
;
890 r
->out
.sids
= r2
.out
.sids
;
891 r
->out
.count
= r2
.out
.count
;
898 NTSTATUS
dcesrv_lsa_LookupNames2(struct dcesrv_call_state
*dce_call
,
900 struct lsa_LookupNames2
*r
)
902 struct lsa_policy_state
*state
;
903 struct dcesrv_handle
*h
;
905 struct loadparm_context
*lp_ctx
= dce_call
->conn
->dce_ctx
->lp_ctx
;
906 struct lsa_RefDomainList
*domains
;
908 *r
->out
.domains
= NULL
;
910 DCESRV_PULL_HANDLE(h
, r
->in
.handle
, LSA_HANDLE_POLICY
);
912 if (r
->in
.level
< LSA_LOOKUP_NAMES_ALL
||
913 r
->in
.level
> LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC
) {
914 return NT_STATUS_INVALID_PARAMETER
;
919 domains
= talloc_zero(mem_ctx
, struct lsa_RefDomainList
);
920 if (domains
== NULL
) {
921 return NT_STATUS_NO_MEMORY
;
923 *r
->out
.domains
= domains
;
925 r
->out
.sids
= talloc_zero(mem_ctx
, struct lsa_TransSidArray2
);
926 if (r
->out
.sids
== NULL
) {
927 return NT_STATUS_NO_MEMORY
;
932 r
->out
.sids
->sids
= talloc_array(r
->out
.sids
, struct lsa_TranslatedSid2
,
934 if (r
->out
.sids
->sids
== NULL
) {
935 return NT_STATUS_NO_MEMORY
;
938 for (i
=0;i
<r
->in
.num_names
;i
++) {
939 const char *name
= r
->in
.names
[i
].string
;
940 const char *authority_name
;
942 uint32_t rtype
, sid_index
, rid
=0;
945 r
->out
.sids
->count
++;
947 r
->out
.sids
->sids
[i
].sid_type
= SID_NAME_UNKNOWN
;
948 /* MS-LSAT 3.1.4.7 - rid zero is considered equivalent
949 to sid NULL - so we should return 0 rid for
951 r
->out
.sids
->sids
[i
].rid
= 0;
952 r
->out
.sids
->sids
[i
].sid_index
= 0xFFFFFFFF;
953 r
->out
.sids
->sids
[i
].unknown
= 0;
955 status2
= dcesrv_lsa_lookup_name(dce_call
->event_ctx
, lp_ctx
, state
, mem_ctx
, name
,
956 &authority_name
, &sid
, &rtype
, &rid
);
957 if (!NT_STATUS_IS_OK(status2
)) {
961 status2
= dcesrv_lsa_authority_list(state
, mem_ctx
, rtype
, authority_name
,
962 sid
, domains
, &sid_index
);
963 if (!NT_STATUS_IS_OK(status2
)) {
967 r
->out
.sids
->sids
[i
].sid_type
= rtype
;
968 r
->out
.sids
->sids
[i
].rid
= rid
;
969 r
->out
.sids
->sids
[i
].sid_index
= sid_index
;
970 r
->out
.sids
->sids
[i
].unknown
= 0;
975 if (*r
->out
.count
== 0) {
976 return NT_STATUS_NONE_MAPPED
;
978 if (*r
->out
.count
!= r
->in
.num_names
) {
979 return STATUS_SOME_UNMAPPED
;
988 NTSTATUS
dcesrv_lsa_LookupNames(struct dcesrv_call_state
*dce_call
, TALLOC_CTX
*mem_ctx
,
989 struct lsa_LookupNames
*r
)
991 struct lsa_LookupNames2 r2
;
997 r2
.in
.handle
= r
->in
.handle
;
998 r2
.in
.num_names
= r
->in
.num_names
;
999 r2
.in
.names
= r
->in
.names
;
1001 r2
.in
.level
= r
->in
.level
;
1002 r2
.in
.count
= r
->in
.count
;
1003 r2
.in
.lookup_options
= 0;
1004 r2
.in
.client_revision
= 0;
1005 r2
.out
.count
= r
->out
.count
;
1006 r2
.out
.domains
= r
->out
.domains
;
1008 status
= dcesrv_lsa_LookupNames2(dce_call
, mem_ctx
, &r2
);
1009 if (r2
.out
.sids
== NULL
) {
1013 r
->out
.sids
= talloc(mem_ctx
, struct lsa_TransSidArray
);
1014 if (r
->out
.sids
== NULL
) {
1015 return NT_STATUS_NO_MEMORY
;
1017 r
->out
.sids
->count
= r2
.out
.sids
->count
;
1018 r
->out
.sids
->sids
= talloc_array(r
->out
.sids
, struct lsa_TranslatedSid
,
1019 r
->out
.sids
->count
);
1020 if (r
->out
.sids
->sids
== NULL
) {
1021 return NT_STATUS_NO_MEMORY
;
1023 for (i
=0;i
<r
->out
.sids
->count
;i
++) {
1024 r
->out
.sids
->sids
[i
].sid_type
= r2
.out
.sids
->sids
[i
].sid_type
;
1025 r
->out
.sids
->sids
[i
].rid
= r2
.out
.sids
->sids
[i
].rid
;
1026 r
->out
.sids
->sids
[i
].sid_index
= r2
.out
.sids
->sids
[i
].sid_index
;