2a465d4d8123e7c7f224595074990205ed57fec5
[kai/samba-autobuild/.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
1 /* need access mask/acl implementation */
2
3 /* 
4    Unix SMB/CIFS implementation.
5
6    endpoint server for the lsarpc pipe
7
8    Copyright (C) Andrew Tridgell 2004
9    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "rpc_server/lsa/lsa.h"
26 #include "system/kerberos.h"
27 #include "auth/kerberos/kerberos.h"
28 #include "librpc/gen_ndr/ndr_drsblobs.h"
29 #include "librpc/gen_ndr/ndr_lsa.h"
30 #include "../lib/crypto/crypto.h"
31 #include "lib/util/tsort.h"
32 #include "dsdb/common/util.h"
33 #include "libcli/security/session.h"
34 #include "libcli/lsarpc/util_lsarpc.h"
35
36 /*
37   this type allows us to distinguish handle types
38 */
39
40 /*
41   state associated with a lsa_OpenAccount() operation
42 */
43 struct lsa_account_state {
44         struct lsa_policy_state *policy;
45         uint32_t access_mask;
46         struct dom_sid *account_sid;
47 };
48
49
50 /*
51   state associated with a lsa_OpenSecret() operation
52 */
53 struct lsa_secret_state {
54         struct lsa_policy_state *policy;
55         uint32_t access_mask;
56         struct ldb_dn *secret_dn;
57         struct ldb_context *sam_ldb;
58         bool global;
59 };
60
61 /*
62   state associated with a lsa_OpenTrustedDomain() operation
63 */
64 struct lsa_trusted_domain_state {
65         struct lsa_policy_state *policy;
66         uint32_t access_mask;
67         struct ldb_dn *trusted_domain_dn;
68         struct ldb_dn *trusted_domain_user_dn;
69 };
70
71 /*
72   this is based on the samba3 function make_lsa_object_sd()
73   It uses the same logic, but with samba4 helper functions
74  */
75 static NTSTATUS dcesrv_build_lsa_sd(TALLOC_CTX *mem_ctx,
76                                     struct security_descriptor **sd,
77                                     struct dom_sid *sid,
78                                     uint32_t sid_access)
79 {
80         NTSTATUS status;
81         uint32_t rid;
82         struct dom_sid *domain_sid, *domain_admins_sid;
83         const char *domain_admins_sid_str, *sidstr;
84         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
85
86         status = dom_sid_split_rid(tmp_ctx, sid, &domain_sid, &rid);
87         if (!NT_STATUS_IS_OK(status)) {
88                 TALLOC_FREE(tmp_ctx);
89                 return status;
90         }
91
92         domain_admins_sid = dom_sid_add_rid(tmp_ctx, domain_sid, DOMAIN_RID_ADMINS);
93         if (domain_admins_sid == NULL) {
94                 TALLOC_FREE(tmp_ctx);
95                 return NT_STATUS_NO_MEMORY;
96         }
97
98         domain_admins_sid_str = dom_sid_string(tmp_ctx, domain_admins_sid);
99         if (domain_admins_sid_str == NULL) {
100                 TALLOC_FREE(tmp_ctx);
101                 return NT_STATUS_NO_MEMORY;
102         }
103
104         sidstr = dom_sid_string(tmp_ctx, sid);
105         if (sidstr == NULL) {
106                 TALLOC_FREE(tmp_ctx);
107                 return NT_STATUS_NO_MEMORY;
108         }
109
110         *sd = security_descriptor_dacl_create(mem_ctx,
111                                               0, sidstr, NULL,
112
113                                               SID_WORLD,
114                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
115                                               SEC_GENERIC_EXECUTE | SEC_GENERIC_READ, 0,
116
117                                               SID_BUILTIN_ADMINISTRATORS,
118                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
119                                               SEC_GENERIC_ALL, 0,
120
121                                               SID_BUILTIN_ACCOUNT_OPERATORS,
122                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
123                                               SEC_GENERIC_ALL, 0,
124
125                                               domain_admins_sid_str,
126                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
127                                               SEC_GENERIC_ALL, 0,
128
129                                               sidstr,
130                                               SEC_ACE_TYPE_ACCESS_ALLOWED,
131                                               sid_access, 0,
132
133                                               NULL);
134         talloc_free(tmp_ctx);
135
136         NT_STATUS_HAVE_NO_MEMORY(*sd);
137
138         return NT_STATUS_OK;
139 }
140
141
142 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
143                                       TALLOC_CTX *mem_ctx,
144                                       struct lsa_EnumAccountRights *r);
145
146 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
147                                            TALLOC_CTX *mem_ctx,
148                                            struct lsa_policy_state *state,
149                                            int ldb_flag,
150                                            struct dom_sid *sid,
151                                            const struct lsa_RightSet *rights);
152
153 /*
154   lsa_Close
155 */
156 static NTSTATUS dcesrv_lsa_Close(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
157                           struct lsa_Close *r)
158 {
159         enum dcerpc_transport_t transport =
160                 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
161         struct dcesrv_handle *h;
162
163         if (transport != NCACN_NP && transport != NCALRPC) {
164                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
165         }
166
167         *r->out.handle = *r->in.handle;
168
169         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
170
171         talloc_free(h);
172
173         ZERO_STRUCTP(r->out.handle);
174
175         return NT_STATUS_OK;
176 }
177
178
179 /*
180   lsa_Delete
181 */
182 static NTSTATUS dcesrv_lsa_Delete(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
183                            struct lsa_Delete *r)
184 {
185         return NT_STATUS_NOT_SUPPORTED;
186 }
187
188
189 /*
190   lsa_DeleteObject
191 */
192 static NTSTATUS dcesrv_lsa_DeleteObject(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
193                        struct lsa_DeleteObject *r)
194 {
195         struct dcesrv_handle *h;
196         int ret;
197
198         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
199
200         if (h->wire_handle.handle_type == LSA_HANDLE_SECRET) {
201                 struct lsa_secret_state *secret_state = h->data;
202
203                 /* Ensure user is permitted to delete this... */
204                 switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
205                 {
206                 case SECURITY_SYSTEM:
207                 case SECURITY_ADMINISTRATOR:
208                         break;
209                 default:
210                         /* Users and anonymous are not allowed to delete things */
211                         return NT_STATUS_ACCESS_DENIED;
212                 }
213
214                 ret = ldb_delete(secret_state->sam_ldb,
215                                  secret_state->secret_dn);
216                 if (ret != LDB_SUCCESS) {
217                         return NT_STATUS_INVALID_HANDLE;
218                 }
219
220                 ZERO_STRUCTP(r->out.handle);
221
222                 return NT_STATUS_OK;
223
224         } else if (h->wire_handle.handle_type == LSA_HANDLE_TRUSTED_DOMAIN) {
225                 struct lsa_trusted_domain_state *trusted_domain_state =
226                         talloc_get_type(h->data, struct lsa_trusted_domain_state);
227                 ret = ldb_transaction_start(trusted_domain_state->policy->sam_ldb);
228                 if (ret != LDB_SUCCESS) {
229                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
230                 }
231
232                 ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
233                                  trusted_domain_state->trusted_domain_dn);
234                 if (ret != LDB_SUCCESS) {
235                         ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
236                         return NT_STATUS_INVALID_HANDLE;
237                 }
238
239                 if (trusted_domain_state->trusted_domain_user_dn) {
240                         ret = ldb_delete(trusted_domain_state->policy->sam_ldb,
241                                          trusted_domain_state->trusted_domain_user_dn);
242                         if (ret != LDB_SUCCESS) {
243                                 ldb_transaction_cancel(trusted_domain_state->policy->sam_ldb);
244                                 return NT_STATUS_INVALID_HANDLE;
245                         }
246                 }
247
248                 ret = ldb_transaction_commit(trusted_domain_state->policy->sam_ldb);
249                 if (ret != LDB_SUCCESS) {
250                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
251                 }
252
253                 ZERO_STRUCTP(r->out.handle);
254
255                 return NT_STATUS_OK;
256
257         } else if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
258                 struct lsa_RightSet *rights;
259                 struct lsa_account_state *astate;
260                 struct lsa_EnumAccountRights r2;
261                 NTSTATUS status;
262
263                 rights = talloc(mem_ctx, struct lsa_RightSet);
264
265                 DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
266
267                 astate = h->data;
268
269                 r2.in.handle = &astate->policy->handle->wire_handle;
270                 r2.in.sid = astate->account_sid;
271                 r2.out.rights = rights;
272
273                 /* dcesrv_lsa_EnumAccountRights takes a LSA_HANDLE_POLICY,
274                    but we have a LSA_HANDLE_ACCOUNT here, so this call
275                    will always fail */
276                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
277                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
278                         return NT_STATUS_OK;
279                 }
280
281                 if (!NT_STATUS_IS_OK(status)) {
282                         return status;
283                 }
284
285                 status = dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
286                                                     LDB_FLAG_MOD_DELETE, astate->account_sid,
287                                                     r2.out.rights);
288                 if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
289                         return NT_STATUS_OK;
290                 }
291
292                 if (!NT_STATUS_IS_OK(status)) {
293                         return status;
294                 }
295
296                 ZERO_STRUCTP(r->out.handle);
297
298                 return NT_STATUS_OK;
299         }
300
301         return NT_STATUS_INVALID_HANDLE;
302 }
303
304
305 /*
306   lsa_EnumPrivs
307 */
308 static NTSTATUS dcesrv_lsa_EnumPrivs(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
309                               struct lsa_EnumPrivs *r)
310 {
311         struct dcesrv_handle *h;
312         uint32_t i;
313         enum sec_privilege priv;
314         const char *privname;
315
316         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
317
318         i = *r->in.resume_handle;
319
320         while (((priv = sec_privilege_from_index(i)) != SEC_PRIV_INVALID) &&
321                r->out.privs->count < r->in.max_count) {
322                 struct lsa_PrivEntry *e;
323                 privname = sec_privilege_name(priv);
324                 r->out.privs->privs = talloc_realloc(r->out.privs,
325                                                        r->out.privs->privs,
326                                                        struct lsa_PrivEntry,
327                                                        r->out.privs->count+1);
328                 if (r->out.privs->privs == NULL) {
329                         return NT_STATUS_NO_MEMORY;
330                 }
331                 e = &r->out.privs->privs[r->out.privs->count];
332                 e->luid.low = priv;
333                 e->luid.high = 0;
334                 e->name.string = privname;
335                 r->out.privs->count++;
336                 i++;
337         }
338
339         *r->out.resume_handle = i;
340
341         return NT_STATUS_OK;
342 }
343
344
345 /*
346   lsa_QuerySecObj
347 */
348 static NTSTATUS dcesrv_lsa_QuerySecurity(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
349                                          struct lsa_QuerySecurity *r)
350 {
351         struct dcesrv_handle *h;
352         struct security_descriptor *sd;
353         NTSTATUS status;
354         struct dom_sid *sid;
355
356         DCESRV_PULL_HANDLE(h, r->in.handle, DCESRV_HANDLE_ANY);
357
358         sid = &dce_call->conn->auth_state.session_info->security_token->sids[PRIMARY_USER_SID_INDEX];
359
360         if (h->wire_handle.handle_type == LSA_HANDLE_POLICY) {
361                 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid, 0);
362         } else  if (h->wire_handle.handle_type == LSA_HANDLE_ACCOUNT) {
363                 status = dcesrv_build_lsa_sd(mem_ctx, &sd, sid,
364                                              LSA_ACCOUNT_ALL_ACCESS);
365         } else {
366                 return NT_STATUS_INVALID_HANDLE;
367         }
368         NT_STATUS_NOT_OK_RETURN(status);
369
370         (*r->out.sdbuf) = talloc(mem_ctx, struct sec_desc_buf);
371         NT_STATUS_HAVE_NO_MEMORY(*r->out.sdbuf);
372
373         (*r->out.sdbuf)->sd = sd;
374
375         return NT_STATUS_OK;
376 }
377
378
379 /*
380   lsa_SetSecObj
381 */
382 static NTSTATUS dcesrv_lsa_SetSecObj(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
383                               struct lsa_SetSecObj *r)
384 {
385         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
386 }
387
388
389 /*
390   lsa_ChangePassword
391 */
392 static NTSTATUS dcesrv_lsa_ChangePassword(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
393                                    struct lsa_ChangePassword *r)
394 {
395         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
396 }
397
398 /*
399   dssetup_DsRoleGetPrimaryDomainInformation
400
401   This is not an LSA call, but is the only call left on the DSSETUP
402   pipe (after the pipe was truncated), and needs lsa_get_policy_state
403 */
404 static WERROR dcesrv_dssetup_DsRoleGetPrimaryDomainInformation(struct dcesrv_call_state *dce_call,
405                                                  TALLOC_CTX *mem_ctx,
406                                                  struct dssetup_DsRoleGetPrimaryDomainInformation *r)
407 {
408         union dssetup_DsRoleInfo *info;
409
410         info = talloc_zero(mem_ctx, union dssetup_DsRoleInfo);
411         W_ERROR_HAVE_NO_MEMORY(info);
412
413         switch (r->in.level) {
414         case DS_ROLE_BASIC_INFORMATION:
415         {
416                 enum dssetup_DsRole role = DS_ROLE_STANDALONE_SERVER;
417                 uint32_t flags = 0;
418                 const char *domain = NULL;
419                 const char *dns_domain = NULL;
420                 const char *forest = NULL;
421                 struct GUID domain_guid;
422                 struct lsa_policy_state *state;
423
424                 NTSTATUS status = dcesrv_lsa_get_policy_state(dce_call, mem_ctx, &state);
425                 if (!NT_STATUS_IS_OK(status)) {
426                         return ntstatus_to_werror(status);
427                 }
428
429                 ZERO_STRUCT(domain_guid);
430
431                 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
432                 case ROLE_STANDALONE:
433                         role            = DS_ROLE_STANDALONE_SERVER;
434                         break;
435                 case ROLE_DOMAIN_MEMBER:
436                         role            = DS_ROLE_MEMBER_SERVER;
437                         break;
438                 case ROLE_ACTIVE_DIRECTORY_DC:
439                         if (samdb_is_pdc(state->sam_ldb)) {
440                                 role    = DS_ROLE_PRIMARY_DC;
441                         } else {
442                                 role    = DS_ROLE_BACKUP_DC;
443                         }
444                         break;
445                 }
446
447                 switch (lpcfg_server_role(dce_call->conn->dce_ctx->lp_ctx)) {
448                 case ROLE_STANDALONE:
449                         domain          = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
450                         W_ERROR_HAVE_NO_MEMORY(domain);
451                         break;
452                 case ROLE_DOMAIN_MEMBER:
453                         domain          = talloc_strdup(mem_ctx, lpcfg_workgroup(dce_call->conn->dce_ctx->lp_ctx));
454                         W_ERROR_HAVE_NO_MEMORY(domain);
455                         /* TODO: what is with dns_domain and forest and guid? */
456                         break;
457                 case ROLE_ACTIVE_DIRECTORY_DC:
458                         flags           = DS_ROLE_PRIMARY_DS_RUNNING;
459
460                         if (state->mixed_domain == 1) {
461                                 flags   |= DS_ROLE_PRIMARY_DS_MIXED_MODE;
462                         }
463
464                         domain          = state->domain_name;
465                         dns_domain      = state->domain_dns;
466                         forest          = state->forest_dns;
467
468                         domain_guid     = state->domain_guid;
469                         flags   |= DS_ROLE_PRIMARY_DOMAIN_GUID_PRESENT;
470                         break;
471                 }
472
473                 info->basic.role        = role;
474                 info->basic.flags       = flags;
475                 info->basic.domain      = domain;
476                 info->basic.dns_domain  = dns_domain;
477                 info->basic.forest      = forest;
478                 info->basic.domain_guid = domain_guid;
479
480                 r->out.info = info;
481                 return WERR_OK;
482         }
483         case DS_ROLE_UPGRADE_STATUS:
484         {
485                 info->upgrade.upgrading     = DS_ROLE_NOT_UPGRADING;
486                 info->upgrade.previous_role = DS_ROLE_PREVIOUS_UNKNOWN;
487
488                 r->out.info = info;
489                 return WERR_OK;
490         }
491         case DS_ROLE_OP_STATUS:
492         {
493                 info->opstatus.status = DS_ROLE_OP_IDLE;
494
495                 r->out.info = info;
496                 return WERR_OK;
497         }
498         default:
499                 return WERR_INVALID_PARAM;
500         }
501 }
502
503 /*
504   fill in the AccountDomain info
505 */
506 static NTSTATUS dcesrv_lsa_info_AccountDomain(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
507                                        struct lsa_DomainInfo *info)
508 {
509         info->name.string = state->domain_name;
510         info->sid         = state->domain_sid;
511
512         return NT_STATUS_OK;
513 }
514
515 /*
516   fill in the DNS domain info
517 */
518 static NTSTATUS dcesrv_lsa_info_DNS(struct lsa_policy_state *state, TALLOC_CTX *mem_ctx,
519                              struct lsa_DnsDomainInfo *info)
520 {
521         info->name.string = state->domain_name;
522         info->sid         = state->domain_sid;
523         info->dns_domain.string = state->domain_dns;
524         info->dns_forest.string = state->forest_dns;
525         info->domain_guid       = state->domain_guid;
526
527         return NT_STATUS_OK;
528 }
529
530 /*
531   lsa_QueryInfoPolicy2
532 */
533 static NTSTATUS dcesrv_lsa_QueryInfoPolicy2(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
534                                      struct lsa_QueryInfoPolicy2 *r)
535 {
536         struct lsa_policy_state *state;
537         struct dcesrv_handle *h;
538         union lsa_PolicyInformation *info;
539
540         *r->out.info = NULL;
541
542         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
543
544         state = h->data;
545
546         info = talloc_zero(mem_ctx, union lsa_PolicyInformation);
547         if (!info) {
548                 return NT_STATUS_NO_MEMORY;
549         }
550         *r->out.info = info;
551
552         switch (r->in.level) {
553         case LSA_POLICY_INFO_AUDIT_LOG:
554                 /* we don't need to fill in any of this */
555                 ZERO_STRUCT(info->audit_log);
556                 return NT_STATUS_OK;
557         case LSA_POLICY_INFO_AUDIT_EVENTS:
558                 /* we don't need to fill in any of this */
559                 ZERO_STRUCT(info->audit_events);
560                 return NT_STATUS_OK;
561         case LSA_POLICY_INFO_PD:
562                 /* we don't need to fill in any of this */
563                 ZERO_STRUCT(info->pd);
564                 return NT_STATUS_OK;
565
566         case LSA_POLICY_INFO_DOMAIN:
567                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->domain);
568         case LSA_POLICY_INFO_ACCOUNT_DOMAIN:
569                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->account_domain);
570         case LSA_POLICY_INFO_L_ACCOUNT_DOMAIN:
571                 return dcesrv_lsa_info_AccountDomain(state, mem_ctx, &info->l_account_domain);
572
573         case LSA_POLICY_INFO_ROLE:
574                 info->role.role = LSA_ROLE_PRIMARY;
575                 return NT_STATUS_OK;
576
577         case LSA_POLICY_INFO_DNS:
578         case LSA_POLICY_INFO_DNS_INT:
579                 return dcesrv_lsa_info_DNS(state, mem_ctx, &info->dns);
580
581         case LSA_POLICY_INFO_REPLICA:
582                 ZERO_STRUCT(info->replica);
583                 return NT_STATUS_OK;
584
585         case LSA_POLICY_INFO_QUOTA:
586                 ZERO_STRUCT(info->quota);
587                 return NT_STATUS_OK;
588
589         case LSA_POLICY_INFO_MOD:
590         case LSA_POLICY_INFO_AUDIT_FULL_SET:
591         case LSA_POLICY_INFO_AUDIT_FULL_QUERY:
592                 /* windows gives INVALID_PARAMETER */
593                 *r->out.info = NULL;
594                 return NT_STATUS_INVALID_PARAMETER;
595         }
596
597         *r->out.info = NULL;
598         return NT_STATUS_INVALID_INFO_CLASS;
599 }
600
601 /*
602   lsa_QueryInfoPolicy
603 */
604 static NTSTATUS dcesrv_lsa_QueryInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
605                                     struct lsa_QueryInfoPolicy *r)
606 {
607         struct lsa_QueryInfoPolicy2 r2;
608         NTSTATUS status;
609
610         ZERO_STRUCT(r2);
611
612         r2.in.handle = r->in.handle;
613         r2.in.level = r->in.level;
614         r2.out.info = r->out.info;
615
616         status = dcesrv_lsa_QueryInfoPolicy2(dce_call, mem_ctx, &r2);
617
618         return status;
619 }
620
621 /*
622   lsa_SetInfoPolicy
623 */
624 static NTSTATUS dcesrv_lsa_SetInfoPolicy(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
625                                   struct lsa_SetInfoPolicy *r)
626 {
627         /* need to support this */
628         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
629 }
630
631
632 /*
633   lsa_ClearAuditLog
634 */
635 static NTSTATUS dcesrv_lsa_ClearAuditLog(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
636                                   struct lsa_ClearAuditLog *r)
637 {
638         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
639 }
640
641
642 static const struct generic_mapping dcesrv_lsa_account_mapping = {
643         LSA_ACCOUNT_READ,
644         LSA_ACCOUNT_WRITE,
645         LSA_ACCOUNT_EXECUTE,
646         LSA_ACCOUNT_ALL_ACCESS
647 };
648
649 /*
650   lsa_CreateAccount
651
652   This call does not seem to have any long-term effects, hence no database operations
653
654   we need to talk to the MS product group to find out what this account database means!
655
656   answer is that the lsa database is totally separate from the SAM and
657   ldap databases. We are going to need a separate ldb to store these
658   accounts. The SIDs on this account bear no relation to the SIDs in
659   AD
660 */
661 static NTSTATUS dcesrv_lsa_CreateAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
662                                   struct lsa_CreateAccount *r)
663 {
664         struct lsa_account_state *astate;
665
666         struct lsa_policy_state *state;
667         struct dcesrv_handle *h, *ah;
668
669         ZERO_STRUCTP(r->out.acct_handle);
670
671         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
672
673         state = h->data;
674
675         astate = talloc(dce_call->conn, struct lsa_account_state);
676         if (astate == NULL) {
677                 return NT_STATUS_NO_MEMORY;
678         }
679
680         astate->account_sid = dom_sid_dup(astate, r->in.sid);
681         if (astate->account_sid == NULL) {
682                 talloc_free(astate);
683                 return NT_STATUS_NO_MEMORY;
684         }
685
686         astate->policy = talloc_reference(astate, state);
687         astate->access_mask = r->in.access_mask;
688
689         /*
690          * For now we grant all requested access.
691          *
692          * We will fail at the ldb layer later.
693          */
694         if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
695                 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
696                 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
697         }
698         se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
699
700         DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X].\n",
701                   __func__, dom_sid_string(mem_ctx, astate->account_sid),
702                  (unsigned)r->in.access_mask,
703                  (unsigned)astate->access_mask));
704
705         ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
706         if (!ah) {
707                 talloc_free(astate);
708                 return NT_STATUS_NO_MEMORY;
709         }
710
711         ah->data = talloc_steal(ah, astate);
712
713         *r->out.acct_handle = ah->wire_handle;
714
715         return NT_STATUS_OK;
716 }
717
718
719 /*
720   lsa_EnumAccounts
721 */
722 static NTSTATUS dcesrv_lsa_EnumAccounts(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
723                                  struct lsa_EnumAccounts *r)
724 {
725         struct dcesrv_handle *h;
726         struct lsa_policy_state *state;
727         int ret;
728         struct ldb_message **res;
729         const char * const attrs[] = { "objectSid", NULL};
730         uint32_t count, i;
731
732         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
733
734         state = h->data;
735
736         /* NOTE: This call must only return accounts that have at least
737            one privilege set
738         */
739         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
740                            "(&(objectSid=*)(privilege=*))");
741         if (ret < 0) {
742                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
743         }
744
745         if (*r->in.resume_handle >= ret) {
746                 return NT_STATUS_NO_MORE_ENTRIES;
747         }
748
749         count = ret - *r->in.resume_handle;
750         if (count > r->in.num_entries) {
751                 count = r->in.num_entries;
752         }
753
754         if (count == 0) {
755                 return NT_STATUS_NO_MORE_ENTRIES;
756         }
757
758         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, count);
759         if (r->out.sids->sids == NULL) {
760                 return NT_STATUS_NO_MEMORY;
761         }
762
763         for (i=0;i<count;i++) {
764                 r->out.sids->sids[i].sid =
765                         samdb_result_dom_sid(r->out.sids->sids,
766                                              res[i + *r->in.resume_handle],
767                                              "objectSid");
768                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
769         }
770
771         r->out.sids->num_sids = count;
772         *r->out.resume_handle = count + *r->in.resume_handle;
773
774         return NT_STATUS_OK;
775 }
776
777 /* This decrypts and returns Trusted Domain Auth Information Internal data */
778 static NTSTATUS get_trustdom_auth_blob(struct dcesrv_call_state *dce_call,
779                                        TALLOC_CTX *mem_ctx, DATA_BLOB *auth_blob,
780                                        struct trustDomainPasswords *auth_struct)
781 {
782         DATA_BLOB session_key = data_blob(NULL, 0);
783         enum ndr_err_code ndr_err;
784         NTSTATUS nt_status;
785
786         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
787         if (!NT_STATUS_IS_OK(nt_status)) {
788                 return nt_status;
789         }
790
791         arcfour_crypt_blob(auth_blob->data, auth_blob->length, &session_key);
792         ndr_err = ndr_pull_struct_blob(auth_blob, mem_ctx,
793                                        auth_struct,
794                                        (ndr_pull_flags_fn_t)ndr_pull_trustDomainPasswords);
795         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
796                 return NT_STATUS_INVALID_PARAMETER;
797         }
798
799         return NT_STATUS_OK;
800 }
801
802 static NTSTATUS get_trustauth_inout_blob(struct dcesrv_call_state *dce_call,
803                                          TALLOC_CTX *mem_ctx,
804                                          struct trustAuthInOutBlob *iopw,
805                                          DATA_BLOB *trustauth_blob)
806 {
807         enum ndr_err_code ndr_err;
808
809         ndr_err = ndr_push_struct_blob(trustauth_blob, mem_ctx,
810                                        iopw,
811                                        (ndr_push_flags_fn_t)ndr_push_trustAuthInOutBlob);
812         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
813                 return NT_STATUS_INVALID_PARAMETER;
814         }
815
816         return NT_STATUS_OK;
817 }
818
819 static NTSTATUS add_trust_user(TALLOC_CTX *mem_ctx,
820                                struct ldb_context *sam_ldb,
821                                struct ldb_dn *base_dn,
822                                const char *netbios_name,
823                                struct trustAuthInOutBlob *in,
824                                struct ldb_dn **user_dn)
825 {
826         struct ldb_request *req;
827         struct ldb_message *msg;
828         struct ldb_dn *dn;
829         uint32_t i;
830         int ret;
831
832         dn = ldb_dn_copy(mem_ctx, base_dn);
833         if (!dn) {
834                 return NT_STATUS_NO_MEMORY;
835         }
836         if (!ldb_dn_add_child_fmt(dn, "cn=%s$,cn=users", netbios_name)) {
837                 return NT_STATUS_NO_MEMORY;
838         }
839
840         msg = ldb_msg_new(mem_ctx);
841         if (!msg) {
842                 return NT_STATUS_NO_MEMORY;
843         }
844         msg->dn = dn;
845
846         ret = ldb_msg_add_string(msg, "objectClass", "user");
847         if (ret != LDB_SUCCESS) {
848                 return NT_STATUS_NO_MEMORY;
849         }
850
851         ret = ldb_msg_add_fmt(msg, "samAccountName", "%s$", netbios_name);
852         if (ret != LDB_SUCCESS) {
853                 return NT_STATUS_NO_MEMORY;
854         }
855
856         ret = samdb_msg_add_uint(sam_ldb, msg, msg, "userAccountControl",
857                                  UF_INTERDOMAIN_TRUST_ACCOUNT);
858         if (ret != LDB_SUCCESS) {
859                 return NT_STATUS_NO_MEMORY;
860         }
861
862         for (i = 0; i < in->count; i++) {
863                 const char *attribute;
864                 struct ldb_val v;
865                 switch (in->current.array[i].AuthType) {
866                 case TRUST_AUTH_TYPE_NT4OWF:
867                         attribute = "unicodePwd";
868                         v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
869                         v.length = 16;
870                         break;
871                 case TRUST_AUTH_TYPE_CLEAR:
872                         attribute = "clearTextPassword";
873                         v.data = in->current.array[i].AuthInfo.clear.password;
874                         v.length = in->current.array[i].AuthInfo.clear.size;
875                         break;
876                 default:
877                         continue;
878                 }
879
880                 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
881                 if (ret != LDB_SUCCESS) {
882                         return NT_STATUS_NO_MEMORY;
883                 }
884         }
885
886         /* create the trusted_domain user account */
887         ret = ldb_build_add_req(&req, sam_ldb, mem_ctx, msg, NULL, NULL,
888                                 ldb_op_default_callback, NULL);
889         if (ret != LDB_SUCCESS) {
890                 return NT_STATUS_NO_MEMORY;
891         }
892
893         ret = ldb_request_add_control(req, DSDB_CONTROL_PERMIT_INTERDOMAIN_TRUST_UAC_OID,
894                                       false, NULL);
895         if (ret != LDB_SUCCESS) {
896                 return NT_STATUS_NO_MEMORY;
897         }
898
899         ret = dsdb_autotransaction_request(sam_ldb, req);
900         if (ret != LDB_SUCCESS) {
901                 DEBUG(0,("Failed to create user record %s: %s\n",
902                          ldb_dn_get_linearized(msg->dn),
903                          ldb_errstring(sam_ldb)));
904
905                 switch (ret) {
906                 case LDB_ERR_ENTRY_ALREADY_EXISTS:
907                         return NT_STATUS_DOMAIN_EXISTS;
908                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
909                         return NT_STATUS_ACCESS_DENIED;
910                 default:
911                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
912                 }
913         }
914
915         if (user_dn) {
916                 *user_dn = dn;
917         }
918         return NT_STATUS_OK;
919 }
920
921 /*
922   lsa_CreateTrustedDomainEx2
923 */
924 static NTSTATUS dcesrv_lsa_CreateTrustedDomain_base(struct dcesrv_call_state *dce_call,
925                                                     TALLOC_CTX *mem_ctx,
926                                                     struct lsa_CreateTrustedDomainEx2 *r,
927                                                     int op,
928                                                     struct lsa_TrustDomainInfoAuthInfo *unencrypted_auth_info)
929 {
930         struct dcesrv_handle *policy_handle;
931         struct lsa_policy_state *policy_state;
932         struct lsa_trusted_domain_state *trusted_domain_state;
933         struct dcesrv_handle *handle;
934         struct ldb_message **msgs, *msg;
935         const char *attrs[] = {
936                 NULL
937         };
938         const char *netbios_name;
939         const char *dns_name;
940         const char *name;
941         DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
942         struct trustDomainPasswords auth_struct;
943         int ret;
944         NTSTATUS nt_status;
945         struct ldb_context *sam_ldb;
946
947         DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
948         ZERO_STRUCTP(r->out.trustdom_handle);
949
950         policy_state = policy_handle->data;
951         sam_ldb = policy_state->sam_ldb;
952
953         netbios_name = r->in.info->netbios_name.string;
954         if (!netbios_name) {
955                 return NT_STATUS_INVALID_PARAMETER;
956         }
957
958         dns_name = r->in.info->domain_name.string;
959
960         trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
961         if (!trusted_domain_state) {
962                 return NT_STATUS_NO_MEMORY;
963         }
964         trusted_domain_state->policy = policy_state;
965
966         if (strcasecmp(netbios_name, "BUILTIN") == 0
967             || (dns_name && strcasecmp(dns_name, "BUILTIN") == 0)
968             || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
969                 return NT_STATUS_INVALID_PARAMETER;
970         }
971
972         if (strcasecmp(netbios_name, policy_state->domain_name) == 0
973             || strcasecmp(netbios_name, policy_state->domain_dns) == 0
974             || (dns_name && strcasecmp(dns_name, policy_state->domain_dns) == 0)
975             || (dns_name && strcasecmp(dns_name, policy_state->domain_name) == 0)
976             || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
977                 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
978         }
979
980         /* While this is a REF pointer, some of the functions that wrap this don't provide this */
981         if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
982                 /* No secrets are created at this time, for this function */
983                 auth_struct.outgoing.count = 0;
984                 auth_struct.incoming.count = 0;
985         } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
986                 auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
987                                             r->in.auth_info_internal->auth_blob.size);
988                 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
989                                                    &auth_blob, &auth_struct);
990                 if (!NT_STATUS_IS_OK(nt_status)) {
991                         return nt_status;
992                 }
993         } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
994
995                 if (unencrypted_auth_info->incoming_count > 1) {
996                         return NT_STATUS_INVALID_PARAMETER;
997                 }
998
999                 /* more investigation required here, do not create secrets for
1000                  * now */
1001                 auth_struct.outgoing.count = 0;
1002                 auth_struct.incoming.count = 0;
1003         } else {
1004                 return NT_STATUS_INVALID_PARAMETER;
1005         }
1006
1007         if (auth_struct.incoming.count) {
1008                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1009                                                      &auth_struct.incoming,
1010                                                      &trustAuthIncoming);
1011                 if (!NT_STATUS_IS_OK(nt_status)) {
1012                         return nt_status;
1013                 }
1014         } else {
1015                 trustAuthIncoming = data_blob(NULL, 0);
1016         }
1017
1018         if (auth_struct.outgoing.count) {
1019                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1020                                                      &auth_struct.outgoing,
1021                                                      &trustAuthOutgoing);
1022                 if (!NT_STATUS_IS_OK(nt_status)) {
1023                         return nt_status;
1024                 }
1025         } else {
1026                 trustAuthOutgoing = data_blob(NULL, 0);
1027         }
1028
1029         ret = ldb_transaction_start(sam_ldb);
1030         if (ret != LDB_SUCCESS) {
1031                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1032         }
1033
1034         if (dns_name) {
1035                 char *dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name);
1036                 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1037                 /* search for the trusted_domain record */
1038                 ret = gendb_search(sam_ldb,
1039                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
1040                                    "(&(|(flatname=%s)(cn=%s)(trustPartner=%s)(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1041                                    dns_encoded, dns_encoded, dns_encoded, netbios_encoded, netbios_encoded, netbios_encoded);
1042                 if (ret > 0) {
1043                         ldb_transaction_cancel(sam_ldb);
1044                         return NT_STATUS_OBJECT_NAME_COLLISION;
1045                 }
1046         } else {
1047                 char *netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1048                 /* search for the trusted_domain record */
1049                 ret = gendb_search(sam_ldb,
1050                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
1051                                    "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))(objectclass=trustedDomain))",
1052                                    netbios_encoded, netbios_encoded, netbios_encoded);
1053                 if (ret > 0) {
1054                         ldb_transaction_cancel(sam_ldb);
1055                         return NT_STATUS_OBJECT_NAME_COLLISION;
1056                 }
1057         }
1058
1059         if (ret < 0 ) {
1060                 ldb_transaction_cancel(sam_ldb);
1061                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1062         }
1063
1064         name = dns_name ? dns_name : netbios_name;
1065
1066         msg = ldb_msg_new(mem_ctx);
1067         if (msg == NULL) {
1068                 return NT_STATUS_NO_MEMORY;
1069         }
1070
1071         msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1072         if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", name)) {
1073                         ldb_transaction_cancel(sam_ldb);
1074                 return NT_STATUS_NO_MEMORY;
1075         }
1076
1077         ldb_msg_add_string(msg, "flatname", netbios_name);
1078
1079         if (r->in.info->sid) {
1080                 ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier", r->in.info->sid);
1081                 if (ret != LDB_SUCCESS) {
1082                         ldb_transaction_cancel(sam_ldb);
1083                         return NT_STATUS_INVALID_PARAMETER;
1084                 }
1085         }
1086
1087         ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1088
1089         samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1090
1091         samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1092
1093         samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1094
1095         if (dns_name) {
1096                 ldb_msg_add_string(msg, "trustPartner", dns_name);
1097         }
1098
1099         if (trustAuthIncoming.data) {
1100                 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1101                 if (ret != LDB_SUCCESS) {
1102                         ldb_transaction_cancel(sam_ldb);
1103                         return NT_STATUS_NO_MEMORY;
1104                 }
1105         }
1106         if (trustAuthOutgoing.data) {
1107                 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1108                 if (ret != LDB_SUCCESS) {
1109                         ldb_transaction_cancel(sam_ldb);
1110                         return NT_STATUS_NO_MEMORY;
1111                 }
1112         }
1113
1114         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1115
1116         /* create the trusted_domain */
1117         ret = ldb_add(sam_ldb, msg);
1118         switch (ret) {
1119         case  LDB_SUCCESS:
1120                 break;
1121         case  LDB_ERR_ENTRY_ALREADY_EXISTS:
1122                 ldb_transaction_cancel(sam_ldb);
1123                 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1124                          ldb_dn_get_linearized(msg->dn),
1125                          ldb_errstring(sam_ldb)));
1126                 return NT_STATUS_DOMAIN_EXISTS;
1127         case  LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1128                 ldb_transaction_cancel(sam_ldb);
1129                 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1130                          ldb_dn_get_linearized(msg->dn),
1131                          ldb_errstring(sam_ldb)));
1132                 return NT_STATUS_ACCESS_DENIED;
1133         default:
1134                 ldb_transaction_cancel(sam_ldb);
1135                 DEBUG(0,("Failed to create user record %s: %s\n",
1136                          ldb_dn_get_linearized(msg->dn),
1137                          ldb_errstring(sam_ldb)));
1138                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1139         }
1140
1141         if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1142                 struct ldb_dn *user_dn;
1143                 /* Inbound trusts must also create a cn=users object to match */
1144                 nt_status = add_trust_user(mem_ctx, sam_ldb,
1145                                            policy_state->domain_dn,
1146                                            netbios_name,
1147                                            &auth_struct.incoming,
1148                                            &user_dn);
1149                 if (!NT_STATUS_IS_OK(nt_status)) {
1150                         ldb_transaction_cancel(sam_ldb);
1151                         return nt_status;
1152                 }
1153
1154                 /* save the trust user dn */
1155                 trusted_domain_state->trusted_domain_user_dn
1156                         = talloc_steal(trusted_domain_state, user_dn);
1157         }
1158
1159         ret = ldb_transaction_commit(sam_ldb);
1160         if (ret != LDB_SUCCESS) {
1161                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1162         }
1163
1164         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1165         if (!handle) {
1166                 return NT_STATUS_NO_MEMORY;
1167         }
1168
1169         handle->data = talloc_steal(handle, trusted_domain_state);
1170
1171         trusted_domain_state->access_mask = r->in.access_mask;
1172         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1173
1174         *r->out.trustdom_handle = handle->wire_handle;
1175
1176         return NT_STATUS_OK;
1177 }
1178
1179 /*
1180   lsa_CreateTrustedDomainEx2
1181 */
1182 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1183                                            TALLOC_CTX *mem_ctx,
1184                                            struct lsa_CreateTrustedDomainEx2 *r)
1185 {
1186         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1187 }
1188 /*
1189   lsa_CreateTrustedDomainEx
1190 */
1191 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1192                                           TALLOC_CTX *mem_ctx,
1193                                           struct lsa_CreateTrustedDomainEx *r)
1194 {
1195         struct lsa_CreateTrustedDomainEx2 r2;
1196
1197         r2.in.policy_handle = r->in.policy_handle;
1198         r2.in.info = r->in.info;
1199         r2.out.trustdom_handle = r->out.trustdom_handle;
1200         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1201 }
1202
1203 /*
1204   lsa_CreateTrustedDomain
1205 */
1206 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1207                                         struct lsa_CreateTrustedDomain *r)
1208 {
1209         struct lsa_CreateTrustedDomainEx2 r2;
1210
1211         r2.in.policy_handle = r->in.policy_handle;
1212         r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1213         if (!r2.in.info) {
1214                 return NT_STATUS_NO_MEMORY;
1215         }
1216
1217         r2.in.info->domain_name.string = NULL;
1218         r2.in.info->netbios_name = r->in.info->name;
1219         r2.in.info->sid = r->in.info->sid;
1220         r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1221         r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1222         r2.in.info->trust_attributes = 0;
1223
1224         r2.in.access_mask = r->in.access_mask;
1225         r2.out.trustdom_handle = r->out.trustdom_handle;
1226
1227         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1228 }
1229
1230 static NTSTATUS dcesrv_lsa_OpenTrustedDomain_common(
1231                                         struct dcesrv_call_state *dce_call,
1232                                         TALLOC_CTX *tmp_mem,
1233                                         struct lsa_policy_state *policy_state,
1234                                         const char *filter,
1235                                         uint32_t access_mask,
1236                                         struct dcesrv_handle **_handle)
1237 {
1238         struct lsa_trusted_domain_state *trusted_domain_state;
1239         struct dcesrv_handle *handle;
1240         struct ldb_message **msgs;
1241         const char *attrs[] = {
1242                 "trustDirection",
1243                 "flatname",
1244                 NULL
1245         };
1246         uint32_t direction;
1247         int ret;
1248
1249         /* TODO: perform access checks */
1250
1251         /* search for the trusted_domain record */
1252         ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1253                            policy_state->system_dn,
1254                            &msgs, attrs, "%s", filter);
1255         if (ret == 0) {
1256                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1257         }
1258
1259         if (ret != 1) {
1260                 DEBUG(0,("Found %d records matching %s under %s\n", ret,
1261                          filter,
1262                          ldb_dn_get_linearized(policy_state->system_dn)));
1263                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1264         }
1265
1266         trusted_domain_state = talloc_zero(tmp_mem,
1267                                            struct lsa_trusted_domain_state);
1268         if (!trusted_domain_state) {
1269                 return NT_STATUS_NO_MEMORY;
1270         }
1271         trusted_domain_state->policy = policy_state;
1272
1273         trusted_domain_state->trusted_domain_dn =
1274                 talloc_steal(trusted_domain_state, msgs[0]->dn);
1275
1276         direction = ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0);
1277         if (direction & LSA_TRUST_DIRECTION_INBOUND) {
1278                 const char *flatname = ldb_msg_find_attr_as_string(msgs[0],
1279                                                         "flatname", NULL);
1280
1281                 /* search for the trusted_domain account */
1282                 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1283                                    policy_state->domain_dn,
1284                                    &msgs, attrs,
1285                                    "(&(samaccountname=%s$)(objectclass=user)"
1286                                    "(userAccountControl:%s:=%u))",
1287                                    flatname,
1288                                    LDB_OID_COMPARATOR_AND,
1289                                    UF_INTERDOMAIN_TRUST_ACCOUNT);
1290                 if (ret == 1) {
1291                         trusted_domain_state->trusted_domain_user_dn =
1292                                 talloc_steal(trusted_domain_state, msgs[0]->dn);
1293                 }
1294         }
1295
1296         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1297         if (!handle) {
1298                 return NT_STATUS_NO_MEMORY;
1299         }
1300
1301         handle->data = talloc_steal(handle, trusted_domain_state);
1302
1303         trusted_domain_state->access_mask = access_mask;
1304         trusted_domain_state->policy = talloc_reference(trusted_domain_state,
1305                                                         policy_state);
1306
1307         *_handle = handle;
1308
1309         return NT_STATUS_OK;
1310 }
1311
1312 /*
1313   lsa_OpenTrustedDomain
1314 */
1315 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1316                                       struct lsa_OpenTrustedDomain *r)
1317 {
1318         struct dcesrv_handle *policy_handle;
1319         struct lsa_policy_state *policy_state;
1320         struct dcesrv_handle *handle;
1321         const char *sid_string;
1322         char *filter;
1323         NTSTATUS status;
1324
1325         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1326         ZERO_STRUCTP(r->out.trustdom_handle);
1327         policy_state = policy_handle->data;
1328
1329         sid_string = dom_sid_string(mem_ctx, r->in.sid);
1330         if (!sid_string) {
1331                 return NT_STATUS_NO_MEMORY;
1332         }
1333
1334         filter = talloc_asprintf(mem_ctx,
1335                                  "(&(securityIdentifier=%s)"
1336                                  "(objectclass=trustedDomain))",
1337                                  sid_string);
1338         if (filter == NULL) {
1339                 return NT_STATUS_NO_MEMORY;
1340         }
1341
1342         status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1343                                                      policy_state,
1344                                                      filter,
1345                                                      r->in.access_mask,
1346                                                      &handle);
1347         if (!NT_STATUS_IS_OK(status)) {
1348                 return status;
1349         }
1350
1351         *r->out.trustdom_handle = handle->wire_handle;
1352
1353         return NT_STATUS_OK;
1354 }
1355
1356
1357 /*
1358   lsa_OpenTrustedDomainByName
1359 */
1360 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1361                                             TALLOC_CTX *mem_ctx,
1362                                             struct lsa_OpenTrustedDomainByName *r)
1363 {
1364         struct dcesrv_handle *policy_handle;
1365         struct lsa_policy_state *policy_state;
1366         struct dcesrv_handle *handle;
1367         char *td_name;
1368         char *filter;
1369         NTSTATUS status;
1370
1371         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1372         ZERO_STRUCTP(r->out.trustdom_handle);
1373         policy_state = policy_handle->data;
1374
1375         if (!r->in.name.string) {
1376                 return NT_STATUS_INVALID_PARAMETER;
1377         }
1378
1379         /* search for the trusted_domain record */
1380         td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1381         if (td_name == NULL) {
1382                 return NT_STATUS_NO_MEMORY;
1383         }
1384
1385         filter = talloc_asprintf(mem_ctx,
1386                            "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1387                              "(objectclass=trustedDomain))",
1388                            td_name, td_name, td_name);
1389         if (filter == NULL) {
1390                 return NT_STATUS_NO_MEMORY;
1391         }
1392
1393         status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1394                                                      policy_state,
1395                                                      filter,
1396                                                      r->in.access_mask,
1397                                                      &handle);
1398         if (!NT_STATUS_IS_OK(status)) {
1399                 return status;
1400         }
1401
1402         *r->out.trustdom_handle = handle->wire_handle;
1403
1404         return NT_STATUS_OK;
1405 }
1406
1407
1408
1409 /*
1410   lsa_SetTrustedDomainInfo
1411 */
1412 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1413                                          struct lsa_SetTrustedDomainInfo *r)
1414 {
1415         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1416 }
1417
1418
1419
1420 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1421  * otherwise at least one must be provided */
1422 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1423                         struct ldb_dn *basedn, const char *dns_domain,
1424                         const char *netbios, struct dom_sid2 *sid,
1425                         struct ldb_message ***msgs)
1426 {
1427         const char *attrs[] = { "flatname", "trustPartner",
1428                                 "securityIdentifier", "trustDirection",
1429                                 "trustType", "trustAttributes",
1430                                 "trustPosixOffset",
1431                                 "msDs-supportedEncryptionTypes",
1432                                 "msDS-TrustForestTrustInfo",
1433                                 NULL
1434         };
1435         char *dns = NULL;
1436         char *nbn = NULL;
1437         char *sidstr = NULL;
1438         char *filter;
1439         int ret;
1440
1441
1442         if (dns_domain || netbios || sid) {
1443                 filter = talloc_strdup(mem_ctx,
1444                                    "(&(objectclass=trustedDomain)(|");
1445         } else {
1446                 filter = talloc_strdup(mem_ctx,
1447                                        "(objectclass=trustedDomain)");
1448         }
1449         if (!filter) {
1450                 return NT_STATUS_NO_MEMORY;
1451         }
1452
1453         if (dns_domain) {
1454                 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1455                 if (!dns) {
1456                         return NT_STATUS_NO_MEMORY;
1457                 }
1458                 filter = talloc_asprintf_append(filter,
1459                                                 "(trustPartner=%s)", dns);
1460                 if (!filter) {
1461                         return NT_STATUS_NO_MEMORY;
1462                 }
1463         }
1464         if (netbios) {
1465                 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1466                 if (!nbn) {
1467                         return NT_STATUS_NO_MEMORY;
1468                 }
1469                 filter = talloc_asprintf_append(filter,
1470                                                 "(flatname=%s)", nbn);
1471                 if (!filter) {
1472                         return NT_STATUS_NO_MEMORY;
1473                 }
1474         }
1475         if (sid) {
1476                 sidstr = dom_sid_string(mem_ctx, sid);
1477                 if (!sidstr) {
1478                         return NT_STATUS_INVALID_PARAMETER;
1479                 }
1480                 filter = talloc_asprintf_append(filter,
1481                                                 "(securityIdentifier=%s)",
1482                                                 sidstr);
1483                 if (!filter) {
1484                         return NT_STATUS_NO_MEMORY;
1485                 }
1486         }
1487         if (dns_domain || netbios || sid) {
1488                 filter = talloc_asprintf_append(filter, "))");
1489                 if (!filter) {
1490                         return NT_STATUS_NO_MEMORY;
1491                 }
1492         }
1493
1494         ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1495         if (ret == 0) {
1496                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1497         }
1498
1499         if (ret != 1) {
1500                 return NT_STATUS_OBJECT_NAME_COLLISION;
1501         }
1502
1503         return NT_STATUS_OK;
1504 }
1505
1506 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1507                                       struct ldb_context *sam_ldb,
1508                                       struct ldb_message *orig,
1509                                       struct ldb_message *dest,
1510                                       const char *attribute,
1511                                       uint32_t value,
1512                                       uint32_t *orig_value)
1513 {
1514         const struct ldb_val *orig_val;
1515         uint32_t orig_uint = 0;
1516         unsigned int flags = 0;
1517         int ret;
1518
1519         orig_val = ldb_msg_find_ldb_val(orig, attribute);
1520         if (!orig_val || !orig_val->data) {
1521                 /* add new attribute */
1522                 flags = LDB_FLAG_MOD_ADD;
1523
1524         } else {
1525                 errno = 0;
1526                 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1527                 if (errno != 0 || orig_uint != value) {
1528                         /* replace also if can't get value */
1529                         flags = LDB_FLAG_MOD_REPLACE;
1530                 }
1531         }
1532
1533         if (flags == 0) {
1534                 /* stored value is identical, nothing to change */
1535                 goto done;
1536         }
1537
1538         ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1539         if (ret != LDB_SUCCESS) {
1540                 return NT_STATUS_NO_MEMORY;
1541         }
1542
1543         ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1544         if (ret != LDB_SUCCESS) {
1545                 return NT_STATUS_NO_MEMORY;
1546         }
1547
1548 done:
1549         if (orig_value) {
1550                 *orig_value = orig_uint;
1551         }
1552         return NT_STATUS_OK;
1553 }
1554
1555 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1556                                   struct ldb_context *sam_ldb,
1557                                   struct ldb_dn *base_dn,
1558                                   bool delete_user,
1559                                   const char *netbios_name,
1560                                   struct trustAuthInOutBlob *in)
1561 {
1562         const char *attrs[] = { "userAccountControl", NULL };
1563         struct ldb_message **msgs;
1564         struct ldb_message *msg;
1565         uint32_t uac;
1566         uint32_t i;
1567         int ret;
1568
1569         ret = gendb_search(sam_ldb, mem_ctx,
1570                            base_dn, &msgs, attrs,
1571                            "samAccountName=%s$", netbios_name);
1572         if (ret > 1) {
1573                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1574         }
1575
1576         if (ret == 0) {
1577                 if (delete_user) {
1578                         return NT_STATUS_OK;
1579                 }
1580
1581                 /* ok no existing user, add it from scratch */
1582                 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1583                                       netbios_name, in, NULL);
1584         }
1585
1586         /* check user is what we are looking for */
1587         uac = ldb_msg_find_attr_as_uint(msgs[0],
1588                                         "userAccountControl", 0);
1589         if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1590                 return NT_STATUS_OBJECT_NAME_COLLISION;
1591         }
1592
1593         if (delete_user) {
1594                 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1595                 switch (ret) {
1596                 case LDB_SUCCESS:
1597                         return NT_STATUS_OK;
1598                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1599                         return NT_STATUS_ACCESS_DENIED;
1600                 default:
1601                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1602                 }
1603         }
1604
1605         /* entry exists, just modify secret if any */
1606         if (in == NULL || in->count == 0) {
1607                 return NT_STATUS_OK;
1608         }
1609
1610         msg = ldb_msg_new(mem_ctx);
1611         if (!msg) {
1612                 return NT_STATUS_NO_MEMORY;
1613         }
1614         msg->dn = msgs[0]->dn;
1615
1616         for (i = 0; i < in->count; i++) {
1617                 const char *attribute;
1618                 struct ldb_val v;
1619                 switch (in->current.array[i].AuthType) {
1620                 case TRUST_AUTH_TYPE_NT4OWF:
1621                         attribute = "unicodePwd";
1622                         v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1623                         v.length = 16;
1624                         break;
1625                 case TRUST_AUTH_TYPE_CLEAR:
1626                         attribute = "clearTextPassword";
1627                         v.data = in->current.array[i].AuthInfo.clear.password;
1628                         v.length = in->current.array[i].AuthInfo.clear.size;
1629                         break;
1630                 default:
1631                         continue;
1632                 }
1633
1634                 ret = ldb_msg_add_empty(msg, attribute,
1635                                         LDB_FLAG_MOD_REPLACE, NULL);
1636                 if (ret != LDB_SUCCESS) {
1637                         return NT_STATUS_NO_MEMORY;
1638                 }
1639
1640                 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1641                 if (ret != LDB_SUCCESS) {
1642                         return NT_STATUS_NO_MEMORY;
1643                 }
1644         }
1645
1646         /* create the trusted_domain user account */
1647         ret = ldb_modify(sam_ldb, msg);
1648         if (ret != LDB_SUCCESS) {
1649                 DEBUG(0,("Failed to create user record %s: %s\n",
1650                          ldb_dn_get_linearized(msg->dn),
1651                          ldb_errstring(sam_ldb)));
1652
1653                 switch (ret) {
1654                 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1655                         return NT_STATUS_DOMAIN_EXISTS;
1656                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1657                         return NT_STATUS_ACCESS_DENIED;
1658                 default:
1659                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1660                 }
1661         }
1662
1663         return NT_STATUS_OK;
1664 }
1665
1666
1667 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1668                                           struct lsa_policy_state *p_state,
1669                                           TALLOC_CTX *mem_ctx,
1670                                           struct ldb_message *dom_msg,
1671                                           enum lsa_TrustDomInfoEnum level,
1672                                           union lsa_TrustedDomainInfo *info)
1673 {
1674         uint32_t *posix_offset = NULL;
1675         struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1676         struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1677         struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1678         uint32_t *enc_types = NULL;
1679         DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1680         struct trustDomainPasswords auth_struct;
1681         struct trustAuthInOutBlob *current_passwords = NULL;
1682         NTSTATUS nt_status;
1683         struct ldb_message **msgs;
1684         struct ldb_message *msg;
1685         bool add_outgoing = false;
1686         bool add_incoming = false;
1687         bool del_outgoing = false;
1688         bool del_incoming = false;
1689         bool del_forest_info = false;
1690         bool in_transaction = false;
1691         int ret;
1692         bool am_rodc;
1693
1694         switch (level) {
1695         case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1696                 posix_offset = &info->posix_offset.posix_offset;
1697                 break;
1698         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1699                 info_ex = &info->info_ex;
1700                 break;
1701         case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1702                 auth_info = &info->auth_info;
1703                 break;
1704         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1705                 posix_offset = &info->full_info.posix_offset.posix_offset;
1706                 info_ex = &info->full_info.info_ex;
1707                 auth_info = &info->full_info.auth_info;
1708                 break;
1709         case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1710                 auth_info_int = &info->auth_info_internal;
1711                 break;
1712         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1713                 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1714                 info_ex = &info->full_info_internal.info_ex;
1715                 auth_info_int = &info->full_info_internal.auth_info;
1716                 break;
1717         case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1718                 enc_types = &info->enc_types.enc_types;
1719                 break;
1720         default:
1721                 return NT_STATUS_INVALID_PARAMETER;
1722         }
1723
1724         if (auth_info) {
1725                 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1726                                                   &trustAuthIncoming,
1727                                                   &trustAuthOutgoing);
1728                 if (!NT_STATUS_IS_OK(nt_status)) {
1729                         return nt_status;
1730                 }
1731                 if (trustAuthIncoming.data) {
1732                         /* This does the decode of some of this twice, but it is easier that way */
1733                         nt_status = auth_info_2_trustauth_inout(mem_ctx,
1734                                                                 auth_info->incoming_count,
1735                                                                 auth_info->incoming_current_auth_info,
1736                                                                 NULL,
1737                                                                 &current_passwords);
1738                         if (!NT_STATUS_IS_OK(nt_status)) {
1739                                 return nt_status;
1740                         }
1741                 }
1742         }
1743
1744         /* decode auth_info_int if set */
1745         if (auth_info_int) {
1746
1747                 /* now decrypt blob */
1748                 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1749                                             auth_info_int->auth_blob.size);
1750
1751                 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1752                                                    &auth_blob, &auth_struct);
1753                 if (!NT_STATUS_IS_OK(nt_status)) {
1754                         return nt_status;
1755                 }
1756         }
1757
1758         if (info_ex) {
1759                 /* verify data matches */
1760                 if (info_ex->trust_attributes &
1761                     LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1762                         /* TODO: check what behavior level we have */
1763                        if (strcasecmp_m(p_state->domain_dns,
1764                                         p_state->forest_dns) != 0) {
1765                                 return NT_STATUS_INVALID_DOMAIN_STATE;
1766                         }
1767                 }
1768
1769                 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1770                 if (ret == LDB_SUCCESS && am_rodc) {
1771                         return NT_STATUS_NO_SUCH_DOMAIN;
1772                 }
1773
1774                 /* verify only one object matches the dns/netbios/sid
1775                  * triplet and that this is the one we already have */
1776                 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1777                                     p_state->system_dn,
1778                                     info_ex->domain_name.string,
1779                                     info_ex->netbios_name.string,
1780                                     info_ex->sid, &msgs);
1781                 if (!NT_STATUS_IS_OK(nt_status)) {
1782                         return nt_status;
1783                 }
1784                 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1785                         return NT_STATUS_OBJECT_NAME_COLLISION;
1786                 }
1787                 talloc_free(msgs);
1788         }
1789
1790         /* TODO: should we fetch previous values from the existing entry
1791          * and append them ? */
1792         if (auth_info_int && auth_struct.incoming.count) {
1793                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1794                                                      &auth_struct.incoming,
1795                                                      &trustAuthIncoming);
1796                 if (!NT_STATUS_IS_OK(nt_status)) {
1797                         return nt_status;
1798                 }
1799
1800                 current_passwords = &auth_struct.incoming;
1801
1802         } else {
1803                 trustAuthIncoming = data_blob(NULL, 0);
1804         }
1805
1806         if (auth_info_int && auth_struct.outgoing.count) {
1807                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1808                                                      &auth_struct.outgoing,
1809                                                      &trustAuthOutgoing);
1810                 if (!NT_STATUS_IS_OK(nt_status)) {
1811                         return nt_status;
1812                 }
1813         } else {
1814                 trustAuthOutgoing = data_blob(NULL, 0);
1815         }
1816
1817         msg = ldb_msg_new(mem_ctx);
1818         if (msg == NULL) {
1819                 return NT_STATUS_NO_MEMORY;
1820         }
1821         msg->dn = dom_msg->dn;
1822
1823         if (posix_offset) {
1824                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1825                                                   dom_msg, msg,
1826                                                   "trustPosixOffset",
1827                                                   *posix_offset, NULL);
1828                 if (!NT_STATUS_IS_OK(nt_status)) {
1829                         return nt_status;
1830                 }
1831         }
1832
1833         if (info_ex) {
1834                 uint32_t origattrs;
1835                 uint32_t changed_attrs;
1836                 uint32_t origdir;
1837                 int origtype;
1838
1839                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1840                                                   dom_msg, msg,
1841                                                   "trustDirection",
1842                                                   info_ex->trust_direction,
1843                                                   &origdir);
1844                 if (!NT_STATUS_IS_OK(nt_status)) {
1845                         return nt_status;
1846                 }
1847
1848                 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1849                         if (auth_info != NULL && trustAuthIncoming.length > 0) {
1850                                 add_incoming = true;
1851                         }
1852                 }
1853                 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
1854                         if (auth_info != NULL && trustAuthOutgoing.length > 0) {
1855                                 add_outgoing = true;
1856                         }
1857                 }
1858
1859                 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
1860                     !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
1861                         del_incoming = true;
1862                 }
1863                 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
1864                     !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
1865                         del_outgoing = true;
1866                 }
1867
1868                 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
1869                 if (origtype == -1 || origtype != info_ex->trust_type) {
1870                         DEBUG(1, ("Attempted to change trust type! "
1871                                   "Operation not handled\n"));
1872                         return NT_STATUS_INVALID_PARAMETER;
1873                 }
1874
1875                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1876                                                   dom_msg, msg,
1877                                                   "trustAttributes",
1878                                                   info_ex->trust_attributes,
1879                                                   &origattrs);
1880                 if (!NT_STATUS_IS_OK(nt_status)) {
1881                         return nt_status;
1882                 }
1883                 /* TODO: check forestFunctionality from ldb opaque */
1884                 /* TODO: check what is set makes sense */
1885
1886                 changed_attrs = origattrs ^ info_ex->trust_attributes;
1887                 if (changed_attrs & ~LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1888                         /*
1889                          * For now we only allow
1890                          * LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE to be changed.
1891                          *
1892                          * TODO: we may need to support more attribute changes
1893                          */
1894                         DEBUG(1, ("Attempted to change trust attributes "
1895                                   "(0x%08x != 0x%08x)! "
1896                                   "Operation not handled yet...\n",
1897                                   (unsigned)origattrs,
1898                                   (unsigned)info_ex->trust_attributes));
1899                         return NT_STATUS_INVALID_PARAMETER;
1900                 }
1901
1902                 if (!(info_ex->trust_attributes &
1903                       LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE))
1904                 {
1905                         struct ldb_message_element *orig_forest_el = NULL;
1906
1907                         orig_forest_el = ldb_msg_find_element(dom_msg,
1908                                                 "msDS-TrustForestTrustInfo");
1909                         if (orig_forest_el != NULL) {
1910                                 del_forest_info = true;
1911                         }
1912                 }
1913         }
1914
1915         if (enc_types) {
1916                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1917                                                   dom_msg, msg,
1918                                                   "msDS-SupportedEncryptionTypes",
1919                                                   *enc_types, NULL);
1920                 if (!NT_STATUS_IS_OK(nt_status)) {
1921                         return nt_status;
1922                 }
1923         }
1924
1925         if (add_incoming || del_incoming) {
1926                 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1927                                         LDB_FLAG_MOD_REPLACE, NULL);
1928                 if (ret != LDB_SUCCESS) {
1929                         return NT_STATUS_NO_MEMORY;
1930                 }
1931                 if (add_incoming) {
1932                         ret = ldb_msg_add_value(msg, "trustAuthIncoming",
1933                                                 &trustAuthIncoming, NULL);
1934                         if (ret != LDB_SUCCESS) {
1935                                 return NT_STATUS_NO_MEMORY;
1936                         }
1937                 }
1938         }
1939         if (add_outgoing || del_outgoing) {
1940                 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
1941                                         LDB_FLAG_MOD_REPLACE, NULL);
1942                 if (ret != LDB_SUCCESS) {
1943                         return NT_STATUS_NO_MEMORY;
1944                 }
1945                 if (add_outgoing) {
1946                         ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1947                                                 &trustAuthOutgoing, NULL);
1948                         if (ret != LDB_SUCCESS) {
1949                                 return NT_STATUS_NO_MEMORY;
1950                         }
1951                 }
1952         }
1953         if (del_forest_info) {
1954                 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
1955                                         LDB_FLAG_MOD_REPLACE, NULL);
1956                 if (ret != LDB_SUCCESS) {
1957                         return NT_STATUS_NO_MEMORY;
1958                 }
1959         }
1960
1961         /* start transaction */
1962         ret = ldb_transaction_start(p_state->sam_ldb);
1963         if (ret != LDB_SUCCESS) {
1964                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1965         }
1966         in_transaction = true;
1967
1968         if (msg->num_elements) {
1969                 ret = ldb_modify(p_state->sam_ldb, msg);
1970                 if (ret != LDB_SUCCESS) {
1971                         DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
1972                                  ldb_dn_get_linearized(msg->dn),
1973                                  ldb_errstring(p_state->sam_ldb)));
1974                         nt_status = dsdb_ldb_err_to_ntstatus(ret);
1975                         goto done;
1976                 }
1977         }
1978
1979         if (add_incoming || del_incoming) {
1980                 const char *netbios_name;
1981
1982                 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
1983                                                            "flatname", NULL);
1984                 if (!netbios_name) {
1985                         nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
1986                         goto done;
1987                 }
1988
1989                 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
1990                 nt_status = update_trust_user(mem_ctx,
1991                                               p_state->sam_ldb,
1992                                               p_state->domain_dn,
1993                                               del_incoming,
1994                                               netbios_name,
1995                                               current_passwords);
1996                 if (!NT_STATUS_IS_OK(nt_status)) {
1997                         goto done;
1998                 }
1999         }
2000
2001         /* ok, all fine, commit transaction and return */
2002         ret = ldb_transaction_commit(p_state->sam_ldb);
2003         if (ret != LDB_SUCCESS) {
2004                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2005         }
2006         in_transaction = false;
2007
2008         nt_status = NT_STATUS_OK;
2009
2010 done:
2011         if (in_transaction) {
2012                 ldb_transaction_cancel(p_state->sam_ldb);
2013         }
2014         return nt_status;
2015 }
2016
2017 /*
2018   lsa_SetInfomrationTrustedDomain
2019 */
2020 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
2021                                 struct dcesrv_call_state *dce_call,
2022                                 TALLOC_CTX *mem_ctx,
2023                                 struct lsa_SetInformationTrustedDomain *r)
2024 {
2025         struct dcesrv_handle *h;
2026         struct lsa_trusted_domain_state *td_state;
2027         struct ldb_message **msgs;
2028         NTSTATUS nt_status;
2029
2030         DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
2031                            LSA_HANDLE_TRUSTED_DOMAIN);
2032
2033         td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2034
2035         /* get the trusted domain object */
2036         nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
2037                             td_state->trusted_domain_dn,
2038                             NULL, NULL, NULL, &msgs);
2039         if (!NT_STATUS_IS_OK(nt_status)) {
2040                 if (NT_STATUS_EQUAL(nt_status,
2041                                     NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2042                         return nt_status;
2043                 }
2044                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2045         }
2046
2047         return setInfoTrustedDomain_base(dce_call, td_state->policy, mem_ctx,
2048                                          msgs[0], r->in.level, r->in.info);
2049 }
2050
2051
2052 /*
2053   lsa_DeleteTrustedDomain
2054 */
2055 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2056                                       struct lsa_DeleteTrustedDomain *r)
2057 {
2058         NTSTATUS status;
2059         struct lsa_OpenTrustedDomain opn;
2060         struct lsa_DeleteObject del;
2061         struct dcesrv_handle *h;
2062
2063         opn.in.handle = r->in.handle;
2064         opn.in.sid = r->in.dom_sid;
2065         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2066         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2067         if (!opn.out.trustdom_handle) {
2068                 return NT_STATUS_NO_MEMORY;
2069         }
2070         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2071         if (!NT_STATUS_IS_OK(status)) {
2072                 return status;
2073         }
2074
2075         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2076         talloc_steal(mem_ctx, h);
2077
2078         del.in.handle = opn.out.trustdom_handle;
2079         del.out.handle = opn.out.trustdom_handle;
2080         status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
2081         if (!NT_STATUS_IS_OK(status)) {
2082                 return status;
2083         }
2084         return NT_STATUS_OK;
2085 }
2086
2087 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
2088                                      struct ldb_message *msg,
2089                                      struct lsa_TrustDomainInfoInfoEx *info_ex)
2090 {
2091         info_ex->domain_name.string
2092                 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2093         info_ex->netbios_name.string
2094                 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2095         info_ex->sid
2096                 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2097         info_ex->trust_direction
2098                 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2099         info_ex->trust_type
2100                 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2101         info_ex->trust_attributes
2102                 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
2103         return NT_STATUS_OK;
2104 }
2105
2106 /*
2107   lsa_QueryTrustedDomainInfo
2108 */
2109 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2110                                            struct lsa_QueryTrustedDomainInfo *r)
2111 {
2112         union lsa_TrustedDomainInfo *info = NULL;
2113         struct dcesrv_handle *h;
2114         struct lsa_trusted_domain_state *trusted_domain_state;
2115         struct ldb_message *msg;
2116         int ret;
2117         struct ldb_message **res;
2118         const char *attrs[] = {
2119                 "flatname",
2120                 "trustPartner",
2121                 "securityIdentifier",
2122                 "trustDirection",
2123                 "trustType",
2124                 "trustAttributes",
2125                 "msDs-supportedEncryptionTypes",
2126                 NULL
2127         };
2128
2129         DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2130
2131         trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2132
2133         /* pull all the user attributes */
2134         ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2135                               trusted_domain_state->trusted_domain_dn, &res, attrs);
2136         if (ret != 1) {
2137                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2138         }
2139         msg = res[0];
2140
2141         info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2142         if (!info) {
2143                 return NT_STATUS_NO_MEMORY;
2144         }
2145         *r->out.info = info;
2146
2147         switch (r->in.level) {
2148         case LSA_TRUSTED_DOMAIN_INFO_NAME:
2149                 info->name.netbios_name.string
2150                         = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2151                 break;
2152         case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2153                 info->posix_offset.posix_offset
2154                         = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2155                 break;
2156 #if 0  /* Win2k3 doesn't implement this */
2157         case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2158                 r->out.info->info_basic.netbios_name.string
2159                         = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2160                 r->out.info->info_basic.sid
2161                         = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2162                 break;
2163 #endif
2164         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2165                 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2166
2167         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2168                 ZERO_STRUCT(info->full_info);
2169                 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2170         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2171                 ZERO_STRUCT(info->full_info2_internal);
2172                 info->full_info2_internal.posix_offset.posix_offset
2173                         = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2174                 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2175
2176         case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2177                 info->enc_types.enc_types
2178                         = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2179                 break;
2180
2181         case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2182         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2183                 /* oops, we don't want to return the info after all */
2184                 talloc_free(info);
2185                 *r->out.info = NULL;
2186                 return NT_STATUS_INVALID_PARAMETER;
2187         default:
2188                 /* oops, we don't want to return the info after all */
2189                 talloc_free(info);
2190                 *r->out.info = NULL;
2191                 return NT_STATUS_INVALID_INFO_CLASS;
2192         }
2193
2194         return NT_STATUS_OK;
2195 }
2196
2197
2198 /*
2199   lsa_QueryTrustedDomainInfoBySid
2200 */
2201 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2202                                                 struct lsa_QueryTrustedDomainInfoBySid *r)
2203 {
2204         NTSTATUS status;
2205         struct lsa_OpenTrustedDomain opn;
2206         struct lsa_QueryTrustedDomainInfo query;
2207         struct dcesrv_handle *h;
2208
2209         opn.in.handle = r->in.handle;
2210         opn.in.sid = r->in.dom_sid;
2211         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2212         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2213         if (!opn.out.trustdom_handle) {
2214                 return NT_STATUS_NO_MEMORY;
2215         }
2216         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2217         if (!NT_STATUS_IS_OK(status)) {
2218                 return status;
2219         }
2220
2221         /* Ensure this handle goes away at the end of this call */
2222         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2223         talloc_steal(mem_ctx, h);
2224
2225         query.in.trustdom_handle = opn.out.trustdom_handle;
2226         query.in.level = r->in.level;
2227         query.out.info = r->out.info;
2228         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2229         if (!NT_STATUS_IS_OK(status)) {
2230                 return status;
2231         }
2232
2233         return NT_STATUS_OK;
2234 }
2235
2236 /*
2237   lsa_SetTrustedDomainInfoByName
2238 */
2239 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2240                                                TALLOC_CTX *mem_ctx,
2241                                                struct lsa_SetTrustedDomainInfoByName *r)
2242 {
2243         struct dcesrv_handle *policy_handle;
2244         struct lsa_policy_state *policy_state;
2245         struct ldb_message **msgs;
2246         NTSTATUS nt_status;
2247
2248         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2249         policy_state = policy_handle->data;
2250
2251         /* get the trusted domain object */
2252         nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2253                             policy_state->domain_dn,
2254                             r->in.trusted_domain->string,
2255                             r->in.trusted_domain->string,
2256                             NULL, &msgs);
2257         if (!NT_STATUS_IS_OK(nt_status)) {
2258                 if (NT_STATUS_EQUAL(nt_status,
2259                                     NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2260                         return nt_status;
2261                 }
2262                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2263         }
2264
2265         return setInfoTrustedDomain_base(dce_call, policy_state, mem_ctx,
2266                                          msgs[0], r->in.level, r->in.info);
2267 }
2268
2269 /*
2270    lsa_QueryTrustedDomainInfoByName
2271 */
2272 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2273                                                  TALLOC_CTX *mem_ctx,
2274                                                  struct lsa_QueryTrustedDomainInfoByName *r)
2275 {
2276         NTSTATUS status;
2277         struct lsa_OpenTrustedDomainByName opn;
2278         struct lsa_QueryTrustedDomainInfo query;
2279         struct dcesrv_handle *h;
2280
2281         opn.in.handle = r->in.handle;
2282         opn.in.name = *r->in.trusted_domain;
2283         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2284         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2285         if (!opn.out.trustdom_handle) {
2286                 return NT_STATUS_NO_MEMORY;
2287         }
2288         status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2289         if (!NT_STATUS_IS_OK(status)) {
2290                 return status;
2291         }
2292
2293         /* Ensure this handle goes away at the end of this call */
2294         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2295         talloc_steal(mem_ctx, h);
2296
2297         query.in.trustdom_handle = opn.out.trustdom_handle;
2298         query.in.level = r->in.level;
2299         query.out.info = r->out.info;
2300         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2301         if (!NT_STATUS_IS_OK(status)) {
2302                 return status;
2303         }
2304
2305         return NT_STATUS_OK;
2306 }
2307
2308 /*
2309   lsa_CloseTrustedDomainEx
2310 */
2311 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2312                                          TALLOC_CTX *mem_ctx,
2313                                          struct lsa_CloseTrustedDomainEx *r)
2314 {
2315         /* The result of a bad hair day from an IDL programmer?  Not
2316          * implmented in Win2k3.  You should always just lsa_Close
2317          * anyway. */
2318         return NT_STATUS_NOT_IMPLEMENTED;
2319 }
2320
2321
2322 /*
2323   comparison function for sorting lsa_DomainInformation array
2324 */
2325 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2326 {
2327         return strcasecmp_m(e1->name.string, e2->name.string);
2328 }
2329
2330 /*
2331   lsa_EnumTrustDom
2332 */
2333 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2334                                  struct lsa_EnumTrustDom *r)
2335 {
2336         struct dcesrv_handle *policy_handle;
2337         struct lsa_DomainInfo *entries;
2338         struct lsa_policy_state *policy_state;
2339         struct ldb_message **domains;
2340         const char *attrs[] = {
2341                 "flatname",
2342                 "securityIdentifier",
2343                 NULL
2344         };
2345
2346
2347         int count, i;
2348
2349         *r->out.resume_handle = 0;
2350
2351         r->out.domains->domains = NULL;
2352         r->out.domains->count = 0;
2353
2354         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2355
2356         policy_state = policy_handle->data;
2357
2358         /* search for all users in this domain. This could possibly be cached and
2359            resumed based on resume_key */
2360         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2361                              "objectclass=trustedDomain");
2362         if (count < 0) {
2363                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2364         }
2365
2366         /* convert to lsa_TrustInformation format */
2367         entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2368         if (!entries) {
2369                 return NT_STATUS_NO_MEMORY;
2370         }
2371         for (i=0;i<count;i++) {
2372                 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2373                 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2374         }
2375
2376         /* sort the results by name */
2377         TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2378
2379         if (*r->in.resume_handle >= count) {
2380                 *r->out.resume_handle = -1;
2381
2382                 return NT_STATUS_NO_MORE_ENTRIES;
2383         }
2384
2385         /* return the rest, limit by max_size. Note that we
2386            use the w2k3 element size value of 60 */
2387         r->out.domains->count = count - *r->in.resume_handle;
2388         r->out.domains->count = MIN(r->out.domains->count,
2389                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2390
2391         r->out.domains->domains = entries + *r->in.resume_handle;
2392         r->out.domains->count = r->out.domains->count;
2393
2394         if (r->out.domains->count < count - *r->in.resume_handle) {
2395                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2396                 return STATUS_MORE_ENTRIES;
2397         }
2398
2399         /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2400          * always be larger than the previous input resume handle, in
2401          * particular when hitting the last query it is vital to set the
2402          * resume handle correctly to avoid infinite client loops, as
2403          * seen e.g. with Windows XP SP3 when resume handle is 0 and
2404          * status is NT_STATUS_OK - gd */
2405
2406         *r->out.resume_handle = (uint32_t)-1;
2407
2408         return NT_STATUS_OK;
2409 }
2410
2411 /*
2412   comparison function for sorting lsa_DomainInformation array
2413 */
2414 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2415 {
2416         return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2417 }
2418
2419 /*
2420   lsa_EnumTrustedDomainsEx
2421 */
2422 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2423                                         struct lsa_EnumTrustedDomainsEx *r)
2424 {
2425         struct dcesrv_handle *policy_handle;
2426         struct lsa_TrustDomainInfoInfoEx *entries;
2427         struct lsa_policy_state *policy_state;
2428         struct ldb_message **domains;
2429         const char *attrs[] = {
2430                 "flatname",
2431                 "trustPartner",
2432                 "securityIdentifier",
2433                 "trustDirection",
2434                 "trustType",
2435                 "trustAttributes",
2436                 NULL
2437         };
2438         NTSTATUS nt_status;
2439
2440         int count, i;
2441
2442         *r->out.resume_handle = 0;
2443
2444         r->out.domains->domains = NULL;
2445         r->out.domains->count = 0;
2446
2447         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2448
2449         policy_state = policy_handle->data;
2450
2451         /* search for all users in this domain. This could possibly be cached and
2452            resumed based on resume_key */
2453         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2454                              "objectclass=trustedDomain");
2455         if (count < 0) {
2456                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2457         }
2458
2459         /* convert to lsa_DomainInformation format */
2460         entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2461         if (!entries) {
2462                 return NT_STATUS_NO_MEMORY;
2463         }
2464         for (i=0;i<count;i++) {
2465                 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2466                 if (!NT_STATUS_IS_OK(nt_status)) {
2467                         return nt_status;
2468                 }
2469         }
2470
2471         /* sort the results by name */
2472         TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2473
2474         if (*r->in.resume_handle >= count) {
2475                 *r->out.resume_handle = -1;
2476
2477                 return NT_STATUS_NO_MORE_ENTRIES;
2478         }
2479
2480         /* return the rest, limit by max_size. Note that we
2481            use the w2k3 element size value of 60 */
2482         r->out.domains->count = count - *r->in.resume_handle;
2483         r->out.domains->count = MIN(r->out.domains->count,
2484                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2485
2486         r->out.domains->domains = entries + *r->in.resume_handle;
2487         r->out.domains->count = r->out.domains->count;
2488
2489         if (r->out.domains->count < count - *r->in.resume_handle) {
2490                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2491                 return STATUS_MORE_ENTRIES;
2492         }
2493
2494         *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2495
2496         return NT_STATUS_OK;
2497 }
2498
2499
2500 /*
2501   lsa_OpenAccount
2502 */
2503 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2504                                 struct lsa_OpenAccount *r)
2505 {
2506         struct dcesrv_handle *h, *ah;
2507         struct lsa_policy_state *state;
2508         struct lsa_account_state *astate;
2509
2510         ZERO_STRUCTP(r->out.acct_handle);
2511
2512         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2513
2514         state = h->data;
2515
2516         astate = talloc(dce_call->conn, struct lsa_account_state);
2517         if (astate == NULL) {
2518                 return NT_STATUS_NO_MEMORY;
2519         }
2520
2521         astate->account_sid = dom_sid_dup(astate, r->in.sid);
2522         if (astate->account_sid == NULL) {
2523                 talloc_free(astate);
2524                 return NT_STATUS_NO_MEMORY;
2525         }
2526
2527         astate->policy = talloc_reference(astate, state);
2528         astate->access_mask = r->in.access_mask;
2529
2530         /*
2531          * For now we grant all requested access.
2532          *
2533          * We will fail at the ldb layer later.
2534          */
2535         if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
2536                 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
2537                 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
2538         }
2539         se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
2540
2541         DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X] - success.\n",
2542                   __func__, dom_sid_string(mem_ctx, astate->account_sid),
2543                  (unsigned)r->in.access_mask,
2544                  (unsigned)astate->access_mask));
2545
2546         ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2547         if (!ah) {
2548                 talloc_free(astate);
2549                 return NT_STATUS_NO_MEMORY;
2550         }
2551
2552         ah->data = talloc_steal(ah, astate);
2553
2554         *r->out.acct_handle = ah->wire_handle;
2555
2556         return NT_STATUS_OK;
2557 }
2558
2559
2560 /*
2561   lsa_EnumPrivsAccount
2562 */
2563 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2564                                      TALLOC_CTX *mem_ctx,
2565                                      struct lsa_EnumPrivsAccount *r)
2566 {
2567         struct dcesrv_handle *h;
2568         struct lsa_account_state *astate;
2569         int ret;
2570         unsigned int i, j;
2571         struct ldb_message **res;
2572         const char * const attrs[] = { "privilege", NULL};
2573         struct ldb_message_element *el;
2574         const char *sidstr;
2575         struct lsa_PrivilegeSet *privs;
2576
2577         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2578
2579         astate = h->data;
2580
2581         privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2582         if (privs == NULL) {
2583                 return NT_STATUS_NO_MEMORY;
2584         }
2585         privs->count = 0;
2586         privs->unknown = 0;
2587         privs->set = NULL;
2588
2589         *r->out.privs = privs;
2590
2591         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2592         if (sidstr == NULL) {
2593                 return NT_STATUS_NO_MEMORY;
2594         }
2595
2596         ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2597                            "objectSid=%s", sidstr);
2598         if (ret < 0) {
2599                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2600         }
2601         if (ret != 1) {
2602                 return NT_STATUS_OK;
2603         }
2604
2605         el = ldb_msg_find_element(res[0], "privilege");
2606         if (el == NULL || el->num_values == 0) {
2607                 return NT_STATUS_OK;
2608         }
2609
2610         privs->set = talloc_array(privs,
2611                                   struct lsa_LUIDAttribute, el->num_values);
2612         if (privs->set == NULL) {
2613                 return NT_STATUS_NO_MEMORY;
2614         }
2615
2616         j = 0;
2617         for (i=0;i<el->num_values;i++) {
2618                 int id = sec_privilege_id((const char *)el->values[i].data);
2619                 if (id == SEC_PRIV_INVALID) {
2620                         /* Perhaps an account right, not a privilege */
2621                         continue;
2622                 }
2623                 privs->set[j].attribute = 0;
2624                 privs->set[j].luid.low = id;
2625                 privs->set[j].luid.high = 0;
2626                 j++;
2627         }
2628
2629         privs->count = j;
2630
2631         return NT_STATUS_OK;
2632 }
2633
2634 /*
2635   lsa_EnumAccountRights
2636 */
2637 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2638                                       TALLOC_CTX *mem_ctx,
2639                                       struct lsa_EnumAccountRights *r)
2640 {
2641         struct dcesrv_handle *h;
2642         struct lsa_policy_state *state;
2643         int ret;
2644         unsigned int i;
2645         struct ldb_message **res;
2646         const char * const attrs[] = { "privilege", NULL};
2647         const char *sidstr;
2648         struct ldb_message_element *el;
2649
2650         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2651
2652         state = h->data;
2653
2654         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2655         if (sidstr == NULL) {
2656                 return NT_STATUS_NO_MEMORY;
2657         }
2658
2659         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2660                            "(&(objectSid=%s)(privilege=*))", sidstr);
2661         if (ret == 0) {
2662                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2663         }
2664         if (ret != 1) {
2665                 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2666                           dom_sid_string(mem_ctx, r->in.sid),
2667                           ldb_errstring(state->pdb)));
2668                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2669         }
2670
2671         el = ldb_msg_find_element(res[0], "privilege");
2672         if (el == NULL || el->num_values == 0) {
2673                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2674         }
2675
2676         r->out.rights->count = el->num_values;
2677         r->out.rights->names = talloc_array(r->out.rights,
2678                                             struct lsa_StringLarge, r->out.rights->count);
2679         if (r->out.rights->names == NULL) {
2680                 return NT_STATUS_NO_MEMORY;
2681         }
2682
2683         for (i=0;i<el->num_values;i++) {
2684                 r->out.rights->names[i].string = (const char *)el->values[i].data;
2685         }
2686
2687         return NT_STATUS_OK;
2688 }
2689
2690
2691
2692 /*
2693   helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2694 */
2695 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2696                                            TALLOC_CTX *mem_ctx,
2697                                            struct lsa_policy_state *state,
2698                                            int ldb_flag,
2699                                            struct dom_sid *sid,
2700                                            const struct lsa_RightSet *rights)
2701 {
2702         const char *sidstr, *sidndrstr;
2703         struct ldb_message *msg;
2704         struct ldb_message_element *el;
2705         int ret;
2706         uint32_t i;
2707         struct lsa_EnumAccountRights r2;
2708         char *dnstr;
2709
2710         if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2711             SECURITY_ADMINISTRATOR) {
2712                 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2713                 return NT_STATUS_ACCESS_DENIED;
2714         }
2715
2716         msg = ldb_msg_new(mem_ctx);
2717         if (msg == NULL) {
2718                 return NT_STATUS_NO_MEMORY;
2719         }
2720
2721         sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2722         if (sidndrstr == NULL) {
2723                 TALLOC_FREE(msg);
2724                 return NT_STATUS_NO_MEMORY;
2725         }
2726
2727         sidstr = dom_sid_string(msg, sid);
2728         if (sidstr == NULL) {
2729                 TALLOC_FREE(msg);
2730                 return NT_STATUS_NO_MEMORY;
2731         }
2732
2733         dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2734         if (dnstr == NULL) {
2735                 TALLOC_FREE(msg);
2736                 return NT_STATUS_NO_MEMORY;
2737         }
2738
2739         msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2740         if (msg->dn == NULL) {
2741                 TALLOC_FREE(msg);
2742                 return NT_STATUS_NO_MEMORY;
2743         }
2744
2745         if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2746                 NTSTATUS status;
2747
2748                 r2.in.handle = &state->handle->wire_handle;
2749                 r2.in.sid = sid;
2750                 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2751
2752                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2753                 if (!NT_STATUS_IS_OK(status)) {
2754                         ZERO_STRUCTP(r2.out.rights);
2755                 }
2756         }
2757
2758         for (i=0;i<rights->count;i++) {
2759                 if (sec_privilege_id(rights->names[i].string) == SEC_PRIV_INVALID) {
2760                         if (sec_right_bit(rights->names[i].string) == 0) {
2761                                 talloc_free(msg);
2762                                 return NT_STATUS_NO_SUCH_PRIVILEGE;
2763                         }
2764
2765                         talloc_free(msg);
2766                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2767                 }
2768
2769                 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2770                         uint32_t j;
2771                         for (j=0;j<r2.out.rights->count;j++) {
2772                                 if (strcasecmp_m(r2.out.rights->names[j].string,
2773                                                rights->names[i].string) == 0) {
2774                                         break;
2775                                 }
2776                         }
2777                         if (j != r2.out.rights->count) continue;
2778                 }
2779
2780                 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2781                 if (ret != LDB_SUCCESS) {
2782                         talloc_free(msg);
2783                         return NT_STATUS_NO_MEMORY;
2784                 }
2785         }
2786
2787         el = ldb_msg_find_element(msg, "privilege");
2788         if (!el) {
2789                 talloc_free(msg);
2790                 return NT_STATUS_OK;
2791         }
2792
2793         el->flags = ldb_flag;
2794
2795         ret = ldb_modify(state->pdb, msg);
2796         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2797                 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2798                         talloc_free(msg);
2799                         return NT_STATUS_NO_MEMORY;
2800                 }
2801                 ldb_msg_add_string(msg, "comment", "added via LSA");
2802                 ret = ldb_add(state->pdb, msg);
2803         }
2804         if (ret != LDB_SUCCESS) {
2805                 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2806                         talloc_free(msg);
2807                         return NT_STATUS_OK;
2808                 }
2809                 DEBUG(3, ("Could not %s attributes from %s: %s",
2810                           LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2811                           ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2812                 talloc_free(msg);
2813                 return NT_STATUS_UNEXPECTED_IO_ERROR;
2814         }
2815
2816         talloc_free(msg);
2817         return NT_STATUS_OK;
2818 }
2819
2820 /*
2821   lsa_AddPrivilegesToAccount
2822 */
2823 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2824                                            struct lsa_AddPrivilegesToAccount *r)
2825 {
2826         struct lsa_RightSet rights;
2827         struct dcesrv_handle *h;
2828         struct lsa_account_state *astate;
2829         uint32_t i;
2830
2831         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2832
2833         astate = h->data;
2834
2835         rights.count = r->in.privs->count;
2836         rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
2837         if (rights.names == NULL) {
2838                 return NT_STATUS_NO_MEMORY;
2839         }
2840         for (i=0;i<rights.count;i++) {
2841                 int id = r->in.privs->set[i].luid.low;
2842                 if (r->in.privs->set[i].luid.high) {
2843                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2844                 }
2845                 rights.names[i].string = sec_privilege_name(id);
2846                 if (rights.names[i].string == NULL) {
2847                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2848                 }
2849         }
2850
2851         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2852                                           LDB_FLAG_MOD_ADD, astate->account_sid,
2853                                           &rights);
2854 }
2855
2856
2857 /*
2858   lsa_RemovePrivilegesFromAccount
2859 */
2860 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2861                                                 struct lsa_RemovePrivilegesFromAccount *r)
2862 {
2863         struct lsa_RightSet *rights;
2864         struct dcesrv_handle *h;
2865         struct lsa_account_state *astate;
2866         uint32_t i;
2867
2868         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2869
2870         astate = h->data;
2871
2872         rights = talloc(mem_ctx, struct lsa_RightSet);
2873
2874         if (r->in.remove_all == 1 &&
2875             r->in.privs == NULL) {
2876                 struct lsa_EnumAccountRights r2;
2877                 NTSTATUS status;
2878
2879                 r2.in.handle = &astate->policy->handle->wire_handle;
2880                 r2.in.sid = astate->account_sid;
2881                 r2.out.rights = rights;
2882
2883                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2884                 if (!NT_STATUS_IS_OK(status)) {
2885                         return status;
2886                 }
2887
2888                 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2889                                                   LDB_FLAG_MOD_DELETE, astate->account_sid,
2890                                                   r2.out.rights);
2891         }
2892
2893         if (r->in.remove_all != 0) {
2894                 return NT_STATUS_INVALID_PARAMETER;
2895         }
2896
2897         rights->count = r->in.privs->count;
2898         rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
2899         if (rights->names == NULL) {
2900                 return NT_STATUS_NO_MEMORY;
2901         }
2902         for (i=0;i<rights->count;i++) {
2903                 int id = r->in.privs->set[i].luid.low;
2904                 if (r->in.privs->set[i].luid.high) {
2905                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2906                 }
2907                 rights->names[i].string = sec_privilege_name(id);
2908                 if (rights->names[i].string == NULL) {
2909                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2910                 }
2911         }
2912
2913         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
2914                                           LDB_FLAG_MOD_DELETE, astate->account_sid,
2915                                           rights);
2916 }
2917
2918
2919 /*
2920   lsa_GetQuotasForAccount
2921 */
2922 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2923                        struct lsa_GetQuotasForAccount *r)
2924 {
2925         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2926 }
2927
2928
2929 /*
2930   lsa_SetQuotasForAccount
2931 */
2932 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2933                        struct lsa_SetQuotasForAccount *r)
2934 {
2935         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2936 }
2937
2938
2939 /*
2940   lsa_GetSystemAccessAccount
2941 */
2942 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2943                        struct lsa_GetSystemAccessAccount *r)
2944 {
2945         struct dcesrv_handle *h;
2946         struct lsa_account_state *astate;
2947         int ret;
2948         unsigned int i;
2949         struct ldb_message **res;
2950         const char * const attrs[] = { "privilege", NULL};
2951         struct ldb_message_element *el;
2952         const char *sidstr;
2953
2954         *(r->out.access_mask) = 0x00000000;
2955
2956         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2957
2958         astate = h->data;
2959
2960         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2961         if (sidstr == NULL) {
2962                 return NT_STATUS_NO_MEMORY;
2963         }
2964
2965         ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2966                            "objectSid=%s", sidstr);
2967         if (ret < 0) {
2968                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2969         }
2970         if (ret != 1) {
2971                 return NT_STATUS_OK;
2972         }
2973
2974         el = ldb_msg_find_element(res[0], "privilege");
2975         if (el == NULL || el->num_values == 0) {
2976                 return NT_STATUS_OK;
2977         }
2978
2979         for (i=0;i<el->num_values;i++) {
2980                 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
2981                 if (right_bit == 0) {
2982                         /* Perhaps an privilege, not a right */
2983                         continue;
2984                 }
2985                 *(r->out.access_mask) |= right_bit;
2986         }
2987
2988         return NT_STATUS_OK;
2989 }
2990
2991
2992 /*
2993   lsa_SetSystemAccessAccount
2994 */
2995 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2996                        struct lsa_SetSystemAccessAccount *r)
2997 {
2998         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
2999 }
3000
3001
3002 /*
3003   lsa_CreateSecret
3004 */
3005 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3006                                  struct lsa_CreateSecret *r)
3007 {
3008         struct dcesrv_handle *policy_handle;
3009         struct lsa_policy_state *policy_state;
3010         struct lsa_secret_state *secret_state;
3011         struct dcesrv_handle *handle;
3012         struct ldb_message **msgs, *msg;
3013         const char *attrs[] = {
3014                 NULL
3015         };
3016
3017         const char *name;
3018
3019         int ret;
3020
3021         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3022         ZERO_STRUCTP(r->out.sec_handle);
3023
3024         switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3025         {
3026         case SECURITY_SYSTEM:
3027         case SECURITY_ADMINISTRATOR:
3028                 break;
3029         default:
3030                 /* Users and annonymous are not allowed create secrets */
3031                 return NT_STATUS_ACCESS_DENIED;
3032         }
3033
3034         policy_state = policy_handle->data;
3035
3036         if (!r->in.name.string) {
3037                 return NT_STATUS_INVALID_PARAMETER;
3038         }
3039
3040         secret_state = talloc(mem_ctx, struct lsa_secret_state);
3041         NT_STATUS_HAVE_NO_MEMORY(secret_state);
3042         secret_state->policy = policy_state;
3043
3044         msg = ldb_msg_new(mem_ctx);
3045         if (msg == NULL) {
3046                 return NT_STATUS_NO_MEMORY;
3047         }
3048
3049         if (strncmp("G$", r->in.name.string, 2) == 0) {
3050                 const char *name2;
3051
3052                 secret_state->global = true;
3053
3054                 name = &r->in.name.string[2];
3055                 if (strlen(name) == 0) {
3056                         return NT_STATUS_INVALID_PARAMETER;
3057                 }
3058
3059                 name2 = talloc_asprintf(mem_ctx, "%s Secret",
3060                                         ldb_binary_encode_string(mem_ctx, name));
3061                 NT_STATUS_HAVE_NO_MEMORY(name2);
3062
3063                 /* We need to connect to the database as system, as this is one
3064                  * of the rare RPC calls that must read the secrets (and this
3065                  * is denied otherwise) */
3066                 secret_state->sam_ldb = talloc_reference(secret_state,
3067                                                          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));
3068                 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3069
3070                 /* search for the secret record */
3071                 ret = gendb_search(secret_state->sam_ldb,
3072                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
3073                                    "(&(cn=%s)(objectclass=secret))",
3074                                    name2);
3075                 if (ret > 0) {
3076                         return NT_STATUS_OBJECT_NAME_COLLISION;
3077                 }
3078
3079                 if (ret < 0) {
3080                         DEBUG(0,("Failure searching for CN=%s: %s\n",
3081                                  name2, ldb_errstring(secret_state->sam_ldb)));
3082                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3083                 }
3084
3085                 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
3086                 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3087                 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
3088                         return NT_STATUS_NO_MEMORY;
3089                 }
3090
3091                 ret = ldb_msg_add_string(msg, "cn", name2);
3092                 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3093         } else {
3094                 secret_state->global = false;
3095
3096                 name = r->in.name.string;
3097                 if (strlen(name) == 0) {
3098                         return NT_STATUS_INVALID_PARAMETER;
3099                 }
3100
3101                 secret_state->sam_ldb = talloc_reference(secret_state,
3102                                                          secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3103                 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3104
3105                 /* search for the secret record */
3106                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3107                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3108                                    &msgs, attrs,
3109                                    "(&(cn=%s)(objectclass=secret))",
3110                                    ldb_binary_encode_string(mem_ctx, name));
3111                 if (ret > 0) {
3112                         return NT_STATUS_OBJECT_NAME_COLLISION;
3113                 }
3114
3115                 if (ret < 0) {
3116                         DEBUG(0,("Failure searching for CN=%s: %s\n",
3117                                  name, ldb_errstring(secret_state->sam_ldb)));
3118                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3119                 }
3120
3121                 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
3122                                          "cn=%s,cn=LSA Secrets", name);
3123                 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3124                 ret = ldb_msg_add_string(msg, "cn", name);
3125                 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3126         }
3127
3128         ret = ldb_msg_add_string(msg, "objectClass", "secret");
3129         if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3130
3131         secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3132         NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3133
3134         /* create the secret */
3135         ret = ldb_add(secret_state->sam_ldb, msg);
3136         if (ret != LDB_SUCCESS) {
3137                 DEBUG(0,("Failed to create secret record %s: %s\n",
3138                          ldb_dn_get_linearized(msg->dn),
3139                          ldb_errstring(secret_state->sam_ldb)));
3140                 return NT_STATUS_ACCESS_DENIED;
3141         }
3142
3143         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3144         NT_STATUS_HAVE_NO_MEMORY(handle);
3145
3146         handle->data = talloc_steal(handle, secret_state);
3147
3148         secret_state->access_mask = r->in.access_mask;
3149         secret_state->policy = talloc_reference(secret_state, policy_state);
3150         NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3151
3152         *r->out.sec_handle = handle->wire_handle;
3153
3154         return NT_STATUS_OK;
3155 }
3156
3157
3158 /*
3159   lsa_OpenSecret
3160 */
3161 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3162                                struct lsa_OpenSecret *r)
3163 {
3164         struct dcesrv_handle *policy_handle;
3165
3166         struct lsa_policy_state *policy_state;
3167         struct lsa_secret_state *secret_state;
3168         struct dcesrv_handle *handle;
3169         struct ldb_message **msgs;
3170         const char *attrs[] = {
3171                 NULL
3172         };
3173
3174         const char *name;
3175
3176         int ret;
3177
3178         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3179         ZERO_STRUCTP(r->out.sec_handle);
3180         policy_state = policy_handle->data;
3181
3182         if (!r->in.name.string) {
3183                 return NT_STATUS_INVALID_PARAMETER;
3184         }
3185
3186         switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3187         {
3188         case SECURITY_SYSTEM:
3189         case SECURITY_ADMINISTRATOR:
3190                 break;
3191         default:
3192                 /* Users and annonymous are not allowed to access secrets */
3193                 return NT_STATUS_ACCESS_DENIED;
3194         }
3195
3196         secret_state = talloc(mem_ctx, struct lsa_secret_state);
3197         if (!secret_state) {
3198                 return NT_STATUS_NO_MEMORY;
3199         }
3200         secret_state->policy = policy_state;
3201
3202         if (strncmp("G$", r->in.name.string, 2) == 0) {
3203                 name = &r->in.name.string[2];
3204                 /* 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) */
3205                 secret_state->sam_ldb = talloc_reference(secret_state,
3206                                                          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));
3207                 secret_state->global = true;
3208
3209                 if (strlen(name) < 1) {
3210                         return NT_STATUS_INVALID_PARAMETER;
3211                 }
3212
3213                 /* search for the secret record */
3214                 ret = gendb_search(secret_state->sam_ldb,
3215                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
3216                                    "(&(cn=%s Secret)(objectclass=secret))",
3217                                    ldb_binary_encode_string(mem_ctx, name));
3218                 if (ret == 0) {
3219                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3220                 }
3221
3222                 if (ret != 1) {
3223                         DEBUG(0,("Found %d records matching DN %s\n", ret,
3224                                  ldb_dn_get_linearized(policy_state->system_dn)));
3225                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3226                 }
3227         } else {
3228                 secret_state->global = false;
3229                 secret_state->sam_ldb = talloc_reference(secret_state,
3230                                                          secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3231
3232                 name = r->in.name.string;
3233                 if (strlen(name) < 1) {
3234                         return NT_STATUS_INVALID_PARAMETER;
3235                 }
3236
3237                 /* search for the secret record */
3238                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3239                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3240                                    &msgs, attrs,
3241                                    "(&(cn=%s)(objectclass=secret))",
3242                                    ldb_binary_encode_string(mem_ctx, name));
3243                 if (ret == 0) {
3244                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3245                 }
3246
3247                 if (ret != 1) {
3248                         DEBUG(0,("Found %d records matching CN=%s\n",
3249                                  ret, ldb_binary_encode_string(mem_ctx, name)));
3250                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3251                 }
3252         }
3253
3254         secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3255
3256         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3257         if (!handle) {
3258                 return NT_STATUS_NO_MEMORY;
3259         }
3260
3261         handle->data = talloc_steal(handle, secret_state);
3262
3263         secret_state->access_mask = r->in.access_mask;
3264         secret_state->policy = talloc_reference(secret_state, policy_state);
3265
3266         *r->out.sec_handle = handle->wire_handle;
3267
3268         return NT_STATUS_OK;
3269 }
3270
3271
3272 /*
3273   lsa_SetSecret
3274 */
3275 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3276                               struct lsa_SetSecret *r)
3277 {
3278
3279         struct dcesrv_handle *h;
3280         struct lsa_secret_state *secret_state;
3281         struct ldb_message *msg;
3282         DATA_BLOB session_key;
3283         DATA_BLOB crypt_secret, secret;
3284         struct ldb_val val;
3285         int ret;
3286         NTSTATUS status = NT_STATUS_OK;
3287
3288         struct timeval now = timeval_current();
3289         NTTIME nt_now = timeval_to_nttime(&now);
3290
3291         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3292
3293         secret_state = h->data;
3294
3295         msg = ldb_msg_new(mem_ctx);
3296         if (msg == NULL) {
3297                 return NT_STATUS_NO_MEMORY;
3298         }
3299
3300         msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3301         if (!msg->dn) {
3302                 return NT_STATUS_NO_MEMORY;
3303         }
3304         status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3305         if (!NT_STATUS_IS_OK(status)) {
3306                 return status;
3307         }
3308
3309         if (r->in.old_val) {
3310                 /* Decrypt */
3311                 crypt_secret.data = r->in.old_val->data;
3312                 crypt_secret.length = r->in.old_val->size;
3313
3314                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3315                 if (!NT_STATUS_IS_OK(status)) {
3316                         return status;
3317                 }
3318
3319                 val.data = secret.data;
3320                 val.length = secret.length;
3321
3322                 /* set value */
3323                 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3324                         return NT_STATUS_NO_MEMORY;
3325                 }
3326
3327                 /* set old value mtime */
3328                 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3329                                          mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3330                         return NT_STATUS_NO_MEMORY;
3331                 }
3332
3333         } else {
3334                 /* If the old value is not set, then migrate the
3335                  * current value to the old value */
3336                 const struct ldb_val *old_val;
3337                 NTTIME last_set_time;
3338                 struct ldb_message **res;
3339                 const char *attrs[] = {
3340                         "currentValue",
3341                         "lastSetTime",
3342                         NULL
3343                 };
3344
3345                 /* search for the secret record */
3346                 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3347                                       secret_state->secret_dn, &res, attrs);
3348                 if (ret == 0) {
3349                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3350                 }
3351
3352                 if (ret != 1) {
3353                         DEBUG(0,("Found %d records matching dn=%s\n", ret,
3354                                  ldb_dn_get_linearized(secret_state->secret_dn)));
3355                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3356                 }
3357
3358                 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3359                 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3360
3361                 if (old_val) {
3362                         /* set old value */
3363                         if (ldb_msg_add_value(msg, "priorValue",
3364                                               old_val, NULL) != LDB_SUCCESS) {
3365                                 return NT_STATUS_NO_MEMORY;
3366                         }
3367                 } else {
3368                         if (samdb_msg_add_delete(secret_state->sam_ldb,
3369                                                  mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3370                                 return NT_STATUS_NO_MEMORY;
3371                         }
3372                 }
3373
3374                 /* set old value mtime */
3375                 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3376                         if (samdb_msg_add_uint64(secret_state->sam_ldb,
3377                                                  mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3378                                 return NT_STATUS_NO_MEMORY;
3379                         }
3380                 } else {
3381                         if (samdb_msg_add_uint64(secret_state->sam_ldb,
3382                                                  mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3383                                 return NT_STATUS_NO_MEMORY;
3384                         }
3385                 }
3386         }
3387
3388         if (r->in.new_val) {
3389                 /* Decrypt */
3390                 crypt_secret.data = r->in.new_val->data;
3391                 crypt_secret.length = r->in.new_val->size;
3392
3393                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3394                 if (!NT_STATUS_IS_OK(status)) {
3395                         return status;
3396                 }
3397
3398                 val.data = secret.data;
3399                 val.length = secret.length;
3400
3401                 /* set value */
3402                 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3403                         return NT_STATUS_NO_MEMORY;
3404                 }