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