lsa4: Fix a set but unused variable warning
[samba.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
1 /* need access mask/acl implementation */
2
3 /* 
4    Unix SMB/CIFS implementation.
5
6    endpoint server for the lsarpc pipe
7
8    Copyright (C) Andrew Tridgell 2004
9    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "rpc_server/lsa/lsa.h"
26 #include "system/kerberos.h"
27 #include "auth/kerberos/kerberos.h"
28 #include "librpc/gen_ndr/ndr_drsblobs.h"
29 #include "librpc/gen_ndr/ndr_lsa.h"
30 #include "../lib/crypto/crypto.h"
31 #include "lib/util/tsort.h"
32 #include "dsdb/common/util.h"
33 #include "libcli/security/session.h"
34 #include "libcli/lsarpc/util_lsarpc.h"
35
36 /*
37   this type allows us to distinguish handle types
38 */
39
40 /*
41   state associated with a lsa_OpenAccount() operation
42 */
43 struct lsa_account_state {
44         struct lsa_policy_state *policy;
45         uint32_t access_mask;
46         struct dom_sid *account_sid;
47 };
48
49
50 /*
51   state associated with a lsa_OpenSecret() operation
52 */
53 struct lsa_secret_state {
54         struct lsa_policy_state *policy;
55         uint32_t access_mask;
56         struct ldb_dn *secret_dn;
57         struct ldb_context *sam_ldb;
58         bool global;
59 };
60
61 /*
62   state associated with a lsa_OpenTrustedDomain() operation
63 */
64 struct lsa_trusted_domain_state {
65         struct lsa_policy_state *policy;
66         uint32_t access_mask;
67         struct ldb_dn *trusted_domain_dn;
68         struct ldb_dn *trusted_domain_user_dn;
69 };
70
71 /*
72   this is based on the samba3 function make_lsa_object_sd()
73   It uses the same logic, but with samba4 helper functions
74  */
75 static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx,
76                                     struct security_descriptor **sd,
77                                     struct dom_sid *sid,
78                                     uint32_t sid_access)
79 {
80         NTSTATUS status;
81         uint32_t rid;
82         struct dom_sid *domain_sid, *domain_admins_sid;
83         const char *domain_admins_sid_str, *sidstr;
84         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
85
86         status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
87         NT_STATUS_NOT_OK_RETURN_AND_FREE(status, tmp_ctx);
88
89         domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
90         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         int id;
3426
3427         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3428
3429         id = sec_privilege_id(r->in.name->string);
3430         if (id == SEC_PRIV_INVALID) {
3431                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3432         }
3433
3434         r->out.luid->low = id;
3435         r->out.luid->high = 0;
3436
3437         return NT_STATUS_OK;
3438 }
3439
3440
3441 /*
3442   lsa_LookupPrivName
3443 */
3444 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3445                                    TALLOC_CTX *mem_ctx,
3446                                    struct lsa_LookupPrivName *r)
3447 {
3448         struct dcesrv_handle *h;
3449         struct lsa_StringLarge *name;
3450         const char *privname;
3451
3452         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3453
3454         if (r->in.luid->high != 0) {
3455                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3456         }
3457
3458         privname = sec_privilege_name(r->in.luid->low);
3459         if (privname == NULL) {
3460                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3461         }
3462
3463         name = talloc(mem_ctx, struct lsa_StringLarge);
3464         if (name == NULL) {
3465                 return NT_STATUS_NO_MEMORY;
3466         }
3467
3468         name->string = privname;
3469
3470         *r->out.name = name;
3471
3472         return NT_STATUS_OK;
3473 }
3474
3475
3476 /*
3477   lsa_LookupPrivDisplayName
3478 */
3479 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3480                                           TALLOC_CTX *mem_ctx,
3481                                           struct lsa_LookupPrivDisplayName *r)
3482 {
3483         struct dcesrv_handle *h;
3484         struct lsa_StringLarge *disp_name = NULL;
3485         enum sec_privilege id;
3486
3487         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3488
3489         id = sec_privilege_id(r->in.name->string);
3490         if (id == SEC_PRIV_INVALID) {
3491                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3492         }
3493
3494         disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3495         if (disp_name == NULL) {
3496                 return NT_STATUS_NO_MEMORY;
3497         }
3498
3499         disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3500         if (disp_name->string == NULL) {
3501                 return NT_STATUS_INTERNAL_ERROR;
3502         }
3503
3504         *r->out.disp_name = disp_name;
3505         *r->out.returned_language_id = 0;
3506
3507         return NT_STATUS_OK;
3508 }
3509
3510
3511 /*
3512   lsa_EnumAccountsWithUserRight
3513 */
3514 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3515                                               TALLOC_CTX *mem_ctx,
3516                                               struct lsa_EnumAccountsWithUserRight *r)
3517 {
3518         struct dcesrv_handle *h;
3519         struct lsa_policy_state *state;
3520         int ret, i;
3521         struct ldb_message **res;
3522         const char * const attrs[] = { "objectSid", NULL};
3523         const char *privname;
3524
3525         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3526
3527         state = h->data;
3528
3529         if (r->in.name == NULL) {
3530                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3531         }
3532
3533         privname = r->in.name->string;
3534         if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
3535                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3536         }
3537
3538         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3539                            "privilege=%s", privname);
3540         if (ret < 0) {
3541                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3542         }
3543         if (ret == 0) {
3544                 return NT_STATUS_NO_MORE_ENTRIES;
3545         }
3546
3547         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3548         if (r->out.sids->sids == NULL) {
3549                 return NT_STATUS_NO_MEMORY;
3550         }
3551         for (i=0;i<ret;i++) {
3552                 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3553                                                                 res[i], "objectSid");
3554                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3555         }
3556         r->out.sids->num_sids = ret;
3557
3558         return NT_STATUS_OK;
3559 }
3560
3561
3562 /*
3563   lsa_AddAccountRights
3564 */
3565 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3566                                      TALLOC_CTX *mem_ctx,
3567                                      struct lsa_AddAccountRights *r)
3568 {
3569         struct dcesrv_handle *h;
3570         struct lsa_policy_state *state;
3571
3572         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3573
3574         state = h->data;
3575
3576         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3577                                           LDB_FLAG_MOD_ADD,
3578                                           r->in.sid, r->in.rights);
3579 }
3580
3581
3582 /*
3583   lsa_RemoveAccountRights
3584 */
3585 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3586                                         TALLOC_CTX *mem_ctx,
3587                                         struct lsa_RemoveAccountRights *r)
3588 {
3589         struct dcesrv_handle *h;
3590         struct lsa_policy_state *state;
3591
3592         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3593
3594         state = h->data;
3595
3596         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3597                                           LDB_FLAG_MOD_DELETE,
3598                                           r->in.sid, r->in.rights);
3599 }
3600
3601
3602 /*
3603   lsa_StorePrivateData
3604 */
3605 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3606                        struct lsa_StorePrivateData *r)
3607 {
3608         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3609 }
3610
3611
3612 /*
3613   lsa_RetrievePrivateData
3614 */
3615 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3616                        struct lsa_RetrievePrivateData *r)
3617 {
3618         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3619 }
3620
3621
3622 /*
3623   lsa_GetUserName
3624 */
3625 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3626                                 struct lsa_GetUserName *r)
3627 {
3628         enum dcerpc_transport_t transport = dce_call->conn->endpoint->ep_description->transport;
3629         NTSTATUS status = NT_STATUS_OK;
3630         const char *account_name;
3631         const char *authority_name;
3632         struct lsa_String *_account_name;
3633         struct lsa_String *_authority_name = NULL;
3634
3635         if (transport != NCACN_NP && transport != NCALRPC) {
3636                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3637         }
3638
3639         /* this is what w2k3 does */
3640         r->out.account_name = r->in.account_name;
3641         r->out.authority_name = r->in.authority_name;
3642
3643         if (r->in.account_name
3644             && *r->in.account_name
3645             /* && *(*r->in.account_name)->string */
3646             ) {
3647                 return NT_STATUS_INVALID_PARAMETER;
3648         }
3649
3650         if (r->in.authority_name
3651             && *r->in.authority_name
3652             /* && *(*r->in.authority_name)->string */
3653             ) {
3654                 return NT_STATUS_INVALID_PARAMETER;
3655         }
3656
3657         account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3658         authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3659
3660         _account_name = talloc(mem_ctx, struct lsa_String);
3661         NT_STATUS_HAVE_NO_MEMORY(_account_name);
3662         _account_name->string = account_name;
3663
3664         if (r->in.authority_name) {
3665                 _authority_name = talloc(mem_ctx, struct lsa_String);
3666                 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3667                 _authority_name->string = authority_name;
3668         }
3669
3670         *r->out.account_name = _account_name;
3671         if (r->out.authority_name) {
3672                 *r->out.authority_name = _authority_name;
3673         }
3674
3675         return status;
3676 }
3677
3678 /*
3679   lsa_SetInfoPolicy2
3680 */
3681 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3682                                    TALLOC_CTX *mem_ctx,
3683                                    struct lsa_SetInfoPolicy2 *r)
3684 {
3685         /* need to support these */
3686         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3687 }
3688
3689 static void kdc_get_policy(struct loadparm_context *lp_ctx,
3690                            struct smb_krb5_context *smb_krb5_context,
3691                            struct lsa_DomainInfoKerberos *k)
3692 {
3693         time_t svc_tkt_lifetime;
3694         time_t usr_tkt_lifetime;
3695         time_t renewal_lifetime;
3696
3697         /* These should be set and stored via Group Policy, but until then, some defaults are in order */
3698
3699         /* Our KDC always re-validates the client */
3700         k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
3701
3702         lpcfg_default_kdc_policy(lp_ctx, &svc_tkt_lifetime,
3703                                  &usr_tkt_lifetime, &renewal_lifetime);
3704
3705         unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
3706         unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
3707         unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
3708 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
3709         However in the parent function we basically just did a full
3710         krb5_context init with the only purpose of getting a global
3711         config option (the max skew), it would probably make more sense
3712         to have a lp_ or ldb global option as the samba default */
3713         if (smb_krb5_context) {
3714                 unix_to_nt_time(&k->clock_skew,
3715                                 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
3716         }
3717 #endif
3718         k->reserved = 0;
3719 }
3720 /*
3721   lsa_QueryDomainInformationPolicy
3722 */
3723 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3724                                                  TALLOC_CTX *mem_ctx,
3725                                                  struct lsa_QueryDomainInformationPolicy *r)
3726 {
3727         union lsa_DomainInformationPolicy *info;
3728
3729         info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
3730         if (!info) {
3731                 return NT_STATUS_NO_MEMORY;
3732         }
3733
3734         switch (r->in.level) {
3735         case LSA_DOMAIN_INFO_POLICY_EFS:
3736                 talloc_free(info);
3737                 *r->out.info = NULL;
3738                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3739         case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3740         {
3741                 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3742                 struct smb_krb5_context *smb_krb5_context;
3743                 int ret = smb_krb5_init_context(mem_ctx,
3744                                                         dce_call->event_ctx,
3745                                                         dce_call->conn->dce_ctx->lp_ctx,
3746                                                         &smb_krb5_context);
3747                 if (ret != 0) {
3748                         talloc_free(info);
3749                         *r->out.info = NULL;
3750                         return NT_STATUS_INTERNAL_ERROR;
3751                 }
3752                 kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
3753                                smb_krb5_context,
3754                                k);
3755                 talloc_free(smb_krb5_context);
3756                 *r->out.info = info;
3757                 return NT_STATUS_OK;
3758         }
3759         default:
3760                 talloc_free(info);
3761                 *r->out.info = NULL;
3762                 return NT_STATUS_INVALID_INFO_CLASS;
3763         }
3764 }
3765
3766 /*
3767   lsa_SetDomInfoPolicy
3768 */
3769 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3770                                               TALLOC_CTX *mem_ctx,
3771                                               struct lsa_SetDomainInformationPolicy *r)
3772 {
3773         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3774 }
3775
3776 /*
3777   lsa_TestCall
3778 */
3779 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3780                              TALLOC_CTX *mem_ctx,
3781                              struct lsa_TestCall *r)
3782 {
3783         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3784 }
3785
3786 /*
3787   lsa_CREDRWRITE
3788 */
3789 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3790                        struct lsa_CREDRWRITE *r)
3791 {
3792         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3793 }
3794
3795
3796 /*
3797   lsa_CREDRREAD
3798 */
3799 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3800                        struct lsa_CREDRREAD *r)
3801 {
3802         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3803 }
3804
3805
3806 /*
3807   lsa_CREDRENUMERATE
3808 */
3809 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3810                        struct lsa_CREDRENUMERATE *r)
3811 {
3812         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3813 }
3814
3815
3816 /*
3817   lsa_CREDRWRITEDOMAINCREDENTIALS
3818 */
3819 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3820                        struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3821 {
3822         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3823 }
3824
3825
3826 /*
3827   lsa_CREDRREADDOMAINCREDENTIALS
3828 */
3829 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3830                        struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3831 {
3832         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3833 }
3834
3835
3836 /*
3837   lsa_CREDRDELETE
3838 */
3839 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3840                        struct lsa_CREDRDELETE *r)
3841 {
3842         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3843 }
3844
3845
3846 /*
3847   lsa_CREDRGETTARGETINFO
3848 */
3849 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3850                        struct lsa_CREDRGETTARGETINFO *r)
3851 {
3852         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3853 }
3854
3855
3856 /*
3857   lsa_CREDRPROFILELOADED
3858 */
3859 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3860                        struct lsa_CREDRPROFILELOADED *r)
3861 {
3862         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3863 }
3864
3865
3866 /*
3867   lsa_CREDRGETSESSIONTYPES
3868 */
3869 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3870                        struct lsa_CREDRGETSESSIONTYPES *r)
3871 {
3872         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3873 }
3874
3875
3876 /*
3877   lsa_LSARREGISTERAUDITEVENT
3878 */
3879 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3880                        struct lsa_LSARREGISTERAUDITEVENT *r)
3881 {
3882         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3883 }
3884
3885
3886 /*
3887   lsa_LSARGENAUDITEVENT
3888 */
3889 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3890                        struct lsa_LSARGENAUDITEVENT *r)
3891 {
3892         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3893 }
3894
3895
3896 /*
3897   lsa_LSARUNREGISTERAUDITEVENT
3898 */
3899 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3900                        struct lsa_LSARUNREGISTERAUDITEVENT *r)
3901 {
3902         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3903 }
3904
3905
3906 /*
3907   lsa_lsaRQueryForestTrustInformation
3908 */
3909 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3910                        struct lsa_lsaRQueryForestTrustInformation *r)
3911 {
3912         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3913 }
3914
3915 #define DNS_CMP_MATCH 0
3916 #define DNS_CMP_FIRST_IS_CHILD 1
3917 #define DNS_CMP_SECOND_IS_CHILD 2
3918 #define DNS_CMP_NO_MATCH 3
3919
3920 /* this function assumes names are well formed DNS names.
3921  * it doesn't validate them */
3922 static int dns_cmp(const char *s1, size_t l1,
3923                    const char *s2, size_t l2)
3924 {
3925         const char *p1, *p2;
3926         size_t t1, t2;
3927         int cret;
3928
3929         if (l1 == l2) {
3930                 if (strcasecmp_m(s1, s2) == 0) {
3931                         return DNS_CMP_MATCH;
3932                 }
3933                 return DNS_CMP_NO_MATCH;
3934         }
3935
3936         if (l1 > l2) {
3937                 p1 = s1;
3938                 p2 = s2;
3939                 t1 = l1;
3940                 t2 = l2;
3941                 cret = DNS_CMP_FIRST_IS_CHILD;
3942         } else {
3943                 p1 = s2;
3944                 p2 = s1;
3945                 t1 = l2;
3946                 t2 = l1;
3947                 cret = DNS_CMP_SECOND_IS_CHILD;
3948         }
3949
3950         if (p1[t1 - t2 - 1] != '.') {
3951                 return DNS_CMP_NO_MATCH;
3952         }
3953
3954         if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
3955                 return cret;
3956         }
3957
3958         return DNS_CMP_NO_MATCH;
3959 }
3960
3961 /* decode all TDOs forest trust info blobs */
3962 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
3963                             struct ldb_message *msg,
3964                             struct ForestTrustInfo *info)
3965 {
3966         const struct ldb_val *ft_blob;
3967         enum ndr_err_code ndr_err;
3968
3969         ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3970         if (!ft_blob || !ft_blob->data) {
3971                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3972         }
3973         /* ldb_val is equivalent to DATA_BLOB */
3974         ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
3975                                            (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
3976         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3977                 return NT_STATUS_INVALID_DOMAIN_STATE;
3978         }
3979
3980         return NT_STATUS_OK;
3981 }
3982
3983 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
3984                             struct ForestTrustInfo *fti)
3985 {
3986         struct ForestTrustDataDomainInfo *info;
3987         struct ForestTrustInfoRecord *rec;
3988
3989         fti->version = 1;
3990         fti->count = 2;
3991         fti->records = talloc_array(fti,
3992                                     struct ForestTrustInfoRecordArmor, 2);
3993         if (!fti->records) {
3994                 return NT_STATUS_NO_MEMORY;
3995         }
3996
3997         /* TLN info */
3998         rec = &fti->records[0].record;
3999
4000         rec->flags = 0;
4001         rec->timestamp = 0;
4002         rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
4003
4004         rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
4005         if (!rec->data.name.string) {
4006                 return NT_STATUS_NO_MEMORY;
4007         }
4008         rec->data.name.size = strlen(rec->data.name.string);
4009
4010         /* DOMAIN info */
4011         rec = &fti->records[1].record;
4012
4013         rec->flags = 0;
4014         rec->timestamp = 0;
4015         rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
4016
4017         info = &rec->data.info;
4018
4019         info->sid = *ps->domain_sid;
4020         info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
4021         if (!info->dns_name.string) {
4022                 return NT_STATUS_NO_MEMORY;
4023         }
4024         info->dns_name.size = strlen(info->dns_name.string);
4025         info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
4026         if (!info->netbios_name.string) {
4027                 return NT_STATUS_NO_MEMORY;
4028         }
4029         info->netbios_name.size = strlen(info->netbios_name.string);
4030
4031         return NT_STATUS_OK;
4032 }
4033
4034 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
4035                              struct lsa_ForestTrustInformation *lfti,
4036                              struct ForestTrustInfo *fti)
4037 {
4038         struct lsa_ForestTrustRecord *lrec;
4039         struct ForestTrustInfoRecord *rec;
4040         struct lsa_StringLarge *tln;
4041         struct lsa_ForestTrustDomainInfo *info;
4042         uint32_t i;
4043
4044         fti->version = 1;
4045         fti->count = lfti->count;
4046         fti->records = talloc_array(mem_ctx,
4047                                     struct ForestTrustInfoRecordArmor,
4048                                     fti->count);
4049         if (!fti->records) {
4050                 return NT_STATUS_NO_MEMORY;
4051         }
4052         for (i = 0; i < fti->count; i++) {
4053                 lrec = lfti->entries[i];
4054                 rec = &fti->records[i].record;
4055
4056                 rec->flags = lrec->flags;
4057                 rec->timestamp = lrec->time;
4058                 rec->type = lrec->type;
4059
4060                 switch (lrec->type) {
4061                 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4062                 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4063                         tln = &lrec->forest_trust_data.top_level_name;
4064                         rec->data.name.string =
4065                                 talloc_strdup(mem_ctx, tln->string);
4066                         if (!rec->data.name.string) {
4067                                 return NT_STATUS_NO_MEMORY;
4068                         }
4069                         rec->data.name.size = strlen(rec->data.name.string);
4070                         break;
4071                 case LSA_FOREST_TRUST_DOMAIN_INFO:
4072                         info = &lrec->forest_trust_data.domain_info;
4073                         rec->data.info.sid = *info->domain_sid;
4074                         rec->data.info.dns_name.string =
4075                                 talloc_strdup(mem_ctx,
4076                                             info->dns_domain_name.string);
4077                         if (!rec->data.info.dns_name.string) {
4078                                 return NT_STATUS_NO_MEMORY;
4079                         }
4080                         rec->data.info.dns_name.size =
4081                                 strlen(rec->data.info.dns_name.string);
4082                         rec->data.info.netbios_name.string =
4083                                 talloc_strdup(mem_ctx,
4084                                             info->netbios_domain_name.string);
4085                         if (!rec->data.info.netbios_name.string) {
4086                                 return NT_STATUS_NO_MEMORY;
4087                         }
4088                         rec->data.info.netbios_name.size =
4089                                 strlen(rec->data.info.netbios_name.string);
4090                         break;
4091                 default:
4092                         return NT_STATUS_INVALID_DOMAIN_STATE;
4093                 }
4094         }
4095
4096         return NT_STATUS_OK;
4097 }
4098
4099 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4100                               uint32_t idx, uint32_t collision_type,
4101                               uint32_t conflict_type, const char *tdo_name);
4102
4103 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4104                               const char *tdo_name,
4105                               struct ForestTrustInfo *tdo_fti,
4106                               struct ForestTrustInfo *new_fti,
4107                               struct lsa_ForestTrustCollisionInfo *c_info)
4108 {
4109         struct ForestTrustInfoRecord *nrec;
4110         struct ForestTrustInfoRecord *trec;
4111         const char *dns_name;
4112         const char *nb_name;
4113         struct dom_sid *sid;
4114         const char *tname;
4115         size_t dns_len;
4116         size_t tlen;
4117         NTSTATUS nt_status = NT_STATUS_OK;
4118         uint32_t new_fti_idx;
4119         uint32_t i;
4120         /* use always TDO type, until we understand when Xref can be used */
4121         uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4122         bool tln_conflict;
4123         bool sid_conflict;
4124         bool nb_conflict;
4125         bool exclusion;
4126         bool ex_rule;
4127         int ret;
4128
4129         for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4130
4131                 nrec = &new_fti->records[new_fti_idx].record;
4132                 dns_name = NULL;
4133                 tln_conflict = false;
4134                 sid_conflict = false;
4135                 nb_conflict = false;
4136                 exclusion = false;
4137
4138                 switch (nrec->type) {
4139                 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4140                         /* exclusions do not conflict by definition */
4141                         break;
4142
4143                 case FOREST_TRUST_TOP_LEVEL_NAME:
4144                         dns_name = nrec->data.name.string;
4145                         dns_len = nrec->data.name.size;
4146                         break;
4147
4148                 case LSA_FOREST_TRUST_DOMAIN_INFO:
4149                         dns_name = nrec->data.info.dns_name.string;
4150                         dns_len = nrec->data.info.dns_name.size;
4151                         nb_name = nrec->data.info.netbios_name.string;
4152                         sid = &nrec->data.info.sid;
4153                         break;
4154                 }
4155
4156                 if (!dns_name) continue;
4157
4158                 /* check if this is already taken and not excluded */
4159                 for (i = 0; i < tdo_fti->count; i++) {
4160                         trec = &tdo_fti->records[i].record;
4161
4162                         switch (trec->type) {
4163                         case FOREST_TRUST_TOP_LEVEL_NAME:
4164                                 ex_rule = false;
4165                                 tname = trec->data.name.string;
4166                                 tlen = trec->data.name.size;
4167                                 break;
4168                         case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4169                                 ex_rule = true;
4170                                 tname = trec->data.name.string;
4171                                 tlen = trec->data.name.size;
4172                                 break;
4173                         case FOREST_TRUST_DOMAIN_INFO:
4174                                 ex_rule = false;
4175                                 tname = trec->data.info.dns_name.string;
4176                                 tlen = trec->data.info.dns_name.size;
4177                         }
4178                         ret = dns_cmp(dns_name, dns_len, tname, tlen);
4179                         switch (ret) {
4180                         case DNS_CMP_MATCH:
4181                                 /* if it matches exclusion,
4182                                  * it doesn't conflict */
4183                                 if (ex_rule) {
4184                                         exclusion = true;
4185                                         break;
4186                                 }
4187                                 /* fall through */
4188                         case DNS_CMP_FIRST_IS_CHILD:
4189                         case DNS_CMP_SECOND_IS_CHILD:
4190                                 tln_conflict = true;
4191                                 /* fall through */
4192                         default:
4193                                 break;
4194                         }
4195
4196                         /* explicit exclusion, no dns name conflict here */
4197                         if (exclusion) {
4198                                 tln_conflict = false;
4199                         }
4200
4201                         if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4202                                 continue;
4203                         }
4204
4205                         /* also test for domain info */
4206                         if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4207                             dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4208                                 sid_conflict = true;
4209                         }
4210                         if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4211                             strcasecmp_m(trec->data.info.netbios_name.string,
4212                                          nb_name) == 0) {
4213                                 nb_conflict = true;
4214                         }
4215                 }
4216
4217                 if (tln_conflict) {
4218                         nt_status = add_collision(c_info, new_fti_idx,
4219                                                   collision_type,
4220                                                   LSA_TLN_DISABLED_CONFLICT,
4221                                                   tdo_name);
4222                         if (!NT_STATUS_IS_OK(nt_status)) {
4223                                 goto done;
4224                         }
4225                 }
4226                 if (sid_conflict) {
4227                         nt_status = add_collision(c_info, new_fti_idx,
4228                                                   collision_type,
4229                                                   LSA_SID_DISABLED_CONFLICT,
4230                                                   tdo_name);
4231                         if (!NT_STATUS_IS_OK(nt_status)) {
4232                                 goto done;
4233                         }
4234                 }
4235                 if (nb_conflict) {
4236                         nt_status = add_collision(c_info, new_fti_idx,
4237                                                   collision_type,
4238                                                   LSA_NB_DISABLED_CONFLICT,
4239                                                   tdo_name);
4240                         if (!NT_STATUS_IS_OK(nt_status)) {
4241                                 goto done;
4242                         }
4243                 }
4244         }
4245
4246 done:
4247         return nt_status;
4248 }
4249
4250 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4251                               uint32_t idx, uint32_t collision_type,
4252                               uint32_t conflict_type, const char *tdo_name)
4253 {
4254         struct lsa_ForestTrustCollisionRecord **es;
4255         uint32_t i = c_info->count;
4256
4257         es = talloc_realloc(c_info, c_info->entries,
4258                             struct lsa_ForestTrustCollisionRecord *, i + 1);
4259         if (!es) {
4260                 return NT_STATUS_NO_MEMORY;
4261         }
4262         c_info->entries = es;
4263         c_info->count = i + 1;
4264
4265         es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4266         if (!es[i]) {
4267                 return NT_STATUS_NO_MEMORY;
4268         }
4269
4270         es[i]->index = idx;
4271         es[i]->type = collision_type;
4272         es[i]->flags.flags = conflict_type;
4273         es[i]->name.string = talloc_strdup(es[i], tdo_name);
4274         if (!es[i]->name.string) {
4275                 return NT_STATUS_NO_MEMORY;
4276         }
4277         es[i]->name.size = strlen(es[i]->name.string);
4278
4279         return NT_STATUS_OK;
4280 }
4281
4282 /*
4283   lsa_lsaRSetForestTrustInformation
4284 */
4285 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4286                                                          TALLOC_CTX *mem_ctx,
4287                                                          struct lsa_lsaRSetForestTrustInformation *r)
4288 {
4289         struct dcesrv_handle *h;
4290         struct lsa_policy_state *p_state;
4291         const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4292                                       "msDS-TrustForestTrustInfo", NULL };
4293         struct ldb_message **dom_res = NULL;
4294         struct ldb_dn *tdo_dn;
4295         struct ldb_message *msg;
4296         int num_res, i;
4297         const char *td_name;
4298         uint32_t trust_attributes;
4299         struct lsa_ForestTrustCollisionInfo *c_info;
4300         struct ForestTrustInfo *nfti;
4301         struct ForestTrustInfo *fti;
4302         DATA_BLOB ft_blob;
4303         enum ndr_err_code ndr_err;
4304         NTSTATUS nt_status;
4305         bool am_rodc;
4306         int ret;
4307
4308         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4309
4310         p_state = h->data;
4311
4312         if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4313                 return NT_STATUS_INVALID_DOMAIN_STATE;
4314         }
4315
4316         /* abort if we are not a PDC */
4317         if (!samdb_is_pdc(p_state->sam_ldb)) {
4318                 return NT_STATUS_INVALID_DOMAIN_ROLE;
4319         }
4320
4321         ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
4322         if (ret == LDB_SUCCESS && am_rodc) {
4323                 return NT_STATUS_NO_SUCH_DOMAIN;
4324         }
4325
4326         /* check caller has TRUSTED_SET_AUTH */
4327
4328         /* fetch all trusted domain objects */
4329         num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4330                                p_state->system_dn,
4331                                &dom_res, trust_attrs,
4332                                "(objectclass=trustedDomain)");
4333         if (num_res == 0) {
4334                 return NT_STATUS_NO_SUCH_DOMAIN;
4335         }
4336
4337         for (i = 0; i < num_res; i++) {
4338                 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4339                                                       "trustPartner", NULL);
4340                 if (!td_name) {
4341                         return NT_STATUS_INVALID_DOMAIN_STATE;
4342                 }
4343                 if (strcasecmp_m(td_name,
4344                                  r->in.trusted_domain_name->string) == 0) {
4345                         break;
4346                 }
4347         }
4348         if (i >= num_res) {
4349                 return NT_STATUS_NO_SUCH_DOMAIN;
4350         }
4351
4352         tdo_dn = dom_res[i]->dn;
4353
4354         trust_attributes = ldb_msg_find_attr_as_uint(dom_res[i],
4355                                                      "trustAttributes", 0);
4356         if (!(trust_attributes & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4357                 return NT_STATUS_INVALID_PARAMETER;
4358         }
4359
4360         if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4361                 return NT_STATUS_INVALID_PARAMETER;
4362         }
4363
4364         nfti = talloc(mem_ctx, struct ForestTrustInfo);
4365         if (!nfti) {
4366                 return NT_STATUS_NO_MEMORY;
4367         }
4368
4369         nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4370         if (!NT_STATUS_IS_OK(nt_status)) {
4371                 return nt_status;
4372         }
4373
4374         c_info = talloc_zero(r->out.collision_info,
4375                              struct lsa_ForestTrustCollisionInfo);
4376         if (!c_info) {
4377                 return NT_STATUS_NO_MEMORY;
4378         }
4379
4380         /* first check own info, then other domains */
4381         fti = talloc(mem_ctx, struct ForestTrustInfo);
4382         if (!fti) {
4383                 return NT_STATUS_NO_MEMORY;
4384         }
4385
4386         nt_status = own_ft_info(p_state, fti);
4387         if (!NT_STATUS_IS_OK(nt_status)) {
4388                 return nt_status;
4389         }
4390
4391         nt_status = check_ft_info(c_info, p_state->domain_dns,
4392                                   fti, nfti, c_info);
4393         if (!NT_STATUS_IS_OK(nt_status)) {
4394                 return nt_status;
4395         }
4396
4397         for (i = 0; i < num_res; i++) {
4398                 fti = talloc(mem_ctx, struct ForestTrustInfo);
4399                 if (!fti) {
4400                         return NT_STATUS_NO_MEMORY;
4401                 }
4402
4403                 nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
4404                 if (!NT_STATUS_IS_OK(nt_status)) {
4405                         if (NT_STATUS_EQUAL(nt_status,
4406                             NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4407                                 continue;
4408                         }
4409                         return nt_status;
4410                 }
4411
4412                 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4413                                                       "trustPartner", NULL);
4414                 if (!td_name) {
4415                         return NT_STATUS_INVALID_DOMAIN_STATE;
4416                 }
4417
4418                 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4419                 if (!NT_STATUS_IS_OK(nt_status)) {
4420                         return nt_status;
4421                 }
4422         }
4423
4424         *r->out.collision_info = c_info;
4425
4426         if (r->in.check_only != 0) {
4427                 return NT_STATUS_OK;
4428         }
4429
4430         /* not just a check, write info back */
4431
4432         ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
4433                                        (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4434         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4435                 return NT_STATUS_INVALID_PARAMETER;
4436         }
4437
4438         msg = ldb_msg_new(mem_ctx);
4439         if (msg == NULL) {
4440                 return NT_STATUS_NO_MEMORY;
4441         }
4442
4443         msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4444         if (!msg->dn) {
4445                 return NT_STATUS_NO_MEMORY;
4446         }
4447
4448         ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4449                                 LDB_FLAG_MOD_REPLACE, NULL);
4450         if (ret != LDB_SUCCESS) {
4451                 return NT_STATUS_NO_MEMORY;
4452         }
4453         ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4454                                 &ft_blob, NULL);
4455         if (ret != LDB_SUCCESS) {
4456                 return NT_STATUS_NO_MEMORY;
4457         }
4458
4459         ret = ldb_modify(p_state->sam_ldb, msg);
4460         if (ret != LDB_SUCCESS) {
4461                 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4462                           ldb_errstring(p_state->sam_ldb)));
4463
4464                 switch (ret) {
4465                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4466                         return NT_STATUS_ACCESS_DENIED;
4467                 default:
4468                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
4469                 }
4470         }
4471
4472         return NT_STATUS_OK;
4473 }
4474
4475 /*
4476   lsa_CREDRRENAME
4477 */
4478 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4479                        struct lsa_CREDRRENAME *r)
4480 {
4481         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4482 }
4483
4484
4485
4486 /*
4487   lsa_LSAROPENPOLICYSCE
4488 */
4489 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4490                        struct lsa_LSAROPENPOLICYSCE *r)
4491 {
4492         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4493 }
4494
4495
4496 /*
4497   lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4498 */
4499 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4500                        struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4501 {
4502         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4503 }
4504
4505
4506 /*
4507   lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4508 */
4509 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4510                        struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4511 {
4512         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4513 }
4514
4515
4516 /*
4517   lsa_LSARADTREPORTSECURITYEVENT
4518 */
4519 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4520                        struct lsa_LSARADTREPORTSECURITYEVENT *r)
4521 {
4522         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4523 }
4524
4525
4526 /* include the generated boilerplate */
4527 #include "librpc/gen_ndr/ndr_lsa_s.c"
4528
4529
4530
4531 /*****************************************
4532 NOTE! The remaining calls below were
4533 removed in w2k3, so the DCESRV_FAULT()
4534 replies are the correct implementation. Do
4535 not try and fill these in with anything else
4536 ******************************************/
4537
4538 /*
4539   dssetup_DsRoleDnsNameToFlatName
4540 */
4541 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4542                                         struct dssetup_DsRoleDnsNameToFlatName *r)
4543 {
4544         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4545 }
4546
4547
4548 /*
4549   dssetup_DsRoleDcAsDc
4550 */
4551 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4552                              struct dssetup_DsRoleDcAsDc *r)
4553 {
4554         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4555 }
4556
4557
4558 /*
4559   dssetup_DsRoleDcAsReplica
4560 */
4561 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4562                                   struct dssetup_DsRoleDcAsReplica *r)
4563 {
4564         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4565 }
4566
4567
4568 /*
4569   dssetup_DsRoleDemoteDc
4570 */
4571 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4572                                struct dssetup_DsRoleDemoteDc *r)
4573 {
4574         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4575 }
4576
4577
4578 /*
4579   dssetup_DsRoleGetDcOperationProgress
4580 */
4581 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4582                                              struct dssetup_DsRoleGetDcOperationProgress *r)
4583 {
4584         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4585 }
4586
4587
4588 /* 
4589   dssetup_DsRoleGetDcOperationResults 
4590 */
4591 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4592                                             struct dssetup_DsRoleGetDcOperationResults *r)
4593 {
4594         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4595 }
4596
4597
4598 /* 
4599   dssetup_DsRoleCancel 
4600 */
4601 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4602                              struct dssetup_DsRoleCancel *r)
4603 {
4604         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4605 }
4606
4607
4608 /*
4609   dssetup_DsRoleServerSaveStateForUpgrade
4610 */
4611 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4612                                                 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4613 {
4614         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4615 }
4616
4617
4618 /*
4619   dssetup_DsRoleUpgradeDownlevelServer
4620 */
4621 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4622                                              struct dssetup_DsRoleUpgradeDownlevelServer *r)
4623 {
4624         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4625 }
4626
4627
4628 /*
4629   dssetup_DsRoleAbortDownlevelServerUpgrade
4630 */
4631 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4632                                                   struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4633 {
4634         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4635 }
4636
4637
4638 /* include the generated boilerplate */
4639 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4640
4641 NTSTATUS dcerpc_server_lsa_init(void)
4642 {
4643         NTSTATUS ret;
4644
4645         ret = dcerpc_server_dssetup_init();
4646         if (!NT_STATUS_IS_OK(ret)) {
4647                 return ret;
4648         }
4649         ret = dcerpc_server_lsarpc_init();
4650         if (!NT_STATUS_IS_OK(ret)) {
4651                 return ret;
4652         }
4653         return ret;
4654 }