lsasrv: Fix CID 241332 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
2661         if (r->out.domains->count < count - *r->in.resume_handle) {
2662                 *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2663                 return STATUS_MORE_ENTRIES;
2664         }
2665
2666         *r->out.resume_handle = *r->in.resume_handle + r->out.domains->count;
2667
2668         return NT_STATUS_OK;
2669 }
2670
2671
2672 /*
2673   lsa_OpenAccount
2674 */
2675 static NTSTATUS dcesrv_lsa_OpenAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2676                                 struct lsa_OpenAccount *r)
2677 {
2678         struct dcesrv_handle *h, *ah;
2679         struct lsa_policy_state *state;
2680         struct lsa_account_state *astate;
2681
2682         ZERO_STRUCTP(r->out.acct_handle);
2683
2684         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2685
2686         state = h->data;
2687
2688         astate = talloc(dce_call->conn, struct lsa_account_state);
2689         if (astate == NULL) {
2690                 return NT_STATUS_NO_MEMORY;
2691         }
2692
2693         astate->account_sid = dom_sid_dup(astate, r->in.sid);
2694         if (astate->account_sid == NULL) {
2695                 talloc_free(astate);
2696                 return NT_STATUS_NO_MEMORY;
2697         }
2698
2699         astate->policy = talloc_reference(astate, state);
2700         astate->access_mask = r->in.access_mask;
2701
2702         /*
2703          * For now we grant all requested access.
2704          *
2705          * We will fail at the ldb layer later.
2706          */
2707         if (astate->access_mask & SEC_FLAG_MAXIMUM_ALLOWED) {
2708                 astate->access_mask &= ~SEC_FLAG_MAXIMUM_ALLOWED;
2709                 astate->access_mask |= LSA_ACCOUNT_ALL_ACCESS;
2710         }
2711         se_map_generic(&astate->access_mask, &dcesrv_lsa_account_mapping);
2712
2713         DEBUG(10,("%s: %s access desired[0x%08X] granted[0x%08X] - success.\n",
2714                   __func__, dom_sid_string(mem_ctx, astate->account_sid),
2715                  (unsigned)r->in.access_mask,
2716                  (unsigned)astate->access_mask));
2717
2718         ah = dcesrv_handle_new(dce_call->context, LSA_HANDLE_ACCOUNT);
2719         if (!ah) {
2720                 talloc_free(astate);
2721                 return NT_STATUS_NO_MEMORY;
2722         }
2723
2724         ah->data = talloc_steal(ah, astate);
2725
2726         *r->out.acct_handle = ah->wire_handle;
2727
2728         return NT_STATUS_OK;
2729 }
2730
2731
2732 /*
2733   lsa_EnumPrivsAccount
2734 */
2735 static NTSTATUS dcesrv_lsa_EnumPrivsAccount(struct dcesrv_call_state *dce_call,
2736                                      TALLOC_CTX *mem_ctx,
2737                                      struct lsa_EnumPrivsAccount *r)
2738 {
2739         struct dcesrv_handle *h;
2740         struct lsa_account_state *astate;
2741         int ret;
2742         unsigned int i, j;
2743         struct ldb_message **res;
2744         const char * const attrs[] = { "privilege", NULL};
2745         struct ldb_message_element *el;
2746         const char *sidstr;
2747         struct lsa_PrivilegeSet *privs;
2748
2749         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
2750
2751         astate = h->data;
2752
2753         privs = talloc(mem_ctx, struct lsa_PrivilegeSet);
2754         if (privs == NULL) {
2755                 return NT_STATUS_NO_MEMORY;
2756         }
2757         privs->count = 0;
2758         privs->unknown = 0;
2759         privs->set = NULL;
2760
2761         *r->out.privs = privs;
2762
2763         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
2764         if (sidstr == NULL) {
2765                 return NT_STATUS_NO_MEMORY;
2766         }
2767
2768         ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
2769                            "objectSid=%s", sidstr);
2770         if (ret < 0) {
2771                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2772         }
2773         if (ret != 1) {
2774                 return NT_STATUS_OK;
2775         }
2776
2777         el = ldb_msg_find_element(res[0], "privilege");
2778         if (el == NULL || el->num_values == 0) {
2779                 return NT_STATUS_OK;
2780         }
2781
2782         privs->set = talloc_array(privs,
2783                                   struct lsa_LUIDAttribute, el->num_values);
2784         if (privs->set == NULL) {
2785                 return NT_STATUS_NO_MEMORY;
2786         }
2787
2788         j = 0;
2789         for (i=0;i<el->num_values;i++) {
2790                 int id = sec_privilege_id((const char *)el->values[i].data);
2791                 if (id == SEC_PRIV_INVALID) {
2792                         /* Perhaps an account right, not a privilege */
2793                         continue;
2794                 }
2795                 privs->set[j].attribute = 0;
2796                 privs->set[j].luid.low = id;
2797                 privs->set[j].luid.high = 0;
2798                 j++;
2799         }
2800
2801         privs->count = j;
2802
2803         return NT_STATUS_OK;
2804 }
2805
2806 /*
2807   lsa_EnumAccountRights
2808 */
2809 static NTSTATUS dcesrv_lsa_EnumAccountRights(struct dcesrv_call_state *dce_call,
2810                                       TALLOC_CTX *mem_ctx,
2811                                       struct lsa_EnumAccountRights *r)
2812 {
2813         struct dcesrv_handle *h;
2814         struct lsa_policy_state *state;
2815         int ret;
2816         unsigned int i;
2817         struct ldb_message **res;
2818         const char * const attrs[] = { "privilege", NULL};
2819         const char *sidstr;
2820         struct ldb_message_element *el;
2821
2822         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
2823
2824         state = h->data;
2825
2826         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, r->in.sid);
2827         if (sidstr == NULL) {
2828                 return NT_STATUS_NO_MEMORY;
2829         }
2830
2831         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
2832                            "(&(objectSid=%s)(privilege=*))", sidstr);
2833         if (ret == 0) {
2834                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2835         }
2836         if (ret != 1) {
2837                 DEBUG(3, ("searching for account rights for SID: %s failed: %s",
2838                           dom_sid_string(mem_ctx, r->in.sid),
2839                           ldb_errstring(state->pdb)));
2840                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
2841         }
2842
2843         el = ldb_msg_find_element(res[0], "privilege");
2844         if (el == NULL || el->num_values == 0) {
2845                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
2846         }
2847
2848         r->out.rights->count = el->num_values;
2849         r->out.rights->names = talloc_array(r->out.rights,
2850                                             struct lsa_StringLarge, r->out.rights->count);
2851         if (r->out.rights->names == NULL) {
2852                 return NT_STATUS_NO_MEMORY;
2853         }
2854
2855         for (i=0;i<el->num_values;i++) {
2856                 r->out.rights->names[i].string = (const char *)el->values[i].data;
2857         }
2858
2859         return NT_STATUS_OK;
2860 }
2861
2862
2863
2864 /*
2865   helper for lsa_AddAccountRights and lsa_RemoveAccountRights
2866 */
2867 static NTSTATUS dcesrv_lsa_AddRemoveAccountRights(struct dcesrv_call_state *dce_call,
2868                                            TALLOC_CTX *mem_ctx,
2869                                            struct lsa_policy_state *state,
2870                                            int ldb_flag,
2871                                            struct dom_sid *sid,
2872                                            const struct lsa_RightSet *rights)
2873 {
2874         const char *sidstr, *sidndrstr;
2875         struct ldb_message *msg;
2876         struct ldb_message_element *el;
2877         int ret;
2878         uint32_t i;
2879         struct lsa_EnumAccountRights r2;
2880         char *dnstr;
2881
2882         if (security_session_user_level(dce_call->conn->auth_state.session_info, NULL) <
2883             SECURITY_ADMINISTRATOR) {
2884                 DEBUG(0,("lsa_AddRemoveAccount refused for supplied security token\n"));
2885                 return NT_STATUS_ACCESS_DENIED;
2886         }
2887
2888         msg = ldb_msg_new(mem_ctx);
2889         if (msg == NULL) {
2890                 return NT_STATUS_NO_MEMORY;
2891         }
2892
2893         sidndrstr = ldap_encode_ndr_dom_sid(msg, sid);
2894         if (sidndrstr == NULL) {
2895                 TALLOC_FREE(msg);
2896                 return NT_STATUS_NO_MEMORY;
2897         }
2898
2899         sidstr = dom_sid_string(msg, sid);
2900         if (sidstr == NULL) {
2901                 TALLOC_FREE(msg);
2902                 return NT_STATUS_NO_MEMORY;
2903         }
2904
2905         dnstr = talloc_asprintf(msg, "sid=%s", sidstr);
2906         if (dnstr == NULL) {
2907                 TALLOC_FREE(msg);
2908                 return NT_STATUS_NO_MEMORY;
2909         }
2910
2911         msg->dn = ldb_dn_new(msg, state->pdb, dnstr);
2912         if (msg->dn == NULL) {
2913                 TALLOC_FREE(msg);
2914                 return NT_STATUS_NO_MEMORY;
2915         }
2916
2917         if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2918                 NTSTATUS status;
2919
2920                 r2.in.handle = &state->handle->wire_handle;
2921                 r2.in.sid = sid;
2922                 r2.out.rights = talloc(mem_ctx, struct lsa_RightSet);
2923
2924                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
2925                 if (!NT_STATUS_IS_OK(status)) {
2926                         ZERO_STRUCTP(r2.out.rights);
2927                 }
2928         }
2929
2930         for (i=0;i<rights->count;i++) {
2931                 bool ok;
2932
2933                 ok = dcesrc_lsa_valid_AccountRight(rights->names[i].string);
2934                 if (!ok) {
2935                         talloc_free(msg);
2936                         return NT_STATUS_NO_SUCH_PRIVILEGE;
2937                 }
2938
2939                 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_ADD) {
2940                         uint32_t j;
2941                         for (j=0;j<r2.out.rights->count;j++) {
2942                                 if (strcasecmp_m(r2.out.rights->names[j].string,
2943                                                rights->names[i].string) == 0) {
2944                                         break;
2945                                 }
2946                         }
2947                         if (j != r2.out.rights->count) continue;
2948                 }
2949
2950                 ret = ldb_msg_add_string(msg, "privilege", rights->names[i].string);
2951                 if (ret != LDB_SUCCESS) {
2952                         talloc_free(msg);
2953                         return NT_STATUS_NO_MEMORY;
2954                 }
2955         }
2956
2957         el = ldb_msg_find_element(msg, "privilege");
2958         if (!el) {
2959                 talloc_free(msg);
2960                 return NT_STATUS_OK;
2961         }
2962
2963         el->flags = ldb_flag;
2964
2965         ret = ldb_modify(state->pdb, msg);
2966         if (ret == LDB_ERR_NO_SUCH_OBJECT) {
2967                 if (samdb_msg_add_dom_sid(state->pdb, msg, msg, "objectSid", sid) != LDB_SUCCESS) {
2968                         talloc_free(msg);
2969                         return NT_STATUS_NO_MEMORY;
2970                 }
2971                 ldb_msg_add_string(msg, "comment", "added via LSA");
2972                 ret = ldb_add(state->pdb, msg);
2973         }
2974         if (ret != LDB_SUCCESS) {
2975                 if (LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE && ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
2976                         talloc_free(msg);
2977                         return NT_STATUS_OK;
2978                 }
2979                 DEBUG(3, ("Could not %s attributes from %s: %s",
2980                           LDB_FLAG_MOD_TYPE(ldb_flag) == LDB_FLAG_MOD_DELETE ? "delete" : "add",
2981                           ldb_dn_get_linearized(msg->dn), ldb_errstring(state->pdb)));
2982                 talloc_free(msg);
2983                 return NT_STATUS_UNEXPECTED_IO_ERROR;
2984         }
2985
2986         talloc_free(msg);
2987         return NT_STATUS_OK;
2988 }
2989
2990 /*
2991   lsa_AddPrivilegesToAccount
2992 */
2993 static NTSTATUS dcesrv_lsa_AddPrivilegesToAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
2994                                            struct lsa_AddPrivilegesToAccount *r)
2995 {
2996         struct lsa_RightSet rights;
2997         struct dcesrv_handle *h;
2998         struct lsa_account_state *astate;
2999         uint32_t i;
3000
3001         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3002
3003         astate = h->data;
3004
3005         rights.count = r->in.privs->count;
3006         rights.names = talloc_array(mem_ctx, struct lsa_StringLarge, rights.count);
3007         if (rights.names == NULL) {
3008                 return NT_STATUS_NO_MEMORY;
3009         }
3010         for (i=0;i<rights.count;i++) {
3011                 int id = r->in.privs->set[i].luid.low;
3012                 if (r->in.privs->set[i].luid.high) {
3013                         return NT_STATUS_NO_SUCH_PRIVILEGE;
3014                 }
3015                 rights.names[i].string = sec_privilege_name(id);
3016                 if (rights.names[i].string == NULL) {
3017                         return NT_STATUS_NO_SUCH_PRIVILEGE;
3018                 }
3019         }
3020
3021         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3022                                           LDB_FLAG_MOD_ADD, astate->account_sid,
3023                                           &rights);
3024 }
3025
3026
3027 /*
3028   lsa_RemovePrivilegesFromAccount
3029 */
3030 static NTSTATUS dcesrv_lsa_RemovePrivilegesFromAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3031                                                 struct lsa_RemovePrivilegesFromAccount *r)
3032 {
3033         struct lsa_RightSet *rights;
3034         struct dcesrv_handle *h;
3035         struct lsa_account_state *astate;
3036         uint32_t i;
3037
3038         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3039
3040         astate = h->data;
3041
3042         rights = talloc(mem_ctx, struct lsa_RightSet);
3043
3044         if (r->in.remove_all == 1 &&
3045             r->in.privs == NULL) {
3046                 struct lsa_EnumAccountRights r2;
3047                 NTSTATUS status;
3048
3049                 r2.in.handle = &astate->policy->handle->wire_handle;
3050                 r2.in.sid = astate->account_sid;
3051                 r2.out.rights = rights;
3052
3053                 status = dcesrv_lsa_EnumAccountRights(dce_call, mem_ctx, &r2);
3054                 if (!NT_STATUS_IS_OK(status)) {
3055                         return status;
3056                 }
3057
3058                 return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3059                                                   LDB_FLAG_MOD_DELETE, astate->account_sid,
3060                                                   r2.out.rights);
3061         }
3062
3063         if (r->in.remove_all != 0) {
3064                 return NT_STATUS_INVALID_PARAMETER;
3065         }
3066
3067         rights->count = r->in.privs->count;
3068         rights->names = talloc_array(mem_ctx, struct lsa_StringLarge, rights->count);
3069         if (rights->names == NULL) {
3070                 return NT_STATUS_NO_MEMORY;
3071         }
3072         for (i=0;i<rights->count;i++) {
3073                 int id = r->in.privs->set[i].luid.low;
3074                 if (r->in.privs->set[i].luid.high) {
3075                         return NT_STATUS_NO_SUCH_PRIVILEGE;
3076                 }
3077                 rights->names[i].string = sec_privilege_name(id);
3078                 if (rights->names[i].string == NULL) {
3079                         return NT_STATUS_NO_SUCH_PRIVILEGE;
3080                 }
3081         }
3082
3083         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, astate->policy,
3084                                           LDB_FLAG_MOD_DELETE, astate->account_sid,
3085                                           rights);
3086 }
3087
3088
3089 /*
3090   lsa_GetQuotasForAccount
3091 */
3092 static NTSTATUS dcesrv_lsa_GetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3093                        struct lsa_GetQuotasForAccount *r)
3094 {
3095         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3096 }
3097
3098
3099 /*
3100   lsa_SetQuotasForAccount
3101 */
3102 static NTSTATUS dcesrv_lsa_SetQuotasForAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3103                        struct lsa_SetQuotasForAccount *r)
3104 {
3105         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3106 }
3107
3108
3109 /*
3110   lsa_GetSystemAccessAccount
3111 */
3112 static NTSTATUS dcesrv_lsa_GetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3113                        struct lsa_GetSystemAccessAccount *r)
3114 {
3115         struct dcesrv_handle *h;
3116         struct lsa_account_state *astate;
3117         int ret;
3118         unsigned int i;
3119         struct ldb_message **res;
3120         const char * const attrs[] = { "privilege", NULL};
3121         struct ldb_message_element *el;
3122         const char *sidstr;
3123
3124         *(r->out.access_mask) = 0x00000000;
3125
3126         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_ACCOUNT);
3127
3128         astate = h->data;
3129
3130         sidstr = ldap_encode_ndr_dom_sid(mem_ctx, astate->account_sid);
3131         if (sidstr == NULL) {
3132                 return NT_STATUS_NO_MEMORY;
3133         }
3134
3135         ret = gendb_search(astate->policy->pdb, mem_ctx, NULL, &res, attrs,
3136                            "objectSid=%s", sidstr);
3137         if (ret < 0) {
3138                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3139         }
3140         if (ret != 1) {
3141                 return NT_STATUS_OK;
3142         }
3143
3144         el = ldb_msg_find_element(res[0], "privilege");
3145         if (el == NULL || el->num_values == 0) {
3146                 return NT_STATUS_OK;
3147         }
3148
3149         for (i=0;i<el->num_values;i++) {
3150                 uint32_t right_bit = sec_right_bit((const char *)el->values[i].data);
3151                 if (right_bit == 0) {
3152                         /* Perhaps an privilege, not a right */
3153                         continue;
3154                 }
3155                 *(r->out.access_mask) |= right_bit;
3156         }
3157
3158         return NT_STATUS_OK;
3159 }
3160
3161
3162 /*
3163   lsa_SetSystemAccessAccount
3164 */
3165 static NTSTATUS dcesrv_lsa_SetSystemAccessAccount(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3166                        struct lsa_SetSystemAccessAccount *r)
3167 {
3168         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3169 }
3170
3171
3172 /*
3173   lsa_CreateSecret
3174 */
3175 static NTSTATUS dcesrv_lsa_CreateSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3176                                  struct lsa_CreateSecret *r)
3177 {
3178         struct dcesrv_handle *policy_handle;
3179         struct lsa_policy_state *policy_state;
3180         struct lsa_secret_state *secret_state;
3181         struct dcesrv_handle *handle;
3182         struct ldb_message **msgs, *msg;
3183         const char *attrs[] = {
3184                 NULL
3185         };
3186
3187         const char *name;
3188
3189         int ret;
3190
3191         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3192         ZERO_STRUCTP(r->out.sec_handle);
3193
3194         switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3195         {
3196         case SECURITY_SYSTEM:
3197         case SECURITY_ADMINISTRATOR:
3198                 break;
3199         default:
3200                 /* Users and annonymous are not allowed create secrets */
3201                 return NT_STATUS_ACCESS_DENIED;
3202         }
3203
3204         policy_state = policy_handle->data;
3205
3206         if (!r->in.name.string) {
3207                 return NT_STATUS_INVALID_PARAMETER;
3208         }
3209
3210         secret_state = talloc(mem_ctx, struct lsa_secret_state);
3211         NT_STATUS_HAVE_NO_MEMORY(secret_state);
3212         secret_state->policy = policy_state;
3213
3214         msg = ldb_msg_new(mem_ctx);
3215         if (msg == NULL) {
3216                 return NT_STATUS_NO_MEMORY;
3217         }
3218
3219         if (strncmp("G$", r->in.name.string, 2) == 0) {
3220                 const char *name2;
3221
3222                 secret_state->global = true;
3223
3224                 name = &r->in.name.string[2];
3225                 if (strlen(name) == 0) {
3226                         return NT_STATUS_INVALID_PARAMETER;
3227                 }
3228
3229                 name2 = talloc_asprintf(mem_ctx, "%s Secret",
3230                                         ldb_binary_encode_string(mem_ctx, name));
3231                 NT_STATUS_HAVE_NO_MEMORY(name2);
3232
3233                 /* We need to connect to the database as system, as this is one
3234                  * of the rare RPC calls that must read the secrets (and this
3235                  * is denied otherwise) */
3236                 secret_state->sam_ldb = talloc_reference(secret_state,
3237                                                          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));
3238                 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3239
3240                 /* search for the secret record */
3241                 ret = gendb_search(secret_state->sam_ldb,
3242                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
3243                                    "(&(cn=%s)(objectclass=secret))",
3244                                    name2);
3245                 if (ret > 0) {
3246                         return NT_STATUS_OBJECT_NAME_COLLISION;
3247                 }
3248
3249                 if (ret < 0) {
3250                         DEBUG(0,("Failure searching for CN=%s: %s\n",
3251                                  name2, ldb_errstring(secret_state->sam_ldb)));
3252                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3253                 }
3254
3255                 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
3256                 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3257                 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
3258                         return NT_STATUS_NO_MEMORY;
3259                 }
3260
3261                 ret = ldb_msg_add_string(msg, "cn", name2);
3262                 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3263         } else {
3264                 secret_state->global = false;
3265
3266                 name = r->in.name.string;
3267                 if (strlen(name) == 0) {
3268                         return NT_STATUS_INVALID_PARAMETER;
3269                 }
3270
3271                 secret_state->sam_ldb = talloc_reference(secret_state,
3272                                                          secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3273                 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3274
3275                 /* search for the secret record */
3276                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3277                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3278                                    &msgs, attrs,
3279                                    "(&(cn=%s)(objectclass=secret))",
3280                                    ldb_binary_encode_string(mem_ctx, name));
3281                 if (ret > 0) {
3282                         return NT_STATUS_OBJECT_NAME_COLLISION;
3283                 }
3284
3285                 if (ret < 0) {
3286                         DEBUG(0,("Failure searching for CN=%s: %s\n",
3287                                  name, ldb_errstring(secret_state->sam_ldb)));
3288                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3289                 }
3290
3291                 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
3292                                          "cn=%s,cn=LSA Secrets", name);
3293                 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3294                 ret = ldb_msg_add_string(msg, "cn", name);
3295                 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3296         }
3297
3298         ret = ldb_msg_add_string(msg, "objectClass", "secret");
3299         if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3300
3301         secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3302         NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3303
3304         /* create the secret */
3305         ret = ldb_add(secret_state->sam_ldb, msg);
3306         if (ret != LDB_SUCCESS) {
3307                 DEBUG(0,("Failed to create secret record %s: %s\n",
3308                          ldb_dn_get_linearized(msg->dn),
3309                          ldb_errstring(secret_state->sam_ldb)));
3310                 return NT_STATUS_ACCESS_DENIED;
3311         }
3312
3313         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3314         NT_STATUS_HAVE_NO_MEMORY(handle);
3315
3316         handle->data = talloc_steal(handle, secret_state);
3317
3318         secret_state->access_mask = r->in.access_mask;
3319         secret_state->policy = talloc_reference(secret_state, policy_state);
3320         NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3321
3322         *r->out.sec_handle = handle->wire_handle;
3323
3324         return NT_STATUS_OK;
3325 }
3326
3327
3328 /*
3329   lsa_OpenSecret
3330 */
3331 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3332                                struct lsa_OpenSecret *r)
3333 {
3334         struct dcesrv_handle *policy_handle;
3335
3336         struct lsa_policy_state *policy_state;
3337         struct lsa_secret_state *secret_state;
3338         struct dcesrv_handle *handle;
3339         struct ldb_message **msgs;
3340         const char *attrs[] = {
3341                 NULL
3342         };
3343
3344         const char *name;
3345
3346         int ret;
3347
3348         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3349         ZERO_STRUCTP(r->out.sec_handle);
3350         policy_state = policy_handle->data;
3351
3352         if (!r->in.name.string) {
3353                 return NT_STATUS_INVALID_PARAMETER;
3354         }
3355
3356         switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3357         {
3358         case SECURITY_SYSTEM:
3359         case SECURITY_ADMINISTRATOR:
3360                 break;
3361         default:
3362                 /* Users and annonymous are not allowed to access secrets */
3363                 return NT_STATUS_ACCESS_DENIED;
3364         }
3365
3366         secret_state = talloc(mem_ctx, struct lsa_secret_state);
3367         if (!secret_state) {
3368                 return NT_STATUS_NO_MEMORY;
3369         }
3370         secret_state->policy = policy_state;
3371
3372         if (strncmp("G$", r->in.name.string, 2) == 0) {
3373                 name = &r->in.name.string[2];
3374                 /* 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) */
3375                 secret_state->sam_ldb = talloc_reference(secret_state,
3376                                                          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));
3377                 secret_state->global = true;
3378
3379                 if (strlen(name) < 1) {
3380                         return NT_STATUS_INVALID_PARAMETER;
3381                 }
3382
3383                 /* search for the secret record */
3384                 ret = gendb_search(secret_state->sam_ldb,
3385                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
3386                                    "(&(cn=%s Secret)(objectclass=secret))",
3387                                    ldb_binary_encode_string(mem_ctx, name));
3388                 if (ret == 0) {
3389                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3390                 }
3391
3392                 if (ret != 1) {
3393                         DEBUG(0,("Found %d records matching DN %s\n", ret,
3394                                  ldb_dn_get_linearized(policy_state->system_dn)));
3395                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3396                 }
3397         } else {
3398                 secret_state->global = false;
3399                 secret_state->sam_ldb = talloc_reference(secret_state,
3400                                                          secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3401
3402                 name = r->in.name.string;
3403                 if (strlen(name) < 1) {
3404                         return NT_STATUS_INVALID_PARAMETER;
3405                 }
3406
3407                 /* search for the secret record */
3408                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3409                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3410                                    &msgs, attrs,
3411                                    "(&(cn=%s)(objectclass=secret))",
3412                                    ldb_binary_encode_string(mem_ctx, name));
3413                 if (ret == 0) {
3414                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3415                 }
3416
3417                 if (ret != 1) {
3418                         DEBUG(0,("Found %d records matching CN=%s\n",
3419                                  ret, ldb_binary_encode_string(mem_ctx, name)));
3420                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3421                 }
3422         }
3423
3424         secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3425
3426         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3427         if (!handle) {
3428                 return NT_STATUS_NO_MEMORY;
3429         }
3430
3431         handle->data = talloc_steal(handle, secret_state);
3432
3433         secret_state->access_mask = r->in.access_mask;
3434         secret_state->policy = talloc_reference(secret_state, policy_state);
3435
3436         *r->out.sec_handle = handle->wire_handle;
3437
3438         return NT_STATUS_OK;
3439 }
3440
3441
3442 /*
3443   lsa_SetSecret
3444 */
3445 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3446                               struct lsa_SetSecret *r)
3447 {
3448
3449         struct dcesrv_handle *h;
3450         struct lsa_secret_state *secret_state;
3451         struct ldb_message *msg;
3452         DATA_BLOB session_key;
3453         DATA_BLOB crypt_secret, secret;
3454         struct ldb_val val;
3455         int ret;
3456         NTSTATUS status = NT_STATUS_OK;
3457
3458         struct timeval now = timeval_current();
3459         NTTIME nt_now = timeval_to_nttime(&now);
3460
3461         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3462
3463         secret_state = h->data;
3464
3465         msg = ldb_msg_new(mem_ctx);
3466         if (msg == NULL) {
3467                 return NT_STATUS_NO_MEMORY;
3468         }
3469
3470         msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3471         if (!msg->dn) {
3472                 return NT_STATUS_NO_MEMORY;
3473         }
3474         status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3475         if (!NT_STATUS_IS_OK(status)) {
3476                 return status;
3477         }
3478
3479         if (r->in.old_val) {
3480                 /* Decrypt */
3481                 crypt_secret.data = r->in.old_val->data;
3482                 crypt_secret.length = r->in.old_val->size;
3483
3484                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3485                 if (!NT_STATUS_IS_OK(status)) {
3486                         return status;
3487                 }
3488
3489                 val.data = secret.data;
3490                 val.length = secret.length;
3491
3492                 /* set value */
3493                 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3494                         return NT_STATUS_NO_MEMORY;
3495                 }
3496
3497                 /* set old value mtime */
3498                 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3499                                          mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3500                         return NT_STATUS_NO_MEMORY;
3501                 }
3502
3503         } else {
3504                 /* If the old value is not set, then migrate the
3505                  * current value to the old value */
3506                 const struct ldb_val *old_val;
3507                 NTTIME last_set_time;
3508                 struct ldb_message **res;
3509                 const char *attrs[] = {
3510                         "currentValue",
3511                         "lastSetTime",
3512                         NULL
3513                 };
3514
3515                 /* search for the secret record */
3516                 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3517                                       secret_state->secret_dn, &res, attrs);
3518                 if (ret == 0) {
3519                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3520                 }
3521
3522                 if (ret != 1) {
3523                         DEBUG(0,("Found %d records matching dn=%s\n", ret,
3524                                  ldb_dn_get_linearized(secret_state->secret_dn)));
3525                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3526                 }
3527
3528                 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3529                 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3530
3531                 if (old_val) {
3532                         /* set old value */
3533                         if (ldb_msg_add_value(msg, "priorValue",
3534                                               old_val, NULL) != LDB_SUCCESS) {
3535                                 return NT_STATUS_NO_MEMORY;
3536                         }
3537                 } else {
3538                         if (samdb_msg_add_delete(secret_state->sam_ldb,
3539                                                  mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3540                                 return NT_STATUS_NO_MEMORY;
3541                         }
3542                 }
3543
3544                 /* set old value mtime */
3545                 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3546                         if (samdb_msg_add_uint64(secret_state->sam_ldb,
3547                                                  mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3548                                 return NT_STATUS_NO_MEMORY;
3549                         }
3550                 } else {
3551                         if (samdb_msg_add_uint64(secret_state->sam_ldb,
3552                                                  mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3553                                 return NT_STATUS_NO_MEMORY;
3554                         }
3555                 }
3556         }
3557
3558         if (r->in.new_val) {
3559                 /* Decrypt */
3560                 crypt_secret.data = r->in.new_val->data;
3561                 crypt_secret.length = r->in.new_val->size;
3562
3563                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3564                 if (!NT_STATUS_IS_OK(status)) {
3565                         return status;
3566                 }
3567
3568                 val.data = secret.data;
3569                 val.length = secret.length;
3570
3571                 /* set value */
3572                 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3573                         return NT_STATUS_NO_MEMORY;
3574                 }
3575
3576                 /* set new value mtime */
3577                 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3578                                          mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3579                         return NT_STATUS_NO_MEMORY;
3580                 }
3581         } else {
3582                 /* NULL out the NEW value */
3583                 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3584                                          mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3585                         return NT_STATUS_NO_MEMORY;
3586                 }
3587                 if (samdb_msg_add_delete(secret_state->sam_ldb,
3588                                          mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3589                         return NT_STATUS_NO_MEMORY;
3590                 }
3591         }
3592
3593         /* modify the samdb record */
3594         ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3595         if (ret != LDB_SUCCESS) {
3596                 return dsdb_ldb_err_to_ntstatus(ret);
3597         }
3598
3599         return NT_STATUS_OK;
3600 }
3601
3602
3603 /*
3604   lsa_QuerySecret
3605 */
3606 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3607                                 struct lsa_QuerySecret *r)
3608 {
3609         struct dcesrv_handle *h;
3610         struct lsa_secret_state *secret_state;
3611         struct ldb_message *msg;
3612         DATA_BLOB session_key;
3613         DATA_BLOB crypt_secret, secret;
3614         int ret;
3615         struct ldb_message **res;
3616         const char *attrs[] = {
3617                 "currentValue",
3618                 "priorValue",
3619                 "lastSetTime",
3620                 "priorSetTime",
3621                 NULL
3622         };
3623
3624         NTSTATUS nt_status;
3625
3626         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3627
3628         /* Ensure user is permitted to read this... */
3629         switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3630         {
3631         case SECURITY_SYSTEM:
3632         case SECURITY_ADMINISTRATOR:
3633                 break;
3634         default:
3635                 /* Users and annonymous are not allowed to read secrets */
3636                 return NT_STATUS_ACCESS_DENIED;
3637         }
3638
3639         secret_state = h->data;
3640
3641         /* pull all the user attributes */
3642         ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3643                               secret_state->secret_dn, &res, attrs);
3644         if (ret != 1) {
3645                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3646         }
3647         msg = res[0];
3648
3649         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3650         if (!NT_STATUS_IS_OK(nt_status)) {
3651                 return nt_status;
3652         }
3653
3654         if (r->in.old_val) {
3655                 const struct ldb_val *prior_val;
3656                 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3657                 if (!r->out.old_val) {
3658                         return NT_STATUS_NO_MEMORY;
3659                 }
3660                 prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3661
3662                 if (prior_val && prior_val->length) {
3663                         secret.data = prior_val->data;
3664                         secret.length = prior_val->length;
3665
3666                         /* Encrypt */
3667                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3668                         if (!crypt_secret.length) {
3669                                 return NT_STATUS_NO_MEMORY;
3670                         }
3671                         r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3672                         if (!r->out.old_val->buf) {
3673                                 return NT_STATUS_NO_MEMORY;
3674                         }
3675                         r->out.old_val->buf->size = crypt_secret.length;
3676                         r->out.old_val->buf->length = crypt_secret.length;
3677                         r->out.old_val->buf->data = crypt_secret.data;
3678                 }
3679         }
3680
3681         if (r->in.old_mtime) {
3682                 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3683                 if (!r->out.old_mtime) {
3684                         return NT_STATUS_NO_MEMORY;
3685                 }
3686                 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3687         }
3688
3689         if (r->in.new_val) {
3690                 const struct ldb_val *new_val;
3691                 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3692                 if (!r->out.new_val) {
3693                         return NT_STATUS_NO_MEMORY;
3694                 }
3695
3696                 new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3697
3698                 if (new_val && new_val->length) {
3699                         secret.data = new_val->data;
3700                         secret.length = new_val->length;
3701
3702                         /* Encrypt */
3703                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3704                         if (!crypt_secret.length) {
3705                                 return NT_STATUS_NO_MEMORY;
3706                         }
3707                         r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3708                         if (!r->out.new_val->buf) {
3709                                 return NT_STATUS_NO_MEMORY;
3710                         }
3711                         r->out.new_val->buf->length = crypt_secret.length;
3712                         r->out.new_val->buf->size = crypt_secret.length;
3713                         r->out.new_val->buf->data = crypt_secret.data;
3714                 }
3715         }
3716
3717         if (r->in.new_mtime) {
3718                 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3719                 if (!r->out.new_mtime) {
3720                         return NT_STATUS_NO_MEMORY;
3721                 }
3722                 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3723         }
3724
3725         return NT_STATUS_OK;
3726 }
3727
3728
3729 /*
3730   lsa_LookupPrivValue
3731 */
3732 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3733                                     TALLOC_CTX *mem_ctx,
3734                                     struct lsa_LookupPrivValue *r)
3735 {
3736         struct dcesrv_handle *h;
3737         int id;
3738
3739         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3740
3741         id = sec_privilege_id(r->in.name->string);
3742         if (id == SEC_PRIV_INVALID) {
3743                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3744         }
3745
3746         r->out.luid->low = id;
3747         r->out.luid->high = 0;
3748
3749         return NT_STATUS_OK;
3750 }
3751
3752
3753 /*
3754   lsa_LookupPrivName
3755 */
3756 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3757                                    TALLOC_CTX *mem_ctx,
3758                                    struct lsa_LookupPrivName *r)
3759 {
3760         struct dcesrv_handle *h;
3761         struct lsa_StringLarge *name;
3762         const char *privname;
3763
3764         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3765
3766         if (r->in.luid->high != 0) {
3767                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3768         }
3769
3770         privname = sec_privilege_name(r->in.luid->low);
3771         if (privname == NULL) {
3772                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3773         }
3774
3775         name = talloc(mem_ctx, struct lsa_StringLarge);
3776         if (name == NULL) {
3777                 return NT_STATUS_NO_MEMORY;
3778         }
3779
3780         name->string = privname;
3781
3782         *r->out.name = name;
3783
3784         return NT_STATUS_OK;
3785 }
3786
3787
3788 /*
3789   lsa_LookupPrivDisplayName
3790 */
3791 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3792                                           TALLOC_CTX *mem_ctx,
3793                                           struct lsa_LookupPrivDisplayName *r)
3794 {
3795         struct dcesrv_handle *h;
3796         struct lsa_StringLarge *disp_name = NULL;
3797         enum sec_privilege id;
3798
3799         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3800
3801         id = sec_privilege_id(r->in.name->string);
3802         if (id == SEC_PRIV_INVALID) {
3803                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3804         }
3805
3806         disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3807         if (disp_name == NULL) {
3808                 return NT_STATUS_NO_MEMORY;
3809         }
3810
3811         disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3812         if (disp_name->string == NULL) {
3813                 return NT_STATUS_INTERNAL_ERROR;
3814         }
3815
3816         *r->out.disp_name = disp_name;
3817         *r->out.returned_language_id = 0;
3818
3819         return NT_STATUS_OK;
3820 }
3821
3822
3823 /*
3824   lsa_EnumAccountsWithUserRight
3825 */
3826 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3827                                               TALLOC_CTX *mem_ctx,
3828                                               struct lsa_EnumAccountsWithUserRight *r)
3829 {
3830         struct dcesrv_handle *h;
3831         struct lsa_policy_state *state;
3832         int ret, i;
3833         struct ldb_message **res;
3834         const char * const attrs[] = { "objectSid", NULL};
3835         const char *privname;
3836         bool ok;
3837
3838         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3839
3840         state = h->data;
3841
3842         if (r->in.name == NULL) {
3843                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3844         }
3845
3846         privname = r->in.name->string;
3847
3848         ok = dcesrc_lsa_valid_AccountRight(privname);
3849         if (!ok) {
3850                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3851         }
3852
3853         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3854                            "privilege=%s", privname);
3855         if (ret < 0) {
3856                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3857         }
3858         if (ret == 0) {
3859                 return NT_STATUS_NO_MORE_ENTRIES;
3860         }
3861
3862         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3863         if (r->out.sids->sids == NULL) {
3864                 return NT_STATUS_NO_MEMORY;
3865         }
3866         for (i=0;i<ret;i++) {
3867                 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3868                                                                 res[i], "objectSid");
3869                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3870         }
3871         r->out.sids->num_sids = ret;
3872
3873         return NT_STATUS_OK;
3874 }
3875
3876
3877 /*
3878   lsa_AddAccountRights
3879 */
3880 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3881                                      TALLOC_CTX *mem_ctx,
3882                                      struct lsa_AddAccountRights *r)
3883 {
3884         struct dcesrv_handle *h;
3885         struct lsa_policy_state *state;
3886
3887         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3888
3889         state = h->data;
3890
3891         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3892                                           LDB_FLAG_MOD_ADD,
3893                                           r->in.sid, r->in.rights);
3894 }
3895
3896
3897 /*
3898   lsa_RemoveAccountRights
3899 */
3900 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3901                                         TALLOC_CTX *mem_ctx,
3902                                         struct lsa_RemoveAccountRights *r)
3903 {
3904         struct dcesrv_handle *h;
3905         struct lsa_policy_state *state;
3906
3907         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3908
3909         state = h->data;
3910
3911         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3912                                           LDB_FLAG_MOD_DELETE,
3913                                           r->in.sid, r->in.rights);
3914 }
3915
3916
3917 /*
3918   lsa_StorePrivateData
3919 */
3920 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3921                        struct lsa_StorePrivateData *r)
3922 {
3923         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3924 }
3925
3926
3927 /*
3928   lsa_RetrievePrivateData
3929 */
3930 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3931                        struct lsa_RetrievePrivateData *r)
3932 {
3933         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3934 }
3935
3936
3937 /*
3938   lsa_GetUserName
3939 */
3940 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3941                                 struct lsa_GetUserName *r)
3942 {
3943         enum dcerpc_transport_t transport =
3944                 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
3945         NTSTATUS status = NT_STATUS_OK;
3946         const char *account_name;
3947         const char *authority_name;
3948         struct lsa_String *_account_name;
3949         struct lsa_String *_authority_name = NULL;
3950
3951         if (transport != NCACN_NP && transport != NCALRPC) {
3952                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3953         }
3954
3955         /* this is what w2k3 does */
3956         r->out.account_name = r->in.account_name;
3957         r->out.authority_name = r->in.authority_name;
3958
3959         if (r->in.account_name
3960             && *r->in.account_name
3961             /* && *(*r->in.account_name)->string */
3962             ) {
3963                 return NT_STATUS_INVALID_PARAMETER;
3964         }
3965
3966         if (r->in.authority_name
3967             && *r->in.authority_name
3968             /* && *(*r->in.authority_name)->string */
3969             ) {
3970                 return NT_STATUS_INVALID_PARAMETER;
3971         }
3972
3973         account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3974         authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3975
3976         _account_name = talloc(mem_ctx, struct lsa_String);
3977         NT_STATUS_HAVE_NO_MEMORY(_account_name);
3978         _account_name->string = account_name;
3979
3980         if (r->in.authority_name) {
3981                 _authority_name = talloc(mem_ctx, struct lsa_String);
3982                 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3983                 _authority_name->string = authority_name;
3984         }
3985
3986         *r->out.account_name = _account_name;
3987         if (r->out.authority_name) {
3988                 *r->out.authority_name = _authority_name;
3989         }
3990
3991         return status;
3992 }
3993
3994 /*
3995   lsa_SetInfoPolicy2
3996 */
3997 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
3998                                    TALLOC_CTX *mem_ctx,
3999                                    struct lsa_SetInfoPolicy2 *r)
4000 {
4001         /* need to support these */
4002         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4003 }
4004
4005 static void kdc_get_policy(TALLOC_CTX *mem_ctx,
4006                            struct loadparm_context *lp_ctx,
4007                            struct smb_krb5_context *smb_krb5_context,
4008                            struct lsa_DomainInfoKerberos *k)
4009 {
4010         time_t svc_tkt_lifetime;
4011         time_t usr_tkt_lifetime;
4012         time_t renewal_lifetime;
4013
4014         /* Our KDC always re-validates the client */
4015         k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
4016
4017         lpcfg_default_kdc_policy(mem_ctx, lp_ctx, &svc_tkt_lifetime,
4018                                  &usr_tkt_lifetime, &renewal_lifetime);
4019
4020         unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
4021         unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
4022         unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
4023 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
4024         However in the parent function we basically just did a full
4025         krb5_context init with the only purpose of getting a global
4026         config option (the max skew), it would probably make more sense
4027         to have a lp_ or ldb global option as the samba default */
4028         if (smb_krb5_context) {
4029                 unix_to_nt_time(&k->clock_skew,
4030                                 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
4031         }
4032 #endif
4033         k->reserved = 0;
4034 }
4035 /*
4036   lsa_QueryDomainInformationPolicy
4037 */
4038 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4039                                                  TALLOC_CTX *mem_ctx,
4040                                                  struct lsa_QueryDomainInformationPolicy *r)
4041 {
4042         union lsa_DomainInformationPolicy *info;
4043
4044         info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
4045         if (!info) {
4046                 return NT_STATUS_NO_MEMORY;
4047         }
4048
4049         switch (r->in.level) {
4050         case LSA_DOMAIN_INFO_POLICY_EFS:
4051                 talloc_free(info);
4052                 *r->out.info = NULL;
4053                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4054         case LSA_DOMAIN_INFO_POLICY_KERBEROS:
4055         {
4056                 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
4057                 struct smb_krb5_context *smb_krb5_context;
4058                 int ret = smb_krb5_init_context(mem_ctx,
4059                                                         dce_call->conn->dce_ctx->lp_ctx,
4060                                                         &smb_krb5_context);
4061                 if (ret != 0) {
4062                         talloc_free(info);
4063                         *r->out.info = NULL;
4064                         return NT_STATUS_INTERNAL_ERROR;
4065                 }
4066                 kdc_get_policy(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
4067                                smb_krb5_context,
4068                                k);
4069                 talloc_free(smb_krb5_context);
4070                 *r->out.info = info;
4071                 return NT_STATUS_OK;
4072         }
4073         default:
4074                 talloc_free(info);
4075                 *r->out.info = NULL;
4076                 return NT_STATUS_INVALID_INFO_CLASS;
4077         }
4078 }
4079
4080 /*
4081   lsa_SetDomInfoPolicy
4082 */
4083 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4084                                               TALLOC_CTX *mem_ctx,
4085                                               struct lsa_SetDomainInformationPolicy *r)
4086 {
4087         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4088 }
4089
4090 /*
4091   lsa_TestCall
4092 */
4093 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
4094                              TALLOC_CTX *mem_ctx,
4095                              struct lsa_TestCall *r)
4096 {
4097         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4098 }
4099
4100 /*
4101   lsa_CREDRWRITE
4102 */
4103 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4104                        struct lsa_CREDRWRITE *r)
4105 {
4106         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4107 }
4108
4109
4110 /*
4111   lsa_CREDRREAD
4112 */
4113 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4114                        struct lsa_CREDRREAD *r)
4115 {
4116         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4117 }
4118
4119
4120 /*
4121   lsa_CREDRENUMERATE
4122 */
4123 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4124                        struct lsa_CREDRENUMERATE *r)
4125 {
4126         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4127 }
4128
4129
4130 /*
4131   lsa_CREDRWRITEDOMAINCREDENTIALS
4132 */
4133 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4134                        struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
4135 {
4136         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4137 }
4138
4139
4140 /*
4141   lsa_CREDRREADDOMAINCREDENTIALS
4142 */
4143 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4144                        struct lsa_CREDRREADDOMAINCREDENTIALS *r)
4145 {
4146         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4147 }
4148
4149
4150 /*
4151   lsa_CREDRDELETE
4152 */
4153 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4154                        struct lsa_CREDRDELETE *r)
4155 {
4156         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4157 }
4158
4159
4160 /*
4161   lsa_CREDRGETTARGETINFO
4162 */
4163 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4164                        struct lsa_CREDRGETTARGETINFO *r)
4165 {
4166         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4167 }
4168
4169
4170 /*
4171   lsa_CREDRPROFILELOADED
4172 */
4173 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4174                        struct lsa_CREDRPROFILELOADED *r)
4175 {
4176         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4177 }
4178
4179
4180 /*
4181   lsa_CREDRGETSESSIONTYPES
4182 */
4183 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4184                        struct lsa_CREDRGETSESSIONTYPES *r)
4185 {
4186         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4187 }
4188
4189
4190 /*
4191   lsa_LSARREGISTERAUDITEVENT
4192 */
4193 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4194                        struct lsa_LSARREGISTERAUDITEVENT *r)
4195 {
4196         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4197 }
4198
4199
4200 /*
4201   lsa_LSARGENAUDITEVENT
4202 */
4203 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4204                        struct lsa_LSARGENAUDITEVENT *r)
4205 {
4206         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4207 }
4208
4209
4210 /*
4211   lsa_LSARUNREGISTERAUDITEVENT
4212 */
4213 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4214                        struct lsa_LSARUNREGISTERAUDITEVENT *r)
4215 {
4216         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4217 }
4218
4219
4220 /*
4221   lsa_lsaRQueryForestTrustInformation
4222 */
4223 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4224                        struct lsa_lsaRQueryForestTrustInformation *r)
4225 {
4226         struct dcesrv_handle *h = NULL;
4227         struct lsa_policy_state *p_state = NULL;
4228         int forest_level = DS_DOMAIN_FUNCTION_2000;
4229         const char * const trust_attrs[] = {
4230                 "securityIdentifier",
4231                 "flatName",
4232                 "trustPartner",
4233                 "trustAttributes",
4234                 "trustDirection",
4235                 "trustType",
4236                 "msDS-TrustForestTrustInfo",
4237                 NULL
4238         };
4239         struct ldb_message *trust_tdo_msg = NULL;
4240         struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4241         struct ForestTrustInfo *trust_fti = NULL;
4242         struct lsa_ForestTrustInformation *trust_lfti = NULL;
4243         NTSTATUS status;
4244
4245         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4246
4247         p_state = h->data;
4248
4249         if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4250                 return NT_STATUS_INVALID_DOMAIN_STATE;
4251         }
4252
4253         forest_level = dsdb_forest_functional_level(p_state->sam_ldb);
4254         if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4255                 return NT_STATUS_INVALID_DOMAIN_STATE;
4256         }
4257
4258         if (r->in.trusted_domain_name->string == NULL) {
4259                 return NT_STATUS_NO_SUCH_DOMAIN;
4260         }
4261
4262         status = dsdb_trust_search_tdo(p_state->sam_ldb,
4263                                        r->in.trusted_domain_name->string,
4264                                        r->in.trusted_domain_name->string,
4265                                        trust_attrs, mem_ctx, &trust_tdo_msg);
4266         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4267                 return NT_STATUS_NO_SUCH_DOMAIN;
4268         }
4269         if (!NT_STATUS_IS_OK(status)) {
4270                 return status;
4271         }
4272
4273         status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4274         if (!NT_STATUS_IS_OK(status)) {
4275                 return status;
4276         }
4277
4278         if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4279                 return NT_STATUS_INVALID_PARAMETER;
4280         }
4281
4282         if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4283                 return NT_STATUS_INVALID_PARAMETER;
4284         }
4285
4286         status = dsdb_trust_parse_forest_info(mem_ctx,
4287                                               trust_tdo_msg,
4288                                               &trust_fti);
4289         if (!NT_STATUS_IS_OK(status)) {
4290                 return status;
4291         }
4292
4293         status = dsdb_trust_forest_info_to_lsa(mem_ctx, trust_fti,
4294                                                &trust_lfti);
4295         if (!NT_STATUS_IS_OK(status)) {
4296                 return status;
4297         }
4298
4299         *r->out.forest_trust_info = trust_lfti;
4300         return NT_STATUS_OK;
4301 }
4302
4303 /*
4304   lsa_lsaRSetForestTrustInformation
4305 */
4306 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4307                                                          TALLOC_CTX *mem_ctx,
4308                                                          struct lsa_lsaRSetForestTrustInformation *r)
4309 {
4310         struct dcesrv_handle *h;
4311         struct lsa_policy_state *p_state;
4312         const char * const trust_attrs[] = {
4313                 "securityIdentifier",
4314                 "flatName",
4315                 "trustPartner",
4316                 "trustAttributes",
4317                 "trustDirection",
4318                 "trustType",
4319                 "msDS-TrustForestTrustInfo",
4320                 NULL
4321         };
4322         struct ldb_message *trust_tdo_msg = NULL;
4323         struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4324         struct lsa_ForestTrustInformation *step1_lfti = NULL;
4325         struct lsa_ForestTrustInformation *step2_lfti = NULL;
4326         struct ForestTrustInfo *trust_fti = NULL;
4327         struct ldb_result *trusts_res = NULL;
4328         unsigned int i;
4329         struct lsa_TrustDomainInfoInfoEx *xref_tdo = NULL;
4330         struct lsa_ForestTrustInformation *xref_lfti = NULL;
4331         struct lsa_ForestTrustCollisionInfo *c_info = NULL;
4332         DATA_BLOB ft_blob = {};
4333         struct ldb_message *msg = NULL;
4334         struct server_id *server_ids = NULL;
4335         uint32_t num_server_ids = 0;
4336         NTSTATUS status;
4337         enum ndr_err_code ndr_err;
4338         int ret;
4339         bool in_transaction = false;
4340
4341         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4342
4343         p_state = h->data;
4344
4345         if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4346                 return NT_STATUS_INVALID_DOMAIN_STATE;
4347         }
4348
4349         if (r->in.check_only == 0) {
4350                 ret = ldb_transaction_start(p_state->sam_ldb);
4351                 if (ret != LDB_SUCCESS) {
4352                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
4353                 }
4354                 in_transaction = true;
4355         }
4356
4357         /*
4358          * abort if we are not a PDC
4359          *
4360          * In future we should use a function like IsEffectiveRoleOwner()
4361          */
4362         if (!samdb_is_pdc(p_state->sam_ldb)) {
4363                 status = NT_STATUS_INVALID_DOMAIN_ROLE;
4364                 goto done;
4365         }
4366
4367         if (r->in.trusted_domain_name->string == NULL) {
4368                 status = NT_STATUS_NO_SUCH_DOMAIN;
4369                 goto done;
4370         }
4371
4372         status = dsdb_trust_search_tdo(p_state->sam_ldb,
4373                                        r->in.trusted_domain_name->string,
4374                                        r->in.trusted_domain_name->string,
4375                                        trust_attrs, mem_ctx, &trust_tdo_msg);
4376         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4377                 status = NT_STATUS_NO_SUCH_DOMAIN;
4378                 goto done;
4379         }
4380         if (!NT_STATUS_IS_OK(status)) {
4381                 goto done;
4382         }
4383
4384         status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4385         if (!NT_STATUS_IS_OK(status)) {
4386                 goto done;
4387         }
4388
4389         if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4390                 status = NT_STATUS_INVALID_PARAMETER;
4391                 goto done;
4392         }
4393
4394         if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4395                 status = NT_STATUS_INVALID_PARAMETER;
4396                 goto done;
4397         }
4398
4399         /*
4400          * verify and normalize the given forest trust info.
4401          *
4402          * Step1: doesn't reorder yet, so step1_lfti might contain
4403          * NULL entries. This means dsdb_trust_verify_forest_info()
4404          * can generate collision entries with the callers index.
4405          */
4406         status = dsdb_trust_normalize_forest_info_step1(mem_ctx,
4407                                                         r->in.forest_trust_info,
4408                                                         &step1_lfti);
4409         if (!NT_STATUS_IS_OK(status)) {
4410                 goto done;
4411         }
4412
4413         c_info = talloc_zero(r->out.collision_info,
4414                              struct lsa_ForestTrustCollisionInfo);
4415         if (c_info == NULL) {
4416                 status = NT_STATUS_NO_MEMORY;
4417                 goto done;
4418         }
4419
4420         /*
4421          * First check our own forest, then other domains/forests
4422          */
4423
4424         status = dsdb_trust_xref_tdo_info(mem_ctx, p_state->sam_ldb,
4425                                           &xref_tdo);
4426         if (!NT_STATUS_IS_OK(status)) {
4427                 goto done;
4428         }
4429         status = dsdb_trust_xref_forest_info(mem_ctx, p_state->sam_ldb,
4430                                              &xref_lfti);
4431         if (!NT_STATUS_IS_OK(status)) {
4432                 goto done;
4433         }
4434
4435         /*
4436          * The documentation proposed to generate
4437          * LSA_FOREST_TRUST_COLLISION_XREF collisions.
4438          * But Windows always uses LSA_FOREST_TRUST_COLLISION_TDO.
4439          */
4440         status = dsdb_trust_verify_forest_info(xref_tdo, xref_lfti,
4441                                                LSA_FOREST_TRUST_COLLISION_TDO,
4442                                                c_info, step1_lfti);
4443         if (!NT_STATUS_IS_OK(status)) {
4444                 goto done;
4445         }
4446
4447         /* fetch all other trusted domain objects */
4448         status = dsdb_trust_search_tdos(p_state->sam_ldb,
4449                                         trust_tdo->domain_name.string,
4450                                         trust_attrs,
4451                                         mem_ctx, &trusts_res);
4452         if (!NT_STATUS_IS_OK(status)) {
4453                 goto done;
4454         }
4455
4456         /*
4457          * now check against the other domains.
4458          * and generate LSA_FOREST_TRUST_COLLISION_TDO collisions.
4459          */
4460         for (i = 0; i < trusts_res->count; i++) {
4461                 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
4462                 struct ForestTrustInfo *fti = NULL;
4463                 struct lsa_ForestTrustInformation *lfti = NULL;
4464
4465                 status = dsdb_trust_parse_tdo_info(mem_ctx,
4466                                                    trusts_res->msgs[i],
4467                                                    &tdo);
4468                 if (!NT_STATUS_IS_OK(status)) {
4469                         goto done;
4470                 }
4471
4472                 status = dsdb_trust_parse_forest_info(tdo,
4473                                                       trusts_res->msgs[i],
4474                                                       &fti);
4475                 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
4476                         continue;
4477                 }
4478                 if (!NT_STATUS_IS_OK(status)) {
4479                         goto done;
4480                 }
4481
4482                 status = dsdb_trust_forest_info_to_lsa(tdo, fti, &lfti);
4483                 if (!NT_STATUS_IS_OK(status)) {
4484                         goto done;
4485                 }
4486
4487                 status = dsdb_trust_verify_forest_info(tdo, lfti,
4488                                                 LSA_FOREST_TRUST_COLLISION_TDO,
4489                                                 c_info, step1_lfti);
4490                 if (!NT_STATUS_IS_OK(status)) {
4491                         goto done;
4492                 }
4493
4494                 TALLOC_FREE(tdo);
4495         }
4496
4497         if (r->in.check_only != 0) {
4498                 status = NT_STATUS_OK;
4499                 goto done;
4500         }
4501
4502         /*
4503          * not just a check, write info back
4504          */
4505
4506         /*
4507          * normalize the given forest trust info.
4508          *
4509          * Step2: adds TOP_LEVEL_NAME[_EX] in reverse order,
4510          * followed by DOMAIN_INFO in reverse order. It also removes
4511          * possible NULL entries from Step1.
4512          */
4513         status = dsdb_trust_normalize_forest_info_step2(mem_ctx, step1_lfti,
4514                                                         &step2_lfti);
4515         if (!NT_STATUS_IS_OK(status)) {
4516                 goto done;
4517         }
4518
4519         status = dsdb_trust_forest_info_from_lsa(mem_ctx, step2_lfti,
4520                                                  &trust_fti);
4521         if (!NT_STATUS_IS_OK(status)) {
4522                 goto done;
4523         }
4524
4525         ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, trust_fti,
4526                                        (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4527         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4528                 status = NT_STATUS_INVALID_PARAMETER;
4529                 goto done;
4530         }
4531
4532         msg = ldb_msg_new(mem_ctx);
4533         if (msg == NULL) {
4534                 status = NT_STATUS_NO_MEMORY;
4535                 goto done;
4536         }
4537
4538         msg->dn = ldb_dn_copy(mem_ctx, trust_tdo_msg->dn);
4539         if (!msg->dn) {
4540                 status = NT_STATUS_NO_MEMORY;
4541                 goto done;
4542         }
4543
4544         ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4545                                 LDB_FLAG_MOD_REPLACE, NULL);
4546         if (ret != LDB_SUCCESS) {
4547                 status = NT_STATUS_NO_MEMORY;
4548                 goto done;
4549         }
4550         ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4551                                 &ft_blob, NULL);
4552         if (ret != LDB_SUCCESS) {
4553                 status = NT_STATUS_NO_MEMORY;
4554                 goto done;
4555         }
4556
4557         ret = ldb_modify(p_state->sam_ldb, msg);
4558         if (ret != LDB_SUCCESS) {
4559                 status = dsdb_ldb_err_to_ntstatus(ret);
4560
4561                 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4562                           ldb_errstring(p_state->sam_ldb)));
4563
4564                 goto done;
4565         }
4566
4567         /* ok, all fine, commit transaction and return */
4568         in_transaction = false;
4569         ret = ldb_transaction_commit(p_state->sam_ldb);
4570         if (ret != LDB_SUCCESS) {
4571                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
4572                 goto done;
4573         }
4574
4575         /*
4576          * Notify winbindd that we have a acquired forest trust info
4577          */
4578         status = irpc_servers_byname(dce_call->msg_ctx,
4579                                      mem_ctx,
4580                                      "winbind_server",
4581                                      &num_server_ids, &server_ids);
4582         if (!NT_STATUS_IS_OK(status)) {
4583                 DBG_ERR("irpc_servers_byname failed\n");
4584                 goto done;
4585         }
4586
4587         imessaging_send(dce_call->msg_ctx, server_ids[0],
4588                         MSG_WINBIND_RELOAD_TRUSTED_DOMAINS, NULL);
4589
4590         status = NT_STATUS_OK;
4591
4592 done:
4593         if (NT_STATUS_IS_OK(status) && c_info->count != 0) {
4594                 *r->out.collision_info = c_info;
4595         }
4596
4597         if (in_transaction) {
4598                 ldb_transaction_cancel(p_state->sam_ldb);
4599         }
4600
4601         return status;
4602 }
4603
4604 /*
4605   lsa_CREDRRENAME
4606 */
4607 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4608                        struct lsa_CREDRRENAME *r)
4609 {
4610         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4611 }
4612
4613
4614
4615 /*
4616   lsa_LSAROPENPOLICYSCE
4617 */
4618 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4619                        struct lsa_LSAROPENPOLICYSCE *r)
4620 {
4621         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4622 }
4623
4624
4625 /*
4626   lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4627 */
4628 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4629                        struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4630 {
4631         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4632 }
4633
4634
4635 /*
4636   lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4637 */
4638 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4639                        struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4640 {
4641         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4642 }
4643
4644
4645 /*
4646   lsa_LSARADTREPORTSECURITYEVENT
4647 */
4648 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4649                        struct lsa_LSARADTREPORTSECURITYEVENT *r)
4650 {
4651         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4652 }
4653
4654
4655 /* include the generated boilerplate */
4656 #include "librpc/gen_ndr/ndr_lsa_s.c"
4657
4658
4659
4660 /*****************************************
4661 NOTE! The remaining calls below were
4662 removed in w2k3, so the DCESRV_FAULT()
4663 replies are the correct implementation. Do
4664 not try and fill these in with anything else
4665 ******************************************/
4666
4667 /*
4668   dssetup_DsRoleDnsNameToFlatName
4669 */
4670 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4671                                         struct dssetup_DsRoleDnsNameToFlatName *r)
4672 {
4673         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4674 }
4675
4676
4677 /*
4678   dssetup_DsRoleDcAsDc
4679 */
4680 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4681                              struct dssetup_DsRoleDcAsDc *r)
4682 {
4683         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4684 }
4685
4686
4687 /*
4688   dssetup_DsRoleDcAsReplica
4689 */
4690 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4691                                   struct dssetup_DsRoleDcAsReplica *r)
4692 {
4693         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4694 }
4695
4696
4697 /*
4698   dssetup_DsRoleDemoteDc
4699 */
4700 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4701                                struct dssetup_DsRoleDemoteDc *r)
4702 {
4703         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4704 }
4705
4706
4707 /*
4708   dssetup_DsRoleGetDcOperationProgress
4709 */
4710 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4711                                              struct dssetup_DsRoleGetDcOperationProgress *r)
4712 {
4713         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4714 }
4715
4716
4717 /* 
4718   dssetup_DsRoleGetDcOperationResults 
4719 */
4720 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4721                                             struct dssetup_DsRoleGetDcOperationResults *r)
4722 {
4723         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4724 }
4725
4726
4727 /* 
4728   dssetup_DsRoleCancel 
4729 */
4730 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4731                              struct dssetup_DsRoleCancel *r)
4732 {
4733         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4734 }
4735
4736
4737 /*
4738   dssetup_DsRoleServerSaveStateForUpgrade
4739 */
4740 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4741                                                 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4742 {
4743         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4744 }
4745
4746
4747 /*
4748   dssetup_DsRoleUpgradeDownlevelServer
4749 */
4750 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4751                                              struct dssetup_DsRoleUpgradeDownlevelServer *r)
4752 {
4753         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4754 }
4755
4756
4757 /*
4758   dssetup_DsRoleAbortDownlevelServerUpgrade
4759 */
4760 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4761                                                   struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4762 {
4763         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4764 }
4765
4766
4767 /* include the generated boilerplate */
4768 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4769
4770 NTSTATUS dcerpc_server_lsa_init(TALLOC_CTX *ctx)
4771 {
4772         NTSTATUS ret;
4773
4774         ret = dcerpc_server_dssetup_init(ctx);
4775         if (!NT_STATUS_IS_OK(ret)) {
4776                 return ret;
4777         }
4778         ret = dcerpc_server_lsarpc_init(ctx);
4779         if (!NT_STATUS_IS_OK(ret)) {
4780                 return ret;
4781         }
4782         return ret;
4783 }