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