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