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