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