r21518: fix panic, sorry...
[samba.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    endpoint server for the lsarpc pipe
5
6    Copyright (C) Andrew Tridgell 2004
7    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
8    
9    This program is free software; you can redistribute it and/or modify
10    it under the terms of the GNU General Public License as published by
11    the Free Software Foundation; either version 2 of the License, or
12    (at your option) any later version.
13    
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License for more details.
18    
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "includes.h"
25 #include "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 "lib/ldb/include/ldb_errors.h"
31 #include "libcli/security/security.h"
32 #include "libcli/auth/libcli_auth.h"
33 #include "param/secrets.h"
34 #include "db_wrap.h"
35 #include "librpc/gen_ndr/ndr_dssetup.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         struct ldb_dn *domain_dn;
56         struct ldb_dn *forest_dn;
57         struct ldb_dn *builtin_dn;
58         struct ldb_dn *system_dn;
59         const char *domain_name;
60         const char *domain_dns;
61         const char *forest_dns;
62         struct dom_sid *domain_sid;
63         struct GUID domain_guid;
64         struct dom_sid *builtin_sid;
65         int mixed_domain;
66 };
67
68
69 /*
70   state associated with a lsa_OpenAccount() operation
71 */
72 struct lsa_account_state {
73         struct lsa_policy_state *policy;
74         uint32_t access_mask;
75         struct dom_sid *account_sid;
76 };
77
78
79 /*
80   state associated with a lsa_OpenSecret() operation
81 */
82 struct lsa_secret_state {
83         struct lsa_policy_state *policy;
84         uint32_t access_mask;
85         struct ldb_dn *secret_dn;
86         struct ldb_context *sam_ldb;
87         BOOL global;
88 };
89
90 /*
91   state associated with a lsa_OpenTrustedDomain() operation
92 */
93 struct lsa_trusted_domain_state {
94         struct lsa_policy_state *policy;
95         uint32_t access_mask;
96         struct ldb_dn *trusted_domain_dn;
97 };
98
99 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call, 
100                                       TALLOC_CTX *mem_ctx,
101                                       struct lsa_EnumAccountRights *r);
102
103 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call, 
104                                            TALLOC_CTX *mem_ctx,
105                                            struct lsa_policy_state *state,
106                                            int ldb_flag,
107                                            struct dom_sid *sid,
108                                            const struct lsa_RightSet *rights);
109
110 /* 
111   lsa_Close 
112 */
113 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
114                           struct lsa_Close *r)
115 {
116         struct dcesrv_handle *h;
117
118         *r->out.handle = *r->in.handle;
119
120         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
121
122         talloc_free(h);
123
124         ZERO_STRUCTP(r->out.handle);
125
126         return NT_STATUS_OK;
127 }
128
129
130 /* 
131   lsa_Delete 
132 */
133 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
134                            struct lsa_Delete *r)
135 {
136         struct dcesrv_handle *h;
137         int ret;
138
139         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
140         if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
141                 struct lsa_secret_state *secret_state = h->data;
142                 ret = samdb_delete(secret_state->sam_ldb, mem_ctx, secret_state->secret_dn);
143                 talloc_free(h);
144                 if (ret != 0) {
145                         return NT_STATUS_INVALID_HANDLE;
146                 }
147
148                 return NT_STATUS_OK;
149         } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
150                 struct lsa_trusted_domain_state *trusted_domain_state = h->data;
151                 ret = samdb_delete(trusted_domain_state->policy->sam_ldb, mem_ctx, 
152                                    trusted_domain_state->trusted_domain_dn);
153                 talloc_free(h);
154                 if (ret != 0) {
155                         return NT_STATUS_INVALID_HANDLE;
156                 }
157
158                 return NT_STATUS_OK;
159         } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
160                 struct lsa_RightSet *rights;
161                 struct lsa_account_state *astate;
162                 struct lsa_EnumAccountRights r2;
163                 NTSTATUS status;
164
165                 rights = talloc(mem_ctx, struct lsa_RightSet);
166
167                 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
168                 
169                 astate = h->data;
170
171                 r2.in.handle = &astate->policy->handle->wire_handle;
172                 r2.in.sid = astate->account_sid;
173                 r2.out.rights = rights;
174
175                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
176                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
177                         return NT_STATUS_OK;
178                 }
179
180                 if (!NT_STATUS_IS_OK(status)) {
181                         return status;
182                 }
183
184                 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
185                                                     LDB_FLAG_MOD_DELETE, astate->account_sid,
186                                                     r2.out.rights);
187                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
188                         return NT_STATUS_OK;
189                 }
190
191                 if (!NT_STATUS_IS_OK(status)) {
192                         return status;
193                 }
194         } 
195         
196         return NT_STATUS_INVALID_HANDLE;
197 }
198
199
200 /* 
201   lsa_EnumPrivs 
202 */
203 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
204                               struct lsa_EnumPrivs *r)
205 {
206         struct dcesrv_handle *h;
207         struct lsa_policy_state *state;
208         int i;
209         const char *privname;
210
211         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
212
213         state = h->data;
214
215         i = *r->in.resume_handle;
216         if (i == 0) i = 1;
217
218         while ((privname = sec_privilege_name(i)) &&
219                r->out.privs->count < r->in.max_count) {
220                 struct lsa_PrivEntry *e;
221
222                 r->out.privs->privs = talloc_realloc(r->out.privs,
223                                                        r->out.privs->privs, 
224                                                        struct lsa_PrivEntry, 
225                                                        r->out.privs->count+1);
226                 if (r->out.privs->privs == NULL) {
227                         return NT_STATUS_NO_MEMORY;
228                 }
229                 e = &r->out.privs->privs[r->out.privs->count];
230                 e->luid.low = i;
231                 e->luid.high = 0;
232                 e->name.string = privname;
233                 r->out.privs->count++;
234                 i++;
235         }
236
237         *r->out.resume_handle = i;
238
239         return NT_STATUS_OK;
240 }
241
242
243 /* 
244   lsa_QuerySecObj 
245 */
246 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
247                                   struct lsa_QuerySecurity *r)
248 {
249         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
250 }
251
252
253 /* 
254   lsa_SetSecObj 
255 */
256 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
257                               struct lsa_SetSecObj *r)
258 {
259         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
260 }
261
262
263 /* 
264   lsa_ChangePassword 
265 */
266 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
267                                    struct lsa_ChangePassword *r)
268 {
269         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
270 }
271
272 static NTSTATUS dcesrv_lsa_get_policy_state(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
273                                      struct lsa_policy_state **_state)
274 {
275         struct lsa_policy_state *state;
276         struct ldb_dn *partitions_basedn;
277         struct ldb_result *dom_res;
278         const char *dom_attrs[] = {
279                 "objectSid", 
280                 "objectGUID", 
281                 "nTMixedDomain",
282                 "fSMORoleOwner",
283                 NULL
284         };
285         struct ldb_result *ref_res;
286         struct ldb_result *forest_ref_res;
287         const char *ref_attrs[] = {
288                 "nETBIOSName",
289                 "dnsRoot",
290                 NULL
291         };
292         int ret;
293
294         state = talloc(mem_ctx, struct lsa_policy_state);
295         if (!state) {
296                 return NT_STATUS_NO_MEMORY;
297         }
298
299         /* make sure the sam database is accessible */
300         state->sam_ldb = samdb_connect(state, dce_call->conn->auth_state.session_info); 
301         if (state->sam_ldb == NULL) {
302                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
303         }
304
305         partitions_basedn = samdb_partitions_dn(state->sam_ldb, mem_ctx);
306
307         state->sidmap = sidmap_open(state);
308         if (state->sidmap == NULL) {
309                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
310         }
311
312         /* work out the domain_dn - useful for so many calls its worth
313            fetching here */
314         state->domain_dn = samdb_base_dn(state->sam_ldb);
315         if (!state->domain_dn) {
316                 return NT_STATUS_NO_MEMORY;             
317         }
318
319         /* work out the forest root_dn - useful for so many calls its worth
320            fetching here */
321         state->forest_dn = samdb_root_dn(state->sam_ldb);
322         if (!state->forest_dn) {
323                 return NT_STATUS_NO_MEMORY;             
324         }
325
326         ret = ldb_search(state->sam_ldb, state->domain_dn, LDB_SCOPE_BASE, NULL, dom_attrs, &dom_res);
327         
328         if (ret != LDB_SUCCESS) {
329                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
330         }
331         talloc_steal(mem_ctx, dom_res);
332         if (dom_res->count != 1) {
333                 return NT_STATUS_NO_SUCH_DOMAIN;                
334         }
335
336         state->domain_sid = samdb_result_dom_sid(state, dom_res->msgs[0], "objectSid");
337         if (!state->domain_sid) {
338                 return NT_STATUS_NO_SUCH_DOMAIN;                
339         }
340
341         state->domain_guid = samdb_result_guid(dom_res->msgs[0], "objectGUID");
342         if (!state->domain_sid) {
343                 return NT_STATUS_NO_SUCH_DOMAIN;                
344         }
345
346         state->mixed_domain = ldb_msg_find_attr_as_uint(dom_res->msgs[0], "nTMixedDomain", 0);
347         
348         talloc_free(dom_res);
349
350         ret = ldb_search_exp_fmt(state->sam_ldb, state, &ref_res,
351                                  partitions_basedn, LDB_SCOPE_SUBTREE, ref_attrs,
352                                  "(&(objectclass=crossRef)(ncName=%s))",
353                                  ldb_dn_get_linearized(state->domain_dn));
354         
355         if (ret != LDB_SUCCESS) {
356                 talloc_free(ref_res);
357                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
358         }
359         if (ref_res->count != 1) {
360                 talloc_free(ref_res);
361                 return NT_STATUS_NO_SUCH_DOMAIN;                
362         }
363
364         state->domain_name = ldb_msg_find_attr_as_string(ref_res->msgs[0], "nETBIOSName", NULL);
365         if (!state->domain_name) {
366                 talloc_free(ref_res);
367                 return NT_STATUS_NO_SUCH_DOMAIN;                
368         }
369         talloc_steal(state, state->domain_name);
370
371         state->domain_dns = ldb_msg_find_attr_as_string(ref_res->msgs[0], "dnsRoot", NULL);
372         if (!state->domain_dns) {
373                 talloc_free(ref_res);
374                 return NT_STATUS_NO_SUCH_DOMAIN;                
375         }
376         talloc_steal(state, state->domain_dns);
377
378         talloc_free(ref_res);
379
380         ret = ldb_search_exp_fmt(state->sam_ldb, state, &forest_ref_res,
381                                  partitions_basedn, LDB_SCOPE_SUBTREE, ref_attrs,
382                                  "(&(objectclass=crossRef)(ncName=%s))",
383                                  ldb_dn_get_linearized(state->forest_dn));
384         
385         if (ret != LDB_SUCCESS) {
386                 talloc_free(forest_ref_res);
387                 return NT_STATUS_INVALID_SYSTEM_SERVICE;
388         }
389         if (forest_ref_res->count != 1) {
390                 talloc_free(forest_ref_res);
391                 return NT_STATUS_NO_SUCH_DOMAIN;                
392         }
393
394         state->forest_dns = ldb_msg_find_attr_as_string(forest_ref_res->msgs[0], "dnsRoot", NULL);
395         if (!state->forest_dns) {
396                 talloc_free(forest_ref_res);
397                 return NT_STATUS_NO_SUCH_DOMAIN;                
398         }
399         talloc_steal(state, state->forest_dns);
400
401         talloc_free(forest_ref_res);
402
403         /* work out the builtin_dn - useful for so many calls its worth
404            fetching here */
405         state->builtin_dn = samdb_search_dn(state->sam_ldb, state, state->domain_dn, "(objectClass=builtinDomain)");
406         if (!state->builtin_dn) {
407                 return NT_STATUS_NO_SUCH_DOMAIN;                
408         }
409
410         /* work out the system_dn - useful for so many calls its worth
411            fetching here */
412         state->system_dn = samdb_search_dn(state->sam_ldb, state,
413                                            state->domain_dn, "(&(objectClass=container)(cn=System))");
414         if (!state->system_dn) {
415                 return NT_STATUS_NO_SUCH_DOMAIN;                
416         }
417
418         state->builtin_sid = dom_sid_parse_talloc(state, SID_BUILTIN);
419         if (!state->builtin_sid) {
420                 return NT_STATUS_NO_SUCH_DOMAIN;                
421         }
422
423         *_state = state;
424
425         return NT_STATUS_OK;
426 }
427
428 /* 
429   dssetup_DsRoleGetPrimaryDomainInformation 
430
431   This is not an LSA call, but is the only call left on the DSSETUP
432   pipe (after the pipe was truncated), and needs lsa_get_policy_state
433 */
434 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call, 
435                                                  TALLOC_CTX *mem_ctx,
436                                                  struct dssetup_DsRoleGetPrimaryDomainInformation *r)
437 {
438         union dssetup_DsRoleInfo *info;
439
440         info = talloc(mem_ctx, union dssetup_DsRoleInfo);
441         W_ERROR_HAVE_NO_MEMORY(info);
442
443         switch (r->in.level) {
444         case DS_ROLE_BASIC_INFORMATION:
445         {
446                 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
447                 uint32_t flags = 0;
448                 const char *domain = NULL;
449                 const char *dns_domain = NULL;
450                 const char *forest = NULL;
451                 struct GUID domain_guid;
452                 struct lsa_policy_state *state;
453
454                 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
455                 if (!NT_STATUS_IS_OK(status)) {
456                         return ntstatus_to_werror(status);
457                 }
458
459                 ZERO_STRUCT(domain_guid);
460
461                 switch (lp_server_role()) {
462                 case ROLE_STANDALONE:
463                         role            = DS_ROLE_STANDALONE_SERVER;
464                         break;
465                 case ROLE_DOMAIN_MEMBER:
466                         role            = DS_ROLE_MEMBER_SERVER;
467                         break;
468                 case ROLE_DOMAIN_CONTROLLER:
469                         if (samdb_is_pdc(state->sam_ldb)) {
470                                 role    = DS_ROLE_PRIMARY_DC;
471                         } else {
472                                 role    = DS_ROLE_BACKUP_DC;
473                         }
474                         break;
475                 }
476
477                 switch (lp_server_role()) {
478                 case ROLE_STANDALONE:
479                         domain          = talloc_strdup(mem_ctx, lp_workgroup());
480                         W_ERROR_HAVE_NO_MEMORY(domain);
481                         break;
482                 case ROLE_DOMAIN_MEMBER:
483                         domain          = talloc_strdup(mem_ctx, lp_workgroup());
484                         W_ERROR_HAVE_NO_MEMORY(domain);
485                         /* TODO: what is with dns_domain and forest and guid? */
486                         break;
487                 case ROLE_DOMAIN_CONTROLLER:
488                         flags           = DS_ROLE_PRIMARY_DS_RUNNING;
489
490                         if (state->mixed_domain == 1) {
491                                 flags   |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
492                         }
493                         
494                         domain          = state->domain_name;
495                         dns_domain      = state->domain_dns;
496                         forest          = state->forest_dns;
497
498                         domain_guid     = state->domain_guid;
499                         flags   |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
500                         break;
501                 }
502
503                 info->basic.role        = role; 
504                 info->basic.flags       = flags;
505                 info->basic.domain      = domain;
506                 info->basic.dns_domain  = dns_domain;
507                 info->basic.forest      = forest;
508                 info->basic.domain_guid = domain_guid;
509
510                 r->out.info = info;
511                 return WERR_OK;
512         }
513         case DS_ROLE_UPGRADE_STATUS:
514         {
515                 info->upgrade.upgrading     = DS_ROLE_NOT_UPGRADING;
516                 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
517
518                 r->out.info = info;
519                 return WERR_OK;
520         }
521         case DS_ROLE_OP_STATUS:
522         {
523                 info->opstatus.status = DS_ROLE_OP_IDLE;
524
525                 r->out.info = info;
526                 return WERR_OK;
527         }
528         default:
529                 return WERR_INVALID_PARAM;
530         }
531
532         return WERR_INVALID_PARAM;
533 }
534
535 /* 
536   lsa_OpenPolicy2
537 */
538 static NTSTATUS dcesrv_lsa_OpenPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
539                                struct lsa_OpenPolicy2 *r)
540 {
541         NTSTATUS status;
542         struct lsa_policy_state *state;
543         struct dcesrv_handle *handle;
544
545         ZERO_STRUCTP(r->out.handle);
546
547         status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
548         if (!NT_STATUS_IS_OK(status)) {
549                 return status;
550         }
551
552         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_POLICY);
553         if (!handle) {
554                 return NT_STATUS_NO_MEMORY;
555         }
556
557         handle->data = talloc_steal(handle, state);
558
559         state->access_mask = r->in.access_mask;
560         state->handle = handle;
561         *r->out.handle = handle->wire_handle;
562
563         /* note that we have completely ignored the attr element of
564            the OpenPolicy. As far as I can tell, this is what w2k3
565            does */
566
567         return NT_STATUS_OK;
568 }
569
570 /* 
571   lsa_OpenPolicy
572   a wrapper around lsa_OpenPolicy2
573 */
574 static NTSTATUS dcesrv_lsa_OpenPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
575                                 struct lsa_OpenPolicy *r)
576 {
577         struct lsa_OpenPolicy2 r2;
578
579         r2.in.system_name = NULL;
580         r2.in.attr = r->in.attr;
581         r2.in.access_mask = r->in.access_mask;
582         r2.out.handle = r->out.handle;
583
584         return dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &r2);
585 }
586
587
588
589
590 /*
591   fill in the AccountDomain info
592 */
593 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
594                                        struct lsa_DomainInfo *info)
595 {
596         info->name.string = state->domain_name;
597         info->sid         = state->domain_sid;
598
599         return NT_STATUS_OK;
600 }
601
602 /*
603   fill in the DNS domain info
604 */
605 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
606                              struct lsa_DnsDomainInfo *info)
607 {
608         info->name.string = state->domain_name;
609         info->sid         = state->domain_sid;
610         info->dns_domain.string = state->domain_dns;
611         info->dns_forest.string = state->forest_dns;
612         info->domain_guid       = state->domain_guid;
613
614         return NT_STATUS_OK;
615 }
616
617 /* 
618   lsa_QueryInfoPolicy2
619 */
620 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
621                                      struct lsa_QueryInfoPolicy2 *r)
622 {
623         struct lsa_policy_state *state;
624         struct dcesrv_handle *h;
625
626         r->out.info = NULL;
627
628         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
629
630         state = h->data;
631
632         r->out.info = talloc(mem_ctx, union lsa_PolicyInformation);
633         if (!r->out.info) {
634                 return NT_STATUS_NO_MEMORY;
635         }
636
637         ZERO_STRUCTP(r->out.info);
638
639         switch (r->in.level) {
640         case LSA_POLICY_INFO_DOMAIN:
641         case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
642                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &r->out.info->account_domain);
643
644         case LSA_POLICY_INFO_DNS:
645                 return dcesrv_lsa_info_DNS(state, mem_ctx, &r->out.info->dns);
646         }
647
648         return NT_STATUS_INVALID_INFO_CLASS;
649 }
650
651 /* 
652   lsa_QueryInfoPolicy 
653 */
654 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
655                                     struct lsa_QueryInfoPolicy *r)
656 {
657         struct lsa_QueryInfoPolicy2 r2;
658         NTSTATUS status;
659
660         r2.in.handle = r->in.handle;
661         r2.in.level = r->in.level;
662         
663         status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
664
665         r->out.info = r2.out.info;
666
667         return status;
668 }
669
670 /* 
671   lsa_SetInfoPolicy 
672 */
673 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
674                                   struct lsa_SetInfoPolicy *r)
675 {
676         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
677 }
678
679
680 /* 
681   lsa_ClearAuditLog 
682 */
683 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
684                                   struct lsa_ClearAuditLog *r)
685 {
686         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
687 }
688
689
690 /* 
691   lsa_CreateAccount 
692 */
693 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
694                                   struct lsa_CreateAccount *r)
695 {
696         struct lsa_account_state *astate;
697
698         struct lsa_policy_state *state;
699         struct dcesrv_handle *h, *ah;
700
701         ZERO_STRUCTP(r->out.acct_handle);
702
703         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
704
705         state = h->data;
706
707         astate = talloc(dce_call->conn, struct lsa_account_state);
708         if (astate == NULL) {
709                 return NT_STATUS_NO_MEMORY;
710         }
711
712         astate->account_sid = dom_sid_dup(astate, r->in.sid);
713         if (astate->account_sid == NULL) {
714                 talloc_free(astate);
715                 return NT_STATUS_NO_MEMORY;
716         }
717         
718         astate->policy = talloc_reference(astate, state);
719         astate->access_mask = r->in.access_mask;
720
721         ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
722         if (!ah) {
723                 talloc_free(astate);
724                 return NT_STATUS_NO_MEMORY;
725         }
726
727         ah->data = talloc_steal(ah, astate);
728
729         *r->out.acct_handle = ah->wire_handle;
730
731         return NT_STATUS_OK;
732 }
733
734
735 /* 
736   lsa_EnumAccounts 
737 */
738 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
739                                  struct lsa_EnumAccounts *r)
740 {
741         struct dcesrv_handle *h;
742         struct lsa_policy_state *state;
743         int ret, i;
744         struct ldb_message **res;
745         const char * const attrs[] = { "objectSid", NULL};
746         uint32_t count;
747
748         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
749
750         state = h->data;
751
752         /* NOTE: This call must only return accounts that have at least
753            one privilege set 
754         */
755         ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs, 
756                            "(&(objectSid=*)(privilege=*))");
757         if (ret < 0) {
758                 return NT_STATUS_NO_SUCH_USER;
759         }
760
761         if (*r->in.resume_handle >= ret) {
762                 return NT_STATUS_NO_MORE_ENTRIES;
763         }
764
765         count = ret - *r->in.resume_handle;
766         if (count > r->in.num_entries) {
767                 count = r->in.num_entries;
768         }
769
770         if (count == 0) {
771                 return NT_STATUS_NO_MORE_ENTRIES;
772         }
773
774         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
775         if (r->out.sids->sids == NULL) {
776                 return NT_STATUS_NO_MEMORY;
777         }
778
779         for (i=0;i<count;i++) {
780                 r->out.sids->sids[i].sid = 
781                         samdb_result_dom_sid(r->out.sids->sids, 
782                                              res[i + *r->in.resume_handle],
783                                              "objectSid");
784                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
785         }
786
787         r->out.sids->num_sids = count;
788         *r->out.resume_handle = count + *r->in.resume_handle;
789
790         return NT_STATUS_OK;
791         
792 }
793
794
795 /*
796   lsa_CreateTrustedDomainEx2
797 */
798 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
799                                            TALLOC_CTX *mem_ctx,
800                                            struct lsa_CreateTrustedDomainEx2 *r)
801 {
802         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
803 }
804
805 /*
806   lsa_CreateTrustedDomainEx
807 */
808 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
809                                           TALLOC_CTX *mem_ctx,
810                                           struct lsa_CreateTrustedDomainEx *r)
811 {
812         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
813 }
814
815 /* 
816   lsa_CreateTrustedDomain 
817 */
818 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
819                                         struct lsa_CreateTrustedDomain *r)
820 {
821         struct dcesrv_handle *policy_handle;
822         struct lsa_policy_state *policy_state;
823         struct lsa_trusted_domain_state *trusted_domain_state;
824         struct dcesrv_handle *handle;
825         struct ldb_message **msgs, *msg;
826         const char *attrs[] = {
827                 NULL
828         };
829         const char *name;
830         int ret;
831
832         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
833         ZERO_STRUCTP(r->out.trustdom_handle);
834         
835         policy_state = policy_handle->data;
836
837         if (!r->in.info->name.string) {
838                 return NT_STATUS_INVALID_PARAMETER;
839         }
840         name = r->in.info->name.string;
841         
842         trusted_domain_state = talloc(mem_ctx, struct lsa_trusted_domain_state);
843         if (!trusted_domain_state) {
844                 return NT_STATUS_NO_MEMORY;
845         }
846         trusted_domain_state->policy = policy_state;
847
848         msg = ldb_msg_new(mem_ctx);
849         if (msg == NULL) {
850                 return NT_STATUS_NO_MEMORY;
851         }
852
853         /* search for the trusted_domain record */
854         ret = gendb_search(trusted_domain_state->policy->sam_ldb,
855                            mem_ctx, policy_state->system_dn, &msgs, attrs,
856                            "(&(cn=%s)(objectclass=trustedDomain))", 
857                            ldb_binary_encode_string(mem_ctx, r->in.info->name.string));
858         if (ret > 0) {
859                 return NT_STATUS_OBJECT_NAME_COLLISION;
860         }
861         
862         if (ret < 0 || ret > 1) {
863                 DEBUG(0,("Found %d records matching DN %s\n", ret,
864                          ldb_dn_get_linearized(policy_state->system_dn)));
865                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
866         }
867         
868         msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
869         if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
870                 return NT_STATUS_NO_MEMORY;
871         }
872         
873         samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "flatname", name);
874
875         if (r->in.info->sid) {
876                 const char *sid_string = dom_sid_string(mem_ctx, r->in.info->sid);
877                 if (!sid_string) {
878                         return NT_STATUS_NO_MEMORY;
879                 }
880                         
881                 samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "securityIdentifier", sid_string);
882         }
883
884         samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "objectClass", "trustedDomain");
885         
886         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
887
888         /* create the trusted_domain */
889         ret = ldb_add(trusted_domain_state->policy->sam_ldb, msg);
890         if (ret != LDB_SUCCESS) {
891                 DEBUG(0,("Failed to create trusted_domain record %s: %s\n",
892                          ldb_dn_get_linearized(msg->dn), ldb_errstring(trusted_domain_state->policy->sam_ldb)));
893                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
894         }
895
896         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
897         if (!handle) {
898                 return NT_STATUS_NO_MEMORY;
899         }
900         
901         handle->data = talloc_steal(handle, trusted_domain_state);
902         
903         trusted_domain_state->access_mask = r->in.access_mask;
904         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
905         
906         *r->out.trustdom_handle = handle->wire_handle;
907         
908         return NT_STATUS_OK;
909 }
910
911 /* 
912   lsa_OpenTrustedDomain
913 */
914 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
915                                       struct lsa_OpenTrustedDomain *r)
916 {
917         struct dcesrv_handle *policy_handle;
918         
919         struct lsa_policy_state *policy_state;
920         struct lsa_trusted_domain_state *trusted_domain_state;
921         struct dcesrv_handle *handle;
922         struct ldb_message **msgs;
923         const char *attrs[] = {
924                 NULL
925         };
926
927         const char *sid_string;
928         int ret;
929
930         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
931         ZERO_STRUCTP(r->out.trustdom_handle);
932         policy_state = policy_handle->data;
933
934         trusted_domain_state = talloc(mem_ctx, struct lsa_trusted_domain_state);
935         if (!trusted_domain_state) {
936                 return NT_STATUS_NO_MEMORY;
937         }
938         trusted_domain_state->policy = policy_state;
939
940         sid_string = dom_sid_string(mem_ctx, r->in.sid);
941         if (!sid_string) {
942                 return NT_STATUS_NO_MEMORY;
943         }
944
945         /* search for the trusted_domain record */
946         ret = gendb_search(trusted_domain_state->policy->sam_ldb,
947                            mem_ctx, policy_state->system_dn, &msgs, attrs,
948                            "(&(securityIdentifier=%s)(objectclass=trustedDomain))", 
949                            sid_string);
950         if (ret == 0) {
951                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
952         }
953         
954         if (ret != 1) {
955                 DEBUG(0,("Found %d records matching DN %s\n", ret,
956                          ldb_dn_get_linearized(policy_state->system_dn)));
957                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
958         }
959
960         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
961         
962         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
963         if (!handle) {
964                 return NT_STATUS_NO_MEMORY;
965         }
966         
967         handle->data = talloc_steal(handle, trusted_domain_state);
968         
969         trusted_domain_state->access_mask = r->in.access_mask;
970         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
971         
972         *r->out.trustdom_handle = handle->wire_handle;
973         
974         return NT_STATUS_OK;
975 }
976
977
978 /*
979   lsa_OpenTrustedDomainByName
980 */
981 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
982                                             TALLOC_CTX *mem_ctx,
983                                             struct lsa_OpenTrustedDomainByName *r)
984 {
985         struct dcesrv_handle *policy_handle;
986         
987         struct lsa_policy_state *policy_state;
988         struct lsa_trusted_domain_state *trusted_domain_state;
989         struct dcesrv_handle *handle;
990         struct ldb_message **msgs;
991         const char *attrs[] = {
992                 NULL
993         };
994
995         int ret;
996
997         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
998         ZERO_STRUCTP(r->out.trustdom_handle);
999         policy_state = policy_handle->data;
1000
1001         if (!r->in.name.string) {
1002                 return NT_STATUS_INVALID_PARAMETER;
1003         }
1004         
1005         trusted_domain_state = talloc(mem_ctx, struct lsa_trusted_domain_state);
1006         if (!trusted_domain_state) {
1007                 return NT_STATUS_NO_MEMORY;
1008         }
1009         trusted_domain_state->policy = policy_state;
1010
1011         /* search for the trusted_domain record */
1012         ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1013                            mem_ctx, policy_state->system_dn, &msgs, attrs,
1014                            "(&(flatname=%s)(objectclass=trustedDomain))", 
1015                            ldb_binary_encode_string(mem_ctx, r->in.name.string));
1016         if (ret == 0) {
1017                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1018         }
1019         
1020         if (ret != 1) {
1021                 DEBUG(0,("Found %d records matching DN %s\n", ret,
1022                          ldb_dn_get_linearized(policy_state->system_dn)));
1023                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1024         }
1025
1026         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1027         
1028         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1029         if (!handle) {
1030                 return NT_STATUS_NO_MEMORY;
1031         }
1032         
1033         handle->data = talloc_steal(handle, trusted_domain_state);
1034         
1035         trusted_domain_state->access_mask = r->in.access_mask;
1036         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1037         
1038         *r->out.trustdom_handle = handle->wire_handle;
1039         
1040         return NT_STATUS_OK;
1041 }
1042
1043
1044
1045 /* 
1046   lsa_SetTrustedDomainInfo
1047 */
1048 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1049                                          struct lsa_SetTrustedDomainInfo *r)
1050 {
1051         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1052 }
1053
1054
1055
1056 /* 
1057   lsa_SetInfomrationTrustedDomain
1058 */
1059 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(struct dcesrv_call_state *dce_call, 
1060                                                 TALLOC_CTX *mem_ctx,
1061                                                 struct lsa_SetInformationTrustedDomain *r)
1062 {
1063         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1064 }
1065
1066
1067 /* 
1068   lsa_DeleteTrustedDomain
1069 */
1070 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1071                                       struct lsa_DeleteTrustedDomain *r)
1072 {
1073         NTSTATUS status;
1074         struct lsa_OpenTrustedDomain open;
1075         struct lsa_Delete delete;
1076         struct dcesrv_handle *h;
1077
1078         open.in.handle = r->in.handle;
1079         open.in.sid = r->in.dom_sid;
1080         open.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1081         open.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1082         if (!open.out.trustdom_handle) {
1083                 return NT_STATUS_NO_MEMORY;
1084         }
1085         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &open);
1086         if (!NT_STATUS_IS_OK(status)) {
1087                 return status;
1088         }
1089
1090         DCESRV_PULL_HANDLE(h, open.out.trustdom_handle, DCESRV_HANDLE_ANY);
1091         talloc_steal(mem_ctx, h);
1092
1093         delete.in.handle = open.out.trustdom_handle;
1094         status = dcesrv_lsa_Delete(dce_call, mem_ctx, &delete);
1095         if (!NT_STATUS_IS_OK(status)) {
1096                 return status;
1097         }
1098         return NT_STATUS_OK;
1099 }
1100
1101 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx, 
1102                                      struct ldb_message *msg, 
1103                                      struct lsa_TrustDomainInfoInfoEx *info_ex) 
1104 {
1105         info_ex->domain_name.string
1106                 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
1107         info_ex->netbios_name.string
1108                 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1109         info_ex->sid 
1110                 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
1111         info_ex->trust_direction
1112                 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
1113         info_ex->trust_type
1114                 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
1115         info_ex->trust_attributes
1116                 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);  
1117         return NT_STATUS_OK;
1118 }
1119
1120 /* 
1121   lsa_QueryTrustedDomainInfo
1122 */
1123 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1124                                            struct lsa_QueryTrustedDomainInfo *r)
1125 {
1126         struct dcesrv_handle *h;
1127         struct lsa_trusted_domain_state *trusted_domain_state;
1128         struct ldb_message *msg;
1129         int ret;
1130         struct ldb_message **res;
1131         const char *attrs[] = {
1132                 "flatname", 
1133                 "trustPartner",
1134                 "securityIdentifier",
1135                 "trustDirection",
1136                 "trustType",
1137                 "trustAttributes", 
1138                 NULL
1139         };
1140
1141         DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
1142
1143         trusted_domain_state = h->data;
1144
1145         /* pull all the user attributes */
1146         ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
1147                               trusted_domain_state->trusted_domain_dn, &res, attrs);
1148         if (ret != 1) {
1149                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1150         }
1151         msg = res[0];
1152         
1153         r->out.info = talloc(mem_ctx, union lsa_TrustedDomainInfo);
1154         if (!r->out.info) {
1155                 return NT_STATUS_NO_MEMORY;
1156         }
1157         switch (r->in.level) {
1158         case LSA_TRUSTED_DOMAIN_INFO_NAME:
1159                 r->out.info->name.netbios_name.string
1160                         = samdb_result_string(msg, "flatname", NULL);                                      
1161                 break;
1162         case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1163                 r->out.info->posix_offset.posix_offset
1164                         = samdb_result_uint(msg, "posixOffset", 0);                                        
1165                 break;
1166 #if 0  /* Win2k3 doesn't implement this */
1167         case LSA_TRUSTED_DOMAIN_INFO_BASIC:
1168                 r->out.info->info_basic.netbios_name.string 
1169                         = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1170                 r->out.info->info_basic.sid
1171                         = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
1172                 break;
1173 #endif
1174         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1175                 return fill_trust_domain_ex(mem_ctx, msg, &r->out.info->info_ex);
1176
1177         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1178                 ZERO_STRUCT(r->out.info->full_info);
1179                 return fill_trust_domain_ex(mem_ctx, msg, &r->out.info->full_info.info_ex);
1180
1181         case LSA_TRUSTED_DOMAIN_INFO_INFO_ALL:
1182                 ZERO_STRUCT(r->out.info->info_all);
1183                 return fill_trust_domain_ex(mem_ctx, msg, &r->out.info->info_all.info_ex);
1184
1185         case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS_INFO:
1186         case LSA_TRUSTED_DOMAIN_INFO_11:
1187                 /* oops, we don't want to return the info after all */
1188                 talloc_free(r->out.info);
1189                 r->out.info = NULL;
1190                 return NT_STATUS_INVALID_PARAMETER;
1191         default:
1192                 /* oops, we don't want to return the info after all */
1193                 talloc_free(r->out.info);
1194                 r->out.info = NULL;
1195                 return NT_STATUS_INVALID_INFO_CLASS;
1196         }
1197
1198         return NT_STATUS_OK;
1199 }
1200
1201
1202 /* 
1203   lsa_QueryTrustedDomainInfoBySid
1204 */
1205 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1206                                                 struct lsa_QueryTrustedDomainInfoBySid *r)
1207 {
1208         NTSTATUS status;
1209         struct lsa_OpenTrustedDomain open;
1210         struct lsa_QueryTrustedDomainInfo query;
1211         struct dcesrv_handle *h;
1212         open.in.handle = r->in.handle;
1213         open.in.sid = r->in.dom_sid;
1214         open.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1215         open.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1216         if (!open.out.trustdom_handle) {
1217                 return NT_STATUS_NO_MEMORY;
1218         }
1219         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &open);
1220         if (!NT_STATUS_IS_OK(status)) {
1221                 return status;
1222         }
1223
1224         /* Ensure this handle goes away at the end of this call */
1225         DCESRV_PULL_HANDLE(h, open.out.trustdom_handle, DCESRV_HANDLE_ANY);
1226         talloc_steal(mem_ctx, h);
1227         
1228         query.in.trustdom_handle = open.out.trustdom_handle;
1229         query.in.level = r->in.level;
1230         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
1231         if (!NT_STATUS_IS_OK(status)) {
1232                 return status;
1233         }
1234         
1235         r->out.info = query.out.info;
1236         return NT_STATUS_OK;
1237 }
1238
1239 /*
1240   lsa_SetTrustedDomainInfoByName
1241 */
1242 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
1243                                                TALLOC_CTX *mem_ctx,
1244                                                struct lsa_SetTrustedDomainInfoByName *r)
1245 {
1246         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1247 }
1248
1249 /* 
1250    lsa_QueryTrustedDomainInfoByName
1251 */
1252 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
1253                                                  TALLOC_CTX *mem_ctx,
1254                                                  struct lsa_QueryTrustedDomainInfoByName *r)
1255 {
1256         NTSTATUS status;
1257         struct lsa_OpenTrustedDomainByName open;
1258         struct lsa_QueryTrustedDomainInfo query;
1259         struct dcesrv_handle *h;
1260         open.in.handle = r->in.handle;
1261         open.in.name = r->in.trusted_domain;
1262         open.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1263         open.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1264         if (!open.out.trustdom_handle) {
1265                 return NT_STATUS_NO_MEMORY;
1266         }
1267         status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &open);
1268         if (!NT_STATUS_IS_OK(status)) {
1269                 return status;
1270         }
1271         
1272         /* Ensure this handle goes away at the end of this call */
1273         DCESRV_PULL_HANDLE(h, open.out.trustdom_handle, DCESRV_HANDLE_ANY);
1274         talloc_steal(mem_ctx, h);
1275
1276         query.in.trustdom_handle = open.out.trustdom_handle;
1277         query.in.level = r->in.level;
1278         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
1279         if (!NT_STATUS_IS_OK(status)) {
1280                 return status;
1281         }
1282         
1283         r->out.info = query.out.info;
1284         return NT_STATUS_OK;
1285 }
1286
1287 /*
1288   lsa_CloseTrustedDomainEx 
1289 */
1290 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
1291                                          TALLOC_CTX *mem_ctx,
1292                                          struct lsa_CloseTrustedDomainEx *r)
1293 {
1294         /* The result of a bad hair day from an IDL programmer?  Not
1295          * implmented in Win2k3.  You should always just lsa_Close
1296          * anyway. */
1297         return NT_STATUS_NOT_IMPLEMENTED;
1298 }
1299
1300
1301 /*
1302   comparison function for sorting lsa_DomainInformation array
1303 */
1304 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
1305 {
1306         return strcasecmp_m(e1->name.string, e2->name.string);
1307 }
1308
1309 /* 
1310   lsa_EnumTrustDom 
1311 */
1312 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1313                                  struct lsa_EnumTrustDom *r)
1314 {
1315         struct dcesrv_handle *policy_handle;
1316         struct lsa_DomainInfo *entries;
1317         struct lsa_policy_state *policy_state;
1318         struct ldb_message **domains;
1319         const char *attrs[] = {
1320                 "flatname", 
1321                 "securityIdentifier",
1322                 NULL
1323         };
1324
1325
1326         int count, i;
1327
1328         *r->out.resume_handle = 0;
1329
1330         r->out.domains->domains = NULL;
1331         r->out.domains->count = 0;
1332
1333         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1334
1335         policy_state = policy_handle->data;
1336
1337         /* search for all users in this domain. This could possibly be cached and 
1338            resumed based on resume_key */
1339         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs, 
1340                              "objectclass=trustedDomain");
1341         if (count == -1) {
1342                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1343         }
1344         if (count == 0 || r->in.max_size == 0) {
1345                 return NT_STATUS_OK;
1346         }
1347
1348         /* convert to lsa_TrustInformation format */
1349         entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
1350         if (!entries) {
1351                 return NT_STATUS_NO_MEMORY;
1352         }
1353         for (i=0;i<count;i++) {
1354                 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
1355                 entries[i].name.string = samdb_result_string(domains[i], "flatname", NULL);
1356         }
1357
1358         /* sort the results by name */
1359         qsort(entries, count, sizeof(*entries), 
1360               (comparison_fn_t)compare_DomainInfo);
1361
1362         if (*r->in.resume_handle >= count) {
1363                 *r->out.resume_handle = -1;
1364
1365                 return NT_STATUS_NO_MORE_ENTRIES;
1366         }
1367
1368         /* return the rest, limit by max_size. Note that we 
1369            use the w2k3 element size value of 60 */
1370         r->out.domains->count = count - *r->in.resume_handle;
1371         r->out.domains->count = MIN(r->out.domains->count, 
1372                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
1373
1374         r->out.domains->domains = entries + *r->in.resume_handle;
1375         r->out.domains->count = r->out.domains->count;
1376
1377         if (r->out.domains->count < count - *r->in.resume_handle) {
1378                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
1379                 return STATUS_MORE_ENTRIES;
1380         }
1381
1382         return NT_STATUS_OK;
1383 }
1384
1385 /*
1386   comparison function for sorting lsa_DomainInformation array
1387 */
1388 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
1389 {
1390         return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
1391 }
1392
1393 /* 
1394   lsa_EnumTrustedDomainsEx 
1395 */
1396 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1397                                         struct lsa_EnumTrustedDomainsEx *r)
1398 {
1399         struct dcesrv_handle *policy_handle;
1400         struct lsa_TrustDomainInfoInfoEx *entries;
1401         struct lsa_policy_state *policy_state;
1402         struct ldb_message **domains;
1403         const char *attrs[] = {
1404                 "flatname", 
1405                 "trustPartner",
1406                 "securityIdentifier",
1407                 "trustDirection",
1408                 "trustType",
1409                 "trustAttributes", 
1410                 NULL
1411         };
1412         NTSTATUS nt_status;
1413
1414         int count, i;
1415
1416         *r->out.resume_handle = 0;
1417
1418         r->out.domains->domains = NULL;
1419         r->out.domains->count = 0;
1420
1421         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1422
1423         policy_state = policy_handle->data;
1424
1425         /* search for all users in this domain. This could possibly be cached and 
1426            resumed based on resume_key */
1427         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs, 
1428                              "objectclass=trustedDomain");
1429         if (count == -1) {
1430                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1431         }
1432         if (count == 0 || r->in.max_size == 0) {
1433                 return NT_STATUS_OK;
1434         }
1435
1436         /* convert to lsa_DomainInformation format */
1437         entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
1438         if (!entries) {
1439                 return NT_STATUS_NO_MEMORY;
1440         }
1441         for (i=0;i<count;i++) {
1442                 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
1443                 if (!NT_STATUS_IS_OK(nt_status)) {
1444                         return nt_status;
1445                 }
1446         }
1447
1448         /* sort the results by name */
1449         qsort(entries, count, sizeof(*entries), 
1450               (comparison_fn_t)compare_TrustDomainInfoInfoEx);
1451
1452         if (*r->in.resume_handle >= count) {
1453                 *r->out.resume_handle = -1;
1454
1455                 return NT_STATUS_NO_MORE_ENTRIES;
1456         }
1457
1458         /* return the rest, limit by max_size. Note that we 
1459            use the w2k3 element size value of 60 */
1460         r->out.domains->count = count - *r->in.resume_handle;
1461         r->out.domains->count = MIN(r->out.domains->count, 
1462                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
1463
1464         r->out.domains->domains = entries + *r->in.resume_handle;
1465         r->out.domains->count = r->out.domains->count;
1466
1467         if (r->out.domains->count < count - *r->in.resume_handle) {
1468                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
1469                 return STATUS_MORE_ENTRIES;
1470         }
1471
1472         return NT_STATUS_OK;
1473 }
1474
1475
1476 /*
1477   return the authority name and authority sid, given a sid
1478 */
1479 static NTSTATUS dcesrv_lsa_authority_name(struct lsa_policy_state *state,
1480                                    TALLOC_CTX *mem_ctx, struct dom_sid *sid,
1481                                    const char **authority_name,
1482                                    struct dom_sid **authority_sid)
1483 {
1484         if (dom_sid_in_domain(state->domain_sid, sid)) {
1485                 *authority_name = state->domain_name;
1486                 *authority_sid = state->domain_sid;
1487                 return NT_STATUS_OK;
1488         }
1489
1490         if (dom_sid_in_domain(state->builtin_sid, sid)) {
1491                 *authority_name = "BUILTIN";
1492                 *authority_sid = state->builtin_sid;
1493                 return NT_STATUS_OK;
1494         }
1495
1496         *authority_sid = dom_sid_dup(mem_ctx, sid);
1497         if (*authority_sid == NULL) {
1498                 return NT_STATUS_NO_MEMORY;
1499         }
1500         (*authority_sid)->num_auths = 0;
1501         *authority_name = dom_sid_string(mem_ctx, *authority_sid);
1502         if (*authority_name == NULL) {
1503                 return NT_STATUS_NO_MEMORY;
1504         }
1505
1506         return NT_STATUS_OK;
1507 }
1508
1509 /*
1510   add to the lsa_RefDomainList for LookupSids and LookupNames
1511 */
1512 static NTSTATUS dcesrv_lsa_authority_list(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx, 
1513                                    struct dom_sid *sid, 
1514                                    struct lsa_RefDomainList *domains,
1515                                    uint32_t *sid_index)
1516 {
1517         NTSTATUS status;
1518         const char *authority_name;
1519         struct dom_sid *authority_sid;
1520         int i;
1521
1522         /* work out the authority name */
1523         status = dcesrv_lsa_authority_name(state, mem_ctx, sid, 
1524                                     &authority_name, &authority_sid);
1525         if (!NT_STATUS_IS_OK(status)) {
1526                 return status;
1527         }
1528         
1529         /* see if we've already done this authority name */
1530         for (i=0;i<domains->count;i++) {
1531                 if (strcmp(authority_name, domains->domains[i].name.string) == 0) {
1532                         *sid_index = i;
1533                         return NT_STATUS_OK;
1534                 }
1535         }
1536
1537         domains->domains = talloc_realloc(domains, 
1538                                           domains->domains,
1539                                           struct lsa_DomainInfo,
1540                                           domains->count+1);
1541         if (domains->domains == NULL) {
1542                 return NT_STATUS_NO_MEMORY;
1543         }
1544         domains->domains[i].name.string = authority_name;
1545         domains->domains[i].sid         = authority_sid;
1546         domains->count++;
1547         domains->max_size = LSA_REF_DOMAIN_LIST_MULTIPLIER * domains->count;
1548         *sid_index = i;
1549         
1550         return NT_STATUS_OK;
1551 }
1552
1553 /*
1554   lookup a name for 1 SID
1555 */
1556 static NTSTATUS dcesrv_lsa_lookup_sid(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
1557                                struct dom_sid *sid, const char *sid_str,
1558                                const char **name, uint32_t *atype)
1559 {
1560         int ret;
1561         struct ldb_message **res;
1562         const char * const attrs[] = { "sAMAccountName", "sAMAccountType", "name", NULL};
1563         NTSTATUS status;
1564
1565         ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs, 
1566                            "objectSid=%s", ldap_encode_ndr_dom_sid(mem_ctx, sid));
1567         if (ret == 1) {
1568                 *name = ldb_msg_find_attr_as_string(res[0], "sAMAccountName", NULL);
1569                 if (!*name) {
1570                         *name = ldb_msg_find_attr_as_string(res[0], "name", NULL);
1571                         if (!*name) {
1572                                 *name = talloc_strdup(mem_ctx, sid_str);
1573                                 NT_STATUS_HAVE_NO_MEMORY(*name);
1574                         }
1575                 }
1576
1577                 *atype = samdb_result_uint(res[0], "sAMAccountType", 0);
1578
1579                 return NT_STATUS_OK;
1580         }
1581
1582         status = sidmap_allocated_sid_lookup(state->sidmap, mem_ctx, sid, name, atype);
1583
1584         return status;
1585 }
1586
1587
1588 /*
1589   lsa_LookupSids2
1590 */
1591 static NTSTATUS dcesrv_lsa_LookupSids2(struct dcesrv_call_state *dce_call,
1592                                 TALLOC_CTX *mem_ctx,
1593                                 struct lsa_LookupSids2 *r)
1594 {
1595         struct lsa_policy_state *state;
1596         int i;
1597         NTSTATUS status = NT_STATUS_OK;
1598
1599         r->out.domains = NULL;
1600
1601         status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
1602         if (!NT_STATUS_IS_OK(status)) {
1603                 return status;
1604         }
1605
1606         r->out.domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
1607         if (r->out.domains == NULL) {
1608                 return NT_STATUS_NO_MEMORY;
1609         }
1610
1611         r->out.names = talloc_zero(mem_ctx,  struct lsa_TransNameArray2);
1612         if (r->out.names == NULL) {
1613                 return NT_STATUS_NO_MEMORY;
1614         }
1615
1616         *r->out.count = 0;
1617
1618         r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName2, 
1619                                              r->in.sids->num_sids);
1620         if (r->out.names->names == NULL) {
1621                 return NT_STATUS_NO_MEMORY;
1622         }
1623
1624         for (i=0;i<r->in.sids->num_sids;i++) {
1625                 struct dom_sid *sid = r->in.sids->sids[i].sid;
1626                 char *sid_str = dom_sid_string(mem_ctx, sid);
1627                 const char *name;
1628                 uint32_t atype, rtype, sid_index;
1629                 NTSTATUS status2;
1630
1631                 r->out.names->count++;
1632                 (*r->out.count)++;
1633
1634                 r->out.names->names[i].sid_type    = SID_NAME_UNKNOWN;
1635                 r->out.names->names[i].name.string = sid_str;
1636                 r->out.names->names[i].sid_index   = 0xFFFFFFFF;
1637                 r->out.names->names[i].unknown     = 0;
1638
1639                 if (sid_str == NULL) {
1640                         r->out.names->names[i].name.string = "(SIDERROR)";
1641                         status = STATUS_SOME_UNMAPPED;
1642                         continue;
1643                 }
1644
1645                 /* work out the authority name */
1646                 status2 = dcesrv_lsa_authority_list(state, mem_ctx, sid, r->out.domains, &sid_index);
1647                 if (!NT_STATUS_IS_OK(status2)) {
1648                         return status2;
1649                 }
1650
1651                 status2 = dcesrv_lsa_lookup_sid(state, mem_ctx, sid, sid_str, 
1652                                          &name, &atype);
1653                 if (!NT_STATUS_IS_OK(status2)) {
1654                         status = STATUS_SOME_UNMAPPED;
1655                         continue;
1656                 }
1657
1658                 rtype = samdb_atype_map(atype);
1659                 if (rtype == SID_NAME_UNKNOWN) {
1660                         status = STATUS_SOME_UNMAPPED;
1661                         continue;
1662                 }
1663
1664                 r->out.names->names[i].sid_type    = rtype;
1665                 r->out.names->names[i].name.string = name;
1666                 r->out.names->names[i].sid_index   = sid_index;
1667                 r->out.names->names[i].unknown     = 0;
1668         }
1669         
1670         return status;
1671 }
1672
1673
1674 /*
1675   lsa_LookupSids3
1676
1677   Identical to LookupSids2, but doesn't take a policy handle
1678   
1679 */
1680 static NTSTATUS dcesrv_lsa_LookupSids3(struct dcesrv_call_state *dce_call,
1681                                 TALLOC_CTX *mem_ctx,
1682                                 struct lsa_LookupSids3 *r)
1683 {
1684         struct lsa_LookupSids2 r2;
1685         struct lsa_OpenPolicy2 pol;
1686         NTSTATUS status;
1687         struct dcesrv_handle *h;
1688
1689         /* No policy handle on the wire, so make one up here */
1690         r2.in.handle = talloc(mem_ctx, struct policy_handle);
1691         if (!r2.in.handle) {
1692                 return NT_STATUS_NO_MEMORY;
1693         }
1694
1695         pol.out.handle = r2.in.handle;
1696         pol.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1697         pol.in.attr = NULL;
1698         pol.in.system_name = NULL;
1699         status = dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &pol);
1700         if (!NT_STATUS_IS_OK(status)) {
1701                 return status;
1702         }
1703
1704         /* ensure this handle goes away at the end of this call */
1705         DCESRV_PULL_HANDLE(h, r2.in.handle, LSA_HANDLE_POLICY);
1706         talloc_steal(mem_ctx, h);
1707
1708         r2.in.sids     = r->in.sids;
1709         r2.in.names    = r->in.names;
1710         r2.in.level    = r->in.level;
1711         r2.in.count    = r->in.count;
1712         r2.in.unknown1 = r->in.unknown1;
1713         r2.in.unknown2 = r->in.unknown2;
1714         r2.out.count   = r->out.count;
1715         r2.out.names   = r->out.names;
1716
1717         status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
1718         if (dce_call->fault_code != 0) {
1719                 return status;
1720         }
1721
1722         r->out.domains = r2.out.domains;
1723         r->out.names   = r2.out.names;
1724         r->out.count   = r2.out.count;
1725
1726         return status;
1727 }
1728
1729
1730 /* 
1731   lsa_LookupSids 
1732 */
1733 static NTSTATUS dcesrv_lsa_LookupSids(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1734                                struct lsa_LookupSids *r)
1735 {
1736         struct lsa_LookupSids2 r2;
1737         NTSTATUS status;
1738         int i;
1739
1740         r2.in.handle   = r->in.handle;
1741         r2.in.sids     = r->in.sids;
1742         r2.in.names    = NULL;
1743         r2.in.level    = r->in.level;
1744         r2.in.count    = r->in.count;
1745         r2.in.unknown1 = 0;
1746         r2.in.unknown2 = 0;
1747         r2.out.count   = r->out.count;
1748         r2.out.names   = NULL;
1749
1750         status = dcesrv_lsa_LookupSids2(dce_call, mem_ctx, &r2);
1751         if (dce_call->fault_code != 0) {
1752                 return status;
1753         }
1754
1755         r->out.domains = r2.out.domains;
1756         if (!r2.out.names) {
1757                 r->out.names = NULL;
1758                 return status;
1759         }
1760
1761         r->out.names = talloc(mem_ctx, struct lsa_TransNameArray);
1762         if (r->out.names == NULL) {
1763                 return NT_STATUS_NO_MEMORY;
1764         }
1765         r->out.names->count = r2.out.names->count;
1766         r->out.names->names = talloc_array(r->out.names, struct lsa_TranslatedName, 
1767                                              r->out.names->count);
1768         if (r->out.names->names == NULL) {
1769                 return NT_STATUS_NO_MEMORY;
1770         }
1771         for (i=0;i<r->out.names->count;i++) {
1772                 r->out.names->names[i].sid_type    = r2.out.names->names[i].sid_type;
1773                 r->out.names->names[i].name.string = r2.out.names->names[i].name.string;
1774                 r->out.names->names[i].sid_index   = r2.out.names->names[i].sid_index;
1775         }
1776
1777         return status;
1778 }
1779
1780
1781 /* 
1782   lsa_OpenAccount 
1783 */
1784 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1785                                 struct lsa_OpenAccount *r)
1786 {
1787         struct dcesrv_handle *h, *ah;
1788         struct lsa_policy_state *state;
1789         struct lsa_account_state *astate;
1790
1791         ZERO_STRUCTP(r->out.acct_handle);
1792
1793         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
1794
1795         state = h->data;
1796
1797         astate = talloc(dce_call->conn, struct lsa_account_state);
1798         if (astate == NULL) {
1799                 return NT_STATUS_NO_MEMORY;
1800         }
1801
1802         astate->account_sid = dom_sid_dup(astate, r->in.sid);
1803         if (astate->account_sid == NULL) {
1804                 talloc_free(astate);
1805                 return NT_STATUS_NO_MEMORY;
1806         }
1807         
1808         astate->policy = talloc_reference(astate, state);
1809         astate->access_mask = r->in.access_mask;
1810
1811         ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
1812         if (!ah) {
1813                 talloc_free(astate);
1814                 return NT_STATUS_NO_MEMORY;
1815         }
1816
1817         ah->data = talloc_steal(ah, astate);
1818
1819         *r->out.acct_handle = ah->wire_handle;
1820
1821         return NT_STATUS_OK;
1822 }
1823
1824
1825 /* 
1826   lsa_EnumPrivsAccount 
1827 */
1828 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call, 
1829                                      TALLOC_CTX *mem_ctx,
1830                                      struct lsa_EnumPrivsAccount *r)
1831 {
1832         struct dcesrv_handle *h;
1833         struct lsa_account_state *astate;
1834         int ret, i;
1835         struct ldb_message **res;
1836         const char * const attrs[] = { "privilege", NULL};
1837         struct ldb_message_element *el;
1838         const char *sidstr;
1839
1840         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
1841
1842         astate = h->data;
1843
1844         r->out.privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
1845         r->out.privs->count = 0;
1846         r->out.privs->unknown = 0;
1847         r->out.privs->set = NULL;
1848
1849         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
1850         if (sidstr == NULL) {
1851                 return NT_STATUS_NO_MEMORY;
1852         }
1853
1854         ret = gendb_search(astate->policy->sam_ldb, mem_ctx, NULL, &res, attrs, 
1855                            "objectSid=%s", sidstr);
1856         if (ret != 1) {
1857                 return NT_STATUS_OK;
1858         }
1859
1860         el = ldb_msg_find_element(res[0], "privilege");
1861         if (el == NULL || el->num_values == 0) {
1862                 return NT_STATUS_OK;
1863         }
1864
1865         r->out.privs->set = talloc_array(r->out.privs, 
1866                                          struct lsa_LUIDAttribute, el->num_values);
1867         if (r->out.privs->set == NULL) {
1868                 return NT_STATUS_NO_MEMORY;
1869         }
1870
1871         for (i=0;i<el->num_values;i++) {
1872                 int id = sec_privilege_id((const char *)el->values[i].data);
1873                 if (id == -1) {
1874                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1875                 }
1876                 r->out.privs->set[i].attribute = 0;
1877                 r->out.privs->set[i].luid.low = id;
1878                 r->out.privs->set[i].luid.high = 0;
1879         }
1880
1881         r->out.privs->count = el->num_values;
1882
1883         return NT_STATUS_OK;
1884 }
1885
1886 /* 
1887   lsa_EnumAccountRights 
1888 */
1889 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call, 
1890                                       TALLOC_CTX *mem_ctx,
1891                                       struct lsa_EnumAccountRights *r)
1892 {
1893         struct dcesrv_handle *h;
1894         struct lsa_policy_state *state;
1895         int ret, i;
1896         struct ldb_message **res;
1897         const char * const attrs[] = { "privilege", NULL};
1898         const char *sidstr;
1899         struct ldb_message_element *el;
1900
1901         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
1902
1903         state = h->data;
1904
1905         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
1906         if (sidstr == NULL) {
1907                 return NT_STATUS_NO_MEMORY;
1908         }
1909
1910         ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs, 
1911                            "(&(objectSid=%s)(privilege=*))", sidstr);
1912         if (ret == 0) {
1913                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1914         }
1915         if (ret > 1) {
1916                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1917         }
1918         if (ret == -1) {
1919                 DEBUG(3, ("searching for account rights for SID: %s failed: %s", 
1920                           dom_sid_string(mem_ctx, r->in.sid),
1921                           ldb_errstring(state->sam_ldb)));
1922                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1923         }
1924
1925         el = ldb_msg_find_element(res[0], "privilege");
1926         if (el == NULL || el->num_values == 0) {
1927                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1928         }
1929
1930         r->out.rights->count = el->num_values;
1931         r->out.rights->names = talloc_array(r->out.rights, 
1932                                             struct lsa_StringLarge, r->out.rights->count);
1933         if (r->out.rights->names == NULL) {
1934                 return NT_STATUS_NO_MEMORY;
1935         }
1936
1937         for (i=0;i<el->num_values;i++) {
1938                 r->out.rights->names[i].string = (const char *)el->values[i].data;
1939         }
1940
1941         return NT_STATUS_OK;
1942 }
1943
1944
1945
1946 /* 
1947   helper for lsa_AddAccountRights and lsa_RemoveAccountRights
1948 */
1949 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call, 
1950                                            TALLOC_CTX *mem_ctx,
1951                                            struct lsa_policy_state *state,
1952                                            int ldb_flag,
1953                                            struct dom_sid *sid,
1954                                            const struct lsa_RightSet *rights)
1955 {
1956         const char *sidstr;
1957         struct ldb_message *msg;
1958         struct ldb_message_element *el;
1959         int i, ret;
1960         struct lsa_EnumAccountRights r2;
1961
1962         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, sid);
1963         if (sidstr == NULL) {
1964                 return NT_STATUS_NO_MEMORY;
1965         }
1966
1967         msg = ldb_msg_new(mem_ctx);
1968         if (msg == NULL) {
1969                 return NT_STATUS_NO_MEMORY;
1970         }
1971
1972         msg->dn = samdb_search_dn(state->sam_ldb, mem_ctx, 
1973                                   NULL, "objectSid=%s", sidstr);
1974         if (msg->dn == NULL) {
1975                 NTSTATUS status;
1976                 if (ldb_flag == LDB_FLAG_MOD_DELETE) {
1977                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1978                 }
1979                 status = samdb_create_foreign_security_principal(state->sam_ldb, mem_ctx, 
1980                                                                  sid, &msg->dn);
1981                 if (!NT_STATUS_IS_OK(status)) {
1982                         return status;
1983                 }
1984                 return NT_STATUS_NO_SUCH_USER;
1985         }
1986
1987         if (ldb_msg_add_empty(msg, "privilege", ldb_flag, NULL)) {
1988                 return NT_STATUS_NO_MEMORY;
1989         }
1990
1991         if (ldb_flag == LDB_FLAG_MOD_ADD) {
1992                 NTSTATUS status;
1993
1994                 r2.in.handle = &state->handle->wire_handle;
1995                 r2.in.sid = sid;
1996                 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
1997
1998                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
1999                 if (!NT_STATUS_IS_OK(status)) {
2000                         ZERO_STRUCTP(r2.out.rights);
2001                 }
2002         }
2003
2004         for (i=0;i<rights->count;i++) {
2005                 if (sec_privilege_id(rights->names[i].string) == -1) {
2006                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2007                 }
2008
2009                 if (ldb_flag == LDB_FLAG_MOD_ADD) {
2010                         int j;
2011                         for (j=0;j<r2.out.rights->count;j++) {
2012                                 if (strcasecmp_m(r2.out.rights->names[j].string, 
2013                                                rights->names[i].string) == 0) {
2014                                         break;
2015                                 }
2016                         }
2017                         if (j != r2.out.rights->count) continue;
2018                 }
2019
2020                 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2021                 if (ret != LDB_SUCCESS) {
2022                         return NT_STATUS_NO_MEMORY;
2023                 }
2024         }
2025
2026         el = ldb_msg_find_element(msg, "privilege");
2027         if (!el) {
2028                 return NT_STATUS_OK;
2029         }
2030
2031         ret = samdb_modify(state->sam_ldb, mem_ctx, msg);
2032         if (ret != 0) {
2033                 if (ldb_flag == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2034                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2035                 }
2036                 DEBUG(3, ("Could not %s attributes from %s: %s", 
2037                           ldb_flag == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2038                           ldb_dn_get_linearized(msg->dn), ldb_errstring(state->sam_ldb)));
2039                 return NT_STATUS_UNEXPECTED_IO_ERROR;
2040         }
2041
2042         return NT_STATUS_OK;
2043 }
2044
2045 /* 
2046   lsa_AddPrivilegesToAccount
2047 */
2048 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2049                                            struct lsa_AddPrivilegesToAccount *r)
2050 {
2051         struct lsa_RightSet rights;
2052         struct dcesrv_handle *h;
2053         struct lsa_account_state *astate;
2054         int i;
2055
2056         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2057
2058         astate = h->data;
2059
2060         rights.count = r->in.privs->count;
2061         rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2062         if (rights.names == NULL) {
2063                 return NT_STATUS_NO_MEMORY;
2064         }
2065         for (i=0;i<rights.count;i++) {
2066                 int id = r->in.privs->set[i].luid.low;
2067                 if (r->in.privs->set[i].luid.high) {
2068                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2069                 }
2070                 rights.names[i].string = sec_privilege_name(id);
2071                 if (rights.names[i].string == NULL) {
2072                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2073                 }
2074         }
2075
2076         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
2077                                           LDB_FLAG_MOD_ADD, astate->account_sid,
2078                                           &rights);
2079 }
2080
2081
2082 /* 
2083   lsa_RemovePrivilegesFromAccount
2084 */
2085 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2086                                                 struct lsa_RemovePrivilegesFromAccount *r)
2087 {
2088         struct lsa_RightSet *rights;
2089         struct dcesrv_handle *h;
2090         struct lsa_account_state *astate;
2091         int i;
2092
2093         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2094
2095         astate = h->data;
2096
2097         rights = talloc(mem_ctx, struct lsa_RightSet);
2098
2099         if (r->in.remove_all == 1 && 
2100             r->in.privs == NULL) {
2101                 struct lsa_EnumAccountRights r2;
2102                 NTSTATUS status;
2103
2104                 r2.in.handle = &astate->policy->handle->wire_handle;
2105                 r2.in.sid = astate->account_sid;
2106                 r2.out.rights = rights;
2107
2108                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2109                 if (!NT_STATUS_IS_OK(status)) {
2110                         return status;
2111                 }
2112
2113                 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
2114                                                   LDB_FLAG_MOD_DELETE, astate->account_sid,
2115                                                   r2.out.rights);
2116         }
2117
2118         if (r->in.remove_all != 0) {
2119                 return NT_STATUS_INVALID_PARAMETER;
2120         }
2121
2122         rights->count = r->in.privs->count;
2123         rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2124         if (rights->names == NULL) {
2125                 return NT_STATUS_NO_MEMORY;
2126         }
2127         for (i=0;i<rights->count;i++) {
2128                 int id = r->in.privs->set[i].luid.low;
2129                 if (r->in.privs->set[i].luid.high) {
2130                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2131                 }
2132                 rights->names[i].string = sec_privilege_name(id);
2133                 if (rights->names[i].string == NULL) {
2134                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2135                 }
2136         }
2137
2138         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
2139                                           LDB_FLAG_MOD_DELETE, astate->account_sid,
2140                                           rights);
2141 }
2142
2143
2144 /* 
2145   lsa_GetQuotasForAccount
2146 */
2147 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2148                        struct lsa_GetQuotasForAccount *r)
2149 {
2150         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2151 }
2152
2153
2154 /* 
2155   lsa_SetQuotasForAccount
2156 */
2157 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2158                        struct lsa_SetQuotasForAccount *r)
2159 {
2160         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2161 }
2162
2163
2164 /* 
2165   lsa_GetSystemAccessAccount
2166 */
2167 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2168                        struct lsa_GetSystemAccessAccount *r)
2169 {
2170         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2171 }
2172
2173
2174 /* 
2175   lsa_SetSystemAccessAccount
2176 */
2177 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2178                        struct lsa_SetSystemAccessAccount *r)
2179 {
2180         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2181 }
2182
2183
2184 /* 
2185   lsa_CreateSecret 
2186 */
2187 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2188                                  struct lsa_CreateSecret *r)
2189 {
2190         struct dcesrv_handle *policy_handle;
2191         struct lsa_policy_state *policy_state;
2192         struct lsa_secret_state *secret_state;
2193         struct dcesrv_handle *handle;
2194         struct ldb_message **msgs, *msg;
2195         const char *errstr;
2196         const char *attrs[] = {
2197                 NULL
2198         };
2199
2200         const char *name;
2201
2202         int ret;
2203
2204         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2205         ZERO_STRUCTP(r->out.sec_handle);
2206         
2207         policy_state = policy_handle->data;
2208
2209         if (!r->in.name.string) {
2210                 return NT_STATUS_INVALID_PARAMETER;
2211         }
2212         
2213         secret_state = talloc(mem_ctx, struct lsa_secret_state);
2214         if (!secret_state) {
2215                 return NT_STATUS_NO_MEMORY;
2216         }
2217         secret_state->policy = policy_state;
2218
2219         msg = ldb_msg_new(mem_ctx);
2220         if (msg == NULL) {
2221                 return NT_STATUS_NO_MEMORY;
2222         }
2223
2224         if (strncmp("G$", r->in.name.string, 2) == 0) {
2225                 const char *name2;
2226                 name = &r->in.name.string[2];
2227                 secret_state->sam_ldb = talloc_reference(secret_state, policy_state->sam_ldb);
2228                 secret_state->global = True;
2229
2230                 if (strlen(name) < 1) {
2231                         return NT_STATUS_INVALID_PARAMETER;
2232                 }
2233
2234                 name2 = talloc_asprintf(mem_ctx, "%s Secret", ldb_binary_encode_string(mem_ctx, name));
2235                 /* search for the secret record */
2236                 ret = gendb_search(secret_state->sam_ldb,
2237                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
2238                                    "(&(cn=%s)(objectclass=secret))", 
2239                                    name2);
2240                 if (ret > 0) {
2241                         return NT_STATUS_OBJECT_NAME_COLLISION;
2242                 }
2243                 
2244                 if (ret == -1) {
2245                         DEBUG(0,("Failure searching for CN=%s: %s\n", 
2246                                  name2, ldb_errstring(secret_state->sam_ldb)));
2247                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2248                 }
2249
2250                 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2251                 if (!name2 || ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2252                         return NT_STATUS_NO_MEMORY;
2253                 }
2254                 
2255                 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name2);
2256         
2257         } else {
2258                 secret_state->global = False;
2259
2260                 name = r->in.name.string;
2261                 if (strlen(name) < 1) {
2262                         return NT_STATUS_INVALID_PARAMETER;
2263                 }
2264
2265                 secret_state->sam_ldb = talloc_reference(secret_state, secrets_db_connect(mem_ctx));
2266                 /* search for the secret record */
2267                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2268                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2269                                    &msgs, attrs,
2270                                    "(&(cn=%s)(objectclass=secret))", 
2271                                    ldb_binary_encode_string(mem_ctx, name));
2272                 if (ret > 0) {
2273                         return NT_STATUS_OBJECT_NAME_COLLISION;
2274                 }
2275                 
2276                 if (ret == -1) {
2277                         DEBUG(0,("Failure searching for CN=%s: %s\n", 
2278                                  name, ldb_errstring(secret_state->sam_ldb)));
2279                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2280                 }
2281
2282                 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb, "cn=%s,cn=LSA Secrets", name);
2283                 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name);
2284         } 
2285
2286         /* pull in all the template attributes.  Note this is always from the global samdb */
2287         ret = samdb_copy_template(secret_state->policy->sam_ldb, msg, 
2288                                   "(&(cn=TemplateSecret)(objectclass=secretTemplate))", &errstr);
2289         if (ret != 0) {
2290                 DEBUG(0,("Failed to load TemplateSecret from samdb: %s\n",
2291                          errstr));
2292                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2293         }
2294
2295         samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "objectClass", "secret");
2296         
2297         secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
2298
2299         /* create the secret */
2300         ret = samdb_add(secret_state->sam_ldb, mem_ctx, msg);
2301         if (ret != 0) {
2302                 DEBUG(0,("Failed to create secret record %s: %s\n",
2303                          ldb_dn_get_linearized(msg->dn), 
2304                          ldb_errstring(secret_state->sam_ldb)));
2305                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2306         }
2307
2308         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2309         if (!handle) {
2310                 return NT_STATUS_NO_MEMORY;
2311         }
2312         
2313         handle->data = talloc_steal(handle, secret_state);
2314         
2315         secret_state->access_mask = r->in.access_mask;
2316         secret_state->policy = talloc_reference(secret_state, policy_state);
2317         
2318         *r->out.sec_handle = handle->wire_handle;
2319         
2320         return NT_STATUS_OK;
2321 }
2322
2323
2324 /* 
2325   lsa_OpenSecret 
2326 */
2327 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2328                                struct lsa_OpenSecret *r)
2329 {
2330         struct dcesrv_handle *policy_handle;
2331         
2332         struct lsa_policy_state *policy_state;
2333         struct lsa_secret_state *secret_state;
2334         struct dcesrv_handle *handle;
2335         struct ldb_message **msgs;
2336         const char *attrs[] = {
2337                 NULL
2338         };
2339
2340         const char *name;
2341
2342         int ret;
2343
2344         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2345         ZERO_STRUCTP(r->out.sec_handle);
2346         policy_state = policy_handle->data;
2347
2348         if (!r->in.name.string) {
2349                 return NT_STATUS_INVALID_PARAMETER;
2350         }
2351         
2352         secret_state = talloc(mem_ctx, struct lsa_secret_state);
2353         if (!secret_state) {
2354                 return NT_STATUS_NO_MEMORY;
2355         }
2356         secret_state->policy = policy_state;
2357
2358         if (strncmp("G$", r->in.name.string, 2) == 0) {
2359                 name = &r->in.name.string[2];
2360                 secret_state->sam_ldb = talloc_reference(secret_state, policy_state->sam_ldb);
2361                 secret_state->global = True;
2362
2363                 if (strlen(name) < 1) {
2364                         return NT_STATUS_INVALID_PARAMETER;
2365                 }
2366
2367                 /* search for the secret record */
2368                 ret = gendb_search(secret_state->sam_ldb,
2369                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
2370                                    "(&(cn=%s Secret)(objectclass=secret))", 
2371                                    ldb_binary_encode_string(mem_ctx, name));
2372                 if (ret == 0) {
2373                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2374                 }
2375                 
2376                 if (ret != 1) {
2377                         DEBUG(0,("Found %d records matching DN %s\n", ret,
2378                                  ldb_dn_get_linearized(policy_state->system_dn)));
2379                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2380                 }
2381         
2382         } else {
2383                 secret_state->sam_ldb = talloc_reference(secret_state, secrets_db_connect(mem_ctx));
2384
2385                 secret_state->global = False;
2386                 name = r->in.name.string;
2387                 if (strlen(name) < 1) {
2388                         return NT_STATUS_INVALID_PARAMETER;
2389                 }
2390
2391                 /* search for the secret record */
2392                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2393                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2394                                    &msgs, attrs,
2395                                    "(&(cn=%s)(objectclass=secret))", 
2396                                    ldb_binary_encode_string(mem_ctx, name));
2397                 if (ret == 0) {
2398                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2399                 }
2400                 
2401                 if (ret != 1) {
2402                         DEBUG(0,("Found %d records matching DN %s\n", ret,
2403                                  ldb_dn_get_linearized(policy_state->system_dn)));
2404                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2405                 }
2406         } 
2407
2408         secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
2409         
2410         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2411         if (!handle) {
2412                 return NT_STATUS_NO_MEMORY;
2413         }
2414         
2415         handle->data = talloc_steal(handle, secret_state);
2416         
2417         secret_state->access_mask = r->in.access_mask;
2418         secret_state->policy = talloc_reference(secret_state, policy_state);
2419         
2420         *r->out.sec_handle = handle->wire_handle;
2421         
2422         return NT_STATUS_OK;
2423 }
2424
2425
2426 /* 
2427   lsa_SetSecret 
2428 */
2429 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2430                               struct lsa_SetSecret *r)
2431 {
2432
2433         struct dcesrv_handle *h;
2434         struct lsa_secret_state *secret_state;
2435         struct ldb_message *msg;
2436         DATA_BLOB session_key;
2437         DATA_BLOB crypt_secret, secret;
2438         struct ldb_val val;
2439         int ret;
2440         NTSTATUS status = NT_STATUS_OK;
2441
2442         struct timeval now = timeval_current();
2443         NTTIME nt_now = timeval_to_nttime(&now);
2444
2445         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
2446
2447         secret_state = h->data;
2448
2449         msg = ldb_msg_new(mem_ctx);
2450         if (msg == NULL) {
2451                 return NT_STATUS_NO_MEMORY;
2452         }
2453
2454         msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
2455         if (!msg->dn) {
2456                 return NT_STATUS_NO_MEMORY;
2457         }
2458         status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
2459         if (!NT_STATUS_IS_OK(status)) {
2460                 return status;
2461         }
2462
2463         if (r->in.old_val) {
2464                 /* Decrypt */
2465                 crypt_secret.data = r->in.old_val->data;
2466                 crypt_secret.length = r->in.old_val->size;
2467                 
2468                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
2469                 if (!NT_STATUS_IS_OK(status)) {
2470                         return status;
2471                 }
2472                 
2473                 val.data = secret.data;
2474                 val.length = secret.length;
2475                 
2476                 /* set value */
2477                 if (samdb_msg_add_value(secret_state->sam_ldb, 
2478                                         mem_ctx, msg, "priorValue", &val) != 0) {
2479                         return NT_STATUS_NO_MEMORY; 
2480                 }
2481                 
2482                 /* set old value mtime */
2483                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2484                                          mem_ctx, msg, "priorSetTime", nt_now) != 0) { 
2485                         return NT_STATUS_NO_MEMORY; 
2486                 }
2487
2488                 if (!r->in.new_val) {
2489                         /* This behaviour varies depending of if this is a local, or a global secret... */
2490                         if (secret_state->global) {
2491                                 /* set old value mtime */
2492                                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2493                                                          mem_ctx, msg, "lastSetTime", nt_now) != 0) { 
2494                                         return NT_STATUS_NO_MEMORY; 
2495                                 }
2496                         } else {
2497                                 if (samdb_msg_add_delete(secret_state->sam_ldb, 
2498                                                          mem_ctx, msg, "currentValue")) {
2499                                         return NT_STATUS_NO_MEMORY;
2500                                 }
2501                                 if (samdb_msg_add_delete(secret_state->sam_ldb, 
2502                                                          mem_ctx, msg, "lastSetTime")) {
2503                                         return NT_STATUS_NO_MEMORY;
2504                                 }
2505                         }
2506                 }
2507         }
2508
2509         if (r->in.new_val) {
2510                 /* Decrypt */
2511                 crypt_secret.data = r->in.new_val->data;
2512                 crypt_secret.length = r->in.new_val->size;
2513                 
2514                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
2515                 if (!NT_STATUS_IS_OK(status)) {
2516                         return status;
2517                 }
2518                 
2519                 val.data = secret.data;
2520                 val.length = secret.length;
2521                 
2522                 /* set value */
2523                 if (samdb_msg_add_value(secret_state->sam_ldb, 
2524                                         mem_ctx, msg, "currentValue", &val) != 0) {
2525                         return NT_STATUS_NO_MEMORY; 
2526                 }
2527                 
2528                 /* set new value mtime */
2529                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2530                                          mem_ctx, msg, "lastSetTime", nt_now) != 0) { 
2531                         return NT_STATUS_NO_MEMORY; 
2532                 }
2533                 
2534                 /* If the old value is not set, then migrate the
2535                  * current value to the old value */
2536                 if (!r->in.old_val) {
2537                         const struct ldb_val *new_val;
2538                         NTTIME last_set_time;
2539                         struct ldb_message **res;
2540                         const char *attrs[] = {
2541                                 "currentValue",
2542                                 "lastSetTime",
2543                                 NULL
2544                         };
2545                         
2546                         /* search for the secret record */
2547                         ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
2548                                               secret_state->secret_dn, &res, attrs);
2549                         if (ret == 0) {
2550                                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2551                         }
2552                         
2553                         if (ret != 1) {
2554                                 DEBUG(0,("Found %d records matching dn=%s\n", ret,
2555                                          ldb_dn_get_linearized(secret_state->secret_dn)));
2556                                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2557                         }
2558
2559                         new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
2560                         last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
2561                         
2562                         if (new_val) {
2563                                 /* set value */
2564                                 if (samdb_msg_add_value(secret_state->sam_ldb, 
2565                                                         mem_ctx, msg, "priorValue", 
2566                                                         new_val) != 0) {
2567                                         return NT_STATUS_NO_MEMORY; 
2568                                 }
2569                         }
2570                         
2571                         /* set new value mtime */
2572                         if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
2573                                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2574                                                          mem_ctx, msg, "priorSetTime", last_set_time) != 0) { 
2575                                         return NT_STATUS_NO_MEMORY; 
2576                                 }
2577                         }
2578                 }
2579         }
2580
2581         /* modify the samdb record */
2582         ret = samdb_replace(secret_state->sam_ldb, mem_ctx, msg);
2583         if (ret != 0) {
2584                 /* we really need samdb.c to return NTSTATUS */
2585                 return NT_STATUS_UNSUCCESSFUL;
2586         }
2587
2588         return NT_STATUS_OK;
2589 }
2590
2591
2592 /* 
2593   lsa_QuerySecret 
2594 */
2595 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2596                                 struct lsa_QuerySecret *r)
2597 {
2598         struct dcesrv_handle *h;
2599         struct lsa_secret_state *secret_state;
2600         struct ldb_message *msg;
2601         DATA_BLOB session_key;
2602         DATA_BLOB crypt_secret, secret;
2603         int ret;
2604         struct ldb_message **res;
2605         const char *attrs[] = {
2606                 "currentValue",
2607                 "priorValue",
2608                 "lastSetTime",
2609                 "priorSetTime", 
2610                 NULL
2611         };
2612
2613         NTSTATUS nt_status;
2614
2615         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
2616
2617         secret_state = h->data;
2618
2619         /* pull all the user attributes */
2620         ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
2621                               secret_state->secret_dn, &res, attrs);
2622         if (ret != 1) {
2623                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2624         }
2625         msg = res[0];
2626         
2627         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
2628         if (!NT_STATUS_IS_OK(nt_status)) {
2629                 return nt_status;
2630         }
2631         
2632         if (r->in.old_val) {
2633                 const struct ldb_val *prior_val;
2634                 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
2635                 if (!r->out.old_val) {
2636                         return NT_STATUS_NO_MEMORY;
2637                 }
2638                 prior_val = ldb_msg_find_ldb_val(res[0], "priorValue");
2639                 
2640                 if (prior_val && prior_val->length) {
2641                         secret.data = prior_val->data;
2642                         secret.length = prior_val->length;
2643                 
2644                         /* Encrypt */
2645                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
2646                         if (!crypt_secret.length) {
2647                                 return NT_STATUS_NO_MEMORY;
2648                         }
2649                         r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
2650                         if (!r->out.old_val->buf) {
2651                                 return NT_STATUS_NO_MEMORY;
2652                         }
2653                         r->out.old_val->buf->size = crypt_secret.length;
2654                         r->out.old_val->buf->length = crypt_secret.length;
2655                         r->out.old_val->buf->data = crypt_secret.data;
2656                 }
2657         }
2658         
2659         if (r->in.old_mtime) {
2660                 r->out.old_mtime = talloc(mem_ctx, NTTIME);
2661                 if (!r->out.old_mtime) {
2662                         return NT_STATUS_NO_MEMORY;
2663                 }
2664                 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(res[0], "priorSetTime", 0);
2665         }
2666         
2667         if (r->in.new_val) {
2668                 const struct ldb_val *new_val;
2669                 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
2670                 if (!r->out.new_val) {
2671                         return NT_STATUS_NO_MEMORY;
2672                 }
2673
2674                 new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
2675                 
2676                 if (new_val && new_val->length) {
2677                         secret.data = new_val->data;
2678                         secret.length = new_val->length;
2679                 
2680                         /* Encrypt */
2681                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
2682                         if (!crypt_secret.length) {
2683                                 return NT_STATUS_NO_MEMORY;
2684                         }
2685                         r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
2686                         if (!r->out.new_val->buf) {
2687                                 return NT_STATUS_NO_MEMORY;
2688                         }
2689                         r->out.new_val->buf->length = crypt_secret.length;
2690                         r->out.new_val->buf->size = crypt_secret.length;
2691                         r->out.new_val->buf->data = crypt_secret.data;
2692                 }
2693         }
2694         
2695         if (r->in.new_mtime) {
2696                 r->out.new_mtime = talloc(mem_ctx, NTTIME);
2697                 if (!r->out.new_mtime) {
2698                         return NT_STATUS_NO_MEMORY;
2699                 }
2700                 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
2701         }
2702         
2703         return NT_STATUS_OK;
2704 }
2705
2706
2707 /* 
2708   lsa_LookupPrivValue
2709 */
2710 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call, 
2711                                     TALLOC_CTX *mem_ctx,
2712                                     struct lsa_LookupPrivValue *r)
2713 {
2714         struct dcesrv_handle *h;
2715         struct lsa_policy_state *state;
2716         int id;
2717
2718         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2719
2720         state = h->data;
2721
2722         id = sec_privilege_id(r->in.name->string);
2723         if (id == -1) {
2724                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2725         }
2726
2727         r->out.luid->low = id;
2728         r->out.luid->high = 0;
2729
2730         return NT_STATUS_OK;    
2731 }
2732
2733
2734 /* 
2735   lsa_LookupPrivName 
2736 */
2737 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call, 
2738                                    TALLOC_CTX *mem_ctx,
2739                                    struct lsa_LookupPrivName *r)
2740 {
2741         struct dcesrv_handle *h;
2742         struct lsa_policy_state *state;
2743         const char *privname;
2744
2745         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2746
2747         state = h->data;
2748
2749         if (r->in.luid->high != 0) {
2750                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2751         }
2752
2753         privname = sec_privilege_name(r->in.luid->low);
2754         if (privname == NULL) {
2755                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2756         }
2757
2758         r->out.name = talloc(mem_ctx, struct lsa_StringLarge);
2759         if (r->out.name == NULL) {
2760                 return NT_STATUS_NO_MEMORY;
2761         }
2762         r->out.name->string = privname;
2763
2764         return NT_STATUS_OK;    
2765 }
2766
2767
2768 /* 
2769   lsa_LookupPrivDisplayName
2770 */
2771 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call, 
2772                                           TALLOC_CTX *mem_ctx,
2773                                           struct lsa_LookupPrivDisplayName *r)
2774 {
2775         struct dcesrv_handle *h;
2776         struct lsa_policy_state *state;
2777         int id;
2778
2779         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2780
2781         state = h->data;
2782
2783         id = sec_privilege_id(r->in.name->string);
2784         if (id == -1) {
2785                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2786         }
2787         
2788         r->out.disp_name = talloc(mem_ctx, struct lsa_StringLarge);
2789         if (r->out.disp_name == NULL) {
2790                 return NT_STATUS_NO_MEMORY;
2791         }
2792
2793         r->out.disp_name->string = sec_privilege_display_name(id, r->in.language_id);
2794         if (r->out.disp_name->string == NULL) {
2795                 return NT_STATUS_INTERNAL_ERROR;
2796         }
2797
2798         return NT_STATUS_OK;
2799 }
2800
2801
2802 /* 
2803   lsa_DeleteObject
2804 */
2805 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2806                        struct lsa_DeleteObject *r)
2807 {
2808         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2809 }
2810
2811
2812 /* 
2813   lsa_EnumAccountsWithUserRight
2814 */
2815 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call, 
2816                                               TALLOC_CTX *mem_ctx,
2817                                               struct lsa_EnumAccountsWithUserRight *r)
2818 {
2819         struct dcesrv_handle *h;
2820         struct lsa_policy_state *state;
2821         int ret, i;
2822         struct ldb_message **res;
2823         const char * const attrs[] = { "objectSid", NULL};
2824         const char *privname;
2825
2826         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2827
2828         state = h->data;
2829
2830         if (r->in.name == NULL) {
2831                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2832         } 
2833
2834         privname = r->in.name->string;
2835         if (sec_privilege_id(privname) == -1) {
2836                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2837         }
2838
2839         ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs, 
2840                            "privilege=%s", privname);
2841         if (ret == -1) {
2842                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2843         }
2844         if (ret == 0) {
2845                 return NT_STATUS_NO_MORE_ENTRIES;
2846         }
2847
2848         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
2849         if (r->out.sids->sids == NULL) {
2850                 return NT_STATUS_NO_MEMORY;
2851         }
2852         for (i=0;i<ret;i++) {
2853                 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
2854                                                                 res[i], "objectSid");
2855                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
2856         }
2857         r->out.sids->num_sids = ret;
2858
2859         return NT_STATUS_OK;
2860 }
2861
2862
2863 /* 
2864   lsa_AddAccountRights
2865 */
2866 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call, 
2867                                      TALLOC_CTX *mem_ctx,
2868                                      struct lsa_AddAccountRights *r)
2869 {
2870         struct dcesrv_handle *h;
2871         struct lsa_policy_state *state;
2872
2873         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2874
2875         state = h->data;
2876
2877         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
2878                                           LDB_FLAG_MOD_ADD,
2879                                           r->in.sid, r->in.rights);
2880 }
2881
2882
2883 /* 
2884   lsa_RemoveAccountRights
2885 */
2886 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call, 
2887                                         TALLOC_CTX *mem_ctx,
2888                                         struct lsa_RemoveAccountRights *r)
2889 {
2890         struct dcesrv_handle *h;
2891         struct lsa_policy_state *state;
2892
2893         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2894
2895         state = h->data;
2896
2897         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
2898                                           LDB_FLAG_MOD_DELETE,
2899                                           r->in.sid, r->in.rights);
2900 }
2901
2902
2903 /* 
2904   lsa_StorePrivateData
2905 */
2906 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2907                        struct lsa_StorePrivateData *r)
2908 {
2909         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2910 }
2911
2912
2913 /* 
2914   lsa_RetrievePrivateData
2915 */
2916 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2917                        struct lsa_RetrievePrivateData *r)
2918 {
2919         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2920 }
2921
2922
2923 /* 
2924   lsa_GetUserName
2925 */
2926 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2927                                 struct lsa_GetUserName *r)
2928 {
2929         NTSTATUS status = NT_STATUS_OK;
2930         const char *account_name;
2931         const char *authority_name;
2932         struct lsa_String *_account_name;
2933         struct lsa_StringPointer *_authority_name = NULL;
2934
2935         /* this is what w2k3 does */
2936         r->out.account_name = r->in.account_name;
2937         r->out.authority_name = r->in.authority_name;
2938
2939         if (r->in.account_name && r->in.account_name->string) {
2940                 return NT_STATUS_INVALID_PARAMETER;
2941         }
2942
2943         if (r->in.authority_name &&
2944             r->in.authority_name->string &&
2945             r->in.authority_name->string->string) {
2946                 return NT_STATUS_INVALID_PARAMETER;
2947         }
2948
2949         account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->account_name);
2950         authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->domain_name);
2951
2952         _account_name = talloc(mem_ctx, struct lsa_String);
2953         NT_STATUS_HAVE_NO_MEMORY(_account_name);
2954         _account_name->string = account_name;
2955
2956         if (r->in.authority_name) {
2957                 _authority_name = talloc(mem_ctx, struct lsa_StringPointer);
2958                 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
2959                 _authority_name->string = talloc(mem_ctx, struct lsa_String);
2960                 NT_STATUS_HAVE_NO_MEMORY(_authority_name->string);
2961                 _authority_name->string->string = authority_name;
2962         }
2963
2964         r->out.account_name = _account_name;
2965         r->out.authority_name = _authority_name;
2966
2967         return status;
2968 }
2969
2970 /*
2971   lsa_SetInfoPolicy2
2972 */
2973 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
2974                                    TALLOC_CTX *mem_ctx,
2975                                    struct lsa_SetInfoPolicy2 *r)
2976 {
2977         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2978 }
2979
2980 /*
2981   lsa_QueryDomainInformationPolicy
2982 */
2983 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
2984                                                  TALLOC_CTX *mem_ctx,
2985                                                  struct lsa_QueryDomainInformationPolicy *r)
2986 {
2987         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2988 }
2989
2990 /*
2991   lsa_SetDomInfoPolicy
2992 */
2993 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
2994                                               TALLOC_CTX *mem_ctx,
2995                                               struct lsa_SetDomainInformationPolicy *r)
2996 {
2997         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2998 }
2999
3000 /*
3001   lsa_TestCall
3002 */
3003 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3004                              TALLOC_CTX *mem_ctx,
3005                              struct lsa_TestCall *r)
3006 {
3007         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3008 }
3009
3010 /*
3011   lookup a SID for 1 name
3012 */
3013 static NTSTATUS dcesrv_lsa_lookup_name(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
3014                                 const char *name, struct dom_sid **sid, uint32_t *atype)
3015 {
3016         int ret;
3017         struct ldb_message **res;
3018         const char * const attrs[] = { "objectSid", "sAMAccountType", NULL};
3019         const char *p;
3020
3021         p = strchr_m(name, '\\');
3022         if (p != NULL) {
3023                 /* TODO: properly parse the domain prefix here, and use it to 
3024                    limit the search */
3025                 name = p + 1;
3026         }
3027
3028         ret = gendb_search(state->sam_ldb, mem_ctx, NULL, &res, attrs, "sAMAccountName=%s", ldb_binary_encode_string(mem_ctx, name));
3029         if (ret == 1) {
3030                 *sid = samdb_result_dom_sid(mem_ctx, res[0], "objectSid");
3031                 if (*sid == NULL) {
3032                         return NT_STATUS_INVALID_SID;
3033                 }
3034
3035                 *atype = samdb_result_uint(res[0], "sAMAccountType", 0);
3036
3037                 return NT_STATUS_OK;
3038         }
3039
3040         /* need to add a call into sidmap to check for a allocated sid */
3041
3042         return NT_STATUS_INVALID_SID;
3043 }
3044
3045
3046 /*
3047   lsa_LookupNames3
3048 */
3049 static NTSTATUS dcesrv_lsa_LookupNames3(struct dcesrv_call_state *dce_call,
3050                                  TALLOC_CTX *mem_ctx,
3051                                  struct lsa_LookupNames3 *r)
3052 {
3053         struct lsa_policy_state *policy_state;
3054         struct dcesrv_handle *policy_handle;
3055         int i;
3056         NTSTATUS status = NT_STATUS_OK;
3057
3058         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3059
3060         policy_state = policy_handle->data;
3061
3062         r->out.domains = NULL;
3063
3064         r->out.domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
3065         if (r->out.domains == NULL) {
3066                 return NT_STATUS_NO_MEMORY;
3067         }
3068
3069         r->out.sids = talloc_zero(mem_ctx,  struct lsa_TransSidArray3);
3070         if (r->out.sids == NULL) {
3071                 return NT_STATUS_NO_MEMORY;
3072         }
3073
3074         *r->out.count = 0;
3075
3076         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid3, 
3077                                            r->in.num_names);
3078         if (r->out.sids->sids == NULL) {
3079                 return NT_STATUS_NO_MEMORY;
3080         }
3081
3082         for (i=0;i<r->in.num_names;i++) {
3083                 const char *name = r->in.names[i].string;
3084                 struct dom_sid *sid;
3085                 uint32_t atype, rtype, sid_index;
3086                 NTSTATUS status2;
3087
3088                 r->out.sids->count++;
3089                 (*r->out.count)++;
3090
3091                 r->out.sids->sids[i].sid_type    = SID_NAME_UNKNOWN;
3092                 r->out.sids->sids[i].sid         = NULL;
3093                 r->out.sids->sids[i].sid_index   = 0xFFFFFFFF;
3094                 r->out.sids->sids[i].unknown     = 0;
3095
3096                 status2 = dcesrv_lsa_lookup_name(policy_state, mem_ctx, name, &sid, &atype);
3097                 if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) {
3098                         status = STATUS_SOME_UNMAPPED;
3099                         continue;
3100                 }
3101
3102                 rtype = samdb_atype_map(atype);
3103                 if (rtype == SID_NAME_UNKNOWN) {
3104                         status = STATUS_SOME_UNMAPPED;
3105                         continue;
3106                 }
3107
3108                 status2 = dcesrv_lsa_authority_list(policy_state, mem_ctx, sid, r->out.domains, &sid_index);
3109                 if (!NT_STATUS_IS_OK(status2)) {
3110                         return status2;
3111                 }
3112
3113                 r->out.sids->sids[i].sid_type    = rtype;
3114                 r->out.sids->sids[i].sid         = sid;
3115                 r->out.sids->sids[i].sid_index   = sid_index;
3116                 r->out.sids->sids[i].unknown     = 0;
3117         }
3118         
3119         return status;
3120 }
3121
3122 /* 
3123   lsa_LookupNames4
3124
3125   Identical to LookupNames3, but doesn't take a policy handle
3126   
3127 */
3128 static NTSTATUS dcesrv_lsa_LookupNames4(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3129                                  struct lsa_LookupNames4 *r)
3130 {
3131         struct lsa_LookupNames3 r2;
3132         struct lsa_OpenPolicy2 pol;
3133         NTSTATUS status;
3134         struct dcesrv_handle *h;
3135
3136         /* No policy handle on the wire, so make one up here */
3137         r2.in.handle = talloc(mem_ctx, struct policy_handle);
3138         if (!r2.in.handle) {
3139                 return NT_STATUS_NO_MEMORY;
3140         }
3141
3142         pol.out.handle = r2.in.handle;
3143         pol.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
3144         pol.in.attr = NULL;
3145         pol.in.system_name = NULL;
3146         status = dcesrv_lsa_OpenPolicy2(dce_call, mem_ctx, &pol);
3147         if (!NT_STATUS_IS_OK(status)) {
3148                 return status;
3149         }
3150
3151         /* ensure this handle goes away at the end of this call */
3152         DCESRV_PULL_HANDLE(h, r2.in.handle, LSA_HANDLE_POLICY);
3153         talloc_steal(mem_ctx, h);
3154
3155         r2.in.num_names = r->in.num_names;
3156         r2.in.names = r->in.names;
3157         r2.in.sids = r->in.sids;
3158         r2.in.count = r->in.count;
3159         r2.in.unknown1 = r->in.unknown1;
3160         r2.in.unknown2 = r->in.unknown2;
3161         r2.out.domains = r->out.domains;
3162         r2.out.sids = r->out.sids;
3163         r2.out.count = r->out.count;
3164         
3165         status = dcesrv_lsa_LookupNames3(dce_call, mem_ctx, &r2);
3166         if (dce_call->fault_code != 0) {
3167                 return status;
3168         }
3169         
3170         r->out.domains = r2.out.domains;
3171         r->out.sids = r2.out.sids;
3172         r->out.count = r2.out.count;
3173         return status;
3174 }
3175
3176 /*
3177   lsa_LookupNames2
3178 */
3179 static NTSTATUS dcesrv_lsa_LookupNames2(struct dcesrv_call_state *dce_call,
3180                                  TALLOC_CTX *mem_ctx,
3181                                  struct lsa_LookupNames2 *r)
3182 {
3183         struct lsa_policy_state *state;
3184         struct dcesrv_handle *h;
3185         int i;
3186         NTSTATUS status = NT_STATUS_OK;
3187
3188         r->out.domains = NULL;
3189
3190         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3191
3192         state = h->data;
3193
3194         r->out.domains = talloc_zero(mem_ctx,  struct lsa_RefDomainList);
3195         if (r->out.domains == NULL) {
3196                 return NT_STATUS_NO_MEMORY;
3197         }
3198
3199         r->out.sids = talloc_zero(mem_ctx,  struct lsa_TransSidArray2);
3200         if (r->out.sids == NULL) {
3201                 return NT_STATUS_NO_MEMORY;
3202         }
3203
3204         *r->out.count = 0;
3205
3206         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid2, 
3207                                            r->in.num_names);
3208         if (r->out.sids->sids == NULL) {
3209                 return NT_STATUS_NO_MEMORY;
3210         }
3211
3212         for (i=0;i<r->in.num_names;i++) {
3213                 const char *name = r->in.names[i].string;
3214                 struct dom_sid *sid;
3215                 uint32_t atype, rtype, sid_index;
3216                 NTSTATUS status2;
3217
3218                 r->out.sids->count++;
3219                 (*r->out.count)++;
3220
3221                 r->out.sids->sids[i].sid_type    = SID_NAME_UNKNOWN;
3222                 r->out.sids->sids[i].rid         = 0xFFFFFFFF;
3223                 r->out.sids->sids[i].sid_index   = 0xFFFFFFFF;
3224                 r->out.sids->sids[i].unknown     = 0;
3225
3226                 status2 = dcesrv_lsa_lookup_name(state, mem_ctx, name, &sid, &atype);
3227                 if (!NT_STATUS_IS_OK(status2) || sid->num_auths == 0) {
3228                         status = STATUS_SOME_UNMAPPED;
3229                         continue;
3230                 }
3231
3232                 rtype = samdb_atype_map(atype);
3233                 if (rtype == SID_NAME_UNKNOWN) {
3234                         status = STATUS_SOME_UNMAPPED;
3235                         continue;
3236                 }
3237
3238                 status2 = dcesrv_lsa_authority_list(state, mem_ctx, sid, r->out.domains, &sid_index);
3239                 if (!NT_STATUS_IS_OK(status2)) {
3240                         return status2;
3241                 }
3242
3243                 r->out.sids->sids[i].sid_type    = rtype;
3244                 r->out.sids->sids[i].rid         = sid->sub_auths[sid->num_auths-1];
3245                 r->out.sids->sids[i].sid_index   = sid_index;
3246                 r->out.sids->sids[i].unknown     = 0;
3247         }
3248         
3249         return status;
3250 }
3251
3252 /* 
3253   lsa_LookupNames 
3254 */
3255 static NTSTATUS dcesrv_lsa_LookupNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3256                        struct lsa_LookupNames *r)
3257 {
3258         struct lsa_LookupNames2 r2;
3259         NTSTATUS status;
3260         int i;
3261
3262         r2.in.handle    = r->in.handle;
3263         r2.in.num_names = r->in.num_names;
3264         r2.in.names     = r->in.names;
3265         r2.in.sids      = NULL;
3266         r2.in.level     = r->in.level;
3267         r2.in.count     = r->in.count;
3268         r2.in.unknown1  = 0;
3269         r2.in.unknown2  = 0;
3270         r2.out.count    = r->out.count;
3271
3272         status = dcesrv_lsa_LookupNames2(dce_call, mem_ctx, &r2);
3273         if (dce_call->fault_code != 0) {
3274                 return status;
3275         }
3276
3277         r->out.domains = r2.out.domains;
3278         r->out.sids = talloc(mem_ctx, struct lsa_TransSidArray);
3279         if (r->out.sids == NULL) {
3280                 return NT_STATUS_NO_MEMORY;
3281         }
3282         r->out.sids->count = r2.out.sids->count;
3283         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_TranslatedSid, 
3284                                            r->out.sids->count);
3285         if (r->out.sids->sids == NULL) {
3286                 return NT_STATUS_NO_MEMORY;
3287         }
3288         for (i=0;i<r->out.sids->count;i++) {
3289                 r->out.sids->sids[i].sid_type    = r2.out.sids->sids[i].sid_type;
3290                 r->out.sids->sids[i].rid         = r2.out.sids->sids[i].rid;
3291                 r->out.sids->sids[i].sid_index   = r2.out.sids->sids[i].sid_index;
3292         }
3293
3294         return status;
3295 }
3296
3297 /* 
3298   lsa_CREDRWRITE 
3299 */
3300 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3301                        struct lsa_CREDRWRITE *r)
3302 {
3303         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3304 }
3305
3306
3307 /* 
3308   lsa_CREDRREAD 
3309 */
3310 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3311                        struct lsa_CREDRREAD *r)
3312 {
3313         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3314 }
3315
3316
3317 /* 
3318   lsa_CREDRENUMERATE 
3319 */
3320 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3321                        struct lsa_CREDRENUMERATE *r)
3322 {
3323         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3324 }
3325
3326
3327 /* 
3328   lsa_CREDRWRITEDOMAINCREDENTIALS 
3329 */
3330 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3331                        struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3332 {
3333         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3334 }
3335
3336
3337 /* 
3338   lsa_CREDRREADDOMAINCREDENTIALS 
3339 */
3340 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3341                        struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3342 {
3343         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3344 }
3345
3346
3347 /* 
3348   lsa_CREDRDELETE 
3349 */
3350 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3351                        struct lsa_CREDRDELETE *r)
3352 {
3353         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3354 }
3355
3356
3357 /* 
3358   lsa_CREDRGETTARGETINFO 
3359 */
3360 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3361                        struct lsa_CREDRGETTARGETINFO *r)
3362 {
3363         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3364 }
3365
3366
3367 /* 
3368   lsa_CREDRPROFILELOADED 
3369 */
3370 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3371                        struct lsa_CREDRPROFILELOADED *r)
3372 {
3373         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3374 }
3375
3376
3377 /* 
3378   lsa_CREDRGETSESSIONTYPES 
3379 */
3380 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3381                        struct lsa_CREDRGETSESSIONTYPES *r)
3382 {
3383         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3384 }
3385
3386
3387 /* 
3388   lsa_LSARREGISTERAUDITEVENT 
3389 */
3390 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3391                        struct lsa_LSARREGISTERAUDITEVENT *r)
3392 {
3393         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3394 }
3395
3396
3397 /* 
3398   lsa_LSARGENAUDITEVENT 
3399 */
3400 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3401                        struct lsa_LSARGENAUDITEVENT *r)
3402 {
3403         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3404 }
3405
3406
3407 /* 
3408   lsa_LSARUNREGISTERAUDITEVENT 
3409 */
3410 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3411                        struct lsa_LSARUNREGISTERAUDITEVENT *r)
3412 {
3413         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3414 }
3415
3416
3417 /* 
3418   lsa_LSARQUERYFORESTTRUSTINFORMATION 
3419 */
3420 static NTSTATUS dcesrv_lsa_LSARQUERYFORESTTRUSTINFORMATION(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3421                        struct lsa_LSARQUERYFORESTTRUSTINFORMATION *r)
3422 {
3423         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3424 }
3425
3426
3427 /* 
3428   lsa_LSARSETFORESTTRUSTINFORMATION 
3429 */
3430 static NTSTATUS dcesrv_lsa_LSARSETFORESTTRUSTINFORMATION(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3431                        struct lsa_LSARSETFORESTTRUSTINFORMATION *r)
3432 {
3433         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3434 }
3435
3436
3437 /* 
3438   lsa_CREDRRENAME 
3439 */
3440 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3441                        struct lsa_CREDRRENAME *r)
3442 {
3443         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3444 }
3445
3446
3447
3448 /* 
3449   lsa_LSAROPENPOLICYSCE 
3450 */
3451 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3452                        struct lsa_LSAROPENPOLICYSCE *r)
3453 {
3454         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3455 }
3456
3457
3458 /* 
3459   lsa_LSARADTREGISTERSECURITYEVENTSOURCE 
3460 */
3461 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3462                        struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
3463 {
3464         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3465 }
3466
3467
3468 /* 
3469   lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE 
3470 */
3471 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3472                        struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
3473 {
3474         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3475 }
3476
3477
3478 /* 
3479   lsa_LSARADTREPORTSECURITYEVENT 
3480 */
3481 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3482                        struct lsa_LSARADTREPORTSECURITYEVENT *r)
3483 {
3484         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3485 }
3486
3487
3488 /* include the generated boilerplate */
3489 #include "librpc/gen_ndr/ndr_lsa_s.c"
3490
3491
3492
3493 /*****************************************
3494 NOTE! The remaining calls below were
3495 removed in w2k3, so the DCESRV_FAULT()
3496 replies are the correct implementation. Do
3497 not try and fill these in with anything else
3498 ******************************************/
3499
3500 /* 
3501   dssetup_DsRoleDnsNameToFlatName 
3502 */
3503 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3504                                         struct dssetup_DsRoleDnsNameToFlatName *r)
3505 {
3506         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3507 }
3508
3509
3510 /* 
3511   dssetup_DsRoleDcAsDc 
3512 */
3513 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3514                              struct dssetup_DsRoleDcAsDc *r)
3515 {
3516         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3517 }
3518
3519
3520 /* 
3521   dssetup_DsRoleDcAsReplica 
3522 */
3523 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3524                                   struct dssetup_DsRoleDcAsReplica *r)
3525 {
3526         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3527 }
3528
3529
3530 /* 
3531   dssetup_DsRoleDemoteDc 
3532 */
3533 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3534                                struct dssetup_DsRoleDemoteDc *r)
3535 {
3536         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3537 }
3538
3539
3540 /* 
3541   dssetup_DsRoleGetDcOperationProgress 
3542 */
3543 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3544                                              struct dssetup_DsRoleGetDcOperationProgress *r)
3545 {
3546         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3547 }
3548
3549
3550 /* 
3551   dssetup_DsRoleGetDcOperationResults 
3552 */
3553 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3554                                             struct dssetup_DsRoleGetDcOperationResults *r)
3555 {
3556         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3557 }
3558
3559
3560 /* 
3561   dssetup_DsRoleCancel 
3562 */
3563 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3564                              struct dssetup_DsRoleCancel *r)
3565 {
3566         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3567 }
3568
3569
3570 /* 
3571   dssetup_DsRoleServerSaveStateForUpgrade 
3572 */
3573 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3574                                                 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
3575 {
3576         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3577 }
3578
3579
3580 /* 
3581   dssetup_DsRoleUpgradeDownlevelServer 
3582 */
3583 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3584                                              struct dssetup_DsRoleUpgradeDownlevelServer *r)
3585 {
3586         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3587 }
3588
3589
3590 /* 
3591   dssetup_DsRoleAbortDownlevelServerUpgrade 
3592 */
3593 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3594                                                   struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
3595 {
3596         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3597 }
3598
3599
3600 /* include the generated boilerplate */
3601 #include "librpc/gen_ndr/ndr_dssetup_s.c"
3602
3603 NTSTATUS dcerpc_server_lsa_init(void)
3604 {
3605         NTSTATUS ret;
3606         
3607         ret = dcerpc_server_dssetup_init();
3608         if (!NT_STATUS_IS_OK(ret)) {
3609                 return ret;
3610         }
3611         ret = dcerpc_server_lsarpc_init();
3612         if (!NT_STATUS_IS_OK(ret)) {
3613                 return ret;
3614         }
3615         return ret;
3616 }