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