0a347e07dd80c792fc370c0e3611aa268e3d774f
[samba.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 #include "lib/util/tsort.h"
32 #include "dsdb/common/util.h"
33
34 /*
35   this type allows us to distinguish handle types
36 */
37
38 /*
39   state associated with a lsa_OpenAccount() operation
40 */
41 struct lsa_account_state {
42         struct lsa_policy_state *policy;
43         uint32_t access_mask;
44         struct dom_sid *account_sid;
45 };
46
47
48 /*
49   state associated with a lsa_OpenSecret() operation
50 */
51 struct lsa_secret_state {
52         struct lsa_policy_state *policy;
53         uint32_t access_mask;
54         struct ldb_dn *secret_dn;
55         struct ldb_context *sam_ldb;
56         bool global;
57 };
58
59 /*
60   state associated with a lsa_OpenTrustedDomain() operation
61 */
62 struct lsa_trusted_domain_state {
63         struct lsa_policy_state *policy;
64         uint32_t access_mask;
65         struct ldb_dn *trusted_domain_dn;
66         struct ldb_dn *trusted_domain_user_dn;
67 };
68
69 /*
70   this is based on the samba3 function make_lsa_object_sd()
71   It uses the same logic, but with samba4 helper functions
72  */
73 static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx, 
74                                     struct security_descriptor **sd,
75                                     struct dom_sid *sid, 
76                                     uint32_t sid_access)
77 {
78         NTSTATUS status;
79         uint32_t rid;
80         struct dom_sid *domain_sid, *domain_admins_sid;
81         const char *domain_admins_sid_str, *sidstr;
82         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
83
84         status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
85         NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
86
87         domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
88         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid, tmp_ctx);
89
90         domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
91         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(domain_admins_sid_str, tmp_ctx);
92         
93         sidstr = dom_sid_string(tmp_ctx, sid);
94         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, tmp_ctx);
95                                                       
96         *sd = security_descriptor_dacl_create(mem_ctx,
97                                               0, sidstr, NULL,
98
99                                               SID_WORLD,
100                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
101                                               SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
102                                               
103                                               SID_BUILTIN_ADMINISTRATORS,
104                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
105                                               SEC_GENERIC_ALL, 0,
106                                               
107                                               SID_BUILTIN_ACCOUNT_OPERATORS,
108                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
109                                               SEC_GENERIC_ALL, 0,
110                                               
111                                               domain_admins_sid_str,
112                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
113                                               SEC_GENERIC_ALL, 0,
114
115                                               sidstr,
116                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
117                                               sid_access, 0,
118
119                                               NULL);
120         talloc_free(tmp_ctx);
121
122         NT_STATUS_HAVE_NO_MEMORY(*sd);
123
124         return NT_STATUS_OK;
125 }
126
127
128 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call, 
129                                       TALLOC_CTX *mem_ctx,
130                                       struct lsa_EnumAccountRights *r);
131
132 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call, 
133                                            TALLOC_CTX *mem_ctx,
134                                            struct lsa_policy_state *state,
135                                            int ldb_flag,
136                                            struct dom_sid *sid,
137                                            const struct lsa_RightSet *rights);
138
139 /* 
140   lsa_Close 
141 */
142 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
143                           struct lsa_Close *r)
144 {
145         struct dcesrv_handle *h;
146
147         *r->out.handle = *r->in.handle;
148
149         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
150
151         talloc_free(h);
152
153         ZERO_STRUCTP(r->out.handle);
154
155         return NT_STATUS_OK;
156 }
157
158
159 /* 
160   lsa_Delete 
161 */
162 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
163                            struct lsa_Delete *r)
164 {
165         return NT_STATUS_NOT_SUPPORTED;
166 }
167
168
169 /* 
170   lsa_DeleteObject
171 */
172 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
173                        struct lsa_DeleteObject *r)
174 {
175         struct dcesrv_handle *h;
176         int ret;
177
178         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
179
180         if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
181                 struct lsa_secret_state *secret_state = h->data;
182
183                 /* Ensure user is permitted to delete this... */
184                 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
185                 {
186                 case SECURITY_SYSTEM:
187                 case SECURITY_ADMINISTRATOR:
188                         break;
189                 default:
190                         /* Users and anonymous are not allowed to delete things */
191                         return NT_STATUS_ACCESS_DENIED;
192                 }
193
194                 ret = ldb_delete(secret_state->sam_ldb, 
195                                  secret_state->secret_dn);
196                 if (ret != LDB_SUCCESS) {
197                         return NT_STATUS_INVALID_HANDLE;
198                 }
199
200                 ZERO_STRUCTP(r->out.handle);
201
202                 return NT_STATUS_OK;
203
204         } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
205                 struct lsa_trusted_domain_state *trusted_domain_state = 
206                         talloc_get_type(h->data, struct lsa_trusted_domain_state);
207                 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
208                 if (ret != LDB_SUCCESS) {
209                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
210                 }
211
212                 ret = ldb_delete(trusted_domain_state->policy->sam_ldb, 
213                                  trusted_domain_state->trusted_domain_dn);
214                 if (ret != LDB_SUCCESS) {
215                         ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
216                         return NT_STATUS_INVALID_HANDLE;
217                 }
218
219                 if (trusted_domain_state->trusted_domain_user_dn) {
220                         ret = ldb_delete(trusted_domain_state->policy->sam_ldb, 
221                                          trusted_domain_state->trusted_domain_user_dn);
222                         if (ret != LDB_SUCCESS) {
223                                 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
224                                 return NT_STATUS_INVALID_HANDLE;
225                         }
226                 }
227
228                 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
229                 if (ret != LDB_SUCCESS) {
230                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
231                 }
232
233                 ZERO_STRUCTP(r->out.handle);
234
235                 return NT_STATUS_OK;
236
237         } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
238                 struct lsa_RightSet *rights;
239                 struct lsa_account_state *astate;
240                 struct lsa_EnumAccountRights r2;
241                 NTSTATUS status;
242
243                 rights = talloc(mem_ctx, struct lsa_RightSet);
244
245                 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
246                 
247                 astate = h->data;
248
249                 r2.in.handle = &astate->policy->handle->wire_handle;
250                 r2.in.sid = astate->account_sid;
251                 r2.out.rights = rights;
252
253                 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
254                    but we have a LSA_HANDLE_ACCOUNT here, so this call
255                    will always fail */
256                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
257                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
258                         return NT_STATUS_OK;
259                 }
260
261                 if (!NT_STATUS_IS_OK(status)) {
262                         return status;
263                 }
264
265                 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
266                                                     LDB_FLAG_MOD_DELETE, astate->account_sid,
267                                                     r2.out.rights);
268                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
269                         return NT_STATUS_OK;
270                 }
271
272                 if (!NT_STATUS_IS_OK(status)) {
273                         return status;
274                 }
275
276                 ZERO_STRUCTP(r->out.handle);
277
278                 return NT_STATUS_OK;
279         } 
280         
281         return NT_STATUS_INVALID_HANDLE;
282 }
283
284
285 /* 
286   lsa_EnumPrivs 
287 */
288 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
289                               struct lsa_EnumPrivs *r)
290 {
291         struct dcesrv_handle *h;
292         struct lsa_policy_state *state;
293         uint32_t i;
294         const char *privname;
295
296         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
297
298         state = h->data;
299
300         i = *r->in.resume_handle;
301         if (i == 0) i = 1;
302
303         while ((privname = sec_privilege_name(i)) &&
304                r->out.privs->count < r->in.max_count) {
305                 struct lsa_PrivEntry *e;
306
307                 r->out.privs->privs = talloc_realloc(r->out.privs,
308                                                        r->out.privs->privs, 
309                                                        struct lsa_PrivEntry, 
310                                                        r->out.privs->count+1);
311                 if (r->out.privs->privs == NULL) {
312                         return NT_STATUS_NO_MEMORY;
313                 }
314                 e = &r->out.privs->privs[r->out.privs->count];
315                 e->luid.low = i;
316                 e->luid.high = 0;
317                 e->name.string = privname;
318                 r->out.privs->count++;
319                 i++;
320         }
321
322         *r->out.resume_handle = i;
323
324         return NT_STATUS_OK;
325 }
326
327
328 /* 
329   lsa_QuerySecObj 
330 */
331 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
332                                          struct lsa_QuerySecurity *r)
333 {
334         struct dcesrv_handle *h;
335         struct security_descriptor *sd;
336         NTSTATUS status;
337         struct dom_sid *sid;
338
339         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
340
341         sid = dce_call->conn->auth_state.session_info->security_token->user_sid;
342
343         if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
344                 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid, 0);
345         } else  if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
346                 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid, 
347                                              LSA_ACCOUNT_ALL_ACCESS);
348         } else {
349                 return NT_STATUS_INVALID_HANDLE;
350         }
351         NT_STATUS_NOT_OK_RETURN(status);
352
353         (*r->out.sdbuf) = talloc(mem_ctx, struct sec_desc_buf);
354         NT_STATUS_HAVE_NO_MEMORY(*r->out.sdbuf);
355
356         (*r->out.sdbuf)->sd = sd;
357         
358         return NT_STATUS_OK;
359 }
360
361
362 /* 
363   lsa_SetSecObj 
364 */
365 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
366                               struct lsa_SetSecObj *r)
367 {
368         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
369 }
370
371
372 /* 
373   lsa_ChangePassword 
374 */
375 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
376                                    struct lsa_ChangePassword *r)
377 {
378         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
379 }
380
381 /* 
382   dssetup_DsRoleGetPrimaryDomainInformation 
383
384   This is not an LSA call, but is the only call left on the DSSETUP
385   pipe (after the pipe was truncated), and needs lsa_get_policy_state
386 */
387 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call, 
388                                                  TALLOC_CTX *mem_ctx,
389                                                  struct dssetup_DsRoleGetPrimaryDomainInformation *r)
390 {
391         union dssetup_DsRoleInfo *info;
392
393         info = talloc(mem_ctx, union dssetup_DsRoleInfo);
394         W_ERROR_HAVE_NO_MEMORY(info);
395
396         switch (r->in.level) {
397         case DS_ROLE_BASIC_INFORMATION:
398         {
399                 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
400                 uint32_t flags = 0;
401                 const char *domain = NULL;
402                 const char *dns_domain = NULL;
403                 const char *forest = NULL;
404                 struct GUID domain_guid;
405                 struct lsa_policy_state *state;
406
407                 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
408                 if (!NT_STATUS_IS_OK(status)) {
409                         return ntstatus_to_werror(status);
410                 }
411
412                 ZERO_STRUCT(domain_guid);
413
414                 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
415                 case ROLE_STANDALONE:
416                         role            = DS_ROLE_STANDALONE_SERVER;
417                         break;
418                 case ROLE_DOMAIN_MEMBER:
419                         role            = DS_ROLE_MEMBER_SERVER;
420                         break;
421                 case ROLE_DOMAIN_CONTROLLER:
422                         if (samdb_is_pdc(state->sam_ldb)) {
423                                 role    = DS_ROLE_PRIMARY_DC;
424                         } else {
425                                 role    = DS_ROLE_BACKUP_DC;
426                         }
427                         break;
428                 }
429
430                 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
431                 case ROLE_STANDALONE:
432                         domain          = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
433                         W_ERROR_HAVE_NO_MEMORY(domain);
434                         break;
435                 case ROLE_DOMAIN_MEMBER:
436                         domain          = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
437                         W_ERROR_HAVE_NO_MEMORY(domain);
438                         /* TODO: what is with dns_domain and forest and guid? */
439                         break;
440                 case ROLE_DOMAIN_CONTROLLER:
441                         flags           = DS_ROLE_PRIMARY_DS_RUNNING;
442
443                         if (state->mixed_domain == 1) {
444                                 flags   |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
445                         }
446                         
447                         domain          = state->domain_name;
448                         dns_domain      = state->domain_dns;
449                         forest          = state->forest_dns;
450
451                         domain_guid     = state->domain_guid;
452                         flags   |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
453                         break;
454                 }
455
456                 info->basic.role        = role; 
457                 info->basic.flags       = flags;
458                 info->basic.domain      = domain;
459                 info->basic.dns_domain  = dns_domain;
460                 info->basic.forest      = forest;
461                 info->basic.domain_guid = domain_guid;
462
463                 r->out.info = info;
464                 return WERR_OK;
465         }
466         case DS_ROLE_UPGRADE_STATUS:
467         {
468                 info->upgrade.upgrading     = DS_ROLE_NOT_UPGRADING;
469                 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
470
471                 r->out.info = info;
472                 return WERR_OK;
473         }
474         case DS_ROLE_OP_STATUS:
475         {
476                 info->opstatus.status = DS_ROLE_OP_IDLE;
477
478                 r->out.info = info;
479                 return WERR_OK;
480         }
481         default:
482                 return WERR_INVALID_PARAM;
483         }
484 }
485
486 /*
487   fill in the AccountDomain info
488 */
489 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
490                                        struct lsa_DomainInfo *info)
491 {
492         info->name.string = state->domain_name;
493         info->sid         = state->domain_sid;
494
495         return NT_STATUS_OK;
496 }
497
498 /*
499   fill in the DNS domain info
500 */
501 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
502                              struct lsa_DnsDomainInfo *info)
503 {
504         info->name.string = state->domain_name;
505         info->sid         = state->domain_sid;
506         info->dns_domain.string = state->domain_dns;
507         info->dns_forest.string = state->forest_dns;
508         info->domain_guid       = state->domain_guid;
509
510         return NT_STATUS_OK;
511 }
512
513 /* 
514   lsa_QueryInfoPolicy2
515 */
516 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
517                                      struct lsa_QueryInfoPolicy2 *r)
518 {
519         struct lsa_policy_state *state;
520         struct dcesrv_handle *h;
521         union lsa_PolicyInformation *info;
522
523         *r->out.info = NULL;
524
525         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
526
527         state = h->data;
528
529         info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
530         if (!info) {
531                 return NT_STATUS_NO_MEMORY;
532         }
533         *r->out.info = info;
534
535         switch (r->in.level) {
536         case LSA_POLICY_INFO_AUDIT_LOG:
537                 /* we don't need to fill in any of this */
538                 ZERO_STRUCT(info->audit_log);
539                 return NT_STATUS_OK;
540         case LSA_POLICY_INFO_AUDIT_EVENTS:
541                 /* we don't need to fill in any of this */
542                 ZERO_STRUCT(info->audit_events);
543                 return NT_STATUS_OK;
544         case LSA_POLICY_INFO_PD:
545                 /* we don't need to fill in any of this */
546                 ZERO_STRUCT(info->pd);
547                 return NT_STATUS_OK;
548
549         case LSA_POLICY_INFO_DOMAIN:
550                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
551         case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
552                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
553         case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
554                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
555
556         case LSA_POLICY_INFO_ROLE:
557                 info->role.role = LSA_ROLE_PRIMARY;
558                 return NT_STATUS_OK;
559
560         case LSA_POLICY_INFO_DNS:
561         case LSA_POLICY_INFO_DNS_INT:
562                 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
563
564         case LSA_POLICY_INFO_REPLICA:
565                 ZERO_STRUCT(info->replica);
566                 return NT_STATUS_OK;
567
568         case LSA_POLICY_INFO_QUOTA:
569                 ZERO_STRUCT(info->quota);
570                 return NT_STATUS_OK;
571
572         case LSA_POLICY_INFO_MOD:
573         case LSA_POLICY_INFO_AUDIT_FULL_SET:
574         case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
575                 /* windows gives INVALID_PARAMETER */
576                 *r->out.info = NULL;
577                 return NT_STATUS_INVALID_PARAMETER;
578         }
579
580         *r->out.info = NULL;
581         return NT_STATUS_INVALID_INFO_CLASS;
582 }
583
584 /* 
585   lsa_QueryInfoPolicy 
586 */
587 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
588                                     struct lsa_QueryInfoPolicy *r)
589 {
590         struct lsa_QueryInfoPolicy2 r2;
591         NTSTATUS status;
592
593         ZERO_STRUCT(r2);
594
595         r2.in.handle = r->in.handle;
596         r2.in.level = r->in.level;
597         r2.out.info = r->out.info;
598         
599         status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
600
601         return status;
602 }
603
604 /* 
605   lsa_SetInfoPolicy 
606 */
607 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
608                                   struct lsa_SetInfoPolicy *r)
609 {
610         /* need to support this */
611         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
612 }
613
614
615 /* 
616   lsa_ClearAuditLog 
617 */
618 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
619                                   struct lsa_ClearAuditLog *r)
620 {
621         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
622 }
623
624
625 /* 
626   lsa_CreateAccount 
627
628   This call does not seem to have any long-term effects, hence no database operations
629
630   we need to talk to the MS product group to find out what this account database means!
631
632   answer is that the lsa database is totally separate from the SAM and
633   ldap databases. We are going to need a separate ldb to store these
634   accounts. The SIDs on this account bear no relation to the SIDs in
635   AD
636 */
637 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
638                                   struct lsa_CreateAccount *r)
639 {
640         struct lsa_account_state *astate;
641
642         struct lsa_policy_state *state;
643         struct dcesrv_handle *h, *ah;
644
645         ZERO_STRUCTP(r->out.acct_handle);
646
647         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
648
649         state = h->data;
650
651         astate = talloc(dce_call->conn, struct lsa_account_state);
652         if (astate == NULL) {
653                 return NT_STATUS_NO_MEMORY;
654         }
655
656         astate->account_sid = dom_sid_dup(astate, r->in.sid);
657         if (astate->account_sid == NULL) {
658                 talloc_free(astate);
659                 return NT_STATUS_NO_MEMORY;
660         }
661         
662         astate->policy = talloc_reference(astate, state);
663         astate->access_mask = r->in.access_mask;
664
665         ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
666         if (!ah) {
667                 talloc_free(astate);
668                 return NT_STATUS_NO_MEMORY;
669         }
670
671         ah->data = talloc_steal(ah, astate);
672
673         *r->out.acct_handle = ah->wire_handle;
674
675         return NT_STATUS_OK;
676 }
677
678
679 /* 
680   lsa_EnumAccounts 
681 */
682 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
683                                  struct lsa_EnumAccounts *r)
684 {
685         struct dcesrv_handle *h;
686         struct lsa_policy_state *state;
687         int ret;
688         struct ldb_message **res;
689         const char * const attrs[] = { "objectSid", NULL};
690         uint32_t count, i;
691
692         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
693
694         state = h->data;
695
696         /* NOTE: This call must only return accounts that have at least
697            one privilege set 
698         */
699         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs, 
700                            "(&(objectSid=*)(privilege=*))");
701         if (ret < 0) {
702                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
703         }
704
705         if (*r->in.resume_handle >= ret) {
706                 return NT_STATUS_NO_MORE_ENTRIES;
707         }
708
709         count = ret - *r->in.resume_handle;
710         if (count > r->in.num_entries) {
711                 count = r->in.num_entries;
712         }
713
714         if (count == 0) {
715                 return NT_STATUS_NO_MORE_ENTRIES;
716         }
717
718         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
719         if (r->out.sids->sids == NULL) {
720                 return NT_STATUS_NO_MEMORY;
721         }
722
723         for (i=0;i<count;i++) {
724                 r->out.sids->sids[i].sid = 
725                         samdb_result_dom_sid(r->out.sids->sids, 
726                                              res[i + *r->in.resume_handle],
727                                              "objectSid");
728                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
729         }
730
731         r->out.sids->num_sids = count;
732         *r->out.resume_handle = count + *r->in.resume_handle;
733
734         return NT_STATUS_OK;
735         
736 }
737
738 /* This decrypts and returns Trusted Domain Auth Information Internal data */
739 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
740                                        TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
741                                        struct trustDomainPasswords *auth_struct)
742 {
743         DATA_BLOB session_key = data_blob(NULL, 0);
744         enum ndr_err_code ndr_err;
745         NTSTATUS nt_status;
746
747         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
748         if (!NT_STATUS_IS_OK(nt_status)) {
749                 return nt_status;
750         }
751
752         arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
753         ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
754                                        auth_struct,
755                                        (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
756         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
757                 return NT_STATUS_INVALID_PARAMETER;
758         }
759
760         return NT_STATUS_OK;
761 }
762
763 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
764                                          TALLOC_CTX *mem_ctx,
765                                          struct trustCurrentPasswords *iopw,
766                                          DATA_BLOB *trustauth_blob)
767 {
768         uint32_t i;
769         struct trustAuthInOutBlob ioblob;
770         enum ndr_err_code ndr_err;
771
772         ioblob.count = iopw->count;
773         ioblob.current = talloc(mem_ctx,
774                                 struct AuthenticationInformationArray);
775         if (!ioblob.current) {
776                 return NT_STATUS_NO_MEMORY;
777         }
778
779         ioblob.current->array = *iopw->current;
780         if (!ioblob.current->array) {
781                 return NT_STATUS_NO_MEMORY;
782         }
783
784         ioblob.previous = talloc(mem_ctx,
785                                  struct AuthenticationInformationArray);
786         if (!ioblob.previous) {
787                 return NT_STATUS_NO_MEMORY;
788         }
789         ioblob.previous->array = talloc_array(mem_ctx,
790                                         struct AuthenticationInformation,
791                                         ioblob.count);
792         if (!ioblob.previous->array) {
793                 return NT_STATUS_NO_MEMORY;
794         }
795
796         for (i = 0; i < ioblob.count; i++) {
797                 ioblob.previous->array[i].LastUpdateTime = 0;
798                 ioblob.previous->array[i].AuthType = 0;
799         }
800         ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
801                                        &ioblob,
802                                        (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
803         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
804                 return NT_STATUS_INVALID_PARAMETER;
805         }
806
807         return NT_STATUS_OK;
808 }
809
810 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
811                                struct ldb_context *sam_ldb,
812                                struct ldb_dn *base_dn,
813                                const char *netbios_name,
814                                struct trustCurrentPasswords *in,
815                                struct ldb_dn **user_dn)
816 {
817         struct ldb_message *msg;
818         struct ldb_dn *dn;
819         uint32_t i;
820         int ret;
821
822         dn = ldb_dn_copy(mem_ctx, base_dn);
823         if (!dn) {
824                 return NT_STATUS_NO_MEMORY;
825         }
826         if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
827                 return NT_STATUS_NO_MEMORY;
828         }
829
830         msg = ldb_msg_new(mem_ctx);
831         if (!msg) {
832                 return NT_STATUS_NO_MEMORY;
833         }
834         msg->dn = dn;
835
836         ret = ldb_msg_add_string(msg, "objectClass", "user");
837         if (ret != LDB_SUCCESS) {
838                 return NT_STATUS_NO_MEMORY;
839         }
840
841         ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
842         if (ret != LDB_SUCCESS) {
843                 return NT_STATUS_NO_MEMORY;
844         }
845
846         ret = ldb_msg_add_fmt(msg, "userAccountControl", "%u",
847                               UF_INTERDOMAIN_TRUST_ACCOUNT);
848         if (ret != LDB_SUCCESS) {
849                 return NT_STATUS_NO_MEMORY;
850         }
851
852         for (i = 0; i < in->count; i++) {
853                 const char *attribute;
854                 struct ldb_val v;
855                 switch (in->current[i]->AuthType) {
856                 case TRUST_AUTH_TYPE_NT4OWF:
857                         attribute = "unicodePwd";
858                         v.data = (uint8_t *)&in->current[i]->AuthInfo.nt4owf.password;
859                         v.length = 16;
860                         break;
861                 case TRUST_AUTH_TYPE_CLEAR:
862                         attribute = "clearTextPassword";
863                         v.data = in->current[i]->AuthInfo.clear.password;
864                         v.length = in->current[i]->AuthInfo.clear.size;
865                         break;
866                 default:
867                         continue;
868                 }
869
870                 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
871                 if (ret != LDB_SUCCESS) {
872                         return NT_STATUS_NO_MEMORY;
873                 }
874         }
875
876         /* create the trusted_domain user account */
877         ret = ldb_add(sam_ldb, msg);
878         if (ret != LDB_SUCCESS) {
879                 DEBUG(0,("Failed to create user record %s: %s\n",
880                          ldb_dn_get_linearized(msg->dn),
881                          ldb_errstring(sam_ldb)));
882
883                 switch (ret) {
884                 case LDB_ERR_ENTRY_ALREADY_EXISTS:
885                         return NT_STATUS_DOMAIN_EXISTS;
886                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
887                         return NT_STATUS_ACCESS_DENIED;
888                 default:
889                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
890                 }
891         }
892
893         if (user_dn) {
894                 *user_dn = dn;
895         }
896         return NT_STATUS_OK;
897 }
898
899 /*
900   lsa_CreateTrustedDomainEx2
901 */
902 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
903                                                     TALLOC_CTX *mem_ctx,
904                                                     struct lsa_CreateTrustedDomainEx2 *r,
905                                                     int op)
906 {
907         struct dcesrv_handle *policy_handle;
908         struct lsa_policy_state *policy_state;
909         struct lsa_trusted_domain_state *trusted_domain_state;
910         struct dcesrv_handle *handle;
911         struct ldb_message **msgs, *msg;
912         const char *attrs[] = {
913                 NULL
914         };
915         const char *netbios_name;
916         const char *dns_name;
917         const char *name;
918         DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
919         struct trustDomainPasswords auth_struct;
920         int ret;
921         NTSTATUS nt_status;
922         struct ldb_context *sam_ldb;
923
924         DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
925         ZERO_STRUCTP(r->out.trustdom_handle);
926
927         policy_state = policy_handle->data;
928         sam_ldb = policy_state->sam_ldb;
929
930         netbios_name = r->in.info->netbios_name.string;
931         if (!netbios_name) {
932                 return NT_STATUS_INVALID_PARAMETER;
933         }
934
935         dns_name = r->in.info->domain_name.string;
936
937         trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
938         if (!trusted_domain_state) {
939                 return NT_STATUS_NO_MEMORY;
940         }
941         trusted_domain_state->policy = policy_state;
942
943         if (strcasecmp(netbios_name, "BUILTIN") == 0
944             || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0)
945             || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
946                 return NT_STATUS_INVALID_PARAMETER;
947         }
948
949         if (strcasecmp(netbios_name, policy_state->domain_name) == 0
950             || strcasecmp(netbios_name, policy_state->domain_dns) == 0
951             || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0)
952             || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0)
953             || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
954                 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
955         }
956
957         /* While this is a REF pointer, some of the functions that wrap this don't provide this */
958         if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
959                 /* No secrets are created at this time, for this function */
960                 auth_struct.outgoing.count = 0;
961                 auth_struct.incoming.count = 0;
962         } else {
963                 auth_blob = data_blob_const(r->in.auth_info->auth_blob.data,
964                                             r->in.auth_info->auth_blob.size);
965                 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
966                                                    &auth_blob, &auth_struct);
967                 if (!NT_STATUS_IS_OK(nt_status)) {
968                         return nt_status;
969                 }
970
971                 if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
972                         if (auth_struct.incoming.count > 1) {
973                                 return NT_STATUS_INVALID_PARAMETER;
974                         }
975                 }
976         }
977
978         if (auth_struct.incoming.count) {
979                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
980                                                      &auth_struct.incoming,
981                                                      &trustAuthIncoming);
982                 if (!NT_STATUS_IS_OK(nt_status)) {
983                         return nt_status;
984                 }
985         } else {
986                 trustAuthIncoming = data_blob(NULL, 0);
987         }
988
989         if (auth_struct.outgoing.count) {
990                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
991                                                      &auth_struct.outgoing,
992                                                      &trustAuthOutgoing);
993                 if (!NT_STATUS_IS_OK(nt_status)) {
994                         return nt_status;
995                 }
996         } else {
997                 trustAuthOutgoing = data_blob(NULL, 0);
998         }
999
1000         ret = ldb_transaction_start(sam_ldb);
1001         if (ret != LDB_SUCCESS) {
1002                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1003         }
1004
1005         if (dns_name) {
1006                 char *dns_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1007                 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1008                 /* search for the trusted_domain record */
1009                 ret = gendb_search(sam_ldb,
1010                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
1011                                    "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1012                                    dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded);
1013                 if (ret > 0) {
1014                         ldb_transaction_cancel(sam_ldb);
1015                         return NT_STATUS_OBJECT_NAME_COLLISION;
1016                 }
1017         } else {
1018                 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1019                 /* search for the trusted_domain record */
1020                 ret = gendb_search(sam_ldb,
1021                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
1022                                    "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1023                                    netbios_encoded, netbios_encoded, netbios_encoded);
1024                 if (ret > 0) {
1025                         ldb_transaction_cancel(sam_ldb);
1026                         return NT_STATUS_OBJECT_NAME_COLLISION;
1027                 }
1028         }
1029
1030         if (ret < 0 ) {
1031                 ldb_transaction_cancel(sam_ldb);
1032                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1033         }
1034
1035         name = dns_name ? dns_name : netbios_name;
1036
1037         msg = ldb_msg_new(mem_ctx);
1038         if (msg == NULL) {
1039                 return NT_STATUS_NO_MEMORY;
1040         }
1041
1042         msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1043         if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
1044                         ldb_transaction_cancel(sam_ldb);
1045                 return NT_STATUS_NO_MEMORY;
1046         }
1047
1048         samdb_msg_add_string(sam_ldb, mem_ctx, msg, "flatname", netbios_name);
1049
1050         if (r->in.info->sid) {
1051                 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier", r->in.info->sid);
1052                 if (ret != LDB_SUCCESS) {
1053                         ldb_transaction_cancel(sam_ldb);
1054                         return NT_STATUS_INVALID_PARAMETER;
1055                 }
1056         }
1057
1058         samdb_msg_add_string(sam_ldb, mem_ctx, msg, "objectClass", "trustedDomain");
1059
1060         samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1061
1062         samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1063
1064         samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1065
1066         if (dns_name) {
1067                 samdb_msg_add_string(sam_ldb, mem_ctx, msg, "trustPartner", dns_name);
1068         }
1069
1070         if (trustAuthIncoming.data) {
1071                 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1072                 if (ret != LDB_SUCCESS) {
1073                         ldb_transaction_cancel(sam_ldb);
1074                         return NT_STATUS_NO_MEMORY;
1075                 }
1076         }
1077         if (trustAuthOutgoing.data) {
1078                 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1079                 if (ret != LDB_SUCCESS) {
1080                         ldb_transaction_cancel(sam_ldb);
1081                         return NT_STATUS_NO_MEMORY;
1082                 }
1083         }
1084
1085         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1086
1087         /* create the trusted_domain */
1088         ret = dsdb_add(sam_ldb, msg, DSDB_MODIFY_RELAX);
1089         switch (ret) {
1090         case  LDB_SUCCESS:
1091                 break;
1092         case  LDB_ERR_ENTRY_ALREADY_EXISTS:
1093                 ldb_transaction_cancel(sam_ldb);
1094                 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1095                          ldb_dn_get_linearized(msg->dn),
1096                          ldb_errstring(sam_ldb)));
1097                 return NT_STATUS_DOMAIN_EXISTS;
1098         case  LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1099                 ldb_transaction_cancel(sam_ldb);
1100                 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1101                          ldb_dn_get_linearized(msg->dn),
1102                          ldb_errstring(sam_ldb)));
1103                 return NT_STATUS_ACCESS_DENIED;
1104         default:
1105                 ldb_transaction_cancel(sam_ldb);
1106                 DEBUG(0,("Failed to create user record %s: %s\n",
1107                          ldb_dn_get_linearized(msg->dn),
1108                          ldb_errstring(sam_ldb)));
1109                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1110         }
1111
1112         if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1113                 struct ldb_dn *user_dn;
1114                 /* Inbound trusts must also create a cn=users object to match */
1115                 nt_status = add_trust_user(mem_ctx, sam_ldb,
1116                                            policy_state->domain_dn,
1117                                            netbios_name,
1118                                            &auth_struct.incoming,
1119                                            &user_dn);
1120                 if (!NT_STATUS_IS_OK(nt_status)) {
1121                         ldb_transaction_cancel(sam_ldb);
1122                         return nt_status;
1123                 }
1124
1125                 /* save the trust user dn */
1126                 trusted_domain_state->trusted_domain_user_dn
1127                         = talloc_steal(trusted_domain_state, user_dn);
1128         }
1129
1130         ret = ldb_transaction_commit(sam_ldb);
1131         if (ret != LDB_SUCCESS) {
1132                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1133         }
1134
1135         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1136         if (!handle) {
1137                 return NT_STATUS_NO_MEMORY;
1138         }
1139
1140         handle->data = talloc_steal(handle, trusted_domain_state);
1141
1142         trusted_domain_state->access_mask = r->in.access_mask;
1143         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1144
1145         *r->out.trustdom_handle = handle->wire_handle;
1146
1147         return NT_STATUS_OK;
1148 }
1149
1150 /*
1151   lsa_CreateTrustedDomainEx2
1152 */
1153 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1154                                            TALLOC_CTX *mem_ctx,
1155                                            struct lsa_CreateTrustedDomainEx2 *r)
1156 {
1157         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2);
1158 }
1159 /*
1160   lsa_CreateTrustedDomainEx
1161 */
1162 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1163                                           TALLOC_CTX *mem_ctx,
1164                                           struct lsa_CreateTrustedDomainEx *r)
1165 {
1166         struct lsa_CreateTrustedDomainEx2 r2;
1167
1168         r2.in.policy_handle = r->in.policy_handle;
1169         r2.in.info = r->in.info;
1170         r2.in.auth_info = r->in.auth_info;
1171         r2.out.trustdom_handle = r->out.trustdom_handle;
1172         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX);
1173 }
1174
1175 /* 
1176   lsa_CreateTrustedDomain 
1177 */
1178 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1179                                         struct lsa_CreateTrustedDomain *r)
1180 {
1181         struct lsa_CreateTrustedDomainEx2 r2;
1182
1183         r2.in.policy_handle = r->in.policy_handle;
1184         r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1185         if (!r2.in.info) {
1186                 return NT_STATUS_NO_MEMORY;
1187         }
1188
1189         r2.in.info->domain_name.string = NULL;
1190         r2.in.info->netbios_name = r->in.info->name;
1191         r2.in.info->sid = r->in.info->sid;
1192         r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1193         r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1194         r2.in.info->trust_attributes = 0;
1195         
1196         r2.in.access_mask = r->in.access_mask;
1197         r2.out.trustdom_handle = r->out.trustdom_handle;
1198
1199         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN);
1200                          
1201 }
1202
1203 /* 
1204   lsa_OpenTrustedDomain
1205 */
1206 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1207                                       struct lsa_OpenTrustedDomain *r)
1208 {
1209         struct dcesrv_handle *policy_handle;
1210         
1211         struct lsa_policy_state *policy_state;
1212         struct lsa_trusted_domain_state *trusted_domain_state;
1213         struct dcesrv_handle *handle;
1214         struct ldb_message **msgs;
1215         const char *attrs[] = {
1216                 "trustDirection",
1217                 "flatname",
1218                 NULL
1219         };
1220
1221         const char *sid_string;
1222         int ret;
1223
1224         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1225         ZERO_STRUCTP(r->out.trustdom_handle);
1226         policy_state = policy_handle->data;
1227
1228         trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1229         if (!trusted_domain_state) {
1230                 return NT_STATUS_NO_MEMORY;
1231         }
1232         trusted_domain_state->policy = policy_state;
1233
1234         sid_string = dom_sid_string(mem_ctx, r->in.sid);
1235         if (!sid_string) {
1236                 return NT_STATUS_NO_MEMORY;
1237         }
1238
1239         /* search for the trusted_domain record */
1240         ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1241                            mem_ctx, policy_state->system_dn, &msgs, attrs,
1242                            "(&(securityIdentifier=%s)(objectclass=trustedDomain))", 
1243                            sid_string);
1244         if (ret == 0) {
1245                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1246         }
1247         
1248         if (ret != 1) {
1249                 DEBUG(0,("Found %d records matching DN %s\n", ret,
1250                          ldb_dn_get_linearized(policy_state->system_dn)));
1251                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1252         }
1253
1254         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1255
1256         trusted_domain_state->trusted_domain_user_dn = NULL;
1257
1258         if (ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0) & LSA_TRUST_DIRECTION_INBOUND) {
1259                 const char *flatname = ldb_binary_encode_string(mem_ctx, ldb_msg_find_attr_as_string(msgs[0], "flatname", NULL));
1260                 /* search for the trusted_domain record */
1261                 ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1262                                    mem_ctx, policy_state->domain_dn, &msgs, attrs,
1263                                    "(&(samaccountname=%s$)(objectclass=user)(userAccountControl:1.2.840.113556.1.4.803:=%d))", 
1264                                    flatname, UF_INTERDOMAIN_TRUST_ACCOUNT);
1265                 if (ret == 1) {
1266                         trusted_domain_state->trusted_domain_user_dn = talloc_steal(trusted_domain_state, msgs[0]->dn);
1267                 }
1268         }
1269         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1270         if (!handle) {
1271                 return NT_STATUS_NO_MEMORY;
1272         }
1273         
1274         handle->data = talloc_steal(handle, trusted_domain_state);
1275         
1276         trusted_domain_state->access_mask = r->in.access_mask;
1277         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1278         
1279         *r->out.trustdom_handle = handle->wire_handle;
1280         
1281         return NT_STATUS_OK;
1282 }
1283
1284
1285 /*
1286   lsa_OpenTrustedDomainByName
1287 */
1288 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1289                                             TALLOC_CTX *mem_ctx,
1290                                             struct lsa_OpenTrustedDomainByName *r)
1291 {
1292         struct dcesrv_handle *policy_handle;
1293
1294         struct lsa_policy_state *policy_state;
1295         struct lsa_trusted_domain_state *trusted_domain_state;
1296         struct dcesrv_handle *handle;
1297         struct ldb_message **msgs;
1298         const char *attrs[] = {
1299                 NULL
1300         };
1301         char *td_name;
1302         int ret;
1303
1304         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1305         ZERO_STRUCTP(r->out.trustdom_handle);
1306         policy_state = policy_handle->data;
1307
1308         if (!r->in.name.string) {
1309                 return NT_STATUS_INVALID_PARAMETER;
1310         }
1311
1312         trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1313         if (!trusted_domain_state) {
1314                 return NT_STATUS_NO_MEMORY;
1315         }
1316         trusted_domain_state->policy = policy_state;
1317
1318         /* search for the trusted_domain record */
1319         td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1320         ret = gendb_search(trusted_domain_state->policy->sam_ldb,
1321                            mem_ctx, policy_state->system_dn, &msgs, attrs,
1322                            "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1323                              "(objectclass=trustedDomain))",
1324                            td_name, td_name, td_name);
1325         if (ret == 0) {
1326                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1327         }
1328
1329         if (ret != 1) {
1330                 DEBUG(0,("Found %d records matching DN %s\n", ret,
1331                          ldb_dn_get_linearized(policy_state->system_dn)));
1332                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1333         }
1334
1335         /* TODO: perform access checks */
1336
1337         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msgs[0]->dn);
1338
1339         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1340         if (!handle) {
1341                 return NT_STATUS_NO_MEMORY;
1342         }
1343
1344         handle->data = talloc_steal(handle, trusted_domain_state);
1345
1346         trusted_domain_state->access_mask = r->in.access_mask;
1347         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1348
1349         *r->out.trustdom_handle = handle->wire_handle;
1350
1351         return NT_STATUS_OK;
1352 }
1353
1354
1355
1356 /* 
1357   lsa_SetTrustedDomainInfo
1358 */
1359 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1360                                          struct lsa_SetTrustedDomainInfo *r)
1361 {
1362         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1363 }
1364
1365
1366
1367 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1368  * otherwise at least one must be provided */
1369 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1370                         struct ldb_dn *basedn, const char *dns_domain,
1371                         const char *netbios, struct dom_sid2 *sid,
1372                         struct ldb_message ***msgs)
1373 {
1374         const char *attrs[] = { "flatname", "trustPartner",
1375                                 "securityIdentifier", "trustDirection",
1376                                 "trustType", "trustAttributes",
1377                                 "trustPosixOffset",
1378                                 "msDs-supportedEncryptionTypes", NULL };
1379         char *dns = NULL;
1380         char *nbn = NULL;
1381         char *sidstr = NULL;
1382         char *filter;
1383         int ret;
1384
1385
1386         if (dns_domain || netbios || sid) {
1387                 filter = talloc_strdup(mem_ctx,
1388                                    "(&(objectclass=trustedDomain)(|");
1389         } else {
1390                 filter = talloc_strdup(mem_ctx,
1391                                        "(objectclass=trustedDomain)");
1392         }
1393         if (!filter) {
1394                 return NT_STATUS_NO_MEMORY;
1395         }
1396
1397         if (dns_domain) {
1398                 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1399                 if (!dns) {
1400                         return NT_STATUS_NO_MEMORY;
1401                 }
1402                 filter = talloc_asprintf_append(filter,
1403                                                 "(trustPartner=%s)", dns);
1404                 if (!filter) {
1405                         return NT_STATUS_NO_MEMORY;
1406                 }
1407         }
1408         if (netbios) {
1409                 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1410                 if (!nbn) {
1411                         return NT_STATUS_NO_MEMORY;
1412                 }
1413                 filter = talloc_asprintf_append(filter,
1414                                                 "(flatname=%s)", nbn);
1415                 if (!filter) {
1416                         return NT_STATUS_NO_MEMORY;
1417                 }
1418         }
1419         if (sid) {
1420                 sidstr = dom_sid_string(mem_ctx, sid);
1421                 if (!sidstr) {
1422                         return NT_STATUS_INVALID_PARAMETER;
1423                 }
1424                 filter = talloc_asprintf_append(filter,
1425                                                 "(securityIdentifier=%s)",
1426                                                 sidstr);
1427                 if (!filter) {
1428                         return NT_STATUS_NO_MEMORY;
1429                 }
1430         }
1431         if (dns_domain || netbios || sid) {
1432                 filter = talloc_asprintf_append(filter, "))");
1433                 if (!filter) {
1434                         return NT_STATUS_NO_MEMORY;
1435                 }
1436         }
1437
1438         ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1439         if (ret == 0) {
1440                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1441         }
1442
1443         if (ret != 1) {
1444                 return NT_STATUS_OBJECT_NAME_COLLISION;
1445         }
1446
1447         return NT_STATUS_OK;
1448 }
1449
1450 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1451                                       struct ldb_message *orig,
1452                                       struct ldb_message *dest,
1453                                       const char *attribute,
1454                                       uint32_t value,
1455                                       uint32_t *orig_value)
1456 {
1457         const struct ldb_val *orig_val;
1458         uint32_t orig_uint = 0;
1459         char *str_val;
1460         int flags = 0;
1461         int ret;
1462
1463         orig_val = ldb_msg_find_ldb_val(orig, attribute);
1464         if (!orig_val || !orig_val->data) {
1465                 /* add new attribute */
1466                 flags = LDB_FLAG_MOD_ADD;
1467
1468         } else {
1469                 errno = 0;
1470                 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1471                 if (errno != 0 || orig_uint != value) {
1472                         /* replace also if can't get value */
1473                         flags = LDB_FLAG_MOD_REPLACE;
1474                 }
1475         }
1476
1477         if (flags == 0) {
1478                 /* stored value is identical, nothing to change */
1479                 goto done;
1480         }
1481
1482         ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1483         if (ret != LDB_SUCCESS) {
1484                 return NT_STATUS_NO_MEMORY;
1485         }
1486
1487         str_val = talloc_asprintf(mem_ctx, "%u", value);
1488         if (!str_val) {
1489                 return NT_STATUS_NO_MEMORY;
1490         }
1491         ret = ldb_msg_add_steal_string(dest, attribute, str_val);
1492         if (ret != LDB_SUCCESS) {
1493                 return NT_STATUS_NO_MEMORY;
1494         }
1495
1496 done:
1497         if (orig_value) {
1498                 *orig_value = orig_uint;
1499         }
1500         return NT_STATUS_OK;
1501 }
1502
1503 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1504                                   struct ldb_context *sam_ldb,
1505                                   struct ldb_dn *base_dn,
1506                                   bool delete_user,
1507                                   const char *netbios_name,
1508                                   struct trustCurrentPasswords *in)
1509 {
1510         const char *attrs[] = { "userAccountControl", NULL };
1511         struct ldb_message **msgs;
1512         struct ldb_message *msg;
1513         uint32_t uac;
1514         uint32_t i;
1515         int ret;
1516
1517         ret = gendb_search(sam_ldb, mem_ctx,
1518                            base_dn, &msgs, attrs,
1519                            "samAccountName=%s$", netbios_name);
1520         if (ret > 1) {
1521                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1522         }
1523
1524         if (ret == 0) {
1525                 if (delete_user) {
1526                         return NT_STATUS_OK;
1527                 }
1528
1529                 /* ok no existing user, add it from scratch */
1530                 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1531                                       netbios_name, in, NULL);
1532         }
1533
1534         /* check user is what we are looking for */
1535         uac = ldb_msg_find_attr_as_uint(msgs[0],
1536                                         "userAccountControl", 0);
1537         if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1538                 return NT_STATUS_OBJECT_NAME_COLLISION;
1539         }
1540
1541         if (delete_user) {
1542                 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1543                 switch (ret) {
1544                 case LDB_SUCCESS:
1545                         return NT_STATUS_OK;
1546                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1547                         return NT_STATUS_ACCESS_DENIED;
1548                 default:
1549                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1550                 }
1551         }
1552
1553         /* entry exists, just modify secret if any */
1554         if (in->count == 0) {
1555                 return NT_STATUS_OK;
1556         }
1557
1558         msg = ldb_msg_new(mem_ctx);
1559         if (!msg) {
1560                 return NT_STATUS_NO_MEMORY;
1561         }
1562         msg->dn = msgs[0]->dn;
1563
1564         for (i = 0; i < in->count; i++) {
1565                 const char *attribute;
1566                 struct ldb_val v;
1567                 switch (in->current[i]->AuthType) {
1568                 case TRUST_AUTH_TYPE_NT4OWF:
1569                         attribute = "unicodePwd";
1570                         v.data = (uint8_t *)&in->current[i]->AuthInfo.nt4owf.password;
1571                         v.length = 16;
1572                         break;
1573                 case TRUST_AUTH_TYPE_CLEAR:
1574                         attribute = "clearTextPassword";
1575                         v.data = in->current[i]->AuthInfo.clear.password;
1576                         v.length = in->current[i]->AuthInfo.clear.size;
1577                         break;
1578                 default:
1579                         continue;
1580                 }
1581
1582                 ret = ldb_msg_add_empty(msg, attribute,
1583                                         LDB_FLAG_MOD_REPLACE, NULL);
1584                 if (ret != LDB_SUCCESS) {
1585                         return NT_STATUS_NO_MEMORY;
1586                 }
1587
1588                 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1589                 if (ret != LDB_SUCCESS) {
1590                         return NT_STATUS_NO_MEMORY;
1591                 }
1592         }
1593
1594         /* create the trusted_domain user account */
1595         ret = ldb_modify(sam_ldb, msg);
1596         if (ret != LDB_SUCCESS) {
1597                 DEBUG(0,("Failed to create user record %s: %s\n",
1598                          ldb_dn_get_linearized(msg->dn),
1599                          ldb_errstring(sam_ldb)));
1600
1601                 switch (ret) {
1602                 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1603                         return NT_STATUS_DOMAIN_EXISTS;
1604                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1605                         return NT_STATUS_ACCESS_DENIED;
1606                 default:
1607                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1608                 }
1609         }
1610
1611         return NT_STATUS_OK;
1612 }
1613
1614
1615 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1616                                           struct dcesrv_handle *p_handle,
1617                                           TALLOC_CTX *mem_ctx,
1618                                           struct ldb_message *dom_msg,
1619                                           enum lsa_TrustDomInfoEnum level,
1620                                           union lsa_TrustedDomainInfo *info)
1621 {
1622         struct lsa_policy_state *p_state = p_handle->data;
1623         uint32_t *posix_offset = NULL;
1624         struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1625         struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1626         struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1627         uint32_t *enc_types = NULL;
1628         DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1629         struct trustDomainPasswords auth_struct;
1630         NTSTATUS nt_status;
1631         struct ldb_message **msgs;
1632         struct ldb_message *msg;
1633         bool add_outgoing = false;
1634         bool add_incoming = false;
1635         bool del_outgoing = false;
1636         bool del_incoming = false;
1637         bool in_transaction = false;
1638         int ret;
1639         bool am_rodc;
1640
1641         switch (level) {
1642         case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1643                 posix_offset = &info->posix_offset.posix_offset;
1644                 break;
1645         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1646                 info_ex = &info->info_ex;
1647                 break;
1648         case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1649                 auth_info = &info->auth_info;
1650                 break;
1651         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1652                 posix_offset = &info->full_info.posix_offset.posix_offset;
1653                 info_ex = &info->full_info.info_ex;
1654                 auth_info = &info->full_info.auth_info;
1655                 break;
1656         case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1657                 auth_info_int = &info->auth_info_internal;
1658                 break;
1659         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1660                 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1661                 info_ex = &info->full_info_internal.info_ex;
1662                 auth_info_int = &info->full_info_internal.auth_info;
1663                 break;
1664         case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1665                 enc_types = &info->enc_types.enc_types;
1666                 break;
1667         default:
1668                 return NT_STATUS_INVALID_PARAMETER;
1669         }
1670
1671         if (auth_info) {
1672                 /* FIXME: not handled yet */
1673                 return NT_STATUS_INVALID_PARAMETER;
1674         }
1675
1676         /* decode auth_info_int if set */
1677         if (auth_info_int) {
1678
1679                 /* now decrypt blob */
1680                 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1681                                             auth_info_int->auth_blob.size);
1682
1683                 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1684                                                    &auth_blob, &auth_struct);
1685                 if (!NT_STATUS_IS_OK(nt_status)) {
1686                         return nt_status;
1687                 }
1688         }
1689
1690         if (info_ex) {
1691                 /* verify data matches */
1692                 if (info_ex->trust_attributes &
1693                     LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1694                         /* TODO: check what behavior level we have */
1695                        if (strcasecmp_m(p_state->domain_dns,
1696                                         p_state->forest_dns) != 0) {
1697                                 return NT_STATUS_INVALID_DOMAIN_STATE;
1698                         }
1699                 }
1700
1701                 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1702                 if (ret == LDB_SUCCESS && am_rodc) {
1703                         return NT_STATUS_NO_SUCH_DOMAIN;
1704                 }
1705
1706                 /* verify only one object matches the dns/netbios/sid
1707                  * triplet and that this is the one we already have */
1708                 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1709                                     p_state->system_dn,
1710                                     info_ex->domain_name.string,
1711                                     info_ex->netbios_name.string,
1712                                     info_ex->sid, &msgs);
1713                 if (!NT_STATUS_IS_OK(nt_status)) {
1714                         return nt_status;
1715                 }
1716                 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1717                         return NT_STATUS_OBJECT_NAME_COLLISION;
1718                 }
1719                 talloc_free(msgs);
1720         }
1721
1722         /* TODO: should we fetch previous values from the existing entry
1723          * and append them ? */
1724         if (auth_struct.incoming.count) {
1725                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1726                                                      &auth_struct.incoming,
1727                                                      &trustAuthIncoming);
1728                 if (!NT_STATUS_IS_OK(nt_status)) {
1729                         return nt_status;
1730                 }
1731         } else {
1732                 trustAuthIncoming = data_blob(NULL, 0);
1733         }
1734
1735         if (auth_struct.outgoing.count) {
1736                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1737                                                      &auth_struct.outgoing,
1738                                                      &trustAuthOutgoing);
1739                 if (!NT_STATUS_IS_OK(nt_status)) {
1740                         return nt_status;
1741                 }
1742         } else {
1743                 trustAuthOutgoing = data_blob(NULL, 0);
1744         }
1745
1746         msg = ldb_msg_new(mem_ctx);
1747         if (msg == NULL) {
1748                 return NT_STATUS_NO_MEMORY;
1749         }
1750         msg->dn = dom_msg->dn;
1751
1752         if (posix_offset) {
1753                 nt_status = update_uint32_t_value(mem_ctx, dom_msg, msg,
1754                                                   "trustPosixOffset",
1755                                                   *posix_offset, NULL);
1756                 if (!NT_STATUS_IS_OK(nt_status)) {
1757                         return nt_status;
1758                 }
1759         }
1760
1761         if (info_ex) {
1762                 uint32_t origattrs;
1763                 uint32_t origdir;
1764                 uint32_t tmp;
1765                 int origtype;
1766
1767                 nt_status = update_uint32_t_value(mem_ctx, dom_msg, msg,
1768                                                   "trustDirection",
1769                                                   info_ex->trust_direction,
1770                                                   &origdir);
1771                 if (!NT_STATUS_IS_OK(nt_status)) {
1772                         return nt_status;
1773                 }
1774
1775                 tmp = info_ex->trust_direction ^ origdir;
1776                 if (tmp & LSA_TRUST_DIRECTION_INBOUND) {
1777                         if (origdir & LSA_TRUST_DIRECTION_INBOUND) {
1778                                 del_incoming = true;
1779                         } else {
1780                                 add_incoming = true;
1781                         }
1782                 }
1783                 if (tmp & LSA_TRUST_DIRECTION_OUTBOUND) {
1784                         if (origdir & LSA_TRUST_DIRECTION_OUTBOUND) {
1785                                 del_outgoing = true;
1786                         } else {
1787                                 add_outgoing = true;
1788                         }
1789                 }
1790
1791                 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
1792                 if (origtype == -1 || origtype != info_ex->trust_type) {
1793                         DEBUG(1, ("Attempted to change trust type! "
1794                                   "Operation not handled\n"));
1795                         return NT_STATUS_INVALID_PARAMETER;
1796                 }
1797
1798                 nt_status = update_uint32_t_value(mem_ctx, dom_msg, msg,
1799                                                   "trustAttributes",
1800                                                   info_ex->trust_attributes,
1801                                                   &origattrs);
1802                 if (!NT_STATUS_IS_OK(nt_status)) {
1803                         return nt_status;
1804                 }
1805                 /* TODO: check forestFunctionality from ldb opaque */
1806                 /* TODO: check what is set makes sense */
1807                 /* for now refuse changes */
1808                 if (origattrs == -1 ||
1809                     origattrs != info_ex->trust_attributes) {
1810                         DEBUG(1, ("Attempted to change trust attributes! "
1811                                   "Operation not handled\n"));
1812                         return NT_STATUS_INVALID_PARAMETER;
1813                 }
1814         }
1815
1816         if (enc_types) {
1817                 nt_status = update_uint32_t_value(mem_ctx, dom_msg, msg,
1818                                                   "msDS-SupportedEncryptionTypes",
1819                                                   *enc_types, NULL);
1820                 if (!NT_STATUS_IS_OK(nt_status)) {
1821                         return nt_status;
1822                 }
1823         }
1824
1825         if (add_incoming && trustAuthIncoming.data) {
1826                 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1827                                         LDB_FLAG_MOD_REPLACE, NULL);
1828                 if (ret != LDB_SUCCESS) {
1829                         return NT_STATUS_NO_MEMORY;
1830                 }
1831                 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
1832                                         &trustAuthIncoming, NULL);
1833                 if (ret != LDB_SUCCESS) {
1834                         return NT_STATUS_NO_MEMORY;
1835                 }
1836         }
1837         if (add_outgoing && trustAuthOutgoing.data) {
1838                 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1839                                         LDB_FLAG_MOD_REPLACE, NULL);
1840                 if (ret != LDB_SUCCESS) {
1841                         return NT_STATUS_NO_MEMORY;
1842                 }
1843                 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1844                                         &trustAuthOutgoing, NULL);
1845                 if (ret != LDB_SUCCESS) {
1846                         return NT_STATUS_NO_MEMORY;
1847                 }
1848         }
1849
1850         /* start transaction */
1851         ret = ldb_transaction_start(p_state->sam_ldb);
1852         if (ret != LDB_SUCCESS) {
1853                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1854         }
1855         in_transaction = true;
1856
1857         ret = ldb_modify(p_state->sam_ldb, msg);
1858         if (ret != LDB_SUCCESS) {
1859                 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1860                          ldb_dn_get_linearized(msg->dn),
1861                          ldb_errstring(p_state->sam_ldb)));
1862                 if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
1863                         nt_status = NT_STATUS_ACCESS_DENIED;
1864                 } else {
1865                         nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1866                 }
1867                 goto done;
1868         }
1869
1870         if (add_incoming || del_incoming) {
1871                 const char *netbios_name;
1872
1873                 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
1874                                                            "flatname", NULL);
1875                 if (!netbios_name) {
1876                         nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
1877                         goto done;
1878                 }
1879
1880                 nt_status = update_trust_user(mem_ctx,
1881                                               p_state->sam_ldb,
1882                                               p_state->domain_dn,
1883                                               del_incoming,
1884                                               netbios_name,
1885                                               &auth_struct.incoming);
1886                 if (!NT_STATUS_IS_OK(nt_status)) {
1887                         goto done;
1888                 }
1889         }
1890
1891         /* ok, all fine, commit transaction and return */
1892         ret = ldb_transaction_commit(p_state->sam_ldb);
1893         if (ret != LDB_SUCCESS) {
1894                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1895         }
1896         in_transaction = false;
1897
1898         nt_status = NT_STATUS_OK;
1899
1900 done:
1901         if (in_transaction) {
1902                 ldb_transaction_cancel(p_state->sam_ldb);
1903         }
1904         return nt_status;
1905 }
1906
1907 /*
1908   lsa_SetInfomrationTrustedDomain
1909 */
1910 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
1911                                 struct dcesrv_call_state *dce_call,
1912                                 TALLOC_CTX *mem_ctx,
1913                                 struct lsa_SetInformationTrustedDomain *r)
1914 {
1915         struct dcesrv_handle *h;
1916         struct lsa_trusted_domain_state *td_state;
1917         struct ldb_message **msgs;
1918         NTSTATUS nt_status;
1919
1920         DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
1921                            LSA_HANDLE_TRUSTED_DOMAIN);
1922
1923         td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1924
1925         /* get the trusted domain object */
1926         nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
1927                             td_state->trusted_domain_dn,
1928                             NULL, NULL, NULL, &msgs);
1929         if (!NT_STATUS_IS_OK(nt_status)) {
1930                 if (NT_STATUS_EQUAL(nt_status,
1931                                     NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1932                         return nt_status;
1933                 }
1934                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1935         }
1936
1937         return setInfoTrustedDomain_base(dce_call, h, mem_ctx,
1938                                          msgs[0], r->in.level, r->in.info);
1939 }
1940
1941
1942 /* 
1943   lsa_DeleteTrustedDomain
1944 */
1945 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1946                                       struct lsa_DeleteTrustedDomain *r)
1947 {
1948         NTSTATUS status;
1949         struct lsa_OpenTrustedDomain opn;
1950         struct lsa_DeleteObject del;
1951         struct dcesrv_handle *h;
1952
1953         opn.in.handle = r->in.handle;
1954         opn.in.sid = r->in.dom_sid;
1955         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1956         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1957         if (!opn.out.trustdom_handle) {
1958                 return NT_STATUS_NO_MEMORY;
1959         }
1960         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1961         if (!NT_STATUS_IS_OK(status)) {
1962                 return status;
1963         }
1964
1965         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1966         talloc_steal(mem_ctx, h);
1967
1968         del.in.handle = opn.out.trustdom_handle;
1969         del.out.handle = opn.out.trustdom_handle;
1970         status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
1971         if (!NT_STATUS_IS_OK(status)) {
1972                 return status;
1973         }
1974         return NT_STATUS_OK;
1975 }
1976
1977 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx, 
1978                                      struct ldb_message *msg, 
1979                                      struct lsa_TrustDomainInfoInfoEx *info_ex) 
1980 {
1981         info_ex->domain_name.string
1982                 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
1983         info_ex->netbios_name.string
1984                 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1985         info_ex->sid 
1986                 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
1987         info_ex->trust_direction
1988                 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
1989         info_ex->trust_type
1990                 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
1991         info_ex->trust_attributes
1992                 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);  
1993         return NT_STATUS_OK;
1994 }
1995
1996 /* 
1997   lsa_QueryTrustedDomainInfo
1998 */
1999 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2000                                            struct lsa_QueryTrustedDomainInfo *r)
2001 {
2002         union lsa_TrustedDomainInfo *info = NULL;
2003         struct dcesrv_handle *h;
2004         struct lsa_trusted_domain_state *trusted_domain_state;
2005         struct ldb_message *msg;
2006         int ret;
2007         struct ldb_message **res;
2008         const char *attrs[] = {
2009                 "flatname", 
2010                 "trustPartner",
2011                 "securityIdentifier",
2012                 "trustDirection",
2013                 "trustType",
2014                 "trustAttributes", 
2015                 "msDs-supportedEncryptionTypes",
2016                 NULL
2017         };
2018
2019         DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2020
2021         trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2022
2023         /* pull all the user attributes */
2024         ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2025                               trusted_domain_state->trusted_domain_dn, &res, attrs);
2026         if (ret != 1) {
2027                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2028         }
2029         msg = res[0];
2030         
2031         info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2032         if (!info) {
2033                 return NT_STATUS_NO_MEMORY;
2034         }
2035         *r->out.info = info;
2036
2037         switch (r->in.level) {
2038         case LSA_TRUSTED_DOMAIN_INFO_NAME:
2039                 info->name.netbios_name.string
2040                         = samdb_result_string(msg, "flatname", NULL);                                      
2041                 break;
2042         case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2043                 info->posix_offset.posix_offset
2044                         = samdb_result_uint(msg, "posixOffset", 0);                                        
2045                 break;
2046 #if 0  /* Win2k3 doesn't implement this */
2047         case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2048                 r->out.info->info_basic.netbios_name.string 
2049                         = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2050                 r->out.info->info_basic.sid
2051                         = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2052                 break;
2053 #endif
2054         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2055                 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2056
2057         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2058                 ZERO_STRUCT(info->full_info);
2059                 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2060
2061         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2062                 ZERO_STRUCT(info->full_info2_internal);
2063                 info->full_info2_internal.posix_offset.posix_offset
2064                         = samdb_result_uint(msg, "posixOffset", 0);                                        
2065                 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2066                 
2067         case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2068                 info->enc_types.enc_types
2069                         = samdb_result_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2070                 break;
2071
2072         case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2073         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2074                 /* oops, we don't want to return the info after all */
2075                 talloc_free(info);
2076                 *r->out.info = NULL;
2077                 return NT_STATUS_INVALID_PARAMETER;
2078         default:
2079                 /* oops, we don't want to return the info after all */
2080                 talloc_free(info);
2081                 *r->out.info = NULL;
2082                 return NT_STATUS_INVALID_INFO_CLASS;
2083         }
2084
2085         return NT_STATUS_OK;
2086 }
2087
2088
2089 /* 
2090   lsa_QueryTrustedDomainInfoBySid
2091 */
2092 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2093                                                 struct lsa_QueryTrustedDomainInfoBySid *r)
2094 {
2095         NTSTATUS status;
2096         struct lsa_OpenTrustedDomain opn;
2097         struct lsa_QueryTrustedDomainInfo query;
2098         struct dcesrv_handle *h;
2099
2100         opn.in.handle = r->in.handle;
2101         opn.in.sid = r->in.dom_sid;
2102         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2103         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2104         if (!opn.out.trustdom_handle) {
2105                 return NT_STATUS_NO_MEMORY;
2106         }
2107         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2108         if (!NT_STATUS_IS_OK(status)) {
2109                 return status;
2110         }
2111
2112         /* Ensure this handle goes away at the end of this call */
2113         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2114         talloc_steal(mem_ctx, h);
2115
2116         query.in.trustdom_handle = opn.out.trustdom_handle;
2117         query.in.level = r->in.level;
2118         query.out.info = r->out.info;
2119         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2120         if (!NT_STATUS_IS_OK(status)) {
2121                 return status;
2122         }
2123
2124         return NT_STATUS_OK;
2125 }
2126
2127 /*
2128   lsa_SetTrustedDomainInfoByName
2129 */
2130 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2131                                                TALLOC_CTX *mem_ctx,
2132                                                struct lsa_SetTrustedDomainInfoByName *r)
2133 {
2134         struct dcesrv_handle *policy_handle;
2135         struct lsa_policy_state *policy_state;
2136         struct ldb_message **msgs;
2137         NTSTATUS nt_status;
2138
2139         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2140         policy_state = policy_handle->data;
2141
2142         /* get the trusted domain object */
2143         nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2144                             policy_state->domain_dn,
2145                             r->in.trusted_domain->string,
2146                             r->in.trusted_domain->string,
2147                             NULL, &msgs);
2148         if (!NT_STATUS_IS_OK(nt_status)) {
2149                 if (NT_STATUS_EQUAL(nt_status,
2150                                     NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2151                         return nt_status;
2152                 }
2153                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2154         }
2155
2156         return setInfoTrustedDomain_base(dce_call, policy_handle, mem_ctx,
2157                                          msgs[0], r->in.level, r->in.info);
2158 }
2159
2160 /* 
2161    lsa_QueryTrustedDomainInfoByName
2162 */
2163 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2164                                                  TALLOC_CTX *mem_ctx,
2165                                                  struct lsa_QueryTrustedDomainInfoByName *r)
2166 {
2167         NTSTATUS status;
2168         struct lsa_OpenTrustedDomainByName opn;
2169         struct lsa_QueryTrustedDomainInfo query;
2170         struct dcesrv_handle *h;
2171
2172         opn.in.handle = r->in.handle;
2173         opn.in.name = *r->in.trusted_domain;
2174         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2175         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2176         if (!opn.out.trustdom_handle) {
2177                 return NT_STATUS_NO_MEMORY;
2178         }
2179         status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2180         if (!NT_STATUS_IS_OK(status)) {
2181                 return status;
2182         }
2183         
2184         /* Ensure this handle goes away at the end of this call */
2185         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2186         talloc_steal(mem_ctx, h);
2187
2188         query.in.trustdom_handle = opn.out.trustdom_handle;
2189         query.in.level = r->in.level;
2190         query.out.info = r->out.info;
2191         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2192         if (!NT_STATUS_IS_OK(status)) {
2193                 return status;
2194         }
2195         
2196         return NT_STATUS_OK;
2197 }
2198
2199 /*
2200   lsa_CloseTrustedDomainEx 
2201 */
2202 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2203                                          TALLOC_CTX *mem_ctx,
2204                                          struct lsa_CloseTrustedDomainEx *r)
2205 {
2206         /* The result of a bad hair day from an IDL programmer?  Not
2207          * implmented in Win2k3.  You should always just lsa_Close
2208          * anyway. */
2209         return NT_STATUS_NOT_IMPLEMENTED;
2210 }
2211
2212
2213 /*
2214   comparison function for sorting lsa_DomainInformation array
2215 */
2216 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2217 {
2218         return strcasecmp_m(e1->name.string, e2->name.string);
2219 }
2220
2221 /* 
2222   lsa_EnumTrustDom 
2223 */
2224 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2225                                  struct lsa_EnumTrustDom *r)
2226 {
2227         struct dcesrv_handle *policy_handle;
2228         struct lsa_DomainInfo *entries;
2229         struct lsa_policy_state *policy_state;
2230         struct ldb_message **domains;
2231         const char *attrs[] = {
2232                 "flatname", 
2233                 "securityIdentifier",
2234                 NULL
2235         };
2236
2237
2238         int count, i;
2239
2240         *r->out.resume_handle = 0;
2241
2242         r->out.domains->domains = NULL;
2243         r->out.domains->count = 0;
2244
2245         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2246
2247         policy_state = policy_handle->data;
2248
2249         /* search for all users in this domain. This could possibly be cached and 
2250            resumed based on resume_key */
2251         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs, 
2252                              "objectclass=trustedDomain");
2253         if (count < 0) {
2254                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2255         }
2256
2257         /* convert to lsa_TrustInformation format */
2258         entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2259         if (!entries) {
2260                 return NT_STATUS_NO_MEMORY;
2261         }
2262         for (i=0;i<count;i++) {
2263                 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2264                 entries[i].name.string = samdb_result_string(domains[i], "flatname", NULL);
2265         }
2266
2267         /* sort the results by name */
2268         TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2269
2270         if (*r->in.resume_handle >= count) {
2271                 *r->out.resume_handle = -1;
2272
2273                 return NT_STATUS_NO_MORE_ENTRIES;
2274         }
2275
2276         /* return the rest, limit by max_size. Note that we 
2277            use the w2k3 element size value of 60 */
2278         r->out.domains->count = count - *r->in.resume_handle;
2279         r->out.domains->count = MIN(r->out.domains->count, 
2280                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2281
2282         r->out.domains->domains = entries + *r->in.resume_handle;
2283         r->out.domains->count = r->out.domains->count;
2284
2285         if (r->out.domains->count < count - *r->in.resume_handle) {
2286                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2287                 return STATUS_MORE_ENTRIES;
2288         }
2289
2290         /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2291          * always be larger than the previous input resume handle, in
2292          * particular when hitting the last query it is vital to set the
2293          * resume handle correctly to avoid infinite client loops, as
2294          * seen e.g. with Windows XP SP3 when resume handle is 0 and
2295          * status is NT_STATUS_OK - gd */
2296
2297         *r->out.resume_handle = (uint32_t)-1;
2298
2299         return NT_STATUS_OK;
2300 }
2301
2302 /*
2303   comparison function for sorting lsa_DomainInformation array
2304 */
2305 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2306 {
2307         return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2308 }
2309
2310 /* 
2311   lsa_EnumTrustedDomainsEx 
2312 */
2313 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2314                                         struct lsa_EnumTrustedDomainsEx *r)
2315 {
2316         struct dcesrv_handle *policy_handle;
2317         struct lsa_TrustDomainInfoInfoEx *entries;
2318         struct lsa_policy_state *policy_state;
2319         struct ldb_message **domains;
2320         const char *attrs[] = {
2321                 "flatname", 
2322                 "trustPartner",
2323                 "securityIdentifier",
2324                 "trustDirection",
2325                 "trustType",
2326                 "trustAttributes", 
2327                 NULL
2328         };
2329         NTSTATUS nt_status;
2330
2331         int count, i;
2332
2333         *r->out.resume_handle = 0;
2334
2335         r->out.domains->domains = NULL;
2336         r->out.domains->count = 0;
2337
2338         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2339
2340         policy_state = policy_handle->data;
2341
2342         /* search for all users in this domain. This could possibly be cached and 
2343            resumed based on resume_key */
2344         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs, 
2345                              "objectclass=trustedDomain");
2346         if (count < 0) {
2347                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2348         }
2349
2350         /* convert to lsa_DomainInformation format */
2351         entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2352         if (!entries) {
2353                 return NT_STATUS_NO_MEMORY;
2354         }
2355         for (i=0;i<count;i++) {
2356                 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2357                 if (!NT_STATUS_IS_OK(nt_status)) {
2358                         return nt_status;
2359                 }
2360         }
2361
2362         /* sort the results by name */
2363         TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2364
2365         if (*r->in.resume_handle >= count) {
2366                 *r->out.resume_handle = -1;
2367
2368                 return NT_STATUS_NO_MORE_ENTRIES;
2369         }
2370
2371         /* return the rest, limit by max_size. Note that we 
2372            use the w2k3 element size value of 60 */
2373         r->out.domains->count = count - *r->in.resume_handle;
2374         r->out.domains->count = MIN(r->out.domains->count, 
2375                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2376
2377         r->out.domains->domains = entries + *r->in.resume_handle;
2378         r->out.domains->count = r->out.domains->count;
2379
2380         if (r->out.domains->count < count - *r->in.resume_handle) {
2381                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2382                 return STATUS_MORE_ENTRIES;
2383         }
2384
2385         return NT_STATUS_OK;
2386 }
2387
2388
2389 /* 
2390   lsa_OpenAccount 
2391 */
2392 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2393                                 struct lsa_OpenAccount *r)
2394 {
2395         struct dcesrv_handle *h, *ah;
2396         struct lsa_policy_state *state;
2397         struct lsa_account_state *astate;
2398
2399         ZERO_STRUCTP(r->out.acct_handle);
2400
2401         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2402
2403         state = h->data;
2404
2405         astate = talloc(dce_call->conn, struct lsa_account_state);
2406         if (astate == NULL) {
2407                 return NT_STATUS_NO_MEMORY;
2408         }
2409
2410         astate->account_sid = dom_sid_dup(astate, r->in.sid);
2411         if (astate->account_sid == NULL) {
2412                 talloc_free(astate);
2413                 return NT_STATUS_NO_MEMORY;
2414         }
2415         
2416         astate->policy = talloc_reference(astate, state);
2417         astate->access_mask = r->in.access_mask;
2418
2419         ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2420         if (!ah) {
2421                 talloc_free(astate);
2422                 return NT_STATUS_NO_MEMORY;
2423         }
2424
2425         ah->data = talloc_steal(ah, astate);
2426
2427         *r->out.acct_handle = ah->wire_handle;
2428
2429         return NT_STATUS_OK;
2430 }
2431
2432
2433 /* 
2434   lsa_EnumPrivsAccount 
2435 */
2436 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call, 
2437                                      TALLOC_CTX *mem_ctx,
2438                                      struct lsa_EnumPrivsAccount *r)
2439 {
2440         struct dcesrv_handle *h;
2441         struct lsa_account_state *astate;
2442         int ret;
2443         unsigned int i;
2444         struct ldb_message **res;
2445         const char * const attrs[] = { "privilege", NULL};
2446         struct ldb_message_element *el;
2447         const char *sidstr;
2448         struct lsa_PrivilegeSet *privs;
2449
2450         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2451
2452         astate = h->data;
2453
2454         privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2455         if (privs == NULL) {
2456                 return NT_STATUS_NO_MEMORY;
2457         }
2458         privs->count = 0;
2459         privs->unknown = 0;
2460         privs->set = NULL;
2461
2462         *r->out.privs = privs;
2463
2464         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2465         if (sidstr == NULL) {
2466                 return NT_STATUS_NO_MEMORY;
2467         }
2468
2469         ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs, 
2470                            "objectSid=%s", sidstr);
2471         if (ret < 0) {
2472                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2473         }
2474         if (ret != 1) {
2475                 return NT_STATUS_OK;
2476         }
2477
2478         el = ldb_msg_find_element(res[0], "privilege");
2479         if (el == NULL || el->num_values == 0) {
2480                 return NT_STATUS_OK;
2481         }
2482
2483         privs->set = talloc_array(privs,
2484                                   struct lsa_LUIDAttribute, el->num_values);
2485         if (privs->set == NULL) {
2486                 return NT_STATUS_NO_MEMORY;
2487         }
2488
2489         for (i=0;i<el->num_values;i++) {
2490                 int id = sec_privilege_id((const char *)el->values[i].data);
2491                 if (id == -1) {
2492                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2493                 }
2494                 privs->set[i].attribute = 0;
2495                 privs->set[i].luid.low = id;
2496                 privs->set[i].luid.high = 0;
2497         }
2498
2499         privs->count = el->num_values;
2500
2501         return NT_STATUS_OK;
2502 }
2503
2504 /* 
2505   lsa_EnumAccountRights 
2506 */
2507 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call, 
2508                                       TALLOC_CTX *mem_ctx,
2509                                       struct lsa_EnumAccountRights *r)
2510 {
2511         struct dcesrv_handle *h;
2512         struct lsa_policy_state *state;
2513         int ret;
2514         unsigned int i;
2515         struct ldb_message **res;
2516         const char * const attrs[] = { "privilege", NULL};
2517         const char *sidstr;
2518         struct ldb_message_element *el;
2519
2520         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2521
2522         state = h->data;
2523
2524         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2525         if (sidstr == NULL) {
2526                 return NT_STATUS_NO_MEMORY;
2527         }
2528
2529         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs, 
2530                            "(&(objectSid=%s)(privilege=*))", sidstr);
2531         if (ret == 0) {
2532                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2533         }
2534         if (ret != 1) {
2535                 DEBUG(3, ("searching for account rights for SID: %s failed: %s", 
2536                           dom_sid_string(mem_ctx, r->in.sid),
2537                           ldb_errstring(state->pdb)));
2538                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2539         }
2540
2541         el = ldb_msg_find_element(res[0], "privilege");
2542         if (el == NULL || el->num_values == 0) {
2543                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2544         }
2545
2546         r->out.rights->count = el->num_values;
2547         r->out.rights->names = talloc_array(r->out.rights, 
2548                                             struct lsa_StringLarge, r->out.rights->count);
2549         if (r->out.rights->names == NULL) {
2550                 return NT_STATUS_NO_MEMORY;
2551         }
2552
2553         for (i=0;i<el->num_values;i++) {
2554                 r->out.rights->names[i].string = (const char *)el->values[i].data;
2555         }
2556
2557         return NT_STATUS_OK;
2558 }
2559
2560
2561
2562 /* 
2563   helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2564 */
2565 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call, 
2566                                            TALLOC_CTX *mem_ctx,
2567                                            struct lsa_policy_state *state,
2568                                            int ldb_flag,
2569                                            struct dom_sid *sid,
2570                                            const struct lsa_RightSet *rights)
2571 {
2572         const char *sidstr, *sidndrstr;
2573         struct ldb_message *msg;
2574         struct ldb_message_element *el;
2575         int ret;
2576         uint32_t i;
2577         struct lsa_EnumAccountRights r2;
2578         char *dnstr;
2579
2580         if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2581             SECURITY_ADMINISTRATOR) {
2582                 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2583                 return NT_STATUS_ACCESS_DENIED;
2584         }
2585
2586         msg = ldb_msg_new(mem_ctx);
2587         if (msg == NULL) {
2588                 return NT_STATUS_NO_MEMORY;
2589         }
2590
2591         sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2592         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidndrstr, msg);
2593
2594         sidstr = dom_sid_string(msg, sid);
2595         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, msg);
2596
2597         dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2598         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(dnstr, msg);
2599
2600         msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2601         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg->dn, msg);
2602
2603         if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2604                 NTSTATUS status;
2605
2606                 r2.in.handle = &state->handle->wire_handle;
2607                 r2.in.sid = sid;
2608                 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2609
2610                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2611                 if (!NT_STATUS_IS_OK(status)) {
2612                         ZERO_STRUCTP(r2.out.rights);
2613                 }
2614         }
2615
2616         for (i=0;i<rights->count;i++) {
2617                 if (sec_privilege_id(rights->names[i].string) == -1) {
2618                         talloc_free(msg);
2619                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2620                 }
2621
2622                 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2623                         uint32_t j;
2624                         for (j=0;j<r2.out.rights->count;j++) {
2625                                 if (strcasecmp_m(r2.out.rights->names[j].string, 
2626                                                rights->names[i].string) == 0) {
2627                                         break;
2628                                 }
2629                         }
2630                         if (j != r2.out.rights->count) continue;
2631                 }
2632
2633                 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2634                 if (ret != LDB_SUCCESS) {
2635                         talloc_free(msg);
2636                         return NT_STATUS_NO_MEMORY;
2637                 }
2638         }
2639
2640         el = ldb_msg_find_element(msg, "privilege");
2641         if (!el) {
2642                 talloc_free(msg);
2643                 return NT_STATUS_OK;
2644         }
2645
2646         el->flags = ldb_flag;
2647
2648         ret = ldb_modify(state->pdb, msg);
2649         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2650                 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2651                         talloc_free(msg);
2652                         return NT_STATUS_NO_MEMORY;
2653                 }
2654                 samdb_msg_add_string(state->pdb, msg, msg, "comment", "added via LSA");
2655                 ret = ldb_add(state->pdb, msg);         
2656         }
2657         if (ret != LDB_SUCCESS) {
2658                 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2659                         talloc_free(msg);
2660                         return NT_STATUS_OK;
2661                 }
2662                 DEBUG(3, ("Could not %s attributes from %s: %s", 
2663                           LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2664                           ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2665                 talloc_free(msg);
2666                 return NT_STATUS_UNEXPECTED_IO_ERROR;
2667         }
2668
2669         talloc_free(msg);
2670         return NT_STATUS_OK;
2671 }
2672
2673 /* 
2674   lsa_AddPrivilegesToAccount
2675 */
2676 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2677                                            struct lsa_AddPrivilegesToAccount *r)
2678 {
2679         struct lsa_RightSet rights;
2680         struct dcesrv_handle *h;
2681         struct lsa_account_state *astate;
2682         uint32_t i;
2683
2684         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2685
2686         astate = h->data;
2687
2688         rights.count = r->in.privs->count;
2689         rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2690         if (rights.names == NULL) {
2691                 return NT_STATUS_NO_MEMORY;
2692         }
2693         for (i=0;i<rights.count;i++) {
2694                 int id = r->in.privs->set[i].luid.low;
2695                 if (r->in.privs->set[i].luid.high) {
2696                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2697                 }
2698                 rights.names[i].string = sec_privilege_name(id);
2699                 if (rights.names[i].string == NULL) {
2700                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2701                 }
2702         }
2703
2704         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
2705                                           LDB_FLAG_MOD_ADD, astate->account_sid,
2706                                           &rights);
2707 }
2708
2709
2710 /* 
2711   lsa_RemovePrivilegesFromAccount
2712 */
2713 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2714                                                 struct lsa_RemovePrivilegesFromAccount *r)
2715 {
2716         struct lsa_RightSet *rights;
2717         struct dcesrv_handle *h;
2718         struct lsa_account_state *astate;
2719         uint32_t i;
2720
2721         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2722
2723         astate = h->data;
2724
2725         rights = talloc(mem_ctx, struct lsa_RightSet);
2726
2727         if (r->in.remove_all == 1 && 
2728             r->in.privs == NULL) {
2729                 struct lsa_EnumAccountRights r2;
2730                 NTSTATUS status;
2731
2732                 r2.in.handle = &astate->policy->handle->wire_handle;
2733                 r2.in.sid = astate->account_sid;
2734                 r2.out.rights = rights;
2735
2736                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2737                 if (!NT_STATUS_IS_OK(status)) {
2738                         return status;
2739                 }
2740
2741                 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
2742                                                   LDB_FLAG_MOD_DELETE, astate->account_sid,
2743                                                   r2.out.rights);
2744         }
2745
2746         if (r->in.remove_all != 0) {
2747                 return NT_STATUS_INVALID_PARAMETER;
2748         }
2749
2750         rights->count = r->in.privs->count;
2751         rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2752         if (rights->names == NULL) {
2753                 return NT_STATUS_NO_MEMORY;
2754         }
2755         for (i=0;i<rights->count;i++) {
2756                 int id = r->in.privs->set[i].luid.low;
2757                 if (r->in.privs->set[i].luid.high) {
2758                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2759                 }
2760                 rights->names[i].string = sec_privilege_name(id);
2761                 if (rights->names[i].string == NULL) {
2762                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2763                 }
2764         }
2765
2766         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
2767                                           LDB_FLAG_MOD_DELETE, astate->account_sid,
2768                                           rights);
2769 }
2770
2771
2772 /* 
2773   lsa_GetQuotasForAccount
2774 */
2775 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2776                        struct lsa_GetQuotasForAccount *r)
2777 {
2778         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2779 }
2780
2781
2782 /* 
2783   lsa_SetQuotasForAccount
2784 */
2785 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2786                        struct lsa_SetQuotasForAccount *r)
2787 {
2788         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2789 }
2790
2791
2792 /* 
2793   lsa_GetSystemAccessAccount
2794 */
2795 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2796                        struct lsa_GetSystemAccessAccount *r)
2797 {
2798         uint32_t i;
2799         NTSTATUS status;
2800         struct lsa_EnumPrivsAccount enumPrivs;
2801         struct lsa_PrivilegeSet *privs;
2802
2803         privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2804         if (!privs) {
2805                 return NT_STATUS_NO_MEMORY;
2806         }
2807         privs->count = 0;
2808         privs->unknown = 0;
2809         privs->set = NULL;
2810
2811         enumPrivs.in.handle = r->in.handle;
2812         enumPrivs.out.privs = &privs;
2813
2814         status = dcesrv_lsa_EnumPrivsAccount(dce_call, mem_ctx, &enumPrivs);
2815         if (!NT_STATUS_IS_OK(status)) {
2816                 return status;
2817         }       
2818
2819         *(r->out.access_mask) = 0x00000000;
2820
2821         for (i = 0; i < privs->count; i++) {
2822                 int priv = privs->set[i].luid.low;
2823
2824                 switch (priv) {
2825                 case SEC_PRIV_INTERACTIVE_LOGON:
2826                         *(r->out.access_mask) |= LSA_POLICY_MODE_INTERACTIVE;
2827                         break;
2828                 case SEC_PRIV_NETWORK_LOGON:
2829                         *(r->out.access_mask) |= LSA_POLICY_MODE_NETWORK;
2830                         break;
2831                 case SEC_PRIV_REMOTE_INTERACTIVE_LOGON:
2832                         *(r->out.access_mask) |= LSA_POLICY_MODE_REMOTE_INTERACTIVE;
2833                         break;
2834                 }
2835         }
2836
2837         return NT_STATUS_OK;
2838 }
2839
2840
2841 /* 
2842   lsa_SetSystemAccessAccount
2843 */
2844 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2845                        struct lsa_SetSystemAccessAccount *r)
2846 {
2847         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2848 }
2849
2850
2851 /* 
2852   lsa_CreateSecret 
2853 */
2854 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2855                                  struct lsa_CreateSecret *r)
2856 {
2857         struct dcesrv_handle *policy_handle;
2858         struct lsa_policy_state *policy_state;
2859         struct lsa_secret_state *secret_state;
2860         struct dcesrv_handle *handle;
2861         struct ldb_message **msgs, *msg;
2862         const char *attrs[] = {
2863                 NULL
2864         };
2865
2866         const char *name;
2867
2868         int ret;
2869
2870         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2871         ZERO_STRUCTP(r->out.sec_handle);
2872         
2873         switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
2874         {
2875         case SECURITY_SYSTEM:
2876         case SECURITY_ADMINISTRATOR:
2877                 break;
2878         default:
2879                 /* Users and annonymous are not allowed create secrets */
2880                 return NT_STATUS_ACCESS_DENIED;
2881         }
2882
2883         policy_state = policy_handle->data;
2884
2885         if (!r->in.name.string) {
2886                 return NT_STATUS_INVALID_PARAMETER;
2887         }
2888         
2889         secret_state = talloc(mem_ctx, struct lsa_secret_state);
2890         if (!secret_state) {
2891                 return NT_STATUS_NO_MEMORY;
2892         }
2893         secret_state->policy = policy_state;
2894
2895         msg = ldb_msg_new(mem_ctx);
2896         if (msg == NULL) {
2897                 return NT_STATUS_NO_MEMORY;
2898         }
2899
2900         if (strncmp("G$", r->in.name.string, 2) == 0) {
2901                 const char *name2;
2902                 name = &r->in.name.string[2];
2903                         /* 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) */
2904                 secret_state->sam_ldb = talloc_reference(secret_state, 
2905                                                          samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx)));
2906                 secret_state->global = true;
2907
2908                 if (strlen(name) < 1) {
2909                         return NT_STATUS_INVALID_PARAMETER;
2910                 }
2911
2912                 name2 = talloc_asprintf(mem_ctx, "%s Secret", ldb_binary_encode_string(mem_ctx, name));
2913                 /* search for the secret record */
2914                 ret = gendb_search(secret_state->sam_ldb,
2915                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
2916                                    "(&(cn=%s)(objectclass=secret))", 
2917                                    name2);
2918                 if (ret > 0) {
2919                         return NT_STATUS_OBJECT_NAME_COLLISION;
2920                 }
2921                 
2922                 if (ret < 0) {
2923                         DEBUG(0,("Failure searching for CN=%s: %s\n", 
2924                                  name2, ldb_errstring(secret_state->sam_ldb)));
2925                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2926                 }
2927
2928                 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2929                 if (!name2 || ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2930                         return NT_STATUS_NO_MEMORY;
2931                 }
2932                 
2933                 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name2);
2934         
2935         } else {
2936                 secret_state->global = false;
2937
2938                 name = r->in.name.string;
2939                 if (strlen(name) < 1) {
2940                         return NT_STATUS_INVALID_PARAMETER;
2941                 }
2942
2943                 secret_state->sam_ldb = talloc_reference(secret_state, 
2944                                                          secrets_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx));
2945                 /* search for the secret record */
2946                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2947                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2948                                    &msgs, attrs,
2949                                    "(&(cn=%s)(objectclass=secret))", 
2950                                    ldb_binary_encode_string(mem_ctx, name));
2951                 if (ret > 0) {
2952                         return NT_STATUS_OBJECT_NAME_COLLISION;
2953                 }
2954                 
2955                 if (ret < 0) {
2956                         DEBUG(0,("Failure searching for CN=%s: %s\n", 
2957                                  name, ldb_errstring(secret_state->sam_ldb)));
2958                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2959                 }
2960
2961                 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb, "cn=%s,cn=LSA Secrets", name);
2962                 samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "cn", name);
2963         } 
2964
2965         samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg, "objectClass", "secret");
2966         
2967         secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
2968
2969         /* create the secret */
2970         ret = dsdb_add(secret_state->sam_ldb, msg, DSDB_MODIFY_RELAX);
2971         if (ret != LDB_SUCCESS) {
2972                 DEBUG(0,("Failed to create secret record %s: %s\n",
2973                          ldb_dn_get_linearized(msg->dn), 
2974                          ldb_errstring(secret_state->sam_ldb)));
2975                 return NT_STATUS_ACCESS_DENIED;
2976         }
2977
2978         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2979         if (!handle) {
2980                 return NT_STATUS_NO_MEMORY;
2981         }
2982         
2983         handle->data = talloc_steal(handle, secret_state);
2984         
2985         secret_state->access_mask = r->in.access_mask;
2986         secret_state->policy = talloc_reference(secret_state, policy_state);
2987         
2988         *r->out.sec_handle = handle->wire_handle;
2989         
2990         return NT_STATUS_OK;
2991 }
2992
2993
2994 /* 
2995   lsa_OpenSecret 
2996 */
2997 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2998                                struct lsa_OpenSecret *r)
2999 {
3000         struct dcesrv_handle *policy_handle;
3001         
3002         struct lsa_policy_state *policy_state;
3003         struct lsa_secret_state *secret_state;
3004         struct dcesrv_handle *handle;
3005         struct ldb_message **msgs;
3006         const char *attrs[] = {
3007                 NULL
3008         };
3009
3010         const char *name;
3011
3012         int ret;
3013
3014         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3015         ZERO_STRUCTP(r->out.sec_handle);
3016         policy_state = policy_handle->data;
3017
3018         if (!r->in.name.string) {
3019                 return NT_STATUS_INVALID_PARAMETER;
3020         }
3021         
3022         switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3023         {
3024         case SECURITY_SYSTEM:
3025         case SECURITY_ADMINISTRATOR:
3026                 break;
3027         default:
3028                 /* Users and annonymous are not allowed to access secrets */
3029                 return NT_STATUS_ACCESS_DENIED;
3030         }
3031
3032         secret_state = talloc(mem_ctx, struct lsa_secret_state);
3033         if (!secret_state) {
3034                 return NT_STATUS_NO_MEMORY;
3035         }
3036         secret_state->policy = policy_state;
3037
3038         if (strncmp("G$", r->in.name.string, 2) == 0) {
3039                 name = &r->in.name.string[2];
3040                 /* 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) */
3041                 secret_state->sam_ldb = talloc_reference(secret_state, 
3042                                                          samdb_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx, system_session(dce_call->conn->dce_ctx->lp_ctx)));
3043                 secret_state->global = true;
3044
3045                 if (strlen(name) < 1) {
3046                         return NT_STATUS_INVALID_PARAMETER;
3047                 }
3048
3049                 /* search for the secret record */
3050                 ret = gendb_search(secret_state->sam_ldb,
3051                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
3052                                    "(&(cn=%s Secret)(objectclass=secret))", 
3053                                    ldb_binary_encode_string(mem_ctx, name));
3054                 if (ret == 0) {
3055                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3056                 }
3057                 
3058                 if (ret != 1) {
3059                         DEBUG(0,("Found %d records matching DN %s\n", ret,
3060                                  ldb_dn_get_linearized(policy_state->system_dn)));
3061                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3062                 }
3063         
3064         } else {
3065                 secret_state->global = false;
3066                 secret_state->sam_ldb = talloc_reference(secret_state, 
3067                                  secrets_db_connect(mem_ctx, dce_call->event_ctx, dce_call->conn->dce_ctx->lp_ctx));
3068
3069                 name = r->in.name.string;
3070                 if (strlen(name) < 1) {
3071                         return NT_STATUS_INVALID_PARAMETER;
3072                 }
3073
3074                 /* search for the secret record */
3075                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3076                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3077                                    &msgs, attrs,
3078                                    "(&(cn=%s)(objectclass=secret))", 
3079                                    ldb_binary_encode_string(mem_ctx, name));
3080                 if (ret == 0) {
3081                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3082                 }
3083                 
3084                 if (ret != 1) {
3085                         DEBUG(0,("Found %d records matching CN=%s\n", 
3086                                  ret, ldb_binary_encode_string(mem_ctx, name)));
3087                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3088                 }
3089         } 
3090
3091         secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3092         
3093         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3094         if (!handle) {
3095                 return NT_STATUS_NO_MEMORY;
3096         }
3097         
3098         handle->data = talloc_steal(handle, secret_state);
3099         
3100         secret_state->access_mask = r->in.access_mask;
3101         secret_state->policy = talloc_reference(secret_state, policy_state);
3102         
3103         *r->out.sec_handle = handle->wire_handle;
3104         
3105         return NT_STATUS_OK;
3106 }
3107
3108
3109 /* 
3110   lsa_SetSecret 
3111 */
3112 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3113                               struct lsa_SetSecret *r)
3114 {
3115
3116         struct dcesrv_handle *h;
3117         struct lsa_secret_state *secret_state;
3118         struct ldb_message *msg;
3119         DATA_BLOB session_key;
3120         DATA_BLOB crypt_secret, secret;
3121         struct ldb_val val;
3122         int ret;
3123         NTSTATUS status = NT_STATUS_OK;
3124
3125         struct timeval now = timeval_current();
3126         NTTIME nt_now = timeval_to_nttime(&now);
3127
3128         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3129
3130         secret_state = h->data;
3131
3132         msg = ldb_msg_new(mem_ctx);
3133         if (msg == NULL) {
3134                 return NT_STATUS_NO_MEMORY;
3135         }
3136
3137         msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3138         if (!msg->dn) {
3139                 return NT_STATUS_NO_MEMORY;
3140         }
3141         status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3142         if (!NT_STATUS_IS_OK(status)) {
3143                 return status;
3144         }
3145
3146         if (r->in.old_val) {
3147                 /* Decrypt */
3148                 crypt_secret.data = r->in.old_val->data;
3149                 crypt_secret.length = r->in.old_val->size;
3150                 
3151                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3152                 if (!NT_STATUS_IS_OK(status)) {
3153                         return status;
3154                 }
3155                 
3156                 val.data = secret.data;
3157                 val.length = secret.length;
3158                 
3159                 /* set value */
3160                 if (samdb_msg_add_value(secret_state->sam_ldb, 
3161                                         mem_ctx, msg, "priorValue", &val) != LDB_SUCCESS) {
3162                         return NT_STATUS_NO_MEMORY; 
3163                 }
3164                 
3165                 /* set old value mtime */
3166                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
3167                                          mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3168                         return NT_STATUS_NO_MEMORY; 
3169                 }
3170
3171         } else {
3172                 /* If the old value is not set, then migrate the
3173                  * current value to the old value */
3174                 const struct ldb_val *old_val;
3175                 NTTIME last_set_time;
3176                 struct ldb_message **res;
3177                 const char *attrs[] = {
3178                         "currentValue",
3179                         "lastSetTime",
3180                         NULL
3181                 };
3182                 
3183                 /* search for the secret record */
3184                 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3185                                       secret_state->secret_dn, &res, attrs);
3186                 if (ret == 0) {
3187                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3188                 }
3189                 
3190                 if (ret != 1) {
3191                         DEBUG(0,("Found %d records matching dn=%s\n", ret,
3192                                  ldb_dn_get_linearized(secret_state->secret_dn)));
3193                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3194                 }
3195                 
3196                 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3197                 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3198                 
3199                 if (old_val) {
3200                         /* set old value */
3201                         if (samdb_msg_add_value(secret_state->sam_ldb, 
3202                                                 mem_ctx, msg, "priorValue", 
3203                                                 old_val) != 0) {
3204                                 return NT_STATUS_NO_MEMORY; 
3205                         }
3206                 } else {
3207                         if (samdb_msg_add_delete(secret_state->sam_ldb, 
3208                                                  mem_ctx, msg, "priorValue")) {
3209                                 return NT_STATUS_NO_MEMORY;
3210                         }
3211                         
3212                 }
3213                 
3214                 /* set old value mtime */
3215                 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3216                         if (samdb_msg_add_uint64(secret_state->sam_ldb, 
3217                                                  mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3218                                 return NT_STATUS_NO_MEMORY; 
3219                         }
3220                 } else {
3221                         if (samdb_msg_add_uint64(secret_state->sam_ldb, 
3222                                                  mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3223                                 return NT_STATUS_NO_MEMORY; 
3224                         }
3225                 }
3226         }
3227
3228         if (r->in.new_val) {
3229                 /* Decrypt */
3230                 crypt_secret.data = r->in.new_val->data;
3231                 crypt_secret.length = r->in.new_val->size;
3232                 
3233                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3234                 if (!NT_STATUS_IS_OK(status)) {
3235                         return status;
3236                 }
3237                 
3238                 val.data = secret.data;
3239                 val.length = secret.length;
3240                 
3241                 /* set value */
3242                 if (samdb_msg_add_value(secret_state->sam_ldb, 
3243                                         mem_ctx, msg, "currentValue", &val) != LDB_SUCCESS) {
3244                         return NT_STATUS_NO_MEMORY; 
3245                 }
3246                 
3247                 /* set new value mtime */
3248                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
3249                                          mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3250                         return NT_STATUS_NO_MEMORY; 
3251                 }
3252                 
3253         } else {
3254                 /* NULL out the NEW value */
3255                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
3256                                          mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3257                         return NT_STATUS_NO_MEMORY; 
3258                 }
3259                 if (samdb_msg_add_delete(secret_state->sam_ldb, 
3260                                          mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3261                         return NT_STATUS_NO_MEMORY;
3262                 }
3263         }
3264
3265         /* modify the samdb record */
3266         ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3267         if (ret != LDB_SUCCESS) {
3268                 /* we really need samdb.c to return NTSTATUS */
3269                 return NT_STATUS_UNSUCCESSFUL;
3270         }
3271
3272         return NT_STATUS_OK;
3273 }
3274
3275
3276 /* 
3277   lsa_QuerySecret 
3278 */
3279 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3280                                 struct lsa_QuerySecret *r)
3281 {
3282         struct dcesrv_handle *h;
3283         struct lsa_secret_state *secret_state;
3284         struct ldb_message *msg;
3285         DATA_BLOB session_key;
3286         DATA_BLOB crypt_secret, secret;
3287         int ret;
3288         struct ldb_message **res;
3289         const char *attrs[] = {
3290                 "currentValue",
3291                 "priorValue",
3292                 "lastSetTime",
3293                 "priorSetTime", 
3294                 NULL
3295         };
3296
3297         NTSTATUS nt_status;
3298
3299         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3300
3301         /* Ensure user is permitted to read this... */
3302         switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3303         {
3304         case SECURITY_SYSTEM:
3305         case SECURITY_ADMINISTRATOR:
3306                 break;
3307         default:
3308                 /* Users and annonymous are not allowed to read secrets */
3309                 return NT_STATUS_ACCESS_DENIED;
3310         }
3311
3312         secret_state = h->data;
3313
3314         /* pull all the user attributes */
3315         ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3316                               secret_state->secret_dn, &res, attrs);
3317         if (ret != 1) {
3318                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3319         }
3320         msg = res[0];
3321         
3322         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3323         if (!NT_STATUS_IS_OK(nt_status)) {
3324                 return nt_status;
3325         }
3326         
3327         if (r->in.old_val) {
3328                 const struct ldb_val *prior_val;
3329                 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3330                 if (!r->out.old_val) {
3331                         return NT_STATUS_NO_MEMORY;
3332                 }
3333                 prior_val = ldb_msg_find_ldb_val(res[0], "priorValue");
3334                 
3335                 if (prior_val && prior_val->length) {
3336                         secret.data = prior_val->data;
3337                         secret.length = prior_val->length;
3338                 
3339                         /* Encrypt */
3340                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3341                         if (!crypt_secret.length) {
3342                                 return NT_STATUS_NO_MEMORY;
3343                         }
3344                         r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3345                         if (!r->out.old_val->buf) {
3346                                 return NT_STATUS_NO_MEMORY;
3347                         }
3348                         r->out.old_val->buf->size = crypt_secret.length;
3349                         r->out.old_val->buf->length = crypt_secret.length;
3350                         r->out.old_val->buf->data = crypt_secret.data;
3351                 }
3352         }
3353         
3354         if (r->in.old_mtime) {
3355                 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3356                 if (!r->out.old_mtime) {
3357                         return NT_STATUS_NO_MEMORY;
3358                 }
3359                 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(res[0], "priorSetTime", 0);
3360         }
3361         
3362         if (r->in.new_val) {
3363                 const struct ldb_val *new_val;
3364                 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3365                 if (!r->out.new_val) {
3366                         return NT_STATUS_NO_MEMORY;
3367                 }
3368
3369                 new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3370                 
3371                 if (new_val && new_val->length) {
3372                         secret.data = new_val->data;
3373                         secret.length = new_val->length;
3374                 
3375                         /* Encrypt */
3376                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3377                         if (!crypt_secret.length) {
3378                                 return NT_STATUS_NO_MEMORY;
3379                         }
3380                         r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3381                         if (!r->out.new_val->buf) {
3382                                 return NT_STATUS_NO_MEMORY;
3383                         }
3384                         r->out.new_val->buf->length = crypt_secret.length;
3385                         r->out.new_val->buf->size = crypt_secret.length;
3386                         r->out.new_val->buf->data = crypt_secret.data;
3387                 }
3388         }
3389         
3390         if (r->in.new_mtime) {
3391                 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3392                 if (!r->out.new_mtime) {
3393                         return NT_STATUS_NO_MEMORY;
3394                 }
3395                 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3396         }
3397         
3398         return NT_STATUS_OK;
3399 }
3400
3401
3402 /* 
3403   lsa_LookupPrivValue
3404 */
3405 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call, 
3406                                     TALLOC_CTX *mem_ctx,
3407                                     struct lsa_LookupPrivValue *r)
3408 {
3409         struct dcesrv_handle *h;
3410         struct lsa_policy_state *state;
3411         int id;
3412
3413         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3414
3415         state = h->data;
3416
3417         id = sec_privilege_id(r->in.name->string);
3418         if (id == -1) {
3419                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3420         }
3421
3422         r->out.luid->low = id;
3423         r->out.luid->high = 0;
3424
3425         return NT_STATUS_OK;    
3426 }
3427
3428
3429 /* 
3430   lsa_LookupPrivName 
3431 */
3432 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call, 
3433                                    TALLOC_CTX *mem_ctx,
3434                                    struct lsa_LookupPrivName *r)
3435 {
3436         struct dcesrv_handle *h;
3437         struct lsa_policy_state *state;
3438         struct lsa_StringLarge *name;
3439         const char *privname;
3440
3441         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3442
3443         state = h->data;
3444
3445         if (r->in.luid->high != 0) {
3446                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3447         }
3448
3449         privname = sec_privilege_name(r->in.luid->low);
3450         if (privname == NULL) {
3451                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3452         }
3453
3454         name = talloc(mem_ctx, struct lsa_StringLarge);
3455         if (name == NULL) {
3456                 return NT_STATUS_NO_MEMORY;
3457         }
3458
3459         name->string = privname;
3460
3461         *r->out.name = name;
3462
3463         return NT_STATUS_OK;    
3464 }
3465
3466
3467 /* 
3468   lsa_LookupPrivDisplayName
3469 */
3470 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call, 
3471                                           TALLOC_CTX *mem_ctx,
3472                                           struct lsa_LookupPrivDisplayName *r)
3473 {
3474         struct dcesrv_handle *h;
3475         struct lsa_policy_state *state;
3476         struct lsa_StringLarge *disp_name = NULL;
3477         int id;
3478
3479         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3480
3481         state = h->data;
3482
3483         id = sec_privilege_id(r->in.name->string);
3484         if (id == -1) {
3485                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3486         }
3487
3488         disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3489         if (disp_name == NULL) {
3490                 return NT_STATUS_NO_MEMORY;
3491         }
3492
3493         disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3494         if (disp_name->string == NULL) {
3495                 return NT_STATUS_INTERNAL_ERROR;
3496         }
3497
3498         *r->out.disp_name = disp_name;
3499         *r->out.returned_language_id = 0;
3500
3501         return NT_STATUS_OK;
3502 }
3503
3504
3505 /* 
3506   lsa_EnumAccountsWithUserRight
3507 */
3508 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call, 
3509                                               TALLOC_CTX *mem_ctx,
3510                                               struct lsa_EnumAccountsWithUserRight *r)
3511 {
3512         struct dcesrv_handle *h;
3513         struct lsa_policy_state *state;
3514         int ret, i;
3515         struct ldb_message **res;
3516         const char * const attrs[] = { "objectSid", NULL};
3517         const char *privname;
3518
3519         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3520
3521         state = h->data;
3522
3523         if (r->in.name == NULL) {
3524                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3525         } 
3526
3527         privname = r->in.name->string;
3528         if (sec_privilege_id(privname) == -1) {
3529                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3530         }
3531
3532         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs, 
3533                            "privilege=%s", privname);
3534         if (ret < 0) {
3535                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3536         }
3537         if (ret == 0) {
3538                 return NT_STATUS_NO_MORE_ENTRIES;
3539         }
3540
3541         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3542         if (r->out.sids->sids == NULL) {
3543                 return NT_STATUS_NO_MEMORY;
3544         }
3545         for (i=0;i<ret;i++) {
3546                 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3547                                                                 res[i], "objectSid");
3548                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3549         }
3550         r->out.sids->num_sids = ret;
3551
3552         return NT_STATUS_OK;
3553 }
3554
3555
3556 /* 
3557   lsa_AddAccountRights
3558 */
3559 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call, 
3560                                      TALLOC_CTX *mem_ctx,
3561                                      struct lsa_AddAccountRights *r)
3562 {
3563         struct dcesrv_handle *h;
3564         struct lsa_policy_state *state;
3565
3566         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3567
3568         state = h->data;
3569
3570         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
3571                                           LDB_FLAG_MOD_ADD,
3572                                           r->in.sid, r->in.rights);
3573 }
3574
3575
3576 /* 
3577   lsa_RemoveAccountRights
3578 */
3579 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call, 
3580                                         TALLOC_CTX *mem_ctx,
3581                                         struct lsa_RemoveAccountRights *r)
3582 {
3583         struct dcesrv_handle *h;
3584         struct lsa_policy_state *state;
3585
3586         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3587
3588         state = h->data;
3589
3590         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
3591                                           LDB_FLAG_MOD_DELETE,
3592                                           r->in.sid, r->in.rights);
3593 }
3594
3595
3596 /* 
3597   lsa_StorePrivateData
3598 */
3599 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3600                        struct lsa_StorePrivateData *r)
3601 {
3602         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3603 }
3604
3605
3606 /* 
3607   lsa_RetrievePrivateData
3608 */
3609 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3610                        struct lsa_RetrievePrivateData *r)
3611 {
3612         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3613 }
3614
3615
3616 /* 
3617   lsa_GetUserName
3618 */
3619 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3620                                 struct lsa_GetUserName *r)
3621 {
3622         NTSTATUS status = NT_STATUS_OK;
3623         const char *account_name;
3624         const char *authority_name;
3625         struct lsa_String *_account_name;
3626         struct lsa_String *_authority_name = NULL;
3627
3628         /* this is what w2k3 does */
3629         r->out.account_name = r->in.account_name;
3630         r->out.authority_name = r->in.authority_name;
3631
3632         if (r->in.account_name
3633             && *r->in.account_name
3634             /* && *(*r->in.account_name)->string */
3635             ) {
3636                 return NT_STATUS_INVALID_PARAMETER;
3637         }
3638
3639         if (r->in.authority_name
3640             && *r->in.authority_name
3641             /* && *(*r->in.authority_name)->string */
3642             ) {
3643                 return NT_STATUS_INVALID_PARAMETER;
3644         }
3645
3646         account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->account_name);
3647         authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->domain_name);
3648
3649         _account_name = talloc(mem_ctx, struct lsa_String);
3650         NT_STATUS_HAVE_NO_MEMORY(_account_name);
3651         _account_name->string = account_name;
3652
3653         if (r->in.authority_name) {
3654                 _authority_name = talloc(mem_ctx, struct lsa_String);
3655                 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3656                 _authority_name->string = authority_name;
3657         }
3658
3659         *r->out.account_name = _account_name;
3660         if (r->out.authority_name) {
3661                 *r->out.authority_name = _authority_name;
3662         }
3663
3664         return status;
3665 }
3666
3667 /*
3668   lsa_SetInfoPolicy2
3669 */
3670 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3671                                    TALLOC_CTX *mem_ctx,
3672                                    struct lsa_SetInfoPolicy2 *r)
3673 {
3674         /* need to support these */
3675         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3676 }
3677
3678 /*
3679   lsa_QueryDomainInformationPolicy
3680 */
3681 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3682                                                  TALLOC_CTX *mem_ctx,
3683                                                  struct lsa_QueryDomainInformationPolicy *r)
3684 {
3685         union lsa_DomainInformationPolicy *info;
3686
3687         info = talloc(r->out.info, union lsa_DomainInformationPolicy);
3688         if (!info) {
3689                 return NT_STATUS_NO_MEMORY;
3690         }
3691
3692         switch (r->in.level) {
3693         case LSA_DOMAIN_INFO_POLICY_EFS:
3694                 talloc_free(info);
3695                 *r->out.info = NULL;
3696                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3697         case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3698         {
3699                 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3700                 struct smb_krb5_context *smb_krb5_context;
3701                 int ret = smb_krb5_init_context(mem_ctx, 
3702                                                         dce_call->event_ctx, 
3703                                                         dce_call->conn->dce_ctx->lp_ctx,
3704                                                         &smb_krb5_context);
3705                 if (ret != 0) {
3706                         talloc_free(info);
3707                         *r->out.info = NULL;
3708                         return NT_STATUS_INTERNAL_ERROR;
3709                 }
3710                 k->enforce_restrictions = 0; /* FIXME, details missing from MS-LSAD 2.2.53 */
3711                 k->service_tkt_lifetime = 0; /* Need to find somewhere to store this, and query in KDC too */
3712                 k->user_tkt_lifetime = 0;    /* Need to find somewhere to store this, and query in KDC too */
3713                 k->user_tkt_renewaltime = 0; /* Need to find somewhere to store this, and query in KDC too */
3714                 k->clock_skew = krb5_get_max_time_skew(smb_krb5_context->krb5_context);
3715                 talloc_free(smb_krb5_context);
3716                 *r->out.info = info;
3717                 return NT_STATUS_OK;
3718         }
3719         default:
3720                 talloc_free(info);
3721                 *r->out.info = NULL;
3722                 return NT_STATUS_INVALID_INFO_CLASS;
3723         }
3724 }
3725
3726 /*
3727   lsa_SetDomInfoPolicy
3728 */
3729 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3730                                               TALLOC_CTX *mem_ctx,
3731                                               struct lsa_SetDomainInformationPolicy *r)
3732 {
3733         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3734 }
3735
3736 /*
3737   lsa_TestCall
3738 */
3739 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3740                              TALLOC_CTX *mem_ctx,
3741                              struct lsa_TestCall *r)
3742 {
3743         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3744 }
3745
3746 /* 
3747   lsa_CREDRWRITE 
3748 */
3749 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3750                        struct lsa_CREDRWRITE *r)
3751 {
3752         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3753 }
3754
3755
3756 /* 
3757   lsa_CREDRREAD 
3758 */
3759 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3760                        struct lsa_CREDRREAD *r)
3761 {
3762         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3763 }
3764
3765
3766 /* 
3767   lsa_CREDRENUMERATE 
3768 */
3769 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3770                        struct lsa_CREDRENUMERATE *r)
3771 {
3772         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3773 }
3774
3775
3776 /* 
3777   lsa_CREDRWRITEDOMAINCREDENTIALS 
3778 */
3779 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3780                        struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3781 {
3782         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3783 }
3784
3785
3786 /* 
3787   lsa_CREDRREADDOMAINCREDENTIALS 
3788 */
3789 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3790                        struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3791 {
3792         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3793 }
3794
3795
3796 /* 
3797   lsa_CREDRDELETE 
3798 */
3799 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3800                        struct lsa_CREDRDELETE *r)
3801 {
3802         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3803 }
3804
3805
3806 /* 
3807   lsa_CREDRGETTARGETINFO 
3808 */
3809 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3810                        struct lsa_CREDRGETTARGETINFO *r)
3811 {
3812         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3813 }
3814
3815
3816 /* 
3817   lsa_CREDRPROFILELOADED 
3818 */
3819 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3820                        struct lsa_CREDRPROFILELOADED *r)
3821 {
3822         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3823 }
3824
3825
3826 /* 
3827   lsa_CREDRGETSESSIONTYPES 
3828 */
3829 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3830                        struct lsa_CREDRGETSESSIONTYPES *r)
3831 {
3832         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3833 }
3834
3835
3836 /* 
3837   lsa_LSARREGISTERAUDITEVENT 
3838 */
3839 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3840                        struct lsa_LSARREGISTERAUDITEVENT *r)
3841 {
3842         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3843 }
3844
3845
3846 /* 
3847   lsa_LSARGENAUDITEVENT 
3848 */
3849 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3850                        struct lsa_LSARGENAUDITEVENT *r)
3851 {
3852         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3853 }
3854
3855
3856 /* 
3857   lsa_LSARUNREGISTERAUDITEVENT 
3858 */
3859 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3860                        struct lsa_LSARUNREGISTERAUDITEVENT *r)
3861 {
3862         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3863 }
3864
3865
3866 /* 
3867   lsa_lsaRQueryForestTrustInformation 
3868 */
3869 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3870                        struct lsa_lsaRQueryForestTrustInformation *r)
3871 {
3872         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3873 }
3874
3875 #define DNS_CMP_MATCH 0
3876 #define DNS_CMP_FIRST_IS_CHILD 1
3877 #define DNS_CMP_SECOND_IS_CHILD 2
3878 #define DNS_CMP_NO_MATCH 3
3879
3880 /* this function assumes names are well formed DNS names.
3881  * it doesn't validate them */
3882 static int dns_cmp(const char *s1, size_t l1,
3883                    const char *s2, size_t l2)
3884 {
3885         const char *p1, *p2;
3886         size_t t1, t2;
3887         int cret;
3888
3889         if (l1 == l2) {
3890                 if (strcasecmp_m(s1, s2) == 0) {
3891                         return DNS_CMP_MATCH;
3892                 }
3893                 return DNS_CMP_NO_MATCH;
3894         }
3895
3896         if (l1 > l2) {
3897                 p1 = s1;
3898                 p2 = s2;
3899                 t1 = l1;
3900                 t2 = l2;
3901                 cret = DNS_CMP_FIRST_IS_CHILD;
3902         } else {
3903                 p1 = s2;
3904                 p2 = s1;
3905                 t1 = l2;
3906                 t2 = l1;
3907                 cret = DNS_CMP_SECOND_IS_CHILD;
3908         }
3909
3910         if (p1[t1 - t2 - 1] != '.') {
3911                 return DNS_CMP_NO_MATCH;
3912         }
3913
3914         if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
3915                 return cret;
3916         }
3917
3918         return DNS_CMP_NO_MATCH;
3919 }
3920
3921 /* decode all TDOs forest trust info blobs */
3922 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
3923                             struct ldb_message *msg,
3924                             struct ForestTrustInfo *info)
3925 {
3926         const struct ldb_val *ft_blob;
3927         enum ndr_err_code ndr_err;
3928
3929         ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3930         if (!ft_blob || !ft_blob->data) {
3931                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3932         }
3933         /* ldb_val is equivalent to DATA_BLOB */
3934         ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
3935                                            (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
3936         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3937                 return NT_STATUS_INVALID_DOMAIN_STATE;
3938         }
3939
3940         return NT_STATUS_OK;
3941 }
3942
3943 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
3944                             struct ForestTrustInfo *fti)
3945 {
3946         struct ForestTrustDataDomainInfo *info;
3947         struct ForestTrustInfoRecord *rec;
3948
3949         fti->version = 1;
3950         fti->count = 2;
3951         fti->records = talloc_array(fti,
3952                                     struct ForestTrustInfoRecordArmor, 2);
3953         if (!fti->records) {
3954                 return NT_STATUS_NO_MEMORY;
3955         }
3956
3957         /* TLN info */
3958         rec = &fti->records[0].record;
3959
3960         rec->flags = 0;
3961         rec->timestamp = 0;
3962         rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
3963
3964         rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
3965         if (!rec->data.name.string) {
3966                 return NT_STATUS_NO_MEMORY;
3967         }
3968         rec->data.name.size = strlen(rec->data.name.string);
3969
3970         /* DOMAIN info */
3971         rec = &fti->records[1].record;
3972
3973         rec->flags = 0;
3974         rec->timestamp = 0;
3975         rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
3976
3977         info = &rec->data.info;
3978
3979         info->sid = *ps->domain_sid;
3980         info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
3981         if (!info->dns_name.string) {
3982                 return NT_STATUS_NO_MEMORY;
3983         }
3984         info->dns_name.size = strlen(info->dns_name.string);
3985         info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
3986         if (!info->netbios_name.string) {
3987                 return NT_STATUS_NO_MEMORY;
3988         }
3989         info->netbios_name.size = strlen(info->netbios_name.string);
3990
3991         return NT_STATUS_OK;
3992 }
3993
3994 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
3995                              struct lsa_ForestTrustInformation *lfti,
3996                              struct ForestTrustInfo *fti)
3997 {
3998         struct lsa_ForestTrustRecord *lrec;
3999         struct ForestTrustInfoRecord *rec;
4000         struct lsa_StringLarge *tln;
4001         struct lsa_ForestTrustDomainInfo *info;
4002         uint32_t i;
4003
4004         fti->version = 1;
4005         fti->count = lfti->count;
4006         fti->records = talloc_array(mem_ctx,
4007                                     struct ForestTrustInfoRecordArmor,
4008                                     fti->count);
4009         if (!fti->records) {
4010                 return NT_STATUS_NO_MEMORY;
4011         }
4012         for (i = 0; i < fti->count; i++) {
4013                 lrec = lfti->entries[i];
4014                 rec = &fti->records[i].record;
4015
4016                 rec->flags = lrec->flags;
4017                 rec->timestamp = lrec->time;
4018                 rec->type = lrec->type;
4019
4020                 switch (lrec->type) {
4021                 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4022                 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4023                         tln = &lrec->forest_trust_data.top_level_name;
4024                         rec->data.name.string =
4025                                 talloc_strdup(mem_ctx, tln->string);
4026                         if (!rec->data.name.string) {
4027                                 return NT_STATUS_NO_MEMORY;
4028                         }
4029                         rec->data.name.size = strlen(rec->data.name.string);
4030                         break;
4031                 case LSA_FOREST_TRUST_DOMAIN_INFO:
4032                         info = &lrec->forest_trust_data.domain_info;
4033                         rec->data.info.sid = *info->domain_sid;
4034                         rec->data.info.dns_name.string =
4035                                 talloc_strdup(mem_ctx,
4036                                             info->dns_domain_name.string);
4037                         if (!rec->data.info.dns_name.string) {
4038                                 return NT_STATUS_NO_MEMORY;
4039                         }
4040                         rec->data.info.dns_name.size =
4041                                 strlen(rec->data.info.dns_name.string);
4042                         rec->data.info.netbios_name.string =
4043                                 talloc_strdup(mem_ctx,
4044                                             info->netbios_domain_name.string);
4045                         if (!rec->data.info.netbios_name.string) {
4046                                 return NT_STATUS_NO_MEMORY;
4047                         }
4048                         rec->data.info.netbios_name.size =
4049                                 strlen(rec->data.info.netbios_name.string);
4050                         break;
4051                 default:
4052                         return NT_STATUS_INVALID_DOMAIN_STATE;
4053                 }
4054         }
4055
4056         return NT_STATUS_OK;
4057 }
4058
4059 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4060                               uint32_t index, uint32_t collision_type,
4061                               uint32_t conflict_type, const char *tdo_name);
4062
4063 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4064                               const char *tdo_name,
4065                               struct ForestTrustInfo *tdo_fti,
4066                               struct ForestTrustInfo *new_fti,
4067                               struct lsa_ForestTrustCollisionInfo *c_info)
4068 {
4069         struct ForestTrustInfoRecord *nrec;
4070         struct ForestTrustInfoRecord *trec;
4071         const char *dns_name;
4072         const char *nb_name;
4073         struct dom_sid *sid;
4074         const char *tname;
4075         size_t dns_len;
4076         size_t nb_len;
4077         size_t tlen;
4078         NTSTATUS nt_status;
4079         uint32_t new_fti_idx;
4080         uint32_t i;
4081         /* use always TDO type, until we understand when Xref can be used */
4082         uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4083         bool tln_conflict;
4084         bool sid_conflict;
4085         bool nb_conflict;
4086         bool exclusion;
4087         bool ex_rule;
4088         int ret;
4089
4090         for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4091
4092                 nrec = &new_fti->records[new_fti_idx].record;
4093                 dns_name = NULL;
4094                 tln_conflict = false;
4095                 sid_conflict = false;
4096                 nb_conflict = false;
4097                 exclusion = false;
4098
4099                 switch (nrec->type) {
4100                 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4101                         /* exclusions do not conflict by definition */
4102                         break;
4103
4104                 case FOREST_TRUST_TOP_LEVEL_NAME:
4105                         dns_name = nrec->data.name.string;
4106                         dns_len = nrec->data.name.size;
4107                         break;
4108
4109                 case LSA_FOREST_TRUST_DOMAIN_INFO:
4110                         dns_name = nrec->data.info.dns_name.string;
4111                         dns_len = nrec->data.info.dns_name.size;
4112                         nb_name = nrec->data.info.netbios_name.string;
4113                         nb_len = nrec->data.info.netbios_name.size;
4114                         sid = &nrec->data.info.sid;
4115                         break;
4116                 }
4117
4118                 if (!dns_name) continue;
4119
4120                 /* check if this is already taken and not excluded */
4121                 for (i = 0; i < tdo_fti->count; i++) {
4122                         trec = &tdo_fti->records[i].record;
4123
4124                         switch (trec->type) {
4125                         case FOREST_TRUST_TOP_LEVEL_NAME:
4126                                 ex_rule = false;
4127                                 tname = trec->data.name.string;
4128                                 tlen = trec->data.name.size;
4129                                 break;
4130                         case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4131                                 ex_rule = true;
4132                                 tname = trec->data.name.string;
4133                                 tlen = trec->data.name.size;
4134                                 break;
4135                         case FOREST_TRUST_DOMAIN_INFO:
4136                                 ex_rule = false;
4137                                 tname = trec->data.info.dns_name.string;
4138                                 tlen = trec->data.info.dns_name.size;
4139                         }
4140                         ret = dns_cmp(dns_name, dns_len, tname, tlen);
4141                         switch (ret) {
4142                         case DNS_CMP_MATCH:
4143                                 /* if it matches exclusion,
4144                                  * it doesn't conflict */
4145                                 if (ex_rule) {
4146                                         exclusion = true;
4147                                         break;
4148                                 }
4149                                 /* fall through */
4150                         case DNS_CMP_FIRST_IS_CHILD:
4151                         case DNS_CMP_SECOND_IS_CHILD:
4152                                 tln_conflict = true;
4153                                 /* fall through */
4154                         default:
4155                                 break;
4156                         }
4157
4158                         /* explicit exclusion, no dns name conflict here */
4159                         if (exclusion) {
4160                                 tln_conflict = false;
4161                         }
4162
4163                         if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4164                                 continue;
4165                         }
4166
4167                         /* also test for domain info */
4168                         if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4169                             dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4170                                 sid_conflict = true;
4171                         }
4172                         if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4173                             strcasecmp_m(trec->data.info.netbios_name.string,
4174                                          nb_name) == 0) {
4175                                 nb_conflict = true;
4176                         }
4177                 }
4178
4179                 if (tln_conflict) {
4180                         nt_status = add_collision(c_info, new_fti_idx,
4181                                                   collision_type,
4182                                                   LSA_TLN_DISABLED_CONFLICT,
4183                                                   tdo_name);
4184                 }
4185                 if (sid_conflict) {
4186                         nt_status = add_collision(c_info, new_fti_idx,
4187                                                   collision_type,
4188                                                   LSA_SID_DISABLED_CONFLICT,
4189                                                   tdo_name);
4190                 }
4191                 if (nb_conflict) {
4192                         nt_status = add_collision(c_info, new_fti_idx,
4193                                                   collision_type,
4194                                                   LSA_NB_DISABLED_CONFLICT,
4195                                                   tdo_name);
4196                 }
4197         }
4198
4199         return NT_STATUS_OK;
4200 }
4201
4202 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4203                               uint32_t idx, uint32_t collision_type,
4204                               uint32_t conflict_type, const char *tdo_name)
4205 {
4206         struct lsa_ForestTrustCollisionRecord **es;
4207         uint32_t i = c_info->count;
4208
4209         es = talloc_realloc(c_info, c_info->entries,
4210                             struct lsa_ForestTrustCollisionRecord *, i + 1);
4211         if (!es) {
4212                 return NT_STATUS_NO_MEMORY;
4213         }
4214         c_info->entries = es;
4215         c_info->count = i + 1;
4216
4217         es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4218         if (!es[i]) {
4219                 return NT_STATUS_NO_MEMORY;
4220         }
4221
4222         es[i]->index = idx;
4223         es[i]->type = collision_type;
4224         es[i]->flags.flags = conflict_type;
4225         es[i]->name.string = talloc_strdup(es[i], tdo_name);
4226         if (!es[i]->name.string) {
4227                 return NT_STATUS_NO_MEMORY;
4228         }
4229         es[i]->name.size = strlen(es[i]->name.string);
4230
4231         return NT_STATUS_OK;
4232 }
4233
4234 /*
4235   lsa_lsaRSetForestTrustInformation
4236 */
4237 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4238                                                          TALLOC_CTX *mem_ctx,
4239                                                          struct lsa_lsaRSetForestTrustInformation *r)
4240 {
4241         struct dcesrv_handle *h;
4242         struct lsa_policy_state *p_state;
4243         const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4244                                       "msDS-TrustForestTrustInfo", NULL };
4245         struct ldb_message **dom_res = NULL;
4246         struct ldb_dn *tdo_dn;
4247         struct ldb_message *msg;
4248         int num_res, i;
4249         const char *td_name;
4250         uint32_t trust_attributes;
4251         struct lsa_ForestTrustCollisionInfo *c_info;
4252         struct ForestTrustInfo *nfti;
4253         struct ForestTrustInfo *fti;
4254         DATA_BLOB ft_blob;
4255         enum ndr_err_code ndr_err;
4256         NTSTATUS nt_status;
4257         bool am_rodc;
4258         int ret;
4259
4260         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4261
4262         p_state = h->data;
4263
4264         if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4265                 return NT_STATUS_INVALID_DOMAIN_STATE;
4266         }
4267
4268         /* abort if we are not a PDC */
4269         if (!samdb_is_pdc(p_state->sam_ldb)) {
4270                 return NT_STATUS_INVALID_DOMAIN_ROLE;
4271         }
4272
4273         ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
4274         if (ret == LDB_SUCCESS && am_rodc) {
4275                 return NT_STATUS_NO_SUCH_DOMAIN;
4276         }
4277
4278         /* check caller has TRUSTED_SET_AUTH */
4279
4280         /* fetch all trusted domain objects */
4281         num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4282                                p_state->system_dn,
4283                                &dom_res, trust_attrs,
4284                                "(objectclass=trustedDomain)");
4285         if (num_res == 0) {
4286                 return NT_STATUS_NO_SUCH_DOMAIN;
4287         }
4288
4289         for (i = 0; i < num_res; i++) {
4290                 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4291                                                       "trustPartner", NULL);
4292                 if (!td_name) {
4293                         return NT_STATUS_INVALID_DOMAIN_STATE;
4294                 }
4295                 if (strcasecmp_m(td_name,
4296                                  r->in.trusted_domain_name->string) == 0) {
4297                         break;
4298                 }
4299         }
4300         if (i >= num_res) {
4301                 return NT_STATUS_NO_SUCH_DOMAIN;
4302         }
4303
4304         tdo_dn = dom_res[i]->dn;
4305
4306         trust_attributes = samdb_result_uint(dom_res[i],
4307                                              "trustAttributes", 0);
4308         if (!(trust_attributes & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4309                 return NT_STATUS_INVALID_PARAMETER;
4310         }
4311
4312         if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4313                 return NT_STATUS_INVALID_PARAMETER;
4314         }
4315
4316         nfti = talloc(mem_ctx, struct ForestTrustInfo);
4317         if (!nfti) {
4318                 return NT_STATUS_NO_MEMORY;
4319         }
4320
4321         nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4322         if (!NT_STATUS_IS_OK(nt_status)) {
4323                 return nt_status;
4324         }
4325
4326         c_info = talloc_zero(r->out.collision_info,
4327                              struct lsa_ForestTrustCollisionInfo);
4328         if (!c_info) {
4329                 return NT_STATUS_NO_MEMORY;
4330         }
4331
4332         /* first check own info, then other domains */
4333         fti = talloc(mem_ctx, struct ForestTrustInfo);
4334         if (!fti) {
4335                 return NT_STATUS_NO_MEMORY;
4336         }
4337
4338         nt_status = own_ft_info(p_state, fti);
4339         if (!NT_STATUS_IS_OK(nt_status)) {
4340                 return nt_status;
4341         }
4342
4343         nt_status = check_ft_info(c_info, p_state->domain_dns,
4344                                   fti, nfti, c_info);
4345         if (!NT_STATUS_IS_OK(nt_status)) {
4346                 return nt_status;
4347         }
4348
4349         for (i = 0; i < num_res; i++) {
4350                 fti = talloc(mem_ctx, struct ForestTrustInfo);
4351                 if (!fti) {
4352                         return NT_STATUS_NO_MEMORY;
4353                 }
4354
4355                 nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
4356                 if (!NT_STATUS_IS_OK(nt_status)) {
4357                         if (NT_STATUS_EQUAL(nt_status,
4358                             NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4359                                 continue;
4360                         }
4361                         return nt_status;
4362                 }
4363
4364                 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4365                                                       "trustPartner", NULL);
4366                 if (!td_name) {
4367                         return NT_STATUS_INVALID_DOMAIN_STATE;
4368                 }
4369
4370                 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4371                 if (!NT_STATUS_IS_OK(nt_status)) {
4372                         return nt_status;
4373                 }
4374         }
4375
4376         *r->out.collision_info = c_info;
4377
4378         if (r->in.check_only != 0) {
4379                 return NT_STATUS_OK;
4380         }
4381
4382         /* not just a check, write info back */
4383
4384         ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
4385                                        (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4386         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4387                 return NT_STATUS_INVALID_PARAMETER;
4388         }
4389
4390         msg = ldb_msg_new(mem_ctx);
4391         if (msg == NULL) {
4392                 return NT_STATUS_NO_MEMORY;
4393         }
4394
4395         msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4396         if (!msg->dn) {
4397                 return NT_STATUS_NO_MEMORY;
4398         }
4399
4400         ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4401                                 LDB_FLAG_MOD_REPLACE, NULL);
4402         if (ret != LDB_SUCCESS) {
4403                 return NT_STATUS_NO_MEMORY;
4404         }
4405         ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4406                                 &ft_blob, NULL);
4407         if (ret != LDB_SUCCESS) {
4408                 return NT_STATUS_NO_MEMORY;
4409         }
4410
4411         ret = ldb_modify(p_state->sam_ldb, msg);
4412         if (ret != LDB_SUCCESS) {
4413                 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4414                           ldb_errstring(p_state->sam_ldb)));
4415
4416                 switch (ret) {
4417                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4418                         return NT_STATUS_ACCESS_DENIED;
4419                 default:
4420                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
4421                 }
4422         }
4423
4424         return NT_STATUS_OK;
4425 }
4426
4427 /* 
4428   lsa_CREDRRENAME 
4429 */
4430 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4431                        struct lsa_CREDRRENAME *r)
4432 {
4433         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4434 }
4435
4436
4437
4438 /* 
4439   lsa_LSAROPENPOLICYSCE 
4440 */
4441 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4442                        struct lsa_LSAROPENPOLICYSCE *r)
4443 {
4444         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4445 }
4446
4447
4448 /* 
4449   lsa_LSARADTREGISTERSECURITYEVENTSOURCE 
4450 */
4451 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4452                        struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4453 {
4454         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4455 }
4456
4457
4458 /* 
4459   lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE 
4460 */
4461 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4462                        struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4463 {
4464         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4465 }
4466
4467
4468 /* 
4469   lsa_LSARADTREPORTSECURITYEVENT 
4470 */
4471 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4472                        struct lsa_LSARADTREPORTSECURITYEVENT *r)
4473 {
4474         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4475 }
4476
4477
4478 /* include the generated boilerplate */
4479 #include "librpc/gen_ndr/ndr_lsa_s.c"
4480
4481
4482
4483 /*****************************************
4484 NOTE! The remaining calls below were
4485 removed in w2k3, so the DCESRV_FAULT()
4486 replies are the correct implementation. Do
4487 not try and fill these in with anything else
4488 ******************************************/
4489
4490 /* 
4491   dssetup_DsRoleDnsNameToFlatName 
4492 */
4493 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4494                                         struct dssetup_DsRoleDnsNameToFlatName *r)
4495 {
4496         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4497 }
4498
4499
4500 /* 
4501   dssetup_DsRoleDcAsDc 
4502 */
4503 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4504                              struct dssetup_DsRoleDcAsDc *r)
4505 {
4506         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4507 }
4508
4509
4510 /* 
4511   dssetup_DsRoleDcAsReplica 
4512 */
4513 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4514                                   struct dssetup_DsRoleDcAsReplica *r)
4515 {
4516         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4517 }
4518
4519
4520 /* 
4521   dssetup_DsRoleDemoteDc 
4522 */
4523 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4524                                struct dssetup_DsRoleDemoteDc *r)
4525 {
4526         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4527 }
4528
4529
4530 /* 
4531   dssetup_DsRoleGetDcOperationProgress 
4532 */
4533 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4534                                              struct dssetup_DsRoleGetDcOperationProgress *r)
4535 {
4536         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4537 }
4538
4539
4540 /* 
4541   dssetup_DsRoleGetDcOperationResults 
4542 */
4543 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4544                                             struct dssetup_DsRoleGetDcOperationResults *r)
4545 {
4546         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4547 }
4548
4549
4550 /* 
4551   dssetup_DsRoleCancel 
4552 */
4553 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4554                              struct dssetup_DsRoleCancel *r)
4555 {
4556         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4557 }
4558
4559
4560 /* 
4561   dssetup_DsRoleServerSaveStateForUpgrade 
4562 */
4563 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4564                                                 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4565 {
4566         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4567 }
4568
4569
4570 /* 
4571   dssetup_DsRoleUpgradeDownlevelServer 
4572 */
4573 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4574                                              struct dssetup_DsRoleUpgradeDownlevelServer *r)
4575 {
4576         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4577 }
4578
4579
4580 /* 
4581   dssetup_DsRoleAbortDownlevelServerUpgrade 
4582 */
4583 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4584                                                   struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4585 {
4586         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4587 }
4588
4589
4590 /* include the generated boilerplate */
4591 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4592
4593 NTSTATUS dcerpc_server_lsa_init(void)
4594 {
4595         NTSTATUS ret;
4596         
4597         ret = dcerpc_server_dssetup_init();
4598         if (!NT_STATUS_IS_OK(ret)) {
4599                 return ret;
4600         }
4601         ret = dcerpc_server_lsarpc_init();
4602         if (!NT_STATUS_IS_OK(ret)) {
4603                 return ret;
4604         }
4605         return ret;
4606 }