libds: merge the UF<->ACB flag mapping functions.
[sfrench/samba-autobuild/.git] / source4 / rpc_server / lsa / lsa_lookup.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    endpoint server for the lsarpc pipe
5
6    Copyright (C) Andrew Tridgell 2004
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2007
8    
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.
13    
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.
18    
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/>.
21 */
22
23 #include "rpc_server/lsa/lsa.h"
24
25 static const struct {
26         const char *domain;
27         const char *name;
28         const char *sid;
29         int rtype;
30 } well_known[] = {
31         {
32                 .name = "EVERYONE",
33                 .sid = SID_WORLD,
34                 .rtype = SID_NAME_WKN_GRP,
35         },
36         {
37                 .name = "CREATOR OWNER",
38                 .sid = SID_CREATOR_OWNER,
39                 .rtype = SID_NAME_WKN_GRP,
40         },
41         {
42                 .name = "CREATOR GROUP",
43                 .sid = SID_CREATOR_GROUP,
44                 .rtype = SID_NAME_WKN_GRP,
45         },
46         {
47                 .name = "Owner Rights",
48                 .sid = SID_OWNER_RIGHTS,
49                 .rtype = SID_NAME_WKN_GRP,
50         },
51         {
52                 .domain = "NT AUTHORITY",
53                 .name = "Dialup",
54                 .sid = SID_NT_DIALUP,
55                 .rtype = SID_NAME_WKN_GRP,
56         },
57         {
58                 .domain = "NT AUTHORITY",
59                 .name = "Network",
60                 .sid = SID_NT_NETWORK,
61                 .rtype = SID_NAME_WKN_GRP,
62         },
63         {
64                 .domain = "NT AUTHORITY",
65                 .name = "Batch",
66                 .sid = SID_NT_BATCH,
67                 .rtype = SID_NAME_WKN_GRP,
68         },
69         {
70                 .domain = "NT AUTHORITY",
71                 .name = "Interactive",
72                 .sid = SID_NT_INTERACTIVE,
73                 .rtype = SID_NAME_WKN_GRP,
74         },
75         {
76                 .domain = "NT AUTHORITY",
77                 .name = "Service",
78                 .sid = SID_NT_SERVICE,
79                 .rtype = SID_NAME_WKN_GRP,
80         },
81         {
82                 .domain = "NT AUTHORITY",
83                 .name = "ANONYMOUS LOGON",
84                 .sid = SID_NT_ANONYMOUS,
85                 .rtype = SID_NAME_WKN_GRP,
86         },
87         {
88                 .domain = "NT AUTHORITY",
89                 .name = "Proxy",
90                 .sid = SID_NT_PROXY,
91                 .rtype = SID_NAME_WKN_GRP,
92         },
93         {
94                 .domain = "NT AUTHORITY",
95                 .name = "ServerLogon",
96                 .sid = SID_NT_ENTERPRISE_DCS,
97                 .rtype = SID_NAME_WKN_GRP,
98         },
99         {
100                 .domain = "NT AUTHORITY",
101                 .name = "Self",
102                 .sid = SID_NT_SELF,
103                 .rtype = SID_NAME_WKN_GRP,
104         },
105         {
106                 .domain = "NT AUTHORITY",
107                 .name = "Authenticated Users",
108                 .sid = SID_NT_AUTHENTICATED_USERS,
109                 .rtype = SID_NAME_WKN_GRP,
110         },
111         {
112                 .domain = "NT AUTHORITY",
113                 .name = "Restricted",
114                 .sid = SID_NT_RESTRICTED,
115                 .rtype = SID_NAME_WKN_GRP,
116         },
117         {
118                 .domain = "NT AUTHORITY",
119                 .name = "Terminal Server User",
120                 .sid = SID_NT_TERMINAL_SERVER_USERS,
121                 .rtype = SID_NAME_WKN_GRP,
122         },
123         {
124                 .domain = "NT AUTHORITY",
125                 .name = "Remote Interactive Logon",
126                 .sid = SID_NT_REMOTE_INTERACTIVE,
127                 .rtype = SID_NAME_WKN_GRP,
128         },
129         {
130                 .domain = "NT AUTHORITY",
131                 .name = "This Organization",
132                 .sid = SID_NT_THIS_ORGANISATION,
133                 .rtype = SID_NAME_WKN_GRP,
134         },
135         {
136                 .domain = "NT AUTHORITY",
137                 .name = "SYSTEM",
138                 .sid = SID_NT_SYSTEM,
139                 .rtype = SID_NAME_WKN_GRP,
140         },
141         {
142                 .domain = "NT AUTHORITY",
143                 .name = "Local Service",
144                 .sid = SID_NT_LOCAL_SERVICE,
145                 .rtype = SID_NAME_WKN_GRP,
146         },
147         {
148                 .domain = "NT AUTHORITY",
149                 .name = "Network Service",
150                 .sid = SID_NT_NETWORK_SERVICE,
151                 .rtype = SID_NAME_WKN_GRP,
152         },
153         {
154                 .domain = "NT AUTHORITY",
155                 .name = "Digest Authentication",
156                 .sid = SID_NT_DIGEST_AUTHENTICATION,
157                 .rtype = SID_NAME_WKN_GRP,
158         },
159         {
160                 .domain = "NT AUTHORITY",
161                 .name = "Enterprise Domain Controllers",
162                 .sid = SID_NT_ENTERPRISE_DCS,
163                 .rtype = SID_NAME_WKN_GRP,
164         },
165         {
166                 .domain = "NT AUTHORITY",
167                 .name = "NTLM Authentication",
168                 .sid = SID_NT_NTLM_AUTHENTICATION,
169                 .rtype = SID_NAME_WKN_GRP,
170         },
171         {
172                 .domain = "NT AUTHORITY",
173                 .name = "Other Organization",
174                 .sid = SID_NT_OTHER_ORGANISATION,
175                 .rtype = SID_NAME_WKN_GRP,
176         },
177         {
178                 .domain = "NT AUTHORITY",
179                 .name = "SChannel Authentication",
180                 .sid = SID_NT_SCHANNEL_AUTHENTICATION,
181                 .rtype = SID_NAME_WKN_GRP,
182         },
183         {
184                 .domain = "NT AUTHORITY",
185                 .name = "IUSR",
186                 .sid = SID_NT_IUSR,
187                 .rtype = SID_NAME_WKN_GRP,
188         },
189         {
190                 .sid = NULL,
191         }
192 };
193
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) 
197 {
198         int i;
199         for (i=0; well_known[i].sid; i++) {
200                 if (domain) {
201                         if (strcasecmp_m(domain, well_known[i].domain) == 0
202                             && strcasecmp_m(name, well_known[i].name) == 0) {
203                                 *authority_name = well_known[i].domain;
204                                 *sid = dom_sid_parse_talloc(mem_ctx, well_known[i].sid);
205                                 *rtype = well_known[i].rtype;
206                                 return NT_STATUS_OK;
207                         }
208                 } else {
209                         if (strcasecmp_m(name, well_known[i].name) == 0) {
210                                 *authority_name = well_known[i].domain;
211                                 *sid = dom_sid_parse_talloc(mem_ctx, well_known[i].sid);
212                                 *rtype = well_known[i].rtype;
213                                 return NT_STATUS_OK;
214                         }
215                 }
216         }
217         return NT_STATUS_NOT_FOUND;     
218 }
219
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) 
223 {
224         int i;
225         for (i=0; well_known[i].sid; i++) {
226                 if (strcasecmp_m(sid_str, well_known[i].sid) == 0) {
227                         *authority_name = well_known[i].domain;
228                         *name = well_known[i].name;
229                         *rtype = well_known[i].rtype;
230                         return NT_STATUS_OK;
231                 }
232         }
233         return NT_STATUS_NOT_FOUND;     
234 }
235
236 /*
237   lookup a SID for 1 name
238 */
239 static NTSTATUS dcesrv_lsa_lookup_name(struct tevent_context *ev_ctx, 
240                                        struct loadparm_context *lp_ctx,
241                                        struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
242                                 const char *name, const char **authority_name, 
243                                 struct dom_sid **sid, enum lsa_SidType *rtype)
244 {
245         int ret, atype, i;
246         struct ldb_message **res;
247         const char * const attrs[] = { "objectSid", "sAMAccountType", NULL};
248         const char *p;
249         const char *domain;
250         const char *username;
251         struct ldb_dn *domain_dn;
252         struct dom_sid *domain_sid;
253         NTSTATUS status;
254
255         p = strchr_m(name, '\\');
256         if (p != NULL) {
257                 domain = talloc_strndup(mem_ctx, name, p-name);
258                 if (!domain) {
259                         return NT_STATUS_NO_MEMORY;
260                 }
261                 username = p + 1;
262         } else if (strchr_m(name, '@')) {
263                 status = crack_name_to_nt4_name(mem_ctx, ev_ctx, lp_ctx, DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL, name, &domain, &username);
264                 if (!NT_STATUS_IS_OK(status)) {
265                         DEBUG(3, ("Failed to crack name %s into an NT4 name: %s\n", name, nt_errstr(status)));
266                         return status;
267                 }
268         } else {
269                 domain = NULL;
270                 username = name;
271         }
272         
273         if (!domain) {
274                 /* Look up table of well known names */
275                 status = lookup_well_known_names(mem_ctx, NULL, username, authority_name, sid, rtype);
276                 if (NT_STATUS_IS_OK(status)) {
277                         return NT_STATUS_OK;
278                 }
279
280                 if (strcasecmp_m(username, NAME_NT_AUTHORITY) == 0) { 
281                         *authority_name = NAME_NT_AUTHORITY;
282                         *sid =  dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY);
283                         *rtype = SID_NAME_DOMAIN;
284                         return NT_STATUS_OK;
285                 }
286                 if (strcasecmp_m(username, NAME_BUILTIN) == 0) { 
287                         *authority_name = NAME_BUILTIN;
288                         *sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN);
289                         *rtype = SID_NAME_DOMAIN;
290                         return NT_STATUS_OK;
291                 }
292                 if (strcasecmp_m(username, state->domain_dns) == 0) { 
293                         *authority_name = state->domain_name;
294                         *sid =  state->domain_sid;
295                         *rtype = SID_NAME_DOMAIN;
296                         return NT_STATUS_OK;
297                 }
298                 if (strcasecmp_m(username, state->domain_name) == 0) { 
299                         *authority_name = state->domain_name;
300                         *sid =  state->domain_sid;
301                         *rtype = SID_NAME_DOMAIN;
302                         return NT_STATUS_OK;
303                 }
304                 
305                 /* Perhaps this is a well known user? */
306                 name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_NT_AUTHORITY, username);
307                 if (!name) {
308                         return NT_STATUS_NO_MEMORY;
309                 }
310                 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype);
311                 if (NT_STATUS_IS_OK(status)) {
312                         return status;
313                 }
314
315                 /* Perhaps this is a BUILTIN user? */
316                 name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_BUILTIN, username);
317                 if (!name) {
318                         return NT_STATUS_NO_MEMORY;
319                 }
320                 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype);
321                 if (NT_STATUS_IS_OK(status)) {
322                         return status;
323                 }
324
325                 /* OK, I give up - perhaps we need to assume the user is in our domain? */
326                 name = talloc_asprintf(mem_ctx, "%s\\%s", state->domain_name, username);
327                 if (!name) {
328                         return NT_STATUS_NO_MEMORY;
329                 }
330                 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype);
331                 if (NT_STATUS_IS_OK(status)) {
332                         return status;
333                 }
334
335                 return STATUS_SOME_UNMAPPED;
336         } else if (strcasecmp_m(domain, NAME_NT_AUTHORITY) == 0) {
337                 if (!*username) {
338                         *authority_name = NAME_NT_AUTHORITY;
339                         *sid = dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY);
340                         *rtype = SID_NAME_DOMAIN;
341                         return NT_STATUS_OK;
342                 }
343
344                 /* Look up table of well known names */
345                 return lookup_well_known_names(mem_ctx, domain, username, authority_name, 
346                                                sid, rtype);
347         } else if (strcasecmp_m(domain, NAME_BUILTIN) == 0) {
348                 *authority_name = NAME_BUILTIN;
349                 domain_dn = state->builtin_dn;
350         } else if (strcasecmp_m(domain, state->domain_dns) == 0) { 
351                 *authority_name = state->domain_name;
352                 domain_dn = state->domain_dn;
353         } else if (strcasecmp_m(domain, state->domain_name) == 0) { 
354                 *authority_name = state->domain_name;
355                 domain_dn = state->domain_dn;
356         } else {
357                 /* Not local, need to ask winbind in future */
358                 return STATUS_SOME_UNMAPPED;
359         }
360
361         ret = gendb_search_dn(state->sam_ldb, mem_ctx, domain_dn, &res, attrs);
362         if (ret == 1) {
363                 domain_sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
364                 if (domain_sid == NULL) {
365                         return NT_STATUS_INVALID_SID;
366                 }
367         } else {
368                 return NT_STATUS_INVALID_SID;
369         }
370
371         if (!*username) {
372                 *sid = domain_sid;
373                 *rtype = SID_NAME_DOMAIN;
374                 return NT_STATUS_OK;
375         }
376         
377         ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs, 
378                            "(&(sAMAccountName=%s)(objectSid=*))", 
379                            ldb_binary_encode_string(mem_ctx, username));
380         if (ret == -1) {
381                 return NT_STATUS_INVALID_SID;
382         }
383
384         for (i=0; i < ret; i++) {
385                 *sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
386                 if (*sid == NULL) {
387                         return NT_STATUS_INVALID_SID;
388                 }
389
390                 /* Check that this is in the domain */
391                 if (!dom_sid_in_domain(domain_sid, *sid)) {
392                         continue;
393                 }
394
395                 atype = samdb_result_uint(res[i], "sAMAccountType", 0);
396                         
397                 *rtype = ds_atype_map(atype);
398                 if (*rtype == SID_NAME_UNKNOWN) {
399                         return STATUS_SOME_UNMAPPED;
400                 }
401
402                 return NT_STATUS_OK;
403         }
404
405         /* need to check for an allocated sid */
406
407         return NT_STATUS_INVALID_SID;
408 }
409
410
411 /*
412   add to the lsa_RefDomainList for LookupSids and LookupNames
413 */
414 static NTSTATUS dcesrv_lsa_authority_list(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx, 
415                                           enum lsa_SidType rtype,
416                                           const char *authority_name,
417                                           struct dom_sid *sid, 
418                                           struct lsa_RefDomainList *domains,
419                                           uint32_t *sid_index)
420 {
421         struct dom_sid *authority_sid;
422         int i;
423
424         if (rtype != SID_NAME_DOMAIN) {
425                 authority_sid = dom_sid_dup(mem_ctx, sid);
426                 if (authority_sid == NULL) {
427                         return NT_STATUS_NO_MEMORY;
428                 }
429                 authority_sid->num_auths--;
430         } else {
431                 authority_sid = sid;
432         }
433
434         /* see if we've already done this authority name */
435         for (i=0;i<domains->count;i++) {
436                 if (strcasecmp_m(authority_name, domains->domains[i].name.string) == 0) {
437                         *sid_index = i;
438                         return NT_STATUS_OK;
439                 }
440         }
441
442         domains->domains = talloc_realloc(domains, 
443                                           domains->domains,
444                                           struct lsa_DomainInfo,
445                                           domains->count+1);
446         if (domains->domains == NULL) {
447                 return NT_STATUS_NO_MEMORY;
448         }
449         domains->domains[i].name.string = authority_name;
450         domains->domains[i].sid         = authority_sid;
451         domains->count++;
452         domains->max_size = LSA_REF_DOMAIN_LIST_MULTIPLIER * domains->count;
453         *sid_index = i;
454         
455         return NT_STATUS_OK;
456 }
457
458 /*
459   lookup a name for 1 SID
460 */
461 static NTSTATUS dcesrv_lsa_lookup_sid(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
462                                       struct dom_sid *sid, const char *sid_str,
463                                       const char **authority_name, 
464                                       const char **name, enum lsa_SidType *rtype)
465 {
466         NTSTATUS status;
467         int ret;
468         uint32_t atype;
469         struct ldb_message **res;
470         struct ldb_dn *domain_dn;
471         const char * const attrs[] = { "sAMAccountName", "sAMAccountType", "cn", NULL};
472
473         status = lookup_well_known_sids(mem_ctx, sid_str, authority_name, name, rtype);
474         if (NT_STATUS_IS_OK(status)) {
475                 return status;
476         }
477
478         if (dom_sid_in_domain(state->domain_sid, sid)) {
479                 *authority_name = state->domain_name;
480                 domain_dn = state->domain_dn;
481         } else if (dom_sid_in_domain(state->builtin_sid, sid)) {
482                 *authority_name = NAME_BUILTIN;
483                 domain_dn = state->builtin_dn;
484         } else {
485                 /* Not well known, our domain or built in */
486
487                 /* In future, we must look at SID histories, and at trusted domains via winbind */
488
489                 return NT_STATUS_NOT_FOUND;
490         }
491
492         ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs, 
493                            "objectSid=%s", ldap_encode_ndr_dom_sid(mem_ctx, sid));
494         if (ret == 1) {
495                 *name = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
496                 if (!*name) {
497                         *name = ldb_msg_find_attr_as_string(res[0], "cn", NULL);
498                         if (!*name) {
499                                 *name = talloc_strdup(mem_ctx, sid_str);
500                                 NT_STATUS_HAVE_NO_MEMORY(*name);
501                         }
502                 }
503
504                 atype = samdb_result_uint(res[0], "sAMAccountType", 0);
505
506                 *rtype = ds_atype_map(atype);
507
508                 return NT_STATUS_OK;
509         }
510
511         /* need to re-add a check for an allocated sid */
512
513         return NT_STATUS_NOT_FOUND;
514 }
515
516
517 /*
518   lsa_LookupSids2
519 */
520 NTSTATUS dcesrv_lsa_LookupSids2(struct dcesrv_call_state *dce_call,
521                                 TALLOC_CTX *mem_ctx,
522                                 struct lsa_LookupSids2 *r)
523 {
524         struct lsa_policy_state *state;
525         struct lsa_RefDomainList *domains = NULL;
526         int i;
527         NTSTATUS status = NT_STATUS_OK;
528
529         if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
530             r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
531                 return NT_STATUS_INVALID_PARAMETER;
532         }
533
534         *r->out.domains = NULL;
535
536         /* NOTE: the WSPP test suite tries SIDs with invalid revision numbers,
537            and expects NT_STATUS_INVALID_PARAMETER back - we just treat it as 
538            an unknown SID. We could add a SID validator here. (tridge) 
539            MS-DTYP 2.4.2
540         */
541
542         status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
543         if (!NT_STATUS_IS_OK(status)) {
544                 return status;
545         }
546
547         domains = talloc_zero(r->out.domains,  struct lsa_RefDomainList);
548         if (domains == NULL) {
549                 return NT_STATUS_NO_MEMORY;
550         }
551         *r->out.domains = domains;
552
553         r->out.names = talloc_zero(mem_ctx,  struct lsa_TransNameArray2);
554         if (r->out.names == NULL) {
555                 return NT_STATUS_NO_MEMORY;
556         }
557
558         *r->out.count = 0;
559
560         r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName2, 
561                                              r->in.sids->num_sids);
562         if (r->out.names->names == NULL) {
563                 return NT_STATUS_NO_MEMORY;
564         }
565
566         for (i=0;i<r->in.sids->num_sids;i++) {
567                 struct dom_sid *sid = r->in.sids->sids[i].sid;
568                 char *sid_str = dom_sid_string(mem_ctx, sid);
569                 const char *name, *authority_name;
570                 enum lsa_SidType rtype;
571                 uint32_t sid_index;
572                 NTSTATUS status2;
573
574                 r->out.names->count++;
575
576                 r->out.names->names[i].sid_type    = SID_NAME_UNKNOWN;
577                 r->out.names->names[i].name.string = sid_str;
578                 r->out.names->names[i].sid_index   = 0xFFFFFFFF;
579                 r->out.names->names[i].unknown     = 0;
580
581                 if (sid_str == NULL) {
582                         r->out.names->names[i].name.string = "(SIDERROR)";
583                         status = STATUS_SOME_UNMAPPED;
584                         continue;
585                 }
586
587                 status2 = dcesrv_lsa_lookup_sid(state, mem_ctx, sid, sid_str, 
588                                                 &authority_name, &name, &rtype);
589                 if (!NT_STATUS_IS_OK(status2)) {
590                         status = STATUS_SOME_UNMAPPED;
591                         continue;
592                 }
593
594                 /* set up the authority table */
595                 status2 = dcesrv_lsa_authority_list(state, mem_ctx, rtype, 
596                                                     authority_name, sid, 
597                                                     domains, &sid_index);
598                 if (!NT_STATUS_IS_OK(status2)) {
599                         continue;
600                 }
601
602                 r->out.names->names[i].sid_type    = rtype;
603                 r->out.names->names[i].name.string = name;
604                 r->out.names->names[i].sid_index   = sid_index;
605                 r->out.names->names[i].unknown     = 0;
606
607                 (*r->out.count)++;
608         }
609
610         if (*r->out.count == 0) {
611                 return NT_STATUS_NONE_MAPPED;
612         }
613         if (*r->out.count != r->in.sids->num_sids) {
614                 return STATUS_SOME_UNMAPPED;
615         }
616
617         return NT_STATUS_OK;
618 }
619
620
621 /*
622   lsa_LookupSids3
623
624   Identical to LookupSids2, but doesn't take a policy handle
625   
626 */
627 NTSTATUS dcesrv_lsa_LookupSids3(struct dcesrv_call_state *dce_call,
628                                 TALLOC_CTX *mem_ctx,
629                                 struct lsa_LookupSids3 *r)
630 {
631         struct lsa_LookupSids2 r2;
632         struct lsa_OpenPolicy2 pol;
633         NTSTATUS status;
634         struct dcesrv_handle *h;
635
636         ZERO_STRUCT(r2);
637         
638         /* No policy handle on the wire, so make one up here */
639         r2.in.handle = talloc(mem_ctx, struct policy_handle);
640         if (!r2.in.handle) {
641                 return NT_STATUS_NO_MEMORY;
642         }
643
644         pol.out.handle = r2.in.handle;
645         pol.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
646         pol.in.attr = NULL;
647         pol.in.system_name = NULL;
648         status = dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &pol);
649         if (!NT_STATUS_IS_OK(status)) {
650                 return status;
651         }
652
653         /* ensure this handle goes away at the end of this call */
654         DCESRV_PULL_HANDLE(h, r2.in.handle, LSA_HANDLE_POLICY);
655         talloc_steal(mem_ctx, h);
656
657         r2.in.sids     = r->in.sids;
658         r2.in.names    = r->in.names;
659         r2.in.level    = r->in.level;
660         r2.in.count    = r->in.count;
661         r2.in.unknown1 = r->in.unknown1;
662         r2.in.unknown2 = r->in.unknown2;
663         r2.out.count   = r->out.count;
664         r2.out.names   = r->out.names;
665         r2.out.domains = r->out.domains;
666
667         status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
668
669         r->out.domains = r2.out.domains;
670         r->out.names   = r2.out.names;
671         r->out.count   = r2.out.count;
672
673         return status;
674 }
675
676
677 /* 
678   lsa_LookupSids 
679 */
680 NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
681                                struct lsa_LookupSids *r)
682 {
683         struct lsa_LookupSids2 r2;
684         NTSTATUS status;
685         int i;
686
687         ZERO_STRUCT(r2);
688
689         r2.in.handle   = r->in.handle;
690         r2.in.sids     = r->in.sids;
691         r2.in.names    = NULL;
692         r2.in.level    = r->in.level;
693         r2.in.count    = r->in.count;
694         r2.in.unknown1 = 0;
695         r2.in.unknown2 = 0;
696         r2.out.count   = r->out.count;
697         r2.out.names   = NULL;
698         r2.out.domains = r->out.domains;
699
700         status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
701         /* we deliberately don't check for error from the above,
702            as even on error we are supposed to return the names  */
703
704         r->out.domains = r2.out.domains;
705         if (!r2.out.names) {
706                 r->out.names = NULL;
707                 return status;
708         }
709
710         r->out.names = talloc(mem_ctx, struct lsa_TransNameArray);
711         if (r->out.names == NULL) {
712                 return NT_STATUS_NO_MEMORY;
713         }
714         r->out.names->count = r2.out.names->count;
715         r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName, 
716                                              r->out.names->count);
717         if (r->out.names->names == NULL) {
718                 return NT_STATUS_NO_MEMORY;
719         }
720         for (i=0;i<r->out.names->count;i++) {
721                 r->out.names->names[i].sid_type    = r2.out.names->names[i].sid_type;
722                 r->out.names->names[i].name.string = r2.out.names->names[i].name.string;
723                 r->out.names->names[i].sid_index   = r2.out.names->names[i].sid_index;
724         }
725
726         return status;
727 }
728
729
730 /*
731   lsa_LookupNames3
732 */
733 NTSTATUS dcesrv_lsa_LookupNames3(struct dcesrv_call_state *dce_call,
734                                  TALLOC_CTX *mem_ctx,
735                                  struct lsa_LookupNames3 *r)
736 {
737         struct lsa_policy_state *policy_state;
738         struct dcesrv_handle *policy_handle;
739         int i;
740         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
741         struct lsa_RefDomainList *domains;
742
743         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
744
745         if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
746             r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
747                 return NT_STATUS_INVALID_PARAMETER;
748         }
749
750         policy_state = policy_handle->data;
751
752         *r->out.domains = NULL;
753
754         domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
755         if (domains == NULL) {
756                 return NT_STATUS_NO_MEMORY;
757         }
758         *r->out.domains = domains;
759
760         r->out.sids = talloc_zero(mem_ctx,  struct lsa_TransSidArray3);
761         if (r->out.sids == NULL) {
762                 return NT_STATUS_NO_MEMORY;
763         }
764
765         *r->out.count = 0;
766
767         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid3, 
768                                            r->in.num_names);
769         if (r->out.sids->sids == NULL) {
770                 return NT_STATUS_NO_MEMORY;
771         }
772
773         for (i=0;i<r->in.num_names;i++) {
774                 const char *name = r->in.names[i].string;
775                 const char *authority_name;
776                 struct dom_sid *sid;
777                 uint32_t sid_index;
778                 enum lsa_SidType rtype;
779                 NTSTATUS status2;
780
781                 r->out.sids->count++;
782
783                 r->out.sids->sids[i].sid_type    = SID_NAME_UNKNOWN;
784                 r->out.sids->sids[i].sid         = NULL;
785                 r->out.sids->sids[i].sid_index   = 0xFFFFFFFF;
786                 r->out.sids->sids[i].flags       = 0;
787
788                 status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, policy_state, mem_ctx, name, &authority_name, &sid, &rtype);
789                 if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) {
790                         continue;
791                 }
792
793                 status2 = dcesrv_lsa_authority_list(policy_state, mem_ctx, rtype, authority_name, 
794                                                     sid, domains, &sid_index);
795                 if (!NT_STATUS_IS_OK(status2)) {
796                         continue;
797                 }
798
799                 r->out.sids->sids[i].sid_type    = rtype;
800                 r->out.sids->sids[i].sid         = sid;
801                 r->out.sids->sids[i].sid_index   = sid_index;
802                 r->out.sids->sids[i].flags       = 0;
803
804                 (*r->out.count)++;
805         }
806         
807         if (*r->out.count == 0) {
808                 return NT_STATUS_NONE_MAPPED;
809         }
810         if (*r->out.count != r->in.num_names) {
811                 return STATUS_SOME_UNMAPPED;
812         }
813
814         return NT_STATUS_OK;
815 }
816
817 /* 
818   lsa_LookupNames4
819
820   Identical to LookupNames3, but doesn't take a policy handle
821   
822 */
823 NTSTATUS dcesrv_lsa_LookupNames4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
824                                  struct lsa_LookupNames4 *r)
825 {
826         struct lsa_LookupNames3 r2;
827         struct lsa_OpenPolicy2 pol;
828         NTSTATUS status;
829         struct dcesrv_handle *h;
830
831         ZERO_STRUCT(r2);
832
833         /* No policy handle on the wire, so make one up here */
834         r2.in.handle = talloc(mem_ctx, struct policy_handle);
835         if (!r2.in.handle) {
836                 return NT_STATUS_NO_MEMORY;
837         }
838
839         pol.out.handle = r2.in.handle;
840         pol.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
841         pol.in.attr = NULL;
842         pol.in.system_name = NULL;
843         status = dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &pol);
844         if (!NT_STATUS_IS_OK(status)) {
845                 return status;
846         }
847
848         /* ensure this handle goes away at the end of this call */
849         DCESRV_PULL_HANDLE(h, r2.in.handle, LSA_HANDLE_POLICY);
850         talloc_steal(mem_ctx, h);
851
852         r2.in.num_names = r->in.num_names;
853         r2.in.names = r->in.names;
854         r2.in.level = r->in.level;
855         r2.in.sids = r->in.sids;
856         r2.in.count = r->in.count;
857         r2.in.lookup_options = r->in.lookup_options;
858         r2.in.client_revision = r->in.client_revision;
859         r2.out.domains = r->out.domains;
860         r2.out.sids = r->out.sids;
861         r2.out.count = r->out.count;
862         
863         status = dcesrv_lsa_LookupNames3(dce_call, mem_ctx, &r2);
864         
865         r->out.domains = r2.out.domains;
866         r->out.sids = r2.out.sids;
867         r->out.count = r2.out.count;
868         return status;
869 }
870
871 /*
872   lsa_LookupNames2
873 */
874 NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call,
875                                  TALLOC_CTX *mem_ctx,
876                                  struct lsa_LookupNames2 *r)
877 {
878         struct lsa_policy_state *state;
879         struct dcesrv_handle *h;
880         int i;
881         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
882         struct lsa_RefDomainList *domains;
883
884         *r->out.domains = NULL;
885
886         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
887
888         if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
889             r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
890                 return NT_STATUS_INVALID_PARAMETER;
891         }
892
893         state = h->data;
894
895         domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
896         if (domains == NULL) {
897                 return NT_STATUS_NO_MEMORY;
898         }
899         *r->out.domains = domains;
900
901         r->out.sids = talloc_zero(mem_ctx,  struct lsa_TransSidArray2);
902         if (r->out.sids == NULL) {
903                 return NT_STATUS_NO_MEMORY;
904         }
905
906         *r->out.count = 0;
907
908         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid2, 
909                                            r->in.num_names);
910         if (r->out.sids->sids == NULL) {
911                 return NT_STATUS_NO_MEMORY;
912         }
913
914         for (i=0;i<r->in.num_names;i++) {
915                 const char *name = r->in.names[i].string;
916                 const char *authority_name;
917                 struct dom_sid *sid;
918                 uint32_t rtype, sid_index;
919                 NTSTATUS status2;
920
921                 r->out.sids->count++;
922
923                 r->out.sids->sids[i].sid_type    = SID_NAME_UNKNOWN;
924                 /* MS-LSAT 3.1.4.7 - rid zero is considered equivalent
925                    to sid NULL - so we should return 0 rid for
926                    unmapped entries */
927                 r->out.sids->sids[i].rid         = 0;
928                 r->out.sids->sids[i].sid_index   = 0xFFFFFFFF;
929                 r->out.sids->sids[i].unknown     = 0;
930
931                 status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, state, mem_ctx, name, 
932                                                  &authority_name, &sid, &rtype);
933                 if (!NT_STATUS_IS_OK(status2)) {
934                         continue;
935                 }
936
937                 status2 = dcesrv_lsa_authority_list(state, mem_ctx, rtype, authority_name, 
938                                                     sid, domains, &sid_index);
939                 if (!NT_STATUS_IS_OK(status2)) {
940                         continue;
941                 }
942
943                 r->out.sids->sids[i].sid_type    = rtype;
944                 r->out.sids->sids[i].rid         = sid->sub_auths[sid->num_auths-1];
945                 r->out.sids->sids[i].sid_index   = sid_index;
946                 r->out.sids->sids[i].unknown     = 0;
947
948                 (*r->out.count)++;
949         }
950         
951         if (*r->out.count == 0) {
952                 return NT_STATUS_NONE_MAPPED;
953         }
954         if (*r->out.count != r->in.num_names) {
955                 return STATUS_SOME_UNMAPPED;
956         }
957
958         return NT_STATUS_OK;
959 }
960
961 /* 
962   lsa_LookupNames 
963 */
964 NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
965                        struct lsa_LookupNames *r)
966 {
967         struct lsa_LookupNames2 r2;
968         NTSTATUS status;
969         int i;
970
971         ZERO_STRUCT(r2);
972
973         r2.in.handle    = r->in.handle;
974         r2.in.num_names = r->in.num_names;
975         r2.in.names     = r->in.names;
976         r2.in.sids      = NULL;
977         r2.in.level     = r->in.level;
978         r2.in.count     = r->in.count;
979         r2.in.lookup_options = 0;
980         r2.in.client_revision = 0;
981         r2.out.count    = r->out.count;
982         r2.out.domains  = r->out.domains;
983
984         status = dcesrv_lsa_LookupNames2(dce_call, mem_ctx, &r2);
985         if (r2.out.sids == NULL) {
986                 return status;
987         }
988
989         r->out.sids = talloc(mem_ctx, struct lsa_TransSidArray);
990         if (r->out.sids == NULL) {
991                 return NT_STATUS_NO_MEMORY;
992         }
993         r->out.sids->count = r2.out.sids->count;
994         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid, 
995                                            r->out.sids->count);
996         if (r->out.sids->sids == NULL) {
997                 return NT_STATUS_NO_MEMORY;
998         }
999         for (i=0;i<r->out.sids->count;i++) {
1000                 r->out.sids->sids[i].sid_type    = r2.out.sids->sids[i].sid_type;
1001                 r->out.sids->sids[i].rid         = r2.out.sids->sids[i].rid;
1002                 r->out.sids->sids[i].sid_index   = r2.out.sids->sids[i].sid_index;
1003         }
1004
1005         return status;
1006 }
1007