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