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