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