s4-lsarpc: DCERPC_FAULT_ACCESS_DENIED for tcp
[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                         *rtype = SID_NAME_DOMAIN;
288                         *rid = 0xFFFFFFFF;
289                         return NT_STATUS_OK;
290                 }
291
292                 if (strcasecmp_m(username, NAME_NT_AUTHORITY) == 0) { 
293                         *authority_name = NAME_NT_AUTHORITY;
294                         *sid =  dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY);
295                         *rtype = SID_NAME_DOMAIN;
296                         dom_sid_split_rid(NULL, *sid, NULL, rid);
297                         return NT_STATUS_OK;
298                 }
299                 if (strcasecmp_m(username, NAME_BUILTIN) == 0) { 
300                         *authority_name = NAME_BUILTIN;
301                         *sid = dom_sid_parse_talloc(mem_ctx, SID_BUILTIN);
302                         *rtype = SID_NAME_DOMAIN;
303                         *rid = 0xFFFFFFFF;
304                         return NT_STATUS_OK;
305                 }
306                 if (strcasecmp_m(username, state->domain_dns) == 0) { 
307                         *authority_name = state->domain_name;
308                         *sid =  state->domain_sid;
309                         *rtype = SID_NAME_DOMAIN;
310                         *rid = 0xFFFFFFFF;
311                         return NT_STATUS_OK;
312                 }
313                 if (strcasecmp_m(username, state->domain_name) == 0) { 
314                         *authority_name = state->domain_name;
315                         *sid =  state->domain_sid;
316                         *rtype = SID_NAME_DOMAIN;
317                         *rid = 0xFFFFFFFF;
318                         return NT_STATUS_OK;
319                 }
320                 
321                 /* Perhaps this is a well known user? */
322                 name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_NT_AUTHORITY, username);
323                 if (!name) {
324                         return NT_STATUS_NO_MEMORY;
325                 }
326                 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
327                 if (NT_STATUS_IS_OK(status)) {
328                         return status;
329                 }
330
331                 /* Perhaps this is a BUILTIN user? */
332                 name = talloc_asprintf(mem_ctx, "%s\\%s", NAME_BUILTIN, username);
333                 if (!name) {
334                         return NT_STATUS_NO_MEMORY;
335                 }
336                 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
337                 if (NT_STATUS_IS_OK(status)) {
338                         return status;
339                 }
340
341                 /* OK, I give up - perhaps we need to assume the user is in our domain? */
342                 name = talloc_asprintf(mem_ctx, "%s\\%s", state->domain_name, username);
343                 if (!name) {
344                         return NT_STATUS_NO_MEMORY;
345                 }
346                 status = dcesrv_lsa_lookup_name(ev_ctx, lp_ctx, state, mem_ctx, name, authority_name, sid, rtype, rid);
347                 if (NT_STATUS_IS_OK(status)) {
348                         return status;
349                 }
350
351                 return STATUS_SOME_UNMAPPED;
352         } else if (strcasecmp_m(domain, NAME_NT_AUTHORITY) == 0) {
353                 if (!*username) {
354                         *authority_name = NAME_NT_AUTHORITY;
355                         *sid = dom_sid_parse_talloc(mem_ctx, SID_NT_AUTHORITY);
356                         *rtype = SID_NAME_DOMAIN;
357                         dom_sid_split_rid(NULL, *sid, NULL, rid);
358                         return NT_STATUS_OK;
359                 }
360
361                 /* Look up table of well known names */
362                 status = lookup_well_known_names(mem_ctx, domain, username, authority_name, 
363                                                  sid, rtype);
364                 if (NT_STATUS_IS_OK(status)) {
365                         dom_sid_split_rid(NULL, *sid, NULL, rid);
366                 }
367                 return status;
368         } else if (strcasecmp_m(domain, NAME_BUILTIN) == 0) {
369                 *authority_name = NAME_BUILTIN;
370                 domain_dn = state->builtin_dn;
371         } else if (strcasecmp_m(domain, state->domain_dns) == 0) { 
372                 *authority_name = state->domain_name;
373                 domain_dn = state->domain_dn;
374         } else if (strcasecmp_m(domain, state->domain_name) == 0) { 
375                 *authority_name = state->domain_name;
376                 domain_dn = state->domain_dn;
377         } else {
378                 /* Not local, need to ask winbind in future */
379                 return STATUS_SOME_UNMAPPED;
380         }
381
382         ret = gendb_search_dn(state->sam_ldb, mem_ctx, domain_dn, &res, attrs);
383         if (ret != 1) {
384                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
385         }
386         domain_sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
387         if (domain_sid == NULL) {
388                 return NT_STATUS_INVALID_SID;
389         }
390
391         if (!*username) {
392                 *sid = domain_sid;
393                 *rtype = SID_NAME_DOMAIN;
394                 *rid = 0xFFFFFFFF;
395                 return NT_STATUS_OK;
396         }
397         
398         ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs, 
399                            "(&(sAMAccountName=%s)(objectSid=*))", 
400                            ldb_binary_encode_string(mem_ctx, username));
401         if (ret < 0) {
402                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
403         }
404
405         for (i=0; i < ret; i++) {
406                 *sid = samdb_result_dom_sid(mem_ctx, res[i], "objectSid");
407                 if (*sid == NULL) {
408                         return NT_STATUS_INVALID_SID;
409                 }
410
411                 /* Check that this is in the domain */
412                 if (!dom_sid_in_domain(domain_sid, *sid)) {
413                         continue;
414                 }
415
416                 atype = ldb_msg_find_attr_as_uint(res[i], "sAMAccountType", 0);
417                         
418                 *rtype = ds_atype_map(atype);
419                 if (*rtype == SID_NAME_UNKNOWN) {
420                         return STATUS_SOME_UNMAPPED;
421                 }
422
423                 dom_sid_split_rid(NULL, *sid, NULL, rid);
424                 return NT_STATUS_OK;
425         }
426
427         /* need to check for an allocated sid */
428
429         return NT_STATUS_INVALID_SID;
430 }
431
432
433 /*
434   add to the lsa_RefDomainList for LookupSids and LookupNames
435 */
436 static NTSTATUS dcesrv_lsa_authority_list(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx, 
437                                           enum lsa_SidType rtype,
438                                           const char *authority_name,
439                                           struct dom_sid *sid, 
440                                           struct lsa_RefDomainList *domains,
441                                           uint32_t *sid_index)
442 {
443         struct dom_sid *authority_sid;
444         uint32_t i;
445
446         if (rtype != SID_NAME_DOMAIN) {
447                 authority_sid = dom_sid_dup(mem_ctx, sid);
448                 if (authority_sid == NULL) {
449                         return NT_STATUS_NO_MEMORY;
450                 }
451                 authority_sid->num_auths--;
452         } else {
453                 authority_sid = sid;
454         }
455
456         /* see if we've already done this authority name */
457         for (i=0;i<domains->count;i++) {
458                 if (strcasecmp_m(authority_name, domains->domains[i].name.string) == 0) {
459                         *sid_index = i;
460                         return NT_STATUS_OK;
461                 }
462         }
463
464         domains->domains = talloc_realloc(domains, 
465                                           domains->domains,
466                                           struct lsa_DomainInfo,
467                                           domains->count+1);
468         if (domains->domains == NULL) {
469                 return NT_STATUS_NO_MEMORY;
470         }
471         domains->domains[i].name.string = authority_name;
472         domains->domains[i].sid         = authority_sid;
473         domains->count++;
474         domains->max_size = LSA_REF_DOMAIN_LIST_MULTIPLIER * domains->count;
475         *sid_index = i;
476         
477         return NT_STATUS_OK;
478 }
479
480 /*
481   lookup a name for 1 SID
482 */
483 static NTSTATUS dcesrv_lsa_lookup_sid(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
484                                       struct dom_sid *sid, const char *sid_str,
485                                       const char **authority_name, 
486                                       const char **name, enum lsa_SidType *rtype)
487 {
488         NTSTATUS status;
489         int ret;
490         uint32_t atype;
491         struct ldb_message **res;
492         struct ldb_dn *domain_dn;
493         const char * const attrs[] = { "sAMAccountName", "sAMAccountType", "cn", NULL};
494
495         status = lookup_well_known_sids(mem_ctx, sid_str, authority_name, name, rtype);
496         if (NT_STATUS_IS_OK(status)) {
497                 return status;
498         }
499
500         if (dom_sid_in_domain(state->domain_sid, sid)) {
501                 *authority_name = state->domain_name;
502                 domain_dn = state->domain_dn;
503         } else if (dom_sid_in_domain(state->builtin_sid, sid)) {
504                 *authority_name = NAME_BUILTIN;
505                 domain_dn = state->builtin_dn;
506         } else {
507                 /* Not well known, our domain or built in */
508
509                 /* In future, we must look at SID histories, and at trusted domains via winbind */
510
511                 return NT_STATUS_NOT_FOUND;
512         }
513
514         /* need to re-add a check for an allocated sid */
515
516         ret = gendb_search(state->sam_ldb, mem_ctx, domain_dn, &res, attrs, 
517                            "objectSid=%s", ldap_encode_ndr_dom_sid(mem_ctx, sid));
518         if ((ret < 0) || (ret > 1)) {
519                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
520         }
521         if (ret == 0) {
522                 return NT_STATUS_NOT_FOUND;
523         }
524
525         *name = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
526         if (!*name) {
527                 *name = ldb_msg_find_attr_as_string(res[0], "cn", NULL);
528                 if (!*name) {
529                         *name = talloc_strdup(mem_ctx, sid_str);
530                         NT_STATUS_HAVE_NO_MEMORY(*name);
531                 }
532         }
533
534         atype = ldb_msg_find_attr_as_uint(res[0], "sAMAccountType", 0);
535         *rtype = ds_atype_map(atype);
536
537         return NT_STATUS_OK;
538 }
539
540 static NTSTATUS dcesrv_lsa_LookupSids_common(struct dcesrv_call_state *dce_call,
541                                              TALLOC_CTX *mem_ctx,
542                                              struct lsa_policy_state *state,
543                                              struct lsa_LookupSids2 *r)
544 {
545         struct lsa_RefDomainList *domains = NULL;
546         NTSTATUS status = NT_STATUS_OK;
547         uint32_t i;
548
549         if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
550             r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
551                 return NT_STATUS_INVALID_PARAMETER;
552         }
553
554         *r->out.domains = NULL;
555
556         /* NOTE: the WSPP test suite tries SIDs with invalid revision numbers,
557            and expects NT_STATUS_INVALID_PARAMETER back - we just treat it as 
558            an unknown SID. We could add a SID validator here. (tridge) 
559            MS-DTYP 2.4.2
560         */
561
562         domains = talloc_zero(r->out.domains,  struct lsa_RefDomainList);
563         if (domains == NULL) {
564                 return NT_STATUS_NO_MEMORY;
565         }
566         *r->out.domains = domains;
567
568         r->out.names = talloc_zero(mem_ctx,  struct lsa_TransNameArray2);
569         if (r->out.names == NULL) {
570                 return NT_STATUS_NO_MEMORY;
571         }
572
573         *r->out.count = 0;
574
575         r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName2, 
576                                              r->in.sids->num_sids);
577         if (r->out.names->names == NULL) {
578                 return NT_STATUS_NO_MEMORY;
579         }
580
581         for (i=0;i<r->in.sids->num_sids;i++) {
582                 struct dom_sid *sid = r->in.sids->sids[i].sid;
583                 char *sid_str = dom_sid_string(mem_ctx, sid);
584                 const char *name, *authority_name;
585                 enum lsa_SidType rtype;
586                 uint32_t sid_index;
587                 NTSTATUS status2;
588
589                 r->out.names->count++;
590
591                 r->out.names->names[i].sid_type    = SID_NAME_UNKNOWN;
592                 r->out.names->names[i].name.string = sid_str;
593                 r->out.names->names[i].sid_index   = 0xFFFFFFFF;
594                 r->out.names->names[i].unknown     = 0;
595
596                 if (sid_str == NULL) {
597                         r->out.names->names[i].name.string = "(SIDERROR)";
598                         status = STATUS_SOME_UNMAPPED;
599                         continue;
600                 }
601
602                 status2 = dcesrv_lsa_lookup_sid(state, mem_ctx, sid, sid_str, 
603                                                 &authority_name, &name, &rtype);
604                 if (!NT_STATUS_IS_OK(status2)) {
605                         status = STATUS_SOME_UNMAPPED;
606                         continue;
607                 }
608
609                 /* set up the authority table */
610                 status2 = dcesrv_lsa_authority_list(state, mem_ctx, rtype, 
611                                                     authority_name, sid, 
612                                                     domains, &sid_index);
613                 if (!NT_STATUS_IS_OK(status2)) {
614                         continue;
615                 }
616
617                 r->out.names->names[i].sid_type    = rtype;
618                 r->out.names->names[i].name.string = name;
619                 r->out.names->names[i].sid_index   = sid_index;
620                 r->out.names->names[i].unknown     = 0;
621
622                 (*r->out.count)++;
623         }
624
625         if (*r->out.count == 0) {
626                 return NT_STATUS_NONE_MAPPED;
627         }
628         if (*r->out.count != r->in.sids->num_sids) {
629                 return STATUS_SOME_UNMAPPED;
630         }
631
632         return NT_STATUS_OK;
633 }
634
635 /*
636   lsa_LookupSids2
637 */
638 NTSTATUS dcesrv_lsa_LookupSids2(struct dcesrv_call_state *dce_call,
639                                 TALLOC_CTX *mem_ctx,
640                                 struct lsa_LookupSids2 *r)
641 {
642         enum dcerpc_transport_t transport = dce_call->conn->endpoint->ep_description->transport;
643         struct lsa_policy_state *state;
644         struct dcesrv_handle *h;
645
646         if (transport != NCACN_NP && transport != NCALRPC) {
647                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
648         }
649
650         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
651
652         state = h->data;
653
654         return dcesrv_lsa_LookupSids_common(dce_call,
655                                             mem_ctx,
656                                             state,
657                                             r);
658 }
659
660
661 /*
662   lsa_LookupSids3
663
664   Identical to LookupSids2, but doesn't take a policy handle
665   
666 */
667 NTSTATUS dcesrv_lsa_LookupSids3(struct dcesrv_call_state *dce_call,
668                                 TALLOC_CTX *mem_ctx,
669                                 struct lsa_LookupSids3 *r)
670 {
671         enum dcerpc_transport_t transport = dce_call->conn->endpoint->ep_description->transport;
672         struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
673         struct lsa_policy_state *policy_state;
674         struct lsa_LookupSids2 q;
675         NTSTATUS status;
676
677         if (transport != NCACN_IP_TCP) {
678                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
679         }
680
681         /*
682          * We don't have policy handles on this call. So this must be restricted
683          * to crypto connections only.
684          */
685         if (auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL ||
686             auth_info->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
687                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
688         }
689
690         status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &policy_state);
691         if (!NT_STATUS_IS_OK(status)) {
692                 return status;
693         }
694
695         ZERO_STRUCT(q);
696
697         q.in.handle   = NULL;
698         q.in.sids     = r->in.sids;
699         q.in.names    = r->in.names;
700         q.in.level    = r->in.level;
701         q.in.count    = r->in.count;
702         q.in.lookup_options = r->in.lookup_options;
703         q.in.client_revision = r->in.client_revision;
704         q.out.count   = r->out.count;
705         q.out.names   = r->out.names;
706         q.out.domains = r->out.domains;
707
708         status = dcesrv_lsa_LookupSids_common(dce_call,
709                                               mem_ctx,
710                                               policy_state,
711                                               &q);
712
713         talloc_free(policy_state);
714
715         r->out.count = q.out.count;
716         r->out.names = q.out.names;
717         r->out.domains = q.out.domains;
718
719         return status;
720 }
721
722
723 /* 
724   lsa_LookupSids 
725 */
726 NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
727                                struct lsa_LookupSids *r)
728 {
729         enum dcerpc_transport_t transport = dce_call->conn->endpoint->ep_description->transport;
730         struct lsa_LookupSids2 r2;
731         NTSTATUS status;
732         uint32_t i;
733
734         if (transport != NCACN_NP && transport != NCALRPC) {
735                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
736         }
737
738         ZERO_STRUCT(r2);
739
740         r2.in.handle   = r->in.handle;
741         r2.in.sids     = r->in.sids;
742         r2.in.names    = NULL;
743         r2.in.level    = r->in.level;
744         r2.in.count    = r->in.count;
745         r2.in.lookup_options = 0;
746         r2.in.client_revision = 0;
747         r2.out.count   = r->out.count;
748         r2.out.names   = NULL;
749         r2.out.domains = r->out.domains;
750
751         status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
752         /* we deliberately don't check for error from the above,
753            as even on error we are supposed to return the names  */
754
755         r->out.domains = r2.out.domains;
756         if (!r2.out.names) {
757                 r->out.names = NULL;
758                 return status;
759         }
760
761         r->out.names = talloc(mem_ctx, struct lsa_TransNameArray);
762         if (r->out.names == NULL) {
763                 return NT_STATUS_NO_MEMORY;
764         }
765         r->out.names->count = r2.out.names->count;
766         r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName, 
767                                              r->out.names->count);
768         if (r->out.names->names == NULL) {
769                 return NT_STATUS_NO_MEMORY;
770         }
771         for (i=0;i<r->out.names->count;i++) {
772                 r->out.names->names[i].sid_type    = r2.out.names->names[i].sid_type;
773                 r->out.names->names[i].name.string = r2.out.names->names[i].name.string;
774                 r->out.names->names[i].sid_index   = r2.out.names->names[i].sid_index;
775         }
776
777         return status;
778 }
779
780 static NTSTATUS dcesrv_lsa_LookupNames_common(struct dcesrv_call_state *dce_call,
781                                               TALLOC_CTX *mem_ctx,
782                                               struct lsa_policy_state *policy_state,
783                                               struct lsa_LookupNames3 *r)
784 {
785         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
786         struct lsa_RefDomainList *domains;
787         uint32_t i;
788
789         if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
790             r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
791                 return NT_STATUS_INVALID_PARAMETER;
792         }
793
794         *r->out.domains = NULL;
795
796         domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
797         if (domains == NULL) {
798                 return NT_STATUS_NO_MEMORY;
799         }
800         *r->out.domains = domains;
801
802         r->out.sids = talloc_zero(mem_ctx,  struct lsa_TransSidArray3);
803         if (r->out.sids == NULL) {
804                 return NT_STATUS_NO_MEMORY;
805         }
806
807         *r->out.count = 0;
808
809         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid3, 
810                                            r->in.num_names);
811         if (r->out.sids->sids == NULL) {
812                 return NT_STATUS_NO_MEMORY;
813         }
814
815         for (i=0;i<r->in.num_names;i++) {
816                 const char *name = r->in.names[i].string;
817                 const char *authority_name;
818                 struct dom_sid *sid;
819                 uint32_t sid_index, rid;
820                 enum lsa_SidType rtype;
821                 NTSTATUS status2;
822
823                 r->out.sids->count++;
824
825                 r->out.sids->sids[i].sid_type    = SID_NAME_UNKNOWN;
826                 r->out.sids->sids[i].sid         = NULL;
827                 r->out.sids->sids[i].sid_index   = 0xFFFFFFFF;
828                 r->out.sids->sids[i].flags       = 0;
829
830                 status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, policy_state, mem_ctx, name,
831                                                  &authority_name, &sid, &rtype, &rid);
832                 if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) {
833                         continue;
834                 }
835
836                 status2 = dcesrv_lsa_authority_list(policy_state, mem_ctx, rtype, authority_name, 
837                                                     sid, domains, &sid_index);
838                 if (!NT_STATUS_IS_OK(status2)) {
839                         continue;
840                 }
841
842                 r->out.sids->sids[i].sid_type    = rtype;
843                 r->out.sids->sids[i].sid         = sid;
844                 r->out.sids->sids[i].sid_index   = sid_index;
845                 r->out.sids->sids[i].flags       = 0;
846
847                 (*r->out.count)++;
848         }
849         
850         if (*r->out.count == 0) {
851                 return NT_STATUS_NONE_MAPPED;
852         }
853         if (*r->out.count != r->in.num_names) {
854                 return STATUS_SOME_UNMAPPED;
855         }
856
857         return NT_STATUS_OK;
858 }
859
860 /*
861   lsa_LookupNames3
862 */
863 NTSTATUS dcesrv_lsa_LookupNames3(struct dcesrv_call_state *dce_call,
864                                  TALLOC_CTX *mem_ctx,
865                                  struct lsa_LookupNames3 *r)
866 {
867         enum dcerpc_transport_t transport = dce_call->conn->endpoint->ep_description->transport;
868         struct lsa_policy_state *policy_state;
869         struct dcesrv_handle *policy_handle;
870
871         if (transport != NCACN_NP && transport != NCALRPC) {
872                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
873         }
874
875         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
876
877         policy_state = policy_handle->data;
878
879         return dcesrv_lsa_LookupNames_common(dce_call,
880                                              mem_ctx,
881                                              policy_state,
882                                              r);
883 }
884
885 /* 
886   lsa_LookupNames4
887
888   Identical to LookupNames3, but doesn't take a policy handle
889   
890 */
891 NTSTATUS dcesrv_lsa_LookupNames4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
892                                  struct lsa_LookupNames4 *r)
893 {
894         enum dcerpc_transport_t transport = dce_call->conn->endpoint->ep_description->transport;
895         struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
896         struct lsa_policy_state *policy_state;
897         struct lsa_LookupNames3 q;
898         NTSTATUS status;
899
900         if (transport != NCACN_IP_TCP) {
901                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
902         }
903
904         /*
905          * We don't have policy handles on this call. So this must be restricted
906          * to crypto connections only.
907          */
908         if (auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL ||
909             auth_info->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
910                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
911         }
912
913         status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &policy_state);
914         if (!NT_STATUS_IS_OK(status)) {
915                 return status;
916         }
917
918         ZERO_STRUCT(q);
919
920         q.in.handle = NULL;
921         q.in.num_names = r->in.num_names;
922         q.in.names = r->in.names;
923         q.in.level = r->in.level;
924         q.in.sids = r->in.sids;
925         q.in.count = r->in.count;
926         q.in.lookup_options = r->in.lookup_options;
927         q.in.client_revision = r->in.client_revision;
928
929         q.out.count = r->out.count;
930         q.out.sids = r->out.sids;
931         q.out.domains = r->out.domains;
932
933         status = dcesrv_lsa_LookupNames_common(dce_call,
934                                                mem_ctx,
935                                                policy_state,
936                                                &q);
937
938         talloc_free(policy_state);
939
940         r->out.count = q.out.count;
941         r->out.sids = q.out.sids;
942         r->out.domains = q.out.domains;
943
944         return status;
945 }
946
947 /*
948   lsa_LookupNames2
949 */
950 NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call,
951                                  TALLOC_CTX *mem_ctx,
952                                  struct lsa_LookupNames2 *r)
953 {
954         enum dcerpc_transport_t transport = dce_call->conn->endpoint->ep_description->transport;
955         struct lsa_policy_state *state;
956         struct dcesrv_handle *h;
957         uint32_t i;
958         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
959         struct lsa_RefDomainList *domains;
960
961         if (transport != NCACN_NP && transport != NCALRPC) {
962                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
963         }
964
965         *r->out.domains = NULL;
966
967         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
968
969         if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
970             r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
971                 return NT_STATUS_INVALID_PARAMETER;
972         }
973
974         state = h->data;
975
976         domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
977         if (domains == NULL) {
978                 return NT_STATUS_NO_MEMORY;
979         }
980         *r->out.domains = domains;
981
982         r->out.sids = talloc_zero(mem_ctx,  struct lsa_TransSidArray2);
983         if (r->out.sids == NULL) {
984                 return NT_STATUS_NO_MEMORY;
985         }
986
987         *r->out.count = 0;
988
989         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid2, 
990                                            r->in.num_names);
991         if (r->out.sids->sids == NULL) {
992                 return NT_STATUS_NO_MEMORY;
993         }
994
995         for (i=0;i<r->in.num_names;i++) {
996                 const char *name = r->in.names[i].string;
997                 const char *authority_name;
998                 struct dom_sid *sid;
999                 uint32_t sid_index, rid=0;
1000                 enum lsa_SidType rtype;
1001                 NTSTATUS status2;
1002
1003                 r->out.sids->count++;
1004
1005                 r->out.sids->sids[i].sid_type    = SID_NAME_UNKNOWN;
1006                 /* MS-LSAT 3.1.4.7 - rid zero is considered equivalent
1007                    to sid NULL - so we should return 0 rid for
1008                    unmapped entries */
1009                 r->out.sids->sids[i].rid         = 0;
1010                 r->out.sids->sids[i].sid_index   = 0xFFFFFFFF;
1011                 r->out.sids->sids[i].unknown     = 0;
1012
1013                 status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, state, mem_ctx, name,
1014                                                  &authority_name, &sid, &rtype, &rid);
1015                 if (!NT_STATUS_IS_OK(status2)) {
1016                         continue;
1017                 }
1018
1019                 status2 = dcesrv_lsa_authority_list(state, mem_ctx, rtype, authority_name, 
1020                                                     sid, domains, &sid_index);
1021                 if (!NT_STATUS_IS_OK(status2)) {
1022                         continue;
1023                 }
1024
1025                 r->out.sids->sids[i].sid_type    = rtype;
1026                 r->out.sids->sids[i].rid         = rid;
1027                 r->out.sids->sids[i].sid_index   = sid_index;
1028                 r->out.sids->sids[i].unknown     = 0;
1029
1030                 (*r->out.count)++;
1031         }
1032         
1033         if (*r->out.count == 0) {
1034                 return NT_STATUS_NONE_MAPPED;
1035         }
1036         if (*r->out.count != r->in.num_names) {
1037                 return STATUS_SOME_UNMAPPED;
1038         }
1039
1040         return NT_STATUS_OK;
1041 }
1042
1043 /* 
1044   lsa_LookupNames 
1045 */
1046 NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1047                        struct lsa_LookupNames *r)
1048 {
1049         enum dcerpc_transport_t transport = dce_call->conn->endpoint->ep_description->transport;
1050         struct lsa_LookupNames2 r2;
1051         NTSTATUS status;
1052         uint32_t i;
1053
1054         if (transport != NCACN_NP && transport != NCALRPC) {
1055                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
1056         }
1057
1058         ZERO_STRUCT(r2);
1059
1060         r2.in.handle    = r->in.handle;
1061         r2.in.num_names = r->in.num_names;
1062         r2.in.names     = r->in.names;
1063         r2.in.sids      = NULL;
1064         r2.in.level     = r->in.level;
1065         r2.in.count     = r->in.count;
1066         r2.in.lookup_options = 0;
1067         r2.in.client_revision = 0;
1068         r2.out.count    = r->out.count;
1069         r2.out.domains  = r->out.domains;
1070
1071         status = dcesrv_lsa_LookupNames2(dce_call, mem_ctx, &r2);
1072         if (r2.out.sids == NULL) {
1073                 return status;
1074         }
1075
1076         r->out.sids = talloc(mem_ctx, struct lsa_TransSidArray);
1077         if (r->out.sids == NULL) {
1078                 return NT_STATUS_NO_MEMORY;
1079         }
1080         r->out.sids->count = r2.out.sids->count;
1081         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid, 
1082                                            r->out.sids->count);
1083         if (r->out.sids->sids == NULL) {
1084                 return NT_STATUS_NO_MEMORY;
1085         }
1086         for (i=0;i<r->out.sids->count;i++) {
1087                 r->out.sids->sids[i].sid_type    = r2.out.sids->sids[i].sid_type;
1088                 r->out.sids->sids[i].rid         = r2.out.sids->sids[i].rid;
1089                 r->out.sids->sids[i].sid_index   = r2.out.sids->sids[i].sid_index;
1090         }
1091
1092         return status;
1093 }
1094