s4-lsa: Fix dcesrv_lsa_EnumTrustDom() and avoid infite windows client loop.
[ira/wip.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
1 /* need access mask/acl implementation */
2
3 /* 
4    Unix SMB/CIFS implementation.
5
6    endpoint server for the lsarpc pipe
7
8    Copyright (C) Andrew Tridgell 2004
9    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
10    
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15    
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20    
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "rpc_server/lsa/lsa.h"
26 #include "system/kerberos.h"
27 #include "auth/kerberos/kerberos.h"
28 #include "librpc/gen_ndr/ndr_drsblobs.h"
29 #include "librpc/gen_ndr/ndr_lsa.h"
30 #include "../lib/crypto/crypto.h"
31
32 /*
33   this type allows us to distinguish handle types
34 */
35
36 /*
37   state associated with a lsa_OpenAccount() operation
38 */
39 struct lsa_account_state {
40         struct lsa_policy_state *policy;
41         uint32_t access_mask;
42         struct dom_sid *account_sid;
43 };
44
45
46 /*
47   state associated with a lsa_OpenSecret() operation
48 */
49 struct lsa_secret_state {
50         struct lsa_policy_state *policy;
51         uint32_t access_mask;
52         struct ldb_dn *secret_dn;
53         struct ldb_context *sam_ldb;
54         bool global;
55 };
56
57 /*
58   state associated with a lsa_OpenTrustedDomain() operation
59 */
60 struct lsa_trusted_domain_state {
61         struct lsa_policy_state *policy;
62         uint32_t access_mask;
63         struct ldb_dn *trusted_domain_dn;
64         struct ldb_dn *trusted_domain_user_dn;
65 };
66
67 /*
68   this is based on the samba3 function make_lsa_object_sd()
69   It uses the same logic, but with samba4 helper functions
70  */
71 static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx, 
72                                     struct security_descriptor **sd,
73                                     struct dom_sid *sid, 
74                                     uint32_t sid_access)
75 {
76         NTSTATUS status;
77         uint32_t rid;
78         struct dom_sid *domain_sid, *domain_admins_sid;
79         const char *domain_admins_sid_str, *sidstr;
80         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
81
82         status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
83         NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
84
85         domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
86         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid, tmp_ctx);
87
88         domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
89         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid_str, tmp_ctx);
90         
91         sidstr = dom_sid_string(tmp_ctx, sid);
92         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, tmp_ctx);
93                                                       
94         *sd = security_descriptor_dacl_create(mem_ctx,
95                                               0, sidstr, NULL,
96
97                                               SID_WORLD,
98                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
99                                               SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
100                                               
101                                               SID_BUILTIN_ADMINISTRATORS,
102                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
103                                               SEC_GENERIC_ALL, 0,
104                                               
105                                               SID_BUILTIN_ACCOUNT_OPERATORS,
106                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
107                                               SEC_GENERIC_ALL, 0,
108                                               
109                                               domain_admins_sid_str,
110                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
111                                               SEC_GENERIC_ALL, 0,
112
113                                               sidstr,
114                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
115                                               sid_access, 0,
116
117                                               NULL);
118         talloc_free(tmp_ctx);
119
120         NT_STATUS_HAVE_NO_MEMORY(*sd);
121
122         return NT_STATUS_OK;
123 }
124
125
126 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call, 
127                                       TALLOC_CTX *mem_ctx,
128                                       struct lsa_EnumAccountRights *r);
129
130 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call, 
131                                            TALLOC_CTX *mem_ctx,
132                                            struct lsa_policy_state *state,
133                                            int ldb_flag,
134                                            struct dom_sid *sid,
135                                            const struct lsa_RightSet *rights);
136
137 /* 
138   lsa_Close 
139 */
140 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
141                           struct lsa_Close *r)
142 {
143         struct dcesrv_handle *h;
144
145         *r->out.handle = *r->in.handle;
146
147         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
148
149         talloc_free(h);
150
151         ZERO_STRUCTP(r->out.handle);
152
153         return NT_STATUS_OK;
154 }
155
156
157 /* 
158   lsa_Delete 
159 */
160 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
161                            struct lsa_Delete *r)
162 {
163         return NT_STATUS_NOT_SUPPORTED;
164 }
165
166
167 /* 
168   lsa_DeleteObject
169 */
170 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
171                        struct lsa_DeleteObject *r)
172 {
173         struct dcesrv_handle *h;
174         int ret;
175
176         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
177
178         if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
179                 struct lsa_secret_state *secret_state = h->data;
180
181                 /* Ensure user is permitted to delete this... */
182                 switch (security_session_user_level(dce_call->conn->auth_state.session_info))
183                 {
184                 case SECURITY_SYSTEM:
185                 case SECURITY_ADMINISTRATOR:
186                         break;
187                 default:
188                         /* Users and annonymous are not allowed delete things */
189                         return NT_STATUS_ACCESS_DENIED;
190                 }
191
192                 ret = ldb_delete(secret_state->sam_ldb, 
193                                  secret_state->secret_dn);
194                 talloc_free(h);
195                 if (ret != 0) {
196                         return NT_STATUS_INVALID_HANDLE;
197                 }
198
199                 ZERO_STRUCTP(r->out.handle);
200
201                 return NT_STATUS_OK;
202         } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
203                 struct lsa_trusted_domain_state *trusted_domain_state = 
204                         talloc_get_type(h->data, struct lsa_trusted_domain_state);
205                 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
206                 if (ret != 0) {
207                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
208                 }
209
210                 ret = ldb_delete(trusted_domain_state->policy->sam_ldb, 
211                                  trusted_domain_state->trusted_domain_dn);
212                 if (ret != 0) {
213                         ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
214                         return NT_STATUS_INVALID_HANDLE;
215                 }
216
217                 if (trusted_domain_state->trusted_domain_user_dn) {
218                         ret = ldb_delete(trusted_domain_state->policy->sam_ldb, 
219                                          trusted_domain_state->trusted_domain_user_dn);
220                         if (ret != 0) {
221                                 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
222                                 return NT_STATUS_INVALID_HANDLE;
223                         }
224                 }
225
226                 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
227                 if (ret != 0) {
228                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
229                 }
230                 talloc_free(h);
231                 ZERO_STRUCTP(r->out.handle);
232
233                 return NT_STATUS_OK;
234         } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
235                 struct lsa_RightSet *rights;
236                 struct lsa_account_state *astate;
237                 struct lsa_EnumAccountRights r2;
238                 NTSTATUS status;
239
240                 rights = talloc(mem_ctx, struct lsa_RightSet);
241
242                 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
243                 
244                 astate = h->data;
245
246                 r2.in.handle = &astate->policy->handle->wire_handle;
247                 r2.in.sid = astate->account_sid;
248                 r2.out.rights = rights;
249
250                 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
251                    but we have a LSA_HANDLE_ACCOUNT here, so this call
252                    will always fail */
253                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
254                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
255                         return NT_STATUS_OK;
256                 }
257
258                 if (!NT_STATUS_IS_OK(status)) {
259                         return status;
260                 }
261
262                 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
263                                                     LDB_FLAG_MOD_DELETE, astate->account_sid,
264                                                     r2.out.rights);
265                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
266                         return NT_STATUS_OK;
267                 }
268
269                 if (!NT_STATUS_IS_OK(status)) {
270                         return status;
271                 }
272
273                 ZERO_STRUCTP(r->out.handle);
274         } 
275         
276         return NT_STATUS_INVALID_HANDLE;
277 }
278
279
280 /* 
281   lsa_EnumPrivs 
282 */
283 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
284                               struct lsa_EnumPrivs *r)
285 {
286         struct dcesrv_handle *h;
287         struct lsa_policy_state *state;
288         int i;
289         const char *privname;
290
291         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
292
293         state = h->data;
294
295         i = *r->in.resume_handle;
296         if (i == 0) i = 1;
297
298         while ((privname = sec_privilege_name(i)) &&
299                r->out.privs->count < r->in.max_count) {
300                 struct lsa_PrivEntry *e;
301
302                 r->out.privs->privs = talloc_realloc(r->out.privs,
303                                                        r->out.privs->privs, 
304                                                        struct lsa_PrivEntry, 
305                                                        r->out.privs->count+1);
306                 if (r->out.privs->privs == NULL) {
307                         return NT_STATUS_NO_MEMORY;
308                 }
309                 e = &r->out.privs->privs[r->out.privs->count];
310                 e->luid.low = i;
311                 e->luid.high = 0;
312                 e->name.string = privname;
313                 r->out.privs->count++;
314                 i++;
315         }
316
317         *r->out.resume_handle = i;
318
319         return NT_STATUS_OK;
320 }
321
322
323 /* 
324   lsa_QuerySecObj 
325 */
326 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
327                                          struct lsa_QuerySecurity *r)
328 {
329         struct dcesrv_handle *h;
330         struct security_descriptor *sd;
331         NTSTATUS status;
332         struct dom_sid *sid;
333
334         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
335
336         sid = dce_call->conn->auth_state.session_info->security_token->user_sid;
337
338         if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
339                 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid, 0);
340         } else  if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
341                 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid, 
342                                              LSA_ACCOUNT_ALL_ACCESS);
343         } else {
344                 return NT_STATUS_INVALID_HANDLE;
345         }
346         NT_STATUS_NOT_OK_RETURN(status);
347
348         (*r->out.sdbuf) = talloc(mem_ctx, struct sec_desc_buf);
349         NT_STATUS_HAVE_NO_MEMORY(*r->out.sdbuf);
350
351         (*r->out.sdbuf)->sd = sd;
352         
353         return NT_STATUS_OK;
354 }
355
356
357 /* 
358   lsa_SetSecObj 
359 */
360 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
361                               struct lsa_SetSecObj *r)
362 {
363         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
364 }
365
366
367 /* 
368   lsa_ChangePassword 
369 */
370 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
371                                    struct lsa_ChangePassword *r)
372 {
373         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
374 }
375
376 /* 
377   dssetup_DsRoleGetPrimaryDomainInformation 
378
379   This is not an LSA call, but is the only call left on the DSSETUP
380   pipe (after the pipe was truncated), and needs lsa_get_policy_state
381 */
382 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call, 
383                                                  TALLOC_CTX *mem_ctx,
384                                                  struct dssetup_DsRoleGetPrimaryDomainInformation *r)
385 {
386         union dssetup_DsRoleInfo *info;
387
388         info = talloc(mem_ctx, union dssetup_DsRoleInfo);
389         W_ERROR_HAVE_NO_MEMORY(info);
390
391         switch (r->in.level) {
392         case DS_ROLE_BASIC_INFORMATION:
393         {
394                 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
395                 uint32_t flags = 0;
396                 const char *domain = NULL;
397                 const char *dns_domain = NULL;
398                 const char *forest = NULL;
399                 struct GUID domain_guid;
400                 struct lsa_policy_state *state;
401
402                 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
403                 if (!NT_STATUS_IS_OK(status)) {
404                         return ntstatus_to_werror(status);
405                 }
406
407                 ZERO_STRUCT(domain_guid);
408
409                 switch (lp_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
410                 case ROLE_STANDALONE:
411                         role            = DS_ROLE_STANDALONE_SERVER;
412                         break;
413                 case ROLE_DOMAIN_MEMBER:
414                         role            = DS_ROLE_MEMBER_SERVER;
415                         break;
416                 case ROLE_DOMAIN_CONTROLLER:
417                         if (samdb_is_pdc(state->sam_ldb)) {
418                                 role    = DS_ROLE_PRIMARY_DC;
419                         } else {
420                                 role    = DS_ROLE_BACKUP_DC;
421                         }
422                         break;
423                 }
424
425                 switch (lp_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
426                 case ROLE_STANDALONE:
427                         domain          = talloc_strdup(mem_ctx, lp_workgroup(dce_call->conn->dce_ctx->lp_ctx));
428                         W_ERROR_HAVE_NO_MEMORY(domain);
429                         break;
430                 case ROLE_DOMAIN_MEMBER:
431                         domain          = talloc_strdup(mem_ctx, lp_workgroup(dce_call->conn->dce_ctx->lp_ctx));
432                         W_ERROR_HAVE_NO_MEMORY(domain);
433                         /* TODO: what is with dns_domain and forest and guid? */
434                         break;
435                 case ROLE_DOMAIN_CONTROLLER:
436                         flags           = DS_ROLE_PRIMARY_DS_RUNNING;
437
438                         if (state->mixed_domain == 1) {
439                                 flags   |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
440                         }
441                         
442                         domain          = state->domain_name;
443                         dns_domain      = state->domain_dns;
444                         forest          = state->forest_dns;
445
446                         domain_guid     = state->domain_guid;
447                         flags   |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
448                         break;
449                 }
450
451                 info->basic.role        = role; 
452                 info->basic.flags       = flags;
453                 info->basic.domain      = domain;
454                 info->basic.dns_domain  = dns_domain;
455                 info->basic.forest      = forest;
456                 info->basic.domain_guid = domain_guid;
457
458                 r->out.info = info;
459                 return WERR_OK;
460         }
461         case DS_ROLE_UPGRADE_STATUS:
462         {
463                 info->upgrade.upgrading     = DS_ROLE_NOT_UPGRADING;
464                 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
465
466                 r->out.info = info;
467                 return WERR_OK;
468         }
469         case DS_ROLE_OP_STATUS:
470         {
471                 info->opstatus.status = DS_ROLE_OP_IDLE;
472
473                 r->out.info = info;
474                 return WERR_OK;
475         }
476         default:
477                 return WERR_INVALID_PARAM;
478         }
479
480         return WERR_INVALID_PARAM;
481 }
482
483 /*
484   fill in the AccountDomain info
485 */
486 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
487                                        struct lsa_DomainInfo *info)
488 {
489         info->name.string = state->domain_name;
490         info->sid         = state->domain_sid;
491
492         return NT_STATUS_OK;
493 }
494
495 /*
496   fill in the DNS domain info
497 */
498 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
499                              struct lsa_DnsDomainInfo *info)
500 {
501         info->name.string = state->domain_name;
502         info->sid         = state->domain_sid;
503         info->dns_domain.string = state->domain_dns;
504         info->dns_forest.string = state->forest_dns;
505         info->domain_guid       = state->domain_guid;
506
507         return NT_STATUS_OK;
508 }
509
510 /* 
511   lsa_QueryInfoPolicy2
512 */
513 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
514                                      struct lsa_QueryInfoPolicy2 *r)
515 {
516         struct lsa_policy_state *state;
517         struct dcesrv_handle *h;
518         union lsa_PolicyInformation *info;
519
520         *r->out.info = NULL;
521
522         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
523
524         state = h->data;
525
526         info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
527         if (!info) {
528                 return NT_STATUS_NO_MEMORY;
529         }
530         *r->out.info = info;
531
532         switch (r->in.level) {
533         case LSA_POLICY_INFO_AUDIT_LOG:
534                 /* we don't need to fill in any of this */
535                 ZERO_STRUCT(info->audit_log);
536                 return NT_STATUS_OK;
537         case LSA_POLICY_INFO_AUDIT_EVENTS:
538                 /* we don't need to fill in any of this */
539                 ZERO_STRUCT(info->audit_events);
540                 return NT_STATUS_OK;
541         case LSA_POLICY_INFO_PD:
542                 /* we don't need to fill in any of this */
543                 ZERO_STRUCT(info->pd);
544                 return NT_STATUS_OK;
545
546         case LSA_POLICY_INFO_DOMAIN:
547                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
548         case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
549                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
550         case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
551                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
552
553
554         case LSA_POLICY_INFO_ROLE:
555                 info->role.role = LSA_ROLE_PRIMARY;
556                 return NT_STATUS_OK;
557
558         case LSA_POLICY_INFO_DNS:
559         case LSA_POLICY_INFO_DNS_INT:
560                 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
561
562         case LSA_POLICY_INFO_REPLICA:
563                 ZERO_STRUCT(info->replica);
564                 return NT_STATUS_OK;
565
566         case LSA_POLICY_INFO_QUOTA:
567                 ZERO_STRUCT(info->quota);
568                 return NT_STATUS_OK;
569
570         case LSA_POLICY_INFO_MOD:
571         case LSA_POLICY_INFO_AUDIT_FULL_SET:
572         case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
573                 /* windows gives INVALID_PARAMETER */
574                 *r->out.info = NULL;
575                 return NT_STATUS_INVALID_PARAMETER;
576         }
577
578         *r->out.info = NULL;
579         return NT_STATUS_INVALID_INFO_CLASS;
580 }
581
582 /* 
583   lsa_QueryInfoPolicy 
584 */
585 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
586                                     struct lsa_QueryInfoPolicy *r)
587 {
588         struct lsa_QueryInfoPolicy2 r2;
589         NTSTATUS status;
590
591         ZERO_STRUCT(r2);
592
593         r2.in.handle = r->in.handle;
594         r2.in.level = r->in.level;
595         r2.out.info = r->out.info;
596         
597         status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
598
599         return status;
600 }
601
602 /* 
603   lsa_SetInfoPolicy 
604 */
605 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
606                                   struct lsa_SetInfoPolicy *r)
607 {
608         /* need to support this */
609         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
610 }
611
612
613 /* 
614   lsa_ClearAuditLog 
615 */
616 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
617                                   struct lsa_ClearAuditLog *r)
618 {
619         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
620 }
621
622
623 /* 
624   lsa_CreateAccount 
625
626   This call does not seem to have any long-term effects, hence no database operations
627
628   we need to talk to the MS product group to find out what this account database means!
629
630   answer is that the lsa database is totally separate from the SAM and
631   ldap databases. We are going to need a separate ldb to store these
632   accounts. The SIDs on this account bear no relation to the SIDs in
633   AD
634 */
635 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
636                                   struct lsa_CreateAccount *r)
637 {
638         struct lsa_account_state *astate;
639
640         struct lsa_policy_state *state;
641         struct dcesrv_handle *h, *ah;
642
643         ZERO_STRUCTP(r->out.acct_handle);
644
645         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
646
647         state = h->data;
648
649         astate = talloc(dce_call->conn, struct lsa_account_state);
650         if (astate == NULL) {
651                 return NT_STATUS_NO_MEMORY;
652         }
653
654         astate->account_sid = dom_sid_dup(astate, r->in.sid);
655         if (astate->account_sid == NULL) {
656                 talloc_free(astate);
657                 return NT_STATUS_NO_MEMORY;
658         }
659         
660         astate->policy = talloc_reference(astate, state);
661         astate->access_mask = r->in.access_mask;
662
663         ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
664         if (!ah) {
665                 talloc_free(astate);
666                 return NT_STATUS_NO_MEMORY;
667         }
668
669         ah->data = talloc_steal(ah, astate);
670
671         *r->out.acct_handle = ah->wire_handle;
672
673         return NT_STATUS_OK;
674 }
675
676
677 /* 
678   lsa_EnumAccounts 
679 */
680 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
681                                  struct lsa_EnumAccounts *r)
682 {
683         struct dcesrv_handle *h;
684         struct lsa_policy_state *state;
685         int ret, i;
686         struct ldb_message **res;
687         const char * const attrs[] = { "objectSid", NULL};
688         uint32_t count;
689
690         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
691
692         state = h->data;
693
694         /* NOTE: This call must only return accounts that have at least
695            one privilege set 
696         */
697         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs, 
698                            "(&(objectSid=*)(privilege=*))");
699         if (ret < 0) {
700                 return NT_STATUS_NO_SUCH_USER;
701         }
702
703         if (*r->in.resume_handle >= ret) {
704                 return NT_STATUS_NO_MORE_ENTRIES;
705         }
706
707         count = ret - *r->in.resume_handle;
708         if (count > r->in.num_entries) {
709                 count = r->in.num_entries;
710         }
711
712         if (count == 0) {
713                 return NT_STATUS_NO_MORE_ENTRIES;
714         }
715
716         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
717         if (r->out.sids->sids == NULL) {
718                 return NT_STATUS_NO_MEMORY;
719         }
720
721         for (i=0;i<count;i++) {
722                 r->out.sids->sids[i].sid = 
723                         samdb_result_dom_sid(r->out.sids->sids, 
724                                              res[i + *r->in.resume_handle],
725                                              "objectSid");
726                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
727         }
728
729         r->out.sids->num_sids = count;
730         *r->out.resume_handle = count + *r->in.resume_handle;
731
732         return NT_STATUS_OK;
733         
734 }
735
736
737 /*
738   lsa_CreateTrustedDomainEx2
739 */
740 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
741                                                     TALLOC_CTX *mem_ctx,
742                                                     struct lsa_CreateTrustedDomainEx2 *r,
743                                                     int op)
744 {
745         struct dcesrv_handle *policy_handle;
746         struct lsa_policy_state *policy_state;
747         struct lsa_trusted_domain_state *trusted_domain_state;
748         struct dcesrv_handle *handle;
749         struct ldb_message **msgs, *msg, *msg_user;
750         const char *attrs[] = {
751                 NULL
752         };
753         const char *netbios_name;
754         const char *dns_name;
755         const char *name;
756         DATA_BLOB session_key = data_blob(NULL, 0);
757         DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
758         struct trustDomainPasswords auth_struct;
759         int ret;
760         NTSTATUS nt_status;
761         enum ndr_err_code ndr_err;
762         
763         DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
764         ZERO_STRUCTP(r->out.trustdom_handle);
765         
766         policy_state = policy_handle->data;
767
768         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
769         if (!NT_STATUS_IS_OK(nt_status)) {
770                 return nt_status;
771         }
772
773         netbios_name = r->in.info->netbios_name.string;
774         if (!netbios_name) {
775                 return NT_STATUS_INVALID_PARAMETER;
776         }
777         
778         dns_name = r->in.info->domain_name.string;
779         
780         trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
781         if (!trusted_domain_state) {
782                 return NT_STATUS_NO_MEMORY;
783         }
784         trusted_domain_state->policy = policy_state;
785
786         if (strcasecmp(netbios_name, "BUILTIN") == 0
787             || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0) 
788             || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
789                 return NT_STATUS_INVALID_PARAMETER;;
790         }
791
792         if (strcasecmp(netbios_name, policy_state->domain_name) == 0
793             || strcasecmp(netbios_name, policy_state->domain_dns) == 0
794             || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0) 
795             || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0)
796             || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
797                 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
798         }
799
800         /* While this is a REF pointer, some of the functions that wrap this don't provide this */
801         if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
802                 /* No secrets are created at this time, for this function */
803                 auth_struct.outgoing.count = 0;
804                 auth_struct.incoming.count = 0;
805         } else {
806                 auth_blob = data_blob_const(r->in.auth_info->auth_blob.data, r->in.auth_info->auth_blob.size);
807                 arcfour_crypt_blob(auth_blob.data, auth_blob.length, &session_key);
808                 ndr_err = ndr_pull_struct_blob(&auth_blob, mem_ctx, 
809                                                lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
810                                                &auth_struct,
811                                                (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
812                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
813                         return NT_STATUS_INVALID_PARAMETER;
814                 }                               
815
816                 if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
817                         if (auth_struct.incoming.count > 1) {
818                                 return NT_STATUS_INVALID_PARAMETER;
819                         }
820                 }
821         }
822
823         if (auth_struct.incoming.count) {
824                 int i;
825                 struct trustAuthInOutBlob incoming;
826                 
827                 incoming.count = auth_struct.incoming.count;
828                 incoming.current = talloc(mem_ctx, struct AuthenticationInformationArray);
829                 if (!incoming.current) {
830                         return NT_STATUS_NO_MEMORY;
831                 }
832                 
833                 incoming.current->array = *auth_struct.incoming.current;
834                 if (!incoming.current->array) {
835                         return NT_STATUS_NO_MEMORY;
836                 }
837
838                 incoming.previous = talloc(mem_ctx, struct AuthenticationInformationArray);
839                 if (!incoming.previous) {
840                         return NT_STATUS_NO_MEMORY;
841                 }
842                 incoming.previous->array = talloc_array(mem_ctx, struct AuthenticationInformation, incoming.count);
843                 if (!incoming.previous->array) {
844                         return NT_STATUS_NO_MEMORY;
845                 }
846
847                 for (i = 0; i < incoming.count; i++) {
848                         incoming.previous->array[i].LastUpdateTime = 0;
849                         incoming.previous->array[i].AuthType = 0;
850                 }
851                 ndr_err = ndr_push_struct_blob(&trustAuthIncoming, mem_ctx, 
852                                                lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
853                                                &incoming,
854                                                (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
855                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
856                         return NT_STATUS_INVALID_PARAMETER;
857                 }
858         } else {
859                 trustAuthIncoming = data_blob(NULL, 0);
860         }
861         
862         if (auth_struct.outgoing.count) {
863                 int i;
864                 struct trustAuthInOutBlob outgoing;
865                 
866                 outgoing.count = auth_struct.outgoing.count;
867                 outgoing.current = talloc(mem_ctx, struct AuthenticationInformationArray);
868                 if (!outgoing.current) {
869                         return NT_STATUS_NO_MEMORY;
870                 }
871                 
872                 outgoing.current->array = *auth_struct.outgoing.current;
873                 if (!outgoing.current->array) {
874                         return NT_STATUS_NO_MEMORY;
875                 }
876
877                 outgoing.previous = talloc(mem_ctx, struct AuthenticationInformationArray);
878                 if (!outgoing.previous) {
879                         return NT_STATUS_NO_MEMORY;
880                 }
881                 outgoing.previous->array = talloc_array(mem_ctx, struct AuthenticationInformation, outgoing.count);
882                 if (!outgoing.previous->array) {
883                         return NT_STATUS_NO_MEMORY;
884                 }
885
886                 for (i = 0; i < outgoing.count; i++) {
887                         outgoing.previous->array[i].LastUpdateTime = 0;
888                         outgoing.previous->array[i].AuthType = 0;
889                 }
890                 ndr_err = ndr_push_struct_blob(&trustAuthOutgoing, mem_ctx, 
891                                                lp_iconv_convenience(dce_call->conn->dce_ctx->lp_ctx),
892                                                &outgoing,
893                                                (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
894                 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
895                         return NT_STATUS_INVALID_PARAMETER;
896                 }
897         } else {
898                 trustAuthOutgoing = data_blob(NULL, 0);
899         }
900
901         ret = ldb_transaction_start(policy_state->sam_ldb);
902         if (ret != LDB_SUCCESS) {
903                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
904         }
905
906         if (dns_name) {
907                 char *dns_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
908                 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
909                 /* search for the trusted_domain record */
910                 ret = gendb_search(policy_state->sam_ldb,
911                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
912                                    "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))", 
913                                    dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded);
914                 if (ret > 0) {
915                         ldb_transaction_cancel(policy_state->sam_ldb);
916                         return NT_STATUS_OBJECT_NAME_COLLISION;
917                 }
918         } else {
919                 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
920                 /* search for the trusted_domain record */
921                 ret = gendb_search(policy_state->sam_ldb,
922                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
923                                    "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))", 
924                                    netbios_encoded, netbios_encoded, netbios_encoded);
925                 if (ret > 0) {
926                         ldb_transaction_cancel(policy_state->sam_ldb);
927                         return NT_STATUS_OBJECT_NAME_COLLISION;
928                 }
929         }
930         
931         if (ret < 0 ) {
932                 ldb_transaction_cancel(policy_state->sam_ldb);
933                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
934         }
935         
936         name = dns_name ? dns_name : netbios_name;
937
938         msg = ldb_msg_new(mem_ctx);
939         if (msg == NULL) {
940                 return NT_STATUS_NO_MEMORY;
941         }
942
943         msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
944         if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
945                         ldb_transaction_cancel(policy_state->sam_ldb);
946                 return NT_STATUS_NO_MEMORY;
947         }
948         
949         samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "flatname", netbios_name);
950
951         if (r->in.info->sid) {
952                 const char *sid_string = dom_sid_string(mem_ctx, r->in.info->sid);
953                 if (!sid_string) {
954                         ldb_transaction_cancel(policy_state->sam_ldb);
955                         return NT_STATUS_NO_MEMORY;
956                 }
957                         
958                 samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "securityIdentifier", sid_string);
959         }
960
961         samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "objectClass", "trustedDomain");
962
963         samdb_msg_add_int(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
964
965         samdb_msg_add_int(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
966
967         samdb_msg_add_int(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
968         
969         if (dns_name) {
970                 samdb_msg_add_string(trusted_domain_state->policy->sam_ldb, mem_ctx, msg, "trustPartner", dns_name);
971         }
972
973         if (trustAuthIncoming.data) {
974                 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
975                 if (ret != LDB_SUCCESS) {
976                         ldb_transaction_cancel(policy_state->sam_ldb);
977                         return NT_STATUS_NO_MEMORY;
978                 }
979         }
980         if (trustAuthOutgoing.data) {
981                 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
982                 if (ret != LDB_SUCCESS) {
983                         ldb_transaction_cancel(policy_state->sam_ldb);
984                         return NT_STATUS_NO_MEMORY;
985                 }
986         }
987
988         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
989
990         /* create the trusted_domain */
991         ret = ldb_add(trusted_domain_state->policy->sam_ldb, msg);
992         switch (ret) {
993         case  LDB_SUCCESS:
994                 break;
995         case  LDB_ERR_ENTRY_ALREADY_EXISTS:
996                 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
997                 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
998                          ldb_dn_get_linearized(msg->dn),
999                          ldb_errstring(trusted_domain_state->policy->sam_ldb)));
1000                 return NT_STATUS_DOMAIN_EXISTS;
1001         case  LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1002                 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
1003                 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1004                          ldb_dn_get_linearized(msg->dn),
1005                          ldb_errstring(trusted_domain_state->policy->sam_ldb)));
1006                 return NT_STATUS_ACCESS_DENIED;
1007         default:
1008                 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
1009                 DEBUG(0,("Failed to create user record %s: %s\n",
1010                          ldb_dn_get_linearized(msg->dn),
1011                          ldb_errstring(trusted_domain_state->policy->sam_ldb)));
1012                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1013         }
1014
1015         if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1016                 msg_user = ldb_msg_new(mem_ctx);
1017                 if (msg_user == NULL) {
1018                         ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
1019                         return NT_STATUS_NO_MEMORY;
1020                 }
1021
1022                 /* Inbound trusts must also create a cn=users object to match */
1023
1024                 trusted_domain_state->trusted_domain_user_dn = msg_user->dn
1025                         = ldb_dn_copy(trusted_domain_state, policy_state->domain_dn);
1026                 if ( ! ldb_dn_add_child_fmt(msg_user->dn, "cn=users")) {
1027                         ldb_transaction_cancel(policy_state->sam_ldb);
1028                         return NT_STATUS_NO_MEMORY;
1029                 }
1030         
1031                 if ( ! ldb_dn_add_child_fmt(msg_user->dn, "cn=%s", netbios_name)) {
1032                         ldb_transaction_cancel(policy_state->sam_ldb);
1033                         return NT_STATUS_NO_MEMORY;
1034                 }
1035
1036                 ldb_msg_add_string(msg_user, "objectClass", "user");
1037
1038                 ldb_msg_add_steal_string(msg_user, "samAccountName", 
1039                                          talloc_asprintf(mem_ctx, "%s$", netbios_name));
1040
1041                 if (samdb_msg_add_uint(trusted_domain_state->policy->sam_ldb, mem_ctx, msg_user, 
1042                                        "userAccountControl", 
1043                                        UF_INTERDOMAIN_TRUST_ACCOUNT) != 0) { 
1044                         ldb_transaction_cancel(policy_state->sam_ldb);
1045                         return NT_STATUS_NO_MEMORY; 
1046                 }
1047
1048                 if (auth_struct.incoming.count) {
1049                         int i;
1050                         for (i=0; i < auth_struct.incoming.count; i++ ) {
1051                                 if (auth_struct.incoming.current[i]->AuthType == TRUST_AUTH_TYPE_NT4OWF) {
1052                                         samdb_msg_add_hash(trusted_domain_state->policy->sam_ldb, 
1053                                                            mem_ctx, msg_user, "unicodePwd", 
1054                                                            &auth_struct.incoming.current[i]->AuthInfo.nt4owf.password);
1055                                 } else if (auth_struct.incoming.current[i]->AuthType == TRUST_AUTH_TYPE_CLEAR) {
1056                                         DATA_BLOB new_password = data_blob_const(auth_struct.incoming.current[i]->AuthInfo.clear.password,
1057                                                                                  auth_struct.incoming.current[i]->AuthInfo.clear.size);
1058                                         ret = ldb_msg_add_value(msg_user, "clearTextPassword", &new_password, NULL);
1059                                         if (ret != LDB_SUCCESS) {
1060                                                 ldb_transaction_cancel(policy_state->sam_ldb);
1061                                                 return NT_STATUS_NO_MEMORY;
1062                                         }
1063                                 } 
1064                         }
1065                 }
1066
1067                 /* create the cn=users trusted_domain account */
1068                 ret = ldb_add(trusted_domain_state->policy->sam_ldb, msg_user);
1069                 switch (ret) {
1070                 case  LDB_SUCCESS:
1071                         break;
1072                 case  LDB_ERR_ENTRY_ALREADY_EXISTS:
1073                         ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
1074                         DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1075                                  ldb_dn_get_linearized(msg_user->dn),
1076                                  ldb_errstring(trusted_domain_state->policy->sam_ldb)));
1077                         return NT_STATUS_DOMAIN_EXISTS;
1078                 case  LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1079                         ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
1080                         DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1081                                  ldb_dn_get_linearized(msg_user->dn),
1082                                  ldb_errstring(trusted_domain_state->policy->sam_ldb)));
1083                         return NT_STATUS_ACCESS_DENIED;
1084                 default:
1085                         ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
1086                         DEBUG(0,("Failed to create user record %s: %s\n",
1087                                  ldb_dn_get_linearized(msg_user->dn),
1088                                  ldb_errstring(trusted_domain_state->policy->sam_ldb)));
1089                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1090                 }
1091         }
1092
1093         ret = ldb_transaction_commit(policy_state->sam_ldb);
1094         if (ret != LDB_SUCCESS) {
1095                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1096         }
1097
1098         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1099         if (!handle) {
1100                 return NT_STATUS_NO_MEMORY;
1101         }
1102         
1103         handle->data = talloc_steal(handle, trusted_domain_state);
1104         
1105         trusted_domain_state->access_mask = r->in.access_mask;
1106         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1107         
1108         *r->out.trustdom_handle = handle->wire_handle;
1109         
1110         return NT_STATUS_OK;
1111 }
1112
1113 /*
1114   lsa_CreateTrustedDomainEx2
1115 */
1116 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1117                                            TALLOC_CTX *mem_ctx,
1118                                            struct lsa_CreateTrustedDomainEx2 *r)
1119 {
1120         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2);
1121 }
1122 /*
1123   lsa_CreateTrustedDomainEx
1124 */
1125 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1126                                           TALLOC_CTX *mem_ctx,
1127                                           struct lsa_CreateTrustedDomainEx *r)
1128 {
1129         struct lsa_CreateTrustedDomainEx2 r2;
1130
1131         r2.in.policy_handle = r->in.policy_handle;
1132         r2.in.info = r->in.info;
1133         r2.in.auth_info = r->in.auth_info;
1134         r2.out.trustdom_handle = r->out.trustdom_handle;
1135         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX);
1136 }
1137
1138 /* 
1139   lsa_CreateTrustedDomain 
1140 */
1141 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1142                                         struct lsa_CreateTrustedDomain *r)
1143 {
1144         struct lsa_CreateTrustedDomainEx2 r2;
1145
1146         r2.in.policy_handle = r->in.policy_handle;
1147         r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1148         if (!r2.in.info) {
1149                 return NT_STATUS_NO_MEMORY;
1150         }
1151
1152         r2.in.info->domain_name.string = NULL;
1153         r2.in.info->netbios_name = r->in.info->name;
1154         r2.in.info->sid = r->in.info->sid;
1155         r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1156         r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1157         r2.in.info->trust_attributes = 0;
1158         
1159         r2.in.access_mask = r->in.access_mask;
1160         r2.out.trustdom_handle = r->out.trustdom_handle;
1161
1162         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN);
1163                          
1164 }
1165
1166 /* 
1167   lsa_OpenTrustedDomain
1168 */
1169 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1170                                       struct lsa_OpenTrustedDomain *r)
1171 {
1172         struct dcesrv_handle *policy_handle;
1173         
1174         struct lsa_policy_state *policy_state;
1175         struct lsa_trusted_domain_state *trusted_domain_state;
1176         struct dcesrv_handle *handle;
1177         struct ldb_message **msgs;
1178         const char *attrs[] = {
1179                 "trustDirection",
1180                 "flatname",
1181                 NULL
1182         };
1183
1184         const char *sid_string;
1185         int ret;
1186
1187         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1188         ZERO_STRUCTP(r->out.trustdom_handle);
1189         policy_state = policy_handle->data;
1190
1191         trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1192         if (!trusted_domain_state) {
1193                 return NT_STATUS_NO_MEMORY;
1194         }
1195         trusted_domain_state->policy = policy_state;
1196
1197         sid_string = dom_sid_string(mem_ctx, r->in.sid);
1198         if (!sid_string) {
1199                 return NT_STATUS_NO_MEMORY;
1200         }
1201
1202         /* search for the trusted_domain record */
1203         ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1204                            mem_ctx, policy_state->system_dn, &msgs, attrs,
1205                            "(&(securityIdentifier=%s)(objectclass=trustedDomain))", 
1206                            sid_string);
1207         if (ret == 0) {
1208                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1209         }
1210         
1211         if (ret != 1) {
1212                 DEBUG(0,("Found %d records matching DN %s\n", ret,
1213                          ldb_dn_get_linearized(policy_state->system_dn)));
1214                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1215         }
1216
1217         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1218
1219         trusted_domain_state->trusted_domain_user_dn = NULL;
1220
1221         if (ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0) & LSA_TRUST_DIRECTION_INBOUND) {
1222                 const char *flatname = ldb_binary_encode_string(mem_ctx, ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL));
1223                 /* search for the trusted_domain record */
1224                 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1225                                    mem_ctx, policy_state->domain_dn, &msgs, attrs,
1226                                    "(&(samaccountname=%s$)(objectclass=user)(userAccountControl:1.2.840.113556.1.4.803:=%d))", 
1227                                    flatname, UF_INTERDOMAIN_TRUST_ACCOUNT);
1228                 if (ret == 1) {
1229                         trusted_domain_state->trusted_domain_user_dn = talloc_steal(trusted_domain_state, msgs[0]->dn);
1230                 }
1231         }
1232         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1233         if (!handle) {
1234                 return NT_STATUS_NO_MEMORY;
1235         }
1236         
1237         handle->data = talloc_steal(handle, trusted_domain_state);
1238         
1239         trusted_domain_state->access_mask = r->in.access_mask;
1240         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1241         
1242         *r->out.trustdom_handle = handle->wire_handle;
1243         
1244         return NT_STATUS_OK;
1245 }
1246
1247
1248 /*
1249   lsa_OpenTrustedDomainByName
1250 */
1251 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1252                                             TALLOC_CTX *mem_ctx,
1253                                             struct lsa_OpenTrustedDomainByName *r)
1254 {
1255         struct dcesrv_handle *policy_handle;
1256         
1257         struct lsa_policy_state *policy_state;
1258         struct lsa_trusted_domain_state *trusted_domain_state;
1259         struct dcesrv_handle *handle;
1260         struct ldb_message **msgs;
1261         const char *attrs[] = {
1262                 NULL
1263         };
1264
1265         int ret;
1266
1267         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1268         ZERO_STRUCTP(r->out.trustdom_handle);
1269         policy_state = policy_handle->data;
1270
1271         if (!r->in.name.string) {
1272                 return NT_STATUS_INVALID_PARAMETER;
1273         }
1274         
1275         trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1276         if (!trusted_domain_state) {
1277                 return NT_STATUS_NO_MEMORY;
1278         }
1279         trusted_domain_state->policy = policy_state;
1280
1281         /* search for the trusted_domain record */
1282         ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1283                            mem_ctx, policy_state->system_dn, &msgs, attrs,
1284                            "(&(flatname=%s)(objectclass=trustedDomain))", 
1285                            ldb_binary_encode_string(mem_ctx, r->in.name.string));
1286         if (ret == 0) {
1287                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1288         }
1289         
1290         if (ret != 1) {
1291                 DEBUG(0,("Found %d records matching DN %s\n", ret,
1292                          ldb_dn_get_linearized(policy_state->system_dn)));
1293                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1294         }
1295
1296         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1297         
1298         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1299         if (!handle) {
1300                 return NT_STATUS_NO_MEMORY;
1301         }
1302         
1303         handle->data = talloc_steal(handle, trusted_domain_state);
1304         
1305         trusted_domain_state->access_mask = r->in.access_mask;
1306         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1307         
1308         *r->out.trustdom_handle = handle->wire_handle;
1309         
1310         return NT_STATUS_OK;
1311 }
1312
1313
1314
1315 /* 
1316   lsa_SetTrustedDomainInfo
1317 */
1318 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1319                                          struct lsa_SetTrustedDomainInfo *r)
1320 {
1321         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1322 }
1323
1324
1325
1326 /* 
1327   lsa_SetInfomrationTrustedDomain
1328 */
1329 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(struct dcesrv_call_state *dce_call, 
1330                                                 TALLOC_CTX *mem_ctx,
1331                                                 struct lsa_SetInformationTrustedDomain *r)
1332 {
1333         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1334 }
1335
1336
1337 /* 
1338   lsa_DeleteTrustedDomain
1339 */
1340 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1341                                       struct lsa_DeleteTrustedDomain *r)
1342 {
1343         NTSTATUS status;
1344         struct lsa_OpenTrustedDomain opn;
1345         struct lsa_DeleteObject del;
1346         struct dcesrv_handle *h;
1347
1348         opn.in.handle = r->in.handle;
1349         opn.in.sid = r->in.dom_sid;
1350         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1351         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1352         if (!opn.out.trustdom_handle) {
1353                 return NT_STATUS_NO_MEMORY;
1354         }
1355         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1356         if (!NT_STATUS_IS_OK(status)) {
1357                 return status;
1358         }
1359
1360         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1361         talloc_steal(mem_ctx, h);
1362
1363         del.in.handle = opn.out.trustdom_handle;
1364         del.out.handle = opn.out.trustdom_handle;
1365         status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
1366         if (!NT_STATUS_IS_OK(status)) {
1367                 return status;
1368         }
1369         return NT_STATUS_OK;
1370 }
1371
1372 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx, 
1373                                      struct ldb_message *msg, 
1374                                      struct lsa_TrustDomainInfoInfoEx *info_ex) 
1375 {
1376         info_ex->domain_name.string
1377                 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
1378         info_ex->netbios_name.string
1379                 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1380         info_ex->sid 
1381                 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
1382         info_ex->trust_direction
1383                 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
1384         info_ex->trust_type
1385                 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
1386         info_ex->trust_attributes
1387                 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);  
1388         return NT_STATUS_OK;
1389 }
1390
1391 /* 
1392   lsa_QueryTrustedDomainInfo
1393 */
1394 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1395                                            struct lsa_QueryTrustedDomainInfo *r)
1396 {
1397         union lsa_TrustedDomainInfo *info = NULL;
1398         struct dcesrv_handle *h;
1399         struct lsa_trusted_domain_state *trusted_domain_state;
1400         struct ldb_message *msg;
1401         int ret;
1402         struct ldb_message **res;
1403         const char *attrs[] = {
1404                 "flatname", 
1405                 "trustPartner",
1406                 "securityIdentifier",
1407                 "trustDirection",
1408                 "trustType",
1409                 "trustAttributes", 
1410                 "msDs-supportedEncryptionTypes",
1411                 NULL
1412         };
1413
1414         DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
1415
1416         trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1417
1418         /* pull all the user attributes */
1419         ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
1420                               trusted_domain_state->trusted_domain_dn, &res, attrs);
1421         if (ret != 1) {
1422                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1423         }
1424         msg = res[0];
1425         
1426         info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
1427         if (!info) {
1428                 return NT_STATUS_NO_MEMORY;
1429         }
1430         *r->out.info = info;
1431
1432         switch (r->in.level) {
1433         case LSA_TRUSTED_DOMAIN_INFO_NAME:
1434                 info->name.netbios_name.string
1435                         = samdb_result_string(msg, "flatname", NULL);                                      
1436                 break;
1437         case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1438                 info->posix_offset.posix_offset
1439                         = samdb_result_uint(msg, "posixOffset", 0);                                        
1440                 break;
1441 #if 0  /* Win2k3 doesn't implement this */
1442         case LSA_TRUSTED_DOMAIN_INFO_BASIC:
1443                 r->out.info->info_basic.netbios_name.string 
1444                         = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1445                 r->out.info->info_basic.sid
1446                         = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
1447                 break;
1448 #endif
1449         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1450                 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
1451
1452         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1453                 ZERO_STRUCT(info->full_info);
1454                 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
1455
1456         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
1457                 ZERO_STRUCT(info->full_info2_internal);
1458                 info->full_info2_internal.posix_offset.posix_offset
1459                         = samdb_result_uint(msg, "posixOffset", 0);                                        
1460                 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
1461                 
1462         case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1463                 info->enc_types.enc_types
1464                         = samdb_result_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
1465                 break;
1466
1467         case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
1468         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
1469                 /* oops, we don't want to return the info after all */
1470                 talloc_free(info);
1471                 *r->out.info = NULL;
1472                 return NT_STATUS_INVALID_PARAMETER;
1473         default:
1474                 /* oops, we don't want to return the info after all */
1475                 talloc_free(info);
1476                 *r->out.info = NULL;
1477                 return NT_STATUS_INVALID_INFO_CLASS;
1478         }
1479
1480         return NT_STATUS_OK;
1481 }
1482
1483
1484 /* 
1485   lsa_QueryTrustedDomainInfoBySid
1486 */
1487 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1488                                                 struct lsa_QueryTrustedDomainInfoBySid *r)
1489 {
1490         NTSTATUS status;
1491         struct lsa_OpenTrustedDomain opn;
1492         struct lsa_QueryTrustedDomainInfo query;
1493         struct dcesrv_handle *h;
1494
1495         opn.in.handle = r->in.handle;
1496         opn.in.sid = r->in.dom_sid;
1497         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1498         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1499         if (!opn.out.trustdom_handle) {
1500                 return NT_STATUS_NO_MEMORY;
1501         }
1502         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1503         if (!NT_STATUS_IS_OK(status)) {
1504                 return status;
1505         }
1506
1507         /* Ensure this handle goes away at the end of this call */
1508         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1509         talloc_steal(mem_ctx, h);
1510
1511         query.in.trustdom_handle = opn.out.trustdom_handle;
1512         query.in.level = r->in.level;
1513         query.out.info = r->out.info;
1514         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
1515         if (!NT_STATUS_IS_OK(status)) {
1516                 return status;
1517         }
1518
1519         return NT_STATUS_OK;
1520 }
1521
1522 /*
1523   lsa_SetTrustedDomainInfoByName
1524 */
1525 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
1526                                                TALLOC_CTX *mem_ctx,
1527                                                struct lsa_SetTrustedDomainInfoByName *r)
1528 {
1529         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1530 }
1531
1532 /* 
1533    lsa_QueryTrustedDomainInfoByName
1534 */
1535 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
1536                                                  TALLOC_CTX *mem_ctx,
1537                                                  struct lsa_QueryTrustedDomainInfoByName *r)
1538 {
1539         NTSTATUS status;
1540         struct lsa_OpenTrustedDomainByName opn;
1541         struct lsa_QueryTrustedDomainInfo query;
1542         struct dcesrv_handle *h;
1543
1544         opn.in.handle = r->in.handle;
1545         opn.in.name = *r->in.trusted_domain;
1546         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1547         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1548         if (!opn.out.trustdom_handle) {
1549                 return NT_STATUS_NO_MEMORY;
1550         }
1551         status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
1552         if (!NT_STATUS_IS_OK(status)) {
1553                 return status;
1554         }
1555         
1556         /* Ensure this handle goes away at the end of this call */
1557         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1558         talloc_steal(mem_ctx, h);
1559
1560         query.in.trustdom_handle = opn.out.trustdom_handle;
1561         query.in.level = r->in.level;
1562         query.out.info = r->out.info;
1563         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
1564         if (!NT_STATUS_IS_OK(status)) {
1565                 return status;
1566         }
1567         
1568         return NT_STATUS_OK;
1569 }
1570
1571 /*
1572   lsa_CloseTrustedDomainEx 
1573 */
1574 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
1575                                          TALLOC_CTX *mem_ctx,
1576                                          struct lsa_CloseTrustedDomainEx *r)
1577 {
1578         /* The result of a bad hair day from an IDL programmer?  Not
1579          * implmented in Win2k3.  You should always just lsa_Close
1580          * anyway. */
1581         return NT_STATUS_NOT_IMPLEMENTED;
1582 }
1583
1584
1585 /*
1586   comparison function for sorting lsa_DomainInformation array
1587 */
1588 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
1589 {
1590         return strcasecmp_m(e1->name.string, e2->name.string);
1591 }
1592
1593 /* 
1594   lsa_EnumTrustDom 
1595 */
1596 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1597                                  struct lsa_EnumTrustDom *r)
1598 {
1599         struct dcesrv_handle *policy_handle;
1600         struct lsa_DomainInfo *entries;
1601         struct lsa_policy_state *policy_state;
1602         struct ldb_message **domains;
1603         const char *attrs[] = {
1604                 "flatname", 
1605                 "securityIdentifier",
1606                 NULL
1607         };
1608
1609
1610         int count, i;
1611
1612         *r->out.resume_handle = 0;
1613
1614         r->out.domains->domains = NULL;
1615         r->out.domains->count = 0;
1616
1617         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1618
1619         policy_state = policy_handle->data;
1620
1621         /* search for all users in this domain. This could possibly be cached and 
1622            resumed based on resume_key */
1623         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs, 
1624                              "objectclass=trustedDomain");
1625         if (count == -1) {
1626                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1627         }
1628
1629         /* convert to lsa_TrustInformation format */
1630         entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
1631         if (!entries) {
1632                 return NT_STATUS_NO_MEMORY;
1633         }
1634         for (i=0;i<count;i++) {
1635                 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
1636                 entries[i].name.string = samdb_result_string(domains[i], "flatname", NULL);
1637         }
1638
1639         /* sort the results by name */
1640         qsort(entries, count, sizeof(*entries), 
1641               (comparison_fn_t)compare_DomainInfo);
1642
1643         if (*r->in.resume_handle >= count) {
1644                 *r->out.resume_handle = -1;
1645
1646                 return NT_STATUS_NO_MORE_ENTRIES;
1647         }
1648
1649         /* return the rest, limit by max_size. Note that we 
1650            use the w2k3 element size value of 60 */
1651         r->out.domains->count = count - *r->in.resume_handle;
1652         r->out.domains->count = MIN(r->out.domains->count, 
1653                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
1654
1655         r->out.domains->domains = entries + *r->in.resume_handle;
1656         r->out.domains->count = r->out.domains->count;
1657
1658         if (r->out.domains->count < count - *r->in.resume_handle) {
1659                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
1660                 return STATUS_MORE_ENTRIES;
1661         }
1662
1663         /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
1664          * always be larger than the previous input resume handle, in
1665          * particular when hitting the last query it is vital to set the
1666          * resume handle correctly to avoid infinite client loops, as
1667          * seen e.g. with Windows XP SP3 when resume handle is 0 and
1668          * status is NT_STATUS_OK - gd */
1669
1670         *r->out.resume_handle = (uint32_t)-1;
1671
1672         return NT_STATUS_OK;
1673 }
1674
1675 /*
1676   comparison function for sorting lsa_DomainInformation array
1677 */
1678 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
1679 {
1680         return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
1681 }
1682
1683 /* 
1684   lsa_EnumTrustedDomainsEx 
1685 */
1686 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1687                                         struct lsa_EnumTrustedDomainsEx *r)
1688 {
1689         struct dcesrv_handle *policy_handle;
1690         struct lsa_TrustDomainInfoInfoEx *entries;
1691         struct lsa_policy_state *policy_state;
1692         struct ldb_message **domains;
1693         const char *attrs[] = {
1694                 "flatname", 
1695                 "trustPartner",
1696                 "securityIdentifier",
1697                 "trustDirection",
1698                 "trustType",
1699                 "trustAttributes", 
1700                 NULL
1701         };
1702         NTSTATUS nt_status;
1703
1704         int count, i;
1705
1706         *r->out.resume_handle = 0;
1707
1708         r->out.domains->domains = NULL;
1709         r->out.domains->count = 0;
1710
1711         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1712
1713         policy_state = policy_handle->data;
1714
1715         /* search for all users in this domain. This could possibly be cached and 
1716            resumed based on resume_key */
1717         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs, 
1718                              "objectclass=trustedDomain");
1719         if (count == -1) {
1720                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1721         }
1722
1723         /* convert to lsa_DomainInformation format */
1724         entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
1725         if (!entries) {
1726                 return NT_STATUS_NO_MEMORY;
1727         }
1728         for (i=0;i<count;i++) {
1729                 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
1730                 if (!NT_STATUS_IS_OK(nt_status)) {
1731                         return nt_status;
1732                 }
1733         }
1734
1735         /* sort the results by name */
1736         qsort(entries, count, sizeof(*entries), 
1737               (comparison_fn_t)compare_TrustDomainInfoInfoEx);
1738
1739         if (*r->in.resume_handle >= count) {
1740                 *r->out.resume_handle = -1;
1741
1742                 return NT_STATUS_NO_MORE_ENTRIES;
1743         }
1744
1745         /* return the rest, limit by max_size. Note that we 
1746            use the w2k3 element size value of 60 */
1747         r->out.domains->count = count - *r->in.resume_handle;
1748         r->out.domains->count = MIN(r->out.domains->count, 
1749                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
1750
1751         r->out.domains->domains = entries + *r->in.resume_handle;
1752         r->out.domains->count = r->out.domains->count;
1753
1754         if (r->out.domains->count < count - *r->in.resume_handle) {
1755                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
1756                 return STATUS_MORE_ENTRIES;
1757         }
1758
1759         return NT_STATUS_OK;
1760 }
1761
1762
1763 /* 
1764   lsa_OpenAccount 
1765 */
1766 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1767                                 struct lsa_OpenAccount *r)
1768 {
1769         struct dcesrv_handle *h, *ah;
1770         struct lsa_policy_state *state;
1771         struct lsa_account_state *astate;
1772
1773         ZERO_STRUCTP(r->out.acct_handle);
1774
1775         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
1776
1777         state = h->data;
1778
1779         astate = talloc(dce_call->conn, struct lsa_account_state);
1780         if (astate == NULL) {
1781                 return NT_STATUS_NO_MEMORY;
1782         }
1783
1784         astate->account_sid = dom_sid_dup(astate, r->in.sid);
1785         if (astate->account_sid == NULL) {
1786                 talloc_free(astate);
1787                 return NT_STATUS_NO_MEMORY;
1788         }
1789         
1790         astate->policy = talloc_reference(astate, state);
1791         astate->access_mask = r->in.access_mask;
1792
1793         ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
1794         if (!ah) {
1795                 talloc_free(astate);
1796                 return NT_STATUS_NO_MEMORY;
1797         }
1798
1799         ah->data = talloc_steal(ah, astate);
1800
1801         *r->out.acct_handle = ah->wire_handle;
1802
1803         return NT_STATUS_OK;
1804 }
1805
1806
1807 /* 
1808   lsa_EnumPrivsAccount 
1809 */
1810 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call, 
1811                                      TALLOC_CTX *mem_ctx,
1812                                      struct lsa_EnumPrivsAccount *r)
1813 {
1814         struct dcesrv_handle *h;
1815         struct lsa_account_state *astate;
1816         int ret, i;
1817         struct ldb_message **res;
1818         const char * const attrs[] = { "privilege", NULL};
1819         struct ldb_message_element *el;
1820         const char *sidstr;
1821         struct lsa_PrivilegeSet *privs;
1822
1823         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
1824
1825         astate = h->data;
1826
1827         privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
1828         if (privs == NULL) {
1829                 return NT_STATUS_NO_MEMORY;
1830         }
1831         privs->count = 0;
1832         privs->unknown = 0;
1833         privs->set = NULL;
1834
1835         *r->out.privs = privs;
1836
1837         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
1838         if (sidstr == NULL) {
1839                 return NT_STATUS_NO_MEMORY;
1840         }
1841
1842         ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs, 
1843                            "objectSid=%s", sidstr);
1844         if (ret != 1) {
1845                 return NT_STATUS_OK;
1846         }
1847
1848         el = ldb_msg_find_element(res[0], "privilege");
1849         if (el == NULL || el->num_values == 0) {
1850                 return NT_STATUS_OK;
1851         }
1852
1853         privs->set = talloc_array(privs,
1854                                   struct lsa_LUIDAttribute, el->num_values);
1855         if (privs->set == NULL) {
1856                 return NT_STATUS_NO_MEMORY;
1857         }
1858
1859         for (i=0;i<el->num_values;i++) {
1860                 int id = sec_privilege_id((const char *)el->values[i].data);
1861                 if (id == -1) {
1862                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1863                 }
1864                 privs->set[i].attribute = 0;
1865                 privs->set[i].luid.low = id;
1866                 privs->set[i].luid.high = 0;
1867         }
1868
1869         privs->count = el->num_values;
1870
1871         return NT_STATUS_OK;
1872 }
1873
1874 /* 
1875   lsa_EnumAccountRights 
1876 */
1877 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call, 
1878                                       TALLOC_CTX *mem_ctx,
1879                                       struct lsa_EnumAccountRights *r)
1880 {
1881         struct dcesrv_handle *h;
1882         struct lsa_policy_state *state;
1883         int ret, i;
1884         struct ldb_message **res;
1885         const char * const attrs[] = { "privilege", NULL};
1886         const char *sidstr;
1887         struct ldb_message_element *el;
1888
1889         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
1890
1891         state = h->data;
1892
1893         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
1894         if (sidstr == NULL) {
1895                 return NT_STATUS_NO_MEMORY;
1896         }
1897
1898         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs, 
1899                            "(&(objectSid=%s)(privilege=*))", sidstr);
1900         if (ret == 0) {
1901                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1902         }
1903         if (ret > 1) {
1904                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1905         }
1906         if (ret == -1) {
1907                 DEBUG(3, ("searching for account rights for SID: %s failed: %s", 
1908                           dom_sid_string(mem_ctx, r->in.sid),
1909                           ldb_errstring(state->pdb)));
1910                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1911         }
1912
1913         el = ldb_msg_find_element(res[0], "privilege");
1914         if (el == NULL || el->num_values == 0) {
1915                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1916         }
1917
1918         r->out.rights->count = el->num_values;
1919         r->out.rights->names = talloc_array(r->out.rights, 
1920                                             struct lsa_StringLarge, r->out.rights->count);
1921         if (r->out.rights->names == NULL) {
1922                 return NT_STATUS_NO_MEMORY;
1923         }
1924
1925         for (i=0;i<el->num_values;i++) {
1926                 r->out.rights->names[i].string = (const char *)el->values[i].data;
1927         }
1928
1929         return NT_STATUS_OK;
1930 }
1931
1932
1933
1934 /* 
1935   helper for lsa_AddAccountRights and lsa_RemoveAccountRights
1936 */
1937 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call, 
1938                                            TALLOC_CTX *mem_ctx,
1939                                            struct lsa_policy_state *state,
1940                                            int ldb_flag,
1941                                            struct dom_sid *sid,
1942                                            const struct lsa_RightSet *rights)
1943 {
1944         const char *sidstr, *sidndrstr;
1945         struct ldb_message *msg;
1946         struct ldb_message_element *el;
1947         int i, ret;
1948         struct lsa_EnumAccountRights r2;
1949         char *dnstr;
1950
1951         if (security_session_user_level(dce_call->conn->auth_state.session_info) < 
1952             SECURITY_ADMINISTRATOR) {
1953                 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
1954                 return NT_STATUS_ACCESS_DENIED;
1955         }
1956
1957         msg = ldb_msg_new(mem_ctx);
1958         if (msg == NULL) {
1959                 return NT_STATUS_NO_MEMORY;
1960         }
1961
1962         sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
1963         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidndrstr, msg);
1964
1965         sidstr = dom_sid_string(msg, sid);
1966         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, msg);
1967
1968         dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
1969         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(dnstr, msg);
1970
1971         msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
1972         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg->dn, msg);
1973
1974         if (ldb_flag == LDB_FLAG_MOD_ADD) {
1975                 NTSTATUS status;
1976
1977                 r2.in.handle = &state->handle->wire_handle;
1978                 r2.in.sid = sid;
1979                 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
1980
1981                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
1982                 if (!NT_STATUS_IS_OK(status)) {
1983                         ZERO_STRUCTP(r2.out.rights);
1984                 }
1985         }
1986
1987         for (i=0;i<rights->count;i++) {
1988                 if (sec_privilege_id(rights->names[i].string) == -1) {
1989                         talloc_free(msg);
1990                         return NT_STATUS_NO_SUCH_PRIVILEGE;
1991                 }
1992
1993                 if (ldb_flag == LDB_FLAG_MOD_ADD) {
1994                         int j;
1995                         for (j=0;j<r2.out.rights->count;j++) {
1996                                 if (strcasecmp_m(r2.out.rights->names[j].string, 
1997                                                rights->names[i].string) == 0) {
1998                                         break;
1999                                 }
2000                         }
2001                         if (j != r2.out.rights->count) continue;
2002                 }
2003
2004                 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2005                 if (ret != LDB_SUCCESS) {
2006                         talloc_free(msg);
2007                         return NT_STATUS_NO_MEMORY;
2008                 }
2009         }
2010
2011         el = ldb_msg_find_element(msg, "privilege");
2012         if (!el) {
2013                 talloc_free(msg);
2014                 return NT_STATUS_OK;
2015         }
2016
2017         el->flags = ldb_flag;
2018
2019         ret = ldb_modify(state->pdb, msg);
2020         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2021                 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2022                         talloc_free(msg);
2023                         return NT_STATUS_NO_MEMORY;
2024                 }
2025                 samdb_msg_add_string(state->pdb, msg, msg, "comment", "added via LSA");
2026                 ret = ldb_add(state->pdb, msg);         
2027         }
2028         if (ret != 0) {
2029                 if (ldb_flag == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2030                         talloc_free(msg);
2031                         return NT_STATUS_OK;
2032                 }
2033                 DEBUG(3, ("Could not %s attributes from %s: %s", 
2034                           ldb_flag == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2035                           ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2036                 talloc_free(msg);
2037                 return NT_STATUS_UNEXPECTED_IO_ERROR;
2038         }
2039
2040         talloc_free(msg);
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         int i;
2170         NTSTATUS status;
2171         struct lsa_EnumPrivsAccount enumPrivs;
2172         struct lsa_PrivilegeSet *privs;
2173
2174         privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2175         if (!privs) {
2176                 return NT_STATUS_NO_MEMORY;
2177         }
2178         privs->count = 0;
2179         privs->unknown = 0;
2180         privs->set = NULL;
2181
2182         enumPrivs.in.handle = r->in.handle;
2183         enumPrivs.out.privs = &privs;
2184
2185         status = dcesrv_lsa_EnumPrivsAccount(dce_call, mem_ctx, &enumPrivs);
2186         if (!NT_STATUS_IS_OK(status)) {
2187                 return status;
2188         }       
2189
2190         *(r->out.access_mask) = 0x00000000;
2191
2192         for (i = 0; i < privs->count; i++) {
2193                 int priv = privs->set[i].luid.low;
2194
2195                 switch (priv) {
2196                 case SEC_PRIV_INTERACTIVE_LOGON:
2197                         *(r->out.access_mask) |= LSA_POLICY_MODE_INTERACTIVE;
2198                         break;
2199                 case SEC_PRIV_NETWORK_LOGON:
2200                         *(r->out.access_mask) |= LSA_POLICY_MODE_NETWORK;
2201                         break;
2202                 case SEC_PRIV_REMOTE_INTERACTIVE_LOGON:
2203                         *(r->out.access_mask) |= LSA_POLICY_MODE_REMOTE_INTERACTIVE;
2204                         break;
2205                 }
2206         }
2207
2208         return NT_STATUS_OK;
2209 }
2210
2211
2212 /* 
2213   lsa_SetSystemAccessAccount
2214 */
2215 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2216                        struct lsa_SetSystemAccessAccount *r)
2217 {
2218         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2219 }
2220
2221
2222 /* 
2223   lsa_CreateSecret 
2224 */
2225 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2226                                  struct lsa_CreateSecret *r)
2227 {
2228         struct dcesrv_handle *policy_handle;
2229         struct lsa_policy_state *policy_state;
2230         struct lsa_secret_state *secret_state;
2231         struct dcesrv_handle *handle;
2232         struct ldb_message **msgs, *msg;
2233         const char *attrs[] = {
2234                 NULL
2235         };
2236
2237         const char *name;
2238
2239         int ret;
2240
2241         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2242         ZERO_STRUCTP(r->out.sec_handle);
2243         
2244         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
2245         {
2246         case SECURITY_SYSTEM:
2247         case SECURITY_ADMINISTRATOR:
2248                 break;
2249         default:
2250                 /* Users and annonymous are not allowed create secrets */
2251                 return NT_STATUS_ACCESS_DENIED;
2252         }
2253
2254         policy_state = policy_handle->data;
2255
2256         if (!r->in.name.string) {
2257                 return NT_STATUS_INVALID_PARAMETER;
2258         }
2259         
2260         secret_state = talloc(mem_ctx, struct lsa_secret_state);
2261         if (!secret_state) {
2262                 return NT_STATUS_NO_MEMORY;
2263         }
2264         secret_state->policy = policy_state;
2265
2266         msg = ldb_msg_new(mem_ctx);
2267         if (msg == NULL) {
2268                 return NT_STATUS_NO_MEMORY;
2269         }
2270
2271         if (strncmp("G$", r->in.name.string, 2) == 0) {
2272                 const char *name2;
2273                 name = &r->in.name.string[2];
2274                         /* We need to connect to the database as system, as this is one of the rare RPC calls that must read the secrets (and this is denied otherwise) */
2275                 secret_state->sam_ldb = talloc_reference(secret_state, 
2276                                                          samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(secret_state, dce_call->conn->dce_ctx->lp_ctx))); 
2277                 secret_state->global = true;
2278
2279                 if (strlen(name) < 1) {
2280                         return NT_STATUS_INVALID_PARAMETER;
2281                 }
2282
2283                 name2 = talloc_asprintf(mem_ctx, "%s Secret", ldb_binary_encode_string(mem_ctx, name));
2284                 /* search for the secret record */
2285                 ret = gendb_search(secret_state->sam_ldb,
2286                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
2287                                    "(&(cn=%s)(objectclass=secret))", 
2288                                    name2);
2289                 if (ret > 0) {
2290                         return NT_STATUS_OBJECT_NAME_COLLISION;
2291                 }
2292                 
2293                 if (ret == -1) {
2294                         DEBUG(0,("Failure searching for CN=%s: %s\n", 
2295                                  name2, ldb_errstring(secret_state->sam_ldb)));
2296                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2297                 }
2298
2299                 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2300                 if (!name2 || ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2301                         return NT_STATUS_NO_MEMORY;
2302                 }
2303                 
2304                 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name2);
2305         
2306         } else {
2307                 secret_state->global = false;
2308
2309                 name = r->in.name.string;
2310                 if (strlen(name) < 1) {
2311                         return NT_STATUS_INVALID_PARAMETER;
2312                 }
2313
2314                 secret_state->sam_ldb = talloc_reference(secret_state, 
2315                                                          secrets_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx));
2316                 /* search for the secret record */
2317                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2318                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2319                                    &msgs, attrs,
2320                                    "(&(cn=%s)(objectclass=secret))", 
2321                                    ldb_binary_encode_string(mem_ctx, name));
2322                 if (ret > 0) {
2323                         return NT_STATUS_OBJECT_NAME_COLLISION;
2324                 }
2325                 
2326                 if (ret == -1) {
2327                         DEBUG(0,("Failure searching for CN=%s: %s\n", 
2328                                  name, ldb_errstring(secret_state->sam_ldb)));
2329                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2330                 }
2331
2332                 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb, "cn=%s,cn=LSA Secrets", name);
2333                 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name);
2334         } 
2335
2336         samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "objectClass", "secret");
2337         
2338         secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
2339
2340         /* create the secret */
2341         ret = ldb_add(secret_state->sam_ldb, msg);
2342         if (ret != 0) {
2343                 DEBUG(0,("Failed to create secret record %s: %s\n",
2344                          ldb_dn_get_linearized(msg->dn), 
2345                          ldb_errstring(secret_state->sam_ldb)));
2346                 return NT_STATUS_ACCESS_DENIED;
2347         }
2348
2349         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2350         if (!handle) {
2351                 return NT_STATUS_NO_MEMORY;
2352         }
2353         
2354         handle->data = talloc_steal(handle, secret_state);
2355         
2356         secret_state->access_mask = r->in.access_mask;
2357         secret_state->policy = talloc_reference(secret_state, policy_state);
2358         
2359         *r->out.sec_handle = handle->wire_handle;
2360         
2361         return NT_STATUS_OK;
2362 }
2363
2364
2365 /* 
2366   lsa_OpenSecret 
2367 */
2368 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2369                                struct lsa_OpenSecret *r)
2370 {
2371         struct dcesrv_handle *policy_handle;
2372         
2373         struct lsa_policy_state *policy_state;
2374         struct lsa_secret_state *secret_state;
2375         struct dcesrv_handle *handle;
2376         struct ldb_message **msgs;
2377         const char *attrs[] = {
2378                 NULL
2379         };
2380
2381         const char *name;
2382
2383         int ret;
2384
2385         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2386         ZERO_STRUCTP(r->out.sec_handle);
2387         policy_state = policy_handle->data;
2388
2389         if (!r->in.name.string) {
2390                 return NT_STATUS_INVALID_PARAMETER;
2391         }
2392         
2393         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
2394         {
2395         case SECURITY_SYSTEM:
2396         case SECURITY_ADMINISTRATOR:
2397                 break;
2398         default:
2399                 /* Users and annonymous are not allowed to access secrets */
2400                 return NT_STATUS_ACCESS_DENIED;
2401         }
2402
2403         secret_state = talloc(mem_ctx, struct lsa_secret_state);
2404         if (!secret_state) {
2405                 return NT_STATUS_NO_MEMORY;
2406         }
2407         secret_state->policy = policy_state;
2408
2409         if (strncmp("G$", r->in.name.string, 2) == 0) {
2410                 name = &r->in.name.string[2];
2411                 /* We need to connect to the database as system, as this is one of the rare RPC calls that must read the secrets (and this is denied otherwise) */
2412                 secret_state->sam_ldb = talloc_reference(secret_state, 
2413                                                          samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(secret_state, dce_call->conn->dce_ctx->lp_ctx))); 
2414                 secret_state->global = true;
2415
2416                 if (strlen(name) < 1) {
2417                         return NT_STATUS_INVALID_PARAMETER;
2418                 }
2419
2420                 /* search for the secret record */
2421                 ret = gendb_search(secret_state->sam_ldb,
2422                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
2423                                    "(&(cn=%s Secret)(objectclass=secret))", 
2424                                    ldb_binary_encode_string(mem_ctx, name));
2425                 if (ret == 0) {
2426                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2427                 }
2428                 
2429                 if (ret != 1) {
2430                         DEBUG(0,("Found %d records matching DN %s\n", ret,
2431                                  ldb_dn_get_linearized(policy_state->system_dn)));
2432                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2433                 }
2434         
2435         } else {
2436                 secret_state->global = false;
2437                 secret_state->sam_ldb = talloc_reference(secret_state, 
2438                                  secrets_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx));
2439
2440                 name = r->in.name.string;
2441                 if (strlen(name) < 1) {
2442                         return NT_STATUS_INVALID_PARAMETER;
2443                 }
2444
2445                 /* search for the secret record */
2446                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2447                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2448                                    &msgs, attrs,
2449                                    "(&(cn=%s)(objectclass=secret))", 
2450                                    ldb_binary_encode_string(mem_ctx, name));
2451                 if (ret == 0) {
2452                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2453                 }
2454                 
2455                 if (ret != 1) {
2456                         DEBUG(0,("Found %d records matching CN=%s\n", 
2457                                  ret, ldb_binary_encode_string(mem_ctx, name)));
2458                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2459                 }
2460         } 
2461
2462         secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
2463         
2464         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2465         if (!handle) {
2466                 return NT_STATUS_NO_MEMORY;
2467         }
2468         
2469         handle->data = talloc_steal(handle, secret_state);
2470         
2471         secret_state->access_mask = r->in.access_mask;
2472         secret_state->policy = talloc_reference(secret_state, policy_state);
2473         
2474         *r->out.sec_handle = handle->wire_handle;
2475         
2476         return NT_STATUS_OK;
2477 }
2478
2479
2480 /* 
2481   lsa_SetSecret 
2482 */
2483 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2484                               struct lsa_SetSecret *r)
2485 {
2486
2487         struct dcesrv_handle *h;
2488         struct lsa_secret_state *secret_state;
2489         struct ldb_message *msg;
2490         DATA_BLOB session_key;
2491         DATA_BLOB crypt_secret, secret;
2492         struct ldb_val val;
2493         int ret;
2494         NTSTATUS status = NT_STATUS_OK;
2495
2496         struct timeval now = timeval_current();
2497         NTTIME nt_now = timeval_to_nttime(&now);
2498
2499         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
2500
2501         secret_state = h->data;
2502
2503         msg = ldb_msg_new(mem_ctx);
2504         if (msg == NULL) {
2505                 return NT_STATUS_NO_MEMORY;
2506         }
2507
2508         msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
2509         if (!msg->dn) {
2510                 return NT_STATUS_NO_MEMORY;
2511         }
2512         status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
2513         if (!NT_STATUS_IS_OK(status)) {
2514                 return status;
2515         }
2516
2517         if (r->in.old_val) {
2518                 /* Decrypt */
2519                 crypt_secret.data = r->in.old_val->data;
2520                 crypt_secret.length = r->in.old_val->size;
2521                 
2522                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
2523                 if (!NT_STATUS_IS_OK(status)) {
2524                         return status;
2525                 }
2526                 
2527                 val.data = secret.data;
2528                 val.length = secret.length;
2529                 
2530                 /* set value */
2531                 if (samdb_msg_add_value(secret_state->sam_ldb, 
2532                                         mem_ctx, msg, "priorValue", &val) != 0) {
2533                         return NT_STATUS_NO_MEMORY; 
2534                 }
2535                 
2536                 /* set old value mtime */
2537                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2538                                          mem_ctx, msg, "priorSetTime", nt_now) != 0) { 
2539                         return NT_STATUS_NO_MEMORY; 
2540                 }
2541
2542         } else {
2543                 /* If the old value is not set, then migrate the
2544                  * current value to the old value */
2545                 const struct ldb_val *old_val;
2546                 NTTIME last_set_time;
2547                 struct ldb_message **res;
2548                 const char *attrs[] = {
2549                         "currentValue",
2550                         "lastSetTime",
2551                         NULL
2552                 };
2553                 
2554                 /* search for the secret record */
2555                 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
2556                                       secret_state->secret_dn, &res, attrs);
2557                 if (ret == 0) {
2558                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2559                 }
2560                 
2561                 if (ret != 1) {
2562                         DEBUG(0,("Found %d records matching dn=%s\n", ret,
2563                                  ldb_dn_get_linearized(secret_state->secret_dn)));
2564                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2565                 }
2566                 
2567                 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
2568                 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
2569                 
2570                 if (old_val) {
2571                         /* set old value */
2572                         if (samdb_msg_add_value(secret_state->sam_ldb, 
2573                                                 mem_ctx, msg, "priorValue", 
2574                                                 old_val) != 0) {
2575                                 return NT_STATUS_NO_MEMORY; 
2576                         }
2577                 } else {
2578                         if (samdb_msg_add_delete(secret_state->sam_ldb, 
2579                                                  mem_ctx, msg, "priorValue")) {
2580                                 return NT_STATUS_NO_MEMORY;
2581                         }
2582                         
2583                 }
2584                 
2585                 /* set old value mtime */
2586                 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
2587                         if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2588                                                  mem_ctx, msg, "priorSetTime", last_set_time) != 0) { 
2589                                 return NT_STATUS_NO_MEMORY; 
2590                         }
2591                 } else {
2592                         if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2593                                                  mem_ctx, msg, "priorSetTime", nt_now) != 0) { 
2594                                 return NT_STATUS_NO_MEMORY; 
2595                         }
2596                 }
2597         }
2598
2599         if (r->in.new_val) {
2600                 /* Decrypt */
2601                 crypt_secret.data = r->in.new_val->data;
2602                 crypt_secret.length = r->in.new_val->size;
2603                 
2604                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
2605                 if (!NT_STATUS_IS_OK(status)) {
2606                         return status;
2607                 }
2608                 
2609                 val.data = secret.data;
2610                 val.length = secret.length;
2611                 
2612                 /* set value */
2613                 if (samdb_msg_add_value(secret_state->sam_ldb, 
2614                                         mem_ctx, msg, "currentValue", &val) != 0) {
2615                         return NT_STATUS_NO_MEMORY; 
2616                 }
2617                 
2618                 /* set new value mtime */
2619                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2620                                          mem_ctx, msg, "lastSetTime", nt_now) != 0) { 
2621                         return NT_STATUS_NO_MEMORY; 
2622                 }
2623                 
2624         } else {
2625                 /* NULL out the NEW value */
2626                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
2627                                          mem_ctx, msg, "lastSetTime", nt_now) != 0) { 
2628                         return NT_STATUS_NO_MEMORY; 
2629                 }
2630                 if (samdb_msg_add_delete(secret_state->sam_ldb, 
2631                                          mem_ctx, msg, "currentValue")) {
2632                         return NT_STATUS_NO_MEMORY;
2633                 }
2634         }
2635
2636         /* modify the samdb record */
2637         ret = samdb_replace(secret_state->sam_ldb, mem_ctx, msg);
2638         if (ret != 0) {
2639                 /* we really need samdb.c to return NTSTATUS */
2640                 return NT_STATUS_UNSUCCESSFUL;
2641         }
2642
2643         return NT_STATUS_OK;
2644 }
2645
2646
2647 /* 
2648   lsa_QuerySecret 
2649 */
2650 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2651                                 struct lsa_QuerySecret *r)
2652 {
2653         struct dcesrv_handle *h;
2654         struct lsa_secret_state *secret_state;
2655         struct ldb_message *msg;
2656         DATA_BLOB session_key;
2657         DATA_BLOB crypt_secret, secret;
2658         int ret;
2659         struct ldb_message **res;
2660         const char *attrs[] = {
2661                 "currentValue",
2662                 "priorValue",
2663                 "lastSetTime",
2664                 "priorSetTime", 
2665                 NULL
2666         };
2667
2668         NTSTATUS nt_status;
2669
2670         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
2671
2672         /* Ensure user is permitted to read this... */
2673         switch (security_session_user_level(dce_call->conn->auth_state.session_info))
2674         {
2675         case SECURITY_SYSTEM:
2676         case SECURITY_ADMINISTRATOR:
2677                 break;
2678         default:
2679                 /* Users and annonymous are not allowed to read secrets */
2680                 return NT_STATUS_ACCESS_DENIED;
2681         }
2682
2683         secret_state = h->data;
2684
2685         /* pull all the user attributes */
2686         ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
2687                               secret_state->secret_dn, &res, attrs);
2688         if (ret != 1) {
2689                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2690         }
2691         msg = res[0];
2692         
2693         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
2694         if (!NT_STATUS_IS_OK(nt_status)) {
2695                 return nt_status;
2696         }
2697         
2698         if (r->in.old_val) {
2699                 const struct ldb_val *prior_val;
2700                 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
2701                 if (!r->out.old_val) {
2702                         return NT_STATUS_NO_MEMORY;
2703                 }
2704                 prior_val = ldb_msg_find_ldb_val(res[0], "priorValue");
2705                 
2706                 if (prior_val && prior_val->length) {
2707                         secret.data = prior_val->data;
2708                         secret.length = prior_val->length;
2709                 
2710                         /* Encrypt */
2711                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
2712                         if (!crypt_secret.length) {
2713                                 return NT_STATUS_NO_MEMORY;
2714                         }
2715                         r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
2716                         if (!r->out.old_val->buf) {
2717                                 return NT_STATUS_NO_MEMORY;
2718                         }
2719                         r->out.old_val->buf->size = crypt_secret.length;
2720                         r->out.old_val->buf->length = crypt_secret.length;
2721                         r->out.old_val->buf->data = crypt_secret.data;
2722                 }
2723         }
2724         
2725         if (r->in.old_mtime) {
2726                 r->out.old_mtime = talloc(mem_ctx, NTTIME);
2727                 if (!r->out.old_mtime) {
2728                         return NT_STATUS_NO_MEMORY;
2729                 }
2730                 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(res[0], "priorSetTime", 0);
2731         }
2732         
2733         if (r->in.new_val) {
2734                 const struct ldb_val *new_val;
2735                 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
2736                 if (!r->out.new_val) {
2737                         return NT_STATUS_NO_MEMORY;
2738                 }
2739
2740                 new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
2741                 
2742                 if (new_val && new_val->length) {
2743                         secret.data = new_val->data;
2744                         secret.length = new_val->length;
2745                 
2746                         /* Encrypt */
2747                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
2748                         if (!crypt_secret.length) {
2749                                 return NT_STATUS_NO_MEMORY;
2750                         }
2751                         r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
2752                         if (!r->out.new_val->buf) {
2753                                 return NT_STATUS_NO_MEMORY;
2754                         }
2755                         r->out.new_val->buf->length = crypt_secret.length;
2756                         r->out.new_val->buf->size = crypt_secret.length;
2757                         r->out.new_val->buf->data = crypt_secret.data;
2758                 }
2759         }
2760         
2761         if (r->in.new_mtime) {
2762                 r->out.new_mtime = talloc(mem_ctx, NTTIME);
2763                 if (!r->out.new_mtime) {
2764                         return NT_STATUS_NO_MEMORY;
2765                 }
2766                 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
2767         }
2768         
2769         return NT_STATUS_OK;
2770 }
2771
2772
2773 /* 
2774   lsa_LookupPrivValue
2775 */
2776 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call, 
2777                                     TALLOC_CTX *mem_ctx,
2778                                     struct lsa_LookupPrivValue *r)
2779 {
2780         struct dcesrv_handle *h;
2781         struct lsa_policy_state *state;
2782         int id;
2783
2784         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2785
2786         state = h->data;
2787
2788         id = sec_privilege_id(r->in.name->string);
2789         if (id == -1) {
2790                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2791         }
2792
2793         r->out.luid->low = id;
2794         r->out.luid->high = 0;
2795
2796         return NT_STATUS_OK;    
2797 }
2798
2799
2800 /* 
2801   lsa_LookupPrivName 
2802 */
2803 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call, 
2804                                    TALLOC_CTX *mem_ctx,
2805                                    struct lsa_LookupPrivName *r)
2806 {
2807         struct dcesrv_handle *h;
2808         struct lsa_policy_state *state;
2809         struct lsa_StringLarge *name;
2810         const char *privname;
2811
2812         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2813
2814         state = h->data;
2815
2816         if (r->in.luid->high != 0) {
2817                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2818         }
2819
2820         privname = sec_privilege_name(r->in.luid->low);
2821         if (privname == NULL) {
2822                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2823         }
2824
2825         name = talloc(mem_ctx, struct lsa_StringLarge);
2826         if (name == NULL) {
2827                 return NT_STATUS_NO_MEMORY;
2828         }
2829
2830         name->string = privname;
2831
2832         *r->out.name = name;
2833
2834         return NT_STATUS_OK;    
2835 }
2836
2837
2838 /* 
2839   lsa_LookupPrivDisplayName
2840 */
2841 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call, 
2842                                           TALLOC_CTX *mem_ctx,
2843                                           struct lsa_LookupPrivDisplayName *r)
2844 {
2845         struct dcesrv_handle *h;
2846         struct lsa_policy_state *state;
2847         struct lsa_StringLarge *disp_name = NULL;
2848         int id;
2849
2850         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2851
2852         state = h->data;
2853
2854         id = sec_privilege_id(r->in.name->string);
2855         if (id == -1) {
2856                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2857         }
2858
2859         disp_name = talloc(mem_ctx, struct lsa_StringLarge);
2860         if (disp_name == NULL) {
2861                 return NT_STATUS_NO_MEMORY;
2862         }
2863
2864         disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
2865         if (disp_name->string == NULL) {
2866                 return NT_STATUS_INTERNAL_ERROR;
2867         }
2868
2869         *r->out.disp_name = disp_name;
2870         *r->out.returned_language_id = 0;
2871
2872         return NT_STATUS_OK;
2873 }
2874
2875
2876 /* 
2877   lsa_EnumAccountsWithUserRight
2878 */
2879 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call, 
2880                                               TALLOC_CTX *mem_ctx,
2881                                               struct lsa_EnumAccountsWithUserRight *r)
2882 {
2883         struct dcesrv_handle *h;
2884         struct lsa_policy_state *state;
2885         int ret, i;
2886         struct ldb_message **res;
2887         const char * const attrs[] = { "objectSid", NULL};
2888         const char *privname;
2889
2890         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2891
2892         state = h->data;
2893
2894         if (r->in.name == NULL) {
2895                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2896         } 
2897
2898         privname = r->in.name->string;
2899         if (sec_privilege_id(privname) == -1) {
2900                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2901         }
2902
2903         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs, 
2904                            "privilege=%s", privname);
2905         if (ret == -1) {
2906                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2907         }
2908         if (ret == 0) {
2909                 return NT_STATUS_NO_MORE_ENTRIES;
2910         }
2911
2912         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
2913         if (r->out.sids->sids == NULL) {
2914                 return NT_STATUS_NO_MEMORY;
2915         }
2916         for (i=0;i<ret;i++) {
2917                 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
2918                                                                 res[i], "objectSid");
2919                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
2920         }
2921         r->out.sids->num_sids = ret;
2922
2923         return NT_STATUS_OK;
2924 }
2925
2926
2927 /* 
2928   lsa_AddAccountRights
2929 */
2930 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call, 
2931                                      TALLOC_CTX *mem_ctx,
2932                                      struct lsa_AddAccountRights *r)
2933 {
2934         struct dcesrv_handle *h;
2935         struct lsa_policy_state *state;
2936
2937         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2938
2939         state = h->data;
2940
2941         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
2942                                           LDB_FLAG_MOD_ADD,
2943                                           r->in.sid, r->in.rights);
2944 }
2945
2946
2947 /* 
2948   lsa_RemoveAccountRights
2949 */
2950 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call, 
2951                                         TALLOC_CTX *mem_ctx,
2952                                         struct lsa_RemoveAccountRights *r)
2953 {
2954         struct dcesrv_handle *h;
2955         struct lsa_policy_state *state;
2956
2957         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2958
2959         state = h->data;
2960
2961         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
2962                                           LDB_FLAG_MOD_DELETE,
2963                                           r->in.sid, r->in.rights);
2964 }
2965
2966
2967 /* 
2968   lsa_StorePrivateData
2969 */
2970 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2971                        struct lsa_StorePrivateData *r)
2972 {
2973         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2974 }
2975
2976
2977 /* 
2978   lsa_RetrievePrivateData
2979 */
2980 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2981                        struct lsa_RetrievePrivateData *r)
2982 {
2983         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2984 }
2985
2986
2987 /* 
2988   lsa_GetUserName
2989 */
2990 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2991                                 struct lsa_GetUserName *r)
2992 {
2993         NTSTATUS status = NT_STATUS_OK;
2994         const char *account_name;
2995         const char *authority_name;
2996         struct lsa_String *_account_name;
2997         struct lsa_String *_authority_name = NULL;
2998
2999         /* this is what w2k3 does */
3000         r->out.account_name = r->in.account_name;
3001         r->out.authority_name = r->in.authority_name;
3002
3003         if (r->in.account_name
3004             && *r->in.account_name
3005             /* && *(*r->in.account_name)->string */
3006             ) {
3007                 return NT_STATUS_INVALID_PARAMETER;
3008         }
3009
3010         if (r->in.authority_name
3011             && *r->in.authority_name
3012             /* && *(*r->in.authority_name)->string */
3013             ) {
3014                 return NT_STATUS_INVALID_PARAMETER;
3015         }
3016
3017         account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->account_name);
3018         authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->domain_name);
3019
3020         _account_name = talloc(mem_ctx, struct lsa_String);
3021         NT_STATUS_HAVE_NO_MEMORY(_account_name);
3022         _account_name->string = account_name;
3023
3024         if (r->in.authority_name) {
3025                 _authority_name = talloc(mem_ctx, struct lsa_String);
3026                 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3027                 _authority_name->string = authority_name;
3028         }
3029
3030         *r->out.account_name = _account_name;
3031         if (r->out.authority_name) {
3032                 *r->out.authority_name = _authority_name;
3033         }
3034
3035         return status;
3036 }
3037
3038 /*
3039   lsa_SetInfoPolicy2
3040 */
3041 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3042                                    TALLOC_CTX *mem_ctx,
3043                                    struct lsa_SetInfoPolicy2 *r)
3044 {
3045         /* need to support these */
3046         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3047 }
3048
3049 /*
3050   lsa_QueryDomainInformationPolicy
3051 */
3052 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3053                                                  TALLOC_CTX *mem_ctx,
3054                                                  struct lsa_QueryDomainInformationPolicy *r)
3055 {
3056         union lsa_DomainInformationPolicy *info;
3057
3058         info = talloc(r->out.info, union lsa_DomainInformationPolicy);
3059         if (!info) {
3060                 return NT_STATUS_NO_MEMORY;
3061         }
3062
3063         switch (r->in.level) {
3064         case LSA_DOMAIN_INFO_POLICY_EFS:
3065                 talloc_free(info);
3066                 *r->out.info = NULL;
3067                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3068         case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3069         {
3070                 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3071                 struct smb_krb5_context *smb_krb5_context;
3072                 int ret = smb_krb5_init_context(mem_ctx, 
3073                                                         dce_call->event_ctx, 
3074                                                         dce_call->conn->dce_ctx->lp_ctx,
3075                                                         &smb_krb5_context);
3076                 if (ret != 0) {
3077                         talloc_free(info);
3078                         *r->out.info = NULL;
3079                         return NT_STATUS_INTERNAL_ERROR;
3080                 }
3081                 k->enforce_restrictions = 0; /* FIXME, details missing from MS-LSAD 2.2.53 */
3082                 k->service_tkt_lifetime = 0; /* Need to find somewhere to store this, and query in KDC too */
3083                 k->user_tkt_lifetime = 0;    /* Need to find somewhere to store this, and query in KDC too */
3084                 k->user_tkt_renewaltime = 0; /* Need to find somewhere to store this, and query in KDC too */
3085                 k->clock_skew = krb5_get_max_time_skew(smb_krb5_context->krb5_context);
3086                 talloc_free(smb_krb5_context);
3087                 *r->out.info = info;
3088                 return NT_STATUS_OK;
3089         }
3090         default:
3091                 talloc_free(info);
3092                 *r->out.info = NULL;
3093                 return NT_STATUS_INVALID_INFO_CLASS;
3094         }
3095 }
3096
3097 /*
3098   lsa_SetDomInfoPolicy
3099 */
3100 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3101                                               TALLOC_CTX *mem_ctx,
3102                                               struct lsa_SetDomainInformationPolicy *r)
3103 {
3104         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3105 }
3106
3107 /*
3108   lsa_TestCall
3109 */
3110 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3111                              TALLOC_CTX *mem_ctx,
3112                              struct lsa_TestCall *r)
3113 {
3114         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3115 }
3116
3117 /* 
3118   lsa_CREDRWRITE 
3119 */
3120 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3121