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