575bf845539d51ed60d8815138d601a3262109f7
[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/util/tsort.h"
31 #include "dsdb/common/util.h"
32 #include "libcli/security/session.h"
33 #include "libcli/lsarpc/util_lsarpc.h"
34 #include "lib/messaging/irpc.h"
35 #include "libds/common/roles.h"
36 #include "lib/util/smb_strtox.h"
37 #include "lib/param/loadparm.h"
38 #include "librpc/rpc/dcerpc_helper.h"
39
40 #include "lib/crypto/gnutls_helpers.h"
41 #include <gnutls/gnutls.h>
42 #include <gnutls/crypto.h>
43
44 #undef strcasecmp
45
46 #define DCESRV_INTERFACE_LSARPC_BIND(context, iface) \
47        dcesrv_interface_lsarpc_bind(context, iface)
48 static NTSTATUS dcesrv_interface_lsarpc_bind(struct dcesrv_connection_context *context,
49                                              const struct dcesrv_interface *iface)
50 {
51         return dcesrv_interface_bind_reject_connect(context, iface);
52 }
53
54 static NTSTATUS lsarpc__op_init_server(struct dcesrv_context *dce_ctx,
55                                        const struct dcesrv_endpoint_server *ep_server);
56 static const struct dcesrv_interface dcesrv_lsarpc_interface;
57
58 #define NCACN_NP_PIPE_NETLOGON "ncacn_np:[\\pipe\\netlogon]"
59 #define NCACN_NP_PIPE_LSASS "ncacn_np:[\\pipe\\lsass]"
60 #define DCESRV_INTERFACE_LSARPC_NCACN_NP_SECONDARY_ENDPOINT NCACN_NP_PIPE_LSASS
61
62 #define DCESRV_INTERFACE_LSARPC_INIT_SERVER     \
63        dcesrv_interface_lsarpc_init_server
64 static NTSTATUS dcesrv_interface_lsarpc_init_server(struct dcesrv_context *dce_ctx,
65                                                     const struct dcesrv_endpoint_server *ep_server)
66 {
67         if (lpcfg_lsa_over_netlogon(dce_ctx->lp_ctx)) {
68                 NTSTATUS ret = dcesrv_interface_register(dce_ctx,
69                                                 NCACN_NP_PIPE_NETLOGON,
70                                                 NCACN_NP_PIPE_LSASS,
71                                                 &dcesrv_lsarpc_interface, NULL);
72                 if (!NT_STATUS_IS_OK(ret)) {
73                         DEBUG(1,("lsarpc_op_init_server: failed to register endpoint '\\pipe\\netlogon'\n"));
74                         return ret;
75                 }
76         }
77         return lsarpc__op_init_server(dce_ctx, ep_server);
78 }
79
80 /*
81   this type allows us to distinguish handle types
82 */
83
84 /*
85   state associated with a lsa_OpenAccount() operation
86 */
87 struct lsa_account_state {
88         struct lsa_policy_state *policy;
89         uint32_t access_mask;
90         struct dom_sid *account_sid;
91 };
92
93
94 /*
95   state associated with a lsa_OpenSecret() operation
96 */
97 struct lsa_secret_state {
98         struct lsa_policy_state *policy;
99         uint32_t access_mask;
100         struct ldb_dn *secret_dn;
101         struct ldb_context *sam_ldb;
102         bool global;
103 };
104
105 /*
106   state associated with a lsa_OpenTrustedDomain() operation
107 */
108 struct lsa_trusted_domain_state {
109         struct lsa_policy_state *policy;
110         uint32_t access_mask;
111         struct ldb_dn *trusted_domain_dn;
112         struct ldb_dn *trusted_domain_user_dn;
113 };
114
115 static bool dcesrc_lsa_valid_AccountRight(const char *right)
116 {
117         enum sec_privilege priv_id;
118         uint32_t right_bit;
119
120         priv_id = sec_privilege_id(right);
121         if (priv_id != SEC_PRIV_INVALID) {
122                 return true;
123         }
124
125         right_bit = sec_right_bit(right);
126         if (right_bit != 0) {
127                 return true;
128         }
129
130         return false;
131 }
132
133 /*
134   this is based on the samba3 function make_lsa_object_sd()
135   It uses the same logic, but with samba4 helper functions
136  */
137 static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx,
138                                     struct security_descriptor **sd,
139                                     struct dom_sid *sid,
140                                     uint32_t sid_access)
141 {
142         NTSTATUS status;
143         uint32_t rid;
144         struct dom_sid *domain_sid, *domain_admins_sid;
145         const char *domain_admins_sid_str, *sidstr;
146         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
147
148         status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
149         if (!NT_STATUS_IS_OK(status)) {
150                 TALLOC_FREE(tmp_ctx);
151                 return status;
152         }
153
154         domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
155         if (domain_admins_sid == NULL) {
156                 TALLOC_FREE(tmp_ctx);
157                 return NT_STATUS_NO_MEMORY;
158         }
159
160         domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
161         if (domain_admins_sid_str == NULL) {
162                 TALLOC_FREE(tmp_ctx);
163                 return NT_STATUS_NO_MEMORY;
164         }
165
166         sidstr = dom_sid_string(tmp_ctx, sid);
167         if (sidstr == NULL) {
168                 TALLOC_FREE(tmp_ctx);
169                 return NT_STATUS_NO_MEMORY;
170         }
171
172         *sd = security_descriptor_dacl_create(mem_ctx,
173                                               0, sidstr, NULL,
174
175                                               SID_WORLD,
176                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
177                                               SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
178
179                                               SID_BUILTIN_ADMINISTRATORS,
180                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
181                                               SEC_GENERIC_ALL, 0,
182
183                                               SID_BUILTIN_ACCOUNT_OPERATORS,
184                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
185                                               SEC_GENERIC_ALL, 0,
186
187                                               domain_admins_sid_str,
188                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
189                                               SEC_GENERIC_ALL, 0,
190
191                                               sidstr,
192                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
193                                               sid_access, 0,
194
195                                               NULL);
196         talloc_free(tmp_ctx);
197
198         NT_STATUS_HAVE_NO_MEMORY(*sd);
199
200         return NT_STATUS_OK;
201 }
202
203
204 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
205                                       TALLOC_CTX *mem_ctx,
206                                       struct lsa_EnumAccountRights *r);
207
208 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
209                                            TALLOC_CTX *mem_ctx,
210                                            struct lsa_policy_state *state,
211                                            int ldb_flag,
212                                            struct dom_sid *sid,
213                                            const struct lsa_RightSet *rights);
214
215 /*
216   lsa_Close
217 */
218 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
219                           struct lsa_Close *r)
220 {
221         enum dcerpc_transport_t transport =
222                 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
223         struct dcesrv_handle *h;
224
225         if (transport != NCACN_NP && transport != NCALRPC) {
226                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
227         }
228
229         *r->out.handle = *r->in.handle;
230
231         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
232
233         talloc_free(h);
234
235         ZERO_STRUCTP(r->out.handle);
236
237         return NT_STATUS_OK;
238 }
239
240
241 /*
242   lsa_Delete
243 */
244 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
245                            struct lsa_Delete *r)
246 {
247         return NT_STATUS_NOT_SUPPORTED;
248 }
249
250
251 /*
252   lsa_DeleteObject
253 */
254 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
255                        struct lsa_DeleteObject *r)
256 {
257         struct auth_session_info *session_info =
258                 dcesrv_call_session_info(dce_call);
259         struct dcesrv_handle *h;
260         int ret;
261
262         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
263
264         if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
265                 struct lsa_secret_state *secret_state = h->data;
266
267                 /* Ensure user is permitted to delete this... */
268                 switch (security_session_user_level(session_info, NULL))
269                 {
270                 case SECURITY_SYSTEM:
271                 case SECURITY_ADMINISTRATOR:
272                         break;
273                 default:
274                         /* Users and anonymous are not allowed to delete things */
275                         return NT_STATUS_ACCESS_DENIED;
276                 }
277
278                 ret = ldb_delete(secret_state->sam_ldb,
279                                  secret_state->secret_dn);
280                 if (ret != LDB_SUCCESS) {
281                         return NT_STATUS_INVALID_HANDLE;
282                 }
283
284                 ZERO_STRUCTP(r->out.handle);
285
286                 return NT_STATUS_OK;
287
288         } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
289                 struct lsa_trusted_domain_state *trusted_domain_state =
290                         talloc_get_type(h->data, struct lsa_trusted_domain_state);
291                 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
292                 if (ret != LDB_SUCCESS) {
293                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
294                 }
295
296                 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
297                                  trusted_domain_state->trusted_domain_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                 if (trusted_domain_state->trusted_domain_user_dn) {
304                         ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
305                                          trusted_domain_state->trusted_domain_user_dn);
306                         if (ret != LDB_SUCCESS) {
307                                 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
308                                 return NT_STATUS_INVALID_HANDLE;
309                         }
310                 }
311
312                 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
313                 if (ret != LDB_SUCCESS) {
314                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
315                 }
316
317                 ZERO_STRUCTP(r->out.handle);
318
319                 return NT_STATUS_OK;
320
321         } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
322                 struct lsa_RightSet *rights;
323                 struct lsa_account_state *astate;
324                 struct lsa_EnumAccountRights r2;
325                 NTSTATUS status;
326
327                 rights = talloc(mem_ctx, struct lsa_RightSet);
328
329                 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
330
331                 astate = h->data;
332
333                 r2.in.handle = &astate->policy->handle->wire_handle;
334                 r2.in.sid = astate->account_sid;
335                 r2.out.rights = rights;
336
337                 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
338                    but we have a LSA_HANDLE_ACCOUNT here, so this call
339                    will always fail */
340                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
341                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
342                         return NT_STATUS_OK;
343                 }
344
345                 if (!NT_STATUS_IS_OK(status)) {
346                         return status;
347                 }
348
349                 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
350                                                     LDB_FLAG_MOD_DELETE, astate->account_sid,
351                                                     r2.out.rights);
352                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
353                         return NT_STATUS_OK;
354                 }
355
356                 if (!NT_STATUS_IS_OK(status)) {
357                         return status;
358                 }
359
360                 ZERO_STRUCTP(r->out.handle);
361
362                 return NT_STATUS_OK;
363         }
364
365         return NT_STATUS_INVALID_HANDLE;
366 }
367
368
369 /*
370   lsa_EnumPrivs
371 */
372 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
373                               struct lsa_EnumPrivs *r)
374 {
375         struct dcesrv_handle *h;
376         uint32_t i;
377         enum sec_privilege priv;
378         const char *privname;
379
380         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
381
382         i = *r->in.resume_handle;
383
384         while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
385                r->out.privs->count < r->in.max_count) {
386                 struct lsa_PrivEntry *e;
387                 privname = sec_privilege_name(priv);
388                 r->out.privs->privs = talloc_realloc(r->out.privs,
389                                                        r->out.privs->privs,
390                                                        struct lsa_PrivEntry,
391                                                        r->out.privs->count+1);
392                 if (r->out.privs->privs == NULL) {
393                         return NT_STATUS_NO_MEMORY;
394                 }
395                 e = &r->out.privs->privs[r->out.privs->count];
396                 e->luid.low = priv;
397                 e->luid.high = 0;
398                 e->name.string = privname;
399                 r->out.privs->count++;
400                 i++;
401         }
402
403         *r->out.resume_handle = i;
404
405         return NT_STATUS_OK;
406 }
407
408
409 /*
410   lsa_QuerySecObj
411 */
412 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
413                                          struct lsa_QuerySecurity *r)
414 {
415         struct auth_session_info *session_info =
416                 dcesrv_call_session_info(dce_call);
417         struct dcesrv_handle *h;
418         const struct security_descriptor *sd = NULL;
419         uint32_t access_granted = 0;
420         struct sec_desc_buf *sdbuf = NULL;
421         NTSTATUS status;
422         struct dom_sid *sid;
423
424         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
425
426         sid = &session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
427
428         if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
429                 struct lsa_policy_state *pstate = h->data;
430
431                 sd = pstate->sd;
432                 access_granted = pstate->access_mask;
433
434         } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
435                 struct lsa_account_state *astate = h->data;
436                 struct security_descriptor *_sd = NULL;
437
438                 status = dcesrv_build_lsa_sd(mem_ctx, &_sd, sid,
439                                              LSA_ACCOUNT_ALL_ACCESS);
440                 if (!NT_STATUS_IS_OK(status)) {
441                         return status;
442                 }
443                 sd = _sd;
444                 access_granted = astate->access_mask;
445         } else {
446                 return NT_STATUS_INVALID_HANDLE;
447         }
448
449         sdbuf = talloc_zero(mem_ctx, struct sec_desc_buf);
450         if (sdbuf == NULL) {
451                 return NT_STATUS_NO_MEMORY;
452         }
453
454         status = security_descriptor_for_client(sdbuf, sd, r->in.sec_info,
455                                                 access_granted, &sdbuf->sd);
456         if (!NT_STATUS_IS_OK(status)) {
457                 return status;
458         }
459
460         *r->out.sdbuf = sdbuf;
461
462         return NT_STATUS_OK;
463 }
464
465
466 /*
467   lsa_SetSecObj
468 */
469 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
470                               struct lsa_SetSecObj *r)
471 {
472         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
473 }
474
475
476 /*
477   lsa_ChangePassword
478 */
479 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
480                                    struct lsa_ChangePassword *r)
481 {
482         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
483 }
484
485 /*
486   dssetup_DsRoleGetPrimaryDomainInformation
487
488   This is not an LSA call, but is the only call left on the DSSETUP
489   pipe (after the pipe was truncated), and needs lsa_get_policy_state
490 */
491 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
492                                                  TALLOC_CTX *mem_ctx,
493                                                  struct dssetup_DsRoleGetPrimaryDomainInformation *r)
494 {
495         union dssetup_DsRoleInfo *info;
496
497         info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
498         W_ERROR_HAVE_NO_MEMORY(info);
499
500         switch (r->in.level) {
501         case DS_ROLE_BASIC_INFORMATION:
502         {
503                 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
504                 uint32_t flags = 0;
505                 const char *domain = NULL;
506                 const char *dns_domain = NULL;
507                 const char *forest = NULL;
508                 struct GUID domain_guid;
509                 struct lsa_policy_state *state;
510
511                 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx,
512                                                               0, /* we skip access checks */
513                                                               &state);
514                 if (!NT_STATUS_IS_OK(status)) {
515                         return ntstatus_to_werror(status);
516                 }
517
518                 ZERO_STRUCT(domain_guid);
519
520                 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
521                 case ROLE_STANDALONE:
522                         role            = DS_ROLE_STANDALONE_SERVER;
523                         break;
524                 case ROLE_DOMAIN_MEMBER:
525                         role            = DS_ROLE_MEMBER_SERVER;
526                         break;
527                 case ROLE_ACTIVE_DIRECTORY_DC:
528                         if (samdb_is_pdc(state->sam_ldb)) {
529                                 role    = DS_ROLE_PRIMARY_DC;
530                         } else {
531                                 role    = DS_ROLE_BACKUP_DC;
532                         }
533                         break;
534                 }
535
536                 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
537                 case ROLE_STANDALONE:
538                         domain          = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
539                         W_ERROR_HAVE_NO_MEMORY(domain);
540                         break;
541                 case ROLE_DOMAIN_MEMBER:
542                         domain          = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
543                         W_ERROR_HAVE_NO_MEMORY(domain);
544                         /* TODO: what is with dns_domain and forest and guid? */
545                         break;
546                 case ROLE_ACTIVE_DIRECTORY_DC:
547                         flags           = DS_ROLE_PRIMARY_DS_RUNNING;
548
549                         if (state->mixed_domain == 1) {
550                                 flags   |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
551                         }
552
553                         domain          = state->domain_name;
554                         dns_domain      = state->domain_dns;
555                         forest          = state->forest_dns;
556
557                         domain_guid     = state->domain_guid;
558                         flags   |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
559                         break;
560                 }
561
562                 info->basic.role        = role;
563                 info->basic.flags       = flags;
564                 info->basic.domain      = domain;
565                 info->basic.dns_domain  = dns_domain;
566                 info->basic.forest      = forest;
567                 info->basic.domain_guid = domain_guid;
568
569                 r->out.info = info;
570                 return WERR_OK;
571         }
572         case DS_ROLE_UPGRADE_STATUS:
573         {
574                 info->upgrade.upgrading     = DS_ROLE_NOT_UPGRADING;
575                 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
576
577                 r->out.info = info;
578                 return WERR_OK;
579         }
580         case DS_ROLE_OP_STATUS:
581         {
582                 info->opstatus.status = DS_ROLE_OP_IDLE;
583
584                 r->out.info = info;
585                 return WERR_OK;
586         }
587         default:
588                 return WERR_INVALID_PARAMETER;
589         }
590 }
591
592 /*
593   fill in the AccountDomain info
594 */
595 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
596                                        struct lsa_DomainInfo *info)
597 {
598         info->name.string = state->domain_name;
599         info->sid         = state->domain_sid;
600
601         return NT_STATUS_OK;
602 }
603
604 /*
605   fill in the DNS domain info
606 */
607 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
608                              struct lsa_DnsDomainInfo *info)
609 {
610         info->name.string = state->domain_name;
611         info->sid         = state->domain_sid;
612         info->dns_domain.string = state->domain_dns;
613         info->dns_forest.string = state->forest_dns;
614         info->domain_guid       = state->domain_guid;
615
616         return NT_STATUS_OK;
617 }
618
619 /*
620   lsa_QueryInfoPolicy2
621 */
622 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
623                                      struct lsa_QueryInfoPolicy2 *r)
624 {
625         struct lsa_policy_state *state;
626         struct dcesrv_handle *h;
627         union lsa_PolicyInformation *info;
628
629         *r->out.info = NULL;
630
631         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
632
633         state = h->data;
634
635         info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
636         if (!info) {
637                 return NT_STATUS_NO_MEMORY;
638         }
639         *r->out.info = info;
640
641         switch (r->in.level) {
642         case LSA_POLICY_INFO_AUDIT_LOG:
643                 /* we don't need to fill in any of this */
644                 ZERO_STRUCT(info->audit_log);
645                 return NT_STATUS_OK;
646         case LSA_POLICY_INFO_AUDIT_EVENTS:
647                 /* we don't need to fill in any of this */
648                 ZERO_STRUCT(info->audit_events);
649                 return NT_STATUS_OK;
650         case LSA_POLICY_INFO_PD:
651                 /* we don't need to fill in any of this */
652                 ZERO_STRUCT(info->pd);
653                 return NT_STATUS_OK;
654
655         case LSA_POLICY_INFO_DOMAIN:
656                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
657         case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
658                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
659         case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
660                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
661
662         case LSA_POLICY_INFO_ROLE:
663                 info->role.role = LSA_ROLE_PRIMARY;
664                 return NT_STATUS_OK;
665
666         case LSA_POLICY_INFO_DNS:
667         case LSA_POLICY_INFO_DNS_INT:
668                 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
669
670         case LSA_POLICY_INFO_REPLICA:
671                 ZERO_STRUCT(info->replica);
672                 return NT_STATUS_OK;
673
674         case LSA_POLICY_INFO_QUOTA:
675                 ZERO_STRUCT(info->quota);
676                 return NT_STATUS_OK;
677
678         case LSA_POLICY_INFO_MOD:
679         case LSA_POLICY_INFO_AUDIT_FULL_SET:
680         case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
681                 /* windows gives INVALID_PARAMETER */
682                 *r->out.info = NULL;
683                 return NT_STATUS_INVALID_PARAMETER;
684         }
685
686         *r->out.info = NULL;
687         return NT_STATUS_INVALID_INFO_CLASS;
688 }
689
690 /*
691   lsa_QueryInfoPolicy
692 */
693 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
694                                     struct lsa_QueryInfoPolicy *r)
695 {
696         struct lsa_QueryInfoPolicy2 r2;
697         NTSTATUS status;
698
699         ZERO_STRUCT(r2);
700
701         r2.in.handle = r->in.handle;
702         r2.in.level = r->in.level;
703         r2.out.info = r->out.info;
704
705         status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
706
707         return status;
708 }
709
710 /*
711   lsa_SetInfoPolicy
712 */
713 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
714                                   struct lsa_SetInfoPolicy *r)
715 {
716         /* need to support this */
717         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
718 }
719
720
721 /*
722   lsa_ClearAuditLog
723 */
724 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
725                                   struct lsa_ClearAuditLog *r)
726 {
727         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
728 }
729
730
731 static const struct generic_mapping dcesrv_lsa_account_mapping = {
732         LSA_ACCOUNT_READ,
733         LSA_ACCOUNT_WRITE,
734         LSA_ACCOUNT_EXECUTE,
735         LSA_ACCOUNT_ALL_ACCESS
736 };
737
738 /*
739   lsa_CreateAccount
740
741   This call does not seem to have any long-term effects, hence no database operations
742
743   we need to talk to the MS product group to find out what this account database means!
744
745   answer is that the lsa database is totally separate from the SAM and
746   ldap databases. We are going to need a separate ldb to store these
747   accounts. The SIDs on this account bear no relation to the SIDs in
748   AD
749 */
750 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
751                                   struct lsa_CreateAccount *r)
752 {
753         struct lsa_account_state *astate;
754
755         struct lsa_policy_state *state;
756         struct dcesrv_handle *h, *ah;
757
758         ZERO_STRUCTP(r->out.acct_handle);
759
760         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
761
762         state = h->data;
763
764         astate = talloc(dce_call->conn, struct lsa_account_state);
765         if (astate == NULL) {
766                 return NT_STATUS_NO_MEMORY;
767         }
768
769         astate->account_sid = dom_sid_dup(astate, r->in.sid);
770         if (astate->account_sid == NULL) {
771                 talloc_free(astate);
772                 return NT_STATUS_NO_MEMORY;
773         }
774
775         astate->policy = talloc_reference(astate, state);
776         astate->access_mask = r->in.access_mask;
777
778         /*
779          * For now we grant all requested access.
780          *
781          * We will fail at the ldb layer later.
782          */
783         if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
784                 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
785                 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
786         }
787         se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
788
789         DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X].\n",
790                   __func__, dom_sid_string(mem_ctx, astate->account_sid),
791                  (unsigned)r->in.access_mask,
792                  (unsigned)astate->access_mask));
793
794         ah = dcesrv_handle_create(dce_call, LSA_HANDLE_ACCOUNT);
795         if (!ah) {
796                 talloc_free(astate);
797                 return NT_STATUS_NO_MEMORY;
798         }
799
800         ah->data = talloc_steal(ah, astate);
801
802         *r->out.acct_handle = ah->wire_handle;
803
804         return NT_STATUS_OK;
805 }
806
807
808 /*
809   lsa_EnumAccounts
810 */
811 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
812                                  struct lsa_EnumAccounts *r)
813 {
814         struct dcesrv_handle *h;
815         struct lsa_policy_state *state;
816         int ret;
817         struct ldb_message **res;
818         const char * const attrs[] = { "objectSid", NULL};
819         uint32_t count, i;
820
821         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
822
823         state = h->data;
824
825         /* NOTE: This call must only return accounts that have at least
826            one privilege set
827         */
828         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
829                            "(&(objectSid=*)(privilege=*))");
830         if (ret < 0) {
831                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
832         }
833
834         if (*r->in.resume_handle >= ret) {
835                 return NT_STATUS_NO_MORE_ENTRIES;
836         }
837
838         count = ret - *r->in.resume_handle;
839         if (count > r->in.num_entries) {
840                 count = r->in.num_entries;
841         }
842
843         if (count == 0) {
844                 return NT_STATUS_NO_MORE_ENTRIES;
845         }
846
847         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
848         if (r->out.sids->sids == NULL) {
849                 return NT_STATUS_NO_MEMORY;
850         }
851
852         for (i=0;i<count;i++) {
853                 r->out.sids->sids[i].sid =
854                         samdb_result_dom_sid(r->out.sids->sids,
855                                              res[i + *r->in.resume_handle],
856                                              "objectSid");
857                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
858         }
859
860         r->out.sids->num_sids = count;
861         *r->out.resume_handle = count + *r->in.resume_handle;
862
863         return NT_STATUS_OK;
864 }
865
866 /* This decrypts and returns Trusted Domain Auth Information Internal data */
867 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
868                                        TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
869                                        struct trustDomainPasswords *auth_struct)
870 {
871         DATA_BLOB session_key = data_blob(NULL, 0);
872         enum ndr_err_code ndr_err;
873         NTSTATUS nt_status;
874         gnutls_cipher_hd_t cipher_hnd = NULL;
875         gnutls_datum_t _session_key;
876         int rc;
877         struct auth_session_info *session_info =
878                 dcesrv_call_session_info(dce_call);
879         struct loadparm_context *lp_ctx = dce_call->conn->dce_ctx->lp_ctx;
880         bool encrypted;
881
882         encrypted =
883                 dcerpc_is_transport_encrypted(session_info);
884         if (lpcfg_weak_crypto(lp_ctx) == SAMBA_WEAK_CRYPTO_DISALLOWED &&
885             !encrypted) {
886                 DBG_ERR("Transport isn't encrypted and weak crypto disallowed!\n");
887                 return NT_STATUS_ACCESS_DENIED;
888         }
889
890
891         nt_status = dcesrv_transport_session_key(dce_call, &session_key);
892         if (!NT_STATUS_IS_OK(nt_status)) {
893                 return nt_status;
894         }
895
896         _session_key = (gnutls_datum_t) {
897                 .data = session_key.data,
898                 .size = session_key.length,
899         };
900
901         GNUTLS_FIPS140_SET_LAX_MODE();
902         rc = gnutls_cipher_init(&cipher_hnd,
903                                 GNUTLS_CIPHER_ARCFOUR_128,
904                                 &_session_key,
905                                 NULL);
906         if (rc < 0) {
907                 GNUTLS_FIPS140_SET_STRICT_MODE();
908                 nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
909                 goto out;
910         }
911
912         rc = gnutls_cipher_decrypt(cipher_hnd,
913                                    auth_blob->data,
914                                    auth_blob->length);
915         gnutls_cipher_deinit(cipher_hnd);
916         GNUTLS_FIPS140_SET_STRICT_MODE();
917         if (rc < 0) {
918                 nt_status = gnutls_error_to_ntstatus(rc, NT_STATUS_CRYPTO_SYSTEM_INVALID);
919                 goto out;
920         }
921
922         ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
923                                        auth_struct,
924                                        (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
925         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
926                 return NT_STATUS_INVALID_PARAMETER;
927         }
928
929         nt_status = NT_STATUS_OK;
930 out:
931         return nt_status;
932 }
933
934 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
935                                          TALLOC_CTX *mem_ctx,
936                                          struct trustAuthInOutBlob *iopw,
937                                          DATA_BLOB *trustauth_blob)
938 {
939         enum ndr_err_code ndr_err;
940
941         if (iopw->current.count != iopw->count) {
942                 return NT_STATUS_INVALID_PARAMETER;
943         }
944
945         if (iopw->previous.count > iopw->current.count) {
946                 return NT_STATUS_INVALID_PARAMETER;
947         }
948
949         if (iopw->previous.count == 0) {
950                 /*
951                  * If the previous credentials are not present
952                  * we need to make a copy.
953                  */
954                 iopw->previous = iopw->current;
955         }
956
957         if (iopw->previous.count < iopw->current.count) {
958                 struct AuthenticationInformationArray *c = &iopw->current;
959                 struct AuthenticationInformationArray *p = &iopw->previous;
960
961                 /*
962                  * The previous array needs to have the same size
963                  * as the current one.
964                  *
965                  * We may have to fill with TRUST_AUTH_TYPE_NONE
966                  * elements.
967                  */
968                 p->array = talloc_realloc(mem_ctx, p->array,
969                                    struct AuthenticationInformation,
970                                    c->count);
971                 if (p->array == NULL) {
972                         return NT_STATUS_NO_MEMORY;
973                 }
974
975                 while (p->count < c->count) {
976                         struct AuthenticationInformation *a =
977                                 &p->array[p->count++];
978
979                         *a = (struct AuthenticationInformation) {
980                                 .LastUpdateTime = p->array[0].LastUpdateTime,
981                                 .AuthType = TRUST_AUTH_TYPE_NONE,
982                         };
983                 }
984         }
985
986         ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
987                                        iopw,
988                                        (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
989         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
990                 return NT_STATUS_INVALID_PARAMETER;
991         }
992
993         return NT_STATUS_OK;
994 }
995
996 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
997                                struct ldb_context *sam_ldb,
998                                struct ldb_dn *base_dn,
999                                const char *netbios_name,
1000                                struct trustAuthInOutBlob *in,
1001                                struct ldb_dn **user_dn)
1002 {
1003         struct ldb_request *req;
1004         struct ldb_message *msg;
1005         struct ldb_dn *dn;
1006         uint32_t i;
1007         int ret;
1008
1009         dn = ldb_dn_copy(mem_ctx, base_dn);
1010         if (!dn) {
1011                 return NT_STATUS_NO_MEMORY;
1012         }
1013         if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
1014                 return NT_STATUS_NO_MEMORY;
1015         }
1016
1017         msg = ldb_msg_new(mem_ctx);
1018         if (!msg) {
1019                 return NT_STATUS_NO_MEMORY;
1020         }
1021         msg->dn = dn;
1022
1023         ret = ldb_msg_add_string(msg, "objectClass", "user");
1024         if (ret != LDB_SUCCESS) {
1025                 return NT_STATUS_NO_MEMORY;
1026         }
1027
1028         ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
1029         if (ret != LDB_SUCCESS) {
1030                 return NT_STATUS_NO_MEMORY;
1031         }
1032
1033         ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
1034                                  UF_INTERDOMAIN_TRUST_ACCOUNT);
1035         if (ret != LDB_SUCCESS) {
1036                 return NT_STATUS_NO_MEMORY;
1037         }
1038
1039         for (i = 0; i < in->count; i++) {
1040                 const char *attribute;
1041                 struct ldb_val v;
1042                 switch (in->current.array[i].AuthType) {
1043                 case TRUST_AUTH_TYPE_NT4OWF:
1044                         attribute = "unicodePwd";
1045                         v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1046                         v.length = 16;
1047                         break;
1048                 case TRUST_AUTH_TYPE_CLEAR:
1049                         attribute = "clearTextPassword";
1050                         v.data = in->current.array[i].AuthInfo.clear.password;
1051                         v.length = in->current.array[i].AuthInfo.clear.size;
1052                         break;
1053                 default:
1054                         continue;
1055                 }
1056
1057                 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1058                 if (ret != LDB_SUCCESS) {
1059                         return NT_STATUS_NO_MEMORY;
1060                 }
1061         }
1062
1063         /* create the trusted_domain user account */
1064         ret = ldb_build_add_req(&req, sam_ldb, mem_ctx, msg, NULL, NULL,
1065                                 ldb_op_default_callback, NULL);
1066         if (ret != LDB_SUCCESS) {
1067                 return NT_STATUS_NO_MEMORY;
1068         }
1069
1070         ret = ldb_request_add_control(req, DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
1071                                       false, NULL);
1072         if (ret != LDB_SUCCESS) {
1073                 return NT_STATUS_NO_MEMORY;
1074         }
1075
1076         ret = dsdb_autotransaction_request(sam_ldb, req);
1077         if (ret != LDB_SUCCESS) {
1078                 DEBUG(0,("Failed to create user record %s: %s\n",
1079                          ldb_dn_get_linearized(msg->dn),
1080                          ldb_errstring(sam_ldb)));
1081
1082                 switch (ret) {
1083                 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1084                         return NT_STATUS_DOMAIN_EXISTS;
1085                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1086                         return NT_STATUS_ACCESS_DENIED;
1087                 default:
1088                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1089                 }
1090         }
1091
1092         if (user_dn) {
1093                 *user_dn = dn;
1094         }
1095         return NT_STATUS_OK;
1096 }
1097
1098 /*
1099   lsa_CreateTrustedDomainEx2
1100 */
1101 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
1102                                                     TALLOC_CTX *mem_ctx,
1103                                                     struct lsa_CreateTrustedDomainEx2 *r,
1104                                                     int op,
1105                                                     struct lsa_TrustDomainInfoAuthInfo *unencrypted_auth_info)
1106 {
1107         struct dcesrv_handle *policy_handle;
1108         struct lsa_policy_state *policy_state;
1109         struct lsa_trusted_domain_state *trusted_domain_state;
1110         struct dcesrv_handle *handle;
1111         struct ldb_message **msgs, *msg;
1112         const char *attrs[] = {
1113                 NULL
1114         };
1115         const char *netbios_name;
1116         const char *dns_name;
1117         DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1118         struct trustDomainPasswords auth_struct;
1119         int ret;
1120         NTSTATUS nt_status;
1121         struct ldb_context *sam_ldb;
1122         struct server_id *server_ids = NULL;
1123         uint32_t num_server_ids = 0;
1124         NTSTATUS status;
1125         bool ok;
1126         char *dns_encoded = NULL;
1127         char *netbios_encoded = NULL;
1128         char *sid_encoded = NULL;
1129         struct imessaging_context *imsg_ctx =
1130                 dcesrv_imessaging_context(dce_call->conn);
1131
1132         DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
1133         ZERO_STRUCTP(r->out.trustdom_handle);
1134
1135         policy_state = policy_handle->data;
1136         sam_ldb = policy_state->sam_ldb;
1137
1138         netbios_name = r->in.info->netbios_name.string;
1139         if (!netbios_name) {
1140                 return NT_STATUS_INVALID_PARAMETER;
1141         }
1142
1143         dns_name = r->in.info->domain_name.string;
1144         if (dns_name == NULL) {
1145                 return NT_STATUS_INVALID_PARAMETER;
1146         }
1147
1148         if (r->in.info->sid == NULL) {
1149                 return NT_STATUS_INVALID_SID;
1150         }
1151
1152         /*
1153          * We expect S-1-5-21-A-B-C, but we don't
1154          * allow S-1-5-21-0-0-0 as this is used
1155          * for claims and compound identities.
1156          */
1157         ok = dom_sid_is_valid_account_domain(r->in.info->sid);
1158         if (!ok) {
1159                 return NT_STATUS_INVALID_PARAMETER;
1160         }
1161
1162         dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name);
1163         if (dns_encoded == NULL) {
1164                 return NT_STATUS_NO_MEMORY;
1165         }
1166         netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1167         if (netbios_encoded == NULL) {
1168                 return NT_STATUS_NO_MEMORY;
1169         }
1170         sid_encoded = ldap_encode_ndr_dom_sid(mem_ctx, r->in.info->sid);
1171         if (sid_encoded == NULL) {
1172                 return NT_STATUS_NO_MEMORY;
1173         }
1174
1175         trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1176         if (!trusted_domain_state) {
1177                 return NT_STATUS_NO_MEMORY;
1178         }
1179         trusted_domain_state->policy = policy_state;
1180
1181         if (strcasecmp(netbios_name, "BUILTIN") == 0
1182             || (strcasecmp(dns_name, "BUILTIN") == 0)
1183             || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
1184                 return NT_STATUS_INVALID_PARAMETER;
1185         }
1186
1187         if (strcasecmp(netbios_name, policy_state->domain_name) == 0
1188             || strcasecmp(netbios_name, policy_state->domain_dns) == 0
1189             || strcasecmp(dns_name, policy_state->domain_dns) == 0
1190             || strcasecmp(dns_name, policy_state->domain_name) == 0
1191             || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
1192                 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
1193         }
1194
1195         /* While this is a REF pointer, some of the functions that wrap this don't provide this */
1196         if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
1197                 /* No secrets are created at this time, for this function */
1198                 auth_struct.outgoing.count = 0;
1199                 auth_struct.incoming.count = 0;
1200         } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
1201                 auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
1202                                             r->in.auth_info_internal->auth_blob.size);
1203                 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1204                                                    &auth_blob, &auth_struct);
1205                 if (!NT_STATUS_IS_OK(nt_status)) {
1206                         return nt_status;
1207                 }
1208         } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
1209
1210                 if (unencrypted_auth_info->incoming_count > 1) {
1211                         return NT_STATUS_INVALID_PARAMETER;
1212                 }
1213
1214                 /* more investigation required here, do not create secrets for
1215                  * now */
1216                 auth_struct.outgoing.count = 0;
1217                 auth_struct.incoming.count = 0;
1218         } else {
1219                 return NT_STATUS_INVALID_PARAMETER;
1220         }
1221
1222         if (auth_struct.incoming.count) {
1223                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1224                                                      &auth_struct.incoming,
1225                                                      &trustAuthIncoming);
1226                 if (!NT_STATUS_IS_OK(nt_status)) {
1227                         return nt_status;
1228                 }
1229         } else {
1230                 trustAuthIncoming = data_blob(NULL, 0);
1231         }
1232
1233         if (auth_struct.outgoing.count) {
1234                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1235                                                      &auth_struct.outgoing,
1236                                                      &trustAuthOutgoing);
1237                 if (!NT_STATUS_IS_OK(nt_status)) {
1238                         return nt_status;
1239                 }
1240         } else {
1241                 trustAuthOutgoing = data_blob(NULL, 0);
1242         }
1243
1244         ret = ldb_transaction_start(sam_ldb);
1245         if (ret != LDB_SUCCESS) {
1246                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1247         }
1248
1249         /* search for the trusted_domain record */
1250         ret = gendb_search(sam_ldb,
1251                            mem_ctx, policy_state->system_dn, &msgs, attrs,
1252                            "(&(objectClass=trustedDomain)(|"
1253                              "(flatname=%s)(trustPartner=%s)"
1254                              "(flatname=%s)(trustPartner=%s)"
1255                              "(securityIdentifier=%s)))",
1256                            dns_encoded, dns_encoded,
1257                            netbios_encoded, netbios_encoded,
1258                            sid_encoded);
1259         if (ret > 0) {
1260                 ldb_transaction_cancel(sam_ldb);
1261                 return NT_STATUS_OBJECT_NAME_COLLISION;
1262         }
1263         if (ret < 0) {
1264                 ldb_transaction_cancel(sam_ldb);
1265                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1266         }
1267
1268         msg = ldb_msg_new(mem_ctx);
1269         if (msg == NULL) {
1270                 return NT_STATUS_NO_MEMORY;
1271         }
1272
1273         msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1274         if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", dns_name)) {
1275                         ldb_transaction_cancel(sam_ldb);
1276                 return NT_STATUS_NO_MEMORY;
1277         }
1278
1279         ret = ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1280         if (ret != LDB_SUCCESS) {
1281                 ldb_transaction_cancel(sam_ldb);
1282                 return NT_STATUS_NO_MEMORY;;
1283         }
1284
1285         ret = ldb_msg_add_string(msg, "flatname", netbios_name);
1286         if (ret != LDB_SUCCESS) {
1287                 ldb_transaction_cancel(sam_ldb);
1288                 return NT_STATUS_NO_MEMORY;
1289         }
1290
1291         ret = ldb_msg_add_string(msg, "trustPartner", dns_name);
1292         if (ret != LDB_SUCCESS) {
1293                 ldb_transaction_cancel(sam_ldb);
1294                 return NT_STATUS_NO_MEMORY;;
1295         }
1296
1297         ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier",
1298                                     r->in.info->sid);
1299         if (ret != LDB_SUCCESS) {
1300                 ldb_transaction_cancel(sam_ldb);
1301                 return NT_STATUS_NO_MEMORY;;
1302         }
1303
1304         ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1305         if (ret != LDB_SUCCESS) {
1306                 ldb_transaction_cancel(sam_ldb);
1307                 return NT_STATUS_NO_MEMORY;;
1308         }
1309
1310         ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1311         if (ret != LDB_SUCCESS) {
1312                 ldb_transaction_cancel(sam_ldb);
1313                 return NT_STATUS_NO_MEMORY;;
1314         }
1315
1316         ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1317         if (ret != LDB_SUCCESS) {
1318                 ldb_transaction_cancel(sam_ldb);
1319                 return NT_STATUS_NO_MEMORY;;
1320         }
1321
1322         if (trustAuthIncoming.data) {
1323                 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1324                 if (ret != LDB_SUCCESS) {
1325                         ldb_transaction_cancel(sam_ldb);
1326                         return NT_STATUS_NO_MEMORY;
1327                 }
1328         }
1329         if (trustAuthOutgoing.data) {
1330                 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1331                 if (ret != LDB_SUCCESS) {
1332                         ldb_transaction_cancel(sam_ldb);
1333                         return NT_STATUS_NO_MEMORY;
1334                 }
1335         }
1336
1337         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1338
1339         /* create the trusted_domain */
1340         ret = ldb_add(sam_ldb, msg);
1341         switch (ret) {
1342         case  LDB_SUCCESS:
1343                 break;
1344         case  LDB_ERR_ENTRY_ALREADY_EXISTS:
1345                 ldb_transaction_cancel(sam_ldb);
1346                 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1347                          ldb_dn_get_linearized(msg->dn),
1348                          ldb_errstring(sam_ldb)));
1349                 return NT_STATUS_DOMAIN_EXISTS;
1350         case  LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1351                 ldb_transaction_cancel(sam_ldb);
1352                 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1353                          ldb_dn_get_linearized(msg->dn),
1354                          ldb_errstring(sam_ldb)));
1355                 return NT_STATUS_ACCESS_DENIED;
1356         default:
1357                 ldb_transaction_cancel(sam_ldb);
1358                 DEBUG(0,("Failed to create user record %s: %s\n",
1359                          ldb_dn_get_linearized(msg->dn),
1360                          ldb_errstring(sam_ldb)));
1361                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1362         }
1363
1364         if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1365                 struct ldb_dn *user_dn;
1366                 /* Inbound trusts must also create a cn=users object to match */
1367                 nt_status = add_trust_user(mem_ctx, sam_ldb,
1368                                            policy_state->domain_dn,
1369                                            netbios_name,
1370                                            &auth_struct.incoming,
1371                                            &user_dn);
1372                 if (!NT_STATUS_IS_OK(nt_status)) {
1373                         ldb_transaction_cancel(sam_ldb);
1374                         return nt_status;
1375                 }
1376
1377                 /* save the trust user dn */
1378                 trusted_domain_state->trusted_domain_user_dn
1379                         = talloc_steal(trusted_domain_state, user_dn);
1380         }
1381
1382         ret = ldb_transaction_commit(sam_ldb);
1383         if (ret != LDB_SUCCESS) {
1384                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1385         }
1386
1387         /*
1388          * Notify winbindd that we have a new trust
1389          */
1390         status = irpc_servers_byname(imsg_ctx,
1391                                      mem_ctx,
1392                                      "winbind_server",
1393                                      &num_server_ids,
1394                                      &server_ids);
1395         if (NT_STATUS_IS_OK(status) && num_server_ids >= 1) {
1396                 imessaging_send(imsg_ctx,
1397                                 server_ids[0],
1398                                 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS,
1399                                 NULL);
1400         }
1401         TALLOC_FREE(server_ids);
1402
1403         handle = dcesrv_handle_create(dce_call, LSA_HANDLE_TRUSTED_DOMAIN);
1404         if (!handle) {
1405                 return NT_STATUS_NO_MEMORY;
1406         }
1407
1408         handle->data = talloc_steal(handle, trusted_domain_state);
1409
1410         trusted_domain_state->access_mask = r->in.access_mask;
1411         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1412
1413         *r->out.trustdom_handle = handle->wire_handle;
1414
1415         return NT_STATUS_OK;
1416 }
1417
1418 /*
1419   lsa_CreateTrustedDomainEx2
1420 */
1421 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1422                                            TALLOC_CTX *mem_ctx,
1423                                            struct lsa_CreateTrustedDomainEx2 *r)
1424 {
1425         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1426 }
1427 /*
1428   lsa_CreateTrustedDomainEx
1429 */
1430 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1431                                           TALLOC_CTX *mem_ctx,
1432                                           struct lsa_CreateTrustedDomainEx *r)
1433 {
1434         struct lsa_CreateTrustedDomainEx2 r2;
1435
1436         r2.in.policy_handle = r->in.policy_handle;
1437         r2.in.info = r->in.info;
1438         r2.out.trustdom_handle = r->out.trustdom_handle;
1439         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1440 }
1441
1442 /*
1443   lsa_CreateTrustedDomain
1444 */
1445 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1446                                         struct lsa_CreateTrustedDomain *r)
1447 {
1448         struct lsa_CreateTrustedDomainEx2 r2;
1449
1450         r2.in.policy_handle = r->in.policy_handle;
1451         r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1452         if (!r2.in.info) {
1453                 return NT_STATUS_NO_MEMORY;
1454         }
1455
1456         r2.in.info->domain_name = r->in.info->name;
1457         r2.in.info->netbios_name = r->in.info->name;
1458         r2.in.info->sid = r->in.info->sid;
1459         r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1460         r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1461         r2.in.info->trust_attributes = 0;
1462
1463         r2.in.access_mask = r->in.access_mask;
1464         r2.out.trustdom_handle = r->out.trustdom_handle;
1465
1466         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1467 }
1468
1469 static NTSTATUS dcesrv_lsa_OpenTrustedDomain_common(
1470                                         struct dcesrv_call_state *dce_call,
1471                                         TALLOC_CTX *tmp_mem,
1472                                         struct lsa_policy_state *policy_state,
1473                                         const char *filter,
1474                                         uint32_t access_mask,
1475                                         struct dcesrv_handle **_handle)
1476 {
1477         struct lsa_trusted_domain_state *trusted_domain_state;
1478         struct dcesrv_handle *handle;
1479         struct ldb_message **msgs;
1480         const char *attrs[] = {
1481                 "trustDirection",
1482                 "flatname",
1483                 NULL
1484         };
1485         uint32_t direction;
1486         int ret;
1487
1488         /* TODO: perform access checks */
1489
1490         /* search for the trusted_domain record */
1491         ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1492                            policy_state->system_dn,
1493                            &msgs, attrs, "%s", filter);
1494         if (ret == 0) {
1495                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1496         }
1497
1498         if (ret != 1) {
1499                 DEBUG(0,("Found %d records matching %s under %s\n", ret,
1500                          filter,
1501                          ldb_dn_get_linearized(policy_state->system_dn)));
1502                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1503         }
1504
1505         trusted_domain_state = talloc_zero(tmp_mem,
1506                                            struct lsa_trusted_domain_state);
1507         if (!trusted_domain_state) {
1508                 return NT_STATUS_NO_MEMORY;
1509         }
1510         trusted_domain_state->policy = policy_state;
1511
1512         trusted_domain_state->trusted_domain_dn =
1513                 talloc_steal(trusted_domain_state, msgs[0]->dn);
1514
1515         direction = ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0);
1516         if (direction & LSA_TRUST_DIRECTION_INBOUND) {
1517                 const char *flatname = ldb_msg_find_attr_as_string(msgs[0],
1518                                                         "flatname", NULL);
1519
1520                 /* search for the trusted_domain account */
1521                 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1522                                    policy_state->domain_dn,
1523                                    &msgs, attrs,
1524                                    "(&(samaccountname=%s$)(objectclass=user)"
1525                                    "(userAccountControl:%s:=%u))",
1526                                    flatname,
1527                                    LDB_OID_COMPARATOR_AND,
1528                                    UF_INTERDOMAIN_TRUST_ACCOUNT);
1529                 if (ret == 1) {
1530                         trusted_domain_state->trusted_domain_user_dn =
1531                                 talloc_steal(trusted_domain_state, msgs[0]->dn);
1532                 }
1533         }
1534
1535         handle = dcesrv_handle_create(dce_call, LSA_HANDLE_TRUSTED_DOMAIN);
1536         if (!handle) {
1537                 return NT_STATUS_NO_MEMORY;
1538         }
1539
1540         handle->data = talloc_steal(handle, trusted_domain_state);
1541
1542         trusted_domain_state->access_mask = access_mask;
1543         trusted_domain_state->policy = talloc_reference(trusted_domain_state,
1544                                                         policy_state);
1545
1546         *_handle = handle;
1547
1548         return NT_STATUS_OK;
1549 }
1550
1551 /*
1552   lsa_OpenTrustedDomain
1553 */
1554 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1555                                       struct lsa_OpenTrustedDomain *r)
1556 {
1557         struct dcesrv_handle *policy_handle;
1558         struct lsa_policy_state *policy_state;
1559         struct dcesrv_handle *handle;
1560         const char *sid_string;
1561         char *filter;
1562         NTSTATUS status;
1563
1564         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1565         ZERO_STRUCTP(r->out.trustdom_handle);
1566         policy_state = policy_handle->data;
1567
1568         sid_string = dom_sid_string(mem_ctx, r->in.sid);
1569         if (!sid_string) {
1570                 return NT_STATUS_NO_MEMORY;
1571         }
1572
1573         filter = talloc_asprintf(mem_ctx,
1574                                  "(&(securityIdentifier=%s)"
1575                                  "(objectclass=trustedDomain))",
1576                                  sid_string);
1577         if (filter == NULL) {
1578                 return NT_STATUS_NO_MEMORY;
1579         }
1580
1581         status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1582                                                      policy_state,
1583                                                      filter,
1584                                                      r->in.access_mask,
1585                                                      &handle);
1586         if (!NT_STATUS_IS_OK(status)) {
1587                 return status;
1588         }
1589
1590         *r->out.trustdom_handle = handle->wire_handle;
1591
1592         return NT_STATUS_OK;
1593 }
1594
1595
1596 /*
1597   lsa_OpenTrustedDomainByName
1598 */
1599 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1600                                             TALLOC_CTX *mem_ctx,
1601                                             struct lsa_OpenTrustedDomainByName *r)
1602 {
1603         struct dcesrv_handle *policy_handle;
1604         struct lsa_policy_state *policy_state;
1605         struct dcesrv_handle *handle;
1606         char *td_name;
1607         char *filter;
1608         NTSTATUS status;
1609
1610         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1611         ZERO_STRUCTP(r->out.trustdom_handle);
1612         policy_state = policy_handle->data;
1613
1614         if (!r->in.name.string) {
1615                 return NT_STATUS_INVALID_PARAMETER;
1616         }
1617
1618         /* search for the trusted_domain record */
1619         td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1620         if (td_name == NULL) {
1621                 return NT_STATUS_NO_MEMORY;
1622         }
1623
1624         filter = talloc_asprintf(mem_ctx,
1625                            "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1626                              "(objectclass=trustedDomain))",
1627                            td_name, td_name, td_name);
1628         if (filter == NULL) {
1629                 return NT_STATUS_NO_MEMORY;
1630         }
1631
1632         status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1633                                                      policy_state,
1634                                                      filter,
1635                                                      r->in.access_mask,
1636                                                      &handle);
1637         if (!NT_STATUS_IS_OK(status)) {
1638                 return status;
1639         }
1640
1641         *r->out.trustdom_handle = handle->wire_handle;
1642
1643         return NT_STATUS_OK;
1644 }
1645
1646
1647
1648 /*
1649   lsa_SetTrustedDomainInfo
1650 */
1651 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1652                                          struct lsa_SetTrustedDomainInfo *r)
1653 {
1654         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1655 }
1656
1657
1658
1659 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1660  * otherwise at least one must be provided */
1661 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1662                         struct ldb_dn *basedn, const char *dns_domain,
1663                         const char *netbios, struct dom_sid2 *sid,
1664                         struct ldb_message ***msgs)
1665 {
1666         const char *attrs[] = { "flatname", "trustPartner",
1667                                 "securityIdentifier", "trustDirection",
1668                                 "trustType", "trustAttributes",
1669                                 "trustPosixOffset",
1670                                 "msDs-supportedEncryptionTypes",
1671                                 "msDS-TrustForestTrustInfo",
1672                                 NULL
1673         };
1674         char *dns = NULL;
1675         char *nbn = NULL;
1676         char *filter;
1677         int ret;
1678
1679
1680         if (dns_domain || netbios || sid) {
1681                 filter = talloc_strdup(mem_ctx,
1682                                    "(&(objectclass=trustedDomain)(|");
1683         } else {
1684                 filter = talloc_strdup(mem_ctx,
1685                                        "(objectclass=trustedDomain)");
1686         }
1687
1688         if (dns_domain) {
1689                 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1690                 if (!dns) {
1691                         return NT_STATUS_NO_MEMORY;
1692                 }
1693                 talloc_asprintf_addbuf(&filter, "(trustPartner=%s)", dns);
1694         }
1695         if (netbios) {
1696                 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1697                 if (!nbn) {
1698                         return NT_STATUS_NO_MEMORY;
1699                 }
1700                 talloc_asprintf_addbuf(&filter, "(flatname=%s)", nbn);
1701         }
1702         if (sid) {
1703                 struct dom_sid_buf buf;
1704                 char *sidstr = dom_sid_str_buf(sid, &buf);
1705                 talloc_asprintf_addbuf(
1706                         &filter, "(securityIdentifier=%s)", sidstr);
1707         }
1708         if (dns_domain || netbios || sid) {
1709                 talloc_asprintf_addbuf(&filter, "))");
1710         }
1711         if (filter == NULL) {
1712                 return NT_STATUS_NO_MEMORY;
1713         }
1714
1715         ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1716         if (ret == 0) {
1717                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1718         }
1719
1720         if (ret != 1) {
1721                 return NT_STATUS_OBJECT_NAME_COLLISION;
1722         }
1723
1724         return NT_STATUS_OK;
1725 }
1726
1727 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1728                                       struct ldb_context *sam_ldb,
1729                                       struct ldb_message *orig,
1730                                       struct ldb_message *dest,
1731                                       const char *attribute,
1732                                       uint32_t value,
1733                                       uint32_t *orig_value)
1734 {
1735         const struct ldb_val *orig_val;
1736         uint32_t orig_uint = 0;
1737         unsigned int flags = 0;
1738         int ret;
1739         int error = 0;
1740
1741         orig_val = ldb_msg_find_ldb_val(orig, attribute);
1742         if (!orig_val || !orig_val->data) {
1743                 /* add new attribute */
1744                 flags = LDB_FLAG_MOD_ADD;
1745
1746         } else {
1747                 orig_uint = smb_strtoul((const char *)orig_val->data,
1748                                         NULL,
1749                                         0,
1750                                         &error,
1751                                         SMB_STR_STANDARD);
1752                 if (error != 0 || orig_uint != value) {
1753                         /* replace also if can't get value */
1754                         flags = LDB_FLAG_MOD_REPLACE;
1755                 }
1756         }
1757
1758         if (flags == 0) {
1759                 /* stored value is identical, nothing to change */
1760                 goto done;
1761         }
1762
1763         ret = samdb_msg_append_uint(sam_ldb, dest, dest, attribute, value, flags);
1764         if (ret != LDB_SUCCESS) {
1765                 return NT_STATUS_NO_MEMORY;
1766         }
1767
1768 done:
1769         if (orig_value) {
1770                 *orig_value = orig_uint;
1771         }
1772         return NT_STATUS_OK;
1773 }
1774
1775 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1776                                   struct ldb_context *sam_ldb,
1777                                   struct ldb_dn *base_dn,
1778                                   bool delete_user,
1779                                   const char *netbios_name,
1780                                   struct trustAuthInOutBlob *in)
1781 {
1782         const char *attrs[] = { "userAccountControl", NULL };
1783         struct ldb_message **msgs;
1784         struct ldb_message *msg;
1785         uint32_t uac;
1786         uint32_t i;
1787         int ret;
1788
1789         ret = gendb_search(sam_ldb, mem_ctx,
1790                            base_dn, &msgs, attrs,
1791                            "samAccountName=%s$", netbios_name);
1792         if (ret > 1) {
1793                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1794         }
1795
1796         if (ret == 0) {
1797                 if (delete_user) {
1798                         return NT_STATUS_OK;
1799                 }
1800
1801                 /* ok no existing user, add it from scratch */
1802                 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1803                                       netbios_name, in, NULL);
1804         }
1805
1806         /* check user is what we are looking for */
1807         uac = ldb_msg_find_attr_as_uint(msgs[0],
1808                                         "userAccountControl", 0);
1809         if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1810                 return NT_STATUS_OBJECT_NAME_COLLISION;
1811         }
1812
1813         if (delete_user) {
1814                 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1815                 switch (ret) {
1816                 case LDB_SUCCESS:
1817                         return NT_STATUS_OK;
1818                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1819                         return NT_STATUS_ACCESS_DENIED;
1820                 default:
1821                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1822                 }
1823         }
1824
1825         /* entry exists, just modify secret if any */
1826         if (in == NULL || in->count == 0) {
1827                 return NT_STATUS_OK;
1828         }
1829
1830         msg = ldb_msg_new(mem_ctx);
1831         if (!msg) {
1832                 return NT_STATUS_NO_MEMORY;
1833         }
1834         msg->dn = msgs[0]->dn;
1835
1836         for (i = 0; i < in->count; i++) {
1837                 const char *attribute;
1838                 struct ldb_val v;
1839                 switch (in->current.array[i].AuthType) {
1840                 case TRUST_AUTH_TYPE_NT4OWF:
1841                         attribute = "unicodePwd";
1842                         v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1843                         v.length = 16;
1844                         break;
1845                 case TRUST_AUTH_TYPE_CLEAR:
1846                         attribute = "clearTextPassword";
1847                         v.data = in->current.array[i].AuthInfo.clear.password;
1848                         v.length = in->current.array[i].AuthInfo.clear.size;
1849                         break;
1850                 default:
1851                         continue;
1852                 }
1853
1854                 ret = ldb_msg_append_value(msg, attribute, &v, LDB_FLAG_MOD_REPLACE);
1855                 if (ret != LDB_SUCCESS) {
1856                         return NT_STATUS_NO_MEMORY;
1857                 }
1858         }
1859
1860         /* create the trusted_domain user account */
1861         ret = ldb_modify(sam_ldb, msg);
1862         if (ret != LDB_SUCCESS) {
1863                 DEBUG(0,("Failed to create user record %s: %s\n",
1864                          ldb_dn_get_linearized(msg->dn),
1865                          ldb_errstring(sam_ldb)));
1866
1867                 switch (ret) {
1868                 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1869                         return NT_STATUS_DOMAIN_EXISTS;
1870                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1871                         return NT_STATUS_ACCESS_DENIED;
1872                 default:
1873                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1874                 }
1875         }
1876
1877         return NT_STATUS_OK;
1878 }
1879
1880
1881 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1882                                           struct lsa_policy_state *p_state,
1883                                           TALLOC_CTX *mem_ctx,
1884                                           struct ldb_message *dom_msg,
1885                                           enum lsa_TrustDomInfoEnum level,
1886                                           union lsa_TrustedDomainInfo *info)
1887 {
1888         uint32_t *posix_offset = NULL;
1889         struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1890         struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1891         struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1892         uint32_t *enc_types = NULL;
1893         DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1894         struct trustDomainPasswords auth_struct;
1895         struct trustAuthInOutBlob *current_passwords = NULL;
1896         NTSTATUS nt_status;
1897         struct ldb_message **msgs;
1898         struct ldb_message *msg;
1899         bool add_outgoing = false;
1900         bool add_incoming = false;
1901         bool del_outgoing = false;
1902         bool del_incoming = false;
1903         bool del_forest_info = false;
1904         bool in_transaction = false;
1905         int ret;
1906         bool am_rodc;
1907
1908         switch (level) {
1909         case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1910                 posix_offset = &info->posix_offset.posix_offset;
1911                 break;
1912         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1913                 info_ex = &info->info_ex;
1914                 break;
1915         case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1916                 auth_info = &info->auth_info;
1917                 break;
1918         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1919                 posix_offset = &info->full_info.posix_offset.posix_offset;
1920                 info_ex = &info->full_info.info_ex;
1921                 auth_info = &info->full_info.auth_info;
1922                 break;
1923         case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1924                 auth_info_int = &info->auth_info_internal;
1925                 break;
1926         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1927                 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1928                 info_ex = &info->full_info_internal.info_ex;
1929                 auth_info_int = &info->full_info_internal.auth_info;
1930                 break;
1931         case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1932                 enc_types = &info->enc_types.enc_types;
1933                 break;
1934         default:
1935                 return NT_STATUS_INVALID_PARAMETER;
1936         }
1937
1938         if (auth_info) {
1939                 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1940                                                   &trustAuthIncoming,
1941                                                   &trustAuthOutgoing);
1942                 if (!NT_STATUS_IS_OK(nt_status)) {
1943                         return nt_status;
1944                 }
1945                 if (trustAuthIncoming.data) {
1946                         /* This does the decode of some of this twice, but it is easier that way */
1947                         nt_status = auth_info_2_trustauth_inout(mem_ctx,
1948                                                                 auth_info->incoming_count,
1949                                                                 auth_info->incoming_current_auth_info,
1950                                                                 NULL,
1951                                                                 &current_passwords);
1952                         if (!NT_STATUS_IS_OK(nt_status)) {
1953                                 return nt_status;
1954                         }
1955                 }
1956         }
1957
1958         /* decode auth_info_int if set */
1959         if (auth_info_int) {
1960
1961                 /* now decrypt blob */
1962                 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1963                                             auth_info_int->auth_blob.size);
1964
1965                 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1966                                                    &auth_blob, &auth_struct);
1967                 if (!NT_STATUS_IS_OK(nt_status)) {
1968                         return nt_status;
1969                 }
1970         }
1971
1972         if (info_ex) {
1973                 /* verify data matches */
1974                 if (info_ex->trust_attributes &
1975                     LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1976                         /* TODO: check what behavior level we have */
1977                        if (strcasecmp_m(p_state->domain_dns,
1978                                         p_state->forest_dns) != 0) {
1979                                 return NT_STATUS_INVALID_DOMAIN_STATE;
1980                         }
1981                 }
1982
1983                 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1984                 if (ret == LDB_SUCCESS && am_rodc) {
1985                         return NT_STATUS_NO_SUCH_DOMAIN;
1986                 }
1987
1988                 /* verify only one object matches the dns/netbios/sid
1989                  * triplet and that this is the one we already have */
1990                 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1991                                     p_state->system_dn,
1992                                     info_ex->domain_name.string,
1993                                     info_ex->netbios_name.string,
1994                                     info_ex->sid, &msgs);
1995                 if (!NT_STATUS_IS_OK(nt_status)) {
1996                         return nt_status;
1997                 }
1998                 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1999                         return NT_STATUS_OBJECT_NAME_COLLISION;
2000                 }
2001                 talloc_free(msgs);
2002         }
2003
2004         /* TODO: should we fetch previous values from the existing entry
2005          * and append them ? */
2006         if (auth_info_int && auth_struct.incoming.count) {
2007                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
2008                                                      &auth_struct.incoming,
2009                                                      &trustAuthIncoming);
2010                 if (!NT_STATUS_IS_OK(nt_status)) {
2011                         return nt_status;
2012                 }
2013
2014                 current_passwords = &auth_struct.incoming;
2015
2016         } else {
2017                 trustAuthIncoming = data_blob(NULL, 0);
2018         }
2019
2020         if (auth_info_int && auth_struct.outgoing.count) {
2021                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
2022                                                      &auth_struct.outgoing,
2023                                                      &trustAuthOutgoing);
2024                 if (!NT_STATUS_IS_OK(nt_status)) {
2025                         return nt_status;
2026                 }
2027         } else {
2028                 trustAuthOutgoing = data_blob(NULL, 0);
2029         }
2030
2031         msg = ldb_msg_new(mem_ctx);
2032         if (msg == NULL) {
2033                 return NT_STATUS_NO_MEMORY;
2034         }
2035         msg->dn = dom_msg->dn;
2036
2037         if (posix_offset) {
2038                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2039                                                   dom_msg, msg,
2040                                                   "trustPosixOffset",
2041                                                   *posix_offset, NULL);
2042                 if (!NT_STATUS_IS_OK(nt_status)) {
2043                         return nt_status;
2044                 }
2045         }
2046
2047         if (info_ex) {
2048                 uint32_t origattrs;
2049                 uint32_t changed_attrs;
2050                 uint32_t origdir;
2051                 int origtype;
2052
2053                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2054                                                   dom_msg, msg,
2055                                                   "trustDirection",
2056                                                   info_ex->trust_direction,
2057                                                   &origdir);
2058                 if (!NT_STATUS_IS_OK(nt_status)) {
2059                         return nt_status;
2060                 }
2061
2062                 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
2063                         if (auth_info != NULL && trustAuthIncoming.length > 0) {
2064                                 add_incoming = true;
2065                         }
2066                 }
2067                 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
2068                         if (auth_info != NULL && trustAuthOutgoing.length > 0) {
2069                                 add_outgoing = true;
2070                         }
2071                 }
2072
2073                 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
2074                     !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
2075                         del_incoming = true;
2076                 }
2077                 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
2078                     !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
2079                         del_outgoing = true;
2080                 }
2081
2082                 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
2083                 if (origtype == -1 || origtype != info_ex->trust_type) {
2084                         DEBUG(1, ("Attempted to change trust type! "
2085                                   "Operation not handled\n"));
2086                         return NT_STATUS_INVALID_PARAMETER;
2087                 }
2088
2089                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2090                                                   dom_msg, msg,
2091                                                   "trustAttributes",
2092                                                   info_ex->trust_attributes,
2093                                                   &origattrs);
2094                 if (!NT_STATUS_IS_OK(nt_status)) {
2095                         return nt_status;
2096                 }
2097                 /* TODO: check forestFunctionality from ldb opaque */
2098                 /* TODO: check what is set makes sense */
2099
2100                 changed_attrs = origattrs ^ info_ex->trust_attributes;
2101                 if (changed_attrs & ~LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
2102                         /*
2103                          * For now we only allow
2104                          * LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE to be changed.
2105                          *
2106                          * TODO: we may need to support more attribute changes
2107                          */
2108                         DEBUG(1, ("Attempted to change trust attributes "
2109                                   "(0x%08x != 0x%08x)! "
2110                                   "Operation not handled yet...\n",
2111                                   (unsigned)origattrs,
2112                                   (unsigned)info_ex->trust_attributes));
2113                         return NT_STATUS_INVALID_PARAMETER;
2114                 }
2115
2116                 if (!(info_ex->trust_attributes &
2117                       LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE))
2118                 {
2119                         struct ldb_message_element *orig_forest_el = NULL;
2120
2121                         orig_forest_el = ldb_msg_find_element(dom_msg,
2122                                                 "msDS-TrustForestTrustInfo");
2123                         if (orig_forest_el != NULL) {
2124                                 del_forest_info = true;
2125                         }
2126                 }
2127         }
2128
2129         if (enc_types) {
2130                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2131                                                   dom_msg, msg,
2132                                                   "msDS-SupportedEncryptionTypes",
2133                                                   *enc_types, NULL);
2134                 if (!NT_STATUS_IS_OK(nt_status)) {
2135                         return nt_status;
2136                 }
2137         }
2138
2139         if (add_incoming || del_incoming) {
2140                 if (add_incoming) {
2141                         ret = ldb_msg_append_value(msg, "trustAuthIncoming",
2142                                                    &trustAuthIncoming, LDB_FLAG_MOD_REPLACE);
2143                         if (ret != LDB_SUCCESS) {
2144                                 return NT_STATUS_NO_MEMORY;
2145                         }
2146                 } else {
2147                         ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
2148                                                 LDB_FLAG_MOD_REPLACE, NULL);
2149                         if (ret != LDB_SUCCESS) {
2150                                 return NT_STATUS_NO_MEMORY;
2151                         }
2152                 }
2153         }
2154         if (add_outgoing || del_outgoing) {
2155                 if (add_outgoing) {
2156                         ret = ldb_msg_append_value(msg, "trustAuthOutgoing",
2157                                                    &trustAuthOutgoing, LDB_FLAG_MOD_REPLACE);
2158                         if (ret != LDB_SUCCESS) {
2159                                 return NT_STATUS_NO_MEMORY;
2160                         }
2161                 } else {
2162                         ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
2163                                                 LDB_FLAG_MOD_REPLACE, NULL);
2164                         if (ret != LDB_SUCCESS) {
2165                                 return NT_STATUS_NO_MEMORY;
2166                         }
2167                 }
2168         }
2169         if (del_forest_info) {
2170                 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
2171                                         LDB_FLAG_MOD_REPLACE, NULL);
2172                 if (ret != LDB_SUCCESS) {
2173                         return NT_STATUS_NO_MEMORY;
2174                 }
2175         }
2176
2177         /* start transaction */
2178         ret = ldb_transaction_start(p_state->sam_ldb);
2179         if (ret != LDB_SUCCESS) {
2180                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2181         }
2182         in_transaction = true;
2183
2184         if (msg->num_elements) {
2185                 ret = ldb_modify(p_state->sam_ldb, msg);
2186                 if (ret != LDB_SUCCESS) {
2187                         DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
2188                                  ldb_dn_get_linearized(msg->dn),
2189                                  ldb_errstring(p_state->sam_ldb)));
2190                         nt_status = dsdb_ldb_err_to_ntstatus(ret);
2191                         goto done;
2192                 }
2193         }
2194
2195         if (add_incoming || del_incoming) {
2196                 const char *netbios_name;
2197
2198                 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
2199                                                            "flatname", NULL);
2200                 if (!netbios_name) {
2201                         nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
2202                         goto done;
2203                 }
2204
2205                 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
2206                 nt_status = update_trust_user(mem_ctx,
2207                                               p_state->sam_ldb,
2208                                               p_state->domain_dn,
2209                                               del_incoming,
2210                                               netbios_name,
2211                                               current_passwords);
2212                 if (!NT_STATUS_IS_OK(nt_status)) {
2213                         goto done;
2214                 }
2215         }
2216
2217         /* ok, all fine, commit transaction and return */
2218         ret = ldb_transaction_commit(p_state->sam_ldb);
2219         if (ret != LDB_SUCCESS) {
2220                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2221         }
2222         in_transaction = false;
2223
2224         nt_status = NT_STATUS_OK;
2225
2226 done:
2227         if (in_transaction) {
2228                 ldb_transaction_cancel(p_state->sam_ldb);
2229         }
2230         return nt_status;
2231 }
2232
2233 /*
2234   lsa_SetInformationTrustedDomain
2235 */
2236 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
2237                                 struct dcesrv_call_state *dce_call,
2238                                 TALLOC_CTX *mem_ctx,
2239                                 struct lsa_SetInformationTrustedDomain *r)
2240 {
2241         struct dcesrv_handle *h;
2242         struct lsa_trusted_domain_state *td_state;
2243         struct ldb_message **msgs;
2244         NTSTATUS nt_status;
2245
2246         DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
2247                            LSA_HANDLE_TRUSTED_DOMAIN);
2248
2249         td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2250
2251         /* get the trusted domain object */
2252         nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
2253                             td_state->trusted_domain_dn,
2254                             NULL, NULL, NULL, &msgs);
2255         if (!NT_STATUS_IS_OK(nt_status)) {
2256                 if (NT_STATUS_EQUAL(nt_status,
2257                                     NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2258                         return nt_status;
2259                 }
2260                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2261         }
2262
2263         return setInfoTrustedDomain_base(dce_call, td_state->policy, mem_ctx,
2264                                          msgs[0], r->in.level, r->in.info);
2265 }
2266
2267
2268 /*
2269   lsa_DeleteTrustedDomain
2270 */
2271 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2272                                       struct lsa_DeleteTrustedDomain *r)
2273 {
2274         NTSTATUS status;
2275         struct lsa_OpenTrustedDomain opn = {{0},{0}};
2276         struct lsa_DeleteObject del;
2277         struct dcesrv_handle *h;
2278
2279         opn.in.handle = r->in.handle;
2280         opn.in.sid = r->in.dom_sid;
2281         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2282         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2283         if (!opn.out.trustdom_handle) {
2284                 return NT_STATUS_NO_MEMORY;
2285         }
2286         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2287         if (!NT_STATUS_IS_OK(status)) {
2288                 return status;
2289         }
2290
2291         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2292         talloc_steal(mem_ctx, h);
2293
2294         del.in.handle = opn.out.trustdom_handle;
2295         del.out.handle = opn.out.trustdom_handle;
2296         status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
2297         if (!NT_STATUS_IS_OK(status)) {
2298                 return status;
2299         }
2300         return NT_STATUS_OK;
2301 }
2302
2303 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
2304                                      struct ldb_message *msg,
2305                                      struct lsa_TrustDomainInfoInfoEx *info_ex)
2306 {
2307         info_ex->domain_name.string
2308                 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2309         info_ex->netbios_name.string
2310                 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2311         info_ex->sid
2312                 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2313         info_ex->trust_direction
2314                 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2315         info_ex->trust_type
2316                 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2317         info_ex->trust_attributes
2318                 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
2319         return NT_STATUS_OK;
2320 }
2321
2322 /*
2323   lsa_QueryTrustedDomainInfo
2324 */
2325 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2326                                            struct lsa_QueryTrustedDomainInfo *r)
2327 {
2328         union lsa_TrustedDomainInfo *info = NULL;
2329         struct dcesrv_handle *h;
2330         struct lsa_trusted_domain_state *trusted_domain_state;
2331         struct ldb_message *msg;
2332         int ret;
2333         struct ldb_message **res;
2334         const char *attrs[] = {
2335                 "flatname",
2336                 "trustPartner",
2337                 "securityIdentifier",
2338                 "trustDirection",
2339                 "trustType",
2340                 "trustAttributes",
2341                 "msDs-supportedEncryptionTypes",
2342                 NULL
2343         };
2344
2345         DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2346
2347         trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2348
2349         /* pull all the user attributes */
2350         ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2351                               trusted_domain_state->trusted_domain_dn, &res, attrs);
2352         if (ret != 1) {
2353                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2354         }
2355         msg = res[0];
2356
2357         info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2358         if (!info) {
2359                 return NT_STATUS_NO_MEMORY;
2360         }
2361         *r->out.info = info;
2362
2363         switch (r->in.level) {
2364         case LSA_TRUSTED_DOMAIN_INFO_NAME:
2365                 info->name.netbios_name.string
2366                         = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2367                 break;
2368         case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2369                 info->posix_offset.posix_offset
2370                         = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2371                 break;
2372 #if 0  /* Win2k3 doesn't implement this */
2373         case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2374                 r->out.info->info_basic.netbios_name.string
2375                         = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2376                 r->out.info->info_basic.sid
2377                         = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2378                 break;
2379 #endif
2380         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2381                 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2382
2383         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2384                 ZERO_STRUCT(info->full_info);
2385                 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2386         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2387                 ZERO_STRUCT(info->full_info2_internal);
2388                 info->full_info2_internal.posix_offset.posix_offset
2389                         = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2390                 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2391
2392         case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2393                 info->enc_types.enc_types
2394                         = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2395                 break;
2396
2397         case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2398         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2399                 /* oops, we don't want to return the info after all */
2400                 talloc_free(info);
2401                 *r->out.info = NULL;
2402                 return NT_STATUS_INVALID_PARAMETER;
2403         default:
2404                 /* oops, we don't want to return the info after all */
2405                 talloc_free(info);
2406                 *r->out.info = NULL;
2407                 return NT_STATUS_INVALID_INFO_CLASS;
2408         }
2409
2410         return NT_STATUS_OK;
2411 }
2412
2413
2414 /*
2415   lsa_QueryTrustedDomainInfoBySid
2416 */
2417 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2418                                                 struct lsa_QueryTrustedDomainInfoBySid *r)
2419 {
2420         NTSTATUS status;
2421         struct lsa_OpenTrustedDomain opn = {{0},{0}};
2422         struct lsa_QueryTrustedDomainInfo query;
2423         struct dcesrv_handle *h;
2424
2425         opn.in.handle = r->in.handle;
2426         opn.in.sid = r->in.dom_sid;
2427         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2428         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2429         if (!opn.out.trustdom_handle) {
2430                 return NT_STATUS_NO_MEMORY;
2431         }
2432         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2433         if (!NT_STATUS_IS_OK(status)) {
2434                 return status;
2435         }
2436
2437         /* Ensure this handle goes away at the end of this call */
2438         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2439         talloc_steal(mem_ctx, h);
2440
2441         query.in.trustdom_handle = opn.out.trustdom_handle;
2442         query.in.level = r->in.level;
2443         query.out.info = r->out.info;
2444         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2445         if (!NT_STATUS_IS_OK(status)) {
2446                 return status;
2447         }
2448
2449         return NT_STATUS_OK;
2450 }
2451
2452 /*
2453   lsa_SetTrustedDomainInfoByName
2454 */
2455 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2456                                                TALLOC_CTX *mem_ctx,
2457                                                struct lsa_SetTrustedDomainInfoByName *r)
2458 {
2459         struct dcesrv_handle *policy_handle;
2460         struct lsa_policy_state *policy_state;
2461         struct ldb_message **msgs;
2462         NTSTATUS nt_status;
2463
2464         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2465         policy_state = policy_handle->data;
2466
2467         /* get the trusted domain object */
2468         nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2469                             policy_state->domain_dn,
2470                             r->in.trusted_domain->string,
2471                             r->in.trusted_domain->string,
2472                             NULL, &msgs);
2473         if (!NT_STATUS_IS_OK(nt_status)) {
2474                 if (NT_STATUS_EQUAL(nt_status,
2475                                     NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2476                         return nt_status;
2477                 }
2478                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2479         }
2480
2481         return setInfoTrustedDomain_base(dce_call, policy_state, mem_ctx,
2482                                          msgs[0], r->in.level, r->in.info);
2483 }
2484
2485 /*
2486    lsa_QueryTrustedDomainInfoByName
2487 */
2488 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2489                                                  TALLOC_CTX *mem_ctx,
2490                                                  struct lsa_QueryTrustedDomainInfoByName *r)
2491 {
2492         NTSTATUS status;
2493         struct lsa_OpenTrustedDomainByName opn = {{0},{0}};
2494         struct lsa_QueryTrustedDomainInfo query;
2495         struct dcesrv_handle *h;
2496
2497         opn.in.handle = r->in.handle;
2498         opn.in.name = *r->in.trusted_domain;
2499         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2500         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2501         if (!opn.out.trustdom_handle) {
2502                 return NT_STATUS_NO_MEMORY;
2503         }
2504         status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2505         if (!NT_STATUS_IS_OK(status)) {
2506                 return status;
2507         }
2508
2509         /* Ensure this handle goes away at the end of this call */
2510         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2511         talloc_steal(mem_ctx, h);
2512
2513         query.in.trustdom_handle = opn.out.trustdom_handle;
2514         query.in.level = r->in.level;
2515         query.out.info = r->out.info;
2516         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2517         if (!NT_STATUS_IS_OK(status)) {
2518                 return status;
2519         }
2520
2521         return NT_STATUS_OK;
2522 }
2523
2524 /*
2525   lsa_CloseTrustedDomainEx
2526 */
2527 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2528                                          TALLOC_CTX *mem_ctx,
2529                                          struct lsa_CloseTrustedDomainEx *r)
2530 {
2531         /* The result of a bad hair day from an IDL programmer?  Not
2532          * implmented in Win2k3.  You should always just lsa_Close
2533          * anyway. */
2534         return NT_STATUS_NOT_IMPLEMENTED;
2535 }
2536
2537
2538 /*
2539   comparison function for sorting lsa_DomainInformation array
2540 */
2541 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2542 {
2543         return strcasecmp_m(e1->name.string, e2->name.string);
2544 }
2545
2546 /*
2547   lsa_EnumTrustDom
2548 */
2549 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2550                                  struct lsa_EnumTrustDom *r)
2551 {
2552         struct dcesrv_handle *policy_handle;
2553         struct lsa_DomainInfo *entries;
2554         struct lsa_policy_state *policy_state;
2555         struct ldb_message **domains;
2556         const char *attrs[] = {
2557                 "flatname",
2558                 "securityIdentifier",
2559                 NULL
2560         };
2561
2562
2563         int count, i;
2564
2565         *r->out.resume_handle = 0;
2566
2567         r->out.domains->domains = NULL;
2568         r->out.domains->count = 0;
2569
2570         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2571
2572         policy_state = policy_handle->data;
2573
2574         /* search for all users in this domain. This could possibly be cached and
2575            resumed based on resume_key */
2576         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2577                              "objectclass=trustedDomain");
2578         if (count < 0) {
2579                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2580         }
2581
2582         /* convert to lsa_TrustInformation format */
2583         entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2584         if (!entries) {
2585                 return NT_STATUS_NO_MEMORY;
2586         }
2587         for (i=0;i<count;i++) {
2588                 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2589                 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2590         }
2591
2592         /* sort the results by name */
2593         TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2594
2595         if (*r->in.resume_handle >= count) {
2596                 *r->out.resume_handle = -1;
2597
2598                 return NT_STATUS_NO_MORE_ENTRIES;
2599         }
2600
2601         /* return the rest, limit by max_size. Note that we
2602            use the w2k3 element size value of 60 */
2603         r->out.domains->count = count - *r->in.resume_handle;
2604         r->out.domains->count = MIN(r->out.domains->count,
2605                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2606
2607         r->out.domains->domains = entries + *r->in.resume_handle;
2608
2609         if (r->out.domains->count < count - *r->in.resume_handle) {
2610                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2611                 return STATUS_MORE_ENTRIES;
2612         }
2613
2614         /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2615          * always be larger than the previous input resume handle, in
2616          * particular when hitting the last query it is vital to set the
2617          * resume handle correctly to avoid infinite client loops, as
2618          * seen e.g. with Windows XP SP3 when resume handle is 0 and
2619          * status is NT_STATUS_OK - gd */
2620
2621         *r->out.resume_handle = (uint32_t)-1;
2622
2623         return NT_STATUS_OK;
2624 }
2625
2626 /*
2627   comparison function for sorting lsa_DomainInformation array
2628 */
2629 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2630 {
2631         return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2632 }
2633
2634 /*
2635   lsa_EnumTrustedDomainsEx
2636 */
2637 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2638                                         struct lsa_EnumTrustedDomainsEx *r)
2639 {
2640         struct dcesrv_handle *policy_handle;
2641         struct lsa_TrustDomainInfoInfoEx *entries;
2642         struct lsa_policy_state *policy_state;
2643         struct ldb_message **domains;
2644         const char *attrs[] = {
2645                 "flatname",
2646                 "trustPartner",
2647                 "securityIdentifier",
2648                 "trustDirection",
2649                 "trustType",
2650                 "trustAttributes",
2651                 NULL
2652         };
2653         NTSTATUS nt_status;
2654
2655         int count, i;
2656
2657         *r->out.resume_handle = 0;
2658
2659         r->out.domains->domains = NULL;
2660         r->out.domains->count = 0;
2661
2662         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2663
2664         policy_state = policy_handle->data;
2665
2666         /* search for all users in this domain. This could possibly be cached and
2667            resumed based on resume_key */
2668         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2669                              "objectclass=trustedDomain");
2670         if (count < 0) {
2671                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2672         }
2673
2674         /* convert to lsa_DomainInformation format */
2675         entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2676         if (!entries) {
2677                 return NT_STATUS_NO_MEMORY;
2678         }
2679         for (i=0;i<count;i++) {
2680                 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2681                 if (!NT_STATUS_IS_OK(nt_status)) {
2682                         return nt_status;
2683                 }
2684         }
2685
2686         /* sort the results by name */
2687         TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2688
2689         if (*r->in.resume_handle >= count) {
2690                 *r->out.resume_handle = -1;
2691
2692                 return NT_STATUS_NO_MORE_ENTRIES;
2693         }
2694
2695         /* return the rest, limit by max_size. Note that we
2696            use the w2k3 element size value of 60 */
2697         r->out.domains->count = count - *r->in.resume_handle;
2698         r->out.domains->count = MIN(r->out.domains->count,
2699                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2700
2701         r->out.domains->domains = entries + *r->in.resume_handle;
2702
2703         if (r->out.domains->count < count - *r->in.resume_handle) {
2704                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2705                 return STATUS_MORE_ENTRIES;
2706         }
2707
2708         *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2709
2710         return NT_STATUS_OK;
2711 }
2712
2713
2714 /*
2715   lsa_OpenAccount
2716 */
2717 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2718                                 struct lsa_OpenAccount *r)
2719 {
2720         struct dcesrv_handle *h, *ah;
2721         struct lsa_policy_state *state;
2722         struct lsa_account_state *astate;
2723
2724         ZERO_STRUCTP(r->out.acct_handle);
2725
2726         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2727
2728         state = h->data;
2729
2730         astate = talloc(dce_call->conn, struct lsa_account_state);
2731         if (astate == NULL) {
2732                 return NT_STATUS_NO_MEMORY;
2733         }
2734
2735         astate->account_sid = dom_sid_dup(astate, r->in.sid);
2736         if (astate->account_sid == NULL) {
2737                 talloc_free(astate);
2738                 return NT_STATUS_NO_MEMORY;
2739         }
2740
2741         astate->policy = talloc_reference(astate, state);
2742         astate->access_mask = r->in.access_mask;
2743
2744         /*
2745          * For now we grant all requested access.
2746          *
2747          * We will fail at the ldb layer later.
2748          */
2749         if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
2750                 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
2751                 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
2752         }
2753         se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
2754
2755         DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X] - success.\n",
2756                   __func__, dom_sid_string(mem_ctx, astate->account_sid),
2757                  (unsigned)r->in.access_mask,
2758                  (unsigned)astate->access_mask));
2759
2760         ah = dcesrv_handle_create(dce_call, LSA_HANDLE_ACCOUNT);
2761         if (!ah) {
2762                 talloc_free(astate);
2763                 return NT_STATUS_NO_MEMORY;
2764         }
2765
2766         ah->data = talloc_steal(ah, astate);
2767
2768         *r->out.acct_handle = ah->wire_handle;
2769
2770         return NT_STATUS_OK;
2771 }
2772
2773
2774 /*
2775   lsa_EnumPrivsAccount
2776 */
2777 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2778                                      TALLOC_CTX *mem_ctx,
2779                                      struct lsa_EnumPrivsAccount *r)
2780 {
2781         struct dcesrv_handle *h;
2782         struct lsa_account_state *astate;
2783         int ret;
2784         unsigned int i, j;
2785         struct ldb_message **res;
2786         const char * const attrs[] = { "privilege", NULL};
2787         struct ldb_message_element *el;
2788         const char *sidstr;
2789         struct lsa_PrivilegeSet *privs;
2790
2791         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2792
2793         astate = h->data;
2794
2795         privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2796         if (privs == NULL) {
2797                 return NT_STATUS_NO_MEMORY;
2798         }
2799         privs->count = 0;
2800         privs->unknown = 0;
2801         privs->set = NULL;
2802
2803         *r->out.privs = privs;
2804
2805         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2806         if (sidstr == NULL) {
2807                 return NT_STATUS_NO_MEMORY;
2808         }
2809
2810         ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2811                            "objectSid=%s", sidstr);
2812         if (ret < 0) {
2813                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2814         }
2815         if (ret != 1) {
2816                 return NT_STATUS_OK;
2817         }
2818
2819         el = ldb_msg_find_element(res[0], "privilege");
2820         if (el == NULL || el->num_values == 0) {
2821                 return NT_STATUS_OK;
2822         }
2823
2824         privs->set = talloc_array(privs,
2825                                   struct lsa_LUIDAttribute, el->num_values);
2826         if (privs->set == NULL) {
2827                 return NT_STATUS_NO_MEMORY;
2828         }
2829
2830         j = 0;
2831         for (i=0;i<el->num_values;i++) {
2832                 int id = sec_privilege_id((const char *)el->values[i].data);
2833                 if (id == SEC_PRIV_INVALID) {
2834                         /* Perhaps an account right, not a privilege */
2835                         continue;
2836                 }
2837                 privs->set[j].attribute = 0;
2838                 privs->set[j].luid.low = id;
2839                 privs->set[j].luid.high = 0;
2840                 j++;
2841         }
2842
2843         privs->count = j;
2844
2845         return NT_STATUS_OK;
2846 }
2847
2848 /*
2849   lsa_EnumAccountRights
2850 */
2851 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2852                                       TALLOC_CTX *mem_ctx,
2853                                       struct lsa_EnumAccountRights *r)
2854 {
2855         struct dcesrv_handle *h;
2856         struct lsa_policy_state *state;
2857         int ret;
2858         unsigned int i;
2859         struct ldb_message **res;
2860         const char * const attrs[] = { "privilege", NULL};
2861         const char *sidstr;
2862         struct ldb_message_element *el;
2863
2864         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2865
2866         state = h->data;
2867
2868         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2869         if (sidstr == NULL) {
2870                 return NT_STATUS_NO_MEMORY;
2871         }
2872
2873         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2874                            "(&(objectSid=%s)(privilege=*))", sidstr);
2875         if (ret == 0) {
2876                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2877         }
2878         if (ret != 1) {
2879                 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2880                           dom_sid_string(mem_ctx, r->in.sid),
2881                           ldb_errstring(state->pdb)));
2882                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2883         }
2884
2885         el = ldb_msg_find_element(res[0], "privilege");
2886         if (el == NULL || el->num_values == 0) {
2887                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2888         }
2889
2890         r->out.rights->count = el->num_values;
2891         r->out.rights->names = talloc_array(r->out.rights,
2892                                             struct lsa_StringLarge, r->out.rights->count);
2893         if (r->out.rights->names == NULL) {
2894                 return NT_STATUS_NO_MEMORY;
2895         }
2896
2897         for (i=0;i<el->num_values;i++) {
2898                 r->out.rights->names[i].string = (const char *)el->values[i].data;
2899         }
2900
2901         return NT_STATUS_OK;
2902 }
2903
2904
2905
2906 /*
2907   helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2908 */
2909 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2910                                            TALLOC_CTX *mem_ctx,
2911                                            struct lsa_policy_state *state,
2912                                            int ldb_flag,
2913                                            struct dom_sid *sid,
2914                                            const struct lsa_RightSet *rights)
2915 {
2916         struct auth_session_info *session_info =
2917                 dcesrv_call_session_info(dce_call);
2918         const char *sidstr, *sidndrstr;
2919         struct ldb_message *msg;
2920         struct ldb_message_element *el;
2921         int ret;
2922         uint32_t i;
2923         struct lsa_EnumAccountRights r2;
2924         char *dnstr;
2925
2926         if (security_session_user_level(session_info, NULL) <
2927             SECURITY_ADMINISTRATOR) {
2928                 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2929                 return NT_STATUS_ACCESS_DENIED;
2930         }
2931
2932         msg = ldb_msg_new(mem_ctx);
2933         if (msg == NULL) {
2934                 return NT_STATUS_NO_MEMORY;
2935         }
2936
2937         sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2938         if (sidndrstr == NULL) {
2939                 TALLOC_FREE(msg);
2940                 return NT_STATUS_NO_MEMORY;
2941         }
2942
2943         sidstr = dom_sid_string(msg, sid);
2944         if (sidstr == NULL) {
2945                 TALLOC_FREE(msg);
2946                 return NT_STATUS_NO_MEMORY;
2947         }
2948
2949         dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2950         if (dnstr == NULL) {
2951                 TALLOC_FREE(msg);
2952                 return NT_STATUS_NO_MEMORY;
2953         }
2954
2955         msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2956         if (msg->dn == NULL) {
2957                 TALLOC_FREE(msg);
2958                 return NT_STATUS_NO_MEMORY;
2959         }
2960
2961         if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2962                 NTSTATUS status;
2963
2964                 r2.in.handle = &state->handle->wire_handle;
2965                 r2.in.sid = sid;
2966                 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2967
2968                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2969                 if (!NT_STATUS_IS_OK(status)) {
2970                         ZERO_STRUCTP(r2.out.rights);
2971                 }
2972         }
2973
2974         for (i=0;i<rights->count;i++) {
2975                 bool ok;
2976
2977                 ok = dcesrc_lsa_valid_AccountRight(rights->names[i].string);
2978                 if (!ok) {
2979                         talloc_free(msg);
2980                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2981                 }
2982
2983                 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2984                         uint32_t j;
2985                         for (j=0;j<r2.out.rights->count;j++) {
2986                                 if (strcasecmp_m(r2.out.rights->names[j].string,
2987                                                rights->names[i].string) == 0) {
2988                                         break;
2989                                 }
2990                         }
2991                         if (j != r2.out.rights->count) continue;
2992                 }
2993
2994                 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2995                 if (ret != LDB_SUCCESS) {
2996                         talloc_free(msg);
2997                         return NT_STATUS_NO_MEMORY;
2998                 }
2999         }
3000
3001         el = ldb_msg_find_element(msg, "privilege");
3002         if (!el) {
3003                 talloc_free(msg);
3004                 return NT_STATUS_OK;
3005         }
3006
3007         el->flags = ldb_flag;
3008
3009         ret = ldb_modify(state->pdb, msg);
3010         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
3011                 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
3012                         talloc_free(msg);
3013                         return NT_STATUS_NO_MEMORY;
3014                 }
3015                 ldb_msg_add_string(msg, "comment", "added via LSA");
3016                 ret = ldb_add(state->pdb, msg);
3017         }
3018         if (ret != LDB_SUCCESS) {
3019                 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
3020                         talloc_free(msg);
3021                         return NT_STATUS_OK;
3022                 }
3023                 DEBUG(3, ("Could not %s attributes from %s: %s",
3024                           LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
3025                           ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
3026                 talloc_free(msg);
3027                 return NT_STATUS_UNEXPECTED_IO_ERROR;
3028         }
3029
3030         talloc_free(msg);
3031         return NT_STATUS_OK;
3032 }
3033
3034 /*
3035   lsa_AddPrivilegesToAccount
3036 */
3037 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3038                                            struct lsa_AddPrivilegesToAccount *r)
3039 {
3040         struct lsa_RightSet rights;
3041         struct dcesrv_handle *h;
3042         struct lsa_account_state *astate;
3043         uint32_t i;
3044
3045         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3046
3047         astate = h->data;
3048
3049         rights.count = r->in.privs->count;
3050         rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
3051         if (rights.names == NULL) {
3052                 return NT_STATUS_NO_MEMORY;
3053         }
3054         for (i=0;i<rights.count;i++) {
3055                 int id = r->in.privs->set[i].luid.low;
3056                 if (r->in.privs->set[i].luid.high) {
3057                         return NT_STATUS_NO_SUCH_PRIVILEGE;
3058                 }
3059                 rights.names[i].string = sec_privilege_name(id);
3060                 if (rights.names[i].string == NULL) {
3061                         return NT_STATUS_NO_SUCH_PRIVILEGE;
3062                 }
3063         }
3064
3065         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3066                                           LDB_FLAG_MOD_ADD, astate->account_sid,
3067                                           &rights);
3068 }
3069
3070
3071 /*
3072   lsa_RemovePrivilegesFromAccount
3073 */
3074 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3075                                                 struct lsa_RemovePrivilegesFromAccount *r)
3076 {
3077         struct lsa_RightSet *rights;
3078         struct dcesrv_handle *h;
3079         struct lsa_account_state *astate;
3080         uint32_t i;
3081
3082         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3083
3084         astate = h->data;
3085
3086         rights = talloc(mem_ctx, struct lsa_RightSet);
3087
3088         if (r->in.remove_all == 1 &&
3089             r->in.privs == NULL) {
3090                 struct lsa_EnumAccountRights r2;
3091                 NTSTATUS status;
3092
3093                 r2.in.handle = &astate->policy->handle->wire_handle;
3094                 r2.in.sid = astate->account_sid;
3095                 r2.out.rights = rights;
3096
3097                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
3098                 if (!NT_STATUS_IS_OK(status)) {
3099                         return status;
3100                 }
3101
3102                 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3103                                                   LDB_FLAG_MOD_DELETE, astate->account_sid,
3104                                                   r2.out.rights);
3105         }
3106
3107         if (r->in.remove_all != 0) {
3108                 return NT_STATUS_INVALID_PARAMETER;
3109         }
3110
3111         rights->count = r->in.privs->count;
3112         rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
3113         if (rights->names == NULL) {
3114                 return NT_STATUS_NO_MEMORY;
3115         }
3116         for (i=0;i<rights->count;i++) {
3117                 int id = r->in.privs->set[i].luid.low;
3118                 if (r->in.privs->set[i].luid.high) {
3119                         return NT_STATUS_NO_SUCH_PRIVILEGE;
3120                 }
3121                 rights->names[i].string = sec_privilege_name(id);
3122                 if (rights->names[i].string == NULL) {
3123                         return NT_STATUS_NO_SUCH_PRIVILEGE;
3124                 }
3125         }
3126
3127         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3128                                           LDB_FLAG_MOD_DELETE, astate->account_sid,
3129                                           rights);
3130 }
3131
3132
3133 /*
3134   lsa_GetQuotasForAccount
3135 */
3136 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3137                        struct lsa_GetQuotasForAccount *r)
3138 {
3139         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3140 }
3141
3142
3143 /*
3144   lsa_SetQuotasForAccount
3145 */
3146 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3147                        struct lsa_SetQuotasForAccount *r)
3148 {
3149         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3150 }
3151
3152
3153 /*
3154   lsa_GetSystemAccessAccount
3155 */
3156 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3157                        struct lsa_GetSystemAccessAccount *r)
3158 {
3159         struct dcesrv_handle *h;
3160         struct lsa_account_state *astate;
3161         int ret;
3162         unsigned int i;
3163         struct ldb_message **res;
3164         const char * const attrs[] = { "privilege", NULL};
3165         struct ldb_message_element *el;
3166         const char *sidstr;
3167
3168         *(r->out.access_mask) = 0x00000000;
3169
3170         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3171
3172         astate = h->data;
3173
3174         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
3175         if (sidstr == NULL) {
3176                 return NT_STATUS_NO_MEMORY;
3177         }
3178
3179         ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
3180                            "objectSid=%s", sidstr);
3181         if (ret < 0) {
3182                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3183         }
3184         if (ret != 1) {
3185                 return NT_STATUS_OK;
3186         }
3187
3188         el = ldb_msg_find_element(res[0], "privilege");
3189         if (el == NULL || el->num_values == 0) {
3190                 return NT_STATUS_OK;
3191         }
3192
3193         for (i=0;i<el->num_values;i++) {
3194                 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
3195                 if (right_bit == 0) {
3196                         /* Perhaps an privilege, not a right */
3197                         continue;
3198                 }
3199                 *(r->out.access_mask) |= right_bit;
3200         }
3201
3202         return NT_STATUS_OK;
3203 }
3204
3205
3206 /*
3207   lsa_SetSystemAccessAccount
3208 */
3209 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3210                        struct lsa_SetSystemAccessAccount *r)
3211 {
3212         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3213 }
3214 /*
3215   lsa_CreateSecret
3216 */
3217 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3218                                  struct lsa_CreateSecret *r)
3219 {
3220         struct auth_session_info *session_info =
3221                 dcesrv_call_session_info(dce_call);
3222         struct dcesrv_handle *policy_handle;
3223         struct lsa_policy_state *policy_state;
3224         struct lsa_secret_state *secret_state;
3225         struct dcesrv_handle *handle;
3226         struct ldb_message **msgs, *msg;
3227         const char *attrs[] = {
3228                 NULL
3229         };
3230
3231         const char *name;
3232
3233         int ret;
3234
3235         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3236         ZERO_STRUCTP(r->out.sec_handle);
3237
3238         switch (security_session_user_level(session_info, NULL))
3239         {
3240         case SECURITY_SYSTEM:
3241         case SECURITY_ADMINISTRATOR:
3242                 break;
3243         default:
3244                 /* Users and annonymous are not allowed create secrets */
3245                 return NT_STATUS_ACCESS_DENIED;
3246         }
3247
3248         policy_state = policy_handle->data;
3249
3250         if (!r->in.name.string) {
3251                 return NT_STATUS_INVALID_PARAMETER;
3252         }
3253
3254         secret_state = talloc(mem_ctx, struct lsa_secret_state);
3255         NT_STATUS_HAVE_NO_MEMORY(secret_state);
3256         secret_state->policy = policy_state;
3257
3258         msg = ldb_msg_new(mem_ctx);
3259         if (msg == NULL) {
3260                 return NT_STATUS_NO_MEMORY;
3261         }
3262
3263         if (strncmp("G$", r->in.name.string, 2) == 0) {
3264                 const char *name2;
3265
3266                 secret_state->global = true;
3267
3268                 name = &r->in.name.string[2];
3269                 if (strlen(name) == 0) {
3270                         return NT_STATUS_INVALID_PARAMETER;
3271                 }
3272
3273                 name2 = talloc_asprintf(mem_ctx, "%s Secret",
3274                                         ldb_binary_encode_string(mem_ctx, name));
3275                 NT_STATUS_HAVE_NO_MEMORY(name2);
3276
3277                 /*
3278                  * We need to connect to the database as system, as this is
3279                  * one of the rare RPC calls that must read the secrets
3280                  * (and this is denied otherwise)
3281                  *
3282                  * We also save the current remote session details so they can
3283                  * used by the audit logging module. This allows the audit
3284                  * logging to report the remote users details, rather than the
3285                  * system users details.
3286                  */
3287                 secret_state->sam_ldb =
3288                         dcesrv_samdb_connect_as_system(secret_state, dce_call);
3289                 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3290
3291                 /* search for the secret record */
3292                 ret = gendb_search(secret_state->sam_ldb,
3293                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
3294                                    "(&(cn=%s)(objectclass=secret))",
3295                                    name2);
3296                 if (ret > 0) {
3297                         return NT_STATUS_OBJECT_NAME_COLLISION;
3298                 }
3299
3300                 if (ret < 0) {
3301                         DEBUG(0,("Failure searching for CN=%s: %s\n",
3302                                  name2, ldb_errstring(secret_state->sam_ldb)));
3303                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3304                 }
3305
3306                 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
3307                 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3308                 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
3309                         return NT_STATUS_NO_MEMORY;
3310                 }
3311
3312                 ret = ldb_msg_add_string(msg, "cn", name2);
3313                 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3314         } else {
3315                 secret_state->global = false;
3316
3317                 name = r->in.name.string;
3318                 if (strlen(name) == 0) {
3319                         return NT_STATUS_INVALID_PARAMETER;
3320                 }
3321
3322                 secret_state->sam_ldb = secrets_db_connect(secret_state,
3323                                         dce_call->conn->dce_ctx->lp_ctx);
3324                 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3325
3326                 /* search for the secret record */
3327                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3328                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3329                                    &msgs, attrs,
3330                                    "(&(cn=%s)(objectclass=secret))",
3331                                    ldb_binary_encode_string(mem_ctx, name));
3332                 if (ret > 0) {
3333                         return NT_STATUS_OBJECT_NAME_COLLISION;
3334                 }
3335
3336                 if (ret < 0) {
3337                         DEBUG(0,("Failure searching for CN=%s: %s\n",
3338                                  name, ldb_errstring(secret_state->sam_ldb)));
3339                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3340                 }
3341
3342                 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
3343                                          "cn=%s,cn=LSA Secrets", name);
3344                 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3345                 ret = ldb_msg_add_string(msg, "cn", name);
3346                 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3347         }
3348
3349         ret = ldb_msg_add_string(msg, "objectClass", "secret");
3350         if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3351
3352         secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3353         NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3354
3355         /* create the secret */
3356         ret = ldb_add(secret_state->sam_ldb, msg);
3357         if (ret != LDB_SUCCESS) {
3358                 DEBUG(0,("Failed to create secret record %s: %s\n",
3359                          ldb_dn_get_linearized(msg->dn),
3360                          ldb_errstring(secret_state->sam_ldb)));
3361                 return NT_STATUS_ACCESS_DENIED;
3362         }
3363
3364         handle = dcesrv_handle_create(dce_call, LSA_HANDLE_SECRET);
3365         NT_STATUS_HAVE_NO_MEMORY(handle);
3366
3367         handle->data = talloc_steal(handle, secret_state);
3368
3369         secret_state->access_mask = r->in.access_mask;
3370         secret_state->policy = talloc_reference(secret_state, policy_state);
3371         NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3372
3373         *r->out.sec_handle = handle->wire_handle;
3374
3375         return NT_STATUS_OK;
3376 }
3377
3378
3379 /*
3380   lsa_OpenSecret
3381 */
3382 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3383                                struct lsa_OpenSecret *r)
3384 {
3385         struct auth_session_info *session_info =
3386                 dcesrv_call_session_info(dce_call);
3387         struct dcesrv_handle *policy_handle;
3388         struct lsa_policy_state *policy_state;
3389         struct lsa_secret_state *secret_state;
3390         struct dcesrv_handle *handle;
3391         struct ldb_message **msgs;
3392         const char *attrs[] = {
3393                 NULL
3394         };
3395         const char *name;
3396         int ret;
3397
3398         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3399         ZERO_STRUCTP(r->out.sec_handle);
3400         policy_state = policy_handle->data;
3401
3402         if (!r->in.name.string) {
3403                 return NT_STATUS_INVALID_PARAMETER;
3404         }
3405
3406         switch (security_session_user_level(session_info, NULL))
3407         {
3408         case SECURITY_SYSTEM:
3409         case SECURITY_ADMINISTRATOR:
3410                 break;
3411         default:
3412                 /* Users and annonymous are not allowed to access secrets */
3413                 return NT_STATUS_ACCESS_DENIED;
3414         }
3415
3416         secret_state = talloc(mem_ctx, struct lsa_secret_state);
3417         if (!secret_state) {
3418                 return NT_STATUS_NO_MEMORY;
3419         }
3420         secret_state->policy = policy_state;
3421
3422         if (strncmp("G$", r->in.name.string, 2) == 0) {
3423                 name = &r->in.name.string[2];
3424                 /*
3425                  * We need to connect to the database as system, as this is
3426                  * one of the rare RPC calls that must read the secrets
3427                  * (and this is denied otherwise)
3428                  *
3429                  * We also save the current remote session details so they can
3430                  * used by the audit logging module. This allows the audit
3431                  * logging to report the remote users details, rather than the
3432                  * system users details.
3433                  */
3434                 secret_state->sam_ldb =
3435                         dcesrv_samdb_connect_as_system(secret_state, dce_call);
3436                 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3437                 secret_state->global = true;
3438
3439                 if (strlen(name) < 1) {
3440                         return NT_STATUS_INVALID_PARAMETER;
3441                 }
3442
3443                 /* search for the secret record */
3444                 ret = gendb_search(secret_state->sam_ldb,
3445                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
3446                                    "(&(cn=%s Secret)(objectclass=secret))",
3447                                    ldb_binary_encode_string(mem_ctx, name));
3448                 if (ret == 0) {
3449                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3450                 }
3451
3452                 if (ret != 1) {
3453                         DEBUG(0,("Found %d records matching DN %s\n", ret,
3454                                  ldb_dn_get_linearized(policy_state->system_dn)));
3455                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3456                 }
3457         } else {
3458                 secret_state->global = false;
3459                 secret_state->sam_ldb = secrets_db_connect(secret_state,
3460                                         dce_call->conn->dce_ctx->lp_ctx);
3461                 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3462
3463                 name = r->in.name.string;
3464                 if (strlen(name) < 1) {
3465                         return NT_STATUS_INVALID_PARAMETER;
3466                 }
3467
3468                 /* search for the secret record */
3469                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3470                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3471                                    &msgs, attrs,
3472                                    "(&(cn=%s)(objectclass=secret))",
3473                                    ldb_binary_encode_string(mem_ctx, name));
3474                 if (ret == 0) {
3475                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3476                 }
3477
3478                 if (ret != 1) {
3479                         DEBUG(0,("Found %d records matching CN=%s\n",
3480                                  ret, ldb_binary_encode_string(mem_ctx, name)));
3481                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3482                 }
3483         }
3484
3485         secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3486
3487         handle = dcesrv_handle_create(dce_call, LSA_HANDLE_SECRET);
3488         if (!handle) {
3489                 return NT_STATUS_NO_MEMORY;
3490         }
3491
3492         handle->data = talloc_steal(handle, secret_state);
3493
3494         secret_state->access_mask = r->in.access_mask;
3495         secret_state->policy = talloc_reference(secret_state, policy_state);
3496
3497         *r->out.sec_handle = handle->wire_handle;
3498
3499         return NT_STATUS_OK;
3500 }
3501
3502
3503 /*
3504   lsa_SetSecret
3505 */
3506 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3507                               struct lsa_SetSecret *r)
3508 {
3509
3510         struct dcesrv_handle *h;
3511         struct lsa_secret_state *secret_state;
3512         struct ldb_message *msg;
3513         DATA_BLOB session_key;
3514         DATA_BLOB crypt_secret, secret;
3515         struct ldb_val val;
3516         int ret;
3517         NTSTATUS status = NT_STATUS_OK;
3518
3519         struct timeval now = timeval_current();
3520         NTTIME nt_now = timeval_to_nttime(&now);
3521
3522         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3523
3524         secret_state = h->data;
3525
3526         msg = ldb_msg_new(mem_ctx);
3527         if (msg == NULL) {
3528                 return NT_STATUS_NO_MEMORY;
3529         }
3530
3531         msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3532         if (!msg->dn) {
3533                 return NT_STATUS_NO_MEMORY;
3534         }
3535         status = dcesrv_transport_session_key(dce_call, &session_key);
3536         if (!NT_STATUS_IS_OK(status)) {
3537                 return status;
3538         }
3539
3540         if (r->in.old_val) {
3541                 /* Decrypt */
3542                 crypt_secret.data = r->in.old_val->data;
3543                 crypt_secret.length = r->in.old_val->size;
3544
3545                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3546                 if (!NT_STATUS_IS_OK(status)) {
3547                         return status;
3548                 }
3549
3550                 val.data = secret.data;
3551                 val.length = secret.length;
3552
3553                 /* set value */
3554                 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3555                         return NT_STATUS_NO_MEMORY;
3556                 }
3557
3558                 /* set old value mtime */
3559                 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3560                                          mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3561                         return NT_STATUS_NO_MEMORY;
3562                 }
3563
3564         } else {
3565                 /* If the old value is not set, then migrate the
3566                  * current value to the old value */
3567                 const struct ldb_val *old_val;
3568                 NTTIME last_set_time;
3569                 struct ldb_message **res;
3570                 const char *attrs[] = {
3571                         "currentValue",
3572                         "lastSetTime",
3573                         NULL
3574                 };
3575
3576                 /* search for the secret record */
3577                 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3578                                       secret_state->secret_dn, &res, attrs);
3579                 if (ret == 0) {
3580                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3581                 }
3582
3583                 if (ret != 1) {
3584                         DEBUG(0,("Found %d records matching dn=%s\n", ret,
3585                                  ldb_dn_get_linearized(secret_state->secret_dn)));
3586                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3587                 }
3588
3589                 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3590                 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3591
3592                 if (old_val) {
3593                         /* set old value */
3594                         if (ldb_msg_add_value(msg, "priorValue",
3595                                               old_val, NULL) != LDB_SUCCESS) {
3596                                 return NT_STATUS_NO_MEMORY;
3597                         }
3598                 } else {
3599                         if (samdb_msg_add_delete(secret_state->sam_ldb,
3600                                                  mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3601                                 return NT_STATUS_NO_MEMORY;
3602                         }
3603                 }
3604
3605                 /* set old value mtime */
3606                 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3607                         if (samdb_msg_add_uint64(secret_state->sam_ldb,
3608                                                  mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3609                                 return NT_STATUS_NO_MEMORY;
3610                         }
3611                 } else {
3612                         if (samdb_msg_add_uint64(secret_state->sam_ldb,
3613                                                  mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3614                                 return NT_STATUS_NO_MEMORY;
3615                         }
3616                 }
3617         }
3618
3619         if (r->in.new_val) {
3620                 /* Decrypt */
3621                 crypt_secret.data = r->in.new_val->data;
3622                 crypt_secret.length = r->in.new_val->size;
3623
3624                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3625                 if (!NT_STATUS_IS_OK(status)) {
3626                         return status;
3627                 }
3628
3629                 val.data = secret.data;
3630                 val.length = secret.length;
3631
3632                 /* set value */
3633                 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3634                         return NT_STATUS_NO_MEMORY;
3635                 }
3636
3637                 /* set new value mtime */
3638                 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3639                                          mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3640                         return NT_STATUS_NO_MEMORY;
3641                 }
3642         } else {
3643                 /* NULL out the NEW value */
3644                 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3645                                          mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3646                         return NT_STATUS_NO_MEMORY;
3647                 }
3648                 if (samdb_msg_add_delete(secret_state->sam_ldb,
3649                                          mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3650                         return NT_STATUS_NO_MEMORY;
3651                 }
3652         }
3653
3654         /* modify the samdb record */
3655         ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3656         if (ret != LDB_SUCCESS) {
3657                 return dsdb_ldb_err_to_ntstatus(ret);
3658         }
3659
3660         return NT_STATUS_OK;
3661 }
3662
3663
3664 /*
3665   lsa_QuerySecret
3666 */
3667 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3668                                 struct lsa_QuerySecret *r)
3669 {
3670         struct auth_session_info *session_info =
3671                 dcesrv_call_session_info(dce_call);
3672         struct dcesrv_handle *h;
3673         struct lsa_secret_state *secret_state;
3674         struct ldb_message *msg;
3675         DATA_BLOB session_key;
3676         DATA_BLOB crypt_secret, secret;
3677         int ret;
3678         struct ldb_message **res;
3679         const char *attrs[] = {
3680                 "currentValue",
3681                 "priorValue",
3682                 "lastSetTime",
3683                 "priorSetTime",
3684                 NULL
3685         };
3686
3687         NTSTATUS nt_status;
3688
3689         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3690
3691         /* Ensure user is permitted to read this... */
3692         switch (security_session_user_level(session_info, NULL))
3693         {
3694         case SECURITY_SYSTEM:
3695         case SECURITY_ADMINISTRATOR:
3696                 break;
3697         default:
3698                 /* Users and annonymous are not allowed to read secrets */
3699                 return NT_STATUS_ACCESS_DENIED;
3700         }
3701
3702         secret_state = h->data;
3703
3704         /* pull all the user attributes */
3705         ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3706                               secret_state->secret_dn, &res, attrs);
3707         if (ret != 1) {
3708                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3709         }
3710         msg = res[0];
3711
3712         nt_status = dcesrv_transport_session_key(dce_call, &session_key);
3713         if (!NT_STATUS_IS_OK(nt_status)) {
3714                 return nt_status;
3715         }
3716
3717         if (r->in.old_val) {
3718                 const struct ldb_val *prior_val;
3719                 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3720                 if (!r->out.old_val) {
3721                         return NT_STATUS_NO_MEMORY;
3722                 }
3723                 prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3724
3725                 if (prior_val && prior_val->length) {
3726                         secret.data = prior_val->data;
3727                         secret.length = prior_val->length;
3728
3729                         /* Encrypt */
3730                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3731                         if (!crypt_secret.length) {
3732                                 return NT_STATUS_NO_MEMORY;
3733                         }
3734                         r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3735                         if (!r->out.old_val->buf) {
3736                                 return NT_STATUS_NO_MEMORY;
3737                         }
3738                         r->out.old_val->buf->size = crypt_secret.length;
3739                         r->out.old_val->buf->length = crypt_secret.length;
3740                         r->out.old_val->buf->data = crypt_secret.data;
3741                 }
3742         }
3743
3744         if (r->in.old_mtime) {
3745                 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3746                 if (!r->out.old_mtime) {
3747                         return NT_STATUS_NO_MEMORY;
3748                 }
3749                 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3750         }
3751
3752         if (r->in.new_val) {
3753                 const struct ldb_val *new_val;
3754                 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3755                 if (!r->out.new_val) {
3756                         return NT_STATUS_NO_MEMORY;
3757                 }
3758
3759                 new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3760
3761                 if (new_val && new_val->length) {
3762                         secret.data = new_val->data;
3763                         secret.length = new_val->length;
3764
3765                         /* Encrypt */
3766                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3767                         if (!crypt_secret.length) {
3768                                 return NT_STATUS_NO_MEMORY;
3769                         }
3770                         r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3771                         if (!r->out.new_val->buf) {
3772                                 return NT_STATUS_NO_MEMORY;
3773                         }
3774                         r->out.new_val->buf->length = crypt_secret.length;
3775                         r->out.new_val->buf->size = crypt_secret.length;
3776                         r->out.new_val->buf->data = crypt_secret.data;
3777                 }
3778         }
3779
3780         if (r->in.new_mtime) {
3781                 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3782                 if (!r->out.new_mtime) {
3783                         return NT_STATUS_NO_MEMORY;
3784                 }
3785                 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3786         }
3787
3788         return NT_STATUS_OK;
3789 }
3790
3791
3792 /*
3793   lsa_LookupPrivValue
3794 */
3795 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3796                                     TALLOC_CTX *mem_ctx,
3797                                     struct lsa_LookupPrivValue *r)
3798 {
3799         struct dcesrv_handle *h;
3800         int id;
3801
3802         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3803
3804         id = sec_privilege_id(r->in.name->string);
3805         if (id == SEC_PRIV_INVALID) {
3806                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3807         }
3808
3809         r->out.luid->low = id;
3810         r->out.luid->high = 0;
3811
3812         return NT_STATUS_OK;
3813 }
3814
3815
3816 /*
3817   lsa_LookupPrivName
3818 */
3819 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3820                                    TALLOC_CTX *mem_ctx,
3821                                    struct lsa_LookupPrivName *r)
3822 {
3823         struct dcesrv_handle *h;
3824         struct lsa_StringLarge *name;
3825         const char *privname;
3826
3827         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3828
3829         if (r->in.luid->high != 0) {
3830                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3831         }
3832
3833         privname = sec_privilege_name(r->in.luid->low);
3834         if (privname == NULL) {
3835                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3836         }
3837
3838         name = talloc(mem_ctx, struct lsa_StringLarge);
3839         if (name == NULL) {
3840                 return NT_STATUS_NO_MEMORY;
3841         }
3842
3843         name->string = privname;
3844
3845         *r->out.name = name;
3846
3847         return NT_STATUS_OK;
3848 }
3849
3850
3851 /*
3852   lsa_LookupPrivDisplayName
3853 */
3854 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3855                                           TALLOC_CTX *mem_ctx,
3856                                           struct lsa_LookupPrivDisplayName *r)
3857 {
3858         struct dcesrv_handle *h;
3859         struct lsa_StringLarge *disp_name = NULL;
3860         enum sec_privilege id;
3861
3862         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3863
3864         id = sec_privilege_id(r->in.name->string);
3865         if (id == SEC_PRIV_INVALID) {
3866                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3867         }
3868
3869         disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3870         if (disp_name == NULL) {
3871                 return NT_STATUS_NO_MEMORY;
3872         }
3873
3874         disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3875         if (disp_name->string == NULL) {
3876                 return NT_STATUS_INTERNAL_ERROR;
3877         }
3878
3879         *r->out.disp_name = disp_name;
3880         *r->out.returned_language_id = 0;
3881
3882         return NT_STATUS_OK;
3883 }
3884
3885
3886 /*
3887   lsa_EnumAccountsWithUserRight
3888 */
3889 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3890                                               TALLOC_CTX *mem_ctx,
3891                                               struct lsa_EnumAccountsWithUserRight *r)
3892 {
3893         struct dcesrv_handle *h;
3894         struct lsa_policy_state *state;
3895         int ret, i;
3896         struct ldb_message **res;
3897         const char * const attrs[] = { "objectSid", NULL};
3898         const char *privname;
3899         bool ok;
3900
3901         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3902
3903         state = h->data;
3904
3905         if (r->in.name == NULL) {
3906                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3907         }
3908
3909         privname = r->in.name->string;
3910
3911         ok = dcesrc_lsa_valid_AccountRight(privname);
3912         if (!ok) {
3913                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3914         }
3915
3916         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3917                            "privilege=%s", privname);
3918         if (ret < 0) {
3919                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3920         }
3921         if (ret == 0) {
3922                 return NT_STATUS_NO_MORE_ENTRIES;
3923         }
3924
3925         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3926         if (r->out.sids->sids == NULL) {
3927                 return NT_STATUS_NO_MEMORY;
3928         }
3929         for (i=0;i<ret;i++) {
3930                 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3931                                                                 res[i], "objectSid");
3932                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3933         }
3934         r->out.sids->num_sids = ret;
3935
3936         return NT_STATUS_OK;
3937 }
3938
3939
3940 /*
3941   lsa_AddAccountRights
3942 */
3943 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3944                                      TALLOC_CTX *mem_ctx,
3945                                      struct lsa_AddAccountRights *r)
3946 {
3947         struct dcesrv_handle *h;
3948         struct lsa_policy_state *state;
3949
3950         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3951
3952         state = h->data;
3953
3954         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3955                                           LDB_FLAG_MOD_ADD,
3956                                           r->in.sid, r->in.rights);
3957 }
3958
3959
3960 /*
3961   lsa_RemoveAccountRights
3962 */
3963 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3964                                         TALLOC_CTX *mem_ctx,
3965                                         struct lsa_RemoveAccountRights *r)
3966 {
3967         struct dcesrv_handle *h;
3968         struct lsa_policy_state *state;
3969
3970         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3971
3972         state = h->data;
3973
3974         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3975                                           LDB_FLAG_MOD_DELETE,
3976                                           r->in.sid, r->in.rights);
3977 }
3978
3979
3980 /*
3981   lsa_StorePrivateData
3982 */
3983 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3984                        struct lsa_StorePrivateData *r)
3985 {
3986         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3987 }
3988
3989
3990 /*
3991   lsa_RetrievePrivateData
3992 */
3993 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3994                        struct lsa_RetrievePrivateData *r)
3995 {
3996         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3997 }
3998
3999
4000 /*
4001   lsa_GetUserName
4002 */
4003 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4004                                 struct lsa_GetUserName *r)
4005 {
4006         enum dcerpc_transport_t transport =
4007                 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
4008         struct auth_session_info *session_info =
4009                 dcesrv_call_session_info(dce_call);
4010         NTSTATUS status = NT_STATUS_OK;
4011         const char *account_name;
4012         const char *authority_name;
4013         struct lsa_String *_account_name;
4014         struct lsa_String *_authority_name = NULL;
4015
4016         if (transport != NCACN_NP && transport != NCALRPC) {
4017                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
4018         }
4019
4020         /* this is what w2k3 does */
4021         r->out.account_name = r->in.account_name;
4022         r->out.authority_name = r->in.authority_name;
4023
4024         if (r->in.account_name
4025             && *r->in.account_name
4026             /* && *(*r->in.account_name)->string */
4027             ) {
4028                 return NT_STATUS_INVALID_PARAMETER;
4029         }
4030
4031         if (r->in.authority_name
4032             && *r->in.authority_name
4033             /* && *(*r->in.authority_name)->string */
4034             ) {
4035                 return NT_STATUS_INVALID_PARAMETER;
4036         }
4037
4038         account_name = talloc_reference(mem_ctx, session_info->info->account_name);
4039         authority_name = talloc_reference(mem_ctx, session_info->info->domain_name);
4040
4041         _account_name = talloc(mem_ctx, struct lsa_String);
4042         NT_STATUS_HAVE_NO_MEMORY(_account_name);
4043         _account_name->string = account_name;
4044
4045         if (r->in.authority_name) {
4046                 _authority_name = talloc(mem_ctx, struct lsa_String);
4047                 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
4048                 _authority_name->string = authority_name;
4049         }
4050
4051         *r->out.account_name = _account_name;
4052         if (r->out.authority_name) {
4053                 *r->out.authority_name = _authority_name;
4054         }
4055
4056         return status;
4057 }
4058
4059 /*
4060   lsa_SetInfoPolicy2
4061 */
4062 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
4063                                    TALLOC_CTX *mem_ctx,
4064                                    struct lsa_SetInfoPolicy2 *r)
4065 {
4066         /* need to support these */
4067         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4068 }
4069
4070 static void kdc_get_policy(TALLOC_CTX *mem_ctx,
4071                            struct loadparm_context *lp_ctx,
4072                            struct smb_krb5_context *smb_krb5_context,
4073                            struct lsa_DomainInfoKerberos *k)
4074 {
4075         time_t svc_tkt_lifetime;
4076         time_t usr_tkt_lifetime;
4077         time_t renewal_lifetime;
4078
4079         /* Our KDC always re-validates the client */
4080         k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
4081
4082         lpcfg_default_kdc_policy(mem_ctx, lp_ctx, &svc_tkt_lifetime,
4083                                  &usr_tkt_lifetime, &renewal_lifetime);
4084
4085         unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
4086         unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
4087         unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
4088 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
4089         However in the parent function we basically just did a full
4090         krb5_context init with the only purpose of getting a global
4091         config option (the max skew), it would probably make more sense
4092         to have a lp_ or ldb global option as the samba default */
4093         if (smb_krb5_context) {
4094                 unix_to_nt_time(&k->clock_skew,
4095                                 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
4096         }
4097 #endif
4098         k->reserved = 0;
4099 }
4100 /*
4101   lsa_QueryDomainInformationPolicy
4102 */
4103 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4104                                                  TALLOC_CTX *mem_ctx,
4105                                                  struct lsa_QueryDomainInformationPolicy *r)
4106 {
4107         union lsa_DomainInformationPolicy *info;
4108
4109         info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
4110         if (!info) {
4111                 return NT_STATUS_NO_MEMORY;
4112         }
4113
4114         switch (r->in.level) {
4115         case LSA_DOMAIN_INFO_POLICY_EFS:
4116                 talloc_free(info);
4117                 *r->out.info = NULL;
4118                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4119         case LSA_DOMAIN_INFO_POLICY_KERBEROS:
4120         {
4121                 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
4122                 struct smb_krb5_context *smb_krb5_context;
4123                 int ret = smb_krb5_init_context(mem_ctx,
4124                                                         dce_call->conn->dce_ctx->lp_ctx,
4125                                                         &smb_krb5_context);
4126                 if (ret != 0) {
4127                         talloc_free(info);
4128                         *r->out.info = NULL;
4129                         return NT_STATUS_INTERNAL_ERROR;
4130                 }
4131                 kdc_get_policy(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
4132                                smb_krb5_context,
4133                                k);
4134                 talloc_free(smb_krb5_context);
4135                 *r->out.info = info;
4136                 return NT_STATUS_OK;
4137         }
4138         default:
4139                 talloc_free(info);
4140                 *r->out.info = NULL;
4141                 return NT_STATUS_INVALID_INFO_CLASS;
4142         }
4143 }
4144
4145 /*
4146   lsa_SetDomInfoPolicy
4147 */
4148 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4149                                               TALLOC_CTX *mem_ctx,
4150                                               struct lsa_SetDomainInformationPolicy *r)
4151 {
4152         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4153 }
4154
4155 /*
4156   lsa_TestCall
4157 */
4158 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
4159                              TALLOC_CTX *mem_ctx,
4160                              struct lsa_TestCall *r)
4161 {
4162         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4163 }
4164
4165 /*
4166   lsa_CREDRWRITE
4167 */
4168 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4169                        struct lsa_CREDRWRITE *r)
4170 {
4171         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4172 }
4173
4174
4175 /*
4176   lsa_CREDRREAD
4177 */
4178 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4179                        struct lsa_CREDRREAD *r)
4180 {
4181         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4182 }
4183
4184
4185 /*
4186   lsa_CREDRENUMERATE
4187 */
4188 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4189                        struct lsa_CREDRENUMERATE *r)
4190 {
4191         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4192 }
4193
4194
4195 /*
4196   lsa_CREDRWRITEDOMAINCREDENTIALS
4197 */
4198 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4199                        struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
4200 {
4201         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4202 }
4203
4204
4205 /*
4206   lsa_CREDRREADDOMAINCREDENTIALS
4207 */
4208 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4209                        struct lsa_CREDRREADDOMAINCREDENTIALS *r)
4210 {
4211         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4212 }
4213
4214
4215 /*
4216   lsa_CREDRDELETE
4217 */
4218 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4219                        struct lsa_CREDRDELETE *r)
4220 {
4221         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4222 }
4223
4224
4225 /*
4226   lsa_CREDRGETTARGETINFO
4227 */
4228 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4229                        struct lsa_CREDRGETTARGETINFO *r)
4230 {
4231         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4232 }
4233
4234
4235 /*
4236   lsa_CREDRPROFILELOADED
4237 */
4238 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4239                        struct lsa_CREDRPROFILELOADED *r)
4240 {
4241         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4242 }
4243
4244
4245 /*
4246   lsa_CREDRGETSESSIONTYPES
4247 */
4248 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4249                        struct lsa_CREDRGETSESSIONTYPES *r)
4250 {
4251         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4252 }
4253
4254
4255 /*
4256   lsa_LSARREGISTERAUDITEVENT
4257 */
4258 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4259                        struct lsa_LSARREGISTERAUDITEVENT *r)
4260 {
4261         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4262 }
4263
4264
4265 /*
4266   lsa_LSARGENAUDITEVENT
4267 */
4268 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4269                        struct lsa_LSARGENAUDITEVENT *r)
4270 {
4271         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4272 }
4273
4274
4275 /*
4276   lsa_LSARUNREGISTERAUDITEVENT
4277 */
4278 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4279                        struct lsa_LSARUNREGISTERAUDITEVENT *r)
4280 {
4281         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4282 }
4283
4284
4285 /*
4286   lsa_lsaRQueryForestTrustInformation
4287 */
4288 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4289                        struct lsa_lsaRQueryForestTrustInformation *r)
4290 {
4291         struct dcesrv_handle *h = NULL;
4292         struct lsa_policy_state *p_state = NULL;
4293         int forest_level = DS_DOMAIN_FUNCTION_2000;
4294         const char * const trust_attrs[] = {
4295                 "securityIdentifier",
4296                 "flatName",
4297                 "trustPartner",
4298                 "trustAttributes",
4299                 "trustDirection",
4300                 "trustType",
4301                 "msDS-TrustForestTrustInfo",
4302                 NULL
4303         };
4304         struct ldb_message *trust_tdo_msg = NULL;
4305         struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4306         struct ForestTrustInfo *trust_fti = NULL;
4307         struct lsa_ForestTrustInformation *trust_lfti = NULL;
4308         NTSTATUS status;
4309
4310         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4311
4312         p_state = h->data;
4313
4314         if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4315                 return NT_STATUS_INVALID_DOMAIN_STATE;
4316         }
4317
4318         forest_level = dsdb_forest_functional_level(p_state->sam_ldb);
4319         if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4320                 return NT_STATUS_INVALID_DOMAIN_STATE;
4321         }
4322
4323         if (r->in.trusted_domain_name->string == NULL) {
4324                 return NT_STATUS_NO_SUCH_DOMAIN;
4325         }
4326
4327         status = dsdb_trust_search_tdo(p_state->sam_ldb,
4328                                        r->in.trusted_domain_name->string,
4329                                        r->in.trusted_domain_name->string,
4330                                        trust_attrs, mem_ctx, &trust_tdo_msg);
4331         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4332                 return NT_STATUS_NO_SUCH_DOMAIN;
4333         }
4334         if (!NT_STATUS_IS_OK(status)) {
4335                 return status;
4336         }
4337
4338         status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4339         if (!NT_STATUS_IS_OK(status)) {
4340                 return status;
4341         }
4342
4343         if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4344                 return NT_STATUS_INVALID_PARAMETER;
4345         }
4346
4347         if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4348                 return NT_STATUS_INVALID_PARAMETER;
4349         }
4350
4351         status = dsdb_trust_parse_forest_info(mem_ctx,
4352                                               trust_tdo_msg,
4353                                               &trust_fti);
4354         if (!NT_STATUS_IS_OK(status)) {
4355                 return status;
4356         }
4357
4358         status = dsdb_trust_forest_info_to_lsa(mem_ctx, trust_fti,
4359                                                &trust_lfti);
4360         if (!NT_STATUS_IS_OK(status)) {
4361                 return status;
4362         }
4363
4364         *r->out.forest_trust_info = trust_lfti;
4365         return NT_STATUS_OK;
4366 }
4367
4368 /*
4369   lsa_lsaRSetForestTrustInformation
4370 */
4371 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4372                                                          TALLOC_CTX *mem_ctx,
4373                                                          struct lsa_lsaRSetForestTrustInformation *r)
4374 {
4375         struct dcesrv_handle *h;
4376         struct lsa_policy_state *p_state;
4377         const char * const trust_attrs[] = {
4378                 "securityIdentifier",
4379                 "flatName",
4380                 "trustPartner",
4381                 "trustAttributes",
4382                 "trustDirection",
4383                 "trustType",
4384                 "msDS-TrustForestTrustInfo",
4385                 NULL
4386         };
4387         struct ldb_message *trust_tdo_msg = NULL;
4388         struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4389         struct lsa_ForestTrustInformation *step1_lfti = NULL;
4390         struct lsa_ForestTrustInformation *step2_lfti = NULL;
4391         struct ForestTrustInfo *trust_fti = NULL;
4392         struct ldb_result *trusts_res = NULL;
4393         unsigned int i;
4394         struct lsa_TrustDomainInfoInfoEx *xref_tdo = NULL;
4395         struct lsa_ForestTrustInformation *xref_lfti = NULL;
4396         struct lsa_ForestTrustCollisionInfo *c_info = NULL;
4397         DATA_BLOB ft_blob = {};
4398         struct ldb_message *msg = NULL;
4399         struct server_id *server_ids = NULL;
4400         uint32_t num_server_ids = 0;
4401         NTSTATUS status;
4402         enum ndr_err_code ndr_err;
4403         int ret;
4404         bool in_transaction = false;
4405         struct imessaging_context *imsg_ctx =
4406                 dcesrv_imessaging_context(dce_call->conn);
4407
4408         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4409
4410         p_state = h->data;
4411
4412         if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4413                 return NT_STATUS_INVALID_DOMAIN_STATE;
4414         }
4415
4416         if (r->in.check_only == 0) {
4417                 ret = ldb_transaction_start(p_state->sam_ldb);
4418                 if (ret != LDB_SUCCESS) {
4419                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
4420                 }
4421                 in_transaction = true;
4422         }
4423
4424         /*
4425          * abort if we are not a PDC
4426          *
4427          * In future we should use a function like IsEffectiveRoleOwner()
4428          */
4429         if (!samdb_is_pdc(p_state->sam_ldb)) {
4430                 status = NT_STATUS_INVALID_DOMAIN_ROLE;
4431                 goto done;
4432         }
4433
4434         if (r->in.trusted_domain_name->string == NULL) {
4435                 status = NT_STATUS_NO_SUCH_DOMAIN;
4436                 goto done;
4437         }
4438
4439         status = dsdb_trust_search_tdo(p_state->sam_ldb,
4440                                        r->in.trusted_domain_name->string,
4441                                        r->in.trusted_domain_name->string,
4442                       &nb