s4:fix some shadowed declaration warnings on Solaris by renaming the symbols
[gd/samba-autobuild/.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
1 /* need access mask/acl implementation */
2
3 /* 
4    Unix SMB/CIFS implementation.
5
6    endpoint server for the lsarpc pipe
7
8    Copyright (C) Andrew Tridgell 2004
9    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
10    
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15    
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20    
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "rpc_server/lsa/lsa.h"
26 #include "system/kerberos.h"
27 #include "auth/kerberos/kerberos.h"
28 #include "librpc/gen_ndr/ndr_drsblobs.h"
29 #include "librpc/gen_ndr/ndr_lsa.h"
30 #include "../lib/crypto/crypto.h"
31 #include "lib/util/tsort.h"
32 #include "dsdb/common/util.h"
33 #include "libcli/security/session.h"
34
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_zero(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         NT_STATUS_HAVE_NO_MEMORY(secret_state);
2873         secret_state->policy = policy_state;
2874
2875         msg = ldb_msg_new(mem_ctx);
2876         if (msg == NULL) {
2877                 return NT_STATUS_NO_MEMORY;
2878         }
2879
2880         if (strncmp("G$", r->in.name.string, 2) == 0) {
2881                 const char *name2;
2882
2883                 secret_state->global = true;
2884
2885                 name = &r->in.name.string[2];
2886                 if (strlen(name) == 0) {
2887                         return NT_STATUS_INVALID_PARAMETER;
2888                 }
2889
2890                 name2 = talloc_asprintf(mem_ctx, "%s Secret",
2891                                         ldb_binary_encode_string(mem_ctx, name));
2892                 NT_STATUS_HAVE_NO_MEMORY(name2);
2893
2894                 /* We need to connect to the database as system, as this is one
2895                  * of the rare RPC calls that must read the secrets (and this
2896                  * is denied otherwise) */
2897                 secret_state->sam_ldb = talloc_reference(secret_state,
2898                                                          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));
2899                 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2900
2901                 /* search for the secret record */
2902                 ret = gendb_search(secret_state->sam_ldb,
2903                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
2904                                    "(&(cn=%s)(objectclass=secret))", 
2905                                    name2);
2906                 if (ret > 0) {
2907                         return NT_STATUS_OBJECT_NAME_COLLISION;
2908                 }
2909                 
2910                 if (ret < 0) {
2911                         DEBUG(0,("Failure searching for CN=%s: %s\n", 
2912                                  name2, ldb_errstring(secret_state->sam_ldb)));
2913                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2914                 }
2915
2916                 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2917                 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2918                 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2919                         return NT_STATUS_NO_MEMORY;
2920                 }
2921
2922                 ret = ldb_msg_add_string(msg, "cn", name2);
2923                 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2924         } else {
2925                 secret_state->global = false;
2926
2927                 name = r->in.name.string;
2928                 if (strlen(name) == 0) {
2929                         return NT_STATUS_INVALID_PARAMETER;
2930                 }
2931
2932                 secret_state->sam_ldb = talloc_reference(secret_state, 
2933                                                          secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
2934                 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2935
2936                 /* search for the secret record */
2937                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2938                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2939                                    &msgs, attrs,
2940                                    "(&(cn=%s)(objectclass=secret))", 
2941                                    ldb_binary_encode_string(mem_ctx, name));
2942                 if (ret > 0) {
2943                         return NT_STATUS_OBJECT_NAME_COLLISION;
2944                 }
2945                 
2946                 if (ret < 0) {
2947                         DEBUG(0,("Failure searching for CN=%s: %s\n", 
2948                                  name, ldb_errstring(secret_state->sam_ldb)));
2949                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2950                 }
2951
2952                 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
2953                                          "cn=%s,cn=LSA Secrets", name);
2954                 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2955                 ret = ldb_msg_add_string(msg, "cn", name);
2956                 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2957         } 
2958
2959         ret = samdb_msg_add_string(secret_state->sam_ldb, mem_ctx, msg,
2960                                    "objectClass", "secret");
2961         if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2962         
2963         secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
2964         NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
2965
2966         /* create the secret */
2967         ret = ldb_add(secret_state->sam_ldb, msg);
2968         if (ret != LDB_SUCCESS) {
2969                 DEBUG(0,("Failed to create secret record %s: %s\n",
2970                          ldb_dn_get_linearized(msg->dn), 
2971                          ldb_errstring(secret_state->sam_ldb)));
2972                 return NT_STATUS_ACCESS_DENIED;
2973         }
2974
2975         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2976         NT_STATUS_HAVE_NO_MEMORY(handle);
2977
2978         handle->data = talloc_steal(handle, secret_state);
2979         
2980         secret_state->access_mask = r->in.access_mask;
2981         secret_state->policy = talloc_reference(secret_state, policy_state);
2982         NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
2983         
2984         *r->out.sec_handle = handle->wire_handle;
2985         
2986         return NT_STATUS_OK;
2987 }
2988
2989
2990 /* 
2991   lsa_OpenSecret 
2992 */
2993 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2994                                struct lsa_OpenSecret *r)
2995 {
2996         struct dcesrv_handle *policy_handle;
2997         
2998         struct lsa_policy_state *policy_state;
2999         struct lsa_secret_state *secret_state;
3000         struct dcesrv_handle *handle;
3001         struct ldb_message **msgs;
3002         const char *attrs[] = {
3003                 NULL
3004         };
3005
3006         const char *name;
3007
3008         int ret;
3009
3010         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3011         ZERO_STRUCTP(r->out.sec_handle);
3012         policy_state = policy_handle->data;
3013
3014         if (!r->in.name.string) {
3015                 return NT_STATUS_INVALID_PARAMETER;
3016         }
3017         
3018         switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3019         {
3020         case SECURITY_SYSTEM:
3021         case SECURITY_ADMINISTRATOR:
3022                 break;
3023         default:
3024                 /* Users and annonymous are not allowed to access secrets */
3025                 return NT_STATUS_ACCESS_DENIED;
3026         }
3027
3028         secret_state = talloc(mem_ctx, struct lsa_secret_state);
3029         if (!secret_state) {
3030                 return NT_STATUS_NO_MEMORY;
3031         }
3032         secret_state->policy = policy_state;
3033
3034         if (strncmp("G$", r->in.name.string, 2) == 0) {
3035                 name = &r->in.name.string[2];
3036                 /* 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) */
3037                 secret_state->sam_ldb = talloc_reference(secret_state, 
3038                                                          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));
3039                 secret_state->global = true;
3040
3041                 if (strlen(name) < 1) {
3042                         return NT_STATUS_INVALID_PARAMETER;
3043                 }
3044
3045                 /* search for the secret record */
3046                 ret = gendb_search(secret_state->sam_ldb,
3047                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
3048                                    "(&(cn=%s Secret)(objectclass=secret))", 
3049                                    ldb_binary_encode_string(mem_ctx, name));
3050                 if (ret == 0) {
3051                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3052                 }
3053                 
3054                 if (ret != 1) {
3055                         DEBUG(0,("Found %d records matching DN %s\n", ret,
3056                                  ldb_dn_get_linearized(policy_state->system_dn)));
3057                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3058                 }
3059         
3060         } else {
3061                 secret_state->global = false;
3062                 secret_state->sam_ldb = talloc_reference(secret_state, 
3063                                                          secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3064
3065                 name = r->in.name.string;
3066                 if (strlen(name) < 1) {
3067                         return NT_STATUS_INVALID_PARAMETER;
3068                 }
3069
3070                 /* search for the secret record */
3071                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3072                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3073                                    &msgs, attrs,
3074                                    "(&(cn=%s)(objectclass=secret))", 
3075                                    ldb_binary_encode_string(mem_ctx, name));
3076                 if (ret == 0) {
3077                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3078                 }
3079                 
3080                 if (ret != 1) {
3081                         DEBUG(0,("Found %d records matching CN=%s\n", 
3082                                  ret, ldb_binary_encode_string(mem_ctx, name)));
3083                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3084                 }
3085         } 
3086
3087         secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3088         
3089         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3090         if (!handle) {
3091                 return NT_STATUS_NO_MEMORY;
3092         }
3093         
3094         handle->data = talloc_steal(handle, secret_state);
3095         
3096         secret_state->access_mask = r->in.access_mask;
3097         secret_state->policy = talloc_reference(secret_state, policy_state);
3098         
3099         *r->out.sec_handle = handle->wire_handle;
3100         
3101         return NT_STATUS_OK;
3102 }
3103
3104
3105 /* 
3106   lsa_SetSecret 
3107 */
3108 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3109                               struct lsa_SetSecret *r)
3110 {
3111
3112         struct dcesrv_handle *h;
3113         struct lsa_secret_state *secret_state;
3114         struct ldb_message *msg;
3115         DATA_BLOB session_key;
3116         DATA_BLOB crypt_secret, secret;
3117         struct ldb_val val;
3118         int ret;
3119         NTSTATUS status = NT_STATUS_OK;
3120
3121         struct timeval now = timeval_current();
3122         NTTIME nt_now = timeval_to_nttime(&now);
3123
3124         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3125
3126         secret_state = h->data;
3127
3128         msg = ldb_msg_new(mem_ctx);
3129         if (msg == NULL) {
3130                 return NT_STATUS_NO_MEMORY;
3131         }
3132
3133         msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3134         if (!msg->dn) {
3135                 return NT_STATUS_NO_MEMORY;
3136         }
3137         status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3138         if (!NT_STATUS_IS_OK(status)) {
3139                 return status;
3140         }
3141
3142         if (r->in.old_val) {
3143                 /* Decrypt */
3144                 crypt_secret.data = r->in.old_val->data;
3145                 crypt_secret.length = r->in.old_val->size;
3146                 
3147                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3148                 if (!NT_STATUS_IS_OK(status)) {
3149                         return status;
3150                 }
3151                 
3152                 val.data = secret.data;
3153                 val.length = secret.length;
3154                 
3155                 /* set value */
3156                 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3157                         return NT_STATUS_NO_MEMORY; 
3158                 }
3159                 
3160                 /* set old value mtime */
3161                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
3162                                          mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3163                         return NT_STATUS_NO_MEMORY; 
3164                 }
3165
3166         } else {
3167                 /* If the old value is not set, then migrate the
3168                  * current value to the old value */
3169                 const struct ldb_val *old_val;
3170                 NTTIME last_set_time;
3171                 struct ldb_message **res;
3172                 const char *attrs[] = {
3173                         "currentValue",
3174                         "lastSetTime",
3175                         NULL
3176                 };
3177                 
3178                 /* search for the secret record */
3179                 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3180                                       secret_state->secret_dn, &res, attrs);
3181                 if (ret == 0) {
3182                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3183                 }
3184                 
3185                 if (ret != 1) {
3186                         DEBUG(0,("Found %d records matching dn=%s\n", ret,
3187                                  ldb_dn_get_linearized(secret_state->secret_dn)));
3188                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3189                 }
3190                 
3191                 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3192                 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3193                 
3194                 if (old_val) {
3195                         /* set old value */
3196                         if (ldb_msg_add_value(msg, "priorValue",
3197                                               old_val, NULL) != LDB_SUCCESS) {
3198                                 return NT_STATUS_NO_MEMORY; 
3199                         }
3200                 } else {
3201                         if (samdb_msg_add_delete(secret_state->sam_ldb, 
3202                                                  mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3203                                 return NT_STATUS_NO_MEMORY;
3204                         }
3205                         
3206                 }
3207                 
3208                 /* set old value mtime */
3209                 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3210                         if (samdb_msg_add_uint64(secret_state->sam_ldb, 
3211                                                  mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3212                                 return NT_STATUS_NO_MEMORY; 
3213                         }
3214                 } else {
3215                         if (samdb_msg_add_uint64(secret_state->sam_ldb, 
3216                                                  mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3217                                 return NT_STATUS_NO_MEMORY; 
3218                         }
3219                 }
3220         }
3221
3222         if (r->in.new_val) {
3223                 /* Decrypt */
3224                 crypt_secret.data = r->in.new_val->data;
3225                 crypt_secret.length = r->in.new_val->size;
3226                 
3227                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3228                 if (!NT_STATUS_IS_OK(status)) {
3229                         return status;
3230                 }
3231                 
3232                 val.data = secret.data;
3233                 val.length = secret.length;
3234                 
3235                 /* set value */
3236                 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3237                         return NT_STATUS_NO_MEMORY; 
3238                 }
3239                 
3240                 /* set new value mtime */
3241                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
3242                                          mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3243                         return NT_STATUS_NO_MEMORY; 
3244                 }
3245                 
3246         } else {
3247                 /* NULL out the NEW value */
3248                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
3249                                          mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3250                         return NT_STATUS_NO_MEMORY; 
3251                 }
3252                 if (samdb_msg_add_delete(secret_state->sam_ldb, 
3253                                          mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3254                         return NT_STATUS_NO_MEMORY;
3255                 }
3256         }
3257
3258         /* modify the samdb record */
3259         ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3260         if (ret != LDB_SUCCESS) {
3261                 /* we really need samdb.c to return NTSTATUS */
3262                 return NT_STATUS_UNSUCCESSFUL;
3263         }
3264
3265         return NT_STATUS_OK;
3266 }
3267
3268
3269 /* 
3270   lsa_QuerySecret 
3271 */
3272 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3273                                 struct lsa_QuerySecret *r)
3274 {
3275         struct dcesrv_handle *h;
3276         struct lsa_secret_state *secret_state;
3277         struct ldb_message *msg;
3278         DATA_BLOB session_key;
3279         DATA_BLOB crypt_secret, secret;
3280         int ret;
3281         struct ldb_message **res;
3282         const char *attrs[] = {
3283                 "currentValue",
3284                 "priorValue",
3285                 "lastSetTime",
3286                 "priorSetTime", 
3287                 NULL
3288         };
3289
3290         NTSTATUS nt_status;
3291
3292         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3293
3294         /* Ensure user is permitted to read this... */
3295         switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3296         {
3297         case SECURITY_SYSTEM:
3298         case SECURITY_ADMINISTRATOR:
3299                 break;
3300         default:
3301                 /* Users and annonymous are not allowed to read secrets */
3302                 return NT_STATUS_ACCESS_DENIED;
3303         }
3304
3305         secret_state = h->data;
3306
3307         /* pull all the user attributes */
3308         ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3309                               secret_state->secret_dn, &res, attrs);
3310         if (ret != 1) {
3311                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3312         }
3313         msg = res[0];
3314         
3315         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3316         if (!NT_STATUS_IS_OK(nt_status)) {
3317                 return nt_status;
3318         }
3319         
3320         if (r->in.old_val) {
3321                 const struct ldb_val *prior_val;
3322                 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3323                 if (!r->out.old_val) {
3324                         return NT_STATUS_NO_MEMORY;
3325                 }
3326                 prior_val = ldb_msg_find_ldb_val(res[0], "priorValue");
3327                 
3328                 if (prior_val && prior_val->length) {
3329                         secret.data = prior_val->data;
3330                         secret.length = prior_val->length;
3331                 
3332                         /* Encrypt */
3333                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3334                         if (!crypt_secret.length) {
3335                                 return NT_STATUS_NO_MEMORY;
3336                         }
3337                         r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3338                         if (!r->out.old_val->buf) {
3339                                 return NT_STATUS_NO_MEMORY;
3340                         }
3341                         r->out.old_val->buf->size = crypt_secret.length;
3342                         r->out.old_val->buf->length = crypt_secret.length;
3343                         r->out.old_val->buf->data = crypt_secret.data;
3344                 }
3345         }
3346         
3347         if (r->in.old_mtime) {
3348                 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3349                 if (!r->out.old_mtime) {
3350                         return NT_STATUS_NO_MEMORY;
3351                 }
3352                 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(res[0], "priorSetTime", 0);
3353         }
3354         
3355         if (r->in.new_val) {
3356                 const struct ldb_val *new_val;
3357                 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3358                 if (!r->out.new_val) {
3359                         return NT_STATUS_NO_MEMORY;
3360                 }
3361
3362                 new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3363                 
3364                 if (new_val && new_val->length) {
3365                         secret.data = new_val->data;
3366                         secret.length = new_val->length;
3367                 
3368                         /* Encrypt */
3369                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3370                         if (!crypt_secret.length) {
3371                                 return NT_STATUS_NO_MEMORY;
3372                         }
3373                         r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3374                         if (!r->out.new_val->buf) {
3375                                 return NT_STATUS_NO_MEMORY;
3376                         }
3377                         r->out.new_val->buf->length = crypt_secret.length;
3378                         r->out.new_val->buf->size = crypt_secret.length;
3379                         r->out.new_val->buf->data = crypt_secret.data;
3380                 }
3381         }
3382         
3383         if (r->in.new_mtime) {
3384                 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3385                 if (!r->out.new_mtime) {
3386                         return NT_STATUS_NO_MEMORY;
3387                 }
3388                 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3389         }
3390         
3391         return NT_STATUS_OK;
3392 }
3393
3394
3395 /* 
3396   lsa_LookupPrivValue
3397 */
3398 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call, 
3399                                     TALLOC_CTX *mem_ctx,
3400                                     struct lsa_LookupPrivValue *r)
3401 {
3402         struct dcesrv_handle *h;
3403         struct lsa_policy_state *state;
3404         int id;
3405
3406         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3407
3408         state = h->data;
3409
3410         id = sec_privilege_id(r->in.name->string);
3411         if (id == SEC_PRIV_INVALID) {
3412                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3413         }
3414
3415         r->out.luid->low = id;
3416         r->out.luid->high = 0;
3417
3418         return NT_STATUS_OK;    
3419 }
3420
3421
3422 /* 
3423   lsa_LookupPrivName 
3424 */
3425 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call, 
3426                                    TALLOC_CTX *mem_ctx,
3427                                    struct lsa_LookupPrivName *r)
3428 {
3429         struct dcesrv_handle *h;
3430         struct lsa_policy_state *state;
3431         struct lsa_StringLarge *name;
3432         const char *privname;
3433
3434         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3435
3436         state = h->data;
3437
3438         if (r->in.luid->high != 0) {
3439                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3440         }
3441
3442         privname = sec_privilege_name(r->in.luid->low);
3443         if (privname == NULL) {
3444                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3445         }
3446
3447         name = talloc(mem_ctx, struct lsa_StringLarge);
3448         if (name == NULL) {
3449                 return NT_STATUS_NO_MEMORY;
3450         }
3451
3452         name->string = privname;
3453
3454         *r->out.name = name;
3455
3456         return NT_STATUS_OK;    
3457 }
3458
3459
3460 /* 
3461   lsa_LookupPrivDisplayName
3462 */
3463 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call, 
3464                                           TALLOC_CTX *mem_ctx,
3465                                           struct lsa_LookupPrivDisplayName *r)
3466 {
3467         struct dcesrv_handle *h;
3468         struct lsa_policy_state *state;
3469         struct lsa_StringLarge *disp_name = NULL;
3470         enum sec_privilege id;
3471
3472         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3473
3474         state = h->data;
3475
3476         id = sec_privilege_id(r->in.name->string);
3477         if (id == SEC_PRIV_INVALID) {
3478                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3479         }
3480
3481         disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3482         if (disp_name == NULL) {
3483                 return NT_STATUS_NO_MEMORY;
3484         }
3485
3486         disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3487         if (disp_name->string == NULL) {
3488                 return NT_STATUS_INTERNAL_ERROR;
3489         }
3490
3491         *r->out.disp_name = disp_name;
3492         *r->out.returned_language_id = 0;
3493
3494         return NT_STATUS_OK;
3495 }
3496
3497
3498 /* 
3499   lsa_EnumAccountsWithUserRight
3500 */
3501 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call, 
3502                                               TALLOC_CTX *mem_ctx,
3503                                               struct lsa_EnumAccountsWithUserRight *r)
3504 {
3505         struct dcesrv_handle *h;
3506         struct lsa_policy_state *state;
3507         int ret, i;
3508         struct ldb_message **res;
3509         const char * const attrs[] = { "objectSid", NULL};
3510         const char *privname;
3511
3512         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3513
3514         state = h->data;
3515
3516         if (r->in.name == NULL) {
3517                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3518         } 
3519
3520         privname = r->in.name->string;
3521         if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
3522                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3523         }
3524
3525         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs, 
3526                            "privilege=%s", privname);
3527         if (ret < 0) {
3528                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3529         }
3530         if (ret == 0) {
3531                 return NT_STATUS_NO_MORE_ENTRIES;
3532         }
3533
3534         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3535         if (r->out.sids->sids == NULL) {
3536                 return NT_STATUS_NO_MEMORY;
3537         }
3538         for (i=0;i<ret;i++) {
3539                 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3540                                                                 res[i], "objectSid");
3541                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3542         }
3543         r->out.sids->num_sids = ret;
3544
3545         return NT_STATUS_OK;
3546 }
3547
3548
3549 /* 
3550   lsa_AddAccountRights
3551 */
3552 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call, 
3553                                      TALLOC_CTX *mem_ctx,
3554                                      struct lsa_AddAccountRights *r)
3555 {
3556         struct dcesrv_handle *h;
3557         struct lsa_policy_state *state;
3558
3559         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3560
3561         state = h->data;
3562
3563         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
3564                                           LDB_FLAG_MOD_ADD,
3565                                           r->in.sid, r->in.rights);
3566 }
3567
3568
3569 /* 
3570   lsa_RemoveAccountRights
3571 */
3572 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call, 
3573                                         TALLOC_CTX *mem_ctx,
3574                                         struct lsa_RemoveAccountRights *r)
3575 {
3576         struct dcesrv_handle *h;
3577         struct lsa_policy_state *state;
3578
3579         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3580
3581         state = h->data;
3582
3583         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
3584                                           LDB_FLAG_MOD_DELETE,
3585                                           r->in.sid, r->in.rights);
3586 }
3587
3588
3589 /* 
3590   lsa_StorePrivateData
3591 */
3592 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3593                        struct lsa_StorePrivateData *r)
3594 {
3595         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3596 }
3597
3598
3599 /* 
3600   lsa_RetrievePrivateData
3601 */
3602 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3603                        struct lsa_RetrievePrivateData *r)
3604 {
3605         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3606 }
3607
3608
3609 /* 
3610   lsa_GetUserName
3611 */
3612 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3613                                 struct lsa_GetUserName *r)
3614 {
3615         NTSTATUS status = NT_STATUS_OK;
3616         const char *account_name;
3617         const char *authority_name;
3618         struct lsa_String *_account_name;
3619         struct lsa_String *_authority_name = NULL;
3620
3621         /* this is what w2k3 does */
3622         r->out.account_name = r->in.account_name;
3623         r->out.authority_name = r->in.authority_name;
3624
3625         if (r->in.account_name
3626             && *r->in.account_name
3627             /* && *(*r->in.account_name)->string */
3628             ) {
3629                 return NT_STATUS_INVALID_PARAMETER;
3630         }
3631
3632         if (r->in.authority_name
3633             && *r->in.authority_name
3634             /* && *(*r->in.authority_name)->string */
3635             ) {
3636                 return NT_STATUS_INVALID_PARAMETER;
3637         }
3638
3639         account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->account_name);
3640         authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->server_info->domain_name);
3641
3642         _account_name = talloc(mem_ctx, struct lsa_String);
3643         NT_STATUS_HAVE_NO_MEMORY(_account_name);
3644         _account_name->string = account_name;
3645
3646         if (r->in.authority_name) {
3647                 _authority_name = talloc(mem_ctx, struct lsa_String);
3648                 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3649                 _authority_name->string = authority_name;
3650         }
3651
3652         *r->out.account_name = _account_name;
3653         if (r->out.authority_name) {
3654                 *r->out.authority_name = _authority_name;
3655         }
3656
3657         return status;
3658 }
3659
3660 /*
3661   lsa_SetInfoPolicy2
3662 */
3663 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3664                                    TALLOC_CTX *mem_ctx,
3665                                    struct lsa_SetInfoPolicy2 *r)
3666 {
3667         /* need to support these */
3668         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3669 }
3670
3671 /*
3672   lsa_QueryDomainInformationPolicy
3673 */
3674 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3675                                                  TALLOC_CTX *mem_ctx,
3676                                                  struct lsa_QueryDomainInformationPolicy *r)
3677 {
3678         union lsa_DomainInformationPolicy *info;
3679
3680         info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
3681         if (!info) {
3682                 return NT_STATUS_NO_MEMORY;
3683         }
3684
3685         switch (r->in.level) {
3686         case LSA_DOMAIN_INFO_POLICY_EFS:
3687                 talloc_free(info);
3688                 *r->out.info = NULL;
3689                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3690         case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3691         {
3692                 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3693                 struct smb_krb5_context *smb_krb5_context;
3694                 int ret = smb_krb5_init_context(mem_ctx, 
3695                                                         dce_call->event_ctx, 
3696                                                         dce_call->conn->dce_ctx->lp_ctx,
3697                                                         &smb_krb5_context);
3698                 if (ret != 0) {
3699                         talloc_free(info);
3700                         *r->out.info = NULL;
3701                         return NT_STATUS_INTERNAL_ERROR;
3702                 }
3703                 k->enforce_restrictions = 0; /* FIXME, details missing from MS-LSAD 2.2.53 */
3704                 k->service_tkt_lifetime = 0; /* Need to find somewhere to store this, and query in KDC too */
3705                 k->user_tkt_lifetime = 0;    /* Need to find somewhere to store this, and query in KDC too */
3706                 k->user_tkt_renewaltime = 0; /* Need to find somewhere to store this, and query in KDC too */
3707                 k->clock_skew = krb5_get_max_time_skew(smb_krb5_context->krb5_context);
3708                 k->reserved = 0;
3709                 talloc_free(smb_krb5_context);
3710                 *r->out.info = info;
3711                 return NT_STATUS_OK;
3712         }
3713         default:
3714                 talloc_free(info);
3715                 *r->out.info = NULL;
3716                 return NT_STATUS_INVALID_INFO_CLASS;
3717         }
3718 }
3719
3720 /*
3721   lsa_SetDomInfoPolicy
3722 */
3723 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3724                                               TALLOC_CTX *mem_ctx,
3725                                               struct lsa_SetDomainInformationPolicy *r)
3726 {
3727         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3728 }
3729
3730 /*
3731   lsa_TestCall
3732 */
3733 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3734                              TALLOC_CTX *mem_ctx,
3735                              struct lsa_TestCall *r)
3736 {
3737         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3738 }
3739
3740 /* 
3741   lsa_CREDRWRITE 
3742 */
3743 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3744                        struct lsa_CREDRWRITE *r)
3745 {
3746         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3747 }
3748
3749
3750 /* 
3751   lsa_CREDRREAD 
3752 */
3753 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3754                        struct lsa_CREDRREAD *r)
3755 {
3756         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3757 }
3758
3759
3760 /* 
3761   lsa_CREDRENUMERATE 
3762 */
3763 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3764                        struct lsa_CREDRENUMERATE *r)
3765 {
3766         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3767 }
3768
3769
3770 /* 
3771   lsa_CREDRWRITEDOMAINCREDENTIALS 
3772 */
3773 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3774                        struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3775 {
3776         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3777 }
3778
3779
3780 /* 
3781   lsa_CREDRREADDOMAINCREDENTIALS 
3782 */
3783 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3784                        struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3785 {
3786         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3787 }
3788
3789
3790 /* 
3791   lsa_CREDRDELETE 
3792 */
3793 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3794                        struct lsa_CREDRDELETE *r)
3795 {
3796         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3797 }
3798
3799
3800 /* 
3801   lsa_CREDRGETTARGETINFO 
3802 */
3803 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3804                        struct lsa_CREDRGETTARGETINFO *r)
3805 {
3806         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3807 }
3808
3809
3810 /* 
3811   lsa_CREDRPROFILELOADED 
3812 */
3813 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3814                        struct lsa_CREDRPROFILELOADED *r)
3815 {
3816         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3817 }
3818
3819
3820 /* 
3821   lsa_CREDRGETSESSIONTYPES 
3822 */
3823 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3824                        struct lsa_CREDRGETSESSIONTYPES *r)
3825 {
3826         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3827 }
3828
3829
3830 /* 
3831   lsa_LSARREGISTERAUDITEVENT 
3832 */
3833 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3834                        struct lsa_LSARREGISTERAUDITEVENT *r)
3835 {
3836         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3837 }
3838
3839
3840 /* 
3841   lsa_LSARGENAUDITEVENT 
3842 */
3843 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3844                        struct lsa_LSARGENAUDITEVENT *r)
3845 {
3846         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3847 }
3848
3849
3850 /* 
3851   lsa_LSARUNREGISTERAUDITEVENT 
3852 */
3853 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3854                        struct lsa_LSARUNREGISTERAUDITEVENT *r)
3855 {
3856         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3857 }
3858
3859
3860 /* 
3861   lsa_lsaRQueryForestTrustInformation 
3862 */
3863 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3864                        struct lsa_lsaRQueryForestTrustInformation *r)
3865 {
3866         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3867 }
3868
3869 #define DNS_CMP_MATCH 0
3870 #define DNS_CMP_FIRST_IS_CHILD 1
3871 #define DNS_CMP_SECOND_IS_CHILD 2
3872 #define DNS_CMP_NO_MATCH 3
3873
3874 /* this function assumes names are well formed DNS names.
3875  * it doesn't validate them */
3876 static int dns_cmp(const char *s1, size_t l1,
3877                    const char *s2, size_t l2)
3878 {
3879         const char *p1, *p2;
3880         size_t t1, t2;
3881         int cret;
3882
3883         if (l1 == l2) {
3884                 if (strcasecmp_m(s1, s2) == 0) {
3885                         return DNS_CMP_MATCH;
3886                 }
3887                 return DNS_CMP_NO_MATCH;
3888         }
3889
3890         if (l1 > l2) {
3891                 p1 = s1;
3892                 p2 = s2;
3893                 t1 = l1;
3894                 t2 = l2;
3895                 cret = DNS_CMP_FIRST_IS_CHILD;
3896         } else {
3897                 p1 = s2;
3898                 p2 = s1;
3899                 t1 = l2;
3900                 t2 = l1;
3901                 cret = DNS_CMP_SECOND_IS_CHILD;
3902         }
3903
3904         if (p1[t1 - t2 - 1] != '.') {
3905                 return DNS_CMP_NO_MATCH;
3906         }
3907
3908         if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
3909                 return cret;
3910         }
3911
3912         return DNS_CMP_NO_MATCH;
3913 }
3914
3915 /* decode all TDOs forest trust info blobs */
3916 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
3917                             struct ldb_message *msg,
3918                             struct ForestTrustInfo *info)
3919 {
3920         const struct ldb_val *ft_blob;
3921         enum ndr_err_code ndr_err;
3922
3923         ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3924         if (!ft_blob || !ft_blob->data) {
3925                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3926         }
3927         /* ldb_val is equivalent to DATA_BLOB */
3928         ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
3929                                            (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
3930         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3931                 return NT_STATUS_INVALID_DOMAIN_STATE;
3932         }
3933
3934         return NT_STATUS_OK;
3935 }
3936
3937 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
3938                             struct ForestTrustInfo *fti)
3939 {
3940         struct ForestTrustDataDomainInfo *info;
3941         struct ForestTrustInfoRecord *rec;
3942
3943         fti->version = 1;
3944         fti->count = 2;
3945         fti->records = talloc_array(fti,
3946                                     struct ForestTrustInfoRecordArmor, 2);
3947         if (!fti->records) {
3948                 return NT_STATUS_NO_MEMORY;
3949         }
3950
3951         /* TLN info */
3952         rec = &fti->records[0].record;
3953
3954         rec->flags = 0;
3955         rec->timestamp = 0;
3956         rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
3957
3958         rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
3959         if (!rec->data.name.string) {
3960                 return NT_STATUS_NO_MEMORY;
3961         }
3962         rec->data.name.size = strlen(rec->data.name.string);
3963
3964         /* DOMAIN info */
3965         rec = &fti->records[1].record;
3966
3967         rec->flags = 0;
3968         rec->timestamp = 0;
3969         rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
3970
3971         info = &rec->data.info;
3972
3973         info->sid = *ps->domain_sid;
3974         info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
3975         if (!info->dns_name.string) {
3976                 return NT_STATUS_NO_MEMORY;
3977         }
3978         info->dns_name.size = strlen(info->dns_name.string);
3979         info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
3980         if (!info->netbios_name.string) {
3981                 return NT_STATUS_NO_MEMORY;
3982         }
3983         info->netbios_name.size = strlen(info->netbios_name.string);
3984
3985         return NT_STATUS_OK;
3986 }
3987
3988 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
3989                              struct lsa_ForestTrustInformation *lfti,
3990                              struct ForestTrustInfo *fti)
3991 {
3992         struct lsa_ForestTrustRecord *lrec;
3993         struct ForestTrustInfoRecord *rec;
3994         struct lsa_StringLarge *tln;
3995         struct lsa_ForestTrustDomainInfo *info;
3996         uint32_t i;
3997
3998         fti->version = 1;
3999         fti->count = lfti->count;
4000         fti->records = talloc_array(mem_ctx,
4001                                     struct ForestTrustInfoRecordArmor,
4002                                     fti->count);
4003         if (!fti->records) {
4004                 return NT_STATUS_NO_MEMORY;
4005         }
4006         for (i = 0; i < fti->count; i++) {
4007                 lrec = lfti->entries[i];
4008                 rec = &fti->records[i].record;
4009
4010                 rec->flags = lrec->flags;
4011                 rec->timestamp = lrec->time;
4012                 rec->type = lrec->type;
4013
4014                 switch (lrec->type) {
4015                 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4016                 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4017                         tln = &lrec->forest_trust_data.top_level_name;
4018                         rec->data.name.string =
4019                                 talloc_strdup(mem_ctx, tln->string);
4020                         if (!rec->data.name.string) {
4021                                 return NT_STATUS_NO_MEMORY;
4022                         }
4023                         rec->data.name.size = strlen(rec->data.name.string);
4024                         break;
4025                 case LSA_FOREST_TRUST_DOMAIN_INFO:
4026                         info = &lrec->forest_trust_data.domain_info;
4027                         rec->data.info.sid = *info->domain_sid;
4028                         rec->data.info.dns_name.string =
4029                                 talloc_strdup(mem_ctx,
4030                                             info->dns_domain_name.string);
4031                         if (!rec->data.info.dns_name.string) {
4032                                 return NT_STATUS_NO_MEMORY;
4033                         }
4034                         rec->data.info.dns_name.size =
4035                                 strlen(rec->data.info.dns_name.string);
4036                         rec->data.info.netbios_name.string =
4037                                 talloc_strdup(mem_ctx,
4038                                             info->netbios_domain_name.string);
4039                         if (!rec->data.info.netbios_name.string) {
4040                                 return NT_STATUS_NO_MEMORY;
4041                         }
4042                         rec->data.info.netbios_name.size =
4043                                 strlen(rec->data.info.netbios_name.string);
4044                         break;
4045                 default:
4046                         return NT_STATUS_INVALID_DOMAIN_STATE;
4047                 }
4048         }
4049
4050         return NT_STATUS_OK;
4051 }
4052
4053 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4054                               uint32_t idx, uint32_t collision_type,
4055                               uint32_t conflict_type, const char *tdo_name);
4056
4057 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4058                               const char *tdo_name,
4059                               struct ForestTrustInfo *tdo_fti,
4060                               struct ForestTrustInfo *new_fti,
4061                               struct lsa_ForestTrustCollisionInfo *c_info)
4062 {
4063         struct ForestTrustInfoRecord *nrec;
4064         struct ForestTrustInfoRecord *trec;
4065         const char *dns_name;
4066         const char *nb_name;
4067         struct dom_sid *sid;
4068         const char *tname;
4069         size_t dns_len;
4070         size_t nb_len;
4071         size_t tlen;
4072         NTSTATUS nt_status;
4073         uint32_t new_fti_idx;
4074         uint32_t i;
4075         /* use always TDO type, until we understand when Xref can be used */
4076         uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4077         bool tln_conflict;
4078         bool sid_conflict;
4079         bool nb_conflict;
4080         bool exclusion;
4081         bool ex_rule;
4082         int ret;
4083
4084         for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4085
4086                 nrec = &new_fti->records[new_fti_idx].record;
4087                 dns_name = NULL;
4088                 tln_conflict = false;
4089                 sid_conflict = false;
4090                 nb_conflict = false;
4091                 exclusion = false;
4092
4093                 switch (nrec->type) {
4094                 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4095                         /* exclusions do not conflict by definition */
4096                         break;
4097
4098                 case FOREST_TRUST_TOP_LEVEL_NAME:
4099                         dns_name = nrec->data.name.string;
4100                         dns_len = nrec->data.name.size;
4101                         break;
4102
4103                 case LSA_FOREST_TRUST_DOMAIN_INFO:
4104                         dns_name = nrec->data.info.dns_name.string;
4105                         dns_len = nrec->data.info.dns_name.size;
4106                         nb_name = nrec->data.info.netbios_name.string;
4107                         nb_len = nrec->data.info.netbios_name.size;
4108                         sid = &nrec->data.info.sid;
4109                         break;
4110                 }
4111
4112                 if (!dns_name) continue;
4113
4114                 /* check if this is already taken and not excluded */
4115                 for (i = 0; i < tdo_fti->count; i++) {
4116                         trec = &tdo_fti->records[i].record;
4117
4118                         switch (trec->type) {
4119                         case FOREST_TRUST_TOP_LEVEL_NAME:
4120                                 ex_rule = false;
4121                                 tname = trec->data.name.string;
4122                                 tlen = trec->data.name.size;
4123                                 break;
4124                         case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4125                                 ex_rule = true;
4126                                 tname = trec->data.name.string;
4127                                 tlen = trec->data.name.size;
4128                                 break;
4129                         case FOREST_TRUST_DOMAIN_INFO:
4130                                 ex_rule = false;
4131                                 tname = trec->data.info.dns_name.string;
4132                                 tlen = trec->data.info.dns_name.size;
4133                         }
4134                         ret = dns_cmp(dns_name, dns_len, tname, tlen);
4135                         switch (ret) {
4136                         case DNS_CMP_MATCH:
4137                                 /* if it matches exclusion,
4138                                  * it doesn't conflict */
4139                                 if (ex_rule) {
4140                                         exclusion = true;
4141                                         break;
4142                                 }
4143                                 /* fall through */
4144                         case DNS_CMP_FIRST_IS_CHILD:
4145                         case DNS_CMP_SECOND_IS_CHILD:
4146                                 tln_conflict = true;
4147                                 /* fall through */
4148                         default:
4149                                 break;
4150                         }
4151
4152                         /* explicit exclusion, no dns name conflict here */
4153                         if (exclusion) {
4154                                 tln_conflict = false;
4155                         }
4156
4157                         if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4158                                 continue;
4159                         }
4160
4161                         /* also test for domain info */
4162                         if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4163                             dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4164                                 sid_conflict = true;
4165                         }
4166                         if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4167                             strcasecmp_m(trec->data.info.netbios_name.string,
4168                                          nb_name) == 0) {
4169                                 nb_conflict = true;
4170                         }
4171                 }
4172
4173                 if (tln_conflict) {
4174                         nt_status = add_collision(c_info, new_fti_idx,
4175                                                   collision_type,
4176                                                   LSA_TLN_DISABLED_CONFLICT,
4177                                                   tdo_name);
4178                 }
4179                 if (sid_conflict) {
4180                         nt_status = add_collision(c_info, new_fti_idx,
4181                                                   collision_type,
4182                                                   LSA_SID_DISABLED_CONFLICT,
4183                                                   tdo_name);
4184                 }
4185                 if (nb_conflict) {
4186                         nt_status = add_collision(c_info, new_fti_idx,
4187                                                   collision_type,
4188                                                   LSA_NB_DISABLED_CONFLICT,
4189                                                   tdo_name);
4190                 }
4191         }
4192
4193         return NT_STATUS_OK;
4194 }
4195
4196 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4197                               uint32_t idx, uint32_t collision_type,
4198                               uint32_t conflict_type, const char *tdo_name)
4199 {
4200         struct lsa_ForestTrustCollisionRecord **es;
4201         uint32_t i = c_info->count;
4202
4203         es = talloc_realloc(c_info, c_info->entries,
4204                             struct lsa_ForestTrustCollisionRecord *, i + 1);
4205         if (!es) {
4206                 return NT_STATUS_NO_MEMORY;
4207         }
4208         c_info->entries = es;
4209         c_info->count = i + 1;
4210
4211         es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4212         if (!es[i]) {
4213                 return NT_STATUS_NO_MEMORY;
4214         }
4215
4216         es[i]->index = idx;
4217         es[i]->type = collision_type;
4218         es[i]->flags.flags = conflict_type;
4219         es[i]->name.string = talloc_strdup(es[i], tdo_name);
4220         if (!es[i]->name.string) {
4221                 return NT_STATUS_NO_MEMORY;
4222         }
4223         es[i]->name.size = strlen(es[i]->name.string);
4224
4225         return NT_STATUS_OK;
4226 }
4227
4228 /*
4229   lsa_lsaRSetForestTrustInformation
4230 */
4231 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4232                                                          TALLOC_CTX *mem_ctx,
4233                                                          struct lsa_lsaRSetForestTrustInformation *r)
4234 {
4235         struct dcesrv_handle *h;
4236         struct lsa_policy_state *p_state;
4237         const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4238                                       "msDS-TrustForestTrustInfo", NULL };
4239         struct ldb_message **dom_res = NULL;
4240         struct ldb_dn *tdo_dn;
4241         struct ldb_message *msg;
4242         int num_res, i;
4243         const char *td_name;
4244         uint32_t trust_attributes;
4245         struct lsa_ForestTrustCollisionInfo *c_info;
4246         struct ForestTrustInfo *nfti;
4247         struct ForestTrustInfo *fti;
4248         DATA_BLOB ft_blob;
4249         enum ndr_err_code ndr_err;
4250         NTSTATUS nt_status;
4251         bool am_rodc;
4252         int ret;
4253
4254         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4255
4256         p_state = h->data;
4257
4258         if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4259                 return NT_STATUS_INVALID_DOMAIN_STATE;
4260         }
4261
4262         /* abort if we are not a PDC */
4263         if (!samdb_is_pdc(p_state->sam_ldb)) {
4264                 return NT_STATUS_INVALID_DOMAIN_ROLE;
4265         }
4266
4267         ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
4268         if (ret == LDB_SUCCESS && am_rodc) {
4269                 return NT_STATUS_NO_SUCH_DOMAIN;
4270         }
4271
4272         /* check caller has TRUSTED_SET_AUTH */
4273
4274         /* fetch all trusted domain objects */
4275         num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4276                                p_state->system_dn,
4277                                &dom_res, trust_attrs,
4278                                "(objectclass=trustedDomain)");
4279         if (num_res == 0) {
4280                 return NT_STATUS_NO_SUCH_DOMAIN;
4281         }
4282
4283         for (i = 0; i < num_res; i++) {
4284                 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4285                                                       "trustPartner", NULL);
4286                 if (!td_name) {
4287                         return NT_STATUS_INVALID_DOMAIN_STATE;
4288                 }
4289                 if (strcasecmp_m(td_name,
4290                                  r->in.trusted_domain_name->string) == 0) {
4291                         break;
4292                 }
4293         }
4294         if (i >= num_res) {
4295                 return NT_STATUS_NO_SUCH_DOMAIN;
4296         }
4297
4298         tdo_dn = dom_res[i]->dn;
4299
4300         trust_attributes = ldb_msg_find_attr_as_uint(dom_res[i],
4301                                                      "trustAttributes", 0);
4302         if (!(trust_attributes & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4303                 return NT_STATUS_INVALID_PARAMETER;
4304         }
4305
4306         if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4307                 return NT_STATUS_INVALID_PARAMETER;
4308         }
4309
4310         nfti = talloc(mem_ctx, struct ForestTrustInfo);
4311         if (!nfti) {
4312                 return NT_STATUS_NO_MEMORY;
4313         }
4314
4315         nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4316         if (!NT_STATUS_IS_OK(nt_status)) {
4317                 return nt_status;
4318         }
4319
4320         c_info = talloc_zero(r->out.collision_info,
4321                              struct lsa_ForestTrustCollisionInfo);
4322         if (!c_info) {
4323                 return NT_STATUS_NO_MEMORY;
4324         }
4325
4326         /* first check own info, then other domains */
4327         fti = talloc(mem_ctx, struct ForestTrustInfo);
4328         if (!fti) {
4329                 return NT_STATUS_NO_MEMORY;
4330         }
4331
4332         nt_status = own_ft_info(p_state, fti);
4333         if (!NT_STATUS_IS_OK(nt_status)) {
4334                 return nt_status;
4335         }
4336
4337         nt_status = check_ft_info(c_info, p_state->domain_dns,
4338                                   fti, nfti, c_info);
4339         if (!NT_STATUS_IS_OK(nt_status)) {
4340                 return nt_status;
4341         }
4342
4343         for (i = 0; i < num_res; i++) {
4344                 fti = talloc(mem_ctx, struct ForestTrustInfo);
4345                 if (!fti) {
4346                         return NT_STATUS_NO_MEMORY;
4347                 }
4348
4349                 nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
4350                 if (!NT_STATUS_IS_OK(nt_status)) {
4351                         if (NT_STATUS_EQUAL(nt_status,
4352                             NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4353                                 continue;
4354                         }
4355                         return nt_status;
4356                 }
4357
4358                 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4359                                                       "trustPartner", NULL);
4360                 if (!td_name) {
4361                         return NT_STATUS_INVALID_DOMAIN_STATE;
4362                 }
4363
4364                 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4365                 if (!NT_STATUS_IS_OK(nt_status)) {
4366                         return nt_status;
4367                 }
4368         }
4369
4370         *r->out.collision_info = c_info;
4371
4372         if (r->in.check_only != 0) {
4373                 return NT_STATUS_OK;
4374         }
4375
4376         /* not just a check, write info back */
4377
4378         ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
4379                                        (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4380         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4381                 return NT_STATUS_INVALID_PARAMETER;
4382         }
4383
4384         msg = ldb_msg_new(mem_ctx);
4385         if (msg == NULL) {
4386                 return NT_STATUS_NO_MEMORY;
4387         }
4388
4389         msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4390         if (!msg->dn) {
4391                 return NT_STATUS_NO_MEMORY;
4392         }
4393
4394         ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4395                                 LDB_FLAG_MOD_REPLACE, NULL);
4396         if (ret != LDB_SUCCESS) {
4397                 return NT_STATUS_NO_MEMORY;
4398         }
4399         ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4400                                 &ft_blob, NULL);
4401         if (ret != LDB_SUCCESS) {
4402                 return NT_STATUS_NO_MEMORY;
4403         }
4404
4405         ret = ldb_modify(p_state->sam_ldb, msg);
4406         if (ret != LDB_SUCCESS) {
4407                 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4408                           ldb_errstring(p_state->sam_ldb)));
4409
4410                 switch (ret) {
4411                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4412                         return NT_STATUS_ACCESS_DENIED;
4413                 default:
4414                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
4415                 }
4416         }
4417
4418         return NT_STATUS_OK;
4419 }
4420
4421 /* 
4422   lsa_CREDRRENAME 
4423 */
4424 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4425                        struct lsa_CREDRRENAME *r)
4426 {
4427         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4428 }
4429
4430
4431
4432 /* 
4433   lsa_LSAROPENPOLICYSCE 
4434 */
4435 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4436                        struct lsa_LSAROPENPOLICYSCE *r)
4437 {
4438         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4439 }
4440
4441
4442 /* 
4443   lsa_LSARADTREGISTERSECURITYEVENTSOURCE 
4444 */
4445 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4446                        struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4447 {
4448         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4449 }
4450
4451
4452 /* 
4453   lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE 
4454 */
4455 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4456                        struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4457 {
4458         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4459 }
4460
4461
4462 /* 
4463   lsa_LSARADTREPORTSECURITYEVENT 
4464 */
4465 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4466                        struct lsa_LSARADTREPORTSECURITYEVENT *r)
4467 {
4468         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4469 }
4470
4471
4472 /* include the generated boilerplate */
4473 #include "librpc/gen_ndr/ndr_lsa_s.c"
4474
4475
4476
4477 /*****************************************
4478 NOTE! The remaining calls below were
4479 removed in w2k3, so the DCESRV_FAULT()
4480 replies are the correct implementation. Do
4481 not try and fill these in with anything else
4482 ******************************************/
4483
4484 /* 
4485   dssetup_DsRoleDnsNameToFlatName 
4486 */
4487 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4488                                         struct dssetup_DsRoleDnsNameToFlatName *r)
4489 {
4490         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4491 }
4492
4493
4494 /* 
4495   dssetup_DsRoleDcAsDc 
4496 */
4497 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4498                              struct dssetup_DsRoleDcAsDc *r)
4499 {
4500         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4501 }
4502
4503
4504 /* 
4505   dssetup_DsRoleDcAsReplica 
4506 */
4507 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4508                                   struct dssetup_DsRoleDcAsReplica *r)
4509 {
4510         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4511 }
4512
4513
4514 /* 
4515   dssetup_DsRoleDemoteDc 
4516 */
4517 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4518                                struct dssetup_DsRoleDemoteDc *r)
4519 {
4520         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4521 }
4522
4523
4524 /* 
4525   dssetup_DsRoleGetDcOperationProgress 
4526 */
4527 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4528                                              struct dssetup_DsRoleGetDcOperationProgress *r)
4529 {
4530         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4531 }
4532
4533
4534 /* 
4535   dssetup_DsRoleGetDcOperationResults 
4536 */
4537 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4538                                             struct dssetup_DsRoleGetDcOperationResults *r)
4539 {
4540         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4541 }
4542
4543
4544 /* 
4545   dssetup_DsRoleCancel 
4546 */
4547 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4548                              struct dssetup_DsRoleCancel *r)
4549 {
4550         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4551 }
4552
4553
4554 /* 
4555   dssetup_DsRoleServerSaveStateForUpgrade 
4556 */
4557 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4558                                                 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4559 {
4560         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4561 }
4562
4563
4564 /* 
4565   dssetup_DsRoleUpgradeDownlevelServer 
4566 */
4567 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4568                                              struct dssetup_DsRoleUpgradeDownlevelServer *r)
4569 {
4570         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4571 }
4572
4573
4574 /* 
4575   dssetup_DsRoleAbortDownlevelServerUpgrade 
4576 */
4577 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4578                                                   struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4579 {
4580         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4581 }
4582
4583
4584 /* include the generated boilerplate */
4585 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4586
4587 NTSTATUS dcerpc_server_lsa_init(void)
4588 {
4589         NTSTATUS ret;
4590         
4591         ret = dcerpc_server_dssetup_init();
4592         if (!NT_STATUS_IS_OK(ret)) {
4593                 return ret;
4594         }
4595         ret = dcerpc_server_lsarpc_init();
4596         if (!NT_STATUS_IS_OK(ret)) {
4597                 return ret;
4598         }
4599         return ret;
4600 }