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