samdb: Add remote address to connect
[amitay/samba.git] / source4 / rpc_server / lsa / dcesrv_lsa.c
1 /* need access mask/acl implementation */
2
3 /* 
4    Unix SMB/CIFS implementation.
5
6    endpoint server for the lsarpc pipe
7
8    Copyright (C) Andrew Tridgell 2004
9    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2008
10
11    This program is free software; you can redistribute it and/or modify
12    it under the terms of the GNU General Public License as published by
13    the Free Software Foundation; either version 3 of the License, or
14    (at your option) any later version.
15
16    This program is distributed in the hope that it will be useful,
17    but WITHOUT ANY WARRANTY; without even the implied warranty of
18    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19    GNU General Public License for more details.
20
21    You should have received a copy of the GNU General Public License
22    along with this program.  If not, see <http://www.gnu.org/licenses/>.
23 */
24
25 #include "rpc_server/lsa/lsa.h"
26 #include "system/kerberos.h"
27 #include "auth/kerberos/kerberos.h"
28 #include "librpc/gen_ndr/ndr_drsblobs.h"
29 #include "librpc/gen_ndr/ndr_lsa.h"
30 #include "../lib/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         struct ldb_context *samdb = NULL;
3184         const char *attrs[] = {
3185                 NULL
3186         };
3187
3188         const char *name;
3189
3190         int ret;
3191
3192         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3193         ZERO_STRUCTP(r->out.sec_handle);
3194
3195         switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3196         {
3197         case SECURITY_SYSTEM:
3198         case SECURITY_ADMINISTRATOR:
3199                 break;
3200         default:
3201                 /* Users and annonymous are not allowed create secrets */
3202                 return NT_STATUS_ACCESS_DENIED;
3203         }
3204
3205         policy_state = policy_handle->data;
3206
3207         if (!r->in.name.string) {
3208                 return NT_STATUS_INVALID_PARAMETER;
3209         }
3210
3211         secret_state = talloc(mem_ctx, struct lsa_secret_state);
3212         NT_STATUS_HAVE_NO_MEMORY(secret_state);
3213         secret_state->policy = policy_state;
3214
3215         msg = ldb_msg_new(mem_ctx);
3216         if (msg == NULL) {
3217                 return NT_STATUS_NO_MEMORY;
3218         }
3219
3220         if (strncmp("G$", r->in.name.string, 2) == 0) {
3221                 const char *name2;
3222
3223                 secret_state->global = true;
3224
3225                 name = &r->in.name.string[2];
3226                 if (strlen(name) == 0) {
3227                         return NT_STATUS_INVALID_PARAMETER;
3228                 }
3229
3230                 name2 = talloc_asprintf(mem_ctx, "%s Secret",
3231                                         ldb_binary_encode_string(mem_ctx, name));
3232                 NT_STATUS_HAVE_NO_MEMORY(name2);
3233
3234                 /* We need to connect to the database as system, as this is one
3235                  * of the rare RPC calls that must read the secrets (and this
3236                  * is denied otherwise) */
3237                 samdb = samdb_connect(
3238                         mem_ctx,
3239                         dce_call->event_ctx,
3240                         dce_call->conn->dce_ctx->lp_ctx,
3241                         system_session(dce_call->conn->dce_ctx->lp_ctx),
3242                         dce_call->conn->remote_address,
3243                         0);
3244                 secret_state->sam_ldb = talloc_reference(secret_state, samdb);
3245                 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3246
3247                 /* search for the secret record */
3248                 ret = gendb_search(secret_state->sam_ldb,
3249                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
3250                                    "(&(cn=%s)(objectclass=secret))",
3251                                    name2);
3252                 if (ret > 0) {
3253                         return NT_STATUS_OBJECT_NAME_COLLISION;
3254                 }
3255
3256                 if (ret < 0) {
3257                         DEBUG(0,("Failure searching for CN=%s: %s\n",
3258                                  name2, ldb_errstring(secret_state->sam_ldb)));
3259                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3260                 }
3261
3262                 msg->dn = ldb_dn_copy(mem_ctx, policy_state->system_dn);
3263                 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3264                 if (!ldb_dn_add_child_fmt(msg->dn, "cn=%s", name2)) {
3265                         return NT_STATUS_NO_MEMORY;
3266                 }
3267
3268                 ret = ldb_msg_add_string(msg, "cn", name2);
3269                 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3270         } else {
3271                 secret_state->global = false;
3272
3273                 name = r->in.name.string;
3274                 if (strlen(name) == 0) {
3275                         return NT_STATUS_INVALID_PARAMETER;
3276                 }
3277
3278                 secret_state->sam_ldb = talloc_reference(secret_state,
3279                                                          secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3280                 NT_STATUS_HAVE_NO_MEMORY(secret_state->sam_ldb);
3281
3282                 /* search for the secret record */
3283                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3284                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3285                                    &msgs, attrs,
3286                                    "(&(cn=%s)(objectclass=secret))",
3287                                    ldb_binary_encode_string(mem_ctx, name));
3288                 if (ret > 0) {
3289                         return NT_STATUS_OBJECT_NAME_COLLISION;
3290                 }
3291
3292                 if (ret < 0) {
3293                         DEBUG(0,("Failure searching for CN=%s: %s\n",
3294                                  name, ldb_errstring(secret_state->sam_ldb)));
3295                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3296                 }
3297
3298                 msg->dn = ldb_dn_new_fmt(mem_ctx, secret_state->sam_ldb,
3299                                          "cn=%s,cn=LSA Secrets", name);
3300                 NT_STATUS_HAVE_NO_MEMORY(msg->dn);
3301                 ret = ldb_msg_add_string(msg, "cn", name);
3302                 if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3303         }
3304
3305         ret = ldb_msg_add_string(msg, "objectClass", "secret");
3306         if (ret != LDB_SUCCESS) return NT_STATUS_NO_MEMORY;
3307
3308         secret_state->secret_dn = talloc_reference(secret_state, msg->dn);
3309         NT_STATUS_HAVE_NO_MEMORY(secret_state->secret_dn);
3310
3311         /* create the secret */
3312         ret = ldb_add(secret_state->sam_ldb, msg);
3313         if (ret != LDB_SUCCESS) {
3314                 DEBUG(0,("Failed to create secret record %s: %s\n",
3315                          ldb_dn_get_linearized(msg->dn),
3316                          ldb_errstring(secret_state->sam_ldb)));
3317                 return NT_STATUS_ACCESS_DENIED;
3318         }
3319
3320         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3321         NT_STATUS_HAVE_NO_MEMORY(handle);
3322
3323         handle->data = talloc_steal(handle, secret_state);
3324
3325         secret_state->access_mask = r->in.access_mask;
3326         secret_state->policy = talloc_reference(secret_state, policy_state);
3327         NT_STATUS_HAVE_NO_MEMORY(secret_state->policy);
3328
3329         *r->out.sec_handle = handle->wire_handle;
3330
3331         return NT_STATUS_OK;
3332 }
3333
3334
3335 /*
3336   lsa_OpenSecret
3337 */
3338 static NTSTATUS dcesrv_lsa_OpenSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3339                                struct lsa_OpenSecret *r)
3340 {
3341         struct dcesrv_handle *policy_handle;
3342
3343         struct lsa_policy_state *policy_state;
3344         struct lsa_secret_state *secret_state;
3345         struct dcesrv_handle *handle;
3346         struct ldb_message **msgs;
3347         struct ldb_context *samdb = NULL;
3348         const char *attrs[] = {
3349                 NULL
3350         };
3351
3352         const char *name;
3353
3354         int ret;
3355
3356         DCESRV_PULL_HANDLE(policy_handle, r->in.handle, LSA_HANDLE_POLICY);
3357         ZERO_STRUCTP(r->out.sec_handle);
3358         policy_state = policy_handle->data;
3359
3360         if (!r->in.name.string) {
3361                 return NT_STATUS_INVALID_PARAMETER;
3362         }
3363
3364         switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3365         {
3366         case SECURITY_SYSTEM:
3367         case SECURITY_ADMINISTRATOR:
3368                 break;
3369         default:
3370                 /* Users and annonymous are not allowed to access secrets */
3371                 return NT_STATUS_ACCESS_DENIED;
3372         }
3373
3374         secret_state = talloc(mem_ctx, struct lsa_secret_state);
3375         if (!secret_state) {
3376                 return NT_STATUS_NO_MEMORY;
3377         }
3378         secret_state->policy = policy_state;
3379
3380         if (strncmp("G$", r->in.name.string, 2) == 0) {
3381                 name = &r->in.name.string[2];
3382                 /* 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) */
3383                 samdb = samdb_connect(
3384                         mem_ctx,
3385                         dce_call->event_ctx,
3386                         dce_call->conn->dce_ctx->lp_ctx,
3387                         system_session(dce_call->conn->dce_ctx->lp_ctx),
3388                         dce_call->conn->remote_address,
3389                         0);
3390                 secret_state->sam_ldb = talloc_reference(secret_state, samdb);
3391                 secret_state->global = true;
3392
3393                 if (strlen(name) < 1) {
3394                         return NT_STATUS_INVALID_PARAMETER;
3395                 }
3396
3397                 /* search for the secret record */
3398                 ret = gendb_search(secret_state->sam_ldb,
3399                                    mem_ctx, policy_state->system_dn, &msgs, attrs,
3400                                    "(&(cn=%s Secret)(objectclass=secret))",
3401                                    ldb_binary_encode_string(mem_ctx, name));
3402                 if (ret == 0) {
3403                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3404                 }
3405
3406                 if (ret != 1) {
3407                         DEBUG(0,("Found %d records matching DN %s\n", ret,
3408                                  ldb_dn_get_linearized(policy_state->system_dn)));
3409                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3410                 }
3411         } else {
3412                 secret_state->global = false;
3413                 secret_state->sam_ldb = talloc_reference(secret_state,
3414                                                          secrets_db_connect(mem_ctx, dce_call->conn->dce_ctx->lp_ctx));
3415
3416                 name = r->in.name.string;
3417                 if (strlen(name) < 1) {
3418                         return NT_STATUS_INVALID_PARAMETER;
3419                 }
3420
3421                 /* search for the secret record */
3422                 ret = gendb_search(secret_state->sam_ldb, mem_ctx,
3423                                    ldb_dn_new(mem_ctx, secret_state->sam_ldb, "cn=LSA Secrets"),
3424                                    &msgs, attrs,
3425                                    "(&(cn=%s)(objectclass=secret))",
3426                                    ldb_binary_encode_string(mem_ctx, name));
3427                 if (ret == 0) {
3428                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3429                 }
3430
3431                 if (ret != 1) {
3432                         DEBUG(0,("Found %d records matching CN=%s\n",
3433                                  ret, ldb_binary_encode_string(mem_ctx, name)));
3434                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3435                 }
3436         }
3437
3438         secret_state->secret_dn = talloc_reference(secret_state, msgs[0]->dn);
3439
3440         handle = dcesrv_handle_new(dce_call->context, LSA_HANDLE_SECRET);
3441         if (!handle) {
3442                 return NT_STATUS_NO_MEMORY;
3443         }
3444
3445         handle->data = talloc_steal(handle, secret_state);
3446
3447         secret_state->access_mask = r->in.access_mask;
3448         secret_state->policy = talloc_reference(secret_state, policy_state);
3449
3450         *r->out.sec_handle = handle->wire_handle;
3451
3452         return NT_STATUS_OK;
3453 }
3454
3455
3456 /*
3457   lsa_SetSecret
3458 */
3459 static NTSTATUS dcesrv_lsa_SetSecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3460                               struct lsa_SetSecret *r)
3461 {
3462
3463         struct dcesrv_handle *h;
3464         struct lsa_secret_state *secret_state;
3465         struct ldb_message *msg;
3466         DATA_BLOB session_key;
3467         DATA_BLOB crypt_secret, secret;
3468         struct ldb_val val;
3469         int ret;
3470         NTSTATUS status = NT_STATUS_OK;
3471
3472         struct timeval now = timeval_current();
3473         NTTIME nt_now = timeval_to_nttime(&now);
3474
3475         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3476
3477         secret_state = h->data;
3478
3479         msg = ldb_msg_new(mem_ctx);
3480         if (msg == NULL) {
3481                 return NT_STATUS_NO_MEMORY;
3482         }
3483
3484         msg->dn = talloc_reference(mem_ctx, secret_state->secret_dn);
3485         if (!msg->dn) {
3486                 return NT_STATUS_NO_MEMORY;
3487         }
3488         status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3489         if (!NT_STATUS_IS_OK(status)) {
3490                 return status;
3491         }
3492
3493         if (r->in.old_val) {
3494                 /* Decrypt */
3495                 crypt_secret.data = r->in.old_val->data;
3496                 crypt_secret.length = r->in.old_val->size;
3497
3498                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3499                 if (!NT_STATUS_IS_OK(status)) {
3500                         return status;
3501                 }
3502
3503                 val.data = secret.data;
3504                 val.length = secret.length;
3505
3506                 /* set value */
3507                 if (ldb_msg_add_value(msg, "priorValue", &val, NULL) != LDB_SUCCESS) {
3508                         return NT_STATUS_NO_MEMORY;
3509                 }
3510
3511                 /* set old value mtime */
3512                 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3513                                          mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3514                         return NT_STATUS_NO_MEMORY;
3515                 }
3516
3517         } else {
3518                 /* If the old value is not set, then migrate the
3519                  * current value to the old value */
3520                 const struct ldb_val *old_val;
3521                 NTTIME last_set_time;
3522                 struct ldb_message **res;
3523                 const char *attrs[] = {
3524                         "currentValue",
3525                         "lastSetTime",
3526                         NULL
3527                 };
3528
3529                 /* search for the secret record */
3530                 ret = gendb_search_dn(secret_state->sam_ldb,mem_ctx,
3531                                       secret_state->secret_dn, &res, attrs);
3532                 if (ret == 0) {
3533                         return NT_STATUS_OBJECT_NAME_NOT_FOUND;
3534                 }
3535
3536                 if (ret != 1) {
3537                         DEBUG(0,("Found %d records matching dn=%s\n", ret,
3538                                  ldb_dn_get_linearized(secret_state->secret_dn)));
3539                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
3540                 }
3541
3542                 old_val = ldb_msg_find_ldb_val(res[0], "currentValue");
3543                 last_set_time = ldb_msg_find_attr_as_uint64(res[0], "lastSetTime", 0);
3544
3545                 if (old_val) {
3546                         /* set old value */
3547                         if (ldb_msg_add_value(msg, "priorValue",
3548                                               old_val, NULL) != LDB_SUCCESS) {
3549                                 return NT_STATUS_NO_MEMORY;
3550                         }
3551                 } else {
3552                         if (samdb_msg_add_delete(secret_state->sam_ldb,
3553                                                  mem_ctx, msg, "priorValue") != LDB_SUCCESS) {
3554                                 return NT_STATUS_NO_MEMORY;
3555                         }
3556                 }
3557
3558                 /* set old value mtime */
3559                 if (ldb_msg_find_ldb_val(res[0], "lastSetTime")) {
3560                         if (samdb_msg_add_uint64(secret_state->sam_ldb,
3561                                                  mem_ctx, msg, "priorSetTime", last_set_time) != LDB_SUCCESS) {
3562                                 return NT_STATUS_NO_MEMORY;
3563                         }
3564                 } else {
3565                         if (samdb_msg_add_uint64(secret_state->sam_ldb,
3566                                                  mem_ctx, msg, "priorSetTime", nt_now) != LDB_SUCCESS) {
3567                                 return NT_STATUS_NO_MEMORY;
3568                         }
3569                 }
3570         }
3571
3572         if (r->in.new_val) {
3573                 /* Decrypt */
3574                 crypt_secret.data = r->in.new_val->data;
3575                 crypt_secret.length = r->in.new_val->size;
3576
3577                 status = sess_decrypt_blob(mem_ctx, &crypt_secret, &session_key, &secret);
3578                 if (!NT_STATUS_IS_OK(status)) {
3579                         return status;
3580                 }
3581
3582                 val.data = secret.data;
3583                 val.length = secret.length;
3584
3585                 /* set value */
3586                 if (ldb_msg_add_value(msg, "currentValue", &val, NULL) != LDB_SUCCESS) {
3587                         return NT_STATUS_NO_MEMORY;
3588                 }
3589
3590                 /* set new value mtime */
3591                 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3592                                          mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3593                         return NT_STATUS_NO_MEMORY;
3594                 }
3595         } else {
3596                 /* NULL out the NEW value */
3597                 if (samdb_msg_add_uint64(secret_state->sam_ldb,
3598                                          mem_ctx, msg, "lastSetTime", nt_now) != LDB_SUCCESS) {
3599                         return NT_STATUS_NO_MEMORY;
3600                 }
3601                 if (samdb_msg_add_delete(secret_state->sam_ldb,
3602                                          mem_ctx, msg, "currentValue") != LDB_SUCCESS) {
3603                         return NT_STATUS_NO_MEMORY;
3604                 }
3605         }
3606
3607         /* modify the samdb record */
3608         ret = dsdb_replace(secret_state->sam_ldb, msg, 0);
3609         if (ret != LDB_SUCCESS) {
3610                 return dsdb_ldb_err_to_ntstatus(ret);
3611         }
3612
3613         return NT_STATUS_OK;
3614 }
3615
3616
3617 /*
3618   lsa_QuerySecret
3619 */
3620 static NTSTATUS dcesrv_lsa_QuerySecret(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3621                                 struct lsa_QuerySecret *r)
3622 {
3623         struct dcesrv_handle *h;
3624         struct lsa_secret_state *secret_state;
3625         struct ldb_message *msg;
3626         DATA_BLOB session_key;
3627         DATA_BLOB crypt_secret, secret;
3628         int ret;
3629         struct ldb_message **res;
3630         const char *attrs[] = {
3631                 "currentValue",
3632                 "priorValue",
3633                 "lastSetTime",
3634                 "priorSetTime",
3635                 NULL
3636         };
3637
3638         NTSTATUS nt_status;
3639
3640         DCESRV_PULL_HANDLE(h, r->in.sec_handle, LSA_HANDLE_SECRET);
3641
3642         /* Ensure user is permitted to read this... */
3643         switch (security_session_user_level(dce_call->conn->auth_state.session_info, NULL))
3644         {
3645         case SECURITY_SYSTEM:
3646         case SECURITY_ADMINISTRATOR:
3647                 break;
3648         default:
3649                 /* Users and annonymous are not allowed to read secrets */
3650                 return NT_STATUS_ACCESS_DENIED;
3651         }
3652
3653         secret_state = h->data;
3654
3655         /* pull all the user attributes */
3656         ret = gendb_search_dn(secret_state->sam_ldb, mem_ctx,
3657                               secret_state->secret_dn, &res, attrs);
3658         if (ret != 1) {
3659                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3660         }
3661         msg = res[0];
3662
3663         nt_status = dcesrv_fetch_session_key(dce_call->conn, &session_key);
3664         if (!NT_STATUS_IS_OK(nt_status)) {
3665                 return nt_status;
3666         }
3667
3668         if (r->in.old_val) {
3669                 const struct ldb_val *prior_val;
3670                 r->out.old_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3671                 if (!r->out.old_val) {
3672                         return NT_STATUS_NO_MEMORY;
3673                 }
3674                 prior_val = ldb_msg_find_ldb_val(msg, "priorValue");
3675
3676                 if (prior_val && prior_val->length) {
3677                         secret.data = prior_val->data;
3678                         secret.length = prior_val->length;
3679
3680                         /* Encrypt */
3681                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3682                         if (!crypt_secret.length) {
3683                                 return NT_STATUS_NO_MEMORY;
3684                         }
3685                         r->out.old_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3686                         if (!r->out.old_val->buf) {
3687                                 return NT_STATUS_NO_MEMORY;
3688                         }
3689                         r->out.old_val->buf->size = crypt_secret.length;
3690                         r->out.old_val->buf->length = crypt_secret.length;
3691                         r->out.old_val->buf->data = crypt_secret.data;
3692                 }
3693         }
3694
3695         if (r->in.old_mtime) {
3696                 r->out.old_mtime = talloc(mem_ctx, NTTIME);
3697                 if (!r->out.old_mtime) {
3698                         return NT_STATUS_NO_MEMORY;
3699                 }
3700                 *r->out.old_mtime = ldb_msg_find_attr_as_uint64(msg, "priorSetTime", 0);
3701         }
3702
3703         if (r->in.new_val) {
3704                 const struct ldb_val *new_val;
3705                 r->out.new_val = talloc_zero(mem_ctx, struct lsa_DATA_BUF_PTR);
3706                 if (!r->out.new_val) {
3707                         return NT_STATUS_NO_MEMORY;
3708                 }
3709
3710                 new_val = ldb_msg_find_ldb_val(msg, "currentValue");
3711
3712                 if (new_val && new_val->length) {
3713                         secret.data = new_val->data;
3714                         secret.length = new_val->length;
3715
3716                         /* Encrypt */
3717                         crypt_secret = sess_encrypt_blob(mem_ctx, &secret, &session_key);
3718                         if (!crypt_secret.length) {
3719                                 return NT_STATUS_NO_MEMORY;
3720                         }
3721                         r->out.new_val->buf = talloc(mem_ctx, struct lsa_DATA_BUF);
3722                         if (!r->out.new_val->buf) {
3723                                 return NT_STATUS_NO_MEMORY;
3724                         }
3725                         r->out.new_val->buf->length = crypt_secret.length;
3726                         r->out.new_val->buf->size = crypt_secret.length;
3727                         r->out.new_val->buf->data = crypt_secret.data;
3728                 }
3729         }
3730
3731         if (r->in.new_mtime) {
3732                 r->out.new_mtime = talloc(mem_ctx, NTTIME);
3733                 if (!r->out.new_mtime) {
3734                         return NT_STATUS_NO_MEMORY;
3735                 }
3736                 *r->out.new_mtime = ldb_msg_find_attr_as_uint64(msg, "lastSetTime", 0);
3737         }
3738
3739         return NT_STATUS_OK;
3740 }
3741
3742
3743 /*
3744   lsa_LookupPrivValue
3745 */
3746 static NTSTATUS dcesrv_lsa_LookupPrivValue(struct dcesrv_call_state *dce_call,
3747                                     TALLOC_CTX *mem_ctx,
3748                                     struct lsa_LookupPrivValue *r)
3749 {
3750         struct dcesrv_handle *h;
3751         int id;
3752
3753         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3754
3755         id = sec_privilege_id(r->in.name->string);
3756         if (id == SEC_PRIV_INVALID) {
3757                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3758         }
3759
3760         r->out.luid->low = id;
3761         r->out.luid->high = 0;
3762
3763         return NT_STATUS_OK;
3764 }
3765
3766
3767 /*
3768   lsa_LookupPrivName
3769 */
3770 static NTSTATUS dcesrv_lsa_LookupPrivName(struct dcesrv_call_state *dce_call,
3771                                    TALLOC_CTX *mem_ctx,
3772                                    struct lsa_LookupPrivName *r)
3773 {
3774         struct dcesrv_handle *h;
3775         struct lsa_StringLarge *name;
3776         const char *privname;
3777
3778         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3779
3780         if (r->in.luid->high != 0) {
3781                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3782         }
3783
3784         privname = sec_privilege_name(r->in.luid->low);
3785         if (privname == NULL) {
3786                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3787         }
3788
3789         name = talloc(mem_ctx, struct lsa_StringLarge);
3790         if (name == NULL) {
3791                 return NT_STATUS_NO_MEMORY;
3792         }
3793
3794         name->string = privname;
3795
3796         *r->out.name = name;
3797
3798         return NT_STATUS_OK;
3799 }
3800
3801
3802 /*
3803   lsa_LookupPrivDisplayName
3804 */
3805 static NTSTATUS dcesrv_lsa_LookupPrivDisplayName(struct dcesrv_call_state *dce_call,
3806                                           TALLOC_CTX *mem_ctx,
3807                                           struct lsa_LookupPrivDisplayName *r)
3808 {
3809         struct dcesrv_handle *h;
3810         struct lsa_StringLarge *disp_name = NULL;
3811         enum sec_privilege id;
3812
3813         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3814
3815         id = sec_privilege_id(r->in.name->string);
3816         if (id == SEC_PRIV_INVALID) {
3817                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3818         }
3819
3820         disp_name = talloc(mem_ctx, struct lsa_StringLarge);
3821         if (disp_name == NULL) {
3822                 return NT_STATUS_NO_MEMORY;
3823         }
3824
3825         disp_name->string = sec_privilege_display_name(id, &r->in.language_id);
3826         if (disp_name->string == NULL) {
3827                 return NT_STATUS_INTERNAL_ERROR;
3828         }
3829
3830         *r->out.disp_name = disp_name;
3831         *r->out.returned_language_id = 0;
3832
3833         return NT_STATUS_OK;
3834 }
3835
3836
3837 /*
3838   lsa_EnumAccountsWithUserRight
3839 */
3840 static NTSTATUS dcesrv_lsa_EnumAccountsWithUserRight(struct dcesrv_call_state *dce_call,
3841                                               TALLOC_CTX *mem_ctx,
3842                                               struct lsa_EnumAccountsWithUserRight *r)
3843 {
3844         struct dcesrv_handle *h;
3845         struct lsa_policy_state *state;
3846         int ret, i;
3847         struct ldb_message **res;
3848         const char * const attrs[] = { "objectSid", NULL};
3849         const char *privname;
3850         bool ok;
3851
3852         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3853
3854         state = h->data;
3855
3856         if (r->in.name == NULL) {
3857                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3858         }
3859
3860         privname = r->in.name->string;
3861
3862         ok = dcesrc_lsa_valid_AccountRight(privname);
3863         if (!ok) {
3864                 return NT_STATUS_NO_SUCH_PRIVILEGE;
3865         }
3866
3867         ret = gendb_search(state->pdb, mem_ctx, NULL, &res, attrs,
3868                            "privilege=%s", privname);
3869         if (ret < 0) {
3870                 return NT_STATUS_INTERNAL_DB_CORRUPTION;
3871         }
3872         if (ret == 0) {
3873                 return NT_STATUS_NO_MORE_ENTRIES;
3874         }
3875
3876         r->out.sids->sids = talloc_array(r->out.sids, struct lsa_SidPtr, ret);
3877         if (r->out.sids->sids == NULL) {
3878                 return NT_STATUS_NO_MEMORY;
3879         }
3880         for (i=0;i<ret;i++) {
3881                 r->out.sids->sids[i].sid = samdb_result_dom_sid(r->out.sids->sids,
3882                                                                 res[i], "objectSid");
3883                 NT_STATUS_HAVE_NO_MEMORY(r->out.sids->sids[i].sid);
3884         }
3885         r->out.sids->num_sids = ret;
3886
3887         return NT_STATUS_OK;
3888 }
3889
3890
3891 /*
3892   lsa_AddAccountRights
3893 */
3894 static NTSTATUS dcesrv_lsa_AddAccountRights(struct dcesrv_call_state *dce_call,
3895                                      TALLOC_CTX *mem_ctx,
3896                                      struct lsa_AddAccountRights *r)
3897 {
3898         struct dcesrv_handle *h;
3899         struct lsa_policy_state *state;
3900
3901         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3902
3903         state = h->data;
3904
3905         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3906                                           LDB_FLAG_MOD_ADD,
3907                                           r->in.sid, r->in.rights);
3908 }
3909
3910
3911 /*
3912   lsa_RemoveAccountRights
3913 */
3914 static NTSTATUS dcesrv_lsa_RemoveAccountRights(struct dcesrv_call_state *dce_call,
3915                                         TALLOC_CTX *mem_ctx,
3916                                         struct lsa_RemoveAccountRights *r)
3917 {
3918         struct dcesrv_handle *h;
3919         struct lsa_policy_state *state;
3920
3921         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
3922
3923         state = h->data;
3924
3925         return dcesrv_lsa_AddRemoveAccountRights(dce_call, mem_ctx, state,
3926                                           LDB_FLAG_MOD_DELETE,
3927                                           r->in.sid, r->in.rights);
3928 }
3929
3930
3931 /*
3932   lsa_StorePrivateData
3933 */
3934 static NTSTATUS dcesrv_lsa_StorePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3935                        struct lsa_StorePrivateData *r)
3936 {
3937         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3938 }
3939
3940
3941 /*
3942   lsa_RetrievePrivateData
3943 */
3944 static NTSTATUS dcesrv_lsa_RetrievePrivateData(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3945                        struct lsa_RetrievePrivateData *r)
3946 {
3947         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
3948 }
3949
3950
3951 /*
3952   lsa_GetUserName
3953 */
3954 static NTSTATUS dcesrv_lsa_GetUserName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
3955                                 struct lsa_GetUserName *r)
3956 {
3957         enum dcerpc_transport_t transport =
3958                 dcerpc_binding_get_transport(dce_call->conn->endpoint->ep_description);
3959         NTSTATUS status = NT_STATUS_OK;
3960         const char *account_name;
3961         const char *authority_name;
3962         struct lsa_String *_account_name;
3963         struct lsa_String *_authority_name = NULL;
3964
3965         if (transport != NCACN_NP && transport != NCALRPC) {
3966                 DCESRV_FAULT(DCERPC_FAULT_ACCESS_DENIED);
3967         }
3968
3969         /* this is what w2k3 does */
3970         r->out.account_name = r->in.account_name;
3971         r->out.authority_name = r->in.authority_name;
3972
3973         if (r->in.account_name
3974             && *r->in.account_name
3975             /* && *(*r->in.account_name)->string */
3976             ) {
3977                 return NT_STATUS_INVALID_PARAMETER;
3978         }
3979
3980         if (r->in.authority_name
3981             && *r->in.authority_name
3982             /* && *(*r->in.authority_name)->string */
3983             ) {
3984                 return NT_STATUS_INVALID_PARAMETER;
3985         }
3986
3987         account_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->account_name);
3988         authority_name = talloc_reference(mem_ctx, dce_call->conn->auth_state.session_info->info->domain_name);
3989
3990         _account_name = talloc(mem_ctx, struct lsa_String);
3991         NT_STATUS_HAVE_NO_MEMORY(_account_name);
3992         _account_name->string = account_name;
3993
3994         if (r->in.authority_name) {
3995                 _authority_name = talloc(mem_ctx, struct lsa_String);
3996                 NT_STATUS_HAVE_NO_MEMORY(_authority_name);
3997                 _authority_name->string = authority_name;
3998         }
3999
4000         *r->out.account_name = _account_name;
4001         if (r->out.authority_name) {
4002                 *r->out.authority_name = _authority_name;
4003         }
4004
4005         return status;
4006 }
4007
4008 /*
4009   lsa_SetInfoPolicy2
4010 */
4011 static NTSTATUS dcesrv_lsa_SetInfoPolicy2(struct dcesrv_call_state *dce_call,
4012                                    TALLOC_CTX *mem_ctx,
4013                                    struct lsa_SetInfoPolicy2 *r)
4014 {
4015         /* need to support these */
4016         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4017 }
4018
4019 static void kdc_get_policy(TALLOC_CTX *mem_ctx,
4020                            struct loadparm_context *lp_ctx,
4021                            struct smb_krb5_context *smb_krb5_context,
4022                            struct lsa_DomainInfoKerberos *k)
4023 {
4024         time_t svc_tkt_lifetime;
4025         time_t usr_tkt_lifetime;
4026         time_t renewal_lifetime;
4027
4028         /* Our KDC always re-validates the client */
4029         k->authentication_options = LSA_POLICY_KERBEROS_VALIDATE_CLIENT;
4030
4031         lpcfg_default_kdc_policy(mem_ctx, lp_ctx, &svc_tkt_lifetime,
4032                                  &usr_tkt_lifetime, &renewal_lifetime);
4033
4034         unix_to_nt_time(&k->service_tkt_lifetime, svc_tkt_lifetime);
4035         unix_to_nt_time(&k->user_tkt_lifetime, usr_tkt_lifetime);
4036         unix_to_nt_time(&k->user_tkt_renewaltime, renewal_lifetime);
4037 #ifdef SAMBA4_USES_HEIMDAL /* MIT lacks krb5_get_max_time_skew.
4038         However in the parent function we basically just did a full
4039         krb5_context init with the only purpose of getting a global
4040         config option (the max skew), it would probably make more sense
4041         to have a lp_ or ldb global option as the samba default */
4042         if (smb_krb5_context) {
4043                 unix_to_nt_time(&k->clock_skew,
4044                                 krb5_get_max_time_skew(smb_krb5_context->krb5_context));
4045         }
4046 #endif
4047         k->reserved = 0;
4048 }
4049 /*
4050   lsa_QueryDomainInformationPolicy
4051 */
4052 static NTSTATUS dcesrv_lsa_QueryDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4053                                                  TALLOC_CTX *mem_ctx,
4054                                                  struct lsa_QueryDomainInformationPolicy *r)
4055 {
4056         union lsa_DomainInformationPolicy *info;
4057
4058         info = talloc_zero(r->out.info, union lsa_DomainInformationPolicy);
4059         if (!info) {
4060                 return NT_STATUS_NO_MEMORY;
4061         }
4062
4063         switch (r->in.level) {
4064         case LSA_DOMAIN_INFO_POLICY_EFS:
4065                 talloc_free(info);
4066                 *r->out.info = NULL;
4067                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
4068         case LSA_DOMAIN_INFO_POLICY_KERBEROS:
4069         {
4070                 struct lsa_DomainInfoKerberos *k = &info->kerberos_info;
4071                 struct smb_krb5_context *smb_krb5_context;
4072                 int ret = smb_krb5_init_context(mem_ctx,
4073                                                         dce_call->conn->dce_ctx->lp_ctx,
4074                                                         &smb_krb5_context);
4075                 if (ret != 0) {
4076                         talloc_free(info);
4077                         *r->out.info = NULL;
4078                         return NT_STATUS_INTERNAL_ERROR;
4079                 }
4080                 kdc_get_policy(mem_ctx, dce_call->conn->dce_ctx->lp_ctx,
4081                                smb_krb5_context,
4082                                k);
4083                 talloc_free(smb_krb5_context);
4084                 *r->out.info = info;
4085                 return NT_STATUS_OK;
4086         }
4087         default:
4088                 talloc_free(info);
4089                 *r->out.info = NULL;
4090                 return NT_STATUS_INVALID_INFO_CLASS;
4091         }
4092 }
4093
4094 /*
4095   lsa_SetDomInfoPolicy
4096 */
4097 static NTSTATUS dcesrv_lsa_SetDomainInformationPolicy(struct dcesrv_call_state *dce_call,
4098                                               TALLOC_CTX *mem_ctx,
4099                                               struct lsa_SetDomainInformationPolicy *r)
4100 {
4101         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4102 }
4103
4104 /*
4105   lsa_TestCall
4106 */
4107 static NTSTATUS dcesrv_lsa_TestCall(struct dcesrv_call_state *dce_call,
4108                              TALLOC_CTX *mem_ctx,
4109                              struct lsa_TestCall *r)
4110 {
4111         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4112 }
4113
4114 /*
4115   lsa_CREDRWRITE
4116 */
4117 static NTSTATUS dcesrv_lsa_CREDRWRITE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4118                        struct lsa_CREDRWRITE *r)
4119 {
4120         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4121 }
4122
4123
4124 /*
4125   lsa_CREDRREAD
4126 */
4127 static NTSTATUS dcesrv_lsa_CREDRREAD(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4128                        struct lsa_CREDRREAD *r)
4129 {
4130         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4131 }
4132
4133
4134 /*
4135   lsa_CREDRENUMERATE
4136 */
4137 static NTSTATUS dcesrv_lsa_CREDRENUMERATE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4138                        struct lsa_CREDRENUMERATE *r)
4139 {
4140         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4141 }
4142
4143
4144 /*
4145   lsa_CREDRWRITEDOMAINCREDENTIALS
4146 */
4147 static NTSTATUS dcesrv_lsa_CREDRWRITEDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4148                        struct lsa_CREDRWRITEDOMAINCREDENTIALS *r)
4149 {
4150         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4151 }
4152
4153
4154 /*
4155   lsa_CREDRREADDOMAINCREDENTIALS
4156 */
4157 static NTSTATUS dcesrv_lsa_CREDRREADDOMAINCREDENTIALS(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4158                        struct lsa_CREDRREADDOMAINCREDENTIALS *r)
4159 {
4160         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4161 }
4162
4163
4164 /*
4165   lsa_CREDRDELETE
4166 */
4167 static NTSTATUS dcesrv_lsa_CREDRDELETE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4168                        struct lsa_CREDRDELETE *r)
4169 {
4170         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4171 }
4172
4173
4174 /*
4175   lsa_CREDRGETTARGETINFO
4176 */
4177 static NTSTATUS dcesrv_lsa_CREDRGETTARGETINFO(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4178                        struct lsa_CREDRGETTARGETINFO *r)
4179 {
4180         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4181 }
4182
4183
4184 /*
4185   lsa_CREDRPROFILELOADED
4186 */
4187 static NTSTATUS dcesrv_lsa_CREDRPROFILELOADED(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4188                        struct lsa_CREDRPROFILELOADED *r)
4189 {
4190         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4191 }
4192
4193
4194 /*
4195   lsa_CREDRGETSESSIONTYPES
4196 */
4197 static NTSTATUS dcesrv_lsa_CREDRGETSESSIONTYPES(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4198                        struct lsa_CREDRGETSESSIONTYPES *r)
4199 {
4200         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4201 }
4202
4203
4204 /*
4205   lsa_LSARREGISTERAUDITEVENT
4206 */
4207 static NTSTATUS dcesrv_lsa_LSARREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4208                        struct lsa_LSARREGISTERAUDITEVENT *r)
4209 {
4210         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4211 }
4212
4213
4214 /*
4215   lsa_LSARGENAUDITEVENT
4216 */
4217 static NTSTATUS dcesrv_lsa_LSARGENAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4218                        struct lsa_LSARGENAUDITEVENT *r)
4219 {
4220         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4221 }
4222
4223
4224 /*
4225   lsa_LSARUNREGISTERAUDITEVENT
4226 */
4227 static NTSTATUS dcesrv_lsa_LSARUNREGISTERAUDITEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4228                        struct lsa_LSARUNREGISTERAUDITEVENT *r)
4229 {
4230         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4231 }
4232
4233
4234 /*
4235   lsa_lsaRQueryForestTrustInformation
4236 */
4237 static NTSTATUS dcesrv_lsa_lsaRQueryForestTrustInformation(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4238                        struct lsa_lsaRQueryForestTrustInformation *r)
4239 {
4240         struct dcesrv_handle *h = NULL;
4241         struct lsa_policy_state *p_state = NULL;
4242         int forest_level = DS_DOMAIN_FUNCTION_2000;
4243         const char * const trust_attrs[] = {
4244                 "securityIdentifier",
4245                 "flatName",
4246                 "trustPartner",
4247                 "trustAttributes",
4248                 "trustDirection",
4249                 "trustType",
4250                 "msDS-TrustForestTrustInfo",
4251                 NULL
4252         };
4253         struct ldb_message *trust_tdo_msg = NULL;
4254         struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4255         struct ForestTrustInfo *trust_fti = NULL;
4256         struct lsa_ForestTrustInformation *trust_lfti = NULL;
4257         NTSTATUS status;
4258
4259         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4260
4261         p_state = h->data;
4262
4263         if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4264                 return NT_STATUS_INVALID_DOMAIN_STATE;
4265         }
4266
4267         forest_level = dsdb_forest_functional_level(p_state->sam_ldb);
4268         if (forest_level < DS_DOMAIN_FUNCTION_2003) {
4269                 return NT_STATUS_INVALID_DOMAIN_STATE;
4270         }
4271
4272         if (r->in.trusted_domain_name->string == NULL) {
4273                 return NT_STATUS_NO_SUCH_DOMAIN;
4274         }
4275
4276         status = dsdb_trust_search_tdo(p_state->sam_ldb,
4277                                        r->in.trusted_domain_name->string,
4278                                        r->in.trusted_domain_name->string,
4279                                        trust_attrs, mem_ctx, &trust_tdo_msg);
4280         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4281                 return NT_STATUS_NO_SUCH_DOMAIN;
4282         }
4283         if (!NT_STATUS_IS_OK(status)) {
4284                 return status;
4285         }
4286
4287         status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4288         if (!NT_STATUS_IS_OK(status)) {
4289                 return status;
4290         }
4291
4292         if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4293                 return NT_STATUS_INVALID_PARAMETER;
4294         }
4295
4296         if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4297                 return NT_STATUS_INVALID_PARAMETER;
4298         }
4299
4300         status = dsdb_trust_parse_forest_info(mem_ctx,
4301                                               trust_tdo_msg,
4302                                               &trust_fti);
4303         if (!NT_STATUS_IS_OK(status)) {
4304                 return status;
4305         }
4306
4307         status = dsdb_trust_forest_info_to_lsa(mem_ctx, trust_fti,
4308                                                &trust_lfti);
4309         if (!NT_STATUS_IS_OK(status)) {
4310                 return status;
4311         }
4312
4313         *r->out.forest_trust_info = trust_lfti;
4314         return NT_STATUS_OK;
4315 }
4316
4317 /*
4318   lsa_lsaRSetForestTrustInformation
4319 */
4320 static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_state *dce_call,
4321                                                          TALLOC_CTX *mem_ctx,
4322                                                          struct lsa_lsaRSetForestTrustInformation *r)
4323 {
4324         struct dcesrv_handle *h;
4325         struct lsa_policy_state *p_state;
4326         const char * const trust_attrs[] = {
4327                 "securityIdentifier",
4328                 "flatName",
4329                 "trustPartner",
4330                 "trustAttributes",
4331                 "trustDirection",
4332                 "trustType",
4333                 "msDS-TrustForestTrustInfo",
4334                 NULL
4335         };
4336         struct ldb_message *trust_tdo_msg = NULL;
4337         struct lsa_TrustDomainInfoInfoEx *trust_tdo = NULL;
4338         struct lsa_ForestTrustInformation *step1_lfti = NULL;
4339         struct lsa_ForestTrustInformation *step2_lfti = NULL;
4340         struct ForestTrustInfo *trust_fti = NULL;
4341         struct ldb_result *trusts_res = NULL;
4342         unsigned int i;
4343         struct lsa_TrustDomainInfoInfoEx *xref_tdo = NULL;
4344         struct lsa_ForestTrustInformation *xref_lfti = NULL;
4345         struct lsa_ForestTrustCollisionInfo *c_info = NULL;
4346         DATA_BLOB ft_blob = {};
4347         struct ldb_message *msg = NULL;
4348         struct server_id *server_ids = NULL;
4349         uint32_t num_server_ids = 0;
4350         NTSTATUS status;
4351         enum ndr_err_code ndr_err;
4352         int ret;
4353         bool in_transaction = false;
4354
4355         DCESRV_PULL_HANDLE(h, r->in.handle, LSA_HANDLE_POLICY);
4356
4357         p_state = h->data;
4358
4359         if (strcmp(p_state->domain_dns, p_state->forest_dns)) {
4360                 return NT_STATUS_INVALID_DOMAIN_STATE;
4361         }
4362
4363         if (r->in.check_only == 0) {
4364                 ret = ldb_transaction_start(p_state->sam_ldb);
4365                 if (ret != LDB_SUCCESS) {
4366                         return NT_STATUS_INTERNAL_DB_CORRUPTION;
4367                 }
4368                 in_transaction = true;
4369         }
4370
4371         /*
4372          * abort if we are not a PDC
4373          *
4374          * In future we should use a function like IsEffectiveRoleOwner()
4375          */
4376         if (!samdb_is_pdc(p_state->sam_ldb)) {
4377                 status = NT_STATUS_INVALID_DOMAIN_ROLE;
4378                 goto done;
4379         }
4380
4381         if (r->in.trusted_domain_name->string == NULL) {
4382                 status = NT_STATUS_NO_SUCH_DOMAIN;
4383                 goto done;
4384         }
4385
4386         status = dsdb_trust_search_tdo(p_state->sam_ldb,
4387                                        r->in.trusted_domain_name->string,
4388                                        r->in.trusted_domain_name->string,
4389                                        trust_attrs, mem_ctx, &trust_tdo_msg);
4390         if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) {
4391                 status = NT_STATUS_NO_SUCH_DOMAIN;
4392                 goto done;
4393         }
4394         if (!NT_STATUS_IS_OK(status)) {
4395                 goto done;
4396         }
4397
4398         status = dsdb_trust_parse_tdo_info(mem_ctx, trust_tdo_msg, &trust_tdo);
4399         if (!NT_STATUS_IS_OK(status)) {
4400                 goto done;
4401         }
4402
4403         if (!(trust_tdo->trust_attributes & LSA_TRUST_ATTRIBUTE_FOREST_TRANSITIVE)) {
4404                 status = NT_STATUS_INVALID_PARAMETER;
4405                 goto done;
4406         }
4407
4408         if (r->in.highest_record_type >= LSA_FOREST_TRUST_RECORD_TYPE_LAST) {
4409                 status = NT_STATUS_INVALID_PARAMETER;
4410                 goto done;
4411         }
4412
4413         /*
4414          * verify and normalize the given forest trust info.
4415          *
4416          * Step1: doesn't reorder yet, so step1_lfti might contain
4417          * NULL entries. This means dsdb_trust_verify_forest_info()
4418          * can generate collision entries with the callers index.
4419          */
4420         status = dsdb_trust_normalize_forest_info_step1(mem_ctx,
4421                                                         r->in.forest_trust_info,
4422                                                         &step1_lfti);
4423         if (!NT_STATUS_IS_OK(status)) {
4424                 goto done;
4425         }
4426
4427         c_info = talloc_zero(r->out.collision_info,
4428                              struct lsa_ForestTrustCollisionInfo);
4429         if (c_info == NULL) {
4430                 status = NT_STATUS_NO_MEMORY;
4431                 goto done;
4432         }
4433
4434         /*
4435          * First check our own forest, then other domains/forests
4436          */
4437
4438         status = dsdb_trust_xref_tdo_info(mem_ctx, p_state->sam_ldb,
4439                                           &xref_tdo);
4440         if (!NT_STATUS_IS_OK(status)) {
4441                 goto done;
4442         }
4443         status = dsdb_trust_xref_forest_info(mem_ctx, p_state->sam_ldb,
4444                                              &xref_lfti);
4445         if (!NT_STATUS_IS_OK(status)) {
4446                 goto done;
4447         }
4448
4449         /*
4450          * The documentation proposed to generate
4451          * LSA_FOREST_TRUST_COLLISION_XREF collisions.
4452          * But Windows always uses LSA_FOREST_TRUST_COLLISION_TDO.
4453          */
4454         status = dsdb_trust_verify_forest_info(xref_tdo, xref_lfti,
4455                                                LSA_FOREST_TRUST_COLLISION_TDO,
4456                                                c_info, step1_lfti);
4457         if (!NT_STATUS_IS_OK(status)) {
4458                 goto done;
4459         }
4460
4461         /* fetch all other trusted domain objects */
4462         status = dsdb_trust_search_tdos(p_state->sam_ldb,
4463                                         trust_tdo->domain_name.string,
4464                                         trust_attrs,
4465                                         mem_ctx, &trusts_res);
4466         if (!NT_STATUS_IS_OK(status)) {
4467                 goto done;
4468         }
4469
4470         /*
4471          * now check against the other domains.
4472          * and generate LSA_FOREST_TRUST_COLLISION_TDO collisions.
4473          */
4474         for (i = 0; i < trusts_res->count; i++) {
4475                 struct lsa_TrustDomainInfoInfoEx *tdo = NULL;
4476                 struct ForestTrustInfo *fti = NULL;
4477                 struct lsa_ForestTrustInformation *lfti = NULL;
4478
4479                 status = dsdb_trust_parse_tdo_info(mem_ctx,
4480                                                    trusts_res->msgs[i],
4481                                                    &tdo);
4482                 if (!NT_STATUS_IS_OK(status)) {
4483                         goto done;
4484                 }
4485
4486                 status = dsdb_trust_parse_forest_info(tdo,
4487                                                       trusts_res->msgs[i],
4488                                                       &fti);
4489                 if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) {
4490                         continue;
4491                 }
4492                 if (!NT_STATUS_IS_OK(status)) {
4493                         goto done;
4494                 }
4495
4496                 status = dsdb_trust_forest_info_to_lsa(tdo, fti, &lfti);
4497                 if (!NT_STATUS_IS_OK(status)) {
4498                         goto done;
4499                 }
4500
4501                 status = dsdb_trust_verify_forest_info(tdo, lfti,
4502                                                 LSA_FOREST_TRUST_COLLISION_TDO,
4503                                                 c_info, step1_lfti);
4504                 if (!NT_STATUS_IS_OK(status)) {
4505                         goto done;
4506                 }
4507
4508                 TALLOC_FREE(tdo);
4509         }
4510
4511         if (r->in.check_only != 0) {
4512                 status = NT_STATUS_OK;
4513                 goto done;
4514         }
4515
4516         /*
4517          * not just a check, write info back
4518          */
4519
4520         /*
4521          * normalize the given forest trust info.
4522          *
4523          * Step2: adds TOP_LEVEL_NAME[_EX] in reverse order,
4524          * followed by DOMAIN_INFO in reverse order. It also removes
4525          * possible NULL entries from Step1.
4526          */
4527         status = dsdb_trust_normalize_forest_info_step2(mem_ctx, step1_lfti,
4528                                                         &step2_lfti);
4529         if (!NT_STATUS_IS_OK(status)) {
4530                 goto done;
4531         }
4532
4533         status = dsdb_trust_forest_info_from_lsa(mem_ctx, step2_lfti,
4534                                                  &trust_fti);
4535         if (!NT_STATUS_IS_OK(status)) {
4536                 goto done;
4537         }
4538
4539         ndr_err = ndr_push_struct_blob(&ft_blob, mem_ctx, trust_fti,
4540                                        (ndr_push_flags_fn_t)ndr_push_ForestTrustInfo);
4541         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
4542                 status = NT_STATUS_INVALID_PARAMETER;
4543                 goto done;
4544         }
4545
4546         msg = ldb_msg_new(mem_ctx);
4547         if (msg == NULL) {
4548                 status = NT_STATUS_NO_MEMORY;
4549                 goto done;
4550         }
4551
4552         msg->dn = ldb_dn_copy(mem_ctx, trust_tdo_msg->dn);
4553         if (!msg->dn) {
4554                 status = NT_STATUS_NO_MEMORY;
4555                 goto done;
4556         }
4557
4558         ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
4559                                 LDB_FLAG_MOD_REPLACE, NULL);
4560         if (ret != LDB_SUCCESS) {
4561                 status = NT_STATUS_NO_MEMORY;
4562                 goto done;
4563         }
4564         ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
4565                                 &ft_blob, NULL);
4566         if (ret != LDB_SUCCESS) {
4567                 status = NT_STATUS_NO_MEMORY;
4568                 goto done;
4569         }
4570
4571         ret = ldb_modify(p_state->sam_ldb, msg);
4572         if (ret != LDB_SUCCESS) {
4573                 status = dsdb_ldb_err_to_ntstatus(ret);
4574
4575                 DEBUG(0, ("Failed to store Forest Trust Info: %s\n",
4576                           ldb_errstring(p_state->sam_ldb)));
4577
4578                 goto done;
4579         }
4580
4581         /* ok, all fine, commit transaction and return */
4582         in_transaction = false;
4583         ret = ldb_transaction_commit(p_state->sam_ldb);
4584         if (ret != LDB_SUCCESS) {
4585                 status = NT_STATUS_INTERNAL_DB_CORRUPTION;
4586                 goto done;
4587         }
4588
4589         /*
4590          * Notify winbindd that we have a acquired forest trust info
4591          */
4592         status = irpc_servers_byname(dce_call->msg_ctx,
4593                                      mem_ctx,
4594                                      "winbind_server",
4595                                      &num_server_ids, &server_ids);
4596         if (!NT_STATUS_IS_OK(status)) {
4597                 DBG_ERR("irpc_servers_byname failed\n");
4598                 goto done;
4599         }
4600
4601         imessaging_send(dce_call->msg_ctx, server_ids[0],
4602                         MSG_WINBIND_RELOAD_TRUSTED_DOMAINS, NULL);
4603
4604         status = NT_STATUS_OK;
4605
4606 done:
4607         if (NT_STATUS_IS_OK(status) && c_info->count != 0) {
4608                 *r->out.collision_info = c_info;
4609         }
4610
4611         if (in_transaction) {
4612                 ldb_transaction_cancel(p_state->sam_ldb);
4613         }
4614
4615         return status;
4616 }
4617
4618 /*
4619   lsa_CREDRRENAME
4620 */
4621 static NTSTATUS dcesrv_lsa_CREDRRENAME(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4622                        struct lsa_CREDRRENAME *r)
4623 {
4624         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4625 }
4626
4627
4628
4629 /*
4630   lsa_LSAROPENPOLICYSCE
4631 */
4632 static NTSTATUS dcesrv_lsa_LSAROPENPOLICYSCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4633                        struct lsa_LSAROPENPOLICYSCE *r)
4634 {
4635         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4636 }
4637
4638
4639 /*
4640   lsa_LSARADTREGISTERSECURITYEVENTSOURCE
4641 */
4642 static NTSTATUS dcesrv_lsa_LSARADTREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4643                        struct lsa_LSARADTREGISTERSECURITYEVENTSOURCE *r)
4644 {
4645         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4646 }
4647
4648
4649 /*
4650   lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE
4651 */
4652 static NTSTATUS dcesrv_lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4653                        struct lsa_LSARADTUNREGISTERSECURITYEVENTSOURCE *r)
4654 {
4655         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4656 }
4657
4658
4659 /*
4660   lsa_LSARADTREPORTSECURITYEVENT
4661 */
4662 static NTSTATUS dcesrv_lsa_LSARADTREPORTSECURITYEVENT(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4663                        struct lsa_LSARADTREPORTSECURITYEVENT *r)
4664 {
4665         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4666 }
4667
4668
4669 /* include the generated boilerplate */
4670 #include "librpc/gen_ndr/ndr_lsa_s.c"
4671
4672
4673
4674 /*****************************************
4675 NOTE! The remaining calls below were
4676 removed in w2k3, so the DCESRV_FAULT()
4677 replies are the correct implementation. Do
4678 not try and fill these in with anything else
4679 ******************************************/
4680
4681 /*
4682   dssetup_DsRoleDnsNameToFlatName
4683 */
4684 static WERROR dcesrv_dssetup_DsRoleDnsNameToFlatName(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4685                                         struct dssetup_DsRoleDnsNameToFlatName *r)
4686 {
4687         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4688 }
4689
4690
4691 /*
4692   dssetup_DsRoleDcAsDc
4693 */
4694 static WERROR dcesrv_dssetup_DsRoleDcAsDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4695                              struct dssetup_DsRoleDcAsDc *r)
4696 {
4697         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4698 }
4699
4700
4701 /*
4702   dssetup_DsRoleDcAsReplica
4703 */
4704 static WERROR dcesrv_dssetup_DsRoleDcAsReplica(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4705                                   struct dssetup_DsRoleDcAsReplica *r)
4706 {
4707         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4708 }
4709
4710
4711 /*
4712   dssetup_DsRoleDemoteDc
4713 */
4714 static WERROR dcesrv_dssetup_DsRoleDemoteDc(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4715                                struct dssetup_DsRoleDemoteDc *r)
4716 {
4717         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4718 }
4719
4720
4721 /*
4722   dssetup_DsRoleGetDcOperationProgress
4723 */
4724 static WERROR dcesrv_dssetup_DsRoleGetDcOperationProgress(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4725                                              struct dssetup_DsRoleGetDcOperationProgress *r)
4726 {
4727         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4728 }
4729
4730
4731 /* 
4732   dssetup_DsRoleGetDcOperationResults 
4733 */
4734 static WERROR dcesrv_dssetup_DsRoleGetDcOperationResults(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4735                                             struct dssetup_DsRoleGetDcOperationResults *r)
4736 {
4737         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4738 }
4739
4740
4741 /* 
4742   dssetup_DsRoleCancel 
4743 */
4744 static WERROR dcesrv_dssetup_DsRoleCancel(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4745                              struct dssetup_DsRoleCancel *r)
4746 {
4747         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4748 }
4749
4750
4751 /*
4752   dssetup_DsRoleServerSaveStateForUpgrade
4753 */
4754 static WERROR dcesrv_dssetup_DsRoleServerSaveStateForUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4755                                                 struct dssetup_DsRoleServerSaveStateForUpgrade *r)
4756 {
4757         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4758 }
4759
4760
4761 /*
4762   dssetup_DsRoleUpgradeDownlevelServer
4763 */
4764 static WERROR dcesrv_dssetup_DsRoleUpgradeDownlevelServer(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4765                                              struct dssetup_DsRoleUpgradeDownlevelServer *r)
4766 {
4767         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4768 }
4769
4770
4771 /*
4772   dssetup_DsRoleAbortDownlevelServerUpgrade
4773 */
4774 static WERROR dcesrv_dssetup_DsRoleAbortDownlevelServerUpgrade(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
4775                                                   struct dssetup_DsRoleAbortDownlevelServerUpgrade *r)
4776 {
4777         DCESRV_FAULT(DCERPC_FAULT_OP_RNG_ERROR);
4778 }
4779
4780
4781 /* include the generated boilerplate */
4782 #include "librpc/gen_ndr/ndr_dssetup_s.c"
4783
4784 NTSTATUS dcerpc_server_lsa_init(TALLOC_CTX *ctx)
4785 {
4786         NTSTATUS ret;
4787
4788         ret = dcerpc_server_dssetup_init(ctx);
4789         if (!NT_STATUS_IS_OK(ret)) {
4790                 return ret;
4791         }
4792         ret = dcerpc_server_lsarpc_init(ctx);
4793         if (!NT_STATUS_IS_OK(ret)) {
4794                 return ret;
4795         }
4796         return ret;
4797 }