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"
30 enum lsa_SidType rtype
;
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",
56 .rtype
= SID_NAME_WKN_GRP
,
59 .domain
= "NT AUTHORITY",
61 .sid
= SID_NT_NETWORK
,
62 .rtype
= SID_NAME_WKN_GRP
,
65 .domain
= "NT AUTHORITY",
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",
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",
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",
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",
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",
188 .rtype
= SID_NAME_WKN_GRP
,
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
)
200 for (i
=0; well_known
[i
].sid
; i
++) {
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
;
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
;
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
)
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
;
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
,
249 struct ldb_message
**res
;
250 const char * const attrs
[] = { "objectSid", "sAMAccountType", NULL
};
253 const char *username
;
254 struct ldb_dn
*domain_dn
;
255 struct dom_sid
*domain_sid
;
258 p
= strchr_m(name
, '\\');
260 domain
= talloc_strndup(mem_ctx
, name
, p
-name
);
262 return NT_STATUS_NO_MEMORY
;
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
)));
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
);
284 if (username
== NULL
) {
285 *authority_name
= NAME_BUILTIN
;
286 *sid
= dom_sid_parse_talloc(mem_ctx
, SID_BUILTIN
);
287 *rtype
= SID_NAME_DOMAIN
;
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
);
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
;
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
;
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
;
321 /* Perhaps this is a well known user? */
322 name
= talloc_asprintf(mem_ctx
, "%s\\%s", NAME_NT_AUTHORITY
, username
);
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
)) {
331 /* Perhaps this is a BUILTIN user? */
332 name
= talloc_asprintf(mem_ctx
, "%s\\%s", NAME_BUILTIN
, username
);
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
)) {
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
);
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
)) {
351 return STATUS_SOME_UNMAPPED
;
352 } else if (strcasecmp_m(domain
, NAME_NT_AUTHORITY
) == 0) {
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
);
361 /* Look up table of well known names */
362 status
= lookup_well_known_names(mem_ctx
, domain
, username
, authority_name
,
364 if (NT_STATUS_IS_OK(status
)) {
365 dom_sid_split_rid(NULL
, *sid
, NULL
, rid
);
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
;
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
);
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
;
393 *rtype
= SID_NAME_DOMAIN
;
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
));
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");
408 return NT_STATUS_INVALID_SID
;
411 /* Check that this is in the domain */
412 if (!dom_sid_in_domain(domain_sid
, *sid
)) {
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
);
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
,
440 struct lsa_RefDomainList
*domains
,
443 struct dom_sid
*authority_sid
;
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
--;
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) {
464 domains
->domains
= talloc_realloc(domains
,
466 struct lsa_DomainInfo
,
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
;
474 domains
->max_size
= LSA_REF_DOMAIN_LIST_MULTIPLIER
* domains
->count
;
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
)
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
)) {
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
;
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
;
522 return NT_STATUS_NOT_FOUND
;
525 *name
= ldb_msg_find_attr_as_string(res
[0], "sAMAccountName", NULL
);
527 *name
= ldb_msg_find_attr_as_string(res
[0], "cn", NULL
);
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
);
544 NTSTATUS
dcesrv_lsa_LookupSids2(struct dcesrv_call_state
*dce_call
,
546 struct lsa_LookupSids2
*r
)
548 struct lsa_policy_state
*state
;
549 struct lsa_RefDomainList
*domains
= NULL
;
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
;
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)
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
;
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
;
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
;
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
;
618 /* set up the authority table */
619 status2
= dcesrv_lsa_authority_list(state
, mem_ctx
, rtype
,
621 domains
, &sid_index
);
622 if (!NT_STATUS_IS_OK(status2
)) {
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;
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
;
648 Identical to LookupSids2, but doesn't take a policy handle
651 NTSTATUS
dcesrv_lsa_LookupSids3(struct dcesrv_call_state
*dce_call
,
653 struct lsa_LookupSids3
*r
)
655 struct lsa_LookupSids2 r2
;
656 struct lsa_OpenPolicy2 pol
;
658 struct dcesrv_handle
*h
;
662 /* No policy handle on the wire, so make one up here */
663 r2
.in
.handle
= talloc(mem_ctx
, struct policy_handle
);
665 return NT_STATUS_NO_MEMORY
;
668 pol
.out
.handle
= r2
.in
.handle
;
669 pol
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
671 pol
.in
.system_name
= NULL
;
672 status
= dcesrv_lsa_OpenPolicy2(dce_call
, mem_ctx
, &pol
);
673 if (!NT_STATUS_IS_OK(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
;
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
;
713 r2
.in
.handle
= r
->in
.handle
;
714 r2
.in
.sids
= r
->in
.sids
;
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
;
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
;
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
;
757 NTSTATUS
dcesrv_lsa_LookupNames3(struct dcesrv_call_state
*dce_call
,
759 struct lsa_LookupNames3
*r
)
761 struct lsa_policy_state
*policy_state
;
762 struct dcesrv_handle
*policy_handle
;
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
;
791 r
->out
.sids
->sids
= talloc_array(r
->out
.sids
, struct lsa_TranslatedSid3
,
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
;
801 uint32_t sid_index
, rid
;
802 enum lsa_SidType rtype
;
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) {
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
)) {
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;
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
;
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
;
854 struct dcesrv_handle
*h
;
858 /* No policy handle on the wire, so make one up here */
859 r2
.in
.handle
= talloc(mem_ctx
, struct policy_handle
);
861 return NT_STATUS_NO_MEMORY
;
864 pol
.out
.handle
= r2
.in
.handle
;
865 pol
.in
.access_mask
= SEC_FLAG_MAXIMUM_ALLOWED
;
867 pol
.in
.system_name
= NULL
;
868 status
= dcesrv_lsa_OpenPolicy2(dce_call
, mem_ctx
, &pol
);
869 if (!NT_STATUS_IS_OK(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
;
899 NTSTATUS
dcesrv_lsa_LookupNames2(struct dcesrv_call_state
*dce_call
,
901 struct lsa_LookupNames2
*r
)
903 struct lsa_policy_state
*state
;
904 struct dcesrv_handle
*h
;
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
;
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
;
933 r
->out
.sids
->sids
= talloc_array(r
->out
.sids
, struct lsa_TranslatedSid2
,
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
;
943 uint32_t sid_index
, rid
=0;
944 enum lsa_SidType rtype
;
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
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
)) {
963 status2
= dcesrv_lsa_authority_list(state
, mem_ctx
, rtype
, authority_name
,
964 sid
, domains
, &sid_index
);
965 if (!NT_STATUS_IS_OK(status2
)) {
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;
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
;
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
;
999 r2
.in
.handle
= r
->in
.handle
;
1000 r2
.in
.num_names
= r
->in
.num_names
;
1001 r2
.in
.names
= r
->in
.names
;
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
) {
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
;