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