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