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