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