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