b96adaa13d0562b45a08efe453a182c2e718d273
[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         struct lsa_policy_state *state;
643         struct dcesrv_handle *h;
644
645         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
646
647         state = h->data;
648
649         return dcesrv_lsa_LookupSids_common(dce_call,
650                                             mem_ctx,
651                                             state,
652                                             r);
653 }
654
655
656 /*
657   lsa_LookupSids3
658
659   Identical to LookupSids2, but doesn't take a policy handle
660   
661 */
662 NTSTATUS dcesrv_lsa_LookupSids3(struct dcesrv_call_state *dce_call,
663                                 TALLOC_CTX *mem_ctx,
664                                 struct lsa_LookupSids3 *r)
665 {
666         struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
667         struct lsa_policy_state *policy_state;
668         struct lsa_LookupSids2 q;
669         NTSTATUS status;
670
671         /*
672          * We don't have policy handles on this call. So this must be restricted
673          * to crypto connections only.
674          */
675         if (auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL ||
676             auth_info->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
677                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
678         }
679
680         status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &policy_state);
681         if (!NT_STATUS_IS_OK(status)) {
682                 return status;
683         }
684
685         ZERO_STRUCT(q);
686
687         q.in.handle   = NULL;
688         q.in.sids     = r->in.sids;
689         q.in.names    = r->in.names;
690         q.in.level    = r->in.level;
691         q.in.count    = r->in.count;
692         q.in.lookup_options = r->in.lookup_options;
693         q.in.client_revision = r->in.client_revision;
694         q.out.count   = r->out.count;
695         q.out.names   = r->out.names;
696         q.out.domains = r->out.domains;
697
698         status = dcesrv_lsa_LookupSids_common(dce_call,
699                                               mem_ctx,
700                                               policy_state,
701                                               &q);
702
703         talloc_free(policy_state);
704
705         r->out.count = q.out.count;
706         r->out.names = q.out.names;
707         r->out.domains = q.out.domains;
708
709         return status;
710 }
711
712
713 /* 
714   lsa_LookupSids 
715 */
716 NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
717                                struct lsa_LookupSids *r)
718 {
719         struct lsa_LookupSids2 r2;
720         NTSTATUS status;
721         uint32_t i;
722
723         ZERO_STRUCT(r2);
724
725         r2.in.handle   = r->in.handle;
726         r2.in.sids     = r->in.sids;
727         r2.in.names    = NULL;
728         r2.in.level    = r->in.level;
729         r2.in.count    = r->in.count;
730         r2.in.lookup_options = 0;
731         r2.in.client_revision = 0;
732         r2.out.count   = r->out.count;
733         r2.out.names   = NULL;
734         r2.out.domains = r->out.domains;
735
736         status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
737         /* we deliberately don't check for error from the above,
738            as even on error we are supposed to return the names  */
739
740         r->out.domains = r2.out.domains;
741         if (!r2.out.names) {
742                 r->out.names = NULL;
743                 return status;
744         }
745
746         r->out.names = talloc(mem_ctx, struct lsa_TransNameArray);
747         if (r->out.names == NULL) {
748                 return NT_STATUS_NO_MEMORY;
749         }
750         r->out.names->count = r2.out.names->count;
751         r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName, 
752                                              r->out.names->count);
753         if (r->out.names->names == NULL) {
754                 return NT_STATUS_NO_MEMORY;
755         }
756         for (i=0;i<r->out.names->count;i++) {
757                 r->out.names->names[i].sid_type    = r2.out.names->names[i].sid_type;
758                 r->out.names->names[i].name.string = r2.out.names->names[i].name.string;
759                 r->out.names->names[i].sid_index   = r2.out.names->names[i].sid_index;
760         }
761
762         return status;
763 }
764
765 static NTSTATUS dcesrv_lsa_LookupNames_common(struct dcesrv_call_state *dce_call,
766                                               TALLOC_CTX *mem_ctx,
767                                               struct lsa_policy_state *policy_state,
768                                               struct lsa_LookupNames3 *r)
769 {
770         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
771         struct lsa_RefDomainList *domains;
772         uint32_t i;
773
774         if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
775             r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
776                 return NT_STATUS_INVALID_PARAMETER;
777         }
778
779         *r->out.domains = NULL;
780
781         domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
782         if (domains == NULL) {
783                 return NT_STATUS_NO_MEMORY;
784         }
785         *r->out.domains = domains;
786
787         r->out.sids = talloc_zero(mem_ctx,  struct lsa_TransSidArray3);
788         if (r->out.sids == NULL) {
789                 return NT_STATUS_NO_MEMORY;
790         }
791
792         *r->out.count = 0;
793
794         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid3, 
795                                            r->in.num_names);
796         if (r->out.sids->sids == NULL) {
797                 return NT_STATUS_NO_MEMORY;
798         }
799
800         for (i=0;i<r->in.num_names;i++) {
801                 const char *name = r->in.names[i].string;
802                 const char *authority_name;
803                 struct dom_sid *sid;
804                 uint32_t sid_index, rid;
805                 enum lsa_SidType rtype;
806                 NTSTATUS status2;
807
808                 r->out.sids->count++;
809
810                 r->out.sids->sids[i].sid_type    = SID_NAME_UNKNOWN;
811                 r->out.sids->sids[i].sid         = NULL;
812                 r->out.sids->sids[i].sid_index   = 0xFFFFFFFF;
813                 r->out.sids->sids[i].flags       = 0;
814
815                 status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, policy_state, mem_ctx, name,
816                                                  &authority_name, &sid, &rtype, &rid);
817                 if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) {
818                         continue;
819                 }
820
821                 status2 = dcesrv_lsa_authority_list(policy_state, mem_ctx, rtype, authority_name, 
822                                                     sid, domains, &sid_index);
823                 if (!NT_STATUS_IS_OK(status2)) {
824                         continue;
825                 }
826
827                 r->out.sids->sids[i].sid_type    = rtype;
828                 r->out.sids->sids[i].sid         = sid;
829                 r->out.sids->sids[i].sid_index   = sid_index;
830                 r->out.sids->sids[i].flags       = 0;
831
832                 (*r->out.count)++;
833         }
834         
835         if (*r->out.count == 0) {
836                 return NT_STATUS_NONE_MAPPED;
837         }
838         if (*r->out.count != r->in.num_names) {
839                 return STATUS_SOME_UNMAPPED;
840         }
841
842         return NT_STATUS_OK;
843 }
844
845 /*
846   lsa_LookupNames3
847 */
848 NTSTATUS dcesrv_lsa_LookupNames3(struct dcesrv_call_state *dce_call,
849                                  TALLOC_CTX *mem_ctx,
850                                  struct lsa_LookupNames3 *r)
851 {
852         struct lsa_policy_state *policy_state;
853         struct dcesrv_handle *policy_handle;
854
855         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
856
857         policy_state = policy_handle->data;
858
859         return dcesrv_lsa_LookupNames_common(dce_call,
860                                              mem_ctx,
861                                              policy_state,
862                                              r);
863 }
864
865 /* 
866   lsa_LookupNames4
867
868   Identical to LookupNames3, but doesn't take a policy handle
869   
870 */
871 NTSTATUS dcesrv_lsa_LookupNames4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
872                                  struct lsa_LookupNames4 *r)
873 {
874         struct dcerpc_auth *auth_info = dce_call->conn->auth_state.auth_info;
875         struct lsa_policy_state *policy_state;
876         struct lsa_LookupNames3 q;
877         NTSTATUS status;
878
879         /*
880          * We don't have policy handles on this call. So this must be restricted
881          * to crypto connections only.
882          */
883         if (auth_info->auth_type != DCERPC_AUTH_TYPE_SCHANNEL ||
884             auth_info->auth_level < DCERPC_AUTH_LEVEL_INTEGRITY) {
885                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
886         }
887
888         status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &policy_state);
889         if (!NT_STATUS_IS_OK(status)) {
890                 return status;
891         }
892
893         ZERO_STRUCT(q);
894
895         q.in.handle = NULL;
896         q.in.num_names = r->in.num_names;
897         q.in.names = r->in.names;
898         q.in.level = r->in.level;
899         q.in.sids = r->in.sids;
900         q.in.count = r->in.count;
901         q.in.lookup_options = r->in.lookup_options;
902         q.in.client_revision = r->in.client_revision;
903
904         q.out.count = r->out.count;
905         q.out.sids = r->out.sids;
906         q.out.domains = r->out.domains;
907
908         status = dcesrv_lsa_LookupNames_common(dce_call,
909                                                mem_ctx,
910                                                policy_state,
911                                                &q);
912
913         talloc_free(policy_state);
914
915         r->out.count = q.out.count;
916         r->out.sids = q.out.sids;
917         r->out.domains = q.out.domains;
918
919         return status;
920 }
921
922 /*
923   lsa_LookupNames2
924 */
925 NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call,
926                                  TALLOC_CTX *mem_ctx,
927                                  struct lsa_LookupNames2 *r)
928 {
929         struct lsa_policy_state *state;
930         struct dcesrv_handle *h;
931         uint32_t i;
932         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
933         struct lsa_RefDomainList *domains;
934
935         *r->out.domains = NULL;
936
937         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
938
939         if (r->in.level < LSA_LOOKUP_NAMES_ALL ||
940             r->in.level > LSA_LOOKUP_NAMES_RODC_REFERRAL_TO_FULL_DC) {
941                 return NT_STATUS_INVALID_PARAMETER;
942         }
943
944         state = h->data;
945
946         domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
947         if (domains == NULL) {
948                 return NT_STATUS_NO_MEMORY;
949         }
950         *r->out.domains = domains;
951
952         r->out.sids = talloc_zero(mem_ctx,  struct lsa_TransSidArray2);
953         if (r->out.sids == NULL) {
954                 return NT_STATUS_NO_MEMORY;
955         }
956
957         *r->out.count = 0;
958
959         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid2, 
960                                            r->in.num_names);
961         if (r->out.sids->sids == NULL) {
962                 return NT_STATUS_NO_MEMORY;
963         }
964
965         for (i=0;i<r->in.num_names;i++) {
966                 const char *name = r->in.names[i].string;
967                 const char *authority_name;
968                 struct dom_sid *sid;
969                 uint32_t sid_index, rid=0;
970                 enum lsa_SidType rtype;
971                 NTSTATUS status2;
972
973                 r->out.sids->count++;
974
975                 r->out.sids->sids[i].sid_type    = SID_NAME_UNKNOWN;
976                 /* MS-LSAT 3.1.4.7 - rid zero is considered equivalent
977                    to sid NULL - so we should return 0 rid for
978                    unmapped entries */
979                 r->out.sids->sids[i].rid         = 0;
980                 r->out.sids->sids[i].sid_index   = 0xFFFFFFFF;
981                 r->out.sids->sids[i].unknown     = 0;
982
983                 status2 = dcesrv_lsa_lookup_name(dce_call->event_ctx, lp_ctx, state, mem_ctx, name,
984                                                  &authority_name, &sid, &rtype, &rid);
985                 if (!NT_STATUS_IS_OK(status2)) {
986                         continue;
987                 }
988
989                 status2 = dcesrv_lsa_authority_list(state, mem_ctx, rtype, authority_name, 
990                                                     sid, domains, &sid_index);
991                 if (!NT_STATUS_IS_OK(status2)) {
992                         continue;
993                 }
994
995                 r->out.sids->sids[i].sid_type    = rtype;
996                 r->out.sids->sids[i].rid         = rid;
997                 r->out.sids->sids[i].sid_index   = sid_index;
998                 r->out.sids->sids[i].unknown     = 0;
999
1000                 (*r->out.count)++;
1001         }
1002         
1003         if (*r->out.count == 0) {
1004                 return NT_STATUS_NONE_MAPPED;
1005         }
1006         if (*r->out.count != r->in.num_names) {
1007                 return STATUS_SOME_UNMAPPED;
1008         }
1009
1010         return NT_STATUS_OK;
1011 }
1012
1013 /* 
1014   lsa_LookupNames 
1015 */
1016 NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1017                        struct lsa_LookupNames *r)
1018 {
1019         struct lsa_LookupNames2 r2;
1020         NTSTATUS status;
1021         uint32_t i;
1022
1023         ZERO_STRUCT(r2);
1024
1025         r2.in.handle    = r->in.handle;
1026         r2.in.num_names = r->in.num_names;
1027         r2.in.names     = r->in.names;
1028         r2.in.sids      = NULL;
1029         r2.in.level     = r->in.level;
1030         r2.in.count     = r->in.count;
1031         r2.in.lookup_options = 0;
1032         r2.in.client_revision = 0;
1033         r2.out.count    = r->out.count;
1034         r2.out.domains  = r->out.domains;
1035
1036         status = dcesrv_lsa_LookupNames2(dce_call, mem_ctx, &r2);
1037         if (r2.out.sids == NULL) {
1038                 return status;
1039         }
1040
1041         r->out.sids = talloc(mem_ctx, struct lsa_TransSidArray);
1042         if (r->out.sids == NULL) {
1043                 return NT_STATUS_NO_MEMORY;
1044         }
1045         r->out.sids->count = r2.out.sids->count;
1046         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid, 
1047                                            r->out.sids->count);
1048         if (r->out.sids->sids == NULL) {
1049                 return NT_STATUS_NO_MEMORY;
1050         }
1051         for (i=0;i<r->out.sids->count;i++) {
1052                 r->out.sids->sids[i].sid_type    = r2.out.sids->sids[i].sid_type;
1053                 r->out.sids->sids[i].rid         = r2.out.sids->sids[i].rid;
1054                 r->out.sids->sids[i].sid_index   = r2.out.sids->sids[i].sid_index;
1055         }
1056
1057         return status;
1058 }
1059