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