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