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