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