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