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