r5037: got rid of all of the TALLOC_DEPRECATED stuff. My apologies for the
[kai/samba-autobuild/.git] / source4 / rpc_server / lsa / dcesrv_lsa.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-2005
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 2 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, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25 #include "librpc/gen_ndr/ndr_lsa.h"
26 #include "librpc/gen_ndr/ndr_samr.h"
27 #include "rpc_server/dcerpc_server.h"
28 #include "rpc_server/common/common.h"
29 #include "lib/ldb/include/ldb.h"
30 #include "auth/auth.h"
31 #include "system/time.h"
32
33 /*
34   this type allows us to distinguish handle types
35 */
36 enum lsa_handle {
37         LSA_HANDLE_POLICY,
38         LSA_HANDLE_ACCOUNT,
39         LSA_HANDLE_SECRET,
40         LSA_HANDLE_TRUSTED_DOMAIN
41 };
42
43 /*
44   state associated with a lsa_OpenPolicy() operation
45 */
46 struct lsa_policy_state {
47         struct dcesrv_handle *handle;
48         struct ldb_wrap *sam_ctx;
49         struct sidmap_context *sidmap;
50         uint32_t access_mask;
51         const char *domain_dn;
52         const char *builtin_dn;
53         const char *system_dn;
54         const char *domain_name;
55         struct dom_sid *domain_sid;
56         struct dom_sid *builtin_sid;
57 };
58
59
60 /*
61   state associated with a lsa_OpenAccount() operation
62 */
63 struct lsa_account_state {
64         struct lsa_policy_state *policy;
65         uint32_t access_mask;
66         struct dom_sid *account_sid;
67         const char *account_sid_str;
68         const char *account_dn;
69 };
70
71
72 /*
73   state associated with a lsa_OpenSecret() operation
74 */
75 struct lsa_secret_state {
76         struct lsa_policy_state *policy;
77         uint32_t access_mask;
78         const char *secret_dn;
79         struct ldb_wrap *sam_ctx;
80         BOOL global;
81 };
82
83 /*
84   state associated with a lsa_OpenTrustedDomain() operation
85 */
86 struct lsa_trusted_domain_state {
87         struct lsa_policy_state *policy;
88         uint32_t access_mask;
89         const char *trusted_domain_dn;
90 };
91
92 /* 
93   lsa_Close 
94 */
95 static NTSTATUS lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
96                           struct lsa_Close *r)
97 {
98         struct dcesrv_handle *h;
99
100         *r->out.handle = *r->in.handle;
101
102         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
103
104         talloc_free(h);
105
106         ZERO_STRUCTP(r->out.handle);
107
108         return NT_STATUS_OK;
109 }
110
111
112 /* 
113   lsa_Delete 
114 */
115 static NTSTATUS lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
116                            struct lsa_Delete *r)
117 {
118         struct dcesrv_handle *h;
119         int ret;
120
121         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
122         if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
123                 struct lsa_secret_state *secret_state = h->data;
124                 ret = samdb_delete(secret_state->sam_ctx, mem_ctx, secret_state->secret_dn);
125                 talloc_free(h);
126                 if (ret != 0) {
127                         return NT_STATUS_INVALID_HANDLE;
128                 }
129
130                 return NT_STATUS_OK;
131         } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
132                 struct lsa_trusted_domain_state *trusted_domain_state = h->data;
133                 ret = samdb_delete(trusted_domain_state->policy->sam_ctx, mem_ctx, 
134                                    trusted_domain_state->trusted_domain_dn);
135                 talloc_free(h);
136                 if (ret != 0) {
137                         return NT_STATUS_INVALID_HANDLE;
138                 }
139
140                 return NT_STATUS_OK;
141         } 
142         
143         return NT_STATUS_INVALID_HANDLE;
144 }
145
146
147 /* 
148   lsa_EnumPrivs 
149 */
150 static NTSTATUS lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
151                               struct lsa_EnumPrivs *r)
152 {
153         struct dcesrv_handle *h;
154         struct lsa_policy_state *state;
155         int i;
156         const char *privname;
157
158         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
159
160         state = h->data;
161
162         i = *r->in.resume_handle;
163         if (i == 0) i = 1;
164
165         while ((privname = sec_privilege_name(i)) &&
166                r->out.privs->count < r->in.max_count) {
167                 struct lsa_PrivEntry *e;
168
169                 r->out.privs->privs = talloc_realloc(r->out.privs,
170                                                        r->out.privs->privs, 
171                                                        struct lsa_PrivEntry, 
172                                                        r->out.privs->count+1);
173                 if (r->out.privs->privs == NULL) {
174                         return NT_STATUS_NO_MEMORY;
175                 }
176                 e = &r->out.privs->privs[r->out.privs->count];
177                 e->luid.low = i;
178                 e->luid.high = 0;
179                 e->name.string = privname;
180                 r->out.privs->count++;
181                 i++;
182         }
183
184         *r->out.resume_handle = i;
185
186         return NT_STATUS_OK;
187 }
188
189
190 /* 
191   lsa_QuerySecObj 
192 */
193 static NTSTATUS lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
194                                   struct lsa_QuerySecurity *r)
195 {
196         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
197 }
198
199
200 /* 
201   lsa_SetSecObj 
202 */
203 static NTSTATUS lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
204                               struct lsa_SetSecObj *r)
205 {
206         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
207 }
208
209
210 /* 
211   lsa_ChangePassword 
212 */
213 static NTSTATUS lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
214                                    struct lsa_ChangePassword *r)
215 {
216         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
217 }
218
219 static NTSTATUS lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
220                                      struct lsa_policy_state **_state)
221 {
222         struct lsa_policy_state *state;
223         const char *sid_str;
224
225         state = talloc(mem_ctx, struct lsa_policy_state);
226         if (!state) {
227                 return NT_STATUS_NO_MEMORY;
228         }
229
230         /* make sure the sam database is accessible */
231         state->sam_ctx = samdb_connect(state);
232         if (state->sam_ctx == NULL) {
233                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
234         }
235
236         state->sidmap = sidmap_open(state);
237         if (state->sidmap == NULL) {
238                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
239         }
240
241         /* work out the domain_dn - useful for so many calls its worth
242            fetching here */
243         state->domain_dn = talloc_reference(state, 
244                                             samdb_search_string(state->sam_ctx, mem_ctx, NULL,
245                                                                 "dn", "(&(objectClass=domain)(!(objectclass=builtinDomain)))"));
246         if (!state->domain_dn) {
247                 return NT_STATUS_NO_SUCH_DOMAIN;                
248         }
249
250         /* work out the builtin_dn - useful for so many calls its worth
251            fetching here */
252         state->builtin_dn = talloc_reference(state, 
253                                              samdb_search_string(state->sam_ctx, mem_ctx, NULL,
254                                                 "dn", "objectClass=builtinDomain"));
255         if (!state->builtin_dn) {
256                 return NT_STATUS_NO_SUCH_DOMAIN;                
257         }
258
259         /* work out the system_dn - useful for so many calls its worth
260            fetching here */
261         state->system_dn = talloc_reference(state, 
262                                              samdb_search_string(state->sam_ctx, mem_ctx, state->domain_dn,
263                                                "dn", "(&(objectClass=container)(cn=System))"));
264         if (!state->system_dn) {
265                 return NT_STATUS_NO_SUCH_DOMAIN;                
266         }
267
268         sid_str = samdb_search_string(state->sam_ctx, mem_ctx, NULL,
269                                       "objectSid", "dn=%s", state->domain_dn);
270         if (!sid_str) {
271                 return NT_STATUS_NO_SUCH_DOMAIN;                
272         }
273
274         state->domain_sid = dom_sid_parse_talloc(state, sid_str);
275         if (!state->domain_sid) {
276                 return NT_STATUS_NO_SUCH_DOMAIN;                
277         }
278
279         state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN);
280         if (!state->builtin_sid) {
281                 return NT_STATUS_NO_SUCH_DOMAIN;                
282         }
283
284         state->domain_name = talloc_reference(state, 
285                                               samdb_search_string(state->sam_ctx, mem_ctx, NULL,
286                                                                   "name", "dn=%s", state->domain_dn));
287         if (!state->domain_name) {
288                 return NT_STATUS_NO_SUCH_DOMAIN;                
289         }
290
291         *_state = state;
292
293         return NT_STATUS_OK;
294 }
295
296 /* 
297   lsa_OpenPolicy2
298 */
299 static NTSTATUS lsa_OpenPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
300                                struct lsa_OpenPolicy2 *r)
301 {
302         NTSTATUS status;
303         struct lsa_policy_state *state;
304         struct dcesrv_handle *handle;
305
306         ZERO_STRUCTP(r->out.handle);
307
308         status = lsa_get_policy_state(dce_call, mem_ctx, &state);
309         if (!NT_STATUS_IS_OK(status)) {
310                 return status;
311         }
312
313         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_POLICY);
314         if (!handle) {
315                 return NT_STATUS_NO_MEMORY;
316         }
317
318         handle->data = talloc_steal(handle, state);
319
320         state->access_mask = r->in.access_mask;
321         state->handle = handle;
322         *r->out.handle = handle->wire_handle;
323
324         /* note that we have completely ignored the attr element of
325            the OpenPolicy. As far as I can tell, this is what w2k3
326            does */
327
328         return NT_STATUS_OK;
329 }
330
331 /* 
332   lsa_OpenPolicy
333   a wrapper around lsa_OpenPolicy2
334 */
335 static NTSTATUS lsa_OpenPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
336                                 struct lsa_OpenPolicy *r)
337 {
338         struct lsa_OpenPolicy2 r2;
339
340         r2.in.system_name = NULL;
341         r2.in.attr = r->in.attr;
342         r2.in.access_mask = r->in.access_mask;
343         r2.out.handle = r->out.handle;
344
345         return lsa_OpenPolicy2(dce_call, mem_ctx, &r2);
346 }
347
348
349
350
351 /*
352   fill in the AccountDomain info
353 */
354 static NTSTATUS lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
355                                        struct lsa_DomainInfo *info)
356 {
357         const char * const attrs[] = { "objectSid", "name", NULL};
358         int ret;
359         struct ldb_message **res;
360
361         ret = samdb_search(state->sam_ctx, mem_ctx, NULL, &res, attrs, 
362                            "dn=%s", state->domain_dn);
363         if (ret != 1) {
364                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
365         }
366
367         info->name.string = samdb_result_string(res[0], "name", NULL);
368         info->sid         = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
369
370         return NT_STATUS_OK;
371 }
372
373 /*
374   fill in the DNS domain info
375 */
376 static NTSTATUS lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
377                              struct lsa_DnsDomainInfo *info)
378 {
379         const char * const attrs[] = { "name", "dnsDomain", "objectGUID", "objectSid", NULL };
380         int ret;
381         struct ldb_message **res;
382
383         ret = samdb_search(state->sam_ctx, mem_ctx, NULL, &res, attrs, 
384                            "dn=%s", state->domain_dn);
385         if (ret != 1) {
386                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
387         }
388
389         info->name.string       = samdb_result_string(res[0],           "name", NULL);
390         info->dns_domain.string = samdb_result_string(res[0],           "dnsDomain", NULL);
391         info->dns_forest.string = samdb_result_string(res[0],           "dnsDomain", NULL);
392         info->domain_guid       = samdb_result_guid(res[0],             "objectGUID");
393         info->sid               = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
394
395         return NT_STATUS_OK;
396 }
397
398 /* 
399   lsa_QueryInfoPolicy2
400 */
401 static NTSTATUS lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
402                                      struct lsa_QueryInfoPolicy2 *r)
403 {
404         struct lsa_policy_state *state;
405         struct dcesrv_handle *h;
406
407         r->out.info = NULL;
408
409         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
410
411         state = h->data;
412
413         r->out.info = talloc(mem_ctx, union lsa_PolicyInformation);
414         if (!r->out.info) {
415                 return NT_STATUS_NO_MEMORY;
416         }
417
418         ZERO_STRUCTP(r->out.info);
419
420         switch (r->in.level) {
421         case LSA_POLICY_INFO_DOMAIN:
422         case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
423                 return lsa_info_AccountDomain(state, mem_ctx, &r->out.info->account_domain);
424
425         case LSA_POLICY_INFO_DNS:
426                 return lsa_info_DNS(state, mem_ctx, &r->out.info->dns);
427         }
428
429         return NT_STATUS_INVALID_INFO_CLASS;
430 }
431
432 /* 
433   lsa_QueryInfoPolicy 
434 */
435 static NTSTATUS lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
436                                     struct lsa_QueryInfoPolicy *r)
437 {
438         struct lsa_QueryInfoPolicy2 r2;
439         NTSTATUS status;
440
441         r2.in.handle = r->in.handle;
442         r2.in.level = r->in.level;
443         
444         status = lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
445
446         r->out.info = r2.out.info;
447
448         return status;
449 }
450
451 /* 
452   lsa_SetInfoPolicy 
453 */
454 static NTSTATUS lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
455                                   struct lsa_SetInfoPolicy *r)
456 {
457         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
458 }
459
460
461 /* 
462   lsa_ClearAuditLog 
463 */
464 static NTSTATUS lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
465                                   struct lsa_ClearAuditLog *r)
466 {
467         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
468 }
469
470
471 /* 
472   lsa_CreateAccount 
473 */
474 static NTSTATUS lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
475                                   struct lsa_CreateAccount *r)
476 {
477         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
478 }
479
480
481 /* 
482   lsa_EnumAccounts 
483 */
484 static NTSTATUS lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
485                                  struct lsa_EnumAccounts *r)
486 {
487         struct dcesrv_handle *h;
488         struct lsa_policy_state *state;
489         int ret, i;
490         struct ldb_message **res;
491         const char * const attrs[] = { "objectSid", NULL};
492         uint32_t count;
493
494         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
495
496         state = h->data;
497
498         ret = samdb_search(state->sam_ctx, mem_ctx, state->builtin_dn, &res, attrs, 
499                            "privilege=*");
500         if (ret <= 0) {
501                 return NT_STATUS_NO_SUCH_USER;
502         }
503
504         if (*r->in.resume_handle >= ret) {
505                 return NT_STATUS_NO_MORE_ENTRIES;
506         }
507
508         count = ret - *r->in.resume_handle;
509         if (count > r->in.num_entries) {
510                 count = r->in.num_entries;
511         }
512
513         if (count == 0) {
514                 return NT_STATUS_NO_MORE_ENTRIES;
515         }
516
517         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
518         if (r->out.sids->sids == NULL) {
519                 return NT_STATUS_NO_MEMORY;
520         }
521
522         for (i=0;i<count;i++) {
523                 const char *sidstr;
524
525                 sidstr = samdb_result_string(res[i + *r->in.resume_handle], "objectSid", NULL);
526                 if (sidstr == NULL) {
527                         return NT_STATUS_NO_MEMORY;
528                 }
529                 r->out.sids->sids[i].sid = dom_sid_parse_talloc(r->out.sids->sids, sidstr);
530                 if (r->out.sids->sids[i].sid == NULL) {
531                         return NT_STATUS_NO_MEMORY;
532                 }
533         }
534
535         r->out.sids->num_sids = count;
536         *r->out.resume_handle = count + *r->in.resume_handle;
537
538         return NT_STATUS_OK;
539         
540 }
541
542
543 /*
544   lsa_CreateTrustedDomainEx2
545 */
546 static NTSTATUS lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
547                                            TALLOC_CTX *mem_ctx,
548                                            struct lsa_CreateTrustedDomainEx2 *r)
549 {
550         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
551 }
552
553 /*
554   lsa_CreateTrustedDomainEx
555 */
556 static NTSTATUS lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
557                                           TALLOC_CTX *mem_ctx,
558                                           struct lsa_CreateTrustedDomainEx *r)
559 {
560         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
561 }
562
563 /* 
564   lsa_CreateTrustedDomain 
565 */
566 static NTSTATUS lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
567                                         struct lsa_CreateTrustedDomain *r)
568 {
569         struct dcesrv_handle *policy_handle;
570         struct lsa_policy_state *policy_state;
571         struct lsa_trusted_domain_state *trusted_domain_state;
572         struct dcesrv_handle *handle;
573         struct ldb_message **msgs, *msg;
574         const char *attrs[] = {
575                 NULL
576         };
577         const char *name;
578         int ret;
579
580         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
581         ZERO_STRUCTP(r->out.trustdom_handle);
582         
583         policy_state = policy_handle->data;
584
585         if (!r->in.info->name.string) {
586                 return NT_STATUS_INVALID_PARAMETER;
587         }
588         name = r->in.info->name.string;
589         
590         trusted_domain_state = talloc(mem_ctx, struct lsa_trusted_domain_state);
591         if (!trusted_domain_state) {
592                 return NT_STATUS_NO_MEMORY;
593         }
594         trusted_domain_state->policy = policy_state;
595
596         msg = ldb_msg_new(mem_ctx);
597         if (msg == NULL) {
598                 return NT_STATUS_NO_MEMORY;
599         }
600
601         /* search for the trusted_domain record */
602         ret = samdb_search(trusted_domain_state->policy->sam_ctx,
603                            mem_ctx, policy_state->system_dn, &msgs, attrs,
604                            "(&(cn=%s)(objectclass=trustedDomain))", 
605                            r->in.info->name.string);
606         if (ret > 0) {
607                 return NT_STATUS_OBJECT_NAME_COLLISION;
608         }
609         
610         if (ret < 0 || ret > 1) {
611                 DEBUG(0,("Found %d records matching DN %s\n", ret, policy_state->system_dn));
612                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
613         }
614         
615         msg->dn = talloc_asprintf(mem_ctx, "cn=%s,%s", r->in.info->name.string, 
616                                   policy_state->system_dn);
617         if (!msg->dn) {
618                 return NT_STATUS_NO_MEMORY;
619         }
620         
621         samdb_msg_add_string(trusted_domain_state->policy->sam_ctx, mem_ctx, msg, "cn", name);
622         samdb_msg_add_string(trusted_domain_state->policy->sam_ctx, mem_ctx, msg, "flatname", name);
623
624         if (r->in.info->sid) {
625                 const char *sid_string = dom_sid_string(mem_ctx, r->in.info->sid);
626                 if (!sid_string) {
627                         return NT_STATUS_NO_MEMORY;
628                 }
629                         
630                 samdb_msg_add_string(trusted_domain_state->policy->sam_ctx, mem_ctx, msg, "securityIdentifier", sid_string);
631         }
632
633         /* pull in all the template attributes.  Note this is always from the global samdb */
634         ret = samdb_copy_template(trusted_domain_state->policy->sam_ctx, mem_ctx, msg, 
635                                   "(&(name=TemplateTrustedDomain)(objectclass=trustedDomainTemplate))");
636         if (ret != 0) {
637                 DEBUG(0,("Failed to load TemplateTrustedDomain from samdb\n"));
638                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
639         }
640
641         samdb_msg_add_string(trusted_domain_state->policy->sam_ctx, mem_ctx, msg, "objectClass", "trustedDomain");
642         
643         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
644
645         /* create the trusted_domain */
646         ret = samdb_add(trusted_domain_state->policy->sam_ctx, mem_ctx, msg);
647         if (ret != 0) {
648                 DEBUG(0,("Failed to create trusted_domain record %s\n", msg->dn));
649                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
650         }
651
652         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
653         if (!handle) {
654                 return NT_STATUS_NO_MEMORY;
655         }
656         
657         handle->data = talloc_steal(handle, trusted_domain_state);
658         
659         trusted_domain_state->access_mask = r->in.access_mask;
660         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
661         
662         *r->out.trustdom_handle = handle->wire_handle;
663         
664         return NT_STATUS_OK;
665 }
666
667 /* 
668   lsa_OpenTrustedDomain
669 */
670 static NTSTATUS lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
671                                       struct lsa_OpenTrustedDomain *r)
672 {
673         struct dcesrv_handle *policy_handle;
674         
675         struct lsa_policy_state *policy_state;
676         struct lsa_trusted_domain_state *trusted_domain_state;
677         struct dcesrv_handle *handle;
678         struct ldb_message **msgs;
679         const char *attrs[] = {
680                 NULL
681         };
682
683         const char *sid_string;
684         int ret;
685
686         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
687         ZERO_STRUCTP(r->out.trustdom_handle);
688         policy_state = policy_handle->data;
689
690         trusted_domain_state = talloc(mem_ctx, struct lsa_trusted_domain_state);
691         if (!trusted_domain_state) {
692                 return NT_STATUS_NO_MEMORY;
693         }
694         trusted_domain_state->policy = policy_state;
695
696         sid_string = dom_sid_string(mem_ctx, r->in.sid);
697         if (!sid_string) {
698                 return NT_STATUS_NO_MEMORY;
699         }
700
701         /* search for the trusted_domain record */
702         ret = samdb_search(trusted_domain_state->policy->sam_ctx,
703                            mem_ctx, policy_state->system_dn, &msgs, attrs,
704                            "(&(securityIdentifier=%s)(objectclass=trustedDomain))", 
705                            sid_string);
706         if (ret == 0) {
707                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
708         }
709         
710         if (ret != 1) {
711                 DEBUG(0,("Found %d records matching DN %s\n", ret, policy_state->system_dn));
712                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
713         }
714
715         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
716         
717         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
718         if (!handle) {
719                 return NT_STATUS_NO_MEMORY;
720         }
721         
722         handle->data = talloc_steal(handle, trusted_domain_state);
723         
724         trusted_domain_state->access_mask = r->in.access_mask;
725         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
726         
727         *r->out.trustdom_handle = handle->wire_handle;
728         
729         return NT_STATUS_OK;
730 }
731
732
733 /*
734   lsa_OpenTrustedDomainByName
735 */
736 static NTSTATUS lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
737                                             TALLOC_CTX *mem_ctx,
738                                             struct lsa_OpenTrustedDomainByName *r)
739 {
740         struct dcesrv_handle *policy_handle;
741         
742         struct lsa_policy_state *policy_state;
743         struct lsa_trusted_domain_state *trusted_domain_state;
744         struct dcesrv_handle *handle;
745         struct ldb_message **msgs;
746         const char *attrs[] = {
747                 NULL
748         };
749
750         int ret;
751
752         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
753         ZERO_STRUCTP(r->out.trustdom_handle);
754         policy_state = policy_handle->data;
755
756         if (!r->in.name.string) {
757                 return NT_STATUS_INVALID_PARAMETER;
758         }
759         
760         trusted_domain_state = talloc(mem_ctx, struct lsa_trusted_domain_state);
761         if (!trusted_domain_state) {
762                 return NT_STATUS_NO_MEMORY;
763         }
764         trusted_domain_state->policy = policy_state;
765
766         /* search for the trusted_domain record */
767         ret = samdb_search(trusted_domain_state->policy->sam_ctx,
768                            mem_ctx, policy_state->system_dn, &msgs, attrs,
769                            "(&(flatname=%s)(objectclass=trustedDomain))", 
770                            r->in.name.string);
771         if (ret == 0) {
772                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
773         }
774         
775         if (ret != 1) {
776                 DEBUG(0,("Found %d records matching DN %s\n", ret, policy_state->system_dn));
777                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
778         }
779
780         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
781         
782         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
783         if (!handle) {
784                 return NT_STATUS_NO_MEMORY;
785         }
786         
787         handle->data = talloc_steal(handle, trusted_domain_state);
788         
789         trusted_domain_state->access_mask = r->in.access_mask;
790         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
791         
792         *r->out.trustdom_handle = handle->wire_handle;
793         
794         return NT_STATUS_OK;
795 }
796
797
798 /* 
799   lsa_QueryTrustedDomainInfoBySid
800 */
801 static NTSTATUS lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
802                                                 struct lsa_QueryTrustedDomainInfoBySid *r)
803 {
804         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
805 }
806
807
808 /* 
809   lsa_SetTrustDomainInfo
810 */
811 static NTSTATUS lsa_SetTrustDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
812                        struct lsa_SetTrustDomainInfo *r)
813 {
814         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
815 }
816
817
818 /* 
819   lsa_DeleteTrustDomain
820 */
821 static NTSTATUS lsa_DeleteTrustDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
822                                       struct lsa_DeleteTrustDomain *r)
823 {
824         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
825 }
826
827
828 /* 
829   lsa_QueryTrustedDomainInfo
830 */
831 static NTSTATUS lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
832                                            struct lsa_QueryTrustedDomainInfo *r)
833 {
834         struct dcesrv_handle *h;
835         struct lsa_trusted_domain_state *trusted_domain_state;
836         struct ldb_message *msg;
837         int ret;
838         struct ldb_message **res;
839         const char *attrs[] = {
840                 "cn",
841                 "flatname",
842                 "posixOffset",
843                 "securityIdentifier",
844                 NULL
845         };
846
847         DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
848
849         trusted_domain_state = h->data;
850
851         /* pull all the user attributes */
852         ret = samdb_search(trusted_domain_state->policy->sam_ctx, mem_ctx, NULL, &res, attrs,
853                            "dn=%s", trusted_domain_state->trusted_domain_dn);
854         if (ret != 1) {
855                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
856         }
857         msg = res[0];
858         
859         r->out.info = talloc(mem_ctx, union lsa_TrustedDomainInfo);
860         if (!r->out.info) {
861                 return NT_STATUS_NO_MEMORY;
862         }
863         switch (r->in.level) {
864         case LSA_TRUSTED_DOMAIN_INFO_NAME:
865                 r->out.info->name.netbios_name.string
866                         = samdb_result_string(msg, "flatname", NULL);                                      
867                 break;
868         case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
869                 r->out.info->posix_offset.posix_offset
870                         = samdb_result_uint(msg, "posixOffset", 0);                                        
871                 break;
872         default:
873                 /* oops, we don't want to return the info after all */
874                 talloc_free(r->out.info);
875                 r->out.info = NULL;
876                 return NT_STATUS_INVALID_INFO_CLASS;
877         }
878
879         return NT_STATUS_OK;
880 }
881
882
883 /* 
884   lsa_SetInformationTrustedDomain
885 */
886 static NTSTATUS lsa_SetInformationTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
887                        struct lsa_SetInformationTrustedDomain *r)
888 {
889         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
890 }
891
892
893 /*
894   lsa_QueryTrustedDomainInfoByName
895 */
896 static NTSTATUS lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
897                                                  TALLOC_CTX *mem_ctx,
898                                                  struct lsa_QueryTrustedDomainInfoByName *r)
899 {
900         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
901 }
902
903 /*
904   lsa_SetTrustedDomainInfoByName
905 */
906 static NTSTATUS lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
907                                                TALLOC_CTX *mem_ctx,
908                                                struct lsa_SetTrustedDomainInfoByName *r)
909 {
910         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
911 }
912
913 /*
914   lsa_EnumTrustedDomainsEx
915 */
916 static NTSTATUS lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call,
917                                          TALLOC_CTX *mem_ctx,
918                                          struct lsa_EnumTrustedDomainsEx *r)
919 {
920         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
921 }
922
923 /*
924   lsa_CloseTrustedDomainEx
925 */
926 static NTSTATUS lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
927                                          TALLOC_CTX *mem_ctx,
928                                          struct lsa_CloseTrustedDomainEx *r)
929 {
930         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
931 }
932
933
934 /*
935   comparison function for sorting lsa_DomainInformation array
936 */
937 static int compare_DomainInformation(struct lsa_DomainInformation *e1, struct lsa_DomainInformation *e2)
938 {
939         return strcasecmp(e1->name.string, e2->name.string);
940 }
941
942 /* 
943   lsa_EnumTrustDom 
944 */
945 static NTSTATUS lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
946                                  struct lsa_EnumTrustDom *r)
947 {
948         struct dcesrv_handle *policy_handle;
949         struct lsa_DomainInformation *entries;
950         struct lsa_policy_state *policy_state;
951         struct ldb_message **domains;
952         const char *attrs[] = {
953                 "flatname", 
954                 "securityIdentifier",
955                 NULL
956         };
957
958
959         int count, i;
960
961         *r->out.resume_handle = 0;
962
963         r->out.domains->domains = NULL;
964         r->out.domains->count = 0;
965
966         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
967
968         policy_state = policy_handle->data;
969
970         /* search for all users in this domain. This could possibly be cached and 
971            resumed based on resume_key */
972         count = samdb_search(policy_state->sam_ctx, mem_ctx, policy_state->system_dn, &domains, attrs, 
973                              "objectclass=trustedDomain");
974         if (count == -1) {
975                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
976         }
977         if (count == 0 || r->in.max_size == 0) {
978                 return NT_STATUS_OK;
979         }
980
981         /* convert to lsa_DomainInformation format */
982         entries = talloc_array(mem_ctx, struct lsa_DomainInformation, count);
983         if (!entries) {
984                 return NT_STATUS_NO_MEMORY;
985         }
986         for (i=0;i<count;i++) {
987                 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
988                 entries[i].name.string = samdb_result_string(domains[i], "flatname", NULL);
989         }
990
991         /* sort the results by name */
992         qsort(entries, count, sizeof(struct lsa_DomainInformation), 
993               (comparison_fn_t)compare_DomainInformation);
994
995         if (*r->in.resume_handle >= count) {
996                 *r->out.resume_handle = -1;
997
998                 return NT_STATUS_NO_MORE_ENTRIES;
999         }
1000
1001         /* return the rest, limit by max_size. Note that we 
1002            use the w2k3 element size value of 60 */
1003         r->out.domains->count = count - *r->in.resume_handle;
1004         r->out.domains->count = MIN(r->out.domains->count, 
1005                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
1006
1007         r->out.domains->domains = entries + *r->in.resume_handle;
1008         r->out.domains->count = r->out.domains->count;
1009
1010         if (r->out.domains->count < count - *r->in.resume_handle) {
1011                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
1012                 return STATUS_MORE_ENTRIES;
1013         }
1014
1015         return NT_STATUS_OK;
1016 }
1017
1018
1019 /*
1020   return the authority name and authority sid, given a sid
1021 */
1022 static NTSTATUS lsa_authority_name(struct lsa_policy_state *state,
1023                                    TALLOC_CTX *mem_ctx, struct dom_sid *sid,
1024                                    const char **authority_name,
1025                                    struct dom_sid **authority_sid)
1026 {
1027         if (dom_sid_in_domain(state->domain_sid, sid)) {
1028                 *authority_name = state->domain_name;
1029                 *authority_sid = state->domain_sid;
1030                 return NT_STATUS_OK;
1031         }
1032
1033         if (dom_sid_in_domain(state->builtin_sid, sid)) {
1034                 *authority_name = "BUILTIN";
1035                 *authority_sid = state->builtin_sid;
1036                 return NT_STATUS_OK;
1037         }
1038
1039         *authority_sid = dom_sid_dup(mem_ctx, sid);
1040         if (*authority_sid == NULL) {
1041                 return NT_STATUS_NO_MEMORY;
1042         }
1043         (*authority_sid)->num_auths = 0;
1044         *authority_name = dom_sid_string(mem_ctx, *authority_sid);
1045         if (*authority_name == NULL) {
1046                 return NT_STATUS_NO_MEMORY;
1047         }
1048
1049         return NT_STATUS_OK;
1050 }
1051
1052 /*
1053   add to the lsa_RefDomainList for LookupSids and LookupNames
1054 */
1055 static NTSTATUS lsa_authority_list(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx, 
1056                                    struct dom_sid *sid, 
1057                                    struct lsa_RefDomainList *domains,
1058                                    uint32_t *sid_index)
1059 {
1060         NTSTATUS status;
1061         const char *authority_name;
1062         struct dom_sid *authority_sid;
1063         int i;
1064
1065         /* work out the authority name */
1066         status = lsa_authority_name(state, mem_ctx, sid, 
1067                                     &authority_name, &authority_sid);
1068         if (!NT_STATUS_IS_OK(status)) {
1069                 return status;
1070         }
1071         
1072         /* see if we've already done this authority name */
1073         for (i=0;i<domains->count;i++) {
1074                 if (strcmp(authority_name, domains->domains[i].name.string) == 0) {
1075                         *sid_index = i;
1076                         return NT_STATUS_OK;
1077                 }
1078         }
1079
1080         domains->domains = talloc_realloc(domains, 
1081                                             domains->domains,
1082                                             struct lsa_TrustInformation,
1083                                             domains->count+1);
1084         if (domains->domains == NULL) {
1085                 return NT_STATUS_NO_MEMORY;
1086         }
1087         domains->domains[i].name.string = authority_name;
1088         domains->domains[i].sid         = authority_sid;
1089         domains->count++;
1090         *sid_index = i;
1091         
1092         return NT_STATUS_OK;
1093 }
1094
1095 /*
1096   lookup a name for 1 SID
1097 */
1098 static NTSTATUS lsa_lookup_sid(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
1099                                struct dom_sid *sid, const char *sid_str,
1100                                const char **name, uint32_t *atype)
1101 {
1102         int ret;
1103         struct ldb_message **res;
1104         const char * const attrs[] = { "sAMAccountName", "sAMAccountType", "name", NULL};
1105         NTSTATUS status;
1106
1107         ret = samdb_search(state->sam_ctx, mem_ctx, NULL, &res, attrs, 
1108                            "objectSid=%s", sid_str);
1109         if (ret == 1) {
1110                 *name = ldb_msg_find_string(res[0], "sAMAccountName", NULL);
1111                 if (!*name) {
1112                         *name = ldb_msg_find_string(res[0], "name", NULL);
1113                         if (!*name) {
1114                                 *name = talloc_strdup(mem_ctx, sid_str);
1115                                 NTSTATUS_TALLOC_CHECK(*name);
1116                         }
1117                 }
1118
1119                 *atype = samdb_result_uint(res[0], "sAMAccountType", 0);
1120
1121                 return NT_STATUS_OK;
1122         }
1123
1124         status = sidmap_allocated_sid_lookup(state->sidmap, mem_ctx, sid, name, atype);
1125
1126         return status;
1127 }
1128
1129
1130 /*
1131   lsa_LookupSids3
1132 */
1133 static NTSTATUS lsa_LookupSids3(struct dcesrv_call_state *dce_call,
1134                                 TALLOC_CTX *mem_ctx,
1135                                 struct lsa_LookupSids3 *r)
1136 {
1137         struct lsa_policy_state *state;
1138         int i;
1139         NTSTATUS status = NT_STATUS_OK;
1140
1141         r->out.domains = NULL;
1142
1143         status = lsa_get_policy_state(dce_call, mem_ctx, &state);
1144         if (!NT_STATUS_IS_OK(status)) {
1145                 return status;
1146         }
1147
1148         r->out.domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
1149         if (r->out.domains == NULL) {
1150                 return NT_STATUS_NO_MEMORY;
1151         }
1152
1153         r->out.names = talloc_zero(mem_ctx,  struct lsa_TransNameArray2);
1154         if (r->out.names == NULL) {
1155                 return NT_STATUS_NO_MEMORY;
1156         }
1157
1158         *r->out.count = 0;
1159
1160         r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName2, 
1161                                              r->in.sids->num_sids);
1162         if (r->out.names->names == NULL) {
1163                 return NT_STATUS_NO_MEMORY;
1164         }
1165
1166         for (i=0;i<r->in.sids->num_sids;i++) {
1167                 struct dom_sid *sid = r->in.sids->sids[i].sid;
1168                 char *sid_str = dom_sid_string(mem_ctx, sid);
1169                 const char *name;
1170                 uint32_t atype, rtype, sid_index;
1171                 NTSTATUS status2;
1172
1173                 r->out.names->count++;
1174                 (*r->out.count)++;
1175
1176                 r->out.names->names[i].sid_type    = SID_NAME_UNKNOWN;
1177                 r->out.names->names[i].name.string = sid_str;
1178                 r->out.names->names[i].sid_index   = 0xFFFFFFFF;
1179                 r->out.names->names[i].unknown     = 0;
1180
1181                 if (sid_str == NULL) {
1182                         r->out.names->names[i].name.string = "(SIDERROR)";
1183                         status = STATUS_SOME_UNMAPPED;
1184                         continue;
1185                 }
1186
1187                 /* work out the authority name */
1188                 status2 = lsa_authority_list(state, mem_ctx, sid, r->out.domains, &sid_index);
1189                 if (!NT_STATUS_IS_OK(status2)) {
1190                         return status2;
1191                 }
1192
1193                 status2 = lsa_lookup_sid(state, mem_ctx, sid, sid_str, 
1194                                          &name, &atype);
1195                 if (!NT_STATUS_IS_OK(status2)) {
1196                         status = STATUS_SOME_UNMAPPED;
1197                         continue;
1198                 }
1199
1200                 rtype = samdb_atype_map(atype);
1201                 if (rtype == SID_NAME_UNKNOWN) {
1202                         status = STATUS_SOME_UNMAPPED;
1203                         continue;
1204                 }
1205
1206                 r->out.names->names[i].sid_type    = rtype;
1207                 r->out.names->names[i].name.string = name;
1208                 r->out.names->names[i].sid_index   = sid_index;
1209                 r->out.names->names[i].unknown     = 0;
1210         }
1211         
1212         return status;
1213 }
1214
1215
1216 /*
1217   lsa_LookupSids2
1218 */
1219 static NTSTATUS lsa_LookupSids2(struct dcesrv_call_state *dce_call,
1220                                 TALLOC_CTX *mem_ctx,
1221                                 struct lsa_LookupSids2 *r)
1222 {
1223         struct lsa_LookupSids3 r3;
1224         NTSTATUS status;
1225
1226         r3.in.sids     = r->in.sids;
1227         r3.in.names    = r->in.names;
1228         r3.in.level    = r->in.level;
1229         r3.in.count    = r->in.count;
1230         r3.in.unknown1 = r->in.unknown1;
1231         r3.in.unknown2 = r->in.unknown2;
1232         r3.out.count   = r->out.count;
1233         r3.out.names   = r->out.names;
1234
1235         status = lsa_LookupSids3(dce_call, mem_ctx, &r3);
1236         if (dce_call->fault_code != 0) {
1237                 return status;
1238         }
1239
1240         r->out.domains = r3.out.domains;
1241         r->out.names   = r3.out.names;
1242         r->out.count   = r3.out.count;
1243
1244         return status;
1245 }
1246
1247
1248 /* 
1249   lsa_LookupSids 
1250 */
1251 static NTSTATUS lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1252                                struct lsa_LookupSids *r)
1253 {
1254         struct lsa_LookupSids3 r3;
1255         NTSTATUS status;
1256         int i;
1257
1258         r3.in.sids     = r->in.sids;
1259         r3.in.names    = NULL;
1260         r3.in.level    = r->in.level;
1261         r3.in.count    = r->in.count;
1262         r3.in.unknown1 = 0;
1263         r3.in.unknown2 = 0;
1264         r3.out.count   = r->out.count;
1265
1266         status = lsa_LookupSids3(dce_call, mem_ctx, &r3);
1267         if (dce_call->fault_code != 0) {
1268                 return status;
1269         }
1270
1271         r->out.domains = r3.out.domains;
1272         r->out.names = talloc(mem_ctx, struct lsa_TransNameArray);
1273         if (r->out.names == NULL) {
1274                 return NT_STATUS_NO_MEMORY;
1275         }
1276         r->out.names->count = r3.out.names->count;
1277         r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName, 
1278                                              r->out.names->count);
1279         if (r->out.names->names == NULL) {
1280                 return NT_STATUS_NO_MEMORY;
1281         }
1282         for (i=0;i<r->out.names->count;i++) {
1283                 r->out.names->names[i].sid_type    = r3.out.names->names[i].sid_type;
1284                 r->out.names->names[i].name.string = r3.out.names->names[i].name.string;
1285                 r->out.names->names[i].sid_index   = r3.out.names->names[i].sid_index;
1286         }
1287
1288         return status;
1289 }
1290
1291
1292 /* 
1293   lsa_OpenAccount 
1294 */
1295 static NTSTATUS lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1296                                 struct lsa_OpenAccount *r)
1297 {
1298         struct dcesrv_handle *h, *ah;
1299         struct lsa_policy_state *state;
1300         struct lsa_account_state *astate;
1301
1302         ZERO_STRUCTP(r->out.acct_handle);
1303
1304         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
1305
1306         state = h->data;
1307
1308         astate = talloc(dce_call->conn, struct lsa_account_state);
1309         if (astate == NULL) {
1310                 return NT_STATUS_NO_MEMORY;
1311         }
1312
1313         astate->account_sid = dom_sid_dup(astate, r->in.sid);
1314         if (astate->account_sid == NULL) {
1315                 talloc_free(astate);
1316                 return NT_STATUS_NO_MEMORY;
1317         }
1318         
1319         astate->account_sid_str = dom_sid_string(astate, astate->account_sid);
1320         if (astate->account_sid_str == NULL) {
1321                 talloc_free(astate);
1322                 return NT_STATUS_NO_MEMORY;
1323         }
1324
1325         /* check it really exists */
1326         astate->account_dn = samdb_search_string(state->sam_ctx, astate,
1327                                                  NULL, "dn", 
1328                                                  "(&(objectSid=%s)(objectClass=group))", 
1329                                                  astate->account_sid_str);
1330         if (astate->account_dn == NULL) {
1331                 talloc_free(astate);
1332                 return NT_STATUS_NO_SUCH_USER;
1333         }
1334         
1335         astate->policy = talloc_reference(astate, state);
1336         astate->access_mask = r->in.access_mask;
1337
1338         ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
1339         if (!ah) {
1340                 talloc_free(astate);
1341                 return NT_STATUS_NO_MEMORY;
1342         }
1343
1344         ah->data = talloc_steal(ah, astate);
1345
1346         *r->out.acct_handle = ah->wire_handle;
1347
1348         return NT_STATUS_OK;
1349 }
1350
1351
1352 /* 
1353   lsa_EnumPrivsAccount 
1354 */
1355 static NTSTATUS lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call, 
1356                                      TALLOC_CTX *mem_ctx,
1357                                      struct lsa_EnumPrivsAccount *r)
1358 {
1359         struct dcesrv_handle *h;
1360         struct lsa_account_state *astate;
1361         int ret, i;
1362         struct ldb_message **res;
1363         const char * const attrs[] = { "privilege", NULL};
1364         struct ldb_message_element *el;
1365
1366         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
1367
1368         astate = h->data;
1369
1370         r->out.privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
1371         r->out.privs->count = 0;
1372         r->out.privs->unknown = 0;
1373         r->out.privs->set = NULL;
1374
1375         ret = samdb_search(astate->policy->sam_ctx, mem_ctx, NULL, &res, attrs, 
1376                            "dn=%s", astate->account_dn);
1377         if (ret != 1) {
1378                 return NT_STATUS_OK;
1379         }
1380
1381         el = ldb_msg_find_element(res[0], "privilege");
1382         if (el == NULL || el->num_values == 0) {
1383                 return NT_STATUS_OK;
1384         }
1385
1386         r->out.privs->set = talloc_array(r->out.privs, 
1387                                            struct lsa_LUIDAttribute, el->num_values);
1388         if (r->out.privs->set == NULL) {
1389                 return NT_STATUS_NO_MEMORY;
1390         }
1391
1392         for (i=0;i<el->num_values;i++) {
1393                 int id = sec_privilege_id(el->values[i].data);
1394                 if (id == -1) {
1395                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1396                 }
1397                 r->out.privs->set[i].attribute = 0;
1398                 r->out.privs->set[i].luid.low = id;
1399                 r->out.privs->set[i].luid.high = 0;
1400         }
1401
1402         r->out.privs->count = el->num_values;
1403
1404         return NT_STATUS_OK;
1405 }
1406
1407 /* 
1408   lsa_EnumAccountRights 
1409 */
1410 static NTSTATUS lsa_EnumAccountRights(struct dcesrv_call_state *dce_call, 
1411                                       TALLOC_CTX *mem_ctx,
1412                                       struct lsa_EnumAccountRights *r)
1413 {
1414         struct dcesrv_handle *h;
1415         struct lsa_policy_state *state;
1416         int ret, i;
1417         struct ldb_message **res;
1418         const char * const attrs[] = { "privilege", NULL};
1419         const char *sidstr;
1420         struct ldb_message_element *el;
1421
1422         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
1423
1424         state = h->data;
1425
1426         sidstr = dom_sid_string(mem_ctx, r->in.sid);
1427         if (sidstr == NULL) {
1428                 return NT_STATUS_NO_MEMORY;
1429         }
1430
1431         ret = samdb_search(state->sam_ctx, mem_ctx, NULL, &res, attrs, 
1432                            "objectSid=%s", sidstr);
1433         if (ret != 1) {
1434                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1435         }
1436
1437         el = ldb_msg_find_element(res[0], "privilege");
1438         if (el == NULL || el->num_values == 0) {
1439                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1440         }
1441
1442         r->out.rights->count = el->num_values;
1443         r->out.rights->names = talloc_array(r->out.rights, 
1444                                               struct lsa_String, r->out.rights->count);
1445         if (r->out.rights->names == NULL) {
1446                 return NT_STATUS_NO_MEMORY;
1447         }
1448
1449         for (i=0;i<el->num_values;i++) {
1450                 r->out.rights->names[i].string = el->values[i].data;
1451         }
1452
1453         return NT_STATUS_OK;
1454 }
1455
1456
1457
1458 /* 
1459   helper for lsa_AddAccountRights and lsa_RemoveAccountRights
1460 */
1461 static NTSTATUS lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call, 
1462                                            TALLOC_CTX *mem_ctx,
1463                                            struct lsa_policy_state *state,
1464                                            int ldb_flag,
1465                                            struct dom_sid *sid,
1466                                            const struct lsa_RightSet *rights)
1467 {
1468         const char *sidstr;
1469         struct ldb_message *msg;
1470         struct ldb_message_element el;
1471         int i, ret;
1472         const char *dn;
1473         struct lsa_EnumAccountRights r2;
1474
1475         sidstr = dom_sid_string(mem_ctx, sid);
1476         if (sidstr == NULL) {
1477                 return NT_STATUS_NO_MEMORY;
1478         }
1479
1480         msg = ldb_msg_new(mem_ctx);
1481         if (msg == NULL) {
1482                 return NT_STATUS_NO_MEMORY;
1483         }
1484
1485         dn = samdb_search_string(state->sam_ctx, mem_ctx, NULL, "dn", 
1486                                  "objectSid=%s", sidstr);
1487         if (dn == NULL) {
1488                 return NT_STATUS_NO_SUCH_USER;
1489         }
1490
1491         msg->dn = talloc_strdup(mem_ctx, dn);
1492         if (msg->dn == NULL) {
1493                 return NT_STATUS_NO_MEMORY;
1494         }
1495
1496         if (ldb_msg_add_empty(state->sam_ctx->ldb, msg, "privilege", ldb_flag)) {
1497                 return NT_STATUS_NO_MEMORY;
1498         }
1499
1500         if (ldb_flag == LDB_FLAG_MOD_ADD) {
1501                 NTSTATUS status;
1502
1503                 r2.in.handle = &state->handle->wire_handle;
1504                 r2.in.sid = sid;
1505                 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
1506
1507                 status = lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
1508                 if (!NT_STATUS_IS_OK(status)) {
1509                         ZERO_STRUCTP(r2.out.rights);
1510                 }
1511         }
1512
1513         el.num_values = 0;
1514         el.values = talloc_array(mem_ctx, struct ldb_val, rights->count);
1515         if (el.values == NULL) {
1516                 return NT_STATUS_NO_MEMORY;
1517         }
1518         for (i=0;i<rights->count;i++) {
1519                 if (sec_privilege_id(rights->names[i].string) == -1) {
1520                         return NT_STATUS_NO_SUCH_PRIVILEGE;
1521                 }
1522
1523                 if (ldb_flag == LDB_FLAG_MOD_ADD) {
1524                         int j;
1525                         for (j=0;j<r2.out.rights->count;j++) {
1526                                 if (StrCaseCmp(r2.out.rights->names[j].string, 
1527                                                rights->names[i].string) == 0) {
1528                                         break;
1529                                 }
1530                         }
1531                         if (j != r2.out.rights->count) continue;
1532                 }
1533
1534
1535                 el.values[el.num_values].length = strlen(rights->names[i].string);
1536                 el.values[el.num_values].data = talloc_strdup(mem_ctx, rights->names[i].string);
1537                 if (el.values[el.num_values].data == NULL) {
1538                         return NT_STATUS_NO_MEMORY;
1539                 }
1540                 el.num_values++;
1541         }
1542
1543         if (el.num_values == 0) {
1544                 return NT_STATUS_OK;
1545         }
1546
1547         ret = samdb_modify(state->sam_ctx, mem_ctx, msg);
1548         if (ret != 0) {
1549                 if (ldb_flag == LDB_FLAG_MOD_DELETE) {
1550                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1551                 }
1552                 return NT_STATUS_UNEXPECTED_IO_ERROR;
1553         }
1554
1555         return NT_STATUS_OK;
1556 }
1557
1558 /* 
1559   lsa_AddPrivilegesToAccount
1560 */
1561 static NTSTATUS lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1562                                            struct lsa_AddPrivilegesToAccount *r)
1563 {
1564         struct lsa_RightSet rights;
1565         struct dcesrv_handle *h;
1566         struct lsa_account_state *astate;
1567         int i;
1568
1569         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
1570
1571         astate = h->data;
1572
1573         rights.count = r->in.privs->count;
1574         rights.names = talloc_array(mem_ctx, struct lsa_String, rights.count);
1575         if (rights.names == NULL) {
1576                 return NT_STATUS_NO_MEMORY;
1577         }
1578         for (i=0;i<rights.count;i++) {
1579                 int id = r->in.privs->set[i].luid.low;
1580                 if (r->in.privs->set[i].luid.high) {
1581                         return NT_STATUS_NO_SUCH_PRIVILEGE;
1582                 }
1583                 rights.names[i].string = sec_privilege_name(id);
1584                 if (rights.names[i].string == NULL) {
1585                         return NT_STATUS_NO_SUCH_PRIVILEGE;
1586                 }
1587         }
1588
1589         return lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
1590                                           LDB_FLAG_MOD_ADD, astate->account_sid,
1591                                           &rights);
1592 }
1593
1594
1595 /* 
1596   lsa_RemovePrivilegesFromAccount
1597 */
1598 static NTSTATUS lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1599                                                 struct lsa_RemovePrivilegesFromAccount *r)
1600 {
1601         struct lsa_RightSet *rights;
1602         struct dcesrv_handle *h;
1603         struct lsa_account_state *astate;
1604         int i;
1605
1606         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
1607
1608         astate = h->data;
1609
1610         rights = talloc(mem_ctx, struct lsa_RightSet);
1611
1612         if (r->in.remove_all == 1 && 
1613             r->in.privs == NULL) {
1614                 struct lsa_EnumAccountRights r2;
1615                 NTSTATUS status;
1616
1617                 r2.in.handle = &astate->policy->handle->wire_handle;
1618                 r2.in.sid = astate->account_sid;
1619                 r2.out.rights = rights;
1620
1621                 status = lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
1622                 if (!NT_STATUS_IS_OK(status)) {
1623                         return status;
1624                 }
1625
1626                 return lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
1627                                                   LDB_FLAG_MOD_DELETE, astate->account_sid,
1628                                                   r2.out.rights);
1629         }
1630
1631         if (r->in.remove_all != 0) {
1632                 return NT_STATUS_INVALID_PARAMETER;
1633         }
1634
1635         rights->count = r->in.privs->count;
1636         rights->names = talloc_array(mem_ctx, struct lsa_String, rights->count);
1637         if (rights->names == NULL) {
1638                 return NT_STATUS_NO_MEMORY;
1639         }
1640         for (i=0;i<rights->count;i++) {
1641                 int id = r->in.privs->set[i].luid.low;
1642                 if (r->in.privs->set[i].luid.high) {
1643                         return NT_STATUS_NO_SUCH_PRIVILEGE;
1644                 }
1645                 rights->names[i].string = sec_privilege_name(id);
1646                 if (rights->names[i].string == NULL) {
1647                         return NT_STATUS_NO_SUCH_PRIVILEGE;
1648                 }
1649         }
1650
1651         return lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
1652                                           LDB_FLAG_MOD_DELETE, astate->account_sid,
1653                                           rights);
1654 }
1655
1656
1657 /* 
1658   lsa_GetQuotasForAccount
1659 */
1660 static NTSTATUS lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1661                        struct lsa_GetQuotasForAccount *r)
1662 {
1663         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1664 }
1665
1666
1667 /* 
1668   lsa_SetQuotasForAccount
1669 */
1670 static NTSTATUS lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1671                        struct lsa_SetQuotasForAccount *r)
1672 {
1673         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1674 }
1675
1676
1677 /* 
1678   lsa_GetSystemAccessAccount
1679 */
1680 static NTSTATUS lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1681                        struct lsa_GetSystemAccessAccount *r)
1682 {
1683         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1684 }
1685
1686
1687 /* 
1688   lsa_SetSystemAccessAccount
1689 */
1690 static NTSTATUS lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1691                        struct lsa_SetSystemAccessAccount *r)
1692 {
1693         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1694 }
1695
1696
1697 /* 
1698   lsa_CreateSecret 
1699 */
1700 static NTSTATUS lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1701                                  struct lsa_CreateSecret *r)
1702 {
1703         struct dcesrv_handle *policy_handle;
1704         struct lsa_policy_state *policy_state;
1705         struct lsa_secret_state *secret_state;
1706         struct dcesrv_handle *handle;
1707         struct ldb_message **msgs, *msg;
1708         const char *attrs[] = {
1709                 NULL
1710         };
1711
1712         const char *name;
1713
1714         int ret;
1715
1716         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1717         ZERO_STRUCTP(r->out.sec_handle);
1718         
1719         policy_state = policy_handle->data;
1720
1721         if (!r->in.name.string) {
1722                 return NT_STATUS_INVALID_PARAMETER;
1723         }
1724         
1725         secret_state = talloc(mem_ctx, struct lsa_secret_state);
1726         if (!secret_state) {
1727                 return NT_STATUS_NO_MEMORY;
1728         }
1729         secret_state->policy = policy_state;
1730
1731         msg = ldb_msg_new(mem_ctx);
1732         if (msg == NULL) {
1733                 return NT_STATUS_NO_MEMORY;
1734         }
1735
1736         if (strncmp("G$", r->in.name.string, 2) == 0) {
1737                 const char *name2;
1738                 name = &r->in.name.string[2];
1739                 secret_state->sam_ctx = talloc_reference(secret_state, policy_state->sam_ctx);
1740                 secret_state->global = True;
1741
1742                 if (strlen(name) < 1) {
1743                         return NT_STATUS_INVALID_PARAMETER;
1744                 }
1745
1746                 name2 = talloc_asprintf(mem_ctx, "%s Secret", name);
1747                 /* search for the secret record */
1748                 ret = samdb_search(secret_state->sam_ctx,
1749                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
1750                                    "(&(cn=%s)(objectclass=secret))", 
1751                                    name2);
1752                 if (ret > 0) {
1753                         return NT_STATUS_OBJECT_NAME_COLLISION;
1754                 }
1755                 
1756                 if (ret < 0 || ret > 1) {
1757                         DEBUG(0,("Found %d records matching DN %s\n", ret, policy_state->system_dn));
1758                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1759                 }
1760
1761                 msg->dn = talloc_asprintf(mem_ctx, "cn=%s,%s", name2, policy_state->system_dn);
1762                 if (!name2 || !msg->dn) {
1763                         return NT_STATUS_NO_MEMORY;
1764                 }
1765                 
1766                 samdb_msg_add_string(secret_state->sam_ctx, mem_ctx, msg, "cn", name2);
1767         
1768         } else {
1769                 secret_state->global = False;
1770
1771                 name = r->in.name.string;
1772                 if (strlen(name) < 1) {
1773                         return NT_STATUS_INVALID_PARAMETER;
1774                 }
1775
1776                 secret_state->sam_ctx = talloc_reference(secret_state, secrets_db_connect(mem_ctx));
1777                 /* search for the secret record */
1778                 ret = samdb_search(secret_state->sam_ctx,
1779                                    mem_ctx, "cn=LSA Secrets", &msgs, attrs,
1780                                    "(&(cn=%s)(objectclass=secret))", 
1781                                    name);
1782                 if (ret > 0) {
1783                         return NT_STATUS_OBJECT_NAME_COLLISION;
1784                 }
1785                 
1786                 if (ret < 0 || ret > 1) {
1787                         DEBUG(0,("Found %d records matching DN %s\n", ret, policy_state->system_dn));
1788                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1789                 }
1790
1791                 msg->dn = talloc_asprintf(mem_ctx, "cn=%s,cn=LSA Secrets", name);
1792                 samdb_msg_add_string(secret_state->sam_ctx, mem_ctx, msg, "cn", name);
1793         } 
1794
1795         /* pull in all the template attributes.  Note this is always from the global samdb */
1796         ret = samdb_copy_template(secret_state->policy->sam_ctx, mem_ctx, msg, 
1797                                   "(&(name=TemplateSecret)(objectclass=secretTemplate))");
1798         if (ret != 0) {
1799                 DEBUG(0,("Failed to load TemplateSecret from samdb\n"));
1800                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1801         }
1802
1803         samdb_msg_add_string(secret_state->sam_ctx, mem_ctx, msg, "objectClass", "secret");
1804         
1805         secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
1806
1807         /* create the secret */
1808         ret = samdb_add(secret_state->sam_ctx, mem_ctx, msg);
1809         if (ret != 0) {
1810                 DEBUG(0,("Failed to create secret record %s\n", msg->dn));
1811                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1812         }
1813
1814         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
1815         if (!handle) {
1816                 return NT_STATUS_NO_MEMORY;
1817         }
1818         
1819         handle->data = talloc_steal(handle, secret_state);
1820         
1821         secret_state->access_mask = r->in.access_mask;
1822         secret_state->policy = talloc_reference(secret_state, policy_state);
1823         
1824         *r->out.sec_handle = handle->wire_handle;
1825         
1826         return NT_STATUS_OK;
1827 }
1828
1829
1830 /* 
1831   lsa_OpenSecret 
1832 */
1833 static NTSTATUS lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1834                                struct lsa_OpenSecret *r)
1835 {
1836         struct dcesrv_handle *policy_handle;
1837         
1838         struct lsa_policy_state *policy_state;
1839         struct lsa_secret_state *secret_state;
1840         struct dcesrv_handle *handle;
1841         struct ldb_message **msgs;
1842         const char *attrs[] = {
1843                 NULL
1844         };
1845
1846         const char *name;
1847
1848         int ret;
1849
1850         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1851         ZERO_STRUCTP(r->out.sec_handle);
1852         policy_state = policy_handle->data;
1853
1854         if (!r->in.name.string) {
1855                 return NT_STATUS_INVALID_PARAMETER;
1856         }
1857         
1858         secret_state = talloc(mem_ctx, struct lsa_secret_state);
1859         if (!secret_state) {
1860                 return NT_STATUS_NO_MEMORY;
1861         }
1862         secret_state->policy = policy_state;
1863
1864         if (strncmp("G$", r->in.name.string, 2) == 0) {
1865                 name = &r->in.name.string[2];
1866                 secret_state->sam_ctx = talloc_reference(secret_state, policy_state->sam_ctx);
1867                 secret_state->global = True;
1868
1869                 if (strlen(name) < 1) {
1870                         return NT_STATUS_INVALID_PARAMETER;
1871                 }
1872
1873                 /* search for the secret record */
1874                 ret = samdb_search(secret_state->sam_ctx,
1875                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
1876                                    "(&(cn=%s Secret)(objectclass=secret))", 
1877                                    name);
1878                 if (ret == 0) {
1879                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1880                 }
1881                 
1882                 if (ret != 1) {
1883                         DEBUG(0,("Found %d records matching DN %s\n", ret, policy_state->system_dn));
1884                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1885                 }
1886         
1887         } else {
1888                 secret_state->sam_ctx = talloc_reference(secret_state, secrets_db_connect(mem_ctx));
1889
1890                 secret_state->global = False;
1891                 name = r->in.name.string;
1892                 if (strlen(name) < 1) {
1893                         return NT_STATUS_INVALID_PARAMETER;
1894                 }
1895
1896                 /* search for the secret record */
1897                 ret = samdb_search(secret_state->sam_ctx,
1898                                    mem_ctx, "cn=LSA Secrets", &msgs, attrs,
1899                                    "(&(cn=%s)(objectclass=secret))", 
1900                                    name);
1901                 if (ret == 0) {
1902                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1903                 }
1904                 
1905                 if (ret != 1) {
1906                         DEBUG(0,("Found %d records matching DN %s\n", ret, policy_state->system_dn));
1907                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1908                 }
1909         } 
1910
1911         secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
1912         
1913         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
1914         if (!handle) {
1915                 return NT_STATUS_NO_MEMORY;
1916         }
1917         
1918         handle->data = talloc_steal(handle, secret_state);
1919         
1920         secret_state->access_mask = r->in.access_mask;
1921         secret_state->policy = talloc_reference(secret_state, policy_state);
1922         
1923         *r->out.sec_handle = handle->wire_handle;
1924         
1925         return NT_STATUS_OK;
1926 }
1927
1928
1929 /* 
1930   lsa_SetSecret 
1931 */
1932 static NTSTATUS lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1933                               struct lsa_SetSecret *r)
1934 {
1935
1936         struct dcesrv_handle *h;
1937         struct lsa_secret_state *secret_state;
1938         struct ldb_message *msg;
1939         DATA_BLOB session_key;
1940         DATA_BLOB crypt_secret, secret;
1941         struct ldb_val val;
1942         int ret;
1943         NTSTATUS status = NT_STATUS_OK;
1944
1945         struct timeval now = timeval_current();
1946         NTTIME nt_now = timeval_to_nttime(&now);
1947
1948         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
1949
1950         secret_state = h->data;
1951
1952         msg = ldb_msg_new(mem_ctx);
1953         if (msg == NULL) {
1954                 return NT_STATUS_NO_MEMORY;
1955         }
1956
1957         msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
1958         if (!msg->dn) {
1959                 return NT_STATUS_NO_MEMORY;
1960         }
1961         status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
1962         if (!NT_STATUS_IS_OK(status)) {
1963                 return status;
1964         }
1965
1966         if (r->in.old_val) {
1967                 /* Decrypt */
1968                 crypt_secret.data = r->in.old_val->data;
1969                 crypt_secret.length = r->in.old_val->size;
1970                 
1971                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
1972                 if (!NT_STATUS_IS_OK(status)) {
1973                         return status;
1974                 }
1975                 
1976                 val.data = secret.data;
1977                 val.length = secret.length;
1978                 
1979                 /* set value */
1980                 if (samdb_msg_add_value(secret_state->sam_ctx, 
1981                                         mem_ctx, msg, "priorSecret", &val) != 0) {
1982                         return NT_STATUS_NO_MEMORY; 
1983                 }
1984                 
1985                 /* set old value mtime */
1986                 if (samdb_msg_add_uint64(secret_state->sam_ctx, 
1987                                          mem_ctx, msg, "priorSetTime", nt_now) != 0) { 
1988                         return NT_STATUS_NO_MEMORY; 
1989                 }
1990
1991                 if (!r->in.new_val) {
1992                         /* This behaviour varies depending of if this is a local, or a global secret... */
1993                         if (secret_state->global) {
1994                                 /* set old value mtime */
1995                                 if (samdb_msg_add_uint64(secret_state->sam_ctx, 
1996                                                          mem_ctx, msg, "lastSetTime", nt_now) != 0) { 
1997                                         return NT_STATUS_NO_MEMORY; 
1998                                 }
1999                         } else {
2000                                 if (samdb_msg_add_delete(secret_state->sam_ctx, 
2001                                                          mem_ctx, msg, "secret")) {
2002                                         return NT_STATUS_NO_MEMORY;
2003                                 }
2004                                 if (samdb_msg_add_delete(secret_state->sam_ctx, 
2005                                                          mem_ctx, msg, "lastSetTime")) {
2006                                         return NT_STATUS_NO_MEMORY;
2007                                 }
2008                         }
2009                 }
2010         }
2011
2012         if (r->in.new_val) {
2013                 /* Decrypt */
2014                 crypt_secret.data = r->in.new_val->data;
2015                 crypt_secret.length = r->in.new_val->size;
2016                 
2017                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
2018                 if (!NT_STATUS_IS_OK(status)) {
2019                         return status;
2020                 }
2021                 
2022                 val.data = secret.data;
2023                 val.length = secret.length;
2024                 
2025                 /* set value */
2026                 if (samdb_msg_add_value(secret_state->sam_ctx, 
2027                                         mem_ctx, msg, "secret", &val) != 0) {
2028                         return NT_STATUS_NO_MEMORY; 
2029                 }
2030                 
2031                 /* set new value mtime */
2032                 if (samdb_msg_add_uint64(secret_state->sam_ctx, 
2033                                          mem_ctx, msg, "lastSetTime", nt_now) != 0) { 
2034                         return NT_STATUS_NO_MEMORY; 
2035                 }
2036                 
2037                 /* If the old value is not set, then migrate the
2038                  * current value to the old value */
2039                 if (!r->in.old_val) {
2040                         const struct ldb_val *new_val;
2041                         NTTIME last_set_time;
2042                         struct ldb_message **res;
2043                         const char *attrs[] = {
2044                                 "secret",
2045                                 "lastSetTime",
2046                                 NULL
2047                         };
2048                         
2049                         /* search for the secret record */
2050                         ret = samdb_search(secret_state->sam_ctx,
2051                                            mem_ctx, NULL, &res, attrs,
2052                                            "(dn=%s)", secret_state->secret_dn);
2053                         if (ret == 0) {
2054                                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2055                         }
2056                         
2057                         if (ret != 1) {
2058                                 DEBUG(0,("Found %d records matching dn=%s\n", ret, secret_state->secret_dn));
2059                                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2060                         }
2061
2062                         new_val = ldb_msg_find_ldb_val(res[0], "secret");
2063                         last_set_time = ldb_msg_find_uint64(res[0], "lastSetTime", 0);
2064                         
2065                         if (new_val) {
2066                                 /* set value */
2067                                 if (samdb_msg_add_value(secret_state->sam_ctx, 
2068                                                         mem_ctx, msg, "priorSecret", 
2069                                                         new_val) != 0) {
2070                                         return NT_STATUS_NO_MEMORY; 
2071                                 }
2072                         }
2073                         
2074                         /* set new value mtime */
2075                         if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
2076                                 if (samdb_msg_add_uint64(secret_state->sam_ctx, 
2077                                                          mem_ctx, msg, "priorSetTime", last_set_time) != 0) { 
2078                                         return NT_STATUS_NO_MEMORY; 
2079                                 }
2080                         }
2081                 }
2082         }
2083
2084         /* modify the samdb record */
2085         ret = samdb_replace(secret_state->sam_ctx, mem_ctx, msg);
2086         if (ret != 0) {
2087                 /* we really need samdb.c to return NTSTATUS */
2088                 return NT_STATUS_UNSUCCESSFUL;
2089         }
2090
2091         return NT_STATUS_OK;
2092 }
2093
2094
2095 /* 
2096   lsa_QuerySecret 
2097 */
2098 static NTSTATUS lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2099                                 struct lsa_QuerySecret *r)
2100 {
2101         struct dcesrv_handle *h;
2102         struct lsa_secret_state *secret_state;
2103         struct ldb_message *msg;
2104         DATA_BLOB session_key;
2105         DATA_BLOB crypt_secret, secret;
2106         int ret;
2107         struct ldb_message **res;
2108         const char *attrs[] = {
2109                 "secret",
2110                 "priorSecret",
2111                 "lastSetTime",
2112                 "priorSetTime", 
2113                 NULL
2114         };
2115
2116         NTSTATUS nt_status;
2117
2118         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
2119
2120         secret_state = h->data;
2121
2122         /* pull all the user attributes */
2123         ret = samdb_search(secret_state->sam_ctx, mem_ctx, NULL, &res, attrs,
2124                            "dn=%s", secret_state->secret_dn);
2125         if (ret != 1) {
2126                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2127         }
2128         msg = res[0];
2129         
2130         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
2131         if (!NT_STATUS_IS_OK(nt_status)) {
2132                 return nt_status;
2133         }
2134         
2135         if (r->in.old_val) {
2136                 const struct ldb_val *prior_val;
2137                 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
2138                 if (!r->out.old_val) {
2139                         return NT_STATUS_NO_MEMORY;
2140                 }
2141                 /* Decrypt */
2142                 prior_val = ldb_msg_find_ldb_val(res[0], "priorSecret");
2143                 
2144                 if (prior_val && prior_val->length) {
2145                         secret.data = prior_val->data;
2146                         secret.length = prior_val->length;
2147                 
2148                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
2149                         if (!crypt_secret.length) {
2150                                 return NT_STATUS_NO_MEMORY;
2151                         }
2152                         r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
2153                         if (!r->out.old_val->buf) {
2154                                 return NT_STATUS_NO_MEMORY;
2155                         }
2156                         r->out.old_val->buf->size = crypt_secret.length;
2157                         r->out.old_val->buf->length = crypt_secret.length;
2158                         r->out.old_val->buf->data = crypt_secret.data;
2159                 }
2160         }
2161         
2162         if (r->in.old_mtime) {
2163                 r->out.old_mtime = talloc(mem_ctx, NTTIME);
2164                 if (!r->out.old_mtime) {
2165                         return NT_STATUS_NO_MEMORY;
2166                 }
2167                 *r->out.old_mtime = ldb_msg_find_uint64(res[0], "priorSetTime", 0);
2168         }
2169         
2170         if (r->in.new_val) {
2171                 const struct ldb_val *new_val;
2172                 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
2173                 if (!r->out.new_val) {
2174                         return NT_STATUS_NO_MEMORY;
2175                 }
2176
2177                 /* Decrypt */
2178                 new_val = ldb_msg_find_ldb_val(res[0], "secret");
2179                 
2180                 if (new_val && new_val->length) {
2181                         secret.data = new_val->data;
2182                         secret.length = new_val->length;
2183                 
2184                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
2185                         if (!crypt_secret.length) {
2186                                 return NT_STATUS_NO_MEMORY;
2187                         }
2188                         r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
2189                         if (!r->out.new_val->buf) {
2190                                 return NT_STATUS_NO_MEMORY;
2191                         }
2192                         r->out.new_val->buf->length = crypt_secret.length;
2193                         r->out.new_val->buf->size = crypt_secret.length;
2194                         r->out.new_val->buf->data = crypt_secret.data;
2195                 }
2196         }
2197         
2198         if (r->in.new_mtime) {
2199                 r->out.new_mtime = talloc(mem_ctx, NTTIME);
2200                 if (!r->out.new_mtime) {
2201                         return NT_STATUS_NO_MEMORY;
2202                 }
2203                 *r->out.new_mtime = ldb_msg_find_uint64(res[0], "lastSetTime", 0);
2204         }
2205         
2206         return NT_STATUS_OK;
2207 }
2208
2209
2210 /* 
2211   lsa_LookupPrivValue
2212 */
2213 static NTSTATUS lsa_LookupPrivValue(struct dcesrv_call_state *dce_call, 
2214                                     TALLOC_CTX *mem_ctx,
2215                                     struct lsa_LookupPrivValue *r)
2216 {
2217         struct dcesrv_handle *h;
2218         struct lsa_policy_state *state;
2219         int id;
2220
2221         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2222
2223         state = h->data;
2224
2225         id = sec_privilege_id(r->in.name->string);
2226         if (id == -1) {
2227                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2228         }
2229
2230         r->out.luid->low = id;
2231         r->out.luid->high = 0;
2232
2233         return NT_STATUS_OK;    
2234 }
2235
2236
2237 /* 
2238   lsa_LookupPrivName 
2239 */
2240 static NTSTATUS lsa_LookupPrivName(struct dcesrv_call_state *dce_call, 
2241                                    TALLOC_CTX *mem_ctx,
2242                                    struct lsa_LookupPrivName *r)
2243 {
2244         struct dcesrv_handle *h;
2245         struct lsa_policy_state *state;
2246         const char *privname;
2247
2248         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2249
2250         state = h->data;
2251
2252         if (r->in.luid->high != 0) {
2253                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2254         }
2255
2256         privname = sec_privilege_name(r->in.luid->low);
2257         if (privname == NULL) {
2258                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2259         }
2260
2261         r->out.name = talloc(mem_ctx, struct lsa_String);
2262         if (r->out.name == NULL) {
2263                 return NT_STATUS_NO_MEMORY;
2264         }
2265         r->out.name->string = privname;
2266
2267         return NT_STATUS_OK;    
2268 }
2269
2270
2271 /* 
2272   lsa_LookupPrivDisplayName
2273 */
2274 static NTSTATUS lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call, 
2275                                           TALLOC_CTX *mem_ctx,
2276                                           struct lsa_LookupPrivDisplayName *r)
2277 {
2278         struct dcesrv_handle *h;
2279         struct lsa_policy_state *state;
2280         int id;
2281
2282         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2283
2284         state = h->data;
2285
2286         id = sec_privilege_id(r->in.name->string);
2287         if (id == -1) {
2288                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2289         }
2290         
2291         r->out.disp_name = talloc(mem_ctx, struct lsa_String);
2292         if (r->out.disp_name == NULL) {
2293                 return NT_STATUS_NO_MEMORY;
2294         }
2295
2296         r->out.disp_name->string = sec_privilege_display_name(id, r->in.language_id);
2297         if (r->out.disp_name->string == NULL) {
2298                 return NT_STATUS_INTERNAL_ERROR;
2299         }
2300
2301         return NT_STATUS_OK;
2302 }
2303
2304
2305 /* 
2306   lsa_DeleteObject
2307 */
2308 static NTSTATUS lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2309                        struct lsa_DeleteObject *r)
2310 {
2311         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2312 }
2313
2314
2315 /* 
2316   lsa_EnumAccountsWithUserRight
2317 */
2318 static NTSTATUS lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call, 
2319                                               TALLOC_CTX *mem_ctx,
2320                                               struct lsa_EnumAccountsWithUserRight *r)
2321 {
2322         struct dcesrv_handle *h;
2323         struct lsa_policy_state *state;
2324         int ret, i;
2325         struct ldb_message **res;
2326         const char * const attrs[] = { "objectSid", NULL};
2327         const char *privname;
2328
2329         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2330
2331         state = h->data;
2332
2333         if (r->in.name == NULL) {
2334                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2335         } 
2336
2337         privname = r->in.name->string;
2338         if (sec_privilege_id(privname) == -1) {
2339                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2340         }
2341
2342         ret = samdb_search(state->sam_ctx, mem_ctx, NULL, &res, attrs, 
2343                            "privilege=%s", privname);
2344         if (ret <= 0) {
2345                 return NT_STATUS_NO_SUCH_USER;
2346         }
2347
2348         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
2349         if (r->out.sids->sids == NULL) {
2350                 return NT_STATUS_NO_MEMORY;
2351         }
2352         for (i=0;i<ret;i++) {
2353                 const char *sidstr;
2354                 sidstr = samdb_result_string(res[i], "objectSid", NULL);
2355                 if (sidstr == NULL) {
2356                         return NT_STATUS_NO_MEMORY;
2357                 }
2358                 r->out.sids->sids[i].sid = dom_sid_parse_talloc(r->out.sids->sids,
2359                                                                 sidstr);
2360                 if (r->out.sids->sids[i].sid == NULL) {
2361                         return NT_STATUS_NO_MEMORY;
2362                 }
2363         }
2364         r->out.sids->num_sids = ret;
2365
2366         return NT_STATUS_OK;
2367 }
2368
2369
2370 /* 
2371   lsa_AddAccountRights
2372 */
2373 static NTSTATUS lsa_AddAccountRights(struct dcesrv_call_state *dce_call, 
2374                                      TALLOC_CTX *mem_ctx,
2375                                      struct lsa_AddAccountRights *r)
2376 {
2377         struct dcesrv_handle *h;
2378         struct lsa_policy_state *state;
2379
2380         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2381
2382         state = h->data;
2383
2384         return lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
2385                                           LDB_FLAG_MOD_ADD,
2386                                           r->in.sid, r->in.rights);
2387 }
2388
2389
2390 /* 
2391   lsa_RemoveAccountRights
2392 */
2393 static NTSTATUS lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call, 
2394                                         TALLOC_CTX *mem_ctx,
2395                                         struct lsa_RemoveAccountRights *r)
2396 {
2397         struct dcesrv_handle *h;
2398         struct lsa_policy_state *state;
2399
2400         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2401
2402         state = h->data;
2403
2404         return lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
2405                                           LDB_FLAG_MOD_DELETE,
2406                                           r->in.sid, r->in.rights);
2407 }
2408
2409
2410 /* 
2411   lsa_StorePrivateData
2412 */
2413 static NTSTATUS lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2414                        struct lsa_StorePrivateData *r)
2415 {
2416         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2417 }
2418
2419
2420 /* 
2421   lsa_RetrievePrivateData
2422 */
2423 static NTSTATUS lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2424                        struct lsa_RetrievePrivateData *r)
2425 {
2426         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2427 }
2428
2429
2430 /* 
2431   lsa_GetUserName
2432 */
2433 static NTSTATUS lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2434                        struct lsa_GetUserName *r)
2435 {
2436         NTSTATUS status = NT_STATUS_OK;
2437         const char *account_name;
2438         const char *authority_name;
2439         struct lsa_String *_account_name;
2440         struct lsa_StringPointer *_authority_name = NULL;
2441
2442         /* this is what w2k3 does */
2443         r->out.account_name = r->in.account_name;
2444         r->out.authority_name = r->in.authority_name;
2445
2446         if (r->in.account_name && r->in.account_name->string) {
2447                 return NT_STATUS_INVALID_PARAMETER;
2448         }
2449
2450         if (r->in.authority_name &&
2451             r->in.authority_name->string &&
2452             r->in.authority_name->string->string) {
2453                 return NT_STATUS_INVALID_PARAMETER;
2454         }
2455
2456         /* TODO: this check should go and we should rely on the calling code that this is valid */
2457         if (!dce_call->conn->auth_state.session_info ||
2458             !dce_call->conn->auth_state.session_info->server_info ||
2459             !dce_call->conn->auth_state.session_info->server_info->account_name ||
2460             !dce_call->conn->auth_state.session_info->server_info->domain_name) {
2461                 return NT_STATUS_INTERNAL_ERROR;
2462         }
2463
2464         account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->account_name);
2465         authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->domain_name);
2466
2467         _account_name = talloc(mem_ctx, struct lsa_String);
2468         NTSTATUS_TALLOC_CHECK(_account_name);
2469         _account_name->string = account_name;
2470
2471         if (r->in.authority_name) {
2472                 _authority_name = talloc(mem_ctx, struct lsa_StringPointer);
2473                 NTSTATUS_TALLOC_CHECK(_authority_name);
2474                 _authority_name->string = talloc(mem_ctx, struct lsa_String);
2475                 NTSTATUS_TALLOC_CHECK(_authority_name->string);
2476                 _authority_name->string->string = authority_name;
2477         }
2478
2479         r->out.account_name = _account_name;
2480         r->out.authority_name = _authority_name;
2481
2482         return status;
2483 }
2484
2485 /*
2486   lsa_SetInfoPolicy2
2487 */
2488 static NTSTATUS lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
2489                                    TALLOC_CTX *mem_ctx,
2490                                    struct lsa_SetInfoPolicy2 *r)
2491 {
2492         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2493 }
2494
2495 /*
2496   lsa_QueryDomainInformationPolicy
2497 */
2498 static NTSTATUS lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
2499                                                  TALLOC_CTX *mem_ctx,
2500                                                  struct lsa_QueryDomainInformationPolicy *r)
2501 {
2502         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2503 }
2504
2505 /*
2506   lsa_SetDomInfoPolicy
2507 */
2508 static NTSTATUS lsa_SetDomInfoPolicy(struct dcesrv_call_state *dce_call,
2509                                      TALLOC_CTX *mem_ctx,
2510                                      struct lsa_SetDomInfoPolicy *r)
2511 {
2512         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2513 }
2514
2515 /*
2516   lsa_TestCall
2517 */
2518 static NTSTATUS lsa_TestCall(struct dcesrv_call_state *dce_call,
2519                              TALLOC_CTX *mem_ctx,
2520                              struct lsa_TestCall *r)
2521 {
2522         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2523 }
2524
2525 /*
2526   lookup a SID for 1 name
2527 */
2528 static NTSTATUS lsa_lookup_name(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
2529                                 const char *name, struct dom_sid **sid, uint32_t *atype)
2530 {
2531         int ret;
2532         struct ldb_message **res;
2533         const char * const attrs[] = { "objectSid", "sAMAccountType", NULL};
2534         const char *p;
2535
2536         p = strchr_m(name, '\\');
2537         if (p != NULL) {
2538                 /* TODO: properly parse the domain prefix here, and use it to 
2539                    limit the search */
2540                 name = p + 1;
2541         }
2542
2543         ret = samdb_search(state->sam_ctx, mem_ctx, NULL, &res, attrs, "sAMAccountName=%s", name);
2544         if (ret == 1) {
2545                 const char *sid_str = ldb_msg_find_string(res[0], "objectSid", NULL);
2546                 if (sid_str == NULL) {
2547                         return NT_STATUS_INVALID_SID;
2548                 }
2549
2550                 *sid = dom_sid_parse_talloc(mem_ctx, sid_str);
2551                 if (*sid == NULL) {
2552                         return NT_STATUS_INVALID_SID;
2553                 }
2554
2555                 *atype = samdb_result_uint(res[0], "sAMAccountType", 0);
2556
2557                 return NT_STATUS_OK;
2558         }
2559
2560         /* need to add a call into sidmap to check for a allocated sid */
2561
2562         return NT_STATUS_INVALID_SID;
2563 }
2564
2565
2566 /*
2567   lsa_LookupNames3
2568 */
2569 static NTSTATUS lsa_LookupNames3(struct dcesrv_call_state *dce_call,
2570                                  TALLOC_CTX *mem_ctx,
2571                                  struct lsa_LookupNames3 *r)
2572 {
2573         struct lsa_policy_state *state;
2574         struct dcesrv_handle *h;
2575         int i;
2576         NTSTATUS status = NT_STATUS_OK;
2577
2578         r->out.domains = NULL;
2579
2580         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2581
2582         state = h->data;
2583
2584         r->out.domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
2585         if (r->out.domains == NULL) {
2586                 return NT_STATUS_NO_MEMORY;
2587         }
2588
2589         r->out.sids = talloc_zero(mem_ctx,  struct lsa_TransSidArray3);
2590         if (r->out.sids == NULL) {
2591                 return NT_STATUS_NO_MEMORY;
2592         }
2593
2594         *r->out.count = 0;
2595
2596         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid3, 
2597                                            r->in.num_names);
2598         if (r->out.sids->sids == NULL) {
2599                 return NT_STATUS_NO_MEMORY;
2600         }
2601
2602         for (i=0;i<r->in.num_names;i++) {
2603                 const char *name = r->in.names[i].string;
2604                 struct dom_sid *sid;
2605                 uint32_t atype, rtype, sid_index;
2606                 NTSTATUS status2;
2607
2608                 r->out.sids->count++;
2609                 (*r->out.count)++;
2610
2611                 r->out.sids->sids[i].sid_type    = SID_NAME_UNKNOWN;
2612                 r->out.sids->sids[i].sid         = NULL;
2613                 r->out.sids->sids[i].sid_index   = 0xFFFFFFFF;
2614                 r->out.sids->sids[i].unknown     = 0;
2615
2616                 status2 = lsa_lookup_name(state, mem_ctx, name, &sid, &atype);
2617                 if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) {
2618                         status = STATUS_SOME_UNMAPPED;
2619                         continue;
2620                 }
2621
2622                 rtype = samdb_atype_map(atype);
2623                 if (rtype == SID_NAME_UNKNOWN) {
2624                         status = STATUS_SOME_UNMAPPED;
2625                         continue;
2626                 }
2627
2628                 status2 = lsa_authority_list(state, mem_ctx, sid, r->out.domains, &sid_index);
2629                 if (!NT_STATUS_IS_OK(status2)) {
2630                         return status2;
2631                 }
2632
2633                 r->out.sids->sids[i].sid_type    = rtype;
2634                 r->out.sids->sids[i].sid         = sid;
2635                 r->out.sids->sids[i].sid_index   = sid_index;
2636                 r->out.sids->sids[i].unknown     = 0;
2637         }
2638         
2639         return status;
2640 }
2641
2642 /*
2643   lsa_LookupNames2
2644 */
2645 static NTSTATUS lsa_LookupNames2(struct dcesrv_call_state *dce_call,
2646                                  TALLOC_CTX *mem_ctx,
2647                                  struct lsa_LookupNames2 *r)
2648 {
2649         struct lsa_policy_state *state;
2650         struct dcesrv_handle *h;
2651         int i;
2652         NTSTATUS status = NT_STATUS_OK;
2653
2654         r->out.domains = NULL;
2655
2656         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2657
2658         state = h->data;
2659
2660         r->out.domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
2661         if (r->out.domains == NULL) {
2662                 return NT_STATUS_NO_MEMORY;
2663         }
2664
2665         r->out.sids = talloc_zero(mem_ctx,  struct lsa_TransSidArray2);
2666         if (r->out.sids == NULL) {
2667                 return NT_STATUS_NO_MEMORY;
2668         }
2669
2670         *r->out.count = 0;
2671
2672         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid2, 
2673                                            r->in.num_names);
2674         if (r->out.sids->sids == NULL) {
2675                 return NT_STATUS_NO_MEMORY;
2676         }
2677
2678         for (i=0;i<r->in.num_names;i++) {
2679                 const char *name = r->in.names[i].string;
2680                 struct dom_sid *sid;
2681                 uint32_t atype, rtype, sid_index;
2682                 NTSTATUS status2;
2683
2684                 r->out.sids->count++;
2685                 (*r->out.count)++;
2686
2687                 r->out.sids->sids[i].sid_type    = SID_NAME_UNKNOWN;
2688                 r->out.sids->sids[i].rid         = 0xFFFFFFFF;
2689                 r->out.sids->sids[i].sid_index   = 0xFFFFFFFF;
2690                 r->out.sids->sids[i].unknown     = 0;
2691
2692                 status2 = lsa_lookup_name(state, mem_ctx, name, &sid, &atype);
2693                 if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) {
2694                         status = STATUS_SOME_UNMAPPED;
2695                         continue;
2696                 }
2697
2698                 rtype = samdb_atype_map(atype);
2699                 if (rtype == SID_NAME_UNKNOWN) {
2700                         status = STATUS_SOME_UNMAPPED;
2701                         continue;
2702                 }
2703
2704                 status2 = lsa_authority_list(state, mem_ctx, sid, r->out.domains, &sid_index);
2705                 if (!NT_STATUS_IS_OK(status2)) {
2706                         return status2;
2707                 }
2708
2709                 r->out.sids->sids[i].sid_type    = rtype;
2710                 r->out.sids->sids[i].rid         = sid->sub_auths[sid->num_auths-1];
2711                 r->out.sids->sids[i].sid_index   = sid_index;
2712                 r->out.sids->sids[i].unknown     = 0;
2713         }
2714         
2715         return status;
2716 }
2717
2718 /* 
2719   lsa_LookupNames 
2720 */
2721 static NTSTATUS lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2722                        struct lsa_LookupNames *r)
2723 {
2724         struct lsa_LookupNames2 r2;
2725         NTSTATUS status;
2726         int i;
2727
2728         r2.in.handle    = r->in.handle;
2729         r2.in.num_names = r->in.num_names;
2730         r2.in.names     = r->in.names;
2731         r2.in.sids      = NULL;
2732         r2.in.level     = r->in.level;
2733         r2.in.count     = r->in.count;
2734         r2.in.unknown1  = 0;
2735         r2.in.unknown2  = 0;
2736         r2.out.count    = r->out.count;
2737
2738         status = lsa_LookupNames2(dce_call, mem_ctx, &r2);
2739         if (dce_call->fault_code != 0) {
2740                 return status;
2741         }
2742
2743         r->out.domains = r2.out.domains;
2744         r->out.sids = talloc(mem_ctx, struct lsa_TransSidArray);
2745         if (r->out.sids == NULL) {
2746                 return NT_STATUS_NO_MEMORY;
2747         }
2748         r->out.sids->count = r2.out.sids->count;
2749         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid, 
2750                                            r->out.sids->count);
2751         if (r->out.sids->sids == NULL) {
2752                 return NT_STATUS_NO_MEMORY;
2753         }
2754         for (i=0;i<r->out.sids->count;i++) {
2755                 r->out.sids->sids[i].sid_type    = r2.out.sids->sids[i].sid_type;
2756                 r->out.sids->sids[i].rid         = r2.out.sids->sids[i].rid;
2757                 r->out.sids->sids[i].sid_index   = r2.out.sids->sids[i].sid_index;
2758         }
2759
2760         return status;
2761 }
2762
2763 /* 
2764   lsa_CREDRWRITE 
2765 */
2766 static NTSTATUS lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2767                        struct lsa_CREDRWRITE *r)
2768 {
2769         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2770 }
2771
2772
2773 /* 
2774   lsa_CREDRREAD 
2775 */
2776 static NTSTATUS lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2777                        struct lsa_CREDRREAD *r)
2778 {
2779         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2780 }
2781
2782
2783 /* 
2784   lsa_CREDRENUMERATE 
2785 */
2786 static NTSTATUS lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2787                        struct lsa_CREDRENUMERATE *r)
2788 {
2789         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2790 }
2791
2792
2793 /* 
2794   lsa_CREDRWRITEDOMAINCREDENTIALS 
2795 */
2796 static NTSTATUS lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2797                        struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
2798 {
2799         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2800 }
2801
2802
2803 /* 
2804   lsa_CREDRREADDOMAINCREDENTIALS 
2805 */
2806 static NTSTATUS lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2807                        struct lsa_CREDRREADDOMAINCREDENTIALS *r)
2808 {
2809         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2810 }
2811
2812
2813 /* 
2814   lsa_CREDRDELETE 
2815 */
2816 static NTSTATUS lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2817                        struct lsa_CREDRDELETE *r)
2818 {
2819         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2820 }
2821
2822
2823 /* 
2824   lsa_CREDRGETTARGETINFO 
2825 */
2826 static NTSTATUS lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2827                        struct lsa_CREDRGETTARGETINFO *r)
2828 {
2829         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2830 }
2831
2832
2833 /* 
2834   lsa_CREDRPROFILELOADED 
2835 */
2836 static NTSTATUS lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2837                        struct lsa_CREDRPROFILELOADED *r)
2838 {
2839         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2840 }
2841
2842
2843 /* 
2844   lsa_CREDRGETSESSIONTYPES 
2845 */
2846 static NTSTATUS lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2847                        struct lsa_CREDRGETSESSIONTYPES *r)
2848 {
2849         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2850 }
2851
2852
2853 /* 
2854   lsa_LSARREGISTERAUDITEVENT 
2855 */
2856 static NTSTATUS lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2857                        struct lsa_LSARREGISTERAUDITEVENT *r)
2858 {
2859         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2860 }
2861
2862
2863 /* 
2864   lsa_LSARGENAUDITEVENT 
2865 */
2866 static NTSTATUS lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2867                        struct lsa_LSARGENAUDITEVENT *r)
2868 {
2869         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2870 }
2871
2872
2873 /* 
2874   lsa_LSARUNREGISTERAUDITEVENT 
2875 */
2876 static NTSTATUS lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2877                        struct lsa_LSARUNREGISTERAUDITEVENT *r)
2878 {
2879         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2880 }
2881
2882
2883 /* 
2884   lsa_LSARQUERYFORESTTRUSTINFORMATION 
2885 */
2886 static NTSTATUS lsa_LSARQUERYFORESTTRUSTINFORMATION(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2887                        struct lsa_LSARQUERYFORESTTRUSTINFORMATION *r)
2888 {
2889         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2890 }
2891
2892
2893 /* 
2894   lsa_LSARSETFORESTTRUSTINFORMATION 
2895 */
2896 static NTSTATUS lsa_LSARSETFORESTTRUSTINFORMATION(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2897                        struct lsa_LSARSETFORESTTRUSTINFORMATION *r)
2898 {
2899         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2900 }
2901
2902
2903 /* 
2904   lsa_CREDRRENAME 
2905 */
2906 static NTSTATUS lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2907                        struct lsa_CREDRRENAME *r)
2908 {
2909         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2910 }
2911
2912
2913 /* 
2914   lsa_LSARLOOKUPNAMES4 
2915 */
2916 static NTSTATUS lsa_LSARLOOKUPNAMES4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2917                        struct lsa_LSARLOOKUPNAMES4 *r)
2918 {
2919         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2920 }
2921
2922
2923 /* 
2924   lsa_LSAROPENPOLICYSCE 
2925 */
2926 static NTSTATUS lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2927                        struct lsa_LSAROPENPOLICYSCE *r)
2928 {
2929         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2930 }
2931
2932
2933 /* 
2934   lsa_LSARADTREGISTERSECURITYEVENTSOURCE 
2935 */
2936 static NTSTATUS lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2937                        struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
2938 {
2939         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2940 }
2941
2942
2943 /* 
2944   lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE 
2945 */
2946 static NTSTATUS lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2947                        struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
2948 {
2949         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2950 }
2951
2952
2953 /* 
2954   lsa_LSARADTREPORTSECURITYEVENT 
2955 */
2956 static NTSTATUS lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2957                        struct lsa_LSARADTREPORTSECURITYEVENT *r)
2958 {
2959         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2960 }
2961
2962
2963 /* include the generated boilerplate */
2964 #include "librpc/gen_ndr/ndr_lsa_s.c"