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