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