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