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