5acdfe8046081f43617ed6d3dbf39ed3e11af82c
[ddiss/samba.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
1 /* need access mask/acl implementation */
2
3 /* 
4    Unix SMB/CIFS implementation.
5
6    endpoint server for the lsarpc pipe
7
8    Copyright (C) Andrew Tridgell 2004
9    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
10    
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15    
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20    
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "rpc_server/lsa/lsa.h"
26 #include "system/kerberos.h"
27 #include "auth/kerberos/kerberos.h"
28 #include "librpc/gen_ndr/ndr_drsblobs.h"
29 #include "librpc/gen_ndr/ndr_lsa.h"
30 #include "../lib/crypto/crypto.h"
31 #include "lib/util/tsort.h"
32 #include "dsdb/common/util.h"
33 #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->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         NTSTATUS nt_status;
1605         struct ldb_message **msgs;
1606         struct ldb_message *msg;
1607         bool add_outgoing = false;
1608         bool add_incoming = false;
1609         bool del_outgoing = false;
1610         bool del_incoming = false;
1611         bool in_transaction = false;
1612         int ret;
1613         bool am_rodc;
1614
1615         switch (level) {
1616         case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1617                 posix_offset = &info->posix_offset.posix_offset;
1618                 break;
1619         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1620                 info_ex = &info->info_ex;
1621                 break;
1622         case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1623                 auth_info = &info->auth_info;
1624                 break;
1625         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1626                 posix_offset = &info->full_info.posix_offset.posix_offset;
1627                 info_ex = &info->full_info.info_ex;
1628                 auth_info = &info->full_info.auth_info;
1629                 break;
1630         case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1631                 auth_info_int = &info->auth_info_internal;
1632                 break;
1633         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1634                 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1635                 info_ex = &info->full_info_internal.info_ex;
1636                 auth_info_int = &info->full_info_internal.auth_info;
1637                 break;
1638         case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1639                 enc_types = &info->enc_types.enc_types;
1640                 break;
1641         default:
1642                 return NT_STATUS_INVALID_PARAMETER;
1643         }
1644
1645         if (auth_info) {
1646                 /* FIXME: not handled yet */
1647                 return NT_STATUS_INVALID_PARAMETER;
1648         }
1649
1650         /* decode auth_info_int if set */
1651         if (auth_info_int) {
1652
1653                 /* now decrypt blob */
1654                 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1655                                             auth_info_int->auth_blob.size);
1656
1657                 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1658                                                    &auth_blob, &auth_struct);
1659                 if (!NT_STATUS_IS_OK(nt_status)) {
1660                         return nt_status;
1661                 }
1662         }
1663
1664         if (info_ex) {
1665                 /* verify data matches */
1666                 if (info_ex->trust_attributes &
1667                     LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1668                         /* TODO: check what behavior level we have */
1669                        if (strcasecmp_m(p_state->domain_dns,
1670                                         p_state->forest_dns) != 0) {
1671                                 return NT_STATUS_INVALID_DOMAIN_STATE;
1672                         }
1673                 }
1674
1675                 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1676                 if (ret == LDB_SUCCESS && am_rodc) {
1677                         return NT_STATUS_NO_SUCH_DOMAIN;
1678                 }
1679
1680                 /* verify only one object matches the dns/netbios/sid
1681                  * triplet and that this is the one we already have */
1682                 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1683                                     p_state->system_dn,
1684                                     info_ex->domain_name.string,
1685                                     info_ex->netbios_name.string,
1686                                     info_ex->sid, &msgs);
1687                 if (!NT_STATUS_IS_OK(nt_status)) {
1688                         return nt_status;
1689                 }
1690                 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1691                         return NT_STATUS_OBJECT_NAME_COLLISION;
1692                 }
1693                 talloc_free(msgs);
1694         }
1695
1696         /* TODO: should we fetch previous values from the existing entry
1697          * and append them ? */
1698         if (auth_struct.incoming.count) {
1699                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1700                                                      &auth_struct.incoming,
1701                                                      &trustAuthIncoming);
1702                 if (!NT_STATUS_IS_OK(nt_status)) {
1703                         return nt_status;
1704                 }
1705         } else {
1706                 trustAuthIncoming = data_blob(NULL, 0);
1707         }
1708
1709         if (auth_struct.outgoing.count) {
1710                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1711                                                      &auth_struct.outgoing,
1712                                                      &trustAuthOutgoing);
1713                 if (!NT_STATUS_IS_OK(nt_status)) {
1714                         return nt_status;
1715                 }
1716         } else {
1717                 trustAuthOutgoing = data_blob(NULL, 0);
1718         }
1719
1720         msg = ldb_msg_new(mem_ctx);
1721         if (msg == NULL) {
1722                 return NT_STATUS_NO_MEMORY;
1723         }
1724         msg->dn = dom_msg->dn;
1725
1726         if (posix_offset) {
1727                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1728                                                   dom_msg, msg,
1729                                                   "trustPosixOffset",
1730                                                   *posix_offset, NULL);
1731                 if (!NT_STATUS_IS_OK(nt_status)) {
1732                         return nt_status;
1733                 }
1734         }
1735
1736         if (info_ex) {
1737                 uint32_t origattrs;
1738                 uint32_t origdir;
1739                 int origtype;
1740
1741                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1742                                                   dom_msg, msg,
1743                                                   "trustDirection",
1744                                                   info_ex->trust_direction,
1745                                                   &origdir);
1746                 if (!NT_STATUS_IS_OK(nt_status)) {
1747                         return nt_status;
1748                 }
1749
1750                 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1751                         add_incoming = true;
1752                 }
1753                 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
1754                         add_outgoing = true;
1755                 }
1756
1757                 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
1758                     !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
1759                         del_incoming = true;
1760                 }
1761                 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
1762                     !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
1763                         del_outgoing = true;
1764                 }
1765
1766                 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
1767                 if (origtype == -1 || origtype != info_ex->trust_type) {
1768                         DEBUG(1, ("Attempted to change trust type! "
1769                                   "Operation not handled\n"));
1770                         return NT_STATUS_INVALID_PARAMETER;
1771                 }
1772
1773                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1774                                                   dom_msg, msg,
1775                                                   "trustAttributes",
1776                                                   info_ex->trust_attributes,
1777                                                   &origattrs);
1778                 if (!NT_STATUS_IS_OK(nt_status)) {
1779                         return nt_status;
1780                 }
1781                 /* TODO: check forestFunctionality from ldb opaque */
1782                 /* TODO: check what is set makes sense */
1783                 /* for now refuse changes */
1784                 if (origattrs == -1 ||
1785                     origattrs != info_ex->trust_attributes) {
1786                         DEBUG(1, ("Attempted to change trust attributes! "
1787                                   "Operation not handled\n"));
1788                         return NT_STATUS_INVALID_PARAMETER;
1789                 }
1790         }
1791
1792         if (enc_types) {
1793                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1794                                                   dom_msg, msg,
1795                                                   "msDS-SupportedEncryptionTypes",
1796                                                   *enc_types, NULL);
1797                 if (!NT_STATUS_IS_OK(nt_status)) {
1798                         return nt_status;
1799                 }
1800         }
1801
1802         if (add_incoming && trustAuthIncoming.data) {
1803                 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1804                                         LDB_FLAG_MOD_REPLACE, NULL);
1805                 if (ret != LDB_SUCCESS) {
1806                         return NT_STATUS_NO_MEMORY;
1807                 }
1808                 ret = ldb_msg_add_value(msg, "trustAuthIncoming",
1809                                         &trustAuthIncoming, NULL);
1810                 if (ret != LDB_SUCCESS) {
1811                         return NT_STATUS_NO_MEMORY;
1812                 }
1813         }
1814         if (add_outgoing && trustAuthOutgoing.data) {
1815                 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
1816                                         LDB_FLAG_MOD_REPLACE, NULL);
1817                 if (ret != LDB_SUCCESS) {
1818                         return NT_STATUS_NO_MEMORY;
1819                 }
1820                 ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1821                                         &trustAuthOutgoing, NULL);
1822                 if (ret != LDB_SUCCESS) {
1823                         return NT_STATUS_NO_MEMORY;
1824                 }
1825         }
1826
1827         /* start transaction */
1828         ret = ldb_transaction_start(p_state->sam_ldb);
1829         if (ret != LDB_SUCCESS) {
1830                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1831         }
1832         in_transaction = true;
1833
1834         ret = ldb_modify(p_state->sam_ldb, msg);
1835         if (ret != LDB_SUCCESS) {
1836                 DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1837                          ldb_dn_get_linearized(msg->dn),
1838                          ldb_errstring(p_state->sam_ldb)));
1839                 if (ret == LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS) {
1840                         nt_status = NT_STATUS_ACCESS_DENIED;
1841                 } else {
1842                         nt_status = NT_STATUS_INTERNAL_DB_CORRUPTION;
1843                 }
1844                 goto done;
1845         }
1846
1847         if (add_incoming || del_incoming) {
1848                 const char *netbios_name;
1849
1850                 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
1851                                                            "flatname", NULL);
1852                 if (!netbios_name) {
1853                         nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
1854                         goto done;
1855                 }
1856
1857                 nt_status = update_trust_user(mem_ctx,
1858                                               p_state->sam_ldb,
1859                                               p_state->domain_dn,
1860                                               del_incoming,
1861                                               netbios_name,
1862                                               &auth_struct.incoming);
1863                 if (!NT_STATUS_IS_OK(nt_status)) {
1864                         goto done;
1865                 }
1866         }
1867
1868         /* ok, all fine, commit transaction and return */
1869         ret = ldb_transaction_commit(p_state->sam_ldb);
1870         if (ret != LDB_SUCCESS) {
1871                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1872         }
1873         in_transaction = false;
1874
1875         nt_status = NT_STATUS_OK;
1876
1877 done:
1878         if (in_transaction) {
1879                 ldb_transaction_cancel(p_state->sam_ldb);
1880         }
1881         return nt_status;
1882 }
1883
1884 /*
1885   lsa_SetInfomrationTrustedDomain
1886 */
1887 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
1888                                 struct dcesrv_call_state *dce_call,
1889                                 TALLOC_CTX *mem_ctx,
1890                                 struct lsa_SetInformationTrustedDomain *r)
1891 {
1892         struct dcesrv_handle *h;
1893         struct lsa_trusted_domain_state *td_state;
1894         struct ldb_message **msgs;
1895         NTSTATUS nt_status;
1896
1897         DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
1898                            LSA_HANDLE_TRUSTED_DOMAIN);
1899
1900         td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1901
1902         /* get the trusted domain object */
1903         nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
1904                             td_state->trusted_domain_dn,
1905                             NULL, NULL, NULL, &msgs);
1906         if (!NT_STATUS_IS_OK(nt_status)) {
1907                 if (NT_STATUS_EQUAL(nt_status,
1908                                     NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
1909                         return nt_status;
1910                 }
1911                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1912         }
1913
1914         return setInfoTrustedDomain_base(dce_call, h, mem_ctx,
1915                                          msgs[0], r->in.level, r->in.info);
1916 }
1917
1918
1919 /* 
1920   lsa_DeleteTrustedDomain
1921 */
1922 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1923                                       struct lsa_DeleteTrustedDomain *r)
1924 {
1925         NTSTATUS status;
1926         struct lsa_OpenTrustedDomain opn;
1927         struct lsa_DeleteObject del;
1928         struct dcesrv_handle *h;
1929
1930         opn.in.handle = r->in.handle;
1931         opn.in.sid = r->in.dom_sid;
1932         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
1933         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
1934         if (!opn.out.trustdom_handle) {
1935                 return NT_STATUS_NO_MEMORY;
1936         }
1937         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
1938         if (!NT_STATUS_IS_OK(status)) {
1939                 return status;
1940         }
1941
1942         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
1943         talloc_steal(mem_ctx, h);
1944
1945         del.in.handle = opn.out.trustdom_handle;
1946         del.out.handle = opn.out.trustdom_handle;
1947         status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
1948         if (!NT_STATUS_IS_OK(status)) {
1949                 return status;
1950         }
1951         return NT_STATUS_OK;
1952 }
1953
1954 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx, 
1955                                      struct ldb_message *msg, 
1956                                      struct lsa_TrustDomainInfoInfoEx *info_ex) 
1957 {
1958         info_ex->domain_name.string
1959                 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
1960         info_ex->netbios_name.string
1961                 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
1962         info_ex->sid 
1963                 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
1964         info_ex->trust_direction
1965                 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
1966         info_ex->trust_type
1967                 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
1968         info_ex->trust_attributes
1969                 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);  
1970         return NT_STATUS_OK;
1971 }
1972
1973 /* 
1974   lsa_QueryTrustedDomainInfo
1975 */
1976 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1977                                            struct lsa_QueryTrustedDomainInfo *r)
1978 {
1979         union lsa_TrustedDomainInfo *info = NULL;
1980         struct dcesrv_handle *h;
1981         struct lsa_trusted_domain_state *trusted_domain_state;
1982         struct ldb_message *msg;
1983         int ret;
1984         struct ldb_message **res;
1985         const char *attrs[] = {
1986                 "flatname", 
1987                 "trustPartner",
1988                 "securityIdentifier",
1989                 "trustDirection",
1990                 "trustType",
1991                 "trustAttributes", 
1992                 "msDs-supportedEncryptionTypes",
1993                 NULL
1994         };
1995
1996         DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
1997
1998         trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
1999
2000         /* pull all the user attributes */
2001         ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2002                               trusted_domain_state->trusted_domain_dn, &res, attrs);
2003         if (ret != 1) {
2004                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2005         }
2006         msg = res[0];
2007         
2008         info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2009         if (!info) {
2010                 return NT_STATUS_NO_MEMORY;
2011         }
2012         *r->out.info = info;
2013
2014         switch (r->in.level) {
2015         case LSA_TRUSTED_DOMAIN_INFO_NAME:
2016                 info->name.netbios_name.string
2017                         = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2018                 break;
2019         case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2020                 info->posix_offset.posix_offset
2021                         = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2022                 break;
2023 #if 0  /* Win2k3 doesn't implement this */
2024         case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2025                 r->out.info->info_basic.netbios_name.string 
2026                         = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2027                 r->out.info->info_basic.sid
2028                         = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2029                 break;
2030 #endif
2031         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2032                 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2033
2034         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2035                 ZERO_STRUCT(info->full_info);
2036                 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2037         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2038                 ZERO_STRUCT(info->full_info2_internal);
2039                 info->full_info2_internal.posix_offset.posix_offset
2040                         = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2041                 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2042                 
2043         case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2044                 info->enc_types.enc_types
2045                         = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2046                 break;
2047
2048         case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2049         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2050                 /* oops, we don't want to return the info after all */
2051                 talloc_free(info);
2052                 *r->out.info = NULL;
2053                 return NT_STATUS_INVALID_PARAMETER;
2054         default:
2055                 /* oops, we don't want to return the info after all */
2056                 talloc_free(info);
2057                 *r->out.info = NULL;
2058                 return NT_STATUS_INVALID_INFO_CLASS;
2059         }
2060
2061         return NT_STATUS_OK;
2062 }
2063
2064
2065 /* 
2066   lsa_QueryTrustedDomainInfoBySid
2067 */
2068 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2069                                                 struct lsa_QueryTrustedDomainInfoBySid *r)
2070 {
2071         NTSTATUS status;
2072         struct lsa_OpenTrustedDomain opn;
2073         struct lsa_QueryTrustedDomainInfo query;
2074         struct dcesrv_handle *h;
2075
2076         opn.in.handle = r->in.handle;
2077         opn.in.sid = r->in.dom_sid;
2078         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2079         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2080         if (!opn.out.trustdom_handle) {
2081                 return NT_STATUS_NO_MEMORY;
2082         }
2083         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2084         if (!NT_STATUS_IS_OK(status)) {
2085                 return status;
2086         }
2087
2088         /* Ensure this handle goes away at the end of this call */
2089         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2090         talloc_steal(mem_ctx, h);
2091
2092         query.in.trustdom_handle = opn.out.trustdom_handle;
2093         query.in.level = r->in.level;
2094         query.out.info = r->out.info;
2095         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2096         if (!NT_STATUS_IS_OK(status)) {
2097                 return status;
2098         }
2099
2100         return NT_STATUS_OK;
2101 }
2102
2103 /*
2104   lsa_SetTrustedDomainInfoByName
2105 */
2106 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2107                                                TALLOC_CTX *mem_ctx,
2108                                                struct lsa_SetTrustedDomainInfoByName *r)
2109 {
2110         struct dcesrv_handle *policy_handle;
2111         struct lsa_policy_state *policy_state;
2112         struct ldb_message **msgs;
2113         NTSTATUS nt_status;
2114
2115         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2116         policy_state = policy_handle->data;
2117
2118         /* get the trusted domain object */
2119         nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2120                             policy_state->domain_dn,
2121                             r->in.trusted_domain->string,
2122                             r->in.trusted_domain->string,
2123                             NULL, &msgs);
2124         if (!NT_STATUS_IS_OK(nt_status)) {
2125                 if (NT_STATUS_EQUAL(nt_status,
2126                                     NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2127                         return nt_status;
2128                 }
2129                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2130         }
2131
2132         return setInfoTrustedDomain_base(dce_call, policy_handle, mem_ctx,
2133                                          msgs[0], r->in.level, r->in.info);
2134 }
2135
2136 /* 
2137    lsa_QueryTrustedDomainInfoByName
2138 */
2139 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2140                                                  TALLOC_CTX *mem_ctx,
2141                                                  struct lsa_QueryTrustedDomainInfoByName *r)
2142 {
2143         NTSTATUS status;
2144         struct lsa_OpenTrustedDomainByName opn;
2145         struct lsa_QueryTrustedDomainInfo query;
2146         struct dcesrv_handle *h;
2147
2148         opn.in.handle = r->in.handle;
2149         opn.in.name = *r->in.trusted_domain;
2150         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2151         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2152         if (!opn.out.trustdom_handle) {
2153                 return NT_STATUS_NO_MEMORY;
2154         }
2155         status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2156         if (!NT_STATUS_IS_OK(status)) {
2157                 return status;
2158         }
2159         
2160         /* Ensure this handle goes away at the end of this call */
2161         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2162         talloc_steal(mem_ctx, h);
2163
2164         query.in.trustdom_handle = opn.out.trustdom_handle;
2165         query.in.level = r->in.level;
2166         query.out.info = r->out.info;
2167         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2168         if (!NT_STATUS_IS_OK(status)) {
2169                 return status;
2170         }
2171         
2172         return NT_STATUS_OK;
2173 }
2174
2175 /*
2176   lsa_CloseTrustedDomainEx 
2177 */
2178 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2179                                          TALLOC_CTX *mem_ctx,
2180                                          struct lsa_CloseTrustedDomainEx *r)
2181 {
2182         /* The result of a bad hair day from an IDL programmer?  Not
2183          * implmented in Win2k3.  You should always just lsa_Close
2184          * anyway. */
2185         return NT_STATUS_NOT_IMPLEMENTED;
2186 }
2187
2188
2189 /*
2190   comparison function for sorting lsa_DomainInformation array
2191 */
2192 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2193 {
2194         return strcasecmp_m(e1->name.string, e2->name.string);
2195 }
2196
2197 /* 
2198   lsa_EnumTrustDom 
2199 */
2200 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2201                                  struct lsa_EnumTrustDom *r)
2202 {
2203         struct dcesrv_handle *policy_handle;
2204         struct lsa_DomainInfo *entries;
2205         struct lsa_policy_state *policy_state;
2206         struct ldb_message **domains;
2207         const char *attrs[] = {
2208                 "flatname", 
2209                 "securityIdentifier",
2210                 NULL
2211         };
2212
2213
2214         int count, i;
2215
2216         *r->out.resume_handle = 0;
2217
2218         r->out.domains->domains = NULL;
2219         r->out.domains->count = 0;
2220
2221         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2222
2223         policy_state = policy_handle->data;
2224
2225         /* search for all users in this domain. This could possibly be cached and 
2226            resumed based on resume_key */
2227         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs, 
2228                              "objectclass=trustedDomain");
2229         if (count < 0) {
2230                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2231         }
2232
2233         /* convert to lsa_TrustInformation format */
2234         entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2235         if (!entries) {
2236                 return NT_STATUS_NO_MEMORY;
2237         }
2238         for (i=0;i<count;i++) {
2239                 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2240                 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2241         }
2242
2243         /* sort the results by name */
2244         TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2245
2246         if (*r->in.resume_handle >= count) {
2247                 *r->out.resume_handle = -1;
2248
2249                 return NT_STATUS_NO_MORE_ENTRIES;
2250         }
2251
2252         /* return the rest, limit by max_size. Note that we 
2253            use the w2k3 element size value of 60 */
2254         r->out.domains->count = count - *r->in.resume_handle;
2255         r->out.domains->count = MIN(r->out.domains->count, 
2256                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2257
2258         r->out.domains->domains = entries + *r->in.resume_handle;
2259         r->out.domains->count = r->out.domains->count;
2260
2261         if (r->out.domains->count < count - *r->in.resume_handle) {
2262                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2263                 return STATUS_MORE_ENTRIES;
2264         }
2265
2266         /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2267          * always be larger than the previous input resume handle, in
2268          * particular when hitting the last query it is vital to set the
2269          * resume handle correctly to avoid infinite client loops, as
2270          * seen e.g. with Windows XP SP3 when resume handle is 0 and
2271          * status is NT_STATUS_OK - gd */
2272
2273         *r->out.resume_handle = (uint32_t)-1;
2274
2275         return NT_STATUS_OK;
2276 }
2277
2278 /*
2279   comparison function for sorting lsa_DomainInformation array
2280 */
2281 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2282 {
2283         return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2284 }
2285
2286 /* 
2287   lsa_EnumTrustedDomainsEx 
2288 */
2289 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2290                                         struct lsa_EnumTrustedDomainsEx *r)
2291 {
2292         struct dcesrv_handle *policy_handle;
2293         struct lsa_TrustDomainInfoInfoEx *entries;
2294         struct lsa_policy_state *policy_state;
2295         struct ldb_message **domains;
2296         const char *attrs[] = {
2297                 "flatname", 
2298                 "trustPartner",
2299                 "securityIdentifier",
2300                 "trustDirection",
2301                 "trustType",
2302                 "trustAttributes", 
2303                 NULL
2304         };
2305         NTSTATUS nt_status;
2306
2307         int count, i;
2308
2309         *r->out.resume_handle = 0;
2310
2311         r->out.domains->domains = NULL;
2312         r->out.domains->count = 0;
2313
2314         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2315
2316         policy_state = policy_handle->data;
2317
2318         /* search for all users in this domain. This could possibly be cached and 
2319            resumed based on resume_key */
2320         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs, 
2321                              "objectclass=trustedDomain");
2322         if (count < 0) {
2323                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2324         }
2325
2326         /* convert to lsa_DomainInformation format */
2327         entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2328         if (!entries) {
2329                 return NT_STATUS_NO_MEMORY;
2330         }
2331         for (i=0;i<count;i++) {
2332                 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2333                 if (!NT_STATUS_IS_OK(nt_status)) {
2334                         return nt_status;
2335                 }
2336         }
2337
2338         /* sort the results by name */
2339         TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2340
2341         if (*r->in.resume_handle >= count) {
2342                 *r->out.resume_handle = -1;
2343
2344                 return NT_STATUS_NO_MORE_ENTRIES;
2345         }
2346
2347         /* return the rest, limit by max_size. Note that we 
2348            use the w2k3 element size value of 60 */
2349         r->out.domains->count = count - *r->in.resume_handle;
2350         r->out.domains->count = MIN(r->out.domains->count, 
2351                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2352
2353         r->out.domains->domains = entries + *r->in.resume_handle;
2354         r->out.domains->count = r->out.domains->count;
2355
2356         if (r->out.domains->count < count - *r->in.resume_handle) {
2357                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2358                 return STATUS_MORE_ENTRIES;
2359         }
2360
2361         return NT_STATUS_OK;
2362 }
2363
2364
2365 /* 
2366   lsa_OpenAccount 
2367 */
2368 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2369                                 struct lsa_OpenAccount *r)
2370 {
2371         struct dcesrv_handle *h, *ah;
2372         struct lsa_policy_state *state;
2373         struct lsa_account_state *astate;
2374
2375         ZERO_STRUCTP(r->out.acct_handle);
2376
2377         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2378
2379         state = h->data;
2380
2381         astate = talloc(dce_call->conn, struct lsa_account_state);
2382         if (astate == NULL) {
2383                 return NT_STATUS_NO_MEMORY;
2384         }
2385
2386         astate->account_sid = dom_sid_dup(astate, r->in.sid);
2387         if (astate->account_sid == NULL) {
2388                 talloc_free(astate);
2389                 return NT_STATUS_NO_MEMORY;
2390         }
2391         
2392         astate->policy = talloc_reference(astate, state);
2393         astate->access_mask = r->in.access_mask;
2394
2395         ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2396         if (!ah) {
2397                 talloc_free(astate);
2398                 return NT_STATUS_NO_MEMORY;
2399         }
2400
2401         ah->data = talloc_steal(ah, astate);
2402
2403         *r->out.acct_handle = ah->wire_handle;
2404
2405         return NT_STATUS_OK;
2406 }
2407
2408
2409 /* 
2410   lsa_EnumPrivsAccount 
2411 */
2412 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call, 
2413                                      TALLOC_CTX *mem_ctx,
2414                                      struct lsa_EnumPrivsAccount *r)
2415 {
2416         struct dcesrv_handle *h;
2417         struct lsa_account_state *astate;
2418         int ret;
2419         unsigned int i, j;
2420         struct ldb_message **res;
2421         const char * const attrs[] = { "privilege", NULL};
2422         struct ldb_message_element *el;
2423         const char *sidstr;
2424         struct lsa_PrivilegeSet *privs;
2425
2426         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2427
2428         astate = h->data;
2429
2430         privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2431         if (privs == NULL) {
2432                 return NT_STATUS_NO_MEMORY;
2433         }
2434         privs->count = 0;
2435         privs->unknown = 0;
2436         privs->set = NULL;
2437
2438         *r->out.privs = privs;
2439
2440         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2441         if (sidstr == NULL) {
2442                 return NT_STATUS_NO_MEMORY;
2443         }
2444
2445         ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs, 
2446                            "objectSid=%s", sidstr);
2447         if (ret < 0) {
2448                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2449         }
2450         if (ret != 1) {
2451                 return NT_STATUS_OK;
2452         }
2453
2454         el = ldb_msg_find_element(res[0], "privilege");
2455         if (el == NULL || el->num_values == 0) {
2456                 return NT_STATUS_OK;
2457         }
2458
2459         privs->set = talloc_array(privs,
2460                                   struct lsa_LUIDAttribute, el->num_values);
2461         if (privs->set == NULL) {
2462                 return NT_STATUS_NO_MEMORY;
2463         }
2464
2465         j = 0;
2466         for (i=0;i<el->num_values;i++) {
2467                 int id = sec_privilege_id((const char *)el->values[i].data);
2468                 if (id == SEC_PRIV_INVALID) {
2469                         /* Perhaps an account right, not a privilege */
2470                         continue;
2471                 }
2472                 privs->set[j].attribute = 0;
2473                 privs->set[j].luid.low = id;
2474                 privs->set[j].luid.high = 0;
2475                 j++;
2476         }
2477
2478         privs->count = j;
2479
2480         return NT_STATUS_OK;
2481 }
2482
2483 /* 
2484   lsa_EnumAccountRights 
2485 */
2486 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call, 
2487                                       TALLOC_CTX *mem_ctx,
2488                                       struct lsa_EnumAccountRights *r)
2489 {
2490         struct dcesrv_handle *h;
2491         struct lsa_policy_state *state;
2492         int ret;
2493         unsigned int i;
2494         struct ldb_message **res;
2495         const char * const attrs[] = { "privilege", NULL};
2496         const char *sidstr;
2497         struct ldb_message_element *el;
2498
2499         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2500
2501         state = h->data;
2502
2503         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2504         if (sidstr == NULL) {
2505                 return NT_STATUS_NO_MEMORY;
2506         }
2507
2508         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs, 
2509                            "(&(objectSid=%s)(privilege=*))", sidstr);
2510         if (ret == 0) {
2511                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2512         }
2513         if (ret != 1) {
2514                 DEBUG(3, ("searching for account rights for SID: %s failed: %s", 
2515                           dom_sid_string(mem_ctx, r->in.sid),
2516                           ldb_errstring(state->pdb)));
2517                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2518         }
2519
2520         el = ldb_msg_find_element(res[0], "privilege");
2521         if (el == NULL || el->num_values == 0) {
2522                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2523         }
2524
2525         r->out.rights->count = el->num_values;
2526         r->out.rights->names = talloc_array(r->out.rights, 
2527                                             struct lsa_StringLarge, r->out.rights->count);
2528         if (r->out.rights->names == NULL) {
2529                 return NT_STATUS_NO_MEMORY;
2530         }
2531
2532         for (i=0;i<el->num_values;i++) {
2533                 r->out.rights->names[i].string = (const char *)el->values[i].data;
2534         }
2535
2536         return NT_STATUS_OK;
2537 }
2538
2539
2540
2541 /* 
2542   helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2543 */
2544 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call, 
2545                                            TALLOC_CTX *mem_ctx,
2546                                            struct lsa_policy_state *state,
2547                                            int ldb_flag,
2548                                            struct dom_sid *sid,
2549                                            const struct lsa_RightSet *rights)
2550 {
2551         const char *sidstr, *sidndrstr;
2552         struct ldb_message *msg;
2553         struct ldb_message_element *el;
2554         int ret;
2555         uint32_t i;
2556         struct lsa_EnumAccountRights r2;
2557         char *dnstr;
2558
2559         if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2560             SECURITY_ADMINISTRATOR) {
2561                 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2562                 return NT_STATUS_ACCESS_DENIED;
2563         }
2564
2565         msg = ldb_msg_new(mem_ctx);
2566         if (msg == NULL) {
2567                 return NT_STATUS_NO_MEMORY;
2568         }
2569
2570         sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2571         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidndrstr, msg);
2572
2573         sidstr = dom_sid_string(msg, sid);
2574         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(sidstr, msg);
2575
2576         dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2577         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(dnstr, msg);
2578
2579         msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2580         NT_STATUS_HAVE_NO_MEMORY_AND_FREE(msg->dn, msg);
2581
2582         if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2583                 NTSTATUS status;
2584
2585                 r2.in.handle = &state->handle->wire_handle;
2586                 r2.in.sid = sid;
2587                 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2588
2589                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2590                 if (!NT_STATUS_IS_OK(status)) {
2591                         ZERO_STRUCTP(r2.out.rights);
2592                 }
2593         }
2594
2595         for (i=0;i<rights->count;i++) {
2596                 if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
2597                         if (sec_right_bit(rights->names[i].string) == 0) {
2598                                 talloc_free(msg);
2599                                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2600                         }
2601
2602                         talloc_free(msg);
2603                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2604                 }
2605
2606                 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2607                         uint32_t j;
2608                         for (j=0;j<r2.out.rights->count;j++) {
2609                                 if (strcasecmp_m(r2.out.rights->names[j].string, 
2610                                                rights->names[i].string) == 0) {
2611                                         break;
2612                                 }
2613                         }
2614                         if (j != r2.out.rights->count) continue;
2615                 }
2616
2617                 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2618                 if (ret != LDB_SUCCESS) {
2619                         talloc_free(msg);
2620                         return NT_STATUS_NO_MEMORY;
2621                 }
2622         }
2623
2624         el = ldb_msg_find_element(msg, "privilege");
2625         if (!el) {
2626                 talloc_free(msg);
2627                 return NT_STATUS_OK;
2628         }
2629
2630         el->flags = ldb_flag;
2631
2632         ret = ldb_modify(state->pdb, msg);
2633         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2634                 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2635                         talloc_free(msg);
2636                         return NT_STATUS_NO_MEMORY;
2637                 }
2638                 ldb_msg_add_string(msg, "comment", "added via LSA");
2639                 ret = ldb_add(state->pdb, msg);         
2640         }
2641         if (ret != LDB_SUCCESS) {
2642                 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2643                         talloc_free(msg);
2644                         return NT_STATUS_OK;
2645                 }
2646                 DEBUG(3, ("Could not %s attributes from %s: %s", 
2647                           LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2648                           ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2649                 talloc_free(msg);
2650                 return NT_STATUS_UNEXPECTED_IO_ERROR;
2651         }
2652
2653         talloc_free(msg);
2654         return NT_STATUS_OK;
2655 }
2656
2657 /* 
2658   lsa_AddPrivilegesToAccount
2659 */
2660 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2661                                            struct lsa_AddPrivilegesToAccount *r)
2662 {
2663         struct lsa_RightSet rights;
2664         struct dcesrv_handle *h;
2665         struct lsa_account_state *astate;
2666         uint32_t i;
2667
2668         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2669
2670         astate = h->data;
2671
2672         rights.count = r->in.privs->count;
2673         rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2674         if (rights.names == NULL) {
2675                 return NT_STATUS_NO_MEMORY;
2676         }
2677         for (i=0;i<rights.count;i++) {
2678                 int id = r->in.privs->set[i].luid.low;
2679                 if (r->in.privs->set[i].luid.high) {
2680                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2681                 }
2682                 rights.names[i].string = sec_privilege_name(id);
2683                 if (rights.names[i].string == NULL) {
2684                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2685                 }
2686         }
2687
2688         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
2689                                           LDB_FLAG_MOD_ADD, astate->account_sid,
2690                                           &rights);
2691 }
2692
2693
2694 /* 
2695   lsa_RemovePrivilegesFromAccount
2696 */
2697 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2698                                                 struct lsa_RemovePrivilegesFromAccount *r)
2699 {
2700         struct lsa_RightSet *rights;
2701         struct dcesrv_handle *h;
2702         struct lsa_account_state *astate;
2703         uint32_t i;
2704
2705         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2706
2707         astate = h->data;
2708
2709         rights = talloc(mem_ctx, struct lsa_RightSet);
2710
2711         if (r->in.remove_all == 1 && 
2712             r->in.privs == NULL) {
2713                 struct lsa_EnumAccountRights r2;
2714                 NTSTATUS status;
2715
2716                 r2.in.handle = &astate->policy->handle->wire_handle;
2717                 r2.in.sid = astate->account_sid;
2718                 r2.out.rights = rights;
2719
2720                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2721                 if (!NT_STATUS_IS_OK(status)) {
2722                         return status;
2723                 }
2724
2725                 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
2726                                                   LDB_FLAG_MOD_DELETE, astate->account_sid,
2727                                                   r2.out.rights);
2728         }
2729
2730         if (r->in.remove_all != 0) {
2731                 return NT_STATUS_INVALID_PARAMETER;
2732         }
2733
2734         rights->count = r->in.privs->count;
2735         rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2736         if (rights->names == NULL) {
2737                 return NT_STATUS_NO_MEMORY;
2738         }
2739         for (i=0;i<rights->count;i++) {
2740                 int id = r->in.privs->set[i].luid.low;
2741                 if (r->in.privs->set[i].luid.high) {
2742                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2743                 }
2744                 rights->names[i].string = sec_privilege_name(id);
2745                 if (rights->names[i].string == NULL) {
2746                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2747                 }
2748         }
2749
2750         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy, 
2751                                           LDB_FLAG_MOD_DELETE, astate->account_sid,
2752                                           rights);
2753 }
2754
2755
2756 /* 
2757   lsa_GetQuotasForAccount
2758 */
2759 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2760                        struct lsa_GetQuotasForAccount *r)
2761 {
2762         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2763 }
2764
2765
2766 /* 
2767   lsa_SetQuotasForAccount
2768 */
2769 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2770                        struct lsa_SetQuotasForAccount *r)
2771 {
2772         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2773 }
2774
2775
2776 /* 
2777   lsa_GetSystemAccessAccount
2778 */
2779 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2780                        struct lsa_GetSystemAccessAccount *r)
2781 {
2782         struct dcesrv_handle *h;
2783         struct lsa_account_state *astate;
2784         int ret;
2785         unsigned int i;
2786         struct ldb_message **res;
2787         const char * const attrs[] = { "privilege", NULL};
2788         struct ldb_message_element *el;
2789         const char *sidstr;
2790
2791         *(r->out.access_mask) = 0x00000000;
2792
2793         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2794
2795         astate = h->data;
2796
2797         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2798         if (sidstr == NULL) {
2799                 return NT_STATUS_NO_MEMORY;
2800         }
2801
2802         ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs, 
2803                            "objectSid=%s", sidstr);
2804         if (ret < 0) {
2805                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2806         }
2807         if (ret != 1) {
2808                 return NT_STATUS_OK;
2809         }
2810
2811         el = ldb_msg_find_element(res[0], "privilege");
2812         if (el == NULL || el->num_values == 0) {
2813                 return NT_STATUS_OK;
2814         }
2815
2816         for (i=0;i<el->num_values;i++) {
2817                 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
2818                 if (right_bit == 0) {
2819                         /* Perhaps an privilege, not a right */
2820                         continue;
2821                 }
2822                 *(r->out.access_mask) |= right_bit;
2823         }
2824
2825         return NT_STATUS_OK;
2826 }
2827
2828
2829 /* 
2830   lsa_SetSystemAccessAccount
2831 */
2832 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2833                        struct lsa_SetSystemAccessAccount *r)
2834 {
2835         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2836 }
2837
2838
2839 /* 
2840   lsa_CreateSecret 
2841 */
2842 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2843                                  struct lsa_CreateSecret *r)
2844 {
2845         struct dcesrv_handle *policy_handle;
2846         struct lsa_policy_state *policy_state;
2847         struct lsa_secret_state *secret_state;
2848         struct dcesrv_handle *handle;
2849         struct ldb_message **msgs, *msg;
2850         const char *attrs[] = {
2851                 NULL
2852         };
2853
2854         const char *name;
2855
2856         int ret;
2857
2858         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2859         ZERO_STRUCTP(r->out.sec_handle);
2860         
2861         switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
2862         {
2863         case SECURITY_SYSTEM:
2864         case SECURITY_ADMINISTRATOR:
2865                 break;
2866         default:
2867                 /* Users and annonymous are not allowed create secrets */
2868                 return NT_STATUS_ACCESS_DENIED;
2869         }
2870
2871         policy_state = policy_handle->data;
2872
2873         if (!r->in.name.string) {
2874                 return NT_STATUS_INVALID_PARAMETER;
2875         }
2876         
2877         secret_state = talloc(mem_ctx, struct lsa_secret_state);
2878         NT_STATUS_HAVE_NO_MEMORY(secret_state);
2879         secret_state->policy = policy_state;
2880
2881         msg = ldb_msg_new(mem_ctx);
2882         if (msg == NULL) {
2883                 return NT_STATUS_NO_MEMORY;
2884         }
2885
2886         if (strncmp("G$", r->in.name.string, 2) == 0) {
2887                 const char *name2;
2888
2889                 secret_state->global = true;
2890
2891                 name = &r->in.name.string[2];
2892                 if (strlen(name) == 0) {
2893                         return NT_STATUS_INVALID_PARAMETER;
2894                 }
2895
2896                 name2 = talloc_asprintf(mem_ctx, "%s Secret",
2897                                         ldb_binary_encode_string(mem_ctx, name));
2898                 NT_STATUS_HAVE_NO_MEMORY(name2);
2899
2900                 /* We need to connect to the database as system, as this is one
2901                  * of the rare RPC calls that must read the secrets (and this
2902                  * is denied otherwise) */
2903                 secret_state->sam_ldb = talloc_reference(secret_state,
2904                                                          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));
2905                 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2906
2907                 /* search for the secret record */
2908                 ret = gendb_search(secret_state->sam_ldb,
2909                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
2910                                    "(&(cn=%s)(objectclass=secret))", 
2911                                    name2);
2912                 if (ret > 0) {
2913                         return NT_STATUS_OBJECT_NAME_COLLISION;
2914                 }
2915                 
2916                 if (ret < 0) {
2917                         DEBUG(0,("Failure searching for CN=%s: %s\n", 
2918                                  name2, ldb_errstring(secret_state->sam_ldb)));
2919                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2920                 }
2921
2922                 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
2923                 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2924                 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
2925                         return NT_STATUS_NO_MEMORY;
2926                 }
2927
2928                 ret = ldb_msg_add_string(msg, "cn", name2);
2929                 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2930         } else {
2931                 secret_state->global = false;
2932
2933                 name = r->in.name.string;
2934                 if (strlen(name) == 0) {
2935                         return NT_STATUS_INVALID_PARAMETER;
2936                 }
2937
2938                 secret_state->sam_ldb = talloc_reference(secret_state, 
2939                                                          secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
2940                 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
2941
2942                 /* search for the secret record */
2943                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
2944                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
2945                                    &msgs, attrs,
2946                                    "(&(cn=%s)(objectclass=secret))", 
2947                                    ldb_binary_encode_string(mem_ctx, name));
2948                 if (ret > 0) {
2949                         return NT_STATUS_OBJECT_NAME_COLLISION;
2950                 }
2951                 
2952                 if (ret < 0) {
2953                         DEBUG(0,("Failure searching for CN=%s: %s\n", 
2954                                  name, ldb_errstring(secret_state->sam_ldb)));
2955                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
2956                 }
2957
2958                 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
2959                                          "cn=%s,cn=LSA Secrets", name);
2960                 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
2961                 ret = ldb_msg_add_string(msg, "cn", name);
2962                 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2963         } 
2964
2965         ret = ldb_msg_add_string(msg, "objectClass", "secret");
2966         if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
2967         
2968         secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
2969         NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
2970
2971         /* create the secret */
2972         ret = ldb_add(secret_state->sam_ldb, msg);
2973         if (ret != LDB_SUCCESS) {
2974                 DEBUG(0,("Failed to create secret record %s: %s\n",
2975                          ldb_dn_get_linearized(msg->dn), 
2976                          ldb_errstring(secret_state->sam_ldb)));
2977                 return NT_STATUS_ACCESS_DENIED;
2978         }
2979
2980         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
2981         NT_STATUS_HAVE_NO_MEMORY(handle);
2982
2983         handle->data = talloc_steal(handle, secret_state);
2984         
2985         secret_state->access_mask = r->in.access_mask;
2986         secret_state->policy = talloc_reference(secret_state, policy_state);
2987         NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
2988         
2989         *r->out.sec_handle = handle->wire_handle;
2990         
2991         return NT_STATUS_OK;
2992 }
2993
2994
2995 /* 
2996   lsa_OpenSecret 
2997 */
2998 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2999                                struct lsa_OpenSecret *r)
3000 {
3001         struct dcesrv_handle *policy_handle;
3002         
3003         struct lsa_policy_state *policy_state;
3004         struct lsa_secret_state *secret_state;
3005         struct dcesrv_handle *handle;
3006         struct ldb_message **msgs;
3007         const char *attrs[] = {
3008                 NULL
3009         };
3010
3011         const char *name;
3012
3013         int ret;
3014
3015         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3016         ZERO_STRUCTP(r->out.sec_handle);
3017         policy_state = policy_handle->data;
3018
3019         if (!r->in.name.string) {
3020                 return NT_STATUS_INVALID_PARAMETER;
3021         }
3022         
3023         switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3024         {
3025         case SECURITY_SYSTEM:
3026         case SECURITY_ADMINISTRATOR:
3027                 break;
3028         default:
3029                 /* Users and annonymous are not allowed to access secrets */
3030                 return NT_STATUS_ACCESS_DENIED;
3031         }
3032
3033         secret_state = talloc(mem_ctx, struct lsa_secret_state);
3034         if (!secret_state) {
3035                 return NT_STATUS_NO_MEMORY;
3036         }
3037         secret_state->policy = policy_state;
3038
3039         if (strncmp("G$", r->in.name.string, 2) == 0) {
3040                 name = &r->in.name.string[2];
3041                 /* 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) */
3042                 secret_state->sam_ldb = talloc_reference(secret_state, 
3043                                                          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));
3044                 secret_state->global = true;
3045
3046                 if (strlen(name) < 1) {
3047                         return NT_STATUS_INVALID_PARAMETER;
3048                 }
3049
3050                 /* search for the secret record */
3051                 ret = gendb_search(secret_state->sam_ldb,
3052                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
3053                                    "(&(cn=%s Secret)(objectclass=secret))", 
3054                                    ldb_binary_encode_string(mem_ctx, name));
3055                 if (ret == 0) {
3056                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3057                 }
3058                 
3059                 if (ret != 1) {
3060                         DEBUG(0,("Found %d records matching DN %s\n", ret,
3061                                  ldb_dn_get_linearized(policy_state->system_dn)));
3062                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3063                 }
3064         
3065         } else {
3066                 secret_state->global = false;
3067                 secret_state->sam_ldb = talloc_reference(secret_state, 
3068                                                          secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3069
3070                 name = r->in.name.string;
3071                 if (strlen(name) < 1) {
3072                         return NT_STATUS_INVALID_PARAMETER;
3073                 }
3074
3075                 /* search for the secret record */
3076                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3077                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3078                                    &msgs, attrs,
3079                                    "(&(cn=%s)(objectclass=secret))", 
3080                                    ldb_binary_encode_string(mem_ctx, name));
3081                 if (ret == 0) {
3082                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3083                 }
3084                 
3085                 if (ret != 1) {
3086                         DEBUG(0,("Found %d records matching CN=%s\n", 
3087                                  ret, ldb_binary_encode_string(mem_ctx, name)));
3088                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3089                 }
3090         } 
3091
3092         secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3093         
3094         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3095         if (!handle) {
3096                 return NT_STATUS_NO_MEMORY;
3097         }
3098         
3099         handle->data = talloc_steal(handle, secret_state);
3100         
3101         secret_state->access_mask = r->in.access_mask;
3102         secret_state->policy = talloc_reference(secret_state, policy_state);
3103         
3104         *r->out.sec_handle = handle->wire_handle;
3105         
3106         return NT_STATUS_OK;
3107 }
3108
3109
3110 /* 
3111   lsa_SetSecret 
3112 */
3113 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3114                               struct lsa_SetSecret *r)
3115 {
3116
3117         struct dcesrv_handle *h;
3118         struct lsa_secret_state *secret_state;
3119         struct ldb_message *msg;
3120         DATA_BLOB session_key;
3121         DATA_BLOB crypt_secret, secret;
3122         struct ldb_val val;
3123         int ret;
3124         NTSTATUS status = NT_STATUS_OK;
3125
3126         struct timeval now = timeval_current();
3127         NTTIME nt_now = timeval_to_nttime(&now);
3128
3129         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3130
3131         secret_state = h->data;
3132
3133         msg = ldb_msg_new(mem_ctx);
3134         if (msg == NULL) {
3135                 return NT_STATUS_NO_MEMORY;
3136         }
3137
3138         msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3139         if (!msg->dn) {
3140                 return NT_STATUS_NO_MEMORY;
3141         }
3142         status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3143         if (!NT_STATUS_IS_OK(status)) {
3144                 return status;
3145         }
3146
3147         if (r->in.old_val) {
3148                 /* Decrypt */
3149                 crypt_secret.data = r->in.old_val->data;
3150                 crypt_secret.length = r->in.old_val->size;
3151                 
3152                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3153                 if (!NT_STATUS_IS_OK(status)) {
3154                         return status;
3155                 }
3156                 
3157                 val.data = secret.data;
3158                 val.length = secret.length;
3159                 
3160                 /* set value */
3161                 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3162                         return NT_STATUS_NO_MEMORY; 
3163                 }
3164                 
3165                 /* set old value mtime */
3166                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
3167                                          mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3168                         return NT_STATUS_NO_MEMORY; 
3169                 }
3170
3171         } else {
3172                 /* If the old value is not set, then migrate the
3173                  * current value to the old value */
3174                 const struct ldb_val *old_val;
3175                 NTTIME last_set_time;
3176                 struct ldb_message **res;
3177                 const char *attrs[] = {
3178                         "currentValue",
3179                         "lastSetTime",
3180                         NULL
3181                 };
3182                 
3183                 /* search for the secret record */
3184                 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3185                                       secret_state->secret_dn, &res, attrs);
3186                 if (ret == 0) {
3187                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3188                 }
3189                 
3190                 if (ret != 1) {
3191                         DEBUG(0,("Found %d records matching dn=%s\n", ret,
3192                                  ldb_dn_get_linearized(secret_state->secret_dn)));
3193                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3194                 }
3195                 
3196                 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3197                 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3198                 
3199                 if (old_val) {
3200                         /* set old value */
3201                         if (ldb_msg_add_value(msg, "priorValue",
3202                                               old_val, NULL) != LDB_SUCCESS) {
3203                                 return NT_STATUS_NO_MEMORY; 
3204                         }
3205                 } else {
3206                         if (samdb_msg_add_delete(secret_state->sam_ldb, 
3207                                                  mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3208                                 return NT_STATUS_NO_MEMORY;
3209                         }
3210                         
3211                 }
3212                 
3213                 /* set old value mtime */
3214                 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3215                         if (samdb_msg_add_uint64(secret_state->sam_ldb, 
3216                                                  mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3217                                 return NT_STATUS_NO_MEMORY; 
3218                         }
3219                 } else {
3220                         if (samdb_msg_add_uint64(secret_state->sam_ldb, 
3221                                                  mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3222                                 return NT_STATUS_NO_MEMORY; 
3223                         }
3224                 }
3225         }
3226
3227         if (r->in.new_val) {
3228                 /* Decrypt */
3229                 crypt_secret.data = r->in.new_val->data;
3230                 crypt_secret.length = r->in.new_val->size;
3231                 
3232                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3233                 if (!NT_STATUS_IS_OK(status)) {
3234                         return status;
3235                 }
3236                 
3237                 val.data = secret.data;
3238                 val.length = secret.length;
3239                 
3240                 /* set value */
3241                 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3242                         return NT_STATUS_NO_MEMORY; 
3243                 }
3244                 
3245                 /* set new value mtime */
3246                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
3247                                          mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3248                         return NT_STATUS_NO_MEMORY; 
3249                 }
3250                 
3251         } else {
3252                 /* NULL out the NEW value */
3253                 if (samdb_msg_add_uint64(secret_state->sam_ldb, 
3254                                          mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3255                         return NT_STATUS_NO_MEMORY; 
3256                 }
3257                 if (samdb_msg_add_delete(secret_state->sam_ldb, 
3258                                          mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3259                         return NT_STATUS_NO_MEMORY;
3260                 }
3261         }
3262
3263         /* modify the samdb record */
3264         ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3265         if (ret != LDB_SUCCESS) {
3266                 return dsdb_ldb_err_to_ntstatus(ret);
3267         }
3268
3269         return NT_STATUS_OK;
3270 }
3271
3272
3273 /* 
3274   lsa_QuerySecret 
3275 */
3276 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3277                                 struct lsa_QuerySecret *r)
3278 {
3279         struct dcesrv_handle *h;
3280         struct lsa_secret_state *secret_state;
3281         struct ldb_message *msg;
3282         DATA_BLOB session_key;
3283         DATA_BLOB crypt_secret, secret;
3284         int ret;
3285         struct ldb_message **res;
3286         const char *attrs[] = {
3287                 "currentValue",
3288                 "priorValue",
3289                 "lastSetTime",
3290                 "priorSetTime", 
3291                 NULL
3292         };
3293
3294         NTSTATUS nt_status;
3295
3296         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3297
3298         /* Ensure user is permitted to read this... */
3299         switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3300         {
3301         case SECURITY_SYSTEM:
3302         case SECURITY_ADMINISTRATOR:
3303                 break;
3304         default:
3305                 /* Users and annonymous are not allowed to read secrets */
3306                 return NT_STATUS_ACCESS_DENIED;
3307         }
3308
3309         secret_state = h->data;
3310
3311         /* pull all the user attributes */
3312         ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3313                               secret_state->secret_dn, &res, attrs);
3314         if (ret != 1) {
3315                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3316         }
3317         msg = res[0];
3318         
3319         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3320         if (!NT_STATUS_IS_OK(nt_status)) {
3321                 return nt_status;
3322         }
3323         
3324         if (r->in.old_val) {
3325                 const struct ldb_val *prior_val;
3326                 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3327                 if (!r->out.old_val) {
3328                         return NT_STATUS_NO_MEMORY;
3329                 }
3330                 prior_val = ldb_msg_find_ldb_val(res[0], "priorValue");
3331                 
3332                 if (prior_val && prior_val->length) {
3333                         secret.data = prior_val->data;
3334                         secret.length = prior_val->length;
3335                 
3336                         /* Encrypt */
3337                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3338                         if (!crypt_secret.length) {
3339                                 return NT_STATUS_NO_MEMORY;
3340                         }
3341                         r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3342                         if (!r->out.old_val->buf) {
3343                                 return NT_STATUS_NO_MEMORY;
3344                         }
3345                         r->out.old_val->buf->size = crypt_secret.length;
3346                         r->out.old_val->buf->length = crypt_secret.length;
3347                         r->out.old_val->buf->data = crypt_secret.data;
3348                 }
3349         }
3350         
3351         if (r->in.old_mtime) {
3352                 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3353                 if (!r->out.old_mtime) {
3354                         return NT_STATUS_NO_MEMORY;
3355                 }
3356                 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(res[0], "priorSetTime", 0);
3357         }
3358         
3359         if (r->in.new_val) {
3360                 const struct ldb_val *new_val;
3361                 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3362                 if (!r->out.new_val) {
3363                         return NT_STATUS_NO_MEMORY;
3364                 }
3365
3366                 new_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3367                 
3368                 if (new_val && new_val->length) {
3369                         secret.data = new_val->data;
3370                         secret.length = new_val->length;
3371                 
3372                         /* Encrypt */
3373                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3374                         if (!crypt_secret.length) {
3375                                 return NT_STATUS_NO_MEMORY;
3376                         }
3377                         r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3378                         if (!r->out.new_val->buf) {
3379                                 return NT_STATUS_NO_MEMORY;
3380                         }
3381                         r->out.new_val->buf->length = crypt_secret.length;
3382                         r->out.new_val->buf->size = crypt_secret.length;
3383                         r->out.new_val->buf->data = crypt_secret.data;
3384                 }
3385         }
3386         
3387         if (r->in.new_mtime) {
3388                 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3389                 if (!r->out.new_mtime) {
3390                         return NT_STATUS_NO_MEMORY;
3391                 }
3392                 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3393         }
3394         
3395         return NT_STATUS_OK;
3396 }
3397
3398
3399 /* 
3400   lsa_LookupPrivValue
3401 */
3402 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call, 
3403                                     TALLOC_CTX *mem_ctx,
3404                                     struct lsa_LookupPrivValue *r)
3405 {
3406         struct dcesrv_handle *h;
3407         struct lsa_policy_state *state;
3408         int id;
3409
3410         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3411
3412         state = h->data;
3413
3414         id = sec_privilege_id(r->in.name->string);
3415         if (id == SEC_PRIV_INVALID) {
3416                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3417         }
3418
3419         r->out.luid->low = id;
3420         r->out.luid->high = 0;
3421
3422         return NT_STATUS_OK;    
3423 }
3424
3425
3426 /* 
3427   lsa_LookupPrivName 
3428 */
3429 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call, 
3430                                    TALLOC_CTX *mem_ctx,
3431                                    struct lsa_LookupPrivName *r)
3432 {
3433         struct dcesrv_handle *h;
3434         struct lsa_policy_state *state;
3435         struct lsa_StringLarge *name;
3436         const char *privname;
3437
3438         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3439
3440         state = h->data;
3441
3442         if (r->in.luid->high != 0) {
3443                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3444         }
3445
3446         privname = sec_privilege_name(r->in.luid->low);
3447         if (privname == NULL) {
3448                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3449         }
3450
3451         name = talloc(mem_ctx, struct lsa_StringLarge);
3452         if (name == NULL) {
3453                 return NT_STATUS_NO_MEMORY;
3454         }
3455
3456         name->string = privname;
3457
3458         *r->out.name = name;
3459
3460         return NT_STATUS_OK;    
3461 }
3462
3463
3464 /* 
3465   lsa_LookupPrivDisplayName
3466 */
3467 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call, 
3468                                           TALLOC_CTX *mem_ctx,
3469                                           struct lsa_LookupPrivDisplayName *r)
3470 {
3471         struct dcesrv_handle *h;
3472         struct lsa_policy_state *state;
3473         struct lsa_StringLarge *disp_name = NULL;
3474         enum sec_privilege id;
3475
3476         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3477
3478         state = h->data;
3479
3480         id = sec_privilege_id(r->in.name->string);
3481         if (id == SEC_PRIV_INVALID) {
3482                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3483         }
3484
3485         disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3486         if (disp_name == NULL) {
3487                 return NT_STATUS_NO_MEMORY;
3488         }
3489
3490         disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3491         if (disp_name->string == NULL) {
3492                 return NT_STATUS_INTERNAL_ERROR;
3493         }
3494
3495         *r->out.disp_name = disp_name;
3496         *r->out.returned_language_id = 0;
3497
3498         return NT_STATUS_OK;
3499 }
3500
3501
3502 /* 
3503   lsa_EnumAccountsWithUserRight
3504 */
3505 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call, 
3506                                               TALLOC_CTX *mem_ctx,
3507                                               struct lsa_EnumAccountsWithUserRight *r)
3508 {
3509         struct dcesrv_handle *h;
3510         struct lsa_policy_state *state;
3511         int ret, i;
3512         struct ldb_message **res;
3513         const char * const attrs[] = { "objectSid", NULL};
3514         const char *privname;
3515
3516         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3517
3518         state = h->data;
3519
3520         if (r->in.name == NULL) {
3521                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3522         } 
3523
3524         privname = r->in.name->string;
3525         if (sec_privilege_id(privname) == SEC_PRIV_INVALID && sec_right_bit(privname) == 0) {
3526                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3527         }
3528
3529         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs, 
3530                            "privilege=%s", privname);
3531         if (ret < 0) {
3532                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3533         }
3534         if (ret == 0) {
3535                 return NT_STATUS_NO_MORE_ENTRIES;
3536         }
3537
3538         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3539         if (r->out.sids->sids == NULL) {
3540                 return NT_STATUS_NO_MEMORY;
3541         }
3542         for (i=0;i<ret;i++) {
3543                 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3544                                                                 res[i], "objectSid");
3545                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3546         }
3547         r->out.sids->num_sids = ret;
3548
3549         return NT_STATUS_OK;
3550 }
3551
3552
3553 /* 
3554   lsa_AddAccountRights
3555 */
3556 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call, 
3557                                      TALLOC_CTX *mem_ctx,
3558                                      struct lsa_AddAccountRights *r)
3559 {
3560         struct dcesrv_handle *h;
3561         struct lsa_policy_state *state;
3562
3563         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3564
3565         state = h->data;
3566
3567         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
3568                                           LDB_FLAG_MOD_ADD,
3569                                           r->in.sid, r->in.rights);
3570 }
3571
3572
3573 /* 
3574   lsa_RemoveAccountRights
3575 */
3576 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call, 
3577                                         TALLOC_CTX *mem_ctx,
3578                                         struct lsa_RemoveAccountRights *r)
3579 {
3580         struct dcesrv_handle *h;
3581         struct lsa_policy_state *state;
3582
3583         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3584
3585         state = h->data;
3586
3587         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state, 
3588                                           LDB_FLAG_MOD_DELETE,
3589                                           r->in.sid, r->in.rights);
3590 }
3591
3592
3593 /* 
3594   lsa_StorePrivateData
3595 */
3596 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3597                        struct lsa_StorePrivateData *r)
3598 {
3599         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3600 }
3601
3602
3603 /* 
3604   lsa_RetrievePrivateData
3605 */
3606 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3607                        struct lsa_RetrievePrivateData *r)
3608 {
3609         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3610 }
3611
3612
3613 /* 
3614   lsa_GetUserName
3615 */
3616 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3617                                 struct lsa_GetUserName *r)
3618 {
3619         NTSTATUS status = NT_STATUS_OK;
3620         const char *account_name;
3621         const char *authority_name;
3622         struct lsa_String *_account_name;
3623         struct lsa_String *_authority_name = NULL;
3624
3625         /* this is what w2k3 does */
3626         r->out.account_name = r->in.account_name;
3627         r->out.authority_name = r->in.authority_name;
3628
3629         if (r->in.account_name
3630             && *r->in.account_name
3631             /* && *(*r->in.account_name)->string */
3632             ) {
3633                 return NT_STATUS_INVALID_PARAMETER;
3634         }
3635
3636         if (r->in.authority_name
3637             && *r->in.authority_name
3638             /* && *(*r->in.authority_name)->string */
3639             ) {
3640                 return NT_STATUS_INVALID_PARAMETER;
3641         }
3642
3643         account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3644         authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3645
3646         _account_name = talloc(mem_ctx, struct lsa_String);
3647         NT_STATUS_HAVE_NO_MEMORY(_account_name);
3648         _account_name->string = account_name;
3649
3650         if (r->in.authority_name) {
3651                 _authority_name = talloc(mem_ctx, struct lsa_String);
3652                 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3653                 _authority_name->string = authority_name;
3654         }
3655
3656         *r->out.account_name = _account_name;
3657         if (r->out.authority_name) {
3658                 *r->out.authority_name = _authority_name;
3659         }
3660
3661         return status;
3662 }
3663
3664 /*
3665   lsa_SetInfoPolicy2
3666 */
3667 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3668                                    TALLOC_CTX *mem_ctx,
3669                                    struct lsa_SetInfoPolicy2 *r)
3670 {
3671         /* need to support these */
3672         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3673 }
3674
3675 /*
3676   lsa_QueryDomainInformationPolicy
3677 */
3678 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3679                                                  TALLOC_CTX *mem_ctx,
3680                                                  struct lsa_QueryDomainInformationPolicy *r)
3681 {
3682         union lsa_DomainInformationPolicy *info;
3683
3684         info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
3685         if (!info) {
3686                 return NT_STATUS_NO_MEMORY;
3687         }
3688
3689         switch (r->in.level) {
3690         case LSA_DOMAIN_INFO_POLICY_EFS:
3691                 talloc_free(info);
3692                 *r->out.info = NULL;
3693                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3694         case LSA_DOMAIN_INFO_POLICY_KERBEROS:
3695         {
3696                 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
3697                 struct smb_krb5_context *smb_krb5_context;
3698                 int ret = smb_krb5_init_context(mem_ctx, 
3699                                                         dce_call->event_ctx, 
3700                                                         dce_call->conn->dce_ctx->lp_ctx,
3701                                                         &smb_krb5_context);
3702                 if (ret != 0) {
3703                         talloc_free(info);
3704                         *r->out.info = NULL;
3705                         return NT_STATUS_INTERNAL_ERROR;
3706                 }
3707                 kdc_get_policy(dce_call->conn->dce_ctx->lp_ctx,
3708                                smb_krb5_context,
3709                                k);
3710                 talloc_free(smb_krb5_context);
3711                 *r->out.info = info;
3712                 return NT_STATUS_OK;
3713         }
3714         default:
3715                 talloc_free(info);
3716                 *r->out.info = NULL;
3717                 return NT_STATUS_INVALID_INFO_CLASS;
3718         }
3719 }
3720
3721 /*
3722   lsa_SetDomInfoPolicy
3723 */
3724 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
3725                                               TALLOC_CTX *mem_ctx,
3726                                               struct lsa_SetDomainInformationPolicy *r)
3727 {
3728         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3729 }
3730
3731 /*
3732   lsa_TestCall
3733 */
3734 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
3735                              TALLOC_CTX *mem_ctx,
3736                              struct lsa_TestCall *r)
3737 {
3738         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3739 }
3740
3741 /* 
3742   lsa_CREDRWRITE 
3743 */
3744 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3745                        struct lsa_CREDRWRITE *r)
3746 {
3747         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3748 }
3749
3750
3751 /* 
3752   lsa_CREDRREAD 
3753 */
3754 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3755                        struct lsa_CREDRREAD *r)
3756 {
3757         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3758 }
3759
3760
3761 /* 
3762   lsa_CREDRENUMERATE 
3763 */
3764 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3765                        struct lsa_CREDRENUMERATE *r)
3766 {
3767         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3768 }
3769
3770
3771 /* 
3772   lsa_CREDRWRITEDOMAINCREDENTIALS 
3773 */
3774 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3775                        struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
3776 {
3777         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3778 }
3779
3780
3781 /* 
3782   lsa_CREDRREADDOMAINCREDENTIALS 
3783 */
3784 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3785                        struct lsa_CREDRREADDOMAINCREDENTIALS *r)
3786 {
3787         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3788 }
3789
3790
3791 /* 
3792   lsa_CREDRDELETE 
3793 */
3794 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3795                        struct lsa_CREDRDELETE *r)
3796 {
3797         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3798 }
3799
3800
3801 /* 
3802   lsa_CREDRGETTARGETINFO 
3803 */
3804 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3805                        struct lsa_CREDRGETTARGETINFO *r)
3806 {
3807         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3808 }
3809
3810
3811 /* 
3812   lsa_CREDRPROFILELOADED 
3813 */
3814 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3815                        struct lsa_CREDRPROFILELOADED *r)
3816 {
3817         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3818 }
3819
3820
3821 /* 
3822   lsa_CREDRGETSESSIONTYPES 
3823 */
3824 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3825                        struct lsa_CREDRGETSESSIONTYPES *r)
3826 {
3827         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3828 }
3829
3830
3831 /* 
3832   lsa_LSARREGISTERAUDITEVENT 
3833 */
3834 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3835                        struct lsa_LSARREGISTERAUDITEVENT *r)
3836 {
3837         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3838 }
3839
3840
3841 /* 
3842   lsa_LSARGENAUDITEVENT 
3843 */
3844 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3845                        struct lsa_LSARGENAUDITEVENT *r)
3846 {
3847         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3848 }
3849
3850
3851 /* 
3852   lsa_LSARUNREGISTERAUDITEVENT 
3853 */
3854 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3855                        struct lsa_LSARUNREGISTERAUDITEVENT *r)
3856 {
3857         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3858 }
3859
3860
3861 /* 
3862   lsa_lsaRQueryForestTrustInformation 
3863 */
3864 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3865                        struct lsa_lsaRQueryForestTrustInformation *r)
3866 {
3867         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3868 }
3869
3870 #define DNS_CMP_MATCH 0
3871 #define DNS_CMP_FIRST_IS_CHILD 1
3872 #define DNS_CMP_SECOND_IS_CHILD 2
3873 #define DNS_CMP_NO_MATCH 3
3874
3875 /* this function assumes names are well formed DNS names.
3876  * it doesn't validate them */
3877 static int dns_cmp(const char *s1, size_t l1,
3878                    const char *s2, size_t l2)
3879 {
3880         const char *p1, *p2;
3881         size_t t1, t2;
3882         int cret;
3883
3884         if (l1 == l2) {
3885                 if (strcasecmp_m(s1, s2) == 0) {
3886                         return DNS_CMP_MATCH;
3887                 }
3888                 return DNS_CMP_NO_MATCH;
3889         }
3890
3891         if (l1 > l2) {
3892                 p1 = s1;
3893                 p2 = s2;
3894                 t1 = l1;
3895                 t2 = l2;
3896                 cret = DNS_CMP_FIRST_IS_CHILD;
3897         } else {
3898                 p1 = s2;
3899                 p2 = s1;
3900                 t1 = l2;
3901                 t2 = l1;
3902                 cret = DNS_CMP_SECOND_IS_CHILD;
3903         }
3904
3905         if (p1[t1 - t2 - 1] != '.') {
3906                 return DNS_CMP_NO_MATCH;
3907         }
3908
3909         if (strcasecmp_m(&p1[t1 - t2], p2) == 0) {
3910                 return cret;
3911         }
3912
3913         return DNS_CMP_NO_MATCH;
3914 }
3915
3916 /* decode all TDOs forest trust info blobs */
3917 static NTSTATUS get_ft_info(TALLOC_CTX *mem_ctx,
3918                             struct ldb_message *msg,
3919                             struct ForestTrustInfo *info)
3920 {
3921         const struct ldb_val *ft_blob;
3922         enum ndr_err_code ndr_err;
3923
3924         ft_blob = ldb_msg_find_ldb_val(msg, "msDS-TrustForestTrustInfo");
3925         if (!ft_blob || !ft_blob->data) {
3926                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3927         }
3928         /* ldb_val is equivalent to DATA_BLOB */
3929         ndr_err = ndr_pull_struct_blob_all(ft_blob, mem_ctx, info,
3930                                            (ndr_pull_flags_fn_t)ndr_pull_ForestTrustInfo);
3931         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
3932                 return NT_STATUS_INVALID_DOMAIN_STATE;
3933         }
3934
3935         return NT_STATUS_OK;
3936 }
3937
3938 static NTSTATUS own_ft_info(struct lsa_policy_state *ps,
3939                             struct ForestTrustInfo *fti)
3940 {
3941         struct ForestTrustDataDomainInfo *info;
3942         struct ForestTrustInfoRecord *rec;
3943
3944         fti->version = 1;
3945         fti->count = 2;
3946         fti->records = talloc_array(fti,
3947                                     struct ForestTrustInfoRecordArmor, 2);
3948         if (!fti->records) {
3949                 return NT_STATUS_NO_MEMORY;
3950         }
3951
3952         /* TLN info */
3953         rec = &fti->records[0].record;
3954
3955         rec->flags = 0;
3956         rec->timestamp = 0;
3957         rec->type = LSA_FOREST_TRUST_TOP_LEVEL_NAME;
3958
3959         rec->data.name.string = talloc_strdup(fti, ps->forest_dns);
3960         if (!rec->data.name.string) {
3961                 return NT_STATUS_NO_MEMORY;
3962         }
3963         rec->data.name.size = strlen(rec->data.name.string);
3964
3965         /* DOMAIN info */
3966         rec = &fti->records[1].record;
3967
3968         rec->flags = 0;
3969         rec->timestamp = 0;
3970         rec->type = LSA_FOREST_TRUST_DOMAIN_INFO;
3971
3972         info = &rec->data.info;
3973
3974         info->sid = *ps->domain_sid;
3975         info->dns_name.string = talloc_strdup(fti, ps->domain_dns);
3976         if (!info->dns_name.string) {
3977                 return NT_STATUS_NO_MEMORY;
3978         }
3979         info->dns_name.size = strlen(info->dns_name.string);
3980         info->netbios_name.string = talloc_strdup(fti, ps->domain_name);
3981         if (!info->netbios_name.string) {
3982                 return NT_STATUS_NO_MEMORY;
3983         }
3984         info->netbios_name.size = strlen(info->netbios_name.string);
3985
3986         return NT_STATUS_OK;
3987 }
3988
3989 static NTSTATUS make_ft_info(TALLOC_CTX *mem_ctx,
3990                              struct lsa_ForestTrustInformation *lfti,
3991                              struct ForestTrustInfo *fti)
3992 {
3993         struct lsa_ForestTrustRecord *lrec;
3994         struct ForestTrustInfoRecord *rec;
3995         struct lsa_StringLarge *tln;
3996         struct lsa_ForestTrustDomainInfo *info;
3997         uint32_t i;
3998
3999         fti->version = 1;
4000         fti->count = lfti->count;
4001         fti->records = talloc_array(mem_ctx,
4002                                     struct ForestTrustInfoRecordArmor,
4003                                     fti->count);
4004         if (!fti->records) {
4005                 return NT_STATUS_NO_MEMORY;
4006         }
4007         for (i = 0; i < fti->count; i++) {
4008                 lrec = lfti->entries[i];
4009                 rec = &fti->records[i].record;
4010
4011                 rec->flags = lrec->flags;
4012                 rec->timestamp = lrec->time;
4013                 rec->type = lrec->type;
4014
4015                 switch (lrec->type) {
4016                 case LSA_FOREST_TRUST_TOP_LEVEL_NAME:
4017                 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4018                         tln = &lrec->forest_trust_data.top_level_name;
4019                         rec->data.name.string =
4020                                 talloc_strdup(mem_ctx, tln->string);
4021                         if (!rec->data.name.string) {
4022                                 return NT_STATUS_NO_MEMORY;
4023                         }
4024                         rec->data.name.size = strlen(rec->data.name.string);
4025                         break;
4026                 case LSA_FOREST_TRUST_DOMAIN_INFO:
4027                         info = &lrec->forest_trust_data.domain_info;
4028                         rec->data.info.sid = *info->domain_sid;
4029                         rec->data.info.dns_name.string =
4030                                 talloc_strdup(mem_ctx,
4031                                             info->dns_domain_name.string);
4032                         if (!rec->data.info.dns_name.string) {
4033                                 return NT_STATUS_NO_MEMORY;
4034                         }
4035                         rec->data.info.dns_name.size =
4036                                 strlen(rec->data.info.dns_name.string);
4037                         rec->data.info.netbios_name.string =
4038                                 talloc_strdup(mem_ctx,
4039                                             info->netbios_domain_name.string);
4040                         if (!rec->data.info.netbios_name.string) {
4041                                 return NT_STATUS_NO_MEMORY;
4042                         }
4043                         rec->data.info.netbios_name.size =
4044                                 strlen(rec->data.info.netbios_name.string);
4045                         break;
4046                 default:
4047                         return NT_STATUS_INVALID_DOMAIN_STATE;
4048                 }
4049         }
4050
4051         return NT_STATUS_OK;
4052 }
4053
4054 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4055                               uint32_t idx, uint32_t collision_type,
4056                               uint32_t conflict_type, const char *tdo_name);
4057
4058 static NTSTATUS check_ft_info(TALLOC_CTX *mem_ctx,
4059                               const char *tdo_name,
4060                               struct ForestTrustInfo *tdo_fti,
4061                               struct ForestTrustInfo *new_fti,
4062                               struct lsa_ForestTrustCollisionInfo *c_info)
4063 {
4064         struct ForestTrustInfoRecord *nrec;
4065         struct ForestTrustInfoRecord *trec;
4066         const char *dns_name;
4067         const char *nb_name;
4068         struct dom_sid *sid;
4069         const char *tname;
4070         size_t dns_len;
4071         size_t nb_len;
4072         size_t tlen;
4073         NTSTATUS nt_status;
4074         uint32_t new_fti_idx;
4075         uint32_t i;
4076         /* use always TDO type, until we understand when Xref can be used */
4077         uint32_t collision_type = LSA_FOREST_TRUST_COLLISION_TDO;
4078         bool tln_conflict;
4079         bool sid_conflict;
4080         bool nb_conflict;
4081         bool exclusion;
4082         bool ex_rule;
4083         int ret;
4084
4085         for (new_fti_idx = 0; new_fti_idx < new_fti->count; new_fti_idx++) {
4086
4087                 nrec = &new_fti->records[new_fti_idx].record;
4088                 dns_name = NULL;
4089                 tln_conflict = false;
4090                 sid_conflict = false;
4091                 nb_conflict = false;
4092                 exclusion = false;
4093
4094                 switch (nrec->type) {
4095                 case LSA_FOREST_TRUST_TOP_LEVEL_NAME_EX:
4096                         /* exclusions do not conflict by definition */
4097                         break;
4098
4099                 case FOREST_TRUST_TOP_LEVEL_NAME:
4100                         dns_name = nrec->data.name.string;
4101                         dns_len = nrec->data.name.size;
4102                         break;
4103
4104                 case LSA_FOREST_TRUST_DOMAIN_INFO:
4105                         dns_name = nrec->data.info.dns_name.string;
4106                         dns_len = nrec->data.info.dns_name.size;
4107                         nb_name = nrec->data.info.netbios_name.string;
4108                         nb_len = nrec->data.info.netbios_name.size;
4109                         sid = &nrec->data.info.sid;
4110                         break;
4111                 }
4112
4113                 if (!dns_name) continue;
4114
4115                 /* check if this is already taken and not excluded */
4116                 for (i = 0; i < tdo_fti->count; i++) {
4117                         trec = &tdo_fti->records[i].record;
4118
4119                         switch (trec->type) {
4120                         case FOREST_TRUST_TOP_LEVEL_NAME:
4121                                 ex_rule = false;
4122                                 tname = trec->data.name.string;
4123                                 tlen = trec->data.name.size;
4124                                 break;
4125                         case FOREST_TRUST_TOP_LEVEL_NAME_EX:
4126                                 ex_rule = true;
4127                                 tname = trec->data.name.string;
4128                                 tlen = trec->data.name.size;
4129                                 break;
4130                         case FOREST_TRUST_DOMAIN_INFO:
4131                                 ex_rule = false;
4132                                 tname = trec->data.info.dns_name.string;
4133                                 tlen = trec->data.info.dns_name.size;
4134                         }
4135                         ret = dns_cmp(dns_name, dns_len, tname, tlen);
4136                         switch (ret) {
4137                         case DNS_CMP_MATCH:
4138                                 /* if it matches exclusion,
4139                                  * it doesn't conflict */
4140                                 if (ex_rule) {
4141                                         exclusion = true;
4142                                         break;
4143                                 }
4144                                 /* fall through */
4145                         case DNS_CMP_FIRST_IS_CHILD:
4146                         case DNS_CMP_SECOND_IS_CHILD:
4147                                 tln_conflict = true;
4148                                 /* fall through */
4149                         default:
4150                                 break;
4151                         }
4152
4153                         /* explicit exclusion, no dns name conflict here */
4154                         if (exclusion) {
4155                                 tln_conflict = false;
4156                         }
4157
4158                         if (trec->type != FOREST_TRUST_DOMAIN_INFO) {
4159                                 continue;
4160                         }
4161
4162                         /* also test for domain info */
4163                         if (!(trec->flags & LSA_SID_DISABLED_ADMIN) &&
4164                             dom_sid_compare(&trec->data.info.sid, sid) == 0) {
4165                                 sid_conflict = true;
4166                         }
4167                         if (!(trec->flags & LSA_NB_DISABLED_ADMIN) &&
4168                             strcasecmp_m(trec->data.info.netbios_name.string,
4169                                          nb_name) == 0) {
4170                                 nb_conflict = true;
4171                         }
4172                 }
4173
4174                 if (tln_conflict) {
4175                         nt_status = add_collision(c_info, new_fti_idx,
4176                                                   collision_type,
4177                                                   LSA_TLN_DISABLED_CONFLICT,
4178                                                   tdo_name);
4179                 }
4180                 if (sid_conflict) {
4181                         nt_status = add_collision(c_info, new_fti_idx,
4182                                                   collision_type,
4183                                                   LSA_SID_DISABLED_CONFLICT,
4184                                                   tdo_name);
4185                 }
4186                 if (nb_conflict) {
4187                         nt_status = add_collision(c_info, new_fti_idx,
4188                                                   collision_type,
4189                                                   LSA_NB_DISABLED_CONFLICT,
4190                                                   tdo_name);
4191                 }
4192         }
4193
4194         return NT_STATUS_OK;
4195 }
4196
4197 static NTSTATUS add_collision(struct lsa_ForestTrustCollisionInfo *c_info,
4198                               uint32_t idx, uint32_t collision_type,
4199                               uint32_t conflict_type, const char *tdo_name)
4200 {
4201         struct lsa_ForestTrustCollisionRecord **es;
4202         uint32_t i = c_info->count;
4203
4204         es = talloc_realloc(c_info, c_info->entries,
4205                             struct lsa_ForestTrustCollisionRecord *, i + 1);
4206         if (!es) {
4207                 return NT_STATUS_NO_MEMORY;
4208         }
4209         c_info->entries = es;
4210         c_info->count = i + 1;
4211
4212         es[i] = talloc(es, struct lsa_ForestTrustCollisionRecord);
4213         if (!es[i]) {
4214                 return NT_STATUS_NO_MEMORY;
4215         }
4216
4217         es[i]->index = idx;
4218         es[i]->type = collision_type;
4219         es[i]->flags.flags = conflict_type;
4220         es[i]->name.string = talloc_strdup(es[i], tdo_name);
4221         if (!es[i]->name.string) {
4222                 return NT_STATUS_NO_MEMORY;
4223         }
4224         es[i]->name.size = strlen(es[i]->name.string);
4225
4226         return NT_STATUS_OK;
4227 }
4228
4229 /*
4230   lsa_lsaRSetForestTrustInformation
4231 */
4232 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4233                                                          TALLOC_CTX *mem_ctx,
4234                                                          struct lsa_lsaRSetForestTrustInformation *r)
4235 {
4236         struct dcesrv_handle *h;
4237         struct lsa_policy_state *p_state;
4238         const char *trust_attrs[] = { "trustPartner", "trustAttributes",
4239                                       "msDS-TrustForestTrustInfo", NULL };
4240         struct ldb_message **dom_res = NULL;
4241         struct ldb_dn *tdo_dn;
4242         struct ldb_message *msg;
4243         int num_res, i;
4244         const char *td_name;
4245         uint32_t trust_attributes;
4246         struct lsa_ForestTrustCollisionInfo *c_info;
4247         struct ForestTrustInfo *nfti;
4248         struct ForestTrustInfo *fti;
4249         DATA_BLOB ft_blob;
4250         enum ndr_err_code ndr_err;
4251         NTSTATUS nt_status;
4252         bool am_rodc;
4253         int ret;
4254
4255         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4256
4257         p_state = h->data;
4258
4259         if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4260                 return NT_STATUS_INVALID_DOMAIN_STATE;
4261         }
4262
4263         /* abort if we are not a PDC */
4264         if (!samdb_is_pdc(p_state->sam_ldb)) {
4265                 return NT_STATUS_INVALID_DOMAIN_ROLE;
4266         }
4267
4268         ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
4269         if (ret == LDB_SUCCESS && am_rodc) {
4270                 return NT_STATUS_NO_SUCH_DOMAIN;
4271         }
4272
4273         /* check caller has TRUSTED_SET_AUTH */
4274
4275         /* fetch all trusted domain objects */
4276         num_res = gendb_search(p_state->sam_ldb, mem_ctx,
4277                                p_state->system_dn,
4278                                &dom_res, trust_attrs,
4279                                "(objectclass=trustedDomain)");
4280         if (num_res == 0) {
4281                 return NT_STATUS_NO_SUCH_DOMAIN;
4282         }
4283
4284         for (i = 0; i < num_res; i++) {
4285                 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4286                                                       "trustPartner", NULL);
4287                 if (!td_name) {
4288                         return NT_STATUS_INVALID_DOMAIN_STATE;
4289                 }
4290                 if (strcasecmp_m(td_name,
4291                                  r->in.trusted_domain_name->string) == 0) {
4292                         break;
4293                 }
4294         }
4295         if (i >= num_res) {
4296                 return NT_STATUS_NO_SUCH_DOMAIN;
4297         }
4298
4299         tdo_dn = dom_res[i]->dn;
4300
4301         trust_attributes = ldb_msg_find_attr_as_uint(dom_res[i],
4302                                                      "trustAttributes", 0);
4303         if (!(trust_attributes & NETR_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4304                 return NT_STATUS_INVALID_PARAMETER;
4305         }
4306
4307         if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4308                 return NT_STATUS_INVALID_PARAMETER;
4309         }
4310
4311         nfti = talloc(mem_ctx, struct ForestTrustInfo);
4312         if (!nfti) {
4313                 return NT_STATUS_NO_MEMORY;
4314         }
4315
4316         nt_status = make_ft_info(nfti, r->in.forest_trust_info, nfti);
4317         if (!NT_STATUS_IS_OK(nt_status)) {
4318                 return nt_status;
4319         }
4320
4321         c_info = talloc_zero(r->out.collision_info,
4322                              struct lsa_ForestTrustCollisionInfo);
4323         if (!c_info) {
4324                 return NT_STATUS_NO_MEMORY;
4325         }
4326
4327         /* first check own info, then other domains */
4328         fti = talloc(mem_ctx, struct ForestTrustInfo);
4329         if (!fti) {
4330                 return NT_STATUS_NO_MEMORY;
4331         }
4332
4333         nt_status = own_ft_info(p_state, fti);
4334         if (!NT_STATUS_IS_OK(nt_status)) {
4335                 return nt_status;
4336         }
4337
4338         nt_status = check_ft_info(c_info, p_state->domain_dns,
4339                                   fti, nfti, c_info);
4340         if (!NT_STATUS_IS_OK(nt_status)) {
4341                 return nt_status;
4342         }
4343
4344         for (i = 0; i < num_res; i++) {
4345                 fti = talloc(mem_ctx, struct ForestTrustInfo);
4346                 if (!fti) {
4347                         return NT_STATUS_NO_MEMORY;
4348                 }
4349
4350                 nt_status = get_ft_info(mem_ctx, dom_res[i], fti);
4351                 if (!NT_STATUS_IS_OK(nt_status)) {
4352                         if (NT_STATUS_EQUAL(nt_status,
4353                             NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4354                                 continue;
4355                         }
4356                         return nt_status;
4357                 }
4358
4359                 td_name = ldb_msg_find_attr_as_string(dom_res[i],
4360                                                       "trustPartner", NULL);
4361                 if (!td_name) {
4362                         return NT_STATUS_INVALID_DOMAIN_STATE;
4363                 }
4364
4365                 nt_status = check_ft_info(c_info, td_name, fti, nfti, c_info);
4366                 if (!NT_STATUS_IS_OK(nt_status)) {
4367                         return nt_status;
4368                 }
4369         }
4370
4371         *r->out.collision_info = c_info;
4372
4373         if (r->in.check_only != 0) {
4374                 return NT_STATUS_OK;
4375         }
4376
4377         /* not just a check, write info back */
4378
4379         ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, nfti,
4380                                        (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4381         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4382                 return NT_STATUS_INVALID_PARAMETER;
4383         }
4384
4385         msg = ldb_msg_new(mem_ctx);
4386         if (msg == NULL) {
4387                 return NT_STATUS_NO_MEMORY;
4388         }
4389
4390         msg->dn = ldb_dn_copy(mem_ctx, tdo_dn);
4391         if (!msg->dn) {
4392                 return NT_STATUS_NO_MEMORY;
4393         }
4394
4395         ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4396                                 LDB_FLAG_MOD_REPLACE, NULL);
4397         if (ret != LDB_SUCCESS) {
4398                 return NT_STATUS_NO_MEMORY;
4399         }
4400         ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4401                                 &ft_blob, NULL);
4402         if (ret != LDB_SUCCESS) {
4403                 return NT_STATUS_NO_MEMORY;
4404         }
4405
4406         ret = ldb_modify(p_state->sam_ldb, msg);
4407         if (ret != LDB_SUCCESS) {
4408                 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4409                           ldb_errstring(p_state->sam_ldb)));
4410
4411                 switch (ret) {
4412                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
4413                         return NT_STATUS_ACCESS_DENIED;
4414                 default:
4415                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
4416                 }
4417         }
4418
4419         return NT_STATUS_OK;
4420 }
4421
4422 /* 
4423   lsa_CREDRRENAME 
4424 */
4425 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4426                        struct lsa_CREDRRENAME *r)
4427 {
4428         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4429 }
4430
4431
4432
4433 /* 
4434   lsa_LSAROPENPOLICYSCE 
4435 */
4436 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4437                        struct lsa_LSAROPENPOLICYSCE *r)
4438 {
4439         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4440 }
4441
4442
4443 /* 
4444   lsa_LSARADTREGISTERSECURITYEVENTSOURCE 
4445 */
4446 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4447                        struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4448 {
4449         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4450 }
4451
4452
4453 /* 
4454   lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE 
4455 */
4456 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4457                        struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4458 {
4459         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4460 }
4461
4462
4463 /* 
4464   lsa_LSARADTREPORTSECURITYEVENT 
4465 */
4466 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4467                        struct lsa_LSARADTREPORTSECURITYEVENT *r)
4468 {
4469         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4470 }
4471
4472
4473 /* include the generated boilerplate */
4474 #include "librpc/gen_ndr/ndr_lsa_s.c"
4475
4476
4477
4478 /*****************************************
4479 NOTE! The remaining calls below were
4480 removed in w2k3, so the DCESRV_FAULT()
4481 replies are the correct implementation. Do
4482 not try and fill these in with anything else
4483 ******************************************/
4484
4485 /* 
4486   dssetup_DsRoleDnsNameToFlatName 
4487 */
4488 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4489                                         struct dssetup_DsRoleDnsNameToFlatName *r)
4490 {
4491         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4492 }
4493
4494
4495 /* 
4496   dssetup_DsRoleDcAsDc 
4497 */
4498 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4499                              struct dssetup_DsRoleDcAsDc *r)
4500 {
4501         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4502 }
4503
4504
4505 /* 
4506   dssetup_DsRoleDcAsReplica 
4507 */
4508 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4509                                   struct dssetup_DsRoleDcAsReplica *r)
4510 {
4511         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4512 }
4513
4514
4515 /* 
4516   dssetup_DsRoleDemoteDc 
4517 */
4518 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4519                                struct dssetup_DsRoleDemoteDc *r)
4520 {
4521         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4522 }
4523
4524
4525 /* 
4526   dssetup_DsRoleGetDcOperationProgress 
4527 */
4528 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4529                                              struct dssetup_DsRoleGetDcOperationProgress *r)
4530 {
4531         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4532 }
4533
4534
4535 /* 
4536   dssetup_DsRoleGetDcOperationResults 
4537 */
4538 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4539                                             struct dssetup_DsRoleGetDcOperationResults *r)
4540 {
4541         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4542 }
4543
4544
4545 /* 
4546   dssetup_DsRoleCancel 
4547 */
4548 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4549                              struct dssetup_DsRoleCancel *r)
4550 {
4551         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4552 }
4553
4554
4555 /* 
4556   dssetup_DsRoleServerSaveStateForUpgrade 
4557 */
4558 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4559                                                 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4560 {
4561         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4562 }
4563
4564
4565 /* 
4566   dssetup_DsRoleUpgradeDownlevelServer 
4567 */
4568 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4569                                              struct dssetup_DsRoleUpgradeDownlevelServer *r)
4570 {
4571         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4572 }
4573
4574
4575 /* 
4576   dssetup_DsRoleAbortDownlevelServerUpgrade 
4577 */
4578 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4579                                                   struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4580 {
4581         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4582 }
4583
4584
4585 /* include the generated boilerplate */
4586 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4587
4588 NTSTATUS dcerpc_server_lsa_init(void)
4589 {
4590         NTSTATUS ret;
4591         
4592         ret = dcerpc_server_dssetup_init();
4593         if (!NT_STATUS_IS_OK(ret)) {
4594                 return ret;
4595         }
4596         ret = dcerpc_server_lsarpc_init();
4597         if (!NT_STATUS_IS_OK(ret)) {
4598                 return ret;
4599         }
4600         return ret;
4601 }