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