s4-loadparm: 2nd half of lp_ to lpcfg_ conversion
[garming/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         enum lsa_SidType 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, enum lsa_SidType *rtype)
197 {
198         unsigned 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, enum lsa_SidType *rtype) 
223 {
224         unsigned 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                                        uint32_t *rid)
245 {
246         int ret, i;
247         uint32_t atype;
248         struct ldb_message **res;
249         const char * const attrs[] = { "objectSid", "sAMAccountType", NULL};
250         const char *p;
251         const char *domain;
252         const char *username;
253         struct ldb_dn *domain_dn;
254         struct dom_sid *domain_sid;
255         NTSTATUS status;
256
257         p = strchr_m(name, '\\');
258         if (p != NULL) {
259                 domain = talloc_strndup(mem_ctx, name, p-name);
260                 if (!domain) {
261                         return NT_STATUS_NO_MEMORY;
262                 }
263                 username = p + 1;
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)));
268                         return status;
269                 }
270         } else {
271                 domain = NULL;
272                 username = name;
273         }
274         
275         if (!domain) {
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);
280                         return NT_STATUS_OK;
281                 }
282
283                 if (username == NULL) {
284                         *authority_name = NAME_BUILTIN;
285                         *sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN);
286                         *rtype = SID_NAME_DOMAIN;
287                         *rid = 0xFFFFFFFF;
288                         return NT_STATUS_OK;
289                 }
290
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);
296                         return NT_STATUS_OK;
297                 }
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;
302                         *rid = 0xFFFFFFFF;
303                         return NT_STATUS_OK;
304                 }
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;
309                         *rid = 0xFFFFFFFF;
310                         return NT_STATUS_OK;
311                 }
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;
316                         *rid = 0xFFFFFFFF;
317                         return NT_STATUS_OK;
318                 }
319                 
320                 /* Perhaps this is a well known user? */
321                 name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_NT_AUTHORITY, username);
322                 if (!name) {
323                         return NT_STATUS_NO_MEMORY;
324                 }
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)) {
327                         return status;
328                 }
329
330                 /* Perhaps this is a BUILTIN user? */
331                 name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_BUILTIN, username);
332                 if (!name) {
333                         return NT_STATUS_NO_MEMORY;
334                 }
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)) {
337                         return status;
338                 }
339
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);
342                 if (!name) {
343                         return NT_STATUS_NO_MEMORY;
344                 }
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)) {
347                         return status;
348                 }
349
350                 return STATUS_SOME_UNMAPPED;
351         } else if (strcasecmp_m(domain, NAME_NT_AUTHORITY) == 0) {
352                 if (!*username) {
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);
357                         return NT_STATUS_OK;
358                 }
359
360                 /* Look up table of well known names */
361                 status = lookup_well_known_names(mem_ctx, domain, username, authority_name, 
362                                                  sid, rtype);
363                 if (NT_STATUS_IS_OK(status)) {
364                         dom_sid_split_rid(NULL, *sid, NULL, rid);
365                 }
366                 return status;
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;
376         } else {
377                 /* Not local, need to ask winbind in future */
378                 return STATUS_SOME_UNMAPPED;
379         }
380
381         ret = gendb_search_dn(state->sam_ldb, mem_ctx, domain_dn, &res, attrs);
382         if (ret != 1) {
383                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
384         }
385         domain_sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
386         if (domain_sid == NULL) {
387                 return NT_STATUS_INVALID_SID;
388         }
389
390         if (!*username) {
391                 *sid = domain_sid;
392                 *rtype = SID_NAME_DOMAIN;
393                 *rid = 0xFFFFFFFF;
394                 return NT_STATUS_OK;
395         }
396         
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));
400         if (ret < 0) {
401                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
402         }
403
404         for (i=0; i < ret; i++) {
405                 *sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
406                 if (*sid == NULL) {
407                         return NT_STATUS_INVALID_SID;
408                 }
409
410                 /* Check that this is in the domain */
411                 if (!dom_sid_in_domain(domain_sid, *sid)) {
412                         continue;
413                 }
414
415                 atype = samdb_result_uint(res[i], "sAMAccountType", 0);
416                         
417                 *rtype = ds_atype_map(atype);
418                 if (*rtype == SID_NAME_UNKNOWN) {
419                         return STATUS_SOME_UNMAPPED;
420                 }
421
422                 dom_sid_split_rid(NULL, *sid, NULL, rid);
423                 return NT_STATUS_OK;
424         }
425
426         /* need to check for an allocated sid */
427
428         return NT_STATUS_INVALID_SID;
429 }
430
431
432 /*
433   add to the lsa_RefDomainList for LookupSids and LookupNames
434 */
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,
438                                           struct dom_sid *sid, 
439                                           struct lsa_RefDomainList *domains,
440                                           uint32_t *sid_index)
441 {
442         struct dom_sid *authority_sid;
443         uint32_t i;
444
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;
449                 }
450                 authority_sid->num_auths--;
451         } else {
452                 authority_sid = sid;
453         }
454
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) {
458                         *sid_index = i;
459                         return NT_STATUS_OK;
460                 }
461         }
462
463         domains->domains = talloc_realloc(domains, 
464                                           domains->domains,
465                                           struct lsa_DomainInfo,
466                                           domains->count+1);
467         if (domains->domains == NULL) {
468                 return NT_STATUS_NO_MEMORY;
469         }
470         domains->domains[i].name.string = authority_name;
471         domains->domains[i].sid         = authority_sid;
472         domains->count++;
473         domains->max_size = LSA_REF_DOMAIN_LIST_MULTIPLIER * domains->count;
474         *sid_index = i;
475         
476         return NT_STATUS_OK;
477 }
478
479 /*
480   lookup a name for 1 SID
481 */
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)
486 {
487         NTSTATUS status;
488         int ret;
489         uint32_t atype;
490         struct ldb_message **res;
491         struct ldb_dn *domain_dn;
492         const char * const attrs[] = { "sAMAccountName", "sAMAccountType", "cn", NULL};
493
494         status = lookup_well_known_sids(mem_ctx, sid_str, authority_name, name, rtype);
495         if (NT_STATUS_IS_OK(status)) {
496                 return status;
497         }
498
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;
505         } else {
506                 /* Not well known, our domain or built in */
507
508                 /* In future, we must look at SID histories, and at trusted domains via winbind */
509
510                 return NT_STATUS_NOT_FOUND;
511         }
512
513         /* need to re-add a check for an allocated sid */
514
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;
519         }
520         if (ret == 0) {
521                 return NT_STATUS_NOT_FOUND;
522         }
523
524         *name = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
525         if (!*name) {
526                 *name = ldb_msg_find_attr_as_string(res[0], "cn", NULL);
527                 if (!*name) {
528                         *name = talloc_strdup(mem_ctx, sid_str);
529                         NT_STATUS_HAVE_NO_MEMORY(*name);
530                 }
531         }
532
533         atype = samdb_result_uint(res[0], "sAMAccountType", 0);
534         *rtype = ds_atype_map(atype);
535
536         return NT_STATUS_OK;
537 }
538
539
540 /*
541   lsa_LookupSids2
542 */
543 NTSTATUS dcesrv_lsa_LookupSids2(struct dcesrv_call_state *dce_call,
544                                 TALLOC_CTX *mem_ctx,
545                                 struct lsa_LookupSids2 *r)
546 {
547         struct lsa_policy_state *state;
548         struct lsa_RefDomainList *domains = NULL;
549         uint32_t i;
550         NTSTATUS status = NT_STATUS_OK;
551
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;
555         }
556
557         *r->out.domains = NULL;
558
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) 
562            MS-DTYP 2.4.2
563         */
564
565         status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
566         if (!NT_STATUS_IS_OK(status)) {
567                 return status;
568         }
569
570         domains = talloc_zero(r->out.domains,  struct lsa_RefDomainList);
571         if (domains == NULL) {
572                 return NT_STATUS_NO_MEMORY;
573         }
574         *r->out.domains = domains;
575
576         r->out.names = talloc_zero(mem_ctx,  struct lsa_TransNameArray2);
577         if (r->out.names == NULL) {
578                 return NT_STATUS_NO_MEMORY;
579         }
580
581         *r->out.count = 0;
582
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;
587         }
588
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;
594                 uint32_t sid_index;
595                 NTSTATUS status2;
596
597                 r->out.names->count++;
598
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;
603
604                 if (sid_str == NULL) {
605                         r->out.names->names[i].name.string = "(SIDERROR)";
606                         status = STATUS_SOME_UNMAPPED;
607                         continue;
608                 }
609
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;
614                         continue;
615                 }
616
617                 /* set up the authority table */
618                 status2 = dcesrv_lsa_authority_list(state, mem_ctx, rtype, 
619                                                     authority_name, sid, 
620                                                     domains, &sid_index);
621                 if (!NT_STATUS_IS_OK(status2)) {
622                         continue;
623                 }
624
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;
629
630                 (*r->out.count)++;
631         }
632
633         if (*r->out.count == 0) {
634                 return NT_STATUS_NONE_MAPPED;
635         }
636         if (*r->out.count != r->in.sids->num_sids) {
637                 return STATUS_SOME_UNMAPPED;
638         }
639
640         return NT_STATUS_OK;
641 }
642
643
644 /*
645   lsa_LookupSids3
646
647   Identical to LookupSids2, but doesn't take a policy handle
648   
649 */
650 NTSTATUS dcesrv_lsa_LookupSids3(struct dcesrv_call_state *dce_call,
651                                 TALLOC_CTX *mem_ctx,
652                                 struct lsa_LookupSids3 *r)
653 {
654         struct lsa_LookupSids2 r2;
655         struct lsa_OpenPolicy2 pol;
656         NTSTATUS status;
657         struct dcesrv_handle *h;
658
659         ZERO_STRUCT(r2);
660         
661         /* No policy handle on the wire, so make one up here */
662         r2.in.handle = talloc(mem_ctx, struct policy_handle);
663         if (!r2.in.handle) {
664                 return NT_STATUS_NO_MEMORY;
665         }
666
667         pol.out.handle = r2.in.handle;
668         pol.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
669         pol.in.attr = NULL;
670         pol.in.system_name = NULL;
671         status = dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &pol);
672         if (!NT_STATUS_IS_OK(status)) {
673                 return status;
674         }
675
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);
679
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;
689
690         status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
691
692         r->out.domains = r2.out.domains;
693         r->out.names   = r2.out.names;
694         r->out.count   = r2.out.count;
695
696         return status;
697 }
698
699
700 /* 
701   lsa_LookupSids 
702 */
703 NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
704                                struct lsa_LookupSids *r)
705 {
706         struct lsa_LookupSids2 r2;
707         NTSTATUS status;
708         uint32_t i;
709
710         ZERO_STRUCT(r2);
711
712         r2.in.handle   = r->in.handle;
713         r2.in.sids     = r->in.sids;
714         r2.in.names    = NULL;
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;
720         r2.out.names   = NULL;
721         r2.out.domains = r->out.domains;
722
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  */
726
727         r->out.domains = r2.out.domains;
728         if (!r2.out.names) {
729                 r->out.names = NULL;
730                 return status;
731         }
732
733         r->out.names = talloc(mem_ctx, struct lsa_TransNameArray);
734         if (r->out.names == NULL) {
735                 return NT_STATUS_NO_MEMORY;
736         }
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;
742         }
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;
747         }
748
749         return status;
750 }
751
752
753 /*
754   lsa_LookupNames3
755 */
756 NTSTATUS dcesrv_lsa_LookupNames3(struct dcesrv_call_state *dce_call,
757                                  TALLOC_CTX *mem_ctx,
758                                  struct lsa_LookupNames3 *r)
759 {
760         struct lsa_policy_state *policy_state;
761         struct dcesrv_handle *policy_handle;
762         uint32_t i;
763         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
764         struct lsa_RefDomainList *domains;
765
766         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
767
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;
771         }
772
773         policy_state = policy_handle->data;
774
775         *r->out.domains = NULL;
776
777         domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
778         if (domains == NULL) {
779                 return NT_STATUS_NO_MEMORY;
780         }
781         *r->out.domains = domains;
782
783         r->out.sids = talloc_zero(mem_ctx,  struct lsa_TransSidArray3);
784         if (r->out.sids == NULL) {
785                 return NT_STATUS_NO_MEMORY;
786         }
787
788         *r->out.count = 0;
789
790         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid3, 
791                                            r->in.num_names);
792         if (r->out.sids->sids == NULL) {
793                 return NT_STATUS_NO_MEMORY;
794         }
795
796         for (i=0;i<r->in.num_names;i++) {
797                 const char *name = r->in.names[i].string;
798                 const char *authority_name;
799                 struct dom_sid *sid;
800                 uint32_t sid_index, rid;
801                 enum lsa_SidType rtype;
802                 NTSTATUS status2;
803
804                 r->out.sids->count++;
805
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;
810
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) {
814                         continue;
815                 }
816
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)) {
820                         continue;
821                 }
822
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;
827
828                 (*r->out.count)++;
829         }
830         
831         if (*r->out.count == 0) {
832                 return NT_STATUS_NONE_MAPPED;
833         }
834         if (*r->out.count != r->in.num_names) {
835                 return STATUS_SOME_UNMAPPED;
836         }
837
838         return NT_STATUS_OK;
839 }
840
841 /* 
842   lsa_LookupNames4
843
844   Identical to LookupNames3, but doesn't take a policy handle
845   
846 */
847 NTSTATUS dcesrv_lsa_LookupNames4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
848                                  struct lsa_LookupNames4 *r)
849 {
850         struct lsa_LookupNames3 r2;
851         struct lsa_OpenPolicy2 pol;
852         NTSTATUS status;
853         struct dcesrv_handle *h;
854
855         ZERO_STRUCT(r2);
856
857         /* No policy handle on the wire, so make one up here */
858         r2.in.handle = talloc(mem_ctx, struct policy_handle);
859         if (!r2.in.handle) {
860                 return NT_STATUS_NO_MEMORY;
861         }
862
863         pol.out.handle = r2.in.handle;
864         pol.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
865         pol.in.attr = NULL;
866         pol.in.system_name = NULL;
867         status = dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &pol);
868         if (!NT_STATUS_IS_OK(status)) {
869                 return status;
870         }
871
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);
875
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;
886         
887         status = dcesrv_lsa_LookupNames3(dce_call, mem_ctx, &r2);
888         
889         r->out.domains = r2.out.domains;
890         r->out.sids = r2.out.sids;
891         r->out.count = r2.out.count;
892         return status;
893 }
894
895 /*
896   lsa_LookupNames2
897 */
898 NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call,
899                                  TALLOC_CTX *mem_ctx,
900                                  struct lsa_LookupNames2 *r)
901 {
902         struct lsa_policy_state *state;
903         struct dcesrv_handle *h;
904         uint32_t i;
905         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
906         struct lsa_RefDomainList *domains;
907
908         *r->out.domains = NULL;
909
910         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
911
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;
915         }
916
917         state = h->data;
918
919         domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
920         if (domains == NULL) {
921                 return NT_STATUS_NO_MEMORY;
922         }
923         *r->out.domains = domains;
924
925         r->out.sids = talloc_zero(mem_ctx,  struct lsa_TransSidArray2);
926         if (r->out.sids == NULL) {
927                 return NT_STATUS_NO_MEMORY;
928         }
929
930         *r->out.count = 0;
931
932         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid2, 
933                                            r->in.num_names);
934         if (r->out.sids->sids == NULL) {
935                 return NT_STATUS_NO_MEMORY;
936         }
937
938         for (i=0;i<r->in.num_names;i++) {
939                 const char *name = r->in.names[i].string;
940                 const char *authority_name;
941                 struct dom_sid *sid;
942                 uint32_t sid_index, rid=0;
943                 enum lsa_SidType rtype;
944                 NTSTATUS status2;
945
946                 r->out.sids->count++;
947
948                 r->out.sids->sids[i].sid_type    = SID_NAME_UNKNOWN;
949                 /* MS-LSAT 3.1.4.7 - rid zero is considered equivalent
950                    to sid NULL - so we should return 0 rid for
951                    unmapped entries */
952                 r->out.sids->sids[i].rid         = 0;
953                 r->out.sids->sids[i].sid_index   = 0xFFFFFFFF;
954                 r->out.sids->sids[i].unknown     = 0;
955
956                 status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, state, mem_ctx, name,
957                                                  &authority_name, &sid, &rtype, &rid);
958                 if (!NT_STATUS_IS_OK(status2)) {
959                         continue;
960                 }
961
962                 status2 = dcesrv_lsa_authority_list(state, mem_ctx, rtype, authority_name, 
963                                                     sid, domains, &sid_index);
964                 if (!NT_STATUS_IS_OK(status2)) {
965                         continue;
966                 }
967
968                 r->out.sids->sids[i].sid_type    = rtype;
969                 r->out.sids->sids[i].rid         = rid;
970                 r->out.sids->sids[i].sid_index   = sid_index;
971                 r->out.sids->sids[i].unknown     = 0;
972
973                 (*r->out.count)++;
974         }
975         
976         if (*r->out.count == 0) {
977                 return NT_STATUS_NONE_MAPPED;
978         }
979         if (*r->out.count != r->in.num_names) {
980                 return STATUS_SOME_UNMAPPED;
981         }
982
983         return NT_STATUS_OK;
984 }
985
986 /* 
987   lsa_LookupNames 
988 */
989 NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
990                        struct lsa_LookupNames *r)
991 {
992         struct lsa_LookupNames2 r2;
993         NTSTATUS status;
994         uint32_t i;
995
996         ZERO_STRUCT(r2);
997
998         r2.in.handle    = r->in.handle;
999         r2.in.num_names = r->in.num_names;
1000         r2.in.names     = r->in.names;
1001         r2.in.sids      = NULL;
1002         r2.in.level     = r->in.level;
1003         r2.in.count     = r->in.count;
1004         r2.in.lookup_options = 0;
1005         r2.in.client_revision = 0;
1006         r2.out.count    = r->out.count;
1007         r2.out.domains  = r->out.domains;
1008
1009         status = dcesrv_lsa_LookupNames2(dce_call, mem_ctx, &r2);
1010         if (r2.out.sids == NULL) {
1011                 return status;
1012         }
1013
1014         r->out.sids = talloc(mem_ctx, struct lsa_TransSidArray);
1015         if (r->out.sids == NULL) {
1016                 return NT_STATUS_NO_MEMORY;
1017         }
1018         r->out.sids->count = r2.out.sids->count;
1019         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid, 
1020                                            r->out.sids->count);
1021         if (r->out.sids->sids == NULL) {
1022                 return NT_STATUS_NO_MEMORY;
1023         }
1024         for (i=0;i<r->out.sids->count;i++) {
1025                 r->out.sids->sids[i].sid_type    = r2.out.sids->sids[i].sid_type;
1026                 r->out.sids->sids[i].rid         = r2.out.sids->sids[i].rid;
1027                 r->out.sids->sids[i].sid_index   = r2.out.sids->sids[i].sid_index;
1028         }
1029
1030         return status;
1031 }
1032