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