s4:rpc_server/lsa: implement the policy security descriptor
[kai/samba-autobuild/.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
1 /* need access mask/acl implementation */
2
3 /* 
4    Unix SMB/CIFS implementation.
5
6    endpoint server for the lsarpc pipe
7
8    Copyright (C) Andrew Tridgell 2004
9    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "rpc_server/lsa/lsa.h"
26 #include "system/kerberos.h"
27 #include "auth/kerberos/kerberos.h"
28 #include "librpc/gen_ndr/ndr_drsblobs.h"
29 #include "librpc/gen_ndr/ndr_lsa.h"
30 #include "../lib/crypto/crypto.h"
31 #include "lib/util/tsort.h"
32 #include "dsdb/common/util.h"
33 #include "libcli/security/session.h"
34 #include "libcli/lsarpc/util_lsarpc.h"
35
36 /*
37   this type allows us to distinguish handle types
38 */
39
40 /*
41   state associated with a lsa_OpenAccount() operation
42 */
43 struct lsa_account_state {
44         struct lsa_policy_state *policy;
45         uint32_t access_mask;
46         struct dom_sid *account_sid;
47 };
48
49
50 /*
51   state associated with a lsa_OpenSecret() operation
52 */
53 struct lsa_secret_state {
54         struct lsa_policy_state *policy;
55         uint32_t access_mask;
56         struct ldb_dn *secret_dn;
57         struct ldb_context *sam_ldb;
58         bool global;
59 };
60
61 /*
62   state associated with a lsa_OpenTrustedDomain() operation
63 */
64 struct lsa_trusted_domain_state {
65         struct lsa_policy_state *policy;
66         uint32_t access_mask;
67         struct ldb_dn *trusted_domain_dn;
68         struct ldb_dn *trusted_domain_user_dn;
69 };
70
71 /*
72   this is based on the samba3 function make_lsa_object_sd()
73   It uses the same logic, but with samba4 helper functions
74  */
75 static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx,
76                                     struct security_descriptor **sd,
77                                     struct dom_sid *sid,
78                                     uint32_t sid_access)
79 {
80         NTSTATUS status;
81         uint32_t rid;
82         struct dom_sid *domain_sid, *domain_admins_sid;
83         const char *domain_admins_sid_str, *sidstr;
84         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
85
86         status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
87         if (!NT_STATUS_IS_OK(status)) {
88                 TALLOC_FREE(tmp_ctx);
89                 return status;
90         }
91
92         domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
93         if (domain_admins_sid == NULL) {
94                 TALLOC_FREE(tmp_ctx);
95                 return NT_STATUS_NO_MEMORY;
96         }
97
98         domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
99         if (domain_admins_sid_str == NULL) {
100                 TALLOC_FREE(tmp_ctx);
101                 return NT_STATUS_NO_MEMORY;
102         }
103
104         sidstr = dom_sid_string(tmp_ctx, sid);
105         if (sidstr == NULL) {
106                 TALLOC_FREE(tmp_ctx);
107                 return NT_STATUS_NO_MEMORY;
108         }
109
110         *sd = security_descriptor_dacl_create(mem_ctx,
111                                               0, sidstr, NULL,
112
113                                               SID_WORLD,
114                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
115                                               SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
116
117                                               SID_BUILTIN_ADMINISTRATORS,
118                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
119                                               SEC_GENERIC_ALL, 0,
120
121                                               SID_BUILTIN_ACCOUNT_OPERATORS,
122                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
123                                               SEC_GENERIC_ALL, 0,
124
125                                               domain_admins_sid_str,
126                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
127                                               SEC_GENERIC_ALL, 0,
128
129                                               sidstr,
130                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
131                                               sid_access, 0,
132
133                                               NULL);
134         talloc_free(tmp_ctx);
135
136         NT_STATUS_HAVE_NO_MEMORY(*sd);
137
138         return NT_STATUS_OK;
139 }
140
141
142 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
143                                       TALLOC_CTX *mem_ctx,
144                                       struct lsa_EnumAccountRights *r);
145
146 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
147                                            TALLOC_CTX *mem_ctx,
148                                            struct lsa_policy_state *state,
149                                            int ldb_flag,
150                                            struct dom_sid *sid,
151                                            const struct lsa_RightSet *rights);
152
153 /*
154   lsa_Close
155 */
156 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
157                           struct lsa_Close *r)
158 {
159         enum dcerpc_transport_t transport =
160                 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
161         struct dcesrv_handle *h;
162
163         if (transport != NCACN_NP && transport != NCALRPC) {
164                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
165         }
166
167         *r->out.handle = *r->in.handle;
168
169         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
170
171         talloc_free(h);
172
173         ZERO_STRUCTP(r->out.handle);
174
175         return NT_STATUS_OK;
176 }
177
178
179 /*
180   lsa_Delete
181 */
182 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
183                            struct lsa_Delete *r)
184 {
185         return NT_STATUS_NOT_SUPPORTED;
186 }
187
188
189 /*
190   lsa_DeleteObject
191 */
192 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
193                        struct lsa_DeleteObject *r)
194 {
195         struct dcesrv_handle *h;
196         int ret;
197
198         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
199
200         if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
201                 struct lsa_secret_state *secret_state = h->data;
202
203                 /* Ensure user is permitted to delete this... */
204                 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
205                 {
206                 case SECURITY_SYSTEM:
207                 case SECURITY_ADMINISTRATOR:
208                         break;
209                 default:
210                         /* Users and anonymous are not allowed to delete things */
211                         return NT_STATUS_ACCESS_DENIED;
212                 }
213
214                 ret = ldb_delete(secret_state->sam_ldb,
215                                  secret_state->secret_dn);
216                 if (ret != LDB_SUCCESS) {
217                         return NT_STATUS_INVALID_HANDLE;
218                 }
219
220                 ZERO_STRUCTP(r->out.handle);
221
222                 return NT_STATUS_OK;
223
224         } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
225                 struct lsa_trusted_domain_state *trusted_domain_state =
226                         talloc_get_type(h->data, struct lsa_trusted_domain_state);
227                 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
228                 if (ret != LDB_SUCCESS) {
229                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
230                 }
231
232                 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
233                                  trusted_domain_state->trusted_domain_dn);
234                 if (ret != LDB_SUCCESS) {
235                         ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
236                         return NT_STATUS_INVALID_HANDLE;
237                 }
238
239                 if (trusted_domain_state->trusted_domain_user_dn) {
240                         ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
241                                          trusted_domain_state->trusted_domain_user_dn);
242                         if (ret != LDB_SUCCESS) {
243                                 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
244                                 return NT_STATUS_INVALID_HANDLE;
245                         }
246                 }
247
248                 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
249                 if (ret != LDB_SUCCESS) {
250                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
251                 }
252
253                 ZERO_STRUCTP(r->out.handle);
254
255                 return NT_STATUS_OK;
256
257         } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
258                 struct lsa_RightSet *rights;
259                 struct lsa_account_state *astate;
260                 struct lsa_EnumAccountRights r2;
261                 NTSTATUS status;
262
263                 rights = talloc(mem_ctx, struct lsa_RightSet);
264
265                 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
266
267                 astate = h->data;
268
269                 r2.in.handle = &astate->policy->handle->wire_handle;
270                 r2.in.sid = astate->account_sid;
271                 r2.out.rights = rights;
272
273                 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
274                    but we have a LSA_HANDLE_ACCOUNT here, so this call
275                    will always fail */
276                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
277                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
278                         return NT_STATUS_OK;
279                 }
280
281                 if (!NT_STATUS_IS_OK(status)) {
282                         return status;
283                 }
284
285                 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
286                                                     LDB_FLAG_MOD_DELETE, astate->account_sid,
287                                                     r2.out.rights);
288                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
289                         return NT_STATUS_OK;
290                 }
291
292                 if (!NT_STATUS_IS_OK(status)) {
293                         return status;
294                 }
295
296                 ZERO_STRUCTP(r->out.handle);
297
298                 return NT_STATUS_OK;
299         }
300
301         return NT_STATUS_INVALID_HANDLE;
302 }
303
304
305 /*
306   lsa_EnumPrivs
307 */
308 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
309                               struct lsa_EnumPrivs *r)
310 {
311         struct dcesrv_handle *h;
312         uint32_t i;
313         enum sec_privilege priv;
314         const char *privname;
315
316         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
317
318         i = *r->in.resume_handle;
319
320         while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
321                r->out.privs->count < r->in.max_count) {
322                 struct lsa_PrivEntry *e;
323                 privname = sec_privilege_name(priv);
324                 r->out.privs->privs = talloc_realloc(r->out.privs,
325                                                        r->out.privs->privs,
326                                                        struct lsa_PrivEntry,
327                                                        r->out.privs->count+1);
328                 if (r->out.privs->privs == NULL) {
329                         return NT_STATUS_NO_MEMORY;
330                 }
331                 e = &r->out.privs->privs[r->out.privs->count];
332                 e->luid.low = priv;
333                 e->luid.high = 0;
334                 e->name.string = privname;
335                 r->out.privs->count++;
336                 i++;
337         }
338
339         *r->out.resume_handle = i;
340
341         return NT_STATUS_OK;
342 }
343
344
345 /*
346   lsa_QuerySecObj
347 */
348 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
349                                          struct lsa_QuerySecurity *r)
350 {
351         struct dcesrv_handle *h;
352         const struct security_descriptor *sd = NULL;
353         uint32_t access_granted = 0;
354         struct sec_desc_buf *sdbuf = NULL;
355         NTSTATUS status;
356         struct dom_sid *sid;
357
358         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
359
360         sid = &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
361
362         if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
363                 struct lsa_policy_state *pstate = h->data;
364
365                 sd = pstate->sd;
366                 access_granted = pstate->access_mask;
367
368         } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
369                 struct lsa_account_state *astate = h->data;
370                 struct security_descriptor *_sd = NULL;
371
372                 status = dcesrv_build_lsa_sd(mem_ctx, &_sd, sid,
373                                              LSA_ACCOUNT_ALL_ACCESS);
374                 if (!NT_STATUS_IS_OK(status)) {
375                         return status;
376                 }
377                 sd = _sd;
378                 access_granted = astate->access_mask;
379         } else {
380                 return NT_STATUS_INVALID_HANDLE;
381         }
382
383         sdbuf = talloc_zero(mem_ctx, struct sec_desc_buf);
384         if (sdbuf == NULL) {
385                 return NT_STATUS_NO_MEMORY;
386         }
387
388         status = security_descriptor_for_client(sdbuf, sd, r->in.sec_info,
389                                                 access_granted, &sdbuf->sd);
390         if (!NT_STATUS_IS_OK(status)) {
391                 return status;
392         }
393
394         *r->out.sdbuf = sdbuf;
395
396         return NT_STATUS_OK;
397 }
398
399
400 /*
401   lsa_SetSecObj
402 */
403 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
404                               struct lsa_SetSecObj *r)
405 {
406         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
407 }
408
409
410 /*
411   lsa_ChangePassword
412 */
413 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
414                                    struct lsa_ChangePassword *r)
415 {
416         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
417 }
418
419 /*
420   dssetup_DsRoleGetPrimaryDomainInformation
421
422   This is not an LSA call, but is the only call left on the DSSETUP
423   pipe (after the pipe was truncated), and needs lsa_get_policy_state
424 */
425 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
426                                                  TALLOC_CTX *mem_ctx,
427                                                  struct dssetup_DsRoleGetPrimaryDomainInformation *r)
428 {
429         union dssetup_DsRoleInfo *info;
430
431         info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
432         W_ERROR_HAVE_NO_MEMORY(info);
433
434         switch (r->in.level) {
435         case DS_ROLE_BASIC_INFORMATION:
436         {
437                 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
438                 uint32_t flags = 0;
439                 const char *domain = NULL;
440                 const char *dns_domain = NULL;
441                 const char *forest = NULL;
442                 struct GUID domain_guid;
443                 struct lsa_policy_state *state;
444
445                 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx,
446                                                               0, /* we skip access checks */
447                                                               &state);
448                 if (!NT_STATUS_IS_OK(status)) {
449                         return ntstatus_to_werror(status);
450                 }
451
452                 ZERO_STRUCT(domain_guid);
453
454                 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
455                 case ROLE_STANDALONE:
456                         role            = DS_ROLE_STANDALONE_SERVER;
457                         break;
458                 case ROLE_DOMAIN_MEMBER:
459                         role            = DS_ROLE_MEMBER_SERVER;
460                         break;
461                 case ROLE_ACTIVE_DIRECTORY_DC:
462                         if (samdb_is_pdc(state->sam_ldb)) {
463                                 role    = DS_ROLE_PRIMARY_DC;
464                         } else {
465                                 role    = DS_ROLE_BACKUP_DC;
466                         }
467                         break;
468                 }
469
470                 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
471                 case ROLE_STANDALONE:
472                         domain          = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
473                         W_ERROR_HAVE_NO_MEMORY(domain);
474                         break;
475                 case ROLE_DOMAIN_MEMBER:
476                         domain          = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
477                         W_ERROR_HAVE_NO_MEMORY(domain);
478                         /* TODO: what is with dns_domain and forest and guid? */
479                         break;
480                 case ROLE_ACTIVE_DIRECTORY_DC:
481                         flags           = DS_ROLE_PRIMARY_DS_RUNNING;
482
483                         if (state->mixed_domain == 1) {
484                                 flags   |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
485                         }
486
487                         domain          = state->domain_name;
488                         dns_domain      = state->domain_dns;
489                         forest          = state->forest_dns;
490
491                         domain_guid     = state->domain_guid;
492                         flags   |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
493                         break;
494                 }
495
496                 info->basic.role        = role;
497                 info->basic.flags       = flags;
498                 info->basic.domain      = domain;
499                 info->basic.dns_domain  = dns_domain;
500                 info->basic.forest      = forest;
501                 info->basic.domain_guid = domain_guid;
502
503                 r->out.info = info;
504                 return WERR_OK;
505         }
506         case DS_ROLE_UPGRADE_STATUS:
507         {
508                 info->upgrade.upgrading     = DS_ROLE_NOT_UPGRADING;
509                 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
510
511                 r->out.info = info;
512                 return WERR_OK;
513         }
514         case DS_ROLE_OP_STATUS:
515         {
516                 info->opstatus.status = DS_ROLE_OP_IDLE;
517
518                 r->out.info = info;
519                 return WERR_OK;
520         }
521         default:
522                 return WERR_INVALID_PARAM;
523         }
524 }
525
526 /*
527   fill in the AccountDomain info
528 */
529 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
530                                        struct lsa_DomainInfo *info)
531 {
532         info->name.string = state->domain_name;
533         info->sid         = state->domain_sid;
534
535         return NT_STATUS_OK;
536 }
537
538 /*
539   fill in the DNS domain info
540 */
541 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
542                              struct lsa_DnsDomainInfo *info)
543 {
544         info->name.string = state->domain_name;
545         info->sid         = state->domain_sid;
546         info->dns_domain.string = state->domain_dns;
547         info->dns_forest.string = state->forest_dns;
548         info->domain_guid       = state->domain_guid;
549
550         return NT_STATUS_OK;
551 }
552
553 /*
554   lsa_QueryInfoPolicy2
555 */
556 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
557                                      struct lsa_QueryInfoPolicy2 *r)
558 {
559         struct lsa_policy_state *state;
560         struct dcesrv_handle *h;
561         union lsa_PolicyInformation *info;
562
563         *r->out.info = NULL;
564
565         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
566
567         state = h->data;
568
569         info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
570         if (!info) {
571                 return NT_STATUS_NO_MEMORY;
572         }
573         *r->out.info = info;
574
575         switch (r->in.level) {
576         case LSA_POLICY_INFO_AUDIT_LOG:
577                 /* we don't need to fill in any of this */
578                 ZERO_STRUCT(info->audit_log);
579                 return NT_STATUS_OK;
580         case LSA_POLICY_INFO_AUDIT_EVENTS:
581                 /* we don't need to fill in any of this */
582                 ZERO_STRUCT(info->audit_events);
583                 return NT_STATUS_OK;
584         case LSA_POLICY_INFO_PD:
585                 /* we don't need to fill in any of this */
586                 ZERO_STRUCT(info->pd);
587                 return NT_STATUS_OK;
588
589         case LSA_POLICY_INFO_DOMAIN:
590                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
591         case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
592                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
593         case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
594                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
595
596         case LSA_POLICY_INFO_ROLE:
597                 info->role.role = LSA_ROLE_PRIMARY;
598                 return NT_STATUS_OK;
599
600         case LSA_POLICY_INFO_DNS:
601         case LSA_POLICY_INFO_DNS_INT:
602                 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
603
604         case LSA_POLICY_INFO_REPLICA:
605                 ZERO_STRUCT(info->replica);
606                 return NT_STATUS_OK;
607
608         case LSA_POLICY_INFO_QUOTA:
609                 ZERO_STRUCT(info->quota);
610                 return NT_STATUS_OK;
611
612         case LSA_POLICY_INFO_MOD:
613         case LSA_POLICY_INFO_AUDIT_FULL_SET:
614         case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
615                 /* windows gives INVALID_PARAMETER */
616                 *r->out.info = NULL;
617                 return NT_STATUS_INVALID_PARAMETER;
618         }
619
620         *r->out.info = NULL;
621         return NT_STATUS_INVALID_INFO_CLASS;
622 }
623
624 /*
625   lsa_QueryInfoPolicy
626 */
627 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
628                                     struct lsa_QueryInfoPolicy *r)
629 {
630         struct lsa_QueryInfoPolicy2 r2;
631         NTSTATUS status;
632
633         ZERO_STRUCT(r2);
634
635         r2.in.handle = r->in.handle;
636         r2.in.level = r->in.level;
637         r2.out.info = r->out.info;
638
639         status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
640
641         return status;
642 }
643
644 /*
645   lsa_SetInfoPolicy
646 */
647 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
648                                   struct lsa_SetInfoPolicy *r)
649 {
650         /* need to support this */
651         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
652 }
653
654
655 /*
656   lsa_ClearAuditLog
657 */
658 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
659                                   struct lsa_ClearAuditLog *r)
660 {
661         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
662 }
663
664
665 static const struct generic_mapping dcesrv_lsa_account_mapping = {
666         LSA_ACCOUNT_READ,
667         LSA_ACCOUNT_WRITE,
668         LSA_ACCOUNT_EXECUTE,
669         LSA_ACCOUNT_ALL_ACCESS
670 };
671
672 /*
673   lsa_CreateAccount
674
675   This call does not seem to have any long-term effects, hence no database operations
676
677   we need to talk to the MS product group to find out what this account database means!
678
679   answer is that the lsa database is totally separate from the SAM and
680   ldap databases. We are going to need a separate ldb to store these
681   accounts. The SIDs on this account bear no relation to the SIDs in
682   AD
683 */
684 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
685                                   struct lsa_CreateAccount *r)
686 {
687         struct lsa_account_state *astate;
688
689         struct lsa_policy_state *state;
690         struct dcesrv_handle *h, *ah;
691
692         ZERO_STRUCTP(r->out.acct_handle);
693
694         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
695
696         state = h->data;
697
698         astate = talloc(dce_call->conn, struct lsa_account_state);
699         if (astate == NULL) {
700                 return NT_STATUS_NO_MEMORY;
701         }
702
703         astate->account_sid = dom_sid_dup(astate, r->in.sid);
704         if (astate->account_sid == NULL) {
705                 talloc_free(astate);
706                 return NT_STATUS_NO_MEMORY;
707         }
708
709         astate->policy = talloc_reference(astate, state);
710         astate->access_mask = r->in.access_mask;
711
712         /*
713          * For now we grant all requested access.
714          *
715          * We will fail at the ldb layer later.
716          */
717         if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
718                 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
719                 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
720         }
721         se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
722
723         DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X].\n",
724                   __func__, dom_sid_string(mem_ctx, astate->account_sid),
725                  (unsigned)r->in.access_mask,
726                  (unsigned)astate->access_mask));
727
728         ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
729         if (!ah) {
730                 talloc_free(astate);
731                 return NT_STATUS_NO_MEMORY;
732         }
733
734         ah->data = talloc_steal(ah, astate);
735
736         *r->out.acct_handle = ah->wire_handle;
737
738         return NT_STATUS_OK;
739 }
740
741
742 /*
743   lsa_EnumAccounts
744 */
745 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
746                                  struct lsa_EnumAccounts *r)
747 {
748         struct dcesrv_handle *h;
749         struct lsa_policy_state *state;
750         int ret;
751         struct ldb_message **res;
752         const char * const attrs[] = { "objectSid", NULL};
753         uint32_t count, i;
754
755         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
756
757         state = h->data;
758
759         /* NOTE: This call must only return accounts that have at least
760            one privilege set
761         */
762         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
763                            "(&(objectSid=*)(privilege=*))");
764         if (ret < 0) {
765                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
766         }
767
768         if (*r->in.resume_handle >= ret) {
769                 return NT_STATUS_NO_MORE_ENTRIES;
770         }
771
772         count = ret - *r->in.resume_handle;
773         if (count > r->in.num_entries) {
774                 count = r->in.num_entries;
775         }
776
777         if (count == 0) {
778                 return NT_STATUS_NO_MORE_ENTRIES;
779         }
780
781         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
782         if (r->out.sids->sids == NULL) {
783                 return NT_STATUS_NO_MEMORY;
784         }
785
786         for (i=0;i<count;i++) {
787                 r->out.sids->sids[i].sid =
788                         samdb_result_dom_sid(r->out.sids->sids,
789                                              res[i + *r->in.resume_handle],
790                                              "objectSid");
791                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
792         }
793
794         r->out.sids->num_sids = count;
795         *r->out.resume_handle = count + *r->in.resume_handle;
796
797         return NT_STATUS_OK;
798 }
799
800 /* This decrypts and returns Trusted Domain Auth Information Internal data */
801 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
802                                        TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
803                                        struct trustDomainPasswords *auth_struct)
804 {
805         DATA_BLOB session_key = data_blob(NULL, 0);
806         enum ndr_err_code ndr_err;
807         NTSTATUS nt_status;
808
809         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
810         if (!NT_STATUS_IS_OK(nt_status)) {
811                 return nt_status;
812         }
813
814         arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
815         ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
816                                        auth_struct,
817                                        (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
818         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
819                 return NT_STATUS_INVALID_PARAMETER;
820         }
821
822         return NT_STATUS_OK;
823 }
824
825 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
826                                          TALLOC_CTX *mem_ctx,
827                                          struct trustAuthInOutBlob *iopw,
828                                          DATA_BLOB *trustauth_blob)
829 {
830         enum ndr_err_code ndr_err;
831
832         ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
833                                        iopw,
834                                        (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
835         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
836                 return NT_STATUS_INVALID_PARAMETER;
837         }
838
839         return NT_STATUS_OK;
840 }
841
842 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
843                                struct ldb_context *sam_ldb,
844                                struct ldb_dn *base_dn,
845                                const char *netbios_name,
846                                struct trustAuthInOutBlob *in,
847                                struct ldb_dn **user_dn)
848 {
849         struct ldb_request *req;
850         struct ldb_message *msg;
851         struct ldb_dn *dn;
852         uint32_t i;
853         int ret;
854
855         dn = ldb_dn_copy(mem_ctx, base_dn);
856         if (!dn) {
857                 return NT_STATUS_NO_MEMORY;
858         }
859         if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
860                 return NT_STATUS_NO_MEMORY;
861         }
862
863         msg = ldb_msg_new(mem_ctx);
864         if (!msg) {
865                 return NT_STATUS_NO_MEMORY;
866         }
867         msg->dn = dn;
868
869         ret = ldb_msg_add_string(msg, "objectClass", "user");
870         if (ret != LDB_SUCCESS) {
871                 return NT_STATUS_NO_MEMORY;
872         }
873
874         ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
875         if (ret != LDB_SUCCESS) {
876                 return NT_STATUS_NO_MEMORY;
877         }
878
879         ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
880                                  UF_INTERDOMAIN_TRUST_ACCOUNT);
881         if (ret != LDB_SUCCESS) {
882                 return NT_STATUS_NO_MEMORY;
883         }
884
885         for (i = 0; i < in->count; i++) {
886                 const char *attribute;
887                 struct ldb_val v;
888                 switch (in->current.array[i].AuthType) {
889                 case TRUST_AUTH_TYPE_NT4OWF:
890                         attribute = "unicodePwd";
891                         v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
892                         v.length = 16;
893                         break;
894                 case TRUST_AUTH_TYPE_CLEAR:
895                         attribute = "clearTextPassword";
896                         v.data = in->current.array[i].AuthInfo.clear.password;
897                         v.length = in->current.array[i].AuthInfo.clear.size;
898                         break;
899                 default:
900                         continue;
901                 }
902
903                 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
904                 if (ret != LDB_SUCCESS) {
905                         return NT_STATUS_NO_MEMORY;
906                 }
907         }
908
909         /* create the trusted_domain user account */
910         ret = ldb_build_add_req(&req, sam_ldb, mem_ctx, msg, NULL, NULL,
911                                 ldb_op_default_callback, NULL);
912         if (ret != LDB_SUCCESS) {
913                 return NT_STATUS_NO_MEMORY;
914         }
915
916         ret = ldb_request_add_control(req, DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
917                                       false, NULL);
918         if (ret != LDB_SUCCESS) {
919                 return NT_STATUS_NO_MEMORY;
920         }
921
922         ret = dsdb_autotransaction_request(sam_ldb, req);
923         if (ret != LDB_SUCCESS) {
924                 DEBUG(0,("Failed to create user record %s: %s\n",
925                          ldb_dn_get_linearized(msg->dn),
926                          ldb_errstring(sam_ldb)));
927
928                 switch (ret) {
929                 case LDB_ERR_ENTRY_ALREADY_EXISTS:
930                         return NT_STATUS_DOMAIN_EXISTS;
931                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
932                         return NT_STATUS_ACCESS_DENIED;
933                 default:
934                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
935                 }
936         }
937
938         if (user_dn) {
939                 *user_dn = dn;
940         }
941         return NT_STATUS_OK;
942 }
943
944 /*
945   lsa_CreateTrustedDomainEx2
946 */
947 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
948                                                     TALLOC_CTX *mem_ctx,
949                                                     struct lsa_CreateTrustedDomainEx2 *r,
950                                                     int op,
951                                                     struct lsa_TrustDomainInfoAuthInfo *unencrypted_auth_info)
952 {
953         struct dcesrv_handle *policy_handle;
954         struct lsa_policy_state *policy_state;
955         struct lsa_trusted_domain_state *trusted_domain_state;
956         struct dcesrv_handle *handle;
957         struct ldb_message **msgs, *msg;
958         const char *attrs[] = {
959                 NULL
960         };
961         const char *netbios_name;
962         const char *dns_name;
963         const char *name;
964         DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
965         struct trustDomainPasswords auth_struct;
966         int ret;
967         NTSTATUS nt_status;
968         struct ldb_context *sam_ldb;
969
970         DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
971         ZERO_STRUCTP(r->out.trustdom_handle);
972
973         policy_state = policy_handle->data;
974         sam_ldb = policy_state->sam_ldb;
975
976         netbios_name = r->in.info->netbios_name.string;
977         if (!netbios_name) {
978                 return NT_STATUS_INVALID_PARAMETER;
979         }
980
981         dns_name = r->in.info->domain_name.string;
982
983         trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
984         if (!trusted_domain_state) {
985                 return NT_STATUS_NO_MEMORY;
986         }
987         trusted_domain_state->policy = policy_state;
988
989         if (strcasecmp(netbios_name, "BUILTIN") == 0
990             || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0)
991             || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
992                 return NT_STATUS_INVALID_PARAMETER;
993         }
994
995         if (strcasecmp(netbios_name, policy_state->domain_name) == 0
996             || strcasecmp(netbios_name, policy_state->domain_dns) == 0
997             || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0)
998             || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0)
999             || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
1000                 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
1001         }
1002
1003         /* While this is a REF pointer, some of the functions that wrap this don't provide this */
1004         if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
1005                 /* No secrets are created at this time, for this function */
1006                 auth_struct.outgoing.count = 0;
1007                 auth_struct.incoming.count = 0;
1008         } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
1009                 auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
1010                                             r->in.auth_info_internal->auth_blob.size);
1011                 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1012                                                    &auth_blob, &auth_struct);
1013                 if (!NT_STATUS_IS_OK(nt_status)) {
1014                         return nt_status;
1015                 }
1016         } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
1017
1018                 if (unencrypted_auth_info->incoming_count > 1) {
1019                         return NT_STATUS_INVALID_PARAMETER;
1020                 }
1021
1022                 /* more investigation required here, do not create secrets for
1023                  * now */
1024                 auth_struct.outgoing.count = 0;
1025                 auth_struct.incoming.count = 0;
1026         } else {
1027                 return NT_STATUS_INVALID_PARAMETER;
1028         }
1029
1030         if (auth_struct.incoming.count) {
1031                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1032                                                      &auth_struct.incoming,
1033                                                      &trustAuthIncoming);
1034                 if (!NT_STATUS_IS_OK(nt_status)) {
1035                         return nt_status;
1036                 }
1037         } else {
1038                 trustAuthIncoming = data_blob(NULL, 0);
1039         }
1040
1041         if (auth_struct.outgoing.count) {
1042                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1043                                                      &auth_struct.outgoing,
1044                                                      &trustAuthOutgoing);
1045                 if (!NT_STATUS_IS_OK(nt_status)) {
1046                         return nt_status;
1047                 }
1048         } else {
1049                 trustAuthOutgoing = data_blob(NULL, 0);
1050         }
1051
1052         ret = ldb_transaction_start(sam_ldb);
1053         if (ret != LDB_SUCCESS) {
1054                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1055         }
1056
1057         if (dns_name) {
1058                 char *dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name);
1059                 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1060                 /* search for the trusted_domain record */
1061                 ret = gendb_search(sam_ldb,
1062                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
1063                                    "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1064                                    dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded);
1065                 if (ret > 0) {
1066                         ldb_transaction_cancel(sam_ldb);
1067                         return NT_STATUS_OBJECT_NAME_COLLISION;
1068                 }
1069         } else {
1070                 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1071                 /* search for the trusted_domain record */
1072                 ret = gendb_search(sam_ldb,
1073                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
1074                                    "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1075                                    netbios_encoded, netbios_encoded, netbios_encoded);
1076                 if (ret > 0) {
1077                         ldb_transaction_cancel(sam_ldb);
1078                         return NT_STATUS_OBJECT_NAME_COLLISION;
1079                 }
1080         }
1081
1082         if (ret < 0 ) {
1083                 ldb_transaction_cancel(sam_ldb);
1084                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1085         }
1086
1087         name = dns_name ? dns_name : netbios_name;
1088
1089         msg = ldb_msg_new(mem_ctx);
1090         if (msg == NULL) {
1091                 return NT_STATUS_NO_MEMORY;
1092         }
1093
1094         msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1095         if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
1096                         ldb_transaction_cancel(sam_ldb);
1097                 return NT_STATUS_NO_MEMORY;
1098         }
1099
1100         ldb_msg_add_string(msg, "flatname", netbios_name);
1101
1102         if (r->in.info->sid) {
1103                 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier", r->in.info->sid);
1104                 if (ret != LDB_SUCCESS) {
1105                         ldb_transaction_cancel(sam_ldb);
1106                         return NT_STATUS_INVALID_PARAMETER;
1107                 }
1108         }
1109
1110         ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1111
1112         samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1113
1114         samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1115
1116         samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1117
1118         if (dns_name) {
1119                 ldb_msg_add_string(msg, "trustPartner", dns_name);
1120         }
1121
1122         if (trustAuthIncoming.data) {
1123                 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1124                 if (ret != LDB_SUCCESS) {
1125                         ldb_transaction_cancel(sam_ldb);
1126                         return NT_STATUS_NO_MEMORY;
1127                 }
1128         }
1129         if (trustAuthOutgoing.data) {
1130                 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1131                 if (ret != LDB_SUCCESS) {
1132                         ldb_transaction_cancel(sam_ldb);
1133                         return NT_STATUS_NO_MEMORY;
1134                 }
1135         }
1136
1137         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1138
1139         /* create the trusted_domain */
1140         ret = ldb_add(sam_ldb, msg);
1141         switch (ret) {
1142         case  LDB_SUCCESS:
1143                 break;
1144         case  LDB_ERR_ENTRY_ALREADY_EXISTS:
1145                 ldb_transaction_cancel(sam_ldb);
1146                 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1147                          ldb_dn_get_linearized(msg->dn),
1148                          ldb_errstring(sam_ldb)));
1149                 return NT_STATUS_DOMAIN_EXISTS;
1150         case  LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1151                 ldb_transaction_cancel(sam_ldb);
1152                 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1153                          ldb_dn_get_linearized(msg->dn),
1154                          ldb_errstring(sam_ldb)));
1155                 return NT_STATUS_ACCESS_DENIED;
1156         default:
1157                 ldb_transaction_cancel(sam_ldb);
1158                 DEBUG(0,("Failed to create user record %s: %s\n",
1159                          ldb_dn_get_linearized(msg->dn),
1160                          ldb_errstring(sam_ldb)));
1161                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1162         }
1163
1164         if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1165                 struct ldb_dn *user_dn;
1166                 /* Inbound trusts must also create a cn=users object to match */
1167                 nt_status = add_trust_user(mem_ctx, sam_ldb,
1168                                            policy_state->domain_dn,
1169                                            netbios_name,
1170                                            &auth_struct.incoming,
1171                                            &user_dn);
1172                 if (!NT_STATUS_IS_OK(nt_status)) {
1173                         ldb_transaction_cancel(sam_ldb);
1174                         return nt_status;
1175                 }
1176
1177                 /* save the trust user dn */
1178                 trusted_domain_state->trusted_domain_user_dn
1179                         = talloc_steal(trusted_domain_state, user_dn);
1180         }
1181
1182         ret = ldb_transaction_commit(sam_ldb);
1183         if (ret != LDB_SUCCESS) {
1184                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1185         }
1186
1187         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1188         if (!handle) {
1189                 return NT_STATUS_NO_MEMORY;
1190         }
1191
1192         handle->data = talloc_steal(handle, trusted_domain_state);
1193
1194         trusted_domain_state->access_mask = r->in.access_mask;
1195         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1196
1197         *r->out.trustdom_handle = handle->wire_handle;
1198
1199         return NT_STATUS_OK;
1200 }
1201
1202 /*
1203   lsa_CreateTrustedDomainEx2
1204 */
1205 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1206                                            TALLOC_CTX *mem_ctx,
1207                                            struct lsa_CreateTrustedDomainEx2 *r)
1208 {
1209         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1210 }
1211 /*
1212   lsa_CreateTrustedDomainEx
1213 */
1214 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1215                                           TALLOC_CTX *mem_ctx,
1216                                           struct lsa_CreateTrustedDomainEx *r)
1217 {
1218         struct lsa_CreateTrustedDomainEx2 r2;
1219
1220         r2.in.policy_handle = r->in.policy_handle;
1221         r2.in.info = r->in.info;
1222         r2.out.trustdom_handle = r->out.trustdom_handle;
1223         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1224 }
1225
1226 /*
1227   lsa_CreateTrustedDomain
1228 */
1229 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1230                                         struct lsa_CreateTrustedDomain *r)
1231 {
1232         struct lsa_CreateTrustedDomainEx2 r2;
1233
1234         r2.in.policy_handle = r->in.policy_handle;
1235         r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1236         if (!r2.in.info) {
1237                 return NT_STATUS_NO_MEMORY;
1238         }
1239
1240         r2.in.info->domain_name.string = NULL;
1241         r2.in.info->netbios_name = r->in.info->name;
1242         r2.in.info->sid = r->in.info->sid;
1243         r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1244         r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1245         r2.in.info->trust_attributes = 0;
1246
1247         r2.in.access_mask = r->in.access_mask;
1248         r2.out.trustdom_handle = r->out.trustdom_handle;
1249
1250         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1251 }
1252
1253 static NTSTATUS dcesrv_lsa_OpenTrustedDomain_common(
1254                                         struct dcesrv_call_state *dce_call,
1255                                         TALLOC_CTX *tmp_mem,
1256                                         struct lsa_policy_state *policy_state,
1257                                         const char *filter,
1258                                         uint32_t access_mask,
1259                                         struct dcesrv_handle **_handle)
1260 {
1261         struct lsa_trusted_domain_state *trusted_domain_state;
1262         struct dcesrv_handle *handle;
1263         struct ldb_message **msgs;
1264         const char *attrs[] = {
1265                 "trustDirection",
1266                 "flatname",
1267                 NULL
1268         };
1269         uint32_t direction;
1270         int ret;
1271
1272         /* TODO: perform access checks */
1273
1274         /* search for the trusted_domain record */
1275         ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1276                            policy_state->system_dn,
1277                            &msgs, attrs, "%s", filter);
1278         if (ret == 0) {
1279                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1280         }
1281
1282         if (ret != 1) {
1283                 DEBUG(0,("Found %d records matching %s under %s\n", ret,
1284                          filter,
1285                          ldb_dn_get_linearized(policy_state->system_dn)));
1286                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1287         }
1288
1289         trusted_domain_state = talloc_zero(tmp_mem,
1290                                            struct lsa_trusted_domain_state);
1291         if (!trusted_domain_state) {
1292                 return NT_STATUS_NO_MEMORY;
1293         }
1294         trusted_domain_state->policy = policy_state;
1295
1296         trusted_domain_state->trusted_domain_dn =
1297                 talloc_steal(trusted_domain_state, msgs[0]->dn);
1298
1299         direction = ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0);
1300         if (direction & LSA_TRUST_DIRECTION_INBOUND) {
1301                 const char *flatname = ldb_msg_find_attr_as_string(msgs[0],
1302                                                         "flatname", NULL);
1303
1304                 /* search for the trusted_domain account */
1305                 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1306                                    policy_state->domain_dn,
1307                                    &msgs, attrs,
1308                                    "(&(samaccountname=%s$)(objectclass=user)"
1309                                    "(userAccountControl:%s:=%u))",
1310                                    flatname,
1311                                    LDB_OID_COMPARATOR_AND,
1312                                    UF_INTERDOMAIN_TRUST_ACCOUNT);
1313                 if (ret == 1) {
1314                         trusted_domain_state->trusted_domain_user_dn =
1315                                 talloc_steal(trusted_domain_state, msgs[0]->dn);
1316                 }
1317         }
1318
1319         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1320         if (!handle) {
1321                 return NT_STATUS_NO_MEMORY;
1322         }
1323
1324         handle->data = talloc_steal(handle, trusted_domain_state);
1325
1326         trusted_domain_state->access_mask = access_mask;
1327         trusted_domain_state->policy = talloc_reference(trusted_domain_state,
1328                                                         policy_state);
1329
1330         *_handle = handle;
1331
1332         return NT_STATUS_OK;
1333 }
1334
1335 /*
1336   lsa_OpenTrustedDomain
1337 */
1338 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1339                                       struct lsa_OpenTrustedDomain *r)
1340 {
1341         struct dcesrv_handle *policy_handle;
1342         struct lsa_policy_state *policy_state;
1343         struct dcesrv_handle *handle;
1344         const char *sid_string;
1345         char *filter;
1346         NTSTATUS status;
1347
1348         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1349         ZERO_STRUCTP(r->out.trustdom_handle);
1350         policy_state = policy_handle->data;
1351
1352         sid_string = dom_sid_string(mem_ctx, r->in.sid);
1353         if (!sid_string) {
1354                 return NT_STATUS_NO_MEMORY;
1355         }
1356
1357         filter = talloc_asprintf(mem_ctx,
1358                                  "(&(securityIdentifier=%s)"
1359                                  "(objectclass=trustedDomain))",
1360                                  sid_string);
1361         if (filter == NULL) {
1362                 return NT_STATUS_NO_MEMORY;
1363         }
1364
1365         status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1366                                                      policy_state,
1367                                                      filter,
1368                                                      r->in.access_mask,
1369                                                      &handle);
1370         if (!NT_STATUS_IS_OK(status)) {
1371                 return status;
1372         }
1373
1374         *r->out.trustdom_handle = handle->wire_handle;
1375
1376         return NT_STATUS_OK;
1377 }
1378
1379
1380 /*
1381   lsa_OpenTrustedDomainByName
1382 */
1383 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1384                                             TALLOC_CTX *mem_ctx,
1385                                             struct lsa_OpenTrustedDomainByName *r)
1386 {
1387         struct dcesrv_handle *policy_handle;
1388         struct lsa_policy_state *policy_state;
1389         struct dcesrv_handle *handle;
1390         char *td_name;
1391         char *filter;
1392         NTSTATUS status;
1393
1394         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1395         ZERO_STRUCTP(r->out.trustdom_handle);
1396         policy_state = policy_handle->data;
1397
1398         if (!r->in.name.string) {
1399                 return NT_STATUS_INVALID_PARAMETER;
1400         }
1401
1402         /* search for the trusted_domain record */
1403         td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1404         if (td_name == NULL) {
1405                 return NT_STATUS_NO_MEMORY;
1406         }
1407
1408         filter = talloc_asprintf(mem_ctx,
1409                            "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1410                              "(objectclass=trustedDomain))",
1411                            td_name, td_name, td_name);
1412         if (filter == NULL) {
1413                 return NT_STATUS_NO_MEMORY;
1414         }
1415
1416         status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1417                                                      policy_state,
1418                                                      filter,
1419                                                      r->in.access_mask,
1420                                                      &handle);
1421         if (!NT_STATUS_IS_OK(status)) {
1422                 return status;
1423         }
1424
1425         *r->out.trustdom_handle = handle->wire_handle;
1426
1427         return NT_STATUS_OK;
1428 }
1429
1430
1431
1432 /*
1433   lsa_SetTrustedDomainInfo
1434 */
1435 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1436                                          struct lsa_SetTrustedDomainInfo *r)
1437 {
1438         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1439 }
1440
1441
1442
1443 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1444  * otherwise at least one must be provided */
1445 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1446                         struct ldb_dn *basedn, const char *dns_domain,
1447                         const char *netbios, struct dom_sid2 *sid,
1448                         struct ldb_message ***msgs)
1449 {
1450         const char *attrs[] = { "flatname", "trustPartner",
1451                                 "securityIdentifier", "trustDirection",
1452                                 "trustType", "trustAttributes",
1453                                 "trustPosixOffset",
1454                                 "msDs-supportedEncryptionTypes",
1455                                 "msDS-TrustForestTrustInfo",
1456                                 NULL
1457         };
1458         char *dns = NULL;
1459         char *nbn = NULL;
1460         char *sidstr = NULL;
1461         char *filter;
1462         int ret;
1463
1464
1465         if (dns_domain || netbios || sid) {
1466                 filter = talloc_strdup(mem_ctx,
1467                                    "(&(objectclass=trustedDomain)(|");
1468         } else {
1469                 filter = talloc_strdup(mem_ctx,
1470                                        "(objectclass=trustedDomain)");
1471         }
1472         if (!filter) {
1473                 return NT_STATUS_NO_MEMORY;
1474         }
1475
1476         if (dns_domain) {
1477                 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1478                 if (!dns) {
1479                         return NT_STATUS_NO_MEMORY;
1480                 }
1481                 filter = talloc_asprintf_append(filter,
1482                                                 "(trustPartner=%s)", dns);
1483                 if (!filter) {
1484                         return NT_STATUS_NO_MEMORY;
1485                 }
1486         }
1487         if (netbios) {
1488                 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1489                 if (!nbn) {
1490                         return NT_STATUS_NO_MEMORY;
1491                 }
1492                 filter = talloc_asprintf_append(filter,
1493                                                 "(flatname=%s)", nbn);
1494                 if (!filter) {
1495                         return NT_STATUS_NO_MEMORY;
1496                 }
1497         }
1498         if (sid) {
1499                 sidstr = dom_sid_string(mem_ctx, sid);
1500                 if (!sidstr) {
1501                         return NT_STATUS_INVALID_PARAMETER;
1502                 }
1503                 filter = talloc_asprintf_append(filter,
1504                                                 "(securityIdentifier=%s)",
1505                                                 sidstr);
1506                 if (!filter) {
1507                         return NT_STATUS_NO_MEMORY;
1508                 }
1509         }
1510         if (dns_domain || netbios || sid) {
1511                 filter = talloc_asprintf_append(filter, "))");
1512                 if (!filter) {
1513                         return NT_STATUS_NO_MEMORY;
1514                 }
1515         }
1516
1517         ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1518         if (ret == 0) {
1519                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1520         }
1521
1522         if (ret != 1) {
1523                 return NT_STATUS_OBJECT_NAME_COLLISION;
1524         }
1525
1526         return NT_STATUS_OK;
1527 }
1528
1529 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1530                                       struct ldb_context *sam_ldb,
1531                                       struct ldb_message *orig,
1532                                       struct ldb_message *dest,
1533                                       const char *attribute,
1534                                       uint32_t value,
1535                                       uint32_t *orig_value)
1536 {
1537         const struct ldb_val *orig_val;
1538         uint32_t orig_uint = 0;
1539         unsigned int flags = 0;
1540         int ret;
1541
1542         orig_val = ldb_msg_find_ldb_val(orig, attribute);
1543         if (!orig_val || !orig_val->data) {
1544                 /* add new attribute */
1545                 flags = LDB_FLAG_MOD_ADD;
1546
1547         } else {
1548                 errno = 0;
1549                 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1550                 if (errno != 0 || orig_uint != value) {
1551                         /* replace also if can't get value */
1552                         flags = LDB_FLAG_MOD_REPLACE;
1553                 }
1554         }
1555
1556         if (flags == 0) {
1557                 /* stored value is identical, nothing to change */
1558                 goto done;
1559         }
1560
1561         ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1562         if (ret != LDB_SUCCESS) {
1563                 return NT_STATUS_NO_MEMORY;
1564         }
1565
1566         ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1567         if (ret != LDB_SUCCESS) {
1568                 return NT_STATUS_NO_MEMORY;
1569         }
1570
1571 done:
1572         if (orig_value) {
1573                 *orig_value = orig_uint;
1574         }
1575         return NT_STATUS_OK;
1576 }
1577
1578 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1579                                   struct ldb_context *sam_ldb,
1580                                   struct ldb_dn *base_dn,
1581                                   bool delete_user,
1582                                   const char *netbios_name,
1583                                   struct trustAuthInOutBlob *in)
1584 {
1585         const char *attrs[] = { "userAccountControl", NULL };
1586         struct ldb_message **msgs;
1587         struct ldb_message *msg;
1588         uint32_t uac;
1589         uint32_t i;
1590         int ret;
1591
1592         ret = gendb_search(sam_ldb, mem_ctx,
1593                            base_dn, &msgs, attrs,
1594                            "samAccountName=%s$", netbios_name);
1595         if (ret > 1) {
1596                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1597         }
1598
1599         if (ret == 0) {
1600                 if (delete_user) {
1601                         return NT_STATUS_OK;
1602                 }
1603
1604                 /* ok no existing user, add it from scratch */
1605                 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1606                                       netbios_name, in, NULL);
1607         }
1608
1609         /* check user is what we are looking for */
1610         uac = ldb_msg_find_attr_as_uint(msgs[0],
1611                                         "userAccountControl", 0);
1612         if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1613                 return NT_STATUS_OBJECT_NAME_COLLISION;
1614         }
1615
1616         if (delete_user) {
1617                 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1618                 switch (ret) {
1619                 case LDB_SUCCESS:
1620                         return NT_STATUS_OK;
1621                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1622                         return NT_STATUS_ACCESS_DENIED;
1623                 default:
1624                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1625                 }
1626         }
1627
1628         /* entry exists, just modify secret if any */
1629         if (in == NULL || in->count == 0) {
1630                 return NT_STATUS_OK;
1631         }
1632
1633         msg = ldb_msg_new(mem_ctx);
1634         if (!msg) {
1635                 return NT_STATUS_NO_MEMORY;
1636         }
1637         msg->dn = msgs[0]->dn;
1638
1639         for (i = 0; i < in->count; i++) {
1640                 const char *attribute;
1641                 struct ldb_val v;
1642                 switch (in->current.array[i].AuthType) {
1643                 case TRUST_AUTH_TYPE_NT4OWF:
1644                         attribute = "unicodePwd";
1645                         v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1646                         v.length = 16;
1647                         break;
1648                 case TRUST_AUTH_TYPE_CLEAR:
1649                         attribute = "clearTextPassword";
1650                         v.data = in->current.array[i].AuthInfo.clear.password;
1651                         v.length = in->current.array[i].AuthInfo.clear.size;
1652                         break;
1653                 default:
1654                         continue;
1655                 }
1656
1657                 ret = ldb_msg_add_empty(msg, attribute,
1658                                         LDB_FLAG_MOD_REPLACE, NULL);
1659                 if (ret != LDB_SUCCESS) {
1660                         return NT_STATUS_NO_MEMORY;
1661                 }
1662
1663                 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1664                 if (ret != LDB_SUCCESS) {
1665                         return NT_STATUS_NO_MEMORY;
1666                 }
1667         }
1668
1669         /* create the trusted_domain user account */
1670         ret = ldb_modify(sam_ldb, msg);
1671         if (ret != LDB_SUCCESS) {
1672                 DEBUG(0,("Failed to create user record %s: %s\n",
1673                          ldb_dn_get_linearized(msg->dn),
1674                          ldb_errstring(sam_ldb)));
1675
1676                 switch (ret) {
1677                 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1678                         return NT_STATUS_DOMAIN_EXISTS;
1679                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1680                         return NT_STATUS_ACCESS_DENIED;
1681                 default:
1682                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1683                 }
1684         }
1685
1686         return NT_STATUS_OK;
1687 }
1688
1689
1690 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1691                                           struct lsa_policy_state *p_state,
1692                                           TALLOC_CTX *mem_ctx,
1693                                           struct ldb_message *dom_msg,
1694                                           enum lsa_TrustDomInfoEnum level,
1695                                           union lsa_TrustedDomainInfo *info)
1696 {
1697         uint32_t *posix_offset = NULL;
1698         struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1699         struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1700         struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1701         uint32_t *enc_types = NULL;
1702         DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1703         struct trustDomainPasswords auth_struct;
1704         struct trustAuthInOutBlob *current_passwords = NULL;
1705         NTSTATUS nt_status;
1706         struct ldb_message **msgs;
1707         struct ldb_message *msg;
1708         bool add_outgoing = false;
1709         bool add_incoming = false;
1710         bool del_outgoing = false;
1711         bool del_incoming = false;
1712         bool del_forest_info = false;
1713         bool in_transaction = false;
1714         int ret;
1715         bool am_rodc;
1716
1717         switch (level) {
1718         case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1719                 posix_offset = &info->posix_offset.posix_offset;
1720                 break;
1721         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1722                 info_ex = &info->info_ex;
1723                 break;
1724         case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1725                 auth_info = &info->auth_info;
1726                 break;
1727         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1728                 posix_offset = &info->full_info.posix_offset.posix_offset;
1729                 info_ex = &info->full_info.info_ex;
1730                 auth_info = &info->full_info.auth_info;
1731                 break;
1732         case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1733                 auth_info_int = &info->auth_info_internal;
1734                 break;
1735         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1736                 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1737                 info_ex = &info->full_info_internal.info_ex;
1738                 auth_info_int = &info->full_info_internal.auth_info;
1739                 break;
1740         case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1741                 enc_types = &info->enc_types.enc_types;
1742                 break;
1743         default:
1744                 return NT_STATUS_INVALID_PARAMETER;
1745         }
1746
1747         if (auth_info) {
1748                 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1749                                                   &trustAuthIncoming,
1750                                                   &trustAuthOutgoing);
1751                 if (!NT_STATUS_IS_OK(nt_status)) {
1752                         return nt_status;
1753                 }
1754                 if (trustAuthIncoming.data) {
1755                         /* This does the decode of some of this twice, but it is easier that way */
1756                         nt_status = auth_info_2_trustauth_inout(mem_ctx,
1757                                                                 auth_info->incoming_count,
1758                                                                 auth_info->incoming_current_auth_info,
1759                                                                 NULL,
1760                                                                 &current_passwords);
1761                         if (!NT_STATUS_IS_OK(nt_status)) {
1762                                 return nt_status;
1763                         }
1764                 }
1765         }
1766
1767         /* decode auth_info_int if set */
1768         if (auth_info_int) {
1769
1770                 /* now decrypt blob */
1771                 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1772                                             auth_info_int->auth_blob.size);
1773
1774                 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1775                                                    &auth_blob, &auth_struct);
1776                 if (!NT_STATUS_IS_OK(nt_status)) {
1777                         return nt_status;
1778                 }
1779         }
1780
1781         if (info_ex) {
1782                 /* verify data matches */
1783                 if (info_ex->trust_attributes &
1784                     LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1785                         /* TODO: check what behavior level we have */
1786                        if (strcasecmp_m(p_state->domain_dns,
1787                                         p_state->forest_dns) != 0) {
1788                                 return NT_STATUS_INVALID_DOMAIN_STATE;
1789                         }
1790                 }
1791
1792                 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1793                 if (ret == LDB_SUCCESS && am_rodc) {
1794                         return NT_STATUS_NO_SUCH_DOMAIN;
1795                 }
1796
1797                 /* verify only one object matches the dns/netbios/sid
1798                  * triplet and that this is the one we already have */
1799                 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1800                                     p_state->system_dn,
1801                                     info_ex->domain_name.string,
1802                                     info_ex->netbios_name.string,
1803                                     info_ex->sid, &msgs);
1804                 if (!NT_STATUS_IS_OK(nt_status)) {
1805                         return nt_status;
1806                 }
1807                 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1808                         return NT_STATUS_OBJECT_NAME_COLLISION;
1809                 }
1810                 talloc_free(msgs);
1811         }
1812
1813         /* TODO: should we fetch previous values from the existing entry
1814          * and append them ? */
1815         if (auth_info_int && auth_struct.incoming.count) {
1816                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1817                                                      &auth_struct.incoming,
1818                                                      &trustAuthIncoming);
1819                 if (!NT_STATUS_IS_OK(nt_status)) {
1820                         return nt_status;
1821                 }
1822
1823                 current_passwords = &auth_struct.incoming;
1824
1825         } else {
1826                 trustAuthIncoming = data_blob(NULL, 0);
1827         }
1828
1829         if (auth_info_int && auth_struct.outgoing.count) {
1830                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1831                                                      &auth_struct.outgoing,
1832                                                      &trustAuthOutgoing);
1833                 if (!NT_STATUS_IS_OK(nt_status)) {
1834                         return nt_status;
1835                 }
1836         } else {
1837                 trustAuthOutgoing = data_blob(NULL, 0);
1838         }
1839
1840         msg = ldb_msg_new(mem_ctx);
1841         if (msg == NULL) {
1842                 return NT_STATUS_NO_MEMORY;
1843         }
1844         msg->dn = dom_msg->dn;
1845
1846         if (posix_offset) {
1847                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1848                                                   dom_msg, msg,
1849                                                   "trustPosixOffset",
1850                                                   *posix_offset, NULL);
1851                 if (!NT_STATUS_IS_OK(nt_status)) {
1852                         return nt_status;
1853                 }
1854         }
1855
1856         if (info_ex) {
1857                 uint32_t origattrs;
1858                 uint32_t changed_attrs;
1859                 uint32_t origdir;
1860                 int origtype;
1861
1862                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1863                                                   dom_msg, msg,
1864                                                   "trustDirection",
1865                                                   info_ex->trust_direction,
1866                                                   &origdir);
1867                 if (!NT_STATUS_IS_OK(nt_status)) {
1868                         return nt_status;
1869                 }
1870
1871                 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1872                         if (auth_info != NULL && trustAuthIncoming.length > 0) {
1873                                 add_incoming = true;
1874                         }
1875                 }
1876                 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
1877                         if (auth_info != NULL && trustAuthOutgoing.length > 0) {
1878                                 add_outgoing = true;
1879                         }
1880                 }
1881
1882                 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
1883                     !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
1884                         del_incoming = true;
1885                 }
1886                 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
1887                     !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
1888                         del_outgoing = true;
1889                 }
1890
1891                 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
1892                 if (origtype == -1 || origtype != info_ex->trust_type) {
1893                         DEBUG(1, ("Attempted to change trust type! "
1894                                   "Operation not handled\n"));
1895                         return NT_STATUS_INVALID_PARAMETER;
1896                 }
1897
1898                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1899                                                   dom_msg, msg,
1900                                                   "trustAttributes",
1901                                                   info_ex->trust_attributes,
1902                                                   &origattrs);
1903                 if (!NT_STATUS_IS_OK(nt_status)) {
1904                         return nt_status;
1905                 }
1906                 /* TODO: check forestFunctionality from ldb opaque */
1907                 /* TODO: check what is set makes sense */
1908
1909                 changed_attrs = origattrs ^ info_ex->trust_attributes;
1910                 if (changed_attrs & ~LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1911                         /*
1912                          * For now we only allow
1913                          * LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE to be changed.
1914                          *
1915                          * TODO: we may need to support more attribute changes
1916                          */
1917                         DEBUG(1, ("Attempted to change trust attributes "
1918                                   "(0x%08x != 0x%08x)! "
1919                                   "Operation not handled yet...\n",
1920                                   (unsigned)origattrs,
1921                                   (unsigned)info_ex->trust_attributes));
1922                         return NT_STATUS_INVALID_PARAMETER;
1923                 }
1924
1925                 if (!(info_ex->trust_attributes &
1926                       LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE))
1927                 {
1928                         struct ldb_message_element *orig_forest_el = NULL;
1929
1930                         orig_forest_el = ldb_msg_find_element(dom_msg,
1931                                                 "msDS-TrustForestTrustInfo");
1932                         if (orig_forest_el != NULL) {
1933                                 del_forest_info = true;
1934                         }
1935                 }
1936         }
1937
1938         if (enc_types) {
1939                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1940                                                   dom_msg, msg,
1941                                                   "msDS-SupportedEncryptionTypes",
1942                                                   *enc_types, NULL);
1943                 if (!NT_STATUS_IS_OK(nt_status)) {
1944                         return nt_status;
1945                 }
1946         }
1947
1948         if (add_incoming || del_incoming) {
1949                 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1950                                         LDB_FLAG_MOD_REPLACE, NULL);
1951                 if (ret != LDB_SUCCESS) {
1952                         return NT_STATUS_NO_MEMORY;
1953                 }
1954                 if (add_incoming) {
1955                         ret = ldb_msg_add_value(msg, "trustAuthIncoming",
1956                                                 &trustAuthIncoming, NULL);
1957                         if (ret != LDB_SUCCESS) {
1958                                 return NT_STATUS_NO_MEMORY;
1959                         }
1960                 }
1961         }
1962         if (add_outgoing || del_outgoing) {
1963                 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
1964                                         LDB_FLAG_MOD_REPLACE, NULL);
1965                 if (ret != LDB_SUCCESS) {
1966                         return NT_STATUS_NO_MEMORY;
1967                 }
1968                 if (add_outgoing) {
1969                         ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1970                                                 &trustAuthOutgoing, NULL);
1971                         if (ret != LDB_SUCCESS) {
1972                                 return NT_STATUS_NO_MEMORY;
1973                         }
1974                 }
1975         }
1976         if (del_forest_info) {
1977                 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
1978                                         LDB_FLAG_MOD_REPLACE, NULL);
1979                 if (ret != LDB_SUCCESS) {
1980                         return NT_STATUS_NO_MEMORY;
1981                 }
1982         }
1983
1984         /* start transaction */
1985         ret = ldb_transaction_start(p_state->sam_ldb);
1986         if (ret != LDB_SUCCESS) {
1987                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1988         }
1989         in_transaction = true;
1990
1991         if (msg->num_elements) {
1992                 ret = ldb_modify(p_state->sam_ldb, msg);
1993                 if (ret != LDB_SUCCESS) {
1994                         DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1995                                  ldb_dn_get_linearized(msg->dn),
1996                                  ldb_errstring(p_state->sam_ldb)));
1997                         nt_status = dsdb_ldb_err_to_ntstatus(ret);
1998                         goto done;
1999                 }
2000         }
2001
2002         if (add_incoming || del_incoming) {
2003                 const char *netbios_name;
2004
2005                 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
2006                                                            "flatname", NULL);
2007                 if (!netbios_name) {
2008                         nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
2009                         goto done;
2010                 }
2011
2012                 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
2013                 nt_status = update_trust_user(mem_ctx,
2014                                               p_state->sam_ldb,
2015                                               p_state->domain_dn,
2016                                               del_incoming,
2017                                               netbios_name,
2018                                               current_passwords);
2019                 if (!NT_STATUS_IS_OK(nt_status)) {
2020                         goto done;
2021                 }
2022         }
2023
2024         /* ok, all fine, commit transaction and return */
2025         ret = ldb_transaction_commit(p_state->sam_ldb);
2026         if (ret != LDB_SUCCESS) {
2027                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2028         }
2029         in_transaction = false;
2030
2031         nt_status = NT_STATUS_OK;
2032
2033 done:
2034         if (in_transaction) {
2035                 ldb_transaction_cancel(p_state->sam_ldb);
2036         }
2037         return nt_status;
2038 }
2039
2040 /*
2041   lsa_SetInfomrationTrustedDomain
2042 */
2043 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
2044                                 struct dcesrv_call_state *dce_call,
2045                                 TALLOC_CTX *mem_ctx,
2046                                 struct lsa_SetInformationTrustedDomain *r)
2047 {
2048         struct dcesrv_handle *h;
2049         struct lsa_trusted_domain_state *td_state;
2050         struct ldb_message **msgs;
2051         NTSTATUS nt_status;
2052
2053         DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
2054                            LSA_HANDLE_TRUSTED_DOMAIN);
2055
2056         td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2057
2058         /* get the trusted domain object */
2059         nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
2060                             td_state->trusted_domain_dn,
2061                             NULL, NULL, NULL, &msgs);
2062         if (!NT_STATUS_IS_OK(nt_status)) {
2063                 if (NT_STATUS_EQUAL(nt_status,
2064                                     NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2065                         return nt_status;
2066                 }
2067                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2068         }
2069
2070         return setInfoTrustedDomain_base(dce_call, td_state->policy, mem_ctx,
2071                                          msgs[0], r->in.level, r->in.info);
2072 }
2073
2074
2075 /*
2076   lsa_DeleteTrustedDomain
2077 */
2078 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2079                                       struct lsa_DeleteTrustedDomain *r)
2080 {
2081         NTSTATUS status;
2082         struct lsa_OpenTrustedDomain opn;
2083         struct lsa_DeleteObject del;
2084         struct dcesrv_handle *h;
2085
2086         opn.in.handle = r->in.handle;
2087         opn.in.sid = r->in.dom_sid;
2088         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2089         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2090         if (!opn.out.trustdom_handle) {
2091                 return NT_STATUS_NO_MEMORY;
2092         }
2093         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2094         if (!NT_STATUS_IS_OK(status)) {
2095                 return status;
2096         }
2097
2098         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2099         talloc_steal(mem_ctx, h);
2100
2101         del.in.handle = opn.out.trustdom_handle;
2102         del.out.handle = opn.out.trustdom_handle;
2103         status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
2104         if (!NT_STATUS_IS_OK(status)) {
2105                 return status;
2106         }
2107         return NT_STATUS_OK;
2108 }
2109
2110 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
2111                                      struct ldb_message *msg,
2112                                      struct lsa_TrustDomainInfoInfoEx *info_ex)
2113 {
2114         info_ex->domain_name.string
2115                 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2116         info_ex->netbios_name.string
2117                 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2118         info_ex->sid
2119                 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2120         info_ex->trust_direction
2121                 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2122         info_ex->trust_type
2123                 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2124         info_ex->trust_attributes
2125                 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
2126         return NT_STATUS_OK;
2127 }
2128
2129 /*
2130   lsa_QueryTrustedDomainInfo
2131 */
2132 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2133                                            struct lsa_QueryTrustedDomainInfo *r)
2134 {
2135         union lsa_TrustedDomainInfo *info = NULL;
2136         struct dcesrv_handle *h;
2137         struct lsa_trusted_domain_state *trusted_domain_state;
2138         struct ldb_message *msg;
2139         int ret;
2140         struct ldb_message **res;
2141         const char *attrs[] = {
2142                 "flatname",
2143                 "trustPartner",
2144                 "securityIdentifier",
2145                 "trustDirection",
2146                 "trustType",
2147                 "trustAttributes",
2148                 "msDs-supportedEncryptionTypes",
2149                 NULL
2150         };
2151
2152         DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2153
2154         trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2155
2156         /* pull all the user attributes */
2157         ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2158                               trusted_domain_state->trusted_domain_dn, &res, attrs);
2159         if (ret != 1) {
2160                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2161         }
2162         msg = res[0];
2163
2164         info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2165         if (!info) {
2166                 return NT_STATUS_NO_MEMORY;
2167         }
2168         *r->out.info = info;
2169
2170         switch (r->in.level) {
2171         case LSA_TRUSTED_DOMAIN_INFO_NAME:
2172                 info->name.netbios_name.string
2173                         = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2174                 break;
2175         case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2176                 info->posix_offset.posix_offset
2177                         = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2178                 break;
2179 #if 0  /* Win2k3 doesn't implement this */
2180         case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2181                 r->out.info->info_basic.netbios_name.string
2182                         = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2183                 r->out.info->info_basic.sid
2184                         = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2185                 break;
2186 #endif
2187         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2188                 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2189
2190         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2191                 ZERO_STRUCT(info->full_info);
2192                 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2193         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2194                 ZERO_STRUCT(info->full_info2_internal);
2195                 info->full_info2_internal.posix_offset.posix_offset
2196                         = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2197                 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2198
2199         case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2200                 info->enc_types.enc_types
2201                         = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2202                 break;
2203
2204         case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2205         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2206                 /* oops, we don't want to return the info after all */
2207                 talloc_free(info);
2208                 *r->out.info = NULL;
2209                 return NT_STATUS_INVALID_PARAMETER;
2210         default:
2211                 /* oops, we don't want to return the info after all */
2212                 talloc_free(info);
2213                 *r->out.info = NULL;
2214                 return NT_STATUS_INVALID_INFO_CLASS;
2215         }
2216
2217         return NT_STATUS_OK;
2218 }
2219
2220
2221 /*
2222   lsa_QueryTrustedDomainInfoBySid
2223 */
2224 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2225                                                 struct lsa_QueryTrustedDomainInfoBySid *r)
2226 {
2227         NTSTATUS status;
2228         struct lsa_OpenTrustedDomain opn;
2229         struct lsa_QueryTrustedDomainInfo query;
2230         struct dcesrv_handle *h;
2231
2232         opn.in.handle = r->in.handle;
2233         opn.in.sid = r->in.dom_sid;
2234         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2235         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2236         if (!opn.out.trustdom_handle) {
2237                 return NT_STATUS_NO_MEMORY;
2238         }
2239         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2240         if (!NT_STATUS_IS_OK(status)) {
2241                 return status;
2242         }
2243
2244         /* Ensure this handle goes away at the end of this call */
2245         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2246         talloc_steal(mem_ctx, h);
2247
2248         query.in.trustdom_handle = opn.out.trustdom_handle;
2249         query.in.level = r->in.level;
2250         query.out.info = r->out.info;
2251         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2252         if (!NT_STATUS_IS_OK(status)) {
2253                 return status;
2254         }
2255
2256         return NT_STATUS_OK;
2257 }
2258
2259 /*
2260   lsa_SetTrustedDomainInfoByName
2261 */
2262 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2263                                                TALLOC_CTX *mem_ctx,
2264                                                struct lsa_SetTrustedDomainInfoByName *r)
2265 {
2266         struct dcesrv_handle *policy_handle;
2267         struct lsa_policy_state *policy_state;
2268         struct ldb_message **msgs;
2269         NTSTATUS nt_status;
2270
2271         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2272         policy_state = policy_handle->data;
2273
2274         /* get the trusted domain object */
2275         nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2276                             policy_state->domain_dn,
2277                             r->in.trusted_domain->string,
2278                             r->in.trusted_domain->string,
2279                             NULL, &msgs);
2280         if (!NT_STATUS_IS_OK(nt_status)) {
2281                 if (NT_STATUS_EQUAL(nt_status,
2282                                     NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2283                         return nt_status;
2284                 }
2285                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2286         }
2287
2288         return setInfoTrustedDomain_base(dce_call, policy_state, mem_ctx,
2289                                          msgs[0], r->in.level, r->in.info);
2290 }
2291
2292 /*
2293    lsa_QueryTrustedDomainInfoByName
2294 */
2295 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2296                                                  TALLOC_CTX *mem_ctx,
2297                                                  struct lsa_QueryTrustedDomainInfoByName *r)
2298 {
2299         NTSTATUS status;
2300         struct lsa_OpenTrustedDomainByName opn;
2301         struct lsa_QueryTrustedDomainInfo query;
2302         struct dcesrv_handle *h;
2303
2304         opn.in.handle = r->in.handle;
2305         opn.in.name = *r->in.trusted_domain;
2306         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2307         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2308         if (!opn.out.trustdom_handle) {
2309                 return NT_STATUS_NO_MEMORY;
2310         }
2311         status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2312         if (!NT_STATUS_IS_OK(status)) {
2313                 return status;
2314         }
2315
2316         /* Ensure this handle goes away at the end of this call */
2317         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2318         talloc_steal(mem_ctx, h);
2319
2320         query.in.trustdom_handle = opn.out.trustdom_handle;
2321         query.in.level = r->in.level;
2322         query.out.info = r->out.info;
2323         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2324         if (!NT_STATUS_IS_OK(status)) {
2325                 return status;
2326         }
2327
2328         return NT_STATUS_OK;
2329 }
2330
2331 /*
2332   lsa_CloseTrustedDomainEx
2333 */
2334 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2335                                          TALLOC_CTX *mem_ctx,
2336                                          struct lsa_CloseTrustedDomainEx *r)
2337 {
2338         /* The result of a bad hair day from an IDL programmer?  Not
2339          * implmented in Win2k3.  You should always just lsa_Close
2340          * anyway. */
2341         return NT_STATUS_NOT_IMPLEMENTED;
2342 }
2343
2344
2345 /*
2346   comparison function for sorting lsa_DomainInformation array
2347 */
2348 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2349 {
2350         return strcasecmp_m(e1->name.string, e2->name.string);
2351 }
2352
2353 /*
2354   lsa_EnumTrustDom
2355 */
2356 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2357                                  struct lsa_EnumTrustDom *r)
2358 {
2359         struct dcesrv_handle *policy_handle;
2360         struct lsa_DomainInfo *entries;
2361         struct lsa_policy_state *policy_state;
2362         struct ldb_message **domains;
2363         const char *attrs[] = {
2364                 "flatname",
2365                 "securityIdentifier",
2366                 NULL
2367         };
2368
2369
2370         int count, i;
2371
2372         *r->out.resume_handle = 0;
2373
2374         r->out.domains->domains = NULL;
2375         r->out.domains->count = 0;
2376
2377         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2378
2379         policy_state = policy_handle->data;
2380
2381         /* search for all users in this domain. This could possibly be cached and
2382            resumed based on resume_key */
2383         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2384                              "objectclass=trustedDomain");
2385         if (count < 0) {
2386                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2387         }
2388
2389         /* convert to lsa_TrustInformation format */
2390         entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2391         if (!entries) {
2392                 return NT_STATUS_NO_MEMORY;
2393         }
2394         for (i=0;i<count;i++) {
2395                 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2396                 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2397         }
2398
2399         /* sort the results by name */
2400         TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2401
2402         if (*r->in.resume_handle >= count) {
2403                 *r->out.resume_handle = -1;
2404
2405                 return NT_STATUS_NO_MORE_ENTRIES;
2406         }
2407
2408         /* return the rest, limit by max_size. Note that we
2409            use the w2k3 element size value of 60 */
2410         r->out.domains->count = count - *r->in.resume_handle;
2411         r->out.domains->count = MIN(r->out.domains->count,
2412                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2413
2414         r->out.domains->domains = entries + *r->in.resume_handle;
2415         r->out.domains->count = r->out.domains->count;
2416
2417         if (r->out.domains->count < count - *r->in.resume_handle) {
2418                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2419                 return STATUS_MORE_ENTRIES;
2420         }
2421
2422         /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2423          * always be larger than the previous input resume handle, in
2424          * particular when hitting the last query it is vital to set the
2425          * resume handle correctly to avoid infinite client loops, as
2426          * seen e.g. with Windows XP SP3 when resume handle is 0 and
2427          * status is NT_STATUS_OK - gd */
2428
2429         *r->out.resume_handle = (uint32_t)-1;
2430
2431         return NT_STATUS_OK;
2432 }
2433
2434 /*
2435   comparison function for sorting lsa_DomainInformation array
2436 */
2437 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2438 {
2439         return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2440 }
2441
2442 /*
2443   lsa_EnumTrustedDomainsEx
2444 */
2445 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2446                                         struct lsa_EnumTrustedDomainsEx *r)
2447 {
2448         struct dcesrv_handle *policy_handle;
2449         struct lsa_TrustDomainInfoInfoEx *entries;
2450         struct lsa_policy_state *policy_state;
2451         struct ldb_message **domains;
2452         const char *attrs[] = {
2453                 "flatname",
2454                 "trustPartner",
2455                 "securityIdentifier",
2456                 "trustDirection",
2457                 "trustType",
2458                 "trustAttributes",
2459                 NULL
2460         };
2461         NTSTATUS nt_status;
2462
2463         int count, i;
2464
2465         *r->out.resume_handle = 0;
2466
2467         r->out.domains->domains = NULL;
2468         r->out.domains->count = 0;
2469
2470         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2471
2472         policy_state = policy_handle->data;
2473
2474         /* search for all users in this domain. This could possibly be cached and
2475            resumed based on resume_key */
2476         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2477                              "objectclass=trustedDomain");
2478         if (count < 0) {
2479                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2480         }
2481
2482         /* convert to lsa_DomainInformation format */
2483         entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2484         if (!entries) {
2485                 return NT_STATUS_NO_MEMORY;
2486         }
2487         for (i=0;i<count;i++) {
2488                 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2489                 if (!NT_STATUS_IS_OK(nt_status)) {
2490                         return nt_status;
2491                 }
2492         }
2493
2494         /* sort the results by name */
2495         TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2496
2497         if (*r->in.resume_handle >= count) {
2498                 *r->out.resume_handle = -1;
2499
2500                 return NT_STATUS_NO_MORE_ENTRIES;
2501         }
2502
2503         /* return the rest, limit by max_size. Note that we
2504            use the w2k3 element size value of 60 */
2505         r->out.domains->count = count - *r->in.resume_handle;
2506         r->out.domains->count = MIN(r->out.domains->count,
2507                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2508
2509         r->out.domains->domains = entries + *r->in.resume_handle;
2510         r->out.domains->count = r->out.domains->count;
2511
2512         if (r->out.domains->count < count - *r->in.resume_handle) {
2513                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2514                 return STATUS_MORE_ENTRIES;
2515         }
2516
2517         *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2518
2519         return NT_STATUS_OK;
2520 }
2521
2522
2523 /*
2524   lsa_OpenAccount
2525 */
2526 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2527                                 struct lsa_OpenAccount *r)
2528 {
2529         struct dcesrv_handle *h, *ah;
2530         struct lsa_policy_state *state;
2531         struct lsa_account_state *astate;
2532
2533         ZERO_STRUCTP(r->out.acct_handle);
2534
2535         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2536
2537         state = h->data;
2538
2539         astate = talloc(dce_call->conn, struct lsa_account_state);
2540         if (astate == NULL) {
2541                 return NT_STATUS_NO_MEMORY;
2542         }
2543
2544         astate->account_sid = dom_sid_dup(astate, r->in.sid);
2545         if (astate->account_sid == NULL) {
2546                 talloc_free(astate);
2547                 return NT_STATUS_NO_MEMORY;
2548         }
2549
2550         astate->policy = talloc_reference(astate, state);
2551         astate->access_mask = r->in.access_mask;
2552
2553         /*
2554          * For now we grant all requested access.
2555          *
2556          * We will fail at the ldb layer later.
2557          */
2558         if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
2559                 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
2560                 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
2561         }
2562         se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
2563
2564         DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X] - success.\n",
2565                   __func__, dom_sid_string(mem_ctx, astate->account_sid),
2566                  (unsigned)r->in.access_mask,
2567                  (unsigned)astate->access_mask));
2568
2569         ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2570         if (!ah) {
2571                 talloc_free(astate);
2572                 return NT_STATUS_NO_MEMORY;
2573         }
2574
2575         ah->data = talloc_steal(ah, astate);
2576
2577         *r->out.acct_handle = ah->wire_handle;
2578
2579         return NT_STATUS_OK;
2580 }
2581
2582
2583 /*
2584   lsa_EnumPrivsAccount
2585 */
2586 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2587                                      TALLOC_CTX *mem_ctx,
2588                                      struct lsa_EnumPrivsAccount *r)
2589 {
2590         struct dcesrv_handle *h;
2591         struct lsa_account_state *astate;
2592         int ret;
2593         unsigned int i, j;
2594         struct ldb_message **res;
2595         const char * const attrs[] = { "privilege", NULL};
2596         struct ldb_message_element *el;
2597         const char *sidstr;
2598         struct lsa_PrivilegeSet *privs;
2599
2600         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2601
2602         astate = h->data;
2603
2604         privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2605         if (privs == NULL) {
2606                 return NT_STATUS_NO_MEMORY;
2607         }
2608         privs->count = 0;
2609         privs->unknown = 0;
2610         privs->set = NULL;
2611
2612         *r->out.privs = privs;
2613
2614         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2615         if (sidstr == NULL) {
2616                 return NT_STATUS_NO_MEMORY;
2617         }
2618
2619         ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2620                            "objectSid=%s", sidstr);
2621         if (ret < 0) {
2622                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2623         }
2624         if (ret != 1) {
2625                 return NT_STATUS_OK;
2626         }
2627
2628         el = ldb_msg_find_element(res[0], "privilege");
2629         if (el == NULL || el->num_values == 0) {
2630                 return NT_STATUS_OK;
2631         }
2632
2633         privs->set = talloc_array(privs,
2634                                   struct lsa_LUIDAttribute, el->num_values);
2635         if (privs->set == NULL) {
2636                 return NT_STATUS_NO_MEMORY;
2637         }
2638
2639         j = 0;
2640         for (i=0;i<el->num_values;i++) {
2641                 int id = sec_privilege_id((const char *)el->values[i].data);
2642                 if (id == SEC_PRIV_INVALID) {
2643                         /* Perhaps an account right, not a privilege */
2644                         continue;
2645                 }
2646                 privs->set[j].attribute = 0;
2647                 privs->set[j].luid.low = id;
2648                 privs->set[j].luid.high = 0;
2649                 j++;
2650         }
2651
2652         privs->count = j;
2653
2654         return NT_STATUS_OK;
2655 }
2656
2657 /*
2658   lsa_EnumAccountRights
2659 */
2660 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2661                                       TALLOC_CTX *mem_ctx,
2662                                       struct lsa_EnumAccountRights *r)
2663 {
2664         struct dcesrv_handle *h;
2665         struct lsa_policy_state *state;
2666         int ret;
2667         unsigned int i;
2668         struct ldb_message **res;
2669         const char * const attrs[] = { "privilege", NULL};
2670         const char *sidstr;
2671         struct ldb_message_element *el;
2672
2673         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2674
2675         state = h->data;
2676
2677         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2678         if (sidstr == NULL) {
2679                 return NT_STATUS_NO_MEMORY;
2680         }
2681
2682         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2683                            "(&(objectSid=%s)(privilege=*))", sidstr);
2684         if (ret == 0) {
2685                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2686         }
2687         if (ret != 1) {
2688                 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2689                           dom_sid_string(mem_ctx, r->in.sid),
2690                           ldb_errstring(state->pdb)));
2691                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2692         }
2693
2694         el = ldb_msg_find_element(res[0], "privilege");
2695         if (el == NULL || el->num_values == 0) {
2696                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2697         }
2698
2699         r->out.rights->count = el->num_values;
2700         r->out.rights->names = talloc_array(r->out.rights,
2701                                             struct lsa_StringLarge, r->out.rights->count);
2702         if (r->out.rights->names == NULL) {
2703                 return NT_STATUS_NO_MEMORY;
2704         }
2705
2706         for (i=0;i<el->num_values;i++) {
2707                 r->out.rights->names[i].string = (const char *)el->values[i].data;
2708         }
2709
2710         return NT_STATUS_OK;
2711 }
2712
2713
2714
2715 /*
2716   helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2717 */
2718 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2719                                            TALLOC_CTX *mem_ctx,
2720                                            struct lsa_policy_state *state,
2721                                            int ldb_flag,
2722                                            struct dom_sid *sid,
2723                                            const struct lsa_RightSet *rights)
2724 {
2725         const char *sidstr, *sidndrstr;
2726         struct ldb_message *msg;
2727         struct ldb_message_element *el;
2728         int ret;
2729         uint32_t i;
2730         struct lsa_EnumAccountRights r2;
2731         char *dnstr;
2732
2733         if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2734             SECURITY_ADMINISTRATOR) {
2735                 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2736                 return NT_STATUS_ACCESS_DENIED;
2737         }
2738
2739         msg = ldb_msg_new(mem_ctx);
2740         if (msg == NULL) {
2741                 return NT_STATUS_NO_MEMORY;
2742         }
2743
2744         sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2745         if (sidndrstr == NULL) {
2746                 TALLOC_FREE(msg);
2747                 return NT_STATUS_NO_MEMORY;
2748         }
2749
2750         sidstr = dom_sid_string(msg, sid);
2751         if (sidstr == NULL) {
2752                 TALLOC_FREE(msg);
2753                 return NT_STATUS_NO_MEMORY;
2754         }
2755
2756         dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2757         if (dnstr == NULL) {
2758                 TALLOC_FREE(msg);
2759                 return NT_STATUS_NO_MEMORY;
2760         }
2761
2762         msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2763         if (msg->dn == NULL) {
2764                 TALLOC_FREE(msg);
2765                 return NT_STATUS_NO_MEMORY;
2766         }
2767
2768         if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2769                 NTSTATUS status;
2770
2771                 r2.in.handle = &state->handle->wire_handle;
2772                 r2.in.sid = sid;
2773                 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2774
2775                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2776                 if (!NT_STATUS_IS_OK(status)) {
2777                         ZERO_STRUCTP(r2.out.rights);
2778                 }
2779         }
2780
2781         for (i=0;i<rights->count;i++) {
2782                 if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
2783                         if (sec_right_bit(rights->names[i].string) == 0) {
2784                                 talloc_free(msg);
2785                                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2786                         }
2787
2788                         talloc_free(msg);
2789                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2790                 }
2791
2792                 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2793                         uint32_t j;
2794                         for (j=0;j<r2.out.rights->count;j++) {
2795                                 if (strcasecmp_m(r2.out.rights->names[j].string,
2796                                                rights->names[i].string) == 0) {
2797                                         break;
2798                                 }
2799                         }
2800                         if (j != r2.out.rights->count) continue;
2801                 }
2802
2803                 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2804                 if (ret != LDB_SUCCESS) {
2805                         talloc_free(msg);
2806                         return NT_STATUS_NO_MEMORY;
2807                 }
2808         }
2809
2810         el = ldb_msg_find_element(msg, "privilege");
2811         if (!el) {
2812                 talloc_free(msg);
2813                 return NT_STATUS_OK;
2814         }
2815
2816         el->flags = ldb_flag;
2817
2818         ret = ldb_modify(state->pdb, msg);
2819         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2820                 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2821                         talloc_free(msg);
2822                         return NT_STATUS_NO_MEMORY;
2823                 }
2824                 ldb_msg_add_string(msg, "comment", "added via LSA");
2825                 ret = ldb_add(state->pdb, msg);
2826         }
2827         if (ret != LDB_SUCCESS) {
2828                 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2829                         talloc_free(msg);
2830                         return NT_STATUS_OK;
2831                 }
2832                 DEBUG(3, ("Could not %s attributes from %s: %s",
2833                           LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2834                           ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2835                 talloc_free(msg);
2836                 return NT_STATUS_UNEXPECTED_IO_ERROR;
2837         }
2838
2839         talloc_free(msg);
2840         return NT_STATUS_OK;
2841 }
2842
2843 /*
2844   lsa_AddPrivilegesToAccount
2845 */
2846 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2847                                            struct lsa_AddPrivilegesToAccount *r)
2848 {
2849         struct lsa_RightSet rights;
2850         struct dcesrv_handle *h;
2851         struct lsa_account_state *astate;
2852         uint32_t i;
2853
2854         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2855
2856         astate = h->data;
2857
2858         rights.count = r->in.privs->count;
2859         rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2860         if (rights.names == NULL) {
2861                 return NT_STATUS_NO_MEMORY;
2862         }
2863         for (i=0;i<rights.count;i++) {
2864                 int id = r->in.privs->set[i].luid.low;
2865                 if (r->in.privs->set[i].luid.high) {
2866                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2867                 }
2868                 rights.names[i].string = sec_privilege_name(id);
2869                 if (rights.names[i].string == NULL) {
2870                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2871                 }
2872         }
2873
2874         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2875                                           LDB_FLAG_MOD_ADD, astate->account_sid,
2876                                           &rights);
2877 }
2878
2879
2880 /*
2881   lsa_RemovePrivilegesFromAccount
2882 */
2883 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2884                                                 struct lsa_RemovePrivilegesFromAccount *r)
2885 {
2886         struct lsa_RightSet *rights;
2887         struct dcesrv_handle *h;
2888         struct lsa_account_state *astate;
2889         uint32_t i;
2890
2891         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2892
2893         astate = h->data;
2894
2895         rights = talloc(mem_ctx, struct lsa_RightSet);
2896
2897         if (r->in.remove_all == 1 &&
2898             r->in.privs == NULL) {
2899                 struct lsa_EnumAccountRights r2;
2900                 NTSTATUS status;
2901
2902                 r2.in.handle = &astate->policy->handle->wire_handle;
2903                 r2.in.sid = astate->account_sid;
2904                 r2.out.rights = rights;
2905
2906                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2907                 if (!NT_STATUS_IS_OK(status)) {
2908                         return status;
2909                 }
2910
2911                 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2912                                                   LDB_FLAG_MOD_DELETE, astate->account_sid,
2913                                                   r2.out.rights);
2914         }
2915
2916         if (r->in.remove_all != 0) {
2917                 return NT_STATUS_INVALID_PARAMETER;
2918         }
2919
2920         rights->count = r->in.privs->count;
2921         rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2922         if (rights->names == NULL) {
2923                 return NT_STATUS_NO_MEMORY;
2924         }
2925         for (i=0;i<rights->count;i++) {
2926                 int id = r->in.privs->set[i].luid.low;
2927                 if (r->in.privs->set[i].luid.high) {
2928                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2929                 }
2930                 rights->names[i].string = sec_privilege_name(id);
2931                 if (rights->names[i].string == NULL) {
2932                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2933                 }
2934         }
2935
2936         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2937                                           LDB_FLAG_MOD_DELETE, astate->account_sid,
2938                                           rights);
2939 }
2940
2941
2942 /*
2943   lsa_GetQuotasForAccount
2944 */
2945 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2946                        struct lsa_GetQuotasForAccount *r)
2947 {
2948         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2949 }
2950
2951
2952 /*
2953   lsa_SetQuotasForAccount
2954 */
2955 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2956                        struct lsa_SetQuotasForAccount *r)
2957 {
2958         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2959 }
2960
2961
2962 /*
2963   lsa_GetSystemAccessAccount
2964 */
2965 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2966                        struct lsa_GetSystemAccessAccount *r)
2967 {
2968         struct dcesrv_handle *h;
2969         struct lsa_account_state *astate;
2970         int ret;
2971         unsigned int i;
2972         struct ldb_message **res;
2973         const char * const attrs[] = { "privilege", NULL};
2974         struct ldb_message_element *el;
2975         const char *sidstr;
2976
2977         *(r->out.access_mask) = 0x00000000;
2978
297