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