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