lsasrv: Fix CID 241331 Self assignment
[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         bool ok;
1066         char *dns_encoded = NULL;
1067         char *netbios_encoded = NULL;
1068         char *sid_encoded = NULL;
1069
1070         DCESRV_PULL_HANDLE(policy_handle, r->in.policy_handle, LSA_HANDLE_POLICY);
1071         ZERO_STRUCTP(r->out.trustdom_handle);
1072
1073         policy_state = policy_handle->data;
1074         sam_ldb = policy_state->sam_ldb;
1075
1076         netbios_name = r->in.info->netbios_name.string;
1077         if (!netbios_name) {
1078                 return NT_STATUS_INVALID_PARAMETER;
1079         }
1080
1081         dns_name = r->in.info->domain_name.string;
1082         if (dns_name == NULL) {
1083                 return NT_STATUS_INVALID_PARAMETER;
1084         }
1085
1086         if (r->in.info->sid == NULL) {
1087                 return NT_STATUS_INVALID_SID;
1088         }
1089
1090         /*
1091          * We expect S-1-5-21-A-B-C, but we don't
1092          * allow S-1-5-21-0-0-0 as this is used
1093          * for claims and compound identities.
1094          */
1095         ok = dom_sid_is_valid_account_domain(r->in.info->sid);
1096         if (!ok) {
1097                 return NT_STATUS_INVALID_PARAMETER;
1098         }
1099
1100         dns_encoded = ldb_binary_encode_string(mem_ctx, dns_name);
1101         if (dns_encoded == NULL) {
1102                 return NT_STATUS_NO_MEMORY;
1103         }
1104         netbios_encoded = ldb_binary_encode_string(mem_ctx, netbios_name);
1105         if (netbios_encoded == NULL) {
1106                 return NT_STATUS_NO_MEMORY;
1107         }
1108         sid_encoded = ldap_encode_ndr_dom_sid(mem_ctx, r->in.info->sid);
1109         if (sid_encoded == NULL) {
1110                 return NT_STATUS_NO_MEMORY;
1111         }
1112
1113         trusted_domain_state = talloc_zero(mem_ctx, struct lsa_trusted_domain_state);
1114         if (!trusted_domain_state) {
1115                 return NT_STATUS_NO_MEMORY;
1116         }
1117         trusted_domain_state->policy = policy_state;
1118
1119         if (strcasecmp(netbios_name, "BUILTIN") == 0
1120             || (strcasecmp(dns_name, "BUILTIN") == 0)
1121             || (dom_sid_in_domain(policy_state->builtin_sid, r->in.info->sid))) {
1122                 return NT_STATUS_INVALID_PARAMETER;
1123         }
1124
1125         if (strcasecmp(netbios_name, policy_state->domain_name) == 0
1126             || strcasecmp(netbios_name, policy_state->domain_dns) == 0
1127             || strcasecmp(dns_name, policy_state->domain_dns) == 0
1128             || strcasecmp(dns_name, policy_state->domain_name) == 0
1129             || (dom_sid_equal(policy_state->domain_sid, r->in.info->sid))) {
1130                 return NT_STATUS_CURRENT_DOMAIN_NOT_ALLOWED;
1131         }
1132
1133         /* While this is a REF pointer, some of the functions that wrap this don't provide this */
1134         if (op == NDR_LSA_CREATETRUSTEDDOMAIN) {
1135                 /* No secrets are created at this time, for this function */
1136                 auth_struct.outgoing.count = 0;
1137                 auth_struct.incoming.count = 0;
1138         } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX2) {
1139                 auth_blob = data_blob_const(r->in.auth_info_internal->auth_blob.data,
1140                                             r->in.auth_info_internal->auth_blob.size);
1141                 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1142                                                    &auth_blob, &auth_struct);
1143                 if (!NT_STATUS_IS_OK(nt_status)) {
1144                         return nt_status;
1145                 }
1146         } else if (op == NDR_LSA_CREATETRUSTEDDOMAINEX) {
1147
1148                 if (unencrypted_auth_info->incoming_count > 1) {
1149                         return NT_STATUS_INVALID_PARAMETER;
1150                 }
1151
1152                 /* more investigation required here, do not create secrets for
1153                  * now */
1154                 auth_struct.outgoing.count = 0;
1155                 auth_struct.incoming.count = 0;
1156         } else {
1157                 return NT_STATUS_INVALID_PARAMETER;
1158         }
1159
1160         if (auth_struct.incoming.count) {
1161                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1162                                                      &auth_struct.incoming,
1163                                                      &trustAuthIncoming);
1164                 if (!NT_STATUS_IS_OK(nt_status)) {
1165                         return nt_status;
1166                 }
1167         } else {
1168                 trustAuthIncoming = data_blob(NULL, 0);
1169         }
1170
1171         if (auth_struct.outgoing.count) {
1172                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1173                                                      &auth_struct.outgoing,
1174                                                      &trustAuthOutgoing);
1175                 if (!NT_STATUS_IS_OK(nt_status)) {
1176                         return nt_status;
1177                 }
1178         } else {
1179                 trustAuthOutgoing = data_blob(NULL, 0);
1180         }
1181
1182         ret = ldb_transaction_start(sam_ldb);
1183         if (ret != LDB_SUCCESS) {
1184                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1185         }
1186
1187         /* search for the trusted_domain record */
1188         ret = gendb_search(sam_ldb,
1189                            mem_ctx, policy_state->system_dn, &msgs, attrs,
1190                            "(&(objectClass=trustedDomain)(|"
1191                              "(flatname=%s)(trustPartner=%s)"
1192                              "(flatname=%s)(trustPartner=%s)"
1193                              "(securityIdentifier=%s)))",
1194                            dns_encoded, dns_encoded,
1195                            netbios_encoded, netbios_encoded,
1196                            sid_encoded);
1197         if (ret > 0) {
1198                 ldb_transaction_cancel(sam_ldb);
1199                 return NT_STATUS_OBJECT_NAME_COLLISION;
1200         }
1201         if (ret < 0) {
1202                 ldb_transaction_cancel(sam_ldb);
1203                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1204         }
1205
1206         msg = ldb_msg_new(mem_ctx);
1207         if (msg == NULL) {
1208                 return NT_STATUS_NO_MEMORY;
1209         }
1210
1211         msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
1212         if ( ! ldb_dn_add_child_fmt(msg->dn, "cn=%s", dns_name)) {
1213                         ldb_transaction_cancel(sam_ldb);
1214                 return NT_STATUS_NO_MEMORY;
1215         }
1216
1217         ret = ldb_msg_add_string(msg, "objectClass", "trustedDomain");
1218         if (ret != LDB_SUCCESS) {
1219                 ldb_transaction_cancel(sam_ldb);
1220                 return NT_STATUS_NO_MEMORY;;
1221         }
1222
1223         ret = ldb_msg_add_string(msg, "flatname", netbios_name);
1224         if (ret != LDB_SUCCESS) {
1225                 ldb_transaction_cancel(sam_ldb);
1226                 return NT_STATUS_NO_MEMORY;
1227         }
1228
1229         ret = ldb_msg_add_string(msg, "trustPartner", dns_name);
1230         if (ret != LDB_SUCCESS) {
1231                 ldb_transaction_cancel(sam_ldb);
1232                 return NT_STATUS_NO_MEMORY;;
1233         }
1234
1235         ret = samdb_msg_add_dom_sid(sam_ldb, mem_ctx, msg, "securityIdentifier",
1236                                     r->in.info->sid);
1237         if (ret != LDB_SUCCESS) {
1238                 ldb_transaction_cancel(sam_ldb);
1239                 return NT_STATUS_NO_MEMORY;;
1240         }
1241
1242         ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustType", r->in.info->trust_type);
1243         if (ret != LDB_SUCCESS) {
1244                 ldb_transaction_cancel(sam_ldb);
1245                 return NT_STATUS_NO_MEMORY;;
1246         }
1247
1248         ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustAttributes", r->in.info->trust_attributes);
1249         if (ret != LDB_SUCCESS) {
1250                 ldb_transaction_cancel(sam_ldb);
1251                 return NT_STATUS_NO_MEMORY;;
1252         }
1253
1254         ret = samdb_msg_add_int(sam_ldb, mem_ctx, msg, "trustDirection", r->in.info->trust_direction);
1255         if (ret != LDB_SUCCESS) {
1256                 ldb_transaction_cancel(sam_ldb);
1257                 return NT_STATUS_NO_MEMORY;;
1258         }
1259
1260         if (trustAuthIncoming.data) {
1261                 ret = ldb_msg_add_value(msg, "trustAuthIncoming", &trustAuthIncoming, NULL);
1262                 if (ret != LDB_SUCCESS) {
1263                         ldb_transaction_cancel(sam_ldb);
1264                         return NT_STATUS_NO_MEMORY;
1265                 }
1266         }
1267         if (trustAuthOutgoing.data) {
1268                 ret = ldb_msg_add_value(msg, "trustAuthOutgoing", &trustAuthOutgoing, NULL);
1269                 if (ret != LDB_SUCCESS) {
1270                         ldb_transaction_cancel(sam_ldb);
1271                         return NT_STATUS_NO_MEMORY;
1272                 }
1273         }
1274
1275         trusted_domain_state->trusted_domain_dn = talloc_reference(trusted_domain_state, msg->dn);
1276
1277         /* create the trusted_domain */
1278         ret = ldb_add(sam_ldb, msg);
1279         switch (ret) {
1280         case  LDB_SUCCESS:
1281                 break;
1282         case  LDB_ERR_ENTRY_ALREADY_EXISTS:
1283                 ldb_transaction_cancel(sam_ldb);
1284                 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1285                          ldb_dn_get_linearized(msg->dn),
1286                          ldb_errstring(sam_ldb)));
1287                 return NT_STATUS_DOMAIN_EXISTS;
1288         case  LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1289                 ldb_transaction_cancel(sam_ldb);
1290                 DEBUG(0,("Failed to create trusted domain record %s: %s\n",
1291                          ldb_dn_get_linearized(msg->dn),
1292                          ldb_errstring(sam_ldb)));
1293                 return NT_STATUS_ACCESS_DENIED;
1294         default:
1295                 ldb_transaction_cancel(sam_ldb);
1296                 DEBUG(0,("Failed to create user record %s: %s\n",
1297                          ldb_dn_get_linearized(msg->dn),
1298                          ldb_errstring(sam_ldb)));
1299                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1300         }
1301
1302         if (r->in.info->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
1303                 struct ldb_dn *user_dn;
1304                 /* Inbound trusts must also create a cn=users object to match */
1305                 nt_status = add_trust_user(mem_ctx, sam_ldb,
1306                                            policy_state->domain_dn,
1307                                            netbios_name,
1308                                            &auth_struct.incoming,
1309                                            &user_dn);
1310                 if (!NT_STATUS_IS_OK(nt_status)) {
1311                         ldb_transaction_cancel(sam_ldb);
1312                         return nt_status;
1313                 }
1314
1315                 /* save the trust user dn */
1316                 trusted_domain_state->trusted_domain_user_dn
1317                         = talloc_steal(trusted_domain_state, user_dn);
1318         }
1319
1320         ret = ldb_transaction_commit(sam_ldb);
1321         if (ret != LDB_SUCCESS) {
1322                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1323         }
1324
1325         /*
1326          * Notify winbindd that we have a new trust
1327          */
1328         status = irpc_servers_byname(dce_call->msg_ctx,
1329                                      mem_ctx,
1330                                      "winbind_server",
1331                                      &num_server_ids, &server_ids);
1332         if (NT_STATUS_IS_OK(status) && num_server_ids >= 1) {
1333                 imessaging_send(dce_call->msg_ctx, server_ids[0],
1334                                 MSG_WINBIND_RELOAD_TRUSTED_DOMAINS, NULL);
1335         }
1336         TALLOC_FREE(server_ids);
1337
1338         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1339         if (!handle) {
1340                 return NT_STATUS_NO_MEMORY;
1341         }
1342
1343         handle->data = talloc_steal(handle, trusted_domain_state);
1344
1345         trusted_domain_state->access_mask = r->in.access_mask;
1346         trusted_domain_state->policy = talloc_reference(trusted_domain_state, policy_state);
1347
1348         *r->out.trustdom_handle = handle->wire_handle;
1349
1350         return NT_STATUS_OK;
1351 }
1352
1353 /*
1354   lsa_CreateTrustedDomainEx2
1355 */
1356 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx2(struct dcesrv_call_state *dce_call,
1357                                            TALLOC_CTX *mem_ctx,
1358                                            struct lsa_CreateTrustedDomainEx2 *r)
1359 {
1360         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, r, NDR_LSA_CREATETRUSTEDDOMAINEX2, NULL);
1361 }
1362 /*
1363   lsa_CreateTrustedDomainEx
1364 */
1365 static NTSTATUS dcesrv_lsa_CreateTrustedDomainEx(struct dcesrv_call_state *dce_call,
1366                                           TALLOC_CTX *mem_ctx,
1367                                           struct lsa_CreateTrustedDomainEx *r)
1368 {
1369         struct lsa_CreateTrustedDomainEx2 r2;
1370
1371         r2.in.policy_handle = r->in.policy_handle;
1372         r2.in.info = r->in.info;
1373         r2.out.trustdom_handle = r->out.trustdom_handle;
1374         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAINEX, r->in.auth_info);
1375 }
1376
1377 /*
1378   lsa_CreateTrustedDomain
1379 */
1380 static NTSTATUS dcesrv_lsa_CreateTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1381                                         struct lsa_CreateTrustedDomain *r)
1382 {
1383         struct lsa_CreateTrustedDomainEx2 r2;
1384
1385         r2.in.policy_handle = r->in.policy_handle;
1386         r2.in.info = talloc(mem_ctx, struct lsa_TrustDomainInfoInfoEx);
1387         if (!r2.in.info) {
1388                 return NT_STATUS_NO_MEMORY;
1389         }
1390
1391         r2.in.info->domain_name = r->in.info->name;
1392         r2.in.info->netbios_name = r->in.info->name;
1393         r2.in.info->sid = r->in.info->sid;
1394         r2.in.info->trust_direction = LSA_TRUST_DIRECTION_OUTBOUND;
1395         r2.in.info->trust_type = LSA_TRUST_TYPE_DOWNLEVEL;
1396         r2.in.info->trust_attributes = 0;
1397
1398         r2.in.access_mask = r->in.access_mask;
1399         r2.out.trustdom_handle = r->out.trustdom_handle;
1400
1401         return dcesrv_lsa_CreateTrustedDomain_base(dce_call, mem_ctx, &r2, NDR_LSA_CREATETRUSTEDDOMAIN, NULL);
1402 }
1403
1404 static NTSTATUS dcesrv_lsa_OpenTrustedDomain_common(
1405                                         struct dcesrv_call_state *dce_call,
1406                                         TALLOC_CTX *tmp_mem,
1407                                         struct lsa_policy_state *policy_state,
1408                                         const char *filter,
1409                                         uint32_t access_mask,
1410                                         struct dcesrv_handle **_handle)
1411 {
1412         struct lsa_trusted_domain_state *trusted_domain_state;
1413         struct dcesrv_handle *handle;
1414         struct ldb_message **msgs;
1415         const char *attrs[] = {
1416                 "trustDirection",
1417                 "flatname",
1418                 NULL
1419         };
1420         uint32_t direction;
1421         int ret;
1422
1423         /* TODO: perform access checks */
1424
1425         /* search for the trusted_domain record */
1426         ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1427                            policy_state->system_dn,
1428                            &msgs, attrs, "%s", filter);
1429         if (ret == 0) {
1430                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1431         }
1432
1433         if (ret != 1) {
1434                 DEBUG(0,("Found %d records matching %s under %s\n", ret,
1435                          filter,
1436                          ldb_dn_get_linearized(policy_state->system_dn)));
1437                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1438         }
1439
1440         trusted_domain_state = talloc_zero(tmp_mem,
1441                                            struct lsa_trusted_domain_state);
1442         if (!trusted_domain_state) {
1443                 return NT_STATUS_NO_MEMORY;
1444         }
1445         trusted_domain_state->policy = policy_state;
1446
1447         trusted_domain_state->trusted_domain_dn =
1448                 talloc_steal(trusted_domain_state, msgs[0]->dn);
1449
1450         direction = ldb_msg_find_attr_as_int(msgs[0], "trustDirection", 0);
1451         if (direction & LSA_TRUST_DIRECTION_INBOUND) {
1452                 const char *flatname = ldb_msg_find_attr_as_string(msgs[0],
1453                                                         "flatname", NULL);
1454
1455                 /* search for the trusted_domain account */
1456                 ret = gendb_search(policy_state->sam_ldb, tmp_mem,
1457                                    policy_state->domain_dn,
1458                                    &msgs, attrs,
1459                                    "(&(samaccountname=%s$)(objectclass=user)"
1460                                    "(userAccountControl:%s:=%u))",
1461                                    flatname,
1462                                    LDB_OID_COMPARATOR_AND,
1463                                    UF_INTERDOMAIN_TRUST_ACCOUNT);
1464                 if (ret == 1) {
1465                         trusted_domain_state->trusted_domain_user_dn =
1466                                 talloc_steal(trusted_domain_state, msgs[0]->dn);
1467                 }
1468         }
1469
1470         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_TRUSTED_DOMAIN);
1471         if (!handle) {
1472                 return NT_STATUS_NO_MEMORY;
1473         }
1474
1475         handle->data = talloc_steal(handle, trusted_domain_state);
1476
1477         trusted_domain_state->access_mask = access_mask;
1478         trusted_domain_state->policy = talloc_reference(trusted_domain_state,
1479                                                         policy_state);
1480
1481         *_handle = handle;
1482
1483         return NT_STATUS_OK;
1484 }
1485
1486 /*
1487   lsa_OpenTrustedDomain
1488 */
1489 static NTSTATUS dcesrv_lsa_OpenTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1490                                       struct lsa_OpenTrustedDomain *r)
1491 {
1492         struct dcesrv_handle *policy_handle;
1493         struct lsa_policy_state *policy_state;
1494         struct dcesrv_handle *handle;
1495         const char *sid_string;
1496         char *filter;
1497         NTSTATUS status;
1498
1499         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1500         ZERO_STRUCTP(r->out.trustdom_handle);
1501         policy_state = policy_handle->data;
1502
1503         sid_string = dom_sid_string(mem_ctx, r->in.sid);
1504         if (!sid_string) {
1505                 return NT_STATUS_NO_MEMORY;
1506         }
1507
1508         filter = talloc_asprintf(mem_ctx,
1509                                  "(&(securityIdentifier=%s)"
1510                                  "(objectclass=trustedDomain))",
1511                                  sid_string);
1512         if (filter == NULL) {
1513                 return NT_STATUS_NO_MEMORY;
1514         }
1515
1516         status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1517                                                      policy_state,
1518                                                      filter,
1519                                                      r->in.access_mask,
1520                                                      &handle);
1521         if (!NT_STATUS_IS_OK(status)) {
1522                 return status;
1523         }
1524
1525         *r->out.trustdom_handle = handle->wire_handle;
1526
1527         return NT_STATUS_OK;
1528 }
1529
1530
1531 /*
1532   lsa_OpenTrustedDomainByName
1533 */
1534 static NTSTATUS dcesrv_lsa_OpenTrustedDomainByName(struct dcesrv_call_state *dce_call,
1535                                             TALLOC_CTX *mem_ctx,
1536                                             struct lsa_OpenTrustedDomainByName *r)
1537 {
1538         struct dcesrv_handle *policy_handle;
1539         struct lsa_policy_state *policy_state;
1540         struct dcesrv_handle *handle;
1541         char *td_name;
1542         char *filter;
1543         NTSTATUS status;
1544
1545         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
1546         ZERO_STRUCTP(r->out.trustdom_handle);
1547         policy_state = policy_handle->data;
1548
1549         if (!r->in.name.string) {
1550                 return NT_STATUS_INVALID_PARAMETER;
1551         }
1552
1553         /* search for the trusted_domain record */
1554         td_name = ldb_binary_encode_string(mem_ctx, r->in.name.string);
1555         if (td_name == NULL) {
1556                 return NT_STATUS_NO_MEMORY;
1557         }
1558
1559         filter = talloc_asprintf(mem_ctx,
1560                            "(&(|(flatname=%s)(cn=%s)(trustPartner=%s))"
1561                              "(objectclass=trustedDomain))",
1562                            td_name, td_name, td_name);
1563         if (filter == NULL) {
1564                 return NT_STATUS_NO_MEMORY;
1565         }
1566
1567         status = dcesrv_lsa_OpenTrustedDomain_common(dce_call, mem_ctx,
1568                                                      policy_state,
1569                                                      filter,
1570                                                      r->in.access_mask,
1571                                                      &handle);
1572         if (!NT_STATUS_IS_OK(status)) {
1573                 return status;
1574         }
1575
1576         *r->out.trustdom_handle = handle->wire_handle;
1577
1578         return NT_STATUS_OK;
1579 }
1580
1581
1582
1583 /*
1584   lsa_SetTrustedDomainInfo
1585 */
1586 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
1587                                          struct lsa_SetTrustedDomainInfo *r)
1588 {
1589         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
1590 }
1591
1592
1593
1594 /* parameters 4 to 6 are optional if the dn is a dn of a TDO object,
1595  * otherwise at least one must be provided */
1596 static NTSTATUS get_tdo(struct ldb_context *sam, TALLOC_CTX *mem_ctx,
1597                         struct ldb_dn *basedn, const char *dns_domain,
1598                         const char *netbios, struct dom_sid2 *sid,
1599                         struct ldb_message ***msgs)
1600 {
1601         const char *attrs[] = { "flatname", "trustPartner",
1602                                 "securityIdentifier", "trustDirection",
1603                                 "trustType", "trustAttributes",
1604                                 "trustPosixOffset",
1605                                 "msDs-supportedEncryptionTypes",
1606                                 "msDS-TrustForestTrustInfo",
1607                                 NULL
1608         };
1609         char *dns = NULL;
1610         char *nbn = NULL;
1611         char *sidstr = NULL;
1612         char *filter;
1613         int ret;
1614
1615
1616         if (dns_domain || netbios || sid) {
1617                 filter = talloc_strdup(mem_ctx,
1618                                    "(&(objectclass=trustedDomain)(|");
1619         } else {
1620                 filter = talloc_strdup(mem_ctx,
1621                                        "(objectclass=trustedDomain)");
1622         }
1623         if (!filter) {
1624                 return NT_STATUS_NO_MEMORY;
1625         }
1626
1627         if (dns_domain) {
1628                 dns = ldb_binary_encode_string(mem_ctx, dns_domain);
1629                 if (!dns) {
1630                         return NT_STATUS_NO_MEMORY;
1631                 }
1632                 filter = talloc_asprintf_append(filter,
1633                                                 "(trustPartner=%s)", dns);
1634                 if (!filter) {
1635                         return NT_STATUS_NO_MEMORY;
1636                 }
1637         }
1638         if (netbios) {
1639                 nbn = ldb_binary_encode_string(mem_ctx, netbios);
1640                 if (!nbn) {
1641                         return NT_STATUS_NO_MEMORY;
1642                 }
1643                 filter = talloc_asprintf_append(filter,
1644                                                 "(flatname=%s)", nbn);
1645                 if (!filter) {
1646                         return NT_STATUS_NO_MEMORY;
1647                 }
1648         }
1649         if (sid) {
1650                 sidstr = dom_sid_string(mem_ctx, sid);
1651                 if (!sidstr) {
1652                         return NT_STATUS_INVALID_PARAMETER;
1653                 }
1654                 filter = talloc_asprintf_append(filter,
1655                                                 "(securityIdentifier=%s)",
1656                                                 sidstr);
1657                 if (!filter) {
1658                         return NT_STATUS_NO_MEMORY;
1659                 }
1660         }
1661         if (dns_domain || netbios || sid) {
1662                 filter = talloc_asprintf_append(filter, "))");
1663                 if (!filter) {
1664                         return NT_STATUS_NO_MEMORY;
1665                 }
1666         }
1667
1668         ret = gendb_search(sam, mem_ctx, basedn, msgs, attrs, "%s", filter);
1669         if (ret == 0) {
1670                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
1671         }
1672
1673         if (ret != 1) {
1674                 return NT_STATUS_OBJECT_NAME_COLLISION;
1675         }
1676
1677         return NT_STATUS_OK;
1678 }
1679
1680 static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1681                                       struct ldb_context *sam_ldb,
1682                                       struct ldb_message *orig,
1683                                       struct ldb_message *dest,
1684                                       const char *attribute,
1685                                       uint32_t value,
1686                                       uint32_t *orig_value)
1687 {
1688         const struct ldb_val *orig_val;
1689         uint32_t orig_uint = 0;
1690         unsigned int flags = 0;
1691         int ret;
1692
1693         orig_val = ldb_msg_find_ldb_val(orig, attribute);
1694         if (!orig_val || !orig_val->data) {
1695                 /* add new attribute */
1696                 flags = LDB_FLAG_MOD_ADD;
1697
1698         } else {
1699                 errno = 0;
1700                 orig_uint = strtoul((const char *)orig_val->data, NULL, 0);
1701                 if (errno != 0 || orig_uint != value) {
1702                         /* replace also if can't get value */
1703                         flags = LDB_FLAG_MOD_REPLACE;
1704                 }
1705         }
1706
1707         if (flags == 0) {
1708                 /* stored value is identical, nothing to change */
1709                 goto done;
1710         }
1711
1712         ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1713         if (ret != LDB_SUCCESS) {
1714                 return NT_STATUS_NO_MEMORY;
1715         }
1716
1717         ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1718         if (ret != LDB_SUCCESS) {
1719                 return NT_STATUS_NO_MEMORY;
1720         }
1721
1722 done:
1723         if (orig_value) {
1724                 *orig_value = orig_uint;
1725         }
1726         return NT_STATUS_OK;
1727 }
1728
1729 static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1730                                   struct ldb_context *sam_ldb,
1731                                   struct ldb_dn *base_dn,
1732                                   bool delete_user,
1733                                   const char *netbios_name,
1734                                   struct trustAuthInOutBlob *in)
1735 {
1736         const char *attrs[] = { "userAccountControl", NULL };
1737         struct ldb_message **msgs;
1738         struct ldb_message *msg;
1739         uint32_t uac;
1740         uint32_t i;
1741         int ret;
1742
1743         ret = gendb_search(sam_ldb, mem_ctx,
1744                            base_dn, &msgs, attrs,
1745                            "samAccountName=%s$", netbios_name);
1746         if (ret > 1) {
1747                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
1748         }
1749
1750         if (ret == 0) {
1751                 if (delete_user) {
1752                         return NT_STATUS_OK;
1753                 }
1754
1755                 /* ok no existing user, add it from scratch */
1756                 return add_trust_user(mem_ctx, sam_ldb, base_dn,
1757                                       netbios_name, in, NULL);
1758         }
1759
1760         /* check user is what we are looking for */
1761         uac = ldb_msg_find_attr_as_uint(msgs[0],
1762                                         "userAccountControl", 0);
1763         if (!(uac & UF_INTERDOMAIN_TRUST_ACCOUNT)) {
1764                 return NT_STATUS_OBJECT_NAME_COLLISION;
1765         }
1766
1767         if (delete_user) {
1768                 ret = ldb_delete(sam_ldb, msgs[0]->dn);
1769                 switch (ret) {
1770                 case LDB_SUCCESS:
1771                         return NT_STATUS_OK;
1772                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1773                         return NT_STATUS_ACCESS_DENIED;
1774                 default:
1775                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1776                 }
1777         }
1778
1779         /* entry exists, just modify secret if any */
1780         if (in == NULL || in->count == 0) {
1781                 return NT_STATUS_OK;
1782         }
1783
1784         msg = ldb_msg_new(mem_ctx);
1785         if (!msg) {
1786                 return NT_STATUS_NO_MEMORY;
1787         }
1788         msg->dn = msgs[0]->dn;
1789
1790         for (i = 0; i < in->count; i++) {
1791                 const char *attribute;
1792                 struct ldb_val v;
1793                 switch (in->current.array[i].AuthType) {
1794                 case TRUST_AUTH_TYPE_NT4OWF:
1795                         attribute = "unicodePwd";
1796                         v.data = (uint8_t *)&in->current.array[i].AuthInfo.nt4owf.password;
1797                         v.length = 16;
1798                         break;
1799                 case TRUST_AUTH_TYPE_CLEAR:
1800                         attribute = "clearTextPassword";
1801                         v.data = in->current.array[i].AuthInfo.clear.password;
1802                         v.length = in->current.array[i].AuthInfo.clear.size;
1803                         break;
1804                 default:
1805                         continue;
1806                 }
1807
1808                 ret = ldb_msg_add_empty(msg, attribute,
1809                                         LDB_FLAG_MOD_REPLACE, NULL);
1810                 if (ret != LDB_SUCCESS) {
1811                         return NT_STATUS_NO_MEMORY;
1812                 }
1813
1814                 ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1815                 if (ret != LDB_SUCCESS) {
1816                         return NT_STATUS_NO_MEMORY;
1817                 }
1818         }
1819
1820         /* create the trusted_domain user account */
1821         ret = ldb_modify(sam_ldb, msg);
1822         if (ret != LDB_SUCCESS) {
1823                 DEBUG(0,("Failed to create user record %s: %s\n",
1824                          ldb_dn_get_linearized(msg->dn),
1825                          ldb_errstring(sam_ldb)));
1826
1827                 switch (ret) {
1828                 case LDB_ERR_ENTRY_ALREADY_EXISTS:
1829                         return NT_STATUS_DOMAIN_EXISTS;
1830                 case LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS:
1831                         return NT_STATUS_ACCESS_DENIED;
1832                 default:
1833                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
1834                 }
1835         }
1836
1837         return NT_STATUS_OK;
1838 }
1839
1840
1841 static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1842                                           struct lsa_policy_state *p_state,
1843                                           TALLOC_CTX *mem_ctx,
1844                                           struct ldb_message *dom_msg,
1845                                           enum lsa_TrustDomInfoEnum level,
1846                                           union lsa_TrustedDomainInfo *info)
1847 {
1848         uint32_t *posix_offset = NULL;
1849         struct lsa_TrustDomainInfoInfoEx *info_ex = NULL;
1850         struct lsa_TrustDomainInfoAuthInfo *auth_info = NULL;
1851         struct lsa_TrustDomainInfoAuthInfoInternal *auth_info_int = NULL;
1852         uint32_t *enc_types = NULL;
1853         DATA_BLOB trustAuthIncoming, trustAuthOutgoing, auth_blob;
1854         struct trustDomainPasswords auth_struct;
1855         struct trustAuthInOutBlob *current_passwords = NULL;
1856         NTSTATUS nt_status;
1857         struct ldb_message **msgs;
1858         struct ldb_message *msg;
1859         bool add_outgoing = false;
1860         bool add_incoming = false;
1861         bool del_outgoing = false;
1862         bool del_incoming = false;
1863         bool del_forest_info = false;
1864         bool in_transaction = false;
1865         int ret;
1866         bool am_rodc;
1867
1868         switch (level) {
1869         case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
1870                 posix_offset = &info->posix_offset.posix_offset;
1871                 break;
1872         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
1873                 info_ex = &info->info_ex;
1874                 break;
1875         case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO:
1876                 auth_info = &info->auth_info;
1877                 break;
1878         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
1879                 posix_offset = &info->full_info.posix_offset.posix_offset;
1880                 info_ex = &info->full_info.info_ex;
1881                 auth_info = &info->full_info.auth_info;
1882                 break;
1883         case LSA_TRUSTED_DOMAIN_INFO_AUTH_INFO_INTERNAL:
1884                 auth_info_int = &info->auth_info_internal;
1885                 break;
1886         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_INTERNAL:
1887                 posix_offset = &info->full_info_internal.posix_offset.posix_offset;
1888                 info_ex = &info->full_info_internal.info_ex;
1889                 auth_info_int = &info->full_info_internal.auth_info;
1890                 break;
1891         case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
1892                 enc_types = &info->enc_types.enc_types;
1893                 break;
1894         default:
1895                 return NT_STATUS_INVALID_PARAMETER;
1896         }
1897
1898         if (auth_info) {
1899                 nt_status = auth_info_2_auth_blob(mem_ctx, auth_info,
1900                                                   &trustAuthIncoming,
1901                                                   &trustAuthOutgoing);
1902                 if (!NT_STATUS_IS_OK(nt_status)) {
1903                         return nt_status;
1904                 }
1905                 if (trustAuthIncoming.data) {
1906                         /* This does the decode of some of this twice, but it is easier that way */
1907                         nt_status = auth_info_2_trustauth_inout(mem_ctx,
1908                                                                 auth_info->incoming_count,
1909                                                                 auth_info->incoming_current_auth_info,
1910                                                                 NULL,
1911                                                                 &current_passwords);
1912                         if (!NT_STATUS_IS_OK(nt_status)) {
1913                                 return nt_status;
1914                         }
1915                 }
1916         }
1917
1918         /* decode auth_info_int if set */
1919         if (auth_info_int) {
1920
1921                 /* now decrypt blob */
1922                 auth_blob = data_blob_const(auth_info_int->auth_blob.data,
1923                                             auth_info_int->auth_blob.size);
1924
1925                 nt_status = get_trustdom_auth_blob(dce_call, mem_ctx,
1926                                                    &auth_blob, &auth_struct);
1927                 if (!NT_STATUS_IS_OK(nt_status)) {
1928                         return nt_status;
1929                 }
1930         }
1931
1932         if (info_ex) {
1933                 /* verify data matches */
1934                 if (info_ex->trust_attributes &
1935                     LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
1936                         /* TODO: check what behavior level we have */
1937                        if (strcasecmp_m(p_state->domain_dns,
1938                                         p_state->forest_dns) != 0) {
1939                                 return NT_STATUS_INVALID_DOMAIN_STATE;
1940                         }
1941                 }
1942
1943                 ret = samdb_rodc(p_state->sam_ldb, &am_rodc);
1944                 if (ret == LDB_SUCCESS && am_rodc) {
1945                         return NT_STATUS_NO_SUCH_DOMAIN;
1946                 }
1947
1948                 /* verify only one object matches the dns/netbios/sid
1949                  * triplet and that this is the one we already have */
1950                 nt_status = get_tdo(p_state->sam_ldb, mem_ctx,
1951                                     p_state->system_dn,
1952                                     info_ex->domain_name.string,
1953                                     info_ex->netbios_name.string,
1954                                     info_ex->sid, &msgs);
1955                 if (!NT_STATUS_IS_OK(nt_status)) {
1956                         return nt_status;
1957                 }
1958                 if (ldb_dn_compare(dom_msg->dn, msgs[0]->dn) != 0) {
1959                         return NT_STATUS_OBJECT_NAME_COLLISION;
1960                 }
1961                 talloc_free(msgs);
1962         }
1963
1964         /* TODO: should we fetch previous values from the existing entry
1965          * and append them ? */
1966         if (auth_info_int && auth_struct.incoming.count) {
1967                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1968                                                      &auth_struct.incoming,
1969                                                      &trustAuthIncoming);
1970                 if (!NT_STATUS_IS_OK(nt_status)) {
1971                         return nt_status;
1972                 }
1973
1974                 current_passwords = &auth_struct.incoming;
1975
1976         } else {
1977                 trustAuthIncoming = data_blob(NULL, 0);
1978         }
1979
1980         if (auth_info_int && auth_struct.outgoing.count) {
1981                 nt_status = get_trustauth_inout_blob(dce_call, mem_ctx,
1982                                                      &auth_struct.outgoing,
1983                                                      &trustAuthOutgoing);
1984                 if (!NT_STATUS_IS_OK(nt_status)) {
1985                         return nt_status;
1986                 }
1987         } else {
1988                 trustAuthOutgoing = data_blob(NULL, 0);
1989         }
1990
1991         msg = ldb_msg_new(mem_ctx);
1992         if (msg == NULL) {
1993                 return NT_STATUS_NO_MEMORY;
1994         }
1995         msg->dn = dom_msg->dn;
1996
1997         if (posix_offset) {
1998                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
1999                                                   dom_msg, msg,
2000                                                   "trustPosixOffset",
2001                                                   *posix_offset, NULL);
2002                 if (!NT_STATUS_IS_OK(nt_status)) {
2003                         return nt_status;
2004                 }
2005         }
2006
2007         if (info_ex) {
2008                 uint32_t origattrs;
2009                 uint32_t changed_attrs;
2010                 uint32_t origdir;
2011                 int origtype;
2012
2013                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2014                                                   dom_msg, msg,
2015                                                   "trustDirection",
2016                                                   info_ex->trust_direction,
2017                                                   &origdir);
2018                 if (!NT_STATUS_IS_OK(nt_status)) {
2019                         return nt_status;
2020                 }
2021
2022                 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND) {
2023                         if (auth_info != NULL && trustAuthIncoming.length > 0) {
2024                                 add_incoming = true;
2025                         }
2026                 }
2027                 if (info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND) {
2028                         if (auth_info != NULL && trustAuthOutgoing.length > 0) {
2029                                 add_outgoing = true;
2030                         }
2031                 }
2032
2033                 if ((origdir & LSA_TRUST_DIRECTION_INBOUND) &&
2034                     !(info_ex->trust_direction & LSA_TRUST_DIRECTION_INBOUND)) {
2035                         del_incoming = true;
2036                 }
2037                 if ((origdir & LSA_TRUST_DIRECTION_OUTBOUND) &&
2038                     !(info_ex->trust_direction & LSA_TRUST_DIRECTION_OUTBOUND)) {
2039                         del_outgoing = true;
2040                 }
2041
2042                 origtype = ldb_msg_find_attr_as_int(dom_msg, "trustType", -1);
2043                 if (origtype == -1 || origtype != info_ex->trust_type) {
2044                         DEBUG(1, ("Attempted to change trust type! "
2045                                   "Operation not handled\n"));
2046                         return NT_STATUS_INVALID_PARAMETER;
2047                 }
2048
2049                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2050                                                   dom_msg, msg,
2051                                                   "trustAttributes",
2052                                                   info_ex->trust_attributes,
2053                                                   &origattrs);
2054                 if (!NT_STATUS_IS_OK(nt_status)) {
2055                         return nt_status;
2056                 }
2057                 /* TODO: check forestFunctionality from ldb opaque */
2058                 /* TODO: check what is set makes sense */
2059
2060                 changed_attrs = origattrs ^ info_ex->trust_attributes;
2061                 if (changed_attrs & ~LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE) {
2062                         /*
2063                          * For now we only allow
2064                          * LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE to be changed.
2065                          *
2066                          * TODO: we may need to support more attribute changes
2067                          */
2068                         DEBUG(1, ("Attempted to change trust attributes "
2069                                   "(0x%08x != 0x%08x)! "
2070                                   "Operation not handled yet...\n",
2071                                   (unsigned)origattrs,
2072                                   (unsigned)info_ex->trust_attributes));
2073                         return NT_STATUS_INVALID_PARAMETER;
2074                 }
2075
2076                 if (!(info_ex->trust_attributes &
2077                       LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE))
2078                 {
2079                         struct ldb_message_element *orig_forest_el = NULL;
2080
2081                         orig_forest_el = ldb_msg_find_element(dom_msg,
2082                                                 "msDS-TrustForestTrustInfo");
2083                         if (orig_forest_el != NULL) {
2084                                 del_forest_info = true;
2085                         }
2086                 }
2087         }
2088
2089         if (enc_types) {
2090                 nt_status = update_uint32_t_value(mem_ctx, p_state->sam_ldb,
2091                                                   dom_msg, msg,
2092                                                   "msDS-SupportedEncryptionTypes",
2093                                                   *enc_types, NULL);
2094                 if (!NT_STATUS_IS_OK(nt_status)) {
2095                         return nt_status;
2096                 }
2097         }
2098
2099         if (add_incoming || del_incoming) {
2100                 ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
2101                                         LDB_FLAG_MOD_REPLACE, NULL);
2102                 if (ret != LDB_SUCCESS) {
2103                         return NT_STATUS_NO_MEMORY;
2104                 }
2105                 if (add_incoming) {
2106                         ret = ldb_msg_add_value(msg, "trustAuthIncoming",
2107                                                 &trustAuthIncoming, NULL);
2108                         if (ret != LDB_SUCCESS) {
2109                                 return NT_STATUS_NO_MEMORY;
2110                         }
2111                 }
2112         }
2113         if (add_outgoing || del_outgoing) {
2114                 ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
2115                                         LDB_FLAG_MOD_REPLACE, NULL);
2116                 if (ret != LDB_SUCCESS) {
2117                         return NT_STATUS_NO_MEMORY;
2118                 }
2119                 if (add_outgoing) {
2120                         ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
2121                                                 &trustAuthOutgoing, NULL);
2122                         if (ret != LDB_SUCCESS) {
2123                                 return NT_STATUS_NO_MEMORY;
2124                         }
2125                 }
2126         }
2127         if (del_forest_info) {
2128                 ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
2129                                         LDB_FLAG_MOD_REPLACE, NULL);
2130                 if (ret != LDB_SUCCESS) {
2131                         return NT_STATUS_NO_MEMORY;
2132                 }
2133         }
2134
2135         /* start transaction */
2136         ret = ldb_transaction_start(p_state->sam_ldb);
2137         if (ret != LDB_SUCCESS) {
2138                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2139         }
2140         in_transaction = true;
2141
2142         if (msg->num_elements) {
2143                 ret = ldb_modify(p_state->sam_ldb, msg);
2144                 if (ret != LDB_SUCCESS) {
2145                         DEBUG(1,("Failed to modify trusted domain record %s: %s\n",
2146                                  ldb_dn_get_linearized(msg->dn),
2147                                  ldb_errstring(p_state->sam_ldb)));
2148                         nt_status = dsdb_ldb_err_to_ntstatus(ret);
2149                         goto done;
2150                 }
2151         }
2152
2153         if (add_incoming || del_incoming) {
2154                 const char *netbios_name;
2155
2156                 netbios_name = ldb_msg_find_attr_as_string(dom_msg,
2157                                                            "flatname", NULL);
2158                 if (!netbios_name) {
2159                         nt_status = NT_STATUS_INVALID_DOMAIN_STATE;
2160                         goto done;
2161                 }
2162
2163                 /* We use trustAuthIncoming.data to incidate that auth_struct.incoming is valid */
2164                 nt_status = update_trust_user(mem_ctx,
2165                                               p_state->sam_ldb,
2166                                               p_state->domain_dn,
2167                                               del_incoming,
2168                                               netbios_name,
2169                                               current_passwords);
2170                 if (!NT_STATUS_IS_OK(nt_status)) {
2171                         goto done;
2172                 }
2173         }
2174
2175         /* ok, all fine, commit transaction and return */
2176         ret = ldb_transaction_commit(p_state->sam_ldb);
2177         if (ret != LDB_SUCCESS) {
2178                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2179         }
2180         in_transaction = false;
2181
2182         nt_status = NT_STATUS_OK;
2183
2184 done:
2185         if (in_transaction) {
2186                 ldb_transaction_cancel(p_state->sam_ldb);
2187         }
2188         return nt_status;
2189 }
2190
2191 /*
2192   lsa_SetInfomrationTrustedDomain
2193 */
2194 static NTSTATUS dcesrv_lsa_SetInformationTrustedDomain(
2195                                 struct dcesrv_call_state *dce_call,
2196                                 TALLOC_CTX *mem_ctx,
2197                                 struct lsa_SetInformationTrustedDomain *r)
2198 {
2199         struct dcesrv_handle *h;
2200         struct lsa_trusted_domain_state *td_state;
2201         struct ldb_message **msgs;
2202         NTSTATUS nt_status;
2203
2204         DCESRV_PULL_HANDLE(h, r->in.trustdom_handle,
2205                            LSA_HANDLE_TRUSTED_DOMAIN);
2206
2207         td_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2208
2209         /* get the trusted domain object */
2210         nt_status = get_tdo(td_state->policy->sam_ldb, mem_ctx,
2211                             td_state->trusted_domain_dn,
2212                             NULL, NULL, NULL, &msgs);
2213         if (!NT_STATUS_IS_OK(nt_status)) {
2214                 if (NT_STATUS_EQUAL(nt_status,
2215                                     NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2216                         return nt_status;
2217                 }
2218                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2219         }
2220
2221         return setInfoTrustedDomain_base(dce_call, td_state->policy, mem_ctx,
2222                                          msgs[0], r->in.level, r->in.info);
2223 }
2224
2225
2226 /*
2227   lsa_DeleteTrustedDomain
2228 */
2229 static NTSTATUS dcesrv_lsa_DeleteTrustedDomain(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2230                                       struct lsa_DeleteTrustedDomain *r)
2231 {
2232         NTSTATUS status;
2233         struct lsa_OpenTrustedDomain opn = {{0},{0}};
2234         struct lsa_DeleteObject del;
2235         struct dcesrv_handle *h;
2236
2237         opn.in.handle = r->in.handle;
2238         opn.in.sid = r->in.dom_sid;
2239         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2240         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2241         if (!opn.out.trustdom_handle) {
2242                 return NT_STATUS_NO_MEMORY;
2243         }
2244         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2245         if (!NT_STATUS_IS_OK(status)) {
2246                 return status;
2247         }
2248
2249         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2250         talloc_steal(mem_ctx, h);
2251
2252         del.in.handle = opn.out.trustdom_handle;
2253         del.out.handle = opn.out.trustdom_handle;
2254         status = dcesrv_lsa_DeleteObject(dce_call, mem_ctx, &del);
2255         if (!NT_STATUS_IS_OK(status)) {
2256                 return status;
2257         }
2258         return NT_STATUS_OK;
2259 }
2260
2261 static NTSTATUS fill_trust_domain_ex(TALLOC_CTX *mem_ctx,
2262                                      struct ldb_message *msg,
2263                                      struct lsa_TrustDomainInfoInfoEx *info_ex)
2264 {
2265         info_ex->domain_name.string
2266                 = ldb_msg_find_attr_as_string(msg, "trustPartner", NULL);
2267         info_ex->netbios_name.string
2268                 = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2269         info_ex->sid
2270                 = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2271         info_ex->trust_direction
2272                 = ldb_msg_find_attr_as_int(msg, "trustDirection", 0);
2273         info_ex->trust_type
2274                 = ldb_msg_find_attr_as_int(msg, "trustType", 0);
2275         info_ex->trust_attributes
2276                 = ldb_msg_find_attr_as_int(msg, "trustAttributes", 0);
2277         return NT_STATUS_OK;
2278 }
2279
2280 /*
2281   lsa_QueryTrustedDomainInfo
2282 */
2283 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfo(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2284                                            struct lsa_QueryTrustedDomainInfo *r)
2285 {
2286         union lsa_TrustedDomainInfo *info = NULL;
2287         struct dcesrv_handle *h;
2288         struct lsa_trusted_domain_state *trusted_domain_state;
2289         struct ldb_message *msg;
2290         int ret;
2291         struct ldb_message **res;
2292         const char *attrs[] = {
2293                 "flatname",
2294                 "trustPartner",
2295                 "securityIdentifier",
2296                 "trustDirection",
2297                 "trustType",
2298                 "trustAttributes",
2299                 "msDs-supportedEncryptionTypes",
2300                 NULL
2301         };
2302
2303         DCESRV_PULL_HANDLE(h, r->in.trustdom_handle, LSA_HANDLE_TRUSTED_DOMAIN);
2304
2305         trusted_domain_state = talloc_get_type(h->data, struct lsa_trusted_domain_state);
2306
2307         /* pull all the user attributes */
2308         ret = gendb_search_dn(trusted_domain_state->policy->sam_ldb, mem_ctx,
2309                               trusted_domain_state->trusted_domain_dn, &res, attrs);
2310         if (ret != 1) {
2311                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2312         }
2313         msg = res[0];
2314
2315         info = talloc_zero(mem_ctx, union lsa_TrustedDomainInfo);
2316         if (!info) {
2317                 return NT_STATUS_NO_MEMORY;
2318         }
2319         *r->out.info = info;
2320
2321         switch (r->in.level) {
2322         case LSA_TRUSTED_DOMAIN_INFO_NAME:
2323                 info->name.netbios_name.string
2324                         = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2325                 break;
2326         case LSA_TRUSTED_DOMAIN_INFO_POSIX_OFFSET:
2327                 info->posix_offset.posix_offset
2328                         = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2329                 break;
2330 #if 0  /* Win2k3 doesn't implement this */
2331         case LSA_TRUSTED_DOMAIN_INFO_BASIC:
2332                 r->out.info->info_basic.netbios_name.string
2333                         = ldb_msg_find_attr_as_string(msg, "flatname", NULL);
2334                 r->out.info->info_basic.sid
2335                         = samdb_result_dom_sid(mem_ctx, msg, "securityIdentifier");
2336                 break;
2337 #endif
2338         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX:
2339                 return fill_trust_domain_ex(mem_ctx, msg, &info->info_ex);
2340
2341         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO:
2342                 ZERO_STRUCT(info->full_info);
2343                 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info.info_ex);
2344         case LSA_TRUSTED_DOMAIN_INFO_FULL_INFO_2_INTERNAL:
2345                 ZERO_STRUCT(info->full_info2_internal);
2346                 info->full_info2_internal.posix_offset.posix_offset
2347                         = ldb_msg_find_attr_as_uint(msg, "posixOffset", 0);
2348                 return fill_trust_domain_ex(mem_ctx, msg, &info->full_info2_internal.info.info_ex);
2349
2350         case LSA_TRUSTED_DOMAIN_SUPPORTED_ENCRYPTION_TYPES:
2351                 info->enc_types.enc_types
2352                         = ldb_msg_find_attr_as_uint(msg, "msDs-supportedEncryptionTypes", KERB_ENCTYPE_RC4_HMAC_MD5);
2353                 break;
2354
2355         case LSA_TRUSTED_DOMAIN_INFO_CONTROLLERS:
2356         case LSA_TRUSTED_DOMAIN_INFO_INFO_EX2_INTERNAL:
2357                 /* oops, we don't want to return the info after all */
2358                 talloc_free(info);
2359                 *r->out.info = NULL;
2360                 return NT_STATUS_INVALID_PARAMETER;
2361         default:
2362                 /* oops, we don't want to return the info after all */
2363                 talloc_free(info);
2364                 *r->out.info = NULL;
2365                 return NT_STATUS_INVALID_INFO_CLASS;
2366         }
2367
2368         return NT_STATUS_OK;
2369 }
2370
2371
2372 /*
2373   lsa_QueryTrustedDomainInfoBySid
2374 */
2375 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoBySid(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2376                                                 struct lsa_QueryTrustedDomainInfoBySid *r)
2377 {
2378         NTSTATUS status;
2379         struct lsa_OpenTrustedDomain opn = {{0},{0}};
2380         struct lsa_QueryTrustedDomainInfo query;
2381         struct dcesrv_handle *h;
2382
2383         opn.in.handle = r->in.handle;
2384         opn.in.sid = r->in.dom_sid;
2385         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2386         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2387         if (!opn.out.trustdom_handle) {
2388                 return NT_STATUS_NO_MEMORY;
2389         }
2390         status = dcesrv_lsa_OpenTrustedDomain(dce_call, mem_ctx, &opn);
2391         if (!NT_STATUS_IS_OK(status)) {
2392                 return status;
2393         }
2394
2395         /* Ensure this handle goes away at the end of this call */
2396         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2397         talloc_steal(mem_ctx, h);
2398
2399         query.in.trustdom_handle = opn.out.trustdom_handle;
2400         query.in.level = r->in.level;
2401         query.out.info = r->out.info;
2402         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2403         if (!NT_STATUS_IS_OK(status)) {
2404                 return status;
2405         }
2406
2407         return NT_STATUS_OK;
2408 }
2409
2410 /*
2411   lsa_SetTrustedDomainInfoByName
2412 */
2413 static NTSTATUS dcesrv_lsa_SetTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2414                                                TALLOC_CTX *mem_ctx,
2415                                                struct lsa_SetTrustedDomainInfoByName *r)
2416 {
2417         struct dcesrv_handle *policy_handle;
2418         struct lsa_policy_state *policy_state;
2419         struct ldb_message **msgs;
2420         NTSTATUS nt_status;
2421
2422         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2423         policy_state = policy_handle->data;
2424
2425         /* get the trusted domain object */
2426         nt_status = get_tdo(policy_state->sam_ldb, mem_ctx,
2427                             policy_state->domain_dn,
2428                             r->in.trusted_domain->string,
2429                             r->in.trusted_domain->string,
2430                             NULL, &msgs);
2431         if (!NT_STATUS_IS_OK(nt_status)) {
2432                 if (NT_STATUS_EQUAL(nt_status,
2433                                     NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
2434                         return nt_status;
2435                 }
2436                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2437         }
2438
2439         return setInfoTrustedDomain_base(dce_call, policy_state, mem_ctx,
2440                                          msgs[0], r->in.level, r->in.info);
2441 }
2442
2443 /*
2444    lsa_QueryTrustedDomainInfoByName
2445 */
2446 static NTSTATUS dcesrv_lsa_QueryTrustedDomainInfoByName(struct dcesrv_call_state *dce_call,
2447                                                  TALLOC_CTX *mem_ctx,
2448                                                  struct lsa_QueryTrustedDomainInfoByName *r)
2449 {
2450         NTSTATUS status;
2451         struct lsa_OpenTrustedDomainByName opn = {{0},{0}};
2452         struct lsa_QueryTrustedDomainInfo query;
2453         struct dcesrv_handle *h;
2454
2455         opn.in.handle = r->in.handle;
2456         opn.in.name = *r->in.trusted_domain;
2457         opn.in.access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
2458         opn.out.trustdom_handle = talloc(mem_ctx, struct policy_handle);
2459         if (!opn.out.trustdom_handle) {
2460                 return NT_STATUS_NO_MEMORY;
2461         }
2462         status = dcesrv_lsa_OpenTrustedDomainByName(dce_call, mem_ctx, &opn);
2463         if (!NT_STATUS_IS_OK(status)) {
2464                 return status;
2465         }
2466
2467         /* Ensure this handle goes away at the end of this call */
2468         DCESRV_PULL_HANDLE(h, opn.out.trustdom_handle, DCESRV_HANDLE_ANY);
2469         talloc_steal(mem_ctx, h);
2470
2471         query.in.trustdom_handle = opn.out.trustdom_handle;
2472         query.in.level = r->in.level;
2473         query.out.info = r->out.info;
2474         status = dcesrv_lsa_QueryTrustedDomainInfo(dce_call, mem_ctx, &query);
2475         if (!NT_STATUS_IS_OK(status)) {
2476                 return status;
2477         }
2478
2479         return NT_STATUS_OK;
2480 }
2481
2482 /*
2483   lsa_CloseTrustedDomainEx
2484 */
2485 static NTSTATUS dcesrv_lsa_CloseTrustedDomainEx(struct dcesrv_call_state *dce_call,
2486                                          TALLOC_CTX *mem_ctx,
2487                                          struct lsa_CloseTrustedDomainEx *r)
2488 {
2489         /* The result of a bad hair day from an IDL programmer?  Not
2490          * implmented in Win2k3.  You should always just lsa_Close
2491          * anyway. */
2492         return NT_STATUS_NOT_IMPLEMENTED;
2493 }
2494
2495
2496 /*
2497   comparison function for sorting lsa_DomainInformation array
2498 */
2499 static int compare_DomainInfo(struct lsa_DomainInfo *e1, struct lsa_DomainInfo *e2)
2500 {
2501         return strcasecmp_m(e1->name.string, e2->name.string);
2502 }
2503
2504 /*
2505   lsa_EnumTrustDom
2506 */
2507 static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2508                                  struct lsa_EnumTrustDom *r)
2509 {
2510         struct dcesrv_handle *policy_handle;
2511         struct lsa_DomainInfo *entries;
2512         struct lsa_policy_state *policy_state;
2513         struct ldb_message **domains;
2514         const char *attrs[] = {
2515                 "flatname",
2516                 "securityIdentifier",
2517                 NULL
2518         };
2519
2520
2521         int count, i;
2522
2523         *r->out.resume_handle = 0;
2524
2525         r->out.domains->domains = NULL;
2526         r->out.domains->count = 0;
2527
2528         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2529
2530         policy_state = policy_handle->data;
2531
2532         /* search for all users in this domain. This could possibly be cached and
2533            resumed based on resume_key */
2534         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2535                              "objectclass=trustedDomain");
2536         if (count < 0) {
2537                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2538         }
2539
2540         /* convert to lsa_TrustInformation format */
2541         entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
2542         if (!entries) {
2543                 return NT_STATUS_NO_MEMORY;
2544         }
2545         for (i=0;i<count;i++) {
2546                 entries[i].sid = samdb_result_dom_sid(mem_ctx, domains[i], "securityIdentifier");
2547                 entries[i].name.string = ldb_msg_find_attr_as_string(domains[i], "flatname", NULL);
2548         }
2549
2550         /* sort the results by name */
2551         TYPESAFE_QSORT(entries, count, compare_DomainInfo);
2552
2553         if (*r->in.resume_handle >= count) {
2554                 *r->out.resume_handle = -1;
2555
2556                 return NT_STATUS_NO_MORE_ENTRIES;
2557         }
2558
2559         /* return the rest, limit by max_size. Note that we
2560            use the w2k3 element size value of 60 */
2561         r->out.domains->count = count - *r->in.resume_handle;
2562         r->out.domains->count = MIN(r->out.domains->count,
2563                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_MULTIPLIER));
2564
2565         r->out.domains->domains = entries + *r->in.resume_handle;
2566
2567         if (r->out.domains->count < count - *r->in.resume_handle) {
2568                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2569                 return STATUS_MORE_ENTRIES;
2570         }
2571
2572         /* according to MS-LSAD 3.1.4.7.8 output resume handle MUST
2573          * always be larger than the previous input resume handle, in
2574          * particular when hitting the last query it is vital to set the
2575          * resume handle correctly to avoid infinite client loops, as
2576          * seen e.g. with Windows XP SP3 when resume handle is 0 and
2577          * status is NT_STATUS_OK - gd */
2578
2579         *r->out.resume_handle = (uint32_t)-1;
2580
2581         return NT_STATUS_OK;
2582 }
2583
2584 /*
2585   comparison function for sorting lsa_DomainInformation array
2586 */
2587 static int compare_TrustDomainInfoInfoEx(struct lsa_TrustDomainInfoInfoEx *e1, struct lsa_TrustDomainInfoInfoEx *e2)
2588 {
2589         return strcasecmp_m(e1->netbios_name.string, e2->netbios_name.string);
2590 }
2591
2592 /*
2593   lsa_EnumTrustedDomainsEx
2594 */
2595 static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2596                                         struct lsa_EnumTrustedDomainsEx *r)
2597 {
2598         struct dcesrv_handle *policy_handle;
2599         struct lsa_TrustDomainInfoInfoEx *entries;
2600         struct lsa_policy_state *policy_state;
2601         struct ldb_message **domains;
2602         const char *attrs[] = {
2603                 "flatname",
2604                 "trustPartner",
2605                 "securityIdentifier",
2606                 "trustDirection",
2607                 "trustType",
2608                 "trustAttributes",
2609                 NULL
2610         };
2611         NTSTATUS nt_status;
2612
2613         int count, i;
2614
2615         *r->out.resume_handle = 0;
2616
2617         r->out.domains->domains = NULL;
2618         r->out.domains->count = 0;
2619
2620         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
2621
2622         policy_state = policy_handle->data;
2623
2624         /* search for all users in this domain. This could possibly be cached and
2625            resumed based on resume_key */
2626         count = gendb_search(policy_state->sam_ldb, mem_ctx, policy_state->system_dn, &domains, attrs,
2627                              "objectclass=trustedDomain");
2628         if (count < 0) {
2629                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2630         }
2631
2632         /* convert to lsa_DomainInformation format */
2633         entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
2634         if (!entries) {
2635                 return NT_STATUS_NO_MEMORY;
2636         }
2637         for (i=0;i<count;i++) {
2638                 nt_status = fill_trust_domain_ex(mem_ctx, domains[i], &entries[i]);
2639                 if (!NT_STATUS_IS_OK(nt_status)) {
2640                         return nt_status;
2641                 }
2642         }
2643
2644         /* sort the results by name */
2645         TYPESAFE_QSORT(entries, count, compare_TrustDomainInfoInfoEx);
2646
2647         if (*r->in.resume_handle >= count) {
2648                 *r->out.resume_handle = -1;
2649
2650                 return NT_STATUS_NO_MORE_ENTRIES;
2651         }
2652
2653         /* return the rest, limit by max_size. Note that we
2654            use the w2k3 element size value of 60 */
2655         r->out.domains->count = count - *r->in.resume_handle;
2656         r->out.domains->count = MIN(r->out.domains->count,
2657                                  1+(r->in.max_size/LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER));
2658
2659         r->out.domains->domains = entries + *r->in.resume_handle;
2660         r->out.domains->count = r->out.domains->count;
2661
2662         if (r->out.domains->count < count - *r->in.resume_handle) {
2663                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2664                 return STATUS_MORE_ENTRIES;
2665         }
2666
2667         *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2668
2669         return NT_STATUS_OK;
2670 }
2671
2672
2673 /*
2674   lsa_OpenAccount
2675 */
2676 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2677                                 struct lsa_OpenAccount *r)
2678 {
2679         struct dcesrv_handle *h, *ah;
2680         struct lsa_policy_state *state;
2681         struct lsa_account_state *astate;
2682
2683         ZERO_STRUCTP(r->out.acct_handle);
2684
2685         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2686
2687         state = h->data;
2688
2689         astate = talloc(dce_call->conn, struct lsa_account_state);
2690         if (astate == NULL) {
2691                 return NT_STATUS_NO_MEMORY;
2692         }
2693
2694         astate->account_sid = dom_sid_dup(astate, r->in.sid);
2695         if (astate->account_sid == NULL) {
2696                 talloc_free(astate);
2697                 return NT_STATUS_NO_MEMORY;
2698         }
2699
2700         astate->policy = talloc_reference(astate, state);
2701         astate->access_mask = r->in.access_mask;
2702
2703         /*
2704          * For now we grant all requested access.
2705          *
2706          * We will fail at the ldb layer later.
2707          */
2708         if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
2709                 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
2710                 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
2711         }
2712         se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
2713
2714         DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X] - success.\n",
2715                   __func__, dom_sid_string(mem_ctx, astate->account_sid),
2716                  (unsigned)r->in.access_mask,
2717                  (unsigned)astate->access_mask));
2718
2719         ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2720         if (!ah) {
2721                 talloc_free(astate);
2722                 return NT_STATUS_NO_MEMORY;
2723         }
2724
2725         ah->data = talloc_steal(ah, astate);
2726
2727         *r->out.acct_handle = ah->wire_handle;
2728
2729         return NT_STATUS_OK;
2730 }
2731
2732
2733 /*
2734   lsa_EnumPrivsAccount
2735 */
2736 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2737                                      TALLOC_CTX *mem_ctx,
2738                                      struct lsa_EnumPrivsAccount *r)
2739 {
2740         struct dcesrv_handle *h;
2741         struct lsa_account_state *astate;
2742         int ret;
2743         unsigned int i, j;
2744         struct ldb_message **res;
2745         const char * const attrs[] = { "privilege", NULL};
2746         struct ldb_message_element *el;
2747         const char *sidstr;
2748         struct lsa_PrivilegeSet *privs;
2749
2750         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2751
2752         astate = h->data;
2753
2754         privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2755         if (privs == NULL) {
2756                 return NT_STATUS_NO_MEMORY;
2757         }
2758         privs->count = 0;
2759         privs->unknown = 0;
2760         privs->set = NULL;
2761
2762         *r->out.privs = privs;
2763
2764         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2765         if (sidstr == NULL) {
2766                 return NT_STATUS_NO_MEMORY;
2767         }
2768
2769         ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2770                            "objectSid=%s", sidstr);
2771         if (ret < 0) {
2772                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2773         }
2774         if (ret != 1) {
2775                 return NT_STATUS_OK;
2776         }
2777
2778         el = ldb_msg_find_element(res[0], "privilege");
2779         if (el == NULL || el->num_values == 0) {
2780                 return NT_STATUS_OK;
2781         }
2782
2783         privs->set = talloc_array(privs,
2784                                   struct lsa_LUIDAttribute, el->num_values);
2785         if (privs->set == NULL) {
2786                 return NT_STATUS_NO_MEMORY;
2787         }
2788
2789         j = 0;
2790         for (i=0;i<el->num_values;i++) {
2791                 int id = sec_privilege_id((const char *)el->values[i].data);
2792                 if (id == SEC_PRIV_INVALID) {
2793                         /* Perhaps an account right, not a privilege */
2794                         continue;
2795                 }
2796                 privs->set[j].attribute = 0;
2797                 privs->set[j].luid.low = id;
2798                 privs->set[j].luid.high = 0;
2799                 j++;
2800         }
2801
2802         privs->count = j;
2803
2804         return NT_STATUS_OK;
2805 }
2806
2807 /*
2808   lsa_EnumAccountRights
2809 */
2810 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2811                                       TALLOC_CTX *mem_ctx,
2812                                       struct lsa_EnumAccountRights *r)
2813 {
2814         struct dcesrv_handle *h;
2815         struct lsa_policy_state *state;
2816         int ret;
2817         unsigned int i;
2818         struct ldb_message **res;
2819         const char * const attrs[] = { "privilege", NULL};
2820         const char *sidstr;
2821         struct ldb_message_element *el;
2822
2823         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2824
2825         state = h->data;
2826
2827         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2828         if (sidstr == NULL) {
2829                 return NT_STATUS_NO_MEMORY;
2830         }
2831
2832         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2833                            "(&(objectSid=%s)(privilege=*))", sidstr);
2834         if (ret == 0) {
2835                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2836         }
2837         if (ret != 1) {
2838                 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2839                           dom_sid_string(mem_ctx, r->in.sid),
2840                           ldb_errstring(state->pdb)));
2841                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2842         }
2843
2844         el = ldb_msg_find_element(res[0], "privilege");
2845         if (el == NULL || el->num_values == 0) {
2846                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2847         }
2848
2849         r->out.rights->count = el->num_values;
2850         r->out.rights->names = talloc_array(r->out.rights,
2851                                             struct lsa_StringLarge, r->out.rights->count);
2852         if (r->out.rights->names == NULL) {
2853                 return NT_STATUS_NO_MEMORY;
2854         }
2855
2856         for (i=0;i<el->num_values;i++) {
2857                 r->out.rights->names[i].string = (const char *)el->values[i].data;
2858         }
2859
2860         return NT_STATUS_OK;
2861 }
2862
2863
2864
2865 /*
2866   helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2867 */
2868 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2869                                            TALLOC_CTX *mem_ctx,
2870                                            struct lsa_policy_state *state,
2871                                            int ldb_flag,
2872                                            struct dom_sid *sid,
2873                                            const struct lsa_RightSet *rights)
2874 {
2875         const char *sidstr, *sidndrstr;
2876         struct ldb_message *msg;
2877         struct ldb_message_element *el;
2878         int ret;
2879         uint32_t i;
2880         struct lsa_EnumAccountRights r2;
2881         char *dnstr;
2882
2883         if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2884             SECURITY_ADMINISTRATOR) {
2885                 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2886                 return NT_STATUS_ACCESS_DENIED;
2887         }
2888
2889         msg = ldb_msg_new(mem_ctx);
2890         if (msg == NULL) {
2891                 return NT_STATUS_NO_MEMORY;
2892         }
2893
2894         sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2895         if (sidndrstr == NULL) {
2896                 TALLOC_FREE(msg);
2897                 return NT_STATUS_NO_MEMORY;
2898         }
2899
2900         sidstr = dom_sid_string(msg, sid);
2901         if (sidstr == NULL) {
2902                 TALLOC_FREE(msg);
2903                 return NT_STATUS_NO_MEMORY;
2904         }
2905
2906         dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2907         if (dnstr == NULL) {
2908                 TALLOC_FREE(msg);
2909                 return NT_STATUS_NO_MEMORY;
2910         }
2911
2912         msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2913         if (msg->dn == NULL) {
2914                 TALLOC_FREE(msg);
2915                 return NT_STATUS_NO_MEMORY;
2916         }
2917
2918         if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2919                 NTSTATUS status;
2920
2921                 r2.in.handle = &state->handle->wire_handle;
2922                 r2.in.sid = sid;
2923                 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2924
2925                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2926                 if (!NT_STATUS_IS_OK(status)) {
2927                         ZERO_STRUCTP(r2.out.rights);
2928                 }
2929         }
2930
2931         for (i=0;i<rights->count;i++) {
2932                 bool ok;
2933
2934                 ok = dcesrc_lsa_valid_AccountRight(rights->names[i].string);
2935                 if (!ok) {
2936                         talloc_free(msg);
2937                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2938                 }
2939
2940                 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2941                         uint32_t j;
2942                         for (j=0;j<r2.out.rights->count;j++) {
2943                                 if (strcasecmp_m(r2.out.rights->names[j].string,
2944                                                rights->names[i].string) == 0) {
2945                                         break;
2946                                 }
2947                         }
2948                         if (j != r2.out.rights->count) continue;
2949                 }
2950
2951                 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2952                 if (ret != LDB_SUCCESS) {
2953                         talloc_free(msg);
2954                         return NT_STATUS_NO_MEMORY;
2955                 }
2956         }
2957
2958         el = ldb_msg_find_element(msg, "privilege");
2959         if (!el) {
2960                 talloc_free(msg);
2961                 return NT_STATUS_OK;
2962         }
2963
2964         el->flags = ldb_flag;
2965
2966         ret = ldb_modify(state->pdb, msg);
2967         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2968                 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2969                         talloc_free(msg);
2970                         return NT_STATUS_NO_MEMORY;
2971                 }
2972                 ldb_msg_add_string(msg, "comment", "added via LSA");
2973                 ret = ldb_add(state->pdb, msg);
2974         }
2975         if (ret != LDB_SUCCESS) {
2976                 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2977                         talloc_free(msg);
2978                         return NT_STATUS_OK;
2979                 }
2980                 DEBUG(3, ("Could not %s attributes from %s: %s",
2981                           LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2982                           ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2983                 talloc_free(msg);
2984                 return NT_STATUS_UNEXPECTED_IO_ERROR;
2985         }
2986
2987         talloc_free(msg);
2988         return NT_STATUS_OK;
2989 }
2990
2991 /*
2992   lsa_AddPrivilegesToAccount
2993 */
2994 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2995                                            struct lsa_AddPrivilegesToAccount *r)
2996 {
2997         struct lsa_RightSet rights;
2998         struct dcesrv_handle *h;
2999         struct lsa_account_state *astate;
3000         uint32_t i;
3001
3002         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3003
3004         astate = h->data;
3005
3006         rights.count = r->in.privs->count;
3007         rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
3008         if (rights.names == NULL) {
3009                 return NT_STATUS_NO_MEMORY;
3010         }
3011         for (i=0;i<rights.count;i++) {
3012                 int id = r->in.privs->set[i].luid.low;
3013                 if (r->in.privs->set[i].luid.high) {
3014                         return NT_STATUS_NO_SUCH_PRIVILEGE;
3015                 }
3016                 rights.names[i].string = sec_privilege_name(id);
3017                 if (rights.names[i].string == NULL) {
3018                         return NT_STATUS_NO_SUCH_PRIVILEGE;
3019                 }
3020         }
3021
3022         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3023                                           LDB_FLAG_MOD_ADD, astate->account_sid,
3024                                           &rights);
3025 }
3026
3027
3028 /*
3029   lsa_RemovePrivilegesFromAccount
3030 */
3031 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3032                                                 struct lsa_RemovePrivilegesFromAccount *r)
3033 {
3034         struct lsa_RightSet *rights;
3035         struct dcesrv_handle *h;
3036         struct lsa_account_state *astate;
3037         uint32_t i;
3038
3039         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3040
3041         astate = h->data;
3042
3043         rights = talloc(mem_ctx, struct lsa_RightSet);
3044
3045         if (r->in.remove_all == 1 &&
3046             r->in.privs == NULL) {
3047                 struct lsa_EnumAccountRights r2;
3048                 NTSTATUS status;
3049
3050                 r2.in.handle = &astate->policy->handle->wire_handle;
3051                 r2.in.sid = astate->account_sid;
3052                 r2.out.rights = rights;
3053
3054                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
3055                 if (!NT_STATUS_IS_OK(status)) {
3056                         return status;
3057                 }
3058
3059                 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3060                                                   LDB_FLAG_MOD_DELETE, astate->account_sid,
3061                                                   r2.out.rights);
3062         }
3063
3064         if (r->in.remove_all != 0) {
3065                 return NT_STATUS_INVALID_PARAMETER;
3066         }
3067
3068         rights->count = r->in.privs->count;
3069         rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
3070         if (rights->names == NULL) {
3071                 return NT_STATUS_NO_MEMORY;
3072         }
3073         for (i=0;i<rights->count;i++) {
3074                 int id = r->in.privs->set[i].luid.low;
3075                 if (r->in.privs->set[i].luid.high) {
3076                         return NT_STATUS_NO_SUCH_PRIVILEGE;
3077                 }
3078                 rights->names[i].string = sec_privilege_name(id);
3079                 if (rights->names[i].string == NULL) {
3080                         return NT_STATUS_NO_SUCH_PRIVILEGE;
3081                 }
3082         }
3083
3084         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3085                                           LDB_FLAG_MOD_DELETE, astate->account_sid,
3086                                           rights);
3087 }
3088
3089
3090 /*
3091   lsa_GetQuotasForAccount
3092 */
3093 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3094                        struct lsa_GetQuotasForAccount *r)
3095 {
3096         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3097 }
3098
3099
3100 /*
3101   lsa_SetQuotasForAccount
3102 */
3103 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3104                        struct lsa_SetQuotasForAccount *r)
3105 {
3106         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3107 }
3108
3109
3110 /*
3111   lsa_GetSystemAccessAccount
3112 */
3113 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3114                        struct lsa_GetSystemAccessAccount *r)
3115 {
3116         struct dcesrv_handle *h;
3117         struct lsa_account_state *astate;
3118         int ret;
3119         unsigned int i;
3120         struct ldb_message **res;
3121         const char * const attrs[] = { "privilege", NULL};
3122         struct ldb_message_element *el;
3123         const char *sidstr;
3124
3125         *(r->out.access_mask) = 0x00000000;
3126
3127         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3128
3129         astate = h->data;
3130
3131         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
3132         if (sidstr == NULL) {
3133                 return NT_STATUS_NO_MEMORY;
3134         }
3135
3136         ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
3137                            "objectSid=%s", sidstr);
3138         if (ret < 0) {
3139                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3140         }
3141         if (ret != 1) {
3142                 return NT_STATUS_OK;
3143         }
3144
3145         el = ldb_msg_find_element(res[0], "privilege");
3146         if (el == NULL || el->num_values == 0) {
3147                 return NT_STATUS_OK;
3148         }
3149
3150         for (i=0;i<el->num_values;i++) {
3151                 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
3152                 if (right_bit == 0) {
3153                         /* Perhaps an privilege, not a right */
3154                         continue;
3155                 }
3156                 *(r->out.access_mask) |= right_bit;
3157         }
3158
3159         return NT_STATUS_OK;
3160 }
3161
3162
3163 /*
3164   lsa_SetSystemAccessAccount
3165 */
3166 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3167                        struct lsa_SetSystemAccessAccount *r)
3168 {
3169         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3170 }
3171
3172
3173 /*
3174   lsa_CreateSecret
3175 */
3176 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3177                                  struct lsa_CreateSecret *r)
3178 {
3179         struct dcesrv_handle *policy_handle;
3180         struct lsa_policy_state *policy_state;
3181         struct lsa_secret_state *secret_state;
3182         struct dcesrv_handle *handle;
3183         struct ldb_message **msgs, *msg;
3184         const char *attrs[] = {
3185                 NULL
3186         };
3187
3188         const char *name;
3189
3190         int ret;
3191
3192         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3193         ZERO_STRUCTP(r->out.sec_handle);
3194
3195         switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3196         {
3197         case SECURITY_SYSTEM:
3198         case SECURITY_ADMINISTRATOR:
3199                 break;
3200         default:
3201                 /* Users and annonymous are not allowed create secrets */
3202                 return NT_STATUS_ACCESS_DENIED;
3203         }
3204
3205         policy_state = policy_handle->data;
3206
3207         if (!r->in.name.string) {
3208                 return NT_STATUS_INVALID_PARAMETER;
3209         }
3210
3211         secret_state = talloc(mem_ctx, struct lsa_secret_state);
3212         NT_STATUS_HAVE_NO_MEMORY(secret_state);
3213         secret_state->policy = policy_state;
3214
3215         msg = ldb_msg_new(mem_ctx);
3216         if (msg == NULL) {
3217                 return NT_STATUS_NO_MEMORY;
3218         }
3219
3220         if (strncmp("G$", r->in.name.string, 2) == 0) {
3221                 const char *name2;
3222
3223                 secret_state->global = true;
3224
3225                 name = &r->in.name.string[2];
3226                 if (strlen(name) == 0) {
3227                         return NT_STATUS_INVALID_PARAMETER;
3228                 }
3229
3230                 name2 = talloc_asprintf(mem_ctx, "%s Secret",
3231                                         ldb_binary_encode_string(mem_ctx, name));
3232                 NT_STATUS_HAVE_NO_MEMORY(name2);
3233
3234                 /* We need to connect to the database as system, as this is one
3235                  * of the rare RPC calls that must read the secrets (and this
3236                  * is denied otherwise) */
3237                 secret_state->sam_ldb = talloc_reference(secret_state,
3238                                                          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));
3239                 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3240
3241                 /* search for the secret record */
3242                 ret = gendb_search(secret_state->sam_ldb,
3243                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
3244                                    "(&(cn=%s)(objectclass=secret))",
3245                                    name2);
3246                 if (ret > 0) {
3247                         return NT_STATUS_OBJECT_NAME_COLLISION;
3248                 }
3249
3250                 if (ret < 0) {
3251                         DEBUG(0,("Failure searching for CN=%s: %s\n",
3252                                  name2, ldb_errstring(secret_state->sam_ldb)));
3253                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3254                 }
3255
3256                 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
3257                 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3258                 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
3259                         return NT_STATUS_NO_MEMORY;
3260                 }
3261
3262                 ret = ldb_msg_add_string(msg, "cn", name2);
3263                 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3264         } else {
3265                 secret_state->global = false;
3266
3267                 name = r->in.name.string;
3268                 if (strlen(name) == 0) {
3269                         return NT_STATUS_INVALID_PARAMETER;
3270                 }
3271
3272                 secret_state->sam_ldb = talloc_reference(secret_state,
3273                                                          secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3274                 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3275
3276                 /* search for the secret record */
3277                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3278                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3279                                    &msgs, attrs,
3280                                    "(&(cn=%s)(objectclass=secret))",
3281                                    ldb_binary_encode_string(mem_ctx, name));
3282                 if (ret > 0) {
3283                         return NT_STATUS_OBJECT_NAME_COLLISION;
3284                 }
3285
3286                 if (ret < 0) {
3287                         DEBUG(0,("Failure searching for CN=%s: %s\n",
3288                                  name, ldb_errstring(secret_state->sam_ldb)));
3289                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3290                 }
3291
3292                 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
3293                                          "cn=%s,cn=LSA Secrets", name);
3294                 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3295                 ret = ldb_msg_add_string(msg, "cn", name);
3296                 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3297         }
3298
3299         ret = ldb_msg_add_string(msg, "objectClass", "secret");
3300         if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3301
3302         secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3303         NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3304
3305         /* create the secret */
3306         ret = ldb_add(secret_state->sam_ldb, msg);
3307         if (ret != LDB_SUCCESS) {
3308                 DEBUG(0,("Failed to create secret record %s: %s\n",
3309                          ldb_dn_get_linearized(msg->dn),
3310                          ldb_errstring(secret_state->sam_ldb)));
3311                 return NT_STATUS_ACCESS_DENIED;
3312         }
3313
3314         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3315         NT_STATUS_HAVE_NO_MEMORY(handle);
3316
3317         handle->data = talloc_steal(handle, secret_state);
3318
3319         secret_state->access_mask = r->in.access_mask;
3320         secret_state->policy = talloc_reference(secret_state, policy_state);
3321         NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3322
3323         *r->out.sec_handle = handle->wire_handle;
3324
3325         return NT_STATUS_OK;
3326 }
3327
3328
3329 /*
3330   lsa_OpenSecret
3331 */
3332 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3333                                struct lsa_OpenSecret *r)
3334 {
3335         struct dcesrv_handle *policy_handle;
3336
3337         struct lsa_policy_state *policy_state;
3338         struct lsa_secret_state *secret_state;
3339         struct dcesrv_handle *handle;
3340         struct ldb_message **msgs;
3341         const char *attrs[] = {
3342                 NULL
3343         };
3344
3345         const char *name;
3346
3347         int ret;
3348
3349         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3350         ZERO_STRUCTP(r->out.sec_handle);
3351         policy_state = policy_handle->data;
3352
3353         if (!r->in.name.string) {
3354                 return NT_STATUS_INVALID_PARAMETER;
3355         }
3356
3357         switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3358         {
3359         case SECURITY_SYSTEM:
3360         case SECURITY_ADMINISTRATOR:
3361                 break;
3362         default:
3363                 /* Users and annonymous are not allowed to access secrets */
3364                 return NT_STATUS_ACCESS_DENIED;
3365         }
3366
3367         secret_state = talloc(mem_ctx, struct lsa_secret_state);
3368         if (!secret_state) {
3369                 return NT_STATUS_NO_MEMORY;
3370         }
3371         secret_state->policy = policy_state;
3372
3373         if (strncmp("G$", r->in.name.string, 2) == 0) {
3374                 name = &r->in.name.string[2];
3375                 /* 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) */
3376                 secret_state->sam_ldb = talloc_reference(secret_state,
3377                                                          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));
3378                 secret_state->global = true;
3379
3380                 if (strlen(name) < 1) {
3381                         return NT_STATUS_INVALID_PARAMETER;
3382                 }
3383
3384                 /* search for the secret record */
3385                 ret = gendb_search(secret_state->sam_ldb,
3386                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
3387                                    "(&(cn=%s Secret)(objectclass=secret))",
3388                                    ldb_binary_encode_string(mem_ctx, name));
3389                 if (ret == 0) {
3390                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3391                 }
3392
3393                 if (ret != 1) {
3394                         DEBUG(0,("Found %d records matching DN %s\n", ret,
3395                                  ldb_dn_get_linearized(policy_state->system_dn)));
3396                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3397                 }
3398         } else {
3399                 secret_state->global = false;
3400                 secret_state->sam_ldb = talloc_reference(secret_state,
3401                                                          secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3402
3403                 name = r->in.name.string;
3404                 if (strlen(name) < 1) {
3405                         return NT_STATUS_INVALID_PARAMETER;
3406                 }
3407
3408                 /* search for the secret record */
3409                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3410                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3411                                    &msgs, attrs,
3412                                    "(&(cn=%s)(objectclass=secret))",
3413                                    ldb_binary_encode_string(mem_ctx, name));
3414                 if (ret == 0) {
3415                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3416                 }
3417
3418                 if (ret != 1) {
3419                         DEBUG(0,("Found %d records matching CN=%s\n",
3420                                  ret, ldb_binary_encode_string(mem_ctx, name)));
3421                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3422                 }
3423         }
3424
3425         secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3426
3427         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3428         if (!handle) {
3429                 return NT_STATUS_NO_MEMORY;
3430         }
3431
3432         handle->data = talloc_steal(handle, secret_state);
3433
3434         secret_state->access_mask = r->in.access_mask;
3435         secret_state->policy = talloc_reference(secret_state, policy_state);
3436
3437         *r->out.sec_handle = handle->wire_handle;
3438
3439         return NT_STATUS_OK;
3440 }
3441
3442
3443 /*
3444   lsa_SetSecret
3445 */
3446 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3447                               struct lsa_SetSecret *r)
3448 {
3449
3450         struct dcesrv_handle *h;
3451         struct lsa_secret_state *secret_state;
3452         struct ldb_message *msg;
3453         DATA_BLOB session_key;
3454         DATA_BLOB crypt_secret, secret;
3455         struct ldb_val val;
3456         int ret;
3457         NTSTATUS status = NT_STATUS_OK;
3458
3459         struct timeval now = timeval_current();
3460         NTTIME nt_now = timeval_to_nttime(&now);
3461
3462         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3463
3464         secret_state = h->data;
3465
3466         msg = ldb_msg_new(mem_ctx);
3467         if (msg == NULL) {
3468                 return NT_STATUS_NO_MEMORY;
3469         }
3470
3471         msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3472         if (!msg->dn) {
3473                 return NT_STATUS_NO_MEMORY;
3474         }
3475         status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3476         if (!NT_STATUS_IS_OK(status)) {
3477                 return status;
3478         }
3479
3480         if (r->in.old_val) {
3481                 /* Decrypt */
3482                 crypt_secret.data = r->in.old_val->data;
3483                 crypt_secret.length = r->in.old_val->size;
3484
3485                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3486                 if (!NT_STATUS_IS_OK(status)) {
3487                         return status;
3488                 }
3489
3490                 val.data = secret.data;
3491                 val.length = secret.length;
3492
3493                 /* set value */
3494                 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3495                         return NT_STATUS_NO_MEMORY;
3496                 }
3497
3498                 /* set old value mtime */
3499                 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3500                                          mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3501                         return NT_STATUS_NO_MEMORY;
3502                 }
3503
3504         } else {
3505                 /* If the old value is not set, then migrate the
3506                  * current value to the old value */
3507                 const struct ldb_val *old_val;
3508                 NTTIME last_set_time;
3509                 struct ldb_message **res;
3510                 const char *attrs[] = {
3511                         "currentValue",
3512                         "lastSetTime",
3513                         NULL
3514                 };
3515
3516                 /* search for the secret record */
3517                 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3518                                       secret_state->secret_dn, &res, attrs);
3519                 if (ret == 0) {
3520                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3521                 }
3522
3523                 if (ret != 1) {
3524                         DEBUG(0,("Found %d records matching dn=%s\n", ret,
3525                                  ldb_dn_get_linearized(secret_state->secret_dn)));
3526                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3527                 }
3528
3529                 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3530                 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3531
3532                 if (old_val) {
3533                         /* set old value */
3534                         if (ldb_msg_add_value(msg, "priorValue",
3535                                               old_val, NULL) != LDB_SUCCESS) {
3536                                 return NT_STATUS_NO_MEMORY;
3537                         }
3538                 } else {
3539                         if (samdb_msg_add_delete(secret_state->sam_ldb,
3540                                                  mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3541                                 return NT_STATUS_NO_MEMORY;
3542                         }
3543                 }
3544
3545                 /* set old value mtime */
3546                 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3547                         if (samdb_msg_add_uint64(secret_state->sam_ldb,
3548                                                  mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3549                                 return NT_STATUS_NO_MEMORY;
3550                         }
3551                 } else {
3552                         if (samdb_msg_add_uint64(secret_state->sam_ldb,
3553                                                  mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3554                                 return NT_STATUS_NO_MEMORY;
3555                         }
3556                 }
3557         }
3558
3559         if (r->in.new_val) {
3560                 /* Decrypt */
3561                 crypt_secret.data = r->in.new_val->data;
3562                 crypt_secret.length = r->in.new_val->size;
3563
3564                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3565                 if (!NT_STATUS_IS_OK(status)) {
3566                         return status;
3567                 }
3568
3569                 val.data = secret.data;
3570                 val.length = secret.length;
3571
3572                 /* set value */
3573                 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3574                         return NT_STATUS_NO_MEMORY;
3575                 }
3576
3577                 /* set new value mtime */
3578                 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3579                                          mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3580                         return NT_STATUS_NO_MEMORY;
3581                 }
3582         } else {
3583                 /* NULL out the NEW value */
3584                 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3585                                          mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3586                         return NT_STATUS_NO_MEMORY;
3587                 }
3588                 if (samdb_msg_add_delete(secret_state->sam_ldb,
3589                                          mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3590                         return NT_STATUS_NO_MEMORY;
3591                 }
3592         }
3593
3594         /* modify the samdb record */
3595         ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3596         if (ret != LDB_SUCCESS) {
3597                 return dsdb_ldb_err_to_ntstatus(ret);
3598         }
3599
3600         return NT_STATUS_OK;
3601 }
3602
3603
3604 /*
3605   lsa_QuerySecret
3606 */
3607 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3608                                 struct lsa_QuerySecret *r)
3609 {
3610         struct dcesrv_handle *h;
3611         struct lsa_secret_state *secret_state;
3612         struct ldb_message *msg;
3613         DATA_BLOB session_key;
3614         DATA_BLOB crypt_secret, secret;
3615         int ret;
3616         struct ldb_message **res;
3617         const char *attrs[] = {
3618                 "currentValue",
3619                 "priorValue",
3620                 "lastSetTime",
3621                 "priorSetTime",
3622                 NULL
3623         };
3624
3625         NTSTATUS nt_status;
3626
3627         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3628
3629         /* Ensure user is permitted to read this... */
3630         switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3631         {
3632         case SECURITY_SYSTEM:
3633         case SECURITY_ADMINISTRATOR:
3634                 break;
3635         default:
3636                 /* Users and annonymous are not allowed to read secrets */
3637                 return NT_STATUS_ACCESS_DENIED;
3638         }
3639
3640         secret_state = h->data;
3641
3642         /* pull all the user attributes */
3643         ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3644                               secret_state->secret_dn, &res, attrs);
3645         if (ret != 1) {
3646                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3647         }
3648         msg = res[0];
3649
3650         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3651         if (!NT_STATUS_IS_OK(nt_status)) {
3652                 return nt_status;
3653         }
3654
3655         if (r->in.old_val) {
3656                 const struct ldb_val *prior_val;
3657                 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3658                 if (!r->out.old_val) {
3659                         return NT_STATUS_NO_MEMORY;
3660                 }
3661                 prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3662
3663                 if (prior_val && prior_val->length) {
3664                         secret.data = prior_val->data;
3665                         secret.length = prior_val->length;
3666
3667                         /* Encrypt */
3668                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3669                         if (!crypt_secret.length) {
3670                                 return NT_STATUS_NO_MEMORY;
3671                         }
3672                         r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3673                         if (!r->out.old_val->buf) {
3674                                 return NT_STATUS_NO_MEMORY;
3675                         }
3676                         r->out.old_val->buf->size = crypt_secret.length;
3677                         r->out.old_val->buf->length = crypt_secret.length;
3678                         r->out.old_val->buf->data = crypt_secret.data;
3679                 }
3680         }
3681
3682         if (r->in.old_mtime) {
3683                 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3684                 if (!r->out.old_mtime) {
3685                         return NT_STATUS_NO_MEMORY;
3686                 }
3687                 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3688         }
3689
3690         if (r->in.new_val) {
3691                 const struct ldb_val *new_val;
3692                 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3693                 if (!r->out.new_val) {
3694                         return NT_STATUS_NO_MEMORY;
3695                 }
3696
3697                 new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3698
3699                 if (new_val && new_val->length) {
3700                         secret.data = new_val->data;
3701                         secret.length = new_val->length;
3702
3703                         /* Encrypt */
3704                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3705                         if (!crypt_secret.length) {
3706                                 return NT_STATUS_NO_MEMORY;
3707                         }
3708                         r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3709                         if (!r->out.new_val->buf) {
3710                                 return NT_STATUS_NO_MEMORY;
3711                         }
3712                         r->out.new_val->buf->length = crypt_secret.length;
3713                         r->out.new_val->buf->size = crypt_secret.length;
3714                         r->out.new_val->buf->data = crypt_secret.data;
3715                 }
3716         }
3717
3718         if (r->in.new_mtime) {
3719                 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3720                 if (!r->out.new_mtime) {
3721                         return NT_STATUS_NO_MEMORY;
3722                 }
3723                 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3724         }
3725
3726         return NT_STATUS_OK;
3727 }
3728
3729
3730 /*
3731   lsa_LookupPrivValue
3732 */
3733 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3734                                     TALLOC_CTX *mem_ctx,
3735                                     struct lsa_LookupPrivValue *r)
3736 {
3737         struct dcesrv_handle *h;
3738         int id;
3739
3740         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3741
3742         id = sec_privilege_id(r->in.name->string);
3743         if (id == SEC_PRIV_INVALID) {
3744                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3745         }
3746
3747         r->out.luid->low = id;
3748         r->out.luid->high = 0;
3749
3750         return NT_STATUS_OK;
3751 }
3752
3753
3754 /*
3755   lsa_LookupPrivName
3756 */
3757 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3758                                    TALLOC_CTX *mem_ctx,
3759                                    struct lsa_LookupPrivName *r)
3760 {
3761         struct dcesrv_handle *h;
3762         struct lsa_StringLarge *name;
3763         const char *privname;
3764
3765         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3766
3767         if (r->in.luid->high != 0) {
3768                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3769         }
3770
3771         privname = sec_privilege_name(r->in.luid->low);
3772         if (privname == NULL) {
3773                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3774         }
3775
3776         name = talloc(mem_ctx, struct lsa_StringLarge);
3777         if (name == NULL) {
3778                 return NT_STATUS_NO_MEMORY;
3779         }
3780
3781         name->string = privname;
3782
3783         *r->out.name = name;
3784
3785         return NT_STATUS_OK;
3786 }
3787
3788
3789 /*
3790   lsa_LookupPrivDisplayName
3791 */
3792 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3793                                           TALLOC_CTX *mem_ctx,
3794                                           struct lsa_LookupPrivDisplayName *r)
3795 {
3796         struct dcesrv_handle *h;
3797         struct lsa_StringLarge *disp_name = NULL;
3798         enum sec_privilege id;
3799
3800         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3801
3802         id = sec_privilege_id(r->in.name->string);
3803         if (id == SEC_PRIV_INVALID) {
3804                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3805         }
3806
3807         disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3808         if (disp_name == NULL) {
3809                 return NT_STATUS_NO_MEMORY;
3810         }
3811
3812         disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3813         if (disp_name->string == NULL) {
3814                 return NT_STATUS_INTERNAL_ERROR;
3815         }
3816
3817         *r->out.disp_name = disp_name;
3818         *r->out.returned_language_id = 0;
3819
3820         return NT_STATUS_OK;
3821 }
3822
3823
3824 /*
3825   lsa_EnumAccountsWithUserRight
3826 */
3827 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3828                                               TALLOC_CTX *mem_ctx,
3829                                               struct lsa_EnumAccountsWithUserRight *r)
3830 {
3831         struct dcesrv_handle *h;
3832         struct lsa_policy_state *state;
3833         int ret, i;
3834         struct ldb_message **res;
3835         const char * const attrs[] = { "objectSid", NULL};
3836         const char *privname;
3837         bool ok;
3838
3839         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3840
3841         state = h->data;
3842
3843         if (r->in.name == NULL) {
3844                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3845         }
3846
3847         privname = r->in.name->string;
3848
3849         ok = dcesrc_lsa_valid_AccountRight(privname);
3850         if (!ok) {
3851                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3852         }
3853
3854         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3855                            "privilege=%s", privname);
3856         if (ret < 0) {
3857                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3858         }
3859         if (ret == 0) {
3860                 return NT_STATUS_NO_MORE_ENTRIES;
3861         }
3862
3863         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3864         if (r->out.sids->sids == NULL) {
3865                 return NT_STATUS_NO_MEMORY;
3866         }
3867         for (i=0;i<ret;i++) {
3868                 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3869                                                                 res[i], "objectSid");
3870                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3871         }
3872         r->out.sids->num_sids = ret;
3873
3874         return NT_STATUS_OK;
3875 }
3876
3877
3878 /*
3879   lsa_AddAccountRights
3880 */
3881 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3882                                      TALLOC_CTX *mem_ctx,
3883                                      struct lsa_AddAccountRights *r)
3884 {
3885         struct dcesrv_handle *h;
3886         struct lsa_policy_state *state;
3887
3888         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3889
3890         state = h->data;
3891
3892         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3893                                           LDB_FLAG_MOD_ADD,
3894                                           r->in.sid, r->in.rights);
3895 }
3896
3897
3898 /*
3899   lsa_RemoveAccountRights
3900 */
3901 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3902                                         TALLOC_CTX *mem_ctx,
3903                                         struct lsa_RemoveAccountRights *r)
3904 {
3905         struct dcesrv_handle *h;
3906         struct lsa_policy_state *state;
3907
3908         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3909
3910         state = h->data;
3911
3912         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3913                                           LDB_FLAG_MOD_DELETE,
3914                                           r->in.sid, r->in.rights);
3915 }
3916
3917
3918 /*
3919   lsa_StorePrivateData
3920 */
3921 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3922                        struct lsa_StorePrivateData *r)
3923 {
3924         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3925 }
3926
3927
3928 /*
3929   lsa_RetrievePrivateData
3930 */
3931 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3932                        struct lsa_RetrievePrivateData *r)
3933 {
3934         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3935 }
3936
3937
3938 /*
3939   lsa_GetUserName
3940 */
3941 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3942                                 struct lsa_GetUserName *r)
3943 {
3944         enum dcerpc_transport_t transport =
3945                 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
3946         NTSTATUS status = NT_STATUS_OK;
3947         const char *account_name;
3948         const char *authority_name;
3949         struct lsa_String *_account_name;
3950         struct lsa_String *_authority_name = NULL;
3951
3952         if (transport != NCACN_NP && transport != NCALRPC) {
3953                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3954         }
3955
3956         /* this is what w2k3 does */
3957         r->out.account_name = r->in.account_name;
3958         r->out.authority_name = r->in.authority_name;
3959
3960         if (r->in.account_name
3961             && *r->in.account_name
3962             /* && *(*r->in.account_name)->string */
3963             ) {
3964                 return NT_STATUS_INVALID_PARAMETER;
3965         }
3966
3967         if (r->in.authority_name
3968             && *r->in.authority_name
3969             /* && *(*r->in.authority_name)->string */
3970             ) {
3971                 return NT_STATUS_INVALID_PARAMETER;
3972         }
3973
3974         account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3975         authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3976
3977         _account_name = talloc(mem_ctx, struct lsa_String);
3978         NT_STATUS_HAVE_NO_MEMORY(_account_name);
3979         _account_name->string = account_name;
3980
3981         if (r->in.authority_name) {
3982                 _authority_name = talloc(mem_ctx, struct lsa_String);
3983                 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3984                 _authority_name->string = authority_name;
3985         }
3986
3987         *r->out.account_name = _account_name;
3988         if (r->out.authority_name) {
3989                 *r->out.authority_name = _authority_name;
3990         }
3991
3992         return status;
3993 }
3994
3995 /*
3996   lsa_SetInfoPolicy2
3997 */
3998 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3999                                    TALLOC_CTX *mem_ctx,
4000                                    struct lsa_SetInfoPolicy2 *r)
4001 {
4002         /* need to support these */
4003         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4004 }
4005
4006 static void kdc_get_policy(TALLOC_CTX *mem_ctx,
4007                            struct loadparm_context *lp_ctx,
4008                            struct smb_krb5_context *smb_krb5_context,
4009                            struct lsa_DomainInfoKerberos *k)
4010 {
4011         time_t svc_tkt_lifetime;
4012         time_t usr_tkt_lifetime;
4013         time_t renewal_lifetime;
4014
4015         /* Our KDC always re-validates the client */
4016         k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
4017
4018         lpcfg_default_kdc_policy(mem_ctx, lp_ctx, &svc_tkt_lifetime,
4019                                  &usr_tkt_lifetime, &renewal_lifetime);
4020
4021         unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
4022         unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
4023         unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
4024 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
4025         However in the parent function we basically just did a full
4026         krb5_context init with the only purpose of getting a global
4027         config option (the max skew), it would probably make more sense
4028         to have a lp_ or ldb global option as the samba default */
4029         if (smb_krb5_context) {
4030                 unix_to_nt_time(&k->clock_skew,
4031                                 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
4032         }
4033 #endif
4034         k->reserved = 0;
4035 }
4036 /*
4037   lsa_QueryDomainInformationPolicy
4038 */
4039 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4040                                                  TALLOC_CTX *mem_ctx,
4041                                                  struct lsa_QueryDomainInformationPolicy *r)
4042 {
4043         union lsa_DomainInformationPolicy *info;
4044
4045         info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
4046         if (!info) {
4047                 return NT_STATUS_NO_MEMORY;
4048         }
4049
4050         switch (r->in.level) {
4051         case LSA_DOMAIN_INFO_POLICY_EFS:
4052                 talloc_free(info);
4053                 *r->out.info = NULL;
4054                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4055         case LSA_DOMAIN_INFO_POLICY_KERBEROS:
4056         {
4057                 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
4058                 struct smb_krb5_context *smb_krb5_context;
4059                 int ret = smb_krb5_init_context(mem_ctx,
4060                                                         dce_call->conn->dce_ctx->lp_ctx,
4061                                                         &smb_krb5_context);
4062                 if (ret != 0) {
4063                         talloc_free(info);
4064                         *r->out.info = NULL;
4065                         return NT_STATUS_INTERNAL_ERROR;
4066                 }
4067                 kdc_get_policy(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
4068                                smb_krb5_context,
4069                                k);
4070                 talloc_free(smb_krb5_context);
4071                 *r->out.info = info;
4072                 return NT_STATUS_OK;
4073         }
4074         default:
4075                 talloc_free(info);
4076                 *r->out.info = NULL;
4077                 return NT_STATUS_INVALID_INFO_CLASS;
4078         }
4079 }
4080
4081 /*
4082   lsa_SetDomInfoPolicy
4083 */
4084 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4085                                               TALLOC_CTX *mem_ctx,
4086                                               struct lsa_SetDomainInformationPolicy *r)
4087 {
4088         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4089 }
4090
4091 /*
4092   lsa_TestCall
4093 */
4094 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
4095                              TALLOC_CTX *mem_ctx,
4096                              struct lsa_TestCall *r)
4097 {
4098         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4099 }
4100
4101 /*
4102   lsa_CREDRWRITE
4103 */
4104 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4105                        struct lsa_CREDRWRITE *r)
4106 {
4107         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4108 }
4109
4110
4111 /*
4112   lsa_CREDRREAD
4113 */
4114 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4115                        struct lsa_CREDRREAD *r)
4116 {
4117         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4118 }
4119
4120
4121 /*
4122   lsa_CREDRENUMERATE
4123 */
4124 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4125                        struct lsa_CREDRENUMERATE *r)
4126 {
4127         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4128 }
4129
4130
4131 /*
4132   lsa_CREDRWRITEDOMAINCREDENTIALS
4133 */
4134 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4135                        struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
4136 {
4137         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4138 }
4139
4140
4141 /*
4142   lsa_CREDRREADDOMAINCREDENTIALS
4143 */
4144 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4145                        struct lsa_CREDRREADDOMAINCREDENTIALS *r)
4146 {
4147         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4148 }
4149
4150
4151 /*
4152   lsa_CREDRDELETE
4153 */
4154 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4155                        struct lsa_CREDRDELETE *r)
4156 {
4157         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4158 }
4159
4160
4161 /*
4162   lsa_CREDRGETTARGETINFO
4163 */
4164 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4165                        struct lsa_CREDRGETTARGETINFO *r)
4166 {
4167         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4168 }
4169
4170
4171 /*
4172   lsa_CREDRPROFILELOADED
4173 */
4174 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4175                        struct lsa_CREDRPROFILELOADED *r)
4176 {
4177         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4178 }
4179
4180
4181 /*
4182   lsa_CREDRGETSESSIONTYPES
4183 */
4184 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4185                        struct lsa_CREDRGETSESSIONTYPES *r)
4186 {
4187         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4188 }
4189
4190
4191 /*
4192   lsa_LSARREGISTERAUDITEVENT
4193 */
4194 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4195                        struct lsa_LSARREGISTERAUDITEVENT *r)
4196 {
4197         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4198 }
4199
4200
4201 /*
4202   lsa_LSARGENAUDITEVENT
4203 */
4204 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4205                        struct lsa_LSARGENAUDITEVENT *r)
4206 {
4207         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4208 }
4209
4210
4211 /*
4212   lsa_LSARUNREGISTERAUDITEVENT
4213 */
4214 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4215                        struct lsa_LSARUNREGISTERAUDITEVENT *r)
4216 {
4217         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4218 }
4219
4220
4221 /*
4222   lsa_lsaRQueryForestTrustInformation
4223 */
4224 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4225                        struct lsa_lsaRQueryForestTrustInformation *r)
4226 {
4227         struct dcesrv_handle *h = NULL;
4228         struct lsa_policy_state *p_state = NULL;
4229         int forest_level = DS_DOMAIN_FUNCTION_2000;
4230         const char * const trust_attrs[] = {
4231                 "securityIdentifier",
4232                 "flatName",
4233                 "trustPartner",
4234                 "trustAttributes",
4235                 "trustDirection",
4236                 "trustType",
4237                 "msDS-TrustForestTrustInfo",
4238                 NULL
4239         };
4240         struct ldb_message *trust_tdo_msg = NULL;
4241         struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4242         struct ForestTrustInfo *trust_fti = NULL;
4243         struct lsa_ForestTrustInformation *trust_lfti = NULL;
4244         NTSTATUS status;
4245
4246         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4247
4248         p_state = h->data;
4249
4250         if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4251                 return NT_STATUS_INVALID_DOMAIN_STATE;
4252         }
4253
4254         forest_level = dsdb_forest_functional_level(p_state->sam_ldb);
4255         if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4256                 return NT_STATUS_INVALID_DOMAIN_STATE;
4257         }
4258
4259         if (r->in.trusted_domain_name->string == NULL) {
4260                 return NT_STATUS_NO_SUCH_DOMAIN;
4261         }
4262
4263         status = dsdb_trust_search_tdo(p_state->sam_ldb,
4264                                        r->in.trusted_domain_name->string,
4265                                        r->in.trusted_domain_name->string,
4266                                        trust_attrs, mem_ctx, &trust_tdo_msg);
4267         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4268                 return NT_STATUS_NO_SUCH_DOMAIN;
4269         }
4270         if (!NT_STATUS_IS_OK(status)) {
4271                 return status;
4272         }
4273
4274         status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4275         if (!NT_STATUS_IS_OK(status)) {
4276                 return status;
4277         }
4278
4279         if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4280                 return NT_STATUS_INVALID_PARAMETER;
4281         }
4282
4283         if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4284                 return NT_STATUS_INVALID_PARAMETER;
4285         }
4286
4287         status = dsdb_trust_parse_forest_info(mem_ctx,
4288                                               trust_tdo_msg,
4289                                               &trust_fti);
4290         if (!NT_STATUS_IS_OK(status)) {
4291                 return status;
4292         }
4293
4294         status = dsdb_trust_forest_info_to_lsa(mem_ctx, trust_fti,
4295                                                &trust_lfti);
4296         if (!NT_STATUS_IS_OK(status)) {
4297                 return status;
4298         }
4299
4300         *r->out.forest_trust_info = trust_lfti;
4301         return NT_STATUS_OK;
4302 }
4303
4304 /*
4305   lsa_lsaRSetForestTrustInformation
4306 */
4307 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4308                                                          TALLOC_CTX *mem_ctx,
4309                                                          struct lsa_lsaRSetForestTrustInformation *r)
4310 {
4311         struct dcesrv_handle *h;
4312         struct lsa_policy_state *p_state;
4313         const char * const trust_attrs[] = {
4314                 "securityIdentifier",
4315                 "flatName",
4316                 "trustPartner",
4317                 "trustAttributes",
4318                 "trustDirection",
4319                 "trustType",
4320                 "msDS-TrustForestTrustInfo",
4321                 NULL
4322         };
4323         struct ldb_message *trust_tdo_msg = NULL;
4324         struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4325         struct lsa_ForestTrustInformation *step1_lfti = NULL;
4326         struct lsa_ForestTrustInformation *step2_lfti = NULL;
4327         struct ForestTrustInfo *trust_fti = NULL;
4328         struct ldb_result *trusts_res = NULL;
4329         unsigned int i;
4330         struct lsa_TrustDomainInfoInfoEx *xref_tdo = NULL;
4331         struct lsa_ForestTrustInformation *xref_lfti = NULL;
4332         struct lsa_ForestTrustCollisionInfo *c_info = NULL;
4333         DATA_BLOB ft_blob = {};
4334         struct ldb_message *msg = NULL;
4335         struct server_id *server_ids = NULL;
4336         uint32_t num_server_ids = 0;
4337         NTSTATUS status;
4338         enum ndr_err_code ndr_err;
4339         int ret;
4340         bool in_transaction = false;
4341
4342         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4343
4344         p_state = h->data;
4345
4346         if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4347                 return NT_STATUS_INVALID_DOMAIN_STATE;
4348         }
4349
4350         if (r->in.check_only == 0) {
4351                 ret = ldb_transaction_start(p_state->sam_ldb);
4352                 if (ret != LDB_SUCCESS) {
4353                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
4354                 }
4355                 in_transaction = true;
4356         }
4357
4358         /*
4359          * abort if we are not a PDC
4360          *
4361          * In future we should use a function like IsEffectiveRoleOwner()
4362          */
4363         if (!samdb_is_pdc(p_state->sam_ldb)) {
4364                 status = NT_STATUS_INVALID_DOMAIN_ROLE;
4365                 goto done;
4366         }
4367
4368         if (r->in.trusted_domain_name->string == NULL) {
4369                 status = NT_STATUS_NO_SUCH_DOMAIN;
4370                 goto done;
4371         }
4372
4373         status = dsdb_trust_search_tdo(p_state->sam_ldb,
4374                                        r->in.trusted_domain_name->string,
4375                                        r->in.trusted_domain_name->string,
4376                                        trust_attrs, mem_ctx, &trust_tdo_msg);
4377         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4378                 status = NT_STATUS_NO_SUCH_DOMAIN;
4379                 goto done;
4380         }
4381         if (!NT_STATUS_IS_OK(status)) {
4382                 goto done;
4383         }
4384
4385         status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4386         if (!NT_STATUS_IS_OK(status)) {
4387                 goto done;
4388         }
4389
4390         if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4391                 status = NT_STATUS_INVALID_PARAMETER;
4392                 goto done;
4393         }
4394
4395         if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4396                 status = NT_STATUS_INVALID_PARAMETER;
4397                 goto done;
4398         }
4399
4400         /*
4401          * verify and normalize the given forest trust info.
4402          *
4403          * Step1: doesn't reorder yet, so step1_lfti might contain
4404          * NULL entries. This means dsdb_trust_verify_forest_info()
4405          * can generate collision entries with the callers index.
4406          */
4407         status = dsdb_trust_normalize_forest_info_step1(mem_ctx,
4408                                                         r->in.forest_trust_info,
4409                                                         &step1_lfti);
4410         if (!NT_STATUS_IS_OK(status)) {
4411                 goto done;
4412         }
4413
4414         c_info = talloc_zero(r->out.collision_info,
4415                              struct lsa_ForestTrustCollisionInfo);
4416         if (c_info == NULL) {
4417                 status = NT_STATUS_NO_MEMORY;
4418                 goto done;
4419         }
4420
4421         /*
4422          * First check our own forest, then other domains/forests
4423          */
4424
4425         status = dsdb_trust_xref_tdo_info(mem_ctx, p_state->sam_ldb,
4426                                           &xref_tdo);
4427         if (!NT_STATUS_IS_OK(status)) {
4428                 goto done;
4429         }
4430         status = dsdb_trust_xref_forest_info(mem_ctx, p_state->sam_ldb,
4431                                              &xref_lfti);
4432         if (!NT_STATUS_IS_OK(status)) {
4433                 goto done;
4434         }
4435
4436         /*
4437          * The documentation proposed to generate
4438          * LSA_FOREST_TRUST_COLLISION_XREF collisions.
4439          * But Windows always uses LSA_FOREST_TRUST_COLLISION_TDO.
4440          */
4441         status = dsdb_trust_verify_forest_info(xref_tdo, xref_lfti,
4442                                                LSA_FOREST_TRUST_COLLISION_TDO,
4443                                                c_info, step1_lfti);
4444         if (!NT_STATUS_IS_OK(status)) {
4445                 goto done;
4446         }
4447
4448         /* fetch all other trusted domain objects */
4449         status = dsdb_trust_search_tdos(p_state->sam_ldb,
4450                                         trust_tdo->domain_name.string,
4451                                         trust_attrs,
4452                                         mem_ctx, &trusts_res);
4453         if (!NT_STATUS_IS_OK(status)) {
4454                 goto done;
4455         }
4456
4457         /*
4458          * now check against the other domains.
4459          * and generate LSA_FOREST_TRUST_COLLISION_TDO collisions.
4460          */
4461         for (i = 0; i < trusts_res->count; i++) {
4462                 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
4463                 struct ForestTrustInfo *fti = NULL;
4464                 struct lsa_ForestTrustInformation *lfti = NULL;
4465
4466                 status = dsdb_trust_parse_tdo_info(mem_ctx,
4467                                                    trusts_res->msgs[i],
4468                                                    &tdo);
4469                 if (!NT_STATUS_IS_OK(status)) {
4470                         goto done;
4471                 }
4472
4473                 status = dsdb_trust_parse_forest_info(tdo,
4474                                                       trusts_res->msgs[i],
4475                                                       &fti);
4476                 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
4477                         continue;
4478                 }
4479                 if (!NT_STATUS_IS_OK(status)) {
4480                         goto done;
4481                 }
4482
4483                 status = dsdb_trust_forest_info_to_lsa(tdo, fti, &lfti);
4484                 if (!NT_STATUS_IS_OK(status)) {
4485                         goto done;
4486                 }
4487
4488                 status = dsdb_trust_verify_forest_info(tdo, lfti,
4489                                                 LSA_FOREST_TRUST_COLLISION_TDO,
4490                                                 c_info, step1_lfti);
4491                 if (!NT_STATUS_IS_OK(status)) {
4492                         goto done;
4493                 }
4494
4495                 TALLOC_FREE(tdo);
4496         }
4497
4498         if (r->in.check_only != 0) {
4499                 status = NT_STATUS_OK;
4500                 goto done;
4501         }
4502
4503         /*
4504          * not just a check, write info back
4505          */
4506
4507         /*
4508          * normalize the given forest trust info.
4509          *
4510          * Step2: adds TOP_LEVEL_NAME[_EX] in reverse order,
4511          * followed by DOMAIN_INFO in reverse order. It also removes
4512          * possible NULL entries from Step1.
4513          */
4514         status = dsdb_trust_normalize_forest_info_step2(mem_ctx, step1_lfti,
4515                                                         &step2_lfti);
4516         if (!NT_STATUS_IS_OK(status)) {
4517                 goto done;
4518         }
4519
4520         status = dsdb_trust_forest_info_from_lsa(mem_ctx, step2_lfti,
4521                                                  &trust_fti);
4522         if (!NT_STATUS_IS_OK(status)) {
4523                 goto done;
4524         }
4525
4526         ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, trust_fti,
4527                                        (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4528         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4529                 status = NT_STATUS_INVALID_PARAMETER;
4530                 goto done;
4531         }
4532
4533         msg = ldb_msg_new(mem_ctx);
4534         if (msg == NULL) {
4535                 status = NT_STATUS_NO_MEMORY;
4536                 goto done;
4537         }
4538
4539         msg->dn = ldb_dn_copy(mem_ctx, trust_tdo_msg->dn);
4540         if (!msg->dn) {
4541                 status = NT_STATUS_NO_MEMORY;
4542                 goto done;
4543         }
4544
4545         ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4546                                 LDB_FLAG_MOD_REPLACE, NULL);
4547         if (ret != LDB_SUCCESS) {
4548                 status = NT_STATUS_NO_MEMORY;
4549                 goto done;
4550         }
4551         ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4552                                 &ft_blob, NULL);
4553         if (ret != LDB_SUCCESS) {
4554                 status = NT_STATUS_NO_MEMORY;
4555                 goto done;
4556         }
4557
4558         ret = ldb_modify(p_state->sam_ldb, msg);
4559         if (ret != LDB_SUCCESS) {
4560                 status = dsdb_ldb_err_to_ntstatus(ret);
4561
4562                 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4563                           ldb_errstring(p_state->sam_ldb)));
4564
4565                 goto done;
4566         }
4567
4568         /* ok, all fine, commit transaction and return */
4569         in_transaction = false;
4570         ret = ldb_transaction_commit(p_state->sam_ldb);
4571         if (ret != LDB_SUCCESS) {
4572                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
4573                 goto done;
4574         }
4575
4576         /*
4577          * Notify winbindd that we have a acquired forest trust info
4578          */
4579         status = irpc_servers_byname(dce_call->msg_ctx,
4580                                      mem_ctx,
4581                                      "winbind_server",
4582                                      &num_server_ids, &server_ids);
4583         if (!NT_STATUS_IS_OK(status)) {
4584                 DBG_ERR("irpc_servers_byname failed\n");
4585                 goto done;
4586         }
4587
4588         imessaging_send(dce_call->msg_ctx, server_ids[0],
4589                         MSG_WINBIND_RELOAD_TRUSTED_DOMAINS, NULL);
4590
4591         status = NT_STATUS_OK;
4592
4593 done:
4594         if (NT_STATUS_IS_OK(status) && c_info->count != 0) {
4595                 *r->out.collision_info = c_info;
4596         }
4597
4598         if (in_transaction) {
4599                 ldb_transaction_cancel(p_state->sam_ldb);
4600         }
4601
4602         return status;
4603 }
4604
4605 /*
4606   lsa_CREDRRENAME
4607 */
4608 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4609                        struct lsa_CREDRRENAME *r)
4610 {
4611         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4612 }
4613
4614
4615
4616 /*
4617   lsa_LSAROPENPOLICYSCE
4618 */
4619 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4620                        struct lsa_LSAROPENPOLICYSCE *r)
4621 {
4622         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4623 }
4624
4625
4626 /*
4627   lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4628 */
4629 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4630                        struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4631 {
4632         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4633 }
4634
4635
4636 /*
4637   lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4638 */
4639 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4640                        struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4641 {
4642         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4643 }
4644
4645
4646 /*
4647   lsa_LSARADTREPORTSECURITYEVENT
4648 */
4649 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4650                        struct lsa_LSARADTREPORTSECURITYEVENT *r)
4651 {
4652         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4653 }
4654
4655
4656 /* include the generated boilerplate */
4657 #include "librpc/gen_ndr/ndr_lsa_s.c"
4658
4659
4660
4661 /*****************************************
4662 NOTE! The remaining calls below were
4663 removed in w2k3, so the DCESRV_FAULT()
4664 replies are the correct implementation. Do
4665 not try and fill these in with anything else
4666 ******************************************/
4667
4668 /*
4669   dssetup_DsRoleDnsNameToFlatName
4670 */
4671 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4672                                         struct dssetup_DsRoleDnsNameToFlatName *r)
4673 {
4674         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4675 }
4676
4677
4678 /*
4679   dssetup_DsRoleDcAsDc
4680 */
4681 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4682                              struct dssetup_DsRoleDcAsDc *r)
4683 {
4684         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4685 }
4686
4687
4688 /*
4689   dssetup_DsRoleDcAsReplica
4690 */
4691 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4692                                   struct dssetup_DsRoleDcAsReplica *r)
4693 {
4694         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4695 }
4696
4697
4698 /*
4699   dssetup_DsRoleDemoteDc
4700 */
4701 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4702                                struct dssetup_DsRoleDemoteDc *r)
4703 {
4704         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4705 }
4706
4707
4708 /*
4709   dssetup_DsRoleGetDcOperationProgress
4710 */
4711 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4712                                              struct dssetup_DsRoleGetDcOperationProgress *r)
4713 {
4714         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4715 }
4716
4717
4718 /* 
4719   dssetup_DsRoleGetDcOperationResults 
4720 */
4721 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4722                                             struct dssetup_DsRoleGetDcOperationResults *r)
4723 {
4724         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4725 }
4726
4727
4728 /* 
4729   dssetup_DsRoleCancel 
4730 */
4731 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4732                              struct dssetup_DsRoleCancel *r)
4733 {
4734         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4735 }
4736
4737
4738 /*
4739   dssetup_DsRoleServerSaveStateForUpgrade
4740 */
4741 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4742                                                 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4743 {
4744         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4745 }
4746
4747
4748 /*
4749   dssetup_DsRoleUpgradeDownlevelServer
4750 */
4751 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4752                                              struct dssetup_DsRoleUpgradeDownlevelServer *r)
4753 {
4754         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4755 }
4756
4757
4758 /*
4759   dssetup_DsRoleAbortDownlevelServerUpgrade
4760 */
4761 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4762                                                   struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4763 {
4764         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4765 }
4766
4767
4768 /* include the generated boilerplate */
4769 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4770
4771 NTSTATUS dcerpc_server_lsa_init(TALLOC_CTX *ctx)
4772 {
4773         NTSTATUS ret;
4774
4775         ret = dcerpc_server_dssetup_init(ctx);
4776         if (!NT_STATUS_IS_OK(ret)) {
4777                 return ret;
4778         }
4779         ret = dcerpc_server_lsarpc_init(ctx);
4780         if (!NT_STATUS_IS_OK(ret)) {
4781                 return ret;
4782         }
4783         return ret;
4784 }