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