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