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