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