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