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