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