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