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