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