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