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