kerberos: Remove un-used event context argument from smb_krb5_init_context()
[samba.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
1 /* need access mask/acl implementation */
2
3 /* 
4    Unix SMB/CIFS implementation.
5
6    endpoint server for the lsarpc pipe
7
8    Copyright (C) Andrew Tridgell 2004
9    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "rpc_server/lsa/lsa.h"
26 #include "system/kerberos.h"
27 #include "auth/kerberos/kerberos.h"
28 #include "librpc/gen_ndr/ndr_drsblobs.h"
29 #include "librpc/gen_ndr/ndr_lsa.h"
30 #include "../lib/crypto/crypto.h"
31 #include "lib/util/tsort.h"
32 #include "dsdb/common/util.h"
33 #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 dcesrv_handle *p_handle,
1604                                           TALLOC_CTX *mem_ctx,
1605                                           struct ldb_message *dom_msg,
1606                                           enum lsa_TrustDomInfoEnum level,
1607                                           union lsa_TrustedDomainInfo *info)
1608 {
1609         struct lsa_policy_state *p_state = p_handle->data;
1610         uint32_t *posix_offset = NULL;
1611         struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1612         struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1613         struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1614         uint32_t *enc_types = NULL;
1615         DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1616         struct trustDomainPasswords auth_struct;
1617         struct trustAuthInOutBlob *current_passwords = NULL;
1618         NTSTATUS nt_status;
1619         struct ldb_message **msgs;
1620         struct ldb_message *msg;
1621         bool add_outgoing = false;
1622         bool add_incoming = false;
1623         bool del_outgoing = false;
1624         bool del_incoming = false;
1625         bool in_transaction = false;
1626         int ret;
1627         bool am_rodc;
1628
1629         switch (level) {
1630         case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1631                 posix_offset = &info->posix_offset.posix_offset;
1632                 break;
1633         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1634                 info_ex = &info->info_ex;
1635                 break;
1636         case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1637                 auth_info = &info->auth_info;
1638                 break;
1639         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1640                 posix_offset = &info->full_info.posix_offset.posix_offset;
1641                 info_ex = &info->full_info.info_ex;
1642                 auth_info = &info->full_info.auth_info;
1643                 break;
1644         case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1645                 auth_info_int = &info->auth_info_internal;
1646                 break;
1647         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1648                 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1649                 info_ex = &info->full_info_internal.info_ex;
1650                 auth_info_int = &info->full_info_internal.auth_info;
1651                 break;
1652         case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1653                 enc_types = &info->enc_types.enc_types;
1654                 break;
1655         default:
1656                 return NT_STATUS_INVALID_PARAMETER;
1657         }
1658
1659         if (auth_info) {
1660                 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1661                                                   &trustAuthIncoming,
1662                                                   &trustAuthOutgoing);
1663                 if (!NT_STATUS_IS_OK(nt_status)) {
1664                         return nt_status;
1665                 }
1666                 if (trustAuthIncoming.data) {
1667                         /* This does the decode of some of this twice, but it is easier that way */
1668                         nt_status = auth_info_2_trustauth_inout(mem_ctx,
1669                                                                 auth_info->incoming_count,
1670                                                                 auth_info->incoming_current_auth_info,
1671                                                                 NULL,
1672                                                                 &current_passwords);
1673                         if (!NT_STATUS_IS_OK(nt_status)) {
1674                                 return nt_status;
1675                         }
1676                 }
1677         }
1678
1679         /* decode auth_info_int if set */
1680         if (auth_info_int) {
1681
1682                 /* now decrypt blob */
1683                 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1684                                             auth_info_int->auth_blob.size);
1685
1686                 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1687                                                    &auth_blob, &auth_struct);
1688                 if (!NT_STATUS_IS_OK(nt_status)) {
1689                         return nt_status;
1690                 }
1691         }
1692
1693         if (info_ex) {
1694                 /* verify data matches */
1695                 if (info_ex->trust_attributes &
1696                     LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1697                         /* TODO: check what behavior level we have */
1698                        if (strcasecmp_m(p_state->domain_dns,
1699                                         p_state->forest_dns) != 0) {
1700                                 return NT_STATUS_INVALID_DOMAIN_STATE;
1701                         }
1702                 }
1703
1704                 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1705                 if (ret == LDB_SUCCESS && am_rodc) {
1706                         return NT_STATUS_NO_SUCH_DOMAIN;
1707                 }
1708
1709                 /* verify only one object matches the dns/netbios/sid
1710                  * triplet and that this is the one we already have */
1711                 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1712                                     p_state->system_dn,
1713                                     info_ex->domain_name.string,
1714                                     info_ex->netbios_name.string,
1715                                     info_ex->sid, &msgs);
1716                 if (!NT_STATUS_IS_OK(nt_status)) {
1717                         return nt_status;
1718                 }
1719                 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1720                         return NT_STATUS_OBJECT_NAME_COLLISION;
1721                 }
1722                 talloc_free(msgs);
1723         }
1724
1725         /* TODO: should we fetch previous values from the existing entry
1726          * and append them ? */
1727         if (auth_info_int && auth_struct.incoming.count) {
1728                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1729                                                      &auth_struct.incoming,
1730                                                      &trustAuthIncoming);
1731                 if (!NT_STATUS_IS_OK(nt_status)) {
1732                         return nt_status;
1733                 }
1734
1735                 current_passwords = &auth_struct.incoming;
1736
1737         } else {
1738                 trustAuthIncoming = data_blob(NULL, 0);
1739         }
1740
1741         if (auth_info_int && auth_struct.outgoing.count) {
1742                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1743                                                      &auth_struct.outgoing,
1744                                                      &trustAuthOutgoing);
1745                 if (!NT_STATUS_IS_OK(nt_status)) {
1746                         return nt_status;
1747                 }
1748         } else {
1749                 trustAuthOutgoing = data_blob(NULL, 0);
1750         }
1751
1752         msg = ldb_msg_new(mem_ctx);
1753         if (msg == NULL) {
1754                 return NT_STATUS_NO_MEMORY;
1755         }
1756         msg->dn = dom_msg->dn;
1757
1758         if (posix_offset) {
1759                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1760                                                   dom_msg, msg,
1761                                                   "trustPosixOffset",
1762                                                   *posix_offset, NULL);
1763                 if (!NT_STATUS_IS_OK(nt_status)) {
1764                         return nt_status;
1765                 }
1766         }
1767
1768         if (info_ex) {
1769                 uint32_t origattrs;
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                         add_incoming = true;
1784                 }
1785                 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
1786                         add_outgoing = true;
1787                 }
1788
1789                 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
1790                     !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
1791                         del_incoming = true;
1792                 }
1793                 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
1794                     !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
1795                         del_outgoing = true;
1796                 }
1797
1798                 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
1799                 if (origtype == -1 || origtype != info_ex->trust_type) {
1800                         DEBUG(1, ("Attempted to change trust type! "
1801                                   "Operation not handled\n"));
1802                         return NT_STATUS_INVALID_PARAMETER;
1803                 }
1804
1805                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1806                                                   dom_msg, msg,
1807                                                   "trustAttributes",
1808                                                   info_ex->trust_attributes,
1809                                                   &origattrs);
1810                 if (!NT_STATUS_IS_OK(nt_status)) {
1811                         return nt_status;
1812                 }
1813                 /* TODO: check forestFunctionality from ldb opaque */
1814                 /* TODO: check what is set makes sense */
1815                 /* for now refuse changes */
1816                 if (origattrs == -1 ||
1817                     origattrs != info_ex->trust_attributes) {
1818                         DEBUG(1, ("Attempted to change trust attributes! "
1819                                   "Operation not handled\n"));
1820                         return NT_STATUS_INVALID_PARAMETER;
1821                 }
1822         }
1823
1824         if (enc_types) {
1825                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1826                                                   dom_msg, msg,
1827                                                   "msDS-SupportedEncryptionTypes",
1828                                                   *enc_types, NULL);
1829                 if (!NT_STATUS_IS_OK(nt_status)) {
1830                         return nt_status;
1831                 }
1832         }
1833
1834         if (add_incoming && trustAuthIncoming.data) {
1835                 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1836                                         LDB_FLAG_MOD_REPLACE, NULL);
1837                 if (ret != LDB_SUCCESS) {
1838                         return NT_STATUS_NO_MEMORY;
1839                 }
1840                 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
1841                                         &trustAuthIncoming, NULL);
1842                 if (ret != LDB_SUCCESS) {
1843                         return NT_STATUS_NO_MEMORY;
1844                 }
1845         }
1846         if (add_outgoing && trustAuthOutgoing.data) {
1847                 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
1848                                         LDB_FLAG_MOD_REPLACE, NULL);
1849                 if (ret != LDB_SUCCESS) {
1850                         return NT_STATUS_NO_MEMORY;
1851                 }
1852                 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1853                                         &trustAuthOutgoing, NULL);
1854                 if (ret != LDB_SUCCESS) {
1855                         return NT_STATUS_NO_MEMORY;
1856                 }
1857         }
1858
1859         /* start transaction */
1860         ret = ldb_transaction_start(p_state->sam_ldb);
1861         if (ret != LDB_SUCCESS) {
1862                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1863         }
1864         in_transaction = true;
1865
1866         if (msg->num_elements) {
1867                 ret = ldb_modify(p_state->sam_ldb, msg);
1868                 if (ret != LDB_SUCCESS) {
1869                         DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1870                                  ldb_dn_get_linearized(msg->dn),
1871                                  ldb_errstring(p_state->sam_ldb)));
1872                         nt_status = dsdb_ldb_err_to_ntstatus(ret);
1873                         goto done;
1874                 }
1875         }
1876
1877         if (add_incoming || del_incoming) {
1878                 const char *netbios_name;
1879
1880                 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
1881                                                            "flatname", NULL);
1882                 if (!netbios_name) {
1883                         nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
1884                         goto done;
1885                 }
1886
1887                 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
1888                 nt_status = update_trust_user(mem_ctx,
1889                                               p_state->sam_ldb,
1890                                               p_state->domain_dn,
1891                                               del_incoming,
1892                                               netbios_name,
1893                                               current_passwords);
1894                 if (!NT_STATUS_IS_OK(nt_status)) {
1895                         goto done;
1896                 }
1897         }
1898
1899         /* ok, all fine, commit transaction and return */
1900         ret = ldb_transaction_commit(p_state->sam_ldb);
1901         if (ret != LDB_SUCCESS) {
1902                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1903         }
1904         in_transaction = false;
1905
1906         nt_status = NT_STATUS_OK;
1907
1908 done:
1909         if (in_transaction) {
1910                 ldb_transaction_cancel(p_state->sam_ldb);
1911         }
1912         return nt_status;
1913 }
1914
1915 /*
1916   lsa_SetInfomrationTrustedDomain
1917 */
1918 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
1919                                 struct dcesrv_call_state *dce_call,
1920                                 TALLOC_CTX *mem_ctx,
1921                                 struct lsa_SetInformationTrustedDomain *r)
1922 {
1923         struct dcesrv_handle *h;
1924         struct lsa_trusted_domain_state *td_state;
1925         struct ldb_message **msgs;
1926         NTSTATUS nt_status;
1927
1928         DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
1929                            LSA_HANDLE_TRUSTED_DOMAIN);
1930
1931         td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1932
1933         /* get the trusted domain object */
1934         nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
1935                             td_state->trusted_domain_dn,
1936                             NULL, NULL, NULL, &msgs);
1937         if (!NT_STATUS_IS_OK(nt_status)) {
1938                 if (NT_STATUS_EQUAL(nt_status,
1939                                     NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1940                         return nt_status;
1941                 }
1942                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1943         }
1944
1945         return setInfoTrustedDomain_base(dce_call, h, mem_ctx,
1946                                          msgs[0], r->in.level, r->in.info);
1947 }
1948
1949
1950 /*
1951   lsa_DeleteTrustedDomain
1952 */
1953 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1954                                       struct lsa_DeleteTrustedDomain *r)
1955 {
1956         NTSTATUS status;
1957         struct lsa_OpenTrustedDomain opn;
1958         struct lsa_DeleteObject del;
1959         struct dcesrv_handle *h;
1960
1961         opn.in.handle = r->in.handle;
1962         opn.in.sid = r->in.dom_sid;
1963         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1964         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1965         if (!opn.out.trustdom_handle) {
1966                 return NT_STATUS_NO_MEMORY;
1967         }
1968         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1969         if (!NT_STATUS_IS_OK(status)) {
1970                 return status;
1971         }
1972
1973         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1974         talloc_steal(mem_ctx, h);
1975
1976         del.in.handle = opn.out.trustdom_handle;
1977         del.out.handle = opn.out.trustdom_handle;
1978         status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
1979         if (!NT_STATUS_IS_OK(status)) {
1980                 return status;
1981         }
1982         return NT_STATUS_OK;
1983 }
1984
1985 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
1986                                      struct ldb_message *msg,
1987                                      struct lsa_TrustDomainInfoInfoEx *info_ex)
1988 {
1989         info_ex->domain_name.string
1990                 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
1991         info_ex->netbios_name.string
1992                 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1993         info_ex->sid
1994                 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
1995         info_ex->trust_direction
1996                 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
1997         info_ex->trust_type
1998                 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
1999         info_ex->trust_attributes
2000                 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
2001         return NT_STATUS_OK;
2002 }
2003
2004 /*
2005   lsa_QueryTrustedDomainInfo
2006 */
2007 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2008                                            struct lsa_QueryTrustedDomainInfo *r)
2009 {
2010         union lsa_TrustedDomainInfo *info = NULL;
2011         struct dcesrv_handle *h;
2012         struct lsa_trusted_domain_state *trusted_domain_state;
2013         struct ldb_message *msg;
2014         int ret;
2015         struct ldb_message **res;
2016         const char *attrs[] = {
2017                 "flatname",
2018                 "trustPartner",
2019                 "securityIdentifier",
2020                 "trustDirection",
2021                 "trustType",
2022                 "trustAttributes",
2023                 "msDs-supportedEncryptionTypes",
2024                 NULL
2025         };
2026
2027         DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2028
2029         trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2030
2031         /* pull all the user attributes */
2032         ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2033                               trusted_domain_state->trusted_domain_dn, &res, attrs);
2034         if (ret != 1) {
2035                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2036         }
2037         msg = res[0];
2038
2039         info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2040         if (!info) {
2041                 return NT_STATUS_NO_MEMORY;
2042         }
2043         *r->out.info = info;
2044
2045         switch (r->in.level) {
2046         case LSA_TRUSTED_DOMAIN_INFO_NAME:
2047                 info->name.netbios_name.string
2048                         = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2049                 break;
2050         case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2051                 info->posix_offset.posix_offset
2052                         = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2053                 break;
2054 #if 0  /* Win2k3 doesn't implement this */
2055         case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2056                 r->out.info->info_basic.netbios_name.string
2057                         = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2058                 r->out.info->info_basic.sid
2059                         = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2060                 break;
2061 #endif
2062         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2063                 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2064
2065         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2066                 ZERO_STRUCT(info->full_info);
2067                 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2068         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2069                 ZERO_STRUCT(info->full_info2_internal);
2070                 info->full_info2_internal.posix_offset.posix_offset
2071                         = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2072                 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2073
2074         case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2075                 info->enc_types.enc_types
2076                         = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2077                 break;
2078
2079         case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2080         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2081                 /* oops, we don't want to return the info after all */
2082                 talloc_free(info);
2083                 *r->out.info = NULL;
2084                 return NT_STATUS_INVALID_PARAMETER;
2085         default:
2086                 /* oops, we don't want to return the info after all */
2087                 talloc_free(info);
2088                 *r->out.info = NULL;
2089                 return NT_STATUS_INVALID_INFO_CLASS;
2090         }
2091
2092         return NT_STATUS_OK;
2093 }
2094
2095
2096 /*
2097   lsa_QueryTrustedDomainInfoBySid
2098 */
2099 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2100                                                 struct lsa_QueryTrustedDomainInfoBySid *r)
2101 {
2102         NTSTATUS status;
2103         struct lsa_OpenTrustedDomain opn;
2104         struct lsa_QueryTrustedDomainInfo query;
2105         struct dcesrv_handle *h;
2106
2107         opn.in.handle = r->in.handle;
2108         opn.in.sid = r->in.dom_sid;
2109         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2110         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2111         if (!opn.out.trustdom_handle) {
2112                 return NT_STATUS_NO_MEMORY;
2113         }
2114         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2115         if (!NT_STATUS_IS_OK(status)) {
2116                 return status;
2117         }
2118
2119         /* Ensure this handle goes away at the end of this call */
2120         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2121         talloc_steal(mem_ctx, h);
2122
2123         query.in.trustdom_handle = opn.out.trustdom_handle;
2124         query.in.level = r->in.level;
2125         query.out.info = r->out.info;
2126         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2127         if (!NT_STATUS_IS_OK(status)) {
2128                 return status;
2129         }
2130
2131         return NT_STATUS_OK;
2132 }
2133
2134 /*
2135   lsa_SetTrustedDomainInfoByName
2136 */
2137 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2138                                                TALLOC_CTX *mem_ctx,
2139                                                struct lsa_SetTrustedDomainInfoByName *r)
2140 {
2141         struct dcesrv_handle *policy_handle;
2142         struct lsa_policy_state *policy_state;
2143         struct ldb_message **msgs;
2144         NTSTATUS nt_status;
2145
2146         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2147         policy_state = policy_handle->data;
2148
2149         /* get the trusted domain object */
2150         nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2151                             policy_state->domain_dn,
2152                             r->in.trusted_domain->string,
2153                             r->in.trusted_domain->string,
2154                             NULL, &msgs);
2155         if (!NT_STATUS_IS_OK(nt_status)) {
2156                 if (NT_STATUS_EQUAL(nt_status,
2157                                     NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2158                         return nt_status;
2159                 }
2160                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2161         }
2162
2163         return setInfoTrustedDomain_base(dce_call, policy_handle, mem_ctx,
2164                                          msgs[0], r->in.level, r->in.info);
2165 }
2166
2167 /*
2168    lsa_QueryTrustedDomainInfoByName
2169 */
2170 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2171                                                  TALLOC_CTX *mem_ctx,
2172                                                  struct lsa_QueryTrustedDomainInfoByName *r)
2173 {
2174         NTSTATUS status;
2175         struct lsa_OpenTrustedDomainByName opn;
2176         struct lsa_QueryTrustedDomainInfo query;
2177         struct dcesrv_handle *h;
2178
2179         opn.in.handle = r->in.handle;
2180         opn.in.name = *r->in.trusted_domain;
2181         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2182         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2183         if (!opn.out.trustdom_handle) {
2184                 return NT_STATUS_NO_MEMORY;
2185         }
2186         status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2187         if (!NT_STATUS_IS_OK(status)) {
2188                 return status;
2189         }
2190
2191         /* Ensure this handle goes away at the end of this call */
2192         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2193         talloc_steal(mem_ctx, h);
2194
2195         query.in.trustdom_handle = opn.out.trustdom_handle;
2196         query.in.level = r->in.level;
2197         query.out.info = r->out.info;
2198         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2199         if (!NT_STATUS_IS_OK(status)) {
2200                 return status;
2201         }
2202
2203         return NT_STATUS_OK;
2204 }
2205
2206 /*
2207   lsa_CloseTrustedDomainEx
2208 */
2209 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2210                                          TALLOC_CTX *mem_ctx,
2211                                          struct lsa_CloseTrustedDomainEx *r)
2212 {
2213         /* The result of a bad hair day from an IDL programmer?  Not
2214          * implmented in Win2k3.  You should always just lsa_Close
2215          * anyway. */
2216         return NT_STATUS_NOT_IMPLEMENTED;
2217 }
2218
2219
2220 /*
2221   comparison function for sorting lsa_DomainInformation array
2222 */
2223 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2224 {
2225         return strcasecmp_m(e1->name.string, e2->name.string);
2226 }
2227
2228 /*
2229   lsa_EnumTrustDom
2230 */
2231 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2232                                  struct lsa_EnumTrustDom *r)
2233 {
2234         struct dcesrv_handle *policy_handle;
2235         struct lsa_DomainInfo *entries;
2236         struct lsa_policy_state *policy_state;
2237         struct ldb_message **domains;
2238         const char *attrs[] = {
2239                 "flatname",
2240                 "securityIdentifier",
2241                 NULL
2242         };
2243
2244
2245         int count, i;
2246
2247         *r->out.resume_handle = 0;
2248
2249         r->out.domains->domains = NULL;
2250         r->out.domains->count = 0;
2251
2252         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2253
2254         policy_state = policy_handle->data;
2255
2256         /* search for all users in this domain. This could possibly be cached and
2257            resumed based on resume_key */
2258         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2259                              "objectclass=trustedDomain");
2260         if (count < 0) {
2261                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2262         }
2263
2264         /* convert to lsa_TrustInformation format */
2265         entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2266         if (!entries) {
2267                 return NT_STATUS_NO_MEMORY;
2268         }
2269         for (i=0;i<count;i++) {
2270                 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2271                 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2272         }
2273
2274         /* sort the results by name */
2275         TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2276
2277         if (*r->in.resume_handle >= count) {
2278                 *r->out.resume_handle = -1;
2279
2280                 return NT_STATUS_NO_MORE_ENTRIES;
2281         }
2282
2283         /* return the rest, limit by max_size. Note that we
2284            use the w2k3 element size value of 60 */
2285         r->out.domains->count = count - *r->in.resume_handle;
2286         r->out.domains->count = MIN(r->out.domains->count,
2287                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2288
2289         r->out.domains->domains = entries + *r->in.resume_handle;
2290         r->out.domains->count = r->out.domains->count;
2291
2292         if (r->out.domains->count < count - *r->in.resume_handle) {
2293                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2294                 return STATUS_MORE_ENTRIES;
2295         }
2296
2297         /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2298          * always be larger than the previous input resume handle, in
2299          * particular when hitting the last query it is vital to set the
2300          * resume handle correctly to avoid infinite client loops, as
2301          * seen e.g. with Windows XP SP3 when resume handle is 0 and
2302          * status is NT_STATUS_OK - gd */
2303
2304         *r->out.resume_handle = (uint32_t)-1;
2305
2306         return NT_STATUS_OK;
2307 }
2308
2309 /*
2310   comparison function for sorting lsa_DomainInformation array
2311 */
2312 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2313 {
2314         return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2315 }
2316
2317 /*
2318   lsa_EnumTrustedDomainsEx
2319 */
2320 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2321                                         struct lsa_EnumTrustedDomainsEx *r)
2322 {
2323         struct dcesrv_handle *policy_handle;
2324         struct lsa_TrustDomainInfoInfoEx *entries;
2325         struct lsa_policy_state *policy_state;
2326         struct ldb_message **domains;
2327         const char *attrs[] = {
2328                 "flatname",
2329                 "trustPartner",
2330                 "securityIdentifier",
2331                 "trustDirection",
2332                 "trustType",
2333                 "trustAttributes",
2334                 NULL
2335         };
2336         NTSTATUS nt_status;
2337
2338         int count, i;
2339
2340         *r->out.resume_handle = 0;
2341
2342         r->out.domains->domains = NULL;
2343         r->out.domains->count = 0;
2344
2345         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2346
2347         policy_state = policy_handle->data;
2348
2349         /* search for all users in this domain. This could possibly be cached and
2350            resumed based on resume_key */
2351         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2352                              "objectclass=trustedDomain");
2353         if (count < 0) {
2354                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2355         }
2356
2357         /* convert to lsa_DomainInformation format */
2358         entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2359         if (!entries) {
2360                 return NT_STATUS_NO_MEMORY;
2361         }
2362         for (i=0;i<count;i++) {
2363                 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2364                 if (!NT_STATUS_IS_OK(nt_status)) {
2365                         return nt_status;
2366                 }
2367         }
2368
2369         /* sort the results by name */
2370         TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2371
2372         if (*r->in.resume_handle >= count) {
2373                 *r->out.resume_handle = -1;
2374
2375                 return NT_STATUS_NO_MORE_ENTRIES;
2376         }
2377
2378         /* return the rest, limit by max_size. Note that we
2379            use the w2k3 element size value of 60 */
2380         r->out.domains->count = count - *r->in.resume_handle;
2381         r->out.domains->count = MIN(r->out.domains->count,
2382                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2383
2384         r->out.domains->domains = entries + *r->in.resume_handle;
2385         r->out.domains->count = r->out.domains->count;
2386
2387         if (r->out.domains->count < count - *r->in.resume_handle) {
2388                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2389                 return STATUS_MORE_ENTRIES;
2390         }
2391
2392         return NT_STATUS_OK;
2393 }
2394
2395
2396 /*
2397   lsa_OpenAccount
2398 */
2399 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2400                                 struct lsa_OpenAccount *r)
2401 {
2402         struct dcesrv_handle *h, *ah;
2403         struct lsa_policy_state *state;
2404         struct lsa_account_state *astate;
2405
2406         ZERO_STRUCTP(r->out.acct_handle);
2407
2408         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2409
2410         state = h->data;
2411
2412         astate = talloc(dce_call->conn, struct lsa_account_state);
2413         if (astate == NULL) {
2414                 return NT_STATUS_NO_MEMORY;
2415         }
2416
2417         astate->account_sid = dom_sid_dup(astate, r->in.sid);
2418         if (astate->account_sid == NULL) {
2419                 talloc_free(astate);
2420                 return NT_STATUS_NO_MEMORY;
2421         }
2422
2423         astate->policy = talloc_reference(astate, state);
2424         astate->access_mask = r->in.access_mask;
2425
2426         ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2427         if (!ah) {
2428                 talloc_free(astate);
2429                 return NT_STATUS_NO_MEMORY;
2430         }
2431
2432         ah->data = talloc_steal(ah, astate);
2433
2434         *r->out.acct_handle = ah->wire_handle;
2435
2436         return NT_STATUS_OK;
2437 }
2438
2439
2440 /*
2441   lsa_EnumPrivsAccount
2442 */
2443 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2444                                      TALLOC_CTX *mem_ctx,
2445                                      struct lsa_EnumPrivsAccount *r)
2446 {
2447         struct dcesrv_handle *h;
2448         struct lsa_account_state *astate;
2449         int ret;
2450         unsigned int i, j;
2451         struct ldb_message **res;
2452         const char * const attrs[] = { "privilege", NULL};
2453         struct ldb_message_element *el;
2454         const char *sidstr;
2455         struct lsa_PrivilegeSet *privs;
2456
2457         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2458
2459         astate = h->data;
2460
2461         privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2462         if (privs == NULL) {
2463                 return NT_STATUS_NO_MEMORY;
2464         }
2465         privs->count = 0;
2466         privs->unknown = 0;
2467         privs->set = NULL;
2468
2469         *r->out.privs = privs;
2470
2471         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2472         if (sidstr == NULL) {
2473                 return NT_STATUS_NO_MEMORY;
2474         }
2475
2476         ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2477                            "objectSid=%s", sidstr);
2478         if (ret < 0) {
2479                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2480         }
2481         if (ret != 1) {
2482                 return NT_STATUS_OK;
2483         }
2484
2485         el = ldb_msg_find_element(res[0], "privilege");
2486         if (el == NULL || el->num_values == 0) {
2487                 return NT_STATUS_OK;
2488         }
2489
2490         privs->set = talloc_array(privs,
2491                                   struct lsa_LUIDAttribute, el->num_values);
2492         if (privs->set == NULL) {
2493                 return NT_STATUS_NO_MEMORY;
2494         }
2495
2496         j = 0;
2497         for (i=0;i<el->num_values;i++) {
2498                 int id = sec_privilege_id((const char *)el->values[i].data);
2499                 if (id == SEC_PRIV_INVALID) {
2500                         /* Perhaps an account right, not a privilege */
2501                         continue;
2502                 }
2503                 privs->set[j].attribute = 0;
2504                 privs->set[j].luid.low = id;
2505                 privs->set[j].luid.high = 0;
2506                 j++;
2507         }
2508
2509         privs->count = j;
2510
2511         return NT_STATUS_OK;
2512 }
2513
2514 /*
2515   lsa_EnumAccountRights
2516 */
2517 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2518                                       TALLOC_CTX *mem_ctx,
2519                                       struct lsa_EnumAccountRights *r)
2520 {
2521         struct dcesrv_handle *h;
2522         struct lsa_policy_state *state;
2523         int ret;
2524         unsigned int i;
2525         struct ldb_message **res;
2526         const char * const attrs[] = { "privilege", NULL};
2527         const char *sidstr;
2528         struct ldb_message_element *el;
2529
2530         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2531
2532         state = h->data;
2533
2534         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2535         if (sidstr == NULL) {
2536                 return NT_STATUS_NO_MEMORY;
2537         }
2538
2539         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2540                            "(&(objectSid=%s)(privilege=*))", sidstr);
2541         if (ret == 0) {
2542                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2543         }
2544         if (ret != 1) {
2545                 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2546                           dom_sid_string(mem_ctx, r->in.sid),
2547                           ldb_errstring(state->pdb)));
2548                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2549         }
2550
2551         el = ldb_msg_find_element(res[0], "privilege");
2552         if (el == NULL || el->num_values == 0) {
2553                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2554         }
2555
2556         r->out.rights->count = el->num_values;
2557         r->out.rights->names = talloc_array(r->out.rights,
2558                                             struct lsa_StringLarge, r->out.rights->count);
2559         if (r->out.rights->names == NULL) {
2560                 return NT_STATUS_NO_MEMORY;
2561         }
2562
2563         for (i=0;i<el->num_values;i++) {
2564                 r->out.rights->names[i].string = (const char *)el->values[i].data;
2565         }
2566
2567         return NT_STATUS_OK;
2568 }
2569
2570
2571
2572 /*
2573   helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2574 */
2575 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2576                                            TALLOC_CTX *mem_ctx,
2577                                            struct lsa_policy_state *state,
2578                                            int ldb_flag,
2579                                            struct dom_sid *sid,
2580                                            const struct lsa_RightSet *rights)
2581 {
2582         const char *sidstr, *sidndrstr;
2583         struct ldb_message *msg;
2584         struct ldb_message_element *el;
2585         int ret;
2586         uint32_t i;
2587         struct lsa_EnumAccountRights r2;
2588         char *dnstr;
2589
2590         if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2591             SECURITY_ADMINISTRATOR) {
2592                 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2593                 return NT_STATUS_ACCESS_DENIED;
2594         }
2595
2596         msg = ldb_msg_new(mem_ctx);
2597         if (msg == NULL) {
2598                 return NT_STATUS_NO_MEMORY;
2599         }
2600
2601         sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2602         if (sidndrstr == NULL) {
2603                 TALLOC_FREE(msg);
2604                 return NT_STATUS_NO_MEMORY;
2605         }
2606
2607         sidstr = dom_sid_string(msg, sid);
2608         if (sidstr == NULL) {
2609                 TALLOC_FREE(msg);
2610                 return NT_STATUS_NO_MEMORY;
2611         }
2612
2613         dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2614         if (dnstr == NULL) {
2615                 TALLOC_FREE(msg);
2616                 return NT_STATUS_NO_MEMORY;
2617         }
2618
2619         msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2620         if (msg->dn == NULL) {
2621                 TALLOC_FREE(msg);
2622                 return NT_STATUS_NO_MEMORY;
2623         }
2624
2625         if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2626                 NTSTATUS status;
2627
2628                 r2.in.handle = &state->handle->wire_handle;
2629                 r2.in.sid = sid;
2630                 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2631
2632                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2633                 if (!NT_STATUS_IS_OK(status)) {
2634                         ZERO_STRUCTP(r2.out.rights);
2635                 }
2636         }
2637
2638         for (i=0;i<rights->count;i++) {
2639                 if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
2640                         if (sec_right_bit(rights->names[i].string) == 0) {
2641                                 talloc_free(msg);
2642                                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2643                         }
2644
2645                         talloc_free(msg);
2646                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2647                 }
2648
2649                 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2650                         uint32_t j;
2651                         for (j=0;j<r2.out.rights->count;j++) {
2652                                 if (strcasecmp_m(r2.out.rights->names[j].string,
2653                                                rights->names[i].string) == 0) {
2654                                         break;
2655                                 }
2656                         }
2657                         if (j != r2.out.rights->count) continue;
2658                 }
2659
2660                 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2661                 if (ret != LDB_SUCCESS) {
2662                         talloc_free(msg);
2663                         return NT_STATUS_NO_MEMORY;
2664                 }
2665         }
2666
2667         el = ldb_msg_find_element(msg, "privilege");
2668         if (!el) {
2669                 talloc_free(msg);
2670                 return NT_STATUS_OK;
2671         }
2672
2673         el->flags = ldb_flag;
2674
2675         ret = ldb_modify(state->pdb, msg);
2676         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2677                 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2678                         talloc_free(msg);
2679                         return NT_STATUS_NO_MEMORY;
2680                 }
2681                 ldb_msg_add_string(msg, "comment", "added via LSA");
2682                 ret = ldb_add(state->pdb, msg);
2683         }
2684         if (ret != LDB_SUCCESS) {
2685                 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2686                         talloc_free(msg);
2687                         return NT_STATUS_OK;
2688                 }
2689                 DEBUG(3, ("Could not %s attributes from %s: %s",
2690                           LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2691                           ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2692                 talloc_free(msg);
2693                 return NT_STATUS_UNEXPECTED_IO_ERROR;
2694         }
2695
2696         talloc_free(msg);
2697         return NT_STATUS_OK;
2698 }
2699
2700 /*
2701   lsa_AddPrivilegesToAccount
2702 */
2703 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2704                                            struct lsa_AddPrivilegesToAccount *r)
2705 {
2706         struct lsa_RightSet rights;
2707         struct dcesrv_handle *h;
2708         struct lsa_account_state *astate;
2709         uint32_t i;
2710
2711         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2712
2713         astate = h->data;
2714
2715         rights.count = r->in.privs->count;
2716         rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2717         if (rights.names == NULL) {
2718                 return NT_STATUS_NO_MEMORY;
2719         }
2720         for (i=0;i<rights.count;i++) {
2721                 int id = r->in.privs->set[i].luid.low;
2722                 if (r->in.privs->set[i].luid.high) {
2723                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2724                 }
2725                 rights.names[i].string = sec_privilege_name(id);
2726                 if (rights.names[i].string == NULL) {
2727                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2728                 }
2729         }
2730
2731         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2732                                           LDB_FLAG_MOD_ADD, astate->account_sid,
2733                                           &rights);
2734 }
2735
2736
2737 /*
2738   lsa_RemovePrivilegesFromAccount
2739 */
2740 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2741                                                 struct lsa_RemovePrivilegesFromAccount *r)
2742 {
2743         struct lsa_RightSet *rights;
2744         struct dcesrv_handle *h;
2745         struct lsa_account_state *astate;
2746         uint32_t i;
2747
2748         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2749
2750         astate = h->data;
2751
2752         rights = talloc(mem_ctx, struct lsa_RightSet);
2753
2754         if (r->in.remove_all == 1 &&
2755             r->in.privs == NULL) {
2756                 struct lsa_EnumAccountRights r2;
2757                 NTSTATUS status;
2758
2759                 r2.in.handle = &astate->policy->handle->wire_handle;
2760                 r2.in.sid = astate->account_sid;
2761                 r2.out.rights = rights;
2762
2763                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2764                 if (!NT_STATUS_IS_OK(status)) {
2765                         return status;
2766                 }
2767
2768                 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2769                                                   LDB_FLAG_MOD_DELETE, astate->account_sid,
2770                                                   r2.out.rights);
2771         }
2772
2773         if (r->in.remove_all != 0) {
2774                 return NT_STATUS_INVALID_PARAMETER;
2775         }
2776
2777         rights->count = r->in.privs->count;
2778         rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2779         if (rights->names == NULL) {
2780                 return NT_STATUS_NO_MEMORY;
2781         }
2782         for (i=0;i<rights->count;i++) {
2783                 int id = r->in.privs->set[i].luid.low;
2784                 if (r->in.privs->set[i].luid.high) {
2785                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2786                 }
2787                 rights->names[i].string = sec_privilege_name(id);
2788                 if (rights->names[i].string == NULL) {
2789                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2790                 }
2791         }
2792
2793         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2794                                           LDB_FLAG_MOD_DELETE, astate->account_sid,
2795                                           rights);
2796 }
2797
2798
2799 /*
2800   lsa_GetQuotasForAccount
2801 */
2802 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2803                        struct lsa_GetQuotasForAccount *r)
2804 {
2805         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2806 }
2807
2808
2809 /*
2810   lsa_SetQuotasForAccount
2811 */
2812 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2813                        struct lsa_SetQuotasForAccount *r)
2814 {
2815         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2816 }
2817
2818
2819 /*
2820   lsa_GetSystemAccessAccount
2821 */
2822 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2823                        struct lsa_GetSystemAccessAccount *r)
2824 {
2825         struct dcesrv_handle *h;
2826         struct lsa_account_state *astate;
2827         int ret;
2828         unsigned int i;
2829         struct ldb_message **res;
2830         const char * const attrs[] = { "privilege", NULL};
2831         struct ldb_message_element *el;
2832         const char *sidstr;
2833
2834         *(r->out.access_mask) = 0x00000000;
2835
2836         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2837
2838         astate = h->data;
2839
2840         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2841         if (sidstr == NULL) {
2842                 return NT_STATUS_NO_MEMORY;
2843         }
2844
2845         ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2846                            "objectSid=%s", sidstr);
2847         if (ret < 0) {
2848                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2849         }
2850         if (ret != 1) {
2851                 return NT_STATUS_OK;
2852         }
2853
2854         el = ldb_msg_find_element(res[0], "privilege");
2855         if (el == NULL || el->num_values == 0) {
2856                 return NT_STATUS_OK;
2857         }
2858
2859         for (i=0;i<el->num_values;i++) {
2860                 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
2861                 if (right_bit == 0) {
2862                         /* Perhaps an privilege, not a right */
2863                         continue;
2864                 }
2865                 *(r->out.access_mask) |= right_bit;
2866         }
2867
2868         return NT_STATUS_OK;
2869 }
2870
2871
2872 /*
2873   lsa_SetSystemAccessAccount
2874 */
2875 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2876                        struct lsa_SetSystemAccessAccount *r)
2877 {
2878         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2879 }
2880
2881
2882 /*
2883   lsa_CreateSecret
2884 */
2885 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2886                                  struct lsa_CreateSecret *r)
2887 {
2888         struct dcesrv_handle *policy_handle;
2889         struct lsa_policy_state *policy_state;
2890         struct lsa_secret_state *secret_state;
2891         struct dcesrv_handle *handle;
2892         struct ldb_message **msgs, *msg;
2893         const char *attrs[] = {
2894                 NULL
2895         };
2896
2897         const char *name;
2898
2899         int ret;
2900
2901         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2902         ZERO_STRUCTP(r->out.sec_handle);
2903
2904         switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
2905         {
2906         case SECURITY_SYSTEM:
2907         case SECURITY_ADMINISTRATOR:
2908                 break;
2909         default:
2910                 /* Users and annonymous are not allowed create secrets */
2911                 return NT_STATUS_ACCESS_DENIED;
2912         }
2913
2914         policy_state = policy_handle->data;
2915
2916         if (!r->in.name.string) {
2917                 return NT_STATUS_INVALID_PARAMETER;
2918         }
2919
2920         secret_state = talloc(mem_ctx, struct lsa_secret_state);
2921         NT_STATUS_HAVE_NO_MEMORY(secret_state);
2922         secret_state->policy = policy_state;
2923
2924         msg = ldb_msg_new(mem_ctx);
2925         if (msg == NULL) {
2926                 return NT_STATUS_NO_MEMORY;
2927         }
2928
2929         if (strncmp("G$", r->in.name.string, 2) == 0) {
2930                 const char *name2;
2931
2932                 secret_state->global = true;
2933
2934                 name = &r->in.name.string[2];
2935                 if (strlen(name) == 0) {
2936                         return NT_STATUS_INVALID_PARAMETER;
2937                 }
2938
2939                 name2 = talloc_asprintf(mem_ctx, "%s Secret",
2940                                         ldb_binary_encode_string(mem_ctx, name));
2941                 NT_STATUS_HAVE_NO_MEMORY(name2);
2942
2943                 /* We need to connect to the database as system, as this is one
2944                  * of the rare RPC calls that must read the secrets (and this
2945                  * is denied otherwise) */
2946                 secret_state->sam_ldb = talloc_reference(secret_state,
2947                                                          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));
2948                 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2949
2950                 /* search for the secret record */
2951                 ret = gendb_search(secret_state->sam_ldb,
2952                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
2953                                    "(&(cn=%s)(objectclass=secret))",
2954                                    name2);
2955                 if (ret > 0) {
2956                         return NT_STATUS_OBJECT_NAME_COLLISION;
2957                 }
2958
2959                 if (ret < 0) {
2960                         DEBUG(0,("Failure searching for CN=%s: %s\n",
2961                                  name2, ldb_errstring(secret_state->sam_ldb)));
2962                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2963                 }
2964
2965                 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2966                 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2967                 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2968                         return NT_STATUS_NO_MEMORY;
2969                 }
2970
2971                 ret = ldb_msg_add_string(msg, "cn", name2);
2972                 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2973         } else {
2974                 secret_state->global = false;
2975
2976                 name = r->in.name.string;
2977                 if (strlen(name) == 0) {
2978                         return NT_STATUS_INVALID_PARAMETER;
2979                 }
2980
2981                 secret_state->sam_ldb = talloc_reference(secret_state,
2982                                                          secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
2983                 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2984
2985                 /* search for the secret record */
2986                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2987                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2988                                    &msgs, attrs,
2989                                    "(&(cn=%s)(objectclass=secret))",
2990                                    ldb_binary_encode_string(mem_ctx, name));
2991                 if (ret > 0) {
2992                         return NT_STATUS_OBJECT_NAME_COLLISION;
2993                 }
2994
2995                 if (ret < 0) {
2996                         DEBUG(0,("Failure searching for CN=%s: %s\n",
2997                                  name, ldb_errstring(secret_state->sam_ldb)));
2998                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2999                 }
3000
3001                 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
3002                                          "cn=%s,cn=LSA Secrets", name);
3003                 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3004                 ret = ldb_msg_add_string(msg, "cn", name);
3005                 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3006         }
3007
3008         ret = ldb_msg_add_string(msg, "objectClass", "secret");
3009         if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3010
3011         secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3012         NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3013
3014         /* create the secret */
3015         ret = ldb_add(secret_state->sam_ldb, msg);
3016         if (ret != LDB_SUCCESS) {
3017                 DEBUG(0,("Failed to create secret record %s: %s\n",
3018                          ldb_dn_get_linearized(msg->dn),
3019                          ldb_errstring(secret_state->sam_ldb)));
3020                 return NT_STATUS_ACCESS_DENIED;
3021         }
3022
3023         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3024         NT_STATUS_HAVE_NO_MEMORY(handle);
3025
3026         handle->data = talloc_steal(handle, secret_state);
3027
3028         secret_state->access_mask = r->in.access_mask;
3029         secret_state->policy = talloc_reference(secret_state, policy_state);
3030         NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3031
3032         *r->out.sec_handle = handle->wire_handle;
3033
3034         return NT_STATUS_OK;
3035 }
3036
3037
3038 /*
3039   lsa_OpenSecret
3040 */
3041 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3042                                struct lsa_OpenSecret *r)
3043 {
3044         struct dcesrv_handle *policy_handle;
3045
3046         struct lsa_policy_state *policy_state;
3047         struct lsa_secret_state *secret_state;
3048         struct dcesrv_handle *handle;
3049         struct ldb_message **msgs;
3050         const char *attrs[] = {
3051                 NULL
3052         };
3053
3054         const char *name;
3055
3056         int ret;
3057
3058         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3059         ZERO_STRUCTP(r->out.sec_handle);
3060         policy_state = policy_handle->data;
3061
3062         if (!r->in.name.string) {
3063                 return NT_STATUS_INVALID_PARAMETER;
3064         }
3065
3066         switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3067         {
3068         case SECURITY_SYSTEM:
3069         case SECURITY_ADMINISTRATOR:
3070                 break;
3071         default:
3072                 /* Users and annonymous are not allowed to access secrets */
3073                 return NT_STATUS_ACCESS_DENIED;
3074         }
3075
3076         secret_state = talloc(mem_ctx, struct lsa_secret_state);
3077         if (!secret_state) {
3078                 return NT_STATUS_NO_MEMORY;
3079         }
3080         secret_state->policy = policy_state;
3081
3082         if (strncmp("G$", r->in.name.string, 2) == 0) {
3083                 name = &r->in.name.string[2];
3084                 /* 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) */
3085                 secret_state->sam_ldb = talloc_reference(secret_state,
3086                                                          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));
3087                 secret_state->global = true;
3088
3089                 if (strlen(name) < 1) {
3090                         return NT_STATUS_INVALID_PARAMETER;
3091                 }
3092
3093                 /* search for the secret record */
3094                 ret = gendb_search(secret_state->sam_ldb,
3095                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
3096                                    "(&(cn=%s Secret)(objectclass=secret))",
3097                                    ldb_binary_encode_string(mem_ctx, name));
3098                 if (ret == 0) {
3099                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3100                 }
3101
3102                 if (ret != 1) {
3103                         DEBUG(0,("Found %d records matching DN %s\n", ret,
3104                                  ldb_dn_get_linearized(policy_state->system_dn)));
3105                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3106                 }
3107         } else {
3108                 secret_state->global = false;
3109                 secret_state->sam_ldb = talloc_reference(secret_state,
3110                                                          secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3111
3112                 name = r->in.name.string;
3113                 if (strlen(name) < 1) {
3114                         return NT_STATUS_INVALID_PARAMETER;
3115                 }
3116
3117                 /* search for the secret record */
3118                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3119                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3120                                    &msgs, attrs,
3121                                    "(&(cn=%s)(objectclass=secret))",
3122                                    ldb_binary_encode_string(mem_ctx, name));
3123                 if (ret == 0) {
3124                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3125                 }
3126
3127                 if (ret != 1) {
3128                         DEBUG(0,("Found %d records matching CN=%s\n",
3129                                  ret, ldb_binary_encode_string(mem_ctx, name)));
3130                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3131                 }
3132         }
3133
3134         secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3135
3136         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3137         if (!handle) {
3138                 return NT_STATUS_NO_MEMORY;
3139         }
3140
3141         handle->data = talloc_steal(handle, secret_state);
3142
3143         secret_state->access_mask = r->in.access_mask;
3144         secret_state->policy = talloc_reference(secret_state, policy_state);
3145
3146         *r->out.sec_handle = handle->wire_handle;
3147
3148         return NT_STATUS_OK;
3149 }
3150
3151
3152 /*
3153   lsa_SetSecret
3154 */
3155 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3156                               struct lsa_SetSecret *r)
3157 {
3158
3159         struct dcesrv_handle *h;
3160         struct lsa_secret_state *secret_state;
3161         struct ldb_message *msg;
3162         DATA_BLOB session_key;
3163         DATA_BLOB crypt_secret, secret;
3164         struct ldb_val val;
3165         int ret;
3166         NTSTATUS status = NT_STATUS_OK;
3167
3168         struct timeval now = timeval_current();
3169         NTTIME nt_now = timeval_to_nttime(&now);
3170
3171         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3172
3173         secret_state = h->data;
3174
3175         msg = ldb_msg_new(mem_ctx);
3176         if (msg == NULL) {
3177                 return NT_STATUS_NO_MEMORY;
3178         }
3179
3180         msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3181         if (!msg->dn) {
3182                 return NT_STATUS_NO_MEMORY;
3183         }
3184         status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3185         if (!NT_STATUS_IS_OK(status)) {
3186                 return status;
3187         }
3188
3189         if (r->in.old_val) {
3190                 /* Decrypt */
3191                 crypt_secret.data = r->in.old_val->data;
3192                 crypt_secret.length = r->in.old_val->size;
3193
3194                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3195                 if (!NT_STATUS_IS_OK(status)) {
3196                         return status;
3197                 }
3198
3199                 val.data = secret.data;
3200                 val.length = secret.length;
3201
3202                 /* set value */
3203                 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3204                         return NT_STATUS_NO_MEMORY;
3205                 }
3206
3207                 /* set old value mtime */
3208                 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3209                                          mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3210                         return NT_STATUS_NO_MEMORY;
3211                 }
3212
3213         } else {
3214                 /* If the old value is not set, then migrate the
3215                  * current value to the old value */
3216                 const struct ldb_val *old_val;
3217                 NTTIME last_set_time;
3218                 struct ldb_message **res;
3219                 const char *attrs[] = {
3220                         "currentValue",
3221                         "lastSetTime",
3222                         NULL
3223                 };
3224
3225                 /* search for the secret record */
3226                 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3227                                       secret_state->secret_dn, &res, attrs);
3228                 if (ret == 0) {
3229                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3230                 }
3231
3232                 if (ret != 1) {
3233                         DEBUG(0,("Found %d records matching dn=%s\n", ret,
3234                                  ldb_dn_get_linearized(secret_state->secret_dn)));
3235                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3236                 }
3237
3238                 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3239                 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3240
3241                 if (old_val) {
3242                         /* set old value */
3243                         if (ldb_msg_add_value(msg, "priorValue",
3244                                               old_val, NULL) != LDB_SUCCESS) {
3245                                 return NT_STATUS_NO_MEMORY;
3246                         }
3247                 } else {
3248                         if (samdb_msg_add_delete(secret_state->sam_ldb,
3249                                                  mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3250                                 return NT_STATUS_NO_MEMORY;
3251                         }
3252                 }
3253
3254                 /* set old value mtime */
3255                 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3256                         if (samdb_msg_add_uint64(secret_state->sam_ldb,
3257                                                  mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3258                                 return NT_STATUS_NO_MEMORY;
3259                         }
3260                 } else {
3261                         if (samdb_msg_add_uint64(secret_state->sam_ldb,
3262                                                  mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3263                                 return NT_STATUS_NO_MEMORY;
3264                         }
3265                 }
3266         }
3267
3268         if (r->in.new_val) {
3269                 /* Decrypt */
3270                 crypt_secret.data = r->in.new_val->data;
3271                 crypt_secret.length = r->in.new_val->size;
3272
3273                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3274                 if (!NT_STATUS_IS_OK(status)) {
3275                         return status;
3276                 }
3277
3278                 val.data = secret.data;
3279                 val.length = secret.length;
3280
3281                 /* set value */
3282                 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3283                         return NT_STATUS_NO_MEMORY;
3284                 }
3285
3286                 /* set new value mtime */
3287                 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3288                                          mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3289                         return NT_STATUS_NO_MEMORY;
3290                 }
3291         } else {
3292                 /* NULL out the NEW value */
3293                 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3294                                          mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3295                         return NT_STATUS_NO_MEMORY;
3296                 }
3297                 if (samdb_msg_add_delete(secret_state->sam_ldb,
3298                                          mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3299                         return NT_STATUS_NO_MEMORY;
3300                 }
3301         }
3302
3303         /* modify the samdb record */
3304         ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3305         if (ret != LDB_SUCCESS) {
3306                 return dsdb_ldb_err_to_ntstatus(ret);
3307         }
3308
3309         return NT_STATUS_OK;
3310 }
3311
3312
3313 /*
3314   lsa_QuerySecret
3315 */
3316 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3317                                 struct lsa_QuerySecret *r)
3318 {
3319         struct dcesrv_handle *h;
3320         struct lsa_secret_state *secret_state;
3321         struct ldb_message *msg;
3322         DATA_BLOB session_key;
3323         DATA_BLOB crypt_secret, secret;
3324         int ret;
3325         struct ldb_message **res;
3326         const char *attrs[] = {
3327                 "currentValue",
3328                 "priorValue",
3329                 "lastSetTime",
3330                 "priorSetTime",
3331                 NULL
3332         };
3333
3334         NTSTATUS nt_status;
3335
3336         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3337
3338         /* Ensure user is permitted to read this... */
3339         switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3340         {
3341         case SECURITY_SYSTEM:
3342         case SECURITY_ADMINISTRATOR:
3343                 break;
3344         default:
3345                 /* Users and annonymous are not allowed to read secrets */
3346                 return NT_STATUS_ACCESS_DENIED;
3347         }
3348
3349         secret_state = h->data;
3350
3351         /* pull all the user attributes */
3352         ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3353                               secret_state->secret_dn, &res, attrs);
3354         if (ret != 1) {
3355                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3356         }
3357         msg = res[0];
3358
3359         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3360         if (!NT_STATUS_IS_OK(nt_status)) {
3361                 return nt_status;
3362         }
3363
3364         if (r->in.old_val) {
3365                 const struct ldb_val *prior_val;
3366                 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3367                 if (!r->out.old_val) {
3368                         return NT_STATUS_NO_MEMORY;
3369                 }
3370                 prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3371
3372                 if (prior_val && prior_val->length) {
3373                         secret.data = prior_val->data;
3374                         secret.length = prior_val->length;
3375
3376                         /* Encrypt */
3377                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3378                         if (!crypt_secret.length) {
3379                                 return NT_STATUS_NO_MEMORY;
3380                         }
3381                         r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3382                         if (!r->out.old_val->buf) {
3383                                 return NT_STATUS_NO_MEMORY;
3384                         }
3385                         r->out.old_val->buf->size = crypt_secret.length;
3386                         r->out.old_val->buf->length = crypt_secret.length;
3387                         r->out.old_val->buf->data = crypt_secret.data;
3388                 }
3389         }
3390
3391         if (r->in.old_mtime) {
3392                 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3393                 if (!r->out.old_mtime) {
3394                         return NT_STATUS_NO_MEMORY;
3395                 }
3396                 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3397         }
3398
3399         if (r->in.new_val) {
3400                 const struct ldb_val *new_val;
3401                 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3402                 if (!r->out.new_val) {
3403                         return NT_STATUS_NO_MEMORY;
3404                 }
3405
3406                 new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3407
3408                 if (new_val && new_val->length) {
3409                         secret.data = new_val->data;
3410                         secret.length = new_val->length;
3411
3412                         /* Encrypt */
3413                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3414                         if (!crypt_secret.length) {
3415                                 return NT_STATUS_NO_MEMORY;
3416                         }
3417                         r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3418                         if (!r->out.new_val->buf) {
3419                                 return NT_STATUS_NO_MEMORY;
3420                         }
3421                         r->out.new_val->buf->length = crypt_secret.length;
3422                         r->out.new_val->buf->size = crypt_secret.length;
3423                         r->out.new_val->buf->data = crypt_secret.data;
3424                 }
3425         }
3426
3427         if (r->in.new_mtime) {
3428                 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3429                 if (!r->out.new_mtime) {
3430                         return NT_STATUS_NO_MEMORY;
3431                 }
3432                 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3433         }
3434
3435         return NT_STATUS_OK;
3436 }
3437
3438
3439 /*
3440   lsa_LookupPrivValue
3441 */
3442 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3443                                     TALLOC_CTX *mem_ctx,
3444                                     struct lsa_LookupPrivValue *r)
3445 {
3446         struct dcesrv_handle *h;
3447         int id;
3448
3449         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3450
3451         id = sec_privilege_id(r->in.name->string);
3452         if (id == SEC_PRIV_INVALID) {
3453                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3454         }
3455
3456         r->out.luid->low = id;
3457         r->out.luid->high = 0;
3458
3459         return NT_STATUS_OK;
3460 }
3461
3462
3463 /*
3464   lsa_LookupPrivName
3465 */
3466 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3467                                    TALLOC_CTX *mem_ctx,
3468                                    struct lsa_LookupPrivName *r)
3469 {
3470         struct dcesrv_handle *h;
3471         struct lsa_StringLarge *name;
3472         const char *privname;
3473
3474         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3475
3476         if (r->in.luid->high != 0) {
3477                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3478         }
3479
3480         privname = sec_privilege_name(r->in.luid->low);
3481         if (privname == NULL) {
3482                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3483         }
3484
3485         name = talloc(mem_ctx, struct lsa_StringLarge);
3486         if (name == NULL) {
3487                 return NT_STATUS_NO_MEMORY;
3488         }
3489
3490         name->string = privname;
3491
3492         *r->out.name = name;
3493
3494         return NT_STATUS_OK;
3495 }
3496
3497
3498 /*
3499   lsa_LookupPrivDisplayName
3500 */
3501 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3502                                           TALLOC_CTX *mem_ctx,
3503                                           struct lsa_LookupPrivDisplayName *r)
3504 {
3505         struct dcesrv_handle *h;
3506         struct lsa_StringLarge *disp_name = NULL;
3507         enum sec_privilege id;
3508
3509         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3510
3511         id = sec_privilege_id(r->in.name->string);
3512         if (id == SEC_PRIV_INVALID) {
3513                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3514         }
3515
3516         disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3517         if (disp_name == NULL) {
3518                 return NT_STATUS_NO_MEMORY;
3519         }
3520
3521         disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3522         if (disp_name->string == NULL) {
3523                 return NT_STATUS_INTERNAL_ERROR;
3524         }
3525
3526         *r->out.disp_name = disp_name;
3527         *r->out.returned_language_id = 0;
3528
3529         return NT_STATUS_OK;
3530 }
3531
3532
3533 /*
3534   lsa_EnumAccountsWithUserRight
3535 */
3536 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3537                                               TALLOC_CTX *mem_ctx,
3538                                               struct lsa_EnumAccountsWithUserRight *r)
3539 {
3540         struct dcesrv_handle *h;
3541         struct lsa_policy_state *state;
3542         int ret, i;
3543         struct ldb_message **res;
3544         const char * const attrs[] = { "objectSid", NULL};
3545         const char *privname;
3546
3547         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3548
3549         state = h->data;
3550
3551         if (r->in.name == NULL) {
3552                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3553         }
3554
3555         privname = r->in.name->string;
3556         if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
3557                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3558         }
3559
3560         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3561                            "privilege=%s", privname);
3562         if (ret < 0) {
3563                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3564         }
3565         if (ret == 0) {
3566                 return NT_STATUS_NO_MORE_ENTRIES;
3567         }
3568
3569         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3570         if (r->out.sids->sids == NULL) {
3571                 return NT_STATUS_NO_MEMORY;
3572         }
3573         for (i=0;i<ret;i++) {
3574                 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3575                                                                 res[i], "objectSid");
3576                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3577         }
3578         r->out.sids->num_sids = ret;
3579
3580         return NT_STATUS_OK;
3581 }
3582
3583
3584 /*
3585   lsa_AddAccountRights
3586 */
3587 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3588                                      TALLOC_CTX *mem_ctx,
3589                                      struct lsa_AddAccountRights *r)
3590 {
3591         struct dcesrv_handle *h;
3592         struct lsa_policy_state *state;
3593
3594         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3595
3596         state = h->data;
3597
3598         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3599                                           LDB_FLAG_MOD_ADD,
3600                                           r->in.sid, r->in.rights);
3601 }
3602
3603
3604 /*
3605   lsa_RemoveAccountRights
3606 */
3607 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3608                                         TALLOC_CTX *mem_ctx,
3609                                         struct lsa_RemoveAccountRights *r)
3610 {
3611         struct dcesrv_handle *h;
3612         struct lsa_policy_state *state;
3613
3614         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3615
3616         state = h->data;
3617
3618         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3619                                           LDB_FLAG_MOD_DELETE,
3620                                           r->in.sid, r->in.rights);
3621 }
3622
3623
3624 /*
3625   lsa_StorePrivateData
3626 */
3627 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3628                        struct lsa_StorePrivateData *r)
3629 {
3630         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3631 }
3632
3633
3634 /*
3635   lsa_RetrievePrivateData
3636 */
3637 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3638                        struct lsa_RetrievePrivateData *r)
3639 {
3640         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3641 }
3642
3643
3644 /*
3645   lsa_GetUserName
3646 */
3647 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3648                                 struct lsa_GetUserName *r)
3649 {
3650         enum dcerpc_transport_t transport =
3651                 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
3652         NTSTATUS status = NT_STATUS_OK;
3653         const char *account_name;
3654         const char *authority_name;
3655         struct lsa_String *_account_name;
3656         struct lsa_String *_authority_name = NULL;
3657
3658         if (transport != NCACN_NP && transport != NCALRPC) {
3659                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3660         }
3661
3662         /* this is what w2k3 does */
3663         r->out.account_name = r->in.account_name;
3664         r->out.authority_name = r->in.authority_name;
3665
3666         if (r->in.account_name
3667             && *r->in.account_name
3668             /* && *(*r->in.account_name)->string */
3669             ) {
3670                 return NT_STATUS_INVALID_PARAMETER;
3671         }
3672
3673         if (r->in.authority_name
3674             && *r->in.authority_name
3675             /* && *(*r->in.authority_name)->string */
3676             ) {
3677                 return NT_STATUS_INVALID_PARAMETER;
3678         }
3679
3680         account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3681         authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3682
3683         _account_name = talloc(mem_ctx, struct lsa_String);
3684         NT_STATUS_HAVE_NO_MEMORY(_account_name);
3685         _account_name->string = account_name;
3686
3687         if (r->in.authority_name) {
3688                 _authority_name = talloc(mem_ctx, struct lsa_String);
3689                 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3690                 _authority_name->string = authority_name;
3691         }
3692
3693         *r->out.account_name = _account_name;
3694         if (r->out.authority_name) {
3695                 *r->out.authority_name = _authority_name;
3696         }
3697
3698         return status;
3699 }
3700
3701 /*
3702   lsa_SetInfoPolicy2
3703 */
3704 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3705                                    TALLOC_CTX *mem_ctx,
3706                                    struct lsa_SetInfoPolicy2 *r)
3707 {
3708         /* need to support these */
3709         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3710 }
3711
3712 static void kdc_get_policy(struct loadparm_context *lp_ctx,
3713                            struct smb_krb5_context *smb_krb5_context,
3714                            struct lsa_DomainInfoKerberos *k)
3715 {
3716         time_t svc_tkt_lifetime;
3717         time_t usr_tkt_lifetime;
3718         time_t renewal_lifetime;
3719
3720         /* These should be set and stored via Group Policy, but until then, some defaults are in order */
3721
3722         /* Our KDC always re-validates the client */
3723         k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
3724
3725         lpcfg_default_kdc_policy(lp_ctx, &svc_tkt_lifetime,
3726                                  &usr_tkt_lifetime, &renewal_lifetime);
3727
3728         unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
3729         unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
3730         unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
3731 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
3732         However in the parent function we basically just did a full
3733         krb5_context init with the only purpose of getting a global
3734         config option (the max skew), it would probably make more sense
3735         to have a lp_ or ldb global option as the samba default */
3736         if (smb_krb5_context) {
3737                 unix_to_nt_time(&k->clock_skew,
3738                                 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
3739         }
3740 #endif
3741         k->reserved = 0;
3742 }
3743 /*
3744   lsa_QueryDomainInformationPolicy
3745 */
3746 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3747                                                  TALLOC_CTX *mem_ctx,
3748                                                  struct lsa_QueryDomainInformationPolicy *r)
3749 {
3750         union lsa_DomainInformationPolicy *info;
3751
3752         info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
3753         if (!info) {
3754                 return NT_STATUS_NO_MEMORY;
3755         }
3756
3757         switch (r->in.level) {
3758         case LSA_DOMAIN_INFO_POLICY_EFS:
3759                 talloc_free(info);
3760                 *r->out.info = NULL;
3761                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3762         case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3763         {
3764                 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3765                 struct smb_krb5_context *smb_krb5_context;
3766                 int ret = smb_krb5_init_context(mem_ctx,
3767                                                         dce_call->conn->dce_ctx->lp_ctx,
3768                                                         &smb_krb5_context);
3769                 if (ret != 0) {
3770                         talloc_free(info);
3771                         *r->out.info = NULL;
3772                         return NT_STATUS_INTERNAL_ERROR;
3773                 }
3774                 kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
3775                                smb_krb5_context,
3776                                k);
3777                 talloc_free(smb_krb5_context);
3778                 *r->out.info = info;
3779                 return NT_STATUS_OK;
3780         }
3781         default:
3782                 talloc_free(info);
3783                 *r->out.info = NULL;
3784                 return NT_STATUS_INVALID_INFO_CLASS;
3785         }
3786 }
3787
3788 /*
3789   lsa_SetDomInfoPolicy
3790 */
3791 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3792                                               TALLOC_CTX *mem_ctx,
3793                                               struct lsa_SetDomainInformationPolicy *r)
3794 {
3795         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3796 }
3797
3798 /*
3799   lsa_TestCall
3800 */
3801 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3802                              TALLOC_CTX *mem_ctx,
3803                              struct lsa_TestCall *r)
3804 {
3805         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3806 }
3807
3808 /*
3809   lsa_CREDRWRITE
3810 */
3811 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3812                        struct lsa_CREDRWRITE *r)
3813 {
3814         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3815 }
3816
3817
3818 /*
3819   lsa_CREDRREAD
3820 */
3821 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3822                        struct lsa_CREDRREAD *r)
3823 {
3824         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3825 }
3826
3827
3828 /*
3829   lsa_CREDRENUMERATE
3830 */
3831 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3832                        struct lsa_CREDRENUMERATE *r)
3833 {
3834         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3835 }
3836
3837
3838 /*
3839   lsa_CREDRWRITEDOMAINCREDENTIALS
3840 */
3841 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3842                        struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3843 {
3844         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3845 }
3846
3847
3848 /*
3849   lsa_CREDRREADDOMAINCREDENTIALS
3850 */
3851 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3852                        struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3853 {
3854         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3855 }
3856
3857
3858 /*
3859   lsa_CREDRDELETE
3860 */
3861 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3862                        struct lsa_CREDRDELETE *r)
3863 {
3864         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3865 }
3866
3867
3868 /*
3869   lsa_CREDRGETTARGETINFO
3870 */
3871 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3872                        struct lsa_CREDRGETTARGETINFO *r)
3873 {
3874         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3875 }
3876
3877
3878 /*
3879   lsa_CREDRPROFILELOADED
3880 */
3881 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3882                        struct lsa_CREDRPROFILELOADED *r)
3883 {
3884         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3885 }
3886
3887
3888 /*
3889   lsa_CREDRGETSESSIONTYPES
3890 */
3891 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3892                        struct lsa_CREDRGETSESSIONTYPES *r)
3893 {
3894         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3895 }
3896
3897
3898 /*
3899   lsa_LSARREGISTERAUDITEVENT
3900 */
3901 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3902                        struct lsa_LSARREGISTERAUDITEVENT *r)
3903 {
3904         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3905 }
3906
3907
3908 /*
3909   lsa_LSARGENAUDITEVENT
3910 */
3911 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3912                        struct lsa_LSARGENAUDITEVENT *r)
3913 {
3914         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3915 }
3916
3917
3918 /*
3919   lsa_LSARUNREGISTERAUDITEVENT
3920 */
3921 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3922                        struct lsa_LSARUNREGISTERAUDITEVENT *r)
3923 {
3924         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3925 }
3926
3927
3928 /*
3929   lsa_lsaRQueryForestTrustInformation
3930 */
3931 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3932                        struct lsa_lsaRQueryForestTrustInformation *r)
3933 {
3934         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3935 }
3936
3937 #define DNS_CMP_MATCH 0
3938 #define DNS_CMP_FIRST_IS_CHILD 1
3939 #define DNS_CMP_SECOND_IS_CHILD 2
3940 #define DNS_CMP_NO_MATCH 3
3941
3942 /* this function assumes names are well formed DNS names.
3943  * it doesn't validate them */
3944 static int dns_cmp(const char *s1, size_t l1,
3945                    const char *s2, size_t l2)
3946 {
3947         const char *p1, *p2;
3948         size_t t1, t2;
3949         int cret;
3950
3951         if (l1 == l2) {
3952                 if (strcasecmp_m(s1, s2) == 0) {
3953                         return DNS_CMP_MATCH;
3954                 }
3955                 return DNS_CMP_NO_MATCH;
3956         }
3957
3958         if (l1 > l2) {
3959                 p1 = s1;
3960                 p2 = s2;
3961                 t1 = l1;
3962                 t2 = l2;
3963                 cret = DNS_CMP_FIRST_IS_CHILD;
3964         } else {
3965                 p1 = s2;
3966                 p2 = s1;
3967                 t1 = l2;
3968                 t2 = l1;
3969                 cret = DNS_CMP_SECOND_IS_CHILD;
3970         }
3971
3972         if (p1[t1 - t2 - 1] != '.') {
3973                 return DNS_CMP_NO_MATCH;
3974         }
3975
3976         if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
3977                 return cret;
3978         }
3979
3980         return DNS_CMP_NO_MATCH;
3981 }
3982
3983 /* decode all TDOs forest trust info blobs */
3984 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
3985                             struct ldb_message *msg,
3986                             struct ForestTrustInfo *info)
3987 {
3988         const struct ldb_val *ft_blob;
3989         enum ndr_err_code ndr_err;
3990
3991         ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3992         if (!ft_blob || !ft_blob->data) {
3993                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3994         }
3995         /* ldb_val is equivalent to DATA_BLOB */
3996         ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
3997                                            (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
3998         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3999                 return NT_STATUS_INVALID_DOMAIN_STATE;
4000         }
4001
4002         return NT_STATUS_OK;
4003 }
4004
4005 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
4006                             struct ForestTrustInfo *fti)
4007 {
4008         struct ForestTrustDataDomainInfo *info;
4009         struct ForestTrustInfoRecord *rec;
4010
4011         fti->version = 1;
4012         fti->count = 2;
4013         fti->records = talloc_array(fti,
4014                                     struct ForestTrustInfoRecordArmor, 2);
4015         if (!fti->records) {
4016                 return NT_STATUS_NO_MEMORY;
4017         }
4018
4019         /* TLN info */
4020         rec = &fti->records[0].record;
4021
4022         rec->flags = 0;
4023         rec->timestamp = 0;
4024         rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
4025
4026         rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
4027         if (!rec->data.name.string) {
4028                 return NT_STATUS_NO_MEMORY;
4029         }
4030         rec->data.name.size = strlen(rec->data.name.string);
4031
4032         /* DOMAIN info */
4033         rec = &fti->records[1].record;
4034
4035         rec->flags = 0;
4036         rec->timestamp = 0;
4037         rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
4038
4039         info = &rec->data.info;
4040
4041         info->sid = *ps->domain_sid;
4042         info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
4043         if (!info->dns_name.string) {
4044                 return NT_STATUS_NO_MEMORY;
4045         }
4046         info->dns_name.size = strlen(info->dns_name.string);
4047         info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
4048         if (!info->netbios_name.string) {
4049                 return NT_STATUS_NO_MEMORY;
4050         }
4051         info->netbios_name.size = strlen(info->netbios_name.string);
4052
4053         return NT_STATUS_OK;
4054 }
4055
4056 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
4057                              struct lsa_ForestTrustInformation *lfti,
4058                              struct ForestTrustInfo *fti)
4059 {
4060         struct lsa_ForestTrustRecord *lrec;
4061         struct ForestTrustInfoRecord *rec;
4062         struct lsa_StringLarge *tln;
4063         struct lsa_ForestTrustDomainInfo *info;
4064         uint32_t i;
4065
4066         fti->version = 1;
4067         fti->count = lfti->count;
4068         fti->records = talloc_array(mem_ctx,
4069                                     struct ForestTrustInfoRecordArmor,
4070                                     fti->count);
4071         if (!fti->records) {
4072                 return NT_STATUS_NO_MEMORY;
4073         }
4074         for (i = 0; i < fti->count; i++) {
4075                 lrec = lfti->entries[i];
4076                 rec = &fti->records[i].record;
4077
4078                 rec->flags = lrec->flags;
4079                 rec->timestamp = lrec->time;
4080                 rec->type = lrec->type;
4081
4082                 switch (lrec->type) {
4083                 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4084                 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4085                         tln = &lrec->forest_trust_data.top_level_name;
4086                         rec->data.name.string =
4087                                 talloc_strdup(mem_ctx, tln->string);
4088                         if (!rec->data.name.string) {
4089                                 return NT_STATUS_NO_MEMORY;
4090                         }
4091                         rec->data.name.size = strlen(rec->data.name.string);
4092                         break;
4093                 case LSA_FOREST_TRUST_DOMAIN_INFO:
4094                         info = &lrec->forest_trust_data.domain_info;
4095                         rec->data.info.sid = *info->domain_sid;
4096                         rec->data.info.dns_name.string =
4097                                 talloc_strdup(mem_ctx,
4098                                             info->dns_domain_name.string);
4099                         if (!rec->data.info.dns_name.string) {
4100                                 return NT_STATUS_NO_MEMORY;
4101                         }
4102                         rec->data.info.dns_name.size =
4103                                 strlen(rec->data.info.dns_name.string);
4104                         rec->data.info.netbios_name.string =
4105                                 talloc_strdup(mem_ctx,
4106                                             info->netbios_domain_name.string);
4107                         if (!rec->data.info.netbios_name.string) {
4108                                 return NT_STATUS_NO_MEMORY;
4109                         }
4110                         rec->data.info.netbios_name.size =
4111                                 strlen(rec->data.info.netbios_name.string);
4112                         break;
4113                 default:
4114                         return NT_STATUS_INVALID_DOMAIN_STATE;
4115                 }
4116         }
4117
4118         return NT_STATUS_OK;
4119 }
4120
4121 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4122                               uint32_t idx, uint32_t collision_type,
4123                               uint32_t conflict_type, const char *tdo_name);
4124
4125 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4126                               const char *tdo_name,
4127                               struct ForestTrustInfo *tdo_fti,
4128                               struct ForestTrustInfo *new_fti,
4129                               struct lsa_ForestTrustCollisionInfo *c_info)
4130 {
4131         struct ForestTrustInfoRecord *nrec;
4132         struct ForestTrustInfoRecord *trec;
4133         const char *dns_name;
4134         const char *nb_name;
4135         struct dom_sid *sid;
4136         const char *tname;
4137         size_t dns_len;
4138         size_t tlen;
4139         NTSTATUS nt_status = NT_STATUS_OK;
4140         uint32_t new_fti_idx;
4141         uint32_t i;
4142         /* use always TDO type, until we understand when Xref can be used */
4143         uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4144         bool tln_conflict;
4145         bool sid_conflict;
4146         bool nb_conflict;
4147         bool exclusion;
4148         bool ex_rule;
4149         int ret;
4150
4151         for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4152
4153                 nrec = &new_fti->records[new_fti_idx].record;
4154                 dns_name = NULL;
4155                 tln_conflict = false;
4156                 sid_conflict = false;
4157                 nb_conflict = false;
4158                 exclusion = false;
4159
4160                 switch (nrec->type) {
4161                 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4162                         /* exclusions do not conflict by definition */
4163                         break;
4164
4165                 case FOREST_TRUST_TOP_LEVEL_NAME:
4166                         dns_name = nrec->data.name.string;
4167                         dns_len = nrec->data.name.size;
4168                         break;
4169
4170                 case LSA_FOREST_TRUST_DOMAIN_INFO:
4171                         dns_name = nrec->data.info.dns_name.string;
4172                         dns_len = nrec->data.info.dns_name.size;
4173                         nb_name = nrec->data.info.netbios_name.string;
4174                         sid = &nrec->data.info.sid;
4175                         break;
4176                 }
4177
4178                 if (!dns_name) continue;
4179
4180                 /* check if this is already taken and not excluded */
4181                 for (i = 0; i < tdo_fti->count; i++) {
4182                         trec = &tdo_fti->records[i].record;
4183
4184                         switch (trec->type) {
4185                         case FOREST_TRUST_TOP_LEVEL_NAME:
4186                                 ex_rule = false;
4187                                 tname = trec->data.name.string;
4188                                 tlen = trec->data.name.size;
4189                                 break;
4190                         case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4191                                 ex_rule = true;
4192                                 tname = trec->data.name.string;
4193                                 tlen = trec->data.name.size;
4194                                 break;
4195                         case FOREST_TRUST_DOMAIN_INFO:
4196                                 ex_rule = false;
4197                                 tname = trec->data.info.dns_name.string;
4198                                 tlen = trec->data.info.dns_name.size;
4199                         }
4200                         ret = dns_cmp(dns_name, dns_len, tname, tlen);
4201                         switch (ret) {
4202                         case DNS_CMP_MATCH:
4203                                 /* if it matches exclusion,
4204                                  * it doesn't conflict */
4205                                 if (ex_rule) {
4206                                         exclusion = true;
4207                                         break;
4208                                 }
4209                                 /* fall through */
4210                         case DNS_CMP_FIRST_IS_CHILD:
4211                         case DNS_CMP_SECOND_IS_CHILD:
4212                                 tln_conflict = true;
4213                                 /* fall through */
4214                         default:
4215                                 break;
4216                         }
4217
4218                         /* explicit exclusion, no dns name conflict here */
4219                         if (exclusion) {
4220                                 tln_conflict = false;
4221                         }
4222
4223                         if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4224                                 continue;
4225                         }
4226
4227                         /* also test for domain info */
4228                         if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4229                             dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4230                                 sid_conflict = true;
4231                         }
4232                         if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4233                             strcasecmp_m(trec->data.info.netbios_name.string,
4234                                          nb_name) == 0) {
4235                                 nb_conflict = true;
4236                         }
4237                 }
4238
4239                 if (tln_conflict) {
4240                         nt_status = add_collision(c_info, new_fti_idx,
4241                                                   collision_type,
4242                                                   LSA_TLN_DISABLED_CONFLICT,
4243                                                   tdo_name);
4244                         if (!NT_STATUS_IS_OK(nt_status)) {
4245                                 goto done;
4246                         }
4247                 }
4248                 if (sid_conflict) {
4249                         nt_status = add_collision(c_info, new_fti_idx,
4250                                                   collision_type,
4251                                                   LSA_SID_DISABLED_CONFLICT,
4252                                                   tdo_name);
4253                         if (!NT_STATUS_IS_OK(nt_status)) {
4254                                 goto done;
4255                         }
4256                 }
4257                 if (nb_conflict) {
4258                         nt_status = add_collision(c_info, new_fti_idx,
4259                                                   collision_type,
4260                                                   LSA_NB_DISABLED_CONFLICT,
4261                                                   tdo_name);
4262                         if (!NT_STATUS_IS_OK(nt_status)) {
4263                                 goto done;
4264                         }
4265                 }
4266         }
4267
4268 done:
4269         return nt_status;
4270 }
4271
4272 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4273                               uint32_t idx, uint32_t collision_type,
4274                               uint32_t conflict_type, const char *tdo_name)
4275 {
4276         struct lsa_ForestTrustCollisionRecord **es;
4277         uint32_t i = c_info->count;
4278
4279         es = talloc_realloc(c_info, c_info->entries,
4280                             struct lsa_ForestTrustCollisionRecord *, i + 1);
4281         if (!es) {
4282                 return NT_STATUS_NO_MEMORY;
4283         }
4284         c_info->entries = es;
4285         c_info->count = i + 1;
4286
4287         es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4288         if (!es[i]) {
4289                 return NT_STATUS_NO_MEMORY;
4290         }
4291
4292         es[i]->index = idx;
4293         es[i]->type = collision_type;
4294         es[i]->flags.flags = conflict_type;
4295         es[i]->name.string = talloc_strdup(es[i], tdo_name);
4296         if (!es[i]->name.string) {
4297                 return NT_STATUS_NO_MEMORY;
4298         }
4299         es[i]->name.size = strlen(es[i]->name.string);
4300
4301         return NT_STATUS_OK;
4302 }
4303
4304 /*
4305   lsa_lsaRSetForestTrustInformation
4306 */
4307 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4308                                                          TALLOC_CTX *mem_ctx,
4309                                                          struct lsa_lsaRSetForestTrustInformation *r)
4310 {
4311         struct dcesrv_handle *h;
4312         struct lsa_policy_state *p_state;
4313         const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4314                                       "msDS-TrustForestTrustInfo", NULL };
4315         struct ldb_message **dom_res = NULL;
4316         struct ldb_dn *tdo_dn;
4317         struct ldb_message *msg;
4318         int num_res, i;
4319         const char *td_name;
4320         uint32_t trust_attributes;
4321         struct lsa_ForestTrustCollisionInfo *c_info;
4322         struct ForestTrustInfo *nfti;
4323         struct ForestTrustInfo *fti;
4324         DATA_BLOB ft_blob;
4325         enum ndr_err_code ndr_err;
4326         NTSTATUS nt_status;
4327         bool am_rodc;
4328         int ret;
4329
4330         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4331
4332         p_state = h->data;
4333
4334         if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4335                 return NT_STATUS_INVALID_DOMAIN_STATE;
4336         }
4337
4338         /* abort if we are not a PDC */
4339         if (!samdb_is_pdc(p_state->sam_ldb)) {
4340                 return NT_STATUS_INVALID_DOMAIN_ROLE;
4341         }
4342
4343         ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
4344         if (ret == LDB_SUCCESS && am_rodc) {
4345                 return NT_STATUS_NO_SUCH_DOMAIN;
4346         }
4347
4348         /* check caller has TRUSTED_SET_AUTH */
4349
4350         /* fetch all trusted domain objects */
4351         num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4352                                p_state->system_dn,
4353                                &dom_res, trust_attrs,
4354                                "(objectclass=trustedDomain)");
4355         if (num_res == 0) {
4356                 return NT_STATUS_NO_SUCH_DOMAIN;
4357         }
4358
4359         for (i = 0; i < num_res; i++) {
4360                 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4361                                                       "trustPartner", NULL);
4362                 if (!td_name) {
4363                         return NT_STATUS_INVALID_DOMAIN_STATE;
4364                 }
4365                 if (strcasecmp_m(td_name,
4366                                  r->in.trusted_domain_name->string) == 0) {
4367                         break;
4368                 }
4369         }
4370         if (i >= num_res) {
4371                 return NT_STATUS_NO_SUCH_DOMAIN;
4372         }
4373
4374         tdo_dn = dom_res[i]->dn;
4375
4376         trust_attributes = ldb_msg_find_attr_as_uint(dom_res[i],
4377                                                      "trustAttributes", 0);
4378         if (!(trust_attributes & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4379                 return NT_STATUS_INVALID_PARAMETER;
4380         }
4381
4382         if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4383                 return NT_STATUS_INVALID_PARAMETER;
4384         }
4385
4386         nfti = talloc(mem_ctx, struct ForestTrustInfo);
4387         if (!nfti) {
4388                 return NT_STATUS_NO_MEMORY;
4389         }
4390
4391         nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4392         if (!NT_STATUS_IS_OK(nt_status)) {
4393                 return nt_status;
4394         }
4395
4396         c_info = talloc_zero(r->out.collision_info,
4397                              struct lsa_ForestTrustCollisionInfo);
4398         if (!c_info) {
4399                 return NT_STATUS_NO_MEMORY;
4400         }
4401
4402         /* first check own info, then other domains */
4403         fti = talloc(mem_ctx, struct ForestTrustInfo);
4404         if (!fti) {
4405                 return NT_STATUS_NO_MEMORY;
4406         }
4407
4408         nt_status = own_ft_info(p_state, fti);
4409         if (!NT_STATUS_IS_OK(nt_status)) {
4410                 return nt_status;
4411         }
4412
4413         nt_status = check_ft_info(c_info, p_state->domain_dns,
4414                                   fti, nfti, c_info);
4415         if (!NT_STATUS_IS_OK(nt_status)) {
4416                 return nt_status;
4417         }
4418
4419         for (i = 0; i < num_res; i++) {
4420                 fti = talloc(mem_ctx, struct ForestTrustInfo);
4421                 if (!fti) {
4422                         return NT_STATUS_NO_MEMORY;
4423                 }
4424
4425                 nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
4426                 if (!NT_STATUS_IS_OK(nt_status)) {
4427                         if (NT_STATUS_EQUAL(nt_status,
4428                             NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4429                                 continue;
4430                         }
4431                         return nt_status;
4432                 }
4433
4434                 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4435                                                       "trustPartner", NULL);
4436                 if (!td_name) {
4437                         return NT_STATUS_INVALID_DOMAIN_STATE;
4438                 }
4439
4440                 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4441                 if (!NT_STATUS_IS_OK(nt_status)) {
4442                         return nt_status;
4443                 }
4444         }
4445
4446         *r->out.collision_info = c_info;
4447
4448         if (r->in.check_only != 0) {
4449                 return NT_STATUS_OK;
4450         }
4451
4452         /* not just a check, write info back */
4453
4454         ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
4455                                        (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4456         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4457                 return NT_STATUS_INVALID_PARAMETER;
4458         }
4459
4460         msg = ldb_msg_new(mem_ctx);
4461         if (msg == NULL) {
4462                 return NT_STATUS_NO_MEMORY;
4463         }
4464
4465         msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4466         if (!msg->dn) {
4467                 return NT_STATUS_NO_MEMORY;
4468         }
4469
4470         ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4471                                 LDB_FLAG_MOD_REPLACE, NULL);
4472         if (ret != LDB_SUCCESS) {
4473                 return NT_STATUS_NO_MEMORY;
4474         }
4475         ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4476                                 &ft_blob, NULL);
4477         if (ret != LDB_SUCCESS) {
4478                 return NT_STATUS_NO_MEMORY;
4479         }
4480
4481         ret = ldb_modify(p_state->sam_ldb, msg);
4482         if (ret != LDB_SUCCESS) {
4483                 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4484                           ldb_errstring(p_state->sam_ldb)));
4485
4486                 switch (ret) {
4487                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4488                         return NT_STATUS_ACCESS_DENIED;
4489                 default:
4490                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
4491                 }
4492         }
4493
4494         return NT_STATUS_OK;
4495 }
4496
4497 /*
4498   lsa_CREDRRENAME
4499 */
4500 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4501                        struct lsa_CREDRRENAME *r)
4502 {
4503         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4504 }
4505
4506
4507
4508 /*
4509   lsa_LSAROPENPOLICYSCE
4510 */
4511 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4512                        struct lsa_LSAROPENPOLICYSCE *r)
4513 {
4514         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4515 }
4516
4517
4518 /*
4519   lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4520 */
4521 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4522                        struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4523 {
4524         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4525 }
4526
4527
4528 /*
4529   lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4530 */
4531 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4532                        struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4533 {
4534         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4535 }
4536
4537
4538 /*
4539   lsa_LSARADTREPORTSECURITYEVENT
4540 */
4541 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4542                        struct lsa_LSARADTREPORTSECURITYEVENT *r)
4543 {
4544         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4545 }
4546
4547
4548 /* include the generated boilerplate */
4549 #include "librpc/gen_ndr/ndr_lsa_s.c"
4550
4551
4552
4553 /*****************************************
4554 NOTE! The remaining calls below were
4555 removed in w2k3, so the DCESRV_FAULT()
4556 replies are the correct implementation. Do
4557 not try and fill these in with anything else
4558 ******************************************/
4559
4560 /*
4561   dssetup_DsRoleDnsNameToFlatName
4562 */
4563 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4564                                         struct dssetup_DsRoleDnsNameToFlatName *r)
4565 {
4566         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4567 }
4568
4569
4570 /*
4571   dssetup_DsRoleDcAsDc
4572 */
4573 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4574                              struct dssetup_DsRoleDcAsDc *r)
4575 {
4576         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4577 }
4578
4579
4580 /*
4581   dssetup_DsRoleDcAsReplica
4582 */
4583 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4584                                   struct dssetup_DsRoleDcAsReplica *r)
4585 {
4586         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4587 }
4588
4589
4590 /*
4591   dssetup_DsRoleDemoteDc
4592 */
4593 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4594                                struct dssetup_DsRoleDemoteDc *r)
4595 {
4596         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4597 }
4598
4599
4600 /*
4601   dssetup_DsRoleGetDcOperationProgress
4602 */
4603 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4604                                              struct dssetup_DsRoleGetDcOperationProgress *r)
4605 {
4606         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4607 }
4608
4609
4610 /* 
4611   dssetup_DsRoleGetDcOperationResults 
4612 */
4613 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4614                                             struct dssetup_DsRoleGetDcOperationResults *r)
4615 {
4616         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4617 }
4618
4619
4620 /* 
4621   dssetup_DsRoleCancel 
4622 */
4623 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4624                              struct dssetup_DsRoleCancel *r)
4625 {
4626         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4627 }
4628
4629
4630 /*
4631   dssetup_DsRoleServerSaveStateForUpgrade
4632 */
4633 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4634                                                 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4635 {
4636         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4637 }
4638
4639
4640 /*
4641   dssetup_DsRoleUpgradeDownlevelServer
4642 */
4643 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4644                                              struct dssetup_DsRoleUpgradeDownlevelServer *r)
4645 {
4646         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4647 }
4648
4649
4650 /*
4651   dssetup_DsRoleAbortDownlevelServerUpgrade
4652 */
4653 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4654                                                   struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4655 {
4656         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4657 }
4658
4659
4660 /* include the generated boilerplate */
4661 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4662
4663 NTSTATUS dcerpc_server_lsa_init(void)
4664 {
4665         NTSTATUS ret;
4666
4667         ret = dcerpc_server_dssetup_init();
4668         if (!NT_STATUS_IS_OK(ret)) {
4669                 return ret;
4670         }
4671         ret = dcerpc_server_lsarpc_init();
4672         if (!NT_STATUS_IS_OK(ret)) {
4673                 return ret;
4674         }
4675         return ret;
4676 }