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