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