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