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